From efa3144e7cb2a7a58961e5b881b1b9ef73f39cd5 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 22 Feb 2011 16:43:05 -0800 Subject: iwlegacy: MAINTAINERS Add iwlegacy driver to MAINTAINERS file and mark as 'Orphan' Signed-off-by: Wey-Yi Guy --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 95482e9e5ba5..12698b3e3caa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3322,6 +3322,16 @@ F: Documentation/wimax/README.i2400m F: drivers/net/wimax/i2400m/ F: include/linux/wimax/i2400m.h +INTEL PRO/WIRELESS 3945ABG/BG NETWORK CONNECTION SUPPORT +L: linux-wireless@vger.kernel.org +S: Orphan +F: drivers/net/wireless/iwlegacy/ + +INTEL WIRELESS WIFI 4965AGN NETWORK CONNECTION SUPPORT +L: linux-wireless@vger.kernel.org +S: Orphan +F: drivers/net/wireless/iwlegacy/ + INTEL WIRELESS WIFI LINK (iwlwifi) M: Wey-Yi Guy M: Intel Linux Wireless -- cgit v1.2.3-58-ga151 From d103e3448a3ecb9f81babd1f6d7f5a678e213c82 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 10 Mar 2011 03:17:16 -0800 Subject: iwlagn: use 6030 configuration for 6035 series 6035 series of devices should use the same uCode as 6030 series, change it. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-2000.c | 31 ------------------------------- drivers/net/wireless/iwlwifi/iwl-6000.c | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index d7b6126408c9..b1dbe93a88b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -471,37 +471,6 @@ struct iwl_cfg iwl2030_2bg_cfg = { IWL_DEVICE_2030, }; -#define IWL_DEVICE_6035 \ - .fw_name_pre = IWL2030_FW_PRE, \ - .ucode_api_max = IWL2030_UCODE_API_MAX, \ - .ucode_api_min = IWL2030_UCODE_API_MIN, \ - .eeprom_ver = EEPROM_6035_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_6035_TX_POWER_VERSION, \ - .ops = &iwl2030_ops, \ - .mod_params = &iwlagn_mod_params, \ - .base_params = &iwl2030_base_params, \ - .bt_params = &iwl2030_bt_params, \ - .need_dc_calib = true, \ - .need_temp_offset_calib = true, \ - .led_mode = IWL_LED_RF_STATE, \ - .adv_pm = true \ - -struct iwl_cfg iwl6035_2agn_cfg = { - .name = "2000 Series 2x2 AGN/BT", - IWL_DEVICE_6035, - .ht_params = &iwl2000_ht_params, -}; - -struct iwl_cfg iwl6035_2abg_cfg = { - .name = "2000 Series 2x2 ABG/BT", - IWL_DEVICE_6035, -}; - -struct iwl_cfg iwl6035_2bg_cfg = { - .name = "2000 Series 2x2 BG/BT", - IWL_DEVICE_6035, -}; - #define IWL_DEVICE_200 \ .fw_name_pre = IWL200_FW_PRE, \ .ucode_api_max = IWL200_UCODE_API_MAX, \ diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index a745b01c0ec1..40e022617527 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -613,6 +613,22 @@ struct iwl_cfg iwl6030_2bg_cfg = { IWL_DEVICE_6030, }; +struct iwl_cfg iwl6035_2agn_cfg = { + .name = "6035 Series 2x2 AGN/BT", + IWL_DEVICE_6030, + .ht_params = &iwl6000_ht_params, +}; + +struct iwl_cfg iwl6035_2abg_cfg = { + .name = "6035 Series 2x2 ABG/BT", + IWL_DEVICE_6030, +}; + +struct iwl_cfg iwl6035_2bg_cfg = { + .name = "6035 Series 2x2 BG/BT", + IWL_DEVICE_6030, +}; + struct iwl_cfg iwl1030_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 1030 BGN", IWL_DEVICE_6030, -- cgit v1.2.3-58-ga151 From 7ffef13d7a24654292c4641450f2794224b9eb5d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 15 Mar 2011 04:59:10 -0700 Subject: iwlagn: clean up TX aggregation code Since the driver split, there's no need for function pointers any more for aggregation queue setup and teardown as all devices now share the same code. Simplify this. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-2000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-6000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 17 +++++++---------- drivers/net/wireless/iwlwifi/iwl-agn.h | 4 ---- drivers/net/wireless/iwlwifi/iwl-core.h | 5 ----- 7 files changed, 7 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index e8e1c2dc8659..9631d8fa802a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -179,8 +179,6 @@ static struct iwl_lib_ops iwl1000_lib = { .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, - .txq_agg_enable = iwlagn_txq_agg_enable, - .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index b1dbe93a88b0..55274a14af01 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -259,8 +259,6 @@ static struct iwl_lib_ops iwl2000_lib = { .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, - .txq_agg_enable = iwlagn_txq_agg_enable, - .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 90e727b1b4c1..4064490e3b96 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -348,8 +348,6 @@ static struct iwl_lib_ops iwl5000_lib = { .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, - .txq_agg_enable = iwlagn_txq_agg_enable, - .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, @@ -416,8 +414,6 @@ static struct iwl_lib_ops iwl5150_lib = { .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, - .txq_agg_enable = iwlagn_txq_agg_enable, - .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 40e022617527..7ecfbbc9457a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -288,8 +288,6 @@ static struct iwl_lib_ops iwl6000_lib = { .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, - .txq_agg_enable = iwlagn_txq_agg_enable, - .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, @@ -357,8 +355,6 @@ static struct iwl_lib_ops iwl6030_lib = { .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, - .txq_agg_enable = iwlagn_txq_agg_enable, - .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index a709d05c5868..23e5667108e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -222,8 +222,8 @@ void iwlagn_tx_queue_set_status(struct iwl_priv *priv, scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); } -int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, - int tx_fifo, int sta_id, int tid, u16 ssn_idx) +static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, + int tx_fifo, int sta_id, int tid, u16 ssn_idx) { unsigned long flags; u16 ra_tid; @@ -288,8 +288,8 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, return 0; } -int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo) +static int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo) { if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || (IWLAGN_FIRST_AMPDU_QUEUE + @@ -1037,8 +1037,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id); spin_unlock_irqrestore(&priv->sta_lock, flags); - ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, - sta_id, tid, *ssn); + ret = iwlagn_txq_agg_enable(priv, txq_id, tx_fifo, sta_id, tid, *ssn); if (ret) return ret; @@ -1125,8 +1124,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, * to deactivate the uCode queue, just return "success" to allow * mac80211 to clean up it own data. */ - priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, - tx_fifo_id); + iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo_id); spin_unlock_irqrestore(&priv->lock, flags); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); @@ -1155,8 +1153,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, u16 ssn = SEQ_TO_SN(tid_data->seq_number); int tx_fifo = get_fifo_from_tid(ctx, tid); IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); - priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, - ssn, tx_fifo); + iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo); tid_data->agg.state = IWL_AGG_OFF; ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 20f8e4188994..8d918ea36c61 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -133,10 +133,6 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, u16 byte_cnt); void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq); -int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, - int tx_fifo, int sta_id, int tid, u16 ssn_idx); -int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo); void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); void iwl_free_tfds_in_queue(struct iwl_priv *priv, int sta_id, int tid, int freed); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index b316d833d9a2..1f4f6dd18009 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -171,11 +171,6 @@ struct iwl_lib_ops { struct iwl_tx_queue *txq); int (*txq_init)(struct iwl_priv *priv, struct iwl_tx_queue *txq); - /* aggregations */ - int (*txq_agg_enable)(struct iwl_priv *priv, int txq_id, int tx_fifo, - int sta_id, int tid, u16 ssn_idx); - int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, - u8 tx_fifo); /* setup Rx handler */ void (*rx_handler_setup)(struct iwl_priv *priv); /* setup deferred work */ -- cgit v1.2.3-58-ga151 From c8823ec1337017e23b99fb0814e2f3d62537f811 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 15 Mar 2011 11:33:03 -0700 Subject: iwlagn: fix aggregation queue scheduler setup iwlagn's hardware scheduler needs to be set up with the right aggregation frame limit and buffer sizes. To achieve this, we need to move the hardware queue setup to when the session becomes operational. Tested-by: Daniel Halperin Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 47 ++++++++++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 +++ drivers/net/wireless/iwlwifi/iwl-agn.h | 3 ++ drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 23e5667108e2..fb63a03a395e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -222,13 +222,8 @@ void iwlagn_tx_queue_set_status(struct iwl_priv *priv, scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); } -static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, - int tx_fifo, int sta_id, int tid, u16 ssn_idx) +static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, int tid) { - unsigned long flags; - u16 ra_tid; - int ret; - if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { @@ -240,12 +235,33 @@ static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, return -EINVAL; } - ra_tid = BUILD_RAxTID(sta_id, tid); - /* Modify device's station table to Tx this TID */ - ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); - if (ret) - return ret; + return iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); +} + +void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv, + struct ieee80211_sta *sta, + int tid, int frame_limit) +{ + int sta_id, tx_fifo, txq_id, ssn_idx; + u16 ra_tid; + unsigned long flags; + struct iwl_tid_data *tid_data; + + sta_id = iwl_sta_id(sta); + if (WARN_ON(sta_id == IWL_INVALID_STATION)) + return; + if (WARN_ON(tid >= MAX_TID_COUNT)) + return; + + spin_lock_irqsave(&priv->sta_lock, flags); + tid_data = &priv->stations[sta_id].tid[tid]; + ssn_idx = SEQ_TO_SN(tid_data->seq_number); + txq_id = tid_data->agg.txq_id; + tx_fifo = tid_data->agg.tx_fifo; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + ra_tid = BUILD_RAxTID(sta_id, tid); spin_lock_irqsave(&priv->lock, flags); @@ -271,10 +287,10 @@ static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, iwl_write_targ_mem(priv, priv->scd_base_addr + IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), - ((SCD_WIN_SIZE << + ((frame_limit << IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | - ((SCD_FRAME_LIMIT << + ((frame_limit << IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); @@ -284,8 +300,6 @@ static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); spin_unlock_irqrestore(&priv->lock, flags); - - return 0; } static int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, @@ -1034,10 +1048,11 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, tid_data = &priv->stations[sta_id].tid[tid]; *ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->agg.txq_id = txq_id; + tid_data->agg.tx_fifo = tx_fifo; iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id); spin_unlock_irqrestore(&priv->sta_lock, flags); - ret = iwlagn_txq_agg_enable(priv, txq_id, tx_fifo, sta_id, tid, *ssn); + ret = iwlagn_txq_agg_enable(priv, txq_id, sta_id, tid); if (ret) return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b57fbbf3fb64..8fdd1746c102 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3345,6 +3345,10 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, } break; case IEEE80211_AMPDU_TX_OPERATIONAL: + buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); + + iwlagn_txq_agg_queue_setup(priv, sta, tid, buf_size); + /* * If the limit is 0, then it wasn't initialised yet, * use the default. We can do that since we take the diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 8d918ea36c61..4f7c9ce9d8bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -202,6 +202,9 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn); int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid); +void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv, + struct ieee80211_sta *sta, + int tid, int frame_limit); int iwlagn_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 68b953f2bdc7..a5d438d91821 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -416,6 +416,7 @@ struct iwl_ht_agg { #define IWL_EMPTYING_HW_QUEUE_ADDBA 2 #define IWL_EMPTYING_HW_QUEUE_DELBA 3 u8 state; + u8 tx_fifo; }; -- cgit v1.2.3-58-ga151 From 374920cb0512f5938fdf1f5af4f9afa7502dd0f9 Mon Sep 17 00:00:00 2001 From: Daniel Halperin Date: Wed, 16 Mar 2011 19:16:36 -0700 Subject: iwlwifi: limit number of attempts for highest HT rate When filling out its rate scale table, iwlwifi repeats the first HT rate IWL_HT_NUMBER_TRY times. The hardware scheduler will stop using aggregation for any frame that fails LINK_QUAL_AGG_DISABLE_START_DEF times. Currently, both these constants equal 3. If iwlwifi probes a faster rate than the link supports, all frames in a (potentially tens of frames large) batch will fail IWL_HT_NUMBER_TRY times. Because this happens to be as large as LINK_QUAL_AGG_DISABLE_START_DEF, all frames will then be sent individually. This leads to a short, but performance-degrading window where the legacy stop-and-wait MAC takes over. Bounding the initial rate by (LINK_QUAL_AGG_DISABLE_START_DEF-1) attempts makes the third try use a lower rate and hence more be likely to succeed. This somewhat mitigates the above described behavior. Signed-off-by: Daniel Halperin Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index d03b4734c892..63b58ecb0dc6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2912,7 +2912,8 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, ant_toggle_cnt = 1; repeat_rate = IWL_NUMBER_TRY; } else { - repeat_rate = IWL_HT_NUMBER_TRY; + repeat_rate = min(IWL_HT_NUMBER_TRY, + LINK_QUAL_AGG_DISABLE_START_DEF - 1); } lq_cmd->general_params.mimo_delimiter = -- cgit v1.2.3-58-ga151 From d0eb633431ec922f8f9b2040f46d9b42a4cec193 Mon Sep 17 00:00:00 2001 From: Daniel Halperin Date: Wed, 16 Mar 2011 17:17:36 -0700 Subject: iwlwifi: cleanup and bugfix tx aggregation code Since the driver split, there's no need for no_agg_framecnt_info since all devices have this set to false. Secondly, the compressed block ack handling code was broken. Fix this. (1) A shift less than zero simply implies that the buffer wrapped, this is expected. Remove the incorrect comment. (2) The (agg->frame_count > (64-sh)) condition can happen if the last frame is dropped. E.g., if I send 7 frames and the 6th is received but the 7th is lost, the other side may only shift the window 6, not 7 frames since the last bit is a 0. This is perfectly fine behavior and doesn't invalidate the feedback. (3) Store the feedback from a Compressed BA in the first newly received frame, rather than the start of the window. This way it will get processed by the rate selection code. Feedback stored in a non-received frame is likely to get overwritten by the retransmission. This is based on the approach taken by minstrel_ht. Signed-off-by: Daniel Halperin Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 82 ++++++++++--------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 3 -- 2 files changed, 27 insertions(+), 58 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index fb63a03a395e..cb8eacd5fdb5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1263,11 +1263,11 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, struct iwl_compressed_ba_resp *ba_resp) { - int i, sh, ack; + int sh; u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); - int successes = 0; struct ieee80211_tx_info *info; + u64 bitmap, sent_bitmap; if (unlikely(!agg->wait_for_ba)) { if (unlikely(ba_resp->bitmap)) @@ -1281,70 +1281,42 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, /* Calculate shift to align block-ack bits with our Tx window bits */ sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); - if (sh < 0) /* tbw something is wrong with indices */ + if (sh < 0) sh += 0x100; - if (agg->frame_count > (64 - sh)) { - IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); - return -1; - } - if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) { + /* + * Check for success or failure according to the + * transmitted bitmap and block-ack bitmap + */ + bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; + sent_bitmap = bitmap & agg->bitmap; + + /* Sanity check values reported by uCode */ + if (ba_resp->txed_2_done > ba_resp->txed) { + IWL_DEBUG_TX_REPLY(priv, + "bogus sent(%d) and ack(%d) count\n", + ba_resp->txed, ba_resp->txed_2_done); /* - * sent and ack information provided by uCode - * use it instead of figure out ourself + * set txed_2_done = txed, + * so it won't impact rate scale */ - if (ba_resp->txed_2_done > ba_resp->txed) { - IWL_DEBUG_TX_REPLY(priv, - "bogus sent(%d) and ack(%d) count\n", - ba_resp->txed, ba_resp->txed_2_done); - /* - * set txed_2_done = txed, - * so it won't impact rate scale - */ - ba_resp->txed = ba_resp->txed_2_done; - } - IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", - ba_resp->txed, ba_resp->txed_2_done); - } else { - u64 bitmap, sent_bitmap; - - /* don't use 64-bit values for now */ - bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; - - /* check for success or failure according to the - * transmitted bitmap and block-ack bitmap */ - sent_bitmap = bitmap & agg->bitmap; - - /* For each frame attempted in aggregation, - * update driver's record of tx frame's status. */ - i = 0; - while (sent_bitmap) { - ack = sent_bitmap & 1ULL; - successes += ack; - IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", - ack ? "ACK" : "NACK", i, - (agg->start_idx + i) & 0xff, - agg->start_idx + i); - sent_bitmap >>= 1; - ++i; - } + ba_resp->txed = ba_resp->txed_2_done; + } + IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", + ba_resp->txed, ba_resp->txed_2_done); - IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", - (unsigned long long)bitmap); + /* Find the first ACKed frame to store the TX status */ + while (sent_bitmap && !(sent_bitmap & 1)) { + agg->start_idx = (agg->start_idx + 1) & 0xff; + sent_bitmap >>= 1; } info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb); memset(&info->status, 0, sizeof(info->status)); info->flags |= IEEE80211_TX_STAT_ACK; info->flags |= IEEE80211_TX_STAT_AMPDU; - if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) { - info->status.ampdu_ack_len = ba_resp->txed_2_done; - info->status.ampdu_len = ba_resp->txed; - - } else { - info->status.ampdu_ack_len = successes; - info->status.ampdu_len = agg->frame_count; - } + info->status.ampdu_ack_len = ba_resp->txed_2_done; + info->status.ampdu_len = ba_resp->txed; iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 1f4f6dd18009..3e680af7ff70 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -281,8 +281,6 @@ struct iwl_mod_params { * @chain_noise_calib_by_driver: driver has the capability to perform * chain noise calibration operation * @shadow_reg_enable: HW shadhow register bit - * @no_agg_framecnt_info: uCode do not provide aggregation frame count - * information */ struct iwl_base_params { int eeprom_size; @@ -312,7 +310,6 @@ struct iwl_base_params { const bool sensitivity_calib_by_driver; const bool chain_noise_calib_by_driver; const bool shadow_reg_enable; - const bool no_agg_framecnt_info; }; /* * @advanced_bt_coexist: support advanced bt coexist -- cgit v1.2.3-58-ga151 From 2520546aecc969372080448a2422b39eedb2a528 Mon Sep 17 00:00:00 2001 From: Daniel Halperin Date: Fri, 18 Mar 2011 18:48:55 -0700 Subject: iwlwifi: add RATE_MCS_RATE_MSK Throughout the code we use rate_n_flags & 0xff to extract the lower byte of the rate_n_flags u32 that contains the information about the rate. Add a #define and remove the use of the magic number. Signed-off-by: Daniel Halperin Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 15 ++++++++------- drivers/net/wireless/iwlwifi/iwl-agn.h | 2 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 ++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 63b58ecb0dc6..e394e49228ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -115,13 +115,18 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { /* FIXME:RS: ^^ should be INV (legacy) */ }; +static inline u8 rs_extract_rate(u32 rate_n_flags) +{ + return (u8)(rate_n_flags & RATE_MCS_RATE_MSK); +} + static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) { int idx = 0; /* HT rate format */ if (rate_n_flags & RATE_MCS_HT_MSK) { - idx = (rate_n_flags & 0xff); + idx = rs_extract_rate(rate_n_flags); if (idx >= IWL_RATE_MIMO3_6M_PLCP) idx = idx - IWL_RATE_MIMO3_6M_PLCP; @@ -138,7 +143,8 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) /* legacy rate format, search for match in table */ } else { for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) - if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) + if (iwl_rates[idx].plcp == + rs_extract_rate(rate_n_flags)) return idx; } @@ -239,11 +245,6 @@ static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { #define MCS_INDEX_PER_STREAM (8) -static inline u8 rs_extract_rate(u32 rate_n_flags) -{ - return (u8)(rate_n_flags & 0xFF); -} - static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) { window->data = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 4f7c9ce9d8bd..39313acb9cc7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -310,7 +310,7 @@ static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) static inline u8 iwl_hw_get_rate(__le32 rate_n_flags) { - return le32_to_cpu(rate_n_flags) & 0xFF; + return le32_to_cpu(rate_n_flags) & RATE_MCS_RATE_MSK; } static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index ca42ffa63ed7..288391558afd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -324,6 +324,8 @@ struct iwl3945_power_per_rate { #define RATE_MCS_SPATIAL_MSK 0x18 #define RATE_MCS_HT_DUP_POS 5 #define RATE_MCS_HT_DUP_MSK 0x20 +/* Both legacy and HT use bits 7:0 as the CCK/OFDM rate or HT MCS */ +#define RATE_MCS_RATE_MSK 0xff /* Bit 8: (1) HT format, (0) legacy format in bits 7:0 */ #define RATE_MCS_FLAGS_POS 8 -- cgit v1.2.3-58-ga151 From 4263108c2a9028544cf4037fa4e72000ee456c33 Mon Sep 17 00:00:00 2001 From: Daniel Halperin Date: Mon, 21 Mar 2011 15:27:34 -0700 Subject: iwlwifi: set default aggregation frame limit to 63 This gives much better performance at fast 3x3 rates (up to ~160 Mbps). The scheduler will still make most decisions about batch size based on available packets and RX parameters. Signed-off-by: Daniel Halperin Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 288391558afd..cc2151482f31 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2132,7 +2132,7 @@ struct iwl_link_qual_general_params { #define LINK_QUAL_AGG_DISABLE_START_MAX (255) #define LINK_QUAL_AGG_DISABLE_START_MIN (0) -#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (31) +#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (63) #define LINK_QUAL_AGG_FRAME_LIMIT_MAX (63) #define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0) -- cgit v1.2.3-58-ga151 From d6b8061824a03fbe915c6cf5be2b290ae44c4ec4 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 21 Mar 2011 16:53:38 -0700 Subject: iwlwifi: remove legacy isr tasklet After driver split, no need for support legacy isr, remove it. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-ict.c | 2 - drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 3 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 193 +---------------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - 4 files changed, 3 insertions(+), 196 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c index b5cb3be0eb4b..47e1fa4bacfd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c @@ -59,8 +59,6 @@ void iwl_free_isr_ict(struct iwl_priv *priv) int iwl_alloc_isr_ict(struct iwl_priv *priv) { - if (priv->cfg->base_params->use_isr_legacy) - return 0; /* allocate shrared data table */ priv->_agn.ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 2003c1d4295f..8163a0efdc83 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -652,8 +652,7 @@ int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ - if (!priv->cfg->base_params->use_isr_legacy) - rb_timeout = RX_RB_TIMEOUT; + rb_timeout = RX_RB_TIMEOUT; if (priv->cfg->mod_params->amsdu_size_8K) rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8fdd1746c102..bd980a2da413 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -845,191 +845,6 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv) tasklet_kill(&priv->irq_tasklet); } -static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) -{ - u32 inta, handled = 0; - u32 inta_fh; - unsigned long flags; - u32 i; -#ifdef CONFIG_IWLWIFI_DEBUG - u32 inta_mask; -#endif - - spin_lock_irqsave(&priv->lock, flags); - - /* Ack/clear/reset pending uCode interrupts. - * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, - * and will clear only when CSR_FH_INT_STATUS gets cleared. */ - inta = iwl_read32(priv, CSR_INT); - iwl_write32(priv, CSR_INT, inta); - - /* Ack/clear/reset pending flow-handler (DMA) interrupts. - * Any new interrupts that happen after this, either while we're - * in this tasklet, or later, will show up in next ISR/tasklet. */ - inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & IWL_DL_ISR) { - /* just for debug */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); - IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", - inta, inta_mask, inta_fh); - } -#endif - - spin_unlock_irqrestore(&priv->lock, flags); - - /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not - * atomic, make sure that inta covers all the interrupts that - * we've discovered, even if FH interrupt came in just after - * reading CSR_INT. */ - if (inta_fh & CSR49_FH_INT_RX_MASK) - inta |= CSR_INT_BIT_FH_RX; - if (inta_fh & CSR49_FH_INT_TX_MASK) - inta |= CSR_INT_BIT_FH_TX; - - /* Now service all interrupt bits discovered above. */ - if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERR(priv, "Hardware error detected. Restarting.\n"); - - /* Tell the device to stop sending interrupts */ - iwl_disable_interrupts(priv); - - priv->isr_stats.hw++; - iwl_irq_handle_error(priv); - - handled |= CSR_INT_BIT_HW_ERR; - - return; - } - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { - /* NIC fires this, but we don't use it, redundant with WAKEUP */ - if (inta & CSR_INT_BIT_SCD) { - IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " - "the frame/frames.\n"); - priv->isr_stats.sch++; - } - - /* Alive notification via Rx interrupt will do the real work */ - if (inta & CSR_INT_BIT_ALIVE) { - IWL_DEBUG_ISR(priv, "Alive interrupt\n"); - priv->isr_stats.alive++; - } - } -#endif - /* Safely ignore these bits for debug checks below */ - inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); - - /* HW RF KILL switch toggled */ - if (inta & CSR_INT_BIT_RF_KILL) { - int hw_rf_kill = 0; - if (!(iwl_read32(priv, CSR_GP_CNTRL) & - CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) - hw_rf_kill = 1; - - IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", - hw_rf_kill ? "disable radio" : "enable radio"); - - priv->isr_stats.rfkill++; - - /* driver only loads ucode once setting the interface up. - * the driver allows loading the ucode even if the radio - * is killed. Hence update the killswitch state here. The - * rfkill handler will care about restarting if needed. - */ - if (!test_bit(STATUS_ALIVE, &priv->status)) { - if (hw_rf_kill) - set_bit(STATUS_RF_KILL_HW, &priv->status); - else - clear_bit(STATUS_RF_KILL_HW, &priv->status); - wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); - } - - handled |= CSR_INT_BIT_RF_KILL; - } - - /* Chip got too hot and stopped itself */ - if (inta & CSR_INT_BIT_CT_KILL) { - IWL_ERR(priv, "Microcode CT kill error detected.\n"); - priv->isr_stats.ctkill++; - handled |= CSR_INT_BIT_CT_KILL; - } - - /* Error detected by uCode */ - if (inta & CSR_INT_BIT_SW_ERR) { - IWL_ERR(priv, "Microcode SW error detected. " - " Restarting 0x%X.\n", inta); - priv->isr_stats.sw++; - iwl_irq_handle_error(priv); - handled |= CSR_INT_BIT_SW_ERR; - } - - /* - * uCode wakes up after power-down sleep. - * Tell device about any new tx or host commands enqueued, - * and about any Rx buffers made available while asleep. - */ - if (inta & CSR_INT_BIT_WAKEUP) { - IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); - iwl_rx_queue_update_write_ptr(priv, &priv->rxq); - for (i = 0; i < priv->hw_params.max_txq_num; i++) - iwl_txq_update_write_ptr(priv, &priv->txq[i]); - priv->isr_stats.wakeup++; - handled |= CSR_INT_BIT_WAKEUP; - } - - /* All uCode command responses, including Tx command responses, - * Rx "responses" (frame-received notification), and other - * notifications from uCode come through here*/ - if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { - iwl_rx_handle(priv); - priv->isr_stats.rx++; - handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); - } - - /* This "Tx" DMA channel is used only for loading uCode */ - if (inta & CSR_INT_BIT_FH_TX) { - IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); - priv->isr_stats.tx++; - handled |= CSR_INT_BIT_FH_TX; - /* Wake up uCode load routine, now that load is complete */ - priv->ucode_write_complete = 1; - wake_up_interruptible(&priv->wait_command_queue); - } - - if (inta & ~handled) { - IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); - priv->isr_stats.unhandled++; - } - - if (inta & ~(priv->inta_mask)) { - IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", - inta & ~priv->inta_mask); - IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); - } - - /* Re-enable all interrupts */ - /* only Re-enable if disabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &priv->status)) - iwl_enable_interrupts(priv); - /* Re-enable RF_KILL if it occurred */ - else if (handled & CSR_INT_BIT_RF_KILL) - iwl_enable_rfkill_int(priv); - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { - inta = iwl_read32(priv, CSR_INT); - inta_mask = iwl_read32(priv, CSR_INT_MASK); - inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, " - "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); - } -#endif -} - /* tasklet for iwlagn interrupt */ static void iwl_irq_tasklet(struct iwl_priv *priv) { @@ -3751,12 +3566,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) priv->watchdog.data = (unsigned long)priv; priv->watchdog.function = iwl_bg_watchdog; - if (!priv->cfg->base_params->use_isr_legacy) - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) - iwl_irq_tasklet, (unsigned long)priv); - else - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) - iwl_irq_tasklet_legacy, (unsigned long)priv); + tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) + iwl_irq_tasklet, (unsigned long)priv); } static void iwl_cancel_deferred_work(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 3e680af7ff70..3a4e9b4d0973 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -291,7 +291,6 @@ struct iwl_base_params { bool set_l0s; bool use_bsm; - bool use_isr_legacy; const u16 max_ll_items; const bool shadow_ram_support; u16 led_compensation; -- cgit v1.2.3-58-ga151 From 2a226ab67f2f9c46e534f37f867d3bf3af335d02 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 22 Mar 2011 08:05:36 -0700 Subject: iwlagn: remove 3945 only station code After driver split, no more 3945 only station support needed. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-sta.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index bc90a12408a3..b0dcca07ff45 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -306,12 +306,6 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, */ iwl_set_ht_add_station(priv, sta_id, sta, ctx); - /* 3945 only */ - rate = (priv->band == IEEE80211_BAND_5GHZ) ? - IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP; - /* Turn on both antennas for the station... */ - station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK); - return sta_id; } -- cgit v1.2.3-58-ga151 From f7d046f91bd165e747b9a95d089a4168b6f9796a Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 22 Mar 2011 08:05:37 -0700 Subject: iwlagn: remove reference to 3945 and 4965 After driver split, remove the unused reference to 3945 and 4965 Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 39 ++++++++++++------------------- drivers/net/wireless/iwlwifi/iwl-csr.h | 39 +++++++------------------------ drivers/net/wireless/iwlwifi/iwl-eeprom.c | 2 -- 3 files changed, 23 insertions(+), 57 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index bd980a2da413..9251c68934dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -409,7 +409,7 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, * Tell nic where to find circular buffer of Tx Frame Descriptors for * given Tx queue, and enable the DMA channel used for that queue. * - * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA + * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA * channels supported in hardware. */ int iwl_hw_tx_queue_init(struct iwl_priv *priv, @@ -986,7 +986,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); iwl_write32(priv, CSR_FH_INT_STATUS, - CSR49_FH_INT_RX_MASK); + CSR_FH_INT_RX_MASK); } if (inta & CSR_INT_BIT_RX_PERIODIC) { handled |= CSR_INT_BIT_RX_PERIODIC; @@ -1024,7 +1024,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) /* This "Tx" DMA channel is used only for loading uCode */ if (inta & CSR_INT_BIT_FH_TX) { - iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_TX_MASK); + iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); priv->isr_stats.tx++; handled |= CSR_INT_BIT_FH_TX; @@ -1259,28 +1259,19 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, switch (api_ver) { default: - /* - * 4965 doesn't revision the firmware file format - * along with the API version, it always uses v1 - * file format. - */ - if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != - CSR_HW_REV_TYPE_4965) { - hdr_size = 28; - if (ucode_raw->size < hdr_size) { - IWL_ERR(priv, "File size too small!\n"); - return -EINVAL; - } - pieces->build = le32_to_cpu(ucode->u.v2.build); - pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); - pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); - pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); - pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); - pieces->boot_size = le32_to_cpu(ucode->u.v2.boot_size); - src = ucode->u.v2.data; - break; + hdr_size = 28; + if (ucode_raw->size < hdr_size) { + IWL_ERR(priv, "File size too small!\n"); + return -EINVAL; } - /* fall through for 4965 */ + pieces->build = le32_to_cpu(ucode->u.v2.build); + pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); + pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); + pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); + pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); + pieces->boot_size = le32_to_cpu(ucode->u.v2.boot_size); + src = ucode->u.v2.data; + break; case 0: case 1: case 2: diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index f52bc040bcbf..1123319f2e2b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -155,18 +155,10 @@ #define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250) /* Bits for CSR_HW_IF_CONFIG_REG */ -#define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010) #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00) #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) -#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MB (0x00000100) -#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MM (0x00000200) -#define CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400) -#define CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800) -#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) -#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) - #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) #define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */ @@ -186,7 +178,7 @@ #define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ #define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ #define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ -#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */ +#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses */ #define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */ #define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */ @@ -202,29 +194,17 @@ /* interrupt flags in FH (flow handler) (PCI busmaster DMA) */ #define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */ #define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */ -#define CSR39_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */ #define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */ #define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */ -#define CSR39_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */ #define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */ #define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */ -#define CSR39_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ - CSR39_FH_INT_BIT_RX_CHNL2 | \ - CSR_FH_INT_BIT_RX_CHNL1 | \ - CSR_FH_INT_BIT_RX_CHNL0) - - -#define CSR39_FH_INT_TX_MASK (CSR39_FH_INT_BIT_TX_CHNL6 | \ - CSR_FH_INT_BIT_TX_CHNL1 | \ - CSR_FH_INT_BIT_TX_CHNL0) - -#define CSR49_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ - CSR_FH_INT_BIT_RX_CHNL1 | \ - CSR_FH_INT_BIT_RX_CHNL0) +#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ + CSR_FH_INT_BIT_RX_CHNL1 | \ + CSR_FH_INT_BIT_RX_CHNL0) -#define CSR49_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \ - CSR_FH_INT_BIT_TX_CHNL0) +#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \ + CSR_FH_INT_BIT_TX_CHNL0) /* GPIO */ #define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200) @@ -268,7 +248,7 @@ * Indicates MAC (ucode processor, etc.) is powered up and can run. * Internal resources are accessible. * NOTE: This does not indicate that the processor is actually running. - * NOTE: This does not indicate that 4965 or 3945 has completed + * NOTE: This does not indicate that device has completed * init or post-power-down restore of internal SRAM memory. * Use CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that * SRAM is restored and uCode is in normal operation mode. @@ -291,8 +271,6 @@ /* HW REV */ #define CSR_HW_REV_TYPE_MSK (0x00001F0) -#define CSR_HW_REV_TYPE_3945 (0x00000D0) -#define CSR_HW_REV_TYPE_4965 (0x0000000) #define CSR_HW_REV_TYPE_5300 (0x0000020) #define CSR_HW_REV_TYPE_5350 (0x0000030) #define CSR_HW_REV_TYPE_5100 (0x0000050) @@ -363,7 +341,7 @@ * 0: MAC_SLEEP * uCode sets this when preparing a power-saving power-down. * uCode resets this when power-up is complete and SRAM is sane. - * NOTE: 3945/4965 saves internal SRAM data to host when powering down, + * NOTE: device saves internal SRAM data to host when powering down, * and must restore this data after powering back up. * MAC_SLEEP is the best indication that restore is complete. * Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and @@ -394,7 +372,6 @@ #define CSR_LED_REG_TRUN_OFF (0x38) /* ANA_PLL */ -#define CSR39_ANA_PLL_CFG_VAL (0x01000000) #define CSR50_ANA_PLL_CFG_VAL (0x00880300) /* HPET MEM debug */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 833194a2c639..c831a0f24613 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -198,8 +198,6 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv) case CSR_HW_REV_TYPE_NONE: IWL_ERR(priv, "Unknown hardware type\n"); return -ENOENT; - case CSR_HW_REV_TYPE_3945: - case CSR_HW_REV_TYPE_4965: case CSR_HW_REV_TYPE_5300: case CSR_HW_REV_TYPE_5350: case CSR_HW_REV_TYPE_5100: -- cgit v1.2.3-58-ga151 From 7eaa6a5e964f1ab02d849bda36950c0d30be8ce2 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 22 Mar 2011 08:05:38 -0700 Subject: iwlagn: remove deprecated module parameters Number of deprecated module parameters need to be remove for 2.6.40 kernel Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 30 ------------------------------ drivers/net/wireless/iwlwifi/iwl-core.h | 1 - 2 files changed, 31 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 9251c68934dd..39a05e32c34f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3771,14 +3771,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * 1. Allocating HW data ************************/ - /* Disabling hardware scan means that mac80211 will perform scans - * "the hard way", rather than using device's scan. */ - if (cfg->mod_params->disable_hw_scan) { - dev_printk(KERN_DEBUG, &(pdev->dev), - "sw scan support is deprecated\n"); - iwlagn_hw_ops.hw_scan = NULL; - } - hw = iwl_alloc_all(cfg); if (!hw) { err = -ENOMEM; @@ -4388,43 +4380,21 @@ module_exit(iwl_exit); module_init(iwl_init); #ifdef CONFIG_IWLWIFI_DEBUG -module_param_named(debug50, iwl_debug_level, uint, S_IRUGO); -MODULE_PARM_DESC(debug50, "50XX debug output mask (deprecated)"); module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "debug output mask"); #endif -module_param_named(swcrypto50, iwlagn_mod_params.sw_crypto, bool, S_IRUGO); -MODULE_PARM_DESC(swcrypto50, - "using crypto in software (default 0 [hardware]) (deprecated)"); module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO); MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); -module_param_named(queues_num50, - iwlagn_mod_params.num_of_queues, int, S_IRUGO); -MODULE_PARM_DESC(queues_num50, - "number of hw queues in 50xx series (deprecated)"); module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO); MODULE_PARM_DESC(queues_num, "number of hw queues."); -module_param_named(11n_disable50, iwlagn_mod_params.disable_11n, int, S_IRUGO); -MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality (deprecated)"); module_param_named(11n_disable, iwlagn_mod_params.disable_11n, int, S_IRUGO); MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); -module_param_named(amsdu_size_8K50, iwlagn_mod_params.amsdu_size_8K, - int, S_IRUGO); -MODULE_PARM_DESC(amsdu_size_8K50, - "enable 8K amsdu size in 50XX series (deprecated)"); module_param_named(amsdu_size_8K, iwlagn_mod_params.amsdu_size_8K, int, S_IRUGO); MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); -module_param_named(fw_restart50, iwlagn_mod_params.restart_fw, int, S_IRUGO); -MODULE_PARM_DESC(fw_restart50, - "restart firmware in case of error (deprecated)"); module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO); MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); -module_param_named( - disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); -MODULE_PARM_DESC(disable_hw_scan, - "disable hardware scanning (default 0) (deprecated)"); module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, S_IRUGO); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 3a4e9b4d0973..967b4c008bc0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -247,7 +247,6 @@ struct iwl_ops { struct iwl_mod_params { int sw_crypto; /* def: 0 = using hardware encryption */ - int disable_hw_scan; /* def: 0 = use h/w scan */ int num_of_queues; /* def: HW dependent */ int disable_11n; /* def: 0 = 11n capabilities enabled */ int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ -- cgit v1.2.3-58-ga151 From 22dd2fd283ea96b4d45185d3e861ef46005082f4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 15 Mar 2011 10:03:24 +0300 Subject: iwlwifi: remove duplicate initialization in __iwl_down() We initialize exit_pending twice. It's the second initialization which is correct. That was added in d745d472af "iwlwifi: cancel scan when down the device". Signed-off-by: Dan Carpenter Acked-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 321b18b59135..7adc60ea03cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2537,7 +2537,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv); static void __iwl_down(struct iwl_priv *priv) { unsigned long flags; - int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status); + int exit_pending; IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); -- cgit v1.2.3-58-ga151 From 6d64ab7f9240e3201fde3fd16ce4227bd795d2ab Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 15 Mar 2011 19:55:35 +0530 Subject: ath9k_htc: Fix LED pin for AR9287 HTC device Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 753a245c5ad1..ec47be94b74f 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -328,7 +328,7 @@ struct ath9k_debug { #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ #define ATH_LED_PIN_DEF 1 -#define ATH_LED_PIN_9287 8 +#define ATH_LED_PIN_9287 10 #define ATH_LED_PIN_9271 15 #define ATH_LED_PIN_7010 12 #define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ -- cgit v1.2.3-58-ga151 From 81544026e4cecb85a8b727d5f64cb3c8a8cb64a3 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 15 Mar 2011 19:55:36 +0530 Subject: ath9k_hw: Fix throughput drops in HT40 mode for AR9287 chips Doing adc gain calibration for AR9287 chips is causing throughput drops in HT40 mode. Remove ADC Gain from supported calibration list. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_calib.c | 43 ++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 76388c6d6692..cb611b287b35 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -26,6 +26,27 @@ enum ar9002_cal_types { IQ_MISMATCH_CAL = BIT(2), }; +static bool ar9002_hw_is_cal_supported(struct ath_hw *ah, + struct ath9k_channel *chan, + enum ar9002_cal_types cal_type) +{ + bool supported = false; + switch (ah->supp_cals & cal_type) { + case IQ_MISMATCH_CAL: + /* Run IQ Mismatch for non-CCK only */ + if (!IS_CHAN_B(chan)) + supported = true; + break; + case ADC_GAIN_CAL: + case ADC_DC_CAL: + /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ + if (!IS_CHAN_B(chan) && + !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) + supported = true; + break; + } + return supported; +} static void ar9002_hw_setup_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal) @@ -858,26 +879,32 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { ah->supp_cals = IQ_MISMATCH_CAL; - if (AR_SREV_9160_10_OR_LATER(ah) && - !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) { + if (AR_SREV_9160_10_OR_LATER(ah)) ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL; + if (AR_SREV_9287(ah)) + ah->supp_cals &= ~ADC_GAIN_CAL; + if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) { INIT_CAL(&ah->adcgain_caldata); INSERT_CAL(ah, &ah->adcgain_caldata); ath_dbg(common, ATH_DBG_CALIBRATE, - "enabling ADC Gain Calibration.\n"); + "enabling ADC Gain Calibration.\n"); + } + if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) { INIT_CAL(&ah->adcdc_caldata); INSERT_CAL(ah, &ah->adcdc_caldata); ath_dbg(common, ATH_DBG_CALIBRATE, - "enabling ADC DC Calibration.\n"); + "enabling ADC DC Calibration.\n"); } - INIT_CAL(&ah->iq_caldata); - INSERT_CAL(ah, &ah->iq_caldata); - ath_dbg(common, ATH_DBG_CALIBRATE, - "enabling IQ Calibration.\n"); + if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) { + INIT_CAL(&ah->iq_caldata); + INSERT_CAL(ah, &ah->iq_caldata); + ath_dbg(common, ATH_DBG_CALIBRATE, + "enabling IQ Calibration.\n"); + } ah->cal_list_curr = ah->cal_list; -- cgit v1.2.3-58-ga151 From b0a9ede228175c25f76314a028d305fd5b2de427 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 15 Mar 2011 19:55:38 +0530 Subject: ath: Speedup key set/reset ops for HTC driver By enabling buffered register write for ath9k_htc driver avoids unnecessary dissociation while rekeying phase under heavy traffic exchange. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/key.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c index 37b8e115375a..0d4f39cbdcab 100644 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c @@ -23,6 +23,14 @@ #define REG_READ (common->ops->read) #define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg) +#define ENABLE_REGWRITE_BUFFER(_ah) \ + if (common->ops->enable_write_buffer) \ + common->ops->enable_write_buffer((_ah)); + +#define REGWRITE_BUFFER_FLUSH(_ah) \ + if (common->ops->write_flush) \ + common->ops->write_flush((_ah)); + #define IEEE80211_WEP_NKID 4 /* number of key ids */ @@ -42,6 +50,8 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry) keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry)); + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); @@ -66,6 +76,8 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry) } + REGWRITE_BUFFER_FLUSH(ah); + return true; } EXPORT_SYMBOL(ath_hw_keyreset); @@ -104,9 +116,13 @@ static bool ath_hw_keysetmac(struct ath_common *common, } else { macLo = macHi = 0; } + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag); + REGWRITE_BUFFER_FLUSH(ah); + return true; } @@ -223,6 +239,8 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff; mic4 = get_unaligned_le32(k->kv_txmic + 4); + ENABLE_REGWRITE_BUFFER(ah); + /* Write RX[31:0] and TX[31:16] */ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); @@ -236,6 +254,8 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), AR_KEYTABLE_TYPE_CLR); + REGWRITE_BUFFER_FLUSH(ah); + } else { /* * TKIP uses four key cache entries (two for group @@ -258,6 +278,8 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, mic0 = get_unaligned_le32(k->kv_mic + 0); mic2 = get_unaligned_le32(k->kv_mic + 4); + ENABLE_REGWRITE_BUFFER(ah); + /* Write MIC key[31:0] */ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); @@ -270,8 +292,12 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), AR_KEYTABLE_TYPE_CLR); + + REGWRITE_BUFFER_FLUSH(ah); } + ENABLE_REGWRITE_BUFFER(ah); + /* MAC address registers are reserved for the MIC entry */ REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); @@ -283,7 +309,11 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, */ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); + + REGWRITE_BUFFER_FLUSH(ah); } else { + ENABLE_REGWRITE_BUFFER(ah); + /* Write key[47:0] */ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); @@ -296,6 +326,8 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); + REGWRITE_BUFFER_FLUSH(ah); + /* Write MAC address for the entry */ (void) ath_hw_keysetmac(common, entry, mac); } -- cgit v1.2.3-58-ga151 From e7fc63388def06d2d1bdb6916748c92c037a42c6 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 15 Mar 2011 23:11:35 +0530 Subject: ath9k_hw: Speedup register ops for HTC driver Fine-tuning register write operation and avoid unnecessay delays for ath9k_htc driver, saves hw reset time which improves scanning time and also solves one of the following scenario. Sometimes the ACK is sent by STA for assoc response is not seen at AP side. So the AP continues to send retry assoc responses. At the STA side, since the assoc response was already forwarded to mac80211, it proceeded to channel change which in turns does chip reset. In most of the cases the chip reset was completed before max retries are reached at AP side. Hence STA can able to ACK the retried frames again. But in clear environment these retries are completed within shortspan of time. Since ath9k_htc consumes more time for hw reset, this latency is causing dissociation by AP due to max reties are reached. This issue was originally reported with Cisco Aironet 1250 AP in HT40 mode in noise free environment. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar5008_phy.c | 7 +++++-- drivers/net/wireless/ath/ath9k/eeprom_9287.c | 6 ++++++ drivers/net/wireless/ath/ath9k/eeprom_def.c | 7 +++++++ drivers/net/wireless/ath/ath9k/hw.h | 10 +++++++--- drivers/net/wireless/ath/ath9k/phy.h | 2 ++ 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index ffcf44a4058b..94acce59f51d 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -729,6 +729,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, struct ath9k_channel *chan) { struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + struct ath_common *common = ath9k_hw_common(ah); int i, regWrites = 0; struct ieee80211_channel *channel = chan->chan; u32 modesIndex, freqIndex; @@ -805,7 +806,8 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, REG_WRITE(ah, reg, val); if (reg >= 0x7800 && reg < 0x78a0 - && ah->config.analog_shiftreg) { + && ah->config.analog_shiftreg + && (common->bus_ops->ath_bus_type != ATH_USB)) { udelay(100); } @@ -835,7 +837,8 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, REG_WRITE(ah, reg, val); if (reg >= 0x7800 && reg < 0x78a0 - && ah->config.analog_shiftreg) { + && ah->config.analog_shiftreg + && (common->bus_ops->ath_bus_type != ATH_USB)) { udelay(100); } diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 8cd8333cc086..2f0712ea49a6 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -392,6 +392,8 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, numXpdGain); } + ENABLE_REGWRITE_BUFFER(ah); + if (i == 0) { if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { @@ -442,6 +444,7 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, regOffset += 4; } } + REGWRITE_BUFFER_FLUSH(ah); } } @@ -757,6 +760,8 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; } + ENABLE_REGWRITE_BUFFER(ah); + /* OFDM power per rate */ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, ATH9K_POW_SM(ratesArray[rate18mb], 24) @@ -840,6 +845,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); } + REGWRITE_BUFFER_FLUSH(ah); } static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index fccd87df7300..995949ddd63e 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -799,6 +799,8 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, pwr_table_offset, &diff); + ENABLE_REGWRITE_BUFFER(ah); + if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { if (OLC_FOR_AR9280_20_LATER) { REG_WRITE(ah, @@ -847,6 +849,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, regOffset += 4; } + REGWRITE_BUFFER_FLUSH(ah); } } @@ -1205,6 +1208,8 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, } } + ENABLE_REGWRITE_BUFFER(ah); + REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, ATH9K_POW_SM(ratesArray[rate18mb], 24) | ATH9K_POW_SM(ratesArray[rate12mb], 16) @@ -1291,6 +1296,8 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, REG_WRITE(ah, AR_PHY_POWER_TX_SUB, ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); + + REGWRITE_BUFFER_FLUSH(ah); } static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 6650fd48415c..c86eea28a88f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -99,18 +99,22 @@ #define REG_CLR_BIT(_a, _r, _f) \ REG_WRITE(_a, _r, REG_READ(_a, _r) & ~(_f)) -#define DO_DELAY(x) do { \ - if ((++(x) % 64) == 0) \ - udelay(1); \ +#define DO_DELAY(x) do { \ + if (((++(x) % 64) == 0) && \ + (ath9k_hw_common(ah)->bus_ops->ath_bus_type \ + != ATH_USB)) \ + udelay(1); \ } while (0) #define REG_WRITE_ARRAY(iniarray, column, regWr) do { \ int r; \ + ENABLE_REGWRITE_BUFFER(ah); \ for (r = 0; r < ((iniarray)->ia_rows); r++) { \ REG_WRITE(ah, INI_RA((iniarray), (r), 0), \ INI_RA((iniarray), r, (column))); \ DO_DELAY(regWr); \ } \ + REGWRITE_BUFFER_FLUSH(ah); \ } while (0) #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 5e3d7496986e..e4029325c787 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -40,10 +40,12 @@ #define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do { \ int r; \ + ENABLE_REGWRITE_BUFFER(ah); \ for (r = 0; r < ((iniarray)->ia_rows); r++) { \ REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \ DO_DELAY(regWr); \ } \ + REGWRITE_BUFFER_FLUSH(ah); \ } while (0) #define ANTSWAP_AB 0x0001 -- cgit v1.2.3-58-ga151 From c835b21405fa551cd5af2c7bfe1c3ae129c5f8ef Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 15 Mar 2011 23:17:01 +0100 Subject: mac80211: add comment about reordering Took me a minute to figure this out, maybe it's better documented... Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/rx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5c1930ba8ebe..82414a636824 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -706,6 +706,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, /* * If the current MPDU is in the right order and nothing else * is stored we can process it directly, no need to buffer it. + * If it is first but there's something stored, we may be able + * to release frames after this one. */ if (mpdu_seq_num == tid_agg_rx->head_seq_num && tid_agg_rx->stored_mpdu_num == 0) { -- cgit v1.2.3-58-ga151 From 73b46320209e9fe0d65aba1b8c21489278047574 Mon Sep 17 00:00:00 2001 From: Brian Cavagnolo Date: Thu, 17 Mar 2011 11:58:41 -0700 Subject: mwl8k: refactor in preparation for APIv2 update Specifically, APIv2 will specify a variable number of AMPDU queues in the MWL8K_CMD_GET_HW_SPEC. So init the tx queues after MWL8K_CMD_GET_HW_SPEC for ap fw. Also, we make it safe to deinit queues that have not been init'd. This happens if the mwl8k_get_hw_spec_ap routine fails, for example. Signed-off-by: Nishant Sarmukadam Signed-off-by: Brian Cavagnolo Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 51 +++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 36952274950e..8fefed2342d7 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -191,6 +191,7 @@ struct mwl8k_priv { struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES]; + u32 txq_offset[MWL8K_TX_QUEUES]; bool radio_on; bool radio_short_preamble; @@ -1126,6 +1127,9 @@ static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index) struct mwl8k_rx_queue *rxq = priv->rxq + index; int i; + if (rxq->rxd == NULL) + return; + for (i = 0; i < MWL8K_RX_DESCS; i++) { if (rxq->buf[i].skb != NULL) { pci_unmap_single(priv->pdev, @@ -1560,6 +1564,9 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index) struct mwl8k_priv *priv = hw->priv; struct mwl8k_tx_queue *txq = priv->txq + index; + if (txq->txd == NULL) + return; + mwl8k_txq_reclaim(hw, index, INT_MAX, 1); kfree(txq->skb); @@ -2058,23 +2065,16 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) priv->ap_macids_supported = 0x000000ff; priv->sta_macids_supported = 0x00000000; - off = le32_to_cpu(cmd->wcbbase0) & 0xffff; - iowrite32(priv->txq[0].txd_dma, priv->sram + off); - off = le32_to_cpu(cmd->rxwrptr) & 0xffff; iowrite32(priv->rxq[0].rxd_dma, priv->sram + off); off = le32_to_cpu(cmd->rxrdptr) & 0xffff; iowrite32(priv->rxq[0].rxd_dma, priv->sram + off); - off = le32_to_cpu(cmd->wcbbase1) & 0xffff; - iowrite32(priv->txq[1].txd_dma, priv->sram + off); - - off = le32_to_cpu(cmd->wcbbase2) & 0xffff; - iowrite32(priv->txq[2].txd_dma, priv->sram + off); - - off = le32_to_cpu(cmd->wcbbase3) & 0xffff; - iowrite32(priv->txq[3].txd_dma, priv->sram + off); + priv->txq_offset[0] = le32_to_cpu(cmd->wcbbase0) & 0xffff; + priv->txq_offset[1] = le32_to_cpu(cmd->wcbbase1) & 0xffff; + priv->txq_offset[2] = le32_to_cpu(cmd->wcbbase2) & 0xffff; + priv->txq_offset[3] = le32_to_cpu(cmd->wcbbase3) & 0xffff; } done: @@ -4600,6 +4600,23 @@ static int mwl8k_init_firmware(struct ieee80211_hw *hw, char *fw_image, return rc; } +static int mwl8k_init_txqs(struct ieee80211_hw *hw) +{ + struct mwl8k_priv *priv = hw->priv; + int rc = 0; + int i; + + for (i = 0; i < MWL8K_TX_QUEUES; i++) { + rc = mwl8k_txq_init(hw, i); + if (rc) + break; + if (priv->ap_fw) + iowrite32(priv->txq[i].txd_dma, + priv->sram + priv->txq_offset[i]); + } + return rc; +} + /* initialize hw after successfully loading a firmware image */ static int mwl8k_probe_hw(struct ieee80211_hw *hw) { @@ -4627,8 +4644,14 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) goto err_stop_firmware; rxq_refill(hw, 0, INT_MAX); - for (i = 0; i < MWL8K_TX_QUEUES; i++) { - rc = mwl8k_txq_init(hw, i); + /* For the sta firmware, we need to know the dma addresses of tx queues + * before sending MWL8K_CMD_GET_HW_SPEC. So we must initialize them + * prior to issuing this command. But for the AP case, we learn the + * total number of queues from the result CMD_GET_HW_SPEC, so for this + * case we must initialize the tx queues after. + */ + if (!priv->ap_fw) { + rc = mwl8k_init_txqs(hw); if (rc) goto err_free_queues; } @@ -4656,6 +4679,8 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) /* Get config data, mac addrs etc */ if (priv->ap_fw) { rc = mwl8k_cmd_get_hw_spec_ap(hw); + if (!rc) + rc = mwl8k_init_txqs(hw); if (!rc) rc = mwl8k_cmd_set_hw_spec(hw); } else { -- cgit v1.2.3-58-ga151 From 8a7a578c2e3ac463a17fe30b11ada0509658a952 Mon Sep 17 00:00:00 2001 From: Brian Cavagnolo Date: Thu, 17 Mar 2011 11:58:42 -0700 Subject: mwl8k: update to ap firmware API version 2 Firmware APIv2 adds the following enhancements: -- capabilities are reported by the firmware -- API supports up to 8 dedicated AMPDU streams -- optional packet timestamping and expiration can be enabled. Specifically, packets that are queued in firmware for longer than 500ms will be dropped if this option is used. Based on work by "Nishant Sarmukadam" Signed-off-by: Brian Cavagnolo Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 8fefed2342d7..9db66d58f0ef 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -86,6 +86,7 @@ MODULE_PARM_DESC(ap_mode_default, #define MWL8K_RX_QUEUES 1 #define MWL8K_TX_QUEUES 4 +#define MWL8K_MAX_AMPDU_QUEUES 8 struct rxd_ops { int rxd_size; @@ -159,6 +160,9 @@ struct mwl8k_priv { u32 ap_macids_supported; u32 sta_macids_supported; + /* Ampdu stream information */ + u8 num_ampdu_queues; + /* firmware access */ struct mutex fw_mutex; struct task_struct *fw_mutex_owner; @@ -190,8 +194,8 @@ struct mwl8k_priv { int pending_tx_pkts; struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; - struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES]; - u32 txq_offset[MWL8K_TX_QUEUES]; + struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES + MWL8K_MAX_AMPDU_QUEUES]; + u32 txq_offset[MWL8K_TX_QUEUES + MWL8K_MAX_AMPDU_QUEUES]; bool radio_on; bool radio_short_preamble; @@ -1322,7 +1326,7 @@ struct mwl8k_tx_desc { __le16 pkt_len; __u8 dest_MAC_addr[ETH_ALEN]; __le32 next_txd_phys_addr; - __le32 reserved; + __le32 timestamp; __le16 rate_info; __u8 peer_id; __u8 tx_frag_cnt; @@ -2023,13 +2027,16 @@ struct mwl8k_cmd_get_hw_spec_ap { __le32 wcbbase2; __le32 wcbbase3; __le32 fw_api_version; + __le32 caps; + __le32 num_of_ampdu_queues; + __le32 wcbbase_ampdu[MWL8K_MAX_AMPDU_QUEUES]; } __packed; static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_cmd_get_hw_spec_ap *cmd; - int rc; + int rc, i; u32 api_version; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -2061,10 +2068,17 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); priv->fw_rev = le32_to_cpu(cmd->fw_rev); priv->hw_rev = cmd->hw_rev; - mwl8k_setup_2ghz_band(hw); + mwl8k_set_caps(hw, le32_to_cpu(cmd->caps)); priv->ap_macids_supported = 0x000000ff; priv->sta_macids_supported = 0x00000000; - + priv->num_ampdu_queues = le32_to_cpu(cmd->num_of_ampdu_queues); + if (priv->num_ampdu_queues > MWL8K_MAX_AMPDU_QUEUES) { + wiphy_warn(hw->wiphy, "fw reported %d ampdu queues" + " but we only support %d.\n", + priv->num_ampdu_queues, + MWL8K_MAX_AMPDU_QUEUES); + priv->num_ampdu_queues = MWL8K_MAX_AMPDU_QUEUES; + } off = le32_to_cpu(cmd->rxwrptr) & 0xffff; iowrite32(priv->rxq[0].rxd_dma, priv->sram + off); @@ -2075,6 +2089,10 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) priv->txq_offset[1] = le32_to_cpu(cmd->wcbbase1) & 0xffff; priv->txq_offset[2] = le32_to_cpu(cmd->wcbbase2) & 0xffff; priv->txq_offset[3] = le32_to_cpu(cmd->wcbbase3) & 0xffff; + + for (i = 0; i < priv->num_ampdu_queues; i++) + priv->txq_offset[i + MWL8K_TX_QUEUES] = + le32_to_cpu(cmd->wcbbase_ampdu[i]) & 0xffff; } done: @@ -2103,6 +2121,14 @@ struct mwl8k_cmd_set_hw_spec { __le32 total_rxd; } __packed; +/* If enabled, MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY will cause + * packets to expire 500 ms after the timestamp in the tx descriptor. That is, + * the packets that are queued for more than 500ms, will be dropped in the + * hardware. This helps minimizing the issues caused due to head-of-line + * blocking where a slow client can hog the bandwidth and affect traffic to a + * faster client. + */ +#define MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY 0x00000400 #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010 @@ -4434,7 +4460,7 @@ enum { MWL8366, }; -#define MWL8K_8366_AP_FW_API 1 +#define MWL8K_8366_AP_FW_API 2 #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) @@ -4650,6 +4676,7 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) * total number of queues from the result CMD_GET_HW_SPEC, so for this * case we must initialize the tx queues after. */ + priv->num_ampdu_queues = 0; if (!priv->ap_fw) { rc = mwl8k_init_txqs(hw); if (rc) -- cgit v1.2.3-58-ga151 From 5faa1aff08ef8d82b98ac2dfd7beb62ae6eda5e5 Mon Sep 17 00:00:00 2001 From: Nishant Sarmukadam Date: Thu, 17 Mar 2011 11:58:43 -0700 Subject: mwl8k: add support for block ack commands Signed-off-by: Pradeep Nemavat Signed-off-by: Brian Cavagnolo Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 156 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 9db66d58f0ef..944ad030e4dd 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -135,6 +135,14 @@ struct mwl8k_tx_queue { struct sk_buff **skb; }; +struct mwl8k_ampdu_stream { + struct ieee80211_sta *sta; + u8 tid; + u8 state; + u8 idx; + u8 txq_idx; /* index of this stream in priv->txq */ +}; + struct mwl8k_priv { struct ieee80211_hw *hw; struct pci_dev *pdev; @@ -360,6 +368,7 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { #define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ #define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */ #define MWL8K_CMD_UPDATE_STADB 0x1123 +#define MWL8K_CMD_BASTREAM 0x1125 static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) { @@ -399,6 +408,7 @@ static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) MWL8K_CMDNAME(SET_NEW_STN); MWL8K_CMDNAME(UPDATE_ENCRYPTION); MWL8K_CMDNAME(UPDATE_STADB); + MWL8K_CMDNAME(BASTREAM); default: snprintf(buf, bufsize, "0x%x", cmd); } @@ -3175,6 +3185,152 @@ static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw, return rc; } +/* + * CMD_BASTREAM. + */ + +/* + * UPSTREAM is tx direction + */ +#define BASTREAM_FLAG_DIRECTION_UPSTREAM 0x00 +#define BASTREAM_FLAG_IMMEDIATE_TYPE 0x01 + +enum { + MWL8K_BA_CREATE, + MWL8K_BA_UPDATE, + MWL8K_BA_DESTROY, + MWL8K_BA_FLUSH, + MWL8K_BA_CHECK, +} ba_stream_action_type; + + +struct mwl8k_create_ba_stream { + __le32 flags; + __le32 idle_thrs; + __le32 bar_thrs; + __le32 window_size; + u8 peer_mac_addr[6]; + u8 dialog_token; + u8 tid; + u8 queue_id; + u8 param_info; + __le32 ba_context; + u8 reset_seq_no_flag; + __le16 curr_seq_no; + u8 sta_src_mac_addr[6]; +} __packed; + +struct mwl8k_destroy_ba_stream { + __le32 flags; + __le32 ba_context; +} __packed; + +struct mwl8k_cmd_bastream { + struct mwl8k_cmd_pkt header; + __le32 action; + union { + struct mwl8k_create_ba_stream create_params; + struct mwl8k_destroy_ba_stream destroy_params; + }; +} __packed; + +static int +mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream) +{ + struct mwl8k_cmd_bastream *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + + cmd->action = cpu_to_le32(MWL8K_BA_CHECK); + + cmd->create_params.queue_id = stream->idx; + memcpy(&cmd->create_params.peer_mac_addr[0], stream->sta->addr, + ETH_ALEN); + cmd->create_params.tid = stream->tid; + + cmd->create_params.flags = + cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE) | + cpu_to_le32(BASTREAM_FLAG_DIRECTION_UPSTREAM); + + rc = mwl8k_post_cmd(hw, &cmd->header); + + kfree(cmd); + + return rc; +} + +static int +mwl8k_create_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream, + u8 buf_size) +{ + struct mwl8k_cmd_bastream *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + + cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + + cmd->action = cpu_to_le32(MWL8K_BA_CREATE); + + cmd->create_params.bar_thrs = cpu_to_le32((u32)buf_size); + cmd->create_params.window_size = cpu_to_le32((u32)buf_size); + cmd->create_params.queue_id = stream->idx; + + memcpy(cmd->create_params.peer_mac_addr, stream->sta->addr, ETH_ALEN); + cmd->create_params.tid = stream->tid; + cmd->create_params.curr_seq_no = cpu_to_le16(0); + cmd->create_params.reset_seq_no_flag = 1; + + cmd->create_params.param_info = + (stream->sta->ht_cap.ampdu_factor & + IEEE80211_HT_AMPDU_PARM_FACTOR) | + ((stream->sta->ht_cap.ampdu_density << 2) & + IEEE80211_HT_AMPDU_PARM_DENSITY); + + cmd->create_params.flags = + cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE | + BASTREAM_FLAG_DIRECTION_UPSTREAM); + + rc = mwl8k_post_cmd(hw, &cmd->header); + + wiphy_debug(hw->wiphy, "Created a BA stream for %pM : tid %d\n", + stream->sta->addr, stream->tid); + kfree(cmd); + + return rc; +} + +static void mwl8k_destroy_ba(struct ieee80211_hw *hw, + struct mwl8k_ampdu_stream *stream) +{ + struct mwl8k_cmd_bastream *cmd; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le32(MWL8K_BA_DESTROY); + + cmd->destroy_params.ba_context = cpu_to_le32(stream->idx); + mwl8k_post_cmd(hw, &cmd->header); + + wiphy_debug(hw->wiphy, "Deleted BA stream index %d\n", stream->idx); + + kfree(cmd); +} + /* * CMD_SET_NEW_STN. */ -- cgit v1.2.3-58-ga151 From e600707b021efdc109e7becd467798da339ec26d Mon Sep 17 00:00:00 2001 From: Brian Cavagnolo Date: Thu, 17 Mar 2011 11:58:44 -0700 Subject: mwl8k: differentiate between WMM queues and AMPDU queues We now have two different kinds of queues. And the number of AMPDU queues may vary. So we must be clear about which queues we are dealing with. Note that when we report the number of queues to mac80211, we only report the WMM queues. Based on work by Yogesh Powar . Signed-off-by: Brian Cavagnolo Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 52 +++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 944ad030e4dd..53581ee8b79f 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -85,8 +85,10 @@ MODULE_PARM_DESC(ap_mode_default, MWL8K_A2H_INT_TX_DONE) #define MWL8K_RX_QUEUES 1 -#define MWL8K_TX_QUEUES 4 +#define MWL8K_TX_WMM_QUEUES 4 #define MWL8K_MAX_AMPDU_QUEUES 8 +#define MWL8K_MAX_TX_QUEUES (MWL8K_TX_WMM_QUEUES + MWL8K_MAX_AMPDU_QUEUES) +#define mwl8k_tx_queues(priv) (MWL8K_TX_WMM_QUEUES + (priv)->num_ampdu_queues) struct rxd_ops { int rxd_size; @@ -202,8 +204,8 @@ struct mwl8k_priv { int pending_tx_pkts; struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; - struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES + MWL8K_MAX_AMPDU_QUEUES]; - u32 txq_offset[MWL8K_TX_QUEUES + MWL8K_MAX_AMPDU_QUEUES]; + struct mwl8k_tx_queue txq[MWL8K_MAX_TX_QUEUES]; + u32 txq_offset[MWL8K_MAX_TX_QUEUES]; bool radio_on; bool radio_short_preamble; @@ -236,7 +238,7 @@ struct mwl8k_priv { * preserve the queue configurations so they can be restored if/when * the firmware image is swapped. */ - struct ieee80211_tx_queue_params wmm_params[MWL8K_TX_QUEUES]; + struct ieee80211_tx_queue_params wmm_params[MWL8K_TX_WMM_QUEUES]; /* async firmware loading state */ unsigned fw_state; @@ -1400,7 +1402,7 @@ static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw) struct mwl8k_priv *priv = hw->priv; int i; - for (i = 0; i < MWL8K_TX_QUEUES; i++) { + for (i = 0; i < mwl8k_tx_queues(priv); i++) { struct mwl8k_tx_queue *txq = priv->txq + i; int fw_owned = 0; int drv_owned = 0; @@ -1888,7 +1890,7 @@ struct mwl8k_cmd_get_hw_spec_sta { __u8 mcs_bitmap[16]; __le32 rx_queue_ptr; __le32 num_tx_queues; - __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; + __le32 tx_queue_ptrs[MWL8K_TX_WMM_QUEUES]; __le32 caps2; __le32 num_tx_desc_per_queue; __le32 total_rxd; @@ -1994,8 +1996,8 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr)); cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma); - cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); - for (i = 0; i < MWL8K_TX_QUEUES; i++) + cmd->num_tx_queues = cpu_to_le32(mwl8k_tx_queues(priv)); + for (i = 0; i < mwl8k_tx_queues(priv); i++) cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma); cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); @@ -2101,7 +2103,7 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) priv->txq_offset[3] = le32_to_cpu(cmd->wcbbase3) & 0xffff; for (i = 0; i < priv->num_ampdu_queues; i++) - priv->txq_offset[i + MWL8K_TX_QUEUES] = + priv->txq_offset[i + MWL8K_TX_WMM_QUEUES] = le32_to_cpu(cmd->wcbbase_ampdu[i]) & 0xffff; } @@ -2125,7 +2127,7 @@ struct mwl8k_cmd_set_hw_spec { __le32 caps; __le32 rx_queue_ptr; __le32 num_tx_queues; - __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; + __le32 tx_queue_ptrs[MWL8K_MAX_TX_QUEUES]; __le32 flags; __le32 num_tx_desc_per_queue; __le32 total_rxd; @@ -2159,7 +2161,7 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma); - cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); + cmd->num_tx_queues = cpu_to_le32(mwl8k_tx_queues(priv)); /* * Mac80211 stack has Q0 as highest priority and Q3 as lowest in @@ -2167,8 +2169,8 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) * in that order. Map Q3 of mac80211 to Q0 of firmware so that the * priority is interpreted the right way in firmware. */ - for (i = 0; i < MWL8K_TX_QUEUES; i++) { - int j = MWL8K_TX_QUEUES - 1 - i; + for (i = 0; i < mwl8k_tx_queues(priv); i++) { + int j = mwl8k_tx_queues(priv) - 1 - i; cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[j].txd_dma); } @@ -3880,7 +3882,7 @@ static void mwl8k_tx_poll(unsigned long data) spin_lock_bh(&priv->tx_lock); - for (i = 0; i < MWL8K_TX_QUEUES; i++) + for (i = 0; i < mwl8k_tx_queues(priv); i++) limit -= mwl8k_txq_reclaim(hw, i, limit, 0); if (!priv->pending_tx_pkts && priv->tx_wait != NULL) { @@ -4012,7 +4014,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) tasklet_disable(&priv->poll_rx_task); /* Return all skbs to mac80211 */ - for (i = 0; i < MWL8K_TX_QUEUES; i++) + for (i = 0; i < mwl8k_tx_queues(priv); i++) mwl8k_txq_reclaim(hw, i, INT_MAX, 1); } @@ -4510,14 +4512,14 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, rc = mwl8k_fw_lock(hw); if (!rc) { - BUG_ON(queue > MWL8K_TX_QUEUES - 1); + BUG_ON(queue > MWL8K_TX_WMM_QUEUES - 1); memcpy(&priv->wmm_params[queue], params, sizeof(*params)); if (!priv->wmm_enabled) rc = mwl8k_cmd_set_wmm_mode(hw, 1); if (!rc) { - int q = MWL8K_TX_QUEUES - 1 - queue; + int q = MWL8K_TX_WMM_QUEUES - 1 - queue; rc = mwl8k_cmd_set_edca_params(hw, q, params->cw_min, params->cw_max, @@ -4788,7 +4790,7 @@ static int mwl8k_init_txqs(struct ieee80211_hw *hw) int rc = 0; int i; - for (i = 0; i < MWL8K_TX_QUEUES; i++) { + for (i = 0; i < mwl8k_tx_queues(priv); i++) { rc = mwl8k_txq_init(hw, i); if (rc) break; @@ -4906,7 +4908,7 @@ err_free_irq: free_irq(priv->pdev->irq, hw); err_free_queues: - for (i = 0; i < MWL8K_TX_QUEUES; i++) + for (i = 0; i < mwl8k_tx_queues(priv); i++) mwl8k_txq_deinit(hw, i); mwl8k_rxq_deinit(hw, 0); @@ -4928,7 +4930,7 @@ static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image) mwl8k_stop(hw); mwl8k_rxq_deinit(hw, 0); - for (i = 0; i < MWL8K_TX_QUEUES; i++) + for (i = 0; i < mwl8k_tx_queues(priv); i++) mwl8k_txq_deinit(hw, i); rc = mwl8k_init_firmware(hw, fw_image, false); @@ -4947,7 +4949,7 @@ static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image) if (rc) goto fail; - for (i = 0; i < MWL8K_TX_QUEUES; i++) { + for (i = 0; i < MWL8K_TX_WMM_QUEUES; i++) { rc = mwl8k_conf_tx(hw, i, &priv->wmm_params[i]); if (rc) goto fail; @@ -4981,7 +4983,7 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) hw->channel_change_time = 10; - hw->queues = MWL8K_TX_QUEUES; + hw->queues = MWL8K_TX_WMM_QUEUES; /* Set rssi values to dBm */ hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL; @@ -5037,7 +5039,7 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) return 0; err_unprobe_hw: - for (i = 0; i < MWL8K_TX_QUEUES; i++) + for (i = 0; i < mwl8k_tx_queues(priv); i++) mwl8k_txq_deinit(hw, i); mwl8k_rxq_deinit(hw, 0); @@ -5196,10 +5198,10 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) mwl8k_hw_reset(priv); /* Return all skbs to mac80211 */ - for (i = 0; i < MWL8K_TX_QUEUES; i++) + for (i = 0; i < mwl8k_tx_queues(priv); i++) mwl8k_txq_reclaim(hw, i, INT_MAX, 1); - for (i = 0; i < MWL8K_TX_QUEUES; i++) + for (i = 0; i < mwl8k_tx_queues(priv); i++) mwl8k_txq_deinit(hw, i); mwl8k_rxq_deinit(hw, 0); -- cgit v1.2.3-58-ga151 From ac109fd0427008e5b55e0e52e59c364de6d686fe Mon Sep 17 00:00:00 2001 From: Brian Cavagnolo Date: Thu, 17 Mar 2011 11:58:45 -0700 Subject: mwl8k: add internal API for managing AMPDU streams In particular, we can now add, start, lookup, and remove streams. Based on work by Nishant Sarmukadam and Pradeep Nemavat . Signed-off-by: Pradeep Nemavat Signed-off-by: Nishant Sarmukadam Signed-off-by: Brian Cavagnolo Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 53581ee8b79f..dcd4508b1fd4 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -137,6 +137,13 @@ struct mwl8k_tx_queue { struct sk_buff **skb; }; +enum { + AMPDU_NO_STREAM, + AMPDU_STREAM_NEW, + AMPDU_STREAM_IN_PROGRESS, + AMPDU_STREAM_ACTIVE, +}; + struct mwl8k_ampdu_stream { struct ieee80211_sta *sta; u8 tid; @@ -172,6 +179,8 @@ struct mwl8k_priv { /* Ampdu stream information */ u8 num_ampdu_queues; + spinlock_t stream_lock; + struct mwl8k_ampdu_stream ampdu[MWL8K_MAX_AMPDU_QUEUES]; /* firmware access */ struct mutex fw_mutex; @@ -1594,6 +1603,74 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index) txq->txd = NULL; } +/* caller must hold priv->stream_lock when calling the stream functions */ +struct mwl8k_ampdu_stream * +mwl8k_add_stream(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 tid) +{ + struct mwl8k_ampdu_stream *stream; + struct mwl8k_priv *priv = hw->priv; + int i; + + for (i = 0; i < priv->num_ampdu_queues; i++) { + stream = &priv->ampdu[i]; + if (stream->state == AMPDU_NO_STREAM) { + stream->sta = sta; + stream->state = AMPDU_STREAM_NEW; + stream->tid = tid; + stream->idx = i; + stream->txq_idx = MWL8K_TX_WMM_QUEUES + i; + wiphy_debug(hw->wiphy, "Added a new stream for %pM %d", + sta->addr, tid); + return stream; + } + } + return NULL; +} + +static int +mwl8k_start_stream(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream) +{ + int ret; + + /* if the stream has already been started, don't start it again */ + if (stream->state != AMPDU_STREAM_NEW) + return 0; + ret = ieee80211_start_tx_ba_session(stream->sta, stream->tid, 0); + if (ret) + wiphy_debug(hw->wiphy, "Failed to start stream for %pM %d: " + "%d\n", stream->sta->addr, stream->tid, ret); + else + wiphy_debug(hw->wiphy, "Started stream for %pM %d\n", + stream->sta->addr, stream->tid); + return ret; +} + +static void +mwl8k_remove_stream(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream) +{ + wiphy_debug(hw->wiphy, "Remove stream for %pM %d\n", stream->sta->addr, + stream->tid); + memset(stream, 0, sizeof(*stream)); +} + +static struct mwl8k_ampdu_stream * +mwl8k_lookup_stream(struct ieee80211_hw *hw, u8 *addr, u8 tid) +{ + struct mwl8k_priv *priv = hw->priv; + int i; + + for (i = 0 ; i < priv->num_ampdu_queues; i++) { + struct mwl8k_ampdu_stream *stream; + stream = &priv->ampdu[i]; + if (stream->state == AMPDU_NO_STREAM) + continue; + if (!memcmp(stream->sta->addr, addr, ETH_ALEN) && + stream->tid == tid) + return stream; + } + return NULL; +} + static void mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) { @@ -4854,6 +4931,8 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) goto err_free_queues; } + memset(priv->ampdu, 0, sizeof(priv->ampdu)); + /* * Temporarily enable interrupts. Initial firmware host * commands use interrupts and avoid polling. Disable @@ -5018,6 +5097,8 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) spin_lock_init(&priv->tx_lock); + spin_lock_init(&priv->stream_lock); + priv->tx_wait = NULL; rc = mwl8k_probe_hw(hw); -- cgit v1.2.3-58-ga151 From 65f3ddcd08fe24490359274a8c9bf526e81357a5 Mon Sep 17 00:00:00 2001 From: Nishant Sarmukadam Date: Thu, 17 Mar 2011 11:58:46 -0700 Subject: mwl8k: Initiate BA sessions Specifically, handle ampdu_action and attempt to start a BA session on receiving the first qos packet from mac80211 for transmission to a HT sta. While the BA session is being created, all the packets belonging to that stream will be dropped to prevent sequence number mismatch at the recipient. Contains contributions from: Yogesh Powar Pradeep Nemavat Brian Cavagnolo Signed-off-by: Brian Cavagnolo Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 194 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 187 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index dcd4508b1fd4..ec1190ab0f8e 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1577,7 +1577,8 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) processed++; } - if (processed && priv->radio_on && !mutex_is_locked(&priv->fw_mutex)) + if (index < MWL8K_TX_WMM_QUEUES && processed && priv->radio_on && + !mutex_is_locked(&priv->fw_mutex)) ieee80211_wake_queue(hw, index); return processed; @@ -1677,6 +1678,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) struct mwl8k_priv *priv = hw->priv; struct ieee80211_tx_info *tx_info; struct mwl8k_vif *mwl8k_vif; + struct ieee80211_sta *sta; struct ieee80211_hdr *wh; struct mwl8k_tx_queue *txq; struct mwl8k_tx_desc *tx; @@ -1684,6 +1686,10 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) u32 txstatus; u8 txdatarate; u16 qos; + int txpriority; + u8 tid = 0; + struct mwl8k_ampdu_stream *stream = NULL; + bool start_ba_session = false; wh = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_data_qos(wh->frame_control)) @@ -1699,6 +1705,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) wh = &((struct mwl8k_dma_data *)skb->data)->wh; tx_info = IEEE80211_SKB_CB(skb); + sta = tx_info->control.sta; mwl8k_vif = MWL8K_VIF(tx_info->control.vif); if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { @@ -1726,12 +1733,70 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) qos |= MWL8K_QOS_ACK_POLICY_NORMAL; } + txpriority = index; + + if (ieee80211_is_data_qos(wh->frame_control) && + skb->protocol != cpu_to_be16(ETH_P_PAE) && + sta->ht_cap.ht_supported && priv->ap_fw) { + tid = qos & 0xf; + spin_lock(&priv->stream_lock); + stream = mwl8k_lookup_stream(hw, sta->addr, tid); + if (stream != NULL) { + if (stream->state == AMPDU_STREAM_ACTIVE) { + txpriority = stream->txq_idx; + index = stream->txq_idx; + } else if (stream->state == AMPDU_STREAM_NEW) { + /* We get here if the driver sends us packets + * after we've initiated a stream, but before + * our ampdu_action routine has been called + * with IEEE80211_AMPDU_TX_START to get the SSN + * for the ADDBA request. So this packet can + * go out with no risk of sequence number + * mismatch. No special handling is required. + */ + } else { + /* Drop packets that would go out after the + * ADDBA request was sent but before the ADDBA + * response is received. If we don't do this, + * the recipient would probably receive it + * after the ADDBA request with SSN 0. This + * will cause the recipient's BA receive window + * to shift, which would cause the subsequent + * packets in the BA stream to be discarded. + * mac80211 queues our packets for us in this + * case, so this is really just a safety check. + */ + wiphy_warn(hw->wiphy, + "Cannot send packet while ADDBA " + "dialog is underway.\n"); + spin_unlock(&priv->stream_lock); + dev_kfree_skb(skb); + return; + } + } else { + /* Defer calling mwl8k_start_stream so that the current + * skb can go out before the ADDBA request. This + * prevents sequence number mismatch at the recepient + * as described above. + */ + stream = mwl8k_add_stream(hw, sta, tid); + if (stream != NULL) + start_ba_session = true; + } + spin_unlock(&priv->stream_lock); + } + dma = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); if (pci_dma_mapping_error(priv->pdev, dma)) { wiphy_debug(hw->wiphy, "failed to dma map skb, dropping TX frame.\n"); + if (start_ba_session) { + spin_lock(&priv->stream_lock); + mwl8k_remove_stream(hw, stream); + spin_unlock(&priv->stream_lock); + } dev_kfree_skb(skb); return; } @@ -1740,12 +1805,22 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) txq = priv->txq + index; + if (index >= MWL8K_TX_WMM_QUEUES && txq->len >= MWL8K_TX_DESCS) { + /* This is the case in which the tx packet is destined for an + * AMPDU queue and that AMPDU queue is full. Because we don't + * start and stop the AMPDU queues, we must drop these packets. + */ + dev_kfree_skb(skb); + spin_unlock_bh(&priv->tx_lock); + return; + } + BUG_ON(txq->skb[txq->tail] != NULL); txq->skb[txq->tail] = skb; tx = txq->txd + txq->tail; tx->data_rate = txdatarate; - tx->tx_priority = index; + tx->tx_priority = txpriority; tx->qos_control = cpu_to_le16(qos); tx->pkt_phys_addr = cpu_to_le32(dma); tx->pkt_len = cpu_to_le16(skb->len); @@ -1764,12 +1839,20 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) if (txq->tail == MWL8K_TX_DESCS) txq->tail = 0; - if (txq->head == txq->tail) + if (txq->head == txq->tail && index < MWL8K_TX_WMM_QUEUES) ieee80211_stop_queue(hw, index); mwl8k_tx_start(priv); spin_unlock_bh(&priv->tx_lock); + + /* Initiate the ampdu session here */ + if (start_ba_session) { + spin_lock(&priv->stream_lock); + if (mwl8k_start_stream(hw, stream)) + mwl8k_remove_stream(hw, stream); + spin_unlock(&priv->stream_lock); + } } @@ -4632,21 +4715,118 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx, return 0; } +#define MAX_AMPDU_ATTEMPTS 5 + static int mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size) { + + int i, rc = 0; + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_ampdu_stream *stream; + u8 *addr = sta->addr; + + if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) + return -ENOTSUPP; + + spin_lock(&priv->stream_lock); + stream = mwl8k_lookup_stream(hw, addr, tid); + switch (action) { case IEEE80211_AMPDU_RX_START: case IEEE80211_AMPDU_RX_STOP: - if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) - return -ENOTSUPP; - return 0; + break; + case IEEE80211_AMPDU_TX_START: + /* By the time we get here the hw queues may contain outgoing + * packets for this RA/TID that are not part of this BA + * session. The hw will assign sequence numbers to these + * packets as they go out. So if we query the hw for its next + * sequence number and use that for the SSN here, it may end up + * being wrong, which will lead to sequence number mismatch at + * the recipient. To avoid this, we reset the sequence number + * to O for the first MPDU in this BA stream. + */ + *ssn = 0; + if (stream == NULL) { + /* This means that somebody outside this driver called + * ieee80211_start_tx_ba_session. This is unexpected + * because we do our own rate control. Just warn and + * move on. + */ + wiphy_warn(hw->wiphy, "Unexpected call to %s. " + "Proceeding anyway.\n", __func__); + stream = mwl8k_add_stream(hw, sta, tid); + } + if (stream == NULL) { + wiphy_debug(hw->wiphy, "no free AMPDU streams\n"); + rc = -EBUSY; + break; + } + stream->state = AMPDU_STREAM_IN_PROGRESS; + + /* Release the lock before we do the time consuming stuff */ + spin_unlock(&priv->stream_lock); + for (i = 0; i < MAX_AMPDU_ATTEMPTS; i++) { + rc = mwl8k_check_ba(hw, stream); + + if (!rc) + break; + /* + * HW queues take time to be flushed, give them + * sufficient time + */ + + msleep(1000); + } + spin_lock(&priv->stream_lock); + if (rc) { + wiphy_err(hw->wiphy, "Stream for tid %d busy after %d" + " attempts\n", tid, MAX_AMPDU_ATTEMPTS); + mwl8k_remove_stream(hw, stream); + rc = -EBUSY; + break; + } + ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); + break; + case IEEE80211_AMPDU_TX_STOP: + if (stream == NULL) + break; + if (stream->state == AMPDU_STREAM_ACTIVE) { + spin_unlock(&priv->stream_lock); + mwl8k_destroy_ba(hw, stream); + spin_lock(&priv->stream_lock); + } + mwl8k_remove_stream(hw, stream); + ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + BUG_ON(stream == NULL); + BUG_ON(stream->state != AMPDU_STREAM_IN_PROGRESS); + spin_unlock(&priv->stream_lock); + rc = mwl8k_create_ba(hw, stream, buf_size); + spin_lock(&priv->stream_lock); + if (!rc) + stream->state = AMPDU_STREAM_ACTIVE; + else { + spin_unlock(&priv->stream_lock); + mwl8k_destroy_ba(hw, stream); + spin_lock(&priv->stream_lock); + wiphy_debug(hw->wiphy, + "Failed adding stream for sta %pM tid %d\n", + addr, tid); + mwl8k_remove_stream(hw, stream); + } + break; + default: - return -ENOTSUPP; + rc = -ENOTSUPP; } + + spin_unlock(&priv->stream_lock); + return rc; } static const struct ieee80211_ops mwl8k_ops = { -- cgit v1.2.3-58-ga151 From 3aefc37ee789188f0d4488cae04ff618f4c4ddf6 Mon Sep 17 00:00:00 2001 From: Nishant Sarmukadam Date: Thu, 17 Mar 2011 11:58:47 -0700 Subject: mwl8k: Handle the watchdog event from the firmware When an ampdu stream is on, if the firmware rate adaptation logic decides that the outgoing packet rate to the station needs to go below 6.5Mbps (non HT rate), it sends an event indicating that the ampdu stream needs to be destroyed. Handle this event in the driver and destroy the ampdu stream so that the rate can go below 6.5Mbps Signed-off-by: Nishant Sarmukadam Signed-off-by: Brian Cavagnolo Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 77 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index ec1190ab0f8e..b90178da5a27 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -63,6 +63,7 @@ MODULE_PARM_DESC(ap_mode_default, #define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38 #define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c #define MWL8K_A2H_INT_DUMMY (1 << 20) +#define MWL8K_A2H_INT_BA_WATCHDOG (1 << 14) #define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11) #define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10) #define MWL8K_A2H_INT_RADAR_DETECT (1 << 7) @@ -82,7 +83,8 @@ MODULE_PARM_DESC(ap_mode_default, MWL8K_A2H_INT_MAC_EVENT | \ MWL8K_A2H_INT_OPC_DONE | \ MWL8K_A2H_INT_RX_READY | \ - MWL8K_A2H_INT_TX_DONE) + MWL8K_A2H_INT_TX_DONE | \ + MWL8K_A2H_INT_BA_WATCHDOG) #define MWL8K_RX_QUEUES 1 #define MWL8K_TX_WMM_QUEUES 4 @@ -181,6 +183,7 @@ struct mwl8k_priv { u8 num_ampdu_queues; spinlock_t stream_lock; struct mwl8k_ampdu_stream ampdu[MWL8K_MAX_AMPDU_QUEUES]; + struct work_struct watchdog_ba_handle; /* firmware access */ struct mutex fw_mutex; @@ -375,6 +378,7 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { #define MWL8K_CMD_ENABLE_SNIFFER 0x0150 #define MWL8K_CMD_SET_MAC_ADDR 0x0202 /* per-vif */ #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 +#define MWL8K_CMD_GET_WATCHDOG_BITMAP 0x0205 #define MWL8K_CMD_BSS_START 0x1100 /* per-vif */ #define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ #define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */ @@ -420,6 +424,7 @@ static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) MWL8K_CMDNAME(UPDATE_ENCRYPTION); MWL8K_CMDNAME(UPDATE_STADB); MWL8K_CMDNAME(BASTREAM); + MWL8K_CMDNAME(GET_WATCHDOG_BITMAP); default: snprintf(buf, bufsize, "0x%x", cmd); } @@ -3319,6 +3324,65 @@ static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode) return rc; } +/* + * CMD_GET_WATCHDOG_BITMAP. + */ +struct mwl8k_cmd_get_watchdog_bitmap { + struct mwl8k_cmd_pkt header; + u8 bitmap; +} __packed; + +static int mwl8k_cmd_get_watchdog_bitmap(struct ieee80211_hw *hw, u8 *bitmap) +{ + struct mwl8k_cmd_get_watchdog_bitmap *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_WATCHDOG_BITMAP); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + + rc = mwl8k_post_cmd(hw, &cmd->header); + if (!rc) + *bitmap = cmd->bitmap; + + kfree(cmd); + + return rc; +} + +#define INVALID_BA 0xAA +static void mwl8k_watchdog_ba_events(struct work_struct *work) +{ + int rc; + u8 bitmap = 0, stream_index; + struct mwl8k_ampdu_stream *streams; + struct mwl8k_priv *priv = + container_of(work, struct mwl8k_priv, watchdog_ba_handle); + + rc = mwl8k_cmd_get_watchdog_bitmap(priv->hw, &bitmap); + if (rc) + return; + + if (bitmap == INVALID_BA) + return; + + /* the bitmap is the hw queue number. Map it to the ampdu queue. */ + stream_index = bitmap - MWL8K_TX_WMM_QUEUES; + + BUG_ON(stream_index >= priv->num_ampdu_queues); + + streams = &priv->ampdu[stream_index]; + + if (streams->state == AMPDU_STREAM_ACTIVE) + ieee80211_stop_tx_ba_session(streams->sta, streams->tid); + + return; +} + + /* * CMD_BSS_START. */ @@ -4014,6 +4078,11 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) tasklet_schedule(&priv->poll_rx_task); } + if (status & MWL8K_A2H_INT_BA_WATCHDOG) { + status &= ~MWL8K_A2H_INT_BA_WATCHDOG; + ieee80211_queue_work(hw, &priv->watchdog_ba_handle); + } + if (status) iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); @@ -4166,6 +4235,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) /* Stop finalize join worker */ cancel_work_sync(&priv->finalize_join_worker); + cancel_work_sync(&priv->watchdog_ba_handle); if (priv->beacon_skb != NULL) dev_kfree_skb(priv->beacon_skb); @@ -5100,7 +5170,8 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - iowrite32(MWL8K_A2H_INT_TX_DONE | MWL8K_A2H_INT_RX_READY, + iowrite32(MWL8K_A2H_INT_TX_DONE|MWL8K_A2H_INT_RX_READY| + MWL8K_A2H_INT_BA_WATCHDOG, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); @@ -5258,6 +5329,8 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) /* Finalize join worker */ INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); + /* Handle watchdog ba events */ + INIT_WORK(&priv->watchdog_ba_handle, mwl8k_watchdog_ba_events); /* TX reclaim and RX tasklets. */ tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); -- cgit v1.2.3-58-ga151 From 170335432ad36584a6d24fc1fd903024d221ef55 Mon Sep 17 00:00:00 2001 From: Nishant Sarmukadam Date: Thu, 17 Mar 2011 11:58:48 -0700 Subject: mwl8k: Check outgoing rate for a station to decide if ampdu can be created If the outgoing packet rate to a particular HT station is <=6.5 Mbps, do not attempt to create an ampdu. Also, if the outgoing rate is legacy rate, do not create an ampdu. Signed-off-by: Nishant Sarmukadam Signed-off-by: Brian Cavagnolo Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 60 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index b90178da5a27..5473f4ca0ca0 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -291,6 +291,7 @@ struct mwl8k_vif { struct mwl8k_sta { /* Index into station database. Returned by UPDATE_STADB. */ u8 peer_id; + u8 is_ampdu_allowed; }; #define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv)) @@ -1517,6 +1518,27 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) MWL8K_TXD_STATUS_OK_RETRY | \ MWL8K_TXD_STATUS_OK_MORE_RETRY)) +/* The firmware will fill in the rate information + * for each packet that gets queued in the hardware + * in this structure + */ + +struct rateinfo { + __le16 format:1; + __le16 short_gi:1; + __le16 band_width:1; + __le16 rate_id_mcs:6; + __le16 adv_coding:2; + __le16 antenna:2; + __le16 act_sub_chan:2; + __le16 preamble_type:1; + __le16 power_id:4; + __le16 antenna2:1; + __le16 reserved:1; + __le16 tx_bf_frame:1; + __le16 green_field:1; +} __packed; + static int mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) { @@ -1533,6 +1555,11 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) struct sk_buff *skb; struct ieee80211_tx_info *info; u32 status; + struct ieee80211_sta *sta; + struct mwl8k_sta *sta_info = NULL; + u16 rate_info; + struct rateinfo *rate; + struct ieee80211_hdr *wh; tx = txq->head; tx_desc = txq->txd + tx; @@ -1561,11 +1588,34 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) mwl8k_remove_dma_header(skb, tx_desc->qos_control); + wh = (struct ieee80211_hdr *) skb->data; + /* Mark descriptor as unused */ tx_desc->pkt_phys_addr = 0; tx_desc->pkt_len = 0; info = IEEE80211_SKB_CB(skb); + if (ieee80211_is_data(wh->frame_control)) { + sta = info->control.sta; + if (sta) { + sta_info = MWL8K_STA(sta); + BUG_ON(sta_info == NULL); + rate_info = le16_to_cpu(tx_desc->rate_info); + rate = (struct rateinfo *)&rate_info; + /* If rate is < 6.5 Mpbs for an ht station + * do not form an ampdu. If the station is a + * legacy station (format = 0), do not form an + * ampdu + */ + if (rate->rate_id_mcs < 1 || + rate->format == 0) { + sta_info->is_ampdu_allowed = false; + } else { + sta_info->is_ampdu_allowed = true; + } + } + } + ieee80211_tx_info_clear_status(info); /* Rate control is happening in the firmware. @@ -1784,9 +1834,11 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) * prevents sequence number mismatch at the recepient * as described above. */ - stream = mwl8k_add_stream(hw, sta, tid); - if (stream != NULL) - start_ba_session = true; + if (MWL8K_STA(sta)->is_ampdu_allowed) { + stream = mwl8k_add_stream(hw, sta, tid); + if (stream != NULL) + start_ba_session = true; + } } spin_unlock(&priv->stream_lock); } @@ -4719,6 +4771,8 @@ static int mwl8k_sta_add(struct ieee80211_hw *hw, ret = mwl8k_cmd_update_stadb_add(hw, vif, sta); if (ret >= 0) { MWL8K_STA(sta)->peer_id = ret; + if (sta->ht_cap.ht_supported) + MWL8K_STA(sta)->is_ampdu_allowed = true; ret = 0; } -- cgit v1.2.3-58-ga151 From a0e7c6cfe2a04af450274638845802b5c384e8df Mon Sep 17 00:00:00 2001 From: Nishant Sarmukadam Date: Thu, 17 Mar 2011 11:58:49 -0700 Subject: mwl8k: Queue ADDBA requests in respective data queues Queue ADDBA requests in respective data queues to avoid ADDBA requests and the the related data packets (to the same ra/tid) queued in the hardware to be sent out asynchronously. Signed-off-by: Nishant Sarmukadam Signed-off-by: Brian Cavagnolo Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 5473f4ca0ca0..ae56d2f32b2e 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1518,6 +1518,33 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) MWL8K_TXD_STATUS_OK_RETRY | \ MWL8K_TXD_STATUS_OK_MORE_RETRY)) +static int mwl8k_tid_queue_mapping(u8 tid) +{ + BUG_ON(tid > 7); + + switch (tid) { + case 0: + case 3: + return IEEE80211_AC_BE; + break; + case 1: + case 2: + return IEEE80211_AC_BK; + break; + case 4: + case 5: + return IEEE80211_AC_VI; + break; + case 6: + case 7: + return IEEE80211_AC_VO; + break; + default: + return -1; + break; + } +} + /* The firmware will fill in the rate information * for each packet that gets queued in the hardware * in this structure @@ -1745,6 +1772,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) u8 tid = 0; struct mwl8k_ampdu_stream *stream = NULL; bool start_ba_session = false; + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; wh = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_data_qos(wh->frame_control)) @@ -1788,6 +1816,24 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) qos |= MWL8K_QOS_ACK_POLICY_NORMAL; } + /* Queue ADDBA request in the respective data queue. While setting up + * the ampdu stream, mac80211 queues further packets for that + * particular ra/tid pair. However, packets piled up in the hardware + * for that ra/tid pair will still go out. ADDBA request and the + * related data packets going out from different queues asynchronously + * will cause a shift in the receiver window which might result in + * ampdu packets getting dropped at the receiver after the stream has + * been setup. + */ + if (unlikely(ieee80211_is_action(wh->frame_control) && + mgmt->u.action.category == WLAN_CATEGORY_BACK && + mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ && + priv->ap_fw)) { + u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); + tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; + index = mwl8k_tid_queue_mapping(tid); + } + txpriority = index; if (ieee80211_is_data_qos(wh->frame_control) && -- cgit v1.2.3-58-ga151 From 716b1bf3c5040f2303d6d1d0dfee6d8851cedc9d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 17 Mar 2011 21:53:01 -0500 Subject: rtlwifi: rtl8192c{e,u}: Remove some extraneous casts on memcpy commands Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192ce/trx.h | 4 ++-- drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h index 803adcc80c96..b0b0b13dd0ae 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h @@ -532,9 +532,9 @@ #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ do { \ if (_size > TX_DESC_NEXT_DESC_OFFSET) \ - memset((void *)__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ + memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ else \ - memset((void *)__pdesc, 0, _size); \ + memset(__pdesc, 0, _size); \ } while (0); #define RX_HAL_IS_CCK_RATE(_pdesc)\ diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index d0b0d43b9a6d..3f0cb81c424f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -656,7 +656,7 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); __le16 fc = hdr->frame_control; - memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE); + memset(pdesc, 0, RTL_TX_HEADER_SIZE); if (firstseg) SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); -- cgit v1.2.3-58-ga151 From c70cab1a45d56395db03957f6504c6b613bece5b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 19 Mar 2011 13:55:37 +0100 Subject: ath9k: remove unnecessary debugfs return code checks Since the ath9k debugfs directory is cleaned up by debugfs_remove_recursive, there's no point in checking the return code of every single debugfs create line. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 88 +++++++++++----------------------- 1 file changed, 29 insertions(+), 59 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 8df5a92a20f1..9fe86939d93e 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1088,67 +1088,37 @@ int ath9k_init_debug(struct ath_hw *ah) return -ENOMEM; #ifdef CONFIG_ATH_DEBUG - if (!debugfs_create_file("debug", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, &fops_debug)) - goto err; + debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, + sc, &fops_debug); #endif - - if (!debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, - sc, &fops_dma)) - goto err; - - if (!debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, - sc, &fops_interrupt)) - goto err; - - if (!debugfs_create_file("wiphy", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, &fops_wiphy)) - goto err; - - if (!debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, - sc, &fops_xmit)) - goto err; - - if (!debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, - sc, &fops_stations)) - goto err; - - if (!debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, - sc, &fops_misc)) - goto err; - - if (!debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, - sc, &fops_recv)) - goto err; - - if (!debugfs_create_file("rx_chainmask", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, &fops_rx_chainmask)) - goto err; - - if (!debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, &fops_tx_chainmask)) - goto err; - - if (!debugfs_create_file("regidx", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, &fops_regidx)) - goto err; - - if (!debugfs_create_file("regval", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, &fops_regval)) - goto err; - - if (!debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca)) - goto err; - - if (!debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, - sc, &fops_regdump)) - goto err; + debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_dma); + debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_interrupt); + debugfs_create_file("wiphy", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, + sc, &fops_wiphy); + debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_xmit); + debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_stations); + debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_misc); + debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_recv); + debugfs_create_file("rx_chainmask", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_rx_chainmask); + debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_tx_chainmask); + debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, + sc, &fops_regidx); + debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, + sc, &fops_regval); + debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, + &ah->config.cwm_ignore_extcca); + debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_regdump); sc->debug.regidx = 0; return 0; -err: - debugfs_remove_recursive(sc->debug.debugfs_phy); - sc->debug.debugfs_phy = NULL; - return -ENOMEM; } -- cgit v1.2.3-58-ga151 From 691680b8335fa8995b190676f53e3bcef6477b4a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 19 Mar 2011 13:55:38 +0100 Subject: ath9k: add an interface for overriding the value of specific GPIO pins Some devices control antenna settings or other things through GPIO pins of the wireless interface. Add a debugfs interface for changing those and keeping them set across card resets. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 6 ++++++ drivers/net/wireless/ath/ath9k/hw.c | 16 ++++++++++++++++ drivers/net/wireless/ath/ath9k/hw.h | 2 ++ 3 files changed, 24 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 9fe86939d93e..a762cadb3ab7 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1119,6 +1119,12 @@ int ath9k_init_debug(struct ath_hw *ah) debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_regdump); + debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); + + debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); + sc->debug.regidx = 0; return 0; } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 338b07502f1a..b170c455a40b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1212,6 +1212,20 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, return true; } +static void ath9k_hw_apply_gpio_override(struct ath_hw *ah) +{ + u32 gpio_mask = ah->gpio_mask; + int i; + + for (i = 0; gpio_mask; i++, gpio_mask >>= 1) { + if (!(gpio_mask & 1)) + continue; + + ath9k_hw_cfg_output(ah, i, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i))); + } +} + bool ath9k_hw_check_alive(struct ath_hw *ah) { int count = 50; @@ -1500,6 +1514,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (AR_SREV_9300_20_OR_LATER(ah)) ar9003_hw_bb_watchdog_config(ah); + ath9k_hw_apply_gpio_override(ah); + return 0; } EXPORT_SYMBOL(ath9k_hw_reset); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index c86eea28a88f..775c0eb10b95 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -799,6 +799,8 @@ struct ath_hw { int initPDADC; int PDADCdelta; u8 led_pin; + u32 gpio_mask; + u32 gpio_val; struct ar5416IniArray iniModes; struct ar5416IniArray iniCommon; -- cgit v1.2.3-58-ga151 From 6fb1b1e18fe3d141c54182c5d5b3af823bed455f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 19 Mar 2011 13:55:39 +0100 Subject: ath9k: add support for overriding the MAC address through platform data On some devices the correct MAC address is not in the EEPROM data, but stored somewhere else. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 7 ++++++- include/linux/ath9k_platform.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 79aec983279f..e22e8215d941 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -15,6 +15,7 @@ */ #include +#include #include "ath9k.h" @@ -537,6 +538,7 @@ static void ath9k_init_misc(struct ath_softc *sc) static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, const struct ath_bus_ops *bus_ops) { + struct ath9k_platform_data *pdata = sc->dev->platform_data; struct ath_hw *ah = NULL; struct ath_common *common; int ret = 0, i; @@ -551,7 +553,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, ah->hw_version.subsysid = subsysid; sc->sc_ah = ah; - if (!sc->dev->platform_data) + if (!pdata) ah->ah_flags |= AH_USE_EEPROM; common = ath9k_hw_common(ah); @@ -587,6 +589,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, if (ret) goto err_hw; + if (pdata && pdata->macaddr) + memcpy(common->macaddr, pdata->macaddr, ETH_ALEN); + ret = ath9k_init_queues(sc); if (ret) goto err_queues; diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h index b847fc7b93f9..b5f06583a1ba 100644 --- a/include/linux/ath9k_platform.h +++ b/include/linux/ath9k_platform.h @@ -23,6 +23,7 @@ struct ath9k_platform_data { u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS]; + u8 *macaddr; }; #endif /* _LINUX_ATH9K_PLATFORM_H */ -- cgit v1.2.3-58-ga151 From 6de66dd963ddd669667a81a2401f2fd6472ff55c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 19 Mar 2011 13:55:40 +0100 Subject: ath9k: add support for overriding LED pin and GPIO settings from platform data Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/gpio.c | 14 ++++++++------ drivers/net/wireless/ath/ath9k/hw.h | 2 +- drivers/net/wireless/ath/ath9k/init.c | 8 +++++++- include/linux/ath9k_platform.h | 4 ++++ 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 0fb8f8ac275a..44a0a886124d 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -41,12 +41,14 @@ void ath_init_leds(struct ath_softc *sc) { int ret; - if (AR_SREV_9287(sc->sc_ah)) - sc->sc_ah->led_pin = ATH_LED_PIN_9287; - else if (AR_SREV_9485(sc->sc_ah)) - sc->sc_ah->led_pin = ATH_LED_PIN_9485; - else - sc->sc_ah->led_pin = ATH_LED_PIN_DEF; + if (sc->sc_ah->led_pin < 0) { + if (AR_SREV_9287(sc->sc_ah)) + sc->sc_ah->led_pin = ATH_LED_PIN_9287; + else if (AR_SREV_9485(sc->sc_ah)) + sc->sc_ah->led_pin = ATH_LED_PIN_9485; + else + sc->sc_ah->led_pin = ATH_LED_PIN_DEF; + } /* Configure gpio 1 for output */ ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 775c0eb10b95..3d9fc6e391a7 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -798,7 +798,7 @@ struct ath_hw { u32 originalGain[22]; int initPDADC; int PDADCdelta; - u8 led_pin; + int led_pin; u32 gpio_mask; u32 gpio_val; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index e22e8215d941..cdb0f1c89a0e 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -553,8 +553,14 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, ah->hw_version.subsysid = subsysid; sc->sc_ah = ah; - if (!pdata) + if (!pdata) { ah->ah_flags |= AH_USE_EEPROM; + sc->sc_ah->led_pin = -1; + } else { + sc->sc_ah->gpio_mask = pdata->gpio_mask; + sc->sc_ah->gpio_val = pdata->gpio_val; + sc->sc_ah->led_pin = pdata->led_pin; + } common = ath9k_hw_common(ah); common->ops = &ath9k_common_ops; diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h index b5f06583a1ba..020387a114e3 100644 --- a/include/linux/ath9k_platform.h +++ b/include/linux/ath9k_platform.h @@ -24,6 +24,10 @@ struct ath9k_platform_data { u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS]; u8 *macaddr; + + int led_pin; + u32 gpio_mask; + u32 gpio_val; }; #endif /* _LINUX_ATH9K_PLATFORM_H */ -- cgit v1.2.3-58-ga151 From f171760c558946c7a2e0ee310dfb968f9d4853c6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 19 Mar 2011 13:55:41 +0100 Subject: ath9k_hw: enable a BlockAck related fixup specific to AR9100 Fixes interop issues with aggregation in combination with multi-BSSID Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 ++ drivers/net/wireless/ath/ath9k/reg.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index b170c455a40b..175c36f3fdac 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -410,6 +410,8 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE | AR_STA_ID1_MCAST_KSRCH; + if (AR_SREV_9100(ah)) + ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; ah->enable_32kHz_clock = DONT_USE_32KHZ; ah->slottime = 20; ah->globaltxtimeout = (u32) -1; diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 8fa8acfde62e..693d543937b5 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1396,6 +1396,7 @@ enum { #define AR_STA_ID1_PCF 0x00100000 #define AR_STA_ID1_USE_DEFANT 0x00200000 #define AR_STA_ID1_DEFANT_UPDATE 0x00400000 +#define AR_STA_ID1_AR9100_BA_FIX 0x00400000 #define AR_STA_ID1_RTS_USE_DEF 0x00800000 #define AR_STA_ID1_ACKCTS_6MB 0x01000000 #define AR_STA_ID1_BASE_RATE_11B 0x02000000 -- cgit v1.2.3-58-ga151 From 598cdd5246ea158310942699e5008ac7f687ad62 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 19 Mar 2011 13:55:42 +0100 Subject: ath9k_hw: force rx chainmask to 7 on AR9100 Most AR9100 devices already have a chainmask of 7 (three antennas), however on the ones that don't (rx and tx chainmask set to 5), problems with IQ mismatch calibration have been observed. This shows up as tx queue hangs (and subsequent hardware resets) if traffic is sent during this type of calibration. Forcing the rx chainmask to 7 fixes the calibration issues with no apparent negative side effects on throughput and stability. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 175c36f3fdac..8b8656898dfe 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1869,6 +1869,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) !(AR_SREV_9271(ah))) /* CB71: GPIO 0 is pulled down to indicate 3 rx chains */ pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7; + else if (AR_SREV_9100(ah)) + pCap->rx_chainmask = 0x7; else /* Use rx_chainmask from EEPROM. */ pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); -- cgit v1.2.3-58-ga151 From a9cbe96d19861755680a712b709cccac5dc6aca8 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 19 Mar 2011 13:55:43 +0100 Subject: ath9k: remove the pending frames ath_txq_schedule workaround This workaround called ath_txq_schedule whenever there were still pending frames for a queue, but the queue depth was zero. Because of its its high false positive probability (e.g. with paused TIDs) and because it is in the way of other pending work (AP powersave fixes), it is better to remove this code entirely. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 26734e53b37f..f916f088b553 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2144,33 +2144,6 @@ static void ath_tx_complete_poll_work(struct work_struct *work) } else { txq->axq_tx_inprogress = true; } - } else { - /* If the queue has pending buffers, then it - * should be doing tx work (and have axq_depth). - * Shouldn't get to this state I think..but - * we do. - */ - if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && - (txq->pending_frames > 0 || - !list_empty(&txq->axq_acq) || - txq->stopped)) { - ath_err(ath9k_hw_common(sc->sc_ah), - "txq: %p axq_qnum: %u," - " mac80211_qnum: %i" - " axq_link: %p" - " pending frames: %i" - " axq_acq empty: %i" - " stopped: %i" - " axq_depth: 0 Attempting to" - " restart tx logic.\n", - txq, txq->axq_qnum, - txq->mac80211_qnum, - txq->axq_link, - txq->pending_frames, - list_empty(&txq->axq_acq), - txq->stopped); - ath_txq_schedule(sc, txq); - } } spin_unlock_bh(&txq->axq_lock); } -- cgit v1.2.3-58-ga151 From be7974aa105dc47bb25013016d1fcad17da17783 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 21 Mar 2011 15:07:55 +0100 Subject: mac80211: Minor optimization in tx status handling ieee80211_tx_status iterates over all tx rates the driver reports back in order to 1) mark tx rates as invalid if the driver cannot have tried that rate 2) find the actually used tx rate for the final retransmission By leaving the for loop when the first invalid rate index is found we can move the rates_idx assignment after the loop and therefore save a few assignments and conditionals. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- net/mac80211/status.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index b936dd29e92b..3ed3c835fbbf 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -189,16 +189,19 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) bool acked; for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { - /* the HW cannot have attempted that rate */ - if (i >= hw->max_report_rates) { + if (info->status.rates[i].idx < 0) { + break; + } else if (i >= hw->max_report_rates) { + /* the HW cannot have attempted that rate */ info->status.rates[i].idx = -1; info->status.rates[i].count = 0; - } else if (info->status.rates[i].idx >= 0) { - rates_idx = i; + break; } retry_count += info->status.rates[i].count; } + rates_idx = i - 1; + if (retry_count < 0) retry_count = 0; -- cgit v1.2.3-58-ga151 From 903946e6e21ef4dd678acafb8881cabde9182caf Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 21 Mar 2011 17:27:35 -0700 Subject: ath9k_hw: remove AR9485 1.0 support Only AR9485 1.1 was sold. This debloats the driver by ~14 KiB. text data bss dec hex filename 300413 624 1056 302093 49c0d drivers/net/wireless/ath/ath9k/ath9k_hw.ko text data bss dec hex filename 310285 624 1056 311965 4c29d drivers/net/wireless/ath/ath9k/ath9k_hw-old.ko $ du -b ath9k_hw* 6210541 ath9k_hw.ko 6225089 ath9k_hw-old.ko Cc: Bill Wu Cc: Paul Shaw Cc: Forbes Tsai Cc: Jesmine Chen Cc: Marvian Chen Cc: Vivek Natarajan Cc: Bernadette Yetso Cc: Sarvesh Shrivastava Acked-by: Yi-Chen Su Acked-by: Jeffrey Chung Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 90 --- drivers/net/wireless/ath/ath9k/ar9485_initvals.h | 925 ----------------------- 2 files changed, 1015 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 7f5de6e4448b..3daf3df02481 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -88,66 +88,6 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) ar9485_1_1_pcie_phy_clkreq_disable_L1, ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), 2); - } else if (AR_SREV_9485(ah)) { - /* mac */ - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], - ar9485_1_0_mac_core, - ARRAY_SIZE(ar9485_1_0_mac_core), 2); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], - ar9485_1_0_mac_postamble, - ARRAY_SIZE(ar9485_1_0_mac_postamble), 5); - - /* bb */ - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_0, - ARRAY_SIZE(ar9485_1_0), 2); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], - ar9485_1_0_baseband_core, - ARRAY_SIZE(ar9485_1_0_baseband_core), 2); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], - ar9485_1_0_baseband_postamble, - ARRAY_SIZE(ar9485_1_0_baseband_postamble), 5); - - /* radio */ - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], - ar9485_1_0_radio_core, - ARRAY_SIZE(ar9485_1_0_radio_core), 2); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], - ar9485_1_0_radio_postamble, - ARRAY_SIZE(ar9485_1_0_radio_postamble), 2); - - /* soc */ - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], - ar9485_1_0_soc_preamble, - ARRAY_SIZE(ar9485_1_0_soc_preamble), 2); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0); - - /* rx/tx gain */ - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9485Common_rx_gain_1_0, - ARRAY_SIZE(ar9485Common_rx_gain_1_0), 2); - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9485Modes_lowest_ob_db_tx_gain_1_0, - ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0), - 5); - - /* Load PCIE SERDES settings from INI */ - - /* Awake Setting */ - - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1, - ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1), - 2); - - /* Sleep Setting */ - - INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, - ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1, - ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1), - 2); } else { /* mac */ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); @@ -228,11 +168,6 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) ar9485_modes_lowest_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), 5); - else if (AR_SREV_9485(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9485Modes_lowest_ob_db_tx_gain_1_0, - ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0), - 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_lowest_ob_db_tx_gain_table_2p2, @@ -245,11 +180,6 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) ar9485Modes_high_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1), 5); - else if (AR_SREV_9485(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9485Modes_high_ob_db_tx_gain_1_0, - ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_0), - 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_high_ob_db_tx_gain_table_2p2, @@ -262,11 +192,6 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) ar9485Modes_low_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1), 5); - else if (AR_SREV_9485(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9485Modes_low_ob_db_tx_gain_1_0, - ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_0), - 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_low_ob_db_tx_gain_table_2p2, @@ -279,11 +204,6 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) ar9485Modes_high_power_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1), 5); - else if (AR_SREV_9485(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9485Modes_high_power_tx_gain_1_0, - ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_0), - 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_high_power_tx_gain_table_2p2, @@ -303,11 +223,6 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) ar9485_common_rx_gain_1_1, ARRAY_SIZE(ar9485_common_rx_gain_1_1), 2); - else if (AR_SREV_9485(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9485Common_rx_gain_1_0, - ARRAY_SIZE(ar9485Common_rx_gain_1_0), - 2); else INIT_INI_ARRAY(&ah->iniModesRxGain, ar9300Common_rx_gain_table_2p2, @@ -320,11 +235,6 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) ar9485Common_wo_xlna_rx_gain_1_1, ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2); - else if (AR_SREV_9485(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9485Common_wo_xlna_rx_gain_1_0, - ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_0), - 2); else INIT_INI_ARRAY(&ah->iniModesRxGain, ar9300Common_wo_xlna_rx_gain_table_2p2, diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index 71cc0a3a29fb..f91f73e50d00 100644 --- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h @@ -17,931 +17,6 @@ #ifndef INITVALS_9485_H #define INITVALS_9485_H -static const u32 ar9485Common_1_0[][2] = { - /* Addr allmodes */ - {0x00007010, 0x00000022}, - {0x00007020, 0x00000000}, - {0x00007034, 0x00000002}, - {0x00007038, 0x000004c2}, -}; - -static const u32 ar9485_1_0_mac_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, - {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, -}; - -static const u32 ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1[][2] = { - /* Addr allmodes */ - {0x00018c00, 0x10212e5e}, - {0x00018c04, 0x000801d8}, - {0x00018c08, 0x0000580c}, -}; - -static const u32 ar9485Common_wo_xlna_rx_gain_1_0[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x01800082}, - {0x0000a014, 0x01820181}, - {0x0000a018, 0x01840183}, - {0x0000a01c, 0x01880185}, - {0x0000a020, 0x018a0189}, - {0x0000a024, 0x02850284}, - {0x0000a028, 0x02890288}, - {0x0000a02c, 0x03850384}, - {0x0000a030, 0x03890388}, - {0x0000a034, 0x038b038a}, - {0x0000a038, 0x038d038c}, - {0x0000a03c, 0x03910390}, - {0x0000a040, 0x03930392}, - {0x0000a044, 0x03950394}, - {0x0000a048, 0x00000396}, - {0x0000a04c, 0x00000000}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x28282828}, - {0x0000a084, 0x28282828}, - {0x0000a088, 0x28282828}, - {0x0000a08c, 0x28282828}, - {0x0000a090, 0x28282828}, - {0x0000a094, 0x21212128}, - {0x0000a098, 0x171c1c1c}, - {0x0000a09c, 0x02020212}, - {0x0000a0a0, 0x00000202}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x111f1100}, - {0x0000a0c8, 0x111d111e}, - {0x0000a0cc, 0x111b111c}, - {0x0000a0d0, 0x22032204}, - {0x0000a0d4, 0x22012202}, - {0x0000a0d8, 0x221f2200}, - {0x0000a0dc, 0x221d221e}, - {0x0000a0e0, 0x33013302}, - {0x0000a0e4, 0x331f3300}, - {0x0000a0e8, 0x4402331e}, - {0x0000a0ec, 0x44004401}, - {0x0000a0f0, 0x441e441f}, - {0x0000a0f4, 0x55015502}, - {0x0000a0f8, 0x551f5500}, - {0x0000a0fc, 0x6602551e}, - {0x0000a100, 0x66006601}, - {0x0000a104, 0x661e661f}, - {0x0000a108, 0x7703661d}, - {0x0000a10c, 0x77017702}, - {0x0000a110, 0x00007700}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x111f1100}, - {0x0000a148, 0x111d111e}, - {0x0000a14c, 0x111b111c}, - {0x0000a150, 0x22032204}, - {0x0000a154, 0x22012202}, - {0x0000a158, 0x221f2200}, - {0x0000a15c, 0x221d221e}, - {0x0000a160, 0x33013302}, - {0x0000a164, 0x331f3300}, - {0x0000a168, 0x4402331e}, - {0x0000a16c, 0x44004401}, - {0x0000a170, 0x441e441f}, - {0x0000a174, 0x55015502}, - {0x0000a178, 0x551f5500}, - {0x0000a17c, 0x6602551e}, - {0x0000a180, 0x66006601}, - {0x0000a184, 0x661e661f}, - {0x0000a188, 0x7703661d}, - {0x0000a18c, 0x77017702}, - {0x0000a190, 0x00007700}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000296}, -}; - -static const u32 ar9485Modes_high_power_tx_gain_1_0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, - {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, - {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, - {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, - {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, - {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, - {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, - {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, - {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, - {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, - {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, - {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, - {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, - {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, - {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, - {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, - {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, - {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, - {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, - {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, - {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, - {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, - {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, - {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, - {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, - {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, - {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, -}; - -static const u32 ar9485_1_0[][2] = { - /* Addr allmodes */ - {0x0000a580, 0x00000000}, - {0x0000a584, 0x00000000}, - {0x0000a588, 0x00000000}, - {0x0000a58c, 0x00000000}, - {0x0000a590, 0x00000000}, - {0x0000a594, 0x00000000}, - {0x0000a598, 0x00000000}, - {0x0000a59c, 0x00000000}, - {0x0000a5a0, 0x00000000}, - {0x0000a5a4, 0x00000000}, - {0x0000a5a8, 0x00000000}, - {0x0000a5ac, 0x00000000}, - {0x0000a5b0, 0x00000000}, - {0x0000a5b4, 0x00000000}, - {0x0000a5b8, 0x00000000}, - {0x0000a5bc, 0x00000000}, -}; - -static const u32 ar9485_1_0_radio_core[][2] = { - /* Addr allmodes */ - {0x00016000, 0x36db6db6}, - {0x00016004, 0x6db6db40}, - {0x00016008, 0x73800000}, - {0x0001600c, 0x00000000}, - {0x00016040, 0x7f80fff8}, - {0x00016048, 0x6c92426e}, - {0x0001604c, 0x000f0278}, - {0x00016050, 0x6db6db6c}, - {0x00016054, 0x6db60000}, - {0x00016080, 0x00080000}, - {0x00016084, 0x0e48048c}, - {0x00016088, 0x14214514}, - {0x0001608c, 0x119f081e}, - {0x00016090, 0x24926490}, - {0x00016098, 0xd28b3330}, - {0x000160a0, 0xc2108ffe}, - {0x000160a4, 0x812fc370}, - {0x000160a8, 0x423c8000}, - {0x000160b4, 0x92480040}, - {0x000160c0, 0x006db6db}, - {0x000160c4, 0x0186db60}, - {0x000160c8, 0x6db6db6c}, - {0x000160cc, 0x6de6fbe0}, - {0x000160d0, 0xf7dfcf3c}, - {0x00016100, 0x04cb0001}, - {0x00016104, 0xfff80015}, - {0x00016108, 0x00080010}, - {0x00016144, 0x01884080}, - {0x00016148, 0x00008040}, - {0x00016180, 0x08453333}, - {0x00016184, 0x18e82f01}, - {0x00016188, 0x00000000}, - {0x0001618c, 0x00000000}, - {0x00016240, 0x08400000}, - {0x00016244, 0x1bf90f00}, - {0x00016248, 0x00000000}, - {0x0001624c, 0x00000000}, - {0x00016280, 0x01000015}, - {0x00016284, 0x00d30000}, - {0x00016288, 0x00318000}, - {0x0001628c, 0x50000000}, - {0x00016290, 0x4b96210f}, - {0x00016380, 0x00000000}, - {0x00016384, 0x00000000}, - {0x00016388, 0x00800700}, - {0x0001638c, 0x00800700}, - {0x00016390, 0x00800700}, - {0x00016394, 0x00000000}, - {0x00016398, 0x00000000}, - {0x0001639c, 0x00000000}, - {0x000163a0, 0x00000001}, - {0x000163a4, 0x00000001}, - {0x000163a8, 0x00000000}, - {0x000163ac, 0x00000000}, - {0x000163b0, 0x00000000}, - {0x000163b4, 0x00000000}, - {0x000163b8, 0x00000000}, - {0x000163bc, 0x00000000}, - {0x000163c0, 0x000000a0}, - {0x000163c4, 0x000c0000}, - {0x000163c8, 0x14021402}, - {0x000163cc, 0x00001402}, - {0x000163d0, 0x00000000}, - {0x000163d4, 0x00000000}, - {0x00016c40, 0x1319c178}, - {0x00016c44, 0x10000000}, -}; - -static const u32 ar9485Modes_lowest_ob_db_tx_gain_1_0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, - {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, - {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, - {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, - {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, - {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, - {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, - {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, - {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, - {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, - {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, - {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, - {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, - {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, - {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, - {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, - {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, - {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, - {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, - {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, - {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, - {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, - {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, - {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, - {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, - {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, - {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, -}; - -static const u32 ar9485_1_0_baseband_core[][2] = { - /* Addr allmodes */ - {0x00009800, 0xafe68e30}, - {0x00009804, 0xfd14e000}, - {0x00009808, 0x9c0a8f6b}, - {0x0000980c, 0x04800000}, - {0x00009814, 0x9280c00a}, - {0x00009818, 0x00000000}, - {0x0000981c, 0x00020028}, - {0x00009834, 0x5f3ca3de}, - {0x00009838, 0x0108ecff}, - {0x0000983c, 0x14750600}, - {0x00009880, 0x201fff00}, - {0x00009884, 0x00001042}, - {0x000098a4, 0x00200400}, - {0x000098b0, 0x52440bbe}, - {0x000098bc, 0x00000002}, - {0x000098d0, 0x004b6a8e}, - {0x000098d4, 0x00000820}, - {0x000098dc, 0x00000000}, - {0x000098f0, 0x00000000}, - {0x000098f4, 0x00000000}, - {0x00009c04, 0x00000000}, - {0x00009c08, 0x03200000}, - {0x00009c0c, 0x00000000}, - {0x00009c10, 0x00000000}, - {0x00009c14, 0x00046384}, - {0x00009c18, 0x05b6b440}, - {0x00009c1c, 0x00b6b440}, - {0x00009d00, 0xc080a333}, - {0x00009d04, 0x40206c10}, - {0x00009d08, 0x009c4060}, - {0x00009d0c, 0x1883800a}, - {0x00009d10, 0x01834061}, - {0x00009d14, 0x00c00400}, - {0x00009d18, 0x00000000}, - {0x00009d1c, 0x00000000}, - {0x00009e08, 0x0038233c}, - {0x00009e24, 0x990bb515}, - {0x00009e28, 0x0a6f0000}, - {0x00009e30, 0x06336f77}, - {0x00009e34, 0x6af6532f}, - {0x00009e38, 0x0cc80c00}, - {0x00009e40, 0x0d261820}, - {0x00009e4c, 0x00001004}, - {0x00009e50, 0x00ff03f1}, - {0x00009fc0, 0x80be4788}, - {0x00009fc4, 0x0001efb5}, - {0x00009fcc, 0x40000014}, - {0x0000a20c, 0x00000000}, - {0x0000a210, 0x00000000}, - {0x0000a220, 0x00000000}, - {0x0000a224, 0x00000000}, - {0x0000a228, 0x10002310}, - {0x0000a23c, 0x00000000}, - {0x0000a244, 0x0c000000}, - {0x0000a2a0, 0x00000001}, - {0x0000a2c0, 0x00000001}, - {0x0000a2c8, 0x00000000}, - {0x0000a2cc, 0x18c43433}, - {0x0000a2d4, 0x00000000}, - {0x0000a2dc, 0x00000000}, - {0x0000a2e0, 0x00000000}, - {0x0000a2e4, 0x00000000}, - {0x0000a2e8, 0x00000000}, - {0x0000a2ec, 0x00000000}, - {0x0000a2f0, 0x00000000}, - {0x0000a2f4, 0x00000000}, - {0x0000a2f8, 0x00000000}, - {0x0000a344, 0x00000000}, - {0x0000a34c, 0x00000000}, - {0x0000a350, 0x0000a000}, - {0x0000a364, 0x00000000}, - {0x0000a370, 0x00000000}, - {0x0000a390, 0x00000001}, - {0x0000a394, 0x00000444}, - {0x0000a398, 0x001f0e0f}, - {0x0000a39c, 0x0075393f}, - {0x0000a3a0, 0xb79f6427}, - {0x0000a3a4, 0x00000000}, - {0x0000a3a8, 0xaaaaaaaa}, - {0x0000a3ac, 0x3c466478}, - {0x0000a3c0, 0x20202020}, - {0x0000a3c4, 0x22222220}, - {0x0000a3c8, 0x20200020}, - {0x0000a3cc, 0x20202020}, - {0x0000a3d0, 0x20202020}, - {0x0000a3d4, 0x20202020}, - {0x0000a3d8, 0x20202020}, - {0x0000a3dc, 0x20202020}, - {0x0000a3e0, 0x20202020}, - {0x0000a3e4, 0x20202020}, - {0x0000a3e8, 0x20202020}, - {0x0000a3ec, 0x20202020}, - {0x0000a3f0, 0x00000000}, - {0x0000a3f4, 0x00000006}, - {0x0000a3f8, 0x0cdbd380}, - {0x0000a3fc, 0x000f0f01}, - {0x0000a400, 0x8fa91f01}, - {0x0000a404, 0x00000000}, - {0x0000a408, 0x0e79e5c6}, - {0x0000a40c, 0x00820820}, - {0x0000a414, 0x1ce739ce}, - {0x0000a418, 0x2d0011ce}, - {0x0000a41c, 0x1ce739ce}, - {0x0000a420, 0x000001ce}, - {0x0000a424, 0x1ce739ce}, - {0x0000a428, 0x000001ce}, - {0x0000a42c, 0x1ce739ce}, - {0x0000a430, 0x1ce739ce}, - {0x0000a434, 0x00000000}, - {0x0000a438, 0x00001801}, - {0x0000a43c, 0x00000000}, - {0x0000a440, 0x00000000}, - {0x0000a444, 0x00000000}, - {0x0000a448, 0x04000000}, - {0x0000a44c, 0x00000001}, - {0x0000a450, 0x00010000}, - {0x0000a458, 0x00000000}, - {0x0000a5c4, 0x3fad9d74}, - {0x0000a5c8, 0x0048060a}, - {0x0000a5cc, 0x00000637}, - {0x0000a760, 0x03020100}, - {0x0000a764, 0x09080504}, - {0x0000a768, 0x0d0c0b0a}, - {0x0000a76c, 0x13121110}, - {0x0000a770, 0x31301514}, - {0x0000a774, 0x35343332}, - {0x0000a778, 0x00000036}, - {0x0000a780, 0x00000838}, - {0x0000a7c0, 0x00000000}, - {0x0000a7c4, 0xfffffffc}, - {0x0000a7c8, 0x00000000}, - {0x0000a7cc, 0x00000000}, - {0x0000a7d0, 0x00000000}, - {0x0000a7d4, 0x00000004}, - {0x0000a7dc, 0x00000001}, -}; - -static const u32 ar9485Modes_high_ob_db_tx_gain_1_0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, - {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, - {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, - {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, - {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, - {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, - {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, - {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, - {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, - {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, - {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, - {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, - {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, - {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, - {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, - {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, - {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, - {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, - {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, - {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, - {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, - {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, - {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, - {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, - {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, - {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, - {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, -}; - -static const u32 ar9485Common_rx_gain_1_0[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x01800082}, - {0x0000a014, 0x01820181}, - {0x0000a018, 0x01840183}, - {0x0000a01c, 0x01880185}, - {0x0000a020, 0x018a0189}, - {0x0000a024, 0x02850284}, - {0x0000a028, 0x02890288}, - {0x0000a02c, 0x03850384}, - {0x0000a030, 0x03890388}, - {0x0000a034, 0x038b038a}, - {0x0000a038, 0x038d038c}, - {0x0000a03c, 0x03910390}, - {0x0000a040, 0x03930392}, - {0x0000a044, 0x03950394}, - {0x0000a048, 0x00000396}, - {0x0000a04c, 0x00000000}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x28282828}, - {0x0000a084, 0x28282828}, - {0x0000a088, 0x28282828}, - {0x0000a08c, 0x28282828}, - {0x0000a090, 0x28282828}, - {0x0000a094, 0x21212128}, - {0x0000a098, 0x171c1c1c}, - {0x0000a09c, 0x02020212}, - {0x0000a0a0, 0x00000202}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x111f1100}, - {0x0000a0c8, 0x111d111e}, - {0x0000a0cc, 0x111b111c}, - {0x0000a0d0, 0x22032204}, - {0x0000a0d4, 0x22012202}, - {0x0000a0d8, 0x221f2200}, - {0x0000a0dc, 0x221d221e}, - {0x0000a0e0, 0x33013302}, - {0x0000a0e4, 0x331f3300}, - {0x0000a0e8, 0x4402331e}, - {0x0000a0ec, 0x44004401}, - {0x0000a0f0, 0x441e441f}, - {0x0000a0f4, 0x55015502}, - {0x0000a0f8, 0x551f5500}, - {0x0000a0fc, 0x6602551e}, - {0x0000a100, 0x66006601}, - {0x0000a104, 0x661e661f}, - {0x0000a108, 0x7703661d}, - {0x0000a10c, 0x77017702}, - {0x0000a110, 0x00007700}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x111f1100}, - {0x0000a148, 0x111d111e}, - {0x0000a14c, 0x111b111c}, - {0x0000a150, 0x22032204}, - {0x0000a154, 0x22012202}, - {0x0000a158, 0x221f2200}, - {0x0000a15c, 0x221d221e}, - {0x0000a160, 0x33013302}, - {0x0000a164, 0x331f3300}, - {0x0000a168, 0x4402331e}, - {0x0000a16c, 0x44004401}, - {0x0000a170, 0x441e441f}, - {0x0000a174, 0x55015502}, - {0x0000a178, 0x551f5500}, - {0x0000a17c, 0x6602551e}, - {0x0000a180, 0x66006601}, - {0x0000a184, 0x661e661f}, - {0x0000a188, 0x7703661d}, - {0x0000a18c, 0x77017702}, - {0x0000a190, 0x00007700}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000296}, -}; - -static const u32 ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1[][2] = { - /* Addr allmodes */ - {0x00018c00, 0x10252e5e}, - {0x00018c04, 0x000801d8}, - {0x00018c08, 0x0000580c}, -}; - -static const u32 ar9485_1_0_pcie_phy_clkreq_enable_L1[][2] = { - /* Addr allmodes */ - {0x00018c00, 0x10253e5e}, - {0x00018c04, 0x000801d8}, - {0x00018c08, 0x0000580c}, -}; - -static const u32 ar9485_1_0_soc_preamble[][2] = { - /* Addr allmodes */ - {0x00004090, 0x00aa10aa}, - {0x000040a4, 0x00a0c9c9}, - {0x00007048, 0x00000004}, -}; - -static const u32 ar9485_fast_clock_1_0_baseband_postamble[][3] = { - /* Addr 5G_HT20 5G_HT40 */ - {0x00009e00, 0x03721821, 0x03721821}, - {0x0000a230, 0x0000400b, 0x00004016}, - {0x0000a254, 0x00000898, 0x00001130}, -}; - -static const u32 ar9485_1_0_baseband_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, - {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e}, - {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, - {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, - {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, - {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044}, - {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, - {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020}, - {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, - {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e}, - {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, - {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, - {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, - {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, - {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, - {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, - {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, - {0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0}, - {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, - {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, - {0x0000a234, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff}, - {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, - {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, - {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, - {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, - {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, - {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501}, - {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, - {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0}, - {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, - {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, - {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, - {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000be04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, - {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -}; - -static const u32 ar9485Modes_low_ob_db_tx_gain_1_0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, - {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, - {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, - {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, - {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, - {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, - {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, - {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, - {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, - {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, - {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, - {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, - {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, - {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, - {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, - {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, - {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, - {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, - {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, - {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, - {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, - {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, - {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, - {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, - {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, - {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, - {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, - {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, -}; - -static const u32 ar9485_1_0_pcie_phy_clkreq_disable_L1[][2] = { - /* Addr allmodes */ - {0x00018c00, 0x10213e5e}, - {0x00018c04, 0x000801d8}, - {0x00018c08, 0x0000580c}, -}; - -static const u32 ar9485_1_0_radio_postamble[][2] = { - /* Addr allmodes */ - {0x0001609c, 0x0b283f31}, - {0x000160ac, 0x24611800}, - {0x000160b0, 0x03284f3e}, - {0x0001610c, 0x00170000}, - {0x00016140, 0x10804008}, -}; - -static const u32 ar9485_1_0_mac_core[][2] = { - /* Addr allmodes */ - {0x00000008, 0x00000000}, - {0x00000030, 0x00020085}, - {0x00000034, 0x00000005}, - {0x00000040, 0x00000000}, - {0x00000044, 0x00000000}, - {0x00000048, 0x00000008}, - {0x0000004c, 0x00000010}, - {0x00000050, 0x00000000}, - {0x00001040, 0x002ffc0f}, - {0x00001044, 0x002ffc0f}, - {0x00001048, 0x002ffc0f}, - {0x0000104c, 0x002ffc0f}, - {0x00001050, 0x002ffc0f}, - {0x00001054, 0x002ffc0f}, - {0x00001058, 0x002ffc0f}, - {0x0000105c, 0x002ffc0f}, - {0x00001060, 0x002ffc0f}, - {0x00001064, 0x002ffc0f}, - {0x000010f0, 0x00000100}, - {0x00001270, 0x00000000}, - {0x000012b0, 0x00000000}, - {0x000012f0, 0x00000000}, - {0x0000143c, 0x00000000}, - {0x0000147c, 0x00000000}, - {0x00008000, 0x00000000}, - {0x00008004, 0x00000000}, - {0x00008008, 0x00000000}, - {0x0000800c, 0x00000000}, - {0x00008018, 0x00000000}, - {0x00008020, 0x00000000}, - {0x00008038, 0x00000000}, - {0x0000803c, 0x00000000}, - {0x00008040, 0x00000000}, - {0x00008044, 0x00000000}, - {0x00008048, 0x00000000}, - {0x0000804c, 0xffffffff}, - {0x00008054, 0x00000000}, - {0x00008058, 0x00000000}, - {0x0000805c, 0x000fc78f}, - {0x00008060, 0x0000000f}, - {0x00008064, 0x00000000}, - {0x00008070, 0x00000310}, - {0x00008074, 0x00000020}, - {0x00008078, 0x00000000}, - {0x0000809c, 0x0000000f}, - {0x000080a0, 0x00000000}, - {0x000080a4, 0x02ff0000}, - {0x000080a8, 0x0e070605}, - {0x000080ac, 0x0000000d}, - {0x000080b0, 0x00000000}, - {0x000080b4, 0x00000000}, - {0x000080b8, 0x00000000}, - {0x000080bc, 0x00000000}, - {0x000080c0, 0x2a800000}, - {0x000080c4, 0x06900168}, - {0x000080c8, 0x13881c20}, - {0x000080cc, 0x01f40000}, - {0x000080d0, 0x00252500}, - {0x000080d4, 0x00a00000}, - {0x000080d8, 0x00400000}, - {0x000080dc, 0x00000000}, - {0x000080e0, 0xffffffff}, - {0x000080e4, 0x0000ffff}, - {0x000080e8, 0x3f3f3f3f}, - {0x000080ec, 0x00000000}, - {0x000080f0, 0x00000000}, - {0x000080f4, 0x00000000}, - {0x000080fc, 0x00020000}, - {0x00008100, 0x00000000}, - {0x00008108, 0x00000052}, - {0x0000810c, 0x00000000}, - {0x00008110, 0x00000000}, - {0x00008114, 0x000007ff}, - {0x00008118, 0x000000aa}, - {0x0000811c, 0x00003210}, - {0x00008124, 0x00000000}, - {0x00008128, 0x00000000}, - {0x0000812c, 0x00000000}, - {0x00008130, 0x00000000}, - {0x00008134, 0x00000000}, - {0x00008138, 0x00000000}, - {0x0000813c, 0x0000ffff}, - {0x00008144, 0xffffffff}, - {0x00008168, 0x00000000}, - {0x0000816c, 0x00000000}, - {0x00008170, 0x18486200}, - {0x00008174, 0x33332210}, - {0x00008178, 0x00000000}, - {0x0000817c, 0x00020000}, - {0x000081c0, 0x00000000}, - {0x000081c4, 0x33332210}, - {0x000081c8, 0x00000000}, - {0x000081cc, 0x00000000}, - {0x000081d4, 0x00000000}, - {0x000081ec, 0x00000000}, - {0x000081f0, 0x00000000}, - {0x000081f4, 0x00000000}, - {0x000081f8, 0x00000000}, - {0x000081fc, 0x00000000}, - {0x00008240, 0x00100000}, - {0x00008244, 0x0010f400}, - {0x00008248, 0x00000800}, - {0x0000824c, 0x0001e800}, - {0x00008250, 0x00000000}, - {0x00008254, 0x00000000}, - {0x00008258, 0x00000000}, - {0x0000825c, 0x40000000}, - {0x00008260, 0x00080922}, - {0x00008264, 0x9ca00010}, - {0x00008268, 0xffffffff}, - {0x0000826c, 0x0000ffff}, - {0x00008270, 0x00000000}, - {0x00008274, 0x40000000}, - {0x00008278, 0x003e4180}, - {0x0000827c, 0x00000004}, - {0x00008284, 0x0000002c}, - {0x00008288, 0x0000002c}, - {0x0000828c, 0x000000ff}, - {0x00008294, 0x00000000}, - {0x00008298, 0x00000000}, - {0x0000829c, 0x00000000}, - {0x00008300, 0x00000140}, - {0x00008314, 0x00000000}, - {0x0000831c, 0x0000010d}, - {0x00008328, 0x00000000}, - {0x0000832c, 0x00000007}, - {0x00008330, 0x00000302}, - {0x00008334, 0x00000700}, - {0x00008338, 0x00ff0000}, - {0x0000833c, 0x02400000}, - {0x00008340, 0x000107ff}, - {0x00008344, 0xa248105b}, - {0x00008348, 0x008f0000}, - {0x0000835c, 0x00000000}, - {0x00008360, 0xffffffff}, - {0x00008364, 0xffffffff}, - {0x00008368, 0x00000000}, - {0x00008370, 0x00000000}, - {0x00008374, 0x000000ff}, - {0x00008378, 0x00000000}, - {0x0000837c, 0x00000000}, - {0x00008380, 0xffffffff}, - {0x00008384, 0xffffffff}, - {0x00008390, 0xffffffff}, - {0x00008394, 0xffffffff}, - {0x00008398, 0x00000000}, - {0x0000839c, 0x00000000}, - {0x000083a0, 0x00000000}, - {0x000083a4, 0x0000fa14}, - {0x000083a8, 0x000f0c00}, - {0x000083ac, 0x33332210}, - {0x000083b0, 0x33332210}, - {0x000083b4, 0x33332210}, - {0x000083b8, 0x33332210}, - {0x000083bc, 0x00000000}, - {0x000083c0, 0x00000000}, - {0x000083c4, 0x00000000}, - {0x000083c8, 0x00000000}, - {0x000083cc, 0x00000200}, - {0x000083d0, 0x000301ff}, -}; - static const u32 ar9485_1_1_mac_core[][2] = { /* Addr allmodes */ {0x00000008, 0x00000000}, -- cgit v1.2.3-58-ga151 From 5e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4e Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Mon, 21 Mar 2011 18:00:50 -0700 Subject: wireless: mwifiex: initial commit for Marvell mwifiex driver This driver adds WiFi support for Marvell 802.11n based chipsets with SDIO interface. Currently only SD8787 is supported. More chipsets will be supported later. drivers/net/wireless/mwifiex/ Signed-off-by: Nishant Sarmukadam Signed-off-by: Amitkumar Karwar Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: Yogesh Ashok Powar Signed-off-by: Marc Yang Signed-off-by: Ramesh Radhakrishnan Signed-off-by: Frank Huang Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/Makefile | 2 + drivers/net/wireless/mwifiex/11n.c | 922 ++++++++ drivers/net/wireless/mwifiex/11n.h | 178 ++ drivers/net/wireless/mwifiex/11n_aggr.c | 423 ++++ drivers/net/wireless/mwifiex/11n_aggr.h | 32 + drivers/net/wireless/mwifiex/11n_rxreorder.c | 637 ++++++ drivers/net/wireless/mwifiex/11n_rxreorder.h | 67 + drivers/net/wireless/mwifiex/Kconfig | 21 + drivers/net/wireless/mwifiex/Makefile | 41 + drivers/net/wireless/mwifiex/README | 204 ++ drivers/net/wireless/mwifiex/cfg80211.c | 1517 +++++++++++++ drivers/net/wireless/mwifiex/cfg80211.h | 31 + drivers/net/wireless/mwifiex/cfp.c | 368 +++ drivers/net/wireless/mwifiex/cmdevt.c | 1463 ++++++++++++ drivers/net/wireless/mwifiex/debugfs.c | 773 +++++++ drivers/net/wireless/mwifiex/decl.h | 177 ++ drivers/net/wireless/mwifiex/fw.h | 1376 ++++++++++++ drivers/net/wireless/mwifiex/init.c | 665 ++++++ drivers/net/wireless/mwifiex/ioctl.h | 433 ++++ drivers/net/wireless/mwifiex/join.c | 1464 ++++++++++++ drivers/net/wireless/mwifiex/main.c | 1102 +++++++++ drivers/net/wireless/mwifiex/main.h | 1081 +++++++++ drivers/net/wireless/mwifiex/scan.c | 3098 ++++++++++++++++++++++++++ drivers/net/wireless/mwifiex/sdio.c | 1770 +++++++++++++++ drivers/net/wireless/mwifiex/sdio.h | 305 +++ drivers/net/wireless/mwifiex/sta_cmd.c | 1226 ++++++++++ drivers/net/wireless/mwifiex/sta_cmdresp.c | 986 ++++++++ drivers/net/wireless/mwifiex/sta_event.c | 405 ++++ drivers/net/wireless/mwifiex/sta_ioctl.c | 2478 ++++++++++++++++++++ drivers/net/wireless/mwifiex/sta_rx.c | 182 ++ drivers/net/wireless/mwifiex/sta_tx.c | 202 ++ drivers/net/wireless/mwifiex/txrx.c | 202 ++ drivers/net/wireless/mwifiex/util.c | 252 +++ drivers/net/wireless/mwifiex/util.h | 32 + drivers/net/wireless/mwifiex/wmm.c | 1237 ++++++++++ drivers/net/wireless/mwifiex/wmm.h | 112 + 37 files changed, 25465 insertions(+) create mode 100644 drivers/net/wireless/mwifiex/11n.c create mode 100644 drivers/net/wireless/mwifiex/11n.h create mode 100644 drivers/net/wireless/mwifiex/11n_aggr.c create mode 100644 drivers/net/wireless/mwifiex/11n_aggr.h create mode 100644 drivers/net/wireless/mwifiex/11n_rxreorder.c create mode 100644 drivers/net/wireless/mwifiex/11n_rxreorder.h create mode 100644 drivers/net/wireless/mwifiex/Kconfig create mode 100644 drivers/net/wireless/mwifiex/Makefile create mode 100644 drivers/net/wireless/mwifiex/README create mode 100644 drivers/net/wireless/mwifiex/cfg80211.c create mode 100644 drivers/net/wireless/mwifiex/cfg80211.h create mode 100644 drivers/net/wireless/mwifiex/cfp.c create mode 100644 drivers/net/wireless/mwifiex/cmdevt.c create mode 100644 drivers/net/wireless/mwifiex/debugfs.c create mode 100644 drivers/net/wireless/mwifiex/decl.h create mode 100644 drivers/net/wireless/mwifiex/fw.h create mode 100644 drivers/net/wireless/mwifiex/init.c create mode 100644 drivers/net/wireless/mwifiex/ioctl.h create mode 100644 drivers/net/wireless/mwifiex/join.c create mode 100644 drivers/net/wireless/mwifiex/main.c create mode 100644 drivers/net/wireless/mwifiex/main.h create mode 100644 drivers/net/wireless/mwifiex/scan.c create mode 100644 drivers/net/wireless/mwifiex/sdio.c create mode 100644 drivers/net/wireless/mwifiex/sdio.h create mode 100644 drivers/net/wireless/mwifiex/sta_cmd.c create mode 100644 drivers/net/wireless/mwifiex/sta_cmdresp.c create mode 100644 drivers/net/wireless/mwifiex/sta_event.c create mode 100644 drivers/net/wireless/mwifiex/sta_ioctl.c create mode 100644 drivers/net/wireless/mwifiex/sta_rx.c create mode 100644 drivers/net/wireless/mwifiex/sta_tx.c create mode 100644 drivers/net/wireless/mwifiex/txrx.c create mode 100644 drivers/net/wireless/mwifiex/util.c create mode 100644 drivers/net/wireless/mwifiex/util.h create mode 100644 drivers/net/wireless/mwifiex/wmm.c create mode 100644 drivers/net/wireless/mwifiex/wmm.h diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 7aeb113cbb90..f354bd4e121e 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -284,5 +284,6 @@ source "drivers/net/wireless/rtlwifi/Kconfig" source "drivers/net/wireless/wl1251/Kconfig" source "drivers/net/wireless/wl12xx/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" +source "drivers/net/wireless/mwifiex/Kconfig" endif # WLAN diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index ddd3fb6ba1d3..7bba6a82b875 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -56,3 +56,5 @@ obj-$(CONFIG_WL12XX) += wl12xx/ obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/ obj-$(CONFIG_IWM) += iwmc3200wifi/ + +obj-$(CONFIG_MWIFIEX) += mwifiex/ diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c new file mode 100644 index 000000000000..0e04a21be0a3 --- /dev/null +++ b/drivers/net/wireless/mwifiex/11n.c @@ -0,0 +1,922 @@ +/* + * Marvell Wireless LAN device driver: 802.11n + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" + +/* + * Fills HT capability information field, AMPDU Parameters field, HT extended + * capability field, and supported MCS set fields. + * + * Only the following HT capability information fields are used, all other + * fields are always turned off. + * + * Bit 1 : Supported channel width (0: 20MHz, 1: Both 20 and 40 MHz) + * Bit 4 : Greenfield support (0: Not supported, 1: Supported) + * Bit 5 : Short GI for 20 MHz support (0: Not supported, 1: Supported) + * Bit 6 : Short GI for 40 MHz support (0: Not supported, 1: Supported) + * Bit 7 : Tx STBC (0: Not supported, 1: Supported) + * Bit 8-9 : Rx STBC (0: Not supported, X: Support for up to X spatial streams) + * Bit 10 : Delayed BA support (0: Not supported, 1: Supported) + * Bit 11 : Maximum AMSDU length (0: 3839 octets, 1: 7935 octets) + * Bit 14 : 40-Mhz intolerant support (0: Not supported, 1: Supported) + * + * In addition, the following AMPDU Parameters are set - + * - Maximum AMPDU length exponent (set to 3) + * - Minimum AMPDU start spacing (set to 0 - No restrictions) + * + * MCS is set for 1x1, with MSC32 for infra mode or ad-hoc mode with 40 MHz + * support. + * + * RD responder bit to set to clear in the extended capability header. + */ +void +mwifiex_fill_cap_info(struct mwifiex_private *priv, + struct mwifiex_ie_types_htcap *ht_cap) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u8 *mcs; + int rx_mcs_supp; + uint16_t ht_cap_info = le16_to_cpu(ht_cap->ht_cap.cap_info); + uint16_t ht_ext_cap = le16_to_cpu(ht_cap->ht_cap.extended_ht_cap_info); + + if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap) && + ISSUPP_CHANWIDTH40(adapter->usr_dot_11n_dev_cap)) + SETHT_SUPPCHANWIDTH(ht_cap_info); + else + RESETHT_SUPPCHANWIDTH(ht_cap_info); + + if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap) && + ISSUPP_GREENFIELD(adapter->usr_dot_11n_dev_cap)) + SETHT_GREENFIELD(ht_cap_info); + else + RESETHT_GREENFIELD(ht_cap_info); + + if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap) && + ISSUPP_SHORTGI20(adapter->usr_dot_11n_dev_cap)) + SETHT_SHORTGI20(ht_cap_info); + else + RESETHT_SHORTGI20(ht_cap_info); + + if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap) && + ISSUPP_SHORTGI40(adapter->usr_dot_11n_dev_cap)) + SETHT_SHORTGI40(ht_cap_info); + else + RESETHT_SHORTGI40(ht_cap_info); + + /* No user config for RX STBC yet */ + if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap) + && ISSUPP_RXSTBC(adapter->usr_dot_11n_dev_cap)) + SETHT_RXSTBC(ht_cap_info, 1); + else + RESETHT_RXSTBC(ht_cap_info); + + /* No user config for TX STBC yet */ + if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) + SETHT_TXSTBC(ht_cap_info); + else + RESETHT_TXSTBC(ht_cap_info); + + /* No user config for Delayed BACK yet */ + if (GET_DELAYEDBACK(adapter->hw_dot_11n_dev_cap)) + SETHT_DELAYEDBACK(ht_cap_info); + else + RESETHT_DELAYEDBACK(ht_cap_info); + + if (ISENABLED_40MHZ_INTOLARENT(adapter->usr_dot_11n_dev_cap)) + SETHT_40MHZ_INTOLARANT(ht_cap_info); + else + RESETHT_40MHZ_INTOLARANT(ht_cap_info); + + SETAMPDU_SIZE(ht_cap->ht_cap.ampdu_params_info, AMPDU_FACTOR_64K); + SETAMPDU_SPACING(ht_cap->ht_cap.ampdu_params_info, 0); + + /* Need change to support 8k AMSDU receive */ + RESETHT_MAXAMSDU(ht_cap_info); + + rx_mcs_supp = GET_RXMCSSUPP(adapter->hw_dev_mcs_support); + + mcs = (u8 *)&ht_cap->ht_cap.mcs; + + /* Set MCS for 1x1 */ + memset(mcs, 0xff, rx_mcs_supp); + + /* Clear all the other values */ + memset(&mcs[rx_mcs_supp], 0, + sizeof(struct ieee80211_mcs_info) - rx_mcs_supp); + + if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA || + (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap) && + ISSUPP_CHANWIDTH40(adapter->usr_dot_11n_dev_cap))) + /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ + SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); + + /* Clear RD responder bit */ + RESETHT_EXTCAP_RDG(ht_ext_cap); + + ht_cap->ht_cap.cap_info = cpu_to_le16(ht_cap_info); + ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap); +} + +/* + * Shows HT capability information fields. + * + * The following HT capability information fields are supported. + * - Maximum AMSDU length (3839 bytes or 7935 bytes) + * - Beam forming support + * - Greenfield preamble support + * - AMPDU support + * - MIMO Power Save support + * - Rx STBC support + * - Tx STBC support + * - Short GI for 20 MHz support + * - Short GI for 40 MHz support + * - LDPC coded packets receive support + * - Number of delayed BA streams + * - Number of immediate BA streams + * - 10 MHz channel width support + * - 20 MHz channel width support + * - 40 MHz channel width support + * - Presence of Tx antenna A/B/C/D + * - Presence of Rx antenna A/B/C/D + */ +void +mwifiex_show_dot_11n_dev_cap(struct mwifiex_adapter *adapter, u32 cap) +{ + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Max MSDU len = %s octets\n", + (ISSUPP_MAXAMSDU(cap) ? "7935" : "3839")); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Beam forming %s\n", + (ISSUPP_BEAMFORMING(cap) ? "supported" : "not supported")); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Greenfield preamble %s\n", + (ISSUPP_GREENFIELD(cap) ? "supported" : "not supported")); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: AMPDU %s\n", + (ISSUPP_AMPDU(cap) ? "supported" : "not supported")); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: MIMO Power Save %s\n", + (ISSUPP_MIMOPS(cap) ? "supported" : "not supported")); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Rx STBC %s\n", + (ISSUPP_RXSTBC(cap) ? "supported" : "not supported")); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Tx STBC %s\n", + (ISSUPP_TXSTBC(cap) ? "supported" : "not supported")); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Short GI for 40 Mhz %s\n", + (ISSUPP_SHORTGI40(cap) ? "supported" : "not supported")); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Short GI for 20 Mhz %s\n", + (ISSUPP_SHORTGI20(cap) ? "supported" : "not supported")); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: LDPC coded packet receive %s\n", + (ISSUPP_RXLDPC(cap) ? "supported" : "not supported")); + dev_dbg(adapter->dev, + "info: GET_HW_SPEC: Number of Delayed Block Ack streams = %d\n", + GET_DELAYEDBACK(cap)); + dev_dbg(adapter->dev, + "info: GET_HW_SPEC: Number of Immediate Block Ack streams = %d\n", + GET_IMMEDIATEBACK(cap)); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: 40 Mhz channel width %s\n", + (ISSUPP_CHANWIDTH40(cap) ? "supported" : "not supported")); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: 20 Mhz channel width %s\n", + (ISSUPP_CHANWIDTH20(cap) ? "supported" : "not supported")); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: 10 Mhz channel width %s\n", + (ISSUPP_CHANWIDTH10(cap) ? "supported" : "not supported")); + + if (ISSUPP_RXANTENNAA(cap)) + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Rx antennea A\n"); + + if (ISSUPP_RXANTENNAB(cap)) + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Rx antennea B\n"); + + if (ISSUPP_RXANTENNAC(cap)) + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Rx antennea C\n"); + + if (ISSUPP_RXANTENNAD(cap)) + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Rx antennea D\n"); + + if (ISSUPP_TXANTENNAA(cap)) + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Tx antennea A\n"); + + if (ISSUPP_TXANTENNAB(cap)) + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Tx antennea B\n"); + + if (ISSUPP_TXANTENNAC(cap)) + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Tx antennea C\n"); + + if (ISSUPP_TXANTENNAD(cap)) + dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Tx antennea D\n"); + + return; +} + +/* + * Shows HT MCS support field. + */ +void +mwifiex_show_dev_mcs_support(struct mwifiex_adapter *adapter, u8 support) +{ + dev_dbg(adapter->dev, "info: GET_HW_SPEC: MCSs for %dx%d MIMO\n", + GET_RXMCSSUPP(support), GET_TXMCSSUPP(support)); + return; +} + +/* + * This function returns the pointer to an entry in BA Stream + * table which matches the requested BA status. + */ +static struct mwifiex_tx_ba_stream_tbl * +mwifiex_11n_get_tx_ba_stream_status(struct mwifiex_private *priv, + enum mwifiex_ba_status ba_status) +{ + struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; + unsigned long flags; + + spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); + list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { + if (tx_ba_tsr_tbl->ba_status == ba_status) { + spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, + flags); + return tx_ba_tsr_tbl; + } + } + spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); + return NULL; +} + +/* + * This function handles the command response of delete a block + * ack request. + * + * The function checks the response success status and takes action + * accordingly (send an add BA request in case of success, or recreate + * the deleted stream in case of failure, if the add BA was also + * initiated by us). + */ +int mwifiex_ret_11n_delba(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + int tid; + struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; + struct host_cmd_ds_11n_delba *del_ba = + (struct host_cmd_ds_11n_delba *) &resp->params.del_ba; + uint16_t del_ba_param_set = le16_to_cpu(del_ba->del_ba_param_set); + + tid = del_ba_param_set >> DELBA_TID_POS; + if (del_ba->del_result == BA_RESULT_SUCCESS) { + mwifiex_11n_delete_ba_stream_tbl(priv, tid, + del_ba->peer_mac_addr, TYPE_DELBA_SENT, + INITIATOR_BIT(del_ba_param_set)); + + tx_ba_tbl = mwifiex_11n_get_tx_ba_stream_status(priv, + BA_STREAM_SETUP_INPROGRESS); + if (tx_ba_tbl) + mwifiex_send_addba(priv, tx_ba_tbl->tid, + tx_ba_tbl->ra); + } else { /* + * In case of failure, recreate the deleted stream in case + * we initiated the ADDBA + */ + if (INITIATOR_BIT(del_ba_param_set)) { + mwifiex_11n_create_tx_ba_stream_tbl(priv, + del_ba->peer_mac_addr, tid, + BA_STREAM_SETUP_INPROGRESS); + + tx_ba_tbl = mwifiex_11n_get_tx_ba_stream_status(priv, + BA_STREAM_SETUP_INPROGRESS); + if (tx_ba_tbl) + mwifiex_11n_delete_ba_stream_tbl(priv, + tx_ba_tbl->tid, tx_ba_tbl->ra, + TYPE_DELBA_SENT, true); + } + } + + return 0; +} + +/* + * This function handles the command response of add a block + * ack request. + * + * Handling includes changing the header fields to CPU formats, checking + * the response success status and taking actions accordingly (delete the + * BA stream table in case of failure). + */ +int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + int tid; + struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = + (struct host_cmd_ds_11n_addba_rsp *) &resp->params.add_ba_rsp; + struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; + + add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) + & SSN_MASK); + + tid = (le16_to_cpu(add_ba_rsp->block_ack_param_set) + & IEEE80211_ADDBA_PARAM_TID_MASK) + >> BLOCKACKPARAM_TID_POS; + if (le16_to_cpu(add_ba_rsp->status_code) == BA_RESULT_SUCCESS) { + tx_ba_tbl = mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, + add_ba_rsp->peer_mac_addr); + if (tx_ba_tbl) { + dev_dbg(priv->adapter->dev, "info: BA stream complete\n"); + tx_ba_tbl->ba_status = BA_STREAM_SETUP_COMPLETE; + } else { + dev_err(priv->adapter->dev, "BA stream not created\n"); + } + } else { + mwifiex_11n_delete_ba_stream_tbl(priv, tid, + add_ba_rsp->peer_mac_addr, + TYPE_DELBA_SENT, true); + if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) + priv->aggr_prio_tbl[tid].ampdu_ap = + BA_STREAM_NOT_ALLOWED; + } + + return 0; +} + +/* + * This function handles the command response of 11n configuration request. + * + * Handling includes changing the header fields into CPU format. + */ +int mwifiex_ret_11n_cfg(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *data_buf) +{ + struct mwifiex_ds_11n_tx_cfg *tx_cfg = NULL; + struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg; + + if (data_buf) { + tx_cfg = (struct mwifiex_ds_11n_tx_cfg *) data_buf; + tx_cfg->tx_htcap = le16_to_cpu(htcfg->ht_tx_cap); + tx_cfg->tx_htinfo = le16_to_cpu(htcfg->ht_tx_info); + } + return 0; +} + +/* + * This function prepares command of reconfigure Tx buffer. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting Tx buffer size (for SET only) + * - Ensuring correct endian-ness + */ +int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, int cmd_action, + void *data_buf) +{ + struct host_cmd_ds_txbuf_cfg *tx_buf = &cmd->params.tx_buf; + u16 action = (u16) cmd_action; + u16 buf_size = *((u16 *) data_buf); + + cmd->command = cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF); + cmd->size = + cpu_to_le16(sizeof(struct host_cmd_ds_txbuf_cfg) + S_DS_GEN); + tx_buf->action = cpu_to_le16(action); + switch (action) { + case HostCmd_ACT_GEN_SET: + dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", buf_size); + tx_buf->buff_size = cpu_to_le16(buf_size); + break; + case HostCmd_ACT_GEN_GET: + default: + tx_buf->buff_size = 0; + break; + } + return 0; +} + +/* + * This function prepares command of AMSDU aggregation control. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting AMSDU control parameters (for SET only) + * - Ensuring correct endian-ness + */ +int mwifiex_cmd_amsdu_aggr_ctrl(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + int cmd_action, void *data_buf) +{ + struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl = + &cmd->params.amsdu_aggr_ctrl; + u16 action = (u16) cmd_action; + struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl = + (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf; + + cmd->command = cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL); + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_amsdu_aggr_ctrl) + + S_DS_GEN); + amsdu_ctrl->action = cpu_to_le16(action); + switch (action) { + case HostCmd_ACT_GEN_SET: + amsdu_ctrl->enable = cpu_to_le16(aa_ctrl->enable); + amsdu_ctrl->curr_buf_size = 0; + break; + case HostCmd_ACT_GEN_GET: + default: + amsdu_ctrl->curr_buf_size = 0; + break; + } + return 0; +} + +/* + * This function handles the command response of AMSDU aggregation + * control request. + * + * Handling includes changing the header fields into CPU format. + */ +int mwifiex_ret_amsdu_aggr_ctrl(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *data_buf) +{ + struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl = NULL; + struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl = + &resp->params.amsdu_aggr_ctrl; + + if (data_buf) { + amsdu_aggr_ctrl = + (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf; + amsdu_aggr_ctrl->enable = le16_to_cpu(amsdu_ctrl->enable); + amsdu_aggr_ctrl->curr_buf_size = + le16_to_cpu(amsdu_ctrl->curr_buf_size); + } + return 0; +} + +/* + * This function prepares 11n configuration command. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting HT Tx capability and HT Tx information fields + * - Ensuring correct endian-ness + */ +int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, void *data_buf) +{ + struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg; + struct mwifiex_ds_11n_tx_cfg *txcfg = + (struct mwifiex_ds_11n_tx_cfg *) data_buf; + + cmd->command = cpu_to_le16(HostCmd_CMD_11N_CFG); + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_11n_cfg) + S_DS_GEN); + htcfg->action = cpu_to_le16(cmd_action); + htcfg->ht_tx_cap = cpu_to_le16(txcfg->tx_htcap); + htcfg->ht_tx_info = cpu_to_le16(txcfg->tx_htinfo); + return 0; +} + +/* + * This function appends an 11n TLV to a buffer. + * + * Buffer allocation is responsibility of the calling + * function. No size validation is made here. + * + * The function fills up the following sections, if applicable - + * - HT capability IE + * - HT information IE (with channel list) + * - 20/40 BSS Coexistence IE + * - HT Extended Capabilities IE + */ +int +mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc, + u8 **buffer) +{ + struct mwifiex_ie_types_htcap *ht_cap; + struct mwifiex_ie_types_htinfo *ht_info; + struct mwifiex_ie_types_chan_list_param_set *chan_list; + struct mwifiex_ie_types_2040bssco *bss_co_2040; + struct mwifiex_ie_types_extcap *ext_cap; + int ret_len = 0; + + if (!buffer || !*buffer) + return ret_len; + + if (bss_desc->bcn_ht_cap) { + ht_cap = (struct mwifiex_ie_types_htcap *) *buffer; + memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); + ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); + ht_cap->header.len = + cpu_to_le16(sizeof(struct ieee80211_ht_cap)); + memcpy((u8 *) ht_cap + sizeof(struct mwifiex_ie_types_header), + (u8 *) bss_desc->bcn_ht_cap + + sizeof(struct ieee_types_header), + le16_to_cpu(ht_cap->header.len)); + + mwifiex_fill_cap_info(priv, ht_cap); + + *buffer += sizeof(struct mwifiex_ie_types_htcap); + ret_len += sizeof(struct mwifiex_ie_types_htcap); + } + + if (bss_desc->bcn_ht_info) { + if (priv->bss_mode == MWIFIEX_BSS_MODE_IBSS) { + ht_info = (struct mwifiex_ie_types_htinfo *) *buffer; + memset(ht_info, 0, + sizeof(struct mwifiex_ie_types_htinfo)); + ht_info->header.type = + cpu_to_le16(WLAN_EID_HT_INFORMATION); + ht_info->header.len = + cpu_to_le16(sizeof(struct ieee80211_ht_info)); + + memcpy((u8 *) ht_info + + sizeof(struct mwifiex_ie_types_header), + (u8 *) bss_desc->bcn_ht_info + + sizeof(struct ieee_types_header), + le16_to_cpu(ht_info->header.len)); + + if (!ISSUPP_CHANWIDTH40 + (priv->adapter->hw_dot_11n_dev_cap) + || !ISSUPP_CHANWIDTH40(priv->adapter-> + usr_dot_11n_dev_cap)) + RESET_CHANWIDTH40(ht_info->ht_info.ht_param); + + *buffer += sizeof(struct mwifiex_ie_types_htinfo); + ret_len += sizeof(struct mwifiex_ie_types_htinfo); + } + + chan_list = + (struct mwifiex_ie_types_chan_list_param_set *) *buffer; + memset(chan_list, 0, + sizeof(struct mwifiex_ie_types_chan_list_param_set)); + chan_list->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); + chan_list->header.len = cpu_to_le16( + sizeof(struct mwifiex_ie_types_chan_list_param_set) - + sizeof(struct mwifiex_ie_types_header)); + chan_list->chan_scan_param[0].chan_number = + bss_desc->bcn_ht_info->control_chan; + chan_list->chan_scan_param[0].radio_type = + mwifiex_band_to_radio_type((u8) bss_desc->bss_band); + + if ((ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) && + ISSUPP_CHANWIDTH40(priv->adapter->usr_dot_11n_dev_cap)) + && ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_info->ht_param)) + SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. + radio_type, + GET_SECONDARYCHAN(bss_desc-> + bcn_ht_info->ht_param)); + + *buffer += sizeof(struct mwifiex_ie_types_chan_list_param_set); + ret_len += sizeof(struct mwifiex_ie_types_chan_list_param_set); + } + + if (bss_desc->bcn_bss_co_2040) { + bss_co_2040 = (struct mwifiex_ie_types_2040bssco *) *buffer; + memset(bss_co_2040, 0, + sizeof(struct mwifiex_ie_types_2040bssco)); + bss_co_2040->header.type = cpu_to_le16(WLAN_EID_BSS_COEX_2040); + bss_co_2040->header.len = + cpu_to_le16(sizeof(bss_co_2040->bss_co_2040)); + + memcpy((u8 *) bss_co_2040 + + sizeof(struct mwifiex_ie_types_header), + (u8 *) bss_desc->bcn_bss_co_2040 + + sizeof(struct ieee_types_header), + le16_to_cpu(bss_co_2040->header.len)); + + *buffer += sizeof(struct mwifiex_ie_types_2040bssco); + ret_len += sizeof(struct mwifiex_ie_types_2040bssco); + } + + if (bss_desc->bcn_ext_cap) { + ext_cap = (struct mwifiex_ie_types_extcap *) *buffer; + memset(ext_cap, 0, sizeof(struct mwifiex_ie_types_extcap)); + ext_cap->header.type = cpu_to_le16(WLAN_EID_EXT_CAPABILITY); + ext_cap->header.len = cpu_to_le16(sizeof(ext_cap->ext_cap)); + + memcpy((u8 *) ext_cap + + sizeof(struct mwifiex_ie_types_header), + (u8 *) bss_desc->bcn_ext_cap + + sizeof(struct ieee_types_header), + le16_to_cpu(ext_cap->header.len)); + + *buffer += sizeof(struct mwifiex_ie_types_extcap); + ret_len += sizeof(struct mwifiex_ie_types_extcap); + } + + return ret_len; +} + +/* + * This function reconfigures the Tx buffer size in firmware. + * + * This function prepares a firmware command and issues it, if + * the current Tx buffer size is different from the one requested. + * Maximum configurable Tx buffer size is limited by the HT capability + * field value. + */ +void +mwifiex_cfg_tx_buf(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc) +{ + u16 max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_2K; + u16 tx_buf = 0; + u16 curr_tx_buf_size = 0; + + if (bss_desc->bcn_ht_cap) { + if (GETHT_MAXAMSDU(le16_to_cpu(bss_desc->bcn_ht_cap->cap_info))) + max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_8K; + else + max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_4K; + } + + tx_buf = min(priv->adapter->max_tx_buf_size, max_amsdu); + + dev_dbg(priv->adapter->dev, "info: max_amsdu=%d, max_tx_buf=%d\n", + max_amsdu, priv->adapter->max_tx_buf_size); + + if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_2K) + curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; + else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_4K) + curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; + else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_8K) + curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_8K; + if (curr_tx_buf_size != tx_buf) + mwifiex_prepare_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, + HostCmd_ACT_GEN_SET, 0, + NULL, &tx_buf); + + return; +} + +/* + * This function checks if the given pointer is valid entry of + * Tx BA Stream table. + */ +static int mwifiex_is_tx_ba_stream_ptr_valid(struct mwifiex_private *priv, + struct mwifiex_tx_ba_stream_tbl *tx_tbl_ptr) +{ + struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; + + list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { + if (tx_ba_tsr_tbl == tx_tbl_ptr) + return true; + } + + return false; +} + +/* + * This function deletes the given entry in Tx BA Stream table. + * + * The function also performs a validity check on the supplied + * pointer before trying to delete. + */ +void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv, + struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl) +{ + if (!tx_ba_tsr_tbl && + mwifiex_is_tx_ba_stream_ptr_valid(priv, tx_ba_tsr_tbl)) + return; + + dev_dbg(priv->adapter->dev, "info: tx_ba_tsr_tbl %p\n", tx_ba_tsr_tbl); + + list_del(&tx_ba_tsr_tbl->list); + + kfree(tx_ba_tsr_tbl); + + return; +} + +/* + * This function deletes all the entries in Tx BA Stream table. + */ +void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv) +{ + int i; + struct mwifiex_tx_ba_stream_tbl *del_tbl_ptr, *tmp_node; + unsigned long flags; + + spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); + list_for_each_entry_safe(del_tbl_ptr, tmp_node, + &priv->tx_ba_stream_tbl_ptr, list) + mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, del_tbl_ptr); + spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); + + INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); + + for (i = 0; i < MAX_NUM_TID; ++i) + priv->aggr_prio_tbl[i].ampdu_ap = + priv->aggr_prio_tbl[i].ampdu_user; +} + +/* + * This function returns the pointer to an entry in BA Stream + * table which matches the given RA/TID pair. + */ +struct mwifiex_tx_ba_stream_tbl * +mwifiex_11n_get_tx_ba_stream_tbl(struct mwifiex_private *priv, + int tid, u8 *ra) +{ + struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; + unsigned long flags; + + spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); + list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { + if ((!memcmp(tx_ba_tsr_tbl->ra, ra, ETH_ALEN)) + && (tx_ba_tsr_tbl->tid == tid)) { + spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, + flags); + return tx_ba_tsr_tbl; + } + } + spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); + return NULL; +} + +/* + * This function creates an entry in Tx BA stream table for the + * given RA/TID pair. + */ +void mwifiex_11n_create_tx_ba_stream_tbl(struct mwifiex_private *priv, + u8 *ra, int tid, + enum mwifiex_ba_status ba_status) +{ + struct mwifiex_tx_ba_stream_tbl *new_node; + unsigned long flags; + + if (!mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, ra)) { + new_node = kzalloc(sizeof(struct mwifiex_tx_ba_stream_tbl), + GFP_ATOMIC); + if (!new_node) { + dev_err(priv->adapter->dev, + "%s: failed to alloc new_node\n", __func__); + return; + } + + INIT_LIST_HEAD(&new_node->list); + + new_node->tid = tid; + new_node->ba_status = ba_status; + memcpy(new_node->ra, ra, ETH_ALEN); + + spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); + list_add_tail(&new_node->list, &priv->tx_ba_stream_tbl_ptr); + spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); + } + + return; +} + +/* + * This function sends an add BA request to the given TID/RA pair. + */ +int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) +{ + struct host_cmd_ds_11n_addba_req add_ba_req; + static u8 dialog_tok; + int ret; + + dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid); + + add_ba_req.block_ack_param_set = cpu_to_le16( + (u16) ((tid << BLOCKACKPARAM_TID_POS) | + (priv->add_ba_param. + tx_win_size << BLOCKACKPARAM_WINSIZE_POS) | + IMMEDIATE_BLOCK_ACK)); + add_ba_req.block_ack_tmo = cpu_to_le16((u16)priv->add_ba_param.timeout); + + ++dialog_tok; + + if (dialog_tok == 0) + dialog_tok = 1; + + add_ba_req.dialog_token = dialog_tok; + memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN); + + /* We don't wait for the response of this command */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_ADDBA_REQ, + 0, 0, NULL, &add_ba_req); + + return ret; +} + +/* + * This function sends a delete BA request to the given TID/RA pair. + */ +int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, + int initiator) +{ + struct host_cmd_ds_11n_delba delba; + int ret; + uint16_t del_ba_param_set; + + memset(&delba, 0, sizeof(delba)); + delba.del_ba_param_set = cpu_to_le16(tid << DELBA_TID_POS); + + del_ba_param_set = le16_to_cpu(delba.del_ba_param_set); + if (initiator) + del_ba_param_set |= IEEE80211_DELBA_PARAM_INITIATOR_MASK; + else + del_ba_param_set &= ~IEEE80211_DELBA_PARAM_INITIATOR_MASK; + + memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN); + + /* We don't wait for the response of this command */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, + HostCmd_ACT_GEN_SET, 0, NULL, &delba); + + return ret; +} + +/* + * This function handles the command response of a delete BA request. + */ +void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba) +{ + struct host_cmd_ds_11n_delba *cmd_del_ba = + (struct host_cmd_ds_11n_delba *) del_ba; + uint16_t del_ba_param_set = le16_to_cpu(cmd_del_ba->del_ba_param_set); + int tid; + + tid = del_ba_param_set >> DELBA_TID_POS; + + mwifiex_11n_delete_ba_stream_tbl(priv, tid, cmd_del_ba->peer_mac_addr, + TYPE_DELBA_RECEIVE, + INITIATOR_BIT(del_ba_param_set)); +} + +/* + * This function retrieves the Rx reordering table. + */ +int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv, + struct mwifiex_ds_rx_reorder_tbl *buf) +{ + int i; + struct mwifiex_ds_rx_reorder_tbl *rx_reo_tbl = buf; + struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr; + int count = 0; + unsigned long flags; + + spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); + list_for_each_entry(rx_reorder_tbl_ptr, &priv->rx_reorder_tbl_ptr, + list) { + rx_reo_tbl->tid = (u16) rx_reorder_tbl_ptr->tid; + memcpy(rx_reo_tbl->ta, rx_reorder_tbl_ptr->ta, ETH_ALEN); + rx_reo_tbl->start_win = rx_reorder_tbl_ptr->start_win; + rx_reo_tbl->win_size = rx_reorder_tbl_ptr->win_size; + for (i = 0; i < rx_reorder_tbl_ptr->win_size; ++i) { + if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) + rx_reo_tbl->buffer[i] = true; + else + rx_reo_tbl->buffer[i] = false; + } + rx_reo_tbl++; + count++; + + if (count >= MWIFIEX_MAX_RX_BASTREAM_SUPPORTED) + break; + } + spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); + + return count; +} + +/* + * This function retrieves the Tx BA stream table. + */ +int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, + struct mwifiex_ds_tx_ba_stream_tbl *buf) +{ + struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; + struct mwifiex_ds_tx_ba_stream_tbl *rx_reo_tbl = buf; + int count = 0; + unsigned long flags; + + spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); + list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { + rx_reo_tbl->tid = (u16) tx_ba_tsr_tbl->tid; + dev_dbg(priv->adapter->dev, "data: %s tid=%d\n", + __func__, rx_reo_tbl->tid); + memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN); + rx_reo_tbl++; + count++; + if (count >= MWIFIEX_MAX_TX_BASTREAM_SUPPORTED) + break; + } + spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); + + return count; +} diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h new file mode 100644 index 000000000000..769a27f2b2c3 --- /dev/null +++ b/drivers/net/wireless/mwifiex/11n.h @@ -0,0 +1,178 @@ +/* + * Marvell Wireless LAN device driver: 802.11n + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#ifndef _MWIFIEX_11N_H_ +#define _MWIFIEX_11N_H_ + +#include "11n_aggr.h" +#include "11n_rxreorder.h" +#include "wmm.h" + +void mwifiex_show_dot_11n_dev_cap(struct mwifiex_adapter *adapter, u32 cap); +void mwifiex_show_dev_mcs_support(struct mwifiex_adapter *adapter, u8 support); +int mwifiex_ret_11n_delba(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp); +int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp); +int mwifiex_ret_11n_cfg(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *data_buf); +int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, void *data_buf); + +int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, void *data_buf); + +int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc, + u8 **buffer); +void mwifiex_cfg_tx_buf(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc); +void mwifiex_fill_cap_info(struct mwifiex_private *, + struct mwifiex_ie_types_htcap *); +int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv, + u16 action, int *htcap_cfg); +void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv, + struct mwifiex_tx_ba_stream_tbl + *tx_tbl); +void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv); +struct mwifiex_tx_ba_stream_tbl *mwifiex_11n_get_tx_ba_stream_tbl(struct + mwifiex_private + *priv, int tid, + u8 *ra); +void mwifiex_11n_create_tx_ba_stream_tbl(struct mwifiex_private *priv, u8 *ra, + int tid, + enum mwifiex_ba_status ba_status); +int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac); +int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, + int initiator); +void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba); +int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv, + struct mwifiex_ds_rx_reorder_tbl *buf); +int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, + struct mwifiex_ds_tx_ba_stream_tbl *buf); +int mwifiex_ret_amsdu_aggr_ctrl(struct mwifiex_private *priv, + struct host_cmd_ds_command + *resp, + void *data_buf); +int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + int cmd_action, void *data_buf); +int mwifiex_cmd_amsdu_aggr_ctrl(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + int cmd_action, + void *data_buf); + +/* + * This function checks whether AMPDU is allowed or not for a particular TID. + */ +static inline u8 +mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ptr, int tid) +{ + return ((priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED) + ? true : false); +} + +/* + * This function checks whether AMSDU is allowed or not for a particular TID. + */ +static inline u8 +mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ptr, int tid) +{ + return (((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED) + && ((priv->is_data_rate_auto) + || !((priv->bitmap_rates[2]) & 0x03))) + ? true : false); +} + +/* + * This function checks whether a BA stream is available or not. + */ +static inline u8 +mwifiex_is_ba_stream_avail(struct mwifiex_private *priv) +{ + struct mwifiex_private *pmpriv = NULL; + u8 i = 0; + u32 ba_stream_num = 0; + + for (i = 0; i < priv->adapter->priv_num; i++) { + pmpriv = priv->adapter->priv[i]; + if (pmpriv) + ba_stream_num += + mwifiex_wmm_list_len(priv->adapter, + (struct list_head + *) &pmpriv-> + tx_ba_stream_tbl_ptr); + } + + return ((ba_stream_num < + MWIFIEX_MAX_TX_BASTREAM_SUPPORTED) ? true : false); +} + +/* + * This function finds the correct Tx BA stream to delete. + * + * Upon successfully locating, both the TID and the RA are returned. + */ +static inline u8 +mwifiex_find_stream_to_delete(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ptr, int ptr_tid, + int *ptid, u8 *ra) +{ + int tid; + u8 ret = false; + struct mwifiex_tx_ba_stream_tbl *tx_tbl; + unsigned long flags; + + tid = priv->aggr_prio_tbl[ptr_tid].ampdu_user; + + spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); + list_for_each_entry(tx_tbl, &priv->tx_ba_stream_tbl_ptr, list) { + if (tid > priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user) { + tid = priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user; + *ptid = tx_tbl->tid; + memcpy(ra, tx_tbl->ra, ETH_ALEN); + ret = true; + } + } + spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); + + return ret; +} + +/* + * This function checks whether BA stream is set up or not. + */ +static inline int +mwifiex_is_ba_stream_setup(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ptr, int tid) +{ + struct mwifiex_tx_ba_stream_tbl *tx_tbl; + + tx_tbl = mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, ptr->ra); + if (tx_tbl && IS_BASTREAM_SETUP(tx_tbl)) + return true; + + return false; +} +#endif /* !_MWIFIEX_11N_H_ */ diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c new file mode 100644 index 000000000000..c2abced66957 --- /dev/null +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -0,0 +1,423 @@ +/* + * Marvell Wireless LAN device driver: 802.11n Aggregation + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" +#include "11n_aggr.h" + +/* + * Creates an AMSDU subframe for aggregation into one AMSDU packet. + * + * The resultant AMSDU subframe format is - + * + * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+ + * | DA | SA | Length | SNAP header | MSDU | + * | data[0..5] | data[6..11] | | | data[14..] | + * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+ + * <--6-bytes--> <--6-bytes--> <--2-bytes--><--8-bytes--> <--n-bytes--> + * + * This function also computes the amount of padding required to make the + * buffer length multiple of 4 bytes. + * + * Data => |DA|SA|SNAP-TYPE|........ .| + * MSDU => |DA|SA|Length|SNAP|...... ..| + */ +static int +mwifiex_11n_form_amsdu_pkt(struct mwifiex_adapter *adapter, + struct sk_buff *skb_aggr, + struct sk_buff *skb_src, int *pad) + +{ + int dt_offset; + struct rfc_1042_hdr snap = { + 0xaa, /* LLC DSAP */ + 0xaa, /* LLC SSAP */ + 0x03, /* LLC CTRL */ + {0x00, 0x00, 0x00}, /* SNAP OUI */ + 0x0000 /* SNAP type */ + /* + * This field will be overwritten + * later with ethertype + */ + }; + struct tx_packet_hdr *tx_header = NULL; + + skb_put(skb_aggr, sizeof(*tx_header)); + + tx_header = (struct tx_packet_hdr *) skb_aggr->data; + + /* Copy DA and SA */ + dt_offset = 2 * ETH_ALEN; + memcpy(&tx_header->eth803_hdr, skb_src->data, dt_offset); + + /* Copy SNAP header */ + snap.snap_type = *(u16 *) ((u8 *)skb_src->data + dt_offset); + dt_offset += sizeof(u16); + + memcpy(&tx_header->rfc1042_hdr, &snap, sizeof(struct rfc_1042_hdr)); + + skb_pull(skb_src, dt_offset); + + /* Update Length field */ + tx_header->eth803_hdr.h_proto = htons(skb_src->len + LLC_SNAP_LEN); + + /* Add payload */ + skb_put(skb_aggr, skb_src->len); + memcpy(skb_aggr->data + sizeof(*tx_header), skb_src->data, + skb_src->len); + *pad = (((skb_src->len + LLC_SNAP_LEN) & 3)) ? (4 - (((skb_src->len + + LLC_SNAP_LEN)) & 3)) : 0; + skb_put(skb_aggr, *pad); + + return skb_aggr->len + *pad; +} + +/* + * Adds TxPD to AMSDU header. + * + * Each AMSDU packet will contain one TxPD at the beginning, + * followed by multiple AMSDU subframes. + */ +static void +mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, + struct sk_buff *skb) +{ + struct txpd *local_tx_pd; + + skb_push(skb, sizeof(*local_tx_pd)); + + local_tx_pd = (struct txpd *) skb->data; + memset(local_tx_pd, 0, sizeof(struct txpd)); + + /* Original priority has been overwritten */ + local_tx_pd->priority = (u8) skb->priority; + local_tx_pd->pkt_delay_2ms = + mwifiex_wmm_compute_drv_pkt_delay(priv, skb); + local_tx_pd->bss_num = priv->bss_num; + local_tx_pd->bss_type = priv->bss_type; + /* Always zero as the data is followed by struct txpd */ + local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); + local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU); + local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len - + sizeof(*local_tx_pd)); + + if (local_tx_pd->tx_control == 0) + /* TxCtrl set by user or default */ + local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); + + if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && + (priv->adapter->pps_uapsd_mode)) { + if (true == mwifiex_check_last_packet_indication(priv)) { + priv->adapter->tx_lock_flag = true; + local_tx_pd->flags = + MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET; + } + } +} + +/* + * Counts the number of subframes in an aggregate packet. + * + * This function parses an aggregate packet buffer, looking for + * subframes and counting the number of such subframe found. The + * function automatically skips the DA/SA fields at the beginning + * of each subframe and padding at the end. + */ +static int +mwifiex_11n_get_num_aggr_pkts(u8 *data, int total_pkt_len) +{ + int pkt_count = 0, pkt_len, pad; + + while (total_pkt_len > 0) { + /* Length will be in network format, change it to host */ + pkt_len = ntohs((*(__be16 *)(data + 2 * ETH_ALEN))); + pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ? + (4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0; + data += pkt_len + pad + sizeof(struct ethhdr); + total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr); + ++pkt_count; + } + + return pkt_count; +} + +/* + * De-aggregate received packets. + * + * This function parses the received aggregate buffer, extracts each subframe, + * strips off the SNAP header from them and sends the data portion for further + * processing. + * + * Each subframe body is copied onto a separate buffer, which are freed by + * upper layer after processing. The function also performs sanity tests on + * the received buffer. + */ +int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, + struct sk_buff *skb) +{ + u16 pkt_len; + int total_pkt_len; + u8 *data; + int pad; + struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); + struct rxpd *local_rx_pd = (struct rxpd *) skb->data; + struct sk_buff *skb_daggr; + struct mwifiex_rxinfo *rx_info_daggr = NULL; + int ret = -1; + struct rx_packet_hdr *rx_pkt_hdr; + struct mwifiex_adapter *adapter = priv->adapter; + u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; + + data = (u8 *) (local_rx_pd + local_rx_pd->rx_pkt_offset); + total_pkt_len = local_rx_pd->rx_pkt_length; + + /* Sanity test */ + if (total_pkt_len > MWIFIEX_RX_DATA_BUF_SIZE) { + dev_err(adapter->dev, "total pkt len greater than buffer" + " size %d\n", total_pkt_len); + return -1; + } + + rx_info->use_count = mwifiex_11n_get_num_aggr_pkts(data, total_pkt_len); + + while (total_pkt_len > 0) { + rx_pkt_hdr = (struct rx_packet_hdr *) data; + /* Length will be in network format, change it to host */ + pkt_len = ntohs((*(__be16 *) (data + 2 * ETH_ALEN))); + if (pkt_len > total_pkt_len) { + dev_err(adapter->dev, "pkt_len %d > total_pkt_len %d\n", + total_pkt_len, pkt_len); + break; + } + + pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ? + (4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0; + + total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr); + + if (memcmp(&rx_pkt_hdr->rfc1042_hdr, + rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) { + memmove(data + LLC_SNAP_LEN, data, 2 * ETH_ALEN); + data += LLC_SNAP_LEN; + pkt_len += sizeof(struct ethhdr) - LLC_SNAP_LEN; + } else { + *(u16 *) (data + 2 * ETH_ALEN) = (u16) 0; + pkt_len += sizeof(struct ethhdr); + } + + skb_daggr = dev_alloc_skb(pkt_len); + if (!skb_daggr) { + dev_err(adapter->dev, "%s: failed to alloc skb_daggr\n", + __func__); + return -1; + } + rx_info_daggr = MWIFIEX_SKB_RXCB(skb_daggr); + + rx_info_daggr->bss_index = rx_info->bss_index; + skb_daggr->tstamp = skb->tstamp; + rx_info_daggr->parent = skb; + skb_daggr->priority = skb->priority; + skb_put(skb_daggr, pkt_len); + memcpy(skb_daggr->data, data, pkt_len); + + ret = mwifiex_recv_packet(adapter, skb_daggr); + + switch (ret) { + case -EINPROGRESS: + break; + case -1: + dev_err(adapter->dev, "deaggr: host_to_card failed\n"); + case 0: + mwifiex_recv_packet_complete(adapter, skb_daggr, ret); + break; + default: + break; + } + + data += pkt_len + pad; + } + + return ret; +} + +/* + * Create aggregated packet. + * + * This function creates an aggregated MSDU packet, by combining buffers + * from the RA list. Each individual buffer is encapsulated as an AMSDU + * subframe and all such subframes are concatenated together to form the + * AMSDU packet. + * + * A TxPD is also added to the front of the resultant AMSDU packets for + * transmission. The resultant packets format is - + * + * +---- ~ ----+------ ~ ------+------ ~ ------+-..-+------ ~ ------+ + * | TxPD |AMSDU sub-frame|AMSDU sub-frame| .. |AMSDU sub-frame| + * | | 1 | 2 | .. | n | + * +---- ~ ----+------ ~ ------+------ ~ ------+ .. +------ ~ ------+ + */ +int +mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *pra_list, int headroom, + int ptrindex, unsigned long ra_list_flags) + __releases(&priv->wmm.ra_list_spinlock) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct sk_buff *skb_aggr, *skb_src; + struct mwifiex_txinfo *tx_info_aggr, *tx_info_src; + int pad = 0; + int ret = 0; + struct mwifiex_tx_param tx_param; + struct txpd *ptx_pd = NULL; + + if (skb_queue_empty(&pra_list->skb_head)) { + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + return 0; + } + skb_src = skb_peek(&pra_list->skb_head); + tx_info_src = MWIFIEX_SKB_TXCB(skb_src); + skb_aggr = dev_alloc_skb(adapter->tx_buf_size); + if (!skb_aggr) { + dev_err(adapter->dev, "%s: alloc skb_aggr\n", __func__); + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + return -1; + } + skb_reserve(skb_aggr, headroom + sizeof(struct txpd)); + tx_info_aggr = MWIFIEX_SKB_TXCB(skb_aggr); + + tx_info_aggr->bss_index = tx_info_src->bss_index; + skb_aggr->priority = skb_src->priority; + + while (skb_src && ((skb_headroom(skb_aggr) + skb_src->len + + LLC_SNAP_LEN) + <= adapter->tx_buf_size)) { + + if (!skb_queue_empty(&pra_list->skb_head)) + skb_src = skb_dequeue(&pra_list->skb_head); + else + skb_src = NULL; + + pra_list->total_pkts_size -= skb_src->len; + + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + mwifiex_11n_form_amsdu_pkt(adapter, skb_aggr, skb_src, &pad); + + mwifiex_write_data_complete(adapter, skb_src, 0); + + spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); + + if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) { + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + return -1; + } + + if (!skb_queue_empty(&pra_list->skb_head)) + skb_src = skb_peek(&pra_list->skb_head); + else + skb_src = NULL; + } + + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); + + /* Last AMSDU packet does not need padding */ + skb_trim(skb_aggr, skb_aggr->len - pad); + + /* Form AMSDU */ + mwifiex_11n_form_amsdu_txpd(priv, skb_aggr); + if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) + ptx_pd = (struct txpd *)skb_aggr->data; + + skb_push(skb_aggr, headroom); + + tx_param.next_pkt_len = ((pra_list->total_pkts_size) ? + (((pra_list->total_pkts_size) > + adapter->tx_buf_size) ? adapter-> + tx_buf_size : pra_list->total_pkts_size + + LLC_SNAP_LEN + sizeof(struct txpd)) : 0); + ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, + skb_aggr->data, + skb_aggr->len, &tx_param); + switch (ret) { + case -EBUSY: + spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); + if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) { + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + mwifiex_write_data_complete(adapter, skb_aggr, -1); + return -1; + } + if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && + (adapter->pps_uapsd_mode) && + (adapter->tx_lock_flag)) { + priv->adapter->tx_lock_flag = false; + ptx_pd->flags = 0; + } + + skb_queue_tail(&pra_list->skb_head, skb_aggr); + + pra_list->total_pkts_size += skb_aggr->len; + + tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); + break; + case -1: + adapter->data_sent = false; + dev_err(adapter->dev, "%s: host_to_card failed: %#x\n", + __func__, ret); + adapter->dbg.num_tx_host_to_card_failure++; + mwifiex_write_data_complete(adapter, skb_aggr, ret); + return 0; + case -EINPROGRESS: + adapter->data_sent = false; + break; + case 0: + mwifiex_write_data_complete(adapter, skb_aggr, ret); + break; + default: + break; + } + if (ret != -EBUSY) { + spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); + if (mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) { + priv->wmm.packets_out[ptrindex]++; + priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = pra_list; + } + /* Now bss_prio_cur pointer points to next node */ + adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = + list_first_entry( + &adapter->bss_prio_tbl[priv->bss_priority] + .bss_prio_cur->list, + struct mwifiex_bss_prio_node, list); + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + } + + return 0; +} diff --git a/drivers/net/wireless/mwifiex/11n_aggr.h b/drivers/net/wireless/mwifiex/11n_aggr.h new file mode 100644 index 000000000000..9c6dca7ab02c --- /dev/null +++ b/drivers/net/wireless/mwifiex/11n_aggr.h @@ -0,0 +1,32 @@ +/* + * Marvell Wireless LAN device driver: 802.11n Aggregation + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#ifndef _MWIFIEX_11N_AGGR_H_ +#define _MWIFIEX_11N_AGGR_H_ + +#define PKT_TYPE_AMSDU 0xE6 + +int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, + struct sk_buff *skb); +int mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ptr, int headroom, + int ptr_index, unsigned long flags) + __releases(&priv->wmm.ra_list_spinlock); + +#endif /* !_MWIFIEX_11N_AGGR_H_ */ diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c new file mode 100644 index 000000000000..8e94e620e6f4 --- /dev/null +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -0,0 +1,637 @@ +/* + * Marvell Wireless LAN device driver: 802.11n RX Re-ordering + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" +#include "11n_rxreorder.h" + +/* + * This function processes a received packet and forwards + * it to the kernel/upper layer. + */ +static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload) +{ + int ret = 0; + struct mwifiex_adapter *adapter = priv->adapter; + + ret = mwifiex_process_rx_packet(adapter, (struct sk_buff *) payload); + return ret; +} + +/* + * This function dispatches all packets in the Rx reorder table. + * + * There could be holes in the buffer, which are skipped by the function. + * Since the buffer is linear, the function uses rotation to simulate + * circular buffer. + */ +static int +mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv, + struct mwifiex_rx_reorder_tbl + *rx_reor_tbl_ptr, int start_win) +{ + int no_pkt_to_send, i, xchg; + void *rx_tmp_ptr = NULL; + unsigned long flags; + + no_pkt_to_send = (start_win > rx_reor_tbl_ptr->start_win) ? + min((start_win - rx_reor_tbl_ptr->start_win), + rx_reor_tbl_ptr->win_size) : rx_reor_tbl_ptr->win_size; + + for (i = 0; i < no_pkt_to_send; ++i) { + spin_lock_irqsave(&priv->rx_pkt_lock, flags); + rx_tmp_ptr = NULL; + if (rx_reor_tbl_ptr->rx_reorder_ptr[i]) { + rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i]; + rx_reor_tbl_ptr->rx_reorder_ptr[i] = NULL; + } + spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); + if (rx_tmp_ptr) + mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); + } + + spin_lock_irqsave(&priv->rx_pkt_lock, flags); + /* + * We don't have a circular buffer, hence use rotation to simulate + * circular buffer + */ + xchg = rx_reor_tbl_ptr->win_size - no_pkt_to_send; + for (i = 0; i < xchg; ++i) { + rx_reor_tbl_ptr->rx_reorder_ptr[i] = + rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i]; + rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i] = NULL; + } + + rx_reor_tbl_ptr->start_win = start_win; + spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); + + return 0; +} + +/* + * This function dispatches all packets in the Rx reorder table until + * a hole is found. + * + * The start window is adjusted automatically when a hole is located. + * Since the buffer is linear, the function uses rotation to simulate + * circular buffer. + */ +static int +mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv, + struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr) +{ + int i, j, xchg; + void *rx_tmp_ptr = NULL; + unsigned long flags; + + for (i = 0; i < rx_reor_tbl_ptr->win_size; ++i) { + spin_lock_irqsave(&priv->rx_pkt_lock, flags); + if (!rx_reor_tbl_ptr->rx_reorder_ptr[i]) { + spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); + break; + } + rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i]; + rx_reor_tbl_ptr->rx_reorder_ptr[i] = NULL; + spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); + mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); + } + + spin_lock_irqsave(&priv->rx_pkt_lock, flags); + /* + * We don't have a circular buffer, hence use rotation to simulate + * circular buffer + */ + if (i > 0) { + xchg = rx_reor_tbl_ptr->win_size - i; + for (j = 0; j < xchg; ++j) { + rx_reor_tbl_ptr->rx_reorder_ptr[j] = + rx_reor_tbl_ptr->rx_reorder_ptr[i + j]; + rx_reor_tbl_ptr->rx_reorder_ptr[i + j] = NULL; + } + } + rx_reor_tbl_ptr->start_win = (rx_reor_tbl_ptr->start_win + i) + &(MAX_TID_VALUE - 1); + spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); + return 0; +} + +/* + * This function deletes the Rx reorder table and frees the memory. + * + * The function stops the associated timer and dispatches all the + * pending packets in the Rx reorder table before deletion. + */ +static void +mwifiex_11n_delete_rx_reorder_tbl_entry(struct mwifiex_private *priv, + struct mwifiex_rx_reorder_tbl + *rx_reor_tbl_ptr) +{ + unsigned long flags; + + if (!rx_reor_tbl_ptr) + return; + + mwifiex_11n_dispatch_pkt_until_start_win(priv, rx_reor_tbl_ptr, + (rx_reor_tbl_ptr->start_win + + rx_reor_tbl_ptr->win_size) + &(MAX_TID_VALUE - 1)); + + del_timer(&rx_reor_tbl_ptr->timer_context.timer); + + spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); + list_del(&rx_reor_tbl_ptr->list); + spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); + + kfree(rx_reor_tbl_ptr->rx_reorder_ptr); + kfree(rx_reor_tbl_ptr); +} + +/* + * This function returns the pointer to an entry in Rx reordering + * table which matches the given TA/TID pair. + */ +static struct mwifiex_rx_reorder_tbl * +mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta) +{ + struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; + unsigned long flags; + + spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); + list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) { + if ((!memcmp(rx_reor_tbl_ptr->ta, ta, ETH_ALEN)) + && (rx_reor_tbl_ptr->tid == tid)) { + spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, + flags); + return rx_reor_tbl_ptr; + } + } + spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); + + return NULL; +} + +/* + * This function finds the last sequence number used in the packets + * buffered in Rx reordering table. + */ +static int +mwifiex_11n_find_last_seq_num(struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr) +{ + int i; + + for (i = (rx_reorder_tbl_ptr->win_size - 1); i >= 0; --i) + if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) + return i; + + return -1; +} + +/* + * This function flushes all the packets in Rx reordering table. + * + * The function checks if any packets are currently buffered in the + * table or not. In case there are packets available, it dispatches + * them and then dumps the Rx reordering table. + */ +static void +mwifiex_flush_data(unsigned long context) +{ + struct reorder_tmr_cnxt *reorder_cnxt = + (struct reorder_tmr_cnxt *) context; + int start_win; + + start_win = mwifiex_11n_find_last_seq_num(reorder_cnxt->ptr); + if (start_win >= 0) { + dev_dbg(reorder_cnxt->priv->adapter->dev, + "info: flush data %d\n", start_win); + mwifiex_11n_dispatch_pkt_until_start_win(reorder_cnxt->priv, + reorder_cnxt->ptr, + ((reorder_cnxt->ptr->start_win + + start_win + 1) & (MAX_TID_VALUE - 1))); + } +} + +/* + * This function creates an entry in Rx reordering table for the + * given TA/TID. + * + * The function also initializes the entry with sequence number, window + * size as well as initializes the timer. + * + * If the received TA/TID pair is already present, all the packets are + * dispatched and the window size is moved until the SSN. + */ +static void +mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, + int tid, int win_size, int seq_num) +{ + int i; + struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr, *new_node; + u16 last_seq = 0; + unsigned long flags; + + /* + * If we get a TID, ta pair which is already present dispatch all the + * the packets and move the window size until the ssn + */ + rx_reor_tbl_ptr = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); + if (rx_reor_tbl_ptr) { + mwifiex_11n_dispatch_pkt_until_start_win(priv, rx_reor_tbl_ptr, + seq_num); + return; + } + /* if !rx_reor_tbl_ptr then create one */ + new_node = kzalloc(sizeof(struct mwifiex_rx_reorder_tbl), GFP_KERNEL); + if (!new_node) { + dev_err(priv->adapter->dev, "%s: failed to alloc new_node\n", + __func__); + return; + } + + INIT_LIST_HEAD(&new_node->list); + new_node->tid = tid; + memcpy(new_node->ta, ta, ETH_ALEN); + new_node->start_win = seq_num; + if (mwifiex_queuing_ra_based(priv)) + /* TODO for adhoc */ + dev_dbg(priv->adapter->dev, + "info: ADHOC:last_seq=%d start_win=%d\n", + last_seq, new_node->start_win); + else + last_seq = priv->rx_seq[tid]; + + if (last_seq >= new_node->start_win) + new_node->start_win = last_seq + 1; + + new_node->win_size = win_size; + + new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size, + GFP_KERNEL); + if (!new_node->rx_reorder_ptr) { + kfree((u8 *) new_node); + dev_err(priv->adapter->dev, + "%s: failed to alloc reorder_ptr\n", __func__); + return; + } + + new_node->timer_context.ptr = new_node; + new_node->timer_context.priv = priv; + + init_timer(&new_node->timer_context.timer); + new_node->timer_context.timer.function = mwifiex_flush_data; + new_node->timer_context.timer.data = + (unsigned long) &new_node->timer_context; + + for (i = 0; i < win_size; ++i) + new_node->rx_reorder_ptr[i] = NULL; + + spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); + list_add_tail(&new_node->list, &priv->rx_reorder_tbl_ptr); + spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); + + return; +} + +/* + * This function prepares command for adding a BA request. + * + * Preparation includes - + * - Setting command ID and proper size + * - Setting add BA request buffer + * - Ensuring correct endian-ness + */ +int mwifiex_cmd_11n_addba_req(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, void *data_buf) +{ + struct host_cmd_ds_11n_addba_req *add_ba_req = + (struct host_cmd_ds_11n_addba_req *) + &cmd->params.add_ba_req; + + cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_REQ); + cmd->size = cpu_to_le16(sizeof(*add_ba_req) + S_DS_GEN); + memcpy(add_ba_req, data_buf, sizeof(*add_ba_req)); + + return 0; +} + +/* + * This function prepares command for adding a BA response. + * + * Preparation includes - + * - Setting command ID and proper size + * - Setting add BA response buffer + * - Ensuring correct endian-ness + */ +int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf) +{ + struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = + (struct host_cmd_ds_11n_addba_rsp *) + &cmd->params.add_ba_rsp; + struct host_cmd_ds_11n_addba_req *cmd_addba_req = + (struct host_cmd_ds_11n_addba_req *) data_buf; + u8 tid = 0; + int win_size = 0; + uint16_t block_ack_param_set; + + cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP); + cmd->size = cpu_to_le16(sizeof(*add_ba_rsp) + S_DS_GEN); + + memcpy(add_ba_rsp->peer_mac_addr, cmd_addba_req->peer_mac_addr, + ETH_ALEN); + add_ba_rsp->dialog_token = cmd_addba_req->dialog_token; + add_ba_rsp->block_ack_tmo = cmd_addba_req->block_ack_tmo; + add_ba_rsp->ssn = cmd_addba_req->ssn; + + block_ack_param_set = le16_to_cpu(cmd_addba_req->block_ack_param_set); + tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) + >> BLOCKACKPARAM_TID_POS; + add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT); + block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; + /* We donot support AMSDU inside AMPDU, hence reset the bit */ + block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK; + block_ack_param_set |= (priv->add_ba_param.rx_win_size << + BLOCKACKPARAM_WINSIZE_POS); + add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set); + win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set) + & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) + >> BLOCKACKPARAM_WINSIZE_POS; + cmd_addba_req->block_ack_param_set = cpu_to_le16(block_ack_param_set); + + mwifiex_11n_create_rx_reorder_tbl(priv, cmd_addba_req->peer_mac_addr, + tid, win_size, le16_to_cpu(cmd_addba_req->ssn)); + return 0; +} + +/* + * This function prepares command for deleting a BA request. + * + * Preparation includes - + * - Setting command ID and proper size + * - Setting del BA request buffer + * - Ensuring correct endian-ness + */ +int mwifiex_cmd_11n_delba(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, void *data_buf) +{ + struct host_cmd_ds_11n_delba *del_ba = (struct host_cmd_ds_11n_delba *) + &cmd->params.del_ba; + + cmd->command = cpu_to_le16(HostCmd_CMD_11N_DELBA); + cmd->size = cpu_to_le16(sizeof(*del_ba) + S_DS_GEN); + memcpy(del_ba, data_buf, sizeof(*del_ba)); + + return 0; +} + +/* + * This function identifies if Rx reordering is needed for a received packet. + * + * In case reordering is required, the function will do the reordering + * before sending it to kernel. + * + * The Rx reorder table is checked first with the received TID/TA pair. If + * not found, the received packet is dispatched immediately. But if found, + * the packet is reordered and all the packets in the updated Rx reordering + * table is dispatched until a hole is found. + * + * For sequence number less than the starting window, the packet is dropped. + */ +int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, + u16 seq_num, u16 tid, + u8 *ta, u8 pkt_type, void *payload) +{ + struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; + int start_win, end_win, win_size; + int ret = 0; + u16 pkt_index = 0; + + rx_reor_tbl_ptr = + mwifiex_11n_get_rx_reorder_tbl((struct mwifiex_private *) priv, + tid, ta); + if (!rx_reor_tbl_ptr) { + if (pkt_type != PKT_TYPE_BAR) + mwifiex_11n_dispatch_pkt(priv, payload); + return 0; + } + start_win = rx_reor_tbl_ptr->start_win; + win_size = rx_reor_tbl_ptr->win_size; + end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); + del_timer(&rx_reor_tbl_ptr->timer_context.timer); + mod_timer(&rx_reor_tbl_ptr->timer_context.timer, jiffies + + (MIN_FLUSH_TIMER_MS * win_size * HZ) / 1000); + + /* + * If seq_num is less then starting win then ignore and drop the + * packet + */ + if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {/* Wrap */ + if (seq_num >= ((start_win + (TWOPOW11)) & (MAX_TID_VALUE - 1)) + && (seq_num < start_win)) + return -1; + } else if ((seq_num < start_win) + || (seq_num > (start_win + (TWOPOW11)))) { + return -1; + } + + /* + * If this packet is a BAR we adjust seq_num as + * WinStart = seq_num + */ + if (pkt_type == PKT_TYPE_BAR) + seq_num = ((seq_num + win_size) - 1) & (MAX_TID_VALUE - 1); + + if (((end_win < start_win) + && (seq_num < (TWOPOW11 - (MAX_TID_VALUE - start_win))) + && (seq_num > end_win)) || ((end_win > start_win) + && ((seq_num > end_win) || (seq_num < start_win)))) { + end_win = seq_num; + if (((seq_num - win_size) + 1) >= 0) + start_win = (end_win - win_size) + 1; + else + start_win = (MAX_TID_VALUE - (win_size - seq_num)) + 1; + ret = mwifiex_11n_dispatch_pkt_until_start_win(priv, + rx_reor_tbl_ptr, start_win); + + if (ret) + return ret; + } + + if (pkt_type != PKT_TYPE_BAR) { + if (seq_num >= start_win) + pkt_index = seq_num - start_win; + else + pkt_index = (seq_num+MAX_TID_VALUE) - start_win; + + if (rx_reor_tbl_ptr->rx_reorder_ptr[pkt_index]) + return -1; + + rx_reor_tbl_ptr->rx_reorder_ptr[pkt_index] = payload; + } + + /* + * Dispatch all packets sequentially from start_win until a + * hole is found and adjust the start_win appropriately + */ + ret = mwifiex_11n_scan_and_dispatch(priv, rx_reor_tbl_ptr); + + return ret; +} + +/* + * This function deletes an entry for a given TID/TA pair. + * + * The TID/TA are taken from del BA event body. + */ +void +mwifiex_11n_delete_ba_stream_tbl(struct mwifiex_private *priv, int tid, + u8 *peer_mac, u8 type, int initiator) +{ + struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; + struct mwifiex_tx_ba_stream_tbl *ptx_tbl; + u8 cleanup_rx_reorder_tbl; + unsigned long flags; + + if (type == TYPE_DELBA_RECEIVE) + cleanup_rx_reorder_tbl = (initiator) ? true : false; + else + cleanup_rx_reorder_tbl = (initiator) ? false : true; + + dev_dbg(priv->adapter->dev, "event: DELBA: %pM tid=%d, " + "initiator=%d\n", peer_mac, tid, initiator); + + if (cleanup_rx_reorder_tbl) { + rx_reor_tbl_ptr = mwifiex_11n_get_rx_reorder_tbl(priv, tid, + peer_mac); + if (!rx_reor_tbl_ptr) { + dev_dbg(priv->adapter->dev, + "event: TID, TA not found in table\n"); + return; + } + mwifiex_11n_delete_rx_reorder_tbl_entry(priv, rx_reor_tbl_ptr); + } else { + ptx_tbl = mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, peer_mac); + if (!ptx_tbl) { + dev_dbg(priv->adapter->dev, + "event: TID, RA not found in table\n"); + return; + } + + spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); + mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, ptx_tbl); + spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); + } +} + +/* + * This function handles the command response of an add BA response. + * + * Handling includes changing the header fields into CPU format and + * creating the stream, provided the add BA is accepted. + */ +int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = + (struct host_cmd_ds_11n_addba_rsp *) + &resp->params.add_ba_rsp; + int tid, win_size; + struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr = NULL; + uint16_t block_ack_param_set; + + block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); + + tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) + >> BLOCKACKPARAM_TID_POS; + /* + * Check if we had rejected the ADDBA, if yes then do not create + * the stream + */ + if (le16_to_cpu(add_ba_rsp->status_code) == BA_RESULT_SUCCESS) { + win_size = (block_ack_param_set & + IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) + >> BLOCKACKPARAM_WINSIZE_POS; + + dev_dbg(priv->adapter->dev, "cmd: ADDBA RSP: %pM" + " tid=%d ssn=%d win_size=%d\n", + add_ba_rsp->peer_mac_addr, + tid, add_ba_rsp->ssn, win_size); + } else { + dev_err(priv->adapter->dev, "ADDBA RSP: failed %pM tid=%d)\n", + add_ba_rsp->peer_mac_addr, tid); + + rx_reor_tbl_ptr = mwifiex_11n_get_rx_reorder_tbl(priv, + tid, add_ba_rsp->peer_mac_addr); + if (rx_reor_tbl_ptr) + mwifiex_11n_delete_rx_reorder_tbl_entry(priv, + rx_reor_tbl_ptr); + } + + return 0; +} + +/* + * This function handles BA stream timeout event by preparing and sending + * a command to the firmware. + */ +void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv, + struct host_cmd_ds_11n_batimeout *event) +{ + struct host_cmd_ds_11n_delba delba; + + memset(&delba, 0, sizeof(struct host_cmd_ds_11n_delba)); + memcpy(delba.peer_mac_addr, event->peer_mac_addr, ETH_ALEN); + + delba.del_ba_param_set |= + cpu_to_le16((u16) event->tid << DELBA_TID_POS); + delba.del_ba_param_set |= cpu_to_le16( + (u16) event->origninator << DELBA_INITIATOR_POS); + delba.reason_code = cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); + mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, NULL, &delba); + + return; +} + +/* + * This function cleans up the Rx reorder table by deleting all the entries + * and re-initializing. + */ +void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv) +{ + struct mwifiex_rx_reorder_tbl *del_tbl_ptr, *tmp_node; + unsigned long flags; + + spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); + list_for_each_entry_safe(del_tbl_ptr, tmp_node, + &priv->rx_reorder_tbl_ptr, list) { + spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); + mwifiex_11n_delete_rx_reorder_tbl_entry(priv, del_tbl_ptr); + spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); + } + spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); + + INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); + memset(priv->rx_seq, 0, sizeof(priv->rx_seq)); +} diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h new file mode 100644 index 000000000000..42f569035745 --- /dev/null +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h @@ -0,0 +1,67 @@ +/* + * Marvell Wireless LAN device driver: 802.11n RX Re-ordering + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#ifndef _MWIFIEX_11N_RXREORDER_H_ +#define _MWIFIEX_11N_RXREORDER_H_ + +#define MIN_FLUSH_TIMER_MS 50 + +#define PKT_TYPE_BAR 0xE7 +#define MAX_TID_VALUE (2 << 11) +#define TWOPOW11 (2 << 10) + +#define BLOCKACKPARAM_TID_POS 2 +#define BLOCKACKPARAM_AMSDU_SUPP_MASK 0x1 +#define BLOCKACKPARAM_WINSIZE_POS 6 +#define DELBA_TID_POS 12 +#define DELBA_INITIATOR_POS 11 +#define TYPE_DELBA_SENT 1 +#define TYPE_DELBA_RECEIVE 2 +#define IMMEDIATE_BLOCK_ACK 0x2 + +#define ADDBA_RSP_STATUS_ACCEPT 0 + +int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *, + u16 seqNum, + u16 tid, u8 *ta, + u8 pkttype, void *payload); +void mwifiex_11n_delete_ba_stream_tbl(struct mwifiex_private *priv, int Tid, + u8 *PeerMACAddr, u8 type, + int initiator); +void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv, + struct host_cmd_ds_11n_batimeout *event); +int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, + struct host_cmd_ds_command + *resp); +int mwifiex_cmd_11n_delba(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf); +int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, + struct host_cmd_ds_command + *cmd, void *data_buf); +int mwifiex_cmd_11n_addba_req(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf); +void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv); +struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct + mwifiex_private + *priv, int tid, + u8 *ta); + +#endif /* _MWIFIEX_11N_RXREORDER_H_ */ diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig new file mode 100644 index 000000000000..86962920cef3 --- /dev/null +++ b/drivers/net/wireless/mwifiex/Kconfig @@ -0,0 +1,21 @@ +config MWIFIEX + tristate "Marvell WiFi-Ex Driver" + depends on CFG80211 + select LIB80211 + ---help--- + This adds support for wireless adapters based on Marvell + 802.11n chipsets. + + If you choose to build it as a module, it will be called + mwifiex. + +config MWIFIEX_SDIO + tristate "Marvell WiFi-Ex Driver for SD8787" + depends on MWIFIEX && MMC + select FW_LOADER + ---help--- + This adds support for wireless adapters based on Marvell + 8787 chipset with SDIO interface. + + If you choose to build it as a module, it will be called + mwifiex_sdio. diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile new file mode 100644 index 000000000000..42cb733ea33a --- /dev/null +++ b/drivers/net/wireless/mwifiex/Makefile @@ -0,0 +1,41 @@ +# +# Copyright (C) 2011, Marvell International Ltd. +# +# This software file (the "File") is distributed by Marvell International +# Ltd. under the terms of the GNU General Public License Version 2, June 1991 +# (the "License"). You may use, redistribute and/or modify this File in +# accordance with the terms and conditions of the License, a copy of which +# is available by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the +# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. +# +# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE +# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE +# ARE EXPRESSLY DISCLAIMED. The License provides additional details about +# this warranty disclaimer. + + +mwifiex-y += main.o +mwifiex-y += init.o +mwifiex-y += cfp.o +mwifiex-y += cmdevt.o +mwifiex-y += util.o +mwifiex-y += txrx.o +mwifiex-y += wmm.o +mwifiex-y += 11n.o +mwifiex-y += 11n_aggr.o +mwifiex-y += 11n_rxreorder.o +mwifiex-y += scan.o +mwifiex-y += join.o +mwifiex-y += sta_ioctl.o +mwifiex-y += sta_cmd.o +mwifiex-y += sta_cmdresp.o +mwifiex-y += sta_event.o +mwifiex-y += sta_tx.o +mwifiex-y += sta_rx.o +mwifiex-y += cfg80211.o +mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o +obj-$(CONFIG_MWIFIEX) += mwifiex.o + +mwifiex_sdio-y += sdio.o +obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o diff --git a/drivers/net/wireless/mwifiex/README b/drivers/net/wireless/mwifiex/README new file mode 100644 index 000000000000..338377f7093b --- /dev/null +++ b/drivers/net/wireless/mwifiex/README @@ -0,0 +1,204 @@ +# Copyright (C) 2011, Marvell International Ltd. +# +# This software file (the "File") is distributed by Marvell International +# Ltd. under the terms of the GNU General Public License Version 2, June 1991 +# (the "License"). You may use, redistribute and/or modify this File in +# accordance with the terms and conditions of the License, a copy of which +# is available by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the +# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. +# +# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE +# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE +# ARE EXPRESSLY DISCLAIMED. The License provides additional details about +# this warranty disclaimer. + + +=============================================================================== + U S E R M A N U A L + +1) FOR DRIVER INSTALL + + a) Copy sd8787.bin to /lib/firmware/mrvl/ directory, + create the directory if it doesn't exist. + b) Install WLAN driver, + insmod mwifiex.ko + c) Uninstall WLAN driver, + ifconfig mlanX down + rmmod mwifiex + + +2) FOR DRIVER CONFIGURATION AND INFO + The configurations can be done either using the 'iw' user space + utility or debugfs. + + a) 'iw' utility commands + + Following are some useful iw commands:- + +iw dev mlan0 scan + + This command will trigger a scan. + The command will then display the scan table entries + +iw dev mlan0 connect -w [] [] [key 0:abcde d:1123456789a] + The above command can be used to connect to an AP with a particular SSID. + Ap's operating frequency can be specified or even the bssid. If the AP is using + WEP encryption, wep keys can be specified in the command. + Note: Every time before connecting to an AP scan command (iw dev mlan0 scan) should be used by user. + +iw dev mlan0 disconnect + This command will be used to disconnect from an AP. + + +iw dev mlan0 ibss join [fixed-freq] [fixed-bssid] [key 0:abcde] + The command will be used to join or create an ibss. Optionally, operating frequency, + bssid and the security related parameters can be specified while joining/creating + and ibss. + +iw dev mlan0 ibss leave + The command will be used to leave an ibss network. + +iw dev mlan0 link + The command will be used to get the connection status. The command will return parameters + such as SSID, operating frequency, rx/tx packets, signal strength, tx bitrate. + + Apart from the iw utility all standard configurations using the 'iwconfig' utility are also supported. + + b) Debugfs interface + + The debugfs interface can be used for configurations and for getting + some useful information from the driver. + The section below explains the configurations that can be + done. + + Mount debugfs to /debugfs mount point: + + mkdir /debugfs + mount -t debugfs debugfs /debugfs + + The information is provided in /debugfs/mwifiex/mlanX/: + +iw reg set + The command will be used to change the regulatory domain. + +iw reg get + The command will be used to get current regulatory domain. + +info + This command is used to get driver info. + + Usage: + cat info + + driver_name = "mwifiex" + driver_version = + interface_name = "mlanX" + bss_mode = "Ad-hoc" | "Managed" | "Auto" | "Unknown" + media_state = "Disconnected" | "Connected" + mac_address = <6-byte adapter MAC address> + multicase_count = + essid = + bssid = + channel = + region_code = + multicasr_address[n] = + num_tx_bytes = + num_rx_bytes = + num_tx_pkts = + num_rx_pkts = + num_tx_pkts_dropped = + num_rx_pkts_dropped = + num_tx_pkts_err = + num_rx_pkts_err = + carrier "on" | "off" + tx queue "stopped" | "started" + + The following debug info are provided in /debugfs/mwifiex/mlanX/debug: + + int_counter = + wmm_ac_vo = + wmm_ac_vi = + wmm_ac_be = + wmm_ac_bk = + max_tx_buf_size = + tx_buf_size = + curr_tx_buf_size = + ps_mode = <0/1, CAM mode/PS mode> + ps_state = <0/1/2/3, full power state/awake state/pre-sleep state/sleep state> + is_deep_sleep = <0/1, not deep sleep state/deep sleep state> + wakeup_dev_req = <0/1, wakeup device not required/required> + wakeup_tries = + hs_configured = <0/1, host sleep not configured/configured> + hs_activated = <0/1, extended host sleep not activated/activated> + num_tx_timeout = + num_cmd_timeout = + timeout_cmd_id = + timeout_cmd_act = + last_cmd_id = + last_cmd_act = + last_cmd_index = <0 based last command index> + last_cmd_resp_id = + last_cmd_resp_index = <0 based last command response index> + last_event = + last_event_index = <0 based last event index> + num_cmd_h2c_fail = + num_cmd_sleep_cfm_fail = + num_tx_h2c_fail = + num_evt_deauth = + num_evt_disassoc = + num_evt_link_lost = + num_cmd_deauth = + num_cmd_assoc_ok = + num_cmd_assoc_fail = + cmd_sent = <0/1, send command resources available/sending command to device> + data_sent = <0/1, send data resources available/sending data to device> + mp_rd_bitmap = + mp_wr_bitmap = + cmd_resp_received = <0/1, no cmd response to process/response received and yet to process> + event_received = <0/1, no event to process/event received and yet to process> + ioctl_pending = + tx_pending = + rx_pending = + + +3) FOR DRIVER CONFIGURATION + +regrdwr + This command is used to read/write the adapter register. + + Usage: + echo " [value]" > regrdwr + cat regrdwr + + where the parameters are, + : 1:MAC/SOC, 2:BBP, 3:RF, 4:PMIC, 5:CAU + : offset of register + [value]: value to be written + + Examples: + echo "1 0xa060" > regrdwr : Read the MAC register + echo "1 0xa060 0x12" > regrdwr : Write the MAC register + echo "1 0xa794 0x80000000" > regrdwr + : Write 0x80000000 to MAC register +rdeeprom + This command is used to read the EEPROM contents of the card. + + Usage: + echo " " > rdeeprom + cat rdeeprom + + where the parameters are, + : multiples of 4 + : 4-20, multiples of 4 + + Example: + echo "0 20" > rdeeprom : Read 20 bytes of EEPROM data from offset 0 + +getlog + This command is used to get the statistics available in the station. + Usage: + + cat getlog + +=============================================================================== diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c new file mode 100644 index 000000000000..80f367f27efc --- /dev/null +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -0,0 +1,1517 @@ +/* + * Marvell Wireless LAN device driver: CFG80211 + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "cfg80211.h" +#include "main.h" + +/* + * This function maps the nl802.11 channel type into driver channel type. + * + * The mapping is as follows - + * NL80211_CHAN_NO_HT -> NO_SEC_CHANNEL + * NL80211_CHAN_HT20 -> NO_SEC_CHANNEL + * NL80211_CHAN_HT40PLUS -> SEC_CHANNEL_ABOVE + * NL80211_CHAN_HT40MINUS -> SEC_CHANNEL_BELOW + * Others -> NO_SEC_CHANNEL + */ +static int +mwifiex_cfg80211_channel_type_to_mwifiex_channels(enum nl80211_channel_type + channel_type) +{ + int channel; + switch (channel_type) { + case NL80211_CHAN_NO_HT: + case NL80211_CHAN_HT20: + channel = NO_SEC_CHANNEL; + break; + case NL80211_CHAN_HT40PLUS: + channel = SEC_CHANNEL_ABOVE; + break; + case NL80211_CHAN_HT40MINUS: + channel = SEC_CHANNEL_BELOW; + break; + default: + channel = NO_SEC_CHANNEL; + } + return channel; +} + +/* + * This function maps the driver channel type into nl802.11 channel type. + * + * The mapping is as follows - + * NO_SEC_CHANNEL -> NL80211_CHAN_HT20 + * SEC_CHANNEL_ABOVE -> NL80211_CHAN_HT40PLUS + * SEC_CHANNEL_BELOW -> NL80211_CHAN_HT40MINUS + * Others -> NL80211_CHAN_HT20 + */ +static enum nl80211_channel_type +mwifiex_channels_to_cfg80211_channel_type(int channel_type) +{ + int channel; + switch (channel_type) { + case NO_SEC_CHANNEL: + channel = NL80211_CHAN_HT20; + break; + case SEC_CHANNEL_ABOVE: + channel = NL80211_CHAN_HT40PLUS; + break; + case SEC_CHANNEL_BELOW: + channel = NL80211_CHAN_HT40MINUS; + break; + default: + channel = NL80211_CHAN_HT20; + } + return channel; +} + +/* + * This function checks whether WEP is set. + */ +static int +mwifiex_is_alg_wep(u32 cipher) +{ + int alg = 0; + + switch (cipher) { + case MWIFIEX_ENCRYPTION_MODE_WEP40: + case MWIFIEX_ENCRYPTION_MODE_WEP104: + alg = 1; + break; + default: + alg = 0; + break; + } + return alg; +} + +/* + * This function maps the given cipher type into driver specific type. + * + * It also sets a flag to indicate whether WPA is enabled or not. + * + * The mapping table is - + * Input cipher Driver cipher type WPA enabled? + * ------------ ------------------ ------------ + * IW_AUTH_CIPHER_NONE MWIFIEX_ENCRYPTION_MODE_NONE No + * WLAN_CIPHER_SUITE_WEP40 MWIFIEX_ENCRYPTION_MODE_WEP40 No + * WLAN_CIPHER_SUITE_WEP104 MWIFIEX_ENCRYPTION_MODE_WEP104 No + * WLAN_CIPHER_SUITE_TKIP MWIFIEX_ENCRYPTION_MODE_TKIP Yes + * WLAN_CIPHER_SUITE_CCMP MWIFIEX_ENCRYPTION_MODE_CCMP Yes + * Others -1 No + */ +static int +mwifiex_get_mwifiex_cipher(u32 cipher, int *wpa_enabled) +{ + int encrypt_mode; + + if (wpa_enabled) + *wpa_enabled = 0; + switch (cipher) { + case IW_AUTH_CIPHER_NONE: + encrypt_mode = MWIFIEX_ENCRYPTION_MODE_NONE; + break; + case WLAN_CIPHER_SUITE_WEP40: + encrypt_mode = MWIFIEX_ENCRYPTION_MODE_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + encrypt_mode = MWIFIEX_ENCRYPTION_MODE_WEP104; + break; + case WLAN_CIPHER_SUITE_TKIP: + encrypt_mode = MWIFIEX_ENCRYPTION_MODE_TKIP; + if (wpa_enabled) + *wpa_enabled = 1; + break; + case WLAN_CIPHER_SUITE_CCMP: + encrypt_mode = MWIFIEX_ENCRYPTION_MODE_CCMP; + if (wpa_enabled) + *wpa_enabled = 1; + break; + default: + encrypt_mode = -1; + } + + return encrypt_mode; +} + +/* + * This function retrieves the private structure from kernel wiphy structure. + */ +static void *mwifiex_cfg80211_get_priv(struct wiphy *wiphy) +{ + return (void *) (*(unsigned long *) wiphy_priv(wiphy)); +} + +/* + * CFG802.11 operation handler to delete a network key. + */ +static int +mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, + u8 key_index, bool pairwise, const u8 *mac_addr) +{ + struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + int ret = 0; + + ret = mwifiex_set_encode(priv, NULL, 0, key_index, 1); + if (ret) { + wiphy_err(wiphy, "deleting the crypto keys\n"); + return -EFAULT; + } + + wiphy_dbg(wiphy, "info: crypto keys deleted\n"); + return 0; +} + +/* + * CFG802.11 operation handler to set Tx power. + */ +static int +mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, + enum nl80211_tx_power_setting type, + int dbm) +{ + int ret = 0; + struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + + ret = mwifiex_set_tx_power(priv, type, dbm); + + return ret; +} + +/* + * CFG802.11 operation handler to set Power Save option. + * + * The timeout value, if provided, is currently ignored. + */ +static int +mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, + bool enabled, int timeout) +{ + int ret = 0; + struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + + if (timeout) + wiphy_dbg(wiphy, + "info: ignoring the timeout value" + " for IEEE power save\n"); + + ret = mwifiex_drv_set_power(priv, enabled); + + return ret; +} + +/* + * CFG802.11 operation handler to set the default network key. + */ +static int +mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, + u8 key_index, bool unicast, + bool multicast) +{ + struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + int ret; + + ret = mwifiex_set_encode(priv, NULL, 0, key_index, 0); + + wiphy_dbg(wiphy, "info: set default Tx key index\n"); + + if (ret) + return -EFAULT; + + return 0; +} + +/* + * CFG802.11 operation handler to add a network key. + */ +static int +mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, + u8 key_index, bool pairwise, const u8 *mac_addr, + struct key_params *params) +{ + struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + int ret = 0; + int encrypt_mode; + + encrypt_mode = mwifiex_get_mwifiex_cipher(params->cipher, NULL); + + if (encrypt_mode != -1) + ret = mwifiex_set_encode(priv, params->key, params->key_len, + key_index, 0); + + wiphy_dbg(wiphy, "info: crypto keys added\n"); + + if (ret) + return -EFAULT; + + return 0; +} + +/* + * This function sends domain information to the firmware. + * + * The following information are passed to the firmware - + * - Country codes + * - Sub bands (first channel, number of channels, maximum Tx power) + */ +static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) +{ + u8 no_of_triplet = 0; + struct ieee80211_country_ie_triplet *t; + u8 no_of_parsed_chan = 0; + u8 first_chan = 0, next_chan = 0, max_pwr = 0; + u8 i, flag = 0; + enum ieee80211_band band; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg; + int ret = 0; + + /* Set country code */ + domain_info->country_code[0] = priv->country_code[0]; + domain_info->country_code[1] = priv->country_code[1]; + domain_info->country_code[2] = ' '; + + band = mwifiex_band_to_radio_type(adapter->config_bands); + if (!wiphy->bands[band]) { + wiphy_err(wiphy, "11D: setting domain info in FW\n"); + return -1; + } + + sband = wiphy->bands[band]; + + for (i = 0; i < sband->n_channels ; i++) { + ch = &sband->channels[i]; + if (ch->flags & IEEE80211_CHAN_DISABLED) + continue; + + if (!flag) { + flag = 1; + first_chan = (u32) ch->hw_value; + next_chan = first_chan; + max_pwr = ch->max_power; + no_of_parsed_chan = 1; + continue; + } + + if (ch->hw_value == next_chan + 1 && + ch->max_power == max_pwr) { + next_chan++; + no_of_parsed_chan++; + } else { + t = &domain_info->triplet[no_of_triplet]; + t->chans.first_channel = first_chan; + t->chans.num_channels = no_of_parsed_chan; + t->chans.max_power = max_pwr; + no_of_triplet++; + first_chan = (u32) ch->hw_value; + next_chan = first_chan; + max_pwr = ch->max_power; + no_of_parsed_chan = 1; + } + } + + if (flag) { + t = &domain_info->triplet[no_of_triplet]; + t->chans.first_channel = first_chan; + t->chans.num_channels = no_of_parsed_chan; + t->chans.max_power = max_pwr; + no_of_triplet++; + } + + domain_info->no_of_triplet = no_of_triplet; + /* Send cmd to FW to set domain info */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, + HostCmd_ACT_GEN_SET, 0, NULL, NULL); + if (ret) + wiphy_err(wiphy, "11D: setting domain info in FW\n"); + + return ret; +} + +/* + * CFG802.11 regulatory domain callback function. + * + * This function is called when the regulatory domain is changed due to the + * following reasons - + * - Set by driver + * - Set by system core + * - Set by user + * - Set bt Country IE + */ +static int mwifiex_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + + wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for domain" + " %c%c\n", request->alpha2[0], request->alpha2[1]); + + memcpy(priv->country_code, request->alpha2, sizeof(request->alpha2)); + + switch (request->initiator) { + case NL80211_REGDOM_SET_BY_DRIVER: + case NL80211_REGDOM_SET_BY_CORE: + case NL80211_REGDOM_SET_BY_USER: + break; + /* Todo: apply driver specific changes in channel flags based + on the request initiator if necessary. */ + case NL80211_REGDOM_SET_BY_COUNTRY_IE: + break; + } + mwifiex_send_domain_info_cmd_fw(wiphy); + + return 0; +} + +/* + * This function sets the RF channel. + * + * This function creates multiple IOCTL requests, populates them accordingly + * and issues them to set the band/channel and frequency. + */ +static int +mwifiex_set_rf_channel(struct mwifiex_private *priv, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) +{ + struct mwifiex_chan_freq_power cfp; + int ret = 0; + int status = 0; + struct mwifiex_ds_band_cfg band_cfg; + int mode; + u8 wait_option = MWIFIEX_IOCTL_WAIT; + u32 config_bands = 0; + struct wiphy *wiphy = priv->wdev->wiphy; + + mode = mwifiex_drv_get_mode(priv, wait_option); + + if (chan) { + memset(&band_cfg, 0, sizeof(band_cfg)); + /* Set appropriate bands */ + if (chan->band == IEEE80211_BAND_2GHZ) + config_bands = BAND_B | BAND_G | BAND_GN; + else + config_bands = BAND_AN | BAND_A; + if (mode == MWIFIEX_BSS_MODE_INFRA + || mode == MWIFIEX_BSS_MODE_AUTO) { + band_cfg.config_bands = config_bands; + } else if (mode == MWIFIEX_BSS_MODE_IBSS) { + band_cfg.config_bands = config_bands; + band_cfg.adhoc_start_band = config_bands; + } + /* Set channel offset */ + band_cfg.sec_chan_offset = + mwifiex_cfg80211_channel_type_to_mwifiex_channels + (channel_type); + status = mwifiex_radio_ioctl_band_cfg(priv, HostCmd_ACT_GEN_SET, + &band_cfg); + + if (status) + return -EFAULT; + mwifiex_send_domain_info_cmd_fw(wiphy); + } + + wiphy_dbg(wiphy, "info: setting band %d, channel offset %d and " + "mode %d\n", config_bands, band_cfg.sec_chan_offset, mode); + if (!chan) + return ret; + + memset(&cfp, 0, sizeof(cfp)); + cfp.freq = chan->center_freq; + /* Convert frequency to channel */ + cfp.channel = ieee80211_frequency_to_channel(chan->center_freq); + + status = mwifiex_bss_ioctl_channel(priv, HostCmd_ACT_GEN_SET, &cfp); + if (status) + return -EFAULT; + + ret = mwifiex_drv_change_adhoc_chan(priv, cfp.channel); + + return ret; +} + +/* + * CFG802.11 operation handler to set channel. + * + * This function can only be used when station is not connected. + */ +static int +mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) +{ + struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + + if (priv->media_connected) { + wiphy_err(wiphy, "This setting is valid only when station " + "is not connected\n"); + return -EINVAL; + } + + return mwifiex_set_rf_channel(priv, chan, channel_type); +} + +/* + * This function sets the fragmentation threshold. + * + * This function creates an IOCTL request, populates it accordingly + * and issues an IOCTL. + * + * The fragmentation threshold value must lies between MWIFIEX_FRAG_MIN_VALUE + * and MWIFIEX_FRAG_MAX_VALUE. + */ +static int +mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) +{ + int ret = 0; + int status = 0; + struct mwifiex_wait_queue *wait = NULL; + u8 wait_option = MWIFIEX_IOCTL_WAIT; + + if (frag_thr < MWIFIEX_FRAG_MIN_VALUE + || frag_thr > MWIFIEX_FRAG_MAX_VALUE) + return -EINVAL; + + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + status = mwifiex_snmp_mib_ioctl(priv, wait, FRAG_THRESH_I, + HostCmd_ACT_GEN_SET, &frag_thr); + + if (mwifiex_request_ioctl(priv, wait, status, wait_option)) + ret = -EFAULT; + + kfree(wait); + return ret; +} + +/* + * This function sets the RTS threshold. + * + * This function creates an IOCTL request, populates it accordingly + * and issues an IOCTL. + */ +static int +mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr) +{ + int ret = 0; + struct mwifiex_wait_queue *wait = NULL; + int status = 0; + u8 wait_option = MWIFIEX_IOCTL_WAIT; + + if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE) + rts_thr = MWIFIEX_RTS_MAX_VALUE; + + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + status = mwifiex_snmp_mib_ioctl(priv, wait, RTS_THRESH_I, + HostCmd_ACT_GEN_SET, &rts_thr); + + if (mwifiex_request_ioctl(priv, wait, status, wait_option)) + ret = -EFAULT; + + kfree(wait); + return ret; +} + +/* + * CFG802.11 operation handler to set wiphy parameters. + * + * This function can be used to set the RTS threshold and the + * Fragmentation threshold of the driver. + */ +static int +mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + + int ret = 0; + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) + ret = mwifiex_set_rts(priv, wiphy->rts_threshold); + + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) + ret = mwifiex_set_frag(priv, wiphy->frag_threshold); + + return ret; +} + +/* + * CFG802.11 operation handler to change interface type. + * + * This function creates an IOCTL request, populates it accordingly + * and issues an IOCTL. + * + * The function also maps the CFG802.11 mode type into driver mode type. + * NL80211_IFTYPE_ADHOC -> MWIFIEX_BSS_MODE_IBSS + * NL80211_IFTYPE_STATION -> MWIFIEX_BSS_MODE_INFRA + * NL80211_IFTYPE_UNSPECIFIED -> MWIFIEX_BSS_MODE_AUTO + */ +static int +mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, + struct net_device *dev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + int ret = 0; + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + int mode = -1; + struct mwifiex_wait_queue *wait = NULL; + int status = 0; + + wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); + if (!wait) + return -ENOMEM; + + switch (type) { + case NL80211_IFTYPE_ADHOC: + mode = MWIFIEX_BSS_MODE_IBSS; + dev->ieee80211_ptr->iftype = NL80211_IFTYPE_ADHOC; + wiphy_dbg(wiphy, "info: setting interface type to adhoc\n"); + break; + case NL80211_IFTYPE_STATION: + mode = MWIFIEX_BSS_MODE_INFRA; + dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; + wiphy_dbg(wiphy, "info: Setting interface type to managed\n"); + break; + case NL80211_IFTYPE_UNSPECIFIED: + mode = MWIFIEX_BSS_MODE_AUTO; + dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; + wiphy_dbg(wiphy, "info: setting interface type to auto\n"); + break; + default: + ret = -EINVAL; + } + if (ret) + goto done; + status = mwifiex_bss_ioctl_mode(priv, wait, HostCmd_ACT_GEN_SET, &mode); + + if (mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT)) + ret = -EFAULT; + +done: + kfree(wait); + return ret; +} + +/* + * This function dumps the station information on a buffer. + * + * The following information are shown - + * - Total bytes transmitted + * - Total bytes received + * - Total packets transmitted + * - Total packets received + * - Signal quality level + * - Transmission rate + */ +static int +mwifiex_dump_station_info(struct mwifiex_private *priv, + struct station_info *sinfo) +{ + struct mwifiex_ds_get_signal signal; + struct mwifiex_rate_cfg rate; + int ret = 0; + + sinfo->filled = STATION_INFO_RX_BYTES | STATION_INFO_TX_BYTES | + STATION_INFO_RX_PACKETS | + STATION_INFO_TX_PACKETS + | STATION_INFO_SIGNAL | STATION_INFO_TX_BITRATE; + + /* Get signal information from the firmware */ + memset(&signal, 0, sizeof(struct mwifiex_ds_get_signal)); + if (mwifiex_get_signal_info(priv, MWIFIEX_IOCTL_WAIT, &signal)) { + dev_err(priv->adapter->dev, "getting signal information\n"); + ret = -EFAULT; + } + + if (mwifiex_drv_get_data_rate(priv, &rate)) { + dev_err(priv->adapter->dev, "getting data rate\n"); + ret = -EFAULT; + } + + sinfo->rx_bytes = priv->stats.rx_bytes; + sinfo->tx_bytes = priv->stats.tx_bytes; + sinfo->rx_packets = priv->stats.rx_packets; + sinfo->tx_packets = priv->stats.tx_packets; + sinfo->signal = priv->w_stats.qual.level; + sinfo->txrate.legacy = rate.rate; + + return ret; +} + +/* + * CFG802.11 operation handler to get station information. + * + * This function only works in connected mode, and dumps the + * requested station information, if available. + */ +static int +mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_info *sinfo) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + int ret = 0; + + mwifiex_dump_station_info(priv, sinfo); + + if (!priv->media_connected) + return -ENOENT; + if (memcmp(mac, priv->cfg_bssid, ETH_ALEN)) + return -ENOENT; + + + ret = mwifiex_dump_station_info(priv, sinfo); + + return ret; +} + +/* Supported rates to be advertised to the cfg80211 */ + +static struct ieee80211_rate mwifiex_rates[] = { + {.bitrate = 10, .hw_value = 2, }, + {.bitrate = 20, .hw_value = 4, }, + {.bitrate = 55, .hw_value = 11, }, + {.bitrate = 110, .hw_value = 22, }, + {.bitrate = 220, .hw_value = 44, }, + {.bitrate = 60, .hw_value = 12, }, + {.bitrate = 90, .hw_value = 18, }, + {.bitrate = 120, .hw_value = 24, }, + {.bitrate = 180, .hw_value = 36, }, + {.bitrate = 240, .hw_value = 48, }, + {.bitrate = 360, .hw_value = 72, }, + {.bitrate = 480, .hw_value = 96, }, + {.bitrate = 540, .hw_value = 108, }, + {.bitrate = 720, .hw_value = 144, }, +}; + +/* Channel definitions to be advertised to cfg80211 */ + +static struct ieee80211_channel mwifiex_channels_2ghz[] = { + {.center_freq = 2412, .hw_value = 1, }, + {.center_freq = 2417, .hw_value = 2, }, + {.center_freq = 2422, .hw_value = 3, }, + {.center_freq = 2427, .hw_value = 4, }, + {.center_freq = 2432, .hw_value = 5, }, + {.center_freq = 2437, .hw_value = 6, }, + {.center_freq = 2442, .hw_value = 7, }, + {.center_freq = 2447, .hw_value = 8, }, + {.center_freq = 2452, .hw_value = 9, }, + {.center_freq = 2457, .hw_value = 10, }, + {.center_freq = 2462, .hw_value = 11, }, + {.center_freq = 2467, .hw_value = 12, }, + {.center_freq = 2472, .hw_value = 13, }, + {.center_freq = 2484, .hw_value = 14, }, +}; + +static struct ieee80211_supported_band mwifiex_band_2ghz = { + .channels = mwifiex_channels_2ghz, + .n_channels = ARRAY_SIZE(mwifiex_channels_2ghz), + .bitrates = mwifiex_rates, + .n_bitrates = 14, +}; + +static struct ieee80211_channel mwifiex_channels_5ghz[] = { + {.center_freq = 5040, .hw_value = 8, }, + {.center_freq = 5060, .hw_value = 12, }, + {.center_freq = 5080, .hw_value = 16, }, + {.center_freq = 5170, .hw_value = 34, }, + {.center_freq = 5190, .hw_value = 38, }, + {.center_freq = 5210, .hw_value = 42, }, + {.center_freq = 5230, .hw_value = 46, }, + {.center_freq = 5180, .hw_value = 36, }, + {.center_freq = 5200, .hw_value = 40, }, + {.center_freq = 5220, .hw_value = 44, }, + {.center_freq = 5240, .hw_value = 48, }, + {.center_freq = 5260, .hw_value = 52, }, + {.center_freq = 5280, .hw_value = 56, }, + {.center_freq = 5300, .hw_value = 60, }, + {.center_freq = 5320, .hw_value = 64, }, + {.center_freq = 5500, .hw_value = 100, }, + {.center_freq = 5520, .hw_value = 104, }, + {.center_freq = 5540, .hw_value = 108, }, + {.center_freq = 5560, .hw_value = 112, }, + {.center_freq = 5580, .hw_value = 116, }, + {.center_freq = 5600, .hw_value = 120, }, + {.center_freq = 5620, .hw_value = 124, }, + {.center_freq = 5640, .hw_value = 128, }, + {.center_freq = 5660, .hw_value = 132, }, + {.center_freq = 5680, .hw_value = 136, }, + {.center_freq = 5700, .hw_value = 140, }, + {.center_freq = 5745, .hw_value = 149, }, + {.center_freq = 5765, .hw_value = 153, }, + {.center_freq = 5785, .hw_value = 157, }, + {.center_freq = 5805, .hw_value = 161, }, + {.center_freq = 5825, .hw_value = 165, }, +}; + +static struct ieee80211_supported_band mwifiex_band_5ghz = { + .channels = mwifiex_channels_5ghz, + .n_channels = ARRAY_SIZE(mwifiex_channels_5ghz), + .bitrates = mwifiex_rates - 4, + .n_bitrates = ARRAY_SIZE(mwifiex_rates) + 4, +}; + + +/* Supported crypto cipher suits to be advertised to cfg80211 */ + +static const u32 mwifiex_cipher_suites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, +}; + +/* + * CFG802.11 operation handler for disconnection request. + * + * This function does not work when there is already a disconnection + * procedure going on. + */ +static int +mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, + u16 reason_code) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + if (priv->disconnect) + return -EBUSY; + + priv->disconnect = 1; + if (mwifiex_disconnect(priv, MWIFIEX_IOCTL_WAIT, NULL)) + return -EFAULT; + + wiphy_dbg(wiphy, "info: successfully disconnected from %pM:" + " reason code %d\n", priv->cfg_bssid, reason_code); + + queue_work(priv->workqueue, &priv->cfg_workqueue); + + return 0; +} + +/* + * This function informs the CFG802.11 subsystem of a new IBSS. + * + * The following information are sent to the CFG802.11 subsystem + * to register the new IBSS. If we do not register the new IBSS, + * a kernel panic will result. + * - SSID + * - SSID length + * - BSSID + * - Channel + */ +static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) +{ + int ret = 0; + struct ieee80211_channel *chan; + struct mwifiex_bss_info bss_info; + int ie_len = 0; + u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)]; + + ret = mwifiex_get_bss_info(priv, &bss_info); + if (ret) + return ret; + + ie_buf[0] = WLAN_EID_SSID; + ie_buf[1] = bss_info.ssid.ssid_len; + + memcpy(&ie_buf[sizeof(struct ieee_types_header)], + &bss_info.ssid.ssid, + bss_info.ssid.ssid_len); + ie_len = ie_buf[1] + sizeof(struct ieee_types_header); + + chan = __ieee80211_get_channel(priv->wdev->wiphy, + ieee80211_channel_to_frequency(bss_info.bss_chan, + priv->curr_bss_params.band)); + + cfg80211_inform_bss(priv->wdev->wiphy, chan, + bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, + 0, ie_buf, ie_len, 0, GFP_KERNEL); + memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); + + return ret; +} + +/* + * This function informs the CFG802.11 subsystem of a new BSS connection. + * + * The following information are sent to the CFG802.11 subsystem + * to register the new BSS connection. If we do not register the new BSS, + * a kernel panic will result. + * - MAC address + * - Capabilities + * - Beacon period + * - RSSI value + * - Channel + * - Supported rates IE + * - Extended capabilities IE + * - DS parameter set IE + * - HT Capability IE + * - Vendor Specific IE (221) + * - WPA IE + * - RSN IE + */ +static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, + struct mwifiex_802_11_ssid *ssid) +{ + struct mwifiex_scan_resp scan_resp; + struct mwifiex_bssdescriptor *scan_table; + int i, j; + struct ieee80211_channel *chan; + u8 *ie, *tmp, *ie_buf; + u32 ie_len; + u64 ts = 0; + u8 *beacon; + int beacon_size; + u8 element_id, element_len; + + memset(&scan_resp, 0, sizeof(scan_resp)); + if (mwifiex_get_scan_table(priv, MWIFIEX_IOCTL_WAIT, &scan_resp)) + return -EFAULT; + +#define MAX_IE_BUF 2048 + ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL); + if (!ie_buf) { + dev_err(priv->adapter->dev, "%s: failed to alloc ie_buf\n", + __func__); + return -ENOMEM; + } + + scan_table = (struct mwifiex_bssdescriptor *) scan_resp.scan_table; + for (i = 0; i < scan_resp.num_in_scan_table; i++) { + if (ssid) { + /* Inform specific BSS only */ + if (memcmp(ssid->ssid, scan_table[i].ssid.ssid, + ssid->ssid_len)) + continue; + } + memset(ie_buf, 0, MAX_IE_BUF); + ie_buf[0] = WLAN_EID_SSID; + ie_buf[1] = scan_table[i].ssid.ssid_len; + memcpy(&ie_buf[sizeof(struct ieee_types_header)], + scan_table[i].ssid.ssid, ie_buf[1]); + + ie = ie_buf + ie_buf[1] + sizeof(struct ieee_types_header); + ie_len = ie_buf[1] + sizeof(struct ieee_types_header); + + ie[0] = WLAN_EID_SUPP_RATES; + + for (j = 0; j < sizeof(scan_table[i].supported_rates); j++) { + if (!scan_table[i].supported_rates[j]) + break; + else + ie[j + sizeof(struct ieee_types_header)] = + scan_table[i].supported_rates[j]; + } + + ie[1] = j; + ie_len += ie[1] + sizeof(struct ieee_types_header); + + beacon = scan_table[i].beacon_buf; + beacon_size = scan_table[i].beacon_buf_size; + + /* Skip time stamp, beacon interval and capability */ + + if (beacon) { + beacon += sizeof(scan_table[i].beacon_period) + + sizeof(scan_table[i].time_stamp) + + +sizeof(scan_table[i].cap_info_bitmap); + + beacon_size -= sizeof(scan_table[i].beacon_period) + + sizeof(scan_table[i].time_stamp) + + sizeof(scan_table[i].cap_info_bitmap); + } + + while (beacon_size >= sizeof(struct ieee_types_header)) { + ie = ie_buf + ie_len; + element_id = *beacon; + element_len = *(beacon + 1); + if (beacon_size < (int) element_len + + sizeof(struct ieee_types_header)) { + dev_err(priv->adapter->dev, "%s: in processing" + " IE, bytes left < IE length\n", + __func__); + break; + } + switch (element_id) { + case WLAN_EID_EXT_CAPABILITY: + case WLAN_EID_DS_PARAMS: + case WLAN_EID_HT_CAPABILITY: + case WLAN_EID_VENDOR_SPECIFIC: + case WLAN_EID_RSN: + case WLAN_EID_BSS_AC_ACCESS_DELAY: + ie[0] = element_id; + ie[1] = element_len; + tmp = (u8 *) beacon; + memcpy(&ie[sizeof(struct ieee_types_header)], + tmp + sizeof(struct ieee_types_header), + element_len); + ie_len += ie[1] + + sizeof(struct ieee_types_header); + break; + default: + break; + } + beacon += element_len + + sizeof(struct ieee_types_header); + beacon_size -= element_len + + sizeof(struct ieee_types_header); + } + chan = ieee80211_get_channel(priv->wdev->wiphy, + scan_table[i].freq); + cfg80211_inform_bss(priv->wdev->wiphy, chan, + scan_table[i].mac_address, + ts, scan_table[i].cap_info_bitmap, + scan_table[i].beacon_period, + ie_buf, ie_len, + scan_table[i].rssi, GFP_KERNEL); + } + + kfree(ie_buf); + return 0; +} + +/* + * This function connects with a BSS. + * + * This function handles both Infra and Ad-Hoc modes. It also performs + * validity checking on the provided parameters, disconnects from the + * current BSS (if any), sets up the association/scan parameters, + * including security settings, and performs specific SSID scan before + * trying to connect. + * + * For Infra mode, the function returns failure if the specified SSID + * is not found in scan table. However, for Ad-Hoc mode, it can create + * the IBSS if it does not exist. On successful completion in either case, + * the function notifies the CFG802.11 subsystem of the new BSS connection, + * otherwise the kernel will panic. + */ +static int +mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, + u8 *bssid, int mode, struct ieee80211_channel *channel, + struct cfg80211_connect_params *sme, bool privacy) +{ + struct mwifiex_802_11_ssid req_ssid; + struct mwifiex_ssid_bssid ssid_bssid; + int ret = 0; + int auth_type = 0, pairwise_encrypt_mode = 0, wpa_enabled = 0; + int group_encrypt_mode = 0; + int alg_is_wep = 0; + + memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid)); + memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); + + req_ssid.ssid_len = ssid_len; + if (ssid_len > IEEE80211_MAX_SSID_LEN) { + dev_err(priv->adapter->dev, "invalid SSID - aborting\n"); + return -EINVAL; + } + + memcpy(req_ssid.ssid, ssid, ssid_len); + if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) { + dev_err(priv->adapter->dev, "invalid SSID - aborting\n"); + return -EINVAL; + } + + /* disconnect before try to associate */ + mwifiex_disconnect(priv, MWIFIEX_IOCTL_WAIT, NULL); + + if (channel) + ret = mwifiex_set_rf_channel(priv, channel, + mwifiex_channels_to_cfg80211_channel_type + (priv->adapter->chan_offset)); + + ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); /* Disable keys */ + + if (mode == MWIFIEX_BSS_MODE_IBSS) { + /* "privacy" is set only for ad-hoc mode */ + if (privacy) { + /* + * Keep MWIFIEX_ENCRYPTION_MODE_WEP104 for now so that + * the firmware can find a matching network from the + * scan. The cfg80211 does not give us the encryption + * mode at this stage so just setting it to WEP here. + */ + wpa_enabled = 0; + auth_type = MWIFIEX_AUTH_MODE_OPEN; + ret = mwifiex_set_auth(priv, + MWIFIEX_ENCRYPTION_MODE_WEP104, + auth_type, wpa_enabled); + } + + goto done; + } + + /* Now handle infra mode. "sme" is valid for infra mode only */ + if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC + || sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) + auth_type = MWIFIEX_AUTH_MODE_OPEN; + else if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) + auth_type = MWIFIEX_AUTH_MODE_SHARED; + + if (sme->crypto.n_ciphers_pairwise) { + pairwise_encrypt_mode = mwifiex_get_mwifiex_cipher(sme->crypto. + ciphers_pairwise[0], &wpa_enabled); + ret = mwifiex_set_auth(priv, pairwise_encrypt_mode, auth_type, + wpa_enabled); + } + + if (sme->crypto.cipher_group) { + group_encrypt_mode = mwifiex_get_mwifiex_cipher(sme->crypto. + cipher_group, &wpa_enabled); + ret = mwifiex_set_auth(priv, group_encrypt_mode, auth_type, + wpa_enabled); + } + if (sme->ie) + ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len); + + if (sme->key) { + alg_is_wep = mwifiex_is_alg_wep(pairwise_encrypt_mode) + | mwifiex_is_alg_wep(group_encrypt_mode); + if (alg_is_wep) { + dev_dbg(priv->adapter->dev, + "info: setting wep encryption" + " with key len %d\n", sme->key_len); + ret = mwifiex_set_encode(priv, sme->key, sme->key_len, + sme->key_idx, 0); + } + } +done: + /* Do specific SSID scanning */ + if (mwifiex_request_scan(priv, MWIFIEX_IOCTL_WAIT, &req_ssid)) { + dev_err(priv->adapter->dev, "scan error\n"); + return -EFAULT; + } + + + memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid)); + + if (mode != MWIFIEX_BSS_MODE_IBSS) { + if (mwifiex_find_best_bss(priv, MWIFIEX_IOCTL_WAIT, + &ssid_bssid)) + return -EFAULT; + /* Inform the BSS information to kernel, otherwise + * kernel will give a panic after successful assoc */ + if (mwifiex_inform_bss_from_scan_result(priv, &req_ssid)) + return -EFAULT; + } + + dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n", + (char *) req_ssid.ssid, ssid_bssid.bssid); + + memcpy(&priv->cfg_bssid, ssid_bssid.bssid, 6); + + /* Connect to BSS by ESSID */ + memset(&ssid_bssid.bssid, 0, ETH_ALEN); + + if (mwifiex_bss_start(priv, MWIFIEX_IOCTL_WAIT, &ssid_bssid)) + return -EFAULT; + + if (mode == MWIFIEX_BSS_MODE_IBSS) { + /* Inform the BSS information to kernel, otherwise + * kernel will give a panic after successful assoc */ + if (mwifiex_cfg80211_inform_ibss_bss(priv)) + return -EFAULT; + } + + return ret; +} + +/* + * CFG802.11 operation handler for association request. + * + * This function does not work when the current mode is set to Ad-Hoc, or + * when there is already an association procedure going on. The given BSS + * information is used to associate. + */ +static int +mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *sme) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + int ret = 0; + int mode = 0; + + if (priv->assoc_request) + return -EBUSY; + + mode = mwifiex_drv_get_mode(priv, MWIFIEX_IOCTL_WAIT); + + if (mode == MWIFIEX_BSS_MODE_IBSS) { + wiphy_err(wiphy, "received infra assoc request " + "when station is in ibss mode\n"); + goto done; + } + + priv->assoc_request = 1; + + wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", + (char *) sme->ssid, sme->bssid); + + ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, + mode, sme->channel, sme, 0); + +done: + priv->assoc_result = ret; + queue_work(priv->workqueue, &priv->cfg_workqueue); + return ret; +} + +/* + * CFG802.11 operation handler to join an IBSS. + * + * This function does not work in any mode other than Ad-Hoc, or if + * a join operation is already in progress. + */ +static int +mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *params) +{ + struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + int ret = 0; + int mode = 0; + + if (priv->ibss_join_request) + return -EBUSY; + + mode = mwifiex_drv_get_mode(priv, MWIFIEX_IOCTL_WAIT); + if (mode != MWIFIEX_BSS_MODE_IBSS) { + wiphy_err(wiphy, "request to join ibss received " + "when station is not in ibss mode\n"); + goto done; + } + + priv->ibss_join_request = 1; + + wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n", + (char *) params->ssid, params->bssid); + + ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid, + params->bssid, mode, params->channel, NULL, + params->privacy); +done: + priv->ibss_join_result = ret; + queue_work(priv->workqueue, &priv->cfg_workqueue); + return ret; +} + +/* + * CFG802.11 operation handler to leave an IBSS. + * + * This function does not work if a leave operation is + * already in progress. + */ +static int +mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +{ + struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + + if (priv->disconnect) + return -EBUSY; + + priv->disconnect = 1; + + wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n", + priv->cfg_bssid); + if (mwifiex_disconnect(priv, MWIFIEX_IOCTL_WAIT, NULL)) + return -EFAULT; + + queue_work(priv->workqueue, &priv->cfg_workqueue); + + return 0; +} + +/* + * CFG802.11 operation handler for scan request. + * + * This function issues a scan request to the firmware based upon + * the user specified scan configuration. On successfull completion, + * it also informs the results. + */ +static int +mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_scan_request *request) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); + + if (priv->scan_request && priv->scan_request != request) + return -EBUSY; + + priv->scan_request = request; + + queue_work(priv->workqueue, &priv->cfg_workqueue); + return 0; +} + +/* + * This function sets up the CFG802.11 specific HT capability fields + * with default values. + * + * The following default values are set - + * - HT Supported = True + * - Maximum AMPDU length factor = 0x3 + * - Minimum AMPDU spacing = 0x6 + * - HT Capabilities map = IEEE80211_HT_CAP_SUP_WIDTH_20_40 (0x0002) + * - MCS information, Rx mask = 0xff + * - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01) + */ +static void +mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, + struct mwifiex_private *priv) +{ + int rx_mcs_supp; + struct ieee80211_mcs_info mcs_set; + u8 *mcs = (u8 *)&mcs_set; + struct mwifiex_adapter *adapter = priv->adapter; + + ht_info->ht_supported = true; + ht_info->ampdu_factor = 0x3; + ht_info->ampdu_density = 0x6; + + memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); + ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40; + + rx_mcs_supp = GET_RXMCSSUPP(priv->adapter->hw_dev_mcs_support); + /* Set MCS for 1x1 */ + memset(mcs, 0xff, rx_mcs_supp); + /* Clear all the other values */ + memset(&mcs[rx_mcs_supp], 0, + sizeof(struct ieee80211_mcs_info) - rx_mcs_supp); + if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA || + (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap) && + ISSUPP_CHANWIDTH40(adapter->usr_dot_11n_dev_cap))) + /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ + SETHT_MCS32(mcs_set.rx_mask); + + memcpy((u8 *) &ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info)); + + ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; +} + +/* station cfg80211 operations */ +static struct cfg80211_ops mwifiex_cfg80211_ops = { + .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf, + .scan = mwifiex_cfg80211_scan, + .connect = mwifiex_cfg80211_connect, + .disconnect = mwifiex_cfg80211_disconnect, + .get_station = mwifiex_cfg80211_get_station, + .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, + .set_channel = mwifiex_cfg80211_set_channel, + .join_ibss = mwifiex_cfg80211_join_ibss, + .leave_ibss = mwifiex_cfg80211_leave_ibss, + .add_key = mwifiex_cfg80211_add_key, + .del_key = mwifiex_cfg80211_del_key, + .set_default_key = mwifiex_cfg80211_set_default_key, + .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, + .set_tx_power = mwifiex_cfg80211_set_tx_power, +}; + +/* + * This function registers the device with CFG802.11 subsystem. + * + * The function creates the wireless device/wiphy, populates it with + * default parameters and handler function pointers, and finally + * registers the device. + */ +int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, + struct mwifiex_private *priv) +{ + int ret = 0; + void *wdev_priv = NULL; + struct wireless_dev *wdev; + + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!wdev) { + dev_err(priv->adapter->dev, "%s: allocating wireless device\n", + __func__); + return -ENOMEM; + } + wdev->wiphy = + wiphy_new(&mwifiex_cfg80211_ops, + sizeof(struct mwifiex_private *)); + if (!wdev->wiphy) + return -ENOMEM; + wdev->iftype = NL80211_IFTYPE_STATION; + wdev->wiphy->max_scan_ssids = 10; + wdev->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; + wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; + + /* Initialize cipher suits */ + wdev->wiphy->cipher_suites = mwifiex_cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); + + /* Initialize parameters for 2GHz band */ + + mwifiex_setup_ht_caps(&wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, + priv); + mwifiex_setup_ht_caps(&wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, + priv); + + memcpy(wdev->wiphy->perm_addr, mac, 6); + wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + + /* We are using custom domains */ + wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + + wdev->wiphy->reg_notifier = mwifiex_reg_notifier; + + /* Set struct mwifiex_private pointer in wiphy_priv */ + wdev_priv = wiphy_priv(wdev->wiphy); + + *(unsigned long *) wdev_priv = (unsigned long) priv; + + ret = wiphy_register(wdev->wiphy); + if (ret < 0) { + dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", + __func__); + wiphy_free(wdev->wiphy); + return ret; + } else { + dev_dbg(priv->adapter->dev, + "info: successfully registered wiphy device\n"); + } + + dev_net_set(dev, wiphy_net(wdev->wiphy)); + dev->ieee80211_ptr = wdev; + memcpy(dev->dev_addr, wdev->wiphy->perm_addr, 6); + memcpy(dev->perm_addr, wdev->wiphy->perm_addr, 6); + SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); + priv->wdev = wdev; + + dev->flags |= IFF_BROADCAST | IFF_MULTICAST; + dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; + dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; + + return ret; +} + +/* + * This function handles the result of different pending network operations. + * + * The following operations are handled and CFG802.11 subsystem is + * notified accordingly - + * - Scan request completion + * - Association request completion + * - IBSS join request completion + * - Disconnect request completion + */ +void +mwifiex_cfg80211_results(struct work_struct *work) +{ + struct mwifiex_private *priv = + container_of(work, struct mwifiex_private, cfg_workqueue); + struct mwifiex_user_scan_cfg *scan_req; + int ret = 0, i; + struct ieee80211_channel *chan; + + if (priv->scan_request) { + scan_req = kzalloc(sizeof(struct mwifiex_user_scan_cfg), + GFP_KERNEL); + if (!scan_req) { + dev_err(priv->adapter->dev, "failed to alloc " + "scan_req\n"); + return; + } + for (i = 0; i < priv->scan_request->n_ssids; i++) { + memcpy(scan_req->ssid_list[i].ssid, + priv->scan_request->ssids[i].ssid, + priv->scan_request->ssids[i].ssid_len); + scan_req->ssid_list[i].max_len = + priv->scan_request->ssids[i].ssid_len; + } + for (i = 0; i < priv->scan_request->n_channels; i++) { + chan = priv->scan_request->channels[i]; + scan_req->chan_list[i].chan_number = chan->hw_value; + scan_req->chan_list[i].radio_type = chan->band; + if (chan->flags & IEEE80211_CHAN_DISABLED) + scan_req->chan_list[i].scan_type = + MWIFIEX_SCAN_TYPE_PASSIVE; + else + scan_req->chan_list[i].scan_type = + MWIFIEX_SCAN_TYPE_ACTIVE; + scan_req->chan_list[i].scan_time = 0; + } + if (mwifiex_set_user_scan_ioctl(priv, scan_req)) { + ret = -EFAULT; + goto done; + } + if (mwifiex_inform_bss_from_scan_result(priv, NULL)) + ret = -EFAULT; +done: + priv->scan_result_status = ret; + dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n", + __func__); + cfg80211_scan_done(priv->scan_request, + (priv->scan_result_status < 0)); + priv->scan_request = NULL; + kfree(scan_req); + } + + if (priv->assoc_request) { + if (!priv->assoc_result) { + cfg80211_connect_result(priv->netdev, priv->cfg_bssid, + NULL, 0, NULL, 0, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + dev_dbg(priv->adapter->dev, + "info: associated to bssid %pM successfully\n", + priv->cfg_bssid); + } else { + dev_dbg(priv->adapter->dev, + "info: association to bssid %pM failed\n", + priv->cfg_bssid); + memset(priv->cfg_bssid, 0, ETH_ALEN); + } + priv->assoc_request = 0; + priv->assoc_result = 0; + } + + if (priv->ibss_join_request) { + if (!priv->ibss_join_result) { + cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, + GFP_KERNEL); + dev_dbg(priv->adapter->dev, + "info: joined/created adhoc network with bssid" + " %pM successfully\n", priv->cfg_bssid); + } else { + dev_dbg(priv->adapter->dev, + "info: failed creating/joining adhoc network\n"); + } + priv->ibss_join_request = 0; + priv->ibss_join_result = 0; + } + + if (priv->disconnect) { + memset(priv->cfg_bssid, 0, ETH_ALEN); + priv->disconnect = 0; + } + + return; +} diff --git a/drivers/net/wireless/mwifiex/cfg80211.h b/drivers/net/wireless/mwifiex/cfg80211.h new file mode 100644 index 000000000000..c4db8f36aa16 --- /dev/null +++ b/drivers/net/wireless/mwifiex/cfg80211.h @@ -0,0 +1,31 @@ +/* + * Marvell Wireless LAN device driver: CFG80211 + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#ifndef __MWIFIEX_CFG80211__ +#define __MWIFIEX_CFG80211__ + +#include + +#include "main.h" + +int mwifiex_register_cfg80211(struct net_device *, u8 *, + struct mwifiex_private *); + +void mwifiex_cfg80211_results(struct work_struct *work); +#endif diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c new file mode 100644 index 000000000000..999ed81512fa --- /dev/null +++ b/drivers/net/wireless/mwifiex/cfp.c @@ -0,0 +1,368 @@ +/* + * Marvell Wireless LAN device driver: Channel, Frequence and Power + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "cfg80211.h" + +/* 100mW */ +#define MWIFIEX_TX_PWR_DEFAULT 20 +/* 100mW */ +#define MWIFIEX_TX_PWR_US_DEFAULT 20 +/* 50mW */ +#define MWIFIEX_TX_PWR_JP_DEFAULT 16 +/* 100mW */ +#define MWIFIEX_TX_PWR_FR_100MW 20 +/* 10mW */ +#define MWIFIEX_TX_PWR_FR_10MW 10 +/* 100mW */ +#define MWIFIEX_TX_PWR_EMEA_DEFAULT 20 + +static u8 adhoc_rates_b[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 }; + +static u8 adhoc_rates_g[G_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24, + 0xb0, 0x48, 0x60, 0x6c, 0 }; + +static u8 adhoc_rates_bg[BG_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, + 0x0c, 0x12, 0x18, 0x24, + 0x30, 0x48, 0x60, 0x6c, 0 }; + +static u8 adhoc_rates_a[A_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24, + 0xb0, 0x48, 0x60, 0x6c, 0 }; +u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24, + 0xb0, 0x48, 0x60, 0x6c, 0 }; +static u16 mwifiex_data_rates[MWIFIEX_SUPPORTED_RATES_EXT] = { 0x02, 0x04, + 0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18, + 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90, + 0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68, + 0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51, + 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00 }; + +u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 }; + +u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24, + 0x30, 0x48, 0x60, 0x6c, 0 }; + +u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c, + 0x12, 0x16, 0x18, 0x24, 0x30, 0x48, + 0x60, 0x6c, 0 }; + +u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x10, 0x20, 0x30, + 0x32, 0x40, 0x41, 0xff }; + +u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 }; + +/* + * This function maps an index in supported rates table into + * the corresponding data rate. + */ +u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index, + u8 ht_info) +{ + u16 mcs_rate[4][8] = { + {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e} + , /* LG 40M */ + {0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c} + , /* SG 40M */ + {0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82} + , /* LG 20M */ + {0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90} + }; /* SG 20M */ + + u32 rate; + + if (ht_info & BIT(0)) { + if (index == MWIFIEX_RATE_BITMAP_MCS0) { + if (ht_info & BIT(2)) + rate = 0x0D; /* MCS 32 SGI rate */ + else + rate = 0x0C; /* MCS 32 LGI rate */ + } else if (index < 8) { + if (ht_info & BIT(1)) { + if (ht_info & BIT(2)) + /* SGI, 40M */ + rate = mcs_rate[1][index]; + else + /* LGI, 40M */ + rate = mcs_rate[0][index]; + } else { + if (ht_info & BIT(2)) + /* SGI, 20M */ + rate = mcs_rate[3][index]; + else + /* LGI, 20M */ + rate = mcs_rate[2][index]; + } + } else + rate = mwifiex_data_rates[0]; + } else { + if (index >= MWIFIEX_SUPPORTED_RATES_EXT) + index = 0; + rate = mwifiex_data_rates[index]; + } + return rate; +} + +/* + * This function maps a data rate value into corresponding index in supported + * rates table. + */ +u8 mwifiex_data_rate_to_index(struct mwifiex_adapter *adapter, u32 rate) +{ + u16 *ptr; + + if (rate) { + ptr = memchr(mwifiex_data_rates, rate, + sizeof(mwifiex_data_rates)); + if (ptr) + return (u8) (ptr - mwifiex_data_rates); + } + return 0; +} + +/* + * This function returns the current active data rates. + * + * The result may vary depending upon connection status. + */ +u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, u8 *rates) +{ + u32 k; + + if (!priv->media_connected) + k = mwifiex_get_supported_rates(priv, rates); + else + k = mwifiex_copy_rates(rates, 0, + priv->curr_bss_params.data_rates, + priv->curr_bss_params.num_of_rates); + + return k; +} + +/* + * This function locates the Channel-Frequency-Power triplet based upon + * band and channel parameters. + */ +struct mwifiex_chan_freq_power * +mwifiex_get_cfp_by_band_and_channel_from_cfg80211(struct mwifiex_private + *priv, u8 band, u16 channel) +{ + struct mwifiex_chan_freq_power *cfp = NULL; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + int i; + + if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG) + sband = priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ]; + else + sband = priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ]; + + if (!sband) { + dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d" + " & channel %d\n", __func__, band, channel); + return cfp; + } + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + if (((ch->hw_value == channel) || + (channel == FIRST_VALID_CHANNEL)) + && !(ch->flags & IEEE80211_CHAN_DISABLED)) { + priv->cfp.channel = channel; + priv->cfp.freq = ch->center_freq; + priv->cfp.max_tx_power = ch->max_power; + cfp = &priv->cfp; + break; + } + } + if (i == sband->n_channels) + dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d" + " & channel %d\n", __func__, band, channel); + + return cfp; +} + +/* + * This function locates the Channel-Frequency-Power triplet based upon + * band and frequency parameters. + */ +struct mwifiex_chan_freq_power * +mwifiex_get_cfp_by_band_and_freq_from_cfg80211(struct mwifiex_private *priv, + u8 band, u32 freq) +{ + struct mwifiex_chan_freq_power *cfp = NULL; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + int i; + + if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG) + sband = priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ]; + else + sband = priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ]; + + if (!sband) { + dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d" + " & freq %d\n", __func__, band, freq); + return cfp; + } + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + if ((ch->center_freq == freq) && + !(ch->flags & IEEE80211_CHAN_DISABLED)) { + priv->cfp.channel = ch->hw_value; + priv->cfp.freq = freq; + priv->cfp.max_tx_power = ch->max_power; + cfp = &priv->cfp; + break; + } + } + if (i == sband->n_channels) + dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d" + " & freq %d\n", __func__, band, freq); + + return cfp; +} + +/* + * This function checks if the data rate is set to auto. + */ +u8 +mwifiex_is_rate_auto(struct mwifiex_private *priv) +{ + u32 i; + int rate_num = 0; + + for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates); i++) + if (priv->bitmap_rates[i]) + rate_num++; + + if (rate_num > 1) + return true; + else + return false; +} + +/* + * This function converts rate bitmap into rate index. + */ +int +mwifiex_get_rate_index(struct mwifiex_adapter *adapter, u16 *rate_bitmap, + int size) +{ + int i; + + for (i = 0; i < size * 8; i++) + if (rate_bitmap[i / 16] & (1 << (i % 16))) + return i; + + return 0; +} + +/* + * This function gets the supported data rates. + * + * The function works in both Ad-Hoc and infra mode by printing the + * band and returning the data rates. + */ +u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates) +{ + u32 k = 0; + struct mwifiex_adapter *adapter = priv->adapter; + if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA) { + /* Infra. mode */ + switch (adapter->config_bands) { + case BAND_B: + dev_dbg(adapter->dev, "info: infra band=%d " + "supported_rates_b\n", adapter->config_bands); + k = mwifiex_copy_rates(rates, k, supported_rates_b, + sizeof(supported_rates_b)); + break; + case BAND_G: + case BAND_G | BAND_GN: + dev_dbg(adapter->dev, "info: infra band=%d " + "supported_rates_g\n", adapter->config_bands); + k = mwifiex_copy_rates(rates, k, supported_rates_g, + sizeof(supported_rates_g)); + break; + case BAND_B | BAND_G: + case BAND_A | BAND_B | BAND_G: + case BAND_A | BAND_B: + case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN: + case BAND_B | BAND_G | BAND_GN: + dev_dbg(adapter->dev, "info: infra band=%d " + "supported_rates_bg\n", adapter->config_bands); + k = mwifiex_copy_rates(rates, k, supported_rates_bg, + sizeof(supported_rates_bg)); + break; + case BAND_A: + case BAND_A | BAND_G: + dev_dbg(adapter->dev, "info: infra band=%d " + "supported_rates_a\n", adapter->config_bands); + k = mwifiex_copy_rates(rates, k, supported_rates_a, + sizeof(supported_rates_a)); + break; + case BAND_A | BAND_AN: + case BAND_A | BAND_G | BAND_AN | BAND_GN: + dev_dbg(adapter->dev, "info: infra band=%d " + "supported_rates_a\n", adapter->config_bands); + k = mwifiex_copy_rates(rates, k, supported_rates_a, + sizeof(supported_rates_a)); + break; + case BAND_GN: + dev_dbg(adapter->dev, "info: infra band=%d " + "supported_rates_n\n", adapter->config_bands); + k = mwifiex_copy_rates(rates, k, supported_rates_n, + sizeof(supported_rates_n)); + break; + } + } else { + /* Ad-hoc mode */ + switch (adapter->adhoc_start_band) { + case BAND_B: + dev_dbg(adapter->dev, "info: adhoc B\n"); + k = mwifiex_copy_rates(rates, k, adhoc_rates_b, + sizeof(adhoc_rates_b)); + break; + case BAND_G: + case BAND_G | BAND_GN: + dev_dbg(adapter->dev, "info: adhoc G only\n"); + k = mwifiex_copy_rates(rates, k, adhoc_rates_g, + sizeof(adhoc_rates_g)); + break; + case BAND_B | BAND_G: + case BAND_B | BAND_G | BAND_GN: + dev_dbg(adapter->dev, "info: adhoc BG\n"); + k = mwifiex_copy_rates(rates, k, adhoc_rates_bg, + sizeof(adhoc_rates_bg)); + break; + case BAND_A: + case BAND_A | BAND_AN: + dev_dbg(adapter->dev, "info: adhoc A\n"); + k = mwifiex_copy_rates(rates, k, adhoc_rates_a, + sizeof(adhoc_rates_a)); + break; + } + } + + return k; +} diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c new file mode 100644 index 000000000000..3a8fe1e122fb --- /dev/null +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -0,0 +1,1463 @@ +/* + * Marvell Wireless LAN device driver: commands and events + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" + +/* + * This function initializes a command node. + * + * The actual allocation of the node is not done by this function. It only + * initiates a node by filling it with default parameters. Similarly, + * allocation of the different buffers used (IOCTL buffer, data buffer) are + * not done by this function either. + */ +static void +mwifiex_init_cmd_node(struct mwifiex_private *priv, + struct cmd_ctrl_node *cmd_node, + u32 cmd_oid, void *wait_queue, void *data_buf) +{ + cmd_node->priv = priv; + cmd_node->cmd_oid = cmd_oid; + cmd_node->wq_buf = wait_queue; + cmd_node->data_buf = data_buf; + cmd_node->cmd_skb = cmd_node->skb; +} + +/* + * This function returns a command node from the free queue depending upon + * availability. + */ +static struct cmd_ctrl_node * +mwifiex_get_cmd_node(struct mwifiex_adapter *adapter) +{ + struct cmd_ctrl_node *cmd_node; + unsigned long flags; + + spin_lock_irqsave(&adapter->cmd_free_q_lock, flags); + if (list_empty(&adapter->cmd_free_q)) { + dev_err(adapter->dev, "GET_CMD_NODE: cmd node not available\n"); + spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); + return NULL; + } + cmd_node = list_first_entry(&adapter->cmd_free_q, + struct cmd_ctrl_node, list); + list_del(&cmd_node->list); + spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); + + return cmd_node; +} + +/* + * This function cleans up a command node. + * + * The function resets the fields including the buffer pointers. + * This function does not try to free the buffers. They must be + * freed before calling this function. + * + * This function will however call the receive completion callback + * in case a response buffer is still available before resetting + * the pointer. + */ +static void +mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, + struct cmd_ctrl_node *cmd_node) +{ + cmd_node->cmd_oid = 0; + cmd_node->cmd_flag = 0; + cmd_node->wq_buf = NULL; + cmd_node->data_buf = NULL; + + if (cmd_node->resp_skb) { + mwifiex_recv_complete(adapter, cmd_node->resp_skb, 0); + cmd_node->resp_skb = NULL; + } + + return; +} + +/* + * This function returns a command node from the pending queue which + * matches the given IOCTL request. + */ +static struct cmd_ctrl_node * +mwifiex_get_pending_ioctl_cmd(struct mwifiex_adapter *adapter, + struct mwifiex_wait_queue *wait_queue) +{ + unsigned long flags; + struct cmd_ctrl_node *cmd_node; + + spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); + list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) { + if (cmd_node->wq_buf == wait_queue) { + spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, + flags); + return cmd_node; + } + } + spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); + + return NULL; +} + +/* + * This function sends a host command to the firmware. + * + * The function copies the host command into the driver command + * buffer, which will be transferred to the firmware later by the + * main thread. + */ +static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, void *data_buf) +{ + struct mwifiex_ds_misc_cmd *pcmd_ptr = + (struct mwifiex_ds_misc_cmd *) data_buf; + + /* Copy the HOST command to command buffer */ + memcpy((void *) cmd, pcmd_ptr->cmd, pcmd_ptr->len); + dev_dbg(priv->adapter->dev, "cmd: host cmd size = %d\n", pcmd_ptr->len); + return 0; +} + +/* + * This function downloads a command to the firmware. + * + * The function performs sanity tests, sets the command sequence + * number and size, converts the header fields to CPU format before + * sending. Afterwards, it logs the command ID and action for debugging + * and sets up the command timeout timer. + */ +static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, + struct cmd_ctrl_node *cmd_node) +{ + + struct mwifiex_adapter *adapter = priv->adapter; + int ret = 0; + struct host_cmd_ds_command *host_cmd; + struct mwifiex_wait_queue *wait_queue = NULL; + uint16_t cmd_code; + uint16_t cmd_size; + struct timeval tstamp; + unsigned long flags; + + if (!adapter || !cmd_node) + return -1; + + host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); + if (cmd_node->wq_buf) + wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf; + + /* Sanity test */ + if (host_cmd == NULL || host_cmd->size == 0) { + dev_err(adapter->dev, "DNLD_CMD: host_cmd is null" + " or cmd size is 0, not sending\n"); + if (wait_queue) + wait_queue->status = MWIFIEX_ERROR_CMD_DNLD_FAIL; + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + return -1; + } + + /* Set command sequence number */ + adapter->seq_num++; + host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO + (adapter->seq_num, cmd_node->priv->bss_num, + cmd_node->priv->bss_type)); + + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->curr_cmd = cmd_node; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + + cmd_code = le16_to_cpu(host_cmd->command); + cmd_size = le16_to_cpu(host_cmd->size); + + skb_trim(cmd_node->cmd_skb, cmd_size); + + do_gettimeofday(&tstamp); + dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d," + " seqno %#x\n", + tstamp.tv_sec, tstamp.tv_usec, cmd_code, + le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size, + le16_to_cpu(host_cmd->seq_num)); + + skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN); + + ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, + cmd_node->cmd_skb->data, + cmd_node->cmd_skb->len, NULL); + + if (ret == -1) { + dev_err(adapter->dev, "DNLD_CMD: host to card failed\n"); + if (wait_queue) + wait_queue->status = MWIFIEX_ERROR_CMD_DNLD_FAIL; + mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); + + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->curr_cmd = NULL; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + + adapter->dbg.num_cmd_host_to_card_failure++; + return -1; + } + + /* Save the last command id and action to debug log */ + adapter->dbg.last_cmd_index = + (adapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM; + adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index] = cmd_code; + adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] = + le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)); + + /* Clear BSS_NO_BITS from HostCmd */ + cmd_code &= HostCmd_CMD_ID_MASK; + + /* Setup the timer after transmit command */ + mod_timer(&adapter->cmd_timer, + jiffies + (MWIFIEX_TIMER_10S * HZ) / 1000); + + return 0; +} + +/* + * This function downloads a sleep confirm command to the firmware. + * + * The function performs sanity tests, sets the command sequence + * number and size, converts the header fields to CPU format before + * sending. + * + * No responses are needed for sleep confirm command. + */ +static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) +{ + int ret = 0; + u16 cmd_len = 0; + struct mwifiex_private *priv; + struct mwifiex_opt_sleep_confirm_buffer *sleep_cfm_buf = + (struct mwifiex_opt_sleep_confirm_buffer *) + adapter->sleep_cfm->data; + cmd_len = sizeof(struct mwifiex_opt_sleep_confirm); + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + + sleep_cfm_buf->ps_cfm_sleep.seq_num = + cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO + (adapter->seq_num, priv->bss_num, + priv->bss_type))); + adapter->seq_num++; + + ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, + adapter->sleep_cfm->data, + adapter->sleep_cfm->len + + INTF_HEADER_LEN, NULL); + + if (ret == -1) { + dev_err(adapter->dev, "SLEEP_CFM: failed\n"); + adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++; + return -1; + } + if (GET_BSS_ROLE(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY)) + == MWIFIEX_BSS_ROLE_STA) { + if (!sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl) + /* Response is not needed for sleep + confirm command */ + adapter->ps_state = PS_STATE_SLEEP; + else + adapter->ps_state = PS_STATE_SLEEP_CFM; + + if (!sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl + && (adapter->is_hs_configured + && !adapter->sleep_period.period)) { + adapter->pm_wakeup_card_req = true; + mwifiex_hs_activated_event(mwifiex_get_priv(adapter, + MWIFIEX_BSS_ROLE_STA), true); + } + } + + return ret; +} + +/* + * This function allocates the command buffers and links them to + * the command free queue. + * + * The driver uses a pre allocated number of command buffers, which + * are created at driver initializations and freed at driver cleanup. + * Every command needs to obtain a command buffer from this pool before + * it can be issued. The command free queue lists the command buffers + * currently free to use, while the command pending queue lists the + * command buffers already in use and awaiting handling. Command buffers + * are returned to the free queue after use. + */ +int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter) +{ + struct cmd_ctrl_node *cmd_array; + u32 buf_size; + u32 i; + + /* Allocate and initialize struct cmd_ctrl_node */ + buf_size = sizeof(struct cmd_ctrl_node) * MWIFIEX_NUM_OF_CMD_BUFFER; + cmd_array = kzalloc(buf_size, GFP_KERNEL); + if (!cmd_array) { + dev_err(adapter->dev, "%s: failed to alloc cmd_array\n", + __func__); + return -1; + } + + adapter->cmd_pool = cmd_array; + memset(adapter->cmd_pool, 0, buf_size); + + /* Allocate and initialize command buffers */ + for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) { + cmd_array[i].skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER); + if (!cmd_array[i].skb) { + dev_err(adapter->dev, "ALLOC_CMD_BUF: out of memory\n"); + return -1; + } + } + + for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) + mwifiex_insert_cmd_to_free_q(adapter, &cmd_array[i]); + + return 0; +} + +/* + * This function frees the command buffers. + * + * The function calls the completion callback for all the command + * buffers that still have response buffers associated with them. + */ +int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter) +{ + struct cmd_ctrl_node *cmd_array; + u32 i; + + /* Need to check if cmd pool is allocated or not */ + if (!adapter->cmd_pool) { + dev_dbg(adapter->dev, "info: FREE_CMD_BUF: cmd_pool is null\n"); + return 0; + } + + cmd_array = adapter->cmd_pool; + + /* Release shared memory buffers */ + for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) { + if (cmd_array[i].skb) { + dev_dbg(adapter->dev, "cmd: free cmd buffer %d\n", i); + dev_kfree_skb_any(cmd_array[i].skb); + } + if (!cmd_array[i].resp_skb) + continue; + mwifiex_recv_complete(adapter, cmd_array[i].resp_skb, 0); + } + /* Release struct cmd_ctrl_node */ + if (adapter->cmd_pool) { + dev_dbg(adapter->dev, "cmd: free cmd pool\n"); + kfree(adapter->cmd_pool); + adapter->cmd_pool = NULL; + } + + return 0; +} + +/* + * This function handles events generated by firmware. + * + * Event body of events received from firmware are not used (though they are + * saved), only the event ID is used. Some events are re-invoked by + * the driver, with a new event body. + * + * After processing, the function calls the completion callback + * for cleanup. + */ +int mwifiex_process_event(struct mwifiex_adapter *adapter) +{ + int ret = 0; + struct mwifiex_private *priv = + mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + struct sk_buff *skb = adapter->event_skb; + u32 eventcause = adapter->event_cause; + struct timeval tstamp; + struct mwifiex_rxinfo *rx_info = NULL; + + /* Save the last event to debug log */ + adapter->dbg.last_event_index = + (adapter->dbg.last_event_index + 1) % DBG_CMD_NUM; + adapter->dbg.last_event[adapter->dbg.last_event_index] = + (u16) eventcause; + + /* Get BSS number and corresponding priv */ + priv = mwifiex_get_priv_by_id(adapter, EVENT_GET_BSS_NUM(eventcause), + EVENT_GET_BSS_TYPE(eventcause)); + if (!priv) + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + /* Clear BSS_NO_BITS from event */ + eventcause &= EVENT_ID_MASK; + adapter->event_cause = eventcause; + + if (skb) { + rx_info = MWIFIEX_SKB_RXCB(skb); + rx_info->bss_index = priv->bss_index; + } + + if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE) { + do_gettimeofday(&tstamp); + dev_dbg(adapter->dev, "event: %lu.%lu: cause: %#x\n", + tstamp.tv_sec, tstamp.tv_usec, eventcause); + } + + ret = mwifiex_process_sta_event(priv); + + adapter->event_cause = 0; + adapter->event_skb = NULL; + + mwifiex_recv_complete(adapter, skb, 0); + + return ret; +} + +/* + * This function prepares a command before sending it to the firmware. + * + * Preparation includes - + * - Sanity tests to make sure the card is still present or the FW + * is not reset + * - Getting a new command node from the command free queue + * - Initializing the command node for default parameters + * - Fill up the non-default parameters and buffer pointers + * - Add the command to pending queue + */ +int mwifiex_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, + u16 cmd_action, u32 cmd_oid, + void *wait_queue, void *data_buf) +{ + int ret = 0; + struct mwifiex_adapter *adapter = priv->adapter; + struct cmd_ctrl_node *cmd_node = NULL; + struct host_cmd_ds_command *cmd_ptr = NULL; + + if (!adapter) { + pr_err("PREP_CMD: adapter is NULL\n"); + return -1; + } + + if (adapter->is_suspended) { + dev_err(adapter->dev, "PREP_CMD: device in suspended state\n"); + return -1; + } + + if (adapter->surprise_removed) { + dev_err(adapter->dev, "PREP_CMD: card is removed\n"); + return -1; + } + + if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) { + if (cmd_no != HostCmd_CMD_FUNC_INIT) { + dev_err(adapter->dev, "PREP_CMD: FW in reset state\n"); + return -1; + } + } + + /* Get a new command node */ + cmd_node = mwifiex_get_cmd_node(adapter); + + if (!cmd_node) { + dev_err(adapter->dev, "PREP_CMD: no free cmd node\n"); + return -1; + } + + /* Initialize the command node */ + mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, wait_queue, data_buf); + + if (!cmd_node->cmd_skb) { + dev_err(adapter->dev, "PREP_CMD: no free cmd buf\n"); + return -1; + } + + memset(skb_put(cmd_node->cmd_skb, sizeof(struct host_cmd_ds_command)), + 0, sizeof(struct host_cmd_ds_command)); + + cmd_ptr = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); + cmd_ptr->command = cpu_to_le16(cmd_no); + cmd_ptr->result = 0; + + /* Prepare command */ + if (cmd_no) { + ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action, + cmd_oid, data_buf, cmd_ptr); + } else { + ret = mwifiex_cmd_host_cmd(priv, cmd_ptr, data_buf); + cmd_node->cmd_flag |= CMD_F_HOSTCMD; + } + + /* Return error, since the command preparation failed */ + if (ret) { + dev_err(adapter->dev, "PREP_CMD: cmd %#x preparation failed\n", + cmd_no); + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + return -1; + } + + /* Send command */ + if (cmd_no == HostCmd_CMD_802_11_SCAN) + mwifiex_queue_scan_cmd(priv, cmd_node); + else + mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); + + return ret; +} + +/* + * This function returns a command to the command free queue. + * + * The function also calls the completion callback if required, before + * cleaning the command node and re-inserting it into the free queue. + */ +void +mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, + struct cmd_ctrl_node *cmd_node) +{ + struct mwifiex_wait_queue *wait_queue = NULL; + unsigned long flags; + + if (cmd_node == NULL) + return; + if (cmd_node->wq_buf) { + wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf; + if (wait_queue->status != MWIFIEX_ERROR_NO_ERROR) + mwifiex_ioctl_complete(adapter, wait_queue, -1); + else + mwifiex_ioctl_complete(adapter, wait_queue, 0); + } + /* Clean the node */ + mwifiex_clean_cmd_node(adapter, cmd_node); + + /* Insert node into cmd_free_q */ + spin_lock_irqsave(&adapter->cmd_free_q_lock, flags); + list_add_tail(&cmd_node->list, &adapter->cmd_free_q); + spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); + + return; +} + +/* + * This function queues a command to the command pending queue. + * + * This in effect adds the command to the command list to be executed. + * Exit PS command is handled specially, by placing it always to the + * front of the command queue. + */ +void +mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, + struct cmd_ctrl_node *cmd_node, u32 add_tail) +{ + struct host_cmd_ds_command *host_cmd = NULL; + u16 command; + unsigned long flags; + + host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); + if (!host_cmd) { + dev_err(adapter->dev, "QUEUE_CMD: host_cmd is NULL\n"); + return; + } + + command = le16_to_cpu(host_cmd->command); + + /* Exit_PS command needs to be queued in the header always. */ + if (command == HostCmd_CMD_802_11_PS_MODE_ENH) { + struct host_cmd_ds_802_11_ps_mode_enh *pm = + &host_cmd->params.psmode_enh; + if ((le16_to_cpu(pm->action) == DIS_PS) + || (le16_to_cpu(pm->action) == DIS_AUTO_PS)) { + if (adapter->ps_state != PS_STATE_AWAKE) + add_tail = false; + } + } + + spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); + if (add_tail) + list_add_tail(&cmd_node->list, &adapter->cmd_pending_q); + else + list_add(&cmd_node->list, &adapter->cmd_pending_q); + spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); + + dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x is queued\n", command); + + return; +} + +/* + * This function executes the next command in command pending queue. + * + * This function will fail if a command is already in processing stage, + * otherwise it will dequeue the first command from the command pending + * queue and send to the firmware. + * + * If the device is currently in host sleep mode, any commands, except the + * host sleep configuration command will de-activate the host sleep. For PS + * mode, the function will put the firmware back to sleep if applicable. + */ +int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter) +{ + struct mwifiex_private *priv = NULL; + struct cmd_ctrl_node *cmd_node = NULL; + int ret = 0; + struct host_cmd_ds_command *host_cmd; + unsigned long cmd_flags; + unsigned long cmd_pending_q_flags; + + /* Check if already in processing */ + if (adapter->curr_cmd) { + dev_err(adapter->dev, "EXEC_NEXT_CMD: cmd in processing\n"); + return -1; + } + + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); + /* Check if any command is pending */ + spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags); + if (list_empty(&adapter->cmd_pending_q)) { + spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, + cmd_pending_q_flags); + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); + return 0; + } + cmd_node = list_first_entry(&adapter->cmd_pending_q, + struct cmd_ctrl_node, list); + spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, + cmd_pending_q_flags); + + host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); + priv = cmd_node->priv; + + if (adapter->ps_state != PS_STATE_AWAKE) { + dev_err(adapter->dev, "%s: cannot send cmd in sleep state," + " this should not happen\n", __func__); + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); + return ret; + } + + spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags); + list_del(&cmd_node->list); + spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, + cmd_pending_q_flags); + + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); + ret = mwifiex_dnld_cmd_to_fw(priv, cmd_node); + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + /* Any command sent to the firmware when host is in sleep + * mode should de-configure host sleep. We should skip the + * host sleep configuration command itself though + */ + if (priv && (host_cmd->command != + cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH))) { + if (adapter->hs_activated) { + adapter->is_hs_configured = false; + mwifiex_hs_activated_event(priv, false); + } + } + + return ret; +} + +/* + * This function handles the command response. + * + * After processing, the function cleans the command node and puts + * it back to the command free queue. + */ +int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) +{ + struct host_cmd_ds_command *resp = NULL; + struct mwifiex_private *priv = + mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + int ret = 0; + uint16_t orig_cmdresp_no; + uint16_t cmdresp_no; + uint16_t cmdresp_result; + struct mwifiex_wait_queue *wait_queue = NULL; + struct timeval tstamp; + unsigned long flags; + + /* Now we got response from FW, cancel the command timer */ + del_timer(&adapter->cmd_timer); + + if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) { + resp = (struct host_cmd_ds_command *) adapter->upld_buf; + dev_err(adapter->dev, "CMD_RESP: NULL curr_cmd, %#x\n", + le16_to_cpu(resp->command)); + return -1; + } + + if (adapter->curr_cmd->wq_buf) + wait_queue = (struct mwifiex_wait_queue *) + adapter->curr_cmd->wq_buf; + + adapter->num_cmd_timeout = 0; + + resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data; + if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) { + dev_err(adapter->dev, "CMD_RESP: %#x been canceled\n", + le16_to_cpu(resp->command)); + mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->curr_cmd = NULL; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + return -1; + } + + if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { + /* Copy original response back to response buffer */ + struct mwifiex_ds_misc_cmd *hostcmd = NULL; + uint16_t size = le16_to_cpu(resp->size); + dev_dbg(adapter->dev, "info: host cmd resp size = %d\n", size); + size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER); + if (adapter->curr_cmd->data_buf) { + hostcmd = (struct mwifiex_ds_misc_cmd *) + adapter->curr_cmd->data_buf; + hostcmd->len = size; + memcpy(hostcmd->cmd, (void *) resp, size); + } + } + orig_cmdresp_no = le16_to_cpu(resp->command); + + /* Get BSS number and corresponding priv */ + priv = mwifiex_get_priv_by_id(adapter, + HostCmd_GET_BSS_NO(le16_to_cpu(resp->seq_num)), + HostCmd_GET_BSS_TYPE(le16_to_cpu(resp->seq_num))); + if (!priv) + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + /* Clear RET_BIT from HostCmd */ + resp->command = cpu_to_le16(orig_cmdresp_no & HostCmd_CMD_ID_MASK); + + cmdresp_no = le16_to_cpu(resp->command); + cmdresp_result = le16_to_cpu(resp->result); + + /* Save the last command response to debug log */ + adapter->dbg.last_cmd_resp_index = + (adapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM; + adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] = + orig_cmdresp_no; + + do_gettimeofday(&tstamp); + dev_dbg(adapter->dev, "cmd: CMD_RESP: (%lu.%lu): 0x%x, result %d," + " len %d, seqno 0x%x\n", + tstamp.tv_sec, tstamp.tv_usec, orig_cmdresp_no, cmdresp_result, + le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num)); + + if (!(orig_cmdresp_no & HostCmd_RET_BIT)) { + dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n"); + if (wait_queue) + wait_queue->status = MWIFIEX_ERROR_FW_CMDRESP; + + mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->curr_cmd = NULL; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + return -1; + } + + if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { + adapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD; + if ((cmdresp_result == HostCmd_RESULT_OK) + && (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH)) + ret = mwifiex_ret_802_11_hs_cfg(priv, resp); + } else { + /* handle response */ + ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp, + wait_queue); + } + + /* Check init command response */ + if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) { + if (ret == -1) { + dev_err(adapter->dev, "%s: cmd %#x failed during " + "initialization\n", __func__, cmdresp_no); + mwifiex_init_fw_complete(adapter); + return -1; + } else if (adapter->last_init_cmd == cmdresp_no) + adapter->hw_status = MWIFIEX_HW_STATUS_INIT_DONE; + } + + if (adapter->curr_cmd) { + if (wait_queue && (!ret)) + wait_queue->status = MWIFIEX_ERROR_NO_ERROR; + else if (wait_queue && (ret == -1)) + wait_queue->status = MWIFIEX_ERROR_CMD_RESP_FAIL; + + /* Clean up and put current command back to cmd_free_q */ + mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); + + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->curr_cmd = NULL; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + } + + return ret; +} + +/* + * This function handles the timeout of command sending. + * + * It will re-send the same command again. + */ +void +mwifiex_cmd_timeout_func(unsigned long function_context) +{ + struct mwifiex_adapter *adapter = + (struct mwifiex_adapter *) function_context; + struct cmd_ctrl_node *cmd_node = NULL; + struct mwifiex_wait_queue *wait_queue = NULL; + struct timeval tstamp; + + adapter->num_cmd_timeout++; + adapter->dbg.num_cmd_timeout++; + if (!adapter->curr_cmd) { + dev_dbg(adapter->dev, "cmd: empty curr_cmd\n"); + return; + } + cmd_node = adapter->curr_cmd; + if (cmd_node->wq_buf) { + wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf; + wait_queue->status = MWIFIEX_ERROR_CMD_TIMEOUT; + } + + if (cmd_node) { + adapter->dbg.timeout_cmd_id = + adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; + adapter->dbg.timeout_cmd_act = + adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index]; + do_gettimeofday(&tstamp); + dev_err(adapter->dev, "%s: Timeout cmd id (%lu.%lu) = %#x," + " act = %#x\n", __func__, + tstamp.tv_sec, tstamp.tv_usec, + adapter->dbg.timeout_cmd_id, + adapter->dbg.timeout_cmd_act); + + dev_err(adapter->dev, "num_data_h2c_failure = %d\n", + adapter->dbg.num_tx_host_to_card_failure); + dev_err(adapter->dev, "num_cmd_h2c_failure = %d\n", + adapter->dbg.num_cmd_host_to_card_failure); + + dev_err(adapter->dev, "num_cmd_timeout = %d\n", + adapter->dbg.num_cmd_timeout); + dev_err(adapter->dev, "num_tx_timeout = %d\n", + adapter->dbg.num_tx_timeout); + + dev_err(adapter->dev, "last_cmd_index = %d\n", + adapter->dbg.last_cmd_index); + print_hex_dump_bytes("last_cmd_id: ", DUMP_PREFIX_OFFSET, + adapter->dbg.last_cmd_id, DBG_CMD_NUM); + print_hex_dump_bytes("last_cmd_act: ", DUMP_PREFIX_OFFSET, + adapter->dbg.last_cmd_act, DBG_CMD_NUM); + + dev_err(adapter->dev, "last_cmd_resp_index = %d\n", + adapter->dbg.last_cmd_resp_index); + print_hex_dump_bytes("last_cmd_resp_id: ", DUMP_PREFIX_OFFSET, + adapter->dbg.last_cmd_resp_id, DBG_CMD_NUM); + + dev_err(adapter->dev, "last_event_index = %d\n", + adapter->dbg.last_event_index); + print_hex_dump_bytes("last_event: ", DUMP_PREFIX_OFFSET, + adapter->dbg.last_event, DBG_CMD_NUM); + + dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n", + adapter->data_sent, adapter->cmd_sent); + + dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n", + adapter->ps_mode, adapter->ps_state); + } + if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) + mwifiex_init_fw_complete(adapter); + + return; +} + +/* + * This function cancels all the pending commands. + * + * The current command, all commands in command pending queue and all scan + * commands in scan pending queue are cancelled. All the completion callbacks + * are called with failure status to ensure cleanup. + */ +void +mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) +{ + struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; + struct mwifiex_wait_queue *wait_queue = NULL; + unsigned long flags; + + /* Cancel current cmd */ + if ((adapter->curr_cmd) && (adapter->curr_cmd->wq_buf)) { + wait_queue = + (struct mwifiex_wait_queue *) adapter->curr_cmd->wq_buf; + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->curr_cmd->wq_buf = NULL; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL; + mwifiex_ioctl_complete(adapter, wait_queue, -1); + } + /* Cancel all pending command */ + spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); + list_for_each_entry_safe(cmd_node, tmp_node, + &adapter->cmd_pending_q, list) { + list_del(&cmd_node->list); + spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); + + if (cmd_node->wq_buf) { + wait_queue = + (struct mwifiex_wait_queue *) cmd_node->wq_buf; + wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL; + mwifiex_ioctl_complete(adapter, wait_queue, -1); + cmd_node->wq_buf = NULL; + } + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); + } + spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); + + /* Cancel all pending scan command */ + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + list_for_each_entry_safe(cmd_node, tmp_node, + &adapter->scan_pending_q, list) { + list_del(&cmd_node->list); + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + + cmd_node->wq_buf = NULL; + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + } + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->scan_processing = false; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); +} + +/* + * This function cancels all pending commands that matches with + * the given IOCTL request. + * + * Both the current command buffer and the pending command queue are + * searched for matching IOCTL request. The completion callback of + * the matched command is called with failure status to ensure cleanup. + * In case of scan commands, all pending commands in scan pending queue + * are cancelled. + */ +void +mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter, + struct mwifiex_wait_queue *wait_queue) +{ + struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; + unsigned long cmd_flags; + unsigned long cmd_pending_q_flags; + unsigned long scan_pending_q_flags; + uint16_t cancel_scan_cmd = false; + + if ((adapter->curr_cmd) && + (adapter->curr_cmd->wq_buf == wait_queue)) { + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); + cmd_node = adapter->curr_cmd; + cmd_node->wq_buf = NULL; + cmd_node->cmd_flag |= CMD_F_CANCELED; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); + } + + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); + while (1) { + cmd_node = mwifiex_get_pending_ioctl_cmd(adapter, wait_queue); + if (!cmd_node) + break; + + spin_lock_irqsave(&adapter->cmd_pending_q_lock, + cmd_pending_q_flags); + list_del(&cmd_node->list); + spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, + cmd_pending_q_flags); + + cmd_node->wq_buf = NULL; + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + } + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); + /* Cancel all pending scan command */ + spin_lock_irqsave(&adapter->scan_pending_q_lock, + scan_pending_q_flags); + list_for_each_entry_safe(cmd_node, tmp_node, + &adapter->scan_pending_q, list) { + if (cmd_node->wq_buf == wait_queue) { + list_del(&cmd_node->list); + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, + scan_pending_q_flags); + cmd_node->wq_buf = NULL; + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + spin_lock_irqsave(&adapter->scan_pending_q_lock, + scan_pending_q_flags); + cancel_scan_cmd = true; + } + } + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, + scan_pending_q_flags); + + if (cancel_scan_cmd) { + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); + adapter->scan_processing = false; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); + } + wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL; + mwifiex_ioctl_complete(adapter, wait_queue, -1); + + return; +} + +/* + * This function sends the sleep confirm command to firmware, if + * possible. + * + * The sleep confirm command cannot be issued if command response, + * data response or event response is awaiting handling, or if we + * are in the middle of sending a command, or expecting a command + * response. + */ +void +mwifiex_check_ps_cond(struct mwifiex_adapter *adapter) +{ + if (!adapter->cmd_sent && + !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter)) + mwifiex_dnld_sleep_confirm_cmd(adapter); + else + dev_dbg(adapter->dev, + "cmd: Delay Sleep Confirm (%s%s%s)\n", + (adapter->cmd_sent) ? "D" : "", + (adapter->curr_cmd) ? "C" : "", + (IS_CARD_RX_RCVD(adapter)) ? "R" : ""); +} + +/* + * This function sends a Host Sleep activated event to applications. + * + * This event is generated by the driver, with a blank event body. + */ +void +mwifiex_hs_activated_event(struct mwifiex_private *priv, u8 activated) +{ + if (activated) { + if (priv->adapter->is_hs_configured) { + priv->adapter->hs_activated = true; + dev_dbg(priv->adapter->dev, "event: hs_activated\n"); + priv->adapter->hs_activate_wait_q_woken = true; + wake_up_interruptible( + &priv->adapter->hs_activate_wait_q); + } else { + dev_dbg(priv->adapter->dev, "event: HS not configured\n"); + } + } else { + dev_dbg(priv->adapter->dev, "event: hs_deactivated\n"); + priv->adapter->hs_activated = false; + } +} + +/* + * This function handles the command response of a Host Sleep configuration + * command. + * + * Handling includes changing the header fields into CPU format + * and setting the current host sleep activation status in driver. + * + * In case host sleep status change, the function generates an event to + * notify the applications. + */ +int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct host_cmd_ds_802_11_hs_cfg_enh *phs_cfg = + &resp->params.opt_hs_cfg; + uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions); + + if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE)) { + mwifiex_hs_activated_event(priv, true); + return 0; + } else { + dev_dbg(adapter->dev, "cmd: CMD_RESP: HS_CFG cmd reply" + " result=%#x, conditions=0x%x gpio=0x%x gap=0x%x\n", + resp->result, conditions, + phs_cfg->params.hs_config.gpio, + phs_cfg->params.hs_config.gap); + } + if (conditions != HOST_SLEEP_CFG_CANCEL) { + adapter->is_hs_configured = true; + } else { + adapter->is_hs_configured = false; + if (adapter->hs_activated) + mwifiex_hs_activated_event(priv, false); + } + + return 0; +} + +/* + * This function wakes up the adapter and generates a Host Sleep + * cancel event on receiving the power up interrupt. + */ +void +mwifiex_process_hs_config(struct mwifiex_adapter *adapter) +{ + dev_dbg(adapter->dev, "info: %s: auto cancelling host sleep" + " since there is interrupt from the firmware\n", __func__); + + adapter->if_ops.wakeup(adapter); + adapter->hs_activated = false; + adapter->is_hs_configured = false; + mwifiex_hs_activated_event(mwifiex_get_priv(adapter, + MWIFIEX_BSS_ROLE_ANY), false); + return; +} + +/* + * This function handles the command response of a sleep confirm command. + * + * The function sets the card state to SLEEP if the response indicates success. + */ +void +mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter, + u8 *pbuf, u32 upld_len) +{ + struct host_cmd_ds_command *cmd = (struct host_cmd_ds_command *) pbuf; + struct mwifiex_private *priv = + mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + uint16_t result = le16_to_cpu(cmd->result); + uint16_t command = le16_to_cpu(cmd->command); + uint16_t seq_num = le16_to_cpu(cmd->seq_num); + + if (!upld_len) { + dev_err(adapter->dev, "%s: cmd size is 0\n", __func__); + return; + } + + /* Get BSS number and corresponding priv */ + priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num), + HostCmd_GET_BSS_TYPE(seq_num)); + if (!priv) + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + + /* Update sequence number */ + seq_num = HostCmd_GET_SEQ_NO(seq_num); + /* Clear RET_BIT from HostCmd */ + command &= HostCmd_CMD_ID_MASK; + + if (command != HostCmd_CMD_802_11_PS_MODE_ENH) { + dev_err(adapter->dev, "%s: received unexpected response for" + " cmd %x, result = %x\n", __func__, command, result); + return; + } + + if (result) { + dev_err(adapter->dev, "%s: sleep confirm cmd failed\n", + __func__); + adapter->pm_wakeup_card_req = false; + adapter->ps_state = PS_STATE_AWAKE; + return; + } + adapter->pm_wakeup_card_req = true; + if (adapter->is_hs_configured) + mwifiex_hs_activated_event(mwifiex_get_priv(adapter, + MWIFIEX_BSS_ROLE_ANY), true); + adapter->ps_state = PS_STATE_SLEEP; + cmd->command = cpu_to_le16(command); + cmd->seq_num = cpu_to_le16(seq_num); +} +EXPORT_SYMBOL_GPL(mwifiex_process_sleep_confirm_resp); + +/* + * This function prepares an enhanced power mode command. + * + * This function can be used to disable power save or to configure + * power save with auto PS or STA PS or auto deep sleep. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting Power Save bitmap, PS parameters TLV, PS mode TLV, + * auto deep sleep TLV (as required) + * - Ensuring correct endian-ness + */ +int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, uint16_t ps_bitmap, + void *data_buf) +{ + struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh = + &cmd->params.psmode_enh; + u8 *tlv = NULL; + u16 cmd_size = 0; + + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); + if (cmd_action == DIS_AUTO_PS) { + psmode_enh->action = cpu_to_le16(DIS_AUTO_PS); + psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); + cmd->size = cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE); + } else if (cmd_action == GET_PS) { + psmode_enh->action = cpu_to_le16(GET_PS); + psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); + cmd->size = cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE); + } else if (cmd_action == EN_AUTO_PS) { + psmode_enh->action = cpu_to_le16(EN_AUTO_PS); + psmode_enh->params.auto_ps.ps_bitmap = cpu_to_le16(ps_bitmap); + cmd_size = S_DS_GEN + AUTO_PS_FIX_SIZE; + tlv = (u8 *) cmd + cmd_size; + if (ps_bitmap & BITMAP_STA_PS) { + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_ie_types_ps_param *ps_tlv = + (struct mwifiex_ie_types_ps_param *) tlv; + struct mwifiex_ps_param *ps_mode = &ps_tlv->param; + ps_tlv->header.type = cpu_to_le16(TLV_TYPE_PS_PARAM); + ps_tlv->header.len = cpu_to_le16(sizeof(*ps_tlv) - + sizeof(struct mwifiex_ie_types_header)); + cmd_size += sizeof(*ps_tlv); + tlv += sizeof(*ps_tlv); + dev_dbg(adapter->dev, "cmd: PS Command: Enter PS\n"); + ps_mode->null_pkt_interval = + cpu_to_le16(adapter->null_pkt_interval); + ps_mode->multiple_dtims = + cpu_to_le16(adapter->multiple_dtim); + ps_mode->bcn_miss_timeout = + cpu_to_le16(adapter->bcn_miss_time_out); + ps_mode->local_listen_interval = + cpu_to_le16(adapter->local_listen_interval); + ps_mode->adhoc_wake_period = + cpu_to_le16(adapter->adhoc_awake_period); + ps_mode->delay_to_ps = + cpu_to_le16(adapter->delay_to_ps); + ps_mode->mode = + cpu_to_le16(adapter->enhanced_ps_mode); + + } + if (ps_bitmap & BITMAP_AUTO_DS) { + struct mwifiex_ie_types_auto_ds_param *auto_ps_tlv = + (struct mwifiex_ie_types_auto_ds_param *) tlv; + struct mwifiex_auto_ds_param *auto_ds = + &auto_ps_tlv->param; + u16 idletime = 0; + auto_ps_tlv->header.type = + cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM); + auto_ps_tlv->header.len = + cpu_to_le16(sizeof(*auto_ps_tlv) - + sizeof(struct mwifiex_ie_types_header)); + cmd_size += sizeof(*auto_ps_tlv); + tlv += sizeof(*auto_ps_tlv); + if (data_buf) + idletime = ((struct mwifiex_ds_auto_ds *) + data_buf)->idle_time; + dev_dbg(priv->adapter->dev, + "cmd: PS Command: Enter Auto Deep Sleep\n"); + auto_ds->deep_sleep_timeout = cpu_to_le16(idletime); + } + cmd->size = cpu_to_le16(cmd_size); + } + return 0; +} + +/* + * This function handles the command response of an enhanced power mode + * command. + * + * Handling includes changing the header fields into CPU format + * and setting the current enhanced power mode in driver. + */ +int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *data_buf) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct host_cmd_ds_802_11_ps_mode_enh *ps_mode = + &resp->params.psmode_enh; + uint16_t action = le16_to_cpu(ps_mode->action); + uint16_t ps_bitmap = le16_to_cpu(ps_mode->params.ps_bitmap); + uint16_t auto_ps_bitmap = + le16_to_cpu(ps_mode->params.auto_ps.ps_bitmap); + + dev_dbg(adapter->dev, "info: %s: PS_MODE cmd reply result=%#x action=%#X\n", + __func__, resp->result, action); + if (action == EN_AUTO_PS) { + if (auto_ps_bitmap & BITMAP_AUTO_DS) { + dev_dbg(adapter->dev, "cmd: Enabled auto deep sleep\n"); + priv->adapter->is_deep_sleep = true; + } + if (auto_ps_bitmap & BITMAP_STA_PS) { + dev_dbg(adapter->dev, "cmd: Enabled STA power save\n"); + if (adapter->sleep_period.period) + dev_dbg(adapter->dev, "cmd: set to uapsd/pps mode\n"); + } + } else if (action == DIS_AUTO_PS) { + if (ps_bitmap & BITMAP_AUTO_DS) { + priv->adapter->is_deep_sleep = false; + dev_dbg(adapter->dev, "cmd: Disabled auto deep sleep\n"); + } + if (ps_bitmap & BITMAP_STA_PS) { + dev_dbg(adapter->dev, "cmd: Disabled STA power save\n"); + if (adapter->sleep_period.period) { + adapter->delay_null_pkt = false; + adapter->tx_lock_flag = false; + adapter->pps_uapsd_mode = false; + } + } + } else if (action == GET_PS) { + if (ps_bitmap & (BITMAP_STA_PS | BITMAP_UAP_INACT_PS + | BITMAP_UAP_DTIM_PS)) + adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; + else + adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; + + dev_dbg(adapter->dev, "cmd: ps_bitmap=%#x\n", ps_bitmap); + + if (data_buf) { + /* This section is for get power save mode */ + struct mwifiex_ds_pm_cfg *pm_cfg = + (struct mwifiex_ds_pm_cfg *)data_buf; + if (ps_bitmap & BITMAP_STA_PS) + pm_cfg->param.ps_mode = 1; + else + pm_cfg->param.ps_mode = 0; + } + } + return 0; +} + +/* + * This function prepares command to get hardware specifications. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting permanent address parameter + * - Ensuring correct endian-ness + */ +int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd) +{ + struct host_cmd_ds_get_hw_spec *hw_spec = &cmd->params.hw_spec; + + cmd->command = cpu_to_le16(HostCmd_CMD_GET_HW_SPEC); + cmd->size = + cpu_to_le16(sizeof(struct host_cmd_ds_get_hw_spec) + S_DS_GEN); + memcpy(hw_spec->permanent_addr, priv->curr_addr, ETH_ALEN); + + return 0; +} + +/* + * This function handles the command response of get hardware + * specifications. + * + * Handling includes changing the header fields into CPU format + * and saving/updating the following parameters in driver - + * - Firmware capability information + * - Firmware band settings + * - Ad-hoc start band and channel + * - Ad-hoc 11n activation status + * - Firmware release number + * - Number of antennas + * - Hardware address + * - Hardware interface version + * - Firmware version + * - Region code + * - 11n capabilities + * - MCS support fields + * - MP end port + */ +int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec; + struct mwifiex_adapter *adapter = priv->adapter; + int i; + + adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info); + + if (IS_SUPPORT_MULTI_BANDS(adapter)) + adapter->fw_bands = (u8) GET_FW_DEFAULT_BANDS(adapter); + else + adapter->fw_bands = BAND_B; + + adapter->config_bands = adapter->fw_bands; + + if (adapter->fw_bands & BAND_A) { + if (adapter->fw_bands & BAND_GN) { + adapter->config_bands |= BAND_AN; + adapter->fw_bands |= BAND_AN; + } + if (adapter->fw_bands & BAND_AN) { + adapter->adhoc_start_band = BAND_A | BAND_AN; + adapter->adhoc_11n_enabled = true; + } else { + adapter->adhoc_start_band = BAND_A; + } + priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A; + } else if (adapter->fw_bands & BAND_GN) { + adapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN; + priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; + adapter->adhoc_11n_enabled = true; + } else if (adapter->fw_bands & BAND_G) { + adapter->adhoc_start_band = BAND_G | BAND_B; + priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; + } else if (adapter->fw_bands & BAND_B) { + adapter->adhoc_start_band = BAND_B; + priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; + } + + adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); + adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); + + dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n", + adapter->fw_release_number); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n", + hw_spec->permanent_addr); + dev_dbg(adapter->dev, "info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n", + le16_to_cpu(hw_spec->hw_if_version), + le16_to_cpu(hw_spec->version)); + + if (priv->curr_addr[0] == 0xff) + memmove(priv->curr_addr, hw_spec->permanent_addr, ETH_ALEN); + + adapter->region_code = le16_to_cpu(hw_spec->region_code); + + for (i = 0; i < MWIFIEX_MAX_REGION_CODE; i++) + /* Use the region code to search for the index */ + if (adapter->region_code == region_code_index[i]) + break; + + /* If it's unidentified region code, use the default (USA) */ + if (i >= MWIFIEX_MAX_REGION_CODE) { + adapter->region_code = 0x10; + dev_dbg(adapter->dev, "cmd: unknown region code, use default (USA)\n"); + } + + adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap); + adapter->usr_dot_11n_dev_cap = adapter->hw_dot_11n_dev_cap & + DEFAULT_11N_CAP_MASK; + adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support; + adapter->usr_dev_mcs_support = adapter->hw_dev_mcs_support; + mwifiex_show_dot_11n_dev_cap(adapter, adapter->hw_dot_11n_dev_cap); + mwifiex_show_dev_mcs_support(adapter, adapter->hw_dev_mcs_support); + + if (adapter->if_ops.update_mp_end_port) + adapter->if_ops.update_mp_end_port(adapter, + le16_to_cpu(hw_spec->mp_end_port)); + + return 0; +} diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c new file mode 100644 index 000000000000..63b09692f27d --- /dev/null +++ b/drivers/net/wireless/mwifiex/debugfs.c @@ -0,0 +1,773 @@ +/* + * Marvell Wireless LAN device driver: debugfs + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include + +#include "main.h" +#include "11n.h" + + +static struct dentry *mwifiex_dfs_dir; + +static char *bss_modes[] = { + "Unknown", + "Managed", + "Ad-hoc", + "Auto" +}; + +/* size/addr for mwifiex_debug_info */ +#define item_size(n) (FIELD_SIZEOF(struct mwifiex_debug_info, n)) +#define item_addr(n) (offsetof(struct mwifiex_debug_info, n)) + +/* size/addr for struct mwifiex_adapter */ +#define adapter_item_size(n) (FIELD_SIZEOF(struct mwifiex_adapter, n)) +#define adapter_item_addr(n) (offsetof(struct mwifiex_adapter, n)) + +struct mwifiex_debug_data { + char name[32]; /* variable/array name */ + u32 size; /* size of the variable/array */ + size_t addr; /* address of the variable/array */ + int num; /* number of variables in an array */ +}; + +static struct mwifiex_debug_data items[] = { + {"int_counter", item_size(int_counter), + item_addr(int_counter), 1}, + {"wmm_ac_vo", item_size(packets_out[WMM_AC_VO]), + item_addr(packets_out[WMM_AC_VO]), 1}, + {"wmm_ac_vi", item_size(packets_out[WMM_AC_VI]), + item_addr(packets_out[WMM_AC_VI]), 1}, + {"wmm_ac_be", item_size(packets_out[WMM_AC_BE]), + item_addr(packets_out[WMM_AC_BE]), 1}, + {"wmm_ac_bk", item_size(packets_out[WMM_AC_BK]), + item_addr(packets_out[WMM_AC_BK]), 1}, + {"max_tx_buf_size", item_size(max_tx_buf_size), + item_addr(max_tx_buf_size), 1}, + {"tx_buf_size", item_size(tx_buf_size), + item_addr(tx_buf_size), 1}, + {"curr_tx_buf_size", item_size(curr_tx_buf_size), + item_addr(curr_tx_buf_size), 1}, + {"ps_mode", item_size(ps_mode), + item_addr(ps_mode), 1}, + {"ps_state", item_size(ps_state), + item_addr(ps_state), 1}, + {"is_deep_sleep", item_size(is_deep_sleep), + item_addr(is_deep_sleep), 1}, + {"wakeup_dev_req", item_size(pm_wakeup_card_req), + item_addr(pm_wakeup_card_req), 1}, + {"wakeup_tries", item_size(pm_wakeup_fw_try), + item_addr(pm_wakeup_fw_try), 1}, + {"hs_configured", item_size(is_hs_configured), + item_addr(is_hs_configured), 1}, + {"hs_activated", item_size(hs_activated), + item_addr(hs_activated), 1}, + {"num_tx_timeout", item_size(num_tx_timeout), + item_addr(num_tx_timeout), 1}, + {"num_cmd_timeout", item_size(num_cmd_timeout), + item_addr(num_cmd_timeout), 1}, + {"timeout_cmd_id", item_size(timeout_cmd_id), + item_addr(timeout_cmd_id), 1}, + {"timeout_cmd_act", item_size(timeout_cmd_act), + item_addr(timeout_cmd_act), 1}, + {"last_cmd_id", item_size(last_cmd_id), + item_addr(last_cmd_id), DBG_CMD_NUM}, + {"last_cmd_act", item_size(last_cmd_act), + item_addr(last_cmd_act), DBG_CMD_NUM}, + {"last_cmd_index", item_size(last_cmd_index), + item_addr(last_cmd_index), 1}, + {"last_cmd_resp_id", item_size(last_cmd_resp_id), + item_addr(last_cmd_resp_id), DBG_CMD_NUM}, + {"last_cmd_resp_index", item_size(last_cmd_resp_index), + item_addr(last_cmd_resp_index), 1}, + {"last_event", item_size(last_event), + item_addr(last_event), DBG_CMD_NUM}, + {"last_event_index", item_size(last_event_index), + item_addr(last_event_index), 1}, + {"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure), + item_addr(num_cmd_host_to_card_failure), 1}, + {"num_cmd_sleep_cfm_fail", + item_size(num_cmd_sleep_cfm_host_to_card_failure), + item_addr(num_cmd_sleep_cfm_host_to_card_failure), 1}, + {"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure), + item_addr(num_tx_host_to_card_failure), 1}, + {"num_evt_deauth", item_size(num_event_deauth), + item_addr(num_event_deauth), 1}, + {"num_evt_disassoc", item_size(num_event_disassoc), + item_addr(num_event_disassoc), 1}, + {"num_evt_link_lost", item_size(num_event_link_lost), + item_addr(num_event_link_lost), 1}, + {"num_cmd_deauth", item_size(num_cmd_deauth), + item_addr(num_cmd_deauth), 1}, + {"num_cmd_assoc_ok", item_size(num_cmd_assoc_success), + item_addr(num_cmd_assoc_success), 1}, + {"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure), + item_addr(num_cmd_assoc_failure), 1}, + {"cmd_sent", item_size(cmd_sent), + item_addr(cmd_sent), 1}, + {"data_sent", item_size(data_sent), + item_addr(data_sent), 1}, + {"cmd_resp_received", item_size(cmd_resp_received), + item_addr(cmd_resp_received), 1}, + {"event_received", item_size(event_received), + item_addr(event_received), 1}, + + /* variables defined in struct mwifiex_adapter */ + {"ioctl_pending", adapter_item_size(ioctl_pending), + adapter_item_addr(ioctl_pending), 1}, + {"tx_pending", adapter_item_size(tx_pending), + adapter_item_addr(tx_pending), 1}, + {"rx_pending", adapter_item_size(rx_pending), + adapter_item_addr(rx_pending), 1}, +}; + +static int num_of_items = ARRAY_SIZE(items); + +/* + * Generic proc file open handler. + * + * This function is called every time a file is accessed for read or write. + */ +static int +mwifiex_open_generic(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +/* + * Proc info file read handler. + * + * This function is called when the 'info' file is opened for reading. + * It prints the following driver related information - + * - Driver name + * - Driver version + * - Driver extended version + * - Interface name + * - BSS mode + * - Media state (connected or disconnected) + * - MAC address + * - Total number of Tx bytes + * - Total number of Rx bytes + * - Total number of Tx packets + * - Total number of Rx packets + * - Total number of dropped Tx packets + * - Total number of dropped Rx packets + * - Total number of corrupted Tx packets + * - Total number of corrupted Rx packets + * - Carrier status (on or off) + * - Tx queue status (started or stopped) + * + * For STA mode drivers, it also prints the following extra - + * - ESSID + * - BSSID + * - Channel + * - Region code + * - Multicast count + * - Multicast addresses + */ +static ssize_t +mwifiex_info_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mwifiex_private *priv = + (struct mwifiex_private *) file->private_data; + struct net_device *netdev = priv->netdev; + struct netdev_hw_addr *ha; + unsigned long page = get_zeroed_page(GFP_KERNEL); + char *p = (char *) page, fmt[64]; + struct mwifiex_bss_info info; + ssize_t ret = 0; + int i = 0; + + if (!p) + return -ENOMEM; + + memset(&info, 0, sizeof(info)); + ret = mwifiex_get_bss_info(priv, &info); + if (ret) + goto free_and_exit; + + mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1); + + if (!priv->version_str[0]) + mwifiex_get_ver_ext(priv); + + p += sprintf(p, "driver_name = " "\"mwifiex\"\n"); + p += sprintf(p, "driver_version = %s", fmt); + p += sprintf(p, "\nverext = %s", priv->version_str); + p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name); + p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]); + p += sprintf(p, "media_state=\"%s\"\n", + (!priv->media_connected ? "Disconnected" : "Connected")); + p += sprintf(p, "mac_address=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", + netdev->dev_addr[0], netdev->dev_addr[1], + netdev->dev_addr[2], netdev->dev_addr[3], + netdev->dev_addr[4], netdev->dev_addr[5]); + + if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { + p += sprintf(p, "multicast_count=\"%d\"\n", + netdev_mc_count(netdev)); + p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid); + p += sprintf(p, "bssid=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", + info.bssid[0], info.bssid[1], + info.bssid[2], info.bssid[3], + info.bssid[4], info.bssid[5]); + p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); + p += sprintf(p, "region_code = \"%02x\"\n", info.region_code); + + netdev_for_each_mc_addr(ha, netdev) + p += sprintf(p, "multicast_address[%d]=" + "\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", i++, + ha->addr[0], ha->addr[1], + ha->addr[2], ha->addr[3], + ha->addr[4], ha->addr[5]); + } + + p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); + p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes); + p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets); + p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets); + p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped); + p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped); + p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors); + p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); + p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) + ? "on" : "off")); + p += sprintf(p, "tx queue %s\n", ((netif_queue_stopped(priv->netdev)) + ? "stopped" : "started")); + + ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, + (unsigned long) p - page); + +free_and_exit: + free_page(page); + return ret; +} + +/* + * Proc getlog file read handler. + * + * This function is called when the 'getlog' file is opened for reading + * It prints the following log information - + * - Number of multicast Tx frames + * - Number of failed packets + * - Number of Tx retries + * - Number of multicast Tx retries + * - Number of duplicate frames + * - Number of RTS successes + * - Number of RTS failures + * - Number of ACK failures + * - Number of fragmented Rx frames + * - Number of multicast Rx frames + * - Number of FCS errors + * - Number of Tx frames + * - WEP ICV error counts + */ +static ssize_t +mwifiex_getlog_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mwifiex_private *priv = + (struct mwifiex_private *) file->private_data; + unsigned long page = get_zeroed_page(GFP_KERNEL); + char *p = (char *) page; + ssize_t ret = 0; + struct mwifiex_ds_get_stats stats; + + if (!p) + return -ENOMEM; + + memset(&stats, 0, sizeof(stats)); + ret = mwifiex_get_stats_info(priv, &stats); + if (ret) + goto free_and_exit; + + p += sprintf(p, "\n" + "mcasttxframe %u\n" + "failed %u\n" + "retry %u\n" + "multiretry %u\n" + "framedup %u\n" + "rtssuccess %u\n" + "rtsfailure %u\n" + "ackfailure %u\n" + "rxfrag %u\n" + "mcastrxframe %u\n" + "fcserror %u\n" + "txframe %u\n" + "wepicverrcnt-1 %u\n" + "wepicverrcnt-2 %u\n" + "wepicverrcnt-3 %u\n" + "wepicverrcnt-4 %u\n", + stats.mcast_tx_frame, + stats.failed, + stats.retry, + stats.multi_retry, + stats.frame_dup, + stats.rts_success, + stats.rts_failure, + stats.ack_failure, + stats.rx_frag, + stats.mcast_rx_frame, + stats.fcs_error, + stats.tx_frame, + stats.wep_icv_error[0], + stats.wep_icv_error[1], + stats.wep_icv_error[2], + stats.wep_icv_error[3]); + + + ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, + (unsigned long) p - page); + +free_and_exit: + free_page(page); + return ret; +} + +static struct mwifiex_debug_info info; + +/* + * Proc debug file read handler. + * + * This function is called when the 'debug' file is opened for reading + * It prints the following log information - + * - Interrupt count + * - WMM AC VO packets count + * - WMM AC VI packets count + * - WMM AC BE packets count + * - WMM AC BK packets count + * - Maximum Tx buffer size + * - Tx buffer size + * - Current Tx buffer size + * - Power Save mode + * - Power Save state + * - Deep Sleep status + * - Device wakeup required status + * - Number of wakeup tries + * - Host Sleep configured status + * - Host Sleep activated status + * - Number of Tx timeouts + * - Number of command timeouts + * - Last timed out command ID + * - Last timed out command action + * - Last command ID + * - Last command action + * - Last command index + * - Last command response ID + * - Last command response index + * - Last event + * - Last event index + * - Number of host to card command failures + * - Number of sleep confirm command failures + * - Number of host to card data failure + * - Number of deauthentication events + * - Number of disassociation events + * - Number of link lost events + * - Number of deauthentication commands + * - Number of association success commands + * - Number of association failure commands + * - Number of commands sent + * - Number of data packets sent + * - Number of command responses received + * - Number of events received + * - Tx BA stream table (TID, RA) + * - Rx reorder table (TID, TA, Start window, Window size, Buffer) + */ +static ssize_t +mwifiex_debug_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mwifiex_private *priv = + (struct mwifiex_private *) file->private_data; + struct mwifiex_debug_data *d = &items[0]; + unsigned long page = get_zeroed_page(GFP_KERNEL); + char *p = (char *) page; + ssize_t ret = 0; + size_t size, addr; + long val; + int i, j; + + if (!p) + return -ENOMEM; + + ret = mwifiex_get_debug_info(priv, &info); + if (ret) + goto free_and_exit; + + for (i = 0; i < num_of_items; i++) { + p += sprintf(p, "%s=", d[i].name); + + size = d[i].size / d[i].num; + + if (i < (num_of_items - 3)) + addr = d[i].addr + (size_t) &info; + else /* The last 3 items are struct mwifiex_adapter variables */ + addr = d[i].addr + (size_t) priv->adapter; + + for (j = 0; j < d[i].num; j++) { + switch (size) { + case 1: + val = *((u8 *) addr); + break; + case 2: + val = *((u16 *) addr); + break; + case 4: + val = *((u32 *) addr); + break; + case 8: + val = *((long long *) addr); + break; + default: + val = -1; + break; + } + + p += sprintf(p, "%#lx ", val); + addr += size; + } + + p += sprintf(p, "\n"); + } + + if (info.tx_tbl_num) { + p += sprintf(p, "Tx BA stream table:\n"); + for (i = 0; i < info.tx_tbl_num; i++) + p += sprintf(p, "tid = %d, " + "ra = %02x:%02x:%02x:%02x:%02x:%02x\n", + info.tx_tbl[i].tid, info.tx_tbl[i].ra[0], + info.tx_tbl[i].ra[1], info.tx_tbl[i].ra[2], + info.tx_tbl[i].ra[3], info.tx_tbl[i].ra[4], + info.tx_tbl[i].ra[5]); + } + + if (info.rx_tbl_num) { + p += sprintf(p, "Rx reorder table:\n"); + for (i = 0; i < info.rx_tbl_num; i++) { + + p += sprintf(p, "tid = %d, " + "ta = %02x:%02x:%02x:%02x:%02x:%02x, " + "start_win = %d, " + "win_size = %d, buffer: ", + info.rx_tbl[i].tid, + info.rx_tbl[i].ta[0], info.rx_tbl[i].ta[1], + info.rx_tbl[i].ta[2], info.rx_tbl[i].ta[3], + info.rx_tbl[i].ta[4], info.rx_tbl[i].ta[5], + info.rx_tbl[i].start_win, + info.rx_tbl[i].win_size); + + for (j = 0; j < info.rx_tbl[i].win_size; j++) + p += sprintf(p, "%c ", + info.rx_tbl[i].buffer[j] ? + '1' : '0'); + + p += sprintf(p, "\n"); + } + } + + ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, + (unsigned long) p - page); + +free_and_exit: + free_page(page); + return ret; +} + +static u32 saved_reg_type, saved_reg_offset, saved_reg_value; + +/* + * Proc regrdwr file write handler. + * + * This function is called when the 'regrdwr' file is opened for writing + * + * This function can be used to write to a register. + */ +static ssize_t +mwifiex_regrdwr_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + unsigned long addr = get_zeroed_page(GFP_KERNEL); + char *buf = (char *) addr; + size_t buf_size = min(count, (size_t) (PAGE_SIZE - 1)); + int ret = 0; + u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX; + + if (!buf) + return -ENOMEM; + + + if (copy_from_user(buf, ubuf, buf_size)) { + ret = -EFAULT; + goto done; + } + + sscanf(buf, "%u %x %x", ®_type, ®_offset, ®_value); + + if (reg_type == 0 || reg_offset == 0) { + ret = -EINVAL; + goto done; + } else { + saved_reg_type = reg_type; + saved_reg_offset = reg_offset; + saved_reg_value = reg_value; + ret = count; + } +done: + free_page(addr); + return ret; +} + +/* + * Proc regrdwr file read handler. + * + * This function is called when the 'regrdwr' file is opened for reading + * + * This function can be used to read from a register. + */ +static ssize_t +mwifiex_regrdwr_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mwifiex_private *priv = + (struct mwifiex_private *) file->private_data; + unsigned long addr = get_zeroed_page(GFP_KERNEL); + char *buf = (char *) addr; + int pos = 0, ret = 0; + u32 reg_value; + + if (!buf) + return -ENOMEM; + + if (!saved_reg_type) { + /* No command has been given */ + pos += snprintf(buf, PAGE_SIZE, "0"); + goto done; + } + /* Set command has been given */ + if (saved_reg_value != UINT_MAX) { + ret = mwifiex_reg_write(priv, saved_reg_type, saved_reg_offset, + saved_reg_value); + + pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", + saved_reg_type, saved_reg_offset, + saved_reg_value); + + ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); + + goto done; + } + /* Get command has been given */ + ret = mwifiex_reg_read(priv, saved_reg_type, + saved_reg_offset, ®_value); + if (ret) { + ret = -EINVAL; + goto done; + } + + pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", saved_reg_type, + saved_reg_offset, reg_value); + + ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); + +done: + free_page(addr); + return ret; +} + +static u32 saved_offset = -1, saved_bytes = -1; + +/* + * Proc rdeeprom file write handler. + * + * This function is called when the 'rdeeprom' file is opened for writing + * + * This function can be used to write to a RDEEPROM location. + */ +static ssize_t +mwifiex_rdeeprom_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + unsigned long addr = get_zeroed_page(GFP_KERNEL); + char *buf = (char *) addr; + size_t buf_size = min(count, (size_t) (PAGE_SIZE - 1)); + int ret = 0; + int offset = -1, bytes = -1; + + if (!buf) + return -ENOMEM; + + + if (copy_from_user(buf, ubuf, buf_size)) { + ret = -EFAULT; + goto done; + } + + sscanf(buf, "%d %d", &offset, &bytes); + + if (offset == -1 || bytes == -1) { + ret = -EINVAL; + goto done; + } else { + saved_offset = offset; + saved_bytes = bytes; + ret = count; + } +done: + free_page(addr); + return ret; +} + +/* + * Proc rdeeprom read write handler. + * + * This function is called when the 'rdeeprom' file is opened for reading + * + * This function can be used to read from a RDEEPROM location. + */ +static ssize_t +mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mwifiex_private *priv = + (struct mwifiex_private *) file->private_data; + unsigned long addr = get_zeroed_page(GFP_KERNEL); + char *buf = (char *) addr; + int pos = 0, ret = 0, i = 0; + u8 value[MAX_EEPROM_DATA]; + + if (!buf) + return -ENOMEM; + + if (saved_offset == -1) { + /* No command has been given */ + pos += snprintf(buf, PAGE_SIZE, "0"); + goto done; + } + + /* Get command has been given */ + ret = mwifiex_eeprom_read(priv, (u16) saved_offset, + (u16) saved_bytes, value); + if (ret) { + ret = -EINVAL; + goto done; + } + + pos += snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes); + + for (i = 0; i < saved_bytes; i++) + pos += snprintf(buf + strlen(buf), PAGE_SIZE, "%d ", value[i]); + + ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); + +done: + free_page(addr); + return ret; +} + + +#define MWIFIEX_DFS_ADD_FILE(name) do { \ + if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir, \ + priv, &mwifiex_dfs_##name##_fops)) \ + return; \ +} while (0); + +#define MWIFIEX_DFS_FILE_OPS(name) \ +static const struct file_operations mwifiex_dfs_##name##_fops = { \ + .read = mwifiex_##name##_read, \ + .write = mwifiex_##name##_write, \ + .open = mwifiex_open_generic, \ +}; + +#define MWIFIEX_DFS_FILE_READ_OPS(name) \ +static const struct file_operations mwifiex_dfs_##name##_fops = { \ + .read = mwifiex_##name##_read, \ + .open = mwifiex_open_generic, \ +}; + +#define MWIFIEX_DFS_FILE_WRITE_OPS(name) \ +static const struct file_operations mwifiex_dfs_##name##_fops = { \ + .write = mwifiex_##name##_write, \ + .open = mwifiex_open_generic, \ +}; + + +MWIFIEX_DFS_FILE_READ_OPS(info); +MWIFIEX_DFS_FILE_READ_OPS(debug); +MWIFIEX_DFS_FILE_READ_OPS(getlog); +MWIFIEX_DFS_FILE_OPS(regrdwr); +MWIFIEX_DFS_FILE_OPS(rdeeprom); + +/* + * This function creates the debug FS directory structure and the files. + */ +void +mwifiex_dev_debugfs_init(struct mwifiex_private *priv) +{ + if (!mwifiex_dfs_dir || !priv) + return; + + priv->dfs_dev_dir = debugfs_create_dir(priv->netdev->name, + mwifiex_dfs_dir); + + if (!priv->dfs_dev_dir) + return; + + MWIFIEX_DFS_ADD_FILE(info); + MWIFIEX_DFS_ADD_FILE(debug); + MWIFIEX_DFS_ADD_FILE(getlog); + MWIFIEX_DFS_ADD_FILE(regrdwr); + MWIFIEX_DFS_ADD_FILE(rdeeprom); + + return; +} + +/* + * This function removes the debug FS directory structure and the files. + */ +void +mwifiex_dev_debugfs_remove(struct mwifiex_private *priv) +{ + if (!priv) + return; + + debugfs_remove_recursive(priv->dfs_dev_dir); + return; +} + +/* + * This function creates the top level proc directory. + */ +void +mwifiex_debugfs_init(void) +{ + if (!mwifiex_dfs_dir) + mwifiex_dfs_dir = debugfs_create_dir("mwifiex", NULL); +} + +/* + * This function removes the top level proc directory. + */ +void +mwifiex_debugfs_remove(void) +{ + if (mwifiex_dfs_dir) + debugfs_remove(mwifiex_dfs_dir); +} diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h new file mode 100644 index 000000000000..4e1f115d3ec3 --- /dev/null +++ b/drivers/net/wireless/mwifiex/decl.h @@ -0,0 +1,177 @@ +/* + * Marvell Wireless LAN device driver: generic data structures and APIs + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#ifndef _MWIFIEX_DECL_H_ +#define _MWIFIEX_DECL_H_ + +#undef pr_fmt +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include + + +#define MWIFIEX_MAX_BSS_NUM (1) + +#define MWIFIEX_MIN_DATA_HEADER_LEN 32 /* (sizeof(mwifiex_txpd)) */ + +#define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2 +#define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16 + +#define MWIFIEX_AMPDU_DEF_TXWINSIZE 32 +#define MWIFIEX_AMPDU_DEF_RXWINSIZE 16 +#define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff + +#define MWIFIEX_RATE_INDEX_HRDSSS0 0 +#define MWIFIEX_RATE_INDEX_HRDSSS3 3 +#define MWIFIEX_RATE_INDEX_OFDM0 4 +#define MWIFIEX_RATE_INDEX_OFDM7 11 +#define MWIFIEX_RATE_INDEX_MCS0 12 + +#define MWIFIEX_RATE_BITMAP_OFDM0 16 +#define MWIFIEX_RATE_BITMAP_OFDM7 23 +#define MWIFIEX_RATE_BITMAP_MCS0 32 +#define MWIFIEX_RATE_BITMAP_MCS127 159 + +#define MWIFIEX_RX_DATA_BUF_SIZE (4 * 1024) +#define MWIFIEX_RX_CMD_BUF_SIZE (2 * 1024) + +#define MWIFIEX_RTS_MIN_VALUE (0) +#define MWIFIEX_RTS_MAX_VALUE (2347) +#define MWIFIEX_FRAG_MIN_VALUE (256) +#define MWIFIEX_FRAG_MAX_VALUE (2346) + +#define MWIFIEX_SDIO_BLOCK_SIZE 256 + +#define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0) + +enum mwifiex_error_code { + MWIFIEX_ERROR_NO_ERROR = 0, + MWIFIEX_ERROR_FW_NOT_READY = 0x00000001, + MWIFIEX_ERROR_FW_BUSY, + MWIFIEX_ERROR_FW_CMDRESP, + MWIFIEX_ERROR_PKT_SIZE_INVALID = 0x80000001, + MWIFIEX_ERROR_PKT_TIMEOUT, + MWIFIEX_ERROR_CMD_INVALID, + MWIFIEX_ERROR_CMD_TIMEOUT, + MWIFIEX_ERROR_CMD_DNLD_FAIL, + MWIFIEX_ERROR_CMD_CANCEL, + MWIFIEX_ERROR_CMD_RESP_FAIL, + MWIFIEX_ERROR_ASSOC_FAIL, + MWIFIEX_ERROR_EVENT_UNKNOWN, + MWIFIEX_ERROR_INVALID_PARAMETER, +}; + +enum mwifiex_bss_type { + MWIFIEX_BSS_TYPE_STA = 0, + MWIFIEX_BSS_TYPE_UAP = 1, + MWIFIEX_BSS_TYPE_ANY = 0xff, +}; + +enum mwifiex_bss_role { + MWIFIEX_BSS_ROLE_STA = 0, + MWIFIEX_BSS_ROLE_UAP = 1, + MWIFIEX_BSS_ROLE_ANY = 0xff, +}; + +#define BSS_ROLE_BIT_MASK BIT(0) + +#define GET_BSS_ROLE(priv) ((priv)->bss_role & BSS_ROLE_BIT_MASK) + +enum mwifiex_data_frame_type { + MWIFIEX_DATA_FRAME_TYPE_ETH_II = 0, + MWIFIEX_DATA_FRAME_TYPE_802_11, +}; + +struct mwifiex_fw_image { + u8 *helper_buf; + u32 helper_len; + u8 *fw_buf; + u32 fw_len; +}; + +struct mwifiex_802_11_ssid { + u32 ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; +}; + +struct mwifiex_wait_queue { + u32 bss_index; + wait_queue_head_t *wait; + u16 *condition; + u32 start_time; + int status; + u32 enabled; +}; + +struct mwifiex_rxinfo { + u8 bss_index; + struct sk_buff *parent; + u8 use_count; +}; + +struct mwifiex_txinfo { + u32 status_code; + u8 flags; + u8 bss_index; +}; + +struct mwifiex_bss_attr { + u32 bss_type; + u32 frame_type; + u32 active; + u32 bss_priority; + u32 bss_num; +}; + +enum mwifiex_cmd_result_e { + MWIFIEX_CMD_RESULT_SUCCESS = 0, + MWIFIEX_CMD_RESULT_FAILURE = 1, + MWIFIEX_CMD_RESULT_TIMEOUT = 2, + MWIFIEX_CMD_RESULT_INVALID_DATA = 3 +} __packed; + +enum mwifiex_wmm_ac_e { + WMM_AC_BK, + WMM_AC_BE, + WMM_AC_VI, + WMM_AC_VO +} __packed; + +enum mwifiex_wmm_queue_config_action_e { + MWIFIEX_WMM_QUEUE_CONFIG_ACTION_GET = 0, + MWIFIEX_WMM_QUEUE_CONFIG_ACTION_SET = 1, + MWIFIEX_WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2, + MWIFIEX_WMM_QUEUE_CONFIG_ACTION_MAX +} __packed; + +enum mwifiex_wmm_queue_stats_action_e { + MWIFIEX_WMM_STATS_ACTION_START = 0, + MWIFIEX_WMM_STATS_ACTION_STOP = 1, + MWIFIEX_WMM_STATS_ACTION_GET_CLR = 2, + MWIFIEX_WMM_STATS_ACTION_SET_CFG = 3, /* Not currently used */ + MWIFIEX_WMM_STATS_ACTION_GET_CFG = 4, /* Not currently used */ + MWIFIEX_WMM_STATS_ACTION_MAX +} __packed; + +struct mwifiex_device { + struct mwifiex_bss_attr bss_attr[MWIFIEX_MAX_BSS_NUM]; +}; +#endif /* !_MWIFIEX_DECL_H_ */ diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h new file mode 100644 index 000000000000..e5dae45b11d2 --- /dev/null +++ b/drivers/net/wireless/mwifiex/fw.h @@ -0,0 +1,1376 @@ +/* + * Marvell Wireless LAN device driver: Firmware specific macros & structures + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#ifndef _MWIFIEX_FW_H_ +#define _MWIFIEX_FW_H_ + +#include + + +#define INTF_HEADER_LEN 4 + +struct rfc_1042_hdr { + u8 llc_dsap; + u8 llc_ssap; + u8 llc_ctrl; + u8 snap_oui[3]; + u16 snap_type; +}; + +struct rx_packet_hdr { + struct ethhdr eth803_hdr; + struct rfc_1042_hdr rfc1042_hdr; +}; + +struct tx_packet_hdr { + struct ethhdr eth803_hdr; + struct rfc_1042_hdr rfc1042_hdr; +}; + +#define B_SUPPORTED_RATES 5 +#define G_SUPPORTED_RATES 9 +#define BG_SUPPORTED_RATES 13 +#define A_SUPPORTED_RATES 9 +#define HOSTCMD_SUPPORTED_RATES 14 +#define N_SUPPORTED_RATES 3 +#define ALL_802_11_BANDS (BAND_A | BAND_B | BAND_G | BAND_GN) + +#define FW_MULTI_BANDS_SUPPORT (BIT(8) | BIT(9) | BIT(10) | BIT(11)) +#define IS_SUPPORT_MULTI_BANDS(adapter) \ + (adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT) +#define GET_FW_DEFAULT_BANDS(adapter) \ + ((adapter->fw_cap_info >> 8) & ALL_802_11_BANDS) + +#define SHORT_SLOT_TIME_DISABLED(CapInfo) (CapInfo &= ~BIT(10)) +#define SHORT_SLOT_TIME_ENABLED(CapInfo) (CapInfo |= BIT(10)) + +extern u8 supported_rates_b[B_SUPPORTED_RATES]; +extern u8 supported_rates_g[G_SUPPORTED_RATES]; +extern u8 supported_rates_bg[BG_SUPPORTED_RATES]; +extern u8 supported_rates_a[A_SUPPORTED_RATES]; +extern u8 supported_rates_n[N_SUPPORTED_RATES]; + +#define HostCmd_WEP_KEY_INDEX_MASK 0x3fff + +#define KEY_INFO_ENABLED 0x01 +enum KEY_TYPE_ID { + KEY_TYPE_ID_WEP = 0, + KEY_TYPE_ID_TKIP, + KEY_TYPE_ID_AES, + KEY_TYPE_ID_WAPI, +}; + +enum KEY_INFO_WEP { + KEY_INFO_WEP_MCAST = 0x01, + KEY_INFO_WEP_UNICAST = 0x02, + KEY_INFO_WEP_ENABLED = 0x04 +}; + +enum KEY_INFO_TKIP { + KEY_INFO_TKIP_MCAST = 0x01, + KEY_INFO_TKIP_UNICAST = 0x02, + KEY_INFO_TKIP_ENABLED = 0x04 +}; + +enum KEY_INFO_AES { + KEY_INFO_AES_MCAST = 0x01, + KEY_INFO_AES_UNICAST = 0x02, + KEY_INFO_AES_ENABLED = 0x04 +}; + +#define WAPI_KEY_LEN 50 + +enum KEY_INFO_WAPI { + KEY_INFO_WAPI_MCAST = 0x01, + KEY_INFO_WAPI_UNICAST = 0x02, + KEY_INFO_WAPI_ENABLED = 0x04 +}; + +#define MAX_POLL_TRIES 100 + +#define MAX_MULTI_INTERFACE_POLL_TRIES 1000 + +#define MAX_FIRMWARE_POLL_TRIES 100 + +#define FIRMWARE_READY 0xfedc + +#define FIRMWARE_TRANSFER_NBLOCK 2 + +enum MWIFIEX_802_11_PRIVACY_FILTER { + MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL, + MWIFIEX_802_11_PRIV_FILTER_8021X_WEP +}; + +enum MWIFIEX_802_11_WEP_STATUS { + MWIFIEX_802_11_WEP_ENABLED, + MWIFIEX_802_11_WEP_DISABLED, +}; + +#define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF))) + +#define PROPRIETARY_TLV_BASE_ID 0x0100 +#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) +#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) +#define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2) +#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 4) +#define TLV_TYPE_SNR_LOW (PROPRIETARY_TLV_BASE_ID + 5) +#define TLV_TYPE_FAILCOUNT (PROPRIETARY_TLV_BASE_ID + 6) +#define TLV_TYPE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 7) +#define TLV_TYPE_LEDBEHAVIOR (PROPRIETARY_TLV_BASE_ID + 9) +#define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10) +#define TLV_TYPE_POWER_TBL_2_4GHZ (PROPRIETARY_TLV_BASE_ID + 12) +#define TLV_TYPE_POWER_TBL_5GHZ (PROPRIETARY_TLV_BASE_ID + 13) +#define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16) +#define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) +#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) +#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) +#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23) + +#define TLV_TYPE_STARTBGSCANLATER (PROPRIETARY_TLV_BASE_ID + 30) +#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) +#define TLV_TYPE_LINK_QUALITY (PROPRIETARY_TLV_BASE_ID + 36) +#define TLV_TYPE_RSSI_LOW_DATA (PROPRIETARY_TLV_BASE_ID + 38) +#define TLV_TYPE_SNR_LOW_DATA (PROPRIETARY_TLV_BASE_ID + 39) +#define TLV_TYPE_RSSI_HIGH_DATA (PROPRIETARY_TLV_BASE_ID + 40) +#define TLV_TYPE_SNR_HIGH_DATA (PROPRIETARY_TLV_BASE_ID + 41) + +#define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) +#define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) +#define TLV_TYPE_BSSID (PROPRIETARY_TLV_BASE_ID + 35) + +#define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 + +#define TLV_TYPE_HT_CAP (PROPRIETARY_TLV_BASE_ID + 74) +#define TLV_TYPE_HT_INFO (PROPRIETARY_TLV_BASE_ID + 75) +#define TLV_SECONDARY_CHANNEL_OFFSET (PROPRIETARY_TLV_BASE_ID + 76) +#define TLV_TYPE_2040BSS_COEXISTENCE (PROPRIETARY_TLV_BASE_ID + 77) +#define TLV_TYPE_OVERLAP_BSS_SCAN_PARAM (PROPRIETARY_TLV_BASE_ID + 78) +#define TLV_TYPE_EXTCAP (PROPRIETARY_TLV_BASE_ID + 79) +#define TLV_TYPE_HT_OPERATIONAL_MCS_SET (PROPRIETARY_TLV_BASE_ID + 80) + +#define ADDBA_TID_MASK (BIT(2) | BIT(3) | BIT(4) | BIT(5)) +#define DELBA_TID_MASK (BIT(12) | BIT(13) | BIT(14) | BIT(15)) +#define SSN_MASK 0xfff0 + +#define BA_RESULT_SUCCESS 0x0 +#define BA_RESULT_FAILURE 0x1 +#define BA_RESULT_TIMEOUT 0x2 +#define BA_RESULT_DATA_INVALID 0x3 + +#define IS_BASTREAM_SETUP(ptr) (ptr->ba_status) + +#define BA_STREAM_NOT_ALLOWED 0xff + +#define IS_11N_ENABLED(priv) ((priv->adapter->config_bands & BAND_GN || \ + priv->adapter->config_bands & BAND_AN) \ + && priv->curr_bss_params.bss_descriptor.bcn_ht_cap) +#define INITIATOR_BIT(DelBAParamSet) (((DelBAParamSet) &\ + BIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS) + +#define MWIFIEX_TX_DATA_BUF_SIZE_4K 4096 +#define MWIFIEX_TX_DATA_BUF_SIZE_8K 8192 +#define MAX_RX_AMPDU_SIZE_64K 0x03 +#define NON_GREENFIELD_STAS 0x04 + +#define HWSPEC_GREENFIELD_SUPP BIT(29) +#define HWSPEC_RXSTBC_SUPP BIT(26) +#define HWSPEC_SHORTGI40_SUPP BIT(24) +#define HWSPEC_SHORTGI20_SUPP BIT(23) +#define HWSPEC_CHANBW40_SUPP BIT(17) + +#define DEFAULT_11N_CAP_MASK (HWSPEC_SHORTGI20_SUPP | HWSPEC_RXSTBC_SUPP) +#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) +#define ISSUPP_MAXAMSDU(Dot11nDevCap) (Dot11nDevCap & BIT(31)) +#define ISSUPP_BEAMFORMING(Dot11nDevCap) (Dot11nDevCap & BIT(30)) +#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) +#define ISSUPP_AMPDU(Dot11nDevCap) (Dot11nDevCap & BIT(28)) +#define ISSUPP_MIMOPS(Dot11nDevCap) (Dot11nDevCap & BIT(27)) +#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26)) +#define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(25)) +#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & BIT(24)) +#define ISSUPP_SHORTGI20(Dot11nDevCap) (Dot11nDevCap & BIT(23)) +#define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & BIT(22)) +#define GET_DELAYEDBACK(Dot11nDevCap) (((Dot11nDevCap >> 20) & 0x03)) +#define GET_IMMEDIATEBACK(Dot11nDevCap) (((Dot11nDevCap >> 18) & 0x03)) +#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & BIT(17)) +#define ISSUPP_CHANWIDTH20(Dot11nDevCap) (Dot11nDevCap & BIT(16)) +#define ISSUPP_CHANWIDTH10(Dot11nDevCap) (Dot11nDevCap & BIT(15)) +#define ISENABLED_40MHZ_INTOLARENT(Dot11nDevCap) (Dot11nDevCap & BIT(8)) +#define ISSUPP_RXANTENNAD(Dot11nDevCap) (Dot11nDevCap & BIT(7)) +#define ISSUPP_RXANTENNAC(Dot11nDevCap) (Dot11nDevCap & BIT(6)) +#define ISSUPP_RXANTENNAB(Dot11nDevCap) (Dot11nDevCap & BIT(5)) +#define ISSUPP_RXANTENNAA(Dot11nDevCap) (Dot11nDevCap & BIT(4)) +#define ISSUPP_TXANTENNAD(Dot11nDevCap) (Dot11nDevCap & BIT(3)) +#define ISSUPP_TXANTENNAC(Dot11nDevCap) (Dot11nDevCap & BIT(2)) +#define ISSUPP_TXANTENNAB(Dot11nDevCap) (Dot11nDevCap & BIT(1)) +#define ISSUPP_TXANTENNAA(Dot11nDevCap) (Dot11nDevCap & BIT(0)) +#define SETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap |= BIT(17)) +#define RESETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap &= ~BIT(17)) +#define GET_TXMCSSUPP(DevMCSSupported) (DevMCSSupported >> 4) +#define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f) +#define GETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo & BIT(1)) +#define GETHT_GREENFIELD(HTCapInfo) (HTCapInfo & BIT(4)) +#define GETHT_SHORTGI20(HTCapInfo) (HTCapInfo & BIT(5)) +#define GETHT_SHORTGI40(HTCapInfo) (HTCapInfo & BIT(6)) +#define GETHT_TXSTBC(HTCapInfo) (HTCapInfo & BIT(7)) +#define GETHT_RXSTBC(HTCapInfo) ((HTCapInfo >> 8) & 0x03) +#define GETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo & BIT(10)) +#define GETHT_MAXAMSDU(HTCapInfo) (HTCapInfo & BIT(11)) +#define SETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo |= BIT(1)) +#define SETHT_GREENFIELD(HTCapInfo) (HTCapInfo |= BIT(4)) +#define SETHT_SHORTGI20(HTCapInfo) (HTCapInfo |= BIT(5)) +#define SETHT_SHORTGI40(HTCapInfo) (HTCapInfo |= BIT(6)) +#define SETHT_TXSTBC(HTCapInfo) (HTCapInfo |= BIT(7)) +#define SETHT_RXSTBC(HTCapInfo, value) (HTCapInfo |= (value << 8)) +#define SETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo |= BIT(10)) +#define SETHT_MAXAMSDU(HTCapInfo) (HTCapInfo |= BIT(11)) +#define SETHT_DSSSCCK40(HTCapInfo) (HTCapInfo |= BIT(12)) +#define SETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo |= BIT(14)) +#define RESETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo &= ~BIT(1)) +#define RESETHT_GREENFIELD(HTCapInfo) (HTCapInfo &= ~BIT(4)) +#define RESETHT_SHORTGI20(HTCapInfo) (HTCapInfo &= ~BIT(5)) +#define RESETHT_SHORTGI40(HTCapInfo) (HTCapInfo &= ~BIT(6)) +#define RESETHT_TXSTBC(HTCapInfo) (HTCapInfo &= ~BIT(7)) +#define RESETHT_RXSTBC(HTCapInfo) (HTCapInfo &= ~(0x03 << 8)) +#define RESETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo &= ~BIT(10)) +#define RESETHT_MAXAMSDU(HTCapInfo) (HTCapInfo &= ~BIT(11)) +#define RESETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo &= ~BIT(14)) +#define RESETHT_EXTCAP_RDG(HTExtCap) (HTExtCap &= ~BIT(11)) +#define SETHT_MCS32(x) (x[4] |= 1) +#define SETHT_MCS_SET_DEFINED(x) (x[12] |= 1) +#define SETHT_RX_HIGHEST_DT_SUPP(x, y) ((*(u16 *) (x + 10)) = y) +#define AMPDU_FACTOR_64K 0x03 +#define SETAMPDU_SIZE(x, y) do { \ + x = x & ~0x03; \ + x |= y & 0x03; \ +} while (0) \ + +#define SETAMPDU_SPACING(x, y) do { \ + x = x & ~0x1c; \ + x |= (y & 0x07) << 2; \ +} while (0) \ + +#define ISSUPP_BANDA(FwCapInfo) (FwCapInfo & BIT(10)) +#define ISALLOWED_CHANWIDTH40(Field2) (Field2 & BIT(2)) +#define SET_CHANWIDTH40(Field2) (Field2 |= BIT(2)) +#define RESET_CHANWIDTH40(Field2) (Field2 &= ~(BIT(0) | BIT(1) | BIT(2))) +#define GET_SECONDARYCHAN(Field2) (Field2 & (BIT(0) | BIT(1))) +#define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4)) + +#define LLC_SNAP_LEN 8 + +#define TLV_TYPE_RATE_DROP_PATTERN (PROPRIETARY_TLV_BASE_ID + 81) +#define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) +#define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) + +#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) + +#define MOD_CLASS_HR_DSSS 0x03 +#define MOD_CLASS_OFDM 0x07 +#define MOD_CLASS_HT 0x08 +#define HT_BW_20 0 +#define HT_BW_40 1 + +#define HostCmd_CMD_GET_HW_SPEC 0x0003 +#define HostCmd_CMD_802_11_SCAN 0x0006 +#define HostCmd_CMD_802_11_GET_LOG 0x000b +#define HostCmd_CMD_MAC_MULTICAST_ADR 0x0010 +#define HostCmd_CMD_802_11_EEPROM_ACCESS 0x0059 +#define HostCmd_CMD_802_11_ASSOCIATE 0x0012 +#define HostCmd_CMD_802_11_SNMP_MIB 0x0016 +#define HostCmd_CMD_MAC_REG_ACCESS 0x0019 +#define HostCmd_CMD_BBP_REG_ACCESS 0x001a +#define HostCmd_CMD_RF_REG_ACCESS 0x001b +#define HostCmd_CMD_PMIC_REG_ACCESS 0x00ad +#define HostCmd_CMD_802_11_RF_CHANNEL 0x001d +#define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024 +#define HostCmd_CMD_MAC_CONTROL 0x0028 +#define HostCmd_CMD_802_11_AD_HOC_START 0x002b +#define HostCmd_CMD_802_11_AD_HOC_JOIN 0x002c +#define HostCmd_CMD_802_11_AD_HOC_STOP 0x0040 +#define HostCmd_CMD_802_11_MAC_ADDRESS 0x004D +#define HostCmd_CMD_802_11D_DOMAIN_INFO 0x005b +#define HostCmd_CMD_802_11_KEY_MATERIAL 0x005e +#define HostCmd_CMD_802_11_BG_SCAN_QUERY 0x006c +#define HostCmd_CMD_WMM_GET_STATUS 0x0071 +#define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f +#define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 +#define HostCmd_CMD_VERSION_EXT 0x0097 +#define HostCmd_CMD_RSSI_INFO 0x00a4 +#define HostCmd_CMD_FUNC_INIT 0x00a9 +#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa +#define HostCmd_CMD_11N_CFG 0x00cd +#define HostCmd_CMD_11N_ADDBA_REQ 0x00ce +#define HostCmd_CMD_11N_ADDBA_RSP 0x00cf +#define HostCmd_CMD_11N_DELBA 0x00d0 +#define HostCmd_CMD_RECONFIGURE_TX_BUFF 0x00d9 +#define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df +#define HostCmd_CMD_TXPWR_CFG 0x00d1 +#define HostCmd_CMD_TX_RATE_CFG 0x00d6 +#define HostCmd_CMD_802_11_PS_MODE_ENH 0x00e4 +#define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5 +#define HostCmd_CMD_CAU_REG_ACCESS 0x00ed +#define HostCmd_CMD_SET_BSS_MODE 0x00f7 + + +enum ENH_PS_MODES { + EN_PS = 1, + DIS_PS = 2, + EN_AUTO_DS = 3, + DIS_AUTO_DS = 4, + SLEEP_CONFIRM = 5, + GET_PS = 0, + EN_AUTO_PS = 0xff, + DIS_AUTO_PS = 0xfe, +}; + +#define HostCmd_RET_BIT 0x8000 +#define HostCmd_ACT_GEN_GET 0x0000 +#define HostCmd_ACT_GEN_SET 0x0001 +#define HostCmd_ACT_GEN_REMOVE 0x0004 +#define HostCmd_ACT_SET_BOTH 0x0003 +#define HostCmd_ACT_GET_BOTH 0x000c +#define HostCmd_RESULT_OK 0x0000 +#define HostCmd_RESULT_ERROR 0x0001 +#define HostCmd_RESULT_NOT_SUPPORT 0x0002 +#define HostCmd_RESULT_PENDING 0x0003 +#define HostCmd_RESULT_BUSY 0x0004 +#define HostCmd_RESULT_PARTIAL_DATA 0x0005 + +#define HostCmd_ACT_MAC_RX_ON 0x0001 +#define HostCmd_ACT_MAC_TX_ON 0x0002 +#define HostCmd_ACT_MAC_WEP_ENABLE 0x0008 +#define HostCmd_ACT_MAC_ETHERNETII_ENABLE 0x0010 +#define HostCmd_ACT_MAC_PROMISCUOUS_ENABLE 0x0080 +#define HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 +#define HostCmd_ACT_MAC_RTS_CTS_ENABLE 0x0200 +#define HostCmd_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400 +#define HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON 0x2000 + +#define HostCmd_BSS_MODE_BSS 0x0001 +#define HostCmd_BSS_MODE_IBSS 0x0002 +#define HostCmd_BSS_MODE_ANY 0x0003 + +#define HostCmd_SCAN_RADIO_TYPE_BG 0 +#define HostCmd_SCAN_RADIO_TYPE_A 1 + +#define HOST_SLEEP_CFG_CANCEL 0xffffffff +#define HOST_SLEEP_CFG_COND_DEF 0x0000000f +#define HOST_SLEEP_CFG_GPIO_DEF 0xff +#define HOST_SLEEP_CFG_GAP_DEF 0 + +#define CMD_F_HOSTCMD (1 << 0) +#define CMD_F_CANCELED (1 << 1) + +#define HostCmd_CMD_ID_MASK 0x0fff + +#define HostCmd_SEQ_NUM_MASK 0x00ff + +#define HostCmd_BSS_NUM_MASK 0x0f00 + +#define HostCmd_BSS_TYPE_MASK 0xf000 + +#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) { \ + (((seq) & 0x00ff) | \ + (((num) & 0x000f) << 8)) | \ + (((type) & 0x000f) << 12); } + +#define HostCmd_GET_SEQ_NO(seq) \ + ((seq) & HostCmd_SEQ_NUM_MASK) + +#define HostCmd_GET_BSS_NO(seq) \ + (((seq) & HostCmd_BSS_NUM_MASK) >> 8) + +#define HostCmd_GET_BSS_TYPE(seq) \ + (((seq) & HostCmd_BSS_TYPE_MASK) >> 12) + +#define EVENT_DUMMY_HOST_WAKEUP_SIGNAL 0x00000001 +#define EVENT_LINK_LOST 0x00000003 +#define EVENT_LINK_SENSED 0x00000004 +#define EVENT_MIB_CHANGED 0x00000006 +#define EVENT_INIT_DONE 0x00000007 +#define EVENT_DEAUTHENTICATED 0x00000008 +#define EVENT_DISASSOCIATED 0x00000009 +#define EVENT_PS_AWAKE 0x0000000a +#define EVENT_PS_SLEEP 0x0000000b +#define EVENT_MIC_ERR_MULTICAST 0x0000000d +#define EVENT_MIC_ERR_UNICAST 0x0000000e +#define EVENT_DEEP_SLEEP_AWAKE 0x00000010 +#define EVENT_ADHOC_BCN_LOST 0x00000011 + +#define EVENT_WMM_STATUS_CHANGE 0x00000017 +#define EVENT_BG_SCAN_REPORT 0x00000018 +#define EVENT_RSSI_LOW 0x00000019 +#define EVENT_SNR_LOW 0x0000001a +#define EVENT_MAX_FAIL 0x0000001b +#define EVENT_RSSI_HIGH 0x0000001c +#define EVENT_SNR_HIGH 0x0000001d +#define EVENT_IBSS_COALESCED 0x0000001e +#define EVENT_DATA_RSSI_LOW 0x00000024 +#define EVENT_DATA_SNR_LOW 0x00000025 +#define EVENT_DATA_RSSI_HIGH 0x00000026 +#define EVENT_DATA_SNR_HIGH 0x00000027 +#define EVENT_LINK_QUALITY 0x00000028 +#define EVENT_PORT_RELEASE 0x0000002b +#define EVENT_PRE_BEACON_LOST 0x00000031 +#define EVENT_ADDBA 0x00000033 +#define EVENT_DELBA 0x00000034 +#define EVENT_BA_STREAM_TIEMOUT 0x00000037 +#define EVENT_AMSDU_AGGR_CTRL 0x00000042 +#define EVENT_WEP_ICV_ERR 0x00000046 +#define EVENT_HS_ACT_REQ 0x00000047 +#define EVENT_BW_CHANGE 0x00000048 + +#define EVENT_HOSTWAKE_STAIE 0x0000004d + +#define EVENT_ID_MASK 0xffff +#define BSS_NUM_MASK 0xf + +#define EVENT_GET_BSS_NUM(event_cause) \ + (((event_cause) >> 16) & BSS_NUM_MASK) + +#define EVENT_GET_BSS_TYPE(event_cause) \ + (((event_cause) >> 24) & 0x00ff) + +struct mwifiex_event_wep_icv_err { + u16 reason_code; + u8 src_mac_addr[ETH_ALEN]; + u8 wep_key_index; + u8 wep_key_length; + u8 key[WLAN_KEY_LEN_WEP104]; +}; + +struct mwifiex_802_11_fixed_ies { + u8 time_stamp[8]; + __le16 beacon_interval; + __le16 capabilities; +}; + +struct mwifiex_ie_types_header { + __le16 type; + __le16 len; +} __packed; + +struct mwifiex_ie_types_data { + struct mwifiex_ie_types_header header; + u8 data[1]; +} __packed; + +#define MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET 0x01 +#define MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET 0x08 + +struct txpd { + u8 bss_type; + u8 bss_num; + __le16 tx_pkt_length; + __le16 tx_pkt_offset; + __le16 tx_pkt_type; + __le32 tx_control; + u8 priority; + u8 flags; + u8 pkt_delay_2ms; + u8 reserved1; +} __packed; + +struct rxpd { + u8 bss_type; + u8 bss_num; + u16 rx_pkt_length; + u16 rx_pkt_offset; + u16 rx_pkt_type; + u16 seq_num; + u8 priority; + u8 rx_rate; + s8 snr; + s8 nf; + /* Ht Info [Bit 0] RxRate format: LG=0, HT=1 + * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 + * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 */ + u8 ht_info; + u8 reserved; +} __packed; + +enum mwifiex_chan_scan_mode_bitmasks { + MWIFIEX_PASSIVE_SCAN = BIT(0), + MWIFIEX_DISABLE_CHAN_FILT = BIT(1), +}; + +#define SECOND_CHANNEL_BELOW 0x30 +#define SECOND_CHANNEL_ABOVE 0x10 +struct mwifiex_chan_scan_param_set { + u8 radio_type; + u8 chan_number; + u8 chan_scan_mode_bitmap; + __le16 min_scan_time; + __le16 max_scan_time; +} __packed; + +struct mwifiex_ie_types_chan_list_param_set { + struct mwifiex_ie_types_header header; + struct mwifiex_chan_scan_param_set chan_scan_param[1]; +} __packed; + +struct chan_band_param_set { + u8 radio_type; + u8 chan_number; +}; + +struct mwifiex_ie_types_chan_band_list_param_set { + struct mwifiex_ie_types_header header; + struct chan_band_param_set chan_band_param[1]; +} __packed; + +struct mwifiex_ie_types_rates_param_set { + struct mwifiex_ie_types_header header; + u8 rates[1]; +} __packed; + +struct mwifiex_ie_types_ssid_param_set { + struct mwifiex_ie_types_header header; + u8 ssid[1]; +} __packed; + +struct mwifiex_ie_types_num_probes { + struct mwifiex_ie_types_header header; + __le16 num_probes; +} __packed; + +struct mwifiex_ie_types_wildcard_ssid_params { + struct mwifiex_ie_types_header header; + u8 max_ssid_length; + u8 ssid[1]; +} __packed; + +#define TSF_DATA_SIZE 8 +struct mwifiex_ie_types_tsf_timestamp { + struct mwifiex_ie_types_header header; + u8 tsf_data[1]; +} __packed; + +struct mwifiex_cf_param_set { + u8 cfp_cnt; + u8 cfp_period; + u16 cfp_max_duration; + u16 cfp_duration_remaining; +} __packed; + +struct mwifiex_ibss_param_set { + u16 atim_window; +} __packed; + +struct mwifiex_ie_types_ss_param_set { + struct mwifiex_ie_types_header header; + union { + struct mwifiex_cf_param_set cf_param_set[1]; + struct mwifiex_ibss_param_set ibss_param_set[1]; + } cf_ibss; +} __packed; + +struct mwifiex_fh_param_set { + u16 dwell_time; + u8 hop_set; + u8 hop_pattern; + u8 hop_index; +} __packed; + +struct mwifiex_ds_param_set { + u8 current_chan; +} __packed; + +struct mwifiex_ie_types_phy_param_set { + struct mwifiex_ie_types_header header; + union { + struct mwifiex_fh_param_set fh_param_set[1]; + struct mwifiex_ds_param_set ds_param_set[1]; + } fh_ds; +} __packed; + +struct mwifiex_ie_types_auth_type { + struct mwifiex_ie_types_header header; + __le16 auth_type; +} __packed; + +struct mwifiex_ie_types_vendor_param_set { + struct mwifiex_ie_types_header header; + u8 ie[MWIFIEX_MAX_VSIE_LEN]; +}; + +struct mwifiex_ie_types_rsn_param_set { + struct mwifiex_ie_types_header header; + u8 rsn_ie[1]; +} __packed; + +#define KEYPARAMSET_FIXED_LEN 6 + +struct mwifiex_ie_type_key_param_set { + __le16 type; + __le16 length; + __le16 key_type_id; + __le16 key_info; + __le16 key_len; + u8 key[50]; +} __packed; + +struct host_cmd_ds_802_11_key_material { + __le16 action; + struct mwifiex_ie_type_key_param_set key_param_set; +} __packed; + +struct host_cmd_ds_gen { + u16 command; + u16 size; + u16 seq_num; + u16 result; +}; + +#define S_DS_GEN sizeof(struct host_cmd_ds_gen) + +enum sleep_resp_ctrl { + RESP_NOT_NEEDED = 0, + RESP_NEEDED, +}; + +struct mwifiex_ps_param { + __le16 null_pkt_interval; + __le16 multiple_dtims; + __le16 bcn_miss_timeout; + __le16 local_listen_interval; + __le16 adhoc_wake_period; + __le16 mode; + __le16 delay_to_ps; +}; + +struct mwifiex_auto_ds_param { + __le16 deep_sleep_timeout; +}; + +struct sleep_confirm_param { + __le16 resp_ctrl; +}; + +#define BITMAP_AUTO_DS 0x01 +#define BITMAP_STA_PS 0x10 +#define BITMAP_UAP_INACT_PS 0x100 +#define BITMAP_UAP_DTIM_PS 0x200 +struct auto_ps_param { + __le16 ps_bitmap; + /* auto deep sleep parameter, + * sta power save parameter + * uap inactivity parameter + * uap DTIM parameter */ +}; + +#define AUTO_PS_FIX_SIZE 4 + +#define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) +#define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) + +struct mwifiex_ie_types_auto_ds_param { + struct mwifiex_ie_types_header header; + struct mwifiex_auto_ds_param param; +} __packed; + +struct mwifiex_ie_types_ps_param { + struct mwifiex_ie_types_header header; + struct mwifiex_ps_param param; +} __packed; + +struct host_cmd_ds_802_11_ps_mode_enh { + __le16 action; + + union { + struct mwifiex_ps_param opt_ps; + struct mwifiex_auto_ds_param auto_ds; + struct sleep_confirm_param sleep_cfm; + __le16 ps_bitmap; + struct auto_ps_param auto_ps; + } params; +} __packed; + +struct host_cmd_ds_get_hw_spec { + __le16 hw_if_version; + __le16 version; + __le16 reserved; + __le16 num_of_mcast_adr; + u8 permanent_addr[ETH_ALEN]; + __le16 region_code; + __le16 number_of_antenna; + __le32 fw_release_number; + __le32 reserved_1; + __le32 reserved_2; + __le32 reserved_3; + __le32 fw_cap_info; + __le32 dot_11n_dev_cap; + u8 dev_mcs_support; + __le16 mp_end_port; /* SDIO only, reserved for other interfacces */ + __le16 reserved_4; +} __packed; + +struct host_cmd_ds_802_11_rssi_info { + __le16 action; + __le16 ndata; + __le16 nbcn; + __le16 reserved[9]; + long long reserved_1; +}; + +struct host_cmd_ds_802_11_rssi_info_rsp { + __le16 action; + __le16 ndata; + __le16 nbcn; + __le16 data_rssi_last; + __le16 data_nf_last; + __le16 data_rssi_avg; + __le16 data_nf_avg; + __le16 bcn_rssi_last; + __le16 bcn_nf_last; + __le16 bcn_rssi_avg; + __le16 bcn_nf_avg; + long long tsf_bcn; +}; + +struct host_cmd_ds_802_11_mac_address { + __le16 action; + u8 mac_addr[ETH_ALEN]; +}; + +struct host_cmd_ds_mac_control { + __le16 action; + __le16 reserved; +}; + +struct host_cmd_ds_mac_multicast_adr { + __le16 action; + __le16 num_of_adrs; + u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; +} __packed; + +struct host_cmd_ds_802_11_deauthenticate { + u8 mac_addr[ETH_ALEN]; + __le16 reason_code; +} __packed; + +struct host_cmd_ds_802_11_associate { + u8 peer_sta_addr[ETH_ALEN]; + __le16 cap_info_bitmap; + __le16 listen_interval; + __le16 beacon_period; + u8 dtim_period; +} __packed; + +struct ieee_types_assoc_rsp { + __le16 cap_info_bitmap; + __le16 status_code; + __le16 a_id; + u8 ie_buffer[1]; +} __packed; + +struct host_cmd_ds_802_11_associate_rsp { + struct ieee_types_assoc_rsp assoc_rsp; +} __packed; + +struct ieee_types_cf_param_set { + u8 element_id; + u8 len; + u8 cfp_cnt; + u8 cfp_period; + u16 cfp_max_duration; + u16 cfp_duration_remaining; +} __packed; + +struct ieee_types_ibss_param_set { + u8 element_id; + u8 len; + __le16 atim_window; +} __packed; + +union ieee_types_ss_param_set { + struct ieee_types_cf_param_set cf_param_set; + struct ieee_types_ibss_param_set ibss_param_set; +} __packed; + +struct ieee_types_fh_param_set { + u8 element_id; + u8 len; + __le16 dwell_time; + u8 hop_set; + u8 hop_pattern; + u8 hop_index; +} __packed; + +struct ieee_types_ds_param_set { + u8 element_id; + u8 len; + u8 current_chan; +} __packed; + +union ieee_types_phy_param_set { + struct ieee_types_fh_param_set fh_param_set; + struct ieee_types_ds_param_set ds_param_set; +} __packed; + +struct host_cmd_ds_802_11_ad_hoc_start { + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 bss_mode; + __le16 beacon_period; + u8 dtim_period; + union ieee_types_ss_param_set ss_param_set; + union ieee_types_phy_param_set phy_param_set; + u16 reserved1; + __le16 cap_info_bitmap; + u8 DataRate[HOSTCMD_SUPPORTED_RATES]; +} __packed; + +struct host_cmd_ds_802_11_ad_hoc_result { + u8 pad[3]; + u8 bssid[ETH_ALEN]; +} __packed; + +struct adhoc_bss_desc { + u8 bssid[ETH_ALEN]; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 bss_mode; + __le16 beacon_period; + u8 dtim_period; + u8 time_stamp[8]; + u8 local_time[8]; + union ieee_types_phy_param_set phy_param_set; + union ieee_types_ss_param_set ss_param_set; + __le16 cap_info_bitmap; + u8 data_rates[HOSTCMD_SUPPORTED_RATES]; + + /* + * DO NOT ADD ANY FIELDS TO THIS STRUCTURE. + * It is used in the Adhoc join command and will cause a + * binary layout mismatch with the firmware + */ +} __packed; + +struct host_cmd_ds_802_11_ad_hoc_join { + struct adhoc_bss_desc bss_descriptor; + u16 reserved1; + u16 reserved2; +} __packed; + +struct host_cmd_ds_802_11_get_log { + __le32 mcast_tx_frame; + __le32 failed; + __le32 retry; + __le32 multi_retry; + __le32 frame_dup; + __le32 rts_success; + __le32 rts_failure; + __le32 ack_failure; + __le32 rx_frag; + __le32 mcast_rx_frame; + __le32 fcs_error; + __le32 tx_frame; + __le32 reserved; + __le32 wep_icv_err_cnt[4]; +}; + +struct host_cmd_ds_tx_rate_query { + u8 tx_rate; + /* Ht Info [Bit 0] RxRate format: LG=0, HT=1 + * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 + * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 */ + u8 ht_info; +} __packed; + +enum Host_Sleep_Action { + HS_CONFIGURE = 0x0001, + HS_ACTIVATE = 0x0002, +}; + +struct mwifiex_hs_config_param { + __le32 conditions; + u8 gpio; + u8 gap; +} __packed; + +struct hs_activate_param { + u16 resp_ctrl; +} __packed; + +struct host_cmd_ds_802_11_hs_cfg_enh { + __le16 action; + + union { + struct mwifiex_hs_config_param hs_config; + struct hs_activate_param hs_activate; + } params; +} __packed; + +enum SNMP_MIB_INDEX { + OP_RATE_SET_I = 1, + DTIM_PERIOD_I = 3, + RTS_THRESH_I = 5, + SHORT_RETRY_LIM_I = 6, + LONG_RETRY_LIM_I = 7, + FRAG_THRESH_I = 8, + DOT11D_I = 9, +}; + +#define MAX_SNMP_BUF_SIZE 128 + +struct host_cmd_ds_802_11_snmp_mib { + __le16 query_type; + __le16 oid; + __le16 buf_size; + u8 value[1]; +} __packed; + +#define RADIO_ON 0x01 +#define RADIO_OFF 0x00 + +struct mwifiex_rate_scope { + __le16 type; + __le16 length; + __le16 hr_dsss_rate_bitmap; + __le16 ofdm_rate_bitmap; + __le16 ht_mcs_rate_bitmap[8]; +} __packed; + +struct mwifiex_rate_drop_pattern { + __le16 type; + __le16 length; + __le32 rate_drop_mode; +} __packed; + +struct host_cmd_ds_tx_rate_cfg { + __le16 action; + __le16 cfg_index; +} __packed; + +struct mwifiex_power_group { + u8 modulation_class; + u8 first_rate_code; + u8 last_rate_code; + s8 power_step; + s8 power_min; + s8 power_max; + u8 ht_bandwidth; + u8 reserved; +} __packed; + +struct mwifiex_types_power_group { + u16 type; + u16 length; +} __packed; + +struct host_cmd_ds_txpwr_cfg { + __le16 action; + __le16 cfg_index; + __le32 mode; +} __packed; + +#define MWIFIEX_USER_SCAN_CHAN_MAX 50 + +#define MWIFIEX_MAX_SSID_LIST_LENGTH 10 + +struct mwifiex_scan_cmd_config { + /* + * BSS Type to be sent in the firmware command + * + * Field can be used to restrict the types of networks returned in the + * scan. Valid settings are: + * + * - MWIFIEX_SCAN_MODE_BSS (infrastructure) + * - MWIFIEX_SCAN_MODE_IBSS (adhoc) + * - MWIFIEX_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure) + */ + u8 bss_mode; + + /* Specific BSSID used to filter scan results in the firmware */ + u8 specific_bssid[ETH_ALEN]; + + /* Length of TLVs sent in command starting at tlvBuffer */ + u32 tlv_buf_len; + + /* + * SSID TLV(s) and ChanList TLVs to be sent in the firmware command + * + * TLV_TYPE_CHANLIST, mwifiex_ie_types_chan_list_param_set + * WLAN_EID_SSID, mwifiex_ie_types_ssid_param_set + */ + u8 tlv_buf[1]; /* SSID TLV(s) and ChanList TLVs are stored + here */ +} __packed; + +struct mwifiex_user_scan_chan { + u8 chan_number; + u8 radio_type; + u8 scan_type; + u8 reserved; + u32 scan_time; +} __packed; + +struct mwifiex_user_scan_ssid { + u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; + u8 max_len; +} __packed; + +struct mwifiex_user_scan_cfg { + /* + * Flag set to keep the previous scan table intact + * + * If set, the scan results will accumulate, replacing any previous + * matched entries for a BSS with the new scan data + */ + u8 keep_previous_scan; + /* + * BSS mode to be sent in the firmware command + * + * Field can be used to restrict the types of networks returned in the + * scan. Valid settings are: + * + * - MWIFIEX_SCAN_MODE_BSS (infrastructure) + * - MWIFIEX_SCAN_MODE_IBSS (adhoc) + * - MWIFIEX_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure) + */ + u8 bss_mode; + /* Configure the number of probe requests for active chan scans */ + u8 num_probes; + u8 reserved; + /* BSSID filter sent in the firmware command to limit the results */ + u8 specific_bssid[ETH_ALEN]; + /* SSID filter list used in the to limit the scan results */ + struct mwifiex_user_scan_ssid ssid_list[MWIFIEX_MAX_SSID_LIST_LENGTH]; + /* Variable number (fixed maximum) of channels to scan up */ + struct mwifiex_user_scan_chan chan_list[MWIFIEX_USER_SCAN_CHAN_MAX]; +} __packed; + +struct ie_body { + u8 grp_key_oui[4]; + u8 ptk_cnt[2]; + u8 ptk_body[4]; +} __packed; + +struct host_cmd_ds_802_11_scan { + u8 bss_mode; + u8 bssid[ETH_ALEN]; + u8 tlv_buffer[1]; +} __packed; + +struct host_cmd_ds_802_11_scan_rsp { + __le16 bss_descript_size; + u8 number_of_sets; + u8 bss_desc_and_tlv_buffer[1]; +} __packed; + +struct host_cmd_ds_802_11_bg_scan_query { + u8 flush; +} __packed; + +struct host_cmd_ds_802_11_bg_scan_query_rsp { + u32 report_condition; + struct host_cmd_ds_802_11_scan_rsp scan_resp; +} __packed; + +struct mwifiex_ietypes_domain_param_set { + struct mwifiex_ie_types_header header; + u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; + struct ieee80211_country_ie_triplet triplet[1]; +} __packed; + +struct host_cmd_ds_802_11d_domain_info { + __le16 action; + struct mwifiex_ietypes_domain_param_set domain; +} __packed; + +struct host_cmd_ds_802_11d_domain_info_rsp { + __le16 action; + struct mwifiex_ietypes_domain_param_set domain; +} __packed; + +struct host_cmd_ds_11n_addba_req { + u8 add_req_result; + u8 peer_mac_addr[ETH_ALEN]; + u8 dialog_token; + __le16 block_ack_param_set; + __le16 block_ack_tmo; + __le16 ssn; +} __packed; + +struct host_cmd_ds_11n_addba_rsp { + u8 add_rsp_result; + u8 peer_mac_addr[ETH_ALEN]; + u8 dialog_token; + __le16 status_code; + __le16 block_ack_param_set; + __le16 block_ack_tmo; + __le16 ssn; +} __packed; + +struct host_cmd_ds_11n_delba { + u8 del_result; + u8 peer_mac_addr[ETH_ALEN]; + __le16 del_ba_param_set; + __le16 reason_code; + u8 reserved; +} __packed; + +struct host_cmd_ds_11n_batimeout { + u8 tid; + u8 peer_mac_addr[ETH_ALEN]; + u8 origninator; +} __packed; + +struct host_cmd_ds_11n_cfg { + __le16 action; + __le16 ht_tx_cap; + __le16 ht_tx_info; +} __packed; + +struct host_cmd_ds_txbuf_cfg { + __le16 action; + __le16 buff_size; + __le16 mp_end_port; /* SDIO only, reserved for other interfacces */ + __le16 reserved3; +} __packed; + +struct host_cmd_ds_amsdu_aggr_ctrl { + __le16 action; + __le16 enable; + __le16 curr_buf_size; +} __packed; + +struct mwifiex_ie_types_wmm_param_set { + struct mwifiex_ie_types_header header; + u8 wmm_ie[1]; +}; + +struct mwifiex_ie_types_wmm_queue_status { + struct mwifiex_ie_types_header header; + u8 queue_index; + u8 disabled; + u16 medium_time; + u8 flow_required; + u8 flow_created; + u32 reserved; +}; + +struct ieee_types_vendor_header { + u8 element_id; + u8 len; + u8 oui[3]; + u8 oui_type; + u8 oui_subtype; + u8 version; +} __packed; + +struct ieee_types_wmm_ac_parameters { + u8 aci_aifsn_bitmap; + u8 ecw_bitmap; + __le16 tx_op_limit; +} __packed; + +struct ieee_types_wmm_parameter { + /* + * WMM Parameter IE - Vendor Specific Header: + * element_id [221/0xdd] + * Len [24] + * Oui [00:50:f2] + * OuiType [2] + * OuiSubType [1] + * Version [1] + */ + struct ieee_types_vendor_header vend_hdr; + u8 qos_info_bitmap; + u8 reserved; + struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_MAX_QUEUES]; +} __packed; + +struct ieee_types_wmm_info { + + /* + * WMM Info IE - Vendor Specific Header: + * element_id [221/0xdd] + * Len [7] + * Oui [00:50:f2] + * OuiType [2] + * OuiSubType [0] + * Version [1] + */ + struct ieee_types_vendor_header vend_hdr; + + u8 qos_info_bitmap; +} __packed; + +struct host_cmd_ds_wmm_get_status { + u8 queue_status_tlv[sizeof(struct mwifiex_ie_types_wmm_queue_status) * + IEEE80211_MAX_QUEUES]; + u8 wmm_param_tlv[sizeof(struct ieee_types_wmm_parameter) + 2]; +} __packed; + +struct mwifiex_wmm_ac_status { + u8 disabled; + u8 flow_required; + u8 flow_created; +}; + +struct mwifiex_ie_types_htcap { + struct mwifiex_ie_types_header header; + struct ieee80211_ht_cap ht_cap; +} __packed; + +struct mwifiex_ie_types_htinfo { + struct mwifiex_ie_types_header header; + struct ieee80211_ht_info ht_info; +} __packed; + +struct mwifiex_ie_types_2040bssco { + struct mwifiex_ie_types_header header; + u8 bss_co_2040; +} __packed; + +struct mwifiex_ie_types_extcap { + struct mwifiex_ie_types_header header; + u8 ext_cap; +} __packed; + +struct host_cmd_ds_mac_reg_access { + __le16 action; + __le16 offset; + __le32 value; +} __packed; + +struct host_cmd_ds_bbp_reg_access { + __le16 action; + __le16 offset; + u8 value; + u8 reserved[3]; +} __packed; + +struct host_cmd_ds_rf_reg_access { + __le16 action; + __le16 offset; + u8 value; + u8 reserved[3]; +} __packed; + +struct host_cmd_ds_pmic_reg_access { + __le16 action; + __le16 offset; + u8 value; + u8 reserved[3]; +} __packed; + +struct host_cmd_ds_802_11_eeprom_access { + __le16 action; + + __le16 offset; + __le16 byte_count; + u8 value; +} __packed; + +struct host_cmd_ds_802_11_rf_channel { + __le16 action; + __le16 current_channel; + __le16 rf_type; + __le16 reserved; + u8 reserved_1[32]; +} __packed; + +struct host_cmd_ds_version_ext { + u8 version_str_sel; + char version_str[128]; +} __packed; + +struct host_cmd_ds_802_11_ibss_status { + __le16 action; + __le16 enable; + u8 bssid[ETH_ALEN]; + __le16 beacon_interval; + __le16 atim_window; + __le16 use_g_rate_protect; +} __packed; + +#define CONNECTION_TYPE_INFRA 0 +#define CONNECTION_TYPE_ADHOC 1 + +struct host_cmd_ds_set_bss_mode { + u8 con_type; +} __packed; + +struct host_cmd_ds_command { + __le16 command; + __le16 size; + __le16 seq_num; + __le16 result; + union { + struct host_cmd_ds_get_hw_spec hw_spec; + struct host_cmd_ds_mac_control mac_ctrl; + struct host_cmd_ds_802_11_mac_address mac_addr; + struct host_cmd_ds_mac_multicast_adr mc_addr; + struct host_cmd_ds_802_11_get_log get_log; + struct host_cmd_ds_802_11_rssi_info rssi_info; + struct host_cmd_ds_802_11_rssi_info_rsp rssi_info_rsp; + struct host_cmd_ds_802_11_snmp_mib smib; + struct host_cmd_ds_802_11_rf_channel rf_channel; + struct host_cmd_ds_tx_rate_query tx_rate; + struct host_cmd_ds_tx_rate_cfg tx_rate_cfg; + struct host_cmd_ds_txpwr_cfg txp_cfg; + struct host_cmd_ds_802_11_ps_mode_enh psmode_enh; + struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg; + struct host_cmd_ds_802_11_scan scan; + struct host_cmd_ds_802_11_scan_rsp scan_resp; + struct host_cmd_ds_802_11_bg_scan_query bg_scan_query; + struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp; + struct host_cmd_ds_802_11_associate associate; + struct host_cmd_ds_802_11_associate_rsp associate_rsp; + struct host_cmd_ds_802_11_deauthenticate deauth; + struct host_cmd_ds_802_11_ad_hoc_start adhoc_start; + struct host_cmd_ds_802_11_ad_hoc_result adhoc_result; + struct host_cmd_ds_802_11_ad_hoc_join adhoc_join; + struct host_cmd_ds_802_11d_domain_info domain_info; + struct host_cmd_ds_802_11d_domain_info_rsp domain_info_resp; + struct host_cmd_ds_11n_addba_req add_ba_req; + struct host_cmd_ds_11n_addba_rsp add_ba_rsp; + struct host_cmd_ds_11n_delba del_ba; + struct host_cmd_ds_txbuf_cfg tx_buf; + struct host_cmd_ds_amsdu_aggr_ctrl amsdu_aggr_ctrl; + struct host_cmd_ds_11n_cfg htcfg; + struct host_cmd_ds_wmm_get_status get_wmm_status; + struct host_cmd_ds_802_11_key_material key_material; + struct host_cmd_ds_version_ext verext; + struct host_cmd_ds_802_11_ibss_status ibss_coalescing; + struct host_cmd_ds_mac_reg_access mac_reg; + struct host_cmd_ds_bbp_reg_access bbp_reg; + struct host_cmd_ds_rf_reg_access rf_reg; + struct host_cmd_ds_pmic_reg_access pmic_reg; + struct host_cmd_ds_set_bss_mode bss_mode; + struct host_cmd_ds_802_11_eeprom_access eeprom; + } params; +} __packed; + +struct mwifiex_opt_sleep_confirm { + __le16 command; + __le16 size; + __le16 seq_num; + __le16 result; + __le16 action; + struct sleep_confirm_param sleep_cfm; +} __packed; + +struct mwifiex_opt_sleep_confirm_buffer { + u8 hdr[4]; + struct mwifiex_opt_sleep_confirm ps_cfm_sleep; +} __packed; +#endif /* !_MWIFIEX_FW_H_ */ diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c new file mode 100644 index 000000000000..07ebc97e19c0 --- /dev/null +++ b/drivers/net/wireless/mwifiex/init.c @@ -0,0 +1,665 @@ +/* + * Marvell Wireless LAN device driver: HW/FW Initialization + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" + +/* + * This function adds a BSS priority table to the table list. + * + * The function allocates a new BSS priority table node and adds it to + * the end of BSS priority table list, kept in driver memory. + */ +static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_bss_prio_node *bss_prio; + int status = 0; + unsigned long flags; + + bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL); + if (!bss_prio) { + dev_err(adapter->dev, "%s: failed to alloc bss_prio\n", + __func__); + return -1; + } + + bss_prio->priv = priv; + INIT_LIST_HEAD(&bss_prio->list); + if (!adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur) + adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = + bss_prio; + + spin_lock_irqsave(&adapter->bss_prio_tbl[priv->bss_priority] + .bss_prio_lock, flags); + list_add_tail(&bss_prio->list, + &adapter->bss_prio_tbl[priv->bss_priority] + .bss_prio_head); + spin_unlock_irqrestore(&adapter->bss_prio_tbl[priv->bss_priority] + .bss_prio_lock, flags); + + return status; +} + +/* + * This function initializes the private structure and sets default + * values to the members. + * + * Additionally, it also initializes all the locks and sets up all the + * lists. + */ +static int mwifiex_init_priv(struct mwifiex_private *priv) +{ + u32 i; + int ret = 0; + + priv->media_connected = false; + memset(priv->curr_addr, 0xff, ETH_ALEN); + + priv->pkt_tx_ctrl = 0; + priv->bss_mode = MWIFIEX_BSS_MODE_INFRA; + priv->data_rate = 0; /* Initially indicate the rate as auto */ + priv->is_data_rate_auto = true; + priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; + priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR; + + priv->sec_info.wep_status = MWIFIEX_802_11_WEP_DISABLED; + priv->sec_info.authentication_mode = MWIFIEX_AUTH_MODE_OPEN; + priv->sec_info.encryption_mode = MWIFIEX_ENCRYPTION_MODE_NONE; + for (i = 0; i < ARRAY_SIZE(priv->wep_key); i++) + memset(&priv->wep_key[i], 0, sizeof(struct mwifiex_wep_key)); + priv->wep_key_curr_index = 0; + priv->curr_pkt_filter = HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON | + HostCmd_ACT_MAC_ETHERNETII_ENABLE; + + priv->beacon_period = 100; /* beacon interval */ ; + priv->attempted_bss_desc = NULL; + memset(&priv->curr_bss_params, 0, sizeof(priv->curr_bss_params)); + priv->listen_interval = MWIFIEX_DEFAULT_LISTEN_INTERVAL; + + memset(&priv->prev_ssid, 0, sizeof(priv->prev_ssid)); + memset(&priv->prev_bssid, 0, sizeof(priv->prev_bssid)); + memset(&priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf)); + priv->assoc_rsp_size = 0; + priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; + priv->atim_window = 0; + priv->adhoc_state = ADHOC_IDLE; + priv->tx_power_level = 0; + priv->max_tx_power_level = 0; + priv->min_tx_power_level = 0; + priv->tx_rate = 0; + priv->rxpd_htinfo = 0; + priv->rxpd_rate = 0; + priv->rate_bitmap = 0; + priv->data_rssi_last = 0; + priv->data_rssi_avg = 0; + priv->data_nf_avg = 0; + priv->data_nf_last = 0; + priv->bcn_rssi_last = 0; + priv->bcn_rssi_avg = 0; + priv->bcn_nf_avg = 0; + priv->bcn_nf_last = 0; + memset(&priv->wpa_ie, 0, sizeof(priv->wpa_ie)); + memset(&priv->aes_key, 0, sizeof(priv->aes_key)); + priv->wpa_ie_len = 0; + priv->wpa_is_gtk_set = false; + + memset(&priv->assoc_tlv_buf, 0, sizeof(priv->assoc_tlv_buf)); + priv->assoc_tlv_buf_len = 0; + memset(&priv->wps, 0, sizeof(priv->wps)); + memset(&priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf)); + priv->gen_ie_buf_len = 0; + memset(priv->vs_ie, 0, sizeof(priv->vs_ie)); + + priv->wmm_required = true; + priv->wmm_enabled = false; + priv->wmm_qosinfo = 0; + priv->curr_bcn_buf = NULL; + priv->curr_bcn_size = 0; + + priv->scan_block = false; + + ret = mwifiex_add_bss_prio_tbl(priv); + + return ret; +} + +/* + * This function allocates buffers for members of the adapter + * structure. + * + * The memory allocated includes scan table, command buffers, and + * sleep confirm command buffer. In addition, the queues are + * also initialized. + */ +static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) +{ + int ret = 0; + u32 buf_size; + struct mwifiex_bssdescriptor *temp_scan_table; + + /* Allocate buffer to store the BSSID list */ + buf_size = sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP; + temp_scan_table = kzalloc(buf_size, GFP_KERNEL); + if (!temp_scan_table) { + dev_err(adapter->dev, "%s: failed to alloc temp_scan_table\n", + __func__); + return -1; + } + + adapter->scan_table = temp_scan_table; + + /* Allocate command buffer */ + ret = mwifiex_alloc_cmd_buffer(adapter); + if (ret) { + dev_err(adapter->dev, "%s: failed to alloc cmd buffer\n", + __func__); + return -1; + } + + adapter->sleep_cfm = + dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm_buffer) + + INTF_HEADER_LEN); + + if (!adapter->sleep_cfm) { + dev_err(adapter->dev, "%s: failed to alloc sleep cfm" + " cmd buffer\n", __func__); + return -1; + } + skb_reserve(adapter->sleep_cfm, INTF_HEADER_LEN); + + return 0; +} + +/* + * This function initializes the adapter structure and sets default + * values to the members of adapter. + * + * This also initializes the WMM related parameters in the driver private + * structures. + */ +static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) +{ + struct mwifiex_opt_sleep_confirm_buffer *sleep_cfm_buf = NULL; + + skb_put(adapter->sleep_cfm, sizeof(sleep_cfm_buf->ps_cfm_sleep)); + sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm_buffer *) + (adapter->sleep_cfm->data); + + adapter->cmd_sent = false; + adapter->data_sent = true; + adapter->cmd_resp_received = false; + adapter->event_received = false; + adapter->data_received = false; + + adapter->surprise_removed = false; + + adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; + + adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; + adapter->ps_state = PS_STATE_AWAKE; + adapter->need_to_wakeup = false; + + adapter->scan_mode = HostCmd_BSS_MODE_ANY; + adapter->specific_scan_time = MWIFIEX_SPECIFIC_SCAN_CHAN_TIME; + adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME; + adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME; + + adapter->num_in_scan_table = 0; + memset(adapter->scan_table, 0, + (sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP)); + adapter->scan_probes = 1; + + memset(adapter->bcn_buf, 0, sizeof(adapter->bcn_buf)); + adapter->bcn_buf_end = adapter->bcn_buf; + + adapter->radio_on = RADIO_ON; + adapter->multiple_dtim = 1; + + adapter->local_listen_interval = 0; /* default value in firmware + will be used */ + + adapter->is_deep_sleep = false; + + adapter->delay_null_pkt = false; + adapter->delay_to_ps = 1000; + adapter->enhanced_ps_mode = PS_MODE_AUTO; + + adapter->gen_null_pkt = false; /* Disable NULL Pkg generation by + default */ + adapter->pps_uapsd_mode = false; /* Disable pps/uapsd mode by + default */ + adapter->pm_wakeup_card_req = false; + + adapter->pm_wakeup_fw_try = false; + + adapter->max_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; + adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; + adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; + + adapter->is_hs_configured = false; + adapter->hs_cfg.conditions = cpu_to_le32(HOST_SLEEP_CFG_COND_DEF); + adapter->hs_cfg.gpio = HOST_SLEEP_CFG_GPIO_DEF; + adapter->hs_cfg.gap = HOST_SLEEP_CFG_GAP_DEF; + adapter->hs_activated = false; + + memset(adapter->event_body, 0, sizeof(adapter->event_body)); + adapter->hw_dot_11n_dev_cap = 0; + adapter->hw_dev_mcs_support = 0; + adapter->usr_dot_11n_dev_cap = 0; + adapter->usr_dev_mcs_support = 0; + adapter->chan_offset = 0; + adapter->adhoc_11n_enabled = false; + + mwifiex_wmm_init(adapter); + + if (adapter->sleep_cfm) { + memset(&sleep_cfm_buf->ps_cfm_sleep, 0, + adapter->sleep_cfm->len); + sleep_cfm_buf->ps_cfm_sleep.command = + cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); + sleep_cfm_buf->ps_cfm_sleep.size = + cpu_to_le16(adapter->sleep_cfm->len); + sleep_cfm_buf->ps_cfm_sleep.result = 0; + sleep_cfm_buf->ps_cfm_sleep.action = cpu_to_le16(SLEEP_CONFIRM); + sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl = + cpu_to_le16(RESP_NEEDED); + } + memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params)); + memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); + adapter->tx_lock_flag = false; + adapter->null_pkt_interval = 0; + adapter->fw_bands = 0; + adapter->config_bands = 0; + adapter->adhoc_start_band = 0; + adapter->scan_channels = NULL; + adapter->fw_release_number = 0; + adapter->fw_cap_info = 0; + memset(&adapter->upld_buf, 0, sizeof(adapter->upld_buf)); + adapter->event_cause = 0; + adapter->region_code = 0; + adapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT; + adapter->adhoc_awake_period = 0; + memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); + adapter->arp_filter_size = 0; + + return; +} + +/* + * This function frees the adapter structure. + * + * The freeing operation is done recursively, by canceling all + * pending commands, freeing the member buffers previously + * allocated (command buffers, scan table buffer, sleep confirm + * command buffer), stopping the timers and calling the cleanup + * routines for every interface, before the actual adapter + * structure is freed. + */ +static void +mwifiex_free_adapter(struct mwifiex_adapter *adapter) +{ + if (!adapter) { + pr_err("%s: adapter is NULL\n", __func__); + return; + } + + mwifiex_cancel_all_pending_cmd(adapter); + + /* Free lock variables */ + mwifiex_free_lock_list(adapter); + + /* Free command buffer */ + dev_dbg(adapter->dev, "info: free cmd buffer\n"); + mwifiex_free_cmd_buffer(adapter); + + del_timer(&adapter->cmd_timer); + + dev_dbg(adapter->dev, "info: free scan table\n"); + kfree(adapter->scan_table); + adapter->scan_table = NULL; + + adapter->if_ops.cleanup_if(adapter); + + dev_kfree_skb_any(adapter->sleep_cfm); + + return; +} + +/* + * This function intializes the lock variables and + * the list heads. + */ +int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) +{ + struct mwifiex_private *priv = NULL; + s32 i = 0; + u32 j = 0; + + spin_lock_init(&adapter->mwifiex_lock); + spin_lock_init(&adapter->int_lock); + spin_lock_init(&adapter->main_proc_lock); + spin_lock_init(&adapter->mwifiex_cmd_lock); + for (i = 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + priv = adapter->priv[i]; + spin_lock_init(&priv->rx_pkt_lock); + spin_lock_init(&priv->wmm.ra_list_spinlock); + spin_lock_init(&priv->curr_bcn_buf_lock); + } + } + + /* Initialize cmd_free_q */ + INIT_LIST_HEAD(&adapter->cmd_free_q); + /* Initialize cmd_pending_q */ + INIT_LIST_HEAD(&adapter->cmd_pending_q); + /* Initialize scan_pending_q */ + INIT_LIST_HEAD(&adapter->scan_pending_q); + + spin_lock_init(&adapter->cmd_free_q_lock); + spin_lock_init(&adapter->cmd_pending_q_lock); + spin_lock_init(&adapter->scan_pending_q_lock); + + for (i = 0; i < adapter->priv_num; ++i) { + INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); + adapter->bss_prio_tbl[i].bss_prio_cur = NULL; + spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock); + } + + for (i = 0; i < adapter->priv_num; i++) { + if (!adapter->priv[i]) + continue; + priv = adapter->priv[i]; + for (j = 0; j < MAX_NUM_TID; ++j) { + INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list); + spin_lock_init(&priv->wmm.tid_tbl_ptr[j].tid_tbl_lock); + } + INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); + INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); + + spin_lock_init(&priv->tx_ba_stream_tbl_lock); + spin_lock_init(&priv->rx_reorder_tbl_lock); + } + + return 0; +} + +/* + * This function releases the lock variables and frees the locks and + * associated locks. + */ +void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) +{ + struct mwifiex_private *priv = NULL; + s32 i = 0; + s32 j = 0; + + /* Free lists */ + list_del(&adapter->cmd_free_q); + list_del(&adapter->cmd_pending_q); + list_del(&adapter->scan_pending_q); + + for (i = 0; i < adapter->priv_num; i++) + list_del(&adapter->bss_prio_tbl[i].bss_prio_head); + + for (i = 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + priv = adapter->priv[i]; + for (j = 0; j < MAX_NUM_TID; ++j) + list_del(&priv->wmm.tid_tbl_ptr[j].ra_list); + list_del(&priv->tx_ba_stream_tbl_ptr); + list_del(&priv->rx_reorder_tbl_ptr); + } + } + + return; +} + +/* + * This function initializes the firmware. + * + * The following operations are performed sequentially - + * - Allocate adapter structure + * - Initialize the adapter structure + * - Initialize the private structure + * - Add BSS priority tables to the adapter structure + * - For each interface, send the init commands to firmware + * - Send the first command in command pending queue, if available + */ +int mwifiex_init_fw(struct mwifiex_adapter *adapter) +{ + int ret = 0; + struct mwifiex_private *priv = NULL; + u8 i = 0; + u8 first_sta = true; + int is_cmd_pend_q_empty; + unsigned long flags; + + adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; + + /* Allocate memory for member of adapter structure */ + ret = mwifiex_allocate_adapter(adapter); + if (ret) + return -1; + + /* Initialize adapter structure */ + mwifiex_init_adapter(adapter); + + for (i = 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + priv = adapter->priv[i]; + + /* Initialize private structure */ + ret = mwifiex_init_priv(priv); + if (ret) + return -1; + } + } + for (i = 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta); + if (ret == -1) + return -1; + + first_sta = false; + } + } + + spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); + is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q); + spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); + if (!is_cmd_pend_q_empty) { + /* Send the first command in queue and return */ + if (mwifiex_main_process(adapter) != -1) + ret = -EINPROGRESS; + } else { + adapter->hw_status = MWIFIEX_HW_STATUS_READY; + } + + return ret; +} + +/* + * This function deletes the BSS priority tables. + * + * The function traverses through all the allocated BSS priority nodes + * in every BSS priority table and frees them. + */ +static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv) +{ + int i; + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_bss_prio_node *bssprio_node = NULL, *tmp_node = NULL, + **cur = NULL; + struct list_head *head; + spinlock_t *lock; + unsigned long flags; + + for (i = 0; i < adapter->priv_num; ++i) { + head = &adapter->bss_prio_tbl[i].bss_prio_head; + cur = &adapter->bss_prio_tbl[i].bss_prio_cur; + lock = &adapter->bss_prio_tbl[i].bss_prio_lock; + dev_dbg(adapter->dev, "info: delete BSS priority table," + " index = %d, i = %d, head = %p, cur = %p\n", + priv->bss_index, i, head, *cur); + if (*cur) { + spin_lock_irqsave(lock, flags); + if (list_empty(head)) { + spin_unlock_irqrestore(lock, flags); + continue; + } + bssprio_node = list_first_entry(head, + struct mwifiex_bss_prio_node, list); + spin_unlock_irqrestore(lock, flags); + + list_for_each_entry_safe(bssprio_node, tmp_node, head, + list) { + if (bssprio_node->priv == priv) { + dev_dbg(adapter->dev, "info: Delete " + "node %p, next = %p\n", + bssprio_node, tmp_node); + spin_lock_irqsave(lock, flags); + list_del(&bssprio_node->list); + spin_unlock_irqrestore(lock, flags); + kfree(bssprio_node); + } + } + *cur = (struct mwifiex_bss_prio_node *)head; + } + } +} + +/* + * This function is used to shutdown the driver. + * + * The following operations are performed sequentially - + * - Check if already shut down + * - Make sure the main process has stopped + * - Clean up the Tx and Rx queues + * - Delete BSS priority tables + * - Free the adapter + * - Notify completion + */ +int +mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) +{ + int ret = -EINPROGRESS; + struct mwifiex_private *priv = NULL; + s32 i = 0; + unsigned long flags; + + /* mwifiex already shutdown */ + if (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY) + return 0; + + adapter->hw_status = MWIFIEX_HW_STATUS_CLOSING; + /* wait for mwifiex_process to complete */ + if (adapter->mwifiex_processing) { + dev_warn(adapter->dev, "main process is still running\n"); + return ret; + } + + /* shut down mwifiex */ + dev_dbg(adapter->dev, "info: shutdown mwifiex...\n"); + + /* Clean up Tx/Rx queues and delete BSS priority table */ + for (i = 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + priv = adapter->priv[i]; + + mwifiex_clean_txrx(priv); + mwifiex_delete_bss_prio_tbl(priv); + } + } + + spin_lock_irqsave(&adapter->mwifiex_lock, flags); + + /* Free adapter structure */ + mwifiex_free_adapter(adapter); + + spin_unlock_irqrestore(&adapter->mwifiex_lock, flags); + + /* Notify completion */ + ret = mwifiex_shutdown_fw_complete(adapter); + + return ret; +} + +/* + * This function downloads the firmware to the card. + * + * The actual download is preceded by two sanity checks - + * - Check if firmware is already running + * - Check if the interface is the winner to download the firmware + * + * ...and followed by another - + * - Check if the firmware is downloaded successfully + * + * After download is successfully completed, the host interrupts are enabled. + */ +int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, + struct mwifiex_fw_image *pmfw) +{ + int ret = 0; + u32 poll_num = 1; + int winner; + + /* Check if firmware is already running */ + ret = adapter->if_ops.check_fw_status(adapter, poll_num, &winner); + if (!ret) { + dev_notice(adapter->dev, + "WLAN FW already running! Skip FW download\n"); + goto done; + } + poll_num = MAX_FIRMWARE_POLL_TRIES; + + /* Check if we are the winner for downloading FW */ + if (!winner) { + dev_notice(adapter->dev, + "Other interface already running!" + " Skip FW download\n"); + poll_num = MAX_MULTI_INTERFACE_POLL_TRIES; + goto poll_fw; + } + if (pmfw) { + /* Download firmware with helper */ + ret = adapter->if_ops.prog_fw(adapter, pmfw); + if (ret) { + dev_err(adapter->dev, "prog_fw failed ret=%#x\n", ret); + return ret; + } + } + +poll_fw: + /* Check if the firmware is downloaded successfully or not */ + ret = adapter->if_ops.check_fw_status(adapter, poll_num, NULL); + if (ret) { + dev_err(adapter->dev, "FW failed to be active in time\n"); + return -1; + } +done: + /* re-enable host interrupt for mwifiex after fw dnld is successful */ + adapter->if_ops.enable_int(adapter); + return ret; +} diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h new file mode 100644 index 000000000000..d6babfb1495c --- /dev/null +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -0,0 +1,433 @@ +/* + * Marvell Wireless LAN device driver: ioctl data structures & APIs + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#ifndef _MWIFIEX_IOCTL_H_ +#define _MWIFIEX_IOCTL_H_ + +#include + +enum { + MWIFIEX_SCAN_MODE_UNCHANGED = 0, + MWIFIEX_SCAN_MODE_BSS, + MWIFIEX_SCAN_MODE_IBSS, + MWIFIEX_SCAN_MODE_ANY +}; + +enum { + MWIFIEX_SCAN_TYPE_UNCHANGED = 0, + MWIFIEX_SCAN_TYPE_ACTIVE, + MWIFIEX_SCAN_TYPE_PASSIVE +}; + +struct mwifiex_get_scan_table_fixed { + u8 bssid[ETH_ALEN]; + u8 channel; + u8 rssi; + long long network_tsf; +}; + +struct mwifiex_scan_time_params { + u32 specific_scan_time; + u32 active_scan_time; + u32 passive_scan_time; +}; + +struct mwifiex_user_scan { + u32 scan_cfg_len; + u8 scan_cfg_buf[1]; +}; + +struct mwifiex_scan_req { + u32 scan_mode; + u32 scan_type; + struct mwifiex_802_11_ssid scan_ssid; + struct mwifiex_scan_time_params scan_time; + struct mwifiex_user_scan user_scan; +}; + +struct mwifiex_scan_resp { + u32 num_in_scan_table; + u8 *scan_table; +}; + +enum { + MWIFIEX_BSS_MODE_INFRA = 1, + MWIFIEX_BSS_MODE_IBSS, + MWIFIEX_BSS_MODE_AUTO +}; + +#define MWIFIEX_PROMISC_MODE 1 +#define MWIFIEX_MULTICAST_MODE 2 +#define MWIFIEX_ALL_MULTI_MODE 4 +#define MWIFIEX_MAX_MULTICAST_LIST_SIZE 32 + +struct mwifiex_multicast_list { + u32 mode; + u32 num_multicast_addr; + u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; +}; + +#define MWIFIEX_MAX_CHANNEL_NUM 128 + +struct mwifiex_chan_freq { + u32 channel; + u32 freq; +}; + +struct mwifiex_chan_list { + u32 num_of_chan; + struct mwifiex_chan_freq cf[MWIFIEX_MAX_CHANNEL_NUM]; +}; + +struct mwifiex_ssid_bssid { + struct mwifiex_802_11_ssid ssid; + u8 bssid[ETH_ALEN]; +}; + +enum { + BAND_B = 1, + BAND_G = 2, + BAND_A = 4, + BAND_GN = 8, + BAND_AN = 16, +}; + +#define NO_SEC_CHANNEL 0 +#define SEC_CHANNEL_ABOVE 1 +#define SEC_CHANNEL_BELOW 3 + +struct mwifiex_ds_band_cfg { + u32 config_bands; + u32 adhoc_start_band; + u32 adhoc_channel; + u32 sec_chan_offset; +}; + +enum { + ADHOC_IDLE, + ADHOC_STARTED, + ADHOC_JOINED, + ADHOC_COALESCED +}; + +struct mwifiex_ds_get_stats { + u32 mcast_tx_frame; + u32 failed; + u32 retry; + u32 multi_retry; + u32 frame_dup; + u32 rts_success; + u32 rts_failure; + u32 ack_failure; + u32 rx_frag; + u32 mcast_rx_frame; + u32 fcs_error; + u32 tx_frame; + u32 wep_icv_error[4]; +}; + +#define BCN_RSSI_LAST_MASK 0x00000001 +#define BCN_RSSI_AVG_MASK 0x00000002 +#define DATA_RSSI_LAST_MASK 0x00000004 +#define DATA_RSSI_AVG_MASK 0x00000008 +#define BCN_SNR_LAST_MASK 0x00000010 +#define BCN_SNR_AVG_MASK 0x00000020 +#define DATA_SNR_LAST_MASK 0x00000040 +#define DATA_SNR_AVG_MASK 0x00000080 +#define BCN_NF_LAST_MASK 0x00000100 +#define BCN_NF_AVG_MASK 0x00000200 +#define DATA_NF_LAST_MASK 0x00000400 +#define DATA_NF_AVG_MASK 0x00000800 +#define ALL_RSSI_INFO_MASK 0x00000fff + +struct mwifiex_ds_get_signal { + /* + * Bit0: Last Beacon RSSI, Bit1: Average Beacon RSSI, + * Bit2: Last Data RSSI, Bit3: Average Data RSSI, + * Bit4: Last Beacon SNR, Bit5: Average Beacon SNR, + * Bit6: Last Data SNR, Bit7: Average Data SNR, + * Bit8: Last Beacon NF, Bit9: Average Beacon NF, + * Bit10: Last Data NF, Bit11: Average Data NF + */ + u16 selector; + s16 bcn_rssi_last; + s16 bcn_rssi_avg; + s16 data_rssi_last; + s16 data_rssi_avg; + s16 bcn_snr_last; + s16 bcn_snr_avg; + s16 data_snr_last; + s16 data_snr_avg; + s16 bcn_nf_last; + s16 bcn_nf_avg; + s16 data_nf_last; + s16 data_nf_avg; +}; + +struct mwifiex_fw_info { + u32 fw_ver; + u8 mac_addr[ETH_ALEN]; +}; + +#define MWIFIEX_MAX_VER_STR_LEN 128 + +struct mwifiex_ver_ext { + u32 version_str_sel; + char version_str[MWIFIEX_MAX_VER_STR_LEN]; +}; + +struct mwifiex_bss_info { + u32 bss_mode; + struct mwifiex_802_11_ssid ssid; + u32 scan_table_idx; + u32 bss_chan; + u32 region_code; + u32 media_connected; + u32 radio_on; + u32 max_power_level; + u32 min_power_level; + u32 adhoc_state; + signed int bcn_nf_last; + u32 wep_status; + u32 is_hs_configured; + u32 is_deep_sleep; + u8 bssid[ETH_ALEN]; +}; + +#define MAX_NUM_TID 8 + +#define MAX_RX_WINSIZE 64 + +struct mwifiex_ds_rx_reorder_tbl { + u16 tid; + u8 ta[ETH_ALEN]; + u32 start_win; + u32 win_size; + u32 buffer[MAX_RX_WINSIZE]; +}; + +struct mwifiex_ds_tx_ba_stream_tbl { + u16 tid; + u8 ra[ETH_ALEN]; +}; + +#define DBG_CMD_NUM 5 + +struct mwifiex_debug_info { + u32 int_counter; + u32 packets_out[MAX_NUM_TID]; + u32 max_tx_buf_size; + u32 tx_buf_size; + u32 curr_tx_buf_size; + u32 tx_tbl_num; + struct mwifiex_ds_tx_ba_stream_tbl + tx_tbl[MWIFIEX_MAX_TX_BASTREAM_SUPPORTED]; + u32 rx_tbl_num; + struct mwifiex_ds_rx_reorder_tbl rx_tbl + [MWIFIEX_MAX_RX_BASTREAM_SUPPORTED]; + u16 ps_mode; + u32 ps_state; + u8 is_deep_sleep; + u8 pm_wakeup_card_req; + u32 pm_wakeup_fw_try; + u8 is_hs_configured; + u8 hs_activated; + u32 num_cmd_host_to_card_failure; + u32 num_cmd_sleep_cfm_host_to_card_failure; + u32 num_tx_host_to_card_failure; + u32 num_event_deauth; + u32 num_event_disassoc; + u32 num_event_link_lost; + u32 num_cmd_deauth; + u32 num_cmd_assoc_success; + u32 num_cmd_assoc_failure; + u32 num_tx_timeout; + u32 num_cmd_timeout; + u16 timeout_cmd_id; + u16 timeout_cmd_act; + u16 last_cmd_id[DBG_CMD_NUM]; + u16 last_cmd_act[DBG_CMD_NUM]; + u16 last_cmd_index; + u16 last_cmd_resp_id[DBG_CMD_NUM]; + u16 last_cmd_resp_index; + u16 last_event[DBG_CMD_NUM]; + u16 last_event_index; + u8 data_sent; + u8 cmd_sent; + u8 cmd_resp_received; + u8 event_received; +}; + +enum { + MWIFIEX_AUTH_MODE_OPEN = 0x00, + MWIFIEX_AUTH_MODE_SHARED = 0x01, + MWIFIEX_AUTH_MODE_NETWORKEAP = 0x80, + MWIFIEX_AUTH_MODE_AUTO = 0xFF, +}; + +enum { + MWIFIEX_ENCRYPTION_MODE_NONE = 0, + MWIFIEX_ENCRYPTION_MODE_WEP40 = 1, + MWIFIEX_ENCRYPTION_MODE_TKIP = 2, + MWIFIEX_ENCRYPTION_MODE_CCMP = 3, + MWIFIEX_ENCRYPTION_MODE_WEP104 = 4, +}; + +#define MWIFIEX_KEY_INDEX_UNICAST 0x40000000 +#define MWIFIEX_MAX_KEY_LENGTH 32 +#define WAPI_RXPN_LEN 16 + +struct mwifiex_ds_encrypt_key { + u32 key_disable; + u32 key_index; + u32 key_len; + u8 key_material[MWIFIEX_MAX_KEY_LENGTH]; + u8 mac_addr[ETH_ALEN]; + u32 is_wapi_key; + u8 wapi_rxpn[WAPI_RXPN_LEN]; +}; + +struct mwifiex_rate_cfg { + u32 action; + u32 is_rate_auto; + u32 rate; +}; + +struct mwifiex_data_rate { + u32 tx_data_rate; + u32 rx_data_rate; +}; + +struct mwifiex_power_cfg { + u32 is_power_auto; + u32 power_level; +}; + +struct mwifiex_ds_hs_cfg { + u32 is_invoke_hostcmd; + /* Bit0: non-unicast data + * Bit1: unicast data + * Bit2: mac events + * Bit3: magic packet + */ + u32 conditions; + u32 gpio; + u32 gap; +}; + +#define DEEP_SLEEP_ON 1 +#define DEEP_SLEEP_OFF 0 + +#define DEEP_SLEEP_IDLE_TIME 100 + +struct mwifiex_ds_auto_ds { + u16 auto_ds; + u16 idle_time; +}; + +#define PS_MODE_UNCHANGED 0 +#define PS_MODE_AUTO 1 +#define PS_MODE_POLL 2 +#define PS_MODE_NULL 3 + + +struct mwifiex_ds_pm_cfg { + union { + u32 ps_mode; + struct mwifiex_ds_hs_cfg hs_cfg; + struct mwifiex_ds_auto_ds auto_deep_sleep; + u32 sleep_period; + } param; +}; + +struct mwifiex_ioctl_wmm_queue_status_ac { + u8 wmm_acm; + u8 flow_required; + u8 flow_created; + u8 disabled; +}; + +struct mwifiex_ds_wmm_queue_status { + struct mwifiex_ioctl_wmm_queue_status_ac + ac_status[IEEE80211_MAX_QUEUES]; +}; + +struct mwifiex_ds_11n_tx_cfg { + u16 tx_htcap; + u16 tx_htinfo; +}; + +struct mwifiex_ds_11n_amsdu_aggr_ctrl { + u16 enable; + u16 curr_buf_size; +}; + +#define MWIFIEX_NUM_OF_CMD_BUFFER 20 +#define MWIFIEX_SIZE_OF_CMD_BUFFER 2048 + +enum { + MWIFIEX_IE_TYPE_GEN_IE = 0, + MWIFIEX_IE_TYPE_ARP_FILTER, +}; + +enum { + MWIFIEX_REG_MAC = 1, + MWIFIEX_REG_BBP, + MWIFIEX_REG_RF, + MWIFIEX_REG_PMIC, + MWIFIEX_REG_CAU, +}; + +struct mwifiex_ds_reg_rw { + __le32 type; + __le32 offset; + __le32 value; +}; + +#define MAX_EEPROM_DATA 256 + +struct mwifiex_ds_read_eeprom { + __le16 offset; + __le16 byte_count; + u8 value[MAX_EEPROM_DATA]; +}; + +struct mwifiex_ds_misc_gen_ie { + u32 type; + u32 len; + u8 ie_data[IW_CUSTOM_MAX]; +}; + +struct mwifiex_ds_misc_cmd { + u32 len; + u8 cmd[MWIFIEX_SIZE_OF_CMD_BUFFER]; +}; + +#define MWIFIEX_MAX_VSIE_LEN (256) +#define MWIFIEX_MAX_VSIE_NUM (8) +#define MWIFIEX_VSIE_MASK_SCAN 0x01 +#define MWIFIEX_VSIE_MASK_ASSOC 0x02 +#define MWIFIEX_VSIE_MASK_ADHOC 0x04 + +enum { + MWIFIEX_FUNC_INIT = 1, + MWIFIEX_FUNC_SHUTDOWN, +}; + +#endif /* !_MWIFIEX_IOCTL_H_ */ diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c new file mode 100644 index 000000000000..d06f4c2d1d30 --- /dev/null +++ b/drivers/net/wireless/mwifiex/join.c @@ -0,0 +1,1464 @@ +/* + * Marvell Wireless LAN device driver: association and ad-hoc start/join + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" + +#define CAPINFO_MASK (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9))) + +/* + * Append a generic IE as a pass through TLV to a TLV buffer. + * + * This function is called from the network join command preparation routine. + * + * If the IE buffer has been setup by the application, this routine appends + * the buffer as a pass through TLV type to the request. + */ +static int +mwifiex_cmd_append_generic_ie(struct mwifiex_private *priv, u8 **buffer) +{ + int ret_len = 0; + struct mwifiex_ie_types_header ie_header; + + /* Null Checks */ + if (!buffer) + return 0; + if (!(*buffer)) + return 0; + + /* + * If there is a generic ie buffer setup, append it to the return + * parameter buffer pointer. + */ + if (priv->gen_ie_buf_len) { + dev_dbg(priv->adapter->dev, "info: %s: append generic %d to %p\n", + __func__, priv->gen_ie_buf_len, *buffer); + + /* Wrap the generic IE buffer with a pass through TLV type */ + ie_header.type = cpu_to_le16(TLV_TYPE_PASSTHROUGH); + ie_header.len = cpu_to_le16(priv->gen_ie_buf_len); + memcpy(*buffer, &ie_header, sizeof(ie_header)); + + /* Increment the return size and the return buffer pointer + param */ + *buffer += sizeof(ie_header); + ret_len += sizeof(ie_header); + + /* Copy the generic IE buffer to the output buffer, advance + pointer */ + memcpy(*buffer, priv->gen_ie_buf, priv->gen_ie_buf_len); + + /* Increment the return size and the return buffer pointer + param */ + *buffer += priv->gen_ie_buf_len; + ret_len += priv->gen_ie_buf_len; + + /* Reset the generic IE buffer */ + priv->gen_ie_buf_len = 0; + } + + /* return the length appended to the buffer */ + return ret_len; +} + +/* + * Append TSF tracking info from the scan table for the target AP. + * + * This function is called from the network join command preparation routine. + * + * The TSF table TSF sent to the firmware contains two TSF values: + * - The TSF of the target AP from its previous beacon/probe response + * - The TSF timestamp of our local MAC at the time we observed the + * beacon/probe response. + * + * The firmware uses the timestamp values to set an initial TSF value + * in the MAC for the new association after a reassociation attempt. + */ +static int +mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer, + struct mwifiex_bssdescriptor *bss_desc) +{ + struct mwifiex_ie_types_tsf_timestamp tsf_tlv; + long long tsf_val; + + /* Null Checks */ + if (buffer == NULL) + return 0; + if (*buffer == NULL) + return 0; + + memset(&tsf_tlv, 0x00, sizeof(struct mwifiex_ie_types_tsf_timestamp)); + + tsf_tlv.header.type = cpu_to_le16(TLV_TYPE_TSFTIMESTAMP); + tsf_tlv.header.len = cpu_to_le16(2 * sizeof(tsf_val)); + + memcpy(*buffer, &tsf_tlv, sizeof(tsf_tlv.header)); + *buffer += sizeof(tsf_tlv.header); + + memcpy(*buffer, &tsf_val, sizeof(tsf_val)); + *buffer += sizeof(tsf_val); + + memcpy(&tsf_val, bss_desc->time_stamp, sizeof(tsf_val)); + + dev_dbg(priv->adapter->dev, "info: %s: TSF offset calc: %016llx - " + "%016llx\n", __func__, tsf_val, bss_desc->network_tsf); + + memcpy(*buffer, &tsf_val, sizeof(tsf_val)); + *buffer += sizeof(tsf_val); + + return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val)); +} + +/* + * This function finds out the common rates between rate1 and rate2. + * + * It will fill common rates in rate1 as output if found. + * + * NOTE: Setting the MSB of the basic rates needs to be taken + * care of, either before or after calling this function. + */ +static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1, + u32 rate1_size, u8 *rate2, u32 rate2_size) +{ + int ret = 0; + u8 *ptr = rate1; + u8 *tmp = NULL; + u32 i, j; + + tmp = kmalloc(rate1_size, GFP_KERNEL); + if (!tmp) { + dev_err(priv->adapter->dev, "failed to alloc tmp buf\n"); + return -ENOMEM; + } + + memcpy(tmp, rate1, rate1_size); + memset(rate1, 0, rate1_size); + + for (i = 0; rate2[i] && i < rate2_size; i++) { + for (j = 0; tmp[j] && j < rate1_size; j++) { + /* Check common rate, excluding the bit for + basic rate */ + if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) { + *rate1++ = tmp[j]; + break; + } + } + } + + dev_dbg(priv->adapter->dev, "info: Tx data rate set to %#x\n", + priv->data_rate); + + if (!priv->is_data_rate_auto) { + while (*ptr) { + if ((*ptr & 0x7f) == priv->data_rate) { + ret = 0; + goto done; + } + ptr++; + } + dev_err(priv->adapter->dev, "previously set fixed data rate %#x" + " is not compatible with the network\n", + priv->data_rate); + + ret = -1; + goto done; + } + + ret = 0; +done: + kfree(tmp); + return ret; +} + +/* + * This function creates the intersection of the rates supported by a + * target BSS and our adapter settings for use in an assoc/join command. + */ +static int +mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc, + u8 *out_rates, u32 *out_rates_size) +{ + u8 card_rates[MWIFIEX_SUPPORTED_RATES]; + u32 card_rates_size = 0; + + /* Copy AP supported rates */ + memcpy(out_rates, bss_desc->supported_rates, MWIFIEX_SUPPORTED_RATES); + /* Get the STA supported rates */ + card_rates_size = mwifiex_get_active_data_rates(priv, card_rates); + /* Get the common rates between AP and STA supported rates */ + if (mwifiex_get_common_rates(priv, out_rates, MWIFIEX_SUPPORTED_RATES, + card_rates, card_rates_size)) { + *out_rates_size = 0; + dev_err(priv->adapter->dev, "%s: cannot get common rates\n", + __func__); + return -1; + } + + *out_rates_size = + min_t(size_t, strlen(out_rates), MWIFIEX_SUPPORTED_RATES); + + return 0; +} + +/* + * This function updates the scan entry TSF timestamps to reflect + * a new association. + */ +static void +mwifiex_update_tsf_timestamps(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *new_bss_desc) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u32 table_idx; + long long new_tsf_base; + signed long long tsf_delta; + + memcpy(&new_tsf_base, new_bss_desc->time_stamp, sizeof(new_tsf_base)); + + tsf_delta = new_tsf_base - new_bss_desc->network_tsf; + + dev_dbg(adapter->dev, "info: TSF: update TSF timestamps, " + "0x%016llx -> 0x%016llx\n", + new_bss_desc->network_tsf, new_tsf_base); + + for (table_idx = 0; table_idx < adapter->num_in_scan_table; + table_idx++) + adapter->scan_table[table_idx].network_tsf += tsf_delta; +} + +/* + * This function appends a WAPI IE. + * + * This function is called from the network join command preparation routine. + * + * If the IE buffer has been setup by the application, this routine appends + * the buffer as a WAPI TLV type to the request. + */ +static int +mwifiex_cmd_append_wapi_ie(struct mwifiex_private *priv, u8 **buffer) +{ + int retLen = 0; + struct mwifiex_ie_types_header ie_header; + + /* Null Checks */ + if (buffer == NULL) + return 0; + if (*buffer == NULL) + return 0; + + /* + * If there is a wapi ie buffer setup, append it to the return + * parameter buffer pointer. + */ + if (priv->wapi_ie_len) { + dev_dbg(priv->adapter->dev, "cmd: append wapi ie %d to %p\n", + priv->wapi_ie_len, *buffer); + + /* Wrap the generic IE buffer with a pass through TLV type */ + ie_header.type = cpu_to_le16(TLV_TYPE_WAPI_IE); + ie_header.len = cpu_to_le16(priv->wapi_ie_len); + memcpy(*buffer, &ie_header, sizeof(ie_header)); + + /* Increment the return size and the return buffer pointer + param */ + *buffer += sizeof(ie_header); + retLen += sizeof(ie_header); + + /* Copy the wapi IE buffer to the output buffer, advance + pointer */ + memcpy(*buffer, priv->wapi_ie, priv->wapi_ie_len); + + /* Increment the return size and the return buffer pointer + param */ + *buffer += priv->wapi_ie_len; + retLen += priv->wapi_ie_len; + + } + /* return the length appended to the buffer */ + return retLen; +} + +/* + * This function appends rsn ie tlv for wpa/wpa2 security modes. + * It is called from the network join command preparation routine. + */ +static int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv, + u8 **buffer) +{ + struct mwifiex_ie_types_rsn_param_set *rsn_ie_tlv; + int rsn_ie_len; + + if (!buffer || !(*buffer)) + return 0; + + rsn_ie_tlv = (struct mwifiex_ie_types_rsn_param_set *) (*buffer); + rsn_ie_tlv->header.type = cpu_to_le16((u16) priv->wpa_ie[0]); + rsn_ie_tlv->header.type = cpu_to_le16( + le16_to_cpu(rsn_ie_tlv->header.type) & 0x00FF); + rsn_ie_tlv->header.len = cpu_to_le16((u16) priv->wpa_ie[1]); + rsn_ie_tlv->header.len = cpu_to_le16(le16_to_cpu(rsn_ie_tlv->header.len) + & 0x00FF); + if (le16_to_cpu(rsn_ie_tlv->header.len) <= (sizeof(priv->wpa_ie) - 2)) + memcpy(rsn_ie_tlv->rsn_ie, &priv->wpa_ie[2], + le16_to_cpu(rsn_ie_tlv->header.len)); + else + return -1; + + rsn_ie_len = sizeof(rsn_ie_tlv->header) + + le16_to_cpu(rsn_ie_tlv->header.len); + *buffer += rsn_ie_len; + + return rsn_ie_len; +} + +/* + * This function prepares command for association. + * + * This sets the following parameters - + * - Peer MAC address + * - Listen interval + * - Beacon interval + * - Capability information + * + * ...and the following TLVs, as required - + * - SSID TLV + * - PHY TLV + * - SS TLV + * - Rates TLV + * - Authentication TLV + * - Channel TLV + * - WPA/WPA2 IE + * - 11n TLV + * - Vendor specific TLV + * - WMM TLV + * - WAPI IE + * - Generic IE + * - TSF TLV + * + * Preparation also includes - + * - Setting command ID and proper size + * - Ensuring correct endian-ness + */ +int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf) +{ + struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate; + struct mwifiex_bssdescriptor *bss_desc; + struct mwifiex_ie_types_ssid_param_set *ssid_tlv; + struct mwifiex_ie_types_phy_param_set *phy_tlv; + struct mwifiex_ie_types_ss_param_set *ss_tlv; + struct mwifiex_ie_types_rates_param_set *rates_tlv; + struct mwifiex_ie_types_auth_type *auth_tlv; + struct mwifiex_ie_types_chan_list_param_set *chan_tlv; + u8 rates[MWIFIEX_SUPPORTED_RATES]; + u32 rates_size; + u16 tmp_cap; + u8 *pos; + int rsn_ie_len = 0; + + bss_desc = (struct mwifiex_bssdescriptor *) data_buf; + pos = (u8 *) assoc; + + mwifiex_cfg_tx_buf(priv, bss_desc); + + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE); + + /* Save so we know which BSS Desc to use in the response handler */ + priv->attempted_bss_desc = bss_desc; + + memcpy(assoc->peer_sta_addr, + bss_desc->mac_address, sizeof(assoc->peer_sta_addr)); + pos += sizeof(assoc->peer_sta_addr); + + /* Set the listen interval */ + assoc->listen_interval = cpu_to_le16(priv->listen_interval); + /* Set the beacon period */ + assoc->beacon_period = cpu_to_le16(bss_desc->beacon_period); + + pos += sizeof(assoc->cap_info_bitmap); + pos += sizeof(assoc->listen_interval); + pos += sizeof(assoc->beacon_period); + pos += sizeof(assoc->dtim_period); + + ssid_tlv = (struct mwifiex_ie_types_ssid_param_set *) pos; + ssid_tlv->header.type = cpu_to_le16(WLAN_EID_SSID); + ssid_tlv->header.len = cpu_to_le16((u16) bss_desc->ssid.ssid_len); + memcpy(ssid_tlv->ssid, bss_desc->ssid.ssid, + le16_to_cpu(ssid_tlv->header.len)); + pos += sizeof(ssid_tlv->header) + le16_to_cpu(ssid_tlv->header.len); + + phy_tlv = (struct mwifiex_ie_types_phy_param_set *) pos; + phy_tlv->header.type = cpu_to_le16(WLAN_EID_DS_PARAMS); + phy_tlv->header.len = cpu_to_le16(sizeof(phy_tlv->fh_ds.ds_param_set)); + memcpy(&phy_tlv->fh_ds.ds_param_set, + &bss_desc->phy_param_set.ds_param_set.current_chan, + sizeof(phy_tlv->fh_ds.ds_param_set)); + pos += sizeof(phy_tlv->header) + le16_to_cpu(phy_tlv->header.len); + + ss_tlv = (struct mwifiex_ie_types_ss_param_set *) pos; + ss_tlv->header.type = cpu_to_le16(WLAN_EID_CF_PARAMS); + ss_tlv->header.len = cpu_to_le16(sizeof(ss_tlv->cf_ibss.cf_param_set)); + pos += sizeof(ss_tlv->header) + le16_to_cpu(ss_tlv->header.len); + + /* Get the common rates supported between the driver and the BSS Desc */ + if (mwifiex_setup_rates_from_bssdesc + (priv, bss_desc, rates, &rates_size)) + return -1; + + /* Save the data rates into Current BSS state structure */ + priv->curr_bss_params.num_of_rates = rates_size; + memcpy(&priv->curr_bss_params.data_rates, rates, rates_size); + + /* Setup the Rates TLV in the association command */ + rates_tlv = (struct mwifiex_ie_types_rates_param_set *) pos; + rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES); + rates_tlv->header.len = cpu_to_le16((u16) rates_size); + memcpy(rates_tlv->rates, rates, rates_size); + pos += sizeof(rates_tlv->header) + rates_size; + dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: rates size = %d\n", + rates_size); + + /* Add the Authentication type to be used for Auth frames if needed */ + if (priv->sec_info.authentication_mode != MWIFIEX_AUTH_MODE_AUTO) { + auth_tlv = (struct mwifiex_ie_types_auth_type *) pos; + auth_tlv->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); + auth_tlv->header.len = cpu_to_le16(sizeof(auth_tlv->auth_type)); + if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED) + auth_tlv->auth_type = cpu_to_le16((u16) priv->sec_info. + authentication_mode); + else + auth_tlv->auth_type = + cpu_to_le16(MWIFIEX_AUTH_MODE_OPEN); + pos += sizeof(auth_tlv->header) + + le16_to_cpu(auth_tlv->header.len); + } + + if (IS_SUPPORT_MULTI_BANDS(priv->adapter) + && !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info) + && (!bss_desc->disable_11n) + && (priv->adapter->config_bands & BAND_GN + || priv->adapter->config_bands & BAND_AN) + && (bss_desc->bcn_ht_cap) + ) + ) { + /* Append a channel TLV for the channel the attempted AP was + found on */ + chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; + chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); + chan_tlv->header.len = + cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); + + memset(chan_tlv->chan_scan_param, 0x00, + sizeof(struct mwifiex_chan_scan_param_set)); + chan_tlv->chan_scan_param[0].chan_number = + (bss_desc->phy_param_set.ds_param_set.current_chan); + dev_dbg(priv->adapter->dev, "info: Assoc: TLV Chan = %d\n", + chan_tlv->chan_scan_param[0].chan_number); + + chan_tlv->chan_scan_param[0].radio_type = + mwifiex_band_to_radio_type((u8) bss_desc->bss_band); + + dev_dbg(priv->adapter->dev, "info: Assoc: TLV Band = %d\n", + chan_tlv->chan_scan_param[0].radio_type); + pos += sizeof(chan_tlv->header) + + sizeof(struct mwifiex_chan_scan_param_set); + } + + if (!priv->wps.session_enable) { + if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) + rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); + + if (rsn_ie_len == -1) + return -1; + } + + if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) + && (!bss_desc->disable_11n) + && (priv->adapter->config_bands & BAND_GN + || priv->adapter->config_bands & BAND_AN)) + mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos); + + /* Append vendor specific IE TLV */ + mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_ASSOC, &pos); + + mwifiex_wmm_process_association_req(priv, &pos, &bss_desc->wmm_ie, + bss_desc->bcn_ht_cap); + if (priv->sec_info.wapi_enabled && priv->wapi_ie_len) + mwifiex_cmd_append_wapi_ie(priv, &pos); + + + mwifiex_cmd_append_generic_ie(priv, &pos); + + mwifiex_cmd_append_tsf_tlv(priv, &pos, bss_desc); + + cmd->size = cpu_to_le16((u16) (pos - (u8 *) assoc) + S_DS_GEN); + + /* Set the Capability info at last */ + tmp_cap = bss_desc->cap_info_bitmap; + + if (priv->adapter->config_bands == BAND_B) + SHORT_SLOT_TIME_DISABLED(tmp_cap); + + tmp_cap &= CAPINFO_MASK; + dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", + tmp_cap, CAPINFO_MASK); + assoc->cap_info_bitmap = cpu_to_le16(tmp_cap); + + return 0; +} + +/* + * Association firmware command response handler + * + * The response buffer for the association command has the following + * memory layout. + * + * For cases where an association response was not received (indicated + * by the CapInfo and AId field): + * + * .------------------------------------------------------------. + * | Header(4 * sizeof(t_u16)): Standard command response hdr | + * .------------------------------------------------------------. + * | cap_info/Error Return(t_u16): | + * | 0xFFFF(-1): Internal error | + * | 0xFFFE(-2): Authentication unhandled message | + * | 0xFFFD(-3): Authentication refused | + * | 0xFFFC(-4): Timeout waiting for AP response | + * .------------------------------------------------------------. + * | status_code(t_u16): | + * | If cap_info is -1: | + * | An internal firmware failure prevented the | + * | command from being processed. The status_code | + * | will be set to 1. | + * | | + * | If cap_info is -2: | + * | An authentication frame was received but was | + * | not handled by the firmware. IEEE Status | + * | code for the failure is returned. | + * | | + * | If cap_info is -3: | + * | An authentication frame was received and the | + * | status_code is the IEEE Status reported in the | + * | response. | + * | | + * | If cap_info is -4: | + * | (1) Association response timeout | + * | (2) Authentication response timeout | + * .------------------------------------------------------------. + * | a_id(t_u16): 0xFFFF | + * .------------------------------------------------------------. + * + * + * For cases where an association response was received, the IEEE + * standard association response frame is returned: + * + * .------------------------------------------------------------. + * | Header(4 * sizeof(t_u16)): Standard command response hdr | + * .------------------------------------------------------------. + * | cap_info(t_u16): IEEE Capability | + * .------------------------------------------------------------. + * | status_code(t_u16): IEEE Status Code | + * .------------------------------------------------------------. + * | a_id(t_u16): IEEE Association ID | + * .------------------------------------------------------------. + * | IEEE IEs(variable): Any received IEs comprising the | + * | remaining portion of a received | + * | association response frame. | + * .------------------------------------------------------------. + * + * For simplistic handling, the status_code field can be used to determine + * an association success (0) or failure (non-zero). + */ +int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, void *wq_buf) +{ + int ret = 0; + struct mwifiex_wait_queue *wait_queue = + (struct mwifiex_wait_queue *) wq_buf; + struct ieee_types_assoc_rsp *assoc_rsp; + struct mwifiex_bssdescriptor *bss_desc; + u8 enable_data = true; + + assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; + + priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN, + sizeof(priv->assoc_rsp_buf)); + + memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size); + + if (le16_to_cpu(assoc_rsp->status_code)) { + priv->adapter->dbg.num_cmd_assoc_failure++; + dev_err(priv->adapter->dev, "ASSOC_RESP: association failed, " + "status code = %d, error = 0x%x, a_id = 0x%x\n", + le16_to_cpu(assoc_rsp->status_code), + le16_to_cpu(assoc_rsp->cap_info_bitmap), + le16_to_cpu(assoc_rsp->a_id)); + + ret = -1; + goto done; + } + + /* Send a Media Connected event, according to the Spec */ + priv->media_connected = true; + + priv->adapter->ps_state = PS_STATE_AWAKE; + priv->adapter->pps_uapsd_mode = false; + priv->adapter->tx_lock_flag = false; + + /* Set the attempted BSSID Index to current */ + bss_desc = priv->attempted_bss_desc; + + dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: %s\n", + bss_desc->ssid.ssid); + + /* Make a copy of current BSSID descriptor */ + memcpy(&priv->curr_bss_params.bss_descriptor, + bss_desc, sizeof(struct mwifiex_bssdescriptor)); + + /* Update curr_bss_params */ + priv->curr_bss_params.bss_descriptor.channel + = bss_desc->phy_param_set.ds_param_set.current_chan; + + priv->curr_bss_params.band = (u8) bss_desc->bss_band; + + /* + * Adjust the timestamps in the scan table to be relative to the newly + * associated AP's TSF + */ + mwifiex_update_tsf_timestamps(priv, bss_desc); + + if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) + priv->curr_bss_params.wmm_enabled = true; + else + priv->curr_bss_params.wmm_enabled = false; + + if ((priv->wmm_required || bss_desc->bcn_ht_cap) + && priv->curr_bss_params.wmm_enabled) + priv->wmm_enabled = true; + else + priv->wmm_enabled = false; + + priv->curr_bss_params.wmm_uapsd_enabled = false; + + if (priv->wmm_enabled) + priv->curr_bss_params.wmm_uapsd_enabled + = ((bss_desc->wmm_ie.qos_info_bitmap & + IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0); + + dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: curr_pkt_filter is %#x\n", + priv->curr_pkt_filter); + if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) + priv->wpa_is_gtk_set = false; + + if (priv->wmm_enabled) { + /* Don't re-enable carrier until we get the WMM_GET_STATUS + event */ + enable_data = false; + } else { + /* Since WMM is not enabled, setup the queues with the + defaults */ + mwifiex_wmm_setup_queue_priorities(priv, NULL); + mwifiex_wmm_setup_ac_downgrade(priv); + } + + if (enable_data) + dev_dbg(priv->adapter->dev, + "info: post association, re-enabling data flow\n"); + + /* Reset SNR/NF/RSSI values */ + priv->data_rssi_last = 0; + priv->data_nf_last = 0; + priv->data_rssi_avg = 0; + priv->data_nf_avg = 0; + priv->bcn_rssi_last = 0; + priv->bcn_nf_last = 0; + priv->bcn_rssi_avg = 0; + priv->bcn_nf_avg = 0; + priv->rxpd_rate = 0; + priv->rxpd_htinfo = 0; + + mwifiex_save_curr_bcn(priv); + + priv->adapter->dbg.num_cmd_assoc_success++; + + dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: associated\n"); + + /* Add the ra_list here for infra mode as there will be only 1 ra + always */ + mwifiex_ralist_add(priv, + priv->curr_bss_params.bss_descriptor.mac_address); + + if (!netif_carrier_ok(priv->netdev)) + netif_carrier_on(priv->netdev); + if (netif_queue_stopped(priv->netdev)) + netif_wake_queue(priv->netdev); + + if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) + priv->scan_block = true; + +done: + /* Need to indicate IOCTL complete */ + if (wait_queue) { + if (ret) { + if (assoc_rsp->status_code) + wait_queue->status = + le16_to_cpu(assoc_rsp->status_code); + else + wait_queue->status = MWIFIEX_ERROR_ASSOC_FAIL; + } else { + wait_queue->status = MWIFIEX_ERROR_NO_ERROR; + } + } + + return ret; +} + +/* + * This function prepares command for ad-hoc start. + * + * Driver will fill up SSID, BSS mode, IBSS parameters, physical + * parameters, probe delay, and capability information. Firmware + * will fill up beacon period, basic rates and operational rates. + * + * In addition, the following TLVs are added - + * - Channel TLV + * - Vendor specific IE + * - WPA/WPA2 IE + * - HT Capabilities IE + * - HT Information IE + * + * Preparation also includes - + * - Setting command ID and proper size + * - Ensuring correct endian-ness + */ +int +mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, void *data_buf) +{ + int ret = 0, rsn_ie_len = 0; + struct mwifiex_adapter *adapter = priv->adapter; + struct host_cmd_ds_802_11_ad_hoc_start *adhoc_start = + &cmd->params.adhoc_start; + struct mwifiex_bssdescriptor *bss_desc; + u32 cmd_append_size = 0; + u32 i; + u16 tmp_cap; + uint16_t ht_cap_info; + struct mwifiex_ie_types_chan_list_param_set *chan_tlv; + + struct mwifiex_ie_types_htcap *ht_cap; + struct mwifiex_ie_types_htinfo *ht_info; + u8 *pos = (u8 *) adhoc_start + + sizeof(struct host_cmd_ds_802_11_ad_hoc_start); + + if (!adapter) + return -1; + + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START); + + bss_desc = &priv->curr_bss_params.bss_descriptor; + priv->attempted_bss_desc = bss_desc; + + /* + * Fill in the parameters for 2 data structures: + * 1. struct host_cmd_ds_802_11_ad_hoc_start command + * 2. bss_desc + * Driver will fill up SSID, bss_mode,IBSS param, Physical Param, + * probe delay, and Cap info. + * Firmware will fill up beacon period, Basic rates + * and operational rates. + */ + + memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN); + + memcpy(adhoc_start->ssid, + ((struct mwifiex_802_11_ssid *) data_buf)->ssid, + ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len); + + dev_dbg(adapter->dev, "info: ADHOC_S_CMD: SSID = %s\n", + adhoc_start->ssid); + + memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN); + memcpy(bss_desc->ssid.ssid, + ((struct mwifiex_802_11_ssid *) data_buf)->ssid, + ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len); + + bss_desc->ssid.ssid_len = + ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len; + + /* Set the BSS mode */ + adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS; + bss_desc->bss_mode = MWIFIEX_BSS_MODE_IBSS; + adhoc_start->beacon_period = cpu_to_le16(priv->beacon_period); + bss_desc->beacon_period = priv->beacon_period; + + /* Set Physical param set */ +/* Parameter IE Id */ +#define DS_PARA_IE_ID 3 +/* Parameter IE length */ +#define DS_PARA_IE_LEN 1 + + adhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID; + adhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN; + + if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211 + (priv, adapter->adhoc_start_band, (u16) + priv->adhoc_channel)) { + struct mwifiex_chan_freq_power *cfp; + cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv, + adapter->adhoc_start_band, FIRST_VALID_CHANNEL); + if (cfp) + priv->adhoc_channel = (u8) cfp->channel; + } + + if (!priv->adhoc_channel) { + dev_err(adapter->dev, "ADHOC_S_CMD: adhoc_channel cannot be 0\n"); + return -1; + } + + dev_dbg(adapter->dev, "info: ADHOC_S_CMD: creating ADHOC on channel %d\n", + priv->adhoc_channel); + + priv->curr_bss_params.bss_descriptor.channel = priv->adhoc_channel; + priv->curr_bss_params.band = adapter->adhoc_start_band; + + bss_desc->channel = priv->adhoc_channel; + adhoc_start->phy_param_set.ds_param_set.current_chan = + priv->adhoc_channel; + + memcpy(&bss_desc->phy_param_set, &adhoc_start->phy_param_set, + sizeof(union ieee_types_phy_param_set)); + + /* Set IBSS param set */ +/* IBSS parameter IE Id */ +#define IBSS_PARA_IE_ID 6 +/* IBSS parameter IE length */ +#define IBSS_PARA_IE_LEN 2 + + adhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID; + adhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN; + adhoc_start->ss_param_set.ibss_param_set.atim_window + = cpu_to_le16(priv->atim_window); + memcpy(&bss_desc->ss_param_set, &adhoc_start->ss_param_set, + sizeof(union ieee_types_ss_param_set)); + + /* Set Capability info */ + bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS; + tmp_cap = le16_to_cpu(adhoc_start->cap_info_bitmap); + tmp_cap &= ~WLAN_CAPABILITY_ESS; + tmp_cap |= WLAN_CAPABILITY_IBSS; + + /* Set up privacy in bss_desc */ + if (priv->sec_info.encryption_mode != MWIFIEX_ENCRYPTION_MODE_NONE) { + /* Ad-Hoc capability privacy on */ + dev_dbg(adapter->dev, + "info: ADHOC_S_CMD: wep_status set privacy to WEP\n"); + bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; + tmp_cap |= WLAN_CAPABILITY_PRIVACY; + } else { + dev_dbg(adapter->dev, "info: ADHOC_S_CMD: wep_status NOT set," + " setting privacy to ACCEPT ALL\n"); + bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL; + } + + memset(adhoc_start->DataRate, 0, sizeof(adhoc_start->DataRate)); + mwifiex_get_active_data_rates(priv, adhoc_start->DataRate); + if ((adapter->adhoc_start_band & BAND_G) && + (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) { + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, + HostCmd_ACT_GEN_SET, + 0, NULL, &priv->curr_pkt_filter); + + if (ret) { + dev_err(adapter->dev, + "ADHOC_S_CMD: G Protection config failed\n"); + return -1; + } + } + /* Find the last non zero */ + for (i = 0; i < sizeof(adhoc_start->DataRate) && + adhoc_start->DataRate[i]; + i++) + ; + + priv->curr_bss_params.num_of_rates = i; + + /* Copy the ad-hoc creating rates into Current BSS rate structure */ + memcpy(&priv->curr_bss_params.data_rates, + &adhoc_start->DataRate, priv->curr_bss_params.num_of_rates); + + dev_dbg(adapter->dev, "info: ADHOC_S_CMD: rates=%02x %02x %02x %02x\n", + adhoc_start->DataRate[0], adhoc_start->DataRate[1], + adhoc_start->DataRate[2], adhoc_start->DataRate[3]); + + dev_dbg(adapter->dev, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n"); + + if (IS_SUPPORT_MULTI_BANDS(adapter)) { + /* Append a channel TLV */ + chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; + chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); + chan_tlv->header.len = + cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); + + memset(chan_tlv->chan_scan_param, 0x00, + sizeof(struct mwifiex_chan_scan_param_set)); + chan_tlv->chan_scan_param[0].chan_number = + (u8) priv->curr_bss_params.bss_descriptor.channel; + + dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Chan = %d\n", + chan_tlv->chan_scan_param[0].chan_number); + + chan_tlv->chan_scan_param[0].radio_type + = mwifiex_band_to_radio_type(priv->curr_bss_params.band); + if (adapter->adhoc_start_band & BAND_GN + || adapter->adhoc_start_band & BAND_AN) { + if (adapter->chan_offset == SEC_CHANNEL_ABOVE) + chan_tlv->chan_scan_param[0].radio_type |= + SECOND_CHANNEL_ABOVE; + else if (adapter->chan_offset == SEC_CHANNEL_BELOW) + chan_tlv->chan_scan_param[0].radio_type |= + SECOND_CHANNEL_BELOW; + } + dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Band = %d\n", + chan_tlv->chan_scan_param[0].radio_type); + pos += sizeof(chan_tlv->header) + + sizeof(struct mwifiex_chan_scan_param_set); + cmd_append_size += + sizeof(chan_tlv->header) + + sizeof(struct mwifiex_chan_scan_param_set); + } + + /* Append vendor specific IE TLV */ + cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, + MWIFIEX_VSIE_MASK_ADHOC, &pos); + + if (priv->sec_info.wpa_enabled) { + rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); + if (rsn_ie_len == -1) + return -1; + cmd_append_size += rsn_ie_len; + } + + if (adapter->adhoc_11n_enabled) { + { + ht_cap = (struct mwifiex_ie_types_htcap *) pos; + memset(ht_cap, 0, + sizeof(struct mwifiex_ie_types_htcap)); + ht_cap->header.type = + cpu_to_le16(WLAN_EID_HT_CAPABILITY); + ht_cap->header.len = + cpu_to_le16(sizeof(struct ieee80211_ht_cap)); + ht_cap_info = le16_to_cpu(ht_cap->ht_cap.cap_info); + + SETHT_SHORTGI20(ht_cap_info); + if (adapter->chan_offset) { + SETHT_SHORTGI40(ht_cap_info); + SETHT_DSSSCCK40(ht_cap_info); + SETHT_SUPPCHANWIDTH(ht_cap_info); + SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); + } + + ht_cap->ht_cap.ampdu_params_info + = MAX_RX_AMPDU_SIZE_64K; + ht_cap->ht_cap.mcs.rx_mask[0] = 0xff; + pos += sizeof(struct mwifiex_ie_types_htcap); + cmd_append_size += + sizeof(struct mwifiex_ie_types_htcap); + } + { + ht_info = (struct mwifiex_ie_types_htinfo *) pos; + memset(ht_info, 0, + sizeof(struct mwifiex_ie_types_htinfo)); + ht_info->header.type = + cpu_to_le16(WLAN_EID_HT_INFORMATION); + ht_info->header.len = + cpu_to_le16(sizeof(struct ieee80211_ht_info)); + ht_info->ht_info.control_chan = + (u8) priv->curr_bss_params.bss_descriptor. + channel; + if (adapter->chan_offset) { + ht_info->ht_info.ht_param = + adapter->chan_offset; + SET_CHANWIDTH40(ht_info->ht_info.ht_param); + } + ht_info->ht_info.operation_mode = + cpu_to_le16(NON_GREENFIELD_STAS); + ht_info->ht_info.basic_set[0] = 0xff; + pos += sizeof(struct mwifiex_ie_types_htinfo); + cmd_append_size += + sizeof(struct mwifiex_ie_types_htinfo); + } + } + + cmd->size = cpu_to_le16((u16) + (sizeof(struct host_cmd_ds_802_11_ad_hoc_start) + + S_DS_GEN + cmd_append_size)); + + if (adapter->adhoc_start_band == BAND_B) + SHORT_SLOT_TIME_DISABLED(tmp_cap); + else + SHORT_SLOT_TIME_ENABLED(tmp_cap); + + adhoc_start->cap_info_bitmap = cpu_to_le16(tmp_cap); + + return 0; +} + +/* + * This function prepares command for ad-hoc join. + * + * Most of the parameters are set up by copying from the target BSS descriptor + * from the scan response. + * + * In addition, the following TLVs are added - + * - Channel TLV + * - Vendor specific IE + * - WPA/WPA2 IE + * - 11n IE + * + * Preparation also includes - + * - Setting command ID and proper size + * - Ensuring correct endian-ness + */ +int +mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, void *data_buf) +{ + int ret = 0, rsn_ie_len = 0; + struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join = + &cmd->params.adhoc_join; + struct mwifiex_bssdescriptor *bss_desc = + (struct mwifiex_bssdescriptor *) data_buf; + struct mwifiex_ie_types_chan_list_param_set *chan_tlv; + u32 cmd_append_size = 0; + u16 tmp_cap; + u32 i, rates_size = 0; + u16 curr_pkt_filter; + u8 *pos = + (u8 *) adhoc_join + + sizeof(struct host_cmd_ds_802_11_ad_hoc_join); + +/* Use G protection */ +#define USE_G_PROTECTION 0x02 + if (bss_desc->erp_flags & USE_G_PROTECTION) { + curr_pkt_filter = + priv-> + curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; + + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, + HostCmd_ACT_GEN_SET, 0, NULL, + &curr_pkt_filter); + if (ret) { + dev_err(priv->adapter->dev, + "ADHOC_J_CMD: G Protection config failed\n"); + return -1; + } + } + + priv->attempted_bss_desc = bss_desc; + + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN); + + adhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS; + + adhoc_join->bss_descriptor.beacon_period + = cpu_to_le16(bss_desc->beacon_period); + + memcpy(&adhoc_join->bss_descriptor.bssid, + &bss_desc->mac_address, ETH_ALEN); + + memcpy(&adhoc_join->bss_descriptor.ssid, + &bss_desc->ssid.ssid, bss_desc->ssid.ssid_len); + + memcpy(&adhoc_join->bss_descriptor.phy_param_set, + &bss_desc->phy_param_set, + sizeof(union ieee_types_phy_param_set)); + + memcpy(&adhoc_join->bss_descriptor.ss_param_set, + &bss_desc->ss_param_set, sizeof(union ieee_types_ss_param_set)); + + tmp_cap = bss_desc->cap_info_bitmap; + + tmp_cap &= CAPINFO_MASK; + + dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: tmp_cap=%4X" + " CAPINFO_MASK=%4lX\n", tmp_cap, CAPINFO_MASK); + + /* Information on BSSID descriptor passed to FW */ + dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: BSSID = %pM, SSID = %s\n", + adhoc_join->bss_descriptor.bssid, + adhoc_join->bss_descriptor.ssid); + + for (i = 0; bss_desc->supported_rates[i] && + i < MWIFIEX_SUPPORTED_RATES; + i++) + ; + rates_size = i; + + /* Copy Data Rates from the Rates recorded in scan response */ + memset(adhoc_join->bss_descriptor.data_rates, 0, + sizeof(adhoc_join->bss_descriptor.data_rates)); + memcpy(adhoc_join->bss_descriptor.data_rates, + bss_desc->supported_rates, rates_size); + + /* Copy the adhoc join rates into Current BSS state structure */ + priv->curr_bss_params.num_of_rates = rates_size; + memcpy(&priv->curr_bss_params.data_rates, bss_desc->supported_rates, + rates_size); + + /* Copy the channel information */ + priv->curr_bss_params.bss_descriptor.channel = bss_desc->channel; + priv->curr_bss_params.band = (u8) bss_desc->bss_band; + + if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED + || priv->sec_info.wpa_enabled) + tmp_cap |= WLAN_CAPABILITY_PRIVACY; + + if (IS_SUPPORT_MULTI_BANDS(priv->adapter)) { + /* Append a channel TLV */ + chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; + chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); + chan_tlv->header.len = + cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); + + memset(chan_tlv->chan_scan_param, 0x00, + sizeof(struct mwifiex_chan_scan_param_set)); + chan_tlv->chan_scan_param[0].chan_number = + (bss_desc->phy_param_set.ds_param_set.current_chan); + dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Chan = %d\n", + chan_tlv->chan_scan_param[0].chan_number); + + chan_tlv->chan_scan_param[0].radio_type = + mwifiex_band_to_radio_type((u8) bss_desc->bss_band); + + dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Band = %d\n", + chan_tlv->chan_scan_param[0].radio_type); + pos += sizeof(chan_tlv->header) + + sizeof(struct mwifiex_chan_scan_param_set); + cmd_append_size += sizeof(chan_tlv->header) + + sizeof(struct mwifiex_chan_scan_param_set); + } + + if (priv->sec_info.wpa_enabled) + rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); + if (rsn_ie_len == -1) + return -1; + cmd_append_size += rsn_ie_len; + + if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) + cmd_append_size += mwifiex_cmd_append_11n_tlv(priv, + bss_desc, &pos); + + /* Append vendor specific IE TLV */ + cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, + MWIFIEX_VSIE_MASK_ADHOC, &pos); + + cmd->size = cpu_to_le16((u16) + (sizeof(struct host_cmd_ds_802_11_ad_hoc_join) + + S_DS_GEN + cmd_append_size)); + + adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap); + + return ret; +} + +/* + * This function handles the command response of ad-hoc start and + * ad-hoc join. + * + * The function generates a device-connected event to notify + * the applications, in case of successful ad-hoc start/join, and + * saves the beacon buffer. + */ +int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, void *wq_buf) +{ + int ret = 0; + struct mwifiex_wait_queue *wait_queue = + (struct mwifiex_wait_queue *) wq_buf; + struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result; + struct mwifiex_bssdescriptor *bss_desc; + u16 command = le16_to_cpu(resp->command); + u16 result = le16_to_cpu(resp->result); + + adhoc_result = &resp->params.adhoc_result; + + bss_desc = priv->attempted_bss_desc; + + /* Join result code 0 --> SUCCESS */ + if (result) { + dev_err(priv->adapter->dev, "ADHOC_RESP: failed\n"); + if (priv->media_connected) + mwifiex_reset_connect_state(priv); + + memset(&priv->curr_bss_params.bss_descriptor, + 0x00, sizeof(struct mwifiex_bssdescriptor)); + + ret = -1; + goto done; + } + + /* Send a Media Connected event, according to the Spec */ + priv->media_connected = true; + + if (command == HostCmd_CMD_802_11_AD_HOC_START) { + dev_dbg(priv->adapter->dev, "info: ADHOC_S_RESP %s\n", + bss_desc->ssid.ssid); + + /* Update the created network descriptor with the new BSSID */ + memcpy(bss_desc->mac_address, + adhoc_result->bssid, ETH_ALEN); + + priv->adhoc_state = ADHOC_STARTED; + } else { + /* + * Now the join cmd should be successful. + * If BSSID has changed use SSID to compare instead of BSSID + */ + dev_dbg(priv->adapter->dev, "info: ADHOC_J_RESP %s\n", + bss_desc->ssid.ssid); + + /* + * Make a copy of current BSSID descriptor, only needed for + * join since the current descriptor is already being used + * for adhoc start + */ + memcpy(&priv->curr_bss_params.bss_descriptor, + bss_desc, sizeof(struct mwifiex_bssdescriptor)); + + priv->adhoc_state = ADHOC_JOINED; + } + + dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: channel = %d\n", + priv->adhoc_channel); + dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: BSSID = %pM\n", + priv->curr_bss_params.bss_descriptor.mac_address); + + if (!netif_carrier_ok(priv->netdev)) + netif_carrier_on(priv->netdev); + if (netif_queue_stopped(priv->netdev)) + netif_wake_queue(priv->netdev); + + mwifiex_save_curr_bcn(priv); + +done: + /* Need to indicate IOCTL complete */ + if (wait_queue) { + if (ret) + wait_queue->status = MWIFIEX_ERROR_ASSOC_FAIL; + else + wait_queue->status = MWIFIEX_ERROR_NO_ERROR; + + } + + return ret; +} + +/* + * This function associates to a specific BSS discovered in a scan. + * + * It clears any past association response stored for application + * retrieval and calls the command preparation routine to send the + * command to firmware. + */ +int mwifiex_associate(struct mwifiex_private *priv, + void *wait_queue, struct mwifiex_bssdescriptor *bss_desc) +{ + int ret = 0; + u8 current_bssid[ETH_ALEN]; + + /* Return error if the adapter or table entry is not marked as infra */ + if ((priv->bss_mode != MWIFIEX_BSS_MODE_INFRA) || + (bss_desc->bss_mode != MWIFIEX_BSS_MODE_INFRA)) + return -1; + + memcpy(¤t_bssid, + &priv->curr_bss_params.bss_descriptor.mac_address, + sizeof(current_bssid)); + + /* Clear any past association response stored for application + retrieval */ + priv->assoc_rsp_size = 0; + + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_ASSOCIATE, + HostCmd_ACT_GEN_SET, 0, wait_queue, + bss_desc); + + return ret; +} + +/* + * This function starts an ad-hoc network. + * + * It calls the command preparation routine to send the command to firmware. + */ +int +mwifiex_adhoc_start(struct mwifiex_private *priv, + void *wait_queue, struct mwifiex_802_11_ssid *adhoc_ssid) +{ + int ret = 0; + + dev_dbg(priv->adapter->dev, "info: Adhoc Channel = %d\n", + priv->adhoc_channel); + dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", + priv->curr_bss_params.bss_descriptor.channel); + dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n", + priv->curr_bss_params.band); + + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_AD_HOC_START, + HostCmd_ACT_GEN_SET, 0, wait_queue, + adhoc_ssid); + + return ret; +} + +/* + * This function joins an ad-hoc network found in a previous scan. + * + * It calls the command preparation routine to send the command to firmware, + * if already not connected to the requested SSID. + */ +int mwifiex_adhoc_join(struct mwifiex_private *priv, + void *wait_queue, struct mwifiex_bssdescriptor *bss_desc) +{ + int ret = 0; + + dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid =%s\n", + priv->curr_bss_params.bss_descriptor.ssid.ssid); + dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid_len =%u\n", + priv->curr_bss_params.bss_descriptor.ssid.ssid_len); + dev_dbg(priv->adapter->dev, "info: adhoc join: ssid =%s\n", + bss_desc->ssid.ssid); + dev_dbg(priv->adapter->dev, "info: adhoc join: ssid_len =%u\n", + bss_desc->ssid.ssid_len); + + /* Check if the requested SSID is already joined */ + if (priv->curr_bss_params.bss_descriptor.ssid.ssid_len && + !mwifiex_ssid_cmp(&bss_desc->ssid, + &priv->curr_bss_params.bss_descriptor.ssid) && + (priv->curr_bss_params.bss_descriptor.bss_mode == + MWIFIEX_BSS_MODE_IBSS)) { + dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: new ad-hoc SSID" + " is the same as current; not attempting to re-join\n"); + return -1; + } + + dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", + priv->curr_bss_params.bss_descriptor.channel); + dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n", + priv->curr_bss_params.band); + + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, + HostCmd_ACT_GEN_SET, 0, wait_queue, + bss_desc); + + return ret; +} + +/* + * This function deauthenticates/disconnects from infra network by sending + * deauthentication request. + */ +static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + u8 *mac) +{ + u8 mac_address[ETH_ALEN]; + int ret = 0; + u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; + + if (mac) { + if (!memcmp(mac, zero_mac, sizeof(zero_mac))) + memcpy((u8 *) &mac_address, + (u8 *) &priv->curr_bss_params.bss_descriptor. + mac_address, ETH_ALEN); + else + memcpy((u8 *) &mac_address, (u8 *) mac, ETH_ALEN); + } else { + memcpy((u8 *) &mac_address, (u8 *) &priv->curr_bss_params. + bss_descriptor.mac_address, ETH_ALEN); + } + + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, + HostCmd_ACT_GEN_SET, 0, wait, &mac_address); + + if (!ret && wait) + ret = -EINPROGRESS; + + return ret; +} + +/* + * This function deauthenticates/disconnects from a BSS. + * + * In case of infra made, it sends deauthentication request, and + * in case of ad-hoc mode, a stop network request is sent to the firmware. + */ +int mwifiex_deauthenticate(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, u8 *mac) +{ + int ret = 0; + + if (priv->media_connected) { + if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA) { + ret = mwifiex_deauthenticate_infra(priv, wait, mac); + } else if (priv->bss_mode == MWIFIEX_BSS_MODE_IBSS) { + ret = mwifiex_prepare_cmd(priv, + HostCmd_CMD_802_11_AD_HOC_STOP, + HostCmd_ACT_GEN_SET, 0, wait, NULL); + + if (!ret && wait) + ret = -EINPROGRESS; + } + } + + return ret; +} + +/* + * This function converts band to radio type used in channel TLV. + */ +u8 +mwifiex_band_to_radio_type(u8 band) +{ + u8 ret_radio_type; + + switch (band) { + case BAND_A: + case BAND_AN: + case BAND_A | BAND_AN: + ret_radio_type = HostCmd_SCAN_RADIO_TYPE_A; + break; + case BAND_B: + case BAND_G: + case BAND_B | BAND_G: + default: + ret_radio_type = HostCmd_SCAN_RADIO_TYPE_BG; + break; + } + + return ret_radio_type; +} diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c new file mode 100644 index 000000000000..ed89ca41a902 --- /dev/null +++ b/drivers/net/wireless/mwifiex/main.c @@ -0,0 +1,1102 @@ +/* + * Marvell Wireless LAN device driver: major functions + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "main.h" +#include "wmm.h" +#include "cfg80211.h" +#include "11n.h" + +#define VERSION "1.0" + +const char driver_version[] = "mwifiex " VERSION " (%s) "; + +struct mwifiex_adapter *g_adapter; +EXPORT_SYMBOL_GPL(g_adapter); + +static struct mwifiex_bss_attr mwifiex_bss_sta[] = { + {MWIFIEX_BSS_TYPE_STA, MWIFIEX_DATA_FRAME_TYPE_ETH_II, true, 0, 0}, +}; + +static int drv_mode = DRV_MODE_STA; + +static char fw_name[32] = DEFAULT_FW_NAME; + +/* Supported drv_mode table */ +static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = { + { + /* drv_mode */ + .drv_mode = DRV_MODE_STA, + /* intf number */ + .intf_num = ARRAY_SIZE(mwifiex_bss_sta), + /* bss_attr */ + .bss_attr = mwifiex_bss_sta, + } + , +}; + +/* + * This function registers the device and performs all the necessary + * initializations. + * + * The following initialization operations are performed - + * - Allocate adapter structure + * - Save interface specific operations table in adapter + * - Call interface specific initialization routine + * - Allocate private structures + * - Set default adapter structure parameters + * - Initialize locks + * + * In case of any errors during inittialization, this function also ensures + * proper cleanup before exiting. + */ +static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, + struct mwifiex_device *mdevice, void **padapter) +{ + int ret = 0; + struct mwifiex_adapter *adapter = NULL; + u8 i = 0; + + adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL); + /* Allocate memory for adapter structure */ + if (!adapter) + return -1; + + g_adapter = adapter; + adapter->card = card; + + /* Save interface specific operations in adapter */ + memmove(&adapter->if_ops, if_ops, sizeof(struct mwifiex_if_ops)); + + /* card specific initialization has been deferred until now .. */ + ret = adapter->if_ops.init_if(adapter); + if (ret) + goto error; + + adapter->priv_num = 0; + for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) { + adapter->priv[i] = NULL; + + if (!mdevice->bss_attr[i].active) + continue; + + /* For valid bss_attr, + allocate memory for private structure */ + adapter->priv[i] = kzalloc(sizeof(struct mwifiex_private), + GFP_KERNEL); + if (!adapter->priv[i]) { + dev_err(adapter->dev, "%s: failed to alloc priv[%d]\n", + __func__, i); + goto error; + } + + adapter->priv_num++; + memset(adapter->priv[i], 0, + sizeof(struct mwifiex_private)); + adapter->priv[i]->adapter = adapter; + /* Save bss_type, frame_type & bss_priority */ + adapter->priv[i]->bss_type = (u8) mdevice->bss_attr[i].bss_type; + adapter->priv[i]->frame_type = + (u8) mdevice->bss_attr[i].frame_type; + adapter->priv[i]->bss_priority = + (u8) mdevice->bss_attr[i].bss_priority; + if (mdevice->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_STA) + adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_STA; + else if (mdevice->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_UAP) + adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_UAP; + + /* Save bss_index & bss_num */ + adapter->priv[i]->bss_index = i; + adapter->priv[i]->bss_num = mdevice->bss_attr[i].bss_num; + } + + /* Initialize lock variables */ + if (mwifiex_init_lock_list(adapter)) + goto error; + + init_timer(&adapter->cmd_timer); + adapter->cmd_timer.function = mwifiex_cmd_timeout_func; + adapter->cmd_timer.data = (unsigned long) adapter; + + /* Return pointer of struct mwifiex_adapter */ + *padapter = adapter; + return 0; + +error: + dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n"); + + /* Free lock variables */ + mwifiex_free_lock_list(adapter); + for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) + kfree(adapter->priv[i]); + kfree(adapter); + + return -1; +} + +/* + * This function unregisters the device and performs all the necessary + * cleanups. + * + * The following cleanup operations are performed - + * - Free the timers + * - Free beacon buffers + * - Free private structures + * - Free adapter structure + */ +static int mwifiex_unregister(struct mwifiex_adapter *adapter) +{ + s32 i = 0; + + del_timer(&adapter->cmd_timer); + + /* Free private structures */ + for (i = 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + mwifiex_free_curr_bcn(adapter->priv[i]); + kfree(adapter->priv[i]); + } + } + + kfree(adapter); + return 0; +} + +/* + * The main process. + * + * This function is the main procedure of the driver and handles various driver + * operations. It runs in a loop and provides the core functionalities. + * + * The main responsibilities of this function are - + * - Ensure concurrency control + * - Handle pending interrupts and call interrupt handlers + * - Wake up the card if required + * - Handle command responses and call response handlers + * - Handle events and call event handlers + * - Execute pending commands + * - Transmit pending data packets + */ +int mwifiex_main_process(struct mwifiex_adapter *adapter) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&adapter->main_proc_lock, flags); + + /* Check if already processing */ + if (adapter->mwifiex_processing) { + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + goto exit_main_proc; + } else { + adapter->mwifiex_processing = true; + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + } +process_start: + do { + if ((adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) || + (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY)) + break; + + /* Handle pending interrupt if any */ + if (adapter->int_status) { + if (adapter->hs_activated) + mwifiex_process_hs_config(adapter); + adapter->if_ops.process_int_status(adapter); + } + + /* Need to wake up the card ? */ + if ((adapter->ps_state == PS_STATE_SLEEP) && + (adapter->pm_wakeup_card_req && + !adapter->pm_wakeup_fw_try) && + (is_command_pending(adapter) + || !mwifiex_wmm_lists_empty(adapter))) { + adapter->pm_wakeup_fw_try = true; + adapter->if_ops.wakeup(adapter); + continue; + } + if (IS_CARD_RX_RCVD(adapter)) { + adapter->pm_wakeup_fw_try = false; + if (adapter->ps_state == PS_STATE_SLEEP) + adapter->ps_state = PS_STATE_AWAKE; + } else { + /* We have tried to wakeup the card already */ + if (adapter->pm_wakeup_fw_try) + break; + if (adapter->ps_state != PS_STATE_AWAKE || + adapter->tx_lock_flag) + break; + + if (adapter->scan_processing || adapter->data_sent + || mwifiex_wmm_lists_empty(adapter)) { + if (adapter->cmd_sent || adapter->curr_cmd + || (!is_command_pending(adapter))) + break; + } + } + + /* Check for Cmd Resp */ + if (adapter->cmd_resp_received) { + adapter->cmd_resp_received = false; + mwifiex_process_cmdresp(adapter); + + /* call mwifiex back when init_fw is done */ + if (adapter->hw_status == MWIFIEX_HW_STATUS_INIT_DONE) { + adapter->hw_status = MWIFIEX_HW_STATUS_READY; + mwifiex_init_fw_complete(adapter); + } + } + + /* Check for event */ + if (adapter->event_received) { + adapter->event_received = false; + mwifiex_process_event(adapter); + } + + /* Check if we need to confirm Sleep Request + received previously */ + if (adapter->ps_state == PS_STATE_PRE_SLEEP) { + if (!adapter->cmd_sent && !adapter->curr_cmd) + mwifiex_check_ps_cond(adapter); + } + + /* * The ps_state may have been changed during processing of + * Sleep Request event. + */ + if ((adapter->ps_state == PS_STATE_SLEEP) + || (adapter->ps_state == PS_STATE_PRE_SLEEP) + || (adapter->ps_state == PS_STATE_SLEEP_CFM) + || adapter->tx_lock_flag) + continue; + + if (!adapter->cmd_sent && !adapter->curr_cmd) { + if (mwifiex_exec_next_cmd(adapter) == -1) { + ret = -1; + break; + } + } + + if (!adapter->scan_processing && !adapter->data_sent && + !mwifiex_wmm_lists_empty(adapter)) { + mwifiex_wmm_process_tx(adapter); + if (adapter->hs_activated) { + adapter->is_hs_configured = false; + mwifiex_hs_activated_event + (mwifiex_get_priv + (adapter, MWIFIEX_BSS_ROLE_ANY), + false); + } + } + + if (adapter->delay_null_pkt && !adapter->cmd_sent && + !adapter->curr_cmd && !is_command_pending(adapter) + && mwifiex_wmm_lists_empty(adapter)) { + if (!mwifiex_send_null_packet + (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), + MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | + MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) { + adapter->delay_null_pkt = false; + adapter->ps_state = PS_STATE_SLEEP; + } + break; + } + } while (true); + + if ((adapter->int_status) || IS_CARD_RX_RCVD(adapter)) + goto process_start; + + spin_lock_irqsave(&adapter->main_proc_lock, flags); + adapter->mwifiex_processing = false; + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + +exit_main_proc: + if (adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) + mwifiex_shutdown_drv(adapter); + return ret; +} + +/* + * This function initializes the software. + * + * The main work includes allocating and initializing the adapter structure + * and initializing the private structures. + */ +static int +mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **pmwifiex) +{ + int i; + struct mwifiex_device device; + struct mwifiex_drv_mode *drv_mode_ptr; + + /* find mwifiex_drv_mode entry from mwifiex_drv_mode_tbl */ + drv_mode_ptr = NULL; + for (i = 0; i < ARRAY_SIZE(mwifiex_drv_mode_tbl); i++) { + if (mwifiex_drv_mode_tbl[i].drv_mode == drv_mode) { + drv_mode_ptr = &mwifiex_drv_mode_tbl[i]; + break; + } + } + + if (!drv_mode_ptr) { + pr_err("invalid drv_mode=%d\n", drv_mode); + return -1; + } + + memset(&device, 0, sizeof(struct mwifiex_device)); + + for (i = 0; i < drv_mode_ptr->intf_num; i++) { + device.bss_attr[i].bss_type = + drv_mode_ptr->bss_attr[i].bss_type; + device.bss_attr[i].frame_type = + drv_mode_ptr->bss_attr[i].frame_type; + device.bss_attr[i].active = drv_mode_ptr->bss_attr[i].active; + device.bss_attr[i].bss_priority = + drv_mode_ptr->bss_attr[i].bss_priority; + device.bss_attr[i].bss_num = drv_mode_ptr->bss_attr[i].bss_num; + } + + if (mwifiex_register(card, if_ops, &device, pmwifiex)) + return -1; + + return 0; +} + +/* + * This function frees the adapter structure. + * + * Additionally, this closes the netlink socket, frees the timers + * and private structures. + */ +static void mwifiex_free_adapter(struct mwifiex_adapter *adapter) +{ + if (!adapter) { + pr_err("%s: adapter is NULL\n", __func__); + return; + } + + mwifiex_unregister(adapter); + pr_debug("info: %s: free adapter\n", __func__); +} + +/* + * This function initializes the hardware and firmware. + * + * The main initialization steps followed are - + * - Download the correct firmware to card + * - Allocate and initialize the adapter structure + * - Initialize the private structures + * - Issue the init commands to firmware + */ +static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) +{ + int ret = 0; + int err; + struct mwifiex_fw_image fw; + + memset(&fw, 0, sizeof(struct mwifiex_fw_image)); + + switch (adapter->revision_id) { + case SD8787_W0: + case SD8787_W1: + strcpy(fw_name, SD8787_W1_FW_NAME); + break; + case SD8787_A0: + case SD8787_A1: + strcpy(fw_name, SD8787_AX_FW_NAME); + break; + default: + break; + } + + err = request_firmware(&adapter->firmware, fw_name, adapter->dev); + if (err < 0) { + dev_err(adapter->dev, "request_firmware() returned" + " error code %#x\n", err); + ret = -1; + goto done; + } + fw.fw_buf = (u8 *) adapter->firmware->data; + fw.fw_len = adapter->firmware->size; + + ret = mwifiex_dnld_fw(adapter, &fw); + if (ret == -1) + goto done; + + dev_notice(adapter->dev, "WLAN FW is active\n"); + + adapter->init_wait_q_woken = false; + ret = mwifiex_init_fw(adapter); + if (ret == -1) { + goto done; + } else if (!ret) { + adapter->hw_status = MWIFIEX_HW_STATUS_READY; + goto done; + } + /* Wait for mwifiex_init to complete */ + wait_event_interruptible(adapter->init_wait_q, + adapter->init_wait_q_woken); + if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) { + ret = -1; + goto done; + } + ret = 0; + +done: + if (adapter->firmware) + release_firmware(adapter->firmware); + if (ret) + ret = -1; + return ret; +} + +/* + * This function fills a driver buffer. + * + * The function associates a given SKB with the provided driver buffer + * and also updates some of the SKB parameters, including IP header, + * priority and timestamp. + */ +static void +mwifiex_fill_buffer(struct sk_buff *skb) +{ + struct ethhdr *eth = NULL; + struct iphdr *iph; + struct timeval tv; + u8 tid = 0; + + eth = (struct ethhdr *) skb->data; + switch (eth->h_proto) { + case __constant_htons(ETH_P_IP): + iph = ip_hdr(skb); + tid = IPTOS_PREC(iph->tos); + pr_debug("data: packet type ETH_P_IP: %04x, tid=%#x prio=%#x\n", + eth->h_proto, tid, skb->priority); + break; + case __constant_htons(ETH_P_ARP): + pr_debug("data: ARP packet: %04x\n", eth->h_proto); + default: + break; + } +/* Offset for TOS field in the IP header */ +#define IPTOS_OFFSET 5 + tid = (tid >> IPTOS_OFFSET); + skb->priority = tid; + /* Record the current time the packet was queued; used to + determine the amount of time the packet was queued in + the driver before it was sent to the firmware. + The delay is then sent along with the packet to the + firmware for aggregate delay calculation for stats and + MSDU lifetime expiry. + */ + do_gettimeofday(&tv); + skb->tstamp = timeval_to_ktime(tv); + return; +} + +/* + * CFG802.11 network device handler for open. + * + * Starts the data queue. + */ +static int +mwifiex_open(struct net_device *dev) +{ + netif_start_queue(dev); + return 0; +} + +/* + * CFG802.11 network device handler for close. + */ +static int +mwifiex_close(struct net_device *dev) +{ + return 0; +} + +/* + * CFG802.11 network device handler for data transmission. + */ +static int +mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + struct sk_buff *new_skb = NULL; + struct mwifiex_txinfo *tx_info; + + dev_dbg(priv->adapter->dev, "data: %lu BSS(%d): Data <= kernel\n", + jiffies, priv->bss_index); + + if (priv->adapter->surprise_removed) { + kfree(skb); + priv->stats.tx_dropped++; + return 0; + } + if (!skb->len || (skb->len > ETH_FRAME_LEN)) { + dev_err(priv->adapter->dev, "Tx: bad skb len %d\n", skb->len); + kfree(skb); + priv->stats.tx_dropped++; + return 0; + } + if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) { + dev_dbg(priv->adapter->dev, + "data: Tx: insufficient skb headroom %d\n", + skb_headroom(skb)); + /* Insufficient skb headroom - allocate a new skb */ + new_skb = + skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN); + if (unlikely(!new_skb)) { + dev_err(priv->adapter->dev, "Tx: cannot alloca new_skb\n"); + kfree(skb); + priv->stats.tx_dropped++; + return 0; + } + kfree_skb(skb); + skb = new_skb; + dev_dbg(priv->adapter->dev, "info: new skb headroomd %d\n", + skb_headroom(skb)); + } + + tx_info = MWIFIEX_SKB_TXCB(skb); + tx_info->bss_index = priv->bss_index; + mwifiex_fill_buffer(skb); + + mwifiex_wmm_add_buf_txqueue(priv->adapter, skb); + atomic_inc(&priv->adapter->tx_pending); + + if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) { + netif_stop_queue(priv->netdev); + dev->trans_start = jiffies; + } + + queue_work(priv->adapter->workqueue, &priv->adapter->main_work); + + return 0; +} + +/* + * CFG802.11 network device handler for setting MAC address. + */ +static int +mwifiex_set_mac_address(struct net_device *dev, void *addr) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + struct sockaddr *hw_addr = (struct sockaddr *) addr; + + memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN); + + if (mwifiex_request_set_mac_address(priv)) { + dev_err(priv->adapter->dev, "set MAC address failed\n"); + return -EFAULT; + } + memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); + + return 0; +} + +/* + * CFG802.11 network device handler for setting multicast list. + */ +static void mwifiex_set_multicast_list(struct net_device *dev) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + mwifiex_request_set_multicast_list(priv, dev); +} + +/* + * CFG802.11 network device handler for transmission timeout. + */ +static void +mwifiex_tx_timeout(struct net_device *dev) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_index=%d\n", + jiffies, priv->bss_index); + dev->trans_start = jiffies; + priv->num_tx_timeout++; +} + +/* + * CFG802.11 network device handler for statistics retrieval. + */ +static struct net_device_stats *mwifiex_get_stats(struct net_device *dev) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + return &priv->stats; +} + +/* Network device handlers */ +static const struct net_device_ops mwifiex_netdev_ops = { + .ndo_open = mwifiex_open, + .ndo_stop = mwifiex_close, + .ndo_start_xmit = mwifiex_hard_start_xmit, + .ndo_set_mac_address = mwifiex_set_mac_address, + .ndo_tx_timeout = mwifiex_tx_timeout, + .ndo_get_stats = mwifiex_get_stats, + .ndo_set_multicast_list = mwifiex_set_multicast_list, +}; + +/* + * This function initializes the private structure parameters. + * + * The following wait queues are initialized - + * - IOCTL wait queue + * - Command wait queue + * - Statistics wait queue + * + * ...and the following default parameters are set - + * - Current key index : Set to 0 + * - Rate index : Set to auto + * - Media connected : Set to disconnected + * - Adhoc link sensed : Set to false + * - Nick name : Set to null + * - Number of Tx timeout : Set to 0 + * - Device address : Set to current address + * + * In addition, the CFG80211 work queue is also created. + */ +static void +mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev) +{ + dev->netdev_ops = &mwifiex_netdev_ops; + /* Initialize private structure */ + init_waitqueue_head(&priv->ioctl_wait_q); + init_waitqueue_head(&priv->cmd_wait_q); + init_waitqueue_head(&priv->w_stats_wait_q); + priv->current_key_index = 0; + priv->media_connected = false; + memset(&priv->nick_name, 0, sizeof(priv->nick_name)); + priv->num_tx_timeout = 0; + priv->workqueue = create_singlethread_workqueue("cfg80211_wq"); + INIT_WORK(&priv->cfg_workqueue, mwifiex_cfg80211_results); + memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); +} + +/* + * This function adds a new logical interface. + * + * It allocates, initializes and registers the interface by performing + * the following opearations - + * - Allocate a new net device structure + * - Assign device name + * - Register the new device with CFG80211 subsystem + * - Initialize semaphore and private structure + * - Register the new device with kernel + * - Create the complete debug FS structure if configured + */ +static struct mwifiex_private *mwifiex_add_interface( + struct mwifiex_adapter *adapter, + u8 bss_index, u8 bss_type) +{ + struct net_device *dev = NULL; + struct mwifiex_private *priv = NULL; + void *mdev_priv = NULL; + + dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), "mlan%d", + ether_setup, 1); + if (!dev) { + dev_err(adapter->dev, "no memory available for netdevice\n"); + goto error; + } + if (dev_alloc_name(dev, dev->name)) { + dev_err(adapter->dev, "unable to alloc name for netdevice\n"); + goto error; + } + + if (mwifiex_register_cfg80211(dev, adapter->priv[bss_index]->curr_addr, + adapter->priv[bss_index]) != 0) { + dev_err(adapter->dev, "cannot register netdevice with cfg80211\n"); + goto error; + } + /* Save the priv pointer in netdev */ + priv = adapter->priv[bss_index]; + mdev_priv = netdev_priv(dev); + *((unsigned long *) mdev_priv) = (unsigned long) priv; + + priv->netdev = dev; + + sema_init(&priv->async_sem, 1); + priv->scan_pending_on_block = false; + + mwifiex_init_priv_params(priv, dev); + + SET_NETDEV_DEV(dev, adapter->dev); + + /* Register network device */ + if (register_netdev(dev)) { + dev_err(adapter->dev, "cannot register virtual network device\n"); + goto error; + } + + dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); +#ifdef CONFIG_DEBUG_FS + mwifiex_dev_debugfs_init(priv); +#endif + return priv; +error: + if (dev) + free_netdev(dev); + return NULL; +} + +/* + * This function removes a logical interface. + * + * It deregisters, resets and frees the interface by performing + * the following operations - + * - Disconnect the device if connected, send wireless event to + * notify applications. + * - Remove the debug FS structure if configured + * - Unregister the device from kernel + * - Free the net device structure + * - Cancel all works and destroy work queue + * - Unregister and free the wireless device from CFG80211 subsystem + */ +static void +mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index) +{ + struct net_device *dev = NULL; + struct mwifiex_private *priv = adapter->priv[bss_index]; + + if (!priv) + return; + dev = priv->netdev; + + if (priv->media_connected) + priv->media_connected = false; + +#ifdef CONFIG_DEBUG_FS + mwifiex_dev_debugfs_remove(priv); +#endif + /* Last reference is our one */ + dev_dbg(adapter->dev, "info: %s: refcnt = %d\n", + dev->name, netdev_refcnt_read(dev)); + + if (dev->reg_state == NETREG_REGISTERED) + unregister_netdev(dev); + + /* Clear the priv in adapter */ + priv->netdev = NULL; + if (dev) + free_netdev(dev); + + cancel_work_sync(&priv->cfg_workqueue); + flush_workqueue(priv->workqueue); + destroy_workqueue(priv->workqueue); + wiphy_unregister(priv->wdev->wiphy); + wiphy_free(priv->wdev->wiphy); + kfree(priv->wdev); + + return; +} + +/* + * Sends IOCTL request to shutdown firmware. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int mwifiex_shutdown_fw(struct mwifiex_private *priv, u8 wait_option) +{ + struct mwifiex_wait_queue *wait = NULL; + int status = 0; + + /* Allocate an IOCTL request buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + status = mwifiex_misc_ioctl_init_shutdown(priv->adapter, wait, + MWIFIEX_FUNC_SHUTDOWN); + + status = mwifiex_request_ioctl(priv, wait, status, wait_option); + + kfree(wait); + return status; +} +EXPORT_SYMBOL_GPL(mwifiex_shutdown_fw); + +/* + * This function check if command is pending. + */ +int is_command_pending(struct mwifiex_adapter *adapter) +{ + unsigned long flags; + int is_cmd_pend_q_empty; + + spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); + is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q); + spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); + + return !is_cmd_pend_q_empty; +} + +/* + * This function returns the correct private structure pointer based + * upon the BSS number. + */ +struct mwifiex_private * +mwifiex_bss_index_to_priv(struct mwifiex_adapter *adapter, u8 bss_index) +{ + if (!adapter || (bss_index >= adapter->priv_num)) + return NULL; + return adapter->priv[bss_index]; +} + +/* + * This is the main work queue function. + * + * It handles the main process, which in turn handles the complete + * driver operations. + */ +static void mwifiex_main_work_queue(struct work_struct *work) +{ + struct mwifiex_adapter *adapter = + container_of(work, struct mwifiex_adapter, main_work); + + if (adapter->surprise_removed) + return; + mwifiex_main_process(adapter); +} + +/* + * This function cancels all works in the queue and destroys + * the main workqueue. + */ +static void +mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter) +{ + flush_workqueue(adapter->workqueue); + destroy_workqueue(adapter->workqueue); + adapter->workqueue = NULL; +} + +/* + * This function adds the card. + * + * This function follows the following major steps to set up the device - + * - Initialize software. This includes probing the card, registering + * the interface operations table, and allocating/initializing the + * adapter structure + * - Set up the netlink socket + * - Create and start the main work queue + * - Register the device + * - Initialize firmware and hardware + * - Add logical interfaces + */ +int +mwifiex_add_card(void *card, struct semaphore *sem, + struct mwifiex_if_ops *if_ops) +{ + int status = 0; + int i; + struct mwifiex_adapter *adapter = NULL; + struct mwifiex_drv_mode *drv_mode_info = &mwifiex_drv_mode_tbl[0]; + + if (down_interruptible(sem)) + goto exit_sem_err; + + if (mwifiex_init_sw(card, if_ops, (void **) &adapter)) { + pr_err("%s: software init failed\n", __func__); + goto err_init_sw; + } + + adapter->drv_mode = drv_mode_info; + + adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; + /* PnP and power profile */ + adapter->surprise_removed = false; + init_waitqueue_head(&adapter->init_wait_q); + adapter->is_suspended = false; + adapter->hs_activated = false; + init_waitqueue_head(&adapter->hs_activate_wait_q); + + /* Create workqueue */ + adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE"); + if (!adapter->workqueue) + goto err_kmalloc; + + INIT_WORK(&adapter->main_work, mwifiex_main_work_queue); + + /* Register the device. Fill up the private data structure with relevant + information from the card and request for the required IRQ. */ + if (adapter->if_ops.register_dev(adapter)) { + pr_err("%s: failed to register mwifiex device\n", __func__); + goto err_registerdev; + } + + /* Init FW and HW */ + if (mwifiex_init_hw_fw(adapter)) { + pr_err("%s: firmware init failed\n", __func__); + goto err_init_fw; + } + /* Add interfaces */ + for (i = 0; i < drv_mode_info->intf_num; i++) { + if (!mwifiex_add_interface(adapter, i, + adapter->drv_mode->bss_attr[i].bss_type)) { + status = -1; + break; + } + } + if (status) + goto err_add_intf; + + up(sem); + + return 0; + +err_add_intf: + for (i = 0; i < adapter->priv_num; i++) + mwifiex_remove_interface(adapter, i); +err_init_fw: + /* Unregister device */ + pr_debug("info: %s: unregister device\n", __func__); + adapter->if_ops.unregister_dev(adapter); +err_registerdev: + adapter->surprise_removed = true; + mwifiex_terminate_workqueue(adapter); +err_kmalloc: + if ((adapter->hw_status == MWIFIEX_HW_STATUS_FW_READY) || + (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) { + pr_debug("info: %s: shutdown mwifiex\n", __func__); + adapter->init_wait_q_woken = false; + status = mwifiex_shutdown_drv(adapter); + if (status == -EINPROGRESS) + wait_event_interruptible(adapter->init_wait_q, + adapter->init_wait_q_woken); + } + + mwifiex_free_adapter(adapter); + +err_init_sw: + up(sem); + +exit_sem_err: + return -1; +} +EXPORT_SYMBOL_GPL(mwifiex_add_card); + +/* + * This function removes the card. + * + * This function follows the following major steps to remove the device - + * - Stop data traffic + * - Shutdown firmware + * - Remove the logical interfaces + * - Terminate the work queue + * - Unregister the device + * - Free the adapter structure + */ +int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) +{ + struct mwifiex_private *priv = NULL; + int status; + int i; + + if (down_interruptible(sem)) + goto exit_sem_err; + + if (!adapter) + goto exit_remove; + + adapter->surprise_removed = true; + + /* Stop data */ + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + if (priv) { + if (!netif_queue_stopped(priv->netdev)) + netif_stop_queue(priv->netdev); + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + } + } + + dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n"); + adapter->init_wait_q_woken = false; + status = mwifiex_shutdown_drv(adapter); + if (status == -EINPROGRESS) + wait_event_interruptible(adapter->init_wait_q, + adapter->init_wait_q_woken); + dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n"); + if (atomic_read(&adapter->rx_pending) || + atomic_read(&adapter->tx_pending) || + atomic_read(&adapter->ioctl_pending)) { + dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, " + "ioctl_pending=%d\n", + atomic_read(&adapter->rx_pending), + atomic_read(&adapter->tx_pending), + atomic_read(&adapter->ioctl_pending)); + } + + /* Remove interface */ + for (i = 0; i < adapter->priv_num; i++) + mwifiex_remove_interface(adapter, i); + + mwifiex_terminate_workqueue(adapter); + + /* Unregister device */ + dev_dbg(adapter->dev, "info: unregister device\n"); + adapter->if_ops.unregister_dev(adapter); + /* Free adapter structure */ + dev_dbg(adapter->dev, "info: free adapter\n"); + mwifiex_free_adapter(adapter); + +exit_remove: + up(sem); +exit_sem_err: + return 0; +} +EXPORT_SYMBOL_GPL(mwifiex_remove_card); + +/* + * This function initializes the module. + * + * The debug FS is also initialized if configured. + */ +static int +mwifiex_init_module(void) +{ +#ifdef CONFIG_DEBUG_FS + mwifiex_debugfs_init(); +#endif + return 0; +} + +/* + * This function cleans up the module. + * + * The debug FS is removed if available. + */ +static void +mwifiex_cleanup_module(void) +{ +#ifdef CONFIG_DEBUG_FS + mwifiex_debugfs_remove(); +#endif +} + +module_init(mwifiex_init_module); +module_exit(mwifiex_cleanup_module); + +MODULE_AUTHOR("Marvell International Ltd."); +MODULE_DESCRIPTION("Marvell WiFi-Ex Driver version " VERSION); +MODULE_VERSION(VERSION); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h new file mode 100644 index 000000000000..2b0ad8e3d6e2 --- /dev/null +++ b/drivers/net/wireless/mwifiex/main.h @@ -0,0 +1,1081 @@ +/* + * Marvell Wireless LAN device driver: major data structures and prototypes + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#ifndef _MWIFIEX_MAIN_H_ +#define _MWIFIEX_MAIN_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" + +extern const char driver_version[]; +extern struct mwifiex_adapter *g_adapter; + +enum { + MWIFIEX_NO_WAIT, + MWIFIEX_IOCTL_WAIT, + MWIFIEX_CMD_WAIT, + MWIFIEX_PROC_WAIT, + MWIFIEX_WSTATS_WAIT +}; + +#define DRV_MODE_STA 0x1 +#define DRV_MODE_UAP 0x2 +#define DRV_MODE_UAP_STA 0x3 + +#define SD8787_W0 0x30 +#define SD8787_W1 0x31 +#define SD8787_A0 0x40 +#define SD8787_A1 0x41 + +#define DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin" +#define SD8787_W1_FW_NAME "mrvl/sd8787_uapsta_w1.bin" +#define SD8787_AX_FW_NAME "mrvl/sd8787_uapsta.bin" + +struct mwifiex_drv_mode { + u16 drv_mode; + u16 intf_num; + struct mwifiex_bss_attr *bss_attr; +}; + + +#define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) + +#define MWIFIEX_TIMER_10S 10000 +#define MWIFIEX_TIMER_1S 1000 + +#define NL_MAX_PAYLOAD 1024 +#define NL_MULTICAST_GROUP 1 + +#define MAX_TX_PENDING 60 + +#define HEADER_ALIGNMENT 8 + +#define MWIFIEX_UPLD_SIZE (2312) + +#define MAX_EVENT_SIZE 1024 + +#define ARP_FILTER_MAX_BUF_SIZE 68 + +#define MWIFIEX_KEY_BUFFER_SIZE 16 +#define MWIFIEX_DEFAULT_LISTEN_INTERVAL 10 +#define MWIFIEX_MAX_REGION_CODE 7 + +#define DEFAULT_BCN_AVG_FACTOR 8 +#define DEFAULT_DATA_AVG_FACTOR 8 + +#define FIRST_VALID_CHANNEL 0xff +#define DEFAULT_AD_HOC_CHANNEL 6 +#define DEFAULT_AD_HOC_CHANNEL_A 36 + +#define DEFAULT_BCN_MISS_TIMEOUT 5 + +#define MAX_SCAN_BEACON_BUFFER 8000 + +#define SCAN_BEACON_ENTRY_PAD 6 + +#define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 200 +#define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 200 +#define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 110 + +#define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI))) + +#define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S) + +#define RSN_GTK_OUI_OFFSET 2 + +#define MWIFIEX_OUI_NOT_PRESENT 0 +#define MWIFIEX_OUI_PRESENT 1 + +#define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \ + adapter->event_received || \ + adapter->data_received) + +#define MWIFIEX_TYPE_CMD 1 +#define MWIFIEX_TYPE_DATA 0 +#define MWIFIEX_TYPE_EVENT 3 + +#define DBG_CMD_NUM 5 + +#define MAX_BITMAP_RATES_SIZE 10 + +#define MAX_CHANNEL_BAND_BG 14 + +#define MAX_FREQUENCY_BAND_BG 2484 + +struct mwifiex_dbg { + u32 num_cmd_host_to_card_failure; + u32 num_cmd_sleep_cfm_host_to_card_failure; + u32 num_tx_host_to_card_failure; + u32 num_event_deauth; + u32 num_event_disassoc; + u32 num_event_link_lost; + u32 num_cmd_deauth; + u32 num_cmd_assoc_success; + u32 num_cmd_assoc_failure; + u32 num_tx_timeout; + u32 num_cmd_timeout; + u16 timeout_cmd_id; + u16 timeout_cmd_act; + u16 last_cmd_id[DBG_CMD_NUM]; + u16 last_cmd_act[DBG_CMD_NUM]; + u16 last_cmd_index; + u16 last_cmd_resp_id[DBG_CMD_NUM]; + u16 last_cmd_resp_index; + u16 last_event[DBG_CMD_NUM]; + u16 last_event_index; +}; + +enum MWIFIEX_HARDWARE_STATUS { + MWIFIEX_HW_STATUS_READY, + MWIFIEX_HW_STATUS_INITIALIZING, + MWIFIEX_HW_STATUS_FW_READY, + MWIFIEX_HW_STATUS_INIT_DONE, + MWIFIEX_HW_STATUS_RESET, + MWIFIEX_HW_STATUS_CLOSING, + MWIFIEX_HW_STATUS_NOT_READY +}; + +enum MWIFIEX_802_11_POWER_MODE { + MWIFIEX_802_11_POWER_MODE_CAM, + MWIFIEX_802_11_POWER_MODE_PSP +}; + +struct mwifiex_tx_param { + u32 next_pkt_len; +}; + +enum MWIFIEX_PS_STATE { + PS_STATE_AWAKE, + PS_STATE_PRE_SLEEP, + PS_STATE_SLEEP_CFM, + PS_STATE_SLEEP +}; + +struct mwifiex_add_ba_param { + u32 tx_win_size; + u32 rx_win_size; + u32 timeout; +}; + +struct mwifiex_tx_aggr { + u8 ampdu_user; + u8 ampdu_ap; + u8 amsdu; +}; + +struct mwifiex_ra_list_tbl { + struct list_head list; + struct sk_buff_head skb_head; + u8 ra[ETH_ALEN]; + u32 total_pkts_size; + u32 is_11n_enabled; +}; + +struct mwifiex_tid_tbl { + struct list_head ra_list; + /* spin lock for tid table */ + spinlock_t tid_tbl_lock; + struct mwifiex_ra_list_tbl *ra_list_curr; +}; + +#define WMM_HIGHEST_PRIORITY 7 +#define HIGH_PRIO_TID 7 +#define LOW_PRIO_TID 0 + +struct mwifiex_wmm_desc { + struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID]; + u32 packets_out[MAX_NUM_TID]; + /* spin lock to protect ra_list */ + spinlock_t ra_list_spinlock; + struct mwifiex_wmm_ac_status ac_status[IEEE80211_MAX_QUEUES]; + enum mwifiex_wmm_ac_e ac_down_graded_vals[IEEE80211_MAX_QUEUES]; + u32 drv_pkt_delay_max; + u8 queue_priority[IEEE80211_MAX_QUEUES]; + u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1]; /* UP: 0 to 7 */ + +}; + +struct mwifiex_802_11_security { + u8 wpa_enabled; + u8 wpa2_enabled; + u8 wapi_enabled; + u8 wapi_key_on; + enum MWIFIEX_802_11_WEP_STATUS wep_status; + u32 authentication_mode; + u32 encryption_mode; +}; + +struct ieee_types_header { + u8 element_id; + u8 len; +} __packed; + +struct ieee_obss_scan_param { + u16 obss_scan_passive_dwell; + u16 obss_scan_active_dwell; + u16 bss_chan_width_trigger_scan_int; + u16 obss_scan_passive_total; + u16 obss_scan_active_total; + u16 bss_width_chan_trans_delay; + u16 obss_scan_active_threshold; +} __packed; + +struct ieee_types_obss_scan_param { + struct ieee_types_header ieee_hdr; + struct ieee_obss_scan_param obss_scan; +} __packed; + +#define MWIFIEX_SUPPORTED_RATES 14 + +#define MWIFIEX_SUPPORTED_RATES_EXT 32 + +#define IEEE_MAX_IE_SIZE 256 + +struct ieee_types_vendor_specific { + struct ieee_types_vendor_header vend_hdr; + u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)]; +} __packed; + +struct ieee_types_generic { + struct ieee_types_header ieee_hdr; + u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_header)]; +} __packed; + +struct mwifiex_bssdescriptor { + u8 mac_address[ETH_ALEN]; + struct mwifiex_802_11_ssid ssid; + u32 privacy; + s32 rssi; + u32 channel; + u32 freq; + u16 beacon_period; + u8 erp_flags; + u32 bss_mode; + u8 supported_rates[MWIFIEX_SUPPORTED_RATES]; + u8 data_rates[MWIFIEX_SUPPORTED_RATES]; + /* Network band. + * BAND_B(0x01): 'b' band + * BAND_G(0x02): 'g' band + * BAND_A(0X04): 'a' band + */ + u16 bss_band; + long long network_tsf; + u8 time_stamp[8]; + union ieee_types_phy_param_set phy_param_set; + union ieee_types_ss_param_set ss_param_set; + u16 cap_info_bitmap; + struct ieee_types_wmm_parameter wmm_ie; + u8 disable_11n; + struct ieee80211_ht_cap *bcn_ht_cap; + u16 ht_cap_offset; + struct ieee80211_ht_info *bcn_ht_info; + u16 ht_info_offset; + u8 *bcn_bss_co_2040; + u16 bss_co_2040_offset; + u8 *bcn_ext_cap; + u16 ext_cap_offset; + struct ieee_types_obss_scan_param *bcn_obss_scan; + u16 overlap_bss_offset; + struct ieee_types_vendor_specific *bcn_wpa_ie; + u16 wpa_offset; + struct ieee_types_generic *bcn_rsn_ie; + u16 rsn_offset; + struct ieee_types_generic *bcn_wapi_ie; + u16 wapi_offset; + u8 *beacon_buf; + u32 beacon_buf_size; + u32 beacon_buf_size_max; + +}; + +struct mwifiex_current_bss_params { + struct mwifiex_bssdescriptor bss_descriptor; + u8 wmm_enabled; + u8 wmm_uapsd_enabled; + u8 band; + u32 num_of_rates; + u8 data_rates[MWIFIEX_SUPPORTED_RATES]; +}; + +struct mwifiex_sleep_params { + u16 sp_error; + u16 sp_offset; + u16 sp_stable_time; + u8 sp_cal_control; + u8 sp_ext_sleep_clk; + u16 sp_reserved; +}; + +struct mwifiex_sleep_period { + u16 period; + u16 reserved; +}; + +struct mwifiex_wep_key { + u32 length; + u32 key_index; + u32 key_length; + u8 key_material[MWIFIEX_KEY_BUFFER_SIZE]; +}; + +#define MAX_REGION_CHANNEL_NUM 2 + +struct mwifiex_chan_freq_power { + u16 channel; + u32 freq; + u16 max_tx_power; + u8 unsupported; +}; + +enum state_11d_t { + DISABLE_11D = 0, + ENABLE_11D = 1, +}; + +#define MWIFIEX_MAX_TRIPLET_802_11D 83 + +struct mwifiex_802_11d_domain_reg { + u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; + u8 no_of_triplet; + struct ieee80211_country_ie_triplet + triplet[MWIFIEX_MAX_TRIPLET_802_11D]; +}; + +struct mwifiex_vendor_spec_cfg_ie { + u16 mask; + u16 flag; + u8 ie[MWIFIEX_MAX_VSIE_LEN]; +}; + +struct wps { + u8 session_enable; +}; + +struct mwifiex_adapter; +struct mwifiex_private; + +struct mwifiex_private { + struct mwifiex_adapter *adapter; + u8 bss_index; + u8 bss_type; + u8 bss_role; + u8 bss_priority; + u8 bss_num; + u8 frame_type; + u8 curr_addr[ETH_ALEN]; + u8 media_connected; + u32 num_tx_timeout; + struct net_device *netdev; + struct net_device_stats stats; + u16 curr_pkt_filter; + u32 bss_mode; + u32 pkt_tx_ctrl; + u16 tx_power_level; + u8 max_tx_power_level; + u8 min_tx_power_level; + u8 tx_rate; + u8 tx_htinfo; + u8 rxpd_htinfo; + u8 rxpd_rate; + u16 rate_bitmap; + u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; + u32 data_rate; + u8 is_data_rate_auto; + u16 bcn_avg_factor; + u16 data_avg_factor; + s16 data_rssi_last; + s16 data_nf_last; + s16 data_rssi_avg; + s16 data_nf_avg; + s16 bcn_rssi_last; + s16 bcn_nf_last; + s16 bcn_rssi_avg; + s16 bcn_nf_avg; + struct mwifiex_bssdescriptor *attempted_bss_desc; + struct mwifiex_802_11_ssid prev_ssid; + u8 prev_bssid[ETH_ALEN]; + struct mwifiex_current_bss_params curr_bss_params; + u16 beacon_period; + u16 listen_interval; + u16 atim_window; + u8 adhoc_channel; + u8 adhoc_is_link_sensed; + u8 adhoc_state; + struct mwifiex_802_11_security sec_info; + struct mwifiex_wep_key wep_key[NUM_WEP_KEYS]; + u16 wep_key_curr_index; + u8 wpa_ie[256]; + u8 wpa_ie_len; + u8 wpa_is_gtk_set; + struct host_cmd_ds_802_11_key_material aes_key; + u8 wapi_ie[256]; + u8 wapi_ie_len; + u8 wmm_required; + u8 wmm_enabled; + u8 wmm_qosinfo; + struct mwifiex_wmm_desc wmm; + struct list_head tx_ba_stream_tbl_ptr; + /* spin lock for tx_ba_stream_tbl_ptr queue */ + spinlock_t tx_ba_stream_tbl_lock; + struct mwifiex_tx_aggr aggr_prio_tbl[MAX_NUM_TID]; + struct mwifiex_add_ba_param add_ba_param; + u16 rx_seq[MAX_NUM_TID]; + struct list_head rx_reorder_tbl_ptr; + /* spin lock for rx_reorder_tbl_ptr queue */ + spinlock_t rx_reorder_tbl_lock; + /* spin lock for Rx packets */ + spinlock_t rx_pkt_lock; + +#define MWIFIEX_ASSOC_RSP_BUF_SIZE 500 + u8 assoc_rsp_buf[MWIFIEX_ASSOC_RSP_BUF_SIZE]; + u32 assoc_rsp_size; + +#define MWIFIEX_GENIE_BUF_SIZE 256 + u8 gen_ie_buf[MWIFIEX_GENIE_BUF_SIZE]; + u8 gen_ie_buf_len; + + struct mwifiex_vendor_spec_cfg_ie vs_ie[MWIFIEX_MAX_VSIE_NUM]; + +#define MWIFIEX_ASSOC_TLV_BUF_SIZE 256 + u8 assoc_tlv_buf[MWIFIEX_ASSOC_TLV_BUF_SIZE]; + u8 assoc_tlv_buf_len; + + u8 *curr_bcn_buf; + u32 curr_bcn_size; + /* spin lock for beacon buffer */ + spinlock_t curr_bcn_buf_lock; + u16 ioctl_wait_q_woken; + wait_queue_head_t ioctl_wait_q; + u16 cmd_wait_q_woken; + wait_queue_head_t cmd_wait_q; + struct wireless_dev *wdev; + struct mwifiex_chan_freq_power cfp; + char version_str[128]; +#ifdef CONFIG_DEBUG_FS + struct dentry *dfs_dev_dir; +#endif + u8 nick_name[16]; + struct iw_statistics w_stats; + u16 w_stats_wait_q_woken; + wait_queue_head_t w_stats_wait_q; + u16 current_key_index; + struct semaphore async_sem; + u8 scan_pending_on_block; + u8 report_scan_result; + struct cfg80211_scan_request *scan_request; + int scan_result_status; + bool assoc_request; + u16 assoc_result; + bool ibss_join_request; + u16 ibss_join_result; + bool disconnect; + u8 cfg_bssid[6]; + struct workqueue_struct *workqueue; + struct work_struct cfg_workqueue; + u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; + struct wps wps; + u8 scan_block; +}; + +enum mwifiex_ba_status { + BA_STREAM_NOT_SETUP = 0, + BA_STREAM_SETUP_INPROGRESS, + BA_STREAM_SETUP_COMPLETE +}; + +struct mwifiex_tx_ba_stream_tbl { + struct list_head list; + int tid; + u8 ra[ETH_ALEN]; + enum mwifiex_ba_status ba_status; +}; + +struct mwifiex_rx_reorder_tbl; + +struct reorder_tmr_cnxt { + struct timer_list timer; + struct mwifiex_rx_reorder_tbl *ptr; + struct mwifiex_private *priv; +}; + +struct mwifiex_rx_reorder_tbl { + struct list_head list; + int tid; + u8 ta[ETH_ALEN]; + int start_win; + int win_size; + void **rx_reorder_ptr; + struct reorder_tmr_cnxt timer_context; +}; + +struct mwifiex_bss_prio_node { + struct list_head list; + struct mwifiex_private *priv; +}; + +struct mwifiex_bss_prio_tbl { + struct list_head bss_prio_head; + /* spin lock for bss priority */ + spinlock_t bss_prio_lock; + struct mwifiex_bss_prio_node *bss_prio_cur; +}; + +struct cmd_ctrl_node { + struct list_head list; + struct mwifiex_private *priv; + u32 cmd_oid; + u32 cmd_flag; + struct sk_buff *cmd_skb; + struct sk_buff *resp_skb; + void *data_buf; + void *wq_buf; + struct sk_buff *skb; +}; + +struct mwifiex_if_ops { + int (*init_if) (struct mwifiex_adapter *); + void (*cleanup_if) (struct mwifiex_adapter *); + int (*check_fw_status) (struct mwifiex_adapter *, u32, int *); + int (*prog_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); + int (*register_dev) (struct mwifiex_adapter *); + void (*unregister_dev) (struct mwifiex_adapter *); + int (*enable_int) (struct mwifiex_adapter *); + int (*process_int_status) (struct mwifiex_adapter *); + int (*host_to_card) (struct mwifiex_adapter *, u8, + u8 *payload, u32 pkt_len, + struct mwifiex_tx_param *); + int (*wakeup) (struct mwifiex_adapter *); + int (*wakeup_complete) (struct mwifiex_adapter *); + + void (*update_mp_end_port) (struct mwifiex_adapter *, u16); + void (*cleanup_mpa_buf) (struct mwifiex_adapter *); +}; + +struct mwifiex_adapter { + struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; + u8 priv_num; + struct mwifiex_drv_mode *drv_mode; + const struct firmware *firmware; + struct device *dev; + bool surprise_removed; + u32 fw_release_number; + u32 revision_id; + u16 init_wait_q_woken; + wait_queue_head_t init_wait_q; + void *card; + struct mwifiex_if_ops if_ops; + atomic_t rx_pending; + atomic_t tx_pending; + atomic_t ioctl_pending; + struct workqueue_struct *workqueue; + struct work_struct main_work; + struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM]; + /* spin lock for init/shutdown */ + spinlock_t mwifiex_lock; + /* spin lock for main process */ + spinlock_t main_proc_lock; + u32 mwifiex_processing; + u16 max_tx_buf_size; + u16 tx_buf_size; + u16 curr_tx_buf_size; + u32 ioport; + enum MWIFIEX_HARDWARE_STATUS hw_status; + u16 radio_on; + u16 number_of_antenna; + u32 fw_cap_info; + /* spin lock for interrupt handling */ + spinlock_t int_lock; + u8 int_status; + u32 event_cause; + struct sk_buff *event_skb; + u8 upld_buf[MWIFIEX_UPLD_SIZE]; + u8 data_sent; + u8 cmd_sent; + u8 cmd_resp_received; + u8 event_received; + u8 data_received; + u16 seq_num; + struct cmd_ctrl_node *cmd_pool; + struct cmd_ctrl_node *curr_cmd; + /* spin lock for command */ + spinlock_t mwifiex_cmd_lock; + u32 num_cmd_timeout; + u16 last_init_cmd; + struct timer_list cmd_timer; + struct list_head cmd_free_q; + /* spin lock for cmd_free_q */ + spinlock_t cmd_free_q_lock; + struct list_head cmd_pending_q; + /* spin lock for cmd_pending_q */ + spinlock_t cmd_pending_q_lock; + struct list_head scan_pending_q; + /* spin lock for scan_pending_q */ + spinlock_t scan_pending_q_lock; + u32 scan_processing; + u16 region_code; + struct mwifiex_802_11d_domain_reg domain_reg; + struct mwifiex_bssdescriptor *scan_table; + u32 num_in_scan_table; + u16 scan_probes; + u32 scan_mode; + u16 specific_scan_time; + u16 active_scan_time; + u16 passive_scan_time; + u8 bcn_buf[MAX_SCAN_BEACON_BUFFER]; + u8 *bcn_buf_end; + u8 fw_bands; + u8 adhoc_start_band; + u8 config_bands; + struct mwifiex_chan_scan_param_set *scan_channels; + u8 tx_lock_flag; + struct mwifiex_sleep_params sleep_params; + struct mwifiex_sleep_period sleep_period; + u16 ps_mode; + u32 ps_state; + u8 need_to_wakeup; + u16 multiple_dtim; + u16 local_listen_interval; + u16 null_pkt_interval; + struct sk_buff *sleep_cfm; + u16 bcn_miss_time_out; + u16 adhoc_awake_period; + u8 is_deep_sleep; + u8 delay_null_pkt; + u16 delay_to_ps; + u16 enhanced_ps_mode; + u8 pm_wakeup_card_req; + u16 gen_null_pkt; + u16 pps_uapsd_mode; + u32 pm_wakeup_fw_try; + u8 is_hs_configured; + struct mwifiex_hs_config_param hs_cfg; + u8 hs_activated; + u16 hs_activate_wait_q_woken; + wait_queue_head_t hs_activate_wait_q; + bool is_suspended; + u8 event_body[MAX_EVENT_SIZE]; + u32 hw_dot_11n_dev_cap; + u8 hw_dev_mcs_support; + u32 usr_dot_11n_dev_cap; + u8 usr_dev_mcs_support; + u8 adhoc_11n_enabled; + u8 chan_offset; + struct mwifiex_dbg dbg; + u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE]; + u32 arp_filter_size; +}; + +int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); +void mwifiex_free_lock_list(struct mwifiex_adapter *adapter); + +int mwifiex_init_fw(struct mwifiex_adapter *adapter); + +int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter); + +int mwifiex_shutdown_drv(struct mwifiex_adapter *adapter); + +int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter); + +int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); + +int mwifiex_recv_complete(struct mwifiex_adapter *, + struct sk_buff *skb, + int status); + +int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb); + +int mwifiex_process_event(struct mwifiex_adapter *adapter); + +int mwifiex_ioctl_complete(struct mwifiex_adapter *adapter, + struct mwifiex_wait_queue *ioctl_wq, + int status); + +int mwifiex_prepare_cmd(struct mwifiex_private *priv, + uint16_t cmd_no, + u16 cmd_action, + u32 cmd_oid, + void *wait_queue, void *data_buf); + +void mwifiex_cmd_timeout_func(unsigned long function_context); + +int mwifiex_misc_ioctl_init_shutdown(struct mwifiex_adapter *adapter, + struct mwifiex_wait_queue *wait_queue, + u32 func_init_shutdown); +int mwifiex_get_debug_info(struct mwifiex_private *, + struct mwifiex_debug_info *); + +int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter); +int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter); +void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter); +void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter, + struct mwifiex_wait_queue *ioctl_wq); + +void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, + struct cmd_ctrl_node *cmd_node); + +void mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, + struct cmd_ctrl_node *cmd_node, + u32 addtail); + +int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter); +int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter); +int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, + struct sk_buff *skb); +int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, + struct mwifiex_tx_param *tx_param); +int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags); +int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, + struct sk_buff *skb, int status); +int mwifiex_recv_packet_complete(struct mwifiex_adapter *, + struct sk_buff *skb, int status); +void mwifiex_clean_txrx(struct mwifiex_private *priv); +u8 mwifiex_check_last_packet_indication(struct mwifiex_private *priv); +void mwifiex_check_ps_cond(struct mwifiex_adapter *adapter); +void mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *, u8 *, + u32); +int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, uint16_t ps_bitmap, + void *data_buf); +int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *data_buf); +void mwifiex_process_hs_config(struct mwifiex_adapter *adapter); +void mwifiex_hs_activated_event(struct mwifiex_private *priv, + u8 activated); +int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp); +int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, + struct sk_buff *skb); +int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no, + u16 cmd_action, u32 cmd_oid, + void *data_buf, void *cmd_buf); +int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, + void *cmd_buf, void *ioctl); +int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *, + struct sk_buff *skb); +int mwifiex_process_sta_event(struct mwifiex_private *); +void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); +int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta); +int mwifiex_scan_networks(struct mwifiex_private *priv, void *wait_queue, + u16 action, + const struct mwifiex_user_scan_cfg + *user_scan_in, struct mwifiex_scan_resp *); +int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf); +void mwifiex_queue_scan_cmd(struct mwifiex_private *priv, + struct cmd_ctrl_node *cmd_node); +int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *wait_queue); +s32 mwifiex_find_ssid_in_list(struct mwifiex_private *priv, + struct mwifiex_802_11_ssid *ssid, u8 *bssid, + u32 mode); +s32 mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid, + u32 mode); +int mwifiex_find_best_network(struct mwifiex_private *priv, + struct mwifiex_ssid_bssid *req_ssid_bssid); +s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1, + struct mwifiex_802_11_ssid *ssid2); +int mwifiex_associate(struct mwifiex_private *priv, void *wait_queue, + struct mwifiex_bssdescriptor *bss_desc); +int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, + struct host_cmd_ds_command + *cmd, void *data_buf); +int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *wait_queue); +void mwifiex_reset_connect_state(struct mwifiex_private *priv); +void mwifiex_2040_coex_event(struct mwifiex_private *priv); +u8 mwifiex_band_to_radio_type(u8 band); +int mwifiex_deauthenticate(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait_queue, + u8 *mac); +int mwifiex_adhoc_start(struct mwifiex_private *priv, void *wait_queue, + struct mwifiex_802_11_ssid *adhoc_ssid); +int mwifiex_adhoc_join(struct mwifiex_private *priv, void *wait_queue, + struct mwifiex_bssdescriptor *bss_desc); +int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf); +int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf); +int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *wait_queue); +int mwifiex_cmd_802_11_bg_scan_query(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf); +struct mwifiex_chan_freq_power * + mwifiex_get_cfp_by_band_and_channel_from_cfg80211( + struct mwifiex_private *priv, + u8 band, u16 channel); +struct mwifiex_chan_freq_power *mwifiex_get_cfp_by_band_and_freq_from_cfg80211( + struct mwifiex_private *priv, + u8 band, u32 freq); +u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index, + u8 ht_info); +u32 mwifiex_find_freq_from_band_chan(u8, u8); +int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask, + u8 **buffer); +u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index, + u8 ht_info); +u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, + u8 *rates); +u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates); +u8 mwifiex_data_rate_to_index(struct mwifiex_adapter *adapter, u32 rate); +u8 mwifiex_is_rate_auto(struct mwifiex_private *priv); +int mwifiex_get_rate_index(struct mwifiex_adapter *adapter, + u16 *rateBitmap, int size); +extern u16 region_code_index[MWIFIEX_MAX_REGION_CODE]; +void mwifiex_save_curr_bcn(struct mwifiex_private *priv); +void mwifiex_free_curr_bcn(struct mwifiex_private *priv); +int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd); +int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp); +int is_command_pending(struct mwifiex_adapter *adapter); + +/* + * This function checks if the queuing is RA based or not. + */ +static inline u8 +mwifiex_queuing_ra_based(struct mwifiex_private *priv) +{ + /* + * Currently we assume if we are in Infra, then DA=RA. This might not be + * true in the future + */ + if ((priv->bss_mode == MWIFIEX_BSS_MODE_INFRA) && + (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)) + return false; + + return true; +} + +/* + * This function copies rates. + */ +static inline u32 +mwifiex_copy_rates(u8 *dest, u32 pos, u8 *src, int len) +{ + int i; + + for (i = 0; i < len && src[i]; i++, pos++) { + if (pos >= MWIFIEX_SUPPORTED_RATES) + break; + dest[pos] = src[i]; + } + + return pos; +} + +/* + * This function returns the correct private structure pointer based + * upon the BSS type and BSS number. + */ +static inline struct mwifiex_private * +mwifiex_get_priv_by_id(struct mwifiex_adapter *adapter, + u32 bss_num, u32 bss_type) +{ + int i; + + for (i = 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + if ((adapter->priv[i]->bss_num == bss_num) + && (adapter->priv[i]->bss_type == bss_type)) + break; + } + } + return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); +} + +/* + * This function returns the first available private structure pointer + * based upon the BSS role. + */ +static inline struct mwifiex_private * +mwifiex_get_priv(struct mwifiex_adapter *adapter, + enum mwifiex_bss_role bss_role) +{ + int i; + + for (i = 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) { + if (bss_role == MWIFIEX_BSS_ROLE_ANY || + GET_BSS_ROLE(adapter->priv[i]) == bss_role) + break; + } + } + + return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); +} + +/* + * This function returns the driver private structure of a network device. + */ +static inline struct mwifiex_private * +mwifiex_netdev_get_priv(struct net_device *dev) +{ + return (struct mwifiex_private *) (*(unsigned long *) netdev_priv(dev)); +} + +struct mwifiex_wait_queue *mwifiex_alloc_fill_wait_queue( + struct mwifiex_private *, + u8 wait_option); +struct mwifiex_private *mwifiex_bss_index_to_priv(struct mwifiex_adapter + *adapter, u8 bss_index); +int mwifiex_shutdown_fw(struct mwifiex_private *, u8); + +int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *); +int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *); + +void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version, + int maxlen); +int mwifiex_request_set_mac_address(struct mwifiex_private *priv); +void mwifiex_request_set_multicast_list(struct mwifiex_private *priv, + struct net_device *dev); +int mwifiex_request_ioctl(struct mwifiex_private *priv, + struct mwifiex_wait_queue *req, + int, u8 wait_option); +int mwifiex_disconnect(struct mwifiex_private *, u8, u8 *); +int mwifiex_bss_start(struct mwifiex_private *priv, + u8 wait_option, + struct mwifiex_ssid_bssid *ssid_bssid); +int mwifiex_set_hs_params(struct mwifiex_private *priv, + u16 action, u8 wait_option, + struct mwifiex_ds_hs_cfg *hscfg); +int mwifiex_cancel_hs(struct mwifiex_private *priv, u8 wait_option); +int mwifiex_enable_hs(struct mwifiex_adapter *adapter); +void mwifiex_process_ioctl_resp(struct mwifiex_private *priv, + struct mwifiex_wait_queue *req); +u32 mwifiex_get_mode(struct mwifiex_private *priv, u8 wait_option); +int mwifiex_get_signal_info(struct mwifiex_private *priv, + u8 wait_option, + struct mwifiex_ds_get_signal *signal); +int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, + struct mwifiex_rate_cfg *rate); +int mwifiex_get_channel_list(struct mwifiex_private *priv, + u8 wait_option, + struct mwifiex_chan_list *chanlist); +int mwifiex_get_scan_table(struct mwifiex_private *priv, + u8 wait_option, + struct mwifiex_scan_resp *scanresp); +int mwifiex_get_auth_mode(struct mwifiex_private *priv, + u8 wait_option, u32 *auth_mode); +int mwifiex_get_encrypt_mode(struct mwifiex_private *priv, + u8 wait_option, + u32 *encrypt_mode); +int mwifiex_enable_wep_key(struct mwifiex_private *priv, u8 wait_option); +int mwifiex_find_best_bss(struct mwifiex_private *priv, u8 wait_option, + struct mwifiex_ssid_bssid *ssid_bssid); +int mwifiex_request_scan(struct mwifiex_private *priv, + u8 wait_option, + struct mwifiex_802_11_ssid *req_ssid); +int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, + struct mwifiex_user_scan_cfg *scan_req); +int mwifiex_change_adhoc_chan(struct mwifiex_private *priv, int channel); +int mwifiex_set_radio(struct mwifiex_private *priv, u8 option); + +int mwifiex_drv_get_mode(struct mwifiex_private *priv, u8 wait_option); + +int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel); + +int mwifiex_set_auth(struct mwifiex_private *priv, int encrypt_mode, + int auth_mode, int wpa_enabled); + +int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, + int key_len, u8 key_index, int disable); + +int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len); + +int mwifiex_get_ver_ext(struct mwifiex_private *priv); + +int mwifiex_get_stats_info(struct mwifiex_private *priv, + struct mwifiex_ds_get_stats *log); + +int mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type, + u32 reg_offset, u32 reg_value); + +int mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type, + u32 reg_offset, u32 *value); + +int mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, + u8 *value); + +int mwifiex_set_11n_httx_cfg(struct mwifiex_private *priv, int data); + +int mwifiex_get_11n_httx_cfg(struct mwifiex_private *priv, int *data); + +int mwifiex_set_tx_rate_cfg(struct mwifiex_private *priv, int tx_rate_index); + +int mwifiex_get_tx_rate_cfg(struct mwifiex_private *priv, int *tx_rate_index); + +int mwifiex_drv_set_power(struct mwifiex_private *priv, bool power_on); + +int mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, + char *version, int max_len); + +int mwifiex_set_tx_power(struct mwifiex_private *priv, int type, int dbm); + +int mwifiex_main_process(struct mwifiex_adapter *); + +int mwifiex_bss_ioctl_mode(struct mwifiex_private *, + struct mwifiex_wait_queue *, + u16 action, int *mode); +int mwifiex_bss_ioctl_channel(struct mwifiex_private *, + u16 action, + struct mwifiex_chan_freq_power *cfp); +int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *, + struct mwifiex_wait_queue *, + struct mwifiex_ssid_bssid *); +int mwifiex_radio_ioctl_band_cfg(struct mwifiex_private *, + u16 action, + struct mwifiex_ds_band_cfg *); +int mwifiex_snmp_mib_ioctl(struct mwifiex_private *, + struct mwifiex_wait_queue *, + u32 cmd_oid, u16 action, u32 *value); +int mwifiex_get_bss_info(struct mwifiex_private *, + struct mwifiex_bss_info *); + +#ifdef CONFIG_DEBUG_FS +void mwifiex_debugfs_init(void); +void mwifiex_debugfs_remove(void); + +void mwifiex_dev_debugfs_init(struct mwifiex_private *priv); +void mwifiex_dev_debugfs_remove(struct mwifiex_private *priv); +#endif +#endif /* !_MWIFIEX_MAIN_H_ */ diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c new file mode 100644 index 000000000000..1152beb930ab --- /dev/null +++ b/drivers/net/wireless/mwifiex/scan.c @@ -0,0 +1,3098 @@ +/* + * Marvell Wireless LAN device driver: scan ioctl and command handling + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "11n.h" +#include "cfg80211.h" + +/* The maximum number of channels the firmware can scan per command */ +#define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN 14 + +#define MWIFIEX_CHANNELS_PER_SCAN_CMD 4 + +/* Memory needed to store a max sized Channel List TLV for a firmware scan */ +#define CHAN_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_header) \ + + (MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN \ + *sizeof(struct mwifiex_chan_scan_param_set))) + +/* Memory needed to store supported rate */ +#define RATE_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_rates_param_set) \ + + HOSTCMD_SUPPORTED_RATES) + +/* Memory needed to store a max number/size WildCard SSID TLV for a firmware + scan */ +#define WILDCARD_SSID_TLV_MAX_SIZE \ + (MWIFIEX_MAX_SSID_LIST_LENGTH * \ + (sizeof(struct mwifiex_ie_types_wildcard_ssid_params) \ + + IEEE80211_MAX_SSID_LEN)) + +/* Maximum memory needed for a mwifiex_scan_cmd_config with all TLVs at max */ +#define MAX_SCAN_CFG_ALLOC (sizeof(struct mwifiex_scan_cmd_config) \ + + sizeof(struct mwifiex_ie_types_num_probes) \ + + sizeof(struct mwifiex_ie_types_htcap) \ + + CHAN_TLV_MAX_SIZE \ + + RATE_TLV_MAX_SIZE \ + + WILDCARD_SSID_TLV_MAX_SIZE) + + +union mwifiex_scan_cmd_config_tlv { + /* Scan configuration (variable length) */ + struct mwifiex_scan_cmd_config config; + /* Max allocated block */ + u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC]; +}; + +enum cipher_suite { + CIPHER_SUITE_TKIP, + CIPHER_SUITE_CCMP, + CIPHER_SUITE_MAX +}; +static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = { + { 0x00, 0x50, 0xf2, 0x02 }, /* TKIP */ + { 0x00, 0x50, 0xf2, 0x04 }, /* AES */ +}; +static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = { + { 0x00, 0x0f, 0xac, 0x02 }, /* TKIP */ + { 0x00, 0x0f, 0xac, 0x04 }, /* AES */ +}; + +/* + * This function parses a given IE for a given OUI. + * + * This is used to parse a WPA/RSN IE to find if it has + * a given oui in PTK. + */ +static u8 +mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui) +{ + u8 count; + + count = iebody->ptk_cnt[0]; + + /* There could be multiple OUIs for PTK hence + 1) Take the length. + 2) Check all the OUIs for AES. + 3) If one of them is AES then pass success. */ + while (count) { + if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body))) + return MWIFIEX_OUI_PRESENT; + + --count; + if (count) + iebody = (struct ie_body *) ((u8 *) iebody + + sizeof(iebody->ptk_body)); + } + + pr_debug("info: %s: OUI is not found in PTK\n", __func__); + return MWIFIEX_OUI_NOT_PRESENT; +} + +/* + * This function checks if a given OUI is present in a RSN IE. + * + * The function first checks if a RSN IE is present or not in the + * BSS descriptor. It tries to locate the OUI only if such an IE is + * present. + */ +static u8 +mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) +{ + u8 *oui = NULL; + struct ie_body *iebody = NULL; + u8 ret = MWIFIEX_OUI_NOT_PRESENT; + + if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)). + ieee_hdr.element_id == WLAN_EID_RSN))) { + iebody = (struct ie_body *) + (((u8 *) bss_desc->bcn_rsn_ie->data) + + RSN_GTK_OUI_OFFSET); + oui = &mwifiex_rsn_oui[cipher][0]; + ret = mwifiex_search_oui_in_ie(iebody, oui); + if (ret) + return ret; + } + return ret; +} + +/* + * This function checks if a given OUI is present in a WPA IE. + * + * The function first checks if a WPA IE is present or not in the + * BSS descriptor. It tries to locate the OUI only if such an IE is + * present. + */ +static u8 +mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) +{ + u8 *oui = NULL; + struct ie_body *iebody = NULL; + u8 ret = MWIFIEX_OUI_NOT_PRESENT; + + if (((bss_desc->bcn_wpa_ie) && ((*(bss_desc->bcn_wpa_ie)). + vend_hdr.element_id == WLAN_EID_WPA))) { + iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data; + oui = &mwifiex_wpa_oui[cipher][0]; + ret = mwifiex_search_oui_in_ie(iebody, oui); + if (ret) + return ret; + } + return ret; +} + +/* + * This function compares two SSIDs and checks if they match. + */ +s32 +mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1, + struct mwifiex_802_11_ssid *ssid2) +{ + if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len)) + return -1; + return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len); +} + +/* + * Sends IOCTL request to get the best BSS. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int mwifiex_find_best_bss(struct mwifiex_private *priv, + u8 wait_option, struct mwifiex_ssid_bssid *ssid_bssid) +{ + struct mwifiex_wait_queue *wait = NULL; + struct mwifiex_ssid_bssid tmp_ssid_bssid; + int ret = 0; + u8 *mac = NULL; + + if (!ssid_bssid) + return -1; + + /* Allocate wait request buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + memcpy(&tmp_ssid_bssid, ssid_bssid, + sizeof(struct mwifiex_ssid_bssid)); + ret = mwifiex_bss_ioctl_find_bss(priv, wait, &tmp_ssid_bssid); + + if (!ret) { + memcpy(ssid_bssid, &tmp_ssid_bssid, + sizeof(struct mwifiex_ssid_bssid)); + mac = (u8 *) &ssid_bssid->bssid; + dev_dbg(priv->adapter->dev, "cmd: found network: ssid=%s," + " %pM\n", ssid_bssid->ssid.ssid, mac); + } + + kfree(wait); + return ret; +} + +/* + * Sends IOCTL request to start a scan with user configurations. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + * + * Upon completion, it also generates a wireless event to notify + * applications. + */ +int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, + struct mwifiex_user_scan_cfg *scan_req) +{ + struct mwifiex_wait_queue *wait = NULL; + int status = 0; + u8 wait_option = MWIFIEX_IOCTL_WAIT; + + /* Allocate an IOCTL request buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_SET, + scan_req, NULL); + + status = mwifiex_request_ioctl(priv, wait, status, wait_option); + + if (wait && (status != -EINPROGRESS)) + kfree(wait); + return status; +} + +/* + * This function checks if wapi is enabled in driver and scanned network is + * compatible with it. + */ +static bool +mwifiex_is_network_compatible_for_wapi(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc) +{ + if (priv->sec_info.wapi_enabled && + (bss_desc->bcn_wapi_ie && + ((*(bss_desc->bcn_wapi_ie)).ieee_hdr.element_id == + WLAN_EID_BSS_AC_ACCESS_DELAY))) { + return true; + } + return false; +} + +/* + * This function checks if driver is configured with no security mode and + * scanned network is compatible with it. + */ +static bool +mwifiex_is_network_compatible_for_no_sec(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc) +{ + if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED + && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled + && ((!bss_desc->bcn_wpa_ie) || + ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != + WLAN_EID_WPA)) + && ((!bss_desc->bcn_rsn_ie) || + ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != + WLAN_EID_RSN)) + && priv->sec_info.encryption_mode == + MWIFIEX_ENCRYPTION_MODE_NONE && !bss_desc->privacy) { + return true; + } + return false; +} + +/* + * This function checks if static WEP is enabled in driver and scanned network + * is compatible with it. + */ +static bool +mwifiex_is_network_compatible_for_static_wep(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc) +{ + if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED + && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled + && bss_desc->privacy) { + return true; + } + return false; +} + +/* + * This function checks if wpa is enabled in driver and scanned network is + * compatible with it. + */ +static bool +mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc, + int index) +{ + if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED + && priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled + && ((bss_desc->bcn_wpa_ie) && ((*(bss_desc->bcn_wpa_ie)).vend_hdr. + element_id == WLAN_EID_WPA)) + /* + * Privacy bit may NOT be set in some APs like + * LinkSys WRT54G && bss_desc->privacy + */ + ) { + dev_dbg(priv->adapter->dev, "info: %s: WPA: index=%d" + " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " + "EncMode=%#x privacy=%#x\n", __func__, index, + (bss_desc->bcn_wpa_ie) ? + (*(bss_desc->bcn_wpa_ie)). + vend_hdr.element_id : 0, + (bss_desc->bcn_rsn_ie) ? + (*(bss_desc->bcn_rsn_ie)). + ieee_hdr.element_id : 0, + (priv->sec_info.wep_status == + MWIFIEX_802_11_WEP_ENABLED) ? "e" : "d", + (priv->sec_info.wpa_enabled) ? "e" : "d", + (priv->sec_info.wpa2_enabled) ? "e" : "d", + priv->sec_info.encryption_mode, + bss_desc->privacy); + return true; + } + return false; +} + +/* + * This function checks if wpa2 is enabled in driver and scanned network is + * compatible with it. + */ +static bool +mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc, + int index) +{ + if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED + && !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled + && ((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)).ieee_hdr. + element_id == WLAN_EID_RSN)) + /* + * Privacy bit may NOT be set in some APs like + * LinkSys WRT54G && bss_desc->privacy + */ + ) { + dev_dbg(priv->adapter->dev, "info: %s: WPA2: index=%d" + " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " + "EncMode=%#x privacy=%#x\n", __func__, index, + (bss_desc->bcn_wpa_ie) ? + (*(bss_desc->bcn_wpa_ie)). + vend_hdr.element_id : 0, + (bss_desc->bcn_rsn_ie) ? + (*(bss_desc->bcn_rsn_ie)). + ieee_hdr.element_id : 0, + (priv->sec_info.wep_status == + MWIFIEX_802_11_WEP_ENABLED) ? "e" : "d", + (priv->sec_info.wpa_enabled) ? "e" : "d", + (priv->sec_info.wpa2_enabled) ? "e" : "d", + priv->sec_info.encryption_mode, + bss_desc->privacy); + return true; + } + return false; +} + +/* + * This function checks if adhoc AES is enabled in driver and scanned network is + * compatible with it. + */ +static bool +mwifiex_is_network_compatible_for_adhoc_aes(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc) +{ + if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED + && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled + && ((!bss_desc->bcn_wpa_ie) || ((*(bss_desc->bcn_wpa_ie)).vend_hdr. + element_id != WLAN_EID_WPA)) + && ((!bss_desc->bcn_rsn_ie) || ((*(bss_desc->bcn_rsn_ie)).ieee_hdr. + element_id != WLAN_EID_RSN)) + && priv->sec_info.encryption_mode == + MWIFIEX_ENCRYPTION_MODE_NONE && bss_desc->privacy) { + return true; + } + return false; +} + +/* + * This function checks if dynamic WEP is enabled in driver and scanned network + * is compatible with it. + */ +static bool +mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc, + int index) +{ + if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED + && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled + && ((!bss_desc->bcn_wpa_ie) || ((*(bss_desc->bcn_wpa_ie)).vend_hdr. + element_id != WLAN_EID_WPA)) + && ((!bss_desc->bcn_rsn_ie) || ((*(bss_desc->bcn_rsn_ie)).ieee_hdr. + element_id != WLAN_EID_RSN)) + && priv->sec_info.encryption_mode != + MWIFIEX_ENCRYPTION_MODE_NONE && bss_desc->privacy) { + dev_dbg(priv->adapter->dev, "info: %s: dynamic " + "WEP: index=%d wpa_ie=%#x wpa2_ie=%#x " + "EncMode=%#x privacy=%#x\n", + __func__, index, + (bss_desc->bcn_wpa_ie) ? + (*(bss_desc->bcn_wpa_ie)). + vend_hdr.element_id : 0, + (bss_desc->bcn_rsn_ie) ? + (*(bss_desc->bcn_rsn_ie)). + ieee_hdr.element_id : 0, + priv->sec_info.encryption_mode, + bss_desc->privacy); + return true; + } + return false; +} + +/* + * This function checks if a scanned network is compatible with the driver + * settings. + * + * WEP WPA WPA2 ad-hoc encrypt Network + * enabled enabled enabled AES mode Privacy WPA WPA2 Compatible + * 0 0 0 0 NONE 0 0 0 yes No security + * 0 1 0 0 x 1x 1 x yes WPA (disable + * HT if no AES) + * 0 0 1 0 x 1x x 1 yes WPA2 (disable + * HT if no AES) + * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES + * 1 0 0 0 NONE 1 0 0 yes Static WEP + * (disable HT) + * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP + * + * Compatibility is not matched while roaming, except for mode. + */ +static s32 +mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_bssdescriptor *bss_desc; + + bss_desc = &adapter->scan_table[index]; + bss_desc->disable_11n = false; + + /* Don't check for compatibility if roaming */ + if (priv->media_connected && (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA) + && (bss_desc->bss_mode == MWIFIEX_BSS_MODE_INFRA)) + return index; + + if (priv->wps.session_enable) { + dev_dbg(adapter->dev, + "info: return success directly in WPS period\n"); + return index; + } + + if (mwifiex_is_network_compatible_for_wapi(priv, bss_desc)) { + dev_dbg(adapter->dev, "info: return success for WAPI AP\n"); + return index; + } + + if (bss_desc->bss_mode == mode) { + if (mwifiex_is_network_compatible_for_no_sec(priv, bss_desc)) { + /* No security */ + return index; + } else if (mwifiex_is_network_compatible_for_static_wep(priv, + bss_desc)) { + /* Static WEP enabled */ + dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n"); + bss_desc->disable_11n = true; + return index; + } else if (mwifiex_is_network_compatible_for_wpa(priv, bss_desc, + index)) { + /* WPA enabled */ + if (((priv->adapter->config_bands & BAND_GN + || priv->adapter->config_bands & BAND_AN) + && bss_desc->bcn_ht_cap) + && !mwifiex_is_wpa_oui_present(bss_desc, + CIPHER_SUITE_CCMP)) { + + if (mwifiex_is_wpa_oui_present(bss_desc, + CIPHER_SUITE_TKIP)) { + dev_dbg(adapter->dev, + "info: Disable 11n if AES " + "is not supported by AP\n"); + bss_desc->disable_11n = true; + } else { + return -1; + } + } + return index; + } else if (mwifiex_is_network_compatible_for_wpa2(priv, + bss_desc, index)) { + /* WPA2 enabled */ + if (((priv->adapter->config_bands & BAND_GN + || priv->adapter->config_bands & BAND_AN) + && bss_desc->bcn_ht_cap) + && !mwifiex_is_rsn_oui_present(bss_desc, + CIPHER_SUITE_CCMP)) { + + if (mwifiex_is_rsn_oui_present(bss_desc, + CIPHER_SUITE_TKIP)) { + dev_dbg(adapter->dev, + "info: Disable 11n if AES " + "is not supported by AP\n"); + bss_desc->disable_11n = true; + } else { + return -1; + } + } + return index; + } else if (mwifiex_is_network_compatible_for_adhoc_aes(priv, + bss_desc)) { + /* Ad-hoc AES enabled */ + return index; + } else if (mwifiex_is_network_compatible_for_dynamic_wep(priv, + bss_desc, index)) { + /* Dynamic WEP enabled */ + return index; + } + + /* Security doesn't match */ + dev_dbg(adapter->dev, "info: %s: failed: index=%d " + "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode" + "=%#x privacy=%#x\n", + __func__, index, + (bss_desc->bcn_wpa_ie) ? + (*(bss_desc->bcn_wpa_ie)).vend_hdr. + element_id : 0, + (bss_desc->bcn_rsn_ie) ? + (*(bss_desc->bcn_rsn_ie)).ieee_hdr. + element_id : 0, + (priv->sec_info.wep_status == + MWIFIEX_802_11_WEP_ENABLED) ? "e" : "d", + (priv->sec_info.wpa_enabled) ? "e" : "d", + (priv->sec_info.wpa2_enabled) ? "e" : "d", + priv->sec_info.encryption_mode, bss_desc->privacy); + return -1; + } + + /* Mode doesn't match */ + return -1; +} + +/* + * This function finds the best SSID in the scan list. + * + * It searches the scan table for the best SSID that also matches the current + * adapter network preference (mode, security etc.). + */ +static s32 +mwifiex_find_best_network_in_list(struct mwifiex_private *priv) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u32 mode = priv->bss_mode; + s32 best_net = -1; + s32 best_rssi = 0; + u32 i; + + dev_dbg(adapter->dev, "info: num of BSSIDs = %d\n", + adapter->num_in_scan_table); + + for (i = 0; i < adapter->num_in_scan_table; i++) { + switch (mode) { + case MWIFIEX_BSS_MODE_INFRA: + case MWIFIEX_BSS_MODE_IBSS: + if (mwifiex_is_network_compatible(priv, i, mode) >= 0) { + if (SCAN_RSSI(adapter->scan_table[i].rssi) > + best_rssi) { + best_rssi = SCAN_RSSI(adapter-> + scan_table[i].rssi); + best_net = i; + } + } + break; + case MWIFIEX_BSS_MODE_AUTO: + default: + if (SCAN_RSSI(adapter->scan_table[i].rssi) > + best_rssi) { + best_rssi = SCAN_RSSI(adapter->scan_table[i]. + rssi); + best_net = i; + } + break; + } + } + + return best_net; +} + +/* + * This function creates a channel list for the driver to scan, based + * on region/band information. + * + * This routine is used for any scan that is not provided with a + * specific channel list to scan. + */ +static void +mwifiex_scan_create_channel_list(struct mwifiex_private *priv, + const struct mwifiex_user_scan_cfg + *user_scan_in, + struct mwifiex_chan_scan_param_set + *scan_chan_list, + u8 filtered_scan) +{ + enum ieee80211_band band; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + struct mwifiex_adapter *adapter = priv->adapter; + int chan_idx = 0, i; + u8 scan_type; + + for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) { + + if (!priv->wdev->wiphy->bands[band]) + continue; + + sband = priv->wdev->wiphy->bands[band]; + + for (i = 0; (i < sband->n_channels) ; i++, chan_idx++) { + ch = &sband->channels[i]; + if (ch->flags & IEEE80211_CHAN_DISABLED) + continue; + scan_chan_list[chan_idx].radio_type = band; + scan_type = ch->flags & IEEE80211_CHAN_PASSIVE_SCAN; + if (user_scan_in && + user_scan_in->chan_list[0].scan_time) + scan_chan_list[chan_idx].max_scan_time = + cpu_to_le16((u16) user_scan_in-> + chan_list[0].scan_time); + else if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) + scan_chan_list[chan_idx].max_scan_time = + cpu_to_le16(adapter->passive_scan_time); + else + scan_chan_list[chan_idx].max_scan_time = + cpu_to_le16(adapter->active_scan_time); + if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) + scan_chan_list[chan_idx].chan_scan_mode_bitmap + |= MWIFIEX_PASSIVE_SCAN; + else + scan_chan_list[chan_idx].chan_scan_mode_bitmap + &= ~MWIFIEX_PASSIVE_SCAN; + scan_chan_list[chan_idx].chan_number = + (u32) ch->hw_value; + if (filtered_scan) { + scan_chan_list[chan_idx].max_scan_time = + cpu_to_le16(adapter->specific_scan_time); + scan_chan_list[chan_idx].chan_scan_mode_bitmap + |= MWIFIEX_DISABLE_CHAN_FILT; + } + } + + } +} + +/* + * This function constructs and sends multiple scan config commands to + * the firmware. + * + * Previous routines in the code flow have created a scan command configuration + * with any requested TLVs. This function splits the channel TLV into maximum + * channels supported per scan lists and sends the portion of the channel TLV, + * along with the other TLVs, to the firmware. + */ +static int +mwifiex_scan_channel_list(struct mwifiex_private *priv, void *wait_buf, + u32 max_chan_per_scan, u8 filtered_scan, + struct mwifiex_scan_cmd_config *scan_cfg_out, + struct mwifiex_ie_types_chan_list_param_set + *chan_tlv_out, + struct mwifiex_chan_scan_param_set *scan_chan_list) +{ + int ret = 0; + struct mwifiex_chan_scan_param_set *tmp_chan_list; + struct mwifiex_chan_scan_param_set *start_chan; + + u32 tlv_idx; + u32 total_scan_time; + u32 done_early; + + if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) { + dev_dbg(priv->adapter->dev, + "info: Scan: Null detect: %p, %p, %p\n", + scan_cfg_out, chan_tlv_out, scan_chan_list); + return -1; + } + + chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); + + /* Set the temp channel struct pointer to the start of the desired + list */ + tmp_chan_list = scan_chan_list; + + /* Loop through the desired channel list, sending a new firmware scan + commands for each max_chan_per_scan channels (or for 1,6,11 + individually if configured accordingly) */ + while (tmp_chan_list->chan_number) { + + tlv_idx = 0; + total_scan_time = 0; + chan_tlv_out->header.len = 0; + start_chan = tmp_chan_list; + done_early = false; + + /* + * Construct the Channel TLV for the scan command. Continue to + * insert channel TLVs until: + * - the tlv_idx hits the maximum configured per scan command + * - the next channel to insert is 0 (end of desired channel + * list) + * - done_early is set (controlling individual scanning of + * 1,6,11) + */ + while (tlv_idx < max_chan_per_scan + && tmp_chan_list->chan_number && !done_early) { + + dev_dbg(priv->adapter->dev, + "info: Scan: Chan(%3d), Radio(%d)," + " Mode(%d, %d), Dur(%d)\n", + tmp_chan_list->chan_number, + tmp_chan_list->radio_type, + tmp_chan_list->chan_scan_mode_bitmap + & MWIFIEX_PASSIVE_SCAN, + (tmp_chan_list->chan_scan_mode_bitmap + & MWIFIEX_DISABLE_CHAN_FILT) >> 1, + le16_to_cpu(tmp_chan_list->max_scan_time)); + + /* Copy the current channel TLV to the command being + prepared */ + memcpy(chan_tlv_out->chan_scan_param + tlv_idx, + tmp_chan_list, + sizeof(chan_tlv_out->chan_scan_param)); + + /* Increment the TLV header length by the size + appended */ + chan_tlv_out->header.len = + cpu_to_le16(le16_to_cpu(chan_tlv_out->header.len) + + (sizeof(chan_tlv_out->chan_scan_param))); + + /* + * The tlv buffer length is set to the number of bytes + * of the between the channel tlv pointer and the start + * of the tlv buffer. This compensates for any TLVs + * that were appended before the channel list. + */ + scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out - + scan_cfg_out->tlv_buf); + + /* Add the size of the channel tlv header and the data + length */ + scan_cfg_out->tlv_buf_len += + (sizeof(chan_tlv_out->header) + + le16_to_cpu(chan_tlv_out->header.len)); + + /* Increment the index to the channel tlv we are + constructing */ + tlv_idx++; + + /* Count the total scan time per command */ + total_scan_time += + le16_to_cpu(tmp_chan_list->max_scan_time); + + done_early = false; + + /* Stop the loop if the *current* channel is in the + 1,6,11 set and we are not filtering on a BSSID + or SSID. */ + if (!filtered_scan && (tmp_chan_list->chan_number == 1 + || tmp_chan_list->chan_number == 6 + || tmp_chan_list->chan_number == 11)) + done_early = true; + + /* Increment the tmp pointer to the next channel to + be scanned */ + tmp_chan_list++; + + /* Stop the loop if the *next* channel is in the 1,6,11 + set. This will cause it to be the only channel + scanned on the next interation */ + if (!filtered_scan && (tmp_chan_list->chan_number == 1 + || tmp_chan_list->chan_number == 6 + || tmp_chan_list->chan_number == 11)) + done_early = true; + } + + /* The total scan time should be less than scan command timeout + value */ + if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) { + dev_err(priv->adapter->dev, "total scan time %dms" + " is over limit (%dms), scan skipped\n", + total_scan_time, MWIFIEX_MAX_TOTAL_SCAN_TIME); + ret = -1; + break; + } + + priv->adapter->scan_channels = start_chan; + + /* Send the scan command to the firmware with the specified + cfg */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_SCAN, + HostCmd_ACT_GEN_SET, + 0, wait_buf, scan_cfg_out); + if (ret) + break; + } + + if (ret) + return -1; + + return 0; +} + +/* + * This function constructs a scan command configuration structure to use + * in scan commands. + * + * Application layer or other functions can invoke network scanning + * with a scan configuration supplied in a user scan configuration structure. + * This structure is used as the basis of one or many scan command configuration + * commands that are sent to the command processing module and eventually to the + * firmware. + * + * This function creates a scan command configuration structure based on the + * following user supplied parameters (if present): + * - SSID filter + * - BSSID filter + * - Number of Probes to be sent + * - Channel list + * + * If the SSID or BSSID filter is not present, the filter is disabled/cleared. + * If the number of probes is not set, adapter default setting is used. + */ +static void +mwifiex_scan_setup_scan_config(struct mwifiex_private *priv, + const struct mwifiex_user_scan_cfg *user_scan_in, + struct mwifiex_scan_cmd_config *scan_cfg_out, + struct mwifiex_ie_types_chan_list_param_set + **chan_list_out, + struct mwifiex_chan_scan_param_set + *scan_chan_list, + u8 *max_chan_per_scan, u8 *filtered_scan, + u8 *scan_current_only) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_ie_types_num_probes *num_probes_tlv; + struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; + struct mwifiex_ie_types_rates_param_set *rates_tlv; + const u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; + u8 *tlv_pos; + u32 num_probes; + u32 ssid_len; + u32 chan_idx; + u32 scan_type; + u16 scan_dur; + u8 channel; + u8 radio_type; + u32 ssid_idx; + u8 ssid_filter; + u8 rates[MWIFIEX_SUPPORTED_RATES]; + u32 rates_size; + struct mwifiex_ie_types_htcap *ht_cap; + + /* The tlv_buf_len is calculated for each scan command. The TLVs added + in this routine will be preserved since the routine that sends the + command will append channelTLVs at *chan_list_out. The difference + between the *chan_list_out and the tlv_buf start will be used to + calculate the size of anything we add in this routine. */ + scan_cfg_out->tlv_buf_len = 0; + + /* Running tlv pointer. Assigned to chan_list_out at end of function + so later routines know where channels can be added to the command + buf */ + tlv_pos = scan_cfg_out->tlv_buf; + + /* Initialize the scan as un-filtered; the flag is later set to TRUE + below if a SSID or BSSID filter is sent in the command */ + *filtered_scan = false; + + /* Initialize the scan as not being only on the current channel. If + the channel list is customized, only contains one channel, and is + the active channel, this is set true and data flow is not halted. */ + *scan_current_only = false; + + if (user_scan_in) { + + /* Default the ssid_filter flag to TRUE, set false under + certain wildcard conditions and qualified by the existence + of an SSID list before marking the scan as filtered */ + ssid_filter = true; + + /* Set the BSS type scan filter, use Adapter setting if + unset */ + scan_cfg_out->bss_mode = + (user_scan_in->bss_mode ? (u8) user_scan_in-> + bss_mode : (u8) adapter->scan_mode); + + /* Set the number of probes to send, use Adapter setting + if unset */ + num_probes = + (user_scan_in->num_probes ? user_scan_in-> + num_probes : adapter->scan_probes); + + /* + * Set the BSSID filter to the incoming configuration, + * if non-zero. If not set, it will remain disabled + * (all zeros). + */ + memcpy(scan_cfg_out->specific_bssid, + user_scan_in->specific_bssid, + sizeof(scan_cfg_out->specific_bssid)); + + for (ssid_idx = 0; + ((ssid_idx < ARRAY_SIZE(user_scan_in->ssid_list)) + && (*user_scan_in->ssid_list[ssid_idx].ssid + || user_scan_in->ssid_list[ssid_idx].max_len)); + ssid_idx++) { + + ssid_len = strlen(user_scan_in->ssid_list[ssid_idx]. + ssid) + 1; + + wildcard_ssid_tlv = + (struct mwifiex_ie_types_wildcard_ssid_params *) + tlv_pos; + wildcard_ssid_tlv->header.type = + cpu_to_le16(TLV_TYPE_WILDCARDSSID); + wildcard_ssid_tlv->header.len = cpu_to_le16( + (u16) (ssid_len + sizeof(wildcard_ssid_tlv-> + max_ssid_length))); + wildcard_ssid_tlv->max_ssid_length = + user_scan_in->ssid_list[ssid_idx].max_len; + + memcpy(wildcard_ssid_tlv->ssid, + user_scan_in->ssid_list[ssid_idx].ssid, + ssid_len); + + tlv_pos += (sizeof(wildcard_ssid_tlv->header) + + le16_to_cpu(wildcard_ssid_tlv->header.len)); + + dev_dbg(adapter->dev, "info: scan: ssid_list[%d]: %s, %d\n", + ssid_idx, wildcard_ssid_tlv->ssid, + wildcard_ssid_tlv->max_ssid_length); + + /* Empty wildcard ssid with a maxlen will match many or + potentially all SSIDs (maxlen == 32), therefore do + not treat the scan as + filtered. */ + if (!ssid_len && wildcard_ssid_tlv->max_ssid_length) + ssid_filter = false; + + } + + /* + * The default number of channels sent in the command is low to + * ensure the response buffer from the firmware does not + * truncate scan results. That is not an issue with an SSID + * or BSSID filter applied to the scan results in the firmware. + */ + if ((ssid_idx && ssid_filter) + || memcmp(scan_cfg_out->specific_bssid, &zero_mac, + sizeof(zero_mac))) + *filtered_scan = true; + } else { + scan_cfg_out->bss_mode = (u8) adapter->scan_mode; + num_probes = adapter->scan_probes; + } + + /* + * If a specific BSSID or SSID is used, the number of channels in the + * scan command will be increased to the absolute maximum. + */ + if (*filtered_scan) + *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN; + else + *max_chan_per_scan = MWIFIEX_CHANNELS_PER_SCAN_CMD; + + /* If the input config or adapter has the number of Probes set, + add tlv */ + if (num_probes) { + + dev_dbg(adapter->dev, "info: scan: num_probes = %d\n", + num_probes); + + num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos; + num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES); + num_probes_tlv->header.len = + cpu_to_le16(sizeof(num_probes_tlv->num_probes)); + num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes); + + tlv_pos += sizeof(num_probes_tlv->header) + + le16_to_cpu(num_probes_tlv->header.len); + + } + + /* Append rates tlv */ + memset(rates, 0, sizeof(rates)); + + rates_size = mwifiex_get_supported_rates(priv, rates); + + rates_tlv = (struct mwifiex_ie_types_rates_param_set *) tlv_pos; + rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES); + rates_tlv->header.len = cpu_to_le16((u16) rates_size); + memcpy(rates_tlv->rates, rates, rates_size); + tlv_pos += sizeof(rates_tlv->header) + rates_size; + + dev_dbg(adapter->dev, "info: SCAN_CMD: Rates size = %d\n", rates_size); + + if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) + && (priv->adapter->config_bands & BAND_GN + || priv->adapter->config_bands & BAND_AN)) { + ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos; + memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); + ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); + ht_cap->header.len = + cpu_to_le16(sizeof(struct ieee80211_ht_cap)); + mwifiex_fill_cap_info(priv, ht_cap); + tlv_pos += sizeof(struct mwifiex_ie_types_htcap); + } + + /* Append vendor specific IE TLV */ + mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos); + + /* + * Set the output for the channel TLV to the address in the tlv buffer + * past any TLVs that were added in this function (SSID, num_probes). + * Channel TLVs will be added past this for each scan command, + * preserving the TLVs that were previously added. + */ + *chan_list_out = + (struct mwifiex_ie_types_chan_list_param_set *) tlv_pos; + + if (user_scan_in && user_scan_in->chan_list[0].chan_number) { + + dev_dbg(adapter->dev, "info: Scan: Using supplied channel list\n"); + + for (chan_idx = 0; + chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX + && user_scan_in->chan_list[chan_idx].chan_number; + chan_idx++) { + + channel = user_scan_in->chan_list[chan_idx].chan_number; + (scan_chan_list + chan_idx)->chan_number = channel; + + radio_type = + user_scan_in->chan_list[chan_idx].radio_type; + (scan_chan_list + chan_idx)->radio_type = radio_type; + + scan_type = user_scan_in->chan_list[chan_idx].scan_type; + + if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) + (scan_chan_list + + chan_idx)->chan_scan_mode_bitmap + |= MWIFIEX_PASSIVE_SCAN; + else + (scan_chan_list + + chan_idx)->chan_scan_mode_bitmap + &= ~MWIFIEX_PASSIVE_SCAN; + + if (user_scan_in->chan_list[chan_idx].scan_time) { + scan_dur = (u16) user_scan_in-> + chan_list[chan_idx].scan_time; + } else { + if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) + scan_dur = adapter->passive_scan_time; + else if (*filtered_scan) + scan_dur = adapter->specific_scan_time; + else + scan_dur = adapter->active_scan_time; + } + + (scan_chan_list + chan_idx)->min_scan_time = + cpu_to_le16(scan_dur); + (scan_chan_list + chan_idx)->max_scan_time = + cpu_to_le16(scan_dur); + } + + /* Check if we are only scanning the current channel */ + if ((chan_idx == 1) + && (user_scan_in->chan_list[0].chan_number + == priv->curr_bss_params.bss_descriptor.channel)) { + *scan_current_only = true; + dev_dbg(adapter->dev, + "info: Scan: Scanning current channel only\n"); + } + + } else { + dev_dbg(adapter->dev, + "info: Scan: Creating full region channel list\n"); + mwifiex_scan_create_channel_list(priv, user_scan_in, + scan_chan_list, + *filtered_scan); + } +} + +/* + * This function inspects the scan response buffer for pointers to + * expected TLVs. + * + * TLVs can be included at the end of the scan response BSS information. + * + * Data in the buffer is parsed pointers to TLVs that can potentially + * be passed back in the response. + */ +static void +mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter, + struct mwifiex_ie_types_data *tlv, + u32 tlv_buf_size, u32 req_tlv_type, + struct mwifiex_ie_types_data **tlv_data) +{ + struct mwifiex_ie_types_data *current_tlv; + u32 tlv_buf_left; + u32 tlv_type; + u32 tlv_len; + + current_tlv = tlv; + tlv_buf_left = tlv_buf_size; + *tlv_data = NULL; + + dev_dbg(adapter->dev, "info: SCAN_RESP: tlv_buf_size = %d\n", + tlv_buf_size); + + while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) { + + tlv_type = le16_to_cpu(current_tlv->header.type); + tlv_len = le16_to_cpu(current_tlv->header.len); + + if (sizeof(tlv->header) + tlv_len > tlv_buf_left) { + dev_err(adapter->dev, "SCAN_RESP: TLV buffer corrupt\n"); + break; + } + + if (req_tlv_type == tlv_type) { + switch (tlv_type) { + case TLV_TYPE_TSFTIMESTAMP: + dev_dbg(adapter->dev, "info: SCAN_RESP: TSF " + "timestamp TLV, len = %d\n", tlv_len); + *tlv_data = (struct mwifiex_ie_types_data *) + current_tlv; + break; + case TLV_TYPE_CHANNELBANDLIST: + dev_dbg(adapter->dev, "info: SCAN_RESP: channel" + " band list TLV, len = %d\n", tlv_len); + *tlv_data = (struct mwifiex_ie_types_data *) + current_tlv; + break; + default: + dev_err(adapter->dev, + "SCAN_RESP: unhandled TLV = %d\n", + tlv_type); + /* Give up, this seems corrupted */ + return; + } + } + + if (*tlv_data) + break; + + + tlv_buf_left -= (sizeof(tlv->header) + tlv_len); + current_tlv = + (struct mwifiex_ie_types_data *) (current_tlv->data + + tlv_len); + + } /* while */ +} + +/* + * This function interprets a BSS scan response returned from the firmware. + * + * The various fixed fields and IEs are parsed and passed back for a BSS + * probe response or beacon from scan command. Information is recorded as + * needed in the scan table for that entry. + * + * The following IE types are recognized and parsed - + * - SSID + * - Supported rates + * - FH parameters set + * - DS parameters set + * - CF parameters set + * - IBSS parameters set + * - ERP information + * - Extended supported rates + * - Vendor specific (221) + * - RSN IE + * - WAPI IE + * - HT capability + * - HT operation + * - BSS Coexistence 20/40 + * - Extended capability + * - Overlapping BSS scan parameters + */ +static int +mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter, + struct mwifiex_bssdescriptor *bss_entry, + u8 **beacon_info, u32 *bytes_left) +{ + int ret = 0; + u8 element_id; + struct ieee_types_fh_param_set *fh_param_set; + struct ieee_types_ds_param_set *ds_param_set; + struct ieee_types_cf_param_set *cf_param_set; + struct ieee_types_ibss_param_set *ibss_param_set; + struct mwifiex_802_11_fixed_ies fixed_ie; + u8 *current_ptr; + u8 *rate; + u8 element_len; + u16 total_ie_len; + u8 bytes_to_copy; + u8 rate_size; + u16 beacon_size; + u8 found_data_rate_ie; + u32 bytes_left_for_current_beacon; + struct ieee_types_vendor_specific *vendor_ie; + const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; + const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; + + found_data_rate_ie = false; + rate_size = 0; + beacon_size = 0; + + if (*bytes_left >= sizeof(beacon_size)) { + /* Extract & convert beacon size from the command buffer */ + memcpy(&beacon_size, *beacon_info, sizeof(beacon_size)); + *bytes_left -= sizeof(beacon_size); + *beacon_info += sizeof(beacon_size); + } + + if (!beacon_size || beacon_size > *bytes_left) { + *beacon_info += *bytes_left; + *bytes_left = 0; + return -1; + } + + /* Initialize the current working beacon pointer for this BSS + iteration */ + current_ptr = *beacon_info; + + /* Advance the return beacon pointer past the current beacon */ + *beacon_info += beacon_size; + *bytes_left -= beacon_size; + + bytes_left_for_current_beacon = beacon_size; + + memcpy(bss_entry->mac_address, current_ptr, ETH_ALEN); + dev_dbg(adapter->dev, "info: InterpretIE: AP MAC Addr: %pM\n", + bss_entry->mac_address); + + current_ptr += ETH_ALEN; + bytes_left_for_current_beacon -= ETH_ALEN; + + if (bytes_left_for_current_beacon < 12) { + dev_err(adapter->dev, "InterpretIE: not enough bytes left\n"); + return -1; + } + + /* + * Next 4 fields are RSSI, time stamp, beacon interval, + * and capability information + */ + + /* RSSI is 1 byte long */ + bss_entry->rssi = (s32) (*current_ptr); + dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n", *current_ptr); + current_ptr += 1; + bytes_left_for_current_beacon -= 1; + + /* + * The RSSI is not part of the beacon/probe response. After we have + * advanced current_ptr past the RSSI field, save the remaining + * data for use at the application layer + */ + bss_entry->beacon_buf = current_ptr; + bss_entry->beacon_buf_size = bytes_left_for_current_beacon; + + /* Time stamp is 8 bytes long */ + memcpy(fixed_ie.time_stamp, current_ptr, 8); + memcpy(bss_entry->time_stamp, current_ptr, 8); + current_ptr += 8; + bytes_left_for_current_beacon -= 8; + + /* Beacon interval is 2 bytes long */ + memcpy(&fixed_ie.beacon_interval, current_ptr, 2); + bss_entry->beacon_period = le16_to_cpu(fixed_ie.beacon_interval); + current_ptr += 2; + bytes_left_for_current_beacon -= 2; + + /* Capability information is 2 bytes long */ + memcpy(&fixed_ie.capabilities, current_ptr, 2); + dev_dbg(adapter->dev, "info: InterpretIE: fixed_ie.capabilities=0x%X\n", + fixed_ie.capabilities); + bss_entry->cap_info_bitmap = le16_to_cpu(fixed_ie.capabilities); + current_ptr += 2; + bytes_left_for_current_beacon -= 2; + + /* Rest of the current buffer are IE's */ + dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP = %d\n", + bytes_left_for_current_beacon); + + if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { + dev_dbg(adapter->dev, "info: InterpretIE: AP WEP enabled\n"); + bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; + } else { + bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL; + } + + if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_IBSS) + bss_entry->bss_mode = MWIFIEX_BSS_MODE_IBSS; + else + bss_entry->bss_mode = MWIFIEX_BSS_MODE_INFRA; + + + /* Process variable IE */ + while (bytes_left_for_current_beacon >= 2) { + element_id = *current_ptr; + element_len = *(current_ptr + 1); + total_ie_len = element_len + sizeof(struct ieee_types_header); + + if (bytes_left_for_current_beacon < total_ie_len) { + dev_err(adapter->dev, "err: InterpretIE: in processing" + " IE, bytes left < IE length\n"); + bytes_left_for_current_beacon = 0; + ret = -1; + continue; + } + switch (element_id) { + case WLAN_EID_SSID: + bss_entry->ssid.ssid_len = element_len; + memcpy(bss_entry->ssid.ssid, (current_ptr + 2), + element_len); + dev_dbg(adapter->dev, "info: InterpretIE: ssid: %-32s\n", + bss_entry->ssid.ssid); + break; + + case WLAN_EID_SUPP_RATES: + memcpy(bss_entry->data_rates, current_ptr + 2, + element_len); + memcpy(bss_entry->supported_rates, current_ptr + 2, + element_len); + rate_size = element_len; + found_data_rate_ie = true; + break; + + case WLAN_EID_FH_PARAMS: + fh_param_set = + (struct ieee_types_fh_param_set *) current_ptr; + memcpy(&bss_entry->phy_param_set.fh_param_set, + fh_param_set, + sizeof(struct ieee_types_fh_param_set)); + break; + + case WLAN_EID_DS_PARAMS: + ds_param_set = + (struct ieee_types_ds_param_set *) current_ptr; + + bss_entry->channel = ds_param_set->current_chan; + + memcpy(&bss_entry->phy_param_set.ds_param_set, + ds_param_set, + sizeof(struct ieee_types_ds_param_set)); + break; + + case WLAN_EID_CF_PARAMS: + cf_param_set = + (struct ieee_types_cf_param_set *) current_ptr; + memcpy(&bss_entry->ss_param_set.cf_param_set, + cf_param_set, + sizeof(struct ieee_types_cf_param_set)); + break; + + case WLAN_EID_IBSS_PARAMS: + ibss_param_set = + (struct ieee_types_ibss_param_set *) + current_ptr; + memcpy(&bss_entry->ss_param_set.ibss_param_set, + ibss_param_set, + sizeof(struct ieee_types_ibss_param_set)); + break; + + case WLAN_EID_ERP_INFO: + bss_entry->erp_flags = *(current_ptr + 2); + break; + + case WLAN_EID_EXT_SUPP_RATES: + /* + * Only process extended supported rate + * if data rate is already found. + * Data rate IE should come before + * extended supported rate IE + */ + if (found_data_rate_ie) { + if ((element_len + rate_size) > + MWIFIEX_SUPPORTED_RATES) + bytes_to_copy = + (MWIFIEX_SUPPORTED_RATES - + rate_size); + else + bytes_to_copy = element_len; + + rate = (u8 *) bss_entry->data_rates; + rate += rate_size; + memcpy(rate, current_ptr + 2, bytes_to_copy); + + rate = (u8 *) bss_entry->supported_rates; + rate += rate_size; + memcpy(rate, current_ptr + 2, bytes_to_copy); + } + break; + + case WLAN_EID_VENDOR_SPECIFIC: + vendor_ie = (struct ieee_types_vendor_specific *) + current_ptr; + + if (!memcmp + (vendor_ie->vend_hdr.oui, wpa_oui, + sizeof(wpa_oui))) { + bss_entry->bcn_wpa_ie = + (struct ieee_types_vendor_specific *) + current_ptr; + bss_entry->wpa_offset = (u16) (current_ptr - + bss_entry->beacon_buf); + } else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui, + sizeof(wmm_oui))) { + if (total_ie_len == + sizeof(struct ieee_types_wmm_parameter) + || total_ie_len == + sizeof(struct ieee_types_wmm_info)) + /* + * Only accept and copy the WMM IE if + * it matches the size expected for the + * WMM Info IE or the WMM Parameter IE. + */ + memcpy((u8 *) &bss_entry->wmm_ie, + current_ptr, total_ie_len); + } + break; + case WLAN_EID_RSN: + bss_entry->bcn_rsn_ie = + (struct ieee_types_generic *) current_ptr; + bss_entry->rsn_offset = (u16) (current_ptr - + bss_entry->beacon_buf); + break; + case WLAN_EID_BSS_AC_ACCESS_DELAY: + bss_entry->bcn_wapi_ie = + (struct ieee_types_generic *) current_ptr; + bss_entry->wapi_offset = (u16) (current_ptr - + bss_entry->beacon_buf); + break; + case WLAN_EID_HT_CAPABILITY: + bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *) + (current_ptr + + sizeof(struct ieee_types_header)); + bss_entry->ht_cap_offset = (u16) (current_ptr + + sizeof(struct ieee_types_header) - + bss_entry->beacon_buf); + break; + case WLAN_EID_HT_INFORMATION: + bss_entry->bcn_ht_info = (struct ieee80211_ht_info *) + (current_ptr + + sizeof(struct ieee_types_header)); + bss_entry->ht_info_offset = (u16) (current_ptr + + sizeof(struct ieee_types_header) - + bss_entry->beacon_buf); + break; + case WLAN_EID_BSS_COEX_2040: + bss_entry->bcn_bss_co_2040 = (u8 *) (current_ptr + + sizeof(struct ieee_types_header)); + bss_entry->bss_co_2040_offset = (u16) (current_ptr + + sizeof(struct ieee_types_header) - + bss_entry->beacon_buf); + break; + case WLAN_EID_EXT_CAPABILITY: + bss_entry->bcn_ext_cap = (u8 *) (current_ptr + + sizeof(struct ieee_types_header)); + bss_entry->ext_cap_offset = (u16) (current_ptr + + sizeof(struct ieee_types_header) - + bss_entry->beacon_buf); + break; + case WLAN_EID_OVERLAP_BSS_SCAN_PARAM: + bss_entry->bcn_obss_scan = + (struct ieee_types_obss_scan_param *) + current_ptr; + bss_entry->overlap_bss_offset = (u16) (current_ptr - + bss_entry->beacon_buf); + break; + default: + break; + } + + current_ptr += element_len + 2; + + /* Need to account for IE ID and IE Len */ + bytes_left_for_current_beacon -= (element_len + 2); + + } /* while (bytes_left_for_current_beacon > 2) */ + return ret; +} + +/* + * This function adjusts the pointers used in beacon buffers to reflect + * shifts. + * + * The memory allocated for beacon buffers is of fixed sizes where all the + * saved beacons must be stored. New beacons are added in the free portion + * of this memory, space permitting; while duplicate beacon buffers are + * placed at the same start location. However, since duplicate beacon + * buffers may not match the size of the old one, all the following buffers + * in the memory must be shifted to either make space, or to fill up freed + * up space. + * + * This function is used to update the beacon buffer pointers that are past + * an existing beacon buffer that is updated with a new one of different + * size. The pointers are shifted by a fixed amount, either forward or + * backward. + * + * the following pointers in every affected beacon buffers are changed, if + * present - + * - WPA IE pointer + * - RSN IE pointer + * - WAPI IE pointer + * - HT capability IE pointer + * - HT information IE pointer + * - BSS coexistence 20/40 IE pointer + * - Extended capability IE pointer + * - Overlapping BSS scan parameter IE pointer + */ +static void +mwifiex_adjust_beacon_buffer_ptrs(struct mwifiex_private *priv, u8 advance, + u8 *bcn_store, u32 rem_bcn_size, + u32 num_of_ent) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u32 adj_idx; + for (adj_idx = 0; adj_idx < num_of_ent; adj_idx++) { + if (adapter->scan_table[adj_idx].beacon_buf > bcn_store) { + + if (advance) + adapter->scan_table[adj_idx].beacon_buf += + rem_bcn_size; + else + adapter->scan_table[adj_idx].beacon_buf -= + rem_bcn_size; + + if (adapter->scan_table[adj_idx].bcn_wpa_ie) + adapter->scan_table[adj_idx].bcn_wpa_ie = + (struct ieee_types_vendor_specific *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].wpa_offset); + if (adapter->scan_table[adj_idx].bcn_rsn_ie) + adapter->scan_table[adj_idx].bcn_rsn_ie = + (struct ieee_types_generic *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].rsn_offset); + if (adapter->scan_table[adj_idx].bcn_wapi_ie) + adapter->scan_table[adj_idx].bcn_wapi_ie = + (struct ieee_types_generic *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].wapi_offset); + if (adapter->scan_table[adj_idx].bcn_ht_cap) + adapter->scan_table[adj_idx].bcn_ht_cap = + (struct ieee80211_ht_cap *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].ht_cap_offset); + + if (adapter->scan_table[adj_idx].bcn_ht_info) + adapter->scan_table[adj_idx].bcn_ht_info = + (struct ieee80211_ht_info *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].ht_info_offset); + if (adapter->scan_table[adj_idx].bcn_bss_co_2040) + adapter->scan_table[adj_idx].bcn_bss_co_2040 = + (u8 *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].bss_co_2040_offset); + if (adapter->scan_table[adj_idx].bcn_ext_cap) + adapter->scan_table[adj_idx].bcn_ext_cap = + (u8 *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].ext_cap_offset); + if (adapter->scan_table[adj_idx].bcn_obss_scan) + adapter->scan_table[adj_idx].bcn_obss_scan = + (struct ieee_types_obss_scan_param *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].overlap_bss_offset); + } + } +} + +/* + * This function updates the pointers used in beacon buffer for given bss + * descriptor to reflect shifts + * + * Following pointers are updated + * - WPA IE pointer + * - RSN IE pointer + * - WAPI IE pointer + * - HT capability IE pointer + * - HT information IE pointer + * - BSS coexistence 20/40 IE pointer + * - Extended capability IE pointer + * - Overlapping BSS scan parameter IE pointer + */ +static void +mwifiex_update_beacon_buffer_ptrs(struct mwifiex_bssdescriptor *beacon) +{ + if (beacon->bcn_wpa_ie) + beacon->bcn_wpa_ie = (struct ieee_types_vendor_specific *) + (beacon->beacon_buf + beacon->wpa_offset); + if (beacon->bcn_rsn_ie) + beacon->bcn_rsn_ie = (struct ieee_types_generic *) + (beacon->beacon_buf + beacon->rsn_offset); + if (beacon->bcn_wapi_ie) + beacon->bcn_wapi_ie = (struct ieee_types_generic *) + (beacon->beacon_buf + beacon->wapi_offset); + if (beacon->bcn_ht_cap) + beacon->bcn_ht_cap = (struct ieee80211_ht_cap *) + (beacon->beacon_buf + beacon->ht_cap_offset); + if (beacon->bcn_ht_info) + beacon->bcn_ht_info = (struct ieee80211_ht_info *) + (beacon->beacon_buf + beacon->ht_info_offset); + if (beacon->bcn_bss_co_2040) + beacon->bcn_bss_co_2040 = (u8 *) (beacon->beacon_buf + + beacon->bss_co_2040_offset); + if (beacon->bcn_ext_cap) + beacon->bcn_ext_cap = (u8 *) (beacon->beacon_buf + + beacon->ext_cap_offset); + if (beacon->bcn_obss_scan) + beacon->bcn_obss_scan = (struct ieee_types_obss_scan_param *) + (beacon->beacon_buf + beacon->overlap_bss_offset); +} + +/* + * This function stores a beacon or probe response for a BSS returned + * in the scan. + * + * This stores a new scan response or an update for a previous scan response. + * New entries need to verify that they do not exceed the total amount of + * memory allocated for the table. + * + * Replacement entries need to take into consideration the amount of space + * currently allocated for the beacon/probe response and adjust the entry + * as needed. + * + * A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved + * for an entry in case it is a beacon since a probe response for the + * network will by larger per the standard. This helps to reduce the + * amount of memory copying to fit a new probe response into an entry + * already occupied by a network's previously stored beacon. + */ +static void +mwifiex_ret_802_11_scan_store_beacon(struct mwifiex_private *priv, + u32 beacon_idx, u32 num_of_ent, + struct mwifiex_bssdescriptor *new_beacon) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u8 *bcn_store; + u32 new_bcn_size; + u32 old_bcn_size; + u32 bcn_space; + + if (adapter->scan_table[beacon_idx].beacon_buf) { + + new_bcn_size = new_beacon->beacon_buf_size; + old_bcn_size = adapter->scan_table[beacon_idx].beacon_buf_size; + bcn_space = adapter->scan_table[beacon_idx].beacon_buf_size_max; + bcn_store = adapter->scan_table[beacon_idx].beacon_buf; + + /* Set the max to be the same as current entry unless changed + below */ + new_beacon->beacon_buf_size_max = bcn_space; + if (new_bcn_size == old_bcn_size) { + /* + * Beacon is the same size as the previous entry. + * Replace the previous contents with the scan result + */ + memcpy(bcn_store, new_beacon->beacon_buf, + new_beacon->beacon_buf_size); + + } else if (new_bcn_size <= bcn_space) { + /* + * New beacon size will fit in the amount of space + * we have previously allocated for it + */ + + /* Copy the new beacon buffer entry over the old one */ + memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size); + + /* + * If the old beacon size was less than the maximum + * we had alloted for the entry, and the new entry + * is even smaller, reset the max size to the old + * beacon entry and compress the storage space + * (leaving a new pad space of (old_bcn_size - + * new_bcn_size). + */ + if (old_bcn_size < bcn_space + && new_bcn_size <= old_bcn_size) { + /* + * Old Beacon size is smaller than the alloted + * storage size. Shrink the alloted storage + * space. + */ + dev_dbg(adapter->dev, "info: AppControl:" + " smaller duplicate beacon " + "(%d), old = %d, new = %d, space = %d," + "left = %d\n", + beacon_idx, old_bcn_size, new_bcn_size, + bcn_space, + (int)(sizeof(adapter->bcn_buf) - + (adapter->bcn_buf_end - + adapter->bcn_buf))); + + /* + * memmove (since the memory overlaps) the + * data after the beacon we just stored to the + * end of the current beacon. This cleans up + * any unused space the old larger beacon was + * using in the buffer + */ + memmove(bcn_store + old_bcn_size, + bcn_store + bcn_space, + adapter->bcn_buf_end - (bcn_store + + bcn_space)); + + /* + * Decrement the end pointer by the difference + * between the old larger size and the new + * smaller size since we are using less space + * due to the new beacon being smaller + */ + adapter->bcn_buf_end -= + (bcn_space - old_bcn_size); + + /* Set the maximum storage size to the old + beacon size */ + new_beacon->beacon_buf_size_max = old_bcn_size; + + /* Adjust beacon buffer pointers that are past + the current */ + mwifiex_adjust_beacon_buffer_ptrs(priv, 0, + bcn_store, (bcn_space - old_bcn_size), + num_of_ent); + } + } else if (adapter->bcn_buf_end + (new_bcn_size - bcn_space) + < (adapter->bcn_buf + sizeof(adapter->bcn_buf))) { + /* + * Beacon is larger than space previously allocated + * (bcn_space) and there is enough space left in the + * beaconBuffer to store the additional data + */ + dev_dbg(adapter->dev, "info: AppControl:" + " larger duplicate beacon (%d), " + "old = %d, new = %d, space = %d, left = %d\n", + beacon_idx, old_bcn_size, new_bcn_size, + bcn_space, + (int)(sizeof(adapter->bcn_buf) - + (adapter->bcn_buf_end - + adapter->bcn_buf))); + + /* + * memmove (since the memory overlaps) the data + * after the beacon we just stored to the end of + * the current beacon. This moves the data for + * the beacons after this further in memory to + * make space for the new larger beacon we are + * about to copy in. + */ + memmove(bcn_store + new_bcn_size, + bcn_store + bcn_space, + adapter->bcn_buf_end - (bcn_store + bcn_space)); + + /* Copy the new beacon buffer entry over the old one */ + memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size); + + /* Move the beacon end pointer by the amount of new + beacon data we are adding */ + adapter->bcn_buf_end += (new_bcn_size - bcn_space); + + /* + * This entry is bigger than the alloted max space + * previously reserved. Increase the max space to + * be equal to the new beacon size + */ + new_beacon->beacon_buf_size_max = new_bcn_size; + + /* Adjust beacon buffer pointers that are past the + current */ + mwifiex_adjust_beacon_buffer_ptrs(priv, 1, bcn_store, + (new_bcn_size - bcn_space), + num_of_ent); + } else { + /* + * Beacon is larger than the previously allocated space, + * but there is not enough free space to store the + * additional data. + */ + dev_err(adapter->dev, "AppControl: larger duplicate " + " beacon (%d), old = %d new = %d, space = %d," + " left = %d\n", beacon_idx, old_bcn_size, + new_bcn_size, bcn_space, + (int)(sizeof(adapter->bcn_buf) - + (adapter->bcn_buf_end - adapter->bcn_buf))); + + /* Storage failure, keep old beacon intact */ + new_beacon->beacon_buf_size = old_bcn_size; + if (new_beacon->bcn_wpa_ie) + new_beacon->wpa_offset = + adapter->scan_table[beacon_idx]. + wpa_offset; + if (new_beacon->bcn_rsn_ie) + new_beacon->rsn_offset = + adapter->scan_table[beacon_idx]. + rsn_offset; + if (new_beacon->bcn_wapi_ie) + new_beacon->wapi_offset = + adapter->scan_table[beacon_idx]. + wapi_offset; + if (new_beacon->bcn_ht_cap) + new_beacon->ht_cap_offset = + adapter->scan_table[beacon_idx]. + ht_cap_offset; + if (new_beacon->bcn_ht_info) + new_beacon->ht_info_offset = + adapter->scan_table[beacon_idx]. + ht_info_offset; + if (new_beacon->bcn_bss_co_2040) + new_beacon->bss_co_2040_offset = + adapter->scan_table[beacon_idx]. + bss_co_2040_offset; + if (new_beacon->bcn_ext_cap) + new_beacon->ext_cap_offset = + adapter->scan_table[beacon_idx]. + ext_cap_offset; + if (new_beacon->bcn_obss_scan) + new_beacon->overlap_bss_offset = + adapter->scan_table[beacon_idx]. + overlap_bss_offset; + } + /* Point the new entry to its permanent storage space */ + new_beacon->beacon_buf = bcn_store; + mwifiex_update_beacon_buffer_ptrs(new_beacon); + } else { + /* + * No existing beacon data exists for this entry, check to see + * if we can fit it in the remaining space + */ + if (adapter->bcn_buf_end + new_beacon->beacon_buf_size + + SCAN_BEACON_ENTRY_PAD < (adapter->bcn_buf + + sizeof(adapter->bcn_buf))) { + + /* + * Copy the beacon buffer data from the local entry to + * the adapter dev struct buffer space used to store + * the raw beacon data for each entry in the scan table + */ + memcpy(adapter->bcn_buf_end, new_beacon->beacon_buf, + new_beacon->beacon_buf_size); + + /* Update the beacon ptr to point to the table save + area */ + new_beacon->beacon_buf = adapter->bcn_buf_end; + new_beacon->beacon_buf_size_max = + (new_beacon->beacon_buf_size + + SCAN_BEACON_ENTRY_PAD); + + mwifiex_update_beacon_buffer_ptrs(new_beacon); + + /* Increment the end pointer by the size reserved */ + adapter->bcn_buf_end += new_beacon->beacon_buf_size_max; + + dev_dbg(adapter->dev, "info: AppControl: beacon[%02d]" + " sz=%03d, used = %04d, left = %04d\n", + beacon_idx, + new_beacon->beacon_buf_size, + (int)(adapter->bcn_buf_end - adapter->bcn_buf), + (int)(sizeof(adapter->bcn_buf) - + (adapter->bcn_buf_end - + adapter->bcn_buf))); + } else { + /* No space for new beacon */ + dev_dbg(adapter->dev, "info: AppControl: no space for" + " beacon (%d): %pM sz=%03d, left=%03d\n", + beacon_idx, new_beacon->mac_address, + new_beacon->beacon_buf_size, + (int)(sizeof(adapter->bcn_buf) - + (adapter->bcn_buf_end - + adapter->bcn_buf))); + + /* Storage failure; clear storage records for this + bcn */ + new_beacon->beacon_buf = NULL; + new_beacon->beacon_buf_size = 0; + new_beacon->beacon_buf_size_max = 0; + new_beacon->bcn_wpa_ie = NULL; + new_beacon->wpa_offset = 0; + new_beacon->bcn_rsn_ie = NULL; + new_beacon->rsn_offset = 0; + new_beacon->bcn_wapi_ie = NULL; + new_beacon->wapi_offset = 0; + new_beacon->bcn_ht_cap = NULL; + new_beacon->ht_cap_offset = 0; + new_beacon->bcn_ht_info = NULL; + new_beacon->ht_info_offset = 0; + new_beacon->bcn_bss_co_2040 = NULL; + new_beacon->bss_co_2040_offset = 0; + new_beacon->bcn_ext_cap = NULL; + new_beacon->ext_cap_offset = 0; + new_beacon->bcn_obss_scan = NULL; + new_beacon->overlap_bss_offset = 0; + } + } +} + +/* + * This function restores a beacon buffer of the current BSS descriptor. + */ +static void mwifiex_restore_curr_bcn(struct mwifiex_private *priv) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_bssdescriptor *curr_bss = + &priv->curr_bss_params.bss_descriptor; + unsigned long flags; + + if (priv->curr_bcn_buf && + ((adapter->bcn_buf_end + priv->curr_bcn_size) < + (adapter->bcn_buf + sizeof(adapter->bcn_buf)))) { + spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags); + + /* restore the current beacon buffer */ + memcpy(adapter->bcn_buf_end, priv->curr_bcn_buf, + priv->curr_bcn_size); + curr_bss->beacon_buf = adapter->bcn_buf_end; + curr_bss->beacon_buf_size = priv->curr_bcn_size; + adapter->bcn_buf_end += priv->curr_bcn_size; + + /* adjust the pointers in the current BSS descriptor */ + if (curr_bss->bcn_wpa_ie) + curr_bss->bcn_wpa_ie = + (struct ieee_types_vendor_specific *) + (curr_bss->beacon_buf + + curr_bss->wpa_offset); + + if (curr_bss->bcn_rsn_ie) + curr_bss->bcn_rsn_ie = (struct ieee_types_generic *) + (curr_bss->beacon_buf + + curr_bss->rsn_offset); + + if (curr_bss->bcn_ht_cap) + curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *) + (curr_bss->beacon_buf + + curr_bss->ht_cap_offset); + + if (curr_bss->bcn_ht_info) + curr_bss->bcn_ht_info = (struct ieee80211_ht_info *) + (curr_bss->beacon_buf + + curr_bss->ht_info_offset); + + if (curr_bss->bcn_bss_co_2040) + curr_bss->bcn_bss_co_2040 = + (u8 *) (curr_bss->beacon_buf + + curr_bss->bss_co_2040_offset); + + if (curr_bss->bcn_ext_cap) + curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf + + curr_bss->ext_cap_offset); + + if (curr_bss->bcn_obss_scan) + curr_bss->bcn_obss_scan = + (struct ieee_types_obss_scan_param *) + (curr_bss->beacon_buf + + curr_bss->overlap_bss_offset); + + spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags); + + dev_dbg(adapter->dev, "info: current beacon restored %d\n", + priv->curr_bcn_size); + } else { + dev_warn(adapter->dev, + "curr_bcn_buf not saved or bcn_buf has no space\n"); + } +} + +/* + * This function post processes the scan table after a new scan command has + * completed. + * + * It inspects each entry of the scan table and tries to find an entry that + * matches with our current associated/joined network from the scan. If + * one is found, the stored copy of the BSS descriptor of our current network + * is updated. + * + * It also debug dumps the current scan table contents after processing is over. + */ +static void +mwifiex_process_scan_results(struct mwifiex_private *priv) +{ + struct mwifiex_adapter *adapter = priv->adapter; + s32 j; + u32 i; + unsigned long flags; + + if (priv->media_connected) { + + j = mwifiex_find_ssid_in_list(priv, &priv->curr_bss_params. + bss_descriptor.ssid, + priv->curr_bss_params. + bss_descriptor.mac_address, + priv->bss_mode); + + if (j >= 0) { + spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags); + priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL; + priv->curr_bss_params.bss_descriptor.wpa_offset = 0; + priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL; + priv->curr_bss_params.bss_descriptor.rsn_offset = 0; + priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL; + priv->curr_bss_params.bss_descriptor.wapi_offset = 0; + priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL; + priv->curr_bss_params.bss_descriptor.ht_cap_offset = + 0; + priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL; + priv->curr_bss_params.bss_descriptor.ht_info_offset = + 0; + priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 = + NULL; + priv->curr_bss_params.bss_descriptor. + bss_co_2040_offset = 0; + priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL; + priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0; + priv->curr_bss_params.bss_descriptor. + bcn_obss_scan = NULL; + priv->curr_bss_params.bss_descriptor. + overlap_bss_offset = 0; + priv->curr_bss_params.bss_descriptor.beacon_buf = NULL; + priv->curr_bss_params.bss_descriptor.beacon_buf_size = + 0; + priv->curr_bss_params.bss_descriptor. + beacon_buf_size_max = 0; + + dev_dbg(adapter->dev, "info: Found current ssid/bssid" + " in list @ index #%d\n", j); + /* Make a copy of current BSSID descriptor */ + memcpy(&priv->curr_bss_params.bss_descriptor, + &adapter->scan_table[j], + sizeof(priv->curr_bss_params.bss_descriptor)); + + mwifiex_save_curr_bcn(priv); + spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags); + + } else { + mwifiex_restore_curr_bcn(priv); + } + } + + for (i = 0; i < adapter->num_in_scan_table; i++) + dev_dbg(adapter->dev, "info: scan:(%02d) %pM " + "RSSI[%03d], SSID[%s]\n", + i, adapter->scan_table[i].mac_address, + (s32) adapter->scan_table[i].rssi, + adapter->scan_table[i].ssid.ssid); +} + +/* + * This function converts radio type scan parameter to a band configuration + * to be used in join command. + */ +static u8 +mwifiex_radio_type_to_band(u8 radio_type) +{ + u8 ret_band; + + switch (radio_type) { + case HostCmd_SCAN_RADIO_TYPE_A: + ret_band = BAND_A; + break; + case HostCmd_SCAN_RADIO_TYPE_BG: + default: + ret_band = BAND_G; + break; + } + + return ret_band; +} + +/* + * This function deletes a specific indexed entry from the scan table. + * + * This also compacts the remaining entries and adjusts any buffering + * of beacon/probe response data if needed. + */ +static void +mwifiex_scan_delete_table_entry(struct mwifiex_private *priv, s32 table_idx) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u32 del_idx; + u32 beacon_buf_adj; + u8 *beacon_buf; + + /* + * Shift the saved beacon buffer data for the scan table back over the + * entry being removed. Update the end of buffer pointer. Save the + * deleted buffer allocation size for pointer adjustments for entries + * compacted after the deleted index. + */ + beacon_buf_adj = adapter->scan_table[table_idx].beacon_buf_size_max; + + dev_dbg(adapter->dev, "info: Scan: Delete Entry %d, beacon buffer " + "removal = %d bytes\n", table_idx, beacon_buf_adj); + + /* Check if the table entry had storage allocated for its beacon */ + if (beacon_buf_adj) { + beacon_buf = adapter->scan_table[table_idx].beacon_buf; + + /* + * Remove the entry's buffer space, decrement the table end + * pointer by the amount we are removing + */ + adapter->bcn_buf_end -= beacon_buf_adj; + + dev_dbg(adapter->dev, "info: scan: delete entry %d," + " compact data: %p <- %p (sz = %d)\n", + table_idx, beacon_buf, + beacon_buf + beacon_buf_adj, + (int)(adapter->bcn_buf_end - beacon_buf)); + + /* + * Compact data storage. Copy all data after the deleted + * entry's end address (beacon_buf + beacon_buf_adj) back + * to the original start address (beacon_buf). + * + * Scan table entries affected by the move will have their + * entry pointer adjusted below. + * + * Use memmove since the dest/src memory regions overlap. + */ + memmove(beacon_buf, beacon_buf + beacon_buf_adj, + adapter->bcn_buf_end - beacon_buf); + } + + dev_dbg(adapter->dev, + "info: Scan: Delete Entry %d, num_in_scan_table = %d\n", + table_idx, adapter->num_in_scan_table); + + /* Shift all of the entries after the table_idx back by one, compacting + the table and removing the requested entry */ + for (del_idx = table_idx; (del_idx + 1) < adapter->num_in_scan_table; + del_idx++) { + /* Copy the next entry over this one */ + memcpy(adapter->scan_table + del_idx, + adapter->scan_table + del_idx + 1, + sizeof(struct mwifiex_bssdescriptor)); + + /* + * Adjust this entry's pointer to its beacon buffer based on + * the removed/compacted entry from the deleted index. Don't + * decrement if the buffer pointer is NULL (no data stored for + * this entry). + */ + if (adapter->scan_table[del_idx].beacon_buf) { + adapter->scan_table[del_idx].beacon_buf -= + beacon_buf_adj; + if (adapter->scan_table[del_idx].bcn_wpa_ie) + adapter->scan_table[del_idx].bcn_wpa_ie = + (struct ieee_types_vendor_specific *) + (adapter->scan_table[del_idx]. + beacon_buf + + adapter->scan_table[del_idx]. + wpa_offset); + if (adapter->scan_table[del_idx].bcn_rsn_ie) + adapter->scan_table[del_idx].bcn_rsn_ie = + (struct ieee_types_generic *) + (adapter->scan_table[del_idx]. + beacon_buf + + adapter->scan_table[del_idx]. + rsn_offset); + if (adapter->scan_table[del_idx].bcn_wapi_ie) + adapter->scan_table[del_idx].bcn_wapi_ie = + (struct ieee_types_generic *) + (adapter->scan_table[del_idx].beacon_buf + + adapter->scan_table[del_idx]. + wapi_offset); + if (adapter->scan_table[del_idx].bcn_ht_cap) + adapter->scan_table[del_idx].bcn_ht_cap = + (struct ieee80211_ht_cap *) + (adapter->scan_table[del_idx].beacon_buf + + adapter->scan_table[del_idx]. + ht_cap_offset); + + if (adapter->scan_table[del_idx].bcn_ht_info) + adapter->scan_table[del_idx].bcn_ht_info = + (struct ieee80211_ht_info *) + (adapter->scan_table[del_idx].beacon_buf + + adapter->scan_table[del_idx]. + ht_info_offset); + if (adapter->scan_table[del_idx].bcn_bss_co_2040) + adapter->scan_table[del_idx].bcn_bss_co_2040 = + (u8 *) + (adapter->scan_table[del_idx].beacon_buf + + adapter->scan_table[del_idx]. + bss_co_2040_offset); + if (adapter->scan_table[del_idx].bcn_ext_cap) + adapter->scan_table[del_idx].bcn_ext_cap = + (u8 *) + (adapter->scan_table[del_idx].beacon_buf + + adapter->scan_table[del_idx]. + ext_cap_offset); + if (adapter->scan_table[del_idx].bcn_obss_scan) + adapter->scan_table[del_idx]. + bcn_obss_scan = + (struct ieee_types_obss_scan_param *) + (adapter->scan_table[del_idx].beacon_buf + + adapter->scan_table[del_idx]. + overlap_bss_offset); + } + } + + /* The last entry is invalid now that it has been deleted or moved + back */ + memset(adapter->scan_table + adapter->num_in_scan_table - 1, + 0x00, sizeof(struct mwifiex_bssdescriptor)); + + adapter->num_in_scan_table--; +} + +/* + * This function deletes all occurrences of a given SSID from the scan table. + * + * This iterates through the scan table and deletes all entries that match + * the given SSID. It also compacts the remaining scan table entries. + */ +static int +mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv, + struct mwifiex_802_11_ssid *del_ssid) +{ + int ret = -1; + s32 table_idx; + + dev_dbg(priv->adapter->dev, "info: scan: delete ssid entry: %-32s\n", + del_ssid->ssid); + + /* If the requested SSID is found in the table, delete it. Then keep + searching the table for multiple entires for the SSID until no + more are found */ + while ((table_idx = mwifiex_find_ssid_in_list(priv, del_ssid, NULL, + MWIFIEX_BSS_MODE_AUTO)) >= + 0) { + dev_dbg(priv->adapter->dev, + "info: Scan: Delete SSID Entry: Found Idx = %d\n", + table_idx); + ret = 0; + mwifiex_scan_delete_table_entry(priv, table_idx); + } + + return ret; +} + +/* + * This is an internal function used to start a scan based on an input + * configuration. + * + * This uses the input user scan configuration information when provided in + * order to send the appropriate scan commands to firmware to populate or + * update the internal driver scan table. + */ +int mwifiex_scan_networks(struct mwifiex_private *priv, + void *wait_buf, u16 action, + const struct mwifiex_user_scan_cfg *user_scan_in, + struct mwifiex_scan_resp *scan_resp) +{ + int ret = 0; + struct mwifiex_adapter *adapter = priv->adapter; + struct cmd_ctrl_node *cmd_node = NULL; + union mwifiex_scan_cmd_config_tlv *scan_cfg_out = NULL; + struct mwifiex_ie_types_chan_list_param_set *chan_list_out; + u32 buf_size; + struct mwifiex_chan_scan_param_set *scan_chan_list; + u8 keep_previous_scan; + u8 filtered_scan; + u8 scan_current_chan_only; + u8 max_chan_per_scan; + unsigned long flags; + + if (action == HostCmd_ACT_GEN_GET) { + if (scan_resp) { + scan_resp->scan_table = (u8 *) adapter->scan_table; + scan_resp->num_in_scan_table = + adapter->num_in_scan_table; + } else { + ret = -1; + } + return ret; + } + + if (adapter->scan_processing && action == HostCmd_ACT_GEN_SET) { + dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); + return ret; + } + + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->scan_processing = true; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + + if (priv->scan_block && action == HostCmd_ACT_GEN_SET) { + dev_dbg(adapter->dev, + "cmd: Scan is blocked during association...\n"); + return ret; + } + + scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv), + GFP_KERNEL); + if (!scan_cfg_out) { + dev_err(adapter->dev, "failed to alloc scan_cfg_out\n"); + return -1; + } + + buf_size = sizeof(struct mwifiex_chan_scan_param_set) * + MWIFIEX_USER_SCAN_CHAN_MAX; + scan_chan_list = kzalloc(buf_size, GFP_KERNEL); + if (!scan_chan_list) { + dev_err(adapter->dev, "failed to alloc scan_chan_list\n"); + kfree(scan_cfg_out); + return -1; + } + + keep_previous_scan = false; + + mwifiex_scan_setup_scan_config(priv, user_scan_in, + &scan_cfg_out->config, &chan_list_out, + scan_chan_list, &max_chan_per_scan, + &filtered_scan, &scan_current_chan_only); + + if (user_scan_in) + keep_previous_scan = user_scan_in->keep_previous_scan; + + + if (!keep_previous_scan) { + memset(adapter->scan_table, 0x00, + sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP); + adapter->num_in_scan_table = 0; + adapter->bcn_buf_end = adapter->bcn_buf; + } + + ret = mwifiex_scan_channel_list(priv, wait_buf, max_chan_per_scan, + filtered_scan, &scan_cfg_out->config, + chan_list_out, scan_chan_list); + + /* Get scan command from scan_pending_q and put to cmd_pending_q */ + if (!ret) { + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + if (!list_empty(&adapter->scan_pending_q)) { + cmd_node = list_first_entry(&adapter->scan_pending_q, + struct cmd_ctrl_node, list); + list_del(&cmd_node->list); + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, + flags); + mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, + true); + } else { + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, + flags); + } + ret = -EINPROGRESS; + } else { + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->scan_processing = true; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + } + + kfree(scan_cfg_out); + kfree(scan_chan_list); + return ret; +} + +/* + * This function prepares a scan command to be sent to the firmware. + * + * This uses the scan command configuration sent to the command processing + * module in command preparation stage to configure a scan command structure + * to send to firmware. + * + * The fixed fields specifying the BSS type and BSSID filters as well as a + * variable number/length of TLVs are sent in the command to firmware. + * + * Preparation also includes - + * - Setting command ID, and proper size + * - Ensuring correct endian-ness + */ +int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, void *data_buf) +{ + struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan; + struct mwifiex_scan_cmd_config *scan_cfg; + + scan_cfg = (struct mwifiex_scan_cmd_config *) data_buf; + + /* Set fixed field variables in scan command */ + scan_cmd->bss_mode = scan_cfg->bss_mode; + memcpy(scan_cmd->bssid, scan_cfg->specific_bssid, + sizeof(scan_cmd->bssid)); + memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len); + + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN); + + /* Size is equal to the sizeof(fixed portions) + the TLV len + header */ + cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode) + + sizeof(scan_cmd->bssid) + + scan_cfg->tlv_buf_len + S_DS_GEN)); + + return 0; +} + +/* + * This function handles the command response of scan. + * + * The response buffer for the scan command has the following + * memory layout: + * + * .-------------------------------------------------------------. + * | Header (4 * sizeof(t_u16)): Standard command response hdr | + * .-------------------------------------------------------------. + * | BufSize (t_u16) : sizeof the BSS Description data | + * .-------------------------------------------------------------. + * | NumOfSet (t_u8) : Number of BSS Descs returned | + * .-------------------------------------------------------------. + * | BSSDescription data (variable, size given in BufSize) | + * .-------------------------------------------------------------. + * | TLV data (variable, size calculated using Header->Size, | + * | BufSize and sizeof the fixed fields above) | + * .-------------------------------------------------------------. + */ +int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, void *wq_buf) +{ + int ret = 0; + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_wait_queue *wait_queue = NULL; + struct cmd_ctrl_node *cmd_node = NULL; + struct host_cmd_ds_802_11_scan_rsp *scan_rsp = NULL; + struct mwifiex_bssdescriptor *bss_new_entry = NULL; + struct mwifiex_ie_types_data *tlv_data; + struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; + u8 *bss_info; + u32 scan_resp_size; + u32 bytes_left; + u32 num_in_table; + u32 bss_idx; + u32 idx; + u32 tlv_buf_size; + long long tsf_val; + struct mwifiex_chan_freq_power *cfp; + struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv; + struct chan_band_param_set *chan_band; + u8 band; + u8 is_bgscan_resp; + unsigned long flags; + + is_bgscan_resp = (le16_to_cpu(resp->command) + == HostCmd_CMD_802_11_BG_SCAN_QUERY); + if (is_bgscan_resp) + scan_rsp = &resp->params.bg_scan_query_resp.scan_resp; + else + scan_rsp = &resp->params.scan_resp; + + + if (scan_rsp->number_of_sets > IW_MAX_AP) { + dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n", + scan_rsp->number_of_sets); + ret = -1; + goto done; + } + + bytes_left = le16_to_cpu(scan_rsp->bss_descript_size); + dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n", + bytes_left); + + scan_resp_size = le16_to_cpu(resp->size); + + dev_dbg(adapter->dev, + "info: SCAN_RESP: returned %d APs before parsing\n", + scan_rsp->number_of_sets); + + num_in_table = adapter->num_in_scan_table; + bss_info = scan_rsp->bss_desc_and_tlv_buffer; + + /* + * The size of the TLV buffer is equal to the entire command response + * size (scan_resp_size) minus the fixed fields (sizeof()'s), the + * BSS Descriptions (bss_descript_size as bytesLef) and the command + * response header (S_DS_GEN) + */ + tlv_buf_size = scan_resp_size - (bytes_left + + sizeof(scan_rsp->bss_descript_size) + + sizeof(scan_rsp->number_of_sets) + + S_DS_GEN); + + tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp-> + bss_desc_and_tlv_buffer + + bytes_left); + + /* Search the TLV buffer space in the scan response for any valid + TLVs */ + mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size, + TLV_TYPE_TSFTIMESTAMP, + (struct mwifiex_ie_types_data **) + &tsf_tlv); + + /* Search the TLV buffer space in the scan response for any valid + TLVs */ + mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size, + TLV_TYPE_CHANNELBANDLIST, + (struct mwifiex_ie_types_data **) + &chan_band_tlv); + + /* + * Process each scan response returned (scan_rsp->number_of_sets). + * Save the information in the bss_new_entry and then insert into the + * driver scan table either as an update to an existing entry + * or as an addition at the end of the table + */ + bss_new_entry = kzalloc(sizeof(struct mwifiex_bssdescriptor), + GFP_KERNEL); + if (!bss_new_entry) { + dev_err(adapter->dev, " failed to alloc bss_new_entry\n"); + return -1; + } + + for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { + /* Zero out the bss_new_entry we are about to store info in */ + memset(bss_new_entry, 0x00, + sizeof(struct mwifiex_bssdescriptor)); + + if (mwifiex_interpret_bss_desc_with_ie(adapter, bss_new_entry, + &bss_info, + &bytes_left)) { + /* Error parsing/interpreting scan response, skipped */ + dev_err(adapter->dev, "SCAN_RESP: " + "mwifiex_interpret_bss_desc_with_ie " + "returned ERROR\n"); + continue; + } + + /* Process the data fields and IEs returned for this BSS */ + dev_dbg(adapter->dev, "info: SCAN_RESP: BSSID = %pM\n", + bss_new_entry->mac_address); + + /* Search the scan table for the same bssid */ + for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) { + if (memcmp(bss_new_entry->mac_address, + adapter->scan_table[bss_idx].mac_address, + sizeof(bss_new_entry->mac_address))) { + continue; + } + /* + * If the SSID matches as well, it is a + * duplicate of this entry. Keep the bss_idx + * set to this entry so we replace the old + * contents in the table + */ + if ((bss_new_entry->ssid.ssid_len + == adapter->scan_table[bss_idx]. ssid.ssid_len) + && (!memcmp(bss_new_entry->ssid.ssid, + adapter->scan_table[bss_idx].ssid.ssid, + bss_new_entry->ssid.ssid_len))) { + dev_dbg(adapter->dev, "info: SCAN_RESP:" + " duplicate of index: %d\n", bss_idx); + break; + } + } + /* + * If the bss_idx is equal to the number of entries in + * the table, the new entry was not a duplicate; append + * it to the scan table + */ + if (bss_idx == num_in_table) { + /* Range check the bss_idx, keep it limited to + the last entry */ + if (bss_idx == IW_MAX_AP) + bss_idx--; + else + num_in_table++; + } + + /* + * Save the beacon/probe response returned for later application + * retrieval. Duplicate beacon/probe responses are updated if + * possible + */ + mwifiex_ret_802_11_scan_store_beacon(priv, bss_idx, + num_in_table, bss_new_entry); + /* + * If the TSF TLV was appended to the scan results, save this + * entry's TSF value in the networkTSF field.The networkTSF is + * the firmware's TSF value at the time the beacon or probe + * response was received. + */ + if (tsf_tlv) { + memcpy(&tsf_val, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE] + , sizeof(tsf_val)); + memcpy(&bss_new_entry->network_tsf, &tsf_val, + sizeof(bss_new_entry->network_tsf)); + } + band = BAND_G; + if (chan_band_tlv) { + chan_band = &chan_band_tlv->chan_band_param[idx]; + band = mwifiex_radio_type_to_band(chan_band->radio_type + & (BIT(0) | BIT(1))); + } + + /* Save the band designation for this entry for use in join */ + bss_new_entry->bss_band = band; + cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv, + (u8) bss_new_entry->bss_band, + (u16)bss_new_entry->channel); + + if (cfp) + bss_new_entry->freq = cfp->freq; + else + bss_new_entry->freq = 0; + + /* Copy the locally created bss_new_entry to the scan table */ + memcpy(&adapter->scan_table[bss_idx], bss_new_entry, + sizeof(adapter->scan_table[bss_idx])); + + } + + dev_dbg(adapter->dev, + "info: SCAN_RESP: Scanned %2d APs, %d valid, %d total\n", + scan_rsp->number_of_sets, + num_in_table - adapter->num_in_scan_table, num_in_table); + + /* Update the total number of BSSIDs in the scan table */ + adapter->num_in_scan_table = num_in_table; + + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + if (list_empty(&adapter->scan_pending_q)) { + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->scan_processing = false; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + /* + * Process the resulting scan table: + * - Remove any bad ssids + * - Update our current BSS information from scan data + */ + mwifiex_process_scan_results(priv); + + /* Need to indicate IOCTL complete */ + wait_queue = (struct mwifiex_wait_queue *) wq_buf; + if (wait_queue) { + wait_queue->status = MWIFIEX_ERROR_NO_ERROR; + + /* Indicate ioctl complete */ + mwifiex_ioctl_complete(adapter, + (struct mwifiex_wait_queue *) wait_queue, 0); + } + if (priv->report_scan_result) + priv->report_scan_result = false; + if (priv->scan_pending_on_block) { + priv->scan_pending_on_block = false; + up(&priv->async_sem); + } + + } else { + /* Get scan command from scan_pending_q and put to + cmd_pending_q */ + cmd_node = list_first_entry(&adapter->scan_pending_q, + struct cmd_ctrl_node, list); + list_del(&cmd_node->list); + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + + mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); + } + +done: + kfree((u8 *) bss_new_entry); + return ret; +} + +/* + * This function prepares command for background scan query. + * + * Preparation includes - + * - Setting command ID and proper size + * - Setting background scan flush parameter + * - Ensuring correct endian-ness + */ +int mwifiex_cmd_802_11_bg_scan_query(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf) +{ + struct host_cmd_ds_802_11_bg_scan_query *bg_query = + &cmd->params.bg_scan_query; + + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY); + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query) + + S_DS_GEN); + + bg_query->flush = 1; + + return 0; +} + +/* + * This function finds a SSID in the scan table. + * + * A BSSID may optionally be provided to qualify the SSID. + * For non-Auto mode, further check is made to make sure the + * BSS found in the scan table is compatible with the current + * settings of the driver. + */ +s32 +mwifiex_find_ssid_in_list(struct mwifiex_private *priv, + struct mwifiex_802_11_ssid *ssid, u8 *bssid, + u32 mode) +{ + struct mwifiex_adapter *adapter = priv->adapter; + s32 net = -1, j; + u8 best_rssi = 0; + u32 i; + + dev_dbg(adapter->dev, "info: num of entries in table = %d\n", + adapter->num_in_scan_table); + + /* + * Loop through the table until the maximum is reached or until a match + * is found based on the bssid field comparison + */ + for (i = 0; + i < adapter->num_in_scan_table && (!bssid || (bssid && net < 0)); + i++) { + if (!mwifiex_ssid_cmp(&adapter->scan_table[i].ssid, ssid) && + (!bssid + || !memcmp(adapter->scan_table[i].mac_address, bssid, + ETH_ALEN)) + && + (mwifiex_get_cfp_by_band_and_channel_from_cfg80211 + (priv, (u8) adapter->scan_table[i].bss_band, + (u16) adapter->scan_table[i].channel))) { + switch (mode) { + case MWIFIEX_BSS_MODE_INFRA: + case MWIFIEX_BSS_MODE_IBSS: + j = mwifiex_is_network_compatible(priv, i, + mode); + + if (j >= 0) { + if (SCAN_RSSI + (adapter->scan_table[i].rssi) > + best_rssi) { + best_rssi = SCAN_RSSI(adapter-> + scan_table + [i].rssi); + net = i; + } + } else { + if (net == -1) + net = j; + } + break; + case MWIFIEX_BSS_MODE_AUTO: + default: + /* + * Do not check compatibility if the mode + * requested is Auto/Unknown. Allows generic + * find to work without verifying against the + * Adapter security settings + */ + if (SCAN_RSSI(adapter->scan_table[i].rssi) > + best_rssi) { + best_rssi = SCAN_RSSI(adapter-> + scan_table[i].rssi); + net = i; + } + break; + } + } + } + + return net; +} + +/* + * This function finds a specific compatible BSSID in the scan list. + * + * This function loops through the scan table looking for a compatible + * match. If a BSSID matches, but the BSS is found to be not compatible + * the function ignores it and continues to search through the rest of + * the entries in case there is an AP with multiple SSIDs assigned to + * the same BSSID. + */ +s32 +mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid, + u32 mode) +{ + struct mwifiex_adapter *adapter = priv->adapter; + s32 net = -1; + u32 i; + + if (!bssid) + return -1; + + dev_dbg(adapter->dev, "info: FindBSSID: Num of BSSIDs = %d\n", + adapter->num_in_scan_table); + + /* + * Look through the scan table for a compatible match. The ret return + * variable will be equal to the index in the scan table (greater + * than zero) if the network is compatible. The loop will continue + * past a matched bssid that is not compatible in case there is an + * AP with multiple SSIDs assigned to the same BSSID + */ + for (i = 0; net < 0 && i < adapter->num_in_scan_table; i++) { + if (!memcmp + (adapter->scan_table[i].mac_address, bssid, ETH_ALEN) + && mwifiex_get_cfp_by_band_and_channel_from_cfg80211 + (priv, + (u8) adapter-> + scan_table[i]. + bss_band, + (u16) adapter-> + scan_table[i]. + channel)) { + switch (mode) { + case MWIFIEX_BSS_MODE_INFRA: + case MWIFIEX_BSS_MODE_IBSS: + net = mwifiex_is_network_compatible(priv, i, + mode); + break; + default: + net = i; + break; + } + } + } + + return net; +} + +/* + * This function inserts scan command node to the scan pending queue. + */ +void +mwifiex_queue_scan_cmd(struct mwifiex_private *priv, + struct cmd_ctrl_node *cmd_node) +{ + struct mwifiex_adapter *adapter = priv->adapter; + unsigned long flags; + + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + list_add_tail(&cmd_node->list, &adapter->scan_pending_q); + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); +} + +/* + * This function finds an AP with specific ssid in the scan list. + */ +int mwifiex_find_best_network(struct mwifiex_private *priv, + struct mwifiex_ssid_bssid *req_ssid_bssid) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_bssdescriptor *req_bss; + s32 i; + + memset(req_ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); + + i = mwifiex_find_best_network_in_list(priv); + + if (i >= 0) { + req_bss = &adapter->scan_table[i]; + memcpy(&req_ssid_bssid->ssid, &req_bss->ssid, + sizeof(struct mwifiex_802_11_ssid)); + memcpy((u8 *) &req_ssid_bssid->bssid, + (u8 *) &req_bss->mac_address, ETH_ALEN); + + /* Make sure we are in the right mode */ + if (priv->bss_mode == MWIFIEX_BSS_MODE_AUTO) + priv->bss_mode = req_bss->bss_mode; + } + + if (!req_ssid_bssid->ssid.ssid_len) + return -1; + + dev_dbg(adapter->dev, "info: Best network found = [%s], " + "[%pM]\n", req_ssid_bssid->ssid.ssid, + req_ssid_bssid->bssid); + + return 0; +} + +/* + * This function sends a scan command for all available channels to the + * firmware, filtered on a specific SSID. + */ +static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, + void *wait_buf, u16 action, + struct mwifiex_802_11_ssid *req_ssid, + struct mwifiex_scan_resp *scan_resp) +{ + struct mwifiex_adapter *adapter = priv->adapter; + int ret = 0; + struct mwifiex_user_scan_cfg *scan_cfg; + + if (!req_ssid) + return -1; + + if (action == HostCmd_ACT_GEN_GET) { + if (scan_resp) { + scan_resp->scan_table = + (u8 *) &priv->curr_bss_params.bss_descriptor; + scan_resp->num_in_scan_table = + adapter->num_in_scan_table; + } else { + ret = -1; + } + return ret; + } + + if (adapter->scan_processing && action == HostCmd_ACT_GEN_SET) { + dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); + return ret; + } + + if (priv->scan_block && action == HostCmd_ACT_GEN_SET) { + dev_dbg(adapter->dev, + "cmd: Scan is blocked during association...\n"); + return ret; + } + + mwifiex_scan_delete_ssid_table_entry(priv, req_ssid); + + scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); + if (!scan_cfg) { + dev_err(adapter->dev, "failed to alloc scan_cfg\n"); + return -1; + } + + memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid, + req_ssid->ssid_len); + scan_cfg->keep_previous_scan = true; + + ret = mwifiex_scan_networks(priv, wait_buf, action, scan_cfg, NULL); + + kfree(scan_cfg); + return ret; +} + +/* + * Sends IOCTL request to start a scan. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + * + * Scan command can be issued for both normal scan and specific SSID + * scan, depending upon whether an SSID is provided or not. + */ +int mwifiex_request_scan(struct mwifiex_private *priv, u8 wait_option, + struct mwifiex_802_11_ssid *req_ssid) +{ + int ret = 0; + struct mwifiex_wait_queue *wait = NULL; + int status = 0; + + if (down_interruptible(&priv->async_sem)) { + dev_err(priv->adapter->dev, "%s: acquire semaphore\n", + __func__); + return -1; + } + priv->scan_pending_on_block = true; + + /* Allocate wait request buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) { + ret = -1; + goto done; + } + + if (req_ssid && req_ssid->ssid_len != 0) + /* Specific SSID scan */ + status = mwifiex_scan_specific_ssid(priv, wait, + HostCmd_ACT_GEN_SET, + req_ssid, NULL); + else + /* Normal scan */ + status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_SET, + NULL, NULL); + status = mwifiex_request_ioctl(priv, wait, status, wait_option); + if (status == -1) + ret = -1; +done: + if ((wait) && (status != -EINPROGRESS)) + kfree(wait); + if (ret == -1) { + priv->scan_pending_on_block = false; + up(&priv->async_sem); + } + return ret; +} + +/* + * This function appends the vendor specific IE TLV to a buffer. + */ +int +mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, + u16 vsie_mask, u8 **buffer) +{ + int id, ret_len = 0; + struct mwifiex_ie_types_vendor_param_set *vs_param_set; + + if (!buffer) + return 0; + if (!(*buffer)) + return 0; + + /* + * Traverse through the saved vendor specific IE array and append + * the selected(scan/assoc/adhoc) IE as TLV to the command + */ + for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) { + if (priv->vs_ie[id].mask & vsie_mask) { + vs_param_set = + (struct mwifiex_ie_types_vendor_param_set *) + *buffer; + vs_param_set->header.type = + cpu_to_le16(TLV_TYPE_PASSTHROUGH); + vs_param_set->header.len = + cpu_to_le16((((u16) priv->vs_ie[id].ie[1]) + & 0x00FF) + 2); + memcpy(vs_param_set->ie, priv->vs_ie[id].ie, + le16_to_cpu(vs_param_set->header.len)); + *buffer += le16_to_cpu(vs_param_set->header.len) + + sizeof(struct mwifiex_ie_types_header); + ret_len += le16_to_cpu(vs_param_set->header.len) + + sizeof(struct mwifiex_ie_types_header); + } + } + return ret_len; +} + +/* + * This function saves a beacon buffer of the current BSS descriptor. + * + * The current beacon buffer is saved so that it can be restored in the + * following cases that makes the beacon buffer not to contain the current + * ssid's beacon buffer. + * - The current ssid was not found somehow in the last scan. + * - The current ssid was the last entry of the scan table and overloaded. + */ +void +mwifiex_save_curr_bcn(struct mwifiex_private *priv) +{ + struct mwifiex_bssdescriptor *curr_bss = + &priv->curr_bss_params.bss_descriptor; + + /* save the beacon buffer if it is not saved or updated */ + if ((priv->curr_bcn_buf == NULL) || + (priv->curr_bcn_size != curr_bss->beacon_buf_size) || + (memcmp(priv->curr_bcn_buf, curr_bss->beacon_buf, + curr_bss->beacon_buf_size))) { + + kfree(priv->curr_bcn_buf); + priv->curr_bcn_buf = NULL; + + priv->curr_bcn_size = curr_bss->beacon_buf_size; + if (!priv->curr_bcn_size) + return; + + priv->curr_bcn_buf = kzalloc(curr_bss->beacon_buf_size, + GFP_KERNEL); + if (!priv->curr_bcn_buf) { + dev_err(priv->adapter->dev, + "failed to alloc curr_bcn_buf\n"); + } else { + memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf, + curr_bss->beacon_buf_size); + dev_dbg(priv->adapter->dev, + "info: current beacon saved %d\n", + priv->curr_bcn_size); + } + } +} + +/* + * This function frees the current BSS descriptor beacon buffer. + */ +void +mwifiex_free_curr_bcn(struct mwifiex_private *priv) +{ + kfree(priv->curr_bcn_buf); + priv->curr_bcn_buf = NULL; +} diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c new file mode 100644 index 000000000000..f21e5cd19839 --- /dev/null +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -0,0 +1,1770 @@ +/* + * Marvell Wireless LAN device driver: SDIO specific handling + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" +#include "sdio.h" + + +#define SDIO_VERSION "1.0" + +static struct mwifiex_if_ops sdio_ops; + +static struct semaphore add_remove_card_sem; + +/* + * SDIO probe. + * + * This function probes an mwifiex device and registers it. It allocates + * the card structure, enables SDIO function number and initiates the + * device registration and initialization procedure by adding a logical + * interface. + */ +static int +mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) +{ + int ret = 0; + struct sdio_mmc_card *card = NULL; + + pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n", + func->vendor, func->device, func->class, func->num); + + card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL); + if (!card) { + pr_err("%s: failed to alloc memory\n", __func__); + return -ENOMEM; + } + + card->func = func; + + func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; + + sdio_claim_host(func); + ret = sdio_enable_func(func); + sdio_release_host(func); + + if (ret) { + pr_err("%s: failed to enable function\n", __func__); + return -EIO; + } + + if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops)) { + pr_err("%s: add card failed\n", __func__); + kfree(card); + sdio_claim_host(func); + ret = sdio_disable_func(func); + sdio_release_host(func); + ret = -1; + } + + return ret; +} + +/* + * SDIO remove. + * + * This function removes the interface and frees up the card structure. + */ +static void +mwifiex_sdio_remove(struct sdio_func *func) +{ + struct sdio_mmc_card *card; + + pr_debug("info: SDIO func num=%d\n", func->num); + + if (func) { + card = sdio_get_drvdata(func); + if (card) { + mwifiex_remove_card(card->adapter, + &add_remove_card_sem); + kfree(card); + } + } +} + +/* + * SDIO suspend. + * + * Kernel needs to suspend all functions separately. Therefore all + * registered functions must have drivers with suspend and resume + * methods. Failing that the kernel simply removes the whole card. + * + * If already not suspended, this function allocates and sends a host + * sleep activate request to the firmware and turns off the traffic. + */ +static int mwifiex_sdio_suspend(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + struct sdio_mmc_card *card; + struct mwifiex_adapter *adapter = NULL; + mmc_pm_flag_t pm_flag = 0; + int hs_actived = 0; + int i; + int ret = 0; + + if (func) { + pm_flag = sdio_get_host_pm_caps(func); + pr_debug("cmd: %s: suspend: PM flag = 0x%x\n", + sdio_func_id(func), pm_flag); + if (!(pm_flag & MMC_PM_KEEP_POWER)) { + pr_err("%s: cannot remain alive while host is" + " suspended\n", sdio_func_id(func)); + return -ENOSYS; + } + + card = sdio_get_drvdata(func); + if (!card || !card->adapter) { + pr_err("suspend: invalid card or adapter\n"); + return 0; + } + } else { + pr_err("suspend: sdio_func is not specified\n"); + return 0; + } + + adapter = card->adapter; + + /* Enable the Host Sleep */ + hs_actived = mwifiex_enable_hs(adapter); + if (hs_actived) { + pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n"); + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + } + + /* Indicate device suspended */ + adapter->is_suspended = true; + + for (i = 0; i < adapter->priv_num; i++) + netif_carrier_off(adapter->priv[i]->netdev); + + return ret; +} + +/* + * SDIO resume. + * + * Kernel needs to suspend all functions separately. Therefore all + * registered functions must have drivers with suspend and resume + * methods. Failing that the kernel simply removes the whole card. + * + * If already not resumed, this function turns on the traffic and + * sends a host sleep cancel request to the firmware. + */ +static int mwifiex_sdio_resume(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + struct sdio_mmc_card *card; + struct mwifiex_adapter *adapter = NULL; + mmc_pm_flag_t pm_flag = 0; + int i; + + if (func) { + pm_flag = sdio_get_host_pm_caps(func); + card = sdio_get_drvdata(func); + if (!card || !card->adapter) { + pr_err("resume: invalid card or adapter\n"); + return 0; + } + } else { + pr_err("resume: sdio_func is not specified\n"); + return 0; + } + + adapter = card->adapter; + + if (!adapter->is_suspended) { + dev_warn(adapter->dev, "device already resumed\n"); + return 0; + } + + adapter->is_suspended = false; + + for (i = 0; i < adapter->priv_num; i++) + if (adapter->priv[i]->media_connected) + netif_carrier_on(adapter->priv[i]->netdev); + + /* Disable Host Sleep */ + mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), + MWIFIEX_NO_WAIT); + + return 0; +} + +/* Device ID for SD8787 */ +#define SDIO_DEVICE_ID_MARVELL_8787 (0x9119) + +/* WLAN IDs */ +static const struct sdio_device_id mwifiex_ids[] = { + {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787)}, + {}, +}; + +MODULE_DEVICE_TABLE(sdio, mwifiex_ids); + +static const struct dev_pm_ops mwifiex_sdio_pm_ops = { + .suspend = mwifiex_sdio_suspend, + .resume = mwifiex_sdio_resume, +}; + +static struct sdio_driver mwifiex_sdio = { + .name = "mwifiex_sdio", + .id_table = mwifiex_ids, + .probe = mwifiex_sdio_probe, + .remove = mwifiex_sdio_remove, + .drv = { + .owner = THIS_MODULE, + .pm = &mwifiex_sdio_pm_ops, + } +}; + +/* + * This function writes data into SDIO card register. + */ +static int +mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u32 data) +{ + struct sdio_mmc_card *card = adapter->card; + int ret = -1; + + sdio_claim_host(card->func); + sdio_writeb(card->func, (u8) data, reg, &ret); + sdio_release_host(card->func); + + return ret; +} + +/* + * This function reads data from SDIO card register. + */ +static int +mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u32 *data) +{ + struct sdio_mmc_card *card = adapter->card; + int ret = -1; + u8 val; + + sdio_claim_host(card->func); + val = sdio_readb(card->func, reg, &ret); + sdio_release_host(card->func); + + *data = val; + + return ret; +} + +/* + * This function writes multiple data into SDIO card memory. + * + * This does not work in suspended mode. + */ +static int +mwifiex_write_data_sync(struct mwifiex_adapter *adapter, + u8 *buffer, u32 pkt_len, u32 port, u32 timeout) +{ + struct sdio_mmc_card *card = adapter->card; + int ret = -1; + u8 blk_mode = + (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE; + u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1; + u32 blk_cnt = + (blk_mode == + BLOCK_MODE) ? (pkt_len / + MWIFIEX_SDIO_BLOCK_SIZE) : pkt_len; + u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK); + + if (adapter->is_suspended) { + dev_err(adapter->dev, + "%s: not allowed while suspended\n", __func__); + return -1; + } + + sdio_claim_host(card->func); + + if (!sdio_writesb(card->func, ioport, buffer, blk_cnt * blk_size)) + ret = 0; + + sdio_release_host(card->func); + + return ret; +} + +/* + * This function reads multiple data from SDIO card memory. + */ +static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, + u8 *buffer, u32 len, + u32 port, u32 timeout, u8 claim) +{ + struct sdio_mmc_card *card = adapter->card; + int ret = -1; + u8 blk_mode = + (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE; + u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1; + u32 blk_cnt = + (blk_mode == + BLOCK_MODE) ? (len / MWIFIEX_SDIO_BLOCK_SIZE) : len; + u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK); + + if (claim) + sdio_claim_host(card->func); + + if (!sdio_readsb(card->func, buffer, ioport, blk_cnt * blk_size)) + ret = 0; + + if (claim) + sdio_release_host(card->func); + + return ret; +} + +/* + * This function wakes up the card. + * + * A host power up command is written to the card configuration + * register to wake up the card. + */ +static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) +{ + int ret; + + dev_dbg(adapter->dev, "event: wakeup device...\n"); + ret = mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP); + + return ret; +} + +/* + * This function is called after the card has woken up. + * + * The card configuration register is reset. + */ +static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter) +{ + int ret; + + dev_dbg(adapter->dev, "cmd: wakeup device completed\n"); + ret = mwifiex_write_reg(adapter, CONFIGURATION_REG, 0); + + return ret; +} + +/* + * This function initializes the IO ports. + * + * The following operations are performed - + * - Read the IO ports (0, 1 and 2) + * - Set host interrupt Reset-To-Read to clear + * - Set auto re-enable interrupt + */ +static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter) +{ + u32 reg; + + adapter->ioport = 0; + + /* Read the IO port */ + if (!mwifiex_read_reg(adapter, IO_PORT_0_REG, ®)) + adapter->ioport |= (reg & 0xff); + else + return -1; + + if (!mwifiex_read_reg(adapter, IO_PORT_1_REG, ®)) + adapter->ioport |= ((reg & 0xff) << 8); + else + return -1; + + if (!mwifiex_read_reg(adapter, IO_PORT_2_REG, ®)) + adapter->ioport |= ((reg & 0xff) << 16); + else + return -1; + + pr_debug("info: SDIO FUNC1 IO port: %#x\n", adapter->ioport); + + /* Set Host interrupt reset to read to clear */ + if (!mwifiex_read_reg(adapter, HOST_INT_RSR_REG, ®)) + mwifiex_write_reg(adapter, HOST_INT_RSR_REG, + reg | SDIO_INT_MASK); + else + return -1; + + /* Dnld/Upld ready set to auto reset */ + if (!mwifiex_read_reg(adapter, CARD_MISC_CFG_REG, ®)) + mwifiex_write_reg(adapter, CARD_MISC_CFG_REG, + reg | AUTO_RE_ENABLE_INT); + else + return -1; + + return 0; +} + +/* + * This function sends data to the card. + */ +static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter, + u8 *payload, u32 pkt_len, u32 port) +{ + u32 i = 0; + int ret = 0; + + do { + ret = mwifiex_write_data_sync(adapter, payload, pkt_len, + port, 0); + if (ret) { + i++; + dev_err(adapter->dev, "host_to_card, write iomem" + " (%d) failed: %d\n", i, ret); + if (mwifiex_write_reg(adapter, + CONFIGURATION_REG, 0x04)) + dev_err(adapter->dev, "write CFG reg failed\n"); + + ret = -1; + if (i > MAX_WRITE_IOMEM_RETRY) + return ret; + } + } while (ret == -1); + + return ret; +} + +/* + * This function gets the read port. + * + * If control port bit is set in MP read bitmap, the control port + * is returned, otherwise the current read port is returned and + * the value is increased (provided it does not reach the maximum + * limit, in which case it is reset to 1) + */ +static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) +{ + struct sdio_mmc_card *card = adapter->card; + u16 rd_bitmap = card->mp_rd_bitmap; + + dev_dbg(adapter->dev, "data: mp_rd_bitmap=0x%04x\n", rd_bitmap); + + if (!(rd_bitmap & (CTRL_PORT_MASK | DATA_PORT_MASK))) + return -1; + + if (card->mp_rd_bitmap & CTRL_PORT_MASK) { + card->mp_rd_bitmap &= (u16) (~CTRL_PORT_MASK); + *port = CTRL_PORT; + dev_dbg(adapter->dev, "data: port=%d mp_rd_bitmap=0x%04x\n", + *port, card->mp_rd_bitmap); + } else { + if (card->mp_rd_bitmap & (1 << card->curr_rd_port)) { + card->mp_rd_bitmap &= + (u16) (~(1 << card->curr_rd_port)); + *port = card->curr_rd_port; + + if (++card->curr_rd_port == MAX_PORT) + card->curr_rd_port = 1; + } else { + return -1; + } + + dev_dbg(adapter->dev, + "data: port=%d mp_rd_bitmap=0x%04x -> 0x%04x\n", + *port, rd_bitmap, card->mp_rd_bitmap); + } + return 0; +} + +/* + * This function gets the write port for data. + * + * The current write port is returned if available and the value is + * increased (provided it does not reach the maximum limit, in which + * case it is reset to 1) + */ +static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u8 *port) +{ + struct sdio_mmc_card *card = adapter->card; + u16 wr_bitmap = card->mp_wr_bitmap; + + dev_dbg(adapter->dev, "data: mp_wr_bitmap=0x%04x\n", wr_bitmap); + + if (!(wr_bitmap & card->mp_data_port_mask)) + return -1; + + if (card->mp_wr_bitmap & (1 << card->curr_wr_port)) { + card->mp_wr_bitmap &= (u16) (~(1 << card->curr_wr_port)); + *port = card->curr_wr_port; + if (++card->curr_wr_port == card->mp_end_port) + card->curr_wr_port = 1; + } else { + adapter->data_sent = true; + return -EBUSY; + } + + if (*port == CTRL_PORT) { + dev_err(adapter->dev, "invalid data port=%d cur port=%d" + " mp_wr_bitmap=0x%04x -> 0x%04x\n", + *port, card->curr_wr_port, wr_bitmap, + card->mp_wr_bitmap); + return -1; + } + + dev_dbg(adapter->dev, "data: port=%d mp_wr_bitmap=0x%04x -> 0x%04x\n", + *port, wr_bitmap, card->mp_wr_bitmap); + + return 0; +} + +/* + * This function polls the card status. + */ +static int +mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) +{ + u32 tries; + u32 cs = 0; + + for (tries = 0; tries < MAX_POLL_TRIES; tries++) { + if (mwifiex_read_reg(adapter, CARD_STATUS_REG, &cs)) + break; + else if ((cs & bits) == bits) + return 0; + + udelay(10); + } + + dev_err(adapter->dev, "poll card status failed, tries = %d\n", + tries); + return -1; +} + +/* + * This function reads the firmware status. + */ +static int +mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) +{ + u32 fws0 = 0, fws1 = 0; + + if (mwifiex_read_reg(adapter, CARD_FW_STATUS0_REG, &fws0)) + return -1; + + if (mwifiex_read_reg(adapter, CARD_FW_STATUS1_REG, &fws1)) + return -1; + + *dat = (u16) ((fws1 << 8) | fws0); + + return 0; +} + +/* + * This function disables the host interrupt. + * + * The host interrupt mask is read, the disable bit is reset and + * written back to the card host interrupt mask register. + */ +static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) +{ + u32 host_int_mask = 0; + + /* Read back the host_int_mask register */ + if (mwifiex_read_reg(adapter, HOST_INT_MASK_REG, &host_int_mask)) + return -1; + + /* Update with the mask and write back to the register */ + host_int_mask &= ~HOST_INT_DISABLE; + + if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, host_int_mask)) { + dev_err(adapter->dev, "disable host interrupt failed\n"); + return -1; + } + + return 0; +} + +/* + * This function enables the host interrupt. + * + * The host interrupt enable mask is written to the card + * host interrupt mask register. + */ +static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter) +{ + /* Simply write the mask to the register */ + if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, HOST_INT_ENABLE)) { + dev_err(adapter->dev, "enable host interrupt failed\n"); + return -1; + } + return 0; +} + +/* + * This function sends a data buffer to the card. + */ +static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter, + u32 *type, u8 *buffer, + u32 npayload, u32 ioport) +{ + int ret = 0; + u32 nb; + + if (!buffer) { + dev_err(adapter->dev, "%s: buffer is NULL\n", __func__); + return -1; + } + + ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 0, 1); + + if (ret) { + dev_err(adapter->dev, "%s: read iomem failed: %d\n", __func__, + ret); + return -1; + } + + nb = le16_to_cpu(*(__le16 *) (buffer)); + if (nb > npayload) { + dev_err(adapter->dev, "%s: invalid packet, nb=%d, npayload=%d\n", + __func__, nb, npayload); + return -1; + } + + *type = le16_to_cpu(*(__le16 *) (buffer + 2)); + + return ret; +} + +/* + * This function downloads the firmware to the card. + * + * Firmware is downloaded to the card in blocks. Every block download + * is tested for CRC errors, and retried a number of times before + * returning failure. + */ +static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, + struct mwifiex_fw_image *fw) +{ + int ret = 0; + u8 *firmware = fw->fw_buf; + u32 firmware_len = fw->fw_len; + u32 offset = 0; + u32 base0, base1; + u8 *fwbuf; + u16 len = 0; + u32 txlen = 0, tx_blocks = 0, tries = 0; + u32 i = 0; + + if (!firmware_len) { + dev_err(adapter->dev, "firmware image not found!" + " Terminating download\n"); + return -1; + } + + dev_dbg(adapter->dev, "info: downloading FW image (%d bytes)\n", + firmware_len); + + /* Assume that the allocated buffer is 8-byte aligned */ + fwbuf = kzalloc(MWIFIEX_UPLD_SIZE, GFP_KERNEL); + if (!fwbuf) { + dev_err(adapter->dev, "unable to alloc buffer for firmware." + " Terminating download\n"); + return -1; + } + + /* Perform firmware data transfer */ + do { + /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY + bits */ + ret = mwifiex_sdio_poll_card_status(adapter, CARD_IO_READY | + DN_LD_CARD_RDY); + if (ret) { + dev_err(adapter->dev, "FW download with helper:" + " poll status timeout @ %d\n", offset); + goto done; + } + + /* More data? */ + if (offset >= firmware_len) + break; + + for (tries = 0; tries < MAX_POLL_TRIES; tries++) { + ret = mwifiex_read_reg(adapter, HOST_F1_RD_BASE_0, + &base0); + if (ret) { + dev_err(adapter->dev, "dev BASE0 register read" + " failed: base0=0x%04X(%d). Terminating " + "download\n", base0, base0); + goto done; + } + ret = mwifiex_read_reg(adapter, HOST_F1_RD_BASE_1, + &base1); + if (ret) { + dev_err(adapter->dev, "dev BASE1 register read" + " failed: base1=0x%04X(%d). Terminating " + "download\n", base1, base1); + goto done; + } + len = (u16) (((base1 & 0xff) << 8) | (base0 & 0xff)); + + if (len) + break; + + udelay(10); + } + + if (!len) { + break; + } else if (len > MWIFIEX_UPLD_SIZE) { + dev_err(adapter->dev, "FW download failed @ %d," + " invalid length %d\n", offset, len); + ret = -1; + goto done; + } + + txlen = len; + + if (len & BIT(0)) { + i++; + if (i > MAX_WRITE_IOMEM_RETRY) { + dev_err(adapter->dev, "FW download failed @" + " %d, over max retry count\n", offset); + ret = -1; + goto done; + } + dev_err(adapter->dev, "CRC indicated by the helper:" + " len = 0x%04X, txlen = %d\n", len, txlen); + len &= ~BIT(0); + /* Setting this to 0 to resend from same offset */ + txlen = 0; + } else { + i = 0; + + /* Set blocksize to transfer - checking for last + block */ + if (firmware_len - offset < txlen) + txlen = firmware_len - offset; + + tx_blocks = (txlen + MWIFIEX_SDIO_BLOCK_SIZE - + 1) / MWIFIEX_SDIO_BLOCK_SIZE; + + /* Copy payload to buffer */ + memmove(fwbuf, &firmware[offset], txlen); + } + + ret = mwifiex_write_data_sync(adapter, fwbuf, tx_blocks * + MWIFIEX_SDIO_BLOCK_SIZE, + adapter->ioport, 0); + if (ret) { + dev_err(adapter->dev, "FW download, write iomem (%d)" + " failed @ %d\n", i, offset); + if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04)) + dev_err(adapter->dev, "write CFG reg failed\n"); + + ret = -1; + goto done; + } + + offset += txlen; + } while (true); + + dev_dbg(adapter->dev, "info: FW download over, size %d bytes\n", + offset); + + ret = 0; +done: + kfree(fwbuf); + return ret; +} + +/* + * This function checks the firmware status in card. + * + * The winner interface is also determined by this function. + */ +static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, + u32 poll_num, int *winner) +{ + int ret = 0; + u16 firmware_stat; + u32 tries; + u32 winner_status; + + /* Wait for firmware initialization event */ + for (tries = 0; tries < poll_num; tries++) { + ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat); + if (ret) + continue; + if (firmware_stat == FIRMWARE_READY) { + ret = 0; + break; + } else { + mdelay(100); + ret = -1; + } + } + + if (winner && ret) { + if (mwifiex_read_reg + (adapter, CARD_FW_STATUS0_REG, &winner_status)) + winner_status = 0; + + if (winner_status) + *winner = 0; + else + *winner = 1; + } + return ret; +} + +/* + * This function reads the interrupt status from card. + */ +static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) +{ + struct sdio_mmc_card *card = adapter->card; + u32 sdio_ireg = 0; + unsigned long flags; + + if (mwifiex_read_data_sync(adapter, card->mp_regs, MAX_MP_REGS, + REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0, + 0)) { + dev_err(adapter->dev, "read mp_regs failed\n"); + return; + } + + sdio_ireg = card->mp_regs[HOST_INTSTATUS_REG]; + if (sdio_ireg) { + /* + * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS + * Clear the interrupt status register + */ + dev_dbg(adapter->dev, "int: sdio_ireg = %#x\n", sdio_ireg); + spin_lock_irqsave(&adapter->int_lock, flags); + adapter->int_status |= sdio_ireg; + spin_unlock_irqrestore(&adapter->int_lock, flags); + } + + return; +} + +/* + * SDIO interrupt handler. + * + * This function reads the interrupt status from firmware and assigns + * the main process in workqueue which will handle the interrupt. + */ +static void +mwifiex_sdio_interrupt(struct sdio_func *func) +{ + struct mwifiex_adapter *adapter; + struct sdio_mmc_card *card; + + card = sdio_get_drvdata(func); + if (!card || !card->adapter) { + pr_debug("int: func=%p card=%p adapter=%p\n", + func, card, card ? card->adapter : NULL); + return; + } + adapter = card->adapter; + + if (adapter->surprise_removed) + return; + + if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP) + adapter->ps_state = PS_STATE_AWAKE; + + mwifiex_interrupt_status(adapter); + queue_work(adapter->workqueue, &adapter->main_work); + + return; +} + +/* + * This function decodes a received packet. + * + * Based on the type, the packet is treated as either a data, or + * a command response, or an event, and the correct handler + * function is invoked. + */ +static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter, + struct sk_buff *skb, u32 upld_typ) +{ + u8 *cmd_buf; + + skb_pull(skb, INTF_HEADER_LEN); + + switch (upld_typ) { + case MWIFIEX_TYPE_DATA: + dev_dbg(adapter->dev, "info: --- Rx: Data packet ---\n"); + mwifiex_handle_rx_packet(adapter, skb); + break; + + case MWIFIEX_TYPE_CMD: + dev_dbg(adapter->dev, "info: --- Rx: Cmd Response ---\n"); + /* take care of curr_cmd = NULL case */ + if (!adapter->curr_cmd) { + cmd_buf = adapter->upld_buf; + + if (adapter->ps_state == PS_STATE_SLEEP_CFM) + mwifiex_process_sleep_confirm_resp(adapter, + skb->data, skb->len); + + memcpy(cmd_buf, skb->data, min_t(u32, + MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len)); + + dev_kfree_skb_any(skb); + } else { + adapter->cmd_resp_received = true; + adapter->curr_cmd->resp_skb = skb; + } + break; + + case MWIFIEX_TYPE_EVENT: + dev_dbg(adapter->dev, "info: --- Rx: Event ---\n"); + adapter->event_cause = *(u32 *) skb->data; + + skb_pull(skb, MWIFIEX_EVENT_HEADER_LEN); + + if ((skb->len > 0) && (skb->len < MAX_EVENT_SIZE)) + memcpy(adapter->event_body, skb->data, skb->len); + + /* event cause has been saved to adapter->event_cause */ + adapter->event_received = true; + adapter->event_skb = skb; + + break; + + default: + dev_err(adapter->dev, "unknown upload type %#x\n", upld_typ); + dev_kfree_skb_any(skb); + break; + } + + return 0; +} + +/* + * This function transfers received packets from card to driver, performing + * aggregation if required. + * + * For data received on control port, or if aggregation is disabled, the + * received buffers are uploaded as separate packets. However, if aggregation + * is enabled and required, the buffers are copied onto an aggregation buffer, + * provided there is space left, processed and finally uploaded. + */ +static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, + struct sk_buff *skb, u8 port) +{ + struct sdio_mmc_card *card = adapter->card; + s32 f_do_rx_aggr = 0; + s32 f_do_rx_cur = 0; + s32 f_aggr_cur = 0; + struct sk_buff *skb_deaggr; + u32 pind = 0; + u32 pkt_len, pkt_type = 0; + u8 *curr_ptr; + u32 rx_len = skb->len; + + if (port == CTRL_PORT) { + /* Read the command Resp without aggr */ + dev_dbg(adapter->dev, "info: %s: no aggregation for cmd " + "response\n", __func__); + + f_do_rx_cur = 1; + goto rx_curr_single; + } + + if (!card->mpa_rx.enabled) { + dev_dbg(adapter->dev, "info: %s: rx aggregation disabled\n", + __func__); + + f_do_rx_cur = 1; + goto rx_curr_single; + } + + if (card->mp_rd_bitmap & (~((u16) CTRL_PORT_MASK))) { + /* Some more data RX pending */ + dev_dbg(adapter->dev, "info: %s: not last packet\n", __func__); + + if (MP_RX_AGGR_IN_PROGRESS(card)) { + if (MP_RX_AGGR_BUF_HAS_ROOM(card, skb->len)) { + f_aggr_cur = 1; + } else { + /* No room in Aggr buf, do rx aggr now */ + f_do_rx_aggr = 1; + f_do_rx_cur = 1; + } + } else { + /* Rx aggr not in progress */ + f_aggr_cur = 1; + } + + } else { + /* No more data RX pending */ + dev_dbg(adapter->dev, "info: %s: last packet\n", __func__); + + if (MP_RX_AGGR_IN_PROGRESS(card)) { + f_do_rx_aggr = 1; + if (MP_RX_AGGR_BUF_HAS_ROOM(card, skb->len)) + f_aggr_cur = 1; + else + /* No room in Aggr buf, do rx aggr now */ + f_do_rx_cur = 1; + } else { + f_do_rx_cur = 1; + } + } + + if (f_aggr_cur) { + dev_dbg(adapter->dev, "info: current packet aggregation\n"); + /* Curr pkt can be aggregated */ + MP_RX_AGGR_SETUP(card, skb, port); + + if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) || + MP_RX_AGGR_PORT_LIMIT_REACHED(card)) { + dev_dbg(adapter->dev, "info: %s: aggregated packet " + "limit reached\n", __func__); + /* No more pkts allowed in Aggr buf, rx it */ + f_do_rx_aggr = 1; + } + } + + if (f_do_rx_aggr) { + /* do aggr RX now */ + dev_dbg(adapter->dev, "info: do_rx_aggr: num of packets: %d\n", + card->mpa_rx.pkt_cnt); + + if (mwifiex_read_data_sync(adapter, card->mpa_rx.buf, + card->mpa_rx.buf_len, + (adapter->ioport | 0x1000 | + (card->mpa_rx.ports << 4)) + + card->mpa_rx.start_port, 0, 1)) + return -1; + + curr_ptr = card->mpa_rx.buf; + + for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) { + + /* get curr PKT len & type */ + pkt_len = *(u16 *) &curr_ptr[0]; + pkt_type = *(u16 *) &curr_ptr[2]; + + /* copy pkt to deaggr buf */ + skb_deaggr = card->mpa_rx.skb_arr[pind]; + + if ((pkt_type == MWIFIEX_TYPE_DATA) && (pkt_len <= + card->mpa_rx.len_arr[pind])) { + + memcpy(skb_deaggr->data, curr_ptr, pkt_len); + + skb_trim(skb_deaggr, pkt_len); + + /* Process de-aggr packet */ + mwifiex_decode_rx_packet(adapter, skb_deaggr, + pkt_type); + } else { + dev_err(adapter->dev, "wrong aggr pkt:" + " type=%d len=%d max_len=%d\n", + pkt_type, pkt_len, + card->mpa_rx.len_arr[pind]); + dev_kfree_skb_any(skb_deaggr); + } + curr_ptr += card->mpa_rx.len_arr[pind]; + } + MP_RX_AGGR_BUF_RESET(card); + } + +rx_curr_single: + if (f_do_rx_cur) { + dev_dbg(adapter->dev, "info: RX: port: %d, rx_len: %d\n", + port, rx_len); + + if (mwifiex_sdio_card_to_host(adapter, &pkt_type, + skb->data, skb->len, + adapter->ioport + port)) + return -1; + + mwifiex_decode_rx_packet(adapter, skb, pkt_type); + } + + return 0; +} + +/* + * This function checks the current interrupt status. + * + * The following interrupts are checked and handled by this function - + * - Data sent + * - Command sent + * - Packets received + * + * Since the firmware does not generate download ready interrupt if the + * port updated is command port only, command sent interrupt checking + * should be done manually, and for every SDIO interrupt. + * + * In case of Rx packets received, the packets are uploaded from card to + * host and processed accordingly. + */ +static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) +{ + struct sdio_mmc_card *card = adapter->card; + int ret = 0; + u8 sdio_ireg; + struct sk_buff *skb = NULL; + u8 port = CTRL_PORT; + u32 len_reg_l, len_reg_u; + u32 rx_blocks; + u16 rx_len; + unsigned long flags; + + spin_lock_irqsave(&adapter->int_lock, flags); + sdio_ireg = adapter->int_status; + adapter->int_status = 0; + spin_unlock_irqrestore(&adapter->int_lock, flags); + + if (!sdio_ireg) + return ret; + + if (sdio_ireg & DN_LD_HOST_INT_STATUS) { + card->mp_wr_bitmap = ((u16) card->mp_regs[WR_BITMAP_U]) << 8; + card->mp_wr_bitmap |= (u16) card->mp_regs[WR_BITMAP_L]; + dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%04x\n", + card->mp_wr_bitmap); + if (adapter->data_sent && + (card->mp_wr_bitmap & card->mp_data_port_mask)) { + dev_dbg(adapter->dev, + "info: <--- Tx DONE Interrupt --->\n"); + adapter->data_sent = false; + } + } + + /* As firmware will not generate download ready interrupt if the port + updated is command port only, cmd_sent should be done for any SDIO + interrupt. */ + if (adapter->cmd_sent) { + /* Check if firmware has attach buffer at command port and + update just that in wr_bit_map. */ + card->mp_wr_bitmap |= + (u16) card->mp_regs[WR_BITMAP_L] & CTRL_PORT_MASK; + if (card->mp_wr_bitmap & CTRL_PORT_MASK) + adapter->cmd_sent = false; + } + + dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n", + adapter->cmd_sent, adapter->data_sent); + if (sdio_ireg & UP_LD_HOST_INT_STATUS) { + card->mp_rd_bitmap = ((u16) card->mp_regs[RD_BITMAP_U]) << 8; + card->mp_rd_bitmap |= (u16) card->mp_regs[RD_BITMAP_L]; + dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%04x\n", + card->mp_rd_bitmap); + + while (true) { + ret = mwifiex_get_rd_port(adapter, &port); + if (ret) { + dev_dbg(adapter->dev, + "info: no more rd_port available\n"); + break; + } + len_reg_l = RD_LEN_P0_L + (port << 1); + len_reg_u = RD_LEN_P0_U + (port << 1); + rx_len = ((u16) card->mp_regs[len_reg_u]) << 8; + rx_len |= (u16) card->mp_regs[len_reg_l]; + dev_dbg(adapter->dev, "info: RX: port=%d rx_len=%u\n", + port, rx_len); + rx_blocks = + (rx_len + MWIFIEX_SDIO_BLOCK_SIZE - + 1) / MWIFIEX_SDIO_BLOCK_SIZE; + if (rx_len <= INTF_HEADER_LEN + || (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > + MWIFIEX_RX_DATA_BUF_SIZE) { + dev_err(adapter->dev, "invalid rx_len=%d\n", + rx_len); + return -1; + } + rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); + + skb = dev_alloc_skb(rx_len); + + if (!skb) { + dev_err(adapter->dev, "%s: failed to alloc skb", + __func__); + return -1; + } + + skb_put(skb, rx_len); + + dev_dbg(adapter->dev, "info: rx_len = %d skb->len = %d\n", + rx_len, skb->len); + + if (mwifiex_sdio_card_to_host_mp_aggr(adapter, skb, + port)) { + u32 cr = 0; + + dev_err(adapter->dev, "card_to_host_mpa failed:" + " int status=%#x\n", sdio_ireg); + if (mwifiex_read_reg(adapter, + CONFIGURATION_REG, &cr)) + dev_err(adapter->dev, + "read CFG reg failed\n"); + + dev_dbg(adapter->dev, + "info: CFG reg val = %d\n", cr); + if (mwifiex_write_reg(adapter, + CONFIGURATION_REG, + (cr | 0x04))) + dev_err(adapter->dev, + "write CFG reg failed\n"); + + dev_dbg(adapter->dev, "info: write success\n"); + if (mwifiex_read_reg(adapter, + CONFIGURATION_REG, &cr)) + dev_err(adapter->dev, + "read CFG reg failed\n"); + + dev_dbg(adapter->dev, + "info: CFG reg val =%x\n", cr); + dev_kfree_skb_any(skb); + return -1; + } + } + } + + return 0; +} + +/* + * This function aggregates transmission buffers in driver and downloads + * the aggregated packet to card. + * + * The individual packets are aggregated by copying into an aggregation + * buffer and then downloaded to the card. Previous unsent packets in the + * aggregation buffer are pre-copied first before new packets are added. + * Aggregation is done till there is space left in the aggregation buffer, + * or till new packets are available. + * + * The function will only download the packet to the card when aggregation + * stops, otherwise it will just aggregate the packet in aggregation buffer + * and return. + */ +static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, + u8 *payload, u32 pkt_len, u8 port, + u32 next_pkt_len) +{ + struct sdio_mmc_card *card = adapter->card; + int ret = 0; + s32 f_send_aggr_buf = 0; + s32 f_send_cur_buf = 0; + s32 f_precopy_cur_buf = 0; + s32 f_postcopy_cur_buf = 0; + + if ((!card->mpa_tx.enabled) || (port == CTRL_PORT)) { + dev_dbg(adapter->dev, "info: %s: tx aggregation disabled\n", + __func__); + + f_send_cur_buf = 1; + goto tx_curr_single; + } + + if (next_pkt_len) { + /* More pkt in TX queue */ + dev_dbg(adapter->dev, "info: %s: more packets in queue.\n", + __func__); + + if (MP_TX_AGGR_IN_PROGRESS(card)) { + if (!MP_TX_AGGR_PORT_LIMIT_REACHED(card) && + MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) { + f_precopy_cur_buf = 1; + + if (!(card->mp_wr_bitmap & + (1 << card->curr_wr_port)) + || !MP_TX_AGGR_BUF_HAS_ROOM( + card, next_pkt_len)) + f_send_aggr_buf = 1; + } else { + /* No room in Aggr buf, send it */ + f_send_aggr_buf = 1; + + if (MP_TX_AGGR_PORT_LIMIT_REACHED(card) || + !(card->mp_wr_bitmap & + (1 << card->curr_wr_port))) + f_send_cur_buf = 1; + else + f_postcopy_cur_buf = 1; + } + } else { + if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len) + && (card->mp_wr_bitmap & (1 << card->curr_wr_port))) + f_precopy_cur_buf = 1; + else + f_send_cur_buf = 1; + } + } else { + /* Last pkt in TX queue */ + dev_dbg(adapter->dev, "info: %s: Last packet in Tx Queue.\n", + __func__); + + if (MP_TX_AGGR_IN_PROGRESS(card)) { + /* some packs in Aggr buf already */ + f_send_aggr_buf = 1; + + if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) + f_precopy_cur_buf = 1; + else + /* No room in Aggr buf, send it */ + f_send_cur_buf = 1; + } else { + f_send_cur_buf = 1; + } + } + + if (f_precopy_cur_buf) { + dev_dbg(adapter->dev, "data: %s: precopy current buffer\n", + __func__); + MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port); + + if (MP_TX_AGGR_PKT_LIMIT_REACHED(card) || + MP_TX_AGGR_PORT_LIMIT_REACHED(card)) + /* No more pkts allowed in Aggr buf, send it */ + f_send_aggr_buf = 1; + } + + if (f_send_aggr_buf) { + dev_dbg(adapter->dev, "data: %s: send aggr buffer: %d %d\n", + __func__, + card->mpa_tx.start_port, card->mpa_tx.ports); + ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf, + card->mpa_tx.buf_len, + (adapter->ioport | 0x1000 | + (card->mpa_tx.ports << 4)) + + card->mpa_tx.start_port); + + MP_TX_AGGR_BUF_RESET(card); + } + +tx_curr_single: + if (f_send_cur_buf) { + dev_dbg(adapter->dev, "data: %s: send current buffer %d\n", + __func__, port); + ret = mwifiex_write_data_to_card(adapter, payload, pkt_len, + adapter->ioport + port); + } + + if (f_postcopy_cur_buf) { + dev_dbg(adapter->dev, "data: %s: postcopy current buffer\n", + __func__); + MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port); + } + + return ret; +} + +/* + * This function downloads data from driver to card. + * + * Both commands and data packets are transferred to the card by this + * function. + * + * This function adds the SDIO specific header to the front of the buffer + * before transferring. The header contains the length of the packet and + * the type. The firmware handles the packets based upon this set type. + */ +static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, + u8 type, u8 *payload, u32 pkt_len, + struct mwifiex_tx_param *tx_param) +{ + struct sdio_mmc_card *card = adapter->card; + int ret = 0; + u32 buf_block_len; + u32 blk_size; + u8 port = CTRL_PORT; + + /* Allocate buffer and copy payload */ + blk_size = MWIFIEX_SDIO_BLOCK_SIZE; + buf_block_len = (pkt_len + blk_size - 1) / blk_size; + *(u16 *) &payload[0] = (u16) pkt_len; + *(u16 *) &payload[2] = type; + + /* + * This is SDIO specific header + * u16 length, + * u16 type (MWIFIEX_TYPE_DATA = 0, MWIFIEX_TYPE_CMD = 1, + * MWIFIEX_TYPE_EVENT = 3) + */ + if (type == MWIFIEX_TYPE_DATA) { + ret = mwifiex_get_wr_port_data(adapter, &port); + if (ret) { + dev_err(adapter->dev, "%s: no wr_port available\n", + __func__); + return ret; + } + } else { + adapter->cmd_sent = true; + /* Type must be MWIFIEX_TYPE_CMD */ + + if (pkt_len <= INTF_HEADER_LEN || + pkt_len > MWIFIEX_UPLD_SIZE) + dev_err(adapter->dev, "%s: payload=%p, nb=%d\n", + __func__, payload, pkt_len); + } + + /* Transfer data to card */ + pkt_len = buf_block_len * blk_size; + + if (tx_param) + ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len, + port, tx_param->next_pkt_len); + else + ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len, + port, 0); + + if (ret) { + if (type == MWIFIEX_TYPE_CMD) + adapter->cmd_sent = false; + if (type == MWIFIEX_TYPE_DATA) + adapter->data_sent = false; + } else { + if (type == MWIFIEX_TYPE_DATA) { + if (!(card->mp_wr_bitmap & (1 << card->curr_wr_port))) + adapter->data_sent = true; + else + adapter->data_sent = false; + } + } + + return ret; +} + +/* + * This function allocates the MPA Tx and Rx buffers. + */ +static int mwifiex_alloc_sdio_mpa_buffers(struct mwifiex_adapter *adapter, + u32 mpa_tx_buf_size, u32 mpa_rx_buf_size) +{ + struct sdio_mmc_card *card = adapter->card; + int ret = 0; + + card->mpa_tx.buf = kzalloc(mpa_tx_buf_size, GFP_KERNEL); + if (!card->mpa_tx.buf) { + dev_err(adapter->dev, "could not alloc buffer for MP-A TX\n"); + ret = -1; + goto error; + } + + card->mpa_tx.buf_size = mpa_tx_buf_size; + + card->mpa_rx.buf = kzalloc(mpa_rx_buf_size, GFP_KERNEL); + if (!card->mpa_rx.buf) { + dev_err(adapter->dev, "could not alloc buffer for MP-A RX\n"); + ret = -1; + goto error; + } + + card->mpa_rx.buf_size = mpa_rx_buf_size; + +error: + if (ret) { + kfree(card->mpa_tx.buf); + kfree(card->mpa_rx.buf); + } + + return ret; +} + +/* + * This function unregisters the SDIO device. + * + * The SDIO IRQ is released, the function is disabled and driver + * data is set to null. + */ +static void +mwifiex_unregister_dev(struct mwifiex_adapter *adapter) +{ + struct sdio_mmc_card *card = adapter->card; + + if (adapter->card) { + /* Release the SDIO IRQ */ + sdio_claim_host(card->func); + sdio_release_irq(card->func); + sdio_disable_func(card->func); + sdio_release_host(card->func); + sdio_set_drvdata(card->func, NULL); + } +} + +/* + * This function registers the SDIO device. + * + * SDIO IRQ is claimed, block size is set and driver data is initialized. + */ +static int mwifiex_register_dev(struct mwifiex_adapter *adapter) +{ + int ret = 0; + struct sdio_mmc_card *card = adapter->card; + struct sdio_func *func = card->func; + + /* save adapter pointer in card */ + card->adapter = adapter; + + sdio_claim_host(func); + + /* Request the SDIO IRQ */ + ret = sdio_claim_irq(func, mwifiex_sdio_interrupt); + if (ret) { + pr_err("claim irq failed: ret=%d\n", ret); + goto disable_func; + } + + /* Set block size */ + ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE); + if (ret) { + pr_err("cannot set SDIO block size\n"); + ret = -1; + goto release_irq; + } + + sdio_release_host(func); + sdio_set_drvdata(func, card); + + adapter->dev = &func->dev; + + return 0; + +release_irq: + sdio_release_irq(func); +disable_func: + sdio_disable_func(func); + sdio_release_host(func); + adapter->card = NULL; + + return -1; +} + +/* + * This function initializes the SDIO driver. + * + * The following initializations steps are followed - + * - Read the Host interrupt status register to acknowledge + * the first interrupt got from bootloader + * - Disable host interrupt mask register + * - Get SDIO port + * - Get revision ID + * - Initialize SDIO variables in card + * - Allocate MP registers + * - Allocate MPA Tx and Rx buffers + */ +static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) +{ + struct sdio_mmc_card *card = adapter->card; + int ret; + u32 sdio_ireg = 0; + + /* + * Read the HOST_INT_STATUS_REG for ACK the first interrupt got + * from the bootloader. If we don't do this we get a interrupt + * as soon as we register the irq. + */ + mwifiex_read_reg(adapter, HOST_INTSTATUS_REG, &sdio_ireg); + + /* Disable host interrupt mask register for SDIO */ + mwifiex_sdio_disable_host_int(adapter); + + /* Get SDIO ioport */ + mwifiex_init_sdio_ioport(adapter); + + /* Get revision ID */ +#define REV_ID_REG 0x5c + mwifiex_read_reg(adapter, REV_ID_REG, &adapter->revision_id); + + /* Initialize SDIO variables in card */ + card->mp_rd_bitmap = 0; + card->mp_wr_bitmap = 0; + card->curr_rd_port = 1; + card->curr_wr_port = 1; + + card->mp_data_port_mask = DATA_PORT_MASK; + + card->mpa_tx.buf_len = 0; + card->mpa_tx.pkt_cnt = 0; + card->mpa_tx.start_port = 0; + + card->mpa_tx.enabled = 0; + card->mpa_tx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT; + + card->mpa_rx.buf_len = 0; + card->mpa_rx.pkt_cnt = 0; + card->mpa_rx.start_port = 0; + + card->mpa_rx.enabled = 0; + card->mpa_rx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT; + + /* Allocate buffers for SDIO MP-A */ + card->mp_regs = kzalloc(MAX_MP_REGS, GFP_KERNEL); + if (!card->mp_regs) { + dev_err(adapter->dev, "failed to alloc mp_regs\n"); + return -1; + } + + ret = mwifiex_alloc_sdio_mpa_buffers(adapter, + SDIO_MP_TX_AGGR_DEF_BUF_SIZE, + SDIO_MP_RX_AGGR_DEF_BUF_SIZE); + if (ret) { + dev_err(adapter->dev, "failed to alloc sdio mp-a buffers\n"); + kfree(card->mp_regs); + return -1; + } + + return ret; +} + +/* + * This function resets the MPA Tx and Rx buffers. + */ +static void mwifiex_cleanup_mpa_buf(struct mwifiex_adapter *adapter) +{ + struct sdio_mmc_card *card = adapter->card; + + MP_TX_AGGR_BUF_RESET(card); + MP_RX_AGGR_BUF_RESET(card); +} + +/* + * This function cleans up the allocated card buffers. + * + * The following are freed by this function - + * - MP registers + * - MPA Tx buffer + * - MPA Rx buffer + */ +static void mwifiex_cleanup_sdio(struct mwifiex_adapter *adapter) +{ + struct sdio_mmc_card *card = adapter->card; + + kfree(card->mp_regs); + kfree(card->mpa_tx.buf); + kfree(card->mpa_rx.buf); +} + +/* + * This function updates the MP end port in card. + */ +static void +mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port) +{ + struct sdio_mmc_card *card = adapter->card; + int i; + + card->mp_end_port = port; + + card->mp_data_port_mask = DATA_PORT_MASK; + + for (i = 1; i <= MAX_PORT - card->mp_end_port; i++) + card->mp_data_port_mask &= ~(1 << (MAX_PORT - i)); + + card->curr_wr_port = 1; + + dev_dbg(adapter->dev, "cmd: mp_end_port %d, data port mask 0x%x\n", + port, card->mp_data_port_mask); +} + +static struct mwifiex_if_ops sdio_ops = { + .init_if = mwifiex_init_sdio, + .cleanup_if = mwifiex_cleanup_sdio, + .check_fw_status = mwifiex_check_fw_status, + .prog_fw = mwifiex_prog_fw_w_helper, + .register_dev = mwifiex_register_dev, + .unregister_dev = mwifiex_unregister_dev, + .enable_int = mwifiex_sdio_enable_host_int, + .process_int_status = mwifiex_process_int_status, + .host_to_card = mwifiex_sdio_host_to_card, + .wakeup = mwifiex_pm_wakeup_card, + .wakeup_complete = mwifiex_pm_wakeup_card_complete, + + /* SDIO specific */ + .update_mp_end_port = mwifiex_update_mp_end_port, + .cleanup_mpa_buf = mwifiex_cleanup_mpa_buf, +}; + +/* + * This function initializes the SDIO driver. + * + * This initiates the semaphore and registers the device with + * SDIO bus. + */ +static int +mwifiex_sdio_init_module(void) +{ + int ret; + + sema_init(&add_remove_card_sem, 1); + + ret = sdio_register_driver(&mwifiex_sdio); + + return ret; +} + +/* + * This function cleans up the SDIO driver. + * + * The following major steps are followed for cleanup - + * - Resume the device if its suspended + * - Disconnect the device if connected + * - Shutdown the firmware + * - Unregister the device from SDIO bus. + */ +static void +mwifiex_sdio_cleanup_module(void) +{ + struct mwifiex_adapter *adapter = g_adapter; + int i; + + if (down_interruptible(&add_remove_card_sem)) + goto exit_sem_err; + + if (!adapter || !adapter->priv_num) + goto exit; + + if (adapter->is_suspended) + mwifiex_sdio_resume(adapter->dev); + + for (i = 0; i < adapter->priv_num; i++) + if ((GET_BSS_ROLE(adapter->priv[i]) == MWIFIEX_BSS_ROLE_STA) && + adapter->priv[i]->media_connected) + mwifiex_disconnect(adapter->priv[i], MWIFIEX_CMD_WAIT, + NULL); + + if (!adapter->surprise_removed) + mwifiex_shutdown_fw(mwifiex_get_priv + (adapter, MWIFIEX_BSS_ROLE_ANY), + MWIFIEX_CMD_WAIT); + +exit: + up(&add_remove_card_sem); + +exit_sem_err: + sdio_unregister_driver(&mwifiex_sdio); +} + +module_init(mwifiex_sdio_init_module); +module_exit(mwifiex_sdio_cleanup_module); + +MODULE_AUTHOR("Marvell International Ltd."); +MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION); +MODULE_VERSION(SDIO_VERSION); +MODULE_LICENSE("GPL v2"); +MODULE_FIRMWARE("sd8787.bin"); diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h new file mode 100644 index 000000000000..a0e9bc5253e0 --- /dev/null +++ b/drivers/net/wireless/mwifiex/sdio.h @@ -0,0 +1,305 @@ +/* + * Marvell Wireless LAN device driver: SDIO specific definitions + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#ifndef _MWIFIEX_SDIO_H +#define _MWIFIEX_SDIO_H + + +#include +#include +#include +#include + +#include "main.h" + +#define BLOCK_MODE 1 +#define BYTE_MODE 0 + +#define REG_PORT 0 +#define RD_BITMAP_L 0x04 +#define RD_BITMAP_U 0x05 +#define WR_BITMAP_L 0x06 +#define WR_BITMAP_U 0x07 +#define RD_LEN_P0_L 0x08 +#define RD_LEN_P0_U 0x09 + +#define MWIFIEX_SDIO_IO_PORT_MASK 0xfffff + +#define MWIFIEX_SDIO_BYTE_MODE_MASK 0x80000000 + +#define CTRL_PORT 0 +#define CTRL_PORT_MASK 0x0001 +#define DATA_PORT_MASK 0xfffe + +#define MAX_MP_REGS 64 +#define MAX_PORT 16 + +#define SDIO_MP_AGGR_DEF_PKT_LIMIT 8 + +#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE (4096) /* 4K */ + +/* Multi port RX aggregation buffer size */ +#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE (4096) /* 4K */ + +/* Misc. Config Register : Auto Re-enable interrupts */ +#define AUTO_RE_ENABLE_INT BIT(4) + +/* Host Control Registers */ +/* Host Control Registers : I/O port 0 */ +#define IO_PORT_0_REG 0x78 +/* Host Control Registers : I/O port 1 */ +#define IO_PORT_1_REG 0x79 +/* Host Control Registers : I/O port 2 */ +#define IO_PORT_2_REG 0x7A + +/* Host Control Registers : Configuration */ +#define CONFIGURATION_REG 0x00 +/* Host Control Registers : Host without Command 53 finish host*/ +#define HOST_TO_CARD_EVENT (0x1U << 3) +/* Host Control Registers : Host without Command 53 finish host */ +#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2) +/* Host Control Registers : Host power up */ +#define HOST_POWER_UP (0x1U << 1) +/* Host Control Registers : Host power down */ +#define HOST_POWER_DOWN (0x1U << 0) + +/* Host Control Registers : Host interrupt mask */ +#define HOST_INT_MASK_REG 0x02 +/* Host Control Registers : Upload host interrupt mask */ +#define UP_LD_HOST_INT_MASK (0x1U) +/* Host Control Registers : Download host interrupt mask */ +#define DN_LD_HOST_INT_MASK (0x2U) +/* Enable Host interrupt mask */ +#define HOST_INT_ENABLE (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK) +/* Disable Host interrupt mask */ +#define HOST_INT_DISABLE 0xff + +/* Host Control Registers : Host interrupt status */ +#define HOST_INTSTATUS_REG 0x03 +/* Host Control Registers : Upload host interrupt status */ +#define UP_LD_HOST_INT_STATUS (0x1U) +/* Host Control Registers : Download host interrupt status */ +#define DN_LD_HOST_INT_STATUS (0x2U) + +/* Host Control Registers : Host interrupt RSR */ +#define HOST_INT_RSR_REG 0x01 +/* Host Control Registers : Upload host interrupt RSR */ +#define UP_LD_HOST_INT_RSR (0x1U) +#define SDIO_INT_MASK 0x3F + +/* Host Control Registers : Host interrupt status */ +#define HOST_INT_STATUS_REG 0x28 +/* Host Control Registers : Upload CRC error */ +#define UP_LD_CRC_ERR (0x1U << 2) +/* Host Control Registers : Upload restart */ +#define UP_LD_RESTART (0x1U << 1) +/* Host Control Registers : Download restart */ +#define DN_LD_RESTART (0x1U << 0) + +/* Card Control Registers : Card status register */ +#define CARD_STATUS_REG 0x30 +/* Card Control Registers : Card I/O ready */ +#define CARD_IO_READY (0x1U << 3) +/* Card Control Registers : CIS card ready */ +#define CIS_CARD_RDY (0x1U << 2) +/* Card Control Registers : Upload card ready */ +#define UP_LD_CARD_RDY (0x1U << 1) +/* Card Control Registers : Download card ready */ +#define DN_LD_CARD_RDY (0x1U << 0) + +/* Card Control Registers : Host interrupt mask register */ +#define HOST_INTERRUPT_MASK_REG 0x34 +/* Card Control Registers : Host power interrupt mask */ +#define HOST_POWER_INT_MASK (0x1U << 3) +/* Card Control Registers : Abort card interrupt mask */ +#define ABORT_CARD_INT_MASK (0x1U << 2) +/* Card Control Registers : Upload card interrupt mask */ +#define UP_LD_CARD_INT_MASK (0x1U << 1) +/* Card Control Registers : Download card interrupt mask */ +#define DN_LD_CARD_INT_MASK (0x1U << 0) + +/* Card Control Registers : Card interrupt status register */ +#define CARD_INTERRUPT_STATUS_REG 0x38 +/* Card Control Registers : Power up interrupt */ +#define POWER_UP_INT (0x1U << 4) +/* Card Control Registers : Power down interrupt */ +#define POWER_DOWN_INT (0x1U << 3) + +/* Card Control Registers : Card interrupt RSR register */ +#define CARD_INTERRUPT_RSR_REG 0x3c +/* Card Control Registers : Power up RSR */ +#define POWER_UP_RSR (0x1U << 4) +/* Card Control Registers : Power down RSR */ +#define POWER_DOWN_RSR (0x1U << 3) + +/* Card Control Registers : Miscellaneous Configuration Register */ +#define CARD_MISC_CFG_REG 0x6C + +/* Host F1 read base 0 */ +#define HOST_F1_RD_BASE_0 0x0040 +/* Host F1 read base 1 */ +#define HOST_F1_RD_BASE_1 0x0041 +/* Host F1 card ready */ +#define HOST_F1_CARD_RDY 0x0020 + +/* Firmware status 0 register */ +#define CARD_FW_STATUS0_REG 0x60 +/* Firmware status 1 register */ +#define CARD_FW_STATUS1_REG 0x61 +/* Rx length register */ +#define CARD_RX_LEN_REG 0x62 +/* Rx unit register */ +#define CARD_RX_UNIT_REG 0x63 + +/* Event header Len*/ +#define MWIFIEX_EVENT_HEADER_LEN 8 + +/* Max retry number of CMD53 write */ +#define MAX_WRITE_IOMEM_RETRY 2 + +/* SDIO Tx aggregation in progress ? */ +#define MP_TX_AGGR_IN_PROGRESS(a) (a->mpa_tx.pkt_cnt > 0) + +/* SDIO Tx aggregation buffer room for next packet ? */ +#define MP_TX_AGGR_BUF_HAS_ROOM(a, len) ((a->mpa_tx.buf_len+len) \ + <= a->mpa_tx.buf_size) + +/* Copy current packet (SDIO Tx aggregation buffer) to SDIO buffer */ +#define MP_TX_AGGR_BUF_PUT(a, payload, pkt_len, port) do { \ + memmove(&a->mpa_tx.buf[a->mpa_tx.buf_len], \ + payload, pkt_len); \ + a->mpa_tx.buf_len += pkt_len; \ + if (!a->mpa_tx.pkt_cnt) \ + a->mpa_tx.start_port = port; \ + if (a->mpa_tx.start_port <= port) \ + a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt)); \ + else \ + a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt+1+(MAX_PORT - \ + a->mp_end_port))); \ + a->mpa_tx.pkt_cnt++; \ +} while (0); + +/* SDIO Tx aggregation limit ? */ +#define MP_TX_AGGR_PKT_LIMIT_REACHED(a) \ + (a->mpa_tx.pkt_cnt == a->mpa_tx.pkt_aggr_limit) + +/* SDIO Tx aggregation port limit ? */ +#define MP_TX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_wr_port < \ + a->mpa_tx.start_port) && (((MAX_PORT - \ + a->mpa_tx.start_port) + a->curr_wr_port) >= \ + SDIO_MP_AGGR_DEF_PKT_LIMIT)) + +/* Reset SDIO Tx aggregation buffer parameters */ +#define MP_TX_AGGR_BUF_RESET(a) do { \ + a->mpa_tx.pkt_cnt = 0; \ + a->mpa_tx.buf_len = 0; \ + a->mpa_tx.ports = 0; \ + a->mpa_tx.start_port = 0; \ +} while (0); + +/* SDIO Rx aggregation limit ? */ +#define MP_RX_AGGR_PKT_LIMIT_REACHED(a) \ + (a->mpa_rx.pkt_cnt == a->mpa_rx.pkt_aggr_limit) + +/* SDIO Tx aggregation port limit ? */ +#define MP_RX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_rd_port < \ + a->mpa_rx.start_port) && (((MAX_PORT - \ + a->mpa_rx.start_port) + a->curr_rd_port) >= \ + SDIO_MP_AGGR_DEF_PKT_LIMIT)) + +/* SDIO Rx aggregation in progress ? */ +#define MP_RX_AGGR_IN_PROGRESS(a) (a->mpa_rx.pkt_cnt > 0) + +/* SDIO Rx aggregation buffer room for next packet ? */ +#define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len) \ + ((a->mpa_rx.buf_len+rx_len) <= a->mpa_rx.buf_size) + +/* Prepare to copy current packet from card to SDIO Rx aggregation buffer */ +#define MP_RX_AGGR_SETUP(a, skb, port) do { \ + a->mpa_rx.buf_len += skb->len; \ + if (!a->mpa_rx.pkt_cnt) \ + a->mpa_rx.start_port = port; \ + if (a->mpa_rx.start_port <= port) \ + a->mpa_rx.ports |= (1<<(a->mpa_rx.pkt_cnt)); \ + else \ + a->mpa_rx.ports |= (1<<(a->mpa_rx.pkt_cnt+1)); \ + a->mpa_rx.skb_arr[a->mpa_rx.pkt_cnt] = skb; \ + a->mpa_rx.len_arr[a->mpa_rx.pkt_cnt] = skb->len; \ + a->mpa_rx.pkt_cnt++; \ +} while (0); + +/* Reset SDIO Rx aggregation buffer parameters */ +#define MP_RX_AGGR_BUF_RESET(a) do { \ + a->mpa_rx.pkt_cnt = 0; \ + a->mpa_rx.buf_len = 0; \ + a->mpa_rx.ports = 0; \ + a->mpa_rx.start_port = 0; \ +} while (0); + + +/* data structure for SDIO MPA TX */ +struct mwifiex_sdio_mpa_tx { + /* multiport tx aggregation buffer pointer */ + u8 *buf; + u32 buf_len; + u32 pkt_cnt; + u16 ports; + u16 start_port; + u8 enabled; + u32 buf_size; + u32 pkt_aggr_limit; +}; + +struct mwifiex_sdio_mpa_rx { + u8 *buf; + u32 buf_len; + u32 pkt_cnt; + u16 ports; + u16 start_port; + + struct sk_buff *skb_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT]; + u32 len_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT]; + + u8 enabled; + u32 buf_size; + u32 pkt_aggr_limit; +}; + +int mwifiex_bus_register(void); +void mwifiex_bus_unregister(void); + +struct sdio_mmc_card { + struct sdio_func *func; + struct mwifiex_adapter *adapter; + + u16 mp_rd_bitmap; + u16 mp_wr_bitmap; + + u16 mp_end_port; + u16 mp_data_port_mask; + + u8 curr_rd_port; + u8 curr_wr_port; + + u8 *mp_regs; + + struct mwifiex_sdio_mpa_tx mpa_tx; + struct mwifiex_sdio_mpa_rx mpa_rx; +}; +#endif /* _MWIFIEX_SDIO_H */ diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c new file mode 100644 index 000000000000..795b1eae768d --- /dev/null +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -0,0 +1,1226 @@ +/* + * Marvell Wireless LAN device driver: station command handling + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" + +/* + * This function prepares command to set/get RSSI information. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting data/beacon average factors + * - Resetting SNR/NF/RSSI values in private structure + * - Ensuring correct endian-ness + */ +static int +mwifiex_cmd_802_11_rssi_info(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, u16 cmd_action) +{ + cmd->command = cpu_to_le16(HostCmd_CMD_RSSI_INFO); + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info) + + S_DS_GEN); + cmd->params.rssi_info.action = cpu_to_le16(cmd_action); + cmd->params.rssi_info.ndata = cpu_to_le16(priv->data_avg_factor); + cmd->params.rssi_info.nbcn = cpu_to_le16(priv->bcn_avg_factor); + + /* Reset SNR/NF/RSSI values in private structure */ + priv->data_rssi_last = 0; + priv->data_nf_last = 0; + priv->data_rssi_avg = 0; + priv->data_nf_avg = 0; + priv->bcn_rssi_last = 0; + priv->bcn_nf_last = 0; + priv->bcn_rssi_avg = 0; + priv->bcn_nf_avg = 0; + + return 0; +} + +/* + * This function prepares command to set MAC control. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_mac_control(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, void *data_buf) +{ + struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl; + u16 action = *((u16 *) data_buf); + + if (cmd_action != HostCmd_ACT_GEN_SET) { + dev_err(priv->adapter->dev, + "mac_control: only support set cmd\n"); + return -1; + } + + cmd->command = cpu_to_le16(HostCmd_CMD_MAC_CONTROL); + cmd->size = + cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN); + mac_ctrl->action = cpu_to_le16(action); + + return 0; +} + +/* + * This function prepares command to set/get SNMP MIB. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting SNMP MIB OID number and value + * (as required) + * - Ensuring correct endian-ness + * + * The following SNMP MIB OIDs are supported - + * - FRAG_THRESH_I : Fragmentation threshold + * - RTS_THRESH_I : RTS threshold + * - SHORT_RETRY_LIM_I : Short retry limit + * - DOT11D_I : 11d support + */ +static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, u32 cmd_oid, + void *data_buf) +{ + struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib; + u32 ul_temp; + + dev_dbg(priv->adapter->dev, "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid); + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB); + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib) + - 1 + S_DS_GEN); + + if (cmd_action == HostCmd_ACT_GEN_GET) { + snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_GET); + snmp_mib->buf_size = cpu_to_le16(MAX_SNMP_BUF_SIZE); + cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) + + MAX_SNMP_BUF_SIZE); + } + + switch (cmd_oid) { + case FRAG_THRESH_I: + snmp_mib->oid = cpu_to_le16((u16) FRAG_THRESH_I); + if (cmd_action == HostCmd_ACT_GEN_SET) { + snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); + snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); + ul_temp = *((u32 *) data_buf); + *((__le16 *) (snmp_mib->value)) = + cpu_to_le16((u16) ul_temp); + cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) + + sizeof(u16)); + } + break; + case RTS_THRESH_I: + snmp_mib->oid = cpu_to_le16((u16) RTS_THRESH_I); + if (cmd_action == HostCmd_ACT_GEN_SET) { + snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); + snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); + ul_temp = *((u32 *) data_buf); + *(__le16 *) (snmp_mib->value) = + cpu_to_le16((u16) ul_temp); + cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) + + sizeof(u16)); + } + break; + + case SHORT_RETRY_LIM_I: + snmp_mib->oid = cpu_to_le16((u16) SHORT_RETRY_LIM_I); + if (cmd_action == HostCmd_ACT_GEN_SET) { + snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); + snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); + ul_temp = (*(u32 *) data_buf); + *((__le16 *) (snmp_mib->value)) = + cpu_to_le16((u16) ul_temp); + cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) + + sizeof(u16)); + } + break; + case DOT11D_I: + snmp_mib->oid = cpu_to_le16((u16) DOT11D_I); + if (cmd_action == HostCmd_ACT_GEN_SET) { + snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); + snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); + ul_temp = *(u32 *) data_buf; + *((__le16 *) (snmp_mib->value)) = + cpu_to_le16((u16) ul_temp); + cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) + + sizeof(u16)); + } + break; + default: + break; + } + dev_dbg(priv->adapter->dev, + "cmd: SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x," + " Value=0x%x\n", + cmd_action, cmd_oid, le16_to_cpu(snmp_mib->buf_size), + le16_to_cpu(*(__le16 *) snmp_mib->value)); + return 0; +} + +/* + * This function prepares command to get log. + * + * Preparation includes - + * - Setting command ID and proper size + * - Ensuring correct endian-ness + */ +static int +mwifiex_cmd_802_11_get_log(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd) +{ + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_GET_LOG); + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log) + + S_DS_GEN); + return 0; +} + +/* + * This function prepares command to set/get Tx data rate configuration. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting configuration index, rate scope and rate drop pattern + * parameters (as required) + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, void *data_buf) +{ + struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg; + struct mwifiex_rate_scope *rate_scope; + struct mwifiex_rate_drop_pattern *rate_drop; + u16 *pbitmap_rates = (u16 *) data_buf; + + u32 i; + + cmd->command = cpu_to_le16(HostCmd_CMD_TX_RATE_CFG); + + rate_cfg->action = cpu_to_le16(cmd_action); + rate_cfg->cfg_index = 0; + + rate_scope = (struct mwifiex_rate_scope *) ((u8 *) rate_cfg + + sizeof(struct host_cmd_ds_tx_rate_cfg)); + rate_scope->type = cpu_to_le16(TLV_TYPE_RATE_SCOPE); + rate_scope->length = cpu_to_le16(sizeof(struct mwifiex_rate_scope) - + sizeof(struct mwifiex_ie_types_header)); + if (pbitmap_rates != NULL) { + rate_scope->hr_dsss_rate_bitmap = cpu_to_le16(pbitmap_rates[0]); + rate_scope->ofdm_rate_bitmap = cpu_to_le16(pbitmap_rates[1]); + for (i = 0; + i < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(u16); + i++) + rate_scope->ht_mcs_rate_bitmap[i] = + cpu_to_le16(pbitmap_rates[2 + i]); + } else { + rate_scope->hr_dsss_rate_bitmap = + cpu_to_le16(priv->bitmap_rates[0]); + rate_scope->ofdm_rate_bitmap = + cpu_to_le16(priv->bitmap_rates[1]); + for (i = 0; + i < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(u16); + i++) + rate_scope->ht_mcs_rate_bitmap[i] = + cpu_to_le16(priv->bitmap_rates[2 + i]); + } + + rate_drop = (struct mwifiex_rate_drop_pattern *) ((u8 *) rate_scope + + sizeof(struct mwifiex_rate_scope)); + rate_drop->type = cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL); + rate_drop->length = cpu_to_le16(sizeof(rate_drop->rate_drop_mode)); + rate_drop->rate_drop_mode = 0; + + cmd->size = + cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_tx_rate_cfg) + + sizeof(struct mwifiex_rate_scope) + + sizeof(struct mwifiex_rate_drop_pattern)); + + return 0; +} + +/* + * This function prepares command to set/get Tx power configuration. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting Tx power mode, power group TLV + * (as required) + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_tx_power_cfg(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, void *data_buf) +{ + struct mwifiex_types_power_group *pg_tlv = NULL; + struct host_cmd_ds_txpwr_cfg *txp = NULL; + struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg; + + cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG); + cmd->size = + cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg)); + switch (cmd_action) { + case HostCmd_ACT_GEN_SET: + txp = (struct host_cmd_ds_txpwr_cfg *) data_buf; + if (txp->mode) { + pg_tlv = (struct mwifiex_types_power_group + *) ((unsigned long) data_buf + + sizeof(struct host_cmd_ds_txpwr_cfg)); + memmove(cmd_txp_cfg, data_buf, + sizeof(struct host_cmd_ds_txpwr_cfg) + + sizeof(struct mwifiex_types_power_group) + + pg_tlv->length); + + pg_tlv = (struct mwifiex_types_power_group *) ((u8 *) + cmd_txp_cfg + + sizeof(struct host_cmd_ds_txpwr_cfg)); + cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) + + sizeof(struct mwifiex_types_power_group) + + pg_tlv->length); + } else { + memmove(cmd_txp_cfg, data_buf, + sizeof(struct host_cmd_ds_txpwr_cfg)); + } + cmd_txp_cfg->action = cpu_to_le16(cmd_action); + break; + case HostCmd_ACT_GEN_GET: + cmd_txp_cfg->action = cpu_to_le16(cmd_action); + break; + } + + return 0; +} + +/* + * This function prepares command to set Host Sleep configuration. + * + * Preparation includes - + * - Setting command ID and proper size + * - Setting Host Sleep action, conditions, ARP filters + * (as required) + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, + struct mwifiex_hs_config_param *data_buf) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg; + u16 hs_activate = false; + + if (data_buf == NULL) + /* New Activate command */ + hs_activate = true; + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); + + if (!hs_activate && + (data_buf->conditions + != cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) + && ((adapter->arp_filter_size > 0) + && (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { + dev_dbg(adapter->dev, + "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n", + adapter->arp_filter_size); + memcpy(((u8 *) hs_cfg) + + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh), + adapter->arp_filter, adapter->arp_filter_size); + cmd->size = cpu_to_le16(adapter->arp_filter_size + + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh) + + S_DS_GEN); + } else { + cmd->size = cpu_to_le16(S_DS_GEN + sizeof(struct + host_cmd_ds_802_11_hs_cfg_enh)); + } + if (hs_activate) { + hs_cfg->action = cpu_to_le16(HS_ACTIVATE); + hs_cfg->params.hs_activate.resp_ctrl = RESP_NEEDED; + } else { + hs_cfg->action = cpu_to_le16(HS_CONFIGURE); + hs_cfg->params.hs_config.conditions = data_buf->conditions; + hs_cfg->params.hs_config.gpio = data_buf->gpio; + hs_cfg->params.hs_config.gap = data_buf->gap; + dev_dbg(adapter->dev, + "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n", + hs_cfg->params.hs_config.conditions, + hs_cfg->params.hs_config.gpio, + hs_cfg->params.hs_config.gap); + } + + return 0; +} + +/* + * This function prepares command to set/get MAC address. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting MAC address (for SET only) + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action) +{ + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS); + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address) + + S_DS_GEN); + cmd->result = 0; + + cmd->params.mac_addr.action = cpu_to_le16(cmd_action); + + if (cmd_action == HostCmd_ACT_GEN_SET) + memcpy(cmd->params.mac_addr.mac_addr, priv->curr_addr, + ETH_ALEN); + return 0; +} + +/* + * This function prepares command to set MAC multicast address. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting MAC multicast address + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_mac_multicast_adr(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, void *data_buf) +{ + struct mwifiex_multicast_list *mcast_list = + (struct mwifiex_multicast_list *) data_buf; + struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr; + + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) + + S_DS_GEN); + cmd->command = cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR); + + mcast_addr->action = cpu_to_le16(cmd_action); + mcast_addr->num_of_adrs = + cpu_to_le16((u16) mcast_list->num_multicast_addr); + memcpy(mcast_addr->mac_list, mcast_list->mac_list, + mcast_list->num_multicast_addr * ETH_ALEN); + + return 0; +} + +/* + * This function prepares command to deauthenticate. + * + * Preparation includes - + * - Setting command ID and proper size + * - Setting AP MAC address and reason code + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf) +{ + struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth; + + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_DEAUTHENTICATE); + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate) + + S_DS_GEN); + + /* Set AP MAC address */ + memcpy(deauth->mac_addr, (u8 *) data_buf, ETH_ALEN); + + dev_dbg(priv->adapter->dev, "cmd: Deauth: %pM\n", deauth->mac_addr); + + deauth->reason_code = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING); + + return 0; +} + +/* + * This function prepares command to stop Ad-Hoc network. + * + * Preparation includes - + * - Setting command ID and proper size + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_802_11_ad_hoc_stop(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd) +{ + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP); + cmd->size = cpu_to_le16(S_DS_GEN); + return 0; +} + +/* + * This function sets WEP key(s) to key parameter TLV(s). + * + * Multi-key parameter TLVs are supported, so we can send multiple + * WEP keys in a single buffer. + */ +static int +mwifiex_set_keyparamset_wep(struct mwifiex_private *priv, + struct mwifiex_ie_type_key_param_set *key_param_set, + u16 *key_param_len) +{ + int cur_key_param_len = 0; + u8 i; + + /* Multi-key_param_set TLV is supported */ + for (i = 0; i < NUM_WEP_KEYS; i++) { + if ((priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP40) || + (priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP104)) { + key_param_set->type = + cpu_to_le16(TLV_TYPE_KEY_MATERIAL); +/* Key_param_set WEP fixed length */ +#define KEYPARAMSET_WEP_FIXED_LEN 8 + key_param_set->length = cpu_to_le16((u16) + (priv->wep_key[i]. + key_length + + KEYPARAMSET_WEP_FIXED_LEN)); + key_param_set->key_type_id = + cpu_to_le16(KEY_TYPE_ID_WEP); + key_param_set->key_info = + cpu_to_le16(KEY_INFO_WEP_ENABLED | + KEY_INFO_WEP_UNICAST | + KEY_INFO_WEP_MCAST); + key_param_set->key_len = + cpu_to_le16(priv->wep_key[i].key_length); + /* Set WEP key index */ + key_param_set->key[0] = i; + /* Set default Tx key flag */ + if (i == + (priv-> + wep_key_curr_index & HostCmd_WEP_KEY_INDEX_MASK)) + key_param_set->key[1] = 1; + else + key_param_set->key[1] = 0; + memmove(&key_param_set->key[2], + priv->wep_key[i].key_material, + priv->wep_key[i].key_length); + + cur_key_param_len = priv->wep_key[i].key_length + + KEYPARAMSET_WEP_FIXED_LEN + + sizeof(struct mwifiex_ie_types_header); + *key_param_len += (u16) cur_key_param_len; + key_param_set = + (struct mwifiex_ie_type_key_param_set *) + ((u8 *)key_param_set + + cur_key_param_len); + } else if (!priv->wep_key[i].key_length) { + continue; + } else { + dev_err(priv->adapter->dev, + "key%d Length = %d is incorrect\n", + (i + 1), priv->wep_key[i].key_length); + return -1; + } + } + + return 0; +} + +/* + * This function prepares command to set/get/reset network key(s). + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting WEP keys, WAPI keys or WPA keys along with required + * encryption (TKIP, AES) (as required) + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, + u32 cmd_oid, void *data_buf) +{ + struct host_cmd_ds_802_11_key_material *key_material = + &cmd->params.key_material; + struct mwifiex_ds_encrypt_key *enc_key = + (struct mwifiex_ds_encrypt_key *) data_buf; + u16 key_param_len = 0; + int ret = 0; + const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL); + key_material->action = cpu_to_le16(cmd_action); + + if (cmd_action == HostCmd_ACT_GEN_GET) { + cmd->size = + cpu_to_le16(sizeof(key_material->action) + S_DS_GEN); + return ret; + } + + if (!enc_key) { + memset(&key_material->key_param_set, 0, + (NUM_WEP_KEYS * + sizeof(struct mwifiex_ie_type_key_param_set))); + ret = mwifiex_set_keyparamset_wep(priv, + &key_material->key_param_set, + &key_param_len); + cmd->size = cpu_to_le16(key_param_len + + sizeof(key_material->action) + S_DS_GEN); + return ret; + } else + memset(&key_material->key_param_set, 0, + sizeof(struct mwifiex_ie_type_key_param_set)); + if (enc_key->is_wapi_key) { + dev_dbg(priv->adapter->dev, "info: Set WAPI Key\n"); + key_material->key_param_set.key_type_id = + cpu_to_le16(KEY_TYPE_ID_WAPI); + if (cmd_oid == KEY_INFO_ENABLED) + key_material->key_param_set.key_info = + cpu_to_le16(KEY_INFO_WAPI_ENABLED); + else + key_material->key_param_set.key_info = + cpu_to_le16(!KEY_INFO_WAPI_ENABLED); + + key_material->key_param_set.key[0] = enc_key->key_index; + if (!priv->sec_info.wapi_key_on) + key_material->key_param_set.key[1] = 1; + else + /* set 0 when re-key */ + key_material->key_param_set.key[1] = 0; + + if (0 != memcmp(enc_key->mac_addr, bc_mac, sizeof(bc_mac))) { + /* WAPI pairwise key: unicast */ + key_material->key_param_set.key_info |= + cpu_to_le16(KEY_INFO_WAPI_UNICAST); + } else { /* WAPI group key: multicast */ + key_material->key_param_set.key_info |= + cpu_to_le16(KEY_INFO_WAPI_MCAST); + priv->sec_info.wapi_key_on = true; + } + + key_material->key_param_set.type = + cpu_to_le16(TLV_TYPE_KEY_MATERIAL); + key_material->key_param_set.key_len = + cpu_to_le16(WAPI_KEY_LEN); + memcpy(&key_material->key_param_set.key[2], + enc_key->key_material, enc_key->key_len); + memcpy(&key_material->key_param_set.key[2 + enc_key->key_len], + enc_key->wapi_rxpn, WAPI_RXPN_LEN); + key_material->key_param_set.length = + cpu_to_le16(WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN); + + key_param_len = (WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN) + + sizeof(struct mwifiex_ie_types_header); + cmd->size = cpu_to_le16(key_param_len + + sizeof(key_material->action) + S_DS_GEN); + return ret; + } + if (enc_key->key_len == WLAN_KEY_LEN_CCMP) { + dev_dbg(priv->adapter->dev, "cmd: WPA_AES\n"); + key_material->key_param_set.key_type_id = + cpu_to_le16(KEY_TYPE_ID_AES); + if (cmd_oid == KEY_INFO_ENABLED) + key_material->key_param_set.key_info = + cpu_to_le16(KEY_INFO_AES_ENABLED); + else + key_material->key_param_set.key_info = + cpu_to_le16(!KEY_INFO_AES_ENABLED); + + if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) + /* AES pairwise key: unicast */ + key_material->key_param_set.key_info |= + cpu_to_le16(KEY_INFO_AES_UNICAST); + else /* AES group key: multicast */ + key_material->key_param_set.key_info |= + cpu_to_le16(KEY_INFO_AES_MCAST); + } else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) { + dev_dbg(priv->adapter->dev, "cmd: WPA_TKIP\n"); + key_material->key_param_set.key_type_id = + cpu_to_le16(KEY_TYPE_ID_TKIP); + key_material->key_param_set.key_info = + cpu_to_le16(KEY_INFO_TKIP_ENABLED); + + if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) + /* TKIP pairwise key: unicast */ + key_material->key_param_set.key_info |= + cpu_to_le16(KEY_INFO_TKIP_UNICAST); + else /* TKIP group key: multicast */ + key_material->key_param_set.key_info |= + cpu_to_le16(KEY_INFO_TKIP_MCAST); + } + + if (key_material->key_param_set.key_type_id) { + key_material->key_param_set.type = + cpu_to_le16(TLV_TYPE_KEY_MATERIAL); + key_material->key_param_set.key_len = + cpu_to_le16((u16) enc_key->key_len); + memcpy(key_material->key_param_set.key, enc_key->key_material, + enc_key->key_len); + key_material->key_param_set.length = + cpu_to_le16((u16) enc_key->key_len + + KEYPARAMSET_FIXED_LEN); + + key_param_len = (u16) (enc_key->key_len + KEYPARAMSET_FIXED_LEN) + + sizeof(struct mwifiex_ie_types_header); + + cmd->size = cpu_to_le16(key_param_len + + sizeof(key_material->action) + S_DS_GEN); + } + + return ret; +} + +/* + * This function prepares command to set/get 11d domain information. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting domain information fields (for SET only) + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct host_cmd_ds_802_11d_domain_info *domain_info = + &cmd->params.domain_info; + struct mwifiex_ietypes_domain_param_set *domain = + &domain_info->domain; + u8 no_of_triplet = adapter->domain_reg.no_of_triplet; + + dev_dbg(adapter->dev, "info: 11D: no_of_triplet=0x%x\n", no_of_triplet); + + cmd->command = cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO); + domain_info->action = cpu_to_le16(cmd_action); + if (cmd_action == HostCmd_ACT_GEN_GET) { + cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN); + return 0; + } + + /* Set domain info fields */ + domain->header.type = cpu_to_le16(WLAN_EID_COUNTRY); + memcpy(domain->country_code, adapter->domain_reg.country_code, + sizeof(domain->country_code)); + + domain->header.len = cpu_to_le16((no_of_triplet * + sizeof(struct ieee80211_country_ie_triplet)) + + sizeof(domain->country_code)); + + if (no_of_triplet) { + memcpy(domain->triplet, adapter->domain_reg.triplet, + no_of_triplet * + sizeof(struct ieee80211_country_ie_triplet)); + + cmd->size = cpu_to_le16(sizeof(domain_info->action) + + le16_to_cpu(domain->header.len) + + sizeof(struct mwifiex_ie_types_header) + + S_DS_GEN); + } else { + cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN); + } + + return 0; +} + +/* + * This function prepares command to set/get RF channel. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting RF type and current RF channel (for SET only) + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, void *data_buf) +{ + struct host_cmd_ds_802_11_rf_channel *rf_chan = + &cmd->params.rf_channel; + uint16_t rf_type = le16_to_cpu(rf_chan->rf_type); + + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_RF_CHANNEL); + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rf_channel) + + S_DS_GEN); + + if (cmd_action == HostCmd_ACT_GEN_SET) { + if ((priv->adapter->adhoc_start_band & BAND_A) + || (priv->adapter->adhoc_start_band & BAND_AN)) + rf_chan->rf_type = + cpu_to_le16(HostCmd_SCAN_RADIO_TYPE_A); + + rf_type = le16_to_cpu(rf_chan->rf_type); + SET_SECONDARYCHAN(rf_type, priv->adapter->chan_offset); + rf_chan->current_channel = cpu_to_le16(*((u16 *) data_buf)); + } + rf_chan->action = cpu_to_le16(cmd_action); + return 0; +} + +/* + * This function prepares command to set/get IBSS coalescing status. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting status to enable or disable (for SET only) + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_ibss_coalescing_status(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, void *data_buf) +{ + struct host_cmd_ds_802_11_ibss_status *ibss_coal = + &(cmd->params.ibss_coalescing); + u16 enable = 0; + + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS); + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status) + + S_DS_GEN); + cmd->result = 0; + ibss_coal->action = cpu_to_le16(cmd_action); + + switch (cmd_action) { + case HostCmd_ACT_GEN_SET: + if (data_buf != NULL) + enable = *(u16 *) data_buf; + ibss_coal->enable = cpu_to_le16(enable); + break; + + /* In other case.. Nothing to do */ + case HostCmd_ACT_GEN_GET: + default: + break; + } + + return 0; +} + +/* + * This function prepares command to set/get register value. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Setting register offset (for both GET and SET) and + * register value (for SET only) + * - Ensuring correct endian-ness + * + * The following type of registers can be accessed with this function - + * - MAC register + * - BBP register + * - RF register + * - PMIC register + * - CAU register + * - EEPROM + */ +static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd, + u16 cmd_action, void *data_buf) +{ + struct mwifiex_ds_reg_rw *reg_rw; + + reg_rw = (struct mwifiex_ds_reg_rw *) data_buf; + switch (le16_to_cpu(cmd->command)) { + case HostCmd_CMD_MAC_REG_ACCESS: + { + struct host_cmd_ds_mac_reg_access *mac_reg; + + cmd->size = cpu_to_le16(sizeof(*mac_reg) + S_DS_GEN); + mac_reg = (struct host_cmd_ds_mac_reg_access *) &cmd-> + params.mac_reg; + mac_reg->action = cpu_to_le16(cmd_action); + mac_reg->offset = + cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); + mac_reg->value = reg_rw->value; + break; + } + case HostCmd_CMD_BBP_REG_ACCESS: + { + struct host_cmd_ds_bbp_reg_access *bbp_reg; + + cmd->size = cpu_to_le16(sizeof(*bbp_reg) + S_DS_GEN); + bbp_reg = (struct host_cmd_ds_bbp_reg_access *) &cmd-> + params.bbp_reg; + bbp_reg->action = cpu_to_le16(cmd_action); + bbp_reg->offset = + cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); + bbp_reg->value = (u8) le32_to_cpu(reg_rw->value); + break; + } + case HostCmd_CMD_RF_REG_ACCESS: + { + struct host_cmd_ds_rf_reg_access *rf_reg; + + cmd->size = cpu_to_le16(sizeof(*rf_reg) + S_DS_GEN); + rf_reg = (struct host_cmd_ds_rf_reg_access *) &cmd-> + params.rf_reg; + rf_reg->action = cpu_to_le16(cmd_action); + rf_reg->offset = + cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); + rf_reg->value = (u8) le32_to_cpu(reg_rw->value); + break; + } + case HostCmd_CMD_PMIC_REG_ACCESS: + { + struct host_cmd_ds_pmic_reg_access *pmic_reg; + + cmd->size = cpu_to_le16(sizeof(*pmic_reg) + S_DS_GEN); + pmic_reg = (struct host_cmd_ds_pmic_reg_access *) &cmd-> + params.pmic_reg; + pmic_reg->action = cpu_to_le16(cmd_action); + pmic_reg->offset = + cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); + pmic_reg->value = (u8) le32_to_cpu(reg_rw->value); + break; + } + case HostCmd_CMD_CAU_REG_ACCESS: + { + struct host_cmd_ds_rf_reg_access *cau_reg; + + cmd->size = cpu_to_le16(sizeof(*cau_reg) + S_DS_GEN); + cau_reg = (struct host_cmd_ds_rf_reg_access *) &cmd-> + params.rf_reg; + cau_reg->action = cpu_to_le16(cmd_action); + cau_reg->offset = + cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); + cau_reg->value = (u8) le32_to_cpu(reg_rw->value); + break; + } + case HostCmd_CMD_802_11_EEPROM_ACCESS: + { + struct mwifiex_ds_read_eeprom *rd_eeprom = + (struct mwifiex_ds_read_eeprom *) data_buf; + struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom = + (struct host_cmd_ds_802_11_eeprom_access *) + &cmd->params.eeprom; + + cmd->size = cpu_to_le16(sizeof(*cmd_eeprom) + S_DS_GEN); + cmd_eeprom->action = cpu_to_le16(cmd_action); + cmd_eeprom->offset = rd_eeprom->offset; + cmd_eeprom->byte_count = rd_eeprom->byte_count; + cmd_eeprom->value = 0; + break; + } + default: + return -1; + } + + return 0; +} + +/* + * This function prepares the commands before sending them to the firmware. + * + * This is a generic function which calls specific command preparation + * routines based upon the command number. + */ +int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, + u16 cmd_action, u32 cmd_oid, + void *data_buf, void *cmd_buf) +{ + struct host_cmd_ds_command *cmd_ptr = + (struct host_cmd_ds_command *) cmd_buf; + int ret = 0; + + /* Prepare command */ + switch (cmd_no) { + case HostCmd_CMD_GET_HW_SPEC: + ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr); + break; + case HostCmd_CMD_MAC_CONTROL: + ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action, + data_buf); + break; + case HostCmd_CMD_802_11_MAC_ADDRESS: + ret = mwifiex_cmd_802_11_mac_address(priv, cmd_ptr, + cmd_action); + break; + case HostCmd_CMD_MAC_MULTICAST_ADR: + ret = mwifiex_cmd_mac_multicast_adr(priv, cmd_ptr, cmd_action, + data_buf); + break; + case HostCmd_CMD_TX_RATE_CFG: + ret = mwifiex_cmd_tx_rate_cfg(priv, cmd_ptr, cmd_action, + data_buf); + break; + case HostCmd_CMD_TXPWR_CFG: + ret = mwifiex_cmd_tx_power_cfg(priv, cmd_ptr, cmd_action, + data_buf); + break; + case HostCmd_CMD_802_11_PS_MODE_ENH: + ret = mwifiex_cmd_enh_power_mode(priv, cmd_ptr, cmd_action, + (uint16_t)cmd_oid, data_buf); + break; + case HostCmd_CMD_802_11_HS_CFG_ENH: + ret = mwifiex_cmd_802_11_hs_cfg(priv, cmd_ptr, cmd_action, + (struct mwifiex_hs_config_param *) data_buf); + break; + case HostCmd_CMD_802_11_SCAN: + ret = mwifiex_cmd_802_11_scan(priv, cmd_ptr, data_buf); + break; + case HostCmd_CMD_802_11_BG_SCAN_QUERY: + ret = mwifiex_cmd_802_11_bg_scan_query(priv, cmd_ptr, + data_buf); + break; + case HostCmd_CMD_802_11_ASSOCIATE: + ret = mwifiex_cmd_802_11_associate(priv, cmd_ptr, data_buf); + break; + case HostCmd_CMD_802_11_DEAUTHENTICATE: + ret = mwifiex_cmd_802_11_deauthenticate(priv, cmd_ptr, + data_buf); + break; + case HostCmd_CMD_802_11_AD_HOC_START: + ret = mwifiex_cmd_802_11_ad_hoc_start(priv, cmd_ptr, + data_buf); + break; + case HostCmd_CMD_802_11_GET_LOG: + ret = mwifiex_cmd_802_11_get_log(priv, cmd_ptr); + break; + case HostCmd_CMD_802_11_AD_HOC_JOIN: + ret = mwifiex_cmd_802_11_ad_hoc_join(priv, cmd_ptr, + data_buf); + break; + case HostCmd_CMD_802_11_AD_HOC_STOP: + ret = mwifiex_cmd_802_11_ad_hoc_stop(priv, cmd_ptr); + break; + case HostCmd_CMD_RSSI_INFO: + ret = mwifiex_cmd_802_11_rssi_info(priv, cmd_ptr, cmd_action); + break; + case HostCmd_CMD_802_11_SNMP_MIB: + ret = mwifiex_cmd_802_11_snmp_mib(priv, cmd_ptr, cmd_action, + cmd_oid, data_buf); + break; + case HostCmd_CMD_802_11_TX_RATE_QUERY: + cmd_ptr->command = + cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY); + cmd_ptr->size = + cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query) + + S_DS_GEN); + priv->tx_rate = 0; + ret = 0; + break; + case HostCmd_CMD_VERSION_EXT: + cmd_ptr->command = cpu_to_le16(cmd_no); + cmd_ptr->params.verext.version_str_sel = + (u8) (*((u32 *) data_buf)); + memcpy(&cmd_ptr->params, data_buf, + sizeof(struct host_cmd_ds_version_ext)); + cmd_ptr->size = + cpu_to_le16(sizeof(struct host_cmd_ds_version_ext) + + S_DS_GEN); + ret = 0; + break; + case HostCmd_CMD_802_11_RF_CHANNEL: + ret = mwifiex_cmd_802_11_rf_channel(priv, cmd_ptr, cmd_action, + data_buf); + break; + case HostCmd_CMD_FUNC_INIT: + if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET) + priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY; + cmd_ptr->command = cpu_to_le16(cmd_no); + cmd_ptr->size = cpu_to_le16(S_DS_GEN); + break; + case HostCmd_CMD_FUNC_SHUTDOWN: + priv->adapter->hw_status = MWIFIEX_HW_STATUS_RESET; + cmd_ptr->command = cpu_to_le16(cmd_no); + cmd_ptr->size = cpu_to_le16(S_DS_GEN); + break; + case HostCmd_CMD_11N_ADDBA_REQ: + ret = mwifiex_cmd_11n_addba_req(priv, cmd_ptr, data_buf); + break; + case HostCmd_CMD_11N_DELBA: + ret = mwifiex_cmd_11n_delba(priv, cmd_ptr, data_buf); + break; + case HostCmd_CMD_11N_ADDBA_RSP: + ret = mwifiex_cmd_11n_addba_rsp_gen(priv, cmd_ptr, data_buf); + break; + case HostCmd_CMD_802_11_KEY_MATERIAL: + ret = mwifiex_cmd_802_11_key_material(priv, cmd_ptr, + cmd_action, cmd_oid, + data_buf); + break; + case HostCmd_CMD_802_11D_DOMAIN_INFO: + ret = mwifiex_cmd_802_11d_domain_info(priv, cmd_ptr, + cmd_action); + break; + case HostCmd_CMD_RECONFIGURE_TX_BUFF: + ret = mwifiex_cmd_recfg_tx_buf(priv, cmd_ptr, cmd_action, + data_buf); + break; + case HostCmd_CMD_AMSDU_AGGR_CTRL: + ret = mwifiex_cmd_amsdu_aggr_ctrl(priv, cmd_ptr, cmd_action, + data_buf); + break; + case HostCmd_CMD_11N_CFG: + ret = mwifiex_cmd_11n_cfg(priv, cmd_ptr, cmd_action, + data_buf); + break; + case HostCmd_CMD_WMM_GET_STATUS: + dev_dbg(priv->adapter->dev, + "cmd: WMM: WMM_GET_STATUS cmd sent\n"); + cmd_ptr->command = cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS); + cmd_ptr->size = + cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status) + + S_DS_GEN); + ret = 0; + break; + case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: + ret = mwifiex_cmd_ibss_coalescing_status(priv, cmd_ptr, + cmd_action, data_buf); + break; + case HostCmd_CMD_MAC_REG_ACCESS: + case HostCmd_CMD_BBP_REG_ACCESS: + case HostCmd_CMD_RF_REG_ACCESS: + case HostCmd_CMD_PMIC_REG_ACCESS: + case HostCmd_CMD_CAU_REG_ACCESS: + case HostCmd_CMD_802_11_EEPROM_ACCESS: + ret = mwifiex_cmd_reg_access(cmd_ptr, cmd_action, data_buf); + break; + case HostCmd_CMD_SET_BSS_MODE: + cmd_ptr->command = cpu_to_le16(cmd_no); + if (priv->bss_mode == MWIFIEX_BSS_MODE_IBSS) + cmd_ptr->params.bss_mode.con_type = + CONNECTION_TYPE_ADHOC; + else if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA) + cmd_ptr->params.bss_mode.con_type = + CONNECTION_TYPE_INFRA; + cmd_ptr->size = cpu_to_le16(sizeof(struct + host_cmd_ds_set_bss_mode) + S_DS_GEN); + ret = 0; + break; + default: + dev_err(priv->adapter->dev, + "PREP_CMD: unknown cmd- %#x\n", cmd_no); + ret = -1; + break; + } + return ret; +} + +/* + * This function issues commands to initialize firmware. + * + * This is called after firmware download to bring the card to + * working state. + * + * The following commands are issued sequentially - + * - Function init (for first interface only) + * - Read MAC address (for first interface only) + * - Reconfigure Tx buffer size (for first interface only) + * - Enable auto deep sleep (for first interface only) + * - Get Tx rate + * - Get Tx power + * - Set IBSS coalescing status + * - Set AMSDU aggregation control + * - Set 11d control + * - Set MAC control (this must be the last command to initialize firmware) + */ +int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) +{ + int ret = 0; + u16 enable = true; + struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; + struct mwifiex_ds_auto_ds auto_ds; + enum state_11d_t state_11d; + + if (first_sta) { + + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_FUNC_INIT, + HostCmd_ACT_GEN_SET, 0, NULL, NULL); + if (ret) + return -1; + /* Read MAC address from HW */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_GET_HW_SPEC, + HostCmd_ACT_GEN_GET, 0, NULL, NULL); + if (ret) + return -1; + + /* Reconfigure tx buf size */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, + HostCmd_ACT_GEN_SET, 0, NULL, + &priv->adapter->tx_buf_size); + if (ret) + return -1; + + /* Enable IEEE PS by default */ + priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, + EN_AUTO_PS, BITMAP_STA_PS, NULL, + NULL); + if (ret) + return -1; + } + + /* get tx rate */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TX_RATE_CFG, + HostCmd_ACT_GEN_GET, 0, NULL, NULL); + if (ret) + return -1; + priv->data_rate = 0; + + /* get tx power */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TXPWR_CFG, + HostCmd_ACT_GEN_GET, 0, NULL, NULL); + if (ret) + return -1; + + /* set ibss coalescing_status */ + ret = mwifiex_prepare_cmd(priv, + HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, + HostCmd_ACT_GEN_SET, 0, NULL, &enable); + if (ret) + return -1; + + memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); + amsdu_aggr_ctrl.enable = true; + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, + HostCmd_ACT_GEN_SET, 0, NULL, + (void *) &amsdu_aggr_ctrl); + if (ret) + return -1; + /* MAC Control must be the last command in init_fw */ + /* set MAC Control */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, + HostCmd_ACT_GEN_SET, 0, NULL, + &priv->curr_pkt_filter); + if (ret) + return -1; + + if (first_sta) { + /* Enable auto deep sleep */ + auto_ds.auto_ds = DEEP_SLEEP_ON; + auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; + ret = mwifiex_prepare_cmd(priv, + HostCmd_CMD_802_11_PS_MODE_ENH, + EN_AUTO_PS, BITMAP_AUTO_DS, NULL, + &auto_ds); + if (ret) + return -1; + } + + /* Send cmd to FW to enable/disable 11D function */ + state_11d = ENABLE_11D; + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_SET, DOT11D_I, + NULL, &state_11d); + if (ret) + dev_err(priv->adapter->dev, "11D: failed to enable 11D\n"); + + /* set last_init_cmd */ + priv->adapter->last_init_cmd = HostCmd_CMD_802_11_SNMP_MIB; + ret = -EINPROGRESS; + + return ret; +} diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c new file mode 100644 index 000000000000..ae960ddf2bd4 --- /dev/null +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -0,0 +1,986 @@ +/* + * Marvell Wireless LAN device driver: station command response handling + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" + + +/* + * This function handles the command response error case. + * + * For scan response error, the function cancels all the pending + * scan commands and generates an event to inform the applications + * of the scan completion. + * + * For Power Save command failure, we do not retry enter PS + * command in case of Ad-hoc mode. + * + * For all other response errors, the current command buffer is freed + * and returned to the free command queue. + */ +static void +mwifiex_process_cmdresp_error(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + struct mwifiex_wait_queue *wq_buf) +{ + struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; + struct mwifiex_adapter *adapter = priv->adapter; + unsigned long flags; + + dev_err(adapter->dev, "CMD_RESP: cmd %#x error, result=%#x\n", + resp->command, resp->result); + if (wq_buf) + wq_buf->status = MWIFIEX_ERROR_FW_CMDRESP; + + switch (le16_to_cpu(resp->command)) { + case HostCmd_CMD_802_11_PS_MODE_ENH: + { + struct host_cmd_ds_802_11_ps_mode_enh *pm = + &resp->params.psmode_enh; + dev_err(adapter->dev, "PS_MODE_ENH cmd failed: " + "result=0x%x action=0x%X\n", + resp->result, le16_to_cpu(pm->action)); + /* We do not re-try enter-ps command in ad-hoc mode. */ + if (le16_to_cpu(pm->action) == EN_AUTO_PS && + (le16_to_cpu(pm->params.auto_ps.ps_bitmap) & + BITMAP_STA_PS) + && priv->bss_mode == MWIFIEX_BSS_MODE_IBSS) + adapter->ps_mode = + MWIFIEX_802_11_POWER_MODE_CAM; + } + break; + case HostCmd_CMD_802_11_SCAN: + /* Cancel all pending scan command */ + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + list_for_each_entry_safe(cmd_node, tmp_node, + &adapter->scan_pending_q, list) { + list_del(&cmd_node->list); + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, + flags); + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + } + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->scan_processing = false; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + if (priv->report_scan_result) + priv->report_scan_result = false; + if (priv->scan_pending_on_block) { + priv->scan_pending_on_block = false; + up(&priv->async_sem); + } + break; + + case HostCmd_CMD_MAC_CONTROL: + break; + + default: + break; + } + /* Handling errors here */ + mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); + + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->curr_cmd = NULL; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + + return; +} + +/* + * This function handles the command response of get RSSI info. + * + * Handling includes changing the header fields into CPU format + * and saving the following parameters in driver - + * - Last data and beacon RSSI value + * - Average data and beacon RSSI value + * - Last data and beacon NF value + * - Average data and beacon NF value + * + * The parameters are send to the application as well, along with + * calculated SNR values. + */ +static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *data_buf) +{ + struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = + &resp->params.rssi_info_rsp; + struct mwifiex_ds_get_signal *signal = NULL; + + priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); + priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); + + priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg); + priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg); + + priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last); + priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last); + + priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg); + priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg); + + /* Need to indicate IOCTL complete */ + if (data_buf) { + signal = (struct mwifiex_ds_get_signal *) data_buf; + memset(signal, 0, sizeof(struct mwifiex_ds_get_signal)); + + signal->selector = ALL_RSSI_INFO_MASK; + + /* RSSI */ + signal->bcn_rssi_last = priv->bcn_rssi_last; + signal->bcn_rssi_avg = priv->bcn_rssi_avg; + signal->data_rssi_last = priv->data_rssi_last; + signal->data_rssi_avg = priv->data_rssi_avg; + + /* SNR */ + signal->bcn_snr_last = + CAL_SNR(priv->bcn_rssi_last, priv->bcn_nf_last); + signal->bcn_snr_avg = + CAL_SNR(priv->bcn_rssi_avg, priv->bcn_nf_avg); + signal->data_snr_last = + CAL_SNR(priv->data_rssi_last, priv->data_nf_last); + signal->data_snr_avg = + CAL_SNR(priv->data_rssi_avg, priv->data_nf_avg); + + /* NF */ + signal->bcn_nf_last = priv->bcn_nf_last; + signal->bcn_nf_avg = priv->bcn_nf_avg; + signal->data_nf_last = priv->data_nf_last; + signal->data_nf_avg = priv->data_nf_avg; + } + + return 0; +} + +/* + * This function handles the command response of set/get SNMP + * MIB parameters. + * + * Handling includes changing the header fields into CPU format + * and saving the parameter in driver. + * + * The following parameters are supported - + * - Fragmentation threshold + * - RTS threshold + * - Short retry limit + */ +static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *data_buf) +{ + struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib; + u16 oid = le16_to_cpu(smib->oid); + u16 query_type = le16_to_cpu(smib->query_type); + u32 ul_temp; + + dev_dbg(priv->adapter->dev, "info: SNMP_RESP: oid value = %#x," + " query_type = %#x, buf size = %#x\n", + oid, query_type, le16_to_cpu(smib->buf_size)); + if (query_type == HostCmd_ACT_GEN_GET) { + ul_temp = le16_to_cpu(*((__le16 *) (smib->value))); + if (data_buf) + *(u32 *)data_buf = ul_temp; + switch (oid) { + case FRAG_THRESH_I: + dev_dbg(priv->adapter->dev, + "info: SNMP_RESP: FragThsd =%u\n", ul_temp); + break; + case RTS_THRESH_I: + dev_dbg(priv->adapter->dev, + "info: SNMP_RESP: RTSThsd =%u\n", ul_temp); + break; + case SHORT_RETRY_LIM_I: + dev_dbg(priv->adapter->dev, + "info: SNMP_RESP: TxRetryCount=%u\n", ul_temp); + break; + default: + break; + } + } + + return 0; +} + +/* + * This function handles the command response of get log request + * + * Handling includes changing the header fields into CPU format + * and sending the received parameters to application. + */ +static int mwifiex_ret_get_log(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *data_buf) +{ + struct host_cmd_ds_802_11_get_log *get_log = + (struct host_cmd_ds_802_11_get_log *) &resp->params.get_log; + struct mwifiex_ds_get_stats *stats = NULL; + + if (data_buf) { + stats = (struct mwifiex_ds_get_stats *) data_buf; + stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame); + stats->failed = le32_to_cpu(get_log->failed); + stats->retry = le32_to_cpu(get_log->retry); + stats->multi_retry = le32_to_cpu(get_log->multi_retry); + stats->frame_dup = le32_to_cpu(get_log->frame_dup); + stats->rts_success = le32_to_cpu(get_log->rts_success); + stats->rts_failure = le32_to_cpu(get_log->rts_failure); + stats->ack_failure = le32_to_cpu(get_log->ack_failure); + stats->rx_frag = le32_to_cpu(get_log->rx_frag); + stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame); + stats->fcs_error = le32_to_cpu(get_log->fcs_error); + stats->tx_frame = le32_to_cpu(get_log->tx_frame); + stats->wep_icv_error[0] = + le32_to_cpu(get_log->wep_icv_err_cnt[0]); + stats->wep_icv_error[1] = + le32_to_cpu(get_log->wep_icv_err_cnt[1]); + stats->wep_icv_error[2] = + le32_to_cpu(get_log->wep_icv_err_cnt[2]); + stats->wep_icv_error[3] = + le32_to_cpu(get_log->wep_icv_err_cnt[3]); + } + + return 0; +} + +/* + * This function handles the command response of set/get Tx rate + * configurations. + * + * Handling includes changing the header fields into CPU format + * and saving the following parameters in driver - + * - DSSS rate bitmap + * - OFDM rate bitmap + * - HT MCS rate bitmaps + * + * Based on the new rate bitmaps, the function re-evaluates if + * auto data rate has been activated. If not, it sends another + * query to the firmware to get the current Tx data rate and updates + * the driver value. + */ +static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *data_buf) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_rate_cfg *ds_rate = NULL; + struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg; + struct mwifiex_rate_scope *rate_scope; + struct mwifiex_ie_types_header *head = NULL; + u16 tlv, tlv_buf_len; + u8 *tlv_buf; + u32 i; + int ret = 0; + + tlv_buf = (u8 *) ((u8 *) rate_cfg) + + sizeof(struct host_cmd_ds_tx_rate_cfg); + tlv_buf_len = *(u16 *) (tlv_buf + sizeof(u16)); + + while (tlv_buf && tlv_buf_len > 0) { + tlv = (*tlv_buf); + tlv = tlv | (*(tlv_buf + 1) << 8); + + switch (tlv) { + case TLV_TYPE_RATE_SCOPE: + rate_scope = (struct mwifiex_rate_scope *) tlv_buf; + priv->bitmap_rates[0] = + le16_to_cpu(rate_scope->hr_dsss_rate_bitmap); + priv->bitmap_rates[1] = + le16_to_cpu(rate_scope->ofdm_rate_bitmap); + for (i = 0; + i < + sizeof(rate_scope->ht_mcs_rate_bitmap) / + sizeof(u16); i++) + priv->bitmap_rates[2 + i] = + le16_to_cpu(rate_scope-> + ht_mcs_rate_bitmap[i]); + break; + /* Add RATE_DROP tlv here */ + } + + head = (struct mwifiex_ie_types_header *) tlv_buf; + tlv_buf += le16_to_cpu(head->len) + sizeof(*head); + tlv_buf_len -= le16_to_cpu(head->len); + } + + priv->is_data_rate_auto = mwifiex_is_rate_auto(priv); + + if (priv->is_data_rate_auto) + priv->data_rate = 0; + else + ret = mwifiex_prepare_cmd(priv, + HostCmd_CMD_802_11_TX_RATE_QUERY, + HostCmd_ACT_GEN_GET, 0, NULL, NULL); + + if (data_buf) { + ds_rate = (struct mwifiex_rate_cfg *) data_buf; + if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) { + if (priv->is_data_rate_auto) { + ds_rate->is_rate_auto = 1; + } else { + ds_rate->rate = + mwifiex_get_rate_index(adapter, + priv-> + bitmap_rates, + sizeof(priv-> + bitmap_rates)); + if (ds_rate->rate >= + MWIFIEX_RATE_BITMAP_OFDM0 + && ds_rate->rate <= + MWIFIEX_RATE_BITMAP_OFDM7) + ds_rate->rate -= + (MWIFIEX_RATE_BITMAP_OFDM0 - + MWIFIEX_RATE_INDEX_OFDM0); + if (ds_rate->rate >= + MWIFIEX_RATE_BITMAP_MCS0 + && ds_rate->rate <= + MWIFIEX_RATE_BITMAP_MCS127) + ds_rate->rate -= + (MWIFIEX_RATE_BITMAP_MCS0 - + MWIFIEX_RATE_INDEX_MCS0); + } + } + } + + return ret; +} + +/* + * This function handles the command response of get Tx power level. + * + * Handling includes saving the maximum and minimum Tx power levels + * in driver, as well as sending the values to user. + */ +static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf) +{ + int length = -1, max_power = -1, min_power = -1; + struct mwifiex_types_power_group *pg_tlv_hdr = NULL; + struct mwifiex_power_group *pg = NULL; + + if (data_buf) { + pg_tlv_hdr = + (struct mwifiex_types_power_group *) ((u8 *) data_buf + + sizeof(struct host_cmd_ds_txpwr_cfg)); + pg = (struct mwifiex_power_group *) ((u8 *) pg_tlv_hdr + + sizeof(struct mwifiex_types_power_group)); + length = pg_tlv_hdr->length; + if (length > 0) { + max_power = pg->power_max; + min_power = pg->power_min; + length -= sizeof(struct mwifiex_power_group); + } + while (length) { + pg++; + if (max_power < pg->power_max) + max_power = pg->power_max; + + if (min_power > pg->power_min) + min_power = pg->power_min; + + length -= sizeof(struct mwifiex_power_group); + } + if (pg_tlv_hdr->length > 0) { + priv->min_tx_power_level = (u8) min_power; + priv->max_tx_power_level = (u8) max_power; + } + } else { + return -1; + } + + return 0; +} + +/* + * This function handles the command response of set/get Tx power + * configurations. + * + * Handling includes changing the header fields into CPU format + * and saving the current Tx power level in driver. + */ +static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *data_buf) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg; + struct mwifiex_types_power_group *pg_tlv_hdr = NULL; + struct mwifiex_power_group *pg = NULL; + u16 action = le16_to_cpu(txp_cfg->action); + + switch (action) { + case HostCmd_ACT_GEN_GET: + { + pg_tlv_hdr = + (struct mwifiex_types_power_group *) ((u8 *) + txp_cfg + + sizeof + (struct + host_cmd_ds_txpwr_cfg)); + pg = (struct mwifiex_power_group *) ((u8 *) + pg_tlv_hdr + + sizeof(struct + mwifiex_types_power_group)); + if (adapter->hw_status == + MWIFIEX_HW_STATUS_INITIALIZING) + mwifiex_get_power_level(priv, txp_cfg); + priv->tx_power_level = (u16) pg->power_min; + break; + } + case HostCmd_ACT_GEN_SET: + if (le32_to_cpu(txp_cfg->mode)) { + pg_tlv_hdr = + (struct mwifiex_types_power_group *) ((u8 *) + txp_cfg + + sizeof + (struct + host_cmd_ds_txpwr_cfg)); + pg = (struct mwifiex_power_group *) ((u8 *) pg_tlv_hdr + + + sizeof(struct + mwifiex_types_power_group)); + if (pg->power_max == pg->power_min) + priv->tx_power_level = (u16) pg->power_min; + } + break; + default: + dev_err(adapter->dev, "CMD_RESP: unknown cmd action %d\n", + action); + return 0; + } + dev_dbg(adapter->dev, + "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n", + priv->tx_power_level, priv->max_tx_power_level, + priv->min_tx_power_level); + + return 0; +} + +/* + * This function handles the command response of set/get MAC address. + * + * Handling includes saving the MAC address in driver. + */ +static int mwifiex_ret_802_11_mac_address(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + struct host_cmd_ds_802_11_mac_address *cmd_mac_addr = + &resp->params.mac_addr; + + memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN); + + dev_dbg(priv->adapter->dev, + "info: set mac address: %pM\n", priv->curr_addr); + + return 0; +} + +/* + * This function handles the command response of set/get MAC multicast + * address. + */ +static int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + return 0; +} + +/* + * This function handles the command response of get Tx rate query. + * + * Handling includes changing the header fields into CPU format + * and saving the Tx rate and HT information parameters in driver. + * + * Both rate configuration and current data rate can be retrieved + * with this request. + */ +static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + struct mwifiex_adapter *adapter = priv->adapter; + + priv->tx_rate = resp->params.tx_rate.tx_rate; + priv->tx_htinfo = resp->params.tx_rate.ht_info; + if (!priv->is_data_rate_auto) + priv->data_rate = + mwifiex_index_to_data_rate(adapter, priv->tx_rate, + priv->tx_htinfo); + + return 0; +} + +/* + * This function handles the command response of a deauthenticate + * command. + * + * If the deauthenticated MAC matches the current BSS MAC, the connection + * state is reset. + */ +static int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + struct mwifiex_adapter *adapter = priv->adapter; + + adapter->dbg.num_cmd_deauth++; + if (!memcmp(resp->params.deauth.mac_addr, + &priv->curr_bss_params.bss_descriptor.mac_address, + sizeof(resp->params.deauth.mac_addr))) + mwifiex_reset_connect_state(priv); + + return 0; +} + +/* + * This function handles the command response of ad-hoc stop. + * + * The function resets the connection state in driver. + */ +static int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + mwifiex_reset_connect_state(priv); + return 0; +} + +/* + * This function handles the command response of set/get key material. + * + * Handling includes updating the driver parameters to reflect the + * changes. + */ +static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + struct host_cmd_ds_802_11_key_material *key = + &resp->params.key_material; + + if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) { + if ((le16_to_cpu(key->key_param_set.key_info) & + KEY_INFO_TKIP_MCAST)) { + dev_dbg(priv->adapter->dev, "info: key: GTK is set\n"); + priv->wpa_is_gtk_set = true; + priv->scan_block = false; + } + } + + memset(priv->aes_key.key_param_set.key, 0, + sizeof(key->key_param_set.key)); + priv->aes_key.key_param_set.key_len = key->key_param_set.key_len; + memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key, + le16_to_cpu(priv->aes_key.key_param_set.key_len)); + + return 0; +} + +/* + * This function handles the command response of get 11d domain information. + */ +static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + struct host_cmd_ds_802_11d_domain_info_rsp *domain_info = + &resp->params.domain_info_resp; + struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain; + u16 action = le16_to_cpu(domain_info->action); + u8 no_of_triplet = 0; + + no_of_triplet = (u8) ((le16_to_cpu(domain->header.len) - + IEEE80211_COUNTRY_STRING_LEN) / + sizeof(struct ieee80211_country_ie_triplet)); + + dev_dbg(priv->adapter->dev, "info: 11D Domain Info Resp:" + " no_of_triplet=%d\n", no_of_triplet); + + if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) { + dev_warn(priv->adapter->dev, + "11D: invalid number of triplets %d " + "returned!!\n", no_of_triplet); + return -1; + } + + switch (action) { + case HostCmd_ACT_GEN_SET: /* Proc Set Action */ + break; + case HostCmd_ACT_GEN_GET: + break; + default: + dev_err(priv->adapter->dev, + "11D: invalid action:%d\n", domain_info->action); + return -1; + } + + return 0; +} + +/* + * This function handles the command response of get RF channel. + * + * Handling includes changing the header fields into CPU format + * and saving the new channel in driver. + */ +static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *data_buf) +{ + struct host_cmd_ds_802_11_rf_channel *rf_channel = + &resp->params.rf_channel; + u16 new_channel = le16_to_cpu(rf_channel->current_channel); + + if (priv->curr_bss_params.bss_descriptor.channel != new_channel) { + dev_dbg(priv->adapter->dev, "cmd: Channel Switch: %d to %d\n", + priv->curr_bss_params.bss_descriptor.channel, + new_channel); + /* Update the channel again */ + priv->curr_bss_params.bss_descriptor.channel = new_channel; + } + if (data_buf) + *((u16 *)data_buf) = new_channel; + + return 0; +} + +/* + * This function handles the command response of get extended version. + * + * Handling includes forming the extended version string and sending it + * to application. + */ +static int mwifiex_ret_ver_ext(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *data_buf) +{ + struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext; + struct host_cmd_ds_version_ext *version_ext = NULL; + + if (data_buf) { + version_ext = (struct host_cmd_ds_version_ext *)data_buf; + version_ext->version_str_sel = ver_ext->version_str_sel; + memcpy(version_ext->version_str, ver_ext->version_str, + sizeof(char) * 128); + memcpy(priv->version_str, ver_ext->version_str, 128); + } + return 0; +} + +/* + * This function handles the command response of register access. + * + * The register value and offset are returned to the user. For EEPROM + * access, the byte count is also returned. + */ +static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp, + void *data_buf) +{ + struct mwifiex_ds_reg_rw *reg_rw = NULL; + struct mwifiex_ds_read_eeprom *eeprom = NULL; + + if (data_buf) { + reg_rw = (struct mwifiex_ds_reg_rw *) data_buf; + eeprom = (struct mwifiex_ds_read_eeprom *) data_buf; + switch (type) { + case HostCmd_CMD_MAC_REG_ACCESS: + { + struct host_cmd_ds_mac_reg_access *reg; + reg = (struct host_cmd_ds_mac_reg_access *) + &resp->params.mac_reg; + reg_rw->offset = cpu_to_le32( + (u32) le16_to_cpu(reg->offset)); + reg_rw->value = reg->value; + break; + } + case HostCmd_CMD_BBP_REG_ACCESS: + { + struct host_cmd_ds_bbp_reg_access *reg; + reg = (struct host_cmd_ds_bbp_reg_access *) + &resp->params.bbp_reg; + reg_rw->offset = cpu_to_le32( + (u32) le16_to_cpu(reg->offset)); + reg_rw->value = cpu_to_le32((u32) reg->value); + break; + } + + case HostCmd_CMD_RF_REG_ACCESS: + { + struct host_cmd_ds_rf_reg_access *reg; + reg = (struct host_cmd_ds_rf_reg_access *) + &resp->params.rf_reg; + reg_rw->offset = cpu_to_le32( + (u32) le16_to_cpu(reg->offset)); + reg_rw->value = cpu_to_le32((u32) reg->value); + break; + } + case HostCmd_CMD_PMIC_REG_ACCESS: + { + struct host_cmd_ds_pmic_reg_access *reg; + reg = (struct host_cmd_ds_pmic_reg_access *) + &resp->params.pmic_reg; + reg_rw->offset = cpu_to_le32( + (u32) le16_to_cpu(reg->offset)); + reg_rw->value = cpu_to_le32((u32) reg->value); + break; + } + case HostCmd_CMD_CAU_REG_ACCESS: + { + struct host_cmd_ds_rf_reg_access *reg; + reg = (struct host_cmd_ds_rf_reg_access *) + &resp->params.rf_reg; + reg_rw->offset = cpu_to_le32( + (u32) le16_to_cpu(reg->offset)); + reg_rw->value = cpu_to_le32((u32) reg->value); + break; + } + case HostCmd_CMD_802_11_EEPROM_ACCESS: + { + struct host_cmd_ds_802_11_eeprom_access + *cmd_eeprom = + (struct host_cmd_ds_802_11_eeprom_access + *) &resp->params.eeprom; + pr_debug("info: EEPROM read len=%x\n", + cmd_eeprom->byte_count); + if (le16_to_cpu(eeprom->byte_count) < + le16_to_cpu( + cmd_eeprom->byte_count)) { + eeprom->byte_count = cpu_to_le16(0); + pr_debug("info: EEPROM read " + "length is too big\n"); + return -1; + } + eeprom->offset = cmd_eeprom->offset; + eeprom->byte_count = cmd_eeprom->byte_count; + if (le16_to_cpu(eeprom->byte_count) > 0) + memcpy(&eeprom->value, + &cmd_eeprom->value, + le16_to_cpu(eeprom->byte_count)); + + break; + } + default: + return -1; + } + } + return 0; +} + +/* + * This function handles the command response of get IBSS coalescing status. + * + * If the received BSSID is different than the current one, the current BSSID, + * beacon interval, ATIM window and ERP information are updated, along with + * changing the ad-hoc state accordingly. + */ +static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp = + &(resp->params.ibss_coalescing); + u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; + + if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET) + return 0; + + dev_dbg(priv->adapter->dev, + "info: new BSSID %pM\n", ibss_coal_resp->bssid); + + /* If rsp has NULL BSSID, Just return..... No Action */ + if (!memcmp(ibss_coal_resp->bssid, zero_mac, ETH_ALEN)) { + dev_warn(priv->adapter->dev, "new BSSID is NULL\n"); + return 0; + } + + /* If BSSID is diff, modify current BSS parameters */ + if (memcmp(priv->curr_bss_params.bss_descriptor.mac_address, + ibss_coal_resp->bssid, ETH_ALEN)) { + /* BSSID */ + memcpy(priv->curr_bss_params.bss_descriptor.mac_address, + ibss_coal_resp->bssid, ETH_ALEN); + + /* Beacon Interval */ + priv->curr_bss_params.bss_descriptor.beacon_period + = le16_to_cpu(ibss_coal_resp->beacon_interval); + + /* ERP Information */ + priv->curr_bss_params.bss_descriptor.erp_flags = + (u8) le16_to_cpu(ibss_coal_resp->use_g_rate_protect); + + priv->adhoc_state = ADHOC_COALESCED; + } + + return 0; +} + +/* + * This function handles the command responses. + * + * This is a generic function, which calls command specific + * response handlers based on the command ID. + */ +int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, + u16 cmdresp_no, void *cmd_buf, void *wq_buf) +{ + int ret = 0; + struct mwifiex_adapter *adapter = priv->adapter; + struct host_cmd_ds_command *resp = + (struct host_cmd_ds_command *) cmd_buf; + struct mwifiex_wait_queue *wait_queue = + (struct mwifiex_wait_queue *) wq_buf; + void *data_buf = adapter->curr_cmd->data_buf; + + /* If the command is not successful, cleanup and return failure */ + if (resp->result != HostCmd_RESULT_OK) { + mwifiex_process_cmdresp_error(priv, resp, wait_queue); + return -1; + } + /* Command successful, handle response */ + switch (cmdresp_no) { + case HostCmd_CMD_GET_HW_SPEC: + ret = mwifiex_ret_get_hw_spec(priv, resp); + break; + case HostCmd_CMD_MAC_CONTROL: + break; + case HostCmd_CMD_802_11_MAC_ADDRESS: + ret = mwifiex_ret_802_11_mac_address(priv, resp); + break; + case HostCmd_CMD_MAC_MULTICAST_ADR: + ret = mwifiex_ret_mac_multicast_adr(priv, resp); + break; + case HostCmd_CMD_TX_RATE_CFG: + ret = mwifiex_ret_tx_rate_cfg(priv, resp, data_buf); + break; + case HostCmd_CMD_802_11_SCAN: + ret = mwifiex_ret_802_11_scan(priv, resp, wait_queue); + wait_queue = NULL; + adapter->curr_cmd->wq_buf = NULL; + break; + case HostCmd_CMD_802_11_BG_SCAN_QUERY: + ret = mwifiex_ret_802_11_scan(priv, resp, wait_queue); + dev_dbg(adapter->dev, + "info: CMD_RESP: BG_SCAN result is ready!\n"); + break; + case HostCmd_CMD_TXPWR_CFG: + ret = mwifiex_ret_tx_power_cfg(priv, resp, data_buf); + break; + case HostCmd_CMD_802_11_PS_MODE_ENH: + ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf); + break; + case HostCmd_CMD_802_11_HS_CFG_ENH: + ret = mwifiex_ret_802_11_hs_cfg(priv, resp); + break; + case HostCmd_CMD_802_11_ASSOCIATE: + ret = mwifiex_ret_802_11_associate(priv, resp, wait_queue); + break; + case HostCmd_CMD_802_11_DEAUTHENTICATE: + ret = mwifiex_ret_802_11_deauthenticate(priv, resp); + break; + case HostCmd_CMD_802_11_AD_HOC_START: + case HostCmd_CMD_802_11_AD_HOC_JOIN: + ret = mwifiex_ret_802_11_ad_hoc(priv, resp, wait_queue); + break; + case HostCmd_CMD_802_11_AD_HOC_STOP: + ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp); + break; + case HostCmd_CMD_802_11_GET_LOG: + ret = mwifiex_ret_get_log(priv, resp, data_buf); + break; + case HostCmd_CMD_RSSI_INFO: + ret = mwifiex_ret_802_11_rssi_info(priv, resp, data_buf); + break; + case HostCmd_CMD_802_11_SNMP_MIB: + ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf); + break; + case HostCmd_CMD_802_11_TX_RATE_QUERY: + ret = mwifiex_ret_802_11_tx_rate_query(priv, resp); + break; + case HostCmd_CMD_802_11_RF_CHANNEL: + ret = mwifiex_ret_802_11_rf_channel(priv, resp, data_buf); + break; + case HostCmd_CMD_VERSION_EXT: + ret = mwifiex_ret_ver_ext(priv, resp, data_buf); + break; + case HostCmd_CMD_FUNC_INIT: + case HostCmd_CMD_FUNC_SHUTDOWN: + break; + case HostCmd_CMD_802_11_KEY_MATERIAL: + ret = mwifiex_ret_802_11_key_material(priv, resp); + break; + case HostCmd_CMD_802_11D_DOMAIN_INFO: + ret = mwifiex_ret_802_11d_domain_info(priv, resp); + break; + case HostCmd_CMD_11N_ADDBA_REQ: + ret = mwifiex_ret_11n_addba_req(priv, resp); + break; + case HostCmd_CMD_11N_DELBA: + ret = mwifiex_ret_11n_delba(priv, resp); + break; + case HostCmd_CMD_11N_ADDBA_RSP: + ret = mwifiex_ret_11n_addba_resp(priv, resp); + break; + case HostCmd_CMD_RECONFIGURE_TX_BUFF: + adapter->tx_buf_size = (u16) le16_to_cpu(resp->params. + tx_buf.buff_size); + adapter->tx_buf_size = (adapter->tx_buf_size / + MWIFIEX_SDIO_BLOCK_SIZE) * + MWIFIEX_SDIO_BLOCK_SIZE; + adapter->curr_tx_buf_size = adapter->tx_buf_size; + dev_dbg(adapter->dev, + "cmd: max_tx_buf_size=%d, tx_buf_size=%d\n", + adapter->max_tx_buf_size, adapter->tx_buf_size); + + if (adapter->if_ops.update_mp_end_port) + adapter->if_ops.update_mp_end_port(adapter, + le16_to_cpu(resp-> + params. + tx_buf. + mp_end_port)); + break; + case HostCmd_CMD_AMSDU_AGGR_CTRL: + ret = mwifiex_ret_amsdu_aggr_ctrl(priv, resp, data_buf); + break; + case HostCmd_CMD_WMM_GET_STATUS: + ret = mwifiex_ret_wmm_get_status(priv, resp); + break; + case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: + ret = mwifiex_ret_ibss_coalescing_status(priv, resp); + break; + case HostCmd_CMD_MAC_REG_ACCESS: + case HostCmd_CMD_BBP_REG_ACCESS: + case HostCmd_CMD_RF_REG_ACCESS: + case HostCmd_CMD_PMIC_REG_ACCESS: + case HostCmd_CMD_CAU_REG_ACCESS: + case HostCmd_CMD_802_11_EEPROM_ACCESS: + ret = mwifiex_ret_reg_access(cmdresp_no, resp, data_buf); + break; + case HostCmd_CMD_SET_BSS_MODE: + break; + case HostCmd_CMD_11N_CFG: + ret = mwifiex_ret_11n_cfg(priv, resp, data_buf); + break; + default: + dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", + resp->command); + break; + } + + return ret; +} diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c new file mode 100644 index 000000000000..d4a5c1fcefc2 --- /dev/null +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -0,0 +1,405 @@ +/* + * Marvell Wireless LAN device driver: station event handling + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" + +/* + * This function resets the connection state. + * + * The function is invoked after receiving a disconnect event from firmware, + * and performs the following actions - + * - Set media status to disconnected + * - Clean up Tx and Rx packets + * - Resets SNR/NF/RSSI value in driver + * - Resets security configurations in driver + * - Enables auto data rate + * - Saves the previous SSID and BSSID so that they can + * be used for re-association, if required + * - Erases current SSID and BSSID information + * - Sends a disconnect event to upper layers/applications. + */ +void +mwifiex_reset_connect_state(struct mwifiex_private *priv) +{ + struct mwifiex_adapter *adapter = priv->adapter; + + if (!priv->media_connected) + return; + + dev_dbg(adapter->dev, "info: handles disconnect event\n"); + + priv->media_connected = false; + + priv->scan_block = false; + + /* Free Tx and Rx packets, report disconnect to upper layer */ + mwifiex_clean_txrx(priv); + + /* Reset SNR/NF/RSSI values */ + priv->data_rssi_last = 0; + priv->data_nf_last = 0; + priv->data_rssi_avg = 0; + priv->data_nf_avg = 0; + priv->bcn_rssi_last = 0; + priv->bcn_nf_last = 0; + priv->bcn_rssi_avg = 0; + priv->bcn_nf_avg = 0; + priv->rxpd_rate = 0; + priv->rxpd_htinfo = 0; + priv->sec_info.wpa_enabled = false; + priv->sec_info.wpa2_enabled = false; + priv->wpa_ie_len = 0; + + priv->sec_info.wapi_enabled = false; + priv->wapi_ie_len = 0; + priv->sec_info.wapi_key_on = false; + + priv->sec_info.encryption_mode = MWIFIEX_ENCRYPTION_MODE_NONE; + + /* Enable auto data rate */ + priv->is_data_rate_auto = true; + priv->data_rate = 0; + + if (priv->bss_mode == MWIFIEX_BSS_MODE_IBSS) { + priv->adhoc_state = ADHOC_IDLE; + priv->adhoc_is_link_sensed = false; + } + + /* + * Memorize the previous SSID and BSSID so + * it could be used for re-assoc + */ + + dev_dbg(adapter->dev, "info: previous SSID=%s, SSID len=%u\n", + priv->prev_ssid.ssid, priv->prev_ssid.ssid_len); + + dev_dbg(adapter->dev, "info: current SSID=%s, SSID len=%u\n", + priv->curr_bss_params.bss_descriptor.ssid.ssid, + priv->curr_bss_params.bss_descriptor.ssid.ssid_len); + + memcpy(&priv->prev_ssid, + &priv->curr_bss_params.bss_descriptor.ssid, + sizeof(struct mwifiex_802_11_ssid)); + + memcpy(priv->prev_bssid, + priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN); + + /* Need to erase the current SSID and BSSID info */ + memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params)); + + adapter->tx_lock_flag = false; + adapter->pps_uapsd_mode = false; + + if (adapter->num_cmd_timeout && adapter->curr_cmd) + return; + priv->media_connected = false; + if (!priv->disconnect) { + priv->disconnect = 1; + dev_dbg(adapter->dev, "info: successfully disconnected from" + " %pM: reason code %d\n", priv->cfg_bssid, + WLAN_REASON_DEAUTH_LEAVING); + cfg80211_disconnected(priv->netdev, + WLAN_REASON_DEAUTH_LEAVING, NULL, 0, + GFP_KERNEL); + queue_work(priv->workqueue, &priv->cfg_workqueue); + } + if (!netif_queue_stopped(priv->netdev)) + netif_stop_queue(priv->netdev); + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + /* Reset wireless stats signal info */ + priv->w_stats.qual.level = 0; + priv->w_stats.qual.noise = 0; +} + +/* + * This function handles events generated by firmware. + * + * This is a generic function and handles all events. + * + * Event specific routines are called by this function based + * upon the generated event cause. + * + * For the following events, the function just forwards them to upper + * layers, optionally recording the change - + * - EVENT_LINK_SENSED + * - EVENT_MIC_ERR_UNICAST + * - EVENT_MIC_ERR_MULTICAST + * - EVENT_PORT_RELEASE + * - EVENT_RSSI_LOW + * - EVENT_SNR_LOW + * - EVENT_MAX_FAIL + * - EVENT_RSSI_HIGH + * - EVENT_SNR_HIGH + * - EVENT_DATA_RSSI_LOW + * - EVENT_DATA_SNR_LOW + * - EVENT_DATA_RSSI_HIGH + * - EVENT_DATA_SNR_HIGH + * - EVENT_LINK_QUALITY + * - EVENT_PRE_BEACON_LOST + * - EVENT_IBSS_COALESCED + * - EVENT_WEP_ICV_ERR + * - EVENT_BW_CHANGE + * - EVENT_HOSTWAKE_STAIE + * + * For the following events, no action is taken - + * - EVENT_MIB_CHANGED + * - EVENT_INIT_DONE + * - EVENT_DUMMY_HOST_WAKEUP_SIGNAL + * + * Rest of the supported events requires driver handling - + * - EVENT_DEAUTHENTICATED + * - EVENT_DISASSOCIATED + * - EVENT_LINK_LOST + * - EVENT_PS_SLEEP + * - EVENT_PS_AWAKE + * - EVENT_DEEP_SLEEP_AWAKE + * - EVENT_HS_ACT_REQ + * - EVENT_ADHOC_BCN_LOST + * - EVENT_BG_SCAN_REPORT + * - EVENT_WMM_STATUS_CHANGE + * - EVENT_ADDBA + * - EVENT_DELBA + * - EVENT_BA_STREAM_TIEMOUT + * - EVENT_AMSDU_AGGR_CTRL + */ +int mwifiex_process_sta_event(struct mwifiex_private *priv) +{ + struct mwifiex_adapter *adapter = priv->adapter; + int ret = 0; + u32 eventcause = adapter->event_cause; + + switch (eventcause) { + case EVENT_DUMMY_HOST_WAKEUP_SIGNAL: + dev_err(adapter->dev, "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL," + " ignoring it\n"); + break; + case EVENT_LINK_SENSED: + dev_dbg(adapter->dev, "event: LINK_SENSED\n"); + if (!netif_carrier_ok(priv->netdev)) + netif_carrier_on(priv->netdev); + if (netif_queue_stopped(priv->netdev)) + netif_wake_queue(priv->netdev); + break; + + case EVENT_DEAUTHENTICATED: + dev_dbg(adapter->dev, "event: Deauthenticated\n"); + adapter->dbg.num_event_deauth++; + if (priv->media_connected) + mwifiex_reset_connect_state(priv); + break; + + case EVENT_DISASSOCIATED: + dev_dbg(adapter->dev, "event: Disassociated\n"); + adapter->dbg.num_event_disassoc++; + if (priv->media_connected) + mwifiex_reset_connect_state(priv); + break; + + case EVENT_LINK_LOST: + dev_dbg(adapter->dev, "event: Link lost\n"); + adapter->dbg.num_event_link_lost++; + if (priv->media_connected) + mwifiex_reset_connect_state(priv); + break; + + case EVENT_PS_SLEEP: + dev_dbg(adapter->dev, "info: EVENT: SLEEP\n"); + + adapter->ps_state = PS_STATE_PRE_SLEEP; + + mwifiex_check_ps_cond(adapter); + break; + + case EVENT_PS_AWAKE: + dev_dbg(adapter->dev, "info: EVENT: AWAKE\n"); + if (!adapter->pps_uapsd_mode && + priv->media_connected && + adapter->sleep_period.period) { + adapter->pps_uapsd_mode = true; + dev_dbg(adapter->dev, + "event: PPS/UAPSD mode activated\n"); + } + adapter->tx_lock_flag = false; + if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { + if (mwifiex_check_last_packet_indication(priv)) { + if (!adapter->data_sent) { + if (!mwifiex_send_null_packet(priv, + MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET + | + MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) + adapter->ps_state = + PS_STATE_SLEEP; + return 0; + } + } + } + adapter->ps_state = PS_STATE_AWAKE; + adapter->pm_wakeup_card_req = false; + adapter->pm_wakeup_fw_try = false; + + break; + + case EVENT_DEEP_SLEEP_AWAKE: + adapter->if_ops.wakeup_complete(adapter); + dev_dbg(adapter->dev, "event: DS_AWAKE\n"); + if (adapter->is_deep_sleep) + adapter->is_deep_sleep = false; + break; + + case EVENT_HS_ACT_REQ: + dev_dbg(adapter->dev, "event: HS_ACT_REQ\n"); + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH, + 0, 0, NULL, NULL); + break; + + case EVENT_MIC_ERR_UNICAST: + dev_dbg(adapter->dev, "event: UNICAST MIC ERROR\n"); + break; + + case EVENT_MIC_ERR_MULTICAST: + dev_dbg(adapter->dev, "event: MULTICAST MIC ERROR\n"); + break; + case EVENT_MIB_CHANGED: + case EVENT_INIT_DONE: + break; + + case EVENT_ADHOC_BCN_LOST: + dev_dbg(adapter->dev, "event: ADHOC_BCN_LOST\n"); + priv->adhoc_is_link_sensed = false; + mwifiex_clean_txrx(priv); + if (!netif_queue_stopped(priv->netdev)) + netif_stop_queue(priv->netdev); + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + break; + + case EVENT_BG_SCAN_REPORT: + dev_dbg(adapter->dev, "event: BGS_REPORT\n"); + /* Clear the previous scan result */ + memset(adapter->scan_table, 0x00, + sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP); + adapter->num_in_scan_table = 0; + adapter->bcn_buf_end = adapter->bcn_buf; + ret = mwifiex_prepare_cmd(priv, + HostCmd_CMD_802_11_BG_SCAN_QUERY, + HostCmd_ACT_GEN_GET, 0, NULL, NULL); + break; + + case EVENT_PORT_RELEASE: + dev_dbg(adapter->dev, "event: PORT RELEASE\n"); + break; + + case EVENT_WMM_STATUS_CHANGE: + dev_dbg(adapter->dev, "event: WMM status changed\n"); + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_WMM_GET_STATUS, + 0, 0, NULL, NULL); + break; + + case EVENT_RSSI_LOW: + dev_dbg(adapter->dev, "event: Beacon RSSI_LOW\n"); + break; + case EVENT_SNR_LOW: + dev_dbg(adapter->dev, "event: Beacon SNR_LOW\n"); + break; + case EVENT_MAX_FAIL: + dev_dbg(adapter->dev, "event: MAX_FAIL\n"); + break; + case EVENT_RSSI_HIGH: + dev_dbg(adapter->dev, "event: Beacon RSSI_HIGH\n"); + break; + case EVENT_SNR_HIGH: + dev_dbg(adapter->dev, "event: Beacon SNR_HIGH\n"); + break; + case EVENT_DATA_RSSI_LOW: + dev_dbg(adapter->dev, "event: Data RSSI_LOW\n"); + break; + case EVENT_DATA_SNR_LOW: + dev_dbg(adapter->dev, "event: Data SNR_LOW\n"); + break; + case EVENT_DATA_RSSI_HIGH: + dev_dbg(adapter->dev, "event: Data RSSI_HIGH\n"); + break; + case EVENT_DATA_SNR_HIGH: + dev_dbg(adapter->dev, "event: Data SNR_HIGH\n"); + break; + case EVENT_LINK_QUALITY: + dev_dbg(adapter->dev, "event: Link Quality\n"); + break; + case EVENT_PRE_BEACON_LOST: + dev_dbg(adapter->dev, "event: Pre-Beacon Lost\n"); + break; + case EVENT_IBSS_COALESCED: + dev_dbg(adapter->dev, "event: IBSS_COALESCED\n"); + ret = mwifiex_prepare_cmd(priv, + HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, + HostCmd_ACT_GEN_GET, 0, NULL, NULL); + break; + case EVENT_ADDBA: + dev_dbg(adapter->dev, "event: ADDBA Request\n"); + mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP, + HostCmd_ACT_GEN_SET, 0, NULL, + adapter->event_body); + break; + case EVENT_DELBA: + dev_dbg(adapter->dev, "event: DELBA Request\n"); + mwifiex_11n_delete_ba_stream(priv, adapter->event_body); + break; + case EVENT_BA_STREAM_TIEMOUT: + dev_dbg(adapter->dev, "event: BA Stream timeout\n"); + mwifiex_11n_ba_stream_timeout(priv, + (struct host_cmd_ds_11n_batimeout + *) + adapter->event_body); + break; + case EVENT_AMSDU_AGGR_CTRL: + dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", + *(u16 *) adapter->event_body); + adapter->tx_buf_size = + min(adapter->curr_tx_buf_size, + le16_to_cpu(*(__le16 *) adapter->event_body)); + dev_dbg(adapter->dev, "event: tx_buf_size %d\n", + adapter->tx_buf_size); + break; + + case EVENT_WEP_ICV_ERR: + dev_dbg(adapter->dev, "event: WEP ICV error\n"); + break; + + case EVENT_BW_CHANGE: + dev_dbg(adapter->dev, "event: BW Change\n"); + break; + + case EVENT_HOSTWAKE_STAIE: + dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause); + break; + default: + dev_dbg(adapter->dev, "event: unknown event id: %#x\n", + eventcause); + break; + } + + return ret; +} diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c new file mode 100644 index 000000000000..665a519b1403 --- /dev/null +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -0,0 +1,2478 @@ +/* + * Marvell Wireless LAN device driver: functions for station ioctl + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" +#include "cfg80211.h" + +/* + * Copies the multicast address list from device to driver. + * + * This function does not validate the destination memory for + * size, and the calling function must ensure enough memory is + * available. + */ +static int +mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, + struct net_device *dev) +{ + int i = 0; + struct netdev_hw_addr *ha; + + netdev_for_each_mc_addr(ha, dev) + memcpy(&mlist->mac_list[i++], ha->addr, ETH_ALEN); + + return i; +} + +/* + * Allocate and fills a wait queue with proper parameters. + * + * This function needs to be called before an IOCTL request can be made. + * It can handle the following wait options: + * MWIFIEX_NO_WAIT - Waiting is disabled + * MWIFIEX_IOCTL_WAIT - Waiting is done on IOCTL wait queue + * MWIFIEX_CMD_WAIT - Waiting is done on command wait queue + * MWIFIEX_WSTATS_WAIT - Waiting is done on stats wait queue + */ +struct mwifiex_wait_queue * +mwifiex_alloc_fill_wait_queue(struct mwifiex_private *priv, + u8 wait_option) +{ + struct mwifiex_wait_queue *wait = NULL; + + wait = (struct mwifiex_wait_queue *) + kzalloc(sizeof(struct mwifiex_wait_queue), GFP_ATOMIC); + if (!wait) { + dev_err(priv->adapter->dev, "%s: fail to alloc buffer\n", + __func__); + return wait; + } + + wait->bss_index = priv->bss_index; + + switch (wait_option) { + case MWIFIEX_NO_WAIT: + wait->enabled = 0; + break; + case MWIFIEX_IOCTL_WAIT: + priv->ioctl_wait_q_woken = false; + wait->start_time = jiffies; + wait->wait = &priv->ioctl_wait_q; + wait->condition = &priv->ioctl_wait_q_woken; + wait->enabled = 1; + break; + case MWIFIEX_CMD_WAIT: + priv->cmd_wait_q_woken = false; + wait->start_time = jiffies; + wait->wait = &priv->cmd_wait_q; + wait->condition = &priv->cmd_wait_q_woken; + wait->enabled = 1; + break; + case MWIFIEX_WSTATS_WAIT: + priv->w_stats_wait_q_woken = false; + wait->start_time = jiffies; + wait->wait = &priv->w_stats_wait_q; + wait->condition = &priv->w_stats_wait_q_woken; + wait->enabled = 1; + break; + } + + return wait; +} + +/* + * Wait queue completion handler. + * + * This function waits on a particular wait queue. + * For NO_WAIT option, it returns immediately. It also cancels the + * pending IOCTL request after waking up, in case of errors. + */ +static void +mwifiex_wait_ioctl_complete(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + u8 wait_option) +{ + bool cancel_flag = false; + + switch (wait_option) { + case MWIFIEX_NO_WAIT: + break; + case MWIFIEX_IOCTL_WAIT: + wait_event_interruptible(priv->ioctl_wait_q, + priv->ioctl_wait_q_woken); + if (!priv->ioctl_wait_q_woken) + cancel_flag = true; + break; + case MWIFIEX_CMD_WAIT: + wait_event_interruptible(priv->cmd_wait_q, + priv->cmd_wait_q_woken); + if (!priv->cmd_wait_q_woken) + cancel_flag = true; + break; + case MWIFIEX_WSTATS_WAIT: + wait_event_interruptible(priv->w_stats_wait_q, + priv->w_stats_wait_q_woken); + if (!priv->w_stats_wait_q_woken) + cancel_flag = true; + break; + } + if (cancel_flag) { + mwifiex_cancel_pending_ioctl(priv->adapter, wait); + dev_dbg(priv->adapter->dev, "cmd: IOCTL cancel: wait=%p, wait_option=%d\n", + wait, wait_option); + } + + return; +} + +/* + * The function waits for the request to complete and issues the + * completion handler, if required. + */ +int mwifiex_request_ioctl(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + int status, u8 wait_option) +{ + switch (status) { + case -EINPROGRESS: + dev_dbg(priv->adapter->dev, "cmd: IOCTL pending: wait=%p, wait_option=%d\n", + wait, wait_option); + atomic_inc(&priv->adapter->ioctl_pending); + /* Status pending, wake up main process */ + queue_work(priv->adapter->workqueue, &priv->adapter->main_work); + + /* Wait for completion */ + if (wait_option) { + mwifiex_wait_ioctl_complete(priv, wait, wait_option); + status = wait->status; + } + break; + case 0: + case -1: + case -EBUSY: + default: + break; + } + return status; +} +EXPORT_SYMBOL_GPL(mwifiex_request_ioctl); + +/* + * IOCTL request handler to set/get MAC address. + * + * This function prepares the correct firmware command and + * issues it to get the extended version information. + */ +static int mwifiex_bss_ioctl_mac_address(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + u8 action, u8 *mac) +{ + int ret = 0; + + if ((action == HostCmd_ACT_GEN_GET) && mac) { + memcpy(mac, priv->curr_addr, ETH_ALEN); + return 0; + } + + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_MAC_ADDRESS, + action, 0, wait, mac); + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * Sends IOCTL request to set MAC address. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int mwifiex_request_set_mac_address(struct mwifiex_private *priv) +{ + struct mwifiex_wait_queue *wait = NULL; + int status = 0; + u8 wait_option = MWIFIEX_CMD_WAIT; + + /* Allocate wait buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + status = mwifiex_bss_ioctl_mac_address(priv, wait, HostCmd_ACT_GEN_SET, + NULL); + + status = mwifiex_request_ioctl(priv, wait, status, wait_option); + if (!status) + memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN); + else + dev_err(priv->adapter->dev, "set mac address failed: status=%d" + " error_code=%#x\n", status, wait->status); + + kfree(wait); + return status; +} + +/* + * IOCTL request handler to set multicast list. + * + * This function prepares the correct firmware command and + * issues it to set the multicast list. + * + * This function can be used to enable promiscuous mode, or enable all + * multicast packets, or to enable selective multicast. + */ +static int +mwifiex_bss_ioctl_multicast_list(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + u16 action, + struct mwifiex_multicast_list *mcast_list) +{ + int ret = 0; + u16 old_pkt_filter; + + old_pkt_filter = priv->curr_pkt_filter; + if (action == HostCmd_ACT_GEN_GET) + return -1; + + if (mcast_list->mode == MWIFIEX_PROMISC_MODE) { + dev_dbg(priv->adapter->dev, "info: Enable Promiscuous mode\n"); + priv->curr_pkt_filter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; + priv->curr_pkt_filter &= + ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; + } else { + /* Multicast */ + priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; + if (mcast_list->mode == MWIFIEX_MULTICAST_MODE) { + dev_dbg(priv->adapter->dev, + "info: Enabling All Multicast!\n"); + priv->curr_pkt_filter |= + HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; + } else { + priv->curr_pkt_filter &= + ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; + if (mcast_list->num_multicast_addr) { + dev_dbg(priv->adapter->dev, + "info: Set multicast list=%d\n", + mcast_list->num_multicast_addr); + /* Set multicast addresses to firmware */ + if (old_pkt_filter == priv->curr_pkt_filter) { + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, + HostCmd_CMD_MAC_MULTICAST_ADR, + action, 0, wait, mcast_list); + if (!ret) + ret = -EINPROGRESS; + } else { + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, + HostCmd_CMD_MAC_MULTICAST_ADR, + action, 0, NULL, + mcast_list); + } + } + } + } + dev_dbg(priv->adapter->dev, + "info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n", + old_pkt_filter, priv->curr_pkt_filter); + if (old_pkt_filter != priv->curr_pkt_filter) { + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, action, + 0, wait, &priv->curr_pkt_filter); + if (!ret) + ret = -EINPROGRESS; + } + + return ret; +} + +/* + * Sends IOCTL request to set multicast list. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +void +mwifiex_request_set_multicast_list(struct mwifiex_private *priv, + struct net_device *dev) +{ + struct mwifiex_wait_queue *wait = NULL; + struct mwifiex_multicast_list mcast_list; + u8 wait_option = MWIFIEX_NO_WAIT; + int status = 0; + + /* Allocate wait buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return; + + if (dev->flags & IFF_PROMISC) { + mcast_list.mode = MWIFIEX_PROMISC_MODE; + } else if (dev->flags & IFF_ALLMULTI || + netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) { + mcast_list.mode = MWIFIEX_ALL_MULTI_MODE; + } else { + mcast_list.mode = MWIFIEX_MULTICAST_MODE; + if (netdev_mc_count(dev)) + mcast_list.num_multicast_addr = + mwifiex_copy_mcast_addr(&mcast_list, dev); + } + status = mwifiex_bss_ioctl_multicast_list(priv, wait, + HostCmd_ACT_GEN_SET, + &mcast_list); + + status = mwifiex_request_ioctl(priv, wait, status, wait_option); + if (wait && status != -EINPROGRESS) + kfree(wait); + + return; +} + +/* + * IOCTL request handler to disconnect from a BSS/IBSS. + */ +static int mwifiex_bss_ioctl_stop(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, u8 *mac) +{ + return mwifiex_deauthenticate(priv, wait, mac); +} + +/* + * Sends IOCTL request to disconnect from a BSS. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int mwifiex_disconnect(struct mwifiex_private *priv, u8 wait_option, u8 *mac) +{ + struct mwifiex_wait_queue *wait = NULL; + int status = 0; + + /* Allocate wait buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + status = mwifiex_bss_ioctl_stop(priv, wait, mac); + + status = mwifiex_request_ioctl(priv, wait, status, wait_option); + + kfree(wait); + return status; +} +EXPORT_SYMBOL_GPL(mwifiex_disconnect); + +/* + * IOCTL request handler to join a BSS/IBSS. + * + * In Ad-Hoc mode, the IBSS is created if not found in scan list. + * In both Ad-Hoc and infra mode, an deauthentication is performed + * first. + */ +static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + struct mwifiex_ssid_bssid *ssid_bssid) +{ + int ret = 0; + struct mwifiex_adapter *adapter = priv->adapter; + s32 i = -1; + + priv->scan_block = false; + if (!ssid_bssid) + return -1; + + if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA) { + /* Infra mode */ + ret = mwifiex_deauthenticate(priv, NULL, NULL); + if (ret) + return ret; + + /* Search for the requested SSID in the scan table */ + if (ssid_bssid->ssid.ssid_len) + i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, + NULL, MWIFIEX_BSS_MODE_INFRA); + else + i = mwifiex_find_bssid_in_list(priv, + (u8 *) &ssid_bssid->bssid, + MWIFIEX_BSS_MODE_INFRA); + if (i < 0) + return -1; + + dev_dbg(adapter->dev, + "info: SSID found in scan list ... associating...\n"); + + /* Clear any past association response stored for + * application retrieval */ + priv->assoc_rsp_size = 0; + ret = mwifiex_associate(priv, wait, &adapter->scan_table[i]); + if (ret) + return ret; + } else { + /* Adhoc mode */ + /* If the requested SSID matches current SSID, return */ + if (ssid_bssid->ssid.ssid_len && + (!mwifiex_ssid_cmp + (&priv->curr_bss_params.bss_descriptor.ssid, + &ssid_bssid->ssid))) + return 0; + + /* Exit Adhoc mode first */ + dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n"); + ret = mwifiex_deauthenticate(priv, NULL, NULL); + if (ret) + return ret; + + priv->adhoc_is_link_sensed = false; + + /* Search for the requested network in the scan table */ + if (ssid_bssid->ssid.ssid_len) + i = mwifiex_find_ssid_in_list(priv, + &ssid_bssid->ssid, NULL, + MWIFIEX_BSS_MODE_IBSS); + else + i = mwifiex_find_bssid_in_list(priv, + (u8 *)&ssid_bssid->bssid, + MWIFIEX_BSS_MODE_IBSS); + + if (i >= 0) { + dev_dbg(adapter->dev, "info: network found in scan" + " list. Joining...\n"); + ret = mwifiex_adhoc_join(priv, wait, + &adapter->scan_table[i]); + if (ret) + return ret; + } else { /* i >= 0 */ + dev_dbg(adapter->dev, "info: Network not found in " + "the list, creating adhoc with ssid = %s\n", + ssid_bssid->ssid.ssid); + ret = mwifiex_adhoc_start(priv, wait, + &ssid_bssid->ssid); + if (ret) + return ret; + } + } + + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * Sends IOCTL request to connect with a BSS. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int mwifiex_bss_start(struct mwifiex_private *priv, u8 wait_option, + struct mwifiex_ssid_bssid *ssid_bssid) +{ + struct mwifiex_wait_queue *wait = NULL; + struct mwifiex_ssid_bssid tmp_ssid_bssid; + int status = 0; + + /* Stop the O.S. TX queue if needed */ + if (!netif_queue_stopped(priv->netdev)) + netif_stop_queue(priv->netdev); + + /* Allocate wait buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + if (ssid_bssid) + memcpy(&tmp_ssid_bssid, ssid_bssid, + sizeof(struct mwifiex_ssid_bssid)); + status = mwifiex_bss_ioctl_start(priv, wait, &tmp_ssid_bssid); + + status = mwifiex_request_ioctl(priv, wait, status, wait_option); + + kfree(wait); + return status; +} + +/* + * IOCTL request handler to set host sleep configuration. + * + * This function prepares the correct firmware command and + * issues it. + */ +static int +mwifiex_pm_ioctl_hs_cfg(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + u16 action, struct mwifiex_ds_hs_cfg *hs_cfg) +{ + struct mwifiex_adapter *adapter = priv->adapter; + int status = 0; + u32 prev_cond = 0; + + switch (action) { + case HostCmd_ACT_GEN_SET: + if (adapter->pps_uapsd_mode) { + dev_dbg(adapter->dev, "info: Host Sleep IOCTL" + " is blocked in UAPSD/PPS mode\n"); + status = -1; + break; + } + if (hs_cfg->is_invoke_hostcmd) { + if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) { + if (!adapter->is_hs_configured) + /* Already cancelled */ + break; + /* Save previous condition */ + prev_cond = le32_to_cpu(adapter->hs_cfg + .conditions); + adapter->hs_cfg.conditions = + cpu_to_le32(hs_cfg->conditions); + } else if (hs_cfg->conditions) { + adapter->hs_cfg.conditions = + cpu_to_le32(hs_cfg->conditions); + adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; + if (hs_cfg->gap) + adapter->hs_cfg.gap = (u8)hs_cfg->gap; + } else if (adapter->hs_cfg.conditions == + cpu_to_le32( + HOST_SLEEP_CFG_CANCEL)) { + /* Return failure if no parameters for HS + enable */ + status = -1; + break; + } + status = mwifiex_prepare_cmd(priv, + HostCmd_CMD_802_11_HS_CFG_ENH, + HostCmd_ACT_GEN_SET, + 0, wait, &adapter->hs_cfg); + if (!status) + status = -EINPROGRESS; + if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) + /* Restore previous condition */ + adapter->hs_cfg.conditions = + cpu_to_le32(prev_cond); + } else { + adapter->hs_cfg.conditions = + cpu_to_le32(hs_cfg->conditions); + adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; + adapter->hs_cfg.gap = (u8)hs_cfg->gap; + } + break; + case HostCmd_ACT_GEN_GET: + hs_cfg->conditions = le32_to_cpu(adapter->hs_cfg.conditions); + hs_cfg->gpio = adapter->hs_cfg.gpio; + hs_cfg->gap = adapter->hs_cfg.gap; + break; + default: + status = -1; + break; + } + + return status; +} + +/* + * Sends IOCTL request to set Host Sleep parameters. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, + u8 wait_option, + struct mwifiex_ds_hs_cfg *hscfg) +{ + int ret = 0; + struct mwifiex_wait_queue *wait = NULL; + + if (!hscfg) + return -ENOMEM; + + /* Allocate wait buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + ret = mwifiex_pm_ioctl_hs_cfg(priv, wait, action, hscfg); + + ret = mwifiex_request_ioctl(priv, wait, ret, wait_option); + + if (wait && (ret != -EINPROGRESS)) + kfree(wait); + return ret; +} + +/* + * Sends IOCTL request to cancel the existing Host Sleep configuration. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int mwifiex_cancel_hs(struct mwifiex_private *priv, u8 wait_option) +{ + int ret = 0; + struct mwifiex_ds_hs_cfg hscfg; + + /* Cancel Host Sleep */ + hscfg.conditions = HOST_SLEEP_CFG_CANCEL; + hscfg.is_invoke_hostcmd = true; + ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, + wait_option, &hscfg); + + return ret; +} +EXPORT_SYMBOL_GPL(mwifiex_cancel_hs); + +/* + * Sends IOCTL request to cancel the existing Host Sleep configuration. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int mwifiex_enable_hs(struct mwifiex_adapter *adapter) +{ + struct mwifiex_ds_hs_cfg hscfg; + + if (adapter->hs_activated) { + dev_dbg(adapter->dev, "cmd: HS Already actived\n"); + return true; + } + + /* Enable Host Sleep */ + adapter->hs_activate_wait_q_woken = false; + + memset(&hscfg, 0, sizeof(struct mwifiex_hs_config_param)); + hscfg.is_invoke_hostcmd = true; + + if (mwifiex_set_hs_params(mwifiex_get_priv(adapter, + MWIFIEX_BSS_ROLE_STA), + HostCmd_ACT_GEN_SET, + MWIFIEX_IOCTL_WAIT, &hscfg)) { + dev_err(adapter->dev, "IOCTL request HS enable failed\n"); + return false; + } + + wait_event_interruptible(adapter->hs_activate_wait_q, + adapter->hs_activate_wait_q_woken); + + return true; +} +EXPORT_SYMBOL_GPL(mwifiex_enable_hs); + +/* + * IOCTL request handler to get signal information. + * + * This function prepares the correct firmware command and + * issues it to get the signal (RSSI) information. + * + * This only works in the connected mode. + */ +static int mwifiex_get_info_signal(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + struct mwifiex_ds_get_signal *signal) +{ + int ret = 0; + + if (!wait) { + dev_err(priv->adapter->dev, "WAIT information is not present\n"); + return -1; + } + + /* Signal info can be obtained only if connected */ + if (!priv->media_connected) { + dev_dbg(priv->adapter->dev, + "info: Can not get signal in disconnected state\n"); + return -1; + } + + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_RSSI_INFO, + HostCmd_ACT_GEN_GET, 0, wait, signal); + + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * IOCTL request handler to get statistics. + * + * This function prepares the correct firmware command and + * issues it to get the statistics (RSSI) information. + */ +static int mwifiex_get_info_stats(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + struct mwifiex_ds_get_stats *log) +{ + int ret = 0; + + if (!wait) { + dev_err(priv->adapter->dev, "MWIFIEX IOCTL information is not present\n"); + return -1; + } + + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_GET_LOG, + HostCmd_ACT_GEN_GET, 0, wait, log); + + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * IOCTL request handler to get BSS information. + * + * This function collates the information from different driver structures + * to send to the user. + */ +int mwifiex_get_bss_info(struct mwifiex_private *priv, + struct mwifiex_bss_info *info) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_bssdescriptor *bss_desc; + s32 tbl_idx = 0; + + if (!info) + return -1; + + /* Get current BSS info */ + bss_desc = &priv->curr_bss_params.bss_descriptor; + + /* BSS mode */ + info->bss_mode = priv->bss_mode; + + /* SSID */ + memcpy(&info->ssid, &bss_desc->ssid, + sizeof(struct mwifiex_802_11_ssid)); + + /* BSSID */ + memcpy(&info->bssid, &bss_desc->mac_address, ETH_ALEN); + + /* Channel */ + info->bss_chan = bss_desc->channel; + + /* Region code */ + info->region_code = adapter->region_code; + + /* Scan table index if connected */ + info->scan_table_idx = 0; + if (priv->media_connected) { + tbl_idx = + mwifiex_find_ssid_in_list(priv, &bss_desc->ssid, + bss_desc->mac_address, + priv->bss_mode); + if (tbl_idx >= 0) + info->scan_table_idx = tbl_idx; + } + + /* Connection status */ + info->media_connected = priv->media_connected; + + /* Radio status */ + info->radio_on = adapter->radio_on; + + /* Tx power information */ + info->max_power_level = priv->max_tx_power_level; + info->min_power_level = priv->min_tx_power_level; + + /* AdHoc state */ + info->adhoc_state = priv->adhoc_state; + + /* Last beacon NF */ + info->bcn_nf_last = priv->bcn_nf_last; + + /* wep status */ + if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED) + info->wep_status = true; + else + info->wep_status = false; + + info->is_hs_configured = adapter->is_hs_configured; + info->is_deep_sleep = adapter->is_deep_sleep; + + return 0; +} + +/* + * IOCTL request handler to get extended version information. + * + * This function prepares the correct firmware command and + * issues it to get the extended version information. + */ +static int mwifiex_get_info_ver_ext(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + struct mwifiex_ver_ext *ver_ext) +{ + int ret = 0; + + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_VERSION_EXT, + HostCmd_ACT_GEN_GET, 0, wait, ver_ext); + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * IOCTL request handler to set/get SNMP MIB parameters. + * + * This function prepares the correct firmware command and + * issues it. + * + * Currently the following parameters are supported - + * Set/get RTS Threshold + * Set/get fragmentation threshold + * Set/get retry count + */ +int mwifiex_snmp_mib_ioctl(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + u32 cmd_oid, u16 action, u32 *value) +{ + int ret = 0; + + if (!value) + return -1; + + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, + action, cmd_oid, wait, value); + + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * IOCTL request handler to set/get band configurations. + * + * For SET operation, it performs extra checks to make sure the Ad-Hoc + * band and channel are compatible. Otherwise it returns an error. + * + * For GET operation, this function retrieves the following information - + * - Infra bands + * - Ad-hoc band + * - Ad-hoc channel + * - Secondary channel offset + */ +int mwifiex_radio_ioctl_band_cfg(struct mwifiex_private *priv, + u16 action, + struct mwifiex_ds_band_cfg *radio_cfg) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u8 infra_band = 0; + u8 adhoc_band = 0; + u32 adhoc_channel = 0; + + if (action == HostCmd_ACT_GEN_GET) { + /* Infra Bands */ + radio_cfg->config_bands = adapter->config_bands; + /* Adhoc Band */ + radio_cfg->adhoc_start_band = adapter->adhoc_start_band; + /* Adhoc channel */ + radio_cfg->adhoc_channel = priv->adhoc_channel; + /* Secondary channel offset */ + radio_cfg->sec_chan_offset = adapter->chan_offset; + return 0; + } + + /* For action = SET */ + infra_band = (u8) radio_cfg->config_bands; + adhoc_band = (u8) radio_cfg->adhoc_start_band; + adhoc_channel = radio_cfg->adhoc_channel; + + /* SET Infra band */ + if ((infra_band | adapter->fw_bands) & ~adapter->fw_bands) + return -1; + + adapter->config_bands = infra_band; + + /* SET Ad-hoc Band */ + if ((adhoc_band | adapter->fw_bands) & ~adapter->fw_bands) + return -1; + + if (adhoc_band) + adapter->adhoc_start_band = adhoc_band; + adapter->chan_offset = (u8) radio_cfg->sec_chan_offset; + /* + * If no adhoc_channel is supplied verify if the existing adhoc + * channel compiles with new adhoc_band + */ + if (!adhoc_channel) { + if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211 + (priv, adapter->adhoc_start_band, + priv->adhoc_channel)) { + /* Pass back the default channel */ + radio_cfg->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; + if ((adapter->adhoc_start_band & BAND_A) + || (adapter->adhoc_start_band & BAND_AN)) + radio_cfg->adhoc_channel = + DEFAULT_AD_HOC_CHANNEL_A; + } + } else { /* Retrurn error if adhoc_band and + adhoc_channel combination is invalid */ + if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211 + (priv, adapter->adhoc_start_band, (u16) adhoc_channel)) + return -1; + priv->adhoc_channel = (u8) adhoc_channel; + } + if ((adhoc_band & BAND_GN) || (adhoc_band & BAND_AN)) + adapter->adhoc_11n_enabled = true; + else + adapter->adhoc_11n_enabled = false; + + return 0; +} + +/* + * IOCTL request handler to set/get active channel. + * + * This function performs validity checking on channel/frequency + * compatibility and returns failure if not valid. + */ +int mwifiex_bss_ioctl_channel(struct mwifiex_private *priv, u16 action, + struct mwifiex_chan_freq_power *chan) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_chan_freq_power *cfp = NULL; + + if (!chan) + return -1; + + if (action == HostCmd_ACT_GEN_GET) { + cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv, + priv->curr_bss_params.band, + (u16) priv->curr_bss_params.bss_descriptor. + channel); + chan->channel = cfp->channel; + chan->freq = cfp->freq; + + return 0; + } + if (!chan->channel && !chan->freq) + return -1; + if (adapter->adhoc_start_band & BAND_AN) + adapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN; + else if (adapter->adhoc_start_band & BAND_A) + adapter->adhoc_start_band = BAND_G | BAND_B; + if (chan->channel) { + if (chan->channel <= MAX_CHANNEL_BAND_BG) + cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211 + (priv, 0, (u16) chan->channel); + if (!cfp) { + cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211 + (priv, BAND_A, (u16) chan->channel); + if (cfp) { + if (adapter->adhoc_11n_enabled) + adapter->adhoc_start_band = BAND_A + | BAND_AN; + else + adapter->adhoc_start_band = BAND_A; + } + } + } else { + if (chan->freq <= MAX_FREQUENCY_BAND_BG) + cfp = mwifiex_get_cfp_by_band_and_freq_from_cfg80211( + priv, 0, chan->freq); + if (!cfp) { + cfp = mwifiex_get_cfp_by_band_and_freq_from_cfg80211 + (priv, BAND_A, chan->freq); + if (cfp) { + if (adapter->adhoc_11n_enabled) + adapter->adhoc_start_band = BAND_A + | BAND_AN; + else + adapter->adhoc_start_band = BAND_A; + } + } + } + if (!cfp || !cfp->channel) { + dev_err(adapter->dev, "invalid channel/freq\n"); + return -1; + } + priv->adhoc_channel = (u8) cfp->channel; + chan->channel = cfp->channel; + chan->freq = cfp->freq; + + return 0; +} + +/* + * IOCTL request handler to set/get BSS mode. + * + * This function prepares the correct firmware command and + * issues it to set or get the BSS mode. + * + * In case the mode is changed, a deauthentication is performed + * first by the function automatically. + */ +int mwifiex_bss_ioctl_mode(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + u16 action, int *mode) +{ + int ret = 0; + + if (!mode) + return -1; + + if (action == HostCmd_ACT_GEN_GET) { + *mode = priv->bss_mode; + return 0; + } + + if ((priv->bss_mode == *mode) || (*mode == MWIFIEX_BSS_MODE_AUTO)) { + dev_dbg(priv->adapter->dev, + "info: Already set to required mode! No change!\n"); + priv->bss_mode = *mode; + return 0; + } + + ret = mwifiex_deauthenticate(priv, wait, NULL); + + priv->sec_info.authentication_mode = MWIFIEX_AUTH_MODE_OPEN; + priv->bss_mode = *mode; + if (priv->bss_mode != MWIFIEX_BSS_MODE_AUTO) { + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_SET_BSS_MODE, + HostCmd_ACT_GEN_SET, 0, wait, NULL); + if (!ret) + ret = -EINPROGRESS; + } + + return ret; +} + +/* + * IOCTL request handler to set/get Ad-Hoc channel. + * + * This function prepares the correct firmware command and + * issues it to set or get the ad-hoc channel. + */ +static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + u16 action, u16 *channel) +{ + int ret = 0; + + if (action == HostCmd_ACT_GEN_GET) { + if (!priv->media_connected) { + *channel = priv->adhoc_channel; + return ret; + } + } else { + priv->adhoc_channel = (u8) *channel; + } + + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_RF_CHANNEL, + action, 0, wait, channel); + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * IOCTL request handler to find a particular BSS. + * + * The BSS can be searched with either a BSSID or a SSID. If none of + * these are provided, just the best BSS (best RSSI) is returned. + */ +int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + struct mwifiex_ssid_bssid *ssid_bssid) +{ + struct mwifiex_adapter *adapter = priv->adapter; + int ret = 0; + struct mwifiex_bssdescriptor *bss_desc; + u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; + u8 mac[ETH_ALEN]; + int i = 0; + + if (memcmp(ssid_bssid->bssid, zero_mac, sizeof(zero_mac))) { + i = mwifiex_find_bssid_in_list(priv, + (u8 *) ssid_bssid->bssid, + priv->bss_mode); + if (i < 0) { + memcpy(mac, ssid_bssid->bssid, sizeof(mac)); + dev_err(adapter->dev, "cannot find bssid %pM\n", mac); + return -1; + } + bss_desc = &adapter->scan_table[i]; + memcpy(&ssid_bssid->ssid, &bss_desc->ssid, + sizeof(struct mwifiex_802_11_ssid)); + } else if (ssid_bssid->ssid.ssid_len) { + i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, NULL, + priv->bss_mode); + if (i < 0) { + dev_err(adapter->dev, "cannot find ssid %s\n", + ssid_bssid->ssid.ssid); + return -1; + } + bss_desc = &adapter->scan_table[i]; + memcpy(ssid_bssid->bssid, bss_desc->mac_address, ETH_ALEN); + } else { + ret = mwifiex_find_best_network(priv, ssid_bssid); + } + + return ret; +} + +/* + * IOCTL request handler to change Ad-Hoc channel. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + * + * The function follows the following steps to perform the change - + * - Get current IBSS information + * - Get current channel + * - If no change is required, return + * - If not connected, change channel and return + * - If connected, + * - Disconnect + * - Change channel + * - Perform specific SSID scan with same SSID + * - Start/Join the IBSS + */ +int +mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) +{ + int ret = 0; + int status = 0; + struct mwifiex_bss_info bss_info; + struct mwifiex_wait_queue *wait = NULL; + u8 wait_option = MWIFIEX_IOCTL_WAIT; + struct mwifiex_ssid_bssid ssid_bssid; + u16 curr_chan = 0; + + memset(&bss_info, 0, sizeof(bss_info)); + + /* Get BSS information */ + if (mwifiex_get_bss_info(priv, &bss_info)) + return -1; + + /* Allocate wait buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + /* Get current channel */ + status = mwifiex_bss_ioctl_ibss_channel(priv, wait, HostCmd_ACT_GEN_GET, + &curr_chan); + + if (mwifiex_request_ioctl(priv, wait, status, wait_option)) { + ret = -1; + goto done; + } + if (curr_chan == channel) { + ret = 0; + goto done; + } + dev_dbg(priv->adapter->dev, "cmd: updating channel from %d to %d\n", + curr_chan, channel); + + if (!bss_info.media_connected) { + ret = 0; + goto done; + } + + /* Do disonnect */ + memset(&ssid_bssid, 0, ETH_ALEN); + status = mwifiex_bss_ioctl_stop(priv, wait, ssid_bssid.bssid); + + if (mwifiex_request_ioctl(priv, wait, status, wait_option)) { + ret = -1; + goto done; + } + + status = mwifiex_bss_ioctl_ibss_channel(priv, wait, HostCmd_ACT_GEN_SET, + (u16 *) &channel); + + if (mwifiex_request_ioctl(priv, wait, status, wait_option)) { + ret = -1; + goto done; + } + + /* Do specific SSID scanning */ + if (mwifiex_request_scan(priv, wait_option, &bss_info.ssid)) { + ret = -1; + goto done; + } + /* Start/Join Adhoc network */ + memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); + memcpy(&ssid_bssid.ssid, &bss_info.ssid, + sizeof(struct mwifiex_802_11_ssid)); + + status = mwifiex_bss_ioctl_start(priv, wait, &ssid_bssid); + + if (mwifiex_request_ioctl(priv, wait, status, wait_option)) + ret = -1; + +done: + kfree(wait); + return ret; +} + +/* + * IOCTL request handler to get current driver mode. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +mwifiex_drv_get_mode(struct mwifiex_private *priv, u8 wait_option) +{ + struct mwifiex_wait_queue *wait = NULL; + int status = 0; + int mode = -1; + + /* Allocate wait buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -1; + + status = mwifiex_bss_ioctl_mode(priv, wait, HostCmd_ACT_GEN_GET, &mode); + + status = mwifiex_request_ioctl(priv, wait, status, wait_option); + + if (wait && (status != -EINPROGRESS)) + kfree(wait); + return mode; +} + +/* + * IOCTL request handler to get rate. + * + * This function prepares the correct firmware command and + * issues it to get the current rate if it is connected, + * otherwise, the function returns the lowest supported rate + * for the band. + */ +static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + struct mwifiex_rate_cfg *rate_cfg) +{ + struct mwifiex_adapter *adapter = priv->adapter; + int ret = 0; + + rate_cfg->is_rate_auto = priv->is_data_rate_auto; + if (!priv->media_connected) { + switch (adapter->config_bands) { + case BAND_B: + /* Return the lowest supported rate for B band */ + rate_cfg->rate = supported_rates_b[0] & 0x7f; + break; + case BAND_G: + case BAND_G | BAND_GN: + /* Return the lowest supported rate for G band */ + rate_cfg->rate = supported_rates_g[0] & 0x7f; + break; + case BAND_B | BAND_G: + case BAND_A | BAND_B | BAND_G: + case BAND_A | BAND_B: + case BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN: + case BAND_B | BAND_G | BAND_GN: + /* Return the lowest supported rate for BG band */ + rate_cfg->rate = supported_rates_bg[0] & 0x7f; + break; + case BAND_A: + case BAND_A | BAND_G: + case BAND_A | BAND_G | BAND_AN | BAND_GN: + case BAND_A | BAND_AN: + /* Return the lowest supported rate for A band */ + rate_cfg->rate = supported_rates_a[0] & 0x7f; + break; + case BAND_GN: + /* Return the lowest supported rate for N band */ + rate_cfg->rate = supported_rates_n[0] & 0x7f; + break; + default: + dev_warn(adapter->dev, "invalid band %#x\n", + adapter->config_bands); + break; + } + } else { + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, + HostCmd_CMD_802_11_TX_RATE_QUERY, + HostCmd_ACT_GEN_GET, 0, wait, NULL); + if (!ret) + ret = -EINPROGRESS; + } + + return ret; +} + +/* + * IOCTL request handler to set rate. + * + * This function prepares the correct firmware command and + * issues it to set the current rate. + * + * The function also performs validation checking on the supplied value. + */ +static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + struct mwifiex_rate_cfg *rate_cfg) +{ + u8 rates[MWIFIEX_SUPPORTED_RATES]; + u8 *rate = NULL; + int rate_index = 0; + u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; + u32 i = 0; + int ret = 0; + struct mwifiex_adapter *adapter = priv->adapter; + + if (rate_cfg->is_rate_auto) { + memset(bitmap_rates, 0, sizeof(bitmap_rates)); + /* Support all HR/DSSS rates */ + bitmap_rates[0] = 0x000F; + /* Support all OFDM rates */ + bitmap_rates[1] = 0x00FF; + /* Support all HT-MCSs rate */ + for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates) - 3; i++) + bitmap_rates[i + 2] = 0xFFFF; + bitmap_rates[9] = 0x3FFF; + } else { + memset(rates, 0, sizeof(rates)); + mwifiex_get_active_data_rates(priv, rates); + rate = rates; + for (i = 0; (rate[i] && i < MWIFIEX_SUPPORTED_RATES); i++) { + dev_dbg(adapter->dev, "info: rate=%#x wanted=%#x\n", + rate[i], rate_cfg->rate); + if ((rate[i] & 0x7f) == (rate_cfg->rate & 0x7f)) + break; + } + if (!rate[i] || (i == MWIFIEX_SUPPORTED_RATES)) { + dev_err(adapter->dev, "fixed data rate %#x is out " + "of range\n", rate_cfg->rate); + return -1; + } + memset(bitmap_rates, 0, sizeof(bitmap_rates)); + + rate_index = + mwifiex_data_rate_to_index(adapter, rate_cfg->rate); + + /* Only allow b/g rates to be set */ + if (rate_index >= MWIFIEX_RATE_INDEX_HRDSSS0 && + rate_index <= MWIFIEX_RATE_INDEX_HRDSSS3) { + bitmap_rates[0] = 1 << rate_index; + } else { + rate_index -= 1; /* There is a 0x00 in the table */ + if (rate_index >= MWIFIEX_RATE_INDEX_OFDM0 && + rate_index <= MWIFIEX_RATE_INDEX_OFDM7) + bitmap_rates[1] = 1 << (rate_index - + MWIFIEX_RATE_INDEX_OFDM0); + } + } + + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TX_RATE_CFG, + HostCmd_ACT_GEN_SET, 0, wait, bitmap_rates); + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * IOCTL request handler to set/get rate. + * + * This function can be used to set/get either the rate value or the + * rate index. + */ +static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + struct mwifiex_rate_cfg *rate_cfg) +{ + int status = 0; + + if (!rate_cfg) + return -1; + + if (rate_cfg->action == HostCmd_ACT_GEN_GET) + status = mwifiex_rate_ioctl_get_rate_value( + priv, wait, rate_cfg); + else + status = mwifiex_rate_ioctl_set_rate_value( + priv, wait, rate_cfg); + + return status; +} + +/* + * Sends IOCTL request to get the data rate. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, + struct mwifiex_rate_cfg *rate) +{ + int ret = 0; + struct mwifiex_wait_queue *wait = NULL; + u8 wait_option = MWIFIEX_IOCTL_WAIT; + + /* Allocate wait buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + memset(rate, 0, sizeof(struct mwifiex_rate_cfg)); + rate->action = HostCmd_ACT_GEN_GET; + ret = mwifiex_rate_ioctl_cfg(priv, wait, rate); + + ret = mwifiex_request_ioctl(priv, wait, ret, wait_option); + if (!ret) { + if (rate && rate->is_rate_auto) + rate->rate = mwifiex_index_to_data_rate(priv->adapter, + priv->tx_rate, priv->tx_htinfo); + else if (rate) + rate->rate = priv->data_rate; + } else { + ret = -1; + } + + kfree(wait); + return ret; +} + +/* + * IOCTL request handler to set tx power configuration. + * + * This function prepares the correct firmware command and + * issues it. + * + * For non-auto power mode, all the following power groups are set - + * - Modulation class HR/DSSS + * - Modulation class OFDM + * - Modulation class HTBW20 + * - Modulation class HTBW40 + */ +static int mwifiex_power_ioctl_set_power(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + struct mwifiex_power_cfg *power_cfg) +{ + int ret = 0; + struct host_cmd_ds_txpwr_cfg *txp_cfg = NULL; + struct mwifiex_types_power_group *pg_tlv = NULL; + struct mwifiex_power_group *pg = NULL; + u8 *buf = NULL; + u16 dbm = 0; + + if (!power_cfg->is_power_auto) { + dbm = (u16) power_cfg->power_level; + if ((dbm < priv->min_tx_power_level) || + (dbm > priv->max_tx_power_level)) { + dev_err(priv->adapter->dev, "txpower value %d dBm" + " is out of range (%d dBm-%d dBm)\n", + dbm, priv->min_tx_power_level, + priv->max_tx_power_level); + return -1; + } + } + buf = kzalloc(MWIFIEX_SIZE_OF_CMD_BUFFER, GFP_KERNEL); + if (!buf) { + dev_err(priv->adapter->dev, "%s: failed to alloc cmd buffer\n", + __func__); + return -1; + } + + txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf; + txp_cfg->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + if (!power_cfg->is_power_auto) { + txp_cfg->mode = cpu_to_le32(1); + pg_tlv = (struct mwifiex_types_power_group *) (buf + + sizeof(struct host_cmd_ds_txpwr_cfg)); + pg_tlv->type = TLV_TYPE_POWER_GROUP; + pg_tlv->length = 4 * sizeof(struct mwifiex_power_group); + pg = (struct mwifiex_power_group *) (buf + + sizeof(struct host_cmd_ds_txpwr_cfg) + + sizeof(struct mwifiex_types_power_group)); + /* Power group for modulation class HR/DSSS */ + pg->first_rate_code = 0x00; + pg->last_rate_code = 0x03; + pg->modulation_class = MOD_CLASS_HR_DSSS; + pg->power_step = 0; + pg->power_min = (s8) dbm; + pg->power_max = (s8) dbm; + pg++; + /* Power group for modulation class OFDM */ + pg->first_rate_code = 0x00; + pg->last_rate_code = 0x07; + pg->modulation_class = MOD_CLASS_OFDM; + pg->power_step = 0; + pg->power_min = (s8) dbm; + pg->power_max = (s8) dbm; + pg++; + /* Power group for modulation class HTBW20 */ + pg->first_rate_code = 0x00; + pg->last_rate_code = 0x20; + pg->modulation_class = MOD_CLASS_HT; + pg->power_step = 0; + pg->power_min = (s8) dbm; + pg->power_max = (s8) dbm; + pg->ht_bandwidth = HT_BW_20; + pg++; + /* Power group for modulation class HTBW40 */ + pg->first_rate_code = 0x00; + pg->last_rate_code = 0x20; + pg->modulation_class = MOD_CLASS_HT; + pg->power_step = 0; + pg->power_min = (s8) dbm; + pg->power_max = (s8) dbm; + pg->ht_bandwidth = HT_BW_40; + } + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TXPWR_CFG, + HostCmd_ACT_GEN_SET, 0, wait, buf); + if (!ret) + ret = -EINPROGRESS; + kfree(buf); + + return ret; +} + +/* + * IOCTL request handler to get power save mode. + * + * This function prepares the correct firmware command and + * issues it. + */ +static int mwifiex_pm_ioctl_ps_mode(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + u32 *ps_mode, u16 action) +{ + int ret = 0; + struct mwifiex_adapter *adapter = priv->adapter; + u16 sub_cmd; + + if (action == HostCmd_ACT_GEN_SET) { + if (*ps_mode) + adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; + else + adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; + sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS; + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, + sub_cmd, BITMAP_STA_PS, wait, NULL); + if ((!ret) && (sub_cmd == DIS_AUTO_PS)) + ret = mwifiex_prepare_cmd(priv, + HostCmd_CMD_802_11_PS_MODE_ENH, GET_PS, + 0, NULL, NULL); + } else { + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, + GET_PS, 0, wait, NULL); + } + + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * IOCTL request handler to set/reset WPA IE. + * + * The supplied WPA IE is treated as a opaque buffer. Only the first field + * is checked to determine WPA version. If buffer length is zero, the existing + * WPA IE is reset. + */ +static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv, + u8 *ie_data_ptr, u16 ie_len) +{ + if (ie_len) { + if (ie_len > sizeof(priv->wpa_ie)) { + dev_err(priv->adapter->dev, + "failed to copy WPA IE, too big\n"); + return -1; + } + memcpy(priv->wpa_ie, ie_data_ptr, ie_len); + priv->wpa_ie_len = (u8) ie_len; + dev_dbg(priv->adapter->dev, "cmd: Set Wpa_ie_len=%d IE=%#x\n", + priv->wpa_ie_len, priv->wpa_ie[0]); + + if (priv->wpa_ie[0] == WLAN_EID_WPA) { + priv->sec_info.wpa_enabled = true; + } else if (priv->wpa_ie[0] == WLAN_EID_RSN) { + priv->sec_info.wpa2_enabled = true; + } else { + priv->sec_info.wpa_enabled = false; + priv->sec_info.wpa2_enabled = false; + } + } else { + memset(priv->wpa_ie, 0, sizeof(priv->wpa_ie)); + priv->wpa_ie_len = 0; + dev_dbg(priv->adapter->dev, "info: reset wpa_ie_len=%d IE=%#x\n", + priv->wpa_ie_len, priv->wpa_ie[0]); + priv->sec_info.wpa_enabled = false; + priv->sec_info.wpa2_enabled = false; + } + + return 0; +} + +/* + * IOCTL request handler to set/reset WAPI IE. + * + * The supplied WAPI IE is treated as a opaque buffer. Only the first field + * is checked to internally enable WAPI. If buffer length is zero, the existing + * WAPI IE is reset. + */ +static int mwifiex_set_wapi_ie(struct mwifiex_private *priv, + u8 *ie_data_ptr, u16 ie_len) +{ + if (ie_len) { + if (ie_len > sizeof(priv->wapi_ie)) { + dev_dbg(priv->adapter->dev, + "info: failed to copy WAPI IE, too big\n"); + return -1; + } + memcpy(priv->wapi_ie, ie_data_ptr, ie_len); + priv->wapi_ie_len = ie_len; + dev_dbg(priv->adapter->dev, "cmd: Set wapi_ie_len=%d IE=%#x\n", + priv->wapi_ie_len, priv->wapi_ie[0]); + + if (priv->wapi_ie[0] == WLAN_EID_BSS_AC_ACCESS_DELAY) + priv->sec_info.wapi_enabled = true; + } else { + memset(priv->wapi_ie, 0, sizeof(priv->wapi_ie)); + priv->wapi_ie_len = ie_len; + dev_dbg(priv->adapter->dev, + "info: Reset wapi_ie_len=%d IE=%#x\n", + priv->wapi_ie_len, priv->wapi_ie[0]); + priv->sec_info.wapi_enabled = false; + } + return 0; +} + +/* + * IOCTL request handler to set WAPI key. + * + * This function prepares the correct firmware command and + * issues it. + */ +static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_adapter *adapter, + struct mwifiex_wait_queue *wait, + struct mwifiex_ds_encrypt_key *encrypt_key) +{ + int ret = 0; + struct mwifiex_private *priv = adapter->priv[wait->bss_index]; + + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, + wait, encrypt_key); + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * IOCTL request handler to set/get authentication mode. + */ +static int mwifiex_set_auth_mode(struct mwifiex_private *priv, u32 auth_mode) +{ + int ret = 0; + + priv->sec_info.authentication_mode = auth_mode; + if (priv->sec_info.authentication_mode == MWIFIEX_AUTH_MODE_NETWORKEAP) + ret = mwifiex_set_wpa_ie_helper(priv, NULL, 0); + + return ret; +} + +/* + * IOCTL request handler to set WEP network key. + * + * This function prepares the correct firmware command and + * issues it, after validation checks. + */ +static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter, + struct mwifiex_wait_queue *wait, + struct mwifiex_ds_encrypt_key *encrypt_key) +{ + int ret = 0; + struct mwifiex_private *priv = adapter->priv[wait->bss_index]; + struct mwifiex_wep_key *wep_key = NULL; + int index; + + if (priv->wep_key_curr_index >= NUM_WEP_KEYS) + priv->wep_key_curr_index = 0; + wep_key = &priv->wep_key[priv->wep_key_curr_index]; + index = encrypt_key->key_index; + if (encrypt_key->key_disable) { + priv->sec_info.wep_status = MWIFIEX_802_11_WEP_DISABLED; + } else if (!encrypt_key->key_len) { + /* Copy the required key as the current key */ + wep_key = &priv->wep_key[index]; + if (!wep_key->key_length) { + dev_err(adapter->dev, + "key not set, so cannot enable it\n"); + return -1; + } + priv->wep_key_curr_index = (u16) index; + priv->sec_info.wep_status = MWIFIEX_802_11_WEP_ENABLED; + } else { + wep_key = &priv->wep_key[index]; + /* Cleanup */ + memset(wep_key, 0, sizeof(struct mwifiex_wep_key)); + /* Copy the key in the driver */ + memcpy(wep_key->key_material, + encrypt_key->key_material, + encrypt_key->key_len); + wep_key->key_index = index; + wep_key->key_length = encrypt_key->key_len; + priv->sec_info.wep_status = MWIFIEX_802_11_WEP_ENABLED; + } + if (wep_key->key_length) { + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, 0, NULL, NULL); + if (ret) + return ret; + } + if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED) + priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; + else + priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; + + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, + HostCmd_ACT_GEN_SET, 0, wait, + &priv->curr_pkt_filter); + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * IOCTL request handler to set WPA key. + * + * This function prepares the correct firmware command and + * issues it, after validation checks. + * + * Current driver only supports key length of up to 32 bytes. + * + * This function can also be used to disable a currently set key. + */ +static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter, + struct mwifiex_wait_queue *wait, + struct mwifiex_ds_encrypt_key *encrypt_key) +{ + int ret = 0; + struct mwifiex_private *priv = adapter->priv[wait->bss_index]; + u8 remove_key = false; + struct host_cmd_ds_802_11_key_material *ibss_key; + + /* Current driver only supports key length of up to 32 bytes */ + if (encrypt_key->key_len > MWIFIEX_MAX_KEY_LENGTH) { + dev_err(adapter->dev, "key length too long\n"); + return -1; + } + + if (priv->bss_mode == MWIFIEX_BSS_MODE_IBSS) { + /* + * IBSS/WPA-None uses only one key (Group) for both receiving + * and sending unicast and multicast packets. + */ + /* Send the key as PTK to firmware */ + encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, + NULL, encrypt_key); + if (ret) + return ret; + + ibss_key = &priv->aes_key; + memset(ibss_key, 0, + sizeof(struct host_cmd_ds_802_11_key_material)); + /* Copy the key in the driver */ + memcpy(ibss_key->key_param_set.key, encrypt_key->key_material, + encrypt_key->key_len); + memcpy(&ibss_key->key_param_set.key_len, &encrypt_key->key_len, + sizeof(ibss_key->key_param_set.key_len)); + ibss_key->key_param_set.key_type_id + = cpu_to_le16(KEY_TYPE_ID_TKIP); + ibss_key->key_param_set.key_info + = cpu_to_le16(KEY_INFO_TKIP_ENABLED); + + /* Send the key as GTK to firmware */ + encrypt_key->key_index = ~MWIFIEX_KEY_INDEX_UNICAST; + } + + if (!encrypt_key->key_index) + encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; + + if (remove_key) + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, + !(KEY_INFO_ENABLED), + wait, encrypt_key); + else + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, + wait, encrypt_key); + + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * IOCTL request handler to set/get network keys. + * + * This is a generic key handling function which supports WEP, WPA + * and WAPI. + */ +static int +mwifiex_sec_ioctl_encrypt_key(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + struct mwifiex_ds_encrypt_key *encrypt_key) +{ + int status = 0; + struct mwifiex_adapter *adapter = priv->adapter; + + if (encrypt_key->is_wapi_key) + status = mwifiex_sec_ioctl_set_wapi_key(adapter, wait, + encrypt_key); + else if (encrypt_key->key_len > WLAN_KEY_LEN_WEP104) + status = mwifiex_sec_ioctl_set_wpa_key(adapter, wait, + encrypt_key); + else + status = mwifiex_sec_ioctl_set_wep_key(adapter, wait, + encrypt_key); + return status; +} + +/* + * This function returns the driver version. + */ +int +mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, + int max_len) +{ + union { + u32 l; + u8 c[4]; + } ver; + char fw_ver[32]; + + ver.l = adapter->fw_release_number; + sprintf(fw_ver, "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0], ver.c[3]); + + snprintf(version, max_len, driver_version, fw_ver); + + dev_dbg(adapter->dev, "info: MWIFIEX VERSION: %s\n", version); + + return 0; +} + +/* + * Sends IOCTL request to set Tx power. It can be set to either auto + * or a fixed value. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +mwifiex_set_tx_power(struct mwifiex_private *priv, int type, int dbm) +{ + struct mwifiex_power_cfg power_cfg; + struct mwifiex_wait_queue *wait = NULL; + int status = 0; + int ret = 0; + + wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); + if (!wait) + return -ENOMEM; + + if (type == NL80211_TX_POWER_FIXED) { + power_cfg.is_power_auto = 0; + power_cfg.power_level = dbm; + } else { + power_cfg.is_power_auto = 1; + } + status = mwifiex_power_ioctl_set_power(priv, wait, &power_cfg); + + ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); + + kfree(wait); + return ret; +} + +/* + * Sends IOCTL request to get scan table. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int mwifiex_get_scan_table(struct mwifiex_private *priv, u8 wait_option, + struct mwifiex_scan_resp *scan_resp) +{ + struct mwifiex_wait_queue *wait = NULL; + struct mwifiex_scan_resp scan; + int status = 0; + + /* Allocate wait buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_GET, + NULL, &scan); + + status = mwifiex_request_ioctl(priv, wait, status, wait_option); + if (!status) { + if (scan_resp) + memcpy(scan_resp, &scan, + sizeof(struct mwifiex_scan_resp)); + } + + if (wait && (status != -EINPROGRESS)) + kfree(wait); + return status; +} + +/* + * Sends IOCTL request to get signal information. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int mwifiex_get_signal_info(struct mwifiex_private *priv, u8 wait_option, + struct mwifiex_ds_get_signal *signal) +{ + struct mwifiex_ds_get_signal info; + struct mwifiex_wait_queue *wait = NULL; + int status = 0; + + /* Allocate wait buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + info.selector = ALL_RSSI_INFO_MASK; + + status = mwifiex_get_info_signal(priv, wait, &info); + + status = mwifiex_request_ioctl(priv, wait, status, wait_option); + if (!status) { + if (signal) + memcpy(signal, &info, + sizeof(struct mwifiex_ds_get_signal)); + if (info.selector & BCN_RSSI_AVG_MASK) + priv->w_stats.qual.level = info.bcn_rssi_avg; + if (info.selector & BCN_NF_AVG_MASK) + priv->w_stats.qual.noise = info.bcn_nf_avg; + } + + if (wait && (status != -EINPROGRESS)) + kfree(wait); + return status; +} + +/* + * Sends IOCTL request to set encryption mode. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +static int mwifiex_set_encrypt_mode(struct mwifiex_private *priv, + u8 wait_option, u32 encrypt_mode) +{ + priv->sec_info.encryption_mode = encrypt_mode; + return 0; +} + +/* + * This function set the authentication parameters. It sets both encryption + * mode and authentication mode, and also enables WPA if required. + */ +int +mwifiex_set_auth(struct mwifiex_private *priv, int encrypt_mode, + int auth_mode, int wpa_enabled) +{ + if (mwifiex_set_encrypt_mode(priv, MWIFIEX_IOCTL_WAIT, encrypt_mode)) + return -EFAULT; + + if (mwifiex_set_auth_mode(priv, auth_mode)) + return -EFAULT; + + return 0; +} + +/* + * Sends IOCTL request to set encoding parameters. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, + int key_len, u8 key_index, int disable) +{ + struct mwifiex_wait_queue *wait = NULL; + struct mwifiex_ds_encrypt_key encrypt_key; + int status = 0; + int ret = 0; + + wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); + if (!wait) + return -ENOMEM; + + memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key)); + encrypt_key.key_len = key_len; + if (!disable) { + encrypt_key.key_index = key_index; + if (key_len) + memcpy(encrypt_key.key_material, key, key_len); + } else { + encrypt_key.key_disable = true; + } + + status = mwifiex_sec_ioctl_encrypt_key(priv, wait, &encrypt_key); + + if (mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT)) + ret = -EFAULT; + + kfree(wait); + return ret; +} + +/* + * Sends IOCTL request to set power management parameters. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +mwifiex_drv_set_power(struct mwifiex_private *priv, bool power_on) +{ + int ret = 0; + int status = 0; + struct mwifiex_wait_queue *wait = NULL; + u32 ps_mode; + + wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); + if (!wait) + return -ENOMEM; + + ps_mode = power_on; + status = mwifiex_pm_ioctl_ps_mode(priv, wait, &ps_mode, + HostCmd_ACT_GEN_SET); + + ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); + + kfree(wait); + return ret; +} + +/* + * Sends IOCTL request to get extended version. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +mwifiex_get_ver_ext(struct mwifiex_private *priv) +{ + struct mwifiex_ver_ext ver_ext; + struct mwifiex_wait_queue *wait = NULL; + int status = 0; + int ret = 0; + u8 wait_option = MWIFIEX_IOCTL_WAIT; + + /* Allocate wait buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + /* get fw version */ + memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext)); + status = mwifiex_get_info_ver_ext(priv, wait, &ver_ext); + + ret = mwifiex_request_ioctl(priv, wait, status, wait_option); + + if (ret) + ret = -1; + + kfree(wait); + return ret; +} + +/* + * Sends IOCTL request to get statistics information. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +mwifiex_get_stats_info(struct mwifiex_private *priv, + struct mwifiex_ds_get_stats *log) +{ + int ret = 0; + int status = 0; + struct mwifiex_wait_queue *wait = NULL; + struct mwifiex_ds_get_stats get_log; + u8 wait_option = MWIFIEX_IOCTL_WAIT; + + /* Allocate wait buffer */ + wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); + if (!wait) + return -ENOMEM; + + memset(&get_log, 0, sizeof(struct mwifiex_ds_get_stats)); + status = mwifiex_get_info_stats(priv, wait, &get_log); + + /* Send IOCTL request to MWIFIEX */ + ret = mwifiex_request_ioctl(priv, wait, status, wait_option); + if (!ret) { + if (log) + memcpy(log, &get_log, sizeof(struct + mwifiex_ds_get_stats)); + priv->w_stats.discard.fragment = get_log.fcs_error; + priv->w_stats.discard.retries = get_log.retry; + priv->w_stats.discard.misc = get_log.ack_failure; + } + + kfree(wait); + return ret; +} + +/* + * IOCTL request handler to read/write register. + * + * This function prepares the correct firmware command and + * issues it. + * + * Access to the following registers are supported - + * - MAC + * - BBP + * - RF + * - PMIC + * - CAU + */ +static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + struct mwifiex_ds_reg_rw *reg_rw, + u16 action) +{ + int ret = 0; + u16 cmd_no; + + switch (le32_to_cpu(reg_rw->type)) { + case MWIFIEX_REG_MAC: + cmd_no = HostCmd_CMD_MAC_REG_ACCESS; + break; + case MWIFIEX_REG_BBP: + cmd_no = HostCmd_CMD_BBP_REG_ACCESS; + break; + case MWIFIEX_REG_RF: + cmd_no = HostCmd_CMD_RF_REG_ACCESS; + break; + case MWIFIEX_REG_PMIC: + cmd_no = HostCmd_CMD_PMIC_REG_ACCESS; + break; + case MWIFIEX_REG_CAU: + cmd_no = HostCmd_CMD_CAU_REG_ACCESS; + break; + default: + return -1; + } + + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, cmd_no, action, 0, wait, reg_rw); + + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * Sends IOCTL request to write to a register. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type, + u32 reg_offset, u32 reg_value) +{ + int ret = 0; + int status = 0; + struct mwifiex_wait_queue *wait = NULL; + struct mwifiex_ds_reg_rw reg_rw; + + wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); + if (!wait) + return -ENOMEM; + + reg_rw.type = cpu_to_le32(reg_type); + reg_rw.offset = cpu_to_le32(reg_offset); + reg_rw.value = cpu_to_le32(reg_value); + status = mwifiex_reg_mem_ioctl_reg_rw(priv, wait, ®_rw, + HostCmd_ACT_GEN_SET); + + ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); + + kfree(wait); + return ret; +} + +/* + * Sends IOCTL request to read from a register. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type, + u32 reg_offset, u32 *value) +{ + int ret = 0; + int status = 0; + struct mwifiex_wait_queue *wait = NULL; + struct mwifiex_ds_reg_rw reg_rw; + + wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); + if (!wait) + return -ENOMEM; + + reg_rw.type = cpu_to_le32(reg_type); + reg_rw.offset = cpu_to_le32(reg_offset); + status = mwifiex_reg_mem_ioctl_reg_rw(priv, wait, ®_rw, + HostCmd_ACT_GEN_GET); + + ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); + if (ret) + goto done; + + *value = le32_to_cpu(reg_rw.value); + +done: + kfree(wait); + return ret; +} + +/* + * IOCTL request handler to read EEPROM. + * + * This function prepares the correct firmware command and + * issues it. + */ +static int +mwifiex_reg_mem_ioctl_read_eeprom(struct mwifiex_private *priv, + struct mwifiex_wait_queue *wait, + struct mwifiex_ds_read_eeprom *rd_eeprom) +{ + int ret = 0; + + /* Send request to firmware */ + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_EEPROM_ACCESS, + HostCmd_ACT_GEN_GET, 0, wait, rd_eeprom); + + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * Sends IOCTL request to read from EEPROM. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, + u8 *value) +{ + int ret = 0; + int status = 0; + struct mwifiex_wait_queue *wait = NULL; + struct mwifiex_ds_read_eeprom rd_eeprom; + + wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); + if (!wait) + return -ENOMEM; + + rd_eeprom.offset = cpu_to_le16((u16) offset); + rd_eeprom.byte_count = cpu_to_le16((u16) bytes); + status = mwifiex_reg_mem_ioctl_read_eeprom(priv, wait, &rd_eeprom); + + ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); + if (ret) + goto done; + + memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA); +done: + kfree(wait); + return ret; +} + +/* + * This function sets a generic IE. In addition to generic IE, it can + * also handle WPA, WPA2 and WAPI IEs. + */ +static int +mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr, + u16 ie_len) +{ + int ret = 0; + struct ieee_types_vendor_header *pvendor_ie; + const u8 wpa_oui[] = { 0x00, 0x50, 0xf2, 0x01 }; + const u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 }; + + /* If the passed length is zero, reset the buffer */ + if (!ie_len) { + priv->gen_ie_buf_len = 0; + priv->wps.session_enable = false; + + return 0; + } else if (!ie_data_ptr) { + return -1; + } + pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr; + /* Test to see if it is a WPA IE, if not, then it is a gen IE */ + if (((pvendor_ie->element_id == WLAN_EID_WPA) + && (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) + || (pvendor_ie->element_id == WLAN_EID_RSN)) { + + /* IE is a WPA/WPA2 IE so call set_wpa function */ + ret = mwifiex_set_wpa_ie_helper(priv, ie_data_ptr, ie_len); + priv->wps.session_enable = false; + + return ret; + } else if (pvendor_ie->element_id == WLAN_EID_BSS_AC_ACCESS_DELAY) { + /* IE is a WAPI IE so call set_wapi function */ + ret = mwifiex_set_wapi_ie(priv, ie_data_ptr, ie_len); + + return ret; + } + /* + * Verify that the passed length is not larger than the + * available space remaining in the buffer + */ + if (ie_len < (sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) { + + /* Test to see if it is a WPS IE, if so, enable + * wps session flag + */ + pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr; + if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) + && (!memcmp(pvendor_ie->oui, wps_oui, + sizeof(wps_oui)))) { + priv->wps.session_enable = true; + dev_dbg(priv->adapter->dev, + "info: WPS Session Enabled.\n"); + } + + /* Append the passed data to the end of the + genIeBuffer */ + memcpy(priv->gen_ie_buf + priv->gen_ie_buf_len, ie_data_ptr, + ie_len); + /* Increment the stored buffer length by the + size passed */ + priv->gen_ie_buf_len += ie_len; + } else { + /* Passed data does not fit in the remaining + buffer space */ + ret = -1; + } + + /* Return 0, or -1 for error case */ + return ret; +} + +/* + * IOCTL request handler to set/get generic IE. + * + * In addition to various generic IEs, this function can also be + * used to set the ARP filter. + */ +static int mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv, + struct mwifiex_ds_misc_gen_ie *gen_ie, + u16 action) +{ + struct mwifiex_adapter *adapter = priv->adapter; + + switch (gen_ie->type) { + case MWIFIEX_IE_TYPE_GEN_IE: + if (action == HostCmd_ACT_GEN_GET) { + gen_ie->len = priv->wpa_ie_len; + memcpy(gen_ie->ie_data, priv->wpa_ie, gen_ie->len); + } else { + mwifiex_set_gen_ie_helper(priv, gen_ie->ie_data, + (u16) gen_ie->len); + } + break; + case MWIFIEX_IE_TYPE_ARP_FILTER: + memset(adapter->arp_filter, 0, sizeof(adapter->arp_filter)); + if (gen_ie->len > ARP_FILTER_MAX_BUF_SIZE) { + adapter->arp_filter_size = 0; + dev_err(adapter->dev, "invalid ARP filter size\n"); + return -1; + } else { + memcpy(adapter->arp_filter, gen_ie->ie_data, + gen_ie->len); + adapter->arp_filter_size = gen_ie->len; + } + break; + default: + dev_err(adapter->dev, "invalid IE type\n"); + return -1; + } + return 0; +} + +/* + * Sends IOCTL request to set a generic IE. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int +mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len) +{ + struct mwifiex_ds_misc_gen_ie gen_ie; + int status = 0; + + if (ie_len > IW_CUSTOM_MAX) + return -EFAULT; + + gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE; + gen_ie.len = ie_len; + memcpy(gen_ie.ie_data, ie, ie_len); + status = mwifiex_misc_ioctl_gen_ie(priv, &gen_ie, HostCmd_ACT_GEN_SET); + if (status) + return -EFAULT; + + return 0; +} diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c new file mode 100644 index 000000000000..8282679e64fd --- /dev/null +++ b/drivers/net/wireless/mwifiex/sta_rx.c @@ -0,0 +1,182 @@ +/* + * Marvell Wireless LAN device driver: station RX data handling + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "11n_aggr.h" +#include "11n_rxreorder.h" + +/* + * This function processes the received packet and forwards it + * to kernel/upper layer. + * + * This function parses through the received packet and determines + * if it is a debug packet or normal packet. + * + * For non-debug packets, the function chops off unnecessary leading + * header bytes, reconstructs the packet as an ethernet frame or + * 802.2/llc/snap frame as required, and sends it to kernel/upper layer. + * + * The completion callback is called after processing in complete. + */ +int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, + struct sk_buff *skb) +{ + int ret = 0; + struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); + struct mwifiex_private *priv = adapter->priv[rx_info->bss_index]; + struct rx_packet_hdr *rx_pkt_hdr; + struct rxpd *local_rx_pd; + int hdr_chop; + struct ethhdr *eth_hdr; + u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; + + local_rx_pd = (struct rxpd *) (skb->data); + + rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd + + local_rx_pd->rx_pkt_offset); + + if (!memcmp(&rx_pkt_hdr->rfc1042_hdr, + rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) { + /* + * Replace the 803 header and rfc1042 header (llc/snap) with an + * EthernetII header, keep the src/dst and snap_type + * (ethertype). + * The firmware only passes up SNAP frames converting + * all RX Data from 802.11 to 802.2/LLC/SNAP frames. + * To create the Ethernet II, just move the src, dst address + * right before the snap_type. + */ + eth_hdr = (struct ethhdr *) + ((u8 *) &rx_pkt_hdr->eth803_hdr + + sizeof(rx_pkt_hdr->eth803_hdr) + + sizeof(rx_pkt_hdr->rfc1042_hdr) + - sizeof(rx_pkt_hdr->eth803_hdr.h_dest) + - sizeof(rx_pkt_hdr->eth803_hdr.h_source) + - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type)); + + memcpy(eth_hdr->h_source, rx_pkt_hdr->eth803_hdr.h_source, + sizeof(eth_hdr->h_source)); + memcpy(eth_hdr->h_dest, rx_pkt_hdr->eth803_hdr.h_dest, + sizeof(eth_hdr->h_dest)); + + /* Chop off the rxpd + the excess memory from the 802.2/llc/snap + header that was removed. */ + hdr_chop = (u8 *) eth_hdr - (u8 *) local_rx_pd; + } else { + /* Chop off the rxpd */ + hdr_chop = (u8 *) &rx_pkt_hdr->eth803_hdr - + (u8 *) local_rx_pd; + } + + /* Chop off the leading header bytes so the it points to the start of + either the reconstructed EthII frame or the 802.2/llc/snap frame */ + skb_pull(skb, hdr_chop); + + priv->rxpd_rate = local_rx_pd->rx_rate; + + priv->rxpd_htinfo = local_rx_pd->ht_info; + + ret = mwifiex_recv_packet(adapter, skb); + if (ret == -1) + dev_err(adapter->dev, "recv packet failed\n"); + + return ret; +} + +/* + * This function processes the received buffer. + * + * The function looks into the RxPD and performs sanity tests on the + * received buffer to ensure its a valid packet, before processing it + * further. If the packet is determined to be aggregated, it is + * de-aggregated accordingly. Non-unicast packets are sent directly to + * the kernel/upper layers. Unicast packets are handed over to the + * Rx reordering routine if 11n is enabled. + * + * The completion callback is called after processing in complete. + */ +int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, + struct sk_buff *skb) +{ + int ret = 0; + struct rxpd *local_rx_pd; + struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); + struct rx_packet_hdr *rx_pkt_hdr; + u8 ta[ETH_ALEN]; + u16 rx_pkt_type = 0; + struct mwifiex_private *priv = adapter->priv[rx_info->bss_index]; + + local_rx_pd = (struct rxpd *) (skb->data); + rx_pkt_type = local_rx_pd->rx_pkt_type; + + rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd + + local_rx_pd->rx_pkt_offset); + + if ((local_rx_pd->rx_pkt_offset + local_rx_pd->rx_pkt_length) > + (u16) skb->len) { + dev_err(adapter->dev, "wrong rx packet: len=%d," + " rx_pkt_offset=%d, rx_pkt_length=%d\n", skb->len, + local_rx_pd->rx_pkt_offset, local_rx_pd->rx_pkt_length); + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + return ret; + } + if (local_rx_pd->rx_pkt_type == PKT_TYPE_AMSDU) { + mwifiex_11n_deaggregate_pkt(priv, skb); + return ret; + } + /* + * If the packet is not an unicast packet then send the packet + * directly to os. Don't pass thru rx reordering + */ + if (!IS_11N_ENABLED(priv) || + memcmp(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN)) { + mwifiex_process_rx_packet(adapter, skb); + return ret; + } + + if (mwifiex_queuing_ra_based(priv)) { + memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); + } else { + if (rx_pkt_type != PKT_TYPE_BAR) + priv->rx_seq[local_rx_pd->priority] = + local_rx_pd->seq_num; + memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address, + ETH_ALEN); + } + + /* Reorder and send to OS */ + ret = mwifiex_11n_rx_reorder_pkt(priv, local_rx_pd->seq_num, + local_rx_pd->priority, ta, + (u8) local_rx_pd->rx_pkt_type, + (void *) skb); + + if (ret || (rx_pkt_type == PKT_TYPE_BAR)) { + if (priv && (ret == -1)) + priv->stats.rx_dropped++; + + dev_kfree_skb_any(skb); + } + + return ret; +} diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c new file mode 100644 index 000000000000..e8db6bd021c6 --- /dev/null +++ b/drivers/net/wireless/mwifiex/sta_tx.c @@ -0,0 +1,202 @@ +/* + * Marvell Wireless LAN device driver: station TX data handling + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" + +/* + * This function fills the TxPD for tx packets. + * + * The Tx buffer received by this function should already have the + * header space allocated for TxPD. + * + * This function inserts the TxPD in between interface header and actual + * data and adjusts the buffer pointers accordingly. + * + * The following TxPD fields are set by this function, as required - + * - BSS number + * - Tx packet length and offset + * - Priority + * - Packet delay + * - Priority specific Tx control + * - Flags + */ +void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, + struct sk_buff *skb) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct txpd *local_tx_pd; + struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); + + if (!skb->len) { + dev_err(adapter->dev, "Tx: bad packet length: %d\n", + skb->len); + tx_info->status_code = MWIFIEX_ERROR_PKT_SIZE_INVALID; + return skb->data; + } + + BUG_ON(skb_headroom(skb) < (sizeof(*local_tx_pd) + INTF_HEADER_LEN)); + skb_push(skb, sizeof(*local_tx_pd)); + + local_tx_pd = (struct txpd *) skb->data; + memset(local_tx_pd, 0, sizeof(struct txpd)); + local_tx_pd->bss_num = priv->bss_num; + local_tx_pd->bss_type = priv->bss_type; + local_tx_pd->tx_pkt_length = cpu_to_le16((u16) (skb->len - + sizeof(struct txpd))); + + local_tx_pd->priority = (u8) skb->priority; + local_tx_pd->pkt_delay_2ms = + mwifiex_wmm_compute_drv_pkt_delay(priv, skb); + + if (local_tx_pd->priority < + ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl)) + /* + * Set the priority specific tx_control field, setting of 0 will + * cause the default value to be used later in this function + */ + local_tx_pd->tx_control = + cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[local_tx_pd-> + priority]); + + if (adapter->pps_uapsd_mode) { + if (mwifiex_check_last_packet_indication(priv)) { + adapter->tx_lock_flag = true; + local_tx_pd->flags = + MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET; + } + } + + /* Offset of actual data */ + local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); + + /* make space for INTF_HEADER_LEN */ + skb_push(skb, INTF_HEADER_LEN); + + if (!local_tx_pd->tx_control) + /* TxCtrl set by user or default */ + local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); + + return skb->data; +} + +/* + * This function tells firmware to send a NULL data packet. + * + * The function creates a NULL data packet with TxPD and sends to the + * firmware for transmission, with highest priority setting. + */ +int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct txpd *local_tx_pd; +/* sizeof(struct txpd) + Interface specific header */ +#define NULL_PACKET_HDR 64 + u32 data_len = NULL_PACKET_HDR; + struct sk_buff *skb = NULL; + int ret = 0; + struct mwifiex_txinfo *tx_info = NULL; + + if (adapter->surprise_removed) + return -1; + + if (!priv->media_connected) + return -1; + + if (adapter->data_sent) + return -1; + + skb = dev_alloc_skb(data_len); + if (!skb) + return -1; + + tx_info = MWIFIEX_SKB_TXCB(skb); + tx_info->bss_index = priv->bss_index; + skb_reserve(skb, sizeof(struct txpd) + INTF_HEADER_LEN); + skb_push(skb, sizeof(struct txpd)); + + local_tx_pd = (struct txpd *) skb->data; + local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); + local_tx_pd->flags = flags; + local_tx_pd->priority = WMM_HIGHEST_PRIORITY; + local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); + local_tx_pd->bss_num = priv->bss_num; + local_tx_pd->bss_type = priv->bss_type; + + skb_push(skb, INTF_HEADER_LEN); + + ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, + skb->data, skb->len, NULL); + switch (ret) { + case -EBUSY: + adapter->data_sent = true; + /* Fall through FAILURE handling */ + case -1: + dev_kfree_skb_any(skb); + dev_err(adapter->dev, "%s: host_to_card failed: ret=%d\n", + __func__, ret); + adapter->dbg.num_tx_host_to_card_failure++; + break; + case 0: + dev_kfree_skb_any(skb); + dev_dbg(adapter->dev, "data: %s: host_to_card succeeded\n", + __func__); + adapter->tx_lock_flag = true; + break; + case -EINPROGRESS: + break; + default: + break; + } + + return ret; +} + +/* + * This function checks if we need to send last packet indication. + */ +u8 +mwifiex_check_last_packet_indication(struct mwifiex_private *priv) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u8 ret = false; + u8 prop_ps = true; + + if (!adapter->sleep_period.period) + return ret; + if (mwifiex_wmm_lists_empty(adapter)) { + if ((priv->curr_bss_params.wmm_uapsd_enabled && + priv->wmm_qosinfo) || prop_ps) + ret = true; + } + + if (ret && !adapter->cmd_sent && !adapter->curr_cmd + && !is_command_pending(adapter)) { + adapter->delay_null_pkt = false; + ret = true; + } else { + ret = false; + adapter->delay_null_pkt = true; + } + return ret; +} diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c new file mode 100644 index 000000000000..f06923cb1c4b --- /dev/null +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -0,0 +1,202 @@ +/* + * Marvell Wireless LAN device driver: generic TX/RX data handling + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" + +/* + * This function processes the received buffer. + * + * Main responsibility of this function is to parse the RxPD to + * identify the correct interface this packet is headed for and + * forwarding it to the associated handling function, where the + * packet will be further processed and sent to kernel/upper layer + * if required. + */ +int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, + struct sk_buff *skb) +{ + int ret = 0; + struct mwifiex_private *priv = + mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + struct rxpd *local_rx_pd; + struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); + + local_rx_pd = (struct rxpd *) (skb->data); + /* Get the BSS number from rxpd, get corresponding priv */ + priv = mwifiex_get_priv_by_id(adapter, local_rx_pd->bss_num & + BSS_NUM_MASK, local_rx_pd->bss_type); + if (!priv) + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + + rx_info->bss_index = priv->bss_index; + ret = mwifiex_process_sta_rx_packet(adapter, skb); + + return ret; +} +EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); + +/* + * This function sends a packet to device. + * + * It processes the packet to add the TxPD, checks condition and + * sends the processed packet to firmware for transmission. + * + * On successful completion, the function calls the completion callback + * and logs the time. + */ +int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, + struct mwifiex_tx_param *tx_param) +{ + int ret = -1; + struct mwifiex_adapter *adapter = priv->adapter; + u8 *head_ptr = NULL; + struct txpd *local_tx_pd = NULL; + + head_ptr = (u8 *) mwifiex_process_sta_txpd(priv, skb); + if (head_ptr) { + if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) + local_tx_pd = + (struct txpd *) (head_ptr + INTF_HEADER_LEN); + + ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, + skb->data, skb->len, tx_param); + } + + switch (ret) { + case -EBUSY: + if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && + (adapter->pps_uapsd_mode) && + (adapter->tx_lock_flag)) { + priv->adapter->tx_lock_flag = false; + local_tx_pd->flags = 0; + } + dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); + break; + case -1: + adapter->data_sent = false; + dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n", + ret); + adapter->dbg.num_tx_host_to_card_failure++; + mwifiex_write_data_complete(adapter, skb, ret); + break; + case -EINPROGRESS: + adapter->data_sent = false; + break; + case 0: + mwifiex_write_data_complete(adapter, skb, ret); + break; + default: + break; + } + + return ret; +} + +/* + * Packet send completion callback handler. + * + * It either frees the buffer directly or forwards it to another + * completion callback which checks conditions, updates statistics, + * wakes up stalled traffic queue if required, and then frees the buffer. + */ +int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, + struct sk_buff *skb, int status) +{ + struct mwifiex_private *priv = NULL, *tpriv = NULL; + struct mwifiex_txinfo *tx_info = NULL; + int i; + + if (!skb) + return 0; + + tx_info = MWIFIEX_SKB_TXCB(skb); + priv = mwifiex_bss_index_to_priv(adapter, tx_info->bss_index); + if (!priv) + goto done; + + priv->netdev->trans_start = jiffies; + if (!status) { + priv->stats.tx_packets++; + priv->stats.tx_bytes += skb->len; + } else { + priv->stats.tx_errors++; + } + atomic_dec(&adapter->tx_pending); + + for (i = 0; i < adapter->priv_num; i++) { + + tpriv = adapter->priv[i]; + + if ((GET_BSS_ROLE(tpriv) == MWIFIEX_BSS_ROLE_STA) + && (tpriv->media_connected)) { + if (netif_queue_stopped(tpriv->netdev)) + netif_wake_queue(tpriv->netdev); + } + } +done: + dev_kfree_skb_any(skb); + + return 0; +} + +/* + * Packet receive completion callback handler. + * + * This function calls another completion callback handler which + * updates the statistics, and optionally updates the parent buffer + * use count before freeing the received packet. + */ +int mwifiex_recv_packet_complete(struct mwifiex_adapter *adapter, + struct sk_buff *skb, int status) +{ + struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); + struct mwifiex_rxinfo *rx_info_parent = NULL; + struct mwifiex_private *priv; + struct sk_buff *skb_parent = NULL; + unsigned long flags; + + priv = adapter->priv[rx_info->bss_index]; + + if (priv && (status == -1)) + priv->stats.rx_dropped++; + + if (rx_info->parent) { + skb_parent = rx_info->parent; + rx_info_parent = MWIFIEX_SKB_RXCB(skb_parent); + + spin_lock_irqsave(&priv->rx_pkt_lock, flags); + --rx_info_parent->use_count; + + if (!rx_info_parent->use_count) { + spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); + dev_kfree_skb_any(skb_parent); + } else { + spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); + } + } else { + dev_kfree_skb_any(skb); + } + + return 0; +} diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c new file mode 100644 index 000000000000..205022aa52f5 --- /dev/null +++ b/drivers/net/wireless/mwifiex/util.c @@ -0,0 +1,252 @@ +/* + * Marvell Wireless LAN device driver: utility functions + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" + +/* + * Firmware initialization complete callback handler. + * + * This function wakes up the function waiting on the init + * wait queue for the firmware initialization to complete. + */ +int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter) +{ + + adapter->init_wait_q_woken = true; + wake_up_interruptible(&adapter->init_wait_q); + return 0; +} + +/* + * Firmware shutdown complete callback handler. + * + * This function sets the hardware status to not ready and wakes up + * the function waiting on the init wait queue for the firmware + * shutdown to complete. + */ +int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter) +{ + adapter->hw_status = MWIFIEX_HW_STATUS_NOT_READY; + adapter->init_wait_q_woken = true; + wake_up_interruptible(&adapter->init_wait_q); + return 0; +} + +/* + * IOCTL request handler to send function init/shutdown command + * to firmware. + * + * This function prepares the correct firmware command and + * issues it. + */ +int mwifiex_misc_ioctl_init_shutdown(struct mwifiex_adapter *adapter, + struct mwifiex_wait_queue *wait, + u32 func_init_shutdown) +{ + struct mwifiex_private *priv = adapter->priv[wait->bss_index]; + int ret; + u16 cmd; + + if (func_init_shutdown == MWIFIEX_FUNC_INIT) { + cmd = HostCmd_CMD_FUNC_INIT; + } else if (func_init_shutdown == MWIFIEX_FUNC_SHUTDOWN) { + cmd = HostCmd_CMD_FUNC_SHUTDOWN; + } else { + dev_err(adapter->dev, "unsupported parameter\n"); + return -1; + } + + /* Send command to firmware */ + ret = mwifiex_prepare_cmd(priv, cmd, HostCmd_ACT_GEN_SET, + 0, wait, NULL); + + if (!ret) + ret = -EINPROGRESS; + + return ret; +} + +/* + * IOCTL request handler to set/get debug information. + * + * This function collates/sets the information from/to different driver + * structures. + */ +int mwifiex_get_debug_info(struct mwifiex_private *priv, + struct mwifiex_debug_info *info) +{ + struct mwifiex_adapter *adapter = priv->adapter; + + if (info) { + memcpy(info->packets_out, + priv->wmm.packets_out, + sizeof(priv->wmm.packets_out)); + info->max_tx_buf_size = (u32) adapter->max_tx_buf_size; + info->tx_buf_size = (u32) adapter->tx_buf_size; + info->rx_tbl_num = mwifiex_get_rx_reorder_tbl( + priv, info->rx_tbl); + info->tx_tbl_num = mwifiex_get_tx_ba_stream_tbl( + priv, info->tx_tbl); + info->ps_mode = adapter->ps_mode; + info->ps_state = adapter->ps_state; + info->is_deep_sleep = adapter->is_deep_sleep; + info->pm_wakeup_card_req = adapter->pm_wakeup_card_req; + info->pm_wakeup_fw_try = adapter->pm_wakeup_fw_try; + info->is_hs_configured = adapter->is_hs_configured; + info->hs_activated = adapter->hs_activated; + info->num_cmd_host_to_card_failure + = adapter->dbg.num_cmd_host_to_card_failure; + info->num_cmd_sleep_cfm_host_to_card_failure + = adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure; + info->num_tx_host_to_card_failure + = adapter->dbg.num_tx_host_to_card_failure; + info->num_event_deauth = adapter->dbg.num_event_deauth; + info->num_event_disassoc = adapter->dbg.num_event_disassoc; + info->num_event_link_lost = adapter->dbg.num_event_link_lost; + info->num_cmd_deauth = adapter->dbg.num_cmd_deauth; + info->num_cmd_assoc_success = + adapter->dbg.num_cmd_assoc_success; + info->num_cmd_assoc_failure = + adapter->dbg.num_cmd_assoc_failure; + info->num_tx_timeout = adapter->dbg.num_tx_timeout; + info->num_cmd_timeout = adapter->dbg.num_cmd_timeout; + info->timeout_cmd_id = adapter->dbg.timeout_cmd_id; + info->timeout_cmd_act = adapter->dbg.timeout_cmd_act; + memcpy(info->last_cmd_id, adapter->dbg.last_cmd_id, + sizeof(adapter->dbg.last_cmd_id)); + memcpy(info->last_cmd_act, adapter->dbg.last_cmd_act, + sizeof(adapter->dbg.last_cmd_act)); + info->last_cmd_index = adapter->dbg.last_cmd_index; + memcpy(info->last_cmd_resp_id, adapter->dbg.last_cmd_resp_id, + sizeof(adapter->dbg.last_cmd_resp_id)); + info->last_cmd_resp_index = adapter->dbg.last_cmd_resp_index; + memcpy(info->last_event, adapter->dbg.last_event, + sizeof(adapter->dbg.last_event)); + info->last_event_index = adapter->dbg.last_event_index; + info->data_sent = adapter->data_sent; + info->cmd_sent = adapter->cmd_sent; + info->cmd_resp_received = adapter->cmd_resp_received; + } + + return 0; +} + +/* + * This function processes the received packet before sending it to the + * kernel. + * + * It extracts the SKB from the received buffer and sends it to kernel. + * In case the received buffer does not contain the data in SKB format, + * the function creates a blank SKB, fills it with the data from the + * received buffer and then sends this new SKB to the kernel. + */ +int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) +{ + struct mwifiex_rxinfo *rx_info = NULL; + struct mwifiex_private *priv = NULL; + + if (!skb) + return -1; + + rx_info = MWIFIEX_SKB_RXCB(skb); + priv = mwifiex_bss_index_to_priv(adapter, rx_info->bss_index); + if (!priv) + return -1; + + skb->dev = priv->netdev; + skb->protocol = eth_type_trans(skb, priv->netdev); + skb->ip_summed = CHECKSUM_NONE; + priv->stats.rx_bytes += skb->len; + priv->stats.rx_packets++; + if (in_interrupt()) + netif_rx(skb); + else + netif_rx_ni(skb); + + return 0; +} + +/* + * Receive packet completion callback handler. + * + * This function updates the statistics and frees the buffer SKB. + */ +int mwifiex_recv_complete(struct mwifiex_adapter *adapter, + struct sk_buff *skb, int status) +{ + struct mwifiex_private *priv = NULL; + struct mwifiex_rxinfo *rx_info = NULL; + + if (!skb) + return 0; + + rx_info = MWIFIEX_SKB_RXCB(skb); + priv = mwifiex_bss_index_to_priv(adapter, rx_info->bss_index); + + if (priv && (status == -1)) + priv->stats.rx_dropped++; + + dev_kfree_skb_any(skb); + + return 0; +} + +/* + * IOCTL completion callback handler. + * + * This function is called when a pending IOCTL is completed. + * + * If work queue support is enabled, the function wakes up the + * corresponding waiting function. Otherwise, it processes the + * IOCTL response and frees the response buffer. + */ +int mwifiex_ioctl_complete(struct mwifiex_adapter *adapter, + struct mwifiex_wait_queue *wait_queue, + int status) +{ + enum mwifiex_error_code status_code = + (enum mwifiex_error_code) wait_queue->status; + + atomic_dec(&adapter->ioctl_pending); + + dev_dbg(adapter->dev, "cmd: IOCTL completed: status=%d," + " status_code=%#x\n", status, status_code); + + if (wait_queue->enabled) { + *wait_queue->condition = true; + wait_queue->status = status; + if (status && (status_code == MWIFIEX_ERROR_CMD_TIMEOUT)) + dev_err(adapter->dev, "cmd timeout\n"); + else + wake_up_interruptible(wait_queue->wait); + } else { + if (status) + dev_err(adapter->dev, "cmd failed: status_code=%#x\n", + status_code); + kfree(wait_queue); + } + + return 0; +} diff --git a/drivers/net/wireless/mwifiex/util.h b/drivers/net/wireless/mwifiex/util.h new file mode 100644 index 000000000000..9506afc6c0e4 --- /dev/null +++ b/drivers/net/wireless/mwifiex/util.h @@ -0,0 +1,32 @@ +/* + * Marvell Wireless LAN device driver: utility functions + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#ifndef _MWIFIEX_UTIL_H_ +#define _MWIFIEX_UTIL_H_ + +static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb) +{ + return (struct mwifiex_rxinfo *)skb->cb; +} + +static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb) +{ + return (struct mwifiex_txinfo *)skb->cb; +} +#endif /* !_MWIFIEX_UTIL_H_ */ diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c new file mode 100644 index 000000000000..1cfbc6bed692 --- /dev/null +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -0,0 +1,1237 @@ +/* + * Marvell Wireless LAN device driver: WMM + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "util.h" +#include "fw.h" +#include "main.h" +#include "wmm.h" +#include "11n.h" + + +/* Maximum value FW can accept for driver delay in packet transmission */ +#define DRV_PKT_DELAY_TO_FW_MAX 512 + + +#define WMM_QUEUED_PACKET_LOWER_LIMIT 180 + +#define WMM_QUEUED_PACKET_UPPER_LIMIT 200 + +/* Offset for TOS field in the IP header */ +#define IPTOS_OFFSET 5 + +/* WMM information IE */ +static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07, + 0x00, 0x50, 0xf2, 0x02, + 0x00, 0x01, 0x00 +}; + +static const u8 wmm_aci_to_qidx_map[] = { WMM_AC_BE, + WMM_AC_BK, + WMM_AC_VI, + WMM_AC_VO +}; + +static u8 tos_to_tid[] = { + /* TID DSCP_P2 DSCP_P1 DSCP_P0 WMM_AC */ + 0x01, /* 0 1 0 AC_BK */ + 0x02, /* 0 0 0 AC_BK */ + 0x00, /* 0 0 1 AC_BE */ + 0x03, /* 0 1 1 AC_BE */ + 0x04, /* 1 0 0 AC_VI */ + 0x05, /* 1 0 1 AC_VI */ + 0x06, /* 1 1 0 AC_VO */ + 0x07 /* 1 1 1 AC_VO */ +}; + +/* + * This table inverses the tos_to_tid operation to get a priority + * which is in sequential order, and can be compared. + * Use this to compare the priority of two different TIDs. + */ +static u8 tos_to_tid_inv[] = { + 0x02, /* from tos_to_tid[2] = 0 */ + 0x00, /* from tos_to_tid[0] = 1 */ + 0x01, /* from tos_to_tid[1] = 2 */ + 0x03, + 0x04, + 0x05, + 0x06, + 0x07}; + +static u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} }; + +/* + * This function debug prints the priority parameters for a WMM AC. + */ +static void +mwifiex_wmm_ac_debug_print(const struct ieee_types_wmm_ac_parameters *ac_param) +{ + const char *ac_str[] = { "BK", "BE", "VI", "VO" }; + + pr_debug("info: WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, " + "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n", + ac_str[wmm_aci_to_qidx_map[(ac_param->aci_aifsn_bitmap + & MWIFIEX_ACI) >> 5]], + (ac_param->aci_aifsn_bitmap & MWIFIEX_ACI) >> 5, + (ac_param->aci_aifsn_bitmap & MWIFIEX_ACM) >> 4, + ac_param->aci_aifsn_bitmap & MWIFIEX_AIFSN, + ac_param->ecw_bitmap & MWIFIEX_ECW_MIN, + (ac_param->ecw_bitmap & MWIFIEX_ECW_MAX) >> 4, + le16_to_cpu(ac_param->tx_op_limit)); +} + +/* + * This function allocates a route address list. + * + * The function also initializes the list with the provided RA. + */ +static struct mwifiex_ra_list_tbl * +mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra) +{ + struct mwifiex_ra_list_tbl *ra_list; + + ra_list = kzalloc(sizeof(struct mwifiex_ra_list_tbl), GFP_ATOMIC); + + if (!ra_list) { + dev_err(adapter->dev, "%s: failed to alloc ra_list\n", + __func__); + return NULL; + } + INIT_LIST_HEAD(&ra_list->list); + skb_queue_head_init(&ra_list->skb_head); + + memcpy(ra_list->ra, ra, ETH_ALEN); + + ra_list->total_pkts_size = 0; + + dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list); + + return ra_list; +} + +/* + * This function allocates and adds a RA list for all TIDs + * with the given RA. + */ +void +mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra) +{ + int i; + struct mwifiex_ra_list_tbl *ra_list; + struct mwifiex_adapter *adapter = priv->adapter; + + for (i = 0; i < MAX_NUM_TID; ++i) { + ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra); + dev_dbg(adapter->dev, "info: created ra_list %p\n", ra_list); + + if (!ra_list) + break; + + if (!mwifiex_queuing_ra_based(priv)) + ra_list->is_11n_enabled = IS_11N_ENABLED(priv); + else + ra_list->is_11n_enabled = false; + + dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n", + ra_list, ra_list->is_11n_enabled); + + list_add_tail(&ra_list->list, + &priv->wmm.tid_tbl_ptr[i].ra_list); + + if (!priv->wmm.tid_tbl_ptr[i].ra_list_curr) + priv->wmm.tid_tbl_ptr[i].ra_list_curr = ra_list; + } +} + +/* + * This function sets the WMM queue priorities to their default values. + */ +static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv) +{ + /* Default queue priorities: VO->VI->BE->BK */ + priv->wmm.queue_priority[0] = WMM_AC_VO; + priv->wmm.queue_priority[1] = WMM_AC_VI; + priv->wmm.queue_priority[2] = WMM_AC_BE; + priv->wmm.queue_priority[3] = WMM_AC_BK; +} + +/* + * This function map ACs to TIDs. + */ +static void +mwifiex_wmm_queue_priorities_tid(struct mwifiex_private *priv, + u8 queue_priority[]) +{ + int i; + + for (i = 0; i < 4; ++i) { + tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1]; + tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0]; + } +} + +/* + * This function initializes WMM priority queues. + */ +void +mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, + struct ieee_types_wmm_parameter *wmm_ie) +{ + u16 cw_min, avg_back_off, tmp[4]; + u32 i, j, num_ac; + u8 ac_idx; + + if (!wmm_ie || !priv->wmm_enabled) { + /* WMM is not enabled, just set the defaults and return */ + mwifiex_wmm_default_queue_priorities(priv); + return; + } + + dev_dbg(priv->adapter->dev, "info: WMM Parameter IE: version=%d, " + "qos_info Parameter Set Count=%d, Reserved=%#x\n", + wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap & + IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK, + wmm_ie->reserved); + + for (num_ac = 0; num_ac < ARRAY_SIZE(wmm_ie->ac_params); num_ac++) { + cw_min = (1 << (wmm_ie->ac_params[num_ac].ecw_bitmap & + MWIFIEX_ECW_MIN)) - 1; + avg_back_off = (cw_min >> 1) + + (wmm_ie->ac_params[num_ac].aci_aifsn_bitmap & + MWIFIEX_AIFSN); + + ac_idx = wmm_aci_to_qidx_map[(wmm_ie->ac_params[num_ac]. + aci_aifsn_bitmap & + MWIFIEX_ACI) >> 5]; + priv->wmm.queue_priority[ac_idx] = ac_idx; + tmp[ac_idx] = avg_back_off; + + dev_dbg(priv->adapter->dev, "info: WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n", + (1 << ((wmm_ie->ac_params[num_ac].ecw_bitmap & + MWIFIEX_ECW_MAX) >> 4)) - 1, + cw_min, avg_back_off); + mwifiex_wmm_ac_debug_print(&wmm_ie->ac_params[num_ac]); + } + + /* Bubble sort */ + for (i = 0; i < num_ac; i++) { + for (j = 1; j < num_ac - i; j++) { + if (tmp[j - 1] > tmp[j]) { + swap(tmp[j - 1], tmp[j]); + swap(priv->wmm.queue_priority[j - 1], + priv->wmm.queue_priority[j]); + } else if (tmp[j - 1] == tmp[j]) { + if (priv->wmm.queue_priority[j - 1] + < priv->wmm.queue_priority[j]) + swap(priv->wmm.queue_priority[j - 1], + priv->wmm.queue_priority[j]); + } + } + } + + mwifiex_wmm_queue_priorities_tid(priv, priv->wmm.queue_priority); +} + +/* + * This function evaluates whether or not an AC is to be downgraded. + * + * In case the AC is not enabled, the highest AC is returned that is + * enabled and does not require admission control. + */ +static enum mwifiex_wmm_ac_e +mwifiex_wmm_eval_downgrade_ac(struct mwifiex_private *priv, + enum mwifiex_wmm_ac_e eval_ac) +{ + int down_ac; + enum mwifiex_wmm_ac_e ret_ac; + struct mwifiex_wmm_ac_status *ac_status; + + ac_status = &priv->wmm.ac_status[eval_ac]; + + if (!ac_status->disabled) + /* Okay to use this AC, its enabled */ + return eval_ac; + + /* Setup a default return value of the lowest priority */ + ret_ac = WMM_AC_BK; + + /* + * Find the highest AC that is enabled and does not require + * admission control. The spec disallows downgrading to an AC, + * which is enabled due to a completed admission control. + * Unadmitted traffic is not to be sent on an AC with admitted + * traffic. + */ + for (down_ac = WMM_AC_BK; down_ac < eval_ac; down_ac++) { + ac_status = &priv->wmm.ac_status[down_ac]; + + if (!ac_status->disabled && !ac_status->flow_required) + /* AC is enabled and does not require admission + control */ + ret_ac = (enum mwifiex_wmm_ac_e) down_ac; + } + + return ret_ac; +} + +/* + * This function downgrades WMM priority queue. + */ +void +mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv) +{ + int ac_val; + + dev_dbg(priv->adapter->dev, "info: WMM: AC Priorities:" + "BK(0), BE(1), VI(2), VO(3)\n"); + + if (!priv->wmm_enabled) { + /* WMM is not enabled, default priorities */ + for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) + priv->wmm.ac_down_graded_vals[ac_val] = + (enum mwifiex_wmm_ac_e) ac_val; + } else { + for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) { + priv->wmm.ac_down_graded_vals[ac_val] + = mwifiex_wmm_eval_downgrade_ac(priv, + (enum mwifiex_wmm_ac_e) ac_val); + dev_dbg(priv->adapter->dev, "info: WMM: AC PRIO %d maps to %d\n", + ac_val, priv->wmm.ac_down_graded_vals[ac_val]); + } + } +} + +/* + * This function converts the IP TOS field to an WMM AC + * Queue assignment. + */ +static enum mwifiex_wmm_ac_e +mwifiex_wmm_convert_tos_to_ac(struct mwifiex_adapter *adapter, u32 tos) +{ + /* Map of TOS UP values to WMM AC */ + const enum mwifiex_wmm_ac_e tos_to_ac[] = { WMM_AC_BE, + WMM_AC_BK, + WMM_AC_BK, + WMM_AC_BE, + WMM_AC_VI, + WMM_AC_VI, + WMM_AC_VO, + WMM_AC_VO + }; + + if (tos >= ARRAY_SIZE(tos_to_ac)) + return WMM_AC_BE; + + return tos_to_ac[tos]; +} + +/* + * This function evaluates a given TID and downgrades it to a lower + * TID if the WMM Parameter IE received from the AP indicates that the + * AP is disabled (due to call admission control (ACM bit). Mapping + * of TID to AC is taken care of internally. + */ +static u8 +mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid) +{ + enum mwifiex_wmm_ac_e ac, ac_down; + u8 new_tid; + + ac = mwifiex_wmm_convert_tos_to_ac(priv->adapter, tid); + ac_down = priv->wmm.ac_down_graded_vals[ac]; + + /* Send the index to tid array, picking from the array will be + * taken care by dequeuing function + */ + new_tid = ac_to_tid[ac_down][tid % 2]; + + return new_tid; +} + +/* + * This function initializes the WMM state information and the + * WMM data path queues. + */ +void +mwifiex_wmm_init(struct mwifiex_adapter *adapter) +{ + int i, j; + struct mwifiex_private *priv; + + for (j = 0; j < adapter->priv_num; ++j) { + priv = adapter->priv[j]; + if (!priv) + continue; + + for (i = 0; i < MAX_NUM_TID; ++i) { + priv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i]; + priv->aggr_prio_tbl[i].ampdu_ap = tos_to_tid_inv[i]; + priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i]; + priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL; + } + + priv->aggr_prio_tbl[6].amsdu + = priv->aggr_prio_tbl[6].ampdu_ap + = priv->aggr_prio_tbl[6].ampdu_user + = BA_STREAM_NOT_ALLOWED; + + priv->aggr_prio_tbl[7].amsdu = priv->aggr_prio_tbl[7].ampdu_ap + = priv->aggr_prio_tbl[7].ampdu_user + = BA_STREAM_NOT_ALLOWED; + + priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; + priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE; + priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; + } +} + +/* + * This function checks if WMM Tx queue is empty. + */ +int +mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) +{ + int i, j; + struct mwifiex_private *priv; + + for (j = 0; j < adapter->priv_num; ++j) { + priv = adapter->priv[j]; + if (priv) { + for (i = 0; i < MAX_NUM_TID; i++) + if (!mwifiex_wmm_is_ra_list_empty(adapter, + &priv->wmm.tid_tbl_ptr[i].ra_list)) + return false; + } + } + + return true; +} + +/* + * This function deletes all packets in an RA list node. + * + * The packet sent completion callback handler are called with + * status failure, after they are dequeued to ensure proper + * cleanup. The RA list node itself is freed at the end. + */ +static void +mwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ra_list) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct sk_buff *skb, *tmp; + + skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) + mwifiex_write_data_complete(adapter, skb, -1); +} + +/* + * This function deletes all packets in an RA list. + * + * Each nodes in the RA list are freed individually first, and then + * the RA list itself is freed. + */ +static void +mwifiex_wmm_del_pkts_in_ralist(struct mwifiex_private *priv, + struct list_head *ra_list_head) +{ + struct mwifiex_ra_list_tbl *ra_list; + + list_for_each_entry(ra_list, ra_list_head, list) + mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list); +} + +/* + * This function deletes all packets in all RA lists. + */ +static void mwifiex_wmm_cleanup_queues(struct mwifiex_private *priv) +{ + int i; + + for (i = 0; i < MAX_NUM_TID; i++) + mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i]. + ra_list); +} + +/* + * This function deletes all route addresses from all RA lists. + */ +static void mwifiex_wmm_delete_all_ralist(struct mwifiex_private *priv) +{ + struct mwifiex_ra_list_tbl *ra_list, *tmp_node; + int i; + + for (i = 0; i < MAX_NUM_TID; ++i) { + dev_dbg(priv->adapter->dev, + "info: ra_list: freeing buf for tid %d\n", i); + list_for_each_entry_safe(ra_list, tmp_node, + &priv->wmm.tid_tbl_ptr[i].ra_list, list) { + list_del(&ra_list->list); + kfree(ra_list); + } + + INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[i].ra_list); + + priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL; + } +} + +/* + * This function cleans up the Tx and Rx queues. + * + * Cleanup includes - + * - All packets in RA lists + * - All entries in Rx reorder table + * - All entries in Tx BA stream table + * - MPA buffer (if required) + * - All RA lists + */ +void +mwifiex_clean_txrx(struct mwifiex_private *priv) +{ + unsigned long flags; + + mwifiex_11n_cleanup_reorder_tbl(priv); + spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); + + mwifiex_wmm_cleanup_queues(priv); + mwifiex_11n_delete_all_tx_ba_stream_tbl(priv); + + if (priv->adapter->if_ops.cleanup_mpa_buf) + priv->adapter->if_ops.cleanup_mpa_buf(priv->adapter); + + mwifiex_wmm_delete_all_ralist(priv); + memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid)); + + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); +} + +/* + * This function retrieves a particular RA list node, matching with the + * given TID and RA address. + */ +static struct mwifiex_ra_list_tbl * +mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, + u8 *ra_addr) +{ + struct mwifiex_ra_list_tbl *ra_list; + + list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[tid].ra_list, + list) { + if (!memcmp(ra_list->ra, ra_addr, ETH_ALEN)) + return ra_list; + } + + return NULL; +} + +/* + * This function retrieves an RA list node for a given TID and + * RA address pair. + * + * If no such node is found, a new node is added first and then + * retrieved. + */ +static struct mwifiex_ra_list_tbl * +mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) +{ + struct mwifiex_ra_list_tbl *ra_list; + + ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra_addr); + if (ra_list) + return ra_list; + mwifiex_ralist_add(priv, ra_addr); + + return mwifiex_wmm_get_ralist_node(priv, tid, ra_addr); +} + +/* + * This function checks if a particular RA list node exists in a given TID + * table index. + */ +int +mwifiex_is_ralist_valid(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ra_list, int ptr_index) +{ + struct mwifiex_ra_list_tbl *rlist; + + list_for_each_entry(rlist, &priv->wmm.tid_tbl_ptr[ptr_index].ra_list, + list) { + if (rlist == ra_list) + return true; + } + + return false; +} + +/* + * This function adds a packet to WMM queue. + * + * In disconnected state the packet is immediately dropped and the + * packet send completion callback is called with status failure. + * + * Otherwise, the correct RA list node is located and the packet + * is queued at the list tail. + */ +void +mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, + struct sk_buff *skb) +{ + struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); + struct mwifiex_private *priv = adapter->priv[tx_info->bss_index]; + u32 tid; + struct mwifiex_ra_list_tbl *ra_list; + u8 ra[ETH_ALEN], tid_down; + unsigned long flags; + + if (!priv->media_connected) { + dev_dbg(adapter->dev, "data: drop packet in disconnect\n"); + mwifiex_write_data_complete(adapter, skb, -1); + return; + } + + tid = skb->priority; + + spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); + + tid_down = mwifiex_wmm_downgrade_tid(priv, tid); + + /* In case of infra as we have already created the list during + association we just don't have to call get_queue_raptr, we will + have only 1 raptr for a tid in case of infra */ + if (!mwifiex_queuing_ra_based(priv)) { + if (!list_empty(&priv->wmm.tid_tbl_ptr[tid_down].ra_list)) + ra_list = list_first_entry( + &priv->wmm.tid_tbl_ptr[tid_down].ra_list, + struct mwifiex_ra_list_tbl, list); + else + ra_list = NULL; + } else { + memcpy(ra, skb->data, ETH_ALEN); + ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra); + } + + if (!ra_list) { + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); + mwifiex_write_data_complete(adapter, skb, -1); + return; + } + + skb_queue_tail(&ra_list->skb_head, skb); + + ra_list->total_pkts_size += skb->len; + + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); +} + +/* + * This function processes the get WMM status command response from firmware. + * + * The response may contain multiple TLVs - + * - AC Queue status TLVs + * - Current WMM Parameter IE TLV + * - Admission Control action frame TLVs + * + * This function parses the TLVs and then calls further specific functions + * to process any changes in the queue prioritize or state. + */ +int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, + const struct host_cmd_ds_command *resp) +{ + u8 *curr = (u8 *) &resp->params.get_wmm_status; + uint16_t resp_len = le16_to_cpu(resp->size), tlv_len; + int valid = true; + + struct mwifiex_ie_types_data *tlv_hdr; + struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus; + struct ieee_types_wmm_parameter *wmm_param_ie = NULL; + struct mwifiex_wmm_ac_status *ac_status; + + dev_dbg(priv->adapter->dev, "info: WMM: WMM_GET_STATUS cmdresp received: %d\n", + resp_len); + + while ((resp_len >= sizeof(tlv_hdr->header)) && valid) { + tlv_hdr = (struct mwifiex_ie_types_data *) curr; + tlv_len = le16_to_cpu(tlv_hdr->header.len); + + switch (le16_to_cpu(tlv_hdr->header.type)) { + case TLV_TYPE_WMMQSTATUS: + tlv_wmm_qstatus = + (struct mwifiex_ie_types_wmm_queue_status *) + tlv_hdr; + dev_dbg(priv->adapter->dev, + "info: CMD_RESP: WMM_GET_STATUS:" + " QSTATUS TLV: %d, %d, %d\n", + tlv_wmm_qstatus->queue_index, + tlv_wmm_qstatus->flow_required, + tlv_wmm_qstatus->disabled); + + ac_status = &priv->wmm.ac_status[tlv_wmm_qstatus-> + queue_index]; + ac_status->disabled = tlv_wmm_qstatus->disabled; + ac_status->flow_required = + tlv_wmm_qstatus->flow_required; + ac_status->flow_created = tlv_wmm_qstatus->flow_created; + break; + + case WLAN_EID_VENDOR_SPECIFIC: + /* + * Point the regular IEEE IE 2 bytes into the Marvell IE + * and setup the IEEE IE type and length byte fields + */ + + wmm_param_ie = + (struct ieee_types_wmm_parameter *) (curr + + 2); + wmm_param_ie->vend_hdr.len = (u8) tlv_len; + wmm_param_ie->vend_hdr.element_id = + WLAN_EID_VENDOR_SPECIFIC; + + dev_dbg(priv->adapter->dev, + "info: CMD_RESP: WMM_GET_STATUS:" + " WMM Parameter Set Count: %d\n", + wmm_param_ie->qos_info_bitmap & + IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK); + + memcpy((u8 *) &priv->curr_bss_params.bss_descriptor. + wmm_ie, wmm_param_ie, + wmm_param_ie->vend_hdr.len + 2); + + break; + + default: + valid = false; + break; + } + + curr += (tlv_len + sizeof(tlv_hdr->header)); + resp_len -= (tlv_len + sizeof(tlv_hdr->header)); + } + + mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie); + mwifiex_wmm_setup_ac_downgrade(priv); + + return 0; +} + +/* + * Callback handler from the command module to allow insertion of a WMM TLV. + * + * If the BSS we are associating to supports WMM, this function adds the + * required WMM Information IE to the association request command buffer in + * the form of a Marvell extended IEEE IE. + */ +u32 +mwifiex_wmm_process_association_req(struct mwifiex_private *priv, + u8 **assoc_buf, + struct ieee_types_wmm_parameter *wmm_ie, + struct ieee80211_ht_cap *ht_cap) +{ + struct mwifiex_ie_types_wmm_param_set *wmm_tlv; + u32 ret_len = 0; + + /* Null checks */ + if (!assoc_buf) + return 0; + if (!(*assoc_buf)) + return 0; + + if (!wmm_ie) + return 0; + + dev_dbg(priv->adapter->dev, "info: WMM: process assoc req:" + "bss->wmmIe=0x%x\n", + wmm_ie->vend_hdr.element_id); + + if ((priv->wmm_required + || (ht_cap && (priv->adapter->config_bands & BAND_GN + || priv->adapter->config_bands & BAND_AN)) + ) + && wmm_ie->vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) { + wmm_tlv = (struct mwifiex_ie_types_wmm_param_set *) *assoc_buf; + wmm_tlv->header.type = cpu_to_le16((u16) wmm_info_ie[0]); + wmm_tlv->header.len = cpu_to_le16((u16) wmm_info_ie[1]); + memcpy(wmm_tlv->wmm_ie, &wmm_info_ie[2], + le16_to_cpu(wmm_tlv->header.len)); + if (wmm_ie->qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) + memcpy((u8 *) (wmm_tlv->wmm_ie + + le16_to_cpu(wmm_tlv->header.len) + - sizeof(priv->wmm_qosinfo)), + &priv->wmm_qosinfo, + sizeof(priv->wmm_qosinfo)); + + ret_len = sizeof(wmm_tlv->header) + + le16_to_cpu(wmm_tlv->header.len); + + *assoc_buf += ret_len; + } + + return ret_len; +} + +/* + * This function computes the time delay in the driver queues for a + * given packet. + * + * When the packet is received at the OS/Driver interface, the current + * time is set in the packet structure. The difference between the present + * time and that received time is computed in this function and limited + * based on pre-compiled limits in the driver. + */ +u8 +mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, + const struct sk_buff *skb) +{ + u8 ret_val = 0; + struct timeval out_tstamp, in_tstamp; + u32 queue_delay; + + do_gettimeofday(&out_tstamp); + in_tstamp = ktime_to_timeval(skb->tstamp); + + queue_delay = (out_tstamp.tv_sec - in_tstamp.tv_sec) * 1000; + queue_delay += (out_tstamp.tv_usec - in_tstamp.tv_usec) / 1000; + + /* + * Queue delay is passed as a uint8 in units of 2ms (ms shifted + * by 1). Min value (other than 0) is therefore 2ms, max is 510ms. + * + * Pass max value if queue_delay is beyond the uint8 range + */ + ret_val = (u8) (min(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1); + + dev_dbg(priv->adapter->dev, "data: WMM: Pkt Delay: %d ms," + " %d ms sent to FW\n", queue_delay, ret_val); + + return ret_val; +} + +/* + * This function retrieves the highest priority RA list table pointer. + */ +static struct mwifiex_ra_list_tbl * +mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, + struct mwifiex_private **priv, int *tid) +{ + struct mwifiex_private *priv_tmp; + struct mwifiex_ra_list_tbl *ptr, *head; + struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head; + struct mwifiex_tid_tbl *tid_ptr; + int is_list_empty; + unsigned long flags; + int i, j; + + for (j = adapter->priv_num - 1; j >= 0; --j) { + spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock, + flags); + is_list_empty = list_empty(&adapter->bss_prio_tbl[j] + .bss_prio_head); + spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, + flags); + if (is_list_empty) + continue; + + if (adapter->bss_prio_tbl[j].bss_prio_cur == + (struct mwifiex_bss_prio_node *) + &adapter->bss_prio_tbl[j].bss_prio_head) { + bssprio_node = + list_first_entry(&adapter->bss_prio_tbl[j] + .bss_prio_head, + struct mwifiex_bss_prio_node, + list); + bssprio_head = bssprio_node; + } else { + bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur; + bssprio_head = bssprio_node; + } + + do { + priv_tmp = bssprio_node->priv; + + for (i = HIGH_PRIO_TID; i >= LOW_PRIO_TID; --i) { + + tid_ptr = &(priv_tmp)->wmm. + tid_tbl_ptr[tos_to_tid[i]]; + + spin_lock_irqsave(&tid_ptr->tid_tbl_lock, + flags); + is_list_empty = + list_empty(&adapter->bss_prio_tbl[j] + .bss_prio_head); + spin_unlock_irqrestore(&tid_ptr->tid_tbl_lock, + flags); + if (is_list_empty) + continue; + + /* + * Always choose the next ra we transmitted + * last time, this way we pick the ra's in + * round robin fashion. + */ + ptr = list_first_entry( + &tid_ptr->ra_list_curr->list, + struct mwifiex_ra_list_tbl, + list); + + head = ptr; + if (ptr == (struct mwifiex_ra_list_tbl *) + &tid_ptr->ra_list) { + /* Get next ra */ + ptr = list_first_entry(&ptr->list, + struct mwifiex_ra_list_tbl, list); + head = ptr; + } + + do { + is_list_empty = + skb_queue_empty(&ptr->skb_head); + if (!is_list_empty) { + *priv = priv_tmp; + *tid = tos_to_tid[i]; + return ptr; + } + /* Get next ra */ + ptr = list_first_entry(&ptr->list, + struct mwifiex_ra_list_tbl, + list); + if (ptr == + (struct mwifiex_ra_list_tbl *) + &tid_ptr->ra_list) + ptr = list_first_entry( + &ptr->list, + struct mwifiex_ra_list_tbl, + list); + } while (ptr != head); + } + + /* Get next bss priority node */ + bssprio_node = list_first_entry(&bssprio_node->list, + struct mwifiex_bss_prio_node, + list); + + if (bssprio_node == + (struct mwifiex_bss_prio_node *) + &adapter->bss_prio_tbl[j].bss_prio_head) + /* Get next bss priority node */ + bssprio_node = list_first_entry( + &bssprio_node->list, + struct mwifiex_bss_prio_node, + list); + } while (bssprio_node != bssprio_head); + } + return NULL; +} + +/* + * This function gets the number of packets in the Tx queue of a + * particular RA list. + */ +static int +mwifiex_num_pkts_in_txq(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ptr, int max_buf_size) +{ + int count = 0, total_size = 0; + struct sk_buff *skb, *tmp; + + skb_queue_walk_safe(&ptr->skb_head, skb, tmp) { + total_size += skb->len; + if (total_size < max_buf_size) + ++count; + else + break; + } + + return count; +} + +/* + * This function sends a single packet to firmware for transmission. + */ +static void +mwifiex_send_single_packet(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ptr, int ptr_index, + unsigned long ra_list_flags) + __releases(&priv->wmm.ra_list_spinlock) +{ + struct sk_buff *skb, *skb_next; + struct mwifiex_tx_param tx_param; + struct mwifiex_adapter *adapter = priv->adapter; + int status = 0; + struct mwifiex_txinfo *tx_info; + + if (skb_queue_empty(&ptr->skb_head)) { + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + dev_dbg(adapter->dev, "data: nothing to send\n"); + return; + } + + skb = skb_dequeue(&ptr->skb_head); + + tx_info = MWIFIEX_SKB_TXCB(skb); + dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb); + + ptr->total_pkts_size -= skb->len; + + if (!skb_queue_empty(&ptr->skb_head)) + skb_next = skb_peek(&ptr->skb_head); + else + skb_next = NULL; + + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); + + tx_param.next_pkt_len = ((skb_next) ? skb_next->len + + sizeof(struct txpd) : 0); + + status = mwifiex_process_tx(priv, skb, &tx_param); + + if (status == -EBUSY) { + /* Queue the packet back at the head */ + spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); + + if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + mwifiex_write_data_complete(adapter, skb, -1); + return; + } + + skb_queue_tail(&ptr->skb_head, skb); + + ptr->total_pkts_size += skb->len; + tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + } else { + spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); + if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { + priv->wmm.packets_out[ptr_index]++; + priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr; + } + adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = + list_first_entry( + &adapter->bss_prio_tbl[priv->bss_priority] + .bss_prio_cur->list, + struct mwifiex_bss_prio_node, + list); + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + } +} + +/* + * This function checks if the first packet in the given RA list + * is already processed or not. + */ +static int +mwifiex_is_ptr_processed(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ptr) +{ + struct sk_buff *skb; + struct mwifiex_txinfo *tx_info; + + if (skb_queue_empty(&ptr->skb_head)) + return false; + + skb = skb_peek(&ptr->skb_head); + + tx_info = MWIFIEX_SKB_TXCB(skb); + if (tx_info->flags & MWIFIEX_BUF_FLAG_REQUEUED_PKT) + return true; + + return false; +} + +/* + * This function sends a single processed packet to firmware for + * transmission. + */ +static void +mwifiex_send_processed_packet(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ptr, int ptr_index, + unsigned long ra_list_flags) + __releases(&priv->wmm.ra_list_spinlock) +{ + struct mwifiex_tx_param tx_param; + struct mwifiex_adapter *adapter = priv->adapter; + int ret = -1; + struct sk_buff *skb, *skb_next; + struct mwifiex_txinfo *tx_info; + + if (skb_queue_empty(&ptr->skb_head)) { + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + return; + } + + skb = skb_dequeue(&ptr->skb_head); + + if (!skb_queue_empty(&ptr->skb_head)) + skb_next = skb_peek(&ptr->skb_head); + else + skb_next = NULL; + + tx_info = MWIFIEX_SKB_TXCB(skb); + + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); + tx_param.next_pkt_len = + ((skb_next) ? skb_next->len + + sizeof(struct txpd) : 0); + ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, + skb->data, skb->len, &tx_param); + switch (ret) { + case -EBUSY: + dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); + spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); + + if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + mwifiex_write_data_complete(adapter, skb, -1); + return; + } + + skb_queue_tail(&ptr->skb_head, skb); + + tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + break; + case -1: + adapter->data_sent = false; + dev_err(adapter->dev, "host_to_card failed: %#x\n", ret); + adapter->dbg.num_tx_host_to_card_failure++; + mwifiex_write_data_complete(adapter, skb, ret); + break; + case -EINPROGRESS: + adapter->data_sent = false; + default: + break; + } + if (ret != -EBUSY) { + spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); + if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { + priv->wmm.packets_out[ptr_index]++; + priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr; + } + adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = + list_first_entry( + &adapter->bss_prio_tbl[priv->bss_priority] + .bss_prio_cur->list, + struct mwifiex_bss_prio_node, + list); + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, + ra_list_flags); + } +} + +/* + * This function dequeues a packet from the highest priority list + * and transmits it. + */ +static int +mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) +{ + struct mwifiex_ra_list_tbl *ptr; + struct mwifiex_private *priv = NULL; + int ptr_index = 0; + u8 ra[ETH_ALEN]; + int tid_del = 0, tid = 0; + unsigned long flags; + + ptr = mwifiex_wmm_get_highest_priolist_ptr(adapter, &priv, &ptr_index); + if (!ptr) + return -1; + + tid = mwifiex_get_tid(priv->adapter, ptr); + + dev_dbg(adapter->dev, "data: tid=%d\n", tid); + + spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); + if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); + return -1; + } + + if (mwifiex_is_ptr_processed(priv, ptr)) { + mwifiex_send_processed_packet(priv, ptr, ptr_index, flags); + /* ra_list_spinlock has been freed in + mwifiex_send_processed_packet() */ + return 0; + } + + if (!ptr->is_11n_enabled || mwifiex_is_ba_stream_setup(priv, ptr, tid) + || ((priv->sec_info.wpa_enabled + || priv->sec_info.wpa2_enabled) && !priv->wpa_is_gtk_set) + ) { + mwifiex_send_single_packet(priv, ptr, ptr_index, flags); + /* ra_list_spinlock has been freed in + mwifiex_send_single_packet() */ + } else { + if (mwifiex_is_ampdu_allowed(priv, ptr, tid)) { + if (mwifiex_is_ba_stream_avail(priv)) { + mwifiex_11n_create_tx_ba_stream_tbl(priv, + ptr->ra, tid, + BA_STREAM_SETUP_INPROGRESS); + mwifiex_send_addba(priv, tid, ptr->ra); + } else if (mwifiex_find_stream_to_delete + (priv, ptr, tid, &tid_del, ra)) { + mwifiex_11n_create_tx_ba_stream_tbl(priv, + ptr->ra, tid, + BA_STREAM_SETUP_INPROGRESS); + mwifiex_send_delba(priv, tid_del, ra, 1); + } + } +/* Minimum number of AMSDU */ +#define MIN_NUM_AMSDU 2 + if (mwifiex_is_amsdu_allowed(priv, ptr, tid) && + (mwifiex_num_pkts_in_txq(priv, ptr, adapter->tx_buf_size) >= + MIN_NUM_AMSDU)) + mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN, + ptr_index, flags); + /* ra_list_spinlock has been freed in + mwifiex_11n_aggregate_pkt() */ + else + mwifiex_send_single_packet(priv, ptr, ptr_index, flags); + /* ra_list_spinlock has been freed in + mwifiex_send_single_packet() */ + } + return 0; +} + +/* + * This function transmits the highest priority packet awaiting in the + * WMM Queues. + */ +void +mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) +{ + do { + /* Check if busy */ + if (adapter->data_sent || adapter->tx_lock_flag) + break; + + if (mwifiex_dequeue_tx_packet(adapter)) + break; + } while (true); + + return; +} diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h new file mode 100644 index 000000000000..241f1b0b77f9 --- /dev/null +++ b/drivers/net/wireless/mwifiex/wmm.h @@ -0,0 +1,112 @@ +/* + * Marvell Wireless LAN device driver: WMM + * + * Copyright (C) 2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#ifndef _MWIFIEX_WMM_H_ +#define _MWIFIEX_WMM_H_ + +enum ieee_types_wmm_aciaifsn_bitmasks { + MWIFIEX_AIFSN = (BIT(0) | BIT(1) | BIT(2) | BIT(3)), + MWIFIEX_ACM = BIT(4), + MWIFIEX_ACI = (BIT(5) | BIT(6)), +}; + +enum ieee_types_wmm_ecw_bitmasks { + MWIFIEX_ECW_MIN = (BIT(0) | BIT(1) | BIT(2) | BIT(3)), + MWIFIEX_ECW_MAX = (BIT(4) | BIT(5) | BIT(6) | BIT(7)), +}; + +/* + * This function retrieves the TID of the given RA list. + */ +static inline int +mwifiex_get_tid(struct mwifiex_adapter *adapter, + struct mwifiex_ra_list_tbl *ptr) +{ + struct sk_buff *skb; + + if (skb_queue_empty(&ptr->skb_head)) + return 0; + + skb = skb_peek(&ptr->skb_head); + + return skb->priority; +} + +/* + * This function gets the length of a list. + */ +static inline int +mwifiex_wmm_list_len(struct mwifiex_adapter *adapter, struct list_head *head) +{ + struct list_head *pos; + int count = 0; + + list_for_each(pos, head) + ++count; + + return count; +} + +/* + * This function checks if a RA list is empty or not. + */ +static inline u8 +mwifiex_wmm_is_ra_list_empty(struct mwifiex_adapter *adapter, + struct list_head *ra_list_hhead) +{ + struct mwifiex_ra_list_tbl *ra_list; + int is_list_empty; + + list_for_each_entry(ra_list, ra_list_hhead, list) { + is_list_empty = skb_queue_empty(&ra_list->skb_head); + if (!is_list_empty) + return false; + } + + return true; +} + +void mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, + struct sk_buff *skb); +void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra); + +int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter); +void mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter); +int mwifiex_is_ralist_valid(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ra_list, int tid); + +u8 mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, + const struct sk_buff *skb); +void mwifiex_wmm_init(struct mwifiex_adapter *adapter); + +extern u32 mwifiex_wmm_process_association_req(struct mwifiex_private *priv, + u8 **assoc_buf, + struct ieee_types_wmm_parameter + *wmmie, + struct ieee80211_ht_cap + *htcap); + +void mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, + struct ieee_types_wmm_parameter + *wmm_ie); +void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv); +extern int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, + const struct host_cmd_ds_command *resp); + +#endif /* !_MWIFIEX_WMM_H_ */ -- cgit v1.2.3-58-ga151 From f39de992540cf68cc865498242f963f70f7e97b3 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Wed, 16 Mar 2011 16:41:46 +0200 Subject: libertas_spi: Add support for suspend/resume Add support for suspend/resume in if_spi. Signed-off-by: Vasily Khoruzhick Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_spi.c | 65 ++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index f6c2cd665f49..078ef43d957d 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -57,6 +57,7 @@ struct if_spi_card { /* Handles all SPI communication (except for FW load) */ struct workqueue_struct *workqueue; struct work_struct packet_work; + struct work_struct resume_work; u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; @@ -68,6 +69,9 @@ struct if_spi_card { /* Protects cmd_packet_list and data_packet_list */ spinlock_t buffer_lock; + + /* True is card suspended */ + u8 suspended; }; static void free_if_spi_card(struct if_spi_card *card) @@ -1057,6 +1061,28 @@ out: return err; } +static void if_spi_resume_worker(struct work_struct *work) +{ + struct if_spi_card *card; + + card = container_of(work, struct if_spi_card, resume_work); + + if (card->suspended) { + if (card->pdata->setup) + card->pdata->setup(card->spi); + + /* Init card ... */ + if_spi_init_card(card); + + enable_irq(card->spi->irq); + + /* And resume it ... */ + lbs_resume(card->priv); + + card->suspended = 0; + } +} + static int __devinit if_spi_probe(struct spi_device *spi) { struct if_spi_card *card; @@ -1107,6 +1133,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) goto free_card; } card->priv = priv; + priv->setup_fw_on_resume = 1; priv->card = card; priv->hw_host_to_card = if_spi_host_to_card; priv->enter_deep_sleep = NULL; @@ -1117,6 +1144,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) /* Initialize interrupt handling stuff. */ card->workqueue = create_workqueue("libertas_spi"); INIT_WORK(&card->packet_work, if_spi_host_to_card_worker); + INIT_WORK(&card->resume_work, if_spi_resume_worker); err = request_irq(spi->irq, if_spi_host_interrupt, IRQF_TRIGGER_FALLING, "libertas_spi", card); @@ -1161,6 +1189,8 @@ static int __devexit libertas_spi_remove(struct spi_device *spi) lbs_deb_spi("libertas_spi_remove\n"); lbs_deb_enter(LBS_DEB_SPI); + cancel_work_sync(&card->resume_work); + lbs_stop_card(priv); lbs_remove_card(priv); /* will call free_netdev */ @@ -1174,6 +1204,40 @@ static int __devexit libertas_spi_remove(struct spi_device *spi) return 0; } +static int if_spi_suspend(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + struct if_spi_card *card = spi_get_drvdata(spi); + + if (!card->suspended) { + lbs_suspend(card->priv); + flush_workqueue(card->workqueue); + disable_irq(spi->irq); + + if (card->pdata->teardown) + card->pdata->teardown(spi); + card->suspended = 1; + } + + return 0; +} + +static int if_spi_resume(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + struct if_spi_card *card = spi_get_drvdata(spi); + + /* Schedule delayed work */ + schedule_work(&card->resume_work); + + return 0; +} + +static const struct dev_pm_ops if_spi_pm_ops = { + .suspend = if_spi_suspend, + .resume = if_spi_resume, +}; + static struct spi_driver libertas_spi_driver = { .probe = if_spi_probe, .remove = __devexit_p(libertas_spi_remove), @@ -1181,6 +1245,7 @@ static struct spi_driver libertas_spi_driver = { .name = "libertas_spi", .bus = &spi_bus_type, .owner = THIS_MODULE, + .pm = &if_spi_pm_ops, }, }; -- cgit v1.2.3-58-ga151 From dd347f2fb2ddb20a80e9a8285252bf208ab91398 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 22 Mar 2011 21:54:17 +0100 Subject: ath9k: fix beacon timer handling issues AP mode beacon timers in ath9k are configured in milliseconds, which breaks when increasing ATH_BCBUF to 8 instead of 4 (due to rounding errors). Since the hardware timers are actually configured in microseconds, it's better to let the driver use that unit directly. To be able to do that, the beacon interval parameter abuse for passing certain flags needs to be removed. This is easy to do, because those flags are completely unnecessary anyway. ATH9K_BEACON_ENA is ignored, ATH9K_BEACON_RESET_TSF can be replaced with calling ath9k_hw_reset_tsf from the driver directly. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 +- drivers/net/wireless/ath/ath9k/beacon.c | 78 ++++++++++--------------- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 9 +-- drivers/net/wireless/ath/ath9k/hw.c | 36 +++++------- drivers/net/wireless/ath/ath9k/hw.h | 3 +- 5 files changed, 49 insertions(+), 79 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 099bd4183ad0..07dfb31f1749 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -386,7 +386,7 @@ struct ath_beacon { u32 beaconq; u32 bmisscnt; u32 ast_be_xmit; - u64 bc_tstamp; + u32 bc_tstamp; struct ieee80211_vif *bslot[ATH_BCBUF]; int slottime; int slotupdate; diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 6d2a545fc35e..b5eab2f55824 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -57,8 +57,8 @@ int ath_beaconq_config(struct ath_softc *sc) /* * Associates the beacon frame buffer with a transmit descriptor. Will set - * up all required antenna switch parameters, rate codes, and channel flags. - * Beacons are always sent out at the lowest rate, and are not retried. + * up rate codes, and channel flags. Beacons are always sent out at the + * lowest rate, and are not retried. */ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, struct ath_buf *bf, int rateidx) @@ -68,7 +68,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, struct ath_common *common = ath9k_hw_common(ah); struct ath_desc *ds; struct ath9k_11n_rate_series series[4]; - int flags, antenna, ctsrate = 0, ctsduration = 0; + int flags, ctsrate = 0, ctsduration = 0; struct ieee80211_supported_band *sband; u8 rate = 0; @@ -76,12 +76,6 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, flags = ATH9K_TXDESC_NOACK; ds->ds_link = 0; - /* - * Switch antenna every beacon. - * Should only switch every beacon period, not for every SWBA - * XXX assumes two antennae - */ - antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); sband = &sc->sbands[common->hw->conf.channel->band]; rate = sband->bitrates[rateidx].hw_value; @@ -278,7 +272,7 @@ int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif) return -ENOMEM; tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - sc->beacon.bc_tstamp = le64_to_cpu(tstamp); + sc->beacon.bc_tstamp = (u32) le64_to_cpu(tstamp); /* Calculate a TSF adjustment factor required for staggered beacons. */ if (avp->av_bslot > 0) { u64 tsfadjust; @@ -294,8 +288,8 @@ int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif) * adjustment. Other slots are adjusted to get the timestamp * close to the TBTT for the BSS. */ - tsfadjust = intval * avp->av_bslot / ATH_BCBUF; - avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); + tsfadjust = TU_TO_USEC(intval * avp->av_bslot) / ATH_BCBUF; + avp->tsf_adjust = cpu_to_le64(tsfadjust); ath_dbg(common, ATH_DBG_BEACON, "stagger beacons, bslot %d intval %u tsfadjust %llu\n", @@ -401,8 +395,9 @@ void ath_beacon_tasklet(unsigned long data) intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; tsf = ath9k_hw_gettsf64(ah); - tsftu = TSF_TO_TU(tsf>>32, tsf); - slot = ((tsftu % intval) * ATH_BCBUF) / intval; + tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); + tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); + slot = (tsftu % (intval * ATH_BCBUF)) / intval; /* * Reverse the slot order to get slot 0 on the TBTT offset that does * not require TSF adjustment and other slots adding @@ -415,7 +410,7 @@ void ath_beacon_tasklet(unsigned long data) ath_dbg(common, ATH_DBG_BEACON, "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", - slot, tsf, tsftu, intval, vif); + slot, tsf, tsftu / ATH_BCBUF, intval, vif); bfaddr = 0; if (vif) { @@ -463,13 +458,17 @@ static void ath9k_beacon_init(struct ath_softc *sc, u32 next_beacon, u32 beacon_period) { - if (beacon_period & ATH9K_BEACON_RESET_TSF) + if (sc->sc_flags & SC_OP_TSF_RESET) { ath9k_ps_wakeup(sc); + ath9k_hw_reset_tsf(sc->sc_ah); + } ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); - if (beacon_period & ATH9K_BEACON_RESET_TSF) + if (sc->sc_flags & SC_OP_TSF_RESET) { ath9k_ps_restore(sc); + sc->sc_flags &= ~SC_OP_TSF_RESET; + } } /* @@ -484,18 +483,14 @@ static void ath_beacon_config_ap(struct ath_softc *sc, u32 nexttbtt, intval; /* NB: the beacon interval is kept internally in TU's */ - intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; + intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); intval /= ATH_BCBUF; /* for staggered beacons */ nexttbtt = intval; - if (sc->sc_flags & SC_OP_TSF_RESET) - intval |= ATH9K_BEACON_RESET_TSF; - /* * In AP mode we enable the beacon timers and SWBA interrupts to * prepare beacon frames. */ - intval |= ATH9K_BEACON_ENA; ah->imask |= ATH9K_INT_SWBA; ath_beaconq_config(sc); @@ -505,11 +500,6 @@ static void ath_beacon_config_ap(struct ath_softc *sc, ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; ath9k_hw_set_interrupts(ah, ah->imask); - - /* Clear the reset TSF flag, so that subsequent beacon updation - will not reset the HW TSF. */ - - sc->sc_flags &= ~SC_OP_TSF_RESET; } /* @@ -643,25 +633,20 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); - u64 tsf; - u32 tsftu, intval, nexttbtt; - - intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; - - - /* Pull nexttbtt forward to reflect the current TSF */ - - nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp); - if (nexttbtt == 0) - nexttbtt = intval; - else if (intval) - nexttbtt = roundup(nexttbtt, intval); - - tsf = ath9k_hw_gettsf64(ah); - tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; - do { - nexttbtt += intval; - } while (nexttbtt < tsftu); + u32 tsf, delta, intval, nexttbtt; + + tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE); + intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); + + if (!sc->beacon.bc_tstamp) + nexttbtt = tsf + intval; + else { + if (tsf > sc->beacon.bc_tstamp) + delta = (tsf - sc->beacon.bc_tstamp); + else + delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp)); + nexttbtt = tsf + roundup(delta, intval); + } ath_dbg(common, ATH_DBG_BEACON, "IBSS nexttbtt %u intval %u (%u)\n", @@ -672,7 +657,6 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, * if we need to manually prepare beacon frames. Otherwise we use a * self-linked tx descriptor and let the hardware deal with things. */ - intval |= ATH9K_BEACON_ENA; ah->imask |= ATH9K_INT_SWBA; ath_beaconq_config(sc); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 8d1d8792436d..8f56158e5887 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -155,7 +155,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, nexttbtt = intval; if (priv->op_flags & OP_TSF_RESET) { - intval |= ATH9K_BEACON_RESET_TSF; + ath9k_hw_reset_tsf(priv->ah); priv->op_flags &= ~OP_TSF_RESET; } else { /* @@ -168,8 +168,6 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, } while (nexttbtt < tsftu); } - intval |= ATH9K_BEACON_ENA; - if (priv->op_flags & OP_ENABLE_BEACON) imask |= ATH9K_INT_SWBA; @@ -178,7 +176,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, bss_conf->beacon_interval, nexttbtt, imask); WMI_CMD(WMI_DISABLE_INTR_CMDID); - ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); + ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); priv->bmiss_cnt = 0; htc_imask = cpu_to_be32(imask); WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); @@ -207,7 +205,6 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, nexttbtt += intval; } while (nexttbtt < tsftu); - intval |= ATH9K_BEACON_ENA; if (priv->op_flags & OP_ENABLE_BEACON) imask |= ATH9K_INT_SWBA; @@ -216,7 +213,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, bss_conf->beacon_interval, nexttbtt, imask); WMI_CMD(WMI_DISABLE_INTR_CMDID); - ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); + ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); priv->bmiss_cnt = 0; htc_imask = cpu_to_be32(imask); WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8b8656898dfe..9513ec745b93 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1697,21 +1697,15 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) case NL80211_IFTYPE_MESH_POINT: REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); - REG_WRITE(ah, AR_NEXT_NDP_TIMER, - TU_TO_USEC(next_beacon + - (ah->atim_window ? ah-> - atim_window : 1))); + REG_WRITE(ah, AR_NEXT_NDP_TIMER, next_beacon + + TU_TO_USEC(ah->atim_window ? ah->atim_window : 1)); flags |= AR_NDP_TIMER_EN; case NL80211_IFTYPE_AP: - REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); - REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, - TU_TO_USEC(next_beacon - - ah->config. - dma_beacon_response_time)); - REG_WRITE(ah, AR_NEXT_SWBA, - TU_TO_USEC(next_beacon - - ah->config. - sw_beacon_response_time)); + REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon); + REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, next_beacon - + TU_TO_USEC(ah->config.dma_beacon_response_time)); + REG_WRITE(ah, AR_NEXT_SWBA, next_beacon - + TU_TO_USEC(ah->config.sw_beacon_response_time)); flags |= AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; break; @@ -1723,18 +1717,13 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) break; } - REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period)); - REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period)); - REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period)); - REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); + REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period); + REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period); + REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period); + REG_WRITE(ah, AR_NDP_PERIOD, beacon_period); REGWRITE_BUFFER_FLUSH(ah); - beacon_period &= ~ATH9K_BEACON_ENA; - if (beacon_period & ATH9K_BEACON_RESET_TSF) { - ath9k_hw_reset_tsf(ah); - } - REG_SET_BIT(ah, AR_TIMER_MODE, flags); } EXPORT_SYMBOL(ath9k_hw_beaconinit); @@ -2395,10 +2384,11 @@ static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask) return timer_table->gen_timer_index[b]; } -static u32 ath9k_hw_gettsf32(struct ath_hw *ah) +u32 ath9k_hw_gettsf32(struct ath_hw *ah) { return REG_READ(ah, AR_TSF_L32); } +EXPORT_SYMBOL(ath9k_hw_gettsf32); struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, void (*trigger)(void *), diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 3d9fc6e391a7..c819973c7c84 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -416,8 +416,6 @@ struct ath9k_beacon_state { u32 bs_nextdtim; u32 bs_intval; #define ATH9K_BEACON_PERIOD 0x0000ffff -#define ATH9K_BEACON_ENA 0x00800000 -#define ATH9K_BEACON_RESET_TSF 0x01000000 #define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */ u32 bs_dtimperiod; u16 bs_cfpperiod; @@ -930,6 +928,7 @@ void ath9k_hw_setopmode(struct ath_hw *ah); void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); void ath9k_hw_setbssidmask(struct ath_hw *ah); void ath9k_hw_write_associd(struct ath_hw *ah); +u32 ath9k_hw_gettsf32(struct ath_hw *ah); u64 ath9k_hw_gettsf64(struct ath_hw *ah); void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); void ath9k_hw_reset_tsf(struct ath_hw *ah); -- cgit v1.2.3-58-ga151 From 87c510fe2d4f193cd4eb518364a2dfa5059b1218 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 22 Mar 2011 21:54:18 +0100 Subject: ath9k: trigger nfcal only after multiple missed beacons in AP mode Single missed (i.e. not transmitted) beacons in AP mode are not very rare and not necessarily an indicator of strong interference, so only trigger noise floor recalibration when multiple consecutive beacons could not be transmitted. Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index b5eab2f55824..6ebeafe3a92f 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -368,7 +368,8 @@ void ath_beacon_tasklet(unsigned long data) "missed %u consecutive beacons\n", sc->beacon.bmisscnt); ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq); - ath9k_hw_bstuck_nfcal(ah); + if (sc->beacon.bmisscnt > 3) + ath9k_hw_bstuck_nfcal(ah); } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { ath_dbg(common, ATH_DBG_BSTUCK, "beacon is officially stuck\n"); -- cgit v1.2.3-58-ga151 From c944daf46a8cfa50d6c1f54d4842180d0384c594 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 22 Mar 2011 21:54:19 +0100 Subject: ath9k: fix stuck beacon detection Stuck beacon detection is supposed to trigger when 9 consecutive beacons could not be sent by the hardware. When the driver runs only one active AP mode interface, it still configures the hardware beacon timer for 4 (ATH_BCBUF) beacon slots slots, which causes stuck beacon detection to be reset if ath9k_hw_stoptxdma clears the stuck frames between SWBA intervals. Fix this by not resetting the missed beacon count for empty slots and multiplying the threshold not by the maximum number of beacon slots but by the configured number of beacon interfaces. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 +- drivers/net/wireless/ath/ath9k/beacon.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 07dfb31f1749..7c91ba4dce41 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -362,7 +362,7 @@ struct ath_vif { * number of BSSIDs) if a given beacon does not go out even after waiting this * number of beacon intervals, the game's up. */ -#define BSTUCK_THRESH (9 * ATH_BCBUF) +#define BSTUCK_THRESH 9 #define ATH_BCBUF 4 #define ATH_DEFAULT_BINTVAL 100 /* TU */ #define ATH_DEFAULT_BMISS_LIMIT 10 diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 6ebeafe3a92f..74f33bc193fe 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -363,7 +363,7 @@ void ath_beacon_tasklet(unsigned long data) if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { sc->beacon.bmisscnt++; - if (sc->beacon.bmisscnt < BSTUCK_THRESH) { + if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) { ath_dbg(common, ATH_DBG_BSTUCK, "missed %u consecutive beacons\n", sc->beacon.bmisscnt); @@ -380,13 +380,6 @@ void ath_beacon_tasklet(unsigned long data) return; } - if (sc->beacon.bmisscnt != 0) { - ath_dbg(common, ATH_DBG_BSTUCK, - "resume beacon xmit after %u misses\n", - sc->beacon.bmisscnt); - sc->beacon.bmisscnt = 0; - } - /* * Generate beacon frames. we are sending frames * staggered so calculate the slot for this frame based @@ -420,6 +413,13 @@ void ath_beacon_tasklet(unsigned long data) bfaddr = bf->bf_daddr; bc = 1; } + + if (sc->beacon.bmisscnt != 0) { + ath_dbg(common, ATH_DBG_BSTUCK, + "resume beacon xmit after %u misses\n", + sc->beacon.bmisscnt); + sc->beacon.bmisscnt = 0; + } } /* -- cgit v1.2.3-58-ga151 From cfdc9a8bb8d90c6aa212a5a881862599673c443d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 23 Mar 2011 14:52:19 +0200 Subject: ath9k: Support RSN IBSS Add support for using RSN IBSS with ath9k. For now, this uses software crypto for group addressed frames in RSN IBSS, but that may be optimized in the future by extending the key cache design to support per-STA RX GTK. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 2 ++ drivers/net/wireless/ath/ath9k/main.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index cdb0f1c89a0e..b590a9e7943a 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -690,6 +690,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) if (AR_SREV_5416(sc->sc_ah)) hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; + hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + hw->queues = 4; hw->max_rates = 4; hw->channel_change_time = 5000; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 524825720a09..3c5de73dcb4b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1845,6 +1845,20 @@ static int ath9k_set_key(struct ieee80211_hw *hw, if (ath9k_modparam_nohwcrypt) return -ENOSPC; + if (vif->type == NL80211_IFTYPE_ADHOC && + (key->cipher == WLAN_CIPHER_SUITE_TKIP || + key->cipher == WLAN_CIPHER_SUITE_CCMP) && + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { + /* + * For now, disable hw crypto for the RSN IBSS group keys. This + * could be optimized in the future to use a modified key cache + * design to support per-STA RX GTK, but until that gets + * implemented, use of software crypto for group addressed + * frames is a acceptable to allow RSN IBSS to be used. + */ + return -EOPNOTSUPP; + } + mutex_lock(&sc->mutex); ath9k_ps_wakeup(sc); ath_dbg(common, ATH_DBG_CONFIG, "Set HW Key\n"); -- cgit v1.2.3-58-ga151 From ec15e68ba6a505631016f230899bafbb7b8cd0d6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 23 Mar 2011 15:29:52 +0200 Subject: cfg80211: Add nl80211 event for deletion of a station entry Indicate an NL80211_CMD_DEL_STATION event when a station entry in mac80211 is deleted to match with the NL80211_CMD_NEW_STATION event that is used when the entry was added. This is needed, e.g., to allow user space to remove a peer from RSN IBSS Authenticator state machine to avoid re-authentication and re-keying delays when the peer is not reachable anymore. Signed-off-by: Jouni Malinen Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 9 +++++++++ net/mac80211/sta_info.c | 2 ++ net/wireless/mlme.c | 9 +++++++++ net/wireless/nl80211.c | 34 ++++++++++++++++++++++++++++++++++ net/wireless/nl80211.h | 3 +++ 5 files changed, 57 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index b2b9d28cb4ab..2c4530451721 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2666,6 +2666,15 @@ void cfg80211_remain_on_channel_expired(struct net_device *dev, void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, struct station_info *sinfo, gfp_t gfp); +/** + * cfg80211_del_sta - notify userspace about deletion of a station + * + * @dev: the netdev + * @mac_addr: the station's address + * @gfp: allocation flags + */ +void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp); + /** * cfg80211_rx_mgmt - notification of received, unprocessed management frame * @dev: network device diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d0311a322ddd..5ec0a7c51b6d 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -698,6 +698,8 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ cancel_work_sync(&sta->drv_unblock_wk); + cfg80211_del_sta(sdata->dev, sta->sta.addr, GFP_KERNEL); + rate_control_remove_sta_debugfs(sta); ieee80211_sta_debugfs_remove(sta); diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index aa5df8865ff7..16881fea4ce6 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -770,6 +770,15 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, } EXPORT_SYMBOL(cfg80211_new_sta); +void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp); +} +EXPORT_SYMBOL(cfg80211_del_sta); + struct cfg80211_mgmt_registration { struct list_head list; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4ebce4284e9d..40c90fb461c4 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5966,6 +5966,40 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, nl80211_mlme_mcgrp.id, gfp); } +void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *mac_addr, + gfp_t gfp) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_GOODSIZE, gfp); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_STATION); + if (!hdr) { + nlmsg_free(msg); + return; + } + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, + nl80211_mlme_mcgrp.id, gfp); + return; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, struct net_device *netdev, u32 nlpid, int freq, const u8 *buf, size_t len, gfp_t gfp) diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index e3f7fa886966..dcac5cd6f017 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -79,6 +79,9 @@ void nl80211_send_remain_on_channel_cancel( void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *mac_addr, struct station_info *sinfo, gfp_t gfp); +void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *mac_addr, + gfp_t gfp); int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, struct net_device *netdev, u32 nlpid, int freq, -- cgit v1.2.3-58-ga151 From f9f84e96f6d642aa7b337c22cbb7d6f936039fda Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 23 Mar 2011 20:57:24 +0100 Subject: ath9k_hw: embed the ath_ops callbacks in the ath_hw struct With this change, loading the address to a register read/write function costs only one pointer dereference instead of two. On MIPS this reduces ath9k_hw binary size from 326k down to 321k. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 15 ++++++--------- drivers/net/wireless/ath/ath9k/hw.h | 16 +++++++++------- drivers/net/wireless/ath/ath9k/init.c | 9 +++------ 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index fc67c937e172..4e26946f7ab2 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -430,14 +430,6 @@ static void ath9k_regwrite_flush(void *hw_priv) mutex_unlock(&priv->wmi->multi_write_mutex); } -static const struct ath_ops ath9k_common_ops = { - .read = ath9k_regread, - .multi_read = ath9k_multi_regread, - .write = ath9k_regwrite, - .enable_write_buffer = ath9k_enable_regwrite_buffer, - .write_flush = ath9k_regwrite_flush, -}; - static void ath_usb_read_cachesize(struct ath_common *common, int *csz) { *csz = L1_CACHE_BYTES >> 2; @@ -658,10 +650,15 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, ah->hw_version.subsysid = 0; /* FIXME */ ah->hw_version.usbdev = drv_info; ah->ah_flags |= AH_USE_EEPROM; + ah->reg_ops.read = ath9k_regread; + ah->reg_ops.multi_read = ath9k_multi_regread; + ah->reg_ops.write = ath9k_regwrite; + ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer; + ah->reg_ops.write_flush = ath9k_regwrite_flush; priv->ah = ah; common = ath9k_hw_common(ah); - common->ops = &ath9k_common_ops; + common->ops = &ah->reg_ops; common->bus_ops = &ath9k_usb_bus_ops; common->ah = ah; common->hw = priv->hw; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index c819973c7c84..ef387a2f54b2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -65,24 +65,24 @@ /* Register read/write primitives */ #define REG_WRITE(_ah, _reg, _val) \ - ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg)) + (_ah)->reg_ops.write((_ah), (_val), (_reg)) #define REG_READ(_ah, _reg) \ - ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) + (_ah)->reg_ops.read((_ah), (_reg)) #define REG_READ_MULTI(_ah, _addr, _val, _cnt) \ - ath9k_hw_common(_ah)->ops->multi_read((_ah), (_addr), (_val), (_cnt)) + (_ah)->reg_ops.multi_read((_ah), (_addr), (_val), (_cnt)) #define ENABLE_REGWRITE_BUFFER(_ah) \ do { \ - if (ath9k_hw_common(_ah)->ops->enable_write_buffer) \ - ath9k_hw_common(_ah)->ops->enable_write_buffer((_ah)); \ + if ((_ah)->reg_ops.enable_write_buffer) \ + (_ah)->reg_ops.enable_write_buffer((_ah)); \ } while (0) #define REGWRITE_BUFFER_FLUSH(_ah) \ do { \ - if (ath9k_hw_common(_ah)->ops->write_flush) \ - ath9k_hw_common(_ah)->ops->write_flush((_ah)); \ + if ((_ah)->reg_ops.write_flush) \ + (_ah)->reg_ops.write_flush((_ah)); \ } while (0) #define SM(_v, _f) (((_v) << _f##_S) & _f) @@ -657,6 +657,8 @@ struct ath_nf_limits { #define AH_UNPLUGGED 0x2 /* The card has been physically removed. */ struct ath_hw { + struct ath_ops reg_ops; + struct ieee80211_hw *hw; struct ath_common common; struct ath9k_hw_version hw_version; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index b590a9e7943a..da114c2f0dbe 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -196,11 +196,6 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) return val; } -static const struct ath_ops ath9k_common_ops = { - .read = ath9k_ioread32, - .write = ath9k_iowrite32, -}; - /**************************/ /* Initialization */ /**************************/ @@ -551,6 +546,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, ah->hw = sc->hw; ah->hw_version.devid = devid; ah->hw_version.subsysid = subsysid; + ah->reg_ops.read = ath9k_ioread32; + ah->reg_ops.write = ath9k_iowrite32; sc->sc_ah = ah; if (!pdata) { @@ -563,7 +560,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, } common = ath9k_hw_common(ah); - common->ops = &ath9k_common_ops; + common->ops = &ah->reg_ops; common->bus_ops = bus_ops; common->ah = ah; common->hw = sc->hw; -- cgit v1.2.3-58-ga151 From 845e03c93dda2c00ffb5c68a1f7c8efc412d7c1a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 23 Mar 2011 20:57:25 +0100 Subject: ath9k_hw: add a new register op for read-mask-write Reduces the number of calls to register ops. On MIPS this reduces the ath9k_hw binary size from 321k down to 310k Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_init.c | 12 ++++++++++++ drivers/net/wireless/ath/ath9k/hw.h | 12 ++++++------ drivers/net/wireless/ath/ath9k/init.c | 23 +++++++++++++++++++++++ 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index a6c6a466000f..6d7105b7e8f1 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -119,6 +119,7 @@ struct ath_ops { void (*write)(void *, u32 val, u32 reg_offset); void (*enable_write_buffer)(void *); void (*write_flush) (void *); + u32 (*rmw)(void *, u32 reg_offset, u32 set, u32 clr); }; struct ath_common; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 4e26946f7ab2..ca69e7ccfd80 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -430,6 +430,17 @@ static void ath9k_regwrite_flush(void *hw_priv) mutex_unlock(&priv->wmi->multi_write_mutex); } +static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) +{ + u32 val; + + val = ath9k_regread(hw_priv, reg_offset); + val &= ~clr; + val |= set; + ath9k_regwrite(hw_priv, val, reg_offset); + return val; +} + static void ath_usb_read_cachesize(struct ath_common *common, int *csz) { *csz = L1_CACHE_BYTES >> 2; @@ -655,6 +666,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, ah->reg_ops.write = ath9k_regwrite; ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer; ah->reg_ops.write_flush = ath9k_regwrite_flush; + ah->reg_ops.rmw = ath9k_reg_rmw; priv->ah = ah; common = ath9k_hw_common(ah); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ef387a2f54b2..e256658c740a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -73,6 +73,9 @@ #define REG_READ_MULTI(_ah, _addr, _val, _cnt) \ (_ah)->reg_ops.multi_read((_ah), (_addr), (_val), (_cnt)) +#define REG_RMW(_ah, _reg, _set, _clr) \ + (_ah)->reg_ops.rmw((_ah), (_reg), (_set), (_clr)) + #define ENABLE_REGWRITE_BUFFER(_ah) \ do { \ if ((_ah)->reg_ops.enable_write_buffer) \ @@ -87,17 +90,14 @@ #define SM(_v, _f) (((_v) << _f##_S) & _f) #define MS(_v, _f) (((_v) & _f) >> _f##_S) -#define REG_RMW(_a, _r, _set, _clr) \ - REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set)) #define REG_RMW_FIELD(_a, _r, _f, _v) \ - REG_WRITE(_a, _r, \ - (REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f)) + REG_RMW(_a, _r, (((_v) << _f##_S) & _f), (_f)) #define REG_READ_FIELD(_a, _r, _f) \ (((REG_READ(_a, _r) & _f) >> _f##_S)) #define REG_SET_BIT(_a, _r, _f) \ - REG_WRITE(_a, _r, REG_READ(_a, _r) | (_f)) + REG_RMW(_a, _r, (_f), 0) #define REG_CLR_BIT(_a, _r, _f) \ - REG_WRITE(_a, _r, REG_READ(_a, _r) & ~(_f)) + REG_RMW(_a, _r, 0, (_f)) #define DO_DELAY(x) do { \ if (((++(x) % 64) == 0) && \ diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index da114c2f0dbe..db1b7553c684 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -196,6 +196,28 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) return val; } +static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) +{ + struct ath_hw *ah = (struct ath_hw *) hw_priv; + struct ath_common *common = ath9k_hw_common(ah); + struct ath_softc *sc = (struct ath_softc *) common->priv; + unsigned long uninitialized_var(flags); + u32 val; + + if (ah->config.serialize_regmode == SER_REG_MODE_ON) + spin_lock_irqsave(&sc->sc_serial_rw, flags); + + val = ioread32(sc->mem + reg_offset); + val &= ~clr; + val |= set; + iowrite32(val, sc->mem + reg_offset); + + if (ah->config.serialize_regmode == SER_REG_MODE_ON) + spin_unlock_irqrestore(&sc->sc_serial_rw, flags); + + return val; +} + /**************************/ /* Initialization */ /**************************/ @@ -548,6 +570,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, ah->hw_version.subsysid = subsysid; ah->reg_ops.read = ath9k_ioread32; ah->reg_ops.write = ath9k_iowrite32; + ah->reg_ops.rmw = ath9k_reg_rmw; sc->sc_ah = ah; if (!pdata) { -- cgit v1.2.3-58-ga151 From ca7a4deb4a1a87dbdc6e7cab0d1022a535204226 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 23 Mar 2011 20:57:26 +0100 Subject: ath9k_hw: replace REG_READ+REG_WRITE with REG_RMW It's easier to read and it slightly decreases code size Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 66 +++++++++++++------------------- drivers/net/wireless/ath/ath9k/mac.c | 73 +++++++++++++++--------------------- 2 files changed, 56 insertions(+), 83 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 9513ec745b93..807d410e7645 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -675,14 +675,14 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) { - REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) & ~(PLL3_DO_MEAS_MASK))); - udelay(100); - REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) | PLL3_DO_MEAS_MASK)); + REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); + udelay(100); + REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); - while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) - udelay(100); + while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) + udelay(100); - return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; + return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; } EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); @@ -832,8 +832,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) ah->misc_mode); if (ah->misc_mode != 0) - REG_WRITE(ah, AR_PCU_MISC, - REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); + REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode); if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ) sifstime = 16; @@ -901,23 +900,19 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan) static inline void ath9k_hw_set_dma(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - u32 regval; ENABLE_REGWRITE_BUFFER(ah); /* * set AHB_MODE not to do cacheline prefetches */ - if (!AR_SREV_9300_20_OR_LATER(ah)) { - regval = REG_READ(ah, AR_AHB_MODE); - REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); - } + if (!AR_SREV_9300_20_OR_LATER(ah)) + REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN); /* * let mac dma reads be in 128 byte chunks */ - regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; - REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); + REG_RMW(ah, AR_TXCFG, AR_TXCFG_DMASZ_128B, AR_TXCFG_DMASZ_MASK); REGWRITE_BUFFER_FLUSH(ah); @@ -934,8 +929,7 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) /* * let mac dma writes be in 128 byte chunks */ - regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK; - REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B); + REG_RMW(ah, AR_RXCFG, AR_RXCFG_DMASZ_128B, AR_RXCFG_DMASZ_MASK); /* * Setup receive FIFO threshold to hold off TX activities @@ -974,30 +968,27 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) { - u32 val; + u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC; + u32 set = AR_STA_ID1_KSRCH_MODE; - val = REG_READ(ah, AR_STA_ID1); - val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC); switch (opmode) { - case NL80211_IFTYPE_AP: - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP - | AR_STA_ID1_KSRCH_MODE); - REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); - break; case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC - | AR_STA_ID1_KSRCH_MODE); + set |= AR_STA_ID1_ADHOC; REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); break; + case NL80211_IFTYPE_AP: + set |= AR_STA_ID1_STA_AP; + /* fall through */ case NL80211_IFTYPE_STATION: - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); + REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); break; default: - if (ah->is_monitoring) - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); + if (!ah->is_monitoring) + set = 0; break; } + REG_RMW(ah, AR_STA_ID1, set, mask); } void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, @@ -1023,10 +1014,8 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) u32 tmpReg; if (AR_SREV_9100(ah)) { - u32 val = REG_READ(ah, AR_RTC_DERIVED_CLK); - val &= ~AR_RTC_DERIVED_CLK_PERIOD; - val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD); - REG_WRITE(ah, AR_RTC_DERIVED_CLK, val); + REG_RMW_FIELD(ah, AR_RTC_DERIVED_CLK, + AR_RTC_DERIVED_CLK_PERIOD, 1); (void)REG_READ(ah, AR_RTC_DERIVED_CLK); } @@ -1451,8 +1440,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ar9002_hw_enable_wep_aggregation(ah); } - REG_WRITE(ah, AR_STA_ID1, - REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); + REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); ath9k_hw_set_dma(ah); @@ -2204,11 +2192,9 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) REG_WRITE(ah, AR_PHY_ERR, phybits); if (phybits) - REG_WRITE(ah, AR_RXCFG, - REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); + REG_SET_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA); else - REG_WRITE(ah, AR_RXCFG, - REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); + REG_CLR_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA); REGWRITE_BUFFER_FLUSH(ah); } diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 562257ac52cf..db496f2e1f6b 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -465,10 +465,9 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) REG_WRITE(ah, AR_QCBRCFG(q), SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH)); - REG_WRITE(ah, AR_QMISC(q), - REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR | - (qi->tqi_cbrOverflowLimit ? - AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0)); + REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_FSP_CBR | + (qi->tqi_cbrOverflowLimit ? + AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0)); } if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) { REG_WRITE(ah, AR_QRDYTIMECFG(q), @@ -481,40 +480,31 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); if (qi->tqi_burstTime - && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) { - REG_WRITE(ah, AR_QMISC(q), - REG_READ(ah, AR_QMISC(q)) | - AR_Q_MISC_RDYTIME_EXP_POLICY); + && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) + REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_RDYTIME_EXP_POLICY); - } - - if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) { - REG_WRITE(ah, AR_DMISC(q), - REG_READ(ah, AR_DMISC(q)) | - AR_D_MISC_POST_FR_BKOFF_DIS); - } + if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) + REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS); REGWRITE_BUFFER_FLUSH(ah); - if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { - REG_WRITE(ah, AR_DMISC(q), - REG_READ(ah, AR_DMISC(q)) | - AR_D_MISC_FRAG_BKOFF_EN); - } + if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) + REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_FRAG_BKOFF_EN); + switch (qi->tqi_type) { case ATH9K_TX_QUEUE_BEACON: ENABLE_REGWRITE_BUFFER(ah); - REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) - | AR_Q_MISC_FSP_DBA_GATED - | AR_Q_MISC_BEACON_USE - | AR_Q_MISC_CBR_INCR_DIS1); + REG_SET_BIT(ah, AR_QMISC(q), + AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_BEACON_USE + | AR_Q_MISC_CBR_INCR_DIS1); - REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) - | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << + REG_SET_BIT(ah, AR_DMISC(q), + (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S) - | AR_D_MISC_BEACON_USE - | AR_D_MISC_POST_FR_BKOFF_DIS); + | AR_D_MISC_BEACON_USE + | AR_D_MISC_POST_FR_BKOFF_DIS); REGWRITE_BUFFER_FLUSH(ah); @@ -533,41 +523,38 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) case ATH9K_TX_QUEUE_CAB: ENABLE_REGWRITE_BUFFER(ah); - REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) - | AR_Q_MISC_FSP_DBA_GATED - | AR_Q_MISC_CBR_INCR_DIS1 - | AR_Q_MISC_CBR_INCR_DIS0); + REG_SET_BIT(ah, AR_QMISC(q), + AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_CBR_INCR_DIS1 + | AR_Q_MISC_CBR_INCR_DIS0); value = (qi->tqi_readyTime - (ah->config.sw_beacon_response_time - ah->config.dma_beacon_response_time) - ah->config.additional_swba_backoff) * 1024; REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_EN); - REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) - | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << + REG_SET_BIT(ah, AR_DMISC(q), + (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); REGWRITE_BUFFER_FLUSH(ah); break; case ATH9K_TX_QUEUE_PSPOLL: - REG_WRITE(ah, AR_QMISC(q), - REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1); + REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_CBR_INCR_DIS1); break; case ATH9K_TX_QUEUE_UAPSD: - REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | - AR_D_MISC_POST_FR_BKOFF_DIS); + REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS); break; default: break; } if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) { - REG_WRITE(ah, AR_DMISC(q), - REG_READ(ah, AR_DMISC(q)) | - SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, - AR_D_MISC_ARB_LOCKOUT_CNTRL) | - AR_D_MISC_POST_FR_BKOFF_DIS); + REG_SET_BIT(ah, AR_DMISC(q), + SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL) | + AR_D_MISC_POST_FR_BKOFF_DIS); } if (AR_SREV_9300_20_OR_LATER(ah)) -- cgit v1.2.3-58-ga151 From a9b6b2569cf107fe541381e82faa0a3c47a9a7fd Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 23 Mar 2011 20:57:27 +0100 Subject: ath9k_hw: turn a few big macros into functions RF_BANK_SETUP, REG_WRITE_RF_ARRAY and REG_WRITE_ARRAY are way too big, so they shouldn't be inlined at every single callsite, especially since they can easily be turned into real functions. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar5008_phy.c | 38 +++++++++++++++++++++++++---- drivers/net/wireless/ath/ath9k/hw.c | 14 +++++++++++ drivers/net/wireless/ath/ath9k/hw.h | 14 +++-------- drivers/net/wireless/ath/ath9k/phy.h | 16 ------------ 4 files changed, 51 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 94acce59f51d..4361704fe0d0 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -44,6 +44,34 @@ static const int m1ThreshExt_off = 127; static const int m2ThreshExt_off = 127; +static void ar5008_rf_bank_setup(u32 *bank, struct ar5416IniArray *array, + int col) +{ + int i; + + for (i = 0; i < array->ia_rows; i++) + bank[i] = INI_RA(array, i, col); +} + + +#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) \ + ar5008_write_rf_array(ah, iniarray, regData, &(regWr)) + +static void ar5008_write_rf_array(struct ath_hw *ah, struct ar5416IniArray *array, + u32 *data, unsigned int *writecnt) +{ + int r; + + ENABLE_REGWRITE_BUFFER(ah); + + for (r = 0; r < array->ia_rows; r++) { + REG_WRITE(ah, INI_RA(array, r, 0), data[r]); + DO_DELAY(*writecnt); + } + + REGWRITE_BUFFER_FLUSH(ah); +} + /** * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters * @rfbuf: @@ -530,16 +558,16 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah, eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); /* Setup Bank 0 Write */ - RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); + ar5008_rf_bank_setup(ah->analogBank0Data, &ah->iniBank0, 1); /* Setup Bank 1 Write */ - RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); + ar5008_rf_bank_setup(ah->analogBank1Data, &ah->iniBank1, 1); /* Setup Bank 2 Write */ - RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); + ar5008_rf_bank_setup(ah->analogBank2Data, &ah->iniBank2, 1); /* Setup Bank 6 Write */ - RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, + ar5008_rf_bank_setup(ah->analogBank3Data, &ah->iniBank3, modesIndex); { int i; @@ -569,7 +597,7 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah, } /* Setup Bank 7 Setup */ - RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); + ar5008_rf_bank_setup(ah->analogBank7Data, &ah->iniBank7, 1); /* Write Analog registers */ REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 807d410e7645..bb9a3f3c1b71 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -130,6 +130,20 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) } EXPORT_SYMBOL(ath9k_hw_wait); +void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array, + int column, unsigned int *writecnt) +{ + int r; + + ENABLE_REGWRITE_BUFFER(ah); + for (r = 0; r < array->ia_rows; r++) { + REG_WRITE(ah, INI_RA(array, r, 0), + INI_RA(array, r, column)); + DO_DELAY(*writecnt); + } + REGWRITE_BUFFER_FLUSH(ah); +} + u32 ath9k_hw_reverse_bits(u32 val, u32 n) { u32 retval; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e256658c740a..dafbe97a969c 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -106,16 +106,8 @@ udelay(1); \ } while (0) -#define REG_WRITE_ARRAY(iniarray, column, regWr) do { \ - int r; \ - ENABLE_REGWRITE_BUFFER(ah); \ - for (r = 0; r < ((iniarray)->ia_rows); r++) { \ - REG_WRITE(ah, INI_RA((iniarray), (r), 0), \ - INI_RA((iniarray), r, (column))); \ - DO_DELAY(regWr); \ - } \ - REGWRITE_BUFFER_FLUSH(ah); \ - } while (0) +#define REG_WRITE_ARRAY(iniarray, column, regWr) \ + ath9k_hw_write_array(ah, iniarray, column, &(regWr)) #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 @@ -913,6 +905,8 @@ void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, /* General Operation */ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); +void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array, + int column, unsigned int *writecnt); u32 ath9k_hw_reverse_bits(u32 val, u32 n); bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); u16 ath9k_hw_computetxtime(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index e4029325c787..f50e2c29f71e 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -38,27 +38,11 @@ #define AR_PHY_CLC_Q0 0x0000ffd0 #define AR_PHY_CLC_Q0_S 5 -#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do { \ - int r; \ - ENABLE_REGWRITE_BUFFER(ah); \ - for (r = 0; r < ((iniarray)->ia_rows); r++) { \ - REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \ - DO_DELAY(regWr); \ - } \ - REGWRITE_BUFFER_FLUSH(ah); \ - } while (0) - #define ANTSWAP_AB 0x0001 #define REDUCE_CHAIN_0 0x00000050 #define REDUCE_CHAIN_1 0x00000051 #define AR_PHY_CHIP_ID 0x9818 -#define RF_BANK_SETUP(_bank, _iniarray, _col) do { \ - int i; \ - for (i = 0; i < (_iniarray)->ia_rows; i++) \ - (_bank)[i] = INI_RA((_iniarray), i, _col);; \ - } while (0) - #define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 #define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 -- cgit v1.2.3-58-ga151 From f4c607dc53ece4ac15afed163292425efa060775 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 23 Mar 2011 20:57:28 +0100 Subject: ath9k_hw: remove pCap->total_queues The EEPROM contains a field that can restrict the number of hardware queues, however this is not only useless (all the known chips contain the same number of hardware queues), but also potentially dangerous in case of a misprogrammed EEPROM (could trigger driver crashes), so let's just ignore it completely. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 8 +------- drivers/net/wireless/ath/ath9k/hw.h | 1 - drivers/net/wireless/ath/ath9k/mac.c | 38 +++++------------------------------- 3 files changed, 6 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index bb9a3f3c1b71..de0d218195da 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1437,7 +1437,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REGWRITE_BUFFER_FLUSH(ah); ah->intr_txqs = 0; - for (i = 0; i < ah->caps.total_queues; i++) + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) ath9k_hw_resettxqueue(ah, i); ath9k_hw_init_interrupt_masks(ah, ah->opmode); @@ -1885,12 +1885,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) else pCap->hw_caps &= ~ATH9K_HW_CAP_HT; - if (capField & AR_EEPROM_EEPCAP_MAXQCU) - pCap->total_queues = - MS(capField, AR_EEPROM_EEPCAP_MAXQCU); - else - pCap->total_queues = ATH9K_NUM_TX_QUEUES; - if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES) pCap->keycache_size = 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index dafbe97a969c..4e62ad858d8a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -191,7 +191,6 @@ enum ath9k_hw_caps { struct ath9k_hw_capabilities { u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ - u16 total_queues; u16 keycache_size; u16 low_5ghz_chan, high_5ghz_chan; u16 low_2ghz_chan, high_2ghz_chan; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index db496f2e1f6b..05efcfbeeadc 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -209,15 +209,8 @@ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, { u32 cw; struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath9k_tx_queue_info *qi; - if (q >= pCap->total_queues) { - ath_dbg(common, ATH_DBG_QUEUE, - "Set TXQ properties, invalid queue: %u\n", q); - return false; - } - qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { ath_dbg(common, ATH_DBG_QUEUE, @@ -280,15 +273,8 @@ bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, struct ath9k_tx_queue_info *qinfo) { struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath9k_tx_queue_info *qi; - if (q >= pCap->total_queues) { - ath_dbg(common, ATH_DBG_QUEUE, - "Get TXQ properties, invalid queue: %u\n", q); - return false; - } - qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { ath_dbg(common, ATH_DBG_QUEUE, @@ -320,28 +306,27 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, { struct ath_common *common = ath9k_hw_common(ah); struct ath9k_tx_queue_info *qi; - struct ath9k_hw_capabilities *pCap = &ah->caps; int q; switch (type) { case ATH9K_TX_QUEUE_BEACON: - q = pCap->total_queues - 1; + q = ATH9K_NUM_TX_QUEUES - 1; break; case ATH9K_TX_QUEUE_CAB: - q = pCap->total_queues - 2; + q = ATH9K_NUM_TX_QUEUES - 2; break; case ATH9K_TX_QUEUE_PSPOLL: q = 1; break; case ATH9K_TX_QUEUE_UAPSD: - q = pCap->total_queues - 3; + q = ATH9K_NUM_TX_QUEUES - 3; break; case ATH9K_TX_QUEUE_DATA: - for (q = 0; q < pCap->total_queues; q++) + for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++) if (ah->txq[q].tqi_type == ATH9K_TX_QUEUE_INACTIVE) break; - if (q == pCap->total_queues) { + if (q == ATH9K_NUM_TX_QUEUES) { ath_err(common, "No available TX queue\n"); return -1; } @@ -382,15 +367,9 @@ EXPORT_SYMBOL(ath9k_hw_setuptxqueue); bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) { - struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_tx_queue_info *qi; - if (q >= pCap->total_queues) { - ath_dbg(common, ATH_DBG_QUEUE, - "Release TXQ, invalid queue: %u\n", q); - return false; - } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { ath_dbg(common, ATH_DBG_QUEUE, @@ -414,18 +393,11 @@ EXPORT_SYMBOL(ath9k_hw_releasetxqueue); bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) { - struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_channel *chan = ah->curchan; struct ath9k_tx_queue_info *qi; u32 cwMin, chanCwMin, value; - if (q >= pCap->total_queues) { - ath_dbg(common, ATH_DBG_QUEUE, - "Reset TXQ, invalid queue: %u\n", q); - return false; - } - qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { ath_dbg(common, ATH_DBG_QUEUE, -- cgit v1.2.3-58-ga151 From 0db156e9648e69c34e8e88328358a26611fd71e3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 23 Mar 2011 20:57:29 +0100 Subject: ath9k_hw: remove ah->config.ht_enable It is only used in one place, and the device id check that it's based on can be moved there as well. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 7 +------ drivers/net/wireless/ath/ath9k/hw.h | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index de0d218195da..625ad0bcdc1f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -378,11 +378,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.spurchans[i][1] = AR_NO_SPUR; } - if (ah->hw_version.devid != AR2427_DEVID_PCIE) - ah->config.ht_enable = 1; - else - ah->config.ht_enable = 0; - /* PAPRD needs some more work to be enabled */ ah->config.paprd_disable = 1; @@ -1880,7 +1875,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; - if (ah->config.ht_enable) + if (ah->hw_version.devid != AR2427_DEVID_PCIE) pCap->hw_caps |= ATH9K_HW_CAP_HT; else pCap->hw_caps &= ~ATH9K_HW_CAP_HT; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 4e62ad858d8a..7bbf7015af13 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -222,7 +222,6 @@ struct ath9k_ops_config { u8 pcie_clock_req; u32 pcie_waen; u8 analog_shiftreg; - u8 ht_enable; u8 paprd_disable; u32 ofdm_trig_low; u32 ofdm_trig_high; -- cgit v1.2.3-58-ga151 From c429bdcf8fe033f04830a960e07c13a01f631499 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 23 Mar 2011 20:57:30 +0100 Subject: ath9k_hw: remove pCap->reg_cap It is not used anywhere and seems pointless Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 17 ----------------- drivers/net/wireless/ath/ath9k/hw.h | 1 - 2 files changed, 18 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 625ad0bcdc1f..be2257469ab5 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1932,23 +1932,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) else pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; - if (regulatory->current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) { - pCap->reg_cap = - AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | - AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | - AR_EEPROM_EEREGCAP_EN_KK_U2 | - AR_EEPROM_EEREGCAP_EN_KK_MIDBAND; - } else { - pCap->reg_cap = - AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | - AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; - } - - /* Advertise midband for AR5416 with FCC midband set in eeprom */ - if (regulatory->current_rd_ext & (1 << REG_EXT_FCC_MIDBAND) && - AR_SREV_5416(ah)) - pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; - if (AR_SREV_9280_20_OR_LATER(ah) && common->btcoex_enabled) { btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7bbf7015af13..a255f9a0a698 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -200,7 +200,6 @@ struct ath9k_hw_capabilities { u8 max_txchains; u8 max_rxchains; u16 tx_triglevel_max; - u16 reg_cap; u8 num_gpio_pins; u8 rx_hp_qdepth; u8 rx_lp_qdepth; -- cgit v1.2.3-58-ga151 From 6de12a1bcef0145436e815d30a3d48b9fadb199d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 23 Mar 2011 20:57:31 +0100 Subject: ath9k_hw: remove pCap->keycache_size Similar to the number of tx queue, the number of keycache entries depends on the chip and shouldn't be messed with based on EEPROM data. Remove this field and stick to using AR_KEYTABLE_SIZE Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 8 +------- drivers/net/wireless/ath/ath9k/hw.c | 6 ------ drivers/net/wireless/ath/ath9k/hw.h | 1 - drivers/net/wireless/ath/ath9k/init.c | 8 +------- 4 files changed, 2 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index ca69e7ccfd80..8303b34bdc90 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -564,13 +564,7 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv) int i = 0; /* Get the hardware key cache size. */ - common->keymax = priv->ah->caps.keycache_size; - if (common->keymax > ATH_KEYMAX) { - ath_dbg(common, ATH_DBG_ANY, - "Warning, using only %u entries in %u key cache\n", - ATH_KEYMAX, common->keymax); - common->keymax = ATH_KEYMAX; - } + common->keymax = AR_KEYTABLE_SIZE; if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index be2257469ab5..5c676da73fee 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1880,12 +1880,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) else pCap->hw_caps &= ~ATH9K_HW_CAP_HT; - if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES) - pCap->keycache_size = - 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES); - else - pCap->keycache_size = AR_KEYTABLE_SIZE; - if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1; else diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index a255f9a0a698..296e51b6135b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -191,7 +191,6 @@ enum ath9k_hw_caps { struct ath9k_hw_capabilities { u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ - u16 keycache_size; u16 low_5ghz_chan, high_5ghz_chan; u16 low_2ghz_chan, high_2ghz_chan; u16 rts_aggr_limit; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index db1b7553c684..1ac8318d82a3 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -407,13 +407,7 @@ void ath9k_init_crypto(struct ath_softc *sc) int i = 0; /* Get the hardware key cache size. */ - common->keymax = sc->sc_ah->caps.keycache_size; - if (common->keymax > ATH_KEYMAX) { - ath_dbg(common, ATH_DBG_ANY, - "Warning, using only %u entries in %u key cache\n", - ATH_KEYMAX, common->keymax); - common->keymax = ATH_KEYMAX; - } + common->keymax = AR_KEYTABLE_SIZE; /* * Reset the key cache since some parts do not -- cgit v1.2.3-58-ga151 From 340d0ea774d4ff0038a068e14340b59c5a1fce2c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 23 Mar 2011 20:57:32 +0100 Subject: ath9k_hw: remove ATH9K_HW_CAP_ENHANCEDPM It is not used anywhere Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 -- drivers/net/wireless/ath/ath9k/hw.h | 1 - 2 files changed, 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 5c676da73fee..a2509dc5e87e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1903,8 +1903,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->rts_aggr_limit = (8 * 1024); } - pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM; - #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); if (ah->rfsilent & EEP_RFSILENT_ENABLED) { diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 296e51b6135b..a0243b810a04 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -174,7 +174,6 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_HT = BIT(0), ATH9K_HW_CAP_RFSILENT = BIT(1), ATH9K_HW_CAP_CST = BIT(2), - ATH9K_HW_CAP_ENHANCEDPM = BIT(3), ATH9K_HW_CAP_AUTOSLEEP = BIT(4), ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(5), ATH9K_HW_CAP_EDMA = BIT(6), -- cgit v1.2.3-58-ga151 From 83860c594f65945b1a2c99e84338e1145cd34890 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 23 Mar 2011 20:57:33 +0100 Subject: ath9k_hw: remove pCap->tx_triglevel_max It has the same purpose (and value) as ah->config.max_txtrig_level Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 5 ----- drivers/net/wireless/ath/ath9k/hw.h | 1 - drivers/net/wireless/ath/ath9k/xmit.c | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index a2509dc5e87e..298f4d6cbdbd 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1880,11 +1880,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) else pCap->hw_caps &= ~ATH9K_HW_CAP_HT; - if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) - pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1; - else - pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; - if (AR_SREV_9271(ah)) pCap->num_gpio_pins = AR9271_NUM_GPIO; else if (AR_DEVID_7010(ah)) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index a0243b810a04..4cc320bdf0aa 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -197,7 +197,6 @@ struct ath9k_hw_capabilities { u8 rx_chainmask; u8 max_txchains; u8 max_rxchains; - u16 tx_triglevel_max; u8 num_gpio_pins; u8 rx_hp_qdepth; u8 rx_lp_qdepth; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index f916f088b553..5943bdc4c8f9 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1980,7 +1980,7 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, if (ieee80211_is_data(hdr->frame_control) && (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN)) && - ah->tx_trig_level >= sc->sc_ah->caps.tx_triglevel_max) + ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level) tx_info->status.rates[tx_rateindex].count = hw->max_rate_tries; } -- cgit v1.2.3-58-ga151 From 36a0e6c2d6f3eb59b7a5ddfda63d252a42dba189 Mon Sep 17 00:00:00 2001 From: hayeswang Date: Mon, 21 Mar 2011 01:50:30 +0000 Subject: net/r8169: add a new chip for RTL8105 Add a new chip for RTL8105 whose settings are the same with RTL_GIGA_MAC_VER_30. Signed-off-by: Hayes Wang Signed-off-by: David S. Miller --- drivers/net/r8169.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 493b0de3848b..0111a143c992 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1574,6 +1574,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, /* 8101 family. */ + { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 }, { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 }, { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 }, { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 }, -- cgit v1.2.3-58-ga151 From 4804b3b3aec163b59328140d6c858c3ed1c85992 Mon Sep 17 00:00:00 2001 From: hayeswang Date: Mon, 21 Mar 2011 01:50:29 +0000 Subject: net/r8169: add a new chip for RTL8168DP Add a new chip for RTL8168DP. Signed-off-by: Hayes Wang Signed-off-by: David S. Miller --- drivers/net/r8169.c | 98 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 22 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 0111a143c992..5c480750d8fb 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -127,6 +127,7 @@ enum mac_version { RTL_GIGA_MAC_VER_28 = 0x1c, // 8168DP RTL_GIGA_MAC_VER_29 = 0x1d, // 8105E RTL_GIGA_MAC_VER_30 = 0x1e, // 8105E + RTL_GIGA_MAC_VER_31 = 0x1f, // 8168DP }; #define _R(NAME,MAC,MASK) \ @@ -166,7 +167,8 @@ static const struct { _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, 0xff7e1880), // PCI-E _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_28, 0xff7e1880), // PCI-E _R("RTL8105e", RTL_GIGA_MAC_VER_29, 0xff7e1880), // PCI-E - _R("RTL8105e", RTL_GIGA_MAC_VER_30, 0xff7e1880) // PCI-E + _R("RTL8105e", RTL_GIGA_MAC_VER_30, 0xff7e1880), // PCI-E + _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_31, 0xff7e1880) // PCI-E }; #undef _R @@ -651,12 +653,18 @@ static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd) static void rtl8168_driver_start(struct rtl8169_private *tp) { int i; + u32 reg; rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START); + if (tp->mac_version == RTL_GIGA_MAC_VER_31) + reg = 0xb8; + else + reg = 0x10; + for (i = 0; i < 10; i++) { msleep(10); - if (ocp_read(tp, 0x0f, 0x0010) & 0x00000800) + if (ocp_read(tp, 0x0f, reg) & 0x00000800) break; } } @@ -664,16 +672,36 @@ static void rtl8168_driver_start(struct rtl8169_private *tp) static void rtl8168_driver_stop(struct rtl8169_private *tp) { int i; + u32 reg; rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP); + if (tp->mac_version == RTL_GIGA_MAC_VER_31) + reg = 0xb8; + else + reg = 0x10; + for (i = 0; i < 10; i++) { msleep(10); - if ((ocp_read(tp, 0x0f, 0x0010) & 0x00000800) == 0) + if ((ocp_read(tp, 0x0f, reg) & 0x00000800) == 0) break; } } +static int r8168dp_check_dash(struct rtl8169_private *tp) +{ + u32 reg; + + if (tp->mac_version == RTL_GIGA_MAC_VER_31) + reg = 0xb8; + else + reg = 0x10; + + if (ocp_read(tp, 0xF, reg) & 0x00008000) + return 1; + else + return 0; +} static void r8169_mdio_write(void __iomem *ioaddr, int reg_addr, int value) { @@ -1555,6 +1583,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, /* 8168DP family. */ { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 }, { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 }, + { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 }, /* 8168C family. */ { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 }, @@ -2860,6 +2889,7 @@ static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp) ops->read = r8168dp_1_mdio_read; break; case RTL_GIGA_MAC_VER_28: + case RTL_GIGA_MAC_VER_31: ops->write = r8168dp_2_mdio_write; ops->read = r8168dp_2_mdio_read; break; @@ -2917,8 +2947,9 @@ static void r8168_pll_power_down(struct rtl8169_private *tp) void __iomem *ioaddr = tp->mmio_addr; if (((tp->mac_version == RTL_GIGA_MAC_VER_27) || - (tp->mac_version == RTL_GIGA_MAC_VER_28)) && - (ocp_read(tp, 0x0f, 0x0010) & 0x00008000)) { + (tp->mac_version == RTL_GIGA_MAC_VER_28) || + (tp->mac_version == RTL_GIGA_MAC_VER_31)) && + r8168dp_check_dash(tp)) { return; } @@ -2944,6 +2975,7 @@ static void r8168_pll_power_down(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_26: case RTL_GIGA_MAC_VER_27: case RTL_GIGA_MAC_VER_28: + case RTL_GIGA_MAC_VER_31: RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80); break; } @@ -2954,8 +2986,9 @@ static void r8168_pll_power_up(struct rtl8169_private *tp) void __iomem *ioaddr = tp->mmio_addr; if (((tp->mac_version == RTL_GIGA_MAC_VER_27) || - (tp->mac_version == RTL_GIGA_MAC_VER_28)) && - (ocp_read(tp, 0x0f, 0x0010) & 0x00008000)) { + (tp->mac_version == RTL_GIGA_MAC_VER_28) || + (tp->mac_version == RTL_GIGA_MAC_VER_31)) && + r8168dp_check_dash(tp)) { return; } @@ -2964,6 +2997,7 @@ static void r8168_pll_power_up(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_26: case RTL_GIGA_MAC_VER_27: case RTL_GIGA_MAC_VER_28: + case RTL_GIGA_MAC_VER_31: RTL_W8(PMCH, RTL_R8(PMCH) | 0x80); break; } @@ -3018,6 +3052,7 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_26: case RTL_GIGA_MAC_VER_27: case RTL_GIGA_MAC_VER_28: + case RTL_GIGA_MAC_VER_31: ops->down = r8168_pll_power_down; ops->up = r8168_pll_power_up; break; @@ -3250,7 +3285,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); if ((tp->mac_version == RTL_GIGA_MAC_VER_27) || - (tp->mac_version == RTL_GIGA_MAC_VER_28)) { + (tp->mac_version == RTL_GIGA_MAC_VER_28) || + (tp->mac_version == RTL_GIGA_MAC_VER_31)) { rtl8168_driver_start(tp); } @@ -3283,7 +3319,8 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) struct rtl8169_private *tp = netdev_priv(dev); if ((tp->mac_version == RTL_GIGA_MAC_VER_27) || - (tp->mac_version == RTL_GIGA_MAC_VER_28)) { + (tp->mac_version == RTL_GIGA_MAC_VER_28) || + (tp->mac_version == RTL_GIGA_MAC_VER_31)) { rtl8168_driver_stop(tp); } @@ -3383,7 +3420,8 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp) rtl8169_irq_mask_and_ack(ioaddr); if (tp->mac_version == RTL_GIGA_MAC_VER_27 || - tp->mac_version == RTL_GIGA_MAC_VER_28) { + tp->mac_version == RTL_GIGA_MAC_VER_28 || + tp->mac_version == RTL_GIGA_MAC_VER_31) { while (RTL_R8(TxPoll) & NPQ) udelay(20); @@ -3780,6 +3818,17 @@ static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev) RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); } +static void rtl_hw_start_8168dp(void __iomem *ioaddr, struct pci_dev *pdev) +{ + rtl_csi_access_enable_1(ioaddr); + + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + + RTL_W8(MaxTxPacketSize, TxPacketMax); + + rtl_disable_clock_request(pdev); +} + static void rtl_hw_start_8168d_4(void __iomem *ioaddr, struct pci_dev *pdev) { static const struct ephy_info e_info_8168d_4[] = { @@ -3843,55 +3892,59 @@ static void rtl_hw_start_8168(struct net_device *dev) switch (tp->mac_version) { case RTL_GIGA_MAC_VER_11: rtl_hw_start_8168bb(ioaddr, pdev); - break; + break; case RTL_GIGA_MAC_VER_12: case RTL_GIGA_MAC_VER_17: rtl_hw_start_8168bef(ioaddr, pdev); - break; + break; case RTL_GIGA_MAC_VER_18: rtl_hw_start_8168cp_1(ioaddr, pdev); - break; + break; case RTL_GIGA_MAC_VER_19: rtl_hw_start_8168c_1(ioaddr, pdev); - break; + break; case RTL_GIGA_MAC_VER_20: rtl_hw_start_8168c_2(ioaddr, pdev); - break; + break; case RTL_GIGA_MAC_VER_21: rtl_hw_start_8168c_3(ioaddr, pdev); - break; + break; case RTL_GIGA_MAC_VER_22: rtl_hw_start_8168c_4(ioaddr, pdev); - break; + break; case RTL_GIGA_MAC_VER_23: rtl_hw_start_8168cp_2(ioaddr, pdev); - break; + break; case RTL_GIGA_MAC_VER_24: rtl_hw_start_8168cp_3(ioaddr, pdev); - break; + break; case RTL_GIGA_MAC_VER_25: case RTL_GIGA_MAC_VER_26: case RTL_GIGA_MAC_VER_27: rtl_hw_start_8168d(ioaddr, pdev); - break; + break; case RTL_GIGA_MAC_VER_28: rtl_hw_start_8168d_4(ioaddr, pdev); - break; + break; + case RTL_GIGA_MAC_VER_31: + rtl_hw_start_8168dp(ioaddr, pdev); + break; + default: printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", dev->name, tp->mac_version); - break; + break; } RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); @@ -4756,6 +4809,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) case RTL_GIGA_MAC_VER_24: case RTL_GIGA_MAC_VER_27: case RTL_GIGA_MAC_VER_28: + case RTL_GIGA_MAC_VER_31: /* Experimental science. Pktgen proof. */ case RTL_GIGA_MAC_VER_12: case RTL_GIGA_MAC_VER_25: -- cgit v1.2.3-58-ga151 From 01dc7fec4025f6bb72b6b98ec88b375346b6dbbb Mon Sep 17 00:00:00 2001 From: hayeswang Date: Mon, 21 Mar 2011 01:50:28 +0000 Subject: net/r8169: support RTL8168E Support RTL8168E/RTL8111E. Signed-off-by: Hayes Wang Signed-off-by: David S. Miller --- drivers/net/r8169.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 207 insertions(+), 5 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 5c480750d8fb..caa99cdb5818 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -37,6 +37,8 @@ #define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw" #define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw" +#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw" +#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw" #define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw" #ifdef RTL8169_DEBUG @@ -128,6 +130,8 @@ enum mac_version { RTL_GIGA_MAC_VER_29 = 0x1d, // 8105E RTL_GIGA_MAC_VER_30 = 0x1e, // 8105E RTL_GIGA_MAC_VER_31 = 0x1f, // 8168DP + RTL_GIGA_MAC_VER_32 = 0x20, // 8168E + RTL_GIGA_MAC_VER_33 = 0x21, // 8168E }; #define _R(NAME,MAC,MASK) \ @@ -168,7 +172,9 @@ static const struct { _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_28, 0xff7e1880), // PCI-E _R("RTL8105e", RTL_GIGA_MAC_VER_29, 0xff7e1880), // PCI-E _R("RTL8105e", RTL_GIGA_MAC_VER_30, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_31, 0xff7e1880) // PCI-E + _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_31, 0xff7e1880), // PCI-E + _R("RTL8168e/8111e", RTL_GIGA_MAC_VER_32, 0xff7e1880), // PCI-E + _R("RTL8168e/8111e", RTL_GIGA_MAC_VER_33, 0xff7e1880) // PCI-E }; #undef _R @@ -317,7 +323,9 @@ enum rtl8168_registers { #define OCPAR_FLAG 0x80000000 #define OCPAR_GPHY_WRITE_CMD 0x8000f060 #define OCPAR_GPHY_READ_CMD 0x0000f060 - RDSAR1 = 0xd0 /* 8168c only. Undocumented on 8168dp */ + RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */ + MISC = 0xf0, /* 8168e only. */ + txpla_rst = (1 << 29) }; enum rtl_register_content { @@ -395,6 +403,7 @@ enum rtl_register_content { BWF = (1 << 6), /* Accept Broadcast wakeup frame */ MWF = (1 << 5), /* Accept Multicast wakeup frame */ UWF = (1 << 4), /* Accept Unicast wakeup frame */ + spi_en = (1 << 3), LanWake = (1 << 1), /* LanWake enable/disable */ PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ @@ -579,6 +588,8 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(RTL8169_VERSION); MODULE_FIRMWARE(FIRMWARE_8168D_1); MODULE_FIRMWARE(FIRMWARE_8168D_2); +MODULE_FIRMWARE(FIRMWARE_8168E_1); +MODULE_FIRMWARE(FIRMWARE_8168E_2); MODULE_FIRMWARE(FIRMWARE_8105E_1); static int rtl8169_open(struct net_device *dev); @@ -1575,6 +1586,11 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, u32 val; int mac_version; } mac_info[] = { + /* 8168E family. */ + { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 }, + { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 }, + { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 }, + /* 8168D family. */ { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, @@ -2466,6 +2482,93 @@ static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp) rtl_patchphy(tp, 0x0d, 1 << 5); } +static void rtl8168e_hw_phy_config(struct rtl8169_private *tp) +{ + static const struct phy_reg phy_reg_init[] = { + /* Enable Delay cap */ + { 0x1f, 0x0005 }, + { 0x05, 0x8b80 }, + { 0x06, 0xc896 }, + { 0x1f, 0x0000 }, + + /* Channel estimation fine tune */ + { 0x1f, 0x0001 }, + { 0x0b, 0x6c20 }, + { 0x07, 0x2872 }, + { 0x1c, 0xefff }, + { 0x1f, 0x0003 }, + { 0x14, 0x6420 }, + { 0x1f, 0x0000 }, + + /* Update PFM & 10M TX idle timer */ + { 0x1f, 0x0007 }, + { 0x1e, 0x002f }, + { 0x15, 0x1919 }, + { 0x1f, 0x0000 }, + + { 0x1f, 0x0007 }, + { 0x1e, 0x00ac }, + { 0x18, 0x0006 }, + { 0x1f, 0x0000 } + }; + + rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); + + /* DCO enable for 10M IDLE Power */ + rtl_writephy(tp, 0x1f, 0x0007); + rtl_writephy(tp, 0x1e, 0x0023); + rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000); + rtl_writephy(tp, 0x1f, 0x0000); + + /* For impedance matching */ + rtl_writephy(tp, 0x1f, 0x0002); + rtl_w1w0_phy(tp, 0x08, 0x8000, 0x7f00); + rtl_writephy(tp, 0x1F, 0x0000); + + /* PHY auto speed down */ + rtl_writephy(tp, 0x1f, 0x0007); + rtl_writephy(tp, 0x1e, 0x002d); + rtl_w1w0_phy(tp, 0x18, 0x0050, 0x0000); + rtl_writephy(tp, 0x1f, 0x0000); + rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000); + + rtl_writephy(tp, 0x1f, 0x0005); + rtl_writephy(tp, 0x05, 0x8b86); + rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000); + rtl_writephy(tp, 0x1f, 0x0000); + + rtl_writephy(tp, 0x1f, 0x0005); + rtl_writephy(tp, 0x05, 0x8b85); + rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000); + rtl_writephy(tp, 0x1f, 0x0007); + rtl_writephy(tp, 0x1e, 0x0020); + rtl_w1w0_phy(tp, 0x15, 0x0000, 0x1100); + rtl_writephy(tp, 0x1f, 0x0006); + rtl_writephy(tp, 0x00, 0x5a00); + rtl_writephy(tp, 0x1f, 0x0000); + rtl_writephy(tp, 0x0d, 0x0007); + rtl_writephy(tp, 0x0e, 0x003c); + rtl_writephy(tp, 0x0d, 0x4007); + rtl_writephy(tp, 0x0e, 0x0000); + rtl_writephy(tp, 0x0d, 0x0000); +} + +static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp) +{ + if (rtl_apply_firmware(tp, FIRMWARE_8168E_1) < 0) + netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); + + rtl8168e_hw_phy_config(tp); +} + +static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp) +{ + if (rtl_apply_firmware(tp, FIRMWARE_8168E_2) < 0) + netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n"); + + rtl8168e_hw_phy_config(tp); +} + static void rtl8102e_hw_phy_config(struct rtl8169_private *tp) { static const struct phy_reg phy_reg_init[] = { @@ -2581,6 +2684,12 @@ static void rtl_hw_phy_config(struct net_device *dev) case RTL_GIGA_MAC_VER_30: rtl8105e_hw_phy_config(tp); break; + case RTL_GIGA_MAC_VER_32: + rtl8168e_1_hw_phy_config(tp); + break; + case RTL_GIGA_MAC_VER_33: + rtl8168e_2_hw_phy_config(tp); + break; default: break; @@ -2931,15 +3040,59 @@ static void r810x_pll_power_up(struct rtl8169_private *tp) static void r8168_phy_power_up(struct rtl8169_private *tp) { rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x0e, 0x0000); + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_11: + case RTL_GIGA_MAC_VER_12: + case RTL_GIGA_MAC_VER_17: + case RTL_GIGA_MAC_VER_18: + case RTL_GIGA_MAC_VER_19: + case RTL_GIGA_MAC_VER_20: + case RTL_GIGA_MAC_VER_21: + case RTL_GIGA_MAC_VER_22: + case RTL_GIGA_MAC_VER_23: + case RTL_GIGA_MAC_VER_24: + case RTL_GIGA_MAC_VER_25: + case RTL_GIGA_MAC_VER_26: + case RTL_GIGA_MAC_VER_27: + case RTL_GIGA_MAC_VER_28: + case RTL_GIGA_MAC_VER_31: + rtl_writephy(tp, 0x0e, 0x0000); + break; + default: + break; + } rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE); } static void r8168_phy_power_down(struct rtl8169_private *tp) { rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x0e, 0x0200); - rtl_writephy(tp, MII_BMCR, BMCR_PDOWN); + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_32: + case RTL_GIGA_MAC_VER_33: + rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); + break; + + case RTL_GIGA_MAC_VER_11: + case RTL_GIGA_MAC_VER_12: + case RTL_GIGA_MAC_VER_17: + case RTL_GIGA_MAC_VER_18: + case RTL_GIGA_MAC_VER_19: + case RTL_GIGA_MAC_VER_20: + case RTL_GIGA_MAC_VER_21: + case RTL_GIGA_MAC_VER_22: + case RTL_GIGA_MAC_VER_23: + case RTL_GIGA_MAC_VER_24: + case RTL_GIGA_MAC_VER_25: + case RTL_GIGA_MAC_VER_26: + case RTL_GIGA_MAC_VER_27: + case RTL_GIGA_MAC_VER_28: + case RTL_GIGA_MAC_VER_31: + rtl_writephy(tp, 0x0e, 0x0200); + default: + rtl_writephy(tp, MII_BMCR, BMCR_PDOWN); + break; + } } static void r8168_pll_power_down(struct rtl8169_private *tp) @@ -2959,6 +3112,10 @@ static void r8168_pll_power_down(struct rtl8169_private *tp) return; } + if (tp->mac_version == RTL_GIGA_MAC_VER_32 || + tp->mac_version == RTL_GIGA_MAC_VER_33) + rtl_ephy_write(ioaddr, 0x19, 0xff64); + if (__rtl8169_get_wol(tp) & WAKE_ANY) { rtl_writephy(tp, 0x1f, 0x0000); rtl_writephy(tp, MII_BMCR, 0x0000); @@ -2976,6 +3133,8 @@ static void r8168_pll_power_down(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_27: case RTL_GIGA_MAC_VER_28: case RTL_GIGA_MAC_VER_31: + case RTL_GIGA_MAC_VER_32: + case RTL_GIGA_MAC_VER_33: RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80); break; } @@ -2998,6 +3157,8 @@ static void r8168_pll_power_up(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_27: case RTL_GIGA_MAC_VER_28: case RTL_GIGA_MAC_VER_31: + case RTL_GIGA_MAC_VER_32: + case RTL_GIGA_MAC_VER_33: RTL_W8(PMCH, RTL_R8(PMCH) | 0x80); break; } @@ -3053,6 +3214,8 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_27: case RTL_GIGA_MAC_VER_28: case RTL_GIGA_MAC_VER_31: + case RTL_GIGA_MAC_VER_32: + case RTL_GIGA_MAC_VER_33: ops->down = r8168_pll_power_down; ops->up = r8168_pll_power_up; break; @@ -3855,6 +4018,41 @@ static void rtl_hw_start_8168d_4(void __iomem *ioaddr, struct pci_dev *pdev) rtl_enable_clock_request(pdev); } +static void rtl_hw_start_8168e(void __iomem *ioaddr, struct pci_dev *pdev) +{ + static const struct ephy_info e_info_8168e[] = { + { 0x00, 0x0200, 0x0100 }, + { 0x00, 0x0000, 0x0004 }, + { 0x06, 0x0002, 0x0001 }, + { 0x06, 0x0000, 0x0030 }, + { 0x07, 0x0000, 0x2000 }, + { 0x00, 0x0000, 0x0020 }, + { 0x03, 0x5800, 0x2000 }, + { 0x03, 0x0000, 0x0001 }, + { 0x01, 0x0800, 0x1000 }, + { 0x07, 0x0000, 0x4000 }, + { 0x1e, 0x0000, 0x2000 }, + { 0x19, 0xffff, 0xfe6c }, + { 0x0a, 0x0000, 0x0040 } + }; + + rtl_csi_access_enable_2(ioaddr); + + rtl_ephy_init(ioaddr, e_info_8168e, ARRAY_SIZE(e_info_8168e)); + + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + + RTL_W8(MaxTxPacketSize, TxPacketMax); + + rtl_disable_clock_request(pdev); + + /* Reset tx FIFO pointer */ + RTL_W32(MISC, RTL_R32(MISC) | txpla_rst); + RTL_W32(MISC, RTL_R32(MISC) & ~txpla_rst); + + RTL_W8(Config5, RTL_R8(Config5) & ~spi_en); +} + static void rtl_hw_start_8168(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -3940,6 +4138,10 @@ static void rtl_hw_start_8168(struct net_device *dev) rtl_hw_start_8168dp(ioaddr, pdev); break; + case RTL_GIGA_MAC_VER_32: + case RTL_GIGA_MAC_VER_33: + rtl_hw_start_8168e(ioaddr, pdev); + break; default: printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", -- cgit v1.2.3-58-ga151 From 311fddc7569d7a3340d61de262cff11685060f74 Mon Sep 17 00:00:00 2001 From: Somnath Kotur Date: Wed, 16 Mar 2011 21:22:43 +0000 Subject: be2net: Support for FAT dump retrieval using ethtool --register-dump option Signed-off-by: Somnath Kotur Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 107 +++++++++++++++++++++++++++++++++++++++++ drivers/net/benet/be_cmds.h | 21 ++++++++ drivers/net/benet/be_ethtool.c | 21 ++++++++ drivers/net/benet/be_hw.h | 4 ++ 4 files changed, 153 insertions(+) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 5a4a87e7c5ea..2aadf88eaa0a 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1186,6 +1186,113 @@ err: return status; } +/* Uses synchronous mcc */ +int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_fat *req; + int status; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + req = embedded_payload(wrb); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, + OPCODE_COMMON_MANAGE_FAT); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_MANAGE_FAT, sizeof(*req)); + req->fat_operation = cpu_to_le32(QUERY_FAT); + status = be_mcc_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_get_fat *resp = embedded_payload(wrb); + if (log_size && resp->log_size) + *log_size = le32_to_cpu(resp->log_size - + sizeof(u32)); + } +err: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} + +void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf) +{ + struct be_dma_mem get_fat_cmd; + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_fat *req; + struct be_sge *sge; + u32 offset = 0, total_size, buf_size, log_offset = sizeof(u32); + int status; + + if (buf_len == 0) + return; + + total_size = buf_len; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + while (total_size) { + buf_size = min(total_size, (u32)60*1024); + total_size -= buf_size; + + get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + buf_size; + get_fat_cmd.va = pci_alloc_consistent(adapter->pdev, + get_fat_cmd.size, + &get_fat_cmd.dma); + if (!get_fat_cmd.va) { + status = -ENOMEM; + dev_err(&adapter->pdev->dev, + "Memory allocation failure while retrieving FAT data\n"); + goto err; + } + req = get_fat_cmd.va; + sge = nonembedded_sgl(wrb); + + be_wrb_hdr_prepare(wrb, get_fat_cmd.size, false, 1, + OPCODE_COMMON_MANAGE_FAT); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_MANAGE_FAT, get_fat_cmd.size); + + sge->pa_hi = cpu_to_le32(upper_32_bits(get_fat_cmd.size)); + sge->pa_lo = cpu_to_le32(get_fat_cmd.dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(get_fat_cmd.size); + + req->fat_operation = cpu_to_le32(RETRIEVE_FAT); + req->read_log_offset = cpu_to_le32(log_offset); + req->read_log_length = cpu_to_le32(buf_size); + req->data_buffer_size = cpu_to_le32(buf_size); + + status = be_mcc_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_get_fat *resp = get_fat_cmd.va; + memcpy(buf + offset, + resp->data_buffer, + resp->read_log_length); + } + pci_free_consistent(adapter->pdev, get_fat_cmd.size, + get_fat_cmd.va, + get_fat_cmd.dma); + if (status) + dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n"); + + offset += buf_size; + log_offset += buf_size; + } +err: + spin_unlock_bh(&adapter->mcc_lock); +} + /* Uses Mbox */ int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver) { diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 4f254cfaabe2..3fb6e0a3ad7a 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -186,6 +186,7 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_NTWK_PMAC_ADD 59 #define OPCODE_COMMON_NTWK_PMAC_DEL 60 #define OPCODE_COMMON_FUNCTION_RESET 61 +#define OPCODE_COMMON_MANAGE_FAT 68 #define OPCODE_COMMON_ENABLE_DISABLE_BEACON 69 #define OPCODE_COMMON_GET_BEACON_STATE 70 #define OPCODE_COMMON_READ_TRANSRECV_DATA 73 @@ -380,6 +381,24 @@ struct be_cmd_resp_cq_create { u16 rsvd0; } __packed; +struct be_cmd_req_get_fat { + struct be_cmd_req_hdr hdr; + u32 fat_operation; + u32 read_log_offset; + u32 read_log_length; + u32 data_buffer_size; + u32 data_buffer[1]; +} __packed; + +struct be_cmd_resp_get_fat { + struct be_cmd_resp_hdr hdr; + u32 log_size; + u32 read_log_length; + u32 rsvd[2]; + u32 data_buffer[1]; +} __packed; + + /******************** Create MCCQ ***************************/ /* Pseudo amap definition in which each bit of the actual structure is defined * as a byte: used to calculate offset/shift/mask of each field */ @@ -1148,4 +1167,6 @@ extern void be_detect_dump_ue(struct be_adapter *adapter); extern int be_cmd_get_die_temperature(struct be_adapter *adapter); extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter); extern int be_cmd_check_native_mode(struct be_adapter *adapter); +extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size); +extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index aac248fbd18b..575ac659ceb4 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -155,6 +155,25 @@ be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) drvinfo->eedump_len = 0; } +static int +be_get_reg_len(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + u32 log_size = 0; + + be_cmd_get_reg_len(adapter, &log_size); + return log_size; +} + +static void +be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + memset(buf, 0, regs->len); + be_cmd_get_regs(adapter, regs->len, buf); +} + static int be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) { @@ -737,6 +756,8 @@ const struct ethtool_ops be_ethtool_ops = { .phys_id = be_phys_id, .get_sset_count = be_get_sset_count, .get_ethtool_stats = be_get_ethtool_stats, + .get_regs_len = be_get_reg_len, + .get_regs = be_get_regs, .flash_device = be_do_flash, .self_test = be_self_test, }; diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index d4344a06090b..53d658afea2a 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -155,6 +155,10 @@ /********** SRIOV VF PCICFG OFFSET ********/ #define SRIOV_VF_PCICFG_OFFSET (4096) +/********** FAT TABLE ********/ +#define RETRIEVE_FAT 0 +#define QUERY_FAT 1 + /* Flashrom related descriptors */ #define IMAGE_TYPE_FIRMWARE 160 #define IMAGE_TYPE_BOOTCODE 224 -- cgit v1.2.3-58-ga151 From ac6a0c4aab16070d7d55f49a52de33f716ae1d3d Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Mon, 21 Mar 2011 20:49:25 +0000 Subject: be2net: refactor code that decides adapter->num_rx_queues The code has been refactored to not set num_rx_qs inside be_enable_msix(). num_rx_qs is now set at the time of queue creation based on the number of available msix vectors. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 8 +++--- drivers/net/benet/be_main.c | 66 +++++++++++++++++++++++---------------------- 2 files changed, 39 insertions(+), 35 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index f803c58b941d..3937bca3d431 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -84,7 +84,8 @@ static inline char *nic_name(struct pci_dev *pdev) #define MCC_CQ_LEN 256 #define MAX_RSS_QS 4 /* BE limit is 4 queues/port */ -#define BE_MAX_MSIX_VECTORS (MAX_RSS_QS + 1 + 1)/* RSS qs + 1 def Rx + Tx */ +#define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */ +#define BE_MAX_MSIX_VECTORS (MAX_RX_QS + 1)/* RX + TX */ #define BE_NAPI_WEIGHT 64 #define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ #define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) @@ -276,7 +277,7 @@ struct be_adapter { spinlock_t mcc_cq_lock; struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS]; - bool msix_enabled; + u32 num_msix_vec; bool isr_registered; /* TX Rings */ @@ -287,7 +288,7 @@ struct be_adapter { u32 cache_line_break[8]; /* Rx rings */ - struct be_rx_obj rx_obj[MAX_RSS_QS + 1]; /* one default non-rss Q */ + struct be_rx_obj rx_obj[MAX_RX_QS]; u32 num_rx_qs; u32 big_page_size; /* Compounded page size shared by rx wrbs */ @@ -351,6 +352,7 @@ struct be_adapter { extern const struct ethtool_ops be_ethtool_ops; +#define msix_enabled(adapter) (adapter->num_msix_vec > 0) #define tx_stats(adapter) (&adapter->tx_stats) #define rx_stats(rxo) (&rxo->stats) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index a71163f1e34b..7a5d6a308051 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1567,12 +1567,31 @@ static void be_rx_queues_destroy(struct be_adapter *adapter) } } +static u32 be_num_rxqs_want(struct be_adapter *adapter) +{ + if (multi_rxq && (adapter->function_caps & BE_FUNCTION_CAPS_RSS) && + !adapter->sriov_enabled && !(adapter->function_mode & 0x400)) { + return 1 + MAX_RSS_QS; /* one default non-RSS queue */ + } else { + dev_warn(&adapter->pdev->dev, + "No support for multiple RX queues\n"); + return 1; + } +} + static int be_rx_queues_create(struct be_adapter *adapter) { struct be_queue_info *eq, *q, *cq; struct be_rx_obj *rxo; int rc, i; + adapter->num_rx_qs = min(be_num_rxqs_want(adapter), + msix_enabled(adapter) ? + adapter->num_msix_vec - 1 : 1); + if (adapter->num_rx_qs != MAX_RX_QS) + dev_warn(&adapter->pdev->dev, + "Can create only %d RX queues", adapter->num_rx_qs); + adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; for_all_rx_queues(adapter, rxo, i) { rxo->adapter = adapter; @@ -1878,51 +1897,35 @@ reschedule: static void be_msix_disable(struct be_adapter *adapter) { - if (adapter->msix_enabled) { + if (msix_enabled(adapter)) { pci_disable_msix(adapter->pdev); - adapter->msix_enabled = false; - } -} - -static int be_num_rxqs_get(struct be_adapter *adapter) -{ - if (multi_rxq && (adapter->function_caps & BE_FUNCTION_CAPS_RSS) && - !adapter->sriov_enabled && !(adapter->function_mode & 0x400)) { - return 1 + MAX_RSS_QS; /* one default non-RSS queue */ - } else { - dev_warn(&adapter->pdev->dev, - "No support for multiple RX queues\n"); - return 1; + adapter->num_msix_vec = 0; } } static void be_msix_enable(struct be_adapter *adapter) { #define BE_MIN_MSIX_VECTORS (1 + 1) /* Rx + Tx */ - int i, status; + int i, status, num_vec; - adapter->num_rx_qs = be_num_rxqs_get(adapter); + num_vec = be_num_rxqs_want(adapter) + 1; - for (i = 0; i < (adapter->num_rx_qs + 1); i++) + for (i = 0; i < num_vec; i++) adapter->msix_entries[i].entry = i; - status = pci_enable_msix(adapter->pdev, adapter->msix_entries, - adapter->num_rx_qs + 1); + status = pci_enable_msix(adapter->pdev, adapter->msix_entries, num_vec); if (status == 0) { goto done; } else if (status >= BE_MIN_MSIX_VECTORS) { + num_vec = status; if (pci_enable_msix(adapter->pdev, adapter->msix_entries, - status) == 0) { - adapter->num_rx_qs = status - 1; - dev_warn(&adapter->pdev->dev, - "Could alloc only %d MSIx vectors. " - "Using %d RX Qs\n", status, adapter->num_rx_qs); + num_vec) == 0) goto done; - } } return; done: - adapter->msix_enabled = true; + adapter->num_msix_vec = num_vec; + return; } static void be_sriov_enable(struct be_adapter *adapter) @@ -2003,8 +2006,7 @@ err_msix: err: dev_warn(&adapter->pdev->dev, "MSIX Request IRQ failed - err %d\n", status); - pci_disable_msix(adapter->pdev); - adapter->msix_enabled = false; + be_msix_disable(adapter); return status; } @@ -2013,7 +2015,7 @@ static int be_irq_register(struct be_adapter *adapter) struct net_device *netdev = adapter->netdev; int status; - if (adapter->msix_enabled) { + if (msix_enabled(adapter)) { status = be_msix_register(adapter); if (status == 0) goto done; @@ -2046,7 +2048,7 @@ static void be_irq_unregister(struct be_adapter *adapter) return; /* INTx */ - if (!adapter->msix_enabled) { + if (!msix_enabled(adapter)) { free_irq(netdev->irq, adapter); goto done; } @@ -2088,7 +2090,7 @@ static int be_close(struct net_device *netdev) be_cq_notify(adapter, rxo->cq.id, false, 0); } - if (adapter->msix_enabled) { + if (msix_enabled(adapter)) { vec = be_msix_vec_get(adapter, tx_eq); synchronize_irq(vec); @@ -2261,7 +2263,7 @@ static int be_setup(struct be_adapter *adapter) BE_IF_FLAGS_PASS_L3L4_ERRORS; en_flags |= BE_IF_FLAGS_PASS_L3L4_ERRORS; - if (be_multi_rxq(adapter)) { + if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) { cap_flags |= BE_IF_FLAGS_RSS; en_flags |= BE_IF_FLAGS_RSS; } -- cgit v1.2.3-58-ga151 From 15d721847f56f32fe9fd43d34db1b32b13de78dc Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Mon, 21 Mar 2011 20:49:26 +0000 Subject: be2net: parse vid and vtm fields of rx-compl only if vlanf bit is set Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 7a5d6a308051..6616300f6070 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1101,8 +1101,12 @@ static void be_parse_rx_compl_v1(struct be_adapter *adapter, AMAP_GET_BITS(struct amap_eth_rx_compl_v1, numfrags, compl); rxcp->pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, cast_enc, compl); - rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm, compl); - rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag, compl); + if (rxcp->vlanf) { + rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm, + compl); + rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag, + compl); + } } static void be_parse_rx_compl_v0(struct be_adapter *adapter, @@ -1127,8 +1131,12 @@ static void be_parse_rx_compl_v0(struct be_adapter *adapter, AMAP_GET_BITS(struct amap_eth_rx_compl_v0, numfrags, compl); rxcp->pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, cast_enc, compl); - rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm, compl); - rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag, compl); + if (rxcp->vlanf) { + rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm, + compl); + rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag, + compl); + } } static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo) @@ -1150,15 +1158,19 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo) else be_parse_rx_compl_v0(adapter, compl, rxcp); - /* vlanf could be wrongly set in some cards. ignore if vtm is not set */ - if ((adapter->function_mode & 0x400) && !rxcp->vtm) - rxcp->vlanf = 0; + if (rxcp->vlanf) { + /* vlanf could be wrongly set in some cards. + * ignore if vtm is not set */ + if ((adapter->function_mode & 0x400) && !rxcp->vtm) + rxcp->vlanf = 0; - if (!lancer_chip(adapter)) - rxcp->vid = swab16(rxcp->vid); + if (!lancer_chip(adapter)) + rxcp->vid = swab16(rxcp->vid); - if ((adapter->pvid == rxcp->vid) && !adapter->vlan_tag[rxcp->vid]) - rxcp->vlanf = 0; + if ((adapter->pvid == rxcp->vid) && + !adapter->vlan_tag[rxcp->vid]) + rxcp->vlanf = 0; + } /* As the compl has been parsed, reset it; we wont touch it again */ compl->dw[offsetof(struct amap_eth_rx_compl_v1, valid) / 32] = 0; -- cgit v1.2.3-58-ga151 From 16da8250df36547269d20a3d53daa11c79f59637 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Mon, 21 Mar 2011 20:49:27 +0000 Subject: be2net: remove redundant code in be_worker() Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 6616300f6070..3bf79d148c24 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1868,6 +1868,9 @@ static void be_worker(struct work_struct *work) struct be_rx_obj *rxo; int i; + if (!adapter->ue_detected && !lancer_chip(adapter)) + be_detect_dump_ue(adapter); + /* when interrupts are not yet enabled, just reap any pending * mcc completions */ if (!netif_running(adapter->netdev)) { @@ -1880,9 +1883,6 @@ static void be_worker(struct work_struct *work) be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl); } - if (!adapter->ue_detected && !lancer_chip(adapter)) - be_detect_dump_ue(adapter); - goto reschedule; } @@ -1900,8 +1900,6 @@ static void be_worker(struct work_struct *work) be_post_rx_frags(rxo, GFP_KERNEL); } } - if (!adapter->ue_detected && !lancer_chip(adapter)) - be_detect_dump_ue(adapter); reschedule: schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); -- cgit v1.2.3-58-ga151 From 0f4a682882171d81c9e3c33c1094b87a197c09fa Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Mon, 21 Mar 2011 20:49:28 +0000 Subject: be2net: cancel be_worker in be_shutdown() even when i/f is down As the be_worker() workqueue is scheduled in be_probe() it must be canceled unconditionally in be_shutdown(). Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 3bf79d148c24..86389133dd3c 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -3155,8 +3155,7 @@ static void be_shutdown(struct pci_dev *pdev) struct be_adapter *adapter = pci_get_drvdata(pdev); struct net_device *netdev = adapter->netdev; - if (netif_running(netdev)) - cancel_delayed_work_sync(&adapter->work); + cancel_delayed_work_sync(&adapter->work); netif_device_detach(netdev); -- cgit v1.2.3-58-ga151 From e8c37c80006c99a00aa70a783023d616c166a04b Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Mon, 21 Mar 2011 20:49:29 +0000 Subject: be2net: remove one useless line Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 86389133dd3c..a24fb45c0f71 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2330,7 +2330,6 @@ static int be_setup(struct be_adapter *adapter) return 0; - be_mcc_queues_destroy(adapter); rx_qs_destroy: be_rx_queues_destroy(adapter); tx_qs_destroy: -- cgit v1.2.3-58-ga151 From dffc6b2432ea89af24a36e8100b3eeea09db67e5 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 25 Mar 2011 14:21:22 +0000 Subject: smsc911x: Use pr_fmt, netdev_, and netif_ Use the more common/verbose logging styles. Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove smsc911x prefixes from format strings. Rename SMSC_WARNING to SMSC_WARN. Remove DPRINTK macro. Use netif_ in SMSC_ macros. Convert NETIF_MSG_ uses to lower case. Add no_printk verification in non-debug uses. Add pdata to SMSC_ uses to avoid hidden variable uses. Convert printks to netdev_ as appropriate. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 292 ++++++++++++++++++++++++------------------------- drivers/net/smsc911x.h | 22 ++-- 2 files changed, 155 insertions(+), 159 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 1566259c1f27..8b501d53063f 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -29,6 +29,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -248,8 +250,8 @@ static int smsc911x_mac_complete(struct smsc911x_data *pdata) if (!(val & MAC_CSR_CMD_CSR_BUSY_)) return 0; } - SMSC_WARNING(HW, "Timed out waiting for MAC not BUSY. " - "MAC_CSR_CMD: 0x%08X", val); + SMSC_WARN(pdata, hw, "Timed out waiting for MAC not BUSY. " + "MAC_CSR_CMD: 0x%08X", val); return -EIO; } @@ -262,7 +264,7 @@ static u32 smsc911x_mac_read(struct smsc911x_data *pdata, unsigned int offset) temp = smsc911x_reg_read(pdata, MAC_CSR_CMD); if (unlikely(temp & MAC_CSR_CMD_CSR_BUSY_)) { - SMSC_WARNING(HW, "MAC busy at entry"); + SMSC_WARN(pdata, hw, "MAC busy at entry"); return 0xFFFFFFFF; } @@ -277,7 +279,7 @@ static u32 smsc911x_mac_read(struct smsc911x_data *pdata, unsigned int offset) if (likely(smsc911x_mac_complete(pdata) == 0)) return smsc911x_reg_read(pdata, MAC_CSR_DATA); - SMSC_WARNING(HW, "MAC busy after read"); + SMSC_WARN(pdata, hw, "MAC busy after read"); return 0xFFFFFFFF; } @@ -291,8 +293,8 @@ static void smsc911x_mac_write(struct smsc911x_data *pdata, temp = smsc911x_reg_read(pdata, MAC_CSR_CMD); if (unlikely(temp & MAC_CSR_CMD_CSR_BUSY_)) { - SMSC_WARNING(HW, - "smsc911x_mac_write failed, MAC busy at entry"); + SMSC_WARN(pdata, hw, + "smsc911x_mac_write failed, MAC busy at entry"); return; } @@ -310,8 +312,7 @@ static void smsc911x_mac_write(struct smsc911x_data *pdata, if (likely(smsc911x_mac_complete(pdata) == 0)) return; - SMSC_WARNING(HW, - "smsc911x_mac_write failed, MAC busy after write"); + SMSC_WARN(pdata, hw, "smsc911x_mac_write failed, MAC busy after write"); } /* Get a phy register */ @@ -326,8 +327,7 @@ static int smsc911x_mii_read(struct mii_bus *bus, int phyaddr, int regidx) /* Confirm MII not busy */ if (unlikely(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) { - SMSC_WARNING(HW, - "MII is busy in smsc911x_mii_read???"); + SMSC_WARN(pdata, hw, "MII is busy in smsc911x_mii_read???"); reg = -EIO; goto out; } @@ -343,7 +343,7 @@ static int smsc911x_mii_read(struct mii_bus *bus, int phyaddr, int regidx) goto out; } - SMSC_WARNING(HW, "Timed out waiting for MII read to finish"); + SMSC_WARN(pdata, hw, "Timed out waiting for MII read to finish"); reg = -EIO; out: @@ -364,8 +364,7 @@ static int smsc911x_mii_write(struct mii_bus *bus, int phyaddr, int regidx, /* Confirm MII not busy */ if (unlikely(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) { - SMSC_WARNING(HW, - "MII is busy in smsc911x_mii_write???"); + SMSC_WARN(pdata, hw, "MII is busy in smsc911x_mii_write???"); reg = -EIO; goto out; } @@ -385,7 +384,7 @@ static int smsc911x_mii_write(struct mii_bus *bus, int phyaddr, int regidx, goto out; } - SMSC_WARNING(HW, "Timed out waiting for MII write to finish"); + SMSC_WARN(pdata, hw, "Timed out waiting for MII write to finish"); reg = -EIO; out: @@ -426,18 +425,20 @@ static void smsc911x_phy_initialise_external(struct smsc911x_data *pdata) unsigned int hwcfg = smsc911x_reg_read(pdata, HW_CFG); if (pdata->config.flags & SMSC911X_FORCE_INTERNAL_PHY) { - SMSC_TRACE(HW, "Forcing internal PHY"); + SMSC_TRACE(pdata, hw, "Forcing internal PHY"); pdata->using_extphy = 0; } else if (pdata->config.flags & SMSC911X_FORCE_EXTERNAL_PHY) { - SMSC_TRACE(HW, "Forcing external PHY"); + SMSC_TRACE(pdata, hw, "Forcing external PHY"); smsc911x_phy_enable_external(pdata); pdata->using_extphy = 1; } else if (hwcfg & HW_CFG_EXT_PHY_DET_) { - SMSC_TRACE(HW, "HW_CFG EXT_PHY_DET set, using external PHY"); + SMSC_TRACE(pdata, hw, + "HW_CFG EXT_PHY_DET set, using external PHY"); smsc911x_phy_enable_external(pdata); pdata->using_extphy = 1; } else { - SMSC_TRACE(HW, "HW_CFG EXT_PHY_DET clear, using internal PHY"); + SMSC_TRACE(pdata, hw, + "HW_CFG EXT_PHY_DET clear, using internal PHY"); pdata->using_extphy = 0; } } @@ -509,13 +510,13 @@ static int smsc911x_phy_check_loopbackpkt(struct smsc911x_data *pdata) } while ((i--) && (!status)); if (!status) { - SMSC_WARNING(HW, "Failed to transmit " - "during loopback test"); + SMSC_WARN(pdata, hw, + "Failed to transmit during loopback test"); continue; } if (status & TX_STS_ES_) { - SMSC_WARNING(HW, "Transmit encountered " - "errors during loopback test"); + SMSC_WARN(pdata, hw, + "Transmit encountered errors during loopback test"); continue; } @@ -527,13 +528,13 @@ static int smsc911x_phy_check_loopbackpkt(struct smsc911x_data *pdata) } while ((i--) && (!status)); if (!status) { - SMSC_WARNING(HW, - "Failed to receive during loopback test"); + SMSC_WARN(pdata, hw, + "Failed to receive during loopback test"); continue; } if (status & RX_STS_ES_) { - SMSC_WARNING(HW, "Receive encountered " - "errors during loopback test"); + SMSC_WARN(pdata, hw, + "Receive encountered errors during loopback test"); continue; } @@ -546,9 +547,9 @@ static int smsc911x_phy_check_loopbackpkt(struct smsc911x_data *pdata) smsc911x_rx_readfifo(pdata, (unsigned int *)bufp, rdsz); if (pktlength != (MIN_PACKET_SIZE + 4)) { - SMSC_WARNING(HW, "Unexpected packet size " - "during loop back test, size=%d, will retry", - pktlength); + SMSC_WARN(pdata, hw, "Unexpected packet size " + "during loop back test, size=%d, will retry", + pktlength); } else { unsigned int j; int mismatch = 0; @@ -560,12 +561,12 @@ static int smsc911x_phy_check_loopbackpkt(struct smsc911x_data *pdata) } } if (!mismatch) { - SMSC_TRACE(HW, "Successfully verified " + SMSC_TRACE(pdata, hw, "Successfully verified " "loopback packet"); return 0; } else { - SMSC_WARNING(HW, "Data mismatch " - "during loop back test, will retry"); + SMSC_WARN(pdata, hw, "Data mismatch " + "during loop back test, will retry"); } } } @@ -582,7 +583,7 @@ static int smsc911x_phy_reset(struct smsc911x_data *pdata) BUG_ON(!phy_dev); BUG_ON(!phy_dev->bus); - SMSC_TRACE(HW, "Performing PHY BCR Reset"); + SMSC_TRACE(pdata, hw, "Performing PHY BCR Reset"); smsc911x_mii_write(phy_dev->bus, phy_dev->addr, MII_BMCR, BMCR_RESET); do { msleep(1); @@ -591,7 +592,7 @@ static int smsc911x_phy_reset(struct smsc911x_data *pdata) } while ((i--) && (temp & BMCR_RESET)); if (temp & BMCR_RESET) { - SMSC_WARNING(HW, "PHY reset failed to complete."); + SMSC_WARN(pdata, hw, "PHY reset failed to complete"); return -EIO; } /* Extra delay required because the phy may not be completed with @@ -695,11 +696,11 @@ static void smsc911x_phy_update_flowcontrol(struct smsc911x_data *pdata) else afc &= ~0xF; - SMSC_TRACE(HW, "rx pause %s, tx pause %s", - (cap & FLOW_CTRL_RX ? "enabled" : "disabled"), - (cap & FLOW_CTRL_TX ? "enabled" : "disabled")); + SMSC_TRACE(pdata, hw, "rx pause %s, tx pause %s", + (cap & FLOW_CTRL_RX ? "enabled" : "disabled"), + (cap & FLOW_CTRL_TX ? "enabled" : "disabled")); } else { - SMSC_TRACE(HW, "half duplex"); + SMSC_TRACE(pdata, hw, "half duplex"); flow = 0; afc |= 0xF; } @@ -722,17 +723,17 @@ static void smsc911x_phy_adjust_link(struct net_device *dev) if (phy_dev->duplex != pdata->last_duplex) { unsigned int mac_cr; - SMSC_TRACE(HW, "duplex state has changed"); + SMSC_TRACE(pdata, hw, "duplex state has changed"); spin_lock_irqsave(&pdata->mac_lock, flags); mac_cr = smsc911x_mac_read(pdata, MAC_CR); if (phy_dev->duplex) { - SMSC_TRACE(HW, - "configuring for full duplex mode"); + SMSC_TRACE(pdata, hw, + "configuring for full duplex mode"); mac_cr |= MAC_CR_FDPX_; } else { - SMSC_TRACE(HW, - "configuring for half duplex mode"); + SMSC_TRACE(pdata, hw, + "configuring for half duplex mode"); mac_cr &= ~MAC_CR_FDPX_; } smsc911x_mac_write(pdata, MAC_CR, mac_cr); @@ -744,9 +745,9 @@ static void smsc911x_phy_adjust_link(struct net_device *dev) carrier = netif_carrier_ok(dev); if (carrier != pdata->last_carrier) { - SMSC_TRACE(HW, "carrier state has changed"); + SMSC_TRACE(pdata, hw, "carrier state has changed"); if (carrier) { - SMSC_TRACE(HW, "configuring for carrier OK"); + SMSC_TRACE(pdata, hw, "configuring for carrier OK"); if ((pdata->gpio_orig_setting & GPIO_CFG_LED1_EN_) && (!pdata->using_extphy)) { /* Restore original GPIO configuration */ @@ -755,7 +756,7 @@ static void smsc911x_phy_adjust_link(struct net_device *dev) pdata->gpio_setting); } } else { - SMSC_TRACE(HW, "configuring for no carrier"); + SMSC_TRACE(pdata, hw, "configuring for no carrier"); /* Check global setting that LED1 * usage is 10/100 indicator */ pdata->gpio_setting = smsc911x_reg_read(pdata, @@ -787,25 +788,25 @@ static int smsc911x_mii_probe(struct net_device *dev) /* find the first phy */ phydev = phy_find_first(pdata->mii_bus); if (!phydev) { - pr_err("%s: no PHY found\n", dev->name); + netdev_err(dev, "no PHY found\n"); return -ENODEV; } - SMSC_TRACE(PROBE, "PHY: addr %d, phy_id 0x%08X", - phydev->addr, phydev->phy_id); + SMSC_TRACE(pdata, probe, "PHY: addr %d, phy_id 0x%08X", + phydev->addr, phydev->phy_id); ret = phy_connect_direct(dev, phydev, &smsc911x_phy_adjust_link, 0, pdata->config.phy_interface); if (ret) { - pr_err("%s: Could not attach to PHY\n", dev->name); + netdev_err(dev, "Could not attach to PHY\n"); return ret; } - pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, - dev_name(&phydev->dev), phydev->irq); + netdev_info(dev, + "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", + phydev->drv->name, dev_name(&phydev->dev), phydev->irq); /* mask with MAC supported features */ phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause | @@ -818,13 +819,13 @@ static int smsc911x_mii_probe(struct net_device *dev) #ifdef USE_PHY_WORK_AROUND if (smsc911x_phy_loopbacktest(dev) < 0) { - SMSC_WARNING(HW, "Failed Loop Back Test"); + SMSC_WARN(pdata, hw, "Failed Loop Back Test"); return -ENODEV; } - SMSC_TRACE(HW, "Passed Loop Back Test"); + SMSC_TRACE(pdata, hw, "Passed Loop Back Test"); #endif /* USE_PHY_WORK_AROUND */ - SMSC_TRACE(HW, "phy initialised successfully"); + SMSC_TRACE(pdata, hw, "phy initialised successfully"); return 0; } @@ -860,8 +861,8 @@ static int __devinit smsc911x_mii_init(struct platform_device *pdev, smsc911x_phy_initialise_external(pdata); break; default: - SMSC_TRACE(HW, "External PHY is not supported, " - "using internal PHY"); + SMSC_TRACE(pdata, hw, "External PHY is not supported, " + "using internal PHY"); pdata->using_extphy = 0; break; } @@ -872,12 +873,12 @@ static int __devinit smsc911x_mii_init(struct platform_device *pdev, } if (mdiobus_register(pdata->mii_bus)) { - SMSC_WARNING(PROBE, "Error registering mii bus"); + SMSC_WARN(pdata, probe, "Error registering mii bus"); goto err_out_free_bus_2; } if (smsc911x_mii_probe(dev) < 0) { - SMSC_WARNING(PROBE, "Error registering mii bus"); + SMSC_WARN(pdata, probe, "Error registering mii bus"); goto err_out_unregister_bus_3; } @@ -913,8 +914,7 @@ static void smsc911x_tx_update_txcounters(struct net_device *dev) * does not reference a hardware defined reserved bit * but rather a driver defined one. */ - SMSC_WARNING(HW, - "Packet tag reserved bit is high"); + SMSC_WARN(pdata, hw, "Packet tag reserved bit is high"); } else { if (unlikely(tx_stat & TX_STS_ES_)) { dev->stats.tx_errors++; @@ -977,8 +977,8 @@ smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktbytes) } while ((val & RX_DP_CTRL_RX_FFWD_) && --timeout); if (unlikely(timeout == 0)) - SMSC_WARNING(HW, "Timed out waiting for " - "RX FFWD to finish, RX_DP_CTRL: 0x%08X", val); + SMSC_WARN(pdata, hw, "Timed out waiting for " + "RX FFWD to finish, RX_DP_CTRL: 0x%08X", val); } else { unsigned int temp; while (pktwords--) @@ -1021,8 +1021,8 @@ static int smsc911x_poll(struct napi_struct *napi, int budget) smsc911x_rx_counterrors(dev, rxstat); if (unlikely(rxstat & RX_STS_ES_)) { - SMSC_WARNING(RX_ERR, - "Discarding packet with error bit set"); + SMSC_WARN(pdata, rx_err, + "Discarding packet with error bit set"); /* Packet has an error, discard it and continue with * the next */ smsc911x_rx_fastforward(pdata, pktwords); @@ -1032,8 +1032,8 @@ static int smsc911x_poll(struct napi_struct *napi, int budget) skb = netdev_alloc_skb(dev, pktlength + NET_IP_ALIGN); if (unlikely(!skb)) { - SMSC_WARNING(RX_ERR, - "Unable to allocate skb for rx packet"); + SMSC_WARN(pdata, rx_err, + "Unable to allocate skb for rx packet"); /* Drop the packet and stop this polling iteration */ smsc911x_rx_fastforward(pdata, pktwords); dev->stats.rx_dropped++; @@ -1083,8 +1083,8 @@ static void smsc911x_rx_multicast_update(struct smsc911x_data *pdata) smsc911x_mac_write(pdata, MAC_CR, mac_cr); smsc911x_mac_write(pdata, HASHH, pdata->hashhi); smsc911x_mac_write(pdata, HASHL, pdata->hashlo); - SMSC_TRACE(HW, "maccr 0x%08X, HASHH 0x%08X, HASHL 0x%08X", - mac_cr, pdata->hashhi, pdata->hashlo); + SMSC_TRACE(pdata, hw, "maccr 0x%08X, HASHH 0x%08X, HASHL 0x%08X", + mac_cr, pdata->hashhi, pdata->hashlo); } static void smsc911x_rx_multicast_update_workaround(struct smsc911x_data *pdata) @@ -1102,7 +1102,7 @@ static void smsc911x_rx_multicast_update_workaround(struct smsc911x_data *pdata) /* Check Rx has stopped */ if (smsc911x_mac_read(pdata, MAC_CR) & MAC_CR_RXEN_) - SMSC_WARNING(DRV, "Rx not stopped"); + SMSC_WARN(pdata, drv, "Rx not stopped"); /* Perform the update - safe to do now Rx has stopped */ smsc911x_rx_multicast_update(pdata); @@ -1131,7 +1131,7 @@ static int smsc911x_soft_reset(struct smsc911x_data *pdata) } while ((--timeout) && (temp & HW_CFG_SRST_)); if (unlikely(temp & HW_CFG_SRST_)) { - SMSC_WARNING(DRV, "Failed to complete reset"); + SMSC_WARN(pdata, drv, "Failed to complete reset"); return -EIO; } return 0; @@ -1160,18 +1160,18 @@ static int smsc911x_open(struct net_device *dev) /* if the phy is not yet registered, retry later*/ if (!pdata->phy_dev) { - SMSC_WARNING(HW, "phy_dev is NULL"); + SMSC_WARN(pdata, hw, "phy_dev is NULL"); return -EAGAIN; } if (!is_valid_ether_addr(dev->dev_addr)) { - SMSC_WARNING(HW, "dev_addr is not a valid MAC address"); + SMSC_WARN(pdata, hw, "dev_addr is not a valid MAC address"); return -EADDRNOTAVAIL; } /* Reset the LAN911x */ if (smsc911x_soft_reset(pdata)) { - SMSC_WARNING(HW, "soft reset failed"); + SMSC_WARN(pdata, hw, "soft reset failed"); return -EIO; } @@ -1191,8 +1191,8 @@ static int smsc911x_open(struct net_device *dev) } if (unlikely(timeout == 0)) - SMSC_WARNING(IFUP, - "Timed out waiting for EEPROM busy bit to clear"); + SMSC_WARN(pdata, ifup, + "Timed out waiting for EEPROM busy bit to clear"); smsc911x_reg_write(pdata, GPIO_CFG, 0x70070000); @@ -1210,22 +1210,22 @@ static int smsc911x_open(struct net_device *dev) intcfg = ((10 << 24) | INT_CFG_IRQ_EN_); if (pdata->config.irq_polarity) { - SMSC_TRACE(IFUP, "irq polarity: active high"); + SMSC_TRACE(pdata, ifup, "irq polarity: active high"); intcfg |= INT_CFG_IRQ_POL_; } else { - SMSC_TRACE(IFUP, "irq polarity: active low"); + SMSC_TRACE(pdata, ifup, "irq polarity: active low"); } if (pdata->config.irq_type) { - SMSC_TRACE(IFUP, "irq type: push-pull"); + SMSC_TRACE(pdata, ifup, "irq type: push-pull"); intcfg |= INT_CFG_IRQ_TYPE_; } else { - SMSC_TRACE(IFUP, "irq type: open drain"); + SMSC_TRACE(pdata, ifup, "irq type: open drain"); } smsc911x_reg_write(pdata, INT_CFG, intcfg); - SMSC_TRACE(IFUP, "Testing irq handler using IRQ %d", dev->irq); + SMSC_TRACE(pdata, ifup, "Testing irq handler using IRQ %d", dev->irq); pdata->software_irq_signal = 0; smp_wmb(); @@ -1241,14 +1241,15 @@ static int smsc911x_open(struct net_device *dev) } if (!pdata->software_irq_signal) { - dev_warn(&dev->dev, "ISR failed signaling test (IRQ %d)\n", - dev->irq); + netdev_warn(dev, "ISR failed signaling test (IRQ %d)\n", + dev->irq); return -ENODEV; } - SMSC_TRACE(IFUP, "IRQ handler passed test using IRQ %d", dev->irq); + SMSC_TRACE(pdata, ifup, "IRQ handler passed test using IRQ %d", + dev->irq); - dev_info(&dev->dev, "SMSC911x/921x identified at %#08lx, IRQ: %d\n", - (unsigned long)pdata->ioaddr, dev->irq); + netdev_info(dev, "SMSC911x/921x identified at %#08lx, IRQ: %d\n", + (unsigned long)pdata->ioaddr, dev->irq); /* Reset the last known duplex and carrier */ pdata->last_duplex = -1; @@ -1313,7 +1314,7 @@ static int smsc911x_stop(struct net_device *dev) if (pdata->phy_dev) phy_stop(pdata->phy_dev); - SMSC_TRACE(IFDOWN, "Interface stopped"); + SMSC_TRACE(pdata, ifdown, "Interface stopped"); return 0; } @@ -1331,8 +1332,8 @@ static int smsc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) freespace = smsc911x_reg_read(pdata, TX_FIFO_INF) & TX_FIFO_INF_TDFREE_; if (unlikely(freespace < TX_FIFO_LOW_THRESHOLD)) - SMSC_WARNING(TX_ERR, - "Tx data fifo low, space available: %d", freespace); + SMSC_WARN(pdata, tx_err, + "Tx data fifo low, space available: %d", freespace); /* Word alignment adjustment */ tx_cmd_a = (u32)((ulong)skb->data & 0x03) << 16; @@ -1432,7 +1433,7 @@ static void smsc911x_set_multicast_list(struct net_device *dev) * receiving data */ if (!pdata->multicast_update_pending) { unsigned int temp; - SMSC_TRACE(HW, "scheduling mcast update"); + SMSC_TRACE(pdata, hw, "scheduling mcast update"); pdata->multicast_update_pending = 1; /* Request the hardware to stop, then perform the @@ -1474,7 +1475,7 @@ static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id) if (unlikely(intsts & inten & INT_STS_RXSTOP_INT_)) { /* Called when there is a multicast update scheduled and * it is now safe to complete the update */ - SMSC_TRACE(INTR, "RX Stop interrupt"); + SMSC_TRACE(pdata, intr, "RX Stop interrupt"); smsc911x_reg_write(pdata, INT_STS, INT_STS_RXSTOP_INT_); if (pdata->multicast_update_pending) smsc911x_rx_multicast_update_workaround(pdata); @@ -1491,7 +1492,7 @@ static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id) } if (unlikely(intsts & inten & INT_STS_RXE_)) { - SMSC_TRACE(INTR, "RX Error interrupt"); + SMSC_TRACE(pdata, intr, "RX Error interrupt"); smsc911x_reg_write(pdata, INT_STS, INT_STS_RXE_); serviced = IRQ_HANDLED; } @@ -1505,8 +1506,7 @@ static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id) /* Schedule a NAPI poll */ __napi_schedule(&pdata->napi); } else { - SMSC_WARNING(RX_ERR, - "napi_schedule_prep failed"); + SMSC_WARN(pdata, rx_err, "napi_schedule_prep failed"); } serviced = IRQ_HANDLED; } @@ -1543,7 +1543,7 @@ static int smsc911x_set_mac_address(struct net_device *dev, void *p) smsc911x_set_hw_mac_address(pdata, dev->dev_addr); spin_unlock_irq(&pdata->mac_lock); - dev_info(&dev->dev, "MAC Address: %pM\n", dev->dev_addr); + netdev_info(dev, "MAC Address: %pM\n", dev->dev_addr); return 0; } @@ -1649,9 +1649,9 @@ static int smsc911x_eeprom_send_cmd(struct smsc911x_data *pdata, u32 op) int timeout = 100; u32 e2cmd; - SMSC_TRACE(DRV, "op 0x%08x", op); + SMSC_TRACE(pdata, drv, "op 0x%08x", op); if (smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_) { - SMSC_WARNING(DRV, "Busy at start"); + SMSC_WARN(pdata, drv, "Busy at start"); return -EBUSY; } @@ -1664,12 +1664,12 @@ static int smsc911x_eeprom_send_cmd(struct smsc911x_data *pdata, u32 op) } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (--timeout)); if (!timeout) { - SMSC_TRACE(DRV, "TIMED OUT"); + SMSC_TRACE(pdata, drv, "TIMED OUT"); return -EAGAIN; } if (e2cmd & E2P_CMD_EPC_TIMEOUT_) { - SMSC_TRACE(DRV, "Error occured during eeprom operation"); + SMSC_TRACE(pdata, drv, "Error occured during eeprom operation"); return -EINVAL; } @@ -1682,7 +1682,7 @@ static int smsc911x_eeprom_read_location(struct smsc911x_data *pdata, u32 op = E2P_CMD_EPC_CMD_READ_ | address; int ret; - SMSC_TRACE(DRV, "address 0x%x", address); + SMSC_TRACE(pdata, drv, "address 0x%x", address); ret = smsc911x_eeprom_send_cmd(pdata, op); if (!ret) @@ -1698,7 +1698,7 @@ static int smsc911x_eeprom_write_location(struct smsc911x_data *pdata, u32 temp; int ret; - SMSC_TRACE(DRV, "address 0x%x, data 0x%x", address, data); + SMSC_TRACE(pdata, drv, "address 0x%x, data 0x%x", address, data); ret = smsc911x_eeprom_send_cmd(pdata, op); if (!ret) { @@ -1811,25 +1811,25 @@ static int __devinit smsc911x_init(struct net_device *dev) struct smsc911x_data *pdata = netdev_priv(dev); unsigned int byte_test; - SMSC_TRACE(PROBE, "Driver Parameters:"); - SMSC_TRACE(PROBE, "LAN base: 0x%08lX", - (unsigned long)pdata->ioaddr); - SMSC_TRACE(PROBE, "IRQ: %d", dev->irq); - SMSC_TRACE(PROBE, "PHY will be autodetected."); + SMSC_TRACE(pdata, probe, "Driver Parameters:"); + SMSC_TRACE(pdata, probe, "LAN base: 0x%08lX", + (unsigned long)pdata->ioaddr); + SMSC_TRACE(pdata, probe, "IRQ: %d", dev->irq); + SMSC_TRACE(pdata, probe, "PHY will be autodetected."); spin_lock_init(&pdata->dev_lock); if (pdata->ioaddr == 0) { - SMSC_WARNING(PROBE, "pdata->ioaddr: 0x00000000"); + SMSC_WARN(pdata, probe, "pdata->ioaddr: 0x00000000"); return -ENODEV; } /* Check byte ordering */ byte_test = smsc911x_reg_read(pdata, BYTE_TEST); - SMSC_TRACE(PROBE, "BYTE_TEST: 0x%08X", byte_test); + SMSC_TRACE(pdata, probe, "BYTE_TEST: 0x%08X", byte_test); if (byte_test == 0x43218765) { - SMSC_TRACE(PROBE, "BYTE_TEST looks swapped, " - "applying WORD_SWAP"); + SMSC_TRACE(pdata, probe, "BYTE_TEST looks swapped, " + "applying WORD_SWAP"); smsc911x_reg_write(pdata, WORD_SWAP, 0xffffffff); /* 1 dummy read of BYTE_TEST is needed after a write to @@ -1840,12 +1840,13 @@ static int __devinit smsc911x_init(struct net_device *dev) } if (byte_test != 0x87654321) { - SMSC_WARNING(DRV, "BYTE_TEST: 0x%08X", byte_test); + SMSC_WARN(pdata, drv, "BYTE_TEST: 0x%08X", byte_test); if (((byte_test >> 16) & 0xFFFF) == (byte_test & 0xFFFF)) { - SMSC_WARNING(PROBE, - "top 16 bits equal to bottom 16 bits"); - SMSC_TRACE(PROBE, "This may mean the chip is set " - "for 32 bit while the bus is reading 16 bit"); + SMSC_WARN(pdata, probe, + "top 16 bits equal to bottom 16 bits"); + SMSC_TRACE(pdata, probe, + "This may mean the chip is set " + "for 32 bit while the bus is reading 16 bit"); } return -ENODEV; } @@ -1880,17 +1881,18 @@ static int __devinit smsc911x_init(struct net_device *dev) break; default: - SMSC_WARNING(PROBE, "LAN911x not identified, idrev: 0x%08X", - pdata->idrev); + SMSC_WARN(pdata, probe, "LAN911x not identified, idrev: 0x%08X", + pdata->idrev); return -ENODEV; } - SMSC_TRACE(PROBE, "LAN911x identified, idrev: 0x%08X, generation: %d", - pdata->idrev, pdata->generation); + SMSC_TRACE(pdata, probe, + "LAN911x identified, idrev: 0x%08X, generation: %d", + pdata->idrev, pdata->generation); if (pdata->generation == 0) - SMSC_WARNING(PROBE, - "This driver is not intended for this chip revision"); + SMSC_WARN(pdata, probe, + "This driver is not intended for this chip revision"); /* workaround for platforms without an eeprom, where the mac address * is stored elsewhere and set by the bootloader. This saves the @@ -1927,7 +1929,7 @@ static int __devexit smsc911x_drv_remove(struct platform_device *pdev) BUG_ON(!pdata->ioaddr); BUG_ON(!pdata->phy_dev); - SMSC_TRACE(IFDOWN, "Stopping driver."); + SMSC_TRACE(pdata, ifdown, "Stopping driver"); phy_disconnect(pdata->phy_dev); pdata->phy_dev = NULL; @@ -1961,11 +1963,11 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) int res_size, irq_flags; int retval; - pr_info("%s: Driver version %s.\n", SMSC_CHIPNAME, SMSC_DRV_VERSION); + pr_info("Driver version %s\n", SMSC_DRV_VERSION); /* platform data specifies irq & dynamic bus configuration */ if (!pdev->dev.platform_data) { - pr_warning("%s: platform_data not provided\n", SMSC_CHIPNAME); + pr_warn("platform_data not provided\n"); retval = -ENODEV; goto out_0; } @@ -1975,8 +1977,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) if (!res) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { - pr_warning("%s: Could not allocate resource.\n", - SMSC_CHIPNAME); + pr_warn("Could not allocate resource\n"); retval = -ENODEV; goto out_0; } @@ -1984,8 +1985,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq_res) { - pr_warning("%s: Could not allocate irq resource.\n", - SMSC_CHIPNAME); + pr_warn("Could not allocate irq resource\n"); retval = -ENODEV; goto out_0; } @@ -1997,7 +1997,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) dev = alloc_etherdev(sizeof(struct smsc911x_data)); if (!dev) { - pr_warning("%s: Could not allocate device.\n", SMSC_CHIPNAME); + pr_warn("Could not allocate device\n"); retval = -ENOMEM; goto out_release_io_1; } @@ -2017,8 +2017,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) pdata->msg_enable = ((1 << debug) - 1); if (pdata->ioaddr == NULL) { - SMSC_WARNING(PROBE, - "Error smsc911x base address invalid"); + SMSC_WARN(pdata, probe, "Error smsc911x base address invalid"); retval = -ENOMEM; goto out_free_netdev_2; } @@ -2043,8 +2042,8 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) retval = request_irq(dev->irq, smsc911x_irqhandler, irq_flags | IRQF_SHARED, dev->name, dev); if (retval) { - SMSC_WARNING(PROBE, - "Unable to claim requested irq: %d", dev->irq); + SMSC_WARN(pdata, probe, + "Unable to claim requested irq: %d", dev->irq); goto out_unmap_io_3; } @@ -2052,19 +2051,18 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) retval = register_netdev(dev); if (retval) { - SMSC_WARNING(PROBE, - "Error %i registering device", retval); + SMSC_WARN(pdata, probe, "Error %i registering device", retval); goto out_unset_drvdata_4; } else { - SMSC_TRACE(PROBE, "Network interface: \"%s\"", dev->name); + SMSC_TRACE(pdata, probe, + "Network interface: \"%s\"", dev->name); } spin_lock_init(&pdata->mac_lock); retval = smsc911x_mii_init(pdev, dev); if (retval) { - SMSC_WARNING(PROBE, - "Error %i initialising mii", retval); + SMSC_WARN(pdata, probe, "Error %i initialising mii", retval); goto out_unregister_netdev_5; } @@ -2073,10 +2071,12 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) /* Check if mac address has been specified when bringing interface up */ if (is_valid_ether_addr(dev->dev_addr)) { smsc911x_set_hw_mac_address(pdata, dev->dev_addr); - SMSC_TRACE(PROBE, "MAC Address is specified by configuration"); + SMSC_TRACE(pdata, probe, + "MAC Address is specified by configuration"); } else if (is_valid_ether_addr(pdata->config.mac)) { memcpy(dev->dev_addr, pdata->config.mac, 6); - SMSC_TRACE(PROBE, "MAC Address specified by platform data"); + SMSC_TRACE(pdata, probe, + "MAC Address specified by platform data"); } else { /* Try reading mac address from device. if EEPROM is present * it will already have been set */ @@ -2084,20 +2084,20 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) if (is_valid_ether_addr(dev->dev_addr)) { /* eeprom values are valid so use them */ - SMSC_TRACE(PROBE, - "Mac Address is read from LAN911x EEPROM"); + SMSC_TRACE(pdata, probe, + "Mac Address is read from LAN911x EEPROM"); } else { /* eeprom values are invalid, generate random MAC */ random_ether_addr(dev->dev_addr); smsc911x_set_hw_mac_address(pdata, dev->dev_addr); - SMSC_TRACE(PROBE, - "MAC Address is set to random_ether_addr"); + SMSC_TRACE(pdata, probe, + "MAC Address is set to random_ether_addr"); } } spin_unlock_irq(&pdata->mac_lock); - dev_info(&dev->dev, "MAC Address: %pM\n", dev->dev_addr); + netdev_info(dev, "MAC Address: %pM\n", dev->dev_addr); return 0; diff --git a/drivers/net/smsc911x.h b/drivers/net/smsc911x.h index 50f712e99e96..8d67aacf8867 100644 --- a/drivers/net/smsc911x.h +++ b/drivers/net/smsc911x.h @@ -33,25 +33,21 @@ * can be successfully looped back */ #define USE_PHY_WORK_AROUND -#define DPRINTK(nlevel, klevel, fmt, args...) \ - ((void)((NETIF_MSG_##nlevel & pdata->msg_enable) && \ - printk(KERN_##klevel "%s: %s: " fmt "\n", \ - pdata->dev->name, __func__, ## args))) - #if USE_DEBUG >= 1 -#define SMSC_WARNING(nlevel, fmt, args...) \ - DPRINTK(nlevel, WARNING, fmt, ## args) +#define SMSC_WARN(pdata, nlevel, fmt, args...) \ + netif_warn(pdata, nlevel, (pdata)->dev, \ + "%s: " fmt "\n", __func__, ##args) #else -#define SMSC_WARNING(nlevel, fmt, args...) \ - ({ do {} while (0); 0; }) +#define SMSC_WARN(pdata, nlevel, fmt, args...) \ + no_printk(fmt "\n", ##args) #endif #if USE_DEBUG >= 2 -#define SMSC_TRACE(nlevel, fmt, args...) \ - DPRINTK(nlevel, INFO, fmt, ## args) +#define SMSC_TRACE(pdata, nlevel, fmt, args...) \ + netif_info(pdata, nlevel, pdata->dev, fmt "\n", ##args) #else -#define SMSC_TRACE(nlevel, fmt, args...) \ - ({ do {} while (0); 0; }) +#define SMSC_TRACE(pdata, nlevel, fmt, args...) \ + no_printk(fmt "\n", ##args) #endif #ifdef CONFIG_DEBUG_SPINLOCK -- cgit v1.2.3-58-ga151 From 19eccc2bc6ad3b1c81d0826a77955500be972504 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 27 Mar 2011 02:58:35 +0000 Subject: kstrtox: convert drivers/isdn/ Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/isdn/gigaset/ev-layer.c | 26 +++++++++----------------- drivers/isdn/hysdn/hysdn_proclog.c | 11 ++++------- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index a14187605f5e..ba74646cf0e4 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -390,12 +390,12 @@ static const struct zsau_resp_t { */ static int cid_of_response(char *s) { - unsigned long cid; + int cid; int rc; if (s[-1] != ';') return 0; /* no CID separator */ - rc = strict_strtoul(s, 10, &cid); + rc = kstrtoint(s, 10, &cid); if (rc) return 0; /* CID not numeric */ if (cid < 1 || cid > 65535) @@ -566,27 +566,19 @@ void gigaset_handle_modem_response(struct cardstate *cs) case RT_ZCAU: event->parameter = -1; if (curarg + 1 < params) { - unsigned long type, value; - - i = strict_strtoul(argv[curarg++], 16, &type); - j = strict_strtoul(argv[curarg++], 16, &value); + u8 type, value; - if (i == 0 && type < 256 && - j == 0 && value < 256) + i = kstrtou8(argv[curarg++], 16, &type); + j = kstrtou8(argv[curarg++], 16, &value); + if (i == 0 && j == 0) event->parameter = (type << 8) | value; } else curarg = params - 1; break; case RT_NUMBER: - event->parameter = -1; - if (curarg < params) { - unsigned long res; - int rc; - - rc = strict_strtoul(argv[curarg++], 10, &res); - if (rc == 0) - event->parameter = res; - } + if (curarg >= params || + kstrtoint(argv[curarg++], 10, &event->parameter)) + event->parameter = -1; gig_dbg(DEBUG_EVENT, "parameter==%d", event->parameter); break; } diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c index 2ee93d04b2dd..236cc7dadfd0 100644 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c @@ -155,7 +155,6 @@ put_log_buffer(hysdn_card * card, char *cp) static ssize_t hysdn_log_write(struct file *file, const char __user *buf, size_t count, loff_t * off) { - unsigned long u = 0; int rc; unsigned char valbuf[128]; hysdn_card *card = file->private_data; @@ -167,12 +166,10 @@ hysdn_log_write(struct file *file, const char __user *buf, size_t count, loff_t valbuf[count] = 0; /* terminating 0 */ - rc = strict_strtoul(valbuf, 0, &u); - - if (rc == 0) { - card->debug_flags = u; /* remember debug flags */ - hysdn_addlog(card, "debug set to 0x%lx", card->debug_flags); - } + rc = kstrtoul(valbuf, 0, &card->debug_flags); + if (rc < 0) + return rc; + hysdn_addlog(card, "debug set to 0x%lx", card->debug_flags); return (count); } /* hysdn_log_write */ -- cgit v1.2.3-58-ga151 From 4562b2fe1ebc7c547746660f735ff9af964f28ad Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Mon, 28 Mar 2011 17:08:59 +0000 Subject: via-rhine: trivial sparse annotation in vlan_tci helper Noticed by sparse: drivers/net/via-rhine.c:1706:16: warning: cast to restricted __be16 Signed-off-by: Harvey Harrison Signed-off-by: David S. Miller --- drivers/net/via-rhine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 5e7f069eab53..707f7f8beb6f 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1703,7 +1703,7 @@ static void rhine_tx(struct net_device *dev) static inline u16 rhine_get_vlan_tci(struct sk_buff *skb, int data_size) { u8 *trailer = (u8 *)skb->data + ((data_size + 3) & ~3) + 2; - return ntohs(*(u16 *)trailer); + return be16_to_cpup((__be16 *)trailer); } /* Process up to limit frames from receive ring */ -- cgit v1.2.3-58-ga151 From 9085fd09859fafbde17380b93d317a13c23c39af Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 29 Mar 2011 20:35:51 +0000 Subject: enic: Add support for new fw devcmds for port profile handling This patch introduces new fw devcmds for port profile handling. These new commands are similar to the current fw commands for port profile handling. The only difference being that the new commands split the existing port profile handling devcmds into multiple fw commands, giving the driver finer control over port profile operations. Signed-off-by: Roopa Prabhu Signed-off-by: David Wang Signed-off-by: Christian Benvenuti Signed-off-by: David S. Miller --- drivers/net/enic/vnic_dev.c | 97 ++++++++++++++++++++++++------------------ drivers/net/enic/vnic_dev.h | 6 ++- drivers/net/enic/vnic_devcmd.h | 57 ++++++++++++++++++++++--- 3 files changed, 111 insertions(+), 49 deletions(-) diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c index c089b362a36f..68f24ae860ae 100644 --- a/drivers/net/enic/vnic_dev.c +++ b/drivers/net/enic/vnic_dev.c @@ -786,48 +786,6 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg) return r; } -int vnic_dev_init_done(struct vnic_dev *vdev, int *done, int *err) -{ - u64 a0 = 0, a1 = 0; - int wait = 1000; - int ret; - - *done = 0; - - ret = vnic_dev_cmd(vdev, CMD_INIT_STATUS, &a0, &a1, wait); - if (ret) - return ret; - - *done = (a0 == 0); - - *err = (a0 == 0) ? (int)a1:0; - - return 0; -} - -int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len) -{ - u64 a0, a1 = len; - int wait = 1000; - dma_addr_t prov_pa; - void *prov_buf; - int ret; - - prov_buf = pci_alloc_consistent(vdev->pdev, len, &prov_pa); - if (!prov_buf) - return -ENOMEM; - - memcpy(prov_buf, buf, len); - - a0 = prov_pa; - - ret = vnic_dev_cmd(vdev, CMD_INIT_PROV_INFO, &a0, &a1, wait); - - pci_free_consistent(vdev->pdev, len, prov_buf, prov_pa); - - return ret; -} - int vnic_dev_deinit(struct vnic_dev *vdev) { u64 a0 = 0, a1 = 0; @@ -927,4 +885,59 @@ err_out: return NULL; } +int vnic_dev_init_prov2(struct vnic_dev *vdev, u8 *buf, u32 len) +{ + u64 a0, a1 = len; + int wait = 1000; + dma_addr_t prov_pa; + void *prov_buf; + int ret; + + prov_buf = pci_alloc_consistent(vdev->pdev, len, &prov_pa); + if (!prov_buf) + return -ENOMEM; + memcpy(prov_buf, buf, len); + + a0 = prov_pa; + + ret = vnic_dev_cmd(vdev, CMD_INIT_PROV_INFO2, &a0, &a1, wait); + + pci_free_consistent(vdev->pdev, len, prov_buf, prov_pa); + + return ret; +} + +int vnic_dev_enable2(struct vnic_dev *vdev, int active) +{ + u64 a0, a1 = 0; + int wait = 1000; + + a0 = (active ? CMD_ENABLE2_ACTIVE : 0); + + return vnic_dev_cmd(vdev, CMD_ENABLE2, &a0, &a1, wait); +} + +static int vnic_dev_cmd_status(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, + int *status) +{ + u64 a0 = cmd, a1 = 0; + int wait = 1000; + int ret; + + ret = vnic_dev_cmd(vdev, CMD_STATUS, &a0, &a1, wait); + if (!ret) + *status = (int)a0; + + return ret; +} + +int vnic_dev_enable2_done(struct vnic_dev *vdev, int *status) +{ + return vnic_dev_cmd_status(vdev, CMD_ENABLE2, status); +} + +int vnic_dev_deinit_done(struct vnic_dev *vdev, int *status) +{ + return vnic_dev_cmd_status(vdev, CMD_DEINIT, status); +} diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h index e837546213a8..cf482a2c9dd9 100644 --- a/drivers/net/enic/vnic_dev.h +++ b/drivers/net/enic/vnic_dev.h @@ -108,8 +108,6 @@ int vnic_dev_disable(struct vnic_dev *vdev); int vnic_dev_open(struct vnic_dev *vdev, int arg); int vnic_dev_open_done(struct vnic_dev *vdev, int *done); int vnic_dev_init(struct vnic_dev *vdev, int arg); -int vnic_dev_init_done(struct vnic_dev *vdev, int *done, int *err); -int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len); int vnic_dev_deinit(struct vnic_dev *vdev); int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg); int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done); @@ -122,5 +120,9 @@ int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev, struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev, void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar, unsigned int num_bars); +int vnic_dev_init_prov2(struct vnic_dev *vdev, u8 *buf, u32 len); +int vnic_dev_enable2(struct vnic_dev *vdev, int active); +int vnic_dev_enable2_done(struct vnic_dev *vdev, int *status); +int vnic_dev_deinit_done(struct vnic_dev *vdev, int *status); #endif /* _VNIC_DEV_H_ */ diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h index d833a071bac5..c5569bfb47ac 100644 --- a/drivers/net/enic/vnic_devcmd.h +++ b/drivers/net/enic/vnic_devcmd.h @@ -267,17 +267,62 @@ enum vnic_devcmd_cmd { /* * As for BY_BDF except a0 is index of hvnlink subordinate vnic - * or SR-IOV virtual vnic */ + * or SR-IOV virtual vnic + */ CMD_PROXY_BY_INDEX = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 43), /* - * in: (u64)a0=paddr of buffer to put latest VIC VIF-CONFIG-INFO TLV in - * (u32)a1=length of buffer in a0 - * out: (u64)a0=paddr of buffer with latest VIC VIF-CONFIG-INFO TLV - * (u32)a1=actual length of latest VIC VIF-CONFIG-INFO TLV */ + * For HPP toggle: + * adapter-info-get + * in: (u64)a0=phsical address of buffer passed in from caller. + * (u16)a1=size of buffer specified in a0. + * out: (u64)a0=phsical address of buffer passed in from caller. + * (u16)a1=actual bytes from VIF-CONFIG-INFO TLV, or + * 0 if no VIF-CONFIG-INFO TLV was ever received. */ CMD_CONFIG_INFO_GET = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44), + + /* init_prov_info2: + * Variant of CMD_INIT_PROV_INFO, where it will not try to enable + * the vnic until CMD_ENABLE2 is issued. + * (u64)a0=paddr of vnic_devcmd_provinfo + * (u32)a1=sizeof provision info */ + CMD_INIT_PROV_INFO2 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 47), + + /* enable2: + * (u32)a0=0 ==> standby + * =CMD_ENABLE2_ACTIVE ==> active + */ + CMD_ENABLE2 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 48), + + /* + * cmd_status: + * Returns the status of the specified command + * Input: + * a0 = command for which status is being queried. + * Possible values are: + * CMD_SOFT_RESET + * CMD_HANG_RESET + * CMD_OPEN + * CMD_INIT + * CMD_INIT_PROV_INFO + * CMD_DEINIT + * CMD_INIT_PROV_INFO2 + * CMD_ENABLE2 + * Output: + * if status == STAT_ERROR + * a0 = ERR_ENOTSUPPORTED - status for command in a0 is + * not supported + * if status == STAT_NONE + * a0 = status of the devcmd specified in a0 as follows. + * ERR_SUCCESS - command in a0 completed successfully + * ERR_EINPROGRESS - command in a0 is still in progress + */ + CMD_STATUS = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 49), }; +/* CMD_ENABLE2 flags */ +#define CMD_ENABLE2_ACTIVE 0x1 + /* flags for CMD_OPEN */ #define CMD_OPENF_OPROM 0x1 /* open coming from option rom */ @@ -315,6 +360,8 @@ enum vnic_devcmd_error { ERR_ETIMEDOUT = 8, ERR_ELINKDOWN = 9, ERR_EMAXRES = 10, + ERR_ENOTSUPPORTED = 11, + ERR_EINPROGRESS = 12, }; /* -- cgit v1.2.3-58-ga151 From 18714ff8de7a000e7642561cabaf8ace8d082e9f Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 29 Mar 2011 20:35:56 +0000 Subject: enic: Add wrapper routines for new fw devcmds for port profile handling This patch adds wrapper routines to new port profile related fw devcmds and removes the old ones Signed-off-by: Roopa Prabhu Signed-off-by: David Wang Signed-off-by: Christian Benvenuti Signed-off-by: David S. Miller --- drivers/net/enic/enic_dev.c | 62 ++++++++++++++++++++++++++++++++++++++++++--- drivers/net/enic/enic_dev.h | 7 +++-- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/drivers/net/enic/enic_dev.c b/drivers/net/enic/enic_dev.c index 37ad3a1c82ee..90687b14e60f 100644 --- a/drivers/net/enic/enic_dev.c +++ b/drivers/net/enic/enic_dev.c @@ -177,24 +177,24 @@ int enic_vnic_dev_deinit(struct enic *enic) return err; } -int enic_dev_init_prov(struct enic *enic, struct vic_provinfo *vp) +int enic_dev_init_prov2(struct enic *enic, struct vic_provinfo *vp) { int err; spin_lock(&enic->devcmd_lock); - err = vnic_dev_init_prov(enic->vdev, + err = vnic_dev_init_prov2(enic->vdev, (u8 *)vp, vic_provinfo_size(vp)); spin_unlock(&enic->devcmd_lock); return err; } -int enic_dev_init_done(struct enic *enic, int *done, int *error) +int enic_dev_deinit_done(struct enic *enic, int *status) { int err; spin_lock(&enic->devcmd_lock); - err = vnic_dev_init_done(enic->vdev, done, error); + err = vnic_dev_deinit_done(enic->vdev, status); spin_unlock(&enic->devcmd_lock); return err; @@ -219,3 +219,57 @@ void enic_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) enic_del_vlan(enic, vid); spin_unlock(&enic->devcmd_lock); } + +int enic_dev_enable2(struct enic *enic, int active) +{ + int err; + + spin_lock(&enic->devcmd_lock); + err = vnic_dev_enable2(enic->vdev, active); + spin_unlock(&enic->devcmd_lock); + + return err; +} + +int enic_dev_enable2_done(struct enic *enic, int *status) +{ + int err; + + spin_lock(&enic->devcmd_lock); + err = vnic_dev_enable2_done(enic->vdev, status); + spin_unlock(&enic->devcmd_lock); + + return err; +} + +int enic_dev_status_to_errno(int devcmd_status) +{ + switch (devcmd_status) { + case ERR_SUCCESS: + return 0; + case ERR_EINVAL: + return -EINVAL; + case ERR_EFAULT: + return -EFAULT; + case ERR_EPERM: + return -EPERM; + case ERR_EBUSY: + return -EBUSY; + case ERR_ECMDUNKNOWN: + case ERR_ENOTSUPPORTED: + return -EOPNOTSUPP; + case ERR_EBADSTATE: + return -EINVAL; + case ERR_ENOMEM: + return -ENOMEM; + case ERR_ETIMEDOUT: + return -ETIMEDOUT; + case ERR_ELINKDOWN: + return -ENETDOWN; + case ERR_EINPROGRESS: + return -EINPROGRESS; + case ERR_EMAXRES: + default: + return (devcmd_status < 0) ? devcmd_status : -1; + } +} diff --git a/drivers/net/enic/enic_dev.h b/drivers/net/enic/enic_dev.h index 495f57fcb887..d5f681337626 100644 --- a/drivers/net/enic/enic_dev.h +++ b/drivers/net/enic/enic_dev.h @@ -35,7 +35,10 @@ int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic); int enic_dev_enable(struct enic *enic); int enic_dev_disable(struct enic *enic); int enic_vnic_dev_deinit(struct enic *enic); -int enic_dev_init_prov(struct enic *enic, struct vic_provinfo *vp); -int enic_dev_init_done(struct enic *enic, int *done, int *error); +int enic_dev_init_prov2(struct enic *enic, struct vic_provinfo *vp); +int enic_dev_deinit_done(struct enic *enic, int *status); +int enic_dev_enable2(struct enic *enic, int arg); +int enic_dev_enable2_done(struct enic *enic, int *status); +int enic_dev_status_to_errno(int devcmd_status); #endif /* _ENIC_DEV_H_ */ -- cgit v1.2.3-58-ga151 From 756462f3434ec4807a61f884d59358092a03fc15 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 29 Mar 2011 20:36:02 +0000 Subject: enic: Cleanups in port profile helper code This patch does the following: - Introduces a new macro VIC_PROVINFO_ADD_TLV - Adds a new OS type in vic_generic_prov_os_type - Changes some vic_provinfo* helper routine args to constants Signed-off-by: Roopa Prabhu Signed-off-by: David Wang Signed-off-by: Christian Benvenuti Signed-off-by: David S. Miller --- drivers/net/enic/vnic_vic.c | 5 +++-- drivers/net/enic/vnic_vic.h | 13 +++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/enic/vnic_vic.c b/drivers/net/enic/vnic_vic.c index 4725b79de0ef..24ef8cd40545 100644 --- a/drivers/net/enic/vnic_vic.c +++ b/drivers/net/enic/vnic_vic.c @@ -23,7 +23,8 @@ #include "vnic_vic.h" -struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, u8 *oui, u8 type) +struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, const u8 *oui, + const u8 type) { struct vic_provinfo *vp; @@ -47,7 +48,7 @@ void vic_provinfo_free(struct vic_provinfo *vp) } int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length, - void *value) + const void *value) { struct vic_provinfo_tlv *tlv; diff --git a/drivers/net/enic/vnic_vic.h b/drivers/net/enic/vnic_vic.h index f700f5d9e81d..9ef81f148351 100644 --- a/drivers/net/enic/vnic_vic.h +++ b/drivers/net/enic/vnic_vic.h @@ -47,6 +47,7 @@ enum vic_generic_prov_os_type { VIC_GENERIC_PROV_OS_TYPE_ESX = 1, VIC_GENERIC_PROV_OS_TYPE_LINUX = 2, VIC_GENERIC_PROV_OS_TYPE_WINDOWS = 3, + VIC_GENERIC_PROV_OS_TYPE_SOLARIS = 4, }; struct vic_provinfo { @@ -61,14 +62,22 @@ struct vic_provinfo { } tlv[0]; } __packed; +#define VIC_PROVINFO_ADD_TLV(vp, tlvtype, tlvlen, data) \ + do { \ + err = vic_provinfo_add_tlv(vp, tlvtype, tlvlen, data); \ + if (err) \ + goto add_tlv_failure; \ + } while (0) + #define VIC_PROVINFO_MAX_DATA 1385 #define VIC_PROVINFO_MAX_TLV_DATA (VIC_PROVINFO_MAX_DATA - \ sizeof(struct vic_provinfo)) -struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, u8 *oui, u8 type); +struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, const u8 *oui, + const u8 type); void vic_provinfo_free(struct vic_provinfo *vp); int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length, - void *value); + const void *value); size_t vic_provinfo_size(struct vic_provinfo *vp); #endif /* _VNIC_VIC_H_ */ -- cgit v1.2.3-58-ga151 From b3abfbd2951102f5f5b8fe251a672e5223ac972b Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 29 Mar 2011 20:36:07 +0000 Subject: enic: Add support for PORT_REQUEST_PREASSOCIATE_RR Current enic code only supports ASSOCIATE and DISASSOCIATE port profile operations. This patch adds enic support for port profile PORT_REQUEST_PREASSOCIATE_RR operation. The VIC adapter (8021qbh) is capable of handling port profile requests done in two steps namely PREASSOCIATE_RR and ASSOCIATE today. The motivation to support PREASSOCIATE_RR comes mainly from its use as an optimization during VM migration ie, to do resource reservation on destination host before resources on source host are released. PREASSOCIATE_RR is a VDP operation and according to the latest at IEEE, 8021qbh will also need to support VDP commands. In addition to handling the new PORT_REQUEST_PREASSOCIATE_RR operation this patch also does the below: - Introduces handlers for PORT_REQUEST operations - Moves most of the port profile handling code to new files enic_pp.[ch] - Uses new fw devcmds for port profile operations Signed-off-by: Roopa Prabhu Signed-off-by: David Wang Signed-off-by: Christian Benvenuti Signed-off-by: David S. Miller --- drivers/net/enic/Makefile | 2 +- drivers/net/enic/enic.h | 4 +- drivers/net/enic/enic_main.c | 196 ++++++++------------------------ drivers/net/enic/enic_pp.c | 264 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/enic/enic_pp.h | 27 +++++ 5 files changed, 344 insertions(+), 149 deletions(-) create mode 100644 drivers/net/enic/enic_pp.c create mode 100644 drivers/net/enic/enic_pp.h diff --git a/drivers/net/enic/Makefile b/drivers/net/enic/Makefile index 2e573be16c13..9d4974bba247 100644 --- a/drivers/net/enic/Makefile +++ b/drivers/net/enic/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_ENIC) := enic.o enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \ - enic_res.o enic_dev.o vnic_dev.o vnic_rq.o vnic_vic.o + enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index 3a3c3c8a3a9b..178b94d7f89b 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -32,7 +32,7 @@ #define DRV_NAME "enic" #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" -#define DRV_VERSION "2.1.1.12" +#define DRV_VERSION "2.1.1.13" #define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc" #define ENIC_BARS_MAX 6 @@ -120,4 +120,6 @@ static inline struct device *enic_get_dev(struct enic *enic) return &(enic->pdev->dev); } +void enic_reset_addr_lists(struct enic *enic); + #endif /* _ENIC_H_ */ diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 8b9cad5e9712..9a3a0277bf21 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -45,6 +45,7 @@ #include "enic_res.h" #include "enic.h" #include "enic_dev.h" +#include "enic_pp.h" #define ENIC_NOTIFY_TIMER_PERIOD (2 * HZ) #define WQ_ENET_MAX_DESC_LEN (1 << WQ_ENET_LEN_BITS) @@ -874,7 +875,7 @@ static struct net_device_stats *enic_get_stats(struct net_device *netdev) return net_stats; } -static void enic_reset_addr_lists(struct enic *enic) +void enic_reset_addr_lists(struct enic *enic) { enic->mc_count = 0; enic->uc_count = 0; @@ -1112,157 +1113,77 @@ static int enic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) return -EINVAL; } -static int enic_set_port_profile(struct enic *enic, u8 *mac) -{ - struct vic_provinfo *vp; - u8 oui[3] = VIC_PROVINFO_CISCO_OUI; - u16 os_type = VIC_GENERIC_PROV_OS_TYPE_LINUX; - char uuid_str[38]; - char client_mac_str[18]; - u8 *client_mac; - int err; - - err = enic_vnic_dev_deinit(enic); - if (err) - return err; - - enic_reset_addr_lists(enic); - - switch (enic->pp.request) { - - case PORT_REQUEST_ASSOCIATE: - - if (!(enic->pp.set & ENIC_SET_NAME) || !strlen(enic->pp.name)) - return -EINVAL; - - if (!is_valid_ether_addr(mac)) - return -EADDRNOTAVAIL; - - vp = vic_provinfo_alloc(GFP_KERNEL, oui, - VIC_PROVINFO_GENERIC_TYPE); - if (!vp) - return -ENOMEM; - - vic_provinfo_add_tlv(vp, - VIC_GENERIC_PROV_TLV_PORT_PROFILE_NAME_STR, - strlen(enic->pp.name) + 1, enic->pp.name); - - if (!is_zero_ether_addr(enic->pp.mac_addr)) - client_mac = enic->pp.mac_addr; - else - client_mac = mac; - - vic_provinfo_add_tlv(vp, - VIC_GENERIC_PROV_TLV_CLIENT_MAC_ADDR, - ETH_ALEN, client_mac); - - sprintf(client_mac_str, "%pM", client_mac); - vic_provinfo_add_tlv(vp, - VIC_GENERIC_PROV_TLV_CLUSTER_PORT_UUID_STR, - sizeof(client_mac_str), client_mac_str); - - if (enic->pp.set & ENIC_SET_INSTANCE) { - sprintf(uuid_str, "%pUB", enic->pp.instance_uuid); - vic_provinfo_add_tlv(vp, - VIC_GENERIC_PROV_TLV_CLIENT_UUID_STR, - sizeof(uuid_str), uuid_str); - } - - if (enic->pp.set & ENIC_SET_HOST) { - sprintf(uuid_str, "%pUB", enic->pp.host_uuid); - vic_provinfo_add_tlv(vp, - VIC_GENERIC_PROV_TLV_HOST_UUID_STR, - sizeof(uuid_str), uuid_str); - } - - os_type = htons(os_type); - vic_provinfo_add_tlv(vp, - VIC_GENERIC_PROV_TLV_OS_TYPE, - sizeof(os_type), &os_type); - - err = enic_dev_init_prov(enic, vp); - vic_provinfo_free(vp); - if (err) - return err; - break; - - case PORT_REQUEST_DISASSOCIATE: - break; - - default: - return -EINVAL; - } - - /* Set flag to indicate that the port assoc/disassoc - * request has been sent out to fw - */ - enic->pp.set |= ENIC_PORT_REQUEST_APPLIED; - - return 0; -} - static int enic_set_vf_port(struct net_device *netdev, int vf, struct nlattr *port[]) { struct enic *enic = netdev_priv(netdev); - struct enic_port_profile new_pp; - int err = 0; + struct enic_port_profile prev_pp; + int err = 0, restore_pp = 1; - memset(&new_pp, 0, sizeof(new_pp)); + /* don't support VFs, yet */ + if (vf != PORT_SELF_VF) + return -EOPNOTSUPP; - if (port[IFLA_PORT_REQUEST]) { - new_pp.set |= ENIC_SET_REQUEST; - new_pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]); - } + if (!port[IFLA_PORT_REQUEST]) + return -EOPNOTSUPP; + + memcpy(&prev_pp, &enic->pp, sizeof(enic->pp)); + memset(&enic->pp, 0, sizeof(enic->pp)); + + enic->pp.set |= ENIC_SET_REQUEST; + enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]); if (port[IFLA_PORT_PROFILE]) { - new_pp.set |= ENIC_SET_NAME; - memcpy(new_pp.name, nla_data(port[IFLA_PORT_PROFILE]), + enic->pp.set |= ENIC_SET_NAME; + memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]), PORT_PROFILE_MAX); } if (port[IFLA_PORT_INSTANCE_UUID]) { - new_pp.set |= ENIC_SET_INSTANCE; - memcpy(new_pp.instance_uuid, + enic->pp.set |= ENIC_SET_INSTANCE; + memcpy(enic->pp.instance_uuid, nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX); } if (port[IFLA_PORT_HOST_UUID]) { - new_pp.set |= ENIC_SET_HOST; - memcpy(new_pp.host_uuid, + enic->pp.set |= ENIC_SET_HOST; + memcpy(enic->pp.host_uuid, nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX); } - /* don't support VFs, yet */ - if (vf != PORT_SELF_VF) - return -EOPNOTSUPP; - - if (!(new_pp.set & ENIC_SET_REQUEST)) - return -EOPNOTSUPP; - - if (new_pp.request == PORT_REQUEST_ASSOCIATE) { - /* Special case handling */ - if (!is_zero_ether_addr(enic->pp.vf_mac)) - memcpy(new_pp.mac_addr, enic->pp.vf_mac, ETH_ALEN); + /* Special case handling: mac came from IFLA_VF_MAC */ + if (!is_zero_ether_addr(prev_pp.vf_mac)) + memcpy(enic->pp.mac_addr, prev_pp.vf_mac, ETH_ALEN); if (is_zero_ether_addr(netdev->dev_addr)) random_ether_addr(netdev->dev_addr); - } - memcpy(&enic->pp, &new_pp, sizeof(struct enic_port_profile)); + err = enic_process_set_pp_request(enic, &prev_pp, &restore_pp); + if (err) { + if (restore_pp) { + /* Things are still the way they were: Implicit + * DISASSOCIATE failed + */ + memcpy(&enic->pp, &prev_pp, sizeof(enic->pp)); + } else { + memset(&enic->pp, 0, sizeof(enic->pp)); + memset(netdev->dev_addr, 0, ETH_ALEN); + } + } else { + /* Set flag to indicate that the port assoc/disassoc + * request has been sent out to fw + */ + enic->pp.set |= ENIC_PORT_REQUEST_APPLIED; - err = enic_set_port_profile(enic, netdev->dev_addr); - if (err) - goto set_port_profile_cleanup; + /* If DISASSOCIATE, clean up all assigned/saved macaddresses */ + if (enic->pp.request == PORT_REQUEST_DISASSOCIATE) { + memset(enic->pp.mac_addr, 0, ETH_ALEN); + memset(netdev->dev_addr, 0, ETH_ALEN); + } + } -set_port_profile_cleanup: memset(enic->pp.vf_mac, 0, ETH_ALEN); - if (err || enic->pp.request == PORT_REQUEST_DISASSOCIATE) { - memset(netdev->dev_addr, 0, ETH_ALEN); - memset(enic->pp.mac_addr, 0, ETH_ALEN); - } - return err; } @@ -1270,34 +1191,15 @@ static int enic_get_vf_port(struct net_device *netdev, int vf, struct sk_buff *skb) { struct enic *enic = netdev_priv(netdev); - int err, error, done; u16 response = PORT_PROFILE_RESPONSE_SUCCESS; + int err; if (!(enic->pp.set & ENIC_PORT_REQUEST_APPLIED)) return -ENODATA; - err = enic_dev_init_done(enic, &done, &error); + err = enic_process_get_pp_request(enic, enic->pp.request, &response); if (err) - error = err; - - switch (error) { - case ERR_SUCCESS: - if (!done) - response = PORT_PROFILE_RESPONSE_INPROGRESS; - break; - case ERR_EINVAL: - response = PORT_PROFILE_RESPONSE_INVALID; - break; - case ERR_EBADSTATE: - response = PORT_PROFILE_RESPONSE_BADSTATE; - break; - case ERR_ENOMEM: - response = PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES; - break; - default: - response = PORT_PROFILE_RESPONSE_ERROR; - break; - } + return err; NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request); NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response); diff --git a/drivers/net/enic/enic_pp.c b/drivers/net/enic/enic_pp.c new file mode 100644 index 000000000000..ffaa75dd1ded --- /dev/null +++ b/drivers/net/enic/enic_pp.c @@ -0,0 +1,264 @@ +/* + * Copyright 2011 Cisco Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vnic_vic.h" +#include "enic_res.h" +#include "enic.h" +#include "enic_dev.h" + +static int enic_set_port_profile(struct enic *enic) +{ + struct net_device *netdev = enic->netdev; + struct vic_provinfo *vp; + const u8 oui[3] = VIC_PROVINFO_CISCO_OUI; + const u16 os_type = htons(VIC_GENERIC_PROV_OS_TYPE_LINUX); + char uuid_str[38]; + char client_mac_str[18]; + u8 *client_mac; + int err; + + if (!(enic->pp.set & ENIC_SET_NAME) || !strlen(enic->pp.name)) + return -EINVAL; + + vp = vic_provinfo_alloc(GFP_KERNEL, oui, + VIC_PROVINFO_GENERIC_TYPE); + if (!vp) + return -ENOMEM; + + VIC_PROVINFO_ADD_TLV(vp, + VIC_GENERIC_PROV_TLV_PORT_PROFILE_NAME_STR, + strlen(enic->pp.name) + 1, enic->pp.name); + + if (!is_zero_ether_addr(enic->pp.mac_addr)) + client_mac = enic->pp.mac_addr; + else + client_mac = netdev->dev_addr; + + VIC_PROVINFO_ADD_TLV(vp, + VIC_GENERIC_PROV_TLV_CLIENT_MAC_ADDR, + ETH_ALEN, client_mac); + + snprintf(client_mac_str, sizeof(client_mac_str), "%pM", client_mac); + VIC_PROVINFO_ADD_TLV(vp, + VIC_GENERIC_PROV_TLV_CLUSTER_PORT_UUID_STR, + sizeof(client_mac_str), client_mac_str); + + if (enic->pp.set & ENIC_SET_INSTANCE) { + sprintf(uuid_str, "%pUB", enic->pp.instance_uuid); + VIC_PROVINFO_ADD_TLV(vp, + VIC_GENERIC_PROV_TLV_CLIENT_UUID_STR, + sizeof(uuid_str), uuid_str); + } + + if (enic->pp.set & ENIC_SET_HOST) { + sprintf(uuid_str, "%pUB", enic->pp.host_uuid); + VIC_PROVINFO_ADD_TLV(vp, + VIC_GENERIC_PROV_TLV_HOST_UUID_STR, + sizeof(uuid_str), uuid_str); + } + + VIC_PROVINFO_ADD_TLV(vp, + VIC_GENERIC_PROV_TLV_OS_TYPE, + sizeof(os_type), &os_type); + + err = enic_dev_status_to_errno(enic_dev_init_prov2(enic, vp)); + +add_tlv_failure: + vic_provinfo_free(vp); + + return err; +} + +static int enic_unset_port_profile(struct enic *enic) +{ + int err; + + err = enic_vnic_dev_deinit(enic); + if (err) + return enic_dev_status_to_errno(err); + + enic_reset_addr_lists(enic); + + return 0; +} + +static int enic_are_pp_different(struct enic_port_profile *pp1, + struct enic_port_profile *pp2) +{ + return strcmp(pp1->name, pp2->name) | !!memcmp(pp1->instance_uuid, + pp2->instance_uuid, PORT_UUID_MAX) | + !!memcmp(pp1->host_uuid, pp2->host_uuid, PORT_UUID_MAX) | + !!memcmp(pp1->mac_addr, pp2->mac_addr, ETH_ALEN); +} + +static int enic_pp_preassociate(struct enic *enic, + struct enic_port_profile *prev_pp, int *restore_pp); +static int enic_pp_disassociate(struct enic *enic, + struct enic_port_profile *prev_pp, int *restore_pp); +static int enic_pp_preassociate_rr(struct enic *enic, + struct enic_port_profile *prev_pp, int *restore_pp); +static int enic_pp_associate(struct enic *enic, + struct enic_port_profile *prev_pp, int *restore_pp); + +static int (*enic_pp_handlers[])(struct enic *enic, + struct enic_port_profile *prev_state, int *restore_pp) = { + [PORT_REQUEST_PREASSOCIATE] = enic_pp_preassociate, + [PORT_REQUEST_PREASSOCIATE_RR] = enic_pp_preassociate_rr, + [PORT_REQUEST_ASSOCIATE] = enic_pp_associate, + [PORT_REQUEST_DISASSOCIATE] = enic_pp_disassociate, +}; + +static const int enic_pp_handlers_count = + sizeof(enic_pp_handlers)/sizeof(*enic_pp_handlers); + +static int enic_pp_preassociate(struct enic *enic, + struct enic_port_profile *prev_pp, int *restore_pp) +{ + return -EOPNOTSUPP; +} + +static int enic_pp_disassociate(struct enic *enic, + struct enic_port_profile *prev_pp, int *restore_pp) +{ + return enic_unset_port_profile(enic); +} + +static int enic_pp_preassociate_rr(struct enic *enic, + struct enic_port_profile *prev_pp, int *restore_pp) +{ + int err; + int active = 0; + + if (enic->pp.request != PORT_REQUEST_ASSOCIATE) { + /* If pre-associate is not part of an associate. + We always disassociate first */ + err = enic_pp_handlers[PORT_REQUEST_DISASSOCIATE](enic, + prev_pp, restore_pp); + if (err) + return err; + + *restore_pp = 0; + } + + *restore_pp = 0; + + err = enic_set_port_profile(enic); + if (err) + return err; + + /* If pre-associate is not part of an associate. */ + if (enic->pp.request != PORT_REQUEST_ASSOCIATE) + err = enic_dev_status_to_errno(enic_dev_enable2(enic, active)); + + return err; +} + +static int enic_pp_associate(struct enic *enic, + struct enic_port_profile *prev_pp, int *restore_pp) +{ + int err; + int active = 1; + + /* Check if a pre-associate was called before */ + if (prev_pp->request != PORT_REQUEST_PREASSOCIATE_RR || + (prev_pp->request == PORT_REQUEST_PREASSOCIATE_RR && + enic_are_pp_different(prev_pp, &enic->pp))) { + err = enic_pp_handlers[PORT_REQUEST_DISASSOCIATE]( + enic, prev_pp, restore_pp); + if (err) + return err; + + *restore_pp = 0; + } + + err = enic_pp_handlers[PORT_REQUEST_PREASSOCIATE_RR]( + enic, prev_pp, restore_pp); + if (err) + return err; + + *restore_pp = 0; + + return enic_dev_status_to_errno(enic_dev_enable2(enic, active)); +} + +int enic_process_set_pp_request(struct enic *enic, + struct enic_port_profile *prev_pp, int *restore_pp) +{ + if (enic->pp.request < enic_pp_handlers_count + && enic_pp_handlers[enic->pp.request]) + return enic_pp_handlers[enic->pp.request](enic, + prev_pp, restore_pp); + else + return -EOPNOTSUPP; +} + +int enic_process_get_pp_request(struct enic *enic, int request, + u16 *response) +{ + int err, status = ERR_SUCCESS; + + switch (request) { + + case PORT_REQUEST_PREASSOCIATE_RR: + case PORT_REQUEST_ASSOCIATE: + err = enic_dev_enable2_done(enic, &status); + break; + + case PORT_REQUEST_DISASSOCIATE: + err = enic_dev_deinit_done(enic, &status); + break; + + default: + return -EINVAL; + } + + if (err) + status = err; + + switch (status) { + case ERR_SUCCESS: + *response = PORT_PROFILE_RESPONSE_SUCCESS; + break; + case ERR_EINVAL: + *response = PORT_PROFILE_RESPONSE_INVALID; + break; + case ERR_EBADSTATE: + *response = PORT_PROFILE_RESPONSE_BADSTATE; + break; + case ERR_ENOMEM: + *response = PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES; + break; + case ERR_EINPROGRESS: + *response = PORT_PROFILE_RESPONSE_INPROGRESS; + break; + default: + *response = PORT_PROFILE_RESPONSE_ERROR; + break; + } + + return 0; +} diff --git a/drivers/net/enic/enic_pp.h b/drivers/net/enic/enic_pp.h new file mode 100644 index 000000000000..699e365a944d --- /dev/null +++ b/drivers/net/enic/enic_pp.h @@ -0,0 +1,27 @@ +/* + * Copyright 2011 Cisco Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _ENIC_PP_H_ +#define _ENIC_PP_H_ + +int enic_process_set_pp_request(struct enic *enic, + struct enic_port_profile *prev_pp, int *restore_pp); +int enic_process_get_pp_request(struct enic *enic, int request, + u16 *response); + +#endif /* _ENIC_PP_H_ */ -- cgit v1.2.3-58-ga151 From ab392d2d6d4e2e50502985eead545b44ee58802c Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 28 Mar 2011 16:27:31 +0000 Subject: drivers/net: Remove IRQF_SAMPLE_RANDOM flag from network drivers The IRQF_SAMPLE_RANDOM flag is marked as deprecated and will be removed. Every input point to the kernel's entropy pool have to better document the type of entropy source it is. drivers/char/random.c now implements a set of interfaces that can be used for devices to collect enviromental noise. IRQF_SAMPLE_RANDOM will be replaced with these add_*_randomness exported functions. Network drivers are not a good source of entropy. They use as a source of entropy essentially a remote host. Which means that the source of entropy can be potentially controlled by an attacker. Also, with heavy workloads the entropy decreases due to less hardware interrupts happening thanks to irq mitigation and NAPI. If a system relies in its network interface as a entropy source it has a false sense of security. Systems that don't have devices whose drivers are good sources of entropy, should either use a hardware random number generator or feed the kernel's entropy pool from userspace using other sources of entropy such as EGD, video_entropyd, timer_entropyd and audio-entropyd. Signed-off-by: Javier Martinez Canillas Signed-off-by: David S. Miller --- drivers/net/atlx/atl1.c | 2 +- drivers/net/bcm63xx_enet.c | 4 ++-- drivers/net/cris/eth_v10.c | 4 ++-- drivers/net/ibmlana.c | 3 ++- drivers/net/macb.c | 3 +-- drivers/net/netxen/netxen_nic_main.c | 2 +- drivers/net/niu.c | 3 +-- drivers/net/qla3xxx.c | 2 +- drivers/net/tg3.c | 4 ++-- drivers/net/xen-netfront.c | 3 +-- 10 files changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 67f40b9c16ed..e973d056dc8f 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -2572,7 +2572,7 @@ static s32 atl1_up(struct atl1_adapter *adapter) { struct net_device *netdev = adapter->netdev; int err; - int irq_flags = IRQF_SAMPLE_RANDOM; + int irq_flags = 0; /* hardware has been reset, we need to reload some things */ atlx_set_multi(netdev); diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c index e94a966af418..2af413fbfb0e 100644 --- a/drivers/net/bcm63xx_enet.c +++ b/drivers/net/bcm63xx_enet.c @@ -839,8 +839,8 @@ static int bcm_enet_open(struct net_device *dev) if (ret) goto out_phy_disconnect; - ret = request_irq(priv->irq_rx, bcm_enet_isr_dma, - IRQF_SAMPLE_RANDOM | IRQF_DISABLED, dev->name, dev); + ret = request_irq(priv->irq_rx, bcm_enet_isr_dma, IRQF_DISABLED, + dev->name, dev); if (ret) goto out_freeirq; diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index 80c2feeefec5..e759d74edd01 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -491,8 +491,8 @@ e100_open(struct net_device *dev) /* allocate the irq corresponding to the receiving DMA */ - if (request_irq(NETWORK_DMA_RX_IRQ_NBR, e100rxtx_interrupt, - IRQF_SAMPLE_RANDOM, cardname, (void *)dev)) { + if (request_irq(NETWORK_DMA_RX_IRQ_NBR, e100rxtx_interrupt, 0, cardname, + (void *)dev)) { goto grace_exit0; } diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c index 94d9969ec0bb..f872f966927a 100644 --- a/drivers/net/ibmlana.c +++ b/drivers/net/ibmlana.c @@ -782,7 +782,8 @@ static int ibmlana_open(struct net_device *dev) /* register resources - only necessary for IRQ */ - result = request_irq(priv->realirq, irq_handler, IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev); + result = request_irq(priv->realirq, irq_handler, IRQF_SHARED, + dev->name, dev); if (result != 0) { printk(KERN_ERR "%s: failed to register irq %d\n", dev->name, dev->irq); return result; diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 79ccb54ab00c..2cb4e792f871 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -1171,8 +1171,7 @@ static int __init macb_probe(struct platform_device *pdev) } dev->irq = platform_get_irq(pdev, 0); - err = request_irq(dev->irq, macb_interrupt, IRQF_SAMPLE_RANDOM, - dev->name, dev); + err = request_irq(dev->irq, macb_interrupt, 0, dev->name, dev); if (err) { printk(KERN_ERR "%s: Unable to request IRQ %d (error %d)\n", diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 83348dc4b184..933671556c15 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -905,7 +905,7 @@ netxen_nic_request_irq(struct netxen_adapter *adapter) struct nx_host_sds_ring *sds_ring; int err, ring; - unsigned long flags = IRQF_SAMPLE_RANDOM; + unsigned long flags = 0; struct net_device *netdev = adapter->netdev; struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 32678b6c6b39..681a42ca5c51 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -6071,8 +6071,7 @@ static int niu_request_irq(struct niu *np) for (i = 0; i < np->num_ldg; i++) { struct niu_ldg *lp = &np->ldg[i]; - err = request_irq(lp->irq, niu_interrupt, - IRQF_SHARED | IRQF_SAMPLE_RANDOM, + err = request_irq(lp->irq, niu_interrupt, IRQF_SHARED, np->irq_name[i], lp); if (err) goto out_free_irqs; diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 348b4f1367c9..f3f737b91248 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -3468,7 +3468,7 @@ static int ql_adapter_up(struct ql3_adapter *qdev) { struct net_device *ndev = qdev->ndev; int err; - unsigned long irq_flags = IRQF_SAMPLE_RANDOM | IRQF_SHARED; + unsigned long irq_flags = IRQF_SHARED; unsigned long hw_flags; if (ql_alloc_mem_resources(qdev)) { diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 73c942d85f07..b7e03a6ebf25 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8839,12 +8839,12 @@ static int tg3_request_irq(struct tg3 *tp, int irq_num) fn = tg3_msi; if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) fn = tg3_msi_1shot; - flags = IRQF_SAMPLE_RANDOM; + flags = 0; } else { fn = tg3_interrupt; if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) fn = tg3_interrupt_tagged; - flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM; + flags = IRQF_SHARED; } return request_irq(tnapi->irq_vec, fn, flags, name, tnapi); diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 5c8d9c385be0..c06f5a09b263 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1416,8 +1416,7 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info) goto fail; err = bind_evtchn_to_irqhandler(info->evtchn, xennet_interrupt, - IRQF_SAMPLE_RANDOM, netdev->name, - netdev); + 0, netdev->name, netdev); if (err < 0) goto fail; netdev->irq = err; -- cgit v1.2.3-58-ga151 From 0a5c047507aaaf00519921336d19c0f8f5f9f363 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 31 Mar 2011 01:51:35 -0700 Subject: fib: add __rcu annotations Add __rcu annotations and lockdep checks. Add const qualifiers node_parent() and node_parent_rcu() can use rcu_dereference_index_check() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/fib_trie.c | 103 +++++++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index b92c86f6e9b3..b9d1f33e5e04 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -126,7 +126,7 @@ struct tnode { struct work_struct work; struct tnode *tnode_free; }; - struct rt_trie_node *child[0]; + struct rt_trie_node __rcu *child[0]; }; #ifdef CONFIG_IP_FIB_TRIE_STATS @@ -151,7 +151,7 @@ struct trie_stat { }; struct trie { - struct rt_trie_node *trie; + struct rt_trie_node __rcu *trie; #ifdef CONFIG_IP_FIB_TRIE_STATS struct trie_use_stats stats; #endif @@ -177,16 +177,29 @@ static const int sync_pages = 128; static struct kmem_cache *fn_alias_kmem __read_mostly; static struct kmem_cache *trie_leaf_kmem __read_mostly; -static inline struct tnode *node_parent(struct rt_trie_node *node) +/* + * caller must hold RTNL + */ +static inline struct tnode *node_parent(const struct rt_trie_node *node) { - return (struct tnode *)(node->parent & ~NODE_TYPE_MASK); + unsigned long parent; + + parent = rcu_dereference_index_check(node->parent, lockdep_rtnl_is_held()); + + return (struct tnode *)(parent & ~NODE_TYPE_MASK); } -static inline struct tnode *node_parent_rcu(struct rt_trie_node *node) +/* + * caller must hold RCU read lock or RTNL + */ +static inline struct tnode *node_parent_rcu(const struct rt_trie_node *node) { - struct tnode *ret = node_parent(node); + unsigned long parent; + + parent = rcu_dereference_index_check(node->parent, rcu_read_lock_held() || + lockdep_rtnl_is_held()); - return rcu_dereference_rtnl(ret); + return (struct tnode *)(parent & ~NODE_TYPE_MASK); } /* Same as rcu_assign_pointer @@ -198,18 +211,24 @@ static inline void node_set_parent(struct rt_trie_node *node, struct tnode *ptr) node->parent = (unsigned long)ptr | NODE_TYPE(node); } -static inline struct rt_trie_node *tnode_get_child(struct tnode *tn, unsigned int i) +/* + * caller must hold RTNL + */ +static inline struct rt_trie_node *tnode_get_child(const struct tnode *tn, unsigned int i) { BUG_ON(i >= 1U << tn->bits); - return tn->child[i]; + return rtnl_dereference(tn->child[i]); } -static inline struct rt_trie_node *tnode_get_child_rcu(struct tnode *tn, unsigned int i) +/* + * caller must hold RCU read lock or RTNL + */ +static inline struct rt_trie_node *tnode_get_child_rcu(const struct tnode *tn, unsigned int i) { - struct rt_trie_node *ret = tnode_get_child(tn, i); + BUG_ON(i >= 1U << tn->bits); - return rcu_dereference_rtnl(ret); + return rcu_dereference_rtnl(tn->child[i]); } static inline int tnode_child_length(const struct tnode *tn) @@ -487,7 +506,7 @@ static inline void put_child(struct trie *t, struct tnode *tn, int i, static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n, int wasfull) { - struct rt_trie_node *chi = tn->child[i]; + struct rt_trie_node *chi = rtnl_dereference(tn->child[i]); int isfull; BUG_ON(i >= 1<bits); @@ -665,7 +684,7 @@ one_child: for (i = 0; i < tnode_child_length(tn); i++) { struct rt_trie_node *n; - n = tn->child[i]; + n = rtnl_dereference(tn->child[i]); if (!n) continue; @@ -679,6 +698,20 @@ one_child: return (struct rt_trie_node *) tn; } + +static void tnode_clean_free(struct tnode *tn) +{ + int i; + struct tnode *tofree; + + for (i = 0; i < tnode_child_length(tn); i++) { + tofree = (struct tnode *)rtnl_dereference(tn->child[i]); + if (tofree) + tnode_free(tofree); + } + tnode_free(tn); +} + static struct tnode *inflate(struct trie *t, struct tnode *tn) { struct tnode *oldtnode = tn; @@ -755,8 +788,8 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn) inode = (struct tnode *) node; if (inode->bits == 1) { - put_child(t, tn, 2*i, inode->child[0]); - put_child(t, tn, 2*i+1, inode->child[1]); + put_child(t, tn, 2*i, rtnl_dereference(inode->child[0])); + put_child(t, tn, 2*i+1, rtnl_dereference(inode->child[1])); tnode_free_safe(inode); continue; @@ -797,8 +830,8 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn) size = tnode_child_length(left); for (j = 0; j < size; j++) { - put_child(t, left, j, inode->child[j]); - put_child(t, right, j, inode->child[j + size]); + put_child(t, left, j, rtnl_dereference(inode->child[j])); + put_child(t, right, j, rtnl_dereference(inode->child[j + size])); } put_child(t, tn, 2*i, resize(t, left)); put_child(t, tn, 2*i+1, resize(t, right)); @@ -808,18 +841,8 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn) tnode_free_safe(oldtnode); return tn; nomem: - { - int size = tnode_child_length(tn); - int j; - - for (j = 0; j < size; j++) - if (tn->child[j]) - tnode_free((struct tnode *)tn->child[j]); - - tnode_free(tn); - - return ERR_PTR(-ENOMEM); - } + tnode_clean_free(tn); + return ERR_PTR(-ENOMEM); } static struct tnode *halve(struct trie *t, struct tnode *tn) @@ -890,18 +913,8 @@ static struct tnode *halve(struct trie *t, struct tnode *tn) tnode_free_safe(oldtnode); return tn; nomem: - { - int size = tnode_child_length(tn); - int j; - - for (j = 0; j < size; j++) - if (tn->child[j]) - tnode_free((struct tnode *)tn->child[j]); - - tnode_free(tn); - - return ERR_PTR(-ENOMEM); - } + tnode_clean_free(tn); + return ERR_PTR(-ENOMEM); } /* readside must use rcu_read_lock currently dump routines @@ -1033,7 +1046,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen) t_key cindex; pos = 0; - n = t->trie; + n = rtnl_dereference(t->trie); /* If we point to NULL, stop. Either the tree is empty and we should * just put a new leaf in if, or we have reached an empty child slot, @@ -1756,7 +1769,7 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c) continue; if (IS_LEAF(c)) { - prefetch(p->child[idx]); + prefetch(rcu_dereference_rtnl(p->child[idx])); return (struct leaf *) c; } @@ -2272,7 +2285,7 @@ static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos) /* walk rest of this hash chain */ h = tb->tb_id & (FIB_TABLE_HASHSZ - 1); - while ( (tb_node = rcu_dereference(tb->tb_hlist.next)) ) { + while ((tb_node = rcu_dereference(hlist_next_rcu(&tb->tb_hlist)))) { tb = hlist_entry(tb_node, struct fib_table, tb_hlist); n = fib_trie_get_first(iter, (struct trie *) tb->tb_data); if (n) -- cgit v1.2.3-58-ga151 From 83229aa5e2c242163599266a686483e3b91ec07e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 31 Mar 2011 04:52:14 -0700 Subject: net: Add helper flowi4_init_output(). On-stack initialization via assignment of flow structures are expensive because GCC emits a memset() to clear the entire structure out no matter what. Add a helper for ipv4 output flow key setup which we can use to avoid the memset. Signed-off-by: David S. Miller --- include/net/flow.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/net/flow.h b/include/net/flow.h index 7fe5a0f9483a..37e77d66f78c 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -70,6 +70,27 @@ struct flowi4 { #define fl4_gre_key uli.gre_key }; +static inline void flowi4_init_output(struct flowi4 *fl4, int oif, + __u32 mark, __u8 tos, __u8 scope, + __u8 proto, __u8 flags, + __be32 daddr, __be32 saddr, + __be16 dport, __be32 sport) +{ + fl4->flowi4_oif = oif; + fl4->flowi4_iif = 0; + fl4->flowi4_mark = mark; + fl4->flowi4_tos = tos; + fl4->flowi4_scope = scope; + fl4->flowi4_proto = proto; + fl4->flowi4_flags = flags; + fl4->flowi4_secid = 0; + fl4->daddr = daddr; + fl4->saddr = saddr; + fl4->fl4_sport = sport; + fl4->fl4_dport = dport; +} + + struct flowi6 { struct flowi_common __fl_common; #define flowi6_oif __fl_common.flowic_oif -- cgit v1.2.3-58-ga151 From 94b92b88344641dbeadd2ef371549b7663a48fb1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 31 Mar 2011 04:52:59 -0700 Subject: ipv4: Use flowi4_init_output() in net/route.h Signed-off-by: David S. Miller --- include/net/route.h | 60 +++++++++++++++++++++-------------------------------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index f88429cad52a..b24288595e58 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -149,17 +149,12 @@ static inline struct rtable *ip_route_output_ports(struct net *net, struct sock __be16 dport, __be16 sport, __u8 proto, __u8 tos, int oif) { - struct flowi4 fl4 = { - .flowi4_oif = oif, - .flowi4_flags = sk ? inet_sk_flowi_flags(sk) : 0, - .flowi4_mark = sk ? sk->sk_mark : 0, - .daddr = daddr, - .saddr = saddr, - .flowi4_tos = tos, - .flowi4_proto = proto, - .fl4_dport = dport, - .fl4_sport = sport, - }; + struct flowi4 fl4; + + flowi4_init_output(&fl4, oif, sk ? sk->sk_mark : 0, tos, + RT_SCOPE_UNIVERSE, proto, + sk ? inet_sk_flowi_flags(sk) : 0, + daddr, saddr, dport, sport); if (sk) security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); return ip_route_output_flow(net, &fl4, sk); @@ -229,25 +224,21 @@ static inline struct rtable *ip_route_connect(__be32 dst, __be32 src, u32 tos, __be16 sport, __be16 dport, struct sock *sk, bool can_sleep) { - struct flowi4 fl4 = { - .flowi4_oif = oif, - .flowi4_mark = sk->sk_mark, - .daddr = dst, - .saddr = src, - .flowi4_tos = tos, - .flowi4_proto = protocol, - .fl4_sport = sport, - .fl4_dport = dport, - }; struct net *net = sock_net(sk); struct rtable *rt; + struct flowi4 fl4; + __u8 flow_flags; + flow_flags = 0; if (inet_sk(sk)->transparent) - fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC; + flow_flags |= FLOWI_FLAG_ANYSRC; if (protocol == IPPROTO_TCP) - fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS; + flow_flags |= FLOWI_FLAG_PRECOW_METRICS; if (can_sleep) - fl4.flowi4_flags |= FLOWI_FLAG_CAN_SLEEP; + flow_flags |= FLOWI_FLAG_CAN_SLEEP; + + flowi4_init_output(&fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE, + protocol, flow_flags, dst, src, dport, sport); if (!dst || !src) { rt = __ip_route_output_key(net, &fl4); @@ -267,20 +258,17 @@ static inline struct rtable *ip_route_newports(struct rtable *rt, __be16 dport, struct sock *sk) { if (sport != orig_sport || dport != orig_dport) { - struct flowi4 fl4 = { - .flowi4_oif = rt->rt_oif, - .flowi4_mark = rt->rt_mark, - .daddr = rt->rt_dst, - .saddr = rt->rt_src, - .flowi4_tos = rt->rt_tos, - .flowi4_proto = protocol, - .fl4_sport = sport, - .fl4_dport = dport - }; + struct flowi4 fl4; + __u8 flow_flags; + + flow_flags = 0; if (inet_sk(sk)->transparent) - fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC; + flow_flags |= FLOWI_FLAG_ANYSRC; if (protocol == IPPROTO_TCP) - fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS; + flow_flags |= FLOWI_FLAG_PRECOW_METRICS; + flowi4_init_output(&fl4, rt->rt_oif, rt->rt_mark, rt->rt_tos, + RT_SCOPE_UNIVERSE, protocol, flow_flags, + rt->rt_dst, rt->rt_src, dport, sport); ip_rt_put(rt); security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); return ip_route_output_flow(sock_net(sk), &fl4, sk); -- cgit v1.2.3-58-ga151 From e79d9bc7ea76e08fc24d7adaad8b6a821d1624c3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 31 Mar 2011 04:53:20 -0700 Subject: ipv4: Use flowi4_init_output() in inet_connection_sock.c Signed-off-by: David S. Miller --- net/ipv4/inet_connection_sock.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 6c0b7f4a3d7d..f784608a4c45 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -356,20 +356,14 @@ struct dst_entry *inet_csk_route_req(struct sock *sk, struct rtable *rt; const struct inet_request_sock *ireq = inet_rsk(req); struct ip_options *opt = inet_rsk(req)->opt; - struct flowi4 fl4 = { - .flowi4_oif = sk->sk_bound_dev_if, - .flowi4_mark = sk->sk_mark, - .daddr = ((opt && opt->srr) ? - opt->faddr : ireq->rmt_addr), - .saddr = ireq->loc_addr, - .flowi4_tos = RT_CONN_FLAGS(sk), - .flowi4_proto = sk->sk_protocol, - .flowi4_flags = inet_sk_flowi_flags(sk), - .fl4_sport = inet_sk(sk)->inet_sport, - .fl4_dport = ireq->rmt_port, - }; struct net *net = sock_net(sk); + struct flowi4 fl4; + flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark, + RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, + sk->sk_protocol, inet_sk_flowi_flags(sk), + (opt && opt->srr) ? opt->faddr : ireq->rmt_addr, + ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport); security_req_classify_flow(req, flowi4_to_flowi(&fl4)); rt = ip_route_output_flow(net, &fl4, sk); if (IS_ERR(rt)) -- cgit v1.2.3-58-ga151 From 538de0e01f1ca3568ad03877ff297c646dd8ad23 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 31 Mar 2011 04:53:37 -0700 Subject: ipv4: Use flowi4_init_output() in ip_send_reply() Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 67f241b97649..86a284308271 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1474,16 +1474,14 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar } { - struct flowi4 fl4 = { - .flowi4_oif = arg->bound_dev_if, - .daddr = daddr, - .saddr = rt->rt_spec_dst, - .flowi4_tos = RT_TOS(ip_hdr(skb)->tos), - .fl4_sport = tcp_hdr(skb)->dest, - .fl4_dport = tcp_hdr(skb)->source, - .flowi4_proto = sk->sk_protocol, - .flowi4_flags = ip_reply_arg_flowi_flags(arg), - }; + struct flowi4 fl4; + + flowi4_init_output(&fl4, arg->bound_dev_if, 0, + RT_TOS(ip_hdr(skb)->tos), + RT_SCOPE_UNIVERSE, sk->sk_protocol, + ip_reply_arg_flowi_flags(arg), + daddr, rt->rt_spec_dst, + tcp_hdr(skb)->source, tcp_hdr(skb)->dest); security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); rt = ip_route_output_key(sock_net(sk), &fl4); if (IS_ERR(rt)) -- cgit v1.2.3-58-ga151 From ef164ae3563bf4d291b6f75ca2e120b17d606963 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 31 Mar 2011 04:53:51 -0700 Subject: ipv4: Use flowi4_init_output() in raw_sendmsg() Signed-off-by: David S. Miller --- net/ipv4/raw.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 2d3c72e5bbbf..7d32d9d57152 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -548,17 +548,13 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, } { - struct flowi4 fl4 = { - .flowi4_oif = ipc.oif, - .flowi4_mark = sk->sk_mark, - .daddr = daddr, - .saddr = saddr, - .flowi4_tos = tos, - .flowi4_proto = (inet->hdrincl ? - IPPROTO_RAW : - sk->sk_protocol), - .flowi4_flags = FLOWI_FLAG_CAN_SLEEP, - }; + struct flowi4 fl4; + + flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, + RT_SCOPE_UNIVERSE, + inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, + FLOWI_FLAG_CAN_SLEEP, daddr, saddr, 0, 0); + if (!inet->hdrincl) { err = raw_probe_proto_opt(&fl4, msg); if (err) -- cgit v1.2.3-58-ga151 From 1bba6ffeeb44480ddbdda912cc85ad2cfd4725ae Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 31 Mar 2011 04:54:08 -0700 Subject: ipv4: Use flowi4_init_output() in cookie_v4_check() Signed-off-by: David S. Miller --- net/ipv4/syncookies.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 8b44c6d2a79b..71e029691908 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -345,17 +345,13 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, * no easy way to do this. */ { - struct flowi4 fl4 = { - .flowi4_mark = sk->sk_mark, - .daddr = ((opt && opt->srr) ? - opt->faddr : ireq->rmt_addr), - .saddr = ireq->loc_addr, - .flowi4_tos = RT_CONN_FLAGS(sk), - .flowi4_proto = IPPROTO_TCP, - .flowi4_flags = inet_sk_flowi_flags(sk), - .fl4_sport = th->dest, - .fl4_dport = th->source, - }; + struct flowi4 fl4; + + flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk), + RT_SCOPE_UNIVERSE, IPPROTO_TCP, + inet_sk_flowi_flags(sk), + (opt && opt->srr) ? opt->faddr : ireq->rmt_addr, + ireq->loc_addr, th->source, th->dest); security_req_classify_flow(req, flowi4_to_flowi(&fl4)); rt = ip_route_output_key(sock_net(sk), &fl4); if (IS_ERR(rt)) { -- cgit v1.2.3-58-ga151 From c0951cbcfd7142003bc683046ef78a53c66d3265 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 31 Mar 2011 04:54:27 -0700 Subject: ipv4: Use flowi4_init_output() in udp_sendmsg() Signed-off-by: David S. Miller --- net/ipv4/udp.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 588f47af5faf..ac66132b8edf 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -909,20 +909,14 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, rt = (struct rtable *)sk_dst_check(sk, 0); if (rt == NULL) { - struct flowi4 fl4 = { - .flowi4_oif = ipc.oif, - .flowi4_mark = sk->sk_mark, - .daddr = faddr, - .saddr = saddr, - .flowi4_tos = tos, - .flowi4_proto = sk->sk_protocol, - .flowi4_flags = (inet_sk_flowi_flags(sk) | - FLOWI_FLAG_CAN_SLEEP), - .fl4_sport = inet->inet_sport, - .fl4_dport = dport, - }; + struct flowi4 fl4; struct net *net = sock_net(sk); + flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, + RT_SCOPE_UNIVERSE, sk->sk_protocol, + inet_sk_flowi_flags(sk)|FLOWI_FLAG_CAN_SLEEP, + faddr, saddr, dport, inet->inet_sport); + security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); rt = ip_route_output_flow(net, &fl4, sk); if (IS_ERR(rt)) { -- cgit v1.2.3-58-ga151 From f0681a68dd3a32699891cd1de93459aee5af7728 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 16 Mar 2011 21:06:52 -0300 Subject: Bluetooth: remove unnecessary function declaration hci_notify() doesn't need declaration first. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index b372fb8bcdcf..c20cbe5ff6db 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -56,7 +56,6 @@ static void hci_cmd_task(unsigned long arg); static void hci_rx_task(unsigned long arg); static void hci_tx_task(unsigned long arg); -static void hci_notify(struct hci_dev *hdev, int event); static DEFINE_RWLOCK(hci_task_lock); -- cgit v1.2.3-58-ga151 From 1f6c6378c59f3ddac9ed89a68ccefe2611300c09 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 16 Mar 2011 14:29:35 +0200 Subject: Bluetooth: Add define for the maximum name length on HCI level This patch adds a clear define for the maximum device name length in HCI messages and thereby avoids magic numbers in the code. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 8 +++++--- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/hci_event.c | 4 ++-- net/bluetooth/hci_sysfs.c | 6 +++--- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index ec6acf2f1c0b..1cd031cd1c4d 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -535,15 +535,17 @@ struct hci_cp_delete_stored_link_key { __u8 delete_all; } __packed; +#define HCI_MAX_NAME_LENGTH 248 + #define HCI_OP_WRITE_LOCAL_NAME 0x0c13 struct hci_cp_write_local_name { - __u8 name[248]; + __u8 name[HCI_MAX_NAME_LENGTH]; } __packed; #define HCI_OP_READ_LOCAL_NAME 0x0c14 struct hci_rp_read_local_name { __u8 status; - __u8 name[248]; + __u8 name[HCI_MAX_NAME_LENGTH]; } __packed; #define HCI_OP_WRITE_CA_TIMEOUT 0x0c16 @@ -745,7 +747,7 @@ struct hci_ev_auth_complete { struct hci_ev_remote_name { __u8 status; bdaddr_t bdaddr; - __u8 name[248]; + __u8 name[HCI_MAX_NAME_LENGTH]; } __packed; #define HCI_EV_ENCRYPT_CHANGE 0x08 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 441dadbf6a89..9aabb14982dd 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -94,7 +94,7 @@ struct hci_dev { __u8 bus; __u8 dev_type; bdaddr_t bdaddr; - __u8 dev_name[248]; + __u8 dev_name[HCI_MAX_NAME_LENGTH]; __u8 dev_class[3]; __u8 major_class; __u8 minor_class; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 3fbfa50c2bff..91ef52673ed3 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -200,7 +200,7 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) if (!sent) return; - memcpy(hdev->dev_name, sent, 248); + memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); } static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) @@ -212,7 +212,7 @@ static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) if (rp->status) return; - memcpy(hdev->dev_name, rp->name, 248); + memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); } static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 3c838a65a75a..e54421693eb8 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -216,13 +216,13 @@ static ssize_t show_type(struct device *dev, struct device_attribute *attr, char static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) { struct hci_dev *hdev = dev_get_drvdata(dev); - char name[249]; + char name[HCI_MAX_NAME_LENGTH + 1]; int i; - for (i = 0; i < 248; i++) + for (i = 0; i < HCI_MAX_NAME_LENGTH; i++) name[i] = hdev->dev_name[i]; - name[248] = '\0'; + name[HCI_MAX_NAME_LENGTH] = '\0'; return sprintf(buf, "%s\n", name); } -- cgit v1.2.3-58-ga151 From dc4fe30b8675033e538e2dea50be8af9c75f1b6a Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 16 Mar 2011 14:29:36 +0200 Subject: Bluetooth: mgmt: Add local name information to read_info reply This patch adds the name of the adapter to the reply of the read_info management command. The management messages reserve 249 bytes for the name instead of 248 (like in the HCI spec) so that there is always a guarantee that it is nul-terminated. That way it can safely be passed onto string manipulation functions. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/mgmt.h | 5 +++++ net/bluetooth/mgmt.c | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 5fabfa886b3e..7d0749bed090 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -41,6 +41,10 @@ struct mgmt_rp_read_index_list { __le16 index[0]; } __packed; +/* Reserve one extra byte for names in management messages so that they + * are always guaranteed to be nul-terminated */ +#define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1) + #define MGMT_OP_READ_INFO 0x0004 struct mgmt_rp_read_info { __u8 type; @@ -55,6 +59,7 @@ struct mgmt_rp_read_info { __u16 manufacturer; __u8 hci_ver; __u16 hci_rev; + __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; struct mgmt_mode { diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 0054c74e27b7..ffdb2f4e8635 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -183,6 +183,8 @@ static int read_controller_info(struct sock *sk, u16 index) set_bit(HCI_MGMT, &hdev->flags); + memset(&rp, 0, sizeof(rp)); + rp.type = hdev->dev_type; rp.powered = test_bit(HCI_UP, &hdev->flags); @@ -204,6 +206,8 @@ static int read_controller_info(struct sock *sk, u16 index) rp.hci_ver = hdev->hci_ver; put_unaligned_le16(hdev->hci_rev, &rp.hci_rev); + memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name)); + hci_dev_unlock_bh(hdev); hci_dev_put(hdev); -- cgit v1.2.3-58-ga151 From b312b161ecb833b1bce5c4a97853f4a4f40c7901 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 16 Mar 2011 14:29:37 +0200 Subject: Bluetooth: mgmt: Add support for setting the local name This patch adds a new set_local_name management command as well as a local_name_changed management event. With these user space can both change the local name as well as monitor changes to it by others. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 1 + include/net/bluetooth/mgmt.h | 10 ++++++ net/bluetooth/hci_event.c | 9 +++-- net/bluetooth/mgmt.c | 75 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 9aabb14982dd..3912c7ab717c 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -767,6 +767,7 @@ int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status); +int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 7d0749bed090..89e7c82c4784 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -172,6 +172,11 @@ struct mgmt_rp_user_confirm_reply { #define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x0016 +#define MGMT_OP_SET_LOCAL_NAME 0x0017 +struct mgmt_cp_set_local_name { + __u8 name[MGMT_MAX_NAME_LENGTH]; +} __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; @@ -239,3 +244,8 @@ struct mgmt_ev_auth_failed { bdaddr_t bdaddr; __u8 status; } __packed; + +#define MGMT_EV_LOCAL_NAME_CHANGED 0x0011 +struct mgmt_ev_local_name_changed { + __u8 name[MGMT_MAX_NAME_LENGTH]; +} __packed; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 91ef52673ed3..0def3e1fe5ef 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -193,13 +193,16 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) BT_DBG("%s status 0x%x", hdev->name, status); - if (status) - return; - sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); if (!sent) return; + if (test_bit(HCI_MGMT, &hdev->flags)) + mgmt_set_local_name_complete(hdev->id, sent, status); + + if (status) + return; + memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ffdb2f4e8635..f7ce78235590 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1256,6 +1256,45 @@ failed: return err; } +static int set_local_name(struct sock *sk, u16 index, unsigned char *data, + u16 len) +{ + struct mgmt_cp_set_local_name *mgmt_cp = (void *) data; + struct hci_cp_write_local_name hci_cp; + struct hci_dev *hdev; + struct pending_cmd *cmd; + int err; + + BT_DBG(""); + + if (len != sizeof(*mgmt_cp)) + return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, EINVAL); + + hdev = hci_dev_get(index); + if (!hdev) + return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV); + + hci_dev_lock_bh(hdev); + + cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len); + if (!cmd) { + err = -ENOMEM; + goto failed; + } + + memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name)); + err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp), + &hci_cp); + if (err < 0) + mgmt_pending_remove(cmd); + +failed: + hci_dev_unlock_bh(hdev); + hci_dev_put(hdev); + + return err; +} + int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) { unsigned char *buf; @@ -1351,6 +1390,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) case MGMT_OP_USER_CONFIRM_NEG_REPLY: err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0); break; + case MGMT_OP_SET_LOCAL_NAME: + err = set_local_name(sk, index, buf + sizeof(*hdr), len); + break; default: BT_DBG("Unknown op %u", opcode); err = cmd_status(sk, index, opcode, 0x01); @@ -1647,3 +1689,36 @@ int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status) return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL); } + +int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status) +{ + struct pending_cmd *cmd; + struct mgmt_cp_set_local_name ev; + int err; + + memset(&ev, 0, sizeof(ev)); + memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); + + cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, index); + if (!cmd) + goto send_event; + + if (status) { + err = cmd_status(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, EIO); + goto failed; + } + + err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev, + sizeof(ev)); + if (err < 0) + goto failed; + +send_event: + err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, index, &ev, sizeof(ev), + cmd ? cmd->sk : NULL); + +failed: + if (cmd) + mgmt_pending_remove(cmd); + return err; +} -- cgit v1.2.3-58-ga151 From b0d2199d6ff9f788b324fe54b1f783aff83502c4 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 22 Mar 2011 18:06:49 -0300 Subject: Bluetooth: Remove unused struct item num in struct l2cap_chan_list isn't used anywhere. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 4f4bff1eaed6..7a0262524a50 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -280,7 +280,6 @@ struct l2cap_conn_param_update_rsp { struct l2cap_chan_list { struct sock *head; rwlock_t lock; - long num; }; struct l2cap_conn { -- cgit v1.2.3-58-ga151 From 2c6d1a2eec5c49793c6760546d05515ce1b76881 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 23 Mar 2011 14:38:32 -0300 Subject: Bluetooth: Improve error message on wrong link type Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c9f9cecca527..b5a1ce06e1c0 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -2670,7 +2670,8 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, if (err) { struct l2cap_cmd_rej rej; - BT_DBG("error %d", err); + + BT_ERR("Wrong link type (%d)", err); /* FIXME: Map err to a valid reason */ rej.reason = cpu_to_le16(0); -- cgit v1.2.3-58-ga151 From a3d9bd4c00f13defd4c0fdcf8b47f8764a69e54d Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 21 Mar 2011 14:19:57 +0100 Subject: Bluetooth: Opencode macros in bnep/core.c BNEP_RX_TYPES and INCA macros have only one user each and don't provide any benefits compared to opencoding them. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/bnep/core.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 03d4d1245d58..940b4e129741 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -187,6 +187,8 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) n /= (ETH_ALEN * 2); if (n > 0) { + int i; + s->mc_filter = 0; /* Always send broadcast */ @@ -202,12 +204,14 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) BT_DBG("mc filter %s -> %s", batostr((void *) a1), batostr((void *) a2)); - #define INCA(a) { int i = 5; while (i >=0 && ++a[i--] == 0); } - /* Iterate from a1 to a2 */ set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter); while (memcmp(a1, a2, 6) < 0 && s->mc_filter != ~0LL) { - INCA(a1); + /* Increment a1 */ + i = 5; + while (i >= 0 && ++a1[i--] == 0) + ; + set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter); } } @@ -302,7 +306,6 @@ static u8 __bnep_rx_hlen[] = { ETH_ALEN + 2, /* BNEP_COMPRESSED_SRC_ONLY */ ETH_ALEN + 2 /* BNEP_COMPRESSED_DST_ONLY */ }; -#define BNEP_RX_TYPES (sizeof(__bnep_rx_hlen) - 1) static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) { @@ -314,7 +317,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) type = *(u8 *) skb->data; skb_pull(skb, 1); - if ((type & BNEP_TYPE_MASK) > BNEP_RX_TYPES) + if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen)) goto badframe; if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) { -- cgit v1.2.3-58-ga151 From 3aad75a128e2f2b8da31de1df4b9b9b4a8f65c66 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 21 Mar 2011 14:19:58 +0100 Subject: Bluetooth: Fix checkpatch errors and some code style issues in bnep Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/bnep/bnep.h | 146 +++++++++++++++++++++++----------------------- net/bluetooth/bnep/core.c | 37 +++++++----- 2 files changed, 94 insertions(+), 89 deletions(-) diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h index 70672544db86..d768e0434ed8 100644 --- a/net/bluetooth/bnep/bnep.h +++ b/net/bluetooth/bnep/bnep.h @@ -23,88 +23,88 @@ #include #include -// Limits -#define BNEP_MAX_PROTO_FILTERS 5 -#define BNEP_MAX_MULTICAST_FILTERS 20 - -// UUIDs -#define BNEP_BASE_UUID 0x0000000000001000800000805F9B34FB -#define BNEP_UUID16 0x02 -#define BNEP_UUID32 0x04 -#define BNEP_UUID128 0x16 - -#define BNEP_SVC_PANU 0x1115 -#define BNEP_SVC_NAP 0x1116 -#define BNEP_SVC_GN 0x1117 - -// Packet types -#define BNEP_GENERAL 0x00 -#define BNEP_CONTROL 0x01 -#define BNEP_COMPRESSED 0x02 -#define BNEP_COMPRESSED_SRC_ONLY 0x03 -#define BNEP_COMPRESSED_DST_ONLY 0x04 - -// Control types -#define BNEP_CMD_NOT_UNDERSTOOD 0x00 -#define BNEP_SETUP_CONN_REQ 0x01 -#define BNEP_SETUP_CONN_RSP 0x02 -#define BNEP_FILTER_NET_TYPE_SET 0x03 -#define BNEP_FILTER_NET_TYPE_RSP 0x04 -#define BNEP_FILTER_MULTI_ADDR_SET 0x05 -#define BNEP_FILTER_MULTI_ADDR_RSP 0x06 - -// Extension types -#define BNEP_EXT_CONTROL 0x00 - -// Response messages -#define BNEP_SUCCESS 0x00 - -#define BNEP_CONN_INVALID_DST 0x01 -#define BNEP_CONN_INVALID_SRC 0x02 -#define BNEP_CONN_INVALID_SVC 0x03 -#define BNEP_CONN_NOT_ALLOWED 0x04 - -#define BNEP_FILTER_UNSUPPORTED_REQ 0x01 -#define BNEP_FILTER_INVALID_RANGE 0x02 -#define BNEP_FILTER_INVALID_MCADDR 0x02 -#define BNEP_FILTER_LIMIT_REACHED 0x03 -#define BNEP_FILTER_DENIED_SECURITY 0x04 - -// L2CAP settings -#define BNEP_MTU 1691 -#define BNEP_PSM 0x0f -#define BNEP_FLUSH_TO 0xffff -#define BNEP_CONNECT_TO 15 -#define BNEP_FILTER_TO 15 - -// Headers -#define BNEP_TYPE_MASK 0x7f -#define BNEP_EXT_HEADER 0x80 +/* Limits */ +#define BNEP_MAX_PROTO_FILTERS 5 +#define BNEP_MAX_MULTICAST_FILTERS 20 + +/* UUIDs */ +#define BNEP_BASE_UUID 0x0000000000001000800000805F9B34FB +#define BNEP_UUID16 0x02 +#define BNEP_UUID32 0x04 +#define BNEP_UUID128 0x16 + +#define BNEP_SVC_PANU 0x1115 +#define BNEP_SVC_NAP 0x1116 +#define BNEP_SVC_GN 0x1117 + +/* Packet types */ +#define BNEP_GENERAL 0x00 +#define BNEP_CONTROL 0x01 +#define BNEP_COMPRESSED 0x02 +#define BNEP_COMPRESSED_SRC_ONLY 0x03 +#define BNEP_COMPRESSED_DST_ONLY 0x04 + +/* Control types */ +#define BNEP_CMD_NOT_UNDERSTOOD 0x00 +#define BNEP_SETUP_CONN_REQ 0x01 +#define BNEP_SETUP_CONN_RSP 0x02 +#define BNEP_FILTER_NET_TYPE_SET 0x03 +#define BNEP_FILTER_NET_TYPE_RSP 0x04 +#define BNEP_FILTER_MULTI_ADDR_SET 0x05 +#define BNEP_FILTER_MULTI_ADDR_RSP 0x06 + +/* Extension types */ +#define BNEP_EXT_CONTROL 0x00 + +/* Response messages */ +#define BNEP_SUCCESS 0x00 + +#define BNEP_CONN_INVALID_DST 0x01 +#define BNEP_CONN_INVALID_SRC 0x02 +#define BNEP_CONN_INVALID_SVC 0x03 +#define BNEP_CONN_NOT_ALLOWED 0x04 + +#define BNEP_FILTER_UNSUPPORTED_REQ 0x01 +#define BNEP_FILTER_INVALID_RANGE 0x02 +#define BNEP_FILTER_INVALID_MCADDR 0x02 +#define BNEP_FILTER_LIMIT_REACHED 0x03 +#define BNEP_FILTER_DENIED_SECURITY 0x04 + +/* L2CAP settings */ +#define BNEP_MTU 1691 +#define BNEP_PSM 0x0f +#define BNEP_FLUSH_TO 0xffff +#define BNEP_CONNECT_TO 15 +#define BNEP_FILTER_TO 15 + +/* Headers */ +#define BNEP_TYPE_MASK 0x7f +#define BNEP_EXT_HEADER 0x80 struct bnep_setup_conn_req { - __u8 type; - __u8 ctrl; - __u8 uuid_size; - __u8 service[0]; + __u8 type; + __u8 ctrl; + __u8 uuid_size; + __u8 service[0]; } __packed; struct bnep_set_filter_req { - __u8 type; - __u8 ctrl; + __u8 type; + __u8 ctrl; __be16 len; - __u8 list[0]; + __u8 list[0]; } __packed; struct bnep_control_rsp { - __u8 type; - __u8 ctrl; + __u8 type; + __u8 ctrl; __be16 resp; } __packed; struct bnep_ext_hdr { - __u8 type; - __u8 len; - __u8 data[0]; + __u8 type; + __u8 len; + __u8 data[0]; } __packed; /* BNEP ioctl defines */ @@ -114,10 +114,10 @@ struct bnep_ext_hdr { #define BNEPGETCONNINFO _IOR('B', 211, int) struct bnep_connadd_req { - int sock; // Connected socket + int sock; /* Connected socket */ __u32 flags; __u16 role; - char device[16]; // Name of the Ethernet device + char device[16]; /* Name of the Ethernet device */ }; struct bnep_conndel_req { @@ -148,7 +148,7 @@ int bnep_del_connection(struct bnep_conndel_req *req); int bnep_get_connlist(struct bnep_connlist_req *req); int bnep_get_conninfo(struct bnep_conninfo *ci); -// BNEP sessions +/* BNEP sessions */ struct bnep_session { struct list_head list; @@ -173,7 +173,7 @@ void bnep_sock_cleanup(void); static inline int bnep_mc_hash(__u8 *addr) { - return (crc32_be(~0, addr, ETH_ALEN) >> 26); + return crc32_be(~0, addr, ETH_ALEN) >> 26; } #endif diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 940b4e129741..0a2e76bde542 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -131,7 +131,8 @@ static int bnep_ctrl_set_netfilter(struct bnep_session *s, __be16 *data, int len return -EILSEQ; n = get_unaligned_be16(data); - data++; len -= 2; + data++; + len -= 2; if (len < n) return -EILSEQ; @@ -176,7 +177,8 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) return -EILSEQ; n = get_unaligned_be16(data); - data += 2; len -= 2; + data += 2; + len -= 2; if (len < n) return -EILSEQ; @@ -198,8 +200,10 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) for (; n > 0; n--) { u8 a1[6], *a2; - memcpy(a1, data, ETH_ALEN); data += ETH_ALEN; - a2 = data; data += ETH_ALEN; + memcpy(a1, data, ETH_ALEN); + data += ETH_ALEN; + a2 = data; + data += ETH_ALEN; BT_DBG("mc filter %s -> %s", batostr((void *) a1), batostr((void *) a2)); @@ -231,7 +235,8 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len) u8 cmd = *(u8 *)data; int err = 0; - data++; len--; + data++; + len--; switch (cmd) { case BNEP_CMD_NOT_UNDERSTOOD: @@ -315,7 +320,8 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) dev->stats.rx_bytes += skb->len; - type = *(u8 *) skb->data; skb_pull(skb, 1); + type = *(u8 *) skb->data; + skb_pull(skb, 1); if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen)) goto badframe; @@ -370,14 +376,14 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) case BNEP_COMPRESSED_DST_ONLY: memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb), - ETH_ALEN); + ETH_ALEN); memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source, - ETH_ALEN + 2); + ETH_ALEN + 2); break; case BNEP_GENERAL: memcpy(__skb_put(nskb, ETH_ALEN * 2), skb_mac_header(skb), - ETH_ALEN * 2); + ETH_ALEN * 2); put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2)); break; } @@ -481,7 +487,7 @@ static int bnep_session(void *arg) while (!atomic_read(&s->killed)) { set_current_state(TASK_INTERRUPTIBLE); - // RX + /* RX */ while ((skb = skb_dequeue(&sk->sk_receive_queue))) { skb_orphan(skb); bnep_rx_frame(s, skb); @@ -490,7 +496,7 @@ static int bnep_session(void *arg) if (sk->sk_state != BT_CONNECTED) break; - // TX + /* TX */ while ((skb = skb_dequeue(&sk->sk_write_queue))) if (bnep_tx_frame(s, skb)) break; @@ -558,8 +564,8 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) /* session struct allocated as private part of net_device */ dev = alloc_netdev(sizeof(struct bnep_session), - (*req->device) ? req->device : "bnep%d", - bnep_net_setup); + (*req->device) ? req->device : "bnep%d", + bnep_net_setup); if (!dev) return -ENOMEM; @@ -574,7 +580,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) s = netdev_priv(dev); /* This is rx header therefore addresses are swapped. - * ie eh.h_dest is our local address. */ + * ie. eh.h_dest is our local address. */ memcpy(s->eh.h_dest, &src, ETH_ALEN); memcpy(s->eh.h_source, &dst, ETH_ALEN); memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN); @@ -600,9 +606,8 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) SET_NETDEV_DEVTYPE(dev, &bnep_type); err = register_netdev(dev); - if (err) { + if (err) goto failed; - } __bnep_link_session(s); -- cgit v1.2.3-58-ga151 From 8c20aa9ffc5a5ef52b6148e905671a8d12b40c87 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 21 Mar 2011 14:19:59 +0100 Subject: Bluetooth: Use #include instead of As warned by checkpatch.pl, use #include instead of Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/bnep/sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index d935da71ab3b..17800b1d28ea 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c @@ -39,10 +39,10 @@ #include #include #include +#include #include #include -#include #include "bnep.h" -- cgit v1.2.3-58-ga151 From 17f09a7e4ec5dd6a0d96498da6bf78762fba4468 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 21 Mar 2011 14:20:01 +0100 Subject: Bluetooth: Fix checkpatch errors, code style issues and typos in hidp Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hidp/core.c | 37 ++++++++++++++++++++----------------- net/bluetooth/hidp/hidp.h | 4 ++-- net/bluetooth/hidp/sock.c | 7 ++++--- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 5ec12971af6b..a1472b75d628 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -55,22 +55,24 @@ static DECLARE_RWSEM(hidp_session_sem); static LIST_HEAD(hidp_session_list); static unsigned char hidp_keycode[256] = { - 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, - 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, - 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, - 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, - 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, - 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, - 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, - 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, - 150,158,159,128,136,177,178,176,142,152,173,140 + 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, + 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, + 21, 44, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, + 14, 15, 57, 12, 13, 26, 27, 43, 43, 39, 40, 41, 51, 52, + 53, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 87, 88, + 99, 70, 119, 110, 102, 104, 111, 107, 109, 106, 105, 108, 103, 69, + 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 72, 73, + 82, 83, 86, 127, 116, 117, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 134, 138, 130, 132, 128, 129, 131, 137, 133, 135, + 136, 113, 115, 114, 0, 0, 0, 121, 0, 89, 93, 124, 92, 94, + 95, 0, 0, 0, 122, 123, 90, 91, 85, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 29, 42, 56, 125, 97, 54, 100, 126, 164, 166, 165, 163, 161, 115, + 114, 113, 150, 158, 159, 128, 136, 177, 178, 176, 142, 152, 173, 140 }; static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; @@ -721,7 +723,8 @@ static int hidp_session(void *arg) while (!atomic_read(&session->terminate)) { set_current_state(TASK_INTERRUPTIBLE); - if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED) + if (ctrl_sk->sk_state != BT_CONNECTED || + intr_sk->sk_state != BT_CONNECTED) break; while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) { diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index 13de5fa03480..b412e7152eec 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h @@ -84,8 +84,8 @@ #define HIDP_WAITING_FOR_SEND_ACK 11 struct hidp_connadd_req { - int ctrl_sock; // Connected control socket - int intr_sock; // Connteted interrupt socket + int ctrl_sock; /* Connected control socket */ + int intr_sock; /* Connected interrupt socket */ __u16 parser; __u16 rd_size; __u8 __user *rd_data; diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 250dfd46237d..178ac7f127ad 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c @@ -85,7 +85,8 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long return err; } - if (csock->sk->sk_state != BT_CONNECTED || isock->sk->sk_state != BT_CONNECTED) { + if (csock->sk->sk_state != BT_CONNECTED || + isock->sk->sk_state != BT_CONNECTED) { sockfd_put(csock); sockfd_put(isock); return -EBADFD; @@ -140,8 +141,8 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long #ifdef CONFIG_COMPAT struct compat_hidp_connadd_req { - int ctrl_sock; // Connected control socket - int intr_sock; // Connteted interrupt socket + int ctrl_sock; /* Connected control socket */ + int intr_sock; /* Connected interrupt socket */ __u16 parser; __u16 rd_size; compat_uptr_t rd_data; -- cgit v1.2.3-58-ga151 From 58aac468be411f2a9b4a28f2ed8e6e2a0db04267 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 21 Mar 2011 14:20:03 +0100 Subject: Bluetooth: Do not use assignments in IF conditions Fix checkpatch warnings concerning assignments in if conditions. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/cmtp/core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 964ea9126f9f..16aa6bd039ba 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -235,9 +235,12 @@ static void cmtp_process_transmit(struct cmtp_session *session) size = min_t(uint, ((tail < 258) ? (tail - 2) : (tail - 3)), skb->len); - if ((scb->id < 0) && ((scb->id = cmtp_alloc_block_id(session)) < 0)) { - skb_queue_head(&session->transmit, skb); - break; + if (scb->id < 0) { + scb->id = cmtp_alloc_block_id(session); + if (scb->id < 0) { + skb_queue_head(&session->transmit, skb); + break; + } } if (size < 256) { -- cgit v1.2.3-58-ga151 From ffd13320aa96e07f3048ebdcc603aaf38bed0c47 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 21 Mar 2011 14:20:04 +0100 Subject: Bluetooth: Use #include instead of As warned by checkpatch.pl, use #include instead of Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/cmtp/sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 7ea1979a8e4f..3f2dd5c25ae5 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c @@ -34,12 +34,12 @@ #include #include #include +#include #include #include #include -#include #include "cmtp.h" -- cgit v1.2.3-58-ga151 From e0e185efbad442a659657c152a9cd9b3fdcb43f2 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 21 Mar 2011 14:20:05 +0100 Subject: Bluetooth: Fix checkpatch error in cmtp.h Do not use C99 // comments. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/cmtp/cmtp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/cmtp/cmtp.h b/net/bluetooth/cmtp/cmtp.h index 785e79e953c5..c6f78f89415c 100644 --- a/net/bluetooth/cmtp/cmtp.h +++ b/net/bluetooth/cmtp/cmtp.h @@ -37,7 +37,7 @@ #define CMTP_LOOPBACK 0 struct cmtp_connadd_req { - int sock; // Connected socket + int sock; /* Connected socket */ __u32 flags; }; -- cgit v1.2.3-58-ga151 From c68fb7ff29622a7db8264f939f94e37330c27080 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 22 Mar 2011 13:12:19 +0100 Subject: Bluetooth: Rename cmd to param in pending_cmd This field holds not whole command but only command specific parameters. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/mgmt.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f7ce78235590..d0c01230bba9 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -36,7 +36,7 @@ struct pending_cmd { struct list_head list; __u16 opcode; int index; - void *cmd; + void *param; struct sock *sk; void *user_data; }; @@ -217,7 +217,7 @@ static int read_controller_info(struct sock *sk, u16 index) static void mgmt_pending_free(struct pending_cmd *cmd) { sock_put(cmd->sk); - kfree(cmd->cmd); + kfree(cmd->param); kfree(cmd); } @@ -233,13 +233,13 @@ static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, cmd->opcode = opcode; cmd->index = index; - cmd->cmd = kmalloc(len, GFP_ATOMIC); - if (!cmd->cmd) { + cmd->param = kmalloc(len, GFP_ATOMIC); + if (!cmd->param) { kfree(cmd); return NULL; } - memcpy(cmd->cmd, data, len); + memcpy(cmd->param, data, len); cmd->sk = sk; sock_hold(sk); @@ -1426,7 +1426,7 @@ struct cmd_lookup { static void mode_rsp(struct pending_cmd *cmd, void *data) { - struct mgmt_mode *cp = cmd->cmd; + struct mgmt_mode *cp = cmd->param; struct cmd_lookup *match = data; if (cp->val != match->val) @@ -1525,7 +1525,7 @@ int mgmt_connected(u16 index, bdaddr_t *bdaddr) static void disconnect_rsp(struct pending_cmd *cmd, void *data) { - struct mgmt_cp_disconnect *cp = cmd->cmd; + struct mgmt_cp_disconnect *cp = cmd->param; struct sock **sk = data; struct mgmt_rp_disconnect rp; -- cgit v1.2.3-58-ga151 From 8fce6357a9e72c4c9c846f9951895954bfb34ad1 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 22 Mar 2011 13:12:20 +0100 Subject: Bluetooth: Allow for NULL data in mgmt_pending_add Since index is in mgmt_hdr it is possible to have mgmt command with no parameters that still needs to add itself to pending list. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/mgmt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index d0c01230bba9..93f0f04c8bcd 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -239,7 +239,8 @@ static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, return NULL; } - memcpy(cmd->param, data, len); + if (data) + memcpy(cmd->param, data, len); cmd->sk = sk; sock_hold(sk); -- cgit v1.2.3-58-ga151 From c35938b2f56547ee77b5a038fe0db394aeac59bb Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 22 Mar 2011 13:12:21 +0100 Subject: Bluetooth: Add read_local_oob_data management command This patch adds a command to read local OOB data to the managment interface. The command maps directly to the Read Local OOB Data HCI command. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 7 ++++ include/net/bluetooth/hci_core.h | 2 + include/net/bluetooth/mgmt.h | 6 +++ net/bluetooth/hci_event.c | 15 ++++++++ net/bluetooth/mgmt.c | 83 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 113 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 1cd031cd1c4d..ac4de1afe046 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -613,6 +613,13 @@ struct hci_cp_write_ssp_mode { __u8 mode; } __packed; +#define HCI_OP_READ_LOCAL_OOB_DATA 0x0c57 +struct hci_rp_read_local_oob_data { + __u8 status; + __u8 hash[16]; + __u8 randomizer[16]; +} __packed; + #define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58 #define HCI_OP_READ_LOCAL_VERSION 0x1001 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3912c7ab717c..fd9b8a31e5b0 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -768,6 +768,8 @@ int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status); +int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, + u8 status); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 89e7c82c4784..6ebb1265c36e 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -177,6 +177,12 @@ struct mgmt_cp_set_local_name { __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; +#define MGMT_OP_READ_LOCAL_OOB_DATA 0x0018 +struct mgmt_rp_read_local_oob_data { + __u8 hash[16]; + __u8 randomizer[16]; +} __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0def3e1fe5ef..582ef60a8bc0 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -822,6 +822,17 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, rp->status); } +static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_rp_read_local_oob_data *rp = (void *) skb->data; + + BT_DBG("%s status 0x%x", hdev->name, rp->status); + + mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash, + rp->randomizer, rp->status); +} + static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) { BT_DBG("%s status 0x%x", hdev->name, status); @@ -1752,6 +1763,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk hci_cc_pin_code_neg_reply(hdev, skb); break; + case HCI_OP_READ_LOCAL_OOB_DATA: + hci_cc_read_local_oob_data_reply(hdev, skb); + break; + case HCI_OP_LE_READ_BUFFER_SIZE: hci_cc_le_read_buffer_size(hdev, skb); break; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 93f0f04c8bcd..33b1f7400dab 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1296,6 +1296,55 @@ failed: return err; } +static int read_local_oob_data(struct sock *sk, u16 index) +{ + struct hci_dev *hdev; + struct pending_cmd *cmd; + int err; + + BT_DBG("hci%u", index); + + hdev = hci_dev_get(index); + if (!hdev) + return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, + ENODEV); + + hci_dev_lock_bh(hdev); + + if (!test_bit(HCI_UP, &hdev->flags)) { + err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, + ENETDOWN); + goto unlock; + } + + if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { + err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, + EOPNOTSUPP); + goto unlock; + } + + if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index)) { + err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY); + goto unlock; + } + + cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, index, NULL, 0); + if (!cmd) { + err = -ENOMEM; + goto unlock; + } + + err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL); + if (err < 0) + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock_bh(hdev); + hci_dev_put(hdev); + + return err; +} + int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) { unsigned char *buf; @@ -1394,6 +1443,10 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) case MGMT_OP_SET_LOCAL_NAME: err = set_local_name(sk, index, buf + sizeof(*hdr), len); break; + case MGMT_OP_READ_LOCAL_OOB_DATA: + err = read_local_oob_data(sk, index); + break; + default: BT_DBG("Unknown op %u", opcode); err = cmd_status(sk, index, opcode, 0x01); @@ -1723,3 +1776,33 @@ failed: mgmt_pending_remove(cmd); return err; } + +int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, + u8 status) +{ + struct pending_cmd *cmd; + int err; + + BT_DBG("hci%u status %u", index, status); + + cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index); + if (!cmd) + return -ENOENT; + + if (status) { + err = cmd_status(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, + EIO); + } else { + struct mgmt_rp_read_local_oob_data rp; + + memcpy(rp.hash, hash, sizeof(rp.hash)); + memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer)); + + err = cmd_complete(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, + &rp, sizeof(rp)); + } + + mgmt_pending_remove(cmd); + + return err; +} -- cgit v1.2.3-58-ga151 From 2763eda6ccaf126633bb3180f440c8f3589f0679 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 22 Mar 2011 13:12:22 +0100 Subject: Bluetooth: Add add/remove_remote_oob_data management commands This patch adds commands to add and remove remote OOB data to the managment interface. Remote data is stored in kernel and can be used by corresponding HCI commands and events when needed. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 17 +++++++++ include/net/bluetooth/hci_core.h | 16 +++++++++ include/net/bluetooth/mgmt.h | 12 +++++++ net/bluetooth/hci_core.c | 67 +++++++++++++++++++++++++++++++++++ net/bluetooth/hci_event.c | 35 +++++++++++++++++++ net/bluetooth/mgmt.c | 75 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 222 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index ac4de1afe046..b989a8c3e01a 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -426,6 +426,18 @@ struct hci_rp_user_confirm_reply { #define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d +#define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430 +struct hci_cp_remote_oob_data_reply { + bdaddr_t bdaddr; + __u8 hash[16]; + __u8 randomizer[16]; +} __packed; + +#define HCI_OP_REMOTE_OOB_DATA_NEG_REPLY 0x0433 +struct hci_cp_remote_oob_data_neg_reply { + bdaddr_t bdaddr; +} __packed; + #define HCI_OP_IO_CAPABILITY_NEG_REPLY 0x0434 struct hci_cp_io_capability_neg_reply { bdaddr_t bdaddr; @@ -962,6 +974,11 @@ struct hci_ev_user_confirm_req { __le32 passkey; } __packed; +#define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35 +struct hci_ev_remote_oob_data_request { + bdaddr_t bdaddr; +} __packed; + #define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36 struct hci_ev_simple_pair_complete { __u8 status; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index fd9b8a31e5b0..87bff518b54b 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -82,6 +82,13 @@ struct link_key { u8 pin_len; }; +struct oob_data { + struct list_head list; + bdaddr_t bdaddr; + u8 hash[16]; + u8 randomizer[16]; +}; + #define NUM_REASSEMBLY 4 struct hci_dev { struct list_head list; @@ -169,6 +176,8 @@ struct hci_dev { struct list_head link_keys; + struct list_head remote_oob_data; + struct hci_dev_stats stat; struct sk_buff_head driver_init; @@ -505,6 +514,13 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, u8 *key, u8 type, u8 pin_len); int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); +int hci_remote_oob_data_clear(struct hci_dev *hdev); +struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, + bdaddr_t *bdaddr); +int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, + u8 *randomizer); +int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); + void hci_del_off_timer(struct hci_dev *hdev); void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 6ebb1265c36e..1a6283f9fee8 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -183,6 +183,18 @@ struct mgmt_rp_read_local_oob_data { __u8 randomizer[16]; } __packed; +#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0019 +struct mgmt_cp_add_remote_oob_data { + bdaddr_t bdaddr; + __u8 hash[16]; + __u8 randomizer[16]; +} __packed; + +#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x001A +struct mgmt_cp_remove_remote_oob_data { + bdaddr_t bdaddr; +} __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index c20cbe5ff6db..675f0a1832ee 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1076,6 +1076,70 @@ static void hci_cmd_timer(unsigned long arg) tasklet_schedule(&hdev->cmd_task); } +struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, + bdaddr_t *bdaddr) +{ + struct oob_data *data; + + list_for_each_entry(data, &hdev->remote_oob_data, list) + if (bacmp(bdaddr, &data->bdaddr) == 0) + return data; + + return NULL; +} + +int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr) +{ + struct oob_data *data; + + data = hci_find_remote_oob_data(hdev, bdaddr); + if (!data) + return -ENOENT; + + BT_DBG("%s removing %s", hdev->name, batostr(bdaddr)); + + list_del(&data->list); + kfree(data); + + return 0; +} + +int hci_remote_oob_data_clear(struct hci_dev *hdev) +{ + struct oob_data *data, *n; + + list_for_each_entry_safe(data, n, &hdev->remote_oob_data, list) { + list_del(&data->list); + kfree(data); + } + + return 0; +} + +int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, + u8 *randomizer) +{ + struct oob_data *data; + + data = hci_find_remote_oob_data(hdev, bdaddr); + + if (!data) { + data = kmalloc(sizeof(*data), GFP_ATOMIC); + if (!data) + return -ENOMEM; + + bacpy(&data->bdaddr, bdaddr); + list_add(&data->list, &hdev->remote_oob_data); + } + + memcpy(data->hash, hash, sizeof(data->hash)); + memcpy(data->randomizer, randomizer, sizeof(data->randomizer)); + + BT_DBG("%s for %s", hdev->name, batostr(bdaddr)); + + return 0; +} + /* Register HCI device */ int hci_register_dev(struct hci_dev *hdev) { @@ -1140,6 +1204,8 @@ int hci_register_dev(struct hci_dev *hdev) INIT_LIST_HEAD(&hdev->link_keys); + INIT_LIST_HEAD(&hdev->remote_oob_data); + INIT_WORK(&hdev->power_on, hci_power_on); INIT_WORK(&hdev->power_off, hci_power_off); setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev); @@ -1219,6 +1285,7 @@ int hci_unregister_dev(struct hci_dev *hdev) hci_blacklist_clear(hdev); hci_uuids_clear(hdev); hci_link_keys_clear(hdev); + hci_remote_oob_data_clear(hdev); hci_dev_unlock_bh(hdev); __hci_dev_put(hdev); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 582ef60a8bc0..e0aaf3053667 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2471,6 +2471,37 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_ hci_dev_unlock(hdev); } +static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; + struct oob_data *data; + + BT_DBG("%s", hdev->name); + + hci_dev_lock(hdev); + + data = hci_find_remote_oob_data(hdev, &ev->bdaddr); + if (data) { + struct hci_cp_remote_oob_data_reply cp; + + bacpy(&cp.bdaddr, &ev->bdaddr); + memcpy(cp.hash, data->hash, sizeof(cp.hash)); + memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); + + hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), + &cp); + } else { + struct hci_cp_remote_oob_data_neg_reply cp; + + bacpy(&cp.bdaddr, &ev->bdaddr); + hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), + &cp); + } + + hci_dev_unlock(hdev); +} + static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_le_conn_complete *ev = (void *) skb->data; @@ -2673,6 +2704,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_le_meta_evt(hdev, skb); break; + case HCI_EV_REMOTE_OOB_DATA_REQUEST: + hci_remote_oob_data_request_evt(hdev, skb); + break; + default: BT_DBG("%s event 0x%x", hdev->name, event); break; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 33b1f7400dab..a42dc8ca0a6f 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1345,6 +1345,74 @@ unlock: return err; } +static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data, + u16 len) +{ + struct hci_dev *hdev; + struct mgmt_cp_add_remote_oob_data *cp = (void *) data; + int err; + + BT_DBG("hci%u ", index); + + if (len != sizeof(*cp)) + return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, + EINVAL); + + hdev = hci_dev_get(index); + if (!hdev) + return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, + ENODEV); + + hci_dev_lock_bh(hdev); + + err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash, + cp->randomizer); + if (err < 0) + err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err); + else + err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL, + 0); + + hci_dev_unlock_bh(hdev); + hci_dev_put(hdev); + + return err; +} + +static int remove_remote_oob_data(struct sock *sk, u16 index, + unsigned char *data, u16 len) +{ + struct hci_dev *hdev; + struct mgmt_cp_remove_remote_oob_data *cp = (void *) data; + int err; + + BT_DBG("hci%u ", index); + + if (len != sizeof(*cp)) + return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, + EINVAL); + + hdev = hci_dev_get(index); + if (!hdev) + return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, + ENODEV); + + hci_dev_lock_bh(hdev); + + err = hci_remove_remote_oob_data(hdev, &cp->bdaddr); + if (err < 0) + err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, + -err); + else + err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, + NULL, 0); + + hci_dev_unlock_bh(hdev); + hci_dev_put(hdev); + + return err; +} + int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) { unsigned char *buf; @@ -1446,6 +1514,13 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) case MGMT_OP_READ_LOCAL_OOB_DATA: err = read_local_oob_data(sk, index); break; + case MGMT_OP_ADD_REMOTE_OOB_DATA: + err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len); + break; + case MGMT_OP_REMOVE_REMOTE_OOB_DATA: + err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr), + len); + break; default: BT_DBG("Unknown op %u", opcode); -- cgit v1.2.3-58-ga151 From ce85ee13e6b5d078f4a6c3b02ba7cd0fa140c552 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 22 Mar 2011 13:12:23 +0100 Subject: Bluetooth: Enable support for out of band association model If remote side reports oob availability or we are pairing initiator use oob data for pairing if available. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index e0aaf3053667..da4c662dbc30 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2371,9 +2371,14 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff bacpy(&cp.bdaddr, &ev->bdaddr); cp.capability = conn->io_capability; - cp.oob_data = 0; cp.authentication = hci_get_auth_req(conn); + if ((conn->out == 0x01 || conn->remote_oob == 0x01) && + hci_find_remote_oob_data(hdev, &conn->dst)) + cp.oob_data = 0x01; + else + cp.oob_data = 0x00; + hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, sizeof(cp), &cp); } else { -- cgit v1.2.3-58-ga151 From f3dd4f0f586b3a70734820b68c69985363e2d798 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Thu, 24 Mar 2011 20:14:16 -0300 Subject: Bluetooth: Remove unused struct l2cap_conn item Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 7a0262524a50..2b9ca0d5c4a0 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -301,7 +301,6 @@ struct l2cap_conn { struct sk_buff *rx_skb; __u32 rx_len; - __u8 rx_ident; __u8 tx_ident; __u8 disc_reason; -- cgit v1.2.3-58-ga151 From d1010240fa9aac93da56a683c1295e759ee69d10 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 00:39:48 -0300 Subject: Bluetooth: Move bt_accept_enqueue() to outside __l2cap_chan_add bt_accept_enqueue() is not really a channel action, so do it outside. This patch is part of a set of patches to create an struct l2cap_chan to have a clear separation between the struct sock and the L2CAP channel stuff. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b5a1ce06e1c0..bf09f6027bd2 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -169,7 +169,7 @@ static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk) __sock_put(sk); } -static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent) +static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) { struct l2cap_chan_list *l = &conn->chan_list; @@ -204,9 +204,6 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so } __l2cap_chan_link(l, sk); - - if (parent) - bt_accept_enqueue(parent, sk); } /* Delete channel. @@ -652,7 +649,9 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) bacpy(&bt_sk(sk)->src, conn->src); bacpy(&bt_sk(sk)->dst, conn->dst); - __l2cap_chan_add(conn, sk, parent); + bt_accept_enqueue(parent, sk); + + __l2cap_chan_add(conn, sk); l2cap_sock_set_timer(sk, sk->sk_sndtimeo); @@ -793,11 +792,11 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) kfree(conn); } -static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent) +static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) { struct l2cap_chan_list *l = &conn->chan_list; write_lock_bh(&l->lock); - __l2cap_chan_add(conn, sk, parent); + __l2cap_chan_add(conn, sk); write_unlock_bh(&l->lock); } @@ -876,7 +875,7 @@ int l2cap_do_connect(struct sock *sk) /* Update source addr of the socket */ bacpy(src, conn->src); - l2cap_chan_add(conn, sk, NULL); + l2cap_chan_add(conn, sk); sk->sk_state = BT_CONNECT; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); @@ -2030,7 +2029,9 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd l2cap_pi(sk)->psm = psm; l2cap_pi(sk)->dcid = scid; - __l2cap_chan_add(conn, sk, parent); + bt_accept_enqueue(parent, sk); + + __l2cap_chan_add(conn, sk); dcid = l2cap_pi(sk)->scid; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); -- cgit v1.2.3-58-ga151 From e90165be9a4d6a1e8fa632fcae00a5294abd3981 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Fri, 25 Mar 2011 11:31:41 +0200 Subject: Bluetooth: check L2CAP info_rsp ident and state Information requests/responses are unbound to L2CAP channel. Patch fixes issue arising when two devices connects at the same time to each other. This way we do not process out of the context messages. We are safe dropping info_rsp since info_timer is left running. Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index bf09f6027bd2..033c83be3524 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -2461,6 +2461,11 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); + /* L2CAP Info req/rsp are unbound to channels, add extra checks */ + if (cmd->ident != conn->info_ident || + conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) + return 0; + del_timer(&conn->info_timer); if (result != L2CAP_IR_SUCCESS) { -- cgit v1.2.3-58-ga151 From 80a1e1dbf62a08984d4c1bfb5a4bca38c3e1664f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 28 Mar 2011 14:07:23 +0300 Subject: Bluetooth: Add local Extended Inquiry Response (EIR) support This patch adds automated creation of the local EIR data based on what 16-bit UUIDs are registered and what the device name is. This should cover the majority use cases, however things like 32/128-bit UUIDs, TX power and Device ID will need to be added later to be on par with what bluetoothd is capable of doing (without the Management interface). Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 8 ++ include/net/bluetooth/hci_core.h | 1 + net/bluetooth/mgmt.c | 163 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index b989a8c3e01a..6846ec02dcb0 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -614,6 +614,14 @@ struct hci_cp_host_buffer_size { #define HCI_OP_WRITE_INQUIRY_MODE 0x0c45 +#define HCI_MAX_EIR_LENGTH 240 + +#define HCI_OP_WRITE_EIR 0x0c52 +struct hci_cp_write_eir { + uint8_t fec; + uint8_t data[HCI_MAX_EIR_LENGTH]; +} __packed; + #define HCI_OP_READ_SSP_MODE 0x0c55 struct hci_rp_read_ssp_mode { __u8 status; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 87bff518b54b..3b2f09df279a 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -102,6 +102,7 @@ struct hci_dev { __u8 dev_type; bdaddr_t bdaddr; __u8 dev_name[HCI_MAX_NAME_LENGTH]; + __u8 eir[HCI_MAX_EIR_LENGTH]; __u8 dev_class[3]; __u8 major_class; __u8 minor_class; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a42dc8ca0a6f..62055c9a8084 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -544,6 +544,150 @@ failed: return err; } +#define EIR_FLAGS 0x01 /* flags */ +#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */ +#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */ +#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */ +#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */ +#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */ +#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */ +#define EIR_NAME_SHORT 0x08 /* shortened local name */ +#define EIR_NAME_COMPLETE 0x09 /* complete local name */ +#define EIR_TX_POWER 0x0A /* transmit power level */ +#define EIR_DEVICE_ID 0x10 /* device ID */ + +#define PNP_INFO_SVCLASS_ID 0x1200 + +static u8 bluetooth_base_uuid[] = { + 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static u16 get_uuid16(u8 *uuid128) +{ + u32 val; + int i; + + for (i = 0; i < 12; i++) { + if (bluetooth_base_uuid[i] != uuid128[i]) + return 0; + } + + memcpy(&val, &uuid128[12], 4); + + val = le32_to_cpu(val); + if (val > 0xffff) + return 0; + + return (u16) val; +} + +static void create_eir(struct hci_dev *hdev, u8 *data) +{ + u8 *ptr = data; + u16 eir_len = 0; + u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)]; + int i, truncated = 0; + struct list_head *p; + size_t name_len; + + name_len = strlen(hdev->dev_name); + + if (name_len > 0) { + /* EIR Data type */ + if (name_len > 48) { + name_len = 48; + ptr[1] = EIR_NAME_SHORT; + } else + ptr[1] = EIR_NAME_COMPLETE; + + /* EIR Data length */ + ptr[0] = name_len + 1; + + memcpy(ptr + 2, hdev->dev_name, name_len); + + eir_len += (name_len + 2); + ptr += (name_len + 2); + } + + memset(uuid16_list, 0, sizeof(uuid16_list)); + + /* Group all UUID16 types */ + list_for_each(p, &hdev->uuids) { + struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list); + u16 uuid16; + + uuid16 = get_uuid16(uuid->uuid); + if (uuid16 == 0) + return; + + if (uuid16 < 0x1100) + continue; + + if (uuid16 == PNP_INFO_SVCLASS_ID) + continue; + + /* Stop if not enough space to put next UUID */ + if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) { + truncated = 1; + break; + } + + /* Check for duplicates */ + for (i = 0; uuid16_list[i] != 0; i++) + if (uuid16_list[i] == uuid16) + break; + + if (uuid16_list[i] == 0) { + uuid16_list[i] = uuid16; + eir_len += sizeof(u16); + } + } + + if (uuid16_list[0] != 0) { + u8 *length = ptr; + + /* EIR Data type */ + ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL; + + ptr += 2; + eir_len += 2; + + for (i = 0; uuid16_list[i] != 0; i++) { + *ptr++ = (uuid16_list[i] & 0x00ff); + *ptr++ = (uuid16_list[i] & 0xff00) >> 8; + } + + /* EIR Data length */ + *length = (i * sizeof(u16)) + 1; + } +} + +static int update_eir(struct hci_dev *hdev) +{ + struct hci_cp_write_eir cp; + + if (!(hdev->features[6] & LMP_EXT_INQ)) + return 0; + + if (hdev->ssp_mode == 0) + return 0; + + if (test_bit(HCI_SERVICE_CACHE, &hdev->flags)) + return 0; + + memset(&cp, 0, sizeof(cp)); + + create_eir(hdev, cp.data); + + if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) + return 0; + + memcpy(hdev->eir, cp.data, sizeof(cp.data)); + + return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); +} + static u8 get_service_classes(struct hci_dev *hdev) { struct list_head *p; @@ -612,6 +756,10 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) if (err < 0) goto failed; + err = update_eir(hdev); + if (err < 0) + goto failed; + err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0); failed: @@ -668,6 +816,10 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) if (err < 0) goto unlock; + err = update_eir(hdev); + if (err < 0) + goto unlock; + err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0); unlock: @@ -737,6 +889,8 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, } else { clear_bit(HCI_SERVICE_CACHE, &hdev->flags); err = update_class(hdev); + if (err == 0) + err = update_eir(hdev); } if (err == 0) @@ -1822,6 +1976,7 @@ int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status) int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status) { struct pending_cmd *cmd; + struct hci_dev *hdev; struct mgmt_cp_set_local_name ev; int err; @@ -1837,6 +1992,14 @@ int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status) goto failed; } + hdev = hci_dev_get(index); + if (hdev) { + hci_dev_lock_bh(hdev); + update_eir(hdev); + hci_dev_unlock_bh(hdev); + hci_dev_put(hdev); + } + err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev, sizeof(ev)); if (err < 0) -- cgit v1.2.3-58-ga151 From 88d377b6c3c28ee54cd4c76bfe6e60f2d9bf6ae1 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Thu, 24 Mar 2011 14:51:21 -0300 Subject: Bluetooth: add support for Apple MacBook Pro 8,2 Just adding the vendor details makes it work fine. Signed-off-by: Marc-Antoine Perennou Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 866811428e20..2af2e770f4bd 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -71,6 +71,9 @@ static struct usb_device_id btusb_table[] = { /* Apple MacBookAir3,1, MacBookAir3,2 */ { USB_DEVICE(0x05ac, 0x821b) }, + /* Apple MacBookPro8,2 */ + { USB_DEVICE(0x05ac, 0x821a) }, + /* AVM BlueFRITZ! USB v2.0 */ { USB_DEVICE(0x057c, 0x3800) }, -- cgit v1.2.3-58-ga151 From 23e9fde2b344c22c5176c7fd37b52c3776ef5aba Mon Sep 17 00:00:00 2001 From: Suraj Sumangala Date: Wed, 9 Mar 2011 14:44:05 +0530 Subject: Bluetooth: Increment unacked_frames count only the first transmit This patch lets 'l2cap_pinfo.unacked_frames' be incremented only the first time a frame is transmitted. Previously it was being incremented for retransmitted packets too resulting the value to cross the transmit window size. Signed-off-by: Suraj Sumangala Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c9f9cecca527..ca27f3a41536 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1116,7 +1116,9 @@ int l2cap_ertm_send(struct sock *sk) bt_cb(skb)->tx_seq = pi->next_tx_seq; pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; - pi->unacked_frames++; + if (bt_cb(skb)->retries == 1) + pi->unacked_frames++; + pi->frames_sent++; if (skb_queue_is_last(TX_QUEUE(sk), skb)) -- cgit v1.2.3-58-ga151 From 105721328f0fa53e772592eaca17ee0023f0cc87 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 16 Mar 2011 15:36:29 -0300 Subject: Bluetooth: Fix HCI_RESET command synchronization We can't send new commands before a cmd_complete for the HCI_RESET command shows up. Reported-by: Mikko Vinni Reported-by: Justin P. Mattock Reported-by: Ed Tomlinson Signed-off-by: Gustavo F. Padovan Tested-by: Justin P. Mattock Tested-by: Mikko Vinni Tested-by: Ed Tomlinson --- include/net/bluetooth/hci.h | 2 ++ net/bluetooth/hci_core.c | 6 +++++- net/bluetooth/hci_event.c | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index ec6acf2f1c0b..2c0d309c7381 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -84,6 +84,8 @@ enum { HCI_SERVICE_CACHE, HCI_LINK_KEYS, HCI_DEBUG_KEYS, + + HCI_RESET, }; /* HCI ioctl defines */ diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index b372fb8bcdcf..92b48e257b89 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -186,6 +186,7 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt) BT_DBG("%s %ld", hdev->name, opt); /* Reset device */ + set_bit(HCI_RESET, &hdev->flags); hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); } @@ -213,8 +214,10 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) /* Mandatory initialization */ /* Reset */ - if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) + if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) { + set_bit(HCI_RESET, &hdev->flags); hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); + } /* Read Local Supported Features */ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); @@ -1074,6 +1077,7 @@ static void hci_cmd_timer(unsigned long arg) BT_ERR("%s command tx timeout", hdev->name); atomic_set(&hdev->cmd_cnt, 1); + clear_bit(HCI_RESET, &hdev->flags); tasklet_schedule(&hdev->cmd_task); } diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 3fbfa50c2bff..cebe7588469f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -183,6 +183,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) BT_DBG("%s status 0x%x", hdev->name, status); + clear_bit(HCI_RESET, &hdev->flags); + hci_req_complete(hdev, HCI_OP_RESET, status); } @@ -1847,7 +1849,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) if (ev->opcode != HCI_OP_NOP) del_timer(&hdev->cmd_timer); - if (ev->ncmd) { + if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { atomic_set(&hdev->cmd_cnt, 1); if (!skb_queue_empty(&hdev->cmd_q)) tasklet_schedule(&hdev->cmd_task); -- cgit v1.2.3-58-ga151 From 8693ac900e230c85d6fff428984a0f983330844d Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Mon, 14 Mar 2011 18:20:33 -0300 Subject: Bluetooth: Fix sending LE data over USB Now that we have support for LE connections, before discarding a frame we must check if there's a LE connection over that transport. Signed-off-by: Vinicius Costa Gomes Acked-by: Ville Tervo Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/btusb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 2af2e770f4bd..762a5109c68a 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -693,7 +693,8 @@ static int btusb_send_frame(struct sk_buff *skb) break; case HCI_ACLDATA_PKT: - if (!data->bulk_tx_ep || hdev->conn_hash.acl_num < 1) + if (!data->bulk_tx_ep || (hdev->conn_hash.acl_num < 1 && + hdev->conn_hash.le_num < 1)) return -ENODEV; urb = usb_alloc_urb(0, GFP_ATOMIC); -- cgit v1.2.3-58-ga151 From 08ba53824a7fb224085a0ff73eab213cab0197e9 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 16 Mar 2011 14:29:34 +0200 Subject: Bluetooth: Fix missing hci_dev_lock_bh in user_confirm_reply The code was correctly calling _unlock at the end of the function but there was no actual _lock call anywhere. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/mgmt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 0054c74e27b7..4476d8e3c0f2 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1230,6 +1230,8 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, if (!hdev) return cmd_status(sk, index, mgmt_op, ENODEV); + hci_dev_lock_bh(hdev); + if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, mgmt_op, ENETDOWN); goto failed; -- cgit v1.2.3-58-ga151 From 34bd0273b631742e8d929c80e90cb7782105d8da Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 24 Mar 2011 17:16:08 +0200 Subject: Bluetooth: delete hanging L2CAP channel Sometimes L2CAP connection remains hanging. Make sure that L2CAP channel is deleted. Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index fc85e7ae33c7..f77308e63e58 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -923,8 +923,9 @@ void __l2cap_sock_close(struct sock *sk, int reason) rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); l2cap_send_cmd(conn, l2cap_pi(sk)->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); - } else - l2cap_chan_del(sk, reason); + } + + l2cap_chan_del(sk, reason); break; case BT_CONNECT: -- cgit v1.2.3-58-ga151 From 6f5ef998b7b0b1bf1471654bf6176a5419197128 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 24 Mar 2011 20:16:42 +0100 Subject: Bluetooth: Fix warning with hci_cmd_timer After we made debugobjects working again, we got the following: WARNING: at lib/debugobjects.c:262 debug_print_object+0x8e/0xb0() Hardware name: System Product Name ODEBUG: free active (active state 0) object type: timer_list hint: hci_cmd_timer+0x0/0x60 Pid: 2125, comm: dmsetup Tainted: G W 2.6.38-06707-gc62b389 #110375 Call Trace: [] warn_slowpath_common+0x7a/0xb0 [] warn_slowpath_fmt+0x46/0x50 [] debug_print_object+0x8e/0xb0 [] ? hci_cmd_timer+0x0/0x60 [] debug_check_no_obj_freed+0x125/0x230 [] ? check_object+0xb3/0x2b0 [] kfree+0x150/0x190 [] ? bt_host_release+0x16/0x20 [] bt_host_release+0x16/0x20 [] device_release+0x27/0xa0 [] kobject_release+0x4c/0xa0 [] ? kobject_release+0x0/0xa0 [] kref_put+0x36/0x70 [] kobject_put+0x27/0x60 [] put_device+0x17/0x20 [] hci_free_dev+0x29/0x30 [] vhci_release+0x36/0x70 [] fput+0xd6/0x1f0 [] filp_close+0x66/0x90 [] sys_close+0x99/0xf0 [] system_call_fastpath+0x16/0x1b That timer was introduced with commit 6bd32326cda(Bluetooth: Use proper timer for hci command timout) Timer seems to be running when the thing is closed. Removing the timer unconditionally fixes the problem. And yes, it needs to be fixed before the HCI_UP check. Signed-off-by: Thomas Gleixner Tested-by: Ingo Molnar Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 92b48e257b89..2216620ff296 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -587,6 +587,9 @@ static int hci_dev_do_close(struct hci_dev *hdev) hci_req_cancel(hdev, ENODEV); hci_req_lock(hdev); + /* Stop timer, it might be running */ + del_timer_sync(&hdev->cmd_timer); + if (!test_and_clear_bit(HCI_UP, &hdev->flags)) { hci_req_unlock(hdev); return 0; @@ -626,7 +629,6 @@ static int hci_dev_do_close(struct hci_dev *hdev) /* Drop last sent command */ if (hdev->sent_cmd) { - del_timer_sync(&hdev->cmd_timer); kfree_skb(hdev->sent_cmd); hdev->sent_cmd = NULL; } -- cgit v1.2.3-58-ga151 From 96b8e1a0e96bd30ffb07e739b29b8c4c5759b93f Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Thu, 31 Mar 2011 17:03:36 -0700 Subject: bnx2x: Update firmware to 6.2.9 To fix bugs when running offloaded FCoE/iSCSI traffic in multiple Class of Service environments. In some scenarios, traffic could stop on certain rings and eventually all traffic would stop. Signed-off-by: Dmitry Kravkov Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_hsi.h | 2 +- firmware/Makefile | 6 +- firmware/WHENCE | 9 +- firmware/bnx2x/bnx2x-e1-6.2.5.0.fw.ihex | 9483 ------------------ firmware/bnx2x/bnx2x-e1-6.2.9.0.fw.ihex | 9484 ++++++++++++++++++ firmware/bnx2x/bnx2x-e1h-6.2.5.0.fw.ihex | 13181 ------------------------ firmware/bnx2x/bnx2x-e1h-6.2.9.0.fw.ihex | 13192 ++++++++++++++++++++++++ firmware/bnx2x/bnx2x-e2-6.2.5.0.fw.ihex | 15456 ---------------------------- firmware/bnx2x/bnx2x-e2-6.2.9.0.fw.ihex | 15473 +++++++++++++++++++++++++++++ 9 files changed, 38158 insertions(+), 38128 deletions(-) delete mode 100644 firmware/bnx2x/bnx2x-e1-6.2.5.0.fw.ihex create mode 100644 firmware/bnx2x/bnx2x-e1-6.2.9.0.fw.ihex delete mode 100644 firmware/bnx2x/bnx2x-e1h-6.2.5.0.fw.ihex create mode 100644 firmware/bnx2x/bnx2x-e1h-6.2.9.0.fw.ihex delete mode 100644 firmware/bnx2x/bnx2x-e2-6.2.5.0.fw.ihex create mode 100644 firmware/bnx2x/bnx2x-e2-6.2.9.0.fw.ihex diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h index be503cc0a50b..d9d0184b8c22 100644 --- a/drivers/net/bnx2x/bnx2x_hsi.h +++ b/drivers/net/bnx2x/bnx2x_hsi.h @@ -1929,7 +1929,7 @@ struct host_func_stats { #define BCM_5710_FW_MAJOR_VERSION 6 #define BCM_5710_FW_MINOR_VERSION 2 -#define BCM_5710_FW_REVISION_VERSION 5 +#define BCM_5710_FW_REVISION_VERSION 9 #define BCM_5710_FW_ENGINEERING_VERSION 0 #define BCM_5710_FW_COMPILE_FLAGS 1 diff --git a/firmware/Makefile b/firmware/Makefile index 0384afa93de9..0d15a3d113a2 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -32,9 +32,9 @@ fw-shipped-$(CONFIG_ADAPTEC_STARFIRE) += adaptec/starfire_rx.bin \ adaptec/starfire_tx.bin fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw -fw-shipped-$(CONFIG_BNX2X) += bnx2x/bnx2x-e1-6.2.5.0.fw \ - bnx2x/bnx2x-e1h-6.2.5.0.fw \ - bnx2x/bnx2x-e2-6.2.5.0.fw +fw-shipped-$(CONFIG_BNX2X) += bnx2x/bnx2x-e1-6.2.9.0.fw \ + bnx2x/bnx2x-e1h-6.2.9.0.fw \ + bnx2x/bnx2x-e2-6.2.9.0.fw fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-6.2.1a.fw \ bnx2/bnx2-rv2p-09-6.0.17.fw \ bnx2/bnx2-rv2p-09ax-6.0.17.fw \ diff --git a/firmware/WHENCE b/firmware/WHENCE index 76404f9ce74d..182ecb6c275e 100644 --- a/firmware/WHENCE +++ b/firmware/WHENCE @@ -679,14 +679,15 @@ Found in hex form in kernel source. Driver: bnx2x: Broadcom Everest -File: bnx2x/bnx2x-e1-5.2.13.0.fw -File: bnx2x/bnx2x-e1h-5.2.13.0.fw +File: bnx2x/bnx2x-e1-6.2.9.0.fw +File: bnx2x/bnx2x-e1h-6.2.9.0.fw +File: bnx2x/bnx2x-e2-6.2.9.0.fw License: - Copyright (c) 2007-2010 Broadcom Corporation + Copyright (c) 2007-2011 Broadcom Corporation This file contains firmware data derived from proprietary unpublished - source code, Copyright (c) 2007-2009 Broadcom Corporation. + source code, Copyright (c) 2007-2011 Broadcom Corporation. Permission is hereby granted for the distribution of this firmware data in hexadecimal or equivalent format, provided this copyright notice is diff --git a/firmware/bnx2x/bnx2x-e1-6.2.5.0.fw.ihex b/firmware/bnx2x/bnx2x-e1-6.2.5.0.fw.ihex deleted file mode 100644 index 1b535827a742..000000000000 --- a/firmware/bnx2x/bnx2x-e1-6.2.5.0.fw.ihex +++ /dev/null @@ -1,9483 +0,0 @@ -:1000000000003BB0000000680000070C00003C202E -:1000100000001AF8000043300000007C00005E3051 -:1000200000007A2C00005EB0000000B00000D8E0B4 -:10003000000080200000D99800000088000159C00D -:100040000000398800015A5000000090000193E040 -:100050000000ABFC0001947800000FFC0002407827 -:100060000000000400025078020400480000000F65 -:100070000204005400000045020400580000000083 -:100080000204005C0000000602040070000000048E -:1000900002040078000000000204007C1217000037 -:1000A00002040080221700000204008432170000BE -:1000B00006040088000000050204009C12150000E0 -:1000C000020400A022150000020400A43215000062 -:1000D000060400A800000004020400B8021000009A -:1000E000020400BC00100000020400C01010000058 -:1000F000020400C420100000020400C830100000F8 -:10010000060400CC00000004020400DC0010000023 -:10011000020400E012140000020400E422140000B3 -:10012000020400E832140000060400EC00000004A1 -:100130000104012400000000010401280000000067 -:100140000104012C00000000010401300000000047 -:1001500002040004000000FF02040008000000FF89 -:100160000204000C000000FF02040010000000FF69 -:1001700002040014000000FF02040018000000FF49 -:100180000204001C000000FF02040020000000FF29 -:10019000020400240000003E0204002800000000C9 -:1001A0000204002C0000003F020400300000003F69 -:1001B000020400340000003F020400380000000088 -:1001C0000204003C0000003F020400400000003F29 -:1001D000020400440000003F020420080000021155 -:1001E0000204200C0000020002042010000002049F -:1001F00002042014000002190204201C0000FFFF6A -:10020000020420200000FFFF020420240000FFFF62 -:10021000020420280000FFFF0604203800000080B0 -:100220000204223807FFFFFF0204223C0000003FC7 -:100230000204224007FFFFFF020422440000000FD7 -:1002400001042248000000000104224C00000000CC -:1002500001042250000000000104225400000000AC -:1002600001042258000000000104225C000000008C -:10027000010422600000000001042264000000006C -:1002800001042268000000000104226C000000004C -:10029000010422700000000001042274000000002C -:1002A00001042278000000000104227C000000000C -:1002B000020424BC000000010C042000000003E83C -:1002C0000A042000000000010B0420000000000AC6 -:1002D0000605400000000D0002050044000000205B -:1002E00002050048000000320205009002150020BF -:1002F000020500940215002002050098000000305D -:100300000205009C08100000020500A00000003358 -:10031000020500A400000030020500A80000003122 -:10032000020500AC00000002020500B0000000055C -:10033000020500B400000006020500B8000000023B -:10034000020500BC00000002020500C00000000021 -:10035000020500C400000005020500C800000002FC -:10036000020500CC00000002020500D000000002DF -:10037000020500D400000001020501140000000184 -:100380000205011C0000000102050120000000021E -:1003900002050204000000010205020C00000040FA -:1003A00002050210000000400205021C00000020AF -:1003B00002050220000000130205022400000020B4 -:1003C000060502400000000A04050280002000002B -:1003D000020500500000000702050054000000075D -:1003E00002050058000000000205005C0000000843 -:1003F0000605006000000004020500D800000006A9 -:10040000020500E00000000D020500E40000002DE0 -:10041000020500E800000000020500EC00000020DA -:10042000020500F000000000020500F400000020BA -:10043000020500F800000000020500FC000000209A -:100440000205000400000001020500080000000190 -:100450000205000C00000001020500100000000170 -:100460000205001400000001020500180000000150 -:100470000205001C00000001020500200000000130 -:100480000205002400000001020500280000000110 -:100490000205002C000000010205003000000001F0 -:1004A00002050034000000010205003800000001D0 -:1004B0000205003C000000010205004000000001B0 -:1004C0000406100002000020020600DC000000010B -:1004D000010600D80000000004060200000302200C -:1004E000020600DC0000000002060068000000B800 -:1004F0000206007800000114010600B800000000A8 -:10050000010600C8000000000206006C000000B8F0 -:100510000206007C00000114010600BC000000007F -:10052000010600CC0000000007180400007B00005A -:100530000818076000140223071C00002A040000AA -:10054000071C800032110A82071D00001E0C1707CD -:10055000081D4550575602250118000000000000F4 -:10056000011800040000000001180008000000004D -:100570000118000C0000000001180010000000002D -:100580000118001400000000021800200000000103 -:1005900002180024000000020218002800000003D6 -:1005A0000218002C000000000218003000000004B7 -:1005B000021800340000000102180038000000009A -:1005C0000218003C00000001021800400000000476 -:1005D000021800440000000002180048000000015A -:1005E0000218004C00000003021800500000000038 -:1005F0000218005400000001021800580000000416 -:100600000218005C000000000218006000000001F9 -:1006100002180064000000030218006800000000D7 -:100620000218006C000000010218007000000004B5 -:100630000218007400000000021800780000000496 -:100640000218007C00000003061800800000000271 -:10065000021800A400003FFF021800A8000003FFDA -:1006600002180224000000000218023400000000FA -:100670000218024C00000000021802E4000000FF13 -:100680000618100000000400021B8BC000000001CF -:10069000021B800000000034021B80400000001894 -:1006A000021B80800000000C021B80C000000020A4 -:1006B0000C1B83000007A1200A1B830000000138E7 -:1006C0000B1B8300000013880A1B834000000000FE -:1006D0000C1B8340000001F40B1B8340000000054D -:1006E000021B83800007A120021B83C0000001F4CD -:1006F000061A100000000273041A19CC0001022728 -:10070000061A2008000000C8061A20000000000297 -:10071000041A499800040228061A2E280000000234 -:10072000061A2E2000000002061A0800000000022F -:10073000061A080800000004061A08180000000243 -:10074000041A08B00002022C061A2FD0000000067E -:10075000041A2FE80002022E041A2FC000040230EF -:10076000041A300000010234061A300400000003AD -:10077000041A301000010235061A3014000000037C -:10078000041A302000010236061A3024000000034B -:10079000041A303000010237061A3034000000031A -:1007A000041A304000010238061A304400000003E9 -:1007B000041A305000010239061A305400000003B8 -:1007C000041A30600001023A061A30640000000387 -:1007D000041A30700001023B061A30740000000356 -:1007E000041A30800001023C061A30840000000325 -:1007F000041A30900001023D061A309400000003F4 -:10080000041A30A00001023E061A30A400000003C2 -:10081000041A30B00001023F061A30B40000000391 -:10082000041A30C000010240061A30C40000000360 -:10083000041A30D000010241061A30D4000000032F -:10084000041A30E000010242061A30E400000003FE -:10085000041A30F000010243061A30F400000003CD -:10086000041A310000010244061A3104000000039A -:10087000041A311000010245061A31140000000369 -:10088000041A312000010246061A31240000000338 -:10089000041A313000010247061A31340000000307 -:1008A000041A314000010248061A314400000003D6 -:1008B000041A315000010249061A315400000003A5 -:1008C000041A31600001024A061A31640000000374 -:1008D000041A31700001024B061A31740000000343 -:1008E000041A31800001024C061A31840000000312 -:1008F000041A31900001024D061A319400000003E1 -:10090000041A31A00001024E061A31A400000003AF -:10091000041A31B00001024F061A31B4000000037E -:10092000041A31C000010250061A31C4000000034D -:10093000041A31D000010251061A31D4000000031C -:10094000041A31E000010252061A31E400000003EB -:10095000041A31F000010253061A31F400000003BA -:10096000041A320000010254061A32040000000387 -:10097000041A321000010255061A32140000000356 -:10098000041A322000010256061A32240000000325 -:10099000041A323000010257061A323400000003F4 -:1009A000041A324000010258061A324400000003C3 -:1009B000041A325000010259061A32540000000392 -:1009C000041A32600001025A061A32640000000361 -:1009D000041A32700001025B061A32740000000330 -:1009E000041A32800001025C061A328400000003FF -:1009F000041A32900001025D061A329400000003CE -:100A0000041A32A00001025E061A32A4000000039C -:100A1000041A32B00001025F061A32B4000000036B -:100A2000041A32C000010260061A32C4000000033A -:100A3000041A32D000010261061A32D40000000309 -:100A4000041A32E000010262061A32E400000003D8 -:100A5000041A32F000010263061A32F400000003A7 -:100A6000041A330000010264061A33040000000374 -:100A7000041A331000010265061A33140000000343 -:100A8000041A332000010266061A33240000000312 -:100A9000041A333000010267061A333400000003E1 -:100AA000041A334000010268061A334400000003B0 -:100AB000041A335000010269061A3354000000037F -:100AC000041A33600001026A061A3364000000034E -:100AD000041A33700001026B061A3374000000031D -:100AE000041A33800001026C061A338400000003EC -:100AF000041A33900001026D061A339400000003BB -:100B0000041A33A00001026E061A33A40000000389 -:100B1000041A33B00001026F061A33B40000000358 -:100B2000041A33C000010270061A33C40000000327 -:100B3000041A33D000010271061A33D400000003F6 -:100B4000041A33E000010272061A33E400000003C5 -:100B5000041A33F000010273061A33F40000000394 -:100B6000041A340000010274061A34040000000361 -:100B7000041A341000010275061A34140000000330 -:100B8000041A342000010276061A342400000003FF -:100B9000041A343000010277061A343400000003CE -:100BA000041A344000010278061A3444000000039D -:100BB000041A345000010279061A3454000000036C -:100BC000041A34600001027A061A3464000000033B -:100BD000041A34700001027B061A3474000000030A -:100BE000041A34800001027C061A348400000003D9 -:100BF000041A34900001027D061A349400000003A8 -:100C0000041A34A00001027E061A34A40000000376 -:100C1000041A34B00001027F061A34B40000000345 -:100C2000041A34C000010280061A34C40000000314 -:100C3000041A34D000010281061A34D400000003E3 -:100C4000041A34E000010282061A34E400000003B2 -:100C5000041A34F000010283061A34F40000000381 -:100C6000041A350000010284061A3504000000034E -:100C7000041A351000010285061A3514000000031D -:100C8000041A352000010286061A352400000003EC -:100C9000041A353000010287061A353400000003BB -:100CA000041A354000010288061A3544000000038A -:100CB000041A355000010289061A35540000000359 -:100CC000041A35600001028A061A35640000000328 -:100CD000041A35700001028B061A357400000003F7 -:100CE000041A35800001028C061A358400000003C6 -:100CF000041A35900001028D061A35940000000395 -:100D0000041A35A00001028E061A35A40000000363 -:100D1000041A35B00001028F061A35B40000000332 -:100D2000041A35C000010290061A35C40000000301 -:100D3000041A35D000010291061A35D400000003D0 -:100D4000041A35E000010292061A35E4000000039F -:100D5000041A35F000010293061A35F4000000036E -:100D6000041A360000010294061A3604000000033B -:100D7000041A361000010295061A3614000000030A -:100D8000041A362000010296061A362400000003D9 -:100D9000041A363000010297061A363400000003A8 -:100DA000041A364000010298061A36440000000377 -:100DB000041A365000010299061A36540000000346 -:100DC000041A36600001029A061A36640000000315 -:100DD000041A36700001029B061A367400000003E4 -:100DE000041A36800001029C061A368400000003B3 -:100DF000041A36900001029D061A36940000000382 -:100E0000041A36A00001029E061A36A40000000350 -:100E1000041A36B00001029F061A36B4000000031F -:100E2000041A36C0000102A0061A36C400000003EE -:100E3000041A36D0000102A1061A36D400000003BD -:100E4000041A36E0000102A2061A36E4000000038C -:100E5000041A36F0000102A3061A36F4000000035B -:100E6000041A3700000102A4061A37040000000328 -:100E7000041A3710000102A5061A371400000003F7 -:100E8000041A3720000102A6061A372400000003C6 -:100E9000041A3730000102A7061A37340000000395 -:100EA000041A3740000102A8061A37440000000364 -:100EB000041A3750000102A9061A37540000000333 -:100EC000041A3760000102AA061A37640000000302 -:100ED000041A3770000102AB061A377400000003D1 -:100EE000041A3780000102AC061A378400000003A0 -:100EF000041A3790000102AD061A3794000000036F -:100F0000041A37A0000102AE061A37A4000000033D -:100F1000041A37B0000102AF061A37B4000000030C -:100F2000041A37C0000102B0061A37C400000003DB -:100F3000041A37D0000102B1061A37D400000003AA -:100F4000041A37E0000102B2061A37E40000000379 -:100F5000041A37F0000102B3061A37F40000000348 -:100F6000041A3800000102B4061A38040000000315 -:100F7000041A3810000102B5061A381400000003E4 -:100F8000041A3820000102B6061A382400000003B3 -:100F9000041A3830000102B7061A38340000000382 -:100FA000041A3840000102B8061A38440000000351 -:100FB000041A3850000102B9061A38540000000320 -:100FC000041A3860000102BA061A386400000003EF -:100FD000041A3870000102BB061A387400000003BE -:100FE000041A3880000102BC061A3884000000038D -:100FF000041A3890000102BD061A3894000000035C -:10100000041A38A0000102BE061A38A4000000032A -:10101000041A38B0000102BF061A38B400000003F9 -:10102000041A38C0000102C0061A38C400000003C8 -:10103000041A38D0000102C1061A38D40000000397 -:10104000041A38E0000102C2061A38E40000000366 -:10105000041A38F0000102C3061A38F40000000335 -:10106000041A3900000102C4061A39040000000302 -:10107000041A3910000102C5061A391400000003D1 -:10108000041A3920000102C6061A392400000003A0 -:10109000041A3930000102C7061A3934000000036F -:1010A000041A3940000102C8061A3944000000033E -:1010B000041A3950000102C9061A3954000000030D -:1010C000041A3960000102CA061A396400000003DC -:1010D000041A3970000102CB061A397400000003AB -:1010E000041A3980000102CC061A3984000000037A -:1010F000041A3990000102CD061A39940000000349 -:10110000041A39A0000102CE061A39A40000000317 -:10111000041A39B0000102CF061A39B400000003E6 -:10112000041A39C0000102D0061A39C400000003B5 -:10113000041A39D0000102D1061A39D40000000384 -:10114000041A39E0000102D2061A39E40000000353 -:10115000041A39F0000102D3061A39F40000000322 -:10116000041A3A00000102D4061A3A0400000003EF -:10117000041A3A10000102D5061A3A1400000003BE -:10118000041A3A20000102D6061A3A24000000038D -:10119000041A3A30000102D7061A3A34000000035C -:1011A000041A3A40000102D8061A3A44000000032B -:1011B000041A3A50000102D9061A3A5400000003FA -:1011C000041A3A60000102DA061A3A6400000003C9 -:1011D000041A3A70000102DB061A3A740000000398 -:1011E000041A3A80000102DC061A3A840000000367 -:1011F000041A3A90000102DD061A3A940000000336 -:10120000041A3AA0000102DE061A3AA40000000304 -:10121000041A3AB0000102DF061A3AB400000003D3 -:10122000041A3AC0000102E0061A3AC400000003A2 -:10123000041A3AD0000102E1061A3AD40000000371 -:10124000041A3AE0000102E2061A3AE40000000340 -:10125000041A3AF0000102E3061A3AF4000000030F -:10126000041A3B00000102E4061A3B0400000003DC -:10127000041A3B10000102E5061A3B1400000003AB -:10128000041A3B20000102E6061A3B24000000037A -:10129000041A3B30000102E7061A3B340000000349 -:1012A000041A3B40000102E8061A3B440000000318 -:1012B000041A3B50000102E9061A3B5400000003E7 -:1012C000041A3B60000102EA061A3B6400000003B6 -:1012D000041A3B70000102EB061A3B740000000385 -:1012E000041A3B80000102EC061A3B840000000354 -:1012F000041A3B90000102ED061A3B940000000323 -:10130000041A3BA0000102EE061A3BA400000003F1 -:10131000041A3BB0000102EF061A3BB400000003C0 -:10132000041A3BC0000102F0061A3BC4000000038F -:10133000041A3BD0000102F1061A3BD4000000035E -:10134000041A3BE0000102F2061A3BE4000000032D -:10135000041A3BF0000102F3061A3BF400000003FC -:10136000041A3C00000102F4061A3C0400000003C9 -:10137000041A3C10000102F5061A3C140000000398 -:10138000041A3C20000102F6061A3C240000000367 -:10139000041A3C30000102F7061A3C340000000336 -:1013A000041A3C40000102F8061A3C440000000305 -:1013B000041A3C50000102F9061A3C5400000003D4 -:1013C000041A3C60000102FA061A3C6400000003A3 -:1013D000041A3C70000102FB061A3C740000000372 -:1013E000041A3C80000102FC061A3C840000000341 -:1013F000041A3C90000102FD061A3C940000000310 -:10140000041A3CA0000102FE061A3CA400000003DE -:10141000041A3CB0000102FF061A3CB400000003AD -:10142000041A3CC000010300061A3CC4000000037B -:10143000041A3CD000010301061A3CD4000000034A -:10144000041A3CE000010302061A3CE40000000319 -:10145000041A3CF000010303061A3CF400000003E8 -:10146000041A3D0000010304061A3D0400000003B5 -:10147000041A3D1000010305061A3D140000000384 -:10148000041A3D2000010306061A3D240000000353 -:10149000041A3D3000010307061A3D340000000322 -:1014A000041A3D4000010308061A3D4400000003F1 -:1014B000041A3D5000010309061A3D5400000003C0 -:1014C000041A3D600001030A061A3D64000000038F -:1014D000041A3D700001030B061A3D74000000035E -:1014E000041A3D800001030C061A3D84000000032D -:1014F000041A3D900001030D061A3D9400000003FC -:10150000041A3DA00001030E061A3DA400000003CA -:10151000041A3DB00001030F061A3DB40000000399 -:10152000041A3DC000010310061A3DC40000000368 -:10153000041A3DD000010311061A3DD40000000337 -:10154000041A3DE000010312061A3DE40000000306 -:10155000041A3DF000010313061A3DF400000003D5 -:10156000041A3E0000010314061A3E0400000003A2 -:10157000041A3E1000010315061A3E140000000371 -:10158000041A3E2000010316061A3E240000000340 -:10159000041A3E3000010317061A3E34000000030F -:1015A000041A3E4000010318061A3E4400000003DE -:1015B000041A3E5000010319061A3E5400000003AD -:1015C000041A3E600001031A061A3E64000000037C -:1015D000041A3E700001031B061A3E74000000034B -:1015E000041A3E800001031C061A3E84000000031A -:1015F000041A3E900001031D061A3E9400000003E9 -:10160000041A3EA00001031E061A3EA400000003B7 -:10161000041A3EB00001031F061A3EB40000000386 -:10162000041A3EC000010320061A3EC40000000355 -:10163000041A3ED000010321061A3ED40000000324 -:10164000041A3EE000010322061A3EE400000003F3 -:10165000041A3EF000010323061A3EF400000003C2 -:10166000041A3F0000010324061A3F04000000038F -:10167000041A3F1000010325061A3F14000000035E -:10168000041A3F2000010326061A3F24000000032D -:10169000041A3F3000010327061A3F3400000003FC -:1016A000041A3F4000010328061A3F4400000003CB -:1016B000041A3F5000010329061A3F54000000039A -:1016C000041A3F600001032A061A3F640000000369 -:1016D000041A3F700001032B061A3F740000000338 -:1016E000041A3F800001032C061A3F840000000307 -:1016F000041A3F900001032D061A3F9400000003D6 -:10170000041A3FA00001032E061A3FA400000003A4 -:10171000041A3FB00001032F061A3FB40000000373 -:10172000041A3FC000010330061A3FC40000000342 -:10173000041A3FD000010331061A3FD40000000311 -:10174000041A3FE000010332061A3FE400000007DC -:10175000041A4CB000080333061A400000000124AC -:10176000021A492000000000061A2500000000109F -:10177000061A258000000012061A09C00000004861 -:10178000061A080000000002061A082000000012D5 -:10179000041A2FB00002033B041A4CF00002033D70 -:1017A000061A500000000004061A449000000124AC -:1017B000021A492400000000061A2540000000100B -:1017C000061A25C800000012061A0AE000000048A8 -:1017D000061A081000000002061A0868000000122D -:1017E000041A2FB80002033F041A4CF80002034108 -:1017F000061A5010000000040200A468000AFFDC72 -:101800000200A280000000010200A294071D29111D -:101810000200A298000000000200A29C009C042488 -:101820000200A2A0000000000200A2A40000020921 -:101830000200A4FCFF000000020100B4000000014F -:10184000020100B800000001020100DC00000001FC -:10185000020101000000000102010104000000017A -:101860000201007C0030000002010084000000281A -:101870000201008C000000000201013000000004A1 -:101880000201025C000000010201032800000000C8 -:101890000201055400000030020100C400000001F4 -:1018A000020100CC00000001020100F8000000016C -:1018B000020100F000000001020100800030000081 -:1018C00002010088000000280201009000000000D2 -:1018D0000201013400000004020102DC00000001EA -:1018E0000201032C0000000002010564000000302A -:1018F000020100C800000001020100D00000000148 -:10190000020100FC00000001020100F400000001DF -:10191000020C100000000028020C200800000A1130 -:10192000020C200C00000A00020C201000000A0427 -:10193000020C201C0000FFFF020C20200000FFFF13 -:10194000020C20240000FFFF020C20280000FFFFF3 -:10195000020C203800000020020C203C0000002176 -:10196000020C204000000022020C20440000002352 -:10197000020C204800000024020C204C000000252E -:10198000020C205000000026020C2054000000270A -:10199000020C205800000028020C205C00000029E6 -:1019A000020C20600000002A020C20640000002BC2 -:1019B000020C20680000002C020C206C0000002D9E -:1019C000020C20700000002E020C20740000002F7A -:1019D000020C207800000010060C207C0000004F54 -:1019E000020C21B800000001020C21BC0000000123 -:1019F000020C21C000000001020C21C40000000103 -:101A0000020C21C800000001020C21CC00000001E2 -:101A1000020C21D000000001020C21D400000001C2 -:101A2000020C21D800000001020C21DC00000001A2 -:101A3000020C21E000000001020C21E40000000182 -:101A4000020C21E800000001020C21EC0000000162 -:101A5000020C21F000000001020C21F40000000142 -:101A6000020C21F800000001060C21FC0000000F10 -:101A7000020C223807FFFFFF020C223C0000003F4F -:101A8000020C224007FFFFFF020C22440000000F5F -:101A9000010C224800000000010C224C0000000054 -:101AA000010C225000000000010C22540000000034 -:101AB000010C225800000000010C225C0000000014 -:101AC000010C226000000000010C226400000000F4 -:101AD000010C226800000000010C226C00000000D4 -:101AE000010C227000000000010C227400000000B4 -:101AF000010C227800000000010C227C0000000094 -:101B0000020C24BC000000010C0C2000000003E8C3 -:101B10000A0C2000000000010B0C20000000000A4D -:101B2000020C400800000562020C400C0000055148 -:101B3000020C401000000555020C40140000057214 -:101B4000020C401C0000FFFF020C40200000FFFFC1 -:101B5000020C40240000FFFF020C40280000FFFFA1 -:101B6000020C403800000046020C403C0000000C13 -:101B7000060C40400000005E020C41B8000000016D -:101B8000060C41BC0000001F020C423807FFFFFF9B -:101B9000020C423C0000003F020C424007FFFFFFE6 -:101BA000020C42440000000F010C424800000000FB -:101BB000010C424C00000000010C425000000000EB -:101BC000010C425400000000010C425800000000CB -:101BD000010C425C00000000010C426000000000AB -:101BE000010C426400000000010C4268000000008B -:101BF000010C426C00000000010C4270000000006B -:101C0000010C427400000000010C4278000000004A -:101C1000010C427C00000000010C4280000000002A -:101C2000020C44C0000000010C0C4000000003E85E -:101C30000A0C4000000000010B0C40000000000AEC -:101C4000060D400000000A00020D004400000032B2 -:101C5000020D008C02150020020D009002150020DC -:101C6000020D009408100000020D009800000033DF -:101C7000020D009C00000002020D00A00000000008 -:101C8000020D00A400000005020D00A800000005E0 -:101C9000060D00AC00000002020D00B400000002BE -:101CA000020D00B800000003020D00BC000000029D -:101CB000020D00C000000001020D00C8000000027B -:101CC000020D00CC00000002020D015C00000001CA -:101CD000020D016400000001020D01680000000215 -:101CE000020D020400000001020D020C00000020A1 -:101CF000020D021000000040020D0214000000401E -:101D0000020D022000000003020D02240000001852 -:101D1000060D028000000012040D030000180343AA -:101D2000060D03600000000C020D004C00000001D5 -:101D3000020D005000000002020D005400000000DF -:101D4000020D005800000008060D005C00000004B1 -:101D5000020D00C400000004020D0114000000097F -:101D6000020D011800000029020D011C0000000AEC -:101D7000020D01200000002A020D012400000000D5 -:101D8000020D012800000020020D012C00000000BF -:101D9000020D013000000020020D0134000000009F -:101DA000020D013800000020020D013C000000007F -:101DB000020D014000000020020D0144000000005F -:101DC000020D014800000020020D00040000000187 -:101DD000020D000800000001020D000C00000001CF -:101DE000020D001000000001020D001400000001AF -:101DF000020D001800000001020D001C000000018F -:101E0000020D002000000001020D0024000000016E -:101E1000020D002800000001020D002C000000014E -:101E2000020D003000000001020D0034000000012E -:101E3000020D003800000001020D003C000000010E -:101E4000060E200000000800020E004C00000032C8 -:101E5000020E009402150020020E009802150020C8 -:101E6000020E009C00000030020E00A008100000CE -:101E7000020E00A400000033020E00A80000003093 -:101E8000020E00AC00000031020E00B000000002A3 -:101E9000020E00B400000004020E00B800000000B2 -:101EA000020E00BC00000002020E00C00000000292 -:101EB000020E00C400000000020E00C80000000274 -:101EC000020E00CC00000007020E00D0000000024D -:101ED000020E00D400000002020E00D80000000133 -:101EE000020E014400000001020E014C000000013E -:101EF000020E015000000002020E02040000000168 -:101F0000020E020C00000040020E02100000004011 -:101F1000020E021C00000004020E0220000000203D -:101F2000020E02240000000E020E02280000001B18 -:101F3000060E030000000012040E0280001B035B6B -:101F4000060E02EC00000005020E00540000000C1A -:101F5000020E00580000000C020E005C00000000A1 -:101F6000020E006000000010060E00640000000475 -:101F7000020E00DC00000003020E01100000000F42 -:101F8000020E01140000002F020E011800000000D4 -:101F9000020E011C00000020020E000400000001DF -:101FA000020E000800000001020E000C00000001FB -:101FB000020E001000000001020E001400000001DB -:101FC000020E001800000001020E001C00000001BB -:101FD000020E002000000001020E0024000000019B -:101FE000020E002800000001020E002C000000017B -:101FF000020E003000000001020E0034000000015B -:10200000020E003800000001020E003C000000013A -:10201000020E004000000001020E0044000000011A -:102020000730040000AF0000083007680013037693 -:1020300007340000331C00000734800032780CC8DD -:10204000073500001A801967083539B058CA037877 -:10205000013000000000000001300004000000001A -:1020600001300008000000000130000C00000000FA -:1020700001300010000000000130001400000000DA -:1020800002300020000000010230002400000002A5 -:1020900002300028000000030230002C0000000085 -:1020A0000230003000000004023000340000000163 -:1020B00002300038000000000230003C0000000147 -:1020C0000230004000000004023000440000000024 -:1020D00002300048000000010230004C0000000304 -:1020E00002300050000000000230005400000001E7 -:1020F00002300058000000040230005C00000000C4 -:1021000002300060000000010230006400000003A3 -:1021100002300068000000000230006C0000000186 -:102120000230007000000004023000740000000063 -:1021300002300078000000040230007C0000000340 -:102140000630008000000002023000A400003FFFC3 -:10215000023000A8000003FF02300224000000004B -:1021600002300234000000000230024C0000000087 -:10217000023002E40000FFFF0630200000000800EB -:1021800002338BC000000001023380000000001AFF -:10219000023380400000004E0233808000000010B7 -:1021A000023380C0000000200C3383000007A12010 -:1021B0000A338300000001380B33830000001388CA -:1021C0000A338340000000000C338340000001F418 -:1021D0000B33834000000005023383800007A120F9 -:1021E000023383C0000001F406322A88000000C2D6 -:1021F00006322008000000C806322000000000025D -:10220000063223E80000004004322E580004037A0E -:10221000063250A000000004063250B80000000250 -:102220000632508000000006043250980002037EFF -:10223000063250000000002006323000000004008A -:1022400006321C0000000004043218300002038033 -:10225000063224E8000000B402322DB00000000075 -:1022600006324000000000B40632300000000020BA -:10227000063231000000002006323200000000204B -:102280000632330000000020063234000000002037 -:102290000632350000000020063236000000002023 -:1022A000063237000000002006323800000000200F -:1022B000063239000000002006323A0000000020FB -:1022C00006323B000000002006323C0000000020E7 -:1022D00006323D000000002006323E0000000020D3 -:1022E00006323F000000002006321C1000000002F1 -:1022F000063245A000000024063227B8000000B4D2 -:1023000002322DB400000000063242D0000000B4BA -:1023100006323080000000200632318000000020AC -:102320000632328000000020063233800000002098 -:102330000632348000000020063235800000002084 -:102340000632368000000020063237800000002070 -:10235000063238800000002006323980000000205C -:1023600006323A800000002006323B800000002048 -:1023700006323C800000002006323D800000002034 -:1023800006323E800000002006323F800000002020 -:1023900006321C20000000020632463000000024F5 -:1023A0000720040000870000082007800010038237 -:1023B000072400003165000007248000081D0C5A26 -:1023C00008248EB06C9003840120000000000000FF -:1023D00001200004000000000120000800000000AF -:1023E0000120000C0000000001200010000000008F -:1023F0000120001400000000022000200000000165 -:102400000220002400000002022000280000000337 -:102410000220002C00000000022000300000000418 -:1024200002200034000000010220003800000000FB -:102430000220003C000000010220004000000004D7 -:1024400002200044000000000220004800000001BB -:102450000220004C00000003022000500000000099 -:102460000220005400000001022000580000000477 -:102470000220005C0000000002200060000000015B -:102480000220006400000003022000680000000039 -:102490000220006C00000001022000700000000417 -:1024A00002200074000000000220007800000004F8 -:1024B0000220007C000000030620008000000002D3 -:1024C000022000A400003FFF022000A8000003FF3C -:1024D000022002240000000002200234000000005C -:1024E0000220024C00000000022002E40000FFFF76 -:1024F000062020000000080002238BC0000000011D -:10250000022380000000001002238040000000121F -:102510000223808000000030022380C00000000EF3 -:102520000C2383000007A1200A2383000000013848 -:102530000B238300000013880A238340000000005F -:102540000C238340000001F40B23834000000005AE -:10255000022383800007A120022383C0000001F42E -:10256000062250000000004206222008000000C899 -:10257000062220000000000206224000000000C6E3 -:1025800004224318000503860622432C0000000B9A -:10259000042243580005038B0622436C0000000B05 -:1025A0000422439800050390062243AC0000000B70 -:1025B000042243D800050395062243EC0000000BDB -:1025C000042244180005039A0622442C0000000B44 -:1025D000042244580005039F0622446C0000000BAF -:1025E00004224498000503A4062244AC0000000B1A -:1025F000042244D8000503A9062244EC0000000B85 -:1026000004224518000503AE0622452C0000000BED -:1026100004224558000503B30622456C0000000B58 -:1026200004224598000503B8062245AC0000000BC3 -:10263000042245D8000503BD062245EC0000000B2E -:1026400004224618000503C20622462C0000000B97 -:1026500004224658000503C70622466C0000000B02 -:1026600004224698000503CC062246AC0000000B6D -:10267000042246D8000503D1062246EC0000000BD8 -:1026800004224718000503D60622472C0000000B41 -:1026900004224758000503DB0622476C0000000BAC -:1026A00004224798000503E0062247AC0000000B17 -:1026B000042247D8000503E5062247EC0000000B82 -:1026C00004224818000503EA0622482C0000000BEB -:1026D00004224858000503EF0622486C0000000B56 -:1026E00004224898000503F4062248AC0000000BC1 -:1026F000042248D8000503F9062248EC0000000B2C -:1027000004224918000503FE0622492C0000000B94 -:1027100004224958000504030622496C0000000BFE -:102720000422499800050408062249AC0000000B69 -:10273000042249D80005040D062249EC0000000BD4 -:1027400004224A180005041206224A2C0000000B3D -:1027500004224A580005041706224A6C0000000BA8 -:1027600004224A980005041C06224AAC0000000B13 -:1027700004224AD80005042106224AEC0000000584 -:1027800006224B000000001704224B5C00010426C7 -:1027900006224B600000000304224B6C000104275A -:1027A000062238000000004006223000000002002F -:1027B000042251C00004042806221000000000C0BA -:1027C000062215C00000024004221EC80008042C86 -:1027D0000622390000000008022251180000000003 -:1027E000062251D00000000606221300000000025D -:1027F00006221410000000300622392000000008D4 -:102800000222511C00000000062251E800000006D0 -:102810000622130800000002062214D00000003037 -:102820000216100000000028021700080000000235 -:102830000217002C000000030217003C00000004F7 -:1028400002170044000000000217004800000002C8 -:102850000217004C0000009002170050000000908A -:102860000217005400800090021700580810000062 -:10287000021700600000008A021700640000008058 -:1028800002170068000000810217006C0000008041 -:10289000021700700000000602170078000007D041 -:1028A0000217007C0000076C02170038007C10043F -:1028B000021700040000000F06164024000000026A -:1028C000021640700000001C0216420800000001C1 -:1028D0000216421000000001021642200000000112 -:1028E00002164228000000010216423000000001DA -:1028F000021642380000000102164260000000018A -:102900000C16401C0003D0900A16401C0000009CCE -:102910000B16401C000009C40216403000000008DD -:10292000021640340000000C02164038000000106F -:102930000216404400000020021640000000000182 -:10294000021640D8000000010216400800000001F5 -:102950000216400C000000010216401000000001A9 -:10296000021642400000000002164248000000002B -:1029700006164270000000020216425000000000DD -:1029800002164258000000000616428000000002B5 -:1029900002166008000006140216600C0000060013 -:1029A00002166010000006040216601C0000FFFF03 -:1029B000021660200000FFFF021660240000FFFFE7 -:1029C000021660280000FFFF021660380000002099 -:1029D0000216603C00000020061660400000000265 -:1029E00002166048000000230216604C000000241C -:1029F00002166050000000250216605400000026F8 -:102A000002166058000000270216605C00000029D2 -:102A1000021660600000002A021660640000002BAD -:102A2000021660680000002C0216606C0000002D89 -:102A30000616607000000012021660B80000000167 -:102A4000021660BC00000001061660C00000003ED7 -:102A5000021661B800000001061661BC0000001FEC -:102A60000216623807FFFFFF0216623C0000003FBB -:102A70000216624007FFFFFF021662440000000FCB -:102A800001166248000000000116624C00000000C0 -:102A900001166250000000000116625400000000A0 -:102AA00001166258000000000116625C0000000080 -:102AB0000116626000000000011662640000000060 -:102AC00001166268000000000116626C0000000040 -:102AD0000116627000000000011662740000000020 -:102AE00001166278000000000116627C0000000000 -:102AF000021664BC000000010C166000000003E830 -:102B00000A166000000000010B1660000000000AB9 -:102B100002168040000000060216804400000005F6 -:102B2000021680480000000A0216804C00000005D2 -:102B30000216805400000002021680CC000000043F -:102B4000021680D000000004021680D400000004A9 -:102B5000021680D800000004021680DC0000000489 -:102B6000021680E000000004021680E40000000469 -:102B7000021680E800000004021688040000000429 -:102B8000021680300000007C021680340000003DF8 -:102B9000021680380000003F0216803C0000009CB6 -:102BA000021680F000000007061680F40000000501 -:102BB0000216880C010101010216810800000000C4 -:102BC0000216810C000000040216811000000004AF -:102BD0000216811400000002021688100801200469 -:102BE00002168118000000050216811C0000000575 -:102BF0000216812000000005021681240000000555 -:102C00000216882C200810010216812800000008F6 -:102C10000216812C00000006021681300000000719 -:102C200002168134000000000216883001010120E4 -:102C300006168138000000040216883401010101E3 -:102C400006168148000000040216883801010101BF -:102C500006168158000000040216883C010101019B -:102C6000061681680000000302168174000000014E -:102C7000021688400101010102168178000000015E -:102C80000216817C00000001021681800000000114 -:102C9000021681840000000102168844010101012E -:102CA00002168188000000010216818C00000004D9 -:102CB00002168190000000040216819400000002B8 -:102CC00002168848080120040216819800000005B9 -:102CD0000216819C00000005021681A0000000057C -:102CE000021681A4000000050216881420081001B5 -:102CF000021681A800000008021681AC0000000640 -:102D0000021681B000000007021681B40000000125 -:102D10000216881801010120021681B80000000186 -:102D2000021681BC00000001021681C000000001F3 -:102D3000021681C4000000010216881C0101010175 -:102D4000021681C800000001021681CC00000001BB -:102D5000021681D000000001021681D4000000019B -:102D60000216882001010101021681D8000000012D -:102D7000021681DC00000001021681E00000000163 -:102D8000021681E4000000010216882401010101FD -:102D9000021681E800000001021681EC000000012B -:102DA000021681F0000000010216882801010101CD -:102DB00002168240FFFF003F061682440000000218 -:102DC0000216824CFFFF003F0216825000000100F5 -:102DD000021682540000010006168258000000020C -:102DE00002168260000000C002168264000000C06B -:102DF0000216826800001E000216826C00001E008F -:102E0000021682700000400002168274000040002A -:102E100002168278000080000216827C000080008A -:102E2000021682800000200002168284000020002A -:102E30000616828800000007021682A40000000126 -:102E4000061682A80000000A021681F400000C0891 -:102E5000021681F800000040021681FC000001000B -:102E600002168200000000200216820400000017F3 -:102E700002168208000000800216820C0000020088 -:102E8000021682100000000002168218FFFF01FFE8 -:102E900002168214FFFF01FF0216823C000000139D -:102EA000021680900000013F021680600000014081 -:102EB00002168064000001400616806800000002CF -:102EC00002168070000000C0061680740000000723 -:102ED0000216809C00000048021680A000000048F6 -:102EE000061680A400000002021680AC0000004814 -:102EF000061680B00000000702168238000080002D -:102F000002168234000025E40216809400007FFF40 -:102F100002168220000000070216821C0000000733 -:102F2000021682280000000002168224FFFFFFFF25 -:102F300002168230000000000216822CFFFFFFFF05 -:102F4000021680EC000000FF0214000000000001E7 -:102F50000214000C000000010214004000000001F7 -:102F60000214004400007FFF0214000C0000000067 -:102F700002140000000000000214006C00000000B9 -:102F800002140004000000010214003000000001DF -:102F900002140004000000000214005C00000000A5 -:102FA00002140008000000010214003400000001B7 -:102FB000021400080000000002140060000000007D -:102FC00006028000000020000202005800000032CB -:102FD000020200A003150020020200A40315002035 -:102FE000020200A801000030020200AC081000003C -:102FF000020200B000000033020200B40000003002 -:10300000020200B800000031020200BC0000000310 -:10301000020200C000000006020200C4000000031B -:10302000020200C800000003020200CC00000002FF -:10303000020200D000000000020200D400000002E2 -:10304000020200DC00000000020200E000000006B6 -:10305000020200E400000004020200E80000000296 -:10306000020200EC00000002020200F00000000179 -:10307000020200FC00000006020201200000000025 -:103080000202013400000002020201B0000000014F -:103090000202020C00000001020202140000000102 -:1030A00002020218000000020202040400000001F3 -:1030B0000202040C00000040020204100000004064 -:1030C0000202041C00000004020204200000002090 -:1030D0000202042400000002020204280000001F73 -:1030E00006020500000000120402048000200434DF -:1030F000020200600000000F0202006400000007EE -:1031000002020068000000000202006C0000000ED5 -:103110000602007000000004020200F40000000437 -:103120000202000400000001020200080000000189 -:103130000202000C00000001020200100000000169 -:103140000202001400000001020200180000000149 -:103150000202001C00000001020200200000000129 -:103160000202002400000001020200280000000109 -:103170000202002C000000010202003000000001E9 -:1031800002020034000000010202003800000001C9 -:103190000202003C000000010202004000000001A9 -:1031A0000202004400000001020200480000000189 -:1031B0000202004C00000001020200500000000169 -:1031C00002020108000000C802020118000000020B -:1031D000020201C400000000020201CC0000000055 -:1031E000020201D400000002020201DC0000000221 -:1031F000020201E4000000FF020201EC000000FFF7 -:103200000202010C000000C80202011C00000002C2 -:10321000020201C800000000020201D0000000000C -:10322000020201D800000002020201E000000002D8 -:10323000020201E8000000FF020201F0000000FFAE -:1032400007280400008D00000828076800130454B4 -:10325000072C000034090000072C800038990D036A -:10326000072D0000390C1B2A072D80000641296E0E -:10327000082D8AB04EAA0456012800000000000064 -:1032800001280004000000000128000800000000E0 -:103290000128000C000000000128001000000000C0 -:1032A0000128001400000000022800200000000196 -:1032B0000228002400000002022800280000000369 -:1032C0000228002C0000000002280030000000044A -:1032D000022800340000000102280038000000002D -:1032E0000228003C00000001022800400000000409 -:1032F00002280044000000000228004800000001ED -:103300000228004C000000030228005000000000CA -:1033100002280054000000010228005800000004A8 -:103320000228005C0000000002280060000000018C -:10333000022800640000000302280068000000006A -:103340000228006C00000001022800700000000448 -:103350000228007400000000022800780000000429 -:103360000228007C00000003062800800000000204 -:10337000022800A400003FFF022800A8000003FF6D -:10338000022802240000000002280234000000008D -:103390000228024C00000000022802E40000FFFFA7 -:1033A0000628200000000800022B8BC0000000014E -:1033B000022B800000000000022B8040000000185B -:1033C000022B80800000000C022B80C000000066F1 -:1033D0000C2B83000007A1200A2B8300000001387A -:1033E0000B2B8300000013880A2B83400000000091 -:1033F0000C2B8340000001F40B2B834000000005E0 -:10340000022B83800007A120022B83C0000001F45F -:10341000062A3D4800000004042A3D5800020458D2 -:10342000062A3D6000000006062A30000000004821 -:10343000062A2008000000C8062A2000000000021A -:10344000062A31280000008E062A33680000000397 -:10345000042A33740001045A062A3A780000000254 -:10346000042A3A800002045B042A3A700002045DD8 -:10347000042A3E280002045F042A3EB000040461CE -:10348000042A250000020465062A25080000010020 -:10349000062A297000000004042A29600004046739 -:1034A000042A2F480002046B062A3378000000D853 -:1034B000022A3A3800000000062A3A88000000324A -:1034C000042A3D880010046D062A502000000002E6 -:1034D000062A503000000002062A500000000002B8 -:1034E000062A501000000002022A50B80000000115 -:1034F000062A50480000000E042A3D780002047D90 -:10350000062A3C1800000026022A50400000000055 -:10351000062A36D8000000D8022A3A3C00000000F3 -:10352000062A3B5000000032042A3DC80010047FE8 -:10353000062A502800000002062A50380000000227 -:10354000062A500800000002062A50180000000257 -:10355000022A50BC00000001062A50800000000E24 -:10356000042A3D800002048F062A3CB00000002699 -:10357000022A504400000000021010080000000160 -:103580000210101000000264021010000003D000AE -:10359000021010040000003D091018000200049100 -:1035A00009101100001006910610114000000008DB -:1035B00009101160000806A1061011800000000229 -:1035C00009101188000606A9061011A000000018B5 -:1035D000021010100000000006102400000000E09F -:1035E0000210201C0000000002102020000000013A -:1035F000021020C0000000010210200400000001A1 -:10360000021020080000000109103C00000506AF70 -:1036100009103C20000506B409103800000506B961 -:1036200002104028000000100210404400003FFF3C -:103630000210405800280000021040840084924A82 -:1036400006104C000000010002104058000000006D -:103650000610806800000004021080000000108046 -:1036600006108028000000020210803800000010C0 -:10367000021080400000FFFF021080440000FFFFA6 -:1036800002108050000000000210810000000000C5 -:10369000061081200000000202108008000002B520 -:1036A0000210801000000000061082000000004A96 -:1036B000021081080001FFFF061081400000000297 -:1036C0000210800000001A80061090000000002404 -:1036D000061091200000004A061093700000004A76 -:1036E000061095C00000004A0210800400001080FF -:1036F00006108030000000020210803C0000001024 -:10370000021080480000FFFF0210804C0000FFFF05 -:10371000021080540000000002108104000000002C -:1037200006108128000000020210800C000002B583 -:103730000210801400000000061084000000004AFF -:103740000210810C0001FFFF0610814800000002FA -:103750000210800400001A800610909000000024DF -:10376000061092480000004A061094980000004A93 -:10377000061096E80000004A0212049000E383401D -:103780000212051400003C10021205200000000285 -:1037900002120494FFFFFFFF02120498FFFFFFFFD5 -:1037A0000212049CFFFFFFFF021204A0FFFFFFFFB5 -:1037B000021204A4FFFFFFFF021204A8FFFFFFFF95 -:1037C000021204ACFFFFFFFF021204B0FFFFFFFF75 -:1037D000021204B8FFFFFFFF021204BCFFFFFFFF4D -:1037E000021204C0FFFFFFFF021204C4FFFFFFFF2D -:1037F000021204C8FFFFFFFF021204CCFFFFFFFF0D -:10380000021204D0FFFFFFFF021204DCFFFFFFFFE4 -:10381000021204E0FFFFFFFF021204E4FFFFFFFFBC -:10382000021204E8FFFFFFFF021204ECFFFFFFFF9C -:10383000021204F0FFFFFFFF021204F4FFFFFFFF7C -:10384000021204F8FFFFFFFF021204FCFFFFFFFF5C -:1038500002120500FFFFFFFF02120504FFFFFFFF3A -:1038600002120508FFFFFFFF0212050CFFFFFFFF1A -:1038700002120510FFFFFFFF021204D4FFFF3330D6 -:10388000021204D8FFFF3340021204B4F0003000EB -:1038900002120390000000080212039C00000008BE -:1038A000061203A000000002021203BC0000000484 -:1038B000021203C400000004021203D00000000042 -:1038C000021203DC000000000212036C0000000181 -:1038D000021203680000003F021201BC0000004019 -:1038E000021201C000001808021201C400000803FF -:1038F000021201C800000803021201CC00000040BF -:10390000021201D000000003021201D400000803DB -:10391000021201D800000803021201DC00000803B3 -:10392000021201E000010003021201E4000008039A -:10393000021201E800000803021201EC000000037B -:10394000021201F000000003021201F40000000363 -:10395000021201F800000003021201FC0000000343 -:103960000212020000000003021202040000000321 -:1039700002120208000000030212020C0000000301 -:1039800002120210000000030212021400000003E1 -:1039900002120218000000030212021C00000003C1 -:1039A00002120220000000030212022400000003A1 -:1039B00002120228000024030212022C0000002F31 -:1039C0000212023000000009021202340000001945 -:1039D00002120238000001840212023C000001833E -:1039E0000212024000000306021202440000001905 -:1039F00002120248000000060212024C00000306F8 -:103A000002120250000003060212025400000306D4 -:103A10000212025800000C860212025C000003062B -:103A20000212026000000306021202640000000697 -:103A300002120268000000060212026C000000067A -:103A4000021202700000000602120274000000065A -:103A500002120278000000060212027C000000063A -:103A6000021202800000000602120284000000061A -:103A700002120288000000060212028C00000006FA -:103A800002120290000000060212029400000006DA -:103A900002120298000000060212029C00000006BA -:103AA000021202A000000306021202A4000000138A -:103AB000021202A800000006021202B00000100468 -:103AC000021202B400001004021203240010644029 -:103AD0000212032800106440021201B0000000012D -:103AE0000600A000000000160200A06CBF5C0000F1 -:103AF0000200A070FFF51FEF0200A0740000FFFF9E -:103B00000200A078F00003E00200A07C00000000AA -:103B10000200A0800000A0000600A08400000005B4 -:103B20000200A0980FE000000600A09C0000001416 -:103B30000200A0EC555400000200A0F05555555568 -:103B40000200A0F4000055550200A0F8F0000000AB -:103B50000200A0FC555400000200A1005555555527 -:103B60000200A104000055550200A108F000000069 -:103B70000600A22C000000040200A0600000030761 -:103B80000200A10CBF5C00000200A110FFF51FEFB6 -:103B90000200A1140000FFFF0200A118F00003E0E2 -:103BA0000200A11C000000000200A1200000A000F3 -:103BB0000600A124000000050200A1380FE000006B -:103BC0000600A13C000000140200A18C5554000026 -:103BD0000200A190555555550200A194000055557D -:103BE0000200A198F00000000200A19C55540000C2 -:103BF0000200A1A0555555550200A1A4000055553D -:103C00000200A1A8F00000000600A23C0000000491 -:103C10000200A06400000307000000000000000094 -:103C20000000002E00000000000000000000000066 -:103C30000000000000000000000000000000000084 -:103C40000000000000000000000000000000000074 -:103C50000000000000000000000000000000000064 -:103C60000000000000000000000000000000000054 -:103C70000000000000000000002E004D00000000C9 -:103C80000000000000000000000000000000000034 -:103C90000000000000000000000000000000000024 -:103CA00000000000004D008B00000000000000003C -:103CB0000000000000000000000000000000000004 -:103CC00000000000000000000000000000000000F4 -:103CD000008B009000900094009400980000000079 -:103CE00000000000000000000000000000000000D4 -:103CF000000000000000000000000000009802DE4C -:103D000002DE02E802E802F200000000000000000B -:103D100000000000000000000000000000000000A3 -:103D20000000000000000000000000000000000093 -:103D30000000000000000000000000000000000083 -:103D40000000000000000000000000000000000073 -:103D50000000000000000000000000000000000063 -:103D60000000000000000000000000000000000053 -:103D70000000000000000000000000000000000043 -:103D80000000000000000000000000000000000033 -:103D90000000000000000000000000000000000023 -:103DA0000000000000000000000000000000000013 -:103DB0000000000000000000000000000000000003 -:103DC00000000000000000000000000000000000F3 -:103DD000000000000000000002F202FA00000000F3 -:103DE00000000000000000000000000000000000D3 -:103DF00000000000000000000000000000000000C3 -:103E000000000000000000000000000000000000B2 -:103E100000000000000000000000000000000000A2 -:103E20000000000000000000000000000000000092 -:103E300002FA02FF02FF030A030A03150000000052 -:103E40000000000000000000000000000000000072 -:103E50000000000000000000000000000000000062 -:103E60000000000000000000000000000000000052 -:103E70000000000000000000000000000000000042 -:103E80000000000000000000031503160000000001 -:103E90000000000000000000000000000000000022 -:103EA0000000000000000000000000000000000012 -:103EB000000000000316035700000000000000008F -:103EC00000000000000000000000000000000000F2 -:103ED00000000000000000000000000000000000E2 -:103EE0000357037B000000000000000000000000FA -:103EF00000000000000000000000000000000000C2 -:103F0000000000000000000000000000037B03BB75 -:103F100000000000000000000000000000000000A1 -:103F20000000000000000000000000000000000091 -:103F3000000000000000000003BB03F700000000C9 -:103F40000000000000000000000000000000000071 -:103F50000000000000000000000000000000000061 -:103F60000000000003F7043D043D045204520467BE -:103F70000000000000000000000000000000000041 -:103F80000000000000000000000000000000000031 -:103F9000046704ED04ED04F204F204F700000000ED -:103FA0000000000000000000000000000000000011 -:103FB00000000000000000000000000004F704F80A -:103FC00000000000000000000000000000000000F1 -:103FD00000000000000000000000000000000000E1 -:103FE000000000000000000004F8050A00000000C6 -:103FF00000000000000000000000000000000000C1 -:1040000000000000000000000000000000000000B0 -:1040100000000000050A051F051F052205220525D1 -:104020000000000000000000000000000000000090 -:104030000000000000000000000000000000000080 -:1040400005250555000000000000000000000000EC -:104050000000000000000000000000000000000060 -:10406000000000000000000000000000055505DC15 -:104070000000000000000000000000000000000040 -:104080000000000000000000000000000000000030 -:10409000000000000000000005DC05E305E305E783 -:1040A00005E705EB00000000000000000000000034 -:1040B0000000000000000000000000000000000000 -:1040C0000000000005EB062B062B06330633063BEB -:1040D00000000000000000000000000000000000E0 -:1040E00000000000000000000000000000000000D0 -:1040F000063B068806880695069506A20000000085 -:1041000000000000000000000000000000000000AF -:1041100000000000000000000000000006A206AE43 -:10412000000000000000000000000000000000008F -:10413000000000000000000000000000000000007F -:10414000000000000000000006AE06B40000000001 -:10415000000000000000000000000000000000005F -:10416000000000000000000000000000000000004F -:104170000000000006B406B70000000000000000C8 -:10418000000000000000000000000000000000002F -:10419000000000000000000000000000000000001F -:1041A00006B706BD0000000000000000000000008F -:1041B00000000000000000000000000000000000FF -:1041C00000000000000000000000000006BD06BE68 -:1041D00006BE06D006D006E2000000000000000087 -:1041E00000000000000000000000000000000000CF -:1041F000000000000000000006E2074F0000000081 -:1042000000000000000000000000000000000000AE -:10421000000000000000000000000000000000009E -:1042200000000000074F0750075007630763077639 -:10423000000000000000000000000000000000007E -:10424000000000000000000000000000000000006E -:10425000000000000000000000000000000000005E -:10426000000000000000000000000000000000004E -:10427000000000000000000000000000000000003E -:10428000000000000000000000000000000000002E -:10429000000000000000000000000000000000001E -:1042A000000000000000000000000000000000000E -:1042B00000000000000000000000000000000000FE -:1042C00000000000000000000000000000000000EE -:1042D00000000000000000000000000000000000DE -:1042E00000000000000000000000000000000000CE -:1042F00000000000000000000000000000000000BE -:1043000000000000000000000000000000000000AD -:10431000000000000000000000000000000000009D -:10432000000000000000000000000000000000008D -:1043300000010000000204C00003098000040E40D8 -:1043400000051300000617C000071C80000821406C -:1043500000092600000A2AC0000B2F80000C344000 -:10436000000D3900000E3DC0000F42800010474094 -:1043700000114C00001250C00013558000145A4028 -:1043800000155F00001663C00017688000186D40BC -:1043900000197200001A76C0001B7B80001C804050 -:1043A000001D8500001E89C0001F8E800000934004 -:1043B00000002000000040000000600000008000BD -:1043C0000000A0000000C0000000E00000010000AC -:1043D0000001200000014000000160000001800099 -:1043E0000001A0000001C0000001E0000002000088 -:1043F0000002200000024000000260000002800075 -:104400000002A0000002C0000002E0000003000063 -:104410000003200000034000000360000003800050 -:104420000003A0000003C0000003E000000400003F -:10443000000420000004400000046000000480002C -:104440000004A0000004C0000004E000000500001B -:104450000005200000054000000560000005800008 -:104460000005A0000005C0000005E00000060000F7 -:1044700000062000000640000006600000068000E4 -:104480000006A0000006C0000006E00000070000D3 -:1044900000072000000740000007600000078000C0 -:1044A0000007A0000007C0000007E00000080000AF -:1044B000000820000008400000086000000880009C -:1044C0000008A0000008C0000008E000000900008B -:1044D0000009200000094000000960000009800078 -:1044E0000009A0000009C0000009E000000A000067 -:1044F000000A2000000A4000000A6000000A800054 -:10450000000AA000000AC000000AE000000B000042 -:10451000000B2000000B4000000B6000000B80002F -:10452000000BA000000BC000000BE000000C00001E -:10453000000C2000000C4000000C6000000C80000B -:10454000000CA000000CC000000CE000000D0000FA -:10455000000D2000000D4000000D6000000D8000E7 -:10456000000DA000000DC000000DE000000E0000D6 -:10457000000E2000000E4000000E6000000E8000C3 -:10458000000EA000000EC000000EE000000F0000B2 -:10459000000F2000000F4000000F6000000F80009F -:1045A000000FA000000FC000000FE000001000008E -:1045B000001020000010400000106000001080007B -:1045C0000010A0000010C0000010E000001100006A -:1045D0000011200000114000001160000011800057 -:1045E0000011A0000011C0000011E0000012000046 -:1045F0000012200000124000001260000012800033 -:104600000012A0000012C0000012E0000013000021 -:10461000001320000013400000136000001380000E -:104620000013A0000013C0000013E00000140000FD -:1046300000142000001440000014600000148000EA -:104640000014A0000014C0000014E00000150000D9 -:1046500000152000001540000015600000158000C6 -:104660000015A0000015C0000015E00000160000B5 -:1046700000162000001640000016600000168000A2 -:104680000016A0000016C0000016E0000017000091 -:10469000001720000017400000176000001780007E -:1046A0000017A0000017C0000017E000001800006D -:1046B000001820000018400000186000001880005A -:1046C0000018A0000018C0000018E0000019000049 -:1046D0000019200000194000001960000019800036 -:1046E0000019A0000019C0000019E000001A000025 -:1046F000001A2000001A4000001A6000001A800012 -:10470000001AA000001AC000001AE000001B000000 -:10471000001B2000001B4000001B6000001B8000ED -:10472000001BA000001BC000001BE000001C0000DC -:10473000001C2000001C4000001C6000001C8000C9 -:10474000001CA000001CC000001CE000001D0000B8 -:10475000001D2000001D4000001D6000001D8000A5 -:10476000001DA000001DC000001DE000001E000094 -:10477000001E2000001E4000001E6000001E800081 -:10478000001EA000001EC000001EE000001F000070 -:10479000001F2000001F4000001F6000001F80005D -:1047A000001FA000001FC000001FE000002000004C -:1047B0000020200000204000002060000020800039 -:1047C0000020A0000020C0000020E0000021000028 -:1047D0000021200000214000002160000021800015 -:1047E0000021A0000021C0000021E0000022000004 -:1047F00000222000002240000022600000228000F1 -:104800000022A0000022C0000022E00000230000DF -:1048100000232000002340000023600000238000CC -:104820000023A0000023C0000023E00000240000BB -:1048300000242000002440000024600000248000A8 -:104840000024A0000024C0000024E0000025000097 -:104850000025200000254000002560000025800084 -:104860000025A0000025C0000025E0000026000073 -:104870000026200000264000002660000026800060 -:104880000026A0000026C0000026E000002700004F -:10489000002720000027400000276000002780003C -:1048A0000027A0000027C0000027E000002800002B -:1048B0000028200000284000002860000028800018 -:1048C0000028A0000028C0000028E0000029000007 -:1048D00000292000002940000029600000298000F4 -:1048E0000029A0000029C0000029E000002A0000E3 -:1048F000002A2000002A4000002A6000002A8000D0 -:10490000002AA000002AC000002AE000002B0000BE -:10491000002B2000002B4000002B6000002B8000AB -:10492000002BA000002BC000002BE000002C00009A -:10493000002C2000002C4000002C6000002C800087 -:10494000002CA000002CC000002CE000002D000076 -:10495000002D2000002D4000002D6000002D800063 -:10496000002DA000002DC000002DE000002E000052 -:10497000002E2000002E4000002E6000002E80003F -:10498000002EA000002EC000002EE000002F00002E -:10499000002F2000002F4000002F6000002F80001B -:1049A000002FA000002FC000002FE000003000000A -:1049B00000302000003040000030600000308000F7 -:1049C0000030A0000030C0000030E00000310000E6 -:1049D00000312000003140000031600000318000D3 -:1049E0000031A0000031C0000031E00000320000C2 -:1049F00000322000003240000032600000328000AF -:104A00000032A0000032C0000032E000003300009D -:104A1000003320000033400000336000003380008A -:104A20000033A0000033C0000033E0000034000079 -:104A30000034200000344000003460000034800066 -:104A40000034A0000034C0000034E0000035000055 -:104A50000035200000354000003560000035800042 -:104A60000035A0000035C0000035E0000036000031 -:104A7000003620000036400000366000003680001E -:104A80000036A0000036C0000036E000003700000D -:104A900000372000003740000037600000378000FA -:104AA0000037A0000037C0000037E00000380000E9 -:104AB00000382000003840000038600000388000D6 -:104AC0000038A0000038C0000038E00000390000C5 -:104AD00000392000003940000039600000398000B2 -:104AE0000039A0000039C0000039E000003A0000A1 -:104AF000003A2000003A4000003A6000003A80008E -:104B0000003AA000003AC000003AE000003B00007C -:104B1000003B2000003B4000003B6000003B800069 -:104B2000003BA000003BC000003BE000003C000058 -:104B3000003C2000003C4000003C6000003C800045 -:104B4000003CA000003CC000003CE000003D000034 -:104B5000003D2000003D4000003D6000003D800021 -:104B6000003DA000003DC000003DE000003E000010 -:104B7000003E2000003E4000003E6000003E8000FD -:104B8000003EA000003EC000003EE000003F0000EC -:104B9000003F2000003F4000003F6000003F8000D9 -:104BA000003FA000003FC000003FE000003FE001E8 -:104BB00000000000000001FF0000020000007FF87C -:104BC00000007FF80000016A0000150000000001ED -:104BD0000000FF00000000000000FF0000000000D7 -:104BE00000000000140AFF000000000100000000A7 -:104BF00000201001000000000100860000000100FC -:104C00000000860200008604000086060000860878 -:104C10000000860A0000860C0000860E0000861048 -:104C20000000861200008614000086160000861818 -:104C30000000861A0000861C0000861E00008620E8 -:104C400000008622000086240000862600008628B8 -:104C50000000862A0000862C0000862E0000863088 -:104C60000000863200008634000086360000863858 -:104C70000000863A0000863C0000863E0000864028 -:104C800000008642000086440000864600008648F8 -:104C90000000864A0000864C0000864E00008650C8 -:104CA0000000865200008654000086560000865898 -:104CB0000000865A0000865C0000865E0000866068 -:104CC0000000866200008664000086660000866838 -:104CD0000000866A0000866C0000866E0000867008 -:104CE00000008672000086740000867600008678D8 -:104CF0000000867A0000867C0000867E00008680A8 -:104D00000000868200008684000086860000868877 -:104D10000000868A0000868C0000868E0000869047 -:104D20000000869200008694000086960000869817 -:104D30000000869A0000869C0000869E000086A0E7 -:104D4000000086A2000086A4000086A6000086A8B7 -:104D5000000086AA000086AC000086AE000086B087 -:104D6000000086B2000086B4000086B6000086B857 -:104D7000000086BA000086BC000086BE000086C027 -:104D8000000086C2000086C4000086C6000086C8F7 -:104D9000000086CA000086CC000086CE000086D0C7 -:104DA000000086D2000086D4000086D6000086D897 -:104DB000000086DA000086DC000086DE000086E067 -:104DC000000086E2000086E4000086E6000086E837 -:104DD000000086EA000086EC000086EE000086F007 -:104DE000000086F2000086F4000086F6000086F8D7 -:104DF000000086FA000086FC000086FE00008700A6 -:104E00000000870200008704000087060000870872 -:104E10000000870A0000870C0000870E0000871042 -:104E20000000871200008714000087160000871812 -:104E30000000871A0000871C0000871E00008720E2 -:104E400000008722000087240000872600008728B2 -:104E50000000872A0000872C0000872E0000873082 -:104E60000000873200008734000087360000873852 -:104E70000000873A0000873C0000873E0000874022 -:104E800000008742000087440000874600008748F2 -:104E90000000874A0000874C0000874E00008750C2 -:104EA0000000875200008754000087560000875892 -:104EB0000000875A0000875C0000875E0000876062 -:104EC0000000876200008764000087660000876832 -:104ED0000000876A0000876C0000876E0000877002 -:104EE00000008772000087740000877600008778D2 -:104EF0000000877A0000877C0000877E00008780A2 -:104F00000000878200008784000087860000878871 -:104F10000000878A0000878C0000878E0000879041 -:104F20000000879200008794000087960000879811 -:104F30000000879A0000879C0000879E000087A0E1 -:104F4000000087A2000087A4000087A6000087A8B1 -:104F5000000087AA000087AC000087AE000087B081 -:104F6000000087B2000087B4000087B6000087B851 -:104F7000000087BA000087BC000087BE000087C021 -:104F8000000087C2000087C4000087C6000087C8F1 -:104F9000000087CA000087CC000087CE000087D0C1 -:104FA000000087D2000087D4000087D6000087D891 -:104FB000000087DA000087DC000087DE000087E061 -:104FC000000087E2000087E4000087E6000087E831 -:104FD000000087EA000087EC000087EE000087F001 -:104FE000000087F2000087F4000087F6000087F8D1 -:104FF000000087FA000087FC000087FEFFFFFFFF2C -:10500000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 -:10501000FFFFFFFFFFFFFFFFFFFFFFFF0000000399 -:1050200000BEBC20000000000000000500000003DE -:1050300000BEBC20000000000000000500002000B1 -:10504000000040C000006180000082400000A3001A -:105050000000C3C00000E4800001054000012600FC -:10506000000146C000016780000188400001A900DE -:105070000001C9C00001EA8000020B4000022C00C0 -:1050800000024CC000026D8000028E400002AF00A2 -:105090000002CFC00002F08000001140000080003C -:1050A000000103800001870000020A8000028E00D8 -:1050B00000031180000395000004188000049C0088 -:1050C00000051F800005A300000626800006AA0038 -:1050D00000072D800007B100000834800008B800E8 -:1050E00000093B800009BF00000A4280000AC60098 -:1050F000000B4980000BCD00000C5080000CD40048 -:10510000000D578000005B0000007FF800007FF872 -:1051100000000166000015000000FF000000000014 -:105120000000FF0000000000000019000000000067 -:1051300000000000FFFFFFFF00007FF800007FF885 -:1051400000000361000015000000FF000FFFFFFFDB -:105150000000FF000FFFFFFF000000FF0000FF0046 -:105160000FFFFFFF0000FF000FFFFFFF000000FF29 -:105170000000FF000FFFFFFF0000FF000FFFFFFF19 -:10518000000000FF0000FF000FFFFFFF0000FF0016 -:105190000FFFFFFF000000FF0000FF000FFFFFFFF9 -:1051A0000000FF000FFFFFFF000000FF0000FF00F6 -:1051B0000FFFFFFF0000FF000FFFFFFF000000FFD9 -:1051C0000000FF000FFFFFFF0000FF000FFFFFFFC9 -:1051D000000000FF0000FF000FFFFFFF0000FF00C6 -:1051E0000FFFFFFF000000FF0000FF000FFFFFFFA9 -:1051F0000000FF000FFFFFFF000000FF0000FF00A6 -:105200000FFFFFFF0000FF000FFFFFFF000000FF88 -:105210000000FF000FFFFFFF0000FF000FFFFFFF78 -:10522000000000FF0000FF000FFFFFFF0000FF0075 -:105230000FFFFFFF000000FF0000FF000FFFFFFF58 -:105240000000FF000FFFFFFF000000FF0000FF0055 -:105250000FFFFFFF0000FF000FFFFFFF000000FF38 -:105260000000FF000FFFFFFF0000FF000FFFFFFF28 -:10527000000000FF0000FF000FFFFFFF0000FF0025 -:105280000FFFFFFF000000FF0000FF000FFFFFFF08 -:105290000000FF000FFFFFFF000000FF0000FF0005 -:1052A0000FFFFFFF0000FF000FFFFFFF000000FFE8 -:1052B0000000FF000FFFFFFF0000FF000FFFFFFFD8 -:1052C000000000FF0000FF000FFFFFFF0000FF00D5 -:1052D0000FFFFFFF000000FF0000FF000FFFFFFFB8 -:1052E0000000FF000FFFFFFF000000FF0000FF00B5 -:1052F0000FFFFFFF0000FF000FFFFFFF000000FF98 -:105300000000FF000FFFFFFF0000FF000FFFFFFF87 -:10531000000000FF0000FF000FFFFFFF0000FF0084 -:105320000FFFFFFF000000FF0000FF000FFFFFFF67 -:105330000000FF000FFFFFFF000000FF0000FF0064 -:105340000FFFFFFF0000FF000FFFFFFF000000FF47 -:105350000000FF000FFFFFFF0000FF000FFFFFFF37 -:10536000000000FF0000FF000FFFFFFF0000FF0034 -:105370000FFFFFFF000000FF0000FF000FFFFFFF17 -:105380000000FF000FFFFFFF000000FF0000FF0014 -:105390000FFFFFFF0000FF000FFFFFFF000000FFF7 -:1053A0000000FF000FFFFFFF0000FF000FFFFFFFE7 -:1053B000000000FF0000FF000FFFFFFF0000FF00E4 -:1053C0000FFFFFFF000000FF000000FF000000FFD4 -:1053D0000000FF00000000000000FF0000000000CF -:1053E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD -:1053F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD -:1054000000001000000020800000310000004180FA -:1054100000005200000062800000730000008380E2 -:10542000000094000000A4800000B5000000C580CA -:105430000000D6000000E6800000F70000010780B1 -:105440000001180000012880000139000001498096 -:1054500000015A0000016A8000017B0000018B807E -:1054600000019C000001AC800001BD000001CD8066 -:105470000001DE000001EE8000000F0000000000CF -:1054800000007FF800007FF80000021D00001500FA -:1054900010000000000028AD00010001FFFFFFFF29 -:1054A000FFFFFFFF00050206CCCCCCC17058103CBA -:1054B000000000000000FF00000000000000FF00EE -:1054C000000000000000000000000001CCCC020140 -:1054D000CCCCCCCCCCCC0201CCCCCCCC00000000D1 -:1054E000FFFFFFFF0000FFFF000000000000FFFFC4 -:1054F000000000000000FFFF000000000000FFFFB0 -:10550000000000000000FFFF000000000000FFFF9F -:10551000000000000000FFFF000000000000FFFF8F -:1055200000000000000E0000011600D60000FFFF82 -:10553000000000000000FFFF000000000000FFFF6F -:10554000000000000000FFFF000000000000FFFF5F -:10555000000000000000FFFF000000000000FFFF4F -:10556000000000000000FFFF0000000000720000CB -:10557000012300F3FFFFFFF3318FFFFF0C30C30C5B -:10558000C30C30C3CF3CF300F3CF3CF30000CF3C5F -:10559000CDCDCDCDFFFFFFF130EFFFFF0C30C30CC1 -:1055A000C30C30C3CF3CF300F3CF3CF30001CF3C3E -:1055B000CDCDCDCDFFFFFFF6305FFFFF0C30C30C2C -:1055C000C30C30C3CF3CF300F3CF3CF30002CF3C1D -:1055D000CDCDCDCDFFFFF4061CBFFFFF0C30C305C2 -:1055E000C30C30C3CF300014F3CF3CF30004CF3CE6 -:1055F000CDCDCDCDFFFFFFF2304FFFFF0C30C30C00 -:10560000C30C30C3CF3CF300F3CF3CF30008CF3CD6 -:10561000CDCDCDCDFFFFFFFA302FFFFF0C30C30CF7 -:10562000C30C30C3CF3CF300F3CF3CF30010CF3CAE -:10563000CDCDCDCDFFFFFFF731EFFFFF0C30C30C19 -:10564000C30C30C3CF3CF300F3CF3CF30020CF3C7E -:10565000CDCDCDCDFFFFFFF5302FFFFF0C30C30CBC -:10566000C30C30C3CF3CF300F3CF3CF30040CF3C3E -:10567000CDCDCDCDFFFFFFF3318FFFFF0C30C30C3D -:10568000C30C30C3CF3CF300F3CF3CF30000CF3C5E -:10569000CDCDCDCDFFFFFFF1310FFFFF0C30C30C9F -:1056A000C30C30C3CF3CF300F3CF3CF30001CF3C3D -:1056B000CDCDCDCDFFFFFFF6305FFFFF0C30C30C2B -:1056C000C30C30C3CF3CF300F3CF3CF30002CF3C1C -:1056D000CDCDCDCDFFFFF4061CBFFFFF0C30C305C1 -:1056E000C30C30C3CF300014F3CF3CF30004CF3CE5 -:1056F000CDCDCDCDFFFFFFF2304FFFFF0C30C30CFF -:10570000C30C30C3CF3CF300F3CF3CF30008CF3CD5 -:10571000CDCDCDCDFFFFFFFA302FFFFF0C30C30CF6 -:10572000C30C30C3CF3CF300F3CF3CF30010CF3CAD -:10573000CDCDCDCDFFFFFFF730EFFFFF0C30C30C19 -:10574000C30C30C3CF3CF300F3CF3CF30020CF3C7D -:10575000CDCDCDCDFFFFFFF5304FFFFF0C30C30C9B -:10576000C30C30C3CF3CF300F3CF3CF30040CF3C3D -:10577000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CF1 -:10578000C30C30C3CF3CF3CCF3CF3CF30000CF3C91 -:10579000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CD1 -:1057A000C30C30C3CF3CF3CCF3CF3CF30001CF3C70 -:1057B000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CB1 -:1057C000C30C30C3CF3CF3CCF3CF3CF30002CF3C4F -:1057D000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C91 -:1057E000C30C30C3CF3CF3CCF3CF3CF30004CF3C2D -:1057F000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C71 -:10580000C30C30C3CF3CF3CCF3CF3CF30008CF3C08 -:10581000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C50 -:10582000C30C30C3CF3CF3CCF3CF3CF30010CF3CE0 -:10583000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C30 -:10584000C30C30C3CF3CF3CCF3CF3CF30020CF3CB0 -:10585000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C10 -:10586000C30C30C3CF3CF3CCF3CF3CF30040CF3C70 -:10587000CDCDCDCDFFFFFFF3320FFFFF0C30C30CBA -:10588000C30C30C3CF3CF300F3CF3CF30000CF3C5C -:10589000CDCDCDCDFFFFFFF1310FFFFF0C30C30C9D -:1058A000C30C30C3CF3CF300F3CF3CF30001CF3C3B -:1058B000CDCDCDCDFFFFFFF6305FFFFF0C30C30C29 -:1058C000C30C30C3CF3CF300F3CF3CF30002CF3C1A -:1058D000CDCDCDCDFFFFF4061CBFFFFF0C30C305BF -:1058E000C30C30C3CF300014F3CF3CF30004CF3CE3 -:1058F000CDCDCDCDFFFFFFF2304FFFFF0C30C30CFD -:10590000C30C30C3CF3CF300F3CF3CF30008CF3CD3 -:10591000CDCDCDCDFFFFFF8A042FFFFF0C30C30C90 -:10592000C30C30C3CF3CC000F3CF3CF30010CF3CDE -:10593000CDCDCDCDFFFFFF9705CFFFFF0C30C30CC2 -:10594000C30C30C3CF3CC000F3CF3CF30020CF3CAE -:10595000CDCDCDCDFFFFFFF5310FFFFF0C30C30CD8 -:10596000C30C30C3CF3CF300F3CF3CF30040CF3C3B -:10597000CDCDCDCDFFFFFFF3300FFFFF0C30C30CBB -:10598000C30C30C3CF3CF300F3CF3CF30000CF3C5B -:10599000CDCDCDCDFFFFFFF1300FFFFF0C30C30C9D -:1059A000C30C30C3CF3CF300F3CF3CF30001CF3C3A -:1059B000CDCDCDCDFFFFFFF6305FFFFF0C30C30C28 -:1059C000C30C30C3CF3CF300F3CF3CF30002CF3C19 -:1059D000CDCDCDCDFFFFF4061CBFFFFF0C30C305BE -:1059E000C30C30C3CF300014F3CF3CF30004CF3CE2 -:1059F000CDCDCDCDFFFFFFF2304FFFFF0C30C30CFC -:105A0000C30C30C3CF3CF300F3CF3CF30008CF3CD2 -:105A1000CDCDCDCDFFFFFFFA302FFFFF0C30C30CF3 -:105A2000C30C30C3CF3CF300F3CF3CF30010CF3CAA -:105A3000CDCDCDCDFFFFFF97040FFFFF0C30C30C82 -:105A4000C30C30C3CF3CC000F3CF3CF30020CF3CAD -:105A5000CDCDCDCDFFFFFFF5300FFFFF0C30C30CD8 -:105A6000C30C30C3CF3CF300F3CF3CF30040CF3C3A -:105A7000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CEE -:105A8000C30C30C3CF3CF3CCF3CF3CF30000CF3C8E -:105A9000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CCE -:105AA000C30C30C3CF3CF3CCF3CF3CF30001CF3C6D -:105AB000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CAE -:105AC000C30C30C3CF3CF3CCF3CF3CF30002CF3C4C -:105AD000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C8E -:105AE000C30C30C3CF3CF3CCF3CF3CF30004CF3C2A -:105AF000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C6E -:105B0000C30C30C3CF3CF3CCF3CF3CF30008CF3C05 -:105B1000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C4D -:105B2000C30C30C3CF3CF3CCF3CF3CF30010CF3CDD -:105B3000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C2D -:105B4000C30C30C3CF3CF3CCF3CF3CF30020CF3CAD -:105B5000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C0D -:105B6000C30C30C3CF3CF3CCF3CF3CF30040CF3C6D -:105B7000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CED -:105B8000C30C30C3CF3CF3CCF3CF3CF30000CF3C8D -:105B9000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CCD -:105BA000C30C30C3CF3CF3CCF3CF3CF30001CF3C6C -:105BB000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CAD -:105BC000C30C30C3CF3CF3CCF3CF3CF30002CF3C4B -:105BD000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C8D -:105BE000C30C30C3CF3CF3CCF3CF3CF30004CF3C29 -:105BF000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C6D -:105C0000C30C30C3CF3CF3CCF3CF3CF30008CF3C04 -:105C1000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C4C -:105C2000C30C30C3CF3CF3CCF3CF3CF30010CF3CDC -:105C3000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C2C -:105C4000C30C30C3CF3CF3CCF3CF3CF30020CF3CAC -:105C5000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C0C -:105C6000C30C30C3CF3CF3CCF3CF3CF30040CF3C6C -:105C7000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CEC -:105C8000C30C30C3CF3CF3CCF3CF3CF30000CF3C8C -:105C9000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CCC -:105CA000C30C30C3CF3CF3CCF3CF3CF30001CF3C6B -:105CB000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CAC -:105CC000C30C30C3CF3CF3CCF3CF3CF30002CF3C4A -:105CD000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C8C -:105CE000C30C30C3CF3CF3CCF3CF3CF30004CF3C28 -:105CF000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C6C -:105D0000C30C30C3CF3CF3CCF3CF3CF30008CF3C03 -:105D1000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C4B -:105D2000C30C30C3CF3CF3CCF3CF3CF30010CF3CDB -:105D3000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C2B -:105D4000C30C30C3CF3CF3CCF3CF3CF30020CF3CAB -:105D5000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C0B -:105D6000C30C30C3CF3CF3CCF3CF3CF30040CF3C6B -:105D7000CDCDCDCD000C0000000700C00002813069 -:105D8000000B81580002021000010230000F024097 -:105D900000010330000C0000000800C00002814038 -:105DA000000B81680002022000010240000702503F -:105DB000000202C000100000000801000002818003 -:105DC000000B81A80002026000018280000E829810 -:105DD0000008038000028000000B8028000200E021 -:105DE000000101000000811000000118CCCCCCCCD7 -:105DF000CCCCCCCCCCCCCCCCCCCCCCCC00002000F3 -:105E0000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCD2 -:105E100000002000CCCCCCCCCCCCCCCCCCCCCCCCD2 -:105E2000CCCCCCCC00002000000000000000000022 -:105E30001F8B080000000000000BFB51CFC0F003D7 -:105E40008ABB5819180238107C7AE0A58C94E9DFD7 -:105E5000C8CCC0B00388AF02F17E66D2F5B34A2346 -:105E6000D8F7241818182419184E893130EC9244A8 -:105E700088E702D5084A3130DC858A0500D967A554 -:105E8000E81B4EA39836F8BB3A2AFF912A84CE87A6 -:105E900089A3C93F86CA6F5480D03FD5B19BBB0947 -:105EA0002A0F00FE694F6760030000000000000039 -:105EB0001F8B080000000000000BED7D0B7854D50F -:105EC000B9E8DACFD933994C7642422610700703ED -:105ED000040D30208FA85427E1D1E0E5E8F0462EEC -:105EE000CA80AF0892448D356D39373B6412020287 -:105EF0008ECAA1B4A53A207AA247DBD4464B7BF5E3 -:105F0000DC206A73DAD37B9152A52DB6413D281669 -:105F100068F49403BDD796BBFE7FAD3DD97B672661 -:105F20000F5FDF395F1B3EDD597BAFBDD6BFFEF78C -:105F3000FAFF7FEDA8A242D44B08B9083FD712B2AE -:105F40004E2084E4F55EADFB448B56935C42AA82FE -:105F5000AAB1953E5B2F858DC669F4FE2562E809DE -:105F600002F7C7CD21930851E0BD0242A6C2FFA6A9 -:105F70001322E7B40E8FFAE93D6955165CADF1AC1A -:105F80006B954C883E159E6F1B97EA7972FE84D202 -:105F9000D3AD11FCB9388690FAE337CE7FC56AD30A -:105FA000FF4692CCDC9397D35F6692991725423EC9 -:105FB0002A5C94D569A41FEF83862E5D1E4BC8F919 -:105FC0008615F35F19DBF7F97A89D4B697F6BD7FAA -:105FD00015D1102F4433D5C8C4DE75AF27A4D39391 -:105FE00043C8E6C24D6CBDB9145957D2FB6DFFA230 -:105FF000CB25BD70AE9769BFA97DD7438889E35A89 -:10600000E324DF4F7439DE77BF971C8FBF4F64FAEC -:106010006F0621D885AE7FBA10BD16EE7B0A1799A0 -:1060200023687BFD33E5245A9A1EFE24BD3E21FCE5 -:10603000D67B69E9C8FB7DB4BFA985D0F74EAAF12C -:10604000EBAFA27CF4DEF7A5D026E0A33DE3E7901A -:1060500000BD4F181F59743AB5BF69782AFE4847EA -:10606000A7BF275EE43F8BBFAAC455599DE493F3B5 -:10607000D71DC05F1936FE6A5FDCEF789F94BF6260 -:106080006EFEE2F838DDCED64F760F6374E1F4721F -:10609000D3272D5D3EE97B7DF9690BE0D5D3BED8D2 -:1060A0001C4152F01387D7A2D7A78577203E222420 -:1060B0008E74262422C1FCBDF7D935A3CC1080CF25 -:1060C00068F330AC23C8A622C15B5BEE16299C01A5 -:1060D00092681D5744DBDD6B1600DC81E3F34F81D2 -:1060E0003C34872AB4D974BDFA34E3A179F49A51C7 -:1060F000AA0BB09EAD44042540C7AB36CB4B815EA6 -:1061000004DB4F9BB7844DC0030913329C90FBF80E -:106110009A08110D99B655F8754CAA75A8A493E183 -:1061200043B8E8E9FB7EBAF5ABBDEF918B45F0FFD4 -:106130007B08AC6FA0F74894BD67D27F80EF1CD777 -:1061400038FA1CDAB6F17D80D8DAF4F951F805F1A5 -:106150007DF717325F36D9A719543FA825A29E8034 -:10616000FEC4C896693BA3922A22781E24072945BB -:1061700006A44B332195EDC08FA49D2C9CD80BDF3A -:106180002922E07A0A6EDFB9A685AAAE7365FE10F1 -:10619000F079502764584EDFF56C6BA08C3CDED64E -:1061A0000E3D87FC1FA37C3486BE6F86983DDC5A6B -:1061B000F2B21EB5C977862070BE74F30731E419B8 -:1061C0002066C02AF45A2286BD814FCF1FB20B8FA2 -:1061D00083E50F7FD4461F32747A05B9DF3058FE4D -:1061E000F8B4F35974ED2B578D165D3542E9B0A51F -:1061F00078514AFF233D5DF711E89F5142C289144F -:10620000EF8D12042E07A643DFE095D2474A92F79E -:106210005E07BDA4FC192BF6F6830F29D7890F6BF7 -:106220005C6FBD64BC4B5522917511C653613CCA6D -:10623000A75B820F9B84CAC339E06D8A0F293EA5F4 -:1062400013DAA498201FD29F4E81B6BDC170622B75 -:10625000F24102E962C1E73144077EE55C9FA34D4C -:106260005698821D7E6FBD8A70A8E823D071743A5B -:10627000204585EC279DC0B716BF021B5CBC14DA15 -:106280005F77F041AB3195A4A283C5AF8056C6AF0E -:106290005F1F9C7E71CFB7C409EFA0DFF3CBC64967 -:1062A0009B1D4AFF9E4C4E5AF4A148AC82016C7C67 -:1062B000B059210784C98434152E23517A77333C91 -:1062C000A276AC05AE05E01F4E45BD40DA0419E0EC -:1062D000B4EC2A09E660BFE98281E3895A2DEA1508 -:1062E000C91F66F6953F4F0F179B7FB8110FEB1430 -:1062F000BFF9241E16297DA8AE0C7512D09B610231 -:106300007C40428C2F24EEA75BEFC7383F7BC951FE -:106310007C9F6A5753477BE694E3B9127D48C7D9FF -:106320005242121EA4535C83B65C2213D81750FD50 -:10633000E42FA0FDB32CF697168400FE2C6E5FC9E7 -:106340002CCEDF02D56714CFFE694EF9F6B9E45FB3 -:10635000E6F6B88F3E4BB39FB0AE6EFFED3181FBDA -:106360006F19C48FF4E6EF137F6A7FD5F2DB2CBC84 -:10637000E68904F1497EAA249E28E26BA3ED7BDE28 -:10638000CA4EC0BACD8AC89A668A07F36D21D40472 -:10639000F494C33D59F4F9C92725DC2FE52DABBF93 -:1063A00004E6DBDE608E2DB6F983DBE55A0DF04D99 -:1063B000F942B3DB8B1B48F405C1B6FFF2045BC6A0 -:1063C000160F43FE7BBBBB044C8580FCE7F5C78200 -:1063D000AF825CF2FB49FCD8DB52DF766E3EE1F621 -:1063E000F286F2309DB71574D7087C6C0A149ED6DD -:1063F00002D6FE49E3F072B09FAD99ACFD51E33B8C -:10640000E146E48BA816A1F7EA09C74B17C50BD2E2 -:10641000DFC8B7DB57F7D5BDFE1DB2EE033EDBEBA1 -:10642000CFB9AE04EC67991802B4EF8D1DD1D7D85F -:10643000F0F14D4FC51B808F91242110A05F2C17C8 -:10644000E5C7F2E780F1A05DC0E5A9901CC67EA378 -:10645000233DE50ADC5AA1BF0CD796E073D9284F3B -:10646000648E7E12E55F122E5E3E78794FB7DE8035 -:106470004022A9FCF9FBA51C94ABC034BA6E875E20 -:106480002FD4911FF9B85F031A81FEC8A6304D06BC -:106490003D125F114931DE4F0411FB69600FAEA060 -:1064A00068285C56F66F74BD9A169EF22A85CB93C7 -:1064B000EB0F990836B3130697014FBC5103FC92BA -:1064C000A31201F9D70AC391DB804F49242CD0FBDA -:1064D0005A301CDA6AF45D9F4A987DC8A1D78B4C6C -:1064E000BE09F4BF274FC7FE04EC85B5AE31009757 -:1064F0008A707D06F4CE15A70F4CE711A4BD1C8C45 -:10650000593A7A7FD6744EF7BE9BBE0181C9D7FD3A -:106510004DE7C32695A796E3822881528C17235D09 -:10652000344E97F34A5403BF71CB5745B28FB61F11 -:10653000ADEFDF4F89819FE2B1D94D9DD16FE45D11 -:10654000FA5460A174EFEDBA4BAC4CA4E0A74A91A9 -:10655000E9FD2D773D1C1F0BF47CC5B9DF53568533 -:10656000D12FA5FBBE4AA087F59EB798D927B29F29 -:10657000AE87F657B83F723E6F511649318F75DDC1 -:10658000E382BF90E23995DCDC2771FF6A271BDFCD -:10659000F277CE17F43FBE859F0B9522395C8A6453 -:1065A000F59152BE188AF7C2A4DF9D876D0F7F94C4 -:1065B000A8157D04EC5E6167395C15D2D3087CBAFE -:1065C0004B2455A9E05B2B89085F61986E3DA8DEDE -:1065D0002F3445D04CE45EC9C0FBF9AB6A0F2A9456 -:1065E0002EADA34808CCCC25301EE8D5835EB49FE1 -:1065F0006A2E4978A99E7EADE82B26D865BD908489 -:106600000116BD16F69CF43F6A5F0DFA5CD9183589 -:1066100011AE6004F708878A9621BD5BA87FE76109 -:106620000B71F0538B297602DFC6E9F8E00FC68DB7 -:106630000A94D773416AF9E1E7630ABFB5DFB8147A -:10664000E242949400E70419E1A423317AEA0C2F82 -:106650002377CF229DD4EEB466EF427930AF242861 -:10666000AF32396C0A6067E48429527863554C1F55 -:1066700028B971C16EC7F690E88376BE91F54EF4E5 -:10668000FF5AFF2CAD4885D76A91E9B7FBB83E3C6D -:10669000AFB4CF477FA399CA4751DFFE614E876FE2 -:1066A000C7163D381EF519B34BD6F32EC170C43151 -:1066B000475E50713D6EBF661EF76B5A0AA95F8335 -:1066C000F24E16801F93C1F9A305B0479F7BB249D4 -:1066D000C2A47064803F43FD1252CAFC128DFE03B7 -:1066E000FD97BFC2E9CF785C7E4B3A7FE66B42E410 -:1066F00007A8EFA8AA02F8770BF1F9E300DF057409 -:106700003F69F45D7717DF4FCE95B615B550B81ECB -:10671000CB151DFC309ACBCB63C43C71913E8F17D7 -:106720008A06C01DAF17711DE70CE6B79377BD0E43 -:106730003BD16C2ED2884DFFECE0F2B4AD4173C872 -:10674000ADFBEA57E3D1480ABDA573FA64CC0A63EE -:10675000FCC31F4A20FD619DA9FCF4074A2BB4FE2F -:10676000F49F5CA2AE41FC15569C92E15AE6DE2FE6 -:10677000A51ED77D25763F534ADF6FB0D72D144F26 -:106780006F2B0E7FBC53827D9749D0FFF386A8A95B -:106790000AC0551F0EF07B4354DCE0DA5D5E09F75A -:1067A0008D59110DE4C8B2CFDE50642BDCCFFA92C4 -:1067B000BC05E8E52D174589D24F934D9263939B15 -:1067C000A970D3C6DF99545DDAF1A145BF52097EA5 -:1067D0002A2914C9580AC7E68F1B343B9DBAE836EC -:1067E00084ED5B9D7C13AFEF5FCF7E5ABEF8B96836 -:1067F000C5439CF4C21F7B3C84D33949FF3E718D55 -:10680000FF1CF4D638FD0C4ABF4D06D093E90BBAF5 -:10681000F142FF21AE996168C70D43346D7AEC6394 -:106820003107F1205F90512FED5ED312067AE974A3 -:106830000C202DBD8653D9ED2E4145B9A27AE32A0D -:10684000693A2A6401E29F73A58D48EFC728BD41CC -:106850008F3D466ABB2EE6F6CABF1655D18FEF6A4A -:1068600034CB1B8B87A237297CD4AF237B98FF7254 -:1068700089E5BFFC3DE59341F82BE7A9D1E0F6D8C7 -:106880000B7C25775396A670156E6476137CB51C29 -:10689000DA36A8DDEB147AF9D1C3E7514A1387C77A -:1068A00023BD9DF6E9B1C297050FD8B76266DF54E4 -:1068B000B3330C7A26504CED1341FBB31AF033A2DC -:1068C000245E0EED91BBE7E13ABE0D7EA81FEC0BF6 -:1068D000417C7C534C349A9466BE70A4539460FF00 -:1068E0004C707F67D1CF3D2FB57A484F5FB6B81750 -:1068F000E814A83D0CCBB4DBBD6A29AFD71E8E28A7 -:10690000E94475EBF617D2FA097F96F87E6C666358 -:1069100098B647C1AFD49FDC293EDE08FBB188277B -:106920005C8F7477ED239271281EEF5E5B6609958C -:10693000B1FC37749E3BBB140A00013F40B2C781D3 -:10694000EE04BB44F5CD5A6ED76E2591003C3C4316 -:10695000448CAF9D21470257D8F870A7A4B2795A4A -:1069600095B7217E6FC5776F8BB3B6A57FEED8ED57 -:106970006CDF4E160D87F8EDED3B155CFF9DAE7D8F -:106980006B4CD271DC3B486D0BE0A15921E827AC80 -:10699000D5890CF1D80D3FFCCE0CD8277C9BDB951C -:1069A0000F287F1936FDB3CE9F50613FFB4EC715B0 -:1069B000CBAE26F07EA26504ECCBB3494A3B7A4BC2 -:1069C000AB13BE81E077C34BC8A67EE190DB849415 -:1069D000F1C3A724C11137ACD70293206872DECB74 -:1069E000AE6605D31FE66FBD8926F0132583F7AF8A -:1069F0009DCCF21CB533E13AD07B3FE3FEE850DF9B -:106A00003B9CE6BD0D5AB70AFC5F239B9582D81BC1 -:106A1000AFD294DAF04890E303E59D2389A35FEBBE -:106A200020FB558AFDF473C37B4AD74C71725FB863 -:106A30006F20D1B740EECE8BD16A8C1370B83D80F9 -:106A40006709AE32D213E3274530AFBF55C882384D -:106A50004A07FA275E4376D0BBC6D203542F41DCE7 -:106A600027A3C4F9DC1D57E949D2B513E50B43A2AE -:106A7000744901CDDF2981BF58269F4EF6A7F355F3 -:106A8000C3BA266327D42F755CBF5413E3C159D30F -:106A900050BE305E57377F8C0970D4E51921D30082 -:106AA000351A0AE3182EBEAAB92090846DFF5D2323 -:106AB000F7A8204735547FDBEFDF1364F1E4747AE5 -:106AC0005B219AE12F01BF56443C493A6DDBD6FD6C -:106AD000515CA86C67FBAAAC25FDEC8BEF09B27882 -:106AE000F1DA2D63B358DCC5A9AFCE72FBF0936722 -:106AF0001E57BB41CF3C7DE27A58E7FAFF29118D42 -:106B0000CE7BF6994CD2897623A182DD58D721A578 -:106B1000B4878434B1FCF9F732915EEB9EF324160E -:106B2000D0F7D7BDF0CE2442E13BBBA9E7B591E059 -:106B30004F3F2DB0B8B8D93D6931BDBF4E26AB53DC -:106B4000C55926C86C1F72FA47192B407E85B6833B -:106B500037E3B8EDCB15B0AB563F4356905F693F76 -:106B6000B4DBE6534262AC900A3E968F38FD94C087 -:106B7000E03BA0E0FE6F5DDB5E354AE1A869FB10FB -:106B8000F5C5ECEF3D1B003CD41C901C7E5C4D9B7E -:106B9000D4E99984D713708538AB3003F884F34B6C -:106BA000C7068CAF56B73FF0A11480F79D7A8BE2F1 -:106BB00025D409787D530A2D80F60FFE316050549C -:106BC0007D70F88900E0958EBB46CD8238BE93BFBC -:106BD00061FC0B397DC7A39C8EF9DE9AF62D6C3EC5 -:106BE000975EFC007E29E81B878DC8CE3C3A691B66 -:106BF0005C9E77FDB3E71E35E97CA79FFBFDA326CE -:106C000085FBAEBFFCFBA35F07B9FC67AF0E7ABD87 -:106C1000E6E95F06888D0FD7C92C7E707614DD42B9 -:106C2000D17E677FE549804370F6A5F7461B74BDAA -:106C300067BFFFA7E106ED5FF7D2DC7C587FDDF38D -:106C4000B3F3FBF363804F131E3B5C091CDF38205A -:106C50003067E1457E75D1E550C7A1D100E7996362 -:106C60001EDC9FD5D07BF553814E1BD0CE427B23BB -:106C7000C56FF5339B3F04FDD017CFE64811835F06 -:106C8000540D0681CEEFCC437A911EB48FEEFE35C3 -:106C900047291D27A7A7DB39F2B10A7AAEE6992D5D -:106CA0006C3E17DDCEC02F57F6A5DB6617DDCE9103 -:106CB000BB1E2B80C46BC730471EC1BAF6C6CF239C -:106CC00059917EF48325FF03E115F32C14AEA572D0 -:106CD000F81B32C8D1731949BA2E00BA3E7B6E3404 -:106CE000A17CF1BED27333D8839E973CFA3E7A7F63 -:106CF000DD4B6FA25C9D7DFE75D5403B46FC02F5E9 -:106D00002BCF92E4CF61F033AB99CF496AF6677627 -:106D10007A02BDF4A94E2CAC340278FF04DE4F3069 -:106D20007EAF4E1C5C22A4A0D7EBF218A6FF13790D -:106D300088970DFB7FA312BF938E4219D0F1C43CFC -:106D4000B89F8E8ED6FA7558FF4C1B3DF7333975B8 -:106D5000F7AFA6F208F62E49D784F02649219767A7 -:106D6000F77A64B07767C1AF4A993765FECC50F3C4 -:106D70002B3F939DF557C9FC0AC7437AFE60F23D4D -:106D8000D0FA868ABF1FC9068EEBC6E3E98F53EBA4 -:106D9000FBF7B8BEA82666E5884BFBFA2132899836 -:106DA000238B7AE13D0D1B54CA7FA79F96301ED4DA -:106DB000D27E08F5B65B4F54A7896F5E90999F50BD -:106DC0007DE0E024D067A75FFE11F267F53327541A -:106DD0008817BFD6F603B5BBB4571EC01E246CF689 -:106DE000E0F4770F4E627A808E9F824E8AC2C6AFE1 -:106DF00079D1397ECD331F3AC65F6FB6A37F30D0CD -:106E00003C1FC8E1E5B0DE0F0E2B04F4E807ED529D -:106E1000652ABFF6036E0F2D3CB5BC3EEF379007D9 -:106E20009B76C46780DDECD814CEDF0EFEDA1185C8 -:106E300080DE2672F8F71EDAEE78DD67407EBAE370 -:106E4000C832C9B0ED437FE8C2E7CCA3E6EC4C3AC8 -:106E5000DECCEEC8347051DD7AA3EC38DD57D9F8BA -:106E6000A0EEF5CA7CD0F7B00F35C6C37CA120ECEC -:106E700073A5C0BC4A96BF16756F4A7BCDC653FC3E -:106E8000118C5729BA988C91C1B82349A211E2AB51 -:106E9000C4EF77E727229A3D0FB5E2F041D862E6CA -:106EA0002E7EB100C60990987E12FD4F12BAD88F7F -:106EB000FFE5CE4758F84CCA5F9AFC44867E73F0D3 -:106EC00020E93B5EDF3C4C5483F8768B7F6D6B9101 -:106ED0002D0FD312EC938799AB503CB40A2465BCB8 -:106EE00076BC52315FC9C3DD7134D5F39B1426578C -:106EF000D792EE7BD7009C1196CF99E5C2D79738F1 -:106F0000BEFE79325D3855A1E5E05951FCCE5E12E6 -:106F10008E29F4FEDC553D97BF8CDD793EC71C2FD2 -:106F20005ECC183CFE869AB78B7816DDAE0C226FCD -:106F3000972E7FDC0B87C9F7E3398E3CC6A1B7EEED -:106F4000D7BA31CF50DB5A648BFB0DEFF49230E6A9 -:106F5000F10CF40F8777DEF9CDDB20EE9C5B18F2A5 -:106F600092BEE3C817AEC6B89195CF970BC39D10DC -:106F7000EF9775A35CC279968721BFB0D960F9827B -:106F8000CDC1FEE37A339468B382F1A86B705C5193 -:106F9000E3F507835CE737160710CF018A67907720 -:106FA000DCFFC0FA8E0B3C6FDE6D4A903F3C918D4A -:106FB000F982804C4A201E705EF08536613EC19990 -:106FC000374FC7BFDB6513F3E6AD469FBCF97714B7 -:106FD0005BBE414B9337D7FC4B306FAE119BBF5B11 -:106FE000D4DBAF57EE5C7973180BE332DB67435C9D -:106FF000A6399B38F2E6CD20F85711F29C72F56C59 -:10700000AC3BF3F2E7E6ACD9617B9B1C7F19DB3C20 -:10701000FEF4C7E6739BA07FEE48528B756A7284BC -:107020002CB5E9C1F71416A7DDA0847FA8D8EB8E94 -:10703000383F58F99F436FBD877C05D73114AFCDDA -:1070400094AF3CC857A7885DAF5A578B7F9A8DFE87 -:10705000F942BD3005E366C976D044BE0804A3E119 -:10706000708AF7267998DC5BF306CAA81EA5F2A6FB -:107070001811CC47A93ADDF01A83873F1D5C169F93 -:10708000361B63581D944EB07E2FFD3AA6B13826AC -:1070900044B8285CBB6EBC3DD49F9F63AD73861221 -:1070A0003E69C77BEE25A9EB77AB55B6EEE6C82A5D -:1070B000965FAF72E653217D6D8FB34E17A2FFAE80 -:1070C000609C90E553452DC2F323A6151F0F26E3C0 -:1070D000E106D419DE65823E5456B59B025C7359B5 -:1070E0003E25578B7EACD8EC83AC7733B975E5077A -:1070F000E74AA787845FAB2E6E6B838E7EFA9686F7 -:1071000020B6373718786D6908E37D371D9B8D975A -:1071100083B7605D9A0FE3B2E9C67FB02184E3C410 -:107120001ACAD8783C6F4E486613F0952A5AF23244 -:107130000CDB7E893F370B9A40FEB60BECF9352D00 -:1071400097A2BC59FCB3C3E83F2E2D2566201F0C27 -:1071500075FCBEFCFA135C67F32C3FEAD781E42888 -:10716000AB93CD3BD87994A4BD60F3EC98A5E13CFA -:107170003B72079827CEE619187E86AF6D074F61E0 -:107180001D8242F9015494A28753D7E97179EB3BF0 -:107190008E07F57C7390D585A9C5FE3028FF6683E0 -:1071A000E71B0B59BE512D195E01F7D5D065582745 -:1071B000AE96FA319FA7160FBF05DADB0E6ED12B04 -:1071C000C07E148A21AF0176BB9BC8B9283618BF90 -:1071D000558B4B6E83FE3AC83185639487EDB7D4E7 -:1071E000E2ABEE80F70F4E79CD68A2FD9B0B7D21BF -:1071F0000FC85BB7ECE0FF41EB8942671E8DC854B6 -:107200005F50FDB56DCAED25289F9AAD4E3245BD44 -:10721000A04D6F6C506D7A4325734CC0433ABD430B -:10722000EDEF7D6A5EDF71ACF73728917A15F54294 -:107230008438EBDD53E7B32D7A809B05F948399804 -:10724000ACD35B5030BC37BF6DD5E9B9F3DA71FA16 -:107250002F555EDB5D7FFE59D5E9ED5493757AA31A -:10726000A04EEFC70A0975425EFE9752689FD197FC -:10727000EFDCE3B9CF5B50FF47837D4E3AB9FC9911 -:10728000EACC9F16445D74BFD5EB98EF159097D26A -:1072900081F5CBC82AE738A36A9D75B597D4E7383E -:1072A000DA45E60847FF4B5BC7389E8F8D5FE6786F -:1072B0003E7EF754477B42E22A47FFCBDB2A1CED98 -:1072C00089EDD739FA4F3EB0C8D19ED2B9D2D1FF9D -:1072D0008AAEB58EE7D30FAF733C9F79EC1E47FBA8 -:1072E000CAEEAF39FAD753774805B9CDE575C8B9B5 -:1072F000F9A23D4FDB9A47ED12DDE7EFC8A30C83FF -:10730000F16F56D7A5B2C7C9BCA1FB3DD950C33A4E -:10731000E6FDC7CD812B91EBD09ECAC6F00A03EFE4 -:10732000CF98075732CD595FAB1AAC3E19F671CEE4 -:107330007A01679DB12A6DC33C9DE7F897BB8449EC -:107340007DE9AA163AE560B075CA8AE17A6F88725B -:1073500071DE928B51542E30FEF6B184E75AE6640A -:10736000A27F61DB4F211EADFDD4351A89818B6967 -:10737000C945F9AA9E91AF62376B1FE51187521775 -:1073800067C95FC0A6F761BF62E999E6B2C1E95774 -:10739000297185C39F745F9B02EBD2E9C7028FCD31 -:1073A000BF77EBC7194AA4109E6B72D824B6780D2C -:1073B000A9551C700F16CE4F6A07EEA20C4752E873 -:1073C0007195D462DD55CB8A300601481D71F0E914 -:1073D000CEC5FFA30CC6A57EE10CE73A995FE8F69F -:1073E000A7A97E437F7A07F5A7D1DEB9F423D55349 -:1073F00026AFFF32981FC1F4A17B9D9F971FFD6FA1 -:10740000E0ACF643AF4051A812F787792281FD61C5 -:10741000F3AC4810E27356DDBCF55EABE7521C27B7 -:1074200096AB8A10BF8C75CDC5787D9316D5589EC6 -:10743000388AE334658B7AAA3AB13A0FCB176BF5E9 -:107440000F8CDDDF4FDC45534934553C6DA787E594 -:107450008362FADA2EB0A39979AA017BEED683A7CC -:1074600022104792CB641DF6EB8402F38E2DBF47AA -:107470004814E34C5A5044BBABD5EFC0F90782F730 -:10748000668FC0CF7D6CE9175EAF9A3AEE920EDE42 -:107490002D00EFB481E1F502BC4530FF369CBFC63C -:1074A00063A4C4BF42C295B3816E27BE1CC1742BB6 -:1074B000651B908F1D656C5F4E0D8183BFAD7D0E8A -:1074C000E5EF873D7958BF8A7C6D9D73B8D1A3E302 -:1074D0003C165D49610EC63502D1D8D862CA6F9993 -:1074E00051B69FEFD54F8C8F329530817896EC173F -:1074F000313FA8F27888D5EF0F1C9F4DB3BA915E4B -:107500009BAF94C926A1B7CE3A5648D735B9775D17 -:10751000FFC793CDF893CFEB234BB2B02E457A261D -:10752000D89FDEF6717CB9F5F7F73C5C7F179002C7 -:10753000A6BF4B9743BE3BDD386E3FA69EC77987FB -:107540005E5FCFCF17F8EFE982389315E723C16963 -:1075500029E3F2BD7865F9CA5EFA2E373A29FDE4CF -:10756000E953314F6E9D57A0EACC592FCCE96BD12E -:10757000D58AA393208B1F5974F626F1B9A75F7C97 -:107580007A415EAEE88BCF5F7978BEE1BF183E5F8F -:10759000019F865E3333D9F97472E8AB04F35285E8 -:1075A0004E39B4DEB3F8DDBDFE3FFD17E5276BFDB8 -:1075B000163FA4EF6FA6DCD758F9D54CCE6F1A9CB6 -:1075C000B2A28AE7D5B2B75B2F85FD6BD08FFBBE29 -:1075D000CCB2189EEF5588A9835EC8B4F635FCBCC2 -:1075E0009155AFE42B75FA659A6BFFA2F2BAA83EEB -:1075F000E76DB9FFE63E4795C4AF8B5E93B534F9AE -:10760000B1419E3FDAC5F3750575F146D80F17DC19 -:10761000CAEAFDF7286435D4578EA832455F2EE4B8 -:107620006F8ABE9F41D75FF0E2438D238124B71A52 -:1076300045E0663CA3190E3B5C7057BCDCC79E4F0F -:1076400081719ED298DE2DA88CE339E7A6E7C76743 -:10765000819FF0CA5BCB75880F7C945B8CFBA73352 -:107660002F78C2A0FFCFE4902AAC0B7B61E66BE0E1 -:10767000C7FFBEA12B47B6F1C999EFBE3E43A14457 -:107680003AF3DCEB33642456C231FF868BBF98019A -:10769000709B15A4A416F277BA4A60DC1A8DE5CB6C -:1076A000AC7A9F5DC3D516B8FED49BCDE289F9E2D2 -:1076B0000E68D743400CFC061ECFBFFAB4B11CEADB -:1076C0002FB3BB1401EAF11E124CD34FAFE74F3C6E -:1076D00024809FA576D6429885DE0F1D02949B6379 -:1076E000D9BEE47C112929A27ADF77B8763CFAD397 -:1076F000AE7A278BFFE5D904F37D3D376A09B0D711 -:10770000DB65E31BABC07EAF92B11E67BB7C18E5A7 -:10771000C24DC7E3DE31CEFA5C1E8F3EF4D61DF1BA -:1077200072FAFE3D5344E457FF8929592485FC6EC3 -:107730006F28C3F903056F579603581FD3BB337ADD -:10774000F7497E999859D4442A45A2A950BCF8CB50 -:107750000879DBC6772D2209EBF4F90B0D04C7E994 -:1077600068D0F0DAD6A08F2DA61B836F3504F1BA4E -:10777000B3C1C0EBC30D25F8FCC1869043EE61BEDA -:10778000B74B783B85BFF2795D1F68A0F3DAE0D88C -:1077900035914A3DA5D72E9E8F7AA0746AD6DA7E9F -:1077A000E2607B1ABA86CD19CB9105F5A675FADE93 -:1077B000ADFDC0BFA75158BD08FC9ABBE5C83ED47B -:1077C0008FD1824536FD48FDB6024259F1DE961151 -:1077D00073E614A03CA2BC4C3B1C457FBC20181790 -:1077E000208E587094DDB7CE5B20BDA8A0FD307709 -:1077F0008EA080DE2C25ED00965A1A2515B4FFCCFC -:10780000BC25E5709F4C74DE9FA132F986712BE890 -:1078100075B616F991361DBED3B1DB7C96AEE78FF7 -:107820001D1E03F23C0FBEFC2715F605B15FA91A19 -:10783000F831052F9EC0BA8798D0AD4265EC71AD86 -:107840007A8E4CF50C6E0631BE4A150BE59318E89E -:10785000588C7FF6C4E6F8E1BC4BF494BDFF2E5F74 -:10786000F46E7E7224AC05291F25F317EB6361BA11 -:10787000E97C81E72F8E6BEB626621B469FF29AC4E -:107880001DA3EFBF901D1D296643D14555ACEB4BA1 -:10789000D0B6FA57C5A0DEF64DAE77883F5A04F24F -:1078A000966CEBB49D696BCBAC4D3476B5D6BBE131 -:1078B000D09F5E033D57FDA2D00EA051BDC7F07F03 -:1078C000E021ACBB6D6BE8D2630AA7BF45072A92E3 -:1078D000138204EBE9D484901843F5C704FE7D8A33 -:1078E000826961A311F46B420981DE0CF998DF38DB -:1078F0002141C7B1C9D58434DF41C1BC2FD0711B30 -:10790000AB1B76F3D7B35E961FA827E656C88391C4 -:1079100067141DF3913C4E79DAB2737CBF7A979766 -:1079200035954DA6EF32D03F6B648C83AD2F8A978F -:10793000AB749EF53F2A0A51CB0A7925AC6B589F50 -:10794000DD3E7C2ACB4B39DA0FF13ADA60B6990D7D -:10795000E707AA0F3C341AEA02AA49FCE6AF01BCC9 -:10796000FFCAF28FA70E5E9975356D6FA06D88BF47 -:107970006EE8785D8DD27EC338DCD51D53AE83F5BD -:10798000556F138958C4E4333C9EE2391CBF4CA6A2 -:107990007C72CDD69173BD94CE4F8D09EB22E583D9 -:1079A00095BE71CD1AB4557D02C8CD4ADFC466E0DC -:1079B000ABF513F9F71AC8C457C332AF97A27C319D -:1079C0006C4B430CEA13F6AFACBC0ECCEC7091C917 -:1079D0002D6544CC1F4AD931CC5BFCA1999D7781A0 -:1079E00094FE464A87629974C9F4BA4B65F4335BD6 -:1079F000648C17D3FBADCA54A04B3C8CE72B5A992F -:107A0000DE1FFBA207E3CEC5B5E13BD12FD04B7102 -:107A10009F329A247F302F7D09FC46C719AF93729D -:107A20003887F0632F8B1716AF58B61EDE93329748 -:107A3000F8705F2EB17350E4DB2C4EBD4B4CB46B31 -:107A400020E78162A4EFAE00E30BF3E152E48BFD8B -:107A500062C56577435C5258B3F55F80AED9C50403 -:107A6000E80AF7EFA1F7F7737A4AD9211DE8B79F23 -:107A7000D33396104DA88FB1EEBF20ACBD13E46D8B -:107A80009DF7F9391AC5EB704F383E8CD2E14EEFB5 -:107A9000F3B16001D2618C46F17EE7968E98368A0A -:107AA0008ED3181EA1DBDAE3FF4CBD11CC4F76A0BC -:107AB0003CCBD90FAF0379A7CF5FD1E83A9FCAE19A -:107AC000FA823F2F1E93D41F61426D8DD4D8AB4FE5 -:107AD000346A1F8A6DFDE7507DF0E4A3AC8EFD7A19 -:107AE0003A1FC83B5D07E67F7B26C809A8CFF25145 -:107AF00058C06FF14D1C83F57974DD04FC929E89AA -:107B000032DA592B8EED9920627C09FA033FF84650 -:107B1000B1FE545022A037E54219F7ABB2B4273C6E -:107B2000C180F031CBEB0AFA423CB7EA2DB1E571E6 -:107B3000496F1D30B68BF033378EF6584F7781483A -:107B4000FDCADCE30B85D174BC3BBCDCDFCEA5FEFB -:107B500036BDBFDECBF4D2FD11F3CB10E220467769 -:107B600001EA2712990AD7FC9B8AF3A3FDD8A5BE88 -:107B70007E7537FA0F3BFCA9CF694EF7B1FD7C93B8 -:107B8000FF880EFC564FA8FC835CE88CDF2CFD615F -:107B90009D4F70D7135BFA44C9666BAC9B5F910F26 -:107BA0007A40E6F549B21ED2A1BEB23C731AFA7D04 -:107BB0004F7A99DE930E5E79039CD350FF95E5854D -:107BC000F678A3184FEA2920EDC0AF72304CECF9DB -:107BD0005F4B1FB43468787D62EAB80A909327A699 -:107BE0000EAFD0A90C1C9AF4E32EC8339DDBC3E47E -:107BF000F7DCE1DBF0FCE33993C59B80AD302ED997 -:107C0000F9089ED77D5C8E3C8875B5501F4141DADE -:107C100096EDACDF2AE67831B97E6A56D8F3CD0D01 -:107C20002C7EAC5EB81CE35A2AD7E39EE8AD786E92 -:107C3000C3436D199CAFD48869B2EF1D303C688591 -:107C4000CEEF61A81726E1FBA697C58FAC7A117716 -:107C50005D8805CF0C0E4FDF73194E7A58FB2F8BC2 -:107C60000ED6FB7542385FEF876F6A2E4824618B12 -:107C70007FF4D677AB78FF2CD4C567411D4F347E97 -:107C80007511C84102F7475E7F1D21FCFB4AC8A75A -:107C900041B9C75E879EE1AA8BEF232F86B3EDAE75 -:107CA0008B580FCCC1EBF8B09E5526DF1428BDCF02 -:107CB00064FC7606F8B535543D681020924D1DE6FB -:107CC0003FCBFD7DF9C5BBC3230D1B9F0B86639F77 -:107CD000507D6021C6116AF6FBB1DEBF1AF4DF6485 -:107CE00038376076791CE705C29D509FA71C60E37A -:107CF0003D09F0D0FB7FD4AB0A60DDC761FF93077D -:107D0000F6242AB1432F87110F316FF818D1993E0D -:107D100093294FC4B22D7D561D830DC32E9538FC7B -:107D2000A55D3EDEF655C762A5BDF51FC7B5FF8749 -:107D3000FACDAAEF38AEFD07FA43BBD47827E83B6B -:107D4000F3058F01F68BBE8FE777CD952568076227 -:107D5000456404E0E1956C15F55CEC79CF3ED07399 -:107D6000B3B5E89B9A6DDF7026FB8DD1B0FF4A3129 -:107D70009EE9186FD4D0C6A3F377005EADE7AF6479 -:107D8000EFC2738BF43D03F386858747AFA1EDE126 -:107D90002F78F0DC90B5DF74F3653E97AF16D77996 -:107DA0004015E4CD0FFAB616E5CC1374E6C12CB934 -:107DB000532F4C70E4039E043B4BE9A7CA51085172 -:107DC000D2E7A5F8DCE47CD6C2EB11D2CF93936660 -:107DD0009E2B509ED3CF3383CB3BE1722CEBC9EF6C -:107DE000C2F4736ED09D2771EB29EB6AE9A96F711C -:107DF000FE9449F40A1F9D675DA27D9E0FDF8E4EA3 -:107E0000023FF8038D9D832A697BE86530CFDFF45C -:107E100084EFF74EC7735FFFE4CD1BBA3CACF4119F -:107E20005E97D9470F31FFEA56E6AFD6CD9F8AFE5F -:107E30005DDDF631BAFD9CA2FB5A7521C3A1878690 -:107E4000790DFEBD3D13F551D585003EFFECE6F3FF -:107E50003ACEAFF49DCF8FCFADF9EE72E9D943930F -:107E60007EBA0BCEB9D77D5F113DB679EABECFEBB6 -:107E7000FFBD54EF3AE53D0CF22E1791647D17E8F3 -:107E8000876DAAD50E37CF99057EAD4D3F9481FF02 -:107E9000D5FB3E7CE76E9B8FF7372B53F7CF70F502 -:107EA0001F638DBF10FBBBE149EA1FD88FD1FEF2E3 -:107EB0009F3D167CA8BF1E125DE3E558F3DF88E303 -:107EC000597EF7456DEDABA60C7C1A2F87FD53CF7D -:107ED0006DC480EF4F3C2E877C213BDF6A8C5FAB0B -:107EE0002E5CEAA0772FDEC739EEBFD71074D4EB33 -:107EF000DE11ADC33AED8B3CFE54453D737C6FCF34 -:107F000048479DEEDFE0F8A4705C9D068E6BBE6076 -:107F1000388A1CF2D90B47B1E3FE278563A1C6F46A -:107F2000D7727E9DABB373B3730D21D4446FCDA5CF -:107F3000F7BD94D7BF4CAF1ABDCE9589E9C7EFA264 -:107F400026587FDA86FDFD0D7FBEF7DD6B315115BA -:107F500074D41548BCCEDBAD77E09C37AB77D31C2F -:107F6000DF87B3AE3E89D56BBAEF7FE86378F9C699 -:107F7000E5D504FC69EAABA73CB7B6CB2FF0EF7DA3 -:107F80000645479C9BB7AD3ADFCF0A2E3983CDF724 -:107F90008DCBAF2710D79573537FDFEEA09FC1DF46 -:107FA000A285B14E3CA6F7FF5D9A4F0ACFF0243C64 -:107FB000D7209EA43478AAB5E0D1595EB025F8F94F -:107FC000C0539261D1AD7FFC6CE570930B97201F7D -:107FD000499C4E2DB07F4BD1DFCA7FB4689F2FFCE8 -:107FE000E141D2F7B98C2F86BE8B0649DF622E079E -:107FF0002DFAE70BCFAD8384E73A8BDF8261A4D7FC -:10800000E705CF570609CF318B5EC6E78B9FD62495 -:10801000FFF70FCF5F38DCF9192C0ED252C2CE9386 -:10802000F8A4C88345C2C072E12B76EEB3B5429F77 -:10803000B3CEE65D67DD57BA75FE9AAF339D3CADB2 -:1080400054127940BF630D2C1EF006DF9FFCBAAAC4 -:108050002913E3F3AE795A82FB32FB8BDBFCF72A60 -:10806000E7B9DC81E4785206CBFFDC1875BEB77C3B -:108070004586AB8ECCC47E16FED28DF7D782B73044 -:1080800024310781378AAFACA27EF60D9F35BED270 -:10809000C9DD50F115D38786AF81E4FD2B43C4972A -:1080A00025AF7FADF8CA077C4DFF1B7F0D165F8B98 -:1080B000FE268F43C2D7AD439547EED7FEB5E26BA0 -:1080C000B0F2E8DEB7D1FD5DA8BFEF0B7CD6F87348 -:1080D000CFFF69F1688DB732CD3E2F1D3E0782C3B9 -:1080E000BA7EE81B245EDDFBCF2F1AAFAEF93F3519 -:1080F0005EF97843C6EB007058577990F26DF975C8 -:108100006D6AEAEF888ECB64DF711B2FD41E990F46 -:10811000F9E3BF93303F7D64CF9C0DF67AA071994F -:10812000CCDF3E52397B03C44FCF4532B0F6ECA8CA -:1081300018FAF934C82B2F62EFB9C73FC2F1E5C96D -:10814000CCB6E2BF7940D7A391C5FDCA23A9B4AD8F -:108150000BF34636FA4A7DF17D8418DBA7411E6297 -:10816000416A382C3AA79B77A8F43D1A797C48FAE3 -:1081700067A0F5FE877FCC20F54F02FBE592E4DF98 -:10818000DDB90CF0D926B27AB8E370AB00BEEB468D -:10819000B0D3F215F97B814E7767B2FC61876A6CC8 -:1081A00080FC8967F182073229DD8E2ECD16ECE73F -:1081B0002FE764B2FDD78C55A9F75D0B391FF4BECC -:1081C0002F90F129F83BCCFB2D5DC5BE3F46E4F076 -:1081D000A845B673A7EB5DCFFBD0233380701C4D51 -:1081E00073EE7F017F7FF992FEDF27B5ECFB3E94B3 -:1081F000EF46D9CFBD26F98CCBC7197F746926BD50 -:10820000BE2144BF731FF0D1043F3B37249322A803 -:10821000BFB2C6C99549A74AF1FEAE628C82BC6660 -:108220008A716ECE9C9E7E9C7478B5D663CD03A277 -:1082300008DFE999ABB138E2B43021B3207EE80918 -:10824000DDCDF2878C0F72781DE2CCDA8C4423EC02 -:108250007B65BA4E1BBC1DFF77F67F83E71D474445 -:108260001DCFB7BBF030907E68CA64F9E45C29BAD0 -:10827000C90B7993D542CAEFD86DCC647FEF6852B1 -:1082800066B25E0AE719B733AAC0F72F96C92CFF6A -:10829000454874D442DBFC9338BFB9DFCB9558BD59 -:1082A000117993C973DBBE75A352C9CF2FB89C4E09 -:1082B000CA2C71D4392E89DCAD807C2E59B0503156 -:1082C000FCF0DCC0F1977238DAD4E8A829FE5E3CF5 -:1082D000A5D5431C3F1DC7A24DF0DD8FD5F502D6B5 -:1082E00009946E647CB77AE3417103BDEEE5F2B7A1 -:1082F0001068601BEFBB9CAE6DFB7CA301FEB664F7 -:10830000FE860E4CE1B87937C17CC893DB4FB7408D -:108310003EA45B203C7F726325D43574F3FAB69794 -:10832000E9F346C0DF9C3C94EF711B3FAC03FDDCDE -:10833000A1123C2FF3BB2D9E049C27B0F825A92742 -:10834000369E6F80FAE147D4CE89C037794DB5F7B4 -:10835000A5CA9FBEC4E9F0477F242B951F685D2DF9 -:108360007D6EF55B241B4AAAFE8B2B5D768DC33D8B -:10837000CCD37986A4C86326F930D1BF9FF64BAE23 -:10838000C77FE1CAF32E39963ACEF82BCEBF6D895E -:108390008AF568B74C0F9E43B1E0B1F0956B323C63 -:1083A0002D5B2239F4EDEA05192EBF87E1F5068F22 -:1083B000F128ACE3917D3F9D88E7A85CF6C1274595 -:1083C00055787E07E954404FBC2F19787DA3C1F939 -:1083D000775EDE20D1EDD3C17ED64B29E5EA8F9CB6 -:1083E0007FDE5871CB52843F26E900FF8955C3AE2A -:1083F0002F03FDB24209C177D34FC4EECDBCCDB639 -:10840000FEA45FE382EBD755B7F46BB796AF70D29B -:10841000AD4D657E81791D93C33B298FCE42FEEA27 -:10842000DE3E93CE7F249133652BEB4EE0EF4C2D57 -:10843000E6BFBF2F4677CCA4FAE694C8F224E657ED -:1084400098DE58B233D20CA9D353F557BCD44DFBA8 -:1084500079038CEF7E5BDFBF7D74F3D3B89D4E7FD5 -:108460006FC631A2C2FBD1BAD4F6E0DB7A06FF7B3D -:1084700062A1D1A05F6EDA98BADFFF0266A6F09C17 -:10848000FA8B54952A3E7995CEE05D1D49FDFE5547 -:108490007A267B0E7629059ECF0532B89ED3478378 -:1084A0009E5E9D06DE0F030184F79DE6FB6F823A18 -:1084B00090F75DDF817F27C0F8E26080F1F7A97D4A -:1084C0002B953CA0538BA0033FBC9D1D9A00FCB68E -:1084D000267602CFBB1CE0787ED3179912980EF255 -:1084E000B2686E1EA54BC72A12128CF4FAFFCA009E -:1084F000F31B7279BC96DABF77C1FED157DF45FF17 -:10850000430E8FBE71222B81823AF053A2B90EEB3B -:108510000CF7F9585D29094DB7FBF15FE6709CDA5D -:108520003F347A2F8DB8FCA03EFE5FBC1AE7DD9F7A -:10853000A1435DCA914AA9F35A0AE4C9FD19F87D1D -:108540005CB75CA49B7FA87EE0A9FD43F303075AB8 -:10855000F78640D1A0FCC073958FEC980672A4C634 -:1085600027A5D2BF969E3ECAE3EF6EFEB1AE5FE591 -:108570007CF47EA27FB8EED8ED84E7A65A273C961D -:10858000BCBC9F68F2AD013C91CE8976BF94CC997A -:108590003E809D65F9A974706E77E909E03CA0C33F -:1085A0009D5CDFFCB6FE91809D0EEEF59F12F9FEFC -:1085B000E05156973B36B2A622CFE8E5CF6F7D4E0D -:1085C0007C69D919F738FFD9F9D0B27303F1616E1C -:1085D0009A3CCE2438E84CDF5F23EB2AE4EB2705F6 -:1085E0000CD626FA3C38AA45CA78DD283146C3F9AC -:1085F000AF53FB7CF8F7A1CCAD9EC4582A02EFEF35 -:10860000BB7A827D3DBFE27CBA7A49367E7EE27DCE -:1086100031343F1FEBCE24FC8EDB1BC772E641FBDF -:1086200091C32268687253DD1A09D6F74680ED3B84 -:10863000576F7C1DFDC1A1F2F9EA5AA7FDBF8AAFB1 -:1086400023E967C93DD3807FD2E1E1358E87A591CB -:108650008573413FDFB251407DFB1318872EE4162E -:10866000398C7A9BC4987D241AC50735212760115F -:10867000808F7FE0DFAD9223AAFD9CDC6DDBEE9F57 -:108680000BFEA15B5E5664313EAEC86276E14D5F83 -:10869000F40FA0EF2DFDFCB6507B309F76D918D09B -:1086A000ADEF04A39C5AEBD9C8E1A27EDAB3F8FD82 -:1086B00062BE3ED2E3E237315EFD63C07F85867ED7 -:1086C00081CF43F53ED4453FEEC33A2A4BAE2C7FD3 -:1086D000C7FDFE3239EAF01B33B38A1CFEBBDB0F49 -:1086E000F99BBD48DDFF8AAC2FD65E5C9BF5D9D8DF -:1086F0008B619CCFDC762329D72DEC3CC889631F86 -:10870000CD4D25D7914F08875B9EDFDFE763DF4DB7 -:10871000BE2613F54EEF7E2A3F01FB65B75CC07E97 -:108720000ABEFBF1C8BE9F4D84BADE13DBEFBF2942 -:10873000153D67E9CC6F22DDF98E78DEDA00C1FAEB -:108740006F42E77BC236BEF55E525E06885F2E5BE7 -:108750007925EE27DF5879F5E835A57DF7157DFAFF -:108760000BD17F580AF336F2FDF40E4FD5BE54FB01 -:10877000408ED7BE7162A77FBF746379336CA9370F -:10878000655CF3A5688AF993FB9A8DA9E3710F7272 -:108790003D95DCD798745F43F1D1BD4A0A944DEB07 -:1087A000DDD7749B9FCFBEE677A4E7E73351FE5336 -:1087B000C3F73D8BBFD4E88E2B297CA7E8FEC70406 -:1087C000F911E97BC02FDF4ABD5F7B9CBFF7BB8DF2 -:1087D00043D457C79CFB9974F2F7BDCF48FEDAD457 -:1087E0009E51A0077EB7F7E3B7EE87F5ECF521BE03 -:1087F000DDE3447489EF2F7CC8B7967DEE5099FE77 -:10880000FFDDDF8DC0BF9BED960F42E2D75F459F36 -:108810001FDF274E81EF2CB6EDCBA84AB5CF59AF5D -:108820000B3CBEE48CF710EEDF2DE5FCA6EF7BBA27 -:10883000D61E8F7E93EB2B2B0EF0BFB3989D5DB2AF -:1088400060A10AF19EDB92F126829B15FDB2C2BDAA -:10885000F0FD8B5FF2F35CE6DACC94E7E37EC3F1E4 -:108860003B501C62C52A679C60C982FEEDCDC9449D -:10887000EABA2C8B9FD3CD3754FBD296185A5E6C34 -:10888000A0758ED007675F9692DA2F41BC631909F5 -:1088900029705D426A27FE98A2F2E4EEC508CF2F48 -:1088A000ADBF7FFCF1BD13ED7ECCFF0710F667274F -:1088B00000800000000000001F8B08000000000086 -:1088C000000BDD7D0B7854459670DDBEFD4AD24924 -:1088D0003A9DEEBC091D020818620742001FD02114 -:1088E0004482B2DA810041519A87184948A2E2CA0B -:1088F000FEBA438720467466C2AA8CBFE3B80D82D5 -:10890000EB286AA2D1418CD8A0F8D8D59DA0AE8B17 -:10891000B3E846C7415E4322A32BB3CB0CFF39A774 -:10892000AAD2F7DE744370C7FDF6FBE338D7BAB7B7 -:108930009EE77D4E9DAAB63915C63C8C7D5B73FBC8 -:108940005F4D628CFDABB579BCD3C1D859FC9B1E81 -:108950007DFECB3AC6221731F6E13A3B8BD8A01CFC -:1089600036558563D4FB53AA8931E8E85FE1C14AF3 -:10897000190B2D50C33B94C1F5B2705CACB7785E57 -:108980006A30463FF2B9A04665113BA3BFB3F06F12 -:10899000CD9C245DF922A753F4D39A182C62EC885D -:1089A0001CF7513EEE91307F2FFBBB488C7B247C23 -:1089B000EE716F7E04C61D131DE78666FDB8BD2CE3 -:1089C000B48AB9619C70A2734701C3FF8CD8264456 -:1089D000DBEF759A08AEEC48A689653076876C1B8C -:1089E00067BC0F057C8DF56BCC7E8B161FB7A77A05 -:1089F00069FEB25C33473F4F6F8A938FCB9CF981FE -:108A000064C68E6E4BF4133CA6258747C13C2BED04 -:108A10002CE480793EF8E4C59FB1118C2D13F8AF9A -:108A2000097C6D41781C35F5DF938CEBFAC0E4DCF2 -:108A30000143951DF45BB4F0BB2B85C3EFE8F673DF -:108A4000C3EFAE143ECF7955FAF9CD3F98A82B1B52 -:108A5000D7FBEF7F7BEF04ECF7DFFFF63B8BB6FF36 -:108A600005A77359243D5A5E52ABF8C34583C77DB1 -:108A700029D53A24B8BF6480E392D3F9D4BF5B65AB -:108A8000CD1D31D655EEB453FDF981728B07E0B997 -:108A9000FC6EC5A74017339CBC9FE566E6EF80F9E6 -:108AA00030B337BF1AE0EE696DBE2310A39FFF23DA -:108AB000E0FD8D23901A8BCFE4F363410FB2DE0209 -:108AC00073D012ABFEC25A3D7C7B19AB8A35FF1FB7 -:108AD0003B395F0E951EE5F8C6FA439DC7DD820E51 -:108AE000D36D91DF33155E9C807ECA2E605C437D22 -:108AF000E3B8F73BF5F8338E7FF4CF6A5D2C38BCD2 -:108B000026F83F1800FA89F93D99BE7FC0DA1B7735 -:108B1000137F27F9762018B62FFF09A09DAD9C7D05 -:108B2000C75BF09A25A614D0FA16070E5412BB9D07 -:108B300079B018F1FE6DD5833F2985A91DB5065B77 -:108B400093A1C1D1F58A2FE41D3CCE07B84E90A366 -:108B50001FA13CBD08FB639C6E67C2FF65333646B0 -:108B6000F5D7A3506177D9BC3B347CEB5EFBDD3A93 -:108B700056CCD853D6C0FA64783FFAEEAFD73094CB -:108B8000792C4CF3FEC2E2BB85E0CD18F1FDA16D5E -:108B90008EAD9BA05E6A0A97938CF9F203E335725F -:108BA000C2ECA4F250F1F3611CFC5CA89C92EB8C2B -:108BB000370E409EE6377786A34D4965ACCBEABDBC -:108BC00009D7D33F3BC1B90D5038D7EABF1AE1F3FB -:108BD000C10193A9A580BA35239DCEE343B0826B32 -:108BE0000AEE1F578AF2C7E24F80A954431B36157D -:108BF000E868862384FD957E38E719C4CF83B536AF -:108C0000AF8AFD4DF37EAA4279EE5536EF7AE8AF92 -:108C1000AC67C45E37F43F7F8EE264D07EE6EC51F1 -:108C20009E5E585FD25AE8270747B8B7AAC2CCD889 -:108C3000D3F89F97323E6180C55C45965F6C9B0977 -:108C4000F2609CA7CBE40050AF4C7BB1CD0EFDDEB3 -:108C5000D312C872A6C1D236DFD7661FC658468661 -:108C6000BF67BA8FB1D99BEFAFB25F01EB7C54B451 -:108C70000F3DD0E6CF63EC5553B04081EFCD9B77ED -:108C80005499015EEE4239FE2B6DFECB613D57DDFE -:108C9000B2630DF4BF25ED9FAACC38EFC572FC9EE0 -:108CA000AA8A9130FFCB65F95FEC385F77926C0F41 -:108CB000F39DC298654474FEE62C18DF25CB9F54C3 -:108CC000CD84F13F2E6FAE30C3F8C7D2FEBDAD6884 -:108CD0002C6393E7943BFD50EEDBFC1F5549809FCE -:108CE0002E06740AE53F6C3E4DF377AB26DE7FE837 -:108CF0008F34BFB2C5A171F85D617F6AAB8275AF79 -:108D0000B6F7BE85E4DAB43664CF4091A4703AB1C8 -:108D10005B9AFDB9003BCBAEF2482E4DA79DD36BBD -:108D20005E643CEAB181F218288FD794B378B96BAE -:108D30003D5B124BDE76BAB81EEE4A8CFDBD228D2D -:108D4000CB03801BE993D483CCBF33865E1997E6AF -:108D5000A07EF627B290DD15E5B76B8187A7005F8F -:108D6000323B9FA7EC6790FE48E3729F85AE75216A -:108D7000DFCCC12E60E9853E258474CD9A93C2A3D1 -:108D8000907658C43C0FF5876AA2F97A5465493544 -:108D9000F49791C8829DF0F4A4332A437B7FA723E4 -:108DA000DADF7B82EE2B0B03DBB1BFCACCEC92D6B1 -:108DB00082683F30EF0DF609BA799BA7B8F0FBDC6B -:108DC000925B8B34F02CE2EB003AA07630CC33D3BC -:108DD000810FBA7AC68DD804F3FB06E5AE27BAAE8A -:108DE000B29EB91606F5B6B8843CF1F2F69E0A2E8C -:108DF0007FFA6F4D0A6F43FEB4FB4A104FB2DD0D90 -:108E000002EE15F7CEF919D66BE8B1301BD45BD35F -:108E1000599EC9CEA1171B4E5FC6C213356573C4D8 -:108E20008A72A7E1F4347A5F71EF7B56E453ECC7A2 -:108E30000BEB5A93E0CFF421DC5A63E39FB1169A0F -:108E400047C3E934169AA87DCFE114EDDF4DDFCF9B -:108E5000B7AE687F2A0BA79FAB3F2B7D1F80BB5906 -:108E6000C0DD1A7B9E1B04FD20BC4D1AFA9A2FE828 -:108E70000DA49F1FE5E1A16B8AB6A1BC8F8EBB9E9E -:108E8000FAEF32031ED10EEC49F4A25D5C66E6F205 -:108E9000B3ACC7E50C2951FA907421F1DAE56A2EDA -:108EA000A7F5562BCE6D0583E775BF9C97D0A79984 -:108EB0008B83EA52CDFC243F40FF5DA2FFD229C440 -:108EC0003FBFE0F4027C7303F22FDA2DB80E5F642B -:108ED000FCDCE4C1F33F0DE4854FC02387FF5F391D -:108EE000C2A80724DC06C33FF73CF8CCA7EF653DDA -:108EF000FBACB8CE86387CFB802B85DA651E8CA453 -:108F000078A1DE19617774754C4CB80CF9628E89C2 -:108F1000A108C375A3BD5A36206FAF7C7706C8DBA6 -:108F2000CC8132C85B2FE26140FE46ECF668FD1F43 -:108F3000B9AE9CBD01E4B5DB06F82F223BD4CE349C -:108F4000FEC4EE346EBF4D09B29876CBDFB9927590 -:108F500072ECFFAEAD60BF85F599D3B8DE9FD21B32 -:108F600052102F92AF8D72EA13C18F1F8BE7FFBC97 -:108F70009C52CE23A7AA859CE2EFF783998FF53206 -:108F80003222E315D089CBDE9D380AFD99DBB2543D -:108F9000EF97C057F314DFB067A1DF1ABBF79E64E9 -:108FA0006F944E6A98DDEB40B883D17416F5FE9C41 -:108FB000042AE31FDA25A7DA154E87CC9B5A333EE5 -:108FC000BE1C92F3B82DCB4AE32DBB6F546A503BC5 -:108FD0003FA127AEB5459E658583F95C9661FEABE2 -:108FE0004DAAE6BB83EBB3B1C9FE6FD2D00E555884 -:108FF0002DCDC7602F3904DF19EDA587B16F0FFDA7 -:109000002F62233E3691739AD9660B33DE24847E19 -:109010006A660713FC1A313568E8C0EECAA3792CDA -:109020005E081F2F01A6B4BF71C9971A3E7A07E7E1 -:10903000437A213209F934C1C57476DE623590A7CE -:10904000A0DD9A69F3A19C013C111CF62730730244 -:109050008CFB363C116F95EAAD7B2D6EA403C5D712 -:109060004AD0DF2AFC5616417D73EDF424B25BD959 -:1090700099DB4756033C3C499C6EA11FBBE8C74E99 -:109080007422E4DEAFF3C76E43FD24E5A7C4033BBF -:10909000A3527FF2FB7EA53ACF09E5FD9E8B4A5A8B -:1090A00015BDFD83F650D47E4ABF6F16F0E3E4AAE7 -:1090B0008E880958A825E4997D27D4AF4CE26B1E11 -:1090C000E9E27A707F41484DC1FE46C13AE0D55B86 -:1090D00089C1A26647141F60E304117F1956783ACC -:1090E000387FE0739F8BF3D99C748E942DE9BC9CE0 -:1090F00091C2EB1BE9ED49F17D95C2F1BBA99CCB77 -:109100000963BDE92EDEDF6A7BA82A6384D6BE0A26 -:1091100030A44333E37696DF25E8A482C3ABE2DED6 -:10912000C5A9A837BFED999FCA8AA272F41E25E887 -:10913000F441FD7B2C819F52BCE35F5486FE883551 -:109140002DE87441BDF4A4D8FEF24D621EE9E84F4B -:1091500043BD9F087FC772FA62F2B317BAB83C4B9F -:10916000C9AA21798E30F4A29FC2FA434E0DFE5255 -:10917000A798747E83E57431B5BF70BBA1248EDDE2 -:1091800050AAB31BE4B846FBE1D37559347FD9FE2E -:1091900086AC8F2A99A6FE8DACF71EECEFC635B9CA -:1091A000BA38513CBBE32E011FB4134231E765D5F9 -:1091B000BDFF14FCC49076FC237CFCE8B849C06871 -:1091C000D171FD2EFFDD2EE2A7CB9D872F864702B2 -:1091D000BC5749DF90DC07BDE4DFEA207D5485F20F -:1091E0005AFA47C8F7CE54A4F1F20DAE491AFD2839 -:1091F000DA19E5D09F453CE3CF4E6EFFA51E94F6ED -:1092000062A25751A2FA66B0BE127AC62017CF6783 -:109210005F03BD86B4FADFD8EF53AEEF6B5716C6C7 -:10922000A18FD1FF237665D9E541753CCACD2A854A -:109230008D82C7E4997A3DDFEDE2FE47B72B49A75F -:10924000E7E72ED6D78B60BD49F84C1A92BFA2D55E -:10925000438A8AF28EF7D728E8A1E0D807562FC8AC -:10926000DFFF1276D017E9FEB791AE3624A614A31D -:109270007ED8FAA78A315B61DEFDEF5B7CDBB0BB99 -:109280005D9C3ECA17AD6935C37B4B87E2B4318D17 -:10929000DE5ADB79C90A58EF0792FEDD7C1D0DEE20 -:1092A0008875248C9BD3C0C7CFEBD8AB9835F22DF3 -:1092B000AF8ED73BE4B2E8F45EAF287F26FD0F16F1 -:1092C0006EA92CC5FA7EF326107D391D0AC583735D -:1092D0009A01004007393EDEBFC31756961745D79F -:1092E000D966AA2E42BDD09691E443BD30D61D3C2E -:1092F0008CF4DF70281241304D3ED46346FBAEC281 -:10930000EDFF0ADFCB757A55670ECAD5A4437C7E84 -:10931000ED067A070B59D0F9362E6F55F60E437CC1 -:10932000A0EC80F132D68F21BD24EB67B8849EC8B3 -:1093300060C117C8AE626D8CF0C5681D19EB47930C -:109340007D2FF119B5A3C64E403BAAF0818879194B -:10935000B4DBFD58ECF8BC45E81158074BF744D78F -:10936000118F2FA41E93F52C71FC6849EF4955B15C -:10937000ED53D000F4BD7C91FB3A5C77C3062BB370 -:109380002951F857B803E9389F9C8EAD0AC246D2DE -:10939000D706D7D34A2EACEFF65B985365F1E7DBDF -:1093A000B0F6C54B5668FC2DE89FF0B1D5CAEAB4BB -:1093B000FA54FA1317A773FD73A73B3002C76DDC8D -:1093C000B5D98AF8BD65FBE7566DBC7BD03A8608F7 -:1093D0002FA58EFB290DB5F630AEB37C9199F057D1 -:1093E000BFC11A4679D4B0B33362427BFA6EE6430A -:1093F0007E6FE8E87C2B07E092DBE09FA47AA3FD78 -:10940000E53684159C4F0610610FF979112BEA6738 -:10941000235DA33D8C76C95B099CDF4F943B420AD8 -:10942000C0EF8425D880F54E6427F942055178BFF6 -:10943000DD39EB1D05583AF9055B049F6DA66D59A2 -:1094400076A8D736CEEA433AAA700767A5037C5CB4 -:10945000E64017B64F7327FB5AA0ADD7C626907EBD -:109460001E221C261BE861F2DD9C4FFE263D45DADC -:109470007B13500E2D4D4F96F612C9A7B72C7C1DAD -:109480001B189FEF3E977F01D1ABD345E3E63444F1 -:1094900014B4F78DE346E9C9BFF842E81BEC3C2B56 -:1094A000CAF57A2167CA176D577EABA1837A3064FB -:1094B000905E72766E55D00F84EF2D956EAACF6CAC -:1094C000286776F2FD887AF87E9346AEC875C49018 -:1094D0002FB7217C1D877ADEE4F22542F427E76B63 -:1094E000C4E78FD2B91D77259805F4DE1A1AE385F3 -:1094F000FEDE1A9148FD497E37F2E78F049DE7D4DE -:109500006E57306EE04EE276A39C9FACF745FA8C26 -:10951000F5389FC9553D0487D5B566C29B9C4FA5BC -:10952000353012FDAF76D1DFBE859F597BA1FCD0CF -:10953000AF0E103DAE6E57FCE417B41FB0CEC7F8A7 -:109540005CE8972AC663AFE62609DBF2D201D22394 -:109550005777F138C1EAAE4EF37247944E0B8EED59 -:10956000BB11E96C75878D2528883FBE5E239D82DF -:109570007C21BA67212BED67817C0C913C65C1028F -:10958000F447A4FCDD27EC4BE6E0EF9F10F396FDDB -:1095900046E56602D17BC1B109FBEC00CFD53EC5E3 -:1095A00007A612D8DBBC1EF41F21F9CBD808F4CBD8 -:1095B00064FF46F8FD5AC8D518787E3E3D861E9158 -:1095C0007AB5E0F1190C9F127F660177D9EF9E748E -:1095D000BE9FB527DD4CFD6F28E7F1EB0D16AE3FC2 -:1095E00036B4D8C3C8D76FA75DF98E520C707259C4 -:1095F00023F8DC6F5AD680DFF7E7F079B499D68F7D -:1096000069E6FAEBF574C25F0AE3F289CBA3875EE1 -:10961000E4F2A421E4203FB12158B382F61FDC0913 -:109620003EB4F759F04DEBFCE4283D18F1EB7D61B9 -:10963000AFD50BDFAFEEE07C10855B5847B720E776 -:1096400008EFFB5C723F2258807005FFBD05E30CFC -:10965000D27F4F591C08257B07F36BBAF0DF27092F -:10966000FFDD32C5FE17F5DFEBD7FE5336965765A3 -:10967000BD4B4FC92FE027EAF8EA84F0DB0E08BCA7 -:10968000FF41D04B7D6907F143FD97CDC4478E2A3A -:109690002E4F1C87F47290B11F8BF53F40FD54266E -:1096A000755CA9A23FFCF78AB395C59FF7CD4AF335 -:1096B0003F4F45BC74AAB42FC5CE80555F06704D90 -:1096C000103010F52C6E1EF73EF1142002F9D2DC9A -:1096D0006C3D97FD7BBE7E59E42305F15D2F607DD7 -:1096E0006267C5D4DF613CF1A954DF2858FAF19DC7 -:1096F000F3FEE677D0FEC4F6E93ED4D3EED600D131 -:109700004FBF27C1877143B70A962DD0434BC71B64 -:109710002997E1BED833974C40B999E7E67C79ECBC -:1097200045752DC267FD3F3C3F0DBFD7879574B48B -:109730001B4F3CF5F77F46BD58B7BD093D0DD6FA26 -:10974000CCEB64879BC25BF9FBA752C9BE3CFAC451 -:10975000E66908F7D68E56FA7EEC89AD54DEF70F2F -:10976000CFEFF94FB43702293EAC77ECC5CD3FFAC5 -:109770004FA4F39A141FAEA32168E6FBB692BE8DE8 -:1097800072AB732FF1A9A497AB51EF229C6AB9FC7D -:1097900091F4FC85D8575A56E1684379F6C5A6E49A -:1097A000BA58F144BF582FC65C488ED52A144F6B67 -:1097B00003AAC1B8465B229B82CFA4A2883517C6F4 -:1097C00059B8B8731AD93DA1CF5762FD79BB12D8E9 -:1097D000268ABF61F016EC7F2275C6C683183C0C42 -:1097E0007E32F4BEFD2CD8D71F5B309643FDE9ECEA -:1097F000FF796DEFFE11E5688DBD77AFC71B7DDF8B -:1098000026E234509FF44ED99AD8F1D02AB743D0EB -:109810002DD79B395DD5795E921336DF288D5D3A61 -:10982000EC60F32610432CA7AEE74A5CC75563965D -:109830004E24BAC0381FEA9F9083FA5F8D714AE0C8 -:10984000B3456ECE4F194EE6BE14C6AF3433B703E0 -:109850009F8C7D642139B283FA05FB83EC2AEFEB00 -:109860000B77A03DB2C512CC9E84FDB409BDB59D59 -:10987000CF1BDA3B71BF14FA735E3A81FAE9B1B8D3 -:10988000A87D88B79FB5BD4589CE1728351FF51629 -:10989000F657EA403D13AA25FC78ADB4AE635825CF -:1098A0009BD65D7CC3F828FF1AE33B28CF701FF8D6 -:1098B0004E77F96DEE49D1A78CFB18E1F9327E871E -:1098C000757FEBF6D3933D95AED32BF1EC957D0BE5 -:1098D0004F72FDFBEAE7246F1A918E71FCE0973A14 -:1098E000FDBB5CD2F12B9F131D2FDFC5F56FE3AEDF -:1098F000122BD2EDF1757EF65B30401BC53EEB16A8 -:10990000A57725C5795E497062FCEEA4D037F50FC6 -:109910007C7E18F74747ECCA26BFFEE42B09B5D872 -:10992000CF7E9389E0B97FDBC55B5B15ED3CB93F2A -:10993000007630916A23D8A9DC0E5EB119FDB3D54B -:1099400075CC87FCDF68A09FC65D07885EA41D5CA0 -:10995000F0F8DC15DCFE4CF025A0FF3693DBA30C01 -:10996000EC51AC9F3633DC6225FA2A2943FADAB788 -:1099700070CF46D4E38D339913FBDF32CCFF4A2EF0 -:10998000AD476198CFB2C5D23EC30CEDB7547A9DB6 -:10999000004980DB76B27BD918ABD0732BC85E6EE2 -:1099A000CCBADE477C669407AFB490DDD5E84DA411 -:1099B000F95CBD4BB98DDB230EC6E7AF107D5E1D94 -:1099C000BE2C8CFBCABF17F093703C69E9B911E15A -:1099D00071F2252044F87EF54C4EAF69333B488E3A -:1099E000BCFDCA2CD2E3922E935FB6913E77999D2F -:1099F0008A8FF4DA3C9B16AFED16AE97D2849E297F -:109A00007C80E33722F82922F440C46DD5C75B9CE3 -:109A1000A162D4BBBF17F8273182F25DC893D52B62 -:109A200022C44F0D3B797F6E9BBFE4760DFDBA2BB0 -:109A3000B85E94717FDC07A88E212F7EE7E6FAB12D -:109A4000E0F1659BD15EBE0AF08E2A25678C90A35B -:109A5000401708B79CBA00D1C155EE9B7D6A01ED55 -:109A60001F909FD8DF6265B1E23C47851CF5A407D3 -:109A70004A31DEECC94C263BC7A3969B12B05D89E8 -:109A8000E2DBE6A5FD4DB2F3FA3DD9BE6D3A7E0F9D -:109A9000949AA0DE918C648EE7F0AFCD73C7231F3C -:109AA0007AA59FAEB3FB06FBDBDC6E9CD31E2A4679 -:109AB0003F44EE5F4838845B126BB5F2B34FC02170 -:109AC0003C96C7F3C1BE7750FCDA09E3A05FBFED57 -:109AD000B227B85FDF4AE31F74F3784625AC0FED79 -:109AE000364F61600DD7A7C9BE58F0B853E079DF93 -:109AF000C21B4BD0AF6CAC71F890DF1E7A55594643 -:109B0000F48CC141F4B7832B080F0CF080FCC082A9 -:109B1000DC2F6D6C0E8463D37B35F15F23F29F42A3 -:109B2000F44EF176A0F730A777AEFFA4DF8FF2B145 -:109B30003AC67EA8942F8DD6DED148C7921F1AA7A9 -:109B4000F58E46B80D559E9CB400FF23FF001C9077 -:109B50007F24BF24EFE67CB2A9C55B8EDF37553288 -:109B600067AB461F19FD259C27FA9D52AE8F7507DE -:109B70000A3D1807304536621E8594C38DBBEF1B26 -:109B80001D2BCF4DCA61BB99CB377B3829DCAAA1ED -:109B90002FDCDB4B9E404FCADB495A1B3B2E52E663 -:109BA000718878FDD0F222325097A3BCD996144622 -:109BB0007925E344C67EC778145D3C46FA2DB8BFCC -:109BC00080F5E77A38BD547AB89CB85E3CE5FC2550 -:109BD000FD7B4DC1CF319F289EFE92EDFE52712B31 -:109BE000398ED4A346FCCBFD115C4F7551FC7AED48 -:109BF0007BB97C32D2E372C1275E5C2BD47B4EEC06 -:109C0000670DC62FEF87D59A75F96F6DA6CEBA5836 -:109C1000F12FB9BFC11E320F29BF6EEF3A9E47F533 -:109C20009CC8A7658BCDBA7C2A87CFDB82F1D3197C -:109C3000F6821295C6E571ACE469EC6BD4C3C5BB82 -:109C4000DAC7609E9227A0DF1FC9AC4DD4ED3F64F8 -:109C5000075DBA726E5D8EAEFEB0E611BAEFC3D785 -:109C60008ED37D2F084DD0950BDB2ED5D51FD53E3D -:109C7000439F8FFBC855BAFA63C37375E54D2D1D1D -:109C8000B588978B9FBA4ED76E86D9692E01B88E4C -:109C9000EF58A6CF1333C033F5CF6A4C3A7CD2537A -:109CA00040789D61D6E70B5FB24B0F0F4C8BC3FE24 -:109CB0008A99E86FDA9109E7CA632D66E66F7A65DB -:109CC000FB82C1F4C0ECBDBE400C3F53D2B92C1B8B -:109CD000F7B1A4FCB850FA8B374F497FF1BEC78368 -:109CE000DBBB1EB90FC3E16219804BADEF5C70B1F5 -:109CF0009C0F2E0CE092FCFDE162EC6F7D5223E59F -:109D0000037F84058D7DDC2BF84896178452B91E9D -:109D10000ACC3B8F1DCDE3C0411BDF9F347EB7676C -:109D200070B9361AE640F019225F7F26F070281EBF -:109D30005FAFFD7A7F26CAEF2A467EB3B3B9E56BE3 -:109D4000D45B4BCC1186F4FF9058CF169117FAC80C -:109D50003A27F5F3A8D87F7C6C9D97DE3FBE6E0C4A -:109D60003DC3EB7CF47EDBBA29F4DC0EF61C3E9F8F -:109D70005C5745CFA7D605A8DED3EB6AE9B9735D7A -:109D800090CF6B10BE5819D93981F498F1D2A52122 -:109D9000754878626A5E4C7D19B71F75F139F3C852 -:109DA000D71E5A34FB4D0DFF666524BB0F630EE3CF -:109DB000643619F733CFD7FEBB75B5B3DF1C3574E6 -:109DC0003E92F4C4CEA48F8EC5D741913FF9BB8794 -:109DD000CF6E0A15C5875794CE62C3A9C67E3207D7 -:109DE0009DF562B41934ED0F1AF8B826981AD36E9F -:109DF000A811F4596BE3FBEF8B0CFCFD92F8FE52BB -:109E000006D7779FC49133576798A43F6FA1FDC0D1 -:109E1000417CF7932B62C1777F8657C7C78B820639 -:109E2000BC1AFAF9C4D23ECC1783CFCED78F5C9F31 -:109E3000B1DDC3195C6EBDF8FF297F7E725332F924 -:109E40000F08378F66FD9FDC94541B2B2EF35A06A8 -:109E5000DF0705EB9C15B8C8D40F59D1561CC3BCFD -:109E60007C9F77A413E343320F203EBD9A298E4492 -:109E7000305407C315F0E1B51642FFE68171226642 -:109E80001CC7678AEA59CCA9619A731EEA607A8076 -:109E9000F6212BE5EFF4E6D0BEFF05D213531F1BCE -:109EA00075AE7DBA41ED2F50CEECF881E58CE473B0 -:109EB00076E6C151B1F4642D8E7D29AC63CBD4FB21 -:109EC00049CE9CA7DF0B855FADDA4BFBD64386DF1F -:109ED0002EF790E2526BED29C50CFCBAEF12F83365 -:109EE0003483F1F3589F2584D1CE3F20E6098EFFBD -:109EF00025DCAF6E9E8CCF7FCE0A7C9801ED975902 -:109F0000B99F383EC3FF119613C53EB035D3BA1181 -:109F10009FCCC9D7718958C74693371FD7F1A5E29F -:109F20001B8B7E8AD314F6E1338545C6F3BCBB7028 -:109F300010FDB3F48B13BDE8DF268E66AC87E2E13B -:109F4000BE048C9B5993FAFF7124F2FBEB268C30F4 -:109F5000B2E79D7CBECF3F924BFB2AE801A17C2853 -:109F6000C6F730F54D688743FB6B59F018CEEFA864 -:109F7000D31E32C1BC8A677FE1C27CA8E7BB67D031 -:109F80003E42E4293564C5730B3D27FEEE6AE8EFD7 -:109F9000921E0BC59B2F612AC9F37A337B00F926E9 -:109FA0001E3C8FFF75ECFCAE2B32B9DC93795BC69F -:109FB000EF79E2FBF13879C48E4CAE17647E8C45A4 -:109FC000E6C778FCE7CC8FB118F2632CE600C37DBE -:109FD00060CB407ECC6246F931D08F363FE6F88CBC -:109FE000D8F3708B79584E27C5E93785DE1F1F716E -:109FF000EE755A4E27E8F2ACA3ED1DF43E5E7ECE20 -:10A000007831FEF138F9496307FACF66A1746D3BE8 -:10A010002F9FF7C03879F4DD62C8F3897EE7F93DF8 -:10A020001BD2389DECCD72BA9742D74B59AF05E998 -:10A030007489C36DC1F85180F93AE9DC8ED9D2DF59 -:10A040002BF96E04D6337F8176B609242DDAD94BED -:10A05000D65ABEE8D5C8A96ABFBECCB0BE46EE6E21 -:10A06000CA6234DFC4716328AFEF14F3A63ACF217C -:10A070003717DB55BB59B3DE4371EC865B05FC0E2D -:10A0800065C786DF7599DCEE88771EE2D6CC14DDD5 -:10A0900039BDDB9DE7969708DF60BAB67F231EDCEB -:10A0A000F4FD7C70F6E0E61AC6D1CA159EBFFF1714 -:10A0B00087779A3857C5CF05580C79E89BB2B8FC1A -:10A0C0008BCE9BE7A17FE40CDC9E8972D1EC1DADA9 -:10A0D0003D07D065F6274D80E72121778C70D99D0B -:10A0E000C9ED37E3BABB443E7DA2CA9A3B35F0378F -:10A0F000AEF73941E7B2FE060BDFBF82BF801DF02D -:10A100007203E372EFE1CC11222F3CCD8CF270315F -:10A11000EF82DDE07C8BF693249C07C14FC0DD0805 -:10A12000C700F3DE8879DBE783674796FF6184CB5E -:10A13000D203895694FF37DAFBF7A38FDADB63FA91 -:10A1400078243C3F778C3CBC9DE1FEDB9897F7C1BF -:10A1500033658A8FE751B09964EF28A15CF5ECC5AF -:10A1600043B77736A604C7207F7C29F2AEA53EDA36 -:10A1700098736C34E6CF7B5DE5ABB23C1477F7A700 -:10A18000231DBD66E374F408F404E5A63D63B7A29D -:10A190009E79302B5887F5641E1FF3F78FC63C84D9 -:10A1A0000B8513FC59908ECE07A7273219E1E75093 -:10A1B0004A6C3AF94D1C3A31F2079D2F2BFDE1F81C -:10A1C00043C253EE5BC8F9D565713A944F093763C2 -:10A1D000FE505D9649D4E3F9880F660508CE7DC32D -:10A1E000BE3E9C00733F64C8F792CF93421E9D6FA2 -:10A1F000FD12DE3F941C3E94187B7EA6ACA1E1E7E5 -:10A20000879A5FBD9C5F71ECF965660D0D7E01D686 -:10A21000FF59DA0FA0C700CFF58867B6A19FE4E326 -:10A220002157EC79960D799E41CB0FA16F257DB317 -:10A23000D0D23ADAAFCF4A8CB95FBF00FC27F47FA7 -:10A240008CFBF6727F1EE407ADB7C6DE7F633AE291 -:10A250007DA65877068BA4E17EE61E1BC5FF8DEB1D -:10A26000BF42D011C0AB82E035A79FE2188746C736 -:10A27000960B15C6FA6D7C9C78E70BAECE528674B1 -:10A28000BE80950629FE576E774454C0C36D021FE9 -:10A29000D6DC553EB40FCBB3DE3B88EB04F89F18F9 -:10A2A00080A7269FEFD8BA779C232DF1E576BDFADB -:10A2B0004259738CF5043DC11BB3347E50FD53EFFE -:10A2C0003A476AF0359EF59AF8F9E87E93CE2FCE9C -:10A2D0006417E41757639F988FE00A903E40FD8013 -:10A2E0007A67E3EEA925884CB433309FA73F3991B4 -:10A2F000E4686BCEA563BC1A7886B2A47DA9C6B10A -:10A300001BFF7BF9FF51BB49D1D9AFD1FECDF45E24 -:10A31000E2A7DCF18F31F111F4F8EF213DE6F26FA5 -:10A32000C4A7117EA17B2F4FA3F30508BFE9D1FE7F -:10A3300006F01F07CF1D1E7F3BF6D720CED1283257 -:10A340008F6F205E61761EB647E13D54BC248A784B -:10A350001AD80D8F211D586D821F9983CE874BBB54 -:10A360008519EC1B3686FBB73764BDF7478CF76C55 -:10A370004CE12CBBF14709E4072E519C565C37D8C1 -:10A380001F9FFE1CEA0759E4D3BBC83F9476469250 -:10A390007A3669E8F394FEF2F9F2A9F7A13D06F3E3 -:10A3A000996172D0FEE63E585F36C88D1956FE2C74 -:10A3B0009F055405FDCD50F3BA7B615EDFB2338952 -:10A3C00057C0F3A78CC361CD81DFB9D01F9D61B6A3 -:10A3D0001CD3CA2D63BCE38DAC6437E151C43BBED2 -:10A3E00065737E7D31C2E57217C1A5F8959999DA3A -:10A3F00078CB40BC43AC635E682997A7063927E554 -:10A4000099C9CEEF11617EE6756650DC88C33DA424 -:10A41000303394AF90657452A07CB9409282ED6164 -:10A42000DD5788275B16CC423983693C381E787F1C -:10A4300059F86C9DEAF3E273BA1230F3798479DE4D -:10A44000216BCEC3FA267BAFCACFE7C10C32B0BDB9 -:10A450001C8F9793457943CDA91B6FF20E8E633005 -:10A460004732D9BD5631AFA34E47C804EF6D8EC8F1 -:10A4700051CA4F154F63BCE33B532884F9D977AADF -:10A48000619A6F128B447A303E61071098288EF0E3 -:10A4900007E403F06E1A719E09CE5391BB18E6399A -:10A4A000FA152CA71BF491C7B186F29E3D01B3416A -:10A4B0000F0515E49BCC5AE37BBD7EB2B343741EFB -:10A4C000488904B2CEA69F3F5E638CD35866701451 -:10A4D000F7DFC2EDDE8F13793B4917E9D95CFF3610 -:10A4E000BAAC8CF25D32EC76B4DB4F261FC12397F9 -:10A4F000A837DA506FD82D7E8287D41FABBB6E652C -:10A50000889FC65DD50CE5E86F14BEFF19BA41A15E -:10A510003C05796F436D117B1F5AB2A6EC1134CE06 -:10A52000FC7782373440B9E63D363E02F54AA6074D -:10A530002AF17E96D6F1CCB71ECAAD09C1675FC2BB -:10A54000F51C50A99F26712E963167FD4EE87FEBD2 -:10A5500075C37C9B704915FD1B310FA8FF3EE6C4F7 -:10A56000BC9141747A06D607F87F02CB30EFA6156E -:10A57000C15FDC01F5B3DF633EAA23BEA32F82785F -:10A5800053043DE0FBE9F0BE49D04D61B7C2F7EF9F -:10A59000DD36CA9F600733895FE6DBF9384DDDE5BC -:10A5A000D74E827915F64C24321E09F531BF093396 -:10A5B0000C787E1D237FD9587F24D6F752B48AE7C2 -:10A5C000D5E458E9FE2326E4DC6403BF5D16A57FCD -:10A5D000FA5E22CA4D421FE9F804FB01FFDC5FC6A8 -:10A5E000B7F3A99D9BF3838FC93FCEB797B2E81FFE -:10A5F000F65B111D87E4EF4CF16DFFA2D994D73DB6 -:10A60000D91CD98B7C7D9978968827F2B51DE0B846 -:10A61000D0DCBCDF03EB495BCB7C2D38CA626F2BEF -:10A62000F657CA022AC2B9CC795F2BCE6FEAE20391 -:10A63000E9485F4F6617123D5D6EF715260089B435 -:10A640004EF1F99CF0AA76B14270995F6B0F63FEF0 -:10A65000DAFC81FB7A82050B806F160615718E3E3F -:10A6600058B058138F95797D0B6CE047C7DA77CED9 -:10A67000E67A5CB66F12E74EE4F76DD90E9E5F99ED -:10A680007D655336E557F07C67E0FBDBB22745E597 -:10A69000088C4BF928F398DF82EB9A27F856F2FDE5 -:10A6A0007CFFED64B7CE0FE8EDCFDF281CDFA145BE -:10A6B0000AD9830B6BCF6D9FB664CBFDDE3C27C5FB -:10A6C000B799D4479CAEA4DC9E8B7A1CE56D15E847 -:10A6D0006D8D7DBCF8CE3369D42EF3C9D56787471D -:10A6E000CFB93419CEB9348A732E4DBB5A2C1948C0 -:10A6F000EFE29C4B53F7E71BB5F97D124E83CFB9C0 -:10A70000F4535EE3026B782F9EFF59B00AD608F52A -:10A71000DF10E722DEC4731113A274947C5D4284BF -:10A72000E7CDF9297F2FCF99E4C37C9336D304CAB0 -:10A73000176A4B49F669F37336B53457623D99276A -:10A7400024CFB52C88B31FFC9C906B5B149EAF1577 -:10A750005A6427787B5476507B4EDF5318A03CB95F -:10A76000A66C2F8DB345C41130AF74223CC3608EEC -:10A77000717CF1F646F900FD6DC0FE2A0A7D941F3A -:10A780005391CAF3CC3CE98192DB8AA2FDD674F3E3 -:10A79000BCBC9AC0D76FF1FCDAEA5284A7519E4B39 -:10A7A000FA32CA75A0BF7D488FDF99B8DE89CAF733 -:10A7B000C0A29BA0BFBEF7AD943FC7EEF62B1668B4 -:10A7C000F7E2BB4E1F9EA7DB501EA8AEA4EF663A71 -:10A7D000EF9751CB2236F85EFA9E751BE6EDD5B1A8 -:10A7E000762BF65767D05BAB1C6F5A913F576DB70E -:10A7F00044E99161BEA1AF10055DC3CE41710F92D6 -:10A800003F522E19E9988DD4CB9F12296F412E709B -:10A810007DB598EB39F6A482F19FBEE423AAF09FA0 -:10A8200049DE4D9242CA20E72775BF4DF6CA3490E3 -:10A830000FE89F29582EA6FA5406F93906F3472F38 -:10A840006389445F83EC0431AFD28179737B48CA5A -:10A85000C5F2298CE17D06122F300ED1B3DCAF9BFF -:10A8600084F7F0C0F33231EE9D267F5144413CB174 -:10A87000B0A910ED8820D93B46FBA7CCDE9C6487AD -:10A88000F54D61ED241727EF7F93E424E0F92CCAFE -:10A8900099D798C4B3CF8E72A61213FF547CEAF1F5 -:10A8A00034CBF19019E1342BCB888F9019E13ADB4E -:10A8B0003B084F744EC01F074F7E2947985E8E1489 -:10A8C000B033FC5CF27D6FDD817EEFF9EC900F3DE3 -:10A8D000C1AC1C929F7A7B245E5E5D418EE382F266 -:10A8E000EAFA2CDC4FB894F5AEDCA90CA68B93FBEE -:10A8F000D7AA591AFA9174B95BE4D92BAF8BBCDD96 -:10A90000D264D27351BDC8F15F264A97225D69F0C7 -:10A910007FC5AE84880AF45622DA5F8AF43021AA11 -:10A9200017232687D70AE36E547C6D6A0CBC67B880 -:10A93000BCA4FF269AFC2AD953CC978E7806BC4F2C -:10A9400043784DB177B49A619E87ADBE9FA3BF5245 -:10A95000CEBC84F772837EA970D498913F2BEC46CD -:10A96000FCFA09EF95CE41EF4DDF07EFC311EF522F -:10A970007F0CC1FE04BC2FCC89B15F180FEFC1EF73 -:10A98000897723BE25DF7726382B1C18D7ADE3F94E -:10A99000C413DF1FD98AE58CD50574CEA533CDF756 -:10A9A000067D6FE6DF4B7BFC2ADE9F58B806BE4370 -:10A9B000B9B3205081E5A6B50AC9CB491F055BB1E3 -:10A9C0003CF26EFEBD647DF31B780F595388B7DFF0 -:10A9D0007D7423DD2711DE28DA97B75760B9A98D7A -:10A9E000B7FF2AD91E42FFBAEC60B815DF8F7D8011 -:10A9F000CF43DA75D3059D752A2FBC41EDDA79BBBB -:10AA00009BDFB227927C1276DA34B1CEE98FF175F2 -:10AA1000BA7F7B559517E8F0A6FE9005E9E0B0A94E -:10AA2000A18CE4651C7FAB5C69CFC3E72C900B8CD9 -:10AA3000F00DF43982E79B6E83211ECBE17686CC44 -:10AA4000D3C47CF16A0DBE1ECBE17127592FC3C55B -:10AA5000785EF1A3C964B7CA3CD2C8CF98827100AE -:10AA60005C23E9D73879A5B30A9B495FCE1A2EF348 -:10AA7000497BCDCB60DC92B37FB832967FFD8418E2 -:10AA8000F788C87F97EFEBC20526F43F3A9178E844 -:10AA90001EB3DAF7D12EE94C63BA7B423A0B78B990 -:10AAA000F3D19A1FB7E5017C4DCDE6100AFD7C85F8 -:10AAB000EE3DB9A68745525306CF7F96994578DE7D -:10AAC000039FFFCA56EBB64D1A3B7DBE141B978FF2 -:10AAD000223D5223F024E5C57C812FE0EFDDC8DF65 -:10AAE0000BECCD64172E12F2FD1616A638C52D06F6 -:10AAF000FEAE777CF399C984F1303D1FAF86E970D3 -:10AB0000BDD0FFF82700FFBA47929DA8E75777E826 -:10AB1000EBD53DF2FE416E5FE9F9BC4EF27958CFBC -:10AB2000E76038703EFFD938DA7F91E7FA12ECFD22 -:10AB30009F855874BD03FADDC07F0978CE6F0CFA8B -:10AB40002D269E5F28CA72DC53ED5C0F87400F0BE9 -:10AB50003F8744EDA943B3C3480F25827F251F9744 -:10AB6000087D3E485F5719FD9887883F268A928462 -:10AB7000BBD4CFD00FE967796E10F4F2FB7EF2EF11 -:10AB8000C1FFC4798ED3F3CB2605E47341D45F01B2 -:10AB9000BC7D8D7803796CE7718A7686F22CAEDD08 -:10ABA000EF5813D3EE074947FB0083EDFD88CE8EA7 -:10ABB00037E22B9E5D3F80AF04B09792D08F67C481 -:10ABC0001FFF88CF21E475809C76E4C690D3D67DA4 -:10ABD000BC5EFFD6048A17C8F8B8E437258FDBD5EA -:10ABE000EF66F95DB9B8FF20FA3F74EB2CDAAFFEDF -:10ABF00086F969BF1AF38D7263E44BE07EF5064D6A -:10AC00009CF4505AECB8F5F05CCEEF4B72F9BAC632 -:10AC10007BFC5E1CEF8895C7C58F248A670ADF57C7 -:10AC2000B83897C7B9978867B9781E1179D8475C43 -:10AC3000FA78BAAC5721C6F9729DDDBE412357BCE4 -:10AC40003FB335A3BEF2148ABCF5359C5EFB5E496A -:10AC5000DBAABDAFED9ADCF22508474FA1DF9A8D44 -:10AC6000719657B85E6834F75A31BFE41A77702A84 -:10AC70007E6FF432FF0BD88FB7D73A0FE0DC27F6A0 -:10AC8000E9FB2CDCDFE84BE04F39AF6B72AB97E0B0 -:10AC90007AFB6EED25F93050AEEE25FEBF2637402B -:10ACA000E3F6CD97DF45F9C7BCCC847F582EF882F8 -:10ACB000E2BC31E2BA83E3B8FAFB679AACB1F7972A -:10ACC000595EB22E3E7B43378F1BDE68671B73E1F4 -:10ACD000FB92EE4CF21FEA5242A39D14C7FBEFC554 -:10ACE0005DFB86F5D0BA3695F7E73F5A4AFBB814B4 -:10ACF000F759DDFD36C9B9D5924FBAF47C522FF021 -:10AD00007BBEFD0F635C7C08FCB32616FFBC8CFA8F -:10AD1000C91285FF6D220FA9526DA8C0B8D0A91520 -:10AD20008CCEBFDEF6AE4AF474DBB30ADD0721ED4C -:10AD3000B3D502BEF1D683E707BC1AF981E707BC99 -:10AD40001AFF0CCF0F68CB787E405B1FCF0F68BF18 -:10AD5000E3F901ED773C3FA02D97B0E5AD18676BA7 -:10AD60006A63CEB0979F27D0B6C7F304DA329E2726 -:10AD7000D0B6C7F304DAF229C6E178EA3195E2F4F5 -:10AD800078AE40DBFEE677276621DD7425F03C32A5 -:10AD900016F2F714015C5608B8E079036D7FC753CB -:10ADA000AE7C8701DDADE85939079F97EC5AA5EBDA -:10ADB000AF5E6D203A64ED5CEE36C33F243FD52292 -:10ADC00015E7F1ED2E85A517E0FDE106FDD9BD796A -:10ADD000238A9E5BC2FAF7F54C13AF2D181C977FA0 -:10ADE0003957E421E6B01C6D9C264A070E5F04D754 -:10ADF000FF91EA8B450725ECA2548ACFBCA362ECF5 -:10AE0000817DC59AB75CAE68E2F70678D8B2F4F4F3 -:10AE100090E0D5D343D2183D3D24FBF4F4903A455D -:10AE20004F0F69FE71E7846F7A959E3E8CF09D020C -:10AE3000FF207C27E0CD9018578275629CF72F0584 -:10AE4000DF2F72C5BE8780EFB7ECF20A87973ED737 -:10AE5000D8CBA2F649E93BCDB4496B8C7B4A384A42 -:10AE60003B41C62F2731EEA7DBF1BC6521DA01DCBF -:10AE70007F43FD8F7C7ED8CAFD36A420949337B1E2 -:10AE800020C9A39B0CFAFF66C74356D4FF83D60B99 -:10AE90001617DE1B685C2FDA514C134F32EA7FA580 -:10AEA0005B892417E372BBA55C0E9E2563C7AF0CBC -:10AEB000455EFCDEE1B7E579681C662FD3C57B6390 -:10AEC000DA73721E122E727C1B6B56B3909EC718DB -:10AED000ED2FBDBF2CFD6BEA54138F96FEB1F44FDE -:10AEE0008C7056871790DD35D129FDE29EEBF1BDC0 -:10AEF000F4878D7EE8F9F6A5E68594DE9F1744ED8C -:10AF0000C92BC4739E8817C1B27EFB6FD0F872C57F -:10AF10003B0CC79BBBFB220FD2CB46A59919E6770A -:10AF2000F055E84735F5A7F3F84B50B75FF5B6D2C3 -:10AF30004BF35EC0FCF7E0B351C4D31ABBDEA67D71 -:10AF4000D4C62E1E2F60BBF47831DAFBAB5887B520 -:10AF500040196CEF37B01EEACF68DF0FA293F3E819 -:10AF6000F18E3C79DF16CF1760422ED50978C5F3F4 -:10AF70000BCC08E0A9D1FB3B811FE6E54D8AE6D169 -:10AF800066B8C08F51310FC36B8D9527C5F0721510 -:10AF9000B049973B6A484E2C6F1B1497B0123FB5CF -:10AFA0009F7B7DD20EB81F7C377C96E67979DC20BA -:10AFB00071CE3B7EFC5CDA93AF3DFFD164E5E70EDA -:10AFC00059B3FE7CFEDA3C933C3FA50E65FD83E160 -:10AFD000FAFDF2F265FE01C0EF2E2DFCE43E825C2C -:10AFE000CFEF27F53C89F1433579A61DFD5AAF2BEC -:10AFF000D882F5871DEC3DACA03C7378293FE4E492 -:10B00000AEA31FA3FF2ED7C758EF16BCDFB66E97AF -:10B010004AFE60DDAE37C82E8AEFEFB50FDCA32005 -:10B02000F6377E126B5E32AFB9522D4AEDD5D8E9B4 -:10B030004B851F307978E0216C57FA615E0ACED7D4 -:10B0400032A283EEC5EABF83DBC16E95CD44F881A1 -:10B05000DEE37ADF61A67D077752484D413B6E29DA -:10B06000E3F7D0F99A7D482AEAB0228AD366DCA1B8 -:10B0700006D0FEFE74CDF2343CAF9C91BC22AD10E4 -:10B080009ED36DFC5E9A0CC514E0E74E97A5E13D9A -:10B090002037D8F8BE7CC15F27450A81DF5EB7F252 -:10B0A000FB46DD4941BABFA03F4DA5F91C5B074BEC -:10B0B0001B85FB1EDF4CC47B0772CE3826E07CB2BA -:10B0C000C5BD163FCAE3F7DC1C7FF6BB89E8AFAA13 -:10B0D000671D74BE5DD29FBB30B6BFB242C0A3D164 -:10B0E000C3F3DE4F0AFBF190D86F9579F06BC43E45 -:10B0F000E0A1D103F78379302FA431C19FBA10E3C7 -:10B10000110754CA6BFFC6E94F4D23BB99E7B3AF94 -:10B1100011F6C34991F7B966F68C4CF42FE2E54B72 -:10B120001FC8E376EF0F755FA5CC3F8D0B873433D7 -:10B13000335F42F72E05CE55EFD53FAB31E1795A5B -:10B140007C8F9737DF97A7E8F2E21B312F1E5EADA9 -:10B1500079A53C939D235FBA11EF23D7E4D7A09F35 -:10B1600086EB6BC4FBC8E99ED213744F07F683F7D6 -:10B17000869DEFDEC815621E8D984F9EAE7DCFF97D -:10B1800039DABF9BBE3F2DE0F6F43BA6AA6D31E64F -:10B1900099378CCBA7711E7300F7252F8EF07B3F5C -:10B1A000E3D593E7B8E3CDAB6B46EF8D386FCCCFEB -:10B1B0008C355ECA304E2772BE5DAEDE9501BE9FF5 -:10B1C00037BA3A595376F6E7CFD5C8D7D9023F5D9B -:10B1D00057F5E6D37D00B3B9FF1A0FCF65E66605D4 -:10B1E000E190E00A06D11E91F715E37DC63CCF231E -:10B1F000744E7C47E1ACEACE1F0C86B395BECBFE05 -:10B20000A4DC39FA884A72E7E807821F99DFA19423 -:10B21000A1BEE27C7594F1B8EED176FEFB1FCB8225 -:10B22000A02B407E2CDD5E3F070F1FAFDC3171236A -:10B230008A7F7C7F37C89FA5598C4D83E7B20DFA72 -:10B24000FDB16FD903A4E7563C60D467012BCAD97E -:10B25000950FE9EBD7B107BE46FBA0CE60F76608B5 -:10B26000BD6BB47F670C13F66F192BBB90734E8FB9 -:10B2700030FFEC61A4FFF97EDB24B19F6EACFFBC14 -:10B2800097D3C36D3BFE60C59F048AD7EF319017FB -:10B2900023A1DF13EB9CF45C32CC5F330CDA350D69 -:10B2A0000B2EC471FA0E70389F6A38B592E2D2B58F -:10B2B000DC0EB0E1252BF09FB6EBEDE447DF8BF71A -:10B2C0008C019C6D366E5F48BB4A556F57F1275B0A -:10B2D000A6FE6E451AAECFFDCCAC2AF43F3CCF247F -:10B2E000F9111F9BCAFD2528BF37553B689F78ABD6 -:10B2F00089DF4368B7F1FDB9F0D353F7613878645B -:10B30000C7E619E86738BBF746302ED166E2FBAFD7 -:10B310006DD398B8C79A8FD7D45DDD89F3CAAF01D2 -:10B32000790FFD6D2AF0973835FD33612F350A5CB2 -:10B33000F4BD76D14FF1DEAB9FBF43E62AAC730478 -:10B34000C5BFC6314E3732BF847E1B43132F3A012F -:10B35000FA8769CE3F8FEB50229614BA5F8FE2D8FE -:10B360000DEB2319D7A3FEFC25DFAF95F373BF9E2A -:10B370003D03E3FD529F5E8FF96D18071676EF22AD -:10B3800026FFF87E41ADA0EB45C2DEBD3E89C37904 -:10B3900019F3D1F9ABEBEC2C05E3CBD757744CA2E6 -:10B3A000FBAFEB2D6968AFC8B8773CBCC78BCF3417 -:10B3B0003E99CCEFCB51FA476327C73006521ACDDE -:10B3C000B737F6B36398E0E7D1C24E1BC9FCB8CFDC -:10B3D000D2B8E722CAC7B725F27D35906F76C4EBA5 -:10B3E0007ED4E7B0EE5B5E4D88F07DE3B0B81787A2 -:10B3F00085683F664F26ED2BB80BFDB4EF7ED2D2A9 -:10B400009B4FF200E49702BA73CFB04FAE31E3FD29 -:10B410002039604741F9F82F0E5F83BFCFD238A2A1 -:10B420007725DE179EFEF8595E1ED77B18CBC31E0C -:10B430004FBC96CA137A57AA509EF278D6B5D41E3E -:10B440001D2820ACCAC7875F8BE7FC8E89F825F3DF -:10B45000F5D23D418DBB2F3269E38325F95C4E1F48 -:10B460004BE0F58E15B0257311DE637A476B7F379D -:10B47000C1932FED526E97C975CA762C2B76FFEFCC -:10B480000B3D708BB8DF677A126B4BE0FB1521B474 -:10B49000AFDEECBE88E0F2C2309780572FDDDB28AC -:10B4A000FB319EEF97E3AE42BD8D72DDA23F4FF4BC -:10B4B0001BA12F609C0D344E91BF04EFE5699C9B4E -:10B4C000578278037C9905BECCDC0FDC4A78C67EB7 -:10B4D000D38A498F4CC43CB137CF40FD82E8BC8D44 -:10B4E000F471588C734B2BDF67EA4F2B243A9A9EEA -:10B4F000C4ED3F560AF003393645C0AD245F9CE3E6 -:10B5000019C043A642FDB70AF8E5F1FA17BADED32F -:10B510003FD07A3578F263DEF19BBBC6129EA60C53 -:10B52000D0C1665D3FC75A0CEDA6F0BC94465721CA -:10B53000B5BB57DCB32FEF2DC67605D06E7A45FF2D -:10B5400044E407796F1B0B4D2367BD41488B817B1A -:10B55000D83A787E0A1BE9E7F711CD9D532AD6E742 -:10B5600014EB736AEFA51BE0C38FFAF36B34F75249 -:10B57000CBF703701FE8AF6882E84FC7CFB1FA433B -:10B58000BE88878F71F97F617CC8791AE0390067BE -:10B59000C3FC243C918FA95D919E9FE43C87E59B71 -:10B5A00084BF6DE0E782EF399EC8EF5FFD37221F51 -:10B5B000D2ABA7E7D55D0526DC3F95EDDA3A5A0216 -:10B5C00028E765BCDBD6551D42FDD7D45D4E799B7F -:10B5D000AB7FF5ECCB2168BFEAF987533099F6A829 -:10B5E000B93D03EDDC861DF7A4F871BFC41C4A41C8 -:10B5F000F97934AC56C53A0F181278907654A3D026 -:10B6000037C79EBEFF1A84C77FECB038518F363DD6 -:10B61000658BD8280E720BD95150FE9C97EFFD1AFE -:10B62000FDD2A65D7A3B69D53F3C9CE1257A0AE5CF -:10B630009AF08C0B8BE43278366EB7F8226E1E4F80 -:10B6400084615813EBDF88F333B6C7799C06BC37A7 -:10B6500075A84BF13CAFF13B4812B2C39ABAEE2742 -:10B66000BBAB491B67003CD4C5B1BB6ECDD7E75B14 -:10B670004BB8B0B087EC9AD65FFEACF87307DEA784 -:10B68000F94F294A91565FAE27389DEA58FEF7BB1D -:10B69000BDF1F5EA49B40B6CDA761CAFDE5D0AED5C -:10B6A00049B06EFE6CB04452D0CF6FD86AF181E6DB -:10B6B000650DCF3EF124EE87B04F6C74FF41FDB3B2 -:10B6C000FB3FBE14CAF59D16F71C3E7D879211C53F -:10B6D0004F9397DB27121FAB5EDC4FF70CE27BB476 -:10B6E0006B255EEA3BF75AD9F8C1F0ABE8D82B7E60 -:10B6F00077C1809F8ECFAFA4FB3C7FF99D15E9FAFF -:10B70000E81E8565160C6E5FB7757F0AD21FC209E9 -:10B71000FD4B89A701BC0DC257E49ADDA5548FE209 -:10B720001AF1F036379FF178D0AF9E7D0E7F07B0CB -:10B73000EE37361FAEBFEEB9DB53701D5F999B39F4 -:10B740007DFFE29E0C3F8C5B67096538E9C9DFD756 -:10B750003D7E07D1DDCD07EEC8E0BFA7E1CF364D76 -:10B76000A17566E3FA6E7A6C3EAD6F250B12DDD5DE -:10B77000FD82C727BE15BFC760C4E769C11F5F6DE3 -:10B78000B3E18F64B0AF30111DF3083F50459EEF19 -:10B79000AD4C7B8F0558DC54FE56C407DE1FD0032A -:10B7A000CCCE3471D9A6EDF7F6207E8E0DF367E28C -:10B7B000BE1AC02124E0A5E0FDBAEA81CA4C8E1F62 -:10B7C000E635CBB832D8DF15F81EEBF758FC09C5C3 -:10B7D000BA7662BF9E8F2FE31330EF44DCF7FB2A6B -:10B7E00023F6B9ADD1C31521DF580FD3D2573C7E14 -:10B7F000DF7E1FD1D5371F71BE690C5757D1F71E99 -:10B800004B048F163786F7D628240F6CBAFB9F0699 -:10B81000E862BB45F0B3FE3BCCD3AC68E1BB87E745 -:10B82000D5AE7CC8A6BB0F214A37D6E8FB82287F5D -:10B830004A3FEA66C1FFC6F51AE5C11F0CF2803D1A -:10B84000E619D2BD320D96F0938F22FF02BFA29F60 -:10B85000D9F0AC85FCFCE33BDFF8F83AA0F3E31D3C -:10B86000926FF572D5C8B7752F4C62B1F8F6B8C3B0 -:10B87000C762F22DBC8FC9B78EE83E8D97FD7072FE -:10B88000F5E63872356FB8F11C4B512AE6BA1F7BCA -:10B89000BA7E38C5050C7095FEAC515EBE9CEF8D2E -:10B8A000292F195E41A581A3849FA4C755CFACA6BB -:10B8B0007106E856D2A5A4DB01BA1C945FA983A344 -:10B8C000F1FB17288F2645F16E590F7E0ADAB1AFCA -:10B8D000A9F43B287D30978D00F7BE9D05B40F7A03 -:10B8E0008FB0F3FB9CFD2918D7BB47F815FD184F07 -:10B8F0004C8DBEEF4F10790381FE94348D5DF47949 -:10B90000B79A82765C6F38F6EFC9CA7B2A7BE3FC74 -:10B91000DEAC3CBF54A93AF2D7629CB69DEF4FAE65 -:10B9200068599882F18CBEEE42FA3DA19BDE057FFC -:10B9300017E6DB27E39A21BF39BB2C7ABFE9111642 -:10B94000A2FDCAE5DDF5B45F688C83AC74D4A4E2D3 -:10B950007EA0310E7233E641611EF263FAF7AB301E -:10B960003E827832D05310E9297B303DAD1C2EF653 -:10B970005F4B58896EFF55C8B54AB5E8A7689FF474 -:10B9800081DF8EF120A616FD1AF5E9B7E8C723037B -:10B99000843C44A7F5C12332CF8AE85AD29DD17F97 -:10B9A000373E4FBCF469199E076A78F9DF8A7F0E2B -:10B9B000CF132F7F32FA552CFFEA5FF3FF8D0DAEC8 -:10B9C0005FB1E78FE4AFF4EDB1D17CFAF6BC9D7FB7 -:10B9D000179677DB7C38DFBEF536FE7BD07B92E9AD -:10B9E000DEE9BE613CCED6FADA77C5BDA4A7361033 -:10B9F000DEFE6E38BF2FF654F77F7D86F7AB9EEAEA -:10BA0000B67931EED0B42789FCF0A6DD09744F7CFD -:10BA1000DF6BDF9569E345FFDDF5348AF3167DC9F9 -:10BA2000AC16F35BFAD2B8BFD6F4EAD4275A0AD0E0 -:10BA30002EDD4BF71657BCFEA762943F7D2F70BBDF -:10BA400002FCF3C77113F117C3BB7F6A998AE78DB4 -:10BA500018F9D553BD7FBA36E48805170E873E80A6 -:10BA600003AE0BE042F775C78347D7707E0FFFFF29 -:10BA70003E787C4DFE4243F764E2A3285C14FEFB53 -:10BA800023DDC961BB42EBE7EFF77C578C76D2F13F -:10BA90008E16D2FBE75BF787FF6BE9E0FBAE5B89B5 -:10BAA0000C65DDA7FED7AE9BD3FFDAE15C3F19F949 -:10BAB00060309DFFEAAFA9FC5CB28FE66BE0FFFF50 -:10BAC00007ABA359F3008000000000001F8B0800A3 -:10BAD00000000000000BCD3C0B7814D5B9FFECCC76 -:10BAE0003E926CC22604084260F2244A1E0B791072 -:10BAF0001EA99B842008E206A4A2222EF8E015923B -:10BB000008B6C66ACD622202F5B6516CAF6DD16F30 -:10BB10004141DADA6B8A41B1025D10115AAAAB8257 -:10BB2000A246BA52AB50031B41052ABDDEFFFFCF30 -:10BB30004CB233243CFCAEDFD7E423C733E7CC3927 -:10BB4000FFFB75CE18498599ADB9004DDB4EE587F1 -:10BB5000B1056806280648526D00FD004E6CFDFADE -:10BB600090944CAD5D853480BAED710045D8FE31BE -:10BB70002600124064DBA9129F13E01BFAB912A041 -:10BB8000A3119718D6DD37B71D9B3F2CB917A7D443 -:10BB9000BCF041FEAFB1ED78E1BDEC97A9FFE2BB8F -:10BBA000433EC0B6D606BE565C2F120F3337213C3B -:10BBB0009144F000EE5FF7F2E8A796E1FE8BDB3EE2 -:10BBC0009F4DFBD76C1D0532F62BFFF4EFFC30CDFB -:10BBD000DF2479C4F3F88003E1AADC7E463CDF7EF3 -:10BBE0002A1FB0FD6C93149413B0FF807D7E80D625 -:10BBF000ED05EF118477F17F22DE3B6CB7E278C36D -:10BC00005095E1EBC67B870DF208DFBDB3697E641A -:10BC10007BBCCB9E46F0FD7B0844E17F21BCBDFF91 -:10BC2000B1FC3E3FDE007E86DB2A7B1DE908DFC3D8 -:10BC3000100CA9D83E0830B1D5792E3C3FA6C16280 -:10BC40007A0F42D01F4006F123272F9C0209D4AE61 -:10BC5000FA5CCEA7F7A74D4C4338FCAAC5BD5EA53C -:10BC60001916A6C38AC1EEC02A840B14EFFCB5D8FE -:10BC7000B70EAD71AFE215EE042801F881435BAF5A -:10BC8000FF948912AED7B40CE1C2759AFA595C4D93 -:10BC9000B88EA25A82F67C6E3FA2F6A1FE57EFA1A3 -:10BCA0007D15A70D82DABBDFE03F27603F47EBE35E -:10BCB0007EB199517DFC17033B5D0AEE1FE35620D0 -:10BCC0008028D921EA7D9C7F93EA62BAC442C0EF02 -:10BCD000725E3A9D7E4F83FD7AA793993E3ADDCE00 -:10BCE000A1138083DE57E8BF08FFE45521D2430546 -:10BCF000147F58E0237D23113DDD290E5CCFDAE768 -:10BD00000EF72A899FAB4A89F69E85FE2C31D01703 -:10BD1000E9E789C9EFA673D47A8CBF99CE974A5FB9 -:10BD20009D2F31308DF91C33D8E90E20FC0FAA82EB -:10BD3000EE0F22DD25A99BBE3ADDCC7CF093EC14FE -:10BD400077D3BFBB1DE7FA64383312BE41E2FA2B4A -:10BD500020A71ED7A992C785FDB8FE89D238B79D06 -:10BD6000F44582A03412DBF2FE15807874A4DA1454 -:10BD70006ACB3A11A72878AF3CED00250ABF72487C -:10BD800034F43B52B3F9FD4AC740C37B1D034B1D3E -:10BD9000F4BCCA956698FF464C423E14D07B1326ED -:10BDA000D2F85529971BDE9B7AB863CD1C6CAF95F2 -:10BDB000C245241C1D7B675510BD26A9230CF3B674 -:10BDC000A059217DEEAC9203EB901ED552B07F3E80 -:10BDD000D26D72CE68237C128C273C6B2C285A388B -:10BDE000EF1A77B961FCDAD2498675AB3DD5867E0C -:10BDF0004DC357A0F40518DB70169442B4E3C15646 -:10BE0000C3FB857BB618E627EC03391EDB11FBD597 -:10BE1000266A0BDB434924BEB6BE0EBFA50F8A704F -:10BE2000D85B89E840C991FA57A86D70203DF0F9B8 -:10BE3000A918D122BF58CEFD8762024D08EF294BC9 -:10BE4000C04774B85B0EE4501B3BE88E7C48073853 -:10BE50009AF2B0DC87E0075FA78A7230FA8B401352 -:10BE6000F5AF3CDB2AFBC80E6F94FDB602E2FB94F3 -:10BE7000B8BF92DD6D9580F85EE3B47802E4B792C6 -:10BE80005AF39746C9D7673F845BBCB9E7EAEB8BA7 -:10BE900059E596345CBF39C5D3B283EC66C587B328 -:10BEA000E5F473E7814BE90CEB7449A7F7BC4583D4 -:10BEB000511EE5F8F10EB2EBB19532E30557590387 -:10BEC000EB719DE516778CA6FCEC5F5D13AC6B49BE -:10BED000AFD7A409FB10FB175025843FB6AF4FCE58 -:10BEE000A3F77E26C17AE8DEEFD652603CB2D22CB0 -:10BEF000420F1457BF9BF3E8FD787EBFA454D011C6 -:10BF0000A6580259B864C241F76E2BF657E7EC7792 -:10BF10009119689B72D82F235DDA0E86CA24D4A5A6 -:10BF2000010F979FCC14F3210BFB6D39E3E3F2D89B -:10BF30008FE558C8CE2C41B347766647D93339E4EC -:10BF400027965C7EC500E8C1BEE96DC26909D4C20E -:10BF5000EEFE9A3495E14A50C2407A9D705AE171E2 -:10BF600068C8B690FDD1D74F98A5BEBB94E0D86302 -:10BF7000852CDA5EF12C223C565DD1AEAE623C04DB -:10BF8000DE00E1142FA2FA4FF4932A315609A7DC00 -:10BF90001C7F2E1CFFDC589CA8221E7DCBDD896EE9 -:10BFA0006A7F8F441FC374F7131D7E4A7F2EA3DE62 -:10BFB000DAD0781CDF4836518C0701E57A954D1BA5 -:10BFC000279382FDBE9236EE5FEB1D4F7C958DF37D -:10BFD0000BD2BBE67B1C29DDEB7BD7AE0D35F748DA -:10BFE0004F3BFBE55513AC01BB7431748DBB005D59 -:10BFF00013045DCFA2F5C77DEE72887D3E96D421F5 -:10C00000246FAB2D68053200F6BB7CD7935CC7CAA2 -:10C01000C13C7A3E37C133A00CE5AFCDE619720FB3 -:10C02000D9956D31EE75F85EF59D9F3DDE407A3D08 -:10C03000F59F39CD24378A276E24EE53E7FA8AED2F -:10C0400041959CDB87E29D2E3A923CE39E3FB5747E -:10C05000F7C93E2474D3D59389E3ABA2E8EC709082 -:10C06000FD12FD47D3DABC4CA7DB1C4CA7A59A4EAA -:10C070003527428B05F5E1A46BC3F7491E4E6EB41C -:10C0800002C54D6D3448FE32C7C17A05C9E1946AD4 -:10C09000D483BC372D5E8ACBDA513E3C241FF5D9C0 -:10C0A00086F54E8E7B37290FDF3B99AC24117D1628 -:10C0B000866D4CB79B1508DAD15EB625DF5659CE92 -:10C0C000FAA1F278ABB6CE6B599EFBD2D8EF8C7743 -:10C0D0007D8278499E31F237C37BE71779D04F7460 -:10C0E000FB8874AE2334937A9783E6724780E2CC60 -:10C0F000BAD265B9E41F9624660F00C4A36EBCC40F -:10C10000FEB6AEE10BA6BBBEBE725A06B56F777F18 -:10C110007C86CAF640513C2C0FCA691B8FD7349CD1 -:10C12000643B8EE0A491DE742C13F6AEC50AB754BE -:10C13000635BF3BFF22DD538BF06430CF617B0D3BF -:10C14000B624CA1E42EBE75D76BF0079B77ACA5BB8 -:10C15000B16467AB25D70C401C8EA6BBAA95D1D87D -:10C160008F71CD90B0DFB6EE8C97FBA9AE1916ECAF -:10C17000EF4ABB498C0F74FDDCE206F87CDD5DA262 -:10C180009FE63A40FD0FD31EA95606623F5EC8C126 -:10C190006FD26AABFDB9245F4EA6CB891571AC1F77 -:10C1A000BDD1795EC3CB06BA9C332E4BB778C96E2E -:10C1B000CC1476F1D8CA416B391ECA0C65D39E5B8C -:10C1C000D344FCDA1F79538AFF5E45BD77201D9268 -:10C1D00033C063C1F9C92FA23FA2F91F878610FDA2 -:10C1E000E6BD181394901F8B9F78C546FE68AEACD1 -:10C1F00066935EBD3FCCB793E4E3787C88FBF31A8B -:10C20000B6335C29592E61A75D9DB95E94CFF9D0F4 -:10C2100062A3F1F9A01C26BF614161A6B866A173B3 -:10C22000978DE2B2854F5B0F87A3FCEA22081F229D -:10C230003DAD79D67A381CE57F81DE8F92AFC3168B -:10C240000187A2D163AE1C9A6D13701D20B816270A -:10C25000617C2F93BB08F5F7715C5493C379494A0D -:10C260002C90DC2DBFECFD7C5F0F7EB0B511FD3E48 -:10C27000AADCA6C62DDCAEC135C9EE0C50C23637DD -:10C28000AE53ABD9E592D0611B44BD7F42A36B9FF7 -:10C290002D128FEBF6A27B3C5ED025D733C2827085 -:10C2A0002C9EB66F1CF145E7E79571D01A93C47CBC -:10C2B000716B7C71135F74FA233D0B157C6FD7593A -:10C2C0007C2FAD27B9D0E92FE06D8B15F6A27373E3 -:10C2D0000CC74D66F8E3D205BC3A1E43D3CF0FFF1F -:10C2E000D0F4EF06FEA1E9428FCD78E87AAC3FD7D3 -:10C2F000F5D88CB70EF7A5CB59C8763172A6DB9965 -:10C300005AF0E5D0FABA5DD1E9ACC3A9D3AB8DF24E -:10C31000A11EE0541A5E32E0A3842A28898071E9C4 -:10C32000E9C28EB54E02E283D2B095E75D2A3EBAED -:10C33000BDED0D2FDDCE9AF1D3EDAD8EA76E7775E5 -:10C340007CCBD090B03DC4349EF2AC2B4FFB0C7133 -:10C3500070392C30C4C9958E3B0DFD2AD73D86F926 -:10C3600057A52C338C4F52571AC627E73C62E85F1B -:10C37000E3FEA5298E5F6B8AE37F63181F170E719A -:10C38000DCFD7AE344509047DF3BD2C9F177B0D16E -:10C39000C5FD9D8D29DCEE6A5459BF7737E670BB29 -:10C3A000A7D1CDCFFFDC58CAEDBE460FB7A1462FAF -:10C3B000B766BB30F5F9EB15CA574A432D9564CAE9 -:10C3C0007764F87E928EF47BC312688A473A8D6A4E -:10C3D00017F139CC37FBE35387EE25BFEEB2B9C96D -:10C3E0001F36EF182DA93DC47309E8EF3C51F292B6 -:10C3F00030250C1E8A7BD03DF7245F2DE916964729 -:10C4000032FB807A37D301D664D4B79933257713BA -:10C41000F0733F24711BF4E1F85405FCE4FFAB9D7D -:10C420004AD09EC0A0791D08E70C0126D8699CFC63 -:10C4300077725F85E2D6EBE821C22B7B64F81E3E63 -:10C440009F51FA97339437DFE86CB5929CDCB0E7E4 -:10C450008163F7E23834FB8B493FBAE206FFFB9673 -:10C460004B891B5A28AE443A462477C843F14EA262 -:10C47000E28ECE07F4F6B674910F4C6DF2CB0948FC -:10C48000CFCE3781E3385D1F11BF1504BFAE17D57E -:10C490002E25382C81FCFD239534BF66BFCA74D18C -:10C4A000F542D7033D0FD4F5A04A7EB689E69F3802 -:10C4B000089C4F8FEAF01D799EF034C59DA59D2DF7 -:10C4C0009594975D286F1C73BAF5159AB7BDD1C7BF -:10C4D00072B4B57126B7C1C6F99A7CD6737F57631B -:10C4E00003F77737FAB9DDD3B84293CF161EDFD7FB -:10C4F000F838F75F6F0C6872BA919F8FCF10FEF714 -:10C500008B50E50092BF17D3451D071CE59C478063 -:10C5100022DA8B95939A9497453C65920FB35CE829 -:10C52000F200683724A4D78DE867C93FDC04FEBC5D -:10C5300039D8CE9CD7621D2B7D7BB958E86CE6F8C4 -:10C54000C36C0F174090EDDDB9F65DC4FF17B2EF75 -:10C5500032E6ABE4AF74FBB718C2BC9E5DBED34DF0 -:10C56000F594EFCEAFB834BF0273687E57DE1DDBA3 -:10C570003E5BB65C38EF2E1A2CF8AAE7DD183F02B6 -:10C58000F9E54840E6B87A7E5A4B02E7DDA59D09F9 -:10C5900014072CD826333F30CF540622DFE6697CBF -:10C5A000EB80E03BC49779E3E6715D6EFE1A233EB3 -:10C5B0000B9DD7F509AA3DC6693DE2590B0F7F4E89 -:10C5C000F5B95A8D5EFC1CE16968BF61D2AEA879ED -:10C5D0003119F1C99FC49142C128A207C2EF0E923E -:10C5E0009EED9759CF7A938BE3989F909C9F6A9C7E -:10C5F000396917CAFDF1B38D9C7F25653CF2887FB0 -:10C60000DC77C7AFB559DEA1199C0F856DA43F3A01 -:10C61000FF96938D44B8975738029468478A5D0A0D -:10C62000ED1F913C723CF1E323702F43FA956F7D2F -:10C63000ED20E947B9C3C9E708884447343F47EFCD -:10C64000F7353971DEA87D1E99C2F7E25DE1269AC1 -:10C65000A6FB1BDDFF8CEDE8947D5C17C8643D02F2 -:10C66000CC25BEC9B8783D32E79B4D946FA2413AC4 -:10C67000E99CC0F09E0C829B9E77D7B544BD69ECC7 -:10C68000598F9C80F02DD7F2C3D11F7B198E6A87FA -:10C69000CA7268D7F2497B8A053C517474D97C1BF5 -:10C6A000A9FE097F8CE13AAF19BEC919C28EAB4908 -:10C6B000DEC94C5FA79A4D794395DCB1E1D7240FD1 -:10C6C0006D716E3BBE67B6B7BA7DEB2D6EAF739DD5 -:10C6D000EC318ED4DB3A8B38371859A91652FE4705 -:10C6E000F125E5857A9E689EEFCBAA989DD18FEBC8 -:10C6F000AB210FC1E5B29C574EEB1A3E3F6F9EA691 -:10C70000EF5FB7ADD83537AA0EB226433F5F505C16 -:10C710009F38BAF976B1FC2DEB9C69F03FFFE9F147 -:10C72000DA540C7324D4A13C2920E20810F1C42C63 -:10C7300008713B1B3AB9F5A124513B17DCDCDE063E -:10C740005E6EBFCEF4AD26B989583BFB931E1F7BAE -:10C75000E1EB5C928B63DF1BEB4A53BBFDABEE6FEF -:10C760002FD5AFC6D2F9520FF2B041935BDD6EF711 -:10C77000CA1F93DD8E8C40FB807046368B73B148A8 -:10C780007C6C80CE0174FB007E63BCA8DB8BC2593D -:10C79000EE37B85EB84FE6BAA5D97E5429228F0786 -:10C7A000C59D43F5517DFF260BCC2739DB88ED1F56 -:10C7B000108F3EB3C28A1A85CF760D8FF21BC60347 -:10C7C000E52F535D223F9CEA80E4D364DBCE9ECC10 -:10C7D0009D8186602AC5A328CFA3923C7F227AFB45 -:10C7E0001F1A97C8E70F647F8622FF3E12E736B014 -:10C7F000400A64213DB6B4897EDEED898CDF4D10A0 -:10C80000643EDE0C612BE17F0B00DBDD39A0727B27 -:10C810002B78989FB8725C3EDAA1DBDB9491AB1069 -:10C82000CF82A4CE74D2CFBCD1EF254908573EC5E4 -:10C83000BF4EAECDACA03845C7C39229F0B82CD3BB -:10C84000F336C15790145AB59AE2C2CD16A0B8F08B -:10C85000D3D1F7DC01517EB524ABE220CD7B4E1263 -:10C86000E785FE6D76515783CEFEDEA878FCEBCCD3 -:10C87000CA43A4F7FF20D838FF5DC5E748D52E414D -:10C880007B18DF8F6980EF0DF1E6F5A49F7EB68FF0 -:10C8900005444B5127F44329EFCBFDAF9EFAA2BAD2 -:10C8A00059E0E3A778AC24CB17A1FD0A6C680A090C -:10C8B000FE27EC81751C37D50FA1FAC5BC27ED16F4 -:10C8C000F2E3EFA11DA673D30F1A1DDC7E88F90DCC -:10C8D000B57FC3FC86DA8F30BFA1F6EF98DF507BBF -:10C8E000FBE9112844003FCCF4FC6FC679F0E8DD89 -:10C8F000CE083C2212CCECE9BCEF5486C83FF2DBF8 -:10C900003E7E208EE4608BEC2639CDDBAC701DE2E0 -:10C91000F8D65101392D9AAEBEB84C84237FCBDBBB -:10C920008F8E2DA2F7149784F38F6F39D99FF3263A -:10C93000137C5DF4D86613F4D0E07D2E31B48ADE2A -:10C940007F6E733A41887604841C123F7BA8A30152 -:10C950002C633EBE9E21E2A76BED9D45D1E79B4037 -:10C960002103D52B353F53259F4D08E76A75DBD151 -:10C9700024D7996FD07EFE3D420F91AF86BA44A571 -:10C9800026877A9BB7CDE6257D7A6EDB3BD32623BF -:10C990001DA68E99542CABDDF30B33FBF1BE79A3AE -:10C9A000CFFC6A7532CFE7738B1B606D950BE7DDAB -:10C9B000E4D8F12A91E066D7475589D8BF2545DAF2 -:10C9C0004DED1C356D4212D90108F03EB7E694EFEB -:10C9D00026119BE2AEB6915F2E27A58AB2BB958E3B -:10C9E000383A49EDEA57B9FA1AFA57A50C32CC9FF2 -:10C9F000A46618C627E70C378CEBFB4E71171AE6B6 -:10CA000091BE52DC8C7830DF61BDCCE732799BBFC0 -:10CA1000787F11E37F4311E11F41FAD930B03852DA -:10CA2000BAF217ABC96C6CDE99C0E7B4A6F8B4666D -:10CA3000DB53BB3D6AEFF1E997B0B5C7B8AEB69727 -:10CA4000B8EE62E353B41F8F92FD2878E13A3E7747 -:10CA50007F6EF499CB54C4CB9789712BD93D53DCAD -:10CA60001AD1E256B3FC74C9A9A40AB9D92B03C5DB -:10CA7000417AFC6A961F800734FF2FDA4BD5F3A961 -:10CA80006F097FF50FD2F7BED172ADB5A67A44819A -:10CA90000DFD0AD509FF2AC33A7A7016E1D0E99F45 -:10CAA000D12DF770DBDA570716F1737F3C6E59AB67 -:10CAB000D5277E95A99DF3D7EC78756072F738DCA1 -:10CAC000F591613EDC27ED36F49BD38CFD87CB7767 -:10CAD00047BFDF9B1D9AB7E64E9B8FEAD28F893AFC -:10CAE000A5795C87A76A678C87ECA5B2D5CEF9508B -:10CAF000ADCBC3F513A597FA896E176E90A1BE272B -:10CB0000FBB65E5B77CACE1890BFC5BAEFA1AC107A -:10CB10003CFE17859F79AF8F07BC51FBB4668AB87E -:10CB2000EF5862CB8FBFC279C75E023791FE58A221 -:10CB3000B0B7F96D9F5A2CE4276285BCE4BBC2965E -:10CB400024BAEF323FCE4FE7C9750BE2FD746E5445 -:10CB500090DEF98E0359BFE569DFA30E94BBF72D74 -:10CB60001683DF8990ADC3FE8E4CDF34F23B9377A2 -:10CB7000C6042DDF029F1D9920FC5A85D0F7D924C9 -:10CB800037FAB9189A9ABA07C1704E46F853FFCCD3 -:10CB9000D3B7BEF518C5BD7B85FEE3B0D39C8FDE51 -:10CBA00014958FC21AA1BF0EFCA53867E1AE161B03 -:10CBB000E549DF95DEB7673ABBF57BD8B9FAACEB50 -:10CBC0007BDD01A1EF27B67EF916D9F513E8EFA2B8 -:10CBD000F5BDCB2F6A7A5EF7B8CCFAA83F3FBE55B9 -:10CBE0009E18E881BEAF697200AE6CC3B9D992B22B -:10CBF00053D3C8AF2DD9A6F079606FFEBA6E85F118 -:10CC00009CECB9EDF6F9E21C59E011D1FDE9B62F23 -:10CC100093CA7345BB8CCF6B5B34BB23E218F4A380 -:10CC2000D664F2A3D512D7DF0E6C1BC0F7330E48C3 -:10CC3000105447F212D739906FD3C572F4DC49F122 -:10CC400018A4E428B4CF348D9FD3B5BAD08C6D33FB -:10CC5000B2885FEFB4CD3DE021F4B232587EAE072A -:10CC60003FC7830712BDA9744F616A9390EF038990 -:10CC70009D1D54473A501627D17914AEDF1C1DEF85 -:10CC80001DB07A53EB192FFD7CF20AF99BB84BC803 -:10CC900083357B88FCF44B229F63F957063ECC72A8 -:10CCA000B50002BB3DB86FAD3BC871E9221079BD3C -:10CCB000399EAF1DF7998DFC8239FF2CDFB2E3203E -:10CCC0009D7B9C538730C9EB85EA0EE6BCB7B7FA6B -:10CCD000C1A8246F615654DDCF1C9F77C5A17A1C73 -:10CCE000B53E8ECF855E29FBEFE38BB07FD7FA3858 -:10CCF00017E5D9479FB4FBC92E1F5D670F48387EE3 -:10CD000034A9B39DF28EA39BF2DCB802CCB3A8BFCA -:10CD10007B96FCFA6FAD2C1700C67B0D4BCAEEE676 -:10CD2000FB7F4BD6C74B740F0752C4B89EF3C9CFD5 -:10CD3000C4735CB0E0F9817CCEA9FB17D20F3A979F -:10CD40003EF2448C8782FCA37BA6F7A17A5F87E53D -:10CD50000F7C9E0FF27D87E8BC7ED186F891143F50 -:10CD6000402E30DFE6AFBB9CCF377FAEF86610FEBB -:10CD700095CF5C3380EE952D78BB1F103E91ADCFE3 -:10CD8000F3F95F779CDE737C77626B461FC8EDA674 -:10CD9000935E075CF1F4322FF1BD5852C5390DD4C2 -:10CDA0007B06915C6CA9065A77A42CEE8D76AE8C2E -:10CDB000E3B8D42C773559220EACD1EB0D7DC1915F -:10CDC00042FAE303A64364E5F075741ED69C95A46D -:10CDD000F9E9CEEC6951F712ABE4F6DA97493ED7A0 -:10CDE000D8B90ED211D3F33958435622CF9FE7302A -:10CDF0009E9BD7369C31F67331BFC3F74736A98562 -:10CE00007762BB54A3FFEA54EFBD59F8FEC2D64780 -:10CE10005ED8C77459F3C3F769DF3D4E517FD927F8 -:10CE2000E8678EFFE739449D03602DEFAF3FFFF4C5 -:10CE30008977F97CF5D3CDC3B3C5B971E8935FA702 -:10CE4000F179F1A17BB1DDB4E72DE68B19DE73CE6C -:10CE5000FD2489F1AD213CFAD2F9AEF71182131904 -:10CE6000C179DBDC55794C3FFDFC2D72B4E7FC4405 -:10CE700087535F5F874F5F5F9FF76496C863666BFA -:10CE8000F9C1315BE8389FA3BF305CA2FA5ED7F3EB -:10CE9000A4507E6294BC7C57F5F41BB57AC841CB94 -:10CEA000B21FD8E89E5CEB6AAB2FDAEE5D621DBD67 -:10CEB0002B0EF480EAEA2F5C09FB2D444EE94FE784 -:10CEC0007D5A9F9401FBE334F0248287EE0D6A2D96 -:10CED0002CF4A5709D9CD693E91A6280FB4DE56EFB -:10CEE00095DA2B25AF22EE7D0558FE2740FD60C266 -:10CEF000C3E208F3B9987ECF6546E2F26BD270BF09 -:10CF0000E67EB09CE29866ABD00BFF9C38CEDF7417 -:10CF10003AE97E065CB906FFD2EC0255C175662A75 -:10CF2000B0C29A24E60D453A1FD833F7558A13DE6E -:10CF300055EAFBD1BEEF391FCB932C14DF05E22954 -:10CF4000477CFFADDF16FF15E77E009E3227CACF74 -:10CF500075AF39D8EE9BEB11B7838FFBF3206CFDD7 -:10CF600002DFFBDBE87FADDF09DD78FD6DCC579B91 -:10CF7000293FB829F181627A5FBF8769BEEF77D414 -:10CF8000E5E47B81E67B7FD782EF33B25BA72CBEE3 -:10CF90005A51FFA81F45FE3792680309E747FA690F -:10CFA000F438064C8F88557BFF7395FB459523B964 -:10CFB0001E09A754B6C7634DFEA668B845E461DFF5 -:10CFC00088F9659D8AC1DF141568759BAF558E4B36 -:10CFD000AF3CAD9CD71F3D942DEC59515F4B7D4F1D -:10CFE000F1A19A2DF4A70982B2C047C40963BBE43A -:10CFF000CA2313FF6AB57E2DF93394A74882C34F25 -:10D00000171DC76E15F2355609EEA016AD2B34501C -:10D010005CB105FD9D0E079D11A60C673918A3CBC9 -:10D0200027AE350BE72D97EA396F71503C83ED2A17 -:10D0300029C4707C0F3AB9F5687EBC02DCDC8E072F -:10D040002FB7289FDC4E84166EAF86566EA74048D9 -:10D05000F8FD2B824DECCFE03E179F5B4C9A67A109 -:10D0600078A3E8FA9EF3850A8D4EBDD30115AEE490 -:10D07000D2E9300150EF327AA0C7E01CB61F667AC1 -:10D0800098F5B30CC232EB2719860CAA13A8ACA7EB -:10D0900095E0E17ED545D2A134EC53B84E63A64766 -:10D0A00065CF723159A3C7BFB281E543E7D3FDD93C -:10D0B0002A3FD7F9857A9542F26FE6A3FEBC28AEE7 -:10D0C000E2245D4DBF237BF874BA57555458B19490 -:10D0D0004CF2DD1BC64CA77B5545632B9EA723CF87 -:10D0E0007BB2C7897E4145A1D58D598B54367D3C95 -:10D0F000CEF769F79261A688AFEFD2E216DFB21FD2 -:10D10000B85DA827BE54A79BF07360704FF759E431 -:10D110000C713E38646270A715E71D527C73B2290A -:10D120003E70041354A4FB5DCBAAF8DEDA4336311B -:10D13000DF6E1775581D2F7CEE8FC1FEA64DC3976D -:10D140004AE9BDEF8FEBD6D2BABE65597ED257DF22 -:10D1500066C92D3859316026EA6747C80A540FD589 -:10D16000F7C94EF52DCDE673DD6CAE930DD2E29985 -:10D170008E4DC387135FEECFD6EE6125A71512DD66 -:10D1800096A57AEFA7F99178215FF76B7CE8ADDD82 -:10D1900090EDB92FBBF8DCE7917F2000F8FECFB20D -:10D1A0007D0FD07A757167D9BF1F1FF1F6F2705AE3 -:10D1B000B79C4AC8A459887793070236F603DA7DEC -:10D1C00075EDBC2A723BAE837428F2FA9AC8A48D1E -:10D1D0009AD55942F613D7FD2F5ED7161E3202DFBD -:10D1E0007B6CFA219B90B3C142CE343BB46DFBDE25 -:10D1F0007B0789AE17A2F4AA6EFB99AF3E40FAD521 -:10D200009D70BA697AB73EFD7229E793E034D80D74 -:10D210005DCFC66CB1735C3D76EBE5B7D3BCB2B7FE -:10D22000DB3308AF2BDBC37C0E16D9F6EE2001876B -:10D230009E6F9C92BE8DDFA5735ACEE3368B73DA58 -:10D240002552FD2BF1D4FFBDE4F623FC9F6A7E43FB -:10D25000CF8BE76B782DDEBB7E39D545E6AFB97550 -:10D260000ADFE30988BC41C55FD2FF2F611F9F8F92 -:10D270002FDA68CE273A6DC4FFC5ADA6FB40940FE8 -:10D28000D3BD8768FBDE433EBC3D5B3BA74D855469 -:10D29000C6439ED5C7D783BD33E7BB8F83E755967B -:10D2A0004FF0CAB47FB1D2733DE1B9EEEF69581FB8 -:10D2B000E6697B139D9C9CEFDAC47DE12796BA5DFD -:10D2C000D4D7F4732DCA4A29C5D19DBF64F9D7DFDD -:10D2D000D3F575C10A712F1BD6F465992BD860F769 -:10D2E000105F0B360CE0FC02F3208EFBD66EB0AF65 -:10D2F000A07ED383B17EB980EAC99D97515DA529EF -:10D30000467CE744EE91EE8916A48B3AC719DDAE50 -:10D310006B7E5DBF6FDB95FFC467F3BDE6AEF1B01A -:10D3200062C8379AB4F8B988E0A338B0DE2AF2A709 -:10D330001801FF8E37BF1F4771EC66C51B4775E9A3 -:10D3400013FBD3FB400F74D3DB62742F709E73C644 -:10D35000E277A7649C8F5F458F6BF7D335F9FC6349 -:10D36000A307FE6EEDE6878E5795FC6CA58DEA1C33 -:10D37000B7818BEA1E4BF63ED544DFDB2C59095CA6 -:10D380005138417F285F3862E173F0317B0B53489D -:10D390001EDB347B47E7C26A945C95505108E7175F -:10D3A0000F86007D7F14A3C6821A9517C7E524193E -:10D3B000FAF1EECB0CEFF7294D378C83DF13CA2D32 -:10D3C000E98E5F133D5718E63F943081BFC7290BA4 -:10D3D000DDC175A5BE13471AC6ED28D774CF01BEAF -:10D3E00010F14F29FEB25F857A99E01C1B06F815F3 -:10D3F000CADD980E637C541A6EE13C3066BF62C889 -:10D40000EBED17A8335D3E4CD3ABC13058D8073392 -:10D41000BD8DF72196EC95398E5B928A81675AEF24 -:10D42000F4D6F54FA77B3FAF91EE03661AE93CD0E7 -:10D4300067A4F3A0F9463AA7D61BE93CB4C148D784 -:10D4400034BF918E192BC618E667B55418FAC31E5F -:10D45000BFDA30FFF2C034437FF8C61B0DF3F35A36 -:10D46000E71AC60BB62C3C2FDF47049718C6CD7CB5 -:10D470002FDCF323931C2A4CE762EDFB2C9DFF7EEF -:10D48000FC25FE8F056F9FA044E5407F13E9E3FF75 -:10D4900017FF170CD3CE1174FE5FA45DBD4AF3C312 -:10D4A000E6EFBCA6C6097BF3FA9E13FB3DD87F438B -:10D4B0002DB4A650DCA4C5075EFD3CC294F7E97903 -:10D4C000CAB5A592E99C3EC6704E7FA17B6DC5A1F1 -:10D4D000A0A13F62BFF83E6AE441F72BD4167FEC6F -:10D4E00091A3BF871AFD05BBE573F24EFD7E9C9E9E -:10D4F0003741F3939C87CED2E127252839B7BEA8C0 -:10D50000E7A7E6BC55CF57CFFDDE4AC42577CBBD94 -:10D51000E5B1227FD5F3D6EF8387BF2BBB6AB06F0F -:10D52000ED30B4FFB2A5B32F8DEBF92C1196CE8D53 -:10D53000234458FE6EE69DE99E5CFE1E95EBDE0BD5 -:10D54000A5B7A7D33D7F04DF152E11E51FFA796932 -:10D5500098EF77B4DE61C9B5BC10DF7D7DCC674341 -:10D5600068BDFF1926E237BB8C1442FF3360960773 -:10D57000E8F9A824CF7334DF7C3FDBDC9AEF0DB5EC -:10D580003506B9555C6EBEB763AE0F862D2AC79DB2 -:10D59000FE1F497C4FE733026E7477BC726285953B -:10D5A000E315D0F2F19B35FAEB758B591A3E877172 -:10D5B00089F9E87F6FDEF21AF365514A8756EFA8C2 -:10D5C000E7F8FAD6C1CE917C0FCD53E816752EBD83 -:10D5D0008E31E892BE2FB910FE8B528E1AEA48F0B7 -:10D5E0006CDF8B3ADFEEC65BAC7F78A5A8471E5E8A -:10D5F00099CAF5EFEEF58F733DE9E6FA370D7A71CA -:10D600004BC37B063D98E3FFC8301E4EEEB452FD7F -:10D6100030FCC2C0093721FD8E6DB6F3F7D0280764 -:10D620001DC4577DFDF0CAE1E3F9BBCA0BE2F9194D -:10D63000C3D1DE1862FEEA781E6A3CC8FD706398AA -:10D640005B339E7A9D426F6D3B2187EEE7774AB14F -:10D650006EAA0B9BEB17775BD44F480F1ECA49D7B6 -:10D66000E2B5FA022FF34FD42BDAB5EF4BDBB5EF6F -:10D670004BDBB5EF45DBB5EF43DBB5EF402356E7BA -:10D680000AAA6BB44BE2DECF2CC9F3E41CDC2F6D8D -:10D69000B0CF994371FFC2CE7C05F7A92B08CF9676 -:10D6A00090CF79FD7C7DE8B984E9C240FE9EC8CF69 -:10D6B000F7C38E58FCF9F4FDCDE48D59D7511E788F -:10D6C00024D67F9C2291CA9CB4EB28EF3B62137A4C -:10D6D000387D63EC75A4771FE362849FFF2549D4EE -:10D6E000959C611B7D3F3535D93728A758DCFBE277 -:10D6F000EF66F039C9A55EE78C58451C18D1E2C128 -:10D70000F41C710E989123E256BD2D239EE3F3E99C -:10D71000D4B27E3E9CCDDF9BACB103C5AFB83F7F9A -:10D720005FA3DF33317F7F33F24F76FE4E42AF8708 -:10D7300096E4A4F13AF45D0EE965F24FE2D86E4149 -:10D74000383484BEE3E98277BFF8AEF218D591A3EE -:10D75000EACF2539A20E03B781E13BA0C57B0F1F9D -:10D76000A23CEBFD61BE3144D7B916B584F8BA3896 -:10D770006107D7BBA6E4A8BC2FC2CBF8A2FD6926DF -:10D780003E2D7684B93E76A17A786FF81FBB3DF4C2 -:10D790008B5CAEFFAAF9FC1D9EB62FC23185E8AFA7 -:10D7A000E3ADC3D1BDCEF9E55FAFEBEAFD4F9F78A6 -:10D7B000285BABCBDFE2EDC19FDEAAD1A5DDDA733A -:10D7C0001DFD7E8DBFE7F0671800D5EDEDB1E823B4 -:10D7D000B0ADD7E874EC06C487EB139E11C4DFC567 -:10D7E000D39CFCFDB9BE3EAEE3FBC379F6599DEA7E -:10D7F0005D48F82FAC1775777D3C2209BEFA578A31 -:10D800003AE8E2EDEF1DA2FF0FC28267F20A39BFCC -:10D81000D7DE37D319E9CBDF45CD95C5B915D2F79A -:10D820006EE2B3B9DEFE6DE91A4915E7AB91B56753 -:10D8300086D03DB2C5746F8DBE0FD3EA57D066ACAB -:10D840004B21BDFC54AF38F73C0AF85CCBAEF91164 -:10D85000BBFEFE60C5F0FE31A7F7A7449F1734BB9F -:10D8600081F30316DCBF4DCF934D7594B690A87726 -:10D87000B6A5D8384EA67887FC931EEFDCF5A6A88F -:10D8800077DE9526E268828FF82B1DDCCD714297FA -:10D89000FF97DC2AD1CF69F505687FF02D65FF255C -:10D8A0000F45FED2F9C59FAFD6EA01C21F166BFE27 -:10D8B000AF98D6A10027B70FFBC5226D5F8C1FB9AB -:10D8C000EE361A7C4D0218AD6EB672B7A18EF07F9F -:10D8D000947817F25045000000000000000000009E -:10D8E0001F8B080000000000000BFB51CFC0F003AD -:10D8F0000917B1A1F26FA0F1533951F9BF5951F98C -:10D9000097D0F884B02E1303C30A46D2F420E39DC7 -:10D9100040FD0780F838109F6322DF1C103E2CCC9E -:10D92000C0F04D8C81610E906E03D2E781F83B1000 -:10D93000DF05F2C5441818548178A12803430C90E0 -:10D940005E0EC44522107D4780749D2879766AF268 -:10D9500050E6E6514C195E2D8DCA2F5701A647554A -:10D960000686B76A10FE622479267506860A1508AF -:10D97000DB408E81A10BA866B63476730D81F2DD93 -:10D9800040792175081F00B5882CEC680300000061 -:10D9900000000000000000001F8B080000000000D5 -:10D9A000000BCD7D097855D5B5F03EC39D879C24ED -:10D9B000377033C9490C1835C04D0C838878120371 -:10D9C000064DF106D1C6FEB45ED0DA481922F26ADD -:10D9D000B4B6B94012C2A441B4A568E98D554B79DB -:10D9E000B646C53EDAA7F482F8446B6BB4D4E1695D -:10D9F000FF469EB5D65FF9E280536DF9D75A7B9FFB -:10DA0000E49C939B04B5EF7D0F87C33E670F6BAF1C -:10DA1000BDE6BDF6BE6ED9C5D804C64EE09FF3186C -:10DA2000BB5A628CE50D3D9937D6C4228C356B6E9E -:10DA30007D530963DF546287F56A783F5E8EDDA30C -:10DA4000E3FB49752CCC9882F5F3198BE1FFA0DD3F -:10DA5000FAE0BA718920BC531667E1D3ECDF7C365B -:10DA6000AB8C6955F87DCBA44CDFCD274BB906FABA -:10DA7000BD8CFE9C2865ACF59597261F32CBF05FD8 -:10DA8000010B455E0FC05F66B0192714C6DE0D2E70 -:10DA9000CC4AB391FB7BB3ADFB4C7522631FB6BD83 -:10DAA00038F9D0C4E1DFBFA9B096DE8AE1EF673074 -:10DAB00018741AE223E98E4F1E9AF7E03C8380A483 -:10DAC000B3A13D63694F0E3C776F3B532D1F82D34B -:10DAD000390FC6921CBF9FB39D27529B2E8052A523 -:10DAE00094984D70A9F0CF74C6A82AACCBB2DD8D46 -:10DAF0008CE072C0DB11F9E7C03BE27A897AEF066D -:10DB0000D7753268B7DEC5E9A53D4F8EAD63C3E971 -:10DB1000C55C0F138F27BB1E37301F8D63D251B3E7 -:10DB2000BC78D4751F8B8EAE443A3AF3BF9F8E9269 -:10DB3000FF7BE9A883FAF95F46478C75737CB17E59 -:10DB400015C71F7ACF9F91C5BD12D21914FB10EED5 -:10DB5000623E142B6EEDBC569E02628AC59E3C0D41 -:10DB6000E45671FF9206847BFC2BF3FF8ACFCE45EF -:10DB7000B5F573617EF94DBDCF5E00CF483C2525DC -:10DB800060BDB63319850AF4B73C5903F36BC7CEB1 -:10DB90006631766F728991C4F93283B1718CFD8BD5 -:10DBA000981363B2AE4239447FCD340F374B737C48 -:10DBB00048273CC3DB8F34FF10B633EB94E0FF57AC -:10DBC000339CDF58EDD81A3E5E12FE417C170E8D55 -:10DBD0004FFDE4375BCA0CF163FFDE877F21FC5EFB -:10DBE000FB3F325E01ABF2A17C0835C85A0AEBB3A9 -:10DBF000DE6C15CA91E52A4B838C28A8EE965CFA58 -:10DC0000D8EBD2C9587D2F5F1FA9313404DF9F990B -:10DC100044F473CA8DAFF56C00923BBE381823FAFA -:10DC2000D018CBCD193E9FDBDB90902DE545B5524A -:10DC300082C68B3D5906ED938BB8DEDBDEB030DB60 -:10DC40002AAF3C9224F0E6A40FA6ABD391AD387D69 -:10DC5000A80DB2E19BF2C5E943FD9CF491B7C6D291 -:10DC60008E7DF6F58A9876C149D2C7171DCF5CD74D -:10DC7000E17CB556AC6B998F01DFDE5ABF30A39DB6 -:10DC800031F2BA5611BF471A9891CAD02E7F703D13 -:10DC900093C39FB03ECAE0F25E675B2F65FCF4A6BB -:10DCA0009E51F0A144ECF335FBF5B52AFA6BB9505F -:10DCB000543519FB73637F40671BA3B72619F0C364 -:10DCC00071A46DC087D25D99C6322B63B17B040409 -:10DCD00032947D5123B589E82045EB62C2E7D165D6 -:10DCE0001BFED588DF56664D49C90ABFAFD54D70BA -:10DCF000B8713CA07745830E01156A90A57D61AC93 -:10DD0000C1E1473238712A96BF6DA3832EBD8A6563 -:10DD10005A07935E11AD9C5EBF7D72F2C539DE225B -:10DD20003BBC27DD2EA8EAAF5BF4D0C8ED54F6BAB1 -:10DD3000B93E80C4ABB0836943EBB4C1C5F6495367 -:10DD4000415F175DC612F076037E3A9BE894EC992A -:10DD50000D45551AD215DB2DA908A7A947593487B7 -:10DD6000EA554A3AF5237B5B18D65382063DCDEF40 -:10DD700023C325E82F691C28837EBF24D6F74B4296 -:10DD8000AFB16AD76BFD26DCA467D5A132CCE3ED39 -:10DD90001BE07F4027C94A29758F34FC7B03EA4585 -:10DDA000904B0DF8DE2257760CF24194D6AB417CB5 -:10DDB0007BECE117269D05F4D11753188AAD750F3A -:10DDC0007B8C3AE8FFD973A5944712F0029C0B04B0 -:10DDD0009C4F1BB9C548A77D751EA2E305177C188B -:10DDE00041323EB6EFF76A267A5930DB350407FC3C -:10DDF000B7CA3A3FF8EF2783EB5244E39870ADA8D7 -:10DE000052088EBED9520AC739F4C7BFDC7C0EC097 -:10DE1000F974B514F3E8046F88C1787DC67B91511D -:10DE2000FD0E737C9D69884FE7F8E67A840B19E153 -:10DE300095FD09F00AE3256B07FAD7239E8F4AB1B7 -:10DE4000F5305ED69CD609384E892C13BC1B677BF7 -:10DE50006505E887BD384E467C06059F67B9BBBDA2 -:10DE6000A7029C9D13657617BCDA5836BA3C6B77CF -:10DE7000C833558B1B12B4D7935A95320A5FA40C42 -:10DE8000B93E93BC7B4AE27AB223B9502BC3E91D59 -:10DE9000B2DB81A897E216BD0AF6E25312CCDF1579 -:10DEA000E1749C5D17E77662DF38925F01B11E591D -:10DEB000531666B10C76F088F3808132D9CDD93211 -:10DEC000878FBDC2FB57CDFE7346EF7F83E8FFA36C -:10DED0006689F5217C6ADC8BEBCF8C4AA267BFA0F8 -:10DEE0004FB62687CAA6DCF594C7BB4A601D3D51D4 -:10DEF00099E93ACE2F49EBBC19D6B80840F1D7C101 -:10DF000077A8BAF9EF0AD925D9F2F16412E0D87CE2 -:10DF1000E01AA6839DEA8FA61895275FED45FC6C55 -:10DF200006A5C0C7EF65387E00C816E56B00E4ABF8 -:10DF30008EF255EF4DCB5056EB59CC804F212D260C -:10DF4000F981640E464BD7AAF0BE7D3123FA65688D -:10DF50004558F0DB1E7DCE5000AECE2646764D678E -:10DF6000A496E6D75E51EB2D417BA741A5F7EC5374 -:10DF7000C0876987803CF4973303C7DB9CCF52414D -:10DF8000E4A5BA3CA247B7C6E7AFEF2863E9B3E020 -:10DF90007BF6F403387EF23B2C36910F49724D35F7 -:10DFA000E9424D2425F4EF5AB5D8A60C74B7832561 -:10DFB000B2E469363A25BDEBC45B969B5D88F8ED0B -:10DFC000AC04FA2F19DE4F11F20FD05B2AB6F0E243 -:10DFD000D20CE394C83AD18759D63F7213FC23D5AB -:10DFE0001FAA0776662E766D4888175617A1F9E5A1 -:10DFF000B0C13F069673C57CC7B116AA179DD97DDF -:10E0000000F9ACC0E8AD415CDC1EBAEC595A377679 -:10E01000A786F10880B6EC44EE909C30825C4EBC42 -:10E020001B93493E86E4B4664007215F5F9494B534 -:10E03000CEC88FC8C22600F0A6B6EEC9E85F8659E2 -:10E040004CC2EFA1989AB4CA9F2C06659BFDC78E5F -:10E05000944D27D2E27CC1B403C8325A79CB69D837 -:10E06000DF7600C8077EF2965082F4C587BEF014B2 -:10E070001CEC43399E95E6EDCBD1EEBE5EF1C73682 -:10E08000213DC4B87EF0C23F28FFB266AA36799C13 -:10E090006DD8CBB90EBD314F09D27CB3BFC4843E1D -:10E0A000301A268E1B820F206B44BAD956A7321C19 -:10E0B0002F18E4709970E62A9FA66546701C4538B3 -:10E0C000003D0447B89C91BF07F01C75C073D40194 -:10E0D000CF512B3CAD5E3E5FA7DFBF54167E3FF8AD -:10E0E000BDA8078FB3B78C7A2418A398F44A58E3D5 -:10E0F0007583DE3E32AA34A6D1FA3BFD7E589F7767 -:10E100006DFA61A628EB60D797127CF6EFAC88E831 -:10E1100084CA0A1BF45F97CE34F1A37FF965E0BB94 -:10E120006B0EBB18F215F0AF82DF5DE2EB35C28FEC -:10E130005D8AFA1FF4F6552C1E46F8DE6632D9CBFE -:10E140006FB3E7C26759E4E276D92DF4382CA8956D -:10E150007F592C8A7EB51AECEC53C2840693CEA468 -:10E1600013B46E31467E7790D35B9279D7927DD18E -:10E17000C5F5A3E9F77DBDDBAEAFBFB1C35EBE9A07 -:10E180002D1C87F475F56D2E96827EAFB1DA1FB027 -:10E190003E37CA1AC1F70DD6D2A905C9CE6AC279CF -:10E1A0002CD5988A7EDA8A7FFBE1F425309F9D4248 -:10E1B0008FBE09725DB7E88D659194DBA8183EBFEC -:10E1C000F5526CC139D2C8F3DBE0EA5B80F64172EC -:10E1D000AB8BFC3AE6F4D7F62AE4AF59DA11BC5718 -:10E1E00076D9E737D6FC9DF3058F85E6BB6CF71231 -:10E1F000D29B23CDC7BD5B325219F4DB03A63E147C -:10E20000F2C5A46F93AF93B58CDB7BFFD7975A0F02 -:10E21000E3FD01E523AD7FCB541E47699981CFB162 -:10E22000DAFDE7E76CF7A7CFD9EE3521C79DED56AC -:10E2300078FBDDB89EABD464BD240FD9D15E578B7B -:10E240005108A870EDAB49A32966A9D77592F50EC0 -:10E250004BA52755AF5E1EA5BF63C2CE78E2BE1F99 -:10E26000BBFB91FFF6BCBA00F5FB37FF5D615E9822 -:10E27000D7B1FB422C8DF4A9A6DC68AF2C03BA4AB7 -:10E2800051393DFD128B5D05144BFD7FF3FE10D916 -:10E2900007CB1EF4A41AA0FDB25FFCD71406783891 -:10E2A000B66EE03F0A915EF748DCFF4BF64FB904CB -:10E2B000DE2F53D915F10C74222B9C5FDEFA65A07A -:10E2C00009ED3E69F781AF51BFBD5F76A15C36EBCA -:10E2D0007D8CFB007954CFC0EFC99F4AA989128772 -:10E2E000AF71F270BFFBAD9F4A1CBE7DAE940FE1D3 -:10E2F000DBDDE34E40BD55BBDF21BA3DFFFE9F8510 -:10E30000110FABF629367F77D56E25ED9942CF57A1 -:10E31000F1899A51027E5B29F875E5DE15A407564E -:10E32000F66E7E07F975D53E974DAE035E6269C401 -:10E33000EB0B4AAC01CB0FFD24AC03AADE8CEE093B -:10E340006B15D4EF1237D0D5C533EDEDB0FF8F721A -:10E3500086F7C7D800C53557F56EE4E331AE6F4C8C -:10E360003E7D13FF923F5C6F9CAED8F71D8EB3A726 -:10E37000A7531C72776E463FCED41726BF7EF36735 -:10E38000C7772561DCB71EFC7FBB9200FFF27FBC24 -:10E39000B7EBDB302FB6DFA7A11C5AB5E70F6166DC -:10E3A000C17B9DC2FDB0633FFDC9BD3B815F8EBD9A -:10E3B000E421BBEED8A37F394587791F7BE0E37169 -:10E3C0006877AE7974EE78A4AF350F9F3F9E8DE2EB -:10E3D0003F20BDA63CD6754DD1BAEAFB240CC23015 -:10E3E000F688783AD6E7B1BD4A1A43B76FBFE84915 -:10E3F00079003FABE05D6B15AED70AD24358BE093A -:10E40000F0BCF2BE0DEF285332E13B592847F10929 -:10E410006C13C5F5BEE4E273ABF1E98AE9481F6C01 -:10E4200080E4BFB3DDAA23B0AE53475EC7E3EC532D -:10E4300037E27FD57D1BF9B88E757C1BFF7276069F -:10E44000FD3F6C1D97FF68277EDC9B4BEB3ED23A6D -:10E45000AE78F8D251FD33531E8C85DF6689C33503 -:10E460005531562BC8570FFEEBBD3B237C7D1B005F -:10E4700021C77E76FC140C2EBFE11AF81ACAC98196 -:10E48000473DDA5DD066D9A32F109F1D7BF859B7A1 -:10E490004E72920525D07BC7D8E09F3ED4832B25B2 -:10E4A0005E58757728ED090FADD3CA5463BD1EA61B -:10E4B000F7AFD2FB14A7FF95A9038BA40CEBB647CB -:10E4C00029E5723995477859A1F7B9B5A07D3DA5E1 -:10E4D00099B88EAFCE43BA1B691DCDF96B38FF19C1 -:10E4E00096F5BC9BF3ED48FC79ACC7A34A5943EBC6 -:10E4F0007B4CD807AB52D20B2C03DF32B68EC33B1A -:10E50000C2FEA3F974D2C3DD0E7A30DB9BF31E8BFF -:10E51000AFC79ECF67C3D76D8A6EA31B136F6F7D86 -:10E520009A59DEA7859C58C992F505A70ED7572A98 -:10E530008B270B4B86E0EDEC55488EBFB55B213B3E -:10E54000DD2917568EE08FFF4EE1F6C7CA7D07A67C -:10E55000A0FC7AEBE02F051D723A5F79DFABEEA4E9 -:10E5600090FF29ABFCC7FE32ACC78B02EE558F641F -:10E57000EE6FD57DEF64ECEF4DD5F832C2FF669FAC -:10E580008B25A18B377B958CF18D838ACB16C7EDBC -:10E590000C4D7F310BE39B61BF8EF35EBFCE7821C4 -:10E5A0008976C8732E4676A01A7BC303DFD787FC13 -:10E5B000B4EFBD3E7C35D32D7ABADD8127351A27DD -:10E5C0003F588DC4AB79EC3565F3475D9A6C839BFE -:10E5D000A9C9228CA7FCAEE42F2AF6FB0CDA7FA790 -:10E5E0000DD57F46651DB9D0DF3386145BCB32C4B1 -:10E5F000A71CFDC7672B4CB7D299512E5BE3ABE14B -:10E600008337505CA295B5A4314EC48A58EF3D962D -:10E610007EEF6CD3581AC667F5E5B235BEEA696974 -:10E62000313C0047D11AAD144DB391C62F6E91ED18 -:10E63000716D31FE6A114F60BBF7ECD903FDD6E373 -:10E64000B752F46378BC0ADC29B263CE1772F0D7F4 -:10E65000C20E3E28C50FA19F65E8DB54947352D9C2 -:10E660003615ED89F99F76AB4B2DF438BF6C6D11E3 -:10E67000D2CBE1BF2B4D99E86A91CAE96A6DC98690 -:10E68000226C7FD8777D117742A334CF0231CF43FC -:10E69000C5DF08F643BF074ABEB16512C0551F5516 -:10E6A00018C65BEA234BB654C2FC0B8E28311F946C -:10E6B0000B9A936A62F2F07176A1BC07FCDD857853 -:10E6C00004F8EF6E8B52F9DE369D9EBBDBCAE9B9CA -:10E6D000A72D46DFEF6B9B49E5DEB67A7A3ED8166A -:10E6E000A7F7E11BFD09A4DFBD6D4DF4FE176D0911 -:10E6F0007AD6AA9CDFE60B7C58E64DFB608BDAC32A -:10E70000EB308E62E2CF89EF3AA0B81CDA37907412 -:10E71000C4F77895CB15275E5B5B836497EE929880 -:10E720000D9FD3556E47C6051CBFF6262E54E1F942 -:10E730006E7D5905D93D2C1E4339BD4B8ADF5209E8 -:10E74000FCF244F18CA855EE66051371356FA87C78 -:10E750004A178FCFCC50B97CAA676B0F65017CC676 -:10E76000A74C473A33E779B0462F42B978702DC0AD -:10E770005381DF65566EA133B3BF59023E16CC2CD0 -:10E78000A787E896F37F7456F9368C1383E3199BB9 -:10E79000A893D56D6BB74D35E3DE3AD1B14927C0AB -:10E7A0003F4F1447A81BEE2F3697F0EF3E4EE7ADD4 -:10E7B000FDEF507C2B3A8ED9E28D1DCD32F9393BDD -:10E7C0005FE171E9E3CDA5DB2641FD1AC01BFAED3F -:10E7D00039F3CBB21216BADE22E869A7379EA58DAF -:10E7E000A2BF3A453DB3FCBC2FF15D5C97EF4FF8FB -:10E7F000793ED2F34E57EA72948FADAF78F475300C -:10E80000A57F04E249FC1E2F82F700D2F1FA351EE3 -:10E810009A5A90EF3FB4DEA46F3BCDC2E7A1989D1A -:10E82000AF77B58E1E9736E1DE85708F129735E192 -:10E8300036D7E378FDA2816FB0E17870F69B337F25 -:10E84000D1A8E3DF897CE7213CECB2D25B518B4657 -:10E85000FB0C667B73BECEF6CEF90EE52B9CDCFE80 -:10E860004CAF8BE5E27A3EF0B7531E7A86E192C751 -:10E8700015946357A8895E84673A6BA1325307F2F7 -:10E88000915F5EF473FADFD9796F3EF1919A2A4174 -:10E89000BD70B2E375B078BC06F5564C8E59E5B93B -:10E8A000F97C5C35E304698A1FD116330C29076EA5 -:10E8B0008A66C2F360FF45EA5BD6FDA42D8C713FEA -:10E8C0003DEDA57D0E0C8868502E39CCAA36417FCF -:10E8D0007B843CA951B95F78D661BD47E1F123A59E -:10E8E0003164C1A388A79A71AC0E7613D3A0A95B3B -:10E8F000AD3C80D54D3E6C74279E477CB9A33AED64 -:10E90000BFBB2209E22B26E2DFC5224E3F57C419C6 -:10E91000EF69E571C65616BFF034E4EB230A23FF16 -:10E920003871AA8D7F9DF33C20E8EADF85FEFBA5C8 -:10E9300090DB65EA01290BFA0FBD913E1886E7BF0F -:10E940000939FEB090E307B7FD4709E6137424DCEC -:10E9500031C469B8DA9F96C00EBD79FA1BFA3550FA -:10E96000BFA37B523BE267C31A1E977F08E53EB404 -:10E970007B40C8FD704BE7B5B46F27E44B91992FEE -:10E9800020E4499190278F6D7B7EC9069C5FC24B26 -:10E99000E3B4B2F49318D7676B64B253C2BDDFBB64 -:10E9A0000EFBB9BFCDE0FD76EFF917B4EF7FE84D70 -:10E9B00057FD06E3FFB3DDB124CAA9D4449B9C0AEA -:10E9C000F7EEBB1EEB857B9FBA81F261041E3C8F84 -:10E9D000C07CA14AD6AD87D321A857D89F46B31B88 -:10E9E000D6B567FEE9D05F59834CE1EAFBA4F8F99C -:10E9F00021A48746BE0F9D55B9682DD6EF5EFE5CFB -:10EA000012DB8F7BBA45C265CFF997BB6A107FF7DF -:10EA100014BDF6640D3C27B94A880E82AFE8F93F71 -:10EA200061D87F3C7A8D3E321D3EB67C354339E657 -:10EA3000B94DA67DFA7B6E5BCDBE61CDBB58AE668F -:10EA40008C8F4D7279F87ED66D0BFB50CE9AFB57AA -:10EA5000852BEABCC4FF4F33DBFEACB98F65B6AF84 -:10EA60009412935C79B45FC1F7B544FB02056D3C29 -:10EA7000285E27733E88A77DD67C93E0B5723C1351 -:10EA80003C335C2AC1D31EABDBFD1F309E3AE33220 -:10EA9000D2CBACDB0E87B31DC03183C3C1E133E100 -:10EAA0002806932008E3DF3AFFF97C84EFA3FA41BC -:10EAB0007DE347FFBFE376393D01D6676BBB4CFB77 -:10EAC000F707AB0F7A118F5BAA6BFDDCFEE1749741 -:10EAD00023F8E8EE7A99F8F67835DFEF679F9EA085 -:10EAE000FD3097F89E9377D04B7B18492358331D00 -:10EAF000D30FCC3F96FC02C04D55D26F939F726BE3 -:10EB00008E2DDFA0981538F2564A87EAA3FF5D7F65 -:10EB10004442BD1412FBD165E6FEB6F24A0CE77F13 -:10EB200087A917DBBCF4EC6939E8D301AEC75B8079 -:10EB30004E685EF6BC144F33A37915B4F07DB62D44 -:10EB40005ADF0137948B6E07D4EB68CFF5927C6166 -:10EB5000DD3C5FC0DCEF98B8DC9EB752E4C8B71963 -:10EB6000969FF519FDCC6B5DF67CC3E36CCBE94455 -:10EB70000F7DA5B675E9391BDC9AA9C3FDCDC17E11 -:10EB8000853FC5A25CCEE5F8F81837DFA834A3BDF1 -:10EB900014BEB02ADBBA3FDAE9E276D2A13F7A1896 -:10EBA000C6E337D479298E63EEA39BEBBD1593AEF4 -:10EBB00030DFA1FD5E1FD2CBCE48293D1F9BF594CF -:10EBC000AF9FE890E70378C49CD6CD7A6A7E33E0A5 -:10EBD000F5877932E9988EA2E7F2717FF1D63A2F64 -:10EBE000EDF78703FDBD8F4139F87D770CF7B7EF5F -:10EBF000A9493759FDD7FB5DDCDEDAE112FA6A8BF1 -:10EC00007DFF19F86007F2812718A7FD4BD92BF279 -:10EC1000261C7E8E898FF0C17CB964327F964E1E91 -:10EC2000B2CFEF1474B353C8FB2D42DE3BFB29690E -:10EC3000D60EBAD1EE5FAE552919F87242ABDD4E51 -:10EC4000286EB1E7D51436DBE93E142B70D8156970 -:10EC5000D263A63EDEE00B9E8A745F05FA92DB0764 -:10EC60009A6CDD6F77EAE33DAAB1CF45F6EEC9D9DC -:10EC700009E140BC05F1EDB4730F097CFF4D310E85 -:10EC8000227E036AFC908BF240E324679C76C330BB -:10EC90003819C0397954387FEBFA0CF6D358FB0396 -:10ECA0001FCAF11DCF00C873B298C8BB08911CEEF3 -:10ECB00008717FA5C3C5FD8477C5BCFECBA550BF39 -:10ECC0000382BEE604584BE67C321E2F7A1F0D13DA -:10ECD000AC373E73FE2E5A2CF4BD30F3F7F75D7C53 -:10ECE0009F6DCE84D1C7F900C781E7EF54E31D972C -:10ECF000651FE75197F19ECB12A7F8C8A5717E302A -:10ED0000D743E4E79AF6D33ED5F8D8DADE7CE6CCF2 -:10ED100057693FF738F3C714C0CFFE7CB697811C04 -:10ED2000D92F097CFED147794026BE07ED6B941F91 -:10ED3000A8075E09A4309E62AE83B90F332847440A -:10ED4000FD33DC5C9E00DD04DC347E9CEF17B234C6 -:10ED5000C9870241373B7D8B6FA983E7CDB3DE7C4A -:10ED600011F315DE7ED8A7235C5BAB8F86AD729363 -:10ED700035DBE9C77CEFFAA890F6E9BF2525F2DD7F -:10ED800016BBDE15197063FBFD924EFE5CF20F0A96 -:10ED9000D923FBA5D4E964A8A88CF633F65F134DFC -:10EDA0006DB2EC7738EDFC1C5FFF1DAB70DECD6003 -:10EDB0002FB10CF12961A70FDA1D517BFBB89B091C -:10EDC0003B1BA60B7C5D29E61D530D05E198C61281 -:10EDD000F49CC1747A823F50E586FA67B1817CE485 -:10EDE000A3758153CEE176C67F1BDE8CFF8D781B29 -:10EDF000A25BBBDE36F71DF2041E42AC85F6DF1FB8 -:10EE00006F5ABA71228CE72E0A923D9CD7D47EAD00 -:10EE10001CC66CBF3E0DFDCD3CB11FCE1671FD6C06 -:10EE2000EE4FE734D8F5B9537F7B84BDE11941AF8C -:10EE30003BE5E6487A7DB9DBAED707E3C723C83F99 -:10EE400067FC786CF9A7DF525782791AC60B756890 -:10EE5000D7CD5629DE193E955D11B7D0C3FF751386 -:10EE6000D1C193E7CD6C027E4D9DC6F99CA19F1048 -:10EE7000000584FB09C5720AF36D362453F5987FAB -:10EE8000B6419DA859D7B1A698DBB35B6BFDCD56B3 -:10EE9000BBF6753F8FA75E1BA8790AE9AA2298AA3C -:10EEA0002577CF0047701CCFBBC4753B5363FDB8BB -:10EEB0000FEB615C6F034778B95EA9D35EA7FCCC0A -:10EEC000043B11184D2FD8F331F7A8A9757EC4471C -:10EED00084C75F423B244ACE517A8D34E6724D0D91 -:10EEE0002CBCD3CDF557398E73603A98BB50FF8355 -:10EEF000036EB2737A43852ADA93FBE5A53F423B62 -:10EF000070E0250FC3FD94DEBF9F41E71A7A43E707 -:10EF1000CC433AE8951878B6307FE01F9EFCC302D8 -:10EF200018B70F9F6F308C5B0E3CCE6277C1F8AE86 -:10EF3000E84371CADB6546409E09ED7CAC0BF35794 -:10EF4000629FF8DF3B0FE8EEC160D5F6A96C280E92 -:10EF500060FAFFE7F9130F219C1DE3FEB319F9AC2A -:10EF60000BE054C80E33A20877559E4CFCC7F282C2 -:10EF7000A989F0BEE670A40EF3D16AD44A94340095 -:10EF8000075FEFE77D8947B19F3AADB12E1BEA5786 -:10EF90001FD1C95E9917BDF61096A7BFC2CB1D6ED3 -:10EFA00046F620F22FB3F05FCD47A7D0FC0E0B3909 -:10EFB000DE1E35FA0C6994F5D054C7790E7B1E8B92 -:10EFC000950EB4E9363A48B8AC743013E860B2959F -:10EFD0000E0CE9B3D0C1F784BC1D9B5F389F5CAFBA -:10EFE00070BE194EF72DDE9C8AE1FC618EBBA93AFA -:10EFF0002782FBAB261F68336ED2B0EC59E28E231A -:10F00000DF997C61F2C33FBC2E820BF8E2421F3CC9 -:10F010001705F5B999F802FD382BFD5F32029F2CD8 -:10F0200060038730E77E81CA925920427E77F61BC3 -:10F0300065A758E8DE89A705B32576D4228F4E9CB4 -:10F04000E0650B1EB5C13C68E5E4F1FD9CAA774480 -:10F050002C7CD709F6331A855D728CE59520DF2D5F -:10F060000D7AA6E1F98607A214DFF7C49B296F6D1C -:10F07000C65B81AB810E3F1827EB38F90E7DE9FDA9 -:10F08000C4BF2F0618DA6D5BA72F9B80FEC907D778 -:10F090002426609C7323E0FF281937A9F132E5424A -:10F0A000F58FE7FB657A943F1351FE9E89EF295156 -:10F0B0003644BD7EAA07EB6C9387DBBD9CBEB77B55 -:10F0C000B95DB8D1DDED45FE1A28F1D27EAA59EF1F -:10F0D0003C85DB6DB33C229EFCE97A1DFDFB591E8D -:10F0E000DE6E7B5B2AFEDA448473373D731B520C61 -:10F0F000F703FCE5491DE3F1DE752C91C9EEBBDD9C -:10F10000CBFD7FEFC11FD03E526E598CFCCE480321 -:10F11000F46759AF05809A2C901F00AE8174DCA172 -:10F12000FBC90E5B10A9FDAB3A65F8FAE29FA39606 -:10F1300075F2FE4349F472FF8CFC8B35C29FAB2BFA -:10F14000F5125F74B4BA7B702A8B3CD9DCDE8DD4A7 -:10F150008E9A3F8B7E5312D639057E133E717F23E4 -:10F16000791ADFDFC032EE6FE013F737F089FB1B4F -:10F17000F81DF737B0FCF33683CAB8CF8165DCE7FA -:10F18000C032EE6F6019F737F0B9AFAD999EBF6A24 -:10F190006BA1EF8FB4B552F93C0FB7B3597932BABE -:10F1A00010F0DC7583DBC07DEBCD627D1E334A73CE -:10F1B00063B08EBE08F73B7D4FDFCA703EBE288F1E -:10F1C0001775466F6557C2B36B5AA80B0359DEFB20 -:10F1D00083F4F4A9DB19C60D7649C9668CD0ADF667 -:10F1E000FCE27C15F47359F4DADA1C28B77A1E595C -:10F1F0008F793B93F4B5B1A5DA50590F552D7BC0EB -:10F20000529E50D1A3FAA1FE7736EC5F8F7C8A70B4 -:10F21000A0F1B6C173E0FCB5B0E4E95246E73706A9 -:10F220004ADC29A4B3AB70BD2622FCDCAEBF88AD9E -:10F230008FA29F3C417757217F40FD34A7CB93ABF2 -:10F24000BF1937A9A60D6F375A3DB9FAA4EA31653F -:10F2500094FEF0BB344A3F1D6CBD8667C936232F30 -:10F26000633E912F407E5A978BF365978F3FDFF473 -:10F2700072BFECD7DEDA8BBCF0BC48F069972F5E2A -:10F280008F71CE81C932C50B7A5DD00526E5B69661 -:10F29000FCBE14C6FDD6532AC3B8F35D1E6EDF4C08 -:10F2A0009C10E2FAF2DB5ED297174CF8597B0E9471 -:10F2B00027FE381643FDB799C5FC4827C92D3C6E7B -:10F2C000FAAFD5A7E63442F533A73D9C43713FC161 -:10F2D000DF293C6F04E5B51D574FC038C707CF7213 -:10F2E000B9F480A0B71E575F0BADE7B420D90D8CE1 -:10F2F00075935DB036AAD2BEBC9CCF9F6E97F615B3 -:10F30000ACE706C59B0478DC7F9FE125FFFB238FDC -:10F3100038A7D647F682DB97D0B2E17D7752267EBA -:10F320005FAFF953988ABF395845E76693152AE5C8 -:10F330005D6FAEE0F1B940E8B214DA09B71CF071C4 -:10F34000F910F452FE55AA62EFE1DA083E650DF9B4 -:10F350003D652CAC27BC6BB246795CF037FADE1CFD -:10F36000A13CEDCD4CAC4BB34C7E60C7B84F7E3367 -:10F3700015F7BBBFAEC5C4D921CA8324D346C67313 -:10F38000BC03070308CF57CD7347FDEB0250BF7D89 -:10F39000A916C37598A2D5D6637CB043ABF5225F9E -:10F3A0000526D77997901C1ACC53A6F36DED15DC82 -:10F3B0005EC5EFC897AC9D1DC2F32C85429605B281 -:10F3C000AB24B4733A1A286C8479BCB6BCCBF69CD7 -:10F3D0000B29AF5D599043707630C38BF5930D2A9E -:10F3E000E9A5C2A0378D765CA11937C494638B1F41 -:10F3F00091BBDC9EB79CDFACDACE758C4FD8CB7955 -:10F40000C22FC873E4377FEA31F755EC7872CE37F4 -:10F4100037725736C29B8B0795F5E1F3D91EA96A5F -:10F42000C479166A7E823BAAADAB41F9359EB5AC74 -:10F4300045BAFBCCF03AE09C52D1DE87EB3E455713 -:10F44000E91CC35436B00EFBDD2CE8BCABC4AE27C0 -:10F45000EFF228627FB7B6DA3B8DC7B99296F14BCF -:10F46000927E96B48C776A578EAD3CB1BBC056FF86 -:10F47000B41DA5B6EFA7A7CEB07D3F737795AD3C81 -:10F48000B97796ADFED47DB5B67265FA425BFDB331 -:10F490000E2FB495A7F57DC5567FC68B4B6DDFCF7C -:10F4A000EE5F66FB7ECE1BAB6DE573076EB4D537A2 -:10F4B000ED66A75E9CE2FD7CF6B207CF79D9E282C9 -:10F4C000767BDC694F7BFFB15E5F87722DEC26FA9D -:10F4D00056518F4379F50DDC9FF1CE89E92857CA43 -:10F4E000845D931534CE41395A13F6923E5083BC55 -:10F4F0009E1A9C4776C7293B401E9D8556201BFCC3 -:10F500001E40B9DC968C97B986E0F669DD7466A179 -:10F51000265C4F7175B3BDAA192C11C2F1746ECF60 -:10F5200080B788F57C3AB4B7CC63BF2CD311EF0118 -:10F53000F0BBEEB2F85D23F9594EBFEA64FDA85363 -:10F5400064E6C7678F146FC16745CBB3B5985E0794 -:10F55000FED5158887ADEE78730FF4BBB5D4CFF721 -:10F56000C1847FD555D24B7C3150A2927E61AA5E78 -:10F57000B1D012DFDAE4E57A25E0BD83FC3BB57457 -:10F58000E6611DF1BE56A5B8C36689C74792B00EA5 -:10F59000A8D776CD7AE39DEFC07B6FA9B7D00BF2E9 -:10F5A00028F698DBC0FDCFED02AFA55A652D585C5B -:10F5B000605F341EC4E7241DEC0C7896976F3B887F -:10F5C000CF9BBC3CBFEE8CD803B5284BBC73B8FDB9 -:10F5D000A74C71A7D6E1FA691C8E91E84CCDD9C130 -:10F5E000F7A9CAD4D791DED0DA3E210FD1810FE935 -:10F5F00040A227D18F2F1224BDE1C38D1C2CAB520A -:10F600002A00DF23658684791735E11DB4EFE64BC8 -:10F61000DBED55F03737215E230DF6F50E787711C7 -:10F620007CED128FBF7665EB4FD702FC5D79A53973 -:10F63000183BC1F844A345DE6C17FAF42B3ED9D42D -:10F64000FF246FE85CD7B4217B07E87F877C2AC260 -:10F65000D7CD506EF96EEA6648EF3E0D5613EDEDCC -:10F66000EF2689FE4D7BF73AC15B75A54DB4DFF5FA -:10F670005EA48AEC5B5FEBCF33E2CFD7AF30E3AC75 -:10F6800091F11A9EB493F43D2B75EB6857B4EA6E72 -:10F69000A327833CA8F2703B6623E67D203C22EF43 -:10F6A000A34BE0C3DC6F7BCFCC8712FBBCD76533A9 -:10F6B000DBBEDF757955E347B3C77DE0F7252CF056 -:10F6C0006E8471102F1D9F36D6C769FF8FF1736A44 -:10F6D0007FAFE8A1F3C0C27FA91276D22C0A9A01AB -:10F6E000DFB819F909E763FCE22CF4362FAA47BE0C -:10F6F00034E31DAF7973A85E2CC99416B2575CA68B -:10F70000DE924F4C259875B719A7249397EB35F8DF -:10F71000F7009EAB38B5CB7E5E6962B7BD7CDA0E72 -:10F720007BF9F494BD0C56F311B40B1A19C7CF9999 -:10F73000BBEDDF1BCD385F1D3F67E185914F70FD4D -:10F740006B3BD7CA84FE37E3A9C5BDE91A14AF45A0 -:10F750006BEC7AB540E8F90287FEAC0A29E4E7D7FA -:10F760001C8E1C42FBD18CBF3CEFD36DF96F661C25 -:10F77000C529CFFDAF6C63F085FCE58487C7171200 -:10F78000E0DFB41689B845317FBA14FD99C564A786 -:10F79000B59C86F2E9D7DEC4075E325AECE720DE7C -:10F7A000AD571F97743E4EC232CEF5E5C90BF8F443 -:10F7B00053945762C6314C3FFD1F01E322E4AFCDA5 -:10F7C000B1E75A1EC338D24B1E86FDCC559E3EDC97 -:10F7D00006E5D5C52AE5416A3396FFC88F7140FC1E -:10F7E0000EE59A127D3CD1FF932EF2D737087A3678 -:10F7F000CFE798718F5C9FD03F3EC9DC87F08B3C90 -:10F80000573FDAB967EE06D96CD3733C9E66C6CD16 -:10F8100026F7DABFF732295783F59BDA9492B95D60 -:10F8200065046B2C71F533C47A4D599CBE753194C7 -:10F83000EF63A92ABC2FA252D045EC90FD3CD838EA -:10F8400026D1B981714794580AEA4F79C4FEBDC2E6 -:10F85000715EEC0CE7F931479C37A4B07796C0781D -:10F860005BF41609E5E796C560C343B9C227F28782 -:10F8700027B149487F7395602C8DF8FD83427AC388 -:10F88000F3EA692F2C417DFE2CCF4FD14ED5B7D551 -:10F890004159FB8D42FA490BB0CACAE0505CF87B73 -:10F8A0002762ACDD351467DA03EB5A3611FD6B2F96 -:10F8B00043BDF273585F2CF7823F8EE507C11FC727 -:10F8C000E75EF0C7F1FD2FC01FC7F23EF0C7F1F9A8 -:10F8D0002BF0C7F1FD23E08F63F9DA404D8D2FCF78 -:10F8E0001EA7B2C6ED86E254FD9219A74251F2BEA0 -:10F8F0009BD3FF60BC2AC1E35563F76398FD503C7E -:10F9000070583F222EF8F60DFF792F9E9F5E316DC5 -:10F910005D179E83F5BACCB818CF7F30F39A4DFEB1 -:10F920005BB1F75ADA0F76E71F69C1F5D85B1DA402 -:10F930003B86DCAE8486F2D1E97F997E97D3FE3593 -:10F940009F4E7DE4473BE02CB493BA29EEB3C9C582 -:10F95000CAE95CACE48F215F38E390261F3FEB2BB4 -:10F96000CD789E69303F56C4673C2CE5C578995BDD -:10F9700012F314F99B24C2A08BCDC8CF967CE36010 -:10F98000459AE21CC1A041F697047619D9695A221A -:10F990008A71A8CE11F26177093E5D9BEFA67B24A8 -:10F9A0003AF3F9FE7F5D512C8AEDD7E74F8F5AF37A -:10F9B00063CDFCDD43A1E9DE7E4B7FAB43A5A3EA2B -:10F9C0002905F4AA3E8A5E553C3C7F7DFDC1B3BD4E -:10F9D0009897BC29B8B40FEDAB4DD1089D5F3F900F -:10F9E0003F9DEC8FC1FAD19994BFAC04B9DDAA4414 -:10F9F000BD64B7AA38FF8AA1FA66BD1B857C06F6EE -:10FA0000A3F85C20D84BF53C6A9CE21F9E08A3FD3E -:10FA10002A8F97E70B04C1BFF6DAE2A6421FFBB8B4 -:10FA20007CDBA427E2D86E5354D5511C6D2AAF223B -:10FA30003CAF17785E9F67EAFD18D91B0F0A39683B -:10FA4000F6B35EF8EBEB9BDD6477C55BB38DBA5C18 -:10FA5000CAC7FC09F2DFA6E05D5ECC6F77E7578F7F -:10FA6000DAEFA363F6FB6A6DDD59D4EF83187F7676 -:10FA700087966AD8AF6B84BCFBA7447F9FD7BE0430 -:10FA8000CC69B4DFC54C7D9B8A5AF7899D4F3FDA1C -:10FA900089670D6FB742EF9F8779BF2A4BD6FB95D9 -:10FAA000E1E71656EEE3F7506D55FBC8DED9FAA92B -:10FAB00094F1FC43B6DFD43F837EB8CD5E2914FCBD -:10FAC0005428BEEB68AF94A05F69B72FCE3A6C2F75 -:10FAD0004FEBB39767BCE8B4578C3FA0BDB248C8A2 -:10FAE000BB3E90CF3C6962404539104FA66A10EE8C -:10FAF00046D6BB16F7295D22CEBC48E8AB8BCDFDC0 -:10FB0000477F36C15FD8ECB7F989E67D1A45A2FF79 -:10FB1000E2BA43D7B6A3708D9BF68F4EFE65F1FC1B -:10FB2000076B484C3AECA046C37E1EF562879DE306 -:10FB3000B4876AD41ECAB72C70C41FCC7D4A9C27D8 -:10FB40009ECB758EFF59C735FBDB097A0BED15F39C -:10FB50009E02BAC70BDA17AB692916A4FC2DCAF3AB -:10FB60002B5CC38C9E0C743CD3CFE5DA30BC25CF24 -:10FB700023BC9D2FDE1504F93D2805754A4A2FE167 -:10FB8000F95F284F162E87F990BD7C82F6A1CDFA39 -:10FB900039D9BD942FB6B341E2FE6392911D62AE96 -:10FBA000F3CE203F3FD378AE9492B17D4B298D4F59 -:10FBB00070950EAD2FE0E928C713CF2FBBA4DE7ED2 -:10FBC000CEA7D1616F98F470B1E3FDCB3E7E4EDAE3 -:10FBD000E483B7CF7E71D22900C70A29591F504E3E -:10FBE0005E4F5AF8C37502F910FF3E8EA642FC71B3 -:10FBF000D0FB9046F901D9FD773020C9063F4BD69E -:10FC0000CD06BDE81F385382F225FEC91D5DE7E22F -:10FC100071C5817F45A3CCE3A99A5B5F3C54F6FB99 -:10FC2000E7503922C601D722C9D7DB726F01C0FB6A -:10FC300003911FB0D960DB14CCAD94B56DB192A126 -:10FC40007639D84E1AA55D9C6D5333B40B9AED00EE -:10FC50005D9DE63D1FA5F8E4DF65018F757C15F11C -:10FC6000A6E9413AC7334FD530EFE18BC2316EACD4 -:10FC70007927D836D7A9C3DB01D86B4DF8E5CCF08E -:10FC8000A7F0BB757CD728F0FFB3F131567F6EF13A -:10FC9000FD33C307D5D78D1B79BE08978BEECBD02C -:10FCA00083B2A59F5B0E7C4CF16BF57246E77454F2 -:10FCB00097A1C580CE2BB4DBC80F57B3EB34B40388 -:10FCC000364219ED808DBDDD14A7AE28BBB50B897A -:10FCD000BE22ED67280F26332DFB3EE877B2A662E1 -:10FCE000260E53CF3D2463DC9B7D89D13991AC0333 -:10FCF0007E7EAF45C9AC1FA37F949DEDA5385020F3 -:10FD00007BFA8FB9B1CBE3C126FC819A23B51827C2 -:10FD1000571B590C59519552AC0699EC7446FB107F -:10FD20007E63EFF578DE12141FE927BAEB01F5AA1E -:10FD3000888B8FE724C3BADC5A23FA09C9A7548AEF -:10FD4000BF8F47D31488B2A222671BC25391800E83 -:10FD500024849FC7B52627E4581AFAAF7A87B76379 -:10FD6000BFE5E703C097687A3838845753AE8C17DD -:10FD7000F1F2E8627B3C990DC09CA17DD56F17DE46 -:10FD800083F18471C3E437F7AFCD7B74B2DE61F1E8 -:10FD900087695FD3AE37FCE2BE0ABFE31E8492A040 -:10FDA000CB768FC130BFE1BB71D2031E16F3BAC947 -:10FDB000BE584C7683E98FECC48A18FF2F66FC5E30 -:10FDC0002B67FBE9BC3D8B72FFC4E30733AF0ABE70 -:10FDD0002FF31BA46F3D50063C4A6EE6CD87F70516 -:10FDE000328F8BAC95988AE5A1F1D2B44FBF418A8E -:10FDF00075C5A421FF77BD16A3FC01B626C7662FE3 -:10FE00009B79A8ABAF29199F03CFACA1F3401AD2BD -:10FE1000E3EABC32B29FC3B9FDFF07E5EBFB9B36BB -:10FE2000CFF5A2FCC4FC8559F05FA0B32309F2D63C -:10FE3000F35121D32D7699476DA13898E7A3536CE0 -:10FE4000EFD36DF6F3834650AEC371C607747E2EB2 -:10FE50008369EDD8AE86D9CF097A3ECAB7D9E943CE -:10FE6000FD17D9DEA7C19EB1DE4F3172FF01A69703 -:10FE70005BFB3F7584FE2739FAD732F63FD46FAE6D -:10FE8000ADDF0E95C74793113FADBBD31E981AA89F -:10FE90002D0A4C1B257E1FE0F1C70DD1168ADFD736 -:10FEA000326078A093F33E3DAAF0F36C8CEC3656AA -:10FEB000648FDFD70AFA958122907ECF53EDF782C7 -:10FEC000CD61CE7BC2ECF6D073C82830AE1CAAEE52 -:10FED000A338FEC7411DFDAF91ECE5BE3646F1E308 -:10FEE0003981FEEB709FFA82CD77BA3A668AFCD7E9 -:10FEF00002C62EDDFCC05CB4EFFBC479BD8E884C1D -:10FF00007889D78EA7F337663F71379B88F2302EFA -:10FF1000F3FC04FA03E3F7E515DCB52903FE9CE7DF -:10FF20003B1B0D295E66A19B3E19F06A1DEFFCC2CA -:10FF30001EC5328FB8874DA3F1849D3B38DEB8CF04 -:10FF400037DEB322EE648ED738CF3EBF46B746F3D6 -:10FF50006B14FC6B8EF72CCE2F037EC71C4FE67400 -:10FF60003338DE05F6F9357A349A5FA3B8E777704F -:10FF7000BC719F6FBC0DAE9604DA6DDB24CEFFDD45 -:10FF8000815F75E0BABED7B03A4AFA40D8C5176368 -:10FF900003A877B1CAC75B50E44DADB58CB713E485 -:10FFA0008021F2DC0D0FE66F68544EB545E97917F4 -:10FFB000D8D906E56F94D3F77BDB6254DEDD369348 -:10FFC0009E663FE533F9BD33A7CF9632DADB870370 -:10FFD000DCCFDA96AF5D7E15EAA51A3F3F0F39F305 -:10FFE0001C6658EC5F30880FFA70FFE5325689BA0C -:10FFF0006DD20E0E77A46E5C0AD7CF5F79A8AF0DD5 -:020000021000EC -:10000000CA1E974B477D0ABC10CFE4A73E16E07E80 -:10001000B8C7CDE53D9BC5EF315C20F40A531A24E7 -:1000200017E2E3E26CDAEF5FB8C8086980B745927F -:10003000F48732A1A7F0DCCAA562A99C767E0435BC -:1000400006F41B319414DE4F7469D1E126D4CBF150 -:10005000D025E41FC4A1610EF473A9D09335AF7A03 -:1000600018E63BB0B96E8263D122BB3DBFCD97D6B7 -:10007000D03ED9561961B83E0B1BECDF3D6ECE87E2 -:1000800071C7BD050BC6B8C780EED2CA9047EA8CCF -:100090004F3E1AB0C7218FB38A5BEAF0635164D434 -:1000A0007B0CD6609BBC21FD369C8E393CAFFB9906 -:1000B000F0DBF6513CCC84AF404D4928AF0B9BF7A9 -:1000C000D9F29A00B1640C9B7178A6DC57897E88BE -:1000D000733E3BA5FBF247BBB7A480A9AFF7978B54 -:1000E0007B3DA5E1F37E2520F26F07E73DFB9932CA -:1000F00096897F78DC75C16125B6561FC28B8987CA -:10010000FF693EEA12787FE6FCF7ABB9FF5664BBA5 -:100110003FD3BC17F892C1B2CA540B3D5FBCCC4D63 -:10012000F60C33062A90EE8E9C1BE0F7B899F64B3E -:10013000FA2519ED972FDEBF516CCBDB14FD8EB481 -:100140005ECE3C42CB39D0A13C77CC2F91F83E56C5 -:1001500001E6B985F9FBA3763BD396E7B6FEC04F1F -:10016000258CF3DD81F978967DEB42F0E7516E1630 -:100170002DB7E7D539E132F3AA06CFD1CE5EA4DDA3 -:10018000A7D3BD89DD78114DD78E649C59F223CD5C -:10019000F381A63FED3C17A804F9FD795171DEC249 -:1001A000190FBE5E4E6A2512E6A3A6BC35F09C92DE -:1001B00093A8C2A3EAD72BC97A7CAF8C9FD58C7841 -:1001C00058DCFAED18C6EFB4DCCC71E9C5427F9F6C -:1001D0001BE4F18E575CE9628C632FCDA93D373863 -:1001E0002D43FDD6EF527F7346B88FFEB220A7BFD6 -:1001F0003B843E777EBF588CF3E51532DD6FE163BB -:10020000A1945482FBC6DD33E93CDECA9DB14CE7C4 -:10021000DE9E0A2716042D71075F193F7FCD58EF28 -:10022000D988AF8D7FBBB3F77E4065CEDF82244790 -:100230007314DEAFA5FD6599DAEFFFF8793AB7BC24 -:100240001FCFA9A09DCCEE9887FEDCD6C1324B4AC9 -:10025000181FCC16E5642BFF3E58AE9A578365A451 -:100260004120B29782733B915EB64A4C10E33C5EEC -:10027000DFC5EBFF427C9F73E15B3FBE05E5FD748C -:1002800037F9815B853D62C2F77290E7CDBC3C06D1 -:100290003E5BC5F720E233F299F0D99A091F2FE7A8 -:1002A0001837E0BAFB30930240F0FDCDBB06F3886F -:1002B0007FD0C66257C11CEE88EDFDE92D8CDA2790 -:1002C000ADF461B6BF28C7581B24788ED2FC4265B6 -:1002D00041746FD8C6198CFAC900C7C64CFD98EB9B -:1002E0007A308BCBB10FD1769E86EBCAED3FC5D36A -:1002F00017C5FD7FADFA7BD76920473A4BBA9B32D1 -:10030000D1F7F7437C9F3A7B8478F5CF053DBEA4B7 -:10031000C57F8070B46BB7D2FDAA6E89DB0D1B67F9 -:10032000F633C9D2EEB7218E6F80BB07EBBBCFE6A9 -:10033000F79E8600EF986016AAE6F06FD48F30CC57 -:10034000EB0E458F505E68A8BA9FF89D8E2A1470F8 -:10035000BA427FCD2BECB39F07BF320FEFDBC85102 -:100360004CBA7BAB13E946192A131DF5E4F0F6BF2E -:100370000FBDD5990491BB0BEC17BC872359C0F373 -:10038000469CF3FBA5807747D8D88BEB320C9F9E19 -:10039000FE1FDF02EDB74EE4E76DE6C87D4D572244 -:1003A0005D5E1824FB0BDE3759EFBF795DE0EBF59E -:1003B00020B79FB67EECA5EFCEF518895E7F27DAD1 -:1003C0007F0E7AFD5D263A017A7D06E765A1D7F7B3 -:1003D00059667A7D7E047A7D21135E9C6585193B82 -:1003E000707F56FD64DE6EEC4FBD68F68EFBE1A9B2 -:1003F0007C725392563326D9CE979AE3544A893F5A -:10040000072DF2DDBC9FFB9B41DEFFB07E674CDF1A -:100410008172EC24FA1DC0F938FBDD1FE4F0CEB97F -:100420003098C8746FD1CE10CF1BBF5BCC6B24BE8D -:10043000792AC4FDD991F8E681D020DFB050DED80A -:100440007CF3AAA80FEBE0C5FA63F3CD6DF4F49545 -:1004500071BEA163C8B386F30D4BBE487CD259C2AE -:10046000F9227FEB9F3B31CE31C847C90FEC7C941A -:10047000FCC0C6477FD9FA01D577B60F8F704F956C -:100480003EC8FFF109380FE34CAD9D9FB3E927BD8E -:10049000DDC3060E7828CF96E7B5FA9349839B0D06 -:1004A0007D0CEF3D2C1778D8853E18FA39D3459C42 -:1004B00049ED630B43C3F939549DAEB6DE23F06BAF -:1004C00031FE47A1F8D4D0341CAFFF74B4BF465AF4 -:1004D000A76A517F5BB6511DCA40D763E9A1CB43E0 -:1004E000FCBCEBE502EE9CBF795BD0FE74F2FB9C9A -:1004F00095BFFAEBBDA3F4739968BF20F4B9F97FF7 -:10050000412833FF5F1CB2F37F35DEBF9981FF2F97 -:10051000CBD41EF8FFCBA10CFCFF05F8FDCA50069A -:100520007E9F1DE2FD8F85EF7B05BEEFFD82F86E9D -:1005300017ED6F0A7D6EFBE0A65066FBE03BA169FC -:100540002785EFF611F0DD1122781E24F8437A900A -:10055000E2D85D33D85EA934231C5BADFD7875DE2F -:100560000FE0FD7D09E87ECE275DB14CF7CE40BBA4 -:10057000DBACF09BEDAA439A99BC7D2DFAE7775C42 -:1005800014A4783FE8C71DFF643AB83B94413ECFBE -:1005900091B91CFA20F820D9815FA0FFDE4CFD2F15 -:1005A000137436965DF098A00F98F7BF85A60D9747 -:1005B0007F3DE27752768413FB4384AFFEF928AF88 -:1005C00076DD9823613CAAC8484BE827EC15FA660B -:1005D0007248E7E71944BB5D6A5AC27C965D2D9A62 -:1005E00084E78D2CFD1D0E4D1BB93F271C00DF6FCE -:1005F0004224EF8CA7B15DF5901DF899ECA44BB2A5 -:100600008D2321D23FF1E7496E9F6697DBE63CE4FC -:100610007837E5BDF86666FE1D97BD41D594FF7F2E -:10062000B2CAFF17429AF9BB52D4DF67D53F00DF49 -:100630001B02BE3733C1E7C4CB58708E177A1EFA3F -:100640007B3F939E72F667FAADE63AB9512759E2BD -:100650003A5278D0EE656194DF1D329D435A20E412 -:10066000C98299D9C26ED7FCD8FF1D224E7EC7F22F -:100670005B6B70BFBBE726AD125150D0CCF59EBE70 -:10068000FC148A7F0644BF4EF807DBBB7B4FC77B59 -:10069000C761DC2C1CF7BCD92C8D7E6316DA0D14D7 -:1006A0008FD0E877BC723CDD518C9F6E94BA9B96DC -:1006B000A25E9D1FE4E74AA28BC6B8BF6D9D8D6EFA -:1006C00059B47A8CFA6BA9BE16E8A6FB2F4EBABEB7 -:1006D000A7BB29537E492C2C9B76D199A3E2351ACE -:1006E000A1B89689DFE1E3F0F5AB89B74888EF5010 -:1006F000B5A4E1D1AB10D009DA4B72591FE5337DB7 -:10070000A99AD30B03BF64F4FB333ACDF59E13CE05 -:10071000FBE27099F5461E4FD4739C57C07D2F8A1B -:10072000CF06B91CA38A507EF7706EC6B8BFF9DC3D -:10073000D0A615A92E6BFF29BE3F33983F1D8BA273 -:10074000BDD5CA383DB2A897EC30BAA7DDB29E4BF2 -:10075000C3DC7FFC4156FCAB61E2EF18DD4BC834D3 -:10076000EDA4E603EDAEA2762AB40B9D7CBB919F6F -:10077000E6EFD7C5F4B8E51E34935FC727920CEFB8 -:1007800099F157304D82F58F84CC7D424E07B705E5 -:10079000CD729236C9E365DD3C2F5F37E984CB1516 -:1007A0002DD06BC8958C6DBF79FE05D1D3A1BFB29A -:1007B0004414AFD487F213788F5A8EC2CBC0684FDF -:1007C0001C227DA19D21C5404FB5CF7DE27031E354 -:1007D00047A5E8F7D5E63E81F9843D66192FA428A0 -:1007E00087B27FB06C78A3502E1D2C27B1BC4BE88C -:1007F000C9ED37CF7DA23D4872EC662B7FD4083A15 -:10080000FC67D35F8FDEAEE13983645425BB6AA3F6 -:10081000831E7E157613FEA76A8914F2C5829B0695 -:10082000543CBAE22D8984901F2644DF4FE2FD79C3 -:1008300013668B34D5327E4F434F740DF1650FAE86 -:100840000BE36909189F1C5A9F54E6F5294FD1FA0A -:10085000F875FE5DC632F9DB3CFE1628E7FCAC7984 -:10086000787CEF2141AF07C33C7E7450C8D7AC6899 -:100870003BF953DE7A99E2C759F5B24D6FD02FE0BC -:10088000517DD5466F2FE724F6872D7A01962F5E8E -:100890000EF3F09F1EC9C1FD979A72750DFADB3FEA -:1008A00012F61FACD30F495E5446FC0992DBF1C728 -:1008B00033AE9BC0CB58EBF67C5B2256E71A79DD52 -:1008C0002EBB9CE7D33BDFBF28E4EAB1A63F7F0FF6 -:1008D000D965857780EEF3EE2A5B4B715833EEEAEB -:1008E000D95B932ED487F201D705C2B3E95C8A6342 -:1008F000DCE73FFDBE46E7443EF664DC4FFA87C0C6 -:10090000F391B6266A070B4CBFBF72054E85E7B15F -:10091000D9CEF199E711BEC638312C8A2FF912CA07 -:10092000A1A54D0ADDDB7005B3E7537CCDCCFB6A96 -:1009300035F3E378DE578265CF43365C9274FC7EF4 -:10094000048BCDC373F4C37E5742EC6F7DDD9137CA -:10095000F1E5A625B13A51EF3DFA7F8AF0B748E7B5 -:10096000F277518CDFDF7369FCF2589D653FFA85A1 -:10097000BF2B19F3262FCA32F1118FD54D1C8E8F44 -:10098000A571C9ADE963E3E564F1B044AD9C97A7F7 -:100990000FC78373FE80B1AD88E7AF039ED1EE1C15 -:1009A000091F508FD6E385CB15FA3D99794A830B01 -:1009B000F741AE6C94688F09F01B1679710D732D99 -:1009C000F03AF1E8C4D7958F323A3770E5ED218AD5 -:1009D000B73D67E2277D1EED5F98FB2796791EE500 -:1009E000F95B1ACD73E1CCCAC7F1DE84443B485BA6 -:1009F0003E5FDB3EE05216CFC2730B30EFA323AC59 -:100A0000BB6D3FD0099F137E9FD02BCE7D31A6A614 -:100A10002B500F1A59625F700A8B89FDB12C4AC79F -:100A20002DCB2C6F9DF7CD997476456BE3E0B8D84C -:100A3000BFC41283650DCF6B3DA96CBD14FEBE3AD9 -:100A4000CA7FD7307E796E077E5BC0CCDF1B3268F1 -:100A5000BFE90A81BF46F0F8F0B7D0CE03E184FBCE -:100A60007A0B0C9F1EB4CCF3DD6EA95E9CA3CA5A10 -:100A70003419DB250F285386C3BB3ACA7FBF10E861 -:100A8000F07D2B1DFA26F27B659D7831F175659618 -:100A9000D8379CC2A67C16BCBC848A731AEDD7904A -:100AA0009D3B2079E93CBCB98F037F4DBA4174B6B8 -:100AB0006695083B80CFDBBCBF8BB116B2EF178BBE -:100AC000F358AFB858D30341BEAF5365915B37E4D9 -:100AD000D4B46659EC6E735FC7BC2FCAA4E7AF7974 -:100AE000836985D3A1ED3EA8A13CA604E53129592F -:100AF000CB75C447177E3A9BEC9EF5D8BF12E0FB3E -:100B000055BE271FEABA541F5ABF4D573DDC3D0D55 -:100B1000CAFEAFFF3E499DEA3984B79058B71AB173 -:100B20006E267CFE0AFEDEB27E3C7E562EE26762B8 -:100B30001D47D213E63A9AEB867614D2AFAF5CFD2E -:100B400024D3EFF0B143D503C8A789A84A39740963 -:100B5000E9B50EBA678BE9BB70FFFD8A5697EDF7D2 -:100B60009712784E1FEB6FF409BF2446ED97E6F31A -:100B7000F6AC9CDB8D83749F84F6963C20E60D8F4B -:100B8000C375EB87B6982706FD8D437DCFBA2CE35E -:100B9000940E1F77C4FE1CED94C17D93582C669172 -:100BA000D70F65713DF96EB4BA57CE107F319F4BA8 -:100BB000BDB945AA253FEC68BEB729D3BDA4667F61 -:100BC00083F7C60DDA896F3F71A868C84EDCEC7AEE -:100BD000C36E27B237BE909DF872D61B4FB4033C4C -:100BE0001FFED143FAEADD7A3FAD436EEBF9ECBF6D -:100BF000F0BCAD8ABFED47F63DDD7BE36D2DA4F97A -:100C0000482A600E7F1F4C8F4988EFD7F0925E8C88 -:100C1000DFE92C1D02E072D59884F8BA55F8A3409C -:100C200067A75BEF677D2D8BDB5BE6381E2F4BE202 -:100C30003963B35FA083B59457DAC0488F98FBB08F -:100C4000263F9BFD0C64D9FDE093E0DF814CFCFB6B -:100C5000B4DCF2A7EFA0FDFA9442F9A05F8DDE406C -:100C6000EF2F6BBD929E97B75E43CF4FC478DF9254 -:100C7000129F64C17AF535FDFEABD703BDAEDAEB4A -:100C8000A173652BBEF5D79B913FBDADB0EED8EEFD -:100C9000EB57DE3E0DBEBB27CA64BF7615F37C0E54 -:100CA000F75A89C7FB75773DC650FE3F378B9AA828 -:100CB00000800000000000001F8B08000000000002 -:100CC000000BE57D097C54D5B9F8B973EF2C496662 -:100CD00026933D210B37842548C049202128D60979 -:100CE0005B632510C40525C0844008109280568798 -:100CF0004A654200A3468D75C3A5BC8162ABADFABF -:100D00008252A56DA4137101A518ABB5B820417826 -:100D10004ADD12411EA3D5FACEF79D73927B6F6612 -:100D200042687DBF7FFFBF177FEDC7B9E7DCB37CAB -:100D3000FBF9CE77EEAC7096E4BA0A09F90EFE2EF6 -:100D4000266485731A9649AAD3448A085963A3FF77 -:100D500056093973F8E6D4C5898444DBED6EFA840C -:100D6000581AB3EF34D132D92F9347289063C8A2D1 -:100D7000F23C0AAD0C0E712984240134218C074801 -:100D8000FBB585244212A09DDBDD60A765C54F5CE5 -:100D900000430A3EB74852795B5EDF7C0414FDD9FC -:100DA000423221E3613CE3FB167C7E8B6A2985F7A6 -:100DB000E504360FF17E0E7F3F87CFC7168A61F3B9 -:100DC0004830F6E364CF65D2D066EF3F8FF5B1537C -:100DD00047B992004F9E5C80847499CB1D842CB4DB -:100DE000BF72481A47A1CD1E9429243EF3A75DB9CE -:100DF00004FFBE1B06FF5FE1FA700C2112E992BEF0 -:100E0000A343CFFA460A0EA5F88B2A91031BB229F9 -:100E1000945C651326D066256637E0B37378A263C9 -:100E20009866FC0B5C12E2EF75C5E58079964F97EA -:100E3000CB0379D87DD2E5D0CFF4AAA25BD97036A6 -:100E4000924CC822F66FF2BABAA37918ADF7FBCD6F -:100E5000EE11948E8B6CFE00CC6F1151FC5D366CE4 -:100E6000227D2721549522FE1E9DEFA269B227CA3A -:100E7000A96B47BEA3F3241BC90BC369FF0B253E17 -:100E8000809F96E97BEFF3E29169A7AE80657411CC -:100E90009765186DBFB0AB722619875576E0A7A588 -:100EA000BCDD229FF9786FBFF47F957E7D797171EB -:100EB000FE4B940C142F81D209C067A34DC867550F -:100EC000CDFA764BDFBBE46FC409FD2AC77BF10D79 -:100ED000F32477313A4F6F72A9144FE7BB542CCFEC -:100EE0009A766C1AA1E5D9845C01FDCE9E26BB8260 -:100EF000B4758BCF443C74E2073D7240A26B3B98C3 -:100F0000DBB5FF62C05BB1597D04D69A4B6E9F9BE7 -:100F100008F5E35D80E772789686ED098176A9B6DB -:100F2000C008FAACD373CC5EA5E1BB83C5C7467BD2 -:100F300029BDB69A484D387E22A411E9FAC24FA2C3 -:100F4000B19F23F748012B9DFF74F99B3F4DA4F3FC -:100F5000A9FAA9D96D55715926A0EB4C3793474290 -:100F60003CF6E9149F0B092B1F23E545413A7E55BA -:100F7000FEE1122BEDA76A9384722AF04FF1FD81F6 -:100F8000166FDE86F2D8A08A78D73DA79D59809F3C -:100F9000299E3F8880E70FB478F6BDF7F6D817345E -:100FA000ED5A5C8E44E07352400ABEA3A8394D2628 -:100FB000C78E27FDD72DE099F587C6BE3082907B7E -:100FC00088E76E2E4F4AF9584A278578C2E9815240 -:100FD000279383E9F2A7489F93C5B20AF83AE8FB42 -:100FE000D84E398C1CFC462E053C130FED6C52DF9D -:100FF0007B8FB92C48FFAD16E2013C6F1D620B34AC -:10100000D2AE3A7E725E4A17D247BD7F32D0F1151A -:101010003379448D3C5F874F26C3296396F9248436 -:10102000827E437D514419DFD76E28093FFFDF835D -:101030001CD37924AD2326958E1BE7279E4018BE2E -:1010400010ED56D97A662804DB07E3E8FCEA54532E -:1010500040A2EBCD97183FDBCC0D9E74DA54699F0C -:10106000E34F27300F19E7A1D2F929747ED9BE18B2 -:101070002C0FF32520CCF1C5211CEE4BC7FA11BE75 -:101080001C84237DD9F87C946F0C96737DE3118EBC -:10109000F6E5233CCF7721C231BEA9D82ECF5782A7 -:1010A00070ACEF527C3ECE3717E1F9BE3908DDBE99 -:1010B000F9589FEFAB4258E0ABC4E7E37D2BB13C5E -:1010C000C1772D960B7DAB1116F96E4438D1D784BC -:1010D000B0D8D788ED26F96EC3F205BEBB115EE825 -:1010E000BB0BE164DF43580F0A08F010CDE5F13681 -:1010F00075898B4A0A70B80A7C1C49EEBEE2F6A8D4 -:10110000D2E5390AF64EB4B3988857DB5EB43BCDCE -:10111000611CD0354C7F3D5C3F7FEEFEE0BE51A4AC -:101120008F6ECDA98DE544EEA397755749309DFE8E -:10113000B36EF71C027A81E426EAF8B4BF7E60EB56 -:10114000EBE2FA6BABD2E991817F1B88DB4F1F95F5 -:101150004D785D827EB6A94A69200CBF8D8E33E33F -:101160007BE7BBBC248ECE2F26FBF80BA04F66FB83 -:101170005D7F9A02FC9297F8CA14DADFD08D2618A8 -:1011800081AA1257C714AA77D46904F5E2362A72E5 -:10119000B0DE6DD17A7B9A1DC7EC28216DFB86A14C -:1011A0003C0D2F60F6A7EB12902FCB4F86915BB3CF -:1011B00041DE829242FBF3AF21E4116133A0FDE6F0 -:1011C000C5BF84FABEFE2C4C8E9AC9F3363A91EC18 -:1011D00056754A1485395B3CCF47D1574604BC53FA -:1011E000A26979D4A3FEE7018E6E0B4C89A170CC65 -:1011F000EEE0F3D49C92B1C1AE29765A3E7F1FD95E -:101200000B68CDEF54A73A6879FC21CF5ECA06A4DB -:10121000B0CB3BD5A9C27C024D4E3A9FADEF1377C0 -:10122000232D177FDA2AC7120DFD2DC4BB53431798 -:10123000C784CE6909F49F19D7B9F265785FE98A46 -:101240008ACBEB4F9F6DB06E5827B5238FD0756555 -:101250007882924BC327657192A0437E1CD8A175FA -:101260003D0AAC73DBC67807D22FDA550243F64C41 -:1012700027AEED2AF0B18278B26C1A86F22EF88E83 -:10128000E277F41C87166F92D06B356D7991F15B24 -:10129000F66F86DFF7383F47C2AF0D7865D2D9E5E4 -:1012A00078615CAF1C5F03788DD4AE298EC9A7111D -:1012B000CFDB4C641FB555745CCAA74CAE889F3613 -:1012C000BD89F3F7D9F0EAFB37C3EB157103E3955A -:1012D000A889A82729BF8E263991F50DF417CE7E4F -:1012E000DDCEF94DA3E72CE02F36BBA89ECB89AC11 -:1012F000E7AE8E3B8BFEE27AC6C2F5B818EF413EF0 -:10130000DE2BCEF22DA0BFEC9B4C7E90B312E240C0 -:10131000B920A9899C4F5CD1C02733655709E81BC8 -:10132000328AA01F1D9317F0C33E65A85F2D90A1C0 -:10133000192865C0E390DCC0ADB4EB6CEA67289473 -:10134000FEB4AB20409BEA322DA6EB8E15F2E6AA46 -:101350004CD5CA9BB0F77DF228F8227EDBADD98C44 -:101360005FE750FFE56DCE6F7DFD48D86EF3DA2163 -:10137000DB6ED5E8C16DA9A95816ED23F1EF19C1AF -:10138000BF1B37102FC8C7E4F07EC31B7132E7DBE9 -:101390001E0FF0B9FF07C405FE4CDCC60F503FC559 -:1013A00051FD24A17E62E367F8A27FE9A7E53FC76C -:1013B00025737DEE8ABED2F1FF8E9F7F45110BF320 -:1013C000183AD9D521D3FAA1D40EA920A793E9DCE4 -:1013D0002700BE2C487795303AAA934900FC5E8AD4 -:1013E000B7A009F4AFC911003B63B1B47A409E893C -:1013F000250ED7FF8AD37B346E00B970C5A8F9409B -:10140000D493715F95DA29FF6DCE764543B99B96EB -:101410005B52E9B8F15D84979BED283FF46F085269 -:101420003148F706601F45D96383F6C37ACB7E281F -:101430006F059FE402DAFF5D67F66DA488991BE7EC -:10144000E989637C7D12F8DA338A6E5073FAF8F911 -:101450006CFE8090CF3E7972E50B79AACC437DF883 -:101460000DF42FFA8BE4DF3CC3F5A7237E60FF4623 -:10147000F0FD39FB377CBE7F07F92F8C2CFF51FB29 -:10148000DFD8B28396D7A4CAEA71EADF3986BCD521 -:10149000A9D0B28DFA9BC768D964EB54A05D1995A9 -:1014A000503BC5B7873A79B0FFB04D6065F883FD12 -:1014B000C7C956A994E96B35F6F2B103E13180F35F -:1014C00059936AC1F1A2460C8F05B97272BE228A85 -:1014D00014003BEE2C76298BB1BF2E7219EDEF3C38 -:1014E0008E2721D7A0B79ECA03BD14AFC07EDD6A88 -:1014F000237E477C5FFF508E2DE8D34F84EFE3AE11 -:10150000E57BA6D60DEED8E120A707591CA5F52648 -:101510002697651924B001F48487A82EDA3E8A88BC -:101520003F2AB8B46CE6A5995F4BC443E77FE06BF4 -:1015300019A1349C041D74BF57E69682B00FB4986D -:101540006C01B0A525436CC40265A7296005F9F8B4 -:1015500040C2755A0A6202A0FCA60D298EEDA2EBCC -:10156000387560AFDD1B86FE57792BDDD3C647C6C5 -:10157000636FBB052FBA008F0FA91B5DE047FA53BD -:10158000158C3BDC024D357AFDEA786637A93F348D -:10159000379EC2594B7A365A80DED989E80F91E1DD -:1015A000F1C8B769A9BB6E29019355CBFCD321249F -:1015B000D0A8F5AB047FBD1BEF5D104FE143DC8E7F -:1015C00050B1EC1C09F1AAD189F1E09796D40F69CA -:1015D000077FF781F5C4BDC48CFAA01CDA7B12DA50 -:1015E000F2817F1F72EF7AEC4EC0A795EE8B418F90 -:1015F0008F3F6C5729BD2A0AF726C17AFE6498BF2F -:101600008015BE9B102FC67DF0AA78BA0F068538CC -:101610008E8C837DF029F7DCD820F2564258F9AE43 -:10162000F0DD88FD88FDF07BE660A62BAC1CEAF1BE -:101630002DC6AF90D8BE969825A6FFB81DA5FA6511 -:101640003DE097BE8676D36395B683BD39E51EEF40 -:1016500006BB1D49DF88F9503C8E287784A997483E -:1016600079383DF1403CB3D71566BA5FA0F5D2EAB0 -:10167000C206985785C32E01DF89769BE2993D13F8 -:10168000FC2CE25572EC3785407F880F865BFF2289 -:10169000A27CA98D476D02594B62F87287F15722DF -:1016A000E1EB90B9B50CE67568A94C1A693FA7BC87 -:1016B00013534898F7057C07F886D2A53E818DD74D -:1016C0004BCFE1E1F177687D8D7B9AB98F9EFDEA82 -:1016D0002BA3E681FD9E0778D48CFB0AC7DF3181FE -:1016E0001FAB5775D17ACBE27B5D642CE8A92F0B39 -:1016F000FD0E888BF5FCB611E8FD5307C62BE655A9 -:101700009E2E6C1CABC167314123B968EF032E9547 -:101710003E9F37626392DF1E198FC7381E6F8307A3 -:1017200093301EF322F2CD20E331242F1EF98DECED -:101730008D7207211EF917D90D7E038CEB45FDC96B -:10174000E2C9D7B9D8BCA20C7EDE3C5F9D4EBFC4B7 -:1017500084241248D09495368CCFC684147C6E9421 -:10176000B75F19E44DE03F123D05FE8DCF9FE7784E -:101770003F54B95C85B8A1253ABC1F9C96C0E824AB -:10178000CA6FADF7EAC6FBEBB7B26EBF2CE07F7352 -:10179000FA9EF24E4A8178D53C8B7FC460E45CE0CF -:1017A000E7AD6FEE7741BF515F59C3CA5F37B74F9F -:1017B000D49E365FA16AECE9D5F246C07B8CC2F5B7 -:1017C0009B41EE3C6057293E2F06BB4AA718731673 -:1017D000BBBA88F83B208E6C1C5FD853237F09FB73 -:1017E0006AA49BE08384041E37E4F41371C348F2B7 -:1017F00025E4EA5DE0DBC2FEF837C2AB2C7ABF47D6 -:10180000C013BDF488227EAA1FAF2D91034442FE6F -:1018100040FB78E85E09FDCD60A515ED72556514B5 -:10182000C667ABF265ACAFBA5D46FB19A4FAA196E8 -:10183000CEE74F5C4F18E3B32544724FD3AC7BD651 -:1018400084285DF9EAA577FF693DC4978BCD2A8C82 -:10185000775065F166BF4746FF95F6E10E427CFA88 -:101860009E8BDC60CF043F1CF4C8286FFE376537C1 -:101870000CDBC9E3D1079BF30332D059F2F68EA3F8 -:10188000E640FF552AD0E1EDD42D2ED07751DFDE92 -:101890005F5E8EFB47AF9A8F76933AAB74DE515CF6 -:1018A0004EA70E29BE12ECF891163381B8D191756E -:1018B000A7509EBBD637B8A78DE88B2F8BF8B031D9 -:1018C000CE6C8C2FF78B2B1BE2C9821F8C7C725540 -:1018D00004FE10FA2A127F503DB630E19FD06342D9 -:1018E0007FBCC3D73975C896DB1B291E6296C88892 -:1018F00007C1976F7F73F3CF410F4751FED800FCAC -:10190000FCEDAF5E847D08592E858D23FF07E737F8 -:10191000BA4F744FCBEDA3CBD5DEE5BD6510FFF913 -:1019200035AB7BCBB07EA35D89ACD706D65BD9093E -:101930002C0E6EB43B4679F8BEEDCEBCCA7B73E18B -:10194000FD79954B03006F1962AB01FD6BD4134613 -:101950003B21E6639C674C482681F1DA79ABD8AE2F -:10196000CF4E58B0DE67738E0367FD4C14837E70D4 -:1019700002C12F7D3F2AD084E3359C5F8EF36F98A0 -:1019800008D047DC5D7E585F6A34C60F5A33587BF7 -:10199000F99268E68F4F88C775CAC221FF320ECB15 -:1019A0004D7C0DE3E2BD4F02BF35794C5170AE3036 -:1019B000D5A1EC87904BEB1413B1923E3C09FF9DEF -:1019C000406480AE17EB24D877E6DB2C39E89F3EE5 -:1019D000930074B889EE0B29BF1F3820EFDA4697C1 -:1019E00078C03D3E369C7F2EE082D4B5A817AEF479 -:1019F00055213CFCE3BF6681BC5E2F793B605E9D58 -:101A0000F3AA6E2FA4F3A9DF2DE3B9D282EBDF1E78 -:101A1000C9F669FAF349D969CB85384A9314ED06BA -:101A20003D22F0D8E1B0A07E693ACCF460D3518970 -:101A300097D93EE2055E7FEA3D07EE3304DEE97AA0 -:101A40003A613D9EBBE3703D629FF12FACE75DE8DC -:101A50002FF27A325CE80F005FC97DF3971D0AAE62 -:101A6000AB9B44BB61FE3E1E0F22EF45A1DF2CE87D -:101A70005BCFF94FD0B78ED3B7BBFDF41D17D2F6AD -:101A8000AD9E783C65903309AEB7FBBD18E40FB14D -:101A90005ECA07DD80EFBDEDCC4EB4BEEF60F872DC -:101AA00014E5C2FC847FED4A607EB271DD157C9F37 -:101AB000FE7502D34BE0DF429C6271FC94AF130AC7 -:101AC000C3B4E77E2DC5F3B780971217F93240FAF9 -:101AD000F02CC611E38AF7A212F5F255C1E30AEF22 -:101AE00099C93C8CD3D2710B34F35B1B5F12959870 -:101AF000D47FDC7F818E898903F2A59E8EF58ABD15 -:101B0000598A25BDFB620CA5A9FDE5DC2867527B3F -:101B1000C757703E6F94FF33A60622D17E6F90BDEB -:101B200087E2296CF2922E6B4E7F79389B1EA1F4CE -:101B3000CE4B4CEAAF4F064BE78989FDE83C31714B -:101B4000003A0F8B2F9F04F5B0FEF402DCE75D082E -:101B500065D0139661381EF2654F1C096CA78D1273 -:101B6000781C45CC07E21251F4BD1F256623FD25E4 -:101B700085F8CDB49C90EB9640EF0F820F7EA49D2C -:101B8000DFF7C007570CCC0741F44B56717AAF1200 -:101B90007916BB06CEB31804DDAA60DC3326778F36 -:101BA00037FBDCE956D79F6E7503D3CDBB1AEA9B92 -:101BB0002CE44BF4C38B2B5361BC579C9EE3B1F4D4 -:101BC000F99E46AE4FB229DD68FD8B8932EAAB9FA4 -:101BD00091F3500FFFC064C2F97753FDBB3D3B1C2E -:101BE000DFFB9578FAFE99CB089EC7D1F5F9195F0E -:101BF000FA25787EC3226282E7A96A23319D831E7B -:101C0000BA8DEB09CD3A6F4B0C6397357AE80EA885 -:101C1000A7FC781DF0A34D752903E9A107CF5D0F3F -:101C20003DF83DEBA14706E6BF73E6AB27C3E903EA -:101C3000C1C7625F10295F88CA23498FEF3F2E21F9 -:101C40006E3C0F2B71DA98DDDD29A19D6D3A9AEF7C -:101C5000C5B2C3864A41D8E193BB58BD3C25BC3FC1 -:101C6000F86C623CF2EFAAB6D56E459707E2477A68 -:101C7000DCE939E91A4EF5E20CD98EEB4B2863F119 -:101C800043B17EAA67674E4FE67153BA9E844C8675 -:101C90008704EA0FC0399A93EF0F628B159DDF2FEF -:101CA000F076835C2E41DC3B2E9140DA0DF5EBD7CC -:101CB0008D82F3FB388FBE7D1269F942C64108CA96 -:101CC000433CB5DF10C74A2835B4837DC83868AFB8 -:101CD000799EDD7F3F713491EF272C2415EC0A911A -:101CE0002B06E41BCD7EE244E220F6139F278AF305 -:101CF00071BDFD6A8B2261E302EB92B8DFFD651CCA -:101D0000FABF32B75BD3BAB2313F658D43C5788134 -:101D10002CBB6D33B3FBBF1FE7311155B3BE84D26B -:101D200068A26AF60F49E5F1BA72CABC21BAF6692F -:101D3000DE61BAFAF49AF374F5990D05BAF250DF40 -:101D400005BAF6D95400B4E59CE61FE9DA8F68BD00 -:101D50004C571EB5E51A5DFBD181C5BAFA318FAE7D -:101D6000D0D58F6D5BA32B9FBFFB27BAF64D3CEE02 -:101D70006BC4CBC5494C3F37294CEF34DA0B301ECE -:101D8000D964D7C723D338FE4B6227E7421CBCE98E -:101D900083FC5CC0F70BCE0B302E1E892F8C7A2C67 -:101DA00092FE343E2FE6E37DFEBCC5047250B79729 -:101DB000CAEBF9B46C7F6733ACA9398F9DA72A842D -:101DC000E5F788F315F17EEFF98AE266F155A79DF4 -:101DD000DC1A862FD292F4EF093D29F82812DE048E -:101DE0003F9E0D6F9EEF096FEF49649E761E15FCB6 -:101DF0003CDBF8DEDA24133F0FF65E93C4FC9D094A -:101E0000D1E889BB501ECF55FF8B7950FDBF3409F7 -:101E1000F7136F2CB801F4FF2EAB1BF6649FCF7B3A -:101E2000A3FA7E15DA57B3F626772ED02552FC7B1F -:101E30006D52BFF8770D8B7F47EBF0B64CC8BB21D6 -:101E40000ED7E4FC1AE3DF4D1677EE60E2DFCBA09D -:101E50000F383FE474EEA52F8F9F47DA07F908D9B2 -:101E60002FC1BEC7AEA870CE75B67D2DDDCFE6C240 -:101E7000796A2BEC9B34FB1CBABFE5FB9B28B40BA7 -:101E8000D4EEDD9184EB22FB55FAFC0CDDF7DEAAE3 -:101E90004251D83F8FCE2FB712B7CD22233DEFC18D -:101EA000F76E22D745C9102F0B1E989CFD2FD9F332 -:101EB000FF481A707F68B4AB673D9743BB5346D762 -:101EC000BF218CDF653C87EBF5BFC14F93F03C0E23 -:101ED000F1B489DA45388FEB4862F679D361B64FB1 -:101EE000DE74744E2ACA4D52D180E77083D5371DF7 -:101EF00049FDFCB58EA401FC35B1FE357CDF3B5DB0 -:101F0000CE6B8378E3C99005F12613961F59BFCF96 -:101F10004C02484F96672CE8680E6DEE04FB6C2669 -:101F2000C6BC623516D66DDE27A37E2289ACDE4F95 -:101F30006C8DE0E7C416EBED569C476FB7124AE391 -:101F40000D764C6FB752E6E9ED569A576FB7D26BE4 -:101F50000A0C764C6FB786FAA618EC98DE6EE5345C -:101F60005F66B0637ABB356A8BDE6E8D0EE8EDD6A8 -:101F70009847D718EC98DE6E9DBF7B83AE3E3F78C6 -:101F8000ABAE7EFCBE9FE9CA859D0FEADA2FDBFF70 -:101F900034E6DF4C3CB45DD76E52D7AF75ED28C246 -:101FA0003B214F7B099284900B4F3CA5AB5FC2FD58 -:101FB000B48B7A7EAFEB87B4B27C6B3FFD0FE8F554 -:101FC00011F15AC0395148CF4BE994AE7501C91D82 -:101FD000A4CD96EFDE5904F3F8E4FD4BF6413FCB78 -:101FE000B6E8F3B49707F4E57A322C16F4433DE5EE -:101FF0008B00E5939590BFADD16B2B498313F321F3 -:1020000006C967CBF6CF2598F7E9F774427EBA5830 -:10201000A7E0370FE737313FB1DE95D4EF0BAA7D4C -:10202000EBF4D0FFD83EB2CB027C5BBD5B220F4A03 -:10203000FDD753D37ED7E6F430EB32AEC3E877BAA0 -:1020400093F5E754D3653BC6F54FBE29BB597C5089 -:102050002F876BF6B378FE9A27248CAF19F121FCF9 -:10206000D2487891FD6C9F509F4802018DFCA91CBD -:102070001FD654BDFC9D847FC07C1E960390171410 -:10208000A5461BF9AD2848FAE33926572FA7463C49 -:102090003BDC43C2F2954AFF83795413762E65E404 -:1020A0002B23DEEB76DF6501BD78AE785F64C0BBC5 -:1020B000383F28A1ABB584C9831378A5FBF2A5C925 -:1020C0004991F7ADAB9325FDF9F2D9F7ADAB93BFCD -:1020D000DFB8C9BAE401F6ADDD102FA37EA5315EED -:1020E000D63F3EB6F72BC989716816FFF2BA6D2C40 -:1020F0005FC5602773537576B277DFFB8114680282 -:1021000039767A6E83F9D43A3D2D007FE4F4DCAE63 -:102110005D6F13C50BDECFA1766A6718FFF0E5642B -:10212000E11795635C6453096B6F6CB7335941BC1D -:10213000772415A5A2DF79349FD94F47D1807EE758 -:102140009DFC3CE736382F1CD197C7733B3F57A106 -:1021500062E701BA6D3297A76AF37CEF498EC3F14B -:102160009C939EEA847CE72697C925A9E03F9BF0D3 -:102170005C74A3C75EBA2B8FBD97A87B8FDD3B92A3 -:1021800001DFE0CFDB95AFB57CFB32C525F41B69E1 -:102190009D2F27337FD74C3C36D0BBE23CD7FC4148 -:1021A000BE0DF4AD22B95DE1F238CD3C4F6A0A3F75 -:1021B000CF955DEC7CB757CECF922755E7F4BE9410 -:1021C000ACF117C4B9EE954ECFCB404F9FE2B7822A -:1021D0007FE9B385DFFFFE89D3F156BE3EEA682270 -:1021E0001FE1F8F2A0E2276F25635CCE8FF98A37F2 -:1021F000C8EE13109F1B6CBCEA6872BFB8DC512D8F -:102200001F1AE58FFA9FC763E17C22768882DB097B -:10221000C59D0BFCDF0CFF9E84F1D513F07EBFFC47 -:1022200053359EE7D3AA03E6D38A7EE6C679BA93EE -:1022300059DEDF17003DA35C1B654D3FCEB3F44371 -:10224000F194DB601F14FEFEC1F0E73EC18209E796 -:1022500016D78C4AE9E73F46A50CE03F9E393C2A59 -:1022600016CE9345DCCAD8CEE64BC8D0DE8F698E39 -:10227000D38FBFB9809513F9B8CB6319DFE7F2B2FA -:10228000C80314716BDB4CE281FB0E3FE3F9D9A26A -:102290009FDC1407B68F8B9F929B5208E76912EE62 -:1022A0002B37C749BAFDE5F1E4925C58CF30DE7FA9 -:1022B0006E0AE3D36DC3587CC69807F9196FFF59AE -:1022C000F214849460A3019F16590E8BC7B1296C38 -:1022D000FEC76359BF227E56752FBBDF25E26622FB -:1022E0000E483D83B762A85E39D6622610D75A2AB7 -:1022F000DB37031FF6DE9FE3E7EA2EFA1FD8CBCACF -:10230000BC72CC3FFA57EF6F013E63E2FBDBCBE9D7 -:1023100029BDF6D27D8EF7B86632FC0CEEBCBD2B23 -:102320009AF16D8FC38EF16C63BB6A4E9F161EA728 -:10233000007D0D76235E260DE1EC4735C7FB99C382 -:10234000560FFA31A5D198CF21CE3F14CA9FB1F1D3 -:102350009806EE0768F3A567C07DA2DEF30F95E04F -:102360007B09763BBEA7A824E8802BA18A5B82FC70 -:10237000B22E4BD7A61498EF45921BEE0FA454B87B -:102380003A5212E11EA18A62B6399B388BA13EDF18 -:1023900084F57197BB369B21EF5A2570924DCC7412 -:1023A0001C071DE78E946C5C7F8B7F6E470A6D1750 -:1023B000ABF6906179A0475C3352418EE7B1FC7572 -:1023C000E3FAD6A730BCD937D17D03E0430D9F0790 -:1023D000BE3E85E501513D7313D0A34425BBD8BD56 -:1023E0002896870A69D6982FE866F9D231906F94BB -:1023F000C3F40CD4DF15377523C88F902F99E31BD6 -:10240000F85E9B0F7F07C77782413E053EE9008D4E -:10241000900FA1CC24C8D7B32BC2CFF7314EE77AA7 -:1024200067F93D30EEECC98D98E74EBEF9EE3BB949 -:10243000089C5E2627F47D027188A844A67FA354D9 -:1024400015F531714998676A53DD35508EB25FE0FA -:1024500092C1EE59F979E1121351A8BC4DE5FD780E -:10246000E611E9C35C166765FA55211F0AB9903970 -:10247000728AC07EB23FEA17B5C4D0F54CB51FC012 -:1024800073C4A8E10D2570AFE0C545AC8F9F45C86A -:10249000DB3FCEF558BCEC4D35814F4F8EBDFA4237 -:1024A00006D2F93CB8A179DBA6C3AFEEBB88C7CF93 -:1024B000215FDC7FF8554FDE3F9F5FFED2FD875FD7 -:1024C00085FCF27F9EFFDD12E8F1E394B160DE4609 -:1024D000FE17FAEC90EC3D7423C5FF1594A97C051A -:1024E00000155281F466F94397733CFBBFA678B69A -:1024F000F5E1F98AF6FD88BF43663A6F3ABE790A7C -:1025000043B5F927B13C1F2380FD5F696B9D0EFE2B -:102510004DB7A5671C8CDBFDDC5F33FD549F1CFEB3 -:10252000E92907A1FC7744E971C0F313EBDE707869 -:10253000E87A0FAF93F1FE1BDE4BD6E4039DE07CFF -:10254000353DB5FC08F0D5A2F5DF1669FD6CE24B10 -:1025500042BBBB3C20C31DDF5EFDB7F2D118CE7479 -:10256000ACBCAA2D415716F6789535FC3DF1CC54FC -:1025700046F7E58F6FB3403EFCF454EF1730FE0989 -:102580009E6F70629703F757623E8B1FCFB7C07E76 -:10259000F248BB950481EF954E33C1389567A64448 -:1025A000F9D6CBF9D038CF97F6C4607F4BEF953191 -:1025B0008E5449C7F251BC7ADB97B3FDAD611D4B18 -:1025C0000FAB33405F2DBD45227E95B55F47E9E6F1 -:1025D000F5DD8CE72BC6751AEDCB69B2CE027AC455 -:1025E000685F961077F364B05BADFAE7CBDA6FC340 -:1025F0007E979DE53C262195DB9B2232F1BB1C8812 -:10260000330FC37CC148F6E6C47A26941FAFB721C6 -:10261000FC74BD0BE11150A614CF2B7777BC948EC0 -:1026200062DD590476286AFF54DB35A4CF7F56B6A5 -:10263000CD0D3EA4025FEAF3212B389E85FFBC8CB2 -:10264000DF33389BFF5C01EB1C201FB26290F990D6 -:1026500027F78DB7C1F3C2547E3E3591E203ED6F8B -:10266000DE6B2A39BBFD8D849748EFAD82EF1C8469 -:10267000C1B3909B23DC8E2CD93167F3103A81A62D -:10268000E73ECAEA42BE647108714E25A76EEE8429 -:10269000F5CBC410FFF3933789867F8DFCB98CB8D6 -:1026A00099DDB1B3F76C3C2ED1CB97EDB7235E0526 -:1026B0001FC18D02532AC060AAA9B8FF7703FA7D13 -:1026C0001FA0555FFEDCDC95057A6399215EF0B9A9 -:1026D000147EFFF5C3D4616CFDAA6706E4452C2582 -:1026E000E59B595CBD159F9F505A5FBA11E479076D -:1026F00093A755CF3EF10CE8A915FF79AF13F4D499 -:10270000DF94D66418AFF6914D4ED0EB2714BF136B -:10271000DEFF5B400E7B5F777BAA24F2E2ED901731 -:1027200056872C0602E69F057AF2BF1F31BB208E2A -:102730005AFFA83568A5F8A8DBC5F048CB4759F97A -:1027400066C457FD6EBD1CAEF8D5BDC92AEEE7FDC7 -:10275000E91C7FE9A0AAEB7698317FB4EE4DD90D44 -:10276000C3D4931E5C9FF17D984788D2ADBE4DAE19 -:10277000B4C4F6AFA71E8F05E4AC7E17A353BDC14A -:10278000CFACE17AD9C8EF3F1372CFF99CE205E3F1 -:1027900061229F9504987E6E7AECFE7147E9BC3EFB -:1027A000DDF1AA53CAEBE377025997145F27DBAA3E -:1027B00016419E41243EFF9CCB45AFDEE77646DDC9 -:1027C0004D2706BE7F3B83B5E6A0F3428A8FDA6DC4 -:1027D00066B79F3EAE7D42F6D8C14F7ADB8ADF777F -:1027E00058F9C48B6F5D40E7B772A73971265B86D5 -:1027F0001DF4B3A0533DF077411F5D563CFDA2058B -:10280000F220E1F9BAF83EFAACDCD96181BC4A2386 -:102810001EA7B67558987C19E8D4767406D8E5A634 -:10282000C7CE58800FFEB64722E0421ADFAFD9F676 -:10283000A213F407E009EC87A0572FFDFAD12D3839 -:10284000EBF713B09D0BCE6922D1EF5A984B12F2E1 -:10285000F793BFA7E3D7BC6375C3FA6B9EBCD609D9 -:10286000EBF84869607CFEF34DC9608F6BCCFE6469 -:102870001742F6BC66EB8F91FF96BDFEE364827A49 -:10288000D39306F24BD79906EB5BFAF015B8BE6A04 -:10289000E245FEABF9B95C0E7EE269859486F3F3FE -:1028A000D3D3989C7CB4DD8A9B828F2C847D87E374 -:1028B000CF32CBE323ABD10FF9315F2BD5C4583ED8 -:1028C0006D6374EA4E357139637AAC9EB7AADF71D5 -:1028D00033EAB18F333D2920EF140FFA78EAEBD3B6 -:1028E00053B8FEC3EFA5E07B94EFA6C27368DF691F -:1028F000F6448DD3BDC7F35AD9F8D7F1F1E9BCA39B -:10290000212EF751B27EFF2AE02569220E463A8930 -:1029100096BF22C9FD8E5B90AFBE7C93E995BAC08D -:102920009C52ACEF340753A03ED071B9847A81FA3F -:1029300017E1E47A8799CBB5BE9ECE5391B4F8DD0A -:10294000C3EEC555DF43DB69FC903EBEB1F43DCF1D -:10295000EE934F915FB1CCE09F0968D40B49697A3F -:10296000FB27DE270F2785BD87D5A70FFC88B75A21 -:1029700073E0970F821CBF6DC57B86B54F98F17BC6 -:10298000399F3CBEF7AD6B28BF7FD226E457AF67B7 -:102990008DF25BF3D415249CFC7E92584EC2CA2F54 -:1029A0007D1E567E1359FEFEFFB69E5D1641CF5E1C -:1029B0009CA6D7B3D49F88BD90163FFEF5CAA1B898 -:1029C000CF32E055E0D3A8370FA5AA885FA3DEA4D5 -:1029D0007F6F120D1E05FE045FAEF8CD2A1CA7976F -:1029E0007F057F0AFEEDE54FE37AF57834D62B704C -:1029F000E7A8B08FEEE60D747F0DE7AECFC978EE95 -:102A0000DAADF638E3212ECBF36EBA5DBC1CC7CA33 -:102A10003D4996CDA03FC4F39E289687D05DDEE366 -:102A20008CD3F8F547DB6527E4D57705C2E74B6023 -:102A3000264512DC128D54DFC8BF5B63CFF2C1BEE6 -:102A4000AC959DF72C69BCCA09FE74777BCEEC79F6 -:102A5000E0C7EF97D1A7EA8EE6F9557E8F9246F14F -:102A60005AC5964C4E10FF7DE06757B5AF9C099B49 -:102A7000C6252D7A7C54DB2FC7F3ACEA7BCC7D7C5A -:102A800041C0DF0958C0CFAA7958FF7C05E4550141 -:102A90007D0C7CE4053E0A730FA359F0513EC967D3 -:102AA000FB647E5EC5F5DA74396FF63CC85FDCC73F -:102AB000EE499C6C97C96658EFE3FCFCCA9F84FC06 -:102AC0005947F9581BE7FC14F86C5464FBFDE96F97 -:102AD0000F17DD489BD43EF3EEB88728FCF499B776 -:102AE00047FE01CACFFE35EB5DD2BFFDD43D5F2D61 -:102AF000C43CCA3D5602FBA2EE3D2F67DD08E5DF70 -:102B00005BDDA8FF37B0FDB17F8F03ED7A7726F349 -:102B1000FF9A9E3B33AE0BEDD346A4D7D369EC9E10 -:102B2000EAC9F6BFBF2F413E5D3B5D15D85DBEEFE4 -:102B3000AAFF7D14EEAFBB9F3BA3DB57FEABEBA917 -:102B4000E3F795BA1D641EDC2FEE8E63F73BEBFFB7 -:102B500030E917705F71D5AE0E4B15AD9FFAC76F98 -:102B6000C781BEE97E8AF913D4BFDD0A2EF59E0720 -:102B70000EB49829FD3E079F6F0821573D682F83AB -:102B80007B18FDF1C2F0D04DF100EBA278A9013D18 -:102B900019091F7FF9B7C5C7170B61FCDAF689045D -:102BA000E2E97D78913CECB903F32EE8FAD9F33DE4 -:102BB00067C6817F74B6F59E4A63F765FEAFAC3792 -:102BC0006EC8BFEB7A19BF3F90A6E23C8D7CDF9FB9 -:102BD000AF9FBD1ECB4F3ADC38DF41CA7BFE90FF72 -:102BE0005BFC3DFBDF76BD67A3F77E4E6F870BCEA8 -:102BF00053BA9FFB368B9CC3BAEBFE3F5D77AF9F0A -:102C00006372DB26D0F9BD430257944891F3381F15 -:102C10001AA2DF47CCE27EC4ACC46AF41F667958BE -:102C20007CA58914EC837B6A7E8F8CE70E984C43DD -:102C3000F1D079797E00F3B614FF88FB208FEBCAC0 -:102C4000556EF69D2FFDFE6A56726929F86F071BB7 -:102C5000E9BC68BB830E93AB892E61B647467F8F74 -:102C600042F4F3FE32E552CC0B995DACDF675C6356 -:102C7000D8375C354F5F7F25D99E04F97757D698B2 -:102C8000315FE80A43FBB5435CB8CEAB48C32616B8 -:102C90009F39373CBDCAF1D41F0F03E3AD1F9EF827 -:102CA0007E127379D4FE78B37AD9FED24A2BB8BF9C -:102CB000C5F3E4D60C0A9F84EF3BAD7C68815FAB23 -:102CC000877DAF53D32FE245E0FD5CF12DE864C46E -:102CD000BBC0AFC09B910E5BE14C42E38FF74191CB -:102CE00047E225DA7CCB59BD7EA31DF1F8DA0E76DA -:102CF0005FE1B5E2AA967C283F2EA1BF767AF278F2 -:102D000062A3EB3D6826BBD9FD2F8FEA2AEACB6789 -:102D1000918A5FC67305C827D4EE4B219F50BB2E06 -:102D2000C827D496219F50DB1EF209B5F5904FA815 -:102D3000AD877C426D19F209B5ED219F505B867C11 -:102D4000426D7BC827D496219F50DB1EF209B5F552 -:102D5000904FA8AD877C426D19F209B5ED219F50C7 -:102D60005B0FF984DA7AC827D496219F50DB1EF2D4 -:102D700008B5F59047A8AD87BC416D19F205B5EDD2 -:102D80002F0E3DAF2B97905775EDA7DADED095A7A4 -:102D9000BBDED5B5FF61EA315DFD25EA27BA7A4190 -:102DA000FF4B734FE99EC39985BF08F631ECAFCC5A -:102DB000FD775D3F0A29C738B3853420B441FC96BE -:102DC000C268D286D04EC51CE0F491DE11E9C0AFD6 -:102DD0005BFD9B81B90E4E3A9305FAFFB5C9735955 -:102DE000FC819F13CC867FAA948963BEC9807DAD88 -:102DF00038F7748664121C4FF930242174856248B8 -:102E00003081F261280A617C28019F2784E2102624 -:102E100086D2F17952280D61722807614A281B6118 -:102E20006A680CC2B4D068844342E3F1BDF4503EFA -:102E3000C28CD085F83C3334096156682A3E1F1A8B -:102E40002A41A8862E45981DBA04E1B0D05C6C9743 -:102E5000139A837078683E3E1F11BA1AE1C8501564 -:102E6000C251A14A84B9A19508478796233C2F7483 -:102E70002DBE3726B41A615EE8467C3E36B416E1B4 -:102E8000B85013C2F3438D08DDA1DBB05D7EE816B8 -:102E90008405A1BBF1F9F8D05D0827841EC2E7853F -:102EA000A1071016857E817062681BC2E2D06F1088 -:102EB0004E0A3D86F082D0D3F8DE85A19D08278793 -:102EC000FE80CF2F0AFD0EE10F427BF1F9C5A10E66 -:102ED000849ED0ABF8BC24B41FE194D01BF87C6A6C -:102EE000E87584D342EFE2F3E9A1B711CE081D43A0 -:102EF000F8C3D05184A5A14F105E12FA1BC21F85E2 -:102F00004EE17B9786BE403833F4777C5E16FA0A32 -:102F100061EF7E7F72A47B895ED37710D7B2C70F33 -:102F2000EA3B5F846CD19D4BDD1FE3443D397B1D43 -:102F3000CB23D95C726A1AFAB5ABAD2AFFBEA641A3 -:102F4000AF7E6307FF6113D4A4B13E200F7001E789 -:102F5000DFD78AF72681BFB4B9A0AB16E221B767E5 -:102F6000775500BC339DC5573773787B3A3BCFAC60 -:102F700018E9C272C5EA11787E451207B78ED78666 -:102F8000B0F744FBBA4C5EB6F764E1BD8041F6335E -:102F9000D87667CB8FBA2EDDBB1DE5BCDFFDBC410B -:102FA000BFFFEBF4C27FE9FDA7067AFF08A7972BC6 -:102FB000A3FC199CA7E21907F55336A4C989B49F4D -:102FC000CA16C90576B26A63FE0CA05F01F1603CC7 -:102FD000714184BCAE7739FD16379809C41517AB1B -:102FE00004E3B98B77B13C5F88839651BEA8E17C3E -:102FF000B1EA969D1670416B1A96B1FCA3008B3313 -:10300000D9E87FC0CF2B5AE660FED1CA47F5F1A7B9 -:103010005A88EBC8708EAC7F5ECFE34CC678A53182 -:10302000BEF4663A8FFBBA59DE11913370BDA7E941 -:103030007A219FC37BBDC306FA9FE201CF49C4FA40 -:1030400045BC52E081F4BFCF8079A127F78DC03C09 -:10305000B593AA9A02EDBC549C3AED90FFE09D080E -:10306000CF29FE309FA4A73106F3918E527DAE4248 -:10307000E293CB3B11BE9FD6F54E26E1DF6FD49F86 -:103080001BD85A30FFBAD24C07A6ED2A1F49C0FB05 -:103090008FB4BF71BB211EF98819F381FC644D2ADE -:1030A00029EE7FAE50BEC98CFCB178771CCB0FF3F4 -:1030B0007BDE847C7D418FA31B7366405ED1E2E69C -:1030C000EC7C0CBBED36A39F27CE4B059DFAE74564 -:1030D00097C7C2F7115734BF8EF4A4F4D2D5D7B630 -:1030E0007C81F70728BD8E47A0D7F181E8159DC1E7 -:1030F000E3816E912796177B1554AE4B4039ADD8BE -:10310000101CD1A0E147639C9E64D8F1BEA3C827E0 -:103110002E1DC2E841147732D0F5544B21D2CB4852 -:10312000A7D27F54213DC83B0EFCDEEE821CB2E8E4 -:1031300032FA7C118F5B2E68BA04FDE79C0CE6D74F -:10314000BFB61E722D09797DBD8D78A8F3FCC67AB5 -:103150001796FFB23E15CB7F5DAF227C7B7D2EC2E2 -:10316000E31696CF23E4893200E6D58DCE60723423 -:103170003A43ECABAE4B85B874E93FDE2884FC9E45 -:10318000247FD2ACE999E877EBF234E65DAECFC3A9 -:10319000E832F33CAF5B24377C476571F985BAF6BA -:1031A00024777C5F19EC07CF1B59DC1C87DF6FBBD2 -:1031B0007A6682AEFD95CDE9BA7249868AFA754E75 -:1031C000698EEEF935156374E54AFEBB09C4166DC8 -:1031D000D29E4F51CAB23C6F176BFB65C3C4941BA0 -:1031E000E8F85F1E3063BD911EC72D7EDC8FFBB7F4 -:1031F0005BDD60874EC03D325A3EF11719F5DD099F -:1032000033F1BBA8EA3E21918D0089C2E4E9F421A3 -:10321000264FA5FF9009ECC3C9AFAD787E57B545E1 -:10322000227EB843D543314FC7BDEE312BAE7BC9AB -:10323000169978F1BE92DA06E7D6D73D32CA0DE785 -:10324000960B728299706FAFE7B751EEEDB4B6AAE4 -:103250008BBD7F82EEAFE3202F492AC0F383CFCA14 -:103260005AAB4D906F201F480239FDEC2919E32914 -:10327000CB57FFA5C8057AEDA5B6B78AE938C75B75 -:10328000651CF79347ADDB6494774F0A7CD7B56F25 -:10329000DD018C33BC945ABE2283F2C1C7D5817143 -:1032A000A877D6B1F8767FFCD0F502BD815F357A7C -:1032B000ACCF6EB17332AA7CD2403F5499DD786EA8 -:1032C0007ABCC58CE77954FFE3F9FFF1D60413D338 -:1032D0003F4F21DF2D56548B76DCC52DB287FD2E56 -:1032E000846A81F992BB642F99086596AFE06F9666 -:1032F000BCECBC464FDF6B574FC4FBC5C6FC290175 -:103300003FA732E5D59C03AD788E9DCF92095D8AAB -:10331000367F5CC457482AEB5F7CC7A776D8FD7719 -:103320004CA6F0A4877D72F0F40E07EAC74F4DCF8C -:1033300017DD40E12765FE0F154A9706D97B5F062A -:10334000E4EF985AB64A782E72EC0E388FFFF809DF -:10335000B31BC590E76BADF8F5F2A103E507C10C0F -:10336000D8F97230594A85AFF212CCDF984FDA782B -:103370007C20C0CEFF6112143FAE5A768E75ACD061 -:10338000712BDCC3AD32DCDB3DC6EF2D3C96C1FCBE -:1033900021619F3FE2E52A13934FB2877D7F11F2AF -:1033A0005E866BECA9D0A7BB3386A1DEE8B5ABA4E3 -:1033B0000DF54A35FF3E70EDA356764F47252E900A -:1033C000C7E584CB1FC8337D6F85E589FB809D975A -:1033D000914EB4731F9B03D59DD9F0FEB68DF1F8C5 -:1033E000BED91D00F9E576C0461507E88F6584CD86 -:1033F0006F55AB14086AE214E2F73808D8058DBEA1 -:10340000E96F0FF4766029B7774B8921DFA7556FF5 -:1034100097CA631CB8AE15AD3CEFB9775E32F98E32 -:10342000E2ACDA1B786916CE5B7207C2CC6319E98D -:1034300009C27780573DCEEE0319E7655CC760E7A8 -:1034400059ED9E330DBE27DC3BAE61DE02DF042E5C -:103450002869E820F05EED67F8AC6E97905EFFC5D6 -:10346000FD2A71CF4ED07D19299F057A6DD93D7403 -:103470005F98DDC707BDF67A6700FDA54F48ABD35F -:103480004EF9BF76CBCE2B27C17B0FBF6E01FEAEB0 -:10349000880F8E30C5C14FD2DC7847E94561ECBB5F -:1034A000C19E7F5FF8213CCE84EF517C2CDD2163EF -:1034B0005E83A61D3FDFF7337EF613CC23AA795334 -:1034C0007637D1A735F0733E05E73E5F819FFFED6C -:1034D000791BFD989CCC81FD18A37EE9E7C718EC09 -:1034E00027DC9B007BD993C4F2C0BF543CB1F1A848 -:1034F000970D7A37A900BF3B2AF46E35B77B629CE3 -:10350000A560EF68F9C32D4F3B21FEF05FF73C9DAE -:103510008C7914605FF2FAECCBF5556CBCEB9F8DA7 -:10352000C2BCA5CFCA3AC781DF57F1F3979DDAEF46 -:103530009AAE48F59664827EE6F67095BC2DCB0572 -:10354000F6D0173EAFA2DFFE2BD23A1D6759A74334 -:10355000BFCEC5B04ECD7D902ABECE0F9AD9FA8E81 -:10356000B5B0F52EE9B74E3F9E835CFF0BABDB8F0A -:103570007E4610EDF8899D3281FB67BD7E86C1EEE7 -:103580009F26AD5B011FABD6FCF57D85F2C5F291A0 -:10359000143F940F2AEEB2A29D5FFE5B76FEF9B156 -:1035A00054928207F02F049D6BE9F315D43F00FF7E -:1035B000A26F1EBD767F39E0B1D7EE0F127F753C4A -:1035C0000E55D7FE32FE5E94E461F99075E23B3011 -:1035D000BB0DDF81514107B07BF236A0530651D9B4 -:1035E0003E511F4FFDEF115F2C5C83FCDF3352FB1C -:1035F000BDDEFAE8A019F27D7B764AE817ADBAAED7 -:10360000C4594220BF95C5C1366732FB25793C9825 -:10361000F762A5748DA6E3DD92A9B2E7AA8BE575E2 -:103620003F4CF0BB3362BEC6E7101FB781FDB39BB2 -:10363000D0FE19D7BF3B93F9CBAB6413FAD3B516C1 -:10364000E65777F3EF3EDCC7EBEFCB64FEF5C399AB -:103650002C9EDF0D7E249C4F5F64C5DFEB21641A36 -:10366000C6C915C2F84F117873299FF7CA37FACB2C -:103670003D1980A785A4D30CF49C553C47857B035A -:10368000EF27DBF03B4AF4AF1CFA99CFFB396866B1 -:10369000F704DE8731E8BAE6F378F2FBF019503A26 -:1036A000FEFB6916F463FDCF59D14FB8399AC5FBBB -:1036B0004862AC027C7E0DD7530B265B3D703E30DA -:1036C0007FF2CDE500697F7E42F15561EBD9944FE1 -:1036D000C76934313BDF184FF0BE24D9D85508F8FC -:1036E0003B9FBAC590274F57BFEBBB8481F8487FFB -:1036F0004FA116E20A1710C660C5885F5DB9D6C231 -:10370000EA0F661E99754F06217F866C26B03380BE -:1037100023E08BCA58DCE7CE863CFE78800AF2DBD9 -:10372000650AF19B186CB6E37788585EBF3807B915 -:10373000A2980463E9FA82FBF5F728AE0A9A82A3FD -:10374000E07C47097600FE4C36D5ECA2E394974A1C -:103750000580F7DA0D839BEFD1CC8F67DD33999627 -:10376000E17B5730CFB512E6F3CCA7420F7CBA50BD -:10377000212FC8058C7EC087F5F1AA1FDBAD667CC2 -:103780002EEE6F08BAE4D3EEB5F89DCFE747FB699C -:1037900076C2FB96F07193CF32C53E8FF9692BB993 -:1037A000DCAE147CF7B85E5E63B354F63D35F007CB -:1037B00029DEE6731889EFED59AC7F7B16E3FB1029 -:1037C00097C7C18EB7CA4A82B8EEE7AC484731EE18 -:1037D0006C0EA3B358FEB29887E0DF6AD280F93747 -:1037E000D53C1E63A29A04F3745B7F81F9FDC63C4D -:1037F00021EA2061DED98A1DC6E79A788EACD34BC8 -:1038000018E7942C3D4B607ED20FA2DCC0EFF32D65 -:103810006D180F30B633B74A28E7E666EA4F49FC21 -:103820007C8B96AD2D12FEBEC3FC8C9EB1F8BD7292 -:10383000EE575773BA52ED3D03EE0155833F85E7CE -:103840005FFC3B515B981FA970FF77718BDECF98AF -:10385000BF51E36732A0BB576F35E4879BB9BF7197 -:10386000C4D23316F4BDF19EFD11139BBF3F996086 -:103870007EA4B867AF707F52F0537A9659773E2690 -:10388000EE7356809E62DF3B30E453D9F1BB2B15BB -:1038900012FF5E258F2B9EA4FE267E57E67014DA5B -:1038A0002D1167EC2E71F84DB1F0394B565E107B3F -:1038B000FD2CF0332B9C1605E01953178E7383DC17 -:1038C000E9C8CEEE8BE36E2E19BF05F286E66CCD0D -:1038D0009D6DCBC4530E7E1F69EC6B90CF7BF93787 -:1038E00074FE581E37DB43F747DD2FF62CB4511515 -:1038F000BD2CEBFCD90AB5E7DDF7F66C85F2DAAC46 -:103900006256BEBD270BBE21BC76EB64566E14FD1D -:103910004D9E0D79F0DD0FB0F295B4DE0F7E2EBF17 -:1039200007547181847A762DB73F227E54617A9E46 -:10393000C129EC773ECED66E4356F9DACC24F8DEB8 -:10394000E771FC3D8116D5B316ECF5FA0C6F6516E0 -:10395000ECA3E6487E0BDC8B7F333092DBAFB0BF4D -:103960007BB13693E5096F1C5A8EEF0B7CD17E56E6 -:1039700064159E7B3FF1FDFBB9F69F99CF91A16C39 -:103980007D9A7ED6FD33FD4C51F5F311FE99F8CEAC -:10399000DCBE6CCF16E877E54D6C3F4C8EDB75F7DF -:1039A000FF4F353C3B12ECFEA9C7AD09C0872B9FEA -:1039B000FC5D5635F87FDC1FFAA4E36D0BE47DD780 -:1039C00085D87771EA43EC3B3975BB3A2C33F2204A -:1039D0008FB5C3325533BFDABEDFB9522ED3F831BB -:1039E0003FCF12F9DAEC771D573EF937FC9EE04ADB -:1039F00053DB8790E74B2E607134E33A37F1F7DE03 -:103A00008773FF30F1825F70FDFB558E673BAC73AF -:103A10006316C1F67284EF767DCAFBAB88667ABC0A -:103A2000AAC8615329BE0BDFF43641DE69F5C3D95C -:103A300005329DC7F68C298F037F448E6FF6B0F850 -:103A4000663B8B6F56C4775E478D14F9686BC59DD6 -:103A500036BACFBBF47ED27BDF0FE286A556213F7C -:103A6000D7CE9E96C1E265507E256BD59D203FFB4B -:103A7000F8EFB32D9838361AE4BC2B3BC6E4A2F21B -:103A8000FF747AE547308F05132F9A01CF4BAC8E28 -:103A900091952C3E8EFCF1747AF9F3500FED21EEE6 -:103AA000E1B50493AEA2EBF0BE2263DEB4775C8C8A -:103AB00037DC3D9520B7571F65313F6D9F89CEB3E9 -:103AC000A06F1E627CEA985DD70971AB0D69F9E0C1 -:103AD00047BB324A3ECC4AEA1BDF95E17D03CA620E -:103AE0007CBADC71F07CB0F3E8E4F4F810E846FB53 -:103AF000299F2CC397127AF5FA65D36274E5CB67D8 -:103B000026108F366E7A79BAAE3CAF2247D7FE9A2E -:103B1000256374F565D6CE090DE7E0EFD73B1EC5EA -:103B2000FCDEC3EDA7DF9A0F7EEC0ED92DD1F52C6C -:103B30007FEE91B720FFFA24FC0449018B8BB1EF93 -:103B400035F2F318C5A3E8CE63F63F6D01BF5D13F0 -:103B5000E737DCCB3B80717CE3798CC817FF67CFFC -:103B6000632C43F9BEB8F7F73C3F7D89AE8C4CDD42 -:103B7000DD81F469DACFF2989BA8DF02DF13FBE165 -:103B80002E6B00BEE1FED9EF8E5A54CDB94C7DA804 -:103B9000117F5777EAEEA3786EF3AB2CA6B7EBDA7A -:103BA000BFB0C03DA91FB6AF46799E41F5572CE581 -:103BB0009BCE0E327617C493B31D9887B3B2F91219 -:103BC0008C53C786E623AC6DBD04FB5B159A8BE571 -:103BD0003AFE7BBEFBA23B67801DDEF74C1CEE0766 -:103BE0005F9383231F827EAC0ED40F65E90B368072 -:103BF0009FB02FDA9F772D1DAFEC3F7F8879E87556 -:103C0000BB248C9B96C9649F04F9F7A128ECAF4CA8 -:103C1000FEF384D5F4F9A553995D2D031F87D6CB08 -:103C2000458E5BF17BD2117E27AD6028D32BE62E2B -:103C300036EFE9A139D89FA82F1E3A4CF7DD18734B -:103C4000D20E65B1BD6F3DE62E09E18F426310D6FD -:103C5000EF9AA340FEF92BB9BF48043CD1F6F87D9A -:103C6000B0FEFA78622C09A3B704B4723D3C1FF48D -:103C7000309CD3677B660D4D82DF23EC526CA047EE -:103C8000ED3617F82FB38AF3D56ACDBAE4E7AFC69D -:103C90007B10D6C41E33F803F329D4EAED4511ECAA -:103CA000CCE5434DDC7F6EC4F50A7B448EFF18CF14 -:103CB000B517F2F88090A792A1261D5E3A25261727 -:103CC000FEDFB27381D26C6F35CCB7B384CC7B0A84 -:103CD000F5686716DC47FFBEE64FE96B03FA3B95D4 -:103CE0002E02718C95BDF367F27CB6F95FCDE7FFCC -:103CF0009A4C7CC017AF5D7C71A787CEABE3C6F151 -:103D0000E3C12E88F1D60D65F987C4D5F30DE61B06 -:103D1000EE895121AE5F06671E13FAFC79C847840D -:103D2000F861FD1EEB76F8406ABD93EEEFED90175B -:103D3000181504BEEDF8639402F663EC70EFBAA1B7 -:103D4000982F386A1A7CC7C7D36E5508FA419E9FD0 -:103D5000C2F348F33D9BFE12F268E4336F33933FA6 -:103D60002F97C34ACEB78BB91C562AEE58388F59B5 -:103D70007440C67B918BD7496377417C4075E03DA9 -:103D80007D218742DECCC097E3813F195FD686E272 -:103D9000B87C67F37E991C94C92CDFAE6C4C1CEE8A -:103DA0009FEB4209D84EC8AB90D3CDD9DEC761DDB9 -:103DB000654D54BEE938DE0D6913405EFAF8C4E281 -:103DC000027EA27C925AADE183A68EAF14E013F37B -:103DD0006409F9C44AE1540D1F95F7FA27AE19C9D1 -:103DE000741EB33666E3F79445FDCEA1C24F191C8D -:103DF000BF6FE5FCB5D81E1C017EADB921CA0DDF31 -:103E0000913F99A8A21E5B738B843F4EB8C65C3E5F -:103E100015FC8B350F4818DF03BF03F44FD1A10603 -:103E20008BF61CE4EAD0383CAF9E1B1A8E707B8662 -:103E3000F78F8087CAD0951C8FE3C29EF77DD9701B -:103E400033C6D5BE0C58DDEC3B63FAF85DA1C78DD7 -:103E5000E77FE60366B24D85B89B57C6F3BD4CE2DB -:103E6000BA5B62F13B88E789F89B38A71371382B5E -:103E70007C0F5763474F2BAD59B00FE9178F2B615C -:103E800076FFD31D66766FABE3CF45265AFF71B63A -:103E900007E3722FA57ADF86F5ACB82CF0A49996CB -:103EA00057DEFEB413E2E5029F6D4A7004EC97DA28 -:103EB000281E213ED8D622970698BF133347935F1A -:103EC0001189AF578472103FC2DE08FDFDECFA5431 -:103ED000DC940A3D7E363B24F87B159783552007FA -:103EE000446B6FE694C3EF9A915C09EFB9F6D91B66 -:103EF000260F424F537E47B929CBC9C4B8BAD0DB8D -:103F0000467BB4576EBBFB02B0BBAA3746A5EB9B02 -:103F1000F29BBF3FFD0EADAA7DEAB16940A7923189 -:103F20001281734CA39EFC1F2B97089D00800000FC -:103F3000000000001F8B080000000000000BB55BB4 -:103F40000B7854D5B55E67CE9C9949322F9210C23A -:103F500023F1CCE441A8018747243CFC3C10082015 -:103F60000627F8155153994404C4BC40B9A642BF72 -:103F700039210902A53654ABD4A29D50B0D4AA8DE4 -:103F80008035AD3C06411A8AD569B5B7F416E828E4 -:103F90005CDE60C05AF116E5AEB5F7399939930485 -:103FA000B5FD3A7E7E9B75F6DA7BAFBDD6BFD65E99 -:103FB0006B9F9359C523E5058500D7E8772B80F8DB -:103FC000E667923C1CC0BAA21C143BC0BDD896D870 -:103FD00063FD1280D28E3440D43CDB117BEE964DD3 -:103FE00000FDE979234011C02C9DEFC432800C8084 -:103FF000FBDCC07F0DC83410E08B1B38FF742BCC6A -:10400000F3E3FA608E64C7CF37DD33D92B63FF50FB -:1040100059E0F3AD889A6DE9C867B7B9B77890FEF3 -:1040200017E52E13C126A40238CD51482DA4F94D11 -:104030006C7E0095C9F36572F7D7F6F9AE080DED01 -:1040400038FEDD5B6F8D2828D7DEE5A3478B726CC9 -:10405000BDF1B285F195A5E1D831005DBBACA14DB4 -:104060002837E07C02F27FB46B58682D6EED18742F -:104070005D05A4D59D2932EDAB6E770AE3AF4B7693 -:104080008504ECAF7376E5FB519E923D4961188142 -:10409000EBEC493203AEFB59CEFDE3E5227A3E74E8 -:1040A0008AE044A1775ACD807C2BB39509A4B7BE92 -:1040B000E4D7E54B6CF5FD97960BAACB0530B3C45E -:1040C000A19AB05D7C25076034C043AB67B0F6F5BC -:1040D00060262A1960EA957200DC5BCD953BD9F326 -:1040E000DA2B298C9EF9DD4829ED075E17600BCA93 -:1040F0005F36F85B2B01E5EB4C86E13B705F9DDEA4 -:104100002C5F137657B7CE60FC65BF9C369DF65585 -:10411000BB0399695C8110CA233D9DB09B48FE8713 -:104120006D5CFC8FEBFF3C46C6F11F8F718C046405 -:10413000DD27B63F395E60F6EC247B4EFEC53FB707 -:10414000FF0FF249574450501EEB1581B57F940381 -:10415000D5A427E40340BEEA6D03C704EC5F054F16 -:10416000BF9664C4A3547D49223C59B12D89EB9F6D -:10417000A7E124518F4BBAF1F4D5FC609EC6FF65D0 -:10418000786AFECFE3A9B90F3CB5FC3B78BA8E1D27 -:104190007DE089E16CE6218E0FC871F8B600C30B93 -:1041A00093BBD392156A42BE7BC9AE84AF6B504FAE -:1041B000FA9C47F64D8BE1F5979EC0CF494EDDCE78 -:1041C0009DC96AE192C2AF62E7BB81E2C6BDE9F573 -:1041D000A0E0F379D8C6C70D2BD9AFB0E7FE5EF9E2 -:1041E0009AF16EE357B4F31EB233E1C78D761CC368 -:1041F000EC27935D13ED4E7625BBD7EDB66EBA9ED8 -:104200005D87E7067E477A49B42BB8934D7073BC3F -:104210005DAC77126E3E0E9B81FCAB2FBB4A1BB888 -:10422000DE75BA256C9E1E62E701A4950F6778398A -:10423000F4EFE0A5ACA4FDEFB67E0067E4257E3385 -:10424000F2CF29C6AE41D4BFB45531537CC17F8E65 -:1042500067332A6063FAD4E8872353508E994F76E8 -:10426000F7ABD43F75A24B1B0F0A6EAB9BFFB45C40 -:104270001F59C7E46EE5FA0E44CDFEE171F418A4AF -:104280001D71747102BD91F3D339E266F384D87362 -:10429000C29F308A687D3ECD0FA0ABB41FDA6FD6C7 -:1042A0000EC1BD16ED7DCFC48F2C649FB292E88104 -:1042B000C1B8DFABF2637E7B123EA73888F2DA3DED -:1042C0002B5B55B3361EF558ADA9D1DA2E2822DA6C -:1042D000A9BA5808793D3DF568F7E8B8D4D7C5A321 -:1042E000D5381E2C63BEDE78C2091BEF65E3C3D64A -:1042F000AFB1FE5D134109F512270779B43879157E -:10430000697D7ED4DD9DB8BF502FFEE6D5E68D9841 -:104310004C3580FAFA86E7E9565B16DA17383E0A1A -:104320003D3FF4AB1C87A024ECF77AF2BA3DC6F30C -:104330009F7EB2717CF87AFACAE8315EC3C7222345 -:104340005E5C66FFFE8F510E57BAE056D1FEB5FE99 -:10435000A475E022FBEBF80EF99521B8BF24E8C65E -:10436000AB11DF6DFE29A8975AD0FB7FDA4AF1CA5C -:104370006FEAE6E778DF29748F2F40FCB8808F2F33 -:10438000F56C6A550B993D583FA3CDD7C17B7B0295 -:104390003D31C13F347C33FFA4B88DFAC9EB256EA3 -:1043A000DCAFD9ED82007329EE4526F37C2FE2E5E0 -:1043B0006D9387E7770F697A7C586B23C9717A18F8 -:1043C00012B333FEC25060D837D3D3DDE9DABED59D -:1043D000BDFEDB715F9154182E204EBED3B6ABB537 -:1043E000F996D8F860DB5E8693EEF9D43D113ADF9A -:1043F000EFD6F4D4D4168E683812C8EF6A1820109D -:10440000073B0455C47DD6100E7AD967594FBF516A -:1044100013C62BD275C6DFD973BC92301EA4F4AF7D -:10442000335EB3D3ED09769C9E60C7290974854E2F -:10443000870CF14C8F73551DEB5B32508E87B60A9B -:10444000744C50BCB608230136780EF9EDE308AF82 -:10445000B2341863FE46CFEF23B66100E514CF18DF -:104460007EDF695572514EF27746BFEB576E22FCE4 -:10447000D4B76422FF264FA4D586ACF734AF972873 -:10448000A779C1F3C75633CE7BF7985F1EA0F9CC4E -:10449000C2FB91DB3DD7C16B6BC23E3626D06A02B0 -:1044A000FF535F12DF9B13C6AF48E85F97406F482A -:1044B000A0571BC757CE17989F54A2FD48715FE6BF -:1044C000373B3DDDF942F77926D8599E64C0FDCCD3 -:1044D000264E1FF07CE85F6D8FA3DB8EFBC9DF7576 -:1044E0001C4BC07FF7A6834AE787D4473CDBD11734 -:1044F0008E0A12CF3BDEFF37FAE740CA3BC1702E6F -:10450000EF138DF45E51F7B74B91470AE9A14E774F -:10451000F90348CF7CC6B82FAC0BB5FE8BFE29E85B -:10452000FF33BFAFF75FF453DCD3F7A9F3977E7E79 -:104530004DA4F58EB45DF06FC6FE8AC9E1BC7A94D5 -:10454000B32295B778CE88748ED5D9B83F95EE1240 -:10455000FD74CE542487F39616C6ED13DAF3699FE3 -:104560007B978BCC3E6A13AF47AAC067012C85F6B8 -:10457000BA5C0D2F20FFBEE562039D6BC71AD232D5 -:10458000A89E18EEE579DB3ED70D190F20BD3765E3 -:104590009E4546BEBD8F4F65ED9BA2B2AA0B71FC36 -:1045A0007F9ECFFDF661D4EF62FAF947DB157F23DA -:1045B000FAC5671E99E93390EACEE8A07C75AD0490 -:1045C0005B6492C7F73CC3CDF7AC23D7A21C958D93 -:1045D000376650FE56F5C3F2D281C857D522F9048A -:1045E000C6072348EEC0DAA916EA9FDFACB5EA3465 -:1045F000D6EEF962FBA111C8DFB546F46D42E6DDE7 -:1046000057BCCE2A94EB78128FC31F9ECF75929C15 -:10461000EBBD01C98B72543A1DC9021D1E6ED939FA -:104620001BE77D2247B1788B62FC7BBE10E751BE51 -:10463000F9C6F9AA0CB29FDBCBF1BAFB4A55465535 -:10464000DC79BFE08299E9798F457E84F2CB3DC960 -:1046500059822A303DA795A3BFCCD7F26BC44BC378 -:10466000F65ECEFDCF3D22D3CB096B031C4710EF86 -:10467000FD6EFF8924A73EAEE8FD409383F03C44E5 -:104680001E159F47F7CB9E3C84F611C359DA1F08CD -:10469000372C8F467AA8D7BD5E455CC13ECCFF491A -:1046A0008E74A594CE0158810C18C720B33D3FFEEF -:1046B0003E2296A7AED4E201E73BAA3A58DD7AF44F -:1046C000A5A410D53347D5BF3AC01ECFCFFD64A1F6 -:1046D000D3A1D2617CCAE130935E8F998327BF8DCD -:1046E000E3163C27B138BAE0B9FE2BBA281EA03D2C -:1046F000F3A0E7BAAA5762F3F4E927E02937F8896B -:104700002A972BF6BEFD6492572EBF9E9F2CD4F2A3 -:10471000F6D2E7243FE17C6191C30C18AF273FF745 -:10472000D616C2E3C22549A3AC28F8C2E7ACCCBE7A -:1047300051874375637FC0E930F7A3B8EEE5712474 -:10474000DA98C4EA1431C3C2E29EB8AA4826FD949E -:104750008860B6E1B9223A7DB29FD3CD6EACDB5A08 -:104760001CC532D9F73B5EEE0FDDFDAEB9B7095877 -:10477000D75CC67DA4E1B8330D4F3E3D16E53B0B3B -:10478000A1396351EF97C9D0B8CEE51D6248A57332 -:10479000C2AC98CB30EE2D02EEEF3507B75B26E1C9 -:1047A0003F17D52FBC9DEAA30743D28751ADF6B979 -:1047B00086FF7F026F5B28BF7D68ABF1397A8C85FD -:1047C000FCAAA6DDF8BC0ED65D1247506BFE305A2F -:1047D000A03DC7751B8EFC65F8FE38BE5AAF23FDA1 -:1047E0002496E0300A46A166719D42D75D04BB065F -:1047F00091C92BAE4C0A911EC56C7E3E4C03219490 -:10480000448070E3BE71DD4F838787EF4740888F18 -:104810008D667A3911443C0D457D386D8C5F7C4C3A -:104820000C5971DD923450FA913E9F2E0770307D05 -:10483000AA6EA4A7A5D79B293E9DD3E24BA500FE57 -:1048400076E6F7BE6CAA8F173C97C4ECB7F0F90771 -:10485000FFFB4763C85E65E9F17EB446C31DCE0722 -:10486000B6D4D83CA71ABF934DF294FC04EB4AAAE5 -:1048700037C5C0D377B37899E26371CB1DFDDE589D -:10488000C24963CAC8B540381998ED2D8C8D5FB800 -:1048900072793E1F8FF5AA93E25512DB4FF50E2B6E -:1048A000C349E51A5161E76396859D8F1F3627310D -:1048B000BA7A4831F3B34A1304681F980B66B2B84A -:1048C000CE550ED57650B6DB29CEAF8B884E661FFF -:1048D00055B39B85ECB3D99BC6FC771EE918CFADC9 -:1048E000FD84B322361FBF7FDA2D84B6B0F8542F73 -:1048F00093FF57980416E712FDF1352FCF5B2BB3CA -:104900007DF7D1B89A27ACBE951E2E83A8CB8378AD -:10491000AA314516FC98E6FD9595DD6BD4E13E92F3 -:104920009CACBE50B6A1FC7566305BE85E4AE6F111 -:104930004C97A74E2E9F4638C5FEC366ECAF71F06C -:10494000785CD38FDFF780C316DA12BF1EC99CC311 -:10495000C7C94EF2B3710C2FE4F726ECFF08787F3D -:1049600089B3588EE2F34E13ACA67B129267D888B7 -:10497000B875911E3882F0B8C4EC75901DD2E6CCA3 -:10498000A5F55E16595C42677AA298F2BF97C5D129 -:1049900054C756AED957BA81E85747BA4984CA575F -:1049A000DE63E7D3431ACEA294F7D37985F4ABD86C -:1049B0001ED5E24240E4F73847498FFD637AD5FBC4 -:1049C0006BD648CC1E352D1C0F358D7F66F3D6383F -:1049D0002219648F9AD7A49B09D72735B9AB1AB38C -:1049E000261E467C54492EB7808FAAD5320BD1D5CE -:1049F000AD02A3F5F56AD6FC29C354C8E7A3D6AA2D -:104A0000E128366FFF6C3ACFCEBD94965D1967F7FB -:104A100073CDAF3B653BF94D38CF4DF7304B927CB2 -:104A20009B989F727B9C6BCEDB44F734F3DD118740 -:104A300080FDF31FC949A573EE983B6CA1FE63EDA1 -:104A40001E13D18ADB3D9168C57C13A3CF61086F2B -:104A50002FD4C08B76AA15386EAA5FDA67F1E27A96 -:104A600029395C3F175E7E2F9FEE0B6AB223F974E3 -:104A7000FE22AEF207935D5E14589E50FB92A8246E -:104A80008D88E1AA967085FEBF58C355ED8ED71F5D -:104A9000253FAD253C8DEA894BAC2BF7B3E7DBDA3C -:104AA0004A818FDF4FB8D3CF7BA49B25BA57B36819 -:104AB00034AE43B43D87EB1FFBA7F07EB5909D233A -:104AC00010B5503E5C27F23C01FD2993F288BA0EE6 -:104AD00049ED8E97B42EF517C6FAFBC2CDF01C93A4 -:104AE00066672B3B8F86E770FF8BAE79CD49B8B8F0 -:104AF000F0F2BE03E3A9BEDA26B829DEF7F0434D93 -:104B00006F75A42727DB27CB8BEA482FCE989EBA58 -:104B1000FD4DC3451D703DE87AA9336B7AD2FBB5D4 -:104B2000F123343D5483A6D71D43B9BF6BFEAD9F1F -:104B300023FAFE02A97CBC8EAF79DAFE266A6D35B7 -:104B4000E2C657C8F0A5586ED6EA7EECBAF06A1BEA -:104B5000BB37D2EDA9CBFDA8B63EC669A55F6ACC2E -:104B6000CE51132CEAED9E7AB6862BC9CEE3CA0746 -:104B70008D83EF6B40FD2D7E49F431E551CD15B7A6 -:104B8000AED51475B0BCF431D14DFB2AF945F96DA1 -:104B9000B46F1D77D256C1DC3186EA8C7E4CFFBAE9 -:104BA0007C2503FCB7F5E3B80B933CBA9C1F086166 -:104BB000662FF555C1CDF3DCA885EE0F753F4D94FA -:104BC000779E666FD1298C176E22797C32F937E097 -:104BD00039C8E4B11F5ECED6538F2EF78C88AD73E3 -:104BE0004C759889EF18F038A0E3F203ED3EE283AC -:104BF00096D7591EACAFB34CD34BDC3A8186F49EAA -:104C0000EBE8FC351ABFEE179DA91CFF25CD7F668A -:104C10007C7A9CA51FDDC3E9FAD4F516E79706FD5B -:104C2000E8FEA5FB936ED77FD5AF60457F96AF3E7C -:104C3000AEED9BF94846EC5C207CD27967B5202E1E -:104C4000ED867393E535D3865CB2047A79AEEB29B1 -:104C5000F179AC9E726793FEA7D9334D94074073E8 -:104C6000E6FEDCB8BCEC38DD77513CED0FFC7D0690 -:104C70008694F8F35CCFD7F4F31A7FEBBA7189E32B -:104C8000EBD29533D4BF68CC927CCA232EE578D979 -:104C9000BA67A1DD3209E7AB3E1D2975CAB17AE5D5 -:104CA00096BF874517DD07EEF018EA85EAF3FB9912 -:104CB0007FD7406415D5B7956BDE2B1B4B76FF393C -:104CC000E6E3C837BFD5C3CEBD339BEF1F4DA56C00 -:104CD000654B1EA31FDCF200A7D7F07CAEB2A5E89F -:104CE00005BA8F3F9EA49412BEBBD60B6EAAB72600 -:104CF0006C295A710FF64F70DCD08FE43EBAF97808 -:104D0000D978AA1B1A44E62FCAE627E750BFD2215A -:104D1000FA68ABF3C1BDE21EC2B7D9C5FCED987607 -:104D20004E34491C676F6B71627F0E3F2FF76B38F3 -:104D30002C696ACA37D1BA6D783EE1FE2B2C727BA2 -:104D400098EABE5D037C9B485F58A666228E4E0B98 -:104D50003CFF5E64011BE1EAA0145946F21F5CE6C9 -:104D600018D9480288576FAEE2753A8B2F5837B181 -:104D700075757DE9EB1FD2D6D5E7D1C775523E4593 -:104D8000E78726EF99E69FCFA13CE1CCD6BC5488BB -:104D9000D3FB19DA17EAFB418C8BDB7AA9FF0EE70C -:104DA000E8F7AB21D62ED2EE0D0F4AAD43E8FD2D2C -:104DB000E6F127E2F3F2536D4936C223E6F1C6E786 -:104DC000123F4F308F373C47BF3961CCF7B5FA4EB1 -:104DD000AC70057A89437A9B98E79FCBB1A79FBCBB -:104DE000117AE4F9BADF258ED7F3FAEE7B9623F633 -:104DF00084F731635D709DF5CF07D13058FBFD948A -:104E00007C17C74F49F97C7B84EAC956ABDB8AFA29 -:104E10003D417E45EF015F13799E68035F18717114 -:104E2000E24FA37DE4870B8E70BF5BD02E84E81524 -:104E3000FBFEF58F8BC4FFC0460106087175D65383 -:104E4000EBE790DB5DF605560D44FECB5B059FCA94 -:104E50002454EC09F5D5818172DFF5D5BF5B57E9A4 -:104E6000F74C897A1F94ABD5573EF019F5CEEBF38A -:104E70003D089FE2513DF57E3E186075D4C5E022A5 -:104E8000D68E6B6F2B198CF27F247CF0C404F21F3A -:104E9000878BDD939C0FD6B39780173B465F9D852C -:104EA000FA79C3EE7253DCB8186C60CFBBF1A2E1A3 -:104EB000F3961D7BC5C1C0F8774E40FEDD7617BD69 -:104EC000D6E8E57D1BB72F40327F3FAAD5DB0F2FF9 -:104ED000193B809EEBFB3DFB6D6E675DFEB35BEFA8 -:104EE00077527EBAF7C7693BC7917D535C6E82D11A -:104EF000C20D220446633EBC81C7A1D336D70B74D2 -:104F00005F7A7AE39D19540F3E2075597C38AF6F54 -:104F100057B993EE41FED71C75BAA945FE30C96159 -:104F20000E8914FFC64F07F61E707CD80CB287BDE1 -:104F3000A267381977DE1C0A237D8EDE0FD2B97D79 -:104F40003599BFA7D7DEFB3DF06B7E9FD67D7FA254 -:104F5000DD234CD0F6FB5FB9A91CE7DAF39262FEC1 -:104F6000FCD4C6EDB368BE339B2537C97B71B3C48F -:104F7000E65F8C75BC0971781AF146F16BF1FBA202 -:104F80008F207D662BAF9317236EE9BEB86689A488 -:104F9000585C3DF158A2F3ED14587DADE372B112A7 -:104FA0002A657AD7F069C3FFAEE191D10FDA579144 -:104FB0003E1271FAAFD6FD35B9BDD7FD8938D0F5AF -:104FC000A5E321864F60B8D4ED9EDA3E72D26036FA -:104FD00040657A54274301E5054D162830130E4CE1 -:104FE000C93EF2F3069B7304DD337D9AC4DB474D63 -:104FF000EEB7A85EFED4244B02B6D15C0F1BFFA80F -:10500000E89B4AB4941E65F70362894931D179D788 -:105010006465F12231DEACC9E571382B8FC79B2D59 -:10502000B96E9E3F423DCB1FF416379845F949793A -:105030004AEA2732B23CBD79C66C33EEAF7C42EA15 -:10504000B21CCC2C9FDF7CC76C7AAF5B3E3AF53547 -:105050002FD2A1DC59BCFFA6D42209E9C646FFEC39 -:1050600029D8BF2B57792AB728B68E3E2F3E7F8688 -:105070009EFF7640E0D9DCFE749ED95753BCFF48B2 -:10508000E8AA358931FE3F0870EC0D21464725C856 -:10509000A67C7A4B2EB07DF4D59EC9557E9ADBCB8B -:1050A000F32A8016D26395FADBC394AFE1CF6F4346 -:1050B000BCDDA1E1ADCA660F132E60B574BE1B172F -:1050C0005E8A4B2E33F9F72CCDDC7798C37B69FCD5 -:1050D0003068769FB4B15470E3B5B4BEE33C3A2671 -:1050E0009CD4E7C3FD7D24E17ED1AE8282B6469793 -:1050F0001250C91518DF849DBFFD8CE66D52219AB0 -:10510000C4EC50E1A6F3488080E91AB63529880737 -:10511000D4D3D2D72EEC27F83FA8E75399FCFB8CC9 -:10512000651A1EEF8828CFB4A150A782909E8BB637 -:10513000BE006F5E34E3BA674C8183A4976AD3DB09 -:10514000D94B65F2DB2627E52F175E117DB7E3B853 -:105150006A2D6F87AB62F8567CDEE919B6696D1C63 -:105160008EFE98CBF394F39E70F6728A1F1E5E77C4 -:10517000C2D57DD9CB917FBA7746119D4B4F81F235 -:105180007E6EDCFBC559E6DEBFBFF8FD209E77C012 -:10519000667EBE5ACDA03A52590B4ED4C70C94A588 -:1051A0001869096991BD8F0F313B129F93F214F971 -:1051B000FE4CFEBE06FCE48FBA1D75FBF4B01B8AE4 -:1051C0004CF9B9C90612F9CB30D8E826FFD6ED372D -:1051D00055B4B378B3F4357E1FB7548836A711FDA4 -:1051E000329E97A42FCD2F7B9E9B5B2C648A451B00 -:1051F000EF67F1498F4B32FE47F8F94FDD4B0A79E3 -:105200000E9EAF8C849184AB2FCB77F4B884F6B12B -:10521000E57D1DFB908A70BF0BB5B5A78A15B299C5 -:10522000F4D2DFE6A3B8BCF4B91C76DEC1BA1FB075 -:10523000FB0F9D0F36A6317CAEF288CC8E651D83A8 -:1052400041C6470F760820E339777B471AA39D575D -:105250000632BAEC67032653FEDFFDDEF267431920 -:105260007DE685436302FC7EC54672F84197A3B094 -:105270009DF2A1CB769403EDE0B7AF66F7857EE8AB -:10528000AE63846B02D18812F2274552B95D6C8DF2 -:10529000CCAFB57D2D75733B2E3DC8CFDDA593F802 -:1052A000FB3DB33ACC4578903A450821FDCD836269 -:1052B0005118599BB4B86CCD34811C678F243919AF -:1052C000E4B8FA0D54254275D25C0D272905A9864C -:1052D000FEC785804472CDB52F60B871F80619E617 -:1052E0008B649776327D04787EABE309C4F36692D3 -:1052F000F3938902A4212EBE3917FBE3E695265EBF -:105300009A22B0D69817A35E4E5C0F4F33F3B4F3D6 -:105310006E180C63784AD00FFA07CB3F2FE3394E53 -:1053200069136617CF4C447A4EA7042199E59BCCAC -:105330007F2E2B29ECFEBE45D3938E3BFF50702869 -:1053400038AFABD8A8B77E8A516F69D38D7AEAEFB0 -:1053500037EA65C05CAFA17F60E01B86FEC18B466B -:1053600019E8ACFAF106FE1B1A261B688F7A9B819E -:105370003F67F56C039DD77A8F817FE8862A43FFCC -:10538000B0D06243FF8D5B971AE8E1ED8F19F86F9B -:10539000EA5869E81F195E6BE81FDDF903035D1425 -:1053A00079D6C03FF6F02643FFB8E88B86FE09A702 -:1053B000B719E85BBA7E63E0BFF5CA9B067A121C98 -:1053C00032F097D8DE33D053DD7F35F04FCB3C6ED3 -:1053D000E89F219F33F4CF2CF8D84097F9FE69E07D -:1053E000DF3828F02CC59FB9A6754755A0F82C7F4B -:1053F0007F22E2F9AE74B32F4C4C5FB36EDBA4C7CF -:10540000410DB79F80FD3E93F7CBE3E0E35A5E305A -:1054100055BC1DE8BEF772BBC070DDD7F9ECC27C8D -:10542000D71CB78F7E8A0D0BF0189D36DD6DA0FB63 -:10543000FB330DFC03E6CA86FE81810243FFE04593 -:105440003E039D555F6CE0BFA14131D01E75BA810E -:105450003F67B5DF40E7B5CE35F00FDD1030F40F14 -:105460000B2D32F4DFB8B5DE400F6F6F30F0DFD4B4 -:10547000A11AFA4786571BFA4777B61AE8A2C80658 -:1054800003FFD8C32143FFB8E85643FF84D3ED069A -:10549000FA96AE0E03FFAD57C2067A121C34F0978F -:1054A000D8FE60A0A7BAFF62E09F96F981A17F862F -:1054B0007CC6D05F7D0EE147F9F31B027BFF35B35D -:1054C000E092A15F4AC73C9DEEA721D9270A3DF390 -:1054D000743D7F2BF37D6658E751533DFB2EEE5311 -:1054E00013CFEB6CF9FC7E0BF3779B8DC5593CA178 -:1054F00086B3AB9646CA4F5DAAC07047A94605BBA6 -:105500002F4C67E72A3B1A65FA0E0DF31B24524D08 -:105510001E0FD50F29B13C74C8B5D15F3D0FCDC862 -:10552000078EFFFC404A7E11D563AF96527DF22074 -:10553000A8AB480E3C5F5DF49EE99D24E3BD91DE7F -:10554000CEB0A1FEE2D63B98D43A64D475FC768600 -:10555000ED3CE3EF9E57BB5712707F4BE3E67F02B3 -:10556000EB26339690AD41F42FF4D31F04DD8C7EEF -:105570002A98C9E8A783326B37040B58FB6CD0C755 -:10558000FA37068B19FD7C50617428389DB59B82D3 -:105590007EF67C73702EA35F080658BB35B888B5BD -:1055A0002F06EB59FF4BC10646BF125459DB1E5C58 -:1055B000CD9E6F0BB6327A477003A37F150CB1B640 -:1055C00023B895B5BF09B6B3FE9DC10E46EF0E8652 -:1055D000191D0E7632FACD6084D1FB8387197D20A8 -:1055E00018656D67F0346B7F17EC62FD6F07AF30A5 -:1055F000FABC76DF5F926F7CAFA6D30053181EF41F -:10560000BC7616D52D048E62E9A2A16E49A81F12A0 -:10561000ED71565B479A8CC736E53983F23735C54D -:10562000E5FB7768EB3D9E0C6A12C6BF462AE61181 -:105630008A8DA9106A62EF5779DEBD50C325A4F3A5 -:105640007C7B8126D742CD1F8A089F050C9F6F7FE8 -:105650009D3A49AF93834302F3F2B15D9C6552D901 -:105660003D813D944F79FFA621812AC2EDE5FA07DD -:105670000EB0F5DCBE7C5AA4CC1AEE7F17DDFF1C01 -:1056800014D97D695FEBD5697FBFD067FFEE3343E7 -:10569000E81C9AFE85C8EED3DF911C73E97EE49185 -:1056A0007CFE1EE3917C93A11D96E57F98E43C95DA -:1056B00057FFC2C3C852B124CF4579EB1D545AA33A -:1056C000DF97832CB1EF6341798B3E99FC262676D8 -:1056D00044DF052A6BB70F0EACA0F177630141746C -:1056E00060BC35BBB7FD24CAB34AB3D3AA7C93A12F -:1056F0002DCDF2B7D07C27F214833CCBB364EDEF11 -:1057000064BA9E27B9FEB1EBD2492127A66FFD5E90 -:1057100062D524EDFBA92582FE9E9AE78336D0F35D -:1057200041D65FB18CDFCF7C0BEB327A5F79448B53 -:105730008797EB25162F2B84641FE5D397EB970DE6 -:10574000A5FD24C6CD0A1C67C27115C0BF87A83845 -:1057500092C2F085F301BD77ABC0CC9DEABFDA2CD5 -:10576000FDDE236AEFCFE551E83DECBC9DD636AABD -:105770005311279B591C1B27AA16AC93DF3185F2C6 -:105780000591E1C322A0BC0BD3111FBDE4053A0E65 -:105790006AB5BF8FD19F23BE5EA1F92EFE7A6C0140 -:1057A0007B6FB27B9C4CFA6B32A13DE8BEE6772260 -:1057B000FF4E82AED8E93B0E57611BFBCE9F92088D -:1057C000B2D738077B1FB2578486577B899FEF6A11 -:1057D000387A27539A1E62F31ADFF3756A76ECD48F -:1057E000EC5BF6E6C1AC4771DEDA4E89D53B30267C -:1057F0005AE8EFE5FBA6BA86430373E3F651D7F107 -:1058000001FF2E0AA285F1DF439DD2D6D7F1245A9B -:105810001C81367BBC7CDDB87E47C3F549CAEB678B -:105820005965D75D38348AAA09631BF8899B7D576F -:10583000A77F5F371FFCAC5D8870201CFBD5F5ACE3 -:10584000FE5D0CEDEC796DF1FDD944D741D7944C58 -:10585000AA5F5637BE9589D2DDD9BA7E2ADD3FCF01 -:105860000E55BE456DF966E124D5DDE8177FA3F539 -:10587000A3427D0B95A4F7BC34A985EE796789DC3A -:105880000E7088DB0171A488A93DF7877E7052F302 -:105890000326BFEE07152B397EF4BFC7E8F68BE26F -:1058A00087FE3698DE7D98BBD8772175BBADA9847D -:1058B000AFC554798AF179A17E3EF3BCE021CC0BCF -:1058C00088EFACC4ED7FF66812FBBB97B302E263CE -:1058D000544FDCEB79E6A7267EEFF6A8885B14A987 -:1058E0005E7E92E969912D3482F484E7330C255C65 -:1058F0001F6F5F3592EEFB2687B2295F955EB4FA83 -:105900009A3C86380FD75262F7784F48FC5E2D518B -:10591000DE1E794BF181CF289FB05A40A5F749E8A8 -:10592000FFDCEF8F71F93F3505326F1679BEC2EAA1 -:10593000E8217E56FF4386CDB756E8B97EB3B66EF2 -:10594000E7E7BC9E56B3807D8F932887E0E6EB2681 -:10595000CA634DE672E8E74E4F79B81D74790A863E -:105960007AF8FD7DB6C2F6DD68EAC7E2D747626025 -:10597000E8503A2FB5FB31BD8EEDF49C62711DAE3F -:10598000360DE1DFF786FB3A4FCF77D7CFDED879F8 -:10599000A7DF33C1C4DEEF05FD36B744769B0D3E6D -:1059A00016F787C1115D3FEC9EE9FF019ECDEE1811 -:1059B000B0390000000000000000000000000000FE -:1059C0001F8B080000000000000B7BC4CEC0F0A3BA -:1059D0001E822538106C62711D0B03C30756D2F569 -:1059E000C17025507F0910E703711610A7027102DC -:1059F000104703711810BF069AFD0C881F02F11D95 -:105A000020BE0EC49780F82C109F40B277191B035C -:105A1000C35A36D2EDFF83E4E78940763910CF24AC -:105A2000231C46F1F0C0F23C0C0CDABC08FE3E5ED2 -:105A30005479051E047BB92065766D03EA0700E9F9 -:105A4000CD424A800300000000000000000000007A -:105A50001F8B080000000000000BD57D0B7854D58B -:105A6000B5F03E8F79253393C9839040C493970452 -:105A700009382421F2AA1E0842A4D406F42A5AAEF8 -:105A80000EC823869044B02DB7729B21092F411B6D -:105A9000152D5AB483458B0A36F268D106EEF028EC -:105AA000C65BB4D1A282D536D45B450B4944116F95 -:105AB000B5BF77ADB5F7C9CC393349406BFF7BC370 -:105AC000C7B7B3CFD967EFB5D75E6BEDF5DA3B76E5 -:105AD000D9C6E42B19FB027FA09CA330C60644CA9A -:105AE00051775EBB687B09FCFE99DDFFB8166967DC -:105AF00094173389B1D1F09E653056CAD8954EF8C7 -:105B000015DA95BD70EA0F97A531B69F29CC018FA4 -:105B1000C26A59EAB7A09FFD9F333FBE975F706787 -:105B200075B8F1BB2063E98C5DC1F877E16C2DCBD2 -:105B300057881526E373DD49BF433FB99BEAE0FB75 -:105B4000B39FBAE97B2B1C46C93E9759587CF34555 -:105B50000EF6AB7EDC5120EAD90C066702DE2C1A69 -:105B6000D780F7D0DBEF11BC075480578B33BE13BF -:105B7000E04F8BC0BF9F5D9BC40A39FC7A6904FE6D -:105B80000B8587E60F786EACD7BE9997CFD8BA7AD7 -:105B900046E5DA7A2795ABEB7DDFCCB331B6B23E82 -:105BA00083CA46153E01381AB7B0501050EF2E8404 -:105BB000F646FFF03F21CF69AA3BB37CA6BA3D0D64 -:105BC000FA2988D455B766AA37BA2739036E1C1F3D -:105BD000E6EEC0F19D5402984733001F978A79BAC8 -:105BE000B4E02C06EB91E7B66B2180E352F782E933 -:105BF0006C24B6CB27BCD9055E9764367420BC1FD5 -:105C0000433B06F31DE69EF23EF332F69FD94FF07A -:105C1000796C606C203C5FFDEF751D12F4B732D3D8 -:105C2000AE35407F4FC0F86B1C5178DCAAFEB9033B -:105C3000FA74C23FC4E3D08DBC1E9937D4A3E631B9 -:105C40008C45BDCF8EF473A1FDE6379BEBD67EF37A -:105C5000347D12D2ABD16F3EAB68F0B9FFF7F67B63 -:105C600029E03C3525D2AF314EBFFD023954C0B7D3 -:105C7000F91B59289C1D3B4E9EE62F0FC2FBBC8D85 -:105C80002A0B65F3E769C01779FC57D6E49B94109B -:105C9000288C8587458F93135997BC34FB1C19E8D2 -:105CA000292FE3FA4512D25573D4FAE63066F0CDC7 -:105CB0008FEA7D4C1FCAD8DDF505546EA9F7E9C8F7 -:105CC0002777FF5D99D55218CB8F7F11F2EA1E1B03 -:105CD00023FA0B3ECE428F4BD85FC5AC39505F3FA5 -:105CE0002ABDE82E8D885C4679E61274BC5ED26EC1 -:105CF000C8C1F6AF280CE5A0951FEEB6E9D3B0BF3A -:105D0000B5A364A901F19CC7F921CF1676E662BF5D -:105D1000CD39A382D88FFF55E287BCFC4B3405C632 -:105D20001D9627F861F4834E94873DF35F96AEE7A6 -:105D300015339664A103DF79D2816F42DF74F07569 -:105D4000F1C3D7475FCD7DD2D77AFF7DEF3BE0FD32 -:105D5000963CBBA664C7C295797138A3C21D4B6F30 -:105D6000797982CEFC7DD399B57CB03EC4DE011A30 -:105D7000BABF3E83E8EEDE7A8DCAB5488730EF07BA -:105D8000B0E958A8231DE2B8D71551BDD77D8BAD1A -:105D900020BA4C9FD5CC50FEDE8FF4390E875BA91C -:105DA000EB1360AE79A20E5BA40C7BC0BDF87E1035 -:105DB000D575DCCAEE928CF6CF0675C0778A683F3F -:105DC00075C5B3C146F8FD7E17AF5FBDA2530F6620 -:105DD000457D1F5CA7EB5991F6500F4F52A3FAC3B4 -:105DE000FE0BA3E13948ED8DFEE6AF38A10701BEF9 -:105DF0007B5DBCBFB52B8EFD53FA5F2B053240B5E2 -:105E000060AB2CFDACEDA9DFAB231E8C7172A45FDF -:105E1000E8C1E8F7C16774DD1D797FB9746F10DFE1 -:105E20006F64157912AC43E6F48A0C06EB6FAF6829 -:105E30000EE296DB039FC077647E0F12BCAE0CFEB1 -:105E40007EC48ADFEB8D51EB3369C5CB4184D7D05B -:105E5000731441AFF20B594B8F00BD2A49763FE9CD -:105E60001BD701D364C278B32A980670C969150C90 -:105E7000E58192A6BE1BCD0706FD019C6309CEC934 -:105E800015B37A8133180DA701477F701B70F44E4C -:105E9000A77C7C2B3D4DBA66CCEF26C0FE6D6FB75C -:105EA000F9515D48453C4157ECF35B8336789E3AA7 -:105EB0001370ADD1BACD62B9B1FDA64D1FC4425128 -:105EC000FBF73F7A5DF3B0CEF116885E5FA8CF9501 -:105ED0000644F03856B4B3D29F313F5BCCFCAE35AC -:105EE000CD8FA9818C0A4FFFF3BBD7E59F55E18E7B -:105EF0006DF75B49A2F1274D19F36DC6C7630E908C -:105F00005FC9385E5164BCE469301E76A636C71D91 -:105F10002F65328CE7FCFAF069E547035E7B0CBC29 -:105F2000B79AE05D6B03BE8DB3FE5F37BCE7CB7FF6 -:105F30002E90BFC47F797DF3DF3FBABF64FC153E6E -:105F4000F94865E12B015F775CE524FDDE9073FF86 -:105F50006C7CA5E2A7B07E77BC547CE24A192B404A -:105F6000D72322E3D74A1AED57BDD1776FF3810DBE -:105F7000D6D4CFFFAFF9F486D7AF5B0E9DAF7C6D63 -:105F8000783D81213FAD2C642107F4B1B2ED2AB2F6 -:105F900037571E291BC8A05FDB9AE14C8749256350 -:105FA000FFD0DF4A43CF985CD24FFF5CCF00FB4E5F -:105FB0006F02A56BB7B782F4A29512A3EFD783DE69 -:105FC00016023DA6E4950DCE3958F7EF70CEC1719B -:105FD0006D8CF4E992570EF9CA80CE5D23524629A2 -:105FE00040022B5DC6F3A3E5A8E7DE55289E7B782B -:105FF0007FF0BC02DB2788F6BDC1959007F044AD69 -:106000007FA2BD395011477FD76599F0F390D0BB7F -:10601000EE46BD0B047262424B00F56A57BA5D7BD7 -:106020004C8AFDEE265912F306BD0DEDEC115332EC -:1060300051CF3A30E389157684AF90915C77E5854E -:106040007419EAEE02CEDB0F59F67D37AE21E95D19 -:106050009952994ADF99EA77F7E831D913516FF3EA -:1060600016F0F7650D574C6C8C7ECFFC1371FF3525 -:10607000DE071A4AE97DA6B3E2D804183F13E468A4 -:1060800023E02B536D96EA685DD3E2EA8F1BE63B73 -:10609000678500860D331ECC9E1F673F81D534F186 -:1060A000E9A079663E7B48E0EF6E81CF4CE4F5D104 -:1060B000820E41BEB978D31EF9E61ACAE55B4241A9 -:1060C000F30AC4F7A079CC8FFAF686194F90DE6AEE -:1060D0008CE32A30CBB94CD53CAFAF6B3E1B99FE5D -:1060E0001D7974EFFD5BF96C230BDC8AED33C57E03 -:1060F0009E5010920285FDCFDF3ADFDEE6FD2DC413 -:10610000271FA74E1E103BCE3F0B2F996E18A7E4FA -:106110001F3F4EC23CB3BC3C5FBCC33E20E88C2951 -:10612000B81F58EDAB84129FC464AAB6A31D4EF2EB -:106130001BE0F6B0E6F24B80DE522B56DD2E83DDFF -:10614000EC79EBEAF7D1CE4EED9843F676536151F8 -:10615000DB246897E4F7CD984274CA08CF6BB1335B -:10616000E2BBAA1513615E8D8CF3DD66F996895C3E -:106170003FD069BDBF2B70062BAEA950477665395D -:10618000F1E66167613E6FE90B47ECF7BDCDDF16C5 -:10619000F94EF8FF9690DFB4BFEFD8743BF9118346 -:1061A000F00FEDD2644B3F49BA3DE2676488A7A87F -:1061B0003ABCFF6D0F5FDFFE4F19CFC7EE736A4029 -:1061C0000AB63CD987F67A12F325AB2867278342B3 -:1061D00000A2D897D61D94B5FED7A589B1F29642F4 -:1061E0004E7733A2F4DC0E99EBC969332767AF848D -:1061F0007ECF9670BF70AA0FFE17C5CE671DEC6BE1 -:10620000E1283FC7BAC2C7887F1B819E72802F8258 -:106210008532F9B7D7E6EDF045F3B5AC18FE6D2B36 -:106220007D304D2D15FA1FE047C99375D7C8AF4E85 -:106230001FCA97A48FC4E951DFB10B5FAF24E5C239 -:10624000E8E3AB8E67AC6B2C5F71FD246DE63C27F9 -:10625000EA3BAB326626C593B3BDAFEB7DB4AEA8C7 -:106260004F84E2F49FA64871FD39567D9EB1A5A6E4 -:10627000F5520696CEDADCD7BAA599F161F4EB5A5D -:10628000A668FF85C24BF5915FDC29FA5BABDD1791 -:10629000C4FDF32CEEED800FA5795418F53D96C79B -:1062A000FC8FF326A487B8343D443A24CADDD208D3 -:1062B0007CF62CD9349E9A9660C2379B05DA761408 -:1062C000FCAE657682C389E3C1388A0F3A94D0FF69 -:1062D000CFC22E2FF548FDE1505FE462FD4E131D45 -:1062E000ACCE2A8ABBDFA9625DD16CE5F47AE7F90E -:1062F000C917EB78D799E13DEFEFDCAAF66E1CFFEA -:1063000071EC772A7BD7C01720F1961E7AE7EBB4A1 -:10631000CAC6F64849200F32AE67010DEAF80A36C0 -:10632000EB35588E453A2CF2915EB05552114E62C3 -:10633000690DFF737DBE10955BE84F7606084F8AA6 -:106340005B67D45E3B3F7DFF9CD0AFD3843E6FBC88 -:10635000FFA162A77E5556C1D06E3EF7F6D40CEA77 -:10636000578747A51138ACFD162A811F2A0390ECE8 -:10637000383CF801FA09584701F9B5F305CECE3D8E -:10638000303389F5C15F0F59F8EB2189C3C92ACE93 -:10639000CFCE380763B6637B359040F1B29305C426 -:1063A00007B962FC27D6CF4DC0F19FD8D8379F1BC5 -:1063B00070FCB4DEC9C2A0A786EA7D541AEF43C2BE -:1063C000DFBF59D831C6F3738A4C70EC137CFF845D -:1063D000B32281FCE7076F9C360CF82BE7A8E24755 -:1063E0001D4F5BCB52FA1A3F3B68E637A6CCEE1343 -:1063F000DE656F4D9C71288A1F7FA178D2DE1D0E4D -:10640000BF5CCE2E47FAEBEFFB73F5FA8C43F95FD6 -:106410001D2F9B85FD79AEF1772B48CF095F49FC95 -:106420009923E448CE3C2E0F72AB594843FEFDFC45 -:106430000B164D1F6099109E32AB558DFC4D4C775D -:10644000CF81F743C5DB4C65BA8C5BF850D4BF50A5 -:106450008E6CE2FE73C3CF0FEB7E17CAB9CDAF29A6 -:10646000640BE7556A0DB8DE39EBCDFEFDC12CCAD1 -:10647000EF8EFE7AA1D7655AFCF85F751D3A701D44 -:1064800012FFF9EB105219D19D51D72456116FFF0D -:10649000FB44D0A9B6E210B743C0F87B272A1E01FF -:1064A000EB99829BC04F83F74D44BB35B886F9F317 -:1064B000E3C84B9B9A48746F637A7828FA0FE65CBE -:1064C000DFB117E5D50466925F71E4864DC5EFD262 -:1064D000B8DC080567F2F27385E265F9EB5908E369 -:1064E0005B9337D4ED47BF5E6635B79B33D7042542 -:1064F0003BD473EA981F87C9AD64BCFD6C16D27992 -:10650000BCE66806D0CD104137430C7A5966A69791 -:10651000C17596B8D01A737D20D2057C37D0422F32 -:10652000D67E723446F1B8BCF5328F17CD32C77DB6 -:10653000F259F7FB3F0778F30FB9FD61161B6FB2F5 -:10654000F6AFB24001E265F70FDDFF590013FCD949 -:10655000FA49A98817902749244F2AE2DB3D31F4F4 -:106560006AE81BBDB48FC84FDEAEB7F7ABF2D39766 -:10657000CE0538D67A7446E307B349AE2B225E794E -:1065800030F37A6707FA6DDC4524DFF7631DFD3CC5 -:1065900019970C8C96F78AF02319F546E147B28ECD -:1065A0003755E57AF07B4C9F8A7818E50864605C83 -:1065B000CF9691BE730E8C67F381BE15E7BBB16AAF -:1065C000029FAFA6FE2D1AFFB071FB481E32BE1F00 -:1065D0003377CA79E1A3440DDCA442199C04660414 -:1065E000D27F0E0B35E2FAD635F3FD2DD2EE16D161 -:1065F0002E8879053DED02D06E84A9DD3C9C0FB458 -:10660000D34DED2A62DADD26FA63A671F598716B37 -:10661000447FA4CFF5B4F3C7F4B754B4233DB0A777 -:106620009D16D3DF3231AE6E6AE78B69F7EF067CD9 -:10663000A6719979DC9EF7A576E33DF9630FE44FE7 -:10664000217A39943FA57C2E8CB3F4451B97115BBE -:10665000793E874157FB45BB26A4AB42CC5B6163C7 -:10666000AA294F85E7AD34BA673A0351CF7BE8CA10 -:106670003DD317FFF95C537B758D8BE9C5F49CDA2C -:1066800037FD5D11F1AA1F4C427FEBEA3459F8DB6C -:10669000AE69D05590630354537D4D86786FBBA689 -:1066A000810262223E02B2F29B8551FCDD33FE3F45 -:1066B0000B7EE13F8EC03FDB02FF6C33FCA2EECCD1 -:1066C000E4EFD595B327E17C0CFFF2D9A6E50D41A7 -:1066D000F7FFE6F95559E65765995F95697EF69596 -:1066E00055938279FF97E6B7CC32BF6596F92D3383 -:1066F000CDCFB972D905AD9FB5DDDDB66692B76B6A -:10670000F35F27FD7FAD88E326ACD41B56E07BE02A -:10671000ED76EA4F23F93E8AE99FA33CE8EFBB47B9 -:10672000548DE482D323935C60F9F6507E36876BF8 -:1067300026C885E7541F97DF02CED72CF50F2D759D -:10674000F8E56FB86FFA9861475AE47C3FFBDACA04 -:106750004CBE9FACF2F8E5E87D4D15B83938A094F1 -:10676000E44FA38FCB9FFD03843C4A837D8DFC4483 -:106770001924AF6C425EDD57CFF3D89A457E506343 -:106780005A11E1A759D80B2C9465DA370F4C9CD2DB -:10679000867EAB334779DEE23A1BD7C756D6339DA8 -:1067A000E8ABDE49F945FBA0DF003468057D0FCB7F -:1067B000E741DFC3724F7D0695BFACD7A8DC01E38C -:1067C00062F94CBD9F0560FC6DF563A8FC31EA8B56 -:1067D000503E20F4C52BD264F2576CAE872D339F08 -:1067E000F4482A1FA9F78D5561BC9FD46750FD233B -:1067F00069E6581BD9AD1D8D4900E7EE57F3285FB8 -:1068000069429A4AFB2F53C34A5249E4B981D78F50 -:10681000A44957E077E33264DECE196AF4C66F57B5 -:1068200086EDC664A8040F7307156F5ADC76E5364B -:10683000C04BA95BF4E70B347AE2F7F72D6C57E411 -:1068400016FDA5698DEEF8FDCDC47147FA381E58C6 -:1068500046474362FC763760BB429F986F56584E5E -:106860008C3FEE6C1C3725A53980F1AD2B6733D2F8 -:10687000476D69DA66292A3E141A50C164A0F39460 -:10688000D4E63A6CF78D809FE5C0F89AD7CF64A024 -:10689000679B1BDE17624E138F478DBF0EDEA33E34 -:1068A0008CEF4744BDC7EFA11C3B4B7C9F647EDF50 -:1068B000A397AF613D793C98BC646B32D79365CEAA -:1068C0009FCB571E98847C9F6CE7EF7F8A75D4B767 -:1068D0009633431EF1F609FCFD8F8CF65EFEFE1723 -:1068E000A27D4A0A9FB76B8A338471B147BE7B4948 -:1068F000E6DCC2C87C2FFA5EC1B0B951F37BE47B01 -:10690000E332E7BA23F3B9E8FB1386CDEDC3EE49D2 -:106910002D977B7264516E25371792FC1CE5A820D9 -:10692000B9336A60A98EFCACACE770FD87EDAE862A -:10693000863C822B88F2C680EB278BCD700DAE3162 -:10694000C3F5931A335C836BFB866B9D8DCBB5DEF1 -:10695000E083F1F5E8F11FFD37F3F8437E601EFF99 -:10696000D11F98C71F72E7571E3F1CBD2E9B6E3765 -:106970008F9FB5C43CFEA625E6F1B3967EB5F1FF28 -:1069800051FA78922D70C426F45D255AEFAC0B981D -:10699000F45368F78A681754A2F5D840C0A49F4200 -:1069A000BBD76D42DF35B5AB8869F707D11F338D93 -:1069B000ABC78CDB21FA0BCBD1FDF963FAFB8B68FB -:1069C0001794A3FBD362FAFBC080CFD4CE17D3AE0B -:1069D0004BB463A67199795CF82950A19FEFB30479 -:1069E0003FFA47964D5E4371AF812C20A1BFCF97F0 -:1069F000CA461D82EF592ECFBF4F9EB2EC62B43B08 -:106A0000D7249BFD5CE9766E9FD9EC0A95BE44566F -:106A100047F900CE60E68CA87C8B6A3BDFCF7ADE3C -:106A2000BB8399D746BD1F28BE5F23E2D469F6D247 -:106A300046942BBEC1D03E8EBF22538C6BBC67697F -:106A4000FE761DE0DDF8AF3347A3BF2832AE8DB729 -:106A5000BB588C9B151FAE35D97CDC45386E213E6A -:106A600037F48B6026E1D7C74BE3F9839EEF49FFEC -:106A70000578593DD9292B49F07E3DF76F1A7EF6EE -:106A8000647B9D13F3761B2F92D963D82EAB6F3F97 -:106A90004E53BDD9DFA9FA2A74B4F70655FA8A1401 -:106AA000D6FB770F97CBE5F1E20DA3C5BC9A2A2759 -:106AB00035E7C1F8EC90D96F0B84CDA2F3610A954C -:106AC000C0687B3CBF6D538129AF3E7950DF7EDBD0 -:106AD00046A15FF4CC033A8AB77E370AF8D8C602DB -:106AE000939E959C3293F4ABE486AB9DBE38DFADAC -:106AF000B5F4EF6233756C9798D6CC64EE5C34E9EC -:106B0000614DBEC7F83E94093209E33F693BC2C8F4 -:106B10003F674BF8790A3523149428CEC1E7896A78 -:106B200025FE24AAE1A00CED076D54593895B1FB60 -:106B3000E5C08D881F575E33F9C7549F2E219ECE26 -:106B4000D94257D379025017E3E57FCCB3733FF0B6 -:106B5000C3DACCDF65C759C7DBEC9A492F1DF4A90E -:106B60009D858B7B6F1F69C7E1EAA1D30CA04FE421 -:106B70006F8DD3E9ED8ABED84EFA5A968FFC8E8679 -:106B80007C35F85FC4B7E78E61E247BBE10F308F19 -:106B9000DBDA6C3CBFEF73681D15F7B94DF8BFE643 -:106BA0008A78F73C56E1C597A7995C8E7C759ABDAB -:106BB000EA2D8E5AAFB5763B1F678D8DFC5B463C48 -:106BC000777EB3CDE4EF5AB8D15C5FC066A6A35C14 -:106BD0005AB0C1C6F07CC76D167FD8BFE17C615E3C -:106BE0000B59DD2AD4D38DFCA0B93EA662FEF7E294 -:106BF0005F3D528A7943CD769EAFF301D08B16C5A7 -:106C00005755EE901DEDF97776155F3F9EE1F7A1A0 -:106C10005583509E26B3B8E78C6E5D6386AF3FF810 -:106C2000ADF032D640F0F60687BA558AEBBF7AD47B -:106C30002E99E244CB9CDE910CE4CC39172F7BFCDF -:106C4000297F74917CDF27E80836C0CBB89CAFBBA6 -:106C50001CCBFEBE3BD8CB778B9D1D76E48F5AB5FF -:106C6000AE5C92237126872DA00F86EF6C7B268663 -:106C7000073353BB35E7D9AE4DCA39AF76E5721F3E -:106C8000FD750A79F9C2B69FD9D1BF78FAA913D791 -:106C9000201F2EFAB5C29CD0AE739B8785715F50C2 -:106CA0004376942755BB94B871598AFCC3FC17FDF1 -:106CB000C24372A26A8723341DBEAFFAE53B231993 -:106CC000E0A1B3A1FBF060DC479F92787C34D8311F -:106CD00012F7AD2A95DD122F4FEC84A0BB53CF25C0 -:106CE000CEC27595B6EEBF99FA6DB9C1E688920F1E -:106CF000C7C4BE04EDB87FED4929941F477E18F143 -:106D0000AC534F4A1CBE3DB6900BE1DBBAD91E0016 -:106D1000386AB77E487454F68BED5EC443ED1EC5E9 -:106D2000E4F7ADDDAA841D23A93C8125C65124E0EA -:106D3000EB1AC6E563CDAEC5E40FAF6959F7A1E222 -:106D4000C5EFCDF40C78F18711AF6F28FEE958DF5D -:106D5000F973AF06A8FAA0FD712FE215FA9D634FF3 -:106D6000C278AED98F8DFD7F9A12DB1F63DD76A4CA -:106D7000AFDA96B57C3C0BBF7C80BF64C6C64F9C27 -:106D80000E4B1C6B6BEA79E9898BB69F7D3408E367 -:106D90009DDAF1D74783B87FFFBF8F1EBD13F59AE9 -:106DA0007D2E1FF27BED53AF7959D43E98E3E07C02 -:106DB000D7F9E4CF9F7818F8A4F3B8838EEE75EE78 -:106DC0007D6F8806F3ED7CF6BFD335687FC7DEABF9 -:106DD000C8EEBF6377D9C0BEF643A4D350F43917C9 -:106DE00091C7A4ED9150D902435E94967539B84B82 -:106DF000612E80F3F4314708F39A6BE1D9B2225C3B -:106E0000A7C5247FB1BE1CF05BB36DF587CAC878F7 -:106E1000780E0E9631C79E01BB64E03A5FFBED6FC2 -:106E2000946069A338492DEB26F969FDAEF628ACCC -:106E3000E765BDAFDF59F6B91D8378B5DBD6F271D2 -:106E40002DEB771A7F191BBB7EBA65FDCEB2EA9F88 -:106E50003E8C2F77A5C68DE71AF1AFC5BBFFA54FB6 -:106E6000BDC99003FDE1B752E270791C7A8503F940 -:106E700069C7D34F3C9CC6D7773A20A473FBD9216E -:106E80000CE8E3A4ADFB66948FDD7B1D3EDCCFAB4D -:106E9000F6BE41FCD5B9FB15BB46F291B925D0131E -:106EA0003A59CF4F3BEA0D3512AFD46EF1841DDE57 -:106EB000C83AD58466946B5E7A7E829E8738DDD729 -:106EC00084F65F27C559B7D58E1C2E8F433C696F5A -:106ED000F1963FD899DBBC9ED2185CC71353F0796A -:106EE0006FEB68CCDF87F3BF3C6A3DB7707EED8DFA -:106EF0002F3B373B54CC4730D6B7D3C6F5FDDA909D -:106F0000F4068BC3AFC6FE76A1F1D00687251E2AF4 -:106F1000E6DB1F3FF73F8F0BC3D3124CAA1C1D8B20 -:106F2000AF539FC797EF8F382401475DF9A0DCD896 -:106F3000FD496515C1C1D911784F8973B3A79E5218 -:106F4000424178BEAAE520C969AB5CA8E9454F7EFD -:106F5000C6186FCFFE9128BF4E1D788EE8B066DB55 -:106F6000093BDA4787B7EEB4771446E81EE57F742D -:106F70005EE4A967F68F24398DFDC7599F5F0B79B1 -:106F800057DB6AEEBF76DB87A6FE17055BECE417DE -:106F9000ED679C0F54FD069CEF07ED368679F71FD1 -:106FA000B428E5F1F49B90C366CA835AE5293D866F -:106FB0007E4525C5AEA1BC6B5AA1BF11A4738F3607 -:106FC0007EEE51D58F39802F1B93ED1ADAAB4D9E93 -:106FD000EB991625B79B2DF8F4A5F926625CCD3701 -:106FE000B9A224DA7E32E04FD66513FC7778CA075F -:106FF000E27909B4C3344C3250FDE45756BC53CA4D -:10700000713E8A4FF6B9E2EECFBC3FF4B721FDDB0B -:107010007C32D3A2E86B54D9F5C3D1D5A632CD9436 -:10702000BF7AEF641EC735E67FEF456C1303B97B6B -:10703000AFD4DD86F9ECC1AB795E201376BA17EDDB -:10704000F4EC587D8EE9BA86F287C40F6FCF7423B3 -:107050007F147EBE0FE0C898BF23FB4999FFBEA2F4 -:10706000533E8F1DC7CD45FB2944CF135998EA8A5B -:1070700093CB1F0FABA3E749ACA319CF30BDEDA84D -:10708000F8D401CFEF2B4F9138DC61CAD74816E313 -:10709000C88959997DF13F9BAC9E8AF6FB38D8266A -:1070A000B24BD0EDF8456A040F463E9CD1EFBDAE21 -:1070B0000912EE3738BFC178AE479C9FF7F5CC5721 -:1070C000A7FA00A36E19075BFA4AC5164BAC1890D5 -:1070D00054056F0D68263FC720D64265166BA73250 -:1070E000C5E9935482EF2DF24BC9ECCFEC8B440BE6 -:1070F0007CE7A18F9F93F5E301281B6DE2F9DB9EEE -:10710000D0E350DF90CC4CE783739D9CBF2F77CAB0 -:10711000865F26106D7735B26A9ABB2B8D1F63315F -:10712000BEBBDE1918EE8CA227C5DDCEF3BE84FDF2 -:107130006BD8EB5729CB29FEBE3A83DBD5BDADCF4B -:10714000CAFA0A935D6D2D9B0738E76C66043FF71A -:1071500053494E7E7E59679A2F9AFE605C67697428 -:107160003EA3AE937D2FDEDB607AF8D28178546245 -:10717000E96F06D2DF68A4BF0ED14937F9296E57EF -:107180000257E37C33F2EA24FE3C2071BF97AEE065 -:107190007CD345FF72627566A08F79B259401F514A -:1071A000792D1B84FDA8AA4C4D284278368975B7E5 -:1071B000D2A5393FD5D0D7DCA2E6107972BF2979A4 -:1071C00095CEA3A8696ECA4F719734DD8EE77C55C2 -:1071D00056E743F9E936F24FFC3C9FD0B08B5D0592 -:1071E000E63C4E87256FD526ECEF983C6EB1EFDE7E -:1071F000830FE2E8C3D67DF77667FC3C2436267E13 -:10720000BEA0A1879D2FDD5BEDC86A67FB611ADC1C -:10721000A7539EA52AFC0D13AFF3911FBC6B9BC413 -:10722000CFAD59E8A86B47D2489487C8BF78CF45FF -:10723000A2782E6DDBBF1FF5A6262FD3935348CE21 -:10724000694A2E9E971AE594A05CBCEBC3977F8D8C -:10725000FEF55685E1D6DCE536E2937A322E5622EB -:107260005B6F5ADF0B9D4F6C5C91F3DB129FC16F1C -:107270006EFAFECC3689CE4F296CF88FF1FC436D47 -:107280009B8D85E0FD19C6FB3FB389EB030B5F8443 -:1072900051F03CA8181FF7A5E8FD23B53C8169D142 -:1072A000793C41BD1DCFFFCF13F8185091627AFF92 -:1072B000D7B9E56DE49F09F07B0006CE1A64EA6F4A -:1072C00091B27C2825E1093F8606FF90FE8CF99F4C -:1072D000930376BE4F542485499F01FB17ED86909A -:1072E00044F94A567F47CD1E89F6A7DB607FC2F37B -:1072F00038B7852CF6A3258FCEC0B7952E0F3985CC -:107300007DE066EE5EF0EA0F97507C94F86AC98BD8 -:107310003C2F6CC976294479CC1D439318E159213F -:10732000BFD17BACEE41D83922F46BC19B23C38C17 -:10733000679766C673628119AF1EBF198F563C27C7 -:107340008DC931B55FA454DB89C8049E0BE01FE2F0 -:1073500019E420CDA306E611D662F159D97AEF2AB5 -:10736000F46FF48B470BFE4E59F07796B5EEE76F4E -:107370005985339D589BE69DA986897FACFC66E0C4 -:1073800029CBD73E919EF93DE42FCE109D48F3F8CE -:1073900077839C2D9C798AFCC46F467E7062CF7E79 -:1073A000F90EFB02CAA5330E9D98CB62F96B1396BA -:1073B000C0D72DF54EDFBC7C8C4F33DF3C1BC6ABFA -:1073C0007D54C6D947A97FA047DA0FEEC1B8641A29 -:1073D000F2B54AF12B5CAAE9504F6CB5F9D06F7940 -:1073E0004F51F735A8B7D7CEE7798E372770FFEB27 -:1073F0009204BEBFDA12785EF35D1532D3D1BE6F50 -:10740000554212FA8B7CFA8B57A2DED56AD3685F9D -:10741000F375BFFC1D7A5FECC3F86EA6DC3C0AE195 -:1074200080F6E46FEF6A7DC77B6B94BED3B9E7FE4D -:1074300061B8EF3C24B3CA787A7CBE8BC3D159F0D3 -:10744000E77424C7C5CE6EB2A35777D455E0BC0C01 -:107450003BC2BE8BFBB76AF6CC207DF2D0027E1E0B -:1074600073F7297E1E738A32FB9B23A03EF6359567 -:10747000CB4DA64F9F93CE5328701D3760BE24F28C -:10748000C17FC9A106C24FF3EF314ED5F81795A1C0 -:10749000FE5852B780F69F5F7BA7B46159AAB71414 -:1074A000235F4F6E4D9E88E7646ADFE27995A3DB28 -:1074B000CDFE1CA6541F443FD8D9637C5BBEFC980C -:1074C0006AB5BB14DC8FC776989F8FEF876ECB5C55 -:1074D000623FF2B2F40BC98BFD91AC4F73917F9474 -:1074E0009FE3F2ABF1EDA74713B87D037891504EBF -:1074F0007575337F03E0A96BDE209A6FD7C7FC6AEE -:10750000A6AECF95F278F6D12D2E4E2F0FD979DC7D -:10751000F6A105EED00A98C781055517A35DF4C9F9 -:10752000BF052E8E17A788D8072C49A63D4F4F625E -:1075300063902F9AF8F932D69C19EFFCBCC10F0664 -:107540007F187C91B9202110CF7FF98E8BCF6FD21D -:107550008202CA83EDDC27518CA7B301E0EA038FD6 -:1075600041D63018E1A9DDF311F9179CADF1FDD03A -:10757000F5784803E9B621B8623CE0EB7BC0D44122 -:10758000E4077B7376BCFE836C03F99B16B834E288 -:10759000B74E27B7A399DA9C39D3837C5276F52A64 -:1075A00080F361E03F24F9876C7E823BB89831F22A -:1075B000AFAA9CFFB3AE619BEF8AB2B7D6BA263EA4 -:1075C000E082FE1E70F178476AC02F21DCFEBF9F6B -:1075D000F362FF5D9F3A68FD06093F8FF15D8BC046 -:1075E0004F5982FE23FC9E55A69130F407BCBE790C -:1075F000B0FF5FB607F01D27BFCBD077520220FB4C -:10760000009E14B74CE756D0DE427BA296193F414C -:10761000523E0DFEC34366783ECB90B752AB14F694 -:1076200080DC2C71BAC3E84F49A98479633C8A395C -:10763000797FED667D14252FCA5D94013C599EDB50 -:107640003B861C36E477533297834DF7AAA146094F -:10765000D3DF3B5CE83FCED6B549985A95A26A94F1 -:10766000E7705125F3075148E63E92DCA3F78C679B -:10767000ECD9BF2B71FD1B275DDC1E294B08FC0AD2 -:10768000F135B2ADFB00AA4F7E174BC5F59E22F433 -:107690009BB1A7B93C32F2FA6B85BD619547CF012A -:1076A0009DA3C018FB0DBEEF8D3DEDF623FDF4C884 -:1076B000A10553681F2D6A2D3E88F939456F717EEB -:1076C0006442FE80F54678296D0B2A880FABDCE911 -:1076D0004FDE18F2C4BACEA05CF7D4B30029C56D52 -:1076E000C06751FBB7554E1D7389FD55C8A9B36CD2 -:1076F000C2C0ABB4083D152DF31F7444D18F21A730 -:1077000022F414223AB48E2331674FDD978BF2E5D1 -:1077100088827E90AE893C3EB942F051F2C7A1AB5F -:1077200071FE1B5AA7BA90EE77B4953991AD966465 -:10773000F0735EEAFEEB824C904F745CD7C69C1AE5 -:107740009E291F0F2B8FF8507C508F9AD79966492E -:107750009C73D492AE8B733F82512EC9E0E7B8760A -:10776000B4E524713B334CEBDE43F7C20F61F08587 -:1077700041EF56FA36F8A19171BF84A13F28528B90 -:10778000B00BCD7E8146C3CF1174519CF80EA10F72 -:1077900036BA2F5937017E6D0A4FF2615CE20E4F07 -:1077A0000EE533DF3180E3CD8A07A3ACFD14F4C3CB -:1077B000A8BCF35AB59BFC5AB59FDA4DCF0DBCF669 -:1077C000860F03AFE310AFD297C7EBA7B8BEA36392 -:1077D000F1FB65E79DB5644CDCF372FF57E63D9E17 -:1077E000057EDD4176173FB761D097212F4A976E0E -:1077F000CC24E26837DFEB65C891317BEA0EA28AC0 -:1078000068951397B5B26B114F63C32AC3A32EFDBE -:10781000C98D8FF1974C3A7F716302F0DFA817662C -:107820002DDA068F466A2C753A0035B25D2539C6C9 -:10783000DACF2F0ED512FE381DFD8B865E1A8357C8 -:10784000A1971AFB8B11075A9710A8C4F1A53DC048 -:10785000375ECC3FE5F6EE5A57605102B44F0498BC -:107860001330D7AE209CCDED53335FF6C687891613 -:107870003E6B01BCD03904D8E7F2A558388CF1F33F -:107880001292399C406DA8BF6495323E580DBFCF0F -:107890002E6B240BE03E8CC736719E6B85FE759770 -:1078A000A55CEBAA68C079D9541674147D79B80D1B -:1078B000BFE0BA043D88F87096EB348FC13EE647CE -:1078C000BD7EB0DA22F9018E946A4DEA71D618FBBA -:1078D000379EFB99AE4D44BA189CC7E83CEC60D487 -:1078E00083E2ACCFA6041EAF5DECEC388C21F3DA5A -:1078F000E975E5DE3EE2D3917B06FCC24F65CEC35F -:10790000E8DAFBC64518977CFBDF3FF260DCE94F05 -:107910006AB707E13CB9FCF71EBCBFE5EDE5DCCE7C -:10792000B8D9A2CFEC14F84B4EAC780AF1774BFDE6 -:10793000DF4BA3F99D2DE37194DB420A1A9D3DF4C0 -:10794000BD686B22F9E68CFAE2965453DDA0D3C5EC -:107950000E9E27659DFFFBC28EBA6DDB66FB600D38 -:10796000C70FB422BE4F0A7DEDE42E0FF9330C7819 -:10797000E66E1B65473CFCA9D521E2F0ED368E7F13 -:107980007D3AC6CF026229AC701EDE9748FDCD7FDE -:107990004021FD620E8CB50CE83BD07A1BD9D9D6BC -:1079A00079CC7F5B9B3210D66FFE5A89F4526CBF44 -:1079B0001CE821B06C35C5D9ACF39C13B4C6339721 -:1079C000939D6ECDF398C7B47513B2E3E47BB4F224 -:1079D00038F9C27EEC9A3F26087DA1945D8EF9E8C5 -:1079E0006759E18F0AB5FEED9A93F58C92B43EA8E3 -:1079F000775279AADE47E553091A8F67EFD97F9846 -:107A0000E84B6D2F457EDFD1F64EE24D5A446E5F56 -:107A1000B1F9A3833F817A31E3FE1BC33F3E5BE0B4 -:107A2000FB4A21BF170A7DA0F8D3BEE5F76C9CEF97 -:107A3000C858780DB93D1BEF958DC28321C7ADF8AD -:107A400038D3969B887421255AE3C05F0D2FBD7DE6 -:107A5000B758899F3768F0CF53C21F306FCB8C5512 -:107A60008360FCC6BDEF0DE1F702B3A3281F0CFA3B -:107A7000B4D21F637576E4E71E3A6BBD9BF063D00A -:107A800005F05186883F66A0DD67A5B7FEF2893A0A -:107A90006D1D43500E58E9AB536271EF154D4DE427 -:107AA000FEF2799A3E05ED50D85E56F1381D973FAB -:107AB00027D5E6C377227F6EE1FCB1F857DB7F89DB -:107AC00072A7EA170F7851EEBCAF36A7E378D58FCF -:107AD000AFF4629CFBA41AF4E2F7EF8794B87985BF -:107AE0000B1325E10F37E72BB035C16B906F3F7952 -:107AF000DCE6433F43ED56078F83EFE278833A8F0E -:107B00007FEF8A9FAF50F5F307D2359EC76ACE5BF1 -:107B1000D862A3FC13F497E130BDC5717BE2C22D9E -:107B20007DC7B76B77AD8B9B7762E40758E9F606A4 -:107B30000BBD025EC88E09023CE4161771EBC62726 -:107B40007F3CF204C0756ACB6FBD5261B4DF9CC745 -:107B5000C7CFB4DCFA530CF1F446AF9D82BE237A52 -:107B600043286E1E43B52DEC453BBC7AB38DECBA71 -:107B7000EAED0A73623ECB7107EDDB8BB6FFE6F5EB -:107B80007100DFA2676D69D3F934285FC158A79EE1 -:107B90003C12B12E553B7FC3E3BD9AC82711EBB30E -:107BA000E8D9FD76CC8BB1E2B1AC65BFBDC3928F95 -:107BB00040EBD472620A9DCB7BF29C1DF7D3F7F7A2 -:107BC0004974BFB2F5FBCACDBFF1A27C403C515C09 -:107BD0005EAC57EFF942E16B9E2FA176E487EB6D27 -:107BE000FDC6E0DE3A9AE8FB99E761FCCA371D94CE -:107BF000AF54F9CC52CAEF794FADE374FEC8CA74E2 -:107C0000DC5F2B6DC1741F95FC79E5A3DF25FA5B62 -:107C1000F8CA77D3F9791E3D93FB6D829938BFF985 -:107C20009BFE85E6B7800588FE2A1F512AD05F7229 -:107C30005665E5CFC6E1933F093E79EF310706511E -:107C4000D97BC26F197C5511F7FE5AE349FCBE95EA -:107C5000B3C28EDE95281BF71439A3EDAADA2DAB3B -:107C6000DB717D3EB8481FE8A3B8BE1A14F89248ED -:107C70001F7FE5AA81428ED13D31869E5386CFB1CA -:107C80007DBB8DEE8B89FACE74DFCB1D627C803B91 -:107C900041BA0CCAF4F8FE4C8F5B32E0E3F92F06D0 -:107CA0007DF5C6F75B783EC9C747B95CC1BC187A99 -:107CB000DF6E0B0F34E5C3384CF78944F23D6C821C -:107CC000AFCDEF014ECA57E9C1EF3E89E2AC0B36AA -:107CD00038CC79703D7463BDE7C69CBFB2D0A26F4B -:107CE00019A5552EBC69910B6CD3F9E5AF54DB4255 -:107CF0009477547DDC41F643F5765B05E2E3AFDB38 -:107D00000EBE7E13D0F95F5B0CBE35CB572BDF5612 -:107D1000EE18CDE2F1ED5FDD7E16976FE1795CBE86 -:107D20007547E2111AFBFAE4EBC25EE4ABE28ED1D6 -:107D30000792302FF783A7165D4C7E060B5E0DB9B8 -:107D40006A95978F246AFCFE8298BC3ABE9F47F2E0 -:107D50001D39FE0C7AAC7A7A318DD343B7065D1AA1 -:107D600074DB4B9E96158FD6F72FA23C1A10EBCFE3 -:107D7000084E620578AF5EA39D15A0FF392827F84D -:107D80001FCF8E93D7C1EA86A29ED1E8CE8E9B9F4D -:107D9000EB77FBD08CC573654ABC78B7BF4C8EAB14 -:107DA000C797B8B95CD98BB40065B59BE3AD49C43E -:107DB00057C012A4BC7FF429123F257B899F6CF029 -:107DC0009CD1B94A3F9DDBF627CA1F69A08255B8EE -:107DD000B5292AFA538BE5A5B9505FE82EE6F5F1EF -:107DE000F2CE1CA8DFE62EE1F5CBE4621B90E61391 -:107DF0006CF494C950AF31E6392FC9E4DF50E51374 -:107E00000F62DC457D9EDF17B70EF8DA591489F74B -:107E1000263A58D05584F7344209F555D9BF5F85C5 -:107E200046E00647E01A37C9A3491AE2F594CF495C -:107E3000F932773C7715E56756BBB9DF78F8CEF1B4 -:107E400074FFEED730FECDEE01BD8FDF64E3FD9C05 -:107E5000DA31BC0CF13AFC62467E0803FF45AA46C3 -:107E6000CF5D2D78F494F83F03CF7F3426DBA99FB4 -:107E7000EA9EF53ABFB251E43528899C0E9424B9A4 -:107E8000EE5928978AF5BF43E0037FD05EEEDA3BD8 -:107E9000F0317EDF53F7105C5F4539F347D41BBBED -:107EA000FF35D18FE757DE4CE0F8BA2169BDED52BE -:107EB000A81739872C45A27E53DAF65D2CBFED0951 -:107EC000FC90E39F85B1BF9B6E56787FEE3A0FDE44 -:107ED0009F26E95C8F96806866031E1A75A6D97383 -:107EE0009145CDF9168A52D41DA6713DA671591639 -:107EF000EC83B04E378CE5EB0438A57DF18D31BCB9 -:107F00003E2B94D3D8A1111CF7201CA31CA18BD00D -:107F1000FEB909D4224ED766FBDB88D3D7FE4526AF -:107F20003BB356D21ADD50DFF91623B9DC99E015C0 -:107F3000F907FCDE19C32F31F6A5B965B864257BB6 -:107F400016F13C0EE18732E2E86759AB829389F182 -:107F5000535BE4E178B69EE4647FF1B19FBB457C5E -:107F60006C101B7481F1B167DCE7111FBBC86DE8B1 -:107F7000F322DE2EF6FF334772285F485531278FF4 -:107F800031BBA6508A88F1DD2E8BFC35E878C451D0 -:107F9000DFAD88971147D92DDC5EEA253FE224A3A7 -:107FA000BCE6511D05941F61B3E6471C9329E1A966 -:107FB000F4C5620DF1D924E2C6171AB737E2FEC53F -:107FC000FC514C1CFF796F39C5418B7DF1E3F8E31F -:107FD00094D914776047F8FA19717CA6142A08E737 -:107FE000D930D86008E751F3DF01B93C2DA8505AC9 -:107FF000CD5BE6E7E32C74605DEFBF58D7FB7CF305 -:1080000020DEE7F7AA8D6223290FC226F2207EC95F -:1080100002F747E7411878EC2FCFC49A5762CD2377 -:10802000C90C98F134B8F252D3FB8BEA8A4CF58B29 -:10803000978D33B5CF868D30BA9EBB669AA97D7E6B -:10804000F34C537DE8C69B4CED8785E69ADE0FDF47 -:108050005AD5E7BA8F6859627AAFC8A162BC0FD20D -:1080600058F7CBF6FC202E5D18EB6EE46961BA116F -:10807000E27734ACFBC3D9E43F2A93B4D8F5F78751 -:1080800083B42F5FE8FAE77B843E7481FC3E0A8963 -:108090000DE3443AD713BB6CEE35A81727036C28C1 -:1080A0006FADFA4572EB0BFF2D79E3E55B682B9022 -:1080B0008EBEAFE86371BF1F20F2239B64719E7474 -:1080C0009293F4817B64F996E87BE4AFF0703972A7 -:1080D0008587FB557E02FB26EE9383135990F64F5E -:1080E00071BE9CA1430AE6EB4D65E2FCF963AB2649 -:1080F0004FC078664781968C2205EADF88C8FD9BD1 -:108100001C5A23C60346295C8E837C9FE6198DFB8F -:10811000CE721BD77F8236C4F360270B7A8B68DF61 -:10812000A3B866324B939614A2E9D5B3BF685F003B -:10813000311CAC1A9E8476D0CB383406699D09B4C4 -:10814000FFDF68C8BDCA6124F7CEB87BEEB5A0F3E7 -:108150008E67E6E5D2F3E33703D701FF1CB79BED4B -:10816000A2FEFC53959BEFF7A0FFFF780133E519C2 -:10817000547BB81D55ED5178BC3CF49774444BD7F3 -:10818000FCCF2E41A06BA5F65528A2576FBCBD822F -:10819000F27677CD08A2FFCFF03B1BFDD4B64E643C -:1081A0003DF707433F37BCC1FD5F377C66F6E7DE2E -:1081B000E9E179D7778AF1AE87C20778BB1EEFF481 -:1081C000C6F2850953901FE0795882FAB7DB40F573 -:1081D00003BA9F11C8B6213CBF67FED7764B98AF54 -:1081E000ADD1F7D7B10A1BC2F5FACD8B3DD8AEA7FA -:1081F0003FA39FC178A613F6E9E4A02D1DE8A7FBD5 -:108200001B12EDEB309E139F57CC1EBC12B70E63B2 -:10821000BCD759E0F46BB0DE33999FFA35FA672C7E -:10822000C1240777542EFA536A0ECA3F99FC1F4B9C -:10823000F63A48FE75559DDBFE20BCBF6570C7450C -:10824000A85FBC59F5D92588971B372A4C83F50FB1 -:108250002504EEF344E1EDF8BC8F3CF81EF484C72E -:108260001FC44DFE69079DF37AB3EAE94BA2F5EA14 -:108270004D9E893FF6E03E39E6FCE23D654F0D2319 -:108280007BDBA0AFDB047D2D797228E9834B3CE6D4 -:108290007B53963C9E4BE7894A2516D78EC47B3F7D -:1082A000302F7D07D0159E23DCF729CF1FDF7924DF -:1082B000A598CEA3B2C07684CF68BFF3E59B865362 -:1082C0005EE7B1B4F3BB1719E00BA27EC5389C2F53 -:1082D00009FE98D59A5A2CF4BBE7106F37FDFAC9FE -:1082E000D37F40FCEC7DFAF13BB14DC9F9E18389C4 -:1082F0007DCC2FF000FB18D93F5D2CC1EF8863FFC8 -:108300003C2BF4AFEFCB3AD925E7E40A91BFCEED91 -:108310001045F667601E774BAB928878F3A2C16276 -:10832000C817D009BD78FFA2B83FDD09F6D9702182 -:108330007FDA3D1F4F69E27108935E5772A8CAA4A5 -:10834000CF55C03F94F7976F0A34E23D8DBDEA7573 -:108350006199ECE12FABDFBDF325E57DA787F37FC6 -:108360004B0197DF2DE18410B71B5831EA7BCFE03A -:108370005CE0FDB464BE2FD8A5CE0227FC7EC6F318 -:10838000C9AA3559B0DC791C1F58C7BFD3C3DA3826 -:108390009DF6E87F872EE57F674E9C032E11E7A2AE -:1083A00063EC49E02BBEC92698F4C7F0E1BFD13990 -:1083B00097ED29DAEFC6A33E0F7A0AF2BD4BEDB076 -:1083C00027C799DF2F517E027D8FF572FBC4B987D5 -:1083D000C7E19C9A4EF79EB97CBE51682F19ED4FAC -:1083E00089FD66F1E13787D8619D4ECB47BC1847C0 -:1083F000A8DEBDC38B66F2658981242FC64B8EBF74 -:108400005AEAA37CABCD43D0AE6D09F3F8C408950E -:1084100005D538F735D76E2CA64BBF6B36A652392B -:108420000CFD09F0A836CCE7D9B9A731259EBD5D72 -:10843000FB1F7B07E1BA3D3D809F971AD15ABC10C4 -:10844000E51FC2620339F7D4A7C3A9BF4BBCD93417 -:108450003F185FC5E7209164BCEFE86961AF757EA6 -:10846000AA503BA3DF117B262A3E58CBC270F301F2 -:10847000B20F5B1D1AAEB36B0BBF0FCED5EA22B99C -:1084800057BB6F2AB7E39279DC737B42F71FC5397C -:1084900036FABB042E5F334B81FEB7DBF9FE380C96 -:1084A0001860873BF2DC18CFD5FA634A6A77E6F1A9 -:1084B0007BF55C6A33FB863B1AEF1EC2FB542FA789 -:1084C000ABED096119F376BA81261F23B822703209 -:1084D0001AD7807318E9F3DBEDDDEFE2F94B3A5F71 -:1084E000A7211C1C4ED63A5443BDC2E5E3F15B976D -:1084F0004FF307A558B86A47829E0BFC764F038B53 -:10850000FC7D04CC634B88D49DC013DB739890072B -:10851000C3564FCE8AAE83401A13F97EF63DC35739 -:10852000374D203B27A8A05D0FA52705E7C9F737E2 -:10853000BCBF604011C703FA89139DFC7D4F7B27A8 -:10854000BFB24475F376FE245FE23489F5DC676AD6 -:10855000F89DEE90C2EF5E89FEADF081911AC05297 -:10856000FDC2F344B78BE4D6074768782E31B000DC -:10857000E9F5576FC90CEF47FAE049179D432E788C -:108580006E33F9ABADFDAD3ED6701FE665773D2786 -:10859000699807DA65EBA6B8514DEB7B745E71EA1A -:1085A0009E13746E4B490AD47947635EC48A32C401 -:1085B000DF58D6DC88FE3D908714A76FC9E0F2E350 -:1085C000CCD14B1E5B1185EF07BDC2BFDB1DB818B8 -:1085D000F9A655F0E73ED46FA0DC2DF4ACDDFB6FBF -:1085E000CC8D3E87156407C81FD6C00E517EA1F101 -:1085F000BC2BA4D239B0E1AF3B6FD1A3E8AD59F0A9 -:108600007BB3182F3F29B08AF876FF9FED5E0DF3FC -:10861000585B86A0DC6D013DACAF7CC65A0BDFF425 -:10862000E4B79CE4F771C3BA3625C13A3DFDFA9E22 -:108630004BF1EF8B00FC8CEEAB3AEE20B9B93B9BD3 -:10864000F3DF8AD73E198972EB93BD8B2E467C2DC2 -:10865000F3DA0C3A9F9480FCF42C233966F0632102 -:10866000F2A384F742713F4A21D239F29FBD7D1AAD -:10867000F1DF6E7E2F04D039D13DD0B90FF58B429A -:108680001FD03D7D3F94F8797BBBCCCF81831CCF3D -:10869000A7FA24CA57D9DE3ED947FC2C036A8B902F -:1086A0002FC307A89F16FADB75ACC4729FEB294C49 -:1086B000D21810918F7FF3703E6D29D092FC309FBD -:1086C000444531F141D43EC9EB621F957F74D3EA32 -:1086D0000DF8F7C3DAC5BE20F4AE7D42CF65C7B84A -:1086E000BC5F2AF6B225BF19F7ED6D30DF252F29C3 -:1086F0005CFE0B3A3920F4E043F51954C7FD428380 -:10870000751A0D25DE0754AAD7E19F2F6163CA9B16 -:108710000F6239AEA2A50C8F4C4D98D57E909F610B -:10872000D38723FDED3A70F570CADF3DEE6098A265 -:10873000B8EB6FDD7F7C0AF351F701FEE3EC4BE809 -:108740009F6514BFA9207AEC8D6EBAA48E6BC6FB10 -:10875000410FBCA77AAA0A1B7D0D1206E0E3F57B48 -:10876000AA56E3BD803725E9C7911E97FB02C79142 -:108770008FBA5EF95B3ACAF4DD47FFEC4579BFCBAF -:10878000AE0F473ADB9503F6401CFA3C2CE8A7A451 -:1087900097BC8ACFBCDC5EBA24C8D621FDD4EC528B -:1087A000E8EF169CDEA5E8780EFB5D3D908E7ACE54 -:1087B0004916BC7E3CEEEFC2AE9DCFD1CEE6A3DE25 -:1087C0003292EECB30D9994C592ED33DEFAD12F900 -:1087D000272A2D7A48356B5E3518F78DD6CD769CD5 -:1087E00047D516F3F7D5A8BF8CC4B26F7BF533AF6E -:1087F000D05F72592EEA2F403FE49FE87E4DF13F53 -:10880000C628BFA70DF37B9E96397E405E121F1AC5 -:108810007ACC569F7E1AF5CAD3824EB70B7BB47BB7 -:10882000BB44F9FDC3B6F2BCEB7127B5CD8CCF9F2D -:10883000F2C22A851C1CA7F2F8C5B8A3B9140F1DF3 -:10884000A333F2872C68954288C74A43AF13E729C0 -:1088500060DB25BD6E2C0B35E2FD720BB74A740E42 -:1088600063D156B3FFBE7AE32B87D13C5CDC62391F -:108870001F2FF0628D6FECC05FE2C4372E4E12FEE8 -:108880009C216C88E9BC55DBF99DB7FAAB387FFDBC -:10889000AAE8DF68372189D34D8D986F754809891B -:1088A000BF4FE9C6FCDB5B057DDC2AE8A39685EDBE -:1088B00098BFBF78039F2F5B6F33DD5BBC60D7ED44 -:1088C000741EC14A4795DB78DC0D1048F19DCA4DF6 -:1088D000E6F755021F55167CD404240B5C5CDF8E32 -:1088E00085ABE57A5CDFC5DB6CF4F739AC709D6570 -:1088F000B3298FE81F0D9F759DAE33D6E95276A937 -:10890000699DCAFBBE9F2062DF98F5DF670F5F4A53 -:10891000F92E67DA72C87F60D087B59F29427F9EA3 -:10892000BA91EB99A7F794258E40BBE888EA97A007 -:108930009FE2973EF6E2798FA2BD0AC3B860576BFB -:10894000F13A3CA7BDB32DEF5ABC8FA2E82595F6AE -:108950008DE2978AE85E90A2978A1273298F424B24 -:10896000457C403FB4EF761DC9FB7D21CACFB6C917 -:108970002588E615478A12513FD8C9B83F427AA9DF -:1089800024B5236A1F599CC4FD03AB32DEB907F539 -:10899000F7A9CFDAE8BCC9545BF7CB987FB0B34DE9 -:1089A000F5AF807AF54B731BF09E8AEA27253FAA24 -:1089B000D987DB97A47D07E9ACD5E67310BCDF3D12 -:1089C00080EF83DB247F3EB4AFDD7BD5F0ED98E70D -:1089D000BDB9D81F7D2EBB2859BB1FF32A5966226B -:1089E000D9DF532FB2D17E7A6A50E2CFE83E167DAE -:1089F000F31494B3A79EDF69A77383DB2596011355 -:108A0000399C71F019BADFE397AF50BE42D9AE5727 -:108A1000283FA137797F3AA4B030D9DDCD742FCC6F -:108A2000E2CD46BD83CE415408BDA966CB09AA5705 -:108A3000A1FE0FE3556D52421AFC7A70EFAF28BFCA -:108A4000A1661BCF6F80F7247FAA307EAA45E87C01 -:108A50002EE3743057C89F458CDF33B4A8999FA389 -:108A600033EE4532E87CFEB639948716936F86F66E -:108A700025C5219A89BE63EF1BE2F46DBD77C84A14 -:108A8000DF2D067D0F63C390BE3F99C8F3C33E79C7 -:108A90002521B110E6F3C98B0AE5DDF741E7B49F64 -:108AA0001E11FBFF99B04CFB93D1AE73CF47B48F2F -:108AB000D41E3963477D754AEB87B40ED35BF74FFD -:108AC000463C7F8B05AA116FDF6A4DF4219F4FEF63 -:108AD000E0726B5AAB23847EEA6FB196265CDFAE00 -:108AE0007D3F6F4A417A7982D38B21CF160A7C2E43 -:108AF00014F85CA8F2FB9EAA0AF73F88F9D0D318B5 -:108B00009737D35A84BCD964C66F97AD4525BA1937 -:108B100021B1E6ECD8FD6E11EBA0738F5D99C3E92E -:108B2000EF4906C15E453DAC7A9B350ECEEDFA1A93 -:108B3000CB7E7A30C9F6A5EEC178C7B22ED3BBF989 -:108B40007E360DE809E3216DE18642947B067EAC1A -:108B5000EBD2A6E526F575DEF965A1B71BF56F8B9F -:108B60007B265A7CCDEE683BBCDCC7F5F0AAB14A47 -:108B700010D7B5C75EC93B38529323F60AD8299F50 -:108B8000250DE076CB28E8FA852C85A5A545EC9542 -:108B9000D519F74F2F4AC3FB23B8BCE81C03FD616E -:108BA000BE80CA484ED56E7384D0CEF81F84BFB83D -:108BB000BB008000000000001F8B080000000000C8 -:108BC000000B8D576D6C53E7153EF7C31F8913FBE0 -:108BD0009A78662C34BB31F9202584DB109A40D773 -:108BE000F626A51D83141C58296AABE2B65BD90A88 -:108BF0004E5085281295B889A9D6956942DA7E54D7 -:108C0000EA56DD226D621BAB4C096A9892C8A1A19D -:108C100025E990A0401BD0D659FC60EB9490C0345D -:108C2000D24D95D873DE7B8D1D12B43A528EDFAFD4 -:108C3000F39EF39CE77DDED75D7DFFF29AF544DF7E -:108C4000EDBFEECDC2C6FBA54709B63A94F069DF89 -:108C500020EA20F2449A60FB242343B0ABAF7B139D -:108C6000254423558B4209CCBBA1EAF335B46FF1FF -:108C7000E7E1BCEDFA52212A23EA84D5CBF2FD9D2F -:108C80006AD6CBF33BFB25D386ED3DF99F8ACA52CA -:108C9000A2C981E98AE760576832FE71FFF796A89A -:108CA000D877EA928F6295D8D8322FD0FD442F9290 -:108CB000F3D9A611ED9987F6F04BEDD4800E697FBC -:108CC00039B5C0AF878C0CD6755E540C4B47FF0985 -:108CD0000F513351F7277F1A9E1721BAF6AE64F869 -:108CE0007467FDAB8D683F6FEF9F87F9377F27195A -:108CF00016A6BFF84DA287D0BFED4DCF95ACDFD9FA -:108D0000EB96F89FBEB217F39247FCFA1B687553B7 -:108D10004F39616E0FED1736493FBBAE04E1AF2FFF -:108D2000E5655CC82E581F23DA7E78A6BF24A9F912 -:108D300036F2DBF397D68EE182F1355A69E46A00A8 -:108D40005FEAA8EE96C2F1171F90B0FFE488A2F97F -:108D50002481DBDBDF2AC4E734C058C0FD4526216F -:108D6000CFC973257611E6FD731FC66A89C6F7C1A0 -:108D7000B90F7E5A148187BCD2B14B06DF8F713D8B -:108D800019FFC452A23F0CBE7F2FF30109883A6C31 -:108D90003F8C798B0BE24E23A88238119791C17ECC -:108DA0005D9F2A06DC735C35DE483EAEE36A3668BA -:108DB00014F0637A9FD9315C8D72492745BD64698F -:108DC00058D8DBBC39A1C4EDFA7C1BF96C35B1FE77 -:108DD000299717A44E45E388F3590D45043FBBFB83 -:108DE0009DFACA038EC5FE9B8971419BF79F35DEB4 -:108DF00066EDE0F19B9501B218B72FAD766EEF8E60 -:108E000029F406DABB3F79A9960AF6278E13F5ED09 -:108E1000F24C4599B75DE764115FD7B91BD12AB40D -:108E2000D7D23BAB35B4D7517A3F8F7F180BFC8834 -:108E3000796DF1BEF3F37EBE0829225EE27CE1CFBC -:108E4000A25F3A7EDD7C7B68A3C0A1C7E5D50B217C -:108E500059CC7F554BBCC2E770F2DC7FA3489B8E98 -:108E60005FB812E47AE5EA7DE7B9BB1D3776E0F535 -:108E7000375BF5F34F83078D23AA15429EC7C68A39 -:108E8000EC76C66560DBDFF672DD2EFB88CFC3EEC5 -:108E9000C16DB5C47E138965719CC39B833F5EC65B -:108EA0003890D423E2B2383EC435D17731AAA33FFB -:108EB000397031CAE3C9E32B7E6161FEF2338DEB79 -:108EC000B8FFD86955F0AFF14C93E0DFB13F37956B -:108ED0002DE2C0C908B0DFE4881A677C92234D1FD9 -:108EE000B7635EF24C5B93C4DB9C692A63FD592E29 -:108EF000513C8D7169A44AB473F9FC5C73F09B1CFE -:108F0000021FD02F51CCE10F55CDE0CF8EDE535E46 -:108F1000CE63479F6216F228B7EE90A60A3FBF6560 -:108F2000FE804FDD69C914FC38EAD81D7DC7447E38 -:108F3000DB3D6951EFEE231E67FC8F8E253A28D664 -:108F40005934CF623C3EE62ED461ADD75E480871FD -:108F5000B492B6A4E7D0C39AB024D68D5E4A7C9B67 -:108F6000F932DA9AA8D5EA67CFB3A84DE443928BD9 -:108F700077AF678D3D87BF2AF6873C8265B4353E63 -:108F8000C77838ECF067AD971273C5F379EE3C11F2 -:108F90001D90C18BF3ED1E8DF94F64962C80CEAEE3 -:108FA000777576D3E31ED3BB0CE3A49D2AC2F8FAEF -:108FB0009CDEB640CFA00B71FCB1BEC5DF8C873202 -:108FC00080B4C39CA9731B29EEA145F0B36666FF6C -:108FD00013AC970D6C55E1E76E3AF829EBE0127C83 -:108FE000A9A11AD641524A021278F3EFD31E4D11AD -:108FF000F1DA55AC0777E697D3990FA17F3AF4EFF2 -:1090000034F48F6D77DD670D59E0313A74E9DDB0E6 -:10901000D0CF228A3101BF8277E49DD4DCBDEFF04E -:10902000D77DFB7C7E7F06DF72F5998064A7EB67B6 -:10903000D7E786E6D421E91FF782ACD4453B5F979A -:109040009147BDE2F0CFE74998E5C8C3D3D79A2945 -:10905000673DAD838A22BF8947259B751E7156F8EF -:109060000A747E628124C6776F966C0B5F87EA3E36 -:1090700013F7763273D6CB7CAAE97DEE35716E2D6F -:10908000BA40D17C1D37F89DFBF276FD72F9F2A053 -:10909000CEF981CF428F23C2F27CBE1FD7BBF7E14E -:1090A000869699F5ABA5B38F95238E274DC9B0E76A -:1090B000AAFB96FB4EB1DC7DDDBA2F09272261E0C9 -:1090C0003179F6C6E6A5F0375AF7F70ABE473BEF07 -:1090D000C2DF0A97DF5D81600385A02EB57A2A0B77 -:1090E0003CDE2B4DDC13669D90BF0ADE4BBC3EFB85 -:1090F000F6CB12D78304DE773B2F55AEBFAAB0E67E -:10910000E874849633AF7EAF69CEB9F5D80B590FAA -:10911000A81E8F9995FF5F77BB4F7CD4C075B93679 -:1091200034D2E02DA8DFF8CB38F77C8F0C7C10D53B -:109130004B0AF925BBFC528595A48DEEFD38936F43 -:10914000E3CC37AEF7D10FD63FCD3CE9DD1491F437 -:1091500082FBF3F8F9607581DF897E45CC27355BAA -:10916000F34469619CAF893827D28E3FA26CCDA6AB -:10917000A585E32997B759C1DB9F2CDE19E7739CBE -:10918000E3AD4A0E6F3BFB3A48DC476EDE692FBE0B -:10919000202E6BD067FF06E3939EA98A70C1B9F8B1 -:1091A000A18B737346127C5C4996C27E9BE1F119D8 -:1091B0006EAB9451611FA08CE8275A48CCE3FB5D4D -:1091C0001E37AB9921A941CCB354F072159D15F30C -:1091D0001EA229614D82C0C3B691216C8B3FB38E14 -:1091E000E5A33E9D56984F99A81ABE0A3EB294CC6C -:1091F00055BF7CFE2A5DCDF11393F1B8D91A9F4378 -:10920000AF0FBAE7DCE0B71AD77982EC43E87A907F -:10921000B20A6FF2804A6B14E4F3A04AFE62C47B88 -:10922000745816E77730ABDBAC5F4699BBEE0BACFE -:1092300043BBD974CE295F35CF34E6F3BD138755D0 -:10924000F017E2792ABDEE113866C47E0F73E0C8CC -:10925000BB957495DBA970A5C3679A7A96F779A434 -:10926000DF27DE39B2DF1278FC34ECD433003C83E4 -:10927000F0B3EAA04463D8D758E4E49BF3BF0AAF45 -:10928000BE5023CF77EE31B4690CFD01BFB38E68B9 -:10929000B5C6784999A87C2BF0F5719D8C92883BD6 -:1092A000F8C2D4B5BDE2DDE6D30E2124A3FFA3317D -:1092B00009EF69C934690FC7E32FC9F0FB1AEC182D -:1092C0002F7C57FF3AFCFC5B7CDE255D13785182D6 -:1092D000747E67CCA75F697C6FC83CAFCC81EF1F01 -:1092E000C0EF4957EF2E173BBA71D8DEA8CBA8C7FD -:1092F0009688DFE07A34FA2B9613FC6E284D08BF6F -:1093000097A523D5C2896AAF60BF399E07C86C6133 -:109310009C25B75E7BFC8EBFE922C7F299643E07AD -:1093200020E77EC47500E7C28FB6D5E6D4DBFABC71 -:10933000C84E61BF69392EC8F88A62F805DF6389B3 -:10934000B16658B5CDD47796F0931D7904F279A41F -:10935000781FDCC7F4033C1041865D9A934FAA4402 -:109360005ECCBF9752546CE07144BB4A1D9EEDFA2F -:109370006B914D95B3E33BE94B9CE4FCA665636CB4 -:1093800054DCA33B9B59EF18A7EFE47092F3386DC0 -:10939000B163A9AC2E7019619DBECF67DF93C1BACE -:1093A000A77C7635C79FC303051224D55C9C73F850 -:1093B000685C3FE6B189FAE5EA1FCBE374A0D8C147 -:1093C000073FDF1C1C74D471E9ECFCFF0753B7A7FF -:1093D000EBB00E00000000000000000000000000E4 -:1093E0001F8B080000000000000B7BCBC7C0F0A360 -:1093F0001E81FDD0F8E8B89D17BF3CA9588601C171 -:10940000CEE7626008E160600805E2FD407C00880C -:10941000E53919182280381288A703F93380B8007B -:1094200088D3816A9B99191876B131301C04E213F4 -:10943000407C9E8D74FB3F88333054C820F8C78031 -:10944000EC2372D4F5E3281EBC38CF0095BF4E1331 -:1094500095BF4D9B81E13D929AF59AA499AF6CC856 -:10946000C0A002C4003A4CE95968030000000000A3 -:1094700000000000000000001F8B0800000000003A -:10948000000BED7D0B7854D5B9E8DA8FD9F39EEC5B -:10949000494218421E3B2140800487102250B0935D -:1094A00014142DB5113D2D7ABC3A8447906740AB1A -:1094B000E9114F3624840001068A3572224E103499 -:1094C0005AA841F1D1536C878716ADED8DD656DB86 -:1094D000FA88A8A0A89C5445A7E7D472D7FFAFB5D7 -:1094E00093BD273301DBDE73EFF7DD9B7E75F1EF74 -:1094F000F5FED7FF5AFFFAD71A45B411F9EB849C51 -:10950000873F9AE68A849021FD2921B2D6E3809490 -:10951000E8E7475860725EBA18F82FA3ADB0CEDB0B -:10952000FD1742B208F91ECFA37F21806770C018D3 -:109530008F9192A04262C5FDEDCC200CD644819C57 -:1095400017E0AB35DFE8A7DEE11B4FD208F9C2C94F -:1095500052BD8A6695D3F44D67B4B1801087101E52 -:10956000C1C65377497529A69742DA2890B95D9EFE -:1095700024E320EB08994493FDC34452D13FFEC439 -:109580007246DAD44048CCDE0FCB3209256BB78265 -:109590008E1FDA7D5F0857E0783C44067C281C1F4C -:1095A00036122484CEEB88FFF2C03C3AFED6694ADC -:1095B000D00E193B874165E233F038371F610787CA -:1095C0002B89C6F11D6B1941EB398322D944A1A621 -:1095D000822A07292164EB94CF03613A1EA71C213C -:1095E0002AA49EE4E3BB9A88BC9DBBC8C5CC3B7152 -:1095F0003D6458A349088A302F63BCDB6C745C99C6 -:10960000743D2689641F85B794CF4983F118F3729E -:10961000A4E8A719F03A9A90CD0D0E4C9B26CF499D -:1096200023508FF4CE85F5DD3A254BDC24F4973FAB -:1096300032E539470F9D6F23AFD7AA1D7540796377 -:109640009D13F1B695E32744041CF7E652D7DC6876 -:10965000C9C07184880FF3B73A692598879744F792 -:1096600015400B3D6DF329EC9BAC966DD206D2CB29 -:109670008C523918A3E3F4783C413BCDF704587D74 -:10968000C7EB4254C3FA21CF305ADE65ACFF64B158 -:109690001F9FF4FF3E524D08E5475F4EEF6BD08FA2 -:1096A000FD757B3044BFBBFFFCE96BF369BBE46D28 -:1096B00021B80FFA25AB2CEB45F632BCDA54FA6F21 -:1096C0009AEF9AB668364CC1FDE5E3D580B78D4573 -:1096D000AB5D6B61AD8AD9FAA9F47FE70B69FB9AA0 -:1096E00062E9DF665EDF02204D2BEC1E39E7DB23EB -:1096F000B4D4F4E1EEF19158062D2CDD88EB9DAA4F -:109700005CFDEB132E3B6EEAB78D78334FB9E93F22 -:109710002E2597229F5FA0FE170DC1CB8EDB70DE3A -:10972000A259DEA42ABF9ED3471F9D1550FA28C117 -:10973000F50C5C53DAFFFD25A00BE007BD12E51820 -:10974000F2229D6FF374D22BD1F5681AA968EB2829 -:109750001EECAA12137CACCF5EA02FF807AD6A2FC7 -:109760006AEE16C603F03D8B1C6C19FAAFC1D82007 -:10977000E34B5C87AF8ABF18E06F5C3FFEECA43A16 -:109780002D06EB5D1D40FC78F938364CBF5D8BD162 -:10979000F96CC8FE61E86D62C2E3A58CCFFAC6938E -:1097A0001325E6FE0DFEBA4408BD08F89194E06B5F -:1097B000618A0F325509EE4B322F596072A51FCFC7 -:1097C0000E99187802FA3DAC07AEF1E290AA1D2678 -:1097D0003CDB03CFFD19F0276792987B3C7E6F92AC -:1097E000D3A9FCCA24BA3B0D5B9101FE332940FE8C -:1097F000A4F9339432900B9707C3B49F661BEF4FC5 -:109800005D6B59D73FF375EDCFD703FF64C9B761DF -:109810007BCD5E2E37D4461CDF80FA7E563F71BE6C -:109820007F02393A09CAA99C7E1A03A06F1CC39A09 -:10983000671D01BC8FAEEB9A0F735409E2C190FF14 -:109840005401122847F5C39FA19E43AB46BCDB736E -:1098500042248C78B3EAD3947239418F0EA02795B5 -:10986000C2461B85F0DF1C15F98D24EA6F9E8672B7 -:109870002F4A0F3626F0156D2AA99E291598BC256A -:109880007A26CE5F36E880DB0736031D3B193FABF7 -:10989000BC5F05C643E5A19344B17137A57480BD93 -:1098A000A40EE173A1B298007423938D20E7EC21FC -:1098B00091E80503FBDFCAF549AA796C9D925C0F1C -:1098C000E40A4C0F489E3ABE1E37AAC067821E2685 -:1098D000E781DF4884EBBF20AEF786867AF20E9DE3 -:1098E0008CEBE89544A3F423E7D48542B49E04BCF2 -:1098F000484534F194B3540E6A66FAEA5B47B216EF -:10990000DBB351B4C03C6D1EC73C321E52F51A4C3D -:109910008BC72E04FEB0A55D5E0FA61CA59B4A0159 -:10992000FA7724A72BE2A14C3A0561AD3A697F7C16 -:10993000BD79B994F4D5471FC67C35A5DA3B906E46 -:109940005CE5AA00AC40C16E18CF503E9AA1E1E69A -:1099500055E27858B7C8AC51747D86F6CC43FDE427 -:109960007DFDCA0F605EEB4BCA4E8009971654AF5F -:10997000B99CAEA7AB980880EF8DD0D85468E1842D -:109980005E097A1DFE994DC8FF109E09E91E463EEC -:10999000567B53D464439E8883DA2FC279FBC0FA86 -:1099A00029E53331F10FEAF1D517672FDDC8FAD376 -:1099B000E9FF80EFFC09FA342D646A97007EACFD64 -:1099C0006C00BA41FCAEFA6FE94F253B1C1AD81D5A -:1099D00045A21AA57DA711D54F653171CD9009E833 -:1099E0001335A75787E5BDD0BAAC276416CA51CA4C -:1099F000B7663A6FE7722050D354D04CDB3D57EE38 -:109A000009821C184AC56646FAC0F96C4EB0B337D5 -:109A100097EC41F9D848E9A810ECFD1211EDA18DA1 -:109A2000458FA9667DF53343DE0CA00FA2C915282A -:109A30003A08A1F8918AC49073FCDF4F1F8976D24F -:109A4000C5D287FB46EB7A7CD5F5FA659FFD7D7123 -:109A5000F4F1F7F667AC6B2AB945D715EDEF166D43 -:109A6000CEA0F6CBC075DD81EBEA2A22A16472B8E4 -:109A70005B10ACFAC99C9AF507B9D5B25EB64BBF7C -:109A800033F78141F0619B6B9DAFD1AEB35ED2DE07 -:109A9000053B5656511F19FB878DDA0E1DECF973E5 -:109AA0003984D97B91553101ECA022827610342083 -:109AB00052D8A985A29B0446FFB02E867D63A3E6FB -:109AC00098B93F497559FB9FAB0BE6F13BEB151C71 -:109AD0008703FA03BEF4D00669BB520E8939D1FE62 -:109AE00064EB075DB17DFC9D17450706BD025A1961 -:109AF000BD5AEB3507CA48B2F51BD0DF75D6F1A6C3 -:109B0000944B89F53CB276CA648FA4AE2793532652 -:109B1000BB66789FFF4237ECB9A7056A173606BEC9 -:109B2000A3E3B8E13F54BFB6404AF59934AC8A8408 -:109B300035D0931AE3132D9DE9DF4EC1B20F37BE26 -:109B4000A71E07EB2FBE90D222C83559B3D8CB89B8 -:109B5000696343E06B32254A77FD0353E589D48876 -:109B60005D1B9A5B4DCB6F6CE89C0ADF8D723345B1 -:109B700063FF4DD5A6C93E96092DE7C0AFE4FC446E -:109B8000F8A812CDA4DF1DA40BF3E957BE7E04D7BD -:109B900001ED2ADA649DA861BB0A791ACB414350D2 -:109BA0008E4AF1A972316B0EE0CDB65008C7254739 -:109BB0001CAB29DF6D767258E3B09FC32A870B3840 -:109BC0004CF504C06E85C23475DA222AC22E0E17F7 -:109BD00070389DC37E0E177258D881F06685B5B770 -:109BE000498EB2F65D1CD6389CCE6195C3851C2685 -:109BF0007B58FF7606BB6C51D6BE9BC3051CCEE0DE -:109C0000B09FC323382CEC4138D5FAB98A3A199E53 -:109C1000FAE442573F8CCA83E3B50F8E25C08C5EB1 -:109C200032044687F16F19741344F9483C79C86FC0 -:109C3000E31C6CBD1BF797A15F82703F8AE9FB09AB -:109C4000D0C7E73AC5E060FCF5432E4F77829D4BC5 -:109C5000D3ED0D2AA6DB1A0268F76E69D0B85FA5AE -:109C600018BF6F6C0822BCA16132A6EB1B42F8BD85 -:109C7000B16116C29D0DD5983ED83017D3BD0D6188 -:109C80004CF7342CC672D1863A8477537B17D2F6C0 -:109C9000061DD35D0D2D98DFD61041F891FD65CFDF -:109CA00017513D7D2E2CA29E4F35FEA173AD7E90A7 -:109CB00021D556B9983E23DD92AF4ECBB6FA4DCAA8 -:109CC0000B2DB0A764AC0576159559DA73E44CB545 -:109CD000E42B99551658F65C6581C744E758E0D1E6 -:109CE0006D3758DA1B19A9B1E48F685962C92FD0B2 -:109CF000575BE0FCFA7FB194CFAD5B67C9DFE60C40 -:109D00003F235279357CF1264BB961E11DD67DDDCB -:109D1000ECCC8B925BE4333DCBECCF4894F7521EF6 -:109D20000985506F31FDD208740B7EAF5C12DD27C0 -:109D300080FFEA8A13B0EFB01731BD33607F99D04E -:109D40009EE279F0359DF653E93B11E831F11909AE -:109D500098EA51B97F5264FBE64D77B17D75EB5DB2 -:109D6000C9F7D728D9E93C5ABF4CEEBFED11256E93 -:109D700007E9967D4AEB5D0296FF7BDB37F213DB4A -:109D8000EDEF8FD25C85D90E891A7E51A267F5EF6F -:109D9000776D3DFEF9B0EF31F6B912E7F3CAB9C1FC -:109DA000B79B289FAC5709FA0DD77BAA08D815E7AF -:109DB00054C6F7646F1EEEC78DF203C767B22B500F -:109DC000FEB8AC7E5ACF1C942FEB3307B7CB94B8B8 -:109DD00084FE3B292E9018D53B8A5C3DAB808E4B90 -:109DE00079450AAE25A87F92EEEF09D981789012C5 -:109DF000EC9BA60509726F462ECEDB66C8B7CC2A4F -:109E0000FCDEA40E3E2E3B8C0BC6C3C7658BBB315C -:109E100095E24E1CEF947806C293E37E4C2F8D0F93 -:109E2000C7B4223E0CD349F1119896C70B309D1848 -:109E30001F87F5CAE263309D109F88DF83F1099880 -:109E40005E12FF1A7E1F1F9F826969FC1BF8BD24EA -:109E50005E89E9B8F837F1FBD8F895988E895F8B61 -:109E6000DF8BE3D7603A3AFECF988E8A5F8FE9C8DE -:109E7000F87C4C8BE2F3301D115F8AF50AE3B76082 -:109E80005A10BF15BF6BF15598E6C7EFC4342FFECB -:109E90007D4C73E38D98E6C4D7623A3CBE19EB65FE -:109EA000C737623A2CFE03FC1E886FC7342B7E2F07 -:109EB000A6FEF80398AFC63B304D8BFF08BFFBE210 -:109EC0000F63EA8D3F8EDF3DF18398BAE33FC5EF24 -:109ED000AEF84F3075C68FE17747FC08A6175A27B2 -:109EE00025C72AC7A54C97059EFC6EBA853E2A5EFB -:109EF000B7CAF1F2570A2DF9652F5AE578F078992B -:109F0000051E7F78AAA57CC9A12A0B3C76BF558E79 -:109F100017EFB5CAF151ED56395EB4D32AC70B5BC2 -:109F2000AD725C6BB2CAF1BC3556399E739B558ECF -:109F3000672FB3CAEFC002ABFCCE22BBACFBEF195C -:109F40007BAC7A6DDA2396F63CE58F25EC57A22898 -:109F5000675C25FF6EA9E7283A9A209F7526A7120D -:109F6000FCE5801299F2F71DC415349FAB18693ACD -:109F7000970719C07734CDE47C3704F88EA6E9DF63 -:109F80005C86E74C5F7CABE5174DB4B1F4E184F936 -:109F900005F44855887E6F1EC661FA45003897A0C3 -:109FA0009F80E8672AC12FD65CC0E07F934E55EAB8 -:109FB000CC7FCBF2C95996EF64F0238DBF5A0BF9D1 -:109FC000E969D1EC204D1FB12597D38F49ECBCED49 -:109FD000AC18EA90E87CFFA3B2E776F0A3FDD51EAB -:109FE000DE27D1EFCB1CE17C704D7F6C0B3F2483CF -:109FF0005C24A107E17B1A093D24A1BCB6FA451BEC -:10A00000C1E0A6ED7C2656EF87FC8CAB17A35FCA98 -:10A010009877B377F0F14425A6979AFD04F78DFA67 -:10A0200011859F2311765E0329D583F7B87D21C85A -:10A03000DF7044D963A7EB60CBC99A4FC6B36216F1 -:10A04000FD116B5E057AD8017A680448F92E4C3D03 -:10A05000A49B9D1B915E4C55A20A901AF3EF9B772F -:10A060002E9B37C5C72F24DC1FD461F975EEAB27B3 -:10A07000C37C283E4EC0778A8FE7A521A9F141E035 -:10A0800064818E3FCFA0A2FD82C5FFF8BE10FE8D79 -:10A0900064F263E6D507713F794052111F06FEE86E -:10A0A000DF6DE9863F86D5FB23F69BD09ECCCFC5DE -:10A0B0007E23F1FEB93E34E8384324E1647ADD388A -:10A0C000F7219D795FC99F2D28CC2E49ECC72657D3 -:10A0D000E379EA00B99799B0AFCF0CC3A250FD491C -:10A0E000F56592714D57B87F4ACEBFA8F32BC35F79 -:10A0F00042F6E77DA5F32EA004286F901C399E87B9 -:10A100007090EBDF02B0EBA83D72EC8DA762CBA99B -:10A110001CD85044752DFA2DACF6DC869888E7EBF8 -:10A12000057E2A706863F5DC0E90B93D68F42B3724 -:10A1300059FD299B6D7C7F7BD88AC7024AD0FF4E90 -:10A14000B7DCC493CFC6C7CF2D8D76F6F48DDF3A3A -:10A150008E074AA83964C2676129251D18478C8D6E -:10A1600023B17FC2CF170CFE913DDC6FA2E663BB2B -:10A1700046BF89FD1069369E27A5C2EF807EBEE2EC -:10A18000795D859CFCBC93AE0FE2696C8AF535CE97 -:10A19000EB0CF8D81BB578FEDDDC59837654738060 -:10A1A0009FB3FF85B60AED1092D45EDCCBF1BB897C -:10A1B000EF17F746AA1C582F33DFB24E45DB67B8BE -:10A1C000000F4D6A553AA4FB76B27223EFBECE154E -:10A1D00066765B3AA49B8AD977D798BD0E567E8F58 -:10A1E0000AE9E612F6DD5D7AC8C1CA333F2DA9A798 -:10A1F0007FA673A022B55A14CA41FF92904C619772 -:10A200001A25E04776AB5D981AE3CE8E88E2185A9D -:10A2100025BB33947E25F8DDEA4870241BAA03D6BB -:10A2200039CA972FC7C8AFA7F9B4BD313B8F564283 -:10A230003DE7CEBD95576AFDE577F3FEC774465BF3 -:10A240000AA17C8EB5BD76DE9EB3B3EB04F89B29E4 -:10A250008EB13D237F17CFB7437E26521BD6974B37 -:10A26000DE8DC1798681E740B1D8087022BF1BED31 -:10A27000B4F171043BA3912AE867AE751C3F34C862 -:10A28000B29384A21E933CE0F9119EBF01F6FDB487 -:10A290003FB993F9518DFCADC63823AC7E23F70B43 -:10A2A00018781DC3E591413FA9E898E8A265FF46EB -:10A2B000EA5D56B8CE64DF01BC38DB9A1F2EB4C20B -:10A2C00073C75AE15099159E3CD5D2DE177D7E9416 -:10A2D000A813FD25DC8F62F85E76A935B8CFE9F7C3 -:10A2E000D3455C588EEF3B7278B987EB98BFA5D108 -:10A2F000C3F985FB5D9C5C2E3617B17D499F5DC11E -:10A30000F1DDC5FD1A8F36B4B1F8940BD8C3EDBC9E -:10A31000DE2E7EFED8C6FD323F04FCDB61BD985FB9 -:10A3200026C2FD325BC12F43D356F0CBD8813F9973 -:10A330005FA605FC32343DC0FD323F02BF0C851FD5 -:10A3400006BF0C4D1FE27E997DDC2FF300F86528D7 -:10A350007C7042F75CF0B775807F86C2F773FF8C24 -:10A360009FCBE58333A3D9E00F7B6466F27DB1DF39 -:10A37000C6FCEEB960A850FAB884048FA1BF9B8ACE -:10A3800061F0774FAC0B362A9960B732BC4D0C07A1 -:10A390001B6DE560B73238DFC6F428E80BD01FE448 -:10A3A00030F327503ECB047C6FE1745976222CCCDD -:10A3B000A3E3F8A3CCF5A2460218B7C0F902F24114 -:10A3C0009EBC21845E972741BB04C795BFB7AE0AE8 -:10A3D000C468F1D3D5475DB4DCA8AEE03A707D1611 -:10A3E00095A8E05920CE224D84F5395819443FDA1A -:10A3F00096DF4AC13DD06626B1D0031D1BCABD31D0 -:10A40000063CCD4A0F97C477A3FDDB5C37270DE9E7 -:10A41000492383EEC7FD21EB3E286DB2D59FD5BC05 -:10A4200097B5938A6E8ADBADF6C4A89DD67D54732A -:10A43000D19C41FDCF45ADD6FE0B9B12EA7B06AF0A -:10A440009F1FBF1AEDFB54F43D4EAC49B34DEA8754 -:10A450003DF1CBB07CA27D2703A150BB4D3EAE6049 -:10A4600048957C5C0D815D2B1FD7781AE4DF431C77 -:10A47000AE66B0CAE220A83D986B1B82EB9370BE1B -:10A480001D2270FE7C109501FDBFBE705D88D2DC80 -:10A49000C17F22B8DF78435E55A55378D76C8728F3 -:10A4A0005D02F4C6E21914BE5E194A746301D0C39A -:10A4B000C322017A78A473703E1E10E7E009A17FE1 -:10A4C000A6A0492D03F59DAADECE2671563449BBC0 -:10A4D00053395F91E324D16E9E0AF35DDF34474523 -:10A4E0003D725D10F7074463E337E45C46FAE0EB46 -:10A4F000B7ABC17ABE964D92DBA16B6C9CDF8A999B -:10A500007C34E83FE3C1C1DBDFC0DB8F770916FF96 -:10A51000CE90EBAA2B6D99B8DF097A408E7E293157 -:10A520003FD961169F66F05363D10E179437FACF67 -:10A53000CE89C1F684341F99C2E226287E713F7805 -:10A5400084CAF11294E368F73917D785989F3C8243 -:10A55000F10DCEBAA00EED481E462FB0DFE4E57136 -:10A560003C1BF78A1872D13897D9AD869C37E8A082 -:10A5700031C0FDEB7365E667FB0B9D9FB11F81FD4D -:10A58000A15A87E77BCD93D87C6C992C0EC4561CBE -:10A590008BC1D959B377D15A98AFBED0D0D73CEE42 -:10A5A00082B0B82B231E0FF003E7E0056DE3518E58 -:10A5B0001878FCB610AE073EB265EA4218E7D185BE -:10A5C000ED1B784BC4FB77B93C1D9EC20F97A6309C -:10A5D000B99EA1A85781BCDD7284D277927DBD93CC -:10A5E00097EB88CDD90636A2C1AF46FE0149C37E9E -:10A5F0000CB820AEB0B8BE9875FFF1FFBA1DFFA829 -:10A60000CD1A77F7FFEDF8FFDBED789A0F7648F873 -:10A6100002763CB7F3F7F6D16F829D5E2C1FC130F6 -:10A62000BA047B3EAB7846AC0AF23BBBBAD18E9FF4 -:10A630003CB81D4F12EC77C3AE37EC77C39E37ECB6 -:10A640007532D09EE7FAEF1BEB4232C48911D47FFA -:10A65000E39ABFB14E87FE13FC1E12157366FF45C9 -:10A660002FF0F910133F78AC76C3C5CB0719F53F2F -:10A6700009E65AE46B46F6E0768E11EFFD45AE61D1 -:10A68000AF87D83968513131DB634D548EFBE87C9C -:10A69000DAE7B2F329C2E578B6E197290EFB47A3C2 -:10A6A0007CB7CADDF6C5353A9EA394133C7FF4E42B -:10A6B0007485E07C3C6B6E04ED492A7F8B1593FC1E -:10A6C0002D68AB4039A773FB32119F20EF0265D094 -:10A6D0004F829C21C19745C8CF85B36BE087A88086 -:10A6E000FA03E234C60F226F2E325EC3889FC8A3DE -:10A6F0007F206736C86C7CE4696BFC3951297D5436 -:10A70000F4DBCDE4FDF98239EECFB06312EB51B941 -:10A71000A026937B6F08E16F2983D047A23F8A244C -:10A72000C8692A8844E8BF60F62CF433F5F9A564BB -:10A73000ABDC9603463CCB7FAFFCAE55FEC6B8F310 -:10A74000AFE8B7DBC8E5F3007E4E68472CE9223D51 -:10A7500049FAF79458F1EE2AB2DAF302085B881F3F -:10A76000CEB19E93CB9EECE4E7003C3EB366B2B123 -:10A770006CDA77FF48F9E4961336BC4762E81DC3EC -:10A780002F7B0BC469D2F5A981B84D4ACF0B48B5D0 -:10A790000F323F2622C6837D4C5EF64D34ADD37D0D -:10A7A0008AC2FA69B19D847B42463CE2C20883FBBF -:10A7B000F0DF668517913959701EB168A70D38888A -:10A7C000DC42E4933DC6F8297F6F51587C752DA972 -:10A7D0006B0639B69EC773D7A84486F8C1E54FDD2E -:10A7E00057318FC27BB9FFF60CC5BF66B28397782D -:10A7F000A20A9C2BBC7368E277BE46A07EB4391BCC -:10A80000E208A9BD0A718489789FDF621DDF85C6D1 -:10A810009F385EE35E51AA71C89D4228D9FEE0319F -:10A82000C51AEF76A1FB4EBF53347EDE6CBDEF74CC -:10A83000A17A7F543492EC9ED485EAF5FC8DFDBD5F -:10A8400097A2DE72478F027260A51C9E2514F6C780 -:10A850006B29B6EAD0708A0AF9E90931385A32957B -:10A860006BB9C8722760637111E5668983B4779606 -:10A87000F3F12FF63FA0007F7EFCC8DB57C379CDF4 -:10A88000D29F4AC441E77576BF97C470DF11554027 -:10A890007F2D392431FF9B1CABB8D6247F315296D3 -:10A8A000E27BE9A35E8CAF58F2983D3A9BD65FF20B -:10A8B000E43BE309C5C3D975BDCF0D87FDC42302B1 -:10A8C0008B27D47BC65F4BBF2F91C9CDD549E4A060 -:10A8D000646774FED14FDC73818E84CE233761BBF5 -:10A8E0005DDFB5D94D76FF7F2A36A31C9E33E90F75 -:10A8F0000BD191021B9FF99E8411C7F9D1C3021B92 -:10A90000DFD3B6A813C6D7D9A18469B9959D7F4274 -:10A91000BAFDC6A3077C8087954F4B16F9B2B25398 -:10A920008AD9C763FAB61DCFAF421E81CA911528D6 -:10A9300062687A6839C67DAFE8DAFC27C907F5ADE9 -:10A94000FC43F1128C015E5F9582B3017EFC211FF6 -:10A95000EC07CF74EFF3015E69BBF3144A57977DA0 -:10A9600066E233C2DA8FA70F6C8F5A380AD0D7CA83 -:10A97000AE8DACBF04FE3C03FF1836502F8CB55B88 -:10A98000EDFA73E4C50ADC877766248D93EFD30B69 -:10A990009C5F971E38B75BA7FD7EF4D887BB753ADE -:10A9A000FE657FFD74F79D6057FECCA9829C59F926 -:10A9B000C86F7DC484F79976C6EF671F7EE8C15DD6 -:10A9C000945FCEFEDE8EFBD1B3CF9CCED3E8BCCF5E -:10A9D0001EFC739646CBDFF6CCCCA18087DB9EF8BD -:10A9E000C6D0C1F6E740AF51BB795DA3B8AEDAD3AC -:10A9F000020BCA3FCCD384F53976E8581E8CF3E3BA -:10AA0000D7EC780F7125FD565F06EBB51CE53EC00F -:10AA10006B289E57ECDFF027697C327CEBC345B88E -:10AA2000F34628DB0460BDAFFDF6F472486D410DBE -:10AA3000DA23BD28B713EBAD7C85AEEB25A9D7F1A2 -:10AA40001CF98B02F85FB97F23EB37611D3F867FCE -:10AA50004C19B88EF3ED56FD7E8E2CBB1F6DFD4359 -:10AA60001949E3A68C755CFEC43F0D6A0718F2E035 -:10AA700042F85DCCE3FF82F6D0AD76E0ABC7DC7A7E -:10AA800080AD6F7436CD3B7BE05C1E186BEFDB7ADC -:10AA90006F0239D9FB8C5D85FDFA92675E453E3BBE -:10AAA000FBC44B8A86729278046A279C257D7FDDE1 -:10AAB0006037AC60B63059B9D71BB3FBFAD76945DC -:10AAC000F49A599A0FBFBF8DDFA38CFE57448F5C59 -:10AAD000272459B703F6422697A343102FCB49B733 -:10AAE000A29658D753980CEBF8F6E54077A9D6D143 -:10AAF00098BF0AF3BFD4B49E7B19DF26965F41F955 -:10AB000013FC837DEB1A155E2549F8F46C875D868E -:10AB100038DFB329CED9FBEEEF7E45FBEF217B8AF0 -:10AB2000FD3BC7C385F8FC42F3FBAAF8BB1B82BF01 -:10AB3000260DC4E3477F492EFF8FD999FF6C050985 -:10AB4000CFCA9606EA2F8984F4E105FDE36DEE9203 -:10AB500050AE7FD42945A16AA29C5891C24FF89269 -:10AB6000D1CFD347C6833CFBE8E84F385D32BA5FAC -:10AB7000B1FF6D45E7FA206AD60729FC547FE4ED62 -:10AB8000AD3C9CBCBD95FBFF94B4BD3372E8BB30BB -:10AB9000FE33DD36A2D326CE744949FDABCFDA6D44 -:10ABA000D638716FC56B69B49EE47369D075E3BA2A -:10ABB000D0ABB09FD35FB611BC4F2B07DFB7D3FC30 -:10ABC00046AF4BDB44F1D5E85B847E48A3BDA604C9 -:10ABD0003CC9816A1DFC1C72667539B391A396FD50 -:10ABE000B04D152DE3A67A3607F4D09B134EDB60EB -:10ABF0009E6F25D8836FC9A479286DEF2D5D08AEAF -:10AC0000D592D1B7B5FDF01A896866FD67EF7D135F -:10AC1000C6437EEE2470BE22FDCCA9833C59B9DB2D -:10AC200019B5D3F91C7BE28B07016F67EFB713BB34 -:10AC3000295EBC56656D9C7EE28BDDFF45F34F437C -:10AC400065DA7FED6E5A1EECF0FD6E0CDAFF8FC7F1 -:10AC5000D2C6132A9F6B7F7EE7D5205F6A41A6D2BA -:10AC6000F2B58F0E45BBEED410069F3A901B85754A -:10AC700059F6F8332B408F2CFDB19B80ABE0D813F5 -:10AC8000AFDE04F0D99F7B31BEF1ECCF4F5F067C85 -:10AC900040ED67CDACC76F31BF3340DB5D0A30CBD1 -:10ACA00017CE735907FB92A59052B9B1F4E934BCA1 -:10ACB000BF632A87F556DA7B6F0FA27F45CF1671E7 -:10ACC0008F13CB063E5CDA69ED4F73303FE84AA53F -:10ACD00077112B1FC966FCDA8DF54A1D9C4E797ED3 -:10ACE000627DA3FC384761423BACFE0A3BA94B4660 -:10ACF000FF931D4CDF2FEDFC72B4B53D9D7F4FECF3 -:10AD0000877DFF9EC0EE9790834E8C235AA6C44643 -:10AD1000A5537E7D52218B816F97F962A3FCB4BF4E -:10AD20009F7239B9CC4561FA3D9B8F03CA034C1C15 -:10AD30003D3F86F55DFE949300BD2FFFB917CF5FB1 -:10AD4000963FF9C5A97FA3DF3F7AC28DFE92E53F0A -:10AD5000BF03D77BB93D7613F8517A0FDAC91E5A73 -:10AD6000FEA383CFE7811DF2912D96973EC8FE7C0E -:10AD700079979D5F6AB0CE83EE0B8AEBE878F4EDAD -:10AD80002CFEAC9EB8826B21AE041C0740C7AF3BC3 -:10AD9000D939213FB75DCDFD499F2CD0D270FC251C -:10ADA000CCAFB59AFB0F567F4B1BEA378D03E243BE -:10ADB000C94442EE50EA46839C95E2DF241A85E5B9 -:10ADC000F8084C8D7292CAFCD05226F3B7D9328360 -:10ADD000A4B604EAB17822E2B9AA8FCFFE275DE2D9 -:10ADE000D5F76A43A1BD790E664F6F7386563870EA -:10ADF0003FE3C17BA1384F2A10F427D8BCBE10D83E -:10AE0000BC12C7FB854DB7833CEF3FCF66E727F504 -:10AE1000B2F6AA06F33FC1E5D280F9333EFB444DBA -:10AE2000473E33E6B1B9414579B2B12180E9868622 -:10AE300062A2615C7F106189E3C35EA21309EEC95F -:10AE40006A6CAC764F7508FC56D026F83B254F1837 -:10AE5000E9CB1EA8C3BDBFC3C3FC94924727B51E50 -:10AE6000F487219EE0BC05F0A470586E9B8D78A5F8 -:10AE7000F5F1FB7267F86EC08B2367AC454E2999DC -:10AE800065167800DE0CBA38F0DF8D3F82F8023F9D -:10AE90008DC6EF4500DEE05E04C0FF07F0F70CC38F -:10AEA000DF542AA3CCF8ABB2C029F1772FC55F6677 -:10AEB0003F5F25E2A19EC7A519FC948A7FE15E0948 -:10AEC0005C1AD8D1D086A9F13D3D855ECF7532B9E7 -:10AED000564FC2782E4654E65721993AC931F99314 -:10AEE0004840C7FB4C782F1AF23DCC8F68ACAFA41A -:10AEF000CAA7ACF24F7B15E673C70B3611E4955425 -:10AF0000FF0079C7748E26CDAE766A88E720FA7581 -:10AF10001BB97E5DDFB79E56FED8DCA061BA85F313 -:10AF2000C936CE27DB61DDC13F1714714D5B671158 -:10AF3000D49F775398EDEF6396732B7FB02B06F178 -:10AF40000E2893344C6328BF5EB34747D27AEE1283 -:10AF500012027AF1BFF6FD28CE957405C01FEAE70C -:10AF6000F823870BFDD7B377106C4C4F1189A511CF -:10AF70001BEC9F12F1DB183CEA807D77AAF1640597 -:10AF8000757B1EED2FEB753BCAEFCC1BBB5EABA1F7 -:10AF9000F3F0B4BA713F991564F4E80986855AD381 -:10AFA000FA65A5B0FBEE735EE976D2F5F4401C2E8F -:10AFB000A5C71D6D239C781E64EB0A801CDCEC6722 -:10AFC0007A469B4B7BBBB4BFDEE70E667FF9CAAD0A -:10AFD000FC6FC863755A99858E0D799B3EC34AEF05 -:10AFE00086BCEDE993B7D5B9309E8C783BF26322ED -:10AFF000FD37DA145DA0764A23D89260DFBD2DB00C -:10B0000078DB817200E3513EE929D803EF05ACE318 -:10B0100071D03AE517D43BDCFF699CB71F20D52DD2 -:10B02000F07E4B0BA52302EFCC50FA2118AF538CC6 -:10B030006984D20FE393C9981AF439139C2726FF29 -:10B04000B954F49CC8EE6188A073884CF7811EF057 -:10B05000331D99E200BB50B6054F80FCEAF58A5DCE -:10B060001097B0DE33C70171D482BF1CD7FD736F58 -:10B070004DFE60E729F01208D08DEA09929325FD74 -:10B08000F77525B58CC07EF280A71BCFFBCA9DA2A9 -:10B09000C59EDCE60C5FE534C1A5D03B5FB7AFE3EE -:10B0A000FC93DFFBFD0EE77792A39322137F1BF146 -:10B0B000A144D349B189CFD78DBC9CC039E740FEAC -:10B0C0004E21C7F6FD63E458637E14D7CD9628372A -:10B0D00032A97CF760AA8B2A8CFF50D33F4F403AAD -:10B0E0005B0AF8209E3D7DF6CBD70B078E33516E61 -:10B0F000F5EB230DFD55541FDD3319E4600A7D7413 -:10B10000E48DD1DF86F8A9779E9704B3BF6E717C7A -:10B1100023EA83DAF814A2D1F1D6B4FD00D3456D49 -:10B120001D48F7EF47D7FB303EA685EDE7DE8FDA07 -:10B13000A25201D2ED7909FCFA84B5FF7E7B2396F9 -:10B1400023E07D31F5FB7E3BAB4FCA35B4A73FE131 -:10B1500073ACD9660FC139CDFB6DB4DE20F8AC817C -:10B16000CD5012FB14DF0180987F52371AE49CC146 -:10B17000EF7728542E011EDEB427F5B32F77CEDCEF -:10B180000E7CBDDC196A839478D22FEA3D8A77441D -:10B190006AF722BEC3BE6B2C7E56E6C77C87DBC532 -:10B1A000C49122DFC7EBABC9F397B77EF8DC5D141F -:10B1B0006A2E095713D3FE5A226C7FBDE2E94AFE7C -:10B1C0002E081B4F12FA64F66CAB1DE5D002EE0F91 -:10B1D00032E8B59F5EC23E7E2FD4424FB7C4B7E37C -:10B1E0007A0B9B4BEF9942F1F729A523F0CB099BF2 -:10B1F000A70F053E5ABBE96BDB6EA4ED7FF6A28478 -:10B20000DF17C79D58FE83BB82F7DC08F6FAAF6CE8 -:10B2100018DFF4D98999780EFB81CDEA47A871B17E -:10B22000FDCD5B4E962E8A6FB6D8C78B5AE62BE0C3 -:10B230007F5C14DF8ADF17C1A10CDECFF8F078A5A0 -:10B240000CE73504CF47DFDA787AC63AD46765E889 -:10B25000C7AADD624F7A9FE42DA766913BB53DAD4D -:10B26000D82EA1F65166166FCF243F6AE370F90419 -:10B27000D6472770DF601197237DE36BB759E4C889 -:10B2800007CEE47E92FFE89BDFD7908F06CEEF32A9 -:10B29000C65F46BF3D8CEFFAE773CF9464F3E99F36 -:10B2A000C7342CFF813F79FF591CCFA71A16931082 -:10B2B000954335765ACE03FDDFDA3C19F6D9EDFE1B -:10B2C00074C134AFDAB6A524643EA76C9FA7D498A6 -:10B2D000DAED5F07DBB39545FDEB90E52233611DA9 -:10B2E000EE73568B2EDA5FCDE6E9E3C3B8CF66F294 -:10B2F000E41D5B300FE4EAE9B65B93F277962B61CD -:10B300007DDAF8FA50BBB7DCB43EC6BA24D63FF5B6 -:10B3100046EDE777811FE05E66D4A4C2D780752B27 -:10B32000488EB7A08BE9975354CF86116FDA93AF4D -:10B33000015D6F71631C676AFC8D23E1C1F097C2E8 -:10B340007EA5F6CE18D710E897201E6ADB181D5C84 -:10B35000086FFDFD723AA84C3E9F9BFAE8A09EE85C -:10B3600094614F2A17A2833B89EE18641E7D7430C6 -:10B37000E659333FDEB449433A781FEC94D103D702 -:10B38000FFA4A2FBA6C239D02609CF994EBAF4ACCD -:10B390001B183C01E4F3495FE4EAA9E5FDF02DFB4D -:10B3A00046FAE699FA3DDD72AB2F999FF5A654F463 -:10B3B00053A493928AFF7DF4F38E2D79FCF2726789 -:10B3C000650DF0018924F7E71AA921BFA5344FDFE5 -:10B3D000BE13F4E9494FE1E7519AFBA833BC1CE8DE -:10B3E000E20E511B3F4FE8DF7F0EB03F1B664D7FE3 -:10B3F0007724F80BABA7BF6B437B08DB23605716A2 -:10B40000F0B808F46F0C437D90785EBAC35590F4A1 -:10B410003C767D43DD4468973874A29AE3E008B334 -:10B42000A3FE9330BF97311FC51656E15E9A229056 -:10B430006AA0739B1C6E817BBCB640E604DD84D79A -:10B44000888BF9BF9CC78FB714D0FACEF75E5461D2 -:10B45000D076DA0FF8D71C39F22766FFB42D93C5E2 -:10B46000279222D3F742884FA0B0659F4FC73BC8B1 -:10B470003EF5A702C383EEB5333F0FD125D07BD76E -:10B480003B89F187F6F7EF8D3810B989E5FB8DEC34 -:10B490002696CFFD972B6B987F32715DAF3FBCA195 -:10B4A0001BEC99EB0F0FC3FB74D77B46BF07E70B71 -:10B4B0003F051F3ED0BB9FE9E5C47A8F733EFDE791 -:10B4C0000E51B7D175396EEB3DEA86F17E8FBDBF67 -:10B4D00078C36F8FDBDC34FDC32B276D104F7433C3 -:10B4E00004E8D079CD239AC28CE028D69F4FBABC0D -:10B4F0000CEE1A32C76B6E8F6E55A1BD55EC9CF7E2 -:10B5000086DFBE3213D4276D6F3DA437BF48146861 -:10B510007FDE21AD995DBFE3ED1DA6ED89FDEDF563 -:10B52000E391DF2B941D88977E3C39106F069EF0C7 -:10B5300002478505CF686F1878EEC35BDADCABC8CD -:10B54000F8D4FC72BD67D47BEC7E221B57229E3F51 -:10B55000832CCA6FCFB8422F03DFEC75857E03E9D9 -:10B5600032476F9E5C88F70F5F05BE5C2185F3B3A1 -:10B5700046E0BDC4D143E05D98EEE4E7AB897CFAD8 -:10B5800026F00BC475F338CB9BF8FC8E7DFFB41707 -:10B59000E3289F78350FD2E552CF96EF02BFFD52D8 -:10B5A00042FBFB9343A3078D477B93FB3BCEBA8CB7 -:10B5B0007759D8FC6EE676DCCD87DC517847F3E628 -:10B5C0007AC962FFDE5CCFE23888DC3DFE3A8B1D33 -:10B5D000D9C4E31D06B603FBCEC4768CF91DCDCBD2 -:10B5E0001E07FBC3FB27291AF81F8EBCF8C9EF6B97 -:10B5F00029ECCA75E0B9EC163FA7DF4A11D7FD7EEA -:10B600007FC85D0A7EA74DE9419DCE73D3B3A44B9D -:10B61000A4F8393AE6F628C4216E9D2EA2CF6A5BC3 -:10B62000FC814815D42B61EF15A9DC1EDDD67DB257 -:10B630000DE8F1F46B76F4F73BBD128E6393AD3AEF -:10B640000FECF7F73A94A4EFE39DF7C82C8E58E877 -:10B65000C178B7F924E200B971A87BCE50188F2FBA -:10B66000485420FFD3ED92C8EC64C3CF1193999F47 -:10B670005D97191CE2A9EA34C7AB6D9C3503E32939 -:10B6800016B4BE84F7297DE5C9DF87BAC4CDEED9EB -:10B690007ABBD3AF04FC7A6788F8B69137D82B40D1 -:10B6A000BDFCEE2A05EB478441EBE7AF51AF04BC8C -:10B6B000427D90FFF917597FB49BC53B6DE7FBE4D2 -:10B6C0000E5BB079066DA7638B5F80F530CA85DCB1 -:10B6D000CC9E393DC3F0DFB0B8F6BC22D509EFA44B -:10B6E000E48590B989B73C82F1B77BA01CF36F2247 -:10B6F0001E3AC63C1983F3E34DA01B609D6D8C9EE2 -:10B70000366D11D09F49F1970DFAE2BDBBEDDF8494 -:10B7100079E4B7082AECBD699A74DCF51E07A3F337 -:10B72000D67B701F08EE516837AFFD37382E6F8A11 -:10B73000F9EEF130FA78EF02F491E1667E9BBCFA03 -:10B740006EBE4F8AE13B8911C013C0A172F63EA1C3 -:10B750001CD2CC7128FDFCC3F661749E2138DFAA8F -:10B7600099AC44C10F20B674E07BC0F32376720518 -:10B770009D5FABD01D027ED12789FC1DAED09B8082 -:10B78000A7ADDB87623CDB06319487FE9D7F55F0D9 -:10B790007CEC68E8937BE13DDDDD9315E48BA32130 -:10B7A00076BFF5FE35851DB00FF7D657E13BBF518B -:10B7B0005541C9D2584E5E180DE7836B4455A0E53C -:10B7C00023D5C63D0315EF314C903EBDB218CECF08 -:10B7D0008689E04B22A705F63EC8FA35552AACEB20 -:10B7E0007A355330EF5BEE7033FDF2B2BFFA0E37AD -:10B7F000C563E0AE1D2A35E3297F668C037FA1DE99 -:10B80000A268C63D7178572483AF4B46B7185BE4F6 -:10B8100043D8B3986E91B74D637ECA1F5C1566FE20 -:10B82000453893AC40FF22FF0BE0BA667268D358EC -:10B8300017023BD72DC2F2D04E166D27A35C8C5554 -:10B84000D076F7F843BB519FCC74209E88DCD3069A -:10B85000788ACECC0E425CEB8E29A35E82FB551912 -:10B86000277AE7801E8DE6BAFED001726ABDA2017A -:10B870009F67AC3975237CF7077F782BA4194DBFE0 -:10B88000BB13F481BFE74F0DF87D9662F1EF65BC05 -:10B89000FEC197909F51AD58FC84BDFEEA5D809734 -:10B8A000DD2591488DC6BE87B2FAE771606DF72C31 -:10B8B00078F7FAF43562700FCFC779ED54A39B186F -:10B8C000DECA41AF1978DB206A5DF02EB37EB50386 -:10B8D000E9A38874A3BC1A06A7C8234CF4FAFAC6D5 -:10B8E00055102791389E1F73BE853F785F12D60A88 -:10B8F000E25194612CAEFE60597700ECF82DFEE425 -:10B90000F109673DACBE3DC53DF5331E460F201223 -:10B91000DBCA300D9542EA217A1AA4398E10C4C7C9 -:10B920001E14B53F229DEF9034581F286FA3EB776C -:10B93000E48533E81F3C12F90DA6CF7B8A8DF662B1 -:10B9400059F03E6EF9493C1FD9AA321AA96D61F22D -:10B95000A236D0E380F38ADA12A2EEE1F4A61B78D5 -:10B96000067F17D75735D731BC6696103C6F059FB9 -:10B9700018BC579605E528FE325BD6AEC27524DDAD -:10B98000FA085A6E2BB40BEBD32412D66E8F03F940 -:10B990003722E17923E5F75FC379624DEB503C6FC5 -:10B9A000876BEAD05E3AEF379DB7D741DB01FFDF07 -:10B9B000E91609EFB140D80BC0DA1A4ACB489FBD4F -:10B9C00095C5B45DAD5C5537197460C831CA1A0BA2 -:10B9D000A8BE00BC2DD0F555407F271DEA0B300EC8 -:10B9E000F74EBB06F35FB0F3A93BC06E71077A5AFE -:10B9F000403ED44E66E34D6FA5DFD1BED17E0DE54E -:10BA00006B5BED1AEB8FE3AF9CD319C7C3423EEEDD -:10BA100085ED6CDCAEDC6804E8B3760DC52BE485FF -:10BA200019DD834BF3BC887C7502E6EFD5B3B0DD3E -:10BA3000217313F82281FE8C79D5F079D5AC61F3AE -:10BA4000229C9FE8B062D06E4D399BE702C2EA8B20 -:10BA5000F09DB6BF90CFA7467F12D3852D764BFBC6 -:10BA6000BB8BF776E37DB612451310CFEC9DCC3C33 -:10BA70003EAFBC26D65F5EC993882F526F1A2FFA4D -:10BA8000454D30E5ABD3CF53C6A276AE90E74062CA -:10BA90003AF97D05CF518A765AE7757AE3E8075A75 -:10BAA000C1FF79B782E71507C5E09BF9B80F553498 -:10BAB000267F82BF990D727A615310E4F8814A861D -:10BAC000FFD3DF2251A0879127AAD301DF234F8420 -:10BAD000795A87E7D81421429FDCA3E3A35BA7161A -:10BAE00001E4657CC48F16831CA0EB0CF660AE7974 -:10BAF000DC747C192D59551087943939BD4AC1A77A -:10BB00007F13F24FEC9A03EFD8661EDF752BF433E8 -:10BB10008C98E643F3477947B0FB57C7692E94AB3F -:10BB20003F7517AC472B7F8F7E248C2C1DD3E39061 -:10BB30006650FEDE9C0EE394C98CB27E79B0EFEEC7 -:10BB40008A092057F0EE4819A6315236506E98CA2D -:10BB50008FE1E5752149B952AF66D997EFBBFBF28A -:10BB600031B07FDF0A76621ABCE7A77E0AF1317A2C -:10BB70005044BC6FB5C51C2599F05EB848C07ED94D -:10BB800056FC3B11F86EEB211204FAC8A8FEABDD9F -:10BB9000BC8EB51E3FCE5B56C866E0FFA3634ECD9C -:10BBA00082758A1E11F13D89AA5F7876B9C11EFAA5 -:10BBB0003D8B3FE978BE0EF5F7ED794AD2F79AC989 -:10BBC00005ECC4C4F2E923E7A01F2F7FE7767C17BA -:10BBD000B676961CBC8296CEDC595909768C564DA9 -:10BBE000A96B281D77FB84B5C084DA6C765EA5CD81 -:10BBF00062DFB5192CDDDCB07822ECDB239DB2B31B -:10BC0000888E77EC46F66EDDE6924F1C616A979659 -:10BC1000573EE6F816FDFE6E39D582F4FBBBD33EE7 -:10BC200071C2F9CCFDE5551980CF432D56BB8EC0AE -:10BC3000A36A741F546A8F84BC745CADBF25884F9F -:10BC4000C91E6BABA1B0F494072C9C01FB9B8DAD7E -:10BC50001D73814E17146378F280F97ECEF5C9FC0E -:10BC6000FADE59705FA94027EC1C35720F0AE58592 -:10BC70005C6414E8DD2874BC3BD9FE2422879E0353 -:10BC8000B91C29092B50C59067AD236B1E0479F6AA -:10BC900025B7EB48DD62BC0789FC2F813DD45B9959 -:10BCA0006CDF749DDB857475BAFDDA57C13FBDA0AA -:10BCB0009ED9FBF9ED9F0AB81ED4EE1B46DBCF2FB1 -:10BCC000C7A72AC98235114729AC4F9148340DC600 -:10BCD000D345609F10A1FAC78C07A3DDBFB5FE76E0 -:10BCE0008F1DEB5F079BE749FDF3F1F0F9E405E9F0 -:10BCF0007C92E8E939BCDFEFDDF7E9912980FF3577 -:10BD00006C8B941F795B7098C691AF5FDC38AE8501 -:10BD1000F6283E1FF1B07B0BDEF21EBC679428DFD5 -:10BD2000C19C07BEDDED3E3B81EDEFADF27400CC72 -:10BD3000E92AF17B5E82BC2AB577E13DD0D603ECDF -:10BD40005D74D87943BE40448DBD171B35DE2FAFDF -:10BD5000837263BD1E15E8A075CCEFCA003F5BB8C7 -:10BD6000BDB0B084E07E75614E37DA0BF39BB8BD91 -:10BD700020079B41C8BADBFD6493C97E405309B6D6 -:10BD8000D04DDC5E30F43FD7DBB581EE16D4AB4D41 -:10BD9000EC7E6A9F9DA133BD9A1F607ABDB685F681 -:10BDA000A37162AE30DB254C8F6B3BB9FDC0F570E3 -:10BDB00006EF37B385E9AB0CB0237C107EA0A35E01 -:10BDC000C6B3BCAC7EBB654809D39719AD0751AF6C -:10BDD0007583D36508C80DA62F735F7A45073405B0 -:10BDE000E8E7362AA77FEA667234A052FB2CBDDF53 -:10BDF0003EDB20F27326C2EC438CADA7E37C9CB7FC -:10BE0000677CDFCBC777F078FA3741BEEE8B144EF4 -:10BE1000904C7C6BDCDBCA2B67E7F479F5EC9CDAA1 -:10BE20001B5CF4A0643A7F68F1B077AE5A0CBAAAF2 -:10BE30008F05A05DBC4788725C41BFDA4678170A5F -:10BE4000E885EFAF6E70F3778D38FDA4D227861C9E -:10BE5000F29290AF84E2F7DDE88328AF75BA5F8293 -:10BE6000B9BD1B69CC5E02FC1EB9A61CC6BF75CA53 -:10BE7000E71877919F62BF78DED8677E45B9EE9D5F -:10BE8000F50ADB87768B49EFC94CF3CA389F2E99A8 -:10BE9000B8019FCE087BA7D03959495AFE122F937B -:10BEA0009B2E2F7BA760EB9407F15E634AFD2C135A -:10BEB0005D4AA24F0D7DDB0AEB3C9590999E1B9A43 -:10BEC0007594FBD16A09E52BC17D6784FF5E8C5EAA -:10BED000ACA0DFB0D51671C07A6C2BE7EBAA3A3A6A -:10BEE000E05EFA575E178A0F58E78D21312A14C099 -:10BEF0003A47D552E6D7C177394ED3FDBBF99CE21C -:10BF00004A2FF36775C99A08F189F92D8CBEB64E90 -:10BF100051701C9B266475480566F9CBF0749D9B97 -:10BF2000D1D7A629CF217D5DECF816D5DF39F55D97 -:10BF3000D339E2A97B1F2A043CF7BFCB121AF4FEC7 -:10BF4000C2A2FA97A6EE4D723ED0970FFB280FECD7 -:10BF500003A33798CF59E6F1F55DE0B5FAEF40BE9F -:10BF6000DA707311CD06FFD281E9511FFAEF97B154 -:10BF7000F3DA5BF879ED99BDD7E2BB07A570973688 -:10BF8000C9BA7FD0607D07E2837D0F6533BF46D499 -:10BF9000625FDDF2E04FC6B2776574FE7B1A44CB78 -:10BFA000AC60EF5FA39E7E2EA8DBA5FE77CD8C77DD -:10BFB000D82EF65DB7746A86E1BE8B54639A45EA63 -:10BFC000300D9008A6D9A40BD31CD8E7C2FB6BA4F4 -:10BFD00017538DA82231C9FD421244B88854632AF0 -:10BFE000C3BA65F49F4BC89D0E8CBF80F30BE07BFA -:10BFF000E39CC238DFAFF6D644BC49CE2B567B4318 -:10C00000DBBDA8576228B7E773117EE2C763BBE0C8 -:10C010007ECFEA2DEC7E8921D7715F43DBFF513A59 -:10C02000D303FA0E01E5D73AF7D597211E5B6D1FB2 -:10C0300099CF1B88C35104BF1B63B43B9FFB17E61A -:10C0400073FD07EE6D76FF2E88F77FE6839FC19420 -:10C050004FFAF2D97D6AA31DD13D6DD460E77BA66E -:10C06000FA188F5C9360FF5F506F27C00B12EBFFD5 -:10C07000850E28ABDF0FF7A3CBB43C76CEC4F436E5 -:10C0800025240DEBB5D8DFC67D586466C88C9713A0 -:10C090009CFE0D7DB220C1AF9F982E90395F24B4D5 -:10C0A00043359F1FEECDE0DB2626BE36DEBF357E54 -:10C0B0005FEB96505819C6AA05601D553EEE0869FB -:10C0C000AF1A46D3F70136F9F35FF4857FE735C53C -:10C0D00043A9A13AD1FCFED222CE8733A5D64A90FD -:10C0E0006FA7C32408FB875B48DD56B0C7C82B1277 -:10C0F000CAB7E174DCF0BB3FB970A0918EB0AED08E -:10C10000F4E306762FE754C2FBD51FF277914ADBA2 -:10C11000EEB81AE8E00C7FB7DAE07FA3DFD22EF7A3 -:10C120003CD0FBA55DD36BA15C69A71D7FE7A9F897 -:10C13000D0C66AF00BC13B2D2EDA4F0EEDCF910E1B -:10C140007284A0BEFDB0D5155D47C7F9619B8472AE -:10C15000F95C8988EF8DC07397121F5F5A3AB4F368 -:10C160005F37811D7286CB11E3DDC70F2B35DC1FD6 -:10C170003F7B608300F7123E9CA7E1BC3F1CD69535 -:10C18000974EF193E363F7738AF6DB6385741C4B78 -:10C190001EF97D610DC8BFC2C89264E7CC437C4CD8 -:10C1A000FE7DF804C178B80F9DFC778D1C5D3EB311 -:10C1B0009F35CD2758E4D6875EFEFB48391728C740 -:10C1C000E3CB89A7CBC7F8BECB07E751F7B87F8C85 -:10C1D000F7D74E3DC1CE299EBDB7360FFC51C37D6A -:10C1E0001A3BF73EF038C68DC33C601F4DC7A7C150 -:10C1F000F8EE71BF7906FC0FB41EDECF30EA9D3A2F -:10C2000050CBCAB7D1F23EC43BF195013D30BC934F -:10C21000FD4C4E18F6E3D26816FEEE427FBE88F95A -:10C22000304427C57FE9FE6BF05CABD497CEE8596C -:10C23000ED1A3B07C71FC983791C981ECE033FDE4A -:10C2400029E377A0E4481EE0A1DA1B2EF599E6FF6A -:10C25000C1DB4FA17C2F16EBDEBA0BE8F231F63BC7 -:10C260002477BCBE5D34CB8F69F0837893607E2BDE -:10C270007C701E75AAEFBD9C088BF739CCDE635D20 -:10C28000CA79EF5407DD3F517C7CB0FF07987FAA45 -:10C29000EF3D9B2E8C27FB60FFB174486B783C3FD1 -:10C2A000895E8BFC45F1D2E248A2AFFAEE4545D952 -:10C2B0007DB7B3027F87F43E036F75CA1CCB791537 -:10C2C000E3EF9CF682E3682F4793DF934BD4F78923 -:10C2D000EFCA5EE81EF049CEA7EFF277D1567BC3D6 -:10C2E000D7FB505F58F548CDE6E57980E71AB8539B -:10C2F00087710ED3AF80FD36DE3761EFCAC6104FAF -:10C300007DEFC64EBC02E21C4FF9195CE79BBD41B4 -:10C31000E77864EFD256B2FA052CBF95E7FFCA5B07 -:10C32000BD98F54F04F6BB46363FFC3E8521FF52D3 -:10C33000CFDFFAFB14F7834C1E82EDADF60DC16C16 -:10C3400081CDE7EF6BCF90377F773B8E7F6C3B865D -:10C350001C06BE84903D120C8EFD47E0EF6FAD4F82 -:10C36000E6E65BE4F917F78E688673A0730182F145 -:10C37000CFF6D6B504F4D2C29DDB93FEBE5D1FCCD2 -:10C38000E349941194CF4CFC1CF3313B3DC6E521AD -:10C39000FCC1F9CC2842F87B1794A6B230E406F72A -:10C3A0007FA3F97BEFC52482F6D558D2856909E9C8 -:10C3B000C6743CE9C5148F494780AB2F28F1777BC1 -:10C3C0002B60F2CB1CE1FB2154F7AFF6F033404F6A -:10C3D000F07EAF20815DB4622A8CFFA84F357E07C6 -:10C3E0009424FCAE5AFFEF816860D7CC0E0C66D760 -:10C3F0001055FEA82F7EA390BDFFCBF821D5EFC42A -:10C4000025FCFE24BF476CE06139E9C2388867DB50 -:10C4100057BF3086E27FC97E2FEA8351ED4DF83B4E -:10C42000604B487716DC2F1DC5DF93206DEC1D0F88 -:10C43000E39D88316D76CBBB1ECB137E876829FFC9 -:10C44000DDB0A509DF8DFB9B9BE143923882C4FBE5 -:10C450009FA77D29DE612D49FE7B3089F73FF77765 -:10C460008918DFB31AE285847EB937666F9DDD4A8D -:10C470005F5D971599DE7B6A14826C3FED7585F6DA -:10C480000903FB19AB323BEE8020248D23BB268DA4 -:10C49000EF174913B98AB6D3B84C5661BFD918758E -:10C4A000E13968A3CAF685C3BD550ED8A713BFA846 -:10C4B000C2FD94CBA569185FAE2C9727C2B9E7F1EE -:10C4C0003D4BBAE1FE426340463FED703F3B0725DE -:10C4D000C3447C1FA0497DCC3F1FD6C9C3CE19736E -:10C4E0005582BF637AA4E37611E046BA6D190AFD5E -:10C4F00008E16EBC77334C26FCFC75F6044A7FF9E4 -:10C500009C1E64D28AF78F672C7FD7097A3D9FAF34 -:10C51000FB94B4029C87CCD77377FD493FD0E9F3F5 -:10C520001DCD2F5F4EDBB345658C6B2DFEB2F10F39 -:10C5300097D3FE7A3B148C6735F090B746B6DC9FF4 -:10C54000CDB9CD0A2B09F7886562CAA7F038DE3F5E -:10C550003CB81A33C755658698B350F5E0FDE04BFB -:10C56000D304661773B814608A924E5BA4CA45C799 -:10C57000D9F986807E87A31D8BF2314EFF27E17C9F -:10C58000A06F831E12D7EF4BB087908F7427BF1F09 -:10C59000EC84C3BA44FA696A2023C11FED881E7770 -:10C5A0008D83753C61C3F7A4D673FB5BF6B0F87757 -:10C5B000835E12D3F50974B7FECB6B91EE7A29DD59 -:10C5C000257B17CEA827AB1ADA09B61C1204F6B0E1 -:10C5D000657667ABB4DEB8A794A087A2ECF2474BB0 -:10C5E000D2C09E1977EC7AF65E1FC517BEF758AF1A -:10C5F0008C847DBFBD3E73A49C01E53C488F9F7831 -:10C60000D8F98F5CEF0E427E6347454033D1757396 -:10C61000833A521E09EFA53A46C2EF2335A7F89D8B -:10C62000E65CBF580DFE2585EFFF97A4B1F12E49BA -:10C6300073637A0B87EF93F53930FEFB28FD40BC1E -:10C64000C091DB18FDAE1EE6C07BCFAB9F1F3174DF -:10C65000B038A0071B0223016FEDB7D5A0DFA3728E -:10C66000D571E715C0E75E870AF428F946DD330D7A -:10C67000E8FD051BDEFB6AF45668F34DED49BEC9C3 -:10C68000E85792443D1B36450D697FB8421E06F4BB -:10C69000A2EF024DB461DB11067BF56C81E66FDB26 -:10C6A000F62C8387E8BB049A7FCFB6E7199CAB676B -:10C6B000C32F80DCBFED570C1EA9EF02F8A16D2F30 -:10C6C00031186C0B6AC73CBAEDB75780EFA7D1168B -:10C6D0009C0BFE9D1FD3F197D8E0BD5A961EE478BF -:10C6E00031F21F83EF14DF87789A98FF24AFF77435 -:10C6F0008AFC7FE7F98753B4FF335E2F96A2FE5181 -:10C700005EEF788AFACFF17A2752E4BFC0F35F4C2C -:10C71000D1FEAF79BDEE14F55FE6F55E4951FF77C6 -:10C72000BCDE6B29F2FFC0F35F4F68FF4D5EBE8732 -:10C730007FCFF1B6FC41A77497D3C15EF82CF6B653 -:10C74000A0FDDE5E578EF4DF3889D91906BDE740BB -:10C75000BC26C85B95C5558D52D93EEE9769CCDE97 -:10C76000A85C55B40DE86EF5AF24D4A7548FE0EF64 -:10C77000F0EAAB58DCCBEAE7D97D90D5AB647C27F7 -:10C78000CDA047A3BE31FEDD7C7C4D7CBCC7D20A68 -:10C79000F9794B60E46C73BCA76A851D949F206493 -:10C7A000A72993E997E255558ED1A03FA87E01B9FC -:10C7B000B9DEA3C4E01EFD7A55C6FCA6CC2A15F24C -:10C7C000755546FDB33EB3CA311FFD39E9E89FC830 -:10C7D000E7717B4DAA8CF7F865FF0CCCBFFCD1D973 -:10C7E0002AC8D126D2EBAF84F9AD91F1BCF6485DF1 -:10C7F000157ECFF77FE607F9FCAC9FE1FDB8F7396E -:10C8000027BCE72A7F4F447D81F8A3FD16AE11A314 -:10C810001A2D725C5D2D02FC4013D357F4CF3BA15F -:10C8200082C771D0BFCEDB2B5E80F89DC62D721003 -:10C83000CE73E04F36E98322FE7BA54355B66F34B5 -:10C84000F4D57DDC8FAB071C188757249380F977CC -:10C850002C87AAFC3C8DBF63362262D54F052DD6AE -:10C86000776CF213F453A2BECAADA3F2D154DE1E0C -:10C87000502DB0A0B2F72CFE17044CD03900800028 -:10C88000000000001F8B080000000000000BDD7D91 -:10C890000B7854D5D5E83E67CE3C3349669299640F -:10C8A00026CF49801020C0044204449D848011B1E9 -:10C8B0000E0F15D4E2846780BCA0A858E9C7840491 -:10C8C0000C1435FE46047EA003A28516ECD0A2020D -:10C8D000063B2022FEC53658DB8B8FDA11B9883C27 -:10C8E000C747953ED4BBD7DA7B27734E12C5B6F740 -:10C8F000FFEF77D3CF1EF6D98FB3F65A6BAFB5F6ED -:10C900005A6BEF215EE2FD5A47C8E23D8B6FB410CF -:10C9100042C6FFA228395A44C85253D210924CC87A -:10C92000D7F07703214DCBC3D7F7D513B269B9A997 -:10C930009F429F4D5F0E9F464A0889255A7CDB2403 -:10C9400042562DB7F553FA75B51F68A32F9D846C19 -:10C9500056829389833E430A69CC23E4D0129940DE -:10C9600079B1DB1432D2268B5FFBFD4DFDA1BC48B3 -:10C97000F6124F577FEDF399E5AE7EF0FDDF50984C -:10C98000605C7D40EA777A38FDB71270F91309E9E7 -:10C99000D3AA9C8A9A08FE7D4DFFCB6BA1E5C2AE5F -:10C9A000B25EEFB7D9AC84E492B876141E4553D684 -:10C9B0003BDFB4078A607C05C7D7C291DD40E71F23 -:10C9C00037AED165539557490D85A40F7D52580157 -:10C9D0003F41A71C7A9ACE336BE983A34FA71292EB -:10C9E00079D4D20C7825AD4F129246880EBE4DE711 -:10C9F000AD483E0FA17468CE2BF64AF479EC590B82 -:10CA0000C353B615F16490BCE937D3A751F6DB6088 -:10CA10007CFAE783F11FCAB66C5D9307C58009F005 -:10CA200090B5830E98418BC19CD53E85D289A29B3F -:10CA30008C86FA375A7C745E3BA4CE722594C3214F -:10CA4000036B4F4804FE6F8F2CF17AE2535C84EC49 -:10CA500096245E5F54599145DB2BB6418A9790B975 -:10CA6000AD435BF4D741BD2CFAFBC8483A3FF81EF2 -:10CA70002F035E7E7E84D707AF6BA9E84BC737884C -:10CA8000EF9320B4DF23CBAC1C2C6D81F17797F3AF -:10CA9000FE41CF6ADF1884E7669D9D9025B6B216E9 -:10CAA000ABBB0BDE95F61B5B1AE9FC2E7AA2497430 -:10CAB0001AA476EBE93442875A352DE0073C12E29E -:10CAC00025FEC1849C9528724774D14FBFB72C981E -:10CAD000495F5D3EFAB7A422FAACD7458F2650FCD9 -:10CAE000D5EE0B98F4F914CF7A5F3033AFAB5FED2E -:10CAF000DE492440F9A6BEBD189F3DF43BA6C8FF01 -:10CB0000543F93E12ABE7731F246DD2E5A55AB0BE6 -:10CB1000B458FB607BC2E8DFF3FC44FF8BBBDEB89C -:10CB20001DBE77C9134D9B007C19A178E9A19F68B0 -:10CB30005FB7AF8C00DF5FB1F89A6CF4FD5D76B63D -:10CB4000CE88D2E085F66153ABCD4BEBCDFA56BF24 -:10CB500097B6A7A40CC923BB9EAB6C7D713CED7B43 -:10CB6000EDFA099B48EA44CAD7C11AC5FB34817261 -:10CB70003061082DAFAD55863752905614FF71586D -:10CB800011949FB312232D37D51C7115C13AF21A97 -:10CB900008152F64EDA8B01BD67173AD61DA76E08D -:10CBA000DFC862D79CA2AEF157DAF508F7EA57E87A -:10CBB0003A1B4A9FFAB05D82FEFD1402EBD06CA7CF -:10CBC00074A665B33B8504F3A09D752DACC7D5FA5B -:10CBD000406539B473CBE469FA5D73BFA995E51478 -:10CBE0000E975396740847C5C9B9B4BEC96600C943 -:10CBF00046DEB0CFDC0578FAB9E26D8075F873AB2C -:10CC0000D516A4155436FA60DD2AFD1C21281B75A3 -:10CC1000A4214CE1CB2C26FEB0B50BCE376094118D -:10CC2000F03420BC6BCDE14965741CCB62D916A4ED -:10CC3000DF5B5DBBAE633CFDCE7FD63E7FA291BE87 -:10CC40005F93A61080C3EA50228624CAC7B7501843 -:10CC500029DCBB1BFD36909F31A742B6D17A4B5FD2 -:10CC600003F1C4C9416B112DC7C9A75487E233D35F -:10CC7000FE317BE0651BFDEEF0D7DF34417FD70846 -:10CC80005986651356189D934AD4E3D8C6A8C74958 -:10CC9000A950D73B26AAEBD3A6AAEB5D77ABCB195D -:10CCA000B3D5E58982DFA8CCB196D279B02A628962 -:10CCB0007EBC9C24217EDE02FC5B0A642FE0C75C04 -:10CCC000BBFDEC5C5A9F09F284C24F8690D0D3948E -:10CCD0009E87737EE889523C1B531A3CF6A2EEF8FD -:10CCE000C8CC36DD0CF4B2F6556C84B6B7BEFBD1B9 -:10CCF0009730BE95C4B5CB03FCF84E037DE1CF451C -:10CD0000E149847F7800DF0D7FFE11E8BD133A2FE3 -:10CD1000E03BB356C1EF3F3CD513D2E5B1E684B654 -:10CD20004FE2ED934C6B3B7443E8F3DDD58B7449D4 -:10CD3000DDF19A461A245897943F505F902A82FA60 -:10CD4000E221995403DFD0E54A603C1B74A072E6EF -:10CD5000C61403F2CDDFB97EA59C26437D9A8D8D46 -:10CD60006970CF36C37A5E7994F1FF4A031BA773CB -:10CD70003C0F7E145510C849A35DC6F1C438EB6C56 -:10CD8000BC0D2F3BEDACBCE748CACDB02ED74D4D06 -:10CD900019067C62944900C64BCE32F906D0F99947 -:10CDA0005F3304253A68B2428EE853687B0BB9C7FB -:10CDB0004FE1D870CC12D4D1F7E639FF61A34826F1 -:10CDC000857606F79E15DEDF831C8855298847B3D4 -:10CDD000B3D536AC88CD2148E14B817F50F958D688 -:10CDE000AFCD06F43497B5A2FE3617B7B6029E361D -:10CDF0004C94D19E48992D233F9BB3C327FAD2F779 -:10CE0000FA39B20DC64BA18ADD4007793CABD5EFAC -:10CE1000877129CEE552C62A302ECE907E2795E323 -:10CE2000D5E1D87BBF44C74985F186B0F680273B62 -:10CE3000C793D7EE41B81D7CDCD4BEB4FD10364E8E -:10CE40007369D738828E1B2A4908E013DF15E37413 -:10CE50008E4F7C12C855FD6F28DE289DA41C13023E -:10CE6000B772010919F3003FFE86ADB8AEAD641B81 -:10CE7000AC17475639F051C6B18D93E521D0CF821A -:10CE8000DFD1CF2121E0E30C8598AE4F01FBC58FA8 -:10CE900078D4AE57F791D629748D74D245BB7EDD18 -:10CEA0000A69D1A5745FC76E87A3BC60480FEB59B0 -:10CEB000B35EDCC762F702D36BD7F596844BC580AF -:10CEC0001712DF5EF7ED659D2E7C623C102B9DEA0C -:10CED000098AFA1CCDF708F9CA086589C89EAFFB14 -:10CEE00080DCB7F3F540F5155DAC7B86D9C65A6199 -:10CEF0009D2E22C85FE52FACBDF33774BCCFFB1964 -:10CF00006CA057B28FB576807E24FB02FD810E9B0C -:10CF100094C04F1268FDA693E904E4F66A339906BB -:10CF2000FCAD703ED7EA97957CDD7840CFB9FEF92D -:10CF3000A7B007C37DD306D9E8DA5BF9D8E1632649 -:10CF4000E77FA39D45FAA39D9575A4A3D10ADF6F42 -:10CF50002D6F3151FC9A5F67ED9B6939A800FE6A1D -:10CF600072611D1ECE9E8B7852DE3612E0D3C13A1E -:10CF70005F08CAE41D3301F9BBE3B9BBAB3D207FB9 -:10CF8000D22678400EADE3EBBDCD2EF5882FC5E05F -:10CF90000B803DA17DFF08E017E9E93F5B45E938DB -:10CFA000F8290359432B0BE5992D79B02E5653F9E7 -:10CFB0004B6B67EA3C753F96BAE8F30B73D9763B47 -:10CFC000EC3B969B48C048E775452201BA38B31D33 -:10CFD0006F9481FCC9211109F46C4E03357881AF3F -:10CFE000965848208EDFB3AE28D8FE1766DF763B12 -:10CFF00097FF262A07F4EC9FE4E7297E52E560328A -:10D000000AEC17FD2ECBFB203788A3C2D7B9DFC8A7 -:10D0100007FEA57A9F7E6F0F9FBF9EE2503F8CFE5A -:10D02000679523C621DDDB3FCFF1A398AC11909724 -:10D030008AF5F849942F36E5427C3B5388E91B5228 -:10D040004342FD2486172CFFC086E54C2A7F8DC302 -:10D05000D0EE0F1A01CE24B6FF203E9FC79106EBFB -:10D06000852092B34CA4C544DB21B7D3F5E6261D39 -:10D0700066B49B8F100FAC078A31FB9904145904D6 -:10D08000F0BA8990CAF875209E0536462765A90E24 -:10D09000F74B835E36233CFA061232833D04B051CF -:10D0A0007C2B4B484881FDD65203B62BB079B09FFC -:10D0B0008134A03DBBFBCBF732404E5B8E527B6C84 -:10D0C00028D059463965B1A8D71F218D88A7D39C90 -:10D0D0003F362FB7219D3BF7678137399DA38DA040 -:10D0E0002F7296A4A8E82BDA655DC92481E1F1E3EB -:10D0F0008670DCACBE47245204F53958BF79B9E7D5 -:10D100005BC6CFEF657C37F251EFE36761FDE6C8A0 -:10D110009BF6EF51546C8A1DB1FB3D5DF6B516CF01 -:10D12000594BD47279E83E7559E0C5ACF7392651B0 -:10D130009C9BEF95BD5BE978D79C54B7ABCCFB03C8 -:10D14000EE6FBBDA471C53A03DDD7F6FA56FAF3D8F -:10D15000AB6EEF2F7BC50EEBB8AB3D83EF862BEAB2 -:10D16000765AFA68E1A570396F8B836BACC9A8AAAF -:10D170009F56D50D2EE71D7170DDE852B70F34F6BE -:10D180000CD7CD85C66F844BB4BB75E4D5B5D3CE73 -:10D19000634AA5B117BCB3F6774CBBBA71EFAAFED0 -:10D1A000E676F72CD57E2788FC7EB3E4BB26853E49 -:10D1B00067C22BB017AD16B47BB5FCB29DEBA7EBE5 -:10D1C000C19EA34F7FA2EF7AE83706D61D2D1B76AE -:10D1D000FEF14E902FC79E1D980E723D13F41CE277 -:10D1E00093F915F6D4B8D0AF3095AF53AA4F9A4102 -:10D1F0005EECD941FB2531B8E2EDA7D41AB6AFB049 -:10D200009118AE67612FA5109BC4F6E3CCDEE9ED63 -:10D210003BDAF11BED0CEE594BC7920FE83A7CDE7E -:10D22000602B53607FB645427B6056854F9748F927 -:10D2300063748B847EA3590FFC6038C89551A73D59 -:10D24000FBA2F4FDAC90DD0B9FADEB20BE10E5AB77 -:10D2500074DDA2E21FD1E71387A9FDC3CB8B80DF6A -:10D26000AC3E0FEC37AA00223ACE057D43B10DE467 -:10D27000E6F7AD3E909B55537D6FE17CFF41AD12CB -:10D28000DA6E0E9B3A79A16D92C143ED8CAABB3D3B -:10D2900023C1EEA90A9B7DF83411C542E75145ED43 -:10D2A0003178A61B886286A78598E059BA82D95F33 -:10D2B0004923FD862AFAFDAAF69FFE05FACD5322E0 -:10D2C00087983D19C27957B5BFF657B0D7E6F8FC35 -:10D2D000069017837618984DCAF96170585D0679E3 -:10D2E000105F2E8EA8CBC38FA9CB7F4A61F83D205B -:10D2F0008506017D0E500507FBE2E06E23EA8BC335 -:10D30000078D489F85E72D5BC1FF3476A115E5FAAF -:10D31000F99F99D11F75400E3F0BE5E0B309B8AFF7 -:10D320003EF4F68152899617FC225186FA17BFD433 -:10D33000219E613A7AFA7EE1B303B6AEA1EF170EF1 -:10D340000F97DAE8FBE70712D201F54A6808CCEF3D -:10D35000F9AF74387E6CA731B48DF2C3F9FD3F7D0F -:10D36000F641FAFDF33B3353244A976B411FD076C5 -:10D37000A39F3259609F31FAFCAE3E202F16EE304B -:10D38000AAE6B53545E2FB194F12F05B6FFEC453B8 -:10D39000AB7F8AFD0BCF9E447E3BA00FCA1698FF41 -:10D3A0006AC65FDAF63B52D87A127040BF3C4A9F99 -:10D3B000CB1F59EE013F5AFFF56AFC0E08A9CB615D -:10D3C0000ED74C12F73E0FC6CB5FE5023B752B41E3 -:10D3D0007BA6F0ECBB77E6811D6D64F683168EFDAF -:10D3E0001C8E9FFD8C8EC3E4838ED9CF74C6743D92 -:10D3F0002EE47CFCA2C4EC57FAB72493F2ED425021 -:10D40000FCF95DEF176AE010E3DFCBC777F07D75BD -:10D41000EC751DD2E3DCF2EAE1A7FB7587E7CCF2FD -:10D42000860115FAAEF2DCF58B8EBA69BF9A3D4ED5 -:10D43000DC278AF7353B5F4EBB8BBEBFB043F18222 -:10D44000E95A33FD99474643BB9DBA30C00BF53EC0 -:10D450003ADF0BE15792A0DDDC4DF661BA383ACCE9 -:10D460005B7FEF808A3879F85DD78358BF357C7F42 -:10D47000FBC2C88EF199C0DFEB252F345B18BE6D5F -:10D48000CA2D60AB6CD279FBD1FA5285F875C370A6 -:10D49000EB3D159E357B9E3B9A41EBEB0F8E28852D -:10D4A00079AD91FD370F06FEDFA2473F96162F9FFD -:10D4B000707AD3FE1199F65F73BBB53A64C5718F6C -:10D4C00040F970E1361DF8D993CE52F9C4DE9F942D -:10D4D000E99A3CDBBE7208F8130FE8AD2DC0E707F0 -:10D4E00012191D82BB7528E74984CD6334F71B2FC1 -:10D4F000FC539B41A1CFB367572495B17584F205C6 -:10D5000084B283CEAFFAA9C1B8EEE6AD57AF13D15E -:10D510004EC03B3FA4AED7F2474AAA5857A4309E0C -:10D52000CFB4ED5227060DB0AE6A9652791C67FF54 -:10D53000D49C6E3580DDA4FD0E588044D05587FC08 -:10D54000493C385F339B2F35594D74BEE7E05FCCC3 -:10D55000EF2DC1BE7C818453240B07920A0FC5E7CF -:10D56000C2C9A4129E07A4C8233A2ECFD0FFBE3B47 -:10D5700001E5D9055BF499FF04FEDB95ED0DD2AA18 -:10D580000CEE97BBE08924A5D0E7655817C07F361D -:10D59000565ED04EE5395DDFE72F1A50AE37865F15 -:10D5A0004E027A5D78D62CCB942EE7F7A496833F73 -:10D5B000E742F8374930AF73E1D472F0CBF5266F0C -:10D5C000B4724AE8F3F7E19FA3A89D96EA1B960A76 -:10D5D000FB9DE65430C6497A6A4371430FEB5FF412 -:10D5E00073181A8A3D2037BE6FF5C2FABC21D5C325 -:10D5F000F486C4C6833F1FADFFE458EA36A0FFB1EE -:10D600004305C9A0E73F219E6490BFB739FDE5A956 -:10D61000B4BDABBCC3A703FFDF04E26DA27D3ED067 -:10D6200079EFB3513CCF2654EFC0B32460407F491B -:10D63000B313E19AA5908842F97416E8C5215846BB -:10D640003CCFDA24859A281CB3D7AAE739B7CDD8BE -:10D65000455FFADF7C4205232CA04D71EDE8F8F31D -:10D6600041FF51FC2D309148021D77C17675BF8571 -:10D670002482F0D4ECFADAD8131EFFC2F1789BD3DF -:10D680007757AA4A7EE9517E2D24FEEBE1BB0BB908 -:10D690009E9D633C8470D43FF0C080D9D46EB8BCEA -:10D6A000F4C101B353C10FC8FA91F512F2DFC20AF7 -:10D6B00012C9A6702D6C972283C10E7893D1478C26 -:10D6C0004FB6B07677723B650EC507E8FDD1BBA4B7 -:10D6D0006022DDC7CC31D12D18C80F3E2FA84FA630 -:10D6E000E56AD28AF3A9255184E37E4E3F8848013A -:10D6F0003EFFF226A3DBE8EAAD3A00EAD8A1528C5D -:10D70000CB7D4ABC483F6A4F10734A77FE007CFBD2 -:10D71000E2F053BD495D26DBE3CAF9804F5A8EC360 -:10D7200073DDDEAF8DBE1EF0FB44A73E090D9834BD -:10D730009874B357DFE3F87FE2B6B96E58FF8F8273 -:10D74000FD96C1071809F292087F44C444C7B70C7C -:10D75000272AFF04B58BB0DCF6F86B37ADCF226417 -:10D760009D3E807EFE593AFF5108497DE60CAC078C -:10D77000BACE927D390ACA015F01EE5397327A3CE4 -:10D7800039AC6140430FFB5301FF3A291C91411E04 -:10D79000EC67FA3DB124A60FC4ADAF5F72F9967C79 -:10D7A000387A3413F8E63909FDE91B24D22C513CB0 -:10D7B000BB2859400F6C90DE3F0A7A63C34D1ED2DE -:10D7C00044EB4BF64E5AF40AEE712D5E884FD4EEC0 -:10D7D0002DD3D55A71FECCCE4C68D82AD3FAF47B1F -:10D7E0000A87C1FAA0F3BE67327DFF02A7B7DBCA82 -:10D7F000F8C1B52298B718FCA987FD8B5E81753DED -:10D80000D8827EAB748AABC4147CB680FDE8228DCE -:10D8100012B45BE594901EABAAC8B45F1621D7285A -:10D82000C929EC79923E258534831F365DA1F628FF -:10D830007BDF0CDF792289C1E59475F74C027B7898 -:10D84000182BA72C937CDB90F91F437CA51B492543 -:10D85000CC1BDE83FD4CC1F0EDC1FA10C29D3EB67B -:10D86000A118E048EFC39E0E43240BC6392EF8A43E -:10D87000DD2D839C5EC2F5ED923D65E929B4FFF193 -:10D880000B2605E4E77197B0FF2256B0FF48DF4250 -:10D89000D69EEBB525C563D381EF1D39EA7697F5A2 -:10D8A000BEE4E1A01F4EE8304EF399D5976CA7ED8A -:10D8B000AE35B07968E97F96D3B5FE8A444271FBF4 -:10D8C000FDFA699FA35D5D7F4551BDBFB0DC444259 -:10D8D00071FBFD9AEAC3E3A15D2DE95805FC581BD5 -:10D8E0004E20A1B8F571ADA5E7EF8A75517F454788 -:10D8F00082C391EDB3C02F795C1F5B3507F8F0A0B0 -:10D9000084FEA37ABA8F0EC6C375259504537B8215 -:10D91000334DFD9ECE4755DEF705B62323A349F0D0 -:10D920009D4BB668929DCF0FDA097D77392407F5B4 -:10D9300043312EC8F41EF875ACCCAE9D04F455628C -:10D94000499313BBC615F5305E4ADC3C2F4D33902E -:10D9500008D22586DF05BC05FB13B2B1FD63830742 -:10D96000F47FFB21C49BE09778FC05E3E3444D1D65 -:10D970001199CA8A7C876D4DD100CA7A87855C4827 -:10D9800059037EC9349DAC921309259D7203C5D4F9 -:10D990001310B5423993BAA6624C7C99B5EFEAEF01 -:10D9A00098007ECF9222D6BFC8E1FCAF157DE17D05 -:10D9B0002B93BB4A2CC79F18573669CA565A1E1C50 -:10D9C00057B669EA1D9A7A97A69CC5DA5F488CE437 -:10D9D000E8BC54DF3BDC13142A2F2FB82333E80EA6 -:10D9E00096AC6DCA9C5041E5586D09D3C775ED9250 -:10D9F000177D751C7F755E66275ABD51C3AC22C06A -:10DA000043C751902B35FB249B44D78135BC2782DB -:10DA100065E8E789EB1796B05F4DF87DECD7EBF83A -:10DA20008532AEF33585A758BBF087A8F757355731 -:10DA3000613C5DC48B75C4EFCB94BAE2C542BE5E57 -:10DA400072FB5E96195FDBE2F74FF5306E9C9F46E6 -:10DA5000B47F6770FB1FC0AC4858F27123D8AF7F0A -:10DA6000AAFD7004D873EF40935120AF4303E0BB8D -:10DA70001B496000E8C9EFD7F63B24D376EFE9A352 -:10DA80009B2126769FA318F1F75E62345BA2326673 -:10DA900069DBB5ACEC8C6E067CFEB66D0C2B674773 -:10DAA000B3655A5EE698C7CAFDA29BA1BCBD6DF2E4 -:10DAB0000485E2FBBDC1D16C1DED9F1F9C32A1828C -:10DAC000D63F6DEB793DD73A981C11F0FD57BEAFAC -:10DAD000DA01F3A961FA6733B5374D545ECE587059 -:10DAE0006EF7D3140F337E988072ECE90B53263017 -:10DAF0007B3CE8574AC1DFCAFE503FA29C57D03E4C -:10DB000071834E4CE9A247624E8707F5C7C0863D38 -:10DB10006067A4CF2842FDE14DF5FD0EBE2B9EF7B8 -:10DB200067B0E7EF1C3626B77532C69FD31F4C444B -:10DB30007BEC51339B0F5D37485F2BA7C70A07F378 -:10DB40004BAF70303FEAF4D47138CEDB926F8389EB -:10DB5000E2FD6D3D099A41CECEB7A0FD7CD7562A95 -:10DB60003792C18FCFE06E7BCC1D82F8F95D12F148 -:10DB7000835C11F2A3CDEE73A7C4ED43DA8A69D9B1 -:10DB8000DAB5EF6C9BE4735B1CF04C9321CE22E47E -:10DB9000525B1EEB27F4517A13FB4EFAA303B6C176 -:10DBA0003C1214E62F9A33AD605B23DA03937FE7D0 -:10DBB000007BD9E77383DFE1F4FC7C19FC48823EEB -:10DBC000E7F37D9BA0FE4EEE87177412F4FC1D9FB9 -:10DBD000F72C1DB527E87C8F3B03381EB52F8670C8 -:10DBE0007F15DA17BF03DD1E875FA24447C0FBFF26 -:10DBF0008FF07408E8FEAFE2A976299517F255C8B0 -:10DC00000B8EBF7552449FCEE405EE9FE13DE89D2B -:10DC1000CDA9813FC0F8E2FB331EAC457B52C095D5 -:10DC200070FF0B957790EEEB4C6BEFFD19E81567E5 -:10DC3000977A85DF917FE7BDB74D186778CF10469B -:10DC4000B9F91EDDFF34827CE171F2D21F2E3C0E49 -:10DC5000FB3F31EE38A70EC75B2DF9DC30BFD59402 -:10DC6000EE26807F9201ED7FA157DBECA10D90A7FE -:10DC7000D0765B16E6295C262C1F24B83401DB5DC8 -:10DC80002B9F22E0C78C8DB2619C9AF209D6B74DCA -:10DC90002FC07C11CA0F4133D4537E82BCBAB66206 -:10DCA0003A21186FFA40AC87FD31EE6BA79B70BC30 -:10DCB0001EF884F985FBB37C88B63CCE87F3F391DC -:10DCC0000FD39A98FF9128BE2193E2F47C9E93F99A -:10DCD0007D124AA2CFFD2FE0F9B566B46741C76255 -:10DCE0000CA7351DC7A3F4B738991F00F96CF623AC -:10DCF000893CFFCC5B0A787D2891F1E526338B2F98 -:10DD00006DA2F633CA45CEBF22EF2DC0EDBC68B57B -:10DD10009C04F682CBD9E95FF0C17E1FFDDBB47EA7 -:10DD200066547A1FF66B3383BA8811F65F2DE37C55 -:10DD3000D1B8FD0BFC417CEE1E2E57C97A827EBF06 -:10DD40007BA05F128C6F498278E43DD01FFCABCB87 -:10DD5000C6A9E26E039D6C7D0BF8B4727FA093C9D7 -:10DD6000490AB72FFE3B627CED7874FF39C8E9445D -:10DD70003C4792611FD1A8433A6AE18CAE677EEAC4 -:10DD8000E8FA5CE43B315E6F70FE5917BB57A27A2C -:10DD900070EE58B62F17FB9E397CDF4C96A9F775AD -:10DDA000E057E92CEBBA97B5FB4488A7ABDB33BB54 -:10DDB00025A12866C0388B4752C12FF0D51B1E26DF -:10DDC0007D47BC09BDF7A499CAD314D87E4BC8B708 -:10DDD000EB1F48403DE6308406005FDDEDF460BB9C -:10DDE0008D90D7827A95ED973F3D2EFC1CEA7D728F -:10DDF000BD25B605F0556F61EBE8D2C1445C07A4C0 -:10DE00006F7406E4855D3E6024C0BF7552B400D6D1 -:10DE1000F525C95785ED1A133CB09E3E903B10DFA7 -:10DE2000F580410A577DF0EF988F54BF4FBD6FBE0C -:10DE300044FFABA6FC7E498E96C238421EC0FA470C -:10DE4000BBA89AC569EA6412847DD5B5F2CCF9A85D -:10DE5000FFA767906DF8FEFD02D84709394FDB1D1B -:10DE6000915218DBC07AA9E1F8AB934F61BB1AC895 -:10DE70002B023CC2FE0AFC615019E7C7AD5B7B1E5A -:10DE8000F39AEAF6AAE95CD3C507D2D712F48BE37A -:10DE90000B5CC741A41BDAD9B0EE2B589C39919783 -:10DEA000132A3B30CFA99EFB3B9C87A3E3419E24D2 -:10DEB0009684C94CFAAC3FCBEC8CD1ED5B5F867D90 -:10DEC000B4BDB2231BD8BF9EFB03059D059CA3DAFE -:10DED0001F43FF86B04FE2F6990326ABFC0C2BB034 -:10DEE0001FEC5BE17B5178E506F233BDB68EEBB5F6 -:10DEF00004D80083FE6BED8FFA0FF413C825B1EF41 -:10DF0000053905F2E13367F94F418EAD4D2BDFC680 -:10DF1000E419E52FB0E761B334AA773F9EC08F685C -:10DF200007FBDF6FF2D3FD92F3ABC3C0E52E617E3A -:10DF3000B9C5AF39855F0EE36F8B254F3AF0EB190A -:10DF40005D00FD6FF34810FD42F3C1EF459F357C46 -:10DF50009DCFE5FEA4B9DC8F047EDDF83821F857AB -:10DF6000E3CB0B08E35FB2C3D8953F037E9F0A1251 -:10DF700049A4E3D5825F0A9E6175BF3A12637CBFF4 -:10DF8000EF6BA32A0ED9C6E67D0FA7BFBD22A4035F -:10DF9000F9B0C1CCFC51426E8C5EC6FC56C9C37C44 -:10DFA000792B81CF5FD3A33FE37F73BA093CDDE6D2 -:10DFB0002CDF05F8B7C03E0DDAAD34A2BC3C4DF500 -:10DFC000F01EEE47990CFBCFE5810190FF4D145BED -:10DFD0004EFCFE543CD71C305703FFFC89EB31F15B -:10DFE000FE31A79EF9E15730FE8D3526A0BD4DC507 -:10DFF000C610E0AFD27CA10FC910F06BBDAF677E39 -:10E00000E0BADBAD01182F2A3339738ECBB3734ED0 -:10E01000967F27CA9DFB3BCE3F22BE077E9E78FFA0 -:10E02000FAC79DED1FE37624C1F9AE9BCFF3B73B52 -:10E03000F95846799450E447B97BAD5C8EF228F6E6 -:10E0400091D50378A93C5F331FE6F1C9340B8138C1 -:10E05000DB6CEEEF95D2EC0887F0EF7E5BFCAB72E9 -:10E06000CD009493A23DC472A1BFD64F7C80CBB1AA -:10E070000384C11B6C3632BF3C87FFC0D98121E0CD -:10E08000636AD70641CEC5F69899BEA37628C8D74D -:10E09000037BFB87603EEFEB99BD10A4F297F50F71 -:10E0A0006C003FC8815F3ABD90D753BFE0DC10B031 -:10E0B0001F0F9CFDD9AF7E0BEF0F1ABDB0DF3BC029 -:10E0C000FDF235864801DACB3C9FB1262952007E0D -:10E0D0009F1739BD6A2CB44CDF579802D96923BA0F -:10E0E000E267D00FDE9F0A31BBFC14617C105CCB71 -:10E0F000E29C14BF6E8023B63A1DE36F302FA0C39D -:10E1000007070723DCEBF4BCFDC3CC7E3BC5CBA7E4 -:10E11000F617637EDF65BF01F371EB1F65F6E22C36 -:10E12000D9B36529C8CA9712D0CF38A7ED04C64322 -:10E13000EA1F993711EAEB172CFB1EF9863801E824 -:10E140009578FFF62512CBC17D70757E3842BF7B76 -:10E15000A97D809785FB5C185CAAE3799FA7297E3F -:10E1600001EED8413DE2FF6AC747876129D36FE8D6 -:10E170000F8F8FC7A03E50C767BEAD7C491F2D785B -:10E18000807E3F9812B835CDC9C41DD0BDFE25375D -:10E19000CABB0F1EFE2207ED8956164F38ADF7CDCC -:10E1A000807562AF881866C6D95FF3D2F8BEC3C85F -:10E1B000ED462A07E3D7BDA82F2D57AF33F19C9B1F -:10E1C000C6ECC9441EFFEF5E2FF25EA718417F32F6 -:10E1D00097128CEBC17173795C6EF4D9D821C8A306 -:10E1E000AA091763DC2F775904D725C57704ECFFFC -:10E1F000D31B12993CA1D38471E68E2468B7CED587 -:10E20000B17C86B9466A07333D8EEDCF6C48473CFA -:10E2100094AE60F65FEC3909E5A2884F5611D6FF3F -:10E2200085E6F7833ADABE6A87544C452BA96A2EF5 -:10E23000C37C87059BF290FEA3B9FC9D65F4156C29 -:10E24000007E7B2111F98D7E0FEDED1AC8E91A864B -:10E2500072C900FAB07A8744D690F878AA860F423D -:10E26000EA78CCE83093DFA037489C9D26F410E88C -:10E270000BA2B11FD57C11E4712A469FC701AF23C1 -:10E28000BAE43F62EC1BF420B5A3DB601D9796B3A4 -:10E29000F516DB23219E6B49038B1F713DD4090FBB -:10E2A000D76367744C6FCE353E86CF9D697908C7BA -:10E2B0000288B360DC206600B9D81B5FECEC852FC8 -:10E2C000043FFC8CCFA3E62C895C47BF57B38C443A -:10E2D0006A87B067E210D4CB4C3F9B987E86A7E557 -:10E2E0002AF4B4563F6BF5B1560FA71B98BE157CA8 -:10E2F00010EF97077B64F4B2908EF95FB36C90C710 -:10E3000027E8323DD57730C3D9656FD59F34993C26 -:10E3100043A1EC27F956F02B95556681DF9ACA6F19 -:10E32000587709144F5BE9FBCDDC2E1F91C5E6EF52 -:10E33000E2F93A7AC54F8AAD40A70EDC47C79C0484 -:10E34000F7B502BF9B1369BF61D08FADC7CEFE2664 -:10E35000D26C89EB5F7EC08CFAE4F3FD89985F4252 -:10E36000F543AE9D8E97F60EB5CF69F9D28144D4B0 -:10E37000EF97B8BC77087F055985F4FD13A7739014 -:10E38000946782DF9748133241440ABBB1D6DE9BC3 -:10E390009F9ED7E775DCCEF8CC887AF6737BF43E87 -:10E3A000285378301FF80F5C2ED4EF1D5BFC20E45F -:10E3B00001F8AD5E86D54031D80D46DD92DBC11F38 -:10E3C000345EB72CF6009D476DB615F38C2B72DFCB -:10E3D000FDE3745AFE68AF9E1881EE4F4F498E40A0 -:10E3E00037C5E7EA493FCF0FE955E7D816EE509712 -:10E3F0006BC3EA723D893BE74651B0F4DDE2EB8F37 -:10E40000C4F1C95769898E338308C8142FE44913AE -:10E41000DDDDC9811EE4A5787EB1DC7BFD113DE622 -:10E4200099E9D3591E8D01EC9A99C00F3DF46B4FB9 -:10E4300063768DD1D87016F2D58D2F1ABD8DB4D7D5 -:10E4400089B44012F4AF936347819EC6DC0B43400E -:10E450000F96E7FE03E3679FFF8878013F9F9BCB02 -:10E46000D0BEF97C83D903FBB2B61C2BF357BC2476 -:10E47000852466BF4F1C510AF1529C03A95F7FD3CC -:10E4800047EC700531C9485FBA7B71819CF1E17E30 -:10E49000EACC248B6D05ED57BD9EE9DB1AD29104C1 -:10E4A00072604A3AA79F6E97C144FF99D7EC1BD080 -:10E4B00048E15DE8B7E0B91AE54BC50FFCF5100C73 -:10E4C0001967FF0F4C67F2A0D6143594C1F7FF31DE -:10E4D000BBD299DFE5DF32E8997F4BD9571CC9A43D -:10E4E0005DE72D9D85FB9CCEF8F30696CF34EF813A -:10E4F0002A7CFFF20623CEEFCC4109F9FCCC66362C -:10E50000FF79EBCD1EC8BBBEC1CEF6B3F368BF9E8C -:10E51000E77FE34730AF0F37DDEF05FFFC87847DF2 -:10E520002768637EA80F6D2C4E0E6D619C0FF7F669 -:10E53000413BA67AFDFC899867B659E7053B821CEA -:10E540004C44FFCEBCCDF7FE7614F88F26DF59027F -:10E5500078B8C1BE240DFC25B49D3FC4EC6296BFC3 -:10E560009B32F2195887377C39B6E306B09736D319 -:10E570007592C7F2E3C14E3FB2F946B44BE74DB2D4 -:10E58000D8615E9E4D4F8F07FDF1E1A40C19E7B3F2 -:10E590005B2236C0837D691ABC9F2729FE9EF8E95D -:10E5A000A334E6672BCBB57A23D0EF0F3AE413BA46 -:10E5B000AE6E07FD59BB598F76EF91C96FFF71BAE7 -:10E5C000A36B5DCDD3B5DE3E3ACEEEA9DF748BE012 -:10E5D00013122985FD14C389767D19739715003CA4 -:10E5E000DA75366F4543018B577DB7F54636B1F581 -:10E5F00056932E91AFE5EFB4DE7E90EEBCFAF54671 -:10E60000B25254FBA8EE722D88ED84BFDFE425BE24 -:10E61000A7AD18D7F549E0974B57B07E533ADBCFFB -:10E62000287F5DBCE3755817E9819500472EF115E9 -:10E63000031F7962B672382B64E5761CD9C4EC6688 -:10E64000B0EF81DEEB9CE49935717E87F5E9EC3C17 -:10E650001B5DFF8FC03897DEFAC751A04F5DCE8596 -:10E66000212CDEF919C607ADED2CAE6CF5C630DEF7 -:10E67000AE77F891FF845CAFF732BDA39DD79FD3EF -:10E68000D9F98B7A470CC739E062EB50F8DB372EAB -:10E69000B5A09F74A32364667E852001BD3471A458 -:10E6A0008EC5C5B89D750BF73F9A4A5E26100F239D -:10E6B0006358DED7EB252F2BA9B4FCDB91E3BC78A4 -:10E6C000DEAEE4A9967C98F7183DAFEF138479FF8E -:10E6D000CE5786F58B5D3A0FACEB89252C7F915494 -:10E6E00027A1BFE4F5920F1CB3E3E0F71393C74AE9 -:10E6F000F96432DDE4C4E7DB7D6F8CD9638DE3AF71 -:10E700004F5AA54A66EF7A92A70E66FE10D4C3252B -:10E710006A7C2C7619F0BB6BD3CAF6039E6FB89E49 -:10E72000D1E3DC6E6308E4DF397E7E458BBF63E9AD -:10E73000DCCF7A77A12A3EEF308473403F9E97D496 -:10E74000FD16B4E8303E3EBF452221FABD733B5F63 -:10E75000C80139FED1D32FE4CC8C8347DB4F3CDF9B -:10E760004857FB01B57EDDDEFCB9A2DDE5F524608E -:10E77000EAD3D5FE72F5DFD09F3BB39DFB837DBE10 -:10E78000BE0ED807F1F6DAF1FECEF943DA27A1BFC3 -:10E7900043F8334F1D7B0A22279DF433B7E7C9F1B5 -:10E7A000F98AE2399AD36D0AD08D4EC5DCC2CABD52 -:10E7B000D1ABB7F5F8643A8343D0ED544B9F64C0B6 -:10E7C000A3A1CEAA10768EAC10ECF4CDC4E285F5F0 -:10E7D00064C87059417E8973F85F98D9D361A14F9D -:10E7E0006AAF65671462BFFB653FE6C57D21B7E28E -:10E7F00039C2FB750D986FFD15FF5E96CDBF672E74 -:10E80000EE4FC2987F4D5AD4F84D6B62FA2356658D -:10E81000403D25F07CEDCCFB709FDA037DD603DF15 -:10E82000648C64EFAE71E571BF4614E304E691C4F5 -:10E8300006FBF9A651418447D0A79E352752BB84D9 -:10E840007632E4B524A4603C34C89FC49A423AE3CB -:10E8500003097C5F4B34F1002AB682D04EC00962B6 -:10E860000CF2631EB5875B0B4A309E8AF6278C0B31 -:10E87000EF671629E84F87768661DFCE6F9D7CC9EA -:10E88000F30C278AF7D5961EE30F13E1BC0E6D9F9C -:10E890004DF520D87FC4AB579DD7D944ED66D88FAE -:10E8A00089F8AE4E0E17BB701FD21105FF88A1D498 -:10E8B000E401BD9AA00B1702DDB4F15EDA2E8FE5FC -:10E8C0001964D941AF88F338754BC7FA21DFBDD33E -:10E8D000CE38C8F647750F94E1FBB1EDCC7F5EDF13 -:10E8E00062C4F384F5FB248C57D5F90D2113FA315A -:10E8F0003C8D40AF20B5C360DFD86667F9516D37F6 -:10E90000D9BC4112EFBF8E6E7910FDD7568CD3FD66 -:10E91000B3F1CBCB89140143E3E253C926A647B830 -:10E920007F3B8DF393A0BF58CF22DE9958E4CF03ED -:10E930008BFBD7EB66FFC6E2FC2E7921D73E0C7924 -:10E940001FBDE7851CBD05F2464C60CDF37A008BF8 -:10E95000EACDCEF375660FC6B53AEBE15E04D33E61 -:10E9600089F7FFC12DE3FA62FE283F5F77DD5AC8C1 -:10E97000637ED44C54DF8B874FD18CAFA7E35B3DD4 -:10E98000A2FD3D378F5330BECBCB2FFDD847E17F63 -:10E9900054AF1E0F59509C0734757DAF3233E1E1FF -:10E9A000B563BAF437D5E7CB5DCE2E3DFED0DB1391 -:10E9B0005B877A607D7D8AF9B8421FD73B589E8875 -:10E9C000566EAD7149C2FE1D0F2A76D5B42ABC47DA -:10E9D000A033BEDB3EC907F72988F86EFD323FE65B -:10E9E000E582FE77A1FEBF70E61001FBF21CDAFFA4 -:10E9F000F55714E60FA2768444F9D0D45E867E4F94 -:10EA0000483705BD29E8BF80EB25B0D581BFEB377E -:10EA1000DDF1B40EEC6597EF491C97EF03B5F08676 -:10EA20005DCC5EAF2F2CDF00F2806C9708E8ED35EF -:10EA3000859FA09D51B77FDC88F8BCF2F9FB9E60F2 -:10EA400079C93BF43DCE3FECD2A17CABDBFF1CFA95 -:10EA500033CF85D871966A25B47A34F855AA65B053 -:10EA6000B44849A86A3AEAFF69741EE03704BD0356 -:10EA700076CA8E2941C873AFA7FF01CA36FAE7A24A -:10EA8000BDBF719AC90AF19AFAC2998B703DD82C10 -:10EA90003E98BF16CECEF8F00316F437AED9A7AF26 -:10EAA00004BBA994DA49BFA2F066A74CA8F452B9F6 -:10EAB00094A9DB53FC032BC4D57BD6C35333981ED8 -:10EAC0006E96FCC15B4B300F92C4E7E9E4EE63F64F -:10EAD000D8AB2E66BF89F7AF42E223C5E79860C77F -:10EAE00058E0B997946802D8C5F5C4F731EC73893A -:10EAF000DFEA8171E02606B0B31CCB3DE8CF3539A3 -:10EB0000A23F1E8A769382FB0CB18FB8B49FF9BFE7 -:10EB100046B9036F021D4B75D1C76F05BCFD989DAB -:10EB2000F3250A93373953ACC3C05F6576441FAFF2 -:10EB3000F4607E0DFA1F92AF6B463ABCE42036C0FB -:10EB4000CFD8609522C5E9192137C6769EA771A056 -:10EB50009FB49C8B977E945A674CC8A2CD5FA776D2 -:10EB6000D905C7FE31558197C25E904D01DCCF5467 -:10EB70004CA3FB43E0CB55B1A332F8E51D1D682F34 -:10EB8000D68625FC4E6DE12F31FF6D21CFB3EACC47 -:10EB90007752A298FF75C995C0F56333E34BD281D4 -:10EBA000FB5FB28BE19FEA4DCC0BEBB2DB1BB19D5F -:10EBB00018CFC0E309B5DC5F431185F57F7589780F -:10EBC000C20AEEAF12796CECBB44F194C6FB17D6C7 -:10EBD0004DA29A04E1F22401BCBF30FB65376D7F82 -:10EBE000AA5A66FEEC9684101C0E5D2775F8C0EFDD -:10EBF000182CEEF91C4CBA5BE279B2B1F1E8EFDF08 -:10EC0000DF5B9E2CCB8BDD306220E69597ECFB78AA -:10EC10003CF007A924B81EA9BCB8AA3CD92C375B84 -:10EC200047FFCFE4C97A25DF36FA1CECB6ABF364B4 -:10EC3000BD8C5E227EA9CD8FBDE48E282C9F2DBA7F -:10EC4000E569D0BBFB8C98273771DFAB27C17F39D3 -:10EC5000D144C218CFD5D80FAFA54E29053A5DBE15 -:10EC60007866CB4A02F9D5CF7B59DE9DDA1EE8CD16 -:10EC7000FEC79846DC3EB1D2FDEFB5FF85BCAEE7DE -:10EC8000FBA9F352EC910298DF419DADA77331B718 -:10EC900089EFF796E7D1DE739E8738775519CD5304 -:10ECA000C5A7EEE91CEFBBC5BB66820FBA87789794 -:10ECB000C2F3B71489890E926D50C5BB147B416FA6 -:10ECC000F1AE08D63FD71FEB1FEA16EF627905CDEC -:10ECD00007D33D60DFD73863CF3CE381F10C384E7A -:10ECE000F3FE8410E4B93773FCD75C7DBCEB41774D -:10ECF0000FF1AEADDC7EFBA0508E18285EB7120679 -:10ED00007FB05DC4BD64DCC7C61ECE16F063FDE5F2 -:10ED10008707A1BF68968867BDC4FC68B378DCEA42 -:10ED200083C90598E7D51B9E67B5A8E3020F039E2C -:10ED30009DE8E7437FFC7DFF3109FD5373C18FDF01 -:10ED4000A7EB1C04E1FE3C4F0B3BDFEED921853CD9 -:10ED50002CAE6292D136B4C9F07E2115A31B41F4CA -:10ED60000629D75C435F4B146BB4DED34CCBD4E89D -:10ED700057562B41176DB7F56402FACF1E72781003 -:10ED8000DE879A597C39B8560AF563E3E2BD61C162 -:10ED900066D907E3EC7633BFD32B6EA6FF3C9AFB14 -:10EDA000089AF53C4ECCBFD748E4083C65893D1F26 -:10EDB000B229953DD90F62BC667D83A90CF09DCD2B -:10EDC000EE27F9DCE09B86FEE59402BC87A839B10A -:10EDD000A1A592D5E39AFDDC1CF363FD750A3348C7 -:10EDE000892705E07DCACDEC1B2D9EE7B4AACBDABE -:10EDF000F88EF6DCD52C12E8EFEED3FD5CD2536E24 -:10EE0000A6FF3E5F93C7E9E2C57849B3DEF3461E2D -:10EE1000F0FB6A76CF506316C39B9CCD9EF9F60A31 -:10EE2000BC0F8ED8B91D4718FCF9D73924580FCD1F -:10EE300076C6B7FF2ADC5A785F771730FCDAD97AC2 -:10EE40006D5E2D8518BE18DC57EB1739FF6F968B5A -:10EE50001F48DE672279D80FE542F0613DAEBB5313 -:10EE60002494C9F2266D283767F27DEE675CCF6D7A -:10EE7000ACCE4F8238E8ACB3ABF0BEA0B153AC0817 -:10EE80007FDD4B66DCC7D52E8BE6003F6BF108D0EB -:10EE90002A429ED2FA990EC2EE996951C7F5B4F191 -:10EEA000DA608A5F8678505D79B400E2464FC81F09 -:10EEB000EC7995C935D4AB75CB62CF809F796A4A1E -:10EEC000C09C41F173E181B7C74B1EEC8EF2EDF2AD -:10EED000C1FE78BE7066B3FABC1659AB8E1B929613 -:10EEE00014762EAD4DFD1ECE27A9FA758B2332BBAD -:10EEF000669D213000ECCE1BAE67791217E7CB047C -:10EF0000E879D14C787C5EC8596F41BC1E28E07608 -:10EF10006F77BAD27680679E172ADAD7025D293DCD -:10EF20006B385D2F3E774D01D0F5C29E6B0A80AEE7 -:10EF3000EBF4AD3E58179F390303011FA7C7F9D162 -:10EF40002E1479B057CB6FA332FE67F5F078819716 -:10EF5000EFA887E12FDE5FF2D23F58BE6AB09D9DD9 -:10EF60004FEDF2D39DC37BB62E5F912590C3BD8D2F -:10EF70007792EF935C261204FBABB43C8AFD4AFF08 -:10EF80002613B00385FDAB857F3AC7DF820CDF4BCC -:10EF90002EC023F7EB56F3B14DA14F999DBD5D42B5 -:10EFA000BFADC9134C1A8DFBAA39C37528577E858E -:10EFB000E72048BB6483FDC9FCED8D587F69DF2CD9 -:10EFC000AC974D9108ECC36A693D94578D51E73574 -:10EFD000EBF71647E2F7BD148E03B09F4970C40CDF -:10EFE000C09F7560575310EB14E6DFAE7310F4AB9F -:10EFF00094EC53EF1345DC76A39FDDE3B2B15DC221 -:10F00000FB9CD20C81BC2CA0AB267E7B7F866F1D27 -:10F01000AC571147BFCDE97B2083E597E5009E8281 -:10F02000190C9F51BD38AFA73E4F78ECD0ED680763 -:10F03000FD85F8937BCE370BA9E2EB73F979CFB955 -:10F04000FCBC27C8E788463EC7976BE2F2CD223D5D -:10F05000E50DC4E59BC5F78BCF378BA8E41A5BFFA2 -:10F06000E9BAC518D7AEA77CBE7458171FD610FED4 -:10F07000B73EF6019E6BD961447F5A0DCF33ADAFD9 -:10F080003E85FB947A3827C3D623CBC7E6F71CD43A -:10F09000D0FD1FE6DB86D5F9A8BB7B951BFF77FC6F -:10F0A000E4FB843CE0EB51CC4BCCA3A65D62EB4788 -:10F0B00003A776DFABF5778B7DEBD5CAA5E3FFC35E -:10F0C00072E9AD7F935CEA1637E81B4BF2FE1BE258 -:10F0D000061F795AD3C095D822317E1DAFB3FA5896 -:10F0E0005C52C7F216B4F15ACF788C430A3FADE9AF -:10F0F000795D68451EB6C7386CEDC144CC23A8F6CF -:10F1000054A39DAD8D4F2E207BC60309FE428EE396 -:10F1100079AC7F351F806476E603E47DC77C0063AD -:10F12000E677884FBE6CFD343510C727E545D460BF -:10F130002FEA3D5FCB99C9F82E81E78D989420B1D5 -:10F14000C7F5EFAD5F7626CB037B99E7193D9A981B -:10F1500080E7F65D0676FEC025B37CA8332E7F6E71 -:10F16000E608D0038C8E3FD97F0781FCC29FE8C39D -:10F17000788E3E586BF582FE127E2631FE83DCCF00 -:10F1800072B5EBA724F3DFBB7EBE4D6E5C2FBE775E -:10F19000B5F1B5F5140771EB4ABB0E7AEBD79B5C62 -:10F1A000B935D33F2113E5966F08C629AE521E2507 -:10F1B0009450790DFA79AFD103FB05133F2743D65D -:10F1C000BA55FBED598F66A3DEBA6866FB07719EE0 -:10F1D00047CC7F66AFF8FEE7ECBBE34EFF6C98CF01 -:10F1E000E9321F9E07782891E995D84E9617A43DDD -:10F1F000D7A2D527E25C86F8DE7DFF667EF8AEF208 -:10F20000B4497CFF5F94A754BFA27FA5D7386CB7E1 -:10F21000FE419E9FD9E1E3F1293CE720E0AAEF609F -:10F22000F9748F674A2A7FF37D5CFE9FCCF4B501A9 -:10F230001D2EBC653241DCB3A484C9CF3ABF15E3AF -:10F24000067561964753B78CE03E5F9C5FCD4B0FD0 -:10F250006C0139F5D0DB56BC77B46EDFD6967CCC2A -:10F260002F08A05D77E92DF6FE445A601B8C5FBF26 -:10F270002CAA8A4F947EFDE9AACA128417F7E90ED8 -:10F28000A3FA5CD0914CB6FF16CF439DF8A5FB12B4 -:10F29000DAEF4235CBDFAE77F86C659857C0FCDF0C -:10F2A000099E0EF45BD7ED452541309914EA1FCC39 -:10F2B00042BEA9DB5B568CF70884CDC578FFCC3BFA -:10F2C00056DC5F5D782023A463FEF2FD006F624987 -:10F2D000E826B02F73E977C0FF7D61CF4DC5E80FF9 -:10F2E000D4AC3BB1DE3ACF83DE650A35495DEB71C4 -:10F2F0009D9EE947A1D77682318B79153C2FB07D51 -:10F30000129963ED2A5B1DEA7CC90519E376023C7C -:10F310003B33591E8988A3E799E8EE33BF3B1FE6CC -:10F32000F138FA249EFF4082A6AEBC87FC6F8FA303 -:10F330000BF84459C4D113AE30FB36DF6640BE48EB -:10F340006C61728350BE00FB7A4CAC632C9CC3EAA8 -:10F35000DB161903F84A06F463FE69F4C743215E1D -:10F3600091AA8C8178C596A5C30E9B1CE03FEAB894 -:10F370000E48E369B595C3D6322FDD7F06F59ED2E0 -:10F380005008FC5FFE073DCB535C9D80FABE2DA765 -:10F3900006F3142FBD6D549DBFD13E8364850BFCD5 -:10F3A00044F92DBFC77841E25EA9C7FCD37E60F463 -:10F3B0008F60EDC1EF94D8D2111C097E9487257619 -:10F3C0007723855E72C1FE5F91C1EE98B58F9DE394 -:10F3D0009ED56A2F37A13C9558BC658C03E5A4B235 -:10F3E000FA6619F6674A23C17BD2B2B2D839817E58 -:10F3F0006D3619E8FEEB2F753DC6D112B2985E85C9 -:10F40000BC374057AD31761442FD22FE27F2DDC4F1 -:10F410007EA853BEF2FBC4853ED2DAB1DDEC57AE16 -:10F420008F3AED780D1FF7D64FF0B7E0E75FEB09A5 -:10F43000DA61BF964C78BE4BF075B3C8DFFF92F926 -:10F440007173793ECDA9357F1FC2EE0F14F1931071 -:10F45000CB83D247576522BEA2D70761DE7BED7210 -:10F460005D11FABFEA709CD5ECBEB3DC963E2B462C -:10F4700096C0D3460005A70E2CCC857519A47CD068 -:10F48000AF073E3897C9F29694D5094837E531BCA5 -:10F49000D99928F634A49BF204A3CF69CEE7227E43 -:10F4A0002BFC94273303A3B39C71E7B2965AD8B9C7 -:10F4B0002C7EDE3771E9DBBBE1BCD316EE2F3EFCC0 -:10F4C000D220FCDD85CF572B12F88D3EB757E5C211 -:10F4D0007E6F1CA76BA2D2416CD678FE3C8CF9B231 -:10F4E000F90759DE9FC2EF4F52563BB6023EBDA907 -:10F4F00001CC0BBEAE39823F59F092ED34C6E5A87F -:10F500005D84E79FCFED97845DA4D28762BFA6DDBF -:10F51000874DCFFAEFB5936667A9F71557BDBF22A0 -:10F52000EA7D66677BB16FD4EE2334FD7BB37F88C1 -:10F530002FA8CA8BB99FE7450BFD9EC165A3C8974D -:10F54000E93CBF4C42663807910CB9AF4CAF63DE63 -:10F55000D07AC9E2053B499B2FD499C7431AFAB325 -:10F560003C9286A1EC5E8A866BE029F289CC904FB2 -:10F57000129FB79AC8F281CC904F42DF37F57ADEFE -:10F58000D9D308DF6FFB914D9C77667EF64AC2E3C4 -:10F590000CDBF03C74ECB62C3C5F33B692F9EF52C6 -:10F5A000FC0619F8F2F9AF743E90BB31BA6EC1BED9 -:10F5B0004AE9EB7383BD65A6F590A7D279DEB98AD7 -:10F5C000F478DE59E43389F86E46FF7512E89FCE71 -:10F5D0003C93FAAE73D0F0DDB6451EF40F77E63DEE -:10F5E0007D9FE03CCB859C31A9E997E463ED92A631 -:10F5F00019D0CE4893033B318EB7B1C38CFE8AAC91 -:10F600007CE4ABA69121BC3F37A5A815FDAF2B53D9 -:10F610007DBBB24674F18F808FAC67F3BF0CE7BC43 -:10F62000A4AEEF5E9EFFB71CB0A7CADB8D8C0F3572 -:10F63000706CECBC6F857E873E0F6531FA7B35F6CA -:10F64000AD781E12FCCEE5B0F87E6FF314FCF86DB9 -:10F6500076BB96BF82E59C3EEF99432C5F49CD5F18 -:10F660008797570E3F4D65C991E57E7C5E364B61AD -:10F670001DE4159963334002FE38BBFE7B700FC753 -:10F68000E5C4580EDCE3F178CE6DB7C23D1D979D01 -:10F69000B1F7A0FC4CF643ACDC2FB605EEF568CF15 -:10F6A0004E6465F85606216F6D926E0D5AF11EADCF -:10F6B000551DA09F4A34F9299AFB07208F12EF4B62 -:10F6C000B0327AA6F33C5652C1ED77882CD17293B2 -:10F6D000BBD80BF90756E2D9DB01F55946764F0145 -:10F6E0006179534DFDF2589E03E77792C5FDCF2413 -:10F6F0001A04FE6DCAB363FF4E79BDD7C8E34EEC62 -:10F70000FB279E63E7CB447E2E21B66CB07BAC1EFC -:10F71000A22A8BFB3B8862CB86F3FA4DC2AFC7CBE4 -:10F72000EF5A027FCF8AB38B4E8CBBBF087FFFE3BB -:10F73000F907FBC27C6F34A8EF4F16CF65394CFE3A -:10F740005EE6F70CB659024A362D9F4C98311EAE34 -:10F750006E9D965A66B0A39DB65307F2C8C9F9C20A -:10F760003E95C167AFF04BF0BB1BE29E3F67404147 -:10F770007F0009B4E9407F3A4FFB310FB0C614CB8C -:10F7800051F2C1AB1FB065431CB0EAFDFB300E98CF -:10F7900071E23DC8DB38A16F1D9B04FA228FDF03A5 -:10F7A00041377E415A3E9A998BFBBECE7B41FB4945 -:10F7B000281F264E65E7562790B082FE171B3B4751 -:10F7C00035BE24CFDB44BF3791E77D8C3FE94F0244 -:10F7D0003FC0F83BA20A8BB7C494F83C0BF1242E2F -:10F7E000BD277E1DDCE4892B13B84F585DBEC5AB29 -:10F7F0002EDF3AF2CBFEF1E564E21B04F37C518A82 -:10F80000E239E4E0286263F362F9843FE3FBB64146 -:10F810002E62CA857C478714847DC1A01732308E42 -:10F82000F2C24882E5B41DA66DA6F8F93F26B338AA -:10F830002DF7738BDF0D823AD0ABCFBF9586F84A98 -:10F84000B3CA284FC1030EFC569A69B2807CD771A7 -:10F85000392FCE6D8F4B32E17DAF4D8BD8EF0D68D8 -:10F86000EFBB6CD2DB0E011D9B3EA273A0DFD99EC5 -:10F870006888C849402F420C8E2E792CF807C6BBE9 -:10F880001EF87E04FB5D27CAE57DE3EF1B6F723235 -:10F89000589B7EA4F0F81CFB7D89C2CEDF9BA0CBD9 -:10F8A0008EB6079B92E03A61F1B16C314FA2F8A09D -:10F8B000BD9B88323B9F95C6CBE29E4D42CA14BC8D -:10F8C000674712ED1AB1FC246F27B5BFFA57E08FD6 -:10F8D000BE49743EF4D994CDE4C453F289F5C827E7 -:10F8E000D68007F8C49BD0F379A1BA6CB66EC62552 -:10F8F0008D7441DE4093DBEB02BB4AE0A7F33D1F72 -:10F9000057D48BEF79537B1EB7898F1BE6E78DB5F4 -:10F91000F53FCA66765BE7F87A3AAEF51BBEEB5464 -:10F920007FB7ABBEB77EECBD688F3F07550AEB8C47 -:10F93000E16D02CF732585EAFC1432D26B62F25E70 -:10F940009D8F72A3B4CC0DEBF326536D7B94F67FA1 -:10F9500095F3C98D72E0338837BC3AA3E008ACCF89 -:10F960004AB8D09E8E733389AC0266B95C16F889AA -:10F97000BD0FCA8B75208FEA7481FE29B47C51DFDC -:10F98000DA77511EAEAF27B34774874FF061279CDB -:10F9900094FF80EE82FFB4700B3E20DF0B6342DFEA -:10F9A0006612C1A78BB03C6AAABF58BEB427BB6B16 -:10F9B0005E9439C79B1AFA827E7FB53188F2E7469A -:10F9C000FBE39837B63337B00BD6FDB4A11FE33D48 -:10F9D00039C45585F6168577F7FF24BC745DB9E107 -:10F9E000BDB00385BDD72D7FF823832A7F58C0A7DC -:10F9F0005DC7028E7AC2EE3F1ADBBE15EDBBFAA9D7 -:10FA0000562F9CF3A887BCD8128C7F619EF101BE53 -:10FA10002F0B4A2CDFB79BBDD87B9E31BB0FA0D6E6 -:10FA2000C6EEC111F729DD9B2FEEC9617053F9C5F0 -:10FA3000EFC9C1725B9507F77F9D76E31C6687DE91 -:10FA4000506069867B07BBDF97C3FC7BE405A38717 -:10FA5000DB89A8BFDB12D9772E9A595E7B9C1C27C5 -:10FA6000525AD73D5EEBF4CC1EBC949DC7E278B2EF -:10FA7000B714E8B111E256BAEE7EC8CF9C818F81EF -:10FA80004FE614F972E0273D6619989F91F2D5A6CA -:10FA90000E02E9710DDBE17ECB9B48C39B721FE434 -:10FAA000AB2F807FA60DFA98DD7BD9C55757185F1D -:10FAB0000551087EDB3A7D2D3520E58CC03CEF7783 -:10FAC000EA4A20CE6844FC8BFC43EDFA8D83E7B410 -:10FAD0009EC1E3807B75293CE61C677778AE86BFC4 -:10FAE000E3F9289D303EEE8DCF21CF3F7158179F0F -:10FAF0002793800BE0EFE4F755DE165D9F1EE0D6FE -:10FB00005991EEB74F67F198FA0466A7425CC69D1B -:10FB100006FE27F6FDDB5733FEB8DD6C447E99D434 -:10FB20005E8BF11752C1E2295EFA3F80671AF18DB0 -:10FB3000839FE698629B84E736A74E54C75BA699DD -:10FB40006EC4F8CE6D84F9D36E9FAA57FDEEA0C0A7 -:10FB5000C334B2F663C8E798A6F9BD412D5EB4F18F -:10FB60001A818FA691DFBCEEAFCD4974609CD8435B -:10FB7000FA7FC7B84E790ECB9FBBAAB8CE117D0CC9 -:10FB8000CFEBBFE29CB769115D17FDFFB308EFE94A -:10FB90001E97367FFB63B4FCD38D03B1FC4ADA5D5C -:10FBA0004B4E40FD96022C57C81FCFC07BD34BA7AE -:10FBB0004F80FBCD8F98D9382E4BA00D7EAFC2352C -:10FBC000247F186CC92A0C316C77F3D0DAE19007E6 -:10FBD000536161E5E3C5FF6B1896F37979D88B0320 -:10FBE000A17C44FA78464F71A1418552047E97AAC0 -:10FBF0002285B59F386C6706F8092ACA597990B7EB -:10FC00006C751FA8973F99D1933E6EE0F6B1B0B7DF -:10FC1000FC7CBDBFE07BBF19CE87F9AD9217CE0546 -:10FC2000F847BECFEEC732B13C02BFAF5881FB13DD -:10FC3000CB7DCCBF37D6DAE806F9F7BD80A104FC4E -:10FC4000B8366B5E33FCBE40F2C8B21140EFB1D49F -:10FC50000C03FD47D7D5125C57D77C9C93847688DC -:10FC60007A5D09BE9D24D653857ADD5079F04346EE -:10FC700047F57AA0E32E87F7D3AE55EBA54EF9AE44 -:10FC800059B75A7EEC55EF13B51CECD44FABC2C834 -:10FC90009759849DFFD90C7CCAD66F2BC061903BCD -:10FCA0003CF03E57F20EC4C48A5EEC07011F983D3B -:10FCB000645877B8E04F11F62283C0664B83EFB2E9 -:10FCC0007ADACF073F2226E0A2DF0F217E56317875 -:10FCD000364B0DFC7729985D2EF6BD7562BEFBD4C0 -:10FCE000F32DB5B073EC2E42E50EFAEE8B077E13C2 -:10FCF000DCF55CCF4E35F91F36D239DC669F857452 -:10FD0000BE83049F03FBA6C312F825D05B27070F11 -:10FD10004625F85D091FC693291D7F9513672F0897 -:10FD2000B8B4F8A8EB45AE6AE1D6E2A18B3E1D68F7 -:10FD30009FB9F9EFCF75CE4B339F267EFF7CACD8B1 -:10FD4000A8CA133D5EC5F260055CC72552887A5289 -:10FD5000B2601CB5D3EFA4956FBD9C6713FA59C070 -:10FD6000793F3F4FF585CCE4DEFDBA08C2995BD9F7 -:10FD700061063C7E92C3FC2E02FEA691416C679008 -:10FD8000A51EE3C49FE4C8C25FA6A2B7B8D74CC4FF -:10FD9000B9045E1D064F16E67B6AF039D364EC3970 -:10FDA000AEAA8DBFF6D24EA2F8CB4CE98E67112FCA -:10FDB000BB45EB87BB89F9A76EE17EB8B1950CFF17 -:10FDC000294B1371DF965272422183BBEE5D16F40C -:10FDD00078C711F82A07E316D111E027787DC44FC0 -:10FDE000314E24EE37D4E2C792DB337E7A5B0FBD0F -:10FDF000C1FFAEC56FCDA5E35C943AF01EB4BFBBA6 -:10FE00006C7CDC401EAC17BB2DAF0CFC0B54AE7EE3 -:10FE1000FD356C36A10AE8E70C38729DB03EFCE374 -:10FE200020F73AA532A067FE7982FEE1C57C9F38B3 -:10FE30008EEBF74F76B1F3F315BE014F8E01FBF356 -:10FE4000989E843C90C7CDF0F3C9261DEAF579AFA2 -:10FE50000D77817DFE01E7B7FEEB65D5EFD30D0889 -:10FE60005954F76C0CDA91A22A0F0E67A8DA0FDD4D -:10FE700097AFAA2F8E0C54D50F3F364C551ED1315B -:10FE80005AD5FE9A93E5AAF2A8E80455FB6BCF4E2B -:10FE90005695AF8BDDA9BE2724E8EB284C83FBF9F0 -:10FEA000193E6EB83253D5FE7CD2F863B0EE66AF21 -:10FEB0006579DB6564A1AAFF425D0DE64393566652 -:10FEC000C734D0FF213D75772B982746EDF754C0F6 -:10FED000DB7AB59D53DDFED82A90B5DDEEA7D0D8EC -:10FEE000335AFBA5BFA30AAE7726B7E6F2BC936BE5 -:10FEF000C835FCF74AB474C5F3FE9FBCA9C37DC4E2 -:10FF0000E2D7987DBF7837CB872B20FD92F11CD8A4 -:10FF1000311D094970EF41C3BA3152971DA3C58BFA -:10FF2000D1A5A6B3D9A3A67342A19ACE895E359D69 -:10FF30009347AAE96CF7A9E99C5AA9A6B3D3AFA63F -:10FF400073FA34359DDD01359D33ABD574CE6E50DB -:10FF5000D33977A99AAE79C105AA7A2137FBB42C97 -:10FF600056BD6F92C2A5545292D9FE6ABCEFA15FF2 -:10FF7000EB0F7BE40F41FF20FD1F5BCF0D985F3F30 -:10FF800097D21FF2EBFF42D61E855094960FEAF6E9 -:10FF90003D8671B5EFCA078F6AE97F95F629D58747 -:10FFA0004F803CA176CC7A900FD3FAF37D87BF6760 -:10FFB0003B46C8AD78BB217E5FDD9B3CEBA627F9B5 -:10FFC0003EBB573DA9D967BF05D94D688FAF45BF27 -:10FFD000D674CED79FC2AB51E0577D16F5FF5B14A8 -:10FFE000909114AEB7006EFA9DB72C83D00F7217A4 -:10FFF00089E8F19E6BC8DCD4E17D9998875945ED7D -:020000022000DC -:100000007278CEE2F6C11CEE27F9CA183890CBFC04 -:1000100023B969F0DDAC0E76EEEB78EA55DD0BF135 -:100020007BF827F8DD73FD87619C0A9367C913F499 -:10003000D561EE7F221359FE2751FC83E3EF61EC7B -:100040001A87C54D5F940201DC67BB4D5ED8670F10 -:10005000CA242637E83757281FE25427347A652008 -:10006000E791DD19E1C576C4572805E304DFF1BB4C -:100070007FCAF59D047E10EDBF6DBE06437811F377 -:1000800027B0DF4B7993D3E5A9DB8D11D897093ED3 -:100090003A9930E3A8D383FEF033C86F77DCB40A13 -:1000A000CAD2E154CF620ADFE5AA28EEEF29FECFDB -:1000B00001DE6A4C14FF748A17B303FD938119FCA7 -:1000C000A9DC49E91FDCD3792401CF58897DFF5D84 -:1000D0004BE05318E7B0DC91E3057C281D786E8F68 -:1000E00058D1B821170D3DFB03051ECA13B2EFC648 -:1000F0007B788D462FEC2FCA2546D7D3A9F7CC8025 -:10010000D8E21CD99F16D1A9E0963C00B7AD2AD7FA -:100110004DF9F1FF00AA42FBD90080000000000069 -:100120001F8B080000000000000BE57D0B7854D504 -:10013000B5F03E7366CE4C924932492024848499AE -:10014000843C20214C82202AE2F0088D1A30BC1415 -:1001500030E2E401843C2080DEC6963603E1A5420D -:100160001B2C2A2ACA8040D102068B801AEC206AF6 -:10017000F16A356DB5A55AB90950E54D0C3E68EBED -:10018000ADFF5A6BEF9D9973480AF6DEFB7DFDBE0D -:100190003FDEDECD3EFBBDD6DA6BAFD7DE73DEE2EF -:1001A000CD8C561963B6DE8CDD00A9D999531CC9D4 -:1001B000D8B7F8774B3065CCC718546954E09FBD69 -:1001C00020F723C5BFCDC5F81FE4F7FB62FC0F4144 -:1001D000DE6ABAF4C114C8770C36B9B740D1C6701C -:1001E000E83A9FB1F7B11EF4FFB405F2B1F47D35E2 -:1001F0007E4F08E7ED131E33F91BA17DF198971789 -:10020000B2EB187B76BEDDADC258A5CCA931985FA4 -:1002100039F3682C8DB1BF8CFEFBC1362763FD9D81 -:10022000DEBECE618CDD1B674AF980E6E1CD9E041F -:10023000F36623E3184BBC72FEC67530B6C6C4869F -:100240003336D9C197301BD705EDA6308F05C79936 -:10025000C6BC161CF77717340F8B82D404E530DF49 -:10026000BB988FBECF607E4AEF6601AA7F0F6BA35B -:10027000FC6F237293EB617E931ECF4C67D0E662D6 -:1002800069DB702CFF87D5EB76C2B83536EFBDBD84 -:10029000E0FBF964EF677D10EEEB39DCAF36DF4948 -:1002A0000A87DFC5FEC52370DDE36CCEEBF2521981 -:1002B0007BDDC42A9BED5036AE37CD9F991DE99367 -:1002C0000777D7CF32C6A05D6B67542E1B82798F1C -:1002D0003D11D6FF3D81C2EF79AA8B709D05AA9D85 -:1002E000F502F8B73A55BF15C62C1C5DDA17D705CD -:1002F0007F913EC0D3448FCA10CFBF5E0A5FA0DE9D -:10030000AFF3543FD2C4C40DE34F63FBA2D1539665 -:1003100047C3FAC77FD3765D00D2C27E96E36D599C -:100320007C8C6FE17F5FB28DE36220BD2D618F9980 -:10033000C1FC6F1BA02F2FCA81BC2D989FC8CCC1B8 -:100340007218F710C201E8A7FECF79A3DE0869C7CB -:1003500058935A0CEB2E7146F6FA3402B283D8A0A9 -:100360006F71DE6A49B4D7DE337CBF6E708F7A035B -:1003700068F276C553EE24BA706A48FF6566E6698E -:10038000EEA6DDAE7445D00F60379EB13BC45C3B3A -:100390008B2E691761BD4F3ABDF3B19F4513FE32F5 -:1003A0000BD7C7CCEC3743016EF3DF03B841F9F14B -:1003B00006807C2663271B6CCC6365ECD30607E5BF -:1003C0004F3524507AA6C149E9B9862C2ABFD0E01E -:1003D000A6FC2167F1F7B1DFB2D59F9BBD398CAD8B -:1003E0000A9378E4F3582CE87855F2F03FBA61BCF0 -:1003F00055EF5A285FD9DC341EC1B138F9F8B2087C -:10040000F8BEF839C58DDFAB5B3C9A1DE633FB0DBA -:10041000EF4A249FB9EFB64D04F0B1DACB0AF3E20C -:10042000161A50BC02C71BF6E1C97884DF670D239A -:10043000683EA71B3C341F4F4BFB5B71D0FE6C43E7 -:1004400021E53F72163F8CF53DEC730DEB4FD8D98B -:100450006E4E82F2028FE2C1FD3DCAC3FC7EC0DF58 -:10046000068BD78B74B321D1E6C6FD3E7AF0E4A7A4 -:10047000EF83713FE9EF7D14E97A5A6C79411C7C76 -:100480009F38A2D48CF5EEFA8631CC4BFABEFABE78 -:10049000E6F0A8157839FF9A42703ABF2FFB8E9B81 -:1004A000A0BFD78EA84C8579755E36D1BC3A8F86B1 -:1004B000FB9912ACB7E82595E87AD160CDCF5C986E -:1004C000CFEEC372709DD019AC3F4B71B27AA0BF12 -:1004D000B3BBBE9F807890E39F8D6DFEEA23E47BE3 -:1004E0009F70BEC758F3A74F225FEC97E07E08725B -:1004F000172C6C3AED5356173119E86BBEC6BC3C4D -:10050000EFCDC6FCD970766F31E487EF4E1A83FBCE -:1005100008C7736606F95AC6EEC7537FE80C8EB754 -:10052000A379F6474F42FEBCDFE4B34443CA9A2F97 -:10053000BC827C79ABDDBD8DE13CCDE138CF872D30 -:100540007C5EBE6DE1EE6D4EECCF4F7C00CA352C6B -:10055000AF79F189BEB88E5701062320FFEABA08A9 -:10056000E277AF5ADCC7EAB1DDD3BCBF9FFFE481BD -:10057000E307305D5B9BFF00A4BF73C612BC2B1E5C -:10058000993708DB6727017A803FFE62BF1208CBEC -:10059000656CF0FA43CB1261BC211BDB4D7D21CD94 -:1005A000DBAA34629A9D5C784485FE8F3A9D348F35 -:1005B000A13B5D6A126ED7BEFE8F6E4923C02988AB -:1005C000BF41027F39EB3F1FD317D25D7D9B17C51B -:1005D00040F920A5F9CC5217D2F91FF2BD04BF266D -:1005E000EAE7A59629BFBF9BE13A7C89369C77A9AB -:1005F000E6A6F309966B81FCF9BD699B1F8235EE77 -:1006000033F936D3F95566736F43BC17FB9E407CB4 -:10061000D7427D1FE46BF37C51374279ED2703DC31 -:1006200040512CF999EF15223CE6EF7D747C5FA8D0 -:10063000777E24730309B0CA972E8DC7762C993123 -:100640006409E7F736C6CF84760FE78C1986F45530 -:10065000AC36D3386C011FE77171EEB136004EBC79 -:100660002055A8F7307CC6EFB12D31879258103F46 -:100670000B5A96BACCD0FE3AAFCDADE2BE71F912AC -:10068000EBECC17314CEBFBFE17E4BD444BF8E29C7 -:1006900029C5DFE1FCD3C47926FB7B5C63BE30E86F -:1006A0002719BE2B783E6BFCDCDE067CA53E3F782E -:1006B0006EC3B8E1AE61D4DE837C38090EE93C98A4 -:1006C00067D2E3563A07AE75FC8B16FB6A05E876EF -:1006D0004138E76363C4F93B3DAEF1601BACF760A2 -:1006E000B837DE05F5668B739F99DD4EE4EF5BC38B -:1006F0003D7D70FC1A5B470AAE01CED524CCCF57A6 -:10070000BDFDE3D3E85CD5C933579B476BB8C785BC -:10071000EDAFB5BE91DF2EFED2C4F2800E163F6A59 -:10072000257ED1887C19D6D51839DC867C83BD61BD -:10073000AA790BCED99B79CBAEFE1647E6135F693B -:1007400064AC5B78BD06FBDF0BFC2600E78417F882 -:10075000C0A8CB1D2AA7F7D6C3D1D7219F659E4835 -:10076000A09F5B2E9B9837E41C34F603F8F2201C04 -:1007700047B308E60D39573D2C46C37DCBECB1FF9E -:10078000DABAC5FC470AFC8DEC3C1AC1EC080FF83C -:100790006EEF795D07C5BA7E85EB82747B7AF16472 -:1007A00084FFCD5F38CCB8BE9BCD935250AE8179DB -:1007B0004FC7798FFAC2A49FF737E1BAFCB5CEFFD5 -:1007C0007E85F94CB81F3FD7FCB81F5BF078043822 -:1007D000B6CCCBF1E3BEDFA7F1BC2F4A23B9B625D7 -:1007E00092F9908FB44C8AF7FB5CC80F19977B7B0A -:1007F000335E1E26DACF88A7F67DAD0052E4077778 -:10080000878BFEEBDE198CE54B93888F345AFCAB5B -:1008100053B1FF1FA9C4878F0ABEBD3E2670B70A19 -:10082000FDAEFF3C9EE13847592069018E53194EB9 -:100830007CF72693E9DE4976ACE7498C0578EFFB37 -:10084000874AE7C4FA3CC8DB896F4F6F86EFEB2716 -:100850007912C3B19F49F1269A8FCAEAE8BB8BB7D8 -:10086000FBC8C2EBCD14F8FA93C00FEC6BDAF7DEDD -:10087000891166A4DB4DAEB247683F304FA202F348 -:100880007DB2229D21DF9C5975AB8BE8A5E971E211 -:100890005FD3050E647FD8C0361CE566FE3763F66D -:1008A000B630C4E7B4CAB0763859D9D1CA65914ECA -:1008B000683FCDAB06ACC04FD9D4024F975C978A46 -:1008C000E37A68DCDAE681692743E8B9CC0A7C027E -:1008D000FA7F21CCFB04CDEB401E951F00A1E65B07 -:1008E000D84FC72BD277E3BE621571427F0994239C -:1008F0001E5EEBB0919CDA133D3422FC87083A452A -:10090000BC2CE17807798DF28DD307913EB3C9C233 -:10091000E9C6B7278CF05A38D94678EE9C1EBED966 -:100920000AE5F70ABED5383DDCA340BDC697AC7ECC -:10093000938BF424AAE73B1849FDD6683C5FF36229 -:100940003AD1D33ECDFFDC762C7F2D8CE8A1268AD0 -:100950008F5BF34A92A0378F6B058E7BD04A745021 -:1009600013EE8CA6F2FF8C233A1967F3BE82F000D7 -:10097000BAAB4339A2460B64C4007C8F09BA3A066D -:100980006D107FBEBA489A376D79C87B1B93B7202C -:100990003EBD1A2F673F50A9FC98838F7F6C0D1FB7 -:1009A000BFE4A7D5EF32C0DBB1E2F189B3611EC766 -:1009B000EA22486EFC73BD1AD0A250EFE9782C03EE -:1009C000EA5D587262F806987FDBB28F53903E4A18 -:1009D00096D51661BB92AA2513F1DCEC695F96D41B -:1009E000C0E60FD9C7275C9EDFE17ABE75793FC4A8 -:1009F0007DBF20A76D0ECACF17B4D66750FF888D74 -:100A0000F31EC5EF175FFE6C3B97AB3B32F03C9893 -:100A10006FE6F421CFD50582FE56A57A8FD1391124 -:100A20001E9885E747444E2BE7774BAE8DCF9F69E5 -:100A3000D9B64F8171AAC35BE653AAFA73B19FB3CB -:100A40004A204A4923F879713F9D7304A210EE5E53 -:100A50001397E7AA77E8D7857F66985735FE03DABC -:100A60005537AB9E30C435F36B38FF6AA605EBBB38 -:100A70008278827E084FCCFEE7593F04F8573D3715 -:100A8000301FF587EA98033FB989EA413BB94FD453 -:100A90002BF3723D57CE87AFEF9CA0FF7392FEA75A -:100AA0006B529FA7F12FBCDC87C63F3BC99F81F0EB -:100AB000BFA0887ACF59793DA00633CEF3054E4FBB -:100AC0008F597CA670B20B30A2E7EAB8E6E10817AE -:100AD000C987600E3E13D43FBB3B89EA4BBEC58A33 -:100AE00019C376D5BB13B770F94CE8B33851A85F7A -:100AF000F50BDE3FE6711F9E793E498CC7E5692301 -:100B0000FE8CEB4D4E35D17A1F93FC3B52EE737742 -:100B1000C224807FE6064D57FF42A476AF07FA1D38 -:100B2000E8D77F97FD0F4C55483EEB6FC05B5FB534 -:100B3000E39015F7D3B38CF6AB715EEE54AE373E4F -:100B4000FF7C179E548E371003257D38B91C6E41EB -:100B500038FFA90B1FF725015FAD4618A406E1B3C6 -:100B60002FCF9B84FCFF02E6F15C88817C0ECA419A -:100B70001CDE322FE16CA4B3657F9A93D406EDEFAF -:100B800046F810BF77F7417AEC925F2CA08FE4A073 -:100B90003E5A39F4643AEAA97503E128E85ACF9C31 -:100BA0000D7936DC4F7337E6D9CA42F0D0B863E826 -:100BB0001127C0F9DC0EB31BD972A3D9FF1394A778 -:100BC0001B77A8CD3E46E53684EF39FBEBEF61BDE0 -:100BD000391B63F2515E96EDE76EB87F604508DC25 -:100BE000B377E8F130B8599F1F72409F9F8DBC6169 -:100BF000D8776F9717D0E7871ED1E75907600BF0BA -:100C0000A0DA389EF68F701F71029EFAFB55377E70 -:100C1000EA6F9F3C6502CA171B55773A94F75F52FB -:100C20007CFB60C89FDA38DB8D68AE547DF37F08AB -:100C300038ACFC78FC113C0FCFB2E63F4C003CCC0A -:100C40006959A7999DB86E3DDDEE33097A7D9EDB2B -:100C5000D9E6F9F5E557EEEBA5028F2C2B949E8C87 -:100C6000788771EFF4C0846AEA170F3D094766651B -:100C700011103AC0EC86E6751ACA6D571FC7C7E552 -:100C800041BBC789F0281DC1CB6EAC1FCB4E0C8574 -:100C90007FACF9ED789C77E9C30AC90DA5BFCC7C80 -:100CA00003CF81F63D336EA3F4CE425ABFB4E7CDF5 -:100CB0006D51029190778C701E688376B3FD8A1B0C -:100CC000E75DB6DC1AE467F0BF8A358679AC0F2998 -:100CD00087F9CF3D70E8AF0AF45FB951DF6E1EF0BF -:100CE00059E45F555BBFB5867E977AE38D2D9B55A2 -:100CF0005CF76C397FDF2886EBBA915765BD847C41 -:100D0000731233706E4CEB5DBC2315DBADE7ED80E9 -:100D10005D96E27A6BED9A13D75B6B63810898C797 -:100D20009148CDE380EF973644921D6D8E15E4C94E -:100D30007C4A59583EB6734763BB4FDFE7F6B4DAD7 -:100D4000388EEFDA4D0AE951B568FCC4FCB33C3F7C -:100D50008F05681D48279ED0F5F9F579D6C4F5AF03 -:100D60001A73E010C2A38AB571FD09F0E891F0038F -:100D700078D5C03A8FC6A2BC6568CFDC5E1C77818F -:100D80009DCB4F0B0E7C6B0D2D977AA0D453A57D78 -:100D900077534671388EB342F13C618379AE10F2DD -:100DA000B56F5D18D1EFCCCDFCBC01393603E1B293 -:100DB0007E5DA21BE58C99209787E1BE99174EF5C1 -:100DC00040DE25BB4C07C8D55B5C58BF3980E7C601 -:100DD000FA475D244783FC4B70E9581BE6DFA2A06D -:100DE0001CCCE598F5EB32490E7F559E536BB9DC70 -:100DF000D58D5C4CE5AC0F97E33FC2A584C8C15FBD -:100E0000F4F67E9ADA3BB8AE8A659E443C772A2691 -:100E10006B26B457B1CAB86B921FB60939B203D664 -:100E20008FEB38A914BF650A9147BF16E7C8F031A8 -:100E30009EEDA29E1BEB5598263D740B8EF798C92C -:100E400089E375C1DBE3C9C0799C5C17968F743662 -:100E50007C0CB7171DCBE3FC3DE23AE6F1E3799A4F -:100E6000C6FB6569265D9A100EF407FD9C2CE0F622 -:100E7000EAC8EB8AC94E076735F179E33AECA29FDD -:100E80000AADF83F6FEE663E123E6C1C97174E2E71 -:100E900054B6F079017E213FFC9130B2EF9D14E70A -:100EA0008F8433D0CD30B2D30B7EB54ED0CB3A0B3E -:100EB000A703DF3CAE3F05E985113DAC177AD64C60 -:100EC000815FB696CBB5402F1CCE6B1305BD30F6B7 -:100ED00037A487022797B3AF515F02BC0F48EB7D61 -:100EE000A5DE24F1CDCCFE61FFCC2F52BB7FD73ED7 -:100EF0001F9C9F552F3C1AC5A0DE697353BC1BDA9B -:100F0000D76C5B11E581F494D917E580F14FFBD5DF -:100F1000427F37F02E4D9376658F5D01FE331FFFC4 -:100F2000E94479E7E189B8BEAFB6591CC81216EC9E -:100F3000B092FE347FEF3C92B321DFCEF3AB3E574D -:100F4000317F406F3FAFFAF9A3F14E82B72FC994BA -:100F500080692089413A7FABC51D40BBF407AA1BBD -:100F60008601B9B96325CECFD81EE77119F0BDA0AF -:100F7000592DD5A2AF2C5F20F8CB82BD0F7F8E7686 -:100F8000BD05067B7DA5F05B18EDF593D2227B7D38 -:100F90009A0DFFB89E5D8F7210C0C51DC07D0BF30A -:100FA000492732E1F6DEC6E71ECF6D477961EB3B9C -:100FB000514A4ED05E2FFD199DCDE59B5E71F6BC6A -:100FC0001F2F08BB6D105F9C6F390F28C80340416D -:100FD000E7698D25107513C0A366B385F84CCDAEB7 -:100FE00067B73F8974F6272B9DE7D5BBDEFCC38D21 -:100FF00028EFEEB1F42AE2CBB02BF1413C2D707218 -:101000003B99C44BD52FDFD49C83F9F725B141FC24 -:1010100054EF39A4B1C157C2716CF321ADCDDE0DCF -:101020009E9ADBC7939DE8B9AF35DC07A75F53589D -:101030001FD795ED2B37BF1985F218C209CF258927 -:10104000AF2EFC19EA43FF135FB98EEA3950AFE8BF -:10105000097FF97876A05EBE3F92C5C0F8951F590A -:10106000FD4588D7DD8BA3701D9F99EB389D3FBD53 -:10107000221EE5BA4A8B2FDE4129FF5EF9CCFD44E2 -:101080007F7395BA78470ED177A28964065F22AE46 -:101090006FF6C669B4BE39CC4BF457F9B45AEC8735 -:1010A000F44B332BDCD3CD3EF958F0A5CFB600522C -:1010B000617D9FA1DD06F9C6EF54A1E72EA4F3FBE5 -:1010C0007EB156C61651FE4B21B7ED4E33497B9685 -:1010D0002D545F5CB075552BE2E74CB2A70FCE13D1 -:1010E000E0E013F052BE857ED5DF16F4E1F8614EE4 -:1010F000F370D10ECED1B1F81DEBB75A3C68F70EA4 -:101100006927F4393EFE7D627C987738EAAB9FC54B -:1011100073B9DDB8BEB001920FB056164A5F3DED0F -:10112000FBAD0F125D7DF101E72BF3FD930AA9BC26 -:10113000D512E883E5FE435315E20B5616E86E5FC1 -:101140006FB5887DAD2F87799A9550F8BEC6E5D0EA -:101150003920770542F671906EB4E0775AF7236232 -:101160001D6DE44F937EB8B9821F18D76DE40F1F31 -:101170001AF8836CCF3676EF070AF2051F8D5B03F2 -:10118000E709CA19357FB2D2B951B3CB528CF039C5 -:10119000BBF3F01F66A21EDA2CF7B19EDF1AF771BF -:1011A000E58BC3BADDC767D7E475BF8FE17BB7FBBB -:1011B000788D42FCED7FCA6FE1A423BB414FFB75E4 -:1011C0006E0FFCF6DB34E11715F0FC92E544DF848A -:1011D000858ED2FE841F035C253C8DFCF3F1342701 -:1011E000C1D7C83FE1EF03160247093F499F8C79F9 -:1011F000699C2E3A96742AE9B88B4E8DEBD5C3D1F3 -:10120000587E18F913CCA7F8650BB79FB528246F43 -:1012100043BBB792AEA37DEAA1E38F35BD95D42B36 -:1012200034EF37E49B0DF53D867CB1A1BED790AF7E -:10123000D3D5AF397058E3FA414057CF5A7F3BE9D5 -:101240001957CA117EEEF7D9FBB9E643BAE8D7A120 -:10125000215FB42C63BE4894770FAA24EF5E7476A6 -:1012600044A15CB2228CCB6D171D221FC3F31DBDA0 -:10127000B595C817E5F78E306E27B958DC111513F0 -:10128000A2A7B7B7A851688F6DF3B3C2EEEC28647C -:101290001905B8B6B19ECAB9FC56A0DA53EAD11EF8 -:1012A000DAA4BA814C58C5D2BBA228EEA125ED8E96 -:1012B000E9F07DF6DB2A850F5C0CE77605E6F3980E -:1012C00031EEA09CA3909D62BEC746C2BACA5B78AD -:1012D000FC41C51A3D7EE7D8A746079CC877F47144 -:1012E000027351AF4B437D4FFFBD8AAD217AAB32C4 -:1012F000EC0BAFB0D31AF745D900B12FF2589EB01E -:10130000C7909F6391E0D7056ACE1DD301FE178F6A -:10131000A8CC0AF9CE1695ADC4F5EE54C8DF830EFD -:1013200001DC6FF3615FE27C247CCEE1BEC9EC5945 -:101330002E39F7D227C37F8874B2EFE3DCA7203DB4 -:10134000B7EF4F19AF627EFF1F533E6657D61FFBA4 -:10135000DA5F67211FBEF89A95217D5F7CEDD72962 -:101360006817BCF88A95F4E58BCBACDCDEFC5AA49C -:101370001FFD911793B99CDB78F0EBDC363A779739 -:1013800013BED60ED0B8DCD4F2F76368AFEE6C8132 -:1013900055A13CF15A04ED9F05AF84913FFCE2C199 -:1013A000AF8787C64DFC4FD723FDDD1723D9F41730 -:1013B000916E855CBFE0D51B9E457F6EEDDE435A86 -:1013C00039948FFDD57FE722FFBCF82297932E58E2 -:1013D000DA9E415BE386AD373C624944FB1C74D620 -:1013E00017D0B5ED81C9B84FAE840B87C3458003D4 -:1013F000AE0BE052897CBF2778BCF06F0B8FCF67B4 -:10140000717E763D43FF6F102E0AF723B444FA6DC8 -:101410000AAD9F7F7FEDEB5CE437575BEF6F70BDEC -:10142000BDFFFF59EFD97F5BFC727A5F3CC049F387 -:1014300033D2FD9574BDFF3F28BF3BD24DF3BDC6EF -:10144000FD1E91FEEFBAFEFF1B7C0FFCB75DEFD5D2 -:10145000F0FDB6C077A403FD8A170FFE770AFB0ED6 -:10146000EB2E4CFF77DDD7FF7CDD525E1FA3BA8FDA -:10147000E441FD7758F3076E17491FDDCA1DF707D2 -:10148000E3EF483F1ACBF8393DD6564DF2E6D87E09 -:101490006B492E6E64F9E487F0F553C91F43C117F9 -:1014A00000875F27E4F9C99F640EF45B0CF93149AA -:1014B000B5149F65D41BC7864F284479F4F0529821 -:1014C00017F47338D2E4405FF1B87E6AC09A4B6972 -:1014D0003BA66FA5DC7E04E5967176BDFE74BB412C -:1014E0001FBAD5A92F2F642FF642FF59618E85F9B7 -:1014F000613EE3B17E88DE3825DD41F0BA95352DB9 -:1015000077D8BF3B9CB6A5733DF94A38FC73B85DEC -:101510000127A1279B457D23DCCCF6875AB19D99F5 -:1015200081DECBD74BFAB2D47BAF064F26F469B33A -:10153000185AC2D7DC8FFB4943FA25B848B87F5701 -:10154000784B3C19E12EE12BE166C4433D1AA37AA6 -:1015500007E1DFCF9C67C67D77B390E3C7996378D7 -:10156000BE5FAB5A4CFBD1CFE9FC0BB719E593D169 -:10157000F6188AD764CEE418D46751C4FC3609E45F -:10158000CE1131C315586F9299F9ACA06FA20F8D8F -:10159000ECA80F9AFDCB5C380EB7D7269BB95D1A25 -:1015A00076B72F3C9FEA7B34C897FE6C2EF340FD44 -:1015B000D224E656787D161D4BE1684CC5B82C4800 -:1015C000B15D6934EFB7B40FF32FE3F824BC0CC05E -:1015D0003495FAF5986279FBA87C6AEF33F1F61E30 -:1015E00033C67BA571FB7AC70A2BE91FA5AB9233E3 -:1015F000907F148DD1DB8D9333B89D59A6AB33F812 -:101600007E574DEE04948BCB960F247D480D2FAE64 -:101610007D09EDFDBB23881E4B57DE336118CE6F6D -:10162000779C1BA77766E29EE1BCFE8CFB3F84EFB4 -:10163000DE1D61F47D6786F7683AF4774671CE7AED -:10164000093E944D3BAC25C010DEE649E7D1FE379C -:10165000D1B7E73DF4334E9CAA52FD898CC73DB209 -:10166000E511E48F9EE0FBDC9C00FD4D006503CBA3 -:10167000DBC31C290B61FEA5C2DE7B52EC17359C37 -:10168000795FB4E3BC923352E1FB04D67D1C706AEF -:1016900086A83F46D988FEA1FE63B93D5ED6C77EC7 -:1016A000B0DF2C018F8BE9DCEE24F30057AA5FB189 -:1016B000DADA9E867ACF6A4B2013D25959632EE12B -:1016C0003A8B52D9F80D08F70754B685E6DB514A34 -:1016D00076EEC82C27E2C10B244DF1854D2E27DA7A -:1016E000BDDA473707D03FD0FE84CBDDE8242C534A -:1016F0003C8ED4B3DA470706A05DBE238FFB198E5C -:1017000039DA22513F2CB7DB283E47C6F5CC76F0BC -:101710007DDEBFB16DEDF5A8773EAABAB7407EF683 -:10172000A3DCEFF217BBCDAFA0BEB69EEF53B6461B -:101730001FC7C31C6EB2F794378DD650BFACB07BB9 -:10174000345C6776A6372603F7D13700BFE118C7A8 -:10175000C96833943695529C891A05FB0EF789D9CE -:1017600019857AAF310E688188FB91F917C2BC7D6B -:1017700033004E65D1CEDD482FC7EBD3C8EE3943D9 -:10178000D05D11C631A27FC2DC9688F379078DB88F -:10179000307E51AC23C34EF41CC6100EED16470626 -:1017A000D277FB8A3013FAD98A9671BA867D66336E -:1017B00043FB07CD2C1CFD06A7D279BF254BCDC519 -:1017C0009B21DFCFC6CC91B148577944D79BB3BC9E -:1017D00017D3A1FF533F6223901ECAD7AC23FF8AC1 -:1017E000A40B666E1D1707E39CDAE6CA47BE29E91B -:1017F0006873D6983C844B173D4C55880E203D9419 -:1018000046F430793896178D090C589483FA680D90 -:10181000F3E0F99EC0DC282774B20EF23F76DA3589 -:1018200027DAB9243F917C03F0EAB1C507E9603BB0 -:101830009CF7660B633B1A6C943EDFE06066E071D8 -:101840003B1B1228BFBBC149697343167D7FB1C1E1 -:101850004DF9BD0D2328BFAFC143F9030D8594BEDB -:10186000D2504CDF255F02B8101F927C45F2A37264 -:10187000BBD68EFE48C9978C74330BC03B2A9FDAC7 -:1018800013DF93FC0ED761CA0FF22389DF54A5D86A -:1018900097E0423ED63603F15FA09EDBB51FF5F21E -:1018A0004ABB9BF474C6F95E27D02BC2254563075B -:1018B000D0EEDAB8D0D3BECA1584FFDD950A3387DF -:1018C000D0D53D7561CC1C726EDC5B1FA3CB97D469 -:1018D000FFFECD3ED0FF1DBDBC55487FC77EFCE955 -:1018E000D37F84EF9B7E7C261DF10DF3D8F6388ED6 -:1018F000BB24BC6B1EB1985F6E217F547F6907814A -:101900003FC44B19E3FB6DD38FFF46FBBBBDDEEA43 -:101910004479F823C413C0F5CF024F65F556825FB2 -:10192000E98A13BBF6E33E5FA2119F2B5B2EF6E123 -:101930006A8067887FF77822237B0448D314AF7EC0 -:10194000FC475A2002FA3FAEF0FDAB805050827146 -:101950007FAB7F7D14F7BF527F84FCE75E9B3D40E9 -:101960007280CF722EB43FA5FE2DAAC7DAFAC5A0A9 -:10197000BD84CEB15BD0EFE8D19CB06EA469C45BEE -:1019800059D6EB2C11FD264D8A03B74C85F85EB174 -:101990005AE1FE49B33B612AC87D8F64A884C7F72A -:1019A000D2CDB42F733298885F68A2F349D26BC549 -:1019B0001A6887FBA2294F9B13C287CBC4F7F22C6E -:1019C00013A5F2FB16D16FDFD579D3519EE88BE5D5 -:1019D0003998E64F47F8F6B58F372B21F8DF986135 -:1019E00016F3E0E3E7E06683FF7B282B559B9D839E -:1019F000F8E1E7971CA72C2B7F25C67196AD198DB2 -:101A0000DC97355ADC09BDA0DEB6AE7E1C5C5EB04C -:101A1000F178E59A1ECE0F693F3B85FFBC81D64D1C -:101A200076DDAADDBFD88D71FC551F5B09BF55431C -:101A300044FC548E7FF8143234EAEDD5E37EF1494C -:101A400014F91FF6F2B84A48B93D754925B7BFBA2F -:101A5000615F75E3FF7963F7C751DDDAA9F7AAD7AC -:101A600064A75EA07C1385F2835C4FC1C12FE3693C -:101A70001ECA65F2FF2C38B822BEBB7B37467B7589 -:101A8000973D5BD8ED8CE5467BDDD10CBD1D1B047D -:101A900044BAC725ED754CCD8946FBFE97E29E47BB -:101AA0004F7A8DB46F2FD8009DC4C1FE343BA3D1B3 -:101AB0005F75B10779DA99C9CFFBF3C21E7E71A7B2 -:101AC0004A7ACEC59D91B49FE6EFFCD95BE83F9C76 -:101AD000BF55A169D4B256821BC093D942CF318C75 -:101AE000378BBB72DE9DFEF4683C47AA7F11598795 -:101AF0007436AF59F16C83F974DA9CD1BD43E6F3C7 -:101B00008DA0B36A6BF37082B39C3FF2C5DEC17ADD -:101B1000F35A7E46F663A87781E4A0172218BFFF28 -:101B2000D1F11ECEF3ECC6A16EF4FBCD6BDE339F7C -:101B3000E4889D110E1481CE883861D98F2D938F42 -:101B400067CBE472CB59E10F3ABB5B257E86F3C4C9 -:101B5000FD7546D1C7E345897651026E2FE2FEEE50 -:101B60001DAC3FAFB93D6A00D4FFECC0EF294DC8B2 -:101B7000E47C609EBD3517CFDFCFF646903FEBB3D8 -:101B8000BD4F8D7F15C63BDF3CBA17EE07D97F46A8 -:101B9000A685EA9FDFA81622BC989FC7BDD4227CE9 -:101BA0008786CE336EB3CF15BAEF78DCCFD9BDBF01 -:101BB0008C32E504F1596BF3DA125371FF9416235A -:101BC000DF38A538A99E65EF681FDE635AD092C73B -:101BD000909E69DF2552FDD5A6907A9AC54D4CD1CD -:101BE0007C60922789E02CEE21897879BC5747F7F1 -:101BF0008A26D9C83F316B88F3AEBB914FBE63E1F3 -:101C000078E9E77C1CE5B759EFC751DCD42297F39C -:101C10002E9CFFE2DFAA14EF3B6BA8E003096DC323 -:101C2000306EB166B5C23CB0CE7617971B6AFC2AFF -:101C3000F342BE2FD0830F4031313355F0D34006ED -:101C4000DE077CB2D2E4D1E0FC3BA6319F8A76A3CA -:101C500017793C734D2A8F1B7E12E91ED29AD84009 -:101C6000461CF4774EE0B366722003E3246A5E4CB0 -:101C7000A43889731AF75BE277F493D6E4437BA820 -:101C8000D74BC4C362FB9810FAA929733BB19E1AC3 -:101C9000EB76E6D971BE8E0B24C7BE14C9508E35C3 -:101CA000ED8FE4714E3F0FDB620DC15399A0B75E1B -:101CB000028F6C268F877C4CC4633FB62DD18FFA80 -:101CC0009BACFF98C53B03E180EB40F97D9ED69429 -:101CD00081F2AD9CEFBCA8269AE73941DFF3C29BA5 -:101CE00078BCB4C6E329B13EE6DB2D8CE2B83B9E5E -:101CF000B3523CC999C4D67D38FE99E706325C7F61 -:101D0000BBCB3FE7009583FC0878AB7ADE1AC0F5C1 -:101D10009C7E8EDB9B4F5BB83C767A528213F156E9 -:101D20003879C32CB2C76CB52A88F7D30AD312B05E -:101D30007C5B6FB70FDB37D4539C7415B009BC8F35 -:101D4000036921DEAB39BD6D20C5879D7E5BC51B58 -:101D500051F87D357EF7B2A6593F4078ECE0FAD3D2 -:101D600099E7FF3E30F41E9A4CABB6EAE3E0249DBF -:101D7000C8F246B12F1B059C5765F273AB36A2F92A -:101D8000B1545A27873BE089F43E38F8239FBA0EB6 -:101D9000E320D215E41B4F025D3D8576851D5CBFB7 -:101DA0003AB3D34271E155FB233D1477B6EA7A1377 -:101DB000C541A85C0EAF3201F82855A8DFAAC95961 -:101DC00074DF17E04D7A6CC736558CC3981DD7BDAC -:101DD0009DC7F916A1AC48E583A9FCB4C89FDE37BE -:101DE00098E43AE8DF83F795AA7EF0430EC7299579 -:101DF000EF32B263D888BFD674F9714646E379579B -:101E0000BBEAA668BC07C8DE5719CA2746385D3248 -:101E1000BBFB205FFD83E05FD5FB9ED6901F548BFC -:101E2000FB21D5CF2BDC9F0CFB0CEF4956AFBCE957 -:101E300071A2CFF72C2C1DD673AEF96751A1F8080B -:101E400008BED6555F7353FD6AA88FFD54AF7C273B -:101E50008AE6B3DD427126463C5E73FBE7D56B6ACA -:101E6000DF451FCDDC8E72C5FA59EB7F7C0CFD7F00 -:101E7000B133CCEDA3AFCD74AFECACA5790EAEFF12 -:101E8000ECAE30E2476763387FF80CF8A72F13E712 -:101E900071FB4F292EEB7753E83EDC5CBFBE5F3908 -:101EA000EE9BC8B7319E24CE1D8D717DB5EF73FEBC -:101EB0000678B983DABF6FA1F6C6756C15FCBE6BE8 -:101EC0007FEE8A207A38DB97E3E5ECEE4C3A8FDA46 -:101ED00063389DC37C53F0FEDCD95D9979742F0D76 -:101EE000851BA0872AA1DF9E8D694E718494B75B04 -:101EF000849E16809A4837D806E4BEAA7A2E575593 -:101F0000DBD6507C08C6D50ECFA734608DBD323EDF -:101F100016E895F4C77E597C7F311C2F5EC46F9301 -:101F2000BCD3AC21FFF60AB9B066A731BE9697FFC5 -:101F30005DEC4F9C6D2F19CF8B74E85328CEA47A9B -:101F4000F9C27948E7D575EBEEC67D26E75F6D6689 -:101F500085A887B52B2ACDA33D8CDD3B19CF8DD02D -:101F60007142E4362DABCB9ECA1CF124AFD2391698 -:101F70009EE5E474832726DE135DAEACA1715C524E -:101F80009FE5EB927002706818D7D73E5A94F7B06D -:101F90006E394FE3BAE57C52B2B89DA4DDE5FCE9A9 -:101FA00048C4F36F54BA4F7BE99BA1D1B1DDC8653A -:101FB000C1735D0BC6B7C2FCB391F6D0EE92C9ED0A -:101FC000A8D5183F0BF3CCD8A88FEBCEDAAACF0F49 -:101FD000DAA9CFE7ECD5E7735BF479F71BFA7C1C41 -:101FE0008EDB9BEBD9787F17F56C4C51CF765AB9C5 -:101FF0009E8D79D4B331453D1BBFA39E8D79D4B35B -:10200000318F7A36E625BC51DFC63CEADB585E22CA -:10201000E05423E224110F48EFECE530DD7D9F8B87 -:1020200007F93D0EA003BE6F6668B46F9EC41AA484 -:102030007770BB52DF293627C6FBFA62BDE3B38651 -:10204000E17D8FD695898837731BC59D2E7885C70E -:102050009DD6E487D9D1BED1B6E2B39518CE393535 -:10206000D67B7B566FBCCFD9B11DE15B5B7F98EE11 -:10207000BDB72D75BE7F0BC71FD95958652CC94DEB -:10208000A578CEC5F68C4763DC375BA38FF336C6E5 -:102090007D1BE3BD8D7420E5BD4D968E44E4EB279A -:1020A0009EB3ADC1F99F0813F74FA6DB0CFE7E214E -:1020B000A7AD55B6E0795D9315CBFD4947403EEF9E -:1020C000E69C9569F9E5A1248777E5D72826BA1714 -:1020D00097104FE7D06231A714A5A37D15F2B97907 -:1020E000263A372F815C86E35DFA4025F921738318 -:1020F00049B79E81FE701D7D65EF8835DC6BE8ABCE -:10210000AB3FE440AAE15EC3207D1CFDD4A587500F -:10211000BF9FB266A8AE5E45F14D06388A790BF9CD -:10212000B502CE0F0FACEFC9251B5210BF8BE77560 -:10213000B6AF42F9F4A530BA175689FF0FF86225F9 -:10214000F489F7192BF78AFBC0F5FA73B85C9C4346 -:102150009566E673C406E9B0D2C13C31D07EDEA0FC -:10216000D6DC00EA156FFF7EB82315F58AD17D9085 -:102170001FA5583C14075BB3273D6629F4BB22CD4D -:10218000FB14D2DDC9A6C33F29C1F3700FD7F74EA8 -:10219000ACF96514C589097A4BB138C211EF9B9B24 -:1021A000787C1CDAC7D4D8205D6C6E8A0B1F600F58 -:1021B000AE374807DF109E003FDC8E53F93AF93DF9 -:1021C0003A9BC57A472B3E94A7E5FA168973850D8D -:1021D000E0FDDC27F227857E21D7796EE0A15C2720 -:1021E000DEBF683890A2223F37EDDC9E08A9DBEA0B -:1021F000DD87FBAE7273FA1F47C238551FF2F5FC3C -:1022000065FDD8A81B50FEDC657117417E55D3B320 -:102210001AEAD95566BF46F195CF6DD630BEF87B28 -:102220003B36D3F7393B4A299E722EAB23FDF394FC -:102230007C7740C0A3728CB2D101F34E1AC8E5BEC0 -:10224000CA70EEBF03F9E84D7CF7E3D20E250FE329 -:1022500078A616EFD14AE1FBFB82CF18F749E7BB1E -:10226000530A7A133CF87D8D0F1968F16957EE8B8C -:1022700029975DB42FA65ECE26BD6C5A6020D77F0D -:10228000730CFAEFBBFCDD85CE16BE0F2AB540AF4E -:1022900029B84F5EB3909C5B0BE7CD887CD4AB191B -:1022A000BB11D2E291AA8E5E178C8BD0D1F374163B -:1022B000B24FA0BF3B316824243FB5284D57FFAE35 -:1022C000A9D906FACF0F96131FB95177BFAE7689F9 -:1022D000CFA9909C3946FF9DF13841C66ED3B5AF6A -:1022E000659383F590BEB77239B8766FCC16B4F7A4 -:1022F000559AB8FE34DDCBBFCF3FC0BFB3E94CB772 -:102300000FFBA7B9FFC8CF450BF905A43D7D3AFEE9 -:10231000BB1BF8C349DE753F1CEFC5A33D42777F69 -:102320005AF80371DE88875A6137AACDE276A35A3C -:102330005FAB86EF0E00FCCD71B154CF1687F191E3 -:102340004D0AD915315D42F192FA382CEC0FE318A1 -:10235000E71F514B719F18CB2BF1DD1FC4EF2B3CB6 -:10236000AE74EE06631CE41AF247CE477B5008DEDB -:10237000EE1EE814F28A7F655F845F919247F72230 -:10238000771ED230CE6EEAD4983CDC3746FA927C87 -:102390001DF633E9DF9DEF1E26FAEAAC3413FD5E2D -:1023A0000D0EF33DDC8E6AA4BB39AC55C37BE273E2 -:1023B000F62A6ED447B11EC2A32FD2A3011E71B15B -:1023C00057C241C2A70B5E7B8D716E1C4E730F28E6 -:1023D000FE40377032CEBB27B8C9F5CCF17AC7239F -:1023E0005F90EB9A8BF3C7FE61FED8BFF443B01148 -:1023F000C6FD9946F6A9F9C53C3ED6480F932F7302 -:10240000BBCB9D97CD944E2DD2EF476C87FB62DA04 -:10241000E5782AFFAEF4321FE6C9EF3F5D1B9DC889 -:102420007548BE1BDC0FFCDEC0D5DE0532DA1DE7C9 -:102430000E14F1C8C3D8305D3CB2E0ABC6F6C67826 -:1024400064290718CF97D24813C54D76DA5349BE91 -:10245000907CD62BCE0FEF8A2FA99E17EAF1D9C414 -:10246000EBCE1BAFB0FF2D8A4CA5F7185296C6C510 -:10247000239E4AC31C147F5FBA54A5B8E752A8E74D -:102480000C914F562E4F4BC1F3E2F88399CFF84091 -:102490006E3FFE40AFF81130CE8915965E3667B0BC -:1024A000DEF115052918A771629D75BABF1B78ADBD -:1024B0001BC8CF87DA1F1FA5F3ECBCE9DDA8E9D064 -:1024C000BE66C54B5118E65FBD829FE303D3BC4D8A -:1024D000037BE379BE79BB03E1E7D89C8B76DF4DC4 -:1024E000701C607B293F54AD28E883F245CD3F0E38 -:1024F0003FE3C07BD64B2DF1287F9EFE00CE438567 -:10250000CE33921B4E854117E44F8B243BC2298565 -:1025100079D0AF74CE74E8AB55A817E635670420C0 -:102520005D68F56E1A88F2FF8A67496EA97A686954 -:1025300086AA62BFE9D1DDD94D64BA5D9CDB28BFB4 -:10254000638AF23BC6C9A0FC8E7994DF3145F91D40 -:10255000BF2FD8A097FF5E10FE42694FEEDFD891E3 -:1025600087FE3BDF18965547E7AD3D0BE5F5C54ABD -:10257000B81BF9D162949530FF4918E9B16C6B2210 -:102580003F6F059EEB6DDC6FF4B5B89F7B7307C89A -:102590006421F479CB651B0BBD373B9AC5E8F26328 -:1025A0006D89BAFA050E97AEFC7B090375E5B73A5B -:1025B000F374F9DBB36ED0D59FE01EADCBDF31E213 -:1025C000565DFD499E49BAFC94C219BAFAD38A4BAA -:1025D00075E5774D9FA72B9FE15DA8CBDF5DF98067 -:1025E000AEFE3D754B75E55F9B4023057A6941BDA5 -:1025F000CB8AEFA7D828FDBEEA3023DF58FC9B74B6 -:102600003BE27BE458535D77F6FD53421E4ACFF61A -:102610009C407A4916EFE3248B776EBE1AC8F19975 -:10262000C480AA48DF6D4D44FA35D633968F8C7836 -:10263000FD92137058FC7CF43433F08991D7BF3E7F -:10264000340DF20F3E3F9EE76F7AFD97A9905FF73A -:10265000FCC3D3CCC0A7460E79FD129627FCE276C8 -:102660009E9FC248F4787AD0DFA7FA70FEB7A4AE76 -:1026700071733B49B7F7CC658A70C0FBDA08074C29 -:102680000340BF98BE0EF48BE91B40BF15C09FDE10 -:1026900002FAC5F408E89FF8FD3F41FFC4F45DD09D -:1026A0003F317D0FF44E4C5B41EFC4F4770DD329DD -:1026B000FDA0C14BEDFED05049E9D1863AFAFE515A -:1026C000433DA57F6EF0D1F7D841D28E1160BAFBA1 -:1026D00001E867447FE201CBB9503FB0F4574AFFAD -:1026E00064631D6B8B407ED1668EF9D416F43BF685 -:1026F0006C0730B34F43E4B168E6491E44E3F77317 -:1027000090DF487CFF557F6FEA20E03B1FBAA6A40C -:102710000F55F1DCAA7B13DDB21F8AFBF5C67EBF25 -:1027200012F4F1D7419E4C6C27FDEBD2BFDD15377B -:1027300013E27F3785C4EBD05F48DC8DF483CB3860 -:102740009F9B6DFC9EB1F473CB781ED95FC1178C33 -:10275000F8C3A8D566925F22CD2C80FDCBB89D51E1 -:10276000B6E63C8C63185563A77BB57DE0BB964FFE -:10277000F53C2AA45BFF0AF573837EF53E62FE50AA -:102780004EF32FF8C24B76D85122AE00DBDB78B97E -:102790000FDB8F42DBC27594127F7A1AEFEDE607EA -:1027A000FDFC583F82D70F607F03FE06E34505F727 -:1027B0004D726C731EF2EBE4F976BA17BA7174803D -:1027C000DEB322A313C0658AD49F6C222FFD793B10 -:1027D000FA901D69ACD8EBC39CDE1988CF62ABE3DD -:1027E0009308DA6769C9689F9C24E4E77F82B75938 -:1027F000D84EC253E245E251E223247E8AF0D01340 -:102800005E8DF834E251E2AFE08B205E10AE57E20D -:102810002D8857B4E7FEBBE0ED3A337FBFCC5A6357 -:10282000A377D1AE86C77B3BD8F868A8F295D3FBD7 -:1028300015F2CFD2CBCEB7305FCE468F47D4CAF297 -:102840006F7B28F77ED161890EC1F7CD02DF19AE0B -:10285000EEEBCB7AF23D06D97F410FF5DF0993719C -:10286000171E7BDEF060FCE3E2020EFF42974AF0A7 -:102870001F9B3397E46466E772A613FE43BE34FEE3 -:102880009B627AD7F24BB6133DB76C7C2FBD7C5A56 -:1028900068F05BDF26E4D2DB0C72A951AE7C71904C -:1028A000F067BB98EB3BBE57F932E76BD7FA5E2572 -:1028B0007FEF749CD8674982CED29C2A1B8974C44E -:1028C000BC744EBE81EF9DE6E2BBA03ECADFCAFCEF -:1028D00094DECE0274BE4E00468CF93B18A37BE416 -:1028E00087232696E0DDB8B143C70EC0EF21EFB2D3 -:1028F000BD87F39BAF7AFFCB11F22EDBEBE39C7429 -:10290000BFF2755B1AC95FB80F2D21F6C0B7E17C25 -:102910001A00E7C76138BF307D13CEAF01B0DE5F6C -:10292000C3F985F9DBB296326C37DEA98FDB91ED06 -:102930006F778C05C5A467F8DD9EFB723F84EF3B83 -:102940003199E3D07EFE4ECCF5E370BDEFC4F43197 -:10295000F1D4AA513A78FF80EEE443B90F82E38DB7 -:10296000A7F18CF095F034C251C2F75F80E7E5EE35 -:10297000E0F995909F3B6DBF8F4A4845FF5D947885 -:10298000C7F237B92AE44FE3D412315EF5269AE74D -:10299000A8FA1B987928F96D7210AE35360E2FA360 -:1029A000DD8A6DED630A8DDF3DA379C3B2619CCFF3 -:1029B00036AA746FFCFC8B61648F3AE5E7F6B6DBF0 -:1029C000156F5436CCAF4675AEC1F747D93BFC9D69 -:1029D00033F6CDE194C991DF814EB7F2FBF635B6FF -:1029E000F1DDE251EA53D12E0FED7326DE8B9472A6 -:1029F000453F2B7F9740BE5FD8939C313C9CF3C1F1 -:102A00007E56CEB7255EA11DE593A09FE1C0E7925B -:102A10007E1A4EFA45636F4F06AE4FDA113AFB4508 -:102A2000F891DF8E0A64D3BB5C8547548A277E5DAC -:102A3000C4777D2FBBCE9E0A789A94EE756793BEBD -:102A4000F98D8A7CE65D58671CDA1F8E0CB593FE03 -:102A5000F81DF5D011D9825FE4B25CDD7D35497790 -:102A6000AA9DE2773A3FE0F7F116BDCDE33617F5C0 -:102A70005629FEDF1817378A65FC14ED8D637B59E4 -:102A8000DC7E6790BFC87780AC0926E60C91B3C3A3 -:102A90009CE1CC19329F88AC585D3ED2DD57573F40 -:102AA0007A44AAAE3CC63348571E5798AFCBF72E90 -:102AB000BE5157BFCFF431BA7CA2F7365DFDA4CA30 -:102AC000C9FA3CEE3B807B72DD4C5DBBFEF565BA1E -:102AD0007A2E5F95AE9CF93CAD59F1C8C7F95FDA23 -:102AE000EA45BAF2A7A20A79FCB87D0EDD534C6F15 -:102AF000FA81AE3F89DFA4388E5FE6E4E7830FFEFC -:102B000023BF85C0734182FEDC18EB18FD8683521B -:102B1000BD5D23E92A71500FFCAB7450CBF474D027 -:102B20008BC7F114BC3DD489728C11FFE88F085D0E -:102B300027FA2342E182FE88D03CFA2342EBA33FEE -:102B400022B41CFD11A1E5438FE8F13FAC558FFF86 -:102B5000EB8F8EF9A778BAA14D4F0F463CDD744A32 -:102B60004F1FA3BCE10497B1208F21BD4B3C4D8783 -:102B7000FFE89C67C5D16837B88579E85EC0FF1665 -:102B8000BE5EC816F62381AF2FD99A61F8CEE5C58F -:102B900052CEC77B3AE79FEBEF7909F9EE09E4F3F0 -:102BA000C3AEB403C87852DF188E4FDFB130E2579E -:102BB0005F9BDA22F1FCF8BEDA4676F944D6F126BC -:102BC000BE3FE3E8E53D84FCA80F460F40F993F3D0 -:102BD000EECCC3736ED6AFAC2928D7CCEACFDF13C7 -:102BE00064396DF44E8B9CCFAC241E7FF476B6E036 -:102BF000D36E1E87F46E36B7FF44BA1D14075D9A74 -:102C000023DEA131B3945983910EDF0DCB443A5B9F -:102C1000CFED5C6D1627C5B5F8801ED14F89F23611 -:102C2000CAC3C9421E6DFC93CDC6E98EE9CEF781B9 -:102C30007E9B2E0E377B8743971FDC9CA0AB3FE427 -:102C40008053579E17C8D2950F3DE2D6E587B58EC3 -:102C5000D0D5BFFEA84797BFA1AD5057FFA653C51B -:102C6000BA7C12EB7802E1A9E6A4123CFA2BC20E60 -:102C7000E0E47899F5FD78BA4F23F5081997ED153A -:102C8000746CD447FA6B5E8AF36E4C646EBA0F6252 -:102C900013FA20D3EB295E11572DE579E6D3C755FA -:102CA000CB78EA2E7D46E82F529F0889A7F6E0FCF4 -:102CB000653C7517DEC5FB9246FA74E408BF906167 -:102CC0001DFD357EFFABF1018DEEB1C8F919E73579 -:102CD00043C4036EB375FFFE504A0EB71B6C4E2DF6 -:102CE0008ECF817ACFC0F144F0BC623C779B0FE07D -:102CF000DBF823CDBDCC79F5F1660DE1EB29C17789 -:102D00005573E89D4EBAB726C7CD15E3F6CA55BA36 -:102D10005DDFAC681EDFC5A235BA77D1F3781CAE93 -:102D2000091A5B4EEF24897B08F7AC695E9B094565 -:102D3000255A9385BFABEFB7A09DA8680CC88179D1 -:102D4000C027B6ED5B6F07F9E7997A33D97D86E541 -:102D500024DFE91B10BC57D21FF434A49322C43FD4 -:102D6000F4FBFC601EEF7C670E5F5F81FA4DD77D40 -:102D700000AB8ECF73FDAF1BBA237A94EBF8BFBACA -:102D80001F20E9D70827A95F33717E0D10F392F059 -:102D9000EBB29F08F8C9FB19CE8596E22D76BAE70B -:102DA00051887165127F070773BA5C2DE081F59039 -:102DB0001FF554AF40CD89463B782773463BAE6242 -:102DC0000FFE3FBA3741F0EFE9BE574F7CE20AFEF3 -:102DD000D0C3FDAF9EE893FEBEC33DB0103EC1E33D -:102DE0007D043EFC034CE4575F15A9DFC7FB73B8B5 -:102DF000DDA544EC2738B7ED797A3EC1D0AEDFB817 -:102E000042157C624ED7EF4FE0F7D92B2C245F336D -:102E100056FC18C619FC65BD85E262477918C931B0 -:102E2000651B15FF6605CFD1910938FF529FFE3C07 -:102E3000BE85B957A2FFA37CB5FEFB5C3BFF9D8A14 -:102E4000D9C6775384BE3EF72AFAFA8E1C718EBB20 -:102E5000999BE42EE1FFAF146D8C7257A79FFBCDB9 -:102E600050DF56B9DD89E2C6E4F9EE44FF4DC87B78 -:102E70002000CFF02C3CC7979BBB8DE7EB82670F00 -:102E8000F10AE7EC225EC1CEE3333AF78671FFA682 -:102E9000F42B89FAE77C97A81CEB636FE7F378DCE7 -:102EA00085F42719FD559D7613F95B3AF746927F15 -:102EB0001EFD38D14007674C7BE247B882F3F3B67A -:102EC000A93A3F8831F52E7D89F4C58169DEDF217D -:102ED0005F3F6B76DBDC907FD0FE3ABD1F5524EC64 -:102EE0005EC6F976E95D23F9FB2E9D3E2ECF761660 -:102EF000F27738802F32DC47320E6112032D15D263 -:102F0000D2C00D349FEFEACF9972398FFB312FDF9A -:102F100044EDBDAB6FA07CFFE56B17E23D98698D7A -:102F2000732DE8C26E7B62494138346D4BF62F0B2E -:102F300047BC8D56BAB5CB5F12786B33C4D7CBB4D0 -:102F40005CF0237C438EF3251187B454A17DB048F7 -:102F500061322E89F8B8CC5F6A12F9029E5FBC829A -:102F6000E7DBC4FBFADB851D05D78D29AE1BF5FE1B -:102F70009DC2CE82EBC614D78DDF916F611EF9160C -:102F8000E6916F611EF916A6C8B7F07B192B4EC9E2 -:102F900053B91F6A5CE8BEBB6C63E342F60BFAA14F -:102FA00042F3E8870AAD8F7EA8D072F4438596A3DA -:102FB0001F2A348F7EA8D0FAE8870ACDB311B7064E -:102FC000F3C8E73C9374F92920E78F0BD9DFE88732 -:102FD0000AED1FFD50BAFEBC0B75EDEF66F5BAF6B3 -:102FE000E8870AAD7F6FBDA2F353DD2BDE392DDFFD -:102FF00010C7E9C759EC1E0C74F05F11FFB8DF92DF -:103000008A786E99C7F5B27037C7735321C7BB89E9 -:10301000713C77CC203C2FD178BE80C7271BE907B5 -:10302000FD3DE32CDCDF8329FA7B30457F0FA6E8EA -:10303000EF1997CEFD3D98A2BF07BFA3BF0753F47A -:10304000F7608AFE1E4CD1DF8329FA7B30457F0F63 -:10305000B6437F0FA6E8EFC1EFE8EFC114FD3DF8DE -:10306000FD18FA9D2CC179A11C3F40A73F021DEA23 -:10307000F447872E8F727C687D94E343CB518E0F8B -:103080002D47393E348F727C687D94E343F3753964 -:103090004EDA5F28CF87B643793E343FB8C9F7266A -:1030A000DACE266CBCF006A66D91CA330AB08C85C8 -:1030B000BBF6DE897EB9B63025250638A74579E509 -:1030C000CE7190F78AF8BF5CD661427C7BC57BEA03 -:1030D000DE00A378CBC17F4DA4F217C4BD7EFA03F6 -:1030E000BCE7ED65F4BB24D25F2CDBBB9943C55430 -:1030F000D60FE6BBAF671C5FD623FE19320FBC01AB -:103100008CF12A794BECF918EFB9DDA4509CC4F688 -:10311000653C4ED84857DB045FDA6EDAF33ADE03DB -:10312000E92855E83E7086991DB1E4239CEAF2F146 -:10313000FC5D3B3846ACABEE46BC6F22E72DED9B09 -:10314000C027E8FEDCC88ED6B1D1D08FD7379A7EA3 -:1031500027A548E37203B6437D32DBA778B684D057 -:10316000F7E38339DFF4FAF8F83FDF3491B70BE780 -:10317000ED7EBE298AE03871B942F1522377320FD1 -:10318000DECFF58B7967EF0CA8385EE9723E9EECD6 -:10319000B774630ADD5B2C656DE312C847A230E4A7 -:1031A000DB126EB0BE37707DA0361C41FBF4B5DE7D -:1031B000FBB9F9BA98028CA3632D8CDEB19C70DD4B -:1031C0006F75EB25B40FA77EE95CCBF429F45EF0B4 -:1031D00044DFD265A86E4CF02D7CB337D6DFCADC55 -:1031E0002E271D45742F56CE6790678F098E459602 -:1031F000C35A4D610AE29B1D8E0BA11FD8F95311D2 -:10320000DF796E0BBDDF3BC9ECB0D0FB113DC49F35 -:103210005CB2CBF81383BC608833695C723405ED13 -:10322000C98B224D64FF5DF412FF3D00EF0685F867 -:103230009A94834A459CDAA5E56FF6BE0BE1BEC7BA -:1032400042FDC9F893DA347F8A09E3EAFB6ECE8D3A -:1032500055490EF8FD6094037CBFBC7304D65BC176 -:10326000DFB1BCB47C5A74807AE2FE9A0A01AF0ADC -:1032700011C7548A0F7AABC1DFD392F73B5813972B -:10328000F7A43DA7F43743DF42FC963E2DDE955E62 -:103290005D4AF7B28D7144F3965B28EE689E412E2D -:1032A000AC167261F555E4C2B3830D72A1FCBD1476 -:1032B000D186A9FDFE80717BF25E628985EFFF9267 -:1032C0003D8CECB0254BC79AE81DE49738DD942C73 -:1032D000E5F24DC9CB1EBA5F28E5C5F7851C33F969 -:1032E0007212C1FDF7426E9986F19500DFA2B630E9 -:1032F00011879548E95D9779BCE5643BE7036D0765 -:10330000F93B109D3E2B97A7DE60FC1D33035D4EFD -:1033100032FB4D78E1CE3D12E812F213500E82FEE0 -:10332000A6A35C148774EE2AA0F8BD4285EEBD18F2 -:10333000E9BCC852F726C687166D636E1F0BA573CE -:10334000A05FECCFA7D0FB005EA1D74AFA35D2FB35 -:10335000AC08618FB2737B53975D0265547CA4DB2C -:10336000177517CA8DB3D0B7D797130CC69D45E60E -:10337000F0F2F4DD51772D4725A7073B85FA038D41 -:10338000E0E195EF20F46037407B01F2C97BEECBA2 -:10339000D3CA42F8E49743C6140CE91DC47759D741 -:1033A0007DBF1C7A1774D183E9F47B383DC9C3E52E -:1033B0000057DC17B3A2DBEEC75F661B97CB3CE37D -:1033C00046E0EF0B32F9087900E308678AFCC2DCBB -:1033D000EBFF88BAEDAC089EF7ECEE7717C685D404 -:1033E000DADAC623D92DC8F116E23DC6207F2AF6C7 -:1033F0002429C89FF202A813CEC810E78FC11EB1BE -:1034000030D7C9D769B04B94E770BE2D7F17E5F868 -:1034100083FB77E37925E77FBC87DF6198976BFAB9 -:103420005FBD0761BCFFF0FDBEDE99B9D0FF63262A -:103430007E9FBFAFDAC4847D88FCC2925F30F10EFC -:103440004610EF1E7A47B7F141C5116A9FF2AE569A -:10345000F83DFA1EEC382CABE3896DD06E568346EE -:10346000BFE3B72983D3CF26A01FFABD14ADF54D16 -:103470009B2B08C78FEB1FB1D0EFD2B0403ABEBF35 -:1034800033B32ECC8DFCF8CB21C575B9C3F0F7480A -:10349000DCC4870A30861CCFF35EC58B713DB56BEB -:1034A0000E3D83EF092C6871D1EF95941EC85B899E -:1034B000EF9C7C39C45B8FE5A57607BDA7317F798A -:1034C0000C9D5FB3FA887BA1AC83FC6C12FE4DC2ED -:1034D0007E75AB9B89DFDB12F71D80414ED2D5EBA9 -:1034E000DE8E27ED84463B83F17D899EEC0BD29ED8 -:1034F00080F6032DC4CE28ED1396ACE333506E282E -:10350000D1F4F712657A2857E8B9420F9CDD756E41 -:10351000E58CEF83F2F13AC541EF4DDA9D77DD009E -:10352000F98A23168CEC6445B14E0DDF1FE800FCD0 -:10353000627C7419EC57E43325224EAB62C30DB4A0 -:10354000DF2AFC9076F30EA74CEF5E7738F965A47E -:103550009F8087FC96150E8F161BB2EFCB9B14DD58 -:10356000BB0332BF2797DBE34A602B23FCEEB9CFC6 -:10357000A5E1DB3E25204660FCDFA15CA7CE7F0CE9 -:10358000F5281EA42895BDC5DF818779BBF878F999 -:1035900021FD9735F17BD3320FF549FE793537920E -:1035A000F057EA8075BB3075D03C010E04A78EB58C -:1035B000D09F93C6217C9407FC16D4B74B300E05E0 -:1035C000F2331D7E0B8E53B69CBF63E25DC3C7F121 -:1035D000AE8ED106A37C647668C9083FF13BAD305E -:1035E0003F92232B002E781F0BEFBBE1D962844F53 -:1035F000A9986F45530CBDA310FCBECE82F898D19C -:10360000C3BB08E705DD962D1F4DF7D72BCC1EBA9F -:10361000E7E015F0FDCBC2B087D03F3063FDE31685 -:1036200017E43F11F47B5EECBBA2D4403ABD57B423 -:1036300030CC8DF39CE168A2F575C1F7518087828B -:10364000EFDC14137C812E7C18B757B15E8FCFE06E -:103650007C387C2BD697D27E9B63F66A8ED0796CB1 -:1036600038948EF7AA66C0FEC6772598C34BF72517 -:103670003F7DF4AE145A27CC13E11AE9768EC7F7D2 -:1036800087804EF83D18B11E79AF5B8E6719C2EF87 -:103690009D5A8670FB59CFFBD243724D23E017ED44 -:1036A000DE3DED4B0D19378CAB55F0DF9130EE530D -:1036B000B93FE5BE94FB54EEDF672CC5810425C8F5 -:1036C00067E09CAD7BB11B38150CE1789829F00AB6 -:1036D000707D23F49E57EE10BE9F4B52F5FB1DFBF1 -:1036E000C37EFB0EE1782F191348C77799647D39A3 -:1036F0006E492C6F87748FF4D6578C87F517517DE0 -:10370000938E5F9477F18B9D2BE2915FEC51B81F04 -:1037100074EDE1E4EFA3FCBA8BCBAF676BB6CDC71A -:10372000F39299FD29A1EFFBCF063907F9C41C716B -:103730003E5704BAE7173B33BCD94342F673C5CFB3 -:1037400076657839BF0920BFF9F3AE573FBCD11970 -:103750003C4FE57ACA56FFD6526A0F859F22DE1D7E -:10376000E9A4FB78E576CD89F1CEE5CB4B89FFB2B4 -:1037700004900B9590F833035D942E57E81E597909 -:10378000FD70BFFABFC8A7CBD74CA2770F24DEE4E9 -:10379000FB2CF27C95F39F28F0356908DF87330511 -:1037A0007DCFAC1CAD25F622B91BC32CD90CF17D05 -:1037B0004685FE7B17DEBAFCD7392B71BFE0FD22B0 -:1037C000D24FD658B8BD6F27B73F9E5DB4FFBD3B03 -:1037D000A1DE99C736A730558F379453E70879751E -:1037E000AEB0FF7583B73294DB647EEE268EB7F2FF -:1037F000DDBFF904DF132B4915FC6E2D7F07A0AC4C -:10380000790FE171C6EA751617CA75435CBAF736C7 -:10381000CAEBF21C68579EB97AB305F9C4A2211C01 -:103820008EC6FD5022E284259CF15C5242FC1BB204 -:103830003EF2477CFFFEBE85615118CF23C7794A0F -:10384000D07D795D4C2C8E575E57FA13D487E4797E -:10385000605CE78930BE5FCAA03FDCB72746BB5338 -:1038600016E504E55963FD47041D3E65E1BF53932A -:1038700014D1FC1CC5352C087723FF1830A0CD8F40 -:10388000E3227DE3BC3513FF5D9B01356D9FE33C77 -:1038900040D4A6B81A4CF17D2C14BDE321BFC5C499 -:1038A000EF6FA5AA3C3D20E003E5012C67BDDAE8F7 -:1038B000F73542E26675F4ABB1ADF4FB895A2F4699 -:1038C000EF9B497A95FD487A95F4DCD3FA9AAF716B -:1038D0007D275C1C9E9AF8DD946B5E9F95FF8EAEF3 -:1038E0005C979C1FC8F01E7ADFE38783C9DE736292 -:1038F000A93B05E3267B5EEFFA82F86ED66B5CA7E8 -:10390000DC373216BECB9FD5C4FD0E271438DFA09E -:10391000DD89856114DF26D7F55DEDE11F0C899502 -:10392000EFF947A29C59121EBC2F8FF03B56CF7F58 -:103930005F577E9772817C674EF2EF9375E2DC648D -:103940006D6B717FB3FA347AFFE458D389487C8F6A -:10395000E5C4683E3FD9EE3E0BBF9FCC223527DE43 -:10396000138BB8EFB7057DD03FB4DE95A740BB7B86 -:10397000EA871EC3F7C7EF59DE87F4FBD976E74A1B -:103980003C1767FB5CE40F8E589FF729BEA3377B7B -:103990007936FD6EEF7D0A2B267D52E8097358D7E4 -:1039A0001FE90973055F9B8BFC12EF4BD51FA677B0 -:1039B000F3E6B8C3F2F07C9FBB81EB094526B61A4B -:1039C000FD89FD1B8BC7231FEB7842E1BFFBBC5178 -:1039D000FF0E577666F1453C1F8CEFDEDD6769F61A -:1039E000E03A18C82368779A6D2FE672BDE09FC74A -:1039F000D6B7D3EF6522BCE9F7720CF69BFE1ABF6F -:103A000047DC1169227B1CE0FD7DFC3D327C6FDDD3 -:103A10004AE78DDE7ED3FFC723E8F7DAE43DA10A4B -:103A2000E177FA7F89106A7A0080000000000000C8 -:103A30001F8B080000000000000BCD567D4C535733 -:103A4000143FF7BE7E53E8E31B44B08060B7157C9B -:103A500005257126FA066A4C66B4B8A13451A851FE -:103A6000192A65CC2C019739AB9DCE68B6B10415E7 -:103A7000892C8529FB675B4A249B666C6924CE6C84 -:103A8000928CC83F266CA4240BA299A16359906420 -:103A9000D39D735F9B1A3F92FDB9F7CF79F7DEF3A1 -:103AA00075CFEF77CE7B506FE29005D06C02F1ECD2 -:103AB000ED7B2D0BAC28BB25B05702F4D0E62A8055 -:103AC000135D35591127C09E4FD69FF597011430CD -:103AD000708750EF375DA4165600CCF465A71D65BE -:103AE00078EE0B94029EEFE9FBA080E44C9FB93E78 -:103AF000887AEBE4DA75A919004D17525D921DE042 -:103B0000113D6BD18F82469900FB7D35D95004D091 -:103B1000F270E453B918E31702C8E8F7AF5052D077 -:103B20008F2A2D47AE14481C40317A7395950007B3 -:103B3000F8F0B655E8E71E0B0EE40A7D7BB66C4D37 -:103B4000F87D524E1F01B01B017CEFDD167EEEF3B7 -:103B5000D1CD1EB46FF15D4E213F07CE8C57C9B851 -:103B6000FF42B1B744C924BF7D03B28477EFEE2B87 -:103B700077E33D4A1510796E4A736FF3605ED11F8B -:103B800025A5DFFEFC78CD5730E9CAC47A67D06638 -:103B900000AC9F370C0699A40C86349433127484BD -:103BA000506E2A82C6ADD6C4FEAA585D666C9D05CD -:103BB0006EDCDF3770AEC08EF26EB2B6DE31B0FDB5 -:103BC000274841FD8B4603E1E5D5814141BBDD7EC0 -:103BD000A6065142731A406E227E8D92048075DBD8 -:103BE000D78D49A527F6018262FFAE0E36521E4BD5 -:103BF0000251D75B282774E1BD84EB449B59F11730 -:103C0000124E7691CF44A7B481F6FD6F332861B48C -:103C1000BE9CBC14E337D8A08DEC935784C21C71B2 -:103C2000F60DA556481AA504BF5A656DB15EB26E71 -:103C3000C8C3F383834C36A2CB8357AF6F006D0D9F -:103C4000C09E5FCFFD0F5683FDB1BCF70F0D1AEC80 -:103C500018AFE50BBC2FC66F090DFEB008FDB45EB2 -:103C6000D955A9C5ED04A8C23CE815E3B40E6975A1 -:103C7000F10D4D19763B137E7639D24EE421B64DC7 -:103C8000A135DBCFA0DE2EC2ED6580C3E515F5477B -:103C9000979294C5BD41172D7027039C72DC327832 -:103CA000C9CFFB317F8E5B278AC47D6BD3E1313E68 -:103CB000BCA1E8855DDC1EEB21ECC23ECB49580E71 -:103CC000A0B65A7524033E6B0AC90B6DDCA1C3BABA -:103CD000AACCA24858EF0E534A39D800E6CD9A1C18 -:103CE000B668B29DBB079B30C5793E6606E47DBBD6 -:103CF000D4C948AE75B631AC34C819DEC3C4DF1CB4 -:103D0000083110850833CA7BF6BB3B95147FCD92F2 -:103D1000C89F8029E9995ABF0EF9715C9105FEE0B0 -:103D20008C5412CF33AF4123F1AB570F27CD15740D -:103D30006F376C2D232FF84EB82FF0E025CC6F98FD -:103D4000853F23FFF1FB5E25BEA21FB7D17A9261AA -:103D50009E06BBF723CA630BD397B93861209590B1 -:103D6000FF59BD760E9DE75413F2A25AA305E473E2 -:103D7000F00352D6B028C74ABC66AA0A1D18FF989D -:103D8000F3DA6EE2C7E9A8098C183710AB4775D48F -:103D900032C5502F7FD1460EE5A86FCF801D687FBA -:103DA000CDC9FD46CCF3349882A40FA6F56AC4A110 -:103DB000C57884F3C5C0CDAAD01FBEB1C050E649B6 -:103DC0007F8CD8503FAF9D2901D469989BEEFD1997 -:103DD000E50E08BAA8AE5B32BC9FD3BC999CDB3819 -:103DE000E5457C4FCB2113F5193D8FE73F7C6821DA -:103DF000258D27F29A8D4E7FF9CD0A922685A15DF9 -:103E0000F5B01436963F9DCF6C8E5D4771502FCC28 -:103E100049DFCA838C91FEC86DCAAFDA640D4B29A5 -:103E200064A7FF3D624AD8C1587EEAF44B20207E49 -:103E300094079015D0705B13EBC3382E37152E7096 -:103E4000B919C3275E3F913CF6C74193D61FDF5B8C -:103E50000776127FE2FDFA666C7FEE41918DE6CB2C -:103E6000DC70B10D9CCFEFCF719CAFB00CE75CA1C3 -:103E70003A4EB8E3A39AD07F5DAC3E8837905F2975 -:103E8000E6B72E56A73A2BD7EAF2FA137589F12432 -:103E9000CE8378DE719CE3F8C13B63D76D8502B7B2 -:103EA000B28F41E0F52BC59F5C183D8E6D058B24CC -:103EB00075CA5BF87FC42B6C5E86BC8E9EE14A3F60 -:103EC000F19F0A5F21A4CAF17EE000310F1A248B12 -:103ED00072EA19F3C04BF36039CD834ED1E7F33C5E -:103EE0007A9D339A076D629D03D1A33A5C4FF248E5 -:103EF00032E51B3123EB5116BA8AC43CCAA38E2E7D -:103F0000D670A2BEEE3D94DC7F0AF5034C3D6F42B5 -:103F1000FB803ED6EFFBACC14BB83F1BE47E3DC6F9 -:103F2000EB4A0D9E6FC2FDAEBAC58A1FEB340B3152 -:103F3000BD668B980BAB3917EBA8272BD85F48FAD7 -:103F4000D8D778CF2ECF8BE23BFEF543744EF72EB9 -:103F500001EDDC05A5DD745EEB10FEBE8DCF990F83 -:103F60009385BFAE5A35D722CEB338D91F4FF7E667 -:103F7000B93209574D0F7F04845E4F8F9A4B78F406 -:103F80006C3508BDB3CCEDD94B7ECAACCA25F41B49 -:103F9000F158BE1AD0E00833DC9FECD0EE1BE7AF3F -:103FA000A7549B834BFC53E7E93FC45F0D8E36E477 -:103FB000FD24F17079021FA6221669099CE27CF4A7 -:103FC000EB11AF0C0DAF63EC69BC326278B10EE45B -:103FD0006D0AE11612F59FE71A0EED124492F04EAB -:103FE0001257728C282732BC55DA3DC772E9BCC122 -:103FF0001859D9E9243CA139F48C3E7CC5A5F53982 -:10400000D0571479DE18E379639C8FEF3EC1C7C89F -:10401000E2D4E9A4181FD1FE178BBB86E2DD67E36B -:1040200055B439FA8F54FFAC389B5CDA7FC99CD108 -:10403000FB2AE9C3C56C2EE688ACF5F5A8EB4E3E2D -:104040007D67E0EF91C5F4DDE94D776F263DF3D252 -:10405000A8C14BF5CC8DEAE93E939E7BF9F43FD3A2 -:10406000D87143F4CD7FCDF35F8E8A94E2B00A001D -:104070000000000000000000000000180000000028 -:1040800000000000000000400000000000000000F0 -:1040900000000028000000000000000000000010E8 -:1040A00000000000000000000000002000000000F0 -:1040B00000000000000000100000000000000000F0 -:1040C00000000008000000000000000000000000E8 -:1040D00000000000000000000000000000000000E0 -:1040E00000000000000000000000000000000000D0 -:1040F00000000000000000000000000000000000C0 -:1041000000000000000000000000000000000000AF -:10411000000000000000000000000000000000009F -:10412000000000000000000000000000000000008F -:10413000000000000000000000000000000000007F -:10414000000000000000000000000000000000006F -:10415000000000000000000000000000000000005F -:10416000000000000000000000000000000000004F -:10417000000000000000000000000000000000003F -:10418000000000000000000000000000000000002F -:10419000000000000000000000000000000000001F -:1041A000000000000000000000000000000000000F -:1041B00000000000000000000000000000000000FF -:1041C00000000000000000000000000000000000EF -:1041D00000000000000000000000000000000000DF -:1041E00000003328001000000000000800003330F9 -:1041F0000010000000000002000033280010000042 -:104200000000001000003A780000000000000008E4 -:10421000800000000000000000000000800000009E -:10422000000000000000000080000000000000000E -:104230000000000000003120000000000000000825 -:10424000000033600001000400000001000033683A -:1042500000000000000000020000337000000000B9 -:10426000000000080000337400000000000000029D -:1042700000003A70000000000000000800003A4012 -:10428000000800000000000800003D880040000019 -:104290000000004000003A50000800000000000844 -:1042A00000003A60000800000000000800003A88A2 -:1042B00000C800000000009800003C1800980000B2 -:1042C0000000002800003C58009800000000002872 -:1042D00000003378036000300000036000003EB04F -:1042E000000800000000000100003EB100080000CE -:1042F0000000000100002008001000000000001075 -:104300000000200000000000000000088000000005 -:10431000000000000000000080000000000000001D -:10432000000000000000000000000000000000008D -:10433000000000000000000000000000000000007D -:1043400000000000000000008000000000000000ED -:1043500000000000800000000000000000000000DD -:10436000800000000000000000000000800000004D -:1043700000000000000000008000000000000000BD -:1043800000000000800000000000000000000000AD -:10439000800000000000000000000000800000001D -:1043A000000000000000000080000000000000008D -:1043B000000000008000000000000000000000007D -:1043C00080000000000000000000000080000000ED -:1043D000000000000000000080000000000000005D -:1043E00000000000000000000000000000000000CD -:1043F00000000000000000000000000000000000BD -:1044000000000000000000000000000000000000AC -:10441000000000000000000000000000000000009C -:10442000800000000000000000000000800000008C -:1044300000000000000000008000000000000000FC -:10444000000000000000000000000000000000006C -:10445000800000000000000000000000800000005C -:1044600000000000000000008000000000000000CC -:10447000000000000000000000000000000000003C -:10448000000000000000000000000000000000002C -:10449000000000000000000000000000000000001C -:1044A000000000000000000000000000000000000C -:1044B000000000000000000000000000000012C822 -:1044C00000800000000000800000000100000000EB -:1044D0000000000000004000049000000000049074 -:1044E000000019C800000000000000080000494852 -:1044F0000008000000000008000049280008000033 -:104500000000000800004938000800000000000812 -:104510000000200800100000000000100000200033 -:10452000000000000000000800004010049000405F -:104530000000004000004998000800000000000151 -:104540000000499900080000000000018000000000 -:1045500000000000000000008000000000000000DB -:1045600000000000800000000000000000000000CB -:10457000800000000000000000000000800000003B -:1045800000000000000000008000000000000000AB -:10459000000000008000000000000000000000009B -:1045A000800000000000000000000000800000000B -:1045B000000000000000000080000000000000007B -:1045C000000000008000000000000000000000006B -:1045D00080000000000000000000000080000000DB -:1045E00000000000000000000000000000000000CB -:1045F00000000000000000000000000000000000BB -:1046000000000000000000000000000000000000AA -:10461000000000000000000000000000000000009A -:10462000000000008000000000000000000000000A -:1046300080000000000000000000000000000000FA -:1046400000000000000000008000000000000000EA -:1046500000000000800000000000000000000000DA -:10466000800000000000000000000000800000004A -:1046700000000000000000000000400000180000E2 -:10468000000000180000430000400000000000404F -:104690000000430000400002000000010000430150 -:1046A0000040000200000000000030000040000058 -:1046B000000000408000000000000000000000003A -:1046C000000030000008004000000004000030043A -:1046D000000800400000000400004B00002800001B -:1046E0000000002800004B500010000000000010E7 -:1046F000000038000080000000000080000038004A -:1047000000080080000000020000390000200000C6 -:104710000000002000002008001000000000001031 -:104720000000200000000000000000080000510808 -:1047300000080000000000080000512000080000F0 -:1047400000000008000051300008000000000008D0 -:10475000000051C00008000000000001000051C12D -:1047600000080000000000010000394000100004B3 -:1047700000000004000051D00030001800000010BC -:10478000000051D800300018000000028000000036 -:104790000000000000000000800000000000000099 -:1047A0000000000080000000000000000000000089 -:1047B00080000000000000000000000080000000F9 -:1047C0000000000000000000800000000000000069 -:1047D0000000000080000000000000000000000059 -:1047E00080000000000000000000000080000000C9 -:1047F00000000000000000000000000000000000B9 -:1048000000000000000000000000000000000000A8 -:104810000000000000000000000000000000000098 -:104820000000000000000000800000000000000008 -:1048300000000000800000000000000000000000F8 -:10484000000000000000000000000000000023E85D -:104850000080000000000080000000010000000057 -:104860000000000000002008001000000000001000 -:1048700000002000000000000000000800002DA043 -:10488000000800000000000800002DB8000800002B -:1048900000000008000024E802D00028000002D038 -:1048A00000002E58000800000000000100002E59F2 -:1048B000000800000000000100002D90000800002A -:1048C0000000000880000000000000000000000060 -:1048D00080000000000000000000000080000000D8 -:1048E0000000000000000000800000000000000048 -:1048F0000000000080000000000000000000000038 -:1049000080000000000000000000000080000000A7 -:104910000000000000000000000000000000000097 -:104920000000000000000000000000000000000087 -:104930000000000000000000000000000000000077 -:1049400000000000000000008000000000000000E7 -:1049500000000000800000000000000000000000D7 -:1049600000000000000000000000000080000000C7 -:1049700000000000000000008000000000000000B7 -:1049800000000000800000000000000000000000A7 -:104990008000000000000000000000000000250072 -:1049A0000040000000000008000025080040000052 -:1049B00000000028000009C00120001000000008CD -:1049C00080000000000000000000000080000000E7 -:1049D00000000000000000000000402002D000287D -:1049E000000000080000300000000000000010007F -:1049F000000050990000000000000001000050B0CD -:104A00000000000000000002000045A00090000827 -:104A1000000000088000000000000000000000000E -:104A2000000029600008000000000001000029616A -:104A300000080000000000010000297000080004C8 -:104A400000000002000029780008000400000004B3 -:104A500000002FB0000800000000000400002FB488 -:104A6000000800000000000400002FC0000000004B -:104A70000000000800002FC800000000000000082F -:104A80000000300000000000000000100000504056 -:104A900000010001000000010000500000000000C3 -:104AA00000000020000008080010000000000004C2 -:104AB0000000080C0010000000000001000008B712 -:104AC0000000000000000001000008B60000000027 -:104AD0000000000100001000003000180000000479 -:104AE000000010040030001800000004000010084E -:104AF00000300018000000020000100A003000180A -:104B0000000000020000100C00300018000000013E -:104B10000000100D00300018000000010000100E11 -:104B200000300018000000010000101000300018D4 -:104B30000000000400001014003000180000000401 -:104B40000000300001000080000800040000300474 -:104B500001000080000800040000000A00000000BE -:104B6000000000000000306801000080000000012B -:104B70000000306901000080000000010000306C7E -:104B800001000080000000020000306E0100008083 -:104B900000000002000030700100008000000004EE -:104BA0000000307401000080000000040000306646 -:104BB000010000800000000200003064010000805D -:104BC00000000001000030600100008000000002D1 -:104BD0000000306201000080000000020000305040 -:104BE000010000800000000400003054010000803B -:104BF00000000004000030580100008000000004A4 -:104C00000000305C01000080000000040000307CE7 -:104C100001000080000000010000307D01000080E4 -:104C20000000000100001C1800100000000000043B -:104C300000001C30001000000000000400001C38C0 -:104C400000100000000000048000000000000000D0 -:104C500000000000800000000000000000000000D4 -:104C60008000000000000000000000008000000044 -:104C7000000000000000000000004C1000080000D0 -:104C80000000000200004C120008000000000002BA -:104C900000004C14000800000000000400004C203C -:104CA000000800000000000800004C300040000830 -:104CB0000000000800004C00000800000000000296 -:104CC00000004C02000800000000000100004C043D -:104CD000000800000000000200004CD000080000A6 -:104CE0000000000800004CE0000800000000000484 -:104CF00000004CE4000800000000000100004CF03F -:104D0000000800000000000200004CF40008000051 -:104D10000000000200004D00000800000000000438 -:104D200000005000001000000000000400005004CB -:104D300000100000000000040000500800100000F7 -:104D40000000000400001400000800000000000241 -:104D5000000014020008000000000001000014041C -:104D6000000800000000000200001410000800000D -:104D700000000002000014140008000000000002FF -:104D8000000014160008000000000002000019B81E -:104D900000080000000000080000142000080000C7 -:104DA00000000002000014240008000000000002BF -:104DB000000019C8000800000000000800002C10C6 -:104DC000000800000000000100002C110008000095 -:104DD0000000000100002C1200080000000000018B -:104DE00000002C13000800000000000100002C004F -:104DF000000800000000000200002C020008000073 -:104E00000000000100002C04000800000000000267 -:104E100000002C30000800000000000200002C32CE -:104E2000000800000000000200002C340008000010 -:104E30000000000200002C2000080000000000011B -:104E400000002C21000800000000000100002C22BE -:104E5000000800000000000100002C2300080000F2 -:104E60000000000100002C240008000000000001E8 -:104E700000002C25000800000000000100002C2686 -:104E800000080000000000010000140000080000FD -:104E900000000002000014020008000000000001F1 -:104EA00000001404000800000000000200001412BA -:104EB00000C00018000000020000141000C000181C -:104EC000000000020000141C00C0001800000008D0 -:104ED0000000141400C0001800000008000014278F -:104EE00000C00018000000010000142400C00018D9 -:104EF000000000020000142600C00018000000019D -:104F0000000015900008000000000008000015A037 -:104F10000008000000000008000015B000080000B4 -:104F200000000008800000000000000000000000F9 -:104F30008000000000000000000000008000000071 -:104F400000000000000000008000000000000000E1 -:104F500000000000800000000000000000000000D1 -:104F60008000000000000000000000008000000041 -:104F700000000000000000008000000000000000B1 -:104F800000000000800000000000000000000000A1 -:104F90008000000000000000000000008000000011 -:104FA0000000000000000000800000000000000081 -:104FB0000000000080000000000000000000000071 -:104FC00080000000000000000000000080000000E1 -:104FD0000000000000000000800000000000000051 -:104FE0000000000080000000000000000000000041 -:104FF00080000000000000000000000080000000B1 -:105000000000000000000000800000000000000020 -:105010000000000080000000000000000000000010 -:105020008000000000000000000000008000000080 -:1050300000000000000000008000000000000000F0 -:1050400000000000800000000000000000000000E0 -:1050500080000000000000000000000000000000D0 -:1050600000000000000000008000000000000000C0 -:105070000000000000000000060205000000000023 -:00000001FF diff --git a/firmware/bnx2x/bnx2x-e1-6.2.9.0.fw.ihex b/firmware/bnx2x/bnx2x-e1-6.2.9.0.fw.ihex new file mode 100644 index 000000000000..0ed7f5891184 --- /dev/null +++ b/firmware/bnx2x/bnx2x-e1-6.2.9.0.fw.ihex @@ -0,0 +1,9484 @@ +:1000000000003BB0000000680000070C00003C202E +:1000100000001AF8000043300000007C00005E3051 +:1000200000007A2C00005EB0000000B00000D8E0B4 +:10003000000080200000D99800000088000159C00D +:100040000000398800015A5000000090000193E040 +:100050000000AC040001947800000FFC0002408016 +:100060000000000400025080020400480000000F5D +:100070000204005400000045020400580000000083 +:100080000204005C0000000602040070000000048E +:1000900002040078000000000204007C1217000037 +:1000A00002040080221700000204008432170000BE +:1000B00006040088000000050204009C12150000E0 +:1000C000020400A022150000020400A43215000062 +:1000D000060400A800000004020400B8021000009A +:1000E000020400BC00100000020400C01010000058 +:1000F000020400C420100000020400C830100000F8 +:10010000060400CC00000004020400DC0010000023 +:10011000020400E012140000020400E422140000B3 +:10012000020400E832140000060400EC00000004A1 +:100130000104012400000000010401280000000067 +:100140000104012C00000000010401300000000047 +:1001500002040004000000FF02040008000000FF89 +:100160000204000C000000FF02040010000000FF69 +:1001700002040014000000FF02040018000000FF49 +:100180000204001C000000FF02040020000000FF29 +:10019000020400240000003E0204002800000000C9 +:1001A0000204002C0000003F020400300000003F69 +:1001B000020400340000003F020400380000000088 +:1001C0000204003C0000003F020400400000003F29 +:1001D000020400440000003F020420080000021155 +:1001E0000204200C0000020002042010000002049F +:1001F00002042014000002190204201C0000FFFF6A +:10020000020420200000FFFF020420240000FFFF62 +:10021000020420280000FFFF0604203800000080B0 +:100220000204223807FFFFFF0204223C0000003FC7 +:100230000204224007FFFFFF020422440000000FD7 +:1002400001042248000000000104224C00000000CC +:1002500001042250000000000104225400000000AC +:1002600001042258000000000104225C000000008C +:10027000010422600000000001042264000000006C +:1002800001042268000000000104226C000000004C +:10029000010422700000000001042274000000002C +:1002A00001042278000000000104227C000000000C +:1002B000020424BC000000010C042000000003E83C +:1002C0000A042000000000010B0420000000000AC6 +:1002D0000605400000000D0002050044000000205B +:1002E00002050048000000320205009002150020BF +:1002F000020500940215002002050098000000305D +:100300000205009C08100000020500A00000003358 +:10031000020500A400000030020500A80000003122 +:10032000020500AC00000002020500B0000000055C +:10033000020500B400000006020500B8000000023B +:10034000020500BC00000002020500C00000000021 +:10035000020500C400000005020500C800000002FC +:10036000020500CC00000002020500D000000002DF +:10037000020500D400000001020501140000000184 +:100380000205011C0000000102050120000000021E +:1003900002050204000000010205020C00000040FA +:1003A00002050210000000400205021C00000020AF +:1003B00002050220000000130205022400000020B4 +:1003C000060502400000000A04050280002000002B +:1003D000020500500000000702050054000000075D +:1003E00002050058000000000205005C0000000843 +:1003F0000605006000000004020500D800000006A9 +:10040000020500E00000000D020500E40000002DE0 +:10041000020500E800000000020500EC00000020DA +:10042000020500F000000000020500F400000020BA +:10043000020500F800000000020500FC000000209A +:100440000205000400000001020500080000000190 +:100450000205000C00000001020500100000000170 +:100460000205001400000001020500180000000150 +:100470000205001C00000001020500200000000130 +:100480000205002400000001020500280000000110 +:100490000205002C000000010205003000000001F0 +:1004A00002050034000000010205003800000001D0 +:1004B0000205003C000000010205004000000001B0 +:1004C0000406100002000020020600DC000000010B +:1004D000010600D80000000004060200000302200C +:1004E000020600DC0000000002060068000000B800 +:1004F0000206007800000114010600B800000000A8 +:10050000010600C8000000000206006C000000B8F0 +:100510000206007C00000114010600BC000000007F +:10052000010600CC0000000007180400007B00005A +:100530000818076000140223071C00002A040000AA +:10054000071C800032110A82071D00001E0C1707CD +:10055000081D4550575602250118000000000000F4 +:10056000011800040000000001180008000000004D +:100570000118000C0000000001180010000000002D +:100580000118001400000000021800200000000103 +:1005900002180024000000020218002800000003D6 +:1005A0000218002C000000000218003000000004B7 +:1005B000021800340000000102180038000000009A +:1005C0000218003C00000001021800400000000476 +:1005D000021800440000000002180048000000015A +:1005E0000218004C00000003021800500000000038 +:1005F0000218005400000001021800580000000416 +:100600000218005C000000000218006000000001F9 +:1006100002180064000000030218006800000000D7 +:100620000218006C000000010218007000000004B5 +:100630000218007400000000021800780000000496 +:100640000218007C00000003061800800000000271 +:10065000021800A400003FFF021800A8000003FFDA +:1006600002180224000000000218023400000000FA +:100670000218024C00000000021802E4000000FF13 +:100680000618100000000400021B8BC000000001CF +:10069000021B800000000034021B80400000001894 +:1006A000021B80800000000C021B80C000000020A4 +:1006B0000C1B83000007A1200A1B830000000138E7 +:1006C0000B1B8300000013880A1B834000000000FE +:1006D0000C1B8340000001F40B1B8340000000054D +:1006E000021B83800007A120021B83C0000001F4CD +:1006F000061A100000000273041A19CC0001022728 +:10070000061A2008000000C8061A20000000000297 +:10071000041A499800040228061A2E280000000234 +:10072000061A2E2000000002061A0800000000022F +:10073000061A080800000004061A08180000000243 +:10074000041A08B00002022C061A2FD0000000067E +:10075000041A2FE80002022E041A2FC000040230EF +:10076000041A300000010234061A300400000003AD +:10077000041A301000010235061A3014000000037C +:10078000041A302000010236061A3024000000034B +:10079000041A303000010237061A3034000000031A +:1007A000041A304000010238061A304400000003E9 +:1007B000041A305000010239061A305400000003B8 +:1007C000041A30600001023A061A30640000000387 +:1007D000041A30700001023B061A30740000000356 +:1007E000041A30800001023C061A30840000000325 +:1007F000041A30900001023D061A309400000003F4 +:10080000041A30A00001023E061A30A400000003C2 +:10081000041A30B00001023F061A30B40000000391 +:10082000041A30C000010240061A30C40000000360 +:10083000041A30D000010241061A30D4000000032F +:10084000041A30E000010242061A30E400000003FE +:10085000041A30F000010243061A30F400000003CD +:10086000041A310000010244061A3104000000039A +:10087000041A311000010245061A31140000000369 +:10088000041A312000010246061A31240000000338 +:10089000041A313000010247061A31340000000307 +:1008A000041A314000010248061A314400000003D6 +:1008B000041A315000010249061A315400000003A5 +:1008C000041A31600001024A061A31640000000374 +:1008D000041A31700001024B061A31740000000343 +:1008E000041A31800001024C061A31840000000312 +:1008F000041A31900001024D061A319400000003E1 +:10090000041A31A00001024E061A31A400000003AF +:10091000041A31B00001024F061A31B4000000037E +:10092000041A31C000010250061A31C4000000034D +:10093000041A31D000010251061A31D4000000031C +:10094000041A31E000010252061A31E400000003EB +:10095000041A31F000010253061A31F400000003BA +:10096000041A320000010254061A32040000000387 +:10097000041A321000010255061A32140000000356 +:10098000041A322000010256061A32240000000325 +:10099000041A323000010257061A323400000003F4 +:1009A000041A324000010258061A324400000003C3 +:1009B000041A325000010259061A32540000000392 +:1009C000041A32600001025A061A32640000000361 +:1009D000041A32700001025B061A32740000000330 +:1009E000041A32800001025C061A328400000003FF +:1009F000041A32900001025D061A329400000003CE +:100A0000041A32A00001025E061A32A4000000039C +:100A1000041A32B00001025F061A32B4000000036B +:100A2000041A32C000010260061A32C4000000033A +:100A3000041A32D000010261061A32D40000000309 +:100A4000041A32E000010262061A32E400000003D8 +:100A5000041A32F000010263061A32F400000003A7 +:100A6000041A330000010264061A33040000000374 +:100A7000041A331000010265061A33140000000343 +:100A8000041A332000010266061A33240000000312 +:100A9000041A333000010267061A333400000003E1 +:100AA000041A334000010268061A334400000003B0 +:100AB000041A335000010269061A3354000000037F +:100AC000041A33600001026A061A3364000000034E +:100AD000041A33700001026B061A3374000000031D +:100AE000041A33800001026C061A338400000003EC +:100AF000041A33900001026D061A339400000003BB +:100B0000041A33A00001026E061A33A40000000389 +:100B1000041A33B00001026F061A33B40000000358 +:100B2000041A33C000010270061A33C40000000327 +:100B3000041A33D000010271061A33D400000003F6 +:100B4000041A33E000010272061A33E400000003C5 +:100B5000041A33F000010273061A33F40000000394 +:100B6000041A340000010274061A34040000000361 +:100B7000041A341000010275061A34140000000330 +:100B8000041A342000010276061A342400000003FF +:100B9000041A343000010277061A343400000003CE +:100BA000041A344000010278061A3444000000039D +:100BB000041A345000010279061A3454000000036C +:100BC000041A34600001027A061A3464000000033B +:100BD000041A34700001027B061A3474000000030A +:100BE000041A34800001027C061A348400000003D9 +:100BF000041A34900001027D061A349400000003A8 +:100C0000041A34A00001027E061A34A40000000376 +:100C1000041A34B00001027F061A34B40000000345 +:100C2000041A34C000010280061A34C40000000314 +:100C3000041A34D000010281061A34D400000003E3 +:100C4000041A34E000010282061A34E400000003B2 +:100C5000041A34F000010283061A34F40000000381 +:100C6000041A350000010284061A3504000000034E +:100C7000041A351000010285061A3514000000031D +:100C8000041A352000010286061A352400000003EC +:100C9000041A353000010287061A353400000003BB +:100CA000041A354000010288061A3544000000038A +:100CB000041A355000010289061A35540000000359 +:100CC000041A35600001028A061A35640000000328 +:100CD000041A35700001028B061A357400000003F7 +:100CE000041A35800001028C061A358400000003C6 +:100CF000041A35900001028D061A35940000000395 +:100D0000041A35A00001028E061A35A40000000363 +:100D1000041A35B00001028F061A35B40000000332 +:100D2000041A35C000010290061A35C40000000301 +:100D3000041A35D000010291061A35D400000003D0 +:100D4000041A35E000010292061A35E4000000039F +:100D5000041A35F000010293061A35F4000000036E +:100D6000041A360000010294061A3604000000033B +:100D7000041A361000010295061A3614000000030A +:100D8000041A362000010296061A362400000003D9 +:100D9000041A363000010297061A363400000003A8 +:100DA000041A364000010298061A36440000000377 +:100DB000041A365000010299061A36540000000346 +:100DC000041A36600001029A061A36640000000315 +:100DD000041A36700001029B061A367400000003E4 +:100DE000041A36800001029C061A368400000003B3 +:100DF000041A36900001029D061A36940000000382 +:100E0000041A36A00001029E061A36A40000000350 +:100E1000041A36B00001029F061A36B4000000031F +:100E2000041A36C0000102A0061A36C400000003EE +:100E3000041A36D0000102A1061A36D400000003BD +:100E4000041A36E0000102A2061A36E4000000038C +:100E5000041A36F0000102A3061A36F4000000035B +:100E6000041A3700000102A4061A37040000000328 +:100E7000041A3710000102A5061A371400000003F7 +:100E8000041A3720000102A6061A372400000003C6 +:100E9000041A3730000102A7061A37340000000395 +:100EA000041A3740000102A8061A37440000000364 +:100EB000041A3750000102A9061A37540000000333 +:100EC000041A3760000102AA061A37640000000302 +:100ED000041A3770000102AB061A377400000003D1 +:100EE000041A3780000102AC061A378400000003A0 +:100EF000041A3790000102AD061A3794000000036F +:100F0000041A37A0000102AE061A37A4000000033D +:100F1000041A37B0000102AF061A37B4000000030C +:100F2000041A37C0000102B0061A37C400000003DB +:100F3000041A37D0000102B1061A37D400000003AA +:100F4000041A37E0000102B2061A37E40000000379 +:100F5000041A37F0000102B3061A37F40000000348 +:100F6000041A3800000102B4061A38040000000315 +:100F7000041A3810000102B5061A381400000003E4 +:100F8000041A3820000102B6061A382400000003B3 +:100F9000041A3830000102B7061A38340000000382 +:100FA000041A3840000102B8061A38440000000351 +:100FB000041A3850000102B9061A38540000000320 +:100FC000041A3860000102BA061A386400000003EF +:100FD000041A3870000102BB061A387400000003BE +:100FE000041A3880000102BC061A3884000000038D +:100FF000041A3890000102BD061A3894000000035C +:10100000041A38A0000102BE061A38A4000000032A +:10101000041A38B0000102BF061A38B400000003F9 +:10102000041A38C0000102C0061A38C400000003C8 +:10103000041A38D0000102C1061A38D40000000397 +:10104000041A38E0000102C2061A38E40000000366 +:10105000041A38F0000102C3061A38F40000000335 +:10106000041A3900000102C4061A39040000000302 +:10107000041A3910000102C5061A391400000003D1 +:10108000041A3920000102C6061A392400000003A0 +:10109000041A3930000102C7061A3934000000036F +:1010A000041A3940000102C8061A3944000000033E +:1010B000041A3950000102C9061A3954000000030D +:1010C000041A3960000102CA061A396400000003DC +:1010D000041A3970000102CB061A397400000003AB +:1010E000041A3980000102CC061A3984000000037A +:1010F000041A3990000102CD061A39940000000349 +:10110000041A39A0000102CE061A39A40000000317 +:10111000041A39B0000102CF061A39B400000003E6 +:10112000041A39C0000102D0061A39C400000003B5 +:10113000041A39D0000102D1061A39D40000000384 +:10114000041A39E0000102D2061A39E40000000353 +:10115000041A39F0000102D3061A39F40000000322 +:10116000041A3A00000102D4061A3A0400000003EF +:10117000041A3A10000102D5061A3A1400000003BE +:10118000041A3A20000102D6061A3A24000000038D +:10119000041A3A30000102D7061A3A34000000035C +:1011A000041A3A40000102D8061A3A44000000032B +:1011B000041A3A50000102D9061A3A5400000003FA +:1011C000041A3A60000102DA061A3A6400000003C9 +:1011D000041A3A70000102DB061A3A740000000398 +:1011E000041A3A80000102DC061A3A840000000367 +:1011F000041A3A90000102DD061A3A940000000336 +:10120000041A3AA0000102DE061A3AA40000000304 +:10121000041A3AB0000102DF061A3AB400000003D3 +:10122000041A3AC0000102E0061A3AC400000003A2 +:10123000041A3AD0000102E1061A3AD40000000371 +:10124000041A3AE0000102E2061A3AE40000000340 +:10125000041A3AF0000102E3061A3AF4000000030F +:10126000041A3B00000102E4061A3B0400000003DC +:10127000041A3B10000102E5061A3B1400000003AB +:10128000041A3B20000102E6061A3B24000000037A +:10129000041A3B30000102E7061A3B340000000349 +:1012A000041A3B40000102E8061A3B440000000318 +:1012B000041A3B50000102E9061A3B5400000003E7 +:1012C000041A3B60000102EA061A3B6400000003B6 +:1012D000041A3B70000102EB061A3B740000000385 +:1012E000041A3B80000102EC061A3B840000000354 +:1012F000041A3B90000102ED061A3B940000000323 +:10130000041A3BA0000102EE061A3BA400000003F1 +:10131000041A3BB0000102EF061A3BB400000003C0 +:10132000041A3BC0000102F0061A3BC4000000038F +:10133000041A3BD0000102F1061A3BD4000000035E +:10134000041A3BE0000102F2061A3BE4000000032D +:10135000041A3BF0000102F3061A3BF400000003FC +:10136000041A3C00000102F4061A3C0400000003C9 +:10137000041A3C10000102F5061A3C140000000398 +:10138000041A3C20000102F6061A3C240000000367 +:10139000041A3C30000102F7061A3C340000000336 +:1013A000041A3C40000102F8061A3C440000000305 +:1013B000041A3C50000102F9061A3C5400000003D4 +:1013C000041A3C60000102FA061A3C6400000003A3 +:1013D000041A3C70000102FB061A3C740000000372 +:1013E000041A3C80000102FC061A3C840000000341 +:1013F000041A3C90000102FD061A3C940000000310 +:10140000041A3CA0000102FE061A3CA400000003DE +:10141000041A3CB0000102FF061A3CB400000003AD +:10142000041A3CC000010300061A3CC4000000037B +:10143000041A3CD000010301061A3CD4000000034A +:10144000041A3CE000010302061A3CE40000000319 +:10145000041A3CF000010303061A3CF400000003E8 +:10146000041A3D0000010304061A3D0400000003B5 +:10147000041A3D1000010305061A3D140000000384 +:10148000041A3D2000010306061A3D240000000353 +:10149000041A3D3000010307061A3D340000000322 +:1014A000041A3D4000010308061A3D4400000003F1 +:1014B000041A3D5000010309061A3D5400000003C0 +:1014C000041A3D600001030A061A3D64000000038F +:1014D000041A3D700001030B061A3D74000000035E +:1014E000041A3D800001030C061A3D84000000032D +:1014F000041A3D900001030D061A3D9400000003FC +:10150000041A3DA00001030E061A3DA400000003CA +:10151000041A3DB00001030F061A3DB40000000399 +:10152000041A3DC000010310061A3DC40000000368 +:10153000041A3DD000010311061A3DD40000000337 +:10154000041A3DE000010312061A3DE40000000306 +:10155000041A3DF000010313061A3DF400000003D5 +:10156000041A3E0000010314061A3E0400000003A2 +:10157000041A3E1000010315061A3E140000000371 +:10158000041A3E2000010316061A3E240000000340 +:10159000041A3E3000010317061A3E34000000030F +:1015A000041A3E4000010318061A3E4400000003DE +:1015B000041A3E5000010319061A3E5400000003AD +:1015C000041A3E600001031A061A3E64000000037C +:1015D000041A3E700001031B061A3E74000000034B +:1015E000041A3E800001031C061A3E84000000031A +:1015F000041A3E900001031D061A3E9400000003E9 +:10160000041A3EA00001031E061A3EA400000003B7 +:10161000041A3EB00001031F061A3EB40000000386 +:10162000041A3EC000010320061A3EC40000000355 +:10163000041A3ED000010321061A3ED40000000324 +:10164000041A3EE000010322061A3EE400000003F3 +:10165000041A3EF000010323061A3EF400000003C2 +:10166000041A3F0000010324061A3F04000000038F +:10167000041A3F1000010325061A3F14000000035E +:10168000041A3F2000010326061A3F24000000032D +:10169000041A3F3000010327061A3F3400000003FC +:1016A000041A3F4000010328061A3F4400000003CB +:1016B000041A3F5000010329061A3F54000000039A +:1016C000041A3F600001032A061A3F640000000369 +:1016D000041A3F700001032B061A3F740000000338 +:1016E000041A3F800001032C061A3F840000000307 +:1016F000041A3F900001032D061A3F9400000003D6 +:10170000041A3FA00001032E061A3FA400000003A4 +:10171000041A3FB00001032F061A3FB40000000373 +:10172000041A3FC000010330061A3FC40000000342 +:10173000041A3FD000010331061A3FD40000000311 +:10174000041A3FE000010332061A3FE400000007DC +:10175000041A4CB000080333061A400000000124AC +:10176000021A492000000000061A2500000000109F +:10177000061A258000000012061A09C00000004861 +:10178000061A080000000002061A082000000012D5 +:10179000041A2FB00002033B041A4CF00002033D70 +:1017A000061A500000000004061A449000000124AC +:1017B000021A492400000000061A2540000000100B +:1017C000061A25C800000012061A0AE000000048A8 +:1017D000061A081000000002061A0868000000122D +:1017E000041A2FB80002033F041A4CF80002034108 +:1017F000061A5010000000040200A468000AFFDC72 +:101800000200A280000000010200A294071D29111D +:101810000200A298000000000200A29C009C042488 +:101820000200A2A0000000000200A2A40000020921 +:101830000200A4FCFF000000020100B4000000014F +:10184000020100B800000001020100DC00000001FC +:10185000020101000000000102010104000000017A +:101860000201007C0030000002010084000000281A +:101870000201008C000000000201013000000004A1 +:101880000201025C000000010201032800000000C8 +:101890000201055400000030020100C400000001F4 +:1018A000020100CC00000001020100F8000000016C +:1018B000020100F000000001020100800030000081 +:1018C00002010088000000280201009000000000D2 +:1018D0000201013400000004020102DC00000001EA +:1018E0000201032C0000000002010564000000302A +:1018F000020100C800000001020100D00000000148 +:10190000020100FC00000001020100F400000001DF +:10191000020C100000000028020C200800000A1130 +:10192000020C200C00000A00020C201000000A0427 +:10193000020C201C0000FFFF020C20200000FFFF13 +:10194000020C20240000FFFF020C20280000FFFFF3 +:10195000020C203800000020020C203C0000002176 +:10196000020C204000000022020C20440000002352 +:10197000020C204800000024020C204C000000252E +:10198000020C205000000026020C2054000000270A +:10199000020C205800000028020C205C00000029E6 +:1019A000020C20600000002A020C20640000002BC2 +:1019B000020C20680000002C020C206C0000002D9E +:1019C000020C20700000002E020C20740000002F7A +:1019D000020C207800000010060C207C0000004F54 +:1019E000020C21B800000001020C21BC0000000123 +:1019F000020C21C000000001020C21C40000000103 +:101A0000020C21C800000001020C21CC00000001E2 +:101A1000020C21D000000001020C21D400000001C2 +:101A2000020C21D800000001020C21DC00000001A2 +:101A3000020C21E000000001020C21E40000000182 +:101A4000020C21E800000001020C21EC0000000162 +:101A5000020C21F000000001020C21F40000000142 +:101A6000020C21F800000001060C21FC0000000F10 +:101A7000020C223807FFFFFF020C223C0000003F4F +:101A8000020C224007FFFFFF020C22440000000F5F +:101A9000010C224800000000010C224C0000000054 +:101AA000010C225000000000010C22540000000034 +:101AB000010C225800000000010C225C0000000014 +:101AC000010C226000000000010C226400000000F4 +:101AD000010C226800000000010C226C00000000D4 +:101AE000010C227000000000010C227400000000B4 +:101AF000010C227800000000010C227C0000000094 +:101B0000020C24BC000000010C0C2000000003E8C3 +:101B10000A0C2000000000010B0C20000000000A4D +:101B2000020C400800000562020C400C0000055148 +:101B3000020C401000000555020C40140000057214 +:101B4000020C401C0000FFFF020C40200000FFFFC1 +:101B5000020C40240000FFFF020C40280000FFFFA1 +:101B6000020C403800000046020C403C0000000C13 +:101B7000060C40400000005E020C41B8000000016D +:101B8000060C41BC0000001F020C423807FFFFFF9B +:101B9000020C423C0000003F020C424007FFFFFFE6 +:101BA000020C42440000000F010C424800000000FB +:101BB000010C424C00000000010C425000000000EB +:101BC000010C425400000000010C425800000000CB +:101BD000010C425C00000000010C426000000000AB +:101BE000010C426400000000010C4268000000008B +:101BF000010C426C00000000010C4270000000006B +:101C0000010C427400000000010C4278000000004A +:101C1000010C427C00000000010C4280000000002A +:101C2000020C44C0000000010C0C4000000003E85E +:101C30000A0C4000000000010B0C40000000000AEC +:101C4000060D400000000A00020D004400000032B2 +:101C5000020D008C02150020020D009002150020DC +:101C6000020D009408100000020D009800000033DF +:101C7000020D009C00000002020D00A00000000008 +:101C8000020D00A400000005020D00A800000005E0 +:101C9000060D00AC00000002020D00B400000002BE +:101CA000020D00B800000003020D00BC000000029D +:101CB000020D00C000000001020D00C8000000027B +:101CC000020D00CC00000002020D015C00000001CA +:101CD000020D016400000001020D01680000000215 +:101CE000020D020400000001020D020C00000020A1 +:101CF000020D021000000040020D0214000000401E +:101D0000020D022000000003020D02240000001852 +:101D1000060D028000000012040D030000180343AA +:101D2000060D03600000000C020D004C00000001D5 +:101D3000020D005000000002020D005400000000DF +:101D4000020D005800000008060D005C00000004B1 +:101D5000020D00C400000004020D0114000000097F +:101D6000020D011800000029020D011C0000000AEC +:101D7000020D01200000002A020D012400000000D5 +:101D8000020D012800000020020D012C00000000BF +:101D9000020D013000000020020D0134000000009F +:101DA000020D013800000020020D013C000000007F +:101DB000020D014000000020020D0144000000005F +:101DC000020D014800000020020D00040000000187 +:101DD000020D000800000001020D000C00000001CF +:101DE000020D001000000001020D001400000001AF +:101DF000020D001800000001020D001C000000018F +:101E0000020D002000000001020D0024000000016E +:101E1000020D002800000001020D002C000000014E +:101E2000020D003000000001020D0034000000012E +:101E3000020D003800000001020D003C000000010E +:101E4000060E200000000800020E004C00000032C8 +:101E5000020E009402150020020E009802150020C8 +:101E6000020E009C00000030020E00A008100000CE +:101E7000020E00A400000033020E00A80000003093 +:101E8000020E00AC00000031020E00B000000002A3 +:101E9000020E00B400000004020E00B800000000B2 +:101EA000020E00BC00000002020E00C00000000292 +:101EB000020E00C400000000020E00C80000000274 +:101EC000020E00CC00000007020E00D0000000024D +:101ED000020E00D400000002020E00D80000000133 +:101EE000020E014400000001020E014C000000013E +:101EF000020E015000000002020E02040000000168 +:101F0000020E020C00000040020E02100000004011 +:101F1000020E021C00000004020E0220000000203D +:101F2000020E02240000000E020E02280000001B18 +:101F3000060E030000000012040E0280001B035B6B +:101F4000060E02EC00000005020E00540000000C1A +:101F5000020E00580000000C020E005C00000000A1 +:101F6000020E006000000010060E00640000000475 +:101F7000020E00DC00000003020E01100000000F42 +:101F8000020E01140000002F020E011800000000D4 +:101F9000020E011C00000020020E000400000001DF +:101FA000020E000800000001020E000C00000001FB +:101FB000020E001000000001020E001400000001DB +:101FC000020E001800000001020E001C00000001BB +:101FD000020E002000000001020E0024000000019B +:101FE000020E002800000001020E002C000000017B +:101FF000020E003000000001020E0034000000015B +:10200000020E003800000001020E003C000000013A +:10201000020E004000000001020E0044000000011A +:102020000730040000AF0000083007680013037693 +:10203000073400003305000007348000327F0CC2F3 +:10204000073500001A951962083539E058C403783D +:10205000013000000000000001300004000000001A +:1020600001300008000000000130000C00000000FA +:1020700001300010000000000130001400000000DA +:1020800002300020000000010230002400000002A5 +:1020900002300028000000030230002C0000000085 +:1020A0000230003000000004023000340000000163 +:1020B00002300038000000000230003C0000000147 +:1020C0000230004000000004023000440000000024 +:1020D00002300048000000010230004C0000000304 +:1020E00002300050000000000230005400000001E7 +:1020F00002300058000000040230005C00000000C4 +:1021000002300060000000010230006400000003A3 +:1021100002300068000000000230006C0000000186 +:102120000230007000000004023000740000000063 +:1021300002300078000000040230007C0000000340 +:102140000630008000000002023000A400003FFFC3 +:10215000023000A8000003FF02300224000000004B +:1021600002300234000000000230024C0000000087 +:10217000023002E40000FFFF0630200000000800EB +:1021800002338BC000000001023380000000001AFF +:10219000023380400000004E0233808000000010B7 +:1021A000023380C0000000200C3383000007A12010 +:1021B0000A338300000001380B33830000001388CA +:1021C0000A338340000000000C338340000001F418 +:1021D0000B33834000000005023383800007A120F9 +:1021E000023383C0000001F406322A88000000C2D6 +:1021F00006322008000000C806322000000000025D +:10220000063223E80000004004322E580004037A0E +:10221000063250A000000004063250B80000000250 +:102220000632508000000006043250980002037EFF +:10223000063250000000002006323000000004008A +:1022400006321C0000000004043218300002038033 +:10225000063224E8000000B402322DB00000000075 +:1022600006324000000000B40632300000000020BA +:10227000063231000000002006323200000000204B +:102280000632330000000020063234000000002037 +:102290000632350000000020063236000000002023 +:1022A000063237000000002006323800000000200F +:1022B000063239000000002006323A0000000020FB +:1022C00006323B000000002006323C0000000020E7 +:1022D00006323D000000002006323E0000000020D3 +:1022E00006323F000000002006321C1000000002F1 +:1022F000063245A000000024063227B8000000B4D2 +:1023000002322DB400000000063242D0000000B4BA +:1023100006323080000000200632318000000020AC +:102320000632328000000020063233800000002098 +:102330000632348000000020063235800000002084 +:102340000632368000000020063237800000002070 +:10235000063238800000002006323980000000205C +:1023600006323A800000002006323B800000002048 +:1023700006323C800000002006323D800000002034 +:1023800006323E800000002006323F800000002020 +:1023900006321C20000000020632463000000024F5 +:1023A0000720040000870000082007800010038237 +:1023B000072400003165000007248000081D0C5A26 +:1023C00008248EB06C9003840120000000000000FF +:1023D00001200004000000000120000800000000AF +:1023E0000120000C0000000001200010000000008F +:1023F0000120001400000000022000200000000165 +:102400000220002400000002022000280000000337 +:102410000220002C00000000022000300000000418 +:1024200002200034000000010220003800000000FB +:102430000220003C000000010220004000000004D7 +:1024400002200044000000000220004800000001BB +:102450000220004C00000003022000500000000099 +:102460000220005400000001022000580000000477 +:102470000220005C0000000002200060000000015B +:102480000220006400000003022000680000000039 +:102490000220006C00000001022000700000000417 +:1024A00002200074000000000220007800000004F8 +:1024B0000220007C000000030620008000000002D3 +:1024C000022000A400003FFF022000A8000003FF3C +:1024D000022002240000000002200234000000005C +:1024E0000220024C00000000022002E40000FFFF76 +:1024F000062020000000080002238BC0000000011D +:10250000022380000000001002238040000000121F +:102510000223808000000030022380C00000000EF3 +:102520000C2383000007A1200A2383000000013848 +:102530000B238300000013880A238340000000005F +:102540000C238340000001F40B23834000000005AE +:10255000022383800007A120022383C0000001F42E +:10256000062250000000004206222008000000C899 +:10257000062220000000000206224000000000C6E3 +:1025800004224318000503860622432C0000000B9A +:10259000042243580005038B0622436C0000000B05 +:1025A0000422439800050390062243AC0000000B70 +:1025B000042243D800050395062243EC0000000BDB +:1025C000042244180005039A0622442C0000000B44 +:1025D000042244580005039F0622446C0000000BAF +:1025E00004224498000503A4062244AC0000000B1A +:1025F000042244D8000503A9062244EC0000000B85 +:1026000004224518000503AE0622452C0000000BED +:1026100004224558000503B30622456C0000000B58 +:1026200004224598000503B8062245AC0000000BC3 +:10263000042245D8000503BD062245EC0000000B2E +:1026400004224618000503C20622462C0000000B97 +:1026500004224658000503C70622466C0000000B02 +:1026600004224698000503CC062246AC0000000B6D +:10267000042246D8000503D1062246EC0000000BD8 +:1026800004224718000503D60622472C0000000B41 +:1026900004224758000503DB0622476C0000000BAC +:1026A00004224798000503E0062247AC0000000B17 +:1026B000042247D8000503E5062247EC0000000B82 +:1026C00004224818000503EA0622482C0000000BEB +:1026D00004224858000503EF0622486C0000000B56 +:1026E00004224898000503F4062248AC0000000BC1 +:1026F000042248D8000503F9062248EC0000000B2C +:1027000004224918000503FE0622492C0000000B94 +:1027100004224958000504030622496C0000000BFE +:102720000422499800050408062249AC0000000B69 +:10273000042249D80005040D062249EC0000000BD4 +:1027400004224A180005041206224A2C0000000B3D +:1027500004224A580005041706224A6C0000000BA8 +:1027600004224A980005041C06224AAC0000000B13 +:1027700004224AD80005042106224AEC0000000584 +:1027800006224B000000001704224B5C00010426C7 +:1027900006224B600000000304224B6C000104275A +:1027A000062238000000004006223000000002002F +:1027B000042251C00004042806221000000000C0BA +:1027C000062215C00000024004221EC80008042C86 +:1027D0000622390000000008022251180000000003 +:1027E000062251D00000000606221300000000025D +:1027F00006221410000000300622392000000008D4 +:102800000222511C00000000062251E800000006D0 +:102810000622130800000002062214D00000003037 +:102820000216100000000028021700080000000235 +:102830000217002C000000030217003C00000004F7 +:1028400002170044000000000217004800000002C8 +:102850000217004C0000009002170050000000908A +:102860000217005400800090021700580810000062 +:10287000021700600000008A021700640000008058 +:1028800002170068000000810217006C0000008041 +:10289000021700700000000602170078000007D041 +:1028A0000217007C0000076C02170038007C10043F +:1028B000021700040000000F06164024000000026A +:1028C000021640700000001C0216420800000001C1 +:1028D0000216421000000001021642200000000112 +:1028E00002164228000000010216423000000001DA +:1028F000021642380000000102164260000000018A +:102900000C16401C0003D0900A16401C0000009CCE +:102910000B16401C000009C40216403000000008DD +:10292000021640340000000C02164038000000106F +:102930000216404400000020021640000000000182 +:10294000021640D8000000010216400800000001F5 +:102950000216400C000000010216401000000001A9 +:10296000021642400000000002164248000000002B +:1029700006164270000000020216425000000000DD +:1029800002164258000000000616428000000002B5 +:1029900002166008000006140216600C0000060013 +:1029A00002166010000006040216601C0000FFFF03 +:1029B000021660200000FFFF021660240000FFFFE7 +:1029C000021660280000FFFF021660380000002099 +:1029D0000216603C00000020061660400000000265 +:1029E00002166048000000230216604C000000241C +:1029F00002166050000000250216605400000026F8 +:102A000002166058000000270216605C00000029D2 +:102A1000021660600000002A021660640000002BAD +:102A2000021660680000002C0216606C0000002D89 +:102A30000616607000000012021660B80000000167 +:102A4000021660BC00000001061660C00000003ED7 +:102A5000021661B800000001061661BC0000001FEC +:102A60000216623807FFFFFF0216623C0000003FBB +:102A70000216624007FFFFFF021662440000000FCB +:102A800001166248000000000116624C00000000C0 +:102A900001166250000000000116625400000000A0 +:102AA00001166258000000000116625C0000000080 +:102AB0000116626000000000011662640000000060 +:102AC00001166268000000000116626C0000000040 +:102AD0000116627000000000011662740000000020 +:102AE00001166278000000000116627C0000000000 +:102AF000021664BC000000010C166000000003E830 +:102B00000A166000000000010B1660000000000AB9 +:102B100002168040000000060216804400000005F6 +:102B2000021680480000000A0216804C00000005D2 +:102B30000216805400000002021680CC000000043F +:102B4000021680D000000004021680D400000004A9 +:102B5000021680D800000004021680DC0000000489 +:102B6000021680E000000004021680E40000000469 +:102B7000021680E800000004021688040000000429 +:102B8000021680300000007C021680340000003DF8 +:102B9000021680380000003F0216803C0000009CB6 +:102BA000021680F000000007061680F40000000501 +:102BB0000216880C010101010216810800000000C4 +:102BC0000216810C000000040216811000000004AF +:102BD0000216811400000002021688100801200469 +:102BE00002168118000000050216811C0000000575 +:102BF0000216812000000005021681240000000555 +:102C00000216882C200810010216812800000008F6 +:102C10000216812C00000006021681300000000719 +:102C200002168134000000000216883001010120E4 +:102C300006168138000000040216883401010101E3 +:102C400006168148000000040216883801010101BF +:102C500006168158000000040216883C010101019B +:102C6000061681680000000302168174000000014E +:102C7000021688400101010102168178000000015E +:102C80000216817C00000001021681800000000114 +:102C9000021681840000000102168844010101012E +:102CA00002168188000000010216818C00000004D9 +:102CB00002168190000000040216819400000002B8 +:102CC00002168848080120040216819800000005B9 +:102CD0000216819C00000005021681A0000000057C +:102CE000021681A4000000050216881420081001B5 +:102CF000021681A800000008021681AC0000000640 +:102D0000021681B000000007021681B40000000125 +:102D10000216881801010120021681B80000000186 +:102D2000021681BC00000001021681C000000001F3 +:102D3000021681C4000000010216881C0101010175 +:102D4000021681C800000001021681CC00000001BB +:102D5000021681D000000001021681D4000000019B +:102D60000216882001010101021681D8000000012D +:102D7000021681DC00000001021681E00000000163 +:102D8000021681E4000000010216882401010101FD +:102D9000021681E800000001021681EC000000012B +:102DA000021681F0000000010216882801010101CD +:102DB00002168240FFFF003F061682440000000218 +:102DC0000216824CFFFF003F0216825000000100F5 +:102DD000021682540000010006168258000000020C +:102DE00002168260000000C002168264000000C06B +:102DF0000216826800001E000216826C00001E008F +:102E0000021682700000400002168274000040002A +:102E100002168278000080000216827C000080008A +:102E2000021682800000200002168284000020002A +:102E30000616828800000007021682A40000000126 +:102E4000061682A80000000A021681F400000C0891 +:102E5000021681F800000040021681FC000001000B +:102E600002168200000000200216820400000017F3 +:102E700002168208000000800216820C0000020088 +:102E8000021682100000000002168218FFFF01FFE8 +:102E900002168214FFFF01FF0216823C000000139D +:102EA000021680900000013F021680600000014081 +:102EB00002168064000001400616806800000002CF +:102EC00002168070000000C0061680740000000723 +:102ED0000216809C00000048021680A000000048F6 +:102EE000061680A400000002021680AC0000004814 +:102EF000061680B00000000702168238000080002D +:102F000002168234000025E40216809400007FFF40 +:102F100002168220000000070216821C0000000733 +:102F2000021682280000000002168224FFFFFFFF25 +:102F300002168230000000000216822CFFFFFFFF05 +:102F4000021680EC000000FF0214000000000001E7 +:102F50000214000C000000010214004000000001F7 +:102F60000214004400007FFF0214000C0000000067 +:102F700002140000000000000214006C00000000B9 +:102F800002140004000000010214003000000001DF +:102F900002140004000000000214005C00000000A5 +:102FA00002140008000000010214003400000001B7 +:102FB000021400080000000002140060000000007D +:102FC00006028000000020000202005800000032CB +:102FD000020200A003150020020200A40315002035 +:102FE000020200A801000030020200AC081000003C +:102FF000020200B000000033020200B40000003002 +:10300000020200B800000031020200BC0000000310 +:10301000020200C000000006020200C4000000031B +:10302000020200C800000003020200CC00000002FF +:10303000020200D000000000020200D400000002E2 +:10304000020200DC00000000020200E000000006B6 +:10305000020200E400000004020200E80000000296 +:10306000020200EC00000002020200F00000000179 +:10307000020200FC00000006020201200000000025 +:103080000202013400000002020201B0000000014F +:103090000202020C00000001020202140000000102 +:1030A00002020218000000020202040400000001F3 +:1030B0000202040C00000040020204100000004064 +:1030C0000202041C00000004020204200000002090 +:1030D0000202042400000002020204280000001F73 +:1030E00006020500000000120402048000200434DF +:1030F000020200600000000F0202006400000007EE +:1031000002020068000000000202006C0000000ED5 +:103110000602007000000004020200F40000000437 +:103120000202000400000001020200080000000189 +:103130000202000C00000001020200100000000169 +:103140000202001400000001020200180000000149 +:103150000202001C00000001020200200000000129 +:103160000202002400000001020200280000000109 +:103170000202002C000000010202003000000001E9 +:1031800002020034000000010202003800000001C9 +:103190000202003C000000010202004000000001A9 +:1031A0000202004400000001020200480000000189 +:1031B0000202004C00000001020200500000000169 +:1031C00002020108000000C802020118000000020B +:1031D000020201C400000000020201CC0000000055 +:1031E000020201D400000002020201DC0000000221 +:1031F000020201E4000000FF020201EC000000FFF7 +:103200000202010C000000C80202011C00000002C2 +:10321000020201C800000000020201D0000000000C +:10322000020201D800000002020201E000000002D8 +:10323000020201E8000000FF020201F0000000FFAE +:1032400007280400008E00000828076800130454B3 +:10325000072C000033C80000072C800038050CF351 +:10326000072D000038B61AF5072D800007762923B0 +:10327000082D8CB04E6A04560128000000000000A2 +:1032800001280004000000000128000800000000E0 +:103290000128000C000000000128001000000000C0 +:1032A0000128001400000000022800200000000196 +:1032B0000228002400000002022800280000000369 +:1032C0000228002C0000000002280030000000044A +:1032D000022800340000000102280038000000002D +:1032E0000228003C00000001022800400000000409 +:1032F00002280044000000000228004800000001ED +:103300000228004C000000030228005000000000CA +:1033100002280054000000010228005800000004A8 +:103320000228005C0000000002280060000000018C +:10333000022800640000000302280068000000006A +:103340000228006C00000001022800700000000448 +:103350000228007400000000022800780000000429 +:103360000228007C00000003062800800000000204 +:10337000022800A400003FFF022800A8000003FF6D +:10338000022802240000000002280234000000008D +:103390000228024C00000000022802E40000FFFFA7 +:1033A0000628200000000800022B8BC0000000014E +:1033B000022B800000000000022B8040000000185B +:1033C000022B80800000000C022B80C000000066F1 +:1033D0000C2B83000007A1200A2B8300000001387A +:1033E0000B2B8300000013880A2B83400000000091 +:1033F0000C2B8340000001F40B2B834000000005E0 +:10340000022B83800007A120022B83C0000001F45F +:10341000062A3D4800000004042A3D5800020458D2 +:10342000062A3D6000000006062A30000000004821 +:10343000062A2008000000C8062A2000000000021A +:10344000062A31280000008E062A33680000000397 +:10345000042A33740001045A062A3A780000000254 +:10346000042A3A800002045B042A3A700002045DD8 +:10347000042A3E280002045F042A3EB000040461CE +:10348000042A250000020465062A25080000010020 +:10349000062A297000000004042A29600004046739 +:1034A000042A2F480002046B062A3378000000D853 +:1034B000022A3A3800000000062A3A88000000324A +:1034C000042A3D880010046D062A502000000002E6 +:1034D000062A503000000002062A500000000002B8 +:1034E000062A501000000002022A50B80000000115 +:1034F000062A50480000000E042A3D780002047D90 +:10350000062A3C1800000026022A50400000000055 +:10351000062A36D8000000D8022A3A3C00000000F3 +:10352000062A3B5000000032042A3DC80010047FE8 +:10353000062A502800000002062A50380000000227 +:10354000062A500800000002062A50180000000257 +:10355000022A50BC00000001062A50800000000E24 +:10356000042A3D800002048F062A3CB00000002699 +:10357000022A504400000000021010080000000160 +:103580000210101000000264021010000003D000AE +:10359000021010040000003D091018000200049100 +:1035A00009101100001006910610114000000008DB +:1035B00009101160000806A1061011800000000229 +:1035C00009101188000606A9061011A000000018B5 +:1035D000021010100000000006102400000000E09F +:1035E0000210201C0000000002102020000000013A +:1035F000021020C0000000010210200400000001A1 +:10360000021020080000000109103C00000506AF70 +:1036100009103C20000506B409103800000506B961 +:1036200002104028000000100210404400003FFF3C +:103630000210405800280000021040840084924A82 +:1036400006104C000000010002104058000000006D +:103650000610806800000004021080000000108046 +:1036600006108028000000020210803800000010C0 +:10367000021080400000FFFF021080440000FFFFA6 +:1036800002108050000000000210810000000000C5 +:10369000061081200000000202108008000002B520 +:1036A0000210801000000000061082000000004A96 +:1036B000021081080001FFFF061081400000000297 +:1036C0000210800000001A80061090000000002404 +:1036D000061091200000004A061093700000004A76 +:1036E000061095C00000004A0210800400001080FF +:1036F00006108030000000020210803C0000001024 +:10370000021080480000FFFF0210804C0000FFFF05 +:10371000021080540000000002108104000000002C +:1037200006108128000000020210800C000002B583 +:103730000210801400000000061084000000004AFF +:103740000210810C0001FFFF0610814800000002FA +:103750000210800400001A800610909000000024DF +:10376000061092480000004A061094980000004A93 +:10377000061096E80000004A0212049000E383401D +:103780000212051400003C10021205200000000285 +:1037900002120494FFFFFFFF02120498FFFFFFFFD5 +:1037A0000212049CFFFFFFFF021204A0FFFFFFFFB5 +:1037B000021204A4FFFFFFFF021204A8FFFFFFFF95 +:1037C000021204ACFFFFFFFF021204B0FFFFFFFF75 +:1037D000021204B8FFFFFFFF021204BCFFFFFFFF4D +:1037E000021204C0FFFFFFFF021204C4FFFFFFFF2D +:1037F000021204C8FFFFFFFF021204CCFFFFFFFF0D +:10380000021204D0FFFFFFFF021204DCFFFFFFFFE4 +:10381000021204E0FFFFFFFF021204E4FFFFFFFFBC +:10382000021204E8FFFFFFFF021204ECFFFFFFFF9C +:10383000021204F0FFFFFFFF021204F4FFFFFFFF7C +:10384000021204F8FFFFFFFF021204FCFFFFFFFF5C +:1038500002120500FFFFFFFF02120504FFFFFFFF3A +:1038600002120508FFFFFFFF0212050CFFFFFFFF1A +:1038700002120510FFFFFFFF021204D4FFFF3330D6 +:10388000021204D8FFFF3340021204B4F0003000EB +:1038900002120390000000080212039C00000008BE +:1038A000061203A000000002021203BC0000000484 +:1038B000021203C400000004021203D00000000042 +:1038C000021203DC000000000212036C0000000181 +:1038D000021203680000003F021201BC0000004019 +:1038E000021201C000001808021201C400000803FF +:1038F000021201C800000803021201CC00000040BF +:10390000021201D000000003021201D400000803DB +:10391000021201D800000803021201DC00000803B3 +:10392000021201E000010003021201E4000008039A +:10393000021201E800000803021201EC000000037B +:10394000021201F000000003021201F40000000363 +:10395000021201F800000003021201FC0000000343 +:103960000212020000000003021202040000000321 +:1039700002120208000000030212020C0000000301 +:1039800002120210000000030212021400000003E1 +:1039900002120218000000030212021C00000003C1 +:1039A00002120220000000030212022400000003A1 +:1039B00002120228000024030212022C0000002F31 +:1039C0000212023000000009021202340000001945 +:1039D00002120238000001840212023C000001833E +:1039E0000212024000000306021202440000001905 +:1039F00002120248000000060212024C00000306F8 +:103A000002120250000003060212025400000306D4 +:103A10000212025800000C860212025C000003062B +:103A20000212026000000306021202640000000697 +:103A300002120268000000060212026C000000067A +:103A4000021202700000000602120274000000065A +:103A500002120278000000060212027C000000063A +:103A6000021202800000000602120284000000061A +:103A700002120288000000060212028C00000006FA +:103A800002120290000000060212029400000006DA +:103A900002120298000000060212029C00000006BA +:103AA000021202A000000306021202A4000000138A +:103AB000021202A800000006021202B00000100468 +:103AC000021202B400001004021203240010644029 +:103AD0000212032800106440021201B0000000012D +:103AE0000600A000000000160200A06CBF5C0000F1 +:103AF0000200A070FFF51FEF0200A0740000FFFF9E +:103B00000200A078F00003E00200A07C00000000AA +:103B10000200A0800000A0000600A08400000005B4 +:103B20000200A0980FE000000600A09C0000001416 +:103B30000200A0EC555400000200A0F05555555568 +:103B40000200A0F4000055550200A0F8F0000000AB +:103B50000200A0FC555400000200A1005555555527 +:103B60000200A104000055550200A108F000000069 +:103B70000600A22C000000040200A0600000030761 +:103B80000200A10CBF5C00000200A110FFF51FEFB6 +:103B90000200A1140000FFFF0200A118F00003E0E2 +:103BA0000200A11C000000000200A1200000A000F3 +:103BB0000600A124000000050200A1380FE000006B +:103BC0000600A13C000000140200A18C5554000026 +:103BD0000200A190555555550200A194000055557D +:103BE0000200A198F00000000200A19C55540000C2 +:103BF0000200A1A0555555550200A1A4000055553D +:103C00000200A1A8F00000000600A23C0000000491 +:103C10000200A06400000307000000000000000094 +:103C20000000002E00000000000000000000000066 +:103C30000000000000000000000000000000000084 +:103C40000000000000000000000000000000000074 +:103C50000000000000000000000000000000000064 +:103C60000000000000000000000000000000000054 +:103C70000000000000000000002E004D00000000C9 +:103C80000000000000000000000000000000000034 +:103C90000000000000000000000000000000000024 +:103CA00000000000004D008B00000000000000003C +:103CB0000000000000000000000000000000000004 +:103CC00000000000000000000000000000000000F4 +:103CD000008B009000900094009400980000000079 +:103CE00000000000000000000000000000000000D4 +:103CF000000000000000000000000000009802DE4C +:103D000002DE02E802E802F200000000000000000B +:103D100000000000000000000000000000000000A3 +:103D20000000000000000000000000000000000093 +:103D30000000000000000000000000000000000083 +:103D40000000000000000000000000000000000073 +:103D50000000000000000000000000000000000063 +:103D60000000000000000000000000000000000053 +:103D70000000000000000000000000000000000043 +:103D80000000000000000000000000000000000033 +:103D90000000000000000000000000000000000023 +:103DA0000000000000000000000000000000000013 +:103DB0000000000000000000000000000000000003 +:103DC00000000000000000000000000000000000F3 +:103DD000000000000000000002F202FA00000000F3 +:103DE00000000000000000000000000000000000D3 +:103DF00000000000000000000000000000000000C3 +:103E000000000000000000000000000000000000B2 +:103E100000000000000000000000000000000000A2 +:103E20000000000000000000000000000000000092 +:103E300002FA02FF02FF030A030A03150000000052 +:103E40000000000000000000000000000000000072 +:103E50000000000000000000000000000000000062 +:103E60000000000000000000000000000000000052 +:103E70000000000000000000000000000000000042 +:103E80000000000000000000031503160000000001 +:103E90000000000000000000000000000000000022 +:103EA0000000000000000000000000000000000012 +:103EB000000000000316035700000000000000008F +:103EC00000000000000000000000000000000000F2 +:103ED00000000000000000000000000000000000E2 +:103EE0000357037B000000000000000000000000FA +:103EF00000000000000000000000000000000000C2 +:103F0000000000000000000000000000037B03BB75 +:103F100000000000000000000000000000000000A1 +:103F20000000000000000000000000000000000091 +:103F3000000000000000000003BB03F700000000C9 +:103F40000000000000000000000000000000000071 +:103F50000000000000000000000000000000000061 +:103F60000000000003F7043D043D045204520467BE +:103F70000000000000000000000000000000000041 +:103F80000000000000000000000000000000000031 +:103F9000046704ED04ED04F204F204F700000000ED +:103FA0000000000000000000000000000000000011 +:103FB00000000000000000000000000004F704F80A +:103FC00000000000000000000000000000000000F1 +:103FD00000000000000000000000000000000000E1 +:103FE000000000000000000004F8050A00000000C6 +:103FF00000000000000000000000000000000000C1 +:1040000000000000000000000000000000000000B0 +:1040100000000000050A051F051F052205220525D1 +:104020000000000000000000000000000000000090 +:104030000000000000000000000000000000000080 +:1040400005250555000000000000000000000000EC +:104050000000000000000000000000000000000060 +:10406000000000000000000000000000055505DC15 +:104070000000000000000000000000000000000040 +:104080000000000000000000000000000000000030 +:10409000000000000000000005DC05E305E305E783 +:1040A00005E705EB00000000000000000000000034 +:1040B0000000000000000000000000000000000000 +:1040C0000000000005EB062B062B06330633063BEB +:1040D00000000000000000000000000000000000E0 +:1040E00000000000000000000000000000000000D0 +:1040F000063B068806880695069506A20000000085 +:1041000000000000000000000000000000000000AF +:1041100000000000000000000000000006A206AE43 +:10412000000000000000000000000000000000008F +:10413000000000000000000000000000000000007F +:10414000000000000000000006AE06B40000000001 +:10415000000000000000000000000000000000005F +:10416000000000000000000000000000000000004F +:104170000000000006B406B70000000000000000C8 +:10418000000000000000000000000000000000002F +:10419000000000000000000000000000000000001F +:1041A00006B706BD0000000000000000000000008F +:1041B00000000000000000000000000000000000FF +:1041C00000000000000000000000000006BD06BE68 +:1041D00006BE06D006D006E2000000000000000087 +:1041E00000000000000000000000000000000000CF +:1041F000000000000000000006E2074F0000000081 +:1042000000000000000000000000000000000000AE +:10421000000000000000000000000000000000009E +:1042200000000000074F0750075007630763077639 +:10423000000000000000000000000000000000007E +:10424000000000000000000000000000000000006E +:10425000000000000000000000000000000000005E +:10426000000000000000000000000000000000004E +:10427000000000000000000000000000000000003E +:10428000000000000000000000000000000000002E +:10429000000000000000000000000000000000001E +:1042A000000000000000000000000000000000000E +:1042B00000000000000000000000000000000000FE +:1042C00000000000000000000000000000000000EE +:1042D00000000000000000000000000000000000DE +:1042E00000000000000000000000000000000000CE +:1042F00000000000000000000000000000000000BE +:1043000000000000000000000000000000000000AD +:10431000000000000000000000000000000000009D +:10432000000000000000000000000000000000008D +:1043300000010000000204C00003098000040E40D8 +:1043400000051300000617C000071C80000821406C +:1043500000092600000A2AC0000B2F80000C344000 +:10436000000D3900000E3DC0000F42800010474094 +:1043700000114C00001250C00013558000145A4028 +:1043800000155F00001663C00017688000186D40BC +:1043900000197200001A76C0001B7B80001C804050 +:1043A000001D8500001E89C0001F8E800000934004 +:1043B00000002000000040000000600000008000BD +:1043C0000000A0000000C0000000E00000010000AC +:1043D0000001200000014000000160000001800099 +:1043E0000001A0000001C0000001E0000002000088 +:1043F0000002200000024000000260000002800075 +:104400000002A0000002C0000002E0000003000063 +:104410000003200000034000000360000003800050 +:104420000003A0000003C0000003E000000400003F +:10443000000420000004400000046000000480002C +:104440000004A0000004C0000004E000000500001B +:104450000005200000054000000560000005800008 +:104460000005A0000005C0000005E00000060000F7 +:1044700000062000000640000006600000068000E4 +:104480000006A0000006C0000006E00000070000D3 +:1044900000072000000740000007600000078000C0 +:1044A0000007A0000007C0000007E00000080000AF +:1044B000000820000008400000086000000880009C +:1044C0000008A0000008C0000008E000000900008B +:1044D0000009200000094000000960000009800078 +:1044E0000009A0000009C0000009E000000A000067 +:1044F000000A2000000A4000000A6000000A800054 +:10450000000AA000000AC000000AE000000B000042 +:10451000000B2000000B4000000B6000000B80002F +:10452000000BA000000BC000000BE000000C00001E +:10453000000C2000000C4000000C6000000C80000B +:10454000000CA000000CC000000CE000000D0000FA +:10455000000D2000000D4000000D6000000D8000E7 +:10456000000DA000000DC000000DE000000E0000D6 +:10457000000E2000000E4000000E6000000E8000C3 +:10458000000EA000000EC000000EE000000F0000B2 +:10459000000F2000000F4000000F6000000F80009F +:1045A000000FA000000FC000000FE000001000008E +:1045B000001020000010400000106000001080007B +:1045C0000010A0000010C0000010E000001100006A +:1045D0000011200000114000001160000011800057 +:1045E0000011A0000011C0000011E0000012000046 +:1045F0000012200000124000001260000012800033 +:104600000012A0000012C0000012E0000013000021 +:10461000001320000013400000136000001380000E +:104620000013A0000013C0000013E00000140000FD +:1046300000142000001440000014600000148000EA +:104640000014A0000014C0000014E00000150000D9 +:1046500000152000001540000015600000158000C6 +:104660000015A0000015C0000015E00000160000B5 +:1046700000162000001640000016600000168000A2 +:104680000016A0000016C0000016E0000017000091 +:10469000001720000017400000176000001780007E +:1046A0000017A0000017C0000017E000001800006D +:1046B000001820000018400000186000001880005A +:1046C0000018A0000018C0000018E0000019000049 +:1046D0000019200000194000001960000019800036 +:1046E0000019A0000019C0000019E000001A000025 +:1046F000001A2000001A4000001A6000001A800012 +:10470000001AA000001AC000001AE000001B000000 +:10471000001B2000001B4000001B6000001B8000ED +:10472000001BA000001BC000001BE000001C0000DC +:10473000001C2000001C4000001C6000001C8000C9 +:10474000001CA000001CC000001CE000001D0000B8 +:10475000001D2000001D4000001D6000001D8000A5 +:10476000001DA000001DC000001DE000001E000094 +:10477000001E2000001E4000001E6000001E800081 +:10478000001EA000001EC000001EE000001F000070 +:10479000001F2000001F4000001F6000001F80005D +:1047A000001FA000001FC000001FE000002000004C +:1047B0000020200000204000002060000020800039 +:1047C0000020A0000020C0000020E0000021000028 +:1047D0000021200000214000002160000021800015 +:1047E0000021A0000021C0000021E0000022000004 +:1047F00000222000002240000022600000228000F1 +:104800000022A0000022C0000022E00000230000DF +:1048100000232000002340000023600000238000CC +:104820000023A0000023C0000023E00000240000BB +:1048300000242000002440000024600000248000A8 +:104840000024A0000024C0000024E0000025000097 +:104850000025200000254000002560000025800084 +:104860000025A0000025C0000025E0000026000073 +:104870000026200000264000002660000026800060 +:104880000026A0000026C0000026E000002700004F +:10489000002720000027400000276000002780003C +:1048A0000027A0000027C0000027E000002800002B +:1048B0000028200000284000002860000028800018 +:1048C0000028A0000028C0000028E0000029000007 +:1048D00000292000002940000029600000298000F4 +:1048E0000029A0000029C0000029E000002A0000E3 +:1048F000002A2000002A4000002A6000002A8000D0 +:10490000002AA000002AC000002AE000002B0000BE +:10491000002B2000002B4000002B6000002B8000AB +:10492000002BA000002BC000002BE000002C00009A +:10493000002C2000002C4000002C6000002C800087 +:10494000002CA000002CC000002CE000002D000076 +:10495000002D2000002D4000002D6000002D800063 +:10496000002DA000002DC000002DE000002E000052 +:10497000002E2000002E4000002E6000002E80003F +:10498000002EA000002EC000002EE000002F00002E +:10499000002F2000002F4000002F6000002F80001B +:1049A000002FA000002FC000002FE000003000000A +:1049B00000302000003040000030600000308000F7 +:1049C0000030A0000030C0000030E00000310000E6 +:1049D00000312000003140000031600000318000D3 +:1049E0000031A0000031C0000031E00000320000C2 +:1049F00000322000003240000032600000328000AF +:104A00000032A0000032C0000032E000003300009D +:104A1000003320000033400000336000003380008A +:104A20000033A0000033C0000033E0000034000079 +:104A30000034200000344000003460000034800066 +:104A40000034A0000034C0000034E0000035000055 +:104A50000035200000354000003560000035800042 +:104A60000035A0000035C0000035E0000036000031 +:104A7000003620000036400000366000003680001E +:104A80000036A0000036C0000036E000003700000D +:104A900000372000003740000037600000378000FA +:104AA0000037A0000037C0000037E00000380000E9 +:104AB00000382000003840000038600000388000D6 +:104AC0000038A0000038C0000038E00000390000C5 +:104AD00000392000003940000039600000398000B2 +:104AE0000039A0000039C0000039E000003A0000A1 +:104AF000003A2000003A4000003A6000003A80008E +:104B0000003AA000003AC000003AE000003B00007C +:104B1000003B2000003B4000003B6000003B800069 +:104B2000003BA000003BC000003BE000003C000058 +:104B3000003C2000003C4000003C6000003C800045 +:104B4000003CA000003CC000003CE000003D000034 +:104B5000003D2000003D4000003D6000003D800021 +:104B6000003DA000003DC000003DE000003E000010 +:104B7000003E2000003E4000003E6000003E8000FD +:104B8000003EA000003EC000003EE000003F0000EC +:104B9000003F2000003F4000003F6000003F8000D9 +:104BA000003FA000003FC000003FE000003FE001E8 +:104BB00000000000000001FF0000020000007FF87C +:104BC00000007FF80000016A0000150000000001ED +:104BD0000000FF00000000000000FF0000000000D7 +:104BE00000000000140AFF000000000100000000A7 +:104BF00000201001000000000100860000000100FC +:104C00000000860200008604000086060000860878 +:104C10000000860A0000860C0000860E0000861048 +:104C20000000861200008614000086160000861818 +:104C30000000861A0000861C0000861E00008620E8 +:104C400000008622000086240000862600008628B8 +:104C50000000862A0000862C0000862E0000863088 +:104C60000000863200008634000086360000863858 +:104C70000000863A0000863C0000863E0000864028 +:104C800000008642000086440000864600008648F8 +:104C90000000864A0000864C0000864E00008650C8 +:104CA0000000865200008654000086560000865898 +:104CB0000000865A0000865C0000865E0000866068 +:104CC0000000866200008664000086660000866838 +:104CD0000000866A0000866C0000866E0000867008 +:104CE00000008672000086740000867600008678D8 +:104CF0000000867A0000867C0000867E00008680A8 +:104D00000000868200008684000086860000868877 +:104D10000000868A0000868C0000868E0000869047 +:104D20000000869200008694000086960000869817 +:104D30000000869A0000869C0000869E000086A0E7 +:104D4000000086A2000086A4000086A6000086A8B7 +:104D5000000086AA000086AC000086AE000086B087 +:104D6000000086B2000086B4000086B6000086B857 +:104D7000000086BA000086BC000086BE000086C027 +:104D8000000086C2000086C4000086C6000086C8F7 +:104D9000000086CA000086CC000086CE000086D0C7 +:104DA000000086D2000086D4000086D6000086D897 +:104DB000000086DA000086DC000086DE000086E067 +:104DC000000086E2000086E4000086E6000086E837 +:104DD000000086EA000086EC000086EE000086F007 +:104DE000000086F2000086F4000086F6000086F8D7 +:104DF000000086FA000086FC000086FE00008700A6 +:104E00000000870200008704000087060000870872 +:104E10000000870A0000870C0000870E0000871042 +:104E20000000871200008714000087160000871812 +:104E30000000871A0000871C0000871E00008720E2 +:104E400000008722000087240000872600008728B2 +:104E50000000872A0000872C0000872E0000873082 +:104E60000000873200008734000087360000873852 +:104E70000000873A0000873C0000873E0000874022 +:104E800000008742000087440000874600008748F2 +:104E90000000874A0000874C0000874E00008750C2 +:104EA0000000875200008754000087560000875892 +:104EB0000000875A0000875C0000875E0000876062 +:104EC0000000876200008764000087660000876832 +:104ED0000000876A0000876C0000876E0000877002 +:104EE00000008772000087740000877600008778D2 +:104EF0000000877A0000877C0000877E00008780A2 +:104F00000000878200008784000087860000878871 +:104F10000000878A0000878C0000878E0000879041 +:104F20000000879200008794000087960000879811 +:104F30000000879A0000879C0000879E000087A0E1 +:104F4000000087A2000087A4000087A6000087A8B1 +:104F5000000087AA000087AC000087AE000087B081 +:104F6000000087B2000087B4000087B6000087B851 +:104F7000000087BA000087BC000087BE000087C021 +:104F8000000087C2000087C4000087C6000087C8F1 +:104F9000000087CA000087CC000087CE000087D0C1 +:104FA000000087D2000087D4000087D6000087D891 +:104FB000000087DA000087DC000087DE000087E061 +:104FC000000087E2000087E4000087E6000087E831 +:104FD000000087EA000087EC000087EE000087F001 +:104FE000000087F2000087F4000087F6000087F8D1 +:104FF000000087FA000087FC000087FEFFFFFFFF2C +:10500000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 +:10501000FFFFFFFFFFFFFFFFFFFFFFFF0000000399 +:1050200000BEBC20000000000000000500000003DE +:1050300000BEBC20000000000000000500002000B1 +:10504000000040C000006180000082400000A3001A +:105050000000C3C00000E4800001054000012600FC +:10506000000146C000016780000188400001A900DE +:105070000001C9C00001EA8000020B4000022C00C0 +:1050800000024CC000026D8000028E400002AF00A2 +:105090000002CFC00002F08000001140000080003C +:1050A000000103800001870000020A8000028E00D8 +:1050B00000031180000395000004188000049C0088 +:1050C00000051F800005A300000626800006AA0038 +:1050D00000072D800007B100000834800008B800E8 +:1050E00000093B800009BF00000A4280000AC60098 +:1050F000000B4980000BCD00000C5080000CD40048 +:10510000000D578000005B0000007FF800007FF872 +:1051100000000166000015000000FF000000000014 +:105120000000FF0000000000000019000000000067 +:1051300000000000FFFFFFFF00007FF800007FF885 +:1051400000000361000015000000FF000FFFFFFFDB +:105150000000FF000FFFFFFF000000FF0000FF0046 +:105160000FFFFFFF0000FF000FFFFFFF000000FF29 +:105170000000FF000FFFFFFF0000FF000FFFFFFF19 +:10518000000000FF0000FF000FFFFFFF0000FF0016 +:105190000FFFFFFF000000FF0000FF000FFFFFFFF9 +:1051A0000000FF000FFFFFFF000000FF0000FF00F6 +:1051B0000FFFFFFF0000FF000FFFFFFF000000FFD9 +:1051C0000000FF000FFFFFFF0000FF000FFFFFFFC9 +:1051D000000000FF0000FF000FFFFFFF0000FF00C6 +:1051E0000FFFFFFF000000FF0000FF000FFFFFFFA9 +:1051F0000000FF000FFFFFFF000000FF0000FF00A6 +:105200000FFFFFFF0000FF000FFFFFFF000000FF88 +:105210000000FF000FFFFFFF0000FF000FFFFFFF78 +:10522000000000FF0000FF000FFFFFFF0000FF0075 +:105230000FFFFFFF000000FF0000FF000FFFFFFF58 +:105240000000FF000FFFFFFF000000FF0000FF0055 +:105250000FFFFFFF0000FF000FFFFFFF000000FF38 +:105260000000FF000FFFFFFF0000FF000FFFFFFF28 +:10527000000000FF0000FF000FFFFFFF0000FF0025 +:105280000FFFFFFF000000FF0000FF000FFFFFFF08 +:105290000000FF000FFFFFFF000000FF0000FF0005 +:1052A0000FFFFFFF0000FF000FFFFFFF000000FFE8 +:1052B0000000FF000FFFFFFF0000FF000FFFFFFFD8 +:1052C000000000FF0000FF000FFFFFFF0000FF00D5 +:1052D0000FFFFFFF000000FF0000FF000FFFFFFFB8 +:1052E0000000FF000FFFFFFF000000FF0000FF00B5 +:1052F0000FFFFFFF0000FF000FFFFFFF000000FF98 +:105300000000FF000FFFFFFF0000FF000FFFFFFF87 +:10531000000000FF0000FF000FFFFFFF0000FF0084 +:105320000FFFFFFF000000FF0000FF000FFFFFFF67 +:105330000000FF000FFFFFFF000000FF0000FF0064 +:105340000FFFFFFF0000FF000FFFFFFF000000FF47 +:105350000000FF000FFFFFFF0000FF000FFFFFFF37 +:10536000000000FF0000FF000FFFFFFF0000FF0034 +:105370000FFFFFFF000000FF0000FF000FFFFFFF17 +:105380000000FF000FFFFFFF000000FF0000FF0014 +:105390000FFFFFFF0000FF000FFFFFFF000000FFF7 +:1053A0000000FF000FFFFFFF0000FF000FFFFFFFE7 +:1053B000000000FF0000FF000FFFFFFF0000FF00E4 +:1053C0000FFFFFFF000000FF000000FF000000FFD4 +:1053D0000000FF00000000000000FF0000000000CF +:1053E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD +:1053F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD +:1054000000001000000020800000310000004180FA +:1054100000005200000062800000730000008380E2 +:10542000000094000000A4800000B5000000C580CA +:105430000000D6000000E6800000F70000010780B1 +:105440000001180000012880000139000001498096 +:1054500000015A0000016A8000017B0000018B807E +:1054600000019C000001AC800001BD000001CD8066 +:105470000001DE000001EE8000000F0000000000CF +:1054800000007FF800007FF80000021D00001500FA +:1054900010000000000028AD00010001FFFFFFFF29 +:1054A000FFFFFFFF00090206CCCCCCC17058103CB6 +:1054B000000000000000FF00000000000000FF00EE +:1054C000000000000000000000000001CCCC020140 +:1054D000CCCCCCCCCCCC0201CCCCCCCC00000000D1 +:1054E000FFFFFFFF0000FFFF000000000000FFFFC4 +:1054F000000000000000FFFF000000000000FFFFB0 +:10550000000000000000FFFF000000000000FFFF9F +:10551000000000000000FFFF000000000000FFFF8F +:1055200000000000000E0000011600D60000FFFF82 +:10553000000000000000FFFF000000000000FFFF6F +:10554000000000000000FFFF000000000000FFFF5F +:10555000000000000000FFFF000000000000FFFF4F +:10556000000000000000FFFF0000000000720000CB +:10557000012300F3FFFFFFF3318FFFFF0C30C30C5B +:10558000C30C30C3CF3CF300F3CF3CF30000CF3C5F +:10559000CDCDCDCDFFFFFFF130EFFFFF0C30C30CC1 +:1055A000C30C30C3CF3CF300F3CF3CF30001CF3C3E +:1055B000CDCDCDCDFFFFFFF6305FFFFF0C30C30C2C +:1055C000C30C30C3CF3CF300F3CF3CF30002CF3C1D +:1055D000CDCDCDCDFFFFF4061CBFFFFF0C30C305C2 +:1055E000C30C30C3CF300014F3CF3CF30004CF3CE6 +:1055F000CDCDCDCDFFFFFFF2304FFFFF0C30C30C00 +:10560000C30C30C3CF3CF300F3CF3CF30008CF3CD6 +:10561000CDCDCDCDFFFFFFFA302FFFFF0C30C30CF7 +:10562000C30C30C3CF3CF300F3CF3CF30010CF3CAE +:10563000CDCDCDCDFFFFFFF731EFFFFF0C30C30C19 +:10564000C30C30C3CF3CF300F3CF3CF30020CF3C7E +:10565000CDCDCDCDFFFFFFF5302FFFFF0C30C30CBC +:10566000C30C30C3CF3CF300F3CF3CF30040CF3C3E +:10567000CDCDCDCDFFFFFFF3318FFFFF0C30C30C3D +:10568000C30C30C3CF3CF300F3CF3CF30000CF3C5E +:10569000CDCDCDCDFFFFFFF1310FFFFF0C30C30C9F +:1056A000C30C30C3CF3CF300F3CF3CF30001CF3C3D +:1056B000CDCDCDCDFFFFFFF6305FFFFF0C30C30C2B +:1056C000C30C30C3CF3CF300F3CF3CF30002CF3C1C +:1056D000CDCDCDCDFFFFF4061CBFFFFF0C30C305C1 +:1056E000C30C30C3CF300014F3CF3CF30004CF3CE5 +:1056F000CDCDCDCDFFFFFFF2304FFFFF0C30C30CFF +:10570000C30C30C3CF3CF300F3CF3CF30008CF3CD5 +:10571000CDCDCDCDFFFFFFFA302FFFFF0C30C30CF6 +:10572000C30C30C3CF3CF300F3CF3CF30010CF3CAD +:10573000CDCDCDCDFFFFFFF730EFFFFF0C30C30C19 +:10574000C30C30C3CF3CF300F3CF3CF30020CF3C7D +:10575000CDCDCDCDFFFFFFF5304FFFFF0C30C30C9B +:10576000C30C30C3CF3CF300F3CF3CF30040CF3C3D +:10577000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CF1 +:10578000C30C30C3CF3CF3CCF3CF3CF30000CF3C91 +:10579000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CD1 +:1057A000C30C30C3CF3CF3CCF3CF3CF30001CF3C70 +:1057B000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CB1 +:1057C000C30C30C3CF3CF3CCF3CF3CF30002CF3C4F +:1057D000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C91 +:1057E000C30C30C3CF3CF3CCF3CF3CF30004CF3C2D +:1057F000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C71 +:10580000C30C30C3CF3CF3CCF3CF3CF30008CF3C08 +:10581000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C50 +:10582000C30C30C3CF3CF3CCF3CF3CF30010CF3CE0 +:10583000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C30 +:10584000C30C30C3CF3CF3CCF3CF3CF30020CF3CB0 +:10585000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C10 +:10586000C30C30C3CF3CF3CCF3CF3CF30040CF3C70 +:10587000CDCDCDCDFFFFFFF3320FFFFF0C30C30CBA +:10588000C30C30C3CF3CF300F3CF3CF30000CF3C5C +:10589000CDCDCDCDFFFFFFF1310FFFFF0C30C30C9D +:1058A000C30C30C3CF3CF300F3CF3CF30001CF3C3B +:1058B000CDCDCDCDFFFFFFF6305FFFFF0C30C30C29 +:1058C000C30C30C3CF3CF300F3CF3CF30002CF3C1A +:1058D000CDCDCDCDFFFFF4061CBFFFFF0C30C305BF +:1058E000C30C30C3CF300014F3CF3CF30004CF3CE3 +:1058F000CDCDCDCDFFFFFFF2304FFFFF0C30C30CFD +:10590000C30C30C3CF3CF300F3CF3CF30008CF3CD3 +:10591000CDCDCDCDFFFFFF8A042FFFFF0C30C30C90 +:10592000C30C30C3CF3CC000F3CF3CF30010CF3CDE +:10593000CDCDCDCDFFFFFF9705CFFFFF0C30C30CC2 +:10594000C30C30C3CF3CC000F3CF3CF30020CF3CAE +:10595000CDCDCDCDFFFFFFF5310FFFFF0C30C30CD8 +:10596000C30C30C3CF3CF300F3CF3CF30040CF3C3B +:10597000CDCDCDCDFFFFFFF3300FFFFF0C30C30CBB +:10598000C30C30C3CF3CF300F3CF3CF30000CF3C5B +:10599000CDCDCDCDFFFFFFF1300FFFFF0C30C30C9D +:1059A000C30C30C3CF3CF300F3CF3CF30001CF3C3A +:1059B000CDCDCDCDFFFFFFF6305FFFFF0C30C30C28 +:1059C000C30C30C3CF3CF300F3CF3CF30002CF3C19 +:1059D000CDCDCDCDFFFFF4061CBFFFFF0C30C305BE +:1059E000C30C30C3CF300014F3CF3CF30004CF3CE2 +:1059F000CDCDCDCDFFFFFFF2304FFFFF0C30C30CFC +:105A0000C30C30C3CF3CF300F3CF3CF30008CF3CD2 +:105A1000CDCDCDCDFFFFFFFA302FFFFF0C30C30CF3 +:105A2000C30C30C3CF3CF300F3CF3CF30010CF3CAA +:105A3000CDCDCDCDFFFFFF97040FFFFF0C30C30C82 +:105A4000C30C30C3CF3CC000F3CF3CF30020CF3CAD +:105A5000CDCDCDCDFFFFFFF5300FFFFF0C30C30CD8 +:105A6000C30C30C3CF3CF300F3CF3CF30040CF3C3A +:105A7000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CEE +:105A8000C30C30C3CF3CF3CCF3CF3CF30000CF3C8E +:105A9000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CCE +:105AA000C30C30C3CF3CF3CCF3CF3CF30001CF3C6D +:105AB000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CAE +:105AC000C30C30C3CF3CF3CCF3CF3CF30002CF3C4C +:105AD000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C8E +:105AE000C30C30C3CF3CF3CCF3CF3CF30004CF3C2A +:105AF000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C6E +:105B0000C30C30C3CF3CF3CCF3CF3CF30008CF3C05 +:105B1000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C4D +:105B2000C30C30C3CF3CF3CCF3CF3CF30010CF3CDD +:105B3000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C2D +:105B4000C30C30C3CF3CF3CCF3CF3CF30020CF3CAD +:105B5000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C0D +:105B6000C30C30C3CF3CF3CCF3CF3CF30040CF3C6D +:105B7000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CED +:105B8000C30C30C3CF3CF3CCF3CF3CF30000CF3C8D +:105B9000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CCD +:105BA000C30C30C3CF3CF3CCF3CF3CF30001CF3C6C +:105BB000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CAD +:105BC000C30C30C3CF3CF3CCF3CF3CF30002CF3C4B +:105BD000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C8D +:105BE000C30C30C3CF3CF3CCF3CF3CF30004CF3C29 +:105BF000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C6D +:105C0000C30C30C3CF3CF3CCF3CF3CF30008CF3C04 +:105C1000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C4C +:105C2000C30C30C3CF3CF3CCF3CF3CF30010CF3CDC +:105C3000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C2C +:105C4000C30C30C3CF3CF3CCF3CF3CF30020CF3CAC +:105C5000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C0C +:105C6000C30C30C3CF3CF3CCF3CF3CF30040CF3C6C +:105C7000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CEC +:105C8000C30C30C3CF3CF3CCF3CF3CF30000CF3C8C +:105C9000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CCC +:105CA000C30C30C3CF3CF3CCF3CF3CF30001CF3C6B +:105CB000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CAC +:105CC000C30C30C3CF3CF3CCF3CF3CF30002CF3C4A +:105CD000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C8C +:105CE000C30C30C3CF3CF3CCF3CF3CF30004CF3C28 +:105CF000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C6C +:105D0000C30C30C3CF3CF3CCF3CF3CF30008CF3C03 +:105D1000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C4B +:105D2000C30C30C3CF3CF3CCF3CF3CF30010CF3CDB +:105D3000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C2B +:105D4000C30C30C3CF3CF3CCF3CF3CF30020CF3CAB +:105D5000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C0B +:105D6000C30C30C3CF3CF3CCF3CF3CF30040CF3C6B +:105D7000CDCDCDCD000C0000000700C00002813069 +:105D8000000B81580002021000010230000F024097 +:105D900000010330000C0000000800C00002814038 +:105DA000000B81680002022000010240000702503F +:105DB000000202C000100000000801000002818003 +:105DC000000B81A80002026000018280000E829810 +:105DD0000008038000028000000B8028000200E021 +:105DE000000101000000811000000118CCCCCCCCD7 +:105DF000CCCCCCCCCCCCCCCCCCCCCCCC00002000F3 +:105E0000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCD2 +:105E100000002000CCCCCCCCCCCCCCCCCCCCCCCCD2 +:105E2000CCCCCCCC00002000000000000000000022 +:105E30001F8B080000000000000BFB51CFC0F003D7 +:105E40008ABB5819180238107C7AE0A58C94E9DFD7 +:105E5000C8CCC0B00388AF02F17E66D2F5B34A2346 +:105E6000D8F7241818182419184E893130EC9244A8 +:105E700088E702D5084A3130DC858A0500D967A554 +:105E8000E81B4EA39836F8BB3A2AFF912A84CE87A6 +:105E900089A3C93F86CA6F5480D03FD5B19BBB0947 +:105EA0002A0F00FE694F6760030000000000000039 +:105EB0001F8B080000000000000BED7D0B7854D50F +:105EC000B9E8DACFD933994C7642422610700703ED +:105ED000040D30208FA85427E1D1E0E5E8F0462EEC +:105EE000CA80AF0892448D356D39373B6412020287 +:105EF0008ECAA1B4A53A207AA247DBD4464B7BF5E3 +:105F0000DC206A73DAD37B9152A52DB6413D281669 +:105F100068F49403BDD796BBFE7FAD3DD97B672661 +:105F20000F5FDF395F1B3EDD597BAFBDD6BFFEF78C +:105F3000FAFF7FEDA8A297A8971072117EAE256494 +:105F40009D4008C9EBBD5AF78916AD26B9845405A2 +:105F500055632B7DB65E0A1B8DD3E8FD4BC4D01371 +:105F600004EE8F9B432611A2C07B05844C85FF4D18 +:105F70002744CE691D1EF5D37BD2AA2CB85AE3590B +:105F8000D72A99107D2A3CDF362ED5F3E4FC09A5EB +:105F9000A75B23F873710C21F5C76F9CFF8AD5A608 +:105FA000FF8D2499B9272FA7BFCC24332F4A847C97 +:105FB00054B828ABD3483FDE070D5DBA3C9690F34A +:105FC0000D2BE6BF32B6EFF3F512A96D2FED7BFF77 +:105FD0002AA2215E8866AA9189BDEB5E4F48A72759 +:105FE0008790CD859BD87A7329B2AEA4F7DBFE45A6 +:105FF000974B7AE15C2FD37E53FBAE871013C7B566 +:10600000C649BE9FE872BCEF7E2F391E7F9FC8F441 +:10601000DF0C42B00B5DFF74217A2DDCF7142E32B9 +:1060200047D0F6FA67CA49B4343DFC497A7D42F854 +:10603000ADF7D2D291F7FB687F530BA1EF9D54E3EC +:10604000D75F45F9E8BDEF4BA14DC0477BC6CF21D7 +:10605000017A9F303EB2E8746A7FD3F054FC918E8F +:106060004E7F4FBCC87F167F5589ABB23AC927E730 +:10607000AF3B80BF326CFCD5BEB8DFF13E297FC597 +:10608000DCFCC5F171BA9DAD9FEC1EC6E8C2E9E526 +:10609000A64F5ABA7CD2F7FAF2D316C0ABA77DB19D +:1060A0003982A4E0270EAF45AF4F0BEF407C444848 +:1060B0001CE94C484482F97BEFB36B469921009F61 +:1060C000D1E6615847904D4582B7B6DC2D52380372 +:1060D00024D13AAE88B6BBD72C00B803C7E79F02DD +:1060E00079680E5568B3E97AF569C643F3E835A3D4 +:1060F0005417603D5B89084A808E576D969702BDA4 +:1061000008B69F366F099B80071226643821F7F185 +:106110003511221A326DABF0EB9854EB504927C37E +:106120008770D1D3F7FD74EB577BDF23178BE0FF2C +:10613000F71058DF40EF91287BCFA4FF00DF39AE86 +:1061400071F439B46DE3FB00B1B5E9F3A3F00BE2F0 +:10615000FBEE2F64BE6CB24F33A87E504B443D0122 +:10616000FD89912DD37646255544F03C480E528A40 +:106170000C489766422ADB811F493B5938B117BE4C +:106180005344C0F514DCBE734D0B555DE7CAFC21CA +:10619000E0F3A04EC8B09CBEEBD9D6401979BCAD97 +:1061A0001D7A0EF93F46F9680C7DDF0C317BB8B5DE +:1061B000E4653D6A93EF0C41E07CE9E60F62C83389 +:1061C00040CC8055E8B5440C7B039F9E3F64171E6E +:1061D00007CB1FFEA88D3E64E8F40A72BF61B0FCD5 +:1061E000F169E7B3E8DA57AE1A2DBA6A84D2614B87 +:1061F000F1A294FE477ABAEE23D03FA384841329F8 +:10620000DE1B25085C0E4C87BEC12BA58F9424EFA6 +:10621000BD0E7A49F93356ECED071F52AE131FD667 +:10622000B8DE7AC97897AA4422EB228CA7C2789468 +:106230004FB7041F3609958773C0DB141F527C4A81 +:1062400027B44931413EA43F9D026D7B83E1C45692 +:10625000E48304D2C582CF63880EFCCAB93E479B53 +:10626000AC30053BFCDE7A15E150D147A0E3E87481 +:10627000408A0AD94F3A816F2D7E0536B87829B405 +:10628000BFEEE08356632A4945078B5F01AD8C5F03 +:10629000BF3E38FDE29E6F8913DE41BFE7978D93C5 +:1062A000363B94FE3D999CB4E84391580503D8F8D9 +:1062B00060B3420E089309692A5C46A2F4EE667840 +:1062C00044ED580B5C0BC03F9C8A7A81B40932C004 +:1062D00069D95512CCC17ED30503C713B55AD42B47 +:1062E000923FCCEC2B7F9E1E2E36FF70231ED629AC +:1062F0007EF3493C2C52FA505D19EA24A037C304BE +:10630000F88084185F48DC4FB7DE8F717EF692A369 +:10631000F83ED5AEA68EF6CC29C77325FA908EB37B +:10632000A584243C48A7B8066DB94426B02FA0FA2E +:10633000C95F40FB6759EC2F2D0801FC59DCBE9268 +:10634000599CBF05AACF289EFDD39CF2ED73C9BF0F +:10635000CCED711F7D96663F615DDDFEDB6302F76C +:10636000DF32881FE9CDDF27FED4FEAAE5B75978D2 +:10637000CD1309E293FC54493C51C4D746DBF7BC2A +:10638000959D80759B159135CD140FE6DB42A809CC +:10639000E829877BB2E8F3934F4AB85FCA5B567F20 +:1063A00009CCB7BDC11C5B6CF307B7CBB51AE09B3A +:1063B000F28566B7173790E80B826DFFE509B68C5A +:1063C0002D1E86FCF7767709980A01F9CFEB8F0529 +:1063D0005F05B9E4F793F8B1B7A5BEEDDC7CC2ED7B +:1063E000E50DE5613A6F2BE8AE11F8D814283CAD05 +:1063F00005ACFD93C6E1E5603F5B3359FBA3C6776F +:10640000C28DC817512D42EFD5138E972E8A17A42F +:10641000BF916FB7AFEEAB7BFD3B64DD077CB6D7BA +:106420009F735D09D8CF32310468DF1B3BA2AFB147 +:10643000E1E39B9E8A37001F2349422040BF582E2C +:10644000CA8FE5CF01E341BB80CB5321398CFD4698 +:10645000477ACA15B8B5427F19AE2DC1E7B2519E31 +:10646000C81CFD24CABF245CBC7CF0F29E6EBD013A +:10647000814452F9F3F74B392857816974DD0EBD19 +:106480005EA8233FF271BF063402FD914D619A0C64 +:106490007A24BE229262BC9F0822F6D3C01E5C41C1 +:1064A000D150B8ACECDFE87A352D3CE5550A97279A +:1064B000D71F32116C66270C2E039E78A306F82591 +:1064C000472502F2AF158623B7019F924858A0F7DF +:1064D000B56038B4D5E8BB3E9530FB9043AF179913 +:1064E0007C13E87F4F9E8EFD09D80B6B5D63002EF9 +:1064F00015E1FA0CE89D2B4E1F98CE23487B3918E6 +:10650000B374F4FEACE99CEE7D377D030293AFFBE0 +:106510009BCE874D2A4F2DC7055102A5182F46BA8D +:10652000689C2EE795A8067EE396AF8A641F6D3FB0 +:106530005ADFBF9F12033FC563B39B3AA3DFC8BBBB +:10654000F4A9C042E9DEDB7597589948C14F9522FE +:10655000D3FB5BEE7A383E16E8F98A73BFA7AC0A24 +:10656000A35F4AF77D95400FEB3D6F31B34F643F1A +:106570005D0FEDAF707FE47CDEA22C92621EEBBA61 +:10658000C7057F21C5732AB9B94FE2FED54E36BE85 +:10659000E5EF9C2FE87F7C0B3F172A4572B814C9A2 +:1065A000EA23A57C3114EF8549BF3B0FDB1EFE2893 +:1065B000512BFA08D8BDC2CE72B82AA4A711F8741C +:1065C0009748AA52C1B7561211BEC230DD7A50BDEB +:1065D0005F688AA099C8BD9281F7F357D51E5428E9 +:1065E0005D5A47911098994B603CD0AB07BD683F0E +:1065F000D55C92F0523DFD5AD1574CB0CB7A21096F +:10660000032C7A2DEC39E97FD4BE1AF4B9B2316A81 +:10661000225CC108EE110E152D437AB750FFCEC390 +:1066200016E2E0A71653EC04BE8DD3F1C11F8C1BFC +:106630001528AFE782D4F2C3CFC7147E6BBF712990 +:10664000C485282901CE0932C2494762F4D4195EB3 +:1066500046EE9E453AA9DD69CDDE85F2605E495081 +:106660005E6572D814C0CEC80953A4F0C6AA983E7D +:106670005072E382DD8EED21D107ED7C23EB9DE8A6 +:10668000FFB5FE595A910AAFD522D36FF7717D78C5 +:106690005E699F8FFE4633958FA2BEFDC39C0EDFC1 +:1066A0008E2D7A703CEA336697ACE75D82E18863B1 +:1066B0008EBCA0E27ADC7ECD3CEED7B41452BF068D +:1066C000E59D2C003F2683F3470B608F3EF76493D4 +:1066D0008449E1C8007F86FA25A494F9251AFD07AC +:1066E000FA2F7F85D39FF1B8FC9674FECCD784C86F +:1066F0000F50DF515505F0EF16E2F3C701BE0BE86E +:106700007ED2E8BBEE2EBE9F9C2B6D2B6AA1703D06 +:10671000962B3AF861349797C78879E2227D1E2F2D +:10672000140D803B5E2FE23ACE19CC6F27EF7A1D15 +:1067300076A2D95CA4119BFED9C1E5695B83E69082 +:106740005BF7D5AFC6A391147A4BE7F4C99815C689 +:10675000F8873F9440FAC33A53F9E90F945668FD1D +:10676000E93FB9445D83F82BAC3825C3B5CCBD5F98 +:106770004A3DAEFB4AEC7EA694BEDF60AF5B289E2E +:10678000DE561CFE78A704FB2E93A0FFE70D5153A5 +:106790001580AB3E1CE0F786A8B8C1B5BBBC12EEB5 +:1067A0001BB3221AC891659FBDA1C856B89FF52595 +:1067B000790BD0CB5B2E8A12A59F269B24C7263748 +:1067C00053E1A68DBF33A9BAB4E3438B7EA512FC77 +:1067D00054522892B1148ECD1F3768763A75D16D18 +:1067E00008DBB73AF9265EDFBF9EFDB47CF173D1BA +:1067F0008A8738E9853FF67808A77392FE7DE21A0A +:10680000FF39E8AD71FA19947E9B0CA027D3177459 +:10681000E385FE435C33C3D08E1B8668DAF4D8C7A9 +:10682000620EE241BE20A35EDABDA6250CF4D2E9D9 +:1068300018405A7A0DA7B2DB5D828A7245F5C655BB +:10684000D27454C802C43FE74A1B91DE8F517A8349 +:106850001E7B8CD4765DCCED957F2DAAA21FDFD553 +:10686000689637160F456F52F8A85F47F630FFE578 +:1068700012CB7FF97BCA2783F057CE53A3C1EDB16A +:1068800017F84AEEA62C4DE12ADCC8EC26F86A3946 +:10689000B46D50BBD729F4F2A387CFA394260E8FF3 +:1068A000477A3BEDD363852F0B1EB06FC5CCBEA9D5 +:1068B000666718F44CA098DA2782F66735E06744DB +:1068C00049BC1CDA2377CFC3757C1BFC503FD8171B +:1068D00082F8F8A698683429CD7CE148A728C1FE43 +:1068E00099E0FECEA29F7B5E6AF5909EBE6C712FF2 +:1068F000D029507B189669B77BD5525EAF3D1C51AD +:10690000D289EAD6ED2FA4F513FE2CF1FDD8CCC622 +:10691000306D8F825FA93FB9537CBC11F663114F74 +:10692000B81EE9EEDA4724E3503CDEBDB6CC122AAD +:1069300063F96FE83C7776291400027E80648F0348 +:10694000DD097689EA9BB5DCAEDD4A2201787886DE +:1069500088185F3B438E04AEB0F1E14E4965F3B455 +:106960002A6F43FCDE8AEFDE16676D4BFFDCB1DB7E +:10697000D9BE9D2C1A0EF1DBDB772AB8FE3B5DFBFE +:10698000D698A4E3B87790DA16C043B342D04F58F4 +:10699000AB1319E2B11B7EF89D19B04FF836B72B37 +:1069A0001F50FE326CFA679D3FA1C27EF69D8E2B72 +:1069B000965D4DE0FD44CB08D89767939476F496A6 +:1069C00056277C03C1EF8697904DFDC221B7092958 +:1069D000E3874F4982236E58AF052641D0E4BC9728 +:1069E0005DCD0AA63FCCDF7A134DE0274A06EF5F64 +:1069F0003B99E5396A67C275A0F77EC6FDD1A1BE95 +:106A00007738CD7B1BB46E15F8BF46362B05B137F2 +:106A10005EA529B5E19120C707CA3B471247BFD6FB +:106A200041F6AB14FBE9E786F794AE99E2E4BE7059 +:106A3000DF40A26F81DC9D17A3D51827E0707B0093 +:106A4000CF125C65A427C64F8A605E7FAB9005714C +:106A5000940EF44FBC86ECA0778DA507A85E82B893 +:106A60004F4689F3B93BAED293A46B27CA1786442D +:106A7000E992029ABF53027FB14C3E9DEC4FE7ABC7 +:106A800086754DC64EA85FEAB87EA926C683B3A612 +:106A9000A17C61BCAE6EFE1813E0A8CB3342A60108 +:106AA0006A3414C6315C7C5573412009DBFEBB4659 +:106AB000EE51418E6AA8FEB6DFBF27C8E2C9E9F4ED +:106AC000B64234C35F027EAD88789274DAB6ADFB0D +:106AD000A3B850D9CEF655594BFAD917DF1364F144 +:106AE000E2B55BC666B1B88B535F9DE5F6E127CF93 +:106AF0003CAE76839E79FAC4F5B0CEF5FF53221AE8 +:106B00009DF7EC3399A413ED464205BBB1AE434A61 +:106B1000690F096962F9F3EF6522BDD63DE7492C9B +:106B2000A0EFAF7BE19D4984C2777653CF6B23C141 +:106B30009F7E5A607171B37BD2627A7F9D4C56A75B +:106B40008AB34C90D93EE4F48F325680FC0A6D072C +:106B50006FC671DB972B6057AD7E86AC20BFD27EAF +:106B600068B7CDA784C45821157C2C1F71FA2981E0 +:106B7000C17740C1FDDFBAB6BD6A94C251D3F621D8 +:106B8000EA8BD9DF7B360078A8392039FCB89A36F1 +:106B9000A9D33309AF27E00A71566106F009E797D8 +:106BA0008E0D185FAD6E7FE0432900EF3BF516C5F3 +:106BB0004BA813F0FAA6145A00ED1FFC63C0A0A85E +:106BC000FAE0F01301C02B1D778D9A05717C277FA9 +:106BD000C3F81772FA8E47391DF3BD35ED5BD87CCB +:106BE0002EBDF801FC52D0370E1B919D7974D23620 +:106BF000B83CEFFA67CF3D6AD2F94E3FF7FB474DFD +:106C00000AF75D7FF9F747BF0E72F9CF5E1DF47A80 +:106C1000CDD3BF0C101B1FAE9359FCE0EC28BA85F6 +:106C2000A2FDCEFECA930087E0EC4BEF8D36E87AEA +:106C3000CF7EFF4FC30DDABFEEA5B9F9B0FEBAE7BC +:106C400067E7F7E7C7009F263C76B81238BE714069 +:106C500060CEC28BFCEAA2CBA18E43A301CE33C788 +:106C60003CB83FABA1F7EAA7029D36A09D85F6464A +:106C70008ADFEA67367F08FAA12F9ECD912206BFF0 +:106C8000A81A0C029DDF9987F4223D681FDDFD6B79 +:106C90008E523A4E4E4FB773E46315F45CCD335BBE +:106CA000D87C2EBA9D815FAEEC4BB7CD2EBA9D231A +:106CB000773D560089D78E618E3C8275ED8D9F475A +:106CC000B222FDE8074BFE07C22BE659285C4BE5D4 +:106CD000F0376490A3E73292745D00747DF6DC684F +:106CE00042F9E27DA5E766B0073D2F79F47DF4FE19 +:106CF000BA97DE44B93AFBFCEBAA81768CF805EA38 +:106D0000579E25C99FC3E06756339F93D4ECCFECC1 +:106D1000F4047AE9539D58586904F0FE09BC9F6059 +:106D2000FC5E9D38B8444841AFD7E5314CFF27F2AF +:106D3000102F1BF6FF46257E271D8532A0E389799B +:106D4000703F1D1DADF5EBB0FE99367AEE6772EA25 +:106D5000EE5F4DE511EC5D92AE09E14D92422ECF12 +:106D6000EEF5C860EFCE825F95326FCAFC99A1E65E +:106D7000577E263BEBAF92F9158E87F4FCC1E47B7E +:106D8000A0F50D157F3F920D1CD78DC7D31FA7D639 +:106D9000F7EF717D514DCCCA1197F6F5436412316E +:106DA0004716F5C27B1A36A894FF4E3F2D613CA8CA +:106DB000A5FD10EA6DB79EA84E13DFBC20333FA19E +:106DC000FAC0C149A0CF4EBFFC23E4CFEA674EA86A +:106DD000102F7EADED076A7769AF3C803D48D8EC57 +:106DE000C1E9EF1E9CC4F4001D3F059D14858D5F15 +:106DF000F3A273FC9A673E748CBFDE6C47FF60A001 +:106E0000793E90C3CB61BD1F1C5608E8D10FDAA5AF +:106E1000CA547EED07DC1E5A786A797DDE6F200F3A +:106E200036ED88CF00BBD9B1299CBF1DFCB5230A24 +:106E300001BD4DE4F0EF3DB4DDF1BACF80FC74C785 +:106E400091659261DB87FED085CF9947CDD9997442 +:106E5000BC99DD9169E0A2BAF546D971BAAFB2F139 +:106E600041DDEB95F9A0EF611F6A8C87F94241D8AB +:106E7000E74A8179952C7F2DEADE94F69A8DA7F862 +:106E80002318AF5274311923837147924423C45796 +:106E900089DFEFCE4F44347B1E6AC5E183B0C5CC99 +:106EA0005DFC62018C132031FD24FA9F2474B11F14 +:106EB000FFCB9D8FB0F09994BF34F9890CFDE6E0CB +:106EC00041D277BCBE7998A806F1ED16FFDAD6223A +:106ED0005B1EA625D8270F3357A178681548CA78B6 +:106EE000ED78A562BE9287BBE368AAE737294CAE6E +:106EF000AE25DDF7AE0138232C9F33CB85AF2F7144 +:106F00007CFDF364BA70AA42CBC1B3A2F89DBD2444 +:106F10001C53E8FDB9AB7A2E7F19BBF37C8E395E2A +:106F2000BC983178FC0D356F17F12CBA5D1944DE31 +:106F30002E5DFEB8170E93EFC7731C798C436FDD7F +:106F4000AF75639EA1B6B5C816F71BDEE92561CC07 +:106F5000E319E81F0EEFBCF39BB741DC39B730E40F +:106F6000257DC7912F5C8D71232B9F2F17863B2189 +:106F7000DE2FEB46B984F32C0F437E61B3C1F205DB +:106F80009B83FDC7F56628D16605E351D7E0B8A21B +:106F9000C6EB0F06B9CE6F2C0E209E0314CF20EF48 +:106FA000B8FF81F51D1778DEBCDB94207F78221BAB +:106FB000F305019994403CE0BCE00B6DC27C823348 +:106FC0006F9E8E7FB7CB26E6CD5B8D3E79F3EF28A3 +:106FD000B67C8396266FAEF99760DE5C23367FB76A +:106FE000A8B75FAFDCB9F2E63016C665B6CF86B893 +:106FF0004C733671E4CD9B41F0AF22E439E5EAD918 +:107000005877E6E5CFCD59B3C3F63639FE32B679B7 +:10701000FCE98FCDE73641FFDC91A416EBD4E40800 +:10702000596AD383EF292C4EBB4109FF50B1D71DBC +:10703000717EB0F23F87DE7A0FF90AAE63285E9B5D +:10704000295F7990AF4E11BB5EB5AE16FF341BFDC4 +:10705000F3857A610AC6CD92EDA0897C110846C3FA +:10706000E114EF4DF230B9B7E60D94513D4AE54DCC +:107070003122988F5275BAE135060F7F3AB82C3E0F +:107080006D36C6B03A289D60FD5EFA754C63714C52 +:10709000887051B876DD787BA83F3FC75AE70C254A +:1070A0007CD28EF7DC4B52D7EF56AB6CDDCD9155D1 +:1070B0002CBF5EE5CCA742FADA1E679D2E44FF5D29 +:1070C000C13821CBA78A5A84E7474C2B3E1E4CC6B9 +:1070D000C30DA833BCCB047DA8AC6A3705B8E6B2B3 +:1070E0007C4AAE16FD58B1D90759EF6672EBCA0F4C +:1070F000CE954E0F09BF565DDCD6061DFDF42D0D55 +:10710000416C6F6E30F0DAD210C6FB6E3A361B2F30 +:10711000076FC1BA341FC665D38DFF604308C789A6 +:107120003594B1F178DE9C90CC26E02B55B4E46523 +:1071300018B6FD127F6E163481FC6D17D8F36B5AAA +:107140002E4579B3F86787D17F5C5A4ACC403E1808 +:10715000EAF87DF9F527B8CEE6597ED4AF03C951D8 +:1071600056279B77B0F328497BC1E6D9314BC379C9 +:1071700076E40E304F9CCD3330FC0C5FDB0E9EC2AC +:107180003A0485F203A828450FA7AED3E3F2D677D9 +:107190001C0FEAF9E620AB0B538BFD6150FECD06C8 +:1071A000CF3716B27CA35A32BC02EEABA1CBB04EA5 +:1071B0005C2DF5633E4F2D1E7E0BB4B71DDCA25730 +:1071C00080FD2814435E03EC76379173516C307E5A +:1071D000AB1697DC06FD7590630AC7280FDB6FA915 +:1071E000C557DD01EF1F9CF29AD144FB3717FA42D5 +:1071F0001E90B76ED9C1FF83D61385CE3C1A91A9D4 +:10720000BEA0FA6BDB94DB4B503E355B9D648A7A03 +:10721000419BDED8A0DAF4864AE6988087747A87A4 +:10722000DADFFBD4BCBEE358EF6F5022F52AEA85C3 +:107230000871D6BBA7CE675BF400370BF2917230B2 +:1072400059A7B7A060786F7EDBAAD373E7B5E3F4E4 +:107250005FAABCB6BBFEFCB3AAD3DBA926EBF446FF +:10726000419DDE8F1512EA84BCFC2FA5D03EA32FD2 +:10727000DFB9C7739FB7A0FE8F06FB9C7472F9330A +:10728000D5993F2D88BAE87EABD731DF2B202FA5CB +:1072900003EB979155CE7146D53AEB6A2FA9CF7182 +:1072A000B48BCC118EFE97B68E713C1F1BBFCCF1F8 +:1072B0007CFCEEA98EF684C4558EFE97B75538DA5D +:1072C00013DBAF73F49F7C6091A33DA573A5A3FF6F +:1072D000155D6B1DCFA71F5EE7783EF3D83D8EF698 +:1072E00095DD5F73F4AFA7EE900A729BCBEB9073C2 +:1072F000F3457B9EB6358FDA25BACFDF9147190665 +:10730000E3DFACAE4B658F937943F77BB2A1867513 +:10731000CCFB8F9B035722D7A13D958DE11506DE4F +:107320009F310FAE649AB3BE5635587D32ECE39C64 +:10733000F502CE3A6355DA86793ACFF12F77099381 +:10734000FAD2552D74CAC160EB9415C3F5DE10E571 +:10735000E2BC2517A3A85C60FCED6309CFB5CCC9DE +:1073600044FFC2B69F423C5AFBA96B34120317D3A9 +:10737000928BF2553D235FC56ED63ECA230EA52ED5 +:10738000CE92BF804DEFC37EC5D233CD6583D3AFE0 +:1073900052E20A873FE9BE3605D6A5D38F051E9B6C +:1073A0007FEFD68F339448213CD7E4B0496CF11A73 +:1073B00052AB38E01E2C9C9FD40EDC45198EA4D015 +:1073C000E32AA9C5BAAB9615610C02903AE2E0D364 +:1073D0009D8BFF47198C4BFDC219CE7532BFD0ED86 +:1073E0004F53FD86FEF40EEA4FA3BD73E947AAA7EB +:1073F0004C5EFF65303F82E943F73A3F2F3FFADFAB +:10740000C059ED875E81A25025EE0FF34402FBC305 +:10741000E6599120C4E7ACBA79EBBD56CFA5384EFA +:107420002C5715217E19EB9A8BF1FA262DAAB13C27 +:107430007114C769CA16F5547562751E962FD6EA7F +:107440001F18BBBF9FB88BA69268AA78DA4E0FCBE5 +:1074500007C5F4B55D604733F35403F6DCAD074F61 +:1074600045208E2497C93AECD70905E61D5B7E8F2F +:107470009028C699B4A0887657ABDF81F30F04EF4C +:10748000CD1E819FFBD8D22FBC5E3575DC251DBC7F +:107490005B00DE6903C3EB05788B60FE6D387F8D82 +:1074A000C748897F85842B6703DD4E7C3982E95686 +:1074B000CA36201F3BCAD8BE9C1A02077F5BFB1C42 +:1074C000CADF0F7BF2B07E15F9DA3AE770A347C73F +:1074D000792CBA92C21C8C6B04A2B1B1C594DF3274 +:1074E000A36C3FDFAB9F181F652A6102F12CD92FD7 +:1074F000627E50E5F110ABDF1F383E9B667523BD01 +:10750000365F29934D426F9D75AC90AE6B72EFBAAA +:10751000FE8F279BF1279FD7479664615D8AF44CC5 +:10752000B03FBDEDE3F872EBEFEF79B8FE2E20052A +:107530004C7F972E877C77BA71DC7E4C3D8FF30EA3 +:10754000BDBE9E9F2FF0DFD30571262BCE4782D381 +:1075500052C6E57BF1CAF295BDF45D6E7452FAC96C +:10756000D3A7629EDC3AAF40D599B35E98D3D7A239 +:10757000AB15472741163FB2E8EC4DE2734FBFF819 +:10758000F482BC5CD1179FBFF2F07CC37F317CBE1C +:10759000023E0DBD6666B2F3E9E4D05709E6A50ADE +:1075A0009D7268BD67F1BB7BFD7FFA2FCA4FD6FA8B +:1075B0002D7E48DFDF4CB9AFB1F2AB999CDF343898 +:1075C000654515CFAB656FB75E0AFBD7A01FF77D8A +:1075D0009965313CDFAB105307BD9069ED6BF879CD +:1075E00023AB5EC957EAF4CB34D7FE45E575517D30 +:1075F000CEDB72FFCD7D8E2A895F17BD266B69F2C7 +:1076000063833C7FB48BE7EB0AEAE28DB01F2EB8B0 +:1076100095D5FBEF51C86AA8AF1C51658ABE5CC8FE +:10762000DF147D3F83AEBFE0C5871A4702496E3540 +:107630008AC0CD7846331C76B8E0AE78B98F3D9FCE +:1076400002E33CA531BD5B5019C773CE4DCF8FCF40 +:10765000023FE195B796EB101FF828B718F74F6770 +:107660005EF08441FF9FC921555817F6C2CCD7C0A0 +:107670008FFF7D43578E6CE39333DF7D7D86428998 +:1076800074E6B9D767C848AC8463FE0D177F310331 +:10769000E0362B48492DE4EF7495C0B8351ACB97E6 +:1076A00059F53EBB86AB2D70FDA9379BC513F3C5BD +:1076B0001DD0AE878018F80D3C9E7FF5696339D4E4 +:1076C0005F66772902D4E33D2498A69F5ECF9F781A +:1076D00048003F4BEDAC85300BBD1F3A042837C73F +:1076E000B27DC9F922525244F5BEEF70ED78F4A78D +:1076F0005DF54E16FFCBB309E6FB7A6ED41260AF90 +:10770000B7CBC6375681FD5E25633DCE76F930CACC +:10771000859B8EC7BD639CF5B93C1E7DE8AD3BE201 +:10772000E5F4FD7BA688C8AFFE1353B2480AF9DD25 +:10773000DE5086F3070ADEAE2C07B03EA67767F46C +:10774000EE93FC3231B3A889548A4453A178F1975F +:1077500011F2B68DEF5A4412D6E9F3171A088ED3F8 +:10776000D1A0E1B5AD411F5B4C3706DF6A08E27579 +:10777000678381D7871B4AF0F9830D2187DCC37C9F +:107780006F97F0760A7FE5F3BA3ED040E7B5C1B116 +:107790006B22957A4AAF5D3C1FF540E9D4ACB5FD4C +:1077A000C4C1F634740D9B3396230BEA4DEBF4BD44 +:1077B0005BFB817F4FA3B07A11F83577CB917DA821 +:1077C0001FA3058B6CFA91FA6D0584B2E2BD2D23DF +:1077D000E6CC29407944799976388AFE7841302E72 +:1077E000401CB1E028BB6F9DB7407A5141FB61EE70 +:1077F0001C4101BD594ADA012CB5344A2A68FF9967 +:10780000794BCAE13E99E8BC3F4365F20DE356D09F +:10781000EB6C2DF2236D3A7CA763B7F92C5DCF1F7B +:107820003B3C06E4791E7CF94F2AEC0B62BF5235D3 +:10783000F0630A5E3C81750F31A15B85CAD8E35ABB +:10784000F51C99EA19DC0C627C952A16CA2731D0FE +:10785000B118FFEC89CDF1C37997E8297BFF5DBEB4 +:10786000E8DDFCE448580B523E4AE62FD6C7C27406 +:10787000D3F902CF5F1CD7D6C5CC4268D3FE53588C +:107880003B46DF7F213B3A52CC86A28BAA58D79742 +:10789000A06DF5AF8A41BDED9B5CEF107FB408E4AD +:1078A0002DD9D6693BD3D696599B68EC6AAD77C380 +:1078B000A13FBD067AAEFA45A11D40A37A8FE1FF34 +:1078C000C0435877DBD6D0A5C7144E7F8B0E542407 +:1078D000270409D6D3A909213186EA8F09FCFB14B4 +:1078E00005D3C24623E8D7841202BD19F231BF7115 +:1078F00042828E6393AB0969BE8382795FA0E336CF +:107900005637ECE6AF67BD2C3F504FCCAD90072308 +:10791000CF283AE623799CF2B465E7F87EF52E2F5E +:107920006B2A9B4CDF65A07FD6C818075B5F142FBE +:1079300057E93CEB7F5414A29615F24A58D7B03E53 +:10794000BB7DF854969772B41FE275B4C16C331BBB +:10795000CE0F541F786834D4055493F8CD5F037864 +:10796000FF95E51F4F1DBC32EB6ADADE40DB107F6E +:10797000DDD0F1BA1AA5FD8671B8AB3BA65C07EB6A +:10798000ABDE2612B188C967783CC573387E994C46 +:10799000F9E49AAD23E77A299D9F1A13D645CA07C1 +:1079A0002B7DE39A3568ABFA04909B95BE89CDC0D8 +:1079B00057EB27F2EF359089AF86655E2F45F96268 +:1079C000D8968618D427EC5F59791D98D9E122936F +:1079D0005BCA88983F94B26398B7F843333BEF0291 +:1079E00029FD8D940EC532E992E97597CAE867B60C +:1079F000C8182FA6F75B95A940977818CF57B432CF +:107A0000BD3FF6450FC69D8B6BC377A25FA097E283 +:107A10003E653449FE605EFA12F88D8E335E27E5CE +:107A2000700EE1C75E162F2C5EB16C3DBC27652E33 +:107A3000F1E1BE5C62E7A0C8B7599C7A979868D715 +:107A400040CE03C548DF5D01C617E6C3A5C817FBD6 +:107A5000C58ACBEE86B8A4B066EBBF005DB38B09D8 +:107A6000D015EEDF43EFEFE7F494B2433AD06F3F27 +:107A7000A7672C219A501F63DD7F41587B27C8DB05 +:107A80003AEFF373348AD7E19E707C18A5C39DDE6C +:107A9000E763C102A4C3188DE2FDCE2D1D316D1424 +:107AA0001DA7313C42B7B5C7FF997A23989FEC4098 +:107AB0007996B31F5E07F24E9FBFA2D1753E95C364 +:107AC000F5057F5E3C26A93FC284DA1AA9B1579F0B +:107AD00068D43E14DBFACFA1FAE0C947591DFBF583 +:107AE000743E9077BA0ECCFFF64C9013509FE5A3EE +:107AF000B080DFE29B3806EBF3E8BA09F8253D13C6 +:107B000065B4B3561CDB3341C4F812F4077EF08D24 +:107B100062FDA9A044406FCA8532EE5765694F786F +:107B20008201E16396D715F485786ED55B62CBE36D +:107B300092DE3A606C17E1676E1CEDB19EEE029129 +:107B4000FA95B9C7170AA3E9787778B9BF9D4BFDB5 +:107B50006D7A7FBD97E9A5FB23E69721C4418CEEA2 +:107B600002D44F243215AEF93715E747FBB14B7DF0 +:107B7000FDEA6EF41F76F8539FD39CEE63FBF92663 +:107B8000FF111DF8AD9E50F907B9D019BF59FAC3BE +:107B90003A9FE0AE27B6F48992CDD65837BF221F60 +:107BA000F480CCEB93643DA4437D6579E634F4FB2B +:107BB0009EF432BD271DBCF20638A7A1FE2BCB0BCD +:107BC000EDF146319ED45340DA815FE56098D8F3F9 +:107BD000BF963E6869D0F0FAC4D4711520274F4C87 +:107BE0001D5EA153193834E9C75D90673AB787C95C +:107BF000EFB9C3B7E1F9C773268B37015B615CB29C +:107C0000F3113CAFFBB81C7910EB6AA13E8282B441 +:107C10002DDB59BF55CCF16272FDD4ACB0E79B1B94 +:107C200058FC58BD7039C6B554AEC73DD15BF1DCC8 +:107C30008687DA32385FA911D364DF3B6078D00AD7 +:107C40009DDFC3502F4CC2F74D2F8B1F59F522EEED +:107C5000BA100B9E191C9EBEE7329CF4B0F65F165C +:107C60001DACF7EB8470BEDE0FDFD45C9048C2160B +:107C7000FFE8ADEF56F1FE59A88BCF823A9E68FC23 +:107C8000EA22908304EE8FBCFE3A42F8F795904FBB +:107C900083728FBD0E3DC35517DF475E0C67DB5DFA +:107CA00017B11E9883D7F1613DAB4CBE29507A9F26 +:107CB000C9F8ED0CF06B6BA87AD02040249B3ACC2D +:107CC0007F96FBFBF28B7787471A363E170CC73E31 +:107CD000A1FAC0428C23D4ECF763BD7F35E8BFC95D +:107CE000706EC0ECF238CE0B843BA13E4F39C0C65B +:107CF0007B12E0A1F7FFA85715C0BA8FC3FE270F6C +:107D0000EC495462875E0E231E62DEF031A2337DA1 +:107D100026539E88655BFAAC3A061B865D2A71F88D +:107D20004BBB7CBCEDAB8EC54A7BEB3F8E6BFF0F34 +:107D3000F59B55DF715CFB0FF48776A9F14ED07788 +:107D4000E60B1E03EC177D1FCFEF9A2B4BD00EC412 +:107D50008AC808C0C32BD92AEAB9D8F39E7DA0E708 +:107D6000666BD13735DBBEE14CF61BA361FF956234 +:107D70003CD331DEA8A18D47E7EF00BC5ACF5FC9E5 +:107D8000DE85E716E97B06E60D0B0F8F5E43DBC34E +:107D90005FF0E0B9216BBFE9E6CB7C2E5F2DAEF33F +:107DA000802AC89B1FF46D2DCA9927E8CC8359728D +:107DB000A75E98E0C8073C097696D24F95A310A21B +:107DC000A4CF4BF1B9C9F9AC85D723A49F2727CD00 +:107DD0003C57A03CA79F67069777C2E558D693DF2C +:107DE00085E9E7DCA03B4FE2D653D6D5D253DFE29C +:107DF000FC2993E8153E3ACFBA44FB3C1FBE1D9DBB +:107E0000047EF0071A3B0755D2F6D0CB609EBFE93F +:107E100009DFEF9D8EE7BEFEC99B37747958E923D1 +:107E2000BC2EB38F1E62FED5ADCC5FAD9B3F15FD62 +:107E3000BBBAED6374FB3945F7B5EA4286430F0DD3 +:107E4000F31AFC7B7B26EAA3AA0B017CFED9CDE7C3 +:107E5000759C5FE93B9F1F9F5BF3DDE5D2B38726EF +:107E6000FD74179C73AFFBBE227A6CF3D47D9FD751 +:107E7000FF7BA9DE75CA7B18E45D2E22C9FA2ED0DD +:107E80000FDB54AB1D6E9E330BFC5A9B7E2803FF09 +:107E9000ABF77DF8CEDD361FEF6F56A6EE9FE1EA19 +:107EA0003FC61A7F21F677C393D43FB01FA3FDE5E9 +:107EB0003F7B2CF8507F3D24BAC6CBB1E6BF11C73B +:107EC000B3FCEE8BDADA574D19F8345E0EFBA79E41 +:107ED000DB8801DF9F785C0EF94276BED518BF566D +:107EE0005DB8D441EF5EBC8F73DC7FAF21E8A8D7CB +:107EF000BD235A8775DA1779FCA98A7AE6F8DE9EDF +:107F0000918E3ADDBFC1F149E1B83A0D1CD77CC171 +:107F1000701439E4B3178E62C7FD4F0AC7428DE96A +:107F2000AFE5FC3A5767E766E71A42A889DE9A4B45 +:107F3000EF7B29AF7F995E357A9D2B13D38FDF4579 +:107F40004DB0FEB40DFBFB1BFE7CEFBBD762A22A3B +:107F5000E8A82B90789DB75BEFC0396F56EFA63934 +:107F6000BE0F675D7D12ABD774DFFFD0C7F0F28D17 +:107F7000CBAB09F8D3D4574F796E6D975FE0DFFB39 +:107F80000C8A8E38376F5B75BE9F155C72069BEF4F +:107F90001B975F4F20AE2BE7A6FEBEDD413F83BFA0 +:107FA000450B639D784CEFFFBB349F149EE14978ED +:107FB000AE413C4969F0546BC1A3B3BC604BF0F3D4 +:107FC00081A724C3A25BFFF8D9CAE126172E413E40 +:107FD00092389D5A60FF96A2BF95FF68D13E5FF828 +:107FE000C383A4EF73195F0C7D170D92BEC55C0EA1 +:107FF0005AF4CF179E5B0709CF7516BF05C348AF6C +:10800000CF0B9EAF0C129E6316BD8CCF173FAD49B0 +:10801000FEEF1F9EBF70B8F333581CA4A5849D27A4 +:10802000F14991078B8481E5C257ECDC676B853E93 +:10803000679DCDBBCEBAAF74EBFC355F673A795A1A +:10804000A924F2807EC71A583CE00DBE3FF9755551 +:108050005326C6E75DF3B404F765F617B7F9EF5595 +:10806000CE73B903C9F1A40C96FFB931EA7C6FF95C +:108070008A0C571D9989FD2CFCA51BEFAF056F617C +:1080800048620E026F145F5945FDEC1B3E6B7CA5E8 +:1080900093BBA1E22BA60F0D5F03C9FB5786882F68 +:1080A0004B5EFF5AF1950FF89AFE37FE1A2CBE165A +:1080B000FD4D1E8784AF5B872A8FDCAFFD6BC5D774 +:1080C00060E5D1BD6FA3FBBB507FDF17F8ACF1E7D4 +:1080D0009EFFD3E2D11A6F659A7D5E3A7C0E0487CB +:1080E00075FDD03748BCBAF79F5F345E5DF37F6A99 +:1080F000BCF2F1868CD701E0B0AEF220E5DBF2EB0A +:10810000DAD4D4DF111D97C9BEE3365EA83D321F15 +:10811000F2C77F27617EFAC89E391BECF540E33237 +:1081200099BF7DA472F606889F9E8B6460EDD9513D +:1081300031F4F36990575EC4DE738F7F84E3CB9391 +:10814000996DC57FF380AE47238BFB954752695BE2 +:1081500017E68D6CF495FAE2FB0831B64F833CC408 +:1081600082D47058744E37EF50E97B34F2F890F4B3 +:10817000CF40EBFD0FFF9841EA9F04F6CB25C9BF26 +:10818000BB7319E0B34D64F570C7E156017CD78D20 +:1081900060A7E52BF2F7029DEECE64F9C30ED5D8A9 +:1081A00000F913CFE2050F6452BA1D5D9A2DD8CFA6 +:1081B0005FCEC964FBAF19AB52EFBB16723EE87DD0 +:1081C0005F20E353F07798F75BBA8A7D7F8CC8E134 +:1081D000518B6CE74ED7BB9EF7A1476600E1389AFA +:1081E000E6DCFF02FEFEF225FDBF4F6AD9F77D28CF +:1081F000DF8DB29F7B4DF219978F33FEE8D24C7A18 +:108200007D43887EE73EE0A3097E766E4826455092 +:108210007F658D932B934E95E2FD5DC5180579CD55 +:1082200014E3DC9C393DFD38E9F06AADC79A074498 +:1082300011BED333576371C46961426641FCD013E8 +:10824000BA9BE50F191FE4F03AC499B5198946D8CD +:10825000F7CA749D36783BFEEFECFF06CF3B8E8865 +:108260003A9E6F77E16120FDD094C9F2C9B952748A +:108270009317F226AB8594DFB1DB98C9FEDED1A45B +:10828000CC64BD14CE336E675481EF5F2C9359FEDE +:108290008B90E8A885B6F927717E73BF972BB17ACA +:1082A00023F22693E7B67DEB46A5929F5F70399D3A +:1082B0009459E2A8735C12B95B01F95CB260A162E7 +:1082C000F8E1B981E32FE570B4A9D15153FCBD7831 +:1082D0004AAB87387E3A8E459BE0BB1FABEB05ACC3 +:1082E0001328DDC8F86EF5C683E2067ADDCBE56FAC +:1082F00021D0C036DE77395DDBF6F94603FC6DC967 +:10830000FC0D1D98C271F36E82F99027B79F6E81A4 +:108310007C48B74078FEE4C64AA86BE8E6F56D2FC6 +:10832000D3E78D80BF397928DFE3367E5807FAB965 +:108330004325785EE6775B3C09384F60F14B524F3E +:108340006C3CDF00F5C38FA89D13816FF29A6AEF32 +:108350004B953F7D89D3E18FFE48562A3FD0BA5ACC +:10836000FADCEAB748369454FD1757BAEC1A877B03 +:1083700098A7F30C4991C74CF261A27F3FED975C3F +:108380008FFFC295E75D722C759CF1579C7FDB12C5 +:1083900015EBD16E991E3C8762C163E12BD76478DF +:1083A0005AB64472E8DBD50B325C7E0FC3EB0D1E70 +:1083B000E35158C723FB7E3A11CF51B9EC834F8A62 +:1083C000AAF0FC0ED2A9809E785F32F0FA4683F3C1 +:1083D000EFBCBC41A2DBA783FDAC9752CAD51F39C5 +:1083E000FFBCB1E296A5087F4CD201FE13AB865DBF +:1083F0005F06FA65851282EFA69F88DD9B799B6DEB +:10840000FD49BFC605D7AFAB6EE9D76E2D5FE1A4BE +:108410005B9BCAFC02F33A268777521E9D85FCD5EA +:10842000BD7D269DFF482267CA56D69DC0DF995A5A +:10843000CC7F7F5F8CEE9849F5CD2991E549CCAF93 +:1084400030BDB16467A41952A7A7EAAF78A99BF61B +:10845000F30618DFFDB6BE7FFBE8E6A7713B9DFE85 +:10846000DE8C634485F7A375A9EDC1B7F50CFEF763 +:10847000C442A341BFDCB43175BFFF05CC4CE13928 +:10848000F517A92A557CF22A9DC1BB3A92FAFDAB99 +:10849000F44CF61CEC520A3C9F0B64703DA78F060F +:1084A0003DBD3A0DBC1F060208EF3BCDF7DF04755A +:1084B00020EFBBBE03FF4E80F1C5C100E3EF53FBCD +:1084C000562A7940A71641077E783B3B3401F86D68 +:1084D0004DEC049E7739C0F1FCA62F3225301DE407 +:1084E00065D1DC3C4A978E55242418E9F5FF9501A7 +:1084F000E637E4F2782DB57FEF82FDA3AFBE8BFEA9 +:10850000871C1E7DE34456020575E0A744731DD603 +:1085100019EEF3B1BA52129A6EF7E3BFCCE138B557 +:108520007F68F45E1A71F9417DFCBF7835CEBB3FA0 +:108530004387BA94239552E7B514C893FB33F0FBF5 +:10854000B86EB94837FF50FDC053FB87E6070EB43D +:10855000EE0D81A241F981E72A1FD9310DE4488D42 +:108560004F4AA57F2D3D7D94C7DFDDFC635DBFCA0B +:10857000F9E8FD44FF70DDB1DB09CF4DB54E782C35 +:1085800079793FD1E45B0378229D13ED7E299933FD +:108590007D003BCBF253E9E0DCEED213C07940879B +:1085A0003BB9BEF96DFD23013B1DDCEB3F25F2FD20 +:1085B000C1A3AC2E776C644D459ED1CB9FDFFA9C56 +:1085C000F8D2B233EE71FEB3F3A165E706E2C3DC85 +:1085D00034799C4970D099BEBF46D655C8D74F0A4A +:1085E00018AC4DF47970548B94F1BA51628C86F3C7 +:1085F0005FA7F6F9F0EF43995B3D89B15404DEDFE4 +:1086000077F504FB7A7EC5F974F5926CFCFCC4FB2B +:1086100062687E3ED69D49F81DB7378EE5CC83F65D +:10862000238745D0D0E4A6BA3512ACEF8D00DB77B6 +:10863000AEDEF83AFA8343E5F3D5B54EFB7F155F1E +:1086400047D2CF927BA601FFA4C3C36B1C0F4B2361 +:108650000BE7827EBE65A380FAF627300E5DC82D3B +:108660007218F5368931FB48348A0F6A424EC022AF +:10867000001FFFC0BF5B254754FB39B9DBB6DD3FA8 +:1086800017FC43B7BCACC8627C5C91C5ECC29BBE16 +:10869000E81F40DF5BFAF96DA1F6603EEDB231A054 +:1086A0005BDF094639B5D6B391C345FDB467F1FB2D +:1086B000C57C7DA4C7C56F62BCFAC780FF0A0DFDEB +:1086C000029F87EA7DA88B7EDC877554965C59FEF5 +:1086D0008EFBFD6572D4E13766661539FC77B71FEE +:1086E000F2377B91BAFF15595FACBDB836EBB3B129 +:1086F00017C3389FB9ED4652AE5BD8799013C73E89 +:108700009A9B4AAE239F100EB73CBFBFCFC7BE9BFC +:108710007C4D26EA9DDEFD547E02F6CB6EB980FDCF +:10872000147CF7E3917D3F9B0875BD27B6DF7F532F +:108730002A7ACED299DF44BAF31DF1BCB50182F595 +:10874000DF84CEF7846D7CEBBDA4BC0C10BF5CB69F +:10875000F24ADC4FBEB1F2EAD16B4AFBEE2BFAF4DF +:1087600017A2FFB014E66DE4FBE91D9EAA7DA9F6F1 +:10877000811CAF7DE3C44EFF7EE9C6F266D8526F1E +:10878000CAB8E64BD114F327F7351B53C7E31EE4F1 +:108790007A2AB9AF31E9BE86E2A37B9514289BD62D +:1087A000BBAFE9363F9F7DCDEF48CFCF67A2FCA797 +:1087B00086EF7B167FA9D11D5752F84ED1FD8F0948 +:1087C000F223D2F7805FBE957ABFF6387FEF771B32 +:1087D00087A8AF8E39F733E9E4EF7B9F91FCB5A909 +:1087E0003DA3400FFC6EEFC76FDD0FEBD9EB437C71 +:1087F000BBC789E812DF5FF8906F2DFBDCA132FD6B +:10880000FFBBBF1B817F37DB2D1F84C4AFBF8A3EF8 +:108810003FBE4F9C02DF596CDB9751956A9FB35E58 +:1088200017787CC919EF21DCBF5BCAF94DDFF774FB +:10883000AD3D1EFD26D757561CE07F67313BBB641C +:10884000C14215E23DB725E34D04372BFA65857B20 +:10885000E1FB17BFE4E7B9CCB59929CFC7FD86E3A3 +:1088600077A038C48A55CE38C19205FDDB9B938929 +:10887000D47559163FA79B6FA8F6A52D31B4BCD867 +:1088800040EB1CA10FCEBE2C25B55F8278C73212FB +:1088900052E0BA84D44EFC3145E5C9DD8B119E5FB0 +:1088A0005A7FFFF8E37B27DAFD98FF0F11FE85A1C1 +:1088B00000800000000000001F8B08000000000086 +:1088C000000BDD7D0B7854459670DDBEFD4AD24924 +:1088D0003A9DEEBC091D020818620742001FD02114 +:1088E0004482B2DA810041519A87184948A2E2CA0B +:1088F000FEBA438720467466C2AA8CBFE3B80D82D5 +:10890000EB286AA2D1418CD8A0F8D8D59DA0AE8B17 +:10891000B3E846C7415E4322A32BB3CB0CFF39A774 +:10892000AAD2F7DE744370C7FDF6FBE338D7BAB7B7 +:108930009EE77D4E9DAAB63915C63C8C7D5B73FBC8 +:108940005F4D628CFDABB579BCD3C1D859FC9B1E81 +:108950007DFECB3AC6221731F6E13A3B8BD8A01CFC +:1089600036558563D4FB53AA8931E8E85FE1C14AF3 +:10897000190B2D50C33B94C1F5B2705CACB7785E57 +:108980006A30463FF2B9A04665113BA3BFB3F06F12 +:10899000CD9C245DF922A753F4D39A182C62EC885D +:1089A0001CF7513EEE91307F2FFBBB488C7B247C23 +:1089B000EE716F7E04C61D131DE78666FDB8BD2CE3 +:1089C000B48AB9619C70A2734701C3FF8CD8264456 +:1089D000DBEF759A08AEEC48A689653076876C1B8C +:1089E00067BC0F057C8DF56BCC7E8B161FB7A77A05 +:1089F00069FEB25C33473F4F6F8A938FCB9CF981FE +:108A000064C68E6E4BF4133CA6258747C13C2BED04 +:108A10002CE480793EF8E4C59FB1118C2D13F8AF9A +:108A2000097C6D41781C35F5DF938CEBFAC0E4DCF2 +:108A30000143951DF45BB4F0BB2B85C3EFE8F673DF +:108A4000C3EFAE143ECF7955FAF9CD3F98A82B1B52 +:108A5000D7FBEF7F7BEF04ECF7DFFFF63B8BB6FF36 +:108A600005A77359243D5A5E52ABF8C34583C77DB1 +:108A700029D53A24B8BF6480E392D3F9D4BF5B65AB +:108A8000CD1D31D655EEB453FDF981728B07E0B997 +:108A9000FC6EC5A74017339CBC9FE566E6EF80F9E6 +:108AA00030B337BF1AE0EE696DBE2310A39FFF23DA +:108AB000E0FD8D23901A8BCFE4F363410FB2DE0209 +:108AC00073D012ABFEC25A3D7C7B19AB8A35FF1FB7 +:108AD0003B395F0E951EE5F8C6FA439DC7DD820E51 +:108AE000D36D91DF33155E9C807ECA2E605C437D22 +:108AF000E3B8F73BF5F8338E7FF4CF6A5D2C38BCD2 +:108B000026F83F1800FA89F93D99BE7FC0DA1B7735 +:108B1000137F27F9762018B62FFF09A09DAD9C7D05 +:108B2000C75BF09A25A614D0FA16070E5412BB9D07 +:108B300079B018F1FE6DD5833F2985A91DB5065B77 +:108B400093A1C1D1F58A2FE41D3CCE07B84E90A366 +:108B50001FA13CBD08FB639C6E67C2FF65333646B0 +:108B6000F5D7A3506177D9BC3B347CEB5EFBDD3A93 +:108B700056CCD853D6C0FA64783FFAEEAFD73094CB +:108B8000792C4CF3FEC2E2BB85E0CD18F1FDA16D5E +:108B90008EAD9BA05E6A0A97938CF9F203E335725F +:108BA000C2ECA4F250F1F3611CFC5CA89C92EB8C2B +:108BB000370E409EE6377786A34D4965ACCBEABDBC +:108BC00009D7D33F3BC1B90D5038D7EABF1AE1F3FB +:108BD000C10193A9A580BA35239DCEE343B0826B32 +:108BE0000AEE1F578AF2C7E24F80A954431B36157D +:108BF000E868862384FD957E38E719C4CF83B536AF +:108C0000AF8AFD4DF37EAA4279EE5536EF7AE8AF92 +:108C1000AC67C45E37F43F7F8EE264D07EE6EC51F1 +:108C20009E5E585FD25AE8270747B8B7AAC2CCD889 +:108C3000D3F89F97323E6180C55C45965F6C9B0977 +:108C4000F2609CA7CBE40050AF4C7BB1CD0EFDDEB3 +:108C5000D312C872A6C1D236DFD7661FC658468661 +:108C6000BF67BA8FB1D99BEFAFB25F01EB7C54B451 +:108C70000F3DD0E6CF63EC5553B04081EFCD9B77ED +:108C80005499015EEE4239FE2B6DFECB613D57DDFE +:108C9000B2630DF4BF25ED9FAACC38EFC572FC9EE0 +:108CA000AA8A9130FFCB65F95FEC385F77926C0F41 +:108CB000F39DC298654474FEE62C18DF25CB9F54C3 +:108CC000CD84F13F2E6FAE30C3F8C7D2FEBDAD6884 +:108CD0002C6393E7943BFD50EEDBFC1F5549809FCE +:108CE0002E06740AE53F6C3E4DF377AB26DE7FE837 +:108CF0008F34BFB2C5A171F85D617F6AAB8275AF79 +:108D0000B6F7BE85E4DAB43664CF4091A4703AB1C8 +:108D10005B9AFDB9003BCBAEF2482E4DA79DD36BBD +:108D20005E643CEAB181F218288FD794B378B96BAE +:108D30003D5B124BDE76BAB81EEE4A8CFDBD228D2D +:108D4000CB03801BE993D483CCBF33865E1997E6AF +:108D5000A07EF627B290DD15E5B76B8187A7005F8F +:108D6000323B9FA7EC6790FE48E3729F85AE75216A +:108D7000DFCCC12E60E9853E258474CD9A93C2A3D1 +:108D8000907658C43C0FF5876AA2F97A5465493544 +:108D9000F49791C8829DF0F4A4332A437B7FA723E4 +:108DA000DADF7B82EE2B0B03DBB1BFCACCEC92D6B1 +:108DB00082683F30EF0DF609BA799BA7B8F0FBDC6B +:108DC000925B8B34F02CE2EB003AA07630CC33D3BC +:108DD000810FBA7AC68DD804F3FB06E5AE27BAAE8A +:108DE000B29EB91606F5B6B8843CF1F2F69E0A2E8C +:108DF0007FFA6F4D0A6F43FEB4FB4A104FB2DD0D90 +:108E000002EE15F7CEF919D66BE8B1301BD45BD35F +:108E1000599EC9CEA1171B4E5FC6C213356573C4D8 +:108E20008A72A7E1F4347A5F71EF7B56E453ECC7A2 +:108E30000BEB5A93E0CFF421DC5A63E39FB1169A0F +:108E400047C3E934169AA87DCFE114EDDF4DDFCF9B +:108E5000B7AE687F2A0BA79FAB3F2B7D1F80BB5906 +:108E6000C0DD1A7B9E1B04FD20BC4D1AFA9A2FE828 +:108E70000DA49F1FE5E1A16B8AB6A1BC8F8EBB9E9E +:108E8000FAEF32031ED10EEC49F4A25D5C66E6F205 +:108E9000B3ACC7E50C2951FA907421F1DAE56A2EDA +:108EA000A7F5562BCE6D0583E775BF9C97D0A79984 +:108EB0008B83EA52CDFC243F40FF5DA2FFD229C440 +:108EC0003FBFE0F4027C7303F22FDA2DB80E5F642B +:108ED000FCDCE4C1F33F0DE4854FC02387FF5F391D +:108EE000C2A80724DC06C33FF73CF8CCA7EF653DDA +:108EF000FBACB8CE86387CFB802B85DA651E8CA453 +:108F000078A1DE19617774754C4CB80CF9628E89C2 +:108F1000A108C375A3BD5A36206FAF7C7706C8DBA6 +:108F2000CC8132C85B2FE26140FE46ECF668FD1F43 +:108F3000B9AE9CBD01E4B5DB06F82F223BD4CE349C +:108F4000FEC4EE346EBF4D09B29876CBDFB9927590 +:108F500072ECFFAEAD60BF85F599D3B8DE9FD21B32 +:108F600052102F92AF8D72EA13C18F1F8BE7FFBC97 +:108F70009C52CE23A7AA859CE2EFF783998FF53206 +:108F80003222E315D089CBDE9D380AFD99DBB2543D +:108F9000EF97C057F314DFB067A1DF1ABBF79E64E9 +:108FA0006F944E6A98DDEB40B883D17416F5FE9C41 +:108FB000042AE31FDA25A7DA154E87CC9B5A333EE5 +:108FC000BE1C92F3B82DCB4AE32DBB6F546A503BC5 +:108FD0003FA127AEB5459E658583F95C9661FEABE2 +:108FE0004DAAE6BB83EBB3B1C9FE6FD2D00E555884 +:108FF0002DCDC7602F3904DF19EDA587B16F0FFDA7 +:109000002F62233E3691739AD9660B33DE24847E19 +:109010006A660713FC1A313568E8C0EECAA3792CDA +:109020005E081F2F01A6B4BF71C9971A3E7A07E7E1 +:10903000437A213209F934C1C57476DE623590A7CE +:10904000A0DD9A69F3A19C013C111CF62730730244 +:109050008CFB363C116F95EAAD7B2D6EA403C5D712 +:109060004AD0DF2AFC5616417D73EDF424B25BD959 +:1090700099DB4756033C3C499C6EA11FBBE8C74E99 +:109080007422E4DEAFF3C76E43FD24E5A7C4033BBF +:10909000A3527FF2FB7EA53ACF09E5FD9E8B4A5A8B +:1090A00015BDFD83F650D47E4ABF6F16F0E3E4AAE7 +:1090B0008E880958A825E4997D27D4AF4CE26B1E11 +:1090C000E9E27A707F41484DC1FE46C13AE0D55B86 +:1090D00089C1A26647141F60E304117F1956783ACC +:1090E000387FE0739F8BF3D99C748E942DE9BC9CE0 +:1090F00091C2EB1BE9ED49F17D95C2F1BBA99CCB77 +:109100000963BDE92EDEDF6A7BA82A6384D6BE0A26 +:1091100030A44333E37696DF25E8A482C3ABE2DED6 +:10912000C5A9A837BFED999FCA8AA272F41E25E887 +:10913000F441FD7B2C819F52BCE35F5486FE883551 +:109140002DE87441BDF4A4D8FEF24D621EE9E84F4B +:1091500043BD9F087FC772FA62F2B317BAB83C4B9F +:10916000C9AA21798E30F4A29FC2FA434E0DFE5255 +:10917000A798747E83E57431B5BF70BBA1248EDDE2 +:1091800050AAB31BE4B846FBE1D37559347FD9FE2E +:1091900086AC8F2A99A6FE8DACF71EECEFC635B9CA +:1091A000BA38513CBBE32E011FB4134231E765D5F9 +:1091B000BDFF14FCC49076FC237CFCE8B849C06871 +:1091C000D171FD2EFFDD2EE2A7CB9D872F864702B2 +:1091D000BC5749DF90DC07BDE4DFEA207D5485F20F +:1091E0005AFA47C8F7CE54A4F1F20DAE491AFD2839 +:1091F000DA19E5D09F453CE3CF4E6EFFA51E94F6ED +:1092000062A25751A2FA66B0BE127AC62017CF6783 +:109210005F03BD86B4FADFD8EF53AEEF6B5716C6C7 +:10922000A18FD1FF237665D9E541753CCACD2A854A +:109230008D82C7E4997A3DDFEDE2FE47B72B49A75F +:10924000E7E72ED6D78B60BD49F84C1A92BFA2D55E +:10925000438A8AF28EF7D728E8A1E0D807562FC8AC +:10926000DFFF1276D017E9FEB791AE3624A614A31D +:109270007ED8FAA78A315B61DEFDEF5B7CDBB0BB99 +:109280005D9C3ECA17AD6935C37B4B87E2B4318D17 +:10929000DE5ADB79C90A58EF0792FEDD7C1D0DEE20 +:1092A0008875248C9BD3C0C7CFEBD8AB9835F22DF3 +:1092B000AF8ED73BE4B2E8F45EAF287F26FD0F16F1 +:1092C0006EA92CC5FA7EF326107D391D0AC583735D +:1092D0009A01004007393EDEBFC31756961745D79F +:1092E000D966AA2E42BDD09691E443BD30D61D3C2E +:1092F0008CF4DF70281241304D3ED46346FBAEC281 +:10930000EDFF0ADFCB757A55670ECAD5A4437C7E84 +:10931000ED067A070B59D0F9362E6F55F60E437CC1 +:10932000A0EC80F132D68F21BD24EB67B8849EC8B3 +:1093300060C117C8AE626D8CF0C5681D19EB47930C +:109340007D2FF119B5A3C64E403BAAF0818879194B +:10935000B4DBFD58ECF8BC45E81158074BF744D78F +:10936000118F2FA41E93F52C71FC6849EF4955B15C +:10937000ED53D000F4BD7C91FB3A5C77C3062BB370 +:109380002951F857B803E9389F9C8EAD0AC246D2DE +:10939000D706D7D34A2EACEFF65B985365F1E7DBDF +:1093A000B0F6C54B5668FC2DE89FF0B1D5CAEAB4BB +:1093B000FA54FA1317A773FD73A73B3002C76DDC8D +:1093C000B5D98AF8BD65FBE7566DBC7BD03A8608F7 +:1093D0002FA58EFB290DB5F630AEB37C9199F057D1 +:1093E000BFC11A4679D4B0B33362427BFA6EE6430A +:1093F0007E6FE8E87C2B07E092DBE09FA47AA3FD78 +:10940000E53684159C4F0610610FF979112BEA6738 +:10941000235DA33D8C76C95B099CDF4F943B420AD8 +:10942000C0EF8425D880F54E6427F942055178BFF6 +:10943000DD39EB1D05583AF9055B049F6DA66D59A2 +:1094400076A8D736CEEA433AAA700767A5037C5CB4 +:10945000E64017B64F7327FB5AA0ADD7C626907EBD +:109460001E221C261BE861F2DD9C4FFE263D45DADC +:109470007B13500E2D4D4F96F612C9A7B72C7C1DAD +:109480001B189FEF3E977F01D1ABD345E3E63444F1 +:1094900014B4F78DE346E9C9BFF842E81BEC3C2B56 +:1094A000CAF57A2167CA176D577EABA1837A3064FB +:1094B000905E72766E55D00F84EF2D956EAACF6CAC +:1094C000286776F2FD887AF87E9346AEC875C49018 +:1094D0002FB7217C1D877ADEE4F22542F427E76B63 +:1094E000C4E78FD2B91D77259805F4DE1A1AE385F3 +:1094F000FEDE1A9148FD497E37F2E78F049DE7D4DE +:109500006E57306EE04EE276A39C9FACF745FA8C26 +:10951000F5389FC9553D0487D5B566C29B9C4FA5BC +:10952000353012FDAF76D1DFBE859F597BA1FCD0CF +:10953000AF0E103DAE6E57FCE417B41FB0CEC7F8A7 +:109540005CE8972AC663AFE62609DBF2D201D22394 +:109550005777F138C1EAAE4EF37247944E0B8EED59 +:10956000BB11E96C75878D2528883FBE5E239D82DF +:109570007C21BA67212BED67817C0C913C65C1028F +:10958000F447A4FCDD27EC4BE6E0EF9F10F396FDDB +:1095900046E56602D17BC1B109FBEC00CFD53EC5E3 +:1095A00007A612D8DBBC1EF41F21F9CBD808F4CBD8 +:1095B00064FF46F8FD5AC8D518787E3E3D861E9158 +:1095C0007AB5E0F1190C9F127F660177D9EF9E748E +:1095D000BE9FB527DD4CFD6F28E7F1EB0D16AE3FC2 +:1095E00036B4D8C3C8D76FA75DF98E520C707259C4 +:1095F00023F8DC6F5AD680DFF7E7F079B499D68F7D +:1096000069E6FAEBF574C25F0AE3F289CBA3875EE1 +:10961000E4F2A421E4203FB12158B382F61FDC0913 +:109620003EB4F759F04DEBFCE4283D18F1EB7D61B9 +:10963000AFD50BDFAFEEE07C10855B5847B720E776 +:1096400008EFFB5C723F2258807005FFBD05E30CFC +:10965000D27F4F591C08257B07F36BBAF0DF27092F +:10966000FFDD32C5FE17F5DFEBD7FE5336965765A3 +:10967000BD4B4FC92FE027EAF8EA84F0DB0E08BCA7 +:10968000FF41D04B7D6907F143FD97CDC4478E2A3A +:109690002E4F1C87F47290B11F8BF53F40FD54266E +:1096A000755CA9A23FFCF78AB395C59FF7CD4AF335 +:1096B0003F4F45BC74AAB42FC5CE80555F06704D90 +:1096C000103010F52C6E1EF73EF1142002F9D2DC9A +:1096D0006C3D97FD7BBE7E59E42305F15D2F607DD7 +:1096E0006267C5D4DF613CF1A954DF2858FAF19DC7 +:1096F000F3FEE677D0FEC4F6E93ED4D3EED600D131 +:109700004FBF27C1877143B70A962DD0434BC71B64 +:109710002997E1BED833974C40B999E7E67C79ECBC +:1097200045752DC267FD3F3C3F0DBFD7879574B48B +:109730001B4F3CF5F77F46BD58B7BD093D0DD6FA26 +:10974000CCEB64879BC25BF9FBA752C9BE3CFAC451 +:10975000E66908F7D68E56FA7EEC89AD54DEF70F2F +:10976000CFEFF94FB43702293EAC77ECC5CD3FFAC5 +:109770004FA4F39A141FAEA32168E6FBB692BE8DE8 +:1097800072AB732FF1A9A497AB51EF229C6AB9FC7D +:1097900091F4FC85D8575A56E1684379F6C5A6E49A +:1097A000BA58F144BF582FC65C488ED52A144F6B67 +:1097B00003AAC1B8465B229B82CFA4A2883517C6F4 +:1097C00059B8B8731AD93DA1CF5762FD79BB12D8E9 +:1097D000268ABF61F016EC7F2275C6C683183C0C42 +:1097E0007E32F4BEFD2CD8D71F5B309643FDE9ECEA +:1097F000FF796DEFFE11E5688DBD77AFC71B7DDF8B +:1098000026E234509FF44ED99AD8F1D02AB743D0EB +:109810002DD79B395DD5795E921336DF288D5D3A61 +:10982000EC60F32610432CA7AEE74A5CC75563965D +:109830004E24BAC0381FEA9F9083FA5F8D714AE0C8 +:10984000B3456ECE4F194EE6BE14C6AF3433B703E0 +:109850009F8C7D642139B283FA05FB83EC2AEFEB00 +:109860000B77A03DB2C512CC9E84FDB409BDB59D59 +:10987000CF1BDA3B71BF14FA735E3A81FAE9B1B8D3 +:10988000A87D88B79FB5BD4589CE1728351FF51629 +:10989000F657EA403D13AA25FC78ADB4AE635825CF +:1098A0009BD65D7CC3F828FF1AE33B28CF701FF8D6 +:1098B0004E77F96DEE49D1A78CFB18E1F9327E871E +:1098C000757FEBF6D3933D95AED32BF1EC957D0BE5 +:1098D0004F72FDFBEAE7246F1A918E71FCE0973A14 +:1098E000FDBB5CD2F12B9F131D2FDFC5F56FE3AEDF +:1098F000122BD2EDF1757EF65B30401BC53EEB16A8 +:10990000A57725C5795E497062FCEEA4D037F50FC6 +:109910007C7E18F74747ECCA26BFFEE42B09B5D872 +:10992000CF7E9389E0B97FDBC55B5B15ED3CB93F2A +:10993000007630916A23D8A9DC0E5EB119FDB3D54B +:1099400075CC87FCDF68A09FC65D07885EA41D5CA0 +:10995000F0F8DC15DCFE4CF025A0FF3693DBA30C01 +:10996000EC51AC9F3633DC6225FA2A2943FADAB788 +:1099700070CF46D4E38D339913FBDF32CCFF4A2EF0 +:10998000AD476198CFB2C5D23EC30CEDB7547A9DB6 +:10999000004980DB76B27BD918ABD0732BC85E6EE2 +:1099A000CCBADE477C669407AFB490DDD5E84DA411 +:1099B000F95CBD4BB98DDB230EC6E7AF107D5E1D94 +:1099C000BE2C8CFBCABF17F093703C69E9B911E15A +:1099D00071F2252044F87EF54C4EAF69333B488E3A +:1099E000BCFDCA2CD2E3922E935FB6913E77999D2F +:1099F0008A8FF4DA3C9B16AFED16AE97D2849E297F +:109A00007C80E33722F82922F440C46DD5C75B9CE3 +:109A1000A162D4BBBF17F8273182F25DC893D52B62 +:109A200022C44F0D3B797F6E9BBFE4760DFDBA2BB0 +:109A3000B85E94717FDC07A88E212F7EE7E6FAB12D +:109A4000E0F1659BD15EBE0AF08E2A25678C90A35B +:109A5000401708B79CBA00D1C155EE9B7D6A01ED55 +:109A60001F909FD8DF6265B1E23C47851CF5A407D3 +:109A70004A31DEECC94C263BC7A3969B12B05D89E8 +:109A8000E2DBE6A5FD4DB2F3FA3DD9BE6D3A7E0F9D +:109A9000949AA0DE918C648EE7F0AFCD73C7231F3C +:109AA0007AA59FAEB3FB06FBDBDC6E9CD31E2A4679 +:109AB0003F44EE5F4838845B126BB5F2B34FC02170 +:109AC0003C96C7F3C1BE7750FCDA09E3A05FBFED57 +:109AD000B227B85FDF4AE31F74F3784625AC0FED79 +:109AE000364F61600DD7A7C9BE58F0B853E079DF93 +:109AF000C21B4BD0AF6CAC71F890DF1E7A55594643 +:109B0000F48CC141F4B7832B080F0CF080FCC082A9 +:109B1000DC2F6D6C0E8463D37B35F15F23F29F42A3 +:109B2000F44EF176A0F730A777AEFFA4DF8FF2B145 +:109B30003AC67EA8942F8DD6DED148C7921F1AA7A9 +:109B4000F58E46B80D559E9CB400FF23FF001C9077 +:109B50007F24BF24EFE67CB2A9C55B8EDF37553288 +:109B600067AB461F19FD259C27FA9D52AE8F7507DE +:109B70000A3D1807304536621E8594C38DBBEF1B26 +:109B80001D2BCF4DCA61BB99CB377B3829DCAAA1ED +:109B90002FDCDB4B9E404FCADB495A1B3B2E52E663 +:109BA000718878FDD0F222325097A3BCD996144622 +:109BB0007925E344C67EC778145D3C46FA2DB8BFCC +:109BC00080F5E77A38BD547AB89CB85E3CE5FC2550 +:109BD000FD7B4DC1CF319F289EFE92EDFE52712B31 +:109BE000398ED4A346FCCBFD115C4F7551FC7AED48 +:109BF0007BB97C32D2E372C1275E5C2BD47B4EEC06 +:109C0000670DC62FEF87D59A75F96F6DA6CEBA5836 +:109C1000F12FB9BFC11E320F29BF6EEF3A9E47F533 +:109C20009CC8A7658BCDBA7C2A87CFDB82F1D3197C +:109C3000F6821295C6E571ACE469EC6BD4C3C5BB82 +:109C4000DAC7609E9227A0DF1FC9AC4DD4ED3F64F8 +:109C5000075DBA726E5D8EAEFEB0E611BAEFC3D785 +:109C60008ED37D2F084DD0950BDB2ED5D51FD53E3D +:109C7000439F8FFBC855BAFA63C37375E54D2D1D1D +:109C8000B588978B9FBA4ED76E86D9692E01B88E4C +:109C9000EF58A6CF1333C033F5CF6A4C3A7CD2537A +:109CA00040789D61D6E70B5FB24B0F0F4C8BC3FE24 +:109CB0008A99E86FDA9109E7CA632D66E66F7A65DB +:109CC000FB82C1F4C0ECBDBE400C3F53D2B92C1B8B +:109CD000F7B1A4FCB850FA8B374F497FF1BEC78368 +:109CE000DBBB1EB90FC3E16219804BADEF5C70B1F5 +:109CF0009C0F2E0CE092FCFDE162EC6F7D5223E59F +:109D0000037F84058D7DDC2BF84896178452B91E9D +:109D10000ACC3B8F1DCDE3C0411BDF9F347EB7676C +:109D200070B9361AE640F019225F7F26F070281EBF +:109D30005FAFFD7A7F26CAEF2A467EB3B3B9E56BE3 +:109D4000D45B4BCC1186F4FF9058CF169117FAC80C +:109D50003A27F5F3A8D87F7C6C9D97DE3FBE6E0C4A +:109D60003DC3EB7CF47EDBBA29F4DC0EF61C3E9F8F +:109D70005C5745CFA7D605A8DED3EB6AE9B9735D7A +:109D800090CF6B10BE5819D93981F498F1D2A52122 +:109D9000754878626A5E4C7D19B71F75F139F3C852 +:109DA000D71E5A34FB4D0DFF666524BB0F630EE3CF +:109DB000643619F733CFD7FEBB75B5B3DF1C3574E6 +:109DC0003E92F4C4CEA48F8EC5D741913FF9BB8794 +:109DD000CF6E0A15C5875794CE62C3A9C67E3207D7 +:109DE0009DF562B41934ED0F1AF8B826981AD36E9F +:109DF000A811F4596BE3FBEF8B0CFCFD92F8FE52BB +:109E000006D7779FC49133576798A43F6FA1FDC0D1 +:109E1000417CF7932B62C1777F8657C7C78B820639 +:109E2000BC1AFAF9C4D23ECC1783CFCED78F5C9F31 +:109E3000B1DDC3195C6EBDF8FF297F7E725332F924 +:109E40000F08378F66FD9FDC94541B2B2EF35A06A8 +:109E5000DF0705EB9C15B8C8D40F59D1561CC3BCFD +:109E60007C9F77A413E343320F203EBD9A298E4492 +:109E7000305407C315F0E1B51642FFE68171226642 +:109E80001CC7678AEA59CCA9619A731EEA607A8076 +:109E9000F6212BE5EFF4E6D0BEFF05D213531F1BCE +:109EA00075AE7DBA41ED2F50CEECF881E58CE473B0 +:109EB00076E6C151B1F4642D8E7D29AC63CBD4FB21 +:109EC00049CE9CA7DF0B855FADDA4BFBD64386DF1F +:109ED0002EF790E2526BED29C50CFCBAEF12F83365 +:109EE0003483F1F3589F2584D1CE3F20E6098EFFBD +:109EF00025DCAF6E9E8CCF7FCE0A7C9801ED975902 +:109F0000B99F383EC3FF119613C53EB035D3BA1181 +:109F10009FCCC9D7718958C74693371FD7F1A5E29F +:109F20001B8B7E8AD314F6E1338545C6F3BCBB7028 +:109F300010FDB3F48B13BDE8DF268E66AC87E2E13B +:109F4000BE048C9B5993FAFF7124F2FBEB268C30F4 +:109F5000B2E79D7CBECF3F924BFB2AE801A17C2853 +:109F6000C6F730F54D688743FB6B59F018CEEFA864 +:109F7000D31E32C1BC8A677FE1C27CA8E7BB67D031 +:109F80003E42E4293564C5730B3D27FEEE6AE8EFD7 +:109F9000921E0BC59B2F612AC9F37A337B00F926E9 +:109FA0001E3C8FFF75ECFCAE2B32B9DC93795BC69F +:109FB000EF79E2FBF13879C48E4CAE17647E8C45A4 +:109FC000E6C778FCE7CC8FB118F2632CE600C37DBE +:109FD00060CB407ECC6246F931D08F363FE6F88CBC +:109FE000D8F3708B79584E27C5E93785DE1F1F716E +:109FF000EE755A4E27E8F2ACA3ED1DF43E5E7ECE20 +:10A000007831FEF138F9496307FACF66A1746D3BE8 +:10A010002F9FF7C03879F4DD62C8F3897EE7F93DF8 +:10A020001BD2389DECCD72BA9742D74B59AF05E998 +:10A030007489C36DC1F85180F93AE9DC8ED9D2DF59 +:10A040002BF96E04D6337F8176B609242DDAD94BED +:10A05000D65ABEE8D5C8A96ABFBECCB0BE46EE6E21 +:10A06000CA6234DFC4716328AFEF14F3A63ACF217C +:10A070003717DB55BB59B3DE4371EC865B05FC0E2D +:10A0800065C786DF7599DCEE88771EE2D6CC14DDD5 +:10A0900039BDDB9DE7969708DF60BAB67F231EDCEB +:10A0A000F4FD7C70F6E0E61AC6D1CA159EBFFF1714 +:10A0B00087779A3857C5CF05580C79E89BB2B8FC1A +:10A0C0008BCE9BE7A17FE40CDC9E8972D1EC1DADA9 +:10A0D0003D07D065F6274D80E72121778C70D99D0B +:10A0E000C9ED37E3BABB443E7DA2CA9A3B35F0378F +:10A0F000AEF73941E7B2FE060BDFBF82BF801DF02D +:10A100007203E372EFE1CC11222F3CCD8CF270315F +:10A11000EF82DDE07C8BF693249C07C14FC0DD0805 +:10A12000C700F3DE8879DBE783674796FF6184CB5E +:10A13000D203895694FF37DAFBF7A38FDADB63FA91 +:10A1400078243C3F778C3CBC9DE1FEDB9897F7C1BF +:10A1500033658A8FE751B09964EF28A15CF5ECC5AF +:10A1600043B77736A604C7207F7C29F2AEA53EDA36 +:10A1700098736C34E6CF7B5DE5ABB23C1477F7A700 +:10A18000231DBD66E374F408F404E5A63D63B7A29D +:10A190009E79302B5887F5641E1FF3F78FC63C84D9 +:10A1A0000B8513FC59908ECE07A7273219E1E75093 +:10A1B0004A6C3AF94D1C3A31F2079D2F2BFDE1F81C +:10A1C00043C253EE5BC8F9D565713A944F093763C2 +:10A1D000FE505D9649D4E3F9880F660508CE7DC32D +:10A1E000BE3E9C00733F64C8F792CF93421E9D6FA2 +:10A1F000FD12DE3F941C3E94187B7EA6ACA1E1E7E5 +:10A20000879A5FBD9C5F71ECF965660D0D7E01D686 +:10A21000FF59DA0FA0C700CFF58867B6A19FE4E326 +:10A220002157EC79960D799E41CB0FA16F257DB317 +:10A23000D0D23ADAAFCF4A8CB95FBF00FC27F47FA7 +:10A240008CFBF6727F1EE407ADB7C6DE7F633AE291 +:10A250007DA65877068BA4E17EE61E1BC5FF8DEB1D +:10A26000BF42D011C0AB82E035A79FE2188746C736 +:10A27000960B15C6FA6D7C9C78E70BAECE528674B1 +:10A28000BE80950629FE576E774454C0C36D021FE9 +:10A29000D6DC553EB40FCBB3DE3B88EB04F89F18F9 +:10A2A00080A7269FEFD8BA779C232DF1E576BDFADB +:10A2B0004259738CF5043DC11BB3347E50FD53EFFE +:10A2C0003A476AF0359EF59AF8F9E87E93CE2FCE9C +:10A2D0006417E41757639F988FE00A903E40FD8013 +:10A2E0007A67E3EEA925884CB433309FA73F3991B4 +:10A2F000E4686BCEA563BC1A7886B2A47DA9C6B10A +:10A300001BFF7BF9FF51BB49D1D9AFD1FECDF45E24 +:10A31000E2A7DCF18F31F111F4F8EF213DE6F26FA5 +:10A32000C4A7117EA17B2F4FA3F30508BFE9D1FE7F +:10A3300006F01F07CF1D1E7F3BF6D720CED1283257 +:10A340008F6F205E61761EB647E13D54BC248A784B +:10A350001AD80D8F211D586D821F9983CE874BBB54 +:10A360008519EC1B3686FBB73764BDF7478CF76C55 +:10A370004CE12CBBF14709E4072E519C565C37D8C1 +:10A380001F9FFE1CEA0759E4D3BBC83F9476469250 +:10A390007A3669E8F394FEF2F9F2A9F7A13D06F3E3 +:10A3A000996172D0FEE63E585F36C88D1956FE2C74 +:10A3B0009F055405FDCD50F3BA7B615EDFB2338952 +:10A3C00057C0F3A78CC361CD81DFB9D01F9D61B6A3 +:10A3D0001CD3CA2D63BCE38DAC6437E151C43BBED2 +:10A3E00065737E7D31C2E57217C1A5F8959999DA3A +:10A3F00078CB40BC43AC635E682997A7063927E554 +:10A4000099C9CEEF11617EE6756650DC88C33DA424 +:10A41000303394AF90657452A07CB9409282ED6164 +:10A42000DD5788275B16CC423983693C381E787F1C +:10A4300059F86C9DEAF3E273BA1230F3798479DE4D +:10A44000216BCEC3FA267BAFCACFE7C10C32B0BDB9 +:10A450001C8F9793457943CDA91B6FF20E8E633005 +:10A460004732D9BD5631AFA34E47C804EF6D8EC8F1 +:10A4700051CA4F154F63BCE33B532884F9D977AADF +:10A48000619A6F128B447A303E61071098288EF0E3 +:10A4900007E403F06E1A719E09CE5391BB18E6399A +:10A4A000FA152CA71BF491C7B186F29E3D01B3416A +:10A4B0000F0515E49BCC5AE37BBD7EB2B343741EFB +:10A4C000488904B2CEA69F3F5E638CD35866701451 +:10A4D000F7DFC2EDDE8F13793B4917E9D95CFF3610 +:10A4E000BAAC8CF25D32EC76B4DB4F261FC12397F9 +:10A4F000A837DA506FD82D7E8287D41FABBB6E652C +:10A50000889FC65DD50CE5E86F14BEFF19BA41A15E +:10A510003C05796F436D117B1F5AB2A6EC1134CE06 +:10A52000FC7782373440B9E63D363E02F54AA6074D +:10A530002AF17E96D6F1CCB71ECAAD09C1675FC2BB +:10A54000F51C50A99F26712E963167FD4EE87FEBD2 +:10A5500075C37C9B704915FD1B310FA8FF3EE6C4F7 +:10A56000BC9141747A06D607F87F02CB30EFA6156E +:10A57000C15FDC01F5B3DF633EAA23BEA32F82785F +:10A5800053043DE0FBE9F0BE49D04D61B7C2F7EF9F +:10A59000DD36CA9F600733895FE6DBF9384DDDE5BC +:10A5A000D74E827915F64C24321E09F531BF093396 +:10A5B0000C787E1D237FD9587F24D6F752B48AE7C2 +:10A5C000D5E458E9FE2326E4DC6403BF5D16A57FCD +:10A5D000FA5E22CA4D421FE9F804FB01FFDC5FC6A8 +:10A5E000B7F3A99D9BF3838FC93FCEB797B2E81FFE +:10A5F000F65B111D87E4EF4CF16DFFA2D994D73DB6 +:10A60000D91CD98B7C7D9978968827F2B51DE0B846 +:10A61000D0DCBCDF03EB495BCB7C2D38CA626F2BEF +:10A62000F657CA022AC2B9CC795F2BCE6FEAE20391 +:10A63000E9485F4F6617123D5D6EF715260089B435 +:10A640004EF1F99CF0AA76B14270995F6B0F63FEF0 +:10A65000DAFC81FB7A82050B806F160615718E3E3F +:10A6600058B058138F95797D0B6CE047C7DA77CED9 +:10A67000E67A5CB66F12E74EE4F76DD90E9E5F99ED +:10A680007D655336E557F07C67E0FBDBB22745E597 +:10A69000088C4BF928F398DF82EB9A27F856F2FDE5 +:10A6A0007CFFED64B7CE0FE8EDCFDF281CDFA145BE +:10A6B0000AD9830B6BCF6D9FB664CBFDDE3C27C5FB +:10A6C000B799D4479CAEA4DC9E8B7A1CE56D15E847 +:10A6D0006D8D7DBCF8CE3369D42EF3C9D56787471D +:10A6E000CFB93419CEB9348A732E4DBB5A2C1948C0 +:10A6F000EFE29C4B53F7E71BB5F97D124E83CFB9C0 +:10A70000F4535EE3026B782F9EFF59B00AD608F52A +:10A71000DF10E722DEC4731113A274947C5D4284BF +:10A72000E7CDF9297F2FCF99E4C37C9336D304CAB0 +:10A73000176A4B49F669F37336B53457623D99276A +:10A7400024CFB52C88B31FFC9C906B5B149EAF1577 +:10A750005A6427787B5476507B4EDF5318A03CB95F +:10A76000A66C2F8DB345C41130AF74223CC3608EEC +:10A77000717CF1F646F900FD6DC0FE2A0A7D941F3A +:10A780005391CAF3CC3CE98192DB8AA2FDD674F3E3 +:10A79000BCBC9AC0D76FF1FCDAEA5284A7519E4B39 +:10A7A000FA32CA75A0BF7D488FDF99B8DE89CAF733 +:10A7B000C0A29BA0BFBEF7AD943FC7EEF62B1668B4 +:10A7C000F7E2BB4E1F9EA7DB501EA8AEA4EF663A71 +:10A7D000EF9751CB2236F85EFA9E751BE6EDD5B1A8 +:10A7E000762BF65767D05BAB1C6F5A913F576DB70E +:10A7F00044E99161BEA1AF10055DC3CE41710F92D6 +:10A800003F522E19E9988DD4CB9F12296F412E709B +:10A810007DB598EB39F6A482F19FBEE423AAF09FA0 +:10A8200049DE4D9242CA20E72775BF4DF6CA3490E3 +:10A830000FE89F29582EA6FA5406F93906F3472F38 +:10A840006389445F83EC0431AFD28179737B48CA5A +:10A85000C5F2298CE17D06122F300ED1B3DCAF9BFF +:10A8600084F7F0C0F33231EE9D267F5144413CB174 +:10A87000B0A910ED8820D93B46FBA7CCDE9C6487AD +:10A88000F54D61ED241727EF7F93E424E0F92CCAFE +:10A8900099D798C4B3CF8E72A61213FF547CEAF1F5 +:10A8A00034CBF19019E1342BCB888F9019E13ADB4E +:10A8B0003B084F744EC01F074F7E2947985E8E1489 +:10A8C000B033FC5CF27D6FDD817EEFF9EC900F3DE3 +:10A8D000C1AC1C929F7A7B245E5E5D418EE382F266 +:10A8E000EAFA2CDC4FB894F5AEDCA90CA68B93FBEE +:10A8F000D7AA591AFA9174B95BE4D92BAF8BBCDD96 +:10A90000D264D27351BDC8F15F264A97225D69F0C7 +:10A910007FC5AE84880AF45622DA5F8AF43021AA11 +:10A9200017232687D70AE36E547C6D6A0CBC67B880 +:10A93000BCA4FF269AFC2AD953CC978E7806BC4F2C +:10A9400043784DB177B49A619E87ADBE9FA3BF5245 +:10A95000CEBC84F772837EA970D498913F2BEC46CD +:10A96000FCFA09EF95CE41EF4DDF07EFC311EF522F +:10A970007F0CC1FE04BC2FCC89B15F180FEFC1EF73 +:10A98000897723BE25DF7726382B1C18D7ADE3F94E +:10A99000C413DF1FD98AE58CD50574CEA533CDF756 +:10A9A000067D6FE6DF4B7BFC2ADE9F58B806BE4370 +:10A9B000B9B3205081E5A6B50AC9CB491F055BB1E3 +:10A9C0003CF26EFEBD647DF31B780F595388B7DFF0 +:10A9D0007D7423DD2711DE28DA97B75760B9A98D7A +:10A9E000B7FF2AD91E42FFBAEC60B815DF8F7D8011 +:10A9F000CF43DA75D3059D752A2FBC41EDDA79BBBB +:10AA00009BDFB227927C1276DA34B1CEE98FF175F2 +:10AA1000BA7F7B559517E8F0A6FE9005E9E0B0A94E +:10AA2000A18CE4651C7FAB5C69CFC3E72C900B8CD9 +:10AA3000F00DF43982E79B6E83211ECBE17686CC44 +:10AA4000D3C47CF16A0DBE1ECBE17127592FC3C55B +:10AA5000785EF1A3C964B7CA3CD2C8CF98827100AE +:10AA60005C23E9D73879A5B30A9B495FCE1A2EF348 +:10AA7000497BCDCB60DC92B37FB832967FFD8418E2 +:10AA8000F788C87F97EFEBC20526F43F3A9178E844 +:10AA90001EB3DAF7D12EE94C63BA7B423A0B78B990 +:10AAA000F3D19A1FB7E5017C4DCDE6100AFD7C85F8 +:10AAB000EE3DB9A68745525306CF7F96994578DE7D +:10AAC000039FFFCA56EBB64D1A3B7DBE141B978FF2 +:10AAD000223D5223F024E5C57C812FE0EFDDC8DF65 +:10AAE0000BECCD64172E12F2FD1616A638C52D06F6 +:10AAF000FEAE777CF399C984F1303D1FAF86E970D3 +:10AB0000BDD0FFF82700FFBA47929DA8E75777E826 +:10AB1000EBD53DF2FE416E5FE9F9BC4EF27958CFBC +:10AB2000E76038703EFFD938DA7F91E7FA12ECFD22 +:10AB30009F855874BD03FADDC07F0978CE6F0CFA8B +:10AB40002D269E5F28CA72DC53ED5C0F87400F0BE9 +:10AB50003F8744EDA943B3C3480F25827F251F9744 +:10AB6000087D3E485F5719FD9887883F268A928462 +:10AB7000BBD4CFD00FE967796E10F4F2FB7EF2EF11 +:10AB8000C1FFC4798ED3F3CB2605E47341D45F01B2 +:10AB9000BC7D8D7803796CE7718A7686F22CAEDD08 +:10ABA000EF5813D3EE074947FB0083EDFD88CE8EA7 +:10ABB00037E22B9E5D3F80AF04B09792D08F67C481 +:10ABC0001FFF88CF21E475809C76E4C690D3D67DA4 +:10ABD000BC5EFFD6048A17C8F8B8E437258FDBD5EA +:10ABE000EF66F95DB9B8FF20FA3F74EB2CDAAFFEDF +:10ABF00086F969BF1AF38D7263E44BE07EF5064D6A +:10AC00009CF4505AECB8F5F05CCEEF4B72F9BAC632 +:10AC10007BFC5E1CEF8895C7C58F248A670ADF57C7 +:10AC2000B83897C7B9978867B9781E1179D8475C43 +:10AC3000FA78BAAC5721C6F9729DDDBE412357BCE4 +:10AC40003FB335A3BEF2148ABCF5359C5EFB5E496A +:10AC5000DBAABDAFED9ADCF22508474FA1DF9A8D44 +:10AC6000719657B85E6834F75A31BFE41A77702A84 +:10AC70007E6FF432FF0BD88FB7D73A0FE0DC27F6A0 +:10AC8000E9FB2CDCDFE84BE04F39AF6B72AB97E0B0 +:10AC90007AFB6EED25F93050AEEE25FEBF2637402B +:10ACA000E3F6CD97DF45F9C7BCCC847F582EF882F8 +:10ACB000E2BC31E2BA83E3B8FAFB679AACB1F7972A +:10ACC000595EB22E3E7B43378F1BDE68671B73E1F4 +:10ACD000FB92EE4CF21FEA5242A39D14C7FBEFC554 +:10ACE0005DFB86F5D0BA3695F7E73F5A4AFBB814B4 +:10ACF000F759DDFD36C9B9D5924FBAF47C522FF021 +:10AD00007BBEFD0F635C7C08FCB32616FFBC8CFA8F +:10AD1000C91285FF6D220FA9526DA8C0B8D0A91520 +:10AD20008CCEBFDEF6AE4AF474DBB30ADD0721ED4C +:10AD3000B3D502BEF1D683E707BC1AF981E707BC99 +:10AD40001AFF0CCF0F68CB787E405B1FCF0F68BF18 +:10AD5000E3F901ED773C3FA02D97B0E5AD18676BA7 +:10AD60006A63CEB0979F27D0B6C7F304DA329E2726 +:10AD7000D0B6C7F304DAF229C6E178EA3195E2F4F5 +:10AD800078AE40DBFEE677276621DD7425F03C32A5 +:10AD900016F2F714015C5608B8E079036D7FC753CB +:10ADA000AE7C8701DDADE85939079F97EC5AA5EBDA +:10ADB000AF5E6D203A64ED5CEE36C33F243FD52292 +:10ADC00015E7F1ED2E85A517E0FDE106FDD9BD796A +:10ADD000238A9E5BC2FAF7F54C13AF2D181C977FA0 +:10ADE0003957E421E6B01C6D9C264A070E5F04D754 +:10ADF000FF91EA8B450725ECA2548ACFBCA362ECF5 +:10AE0000817DC59AB75CAE68E2F70678D8B2F4F4F3 +:10AE100090E0D5D343D2183D3D24FBF4F4903A455D +:10AE20004F0F69FE71E7846F7A959E3E8CF09D020C +:10AE3000FF207C27E0CD9018578275629CF72F0584 +:10AE4000DF2F72C5BE8780EFB7ECF20A87973ED737 +:10AE5000D8CBA2F649E93BCDB4496B8C7B4A384A42 +:10AE60003B41C62F2731EEA7DBF1BC6521DA01DCBF +:10AE70007F43FD8F7C7ED8CAFD36A420949337B1E2 +:10AE800020C9A39B0CFAFF66C74356D4FF83D60B99 +:10AE90001617DE1B685C2FDA514C134F32EA7FA580 +:10AEA0005B892417E372BBA55C0E9E2563C7AF0CBC +:10AEB000455EFCDEE1B7E579681C662FD3C57B6390 +:10AEC000DA73721E122E727C1B6B56B3909EC718DB +:10AED000ED2FBDBF2CFD6BEA54138F96FEB1F44FDE +:10AEE0008C7056871790DD35D129FDE29EEBF1BDC0 +:10AEF000F4878D7EE8F9F6A5E68594DE9F1744ED8C +:10AF0000C92BC4739E8817C1B27EFB6FD0F872C57F +:10AF10003B0CC79BBBFB220FD2CB46A59919E6770A +:10AF2000F055E84735F5A7F3F84B50B75FF5B6D2C3 +:10AF30004BF35EC0FCF7E0B351C4D31ABBDEA67D71 +:10AF4000D4C62E1E2F60BBF47831DAFBAB5887B520 +:10AF500040196CEF37B01EEACF68DF0FA293F3E819 +:10AF6000F18E3C79DF16CF1760422ED50978C5F3F4 +:10AF70000BCC08E0A9D1FB3B811FE6E54D8AE6D169 +:10AF800066B8C08F51310FC36B8D9527C5F0721510 +:10AF9000B049973B6A484E2C6F1B1497B0123FB5CF +:10AFA0009F7B7DD20EB81F7C377C96E67979DC20BA +:10AFB00071CE3B7EFC5CDA93AF3DFFD164E5E70EDA +:10AFC00059B3FE7CFEDA3C933C3FA50E65FD83E160 +:10AFD000FAFDF2F265FE01C0EF2E2DFCE43E825C2C +:10AFE000CFEF27F53C89F1433579A61DFD5AAF2BEC +:10AFF000D882F5871DEC3DACA03C7378293FE4E492 +:10B00000AEA31FA3FF2ED7C758EF16BCDFB66E97AF +:10B010004AFE60DDAE37C82E8AEFEFB50FDCA32005 +:10B02000F6377E126B5E32AFB9522D4AEDD5D8E9B4 +:10B030004B851F307978E0216C57FA615E0ACED7D4 +:10B0400032A283EEC5EABF83DBC16E95CD44F881A1 +:10B05000DEE37ADF61A67D077752484D413B6E29DA +:10B06000E3F7D0F99A7D482AEAB0228AD366DCA1B8 +:10B0700006D0FEFE74CDF2343CAF9C91BC22AD10E4 +:10B080009ED36DFC5E9A0CC514E0E74E97A5E13D9A +:10B090002037D8F8BE7CC15F27450A81DF5EB7F252 +:10B0A000FB46DD4941BABFA03F4DA5F91C5B074BEC +:10B0B0001B85FB1EDF4CC47B0772CE3826E07CB2BA +:10B0C000C5BD163FCAE3F7DC1C7FF6BB89E8AFAA13 +:10B0D000671D74BE5DD29FBB30B6BFB242C0A3D164 +:10B0E000C3F3DE4F0AFBF190D86F9579F06BC43E45 +:10B0F000E0A1D103F78379302FA431C19FBA10E3C7 +:10B10000110754CA6BFFC6E94F4D23BB99E7B3AF94 +:10B1100011F6C34991F7B966F68C4CF42FE2E54B72 +:10B120001FC8E376EF0F755FA5CC3F8D0B873433D7 +:10B13000335F42F72E05CE55EFD53FAB31E1795A5B +:10B140007C8F9737DF97A7E8F2E21B312F1E5EADA9 +:10B1500079A53C939D235FBA11EF23D7E4D7A09F35 +:10B1600086EB6BC4FBC8E99ED213744F07F683F7D6 +:10B17000869DEFDEC815621E8D984F9EAE7DCFF97D +:10B1800039DABF9BBE3F2DE0F6F43BA6AA6D31E64F +:10B1900099378CCBA7711E7300F7252F8EF07B3F5C +:10B1A000E3D593E7B8E3CDAB6B46EF8D386FCCCFEB +:10B1B0008C355ECA304E2772BE5DAEDE9501BE9FF5 +:10B1C00037BA3A595376F6E7CFD5C8D7D9023F5D9B +:10B1D00057F5E6D37D00B3B9FF1A0FCF65E66605D4 +:10B1E000E190E00A06D11E91F715E37DC63CCF231E +:10B1F000744E7C47E1ACEACE1F0C86B395BECBFE05 +:10B20000A4DC39FA884A72E7E807821F99DFA19423 +:10B21000A1BEE27C7594F1B8EED176FEFB1FCB8225 +:10B22000A02B407E2CDD5E3F070F1FAFDC3171236A +:10B230008A7F7C7F37C89FA5598C4D83E7B20DFA72 +:10B24000FDB16FD903A4E7563C60D467012BCAD97E +:10B25000950FE9EBD7B107BE46FBA0CE60F76608B5 +:10B26000BD6BB47F670C13F66F192BBB90734E8FB9 +:10B2700030FFEC61A4FFF97EDB24B19F6EACFFBC14 +:10B2800097D3C36D3BFE60C59F048AD7EF319017FB +:10B2900023A1DF13EB9CF45C32CC5F330CDA350D69 +:10B2A0000B2EC471FA0E70389F6A38B592E2D2B58F +:10B2B000DC0EB0E1252BF09FB6EBEDE447DF8BF71A +:10B2C0008C019C6D366E5F48BB4A556F57F1275B0A +:10B2D000A6FE6E451AAECFFDCCAC2AF43F3CCF247F +:10B2E000F9111F9BCAFD2528BF37553B689F78ABD6 +:10B2F00089DF4368B7F1FDB9F0D353F7613878645B +:10B30000C7E619E86738BBF746302ED166E2FBAFD7 +:10B310006DD398B8C79A8FD7D45DDD89F3CAAF01D2 +:10B32000790FFD6D2AF0973835FD33612F350A5CB2 +:10B33000F4BD76D14FF1DEAB9FBF43E62AAC730478 +:10B34000C5BFC6314E3732BF847E1B43132F3A012F +:10B35000FA8769CE3F8FEB50229614BA5F8FE2D8FE +:10B360000DEB2319D7A3FEFC25DFAF95F373BF9E2A +:10B370003D03E3FD529F5E8FF96D18071676EF22AD +:10B3800026FFF87E41ADA0EB45C2DEBD3E89C37904 +:10B3900019F3D1F9ABEBEC2C05E3CBD757744CA2E6 +:10B3A000FBAFEB2D6968AFC8B8773CBCC78BCF3417 +:10B3B0003E99CCEFCB51FA476327C73006521ACDDE +:10B3C000B737F6B36398E0E7D1C24E1BC9FCB8CFDC +:10B3D000D2B8E722CAC7B725F27D35906F76C4EBA5 +:10B3E0007ED4E7B0EE5B5E4D88F07DE3B0B81787A2 +:10B3F00085683F664F26ED2BB80BFDB4EF7ED2D2A9 +:10B400009B4FF200E49702BA73CFB04FAE31E3FD29 +:10B410002039604741F9F82F0E5F83BFCFD238A2A1 +:10B420007725DE179EFEF8595E1ED77B18CBC31E0C +:10B430004FBC96CA137A57AA509EF278D6B5D41E3E +:10B440001D2820ACCAC7875F8BE7FC8E89F825F3DF +:10B45000F5D23D418DBB2F3269E38325F95C4E1F48 +:10B460004BE0F58E15B0257311DE637A476B7F379D +:10B47000C1932FED526E97C975CA762C2B76FFEFCC +:10B480000B3D708BB8DF677A126B4BE0FB1521B474 +:10B49000AFDEECBE88E0F2C2309780572FDDDB28AC +:10B4A000FB319EEF97E3AE42BD8D72DDA23F4FF4BC +:10B4B0001BA12F609C0D344E91BF04EFE5699C9B4E +:10B4C000578278037C9905BECCDC0FDC4A78C67EB7 +:10B4D000D38A498F4CC43CB137CF40FD82E8BC8D44 +:10B4E000F471588C734B2BDF67EA4F2B243A9A9EEA +:10B4F000C4ED3F560AF003393645C0AD245F9CE3E6 +:10B5000019C043A642FDB70AF8E5F1FA17BADED32F +:10B510003FD07A3578F263DEF19BBBC6129EA60C53 +:10B52000D0C1665D3FC75A0CEDA6F0BC94465721CA +:10B53000B5BB57DCB32FEF2DC67605D06E7A45FF2D +:10B5400044E407796F1B0B4D2367BD41488B817B1A +:10B55000D83A787E0A1BE9E7F711CD9D532AD6E742 +:10B5600014EB736AEFA51BE0C38FFAF36B34F75249 +:10B57000CBF703701FE8AF6882E84FC7CFB1FA433B +:10B58000BE88878F71F97F617CC8791AE0390067BE +:10B59000C3FC243C918FA95D919E9FE43C87E59B71 +:10B5A00084BF6DE0E782EF399EC8EF5FFD37221F51 +:10B5B000D2ABA7E7D55D0526DC3F95EDDA3A5A0216 +:10B5C00028E765BCDBD6551D42FDD7D45D4E799B7F +:10B5D000AB7FF5ECCB2168BFEAF987533099F6A829 +:10B5E000B93D03EDDC861DF7A4F871BFC41C4A41C8 +:10B5F000F97934AC56C53A0F181278907654A3D026 +:10B6000037C79EBEFF1A84C77FECB038518F363DD6 +:10B61000658BD8280E720BD95150FE9C97EFFD1AFE +:10B62000FDD2A65D7A3B69D53F3C9CE1257A0AE5CF +:10B630009AF08C0B8BE43278366EB7F8226E1E4F80 +:10B6400084615813EBDF88F333B6C7799C06BC37A7 +:10B6500075A84BF13CAFF13B4812B2C39ABAEE2742 +:10B66000BBAB491B67003CD4C5B1BB6ECDD7E75B14 +:10B670004BB8B0B087EC9AD65FFEACF87307DEA784 +:10B68000F94F294A91565FAE27389DEA58FEF7BB1D +:10B69000BDF1F5EA49B40B6CDA761CAFDE5D0AED5C +:10B6A00049B06EFE6CB04452D0CF6FD86AF181E6DB +:10B6B000650DCF3EF124EE87B04F6C74FF41FDB3B2 +:10B6C000FB3FBE14CAF59D16F71C3E7D879211C53F +:10B6D0004F9397DB27121FAB5EDC4FF70CE27BB476 +:10B6E0006B255EEA3BF75AD9F8C1F0ABE8D82B7E60 +:10B6F00077C1809F8ECFAFA4FB3C7FF99D15E9FAFF +:10B70000E81E8565160C6E5FB7757F0AD21FC209E9 +:10B71000FD4B89A701BC0DC257E49ADDA5548FE209 +:10B720001AF1F036379FF178D0AF9E7D0E7F07B0CB +:10B73000EE37361FAEBFEEB9DB53701D5F999B39F4 +:10B740007DFFE29E0C3F8C5B67096538E9C9DFD756 +:10B750003D7E07D1DDCD07EEC8E0BFA7E1CF364D76 +:10B76000A17566E3FA6E7A6C3EAD6F250B12DDD5DE +:10B77000FD82C727BE15BFC760C4E769C11F5F6DE3 +:10B78000B3E18F64B0AF30111DF3083F50459EEF19 +:10B79000AD4C7B8F0558DC54FE56C407DE1FD0032A +:10B7A000CCCE3471D9A6EDF7F6207E8E0DF367E28C +:10B7B000BE1AC02124E0A5E0FDBAEA81CA4C8E1F62 +:10B7C000E635CBB832D8DF15F81EEBF758FC09C5C3 +:10B7D000BA7662BF9E8F2FE31330EF44DCF7FB2A6B +:10B7E00023F6B9ADD1C31521DF580FD3D2573C7E14 +:10B7F000DF7E1FD1D5371F71BE690C5757D1F71E99 +:10B800004B048F163786F7D628240F6CBAFB9F0699 +:10B81000E862BB45F0B3FE3BCCD3AC68E1BB87E745 +:10B82000D5AE7CC8A6BB0F214A37D6E8FB82287F5D +:10B830004A3FEA66C1FFC6F51AE5C11F0CF2803D1A +:10B84000E619D2BD320D96F0938F22FF02BFA29F60 +:10B85000D9F0AC85FCFCE33BDFF8F83AA0F3E31D3C +:10B86000926FF572D5C8B7752F4C62B1F8F6B8C3B0 +:10B87000C762F22DBC8FC9B78EE83E8D97FD7072FE +:10B88000F5E63872356FB8F11C4B512AE6BA1F7BCA +:10B89000BA7E38C5050C7095FEAC515EBE9CEF8D2E +:10B8A000292F195E41A581A3849FA4C755CFACA6BB +:10B8B0007106E856D2A5A4DB01BA1C945FA983A344 +:10B8C000F1FB17288F2645F16E590F7E0ADAB1AFCA +:10B8D000A9F43B287D30978D00F7BE9D05B40F7A03 +:10B8E0008FB0F3FB9CFD2918D7BB47F815FD184F07 +:10B8F0004C8DBEEF4F10790381FE94348D5DF47949 +:10B90000B79A82765C6F38F6EFC9CA7B2A7BE3FC74 +:10B91000DEAC3CBF54A93AF2D7629CB69DEF4FAE65 +:10B9200068599882F18CBEEE42FA3DA19BDE057FFC +:10B9300017E6DB27E39A21BF39BB2C7ABFE9111642 +:10B94000A2FDCAE5DDF5B45F688C83AC74D4A4E2D3 +:10B950007EA0310E7233E641611EF263FAF7AB301E +:10B960003E827832D05310E9297B303DAD1C2EF653 +:10B970005F4B58896EFF55C8B54AB5E8A7689FF474 +:10B9800081DF8EF120A616FD1AF5E9B7E8C723037B +:10B99000843C44A7F5C12332CF8AE85AD29DD17F97 +:10B9A000373E4FBCF469199E076A78F9DF8A7F0E2B +:10B9B000CF132F7F32FA552CFFEA5FF3FF8D0DAEC8 +:10B9C0005FB1E78FE4AFF4EDB1D17CFAF6BC9D7FB7 +:10B9D000179677DB7C38DFBEF536FE7BD07B92E9AD +:10B9E000DEE9BE613CCED6FADA77C5BDA4A7361033 +:10B9F000DEFE6E38BF2FF654F77F7D86F7AB9EEAEA +:10BA0000B67931EED0B42789FCF0A6DD09744F7CFD +:10BA1000DF6BDF9569E345FFDDF5348AF3167DC9F9 +:10BA2000AC16F35BFAD2B8BFD6F4EAD4275A0AD0E0 +:10BA30002EDD4BF71657BCFEA762943F7D2F70BBDF +:10BA400002FCF3C77113F117C3BB7F6A998AE78DB4 +:10BA500018F9D553BD7FBA36E48805170E873E80A6 +:10BA600003AE0BE042F775C78347D7707E0FFFFF29 +:10BA70003E787C4DFE4243F764E2A3285C14FEFB53 +:10BA800023DDC961BB42EBE7EFF77C578C76D2F13F +:10BA90008E16D2FBE75BF787FF6BE9E0FBAE5B89B5 +:10BAA0000C65DDA7FED7AE9BD3FFDAE15C3F19F949 +:10BAB00060309DFFEAAFA9FC5CB28FE66BE0FFFF50 +:10BAC00007ABA359F3008000000000001F8B0800A3 +:10BAD00000000000000BCD3C0B7814D5B9FFECCC76 +:10BAE0003E926CC22604084260F2244A1E0B791072 +:10BAF0001EA99B842008E206A4A2222EF8E015923B +:10BB000008B6C66ACD622202F5B6516CAF6DD16F30 +:10BB10004141DADA6B8A41B1025D10115AAAAB8257 +:10BB2000A246BA52AB50031B41052ABDDEFFFFCF30 +:10BB30004CB233243CFCAEDFD7E423C733E7CC3927 +:10BB4000FFFB75CE18498599ADB9004DDB4EE587F1 +:10BB5000B1056806280648526D00FD004E6CFDFADE +:10BB600090944CAD5D853480BAED710045D8FE31BE +:10BB70002600124064DBA9129F13E01BFAB912A041 +:10BB8000A3119718D6DD37B71D9B3F2CB917A7D443 +:10BB9000BCF041FEAFB1ED78E1BDEC97A9FFE2BB8F +:10BBA000433EC0B6D606BE565C2F120F3337213C3B +:10BBB0009144F000EE5FF7F2E8A796E1FE8BDB3EE2 +:10BBC0009F4DFBD76C1D0532F62BFFF4EFFC30CDFB +:10BBD000DF2479C4F3F88003E1AADC7E463CDF7EF3 +:10BBE0002A1FB0FD6C93149413B0FF807D7E80D625 +:10BBF000ED05EF118477F17F22DE3B6CB7E278C36D +:10BC00005095E1EBC67B870DF208DFBDB3697E641A +:10BC10007BBCCB9E46F0FD7B0844E17F21BCBDFF91 +:10BC2000B1FC3E3FDE007E86DB2A7B1DE908DFC3D8 +:10BC3000100CA9D83E0830B1D5792E3C3FA6C16280 +:10BC40007A0F42D01F4006F123272F9C0209D4AE61 +:10BC5000FA5CCEA7F7A74D4C4338FCAAC5BD5EA53C +:10BC60001916A6C38AC1EEC02A840B14EFFCB5D8FE +:10BC7000B70EAD71AFE215EE042801F881435BAF5A +:10BC8000FF948912AED7B40CE1C2759AFA595C4D93 +:10BC9000B88EA25A82F67C6E3FA2F6A1FE57EFA1A3 +:10BCA0007D15A70D82DABBDFE03F27603F47EBE35E +:10BCB0007EB199517DFC17033B5D0AEE1FE35620D0 +:10BCC0008028D921EA7D9C7F93EA62BAC442C0EF02 +:10BCD000725E3A9D7E4F83FD7AA793993E3ADDCE00 +:10BCE000A1138083DE57E8BF08FFE45521D2430546 +:10BCF000147F58E0237D23113DDD290E5CCFDAE768 +:10BD00000EF72A899FAB4A89F69E85FE2C31D01703 +:10BD1000E9E789C9EFA673D47A8CBF99CE974A5FB9 +:10BD20009D2F31308DF91C33D8E90E20FC0FAA82EB +:10BD3000EE0F22DD25A99BBE3ADDCC7CF093EC14FE +:10BD400077D3BFBB1DE7FA64383312BE41E2FA2B4A +:10BD500020A71ED7A992C785FDB8FE89D238B79D06 +:10BD6000F44582A03412DBF2FE15807874A4DA1454 +:10BD70006ACB3A11A72878AF3CED00250ABF72487C +:10BD800034F43B52B3F9FD4AC740C37B1D034B1D3E +:10BD9000F4BCCA956698FF464C423E14D07B1326ED +:10BDA000D2F85529971BDE9B7AB863CD1C6CAF95F2 +:10BDB000C245241C1D7B675510BD26A9230CF3B674 +:10BDC000A059217DEEAC9203EB901ED552B07F3E80 +:10BDD000D26D72CE68237C128C273C6B2C285A388B +:10BDE000EF1A77B961FCDAD2498675AB3DD5867E0C +:10BDF0004DC357A0F40518DB70169442B4E3C15646 +:10BE0000C3FB857BB618E627EC03391EDB11FBD597 +:10BE1000266A0BDB434924BEB6BE0EBFA50F8A704F +:10BE2000D85B89E840C991FA57A86D70203DF0F9B8 +:10BE3000A918D122BF58CEFD8762024D08EF294BC9 +:10BE4000C04774B85B0EE4501B3BE88E7C48073853 +:10BE50009AF2B0DC87E0075FA78A7230FA8B401352 +:10BE6000F5AF3CDB2AFBC80E6F94FDB602E2FB94F3 +:10BE7000B8BF92DD6D9580F85EE3B47802E4B792C6 +:10BE80005AF39746C9D7673F845BBCB9E7EAEB8BA7 +:10BE900059E596345CBF39C5D3B283EC66C587B328 +:10BEA000E5F473E7814BE90CEB7449A7F7BC4583D4 +:10BEB000511EE5F8F10EB2EBB19532E30557590387 +:10BEC000EB719DE516778CA6FCEC5F5D13AC6B49BE +:10BED000AFD7A409FB10FB175025843FB6AF4FCE58 +:10BEE000A3F77E26C17AE8DEEFD652603CB2D22CB0 +:10BEF000420F1457BF9BF3E8FD787EBFA454D011C6 +:10BF0000A6580259B864C241F76E2BF657E7EC7792 +:10BF10009119689B72D82F235DDA0E86CA24D4A5A6 +:10BF2000010F979FCC14F3210BFB6D39E3E3F2D89B +:10BF30008FE558C8CE2C41B347766647D93339E4EC +:10BF400027965C7EC500E8C1BEE96DC26909D4C20E +:10BF5000EEFE9A3495E14A50C2407A9D705AE171E2 +:10BF600068C8B690FDD1D74F98A5BEBB94E0D86302 +:10BF7000852CDA5EF12C223C565DD1AEAE623C04DB +:10BF8000DE00E1142FA2FA4FF4932A315609A7DC00 +:10BF90001C7F2E1CFFDC589CA8221E7DCBDD896EE9 +:10BFA0006A7F8F441FC374F7131D7E4A7F2EA3DE62 +:10BFB000DAD0781CDF4836518C0701E57A954D1BA5 +:10BFC000279382FDBE9236EE5FEB1D4F7C958DF37D +:10BFD0000BD2BBE67B1C29DDEB7BD7AE0D35F748DA +:10BFE0004F3BFBE55513AC01BB7431748DBB005D59 +:10BFF00013045DCFA2F5C77DEE72887D3E96D421F5 +:10C00000246FAB2D68053200F6BB7CD7935CC7CAA2 +:10C01000C13C7A3E37C133A00CE5AFCDE619720FB3 +:10C02000D9956D31EE75F85EF59D9F3DDE407A3D08 +:10C03000F59F39CD24378A276E24EE53E7FA8AED2F +:10C0400041959CDB87E29D2E3A923CE39E3FB5747E +:10C05000F7C93E2474D3D59389E3ABA2E8EC709082 +:10C06000FD12FD47D3DABC4CA7DB1C4CA7A59A4EAA +:10C070003527428B05F5E1A46BC3F7491E4E6EB41C +:10C0800002C54D6D3448FE32C7C17A05C9E1946AD4 +:10C09000D483BC372D5E8ACBDA513E3C241FF5D9C0 +:10C0A00086F54E8E7B37290FDF3B99AC24117D1628 +:10C0B000866D4CB79B1508DAD15EB625DF5659CE92 +:10C0C000FAA1F278ABB6CE6B599EFBD2D8EF8C7743 +:10C0D0007D8278499E31F237C37BE71779D04F7460 +:10C0E000FB8874AE2334937A9783E6724780E2CC60 +:10C0F000BAD265B9E41F9624660F00C4A36EBCC40F +:10C10000FEB6AEE10BA6BBBEBE725A06B56F777F18 +:10C110007C86CAF640513C2C0FCA691B8FD7349CD1 +:10C12000643B8EE0A491DE742C13F6AEC50AB754BE +:10C13000635BF3BFF22DD538BF06430CF617B0D3BF +:10C14000B624CA1E42EBE75D76BF0079B77ACA5BB8 +:10C15000B16467AB25D70C401C8EA6BBAA95D1D87D +:10C160008F71CD90B0DFB6EE8C97FBA9AE1916ECAF +:10C17000EF4ABB498C0F74FDDCE206F87CDD5DA262 +:10C180009FE63A40FD0FD31EA95606623F5EC8C126 +:10C190006FD26AABFDB9245F4EA6CB891571AC1F77 +:10C1A000BDD1795EC3CB06BA9C332E4BB778C96E2E +:10C1B000CC1476F1D8CA416B391ECA0C65D39E5B8C +:10C1C000D344FCDA1F79538AFF5E45BD77201D9268 +:10C1D00033C063C1F9C92FA23FA2F91F878610FDA2 +:10C1E000E6BD181394901F8B9F78C546FE68AEACD1 +:10C1F00066935EBD3FCCB793E4E3787C88FBF31A8B +:10C20000B6335C29592E61A75D9DB95E94CFF9D0F4 +:10C2100062A3F1F9A01C26BF614161A6B866A173B3 +:10C22000978DE2B2854F5B0F87A3FCEA22081F229D +:10C230003DAD79D67A381CE57F81DE8F92AFC3168B +:10C240000187A2D163AE1C9A6D13701D20B816270A +:10C25000617C2F93BB08F5F7715C5493C379494A0D +:10C260002C90DC2DBFECFD7C5F0F7EB0B511FD3E48 +:10C27000AADCA6C62DDCAEC135C9EE0C50C23637DD +:10C28000AE53ABD9E592D0611B44BD7F42A36B9FF7 +:10C290002D128FEBF6A27B3C5ED025D733C2827085 +:10C2A0002C9EB66F1CF145E7E79571D01A93C47CBC +:10C2B000716B7C71135F74FA233D0B157C6FD7593A +:10C2C0007C2FAD27B9D0E92FE06D8B15F6A27373E3 +:10C2D0000CC74D66F8E3D205BC3A1E43D3CF0FFF1F +:10C2E000D0F4EF06FEA1E9428FCD78E87AAC3FD7D3 +:10C2F000F5D88CB70EF7A5CB59C8763172A6DB9965 +:10C300005AF0E5D0FABA5DD1E9ACC3A9D3AB8DF24E +:10C31000A11EE0541A5E32E0A3842A28898071E9C4 +:10C32000E9C28EB54E02E283D2B095E75D2A3EBAED +:10C33000BDED0D2FDDCE9AF1D3EDAD8EA76E7775E5 +:10C340007CCBD090B03DC4349EF2AC2B4FFB0C7133 +:10C3500070392C30C4C9958E3B0DFD2AD73D86F926 +:10C3600057A52C338C4F52571AC627E73C62E85F1B +:10C37000E3FEA5298E5F6B8AE37F63181F170E719A +:10C38000DCFD7AE344509047DF3BD2C9F177B0D16E +:10C39000C5FD9D8D29DCEE6A5459BF7737E670BB29 +:10C3A000A7D1CDCFFFDC58CAEDBE460FB7A1462FAF +:10C3B000B766BB30F5F9EB15CA574A432D9564CAE9 +:10C3C0007764F87E928EF47BC312688A473A8D6A4E +:10C3D00017F139CC37FBE35387EE25BFEEB2B9C96D +:10C3E0001F36EF182DA93DC47309E8EF3C51F292B6 +:10C3F00030250C1E8A7BD03DF7245F2DE916964729 +:10C4000032FB807A37D301D664D4B79933257713BA +:10C41000F0733F24711BF4E1F85405FCE4FFAB9D7D +:10C420004AD09EC0A0791D08E70C0126D8699CFC63 +:10C4300077725F85E2D6EBE821C22B7B64F81E3E63 +:10C440009F51FA97339437DFE86CB5929CDCB0E7E4 +:10C450008163F7E23834FB8B493FBAE206FFFB9673 +:10C460004B891B5A28AE443A462477C843F14EA262 +:10C47000E28ECE07F4F6B674910F4C6DF2CB0948FC +:10C48000CFCE3781E3385D1F11BF1504BFAE17D57E +:10C490002E25382C81FCFD239534BF66BFCA74D18C +:10C4A000F542D7033D0FD4F5A04A7EB689E69F3802 +:10C4B000089C4F8FEAF01D799EF034C59DA59D2DF7 +:10C4C0009594975D286F1C73BAF5159AB7BDD1C7BF +:10C4D00072B4B57126B7C1C6F99A7CD6737F57631B +:10C4E00003F77737FAB9DDD3B84293CF161EDFD7FB +:10C4F000F838F75F6F0C6872BA919F8FCF10FEF714 +:10C500008B50E50092BF17D3451D071CE59C478063 +:10C5100022DA8B95939A9497453C65920FB35CE829 +:10C52000F200683724A4D78DE867C93FDC04FEBC5D +:10C5300039D8CE9CD7621D2B7D7BB958E86CE6F8C4 +:10C54000C36C0F174090EDDDB9F65DC4FF17B2EF75 +:10C5500032E6ABE4AF74FBB718C2BC9E5DBED34DF0 +:10C56000F594EFCEAFB834BF0273687E57DE1DDBA3 +:10C570003E5BB65C38EF2E1A2CF8AAE7DD183F02B6 +:10C58000F9E54840E6B87A7E5A4B02E7DDA59D09F9 +:10C5900014072CD826333F30CF540622DFE6697CBF +:10C5A000EB80E03BC49779E3E6715D6EFE1A233EB3 +:10C5B0000B9DD7F509AA3DC6693DE2590B0F7F4E89 +:10C5C000F5B95A8D5EFC1CE16968BF61D2AEA879ED +:10C5D0003119F1C99FC49142C128A207C2EF0E923E +:10C5E0009EED9759CF7A938BE3989F909C9F6A9C7E +:10C5F000396917CAFDF1B38D9C7F25653CF2887FB0 +:10C60000DC77C7AFB559DEA1199C0F856DA43F3A01 +:10C61000FF96938D44B8975738029468478A5D0A0D +:10C62000ED1F913C723CF1E323702F43FA956F7D2F +:10C63000ED20E947B9C3C9E708884447343F47EFCD +:10C64000F7353971DEA87D1E99C2F7E25DE1269AC1 +:10C65000A6FB1BDDFF8CEDE8947D5C17C8643D02F2 +:10C66000CC25BEC9B8783D32E79B4D946FA2413AC4 +:10C67000E99CC0F09E0C829B9E77D7B544BD69ECC7 +:10C68000598F9C80F02DD7F2C3D11F7B198E6A87FA +:10C69000CA7268D7F2497B8A053C517474D97C1BF5 +:10C6A000A9FE097F8CE13AAF19BEC919C28EAB4908 +:10C6B000DEC94C5FA79A4D794395DCB1E1D7240FD1 +:10C6C0006D716E3BBE67B6B7BA7DEB2D6EAF739DD5 +:10C6D000EC318ED4DB3A8B38371859A91652FE4705 +:10C6E000F125E5857A9E689EEFCBAA989DD18FEBC8 +:10C6F000AB210FC1E5B29C574EEB1A3E3F6F9EA691 +:10C70000EF5FB7ADD83537AA0EB226433F5F505C16 +:10C710009F38BAF976B1FC2DEB9C69F03FFFE9F147 +:10C72000DA540C7324D4A13C2920E20810F1C42C63 +:10C7300008713B1B3AB9F5A124513B17DCDCDE063E +:10C740005E6EBFCEF4AD26B989583BFB931E1F7BAE +:10C75000E1EB5C928B63DF1BEB4A53BBFDABEE6FEF +:10C760002FD5AFC6D2F9520FF2B041935BDD6EF711 +:10C77000CA1F93DD8E8C40FB807046368B73B148A8 +:10C780007C6C80CE0174FB007E63BCA8DB8BC2593D +:10C79000EE37B85EB84FE6BAA5D97E5429228F0786 +:10C7A000C59D43F5517DFF260BCC2739DB88ED1F56 +:10C7B000108F3EB3C28A1A85CF760D8FF21BC60347 +:10C7C000E52F535D223FAC724032E57370F664EEA4 +:10C7D0000C340453291E45791E95E4F913D1DBFF6F +:10C7E000D0B8443E7F20FB3314F9F79138B7810568 +:10C7F00052200BE9B1A54DF4F36E4F64FC6E82201C +:10C80000F3F166085B09FF5B00D8EECE0195DB5BB8 +:10C81000C1C3FCC495E3F2D10EDDDEA68C5C857845 +:10C82000162475A6937EE68D7E2F4942B8F229FE26 +:10C8300075726D6605C5293A1E964C81C765999E2D +:10C84000B709BE82A4D0AAD514176EB600C5859FBD +:10C850008EBEE70E88F2AB2559150769DE73923854 +:10C860002FF46FB38BBA1A74F6F746C5E35F6756B9 +:10C870001E22BDFF07C1C6F9EF2A3E47AA7609DA94 +:10C88000C3F87E4C037C6F8837AF27FDF4B37D2C53 +:10C89000205A8A3AA11F4A795FEE7FF5D417D5CD89 +:10C8A000021F3FC5632559BE08ED5760435348F04A +:10C8B0003F610FACE3B8A97E08D52FE63D69B7907C +:10C8C0001F7F0FED309D9B7ED0E8E0F643CC6FA834 +:10C8D000FD1BE637D47E84F90DB57FC7FC86DADB15 +:10C8E0004F8F402102F861A6E77F33CE8347EF7672 +:10C8F00046E0119160664FE77DA73244FE91DFF676 +:10C90000F1037124075B6437C969DE6685EB10C7E4 +:10C91000B78E0AC869D174F5C565221CF95BDE7E45 +:10C92000746C11BDA7B8249C7F7CCBC9FE9C379941 +:10C93000E0EBA2C7369BA08706EF7389A155F4FEF2 +:10C94000739BD30942B42320E490F8D9431D0D60B2 +:10C9500019F3F1F50C113F5D6BEF2C8A3EDF040AF1 +:10C9600019A85EA9F9992AF96C423857ABDB8E26D3 +:10C97000B9CE7C83F6F3EF117A887C35D4252A353D +:10C9800039D4DBBC6D362FE9D373DBDE993619E978 +:10C990003075CCA46259ED9E5F98D98FF7CD1B7D81 +:10C9A000E657AB93793E9F5BDC006BAB5C38EF26C0 +:10C9B000C78E57890437BB3EAA4AC4FE2D29D26EC2 +:10C9C0006AE7A8691392C80E4080F7B935A77C378B +:10C9D00089D81477B58DFC7239295594DDAD74C4AE +:10C9E000D1496A57BFCAD5D7D0BF2A659061FE2406 +:10C9F00035C3303E3967B8615CDF778ABBD0308F92 +:10CA0000F495E266C483F90EEB653E97C9DBFCC57D +:10CA1000FB8B18FF1B8A08FF08D2CF8681C591D2F5 +:10CA200095BF584D6663F3CE043EA735C5A735DBE9 +:10CA30009EDAED517B8F4FBF84AD3DC675B5BDC449 +:10CA400075171B9FA2FD7894EC47C10BD7F1B9FB7A +:10CA500073A3CF5CA6225EBE4C8C5BC9EE99E2D676 +:10CA60008816B79AE5A74B4E2555C8CD5E19280EF6 +:10CA7000D2E357B3FC003CA0F97FD15EAA9E4F7D64 +:10CA80004BF8AB7F90BEF78D966BAD35D5230A6C16 +:10CA9000E857A84EF85719D6D183B308874EFF8CB4 +:10CAA0006EB987DBD6BE3AB0889FFBE371CB5AAD37 +:10CAB0003EF1AB4CED9CBF66C7AB0393BBC7E1AE89 +:10CAC0008F0CF3E13E69B7A1DF9C66EC3F5CBE3B97 +:10CAD000FAFDDEECD0BC3577DA7C54977E4CD42955 +:10CAE000CDE33A3C553B633C642F95AD76CE876AE7 +:10CAF0005D1EAE9F28BDD44F74BB70830CF53DD92D +:10CB0000B7F5DABA5376C680FC2DD67D0F6585E081 +:10CB1000F1BF28FCCC7B7D3CE08DDAA73553C47D8A +:10CB2000C7125B7EFC15CE3BF612B889F4C712859E +:10CB3000BDCD6FFBD462213F112BE425DF15B62458 +:10CB4000D17D97F9717E3A4FAE5B10EFA773A38248 +:10CB5000F4CE771CC8FA2D4FFB1E75A0DCBD6FB15B +:10CB600018FC4E846C1DF67764FAA691DF99BC33ED +:10CB70002668F916F8ECC804E1D72A84BECF26B996 +:10CB8000D1CFC5D0D4D43D08867332C29FFA679EF8 +:10CB9000BEF5ADC728EEDD2BF41F879DE67CF4A61D +:10CBA000A87C14D608FD75E02FC5390B77B5D828B9 +:10CBB0004FFAAEF4BE3DD3D9ADDFC3CED5675DDF4E +:10CBC000EB0E087D3FB1F5CBB7C8AE9F407F17ADE8 +:10CBD000EF5D7E51D3F3BAC765D647FDF9F1ADF2EB +:10CBE000C4400FF47D4D930370651BCECD96949D8C +:10CBF0009A467E6DC93685CF037BF3D7752B8CE7BC +:10CC000064CF6DB7CF17E7C8028F88EE4FB77D9915 +:10CC1000549E2BDA657C5EDBA2D91D11C7A01FB51F +:10CC200026931FAD96B8FE7660DB00BE9F714082F2 +:10CC3000A03A9297B8CE817C9B2E96A3E74E8AC7E6 +:10CC4000202547A17DA669FC9CAED585666C9B918D +:10CC500045FC7AA76DEE010FA19795C1F2733DF8DF +:10CC6000391E3C90E84DA57B0A539B847C1F48EC01 +:10CC7000ECA03AD281B23889CEA370FDE6E878EF15 +:10CC800080D59B5ACF78E9E79357C8DFC45D421E31 +:10CC9000ACD943E4A75F12F91CCBBF32F06196AB6D +:10CCA0000510D8EDC17D6BDD418E4B1781C8EBCDF2 +:10CCB000F17CEDB8CF6CE417CCF967F9961D07E964 +:10CCC000DCE39C3A84495E2F547730E7BDBDD50F35 +:10CCD0004625790BB3A2EA7EE6F8BC2B0ED5E3A875 +:10CCE000F5717C2EF44AD97F1F5F84FDBBD6C7B98E +:10CCF00028CF3EFAA4DD4F76F9E83A7B40C2F1A393 +:10CD0000499DED94771CDD94E7C615609E45FDDDD9 +:10CD1000B3E4D77F6B65B90030DE6B58527637DFEE +:10CD2000FF5BB23E5EA27B389022C6F59C4F7E260A +:10CD30009EE38205CF0FE4734EDDBF907ED0B9F441 +:10CD40009127623C14E41FDD33BD0FD5FB3A2C7FE5 +:10CD5000E0F37C90EF3B44E7F58B36C48FA4F801F9 +:10CD60007281F9367FDDE57CBEF973C53783F0AF9C +:10CD70007CE69A0174AF6CC1DBFD80F0896C7D9E0E +:10CD8000CFFFBAE3F49EE3BB135B33FA406E379DEB +:10CD9000F43AE08AA7977989EFC5922ACE69A0DE96 +:10CDA0003388E4624B35D0BA2365716FB473651C68 +:10CDB000C7A566B9ABC91271608D5E6FE80B8E14A2 +:10CDC000D21F1F301D222B87AFA3F3B0E6AC24CDBA +:10CDD0004F77664F8BBA975825B7D7BE4CF2B9C676 +:10CDE000CE75908E989ECFC11AB21279FE3C87F113 +:10CDF000DCBCB6E18CB19F8BF91DBE3FB2492DBCA6 +:10CE000013DBA51AFD57A77AEFCDC2F717B63EF28E +:10CE1000C23EA6CB9A1FBE4FFBEE718AFACB3E41B3 +:10CE20003F73FC3FCF21EA1C006B797FFDF9A74FD0 +:10CE3000BCCBE7AB9F6E1E9E2DCE8D439FFC3A8DE3 +:10CE4000CF8B0FDD8BEDA63D6F315FCCF09E73EE87 +:10CE500027498C6F0DE1D197CE77BD8F109CC80804 +:10CE6000CEDBE6AECA63FAE9E76F91A33DE7273A66 +:10CE70009CFAFA3A7CFAFAFABC27B3441E335BCB2D +:10CE80000F8ED942C7F91CFD85E112D5F7BA9E274E +:10CE900085F213A3E4E5BBAAA7DFA8D5430E5A96F3 +:10CEA000FDC046F7E45A575B7DD176EF12EBE85DA3 +:10CEB00071A00754577FE14AD86F21724A7F3AEF39 +:10CEC000D3FAA40CD81FA78127113C746F506B6153 +:10CED000A12F85EBE4B49E4CD71003DC6F2A77AB0F +:10CEE000D45E29791571EF2BC0F23F01EA07131EBA +:10CEF000164798CFC5F47B2E3312975F9386FB3588 +:10CF0000F783E514C7345B855EF8E7C471FEA6D3EA +:10CF100049F733E0CA35F8976617A80AAE3353814C +:10CF200015D624316F28D2F9C09EB9AF529CF0AE0D +:10CF300052DF8FF67DCFF9589E64A1F82E104F393D +:10CF4000E2FB6FFDB6F8AF38F703F09439517EAECF +:10CF50007BCDC176DF5C8FB81D7CDC9F0761EB1752 +:10CF6000F8DEDF46FF6BFD4EE8C6EB6F63BEDA4CC2 +:10CF7000F9C14D890F14D3FBFA3D4CF37DBFA32EAD +:10CF800027DF0B34DFFBBB167C9F91DD3A65F1D5C3 +:10CF90008AFA47FD28F2BF91441B48383FD24FA37D +:10CFA000C731607A44ACDAFB9FABDC2FAA1CC9F511 +:10CFB0004838A5B23D1E6BF23745C32D220FFB4604 +:10CFC000CC2FEB540CFEA6A840ABDB7CAD725C7A98 +:10CFD000E569E5BCFEE8A16C61CF8AFA5AEA7B8A72 +:10CFE0000FD56CA13F4D1094053E224E18DB2557FE +:10CFF0001E99F857ABF56BC99FA13C45121C7EBA30 +:10D00000E83876AB90AFB14A7007B5685DA181E2B0 +:10D010008A2DE8EF7438E88C306538CBC1185D3E56 +:10D0200071AD59386FB954CF798B83E2196C574978 +:10D030002186E37BD0C9AD47F3E315E0E6763C7883 +:10D04000B945F9E47622B4707B35B4723B0542C22F +:10D05000EF5F116C627F06F7B9F8DC62D23C0BC55A +:10D060001B45D7F79C2F546874EA9D0EA87025972E +:10D070004E8709807A97D1033D06E7B0FD30D3C3D0 +:10D08000AC9F651096593FC93064509D40653DADD9 +:10D09000040FF7AB2E920EA5619FC2751A333D2A7D +:10D0A0007B968BC91A3DFE950D2C1F3A9FEECF56ED +:10D0B000F9B9CE2FD4AB14927F331FF5E745711524 +:10D0C00027E96AFA1DD9C3A7D3BDAAA2C28AA5645B +:10D0D00092EFDE30663ADDAB2A1A5BF13C1D79DE59 +:10D0E000933D4EF40B2A0AAD6ECC5AA4B2E9E3711B +:10D0F000BE4FBB970C33457C7D9716B7F896FDC0A5 +:10D10000ED423DF1A53ADD849F03837BAA7FCA19D6 +:10D11000E27C70C8C4E04E2BCE3BA4F8E664537C9E +:10D12000E00826A848F7BB9655F1BDB5876C62BEEE +:10D13000DD2EEAB03A5EF8DC1F83FD4D9B862F950D +:10D14000D27BDF1FD7ADA5757DCBB2FCA4AFBECD22 +:10D15000925B70B262C04CD4CF8E9015A81EAAEF1D +:10D16000939DEA5B9ACDE7BAD95C271BA4C5331D12 +:10D170009B860F27BEDC9FADDDC34A4E2B24BA2D04 +:10D180004BF5DE4FF323F142BEEED7F8D05BBB2167 +:10D19000DB735F76F1B9CF23FF4000F0FD9F65FBA5 +:10D1A0001EA0F5EAE2CEB27F3F3EE2EDE5E1B46ECD +:10D1B00039959049B310EF260F046CEC07B4FBEAE5 +:10D1C000DA7955E4765C07E950E4F53591491B3589 +:10D1D000ABB384EC27AEFB5FBCAE2D3C6404BEF762 +:10D1E000D8F44336216783859C697668DBF6BDF702 +:10D1F0000E125D2F44E955DDF6335F7D80F4AB3BC5 +:10D20000E174D3F46E7DFAE552CE27C169B01BBA42 +:10D210009E8DD962E7B87AECD6CB6FA779656FB7E8 +:10D2200067105E57B687F91C2CB2EDDD41020E3D4A +:10D23000DF38257D1BBF4BE7B49CC76D16E7B44BA9 +:10D24000A4FA57E2A9FF7BC9ED47F83FD5FC869EBB +:10D2500017CFD7F05ABC77FD72AA8BCC5F73EB1453 +:10D26000BEC7131079838ABFA4FF5FC23E3E1F5F13 +:10D27000B4D19C4F74DA88FF8B5B4DF781281FA6D1 +:10D280007B0FD1F6BD877C787BB6764E9B0AA98C46 +:10D29000873CAB8FAF077B67CE771F07CFAB2C9F49 +:10D2A000E09569FF62A5E77AC273DDDFD3B03ECCBB +:10D2B000D3F6263A3939DFB589FBC24F2C75BBA8A6 +:10D2C000AFE9E75A9495528AA33B7FC9F2AFBFA753 +:10D2D000EBEB8215E25E36ACE9CB3257B0C1EE2102 +:10D2E000BE166C18C0F905E6411CF7ADDD605F4164 +:10D2F000FDA60763FD7201D5933B2FA3BA4A538C59 +:10D30000F8CE89DC23DD132D4817758E33BA5DD72F +:10D31000FCBA7EDFB62BFF89CFE67BCD5DE361C52E +:10D32000906F3469F17311C1477160BD55E44F319D +:10D3300002FE1D6F7E3F8EE2D8CD8A378EEAD2275D +:10D34000F6A7F7811EE8A6B7C5E85EE03CE78CC506 +:10D35000EF4EC9381FBF8A1ED7EEA76BF2F9C7463A +:10D360000FFCDDDACD0F1DAF2AF9D94A1BD5396E76 +:10D370000317D53D96EC7DAA89BEB759B212B8A263 +:10D380007082FE50BE70C4C2E7E063F616A6903C01 +:10D39000B669F68ECE85D528B92AA1A210CE2F1E49 +:10D3A0000C01FAFE28468D05352A2F8ECB4932F422 +:10D3B000E3DD9719DEEF539A6E1807BF27945BD20F +:10D3C0001DBF267AAE30CC7F2861027F8F5316BAFC +:10D3D00083EB4A7D278E348CDB51AEE99E037C21A2 +:10D3E000E29F52FC65BF0AF532C139360CF02B942E +:10D3F000BB311DC6F8A834DCC27960CC7EC590D79D +:10D40000DB2F5067BA7C98A6578361B0B00F667A5D +:10D410001BEF432CD92B731CB7241503CFB4DEE9C3 +:10D42000ADEB9F4EF77E5E23DD07CC34D279A0CFE3 +:10D4300048E741F38D744EAD37D279688391AE6978 +:10D440007E231D33568C31CCCF6AA930F4873D7EC4 +:10D45000B561FEE5816986FEF08D371AE6E7B5CE47 +:10D46000358C176C59785EBE8F082E318C9BF95E17 +:10D47000B8E74726395498CEC5DAF7593AFFFDF890 +:10D480004BFC1F0BDE3E4189CA81FE26D2C7FF2F0F +:10D49000FE2F18A69D23E8FCBF48BB7A95E687CDF2 +:10D4A000DF794D8D13F6E6F53D27F67BB0FF865A02 +:10D4B000684DA1B8498B0FBCFA798429EFD3F39456 +:10D4C0006B4B25D3397D8CE19CFE42F7DA8A4341D0 +:10D4D000437FC47EF17DD4C883EE57A82DFED823A8 +:10D4E000477F0F35FA0B76CBE7E49DFAFD383D6FA9 +:10D4F00082E627390F9DA5C34F4A50726E7D51CFEA +:10D500004FCD79AB9EAF9EFBBD95884BEE967BCB06 +:10D510006345FEAAE7ADDF070F7F5776D560DFDAF8 +:10D520006168FF654B675F1AD7F359222C9D1B4733 +:10D5300088B0FCDDCC3BD33DB9FC3D2AD7BD174AB2 +:10D540006F4FA77BFE08BE2B5C22CA3FF4F3D2309C +:10D55000DFEF68BDC3926B7921BEFBFA98CF86D00E +:10D560007AFF334CC46F76192984FE67C02C0FD024 +:10D57000F351499EE768BEF97EB6B935DF1B6A6B89 +:10D580000C72ABB8DC7C6FC75C1F0C5B548E3BFD30 +:10D590003F92F89ECE6704DCE8EE78E5C40A2BC71C +:10D5A0002BA0E5E3376BF4D7EB16B3347C0EE31214 +:10D5B000F3D1FFDEBCE535E6CBA2940EADDE51CF54 +:10D5C000F1F5AD839D23F91E9AA7D02DEA5C7A1D53 +:10D5D00063D0257D5F7221FC17A51C35D491E0D95D +:10D5E000BE1775BEDD8DB758FFF04A518F3CBC3277 +:10D5F00095EBDFDDEB1FE77AD2CDF56F1AF4E296FB +:10D6000086F70C7A30C7FF91613C9CDC69A5FA6112 +:10D61000F88581136E42FA1DDB6CE7EFA1510E3ADB +:10D6200088AFFAFAE195C3C7F3779517C4F3338649 +:10D63000A3BD31C4FCD5F13CD47890FBE1C630B732 +:10D64000663CF53A85DEDA76420EDDCFEF9462DD98 +:10D65000541736D72FEEB6A89F901E3C9493AEC5B4 +:10D660006BF5055EE69FA857B46BDF97B66BDF9747 +:10D67000B66BDF8BB66BDF87B66BDF8146ACCE1542 +:10D6800054D76897C4BD9F5992E7C939B85FDA602B +:10D690009F3387E2FE859DF90AEE5357109E2D2198 +:10D6A0009FF3FAF9FAD07309D38581FC3D919FEF7E +:10D6B000871DB1F8F3E9FB9BC91BB3AEA33CF0484F +:10D6C000ACFF384522953969D751DE77C426F4700E +:10D6D000FAC6D8EB48EF3EC6C5083FFF4B92A82BD1 +:10D6E00039C336FA7E6A6AB26F504EB1B8F7C5DFF9 +:10D6F000CDE073924BBDCE19B18A3830A2C583E913 +:10D7000039E21C302347C4AD7A5B463CC7E7D3A956 +:10D7100065FD7C389BBF375963078A5F717FFEBE0A +:10D7200046BF6762FEFE66E49FECFC9D845E0F2DA3 +:10D73000C949E375E8BB1CD2CBE49FC4B1DD82705C +:10D7400068087DC7D305EF7EF15DE531AA2347D593 +:10D750009F4B72441D066E03C377408BF71E3E44F9 +:10D7600079D6FBC37C6388AE732D6A09F17571C2EB +:10D770000EAE774DC951795F8497F145FBD34C7C50 +:10D780005AEC08737DEC42F5F0DEF03F767BE8174B +:10D79000B95CFF55F3F93B3C6D5F84630AD15FC709 +:10D7A0005B87A37B9DF3CBBF5ED7D5FB9F3EF1503C +:10D7B000B65697BFC5DB833FBD55A34BBBB5E73A14 +:10D7C000FAFD1A7FCFE1CF3000AADBDB63D14760DF +:10D7D0005BAFD1E9D80D880FD7273C2388BF8BA733 +:10D7E00039F9FB737D7D5CC7F787F3ECB33AD5BBA2 +:10D7F00090F05F582FEAEEFA7844127CF5AF14757A +:10D80000D0C5DBDF3B44FF1F8405CFE415727EAF3C +:10D81000BD6FA633D297BF8B9A2B8B732BA4EFDDF2 +:10D82000C46773BDFDDBD235922ACE57236BCF0C74 +:10D83000A17B648BE9DE1A7D1FA6D5AFA0CD5897DA +:10D84000427AF9A95E71EE7914F0B9965DF3237608 +:10D85000FDFDC18AE1FD634EEF4F893E2F687603DF +:10D86000E7072CB87F9B9E279BEA286D2151EF6C20 +:10D870004BB1719C4CF10EF9273DDEB9EB4D51EFE8 +:10D88000BC2B4DC4D1041FF1573AB89BE3842EFF43 +:10D890002FB955A29FD3EA0BD0FEE05BCAFE4B1E08 +:10D8A0008AFCA5F38B3F5FADD503843F2CD6FC5F8C +:10D8B00031AD43014E6E1FF68B45DABE183F72DD67 +:10D8C0006D34F89A04305ADD6CE56E431DE1FF00BB +:10D8D00090CECABD504500000000000000000000CE +:10D8E0001F8B080000000000000BFB51CFC0F003AD +:10D8F0000917B1A1F26FA0F1B33851F9BF5951F92D +:10D9000097D0F884B02E1303C30A46D2F420E39DC7 +:10D9100040FD0780F838109F6322DF1C103E210C69 +:10D92000F48F1803C34220DD0DA4AF00F11F207E49 +:10D9300004E44B8B30306801F1325106864420BD3F +:10D940000688CB4520FA4E02E96651F2ECD4E3A1F9 +:10D95000CCCDA39832BC411A955FA3C2C0B05695F6 +:10D9600081E1931A84BF02499E5D9D81A15605C243 +:10D9700036956360E807AA59208DDD5C33A0FC046E +:10D98000A0BCB83A840F00134DDDCB680300000043 +:10D9900000000000000000001F8B080000000000D5 +:10D9A000000BCD3D097855D599FF5DDEBEE42679A3 +:10D9B000819705B8090183067C09612DE24D8C1819 +:10D9C0006C8A2F88364E197DA0D56859223235B61B +:10D9D000DABC4012C2A6416D8741A52F5A2D525A7A +:10D9E000A3624B67D4792C1DD1B1355AAA76A49D78 +:10D9F000C8388E5A65E242AB558739FF7FCE4DEE6F +:10DA0000BD7909A89DF98ACBE1DC7B96FFFCE7DFB5 +:10DA1000CF7FEE73CB3E80090027F1CFB900574B83 +:10DA2000009037548237D608118026CDAD6F2A0674 +:10DA3000F886123BAC57B1E763E5D8FD3A3E9F5CF0 +:10DA40000B610005DBE703C4F07FACDFFAE0BA311D +:10DA500089207BA62CCDC2D21CDF2C9B5400AD129A +:10DA6000DF6F999CE9BD5942CA35D0EF05FA73B210 +:10DA700004A0E5E86FA71E32EBECBF0208455E0F7D +:10DA8000B0BFCC8259271580F7828BB3D230F278A1 +:10DA90006FB5769FA54E02F853EBCB530F4D1AFE90 +:10DAA000FE1B0A34F7960F7F3E0BD8A433101F4994 +:10DAB000777CEAD0BA07D71964489AC3FA03A43D21 +:10DAC00039ACDCB5ED2CB56C084EE73A00921CBFC2 +:10DAD0009FB39F2752932E60B50A29318FE052D908 +:10DAE0003F3301A829DB97EB763500C1E580B723EA +:10DAF000F2978177C4FD12EDDE0BAEEB04D66FBD5D +:10DB00008BD34B7B9E1C5B07C3E9C5DC0F138FA730 +:10DB1000BB1F37818FE631E9A8495E3AEABE9F8A8A +:10DB20008EAE443A3AEBFF9E8E927FBD74D441E3B1 +:10DB3000FC95D1114037C717F4AB38FFD0735E4660 +:10DB400096F64A4867ACDA87708FE353C1B896CE31 +:10DB5000EBE5694C4C41ECE93398DC1AD7BFAC1EBD +:10DB6000E11E7B74E19B58762EA9A93B9FAD2FBF88 +:10DB7000B1F7F90B581989A7A404DBAF3B4046A1C4 +:10DB8000C2C65B91AC66EB6BC7C1E6023C905C66BB +:10DB90002471BD60008C01F83BB126005957593DF6 +:10DBA000447FCDB40E37A4393EA4939EE1FD475A7D +:10DBB0007F08FB996D8AF1FF6B00D777AA7EB0963C +:10DBC000CF9764FF20BE0B87E6A771F29B2C7540B0 +:10DBD000FCD8DFF7E15F08BFD7FFBFCC5700953E09 +:10DBE000940FA17A594B617BE8CD56593DB24285DD +:10DBF0003493110555DD924B3FF5BE7402D4F5F216 +:10DC0000FD911A4243F0FD2748443FE3BFF55ACF48 +:10DC100006467227960663441F1A406ECEF0F57CC6 +:10DC2000B71509D9525F52232568BED8D3A5AC7F5A +:10DC30007209D77B77D42FCEB6CA2B8F2409BC3973 +:10DC4000E903747526B215A70FB55E367CD3BE38CE +:10DC50007DA89F933EF2D65AFAC167DFAF88691755 +:10DC60009C267D7CD1F9CC7D1DCE576D625F4B7DAE +:10DC7000C0F8F6F6BAC519ED8C91F7B592F83D5299 +:10DC80000F462A43BFFCC1FD4C0E2FD9FE2883DB73 +:10DC90007B836DBF94B1331B7B46C18712B1AFD775 +:10DCA0001CD7D7A2E8AFE5B2AAAAC9389E1BC763A2 +:10DCB00074B6317A7B12183F9C40DA66F850BA2B62 +:10DCC000D258875288DD2F209059DD1735529B8816 +:10DCD0000E52B42F267C1E5DB6E15F8DF86D75681F +:10DCE0004C4A56F87D2D6E82C38DF3317A57343607 +:10DCF0002043851A84B42F8C2D38FC4806272762D0 +:10DD0000FDDB363AE8D22B21D33E98F48A68E5F45D +:10DD1000FAEDD3932FCEF996D8E13DED7E41557FB4 +:10DD2000DDA28746EEA7C2EBE6FE30245E8503CC7B +:10DD300018DAA70D2ED8279DCDF475D1A590604F88 +:10DD400037E0AB3944A764CF6C28AAD490AE609773 +:10DD5000A4229CA61E85680EB5AB90741A47F636B1 +:10DD600003B653820695E6FB91E112F49734F697D9 +:10DD7000B271BF22F6F72B42AF4195EBB57E136E21 +:10DD8000D2B3EA509DADE39D9BD8FF189D242BA4F0 +:10DD9000D4FDD2F0F7F5A817995CAAC7E716B9B277 +:10DDA0007D900FA2B45FF5E2DDC1C75E9A3C9DD1C4 +:10DDB000475F4C01145BEB1EF318B56CFCE7CF9189 +:10DDC000521E49C0CBE05C24E07CD6C81D8774DAC3 +:10DDD00057EB213A5E74C19F2248C6C7F7FD5ACD62 +:10DDE000442F8BE6B986E060FFADB6AE8FFDF7C37A +:10DDF000C17D29A2794CB856562A0447DF3C2985B3 +:10DE0000F31CFADD7FDDFA2506E7B35552CCA313E8 +:10DE1000BC2160F3F519EF4746F53BCCF975D010FE +:10DE20009FCEF9CDFD081702E115FE9DE195CD9736 +:10DE3000AC19E85F8F783E26C5D6B3F9B2E6B74C89 +:10DE4000C0798A6599E0DD38CF2B2B8C7EE0E531F7 +:10DE500032E23328F83CCBDDED9DC8E0EC9C24C3D6 +:10DE6000BDECD1C6D2D1E559BB439EA95ADC90582E +:10DE70007F3DA9552AA3F045CA90EB32C9BB672460 +:10DE8000AE273B928BB5525CDE21BB1D887A296E92 +:10DE9000D1ABCC5E7C4662EB7745381D67D7C6B9FF +:10DEA0009DD83786E45740EC47D6B4C55990C10E8B +:10DEB0001E711D6CA24C7673B6CCE183A37C7CD51D +:10DEC0001C3F67F4F13788F13F6C92A00FE153E3F8 +:10DED0005EDC7F302A889EFD823E616D0ED54DB995 +:10DEE000EB298B7715B37DF44465D0755C5F92F6B2 +:10DEF0007933DBE322068ABF96BD674D377FAA9050 +:10DF00005D922D9F4826191C9BF75F0B3AB353FD7A +:10DF1000D114507DEAD55EC4CF66A614F8FCBD804E +:10DF2000F30718D9A27C0D30F9AAA37CD57BD33294 +:10DF3000ABAB751033D8AB901693FC8C640E444B8E +:10DF4000DA54F6BC7D2910FD025A1116FCB6475F63 +:10DF5000301406576723905DD319A9A1F5B597D75B +:10DF6000788BD1DEA957E9397CC2F061DA214C1EE9 +:10DF7000FACBC0C0F936E7432A88BC549B47F4E883 +:10DF8000D6F8FAF5EDA5909ECEDE67CFDC8FF327AD +:10DF90006F81D8243E25C935D5A40B359194D0BFC7 +:10DFA0006BD1629B32D0DD764864C9336C744A7A97 +:10DFB000D789B72C375C88F8EDAC60F45F3C7C9C6B +:10DFC00022E41F466FA9D8E28B4A32CC532CEB4493 +:10DFD0001F665DFFD04DF08FD47EA81DB3337371E3 +:10DFE000684342BC406D84D69703837F0CACE78ABC +:10DFF000F58E81666A179DDDBD1FF9ACC0E8AD46A0 +:10E000005C7C3774E9F3B46F70B786F108066DE98C +:10E01000C9DC21396104B99C782F26937C0CC9692D +:10E02000CD6003847C7D5152D63A901F91855D1856 +:10E03000C09B5ABBA7A27F19869884EF43313569EC +:10E04000953F59C0EA36FB0F8E94CE24D2E27C0174 +:10E05000DA7E6419ADACF90C1CEF0E06908FF9C98D +:10E060005B4209D2177FF285A7E1647F92E3596989 +:10E07000DEBF0CEDEE1B157F6C13D2438CEB072F2C +:10E08000FB07E55FD66CD5268FB30D7B3DD7A13757 +:10E090001628415A6FF65740E803A37ED29821F81C +:10E0A00018640D4837DB6A55C0F982410E9709673D +:10E0B000AEF2495A0682E318C2C1D0437084CB80C5 +:10E0C000FC3D06CF31073CC71CF01CB3C2D3E2E5D0 +:10E0D000EB75FAFDCB65E1F733BF17F5E00978DBA7 +:10E0E000A8438231C6915E096BBC6DD0DB47469573 +:10E0F000061AEDBFD3EF67FBF39E4D3FCC16759D1F +:10E10000D9F525049FFD3D14119D505D8141FF759A +:10E11000F96C133FFA575F617C77ED6117205F312F +:10E12000FE55F0BD4BBCBD56F8B1CB51FF33BD7DA4 +:10E1300015C4C308DF3B2093BDFC0EBC109E6E913E +:10E140008B77C86EA1C7D9865AF9176251F4ABD53F +:10E1500060679F1226349874269DA47D8B01F9DD9B +:10E16000414E6F49F0B6917DD1C5F5A3E9F77DBD6C +:10E17000DBAEAFAFD96EAF5F0D8BC7207D5D7DA7E6 +:10E180000B526CDC6BADF607DB9F6FC91AC1770DC4 +:10E1900034776A41B2B31A711DCB3550D14F5BF958 +:10E1A000B37B662E63EBD921F4E85B4CAEEB16BD76 +:10E1B000715D24E536CA87AF6FBD145BF42569E451 +:10E1C000F56D70F52D42FB20B9D5457E1D38FDB5A6 +:10E1D000BD0AF96B967E04EF955DF6F59D6AFDCE5E +:10E1E000F5328F85D67BDDAE65A437475A8F7B9796 +:10E1F00064A432E8B7874D7D28E48B49DF265F278A +:10E200006B80DB7BBFF7A5D6B3F97E83F291F6BFB7 +:10E21000F96C1E47699E85E5A9FAFDDBE7ECF7EF8F +:10E220009FB3DF6B428E3BFBADF4F6BB713F57AB48 +:10E23000C93A491EB2A3BDAE66A390A1C2B5AF3A1A +:10E240008DA698A55DD769B63B2C959C56BB3A79AF +:10E2500094F18E0B3BE3A93DF7B9FB91FF76BFBA72 +:10E2600008F5FB37FE49012F5BD7F13D2148237D9F +:10E27000AA2937DA2BD731BA4A513D3DF3628B5D7B +:10E28000C52896C6FFC64321B20FAE7BC493AA67CA +:10E29000FDAFFBE97F4C038687E3EB06FEA510E9A3 +:10E2A00075B7C4FDBF64FFB48BD9F3EB54B8229E9D +:10E2B000814E6485F3CBDB3F0F34A2DD27EDDA7F9F +:10E2C000398DDBFB5517CA65B3DD47B28BE665EDCB +:10E2D0000C7C9F7C504A4D92387C0D5387FBDD6F40 +:10E2E0003F2871F8F6B9523E846F578F3BC1DAADC3 +:10E2F000DEF52ED1ED790FFD388C7858BD4FB1F990 +:10E30000BBAB772969CF342A5FC51235A3C4F86D3A +:10E3100095E0D7557B57921E58D5BBF95DE4D7D50C +:10E32000FB5C36B9CEF0124B235E5F5262F5587F2C +:10E33000F487619DA1EAADE8EEB0564EE32E73334B +:10E34000BABA68B6BD1F8EFF61CEF0F1000628AEE6 +:10E35000B9BA77239F0FB8BE31F9F42DFC4BFE708C +:10E36000BD3145B19F3B9C806767521C72576E461A +:10E370003FCED41726BF7EE3C7277626D9BC6F3F92 +:10E38000F2879D4906FF8AFF797FE7B7D9BAE0494E +:10E390009F867268F5EEDF84C182F75A85FB61C7FC +:10E3A0001FFCE1033B18BF1CFFAD87ECBAE34FFC39 +:10E3B000D7789DADFBF8C31F8D41BB73ED13E78F7D +:10E3C00045FA5AFBD879636114FF01E935E5B1EEEE +:10E3D0006B8AF655DF27611006E071513AF6E7E0E7 +:10E3E0005E258DA1DB775EF6A43C0C3FABD9B396DE +:10E3F0004ADCAF95A487B07E33C3F3AA3D1BDE553C +:10E40000A665C277B2508E62C9D8268AFB7DF145D7 +:10E41000E75461E98AE9481F3040F2DFD96FF5110E +:10E42000B6AF678FBC8F27E01337E27FF59E8D7CF8 +:10E430005EC73EBE837F999341FF0FDBC715DFDFC9 +:10E44000812FF7E6D2BE8FB48F2B1FBB6454FFCC55 +:10E450009407A7C26F93C4E13A5B31D628C8578F9F +:10E46000FCE8811D11BEBFF50C21C77F7C623C0614 +:10E4700097DF700D5C8E7272E0098F762FEB73DD83 +:10E48000132F119F1D7FEC79B74E72128212D37B2E +:10E49000C761F04F1FEAC15512AFACFE4128ED092C +:10E4A0000FEDD3AA54439D1EA6E7AFD2F314A7FFE6 +:10E4B00055A9FD4BA40CFBB65B29E1723995477851 +:10E4C00059A9F7B9B5A07D3FA5D9B88FAF2E40BAED +:10E4D0001B691FCDF56BB8FE5996FDFC01E7DB917A +:10E4E000F8F3788F4795B286F6F7B8B00F56A7A421 +:10E4F000972003DF02ACE3F08E70FE68964E7AF848 +:10E5000081831ECCFEE6BA4FC5D7A75ECF67C3D7BF +:10E510009D8A6EA31B136F6F7F9259DEA7859C584F +:10E5200005C9BA8289C3F5950AF16461F110BC9DF1 +:10E53000BD0AC9F1B7772964A73BE5C2AA11FCF16E +:10E540005F29DCFE58B56FFF34945F6F1FF8B9A0E8 +:10E55000434EE7ABF6BCEA4E0AF99FB2CA7F1C2FC6 +:10E56000C37EBC2CE05EFD78E6F156EF7937E378A8 +:10E570006FA9C65711FEB7FA5C906443BCD5AB6473 +:10E580008C6F1C505CB6386E6768E6CB5918DF0C90 +:10E59000FB755CF7FA75C64B49B4435E7001D981CF +:10E5A0006AEC0D0F7BBF3EE4A773EFF5E1AB41B71B +:10E5B000E8E976079ED4689CFC603512AFE2B1D7DB +:10E5C00094CD1F7569B20D6E509345184FF955F1F2 +:10E5D0007FA938EE7368FF9D31D4FE39153A72D9A0 +:10E5E00078CF1952AC0D32C4A71CE3C7E729A05B52 +:10E5F000E9CC2893ADF1D5F0819B282ED102CD69CD +:10E600008C134111F4DE6F19F7EE560DD26C7EA813 +:10E610002B93ADF1554F73B3E1617014ADD54AD072 +:10E62000341B69FE71CDB23DAE2DE65F23E209B029 +:10E630006BF7EEDD6CDC3A7C57827E0C8F573177BE +:10E640008AEC98F3841CFC6761071F90E287D0CFA7 +:10E6500032F46D2ACA39A9749B8AF6C4C24FBAD55E +:10E66000E5167A5C58DA5684F472F853A531135DD6 +:10E670002D51395DB5156F28C2FE877D371671277C +:10E68000344AEB2C10EB3C34EE9A603F1B777FF161 +:10E69000355B2633B8EAA20A60BCA52EB26C4B05E6 +:10E6A0005B7FC11125E663F582A6A49A983A7C9E09 +:10E6B0009D28EF19FEEE453C32F87FD01AA5FA03EB +:10E6C000AD3A95BB5ACBA8DCDD1AA3F77B5A67534A +:10E6D000BDB7B58ECA475AE3F43CFC2D7F02E977FB +:10E6E0006F6B233DFF696B82CA1A95F3DB42810F82 +:10E6F000CBBAE91C6C497B781DC6514CFC39F15DE5 +:10E70000CB282E87CE0D241DF13D56E572C589D745 +:10E71000969620D9A53B25B0E173A6CAEDC8B8806E +:10E72000E3903771A1CACAF7EA4ACBC9EE81780CE7 +:10E73000E5F44E297E5B05E397A7C6CD8A5AE56EC0 +:10E74000249888AB7943F5F15D3C3E334BE5F2A963 +:10E750000EDA0E6531F88C4F40473A33D779A05A1C +:10E760002F42B978A08DC1538EEF6528B3D0993967 +:10E77000DE5C011F0433CBE921BAE5FC1F9D5BB6CB +:10E780000DE3C4CCF18C4DD2C9EAB6F5DBA69A7183 +:10E790006F9DE8D8A413C63F4F8D8BD030DC5F6CE3 +:10E7A0002AE6EF7D9CCE5BFADFA5F856740CD8E222 +:10E7B0008D1D4D32F9393B8EF2B8F489A6926D93D6 +:10E7C00059FB6A8637F4DB73169666252C74BD45B3 +:10E7D000D0D30E6F3C4B1B457F758A7666FD155F67 +:10E7E000E23B88E7BF9FF0937CA4E71DAED4652889 +:10E7F0001F5B8E7AF475129E37C493B86FF122F6C0 +:10E800009C8174A26EAD879616E4E70F2D37EBDB83 +:10E81000CEB0F0792866E7EB9D2DA3C7A54DB8775C +:10E8200022DCA3C4654DB8CDFD3851B764E01A1899 +:10E830008E07E7B8390B978C3AFFDDC8771EC2C345 +:10E840004ED5229F8A9A353A6730FB9BEB75F67757 +:10E85000AE77285FE1F4CE677A5D908BFBF9F0C765 +:10E86000E31F7D0E70CBE30ACAB12BD4442FEECB4D +:10E870004C68A63AA803F9C82FBFF373FADFD1F9A1 +:10E88000403EF1919A2A46BD70BAF375403C5E8DC8 +:10E890007A2B26C7ACF2DC2C7FA19A718234C58F0B +:10E8A000E888994D29076E8E66C2F3E0F845EADBE9 +:10E8B000D6F3A42D00DC4F4F7BE99C0303221AAB57 +:10E8C000171F86CA4D6CBCDD429E54ABDC2F9C7E6C +:10E8D00058EF5178FC48690859F028E2A9661CAB4A +:10E8E000036E068D7575AB15FBB1B9C9870DEEC406 +:10E8F0008B882F7754A7F3775724417C0522FE3D60 +:10E900004EC4E9CF1771C6FB5B789CB105E2179E38 +:10E91000817C7D4401F28F13136DFCEB5CE77E413B +:10E9200057FF24F4DFCF85DC2E55F74B596CFCD014 +:10E930001BE9036156FE4CC8F1C7841C3FB0ED5F74 +:10E940008A319FA023E18E214EC355FEB4C4ECD082 +:10E950005B67BEA15FCBDA77744F6E47FC6C58CB18 +:10E96000E3F28FA2DC67FD1E16723FDCDC793D9D71 +:10E97000DB09F95264E60B08795224E4C9C16D2F12 +:10E980002EDB80EB4B78699E16483F8D717D582BAE +:10E99000939D12EEFDDE0D38CE43AD061FB77BF71B +:10E9A000DFA17D7F8F375DF9AF18FF9FE78E25517F +:10E9B0004EA526D9E454B877DF8DD82EDCFBCC4D9C +:10E9C000940F23F0E0799CAD9735C9BAFD703AC435 +:10E9D000DA15F6A7D1EC66FBDAB3700A1BAFB45EAA +:10E9E000A670F51E297E5E08E9A1819F4367552C1C +:10E9F00069C3F6DD2B5E4862FF31CF364BB8ED3987 +:10EA00007F776F35E2EFFEA2D79EAE66E5645731A1 +:10EA1000D141F0A89EFF43C0F1E3D16BF591E9F03D +:10EA2000E08A358072CC73A74CE7F4F7DFB906AE05 +:10EA3000B1E65DAC5033C6C726BB3CFC3CEBCEC553 +:10EA40007D2867CDF3ABC295B55EE2FF67C1763E28 +:10EA50006B9E6399FD2BA4C464571E9D57F0732DC4 +:10EA6000D1BF40411B8F556F90391FC4D33E6BBE41 +:10EA700049F07A399E099E592E95E0698FD5EEFAB4 +:10EA800017369F3AEB52D2CBD06D87C3D98FC131A5 +:10EA90008BC3C1E133E118C74C82209BFFF6852F61 +:10EAA000E6237C1FD60DEA1B3FFAFF1DDF95D3132B +:10EAB000D8FE6C6D97E9FCFE40D5012FE2714B55F5 +:10EAC0008D9FDB3F9CEE72041FFDA04E26BE3D5184 +:10EAD000C5CFFBE19393741EE612EF73F20E78E953 +:10EAE0000C236904AB6762FA81F9C7925FC0705367 +:10EAF00099F4DBE4A7DC9263CB371807058EBC954D +:10EB000092A1F6E87FD71D91502F85C47974A97919 +:10EB1000BEAD1C8DE1FAEF32F562AB97CA9EE603FB +:10EB20003E9DC1F58B664627B42E7B5E8AA7096899 +:10EB30005D05CDFC9C6D8BD6B7DFCDEA45DF65A8C2 +:10EB4000D7D19EEB25F902DD3C5FC03CEF98B4C203 +:10EB50009EB752E4C8B719969FF519FDCCEB5DF648 +:10EB60007CC313B0650AD1435F896D5F7AE630B725 +:10EB7000E6ECE1FEE6E0B8C29F82289773393E3E9C +:10EB8000C7ADDF529AD05E0A5F58996D3D1FED7494 +:10EB9000713BE9D0EF3C80F1F80DB55E8AE398E770 +:10EBA000E8E67E6FC5A42BCC77687FC087F4B223DC +:10EBB0005242E5C1B9CFF8FA890E793E8047AC6977 +:10EBC000DDDC67163631BCDE9327938EE9287A2187 +:10EBD0001FCF176FAFF5D2797F38D0DF7B90D58309 +:10EBE0007FEF8EE1F9F6FDD5E946ABFFFA908BDBBE +:10EBF0005BDB5D425F6DB19F3F333ED88E7CE009A9 +:10EC0000C6E9FC52F68ABC09879F63E2237C205F39 +:10EC10002E9ECACB92A943F6F9DD826E760879BFA3 +:10EC200045C87BE738C54DDA0137DAFD2BB44A25F4 +:10EC3000035F4E68B1DB09E39AED7935854D76BA0D +:10EC40000FC50A1C76459AF498A98F37F88213915C +:10EC5000EE2B99BEE4F681265BCFDB9DFA78B76A8E +:10EC6000EC7391BD7B7A764238106F467C3BEDDCCD +:10EC70004302DF1F2BC601C46F408D1F72511E68F7 +:10EC80009CE48CD36E1806273038A78E0AE72F5DD8 +:10EC90009FC17E3AD5F9C09FE4F8F6E718C8F3B3F0 +:10ECA00040E45D84480E7784B8BFD2E1E27EC27B47 +:10ECB000625DFFE15268DC01415FF303D09C399F44 +:10ECC0008CC78B3E40C304DB8DCD9CBF8B160BBD28 +:10ECD0002FCCFCFE03173F679B3F61F479FE88F35E +:10ECE000B0F257AAF1AECB728EF384CB78DF658990 +:10ECF000537CE8D2383F98FB21F2734DFB699F6A41 +:10ED00007C64ED6F96390B553ACF3D01FE98C2F009 +:10ED1000F3643EEC0526479E94043E7FE7A33C2027 +:10ED200013DF83F635CA0FD4034703298CA798FB5A +:10ED3000609EC30CCA11D1FE4C3797278C6E026EB1 +:10ED40009A3FCECF0B214DF2A140D0CD0EDFD2DBCA +:10ED50006A5979EBDCB75EC67C85771EF3E908D784 +:10ED6000D6AA6361ABDC84263BFD98CF5D1F16D22B +:10ED700039FD37A544BEDBE247BA22036EECFFA49F +:10ED8000A4933F97FC8D42F6C893526A0A192A2A27 +:10ED9000D079C693D746539B2CE71D4E3B3FC7D730 +:10EDA0007FD76A5C7713B39760F8BE9976FAA0DDD7 +:10EDB00011B5F78FBB41D8D96CB98CAF2BC4BA63EE +:10EDC000AAA1201C332041E52CD0A964FE40A59BBC +:10EDD000B59F0E03F9C847EB02E3BFC4ED8CFF33C8 +:10EDE000BC197F8D781BA25BBBDE36CF1DF2041EE3 +:10EDF00042D04CE7EFBF685CBE71129BCF5D14241C +:10EE00007B38AFB1FD7A398CD97E7D1AFA9B79E2D5 +:10EE10003C1C9670FD6C9E4FE7D4DBF5B9537F7BAD +:10EE200084BDE11941AF3BE5E6487A7D85DBAED78D +:10EE300007E3C723C83F67FCF8D4F24FBFADB6184D +:10EE4000F3348C976AD1AE9BA752BC333C11AE8889 +:10EE50005BE8E1F76E223A56F2BC994D8C5F53673E +:10EE6000703E07F413024C01E179C2383985F93656 +:10EE70001B92A93ACC3FDBA04ED2ACFB583D8EDBB7 +:10EE8000B35B6BFC4D56BBF60F7E178DFFCD40F587 +:10EE90003348C7E5C1540DB97B067304C7F0BC4BBA +:10EEA000DCB7B334E8C773580F70BDCD38C2CBF5AB +:10EEB0004AADF63AE56726E0646034BD60CFC7DC52 +:10EEC000ADA6D6F9111F111E7F096D97283947E9A4 +:10EED00035D298CB5515587CB79BEBAF329C67FF6A +:10EEE0004C66EEB2F67FDCEF263BA73754A8A23D76 +:10EEF000F9A4BCFCFB68070EFCD603789ED2FBE9A4 +:10EF00009974AFA137F4A5054807BD1230CF96AD6F +:10EF10009FF10F4FFE8100C6EDC3E7198071CB81D1 +:10EF20005F40EC5E36BF2BFA689CF276C108C8B32E +:10EF3000593F1F7461FE4AECCFFEF7CF6574F74866 +:10EF4000B0F28EB361280E60FAFFB5FEC4A3086765 +:10EF5000C7987F6B423EEB62702A6487195184BB6D +:10EF6000324F26FE83BC606A127B5E7D38528BF97D +:10EF700068D56A054A1A0607DFEF577C892710FF14 +:10EF8000B55A436D366B5F7544277B6541F4FA4390 +:10EF9000589F7994D73BDC40F620F22F58F8AFFA0F +:10EFA000C3F1B4BEC3428EB7478D3E431A653F34AA +:10EFB000D5719FC39EC762A5036DA68D0E122E2B21 +:10EFC0001DCC667430D54A0786F459E8E07B42DEF2 +:10EFD0009E9A5F389FDCA870BE194EF7CDDE9CF27A +:10EFE000E1FC61CEBBA92A2782E7AB261F68B36E7E +:10EFF000D6B0EE59E68E23DF997C61F283E21BE402 +:10F000008B8B7C6C7F9704F5F333F105FA7156FA1C +:10F01000BF78043E5904038730E77E910AC92C2645 +:10F02000427E35E78DD2F116BA77E269D13C098E7E +:10F0300059E4D1C993BC6EC1A3369807AD9C3EBEBE +:10F040005F50F58E8885EF3A99FD8C4661971C8359 +:10F05000BC62E4BBE541CF0CBCDFF07094E2FB9EE8 +:10F060007813E5ADCD7A3B7035A3C33F8E91755CC7 +:10F070007C87BEFC21E2DF97038076DBD699D74DF3 +:10F0800040FFE48FD72626609C7323C3FF31326E86 +:10F09000526365CA85EA1FCBCFCBF4282F1351FEEC +:10F0A0001CC4FB94A81BA25D3FB563FB6C9387DB7C +:10F0B000BD5C0E6EF7723B70A3BBDB8BFC3550EC76 +:10F0C000A5F354E7FACFF5707E38D70355B108CDD4 +:10F0D00046F1960EAF52D7C3E350E973D9F37327C5 +:10F0E00096DD6BD58F66BF3B5A53F1D726E17A7612 +:10F0F00051995B9F023C37F09725758CDB7BD7419C +:10F1000022937DB8C3CBE304DE03FF40E74DB9A5EE +:10F1100031F24F23F56C3CCBBE2E6228CC62728656 +:10F120002DCB407AEFD0FD64AF2D8AD4BCA94E1B05 +:10F130004E07F8E798653FBDFFA3247AB91F477EC5 +:10F14000C85AE1F7D59678897F3A5ADC3D184FBB0B +:10F15000CC934DF8FA2052336A9E2DFA5749460F48 +:10F1600029E65F6189E720C933F83908D6F11C0424 +:10F170004B3C07C112CF41F03D9E8360FD27AD0699 +:10F18000D5F13C04EB781E82753C07C13A9E836042 +:10F19000B9AFB589CA7F6C6DA6F78FB7B6509DED34 +:10F1A00013D9E350968C2E6678EEBAC96DE0F976E5 +:10F1B000B7D88F8346492EEEA32FC2FD53DFB3B7D6 +:10F1C00003AEC717E571A5CEE8ED70252BBB6684AD +:10F1D000BA30E0E57D2848A54FBD0330BEB0534AA4 +:10F1E000366124EFC60DFBCE53991E2F8D5E5F93C3 +:10F1F000C3EAB76C78723DE6F74CD6DB62CBB5A1BB +:10F20000BA1EAABCEE614B7D42798FEA67EDD779D1 +:10F21000F6AF477E4638D0C8DBB2E1E0796DA58C09 +:10F22000984A80EE790C14BB53488F57E17E4D42CB +:10F23000F8B9FDFF65581F457F7A82EEAE443E6205 +:10F24000EDD39C7E4FAF7D371E66CD18DE6FB47652 +:10F2500072D569B5036594F1F0BD34CA381DB05E4E +:10F26000C33B679B91E731EFC817207FAECBC5F951 +:10F27000B7CBC7CBFF167C7BC85B13F7B232EEE58A +:10F28000FBDAE58BD7613C7460AA4C71855E171B75 +:10F290000293775B8A7F5DC2E6FDE6332A607CFAE3 +:10F2A000871ECEFF932684B85EFDB697F4EA051359 +:10F2B0007EDC9EC3EA93EE8BC5504F6E86981FE9A5 +:10F2C00024B985F3FB8FAA26E634B0E667CD782C07 +:10F2D00007E30DAA802385F79258BDADE3EA09182C +:10F2E0000FF9E3F35C7EFD54CCD3E3EA6BA6FD9CFF +:10F2F0001124FB82618CEC87B6A84AE7F7723E2F97 +:10F30000DD2EED6FB09D9B29E82483C7FDE92C2FEE +:10F31000F9E91F7AC47DB63EB22BDCBE8496CD9E41 +:10F32000772765E2F7F59A3F8529FB9B839574BFA4 +:10F330003659AE527EF6E6721EC70B842E4DA13DA5 +:10F3400071DB7E1F970F412FE569A5CAF71EAE89B5 +:10F3500060296BC8EF2963711DE15D9335CAF762BF +:10F360007FA3F74D11CAE7DE0C625F9A64F2173B88 +:10F37000C6FCF95FCFC673F1AF6B3171C788F22558 +:10F38000C90492F1BEEFC08100C2F3B7E6FDA4FE4E +:10F390007501D6BE7DB916C37D98A6D5D4611CB1C2 +:10F3A00043ABF1225F05A6D67A97911C1ACC67A6CB +:10F3B0007B70EDE5DCAEC5F7C897D00E87F0DE4B6D +:10F3C000A1906581EC4A09EDA18E7A0A2F61BEAF4A +:10F3D0002D3FB33DE742CA7F5716E5109C1D60786C +:10F3E000B17DB25E25FD5518F4A6D1DE2B34E38B3A +:10F3F000989A6CF1377257D8F39BF39B54DBFD8FCF +:10F40000B1097B3D4FF80F798E3C68C96B9E23DABA +:10F41000F1E45C6F6EE4DE6C8437172F34EBC3D7F6 +:10F420007347A4B201D759A8F909EEA8B6AE1AE5F8 +:10F43000D758686E43BAFBCCF03AE09C56DEDE87C4 +:10F44000FB3E4D57E9BEC3D930B00EC7DD2CE8BC3A +:10F45000ABD8AE4F7FE851C43970CD1CE4478C87E0 +:10F46000252DF31727FD90B4CC37B12BC7569FD469 +:10F470005D606B7FC6F612DBFB29A9336DEFCFDA37 +:10F480005569AB4FED9D6B6B7FF6BE1A5BBD227D60 +:10F49000A1ADFDF4C38B6DF5197D7F636B3FEBE58B +:10F4A000E5B6F773FAAFB3BDFFD21B6B6CF573060D +:10F4B000BE656B6FDAD74EBD38DDFBF9EC6A0FDE47 +:10F4C00007B3C50FED76BBD3EEF6FECF7A7D1DCA2E +:10F4D000B5B09BE85B453DCEEA6B6EE27E8F777EF2 +:10F4E0004C47B93245D063246818B86FD5612FE90D +:10F4F0000335C8DBA9C10564778CDFCEE4D174B4D1 +:10F500001661F07D00E5726B325EEA1A82DBA77548 +:10F51000D3DD86EA701DC5DFCDFEAA66402284F3E6 +:10F52000E93CFF887995D8CEA7B3FE96753C29CBE8 +:10F5300074157C80F967F75AFCB391FC31A7FF750D +:10F54000BAFED67819FC58F648F1662CCB9B9FAFD3 +:10F55000C1343CE6875DE565FBB3D51D6FEA61E329 +:10F560006E2DF1F3F332E1877515F7125F0C14ABD2 +:10F57000A45F40D5CB175BE260B709BB32E0BD8B1F +:10F58000FC40B564F6611DF1DEA6527C62B3C4E3B3 +:10F590002849B60FA8D776CE7DE3DD5BD8736F8997 +:10F5A000B7D0CBE451ECA0DBC073D23B045E4BB4CC +:10F5B0008A1A667131FBA2E1009693756667B0B254 +:10F5C000AC6CDB012CDBBC2534DF99B1876B50962A +:10F5D00078E773FB4F99E64EADC3FDD3381C23D1BA +:10F5E000999AB39D9F6795AAAF23BDA1557E521EE0 +:10F5F000A2031FD2814425D18F2F1224BDE1C30362 +:10F600001FACAB522AC0DE474A0D09F333AAC3DB55 +:10F61000E97CCE97B6DBABCC2FBD0DF11AA9B7EFC5 +:10F6200077C0BB93E06B97789CB62B5B7FB686C1A7 +:10F63000DF9557928331168C633458E4CD76A14F11 +:10F64000AFF0C9A6FE2779E343DEC81BB27718FDE9 +:10F650006F9727227CDD8072CB77733720BDFB3418 +:10F66000B69B686F7F2749F46FDABB3708DEAA2D97 +:10F6700069A473B1F7239564DFFA5A7E92117FBEB5 +:10F680007E058CE923E3353C7907E97B2871EB683B +:10F6900057B4E86EA327D339A047F81F981F82F00C +:10F6A00088FC902E810FF35CEE7D336F4A9C07DF60 +:10F6B000900DB6F3C11BF22AC78E668FFB987F9818 +:10F6C000B0C0BB91CD8378E9F8A4A12E4EE784C0E9 +:10F6D000EFB37D5ADE43F7863F59AFE339E62C811D +:10F6E000EF733D1CBFE3DD407EC27918E7988E5E64 +:10F6F000E997EB902FCDB8C89BDE1CC27F2C094A3E +:10F7000033D92B2E536FC927CF269875B719CF241D +:10F710009397EB35F6EF7EBC7F31B1CB7EAF69526C +:10F72000B7BD7EC6767B7D4ACA5E6756F311B40BC1 +:10F730001A80E3E7AC5DF6F70D663CB096DFC7F0E4 +:10F74000B2994F72FD6BBBFF0A42FF9B71D771BD2F +:10F75000E96A14AF456BED7AB540E8F90287FEAC73 +:10F760000C29140FA83E1C3984F6A319A779C5A744 +:10F77000DBE29F66BCC529CFFD47B7017B437E75A1 +:10F78000C2C3E31009E6DFB41489F8C6385EBA14C0 +:10F79000FDB9A564A7359F81F2E99037F1B197E2F1 +:10F7A000CEF6FB12EFD5A9BF90743E4FC232CF8D7B +:10F7B00065C90BF8F253947F62C63B4C7F5E091A11 +:10F7C000711C6F73EC85E683186FFAAD07709CF3BC +:10F7D00095670FB7B2FA9A712AE54B6AB3567CDF88 +:10F7E0008FF1427CCFEAD5C5FA58A2FFA75DE4D7D6 +:10F7F0006F10F46CDEE331E323519FD03F3ED32EF4 +:10F800004AFA453EAC1FEDDCB37631D96CD3733C7C +:10F81000EE66C6D7A6F6DADFF78294ABB1FD3BBB46 +:10F82000312573BBCA08565BE2EF678AFD9AB6348E +:10F830007DFB5256DF03A94AFCAE4485A08BD8213C +:10F84000FBBDB13120D1FD82314794588AB59FF676 +:10F85000B8FD7DB9E35ED999CE7B668E787048811C +:10F860007797B1F9B6E8CD12CACF2D4B99CCC2F932 +:10F870007D22CF78324C46FA3B5F09C6D288DFDF63 +:10F8800028A4373CAF9EF1D232D4E7CFF33C166DBB +:10F89000A2BEAD96D5B57F55483F6901A8A8080E10 +:10F8A000C58FBF773206EDAEA178D46EB6AFA59303 +:10F8B000D0BFF602EA959FB0FDC57A2FF3C7B1FE1F +:10F8C00008F3C7B1DCCBFC717CFE53E68F637D1F70 +:10F8D000F3C7B1FC47E68FE3F3C7993F8EF56F0698 +:10F8E000AA1738E359D6F8DE503CAB5F32E359280B +:10F8F0004A3E70EBB4EF8371AD048F6B9D7A1CC3ED +:10F900001C87E286C3C611F1C3776EFAB707F09E73 +:10F91000F5CA19EBBAF0BEACD765C6CF789E84990C +:10F92000FF6CF2DFCABDD7D3B9B13BFF4833EEC796 +:10F93000DEAA207D8BC8ED4A68281F9DFE97E977D7 +:10F9400039ED5FB374EA233FDA01D3D14EEAA6B8AA +:10F95000CF261794D1FD59C91F43BE70C62B4D3E0B +:10F960007ED15792F1BED4601EAD88CF7820E5C518 +:10F97000B89A5B12EB14799E24C2D8109B919F2DEC +:10F9800079C9C1F234C539824183EC2F89D96564C4 +:10F99000A7698928C6A13A47C89BBD4FF0675BBEDF +:10F9A0009BBE37D199CFF3046A8B6251ECBF3E7F87 +:10F9B00066D49A476BE6F91E0ACDF4F65BC65B1374 +:10F9C0002A19554F294CAFEAA3E855C5C3F3DCD734 +:10F9D0001F98E3C5FCE54DC1E57D685F6D8A46E88B +:10F9E0009EFBFEFC99647F0CB68FCEA63C6725C8B3 +:10F9F000ED5625EA25BB55C5F5970FB537DBB5FAAA +:10FA0000385D31F6A3F85C20D84BED3C6A9CE21FD0 +:10FA10009E08D0B996C7CBF30A82CCBFF6DAE2AB28 +:10FA20007CDE1611F7DDA427E2D86F5354D5511CA4 +:10FA30006D2AAB243CAF17785E9F67EAFD18D91B8F +:10FA40003F137836C7592FFCF5F54D6EB2BBE22D4A +:10FA5000D9466D2EE56DEEF1E1F8C17BBD9807EF5B +:10FA6000CEAF1A75DC0338EE8CD1C67DB5A6763ADA +:10FA70008DFB331CD71D5AAEE1B8AE11F2F39F13C4 +:10FA8000707E5EFB92614EA3733130F56D2A6A3D44 +:10FA90004F76967EB413A70FEFB752EF5F80F9C190 +:10FAA0002A24EBFCCAF0FB0DABF6F1EF556D55FBCC +:10FAB000C8DED9FA8994F19EC418BF24CE6B07FD25 +:10FAC000709BBD5228F8A950BCD7D15E2946BFD241 +:10FAD0006E5F4C3F6CAFCFE8B3D767BDECB4578CCB +:10FAE000DFA0BDB244C8BB3E269F7972C5808A7232 +:10FAF000209E4C5523DC0DD0DB86E7992E85E7113F +:10FB00002C11FAEA22A1CF82FE6C82BFB0C96FF33A +:10FB100013CDEF6E1489F1C7D51EBABE1D856BDCFF +:10FB2000B47F74F22FC72D7CA49AC4A4C30E6A308C +:10FB3000ECF7562F72D8394E7BA85AEDA1BCCC02F7 +:10FB400047FCC13CCFC475E2FD5DE7FC9F755E7369 +:10FB5000BC1D4C6FA1BD627ECF80BEF7C5FA8F532E +:10FB6000D3522C48795E940F58B8168C9E0C747C36 +:10FB70008ED8F761784B9E4B783B4F3C2B08F2EFC9 +:10FB8000A514D42A29BD98E789A13C59BC82AD8728 +:10FB9000ECE593745E6DB6CFC9EEA5BCB21DF5124F +:10FBA000F71F93407688B9CF3B82FC9E4DC33952F4 +:10FBB0004AC6FECD25343FC15532B4BF0C4FC738BD +:10FBC0009E781EDAC575F6FB400D0E7BC3A4878BAD +:10FBD0001CCFFB7DDC2F32F9E09D392F4F1ECFE08B +:10FBE000582925EB02CAE9EB490B7FB84E221FE2E8 +:10FBF000DFC7D052883F0E781FD5288F20BBFF2E3D +:10FC00006024D9E08764ED3C807FF60F9C25B17AB3 +:10FC1000E3A6B33BBAC6E1B5C6811FA151E6D950F0 +:10FC2000757EDD394375FF2683EA11310F732D92FE +:10FC30007CBF2DDF3760F0EEC43C02B44B0DD8A67C +:10FC4000600EA6AC6D8B150FF5CBC17ED228FDE200 +:10FC5000B04DCDD02F68F663E8EA34BF0752822555 +:10FC60007F2F0B78ACF3AB88374D0FD27D9F05AA61 +:10FC700086E73F5F148E31A75A7702B6B9260EEF9A +:10FC8000C7C06E33E19733C39FC2F7D6F95DA3C0F7 +:10FC9000FF97C6C7A9C6738BF79F193ED67CDD9820 +:10FCA00091D78B70B9E8BB1A7A50B68C73DBFE8F94 +:10FCB000287EAD5E06749F4775195A8CD179B97646 +:10FCC00027F9E16A76AD8676C04656473B60636F9A +:10FCD00037C5A9CB4B6FEF42A22F4FFB01E5C154B3 +:10FCE000D0B2F7B071A76A2A66EC807ACE2119E308 +:10FCF000DEF015A0FB2459FBFDFCFB17C573EF4399 +:10FD0000FF283BDB4B71A040F6CCFBB8B1CBE3C185 +:10FD100026FC81EA23351827571B2086ACA84A29E0 +:10FD2000A846269B02740EE137F6DE88F73299E288 +:10FD300023FD44DF8440BD2AE2E26339C940975B7A +:10FD40006B403F21F98C4AF1F7B17864C188B2BCAD +:10FD50003C671BC2539E600348083F8F6B4D4DC8E4 +:10FD6000B1341BBFF25DDE0F7EC9EF11305FA2F12F +:10FD7000B1E0105E4DB93256C4CBA34BEDF164181F +:10FD8000606B66FD2B7FB9F87E8C278C1926BFB976 +:10FD90007F6D7E6F27EB5D883F46E79A76BDE11762 +:10FDA000DFB5F03BBE97303968BFBF37CC6FF84E38 +:10FDB0009CF48007625E37D9174BC96E30FD911DE8 +:10FDC000D810E3FFE3807FFFCAD97F26EF0F51EE03 +:10FDD0009F78FCCCCCAB64EFAFF31B9417E4617558 +:10FDE0008647C90DDE7CF6BC40E67191360954ACFD +:10FDF0000FCD97A6F3FC0D52AC2B260DF9BFEBB53A +:10FE000018E519C0DA1C9BBD6CE6ABAEB9B6786CD0 +:10FE10000E2BB386EE0D69488F6BF24AC97E0EE752 +:10FE2000F67F0DE5EB47FE5BCFF7A23CC53C87B9FB +:10FE30004C286FEEEA483279EBF9B010748B5DE62E +:10FE4000519B290EE6F970BCED79BAD57ECFD0086A +:10FE5000CAB5384F514027BC5683D68EFDAAC17E05 +:10FE60009FD0F361BECD4E1F1ABFC8F63CCDEC1932 +:10FE7000EB772C461E3F007A9975FC89238C3FD97D +:10FE800031BE9671FCA171736DE376A83C3E9A8CED +:10FE9000F869DF9DF64055A0A63890374AFC3EC071 +:10FEA000E3F71BA2CD14BFAF01C6F08C4ECEFDE42C +:10FEB00098C2EFBD01D96D50648FDFD708FA95194C +:10FEC0004520FD9EABDABF1F361F9CDF13B3DB431B +:10FED0002F21A3B079E550551FC5F13F0AEAE87F0D +:10FEE0008D642FF7B502C58FE707FA6FC073EAFA82 +:10FEF000C0F75D1DB3459E6C01C0DF04F69E8FF711 +:10FF000003FBC4BDBE8E884C7889D78CA57B3AE6AE +:10FF10003871374C42791897797E02FD61F3F7E525 +:10FF200015D8F21CCCD2790FB4C190E2A516BAE96B +:10FF300093195EADF39D57D8A358D611F7C00C9A0C +:10FF40004FD8B983F38DF97CF33D2FE24EE67C0D5B +:10FF50000BECEB6B706BB4BE06C1BFE67CCFE3FA73 +:10FF600032E0F794F3C99C6E06E7BBC0BEBE068FB5 +:10FF700046EB6B10DF031E9C6FCCE79B6F83AB39A6 +:10FF80008176DB3689F3FF77373FDE81FBFA7EFD32 +:10FF90009A28E90361175F841D58BB8B543EDFA28A +:10FFA000226FAACD32DF0E26070C910F6F78307FBB +:10FFB00043A37AAA354AE5BDCCCE36287FA38CDE92 +:10FFC0003FD01AA3FAAED6D9549AE394CDE6DFA770 +:10FFD00099324FCA686FFF32C0FDC66DF9DA6557B6 +:10FFE000A15EAAF6F37B93B3BF0486C5FE6506F156 +:10FFF000011F9EBF5C0A15A8DB266FE770476AC722 +:020000021000EC +:10000000A470FFFC1587FA5A59DDE372E9A84F196D +:100010002FC433F9A98703DC0FF7B8B9BC87B9FC43 +:100020007B878B845E01A55E72213E2ECAA6F3FEFD +:10003000C54B8C90C6F0B644927E532AF414DE6F02 +:10004000B9446C95D3CE8FA0C660E3460C2585DFFE +:1000500031BAA4E87023EAE578E862F20FE2AC6313 +:100060000E1BE712A127AB5FF500E63BC0F96E82DD +:1000700063C912BB3DBFCD97D6D03ED9561101DC26 +:100080009FC5F5F6F71E37E7C3B8E3FB068B4EF1C5 +:10009000BD03FAE656867C53677CF24040E4AB8AA7 +:1000A00038E40928BFAD165F164546FDDEC14D0197 +:1000B0002E9F4CFD369C8E393C7F10726C47EB3E78 +:1000C0008A8799F015A82909E57561D33E5B5E130F +:1000D000432C19C3661C1E943D15E88738D7B343DB +:1000E000DA933FDAF74D0A407DBDBF4C7CFF531ACF +:1000F000BEEE5703F6F8EB0998F75C2964E21F1E81 +:10010000775D745889B5E9437831F1F0FFCD475BED +:100110001166563E77DE0755DC7F2BB27D67D3FC38 +:100120007EF0C5837515540B3D5F749D9BEC1930B3 +:1001300006CA91EE8E9C13E0DF7B33ED97F46F657A +:10014000B45FBEF8F8C6385B7EA71877A4FD72E6E8 +:100150001B5AEE8B0EE5C3637E89C4CFB10A30CF44 +:100160002DCC9F1FB3DB99B63CB7F5FB1F9430CE67 +:100170007717E6E359CEAD0B993F8FF1AEA215F696 +:10018000BC3A275C665ED5E07DDB794BB43D3A7DB9 +:100190005FB11B3F58D3B53D19074B1EA5798FD0D2 +:1001A000F4A79DF7079520FFCE5E54DCCB70C68385 +:1001B0006F94935AB18479AB296F352BA7E72466E6 +:1001C000E195F61B95641D3E57C6CE6D423C2C6DE5 +:1001D000F9760CE3775A6EE6B8F452A1BF6B829CB5 +:1001E0006E8EBAD2E3308E7D4D4E4D4D302F43FB97 +:1001F00096EFD078F347F86EFDD7823C6E7297D0B9 +:10020000E7CEF74BC4FBAFAE94E93B183E08A5A47C +:10021000623C37EE9E4DF7F656ED8865BA1FF75CE7 +:100220003871B1151E5F29BFA70DD03B07F1B5F19D +:10023000E3BB7B1F62A8CCF93848723447E1E35A2C +:10024000FA7F2D386378FF273F7A91EE373F89F7A1 +:1002500059E6E2F6DDB300E3DF5BCD3A86E4B19E1A +:100260006DD6BFCDDF0FD6672CA866FDB7220D3245 +:1002700022FBFD960B3A51CF6E95407C87BC6E01F8 +:10028000FA875B5DBCFD3F89F7F32F7CFBBEDB503B +:10029000DECF74931FB855D823267CFD417E1FA95D +:1002A000FF14F8BC45EC5B10F119F94CF8BC2513B0 +:1002B0003EFB738CEF209E7C9849C140F07DEC5D45 +:1002C0008BF9C6FFD00AB1ABD81AEE8AED7DF036B5 +:1002D000A0FE1D99F019CF313AF17970E5315A5FDE +:1002E000A83488EE0D6C9C05344E06386E1D6D5F8B +:1002F0009FCAE272EC93102F7384FDA778FAA2785C +:10030000FEAF557DEF068DC991CEE2EEC64CF47D71 +:100310007788DBE5D923C4AB1F15F8FDBD16DF894F +:1003200070B76BB7D37758DD12B71B36CEEE07C95F +:10033000D2EF85106FCFE07E00E176CFE1DF470D91 +:1003400031BC638259A88AC3BF513F0298FF1D8AFE +:100350001EA1BCD050553FF13B5D6928E07485FE7D +:100360009A57D8678F6E59BA00E54C8E62D2E1F188 +:100370004EA41B65A84E74D493C3FBBFBCF578276D +:10038000FA733B99FD82DFEB4816F0BC11E7FA9E49 +:1003900014F0DE13367E8EEB1B864F4FFF7DB7B118 +:1003A000FE5B27F17B39F3E5BEC62B912E2F0C9215 +:1003B000FDC59E375ABF93F307416F7F0872FB69F3 +:1003C000EB475E7AEFDC8F91E8F5D702DF9F835E23 +:1003D0007F9D89DE18BD1E71D0EB0790995E5FC9C5 +:1003E00044678C5E8F66C28BB3AE80B11DCF67D57C +:1003F0003F2FD885E3A95F9EB7FD21562A7FBE39DE +:1004000049BB19936CF750CD792AA4C45B418B7C0E +:1004100037BFE34D391099C69D35733BCAB1D31828 +:10042000F704C2ED1CF7208E3B03E54B3091E9FB4E +:1004300046DF0FF1BCF107C5BA46E29BE74EC13774 +:100440003F0D713A607CE30A9D06DFBC2EDAB37D76 +:1004500008854E8B6FEEA4D257CAF986AE2BCF1DFE +:10046000CE3700AF74A23CEE2CE67C313EF44667FA +:10047000B2C8C247F011BD5786EA24BF4D3E7A3B51 +:10048000F411F191B37F7884EF594D1A5C47BC1495 +:10049000D76D9CA5B5F3FB38FDA4B77B6060BF8723 +:1004A000F26C795EAB3F9934B8D9D007F87DC4A916 +:1004B000821F77A20F867ECE4C116752FB60716857 +:1004C000383F87AAD255D6EF0D1C12F37F1A8A57F0 +:1004D000E1FC3DD03F05EDAF91F6698E98EF7BD9F9 +:1004E000C69C50063A3F951EBA3CC4F3372F17F30B +:1004F000E67CEC6D46FBD3C9EFF357FDE39B0F8C15 +:1005000032CED744FF8B439F9BFF2F0E65E6FF251E +:10051000213BFF57E1773A33F0FFD74299F97F69E2 +:1005200026BC7C017E6F0A65E0CBEAD3C4F78F045A +:10053000BE7FF405F1BD51F46FFBFCF86E1B01DFCB +:10054000EB108FA781EF8D23E07B5388EC95470854 +:10055000FE901EA43876D72CD82B956484E376EBD6 +:10056000385E9D8FC3F0FE81C4E87EFE9FBB62991A +:10057000BE4FC3FAFD83157EB3DF9C90B8270DFAFA +:10058000F5E89FDFF5E520C5FB997EBC27F497953C +:10059000FB0F8632C8FDF93297431F6FD9DB89FA0A +:1005A000FE0B8CFF58263A5B2DE03E955D7058D0CF +:1005B000075BF7E3A1BCE1F2AF47FC9ECA3DE1C493 +:1005C000C110F957FD0B515EEDFC568E84F1A82247 +:1005D000232DA19FF073A1C72A433ABFCF20FAED84 +:1005E00054D312E6B3EC6CD624BC6F6419EF97A118 +:1005F00019238FE78483C1D7172279673C8FFDE6E3 +:100600000CD9819FC94E6ACC367E1B22BB2DFE0AB7 +:10061000C9ED33EC72DB5C871CEFA6BC17DFECCCBA +:10062000BFF7F2F3A02AECBFF86B56F97F34A409A8 +:100630003F948FF759F50F83EF9D10D72BFF8DA5B2 +:10064000133E275E4E056711EA793EDE4799F49422 +:10065000733CD36F35F7C98D3AC912D7718707ED4F +:100660005E5718E549874CF790160979B26876B657 +:10067000B0DB353F8E7F978893DFB5E2F66A3CEFBB +:10068000EEB959AB4014143471BDA7AF184FF14FF8 +:100690002D2CD9CE93CD72B0BFBB770A7E9F9CCD57 +:1006A0001BC179CF9D0769F41BB3D06EA078844637 +:1006B000BFF795E3E98E62FC74A3D4DDB81CF5EABC +:1006C000C220BF57125D728AEFBCF1F893B96E88F1 +:1006D000569DA27D1BB5D702DDF49D8CD36EEFE94C +:1006E0006ECC945F32232C9B788D8D8AD76884E200 +:1006F0005A267E87CFC3F7AF3ADE2C21BE435592F0 +:100700008657AF428C4ED05E924BFB289FE92B550B +:100710009C5E80F925A37F67A3D3B4D7CE0BE77D7A +:1007200071B8CC7623CF27DA39EE2BE0B917C5673D +:10073000835C8E5143567FEF706EC6B8BF596E68AA +:10074000D58A549775FC148F430EE64FC7A2686F85 +:10075000B500A747887AC90EA3EFB95BF6F39A30C4 +:10076000CF73DE99155F1E26F862F4FD42D0B4D334 +:100770005A0FEB772DEE2BA8AC5FE8F4FB8D5C9A5B +:10078000BF7317D3E396EFA599FC3A369104FC1E8C +:100790008DBF1C3489ED7F24649E13723AB8336890 +:1007A000D69374481E2FEDE679F9BA49275CAE68F6 +:1007B000815E43AE00D81EAEBF203A858D579A8821 +:1007C000E2A7F759FD2995E42FAF03D43F7588F4CC +:1007D0008576A614637A4AAD7BEAF038E057A5C85F +:1007E000CFAD7B8AE4DD601DD298CFDCE31FAC1B6C +:1007F000DE28AB970CD69358DF29F4E4F670DD536E +:10080000EDC4FFF13BACFC512DE8F02F4D7F3D7A5C +:10081000BB86F70C925195ECAA8D0E7AF8E7B09B47 +:10082000F05FA525EE477A5874F3808A5757BCC508 +:100830009110F2C384E80749FCCEDE8479224DB5DD +:10084000947FCFA127BA96F8B207F705785A02C667 +:100850002787F62795797FCA52B43F7E9DBF97B10F +:100860004EFE368FBF05CA383F6B1E1EDFDB27E406 +:10087000C9536145945CBE6645DBC99FF2D6C91475 +:100880003FCEAA936D7A837E298FDAAB367AEBCF8F +:10089000491C0C5BE523A4E3656C1DFE29911C3CFF +:1008A0007FA92E53D7A2BFFD7D61FFB17DBA97E42A +:1008B0004545C49FE0FBF64CC67D137839D5BEBDD7 +:1008C000D89A88D5BA46DEB74B2FE3F9F4CEE7BF06 +:1008D000137838DEF89FDF437659E91DA0EF7E7765 +:1008E00095B6511CD68CBB7AF656A70BF5A17CC0E9 +:1008F0007581F03C2C9DF3BEF8C9DF6B744FE42387 +:100900004FC6F324258BE3F9486B23F5631B4CBFDB +:10091000D372052E85E7B1D9EEF199F7112E074E66 +:100920000C4BE2CBBE82726879A342DF77B802EC4F +:10093000F914979B795F2D667E1CCFFB4A40F60227 +:1009400064C36549C7EF4C406C01DEB71FF6FB136B +:10095000E27CEBEB8EBC89AF362E8BD58A76EFD35B +:10096000FF5384BF253A97BF4B62FC3B3F97C42F90 +:100970008BD55ACEA35FFA54C99837191FC4473C88 +:10098000563B69383E96C725B7A69F1A2FA78B8777 +:10099000656AC5823C7D381E9CEB6718DB8A78FE51 +:1009A0003AC333DA9D23E183B5A3FD78E932857E2E +:1009B00077668152EFC273902B1B243A6362F80D65 +:1009C0008BBCB8FAF32DF03AF1E8C4D7954F00DDAF +:1009D0001BB8F2BB218AB7BD60E2277D2E9D5F98D0 +:1009E000E72796751EE3F95B1AAD73F1EC8A5FE0B9 +:1009F000F71512ED4CDAF2F5DACE019733CCE3BD00 +:100A000005B6EE6323ECBBED3CD0099F137E9FD06F +:100A10002BCE733150D3E5A807CFCF12E763D32095 +:100A200026CEC7B2281DB734B3BC757E97CEA4B30B +:100A30002B5A1A06E7C5F125480CD635BCAFF5B4DC +:100A4000B2F512F6F73551FEFB87F1CB723BF0DDC4 +:100A500022307F97C8A0F3A62B04FE1A98C787BF41 +:100A600099762E134E78AEB7C8F0E941CB3ADFEB5A +:100A700096EAC43DAAAC2553B15F72BF326D38BC53 +:100A80006BA2FC770E191D7E60A543DF24FEFD5985 +:100A9000275E4C7C350DE165DA67C1CBEF5171E61D +:100AA000D1790DD9B9039297EEC39BE738ECAF49E2 +:100AB00037139DB764150B3B80AFDBFCCE1740337B +:100AC000D9F74BC57DACA32E687C38C8CF752A2DCD +:100AD00072EB3B39D5B76459FC63F35CC7FCAE9449 +:100AE00049CF977B836985D3A1EDBB5143794C09ED +:100AF000CA6352B256E8888F2E7C3587EC9EAE2CA6 +:100B0000F49F03FCBCCAF7F4A35D97E843FBB7E985 +:100B1000AAC7BA67B0BAFFEBBF4ED2A07A0EE12DDA +:100B200024F6AD5AEC9B099FBF9C3FB7EC1F8F9FEB +:100B30009589F899D8C791F484B98FE6BEA11D852F +:100B4000F4EB2B53FF9CE9F7FAE050D500F2692251 +:100B5000AA520E5D427AAD83BEC705FA4E3C7FBFF6 +:100B6000A2C565FB9DA604DED3C7F61B7DC22F89F7 +:100B700051FFE5F9BC3F9471BB7190EE93ACBF257A +:100B80000F08BCE131B86FFDAC2FE689B1F1C6A00A +:100B9000BE872ECB3C25C3E71D713C473F65F0DC8B +:100BA00024168B59E4F5BE2C6EDFBE17ADEA9533E3 +:100BB000C45FCC72B937B748B5E4871DCBF736664A +:100BC000FA7EA939DEE0F7E506EDC481A70ECD1B5C +:100BD000B2133777BC65B713936F7D213BB1FFB676 +:100BE000B79E6A67FDFFF43B0FE9ABF7EAFCB40F71 +:100BF000B92DE7C17FE07D5B157F0390EC7BFA3E6A +:100C00008EB7A590D623A90C73F83B627A4C427C30 +:100C1000BF891FF3C5B88A0EE910032E578D498886 +:100C2000AFDB853FCAE86C8AF53BAE6F66713BC3AC +:100C30009CC7E38524DE3336C76574D04679A5F5B5 +:100C4000407AC43C8735F9D91CE74496DD0F3E0D48 +:100C5000FE3D91897F9F959BFFFD16B45F9F5128B4 +:100C60001FF46FA337D1F34B5BAEA4F2B2966BF9CE +:100C7000BC62BE6F4A8993384E5FE3AFFFF64646CB +:100C8000AFABF77AE85ED9CA6FBE792BF2A7B7850A +:100C9000ED3B6BFFBFCC8E383800800000000000B9 +:100CA0001F8B080000000000000BE57D0B7C54C585 +:100CB000B9F89C3DFB4AB2BBD9DDBC96BC38E11902 +:100CC00025C44D801010EB86575109049F51026CCA +:100CD0000884008104A4BAAD1436246040ACF155F8 +:100CE000F1AA7451ACB657BD4169E5B6D16E442D39 +:100CF000540AB1BED00A06A516154DE45156ABE50F +:100D0000CEF7CD4C72CEC92E84DAFBFBF7FEFEF196 +:100D1000D77ECC9939F3F8DEF3CD37676F5C587521 +:100D2000FF986442CC430D4E8910D29C45CA5B6D3E +:100D3000B4DC209501DCA898A7EDA4B0CE5132D246 +:100D4000398690B3F0773994276399781C0652441A +:100D5000C84A2BFDB742C89943B77BE6D3FEE26D84 +:100D6000362F7D42FBC9B9CB40CB64AF4C1EA740A8 +:100D70004E20F3CAF228B43038D069242405A001EB +:100D8000611A40DAAF3542679304EDBCDE7A3ABEB1 +:100D9000D518244E8011233E374B747E79BDF31154 +:100DA00050F4678DC8848C82F1F4EF9BF139AC0B61 +:100DB000DE9793D83CC4FBB9F0FE1880621E096C24 +:100DC0001E49FA7E1CECB94CEA014FFA7934254EE3 +:100DD000CA73A6009E7C230112D2692AB31332D7AC +:100DE000F68783523E85565B58A690044CC73B73EA +:100DF00009FE9D1D04FF5FE1FC78042112E994CEF9 +:100E0000D2A1677C23850752FCC595C8A17539140A +:100E10004ACED2D1A369B3129317F0D93124D93E67 +:100E20004835FEE540453AEFD78D4E3BCCB36C8A52 +:100E30005C16CAC3EE53AE857EA654156D62C359C7 +:100E4000492A21F3D8BFC9EBCAF6E641B43E1834AB +:100E50007987523ACEB3064330BF79C418ECB462F6 +:100E600013E9AC84503116F1F7E87CE74D967D71BB +:100E70000E4D3B7296CE9334919787D0FEE74A7C15 +:100E800080202DD3F70EF3E207934F5E07CBE824C3 +:100E90004EF320DA7E6E67E574928F5536E0A785B3 +:100EA000BCDDBC80E9684FBFF47F95416D797E71F0 +:100EB000C1AB940C142FA169A381CF2E32209F5572 +:100EC000356BDB2D7CFF8A4F8803FA351EEDC13769 +:100ED000CC93DCCDF8654AA353A1781AED54B03C0D +:100EE00063F24793092DCF24E43AE877E664D919F1 +:100EF000A6AD37070CC44727BEDF278724BAB6FD47 +:100F0000B99D7B2F07BC159B94C761ADB9E4CE6B2F +:100F100092A17E9413F05C06CF06607B42A09DC731 +:100F20001A1A4A9F75F83EB255A9F86E7FF1471715 +:100F3000F929BDB61A484D347E22A401E9FAF28F90 +:100F4000E2B19F0FEE9342163AFF29F2377F1C4B16 +:100F5000E753F56393D7A2E0B20C40D7E95E268F42 +:100F600084F86C53283EE71256FE88941585E9F8FC +:100F70005505874A2CB49FAAF512CAA9C03FC5F7E8 +:100F8000876ABCF9EBCB12C30AE25DF39C76660676 +:100F90007EA678FE30069E3F54E339F0FEBB235F09 +:100FA00056B5BBDB694F063E2785A4F02C45CD69BD +:100FB00032217114E9BB6E01CFAC3D38F2E5A1845A +:100FC000DC477C5B50EF904E63D9484A2723F145BC +:100FD000D303A50E260753E4E3489F13C5B202F8D6 +:100FE000DA1FF8D446398CECFF469E0678263E4A36 +:100FF000EC71BDEF3DE334E37B5BCDC40778DE9A53 +:101000006E0D35D0AEDA7F74715A27D247796002FF +:10101000D0F10F26F2B8127BBEF6804C8650C62C5B +:101020000D480805FD0606E28871944A5F91E8F3D1 +:10103000FF1DC8319D5ACA6A6250E8B8AE20F185DA +:10104000A2F08568B7CCDA3DD548B07DD845E7B782 +:101050005C318424BADE0289F1B3D554EFCBA04DC4 +:101060008D6DB3821904E621E33C143A3F239D5F62 +:101070004E2001CB8302490807075C08870432B081 +:101080007E686030C261811C7C3E3C3002CBB981FD +:1010900051082F0A1420BC387029C2118149D82E5A +:1010A0002F50827064E02A7C9E1FB806E12581598A +:1010B00008BD81D9585F10A8425818A8C4E7A302F8 +:1010C0004BB13C3A703396C70456202C0ADC86702C +:1010D0006CA0116171A001DB8D0BDC81E5F1817BDE +:1010E000115E1AB81BE184C043580F0A08F010CFF4 +:1010F000E5F10E6581934A0A70B8027C1C4BEEFE46 +:10110000C1ED52B5D3F731F09D68673610BFBABD57 +:1011100068F735B71B2EA06B94FE4E73FDFC85F768 +:10112000C39F0E27BD746BF6349411B9975E969DDC +:1011300025E10CFACFE5BB6611D00B243759C3A7C4 +:101140007DF5035BDF5FB8FEDA6AECF0C9C0BFF57E +:10115000C41BA48F4A47BF2E413FDB14E3B4501495 +:101160007ECB7799705EA39D7E938BC2849CA32FC8 +:10117000833E991974FE7122F04B5EF21F26D2FE57 +:101180000636196004AA4A9CED13A9DE512613D431 +:101190008BDB084179DA16AFB5A7C35C0C1F84B4AA +:1011A000EE1984F234A490D99FCE2B40BECC3F1AC6 +:1011B0004436E580BC852523ED2FB89290C785CDB8 +:1011C00080F61BE6FF1CEA7BFB33337FA199BC64EE +:1011D000A513C9695126C65138788BEFA538FACACC +:1011E000D0907F623C2D0F7F32F812C08B5A431390 +:1011F00013281CB12BFC1235A76464B873A28D961A +:101200002FD94376035A0B3A9449765A1E75D0B7B4 +:101210009BB20119D3E99FE450603EA146079DCFE0 +:10122000D6C3C4DB40CBC5C75BE444A2A2BF99F8D8 +:1012300077A8E8621FDD313989FE337395B34086A4 +:10124000F78D9D71AEBCBEF4D906EB8675523BF2AC +:10125000385D57A62F2C39557C72B54B1274280275 +:101260003ACC58DD6D84756E6B72DB917EF1CE12D7 +:1012700018B27B0A713EAA001F1B114FE6F583507E +:10128000DE05DF51FC5E34CBAEC69B24F45A4D6BB9 +:101290005E6CFC5EFD6F86DF23C06D6362E3D70A80 +:1012A000BC32EEFC725CE5EA91E379AE31B1DB353C +:1012B000BB983ED5E3799B81ECA1B68A8E4BF9941D +:1012C000C91509D2A68D9CBFCF87D71FBB985DF9E2 +:1012D00077C1EB4D2EA62762E19528C9A82729BF23 +:1012E0005E4406C7D637D05F34FB758FAB8F9E3315 +:1012F00083BFD8ECA47A6E706C3D37D7C5E81D5318 +:101300007F713D63E67A5C8CF7334EB7038EB2474C +:1013100080BEB6F58620C85909B1A35C104F32E7EC +:1013200013673CF0C974D95902FA860C27E847279D +:10133000E48582B04F1918540A6568064A19F09876 +:101340009E1BDA44BBCEA17E8691D29F761506689D +:10135000559C86F974DD8942DE9C951EB5BC097BDF +:10136000DF2B8F822FDCDB36E5307E9D45FD97C37A +:101370007CDEBDFD48D86EC30FD3B76D52E9C16D99 +:101380001E0F9645FB58FCFB8DE0DFA675C40FF2DF +:101390003121BADF70D02573BEEDF6019F07BF473C +:1013A0009CE0CFB89A3E44FDE4A2FA4942FDC4C68F +:1013B000CF0CC4FF3C48CBEFB852B17FC0E3F5F689 +:1013C000FF77FCFC948B30799AE06C9769FD406A5A +:1013D000871490D30974EEA3015F66A4BB42181D65 +:1013E000950924047E2FC55BD800FAD7600F819D34 +:1013F000319B5B7C20CFC4ECC2F51F70F83F769D1B +:1014000043DF3813940220EA99BBFF3ECD46F96FC3 +:10141000438E331ECAA76879B3878EEBEE24BCDCFB +:101420006C43F9A17FE948C530DD1B807D14659FC1 +:1014300015DA0FEA2907A1BC157C92F1B47FD7D742 +:101440007B9A2862CA5DBED3301FCAD76700FA866E +:10145000D30DEAE05E7E3E9F3F20E4B3579E9C059D +:10146000429E2AF3501F4AEE94DEFE62F937BFE532 +:10147000FAD3ED6630967F23F8FE82FD1B3E5FE2D5 +:1014800056CEE9BFC4ED7D63CB765A5EE99195A354 +:10149000D4BFB3A7BFDD61A4652BF5373FA2658339 +:1014A000B5C308ED4AA984DA28BE7DD4C983FD8777 +:1014B00075342BC31FEC3F4EB448D398BE5612AFC1 +:1014C0001D792E3C86703D2B3D661C2F6EE89044A6 +:1014D000902B07E72B62944260C71DC54EE37CEC5E +:1014E000AF935C4DFBBBC4CDEC82906BD05BCFE681 +:1014F000815E721B61BF6EB192A0DDDDDB3F941394 +:101500000B7BF513E1FBB89BF99EA9659D3771082C +:10151000C8E97E16476959C3E4B2349384D6819EE4 +:10152000F011C549DBC711F1470597964DBC34FD55 +:101530006B89F8E8FCF77D2D23948690B09DEEF73B +:101540004ABD5218F68166833504B6B424DD4ACC10 +:101550005076184216908F0F255CA7B9302104CA27 +:101560006F727A7162275DC7C97DBB6DFE28F4BFBB +:10157000C15FE99D3C2A361E7BDACD79C509787CAE +:10158000486972821F19F41831EEB0119AAAF4FA60 +:101590005C37F347A83F540E7C3A6341779319E8D0 +:1015A0009D938CFE1019E246BE1DE0D9B9B1044CE2 +:1015B000562DF34FD349A841ED5709FEEA74FBE7D6 +:1015C000BBE93C1EE276848A65C73088575D94EC9F +:1015D00006BFB4A42EBD0DFCDD07D712EF0213EA3F +:1015E00083EB605C5F526B01F0EF43DE9DBFB80B95 +:1015F000F069A1FB62D0E3A30ED9144AAF8A31BBD4 +:1016000053603D7FD4CD5FC08AC01AC48B7E1FBC9F +:10161000D2CDF7C1F9241FF6C127BDD7248691B7D3 +:1016200092A2CA7745E036EC47EC87DF3785B39C5A +:1016300051E5508B6F317E85C4F6B5C42431FDC7AA +:10164000ED28D52F4DA8074204EDA6CF223D0AF67E +:10165000E6A4779417EC762C7D23E643F138B4CCDE +:101660001EA55E2265D1F4C45637F30F2A4C74BF11 +:1016700040EBA51563EA615E15769B047C27DA6D65 +:10168000E2ED043F8B78959CF8CD18A03FC407A3EA +:10169000AD7F1E319E52C7A33681ACA5307C79A3A5 +:1016A000F82BB1F075D0D4520AF33AB850260DB4E5 +:1016B0009F93FEB16924CAFB02BE077C43E9B22AAC +:1016C000898DD743CF21D1F177706D8D77B2A997EE +:1016D0009E7DEA2BE3CAC17E97031E55E31E70333D +:1016E0003B7F8C4362F12B4E5A6F9E7FBF938C04DD +:1016F0003D756A4CD00E71B1EE5F3500BD7F6CC791 +:10170000784579E5E9310D2355F82C266824E7ED75 +:101710007ED0A9D0E7E5439B5282B6D8783C0678C4 +:10172000A478BA031E8CC378CC1FDC17108F2179E4 +:101730006EE437B23BCE1B8678E45BB217FC06182A +:10174000D78FFA93C5935739D9BCE2747E5E79601E +:10175000B946BF244424124A52958DAD189F4D8836 +:1017600018F1B95EDE9ED2C99BC07F2C7A0AFCEBD1 +:101770009FFF9EF3E5C1CAC50AC40DCDF1D1FDE0BE +:10178000EC2449C3576FAFF56BC67BE75B59B35F7A +:1017900016F0EFBCFF93FE716910AF2A370787F68A +:1017A00047CE057EDEFEE60127F41BF79525AAFC51 +:1017B0009DE2F689DAD3E6EB14953DBD516E02BC8D +:1017C0002718B97ED3C99D0FEC2AC5E7E56057E914 +:1017D0001413CE6357E791603BC491F5E30B7BAAEA +:1017E000E72F615FF574137CE049A2F44BE8A59FF5 +:1017F000881BC6922F21579D5CFEF5F8D7C31BCCE2 +:101800005ABF47C0CFB99C9DF4C79120D58F379759 +:10181000C82122217FA07D3C78BF84FE66B8D28299 +:1018200076B9AA320EE3B3550532D657DD29A3FDAA +:101830000C53FD504BE7F347AE27F4F1D912227950 +:1018400027ABD63D63749CA67CE3C27BFFB816E24F +:10185000CBC52605C6DBAFB07873D027A3FF4AFB04 +:10186000F086213E7DDF655EB067821FF6FB6494E3 +:10187000B7E09BB21786EDE0F1E8FDCD052119E850 +:101880002CF97BC6510643FF550AD0E15DCF1627E0 +:10189000E8BBB86F1F282BC3FDA35F2940BB499D40 +:1018A000553AEF382EA793D28BAF073BFEC1661394 +:1018B00081B8D107AB4FA23C77AEADF74E1EDA1B15 +:1018C0005F16F1617D9C591F5FEE1357D6C59305D6 +:1018D0003FE8F9A422067F087D158B3FA81EAB4A7E +:1018E0004AB9703D26F4C77B7C9D93D2B7DCD940C2 +:1018F000F190B040463C08BE7CF79BDB1F013D1CCD +:1019000047F9631DF0F3B74FBC02FB10B2588A1AB7 +:1019100047DEDE63F7285D727BE972A37F714F19A2 +:10192000C47F76CD8A9E32AC5F6F5762EBB573EBA6 +:10193000AD61492C5EA1B73B7A79F857DB9DF2CABD +:10194000FB73E1FDF2CA8521801BD3AD35A07FF585 +:101950007A426F27C47CF4F34C88C824344A3D6F24 +:1019600005DBF5DA0933D607AC8E7C70D6CFC431EF +:1019700018042710FCD2C371A1461CAFFE92329C02 +:101980007FFD588001E2ED0CC2FA3CF1183F68C9B6 +:1019900064EDE52BE2993F3EDA8DEB9485437ECAF8 +:1019A00085E546BE86516EFF734914BF8D3E431CCC +:1019B0009C2B4CB21BF742C8A565A28158482F9EAC +:1019C00084FF4E203240D78B7512EC3B0BACE6C146 +:1019D000E89FFE16FA216BE8BE90F2FBBE7DF2CEC8 +:1019E0006D7489FBBCA312A3F9E702CEF1FC10F5DC +:1019F000C2F5812A84877EF04E36C8EB2D92FF55C2 +:101A000090838EF2AA3BE15CB86E978CE74A736EC6 +:101A1000797718DBA769CF2765873517E2288D52BC +:101A2000BC17F488C063BBDD8CFAA5F110D3838D9D +:101A300047245E66FB889779FDC9F7EDB8CF10782B +:101A4000A7EB790BC6F7DDEBC2F5887DC677584F5B +:101A500027E027F67A329DA82F80AFE4DEF9CB7617 +:101A600023AEAB8BC47B61FE011E0F22EFC7A1DF4B +:101A70002CE85BC7F94FD07739A76F57DBE99F5C3C +:101A80004ADBB7F8DC78CA2067115C6FD7FB09C85E +:101A90001F62BD940F4EC1FC76B7313BD172D8CED8 +:101AA000F0652FCA85F909FFDA99C4FC64FDBA2BE9 +:101AB000C43E9DFB19E0DF429C62917BE2D9A431D8 +:101AC00051DA73BF96E2D9904CEB4B9CE45488F406 +:101AD000E2598C23C615EF3992B57E4C058F2BBC8D +:101AE0006F22E5104F84710B55F35BE32E7124A731 +:101AF000F41DF73BD07140F239F9524BC73AA3AD10 +:101B0000594A243DFB620CA5297DE55C2F67525B99 +:101B1000FB57703EAF97FF33867A22D17E6F95FDDB +:101B200007DD1436FA49A765705F79389F1EA1F466 +:101B30002E484EE9AB4FFA4BE709C952CF3E86D348 +:101B400079427214BD27F03DDC5DF63DA887F5674C +:101B500014E23ECF0774073D611E84E3215F76BB2C +:101B600048E851DA2889C751C47C202E1147DF9BF1 +:101B7000999C83E34A461234D17252AE5702BDDFBC +:101B80000F3E98F92FE6839B92CF29CF61F44B96B5 +:101B9000717A2F1379163BCF9D67D10FBAD5C03A12 +:101BA000CE18BCDDFE9C0BA7DBCDC97DE4F3E6E4DB +:101BB00073C8E770B7FF1618AFD14C4EA11F5E5C1B +:101BC000E981F10E387C9F24D2E72F36707D924355 +:101BD000E946EB5F4996515FDD432E463DFC3D8370 +:101BE00001E7DF45F5EFA339D1F83E6874D3F7CFAD +:101BF0005C4DF03C8EAE6F3DE3CBA004CF6F9D47B4 +:101C00000CF0DCA33410C305E8A196BEFCD9722EFB +:101C1000FEA47AE85EA8A7FCB80AF8D1AA388DE736 +:101C2000D2433F4BD6DAF97EF0DFCFD478FE17F0FF +:101C3000DF2FCFCD7F17CC57CF45D307828FC5BEBF +:101C40002056BE10954792E1EE3B2E215E3C0F2BB5 +:101C5000715899DDDD21A19D6D3C52E0C7B2DD8A4E +:101C60004A41D8E1133B59BD3C31BA3FD896EC66A6 +:101C70007906AD2BBC464D1E48109FDFE53BE11CAD +:101C800042F5E254D986EB4B2A65F143B17EAA674F +:101C9000A74F49E57153BA9EA42C868724EA0FC04A +:101CA000399A83EF0F128B8D1ABF5FE0ED56B94C56 +:101CB00082B8B72B9940DA0DF5EB570F87F37B9776 +:101CC0004FDB3E856CFE52C64108CA839BDA6F88A3 +:101CD00063254DD3B5837D483EB4573DCFE9BB9FC7 +:101CE000F83899EF27CCC4037685C815E7E41BD5EF +:101CF0007EE2F3E47EC4454E261BF8798AD67EB593 +:101D0000C691A871818614BE2F38E542FF57E6764A +:101D10006B72670EE6A7ACB42B182F9065AF757A7F +:101D20004EDFF75D3E035154EB4B9A164F14D5FE30 +:101D300021A5CCAD29A795A76BDA0FF00FD2D467F8 +:101D4000D45CACA9CFAA2FD4940706C66BDAE750AF +:101D500001509707375FA9693FB4E56A4D79F89656 +:101D60009B34ED2F0ACDD7D48F787289A67E64EB91 +:101D70004A4DF9925D3FD2B46FE4715F3D5E2673C8 +:101D8000BC361A99DE69B015623CB2D1A68D4766A1 +:101D9000F37625891372210EDEF861412EE0FB6592 +:101DA000C7788C8BC7E20BBD1E8BA53FF5CF2F4BA1 +:101DB00061FAEE8B97CC069083E5BBA9BC5E42CB63 +:101DC000B6F736C09A9AF3D879AA91B0FC1E71BEC4 +:101DD00022DEEF395F317A597CD561239BA2F04531 +:101DE000768A1235FE29F82816DE1AFA89B7297C78 +:101DF0001DDF156FEF4B2C3F55ADFF774499D79AF8 +:101E00001416DFA2F6655E0AF37746C7A327EE44F1 +:101E100079BC50FD2FE641F5FF9214F443DF98732F +:101E20002BE8FF9D162FECC9BE287FA3FA0105DA27 +:101E300057B3F6066F2ED02556FC7B4D4A9FF87798 +:101E40000D8B7FC76BF0562BE45D17876B747C8D11 +:101E5000F1EF46B337B73FF1EF5AD031294007C60B +:101E60001F3DF4E5F1F358FBA000217B25D8F7D8FE +:101E70008C0A9C739D6F5F4BF7B3B9709EDA02FBBF +:101E800026D53E87EE6FF9FE260EED02B57BF7A64E +:101E9000A0DE237B15FAFC0CDDF76E52A028EC9F28 +:101EA0004FE3975B88D76A96919E0FA6E07E97AC2A +:101EB0008A93215E16DE3721E73BD9F3ED291760BF +:101EC000CFC9F9CFE5D0EE94D2F5AF8BE277E9CF69 +:101ED000E17AFC6FF0D3243C8F433CADA77611CE62 +:101EE000E3DA53987D5E7F88ED93D71F99E541B97A +:101EF00049293AE7395C7FF5CDAB297DFCD25753B0 +:101F0000CEE1978AF5AFE4FBDE29725E2BC41B4F4E +:101F100044CC883799B0FCC8BA3D2612427AB23C0C +:101F200063414753644307D86713D1E7152B89B042 +:101F30006ED31E19F5134966F541626D003F27B156 +:101F4000586BB75C3EADDD4A9AE6D6D931ADDD4A75 +:101F50002BD7DAAD017EADDDCAA829D4D931ADDDEC +:101F60001A1898A8B3635ABB35B8F96A9D1DD3DA1D +:101F7000ADE15BB476EBA290D66E8D7872A5CE8E75 +:101F800069EDD625BBD669EA0BC29B34F5A3F6DC16 +:101F9000A3298FE9F80F4DFB457B9FC3FC9BB1073D +:101FA0001FD5B41BD7F94B4D3B8AF00EC8D35E80CA +:101FB0002421E4D263CF6AEA17703FEDB2EEDF6806 +:101FC000FA212D2CDF3A48FF037AFD95F8CDE09CED +:101FD0001849F7AB1994AECB4392374C9B2DDEB525 +:101FE000A308E6F1D9E12BF6403F8BB668F3B417AE +:101FF00087B4E53A322811F4431DE58B10E593A52B +:1020000090BFADD26B4B49BD03F321FAC9678BF684 +:102010005E4330EF33E8EB80FC74B14EC16F3ECECF +:102020006F627E62BD4BA9DF17567AD7E9A3FFB175 +:102030007D64A719F8B67A9744FE43EABB9E9AB628 +:10204000BB37644459977E1D7ABF734CAA368E3DC8 +:1020500045B6615CFFC49BB297C507B572B8722FD5 +:102060008BE7AF7C5AC2F89A1E1FC22F8D85173995 +:10207000C8F60975C9241452C99FC2F161F168E517 +:10208000EF04FC03E6F3B01C82BCA038255ECF6FE2 +:102090004561D217CF09B95A39D5E3D9EE4D8FCA68 +:1020A000570AFD0FE6514DD8B9949EAFF4785FBE44 +:1020B000EB6E33E8C50BC5FB8254EDF9A0383F2821 +:1020C000A1AB3547C9831378A5FBF225A929B1F740 +:1020D000ADB7A45EF0BEF596D47FEDBEB521F51C7C +:1020E000F1B32E889751BF521F2FEB1B1FDBFD95BD +:1020F000E4C038348B7FF9BD5696AFA2B393B91EB6 +:102100008D9DECD9F77E28851A69E7F50E5F0BAC3B +:102110006F85C37737C0990EDF3DA92AFC3452BCC6 +:10212000E0FD1C6AA77644F10FF7A50ABFA80CE3EF +:1021300022EB4B587B7DBB5FA7B2FB40ED29451ED0 +:10214000F43B8F1430FB692F3AA7DF79173FCFB9E3 +:1021500003CE0B87F6E6F1DCC9CF55A8D8F9806E1F +:10216000EB4D651E759EEF83A92E1CCF31EED90E67 +:10217000C8776E741A9C9202FEB301CF459B7CB661 +:10218000693BF3D87BC99AF7D8BD2319F00DFEBC83 +:10219000CDF8B59A6FF7515C42BFB1D6B92F95F91A +:1021A000BB26E2B382DE15E7B9A60F0BACA06F8D9C +:1021B00092D7192D8FD3C4F3A426F2F35CD9C9CEDC +:1021C000777BE4FC3C7952373BFCAFA9F9549CEB9C +:1021D000CE76F8F6C1F380316801FF32608DBEFF24 +:1021E000FD13A7E35DB03EA4A70DF908C797FB1543 +:1021F0003FF9732AC6E58298AF78ABEC3D06F1B99A +:10220000FEC6AB3E4EED13AFFA58CD877AF9A3FE6A +:10221000E72789908797986EC4ED84D19B0BFCDFEC +:102220000CFF1E87F1D5CF61DD7DF24F1537CFA7AB +:1022300055CE994F2BFA2977F94EA5B2BCBFBFA551 +:10224000B2BCBF2659D58FE33CFD503CE5D6DBFA46 +:10225000853F396D0CC6358FB160C285C5351D69A6 +:102260007DFC4747DA39FCC733878627C279B288B5 +:102270005BE9DB59034999EAFB31CD2EEDF81B0AE6 +:102280005979001F777922E3FB91698C8E220F50D8 +:10229000C4ADADD3890FEE3BDCC3F3B3453F23D3CD +:1022A000ECD83ED53D71645A0A9CA749B8AFDCE032 +:1022B0009234FBCB4F524B46C27A86F3FE47A6318F +:1022C0003EDD3688C567F479902778FB13A9131192 +:1022D00052825D04F834CB72543C16A6B1F97F9259 +:1022E000C8E45BC4CFAAEE67F7BB44DC4CC4010969 +:1022F000F1BE9D40F5CA479B4D04E25A0B65DB06D3 +:10230000E0C39EFB73FC5CDD49FF037B5999578654 +:10231000F947DFF5FE16E033C1DDD75E5E99D6E3FF +:10232000A7782FF01ED7ACB40B386FEF8C677CDB2F +:102330006DB7613C5BDF6E29E787CD3C4E01FA1A31 +:10234000EC865B26F5D1ECC7528EF733872C3EF432 +:1023500063A6C5633E8738FF3052FE4C74631A781B +:1023600010A035909109F7897ACE3F1482EF25D9D4 +:102370006CF89E5121613B5C09357A25C82FEB34FE +:1023800077AE4F83F95E2679E1FE405A85B33D2D45 +:1023900019EE112A28661B7288A318EA0B0C58EF55 +:1023A000BAD6B9C10479D70A81936C62A2E3D8E99D +:1023B00038F7A6E5B07505AF694FA3ED12956E32FB +:1023C000280FF48873AA07E4B89CE5AFEBD7D7C40D +:1023D000F9D5B69EEE1B001F4AF43CF0A63483C824 +:1023E0009B6F047E2D51C84E762F8AE5A1429A3507 +:1023F000E60B7A59BE7402E41B0D667A06EA7FEAA0 +:102400009AB411DE13F225737C03DFABF3E1EFE541 +:10241000E324E9E453E0930ED000F910C6E904F98F +:102420007A6645F4F93EC3E9BCCA51F620F0CFCC38 +:10243000090D98E74EBE397B562E02A797C9097D34 +:102440009F401C222E99E9DF3845417D4C9C12E6C5 +:10245000995A156F0D94E36CE39D32D83D0B3F2FD5 +:102460005C6020462A6F93783FBE72227D9CCBE24F +:10247000AC4CBF1AC9C7422E648E9C22B09FEC8F11 +:10248000FA459B13E87A26D9F6E13962DC90FA1214 +:10249000B857F0CA3CD6C73D31F2F63FE17ACC2DB1 +:1024A000FB3D06F0E9837F79EDE50948E78BE1869E +:1024B000E61DA6CED7F65CC6E3E7982FDEF99A2F85 +:1024C000EF9FCF2F7F2DADF3B5A6BCEFC2FF5E0906 +:1024D000F4F82794B160DE7AFE17FAECA0EC3F78AE +:1024E0001BC5FF7594A90285008DA402E9CDF28772 +:1024F000AEE5780E7E4DF16CEDC5F3756D7B117F09 +:10250000074D74DE747CD344866AD38F12793E46BD +:1025100008C7BDDEDA3205FC9B2E73773E8CDBF5F7 +:10252000C23B5941AA4F0EFDF8A49D50FEFBC0D8F6 +:102530006D87E7C756BF61F751BC1F5A2DE3FD37C2 +:10254000BC97ACCA07FA9CCBCB959EB2A3C057F3FD +:10255000D67E5BA4F6B3492005EDEEE2900C777CC5 +:102560007BF4DFD2271338D3B1F2B2D6244D59D839 +:10257000E36596E8F7C40779985C2C7E6A9B19F2AC +:10258000E1AFF4F8FF06E31FE3F906C776DA717FDF +:1025900025E633FFA90233EC273F68B39030F0BD46 +:1025A000B1C344304EE59B2E51BEF5733ED4CFF3FC +:1025B000D51713B0BF85F7CB1847AAA46305285ECB +:1025C000FD6D8BD9FE56B78E858794A9A0AF166E88 +:1025D00094485061ED5753BAF903B7E3F98A7E9DE9 +:1025E0007AFB729AAC36831ED1DB9705C4DB3C01C3 +:1025F000EC568BF6F9A2B63BB0DF45E7398FF178A0 +:10260000F8FEAC888C3D3B18E2CC83305F3096BD41 +:1026100039B69609E5A76BAD088FAF75223C0ACA9B +:1026200094E279E9AEF6573350AC3B8AC00EC5ED63 +:102630009D64BD89F4FACFC66DD7841F52802FB533 +:10264000F990151CCFC27F5EC4EF199CCF7FAE807E +:10265000759E231FB2A29FF99027F68CB2C2F3F1A8 +:10266000021F63293ED0FEE61D50C8F9ED6F2CBC59 +:10267000C47A6F197CE7200A9E85DC1CE5FA7DC1CF +:10268000F6591BD2E9041A5FF86B7627F2258B43C3 +:1026900088732AD9B3A103D62F135DFC2F48DE24FB +:1026A0002AFED5F3E722E26576C7C6DEB3F2B84468 +:1026B0000F5FB6DD8978157C04370A0C1E80618FA8 +:1026C000A1B8EF7703FA7C1FA0455BFEC2D4990D39 +:1026D0007A63912E5EF085147DFF35DD3388AD5F22 +:1026E000F14D85BC8885A46C038BABB7A09E3A6680 +:1026F0006C79F53690E7ED4C9E963DFFF4AF414F77 +:102700002DF9AFFB1DA0A73E31B6A4C278B58FAF9F +:1027100077805E3F660C3AE0FD4F4272D4FBBA4FC1 +:10272000787ACE056C9017B61C590C042C3803F43B +:10273000E4DF1E3739218E5AF7A4256CA1F858BE64 +:1027400093E191968FB0F2ED88AFBA5D5A395CF2A1 +:10275000C4FDA90AEEE783191C7F19A0AA976F3759 +:1027600061FEE8F237652F0C5347BA717DFAF761C5 +:102770001E114AB7BA56B9D29CD8B79E7A3C669019 +:10278000B3BA9D8C4E753A3FB386EB653DBF3FE0D3 +:10279000E17E26E7738A178C87897C561262FAB924 +:1027A000F1170FE41FA1F33ABEFD358794D7CBEFA5 +:1027B00004B22EC12F6FAD9A077906B1F8FC0B2E2B +:1027C000173D7A9FDB1965179D18F8FE6D0CD69A98 +:1027D000C28E4B293E6AB799BC41FAB8F669D967EF +:1027E000033FE95D0B7EDF61E9D3AFBC3D9ECE6F59 +:1027F000E90E53F274B60C1BE86741A73AE0EFC24A +:102800005EBA2C79EE1533E441C2F3D5EE5EFA2CB4 +:10281000DDD16E86BC4A3D1E27B5B69B997CE9E8A2 +:10282000D47A642AD8E5C65F9C31031F7CF2A244A7 +:10283000C085D4BF5FB3ED1507E80FC013D80F41B3 +:10284000AF1EFAF5A15B78C66F46633B279CD3C4E5 +:10285000A25F00E63206F9FB99DFD0F16BDEB378B8 +:1028600061FD35CFDCEC8075FCD558CFF8FC91F5D7 +:10287000A9608F6B4CC1542742F6BC66EB0F90FFEA +:1028800016BDFE8354827AD33700E497AE7300AC52 +:102890006FE1C3D7E1FAAA891FF9AFE611B90CFCC1 +:1028A000C4D346322D9A9FAF0C60FAE9AF8F5A70AD +:1028B00053F0573361DFE1F893CCF2F8C80AF443E0 +:1028C0007EC0D74A3531964F5B199D4E79C4FD7550 +:1028D000A6C7EA78ABBAEDB7A31EFB34CB9706F2D6 +:1028E0004EF1A08DA7BE3E258DEB3FFC5E0ABE4794 +:1028F000F96E123C87F61D265F5CBEE63D9ED7CA88 +:10290000C65FC5C7A7F38E87B8DC5F53B5FB570119 +:10291000670C107A807410357FC592FBED1B91AF68 +:102920004EBDC9F4CAF2D0AC6958DF610AA7417D37 +:10293000A8FD5A09F502F52FA2C9F57613976B6D1C +:102940003D9DA75152E3F745762FAEFA3EDA4EE5AC +:1029500087F4F28DB9F7794EAF7C8AFC8A453AFF4D +:102960004C40BD5E481FA0B57FE27DF2704AD47B2B +:1029700058BDFA20887C516B0AFDFC3F408EDFB5C4 +:10298000E03DC3DAA74DF8BD9CCF9EDAFDF64D942D +:10299000DF3F6B15F2ABD5B37AF9AD79F63A124D4C +:1029A0007E3F4B2E2351E5973E8F2ABFC92C7FFFD8 +:1029B0007F5BCF2E8AA167270FD0EA59EA4F245EAA +:1029C0004A8B9FFE72E940DC67E9F02AF0A9D79BA9 +:1029D000873C0AE257AF37E9DF9B448547813FC117 +:1029E000974BFE73198ED3C3BF823F05FFF6F0A746 +:1029F0007EBD5A3CEAEBE3E0CE514A2FDD4DEBE8D9 +:102A0000FE1ACE5D5F90F1DCB54BE976B8212ECB96 +:102A1000F36EBA9CBCEC62E5EE14F306D01FE279CB +:102A2000771CCB43E82AEB76B8547EFD9136D9016A +:102A300079F59DA1E8F91298499102B74463D53719 +:102A4000F0EFD6D8B203B02F6B61E73D0B1A6E7072 +:102A5000803FDDD536786639F8F17B65F4A9BAE2B6 +:102A6000797E55D0671C40F15AC5964C8E91E04F47 +:102A7000C1CFAE6A5B3A1D368D0B366BF1516DBB23 +:102A800016CFB3AAEF33F5F205017F2764063FABFB +:102A9000E661EDF325905705F4D1F1911FF828CAAE +:102AA0003D8C3B051F159002B64FE6E7555CAF4DD8 +:102AB00091F3669643FEE21E764FE2449B4C36C08D +:102AC0007A9FE2E757C114E4CFE5948FD571CEE346 +:102AD000C067C363DBEFE3BF3A54741B6D52FBEB7B +:102AE0003FE73F44E1F15FBF3BECB7507EFE9DEC1A +:102AF0003F93BEED27BDF8D55CCCA37CD142605F8F +:102B0000D4F5E2EFB36F83F26F2C5E9867D73AB6D5 +:102B10003F0EBE6847BBDE95C5FCBFC617CEE47747 +:102B2000A27D6A427AED1AC0EEA99E68FBFB61099C +:102B3000F2E9DAE8AAC0EEF27D57DD6FE2707FDDE0 +:102B4000F5C219CDBEF2BBAE6739BFAFD46527E57C +:102B500070BFB8CBC5EE77D6FD76DC63705F71D9F8 +:102B6000CE767315AD9FF4BB6FF341DF743DCBFCA4 +:102B700009EADF6E05977AF780039B4D14CF5F80DB +:102B8000CF974EF71FE989A5700FA32F5E181EBAC5 +:102B9000281E605D142F35A02763E1E3BD01ECFE24 +:102BA000C8BF1F3EBE9C0BE3D7B68D25104FEFC5A7 +:102BB0008BE463CFED987741D7CF9EBF78261FFC7B +:102BC000A3F3AD37F2FFD97A53D3FF5DD7CBF87DAE +:102BD000EB00667FF47CDF97AF9FBF05CBCFD8BDFE +:102BE00038DF7ECA7B51FABFABBCFFEFD0FBDAFF08 +:102BF000B3F4DECBE96D77C2794AD70BDF66930B6E +:102C000058F7CDFF47D7DDE3E718BCD6D1747EEF88 +:102C100091D0752552EC3CCE50BA761F3183FB1112 +:102C20003392ABD17F98E163F1954652B807EEA994 +:102C3000057D329E3B60320DC543C7B50521CCDB17 +:102C4000320687FE14F2B8AE5FE665DFF9D2EEAF6A +:102C500066A44E9B06FEDBFE063A2FDA6EBFDDE071 +:102C60006CA44B98E993D1DFA310FDBCB7265E8519 +:102C70007921338BB5FB8C9B74FB861BCAB5F5D7CA +:102C800093475320FFEEFA1A13E60B5DA76BBF269E +:102C9000DD89EBBC81D4AF67F1990BC353473ADBB5 +:102CA0004FF6C5C3B9F1D6074F7C3F89B93C4A5F9F +:102CB000BC59FC6C7F69A115DCDFE279722BFB85C6 +:102CC0004FC2F79D163EB4C0AFC5C7BED7A9EA171D +:102CD000F122F07EA1F81674D2E35DE057E04D4F8B +:102CE00087C7E04C42E58FF7429147E227EA7CCB69 +:102CF000193D7EA30DF178603BBBAF70A0B86A733D +:102D000001949F92D05F3B3D6114B1D2F5EE3791B3 +:102D10005DECFE974F7116F5E6B348C5BFC7730566 +:102D2000C82754EF4B219F50BD2EC8275497219F91 +:102D300050DD1EF209D5F5904FA8AE877C4275197B +:102D4000F209D5ED219F505D867C42757BC82754E2 +:102D500097219F50DD1EF209D5F5904FA8AE877CD4 +:102D6000427519F209D5ED219F505D0FF984EA7A79 +:102D7000C8275497219F50DD1EF208D5F59047A82B +:102D8000AE87BC417519F205D5ED2F8FBCA42997EC +:102D900090D734ED2759DFD094A738FFAC69FF7D79 +:102DA000CF479AFA2B94CF34F582FE57E59ED43C58 +:102DB00087338B6011EC63D85FA9F7EF9A7E8CA400 +:102DC0000CE3CC66528FD00AF15B0AE3492B421B1D +:102DD000157380570EF35F9C01FCBA35B801986BF0 +:102DE000FFB833D9A0FF0F4CB886C51FF839C14CC6 +:102DF000F8A7429938E19B4CD8D78A734F474426AD +:102E0000E151940F2312426724818493281F46E2E4 +:102E100010BA2349F83C29E242981CC9C0E729911D +:102E2000010853238311A64572107A2223100E88BD +:102E30005C84303D320ADFCB881420CC8C5C8ACF96 +:102E4000B322E310664726E1F3819112844AE42A13 +:102E50008439912B100E8A5C83ED064766211C1283 +:102E6000998DCF87466E44382C52857078A41261B4 +:102E70006E6429C28B228B115E1CB919DF1B11599C +:102E800081302F721B3E1F19F921C2FC4823C24B0F +:102E9000220D08BD913BB05D416423C2C2C8BDF89C +:102EA0007C54E46E84A3230FE1F33191071116459E +:102EB0001E433836B20D6171E43F118E8BFC02E186 +:102EC000F8C873F8DEA5911D0827447E8BCF2F8BA1 +:102ED000FC37C2EF4576E3F3CB23ED087D91D7F0C5 +:102EE0007949642FC2899137F0F9A4C8EB082747C4 +:102EF000FE8CCFA744DE453835F211C2EF478E2055 +:102F00009C16F90CE115914F105E193989EF5D158A +:102F1000F912E1F4C8DFF17969E42B843DFBFD0986 +:102F2000B1EE25FA0D6721AE6573F7EB3B5F846C5C +:102F3000D19C4B3D90E0403D397335CB23D9507245 +:102F40007232FAB52B2C0AFFBEA64EAF7E6303FF8A +:102F5000613DD40C607D401EE01CCEBF078A77A780 +:102F600080BFB4A1B0B316E22177E6745600BC2F3F +:102F700083F90D776430BB784F068B97560E73B28A +:102F80007B062B86E2F91549EEDF3ADEE4F659B40A +:102F9000BF398B976DDDD9782FA09FFDF4B7DDF990 +:102FA000F2A37E98E17F2203FD22FDFDBC7EBFFFE0 +:102FB0005FA827FEF9F79F3FD7FB1F707AA564969D +:102FC000FD16E769F4E543FDC47503E464DA4FE5F3 +:102FD00066C90976B2AAA9602AD0AF90F8309E38A7 +:102FE00027465E5727A7DFFC7A1381B8E27C85600D +:102FF0003C77FE4E96E70B71D052CA17359C2F9640 +:103000006DDC610617B4A67E11CB3F0AB1389395EB +:10301000FE07FCBC64F32CCC3F5AFAA436FE540BDA +:10302000711D19CE91B5CFEB789CA9CFB9822EBE78 +:10303000F46E068F2F7959DE11913371BDA7E97AAD +:10304000219FC37F8BDD0AFA9FE201CF49C4FA4575 +:10305000BC52E081F4BDCF8079A127F60CC53CB508 +:10306000138A9206EDFC549C3A6C90FFE01F0BCF44 +:1030700029FE309FA4BB2101F3918E507DAE40E22A +:1030800093D33F16BE9FD6F95E16E1DF6FD49E1B29 +:10309000583763FE75A5890E4CDB553E9E84F71F9D +:1030A000697FF9BB201EF9B809F3818264A58714F2 +:1030B000F73D57285B6F42FE98BFCBC5F2C382BE77 +:1030C00037215F5FD0E348D3E0A9905734BF39A7D9 +:1030D00000C36EBB4CE8E789F35241A7BE79D165C6 +:1030E00089F07DC425CDAF233D29BD34F5B59BBF07 +:1030F000C4FB03945E4763D0EBE8B9E89598A9A5B3 +:1031000017C4956F80CAD54928A715EBC243EB5564 +:10311000FCA88FD3934C1BDE7714F9C4D3D2193D8E +:1031200088D19B0A743DB9790CD24B4FA769FFA88F +:10313000427A90F7ECF8BDDD3983C9BCABE9F3798D +:103140003C6E39A7F10AF49F7333991E3BB0167297 +:103150002D09797DAD95F8A8F3FCC65A2796DF5A5C +:10316000EBC1F23B6B1584EFAECD4578D4CCF27950 +:10317000843C5106C0BCBAFC4C2647F999625FB545 +:10318000CA0371E969FF78638C0155A367C6942C63 +:10319000F4BB35791AE5D76AF3303A4D3CCF6BA3CF +:1031A000E485EFA8CC2FBB54D39EE48EEA2D83FD9B +:1031B000E07923F39B5DF8FDB61BA72769DA5FDF93 +:1031C0009CA1294FCD5410BFB3A60DD63CBFA96218 +:1031D00084A65CC97F378158E30DEAF329EA19B167 +:1031E0003C6F276B7BAA7E6CDAAD74FC53FB4C58AA +:1031F000AFA7C7517310F7E3C1472D5EB043C7E0D7 +:103200001E192D1F7B4B467D77CC44824EAABA8F68 +:1032100049A409203132793A7D90C9D3B47FC804DA +:10322000F6E1E497163CBFABDA229120DCA1EAA6D6 +:1032300098A7E3AEFA8505D7BD608B4CFC785F4953 +:10324000698573EB558F0FF7C2B9E59CC1E12CB8C6 +:10325000B7D7FDAB38EFA3B4B6AA93BD7F8CEEAF62 +:103260005D90972415E2F9C1E7A52DD506C83790E2 +:10327000F7A5809C7EFEAC8CF194C52BDE2A728271 +:103280005E7BB5F5ED623ACED11619C7FDEC49CBA0 +:103290003619E5DD9706DF75ED5D7708E30CAF794C +:1032A000CAEA32291F7C5A1DCA47BDB39AC5B7FB6B +:1032B000E287AE17E80DFCAAD263BD768B9D9351D1 +:1032C000E53300F44395C98BE7A647379BF03C8F65 +:1032D000EA7F3CFF3FDA926460FAE759E4BBF946C3 +:1032E000C5AC1E77FE66D9C77E174231C37CC9DDE7 +:1032F000B29F8C8532CB5708364B7E765EA3A5EF06 +:10330000CD2BC6E2FD627DFE94805F5099F2ABCE7C +:103310008196BCC0CE67C9E84EA33A7F5CC457888B +:1033200087F52FBEE3533BE8819F4CA0F0848F7D4F +:1033300072F0F4763BEAC7E386978A6EA5F0B3D2C3 +:10334000E0C7464A977AD9FF5026E4EF18366F95C2 +:10335000F05CE4A39FC079FCA74F9BBC28863C5F30 +:103360006BC92F170F3C577E10CC809D2F8753259C +:103370000F7C959760FEC66CD2CAE3032176FE0FE0 +:1033800093A0F871D6B273AC8FC6D837C13DDC2A92 +:10339000DDBDDD8FF8BD856732258D7D3ECECB55F9 +:1033A00006269FE445F6FD45C87B19A2B2A7429FB9 +:1033B000BE90C9F2497AEC2A6945BD52CDBF0F5C77 +:1033C000FBA485DDD3518813E47131230FF90AE49E +:1033D00099CE7789F9E99F023B2F221D68E73E3598 +:1033E00085AA3B72E0FD6D4D6E7CDFE40D81FC72C1 +:1033F0003B60A58A03F4C722C2E6B7AC450A8555EF +:10340000710AF17B1C04EC824ADFF4B5075A3BB029 +:1034100090DBBB854497EFD3A2B54B6509765CD7AB +:1034200092169EF7DC332F999CA538ABF6875E9DEC +:1034300081F396BCA128F35844BAC3F01DE0654F50 +:10344000B1FB40FA79E9D7D1DF79567B674D86EF3A +:1034500009F78CAB9BB7C037810B4A2A3A08BC5797 +:1034600007193EABDB24A4D75FB85F25EED909BAB4 +:103470002F22653340AF2DBA8FEE0B737AF9A0C7B8 +:103480005EEF08A1BFF4196971D828FFD76ED97112 +:10349000FD3878EFE1D7CDC0DF15EEF050838BEE2D +:1034A00017833FFEC9B4AC28F65D67CFFF55F821FE +:1034B0003CCE84EF517C2CDC2E635E83AA1D3FDF63 +:1034C0000F327E0E12CC23AA7953F636D2A735F0EE +:1034D000733E85173E5F819FFFED79EBFD98DC2CF5 +:1034E0009E6F10C38FD1EB973E7E8CCE7EC2BD09FE +:1034F000B097DD292C0FFC94D197E846BDACD3BB27 +:103500002985F8DD51A177ABB9DD13E32C047B47A6 +:10351000CB1F6F79CE01F187BFDCF75C2AE65180C3 +:103520007DC9EBB52FB754B1F16E793E0EF3963EDF +:103530002FEDC807BFAFE291DF3BD4DF35ADF3F825 +:10354000A766C17CB93D5C266FCB76823D0C44CF2B +:10355000ABE8B3FF8AB54EFB79D669D7AE733EAC04 +:1035600053751FA48AAFF3C366B6BE8F36B3F52E6C +:10357000E8B3CE209E83DCF298C51B443F238C76B3 +:10358000FCD80E99C0FDB31E3F4367F74F9396AD2D +:10359000808F652BDF396CA47CB17818C50FE5836B +:1035A0008ABB2D68E717FF8A9D7F7E2A95A4E101DB +:1035B000FCCB61C70FE9F325D43F00FFA2771E3D86 +:1035C000767F7996DAEEF7137FCB791C6A79DBEF99 +:1035D000F1F7A2241FCB875C2EBE03B34BF71D1857 +:1035E000057400BB276F053A651285ED13B5F1D45C +:1035F000BF0DFD72EE4AE4FFEE61EAEFF5D6C58736 +:103600004D90EFDBBD4342BF68D9AA12470981FC48 +:10361000561607BB238BD92FC9E7C3BC170BA56B65 +:103620003C1DEF27590A7BAE38595EF7C304BF3BF8 +:1036300023E6AB7F0EF1712BD83F9B01ED9F7EFD02 +:103640002FF07196C906F4A76BCDCCAFEEE2DF7D0B +:1036500078288BF9D30F6531FF7A1B8F0F74811F88 +:1036600009E7D39759F0F77A08998C71722361FCB6 +:10367000671478731ABFE8916FF497BB33014F73E7 +:10368000498709E839A3789602F7060EA75AF13B55 +:103690004AF4AF0CFA99CDFBD96F62F7040EC31848 +:1036A000745DB3793CF9307C06948E7F788019FD87 +:1036B000D8E00B16F4136E8F67F13E929C68043EBF +:1036C000BF89EBA939132C3E381F983DE1F63280B3 +:1036D000B4BF20A1F8AAB076AF2FA0E33418989D0C +:1036E0006F7013BC2F499A3AC700FE2EA16E31E4C9 +:1036F000C9D3D5EF3C9B742E3ED2DE53A885B8C209 +:1037000078C218AC18F1AB29D79A59FD1B8F1C99B8 +:10371000715F26217F826C26B0338023E08BCA4400 +:10372000DCE7CE843C7E374023F2DBD546123430D2 +:10373000D86CC3EF10B1BC7E710E725D310927D217 +:10374000F585F76AEF51DC10368487C3F98E31DCDA +:103750000EF833581593938E53364D2A04BCD7AECA +:10376000EBDF7C3F7EE4F88CFB26D0327CEF0AE670 +:10377000F94309F3796653A1073E9D6B242FCB854E +:103780008C7EC087756E2588ED56303E17F737045E +:103790005D0A68F76AFCCEE6F3A3FD343BE07D7377 +:1037A000F4B8C9892CB1CF637EDA522EB74B05DF4E +:1037B0003DA595D7E46C2E37E00F52BCCDE6301610 +:1037C000DFBBB2995CB8B2599EF5B71738DE320B41 +:1037D00009E3BA5FB0201DC5B833394CCC1E84FD57 +:1037E000897908FEAD26F5987F53CDE33106AA49C5 +:1037F000304FB7E531CCEFD7E709510709F3CE9643 +:103800006CD73F57C573648D5EC238A764EE5E0007 +:10381000F393BE17E7057E9F6D6EC57880BE9DA9A8 +:103820004542393735537F4AE2E75BB46CD92CE126 +:10383000EF3BCCCEEC1E89DF2BE77E7535A72BD571 +:10384000DE53E11E5035F85378FEC5BF13B585F938 +:103850009146EEFFCEDFACF5336637A9FC4C06345B +:10386000F7EA2DBAFC7013F7373E30778F047DAF3F +:10387000BF67FF8181CD3F984A303F52DCB337723A +:103880007F52F093926DD29C8B89FB9C15A0A7D898 +:10389000F70E74F95436FCEE4A85C4BF57C9E38A63 +:1038A00027A8BF89DF95391487764BC419BB4AEC2A +:1038B0004143227CCE9295E724DE3203FCCC0A877A +:1038C000D908F08CA113C7B955EEB0E7E4F4C6717E +:1038D00037948CDA027943D7678F9869CDC2530E3B +:1038E0007EBFC87B00F2D6AFFD86CE1FCB05337DF1 +:1038F000747FD4F54AF75C2B55D1B55B0B661AA9DA +:103900003DEFBABF7B2B94D76C1D3FD348ED60D7FA +:103910009DDDD9F00DE135D997B3FA06D1DFE53356 +:10392000213FB8EB41569E4DEB83E0E7F27B40151B +:10393000E325D4B36BB8FD11F1A30AC34B0C4E645D +:10394000BFF371BE76B76797AD01FB2CDB8FE2EF5B +:1039500009DCADF8D680DFD394E9AFCEA670C92CD0 +:103960002968867BF16F868671FB15F5772FD66403 +:1039700031B9DC3890F527F045FBA9FB67FA49839C +:103980007E5234FD04FE997E8EF6EDA7E19FE9E7B5 +:10399000FB8AB61FE19F89EFCCFD31C7F708F4BB66 +:1039A000740DDB0F93A336CDFDFF93F5CF0F03BB53 +:1039B0007FF2294B12F0E1D267FE3BBB1AFC3FEECF +:1039C0000F7DD6FEAE19F2BE9747D87771EA22EC8A +:1039D0003B39CB77B69BA7E6411E6BBB79926A7EDB +:1039E000B5BDBF7365BC5AE5C73C9A2DF2B5D9EF9A +:1039F0003A2E7DE613FC9EE05243EBC790E74BC6A0 +:103A0000B3389A7E9D9BF87B87E1DC3F4ABCE0C9D6 +:103A10006CA66FFF31D8F74436851BB309F62FC764 +:103A2000F86ED797BCBF8A78A6C7AB8AEC5685E2FA +:103A30007BCC9BFE46C83BAD7E38A750A6F37822D0 +:103A400073E20EE82F767CB39BC537DB587CB3C29C +:103A5000DDB18A1A29723C7BDE5DD6CB08B9EA015A +:103A6000D273DF0FE286D32CA27CCBCCC91358BC17 +:103A70000CCA07B6D6DD05F2B387FF3EDB9CB12347 +:103A8000E341CE3B73120C4E2AFFBB322A8FC33C5C +:103A9000E68CBD6C2A3C2FB1D88755B2F838F2C7F6 +:103AA000AE8CB2DF037DA13DC43DFCE670CA0D744F +:103AB0001DFE3FC89837EDCF4FF047BBA7F20AB7BE +:103AC00057C7B3999FB6C740E759D83B0F313E75EA +:103AD000CC567540DC6ADD8002F0A353324B3ECBFE +:103AE0001ED33B7E4AA6FF2094C5F874B9F9F0BCFA +:103AF000BFF3788BD3E333A01B85651364F8524280 +:103B00008F5EBF7A7282A67CEDF424E253C74DAF7C +:103B1000CDD094CB2B066BDADFB46084A6BED4D2B2 +:103B200031BAFE02FCFD3AFB9398DF7BA8EDF4DB93 +:103B3000B3C18FDD2E7B25BA9EC52F3CFE36E45FD8 +:103B40009F809F2029647131F6BD467E1E63F41963 +:103B500035E7317B9F3383DFAE8AF3EBEEE5EDC3D0 +:103B600038BEFE3C46E48BFFB3E7310903F5BFE7FF +:103B700079FC55BA323269573BD2A7712FCB636EAD +:103B8000A47E0B7C4FECFB3B2D21F886FBE7FF7DF1 +:103B9000C4ACA8CE65EA220DF8BBBA93761DC173FA +:103BA0009BA7B89FB4BCED4B33DC93FA7EDB0A9441 +:103BB000E7A9547F2552BEE968272377423C39C7DD +:103BC0008E79384B9BAFC03875626436C2DA962B5B +:103BD000B0BF65916BB0BC9CFF9EEF9EF88EA96054 +:103BE00087F7FCDA85FBC1037278D843D08FC58E86 +:103BF000FAA13463CE3AF013F6C407F36EA6E39548 +:103C0000FED7F7310F7DF94E09E3A6A532D923413E +:103C1000FE7D240EFB2B95FF347A057D7ED5246630 +:103C2000574BC1C7A1F572917D137E4F3AC6EFA4E1 +:103C30008D1DC8FC3A53279BF794C82CEC4FD45FDA +:103C4000367090E6BB7CA694EDC6F9B6DEF5983AE0 +:103C5000258457464620ACDB39CB08F9E77FC87D81 +:103C60002C19F044DBE3F7C1FAEAE3B189248ADED8 +:103C700012D0C2F5F06CD0C370FE9EE3BB66600A42 +:103C8000FC1E61A7D10A7AD4667582FF32A3B840C0 +:103C9000A956AD4B7EE946BC076149EE3681FD9ED3 +:103CA0004DA15A6FCF8B61676E1C28F47603426179 +:103CB0008F48E407EC3BA83C3E20E469EA4083E6F9 +:103CC0007B3A1D12938BE0AFD8B940698E7FE940F3 +:103CD000DA4F4709297F16F5684736DC47FF57CD8D +:103CE0009FD2D70AF477183B09C431EAF97C843CA7 +:103CF0009F6FFE7379FB033209005F1CB8FCF20E64 +:103D00001F9D57FB6DA346815D10E3350C6479A6BA +:103D1000C4D9FD0DE61BBE98A0405CBF14CE3C4646 +:103D2000F7FAF3908F08F1C3BA172D8FC20752EB41 +:103D30001C747F6F83BCC0B830F06DFBEFE28C6009 +:103D40003F0A87F81B002F937E377C327CC7C7D78A +:103D5000663112F4837CEBE079ACF99E4F7F0979F0 +:103D6000D4F399BF99C99F9FCB6125E7DBF95C0E1E +:103D70002B8DDE44388F99B74FC67B91F3574B2379 +:103D800077427C40B1E33D7D218742DE4CC097A362 +:103D9000803F195FD6465C5CBE7378BF4C0E4A65A7 +:103DA000966F573AC285FBE7E591246C27E455C826 +:103DB000E91D39FE1DC0D7A58D54BEE938FE750337 +:103DC0004683BCF4F289D909FC44F9C453ADE283BB +:103DD000C6F6AF8CC027A60912F28985C2492A3ED1 +:103DE0002AEBF14F9C5353E93C6634E5E0F79445E8 +:103DF000FDAF7BF8A57FFCFE18978FF9B6F050F069 +:103E00006B4DF5715EF88EFC896405F5D8CA8D128C +:103E1000FE38E14A53D924F02F563E28617C0FFC2E +:103E20000ED03F4507EBCDEA73901B23F9785E7DFA +:103E30004D6408C22732FD2F03FD2B23D7733CE6C8 +:103E4000473DEF3B557F3BC6D54E852C5EF69D31F9 +:103E50006DFC6E8CCF8BE77FA67D26B24D81B89B23 +:103E60005FC6F3BD2CE2BC5762F13B88E789F89B43 +:103E700038A71371380B7C0F5765474F1B5BB26136 +:103E80001FD2271E57C2ECFEF1ED26766FABFD4F19 +:103E900045065AFF698E0FE372AF79FC87613D4B8F +:103EA000AE0E3D63A2E5A5773EE78078B9C067AB6B +:103EB000313C14F64BAD148F101F6CDD2C4F0B31C1 +:103EC0007F2761962ABF22165F2F890C46FC087B4C +:103ED00023F4F7F36B3DB829157AFC7C7648F0F7AC +:103EE000322E07CB400E88DADECC2A83DF3523B9A9 +:103EF00012DE73EDB5374C1E849EA6FC8E72533ACB +:103F0000380BE3EA426FEBEDD16EB9F5DEF1C03765 +:103F10008ADFA950FCFC0F4D62B3890080000000CD +:103F20001F8B080000000000000BB55B0B7854D518 +:103F3000B55E67CE9C994932AF3C0986C43393077E +:103F4000700D383C22E1E1C78140002138C15B455A +:103F50004D65402411131250AE51B8DF9C90808003 +:103F6000D486EA55DA824E28285AB551B0C68A302E +:103F70003CB4A15A1DABADF456E8A014791BB15660 +:103F8000FCA472D7DAFB9CCC9C4982526F874F37D6 +:103F9000EBECB5F75E7BAD7FADBDD63E8789BFFC50 +:103FA0007AFBFF0240ED8B4F4F820C8009570920AE +:103FB0000A00339747CD36A4C16E736FF5205D3A82 +:103FC0004C5E500C70917EE301C4BD5F49F210005D +:103FD000EBF24A50EC00B7625B668FF54B004A3B50 +:103FE000D20051F32C47EC79A66CC2FFD1F32680A6 +:103FF000129C57E73BBF14E01A80DBDCC07F8DC802 +:10400000D41FD7217EE49B6A85397E5C1FCC91BC8E +:10401000F8F92A3C1307CAC85A2C0B6CDEFF2FB9DB +:104020002B44B00969004E7314D28A697E5D6E9587 +:10403000AFF32D725FA1F1BF2342633B8E7F67FC1C +:10404000F8888272ED5936628428C7D61B2F5B1818 +:104050005F453A8E1D09D0F59A35B419E5069C4F97 +:1040600040FE4F5F1B1C5A8B5B3B0C5D17C83EEA42 +:10407000CE1499F655BF2B85F1D727BB4202F6D750 +:104080003BBB8AFC284FD9EEA4300CC57576279926 +:1040900001D7FD26FFF6F1A49FB2DD0327094E14D8 +:1040A0007AA7D50CC8F7409EA2D0F3BEE4D7E54B63 +:1040B0006CF5FD97570AAACB0530BDCCA19AB05D2F +:1040C000783E1F6004C05DABA7B1F6E560362A19E3 +:1040D00060F2F94A00DC5BDDF91BD8F345E75318C1 +:1040E0003DFDC14839ED075E16602BCA5F91F3C3F1 +:1040F0001580F27526C3901DB8AF4E6FAEAF9970A4 +:10410000D93A8DF157FC6ACA54DAD7A21DC84CE3DC +:104110000609A142D2D351BB09B200EEB671F13FFC +:104120006FF860A48CE33F1FE91806C8BA4F6C7F94 +:10413000788CC0ECD949F69CA8E15D3A2F8282F2D6 +:1041400058CF0BACFD400E2C964B181F401AF9436C +:10415000FF9101FB77C1D32B928C78946A3F93082F +:104160004F566CCBE2FAE7683849D4E37F5DA61F6F +:10417000CCFF8E785A43782AF9B7E2690DE9A9177E +:104180003CADFD3E78BA841D7DE089E16CFA9B1C54 +:104190001F90EFF06D0586172677A72537D48C7C06 +:1041A000B7925D095F17A181F43987EC9B1EC3EBC1 +:1041B0000E4FE0F9783B7726ABC58B8BBF8B9D6F9D +:1041C000068A1BB766348082CFE7601B1F37AC645A +:1041D000BFE29EFBDB7E99766EFB8E76DEAFD91951 +:1041E000DC68C791CC7E32D935D1EE6457B27BFD05 +:1041F0002EEBE64BD9757841E09DDEEC0AEE6413B8 +:10420000C919B38BF506C2CDE76133907FF56557C9 +:104210006903D7BB4EAF0C9BA786D87900E99543BD +:10422000185E22DF072F1565ED7FB7A5029C0DDD17 +:10423000ED378F06B8B114BBAEA0EE7B5A95028A5B +:104240002FF8F7316C46056C4C9F9C56974626E13B +:104250007EA73FDCDDAF52FFE4712E3E1EF9715B9D +:10426000DDFC67424B22EB98DCAD5CDF81A8D93FD7 +:10427000248E1E89B4238E2E4DA037727E3A47DCE1 +:104280006C9E10F74F9C5F184EB43E9FE607D055CA +:104290009E8AF69BB94370AF457BDF32EE530BD954 +:1042A000A7A22CFA460EEE57685BEEB70FC6E714CE +:1042B0000751DED4B69656B5401B8FFE53ABA9D13D +:1042C000DA2E2822DAA9B65408793D3DF598EA316C +:1042D0009E67F4331BC78365E4E58D273BB2F15E2F +:1042E000363E6CBD8CF56F1A074AA8973879A587BA +:1042F0009FFF7001697D7ED4DD0DB8BF502FFE3663 +:10430000509B376232D501EAEBEAB60DADB65CB42C +:104310002F707C0C6B7BCCAF721C8292B0DF4BC9D0 +:104320009BA9CB11B75FD9383E7C297DE5F4D097A6 +:10433000868F1A235E5C66FFFECF510E5786E056CD +:10434000D1FE8BFC49EBC045F6D7F1BDD9AF0CC00F +:10435000FD2541375E8DF8FE859FF0BD0874FEADEA +:10436000AD742EF94DDDFC1CEF3B85EEF183D0954D +:104370005DC0C74F6FDBD2AA16337BB07E469B2F42 +:1043800081F7F6047A5C827F68F866FE49711BF556 +:1043900053D84BDCA8D1F47B4680D914F72213798B +:1043A000BE17F1F276B587E7770D1A5FA36EE7E4E3 +:1043B000383D0C88D9197F611864D837D3D3CD190B +:1043C000FABEF7FB67A0DF44D26088803859E10964 +:1043D000B7B6C4E1A4C5B39FE12436DFDE08C5FD4E +:1043E0009B353DADF6EC8B683812C8EFEA1820100B +:1043F000073B0455C47DD6110E7AD9E7AC9E3852DE +:1044000013C62BD225C6CFEE395E49180F52C6E52A +:104410008CD7EC3423C18E5313EC382981AED2E90A +:1044200090219EE9716E5EC7FA955928C75DDB043D +:104430003A26285E5B8461009BDA7EEFB7F727BCE3 +:10444000CA520EC6FCB6B6772236C47225C533866C +:10445000DF48AB8278BB81FC9DD1EFFA1517E1A74D +:10446000616536F23FD5F687561BB2DED2B25EA248 +:104470009CE6976DEFB79A71DE9B47FEEA0D9ACFE7 +:10448000DCF4A7C80CCF25F0DA9AB08F8D09B49A66 +:10449000C0FFC8B7C4F79684F1CB13FAD725D01B59 +:1044A00012E8D5C6F173E70BCC4FE6A2FD4871DFE9 +:1044B000E6377B347B76FB3FEE40B0B33CC980FBF4 +:1044C000E9CD9C7EB3EDA87FB53D8EF61CF393BF7E +:1044D000EB389680FF6ECD0095CE0FA98F78F64A07 +:1044E0005F381A9478DEF1FEBFD25FFB53DE098697 +:1044F00073799F68A4F788BADC7F8FDC63A7873A5B +:10450000FDB99FF2F1E98F19F78575A1467FE69F06 +:1045100084FE3FFDC71AAD76F995B87DEAFCE5FF4C +:10452000BC28D27A473C5DFE2DB8EFAA89E1C206CD +:10453000E4AB4AE32D9E33229D63F536EE4FE5AFA3 +:10454000897E3A67AA92C3854B8AE3F609ED45B4A2 +:10455000CF3DCB44661FB599D723F3C067012C85A7 +:10456000F6B85C8D4F22FFBE6562239D6B871BD31F +:10457000B348FEE15E5EEFED735D997507D27B5245 +:10458000E65864E4DBF3C064D6EE1595555D88E328 +:104590008B6D17D939BF27C5C5F4F3B5E76B7F130A +:1045A000C6AB6F3C325B3F90E6CEEAA07C75AD04B3 +:1045B0005B6592C7F738C3CD8FACC3D6A21C739B83 +:1045C000AECAA2FC6DDEFF5496F747BE792B259F3D +:1045D000C0F86028C91D583BD942FDF35BB4569D15 +:1045E000C2DADDDF6C7F7328F277AD117D9B9179A4 +:1045F000D779AF731ECAF571128FC31F9D2E7092AB +:104600009C8F7A03C95EC2ABD3912CD0E1E1969D19 +:10461000B370DE87F395146F668C7FF737E21CCAA0 +:10462000375F3D3D2F2B8074A697E366D7F9795904 +:10463000F3E2CEFB0567CC4CCFBB2DF23D945FEE91 +:104640004ECE155481E939BD12FD65BE965F235EDD +:104650001AB7F772EE9BBC22D3EB516B237C8C20F4 +:10466000DEF360E63892531F57F27EA0D941781EE0 +:10467000200F8FCFA3B3F2267A48DE18CEB2DE2504 +:10468000DCB03C1AE9E2CD69EB553A0BF761FE4F1D +:10469000726428E5D40FCB9101F34EC86E2F8ABF08 +:1046A0008F88E5A92BB478C0F90EA90E56B71E7AEB +:1046B000362944F5CC21F52F0EB0C7F3733FA97608 +:1046C0003A543A8C3F7138CCA4D7C3E6E0B1FB70C2 +:1046D000DC824D128BA30B36652EEFA27880F62C70 +:1046E000849EEBAEF44A6C9E3EFD44CDAF34F80997 +:1046F000E457D2B9D6979F946FF6566EB1F7ED276F +:10470000D55ADE5EBE49F213CEAB4B1C66B81AEB2F +:10471000EC4DAF6F253C562F4E1A6E45C1AB375945 +:10472000997DA30E87EAC6FE80D3614EC5F6560D6D +:104730000FD1A62456A788591616F7C4552532E975 +:10474000A74C04B30DCF15D1E993FD9C6E7163DDC9 +:10475000B6D2512A937D577865B6DFEE7ED7ECEB63 +:1047600004AC6BCEE13ED271DC89C6871F1D85F299 +:104770009D84D08DA350EFE7C8D0B8CEB91D624854 +:10478000A573C2AC982B30EED500F7F7BA03DB2D3A +:1047900013F0AF350DD533A83EBA33247D14D56A56 +:1047A0009F8BF8DF17F09685F2DBBBB6199FA3C786 +:1047B00058C8AFEADA8DCFEB61DD67E2506ACD1FF2 +:1047C000450769CF71DDC60FFF3C647F1CDFDD5EEE +:1047D00047C6312CC161380C47CDE23AC5AE9B08C3 +:1047E000768D2293575C9114223D8A79FC7C980245 +:1047F00042288900E1C67DE3BA5F060F0ED98F809B +:1048000010EF1FC1F4723488781A88FA70DA18BF72 +:1048100078BF18B2E2BA65E9A0A4923E1FAD047059 +:10482000307DAA6EA4A7643498293E7579B83EE716 +:104830000AE06F677EEFCBA3FA78C1A62466BFEAD1 +:10484000C7EFFCD34F4792BD2A32E2FDE821C25D9B +:10485000099B0F6C69B1793E69FAEF3C92A7EC09AC +:10486000AC2BA9DE14038FDECCE2658A8FC52D77D1 +:10487000F447A308274D29C3D602E1A47F9EB73889 +:1048800036BE7AC5B2223E1EEB5527C5AB24B69F75 +:10489000DA1D568693B96B44859D8FB916763E7E98 +:1048A000D492C4E8DA01A5CCCFE69A2040FBC05CE4 +:1048B000309BC575AE72A8B583B2DD4E717E5D4486 +:1048C0007432FBA89ADD2C649FA7BDE96CFD39A466 +:1048D000633CB70E68389B6BE2F8815D42682B8BB6 +:1048E0004F0D32F97F954960712ED11F7F434918D2 +:1048F000C5C93CDF6D34AEEE21AB6F8587CB20EAB6 +:10490000F2209EEA4C91053FA7797F6D65F71AF575 +:10491000B88F2427AB2F941751FE7A33982D742F1C +:1049200025F378A6CB532F574E219C62FF4133F6D7 +:10493000D739783CAE4BE5F73DE0B085B6C6AF471A +:1049400032E7F371B293FC6C34C30BF9BD09FB3F42 +:1049500005DE5FE62C95A3F8BCD304ABE99E84E4A6 +:10496000193C346E5DA4FB0F253C2E367B1D6487FD +:10497000F41B67D37ACF892C2EA1333D544AF9DF3B +:1049800073E208AA63E7AED957BE81E81786B94932 +:1049900084B9CFBFC7CEA7BB349C4529EFA7F30A84 +:1049A000E917B0FDC8CBF3FB80C8EF713EF2F2FC13 +:1049B0005FD7ABDE5FB74662F6A85BC9F150D7F4AC +:1049C000019BB7CE11C9227BD4BD245D43B83EA55F +:1049D000C93DAF2977DC41C4C73CC9E516F051ADEC +:1049E0005A6121BAB65560B4BE5EDD9A3F66998AB7 +:1049F000F97CD45A351CC5E6CDCCA3F3ECD4B3E98D +:104A00007973E3EC7EAAE565A76C27BF0917BAE9BD +:104A10001E6671926F33F3536E8F532D859BE99E03 +:104A200066BE3BE210B07FFE3DF96974CE1D76870D +:104A30002DD47FB8DD63225A71BBC711AD98AF6624 +:104A4000F4290CE1EDC51A78D14E8B048E9BDA6700 +:104A5000F759BCB89E3B9FEBE7CC73EF15D17D4176 +:104A60005D5EA488CE5FC455510ED9E51981E50974 +:104A70008B9E1595A4A1315C2D225CA1FF2FD470D3 +:104A8000B568C7CBF7929F2E223C0DEF894BAC2B1C +:104A9000F7B3E72FB695031FBF9F70A79FF748B7DF +:104AA0004874AF66D1685C87E8D47C99F901F64F09 +:104AB000E2FD6A313B47206AA17CB85EE47902FAE4 +:104AC0005336E511F51D92DA1D2F695DEA2F8EF53B +:104AD000F7859BE1F926CDCE56761E0DD7F4125DF3 +:104AE000F392937071E6B97D6F8CA1FAEA45C14DDE +:104AF000F1BE871F6A7AAB273D39D93E595E544FC4 +:104B00007A71C6F4D4ED6F1A2EEA81EB41D74BBD12 +:104B100059D393DEAF8D1FA1E9A11634BDEE18C89D +:104B2000FD5DF36FFD1CD1F71748E3E3757CCDD72E +:104B3000F637219F9F9BB5881B5F31C39762B946AB +:104B4000ABFBB1EBCC0B6DECDE48B7A72EF7F27CDC +:104B5000EE0718A795D4B4989DA326A8E9ED9EFA70 +:104B6000264D7F929DC795234D39B735A2FE163E3F +:104B70002BFA98F2A8E68A5BD76A8A3A585E7ABF1F +:104B8000E8A67D95FDB2F23ADAB78E3B699B60EEFE +:104B9000184975462AD3BF2E5F593FFF75A91C7768 +:104BA00061924797F3881066F6525F10DC3CCF8D18 +:104BB0005AE8FE50F7D34479E76BF28A4E618C7065 +:104BC00035C9E393C9BF01CF41268FFDE032B69EC0 +:104BD0007A689967686C9DC3AAC34C7C8781C701BA +:104BE0001D9747B4FB88232B5F6679B0BECEFD3D91 +:104BF000D7093466F45C47E75F92CFCF01DD2F3AE7 +:104C0000D338FECB5A3E607C7A9CA51FDDC3E9FAFF +:104C1000D4F516E79706FDE8FEA5FB936ED77FD582 +:104C2000AF607926CB571FD0F6CD7C242B762E1083 +:104C30003EE9BCB35A109776C3B9C9F29A29033E2C +:104C4000B3047A79AEEB29F179AC9E72E791FEA7B5 +:104C5000D8B34D9407404BF6FE82B8BCEC63BAEF74 +:104C6000A2789A09FC7D06A057C69DE77ABEA69F4A +:104C7000D7F85BD78D4B1C5F9FA19CA0FE9A918BB0 +:104C80008B288FF847BE97E9EF24B45B26E07CB50C +:104C9000C723E54E3956AF5CFBF7B0E8A2FBC01D59 +:104CA0001E43BD507B7A3FF3EF3A88ACA2FA76EE12 +:104CB0009AF72A4691DD9FC67C1CF9E6B77AD8B9E7 +:104CC0007762CBED23A8949DBBB290D1776EBD8364 +:104CD000D36B783E377765C993741FFF7192524E3C +:104CE000F8EE5A2FB8A9DE1ABBB564F92DD83FD615 +:104CF00071652AC97D68CBC71563A86E681499BF12 +:104D0000285B1EBE91FA950ED1475B9D0FEEE5B76D +:104D100010BECD2EE66F87B573A259E2387B578B54 +:104D20001307BA5B8EC3B2E6E62213ADDB86E71348 +:104D3000EEBFCA22B787A9EE7BAD9F6F33E90BCBDD +:104D4000D46CC4D17181E7DF3516B011AE0E489135 +:104D5000A524FF81A58E614D248078E11AF20B45D0 +:104D6000ABB3B06E62EBEAFAD2D78F68FEA2CFA3E4 +:104D70008FEBA47C8ACE0F4DDE132D4FDF4879C216 +:104D8000896D856910A7F713B42FD4F79D18175FA5 +:104D9000ECA5FE3B94AFDF4784585BA3DD1B1E9060 +:104DA0005A07D0FB5BCCE38FC6E7E59FB425D90853 +:104DB0008F98C71B9F4BFC3CC13CDEF01CFDE6A856 +:104DC00031DFD7EA3BB1CA15E8250EE96D629EDFF7 +:104DD000956FCF387615F4C8F375BF4B1CAFE7F568 +:104DE000DDF72C1FDA13DEC78C72C125D63F1D44B8 +:104DF000C360EDB78D7C17E59D94F2CFED11AA2726 +:104E00005BAD6E2BEAF728F915BD077C49E479A262 +:104E10000D7C61C4C5D13F8EF0911F2EF890FBDD53 +:104E200082762144AFD8F7AF7F4024FE3B360AD0CC +:104E30004F88ABB31E597F23B9DD395F60557FE4DE +:104E40003FB74DF0A94C42C59E505FBDD15FEEBB50 +:104E5000BEFABE75957ECF94A8F72B0BB4FACA079D +:104E60003EA3DE797DBE1BE1533ABCA7DE4F0703AC +:104E7000AC8E3A1BAC61EDE8F6B6B21C94FF53E180 +:104E8000C84363C97F1C2E764F723AD8C05E029E1B +:104E9000ED18716126EAE755BBCB4D71E36CB0911B +:104EA0003DEFC68B86CF6B77EC117380F1EF1C8BD7 +:104EB000FCBBEC2E7AADD1CBFB366E5F8064FE7E00 +:104EC00054ABB7EF5E3CAA1F3DD7F77BF23E6E674F +:104ED0005DFE93DB6E77527EBAE7E7E93B47937D51 +:104EE000535C6E8251F506110223008E6DE071E86D +:104EF000B8CDF524DD971EDF784316D58377485D5E +:104F0000161FCEEB7BADD249F7027F33479D6E6A09 +:104F1000913F4C72984322C5BF315381BD071C138A +:104F20003683EC61AFE8194E469F3687C2489FA290 +:104F3000F783746E5F48E6EFE9B5F77E77BCC2EFA2 +:104F4000D3BAEF4FB47B84B1DA7E9715A4E9EF7B37 +:104F5000D8F3B252FEFC938DDB67D27C27B6486E45 +:104F600092F7EC1689CDBF10EB7813E2F038E28DA2 +:104F7000E2D7C2F7451F41FAC4365E272F44DCD280 +:104F80007D71DD6249B1B87AE2B14CE7DB29B0FA54 +:104F90005AC7E5422554CEF4AEE1D3867F2EE29186 +:104FA000910AEDAB481F8938FD57EBFE2584CBDE17 +:104FB000E241020E747DE97888E113182E75BBA7D3 +:104FC000B50F9B90C306A82C5EA8136110E505CD14 +:104FD000161864261C98927DE4E78D36E750BA6770 +:104FE000FA3289B7F79ADCAF53BDFCA54996046C39 +:104FF000FF56E061E3EF157D93899632A2EC7E4087 +:105000002C3329263AEF9AAD2C5E24C69B870A786A +:105010007EEA25B061FB4C819BE78FD0C0F207BDD3 +:10502000C50DE6527E529992F6858C2C3F2F983111 +:105030008BDEE3568E4D5B9A8F99E52F0A66CD3253 +:1050400023AE2B47A4BDE4457AEB163FA7AF4E2B0A +:1050500091906E126E983509F9F716283F2D288920 +:10506000ADA3CF8BCF37D2F3B7FA059EA0B6DE62E1 +:105070005F4DF1FE53A16B91498CF1BF2BC0E157FD +:1050800085181D95208FF2E967E89D6A49DFEDD903 +:1050900002655B412FCFE701AC243DCE537F7B906F +:1050A000F235FCF96D88B7EB35BCCDB3D9C3840BB1 +:1050B000582D9DEEC68597E292CB4CFE3D5333F7BB +:1050C000F5E6F01E1A3F185ADCC76C2C15DC783157 +:1050D000BDEF388F8E09C7F4F9707F9F4AB85FB46F +:1050E000ABA0A0ADD1A504547215C63761E76FBF60 +:1050F000A2799B558826313B54B9097F02044C178D +:10510000B1AD4B413CA09E96BC74663FC1FF4E3D85 +:105110009FCAE6DF672CD5F0787D4479AC0D85FA1F +:105120002408190568EB33B0F7AC19D73D610ABC08 +:105130005D807AAC35BD95B74426BF6D7652FE7260 +:10514000E679D13703C7D56A793B5C10C3E3F179BF +:10515000A767F0E6B57138FA40C3CF694F386F19C9 +:10516000C50F0FAF3BE1C2BEBC65C83FD53BAD84A8 +:10517000CEA54740F97301B3377FDF30D3DCFBF7AF +:10518000177FB882E73BB0859FAF5633A88E34D6E1 +:105190008213F5310D6529455A425A64EFE3438C79 +:1051A0009FF89C94A7C8B767F3F735E0277FD4ED45 +:1051B000A8DBA787DD5064CACF4D3690C85F06C311 +:1051C00046379D3BBAFD268B76166F96BCC4EFE33F +:1051D0009608D19674A29FC3F392F4A5F965CF7394 +:1051E00073AB854C51B3F176169FF4B824E31FC21C +:1051F000CFBFEB5ED252A89D9BC36018E1EADBF201 +:105200001D3D2EA17D1C8571EF7FBFD53EA422DC04 +:105210006FB5B6F664B14A36935E326D3E8ACB4BBB +:1052200036E5F7E3F1F82710CF071BD3193E57797E +:105230004466C78A8E1C90F1D19D1D02C878CECDE0 +:10524000E84867B4F37C7F46573CD56F22E5FFDD25 +:10525000EF2D9F1AC8E8134FBE3932C0EF576C3498 +:10526000BF1F74398ADB291F3A674739D00E7EFB8E +:105270006A765FE887EE3A46B828108D28217F527B +:105280002495DBC5D6C4FC5ADBD71237B7E39203AB +:10529000FCDC5D3281BFDF33AB835D8407A95384BF +:1052A00010D23F3820968491B5598BCBD66C13C859 +:1052B00071F6489293418EABDF4055225427CDD6EC +:1052C00070923228CDD0FF80109048AED9F6050CF0 +:1052D000370EDF1586F92279E59D4C1F019EDFEA26 +:1052E0007802F1B499E4FC629C00E9888B1FCCC67B +:1052F000FEB879A5719F4D12586BCC8B512F472F5B +:105300008527BF8EA7C13098E129413FE81F2CFFB8 +:105310003C87E738A54D985D3C360EE91B3B2508D8 +:10532000C92CDF64FE734E4961F7F72B353DE9B8B0 +:10533000F30F048782F3BA4A8D7A4B558C7A4B9FD0 +:105340006AD453A6DFA8977EB3BD86FEFE81FF30E8 +:10535000F4E7D40C37D0B90D630CFC57364E34D07B +:105360001EF53A037FFEEA5906BAB0F51603FFC0F0 +:105370000DF30CFD83430B0DFD576D5B62A087B4ED +:10538000DF6FE0BFBA6385A17F5878ADA17F44E7A6 +:105390004F0C7449E46706FE5107371BFA47479FD5 +:1053A00031F48F3DFEA281BEB6EB3706FEF1E7F782 +:1053B0001AE809F0A681BFCCF69E819EECFE8B8197 +:1053C0007F4AF6C786FE69F22943FFF4419F1BE836 +:1053D0000ADFD706FEB62B024F1462C89F6D5A77BC +:1053E00048058ACFF28FC7219E6FCA30FBC2C474B2 +:1053F0009975DB53855A9EA6E1F60BB0DF66F27E07 +:105400007B1C5C47794126E17A06D07DEFB9768135 +:10541000E1BAAFF3D985F9AE396E1FA98A0D0BF049 +:10542000189D3ED56DA033FDD906FE7EB365437F42 +:10543000FFC020437F4E8DCF40E736941AF8AF6C03 +:10544000540CB4479D6AE0CF5FED37D085ADB30D06 +:10545000FC0337040CFD83433586FEABB63518E8F4 +:1054600021ED8D06FEAB3B5443FFB0F06A43FF884D +:10547000CE56035D12D960E01F753064E81F1DDD54 +:1054800066E81F7BBCDD405FDBD561E01F7F3E6CC3 +:10549000A027C001037F99ED5D033DD9FD6703FFA0 +:1054A00094EC2386FE69F209437FED29841FE5CF42 +:1054B000AF0AECFDD7F4419F19FAA50CCCD3E97ED5 +:1054C0001A927DF41D7E629EAEE76F15BEAF0CEBA7 +:1054D000DC6B6A60DFC57D69E2799DA3C8CBCE37FE +:1054E000CCDF6D361667F1841AC2AE5A9A283F7522 +:1054F000A902C31DA51A55ECBE3083BD576047A352 +:105500004CDFA1617E83449AC9E3A1FA21259687E5 +:105510000EB838E2BBE7A13945C0F07F5D51C05DF0 +:105520005442F5D80BE5549FDC09EA2A9203CF5781 +:1055300017BD677A3BC9786FA4B7D36CA8BFB8F51D +:105540000E24B50E187E09BF9D663BCDF8BBE7D58E +:10555000EE9504DCDF92B8F91FC2BAC98C25646BE2 +:1055600010FD0BFDF4274137A31F096633FAD1A0C4 +:10557000CCDA0DC141ACFD59D0C7FA37064B19FD45 +:1055800078506174283895B59B837EF67C4B7036D5 +:10559000A39F0C0658BB2D58C3DA67820DACFFD908 +:1055A0006023A39F0FAAAC6D0FAE66CF5F0CB6321F +:1055B0007A477003A37F1D0CB1B623B88DB5BF0920 +:1055C000B6B3FE9DC10E46EF0A86191D0E76327ADD +:1055D0006F30C2E8FDC1838C7E2318656D67F0389B +:1055E0006B7F17EC62FD6F05CF33FAB476DF3FB502 +:1055F00088E75FBA5E741A6012C3839ED7CEA4BADE +:1056000085C0512A9D35D42D09F543A23D4E6AEB44 +:105610004813F1D8A63CE78AA2CDCD71F9FE7F16DA +:10562000F17BC10792414DC2F8D744C53C42B12934 +:105630000D42CDECFD2ACFBBAB355C4206CFB71790 +:105640006872556BFE5042F81CC4F0F9D6E5D44997 +:105650007A9DDC322030BF08DB85B92695DD13D872 +:10566000434594F73F3520504DB83DD770C71B6C6C +:105670003DB7AF8816A9B086336FA2FB9F0322BB4C +:105680002FED6BBD7AEDDF2FF4D9BFEBC4003A8765 +:10569000A67E23B2FBF4B725C76CBA1FB94FD3CB94 +:1056A0007D4526433B34D7DF48727E52D8F0E4DD97 +:1056B000C852B5B8D04579EBF5545AA3DF57822CC0 +:1056C000B1EF6341799D3E99FC01267644DF042ABF +:1056D0006B3B72024D34FE662C20880E8CB1E6F5D1 +:1056E000B69F44791ED470F16091C9D04ECFF5AF0A +:1056F00025FD1C2D540CF2A8B9B2F6BD7BD7E324CE +:10570000D73F5EFBEC98901FD3B77E2FB16A82F62D +:10571000FDD462417F4FCDF3411BE8F920EBAF5A36 +:10572000CAEF677E887519BDAFFC508B87E71A24D6 +:10573000162FAB84641FE5D3E71A960EA4FD24C68A +:10574000CD2A1C67C27155C0BF87A8FA3085E10B0E +:10575000E7037AEF5685993BD57F77E7EAF71E5145 +:105760007B269747A1F7B073765ADBA84E459C3C41 +:10577000CDE2D86851B5609DFCB6295424880C1F31 +:105780001601E5ADCE407CF49217E83858A4FDFB35 +:1057900018FD39E26B3BCD77F6955183D87B935D4D +:1057A000A365D25FB309ED41F735BF13F9771274E2 +:1057B000C54EDF71B88ADBD877FE944490BD463B76 +:1057C000D8FB903D2234BED04BFC7C5FB3DBDBD9F1 +:1057D000D2D4109BD7F89EEFF71AAE7EAFE1AD6240 +:1057E000EF81DC7B71DE459D12AB776064B4D8DF5E +:1057F000CBF74DF58D6FF62F88DB477DC711FE5D2A +:1058000014448BE3BF873AADCDABE349B438026DA6 +:10581000F678F9388E10D7EF911E10D7C728AF9FB2 +:1058200069955D37E1D028AA268C6DE00937FBAE7B +:105830004EFFBE6E3EF8595B8D70201CFBD5F5AC5B +:10584000FE5D08EDECF9A2D2DBF388AE87AE49D954 +:1058500054BFAC6E7A3D1BA5BBA175FD64BA7F9E9B +:10586000159AFB3AB5955B84635477A35F1C25BFFB +:10587000880A0D2BA924BDE5D9092BE99E77A6C876 +:10588000ED006F723B208E1431ADE7FED00F4ED18C +:1058900078F40326BFEE07552B387EF47F8FD1EDC9 +:1058A00017A577FD3587DE7D98BBD87721F5BBAC92 +:1058B0006984AF8554798AF179A17E3EF3BCE02EEC +:1058C000CC0B88EFA4C4ED7FF25012FB772F270595 +:1058D000C4C7F09EB8D7F3CC2F4DFCDEED5E11B7F8 +:1058E0002852BDFC30D3538D2D3494F484E7B33467 +:1058F0009070FD71FBAA6174DF37319447F9AAF407 +:105900008CD5D7EC31C479B89812BBC77B48E2F785 +:105910006A89F2F6C85B4ADFF88AF209AB05547A65 +:105920009F84FECFFDFE3097FF4B5320FB1A91E77B +:105930002BAC8E1EE067F53F64D97C6B859EEBB780 +:1059400068EB76FE93D7D36A2EB0EF7112E510DCC8 +:105950007CDD4479ACC95C0EFDDCE9290FB7832EF0 +:10596000CF90811E7E2EE6296CDF4DA65416BF3ED9 +:105970001503C5A437FD7E4CAF633B3D9FB0B80E09 +:10598000179A07F0EF7BC37D9DA7A7BBEB676FEC72 +:10599000BCD3EF99605CEFF7827E9B5B22BBCD02AC +:1059A0001F8BFB83E1435D3F867BC2FF035073AFD8 +:1059B00086E0390000000000000000000000000048 +:1059C0001F8B080000000000000B7BC4CEC0F0A3BA +:1059D0001E822538106C62711D0B03C30756D2F569 +:1059E000C17025507F0910E703711610A7027102DC +:1059F000104703711810BF069AFD0C881F02F11D95 +:105A000020BE0EC49780F82C109F40B277191B035C +:105A1000C35A36D2EDFF83E4E78940763910CF24AC +:105A2000231C46F1F0C0F23C0C0CDABC08FE3E5ED2 +:105A30005479051E047BB92065766D03EA0700E9F9 +:105A4000CD424A800300000000000000000000007A +:105A50001F8B080000000000000BD57D0B7854D58B +:105A6000B5F03E8F79253393C9839040C493970452 +:105A700009382421F2AA1E0842A4D406F42A5AAEF8 +:105A80000EC823869044B02DB7729B21092F411B6D +:105A9000152D5AB483458B0A36F268D106EEF028EC +:105AA000C65BB4D1A282D536D45B450B4944116F95 +:105AB000B5BF77ADB5F7C9CC393349406BFF7BC370 +:105AC000C7B7B3CFD967EFB5D75E6BEDF5DA3B76E5 +:105AD000D9C5E42B19FB027FA09CA330C60644CA9B +:105AE00051775EBB687B09FCFE99DDFFB8166967DC +:105AF00094173389B1D1F09E653056CAD8954EF8C7 +:105B000015DA95BD70EA0F97A531B69F29CC018FA4 +:105B1000C26A59EAB7A09FFD9F333FBE975F706787 +:105B200075B8F1BB2063E98C5DC1F877E16C2DCBD2 +:105B300057881526E373DD49BF433FB99BEAE0FB75 +:105B4000B39FBAE97B2B1C46C93E9759587CF34555 +:105B50000EF6AB7EDC5120EAD90C066702DE2C1A69 +:105B6000D780F7D0DBEF11BC075480578B33BE13BF +:105B7000E04F8BC0BF9F5D9BC40A39FC7A6904FE6D +:105B80000B8587E60F786EACD7BE9997CFD8BA7AD7 +:105B900046E5DA7A2795ABEB7DDFCCB331B6B23E82 +:105BA00083CA46153E01381AB7B0501050EF2E8404 +:105BB000F646FFF03F21CF69AA3BB37CA6BA3D0D64 +:105BC000FA2988D455B766AA37BA2739036E1C1F3D +:105BD000E6EEC0F19D5402984733001F978A79BAC8 +:105BE000B4E02C06EB91E7B66B2180E352F782E933 +:105BF0006C24B6CB27BCD9055E9764367420BC1FD5 +:105C0000433B06F31DE69EF23EF332F69FD94FF07A +:105C1000796C606C203C5FFDEF751D12F4B732D3D8 +:105C2000AE35407F4FC0F86B1C5178DCAAFEB9033B +:105C3000FA74C23FC4E3D08DBC1E9937D4A3E631B9 +:105C40008C45BDCF8EF473A1FDE6379BEBD67EF37A +:105C5000347D12D2ABD16F3EAB68F0B9FFF7F67B63 +:105C600029E03C3525D2AF314EBFFD023954C0B7D3 +:105C7000F91B59289C1D3B4E9EE62F0FC2FBBC8D85 +:105C80002A0B65F3E769C01779FC57D6E49B94109B +:105C9000288C8587458F93135997BC34FB1C19E8D2 +:105CA000292FE3FA4512D25573D4FAE63066F0CDC7 +:105CB0008FEA7D4C1FCAD8DDF505546EA9F7E9C8F7 +:105CC0002777FF5D99D55218CB8F7F11F2EA1E1B03 +:105CD00023FA0B3ECE428F4BD85FC5AC39505F3FA5 +:105CE0002ABDE82E8D885C4679E61274BC5ED26EC1 +:105CF000C8C1F6AF280CE5A0951FEEB6E9D3B0BF3A +:105D0000B5A364A901F19CC7F921CF1676E662BF5D +:105D1000CD39A382D88FFF55E287BCFC4B3405C632 +:105D20001D9627F861F4834E94873DF35F96AEE7A6 +:105D300015339664A103DF79D2816F42DF74F07569 +:105D4000F1C3D7475FCD7DD2D77AFF7DEF3BE0FD32 +:105D5000963CBBA664C7C295797138A3C21D4B6F30 +:105D6000797982CEFC7DD399B57CB03EC4DE011A30 +:105D7000BABF3E83E8EEDE7A8DCAB5488730EF07BA +:105D8000B0E958A8231DE2B8D71551BDD77D8BAD1A +:105D900020BA4C9FD5CC50FEDE8FF4390E875BA91C +:105DA000EB1360AE79A20E5BA40C7BC0BDF87E1035 +:105DB000D575DCCAEE928CF6CF0675C0778A683F3F +:105DC00075C5B3C146F8FD7E17AF5FBDA2530F6620 +:105DD000457D1F5CA7EB5991F6500F4F52A3FAC3B4 +:105DE000FE0BA3E13948ED8DFEE6AF38A10701BEF9 +:105DF0007B5DBCBFB52B8EFD53FA5F2B053240B5E2 +:105E000060AB2CFDACEDA9DFAB231E8C7172A45FDF +:105E1000E8C1E8F7C16774DD1D797FB9746F10DFE1 +:105E20006F64157912AC43E6F48A0C06EB6FAF6829 +:105E30000EE296DB039FC077647E0F12BCAE0CFEB1 +:105E40007EC48ADFEB8D51EB3369C5CB4184D7D05B +:105E5000731441AFF20B594B8F00BD2A49763FE9CD +:105E60001BD701D364C278B32A980670C969150C90 +:105E7000E58192A6BE1BCD0706FD019C6309CEC934 +:105E800015B37A8133180DA701477F701B70F44E4C +:105E9000A77C7C2B3D4DBA66CCEF26C0FE6D6FB75C +:105EA000F9515D48453C4157ECF35B8336789E3AA7 +:105EB0001370ADD1BACD62B9B1FDA64D1FC4425128 +:105EC000FBF73F7A5DF3B0CEF116885E5FA8CF9501 +:105ED0000644F03856B4B3D29F313F5BCCFCAE35AC +:105EE000CD8FA9818C0A4FFFF3BBD7E59F55E18E7B +:105EF0006DF75B49A2F1274D19F36DC6C7630E908C +:105F00005FC9385E5164BCE469301E76A636C71D91 +:105F10002F65328CE7FCFAF069E547035E7B0CBC29 +:105F2000B79AE05D6B03BE8DB3FE5F37BCE7CB7FF6 +:105F30002E90BFC47F797DF3DF3FBABF64FC153E6E +:105F4000F94865E12B015F775CE524FDDE9073FF86 +:105F50006C7CA5E2A7B07E77BC547CE24A192B404A +:105F6000D72322E3D74A1AED57BDD1776FF3810DBE +:105F7000D6D4CFFFAFF9F486D7AF5B0E9DAF7C6D63 +:105F8000783D81213FAD2C642107F4B1B2ED2AB2F6 +:105F900037571E291BC8A05FDB9AE14C8749256350 +:105FA000FFD0DF4A43CF985CD24FFF5CCF00FB4E5F +:105FB0006F02A56BB7B782F4A29512A3EFD783DE69 +:105FC00016023DA6E4950DCE3958F7EF70CEC1719B +:105FD0006D8CF4E992570EF9CA80CE5D23524629A2 +:105FE00040022B5DC6F3A3E5A8E7DE55289E7B782B +:105FF0007FF0BC02DB2788F6BDC1959007F044AD69 +:106000007FA2BD395011477FD76599F0F390D0BB7F +:10601000EE46BD0B047262424B00F56A57BA5D7BD7 +:106020004C8AFDEE265912F306BD0DEDEC115332EC +:1060300051CF3A30E389157684AF90915C77E5854E +:106040007419EAEE02CEDB0F59F67D37AE21E95D19 +:106050009952994ADF99EA77F7E831D913516FF3EA +:1060600016F0F7650D574C6C8C7ECFFC1371FF3525 +:10607000DE071A4AE97DA6B3E2D804183F13E468A4 +:1060800023E02B536D96EA685DD3E2EA8F1BE63B73 +:10609000678500860D331ECC9E1F673F81D534F186 +:1060A000E9A079663E7B48E0EF6E81CF4CE4F5D104 +:1060B000820E41BEB978D31EF9E61ACAE55B4241A9 +:1060C000F30AC4F7A079CC8FFAF686194F90DE6AEE +:1060D0008CE32A30CBB94CD53CAFAF6B3E1B99FE5D +:1060E0001D7974EFFD5BF96C230BDC8AED33C57E03 +:1060F0009E5010920285FDCFDF3ADFDEE6FD2DC413 +:10610000271FA74E1E103BCE3F0B2F996E18A7E4FA +:106110001F3F4EC23CB3BC3C5FBCC33E20E88C2951 +:10612000B81F58EDAB84129FC464AAB6A31D4EF2EB +:106130001BE0F6B0E6F24B80DE522B56DD2E83DDFF +:10614000EC79EBEAF7D1CE4EED9843F676536151F8 +:10615000DB246897E4F7CD984274CA08CF6BB1335B +:10616000E2BBAA1513615E8D8CF3DD66F996895C3E +:106170003FD069BDBF2B70062BAEA950477665395D +:10618000F1E66167613E6FE90B47ECF7BDCDDF16C5 +:10619000F94EF8FF9690DFB4BFEFD8743BF9118346 +:1061A000F00FEDD2644B3F49BA3DE2676488A7A87F +:1061B0003ABCFF6D0F5FDFFE4F19CFC7EE736A4029 +:1061C0000AB63CD987F67A12F325AB2867278342B3 +:1061D00000A2D897D61D94B5FED7A589B1F29642F4 +:1061E0004E7733A2F4DC0E99EBC969332767AF848D +:1061F0007ECF9670BF70AA0FFE17C5CE671DEC6BE1 +:10620000E1283FC7BAC2C7887F1B819E72802F8258 +:106210008532F9B7D7E6EDF045F3B5AC18FE6D2B36 +:106220007D304D2D15FA1FE047C99375D7C8AF4E85 +:106230001FCA97A48FC4E951DFB10B5FAF24E5C239 +:10624000E8E3AB8E67AC6B2C5F71FD246DE63C27F9 +:10625000EA3BAB326626C593B3BDAFEB7DB4AEA8C7 +:106260004F84E2F49FA64871FD39567D9EB1A5A6E4 +:10627000F5520696CEDADCD7BAA599F161F4EB5A5D +:10628000A668FF85C24BF5915FDC29FA5BABDD1791 +:10629000C4FDF32CEEED800FA5795418F53D96C79B +:1062A000FC8FF326A487B8343D443A24CADDD208D3 +:1062B0007CF62CD9349E9A9660C2379B05DA761408 +:1062C000FCAE657682C389E3C1388A0F3A94D0FF69 +:1062D000CFC22E2FF548FDE1505FE462FD4E131D45 +:1062E000ACCE2A8ABBDFA9625DD16CE5F47AE7F90E +:1062F000C917EB78D799E13DEFEFDCAAF66E1CFFEA +:1063000071EC772A7BD7C01720F1961E7AE7EBB4A1 +:10631000CAC6F64849200F32AE67010DEAF80A36C0 +:10632000EB35588E453A2CF2915EB05552114E62C3 +:10633000690DFF737DBE10955BE84F7606084F8AA6 +:106340005B67D45E3B3F7DFF9CD0AFD3843E6FBC88 +:10635000FFA162A77E5556C1D06E3EF7F6D40CEA77 +:10636000578747A51138ACFD162A811F2A0390ECE8 +:10637000383CF801FA09584701F9B5F305CECE3D8E +:10638000303389F5C15F0F59F8EB2189C3C92ACE93 +:10639000CFCE380763B6637B359040F1B29305C426 +:1063A00007B962FC27D6CF4DC0F19FD8D8379F1BC5 +:1063B00070FCB4DEC9C2A0A786EA7D541AEF43C2BE +:1063C000DFBF59D831C6F3738A4C70EC137CFF845D +:1063D000B32281FCE7076F9C360CF82BE7A8E24755 +:1063E0001D4F5BCB52FA1A3F3B68E637A6CCEE1343 +:1063F000DE656F4D9C71288A1F7FA178D2DE1D0E4D +:10640000BF5CCE2E47FAEBEFFB73F5FA8C43F95FD6 +:106410001D2F9B85FD79AEF1772B48CF095F49FC95 +:106420009923E448CE3C2E0F72AB594843FEFDFC45 +:106430000B164D1F6099109E32AB558DFC4D4C775D +:10644000CF81F743C5DB4C65BA8C5BF850D4BF50A5 +:106450008E6CE2FE73C3CF0FEB7E17CAB9CDAF29A6 +:10646000640BE7556A0DB8DE39EBCDFEFDC12CCAD1 +:10647000EF8EFE7AA1D7655AFCF85F751D3A701D44 +:1064800012FFF9EB105219D19D51D72456116FFF0D +:10649000FB44D0A9B6E210B743C0F87B272A1E01FF +:1064A000EB99829BC04F83F74D44BB35B886F9F317 +:1064B000E3C84B9B9A48746F637A7828FA0FE65CBE +:1064C000DFB117E5D50466925F71E4864DC5EFD262 +:1064D000B8DC080567F2F27385E265F9EB5908E369 +:1064E0005B9337D4ED47BF5E6635B79B33D7042542 +:1064F0003BD473EA981F87C9AD64BCFD6C16D27992 +:10650000BCE66806D0CD104137430C7A5966A69791 +:10651000C17596B8D01A737D20D2057C37D0422F32 +:10652000D67E723446F1B8BCF5328F17CD32C77DB6 +:10653000F259F7FB3F0778F30FB9FD61161B6FB2F5 +:10654000F6AFB24001E265F70FDDFF590013FCD949 +:10655000FA49A98817902749244F2AE2DB3D31F4F4 +:106560006AE81BBDB48FC84FDEAEB7F7ABF2D39766 +:10657000CE0538D67A7446E307B349AE2B225E794E +:1065800030F37A6707FA6DDC4524DFF7631DFD3CC5 +:1065900019970C8C96F78AF02319F546E147B28ECD +:1065A0003755E57AF07B4C9F8A7818E50864605C83 +:1065B000CF9691BE730E8C67F381BE15E7BBB16AAF +:1065C000029FAFA6FE2D1AFFB071FB481E32BE1F00 +:1065D0003377CA79E1A3440DDCA442199C04660414 +:1065E000D27F0E0B35E2FAD635F3FD2DD2EE16D161 +:1065F0002E8879053DED02D06E84A9DD3C9C0FB458 +:10660000D34DED2A62DADD26FA63A671F598716B37 +:10661000447FA4CFF5B4F3C7F4B754B4233DB0A777 +:106620009D16D3DF3231AE6E6AE78B69F7EF067CD9 +:10663000A6719979DC9EF7A576E33DF9630FE44FE7 +:10664000217A39943FA57C2E8CB3F4451B97115BBE +:10665000793E874157FB45BB26A4AB42CC5B6163C7 +:10666000AA294F85E7AD34BA673A0351CF7BE8CA10 +:106670003DD317FFF95C537B758D8BE9C5F49CDA2C +:1066800037FD5D11F1AA1F4C427FEBEA3459F8DB6C +:10669000AE69D05590630354537D4D86786FBBA689 +:1066A000810262223E02B2F29B8551FCDD33FE3F45 +:1066B0000B7EE13F8EC03FDB02FF6C33FCA2EECCD1 +:1066C000E4EFD595B327E17C0CFFF2D9A6E50D41A7 +:1066D000F7FFE6F95559E65765995F95697EF69596 +:1066E00055938279FF97E6B7CC32BF6596F92D3383 +:1066F000CDCFB972D905AD9FB5DDDDB66692B76B6A +:10670000F35F27FD7FAD88E326ACD41B56E07BE02A +:10671000ED76EA4F23F93E8AE99FA33CE8EFBB47B9 +:10672000548DE482D323935C60F9F6507E36876BF8 +:1067300026C885E7541F97DF02CED72CF50F2D759D +:10674000F8E56FB86FFA9861475AE47C3FFBDACA04 +:106750004CBE9FACF2F8E5E87D4D15B83938A094F1 +:10676000E44FA38FCB9FFD03843C4A837D8DFC4483 +:106770001924AF6C425EDD57CFF3D89A457E506343 +:106780005A11E1A759D80B2C9465DA370F4C9CD2DB +:10679000867EAB334779DEE23A1BD7C756D6339DA8 +:1067A000E8ABDE49F945FBA0DF003468057D0FCB7F +:1067B000E741DFC3724F7D0695BFACD7A8DC01E38C +:1067C00062F94CBD9F0560FC6DF563A8FC31EA8B56 +:1067D000503E20F4C52BD264F2576CAE872D339F08 +:1067E000F4482A1FA9F78D5561BC9FD46750FD233B +:1067F00069E6581BD9AD1D8D4900E7EE57F3285FB8 +:1068000069429A4AFB2F53C34A5249E4B981D78F50 +:10681000A44957E077E33264DECE196AF4C66F57B5 +:1068200086EDC664A8040F7307156F5ADC76E5364B +:10683000C04BA95BF4E70B347AE2F7F72D6C57E411 +:1068400016FDA5698DEEF8FDCDC47147FA381E58C6 +:1068500046474362FC763760BB429F986F56584E5E +:106860008C3FEE6C1C3725A53980F1AD2B6733D2F8 +:10687000476D69DA66292A3E141A50C164A0F39460 +:10688000D4E63A6CF78D809FE5C0F89AD7CF64A024 +:10689000679B1BDE17624E138F478DBF0EDEA33E34 +:1068A0008CEF4744BDC7EFA11C3B4B7C9F647EDF50 +:1068B000A397AF613D793C98BC646B32D79365CEAA +:1068C0009FCB571E98847C9F6CE7EF7F8A75D4B767 +:1068D0009633431EF1F609FCFD8F8CF65EFEFE1723 +:1068E000A27D4A0A9FB76B8A338471B147BE7B4948 +:1068F000E6DCC2C87C2FFA5EC1B0B951F37BE47B01 +:10690000E332E7BA23F3B9E8FB1386CDEDC3EE49D2 +:106910002D977B7264516E25371792FC1CE5A820D9 +:10692000B9336A60A98EFCACACE770FD87EDAE862A +:10693000863C822B88F2C680EB278BCD700DAE3162 +:10694000C3F5931A335C836BFB866B9D8DCBB5DEF1 +:10695000E083F1F5E8F11FFD37F3F8437E601EFF99 +:10696000D11F98C71F72E7571E3F1CBD2E9B6E3765 +:106970008F9FB5C43CFEA625E6F1B3967EB5F1FF28 +:1069800051FA78922D70C426F45D255AEFAC0B981D +:10699000F45368F78A681754A2F5D840C0A49F4200 +:1069A000BBD76D42DF35B5AB8869F707D11F338D93 +:1069B000ABC78CDB21FA0BCBD1FDF963FAFB8B68FB +:1069C0001794A3FBD362FAFBC080CFD4CE17D3AE0B +:1069D0004BB463A67199795CF82950A19FEFB30479 +:1069E0003FFA47964D5E4371AF812C20A1BFCF97F0 +:1069F000CA461D82EF592ECFBF4F9EB2EC62B43B08 +:106A0000D7249BFD5CE9766E9FD9EC0A95BE44566F +:106A100047F900CE60E68CA87C8B6A3BDFCF7ADE3C +:106A2000BB8399D746BD1F28BE5F23E2D469F6D247 +:106A300046942BBEC1D03E8EBF22538C6BBC67697F +:106A4000FE761DE0DDF8AF3347A3BF2832AE8DB729 +:106A5000BB588C9B151FAE35D97CDC45386E213E6A +:106A600037F48B6026E1D7C74BE3F9839EEF49FFEC +:106A70000578593DD9292B49F07E3DF76F1A7EF6EE +:106A8000647B9D13F3761B2F92D963D82EAB6F3F97 +:106A90004E53BDD9DFA9FA2A74B4F70655FA8A1401 +:106AA000D6FB770F97CBE5F1E20DA3C5BC9A2A2759 +:106AB00035E7C1F8EC90D96F0B84CDA2F3610A954C +:106AC000C0687B3CBF6D538129AF3E7950DF7EDBD0 +:106AD00046A15FF4CC033A8AB77E370AF8D8C602DB +:106AE000939E959C3293F4ABE486AB9DBE38DFADAC +:106AF000B5F4EF6233756C9798D6CC64EE5C34E9EC +:106B0000614DBEC7F83E94093209E33F693BC2C8F4 +:106B10003F674BF8790A3523149428CEC1E7896A78 +:106B200025FE24AAE1A00CED076D54593895B1FB60 +:106B3000E5C08D881F575E33F9C7549F2E219ECE26 +:106B4000D94257D379025017E3E57FCCB3733FF0B6 +:106B5000C3DACCDF65C759C7DBEC9A492F1DF4A90E +:106B60009D858B7B6F1F69C7E1EAA1D30CA04FE421 +:106B70006F8DD3E9ED8ABED84EFA5A968FFC8E8679 +:106B80007C35F85FC4B7E78E61E247BBE10F308F19 +:106B9000DBDA6C3CBFEF73681D15F7B94DF8BFE643 +:106BA0008A78F73C56E1C597A7995C8E7C759ABDAB +:106BB000EA2D8E5AAFB5763B1F678D8DFC5B463C48 +:106BC000777EB3CDE4EF5AB8D15C5FC066A6A35C14 +:106BD0005AB0C1C6F07CC76D167FD8BFE17C615E3C +:106BE0000B59DD2AD4D38DFCA0B93EA662FEF7E294 +:106BF0005F3D528A7943CD769EAFF301D08B16C5A7 +:106C00005755EE901DEDF97776155F3F9EE1F7A1A0 +:106C10005583509E26B3B8E78C6E5D6386AF3FF810 +:106C2000ADF032D640F0F60687BA558AEBBF7AD47B +:106C30002E99E244CB9CDE910CE4CC39172F7BFCDF +:106C4000297F74917CDF27E80836C0CBB89CAFBBA6 +:106C50001CCBFEBE3BD8CB778B9D1D76E48F5AB5FF +:106C6000AE5C92237126872DA00F86EF6C7B268663 +:106C7000073353BB35E7D9AE4DCA39AF76E5721F3E +:106C8000FD750A79F9C2B69FD9D1BF78FAA913D791 +:106C9000201F2EFAB5C29CD0AE739B8785715F50C2 +:106CA0004376942755BB94B871598AFCC3FC17FDF1 +:106CB000C24372A26A8723341DBEAFFAE53B231993 +:106CC000E0A1B3A1FBF060DC479F92787C34D8311F +:106CD00012F7AD2A95DD122F4FEC84A0BB53CF25C0 +:106CE000CEC27595B6EEBF99FA6DB9C1E688920F1E +:106CF000C7C4BE04EDB87FED4929941F477E18F143 +:106D0000AC534F4A1CBE3DB6900BE1DBBAD91E0016 +:106D1000386AB77E487454F68BED5EC443ED1EC5E9 +:106D2000E4F7ADDDAA841D23A93C8125C65124E0EA +:106D3000EB1AC6E563CDAEC5E40FAF6959F7A1E222 +:106D4000C5EFCDF40C78F18711AF6F28FEE958DF5D +:106D5000F973AF06A8FAA0FD712FE215FA9D634FF3 +:106D6000C278AED98F8DFD7F9A12DB1F63DD76A4CA +:106D7000AFDA96B57C3C0BBF7C80BF64C6C64F9C27 +:106D80000E4B1C6B6BEA79E9898BB69F7D3408E367 +:106D90009DDAF1D74783B87FFFBF8F1EBD13F59AE9 +:106DA0007D2E1FF27BED53AF7959D43E98E3E07C02 +:106DB000D7F9E4CF9F7818F8A4F3B8838EEE75EE78 +:106DC0007D6F8806F3ED7CF6BFD335687FC7DEABF9 +:106DD000C8EEBF6377D9C0BEF643A4D350F43917C9 +:106DE00091C7A4ED9150D902435E94967539B84B82 +:106DF000612E80F3F4314708F39A6BE1D9B2225C3B +:106E0000A7C5247FB1BE1CF05BB36DF587CAC878F7 +:106E1000780E0E9631C79E01BB64E03A5FFBED6FC2 +:106E2000946069A338492DEB26F969FDAEF628ACCC +:106E3000E765BDAFDF59F6B91D8378B5DBD6F271D2 +:106E40002DEB771A7F191BBB7EBA65FDCEB2EA9F88 +:106E50003E8C2F77A5C68DE71AF1AFC5BBFFA54FB6 +:106E6000BDC99003FDE1B752E270791C7A8503F940 +:106E700069C7D34F3C9CC6D7773A20A473FBD9216E +:106E80000CE8E3A4ADFB66948FDD7B1D3EDCCFAB4D +:106E9000F6BE41FCD5B9FB15BB46F291B925D0131E +:106EA0003A59CF4F3BEA0D3512AFD46EF1841DDE57 +:106EB000C83AD58466946B5E7A7E829E8738DDD729 +:106EC00084F65F27C559B7D58E1C2E8F433C696F5A +:106ED000F1963FD899DBBC9ED2185CC71353F0796A +:106EE0006FEB68CCDF87F3BF3C6A3DB7707EED8DFA +:106EF0002F3B373B54CC4730D6B7D3C6F5FDDA909D +:106F0000F4068BC3AFC6FE76A1F1D00687251E2AF4 +:106F1000E6DB1F3FF73F8F0BC3D3124CAA1C1D8B20 +:106F2000AF539FC797EF8F382401475DF9A0DCD896 +:106F3000FD496515C1C1D911784F8973B3A79E5218 +:106F4000424178BEAAE520C969AB5CA8E9454F7EFD +:106F5000C6186FCFFE9128BF4E1D788EE8B066DB55 +:106F6000093BDA4787B7EEB4771446E81EE57F742D +:106F70005EE4A967F68F24398DFDC7599F5F0B79B1 +:106F800057DB6AEEBF76DB87A6FE17055BECE417DE +:106F9000ED679C0F54FD069CEF07ED368679F71FD1 +:106FA000B428E5F1F49B90C366CA835AE5293D866F +:106FB0007E4525C5AEA1BC6B5AA1BF11A4738F3607 +:106FC0007EEE51D58F39802F1B93ED1ADAAB4D9E93 +:106FD000EB991625B79B2DF8F4A5F926625CCD3701 +:106FE000B9A224DA7E32E04FD66513FC7778CA075F +:106FF000E27909B4C3344C3250FDE45756BC53CA4D +:10700000713E8A4FF6B9E2EECFBC3FF4B721FDDB0B +:107010007C32D3A2E86B54D9F5C3D1D5A632CD9436 +:10702000BF7AEF641EC735E67FEF456C1303B97B6B +:10703000AFD4DD86F9ECC1AB795E201376BA17EDDB +:10704000F4EC587D8EE9BA86F287C40F6FCF7423B3 +:107050007F147EBE0FE0C898BF23FB4999FFBEA2F4 +:10706000533E8F1DC7CD45FB2944CF135998EA8A5B +:1070700093CB1F0FABA3E749ACA319CF30BDEDA84D +:10708000F8D401CFEF2B4F9138DC61CAD74816E313 +:10709000C88959997DF13F9BAC9E8AF6FB38D8266A +:1070A000B24BD0EDF8456A040F463E9CD1EFBDAE21 +:1070B0000912EE3738BFC178AE479C9FF7F5CC5721 +:1070C000A7FA00A36E19075BFA4AC5164BAC1890D5 +:1070D00054056F0D68263FC720D64265166BA73250 +:1070E000C5E9935482EF2DF24BC9ECCFEC8B440BE6 +:1070F0007CE7A18F9F93F5E301281B6DE2F9DB9EEE +:10710000D0E350DF90CC4CE783739D9CBF2F77CAB0 +:10711000865F26106D7735B26A9ABB2B8D1F63315F +:10712000BEBBDE1918EE8CA227C5DDCEF3BE84FDF2 +:107130006BD8EB5729CB29FEBE3A83DBD5BDADCF4B +:10714000CAFA0A935D6D2D9B0738E76C66043FF71A +:1071500053494E7E7E59679A2F9AFE605C67697428 +:107160003EA3AE937D2FDEDB607AF8D28178546245 +:10717000E96F06D2DF68A4BF0ED14937F9296E57EF +:107180000257E37C33F2EA24FE3C2071BF97AEE065 +:107190007CD345FF72627566A08F79B259401F514A +:1071A000792D1B84FDA8AA4C4D284278368975B7E5 +:1071B000D2A5393FD5D0D7DCA2E6107972BF2979A4 +:1071C00095CEA3A8696ECA4F719734DD8EE77C55C2 +:1071D00056E743F9E936F24FFC3C9FD0B08B5D0592 +:1071E000E63C4E87256FD526ECEF983C6EB1EFDE7E +:1071F000830FE2E8C3D67DF77667FC3C2436267E13 +:10720000BEA0A1879D2FDD5BEDC86A67FB611ADC1C +:10721000A7539EA52AFC0D13AFF3911FBC6B9BC413 +:10722000CFAD59E8A86B47D2489487C8BF78CF45FF +:10723000A2782E6DDBBF1FF5A6262FD3935348CE21 +:10724000694A2E9E971AE594A05CBCEBC3977F8D8C +:10725000FEF55685E1D6DCE536E2937A322E5622EB +:107260005B6F5ADF0B9D4F6C5C91F3DB129FC16F1C +:107270006EFAFECC3689CE4F296CF88FF1FC436D47 +:107280009B8D85E0FD19C6FB3FB389EB030B5F8443 +:1072900051F03CA8181FF7A5E8FD23B53C8169D142 +:1072A000793C41BD1DCFFFCF13F8185091627AFF92 +:1072B000D7B9E56DE49F09F07B0006CE1A64EA6F4A +:1072C00091B27C2825E1093F8606FF90FE8CF99F4C +:1072D000930376BE4F542485499F01FB17ED86909A +:1072E00044F94A567F47CD1E89F6A7DB607FC2F37B +:1072F00038B7852CF6A3258FCEC0B7952E0F3985CC +:107300007DE066EE5EF0EA0F97507C94F86AC98BD8 +:107310003C2F6CC976294479CC1D439318E159213F +:10732000BFD17BACEE41D83922F46BC19B23C38C17 +:10733000679766C673628119AF1EBF198F563C27C7 +:107340008DC931B55FA454DB89C8049E0BE01FE2F0 +:1073500019E420CDA306E611D662F159D97AEF2AB5 +:10736000F46FF48B470BFE4E59F07796B5EEE76F4E +:107370005985339D589BE69DA986897FACFC66E0C4 +:1073800029CBD73E919EF93DE42FCE109D48F3F8CE +:1073900077839C2D9C798AFCC46F467E7062CF7E79 +:1073A000F90EFB02CAA5330E9D98CB62F96B1396BA +:1073B000C0D72DF54EDFBC7C8C4F33DF3C1BC6ABFA +:1073C0007D54C6D947A97FA047DA0FEEC1B8641A29 +:1073D000F2B54AF12B5CAAE9504F6CB5F9D06F7940 +:1073E0004F51F735A8B7D7CEE7798E372770FFEB27 +:1073F0009204BEBFDA12785EF35D1532D3D1BE6F50 +:10740000554212FA8B7CFA8B57A2DED56AD3685F9D +:10741000F375BFFC1D7A5FECC3F86EA6DC3C0AE195 +:1074200080F6E46FEF6A7DC77B6B94BED3B9E7FE4D +:1074300061B8EF3C24B3CA787A7CBE8BC3D159F0D3 +:10744000E77424C7C5CE6EB2A35777D455E0BC0C01 +:107450003BC2BE8BFBB76AF6CC207DF2D0027E1E0B +:1074600073F7297E1E738A32FB9B23A03EF6359567 +:10747000CB4DA64F9F93CE5328701D3760BE24F28C +:10748000C17FC9A106C24FF3EF314ED5F81795A1C0 +:10749000FE5852B780F69F5F7BA7B46159AAB71414 +:1074A000235F4F6E4D9E88E7646ADFE27995A3DB28 +:1074B000CDFE1CA6541F443FD8D9637C5BBEFC980C +:1074C0006AB5BB14DC8FC776989F8FEF876ECB5C55 +:1074D000623FF2B2F40BC98BFD91AC4F73917F9474 +:1074E0009FE3F2ABF1EDA74713B87D037891504EBF +:1074F0007575337F03E0A96BDE209A6FD7C7FC6AEE +:10750000A6AECF95F278F6D12D2E4E2F0FD979DC7D +:10751000F6A105EED00A98C781055517A35DF4C9F9 +:10752000BF052E8E17A788D8072C49A63D4F4F625E +:1075300063902F9AF8F932D69C19EFFCBCC10F0664 +:107540007F187C91B9202110CF7FF98E8BCF6FD21D +:107550008202CA83EDDC27518CA7B301E0EA038FD6 +:1075600041D63018E1A9DDF311F9179CADF1FDD03A +:10757000F5784803E9B621B8623CE0EB7BC0D44122 +:10758000E4077B7376BCFE836C03F99B16B834E288 +:10759000B74E27B7A399DA9C39D3837C5276F52A64 +:1075A00080F361E03F24F9876C7E823BB89831F22A +:1075B000AFAA9CFFB3AE619BEF8AB2B7D6BA263EA4 +:1075C000E082FE1E70F178476AC02F21DCFEBF9F6B +:1075D000F362FF5D9F3A68FD06093F8FF15D8BC046 +:1075E0004F5982FE23FC9E55A69130F407BCBE790C +:1075F000B0FF5FB607F01D27BFCBD077520220FB4C +:10760000009E14B74CE756D0DE427BA296193F414C +:10761000523E0DFEC34366783ECB90B752AB14F694 +:1076200080DC2C71BAC3E84F49A98479633C8A395C +:10763000797FED667D14252FCA5D94013C599EDB50 +:107640003B861C36E477533297834DF7AAA146094F +:10765000D3DF3B5CE83FCED6B549985A95A26A94F1 +:10766000E7705125F3075148E63E92DCA3F78C679B +:10767000ECD9BF2B71FD1B275DDC1E294B08FC0AD2 +:10768000F135B2ADFB00AA4F7E174BC5F59E22F433 +:107690009BB1A7B93C32F2FA6B85BD619547CF012A +:1076A0009DA3C018FB0DBEEF8D3DEDF623FDF4C884 +:1076B000A10553681F2D6A2D3E88F939456F717EEB +:1076C0006442FE80F54678296D0B2A880FABDCE911 +:1076D0004FDE18F2C4BACEA05CF7D4B30029C56D52 +:1076E000C06751FBB7554E1D7389FD55C8A9B36CD2 +:1076F000C2C0ABB4083D152DF31F7444D18F21A730 +:1077000022F414223AB48E2331674FDD978BF2E5D1 +:1077100088827E90AE893C3EB942F051F2C7A1AB5F +:1077200071FE1B5AA7BA90EE77B4953991AD966465 +:10773000F0735EEAFEEB824C904F745CD7C69C1AE5 +:107740009E291F0F2B8FF8507C508F9AD79966492E +:107750009C73D492AE8B733F82512EC9E0E7B8760A +:10776000B4E524713B334CEBDE43F7C20F61F08587 +:1077700041EF56FA36F8A19171BF84A13F28528B90 +:10778000B00BCD7E8146C3CF1174519CF80EA10F72 +:1077900036BA2F5937017E6D0A4FF2615CE20E4F07 +:1077A0000EE533DF3180E3CD8A07A3ACFD14F4C3CB +:1077B000A8BCF35AB59BFC5AB59FDA4DCF0DBCF669 +:1077C000860F03AFE310AFD297C7EBA7B8BEA36392 +:1077D000F1FB65E79DB5644CDCF372FF57E63D9E17 +:1077E000057EDD4176173FB761D097212F4A976E0E +:1077F000CC24E26837DFEB65C891317BEA0EA28AC0 +:1078000068951397B5B26B114F63C32AC3A32EFDBE +:10781000C98D8FF1974C3A7F716302F0DFA817662C +:107820002DDA068F466A2C753A0035B25D2539C6C9 +:10783000DACF2F0ED512FE381DFD8B865E1A8357C8 +:10784000A1971AFB8B11075A9710A8C4F1A53DC048 +:10785000375ECC3FE5F6EE5A57605102B44F0498BC +:107860001330D7AE209CCDED53335FF6C687891613 +:107870003E6B01BCD03904D8E7F2A558388CF1F33F +:107880001292399C406DA8BF6495323E580DBFCF0F +:107890002E6B240BE03E8CC736719E6B85FE759770 +:1078A000A55CEBAA68C079D9541674147D79B80D1B +:1078B000BFE0BA043D88F87096EB348FC13EE647CE +:1078C000BD7EB0DA22F9018E946A4DEA71D618FBBA +:1078D000379EFB99AE4D44BA189CC7E83CEC60D487 +:1078E00083E2ACCFA6041EAF5DECEC388C21F3DA5A +:1078F000E975E5DE3EE2D3917B06FCC24F65CEC35F +:10790000E8DAFBC64518977CFBDF3FF260DCE94F05 +:107910006AB707E13CB9FCF71EBCBFE5EDE5DCCE7C +:10792000B8D9A2CFEC14F84B4EAC780AF1774BFDE6 +:10793000DF4BA3F99D2DE37194DB420A1A9D3DF4C0 +:10794000BD686B22F9E68CFAE2965453DDA0D3C5EC +:107950000E9E27659DFFFBC28EBA6DDB66FB600D38 +:10796000C70FB422BE4F0A7DEDE42E0FF9330C7819 +:10797000E66E1B65473CFCA9D521E2F0ED368E7F13 +:107980007D3AC6CF026229AC701EDE9748FDCD7FDE +:107990004021FD620E8CB50CE83BD07A1BD9D9D6BC +:1079A00079CC7F5B9B3210D66FFE5A89F4526CBF44 +:1079B0001CE821B06C35C5D9ACF39C13B4C6339721 +:1079C000939D6ECDF398C7B47513B2E3E47BB4F224 +:1079D00038F9C27EEC9A3F26087DA1945D8EF9E8C5 +:1079E0006759E18F0AB5FEED9A93F58C92B43EA8E3 +:1079F000775279AADE47E553091A8F67EFD97F9846 +:107A0000E84B6D2F457EDFD1F64EE24D5A446E5F56 +:107A1000B1F9A3833F817A31E3FE1BC33F3E5BE0B4 +:107A2000FB4A21BF170A7DA0F8D3BEE5F76C9CEF97 +:107A3000C858780DB93D1BEF958DC28321C7ADF8AD +:107A400038D3969B887421255AE3C05F0D2FBD7DE6 +:107A5000B758899F3768F0CF53C21F306FCB8C5512 +:107A60008360FCC6BDEF0DE1F702B3A3281F0CFA3B +:107A7000B4D21F637576E4E71E3A6BBD9BF063D00A +:107A800005F05186883F66A0DD67A5B7FEF2893A0A +:107A90006D1D43500E58E9AB536271EF154D4DE427 +:107AA000FEF2799A3E05ED50D85E56F1381D973FAB +:107AB00027D5E6C377227F6EE1FCB1F857DB7F89DB +:107AC00072A7EA170F7851EEBCAF36A7E378D58FCF +:107AD000AFF4629CFBA41AF4E2F7EF8794B87985BF +:107AE0000B1325E10F37E72BB035C16B906F3F7952 +:107AF000DCE6433F43ED56078F83EFE278833A8F0E +:107B00007FEF8A9FAF50F5F307D2359EC76ACE5BF1 +:107B1000D862A3FC13F497E130BDC5717BE2C22D9E +:107B20007DC7B76B77AD8B9B7762E40758E9F606A4 +:107B30000BBD025EC88E09023CE4161771EBC62726 +:107B40007F3CF204C0756ACB6FBD5261B4DF9CC745 +:107B5000C7CFB4DCFA530CF1F446AF9D82BE237A52 +:107B600043286E1E43B52DEC453BBC7AB38DECBA71 +:107B7000EAED0A73623ECB7107EDDB8BB6FFE6F5EB +:107B80007100DFA2676D69D3F934285FC158A79EE1 +:107B90003C12B12E553B7FC3E3BD9AC82711EBB30E +:107BA000E8D9FD76CC8BB1E2B1AC65BFBDC3928F95 +:107BB00040EBD472620A9DCB7BF29C1DF7D3F7F7A2 +:107BC0004974BFB2F5FBCACDBFF1A27C403C515C09 +:107BD0005EAC57EFF942E16B9E2FA176E487EB6D27 +:107BE000FDC6E0DE3A9AE8FB99E761FCCA371D94CE +:107BF000AF54F9CC52CAEF794FADE374FEC8CA74E2 +:107C0000DC5F2B6DC1741F95FC79E5A3DF25FA5B62 +:107C1000F8CA77D3F9791E3D93FB6D829938BFF985 +:107C20009BFE85E6B7800588FE2A1F512AD05F7229 +:107C30005665E5CFC6E1933F093E79EF310706511E +:107C4000D97BC26F197C5511F7FE5AE349FCBE95EA +:107C5000B3C28EDE95281BF71439A3EDAADA2DAB3B +:107C6000DB717D3EB8481FE8A3B8BE1A14F89248ED +:107C70001F7FE5AA81428ED13D31869E5386CFB1CA +:107C80007DBB8DEE8B89FACE74DFCB1D627C803B91 +:107C900041BA0CCAF4F8FE4C8F5B32E0E3F92F06D0 +:107CA0007DF5C6F75B783EC9C747B95CC1BC187A99 +:107CB000DF6E0B0F34E5C3384CF78944F23D6C821C +:107CC000AFCDEF014ECA57E9C1EF3E89E2AC0B36AA +:107CD00038CC79703D7463BDE7C69CBFB2D0A26F4B +:107CE00019A5552EBC69910B6CD3F9E5AF54DB4255 +:107CF0009477547DDC41F643F5765B05E2E3AFDB38 +:107D00000EBE7E13D0F95F5B0CBE35CB572BDF5612 +:107D1000EE18CDE2F1ED5FDD7E16976FE1795CBE86 +:107D20007547E2111AFBFAE4EBC25EE4ABE28ED1D6 +:107D30000792302FF783A7165D4C7E060B5E0DB9B8 +:107D40006A95978F246AFCFE8298BC3ABE9F47F2E0 +:107D50001D39FE0C7AAC7A7A318DD343B7065D1AA1 +:107D600074DB4B9E96158FD6F72FA23C1A10EBCFE3 +:107D7000084E620578AF5EA39D15A0FF392827F84D +:107D80001FCF8E93D7C1EA86A29ED1E8CE8E9B9F4D +:107D9000EB77FBD08CC573654ABC78B7BF4C8EAB14 +:107DA000C797B8B95CD98BB40065B59BE3AD49C43E +:107DB00057C012A4BC7FF429123F257B899F6CF029 +:107DC0009CD1B94A3F9DDBF627CA1F69A08255B8EE +:107DD000B5292AFA538BE5A5B9505FE82EE6F5F1EF +:107DE000F2CE1CA8DFE62EE1F5CBE4621B90E61391 +:107DF0006CF494C950AF31E6392FC9E4DF50E51374 +:107E00000F62DC457D9EDF17B70EF8DA591489F74B +:107E1000263A58D05584F7344209F555D9BF5F85C5 +:107E200046E00647E01A37C9A3491AE2F594CF495C +:107E3000F932773C7715E56756BBB9DF78F8CEF1B4 +:107E400074FFEED730FECDEE01BD8FDF64E3FD9C05 +:107E5000DA31BC0CF13AFC62467E0803FF45AA46C3 +:107E6000CF5D2D78F494F83F03CF7F3426DBA99FB4 +:107E7000EA9EF53ABFB251E43528899C0E9424B9A4 +:107E8000EE5928978AF5BF43E0037FD05EEEDA3BD8 +:107E9000F0317EDF53F7105C5F4539F347D41BBBED +:107EA000FF35D18FE757DE4CE0F8BA2169BDED52BE +:107EB000A81739872C45A27E53DAF65D2CBFED0951 +:107EC000FC90E39F85B1BF9B6E56787FEE3A0FDE44 +:107ED0009F26E95C8F96806866031E1A75A6D97383 +:107EE0009145CDF9168A52D41DA6713DA671591639 +:107EF000EC83B04E378CE5EB0438A57DF18D31BCB9 +:107F00003E2B94D3D8A1111CF7201CA31CA18BD00D +:107F1000FEB909D4224ED766FBDB88D3D7FE4526AF +:107F20003BB356D21ADD50DFF91623B9DC99E015C0 +:107F3000F907FCDE19C32F31F6A5B965B864257BB6 +:107F400016F13C0EE18732E2E86759AB829389F182 +:107F5000535BE4E178B69EE4647FF1B19FBB457C5E +:107F60006C101B7481F1B167DCE7111FBBC86DE8B1 +:107F7000F322DE2EF6FF334772285F485531278FF4 +:107F800031BBA6508A88F1DD2E8BFC35E878C451D0 +:107F9000DFAD88971147D92DDC5EEA253FE224A3A7 +:107FA000BCE6511D05941F61B3E6471C9329E1A966 +:107FB000F4C5620DF1D924E2C6171AB737E2FEC53F +:107FC000FC514C1CFF796F39C5418B7DF1E3F8E31F +:107FD00094D914776047F8FA19717CA6142A08E737 +:107FE000D930D86008E751F3DF01B93C2DA8505AC9 +:107FF000CD5BE6E7E32C74605DEFBF58D7FB7CF305 +:1080000020DEE7F7AA8D6223290FC226F2207EC95F +:1080100002F747E7411878EC2FCFC49A5762CD2377 +:10802000C90C98F134B8F252D3FB8BEA8A4CF58B29 +:10803000978D33B5CF868D30BA9EBB669AA97D7E6B +:10804000F34C537DE8C69B4CED8785E69ADE0FDF47 +:108050005AD5E7BA8F6859627AAFC8A162BC0FD20D +:1080600058F7CBF6FC202E5D18EB6EE46961BA116F +:10807000E27734ACFBC3D9E43F2A93B4D8F5F78751 +:1080800083B42F5FE8FAE77B843E7481FC3E0A8963 +:108090000DE3443AD713BB6CEE35A81727036C28C1 +:1080A0006FADFA4572EB0BFF2D79E3E55B682B9022 +:1080B0008EBEAFE86371BF1F20F2239B64719E7474 +:1080C0009293F4817B64F996E87BE4AFF0703972A7 +:1080D0008587FB557E02FB26EE9383135990F64F5E +:1080E00071BE9CA1430AE6EB4D65E2FCF963AB2649 +:1080F0004FC078664781968C2205EADF88C8FD9BD1 +:108100001C5A23C60346295C8E837C9FE6198DFB8F +:10811000CE721BD77F8236C4F360270B7A8B68DF61 +:10812000A3B866324B939614A2E9D5B3BF685F003B +:10813000311CAC1A9E8476D0CB383406699D09B4C4 +:10814000FFDF68C8BDCA6124F7CEB87BEEB5A0F3E7 +:108150008E67E6E5D2F3E33703D701FF1CB79BED4B +:10816000A2FEFC53959BEFF7A0FFFF780133E519C2 +:10817000547BB81D55ED5178BC3CF49774444BD7F3 +:10818000FCCF2E41A06BA5F65528A2576FBCBD822F +:10819000F27677CD08A2FFCFF03B1BFDD4B64E643C +:1081A0003DF707433F37BCC1FD5F377C66F6E7DE2E +:1081B000E9E179D7778AF1AE87C20778BB1EEFF481 +:1081C000C6F2850953901FE0795882FAB7DB40F573 +:1081D00003BA9F11C8B6213CBF67FED7764B98AF54 +:1081E000ADD1F7D7B10A1BC2F5FACD8B3DD8AEA7FA +:1081F0003FA39FC178A613F6E9E4A02D1DE8A7FBD5 +:108200001B12EDEB309E139F57CC1EBC12B70E63B2 +:10821000BCD759E0F46BB0DE33999FFA35FA672C7E +:10822000C1240777542EFA536A0ECA3F99FC1F4B9C +:10823000F63A48FE75559DDBFE20BCBF6570C7450C +:10824000A85FBC59F5D92588971B372A4C83F50FB1 +:108250002504EEF344E1EDF8BC8F3CF81EF484C72E +:108260001FC44DFE69079DF37AB3EAE94BA2F5EA14 +:108270004D9E893FF6E03E39E6FCE23D654F0D2319 +:108280007BDBA0AFDB047D2D797228E9834B3CE6D4 +:108290007B53963C9E4BE7894A2516D78EC47B3F7D +:1082A000302F7D07D0159E23DCF729CF1FDF7924DF +:1082B000A598CEA3B2C07684CF68BFF3E59B865362 +:1082C0005EE7B1B4F3BB1719E00BA27EC5389C2F53 +:1082D00009FE98D59A5A2CF4BBE7106F37FDFAC9FE +:1082E000D37F40FCEC7DFAF13BB14DC9F9E18389C4 +:1082F0007DCC2FF000FB18D93F5D2CC1EF8863FFC8 +:108300003C2BF4AFEFCB3AD925E7E40A91BFCEED91 +:108310001045F667601E774BAB928878F3A2C16276 +:10832000C817D009BD78FFA2B83FDD09F6D9702182 +:108330007FDA3D1F4F69E27108935E5772A8CAA4A5 +:10834000CF55C03F94F7976F0A34E23D8DBDEA7573 +:108350006199ECE12FABDFBDF325E57DA787F37FC6 +:108360004B0197DF2DE18410B71B5831EA7BCFE03A +:108370005CE0FDB464BE2FD8A5CE0227FC7EC6F318 +:10838000C9AA3559B0DC791C1F58C7BFD3C3DA3826 +:108390009DF6E87F872EE57F674E9C032E11E7A2AE +:1083A00063EC49E02BBEC92698F4C7F0E1BFD13990 +:1083B00097ED29DAEFC6A33E0F7A0AF2BD4BEDB076 +:1083C00027C799DF2F517E027D8FF572FBC4B987D5 +:1083D000C7E19C9A4EF79EB97CBE51682F19ED4FAC +:1083E00089FD66F1E13787D8619D4ECB47BC1847C0 +:1083F000A8DEBDC38B66F2658981242FC64B8EBF74 +:108400005AEAA37CABCD43D0AE6D09F3F8C408950E +:1084100005D538F735D76E2CA64BBF6B36A652392B +:108420000CFD09F0A836CCE7D9B9A731259EBD5D72 +:10843000FB1F7B07E1BA3D3D809F971AD15ABC10C4 +:10844000E51FC2620339F7D4A7C3A9BF4BBCD93417 +:108450003F185FC5E7209164BCEFE86961AF757EA6 +:10846000AA503BA3DF117B262A3E58CBC270F301F2 +:10847000B20F5B1D1AAEB36B0BBF0FCED5EA22B99C +:1084800057BB6F2AB7E39279DC737B42F71FC5397C +:1084900036FABB042E5F334B81FEB7DBF9FE380C96 +:1084A0001860873BF2DC18CFD5FA634A6A77E6F1A9 +:1084B0007BF55C6A33FB863B1AEF1EC2FB542FA789 +:1084C000ABED096119F376BA81261F23B822703209 +:1084D0001AD7807318E9F3DBEDDDEFE2F94B3A5F71 +:1084E000A7211C1C4ED63A5443BDC2E5E3F15B976D +:1084F0004FF307A558B86A47829E0BFC764F038B53 +:10850000FC7D04CC634B88D49DC013DB739890072B +:10851000C3564FCE8AAE83401A13F97EF63DC35739 +:10852000374D203B27A8A05D0FA52705E7C9F737E2 +:10853000BCBF604011C703FA89139DFC7D4F7B27A8 +:10854000BFB24475F376FE245FE23489F5DC676AD6 +:10855000F89DEE90C2EF5E89FEADF081911AC05297 +:10856000FDC2F344B78BE4D6074768782E31B000DC +:10857000E9F5576FC90CEF47FAE049179D432E788C +:108580006E33F9ABADFDAD3ED6701FE665773D2786 +:10859000699807DA65EBA6B8514DEB7B745E71EA1A +:1085A0009E13746E4B490AD47947635EC48A32C401 +:1085B000DF58D6DC88FE3D908714A76FC9E0F2E350 +:1085C000CCD14B1E5B1185EF07BDC2BFDB1DB818B8 +:1085D000F9A655F0E73ED46FA0DC2DF4ACDDFB6FBF +:1085E000CC8D3E87156407C81FD6C00E517EA1F101 +:1085F000BC2BA4D239B0E1AF3B6FD1A3E8AD59F0A9 +:108600007BB3182F3F29B08AF876FF9FED5E0DF3FC +:10861000585B86A0DC6D013DACAF7CC65A0BDFF425 +:10862000E4B79CE4F771C3BA3625C13A3DFDFA9E22 +:108630004BF1EF8B00FC8CEEAB3AEE20B9B93B9BD3 +:10864000F3DF8AD73E198972EB93BD8B2E467C2DC2 +:10865000F3DA0C3A9F9480FCF42C233966F0632102 +:10866000F2A384F742713F4A21D239F29FBD7D1AAD +:10867000F1DF6E7E2F04D039D13DD0B90FF58B429A +:108680001FD03D7D3F94F8797BBBCCCF81831CCF3D +:10869000A7FA24CA57D9DE3ED947FC2C036A8B902F +:1086A0002FC307A89F16FADB75ACC4729FEB294C49 +:1086B000D21810918F7FF3703E6D29D092FC309FBD +:1086C000444531F141D43EC9EB621F957F74D3EA32 +:1086D0000DF8F7C3DAC5BE20F4AE7D42CF65C7B84A +:1086E000BC5F2AF6B225BF19F7ED6D30DF252F29C3 +:1086F0005CFE0B3A3920F4E043F51954C7FD428380 +:10870000751A0D25DE0754AAD7E19F2F6163CA9B16 +:108710000F6239AEA2A50C8F4C4D98D57E909F610B +:10872000D38723FDED3A70F570CADF3DEE6098A265 +:10873000B8EB6FDD7F7C0AF351F701FEE3EC4BE809 +:108740009F6514BFA9207AEC8D6EBAA48E6BC6FB10 +:10875000410FBCA77AAA0A1B7D0D1206E0E3F57B48 +:10876000AA56E3BD803725E9C7911E97FB02C79142 +:108770008FBA5EF95B3ACAF4DD47FFEC4579BFCBAF +:10878000AE0F473ADB9503F6401CFA3C2CE8A7A451 +:1087900097BC8ACFBCDC5EBA24C8D621FDD4EC528B +:1087A000E8EF169CDEA5E8780EFB5D3D908E7ACE54 +:1087B0004916BC7E3CEEEFC2AE9DCFD1CEE6A3DE25 +:1087C0003292EECB30D9994C592ED33DEFAD12F900 +:1087D000272A2D7A48356B5E3518F78DD6CD769CD5 +:1087E00047D516F3F7D5A8BF8CC4B26F7BF533AF6E +:1087F000D05F72592EEA2F403FE49FE87E4DF13F53 +:10880000C628BFA70DF37B9E96397E405E121F1AC5 +:108810007ACC569F7E1AF5CAD3824EB70B7BB47BB7 +:10882000BB44F9FDC3B6F2BCEB7127B5CD8CCF9F2D +:10883000F2C22A851C1CA7F2F8C5B8A3B9140F1DF3 +:10884000A333F2872C68954288C74A43AF13E729C0 +:1088500060DB25BD6E2C0B35E2FD720BB74A740E42 +:1088600063D156B3FFBE7AE32B87D13C5CDC62391F +:108870001F2FF0628D6FECC05FE2C4372E4E12FEE8 +:108880009C216C88E9BC55DBF99DB7FAAB387FFDBC +:10889000AAE8DF68372189D34D8D986F754809891B +:1088A000BF4FE9C6FCDB5B057DDC2AE8A39685EDBE +:1088B00098BFBF78039F2F5B6F33DD5BBC60D7ED44 +:1088C000741EC14A4795DB78DC0D1048F19DCA4DF6 +:1088D000E6F755021F55167CD404240B5C5CDF8E32 +:1088E00085ABE57A5CDFC5DB6CF4F739AC709D6570 +:1088F000B3298FE81F0D9F759DAE33D6E95276A937 +:10890000699DCAFBBE9F2062DF98F5DF670F5F4A53 +:10891000F92E67DA72C87F60D087B59F29427F9EA3 +:10892000BA91EB99A7F794258E40BBE888EA97A007 +:108930009FE2973EF6E2798FA2BD0AC3B860576BFB +:10894000F13A3CA7BDB32DEF5ABC8FA2E82595F6AE +:108950008DE2978AE85E90A2978A1273298F424B24 +:10896000457C403FB4EF761DC9FB7D21CACFB6C917 +:108970002588E615478A12513FD8C9B83F427AA9DF +:1089800024B5236A1F599CC4FD03AB32DEB907F539 +:10899000F7A9CFDAE8BCC9545BF7CB987FB0B34DE9 +:1089A000F5AF807AF54B731BF09E8AEA27253FAA24 +:1089B000D987DB97A47D07E9ACD5E67310BCDF3D12 +:1089C00080EF83DB247F3EB4AFDD7BD5F0ED98E70D +:1089D000BDB9D81F7D2EBB2859BB1FF32A5966226B +:1089E000D9DF532FB2D17E7A6A50E2CFE83E167DAE +:1089F000F31494B3A79EDF69A77383DB2596011355 +:108A0000399C71F019BADFE397AF50BE42D9AE5727 +:108A1000283FA137797F3AA4B030D9DDCD742FCC6F +:108A2000E2CD46BD83CE415408BDA966CB09AA5705 +:108A3000A1FE0FE3556D52421AFC7A70EFAF28BFCA +:108A4000A1661BCF6F80F7247FAA307EAA45E87C01 +:108A50002EE3743057C89F458CDF33B4A8999FA389 +:108A600033EE4532E87CFEB639948716936F86F66E +:108A700025C5219A89BE63EF1BE2F46DBD77C84A14 +:108A8000DF2D067D0F63C390BE3F99C8F3C33E79C7 +:108A90002521B110E6F3C98B0AE5DDF741E7B49F64 +:108AA0001E11FBFF99B04CFB93D1AE73CF47B48F2F +:108AB000D41E3963477D754AEB87B40ED35BF74FFD +:108AC000463C7F8B05AA116FDF6A4DF4219F4FEF63 +:108AD000E0726B5AAB23847EEA6FB196265CDFAE00 +:108AE0007D3F6F4A417A7982D38B21CF160A7C2E43 +:108AF00014F85CA8F2FB9EAA0AF73F88F9D0D318B5 +:108B00009737D35A84BCD964C66F97AD4525BA1937 +:108B100021B1E6ECD8FD6E11EBA0738F5D99C3E92E +:108B2000EF4906C15E453DAC7A9B350ECEEDFA1A93 +:108B3000CB7E7A30C9F6A5EEC178C7B22ED3BBF989 +:108B40007E360DE809E3216DE18642947B067EAC1A +:108B5000EBD2A6E526F575DEF965A1B71BF56F8B9F +:108B60007B265A7CCDEE683BBCDCC7F5F0AAB14A47 +:108B700010D7B5C75EC93B38529323F60AD8299F50 +:108B8000250DE076CB28E8FA852C85A5A545EC9542 +:108B9000D519F74F2F4AC3FB23B8BCE81C03FD616E +:108BA000BE80CA484ED56E7384D0CEF81F85B75AA2 +:108BB0003D008000000000001F8B08000000000046 +:108BC000000B8D576D6C53E7153EF7C31F8913FBE0 +:108BD0009A78662C34BB31F9202584DB109A40D773 +:108BE000F626A51D83141C58296AABE2B65BD90A88 +:108BF0004E5085281295B889A9D6956942DA7E54D7 +:108C0000EA56DD226D621BAB4C096A9892C8A1A19D +:108C100025E990A0401BD0D659FC60EB9490C0345D +:108C2000D24D95D873DE7B8D1D12B43A528EDFAFD4 +:108C3000F39EF39CE77DDED75D7DFFF29AF544DF7E +:108C4000EDBFEECDC2C6FBA54709B63A94F069DF89 +:108C500020EA20F2449A60FB242343B0ABAF7B139D +:108C6000254423558B4209CCBBA1EAF335B46FF1FF +:108C7000E7E1BCEDFA52212A23EA84D5CBF2FD9D2F +:108C80006AD6CBF33BFB25D386ED3DF99F8ACA52CA +:108C9000A2C981E98AE760576832FE71FFF796A89A +:108CA000D877EA928F6295D8D8322FD0FD442F9290 +:108CB000F3D9A611ED9987F6F04BEDD4800E697FBC +:108CC00039B5C0AF878C0CD6755E540C4B47FF0985 +:108CD0000F513351F7277F1A9E1721BAF6AE64F869 +:108CE0007467FDAB8D683F6FEF9F87F9377F27195A +:108CF00016A6BFF84DA287D0BFED4DCF95ACDFD9FA +:108D0000EB96F89FBEB217F39247FCFA1B687553B7 +:108D10004F39616E0FED1736493FBBAE04E1AF2FFF +:108D2000E5655CC82E581F23DA7E78A6BF24A9F912 +:108D300036F2DBF397D68EE182F1355A69E46A00A8 +:108D40005FEAA8EE96C2F1171F90B0FFE488A2F97F +:108D50002481DBDBDF2AC4E734C058C0FD4526216F +:108D6000CFC973257611E6FD731FC66A89C6F7C1A0 +:108D7000B90F7E5A148187BCD2B14B06DF8F713D8B +:108D800019FFC452A23F0CBE7F2FF30109883A6C31 +:108D90003F8C798B0BE24E23A88238119791C17ECC +:108DA0005D9F2A06DC735C35DE483EAEE36A3668BA +:108DB00014F0637A9FD9315C8D72492745BD64698F +:108DC00058D8DBBC39A1C4EDFA7C1BF96C35B1FE77 +:108DD000299717A44E45E388F3590D45043FBBFB83 +:108DE0009DFACA038EC5FE9B8971419BF79F35DEB4 +:108DF00066EDE0F19B9501B218B72FAD766EEF8E60 +:108E000029F406DABB3F79A9960AF6278E13F5ED09 +:108E1000F24C4599B75DE764115FD7B91BD12AB40D +:108E2000D7D23BAB35B4D7517A3F8F7F180BFC8834 +:108E3000796DF1BEF3F37EBE0829225EE27CE1CFBC +:108E4000A25F3A7EDD7C7B68A3C0A1C7E5D50B217C +:108E500059CC7F554BBCC2E770F2DC7FA3489B8E98 +:108E60005FB812E47AE5EA7DE7B9BB1D3776E0F535 +:108E7000375BF5F34F83078D23AA15429EC7C68A39 +:108E8000EC76C66560DBDFF672DD2EFB88CFC3EEC5 +:108E9000C16DB5C47E138965719CC39B833F5EC65B +:108EA0003890D423E2B2383EC435D17731AAA33FFB +:108EB000397031CAE3C9E32B7E6161FEF2338DEB79 +:108EC000B8FFD86955F0AFF14C93E0DFB13F37956B +:108ED0002DE2C0C908B0DFE4881A677C92234D1FD9 +:108EE000B7635EF24C5B93C4DB9C692A63FD592E29 +:108EF000513C8D7169A44AB473F9FC5C73F09B1CFE +:108F0000021FD02F51CCE10F55CDE0CF8EDE535E46 +:108F1000CE63479F6216F228B7EE90A60A3FBF6560 +:108F2000FE804FDD69C914FC38EAD81D7DC7447E38 +:108F3000DB3D6951EFEE231E67FC8F8E253A28D664 +:108F40005934CF623C3EE62ED461ADD75E480871FD +:108F5000B492B6A4E7D0C39AB024D68D5E4A7C9B67 +:108F6000F932DA9AA8D5EA67CFB3A84DE443928BD9 +:108F700077AF678D3D87BF2AF6873C8265B4353E63 +:108F8000C77838ECF067AD971273C5F379EE3C11F2 +:108F90001D90C18BF3ED1E8DF94F64962C80CEAEE3 +:108FA000777576D3E31ED3BB0CE3A49D2AC2F8FAEF +:108FB0009CDEB640CFA00B71FCB1BEC5DF8C873202 +:108FC00080B4C39CA9731B29EEA145F0B36666FF6C +:108FD00013AC970D6C55E1E76E3AF829EBE0127C83 +:108FE000A9A11AD641524A021278F3EFD31E4D11AD +:108FF000F1DA55AC0777E697D3990FA17F3AF4EFF2 +:1090000034F48F6D77DD670D59E0313A74E9DDB0E6 +:10901000D0CF228A3101BF8277E49DD4DCBDEFF04E +:10902000D77DFB7C7E7F06DF72F5998064A7EB67B6 +:10903000D7E786E6D421E91FF782ACD4453B5F979A +:109040009147BDE2F0CFE74998E5C8C3D3D79A2945 +:10905000673DAD838A22BF8947259B751E7156F8EF +:109060000A747E628124C6776F966C0B5F87EA3E36 +:1090700013F7763273D6CB7CAAE97DEE35716E2D6F +:10908000BA40D17C1D37F89DFBF276FD72F9F2A053 +:10909000CEF981CF428F23C2F27CBE1FD7BBF7E14E +:1090A000869699F5ABA5B38F95238E274DC9B0E76A +:1090B000AAFB96FB4EB1DC7DDDBA2F09272261E0C9 +:1090C0003179F6C6E6A5F0375AF7F70ABE473BEF07 +:1090D000C2DF0A97DF5D81600385A02EB57A2A0B77 +:1090E0003CDE2B4DDC13669D90BF0ADE4BBC3EFB85 +:1090F000F6CB12D78304DE773B2F55AEBFAAB0E67E +:10910000E874849633AF7EAF69CEB9F5D80B590FAA +:10911000A81E8F9995FF5F77BB4F7CD4C075B93679 +:1091200034D2E02DA8DFF8CB38F77C8F0C7C10D53B +:109130004B0AF925BBFC528595A48DEEFD38936F43 +:10914000E3CC37AEF7D10FD63FCD3CE9DD1491F437 +:1091500082FBF3F8F9607581DF897E45CC27355BAA +:10916000F34469619CAF893827D28E3FA26CCDA6AB +:10917000A585E32997B759C1DB9F2CDE19E7739CBE +:10918000E3AD4A0E6F3BFB3A48DC476EDE692FBE0B +:10919000202E6BD067FF06E3939EA98A70C1B9F8B1 +:1091A000A18B737346127C5C4996C27E9BE1F119D8 +:1091B0006EAB9451611FA08CE8275A48CCE3FB5D4D +:1091C0001E37AB9921A941CCB354F072159D15F30C +:1091D0001EA229614D82C0C3B691216C8B3FB38E14 +:1091E000E5A33E9D56984F99A81ABE0A3EB294CC6C +:1091F00055BF7CFE2A5DCDF11393F1B8D91A9F4378 +:10920000AF0FBAE7DCE0B71AD77982EC43E87A907F +:10921000B20A6FF2804A6B14E4F3A04AFE62C47B88 +:10922000745816E77730ABDBAC5F4699BBEE0BACFE +:1092300043BBD974CE295F35CF34E6F3BD138755D0 +:10924000F017E2792ABDEE113866C47E0F73E0C8CC +:10925000BB957495DBA970A5C3679A7A96F779A434 +:10926000DF27DE39B2DF1278FC34ECD433003C83E4 +:10927000F0B3EAA04463D8D758E4E49BF3BF0AAF45 +:10928000BE5023CF77EE31B4690CFD01BFB38E68B9 +:10929000B5C6784999A87C2BF0F5719D8C92883BD6 +:1092A000F8C2D4B5BDE2DDE6D30E2124A3FFA3317D +:1092B00009EF69C934690FC7E32FC9F0FB1AEC182D +:1092C0002F7C57FF3AFCFC5B7CDE255D13785182D6 +:1092D000747E67CCA75F697C6FC83CAFCC81EF1F01 +:1092E000C0EF4957EF2E173BBA71D8DEA8CBA8C7FD +:1092F0009688DFE07A34FA2B9613FC6E284D08BF6F +:1093000097A523D5C2896AAF60BF399E07C86C6133 +:109310009C25B75E7BFC8EBFE922C7F299643E07AD +:1093200020E77EC47500E7C28FB6D5E6D4DBFABC71 +:10933000C84E61BF69392EC8F88A62F805DF6389B3 +:10934000B16658B5CDD47796F0931D7904F279A41F +:10935000781FDCC7F4033C1041865D9A934FAA4402 +:109360005ECCBF9752546CE07144BB4A1D9EEDFA2F +:109370006B914D95B3E33BE94B9CE4FCA665636CB4 +:1093800054DCA33B9B59EF18A7EFE47092F3386DC0 +:10939000B163A9AC2E7019619DBECF67DF93C1BACE +:1093A000A77C7635C79FC303051224D55C9C73F850 +:1093B000685C3FE6B189FAE5EA1FCBE374A0D8C147 +:1093C000073FDF1C1C74D471E9ECFCFF0753B7A7FF +:1093D000EBB00E00000000000000000000000000E4 +:1093E0001F8B080000000000000BFBC6C7C0F0A3E5 +:1093F0001E81C3D1F8E878022F7E7952B10C038226 +:109400005DC1C5C010CBC1C01007C42780F82410AF +:109410006B70323024027112102F00F21702712586 +:10942000101700D5363333301C6663603805C41717 +:1094300081F8061BE9F66B483030EC9241F0396454 +:109440001918D8E4A9EBC7513C78F15A0354FE5BD4 +:109450004D54FE576D06063D4304FF9D2669E627E1 +:1094600001F526033100FBB288BA68030000000052 +:1094700000000000000000001F8B0800000000003A +:10948000000BED7D0B7854D5B9E8DA8FD9F39EEC5B +:109490004942184248765E1030E01042048A9E49E4 +:1094A0000A8896D2889E165BAB4340823C035A4C96 +:1094B0008F78B2212104083050AC91224E10305ADE +:1094C00068A3A2D216DB8094A2F5F4466BABB53E3E +:1094D00002521E3E68EAA38EF7D4C359FFBFD6CE10 +:1094E000EC3D9909D89E7BEEFDBE7BD2AF2ED65EB9 +:1094F000EF7FFDEFF5AF358AE824F23F117211FEE0 +:10950000683A4C24840C8AA784C85A8F0352A25FFD +:109510002CB4E4C945E972F27F1B61CDEBBCDF7F5F +:1095200021248B90EFF032FA1782FC149E31E6630F +:10953000A424A890AE92783F5308CB6BA2402E0A89 +:10954000F0D55A6E8C53EFF08D2169847CEA64A9C2 +:109550005E458BCA69FA9633DA984F88430817B28A +:10956000F9D45D593D1AD3AB206D14C8EC4E4F921F +:10957000799035848CA7C9FE2122A988CF3FB19E5E +:1095800091363510D2658FE765998492F55B41E796 +:109590000FFD9E13C215381F0F91011E0A87878D7C +:1095A0000409A1EB3AE29F169843E7DF3A5909DA3A +:1095B000A160FB10684C7C061C67E761DEC1F39577 +:1095C00044E3F0EE6A29A4ED9C41916CA0B9A6FC9D +:1095D0002A07292564F3C4BF06C2743E4E3942549B +:1095E000483DC9E7379388BC9F7BC9E5AC3B713FD9 +:1095F00064D8A3F19815615DC67CB7D8E8BC32E9A0 +:109600007E8C17C95E9ADF543E2B0DE663ACCB917E +:10961000629C6680EB0842363638306D9A302B8D6E +:10962000403BD23B1BF677F3C42C718310AF7F64B1 +:10963000E271470F5D6F236FD7AA1D75407D639F51 +:1096400013E1B699C32744049CF7C6D1AED9D1D251 +:10965000FEF308111F966F76D246B00E2F89EECD1D +:10966000871E7ADAE6D2BC6F825AB641EB8F2F534F +:1096700046CBC12E3A4F8FC713B4D3724F80B57704 +:10968000BC2144356C1FF20CA1F55DC6FE4F10E302 +:10969000F0A4FFF7916A42283DFA727A5F8371EC79 +:1096A0006FD88321FADDFDD947AFCDA5FD92934256 +:1096B000702F8C4B965BF68BEC6170B5A9F4DFB420 +:1096C000DC3579FE0C5882FBF327AB016EEB8B5631 +:1096D000B856C35E95B0FD53E9FF2E16D0FE35C5D2 +:1096E00032BECDBCBFF9809AD6BCBB78D6D70AB5FE +:1096F000D4F8E1EEF191AE0C5A59BA05F73B55BDDD +:10970000FA37C65E73CC346E1BF1669E71D37F5CF4 +:1097100045AE423ABF44FB4F1B82D71CB3E1BA456A +:1097200033BF49557F2DC78F3E3CCBA7F8518AFBED +:1097300019B86174FCFB4B8017400F7A25F231A4F5 +:1097400045BADEE6AB49AF44F7A3A958D1D65038A5 +:10975000D855A54BF0B1317B01BFE01FB4A9BDA81E +:10976000B95B180399EF58F860CBE07F0D760D30A8 +:10977000BFC47DF8A2F0EB02F85D11879F9D54A74E +:1097800075C17E5707103E5E3E8F7557AFD4BAE85D +:109790007AD6657F3F749298E07815A3B3BEF9E45A +:1097A0004489797C83BEAE14422F027C2425F85A6A +:1097B00098C2834C52827B93AC4B16185F89C3D9F5 +:1097C0002113034E80BF87F5C00D5E9C52B5C304C4 +:1097D000677BE0F867003F399374B9C7E0F7263933 +:1097E0009DF2AF4CA2BBD3B01719F29F917CA44F4E +:1097F0005A3E452903BE302D18A6E334DBF878EA3B +:109800006ACBBE7EC6F7355EAE07FED9526EC3FE8A +:109810009ABD9C6FA88D38BF7EEDFDAC7DE27AFFCE +:10982000027C743CD45339FE340640DE3886344F13 +:109830003F02701F51D73917D6A8128483C1FFA9E0 +:109840000024508FCA87CFA09D43AB46B8DB73423C +:10985000248C70B3CAD3947C39418EF6C32795E625 +:109860008D3E0AE0BF392AD21B4994DF3C0D0DBB67 +:109870002C39D8984057B4ABA47266B4C0F82DD137 +:109880003371FDB281075C3FB019E0D8CEE859E5ED +:10989000E32A301FCA0F9D248A9DBB29A643DE4BB5 +:1098A000EA30FF49A8AC4B00BC91C97AE073F6904E +:1098B00048F4FCFEE36FE6F224D53A364F4C2E070F +:1098C00086094C0E489E3ABE1FB7A84067821E26E6 +:1098D0001781DE4884CBBF20EEF7BA867AF20E5DA0 +:1098E0008CEBE87544A3F823E7D48542B49D04B417 +:1098F000485934F194B3540E6A66FCEADB47B21A55 +:10990000FBB351B0C03A6D1EC71C320652F5064C6F +:109910004B46DD0EF4614B9B560FAA1CC59B4A01BA +:10992000C67724C72BE2A1443A11F35A75D2F1F855 +:109930007EF37A29F1AB0F3F8CF56A4AB5B73FDE6B +:10994000B8CA5501488166BB613E83F96C06879BA6 +:10995000978B6360DF22D387D3FD19DC3307E59350 +:10996000F78DEBCEC3BAD696969D00152E2DA8DEA8 +:10997000308DEEA7AB840800EFF5D0D924E8E18460 +:109980005E09721DFE994DC8B7856743BA87A18FDE +:1099900055DF1435D9E027E280FA8B70D1DEBF7D28 +:1099A0004AFE4C4CF483727CC5E5E94BB7B0F174C8 +:1099B000FA3FA03B7F823C4D0B99FA25001FEB3804 +:1099C000EB006F10BECBFF5BC653C93687067A47E4 +:1099D00091A846E9D86944F5535E4C5C536402F2A1 +:1099E00044CDE9D5617B2FB52F6B09998E7C94D23C +:1099F000AD19CF77723E10A869CA6FA6FD7E52EEF0 +:109A000009021F184CD966467AFFF56C4CD0B33763 +:109A100096EE46FED848F1A800F4FD5211F5A1F5E6 +:109A2000454FA86679F57383DFF4C30FA2C915C843 +:109A30003A08A1F0918AC49073CC3F8E1F897AD2E4 +:109A4000E5E287FB16EB7E7CD1FDFA759FFE7D7902 +:109A5000F8F18F8E67EC6B2ABE45F715F5EF166DA2 +:109A6000D680FA4BFF7DDD86FBEA2A22A1647CB812 +:109A70005B10ACF2C99C9AE507B9D3B25FB6C2AF2E +:109A800007760F000F5B49829CE4FD3AEB25ED342D +:109A9000E8B1B28AF2C8B01FD66BDB74D0E73FC919 +:109AA000214CDF8B2CEF12400F2A22A807410722FE +:109AB000CD3BB5507483C0F01FF6C5D06F6C541DFC +:109AC00033C357525D963C99AD0BE6F93BEB159CC1 +:109AD0008703C603BAF4D00E69BF520EE972A2FE24 +:109AE000C9E60F43313BFE9ECBC203035F01AC0CC2 +:109AF0005FADED9A036524D9FEF51BEF26EB7C5391 +:109B0000F2A5C4761E593B63D24752B793C9199345 +:109B10005E33B4CF7FA11BFADC2181EA858D81AF52 +:109B2000EB386FF80F95AF2D905279260DA9226171 +:109B30000DE4A4C6E8444B67F2B743B0D8E1C6F7DA +:109B4000D4F360E3C56EA7B8087C4DD62CFA7262D8 +:109B5000DAD810F8924C91D25DFFF024791C55624E +:109B600057876657D3FAEB1B3A26C177A3DE54D149 +:109B7000B0BFA9D834E9C732A1F51CF8955C1C0721 +:109B80001F55A299E4BB83746239FDCAF78FE03E8A +:109B9000A05E45BBAC1335EC572187B01E7404F5AD +:109BA00028179F2497B0EE20BFD1160AE1BCE488A5 +:109BB0006305A5BB8D4E9ED778DECFF32ACFE7F3A2 +:109BC0003C951390772B344F53A72DA262DEC5F33B +:109BD000F93C9FCEF37E9E2FE079611BE6372AACDD +:109BE000BF0D7294F5EFE2798DE7D3795EE5F90266 +:109BF0009E27BBD9F8769677D9A2AC7F37CFE7F30B +:109C00007C06CFFB79BE90E785DD984FB57FAEA28D +:109C10000E06A73EBED019CFA3F0E070EDCB77259E +:109C2000E419BE64080C0F635F35F02688FC917858 +:109C30007291DE86F0368DF3CAD877EE47317D3FDC +:109C4000A15139F749584439996ABEDFE7FC743BA2 +:109C5000E8B934DDDAA062BAA521807AEFA6068DD4 +:109C6000FB554AF0FBFA8620E6D7354CC0746D43AD +:109C700008BF37364CC7FC630DD598EF68988DE95F +:109C8000BE8630A67B1A1660BABBA10ED328D57744 +:109C900021DDD5A063BAB3A105D31D0D114CDBE6C0 +:109CA000953D5F04F35F40E73F007F183CDBEA0728 +:109CB00019546DE58BE953D22DE5EAE46CABDFA4D2 +:109CC000BCC092F7948EB2E45D456596FE1C399354 +:109CD0002CE54A6695252F7BAEB7E4AFE89865C9B9 +:109CE0008F8C7ED3D2DF88B61A4B797164A1A5BC64 +:109CF000B06585259FAFFF8BA57E5EFD1A4B799BD6 +:109D000033FCAC48F9D5B0BA0D967A43176CB3CA98 +:109D1000AB199997C5B7C8C77A96D99F91C8EFA5CF +:109D20005C120AA1DC62F2A511F016FC5EC3487455 +:109D3000AF00FEAB6B4F80DD612F6272A79F7D99F4 +:109D4000D09FE2D9F79A4EC7A9F49D08F498E88C01 +:109D5000044CED28DF3F2532BB79C3BDCCAE6EBDD0 +:109D600037B97D8D9C9DAEA3F5F3E4FEDB1E51E279 +:109D70007A906EB1535AEF15B0FE3FDABF519ED8BC +:109D80006F7C3C8A7315663D246AF845899E15B739 +:109D9000776D3DFEB960F71876AEE460DF2B4B823D +:109DA000279B28BCD7AA04FD866B3D5504F48A4F37 +:109DB000544637644F2EDAE346FDFEF333E915C807 +:109DC0007F5C563FAD6716FA3DD7660EAC972931DA +:109DD00009FD77524C205D54EE2872F5F47C4ABFA1 +:109DE000CA2B52703541F993D4BE27641BC2414A35 +:109DF000D06F9AE625F0BD29C370DD36BE8EC6CC85 +:109E00002AFCDEA40E3C2F3BCC0BE6C3E7658BB9E6 +:109E10003195624E9CEFC45806E627C4FC985E1547 +:109E20001B8A69456C08A6E363859896C7F2311DC5 +:109E300017BB02DB95C546623A36360EBF07636331 +:109E400031BD32F625FC3E263611D3D1B12FE3F7D2 +:109E5000D25825A657C4BE82DF47C5AEC37464EC92 +:109E600046FC5E12BB01D311B16F613A3C7633A65A +:109E7000C5B1B99816C5E6605A185B84ED0A6277D9 +:109E8000609A1FBB13BF6BB1E598E6C5EEC13437CE +:109E9000F65D4C87C51A31CD89ADC674686C23B6A2 +:109EA000CB8EADC77448EC7BF83D10DB8A6956EC6D +:109EB000014CFDB187B15C8DB5639A16FB217EF72D +:109EC000C51EC5D41B7B12BF7B628F63EA8EFD0C5F +:109ED000BFBB623FC1D4197B0EBF3B624730BDD4CC +:109EE0003E2939563E2E65BA2CF909A7D32DF851D3 +:109EF000F186958F97BF5260292F7BD1CAC783C740 +:109F0000CA2CF931872759EA971EACB2E447EDB75E +:109F1000F2F1923D563E3E7CA7958F176DB7F2F158 +:109F200082562B1FD79AAC7C3C7795958FE7DC65E2 +:109F3000E5E3D98BADFC3B30CFCABFB3C80EABFD58 +:109F40003D65B755AE4D7ECCD29FA7FC09ABBDC0D9 +:109F5000F98CABF4A796768EA2A349ED9A447F398B +:109F60008044A6F47D377105CDE72A469ACEF941A3 +:109F700006D01D4D3339DD0D02BAA369FA5716E339 +:109F800039D3A75F6DF95513ED2C7D28617E017DD6 +:109F90005B15F8BD9A87F03CFD22D07ACDC308FA54 +:109FA0000988FE6E2596E7B3FC0FA433953AF3DFDC +:109FB000B2727281953B59FEB1C67F5B0DE5E969CE +:109FC000A1EC20ED678F2D391F7F4262E76D17C42A +:109FD00050BB44D7FBE7CA9E95E047B33BC27B2505 +:109FE000FA7DB1239C07AEE90F6CE14764E08B2456 +:109FF000B40FBEA791D02312F26BAB5FB415146EF1 +:10A00000DACFC762F57E28CF98D9817691B1EE6616 +:10A01000EFC0F3894A4C2E35FB09DA8DFAA30ACA40 +:10A0200053FC33E4059583F7BB7D2128DFF5A8B207 +:10A03000DBCECB2D72A33E0BE586ADA37939B824D8 +:10A04000EDB09F5232BF680FE6D340E32F04FBBE52 +:10A050003757A6E9527B5733C8F5BFFABBDF122446 +:10A0600084C7AF003E2BAF0F63FD35EE9913603D03 +:10A07000141E27E03B85C7F3D2A0D4F02070B24075 +:10A08000E71F30B068BF60F13F9E13C2BF954C7EA2 +:10A09000CC403888703B20A9080F037EF4EFAE74E3 +:10A0A000C31FC3DAFD11C74DE84FE6E762BF95F85D +:10A0B000F85C1E1A789C21927032F81BE73EA423AC +:10A0C000F70BF9B39D8A98741C9B5C8DE7A9FDF88A +:10A0D0005E66825D9F1986B35E2A3FA9BC4C32AF93 +:10A0E000690AF74FC97997757E15E5FA3DD99FFB47 +:10A0F00085CEBBC0D083FA438D7D3A968BF951BC97 +:10A10000FD50D0EB283E3DF7A6FDE812CA07765178 +:10A110009E614FE20FD8D521E2F9FA503F45385AF7 +:10A120005ECFF5006A13A13E688C2B2FB6FA8F2202 +:10A13000360EC7C356380EA588FD536A72134F1EDC +:10A140009B1F3FB734FA69EF9BBF751EBBF52031EB +:10A15000DBDDF9ABA322E83572079DC798FEE31358 +:10A160007EBE60D091ECE17E13350FFB35C64D1CF1 +:10A17000874833F03C29157CFB8DF305CFEB2AE4AF +:10A18000E4E79D747F104E4529F43CE3BCCEC83F04 +:10A19000F7662D9E7F37476A50BF6B0EF073F6BF90 +:10A1A000D15EA11F921C4FF6727C7A889F8BECDDEA +:10A1B0005EE5C0769979967D2ABEEF265798E967C5 +:10A1C000E990EE6B63F5863F308F7FAFC1EF0FAD47 +:10A1D00062DFF3EEFDD8C9BE7FE88734AAB3EFDAB9 +:10A1E0006A99D717B13EA9A77FA673A0E16AB508FF +:10A1F000FAEEF0ED2404DFF2D45E01FCC89A4A4482 +:10A20000DD04D7ECED472BAFA3E5D991EA59D7C1CF +:10A21000797898048B35F8FEF2EA91B88FC401FB87 +:10A22000BD83AF3B2712DE3012EACDA6F548BCBC99 +:10A230008D8F3B2C12DE761DF8EF4A583F46F9F71A +:10A24000797B97511EB2B68FF0F2DC55A7BA46D093 +:10A2500076B991DE97AE857A1DD67A9B79BD51503D +:10A260000EF3085AC769E5F390F4DD04D0438A90F1 +:10A27000F4E9D08F6AED678381BF505E8EFFC6F22E +:10A28000870DBE90C0478C762D29F6DFE0273BC1B5 +:10A290004F3002FD5598E6B426F7BF96717E65E013 +:10A2A000572A3C270B448B7D47C22E6B7EB649FF55 +:10A2B000837C28DB5A3EA1C05A1E1C65CD97945959 +:10A2C000F3DA244BFED33E3F4BD409F460F8590C2B +:10A2D000DFCC0E95D149DC8FD7ED34DB2539BCDEE0 +:10A2E0008375CC1FD3E8E1F4C4FD322E4E97CD2503 +:10A2F000CC6E31D6FD24E75711EEF7D8D5D0C6FC89 +:10A300003063438E7CBA9F2DBF938203F9A11FE770 +:10A31000FBF1634E8F07B8FFE6877C5F1EE5FE9B6F +:10A3200047C07F03F40AFE1B3BEC3FF3DFB473FF2F +:10A33000CD43E0BFC17DADE67E98D958DE06FE9BD9 +:10A3400011E0275A80E916EEBFD9C4FD371BC17F43 +:10A350003302FC422D980EB231BB7CEBD45036F860 +:10A36000CBF64C4D6E170FB231BCC8074586A6B967 +:10A3700024F46517E02F456C3897293F167ACE4DA7 +:10A38000F323A20CAEE50743CF4179711BCB17F243 +:10A3900071409E807CA1FF60713639541B32E1EF21 +:10A3A000B817A3640EDDB7B7657E0EA051D5232B79 +:10A3B000EE2F8572D8A73785508F3C1EFA25CC8F9B +:10A3C0001F0E0B401E83EFEAD5155A4F5DDC1D8230 +:10A3D00036BE96CE2EB0B335BD0BDB6DAD0CA29F55 +:10A3E000CDD8273ABA051FE8DC902F0EE3FB4F26A5 +:10A3F0005BF12137B60BF5E1E6BA596988771A198E +:10A40000D05E2FD969D517866FB7DA49CD77CD1AC7 +:10A41000D0BF9CE82F53275BFD65CD2503B7F7958B +:10A420005BC7F79426B4F70CDCDE199B39A03D78A6 +:10A43000855893611B14CF17C6AEC1FA89FA9F0CD9 +:10A44000F16F54AF93A72821380796A7A8187A254B +:10A450004FD1781AE4DF433C5FCDF22A8B93A0FA08 +:10A46000623E8C43F727E1FC3B44E07C7AEB48C238 +:10A47000ED91DA35A11C9AFF6782F6C449F9CE2A1C +:10A480009DE677CC7088D295806F2CDE41E1FB95FC +:10A49000A144D723DD6E15C96E9ADF131998EFF525 +:10A4A0008B83F084D07F3374B15A260D40F7DB17CD +:10A4B0008BD3A349FABD86D315394612F5EA6B6CE6 +:10A4C000F4FBDAC5B354E0FFF24D41B41F88C6E691 +:10A4D0006FF0B98CF481F76F57C27C7353F87556DF +:10A4E000DB38BD9530FE68E07FC64A86E7A9FA5F93 +:10A4F000C7F959AC53B0F87F06DD545D69CB447B96 +:10A5000028E8013EFAB9C4FC688759FC9A414F8D8E +:10A51000252F23FF36C6CFCEE902B38D341F99C84D +:10A52000E22A287CD15E3C42F97829F27B02F55D73 +:10A530000B7A2A991F3D8AF10FAEBAA00E79C9C3D2 +:10A54000F005EC515E1FE7B3E1AE5921D8A7C61C58 +:10A5500012E420C6751A78D018103134E29312A68E +:10A56000F7CA2AE51330FF9132CE9FEA59172F1A06 +:10A57000F68B04E789BACEEC37167765C4E30D6D28 +:10A580001B83F8DFEC5D89E785FA58A60748A49B92 +:10A5900088F9381F5D2C077FBF1A04596FCBD4058B +:10A5A00033BE7D4D08DF0BFB1EC7AF4E8C4731E03D +:10A5B0009708FF6F71BE9A4792DB1F83B97D93A105 +:10A5C000745E077CB7E5518AE749E266FCBCDE0FA2 +:10A5D0003A66A5012919746B941F90341CC7C80FE3 +:10A5E0008D292CFEAFCB6AA7FCFFAEEF1FB459E359 +:10A5F000F3FE47DFFF1F7DFFFF117D9FCBC7A96BD8 +:10A6000060236C1E962F6F9EBA46C7F559ED7649AA +:10A610000E5AFC1FBD40FF26392F7BAC7AC9E5F3EB +:10A620000D19F527121C66E1BF19D903CB19C3CF49 +:10A63000F1E930439F0F215D90A21262D6D79A8034 +:10A64000CF5338EEA470E47187384E365F97ABA7CE +:10A650005A17317EC2CAB7772E38EA1C81FC5FC612 +:10A66000769E406708E4AD43EB46FE6BF069CA9FF7 +:10A67000C72A8380CF5720FF739544307E6D2DD736 +:10A680004313E10AFC305006E325F021A2A53BA0CC +:10A69000FCBB0C0764F0E3819FB27E603FCBE5C654 +:10A6A0007D187118B9F40FF8D04699CD8F1CB2C639 +:10A6B000B1537C7458E275CF3D8CF2D4E8C7D077A3 +:10A6C00012DB35A9556A32BEF8A610FEBA32009EDA +:10A6D00024FAB548021FA71C54007D6EE88CE9E8F7 +:10A6E000AFEAF36FC956BE2E078CB898FF5EFE5EC8 +:10A6F000A7FC9DF1EB5FD0FFB78B9FEF27D2716274 +:10A700003FA24EC49E24E3E7EB62C2B9B355EF17F4 +:10A71000648DDD13AAB39ED3C89EECE4E7093CCE5A +:10A72000B366421FFE7EE38F147FEF3861633C8C7B +:10A73000CB25C3BF7B07C47BD2FDA981F84F2ABFBD +:10A74000E7916A1F147E40448C2BFB80BCEC1B6796 +:10A75000DAA77D0AF3E79316DB29B86F64C435DE08 +:10A760001E6179633EB56DD6FC7C322B0BCE35E68F +:10A770006FB7118863BC83C8A77A8CF9533DE7FB98 +:10A780000A8BD3AE2575CDC0CFD672FF7D8D4A64BE +:10A7900088435CF2CC8315606F1E50981EF52E85A1 +:10A7A000BF668A575BE8892A703EF1CEC1715FFFB0 +:10A7B0001281F6D1E66C8847A47A2DD8BD89709FA6 +:10A7C000DB629DDFA5E69F385FE37E52AA79C81D54 +:10A7D0004228991DF133C51A3777A97B536F8391AE +:10A7E0008CE720D67B53976A775AD148B2FB5697AD +:10A7F0006A77FEEF1CEF428AF196387A14E003CBB9 +:10A80000E4F074A1201EF7A5D8AA43432928E44305 +:10A8100063BBC0176EAAD77299F54E80017219F505 +:10A82000A68B03F47781D3F1AFF63FAC007D7EF0C9 +:10A83000D8C99970EEB3E8671271C0BAF67B4917B0 +:10A84000B34F1490630B0F4AE88F237257C58DA640 +:10A85000385A8CB8A5EB5FF4632FC6692C7CC21EF6 +:10A860009D41DB2F7CFA9D3184C2E1C29ADEE34335 +:10A87000C1CE784C6071897ACF981BE9F78532B9DF +:10A88000AD3A091FF4D8199EBFFF13F76CC023A17E +:10A89000E3C8ADD86FE7376C76D3B9A064B7E1B839 +:10A8A000B45E889D6709D16281CDCF7CDFC2880705 +:10A8B0007DFF5181CDEF902DEA84F975B42B615A5B +:10A8C0006F59C75F106FBFFCE3033E80C3B2439272 +:10A8D00085BF2CEB90BAEC63303D69C7FB34218F08 +:10A8E00040F9C8526431343DB804E3C797766EFC32 +:10A8F0008BE483F656FAA1700976015C5F9582338A +:10A9000020FFE4233EB01BDFEDDEEB03B8D27EE791 +:10A910002814AFAEF9D8446784F51F4BEFDF1FD57D +:10A920007414C0AF659DEBD97809F4F92EFC634827 +:10A930007FB930CE6E950B9F90172BD05EEFC84835 +:10A940001A6FDF271738BD2E3AF0C92E9D8EFBFEF9 +:10A9500013EFEDD2E9FC17FFC747BBEE01BDECE7F3 +:10A960004E15F8CCB2C77EE72326B8CFB433BFC1AB +:10A9700085471FD9B783D2CB853FD8D1AEBDF0EC88 +:10A98000D95C8DAEFBC2E39F6569B4FE5DCF4E1D01 +:10A990000C70B8EBA92F0F1EC84F00F81AB59BF723 +:10A9A000358AFD6B870416DC7F98A709FBF3DCC1B1 +:10A9B000E772619E1FBC66C7FB8CCBE8B7FA32D842 +:10A9C000AF25C8F721BF8AC279E9FE757F91C624F9 +:10A9D00083B73E54C4C3454A3601D8EF1BBF7675D2 +:10A9E00039A4B6A006FD915EE4DB89ED96BD42F781 +:10A9F000F5CAD4FBF809F99B02F05FB67F3D1B371F +:10AA0000611F3F807F4CECBF8F8BFBEDE3E287D073 +:10AA1000E638989134FECAD8C7254FFDF3807A8076 +:10AA2000C10F2E05DF053C8E70A23DB4CA0E74F531 +:10AA3000845B0FB0FD8DCEA065170E7C924B287EF7 +:10AA40009CB3F5DE0A7CB2F759BBBA9B7E5FF8EC8B +:10AA5000AB4867179E7A49D1904F128F40F5840B0F +:10AA6000A4EFAF1BF486A5FCCC79D91E6F97DD1738 +:10AA7000DFA7A5D11BA66B3EFC7E12BF4719FE2F98 +:10AA80008D1EB94948B26F4FDB0B183F8F0E42B88D +:10AA90002C21DD8A5A6ADD4F6102ECE3C9698077B7 +:10AAA000A9F6D158BF0AEBBFCAB49F7B18DD26D6E2 +:10AAB0005F4AE913FC887DFB1A155E2549E8F442DC +:10AAC000BB5D8678E10BB64BDC03FE82FA5FA73DE7 +:10AAD000857DCFE170293ABFD4FABE28FC76817318 +:10AAE0007B507F38BEFFB7E4FCFF45CE379692F02F +:10AAF000F46CA9BFFC9248481F9A1F9F6F73A784EC +:10AB00007CFDFD0E290A4D13F9C4D2147EA7D7EDA2 +:10AB10004C1F597AE8C818E067EF1FFD09C74B863C +:10AB2000F74BF79F54742E0FA2667990C23F799A23 +:10AB3000CF7BD9E1E4FD2DDBFF97A4FDBD2B87BEC4 +:10AB400001F37FB7DB4674DAC5BB9D52523FEC6F11 +:10AB5000EC364B5C61B3B7E2B534DA4EF2B9341877 +:10AB6000BA714DE8551DF492976D78DE41E4E039F5 +:10AB70003BF813BD2E6D038557A36F3EFA2B8DFE58 +:10AB80009A12E02407AA75B04BE5CCEA72A62347D7 +:10AB90002D76B14D152DF3A6723607E4D05B63CF49 +:10ABA000DA609D6F27E8836FCBA47930EDEF6D5DA0 +:10ABB00008AED692E1B7B5FFF02A896866F967EF6B +:10ABC0007D0BE6437EE12410A722FDDCA9033F595B +:10ABD000B6CB1985B880E79EFA741FC0EDC24376E4 +:10ABE0001E27C0E2CE6B55D6C7D9A73EDDF5EFB420 +:10ABF000FC2C34A6E3D7EEA2F5410FDFEFC6E0FF51 +:10AC00003F3F91368650FE5CFB8B7B66027FA90539 +:10AC10009E4AEBD7FE7830EA756706B1FC9903C30C +:10AC2000A2B02F8B9F7C7629C891453F7213701973 +:10AC30003CF7D4ABB742FEC22FBC182779E11767A7 +:10AC4000AF013AA0FAB36696E37798DF2BA0FD2E0A +:10AC5000823C2B172E9AE26F16414AF9C6A243692D +:10AC6000780FC8540FDB2DB3F7AE0CA23F59CF16A7 +:10AC7000D1C6E9CA063A5CD4611D6FA483F949972D +:10AC800029BDF359FD4836A3D76E6C57E1E078CA69 +:10AC9000CB13DB1BF5CB1D05967A46FBA5765297A9 +:10ACA0000CFF2B79BF8B3A3E1F61ED8FE16BFF717B +:10ACB000D8F7EF08EC9E0A79DC89E76D8B95AEE159 +:10ACC000E9945E9F56C802A0DBC5BEAEE17E3ADEC7 +:10ACD000CF389F5CECA279FA3D9BCF03EA439E38C4 +:10ACE0007A7E04FBBBE41927017C5FF20B2F9ECF19 +:10ACF0002C79FAD3333FA0DFDF7FCA8D7E9325BF47 +:10AD0000B81BF77B89BDEB56F0FBF53E6E477FF332 +:10AD1000FB8F3F9F0B7AC8FBB6AEDCF401ECF3254A +:10AD20009D76EE8CB0AE83DA052575743EFA561624 +:10AD3000C7564F5CC1D5109F028E03C0E3379C2CD1 +:10AD4000DE8A9FEFAEE0FEA00FE7696938FF52E6AA +:10AD5000DF5AC1FD072BBEAA0DF69BE60171A66462 +:10AD60001C21772B752380CF4AB1AF108DE6E558B3 +:10AD700021A6463D490DE2F98394C9CECF6D994194 +:10AD8000525B0AED585C12F15CDF4767FF8B6EF196 +:10AD90008A07B4C1D0DF4207D3A7DB9CA1BB1D68E3 +:10ADA000CF78F07E29AE933204FD29B6AE4F05B6BA +:10ADB000AEC4F97E6AD3EDC0CFE3E7DEEC9CA55EBE +:10ADC000D65E85F34C7282F3A57EEB6774F6A19A8A +:10ADD0008E7466AC6363838AFC647D4300D3750D17 +:10ADE0002544C3FB0141CC4B1C1EF6529D4870DF2D +:10ADF000566373B57BAA43707E017DE2B986278CCA +:10AE0000F8650FD4A1EDEFF010B44F258F4E6A3DD9 +:10AE1000E80F4338C1B90CC049E179B96D06C29554 +:10AE2000B6C7EF2B9DE15D001747CE280B9F52322E +:10AE3000CB2CF97E7033F0E2C07F37FC08C26B7D0B +:10AE4000830353B85F017083FB1590FFBF00BFE31E +:10AE50008EF1ECBE8366A21FB8EFA059E82905FC6D +:10AE60001EA0F0CB8CD355221CEA797C9B414FA9C4 +:10AE7000E817EEA7C0E5836D0D6D981ADFD353C8B0 +:10AE8000F5E14E81C7058457DBB87F1CF7215327B6 +:10AE900039267F1209E8782F0AEF5743B987F9114D +:10AEA0008DFD9554F98C95FF69AFC27AEE7EC1266F +:10AEB00002BF92EA1F26EF6498E87846B5534338FC +:10AEC00007D17FDBC8E5EBDABEFDB4D2C7C6060DFD +:10AED000D34D9C4EB6703AD90AFB0EFEB9A0887BC2 +:10AEE000DA3A9DA0FCBC8FE6997DDF45CC7E6D7F74 +:10AEF000B0B3CB46F71F7992866917F2AFD7ECD182 +:10AF000062DACE5D4A42802FFED7BE1BC5B592CE17 +:10AF100000F843FD1C7EE47081FF66F69E828DC9B9 +:10AF20002922B1346203FB2911BE8DC1A30EB0BB2F +:10AF300053CD272BA8DB73E978596FD8917F67DE53 +:10AF4000D2F95A0D5D87A7D58DF6645690E1A327F7 +:10AF500018166A4DFB979542EFDBE7BC2ED349E903 +:10AF60007810C4F3D2745B5BA113E0BBD1D6190097 +:10AF70003EB8D1CFE48C369B8E7695A93DE78FBE47 +:10AF8000722BFD1BFC589D5C66C16383DFA64FB12D +:10AF9000E2BBC16FCF3B983ED7E6AC1EEE8478DEB5 +:10AFA000D84EA4C744FC6FB429BA40F59446D025C6 +:10AFB00041BF3B29B0B894FE7C00E3563EECC9DFAC +:10AFC0000DEF0EACE1F1D43AA517943BDCFF699C80 +:10AFD000CB1F20D52DF00E4C0BC52302EFD550FC16 +:10AFE000017AD84CF107D208C51F4627133035F037 +:10AFF0007326384FCCE7BF45C745769F4304994336 +:10B00000646A077AC0CF7464A203F442D9C6E259D5 +:10B010007ABD6227C4B3ACF5CC7284C0AFE32FC74E +:10B020007DFFABB7266FA07315785104F046F50489 +:10B03000C9A9D2F8BD5F492D23604F1EF074E3F912 +:10B04000DED54ED132AF3667F846A7C9CF3F1A4694 +:10B05000E7FBF64FB8FEE4F7876F73723F658E4EDD +:10B060008A4CF46DC499124D2725263A5F533C8DC6 +:10B07000C039687FFA4EC1C7F6FED7F0B1C6BC280A +:10B08000EE9B2D916F6452FEEEC154175538DF3B95 +:10B09000D4F42D3FE2D95D000FE2D9DDA7BFFC5308 +:10B0A00041FF7926F2ADB83CD2D05F45E5D1FD1322 +:10B0B000800FA6904747DE1CF1358596BFF3BC2470 +:10B0C00098FD750B62EB511ED4C626128DCEB7A625 +:10B0D000ED7B98CE6F6B47BC3F175DEBC3389A167C +:10B0E00066CF9D8BDAA2523EE2ED4509FCFA84F56B +:10B0F0007F6E6723D623E07D318D7B6E276B4FCA31 +:10B1000035D4A73FE46BACD9620FC139CDB936DA7B +:10B110006E0078D6803194443FC5F704E0EE00A974 +:10B120001B017CCEA0F7BB15CA97000E6FD993FA0E +:10B13000D9573AA7EE00BA5EE90CB533B8A75FD687 +:10B14000BB16EF8854EF4578877D3758FCACCC8F21 +:10B15000F90ED78B892345B98FB75793972F697D00 +:10B16000EFF8BD34D75C1AAE2626FB5A22CCBE5E61 +:10B170007AA892BF2FC2E693043F993EDB6A473E0E +:10B18000348FFB830C7C8DE34BD8C7EF975AF0E9E3 +:10B190008ED856DC6F61E3E8FB2752F87D44F10856 +:10B1A000FC72C2C6AB07031DADDEF0A52DB7D0FE05 +:10B1B0003F7E51C2EF0B624EAC7FFEDEE0FDB780FA +:10B1C000BEFE6F36027CE4E31353F13CF6BCCDEADD +:10B1D0004758E462F2FA1CA7E3F9B18D16FD787EB8 +:10B1E000CB5C05FC8FF3639BF1FB7C3894C17B2027 +:10B1F0007F3E5629C3790DC1F3D173CEF7A7AC01B9 +:10B20000381C2E433F56ED267BD27B29E79C9AE5DE +:10B21000DCB9B6A715FB25543FCACCE2FD99F84727 +:10B220006D0C2EB1C0FEE804EE2DCCE77CA46F7E41 +:10B230003B6D163E72DE99DC4F12E37AC9FCD8975B +:10B24000908EFAAFEF1A465FC6B83D8CEEE2EBB9CE +:10B250007F62B2F5C4D73119EB9FF7271F3F8FC329 +:10B26000F94CC30212A27CA8C64EEB7960FC3B9B52 +:10B2700027809DBDD39F2E98D655DBB688844CEB96 +:10B28000AADD3947A931F51BDF07E72FCDFB90B7C2 +:10B29000419EBAC60372BBDAEDA270AED978F598BA +:10B2A00030DAD98C9FBC630BE6025F3DDB766752D8 +:10B2B000FACE736916B950DBC6F787EABDE5A6FD7D +:10B2C00031F625B1FD99376BFF7A2FF8011E604AE0 +:10B2D0004D2A78F5DBB7FCE4709BE862787986CA82 +:10B2E000D930C24D7BFA35C0EB4D6E8CF74C0DBF9B +:10B2F0002B487820F8A5D05FA9BE53E61A0FE312B9 +:10B3000084436D1BC3834BC12D3E2EC783CAE4EB20 +:10B31000A9EDC3837AA253823DA55C0A0FEE21BA40 +:10B32000638075F4E1C1680B1ED4BA8AA7023D9E02 +:10B33000033D6544FFFD3FA5E8BE49700EB441C220 +:10B3400073A6532E3DEB9B2C3F16F8F3295F64E662 +:10B35000A4F278FE8EBDC5BE39A671CFB6DCE94B2E +:10B36000E667AD4D853F453A29ADF83F873FEFA4ED +:10B37000B8C7B5D259B908F6934492FB738DD4E09F +:10B38000DF529AA7CFEE04797ACA53F0D7282D3D21 +:10B39000E40CAF047ABA5BD4C6CC11E2F6673FFD89 +:10B3A000B361FAD5A78BC15F587DF5691BEA43D815 +:10B3B0001F01BD329FC745A07F6308CA83C4F3D273 +:10B3C0001FB8F2939E8FAE6DA81B07FD12874E54D7 +:10B3D000739C1C617AD4FF86F1F3E3EB516C613509 +:10B3E00008F6A540AA01CF6D72B805EE03DB0299FD +:10B3F0006375135C1F7031FF97F3D8B1967CDADE6A +:10B40000F9A7175582F7CC74F4AF3972E40FCDFE6B +:10B41000695B268B5F2445A6EF0510874CF3163B2E +:10B420009FCE77003BF567028383EEB5F37B75BA59 +:10B430000472EF662731FE50FFFE8311072237B1F9 +:10B4400072BF51DCC4CAB9FF72590DF34F26EEEB3F +:10B45000CD87D775833E73F3E12173C18F75B367D1 +:10B46000C49FE07CE167E0C3077CF733B99CD8EE6A +:10B4700030A7D36FB58BBA8DEECB315BEF5137CCA4 +:10B48000F73BEC1DC76FFEEE98CD4DD3D75F396506 +:10B4900083773B6E83001DBAAE39445398121CC5A6 +:10B4A000F67349A797E53B07CDF29AFBA3A62AF4CA +:10B4B000B79C9DF37EF377AF4C05F14FFB5B0BE937 +:10B4C0006D2F1205FA9F73506B66D7F8787F8769E6 +:10B4D0007F62BCBF381C1566E7C80E844B1C4E0E3D +:10B4E000849B012778E606CBE370467DC380731FFB +:10B4F000DCD2665F4FC6A4A6979B3DC3FF44C6C47B +:10B50000E79508E78FA188D2DB7157E88F403707AE +:10B510005CA137205DECE8CD950BF01E630FE4973E +:10B520004AE1BC2C8A671F0C0B8F1804715CDDC9C3 +:10B53000CF5713E9F42DA01788FFE67198B7F2F5FD +:10B540003DF7DDB35E8CB37CEAD55C4897483D9B04 +:10B55000BE01F4F66B09F5EF0F0F8E18302EED2DAE +:10B56000EEEFF8D425F2F303B6BEDBB81E77DB416D +:10B570007714DEE3BCAD5EB2E8BFB7D5B3380E22B8 +:10B58000778FB9C9A24736A5EC07ECCEC47E8CF5FF +:10B590001DCDCDBE02ECC387C62B1AF81F8EBCF89A +:10B5A000E11F6A69DE35CC81E7B29BFC1C7F2B452D +:10B5B000DCF787FC21F768F03B6D480FEA749D1BB0 +:10B5C0007E493A450A9FA3235746ABE8789BAF16BE +:10B5D000D167B525F670A40ADA95B2778F54AE8F8D +:10B5E0006EE93ED506F878F6353BFAFBD3BD12CEB0 +:10B5F0006383AD3A17F4F73FB52B49DFD97378650C +:10B60000ACD72EF460BCDB5C127100DF38D83D6B28 +:10B6100030CCC717242AA0FFD99D92C8F464C3CFA9 +:10B62000D125333FBB2EB37C88A7AAD3FCDEDDFA3D +:10B63000E953309E625EEB4B184FEC2B4F7ECF6987 +:10B64000829BDDD7F576A7635CB4778A886F24790F +:10B6500083BD02B4CBEBAE52B07D4418B07DDE2A80 +:10B66000F53A802BB407FE9F7799ED836E05E1B024 +:10B6700095DBC9EDB660F314DA4FFB26BF00FB6122 +:10B68000D4BBCECDF499B3530CFF4D04FD37B9456F +:10B69000AA13DE5BC90D2171136F79C401F0DA0DB5 +:10B6A000F5987F13E1D03EF2E92E383FDE00B2017B +:10B6B000F6D9C6F069C32601FD99147ED9202FFE64 +:10B6C000749FFD2BB08EBC164105DB9BA649E7BDE0 +:10B6D000DAE360F2A6F57EB403C13D0AFDE6EEFCB6 +:10B6E0002DCECB9B62BD3FF430FCF8D325F023C7B1 +:10B6F000CDFC36B9F5DDDC4EEAC2F716230027C8CB +:10B7000087CAD93B87724833C7A1C4E987D9617416 +:10B710009D18075A334189821F406C69C77785E7B6 +:10B7200046ECE45ABABE56A13B04F4A28F17F97B4B +:10B730005EA1B7004E9BB70EC678B675622817FD9E +:10B740003BFFAAE0F9D8D1D0870FC0BBBCBB2628ED +:10B7500048174743EC9EEC43AB0ADAC10EF7D657C5 +:10B76000E17BC1515541CED2584E5E8078D2C6554C +:10B77000A22AD0FA916AE33E82EA02BC182B7D74B9 +:10B780005D099C9F0D11C19744CE0AEC9D91B5AB0C +:10B79000AA54D8D7B56AA660B65B748E077FF457F3 +:10B7A000EB6EBABEC0BDDB548801DF12CBB802FC21 +:10B7B000857A8BA2B1778BD9FB24197C5F32BAC50D +:10B7C000AEF93ECC7B16501379CB64E6A7FCDEF5D0 +:10B7D00061E65F8433C90AF42FF2BF00EE6B26CF17 +:10B7E0006D18E5C2CCF635F3B13EF49345FBC9289C +:10B7F00017BB2A68BFBBFDA15D284FA63A104E4477 +:10B80000EE69033845A76607E1DDE46D1387BF04E1 +:10B810004F54659CE89D0572343ACCF57A3BF0A90B +:10B82000B58A06749EB1EACC2DF0DD1FFCFE9D901A +:10B830006634FDFE1E9007FE9EBF34E0F7E98AC520 +:10B84000BF97F1C6F9CFA13CA35AB1F8093FF3570E +:10B850003FECA6F0D9551A89D468EC7B282BBE8E14 +:10B8600003ABBBA7C3FBD9676F1083BB7939AE6B42 +:10B87000BB1ADDC0E0560E72CD80DB3A51EB84F787 +:10B880009DF5990EC48F22D28DFC6A089C2217C6A2 +:10B89000F725E38DF5CB214E22713ECFB885BE77DB +:10B8A00061E09D4A8CD7A7724C1932C50578FD78A6 +:10B8B000597700F4F84DFEE4F1099F7A587B7B8AB2 +:10B8C000FBEE1F79183E004B6C2BC334341A520F19 +:10B8D000D1D320CD7184203EF67151FB23E2F9369D +:10B8E0004983FD81FA36BA7F475E7817FD83472288 +:10B8F000BFC5F4654F097BD78F125C16BCB35B7E66 +:10B900000ACF4736AB0C476A5B18BFA80DF438E086 +:10B91000BCA2B694A8BB39BEE9069CC1DFC5E555FB +:10B92000CD4D0CAE99A504CF5BC12706EF9E6541B6 +:10B930003D0ABFCC96D5CB711F49B75E48EB6D86EB +:10B940007E617F9AD8FD14427A1C48BF1109CF1B33 +:10B9500029BDFF06CE136B5A07E3793B5C7787FE60 +:10B96000D2F9B8E9BCBF76DA0FF8FFCEB648643733 +:10B97000F2B76E78639868AB282E237EF65696D081 +:10B980007EB57255DD60E081C1C72869CCA3F202A3 +:10B99000E0364FD79703FE9D72A82FC03CDCDBED4D +:10B9A0001AAC7FDEF667EE06BDC51DE86901FE50E4 +:10B9B0003B81CD37BD957E47FD46FB0DD4AF6DB5C0 +:10B9C0006B6C3C0EBF728E671C0EB7F379DFBE93B3 +:10B9D000CDDB352C1A01FCAC5D45E10A656186F7CB +:10B9E000E0D2BC28225D9D80F57BF52CEC77D0EC75 +:10B9F00004BA48C03F635D357C5D35ABD8BA08A753 +:10BA0000273AAD2EE8B7A69CAD731E61ED45F84E02 +:10BA1000FBBF9DAFA7467F1AD3DB5BEC96FE779505 +:10BA2000ECE986F9E4972A9A807066EF6DE6F27584 +:10BA3000E536B1F1724B9F4678917AD37CD12F6A6B +:10BA4000CA53BA3AFB3C252C78CC22D781C874EA79 +:10BA5000BB0A9EA3146DB7AEEBECFA110FB782FFD1 +:10BA6000F33E05CF2B1E17836FE5A11DAA688CFF3F +:10BA7000047F3B03F8F4ED4D78BFEA402583FFD9FE +:10BA8000AF9228E043F189EA748077F189304FEB77 +:10BA9000F01C9B0244E8E37B747ED4746A11805FDF +:10BAA000C60A7FB800F800DD67D0078799E74DE741 +:10BAB00097D192550571489913D2AB147C4238A1A5 +:10BAC000FCC48E59F01E6EE6B11D77C238438869FA +:10BAD0003DB4FC4A6F21BB9F758C9642BDFA33F78B +:10BAE000C27EB4F277ED8B6166E9981E833483D20F +:10BAF000F7C67498A74CA694C5F9C1DEFB2AC60206 +:10BB00005FC1BB2565987691B2FE7CC3547F24AF9C +:10BB1000AF0B49EA5578358B5DBEF7BE6923C17E10 +:10BB2000DF0C7A621ABC0BA87E04F1317A5044B85B +:10BB30006FB675394A33E1DD719180FEB2A5E4F745 +:10BB400022D0DDE6832408F89151FD1F76F33ED61E +:10BB500079FCB86E59211B81FE8F8E3C331DF6296E +:10BB60007A84EA9DB47ED5AF3C3BE03E71FB1F5822 +:10BB7000FC49FBF37528BF57E62A49DF7D2697D09D +:10BB80001313EBA717CF423F5EDEF6ADF8BE6CEDA8 +:10BB90007439782DAD9DB9BDB212F418AD9A62D743 +:10BBA000603AEF9D635703116A33D87995369D7DCE +:10BBB000D7A6B07463C3827160B7473A6467119DBA +:10BBC000EFA8F5ECFDBE8DA51F3AC2542F2DAF7C1A +:10BBD000C2F155FAFD74399582F4FBE9C91F3AE1C7 +:10BBE0007CE6A1F2AA0C80E7C116AB5E47E0713695 +:10BBF0006A078DB647425E3AAFD6DF1184A764EF7D +:10BC00006AABA179E9190F6838FDEC9BF5ADEDB38E +:10BC1000014FE795607872FF7DE7F2626E7DEFF489 +:10BC200002A05B9DB073D4C8FDC8946FE72C235F5E +:10BC3000EF46A6E3DDCEEC93881C3A0E7C39521A0F +:10BC400056A089C1CF5A8B6BF6013F53B8DE4FEA3D +:10BC500016E0FD48A47F09F4A1DECA6476D3B7DDFF +:10BC60002EC4ABB33B6F7C15FCD3F3EA99BE9FB7F0 +:10BC7000F32301F783EA7D4368FF79E5F8E425992A +:10BC8000B72AE2180DFB5324124D83F97412B01336 +:10BC90002254FE98E160F4FBF7B6DFE1B1E33ABE6F +:10BCA0000DC6F3F8F87A3C7C3DB9C1DECA64F1B345 +:10BCB000DFE2E37EE7C18F8E4C04F8AF6226525E6E +:10BCC000E4A4E030CD234FBFBC79DC02FDD1793C48 +:10BCD000E961F7A7BDE53D78EF2891BF833A0F747E +:10BCE000BBCB7D612CB3EFADFCB45F9EE355E2F7B7 +:10BCF000DC047E35DADE793DEEEF01F6BE3A2194C2 +:10BD00006E1DF8ACA8C6DE9D8D1AEFA0D741BD51BF +:10BD10005E8F0A78D03AF2F765009F4D5C5FB8BD40 +:10BD200094A0BD7A7B4E37EA0B739BB8BE20079B6D +:10BD300081C9BA77FAC90693FE802E2C702D357111 +:10BD40007DC190FF5C6ED706BA5B50AE827E60927A +:10BD5000AB353A93AB790126D76B5BE8381A47E6E7 +:10BD60000AB35EC2E4B8B69DEB0F5C0E67F07133A8 +:10BD70005B98BCCA003DC207E1073ACA653CCBCB21 +:10BD80008AEB2D834A99BCCC687D1CE5DA1FC0E99B +:10BD90003208F8069397C35E7A45073005E8E73620 +:10BDA000CAA78FF1F2804AF5B3F4B87EB64EE4E745 +:10BDB0004C84E987185B4FE77998D737BEEFE1F3FA +:10BDC0007BFC58FA5780BFEE8D148C954C748B5EBB +:10BDD0004F9ACF2D67E7F4B9F5EC9CDA1B9CBF4F67 +:10BDE000329D3F6CF5707BD3C0ABFAAE00F48BF79D +:10BDF0001D918FB3F7AAD6537D09FD4FDCBE9AEB98 +:10BE0000E67E0D8E3FA9E489C187BC24E42BA5F012 +:10BE10003D1DDD87FC5AA7F612ACED74A4317B21E1 +:10BE2000D07BE4867298FFE6897FC5B88BBC14F698 +:10BE3000A2C3EB30E0F085F8BA77FA2BCC0EED1602 +:10BE400093DE9399CAFD0F9D3271033C9D11F6DE7E +:10BE5000A1738292B4FE042FE39B195E768F68F380 +:10BE6000C47D78BF31A57C96892E2591A786BC6DAF +:10BE7000857D9E44C8CCD65B9B75B4D3A3D512F206 +:10BE800057760F30C27F77462F51D06FD86A8B38E4 +:10BE9000603FB694F37D551DED703FFD0BEF0B85B4 +:10BEA00007ECF3FA901815F2619FA3EA68E6D7C190 +:10BEB000DFED394BED77F339C52CAFC8E1A489101C +:10BEC0009F98D7C2F06BF34405E7B1616C56BB9401 +:10BED0006FE6BF02E79F0C4E1B261E47FCBADCF93B +:10BEE000CDAFBF67D269D339E299071E290038C7A1 +:10BEF000DF6F090D787F617EFD4B93F624391FE8D3 +:10BF00002B073BCA037660F49BE67396855E6667F3 +:10BF10002DF11AEF3333FE06FCD586C645341BFCE3 +:10BF20004B07AE8EFAD07FBF989DD7DEC1CF6BDFB7 +:10BF3000DD7323BEBF301AEED426D9F7F30DD6F742 +:10BF400017CEEF7D249BF935A216FDEA8E7D3F19B1 +:10BF5000C5DE9FD1F9EF72102DB382BDA38D72FAA9 +:10BF60007850B74BF1F7D114F85D0CF0B703051713 +:10BF7000C22BA09D987A807E0BE1F7857A315541DE +:10BF80001C15829D14C4349354639A45EA300D9075 +:10BF900008A6D9A413D31CB0730B412EF462AA11C6 +:10BFA000552426BE5F4082982F22D598CAB06F19BB +:10BFB000F17309B9C381F117707E01746F9C531836 +:10BFC000E7FB377B6B1EF02639AFB8C71BDAC1BE63 +:10BFD0007721DF9ECB59F8891F8DEA84FB3D2B36F4 +:10BFE000B1FB25065F47BB86F6FFC3742607F46DD9 +:10BFF00002F2AF35EE99D7201C5B6DEF9BCF1B880B +:10C00000C35104BF3F63F43B97FB17E672F907EE99 +:10C010006D76FF2E88F77FE6829FC1544EFACAD90B +:10C02000FD6BA31FD13D79F840E77BA6F6188F5C26 +:10C0300093A0FF5F526E27E4E725B6FF1B9D505685 +:10C04000DC0FF7C36BB45C76CEC4E43645240DDB5D +:10C05000B5D84FA21D16991A32C3E5258EFF863C2E +:10C060009997E0D74F4CE7C99C2E12FAA192CF0FB7 +:10C07000F766F00D14135D1BEFE81ABFD375472860 +:10C08000AC0C61CD02B08F2A9F7784ECAC1A42D3FE +:10C09000739037F9F37FE70BBFED35D1891AAA13F7 +:10C0A000CDEF34CDE77438556AAD04FE76364C8258 +:10C0B000603FDC41EA36833E465E9190BFC13D6CF5 +:10C0C000F8FDA06170A0918E795DA1E9070DEC5E8D +:10C0D000CE1978476904BC7FCDDE517A0FDE4DA2C0 +:10C0E000E9E8B6BB67021EBC0BEF27C1FD5B4EFF44 +:10C0F000C6B8A33BDD7340EE8FEEBCBA16EA8DEEF8 +:10C10000B0E3EF45951C5C5F0D7E2178CFC545C738 +:10C11000C9A1E339D2818F1094B7EFB5BAA26BE809 +:10C120003CDF6B93902F7F522AE2BB23F06CA6C4B6 +:10C13000E797960EFDFCFBADA087BCCBF988F17E9E +:10C14000E47B951ADAC7BF3CB04E807B09EFCDD1B6 +:10C1500070DDEF0DE9CC4D07B9E463F1E545FBED8A +:10C160005D05741E0B1FFB43410DF0BF82C8C26406 +:10C17000E7CCB93E264FDE7B8A603CDC7B4EFEFB83 +:10C18000488E4E9FD9CF1AF00916BEF59E97FFCE66 +:10C1900052CE25EAF1F872E2E9F431BAEFF4C1794E +:10C1A000D4FDEE1FE1FDB5334FB1738A5F3E509B66 +:10C1B0000BFEA8229FC6CEBD0F3C8971E3B00EB026 +:10C1C000A3E9FC3498DFFDEEB7DE05FF036D87F7CA +:10C1D000338C76670ED4B2FA6DB4BE0FE14E7C6537 +:10C1E000800F0CEE643FE31386FEB8289A85BFDF0C +:10C1F000102F17B11CA6E8A4F01FBDFF063CD7AA5C +:10C20000F0A5337C563B47CDC2F94772611D07AE9E +:10C210000EE7821FEF8CF17B52722417E070B33768 +:10C220005CE133ADFFFCC96790BF9788756FDF0B8A +:10C2300078F904FB3D93BBDFD82A9AF9C7541FD382 +:10C240007BEE772FF5C179D499BE7775222CDEE786 +:10C25000307BD77511A7BD33EDD47EA2F038BFFF78 +:10C260007B587EA6EFDD9B4E8C273BBFFFB9744801 +:10C270006B783C3F89DE88F445E1D2E24822AFFA90 +:10C28000EE4545D97DB70B027FCFF441036E75CAE9 +:10C290002CCB7915A3EF9C9DF9C7505F8E26BF2745 +:10C2A0009728EF13DFA7BDD43DE0539C4E4FF377A3 +:10C2B0004DEEF1866B7C49E448CDC625B900E71AFE +:10C2C000B85387710E95D782BD8DF74DD8FBB45DFD +:10C2D0000827E3FD59FDAA6B21CEF18C9FE5BFBB7A +:10C2E000B97A9DCEE1C8EA4F63EDF359F97D504E1E +:10C2F000EBFFDE5BBD9C8D4F04F6FB48363FFCCE6A +:10C3000085C1FF52AFDFFA3B171DC093C7637FF7AC +:10C31000607F32ED6FF43FDE9FC16FFEE17E1CFF58 +:10C32000B5FD187C18E81242F6483038EABF027EA4 +:10C330007F6F7B323BCFC2CF3F7DA0B019CE813E15 +:10C3400009B077A2ECADAB09C8A5DBB76F4DFA3BDE +:10C35000797D791E4FA214523A33D1F3F39CAF3E4C +:10C36000EF8B9F07C0F9CC7042F87B175455C9C2B8 +:10C37000901BB4FF46F077E34B4804F5AB51A41390 +:10C38000D352D28DE918D28B291E931682AB2F88F7 +:10C39000E99F2B7B2A60F18B1DE1872054D7EE08A3 +:10C3A0001F077CFA6058F8117807788D7BE924988C +:10C3B000FFAF7DAAF17BA224E1F7D9E2BF2BA281D6 +:10C3C0005E332330905E4354F9FDBEF88D027C4706 +:10C3D000F8651FAE2FD5EFCD25FC8E25BF476CC06D +:10C3E0006109E9C438885FEE5CF102BCEBB370BF51 +:10C3F00017E5C1F09D4DF87B620B497716DC2F1DC8 +:10C40000CEDF93206DEC1D0FE39D88916D76CB3BC5 +:10C41000164B127ECF6811FFFDB14589BFEFC5EF06 +:10C420006F6E840F49E20812EF7FF6FA52BCE75AAA +:10C430009AFC776512EF7FEEEF1431BE6705C40BEF +:10C440000971BE37724F9DDD8A5F9DD71499DE83D7 +:10C450006A1482CC9EF6BA427B85FEE38C53197E29 +:10C460001D1084A47164DF4C33EC9B26723DEDA754 +:10C4700071B1AC82BDD91875E13968A3CAECC2A10B +:10C48000DE2A07D8E9C42FAA703F659A3419E3CB96 +:10C490009525F23838F73CB67B6137DC5F680CC80D +:10C4A000E8A71DEA67E7A0648888EF0334A94FF87E +:10C4B000E7C23E79D839E33095E0EFA11E695F29E4 +:10C4C00042BE919A2D83611C21DC8DF76E86C88453 +:10C4D0009FBFCE189B85EF98F138A556BC7F3C6571 +:10C4E000C96927C8F53CBEEF5569F9B84E99EFE721 +:10C4F000AEFA537EC0D3E7DB9B5F9E46FBB3456538 +:10C500008C6B2DF9BCF1F56974BCDE768598DFE3A0 +:10C51000CC5D255BEECFE6DC65CD2B09F788656247 +:10C520002AA7F972181FE148F544735C55668839EB +:10C530000B550FDE0F0EA5094C2FE6F90AC85390D4 +:10C5400074D822552E3ACF8E3705F43B1C6D9F9F31 +:10C550008771FA3F09E7017E1BF890B87F4A9A6617 +:10C56000BCEFE1E4F7839D705897883F4D0DA41808 +:10C57000FCD18EE831D715B08F276CF89ED45AAE17 +:10C580007FCB1E16FF6EE04B62BA3601EFD67E7E81 +:10C5900023E25D2FC5BBDD03E09DAC6AA827D872FE +:10C5A0004810C8C396D99DADD276573CA3043D141C +:10C5B00064D37E5C9A06FACC15CFDDCCDEF5A3F011 +:10C5C000C27721EB9562B0FBEDF599C57206D4F305 +:10C5D000203E7EE861E73F72BD3B08E58DED150129 +:10C5E000CD84D7CD0D6AB15C0CEFE3388AE1779644 +:10C5F0009A53FCDEF330BF580DFE2585DBFF77A68E +:10C60000B1F9DE99E6C674451AF35B3C28EBB360DA +:10C61000FE0F52FC817881237731FC5D31C481F7B4 +:10C620009E573C5F3878A038A07D0D816280DBCEBC +:10C63000BB6AD0EF51B9FC9813DE055BE175A880A9 +:10C640008F926FF8FD9301DF5FB0E1BDAF466F855C +:10C6500036D7D49FE49B807E2549D4B3C1286AD9BC +:10C66000F2D6B5F244C0177D0748A248DAF16B65EF +:10C67000CA5F3ABC7AB640CBDBD25E60E583F41D7C +:10C68000022D8FA6FD86E587E9D9F04B221D692F83 +:10C69000B37CB1BE03F29D69BF67ED41B7A07ACC10 +:10C6A000A1B4D7AF053DA7D1169C0DFE9D1FD1F9B2 +:10C6B00097D2F977F2F4A71C4E46F913F09DC2FB0E +:10C6C000204F13CB9FE6ED0EA528FF292F3F9CA2FC +:10C6D000FF9FF3765D29DA1FE5ED8EA5687F9CB795 +:10C6E0003B91A2FC055EFE628AFE7FC3DB75A768F4 +:10C6F000FF326FF74A8AF6BFE7ED5E4B51FE3A2FE5 +:10C700007F23A1FFB778FD1EFE3DC7DBF23ABC1BBD +:10C7100096D3CE5E022DF1B6A0FEBEB3AE1CF1BF25 +:10C72000713CD3330C7CCF81784D9ABF52657ECD5E +:10C730002B55C6E75FE1785DB9BC680BE0DD8A7F09 +:10C7400093509E523982BFE7AB2F67712F2B9E67A4 +:10C75000F741562C97F1F7800C7C34DA1BF3DFC5D8 +:10C76000E7D764C031AD809FB7048A6798E33D5531 +:10C770006BDE41E90942769A32997C29595EE518C7 +:10C7800001F283CA17E09B6B3D4A17DCA35FABCA7B +:10C7900058DE9459A542B9AECA287FD6665639E606 +:10C7A000A23F271DFD13793C6EAF4995F11EBFECEA +:10C7B0009F82E5D37E3C43053EDA447AFD95B0BEC8 +:10C7C00055329ED71EA9ABC2EF79FE8FFDC09F7F69 +:10C7D000E367703FE63DEE84775FE5EF88282F86BC +:10C7E00003FCE8B805ABC4A846AB1C535788907F40 +:10C7F000B889C92BFAE71D6B7A77B16365C50B1051 +:10C80000BFD3B8490EC2790EFCC9267950C47FF750 +:10C810005453D32DF2EA41EEC7D5030E8CC32B92AD +:10C8200049C0FC7B989A2AF17729D83B668511ABE1 +:10C830007CCA6FB1BE63F39FD7EF7F0B008000000F +:10C84000000000001F8B080000000000000BDD7DD1 +:10C850000D7854C5B9F09CB3677FB309BBC96EB2FC +:10C860009BDF4D801024C006420C88BA090122A229 +:10C870002E880ADAE286DF00493670A962C5B22145 +:10C880001103450DB71181825DA85AB462438B1222 +:10C8900031E88A88F8157B43AFF6A2F67A17A48AA6 +:10C8A00080B06A45FB63F9E67D6766B3E7245168AB +:10C8B000FBDC7ECF870F1EE69C397366DEFFBF99D7 +:10C8C000CD23CA89A889E09F8BF984289A764EA344 +:10C8D00069B052C4DBF4AFD16553B52DB664C787D8 +:10C8E00049F41F5EE2BDA82364D9EE65932DB439E7 +:10C8F000E917C503A2C584AC30A58C2003685FF896 +:10C90000732D21CDAB3AAE19A42764EB2A3A2EBD84 +:10C91000367F3D7A26292524966CF1ED900859B38F +:10C920008A8E3FB8A7FF681BBD3986906D4A683A6A +:10C9300071D06B58214D745EAF2C9709B497B94DE7 +:10C940006123EDB2EC8DFFBC6E08B497CA5EE2E9DC +:10C95000795F7B7D72956B307CFF2D3A2718571FCE +:10C9600090069F1C4DFFAD045CFE644206B625ACEC +:10C970009FFECD6FA5ED84F5EAF57E9BCD4A48DE9E +:10C98000B7C04DEF7CCB1E2886F1151C5F3B8F6F27 +:10C9900083EB1AA9B1880CA4573A57804FC829874E +:10C9A0009FA0EBCC5E71EFB8936984641DB2B400B4 +:10C9B0005C49DBA384A413A2836FD3752B92CF436E +:10C9C000281E5AF24BBC12BD1E7ED6C2E0946345AF +:10C9D0003819246FC6F5F46A94FD36189FFEF1C12C +:10C9E000F80FE458B6AFCB8766C00470C8DE4907BD +:10C9F000CC84F6C0B53E85E289829B8CA37F43BF81 +:10CA00006BF5D175ED94E2ED6A6877840DBC3F89D2 +:10CA1000C0FF76CB127B4EC7575C84EC9224F63C69 +:10CA2000E4ADAECAA6FD15DB30C54B48D056DAAA38 +:10CA3000CF81E7B278DF47CAE9FAE07BBC0D70F935 +:10CA4000F941F1BCB2B56A101DDF40C4F821E8BF5E +:10CA50005B9679FBAA56187F57A5787FF05A5F3608 +:10CA6000CEE77A9D9D90FBDA26B65ADD3DF37D68D0 +:10CA7000C3F5AD4D747D9F78A2297419A47EFBC9BE +:10CA80007442875A3333E007380261FB8713724AD6 +:10CA9000F220BD08FCE9F75484B2E8ADF387FE9CB0 +:10CAA000524CAF415DF45012855F7D67C0A42FA04A +:10CAB00070D6FB4259F93DEFD5EF994602946E824C +:10CAC0005D2578EDE3BDC38AFC77BD67325CC2F7B4 +:10CAD0003E89FCB6E119FAA85E1768B50EC4FE845B +:10CAE000E1BFEFF589F73F79E6B7B7C2F7CE79A294 +:10CAF000E953802E23142E7DBC27FA37745610A0DC +:10CB00007B29C9B7DEE624641E853971027F357A38 +:10CB1000A17F87A9CDE6A5CFCDFA36BF97F6A7A806 +:10CB20000CCBE53DD7876D83703CED7D2DFF749870 +:10CB300048DA544AD7A13AC5FB0481762869046DC6 +:10CB4000AFAF574637D129AD2EF9DDA862683F67F0 +:10CB50002546DA6EAE3BE82A063EF21A08152F6427 +:10CB6000FDD80E37F0714BBD61E6E340BF9165AE75 +:10CB7000F9C53DE33F64D7E33CD6BE46F96C24BD1E +:10CB8000EA3BEC12BC3F5821C087663BC5336D9B26 +:10CB9000DDA924940FFDACEB811FD7EA03D595D016 +:10CBA000CF2D9327E877CD83675457D279B89CB2BD +:10CBB000A4C379541D5B409F37DB0C20D9C87BF69A +:10CBC00039CF019C7EAE781B810F7F6EB5DA42F4BF +:10CBD00001958D3EE05B65B0230C6DA38E3476D05D +:10CBE000F96595107F87B5679EEF71F9F89ECD8046 +:10CBF000705E6FEE985641C7B12C936D21FABDB5AA +:10CC0000F51BBB27D1EFFCB8FEF9A34DF4FEBA74B7 +:10CC100085C03CAC0E256248A1747C039D239DF722 +:10CC2000AE26BF0DE467CCA9901DF4B9659081785C +:10CC300012E4A0B598B613E4539A43F199E9FB7F47 +:10CC4000B2078EC0FC47BFF99609DE778D9165600B +:10CC50009B0E85E139A5543D8E6DBC7A9CD42AF596 +:10CC600073C754F5F3F419EAE7AEEFA8DB99F3D4F0 +:10CC7000ED5B80DEC640473AE732BA0EF68858A22E +:10CC80009FAE2229089F7700FE9642D90BF031D73C +:10CC90003F7E6A017D9E05F284CE9F8C20E127288D +:10CCA0003E0FE47EDF13A57036A6367AECC5BDE1F3 +:10CCB000919563BA1EF0651DA4D808ED6FFDFDC700 +:10CCC0005FC3F85692D02F1FE0E3FBC43686B55DF4 +:10CCD000743EC9F00F0FC0BBF17FEE03BD7754E780 +:10CCE000057867D52BF8FD076778C2BA7CD69DD04A +:10CCF000FE29BC7F8A697DB76E04BDFE7EED525D64 +:10CD00004A6FB8A6934609F892D207EA0B524350ED +:10CD10005F3C20935AA01BCAAE04C6B3C10B54CECD +:10CD2000F8530D0827C5CEE887FE4B86E7E936366F +:10CD3000A6C13DCF0CFC7CFF2146FFF71BD838F184 +:10CD4000F13CF851544120276D765935CE461BEF02 +:10CD5000C3DB4E3B6BEF3E987A3DF0E5C619A9A3C5 +:10CD6000804E8C3209C07803B24DBEA1747DE63787 +:10CD70000C21890E3A402107F5A9B4BF85DCE9A74B +:10CD8000F3D87CD812D2D1FBE6F9FF6EA34026255A +:10CD90007CDEBB577BFF13E440AC4641389A9D6D67 +:10CDA000B651C56C0D213ABF54F807958F1583DB3A +:10CDB0006D804F73451BEA6F73495B1BC069F35469 +:10CDC00019ED89D47932D2B339A7E3E8207A5F3FED +:10CDD0005FB6C178A954B11BE8203FCA6EF3FB616E +:10CDE0005C0A73B98C910A8C8B2BA4DF49E37075B4 +:10CDF00038F6DC2DD171D260BC11AC3FC0C9CEE198 +:10CE000034D6EE413E75F071D306D1FE23D8382DCD +:10CE1000653DE3083C6EAE2661989FF8AE18273E4C +:10CE20003EF1492057F5BFA670A37892724D38B9EC +:10CE3000FB1793B0311FE0E36FDC8E7C6D253B80E8 +:10CE40005F1CD99540479987B74C9747C07B16FC24 +:10CE50008E7E3E09031D672AC4744D2AD82F7E8416 +:10CE6000A3965FDD07DB6EA63C12C78B967FDD0ABB +:10CE700069D5A5F6E663B7C3515938A20F7ED6F03F +:10CE80008BFB70EC7B40F45ABE7E2CE95C09C085BC +:10CE900024F6D77D7B5BA7EB383A09909541F504E2 +:10CEA000057DAEE67B84FCCD086D89C89E8B034171 +:10CEB000EEDB391D537D459975F728DB042BF0E92E +:10CEC0005282F455B977FDEDBFA6E35D186CB081D1 +:10CED0005EC939DCD60DFA91740686001EB62A8129 +:10CEE0009F24D1E75B8F651090DB6BCD6426D0B7B4 +:10CEF000C2E95CAB5F1E02BE71226B8465D7DF7F27 +:10CF000015F660C7A0F461361B8CFBFA6193F37FC2 +:10CF1000D1CE0A0D433B2BFB60779315BE6F9BDC94 +:10CF20006AA2F035BFC9FA3F48DBA14100BFBA3C55 +:10CF3000E0C303390B104ECABB4602743A5CE70BE0 +:10CF4000439BBC6726207F773EF79D5A0FC89FF40E +:10CF5000291E90433F017EA7EBD9C6F95EBB7EC573 +:10CF6000E00B803DA1BDFF685C2EF94FD5503C0E13 +:10CF7000FFA981ACA30F8BE439ADF9C0176BA9FCF5 +:10CF8000A54FE7E83C0D3F947AF0D369AED86587AA +:10CF9000EFAD32918091AEEB2B89042873E6387E99 +:10CFA0005B01F227974424D0B3B98DD4E005BA5A77 +:10CFB0006E2181047ACFFE4AC1FE9D66DF2E3B972B +:10CFC000FF262A07F4EC9FE4E7A97E52E360320AC9 +:10CFD000EC17FD3396E3203788A3CA17F7370A808A +:10CFE0007EA9DEA7DFDBC7D7ADA76A423F8AFEB5C1 +:10CFF000CA11E388DEFD5FE6FD14933502F252B1FB +:10D000001E3986F2C5A69C4DEC670A337D43EA487B +:10D0100078B0C4E082ED7FB3613B8BCA5FE328B494 +:10D02000FB434698670AF33F88CFE771A403BF101C +:10D030000472B689B49A683FA476CA6F6ED26D4600 +:10D04000BBF920F1003F5088D9C13F845B00D7ADC8 +:10D05000845427F281B88EB4313E5056E8D05F1A1E +:10D06000F6AA19E7A36F246133D84330370A6F65F6 +:10D0700039092BE06FAD3060BF91360FBE67208D50 +:10D0800068CFEEFAFAFD4C90D39643D41E1B097874 +:10D0900096514E592C6AFE23A409E1F409E7BF6DAD +:10D0A000AB6C88E7B87F16788BE339DA04FA22771D +:10D0B00079AA0ABFA25FF6575924303A71DC308E44 +:10D0C0009B3DE8A0448AE1792E3EDFB6CAF32DE30A +:10D0D00017F433BE1BE9A8FFF1B3F1F9B6C85BF64C +:10D0E0001B2928B6C60EDAFD9E1EFB5A0BE7ECE59F +:10D0F0006AB93CB253DD167031EB7D8E6914E6E6F9 +:10D10000EFC9DEED74BC2B8FA9FB55E7BF8DFE6D1B +:10D110004FFF88E366E84FFDEFED201D4EA9FBFBB6 +:10D120002B5EB3031FF7F467F3BBF62B753F2D7E21 +:10D13000B4F3A5F372DE9230AF0926A3EAF9CC9AD4 +:10D140005EF372DE9630AFC92E75FF4053DFF3BA3F +:10D15000BEC8F88DF312FD6E2ABFB47EDA75DC5CB2 +:10D160006DEC07EEACFF6D332F6DDC3B6ABFB9DFB2 +:10D170009D2BB4DF0921BD5F2FF97CA9F43A076E1E +:10D1800081BD68B5A0DDABA5975D5C7E4E067B8E4C +:10D19000F69F95EC9B9C4ADB1305DF3DF5BBDB411D +:10D1A000BE1C7EF68A0C90EB59A0E7109E2CAEB008 +:10D1B000BBCE857185EFF2FE549FB480BCD8BD9381 +:10D1C000BE97C2E695683FA5D531BFC24662C8CFBB +:10D1D000C25E4A253689F9E3CCDEE9EF3BDAF1D7C6 +:10D1E00071FF73EE8A09E403CA87CF1B6C150AF836 +:10D1F000678F49680FCCADF2E992297D8C6B953031 +:10D200006E34F79E7F1B0D7265EC494F6794DE9F6D +:10D210001BB67BE1B30DDDC417A67495A15B5A72F2 +:10D220001FBD3E7280DA3FBCBD14E8CDEAF380BF7B +:10D23000510333A2E39CD53796D8406E7ED7EA03DC +:10D24000B95933C3F70EAEF7AFD42AA1FDE6B3A5A3 +:10D2500093BDEDD30C1E6A67D47CC7530E764F4D39 +:10D2600087D9875713512C741D35D41E836B868143 +:10D270002866B85A8809AE65AB99FD9552EE37D449 +:10D28000D0EFD774FDEC0B786FA1127985D993613B +:10D29000C45B4DD71B7F027B6DBECF6F0079316CB5 +:10D2A000A781D9A49C1E8677A8DB200F12DB25114D +:10D2B000757BF46175FBC35406DF7D527818E06717 +:10D2C0001F5570E017877619515F1CD86F44FC2CEE +:10D2D0003963D90EF1A7094BAC28D7CF3C6DC6787E +:10D2E000D43EB9E35968879E4D42BFFA9577F795CA +:10D2F00049B4BDF817C9323C7FF16B1DC21996A322 +:10D30000A7F7973C3B74FB3A7A7FC9E88E321BBD86 +:10D31000FFFC158474C373253C02D6F7FCDF743818 +:10D320007EEC29637807A587332FFCECD97BE9F7DE +:10D33000CF3C95952A51BC5C05FA80F61BF75393B8 +:10D3400005FC8C71679E1908F262C94EA36A5D4F95 +:10D35000A7327B83223305E8ADBF78E289B53FC3AE +:10D36000F78B4E1D437ADBA70FC91658FF5A465F4D +:10D37000DAFEBB5399BE11F380F7F2297ECE7F6CA3 +:10D38000B913E2684336A9E13B34AC6EBF90CAF4EE +:10D39000FB1C92703F1FC62B58E3023B753B417B41 +:10D3A000A6E8D4EF6FCF073BDAC8EC07ED3C0EA43C +:10D3B00032BE7EFA693A0E930F3A663FD315537E1A +:10D3C0005CC2E9F84589D9AFF4CFF22C4AB74B409B +:10D3D000F117F4DC5FA2998718FF077C9D0EEE57CA +:10D3E000C7DED4213E4EAFAA1D7D7270EFF97CB826 +:10D3F000AA716895BEA7BD60D3D2436EFA5EDD6E9A +:10D4000027FA89E27EDD53AFA6DF41EF9FDDA978E1 +:10D41000C174AD9BF5E443E3A0DF53BA0E982F3CF3 +:10D42000F7D1F59EED782D05FA2DD86A1FA54BC0D2 +:10D43000C3C24DDF1B5A95200F2F971F04FFD671D3 +:10D44000FF766F79F7A42CA0EF4D9217BA2DE9B8AB +:10D45000E5E61BC056D9AAF30EA6CFCB14E2D78DB2 +:10D4600042D77B065CEB763F7728933E0FEE1F5347 +:10D4700006EB5A27FBAF1F0EF4FF981EE3585AB86D +:10D48000FC85E39BBE1F91E9FBEB6EB5D686AD38FC +:10D49000EE41681F28DAA183387BCA292A9FD8FD6C +:10D4A0006332E5C9535DF78F8078E23EBDB515E87C +:10D4B0007C5F32C34368970EE53C89B0758CE3719D +:10D4C000E325FFDD6E50E8F5D4A9D529158C8F50E2 +:10D4D000BE805076D0F5D5FE7438F2DDC24D6A3E7E +:10D4E00011FDC47C1785D5CFB5F4919526E20DA426 +:10D4F0002891CEB4FDD2A6860CC057752BA83C4E01 +:10D50000B07FEA4EB619C06ED27E072C4022F0AA38 +:10D5100043FA241E5CAF99AD979AAC26BADED3F0DD +:10D520002F16F796C02F5F2CE112C9922B489587D2 +:10D53000C273C974520DD77D52E4211D9767187FBD +:10D54000DF9584F2ECAC2DFAE48F81FE9EC9F18662 +:10D55000E8A34C1E973BEB89A4A4D2EB79E00BA087 +:10D560003F1B6B2FEEA2F29CF2F7994F0C28D79B32 +:10D570003A5E4D017C9D7DD62CCB142F6776A75546 +:10D58000423CE76CC7AF53605DA73BD22A212ED740 +:10D590009FBCD1CA29A1CF8FC33FC7526598E6BBB4 +:10D5A0002A0DE4564B1A18E32423ADB1A4B10FFEA3 +:10D5B00017EF390C8D251E901BDFB57A77303811A7 +:10D5C0001F6D7F76386D07E05BC8A91A898D2FDE45 +:10D5D000BF318EC76F968FD5EB86621EE833E21996 +:10D5E00000F27A1A287AFADEE1570A0780BD20EEA7 +:10D5F000373AFD33D2E87D5765B74F0771C429C468 +:10D60000DB4CBB7EA0F3DE65A3F89A47A8FE826BD5 +:10D6100069C08071971627AE6FAE42220AA5F7B98E +:10D62000A05F47601BF13577AB146EA6EB99B75E30 +:10D630000DAF05EDC61E3AA17F17112A608111B703 +:10D6400026F4A3E32F023D4AF1B0D844224974DC0A +:10D65000C58FABDF5B4222389FBA672E1AFBC2C769 +:10D66000171C1F8D4E5F7D9A4A0EEA510E2E21FE29 +:10D670006BE0BB4B84BE7E8BE12B78CF3D43E75103 +:10D68000FBE3FC8A7B87CE4B837822F1811D41DA54 +:10D6900093918E975491480E9DD7922E29323CA596 +:10D6A000675CF24B89F96744C1F57FF116C3DFED82 +:10D6B000DCEE994F6F831D7115F8EF80EFCD12CE20 +:10D6C00063DC33522899FA49F34DD4C503F9C4D722 +:10D6D0000BFD07D0F6421242F83C9C968F785B44D3 +:10D6E000BA0D8C7FC2CDE9F4BB0DA7A84C2297429E +:10D6F000076311DF9F132FE2FBDFE3745086F421F1 +:10D70000EE53FB8698537BBF0F78F325C0B976ABF9 +:10D71000BA4D1E4F6817005E683B015F0D7B2E1AE5 +:10D720007D7DE0E991B87E0B0F9D363C913F98FDE1 +:10D73000FC3EC7E323B72C70833C7A18ECC94C3EFF +:10D740004039C86F22E22311131DDF329AA8E22567 +:10D75000D44EC3F62FD2FEEBBA4DD9846CD4073029 +:10D76000EF3057E73F0429B281E9815F01DDCF95B2 +:10D770007DB90AC2D557887EF30A460F8F8E6A1C80 +:10D78000DAD887BF2CE6BF51EA88C8209F5E60F6D2 +:10D790004672694C1F48E0F737D3981D33E040F4D8 +:10D7A0005016D0DF7312C6F7374BA445A2707651DE +:10D7B0003C835EDA2C1D3F047A6CF3751ED24C9FBD +:10D7C00097EE99B6F435F4B92D5EC897D4EFA9D089 +:10D7D000D55B71FDCCEE4D6ADC2ED3E71977168D43 +:10D7E000023EA3EBBE733ABDFFDB340FC2CD6D65C5 +:10D7F000F4E35A1DCA5F06F1DD03FEA5AF01DD0D9E +:10D80000B7601C2D83C22A3915AFAD60CFBA4893DB +:10D8100004FDD63825C4C79A1A32F397C548CDCA35 +:10D820008054763D46AF92425A202E9CA150FB98E0 +:10D83000DD6F81EF3C92C2E6E59475774E03FB7C89 +:10D84000146BA7AE947C3B508F6D403864184935FB +:10D85000AC1BEE833D4FA7E1DB8DCFC338EF8C09C6 +:10D860008D25308F8C81ECEA3044B2619C23824E4E +:10D87000BADC32E88DE55CFF2FDF5D91914ADF3F36 +:10D8800072D6A4803C3FE212F668C40AF628195406 +:10D89000C4FA733DBBBC64420630B52357DDEFBC10 +:10D8A000DE376034E8ABA33ACC1BFDD1EA1B60A79E +:10D8B000FDAE32B07568F1AF7330BC06BF92483828 +:10D8C00021FE109C7901EDFCE0578AEAFED955262D +:10D8D000124E883FD4D51E9804FDEA49F71AA0C716 +:10D8E000FA8E24124EE08FAB2C7D7F57F045F02B43 +:10D8F0001D098D46B2CF8638E9117D6CCD7CA0C361 +:10D90000FD12C6B382D4AF0F25CEEBAB34124AEB77 +:10D910006B9EE9EAFB743DAA76E797D88F9447534C +:10D92000E03BE76CD1143B5F1FF413FAF77C580E11 +:10D93000E947629E92E96188335999FE9A06F85543 +:10D940006229D3937BC615CF61BCD484759E9B6935 +:10D950002011C44B0CBF0B700B0D21644BD7A706D5 +:10D960000FD8235DAF20DC04BD24C22F9498B76A82 +:10D97000EE8EC854565CDD9EB3AED84C517580CB4C +:10D980008550DE3ADF78FA5C27ABE44452695C6E7E +:10D99000A0987A04B2681857F5AC83386BBCCDFBFD +:10D9A000C7DF0FE54FA9A2E39516B3F727B717FC1A +:10D9B0009FD5A003491BD3CF4A2CD79F9CD0366953 +:10D9C000DA56DA1E9ED0B6699E3B34CF5D9A763623 +:10D9D000EB7F363992ABF31232BDBD708A42E5D689 +:10D9E00059776436F5A8C97ADDD02955B45D5FCA88 +:10D9F000F47A4397E44535C5E1D7E06576ABD51BAE +:10DA000035CC2D0638741F02B952D729D924CA073C +:10DA1000D68EDD116CC37B9E84F73A247CAFAEE3D7 +:10DA200038BED7EFF84532F2F9BAA213AC5FC74758 +:10DA3000683FAC69A9C1FCBEC85FEB88DF9725F5DC +:10DA4000E4AF857C3DE7F6BD2A33BAB625FA7341CB +:10DA50001837216E24FABF37BCEB6D304F92967F9A +:10DA6000DA04F6F47FD77F3406ECCBF7B81ED9285A +:10DA70008587C277B790C050D0A3DFAD1FFC8A4C1A +:10DA8000FBBDAF8F6E831CDD86F66B107EEF2747E4 +:10DA900073242A637EE4B88EB59DD16D00CF8F1DAF +:10DAA00053A628749CF773A239326D3FDABE9CB539 +:10DAB0000747B741FB654780F51F1ECDD1D9C0553B +:10DAC000AB9952459F3F61EB9B9F5BB91C11F333B0 +:10DAD0000FF4353BC07EAC63FA671BB57F4D545ED7 +:10DAE000CE5E7C7AD713140EB3BF9F8472EC89B3D9 +:10DAF000374F61FE41C8AF9441FC97FD41FD8872EC +:10DB00005E41FBC20D3A31B5071FC9B9DD1ED41FF6 +:10DB10005734EE06BB25637631EA8FB169BED3F088 +:10DB20005D71FD4526BB9E76D8985CD6C9980FCF0F +:10DB3000B83719EDBA87CD6C3D946F10BF568E8FF4 +:10DB40006D0E66976E7330FF7649DAC4D30E7A7D18 +:10DB500057F26D3651B8BFAB272133C8D94516B43B +:10DB600097EED84EE50695DBED7CDEED1BDC61C85B +:10DB7000E7DF21113FC815213FDAED3E776A825F6A +:10DB8000D45E42DBD61E3FB87D9ACF6D71C0355D45 +:10DB900086BC8F904BEDF9EC3DA18F329AD977324C +:10DBA0001E1EBA03D691A4B0F8D5FC99853B9AD035 +:10DBB0001E988EF3253E9F1BE220271715C810D70D +:10DBC00012F8B962A06F2FC0E5769E17107812F890 +:10DBD0003CCDD73D5747ED09BADEBF380308476A49 +:10DBE0005F8CE0F133B42F4E836E4F802F51A263D0 +:10DBF000E0FEFF4770FA3D3CFF47E154BF82CA0B8D +:10DC0000F912E40587DF4629A2CF60F202FD79B858 +:10DC10000F7AA7332D1083F1C5F767DF5B8FF6A46A +:10DC20009857D2DD7BAB6F23BDF94C6BEFFD19F03C +:10DC3000E5ECB14BBD220ECABFF3FEBB26CC7BBCCC +:10DC40006FE840B9F93EF5A39A40BEF0BC7DD9F724 +:10DC5000971C017F548C1B70EA70BCB592CF0DEB02 +:10DC60005B4BF16E82F94F33A0BF21F46ABB3DBC20 +:10DC700019EA26DA6FC9C6BA89F384D5A78456246F +:10DC800061BFABE41304E2AAB1B136CC9B533AC1F5 +:10DC9000E7EDB30AB17E85D243C80CCF293D419D43 +:10DCA0005F7B095D108C37EB0A7C0EFE3AFAD9B324 +:10DCB0004C385E1F74C2E2D443587D467B3EA7C3F6 +:10DCC00045054887E9CD2C1E4A14DF8869097A7E0C +:10DCD000BC93E139A934FADC7F01CDAF37A33D0B0A +:10DCE0003A16734A6D19381EC5FF60278B4B209D6D +:10DCF000CD7B2899D7C379CB00AE0F2433BADC6A29 +:10DD000066F9AEADD47E46B9C8E957D4E105B89DF1 +:10DD100017AD9553C05E18ED8CC73B7C107FC07863 +:10DD20003B7D3E272A1D07BF6F4E481731425CB826 +:10DD300075A22F9AE0BFC01FC817DEC9E52AD944D3 +:10DD4000D0BFBA13DE4B81F12D29901FBD13DE0722 +:10DD5000FF71E544551E7022C8F0313DF3D3CAFD72 +:10DD6000894E1EDF6C7BD497F81D31BE763CEAC726 +:10DD70004E723A11CE9101E04734E9108FDA7946BC +:10DD800037B1B87974531ED29D18AFBF79FE8F2E6C +:10DD9000F63D89EAC10513987F2FFC9EF9DCFF262A +:10DDA0002BD57E1DC479E26D5DEFB6D64F84FCBEE7 +:10DDB000BA3FB35B928A6306CCFB7824D5FC05BCE2 +:10DDC000FA83439DC0E725C24DE8BD47CD549E521E +:10DDD0007AD904759094BE36DD93847ACC61080FAD +:10DDE00005BADA02F535A84F99FFFEF91175FC4521 +:10DDF0008BBF1FC4E9EAF2FCEE26C0B9B3B7DF1D42 +:10DE0000B4C41E03F8072D8C2FCFED4F46BE2283DE +:10DE1000A2B3A1EEEDFC3E23017E6890A2852027EF +:10DE2000CE49BE1AECD794E401FEFC406671812015 +:10DE30006084AE3318FA0BD65B053BD57EF839FA11 +:10DE4000B796F2CF39395A06E308F902F204EDAC7D +:10DE50005A96876A904908FCB4ABE4398BD09E98F7 +:10DE6000954976E0FDE385E09709BD41FB1D94529D +:10DE7000191902FFD5717C34C827B05F1DD44D013C +:10DE80005EC05F83781F3C4C885337AC3F83755B23 +:10DE90000D7BD47453D74357D24509DE4BA033943E +:10DEA0000B218423DAED2047AA581E3D99B793AA87 +:10DEB000BBB18E2BC8E32FCE03D149209F924B3BA1 +:10DEC000C81C7A0D9E6276CBB8AEEDAF825F6EAFA6 +:10DED000EECE01760AF278A7A01B31CFB15D1B749C +:10DEE000E0370A7B27C16F1D3A5D15B7588DEF816A +:10DEF0001F0CDF8BC22D379015D3931BB99E4C029C +:10DF0000871AF469DB10D4A7A0EF40CE093F1AE4CA +:10DF10001ED0D5C0F4CA23C0F72FA657BEEE74B2E8 +:10DF2000EFA17F00CED7D8FEE94EC047F4037FFAB9 +:10DF30009BE3905C7E13167F5CF686F31BE9FFFD86 +:10DF40004BA6FFA11940E7CB244F06D0F9F138FDCD +:10DF50001762BE52DCFF5017C038A388772D82F8B5 +:10DF60001EBDD67139B480C7C71688B8D826755E6D +:10DF700015E2D189EDC5224EB6D3D8536F04F2A372 +:10DF80008A4492E978F51067836B87FABD061263BD +:10DF90007CD479D1A8CADBB63338DEC9E9C95E15AD +:10DFA000D681FCDA6C66F13221D7C6ADDC8E7432D4 +:10DFB00060942FFF7EE09B37F4186FF903A70301ED +:10DFC000974667E551C0A745C7E381F71B519E9F60 +:10DFD000A476C26E1EE7990EFEF1AAC050A897273C +:10DFE0008A2D37D17F16D775FBCCB5687FA7CB2A92 +:10DFF0007A7DDEC9EA9B30FE85FA2209FD012ADE20 +:10E000004600BD9615087D4D4640DCEDB89EC5CD59 +:10E010001B6EB50660BCA8CCE4A13B9DE929773A0C +:10E02000AB5714EDB8FFC9E951E443210E95988F21 +:10E03000F0C4FB6FE075C804D7BB7111AF778FF3E5 +:10E04000858CF22DA9D88F7AE12AB912E55BEC63B1 +:10E05000AB07E0527DA66E11ACE3B399160279C905 +:10E06000793C1EEE4DB7E3B8228E7DB9F1F0D1E9CF +:10E07000717A54C5C3F771B9B88FB0F9865A8C2C30 +:10E080008FC1E7BFEFD41561CE1F21909BB1DD6634 +:10E09000A68FA99D0CF27ADF9E216158CF713DB306 +:10E0A0006742FB93F9FB81CD10A7D9F74BA717EA7D +:10E0B000A0828B4F8F00FB76DFA9A77FF51BB8BF2F +:10E0C000DFE8057F741FCF63D419228568CFF3FA88 +:10E0D000CFBA944821C4A55EE4F8AAB3D036BD7F78 +:10E0E00083293035DDD9936F84F7E0FE8930F31B47 +:10E0F0004E104607A1F52C2F4CE1EB8679C4D6666D +:10E1000060BE12D60578F860FF709CF7463DEFFFC1 +:10E1100020B32F4FF0F689174AB01EF2BCDF80F50E +:10E12000CBC187993D3B57F63CB60264EF4B49188B +:10E13000079DDF7E14F347C187164E85E7C1C52BC7 +:10E140006F24DF9057013D9518C73F4762B9E8A794 +:10E15000D7167444E877CF750DF5B2F4A80B937118 +:10E160000DBC4EF624852FCC3BB65F8FF0BFD4F1AB +:10E1700031A059C6F4257C279898BF42FDA2CE67EE +:10E180007D5BFB9C3E5A780FFDFEDAD4C00FD213A4 +:10E19000ECD8E04B6E94A31F3CF8652EDA3B6D2C57 +:10E1A0006F7252EF9B0D7C62AF8A18E624C8D78D40 +:10E1B0009C8FE71AB95D4BE56022DF8BE765956AB6 +:10E1C0003E13D747D2995C4EE6F512BD9F8B7ABCC1 +:10E1D0009B8DA08F59C80BC6F5E0FD3C9EC71C77F0 +:10E1E0002AF60AD49DD57594609E346F6504F99221 +:10E1F000C23B02FEC9C9CDC94C9ED065C2380BCA0C +:10E2000009DAD50B74ACFE638191DAE9CC2EC0FE3D +:10E210001F6ECE403894AD66F669EC3909E5A2C8A8 +:10E22000E7D610F6FEDE96E3211DED5FB3532AA17B +:10E23000A295D4B454607DC8E2ADF988FF715CFE4C +:10E24000CE35FA0A3703BDED4D467AA3DF437FA0F2 +:10E250000E6AE046A15C32807EADDD29617E44AC71 +:10E260005F9B3F256175DE695C0793DFA03748A29D +:10E27000DDC9F510E80BA2B16FD57411BA247DAADF +:10E28000D50787E372F2F2F4E9AF417E8DE9AD4F35 +:10E29000A9BF70249DD10993FFBB59BEA99E34B27A +:10E2A0007C1BD767F175717DF8A18EE9DF05C60D7E +:10E2B000783D9E9E8FF35A4CA23CEF1433C0FCFA7B +:10E2C000A3AFE3FDD097A0AB139CCEEA4E91C8D587 +:10E2D000F47B752B49A47E04BB268F40FDCEF4BC95 +:10E2E00089E979B85A2E41DF6BF5BC56AF6BF579E9 +:10E2F0008681E96D414F89F907B093C6AD0CEB58A3 +:10E300009C39DB86FBEB387E97A4F92E668EE9B14B +:10E310000383C74C26CF4868FB498115E26715EB9C +:10E32000B2212F40F500F06F1285D376888B71FFF4 +:10E33000E3EE6CB67E17AF93D22B7E5262053C752E +:10E3400063BC20E624E8BF0BF86E4BA6EF8D82F786 +:10E35000185FC7DF3791164BC2FB95FBCCA8972EF1 +:10E36000BC908C753D54CFE4D9E978E9EF51BF8179 +:10E37000B6CFED4B463BE11CD71B0E1197216B101E +:10E38000BFCE0C86E710A9CC82F83691A66481A88E +:10E3900015F66CBDBDBF7C047F9EDF7D2BA33323B0 +:10E3A000EAEB0BF6E85DD0A6F3C13AECE40C36EFED +:10E3B000E09E0925F742FD85DFEA65500D9480FD5A +:10E3C00061D42DBF15E25E93742B63F7D075D4E74B +:10E3D00058B1BEBB2AEFF7BF9B45DB1FEFD113231C +:10E3E000E0FD899B0744E035C5E7EA8B4F1685F5CC +:10E3F000AAFD834B76AADBF51DEA769024EC2FA4C8 +:10E400002058F1FB926B0E26D0495946B2E3C36106 +:10E41000C096C40BF5E944F79D01813EE4AEB87E99 +:10E42000B9CA7BCD413DD6F75D9DC1F8D900F6D183 +:10E430001CA0873EDEFB23E77BA3B1F114EC133075 +:10E44000BE68F436D1B7CC198149F07E831C3B04F9 +:10E45000F834E69D1D01FAB432EFAF9827BC701F67 +:10E46000F1027C2E982BD04EBAB0D9EC017FB13D91 +:10E47000D7CAE2322F496189F91553C750F95A8B2F +:10E4800053A1EBDD74DDC76C530B31C9885FEA55CE +:10E49000B9405EF9D0CFFB709AC5B69ABE57BB891A +:10E4A000E9ED3AD29D0272E087803FA06BDD330632 +:10E4B00013FD677E8B6F68139DEF12BF05F733293D +:10E4C0005F2B7EA0AF0760C804BF644E069307F5BC +:10E4D000A6A8A102BEFFD779D5CE829E389E41CF95 +:10E4E000E2784A6749248BBEBA70C55CF4BFE2F992 +:10E4F000FACDAC8E6CE13D3578FFD5CD465CDF873B +:10E50000FB25A4F30FB7B1F52FDC64F640BDFBB5D6 +:10E5100076E6BF2FA4EFF5BDFEC91FC3BA3EDA7A77 +:10E52000B717F2101F11F69D908DC5DB3EB2B1BA40 +:10E5300002E80BE37CB46720DA43B59B164DC5FABD +:10E54000BE6D3A2FD823647F32C6B1166EFBDE6FE4 +:10E55000C6429C6CFAEDA500876BEDCBD3212E440F +:10E56000FBF9C3CCBE6675D3A9E54F021F5EFBF570 +:10E5700084EE6BC1EEDA46F9249FED4B007BFFE0A1 +:10E58000B6C968DF2E9C66B1C3BA3C5B9F98047A1B +:10E59000E8A3699932AE6797446C0007FB8A74B8A8 +:10E5A000BF5052FC7DD1537E860EE15A9167F546ED +:10E5B000E0BDB775482794AF6E053D5CBF4D8FF643 +:10E5C000F3C1E9EFFE6E96A387AF16EADA6E1D97E8 +:10E5D000603F05B7DE20E88444CAC02F6330D1F223 +:10E5E00097316F6521CC47CB670B573716B2BCDC30 +:10E5F000E5F11BD9CAF8EDF10C89C56F2E9DDF7EC0 +:10E600007E39FC46B25355FAB7B75C0B613F91D7E0 +:10E61000307989EF092BE6AF7D1295BB6F6528F83D +:10E62000FCAD0CBE8FEB4FCB76BE49E1332B23B054 +:10E630003F03EC28E22B013AF2C46C95B047CBCAF9 +:10E64000ED41B295D9DFE02700BE373AC993EB120E +:10E65000E221DD196C1F21E5FF4330CEB977FE7A48 +:10E6600008F0D3907B7604CBEBFE11F3A0D62E9668 +:10E670003FB77A635857A077F891FE845C0F7A9978 +:10E68000DED1AE2BC3C5FCC2A02386E37CE6627C50 +:10E6900028F20A5B5658301EBCC51136B37847883D +:10E6A000805E9A5AAE63F93F6EAFDDC0E3ACA6D28E +:10E6B0005709E4FDC878566FF766E9AB4A1A6DFF53 +:10E6C000A67CA217F73996FEB4B500D63D5ECF9F63 +:10E6D0000F0CC1BAFFC35781CF97B9741EE0EBA9E5 +:10E6E000A5AC6E94D4A6601CE7CDD20F1CF312E645 +:10E6F000EF27268F95D2C974EA2C25D639DE38DE6D +:10E70000ECB126D0D7676D5235B39B3D03660C67DD +:10E71000711AD4C3A56A782C7319F0BB2FA6577C45 +:10E720000A70BEF61A868FD3BB8C61907FA7F9BEA4 +:10E73000A15E74E1E2F4F39D22551D82C3D0910BDA +:10E74000FAF18CA47E6F71AB0EEB0016B54A244C27 +:10E75000BF77FAA9BDB920C73F7E626FEE9C84F9EE +:10E7600068DF13578BF81E8F776AE3D7FDC5AD4579 +:10E77000BFF39B48C034B0A7FFF9DA3F63DC7A4EA1 +:10E78000178F7BFB7C831CE04FF1FEDAF146BB194F +:10E790007D489D12C64D44DCF6C4E19F4286288E1A +:10E7A0003F7357BE9C58272AAEE338DE6E06BCD1B5 +:10E7B000A5985B59BB3F7CF5C78FFFC1F58FC0DBC8 +:10E7C00089D68103008E8606AB42D8FEBD22B0F703 +:10E7D000B7118B17F8C990E9B282FC12E71F7C6968 +:10E7E000665787855EA9BD96935984EFDD2DFBB1F1 +:10E7F0001EF14BB90DF76FDEAD6BC43AF73217FB64 +:10E800005EB6CDBF7B01FA391D58F74E5AD5F04D93 +:10E810000728809EAA31A09E1270BE6ACE5DE8EFE6 +:10E82000F6819F4D403799E5EC5ED095CFEDE52818 +:10E83000E643CCE5C4067181E6B1219C8FC04F90C0 +:10E8400075275297847632D4EF24A562DE37C4AFA1 +:10E85000C49A4AE2799024EE1F134DDE838AAD10EC +:10E86000F413F304310675400FDB3BDA0A59DE1866 +:10E87000ED4F1817EECF2956306F00FD0CA3BE9D4B +:10E88000DEE274C9EB3BA78AFBB5963EF32C5361DD +:10E890009F14ED9F43F520D87FC4AB57ED93DA4A20 +:10E8A000ED66F0EB441E5B277794B8D00FE98E42FB +:10E8B0009CC55066F2805E4DD2751401DEB4796D50 +:10E8C000DA2F9FD55364DB41AF887D500D2B26F89E +:10E8D000619F41DCCED8CFFCA3867B2AF0FE842E3C +:10E8E000962708B61A711F67B053C2BC5C83DF104D +:10E8F00036613CC4D304F80A513B0CFCCF763BABE9 +:10E90000036BBFCEE60D91C4B87AF4B17B31AE6E25 +:10E91000C57CE4DF9BA73D9F4C013032210F37C0FF +:10E92000C4EB0D59DC3D9DD393C0BFE06791D74D3B +:10E930002EF6E783C5FDE5C6D0AF2DCECBA87F214F +:10E94000B73DF88DF52FE4A31BA0FEC504D63C7F90 +:10E950000ED3A27A33BEAFD1ECC1FC5DFC399C472B +:10E9600061EA94F8FBED374C1C8475BBBC9E66D6FF +:10E970007AA8C37FD84C54DF4B9C9FA2195F4FC726 +:10E98000B77A44FF7BAF9FA8601E9BB7DFFD21D401 +:10E99000FB3CAC578F872428F6619A7ABEB72E6B62 +:10E9A000C883EBC7F7E86FAACFF7BAC6F4E8F10758 +:10E9B000DE9DDA36D203FCF539D6410B7D1C74B0EE +:10E9C0007A18ADDC3AE09284FD3B0954EC9A993513 +:10E9D000787E433C8FDD35CD07E758883C7670A5BF +:10E9E0001FEBA141FFBB50FF9FFDF01580D2F4D378 +:10E9F00068FF07BF52585C89DA1112A543535705C7 +:10EA0000C64FA13C17F4A6C0FF62AE97C05607FAE6 +:10EA10000E6EBDED091D7D9EEBF6FD078ECBFD4014 +:10EA2000ED7C4FB9D8BE816051E5669007E47189ED +:10EA300080DE5E57F419DA190D2F4C1C9358CFBFA6 +:10EA4000A8F311560FBE53DFE7FA4FB9983DDAF03D +:10EA5000C27318173D1D66DB886A95F0DA71109F46 +:10EA6000A995C1D222A5E19A59A8FF67D275D075A0 +:10EA7000FD86DB25C19D3787607F4190FE05906D47 +:10EA8000F12F407B7FCB4C9315F248C1A2394B91BB +:10EA90001F6C161FAC5F3BCF781EFC1E0BC62DD71C +:10EAA00075EAABC16E2AA376D2AFE87C7352A75445 +:10EAB0007BA95CCAD2ED2EF9372BD40FF4AD87D7E2 +:10EAC00067323DDC22F943379562BD2749AC47CA1E +:10EAD000EB64F6D84597411587BFE86276E2F850B7 +:10EAE000F704A0B997946812D8C541E2FB14FC5C06 +:10EAF000E2B77A601C380103EC2CC72A0FC6854D9B +:10EB00008EE80F47A2DDA4A09F21FC88732FB038A8 +:10EB1000DA5277C0EA86F88E2EFAA39B006E3F6425 +:10EB2000FBAB89C2E44DEECDD65110F7323BA23F8C +:10EB3000AAF6601D11C61F065CDD827878C9416C9B +:10EB4000009F09A11A454AD033426E4C88EF637288 +:10EB500060BCB5928B97C1145B1F9A90445B2EA644 +:10EB6000F5D80587FF3A43819BC25E904D01F4675B +:10EB7000AA6652FF10E8724DEC900CF17D4737DA2F +:10EB80008BF51D127EA7BEE89758E7B784D793C5CB +:10EB9000EBBA9428D6B915BA93785CAC85D103E961 +:10EBA00046FF973CC3E04FF526D6BFF5D8ED4DACF8 +:10EBB000EE888F67E079897A1EAFA180C2E7256E63 +:10EBC000116F5BCDF5AFA8D763DF258AA72C31BEC7 +:10EBD000B0711AD524382F4F0ACCB7D3EC1FE7A653 +:10EBE000EF9FA895595CBC35290C9B72374ADD3ED6 +:10EBF000885F864AFADE7F7413FFEE8003B149987E +:10EC00003778A1BF7A6056FFBB79CC1558875FDA99 +:10EC1000F9E924A00F524D901FA9BCB8A47AE019BD +:10EC2000800FE7FF43F5C05EC9B7835EE7BBEDEA3F +:10EC30007A602FC397C8AB6AEB80CFB9230AABDBEE +:10EC40008B3EF604E8DD4E23D6034EED7CFD18C462 +:10EC50002FA79A4807E69935F6C3C9B49B1B004F06 +:10EC6000E73FF9F0B1FB09D4913FEF65F5856A7B89 +:10EC7000A03FFB1F7323097E6248D0CD3FC9FE171A +:10EC8000F23AC8FDA93352ECA14258DF7E9DADAFE8 +:10EC9000FD480FBA45DEB59F7A96AEBEEB5944DC0F +:10ECA000B93A9AAFCA733D1AE783CBCB9B6D819C6F +:10ECB000761F793385D7A92912131D24C7A0CA9BB3 +:10ECC00029F6C2FEF266117CFEDC107CFE40AFBC71 +:10ECD00019AB7768D99FE101FBBECE197BF2490FD2 +:10ECE0008C67C0715A5E480A433D7F0B877FDDA564 +:10ECF000E7CD7EE5EE236FB69DDB6F1F14C91103D0 +:10ED000085EB76C2E61FEA12F93319FDD8D88339AC +:10ED100062FEF8FCFC83C3305E3457E4C55E62716A +:10ED2000B4B93CFFF5C1F442AC67EB0FCE735BD5D1 +:10ED3000F985D7389C2F982B301E7FD7BF4FC3F84B +:10ED4000D40288E30F84B8561B8FCBB3789EA79567 +:10ED50009D2BE0D929853D2C3F6392D136B4C970F3 +:10ED60007F0915A35B40F48628D55C496F4B146A74 +:10ED7000F4B9A785B6A9D1AFAC55422EDA6FFBB175 +:10ED8000248C9F3DE0F0E07C1F686179EAD07A290D +:10ED90003C988D8BE7B5855A641F8CF30737D3F306 +:10EDA0005FBB0D7D9E0FD1A2E7F910FEBD26224765 +:10EDB000E02A4BECFA804DA9EECB7E10E3B5E81BC0 +:10EDC0004D1500EF1C762ECC05836F26C697530B8E +:10EDD000F1FCA796E4C6D66AF61C79F68239E6C736 +:10EDE000E7572BCC20259E5498EF7B6E9E5FD3C0B7 +:10EDF000797E9BBAADCD1369F7BBCD258121EE811C +:10EE0000BDF783BDC7F5DF8575F91C2F5ECC97B4C0 +:10EE1000E83DBFCD077A5FCBCE776ACA6670937341 +:10EE2000D8B5C05E85E7F0113BB7E3089B7FC1D53D +:10EE30000E09F8A1C5CEE8F61F9DB776BEFACC4202 +:10EE4000065F3BE3D796B55298C18BCDFB52E322C8 +:10EE50000333FFB972F103C9FB64241FDF43B91008 +:10EE60007A508F7C778284B3587DA80DE5E61CEE3E +:10EE7000E716677AF0FB5B6A0B52209F3AF7D41AC9 +:10EE80003CA769C2CD569C7FC34B66F4E3EA574664 +:10EE900073819EB57084D92A429ED2E7731C849DEB +:10EEA000EFD3AACE0F6AF3BE6B53FDE3201FD450FD +:10EEB000192D84BCD123F207BB5F67720DF56AC3BD +:10EEC000CAD8931067FE6E6AA002FA9DBDE7DD49BD +:10EED00092075F47F9767EFF10DCD739A745BDBFA3 +:10EEE0008DAC57E71F496B2AC6D549BBFA3EECC328 +:10EEF00052BDD72B1FC9EC9A8D86C050B03BAFBD19 +:10EF000086D55B7CB2482680CF4FCC84E7F9859CC0 +:10EF1000F51626EA81D9FDE295F60338F3FA57D1C2 +:10EF2000BF1EF04AF159C7F1FAC9735716025ECFF6 +:10EF3000EEBEB210F0BA51DFE603BE18981E980379 +:10EF4000F03839D18F76A1A8F7BD547A5B9AC9F50C +:10EF5000E0BF480FFF407CFF32F530FC498C97BC86 +:10EF6000F45756971BEA62FB827BE274A7F17CB3ED +:10EF7000F35FC912C8E1FEC6B371FBCE652221B0B2 +:10EF8000BFCA2AA3F85ED99F650276A0B07FB5F309 +:10EF9000DFC0F1BA23D377C105F8E571DD5A3EB67B +:10EFA00029FC39B3B31F97306E6BF28452C6A15F50 +:10EFB000357FB40EE5CAAF70BF07E9926CE09F2CB5 +:10EFC0007ABC099F9FEB9C8BCF655324027E583DF2 +:10EFD0007D0EED35E3D5F5DBFA3D259144BF97CEA7 +:10EFE000E333F04B931C3103D06703D8D5748A0DFB +:10EFF0000A8B6F373808C6554A3BD57EA2C8DB6EF0 +:10F00000F1B3F373B67449788E56BA21909F0D7898 +:10F01000D5E46F7F91E93B96E9ECC9BF373A7DBBF8 +:10F02000810E1D06928BF57A7AB11F51BD8FB3BF49 +:10F030003AB897057F7CABFD340BEDA42F881FED0C +:10F04000A403107BC0BCFDAD685789FBBDEBE0C2DB +:10F05000AA7CFD02BEDF7601DF6F0BF23EA291F7C4 +:10F0600089EDBA843AB8485FF50C09757089EF25C7 +:10F07000D6C1455472B28DEF07598679F220E59BCF +:10F0800015A37AE8BA8EF03F9B621FE07EA09D46F2 +:10F090008CCFD5F1FADC60ED09F47B82B0BF88F14A +:10F0A00037AB63E7E755D4517F12EB943BD475BC83 +:10F0B000E7FFC9FA45F4EB2FEEFE670D7F8B7589EC +:10F0C00075D475498C1F35F3D4FAD1DAF8B9F083C9 +:10F0D0002F55CEA564FD6BE55C5696A0EF7F4CCE18 +:10F0E000F5CA430C8AA578FF0979888F3D6DE91030 +:10F0F0009A6C9518BD4ED2597D2CCFA9637510DA44 +:10F10000FCAF6712E63545DCD7F4BC2EBC3A1FFBDA +:10F11000635EB77E7F32D625D47A6AD16ED7E63B5E +:10F120001793DD9300055F9023B88FED1FAD2FA8D7 +:10F13000CC8AD717E45F667DC175599791EF7CD56E +:10F14000FA795A20814E2A8BA90350DC7F1DD96D94 +:10F150009CEE92781D8A4909117BC2FBFDBD776741 +:10F16000168B1FBECAEB9F1E4E4EC2F3175C06B62F +:10F170006FC325B33AAD5CB7BF266B0CE81586C7E5 +:10F180009FBC701B81BAC79FE83BF03C8450BDD543 +:10F190000BFA50C4ADC4F8BFE2F1D44BE59FBBFEFF +:10F1A000C9FCF36D722324BE77A9F9BA4D14060980 +:10F1B0007CA5E583FEDEEB4FAE6CC8F2AFCF42B963 +:10F1C000E51B81798F4B944749A5545E83BEDF636D +:10F1D000F480FF61E2FB8BC87AB7CA7F9FFB700E99 +:10F1E000EAC34FCCCC1F11FBA0C4FA1FEF17DE7F80 +:10F1F0009FBDF817A7FF4958CFC90A1FEE7B78209B +:10F2000099E995D853ACCE48BB1F48AB4FC47E1686 +:10F21000F1BD4E21CFFE45F2F4B57F923CA5FA1523 +:10F22000ED8D7EF3BABDDE0FE177CB2ABB7D3CDFEF +:10F2300085FB39C4BC82DDAC3EEF6D8E3F71FF595A +:10F24000AE7733B37DBF033C9C7DC764823C6A6963 +:10F2500029939F0D7E2BE6211A3A585D4EC34A82B0 +:10F260007103B1EF775646200A72EA8177AD787E56 +:10F270006C43E7F6D602AC5708A09D78EE1D76DF0A +:10F280009C113809E307574655F98EB28B9FAFA9F9 +:10F290002EC5F9A2DFEF30AAF75319B2993F2FAE6E +:10F2A000BA6CA1B7A99F43DF3B5BCBEACA830E9F31 +:10F2B000AD02EB14583C3DC9D38D71F0863DA824B6 +:10F2C0000816B9C2F37BB3916E1AF65494E0F90BA9 +:10F2D0001DE6123C47E83D2BFA6B67EFC90C433C37 +:10F2E0007BA93BF017986F7269F83AB057F3E8774B +:10F2F000209E7E76F77525185FD4F09DE0B7F83E26 +:10F30000DA3B4CE166A9871F37EA997E147AED0C47 +:10F3100018C74ECC7BB03AC3AE6964BEB5A76D7555 +:10F32000A8EB2F77644E3C03703E93A5F03C39CB9D +:10F33000CBE79BA8375BD09B0EF3795E7E1AAFA715 +:10F340002021534F1D45C1B7E7E5C5FC445BE4E50B +:10F3500093BE62767381CD807491DCCAE406A17499 +:10F3600001F6FAF858F704D8BF36A83D321EE0354A +:10F3700000C00F312E12FDE148C87FA429E321FF10 +:10F38000F1D88A51074C0E8847755F0DA8F1B4D9A2 +:10F390002AC1559D95E12F82FA4AA2341601FD57E4 +:10F3A000BEAD67758F6B9350DFB7E7D661DDE3B90C +:10F3B000778DAA7D46BDE43459ED82B85341EB7F89 +:10F3C00062FE21798FD4673DEB427022C6B0FE10F9 +:10F3D000C74A6EED0E95435CE641899DC149672F92 +:10F3E000B9209EA0C86077CCED64FBDFE7B6D92BCF +:10F3F0004D284F2596BF19EF4039A9ACBD5E067F59 +:10F400004F692278DEDDEC6C76DEEDE0769B0C78E1 +:10F410007FF96B5D9F79B91BB27BEAE8005CF5C6AA +:10F42000D821281D10F944513F27FCABB87CE5E7F3 +:10F43000C20B7DA4B5637BD9AF5C1FC5ED780D1DF4 +:10F44000F7F79EA06F41CF2FEB09DA612F4B26DC37 +:10F45000C726E8BA45EC2BF89AC585F3787DCE89A6 +:10F46000757F19C1CE8114F99830ABABD247D76400 +:10F4700021BCA2D78460DD7BEC724331C6D31A7005 +:10F480009CB5ECDCBABCD681ABCB4BE16A230082E5 +:10F4900013FB96E4015F86281D0CEE830E8AB35998 +:10F4A0001D94B23609F1A66CC013BA89624F47BCED +:10F4B000298F30FC1466333A17F96011F7CCCC0E63 +:10F4C000ACCC1E93B0FF6C8585ED3FE3FBA4935756 +:10F4D000BCBB0BF6753DC6E3CF075E1A86BF9F71B6 +:10F4E00061AD22411CEA82BD260FFCBD07385E9348 +:10F4F000956E62B326D2E701ACBF2DD8CFEA0815CE +:10F500007E0E96B2D6B11DE039362D8075C657B73E +:10F5100044F0A7275EB29DC43C1FB58B70DFF8E9AD +:10F5200017246117A9F4A1F0D7B47ED88FB3FF7761 +:10F53000FDAB27E372FA32FD2BA2F633E3FD85DF44 +:10F54000A8F52334EFF767FF105F485567F302C74C +:10F55000BBD0EF995C368AFA9BF8BE6F1236C3FEB9 +:10F560008CC9504BCBD68375489B248B17EC246DEC +:10F57000FD51BC2E88340E6175298D23D9791E8DDD +:10F5800057C255D42799A13E25B10E3699D5179962 +:10F59000A13E85DE6FEE779FB8A709BEDF7E9F4D47 +:10F5A000EC136771FB6AC2F3163B701F79EC966C23 +:10F5B000DCF733A19AC50353FD0619E8F2F9BFE958 +:10F5C0007C207763946FC1BE4A1DE47383BD65A63A +:10F5D000CFA1EE25BE4FBC86F4B94F5CD447897CE1 +:10F5E00071E6908D12E89F78DD4AB067FF387CB7EE +:10F5F0007DA907E3CDF13AAAEF125C67A590332607 +:10F6000035FE527CAC5FCA4C03DA19E972E029CCB2 +:10F610000B6EE936037FEECE2E40BC359787F11C8A +:10F62000E4D4E2368CE786D37CE7B29D3DF423E652 +:10F630004736B1F59F87FD6752CF77CF2FFA732EEC +:10F64000D853955D4646879A796C899F5343BF434B +:10F65000AFBA1C867FAFC6BE15575D8EA4AAE31352 +:10F66000DFEF6F9D821EBFCD6ED7D257A892E3E722 +:10F670007D7398D53FA9E9EBC0AAEAD127A92C3917 +:10F68000B8CA8FD7F366A94307754AE6D86C90804D +:10F690006FE6B4DD08E7999C4F8EE5C2F9276FE766 +:10F6A000DE7513B69DB1F7A17D2AE769D61E1C7BD6 +:10F6B0000CCE43F95BCE889BE0BC93F3F0AD4C429B +:10F6C000B2B615DC142A867D26D135DDA09F4A35D9 +:10F6D000F52E9A731BA02E13CF99B0327C66F0BA28 +:10F6E0005852C5ED77C854D176B3BBC40BF50C5650 +:10F6F000E2D9D30DCFB38DEC7C07C2EAB09A07E70D +:10F70000B3BA094EEF249BC7B3493404F4DB9C6FB2 +:10F71000C7F7E3F27A8F91E7B1D8F78F3EC7F6BD0E +:10F72000897A5F426C3960F7583D44D516E79E10E0 +:10F73000C59603E71C348B78216FFFC112B83A27B6 +:10F7400041FF1E9D787731FE8ECBF3F70E82F54E8A +:10F7500036A8CFC116D79772197D9CE7E7456EB3DF +:10F760000426C138C792664F82237867A65518ECE5 +:10F7700068A73DA50379E4E474619FC1E667AFF231 +:10F780004BF0FB29E2BC466740C1780009B4EB406E +:10F790007F3A4FFAB1AEB0CE14CB55287D194D81CA +:10F7A000E9399057AC397E17E615338FBE0F7520B7 +:10F7B00047F56D1352405FE4F3F333A8E317A2ED6E +:10F7C000435979E8F7C5CF771D2CA17C983A83ED92 +:10F7D000A79D423A148CBFD8D8FEAE49A5F9DE6683 +:10F7E000FABDA9BC8E64D2317F0AC40126DD16554C +:10F7F00058FE26A624D66D882B71E93D897C709D24 +:10F8000027A14DE05C6875FB06AFBA7D53F9D7437D +:10F8100012DB0388AF1EE0F8A214C5FDD6A1B1C467 +:10F82000C6D6C5EA139FE67EDB301731E541FDA45D +:10F83000430A815F306C6F26E665F696136CA7EF7E +:10F8400034ED3025AE7F83CCF2BE3C6E2E7EFF09B8 +:10F850009E815E7DFE9D748457BA5546790A117566 +:10F86000A0B7B22C9305E4BB8ECB79B13F7D628A01 +:10F8700009CFED6D5ECA7E37427B6E69B3DEF60A54 +:10F88000E0B1F96338928AFAD9C986889C02F8A255 +:10F89000BE8FA3471E0BFA81F1AE01BA1FC37E9F34 +:10F8A0008B52F9A0C473E39B9D6CAECDF7293CDF6E +:10F8B000C77E27A428FEBB2194ED687FB02909F2FA +:10F8C00009CBB7E5887512C507FDDD44B4D97EAF15 +:10F8D00074DE16E7A51252A1E0F94492E8D784ED50 +:10F8E00047793FA9EBF53F017D0C4AA1EBA1D7D7A2 +:10F8F000723C48DC3F958F6E423AB1063C4027DEB1 +:10F90000A4BEF71F75E4303B62624AB90BE2EBCD4F +:10F910006EAF0BEC2A011F715F8C2B9E8BEF79D39E +:10F92000FA1EF7352EAF3BF83E68EDF3977364F59A +:10F9300077F5745CEB377CD7A9FE6EFCBD9CBEDF0F +:10F9400013F7457FFC59AF32E03306B729BC6E96FA +:10F9500014A9EB5D48B9D7C4E4BDBABE65B2B4D250 +:10F960000DFC799DA9BE2B4ADF7F9DD3C96439F078 +:10F9700047C837BC3EBBF020F06735FC30011DE7BF +:10F980007A125903C472BE22F013FB409417C78049 +:10F990008F1A748121A9B4FD89BE6DD0D27CE4AFE9 +:10F9A0007772C6F49E9FA0C3F83C29FD01DE05FDD9 +:10F9B00069E72DE880DCD8810582DB4804AF2EC2E0 +:10F9C000EAB2A9FE62F5D79E9C9E7551E29C646ADC +:10F9D0001C04FAFDF5A610CA9FC9F61F611DDAF9CD +:10F9E000BCC03998D7CC919FE2F942C45583F61632 +:10F9F0009DEFF97FE57CA18208EE0B3B50D87BBDE3 +:10FA0000EA913F36A8EA91C5FCB47C2CE61124ECBF +:10FA1000DCA8095DDBD1BE0BCEB07A61DF4810EA0D +:10FA20006C4B319F8675CBFBB85F169258FD702FDB +:10FA30007BB1FFBA65764E41BD8D9D1F24CEA1FAE4 +:10FA40005E81385F88CD9BCA2F7EBE10B6DB6B3CD3 +:10FA5000E8FFC5EDC6F9CC0EBDB6D0D202E735F64B +:10FA60003E6788C5F7C85EA387DB89A8BFDB93D94B +:10FA7000773E31B33AF904394EA4F49EF3CF36EA17 +:10FA8000993DE8CDCD677941D95B06F8D802792B4D +:10FA90005DEF38E4C0F4C0E85CDA6F7EB12F177E0A +:10FAA0009A65AE81C519295D6DED26506ED7F8387F +:10FAB0009C0B7A1D697C4B1E88743516FACF1CF698 +:10FAC000293B2FB487AEC6E53A99DC0421F86D7C5A +:10FAD0007A322D3001C669B777BCD7500A794B23EB +:10FAE000C25FD4336AF937613E27F56C3E0E381F8A +:10FAF00099CEE7FABEE67329F49D48471984D1717F +:10FB00007F740EFB069247F5D0F90012B81DBE1B9C +:10FB1000A7F735DE56DDC03EE6ADB322DE6F9DC5EC +:10FB2000F231C12466A7425EC69D0EF127F6FD5B49 +:10FB3000D732FAB8D56C447A99D6558FF91752C591 +:10FB4000F2295EFA1FCC6726F14D849F58B9D93649 +:10FB50000DF781CE98AACEB7CC344DC6FCCE2D84FD +:10FB6000C5D36E9DA157FD7EA480C34CB2FE53A8A1 +:10FB70000F99A9F9DD482D5CB4F91A018FE6F26FEF +:10FB8000E6FBFB72E3799D219799D769C945F97422 +:10FB900069799D83FA189E23F09A73E1D6A5942F74 +:10FBA00086FCB818CF5B9F98BEE8F10DB4FDB32D6D +:10FBB0005760FBB5F43B961F85E78F1562BB4AFE85 +:10FBC0007436F04151D9AC29704EFD41331BC765E5 +:10FBD00009B4C3EF8EB846148C0297ACCA10C37E2A +:10FBE000D78FAC1F0D75355516D63E52F25FA3B0B8 +:10FBF0005DC0DBA35EBC02DA07A54F67F795171A55 +:10FC0000562445E0F7C5AA5259FFA9A39ECA8438D5 +:10FC10004155256B0FF356AC1D08CFE5CF66F7A510 +:10FC20008F7FC9ED63616FF939BFEFF51D6F81FDFE +:10FC3000667EABE4857D06FEF2E3EC5C3113AB4BF4 +:10FC4000F0FB4A143877B2D2C7E27B13AC4D6E900A +:10FC50007F37060CA510C7B559F35BE07CE701E5DB +:10FC6000156300DF13A81906FA8FF2D5F3C0CF335E +:10FC7000AFFC343705ED10355F09BA9D26F8A94A67 +:10FC8000CD37541E74313CAAF9818EFB0A8E7B95C8 +:10FC90005A2FC5E5BB866FB5F4D8AFDE276A391891 +:10FCA000D74F6B3A902EB309DB4FB40DE894F1EFC8 +:10FCB0006F617E06B9DB03F7F324EF1558A8D18FE7 +:10FCC000FD20E607660F19D57B5EF04711F6229BF3 +:10FCD00081CD960EDF65CFE97B3EF83138312FFAC2 +:10FCE000FD13089F356C3EDBA446FEFB22CC2E178D +:10FCF0007E6F83586FA77ABD6516B62FDE45A8DCE8 +:10FD0000C1D87DC915DF34EF20D7B3334CFE078D42 +:10FD100032FC4EE15CC4F36D24F41CD837EF58027A +:10FD20007F84F9E8E4D0FEA804BF0FE2C37C32C5AB +:10FD3000E3174CAE33BC887969E1D1D08F5CD5CE66 +:10FD40005B0B871EFC74A37DE6E6BF23185F9766F6 +:10FD50003DCDFC770462254655DDE9911A56572BB7 +:10FD6000E675442245A827250BE651E37127AD7CB3 +:10FD7000EB677F9CD0CF629E77F3FD595FCA4CEE54 +:10FD8000DDAD8BE03CF3AABBCD00C7F2BC02763EF2 +:10FD9000109F7F737908FB1964A9CF3C71799E2C61 +:10FDA000F260A4CF73DC3CF956E08B3B4DFCDC3AAF +:10FDB0000D5D104DFEAC3F3A11F1BB4AEEB7C4F3F6 +:10FDC000A99A73E2E698FACE9B4914BE59A9BDF1EF +:10FDD00020F2693768E374D7B1F8D50D3C4E37A1EE +:10FDE0009AE127754532FA75A9A5471532BCE73C5B +:10FDF0006B81AF0B8E40551EE635A263208EF0E678 +:10FE0000989F611E499C1BA9859F3F4F16F1C64BC9 +:10FE1000E297FEE6FF078B7F3A7CF713A91BCF839F +:10FE20001BEDE6E79192403EF093DD965F01F1070E +:10FE30002A772F5E0467141E51FCEE74066E87F756 +:10FE40006E23FE8950EB9D5A1DD0B3F83DC1F8F1E9 +:10FE500032EE474EE4FAFFB367D87EFD2ADFD04783 +:10FE6000C7837D7A584FC21EA81B67F0F96CAB0E92 +:10FE7000F5FEC23746BBC07EFF80D3E3904DB2EAA9 +:10FE8000770887862DAA733D86ED4C55B587776434 +:10FE9000AAFA8FEC2C503D2F895CA17A3EFAF0280B +:10FEA000557B4CF73855FF2B8F55AADA63A3535473 +:10FEB000FDAF3A355DD5BE3A76BBFA5C9290AFBBEA +:10FEC000281D7E3F81C1E3DAAFE6A8FA9F49997405 +:10FED00018F872DE7A56275E4196A8DE5FA2ABC3A1 +:10FEE000FA6BD2C6EC9C46FA1FDF17AF607D1AB5DD +:10FEF000EFE1A701166E52DB41B55D1BD6802CEEFB +:10FF0000751E86C6DED1DA37431C35706C3679240F +:10FF10008FFFAEF895E44AFEBB345ABCE2F9029F6B +:10FF2000BDA5433F63D91BCCFE5FB68BD5DF1592D1 +:10FF3000C10370DFD9611D094B70CE42E3C6F15297 +:10FF40008F9DA3858BD1A5C6B3D9A3C67352911A31 +:10FF5000CFC95E359E0794ABF16CF7A9F19C56AD05 +:10FF6000C6B3D3AFC673C64C359EDD01359EB36AAA +:10FF7000D578CE6954E3396F851AAFF9A1C5AAE7E0 +:10FF800042AE0E6C5DA6BADF2C759451494AE6F973 +:10FF90006BF17C89C16DDFEF933E04FE43F43FC6F5 +:10FFA000CF8D58CFBF80E21FEAF9BF20EB0F414A47 +:10FFB000564B070D9D1B30EF76B974F0761EB75F78 +:10FFC00005FE2FD17EA5FAF2BDBC3168E7BC0FF269 +:10FFD00061E610EE97F8FBB67384DC4AB42B12FD91 +:10FFE000EEFEE4592F3DCAFDF07EF5A8C60F7F074F +:10FFF000AA9FD05E5F8F71AF599CAE3F875B632134 +:020000022000DC +:10000000EEFA2CDA07EFD08994D379BD03F31E0101 +:1000100076C2308C93DC41227A3C3F1C2A4675A87C +:10002000BFB04EB386DAED709DCBED87F93C8E62A2 +:10003000340588C789F193BC74F86E7637EE33FBCC +:10004000BF17F44F2B008000000000001F8B08003A +:1000500000000000000BE57D097C94D5B5F8FDE6B5 +:100060009B2DC92499241012026126210B908449EA +:100070005804451C9660D4806193C58833498090AC +:100080008504D0D7B4A5CD40C2A28536B4A8A8A80F +:100090000302050B345804D4688745A44F5B636B97 +:1000A000AD4BCB4B0045F618B4D23EDFF37FCEB953 +:1000B000F766E6FB480AF6BDF7FBF5F7FBE3EBBB9B +:1000C000B9DFDDCF76CF3DE7DC3BECED38C612196A +:1000D000FB06FFDD717DCA988FB1DE8CFD01FF84C8 +:1000E0007A231C455607E4275A1D0F3D069F8E189C +:1000F0005879B30DFE28847E46436A2CCA9E96DD4D +:100100005D3F2BA13163AF2A1E0F1B0EBD265A5D2A +:10011000DB15C68624316B622C1427F853A64532B2 +:10012000D6C761A07AF04F61F18C0DB6D2DF6C4F6B +:10013000DFE6A531A9F8973FB628FBDB8F9BEA7075 +:10014000273B4604EBDF68BD6673F3129C6747B537 +:10015000CDB5D5C9D87B5804ED9EBFCF1250A3189A +:10016000BB62B2AD55A219FB2062DEF1DE0EC69E67 +:1001700009F764215C66CFBA6B35E69523718EA5CD +:1001800030BF2BDEB6910CE66DB17A5C585E65F53A +:100190000C8887255EEAEFC98856A1CF220E7FF82A +:1001A00023BBA8DBF9F3F94C50F8F89F847B46E3B6 +:1001B0003A8E185A935D080F63EB486CC76CBDA963 +:1001C0009F4B660E979EE0303EA27F31AEABCC6275 +:1001D00071A9D0E77885E3F54CDC83F36AE0CFF9C9 +:1001E00086A2F880AA99F79D346FBB7740620AF423 +:1001F0006F12F3B6F6167077641545F63CEF06EC11 +:10020000BF17E47EA0F8B73B392E317FD017E37FCC +:1002100014F216C3D5F7A643BE23DBE0DA0A459BEA +:10022000C3A1EB3CC6DE11F07EC604F958FABE1637 +:10023000BF2784F3F6098F1BFC0DD0BE68FCCB846E +:10024000A7E717DB683D5EE63033985F29739B7143 +:10025000FE9F8CFBCFD7DA001FF31D1E0FC2EDC12E +:100260003843F27B340FCF90A9306F36E6E6E89F33 +:10027000B175063692B16976BE84F9026ED399DB08 +:1002800084E3CC641E138EFBFBCB663703FAF83D88 +:10029000E098C17C67311F7D9FC3FC94DECF025480 +:1002A000FF01D646F9772372FAD7C1FCA63E919199 +:1002B000C60C1AB8FF1BCE17E8E5C15E9C5ECEF6F1 +:1002C00041B86FEC7D53F43B55D00BF0EB0FB11FF1 +:1002D000E0D7E1B929217C3391D30B33DAD3FE1176 +:1002E000DFB47646E5B0A19877DB1261FD770A149A +:1002F000DEE9AE2CC475E6AB36D60BE0DFEA50FD86 +:100300001618B3609CB72FAE0BFE45FA004F53DCB6 +:100310002A433CBFB902BE40BD3773553FD2C49497 +:100320004D93CE61FBC271D31BA361FD93BE6E1BC7 +:100330001E80B4A09FE9545B261FE31BF8DF976C77 +:10034000F3C41848EF4ED8676430FFBB076ACB0B85 +:10035000B3206F0DE6A73063B01CC63D8C7000FA69 +:10036000A9FB73EED86321ED186B52916FB63A2258 +:100370007B7D3A04B283D9E06F70DE6A71B4A71B4B +:10038000FE91E957F5AEB1C78026EF51DCBB1C44A6 +:10039000170E33D27F8991B9BBE3BB8B698AA01F4B +:1003A000C02EC8B37BC55C3B0BAF9AAFC07ADB1CD9 +:1003B0009EFDD8CFD2C99FCCC3F53123FBED308051 +:1003C000DBE2DF01DCA0FC543D403E03F8B3DECAB3 +:1003D000DC16C63EADB753FEB3FA044ACFD73B286E +:1003E000BD589F49E597EB5D9467CEA2D7B0DF92E9 +:1003F000B59F1B3D598CAD099378E4F35826E878F6 +:100400004DFF917F72C1786BDE3651BEBCB9695227 +:1004100004A4CBFA9F5A1901DF97ED525CF8BDB2E4 +:10042000C56DB6211F1DF3AC46F259F876DB1414E6 +:100430003BD5D714E601169A3DB0E82D1C6FC41FBA +:10044000CFC423FCCED68FA2F99CAB77D37CDC2D16 +:10045000EDC7E3A0FD85FA02CA273A8BDE45BA74E0 +:10046000B3CFCD587FF2EE76631294E7BB1537F227 +:10047000F75837F3FB017F9B4C7CBFD804FB05F298 +:10048000FBB8EC69CF3CC4509E7B3EC6F166C69675 +:10049000E6C7C1F729A3BC46AC37EB6BC6302FE9E2 +:1004A000FBC67CCDE1512DF072E97585E074E9C0A1 +:1004B000907B6F83FE5E3FA13215E6D579CD40F388 +:1004C000EAFC20DC0F3B5357BDA52FA5F661364C47 +:1004D00087F46159B83EE804D69DA9180D75C0FF90 +:1004E00017F67C2701E12FC7BD10DBFCD78F50DE4C +:1004F000FD85CB3BC69A3F7D0AE561BF04D7A3903B +:10050000BB6C62B3893F596D04EE878BCDCCC3F3CE +:100510009E2198BF10CE1E2C82FCC8BD49E3917F5E +:10052000703C4746509EA5EF7D22E5FB8EE0783B70 +:10053000F63CD9F98A03CBFDC4CFBBF63ED3F769AD +:10054000C855ED5B158EF37A15D6320AF8E3D50D52 +:100550001124B75E35B94ED6A1BC7EC6E6DA0EF5DB +:100560007EFEE3EF9E3A84E9FAEABCEF421AE38C9E +:10057000A57ECA7EBA6830B687FD9B25C23A7F71D8 +:10058000500984E53096BDF1F0CA44186FE8E6766C +:10059000435F4873B7290D980EE95F7002F7CD3EAF +:1005A0004E07C17DD86EA79A846CD7D7FFD11DB4F2 +:1005B000AF6BF7FBAC8D9F8FEFCB82FBFE60A5F995 +:1005C000FC0A27D2EBFB791E824713CDE3A596E9FF +:1005D0007FB89FE13A40A3C0797BCD2EDA6760B93E +:1005E00026C85FDA9FBAE55158E301836F0BED43EC +:1005F000255CEFB854E47B12E9A51AEAFB205F9D65 +:10060000EB8BBA15CAABFF32D00594C1FA3F7B67BA +:1006100001C263F1FEC726F5857A97C6309702536B +:100620002F7FE9EA246CC7FA3386AC7D697F43FCEF +:100630005C68F7A3ACF123904E8AD4661A87D5F094 +:10064000719E10FB176B03E0C40B92837A3F82CF3D +:10065000F83DB625E670120BE2A7A66585D308ED36 +:10066000877BAC2E15E9DFE94BACB505F743D8C75E +:10067000463B91B4CDA25FFBF4E4A26FB18F99C564 +:10068000BE24FB7BC2CC7C61D04F7FF8AEE03E6BDA +:10069000E6FBEF76900F48BF72FF8571EF728EA078 +:1006A000F66E94A749B0D9E6C23C939EB0903CBF89 +:1006B000D9F1A5DE5413CEE591D43F66C735BCD63B +:1006C00006EB3D1EEE9989E3CC17FB3733BA1C28A5 +:1006D000A7F784BBEF73D27ED8918C6B80FD712E0F +:1006E000E617ABA04FA586E853D69BDB1F3F0C77E0 +:1006F0007BB0FDCDD6D7CBCD655F1A582ED0C1B219 +:10070000C72C7E06F36E40F90AEB6A881C694539EE +:10071000C08E19AA8EC37E793B6FD9D5DFB2C83C93 +:1007200092130D8C750BAFD7819F3D203F0220EFB8 +:100730003DC0D763AF75A89CDE5B8F460F4779C974 +:10074000DC91403F775C33304FC87EA6EF07F05511 +:100750008FEB1BC7229827647F74B31833F22DB335 +:10076000C5FE73EB16F31F23F037A6F38308947FBF +:10077000CBBECC2339D8D3BA5E13EBFA35AE0BD24D +:100780004FD28A36201DDFFE85DD88EBBBDD383594 +:1007900019F51398F71338EFB15F18B4F3FE3A5C0C +:1007A00093BFD9F93FAC309F01F9F173B31FF9B191 +:1007B00005B7398063CBA22C3FF2FD0133CFFBA2FA +:1007C000CCA49FB644321FCA9196A9F17E9F13E52F +:1007D00021E3FA6B6FC6CBC344FB39F1D4BEAF053E +:1007E000408AF2E0FE70D17FED5BD958BE2289E4E9 +:1007F0004883C9BF3605FBFF81EADA0E78FBC06F7C +:10080000F099804E36C604EE57A1DF8D9FC7331C8A +:10081000E7031648AAC171CAC349EEDE66303C3808 +:10082000D586F5DC89B100EF03FFAD92DCDF980BD4 +:10083000791BC9EDD9CDF07DE354776238F63335B5 +:10084000DE40F351592D7D77F2761F9978BDB902BC +:100850005F1F0AFC005F13DF7BA64418916E4F3ABE +:100860004BDE7512BEDD890ACCF7A9B234867273ED +:100870006EC55D4EA297A627487ECD163890FD61C5 +:1008800003EB48D47FF9BF39F3B787213E679687DA +:10089000B5C30EC93E285F19E980F6333D6AC00230 +:1008A000F294CDC87777E9672938AE9BC6AD6E1E46 +:1008B000947A26849E4B2C2027A0FF43619E0F88AC +:1008C0004F0FE552F921504EBE017E3A5596B617AC +:1008D000F98A95C9F35FA014F1F07A8795F4CD9E5B +:1008E000E8A101E13F54D029E26539C73BE85D94B6 +:1008F0006F983D98CE25CF9938DDF8F685115E0BBF +:10090000A65909CF9DB3C3B758A0FC4121B71A66B9 +:1009100087BB15A8D7F092C56F70D27987EAF95EC8 +:100920008BA47EABCC3C5FF5621AD1D301B37FD7E9 +:100930000E2C7F3D8CE8A12A8A8F5BF54A92A03766 +:10094000B773158EFB9A85E8A02ADC114DE5FF1ED2 +:10095000477432D9EAF91BC20BE8AE16F5822A7346 +:10096000203D06E07B52D0D5496883F8F3D546D2C6 +:10097000BC89E521EF69E8BF15F1E931F372F63D75 +:1009800095CA4FDAF9F827D7F1F18B7F52F9360380 +:10099000BC9D2C9A94381FE671B23682F4BF3FD7C3 +:1009A000A90173149E5F3A1E4F877A97979F1EB9CD +:1009B00009E6DFB6F2E364A48FE295D585D8AEB838 +:1009C00062F914DC377BE2CBE22A60FE103E4E492E +:1009D00071C7A4C07AC6A6787A615A93D5B600F5D5 +:1009E000E0CBE6D667F11C9114E7E983DFAFBC7C6E +:1009F0007607D78F3BD2713F586CE4F421F7D51AB4 +:100A0000417FC7533CFD53709F080FCCC3FD232289 +:100A1000AB95CBBBE53727E7CFB76C3FA0C0389588 +:100A2000E12D8B2955FD39D8CF052510A5A412FC41 +:100A30003CC84F17ED812884BBC7C0F5B3CA9DDA07 +:100A400075E13F23CCAB12FF807695CDAA3B0C71AC +:100A5000CDFC669C7F253307EB3B8378827E084F75 +:100A6000CCF6E779DF07F857EC1A9487E780CA9845 +:100A7000433FBE8DEA413BC927EAF579B99EEBE7D2 +:100A8000C3D77751D0FF4549FFB3CDF25C4EE35F4A +:100A90007EB90F8D7F61AA3F1DE17F5911F576590F +:100AA000783DA00623CEF3979C9E1E37F90CE17487 +:100AB000BE6744CF9571CD23112E520EC11C7C060A +:100AC000A87F616F12D597728B153186ED2AF726B4 +:100AD0006EE5FA993897E244A17EC52F78FF9847D2 +:100AE0003E3CFF4292188FEBC77AFCE9D75B9C62D1 +:100AF000A0F53E2EE577A4E47357C254807FC62646 +:100B0000B3A6FEE548F3836EE877905FFB5DF65F82 +:100B10009EA2907E364087B7BE6AC7610BF2D3F3C0 +:100B20008CF8553FAF9A147EFE7BE1852E3CA91CC4 +:100B30006FA0064AFA70703DDC8470FEB00B1F0F88 +:100B400025815CAD4418A404E17320D79384F2FF9F +:100B500032E6715F88817C16EA411CDE322FE1ACFF +:100B6000A7B3951F2E486A83F64F09F80042FB2071 +:100B70003D76E92F26385F64E1B9B27CD899343CE0 +:100B80006FD60E82ADA06B3D0B36E55A919F166E67 +:100B9000CEB59684E0A161E7B0130E80F3C59D4603 +:100BA000178AE506A3FFC7A84F37EC549B7D8CCA74 +:100BB000AD08DF8BB623BFC37A0B36C7E4A1BE2CCA +:100BC000DB2FDCF4F0A0B210B80FD9A9C54376B37F +:100BD000363FF49036BF0D6543EF6FDF2E37A0CD63 +:100BE0000F3BA1CDB30EC016E041B5723C1D1CE514 +:100BF0003AE1003C0DF0AB2EFC34C0366DFA64D403 +:100C00002F36ABAE34281FB0BCE89E6CC87FB679D7 +:100C1000BE0BD15CAEFA167F1F7058FEF1A413B85C +:100C20001F5E60CDEF4F063C2C68D960363A70DD10 +:100C30005ABA3D6010F4FA02B7972DF26BCBAFE7CA +:100C4000EB15D25E9A194A4F7ABCC3B8F7B9614224 +:100C50005575CB869D812DB3BC10081D6036BA79C1 +:100C60008319F5B61B8FE3E3F462733B101EDE516C +:100C7000BCECD6BA09ECF430F863DDBB9370DEDE71 +:100C80001F29A437787F95710CF781F67D73EEA646 +:100C9000F4BE025ABFB4CB2D6C51029190B78F7243 +:100CA0001C6A8376F3FD8A0BE75DD26809CA33F8C4 +:100CB0005FD93ADD3C368694C3FC171E3AFC3705F3 +:100CC000FA2FDFAC6DB708E42CCAAF8A6DDF58424B +:100CD000BFCB73E3AD2D5B545CF77C397FDF588667 +:100CE000EBBA955765BD847E730633B06FD4F62E8C +:100CF0003A8BFBCAAD1B793B10975E5C6FB5CDECB0 +:100D0000C0F5565B592002E67122D2ECB6C3F7ABB0 +:100D10009B22C91EB6C002FA641EA52C2C0FDBB99B +:100D2000A2B1DDA7EF70BB58751CC777F5730A9D9C +:100D3000A3AAD18889F9E7797E110BD03A904EDCCD +:100D4000A1EBF36BF3AC899FBFAA8C81C3088F0A18 +:100D5000D6C6CF4F8047B7841FC0AB0AD6F9412C07 +:100D6000EA5BBAF6CCE5C1716B6C5C7FAA39F48D95 +:100D700025B45C9E03E53955DA699F4B2F0AC7718C +:100D80005629EE27AD30CF5542BFF66D0823FA9DA8 +:100D9000BB85EF37A0C7A6235C366E4874A19E3191 +:100DA00017F4F230E49B45E1540FF45DB2AF748068 +:100DB0005E8DF6F68D31CD01DC37363EE6243D1AE8 +:100DC000F45F824BC7FA30FF5605F560AEC76CDCA6 +:100DD00090417AF8AB729F5ACFF5AE6EF4622A67F3 +:100DE0007DB81EFF112E25440F4E8DF7A4A586ACAD +:100DF000AB6CA53B11F79DB2696603DA9D58F9CD3E +:100E0000F90DB60B3DB203D68FEB38A3141D378412 +:100E1000E8A32353F93E3272BC7B87A847FE853294 +:100E2000C3D447EFC0F11E373870BC2E78BBDDE964 +:100E3000388F331BC2F290CE468EE7F69F93B95C93 +:100E4000BE470C676E3FA477887EEF483568D28432 +:100E500070A03FE8E74C3EB73B470E2F227B1BECD0 +:100E6000D524E7F5EBB847F453662EFAF7DBBB99C8 +:100E70008F840F9BC8F585334B94AD7C5E805FC833 +:100E80008FFC6918D9E9CE88FD47C219E86604D9F4 +:100E9000DB85BCDA20E8658389D3816F113F3F058C +:100EA000E985113D6C14E7ACB902BF6C3DD76B818D +:100EB0005E389CD7270A7A61ECEF480FF90EAE67CF +:100EC000DFE47909F05E9ADAFBFA7393C43733FAF8 +:100ED00047FC23FF46F5C13D077CB07F56FCF2B1CD +:100EE0002806F5CE199BE25DD0BE6AFBAA2837A47E +:100EF0009F197D517618FF9C5F2DF077036FBF809F +:100F000037DAD715903F8BF14F07EA3B3F9A82EBD8 +:100F1000FBEB76931D4542CD4E0B9D9F16EF5F4434 +:100F20007A36E4DB797ECDE72AE60F69EDE0153FFE +:100F30007F2CDE41F0F6251912300D243148176F51 +:100F400033B902685F7E4F75C130A03777ACC6F900 +:100F5000E9DBE33CAE01BE6B9A55AF39FAFAF21AFF +:100F6000215F6AF6FFE873B4EBD5E8ECEEE5C2FF6B +:100F7000A0B7BB37A546F6FA140DCCB7B05B500F3F +:100F800002B8B802C8B7309F3422136EB76DD8F5D7 +:100F9000444E3BEA0BDBDE8A52B2827677E997E871 +:100FA0006C2E7D0EED9A3DF1E36561870DE28BCBF2 +:100FB0002DC7210565001CD0795A650A44DD06F06D +:100FC000A8DA62223953B5E7F91D4F219D7D68A14A +:100FD000FDBC72CF1BEFDF8AFAEE3E53AF42BE0C70 +:100FE0009B121FC4538D83DBC9245E2A7EF586D9EC +:100FF00091CDBF2F8F0DE2A772DF6133CBBE1E8E66 +:10100000139A0F9BDB6CDDE0A9B97D12D989767D3F +:1010100065463E38F7BAC2FA38AF6F5FBEE58D2835 +:10102000D4C7104EB82F497C75E14F571FFA9FF275 +:10103000CA70AA67C773454FF85B827B07D17724D4 +:101040008B81F1CB3FB2F80B11AF7B9745E13ACEE4 +:101050001A6B399D3FB32A1EF5BA72932FDE4E29C3 +:10106000FF5EFEECC3447F0B95DA787B16D177A246 +:101070008174065F22AE6FFEE699B4BE05CC43F4E0 +:1010800057FE8C5AE487F44B232BD8D70D9FF41DC1 +:10109000C8F9E4EC56402AACEF2CDA6D506EFC5ED9 +:1010A00015E7DC25B47F3F2CD6CAD852CA7F29F475 +:1010B000B64BA95D7E656BE879B166DB9A56C4CF05 +:1010C000F9FEEE3E384F80834FC04BF906FA55DFEC +:1010D000CDEFC3F1C31CC691A21DECA313F03BD608 +:1010E0006F35B9D1EE1DD24E9CE7F8F80F89F1614A +:1010F000DEE1785E3D1BCFF576FDFA0A062AD2DEE8 +:10110000D6CA42E9AB27BEDFF608D1D517EF71B9D1 +:10111000B2D83FB580CA5B4D813E58EE3F3C43217B +:10112000B9606181EEF87A9B49F0B5B61CE6695466 +:1011300042E1FB3AD7431780DE1508E1E320DD9852 +:1011400083DF69DD3F15EB6823BF98F4A72D14F208 +:1011500040BF6EBD7CE83550F8E3847C90EDD9E665 +:10116000EEFD3941B9E0A371AB603F413DA3EA43D5 +:101170000BED1B557B4C45089F0BBB8FBE3F17CF1C +:10118000A1CD928FB5F256CFC7E52F8EE8968F2F5F +:10119000ACCBED9E8FE17BB77CBC4E21F9F63F9541 +:1011A000B7B0D391DDA0277E5DD883BC1D3B502B0B +:1011B0006FBF6459D1B761A1DD3B80F0A383AB84DD +:1011C000A75E7EBE9FEA20F8EAE527C3D0881038E4 +:1011D0004AF849FA64CC43E374D1B1A45349C75DDA +:1011E00074AA5FAF168EFA72C34046F3297AD9C447 +:1011F000ED672D0AE9DBD0EE78D270E253376D7FD0 +:10120000ACE97852AFD0BC5F976FD6D577EBF2459B +:10121000BAFA1E5DBE5653BFEAD051333F1F0434A5 +:10122000F52C75F7D039E37A3DC2CFFD3EFB3F3751 +:10123000FB902EFA7598512E9A56325F24EABBAF76 +:10124000A9A4EF5E717444A15EB22A8CEB6D57ECD9 +:10125000221FC3F31DBDCDAB512ECAEF1D61DC4E65 +:1012600072A5A8232A26E49CDEDEA246A13DB6CDC7 +:10127000CF0ABA8F136920B8B6B19ECAB9FE96AF2D +:10128000DA92EBD01EDAA4BA804C58D98A5951149C +:10129000BFD0927AEF6CF83EFF372A85015C09E7F0 +:1012A0007605E6731B317EA094A3907DC67C8F8F5C +:1012B000817595B6F03882B2755AFC2EB0CD880E85 +:1012C0003850EE68FDFD0BF15C978AE73DEDF70ABB +:1012D000B68EE8AD42C7171E61A7D5F3C516C9176C +:1012E000B92C57D863C8CFB154C8EB7C35EBDED9E5 +:1012F00000FF2B275466817C678BCA56E37A772BD5 +:10130000E4EF418700F2DB62E04B9C8F84CF45E441 +:101310009B8C9EF5928B2FFD65E4F7914E0E7C9C85 +:10132000837ED88B073E4C7F15F307FF94FC31BBBF +:10133000BEFE84D7FF360FE5F095D72D0CE9FBCA2A +:10134000EB6F26A35DF0CA2B163A2F5F5969E1F6C1 +:10135000E6D723FDE88FBCD29FEBB90DAF7D95D3C7 +:1013600046FB6E23E1EBED8166AE37B5FCE749B491 +:101370005777B6C0AA509F783D82F8A7E69530F21D +:101380006B5F79EDAB91A1F10FFFD3F548FFF595B8 +:101390004836FB45A45BA1D7D7BC3AFA79F4E756A7 +:1013A000EF3F6C2E85F209BFFEAF1C949F575EE4A1 +:1013B0007AD26553DBB3686BFCD3C0393F3525A2C5 +:1013C0007D0E3AEB0BDC96F6E434E493EBE1C2E1FC +:1013D0007005E080EB02B894A3DCEF091E97FF656F +:1013E000E1F1F93C2ECF6E61E8FF0DC245E17E844C +:1013F0009648BF55A1F5F3EFAF7F9583F2E646EB34 +:10140000B5A59989AFFF7F59EFE0B47F55FC727A9B +:101410007F71A083C7F5E9E8FE7ABA3EF86F94DFE2 +:101420001BE9A2F9DE24BFDFFD2FBBFEFF1B7C976B +:10143000FFCBAEF746F8FE8DC077A41DFD8A575E40 +:10144000FBAF64F62DD6BDE65F96AFFFF1BAA5BE41 +:101450003E5E759DC885FA6FB1E6F75C4ED23EBA26 +:10146000D53BF6A7493B093F1F4D607C9F9E60AD71 +:10147000247D7342BFF5A41737B03CF243F8FAA9B4 +:10148000E48FA1E00B80C39B09B97EF2271903FD0D +:1014900096417E7C5235C55BE9CF8D13C22717A0DC +:1014A0003E7A7405CC0BFA391A69B0A3AF78623F63 +:1014B0003560C9A1B41DD3E3C9F79C40BD65A24DF9 +:1014C0007B7EBA47771EBACBA12D2F602FF642FF45 +:1014D00059419689F9613E93B07EC8B9F1A7697602 +:1014E00082CB5DACA9D16EFBF6703A23E0743D1C53 +:1014F000FE31DCAE839338271B457D3DDC8CB6473F +:101500005BB19D91C1B997AF97CECBF2DC7B2378CD +:1015100032719E368AA1257C8DFDB89F34A45F82EE +:101520008B84FBB785B7C4931EEE12BE126E7A3C55 +:101530001C446354EF20FCFB19738DC877B70B3D37 +:101540007EA23186E7FBB5AA45C48F7E82FB842F3D +:101550005C46D44FC6D96228EE9239FAC7E07916B4 +:1015600055CC6F92182B1915335281F5261999CF46 +:1015700002E74DF4A1911DF511A37FA513C7E1F674 +:10158000DAFE466E9706EEF685E7517DB719F2DE74 +:101590009F2D646EA8EF4D622E85D767D1B1148E52 +:1015A000C6548CCB8214DB79A379BFDE3ECCBF92CC +:1015B000E393F082C726B45F40BF6E432C6F1F9544 +:1015C00047ED7D06DEDE6D8474402AB7AF77ACB29E +:1015D000D0F9C3BBA67F3ACA8FC2F15ABB71713A28 +:1015E000B7ABC8F4CD74CEEFAAC195807A7149E348 +:1015F000203A0FA9E145D52FA1BD7F6F04D1A37774 +:10160000F5039347E0FCF6C6B9707AE7A7EC1BC96F +:10161000EBCF79F88FF0DDB3338CBE5F48F7F44938 +:10162000877ECF2B8E792FC187929947CD09308441 +:10163000A779EA25B4FF4DF1EDFB1DFA19A7CC50AF +:10164000A9FE14C6E32B596304F9A327FB3E3726F2 +:10165000407F93E1B081E5ED61F6E425307FAFB0E6 +:10166000F7A6A673BB8B1ACE3C2FDA705EFDD35360 +:10167000E0FB64D67D3CAF57D61FAF6C46FFD080F1 +:1016800009DC1E2FEB633FD8EFC274EE5FCD117003 +:101690009179802BD52F5B6B694FC573CF5A53203F +:1016A00003D26732C7E7A54379610A9BB409E1FE1B +:1016B0005D956DA5F97678C9CE1D99E9403C788095 +:1016C000A429BEB0C9E940BB57FBB8E600FA07DA67 +:1016D0009F74BA1A1C84658AC791E7ACF671818140 +:1016E0006897EFC8E57E8693F6B6483C1F96DAAC5D +:1016F000149F23E37AE6DB399F0F68685B7F0B9EBC +:101700003B1F535D5B213FFF31EE77F9C466F52B3C +:10171000785EDBC8F994ADD3C6F130BB8BEC3DA548 +:101720004DE3CC78BE2CB3B9CDB8CE8A0C4F11AEF8 +:101730008B7D0DF01B89719C8C98C1DBE4A538135F +:10174000350AF80EF9C4E888C273AF3E0EA846C445 +:10175000FDC8FCA130CF1CECAF24DAB117E9E55489 +:101760005D2AD93D3709BA2BC43846F44F18DB122D +:10177000713EE1F81DE05F186B4FB7113D87318472 +:1017800043BBC99E8EF4DDBE2ACC807EB6C2959C3A +:10179000AE81CFAC4668FF889185A3DF2043B42F8C +:1017A0005E612CDA02F97E56668C8C45BACA25BA7F +:1017B0006ECBF4E4207D7EF603360AE9A174DD06E3 +:1017C000F2AF48BA60C6D6897130CE67DB9D792802 +:1017D00037251DB5658EAF4D0FA587190AD101A418 +:1017E0008753891EA63D8CFD168E0F0C5C9A85E7EB +:1017F000D12AE6C6FD3D81B9504FE8641DE47FEC77 +:10180000B4991D68E792F244CA0DC0ABDB1A1FA45D +:10181000831DB0DF1B4D8CEDACB752FA42BD9D1954 +:1018200041C6EDAE4FA0FCDE7A07A5CDF599F4FDDB +:10183000C57A17E5F7D78FA2FC817A37E50FD51760 +:1018400050FA4A7D117D977209E0427248CA152903 +:101850008F4A6DE676F4474AB9A4A79B7900DEB1BA +:1018600079D49EE49E9477B80E435E501E49FCA640 +:101870002845BE0427CAB1B63988FF7CF5E29E83AD +:10188000782E2FB7B9E89CCEB8DCEB047A45B824A3 +:101890009BD921B4BB362C71B7AF7106E17F7FB9FC +:1018A000C28C2174F5406D183386EC1B0FD6C568C9 +:1018B000F2C5757F78A30FF45FD1CBB30BF176F24D +:1018C000879F3EF327F8FEDC0FCFA721BE611EDB0A +:1018D0009FC071978777CD2316F38D26F2470D9021 +:1018E0007610F8877829619CDF9EFBE1DF89BFDBFA +:1018F000EB2C0ED4873F423C015CFF2CF054526726 +:1019000021F879579DDE7310F97CB999E45C49A3FD +:10191000E0C3B500CF10FFEEA94446F608D0A659A3 +:101920001DC0EDD40FCC8108E8FF94C2F95701A582 +:10193000A018E3FED6BEF901F2BF527782FCE71E83 +:10194000AB8DEE35319FE962687F4ADD71AAC7DA57 +:10195000FAC5A0BD84F6B13BD0EFE8363B60DD4868 +:10196000D388B792CC232C11FD264D8A1DFD266508 +:10197000E27BD95A85FC9318773303F4BE77D355AD +:10198000C26364BA91D2CA7426F4BA26DA9F24BD1F +:1019900096AD8376C8174DB9E6052172B8447C2F01 +:1019A000CD34502ABFB78B7EFBAECD9D8DFA445F00 +:1019B0002CCFC2346F36C2B7AF6D925109C1FFC789 +:1019C00038FE089C071FBF12910AFFF768668A79E4 +:1019D0007E16E287EF5F729C92CCBCD518C759B2D5 +:1019E0006E1C4A5FD6607225F4827A67BAFAE17A91 +:1019F0001BB3F278E5AA1EF60F693FFB0CFF1C4DE6 +:101A0000EB26BB6EC5DE5FEC7D057AAEF8D842F8FA +:101A1000AD182AE2A7B2FC23A793A1516BAF9EF8A1 +:101A20008BBF4491FF613F8FAB8494DB53979773D7 +:101A3000FBAB0BF8AA1BFFCFB1BD1F47756BA7DE31 +:101A4000AFDE949DBA46F93A0AF507B99EFCD7BEB7 +:101A50008CA77928D7C8FF53F3DAAAF8EEEECFE8BF +:101A6000EDD55DF66C61B7D397EBED757D32747E85 +:101A70000123A3FB58D25EC7D4AC68B4EF7F29EE34 +:101A80006BF474AE91F6ED9A4DD0491CF0A7D111CC +:101A90008DFEAA2B3DE8D30F66F0FDFE92B0875F66 +:101AA000D9ADD239E7CAEE48E2A7C5BB7F761CFDA7 +:101AB000878BB729348D6AD64A700378326BE83E3B +:101AC00086F16671D7CFBBD39F168DFB48E52F22D9 +:101AD0006B91CE16352BEEED309F4EAB23BA77C807 +:101AE0007C6ECBE0745669691E497016F3CFCD70D9 +:101AF000D077596F51CBCFC87E0CF52E931EF4CB07 +:101B000008F4F523BC7F87F3BCB079980BFD7E8B7E +:101B10009AF72D263D6277841D8F0CE7459CB0EC2B +:101B2000E7CE0CCE9F776670BDE582F0075DD8AB3F +:101B3000923CC379227F9D57B4F1789345BBC9028B +:101B40006E9F0BFE92F51735B7470D84FA670FFDB0 +:101B500081D259625D8B6CAD39B8FF9EDD1F41FEAD +:101B6000ACB3FB9F9EF42A8C77A9795C2FE407D94C +:101B7000FFFC0C13D5BFB4592D4078313F8F7BA9A2 +:101B800046F80E0B9D67DC169F3394EF78DCCF850B +:101B9000FDBF8A326405F1596DF558F15E63CD7E63 +:101BA0006F11CA8DCF140E4FD3FE713EBC8F54D32C +:101BB00092CB909E89EF12A9FE5A43483DB3C94586 +:101BC00042D17868AA3B89E02CEE13897879BC1F52 +:101BD00087F267E9542BF927E60D75CCBA1FE5E4C7 +:101BE0005B268E977E8E27507F9BF74E1CC54D2D12 +:101BF000753A66E1FC97BDAB52BCEFBC61420E2466 +:101C0000B48DC0B8C5AAB50A73C33ADB9D5C6FA892 +:101C1000F2ABCC03F9BE400F3E00C5FA8C14214F45 +:101C200003E978AFEFA97283DB0CFBDF4933F3A93B +:101C300068377A91C73357A5F0B8E1A790EE21AD88 +:101C40008A0DA4C7417F17053EABA605D2314EA22F +:101C5000EAC5448A93B868E67E4BFC8E7ED2AA3CE5 +:101C6000680FF57A8978586C1F13423F55252E0767 +:101C7000D653635D8E5C1BCED77E99F4D89722191C +:101C8000EAB18683913CCEE9E7615B2D2178DA9257 +:101C9000C1F5E55E028F6C2E8F877C5CC4633FBE0E +:101CA0003DD18FE73759FF7193670EC201D781FA93 +:101CB000FB2273533AEAB772BE8BA29A689E17054D +:101CC0007D2F0A6FE2F1D2E29E2CD6C77CBB8951F0 +:101CD0001C77C72E0BC5939C4F6C3D80E39FDF356F +:101CE00088E1FADB9DFE0587A81CF447C05BC50BA5 +:101CF0009600AEE7DC2E6E6F3E67E2FAD8B9A9090E +:101D00000EC45BC1B44DF3C81EB3CDA220DECF29F3 +:101D1000CC9C80E5DB7BBB7CD8BEBE8EE2A42B4096 +:101D20004CE07D1C480BF05ECDB9ED83283EECDC29 +:101D30006F54BC1185DFD7E2770F6B9AF73D84C7EC +:101D40004E7E7E3AFFC27F0E0ABD5726D38A6DDAD9 +:101D500038384927B2FC4806B70F1C11703E9EC1A7 +:101D6000F7ADEA88E6C753689D1CEE80273AF7C1B5 +:101D7000C61FF9F4708C834853506E3C0574F534DB +:101D8000DA1576F2F3D5F9DD268A0BAF3818E9A615 +:101D9000B8B335B718280E42E57A788501C047A94F +:101DA00042FD564CCBA47BBB006F3AC7766C57C53F +:101DB000388CD970DD3B789C6F21EA8A549E4DE5C2 +:101DC000E744FEDC816CD2EBA07F37DE57AAF8DE59 +:101DD000F7391CA797BFCDC88E6125F95AD5E5C73D +:101DE00019138DFB5DF59ADBA2F13E1F7B4765A8B9 +:101DF0009FE8E174D5E8EA8372B577A690B3079EB1 +:101E000031A33CA814F7432A5F50B83F19F80CEFF0 +:101E10003B56AEBEED09A2CFDF99581AACE762F38C +:101E2000CFA234F81072B0ABBED945F52BA13EF667 +:101E300053B9FAAD289ACF0E13C5995CB75FDD6C24 +:101E4000FB17D49B6ADF451FCDDC8E72DDFA59EBA0 +:101E5000BF7D0CFD7FB13BCCE5A3AFCD74AFEC8271 +:101E6000A97901AEFFC29E3092471762B87C380B49 +:101E7000F2D39781F3B8E7271497F5FBE9741F6E47 +:101E8000A15FDBAF1CD79869E27416E78AC6B8BEBB +:101E9000EA77B87C03BCDC4BEDDF31517BFD3A4E79 +:101EA00067F0765DFCB92782E8E1425F8E970B7B95 +:101EB00033683F6A8FE1740EF34DC6FB7317F66407 +:101EC000E4D2BD34546E801E2AC4F9F6424C73B27B +:101ED0003DA4BCDD24CE6901A88974836D40EFABBD +:101EE000A8E37A55A5751DC587605CEDC83C4A031B +:101EF00096D8EBE363815EE9FC787FA6B053E27885 +:101F0000F1227E9BF49D6633CA6F8FD00BAB76EBCC +:101F1000E36B79F9AD998A8C0371F492F1BC48872F +:101F20003E85E24C2A1B972C423AAFACDD703FF263 +:101F3000999C7FA59115E039AC5D51691EED61EC6E +:101F4000C169B86F848E13AAB7C979E254E3495FB7 +:101F5000A57DECAE4CBEAF61BE09FAAB6A54D6D1DA +:101F6000384E799EE5EB927002709831AEAF7D9C51 +:101F700028EF61DD729EFA75CBF93C90C9E551BB43 +:101F8000D3F1933188E7DFAA743FF6EAD7C3A2639F +:101F9000BBD1CB82FBBA3918DF8AF1BE487BD04F68 +:101FA0004E26976B95183F0BF34CDFAC8DEBCEDCD8 +:101FB000A6CD0FDEADCD67EDD7E6735AB479D73134 +:101FC0006D7E1A8EDB9B9FB3F13E2E9EB331C5739F +:101FD000B6C3C2CFD998C77336A678CEC6EF78CE2F +:101FE000C63C9EB3318FE76CCC4B78E3791BF3781A +:101FF000DEC6F2A7059CAA449C24E201E99DBD1C13 +:10200000A6B9EF73E5357E8F03E880F3CD1C33F17D +:10201000CD535883CE1DDCAED477BAD581F1BE8FB7 +:10202000C47A5665A25F54695D9D887833B651DCE9 +:1020300069CD2B3CEEB42A2FCC86F68DB65567576A +:102040006338E703B19E47B1FE1553C70E846F7521 +:10205000DD51BABFDEB6C2F1CE1D1C7F646761E5FB +:10206000B1A43779719F8BED198FFAB86FB64E1BFB +:10207000E7AD8FFBD6C77BEBE940EA7BCF993A12FD +:1020800051AE9FDE655D87F33F1D26EE9FCCB6EA1D +:10209000FCFD424F5BAF6CC5FDFA1799B1DCAF7226 +:1020A00002F4F36EF65999965E1B467A78577E9D38 +:1020B00062A07B7109F1B40F2D13734A563ADAD737 +:1020C000A09C5B64A07DF32AE86538DED5F754D286 +:1020D0001F32361934EB19E40FD7D0D7909DB1BA1F +:1020E0007B0D7D35F5871E4AD1DD6B18AC8DA39F26 +:1020F000B1E2309EEFA7AF1BA6A95756749B0E8E78 +:1021000062DE427F2D83FDC30DEB7B6AF9A664C4BA +:10211000EFB2459DED6B503F7D298CEE8595E3FF39 +:1021200003B9580E7DE27DC6F2FDE23E709D761F3A +:102130002E15FB50B991F9ECB1413A2CB733770C1D +:10214000B45F34B8352780E78ADFFC61A43D05CF52 +:1021500015E3FAA03C4A36B9290EB66A5F5ACC0A92 +:10216000E8F758AAE7A34CC0CB99A6A33F2EC6FD1B +:10217000701F3FEF9D5EF7AB288A1313F4966CB285 +:102180008723DEB734F1F838B48FA9B141BAD8D279 +:1021900014173ED0165C6F900EBE263C017EB81D13 +:1021A000A7FC08F93D3A9BC57AC7293ED4A7E5FAB2 +:1021B000968A7D850DE4FD3C24F267C4F942AEF3B6 +:1021C000E2A0C3390EBC7F517F285945796ED8BD36 +:1021D0002311D2D116CF97B89EF22D697F1A03E34F +:1021E00054FC91AFE7938D13A246A3FEB9C7E42A2E +:1021F00084FC9AA6E7CD78CEAE30FACD145FB96BE9 +:102200008B19E38BEFDCB985BE2FD8E9A578CA8599 +:10221000AC96CE9F9FC97704043CCAC72B9BED3078 +:10222000EFB983B8FC280FE7FE3BD08FDEC0F73B49 +:10223000AEEE5472318E6746D13EB317BE470D12D3 +:10224000F783747CD2F9F6F4FCDE040F7E5FE38F33 +:102250000C4EF1A9D7F3C5F46B4EE28B19D786D09B +:10226000B96C6660103FFF66E9CEBF6FABDC5ED72E +:10227000C2F9A0DC1CE8351DF9E47513E9B9D5B045 +:10228000DF8CCAC37335EC8D90168D5135F45A33FB +:10229000314243CFB359ACE6DECB7D183412929F66 +:1022A0005198AAA93F6BC6101DFDE705CB498EDCEE +:1022B000AAB95F57BDDCE75048CF1CAFFDCE789C74 +:1022C0002063776BDA57B369C17A48DFDBB81E5CED +:1022D000BD3F662BDAFBCA0DFCFC34DBC3BF2F3ECF +:1022E000C4BFB3D94CC38703525D7FE2FBA289FC14 +:1022F00002D29E3E1BFFEE06FE8C8577DD0FC77B6C +:10230000F1688FD0DC9F16FE409C37E2A15AD88D31 +:10231000AA33B9DDA8DAD76AC6770700FEC6B8586F +:10232000AA678DC3F8C82685EC8A982EA778496DD0 +:102330001C16F687718C8B4FA85EE4137D7939BE2D +:10234000DF83F87D85C7952EDCA48F835C47FEC8AC +:10235000C5680F0AC1DB53831C425FF1AFEE8BF0FF +:102360002B5472E95EE4EEC3668CB39B31232617CF +:10237000F9464F5F52AE033FD3F9BBF3EDA3445F81 +:102380009DE546A2DF1BC161B19BDB51F574B780AF +:10239000B59AF19EF882FD8A0BCFA3580FE1D117B1 +:1023A000E951078FB8D8EBE120E1D305AFFDFA384A +:1023B000370EA78587147FA01B38E9E7DD13DCE41F +:1023C0007A16783C93502EC8752DC4F963FF307F80 +:1023D000EC5FFA21D8283D7FA6927D6A71118F8F1C +:1023E000D5D3C3B46BDCEE72DF3523A5330AB5FC5D +:1023F00088ED902F665E8BA7F26F4B2F8B619EFC52 +:10240000FED3CDD1895C8794BB417EE0F7066EF4A4 +:10241000BE8FDEEEB8639088131CC14668E29185DA +:102420005CD5B7D7C7234B3D40BFBF78230D1437CA +:10243000D9694B21FD42CA598FD83F3CABBEA47A23 +:102440001EA8C76713AFD96F3CC2FEB7343285DE12 +:1024500063485E11178F78F286D929FEDEBB42A54C +:10246000B8672FD47384E827AB1B539371BF38F53B +:1024700048C6B33ED0DB4F7DB757FC2818E7F42A97 +:10248000532FAB2358EFD4AAFC648CD338BDC13290 +:10249000DBDF0DBC5AC5FE50FDC30F683FBB64783F +:1024A0003B6A36B4AF5AF5521486F957AEE2FB7860 +:1024B00079AAE79D41BD713FDFB2C38EF0B36FC90A +:1024C00041BBEF49D80EB0BDD41F2A56E5F741FDF8 +:1024D000A2EABF8F3E6BC77BD62B4CF1A87F9E7BB9 +:1024E0000FF64385F633D21B3E0B832EC89F164949 +:1024F0007684CF14E646BFD245C3E1BFAEC1736157 +:102500006E737A00D2EF593C2771DCCA55CF93DE47 +:1025100052F1E88A7455C57ED3A2BBB39BC87487B9 +:10252000D8B7517FC714F5778C9341FD1DF3A8BF31 +:10253000638AFA3B7EAFD9A4D5FF2EA7713925ED6A +:10254000C9031A3A72D17FE71BCF326B69BFB565F9 +:10255000A2BEBE4C0977A13C5A86BA12E6FF1246CB +:10256000E758B62D91EFB702CF7556EE37FA4ADC31 +:10257000CFBDBD0374B210FABCE39A9585DE9B1DF6 +:10258000C76234F909D6444DFD7CBB53537E67C204 +:10259000204DF95D8E5C4DFE9ECCD19AFA935DE3A1 +:1025A00034F97B47DDA5A93FD53D55939F5E304764 +:1025B000537F669157533E6BF6224DF91CCF124D57 +:1025C000FEFEF2EF6AEA3F50BB4253FE95014EA475 +:1025D000402F2D78EEB2E0FB29564ABFA3DA8D28B2 +:1025E0003796FD36CD86F81E33C150DB9D7D3F63A7 +:1025F00030D787CA86B85306F7E6EFE0203DF617D6 +:10260000EFDC8C18CCF199C480AAE8BCDB9A88F482 +:10261000ABAFA72F1F1371E4AA0370F893C14367F0 +:102620001A410E8DB9E5C8B054C89F18BC60A611F8 +:10263000E4C698DB8EFC2A05F2AD837FC1CB871EF2 +:10264000B98AE5B38654F2F2E98C548F3FBFD07754 +:10265000A60FE77F47CA3A17B793747BCF5CA608EB +:1026600007BCAF8D70C03400F48BE911A05F4C8FB4 +:1026700001FD96817C3A0EF48BE909387FE2F77F01 +:1026800087F327A66FC3F913D3DFC1B913D3563825 +:102690007762FAFBFAD994BE57EFA176EFD797533A +:1026A000FA417D2D7DFFA8BE8ED23FD7FBE8FBD43B +:1026B000C1D28E11609AFB01E867447FE221D3C545 +:1026C000503FB0F4574AFF64432D6B8B4079D1667D +:1026D0008CF9D41AF43BF66C0730B24F43F4B1686E +:1026E000E62E1E4CFA423F3BC96FF1DDE4F0781153 +:1026F000CF7F744E4F1BA6E2BE55FB06BA65FF683E +:10270000E8FEDDC411823E460D712F20FA10FE75E1 +:10271000E9DFEE8A9B09F1BF1B42E275E85F48DC06 +:102720008DF483CB389FDBADFC9EB1F473CB781E68 +:10273000D95FFE178CE4C3D8B546D25F228D2C80BA +:10274000FDCBB89DB1D6E65C8C63185B65A37BB509 +:102750007DE0BB398FEAB95548B7FD0DEAE704FDC6 +:10276000EA7DC4FCA19CE69FFF8587ECB063455CD5 +:1027700001B6B7F2721FB61F8BB685E194927C7AD0 +:1027800006EFEDE605FDFC583F82D70F607F03FFA3 +:102790000EE34505F9A67F6C732ECAEBFE8B6D74B4 +:1027A0002F74F3B800BD6745462780CB74797EB29D +:1027B0008ABCF4E7EDEC4376A40982D7BFEFF06C56 +:1027C00042F81759EC7F89203E4BED8FF6C9A9429C +:1027D0007FFE07787B06E940C253E245E251E223DF +:1027E000247E8AF0D0135EF5F8D4E351E22FFF8BFC +:1027F000205E10AED7E32D8857B4E7FEABE06DB88E +:1028000091BF5F66A9B2D2BB6837C2E3831D6C5229 +:102810003456717A46207EBCD71CC7315FCAC64D7C +:1028200042D4CAF2B1583EE2FA72CF171DA6E810A0 +:102830007CDF2EF03DBF87FE643DF91E83ECBFB107 +:1028400087FA6F85C9B80BB72D776430FE71593E92 +:10285000877F815325F84FC85A487A32B3713DD3E8 +:1028600001FFA15C9AF47511BD4FF925DB8D9E5BCC +:1028700036A997563F2DD0F9ADEF167AE9DD3ABD6E +:1028800054AF577E3E58F8B39DCCF92DDF9DBCC6A2 +:10289000E5DACDBE3BC9DF2D9D28F82C49D059AAD9 +:1028A000436563908E9887F6C963F86E690EBEEF34 +:1028B000E9A3FC5DCC4FE93D2C40FBEB6410C498D0 +:1028C000BF174428E68F464C29C6BB7113864D18A6 +:1028D00088DF43DE658B1CD29BDE65FB0F7BC8BBAC +:1028E0006C47263AE87EE5116B2AE95FC887A61097 +:1028F0007BE06F607F1A08FBC751D8BF307D03F6BD +:10290000AF81B0DE3761FFC2FCDD992B18B69BE4C6 +:10291000D0C6EDC8F6F7D827C0C1A467F8DD93F399 +:10292000723F84EF5B311913D17EFE56CC2D1371AB +:10293000BD6FC5F431F0D462A634FBE0C0EEF443C1 +:10294000C907C1F126D1787AF84A78EAE128E1FB93 +:102950004FC0F396EEE0396230E3F649EB1FA21266 +:1029600052D07F1725DEA3FC6D8E0AF97338B5446B +:102970008C57BD8DE639B66E34330E23BF4D16C26B +:10298000B5CACAE1A5B75BB16D7D0CA1F1BB57CD4E +:102990009E8221B0EEB39B55BA377EE9C530B2476F +:1029A0007DE6E7F6B67B14CF649C5F95EA5887EF27 +:1029B00088B2B7F83B67ECEBA3C9D322BF059D6E85 +:1029C000E3F7EDABAC93BAC5A33C4F4D71BA47707A +:1029D000FAE7EF454ABDA29F85BF4B20DF2FEC49A8 +:1029E000CF1819CEE5603F0B97DB12AFD08EF249BE +:1029F000D0CF489073493F09A7F3C5CEDEEEF9B8B2 +:102A00003E6947E8EC17E147793B363084DEE52A3A +:102A100038A1523CF11111DF75E7905A5B0AE0A929 +:102A200029CD5383ED98FAB58A72E66D58671CDAA2 +:102A30001F4E0CB3D1F9F15B9E43BF3344C88B1CCE +:102A400096A3B9AF26E94EB551FC4EE77BFC3EDEBE +:102A5000D2DFF0B8CDA5BD558AFFD7C7C58D65E9D2 +:102A60003F417BE3845E2697DF11942FF21D204BBC +:102A700082813942F4EC3047387384CC27223356B4 +:102A8000938F74F5D5D48F1E95A2298F710FD6948C +:102A9000C715E469F2BD8B6ED5D4EF337BBC269F9E +:102AA000E8B95B533FA97C9A368F7C0770EF5F3B98 +:102AB00057D36E405D89A69ED357A129673E776B99 +:102AC000663CCA71FE2F75ED524DF9D351053C7E1F +:102AD000DCB680EE29A6357D4FD39FC46F521CC74C +:102AE0002F73F0FDC107FF91DF42E0393F41BB6F1B +:102AF0004CB08F3B66A7546BD748BA411CD4A17F1A +:102B0000960EAA99960E7AF1389EFCDF0C73A01EE1 +:102B1000A3C73FFA2342D789FE8850B8A03F22348A +:102B20008FFE88D0FAE88F082D477F4468F9B013EC +:102B30005AFC8F68D5E2FF960FC6FF433C8D6ED3DB +:102B4000D2831E4FB77DA6A58FB19E7082CB04D0D5 +:102B5000C790DE259E66C37FB4CFB3A268B41BDCEA +:102B6000C1DC742FE07F0B5F9775F8FA92AD1B8183 +:102B7000EF5C5EF17239DED33E7F6580FB0B94BB68 +:102B80002942CEEBED00329ED4379EE3D377328CD0 +:102B9000E4D55786B648DC3FBEA3B6915D3E91753D +:102BA000BC81EFCF0CE9E56159BDF1CA36703F94A5 +:102BB0003FB5E8BE5CDCE7E6FDDA928C7ACDBC017D +:102BC000FC3D4196D546EFB4C8F9CC4BE2F147D66F +:102BD0002C21A75D3C0E29228BDB7F225D768A8328 +:102BE000F6663111E7C992E765231DBE1D96817413 +:102BF000B691DBB9DA4C0E8A6BF1013DA29F12F55A +:102C00006DD487FB0B7DB4E143AB95D31DD3ECEFC3 +:102C100083FC564D1CEE909D764D3EBB3941537F53 +:102C2000E82187A63C3790A9291F76C2A5C98F68DD +:102C30001DA5A97FCB076E4D7E745B81A6FE6D9F9F +:102C40001569F249ACE34984E7F8AC141EDFAF081C +:102C50003B8083E365DE77E2E93E8D3C47C8B86C94 +:102C60008FA063FD796480D94371DE0D89CC45F76F +:102C700041ACE23CC8B4E7148F88AB96FA3CF369E8 +:102C8000E3AA653C75D779469C5FE47922249EDAF5 +:102C90008DF397F1D45D7817EF4BEAE9F35E817716 +:102CA000FD3A0698F9FDAF86EF9AE91E8B9C9F7E50 +:102CB0005E9B443CE0766BF7EF0F3D20E8AC2DA522 +:102CC000686616D47B16B62782E775E3B9DA7C000E +:102CD000DF861F985D2B1D371E6FDE50BE9E627C07 +:102CE00057358BDEE9A47B6B72DC6A31EEF41CA5F0 +:102CF000DBF5CD8BE6F15D2CDA4CF72E7A1E8FC317 +:102D000035C1CC1AE99D24710FE18175CDEB3154A9 +:102D1000B3D8DC64E2EFE3FB4D68272A1C0F7A602E +:102D20002EDA0DDFDF68037DEDD93A23D97D1EDA77 +:102D30003DE63ED020BBEE950C80731AD24921E2CD +:102D40001FFA3D97CDE39D1FCBE2F2215FFDBAEB69 +:102D50003E804523E7F9F9AF1BBA237A94EBF8BF1D +:102D6000BA1F20E9570F2779BE6662FF1A28E625A9 +:102D7000E1D7653F11F093F7331C4B4C455B6D7405 +:102D8000CFA300E3CA24FEBECEE674F96616C737A9 +:102D9000D64379D453BD7C352B1AEDE09DCC116D13 +:102DA000BF813DF8FFE8DE04C1BFA7FB5E3DC989D6 +:102DB000EBE4430FF7BF7AA24FFAF72DEE8185C8F7 +:102DC000091EEF23F0E11F6820BFFA9A482D1FFF6C +:102DD000358BDB5D9E96FB850FCEDD5A39C1D0AEBB +:102DE000DFB04A15726241D7EF48E0F7F9AB4CA467 +:102DF0005F3356F438C6197CB2D14471B163DD8CAF +:102E0000F49892CD8A7F8B82FBE898049CBFD7A769 +:102E1000DD8FEF60AED5E8FF285DABFDBED0C67F8D +:102E20006F62BEFEDD14715E5F7883F3FAD92CE128 +:102E300007723117E95DC2FF5F2EDAE8F5AE4E3F4B +:102E4000F79BE1795BE576278A1B93FBBB03FD3794 +:102E500021EF81003CC333711F6F34761BCFD70540 +:102E6000CF1EE2152EDA44BC828DC76774EE0FE3E5 +:102E7000FE4DE95712F52FFAAE5239D6C7DE2EE5D0 +:102E8000F2B80BE94FD2FBAB3A6D06F2B774EE8F96 +:102E900024FF3CFA71A2810ECE1BF6C58F7206E7A5 +:102EA000E76953357E107DEA59F1129D17CB533DEA +:102EB00031D918876D74595D907FC47684DE8F2A6E +:102EC00014762FFD7CBBCE5D63F8FB2E9D3EAECF0E +:102ED0007616F07738402E32E42319873095C129D1 +:102EE00015526F6034CDE7DBFA73A65FCBE57ECC7D +:102EF0006BB7517BCFDAD1941FD0B87E09DE8399AE +:102F0000D9B0D0842EECB62797E78743D3B6FEFE20 +:102F100095E188B7714AB776F9BC6C85F8A14D1771 +:102F20005F2FD3ADD99C5F7E9D2DE5B888435AA114 +:102F3000101F2C55988C4B22392EF3579B443E9FE3 +:102F4000E797ADE2F936F1BEFE0E6147C175638ABF +:102F5000EBC673FF6E6167C175638AEBC6EF28B776 +:102F6000308F720BF328B7308F720B53945BF8BD20 +:102F7000841525E7AADC0F353194EFAE59D9C4107A +:102F80007E413F54681EFD50A1F5D10F155A8E7E2B +:102F9000A8D072F44385E6D10F155A1FFD50A179D0 +:102FA00036EAAE601EE59C7BAA263F1DF4FC892113 +:102FB000FC8D7EA8D0FED10FA5E9CFB344D3FE7E11 +:102FC00056A7698F7EA8D0FA0FD6291A3FD583E27B +:102FD0009DD3D24D71443FF31D4535D980DFFF8825 +:102FE000F8EF874D2988E79645FC5C16EEE2786E8F +:102FF0002AE07837308EE78E3984E7E5669ECFE7A2 +:10300000F1C97AFA417FCF4413F7F7608AFE1E4C6C +:10301000D1DF8329FA7B26A6717F0FA6E8EFC1EFE7 +:10302000E8EFC114FD3D98A2BF0753F4F7608AFE94 +:103030001E4CD1DF83EDD0DF8329FA7BF03BFA7B96 +:1030400030457F0F7E3F897E2753705EA8C70FD41F +:103050009C1F810E35E747BB268F7A7C687DD4E3C1 +:1030600043CB518F0F2D473D3E348F7A7C687DD402 +:10307000E343F3BFCC72109FA13E1FDA0EF5F9D0E7 +:103080007C7693EF0DB49D4DDE7CF918A66D91CA48 +:10309000B30A888CE6ECF7EE433F5D5B98921C0325 +:1030A00092D3B4E2C3FB2682BEE611F17F39ACC3F2 +:1030B00080F8F688F7D43D0146F196D97F4BA4F20B +:1030C000CB78AF5FC4DB22DE73F733FA5D12E92FF2 +:1030D00096ED5DCCAE622AEB07F3DDD7D38F2FEBF5 +:1030E00091FC0C9907DE00C67895DCE5B63C8CF7C0 +:1030F000DC6150284E62C74A1E27ACA7AB33424F53 +:10310000DA61D87704EF81747815BA0F9C6E642762 +:103110004C7908A7DA3CDC7FDFCE8E11EBAABD1517 +:10312000EF9BC8794BFB26C809BA3F37A6A3754267 +:1031300034F4E3F18DA3DF49293473BD01DBE17978 +:1031400072884F716F0DA1EFF785DCF4F8F8F83F46 +:103150007F6E0A6F17CEDBFDFCB92882E3944685AB +:10316000E2A5C6EC666EBC9FFB1F429E0ED91D50A9 +:10317000713C6F231F4FF6EBDD9C4CF716BDAC6D19 +:103180006202F9481486725BC20DD6770CD707C766 +:103190008613689FBED97B3FB70F8FC9C7383AD611 +:1031A000C2E81DCBC9C3DFD5AC97D03E92FAA57D4E +:1031B0002DC3A7D07BC1537C2B56E2B63ED9B7E4D2 +:1031C0008DDE587F1B73391DB415D1BD58399FC191 +:1031D000EE7D06D81659166B358429886F76342E05 +:1031E000847E80F36720BE735D267ABF77AAD16E96 +:1031F000A2F7237A883FB96A93F1273A7D4117678E +:10320000D2B0FC8364B4272F8D3490FD77E94BFC5A +:10321000F7003C9B14926B520FF28A38B5AB8D6F5E +:10322000F49E8570DF67A2FE64FC4975AA3FD980D1 +:1032300071F57DB7E4C4AAA407C4E6A01EE0FBD5DF +:103240007DA3B0DE2AFE8EE5D5C699D101EA89FBC1 +:103250006BCA04BCCA441C93171FF45683BF8B254A +:10326000EF77B026AEEF497B8EF7B7C38E237EBDD6 +:10327000CF8877A5D77AE95EB63E8E6851A389E2FA +:103280008E16E9F4C24AA11756DE402F1C9CA3D328 +:103290000BE5EFA588364CEDF73EC6EDC97B89C539 +:1032A00026CEFFC5FB18D9618B574C30D03BC82FB9 +:1032B00071BA295EC1F59BE297DD74BF50EA8BEFCE +:1032C000083D66DAB52482FB1F84DE3213E32B014E +:1032D000BE856D61220E2B91D259D778BCE5341B87 +:1032E00097036DAFF177203A7D16AE4F1D63FC1D3D +:1032F000331D5D4E35FA0D78E1CE3506E812F293B6 +:10330000510F82FE66A35E148774EECCA7F8BD024F +:1033100085EEBDE8E9BCD054FB06C687166E672E65 +:103320001F0BA573A05FECCFA7D0FB001E71AE955D +:10333000F4ABA7F77911C21E65E3F6A62EBB04EA2B +:10334000A8F44877CE2CD41BE7A16FAF2F27188C99 +:103350003B8BCCE2E5653939B31AF190D3839D42BA +:10336000FD9E99E0E191EF20F46037407B01CAC9EE +:10337000071ECA359784C8C9E1AEF18D434704F1F1 +:103380005DD275DF2F8BDE055DFA481AFD1E4E4FAC +:10339000FA7029C015F9625E74DBC3F80B6B0D3946 +:1033A000CC3D31017F2750AE8F05308E70AEC837CF +:1033B000EFBDEF4F6B6D0417CAD7E78C998571216C +:1033C000D5D6B649487635599E02BCC718944F45A4 +:1033D000EE2405E5536E00CF849BE4FD649D3DA281 +:1033E0003987D7D7DB254AB3B8DC96BF8B72EA9111 +:1033F000837B71BF92F33FD5C3EF30ECCCE1F2F7A2 +:103400007FEB1E84FEFEC32FFB7A9ECC81753C6E43 +:10341000E0F7F9FBAA4D4CD887C82F2CE50513EF30 +:103420006004F1EEA677741B1E51ECA1F629CF5A69 +:1034300085DFA3EFC18EC3323B9EDC0EEDE6D59B4C +:10344000E9F7F89E4BE7F4F31CD00FFD5E8AB9F55F +:103450000DAB3308C78FEB7E6AA2DFA56181347C98 +:103460007F676E6D980BE5F17057D12F71DE1159A2 +:103470002E92438D18430EF9BB7A15BD88DFABD76A +:103480001D7E16DF13A86971D2EF95780FE5AEC6E1 +:10349000774E86BB3C07B1DC6BB3D37B1A8B1B63C7 +:1034A00068FF9AD747DC0B651DE46793F07F47D828 +:1034B000AFD6BA38FD5E11E70E14905335F5BAB7A2 +:1034C000E3493BA1DECEA07F5FA227FB82B427A009 +:1034D000FDC01C626794F60953E6A939A837149B0E +:1034E000B5F71265CA86F27D5F9E03E777ED5B59FB +:1034F00093FAA07EBC41B1D37B9336C7ACD1902F59 +:103500003B61C2C84E5618EB30E3FB031D805F8C55 +:103510008F2E017E4539532CE2B4CA368D267E2B80 +:10352000F343DACD3B9C32BD7FC3D1FE2F23FD0494 +:10353000DCE4B72CB3BBCDB1217C5FDAA468DE1D1F +:1035400090F98E1C95F311A8E308BF071E729AF13B +:103550006D9F62502330FE8F0D7568FCC7508FE25F +:10356000410A53D871FE0E3CCCDBC9C7CB0BE9BF77 +:10357000A489DF9B9679A84FFACFDF732209AE5E4C +:103580003BACDB89A99DE60970203875AC87FE1C31 +:10359000340EE1A334E037E179BB18E350203FD784 +:1035A000EE37E138258DFC1D13CF3A3E8E676D8CCA +:1035B000391BF523A3DDDC1FE1277E6F15E6477A73 +:1035C0006419C005EF63E17D37DC5BF4F0F18AF943 +:1035D0009635C5D03B0AC1EF1B4C888F393DBC8B5B +:1035E000903594D36D49E338BABF5E6674D33D0716 +:1035F0008F80EF274BC21E45FFC09C8D4F989C903B +:10360000EF3794D36FD6504E5F852981347AAF68F7 +:1036100049980BE739C7DE44EBEB82EF63000F05F7 +:10362000DFB92922F8025DF8306EAF6CA3169FC196 +:10363000F970F8966DF412BF2D307ACCF6D0796C13 +:103640003A9C86F7AAE6007FE3BB12CCEEA1FB9280 +:103650009F3E362B99D609F344B846BA1C93F0FD29 +:1036600021A0137E0F46AC47DEEB96E34D1CCAEF5C +:103670009D4E1CCAE567CF7CE926BDA601F08B767E +:10368000EF9EF8D28C821BC63597F1DF91D0F3A95B +:10369000E44FC997924F25FF3E6B2A0A24284139EF +:1036A00003FB6CED8BDDC0A951CC77AEC02BC0F510 +:1036B00058E83DAF6A81D7E2142DBF637FD8EF1C75 +:1036C000C1EFC5E30369F82E93AC2FC72D8EE5ED4E +:1036D00090EE91DEE688F1B0FE52AAAFBDA752DAB5 +:1036E000252F76AF8A4779B14FE17ED0F547FB7F32 +:1036F00007F5D73D5C7FBD50B57D31EE97CCE84FE7 +:103700000E7DDF7F3EE83928271688FDB92CD0BD15 +:10371000BCB890EEA9181AC2CF653FDB93EEE1F278 +:103720002680F2E6CF7B5EFDE3AD8EE07E2AD753A6 +:10373000B2F65D93D7160A3FBEFE47333BE93E5EC5 +:10374000A9CDECC078E7D2462FC95F96007AA112C6 +:10375000127FA6A30B6FA342F7C84AEB46FAD5FF28 +:1037600045395DBA6E2ABD7B20F126DF6791FBAB40 +:103770009CFF7A31FF2621DFE60AFA9E5B3ECE9C53 +:10378000D88BF46E0CB36473C4F73965DAEF5D78E7 +:10379000EBF25F67AD467EC1FB45743E5967E2F6CA +:1037A000BEDDDCFE7861E9C1DFDD07F5CE3FBE2579 +:1037B00099A95ABCA19EBA40E8AB0B85FDAF1BBCD2 +:1037C0006D19DA3B985FF81CC75BE9DEDFFE05DFA9 +:1037D000132B4E11F26E3D7F07A0A4791FE171CE2D +:1037E000DA0D2627D4DB37D44970EA92FFB5B976D3 +:1037F000B42BCF5DBBC58472629F84838E1F8A45C4 +:103800009CB08433EE4B4A887F43D647F988EFDF7C +:103810003FB4242C0AE379E4381F093A2FAD8D898F +:10382000C5F14A6BBD3FC6F390DC0FF4EB3C1DC6FF +:10383000F9A504FA43BE3D3DCE95BC342BA8CFEA92 +:10384000EBBF2BF0F8B489FF4E4D5244F32E8A6B38 +:10385000A80977A1FC1838B0CD8FE3227DE3BCCD59 +:1038600006FEBB3603ABDA3EC77980AA4D713598A8 +:10387000E2FB58A87AC7437EAB81DFDF4A5179FA71 +:103880009590D7501EC072D6AB8D7E5F23246E56A6 +:1038900043BF66B68D7E3FD1DC8BD1FB66925E6501 +:1038A0003F925E253DF7B4BE2B42AEDC687DA79DFE +:1038B0001C9E66F1BB2937BD3E0BFF1D5DB92E393D +:1038C0003FD0E1DDF4BEC7F7B3C9DE737A852B19AB +:1038D000E3267B5EEFC6FCF86ED6AB5FA7E41B1950 +:1038E0000BDFE5CF6AE27E87D30AEC6FD0EEF4926D +:1038F000308A6F93EBD2DBC3FF1FB640B5F6008072 +:10390000000000001F8B080000000000000BCD56D7 +:103910007D6C5355143FF7BE7EAFDDDEBAB1751B2B +:10392000DBBA8D8F46BAF1CA80F891681D8CF0C75A +:10393000A2DD14DD0C6C25B031C68A9360A8C6B830 +:10394000B2229211E24C3618044C876C7F18205D2D +:10395000208AB19A8689468311E11F1292A60B38FC +:10396000D16856310A44649E73DF2B9D08897FFA23 +:1039700092E6F4DE7B3E7FE7E3DE0F7A658085002A +:10398000C77B1D00468093BD4E41A3BD2EB19FA7AE +:10399000D801E6007E495B930D60AD05DA7C565C8C +:1039A000C6F1970F9008568DF4B3CC7E831DDA9A3A +:1039B0009026E4A4CDEEC67DBBBA7FADC7DC0F393F +:1039C000002D90DCE7588AB2C12A1845538981AB93 +:1039D000368E7C579F463E77466EBB3EB51E88CFDF +:1039E00066708E5600646DFFAEBE10EDB50F567852 +:1039F00018CAAD0BD6268278BE6E57A102B86EB734 +:103A00003A773BE83C54A1F4E13A6BD033358CE78C +:103A1000EDBB1629C4BF9D812F4A7E0F1C002800D4 +:103A2000E8807B9FD7B41C6013FD43BE4D56C32472 +:103A3000ABC1F3E0C43C19E53B14B387A1FD4DC312 +:103A40002C6EC4FD060E7BD81280F2B06F5511DAD1 +:103A50004B1D64CA51923D5CEF4D9A5485339500DD +:103A60005D0B7D35CA325CDC99999941FD8F20460A +:103A700020515C512FC501434C1E05F2DB67207CB1 +:103A80004E2C760A9C13839336A75BC5BB11F106B7 +:103A900047010794DF6652FD2B37A426DF46BF524D +:103AA00036AE1CC575BDE4FED649717E2581D1496F +:103AB000721ABFACF1BFF9A8C98FFAB6D92A0B01A7 +:103AC000E9C66174A216CF9A4D9C70E8D47C6E1F33 +:103AD00079AE00D08F763C77E2F921DA7C0C60F782 +:103AE000E08A8224C9BD5BBF3F540D50A6E1784DEA +:103AF000976CA4FC5C1F29B4EFC4D83606C20B0037 +:103B0000CF378EBC5D46F4FA88B939827C2BE5C686 +:103B100095B9186FC7E15C8F84FECCD0F714E64DE1 +:103B20004121C4A72BB0A21010AFEEBB13EFC955B3 +:103B3000681FB126DC7F8F664542C8D2DD7BA64C6C +:103B4000E2E88AD1DF4C786EE1B1171E433D3FB108 +:103B5000C85891E07716CAD68CDEFBE9542FC28094 +:103B6000F51C78F3B2D0F30B3FFF4C0BCA77074E2E +:103B700065939E2D439796CBB8DF59E5DFA8CC21FE +:103B8000BD2363324204C323353E8CA35D01E1674C +:103B900083DDF7420BE1FE9524707F98BDCE334C58 +:103BA000E07B2FCE488E8170F7C7C1201395C140AE +:103BB000F57D5D8260146943A5DA2FE9FD20E1827D +:103BC0007E5CCF1928A3BAD83C76A0CC89F4479B59 +:103BD000BA5E3BF6E2D7908DFCC78C06CA975F07AA +:103BE0000605E5368498374275D389FD5A94B1DFCE +:103BF000A764097D9B87D1A9BCCC3E4044C4F5A3F2 +:103C00000E56931FE5E194E715A45774F176CAEBBD +:103C1000951EB312AAA03C3905DF95016915ED8701 +:103C2000B091E6335A9FB2CD43FBAD39D043F2B6E3 +:103C3000A5D138C73C074EE72E91D49212F5B55561 +:103C40005617F5927555099E6F1B6732D5E9B68FE9 +:103C5000CFAD02750DC01E8E67D7AD27C039CBEF33 +:103C6000AED3E306EA8FEEE3182FDAEF8E8E7F51A4 +:103C70008C7AB69E595FABDA1D00AAFF80D6CF5B67 +:103C80004FABB8044E4F1A36B8337AD6BBECBB4BA9 +:103C900030B7A34AEB8B43C8BA9EF2F63840EC64C7 +:103CA00063F3CE79486B641137E852653EECC37E0E +:103CB000D74503F5516097A6CF757177A588B731C1 +:103CC0000F66D5C398A217726979C443C8C5039615 +:103CD0003DB01887CD56AB8E683860CD267AB88750 +:103CE000BB7488AB97591409F10E9AB26B684EDE1B +:103CF00034AB346651E90EEE1BEF40176FF20B66E2 +:103D0000C0BADF210D30A24FB97B18220D8BF2FD16 +:103D100031AA5F0744190820E28CFC9EFEF4875A02 +:103D2000B2FF6479F2374097F43BDB9A57627D7CAF +:103D3000AE68F1B993B554E773CEAA73FA881EF64C +:103D4000989750DC3E68AA262DF89FF27E9B476824 +:103D50000EC758FC7DD29F8EF796D6C73EA3750F2F +:103D6000433F1B9CFE6FC88F6799BEDAC32907D2F9 +:103D70007CD23FAD57CF71FE7A4D581775DAF02DD2 +:103D8000E510022C5943B1C34A75CDBC5E08A2FDB3 +:103D90003EF7D90D541F7B532630A2DDB086475D18 +:103DA000CA32C990AFB47835079CC7CC994F770C0D +:103DB0009C75F39011FDDC0BA608F18309E7B12B8C +:103DC000338F0DDCEC15FCB12F6FD37C2F917E9DD2 +:103DD000C841FE921D4C09234FEB8DA923DF225DC4 +:103DE0000B110FE1DA95EF9FA2381237564FFA31D7 +:103DF000BF7BE5A84971ABFA66FB1F7BED76B69DEC +:103E000067FC9A4E4D9DF868295193B877EA629203 +:103E1000B837EEF767DAE1D4911DE48B73E2B7F2BD +:103E20000863C43F7199FCAB3359E35236C9E97F4B +:103E30009E7DAFC085D2DCA945E22A8199129CF60D +:103E400061356F4F6A7D98CE8B85C05F4654CD4FEC +:103E50001A3FE1FCACFBE433EBD83AAA9F74BFBE37 +:103E6000ACEDDFB8559943F3E546AC2A07DC0FEF1C +:103E7000CF4B385FE99D70B8C26BF72CCBDCA76BDA +:103E8000D2B7AB76DF4A9ADE351A4E6BAC5CC5E52D +:103E9000F9FB70D1EA245D0769BFD3794EE70F5E65 +:103EA000BF702EA742E4ADFA1D10F99A4BF613B776 +:103EB000CFBF856D05C59277D25FF17FCC57DCBC53 +:103EC00090DE0D435CBC1B4A09F825827A39C6078F +:103ED0002E10F3A055B228FD0F98077E9A078B6924 +:103EE0001E0C883EBFC953E738A379D023D60E48AD +:103EF000EDD4E13AC19336F23769C6AA47EAF754DE +:103F00008A7BA0843ABA4ACD13F5F591D76C47E97C +:103F1000FD1666DE8326940FEBB57EDF6C8D8CE29A +:103F2000FE748487F4686F303772B003F707D7CC1C +:103F3000554288D334687C9D1631179EE05CAC53A3 +:103F40002D0591A315C48F7D8D710EB63C22EEF127 +:103F50000FEF4AE2BD989A0FEAB907160CD379A37E +:103F60004BE8FB243D67F6D984BEC1466F91459C62 +:103F70001770928FE4F95FA2FC164B2A1F3E0404CF +:103F8000DFA143DE22CAC7A12683E0DBCF7C2DED73 +:103F9000A4A7DAAAD0FB32D9623939A6A623CE96D5 +:103FA000D27B558D375DBFC30B64814B7968F2209E +:103FB000BD434275E0EAA1F72BD5E1E24C7E9817AC +:103FC0007361CFE4295D8F213DE62B5FCD571FFB49 +:103FD00077BEF2B57CB120D66D36E52D2AF0BFC98B +:103FE000D53CEC9020998531495C711891FE91EF98 +:103FF0007F558DF342119DB71A93CB06E85DCCA196 +:1040000033FA803E0C519F8BF739DEA258E76D5A88 +:104010009DB7A5EBF18DFBEA313937772A4BAB47DA +:1040200094FFDEE2EB237BBFB04BCB69F3FC5F5226 +:10403000F383ECECD5E6C89F467FBFE8F36385FFCA +:1040400078679EF7FC504AF70CDC99984BF7CE99AD +:104050003CDF3EE233CF4B19FC8467514A4FF124D9 +:104060005A7E2AA5F74C5BF04BD137FFD5CFB41F52 +:104070007F03DC4DE081B00C000000000000000078 +:1040800000000018000000000000000000000040D8 +:1040900000000000000000000000002800000000F8 +:1040A0000000000000000010000000000000000000 +:1040B00000000020000000000000000000000010D0 +:1040C00000000000000000000000000800000000E8 +:1040D00000000000000000000000000000000000E0 +:1040E00000000000000000000000000000000000D0 +:1040F00000000000000000000000000000000000C0 +:1041000000000000000000000000000000000000AF +:10411000000000000000000000000000000000009F +:10412000000000000000000000000000000000008F +:10413000000000000000000000000000000000007F +:10414000000000000000000000000000000000006F +:10415000000000000000000000000000000000005F +:10416000000000000000000000000000000000004F +:10417000000000000000000000000000000000003F +:10418000000000000000000000000000000000002F +:10419000000000000000000000000000000000001F +:1041A000000000000000000000000000000000000F +:1041B00000000000000000000000000000000000FF +:1041C00000000000000000000000000000000000EF +:1041D00000000000000000000000000000000000DF +:1041E0000000000000000000000033280010000064 +:1041F0000000000800003330001000000000000242 +:1042000000003328001000000000001000003A7881 +:104210000000000000000008800000000000000016 +:10422000000000008000000000000000000000000E +:1042300080000000000000000000000000003120AD +:1042400000000000000000080000336000010004CE +:1042500000000001000033680000000000000002C0 +:1042600000003370000000000000000800003374FC +:10427000000000000000000200003A700000000092 +:104280000000000800003A4000080000000000089C +:1042900000003D88004000000000004000003A504F +:1042A000000800000000000800003A60000800005C +:1042B0000000000800003A8800C8000000000098D4 +:1042C00000003C18009800000000002800003C5846 +:1042D00000980000000000280000337803600030E0 +:1042E0000000036000003EB0000800000000000174 +:1042F00000003EB10008000000000001000020089E +:10430000001000000000001000002000000000006D +:104310000000000880000000000000000000000015 +:10432000800000000000000000000000000000000D +:10433000000000000000000000000000000000007D +:10434000000000000000000000000000000000006D +:10435000800000000000000000000000800000005D +:1043600000000000000000008000000000000000CD +:1043700000000000800000000000000000000000BD +:10438000800000000000000000000000800000002D +:10439000000000000000000080000000000000009D +:1043A000000000008000000000000000000000008D +:1043B00080000000000000000000000080000000FD +:1043C000000000000000000080000000000000006D +:1043D000000000008000000000000000000000005D +:1043E000800000000000000000000000000000004D +:1043F00000000000000000000000000000000000BD +:1044000000000000000000000000000000000000AC +:10441000000000000000000000000000000000009C +:10442000000000000000000080000000000000000C +:1044300000000000800000000000000000000000FC +:1044400080000000000000000000000000000000EC +:1044500000000000000000008000000000000000DC +:1044600000000000800000000000000000000000CC +:1044700080000000000000000000000000000000BC +:10448000000000000000000000000000000000002C +:10449000000000000000000000000000000000001C +:1044A000000000000000000000000000000000000C +:1044B00000000000000000000000000000000000FC +:1044C00000000000000012C8008000000000008012 +:1044D000000000010000000000000000000040009B +:1044E0000490000000000490000019C800000000C3 +:1044F0000000000800004948000800000000000813 +:1045000000004928000800000000000800004938A9 +:104510000008000000000008000020080010000053 +:104520000000001000002000000000000000000853 +:104530000000401004900040000000400000499836 +:104540000008000000000001000049990008000078 +:1045500000000001800000000000000000000000DA +:10456000800000000000000000000000800000004B +:1045700000000000000000008000000000000000BB +:1045800000000000800000000000000000000000AB +:10459000800000000000000000000000800000001B +:1045A000000000000000000080000000000000008B +:1045B000000000008000000000000000000000007B +:1045C00080000000000000000000000080000000EB +:1045D000000000000000000080000000000000005B +:1045E000000000008000000000000000000000004B +:1045F00000000000000000000000000000000000BB +:1046000000000000000000000000000000000000AA +:10461000000000000000000000000000000000009A +:10462000000000000000000000000000800000000A +:1046300000000000000000008000000000000000FA +:10464000000000000000000000000000000000006A +:10465000800000000000000000000000800000005A +:1046600000000000000000008000000000000000CA +:1046700000000000800000000000000000000000BA +:104680000000400000180000000000180000430077 +:104690000040000000000040000043000040000215 +:1046A0000000000100004301004000020000000083 +:1046B00000003000004000000000004080000000CA +:1046C0000000000000000000000030000008004072 +:1046D0000000000400003004000800400000000456 +:1046E00000004B00002800000000002800004B5094 +:1046F00000100000000000100000380000800000E2 +:104700000000008000003800000800800000000267 +:1047100000003900002000000000002000002008F8 +:104720000010000000000010000020000000000049 +:104730000000000800005108000800000000000808 +:104740000000512000080000000000080000513067 +:104750000008000000000008000051C00008000030 +:1047600000000001000051C100080000000000012D +:10477000000039400010000400000004000051D087 +:104780000030001800000010000051D80030001860 +:104790000000000280000000000000000000000097 +:1047A0008000000000000000000000008000000009 +:1047B0000000000000000000800000000000000079 +:1047C0000000000080000000000000000000000069 +:1047D00080000000000000000000000080000000D9 +:1047E0000000000000000000800000000000000049 +:1047F0000000000080000000000000000000000039 +:1048000000000000000000000000000000000000A8 +:104810000000000000000000000000000000000098 +:104820000000000000000000000000000000000088 +:104830008000000000000000000000008000000078 +:104840000000000000000000000000000000000068 +:1048500000000000000023E800800000000000804D +:10486000000000010000000000000000000020081F +:1048700000100000000000100000200000000000F8 +:104880000000000800002DA0000800000000000843 +:1048900000002DB80008000000000008000024E817 +:1048A00002D00028000002D000002E5800080000AE +:1048B0000000000100002E59000800000000000167 +:1048C00000002D900008000000000008800000009B +:1048D0000000000000000000800000000000000058 +:1048E0000000000080000000000000000000000048 +:1048F00080000000000000000000000080000000B8 +:104900000000000000000000800000000000000027 +:104910000000000080000000000000000000000017 +:104920000000000000000000000000000000000087 +:104930000000000000000000000000000000000077 +:104940000000000000000000000000000000000067 +:104950008000000000000000000000008000000057 +:104960000000000000000000000000000000000047 +:1049700000000000800000000000000000000000B7 +:104980008000000000000000000000008000000027 +:104990000000000000000000800000000000000097 +:1049A000000000000000250000400000000000089A +:1049B000000025080040000000000028000009C099 +:1049C000012000100000000880000000000000002E +:1049D0000000000080000000000000000000000057 +:1049E0000000402002D00028000000080000300035 +:1049F00000000000000010000000509900000000BE +:104A000000000001000050B00000000000000002A3 +:104A1000000045A000900008000000088000000091 +:104A200000000000000000000000296000080000F5 +:104A300000000001000029610008000000000001E2 +:104A4000000029700008000400000002000029781E +:104A5000000800040000000400002FB0000800005F +:104A60000000000400002FB4000800000000000453 +:104A700000002FC0000000000000000800002FC848 +:104A800000000000000000080000300000000000EE +:104A90000000001000005040000100010000000173 +:104AA0000000500000000000000000200000080886 +:104AB00000100000000000040000080C00100000BE +:104AC00000000001000008B7000000000000000125 +:104AD000000008B600000000000000010000100007 +:104AE000003000180000000400001004003000181E +:104AF0000000000400001008003000180000000250 +:104B00000000100A00300018000000020000100C25 +:104B100000300018000000010000100D00300018E7 +:104B2000000000010000100E00300018000000011D +:104B300000001010003000180000000400001014E5 +:104B40000030001800000004000030000100008068 +:104B50000008000400003004010000800008000488 +:104B60000000000A000000000000000000003068A3 +:104B70000100008000000001000030690100008099 +:104B8000000000010000306C010000800000000205 +:104B90000000306E01000080000000020000307054 +:104BA000010000800000000400003074010000805B +:104BB00000000004000030660100008000000002D8 +:104BC000000030640100008000000001000030603F +:104BD000010000800000000200003062010000803F +:104BE00000000002000030500100008000000004BE +:104BF0000000305401000080000000040000305824 +:104C000001000080000000040000305C0100008012 +:104C1000000000040000307C010000800000000162 +:104C20000000307D010000800000000100001C1821 +:104C3000001000000000000400001C300010000004 +:104C40000000000400001C380010000000000004F8 +:104C50008000000000000000000000008000000054 +:104C600000000000000000008000000000000000C4 +:104C700000000000800000000000000000000000B4 +:104C800000004C10000800000000000200004C1260 +:104C9000000800000000000200004C1400080000A2 +:104CA0000000000400004C20000800000000000884 +:104CB00000004C30004000080000000800004C00DC +:104CC000000800000000000200004C020008000084 +:104CD0000000000100004C04000800000000000279 +:104CE00000004CD0000800000000000800004CE06C +:104CF000000800000000000400004CE40008000070 +:104D00000000000100004CF000080000000000025C +:104D100000004CF4000800000000000200004D00FC +:104D20000008000000000004000050000010000017 +:104D30000000000400005004001000000000000407 +:104D400000005008001000000000000400001400E3 +:104D5000000800000000000200001402000800002B +:104D60000000000100001404000800000000000220 +:104D700000001410000800000000000200001414DD +:104D800000080000000000020000141600080000E7 +:104D900000000002000019B8000800000000000830 +:104DA000000014200008000000000002000014248D +:104DB0000008000000000002000019C80008000000 +:104DC0000000000800002C10000800000000000196 +:104DD00000002C11000800000000000100002C124F +:104DE000000800000000000100002C130008000073 +:104DF0000000000100002C0000080000000000027C +:104E000000002C02000800000000000100002C043B +:104E1000000800000000000200002C300008000024 +:104E20000000000200002C32000800000000000218 +:104E300000002C34000800000000000200002C20BC +:104E4000000800000000000100002C210008000004 +:104E50000000000100002C220008000000000001FA +:104E600000002C23000800000000000100002C249A +:104E7000000800000000000100002C2500080000D0 +:104E80000000000100002C260008000000000001C6 +:104E900000001400000800000000000200001402DE +:104EA00000080000000000010000140400080000D9 +:104EB000000000020000141200C0001800000002F0 +:104EC0000000141000C00018000000020000141CB4 +:104ED00000C00018000000080000141400C00018F2 +:104EE000000000080000142700C0001800000001A6 +:104EF0000000142400C00018000000020000142666 +:104F000000C000180000000100001590000800001B +:104F100000000008000015A00008000000000008C4 +:104F2000000015B00008000000000008800000002C +:104F300000000000000000008000000000000000F1 +:104F400000000000800000000000000000000000E1 +:104F50008000000000000000000000008000000051 +:104F600000000000000000008000000000000000C1 +:104F700000000000800000000000000000000000B1 +:104F80008000000000000000000000008000000021 +:104F90000000000000000000800000000000000091 +:104FA0000000000080000000000000000000000081 +:104FB00080000000000000000000000080000000F1 +:104FC0000000000000000000800000000000000061 +:104FD0000000000080000000000000000000000051 +:104FE00080000000000000000000000080000000C1 +:104FF0000000000000000000800000000000000031 +:105000000000000080000000000000000000000020 +:105010008000000000000000000000008000000090 +:105020000000000000000000800000000000000000 +:1050300000000000800000000000000000000000F0 +:105040008000000000000000000000008000000060 +:1050500000000000000000008000000000000000D0 +:105060000000000000000000000000000000000040 +:1050700080000000000000000000000000000000B0 +:08508000060209000000000017 +:00000001FF diff --git a/firmware/bnx2x/bnx2x-e1h-6.2.5.0.fw.ihex b/firmware/bnx2x/bnx2x-e1h-6.2.5.0.fw.ihex deleted file mode 100644 index 5f04df69e7c3..000000000000 --- a/firmware/bnx2x/bnx2x-e1h-6.2.5.0.fw.ihex +++ /dev/null @@ -1,13181 +0,0 @@ -:1000000000004F48000000680000070C00004FB8D7 -:1000100000001ED4000056C800000094000075A027 -:1000200000009F4C00007638000000CC00011588CD -:100030000000DC4C00011658000000940001F2A8FA -:10004000000040000001F340000000A4000233481B -:100050000000F38C000233F000000FFC0003278047 -:100060000000000400033780020400480000000F75 -:1000700002040054000000450204005C0000000679 -:100080000204007000000004020400780000000078 -:100090000204007C121700000204008022170000F6 -:1000A00002040084321700000604008800000005E6 -:1000B0000204009C12150000020400A0221500009A -:1000C000020400A432150000060400A80000000489 -:1000D000020400B802100000020400BC001000007E -:1000E000020400C010100000020400C42010000030 -:1000F000020400C830100000020400CC40100000D0 -:10010000060400D000000003020400DC0010000020 -:10011000020400E012140000020400E422140000B3 -:10012000020400E832140000020400EC4214000053 -:10013000060400F000000003010401240000000098 -:1001400001040128000000000104012C000000004F -:100150000104013000000000020401D00000890603 -:1001600002040004000000FF02040008000000FF79 -:100170000204000C000000FF02040010000000FF59 -:10018000020400140000007F02040018000000FFB9 -:100190000204001C000000FF02040020000000FF19 -:1001A000020400240000003E0204002800000000B9 -:1001B0000204002C0000003F020400300000003F59 -:1001C000020400340000003F020400380000003F39 -:1001D0000204003C0000003F020400400000003F19 -:1001E000020400440000003F020404CC00000001AF -:1001F00002042008000002110204200C000002008A -:10020000020420100000020402042014000002195D -:100210000204201C0000FFFF020420200000FFFF5A -:10022000020420240000FFFF020420280000FFFF3A -:1002300002042038000000200604203C0000001FBB -:10024000020420B800000001060420BC0000005F8A -:100250000204223807FFFFFF0204223C0000003F97 -:100260000204224007FFFFFF020422440000000FA7 -:1002700001042248000000000104224C000000009C -:10028000010422500000000001042254000000007C -:1002900001042258000000000104225C000000005C -:1002A000010422600000000001042264000000003C -:1002B00001042268000000000104226C000000001C -:1002C00001042270000000000104227400000000FC -:1002D00001042278000000000104227C00000000DC -:1002E0000C042000000003E80A04200000000001C4 -:1002F0000B0420000000000A0605400000000D006D -:100300000205004400000020020500480000003201 -:10031000020500900215002002050094021500203D -:1003200002050098000000300205009C0810000043 -:10033000020500A000000033020500A40000003008 -:10034000020500A800000031020500AC0000000218 -:10035000020500B000000005020500B40000000620 -:10036000020500B800000002020500BC0000000207 -:10037000020500C000000000020500C400000005E6 -:10038000020500C800000002020500CC00000002C7 -:10039000020500D000000002020500D400000001A8 -:1003A00002050114000000010205011C000000010B -:1003B0000205012000000002020502040000000105 -:1003C0000205020C0000004002050210000000407F -:1003D0000205021C0000002002050220000000139C -:1003E0000205022400000020060502400000000A69 -:1003F00004050280002000000205005000000007F4 -:10040000020500540000000702050058000000002B -:100410000205005C00000008020500600000000109 -:100420000605006400000003020500D80000000675 -:1004300002050004000000010205000800000001A0 -:100440000205000C00000001020500100000000180 -:100450000205001400000001020500180000000160 -:100460000205001C00000001020500200000000140 -:100470000205002400000001020500280000000120 -:100480000205002C00000001020500300000000100 -:1004900002050034000000010205003800000001E0 -:1004A0000205003C000000010205004000000001C0 -:1004B000020500E00000000D020500E80000000059 -:1004C000020500F000000000020500F80000000036 -:1004D000020500E40000002D020500EC00000020F1 -:1004E000020500F400000020020500FC00000020CE -:1004F000020500E00000001D020500E800000010F9 -:10050000020500F000000010020500F800000010D5 -:10051000020500E40000003D020500EC0000003090 -:10052000020500F400000030020500FC000000306D -:10053000020500E00000004D020500E80000004058 -:10054000020500F000000040020500F80000004035 -:10055000020500E40000006D020500EC00000060F0 -:10056000020500F400000060020500FC00000060CD -:10057000020500E00000005D020500E800000050F8 -:10058000020500F000000050020500F800000050D5 -:10059000020500E40000007D020500EC0000007090 -:1005A000020500F400000070020500FC000000706D -:1005B0000406100002000020020600DC000000011A -:1005C000010600D80000000004060200000302201B -:1005D000020600DC00000000010600B80000000078 -:1005E000010600C8000000000206016C00000000C7 -:1005F000010600BC00000000010600CC0000000065 -:1006000002060170000000000718040000910000BD -:10061000081807D800050223071C00002BF700006C -:10062000071C80002DD10AFE071D00002F461673FF -:10063000071D800016342245081DB13049DA022515 -:100640000118000000000000011800040000000074 -:1006500001180008000000000118000C0000000054 -:100660000118001000000000011800140000000034 -:1006700002180020000000010218002400000002FF -:1006800002180028000000030218002C00000000DF -:1006900002180030000000040218003400000001BD -:1006A00002180038000000000218003C00000001A1 -:1006B000021800400000000402180044000000007E -:1006C00002180048000000010218004C000000035E -:1006D0000218005000000000021800540000000141 -:1006E00002180058000000040218005C000000001E -:1006F00002180060000000010218006400000003FE -:1007000002180068000000000218006C00000001E0 -:1007100002180070000000040218007400000000BD -:1007200002180078000000040218007C000000039A -:100730000618008000000002021800A400003FFF1D -:10074000021800A8000003FF0218022400000000A5 -:1007500002180234000000000218024C00000000E1 -:10076000021802E4000000FF061810000000040058 -:10077000021B8BC000000001021B8000000000343F -:10078000021B804000000018021B80800000000C4B -:10079000021B80C0000000200C1B83000007A1206A -:1007A0000A1B8300000001380B1B83000000138824 -:1007B0000A1B8340000000000C1B8340000001F472 -:1007C0000B1B834000000005021B83800007A12053 -:1007D000021B83C0000001F4021B14800000000112 -:1007E0000A1B148000000000061A1000000003B36A -:1007F000041A1ECC00010227061A1ED000000008B1 -:10080000061A2008000000C8061A20000000000296 -:10081000041AAF4000100228061A3718000000041E -:10082000061A371000000002061A500000000002ED -:10083000061A500800000004061A501800000004B0 -:10084000061A502800000004061A50380000000460 -:10085000061A504800000004061A50580000000410 -:10086000061A506800000004061A507800000002C2 -:10087000041A52C000020238061A40500000000656 -:10088000041A40680002023A041A40400004023C84 -:10089000041A800000010240061A800400000003D0 -:1008A000041A801000010241061A8014000000039F -:1008B000041A802000010242061A8024000000036E -:1008C000041A803000010243061A8034000000033D -:1008D000041A804000010244061A8044000000030C -:1008E000041A805000010245061A805400000003DB -:1008F000041A806000010246061A806400000003AA -:10090000041A807000010247061A80740000000378 -:10091000041A808000010248061A80840000000347 -:10092000041A809000010249061A80940000000316 -:10093000041A80A00001024A061A80A400000003E5 -:10094000041A80B00001024B061A80B400000003B4 -:10095000041A80C00001024C061A80C40000000383 -:10096000041A80D00001024D061A80D40000000352 -:10097000041A80E00001024E061A80E40000000321 -:10098000041A80F00001024F061A80F400000003F0 -:10099000041A810000010250061A810400000003BD -:1009A000041A811000010251061A8114000000038C -:1009B000041A812000010252061A8124000000035B -:1009C000041A813000010253061A8134000000032A -:1009D000041A814000010254061A814400000003F9 -:1009E000041A815000010255061A815400000003C8 -:1009F000041A816000010256061A81640000000397 -:100A0000041A817000010257061A81740000000365 -:100A1000041A818000010258061A81840000000334 -:100A2000041A819000010259061A81940000000303 -:100A3000041A81A00001025A061A81A400000003D2 -:100A4000041A81B00001025B061A81B400000003A1 -:100A5000041A81C00001025C061A81C40000000370 -:100A6000041A81D00001025D061A81D4000000033F -:100A7000041A81E00001025E061A81E4000000030E -:100A8000041A81F00001025F061A81F400000003DD -:100A9000041A820000010260061A820400000003AA -:100AA000041A821000010261061A82140000000379 -:100AB000041A822000010262061A82240000000348 -:100AC000041A823000010263061A82340000000317 -:100AD000041A824000010264061A824400000003E6 -:100AE000041A825000010265061A825400000003B5 -:100AF000041A826000010266061A82640000000384 -:100B0000041A827000010267061A82740000000352 -:100B1000041A828000010268061A82840000000321 -:100B2000041A829000010269061A829400000003F0 -:100B3000041A82A00001026A061A82A400000003BF -:100B4000041A82B00001026B061A82B4000000038E -:100B5000041A82C00001026C061A82C4000000035D -:100B6000041A82D00001026D061A82D4000000032C -:100B7000041A82E00001026E061A82E400000003FB -:100B8000041A82F00001026F061A82F400000003CA -:100B9000041A830000010270061A83040000000397 -:100BA000041A831000010271061A83140000000366 -:100BB000041A832000010272061A83240000000335 -:100BC000041A833000010273061A83340000000304 -:100BD000041A834000010274061A834400000003D3 -:100BE000041A835000010275061A835400000003A2 -:100BF000041A836000010276061A83640000000371 -:100C0000041A837000010277061A8374000000033F -:100C1000041A838000010278061A8384000000030E -:100C2000041A839000010279061A839400000003DD -:100C3000041A83A00001027A061A83A400000003AC -:100C4000041A83B00001027B061A83B4000000037B -:100C5000041A83C00001027C061A83C4000000034A -:100C6000041A83D00001027D061A83D40000000319 -:100C7000041A83E00001027E061A83E400000003E8 -:100C8000041A83F00001027F061A83F400000003B7 -:100C9000041A840000010280061A84040000000384 -:100CA000041A841000010281061A84140000000353 -:100CB000041A842000010282061A84240000000322 -:100CC000041A843000010283061A843400000003F1 -:100CD000041A844000010284061A844400000003C0 -:100CE000041A845000010285061A8454000000038F -:100CF000041A846000010286061A8464000000035E -:100D0000041A847000010287061A8474000000032C -:100D1000041A848000010288061A848400000003FB -:100D2000041A849000010289061A849400000003CA -:100D3000041A84A00001028A061A84A40000000399 -:100D4000041A84B00001028B061A84B40000000368 -:100D5000041A84C00001028C061A84C40000000337 -:100D6000041A84D00001028D061A84D40000000306 -:100D7000041A84E00001028E061A84E400000003D5 -:100D8000041A84F00001028F061A84F400000003A4 -:100D9000041A850000010290061A85040000000371 -:100DA000041A851000010291061A85140000000340 -:100DB000041A852000010292061A8524000000030F -:100DC000041A853000010293061A853400000003DE -:100DD000041A854000010294061A854400000003AD -:100DE000041A855000010295061A8554000000037C -:100DF000041A856000010296061A8564000000034B -:100E0000041A857000010297061A85740000000319 -:100E1000041A858000010298061A858400000003E8 -:100E2000041A859000010299061A859400000003B7 -:100E3000041A85A00001029A061A85A40000000386 -:100E4000041A85B00001029B061A85B40000000355 -:100E5000041A85C00001029C061A85C40000000324 -:100E6000041A85D00001029D061A85D400000003F3 -:100E7000041A85E00001029E061A85E400000003C2 -:100E8000041A85F00001029F061A85F40000000391 -:100E9000041A8600000102A0061A8604000000035E -:100EA000041A8610000102A1061A8614000000032D -:100EB000041A8620000102A2061A862400000003FC -:100EC000041A8630000102A3061A863400000003CB -:100ED000041A8640000102A4061A8644000000039A -:100EE000041A8650000102A5061A86540000000369 -:100EF000041A8660000102A6061A86640000000338 -:100F0000041A8670000102A7061A86740000000306 -:100F1000041A8680000102A8061A868400000003D5 -:100F2000041A8690000102A9061A869400000003A4 -:100F3000041A86A0000102AA061A86A40000000373 -:100F4000041A86B0000102AB061A86B40000000342 -:100F5000041A86C0000102AC061A86C40000000311 -:100F6000041A86D0000102AD061A86D400000003E0 -:100F7000041A86E0000102AE061A86E400000003AF -:100F8000041A86F0000102AF061A86F4000000037E -:100F9000041A8700000102B0061A8704000000034B -:100FA000041A8710000102B1061A8714000000031A -:100FB000041A8720000102B2061A872400000003E9 -:100FC000041A8730000102B3061A873400000003B8 -:100FD000041A8740000102B4061A87440000000387 -:100FE000041A8750000102B5061A87540000000356 -:100FF000041A8760000102B6061A87640000000325 -:10100000041A8770000102B7061A877400000003F3 -:10101000041A8780000102B8061A878400000003C2 -:10102000041A8790000102B9061A87940000000391 -:10103000041A87A0000102BA061A87A40000000360 -:10104000041A87B0000102BB061A87B4000000032F -:10105000041A87C0000102BC061A87C400000003FE -:10106000041A87D0000102BD061A87D400000003CD -:10107000041A87E0000102BE061A87E4000000039C -:10108000041A87F0000102BF061A87F4000000036B -:10109000041A8800000102C0061A88040000000338 -:1010A000041A8810000102C1061A88140000000307 -:1010B000041A8820000102C2061A882400000003D6 -:1010C000041A8830000102C3061A883400000003A5 -:1010D000041A8840000102C4061A88440000000374 -:1010E000041A8850000102C5061A88540000000343 -:1010F000041A8860000102C6061A88640000000312 -:10110000041A8870000102C7061A887400000003E0 -:10111000041A8880000102C8061A888400000003AF -:10112000041A8890000102C9061A8894000000037E -:10113000041A88A0000102CA061A88A4000000034D -:10114000041A88B0000102CB061A88B4000000031C -:10115000041A88C0000102CC061A88C400000003EB -:10116000041A88D0000102CD061A88D400000003BA -:10117000041A88E0000102CE061A88E40000000389 -:10118000041A88F0000102CF061A88F40000000358 -:10119000041A8900000102D0061A89040000000325 -:1011A000041A8910000102D1061A891400000003F4 -:1011B000041A8920000102D2061A892400000003C3 -:1011C000041A8930000102D3061A89340000000392 -:1011D000041A8940000102D4061A89440000000361 -:1011E000041A8950000102D5061A89540000000330 -:1011F000041A8960000102D6061A896400000003FF -:10120000041A8970000102D7061A897400000003CD -:10121000041A8980000102D8061A8984000000039C -:10122000041A8990000102D9061A8994000000036B -:10123000041A89A0000102DA061A89A4000000033A -:10124000041A89B0000102DB061A89B40000000309 -:10125000041A89C0000102DC061A89C400000003D8 -:10126000041A89D0000102DD061A89D400000003A7 -:10127000041A89E0000102DE061A89E40000000376 -:10128000041A89F0000102DF061A89F40000000345 -:10129000041A8A00000102E0061A8A040000000312 -:1012A000041A8A10000102E1061A8A1400000003E1 -:1012B000041A8A20000102E2061A8A2400000003B0 -:1012C000041A8A30000102E3061A8A34000000037F -:1012D000041A8A40000102E4061A8A44000000034E -:1012E000041A8A50000102E5061A8A54000000031D -:1012F000041A8A60000102E6061A8A6400000003EC -:10130000041A8A70000102E7061A8A7400000003BA -:10131000041A8A80000102E8061A8A840000000389 -:10132000041A8A90000102E9061A8A940000000358 -:10133000041A8AA0000102EA061A8AA40000000327 -:10134000041A8AB0000102EB061A8AB400000003F6 -:10135000041A8AC0000102EC061A8AC400000003C5 -:10136000041A8AD0000102ED061A8AD40000000394 -:10137000041A8AE0000102EE061A8AE40000000363 -:10138000041A8AF0000102EF061A8AF40000000332 -:10139000041A8B00000102F0061A8B0400000003FF -:1013A000041A8B10000102F1061A8B1400000003CE -:1013B000041A8B20000102F2061A8B24000000039D -:1013C000041A8B30000102F3061A8B34000000036C -:1013D000041A8B40000102F4061A8B44000000033B -:1013E000041A8B50000102F5061A8B54000000030A -:1013F000041A8B60000102F6061A8B6400000003D9 -:10140000041A8B70000102F7061A8B7400000003A7 -:10141000041A8B80000102F8061A8B840000000376 -:10142000041A8B90000102F9061A8B940000000345 -:10143000041A8BA0000102FA061A8BA40000000314 -:10144000041A8BB0000102FB061A8BB400000003E3 -:10145000041A8BC0000102FC061A8BC400000003B2 -:10146000041A8BD0000102FD061A8BD40000000381 -:10147000041A8BE0000102FE061A8BE40000000350 -:10148000041A8BF0000102FF061A8BF4000000031F -:10149000041A8C0000010300061A8C0400000003EB -:1014A000041A8C1000010301061A8C1400000003BA -:1014B000041A8C2000010302061A8C240000000389 -:1014C000041A8C3000010303061A8C340000000358 -:1014D000041A8C4000010304061A8C440000000327 -:1014E000041A8C5000010305061A8C5400000003F6 -:1014F000041A8C6000010306061A8C6400000003C5 -:10150000041A8C7000010307061A8C740000000393 -:10151000041A8C8000010308061A8C840000000362 -:10152000041A8C9000010309061A8C940000000331 -:10153000041A8CA00001030A061A8CA40000000300 -:10154000041A8CB00001030B061A8CB400000003CF -:10155000041A8CC00001030C061A8CC4000000039E -:10156000041A8CD00001030D061A8CD4000000036D -:10157000041A8CE00001030E061A8CE4000000033C -:10158000041A8CF00001030F061A8CF4000000030B -:10159000041A8D0000010310061A8D0400000003D8 -:1015A000041A8D1000010311061A8D1400000003A7 -:1015B000041A8D2000010312061A8D240000000376 -:1015C000041A8D3000010313061A8D340000000345 -:1015D000041A8D4000010314061A8D440000000314 -:1015E000041A8D5000010315061A8D5400000003E3 -:1015F000041A8D6000010316061A8D6400000003B2 -:10160000041A8D7000010317061A8D740000000380 -:10161000041A8D8000010318061A8D84000000034F -:10162000041A8D9000010319061A8D94000000031E -:10163000041A8DA00001031A061A8DA400000003ED -:10164000041A8DB00001031B061A8DB400000003BC -:10165000041A8DC00001031C061A8DC4000000038B -:10166000041A8DD00001031D061A8DD4000000035A -:10167000041A8DE00001031E061A8DE40000000329 -:10168000041A8DF00001031F061A8DF400000003F8 -:10169000041A8E0000010320061A8E0400000003C5 -:1016A000041A8E1000010321061A8E140000000394 -:1016B000041A8E2000010322061A8E240000000363 -:1016C000041A8E3000010323061A8E340000000332 -:1016D000041A8E4000010324061A8E440000000301 -:1016E000041A8E5000010325061A8E5400000003D0 -:1016F000041A8E6000010326061A8E64000000039F -:10170000041A8E7000010327061A8E74000000036D -:10171000041A8E8000010328061A8E84000000033C -:10172000041A8E9000010329061A8E94000000030B -:10173000041A8EA00001032A061A8EA400000003DA -:10174000041A8EB00001032B061A8EB400000003A9 -:10175000041A8EC00001032C061A8EC40000000378 -:10176000041A8ED00001032D061A8ED40000000347 -:10177000041A8EE00001032E061A8EE40000000316 -:10178000041A8EF00001032F061A8EF400000003E5 -:10179000041A8F0000010330061A8F0400000003B2 -:1017A000041A8F1000010331061A8F140000000381 -:1017B000041A8F2000010332061A8F240000000350 -:1017C000041A8F3000010333061A8F34000000031F -:1017D000041A8F4000010334061A8F4400000003EE -:1017E000041A8F5000010335061A8F5400000003BD -:1017F000041A8F6000010336061A8F64000000038C -:10180000041A8F7000010337061A8F74000000035A -:10181000041A8F8000010338061A8F840000000329 -:10182000041A8F9000010339061A8F9400000003F8 -:10183000041A8FA00001033A061A8FA400000003C7 -:10184000041A8FB00001033B061A8FB40000000396 -:10185000041A8FC00001033C061A8FC40000000365 -:10186000041A8FD00001033D061A8FD40000000334 -:10187000041A8FE00001033E061A8FE400000007FF -:10188000041A62C00020033F061AD0000000007254 -:10189000061AD24800000010061AD6B00000002038 -:1018A000061AD47000000090061AD46800000002E6 -:1018B000061AA000000001C4061A30000000001043 -:1018C000061A308000000010061A310000000010D7 -:1018D000061A318000000010061A330000000012C2 -:1018E000061A339000000070061AD4580000000257 -:1018F000061AD34800000002061AD3580000002040 -:10190000061AA710000001C4061A3040000000109B -:10191000061A30C000000010061A31400000001006 -:10192000061A31C000000010061A334800000012E9 -:10193000061A355000000070061AD460000000023C -:10194000061AD35000000002061AD3D80000002067 -:10195000021AAE2000000000061A5000000000022B -:10196000061A508000000012041A40000002035FB3 -:10197000041A63C000020361061A7000000000042C -:10198000061A320000000008021AAE24000000000F -:10199000061A501000000002061A50C8000000127B -:1019A000041A400800020363041A63C800020365B6 -:1019B000061A701000000004061A32200000000809 -:1019C000021AAE2800000000061A50200000000293 -:1019D000061A511000000012041A4010000203679A -:1019E000041A63D000020369061A70200000000484 -:1019F000061A324000000008021AAE2C0000000057 -:101A0000061A503000000002061A51580000001259 -:101A1000041A40180002036B041A63D80002036D15 -:101A2000061A703000000004061A32600000000838 -:101A3000021AAE3000000000061A504000000002FA -:101A4000061A51A000000012041A40200002036F81 -:101A5000041A63E000020371061A704000000004DB -:101A6000061A328000000008021AAE34000000009E -:101A7000061A505000000002061A51E80000001239 -:101A8000041A402800020373041A63E80002037575 -:101A9000061A705000000004061A32A00000000868 -:101AA000021AAE3800000000061A50600000000262 -:101AB000061A523000000012041A40300002037768 -:101AC000041A63F000020379061A70600000000433 -:101AD000061A32C000000008021AAE3C00000000E6 -:101AE000061A507000000002061A52780000001218 -:101AF000041A40380002037B041A63F80002037DD5 -:101B0000061A707000000004061A32E00000000897 -:101B10000200A468000B01C80200A294071D29114D -:101B20000200A298000000000200A29C009C042475 -:101B30000200A2A0000000000200A2A4000002090E -:101B40000200A270000000000200A2740000000069 -:101B50000200A270000000000200A2740000000059 -:101B60000200A270000000000200A2740000000049 -:101B70000200A270000000000200A2740000000039 -:101B8000020160A000000001020160A400000262E6 -:101B9000020160A800000002020160AC0000001811 -:101BA0000201620400000001020100B40000000113 -:101BB000020100B800000001020100DC0000000189 -:101BC0000201010000000001020101040000000107 -:101BD0000201007C003000000201008400000028A7 -:101BE0000201008C0000000002010130000000042E -:101BF0000201025C00000001020103280000000055 -:101C0000020160580000FFFF020160700000000741 -:101C10000201608000000001020105540000003054 -:101C2000020100C400000001020100CC000000011C -:101C3000020100F800000001020100F000000001B4 -:101C4000020100800030000002010088000000282E -:101C500002010090000000000201013400000004B5 -:101C6000020102DC000000010201032C0000000060 -:101C70000201605C0000FFFF0201607400000007C9 -:101C800002016084000000010201056400000030D0 -:101C9000020100C800000001020100D000000001A4 -:101CA000020100FC00000001020100F4000000013C -:101CB000020C100000000028020C20080000021195 -:101CC000020C200C00000200020C20100000020494 -:101CD000020C201C0000FFFF020C20200000FFFF70 -:101CE000020C20240000FFFF020C20280000FFFF50 -:101CF000020C203800000020020C203C00000021D3 -:101D0000020C204000000022020C204400000023AE -:101D1000020C204800000024020C204C000000258A -:101D2000020C205000000026020C20540000002766 -:101D3000020C205800000028020C205C0000002942 -:101D4000020C20600000002A020C20640000002B1E -:101D5000020C20680000002C020C206C0000002DFA -:101D6000020C20700000002E020C20740000002FD6 -:101D7000020C207800000010060C207C00000007F8 -:101D8000020C209800000011020C209C00000012A0 -:101D9000020C20A000000013060C20A40000001D6F -:101DA000020C211800000001020C211C000000019F -:101DB000020C212000000001060C21240000001D5F -:101DC000020C219800000001060C219C0000000775 -:101DD000020C21B800000001020C21BC000000012F -:101DE000020C21C000000001020C21C4000000010F -:101DF000020C21C800000001020C21CC00000001EF -:101E0000020C21D000000001020C21D400000001CE -:101E1000020C21D800000001020C21DC00000001AE -:101E2000020C21E000000001020C21E4000000018E -:101E3000020C21E800000001020C21EC000000016E -:101E4000020C21F000000001020C21F4000000014E -:101E5000020C21F800000001060C21FC0000000724 -:101E6000020C221800000001060C221C00000007D2 -:101E7000020C223807FFFFFF020C223C0000003F4B -:101E8000020C224007FFFFFF020C22440000000F5B -:101E9000010C224800000000010C224C0000000050 -:101EA000010C225000000000010C22540000000030 -:101EB000010C225800000000010C225C0000000010 -:101EC000010C226000000000010C226400000000F0 -:101ED000010C226800000000010C226C00000000D0 -:101EE000010C227000000000010C227400000000B0 -:101EF000010C227800000000010C227C0000000090 -:101F00000C0C2000000003E80A0C20000000000177 -:101F10000B0C20000000000A020C40080000101109 -:101F2000020C400C00001000020C401000001004D5 -:101F3000020C401400001021020C401C0000FFFFA6 -:101F4000020C40200000FFFF020C40240000FFFFB5 -:101F5000020C40280000FFFF020C40380000004641 -:101F6000020C403C00000010060C40400000000243 -:101F7000020C404800000018020C404C000000F029 -:101F8000060C40500000001F020C40CC0000000175 -:101F9000060C40D00000003A020C41B800000001DD -:101FA000060C41BC00000003020C41C80000000107 -:101FB000020C41CC00000001060C41D00000001AC8 -:101FC000020C423807FFFFFF020C423C0000003FBA -:101FD000020C424007FFFFFF020C42440000000FCA -:101FE000010C424800000000010C424C00000000BF -:101FF000010C425000000000010C4254000000009F -:10200000010C425800000000010C425C000000007E -:10201000010C426000000000010C4264000000005E -:10202000010C426800000000010C426C000000003E -:10203000010C427000000000010C4274000000001E -:10204000010C427800000000010C427C00000000FE -:10205000010C4280000000000C0C4000000003E86E -:102060000A0C4000000000010B0C40000000000AB8 -:10207000060D400000000A00020D0044000000327E -:10208000020D008C02150020020D009002150020A8 -:10209000020D009408100000020D009800000033AB -:1020A000020D009C00000002020D00A000000000D4 -:1020B000020D00A400000005020D00A800000005AC -:1020C000060D00AC00000002020D00B4000000028A -:1020D000020D00B800000003020D00BC0000000269 -:1020E000020D00C000000001020D00C80000000247 -:1020F000020D00CC00000002020D015C0000000196 -:10210000020D016400000001020D016800000002E0 -:10211000020D020400000001020D020C000000206C -:10212000020D021000000040020D021400000040E9 -:10213000020D022000000003020D0224000000181E -:10214000060D028000000012040D03000018037F3A -:10215000060D03600000000C020D004C00000001A1 -:10216000020D005000000002020D005400000000AB -:10217000020D005800000008060D005C000000047D -:10218000020D00C400000004020D00040000000164 -:10219000020D000800000001020D000C000000010B -:1021A000020D001000000001020D001400000001EB -:1021B000020D001800000001020D001C00000001CB -:1021C000020D002000000001020D002400000001AB -:1021D000020D002800000001020D002C000000018B -:1021E000020D003000000001020D0034000000016B -:1021F000020D003800000001020D003C000000014B -:10220000020D011400000009020D011C0000000A6B -:10221000020D012400000000020D012C000000004E -:10222000020D013400000000020D013C0000000B13 -:10223000020D014400000000020D011800000029F9 -:10224000020D01200000002A020D012800000020DC -:10225000020D013000000020020D013800000020B6 -:10226000020D01400000002B020D0148000000207B -:10227000020D011400000019020D011C0000001ADB -:10228000020D012400000010020D012C00000010BE -:10229000020D013400000010020D013C0000001B83 -:1022A000020D014400000010020D01180000003969 -:1022B000020D01200000003A020D0128000000304C -:1022C000020D013000000030020D01380000003026 -:1022D000020D01400000003B020D014800000030EB -:1022E000020D011400000049020D011C0000004A0B -:1022F000020D012400000040020D012C00000040EE -:10230000020D013400000040020D013C0000004BB2 -:10231000020D014400000040020D01180000006998 -:10232000020D01200000006A020D0128000000607B -:10233000020D013000000060020D01380000006055 -:10234000020D01400000006B020D0148000000601A -:10235000020D011400000059020D011C0000005A7A -:10236000020D012400000050020D012C000000505D -:10237000020D013400000050020D013C0000005B22 -:10238000020D014400000050020D01180000007908 -:10239000020D01200000007A020D012800000070EB -:1023A000020D013000000070020D013800000070C5 -:1023B000020D01400000007B020D0148000000708A -:1023C000060E200000000800020E004C0000003243 -:1023D000020E009402150020020E00980215002043 -:1023E000020E009C00000030020E00A00810000049 -:1023F000020E00A400000033020E00A8000000300E -:10240000020E00AC00000031020E00B0000000021D -:10241000020E00B400000004020E00B8000000002C -:10242000020E00BC00000002020E00C0000000020C -:10243000020E00C400000000020E00C800000002EE -:10244000020E00CC00000007020E00D000000002C7 -:10245000020E00D400000002020E00D800000001AD -:10246000020E014400000001020E014C00000001B8 -:10247000020E015000000002020E020400000001E2 -:10248000020E020C00000040020E0210000000408C -:10249000020E021C00000004020E022000000020B8 -:1024A000020E02240000000E020E02280000001B93 -:1024B000060E030000000012040E0280001B0397AA -:1024C000060E02EC00000005020E00540000000C95 -:1024D000020E00580000000C020E005C000000001C -:1024E000020E006000000010020E006400000010E8 -:1024F000060E006800000003020E00DC000000036E -:10250000020E000400000001020E0008000000019D -:10251000020E000C00000001020E0010000000017D -:10252000020E001400000001020E0018000000015D -:10253000020E001C00000001020E0020000000013D -:10254000020E002400000001020E0028000000011D -:10255000020E002C00000001020E003000000001FD -:10256000020E003400000001020E003800000001DD -:10257000020E003C00000001020E004000000001BD -:10258000020E004400000001020E01100000000FC6 -:10259000020E011800000000020E012000000000E1 -:1025A000020E012800000000020E01140000002F9E -:1025B000020E011C00000020020E01240000000099 -:1025C000020E012C00000000020E01100000001F8E -:1025D000020E011800000010020E01200000000091 -:1025E000020E012800000000020E01140000003F4E -:1025F000020E011C00000030020E01240000000049 -:10260000020E012C00000000020E01100000004F1D -:10261000020E011800000040020E01200000000020 -:10262000020E012800000000020E01140000006FDD -:10263000020E011C00000060020E012400000000D8 -:10264000020E012C00000000020E01100000005FCD -:10265000020E011800000050020E012000000000D0 -:10266000020E012800000000020E01140000007F8D -:10267000020E011C00000070020E01240000000088 -:10268000020E012C000000000730040000C9000009 -:10269000083007D8000503B20734000033320000C9 -:1026A0000734800030A70CCD07350000353518F70A -:1026B000073580002A6226450736000018D330DE31 -:1026C00008364660373403B40130000000000000D3 -:1026D000013000040000000001300008000000008C -:1026E0000130000C0000000001300010000000006C -:1026F0000130001400000000023000200000000142 -:102700000230002400000002023000280000000314 -:102710000230002C000000000230003000000004F5 -:1027200002300034000000010230003800000000D8 -:102730000230003C000000010230004000000004B4 -:102740000230004400000000023000480000000198 -:102750000230004C00000003023000500000000076 -:102760000230005400000001023000580000000454 -:102770000230005C00000000023000600000000138 -:102780000230006400000003023000680000000016 -:102790000230006C000000010230007000000004F4 -:1027A00002300074000000000230007800000004D5 -:1027B0000230007C000000030630008000000002B0 -:1027C000023000A400003FFF023000A8000003FF19 -:1027D0000230022400000000023002340000000039 -:1027E0000230024C00000000023002E40000FFFF53 -:1027F000063020000000080002338BC000000001FA -:10280000023380000000001A023380400000004EB6 -:102810000233808000000010023380C000000020DE -:102820000C3383000007A1200A3383000000013825 -:102830000B338300000013880A338340000000003C -:102840000C338340000001F40B338340000000058B -:10285000023383800007A120023383C0000001F40B -:1028600002331480000000010A33148000000000CD -:10287000063280000000010206322008000000C875 -:10288000063220000000000204328EA0001003B6C1 -:1028900006323EB00000000606323ED800000002BC -:1028A00006323E800000000A04323EA8000203C641 -:1028B00006323E00000000200632500000000400F6 -:1028C0000632400000000004043274C0000203C855 -:1028D00006324110000000020632D0000000003035 -:1028E0000632DD40000000440632DA00000000D06D -:1028F0000632DEA0000000020632E0000000080000 -:1029000006328450000001180632100000000188D1 -:102910000632500000000020063251000000002066 -:102920000632520000000020063253000000002052 -:10293000063254000000002006325500000000203E -:10294000063256000000002006325700000000202A -:102950000632580000000020063259000000002016 -:1029600006325A000000002006325B000000002002 -:1029700006325C000000002006325D0000000020EE -:1029800006325E000000002006325F0000000020DA -:1029900006328DF00000000204328E00000203CAED -:1029A00006328E08000000020632DE9000000002AF -:1029B00006321C4000000038063288B000000118C2 -:1029C00006321620000001880632508000000020E8 -:1029D00006325180000000200632528000000020A4 -:1029E0000632538000000020063254800000002090 -:1029F000063255800000002006325680000000207C -:102A00000632578000000020063258800000002067 -:102A1000063259800000002006325A800000002053 -:102A200006325B800000002006325C80000000203F -:102A300006325D800000002006325E80000000202B -:102A400006325F800000002006328DF80000000290 -:102A500004328E10000203CC06328E1800000002F1 -:102A60000632DE980000000206321D200000003809 -:102A700002328D50000000000632401000000002BB -:102A800002328D5400000000063240200000000297 -:102A900002328D5800000000063240300000000273 -:102AA00002328D5C0000000006324040000000024F -:102AB00002328D600000000006324050000000022B -:102AC00002328D6400000000063240600000000207 -:102AD00002328D68000000000632407000000002E3 -:102AE00002328D6C000000000632408000000002BF -:102AF000072004000091000008200780001003CE8A -:102B0000072400002AF300000724800015090ABDED -:102B10000824A9F0692803D001200000000000006B -:102B20000120000400000000012000080000000057 -:102B30000120000C00000000012000100000000037 -:102B4000012000140000000002200020000000010D -:102B500002200024000000020220002800000003E0 -:102B60000220002C000000000220003000000004C1 -:102B700002200034000000010220003800000000A4 -:102B80000220003C00000001022000400000000480 -:102B90000220004400000000022000480000000164 -:102BA0000220004C00000003022000500000000042 -:102BB0000220005400000001022000580000000420 -:102BC0000220005C00000000022000600000000104 -:102BD00002200064000000030220006800000000E2 -:102BE0000220006C000000010220007000000004C0 -:102BF00002200074000000000220007800000004A1 -:102C00000220007C0000000306200080000000027B -:102C1000022000A400003FFF022000A8000003FFE4 -:102C20000220022400000000022002340000000004 -:102C30000220024C00000000022002E40000FFFF1E -:102C4000062020000000080002238BC000000001C5 -:102C500002238000000000100223804000000012C8 -:102C60000223808000000030022380C00000000E9C -:102C70000C2383000007A1200A23830000000138F1 -:102C80000B238300000013880A2383400000000008 -:102C90000C238340000001F40B2383400000000557 -:102CA000022383800007A120022383C0000001F4D7 -:102CB00002231480000000010A2314800000000099 -:102CC000062210000000004206222008000000C872 -:102CD00006222000000000020622B000000000C60C -:102CE0000422B318000503D20622B32C0000000B07 -:102CF0000422B358000503D70622B36C0000000B72 -:102D00000422B398000503DC0622B3AC0000000BDC -:102D10000422B3D8000503E10622B3EC0000000B47 -:102D20000422B418000503E60622B42C0000000BB0 -:102D30000422B458000503EB0622B46C0000000B1B -:102D40000422B498000503F00622B4AC0000000B86 -:102D50000422B4D8000503F50622B4EC0000000BF1 -:102D60000422B518000503FA0622B52C0000000B5A -:102D70000422B558000503FF0622B56C0000000BC5 -:102D80000422B598000504040622B5AC0000000B2F -:102D90000422B5D8000504090622B5EC0000000B9A -:102DA0000422B6180005040E0622B62C0000000B03 -:102DB0000422B658000504130622B66C0000000B6E -:102DC0000422B698000504180622B6AC0000000BD9 -:102DD0000422B6D80005041D0622B6EC0000000B44 -:102DE0000422B718000504220622B72C0000000BAD -:102DF0000422B758000504270622B76C0000000B18 -:102E00000422B7980005042C0622B7AC0000000B82 -:102E10000422B7D8000504310622B7EC0000000BED -:102E20000422B818000504360622B82C0000000B56 -:102E30000422B8580005043B0622B86C0000000BC1 -:102E40000422B898000504400622B8AC0000000B2C -:102E50000422B8D8000504450622B8EC0000000B97 -:102E60000422B9180005044A0622B92C0000000B00 -:102E70000422B9580005044F0622B96C0000000B6B -:102E80000422B998000504540622B9AC0000000BD6 -:102E90000422B9D8000504590622B9EC0000000B41 -:102EA0000422BA180005045E0622BA2C0000000BAA -:102EB0000422BA58000504630622BA6C0000000B15 -:102EC0000422BA98000504680622BAAC0000000B80 -:102ED0000422BAD80005046D0622BAEC00000005F1 -:102EE0000622BB00000000530422BC4C0001047207 -:102EF0000622BC50000000030422BC5C00010473E5 -:102F00000622BC60000000030422BC6C00010474B3 -:102F10000622BC70000000030422BC7C0001047582 -:102F20000622BC80000000030422BC8C0001047651 -:102F30000622BC90000000030422BC9C0001047720 -:102F40000622BCA0000000030422BCAC00010478EF -:102F50000622BCB0000000030422BCBC00010479BE -:102F60000622880000000100062280000000020006 -:102F7000042212700010047A06223000000000C003 -:102F800006226700000001000622900000000400F5 -:102F900004226B080020048A022212C0FFFFFFFFF8 -:102FA000062211E800000002062212C800000009F3 -:102FB000062212EC0000000906228C000000000826 -:102FC0000222114800000000062213200000000623 -:102FD000062233000000000206226040000000309C -:102FE00006228C20000000080222114C0000000084 -:102FF00006221338000000060622330800000002F3 -:10300000062261000000003006228C40000000080B -:10301000022211500000000006221350000000069A -:103020000622331000000002062261C000000030BA -:1030300006228C60000000080222115400000000EB -:103040000622136800000006062233180000000262 -:10305000062262800000003006228C8000000008FA -:103060000222115800000000062213800000000612 -:1030700006223320000000020622634000000030D8 -:1030800006228CA0000000080222115C0000000053 -:1030900006221398000000060622332800000002D2 -:1030A000062264000000003006228CC000000008E8 -:1030B0000222116000000000062213B0000000068A -:1030C0000622333000000002062264C000000030F7 -:1030D00006228CE0000000080222116400000000BB -:1030E000062213C800000006062233380000000242 -:1030F0000622658000000030021610000000002843 -:1031000002170008000000020217002C0000000354 -:103110000217003C000000040217004800000002F3 -:103120000217004C000000900217005000000090B1 -:103130000217005400800090021700580810000089 -:10314000021700600000008A02170064000000807F -:1031500002170068000000810217006C0000008068 -:10316000021700700000000602170078000007D068 -:103170000217007C0000076C02170038007C100466 -:10318000021700040000000F061640240000000291 -:10319000021640700000001C0216420800000001E8 -:1031A0000216421000000001021642200000000139 -:1031B0000216422800000001021642300000000101 -:1031C00002164238000000010216426000000002B0 -:1031D0000C16401C0003D0900A16401C0000009CF6 -:1031E0000B16401C000009C4021640300000000805 -:1031F000021640340000000C021640380000001097 -:1032000002164044000000200216400000000001A9 -:10321000021640D80000000102164008000000011C -:103220000216400C000000010216401000000001D0 -:103230000216424000000000021642480000000052 -:103240000616427000000002021642500000000004 -:1032500002164258000000000616428000000002DC -:1032600002166008000012240216600C0000121002 -:1032700002166010000012140216601C0000FFFF0E -:10328000021660200000FFFF021660240000FFFF0E -:10329000021660280000FFFF0216603800000020C0 -:1032A0000216603C0000002006166040000000028C -:1032B00002166048000000230216604C0000002443 -:1032C000021660500000002502166054000000261F -:1032D00002166058000000270216605C00000029FA -:1032E000021660600000002A021660640000002BD5 -:1032F000021660680000002C0216606C0000002DB1 -:1033000002166070000000EC0216607400000011EC -:1033100002166078000000120616607C0000000FA4 -:10332000021660B800000001021660BC0000000137 -:10333000061660C00000000C021660F000000001DC -:10334000061660F400000031021661B800000001AA -:10335000061661BC0000000D021661F000000001BD -:10336000061661F4000000110216623807FFFFFF25 -:103370000216623C0000003F0216624007FFFFFF9A -:10338000021662440000000F0116624800000000AF -:103390000116624C0000000001166250000000009F -:1033A000011662540000000001166258000000007F -:1033B0000116625C0000000001166260000000005F -:1033C000011662640000000001166268000000003F -:1033D0000116626C0000000001166270000000001F -:1033E00001166274000000000116627800000000FF -:1033F0000116627C000000000C166000000003E86B -:103400000A166000000000010B1660000000000AB0 -:1034100002168040000000060216804400000005ED -:10342000021680480000000A0216804C00000005C9 -:103430000216805400000002021680CC0000000436 -:10344000021680D000000004021680D400000004A0 -:10345000021680D800000004021680DC0000000480 -:10346000021680E000000004021680E40000000460 -:10347000021680E800000004021688040000000420 -:10348000021680300000007C021680340000003DEF -:10349000021680380000003F0216803C0000009CAD -:1034A000021680F000000007061680F400000005F8 -:1034B0000216880C010101010216810800000000BB -:1034C0000216810C000000040216811000000004A6 -:1034D0000216811400000002021688100801200460 -:1034E00002168118000000050216811C000000056C -:1034F000021681200000000502168124000000054C -:103500000216882C200810010216812800000008ED -:103510000216812C00000006021681300000000710 -:1035200002168134000000000216883001010120DB -:1035300006168138000000040216883401010101DA -:1035400002168148000000000216814C00000004B1 -:10355000021681500000000402168154000000028F -:103560000216883808012004021681580000000560 -:103570000216815C00000005021681600000000553 -:1035800002168164000000050216883C2008100124 -:1035900002168168000000080216816C0000000617 -:1035A00002168170000000070216817400000001FD -:1035B00002168840010101200216817800000001F6 -:1035C0000216817C000000010216818000000001CB -:1035D00002168184000000010216884401010101E5 -:1035E00002168188000000010216818C0000000490 -:1035F000021681900000000402168194000000026F -:10360000021688480801200402168198000000056F -:103610000216819C00000005021681A00000000532 -:10362000021681A40000000502168814200810016B -:10363000021681A800000008021681AC00000006F6 -:10364000021681B000000007021681B400000001DC -:103650000216881801010120021681B8000000013D -:10366000021681BC00000001021681C000000001AA -:10367000021681C4000000010216881C010101012C -:10368000021681C800000001021681CC000000046F -:10369000021681D000000004021681D4000000024E -:1036A0000216882008012004021681D800000005B7 -:1036B000021681DC00000005021681E00000000512 -:1036C000021681E40000000502168824200810017B -:1036D000021681E800000008021681EC00000006D6 -:1036E000021681F0000000070216E40C0000000042 -:1036F00002168828010101200616E41000000004CB -:103700000216E000010101010216E42000000000A1 -:103710000216E424000000040216E428000000045D -:103720000216E42C000000020216E0040801200446 -:103730000216E430000000050216E4340000000523 -:103740000216E438000000050216E43C0000000503 -:103750000216E008200810010216E44000000008EC -:103760000216E444000000060216E44800000007C8 -:103770000216E44C000000000216E00C01010120DA -:103780000616E450000000040216E01001010101D9 -:103790000216E460000000000216E4640000000469 -:1037A0000216E468000000040216E46C0000000247 -:1037B0000216E014080120040216E470000000055F -:1037C0000216E474000000050216E478000000050B -:1037D0000216E47C000000050216E0182008100123 -:1037E0000216E480000000080216E48400000006CF -:1037F0000216E488000000070216E48C00000001B5 -:103800000216E01C010101200216E49000000001F4 -:103810000216E494000000010216E4980000000182 -:103820000216E49C000000010216E02001010101E3 -:103830000216E4A0000000010216E4A40000000447 -:103840000216E4A8000000040216E4AC0000000226 -:103850000216E024080120040216E4B0000000056E -:103860000216E4B4000000050216E4B800000005EA -:103870000216E4BC000000050216E0282008100132 -:103880000216E4C0000000080216E4C400000006AE -:103890000216E4C8000000070216E4CC0000000194 -:1038A0000216E02C010101200216E4D00000000104 -:1038B0000216E4D4000000010216E4D80000000162 -:1038C0000216E4DC000000010216E03001010101F3 -:1038D0000216E4E0000000010216E4E40000000427 -:1038E0000216E4E8000000040216E4EC0000000206 -:1038F0000216E034080120040216E4F0000000057E -:103900000216E4F4000000050216E4F800000005C9 -:103910000216E4FC000000050216E0382008100141 -:103920000216E500000000080216E504000000068B -:103930000216E508000000070216E03C0101012024 -:1039400002168240003F003F021682440000000041 -:103950000216E524003F003F0216E52800000000A3 -:1039600002168248000000000216824C003F003F11 -:103970000216E52C000000000216E530003F003F73 -:10398000021682500100010002168254010001005B -:103990000216E534010001000216E53801000100BD -:1039A00006168258000000020216E53C00000000E6 -:1039B0000216E540000000000216826000C000C050 -:1039C0000216826400C000C00216E54400C000C0B8 -:1039D0000216E54800C000C0021682681E001E00E4 -:1039E0000216826C1E001E000216E54C1E001E0010 -:1039F0000216E5501E001E000216827040004000B4 -:103A000002168274400040000216E5544000400057 -:103A10000216E558400040000216827880008000BF -:103A20000216827C800080000216E55C8000800027 -:103A30000216E560800080000216828020002000CF -:103A400002168284200020000216E5642000200077 -:103A50000216E56820002000061682880000000299 -:103A60000216E56C000000000216E5700000000080 -:103A700002168290000000000216829400000000EE -:103A80000216E574000000000216E5780000000050 -:103A900002168298000000000216829C00000000BE -:103AA0000216E57C000000000216E5800000000020 -:103AB000021682A000000000021682A4000000018D -:103AC000061682A80000000A021681F400000C0805 -:103AD000021681F800000040021681FC000001007F -:103AE0000216820000000020021682040000001767 -:103AF00002168208000000800216820C00000200FC -:103B000002168210000000000216821801FF01FF59 -:103B10000216821401FF01FF0216E51001FF01FFEA -:103B20000216E50C01FF01FF0216823C00000013A3 -:103B3000021680900000013F0216806000000140E4 -:103B40000216806400000140061680680000000232 -:103B500002168070000000C0061680740000000786 -:103B60000216809C00000048021680A00000004859 -:103B7000061680A400000002021680AC0000004877 -:103B8000061680B000000007021682380000800090 -:103B900002168234000025E40216809400007FFFA4 -:103BA00002168220000F000F0216821C000F000F69 -:103BB0000216E518000F000F0216E514000F000FA3 -:103BC000021682280000000002168224FFFFFFFF79 -:103BD0000216E520000000000216E51CFFFFFFFFB3 -:103BE0000216E6BC000000000216E6C0000000025B -:103BF0000216E6C4000000010216E6C80000000339 -:103C00000216E6CC000000040216E6D00000000612 -:103C10000216E6D4000000050216E6D800000007F0 -:103C2000021680EC000000FF0214000000000001FA -:103C30000214000C0000000102140040000000010A -:103C40000214004400007FFF0214000C000000007A -:103C500002140000000000000214006C00000000CC -:103C600002140004000000010214003000000001F2 -:103C700002140004000000000214005C00000000B8 -:103C800002140008000000010214003400000001CA -:103C90000214000800000000021400600000000090 -:103CA00006028000000020000202005800000032DE -:103CB000020200A003150020020200A40315002048 -:103CC000020200A801000030020200AC081000004F -:103CD000020200B000000033020200B40000003015 -:103CE000020200B800000031020200BC0000000324 -:103CF000020200C000000006020200C4000000032F -:103D0000020200C800000003020200CC0000000212 -:103D1000020200D000000000020200D400000002F5 -:103D2000020200DC00000000020200E000000006C9 -:103D3000020200E400000004020200E800000002A9 -:103D4000020200EC00000002020200F0000000018C -:103D5000020200FC00000006020201200000000038 -:103D60000202013400000002020201B00000000162 -:103D70000202020C00000001020202140000000115 -:103D80000202021800000002020204040000000106 -:103D90000202040C00000040020204100000004077 -:103DA0000202041C000000040202042000000020A3 -:103DB0000202042400000002020204280000002085 -:103DC000060205000000001204020480002004AA7C -:103DD000020200600000000F020200640000000701 -:103DE00002020068000000000202006C0000000EE9 -:103DF000020200700000000E0602007400000003C2 -:103E0000020200F4000000040202000400000001AD -:103E100002020008000000010202000C0000000184 -:103E20000202001000000001020200140000000164 -:103E300002020018000000010202001C0000000144 -:103E40000202002000000001020200240000000124 -:103E500002020028000000010202002C0000000104 -:103E600002020030000000010202003400000001E4 -:103E700002020038000000010202003C00000001C4 -:103E800002020040000000010202004400000001A4 -:103E900002020048000000010202004C0000000184 -:103EA000020200500000000102020108000000C8E8 -:103EB0000202011800000002020201C4000000001A -:103EC000020201CC00000000020201D40000000246 -:103ED000020201DC00000002020201E4000000FF17 -:103EE000020201EC000000FF0202010000000000DD -:103EF0000202010C000000C80202011C00000002C6 -:103F0000020201C800000000020201D0000000000F -:103F1000020201D800000002020201E000000002DB -:103F2000020201E8000000FF020201F0000000FFB1 -:103F3000020201040000000002020108000000C8A3 -:103F40000202011800000002020201C40000000089 -:103F5000020201CC00000000020201D400000002B5 -:103F6000020201DC00000002020201E4000000FF86 -:103F7000020201EC000000FF02020100000000004C -:103F80000202010C000000C80202011C0000000235 -:103F9000020201C800000000020201D0000000007F -:103FA000020201D800000002020201E0000000024B -:103FB000020201E8000000FF020201F0000000FF21 -:103FC000020201040000000002020108000000C813 -:103FD0000202011800000002020201C400000000F9 -:103FE000020201CC00000000020201D40000000225 -:103FF000020201DC00000002020201E4000000FFF6 -:10400000020201EC000000FF0202010000000000BB -:104010000202010C000000C80202011C00000002A4 -:10402000020201C800000000020201D000000000EE -:10403000020201D800000002020201E000000002BA -:10404000020201E8000000FF020201F0000000FF90 -:10405000020201040000000002020108000000C882 -:104060000202011800000002020201C40000000068 -:10407000020201CC00000000020201D40000000294 -:10408000020201DC00000002020201E4000000FF65 -:10409000020201EC000000FF02020100000000002B -:1040A0000202010C000000C80202011C0000000214 -:1040B000020201C800000000020201D0000000005E -:1040C000020201D800000002020201E0000000022A -:1040D000020201E8000000FF020201F0000000FF00 -:1040E00002020104000000000728040000A00000F4 -:1040F000082807B8000904CA072C000034DA0000B9 -:10410000072C800038F80D37072D000037B91B76D3 -:10411000072D800031782965072E00001C7A35C4F0 -:10412000082E48E036E404CC01280000000000001E -:104130000128000400000000012800080000000021 -:104140000128000C00000000012800100000000001 -:1041500001280014000000000228002000000001D7 -:1041600002280024000000020228002800000003AA -:104170000228002C0000000002280030000000048B -:10418000022800340000000102280038000000006E -:104190000228003C0000000102280040000000044A -:1041A000022800440000000002280048000000012E -:1041B0000228004C0000000302280050000000000C -:1041C00002280054000000010228005800000004EA -:1041D0000228005C000000000228006000000001CE -:1041E00002280064000000030228006800000000AC -:1041F0000228006C0000000102280070000000048A -:10420000022800740000000002280078000000046A -:104210000228007C00000003062800800000000245 -:10422000022800A400003FFF022800A8000003FFAE -:1042300002280224000000000228023400000000CE -:104240000228024C00000000022802E40000FFFFE8 -:104250000628200000000800022B8BC0000000018F -:10426000022B800000000000022B8040000000189C -:10427000022B80800000000C022B80C00000006632 -:104280000C2B83000007A1200A2B830000000138BB -:104290000B2B8300000013880A2B834000000000D2 -:1042A0000C2B8340000001F40B2B83400000000521 -:1042B000022B83800007A120022B83C0000001F4A1 -:1042C000022B1480000000010A2B14800000000063 -:1042D000062A9AF800000004042A9B08000204CE73 -:1042E000062A9B1000000006062A90800000004865 -:1042F000062A2008000000C8062A2000000000024C -:10430000062A91A800000086062A900000000020DE -:10431000062A93C800000003042A93D4000104D0A5 -:10432000062A9DA800000002042A9498000404D1E3 -:10433000042A9D58000104D5062A9D5C0000001146 -:10434000042ACB20001004D6042A3000000204E620 -:10435000062A300800000100062A40400000001034 -:10436000042A4000001004E8042A8408000204F82B -:10437000062A9DA000000002062AB000000000509E -:10438000062ABB7000000070062AB150000000022F -:10439000062ABB6000000004062AD00000000800C6 -:1043A000062AC00000000150062A94A8000000322E -:1043B000062A502000000002062A503000000002A9 -:1043C000062A500000000002062A501000000002D9 -:1043D000022A520800000001042A9B28000204FA65 -:1043E000062A963800000022042A96C0000104FC28 -:1043F000062A96C400000003062A976800000022DF -:10440000042A97F0000104FD062A97F40000000337 -:10441000062A989800000022042A9920000104FE30 -:10442000062A992400000003062A99C800000022E9 -:10443000042A9A50000104FF062A9A54000000033F -:10444000062AB14000000002062AC54000000150C3 -:10445000062A957000000032062A5028000000024B -:10446000062A503800000002062A50080000000208 -:10447000062A501800000002022A520C0000000117 -:10448000042A9B3000020500062A96D00000002274 -:10449000042A975800010502062A975C00000003D1 -:1044A000062A980000000022042A988800010503CB -:1044B000062A988C00000003062A9930000000228A -:1044C000042A99B800010504062A99BC00000003DB -:1044D000062A9A6000000022042A9AE800010505D5 -:1044E000062A9AEC00000003062AB14800000002E8 -:1044F000022ACA8000000000042A9B38001005062A -:10450000062A50480000000E022ACA84000000005B -:10451000042A9B7800100516062A50800000000E21 -:10452000022ACA8800000000042A9BB80010052651 -:10453000062A50B80000000E022ACA8C00000000B3 -:10454000042A9BF800100536062A50F00000000EE1 -:10455000022ACA9000000000042A9C380010054678 -:10456000062A51280000000E022ACA94000000000A -:10457000042A9C7800100556062A51600000000E9F -:10458000022ACA9800000000042A9CB800100566A0 -:10459000062A51980000000E022ACA9C0000000062 -:1045A000042A9CF800100576062A51D00000000E5F -:1045B000021010080000000102101050000000015D -:1045C000021010000003D000021010040000003D93 -:1045D0000910180002000586091011000010078656 -:1045E0000610114000000008091011600010079625 -:1045F000061011A00000001806102400000000E0C2 -:104600000210201C00000000021020200000000109 -:10461000021020C00000000202102004000000016F -:10462000021020080000000109103C00000507A648 -:1046300009103800000507AB09103820000507B045 -:1046400006104C000000010002104028000000107D -:104650000210404400003FFF0210405800280000B4 -:10466000021040840084924A02104058000000006A -:104670000210800000001080021080AC00000000DA -:1046800002108038000000100210810000000000BD -:10469000061081200000000202108008000002B510 -:1046A0000210801000000000061082000000004A86 -:1046B000021081080001FFFF061081400000000287 -:1046C0000210800000001A800610900000000024F4 -:1046D000061091200000004A061093700000004A66 -:1046E000061095C00000004A0210800400001080EF -:1046F000021080B0000000010210803C0000001099 -:104700000210810400000000061081280000000251 -:104710000210800C000002B502108014000000009E -:10472000061084000000004A0210810C0001FFFF07 -:1047300006108148000000020210800400001A8068 -:104740000610909000000024061092480000004AD5 -:10475000061094980000004A061096E80000004AEF -:104760000210800000001080021080AC00000002E7 -:1047700002108038000000100210810000000000CC -:10478000061081200000000202108008000002B51F -:104790000210801000000000061082000000004A95 -:1047A000021081080001FFFF061081400000000296 -:1047B0000210800000001A80061090000000002403 -:1047C000061091200000004A061093700000004A75 -:1047D000061095C00000004A0210800400001080FE -:1047E000021080B0000000030210803C00000010A6 -:1047F0000210810400000000061081280000000261 -:104800000210800C000002B50210801400000000AD -:10481000061084000000004A0210810C0001FFFF16 -:1048200006108148000000020210800400001A8077 -:104830000610909000000024061092480000004AE4 -:10484000061094980000004A061096E80000004AFE -:104850000210800000001080021080AC00000004F4 -:1048600002108038000000100210810000000000DB -:10487000061081200000000202108008000002B52E -:104880000210801000000000061082000000004AA4 -:10489000021081080001FFFF0610814000000002A5 -:1048A0000210800000001A80061090000000002412 -:1048B000061091200000004A061093700000004A84 -:1048C000061095C00000004A02108004000010800D -:1048D000021080B0000000050210803C00000010B3 -:1048E0000210810400000000061081280000000270 -:1048F0000210800C000002B50210801400000000BD -:10490000061084000000004A0210810C0001FFFF25 -:1049100006108148000000020210800400001A8086 -:104920000610909000000024061092480000004AF3 -:10493000061094980000004A061096E80000004A0D -:104940000210800000001080021080AC0000000601 -:1049500002108038000000100210810000000000EA -:10496000061081200000000202108008000002B53D -:104970000210801000000000061082000000004AB3 -:10498000021081080001FFFF0610814000000002B4 -:104990000210800000001A80061090000000002421 -:1049A000061091200000004A061093700000004A93 -:1049B000061095C00000004A02108004000010801C -:1049C000021080B0000000070210803C00000010C0 -:1049D000021081040000000006108128000000027F -:1049E0000210800C000002B50210801400000000CC -:1049F000061084000000004A0210810C0001FFFF35 -:104A000006108148000000020210800400001A8095 -:104A10000610909000000024061092480000004A02 -:104A2000061094980000004A061096E80000004A1C -:104A3000021205B0000000010212049000E383405E -:104A40000212051400003C100212066C0000000166 -:104A5000021206700000000002120494FFFFFFFF24 -:104A600002120498FFFFFFFF0212049CFFFFFFFFEA -:104A7000021204A0FFFFFFFF021204A4FFFFFFFFCA -:104A8000021204A8FFFFFFFF021204ACFFFFFFFFAA -:104A9000021204B0FFFFFFFF021204BCFFFFFFFF82 -:104AA000021204C0FFFFFFFF021204C4FFFFFFFF5A -:104AB000021204C8FFFFFFFF021204CCFFFFFFFF3A -:104AC000021204D0FFFFFFFF021204D8FFFFFFFF16 -:104AD000021204DCFFFFFFFF021204E0FFFFFFFFF2 -:104AE000021204E4FFFFFFFF021204E8FFFFFFFFD2 -:104AF000021204ECFFFFFFFF021204F0FFFFFFFFB2 -:104B0000021204F4FFFFFFFF021204F8FFFFFFFF91 -:104B1000021204FCFFFFFFFF02120500FFFFFFFF70 -:104B200002120504FFFFFFFF02120508FFFFFFFF4F -:104B30000212050CFFFFFFFF02120510FFFFFFFF2F -:104B4000021204D4FF809000021204B4F00050005E -:104B5000021204B8F00010000212039000000008D6 -:104B60000212039C00000008021203A000000008CB -:104B7000021203A400000002021203BC00000004A1 -:104B8000021203C000000005021203C4000000046A -:104B9000021203D0000000000212036C00000001AA -:104BA000021203680000003F021201BC0000004036 -:104BB000021201C000001808021201C4000008031C -:104BC000021201C800000803021201CC00000040DC -:104BD000021201D000000003021201D400000803F9 -:104BE000021201D800000803021201DC00000803D1 -:104BF000021201E000010003021201E400000803B8 -:104C0000021201E800000803021201EC0000000398 -:104C1000021201F000000003021201F40000000380 -:104C2000021201F800000003021201FC0000000360 -:104C3000021202000000000302120204000000033E -:104C400002120208000000030212020C000000031E -:104C500002120210000000030212021400000003FE -:104C600002120218000000030212021C00000003DE -:104C700002120220000000030212022400000003BE -:104C800002120228000024030212022C0000002F4E -:104C90000212023000000009021202340000001962 -:104CA00002120238000001840212023C000001835B -:104CB0000212024000000306021202440000001922 -:104CC00002120248000000060212024C0000030615 -:104CD00002120250000003060212025400000306F2 -:104CE0000212025800000C860212025C0000030649 -:104CF00002120260000003060212026400000006B5 -:104D000002120268000000060212026C0000000697 -:104D10000212027000000006021202740000000677 -:104D200002120278000000060212027C0000000657 -:104D30000212028000000006021202840000000637 -:104D400002120288000000060212028C0000000617 -:104D500002120290000000060212029400000006F7 -:104D600002120298000000060212029C00000006D7 -:104D7000021202A000000306021202A400000013A7 -:104D8000021202A800000006021202B00000100485 -:104D9000021202B400001004021203240010644046 -:104DA0000212032800106440021205B40000000142 -:104DB000021201B0000000010600A0000000000C7B -:104DC0000200A050000000000200A05400000000FB -:104DD0000200A0EC555400000200A0F055555555B6 -:104DE0000200A0F4000055550200A0F8F0000000F9 -:104DF0000200A0FC555400000200A1005555555575 -:104E00000200A104000055550200A108F0000000B6 -:104E10000200A18C555400000200A1905555555533 -:104E20000200A194000055550200A198F000000076 -:104E30000200A19C000000000200A1A000010000EF -:104E40000200A1A4000050140200A1A8000000006C -:104E50000200A45C00000C000200A61C000000037D -:104E60000200A06CFF5C00000200A070FFF55FFF75 -:104E70000200A0740000FFFF0200A078F00003E031 -:104E80000200A07C000000000200A0800000A00042 -:104E90000600A084000000050200A0980FE00000BA -:104EA0000600A09C000000070200A0B8000004005B -:104EB0000600A0BC000000030200A0C80000100013 -:104EC0000600A0CC000000030200A0D800004000B3 -:104ED0000600A0DC000000030200A0E800010000C2 -:104EE0000600A22C000000040200A10CFF5C0000E0 -:104EF0000200A110FFF55FFF0200A1140000FFFFF8 -:104F00000200A118F00003E00200A11C0000000054 -:104F10000200A1200000A0000600A124000000055E -:104F20000200A1380FE000000600A13C00000007CD -:104F30000200A158000008000600A15C0000000368 -:104F40000200A168000020000600A16C0000000320 -:104F50000200A178000080000600A17C0000000390 -:104F60000200A188000200000600A23C000000042C -:104F70000200A030000000000200A0340000000089 -:104F80000200A038000000000200A03C0000000069 -:104F90000200A040000000000200A0440000000049 -:104FA0000200A048000000000200A04C0000000029 -:104FB00000000000000000000000003000000000C1 -:104FC00000000000000000000000000000000000E1 -:104FD00000000000000000000000000000000000D1 -:104FE0000000000000300031000000000000000060 -:104FF00000000000000000000000000000000000B1 -:1050000000000000000000000000000000000000A0 -:10501000003100520000000000000000000000000D -:105020000000000000000000000000000000000080 -:105030000000000000000000000000000052008995 -:1050400000000000000000000089008D008D00912C -:1050500000910095009500990099009D009D00A188 -:1050600000A100A500A500A900A900AE00AE00B1F6 -:1050700000B100B4000000000000000000000000CB -:105080000000000000000000000000000000000020 -:105090000000000000B40309030903130313031DF8 -:1050A000031D03240324032B032B03320332033990 -:1050B00003390340034003470347034E034E0355A0 -:1050C00000000000000000000000000000000000E0 -:1050D00000000000000000000000000000000000D0 -:1050E00000000000000000000000000000000000C0 -:1050F00000000000000000000000000000000000B0 -:10510000000000000000000000000000000000009F -:10511000000000000000000000000000000000008F -:10512000000000000000000000000000000000007F -:10513000000000000000000000000000000000006F -:10514000000000000000000000000000000000005F -:10515000000000000000000000000000000000004F -:10516000000000000000000000000000000000003F -:105170000355035B0000000000000000035B035CBC -:10518000035C035D035D035E035E035F035F036017 -:1051900003600361036103620362036300000000B4 -:1051A00000000000000000000000000000000000FF -:1051B00000000000000000000000000000000000EF -:1051C00000000000000000000363036D036D037B1B -:1051D000037B0389000000000000000000000000C5 -:1051E00000000000000000000000000000000000BF -:1051F00000000000000000000000000000000000AF -:10520000000000000000000000000000000000009E -:10521000000000000000000000000000000000008E -:105220000389038A00000000000000000000000065 -:10523000000000000000000000000000000000006E -:10524000000000000000000000000000038A03D6F8 -:10525000000000000000000000000000000000004E -:10526000000000000000000000000000000000003E -:10527000000000000000000003D604010000000050 -:10528000000000000000000000000000000000001E -:10529000000000000000000000000000000000000E -:1052A00000000000040104330000000000000000C2 -:1052B0000433043A043A0441044104480448044FC6 -:1052C000044F04560456045D045D04640464046BD6 -:1052D000046B04A4000000000000000004A404A863 -:1052E00004A804AC04AC04B004B004B404B404B81E -:1052F00004B804BC04BC04C004C004C404C4051342 -:105300000513052A052A05410541054305430545C1 -:1053100005450547054705490549054B054B054D1D -:10532000054D054F054F0551055105E805E805E90F -:1053300005E905EA05EA05EF05EF05F405F405F9C9 -:1053400005F905FE05FE0603060306080608060D18 -:10535000060D0612061206130000000000000000F1 -:10536000000000000000000000000000000000003D -:10537000000000000000000000000000000000002D -:1053800006130624000000000000000000000000DA -:10539000000000000000000000000000000000000D -:1053A0000000000000000000000000000624063994 -:1053B0000639063C063C063F0000000000000000E5 -:1053C00000000000000000000000000000000000DD -:1053D0000000000000000000063F0675000000000D -:1053E00000000000000000000000000000000000BD -:1053F00000000000000000000000000000000000AD -:1054000000000000067507780000000000000000A2 -:10541000000000000000000000000000000000008C -:10542000000000000000000000000000000000007C -:105430000778077F077F078307830787000000003F -:10544000000000000000000000000000000000005C -:10545000000000000000000000000000078707C8EF -:10546000000000000000000007C807D107D107DADC -:1054700007DA07E307E307EC07EC07F507F507FE94 -:1054800007FE080708070810081008670867087C67 -:10549000087C089108910894089408970897089A3E -:1054A000089A089D089D08A008A008A308A308A6BC -:1054B00008A608A908A908B2000000000000000022 -:1054C00000000000000000000000000000000000DC -:1054D00000000000000000000000000000000000CC -:1054E00008B208B800000000000000000000000042 -:1054F00000000000000000000000000000000000AC -:1055000000000000000000000000000008B808BB18 -:10551000000000000000000000000000000000008B -:10552000000000000000000000000000000000007B -:10553000000000000000000008BB08C100000000DF -:10554000000000000000000000000000000000005B -:10555000000000000000000000000000000000004B -:10556000000000000000000000000000000000003B -:1055700008C108D008D008DF08DF08EE08EE08FDF3 -:1055800008FD090C090C091B091B092A092A0939FC -:10559000093909AA00000000000000000000000016 -:1055A00000000000000000000000000000000000FB -:1055B00000000000000000000000000009AA09BF70 -:1055C00009BF09D009D009E109E109E209E209E3CB -:1055D00009E309E409E409E509E509E609E609E75B -:1055E00009E709E809E809E90000000000000000F7 -:1055F00000000000000000000000000000000000AB -:10560000000000000000000000000000000000009A -:10561000000000000000000000000000000000008A -:10562000000000000000000000000000000000007A -:10563000000000000000000000000000000000006A -:10564000000000000000000000000000000000005A -:10565000000000000000000000000000000000004A -:10566000000000000000000000000000000000003A -:10567000000000000000000000000000000000002A -:10568000000000000000000000000000000000001A -:10569000000000000000000000000000000000000A -:1056A00000000000000000000000000000000000FA -:1056B00000000000000000000000000000000000EA -:1056C000000000000000000000010000000204C013 -:1056D0000003098000040E4000051300000617C0F7 -:1056E00000071C800008214000092600000A2AC08B -:1056F000000B2F80000C3440000D3900000E3DC01F -:10570000000F42800010474000114C00001250C0B2 -:105710000013558000145A4000155F00001663C046 -:105720000017688000186D4000197200001A76C0DA -:10573000001B7B80001C8040001D8500001E89C06E -:10574000001F8E80000093400000200000004000F9 -:1057500000006000000080000000A0000000C00009 -:105760000000E000000100000001200000014000F6 -:1057700000016000000180000001A0000001C000E5 -:105780000001E000000200000002200000024000D2 -:1057900000026000000280000002A0000002C000C1 -:1057A0000002E000000300000003200000034000AE -:1057B00000036000000380000003A0000003C0009D -:1057C0000003E0000004000000042000000440008A -:1057D00000046000000480000004A0000004C00079 -:1057E0000004E00000050000000520000005400066 -:1057F00000056000000580000005A0000005C00055 -:105800000005E00000060000000620000006400041 -:1058100000066000000680000006A0000006C00030 -:105820000006E0000007000000072000000740001D -:1058300000076000000780000007A0000007C0000C -:105840000007E000000800000008200000084000F9 -:1058500000086000000880000008A0000008C000E8 -:105860000008E000000900000009200000094000D5 -:1058700000096000000980000009A0000009C000C4 -:105880000009E000000A0000000A2000000A4000B1 -:10589000000A6000000A8000000AA000000AC000A0 -:1058A000000AE000000B0000000B2000000B40008D -:1058B000000B6000000B8000000BA000000BC0007C -:1058C000000BE000000C0000000C2000000C400069 -:1058D000000C6000000C8000000CA000000CC00058 -:1058E000000CE000000D0000000D2000000D400045 -:1058F000000D6000000D8000000DA000000DC00034 -:10590000000DE000000E0000000E2000000E400020 -:10591000000E6000000E8000000EA000000EC0000F -:10592000000EE000000F0000000F2000000F4000FC -:10593000000F6000000F8000000FA000000FC000EB -:10594000000FE000001000000010200000104000D8 -:1059500000106000001080000010A0000010C000C7 -:105960000010E000001100000011200000114000B4 -:1059700000116000001180000011A0000011C000A3 -:105980000011E00000120000001220000012400090 -:1059900000126000001280000012A0000012C0007F -:1059A0000012E0000013000000132000001340006C -:1059B00000136000001380000013A0000013C0005B -:1059C0000013E00000140000001420000014400048 -:1059D00000146000001480000014A0000014C00037 -:1059E0000014E00000150000001520000015400024 -:1059F00000156000001580000015A0000015C00013 -:105A00000015E000001600000016200000164000FF -:105A100000166000001680000016A0000016C000EE -:105A20000016E000001700000017200000174000DB -:105A300000176000001780000017A0000017C000CA -:105A40000017E000001800000018200000184000B7 -:105A500000186000001880000018A0000018C000A6 -:105A60000018E00000190000001920000019400093 -:105A700000196000001980000019A0000019C00082 -:105A80000019E000001A0000001A2000001A40006F -:105A9000001A6000001A8000001AA000001AC0005E -:105AA000001AE000001B0000001B2000001B40004B -:105AB000001B6000001B8000001BA000001BC0003A -:105AC000001BE000001C0000001C2000001C400027 -:105AD000001C6000001C8000001CA000001CC00016 -:105AE000001CE000001D0000001D2000001D400003 -:105AF000001D6000001D8000001DA000001DC000F2 -:105B0000001DE000001E0000001E2000001E4000DE -:105B1000001E6000001E8000001EA000001EC000CD -:105B2000001EE000001F0000001F2000001F4000BA -:105B3000001F6000001F8000001FA000001FC000A9 -:105B4000001FE00000200000002020000020400096 -:105B500000206000002080000020A0000020C00085 -:105B60000020E00000210000002120000021400072 -:105B700000216000002180000021A0000021C00061 -:105B80000021E0000022000000222000002240004E -:105B900000226000002280000022A0000022C0003D -:105BA0000022E0000023000000232000002340002A -:105BB00000236000002380000023A0000023C00019 -:105BC0000023E00000240000002420000024400006 -:105BD00000246000002480000024A0000024C000F5 -:105BE0000024E000002500000025200000254000E2 -:105BF00000256000002580000025A0000025C000D1 -:105C00000025E000002600000026200000264000BD -:105C100000266000002680000026A0000026C000AC -:105C20000026E00000270000002720000027400099 -:105C300000276000002780000027A0000027C00088 -:105C40000027E00000280000002820000028400075 -:105C500000286000002880000028A0000028C00064 -:105C60000028E00000290000002920000029400051 -:105C700000296000002980000029A0000029C00040 -:105C80000029E000002A0000002A2000002A40002D -:105C9000002A6000002A8000002AA000002AC0001C -:105CA000002AE000002B0000002B2000002B400009 -:105CB000002B6000002B8000002BA000002BC000F8 -:105CC000002BE000002C0000002C2000002C4000E5 -:105CD000002C6000002C8000002CA000002CC000D4 -:105CE000002CE000002D0000002D2000002D4000C1 -:105CF000002D6000002D8000002DA000002DC000B0 -:105D0000002DE000002E0000002E2000002E40009C -:105D1000002E6000002E8000002EA000002EC0008B -:105D2000002EE000002F0000002F2000002F400078 -:105D3000002F6000002F8000002FA000002FC00067 -:105D4000002FE00000300000003020000030400054 -:105D500000306000003080000030A0000030C00043 -:105D60000030E00000310000003120000031400030 -:105D700000316000003180000031A0000031C0001F -:105D80000031E0000032000000322000003240000C -:105D900000326000003280000032A0000032C000FB -:105DA0000032E000003300000033200000334000E8 -:105DB00000336000003380000033A0000033C000D7 -:105DC0000033E000003400000034200000344000C4 -:105DD00000346000003480000034A0000034C000B3 -:105DE0000034E000003500000035200000354000A0 -:105DF00000356000003580000035A0000035C0008F -:105E00000035E0000036000000362000003640007B -:105E100000366000003680000036A0000036C0006A -:105E20000036E00000370000003720000037400057 -:105E300000376000003780000037A0000037C00046 -:105E40000037E00000380000003820000038400033 -:105E500000386000003880000038A0000038C00022 -:105E60000038E0000039000000392000003940000F -:105E700000396000003980000039A0000039C000FE -:105E80000039E000003A0000003A2000003A4000EB -:105E9000003A6000003A8000003AA000003AC000DA -:105EA000003AE000003B0000003B2000003B4000C7 -:105EB000003B6000003B8000003BA000003BC000B6 -:105EC000003BE000003C0000003C2000003C4000A3 -:105ED000003C6000003C8000003CA000003CC00092 -:105EE000003CE000003D0000003D2000003D40007F -:105EF000003D6000003D8000003DA000003DC0006E -:105F0000003DE000003E0000003E2000003E40005A -:105F1000003E6000003E8000003EA000003EC00049 -:105F2000003EE000003F0000003F2000003F400036 -:105F3000003F6000003F8000003FA000003FC00025 -:105F4000003FE000003FE00100000000000001FF12 -:105F50000000020000007FF800007FF80000014010 -:105F600000003500000000010000FF0000000000FC -:105F70000000FF00000000000000FF000000000023 -:105F80000000FF00000000000000FF000000000013 -:105F90000000FF00000000000000FF000000000003 -:105FA0000000FF000000000000000000140AFF00D5 -:105FB00000000001000000000020100100000000AF -:105FC0000100900000000100000090020000900419 -:105FD00000009006000090080000900A0000900C5D -:105FE0000000900E0000901000009012000090142D -:105FF00000009016000090180000901A0000901CFD -:106000000000901E000090200000902200009024CC -:1060100000009026000090280000902A0000902C9C -:106020000000902E0000903000009032000090346C -:1060300000009036000090380000903A0000903C3C -:106040000000903E0000904000009042000090440C -:1060500000009046000090480000904A0000904CDC -:106060000000904E000090500000905200009054AC -:1060700000009056000090580000905A0000905C7C -:106080000000905E0000906000009062000090644C -:1060900000009066000090680000906A0000906C1C -:1060A0000000906E000090700000907200009074EC -:1060B00000009076000090780000907A0000907CBC -:1060C0000000907E0000908000009082000090848C -:1060D00000009086000090880000908A0000908C5C -:1060E0000000908E0000909000009092000090942C -:1060F00000009096000090980000909A0000909CFC -:106100000000909E000090A0000090A2000090A4CB -:10611000000090A6000090A8000090AA000090AC9B -:10612000000090AE000090B0000090B2000090B46B -:10613000000090B6000090B8000090BA000090BC3B -:10614000000090BE000090C0000090C2000090C40B -:10615000000090C6000090C8000090CA000090CCDB -:10616000000090CE000090D0000090D2000090D4AB -:10617000000090D6000090D8000090DA000090DC7B -:10618000000090DE000090E0000090E2000090E44B -:10619000000090E6000090E8000090EA000090EC1B -:1061A000000090EE000090F0000090F2000090F4EB -:1061B000000090F6000090F8000090FA000090FCBB -:1061C000000090FE00009100000091020000910488 -:1061D00000009106000091080000910A0000910C57 -:1061E0000000910E00009110000091120000911427 -:1061F00000009116000091180000911A0000911CF7 -:106200000000911E000091200000912200009124C6 -:1062100000009126000091280000912A0000912C96 -:106220000000912E00009130000091320000913466 -:1062300000009136000091380000913A0000913C36 -:106240000000913E00009140000091420000914406 -:1062500000009146000091480000914A0000914CD6 -:106260000000914E000091500000915200009154A6 -:1062700000009156000091580000915A0000915C76 -:106280000000915E00009160000091620000916446 -:1062900000009166000091680000916A0000916C16 -:1062A0000000916E000091700000917200009174E6 -:1062B00000009176000091780000917A0000917CB6 -:1062C0000000917E00009180000091820000918486 -:1062D00000009186000091880000918A0000918C56 -:1062E0000000918E00009190000091920000919426 -:1062F00000009196000091980000919A0000919CF6 -:106300000000919E000091A0000091A2000091A4C5 -:10631000000091A6000091A8000091AA000091AC95 -:10632000000091AE000091B0000091B2000091B465 -:10633000000091B6000091B8000091BA000091BC35 -:10634000000091BE000091C0000091C2000091C405 -:10635000000091C6000091C8000091CA000091CCD5 -:10636000000091CE000091D0000091D2000091D4A5 -:10637000000091D6000091D8000091DA000091DC75 -:10638000000091DE000091E0000091E2000091E445 -:10639000000091E6000091E8000091EA000091EC15 -:1063A000000091EE000091F0000091F2000091F4E5 -:1063B000000091F6000091F8000091FA000091FCB5 -:1063C000000091FEFFFFFFFFFFFFFFFFFFFFFFFF4A -:1063D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD -:1063E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD -:1063F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD -:10640000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C -:10641000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C -:10642000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C -:10643000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C -:10644000FFFFFFFF0000000300BEBC2000000000B3 -:10645000000000050000000300BEBC20000000009A -:10646000000000050000000300BEBC20000000008A -:10647000000000050000000300BEBC20000000007A -:10648000000000050000000300BEBC20000000006A -:10649000000000050000000300BEBC20000000005A -:1064A000000000050000000300BEBC20000000004A -:1064B000000000050000000300BEBC20000000003A -:1064C0000000000500002000000040C000006180C6 -:1064D000000082400000A3000000C3C00000E48070 -:1064E0000001054000012600000146C00001678050 -:1064F000000188400001A9000001C9C00001EA8034 -:1065000000020B4000022C0000024CC000026D8013 -:1065100000028E400002AF000002CFC00002F080F7 -:10652000000011400000800000010380000187008E -:1065300000020A8000028E00000311800003950013 -:106540000004188000049C0000051F800005A300C3 -:10655000000626800006AA0000072D800007B10073 -:10656000000834800008B80000093B800009BF0023 -:10657000000A4280000AC600000B4980000BCD00D3 -:10658000000C5080000CD400000D578000005B0010 -:1065900000007FF800007FF8000000D50000150023 -:1065A0000000FF00000000000000FF0000000000ED -:1065B0000000FF00000000000000FF0000000000DD -:1065C0000000FF00000000000000FF0000000000CD -:1065D0000000FF00000000000000FF0000000000BD -:1065E000000019000000000000000000FFFFFFFF96 -:1065F0000000000003938700000000000393870061 -:1066000000007FF800007FF80000068E00003500D3 -:106610000000FF000FFFFFFF0000FF000FFFFFFF64 -:10662000000000FF0000FF000FFFFFFF0000FF0061 -:106630000FFFFFFF000000FF0000FF000FFFFFFF44 -:106640000000FF000FFFFFFF000000FF0000FF0041 -:106650000FFFFFFF0000FF000FFFFFFF000000FF24 -:106660000000FF000FFFFFFF0000FF000FFFFFFF14 -:10667000000000FF0000FF000FFFFFFF0000FF0011 -:106680000FFFFFFF000000FF0000FF000FFFFFFFF4 -:106690000000FF000FFFFFFF000000FF0000FF00F1 -:1066A0000FFFFFFF0000FF000FFFFFFF000000FFD4 -:1066B0000000FF000FFFFFFF0000FF000FFFFFFFC4 -:1066C000000000FF0000FF000FFFFFFF0000FF00C1 -:1066D0000FFFFFFF000000FF0000FF000FFFFFFFA4 -:1066E0000000FF000FFFFFFF000000FF0000FF00A1 -:1066F0000FFFFFFF0000FF000FFFFFFF000000FF84 -:106700000000FF000FFFFFFF0000FF000FFFFFFF73 -:10671000000000FF0000FF000FFFFFFF0000FF0070 -:106720000FFFFFFF000000FF0000FF000FFFFFFF53 -:106730000000FF000FFFFFFF000000FF0000FF0050 -:106740000FFFFFFF0000FF000FFFFFFF000000FF33 -:106750000000FF000FFFFFFF0000FF000FFFFFFF23 -:10676000000000FF0000FF000FFFFFFF0000FF0020 -:106770000FFFFFFF000000FF0000FF000FFFFFFF03 -:106780000000FF000FFFFFFF000000FF0000FF0000 -:106790000FFFFFFF0000FF000FFFFFFF000000FFE3 -:1067A0000000FF000FFFFFFF0000FF000FFFFFFFD3 -:1067B000000000FF0000FF000FFFFFFF0000FF00D0 -:1067C0000FFFFFFF000000FF0000FF000FFFFFFFB3 -:1067D0000000FF000FFFFFFF000000FF0000FF00B0 -:1067E0000FFFFFFF0000FF000FFFFFFF000000FF93 -:1067F0000000FF000FFFFFFF0000FF000FFFFFFF83 -:10680000000000FF0000FF000FFFFFFF0000FF007F -:106810000FFFFFFF000000FF0000FF000FFFFFFF62 -:106820000000FF000FFFFFFF000000FF0000FF005F -:106830000FFFFFFF0000FF000FFFFFFF000000FF42 -:106840000000FF000FFFFFFF0000FF000FFFFFFF32 -:10685000000000FF0000FF000FFFFFFF0000FF002F -:106860000FFFFFFF000000FF0000FF000FFFFFFF12 -:106870000000FF000FFFFFFF000000FF0000FF000F -:106880000FFFFFFF0000FF000FFFFFFF000000FFF2 -:10689000000000FF000000FF000000FF000000FFFC -:1068A000000000FF000000FF000000FF000000FFEC -:1068B0000000FF00000000000000FF0000000000DA -:1068C0000000FF00000000000000FF0000000000CA -:1068D0000000FF00000000000000FF0000000000BA -:1068E0000000FF00000000000000FF0000000000AA -:1068F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA8 -:10690000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97 -:10691000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87 -:10692000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77 -:10693000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67 -:10694000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57 -:10695000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47 -:10696000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37 -:106970000000100000002080000031000000418075 -:10698000000052000000628000007300000083805D -:10699000000094000000A4800000B5000000C58045 -:1069A0000000D6000000E6800000F700000107802C -:1069B0000001180000012880000139000001498011 -:1069C00000015A0000016A8000017B0000018B80F9 -:1069D00000019C000001AC800001BD000001CD80E1 -:1069E0000001DE000001EE800001FF0000000F80CA -:1069F00000007FF800007FF800000344000035002D -:106A000010000000000028AD000100010005020692 -:106A1000CCCCCCC5FFFFFFFFFFFFFFFF7058103C41 -:106A20000000FF00000000000000FF000000000068 -:106A30000000FF00000000000000FF000000000058 -:106A40000000FF00000000000000FF000000000048 -:106A50000000FF00000000000000FF000000000038 -:106A60000000000000000001CCCC0201CCCCCCCC5A -:106A7000CCCC0201CCCCCCCCCCCC0201CCCCCCCC80 -:106A8000CCCC0201CCCCCCCCCCCC0201CCCCCCCC70 -:106A9000CCCC0201CCCCCCCCCCCC0201CCCCCCCC60 -:106AA000CCCC0201CCCCCCCC00000000FFFFFFFF1F -:106AB000000E0000011600D6002625A0002625A005 -:106AC000002625A0002625A000720000012300F367 -:106AD000002625A0002625A0002625A0002625A00A -:106AE0000000FFFF000000000000FFFF00000000AA -:106AF0000000FFFF000000000000FFFF000000009A -:106B00000000FFFF000000000000FFFF0000000089 -:106B10000000FFFF000000000000FFFF0000000079 -:106B20000000FFFF000000000000FFFF0000000069 -:106B30000000FFFF000000000000FFFF0000000059 -:106B40000000FFFF000000000000FFFF0000000049 -:106B50000000FFFF000000000000FFFF0000000039 -:106B60000000FFFF000000000000FFFF0000000029 -:106B70000000FFFF000000000000FFFF0000000019 -:106B80000000FFFF000000000000FFFF0000000009 -:106B90000000FFFF000000000000FFFF00000000F9 -:106BA0000000FFFF000000000000FFFF00000000E9 -:106BB0000000FFFF000000000000FFFF00000000D9 -:106BC0000000FFFF000000000000FFFF00000000C9 -:106BD0000000FFFF000000000000FFFF00000000B9 -:106BE0000000FFFF000000000000FFFF00000000A9 -:106BF0000000FFFF000000000000FFFF0000000099 -:106C00000000FFFF000000000000FFFF0000000088 -:106C10000000FFFF000000000000FFFF0000000078 -:106C20000000FFFF000000000000FFFF0000000068 -:106C30000000FFFF000000000000FFFF0000000058 -:106C40000000FFFF000000000000FFFF0000000048 -:106C50000000FFFF000000000000FFFF0000000038 -:106C60000000FFFF000000000000FFFF0000000028 -:106C70000000FFFF000000000000FFFF0000000018 -:106C80000000FFFF000000000000FFFF0000000008 -:106C90000000FFFF000000000000FFFF00000000F8 -:106CA0000000FFFF000000000000FFFF00000000E8 -:106CB0000000FFFF000000000000FFFF00000000D8 -:106CC0000000FFFF000000000000FFFF00000000C8 -:106CD0000000FFFF000000000000FFFF00000000B8 -:106CE000FFFFFFF3318FFFFF0C30C30CC30C30C329 -:106CF000CF3CF300F3CF3CF30000CF3CCDCDCDCD66 -:106D0000FFFFFFF130EFFFFF0C30C30CC30C30C3AB -:106D1000CF3CF300F3CF3CF30001CF3CCDCDCDCD44 -:106D2000FFFFFFF6305FFFFF0C30C30CC30C30C316 -:106D3000CF3CF300F3CF3CF30002CF3CCDCDCDCD23 -:106D4000FFFFF4061CBFFFFF0C30C305C30C30C3AC -:106D5000CF300014F3CF3CF30004CF3CCDCDCDCDEC -:106D6000FFFFFFF2304FFFFF0C30C30CC30C30C3EA -:106D7000CF3CF300F3CF3CF30008CF3CCDCDCDCDDD -:106D8000FFFFFFFA302FFFFF0C30C30CC30C30C3E2 -:106D9000CF3CF300F3CF3CF30010CF3CCDCDCDCDB5 -:106DA000FFFFFFF731EFFFFF0C30C30CC30C30C304 -:106DB000CF3CF300F3CF3CF30020CF3CCDCDCDCD85 -:106DC000FFFFFFF5302FFFFF0C30C30CC30C30C3A7 -:106DD000CF3CF300F3CF3CF30040CF3CCDCDCDCD45 -:106DE000FFFFFFF3318FFFFF0C30C30CC30C30C328 -:106DF000CF3CF300F3CF3CF30000CF3CCDCDCDCD65 -:106E0000FFFFFFF1310FFFFF0C30C30CC30C30C389 -:106E1000CF3CF300F3CF3CF30001CF3CCDCDCDCD43 -:106E2000FFFFFFF6305FFFFF0C30C30CC30C30C315 -:106E3000CF3CF300F3CF3CF30002CF3CCDCDCDCD22 -:106E4000FFFFF4061CBFFFFF0C30C305C30C30C3AB -:106E5000CF300014F3CF3CF30004CF3CCDCDCDCDEB -:106E6000FFFFFFF2304FFFFF0C30C30CC30C30C3E9 -:106E7000CF3CF300F3CF3CF30008CF3CCDCDCDCDDC -:106E8000FFFFFFFA302FFFFF0C30C30CC30C30C3E1 -:106E9000CF3CF300F3CF3CF30010CF3CCDCDCDCDB4 -:106EA000FFFFFFF730EFFFFF0C30C30CC30C30C304 -:106EB000CF3CF300F3CF3CF30020CF3CCDCDCDCD84 -:106EC000FFFFFFF5304FFFFF0C30C30CC30C30C386 -:106ED000CF3CF300F3CF3CF30040CF3CCDCDCDCD44 -:106EE000FFFFFFFF30CFFFFF0C30C30CC30C30C3DC -:106EF000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD98 -:106F0000FFFFFFFF30CFFFFF0C30C30CC30C30C3BB -:106F1000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD76 -:106F2000FFFFFFFF30CFFFFF0C30C30CC30C30C39B -:106F3000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD55 -:106F4000FFFFFFFF30CFFFFF0C30C30CC30C30C37B -:106F5000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD33 -:106F6000FFFFFFFF30CFFFFF0C30C30CC30C30C35B -:106F7000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD0F -:106F8000FFFFFFFF30CFFFFF0C30C30CC30C30C33B -:106F9000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDE7 -:106FA000FFFFFFFF30CFFFFF0C30C30CC30C30C31B -:106FB000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDB7 -:106FC000FFFFFFFF30CFFFFF0C30C30CC30C30C3FB -:106FD000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD77 -:106FE000FFFFFFF3320FFFFF0C30C30CC30C30C3A5 -:106FF000CF3CF300F3CF3CF30000CF3CCDCDCDCD63 -:10700000FFFFFFF1310FFFFF0C30C30CC30C30C387 -:10701000CF3CF300F3CF3CF30001CF3CCDCDCDCD41 -:10702000FFFFFFF6305FFFFF0C30C30CC30C30C313 -:10703000CF3CF300F3CF3CF30002CF3CCDCDCDCD20 -:10704000FFFFF4061CBFFFFF0C30C305C30C30C3A9 -:10705000CF300014F3CF3CF30004CF3CCDCDCDCDE9 -:10706000FFFFFFF2304FFFFF0C30C30CC30C30C3E7 -:10707000CF3CF300F3CF3CF30008CF3CCDCDCDCDDA -:10708000FFFFFF8A042FFFFF0C30C30CC30C30C37B -:10709000CF3CC000F3CF3CF30010CF3CCDCDCDCDE5 -:1070A000FFFFFF9705CFFFFF0C30C30CC30C30C3AD -:1070B000CF3CC000F3CF3CF30020CF3CCDCDCDCDB5 -:1070C000FFFFFFF5310FFFFF0C30C30CC30C30C3C3 -:1070D000CF3CF300F3CF3CF30040CF3CCDCDCDCD42 -:1070E000FFFFFFF3320FFFFF0C30C30CC30C30C3A4 -:1070F000CF3CF300F3CF3CF30000CF3CCDCDCDCD62 -:10710000FFFFFFF1302FFFFF0C30C30CC30C30C367 -:10711000CF3CF300F3CF3CF30001CF3CCDCDCDCD40 -:10712000FFFFFFF6305FFFFF0C30C30CC30C30C312 -:10713000CF3CF300F3CF3CF30002CF3CCDCDCDCD1F -:10714000FFFFFF061CBFFFFF0C30C30CC30C30C396 -:10715000CF3CC014F3CF3CF30004CF3CCDCDCDCD1C -:10716000FFFFFFF2304FFFFF0C30C30CC30C30C3E6 -:10717000CF3CF300F3CF3CF30008CF3CCDCDCDCDD9 -:10718000FFFFFFFA302FFFFF0C30C30CC30C30C3DE -:10719000CF3CF300F3CF3CF30010CF3CCDCDCDCDB1 -:1071A000FFFFFFF731CFFFFF0C30C30CC30C30C320 -:1071B000CF3CF300F3CF3CF30020CF3CCDCDCDCD81 -:1071C000FFFFFFFF30CFFFFF0C30C30CC30C30C3F9 -:1071D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD75 -:1071E000FFFFFFFF30CFFFFF0C30C30CC30C30C3D9 -:1071F000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD95 -:10720000FFFFFFFF30CFFFFF0C30C30CC30C30C3B8 -:10721000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD73 -:10722000FFFFFFFF30CFFFFF0C30C30CC30C30C398 -:10723000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD52 -:10724000FFFFFFFF30CFFFFF0C30C30CC30C30C378 -:10725000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD30 -:10726000FFFFFFFF30CFFFFF0C30C30CC30C30C358 -:10727000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD0C -:10728000FFFFFFFF30CFFFFF0C30C30CC30C30C338 -:10729000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDE4 -:1072A000FFFFFFFF30CFFFFF0C30C30CC30C30C318 -:1072B000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDB4 -:1072C000FFFFFFFF30CFFFFF0C30C30CC30C30C3F8 -:1072D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD74 -:1072E000FFFFFFFF30CFFFFF0C30C30CC30C30C3D8 -:1072F000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD94 -:10730000FFFFFFFF30CFFFFF0C30C30CC30C30C3B7 -:10731000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD72 -:10732000FFFFFFFF30CFFFFF0C30C30CC30C30C397 -:10733000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD51 -:10734000FFFFFFFF30CFFFFF0C30C30CC30C30C377 -:10735000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD2F -:10736000FFFFFFFF30CFFFFF0C30C30CC30C30C357 -:10737000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD0B -:10738000FFFFFFFF30CFFFFF0C30C30CC30C30C337 -:10739000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDE3 -:1073A000FFFFFFFF30CFFFFF0C30C30CC30C30C317 -:1073B000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDB3 -:1073C000FFFFFFFF30CFFFFF0C30C30CC30C30C3F7 -:1073D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD73 -:1073E000FFFFFFFF30CFFFFF0C30C30CC30C30C3D7 -:1073F000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD93 -:10740000FFFFFFFF30CFFFFF0C30C30CC30C30C3B6 -:10741000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD71 -:10742000FFFFFFFF30CFFFFF0C30C30CC30C30C396 -:10743000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD50 -:10744000FFFFFFFF30CFFFFF0C30C30CC30C30C376 -:10745000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD2E -:10746000FFFFFFFF30CFFFFF0C30C30CC30C30C356 -:10747000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD0A -:10748000FFFFFFFF30CFFFFF0C30C30CC30C30C336 -:10749000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDE2 -:1074A000FFFFFFFF30CFFFFF0C30C30CC30C30C316 -:1074B000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDB2 -:1074C000FFFFFFFF30CFFFFF0C30C30CC30C30C3F6 -:1074D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD72 -:1074E000000C0000000700C000028130000B815832 -:1074F0000002021000010230000F024000010330C0 -:10750000000C0000000800C000028140000B8168F0 -:10751000000202200001024000070250000202C0E7 -:10752000001000000008010000028180000B81A80B -:107530000002026000018280000E82980008038031 -:107540000010000000010100000281100009013854 -:10755000000201C8000101E8000E01F8000002D895 -:10756000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC5B -:1075700000002000CCCCCCCCCCCCCCCCCCCCCCCC5B -:10758000CCCCCCCC00002000CCCCCCCCCCCCCCCC4B -:10759000CCCCCCCCCCCCCCCC040020000000000067 -:1075A0001F8B080000000000000BFB51CFC0F00350 -:1075B0008AB7B13130ECE644F0E98159181818F86F -:1075C00099C8D7BF1168C04E20BE01C4075948D71B -:1075D0007F551AC15E26C9C0700A8827883330B427 -:1075E0004A21C4ED651818EE01F92BA16272403DE5 -:1075F00073A4C977F3281E3CB8D014951F620CA160 -:107600005F9840E82234F950A8BCB81E842E36C5D5 -:107610006EAE841E71F6A7A9A0F2BD55F0ABCFD512 -:1076200040E5C7A2A90F81F2017EE9B234D8030078 -:1076300000000000000000001F8B08000000000098 -:10764000000BED7D0B7455D5B5E8DA9FB3CFFF6421 -:10765000278470123EEEC400C1063C4280A0A83BC5 -:10766000FC1A7DD41E1025E5A11C446B004922A6FE -:10767000D78C96D76CC8870450E3E751BD457BA0F3 -:10768000D88B0E5BA3A68ABDB43D887AA9C3DB2242 -:107690005AA52D7A83FA2C58A0B1572ABD4FCB5B3F -:1076A00073AEB592BD77CEC9C74F47EF788D43769D -:1076B000D6DEEB3BFF6BCEB95634D943F22E27E42E -:1076C0001CFCD0A7291142A6F73DC92D5932C92368 -:1076D000E41B3E823F1FF923534816210D3EF6BCA2 -:1076E0003D10D905CF2D8D84A426C2F771491221F2 -:1076F000244848899A0B2D02B1870BE15977617CA8 -:10770000323E67C23387C8848C84F218FDBD20EBFB -:10771000FB9C42FF399AA880F114F68AA8A43C96F3 -:10772000C2F6DF226446DF3C48DD57F578B86FDEED -:10773000EEA7A26B24C5EB9E837F94E5598950E6A2 -:10774000FA0D47A5C79FB7D51F4FC2B9382F95A8C7 -:10775000382FDE9E108BD8E7E7EEE7A346F2F8F36A -:10776000E3FBC32DD3B8026E6D8D3E7CB636EA24A2 -:10777000E5258436333B4BE93344CC5DA5FDDBCDB9 -:107780002312871F9F0F8C63D0FAF47F42E1DE9CA7 -:107790004B9241C0214938E0D61C5AEC33D3F42730 -:1077A0009E2497C2AD84CFB9A8FF7AFD302F0A0777 -:1077B0003FCC2B0D3C97C2BCA6F79F97BFD83DAFDF -:1077C0006A6287CF70E7159844C821C0876A128221 -:1077D00078B9CDD19FAC9B56779AFE08A70BD5E020 -:1077E000EB1B229E822572DFF8000723E0A02F6F9B -:1077F00034C7496F6EBA067820BE3A387CE20AE395 -:1078000007AB0F8FF4199A1D93803568F110E02DA6 -:107810009F30F8E557B7DE2A4F2194D53A0F4EA096 -:10782000F0CBEF5EB99040F9E8152780DF9ACBA640 -:1078300056CEA5F5B2CB63AF2CA04D423143027AB0 -:10784000DD0A9D15407F5FB32A68B909FAA365CBAD -:10785000BACAB4106EA6036E1472864ACB1EF8B56F -:10786000280DFC482F1EA473DEFEED33C1CF436C00 -:10787000F8437E5EEFA0CB8C78BF91E1CBA2FF01F5 -:10788000BE46101B5FD37EB22B35075EB25CE33C75 -:107890000ABF20BC6FFD9B8C97439EF41994CE3D8C -:1078A000A5B29EA478CA26B16CB58CE263A14A4009 -:1078B0008EE5E4EA1290C360786926A412F89F4A24 -:1078C00007B2C826E77ECEF9AB60CDEE9DAD749CC5 -:1078D00033B34331A895AFD3B94EEDBF9E3B40BE05 -:1078E000786DE5B2E74802C7EB3C5844E76595C9B7 -:1078F000B18729DD6C2D3DACDBE5E3B15EF9E2A695 -:107900000F62A833B83CA0F0514A65D31FF9ECF4DC -:10791000A17C4AFA08DFE8C4C770F1757A98F4F1DF -:1079200059C71378EDCF571B055E7D847EDF52B2B9 -:1079300078407DD51FAF4F92046D172A2566324DD2 -:10794000BBFFB4EB0BF7D326DFDD72541935A36A06 -:10795000E74078CB75AE57F4EB6F508C7747D0A2E9 -:10796000AAA37CD5B81E688FDE63114A776740F6FC -:107970005078281D17A5A04C8A49EC61D64D4AA223 -:10798000657FD44C6E413A48225EC4FCBC86EC90C4 -:10799000B36AAE530E932A4BB2CFDFDFA0E13C3483 -:1079A000182F17EC02DA2105851A2229A05B41AFB6 -:1079B000A092CE9D0F65A79DD1664C25E9F0A072DF -:1079C000BC4B92A0D76F0D4DBEB8C75BE29CEF9049 -:1079D000DB8554E33DD1268D9CEE6BA792F7047EA8 -:1079E00028102F13761DC7D3660FD92B5D48E5C12C -:1079F000986BC152209BE1D32C6A87C0932A9FCDFC -:107A000063A6EA4057648FA4C23C71488A4742F596 -:107A10001DD40B4A06F623FBEA90FE9490894FF1A1 -:107A20003DF3BCD8F8BD655FA206F0531DD58C2D83 -:107A3000748E6B15D3D80874318DC9A7EAE88479A0 -:107A4000A0EF3C129BD7B7A57C5C879AD39687762C -:107A50005906FBAE5AA52A7F2A7CDF3661207E229A -:107A6000494F4FB70D9E6E7BF06689DA835FA2BFE8 -:107A7000CC2433018E7F8A2DCE4A0D80AFF71B0FA9 -:107A8000EAEAF83E7BD0FD7DAD42EAD2C98156C913 -:107A9000C7F8D26769601F8875AF0576A720DD1625 -:107AA000DBC4D69B9B8BF05DBBE717BA6AE3BFB51F -:107AB00054CD78A7F65F8F80B7E8A7B77DF2A0A373 -:107AC000BDBB5D6F7F425E507B18E85CD041504A81 -:107AD0006C95E87B6F6CB105EA6CED63150CFF19D2 -:107AE000E6DF8BAF4F397FD16E30BAFAD3EEA656B0 -:107AF000D04FEF691D575D4CE9E8F74F28B14DF4C1 -:107B00006BF58E89F3C05E7A8FD3B7C0D389DD4D14 -:107B100079E9E823139E7E21F9711C415FD5F2F2C9 -:107B200001E96130FA7ACA4D5F9D577F21F475C82B -:107B30004D5F1C1E273BD9FAC9FD23185E38BEDCF9 -:107B4000F8C988974FDBAE3F3DFD5AA27CEDEDBCF6 -:107B50003A3D3DF1F90A7C7DD6F90E4647798669B2 -:107B6000EA74FC51D48E91407F9491588ACE53A7E9 -:107B70000FD45B31A6B7845C12ED4F4BCC4E53C98A -:107B80006BD85E21294B477BDB6967CC57E84BDA22 -:107B90004F7309497A715F64FA504F95A884E93FA1 -:107BA00033943F03EC08FEA3CC8EC1BAB3C0FE07EA -:107BB000FD359BEB5F89DA5B747DA132E7BE37E070 -:107BC000B23F14BE5FE8676F0D737FEC97F9FE3824 -:107BD0004842A88FC4FE38037FF6EE8B395C476AB3 -:107BE000C494E9BAB5839EE42609B41B41FD4C8ECA -:107BF0004A49E62F20256037AF970A62A00FE83E7A -:107C0000AF278B7E7FEF070AEA878668DD8A1658E2 -:107C1000F6B50D13BBE9B8F7349269C59EBEF1EE17 -:107C2000513B7C00EFF6E2F50EBBF6BB52A250B61C -:107C3000E91D7F549B563C0D8653DFEEA6F090293C -:107C40002081FF02A1FBA22F18003FF6BE174EF6BF -:107C5000B2D2BF9C0B364F011653B02F6DA7B63B67 -:107C6000B9188AA3A50A4A07ED1EFEDDFA4D05ECF8 -:107C700077DBFDACBC63D3AC8D169447F2FA561596 -:107C8000FB9ECFCAB76DFA4105EC0BDAB2E99AA9AF -:107C9000BE6EF324ABE269F8FB365976D85F4DC669 -:107CA00082F2FF43D7E1F79917BD40E1498112B352 -:107CB0000CD26B97150ABF41C7DD952500FFD7147D -:107CC00002F4EC3762F19B0CA43FA47B7FAE19DB7E -:107CD000424B0DF4850CF528DE1E96605FC7EC3133 -:107CE000F0E79C43FAA57C41BFAFCFD6B13ED16D42 -:107CF000F659519F3DD68B2717DEEE557BFC80B79A -:107D0000EF8DF9F01713693FD642390664F3BD0DC4 -:107D100045D92B6D787CCC37A70AF0489A73D12EC1 -:107D20008992DE1F13CA62DF5C403A2BC0781C4385 -:107D3000251FA1743A2EDE53012830AAF4E7708F74 -:107D40004BE6E9EFA15DA548E7BE34743BCA0D07D9 -:107D5000DAE3A845543E8D90483C9DDC5DA9E6A041 -:107D60003C185149D73B809FE09B549F30FB2CE14E -:107D700003FF56A67132CDF333C073934CC71D4D2C -:107D80009208A7C1E09A099EADD127B3515E7FCE7C -:107D900070CDD4DE0DCF1112E397956A39F2CB5036 -:107DA000FD3B6D7C3FD5027E38FA6CE27E38777BF6 -:107DB000BFDA416269F0EB379CFE210DF625B67201 -:107DC000BD6C307D1072FB89189EDD7A6101D70B86 -:107DD0002D51AA17983C5C087A20C8E1DF02BB7ECF -:107DE000909F6192B4E8F720F707915226FF7DF447 -:107DF0003FE0B751554E7DA00D511FBC2BC55F9084 -:107E0000910E8904F3BB5FEAB86202D04F3EB3C75C -:107E1000A337B445133638D4CB4CDF097D962C16E6 -:107E2000FA8C20FCCEE37348920E3FE8C307362C51 -:107E3000CE42BFDD8D41871C8AB62EC6FDAF8D9E1A -:107E4000D12FDAC1FDA399F0A76BC9443A7958A89C -:107E5000307918317B52E0F34342CEE32E434ED6C5 -:107E60000CFEC4B10F8B4CED39783E5DEFCE8BE448 -:107E7000D826DA4E9DADA63C14BE6AF98B55127D0C -:107E8000EE2C64F0B76611A4D390B1E08402FA58E6 -:107E9000ED467F4DA8D2BD2FB69515E8A7E77AD459 -:107EA000DF763FF500FBB8A13E9B28BCDEB6F13F74 -:107EB000855C4AA1EB50371003EC09D5A4223102AE -:107EC0004F3D0FE8453563217C765754C2F3BCD94A -:107ED000F14AD9A6075433BE05EA8FF8CA7DEDB042 -:107EE0005EF526595624C6073936789B4AA1633F6A -:107EF00097ADBBFCA589D62AD4EF8646C617F69F58 -:107F000077BDAC72B9E7A417412703C8BBCF441FA4 -:107F10006FCAC25FEDC4BF834E8AFAF02BDA85FACE -:107F2000F9AB9CF875973F6FBCFA014F141FE751EE -:107F30003C017D9E379BD123B547D17E7AC0D76166 -:107F400002BC1F2836644BEA6B175672989FF92CB7 -:107F5000DD6851BBE7FE95DB4D68975F4C6580841B -:107F6000CFB4FEA37A59C376542E542ACC6E97C050 -:107F70001E9FAF6CAB82F63B295E81DF77027F43A9 -:107F80007C20A1A11CAE97DB2B36D2BE5B8F4AB200 -:107F90000246ACBE14F1EBE7FCFE912751097EC806 -:107FA0002DFF4B26BB0CD04B03FBBD9A38BE4519A9 -:107FB000FC0D609F8CA9D3A702D833B5DB5E275791 -:107FC000A65B57B5C2F07F47DDE10E344F9F77EED9 -:107FD000473CCB4DA048D897542B36FA0E97317FAB -:107FE0000749D0F5407D4E371F150E4CAF0FBAE64E -:107FF0003F96C753DCF55E56B8BFCE60F03244FF03 -:108000001B07EE5FC0E76C9BC2E323D40043221E34 -:1080100049ECFA5BB9F15005BCA75CB709F0B55D56 -:1080200026D5CCDF1C473D14E1E3ED2CCFC1F60B88 -:10803000552647C79AFA16C0F7D866192C05F2B824 -:1080400062E0FB51CBEBF67B281EDA0B492C64E097 -:1080500010D8EF8BE335A4CBFC5CA6C7F2EB290963 -:10806000D07AF9A52469D0F6EDFB1FA8D068394273 -:108070003754600AFBCA193E7D252406A690C72204 -:1080800029997D4F424C5229EFB140951E183F036C -:10809000F75F77E69298D7E8931B82AEEE6CBEC787 -:1080A0000F7AE481E27BAE9800FEC65215FDE4E44F -:1080B000630A27E14F54205E163761BCF6596CDE27 -:1080C000F40DE253D5D9FAC7DC3F1BF9A43DFC34CB -:1080D000CEC35A4762E3B15E8C60FC860A54F05707 -:1080E0003655337BD78D8FF524F1B832DD4EAF870F -:1080F000906EDA3F51F8BEE0C58D60E78F835F690F -:10810000F9974D7FDC381CBB45C40F85DDB245EDCA -:1081100044BEB728CF815E12768CBFB813C7FDBFAF -:108120009CDE87DABFBFC4E96F75DB356E7BA65E68 -:10813000D61DF6AB7B5D1F795257C0FCB6E4537E6B -:108140004FA3077E03FA9AB6DF115DFCAB89465F49 -:108150003F7D72C8C0EFA23CE6AC86F8197A7D2A52 -:10816000F7608F6632BE1A2BE4D037285F0D107F80 -:10817000147CF511151287804FD40EA42F6296201F -:108180005F097E51BA3BDACFA7F460D4CBE0B906E1 -:10819000FE2239B45C48E93D65B38784BC504B3B53 -:1081A000E313A5FE74F7A021231ECF94317F7596AB -:1081B000D56D4293606927C6F5285DFD17D095AA55 -:1081C0002725C0EB98FB17E0BA7EA93056F7AB2CF9 -:1081D0007EEC5EC7CF397C89BE1BED793F1B8EB22A -:1081E000F87D31363F579CBDFE5703C6D9FD319708 -:1081F0009D334C3F428ECAFD08DCEF3558FBE1C68B -:10820000D795B323903E7ACB19E4ED4D2AE78BA3A3 -:10821000BB1C70E9070F65476CA0F9F9859FFE53F9 -:10822000C60550870D010E6E385EA23AFD879F3756 -:108230001CDDF1EF97B8DC1F4C1E044D33252BE0FD -:108240003F23CCBF1322DCBFE3A4F79DCD32DA215C -:10825000C1B0BC134CC9ACFA6ED4C1627C4AEF55B4 -:10826000AA8DDE47971E4A413BB73ECAA4870693B4 -:10827000B7AB7CE60D2ACAADF4FBF1BE7C03CA2580 -:1082800069F20D32E2B5EEF3C937182ABC7BFD9BCB -:108290003C7FE0867241C7C6D2DF51B8AC3EE821D0 -:1082A000E897F998AECE16575BCDF78137F07DE4AD -:1082B0008D241E818FA7885C09FC728A1C8E4CB3AA -:1082C000C993FB548DF14B9BE76DF0AF8A78F94D64 -:1082D0001DAC2CE673F3FDCEF2D7C9E23CF0EB7D8A -:1082E000FD3E0FE26BB5CBBFD6AC32FD7133A96B4F -:1082F00005BCB5784815C8B11B74A28EA0A6EBBA10 -:10830000671E9CB19296BFCBED91F7A95C366C715C -:10831000D035A1A406F87DA76BDAB59710689F6CDD -:108320002D807D5A36C17DAB1BCEABDA9CF31B6C26 -:10833000FEEEF952F2C2F9669A87BA474A6B4F3F8E -:1083400022E40DC757A6BC2A914FF50B20205ADF17 -:108350009A43D8BEF3AD60B209E535CBA71AACFDA0 -:108360002F55463F9FB6FDAB83B45FE7EB5900CC7A -:10837000D6966BC5C12F24E28235A4CE1C4D7F5505 -:10838000F72DB246135BBDE810EB150F5C2FD3BC85 -:108390004FE83E4BBEB06FFEDF9512C7D434F3BF3B -:1083A0005D49D440FF5EC083024F15F18D7E608A27 -:1083B000DF5A35D4266541BE5317EE03FD86EAA089 -:1083C000875AF805E45A09936BC112E777B77FF82B -:1083D0004355C4E153C87F188236C07E08A514F007 -:1083E000DF94AB277BEBD3F16A605D1742298E7275 -:1083F000A35E67F56B8871D7EC32E43F8C3FD4B74E -:108400009F8F71F5FA9106FA77551233B10F17DD88 -:10841000D59E9548D2A60F6BD51E0DF8AC96DA45C1 -:10842000F6F7EBA38AC34FEB7E7AA8E51C2A817D81 -:1084300092CCFC483A2DDBD6FDA70E89E7AF185940 -:108440004B06F0DFAD8F327FF00DEDE3B398DFD058 -:10845000297F4F3732BFDCBF3DF67D0DFCFCA71EE8 -:108460003D7615C07BEDBF2AC407F91B8F85490AED -:10847000EDB1A406F6D89A2EC54CA6CDAF6862F130 -:10848000CFC7C388AF354F7A930B69FB354FBF33E6 -:1084900085D0F99DDED4F3E268B09B1F95581E820B -:1084A000D53DE56AFA7E8D4A56A4F31B4CF630F9A9 -:1084B00073F2D96015F0B7B467FFF5D86FE7528F44 -:1084C000D7B6DF2EF678906F693D66973F2225C7B5 -:1084D0004BE9E6C7F23F4E3E22B1F9EDF524FD30FF -:1084E000BF3D3BB5049D47ED9E0F509ECC7DFC8764 -:1084F000118043ED5EC5A1076AF72829EF147C1EA1 -:108500008327C48DA41940279C5EBAD661BCA8A657 -:1085100073EB07E0C7A8DDEB946B142EB114C0F524 -:108520000D25B610CA4FFD4BC4A0A07AFFD0C311D1 -:10853000802BED77A59605FAC649DFD0FFD99CFEC2 -:10854000FD11D283F1BADACE76365ED7577E0F7A36 -:10855000A5D6253FDF875FF2FBDB33D7785CF6CC0F -:108560009EA1C5EBD6FEF0CC43161DF7E4937F78B1 -:10857000C8A2F3BFE5AFFFF9D0B7803F7FE6D74190 -:10858000FED73EFAEB08B1D163AD87F1E3E9B1C4A0 -:10859000A27B5472FA37DE24F84B4EFFF4F7E30C5B -:1085A000BAEED34FFC25CFA0F5EB7F3A7F14C0A1E4 -:1085B000FEC773470DB4FF067A4D7AEDF34A225E8B -:1085C0008DBD123382F6F1A70B3F07BA0E8C83796B -:1085D0009E3AE28D81DBB996BE6B980AF85A87FA0B -:1085E00018CA1B289C6B1EDBFC01C889FEF0B6462E -:1085F000CBE8AC4F8D06A77D4DD73B0B106FA40782 -:10860000F5A8BB7EED6B149F1766C6DF19F2B106A5 -:10861000F2AEF6B176365E27C55FA43FFE4EC12F9F -:10862000B3FAE3EF0E17FECE905BBE970F798D5D28 -:10863000231C7152F1EC8B0FC6B3E203C80B210F60 -:1086400006836FB5C4E6B5CC633EE801BE7A32D886 -:108650008BDF8580DF1F9E1947287D1CF7F45C0F98 -:1086600072B3E7A75E7D177DBFE6A76F209F9DFED3 -:10867000F12B9A81F9992424E5F13C31F67308E451 -:10868000700DDBCB91DADDE19437D287A79AE4A2B3 -:108690004A2382EF8FE1FB24A3FF9AE4FE25521ABE -:1086A000BCBDE1296276407224C265DDEEDF69CC93 -:1086B000BEECC3A7540EF83CB600DE67C2A758BF95 -:1086C0000EEB9F69C3EB6EC6B7EEFA35943F41EFF0 -:1086D000F5C36F527A039EA7777A55D07BA7C1FE68 -:1086E0000AF5C77B1FFC99FD33DCFDCA2B6EFE1615 -:1086F000F1630E87CCF461713B60E0F50D177E3FAE -:10870000F7180E3A12703CF9717AF97F8ACB8D1AFC -:10871000625516D8EC139F87DA27905F46E2D6E8B9 -:10872000C2BEF99E847D04A5BF938F2A18AF69ED60 -:108730003C8072DC2D2F6A48FA7DFB5F3DCC5EAC3D -:10874000D9BB7F0AC8B593CF3D8BF459F3D8310D0F -:10875000F62F2FEE794AEB2EEDE307D00F499B7EE3 -:1087600038F9A3FD53983C48BFFF0D6AACFFDA7D92 -:10877000CEFE6B1FFBC0D1FF5AAB5363790C038F46 -:10878000F3BE6A2E85F5BE7FC843409EBEDFA9A416 -:10879000F5BFF670FD28E0D4FACA82DF419CBFEC39 -:1087A00070C0003DDAB5C91C7507D86B873D04E47D -:1087B0003751CD3F7869B9EB9500C633BA0E5FAB40 -:1087C0001836FFC4332E78CE7CCD9A1BA6FDCDEC97 -:1087D0008E97C116CA2D37CA8FD27DA3DD7FF54A89 -:1087E000E52890FBCD60CF4F84F16251F07F289156 -:1087F00005952C7F50D6FD69F537EBCF138A63BE04 -:10880000A047977B7DB6488F62BFC5FD4DADA1F4F3 -:10881000FEE8059AD817D0716D7290DAAA55E9F082 -:10882000364B637648A6EF976ACCDF93E97BC52089 -:10883000ED7BF99BE3470BCBF174F39EC6FB71FB19 -:108840005733C9030FEFA74C331CEB05782FB2E564 -:10885000C58F26C98D90274A4221773C3AEEB3C78F -:10886000A3AB0EED87F873EED5FBF201FE11D2AC8F -:10887000BF87763C899D1BC08E75C79FDD7989991E -:10888000E2D1BE50CD9114E9DF5FFFF8BB897928B2 -:10889000CD63E6F90A6DF1F766BD5FFC7DBD46C7A5 -:1088A0006DC9808725DA9C7FD280BE649248F77DAF -:1088B0000BA79BCB49F7532B619E3116BF9FED82CF -:1088C000D7A51C5E3F3B9F2E9CAA9E0A62A81E0A4B -:1088D000DFB94BCC661081F397F7ACDD0F7C26E255 -:1088E000F7D644F95C70E8F01B6E5EC42ADFE27BC9 -:1088F000B521E445103D27AD5EE89B87C5F755518E -:10890000DC2779389F1D78F3661FC82D95242A0B24 -:1089100061BFC4E39A986F4FFBCB4BF98949E7AB32 -:10892000E906DADB79A9D50FDC0471757D0CC62365 -:1089300094B397A0FFD0DDAF128D59980F16322A4D -:1089400014DB38ADB92C3EA3EAF1B479C3ABB4C49F -:1089500013B05EE5EC65D8AFEC8B613D121A5ABEE0 -:10896000EC77AE8E207C7D14BE201F1164B02E9E4D -:108970003775F7D511D433FE839E9DF0DD1F6279E4 -:1089800054B7CB8118E459B9F3A82ADE6A27D05F1F -:10899000EB3109E328827E5B0BEBCE03393E401EB0 -:1089A000D54B9ACDAF9E298FCA1FBA11F3A8FC9F51 -:1089B000368FCA2A9807F6586B361179559644E7D0 -:1089C000D1CAF3A2FEA3F5A5B9A09F5AFDE2FBCB45 -:1089D000734D7BD95A7F00CB3CEF6AB4B7BD09EA2F -:1089E000E78E26759DE8CF33C93536391BF1AA08C5 -:1089F000E77FD6CC7735479E7CD4115F3AF0E666A8 -:108A00001FE86FFAAC2C02F851BA02BB3D2FD54ECD -:108A1000ECFA483C051DB5160F1CBF53CF5E847E93 -:108A20007C51F6E949D34C537FBE8FD91F827E7D9E -:108A3000B924097AC967241EB809E83937140B32FA -:108A4000BAC438595B08DD53FDD6D1567C03C6DB6A -:108A5000CEE804B95ED071FFF95FC6E75F64615C80 -:108A60002244309E96791D65B88E559A19F6DAE043 -:108A7000987B5EFABCD4BBBD6C3D2DF1E52CEFAC10 -:108A8000DA198715791AA27E504A1478411EE6B287 -:108A900038ACEC63FCD6872FAA2A6CFECD26B2DC5C -:108AA0000212509777E2D146554F62FD127FE27C69 -:108AB000AF233ED7CDE2BAAE78E27CE516C6DF83BF -:108AC000E04F9CCBD80A71B789109F8BF2F37D06DB -:108AD0008FD3992CAF28033DB5150F1C87EA688CFE -:108AE00061FBBB1ACB59BE9244B85F3BD9047402F8 -:108AF0006E0946F73F6802BE092B822F7E88E53B50 -:108B00002556BEC9FBCC5CC8373CF0E61B55AB28EC -:108B10007DB49A01E4FFC1D6A72767205E873B4E4C -:108B2000FFF5B271DBCC10EE77075BB79E62E30E08 -:108B3000751C115FEB5B9F0FC769350619A7838D05 -:108B400033F8FC199FDCB17F35E62FF828FFFBE9ED -:108B50007BDFEC1E9248D37F16E79F036F7A515E4E -:108B6000B7E5B2FC284F49C8644E4067FF9ED2BCAF -:108B70003978DEA1EC02CC9FBF637F3BCA190DC6DA -:108B8000A1553CB1D04AD62E61C239DBC83C82F136 -:108B9000674F49DE2A78DF403AE273400F97CB2CCB -:108BA0003FB9A4E426E8271BF892CEA3DCC7F69DC4 -:108BB0009E928B6F86FAFBA7BF9E68023895333A68 -:108BC0002007F31D706C358AC4B99D01F9DE53EEA0 -:108BD0008C5B109F33FF93A84B306E4EE54287D7D6 -:108BE000665752BD781FF23329B3C0DEDBFEB56B8A -:108BF00063767EFE672DFE1D565FE46B093E4F9F38 -:108C000037D79A2BF2E6123EA50CCE29F5E6532F64 -:108C1000CCB7E77FF17CEA90C8A7E6F1CC0EFA5F0B -:108C2000BAFC39F739C6CF2B9FFA292FDF0F07C9B6 -:108C300058C8A7FE8987C4529017F36B250679316F -:108C40006EFA70F7E73E07D06B8F64E0E7F7013804 -:108C500036B9979F70E1ED463FC6E7C478CF837C75 -:108C60002A1D9C4F47573BFB195BE73C9F755E8372 -:108C7000335E55681538EA9FDF56E4F83EBEE302DE -:108C8000C7F789F74F759427252F76D4FFD29E39E1 -:108C90008EF2E4CE2B1DF52FDCBBD851BE28B5CC0F -:108CA000517FDAC11B1CDFA71F5AE3F83EF3C87AD5 -:108CB000477956F7371DF51BA87902F92C7040004B -:108CC000F7ABDB46CB76FA6CCFA67A250BF3B8353B -:108CD0009ED48FF166968BDC9767E06EA7146BA627 -:108CE0004EF9573126CCD331CFF046E423A5386F67 -:108CF0008E81EF672C00BF132963E7B444FCDA537D -:108D00004C527EC8EF0BB9F0EB8A4B7B946D29C0B7 -:108D1000B376F4CB07A5487FBC7AA2EE7CC6A1C58A -:108D2000B555E3B3E507E4F9385F8CA57C817EC4D3 -:108D30008F15D8B7907961B40F6CFB1B84A3D8DF73 -:108D40005CE623CD0053C11715CB7B46BF80D5C44D -:108D5000BEC62B0F272FB9BF5EF1A2DD25E4CC6084 -:108D60007A45494E73E421B89F54FE95F9609F1EE1 -:108D70005986F2A8775FD02B1FE333E1BB478DA163 -:108D80007CEC957F7B0A1C7261A8F6995B4EDF052F -:108D9000421FCF05A597D711C80BA372E9CEABAF81 -:108DA000C23818A9278EF3807955711FE83D6A975C -:108DB0007DC567DB3F47CA997DF6F766A78660BD2C -:108DC00036F927EC5501D7118575718CEB85650255 -:108DD000FBAAA6D9B128F801DBA08A6D9FF65DDF5A -:108DE000F958BF39A4C9E02F6D3E381FE3035E7FF9 -:108DF000DC0779CE4D9E7825ACAB295BD6D3E53B1D -:108E00006DF631FF8CD6109CB67B00FAD034BAEFE9 -:108E10004FB3DE7FF131BF4BB3BEF820E8B99CB051 -:108E20006640FE44EBFE598B305F77A1AAC3BE9625 -:108E3000D04DDC3BB6B8222171F46769B932EA45FE -:108E4000AD2182E30F36DF5B7DCCCFE06DF00F38D4 -:108E50005FAF96DE4F9169BE9B61BEB983CFD70BE2 -:108E6000F39560FC108EBFC9C7F0E886BF87986D88 -:108E7000F368BD96635FEE28468A61F97AF72E9C07 -:108E80008A744A05B5837EC53E82D2EFC340BF6275 -:108E9000FF2ECEB3DEE263790902AFC460FE881113 -:108EA0000915F7BD3909B6FFED931F8C8E723C3161 -:108EB00082E7BFC6A8189704378DDD8FA1F8D9BE09 -:108EC000C77B690CF1D5FE15956C027A2BA6EB8158 -:108ED00073B90759DCA9DD13AB8A87FAC613EDDF36 -:108EE000E1FB40952CC9C27B529485D174F6672F63 -:108EF0009D73B8B9E5EC011FCFC3CA27F94CCE96D4 -:108F00002E85A34499FA71DB1B0DDCAF3CFCF329E1 -:108F10001D08CFF631F7A11D2DFC63245A3688BFFA -:108F200087C54BFBF0BCD448513CAA574C45A75FC2 -:108F30007B31C7739D2B9F97E359E057F8ED493478 -:108F400017F95AE05B017802AE94D9D181F495C249 -:108F5000F9C60DCF53FF4DE17904D600743B96AEB0 -:108F60001FF8E6C01504E3602E7E14ED04DDBBD7C8 -:108F70001FF6FFF75EBFA087CCF5ADB4FB0F11D78E -:108F80000D737AF371BDF942F9DB6D709E44CD65C6 -:108F9000FBDD7079F3AD329CC320960EFEB5B03880 -:108FA000BF53E6BC7F2450EADC7FF85CF74D78F8CD -:108FB000FEA3DFFD2ADCCE12E7F9DDF377E36BAE2B -:108FC0003F7D1E261993DEEFEA8EC789F886C88397 -:108FD00015710084035DBF67961C47F95746CC9D09 -:108FE00069E4D3323FD30B5DCFF9314F225CA5A1A9 -:108FF0003FB6A02C5501E5823A12033D71F1F143D1 -:1090000024413BBD20C0E47E41595202BF47C149C3 -:109010009617B89DC72B0BEA93D24ADB38969FE987 -:10902000AD8FDEBC1DE5E37363595EFA6D15CC7E32 -:109030003B14BDA1A302C62D67F9E461BA5F84BCED -:10904000B1F0116F12EDADB26E027E54AA05AC30D4 -:10905000FD7EBC914CBD713CE47DF9F079B251C705 -:10906000E781B1DAFECB69BDF5850103FA6D290A06 -:10907000B0F3BD611FEEF7FF9CFD75F4AB9E6E8CE7 -:1090800062FDB66F9B685734EF3F817EC3A0392DD8 -:10909000C6FCA8A642CA613E874CF0731035662C08 -:1090A00086EF077E83F5142DF11B0BEC93651AEE0A -:1090B000EF010E104F68F2B37CB9CDFEBA68363CB2 -:1090C0000BC98A4569E0BD82EB1D4A518A96D79744 -:1090D00087A495A7942CF02797914EC873F7B424D2 -:1090E0002B404F93D5BA01E38CF1252BC07F3CA6D2 -:1090F0005A8F810F5D2B67E745043E3C7E127F222D -:1091000004F552D2AD74DC89011DC7293892C4BC64 -:10911000E58FDE9C99D6FEBFFD68057EDFD65879C7 -:10912000789E8D9F4319E2951B8BE73CE0A7E3BD3A -:10913000EA67FC9AA95FF11C6ABFAF723A39F0E6A0 -:10914000C451605F3664C8A356748AA7114C3E812F -:109150003F62FD78635476C8DE0F8387F2DCB30C80 -:10916000AFA58C3E9B7E3C310BFA7DFECDA53AF837 -:10917000FBFE945B8CFB86534F7B4DB05F4EE590BE -:109180006ACCB77C7AE68BB03FFC43E3C11CD526A2 -:10919000174FFDE895191EDADFA9275F99A1227301 -:1091A000251D76ECBA73AFCE003BC19A434AEAE87C -:1091B000B356D708F45BEB63EB107972DBF3B4566C -:1091C000785E19CCC6F679A3E43BA1ACF85E1DF736 -:1091D000EE345C378B2BF0380E5D5F5308E95AA7ED -:1091E0001B1088175ADE7110CF7AD38BF4F75121F8 -:1091F0002929BC10FC820AB6EB594D92904FA1A5CB -:10920000EA803D89FFE52401BE09BEA6EF475AE387 -:10921000F7C1DDE9E7F90F3C8F70E39BB74F04F826 -:1092200008B9AECE2518CFE8F99A2F09F6E83DAA7D -:10923000F19DE560075EA7E23C6819CF1BB9F1B369 -:109240003C58E488E3E5F0F884C06B263AD9DA4864 -:1092500062C514DE3F6BF4C560FC7D8D3A967FD20B -:1092600018C5F2DE46039F4F3796E0B3AB3186DF79 -:10927000F73496E353E4F5E1D65E417B3A5E017A3A -:10928000E81AE687D30DD9847C852C95F8E0BE26B4 -:10929000FDE8BF55C17E1BE44A560EF2BD04ED73D6 -:1092A000799EDFC8FC39ED15469F7C15F2B4C943A1 -:1092B000249047D62CE66708437FB47DEE1242DE49 -:1092C000B6C9F573F49FB74BF8FAE87CB24CE77770 -:1092D00077FD884A1790D3BF1D958B58EEEB373D2D -:1092E000FC86FB047FF9DB36FADE3E9DAE9AD2D1D6 -:1092F0007689C9B13BF9F73BA6CFC8BA01CAB366B4 -:1093000064815CDF3E8B183A85E35D866C79B2FA46 -:10931000EAEF683C98376F3CD74120A7EAF59D5BA0 -:109320006CFB9831165911B7D1CB5D756AE52EB437 -:109330003312F98B2763BE31F76BEF9E678EC17EC8 -:10934000B13C21F0E23C8BEB159033979D657AA8F8 -:1093500057FF7CCCDE0BBDA771FC6F9BBD4989001C -:109360009F803C057959962073E83C4397B2F8F703 -:10937000AC775304F2FBB4187D0FF6A8C6F24D0A81 -:10938000A24909CA3FF2C7670620EF3DE7FED42E87 -:109390008AEF0FBBBC06C41BBB9EFB0BE6672853C2 -:1093A000341FF077C1BE6398B7A4C8DD1AEC789774 -:1093B0000526CF57C19E8589607C802A6A8A6725E9 -:1093C0008FAF8F3CD5322F04E7BE1227ECF5B707DD -:1093D00012B7B21D33317D51CA0F7ED1FE82168085 -:1093E000C7560F2B2F0B4C6AB1B04CEB67B37233DF -:1093F0006DBF35BB332A6743D2D4C4968397425995 -:10940000D49FD862CD26E41AAE0F48285108FCDE5E -:109410005BD669396C2BABAC4C7CEC29D6BBEEC06F -:109420005F5E1C4DE150B34FEAC410DFBE9D12AC2D -:10943000BB60EF4E94AF054982FBFE82A49484A3E7 -:109440009D7B1A0FEACDC2B926F04245C3A428BBC2 -:109450005F484B7A62B0BD9CC4EF0F1174F17490F9 -:10946000E9C74949DADE1E9776DD273289DF57835F -:10947000200579B98D9D0776D37929EFAF81585BA7 -:10948000E03C2E79CCA3637C9CFBD94F0ABB89FBC3 -:10949000736EE10E3CCF262B7001C8BF952AFA816E -:1094A000D7162637521B8AAC7DB630462D56D2E2EF -:1094B00067F4B236BB336F2AC5674BB6B3DCC4F36F -:1094C000E7A3D956369CD7ADD97BF738C8EFA92189 -:1094D0001DD77F13E6FB328B879FD83F2BEB125AA9 -:1094E0005EF7328B63ACEB7A4503FABE27C0F38E8E -:1094F000BA2EBA12D657B34D267221E34B73229D72 -:10950000AED971019CAC7B7EEB5BF3FD630979A462 -:10951000C8D4E58B08E90E9E68F151FC3FA2E9939F -:10952000803EBA833D2D405F6B67C99C9E7A5E305A -:10953000559EFF5800E35CDE027196DDCB2AAF0436 -:10954000732B4F66FC4B0912E3DA4A76B30FECF942 -:109550003FB6C8683F838B7403857BB14A0EAAF47B -:10956000B95DA3F8043E6B55511ED2F76D1EC44B76 -:1095700007DE3342DAD83D2DE3F77957829D5D5CF3 -:1095800067AE467B5B2F453FC038D2FB837912E73D -:1095900011267F27EAA442A5F566050B117FC55564 -:1095A000D7AE85764A784900F83D4F495AD8FF77BB -:1095B000991CDE2E273B7D2097234588DFED114641 -:1095C00017D63DA54817BBE53917805DD422ADDC21 -:1095D000F20BC06B76119E7B85F7EB61FD1C9F4DF6 -:1095E0007ACC07F8DBCDF1A9EC942DC8D714EFB7EE -:1095F0004A37AC06B89ED8523FDF47E19AE735DBE1 -:1096000046503C1CDF52DF129D857828F2D1EFC70F -:1096100003F52D3E8A97DD1BCD02DD569EF8099598 -:10962000EA48B4F52DE66CF09FDCB7069410FDFE19 -:1096300002F83F1EC9117CCFBE1717F5CA1113ECF3 -:10964000D226AB4FAEF8A85E28B6D59F47E5C20F2D -:109650001E5210AFFF4EC7033941D76101DDF74CF1 -:1096600052D12E08D0B904683930B908F36DE9BA7F -:109670004900EC86C92AEA7911C7D126C96837435F -:109680007DA087407E11E6CF51791D87733E4A94B5 -:10969000C5751465874979980479FEBEA42FC2FB6D -:1096A00048FC25B6BC0290BFAE3C04C5551EEFED8C -:1096B000CE97A97ECD3DBA481A47F1F25E80EF8B76 -:1096C00072E93E96BE7F3FC0FC40B7C7AD2F43BE98 -:1096D0000C31BAF3593C2A3E159EA3AE2B1E359091 -:1096E000FFA5FF7E3586F6CBBD63D4B4F960FF1AC3 -:1096F00064FE41EFD862BC57A38150FE07BE08F15B -:10970000FBF2B8FCF0707BC17D4E40C8134F365B56 -:10971000637DFBDC5139A1BE73704AC8F4813CD82B -:10972000AF4FCD027B743C9753CDA9595F05BB4524 -:10973000E5F260879F9DCBEDC9269DBB08D8BF3160 -:1097400062CF4B10F2605BA30F9F0F5F3601E39770 -:109750000F5F963707E215072E7E1FF7BF6776303B -:10976000FE3D73E805B84B899CB1A8B6311859A1E4 -:109770005F3E752FDE17F27D357E17E6CB43BE0EBA -:109780009DD25DD9CE3CCC47395CCE0578DE808752 -:109790007D17F778A867BF847EE06D7C3DBEC43C32 -:1097A000DC57821B0FCE1DFB4907DEC724E0E0BE5D -:1097B000BF433D3B85F9EB036C5F2AF297DC794AA6 -:1097C000623EFB8219EE3376E143F835041E44FB1A -:1097D0007AC91CA50F4037B5671592B4E585F49D8D -:1097E000DBD0F0FD6938EF9205F7AF243A2E29045B -:1097F0003E48A29DE80F353BEE712551B5C77EBEB0 -:1098000024E83AEFE2E617B83F18F4B4660C7CAEF1 -:10981000E57DBACD1579B998A7AE9207C0AE3D15D2 -:109820007C6B06F8E36AA998005739512D3C4F7AB2 -:109830009AEF4BD47DB7E2791E313FE18F13E59A61 -:10984000BD8BD04F57BB3B84E7796A924C0EAEF389 -:109850005907BDB23DEFD64C41BEAD672FEB6F3C13 -:10986000E080D2C7877A753EAC3FD870FE4C38672F -:109870009227D79D370EE0A3323CC07EF9C9109ED7 -:10988000D355BDB6FB53DFE2FBE365DC1E09124B8B -:1098900006782A8158376167164D95DA474AAFDC5A -:1098A0009BDC02FCB0DD656F6D0FB0726B70724BAC -:1098B0007329EA67948BCB023F437BA8C52FCACF9D -:1098C000A29CDCAEB1FB3AACA7BD06E83DDA1ECFE8 -:1098D000A75BCB4A507F2845A400E0360F1C2D2003 -:1098E000FF9EF6EE023FC38FFC896B0236B89D0ADD -:1098F0001F1907FBCA34FD598EFEC60DAF3F3A7ED5 -:1099000017E0417C9F17B91FFBA7EDD0DF41C61CB4 -:109910007A8BDABA24EF692F9E33DCE171DADBE26D -:10992000F920E7CB36D7BD1DBE44B3099B73C19F59 -:10993000EE7B9605BFAA672739F2A4C607593C5BA0 -:10994000554D7055D2EFA5EC7B80D1411BCFC7C9D7 -:109950003C4E4E86719C71BBFEE3CCE07282F07D82 -:10996000ACAAF7DECB3940FEAB3BBEE8966FBD4FED -:109970002EDFF2393DC7A5C4B3415A5E93EC5C10AB -:1099800060FC3905F87335A7D3923D773F076AFD30 -:10999000319FF967D837ACF2991704A70F9F7FBAA8 -:1099A00083623DFDE417B3CBAA999D5BDF3EED4A90 -:1099B00028D7DF51A45B69E245E2597D36E8905F24 -:1099C000F7707F51B56AA11CAB3E1BC1EF9FDF78DA -:1099D0007EC779B6FEE385F0BB18EF16977C3E7024 -:1099E000F14BDBCB291DD73FE191BDB671EA9FE07A -:1099F000E780FC545E3BF9DD047E570B496F9E22E5 -:109A0000C887BB3451565AC12E7AC42E1FCAC16EA4 -:109A1000EB6B0FF716DE15E0F5AD60FAFA4157FD76 -:109A200022D17F2ED677CF47C81F28839DA67EE2FE -:109A300015F343F975B7ECEA2F478C3F06FB13F695 -:109A4000FAB703E35F843B25EECA4E568C66FE1DD3 -:109A500003EC80EFABB180FD3EAC6F737AAD3E7B23 -:109A6000BE03DF7D709FE078FFFBC6A8235FFFE6A3 -:109A7000443D9ED3F87680D16535B5E8B1DD8ED111 -:109A80008E3CFD7FCCE3D3CEE3920CF3B8EC6F3C7D -:109A90008F42077FF6CDA3D8F1FED3CE631FF70B1D -:109AA0003FC79FF375762FC07C4342BFF57C5AD7E2 -:109AB0004F69FDCBF4E9A3CFF92AB14278CF6D927B -:109AC000DD6346CBE00FF8EA27B7BD7B39DE0B6DCF -:109AD000623E8E57E4E3F0731E9BC70C7C5F91FBE4 -:109AE000EF3BB8BF0733DCD3DA1862FBEEBB2FBC09 -:109AF0008A60FE7A28817182FDF90BA260A77FE758 -:109B0000C21A7C36E7CF88823C6A0A7FDD916F4EAD -:109B1000F70869CFC1FE91F74BCE7E59B69F47D962 -:109B20000CE751D2D41771B1CDBE3ACC03FFA2D607 -:109B3000FBE017B4DE4BC38CDE36FB1218176C8DBE -:109B40007E31F37F26C4C6B9FBC2CB089BEF6529E3 -:109B500016F7D10CFB7960F1DC1F9E118575366517 -:109B60002F88023D3767CF70AC47C9B09E5561065C -:109B7000A7CDFA17BB9EC39F793D0BD2E6C1AAB908 -:109B8000E9EF176B17788A2690CEBEA8759DFA1B51 -:109B9000AF6B14C7577588F90D361B8C8F824AFC42 -:109BA0005785D2E07C38D8DF1D21C5863C943CBC6B -:109BB000DF727865E2DF659EE44898D79146B67F0C -:109BC0007E9DDF27F5DBEAA630FAB55DE36C1EB3B8 -:109BD0002B3C909FE37F563BCFA70F26375A422C52 -:109BE0005EF3B584B3DDD2AA60DAFB4D28FCEE2A21 -:109BF0002CEC83673FFC7FCE70CB448FC3855B6BBF -:109C00007478701B8C0FAAE1929BE983C34DD05BE3 -:109C1000A67EFE7FA1B307870E2FA4AFBF15BCFEA3 -:109C20005EE9EB1980D710F8F21FF03AC7F5E6D0DD -:109C3000E025E4D81E8DDDBBE8EEE74498DDAF34C7 -:109C400051AA3B7C05C417BEA2A0BFF7F08E79EBEA -:109C5000886CAFC7F4D9E1CAB9EB30DF351EC47BDD -:109C60003C5F9363FF5E067187C5AC5DBF7972F898 -:109C7000BC14CEE67E4B6324F8115E8B5F3DE0FAA8 -:109C800048A56D5D989769BB8F4AE90FDFC3C4B8DB -:109C9000A30CFC4D0BD3CF43E033D3B8C3C5E76B64 -:109CA000F1EF0F0B9F83ADF7D970D190E485D837D2 -:109CB000E492DEBF977101C0738FCCF2398EC2ABD4 -:109CC0007CB89F8C60A5A555A376029ECA223CEF66 -:109CD0004933D6819FCC7BF5C2AD618AB7D7AEC977 -:109CE00096BC367879230CCF3396A7B70B73233CF9 -:109CF0002FB7B7BD44E03E44773D85D7BB6639BB3F -:109D0000978AA8E6D8C5B67375535CDFDDEDC74604 -:109D100022F8FD351E6F777FCFE2ED972E19B83D03 -:109D2000A963F7B950BA1B9BEE7E41C11F9DE14468 -:109D300034429FAF4B8907BF01743429C4E21E2A05 -:109D4000298478BDE8275725298DC2FD5D8F3116FE -:109D5000FCB469FA291CA89F4C7015EB11E3002B89 -:109D6000C2BD2C74FF88FBC5329390D9B04FF4C6A6 -:109D70006E65870D191DE4F0FC999975C1E446B034 -:109D8000F354BA4EDB7CBBFE6BEEFF80EF5D876564 -:109D90007D53617F380C261F1670BAC955129BFC83 -:109DA000E01F5B21A5BDDFECF208FB3B251F847B98 -:109DB000E3EA38CE84FB121EB8E7E05A9EDF44483F -:109DC00062ACFDEF8C7DC0E58ABB5DAEC2E2D1E442 -:109DD0000DC6CF7B76AD199B8E7F5EE57CFA41B8D0 -:109DE000C4919FB4247EAB07F873C9C2451E2304F7 -:109DF000DF99BCBC86CF638F96187B51A80F4E1994 -:109E0000E510874FD7914413DCEFB0A241C238521E -:109E1000E90646772B36EC97D7D1E74ECE7F8B00FD -:109E200007B6FE6EE578DDB32B300EE6BFA7D74F41 -:109E3000473BA6F3B8FE7E827EAFD591AB3683DF7B -:109E4000AB5B22FCEF32FCA412F20DBA799E480BF8 -:109E5000FDBE11E63B6F24F2F7840D1FD4837CEE28 -:109E6000D2089E97FB8F762FFE7D0B412FBD72622D -:109E7000C3478D907477AF969A0C7433B2A9EE1BDA -:109E8000E9FCE416E7FB0F43F1AC7476AE780A798F -:109E90002EEA2D560D4FBAFA57573AE59898F7081B -:109EA0006FEA54BAFB1A7AE93039B0DEFB3597E332 -:109EB00002EFBDF83E927E5FB423C2E2777B9273DD -:109EC000D6A2DEB2BC06C843311F01AF5C8BC1E92C -:109ED000DA258A43DEAE5818749D476270FDAAD712 -:109EE0007808D671EFAE9726E3DF5174E987809248 -:109EF000D0E0FBCD24E50139715C31F0F97AA3F3B0 -:109F00005EE6D749E28EE9A03F1B94B47CF50CA72E -:109F10009FD7AB565D83F36F567498FFB1E523AEC0 -:109F20002A07F952E5C17B828F35DF16BEC9B67E9E -:109F3000A1EFDCF3FA6DF5AA01F5D6D22A27DEF6F9 -:109F400068CC2EB0AE647CB89ACA9BD9485FDD77E6 -:109F5000CCA4E31F4EE65CB4855527F0F71CAFE6B2 -:109F6000BF1F971377CEA4F2E684CCFC61D63F31B5 -:109F7000B9B1E4BE780BC4794F344CFB6937ADF707 -:109F8000325FDF5B0D03EB47373D4DB8CF793FE5DF -:109F90008C234483F689FAF4FAE0FAEC2093AF6A52 -:109FA0006C1CC897EB36A4AFB709922B69BD137F21 -:109FB00055AAD3E56D7EA2333E59114FDFFE133D06 -:109FC000CCBE835E4A03E7BD59412EE7F47120A75A -:109FD0005764986F575604EBBDD372FB7510EF3B77 -:109FE0002E3BE5F30FB278FC3C8BC9E713BB9679A7 -:109FF00046029E5A251DE8E1EDECD824A0B795CD88 -:10A00000C7D08FF02D5EFFBA50FC43D04F4B8E2C43 -:10A010009E3F92E2A56B3989494666F9FF31E79F79 -:10A020005C85DD6340F5DFBBA0FF68D377D1FE50D0 -:10A03000CD715F9BCCAE6C84BCC213B2B506F3503D -:10A04000760558DE11894DB7DF2F13E0F338B17B69 -:10A0500078F8BE261E1CD08E3F4C3A6A70DCDD417B -:10A060001DE28F872B95D4E57492EFED0EE23DAFA4 -:10A070006EBEC834FE70EDC013BB8767070EB6EE28 -:10A080005856E190ECC03395F7DE59067CA4754C28 -:10A0900049277F859C7E8DFBADDCF4239EB3393E42 -:10A0A0008E27079ED7CDF73BE7735D9D733E825F9A -:10A0B0008E279B02901F4E479F6CB74BC9BCE9830C -:10A0C000E859E6FFCD34CF389FA790134079104F61 -:10A0D0005BCDE5CD5B0DF746EC7870AFFF84CCF738 -:10A0E000070FB1BCADF1F19573461A7DF4795D1699 -:10A0F00093439F375D0A3DE3EEE7EF9D0E859E1B80 -:10A100008C0E855C70B7FF00E2FC23E1EFE3E81AF8 -:10A11000C4653E8818AC4CF40570448694F373CB48 -:10A12000C41807E76E4EEC0AE0FDF6D6166F12FE75 -:10A130006EC7F15D974CB2AF6707C7FF8A25D97824 -:10A140005DCA713976C528CC2F50F0BEAED78FE4EA -:10A150002C80F2BD876490D0E4BAFA950AACEF8106 -:10A160002C9677BE62C32B680F0E97CE57D439F565 -:10A17000FF277C1DBD7696DA5306F493090EED5940 -:10A180003EB6CF892F9A0FF279D50609E5ED962CC8 -:10A1900003DFAF524D94DBA499E947E2A3F0A02A74 -:10A1A000E4182C02E0F1BFF9DF2953E39AFD7CD2D9 -:10A1B0004DDB6E9F0FF6A19B5F46EB8C8EE15E3010 -:10A1C000785E174A3C9935B24F3EBF2DD5ED1F45FD -:10A1D000AB5C9EC5ED6DCEA7623D9767B1F5513B77 -:10A1E000ED87F8F799F8FA48CC456F7247CD4F00E4 -:10A1F000FE737C681704BC54EE43DEDCF7033ACBF5 -:10A200009B637C25EC1D77FB6BD584C36E3C94551A -:10A21000E8C8C771DB21FFD017E9EBFFF96FAC2F5E -:10A2200064FDD3E98BFF0779B222080080000000AB -:10A230001F8B080000000000000BDD3D0B7854D59B -:10A2400099E7CE9DB9994966924932933738930080 -:10A250000625780321449E370991A0A803040C1A0F -:10A260007044D4282144C54ABFD2CD0D893120DAAB -:10A27000505DB4D67587885DB6D235586AD1D2762E -:10A28000B0828FEA365A45DA8D1A1FA5800FA2AD2B -:10A29000ABDB8FAD7BFEFF9C93B9F76626046DFBAD -:10A2A000F12D7C7ED733E7FDBFFFFFFCE7B0A22591 -:10A2B00085449D04FF7C49FF3B9C1A20C44FC8F194 -:10A2C000BFCA8DBD6E428E45DA93AF81AF4D5D90B2 -:10A2D000ED2344EF94C9A3B4DD3B473EAD81F2BD0D -:10A2E0007D36AF44CB2BD65F238769BB4C28F9A1C1 -:10A2F000DF9234287F097FE60EFFDEF0804CA2C596 -:10A30000B179AF867518CAC77A923502F3CDF14498 -:10A31000C60709D9AB109D9411F2F6E6ECC8265A8F -:10A32000AE7112DD3D8590B9696CBDBE8D9FB77A67 -:10A3300027D3F5F4FCBA8414D2F5DD7DFB8AF0A4B2 -:10A3400038F37B6D844CA3130402369245C86D7CB0 -:10A35000EFAB528906E3133ADFA386F145BFC3ADE5 -:10A360008444CFA5F5E368BFF2583FEBF8CBAEBC11 -:10A37000702CECFBF09533C75E3329D62F111C9659 -:10A3800049E17F5E0AF3B6C92AC075D73D498D3DC4 -:10A3900071E0A673B85AE7873F76BA8F25FCFF971E -:10A3A0006EACBCC34341B22965CEEC709CF90F93EF -:10A3B000F0DDD3E87CFA46369F759EC57C9EC3F5DA -:10A3C000D72E05F87FA6CB5E99C263A0414EAD8023 -:10A3D0007EF50E753C1D7F40BFD5739D619DBF4FBF -:10A3E000009FDF375EEB898B07FEBDA2DE4C076F57 -:10A3F00093C197A7C33C3BE3AFEF16581FC5DF31AE -:10A40000257CCF85747DC72F96559DAEE7B88DF618 -:10A41000037A7990F60B0CEF773DEFF7F6C691E9EA -:10A420007249AD793D4B8F249BE9D2461A7BE3EC10 -:10A4300067685D6748F72B2CFCB74B191CE3A5FD3B -:10A44000DFDE71EACDDB613F3B9211DED67132D3A4 -:10A4500065C6A7C02700AF2D499C4FBA9B9FA6FD9C -:10A46000DEBE344FDD4486F30721DD97CDA0F5FD38 -:10A470003DB6D22DB46A574F4A6324CE7A27A7330C -:10A480003AF0C97AF279B43D7983E103C80DF866F0 -:10A4900029A7376FCF0F5B882DD6EF0DA0832442FD -:10A4A0007EDBEAC4EF36AF13C7A95BB84809D079A1 -:10A4B000AEB3130DE0877FE8B8DEF30A766CA153E4 -:10A4C000BD6E63657D15E53F69F87A1EE674B92BAC -:10A4D000B27844F8D637C82678D62D34C3D74A9FE9 -:10A4E0004723B6DA78FB17F49C68BE2B1D113FE0BA -:10A4F000E908DFEF61BEDFDF37B67BA0BD759E5D8B -:10A50000919E11F9E0AA46335D9C6E9F6F7A830895 -:10A510008FE56173BF2BEACDFB5D4A5A66134A2A69 -:10A52000CB88EA806F1D6929799A82F2E8034B7023 -:10A530003DAF13520B729E9CBAB56451496CFC1727 -:10A54000393D7F5677EBA5202EDF505A4ABC71D695 -:10A55000F33A8793C0F7EB09E019E572F70DC033C2 -:10A56000D0EB32392E9EFF8BCFFB46C3C87CB4ACF8 -:10A570006E643C9FF07A113E6F34B427C33E8F89DE -:10A58000791F64F3825E33E2E3C457D45B56FE1D49 -:10A5900020FA4D48C791642FE8111F9087418F74AE -:10A5A000A4DB981C2F1E598F88EF6F855CB5B4AF64 -:10A5B000B36B0E233ECABD01849B28D72D34AFF365 -:10A5C000BD54060FCA7163431E83DCE0FA55E8BB35 -:10A5D0007B7F70FE5BA03FC7A7333CD4853E7100F4 -:10A5E0003CA87CBDC303FB7AD5E605F95A7E4473CB -:10A5F00018E137278DB53FBE7364F8CD4963EB3C56 -:10A600009D9CB5EEF7ED6FDF3905C67DFBDB9F3B0B -:10A610008CE32FFB229F443363E5ABEB252D1287A0 -:10A62000CF36789551C17D83058E577F3116C7F798 -:10A63000C9A4A537CEBEECE94E6CBF3454E9F05343 -:10A64000785EBB5152253A84239DC9DD6B85BCB32E -:10A6500007C62EA270F7B7B7DC168A33CE6C0EEFA2 -:10A660003FBB4369F1F84C7C853E17ED96D9C38E0C -:10A6700078EDAD7A7580F3B9B55DE80CE971C80E77 -:10A68000B2B41FED3AE6A6313ACC4C8A7E04F28889 -:10A690004C32DB61A79DD7D2DE3AEF651CEE89E62E -:10A6A0001776AD757C9DC33F1CA2F413B7DE83F50E -:10A6B000AF12A65FF5480AEAC3633BAFBD07CCB74C -:10A6C000EB17DC7608D4E4CBA9416CD7107AA50649 -:10A6D000D9EDD4BD9301EF9FD5DE7B4F195DDA71C3 -:10A6E00025DCEEA11D8E6F92D06EB1CEF32AD72756 -:10A6F000AF813C3D17C623CC5E9D4747CBA56097F5 -:10A70000B5352054C8B79202463BD5B7E1F356326F -:10A7100019EC87D0260FFD7DC2C64FD6835E262456 -:10A7200082FDDF75A83722BC09B373FB7BDC3BB627 -:10A73000D076AF825C80F1893A3654629013762FDE -:10A7400096478B9FDF26C0CF99CA29B1CF44F350DB -:10A75000C8E3FA1657B9BBA434B07702D7C17E0656 -:10A7600017B8BC3D14858B15ED1280CFABAFD86CFC -:10A770006D411C16ED15611F072F0BDE755E19C8A4 -:10A780001F87E6A24B5904CECB85948EAADC3A8C67 -:10A7900057F6DB858F017EEEAD4F0AC830DE9CC0D8 -:10A7A0009B322D2FBE3829007E47795FE1011F1DA6 -:10A7B0007FE942C94B68FF790BC6FB07E8FE5236BA -:10A7C000D071F26079C76AABC711F243986C066129 -:10A7D0000BA6B0582CF1B2EEDB3C8FB63FCFBFD703 -:10A7E000E6A6A09EF85DDF66271DF78EB6508E3771 -:10A7F0009DDA13E91F743967139295A5F5CD5509B4 -:10A8000071677C540BE5BD0F8AF13EEED20A08F960 -:10A81000992D1C9468FDD48CA405760A2F5F91981D -:10A820003F6FB3368BEEE7E21B1F5D4FC75FFEDD68 -:10A83000490BECB0EE06317FE90258DFD259A25C39 -:10A84000EE82B22F85F787F55650F955185BBF3D5C -:10A8500087CE9F21DACF58308FF63D5CD9526DA755 -:10A86000F3FFE8BBDAE649130999BEB0D2ABD1F2E7 -:10A870001319F50B52287EF6124AA7B4FC64C6954C -:10A880000B60FD3ED9C6C7BF6A33ACBFBC413F0FAA -:10A89000EA257DE5E65ABAEFB5CE814340AEEB3608 -:10A8A000E8CE2CFA3F2912E363A7A345CBA7B073E8 -:10A8B000ECAB8CE6E372BA19BD16444B408F0D9594 -:10A8C0008B69B9C450CE61E5BD9BC8D5F1E4ED6D8F -:10A8D000994CEEED4D8E5FAF64307B80C20DF54933 -:10A8E000DA11A2ED8EA3573E4A77E37C079389EEF7 -:10A8F000CC88F1DBE594872B285F12275BA71867CC -:10A9000098FEC8607287E89767803C5D0843D0ADC9 -:10A9100017A912FABBA42525321E688744ED4B40C7 -:10A920007FC8365CAF5F96AE5E44C7CB4A26E13D3A -:10A93000F4EBCF2458A6FDB53DEED8782F71BAAF11 -:10A94000290AED84F16AB2734BDB83B171E8BA3B3B -:10A950009C534CEBB6576440FDE2D29B2719E0397B -:10A9600089ED83D201F6A3D33C3697F2C1DEBEF364 -:10A970000AC17EFFA945EE96F72D7610DAEECA4C95 -:10A980002E5F02ACBFBF9AC99FC19B53223DC09F9F -:10A990004EB53464B03B031C1ED5772EBC1FDA3590 -:10A9A000F53948126DB77E4F653619412F367D3126 -:10A9B0009344A61ACAF6A80272A7E98B39F87BF568 -:10A9C0009D2F29C0A7304E80EE6BBD4BCB56016E3C -:10A9D000EDF1F14F1D725C47D317E9449F6AFC9D6E -:10A9E000C12936BE0FEB4FB7AFD8783289648E34A9 -:10A9F0009E82F54370B773B82BF1D7395FD02985A4 -:10AA0000B7CD405F4B39BD51E9877194FECB26F538 -:10AA100080BC8FCDBB09C7DF6BA778043BB02F3953 -:10AA2000007671B99DC9CFF2BE0CAF2EC5E843D0F8 -:10AA300085C0EBDE8C964ADCEF22C9DB131CBEAE70 -:10AA4000CBC4BAB83ECD6E08CBD718D627F8818EC6 -:10AA5000BF978F5F5681FCF32F4CFF50BE5901FC0E -:10AA60000B760BEC438D962CF60C5FFFCFA8EC8099 -:10AA70002FC52383FFA5EE08E80101B7E1F0CF3F22 -:10AA80000D3EC7627D79DF330AECB32901DF8632E0 -:10AA900053B15FF691682AF8B5BF4C677A6D6FEFD6 -:10AAA00054D74CE08B853602220CF60DF66AB9902D -:10AAB000B764D70B5576FAFB5099CADB00E06148C2 -:10AAC000FE469DCE58FBAACC5D0B3A689D2F89E2CD -:10AAD0007F12DAA14E62F027BE9DC1E4584598C4AA -:10AAE000B55B966532BB45C0FB7B1BAAC97B747FF7 -:10AAF000CFA533BEAC18D025C08BE06BAB9C7A8859 -:10AB0000E3F17BFCFB8F9753D269E4D4222EA7D8C4 -:10AB1000EF07A9990FEDB2B2A22512D589AB5E98C5 -:10AB20003A1EFC995B72E4C0FB94AF9648EA981F0A -:10AB3000D171EB9C018C93093AA923CE801BE04E86 -:10AB40008DA62F41EF2F746119FE805DF269B7C4A5 -:10AB5000E89004D2EA4A12CB21B18E5B72149C6F4A -:10AB6000D5E6F16961E3FAB89EB83C29FA2352347C -:10AB70009CCF4599AE7FAD4D36D4BB993EFBD0A35B -:10AB8000FD3483E2E15589D4E37A2CF6D26F78DC88 -:10AB9000C66A2FD5733BD20FE625F2B10D9DD3ECDB -:10ABA000AEA408615D74F053B37B09E7D7A8ADC9C3 -:10ABB0004007BFCE286076ED15B4F202CA94CE6A83 -:10ABC000ED7D831C7B1ED6837A213A0DF8F4A50C0B -:10ABD00062B2F31AE4508104766B76920A7286E2CE -:10ABE00009E170D045EC2E3AEF73F40B78AB916F1E -:10ABF0003EE0F0011D486A3B427F07F75B4914F4D1 -:10AC0000CDE57353D06E25A76E1D07F10A7F0AA309 -:10AC10005B3A8E938FE3443AE172EF376327F68015 -:10AC20007E12F253E0819C92713C517F505A54E065 -:10AC3000A5E583FE734BDB25B3FD03F650CC7E5AAE -:10AC4000BF793EB597A6D7F6466D5E902AB72FB866 -:10AC50009DB6AFA1F6938BEEE78F194C0F1E0CEA51 -:10AC6000722A8C379EEE83FE7428393CA9C51DC319 -:10AC700007B571C280BF2C857EDD8C3FE0DB99C9B2 -:10AC80009091E163DF06FECD4A65ED87E93D5EAF59 -:10AC9000490CDE5B2A999CB0B6B3F171D73AF5DA6C -:10ACA000AC42A37D1522408776C2EC2C19748F1F0D -:10ACB000F519C2ABFACE8634D09B9FF52D4D239368 -:10ACC0006272D4E1FCEDD8F7A91C899225DF017EE0 -:10ACD000555E9709D8CB7738185D2AE9616F06FD74 -:10ACE00066A6C4F79B27F2F564825F4DDBDDC3FDEA -:10ACF0001EC717E7A3BF9D9FC9E245A9397528D78D -:10AD00000196018AF73432A87B0D784CABB099FCE0 -:10AD100007C71793B1FF99DB0FA509EC873293FDA5 -:10AD200020E6B5DA116FB6E6E0FA45FF1539AFD582 -:10AD30001043FB9564E00E186FE5FA7C53BC289134 -:10AD4000FD3137531AB217F4B8EB524CBFBF49FD6F -:10AD500045DD38FF31367F6CDE14CA70B179E54CC1 -:10AD60004DCB44BF6F96F7E8F9F4E3A2BFCBA877C9 -:10AD700050FE53FDA4ED70A35EAA05B92DFC24E09E -:10AD80007F6F1AF077656DA6DFA027793FAB3C3A5D -:10AD9000C0FDEA035CDFA41D117663724092627A03 -:10ADA00067B8DEE276B1453E9ECECEA674AB1BED13 -:10ADB000806178CEFCAAF6655102FA98F00FB12FA7 -:10ADC000CB6785E512909FB512194F3FD3E799F5F0 -:10ADD000BD9EC9FC109D329CD16F59DC606ED701BD -:10ADE000EDFCF04D1995DF62D447920C728F8DD730 -:10ADF000CCE92178E2552540E57094DB43BB7CDA51 -:10AE00005D40171DC9A993414F74248F8D405C622A -:10AE1000C7FF5617EFA0EB1F7CD9A1F6C0B0FB18F7 -:10AE20009D542E5FDF6EA7BF3B7A256F1289ADD38D -:10AE3000BD41D256533EBE9FCB89261FDB4F932F79 -:10AE4000AA8CA3F3E735B17514F41E90EC0679577C -:10AE5000D0C8DAEDC87498F4CFA350A6E33C22FC26 -:10AE6000111269AB2983F69A1DCE41F27A258C0F17 -:10AE7000E7B55040507AC853D9F86E35225D3B296A -:10AE8000B6DF2EDBA249A027BAB25254D013277DD9 -:10AE9000E1C760BF4DFDD128806B7A7F9F1DEC3DDF -:10AEA000975FDB0DBF8B7D06646F1EC8D9947EB69D -:10AEB000BE6E0BDD1372175F570F93BF32799E0082 -:10AEC0005E4086D0F9B23615A39E12EDB332B8DEDD -:10AED000C822E127D0CE225D04F146701F599B267F -:10AEE000A0BD2FF01AB3AB264E01BBAA686BD4BE2F -:10AEF0008AF67BFAA1F8F1FA17399FD07D1C34EE5F -:10AF000023117F08BD26DA3912F8D582EE536AE3A1 -:10AF1000DBAB5413607DE572DF95B0EFA60E8524A0 -:10AF20004931F8BBFCA12320B7F27A7748001B2BEC -:10AF30009D7564FC50CAA7FBBCF546E29549E275D5 -:10AF4000376D90B5D5467EEE5018DD28E6F33DE12D -:10AF5000677CC2E305B3FDA163008FE67DDB14C00F -:10AF6000F38D3BDF51463AD7192DDCA446E6BF34BA -:10AF7000D53B23B0DFCAE576C4E39A0E2502F2A9D9 -:10AF800069F79EA80DECEC8D4405FE6FEADD732891 -:10AF90008FC227BF499B260762E3E5374524584FF8 -:10AFA0001625C63EF4FFA20AE86D2B7D839D0CF6A4 -:10AFB000CA2117E3FF0F2BDDBA44E1F8A123DC041B -:10AFC000ED3ECC4D51F5600CEECFED99FFBC4459F0 -:10AFD000DCF3445214BE5DB69E1C276DD7759EA24D -:10AFE000023DB9FC618F8FC229C31EDA0BFDD37DF0 -:10AFF0001EB58DF60D249129A8AF470987E916BA29 -:10B0000098BE91F1CB5C5FAAB003A7805C3AD7E70A -:10B01000117614CAAB430EB68F0EC2D6DB99A915B2 -:10B02000C07A883703E7CD6B8A4AE00758E78DD1AD -:10B03000955688ED47BDCE5E05E4FC1A2E6F2A9723 -:10B04000EF94DE33D041A98F9DCFE6EDDE21817FE5 -:10B0500048EBDB6A7CD89E2481BCD9CDCE29D6D0E2 -:10B06000FAEB0CF245EC238E9CA980F5B9FBFB9E14 -:10B070006572268AF427D66BC5E73C1FB3EF2EA274 -:10B080006602FEAEE8C5013ADEA1C2641C4FF0BD07 -:10B09000954FE7F9189DE7D5EF94209EE04B61F6B8 -:10B0A000A4589F68B7CB5755EB4338F4211CD6D62C -:10B0B000DB116F623D354A681CF865CBF878CF5CD0 -:10B0C000F1963240CBF7FDF415A4C7B5DD9286FEAC -:10B0D00042F72BCA5288DBE9FF2E439CF61266A288 -:10B0E00090ED3F7905F5CA257B59FC60EDDE3DF614 -:10B0F0006BDD313A0D9E786625D0D9DADE24E292F6 -:10B10000007F01E4532B9D523983744F7405CFB9EE -:10B11000A89CD451AE927010FC1421873B397F1348 -:10B1200037FBFD46BE6E316E4C7EBA90DE8327A69D -:10B130003CE3A4F05CAB4AAA0BF891C39B8E1F457D -:10B14000394C4821F86B627C2BFCFE99DBED71F0E9 -:10B150007C1BE0D9AA4F849E0D3E5C45E02BF06736 -:10B16000E7701FD2EF3E05D7DBE1B3333D5FC9E2A5 -:10B17000DA1D0EA6473ADA9C11E0EBE7D22F7A5E91 -:10B18000A2F2D293A144E17BD0B6AA09EA0FE6B1BC -:10B190007574D93615B7303D76870FF1974A987C8C -:10B1A00062F2E8BE1F3379D2A4BBD17F6C0AD7AD5F -:10B1B000C673099F4B857309127E5659EA89D1835C -:10B1C00015BF81270E28015A7F492FE38318DC9889 -:10B1D000BE12744BE51CE2BD33539C5F868300575F -:10B1E000EAD7B741FC41F8F5A90D21DD1318CEAF20 -:10B1F00099DCAF9FC6FD7A4785F36FEAD7AFD9F0E8 -:10B200006BF4836ECA7901BF825FA8FF68E2AB2747 -:10B2100038BEEFF731BDFA948FD1D59AB25EE4878C -:10B2200035EFB7201FB96B993C71F79BE52021776B -:10B2300073FB602B8E5393D27B910C7EF2BF4ADE60 -:10B24000769278DD37482DFF097932640FCFDF38E9 -:10B2500045ADFC720A571787016FF76B1FF3B73EB6 -:10B26000DC4511017C696F5146B2874F372E89BE8C -:10B270002601BED770587FB8BBFAC23F409C7157B9 -:10B280001AE6B37CB07BC937FF40FB7FB873AE0AC8 -:10B290007ADAD71E42FA19F4BB54882752F1592B97 -:10B2A000517A68EBFD55EA4C382F7BEC8229203728 -:10B2B000DFE57C79E2C7F20680CFA67F7B7C0ED4E7 -:10B2C000AF894899603F7EB8EB5FFF0A7AB171E7BA -:10B2D0003ACC4B6B7FEC976897DB223BD8EFBBD225 -:10B2E000D0CE3CFEC8B63900F7F6DE76AC3FF1C8EA -:10B2F0000E2C3FF36F8FFFE22F60778452556877F3 -:10B30000E2C7DBFEE92F40E775A92AECA3296C67A9 -:10B31000E7B982BEAD726BCF01E453412F9780DE57 -:10B320000538D533F923E8F95D7EDEB4AADADD0508 -:10B33000F2ECDD2D9EC6787146C5CFF002B11894AF -:10B3400063F512C6D9BA28D540BCA32B9954C0378F -:10B35000655254C9A7F35CD1B0670EDA3DFA3BD70A -:10B3600043FB25FB5C640BC6E520A84BFD0124755F -:10B37000424AA8183C4AFD663AFACE2F29DD1EA69D -:10B38000F201F58EC51F58D2F5C2FF801CAD730EB9 -:10B390001C0051287EEFE2F11BDA1EF54EF9FAF897 -:10B3A00071D254BF9BD32DD39B797B171504504E7C -:10B3B00024A9E30DF6E998232D5B203D29AFB1EFD9 -:10B3C00022D8C7C5C5D74C45BA80F81FE81FDD8D08 -:10B3D000E3AF85F825E5BF73FC3C2EE225BE19746A -:10B3E000FE1A3BF1B9E14BC86B0E94238FE2B8D43F -:10B3F000FE40BB2AF0CB2B1E057B64BB239C3B0D80 -:10B40000C6E9E27A6B275B37EDEF8573543A9E7796 -:10B41000C6141CA7CF9181FD75D67FFECE3629B606 -:10B420005E4AA963416FC178656ED0337A3DE227E9 -:10B43000A0E0BE4E40935CDCF7E4152531FEB5C6B6 -:10B440007D409EC1F9F06C7F65857F5AEC2BE2410F -:10B4500056786EE4F53FF36BF825BB324D7A2591B3 -:10B46000BDF2CC151F33FDFBB37750DE34031DC393 -:10B47000FCE1F74DFAF75A41C74FBD83747CED3EAE -:10B48000A67F9BF7952A40B71FB46AE43D6A8036D1 -:10B49000F3F3D7EDD2C0F598EFF294CB0B71BD8FDB -:10B4A000B9BE59B3F59DA3706E5AB82F17FDFC8F26 -:10B4B0009F72D5C338076D3684E7C19EF377B44BCE -:10B4C000C67532BF80DAC148AACDD44E6576F0EA9F -:10B4D0006DE0A7AD6D242AF07FB3857E9AF7BD821B -:10B4E000F422ECE0E0C38B5733FBD3A5BAC08F9BAB -:10B4F000C7EC5142ED51689F3E2FD2A6207D959614 -:10B50000037D3D73C52F3A418F37CF235E187FFBF4 -:10B5100018EDA97CDC8F4420CF65BBA3BBCA4EFBD2 -:10B520006FAF0978292429DC76A2DD4B8A15AEE7B6 -:10B5300056A3BDDC9C73958A7C6695074FB5A1DD4B -:10B54000D51C48C6F55CB24FBA85D9236EC2D62F3A -:10B55000217D5E12991981F8D9471C7E028E1F3B0E -:10B56000FA56023C3EFE0925445A7FC93C46AFE9E3 -:10B57000F37A518E3CF7D47CD4E3822E3D4F26A142 -:10B580003ECFB07B2515F5DA9224235EBB1D4C2FF0 -:10B59000A5733D53B495E1B793F353A7DFC6BF8AB4 -:10B5A00039FEE2D52783DEFD88E31FC508C8772E64 -:10B5B0004FD6AE8E223F35ED66E3F992B4D25B0DE5 -:10B5C000F4EBAB667A519C07C0F9C0A238F2E231C5 -:10B5D000BE8EE0C3ABB681BD7C31C53BA894BC62D6 -:10B5E0002E47295D00DCF21A43480717FB6E5021F5 -:10B5F0003FD59F49D05F1C6C5348BCB8CFE35C8EED -:10B60000FA3343651087F6677BD0CEF1CB953617BA -:10B61000F42B95D49E009E7BA29D37E8CF557B4CA2 -:10B62000FC1E2AB3D176C7B23C0CCF91DFD8179756 -:10B63000001F06D8B816BB6FB8DFCDECC685DDFAA3 -:10B6400064F043C4B9868043A42DB9DE283F7FC28D -:10B65000E11099C8E2A9D4BE77635CDB4BE701FF38 -:10B66000BE67E623CCBF6FC7760FFB997D5443F7C7 -:10B6700007769BBF28B49EE9538F1A0F1EB3FDC2F5 -:10B680002E5F590A7E65739D5B057EBBEF67D22AEC -:10B69000A467081682DF1D5E8D7820140FC00F246A -:10B6A000CCFCD2E69650243EBD2F42FE6B06FE93A4 -:10B6B00090DE310E4FE93DC2E89DE93FE1FF837C1A -:10B6C00034E61D0A3920E44BB3323001E858F04328 -:10B6D000F39C810900B7D1CA938F1D94FF817F2805 -:10B6E0001C807F04BF789E667CB2A52D5009F55B57 -:10B6F0006A88B7DDA08FACFE12AC13FC4E21D74F89 -:10B70000FA42C7FD1007B0453B21BF42C8E1E6A79A -:10B71000374F8897FF26E4B0D3CEE49B339212696B -:10B7200037D0179CF979A6E017F3795236C48F8F7A -:10B730009CF2BB791C7F74F91259A0CB41DEF4A4B2 -:10B74000605EBB881759C7FDD82F99E232C26F815E -:10B750007307689F93C5F827258BF3679688CF46B4 -:10B760004CF41FB085DF813CA344FA4BF4FB5BC56E -:10B77000AFC43C428F5AF12FCE4D603F8B26256ED1 -:10B78000D77D80C9272B3D4EE47C72147C0FDAEE06 -:10B790003FF839D770FCB2714878A2292FAECBB6EA -:10B7A000A7315E1C4C9C779087268E2AEFEE402BAB -:10B7B000CBAFFA0F9E674B564F34E559B9D5401BB6 -:10B7C000C451AB9CC15219E765712CCF1CF209E83A -:10B7D000E1C9FBBA8B217FC91F329F9764D7279B92 -:10B7E000CE2372C319A6727E639EA9FD989642531A -:10B7F000FD391BCE33D507F529A67251D70C53FB63 -:10B80000F1DD55A6F2B90F5C6C6A3F31B2D854DE57 -:10B81000D2D65B0F78397FD795A67E5576AFBD948B -:10B82000C2B5A47795397FCC02CFB4BFCA71E9B055 -:10B83000292B8878ADB29BF3882FD8678607A4CBD5 -:10B84000019C27133EDE9C635346CA6F9D4CEC7FE0 -:10B850001E10FD83C3E9813807D4501C3F53D0B973 -:10B86000285BCFB584FC3853FA4BB44E417F89EA4C -:10B8700013C1ED3B9CFF055C1C4370A95747828BAD -:10B88000E3747021142E9EAF0E17EB789B529A3101 -:10B890004FF8352818ECE38156F37D98657A1AD372 -:10B8A00043A125A7B1A3591C389CC4CE2BADF5FFED -:10B8B000C9E1F2218509E261947CFD16C7437F222C -:10B8C000BEDEF0C9C16C90DFB504FD666F4BDB27AF -:10B8D000A0B7AEB64709D0FF7D7C3FDB79BEE80359 -:10B8E000AD5E1CE7417E1EF9506B007F7FB8B51836 -:10B8F000BF9156157FEF69ADC0EF4E6ACFC1F70714 -:10B90000ADB5F8DDD51AC2763F6CADC7EFEED630D7 -:10B910005BD7307C9172B473429971E3A5D7E8F29A -:10B92000A8F044E482B8FA32E13872C388F9E51B22 -:10B93000FAA5C79F35F0EF5B591EDF51C86D9C4ECD -:10B94000A6C3F9E6E9FA7FDE4A1E7F76FCE8F948ED -:10B95000D013399539211E5F87795EE563DB57DDAA -:10B96000A54F4A0CAF189DC587539DF3E33C70D695 -:10B970002783CD60E82FEE9F88725D382DAEDD9075 -:10B9800097CDF46E7D123B8F5F6EE1EF6F6533FAFA -:10B99000FD5636D377BF4B2067D2793D5DA703CFE5 -:10B9A0000787F1DD3DB3E3C1F7AEEC80292FC57AFF -:10B9B0006FC53ACEEF1CDD63D4387C76BA71C4FE15 -:10B9C000ACFDAEE2FBFF663661EBFF7FC69FBFBBFF -:10B9D000CE83FE03C0CD6FD8FFEFAE4BA98F179774 -:10B9E00069CF66E7A1D43A27C10C34F575056CC55B -:10B9F000621260E7BEE3BC101F12790189E9D58E9F -:10BA0000712484A13C1CAE141F01A5888E6F1F9A5F -:10BA1000276A8779545B4CCF42AE0D31DCFF9087AB -:10BA2000D303EDAF2B98D7339007EB3B537A22F239 -:10BA300043E3473AA71BD6FF0CE5CC9AECBFAF9C7B -:10BA4000117C4E4EDD3B3E9E9EAC87B967507BEC31 -:10BA5000FE87989C39CDB8670ABF7A7900CFAF4787 -:10BA60000DBF7DBE51C5A53E77A54E26D4AFDBE008 -:10BA700064DFDB93537BE0FBB96B6C84A4527E8163 -:10BA80007552BED5AB08BBBFF596F09B5AA683BCDA -:10BA9000DD9E1B7A309B8EB34A61FEE29FB2B4EF0B -:10BAA0004339999F0B27F37361255BE98432D18A6F -:10BAB000715F17F07D75DA0263615FEF4BEA44F066 -:10BAC0005BBCB6880ADF54122D61F9799130F86BAE -:10BAD00099E72707C0DF4D9E40481FC6C75517C4CA -:10BAE000D19494C117C701FFFFD286F7A21FF7B206 -:10BAF000753EFE403E9EB350818FF26232FC4EB7DF -:10BB0000B205EC72DAFFFB52F8896CBAAFE35EA7BC -:10BB10006EA3EB9ABCF9BD8C0CFAFBE3FBABF05CBB -:10BB200021BA4BD615B8DFD0F7E1772FA1E35DD06E -:10BB3000E7C0F8F3054446F9BEC64EB6021F25829B -:10BB4000EF07DF889F07E6C8914CF95DD6FAF7B991 -:10BB50001EF82041BEF16BBC5EE4CF3844FE8C5F22 -:10BB60001B317FC661C99F71D84304CE851D43F93F -:10BB7000330D04F367E838C6FC990FAAE2AFA39F20 -:10BB8000CB73C7172909C64DC5DF3F281C799F8E87 -:10BB90002F5CA67CEC587F37FE9E287FE73301A7F9 -:10BBA00004F94B9F0CAD2F97E899C67E8CEF62F39A -:10BBB0001460BDC3920714AB67F93F1DE98C4E0EAC -:10BBC000E4787DD7D0A1AF2103789FF36AB7CF0186 -:10BBD000F1A41051F7E0FD1EBB637040F06121B489 -:10BBE000B3BF0B76B78D4A5EB0BBAFDEE07877C0EF -:10BBF00020B71669E63281F60639BC1862D8741F80 -:10BC0000C9E71563FEDFA72490E61D418E3638E5AF -:10BC100090DDB08FFE0476C4859C0EFB73E3C3AF4A -:10BC200030C766CA631ADE9FE703F07B68B77A47BE -:10BC3000969F00DF70A6717C2B1E7C587F3A38FBE4 -:10BC4000E1B00DE26A9512CBF3FF9BC33B9DE7BBCE -:10BC5000B1FB030E4BBEFAE25CEBBA59BEFAFDE94A -:10BC6000A19939D82F30C1785F60AF5D4B9942BF41 -:10BC7000FD5CEE58E1B289C3D9BAEFBD3CEF3E5945 -:10BC8000262D7B0CF0B7EEF71B398CCE45FB0E074B -:10BC90003BCF02C1E7A4726F0561726F454E21CFA1 -:10BCA0001F4FB703BE1AD8106485F7109E2F0938AE -:10BCB0000F831F87BB158E21125809F9DDA783E773 -:10BCC000865C6D450E9DF79A57921590FF2B9D83CC -:10BCD00007C1671DE8B31D1E47BFEFB8C71DDD498B -:10BCE000E03CAEF8C967E837B542657915641EDAFD -:10BCF0003F929E2F7F79FEE8ED9FCED47031F0C742 -:10BD0000FB3C3F5BE8A5CEBC131320CFFEBD8CCA25 -:10BD100029B97E8CC36B9940473F4F6274F4001D74 -:10BD20008996D7FD6222DE87BF2A37AC423B91E776 -:10BD300047B4C109909770A670A27F1C4047A783A3 -:10BD4000D39A1CC2F831353E9DF4E4B0F8DFE9F82F -:10BD500003EFA195FDFDF843C0539C6388F5A9B995 -:10BD60008C0EC557C0CD9A4FA4E6DA783B96AF78D3 -:10BD7000556E08E17C72CC27475D74EDFD4AFCF7F7 -:10BD80001D9E1CE5FE05BCFF5E72B83F39FEFA5EE3 -:10BD90004CC0C7FFA8F54DCDE5F43339FEFADE1EE1 -:10BDA00025FC4264F0ADF4BF831EA3789E0A78267A -:10BDB0001D83281FFB33E2AFF3AFA35E67D8F1F713 -:10BDC000D0B782BE897E4D239EDFE724C73DBF5F8B -:10BDD00046FD29F087ACE7F8E2BC9ECA0FDC6F9DF8 -:10BDE00073706526E07D1EDF771689A6C3F9E62FFE -:10BDF00092F03C60989EE4FC41E195920BFA64E17C -:10BE000020C635FA27C4970B29B98CEE86DA77B1AC -:10BE10007912DD43C8CC9546750F819485311E5843 -:10BE2000E97447658A875B383E94FC9B54B00F2BBE -:10BE3000735E3A02FBA4F0FF70089E86FCBE13AD51 -:10BE4000CF7BC73912CBED35F213E52D71F63321D7 -:10BE50002B3C21D7106F5CB3EB05EF3803BE4AC80B -:10BE6000808DDDA31EB499FCE46C72467EF27E17D1 -:10BE7000E397F73242A80F403F80DEE97CFAC252D6 -:10BE80004026D81990DF33E8494639DA9E37A3387F -:10BE90006080676DAEB02FE50476E3D7BB1F10B3AB -:10BEA0009B2493FD1A1BDF8EBF0BFC54BA5F8C8B57 -:10BEB0008F0959DAA500CFBF646897C1D70A3FFD43 -:10BEC000CE59E978FF00E0373736DE10FE13E0F98F -:10BED0001B595A3DC04DCD0CB0BC0191D73714BF92 -:10BEE000B07B8F3A63F01E2D5E92797C8DDA0DABBC -:10BEF00061BD4A12E747E2C67BE4C26E2116FB86AB -:10BF000014337F7745CE4BFF03F19FCE54C6B29DCD -:10BF1000FFE4423FF06AC9ABC0BEA9FDF1E6F76994 -:10BF2000FB3089BEF92DF40F859D91227F9932FA5D -:10BF3000750AFFF97479D6CF803D46D7536573E310 -:10BF400079E733747FB9546E5429EC5B399F5215ED -:10BF50001DAF4A2ED83F40D7F51939953C9B7EBF7F -:10BF600043181CD6BFF2870CF047ABEC8E1346B9D2 -:10BF7000658D7FDC956B8E7F7C4616FEE67C80CBE4 -:10BF8000AC0C84CBE4A7E6651BE32F43F10FBE8F17 -:10BF900025FA354C9E5AE49C906736277B6F84685F -:10BFA00024E0CDC2381283BB2EE1FB57B345199C68 -:10BFB000145A9EC59124417FBAEFD9FC4B56857324 -:10BFC00040CE405A0FCC47BDBF1CF8B65FA806E074 -:10BFD0003B570AD9D93A222C0F91B414407B9B735A -:10BFE0004086F945BC02579205E3887959D9C3CBFD -:10BFF0001D759FAEBC2E303CAE41DC1EB47F15BE1D -:10C00000BEE35EB76E33C43B92DCD1E398BFCABFD8 -:10C01000D6B8C7EDB2AE43FE7632E94579E9767F10 -:10C02000A40330BCC42B41F9FB52F8E7C017479575 -:10C030006E12A4BF9FFCF9E704DF65831B6245F025 -:10C0400035EB27BF7B3DE645FB43768B5E0A4BC055 -:10C0500047D9F5D6DFCDFACA49FAF1FE90140DE5BD -:10C060007C9979FA784EA2388EA38AA17EF0466632 -:10C070000F1F4E66FD0F27B37E6F71BDD49CA110BC -:10C08000CC8BC9723AC19EFFD8730CAE6C823EE96C -:10C09000027DE274688857A157D6EEBD9900DE9AFA -:10C0A000F72D4238FC5E62E7A4FA0A09F319C4BB13 -:10C0B0000FF593C8CBB4279991C7FC94A5CF8757A8 -:10C0C00034D172DD4BA4244ADB95CE0DD5C0FB2EB6 -:10C0D000ED2544DD44CBEDAEF08F7E02FB7885BDCF -:10C0E00037B68EDFABA59858B39B8EBFE3CA31EA53 -:10C0F00016D852F56027E40B0D6E265EC82F194640 -:10C10000BFA7283F507A7804CA74DDEB5687FFE555 -:10C1100036DA3EF725A2621B5E0F3E0AE04FE2745C -:10C1200001BFCFA5BFAFE37454B45F62E7FC3EF636 -:10C130000E180E0EEF7439D9FFAEDB5F79F934BA01 -:10C14000AEA2BEA948DEE3687BC883824C04D69EBB -:10C15000D8E2B51F07ED0370AECFF043F2147C3F79 -:10C160008970F937DDC2873363FC80F5A5BCBC8ECE -:10C17000EB2913DFC038D46FD7CAD9B13FF6F331FA -:10C18000FE5089F8C3F8790689FD8171AB63F3A08D -:10C190005C9EC7EB0E2E5F80F9DFD3EDD103C0EFBD -:10C1A00033F9B7947F81DF9D148E57D85B0EFAE97F -:10C1B0007ED23710B50D666908B4C37865242403B0 -:10C1C0009CCBBD9BDB617D1736BC9209F475735E19 -:10C1D00011D2DF2CA75AE4A224D25EA1AADE2278D3 -:10C1E0006F4C42B82CAD774620CF6DE9D07B3FE154 -:10C1F000E032CA3F5784257E0F3F1C6C30C46D452A -:10C20000FEDFB224EA5FC791DF37E731FD2EFAAFD8 -:10C21000E3F75344FDDA3C37CBCFCCBB68461E9ED8 -:10C22000C7B0BC68CAFFB3F3A6C5E40A9D17F356AE -:10C230009610CD01FB5AC2F957F0FF52ED56B46784 -:10C240009786CC76E9EF25866F7DB98476E215F581 -:10C2500023DBAD0BF3C4B9708117F500117A8AD1D5 -:10C260009590E78B41BF831CAEA5FADC603737DCC5 -:10C270007E2A1DFB65FF60ED97E7C4EEC3ACB3DC1F -:10C280008769E6F761D6ED6B736401BDF3FB30EBB4 -:10C29000F6BFD369CC0314701A7E1F6610F31F9784 -:10C2A000299103704F68D94D748FB4FDAFF8FD89A3 -:10C2B00067E1FEC494181D79AE7445597E9D867958 -:10C2C0007E05DE1415F252BA6C5330AFA82BD5A3FD -:10C2D0001AF378B6B4B5D4403B914F24EEBF2C4B43 -:10C2E000706EFCCD3C663F6F97585E97BEDC89F060 -:10C2F000F6CBE488F19EBFBF2884F97433F202388C -:10C30000CF761E5F80FCD3A9F41BA1661AC317EB7E -:10C310006F950F74BC0E18AFBA48C53C9AEA3496B4 -:10C320008FE6CF0C95DE3229366EDD7E96BF57172D -:10C33000FAE410CBC35D5406F04C24D7ADFA8BD28F -:10C34000DF3D408FC3F556B819E8CF51155A7E1D11 -:10C350001DF7E4CB0AE6DB918D9AE4A0ED7EFC822A -:10C3600057857B781D95A14535586FC77B8259F558 -:10C37000249A44EBCB5E527A20CFAF91742B304E8F -:10C38000A3458FDDE47E56013EBD69A72346970491 -:10C39000F213D52210784DBB87C545500E09F964BC -:10C3A000A56732CE2C874A85DCA5F281E5F73530CA -:10C3B000BD477E20417CE8A4E798CCFD6B947BD3FD -:10C3C00084B0B2C8FB69FB9F437B46C0730E9517D0 -:10C3D000E0C749F0FB64EC87652A4F8B21EF742698 -:10C3E00049467A1B6647F0F5950DAD9FD94D424EF3 -:10C3F00056561002EF2358F143E7433A17E77D7092 -:10C40000B402E70833F9FC9FDBB449D120E08B4448 -:10C410006C14CE9D520BEA1D27E481D2EF16298CB5 -:10C4200072F1A7BA2E035C2F242D4B160611EF2FA5 -:10C4300001DE6739FB52000F4715D509F5359030FD -:10C44000885F33BEE6BBEFB303BCE6E758F1A2DB7F -:10C4500001BE0B02C3F085F70BB404F8D2845C2153 -:10C4600066B91224A7D8FDE6CD876E03FFF874F6EF -:10C47000C9F7B2C247E3D1AFB05312E5E59DE4F28C -:10C4800078B47979271DCCAF984106AEDF2D0DA782 -:10C49000938F0F6E90730CF424E8F4699EA72FFD20 -:10C4A00092E7FD967950FFC5F425A383725E9A0149 -:10C4B000F465A083D9FB5C5199EEB394F79F01F426 -:10C4C0003025A62FA33677402904BCAB5DB23CDCF7 -:10C4D0004ECECA0820FEA7DA34C4FF34EA8171BB0D -:10C4E000D39D4FF75FE1EC6DB70710FFDF07FFA6A5 -:10C4F000920410FF9516BD53EDAEB3039D543BADB2 -:10C5000078D610FF35DE61BFDBBE0AFECF01FC0B23 -:10C51000BD320AFB94E27F42FE08E78D89F07F413D -:10C52000BEFB8CF23205FEAD781772608FCB5BEDEF -:10C5300086787023CB4B9EFAF2B8762867AD0DE271 -:10C540007D993DE9EAAFB0BE85D597F56932BCCF9C -:10C5500058B49ED6D3F29E60A81ACAEB3648284734 -:10C56000A7BD166E87F2B88DACBE7453CBAFE09DFD -:10C57000B3753AEBFFF4F14E7CAF22D2C9FB57768C -:10C580005743795D17EBFF478F5307BFBCFC48A4A7 -:10C590001D7E9FB895AD43D87D7339BDED919EF852 -:10C5A00015F6EB66FD6E38E44C66FE12B3E3E6F07A -:10C5B0007DCE7D88EDD3F7DEC5B5010AF7EB0675B4 -:10C5C00007CA0D5B5339CAD1047E5AA5D45D00DF7A -:10C5D000F9544E10C43BA5D34296B7DA43A75893FB -:10C5E000CFEC2691EF0979E78B0CF85A93CFFC0832 -:10C5F000D12E2B83B0FCE407D9BBB3221F357A3F81 -:10C6000091207E007B44FD9B203F757E510BEAD339 -:10C61000F9E788BCD401FB2A3A6FE9977FBA289ED4 -:10C620005F7E4B3EB3938EF13C7AF17B63246803CB -:10C63000FF640F100FBE03147D19EC963DF0BE9100 -:10C64000E11D923D4156D6F3F7DFDD459DDC1B6CC5 -:10C650002D761D94C05809DF55B9AC8F44D352874D -:10C66000AF7FBE9D4459FE045BFFF5ED4ACF1683B4 -:10C670001DBF54888F59E351AFD4713C09B9B194AF -:10C68000E38BF2F9E67CBAFE65CE16B41B9713A6CF -:10C69000D76F24118C6FDC68E1F335EE3FBF65B3D3 -:10C6A000411CCDCCCF6BE972D8F9FAE0C3BFA3F03F -:10C6B0006F7CC0E305FDBFB6D7DCAEF181978F304C -:10C6C000FBCBCCEF8D82DF23667EA70605E3F7FB6D -:10C6D000CFC3731B713FD0E51C7C4B27B1FD0EE926 -:10C6E0007D0BFFB9E0BE6031F8353696A7C8CB6246 -:10C6F000DE4FBB995ED6A95EE67E108ADC4FFB2F2B -:10C70000C17CF852A147B99C11FC5CCAF5FC303DD4 -:10C710005E6BF577EE433E99CA4B56FD2DF4B6B8E5 -:10C720008748C745FD4DF5F5CB1A5D6F9FCD1D01BF -:10C7300078C7F47604F9688A93CA6B1BE2EF00E0CD -:10C740006F1AC75B3BD7EB09FD03F7FAB8FE01F59B -:10C7500037F01C61B85F1035D9FBC3CE3112D8FF5A -:10C76000437873517B2A05FC7DC2ECE23C32AA3C43 -:10C77000112AB7DFCC1F416F2BCFB0DF0777B8305E -:10C78000BE20E2EC82FF5E2F6076F8B65CED3D9055 -:10C79000FFFD7CBE7E3E7EFFCDF3F1FCFBCF44C3AC -:10C7A000F36FC867CA8F937F01E7DF1D8678697FC3 -:10C7B0007AFC38F8275CFE941610FCFEC9AF7D0A9F -:10C7C000EB3FA6B038FBB164FE4D65E714FF3BD4E8 -:10C7D0009EC98F4CFE15EF911FCB30C7E7453B3FFD -:10C7E000FFBEDFEA0C7518E2E181FB935A408FF936 -:10C7F0008B785EFC7A46C7279F4ADF617C272E50E4 -:10C8000050595A300DDA694A2EC4679E62FAA2D98D -:10C810003EA0C0FB3E3E7F38A5C00FF79B88F604C4 -:10C820008C1318509650789FE4E7FE27F97B402739 -:10C830005DEC2BD6152858540AFD4EDE3C80726301 -:10C84000A8BC6800E542A02084F39E5C2AEA79F93E -:10C850006E5626DCAFACE47C8271E33871E2E171A4 -:10C8600061F37B37EB94F8E7D5A4C0638AF7AED8C1 -:10C87000CFE2902B9DA4339FD65FBD3F1BFD8DC69D -:10C88000547D02D0C3D78DE39E1CD387FBDA523987 -:10C8900038F6C1323C17C678D1DAFDCFA1FC5B2B4C -:10C8A000F866AF996F66178CEE3CC51A671F053F97 -:10C8B000CD2F18C10E7A12F4972386875B787E53AA -:10C8C0008DDC540D71A54F5713BC677BCB0B32D257 -:10C8D000D52D3F92F0DD0961C7ADE5704EB42FB89C -:10C8E000A71030C815B8A71030F875704FC158861A -:10C8F0007B0AC6F6704FC1580FF7148CF5704FC104 -:10C90000582E25D7B6439C6E5D17F14602ECDE82A9 -:10C91000B13FDC5B3096E1DE82B13FDC5B30963FBD -:10C92000250C6E9F3E2463FC1FEE2F18FBDFF0C228 -:10C930008FCBA3B06D17CB536B7751F8031DEA5A19 -:10C94000DF240A9FD51C3E70BFC138EE07A9173DF2 -:10C950000FF859DD77FD42F85EB0EF26D3B8A49BFF -:10C96000C9E316FA17E0783D09A5813F37850C1E0B -:10C9700082784773445261DE1B1E30CBEDA1F74C29 -:10C9800022E6DFD71043FC37383CEEBFA5C0E343B7 -:10C99000BACA2379C6784F8C1EDC6A14E0F09AACD0 -:10C9A000C6A38752726E1AC6799E97218641FE48A9 -:10C9B0005AB6CF920CE703167824E598E9C21530F1 -:10C9C000D3454AB1992E3CAA992ED22ACC7491AE65 -:10C9D0009D37227C336BCD74B2466E42BE1770AE6B -:10C9E000A07F01CE53E0854A802FDD27C48BADF0B8 -:10C9F0006DDCBFAD13ECFE3385EF9316F87E466613 -:10CA000055BB03585DE72C8FD93165CFB7E021B016 -:10CA1000357E2AE028EC081107A5FA1FEDE9985F9A -:10CA2000CFFC3D6A1F1C2CC0F303E6E7012581DC27 -:10CA3000BC8E84513E5D67B10F6E70DFA7807D3084 -:10CA40006CBFD43283F70BADFB057B8B18E25256DB -:10CA5000FB40DA2F453D9361BBFB859C0E7F89C669 -:10CA600090268D466EF47AB4FF02B9058EA2B3DC2F -:10CA700014378E6BF7897508B888F993488B9C0337 -:10CA8000F45C6CB5CFCCFEB5F0C745BC5DC4B585D4 -:10CA90003F2DFC182B9CE57382ED40FF53BDC28FE8 -:10CAA000EEBB0A7E17FEB3D56F1DBA170090857BCB -:10CAB000373C4E7FA77F9593BDCBC7F84EFCDEE990 -:10CAC0005B9C36523EE61DADE67B30741BDA88F780 -:10CAD0008A00645970EE4420A842B65E7A6800DE8F -:10CAE000DAD97AD98B83CFD2EF96921F0C6C82BAA7 -:10CAF000535FCA00D7A1783E61F78415DE4F29E85D -:10CB0000BC19F468B26A27EF1AE8C24935D5BBC52B -:10CB10007C5ED0133943F5BF319EEBFFA3BE775146 -:10CB2000F8BC3B7E847A456D8C67D759E1259EC35E -:10CB3000704DBAE838D8272E62D837EA4343598E69 -:10CB4000C10B55AB8CF7A644BD06EF977CDD7D018C -:10CB5000DEDF7518CBD157DE7718D71F617905F660 -:10CB60001081FC5BC547EB8DFA65880E2943951B48 -:10CB7000F6378A7D01D380FBC9EC1286EFBFD5BEA4 -:10CB80003A2CF88271435967F5FAF4B37C7DD1B33E -:10CB90001CBF64D1D90D3F6DD1D90D3FFD2C5F5F16 -:10CBA000F42CC72F597C76AF4F5B7C76E3573FCB95 -:10CBB000D7173DCBF14B969CDDF0D3969CDDF0D39F -:10CBC000CFF2F545CF6EFCEA6807BA2BA204DE97D8 -:10CBD0000874103518A0262BFD19FCF92295609ECB -:10CBE00006E17E4921F74BB66D6DA90717EA115D85 -:10CBF00009603C88FAF739B47E2261F58F742DC63E -:10CC0000386BDB980979F05E95BBEBA2E3707F6F20 -:10CC1000A2CEFC71EBBF1BB64833FFFB6B9757648A -:10CC20009ACAD3FACCEF575CD55864AA5F1E3EDF90 -:10CC3000F2EFE74D35FFBB64A19996F7206E26C64B -:10CC40007B918524AA427CA5F06E5B159C9BD9C183 -:10CC500067BE90FEB753C17E1AFD6BF45F0AA92729 -:10CC600034347E10E0A698C6775BEACFF41EEAFE65 -:10CC7000B1F1EFA112786432CEBD736B1E26B1DF25 -:10CC800088F13981AF3B37DBD0E5FD6C2BC1771ED6 -:10CC9000AB23011BBE83CEF1763E273DB1EF48ABFF -:10CCA000F93E7AA14EAA009F451DC406F1B5E04E9B -:10CCB000A26A04E34248278FE8F1E9E411E2AD8279 -:10CCC00077B91E8910FC77B2045DDCE908E4C1B9CC -:10CCD000DAF95D8C1E049D04804E52212FC8FAEEB5 -:10CCE00080155F644A94AEF591AD8519C67C54B247 -:10CCF0009BC1DD49FF8E84AFE29D667C0588A1FC67 -:10CD000015F0F5E9D7C497E20B45D37C10CF240189 -:10CD1000C8933A3866820DE011EC52D1FFAFA5CD31 -:10CD200000CEC12EF69E9AC093186F6B2B89CE331E -:10CD3000F87F4135AA019C6BE44955907FBEA30C56 -:10CD400043C6C3F0B383789321EEBDA3CB968C6F1B -:10CD500054EFA3782921E4BF372F4B2BA6F53D4193 -:10CD6000920CEF6CF5B4D9F0DDB29EA7A47AF3BBB8 -:10CD7000CAD1245B0EEE23C956815F3BFB6AFC4B94 -:10CD8000ECAC3E2A4379ECC661EF7EC8509F5E6BE7 -:10CD9000F97703892641FBE473581E679A667ECFB4 -:10CDA000C651619607148C7D39E5106FE1F4CEDF32 -:10CDB000498DD490C826BAEE73B8DCB1D251FA1DB1 -:10CDC0008B9198DAC67C03E5594F9B82F077707996 -:10CDD000453632BAD0E95FA0A7740B1D7954331DD4 -:10CDE00039E402CCC3157C25D623E66F1B93956CE2 -:10CDF000C775D9F13D6C87554E58D6E7866020C57A -:10CE00009DDB4722115AEFD0197F10B91F7F774C55 -:10CE1000272433F815D6F935E553E89CBF8D7CF20D -:10CE2000F031EF9CC6F6F999CADEB5AEEE60F4EECD -:10CE3000D9CAE81D6E74B37C2D6D61AEE15C752FAF -:10CE4000975356B879FAB46AA0E78BE49734C88F41 -:10CE5000B8FB3546FF6D630E3F0FE5AD7733F8073E -:10CE60005586674A2F6A942EFDEE3BDC98173CB539 -:10CE70008CE20BF0FF92599E4CEB33C3B1C82237C2 -:10CE80008209E06AE5D74470FD96806B39856BD1E5 -:10CE900099C355D1997C4E9FC5DE593C384661FFF8 -:10CEA0003EAFCEE098AEA9287F2F924F45D368BB06 -:10CEB0006D1A9537749DB51A83B7779690E36678A7 -:10CEC0000AF922E05FC8E1EF55BD2FC0BFF3E2D6FB -:10CED000ED2420017CFF5B033BA27B9A9037830407 -:10CEE000F096A631BA1570EE9ECDE05CA871387749 -:10CEF00071B8494402385BE9D52A9FD3BE269C7796 -:10CF00009DC3E3F159A4FCABC0795B0A7B47D931DF -:10CF10008EC1D5E11E8C829CED0ADA715F07820A10 -:10CF2000D67795B0FAFB5356E680BEEDF277E60071 -:10CF30005DB605AFCF01F9EECAE1728668EEDCF2AC -:10CF4000D8BD831A792BBE43DA1950103F9E407C1E -:10CF5000F995362BECC47926D9898C7078488D07E1 -:10CF6000076799629297F98D66F8A658E0EBFA9AEE -:10CF7000F2E1B5AF291FEE216CFD778E17EF347407 -:10CF80003B513F55DC8471F34C3ED7E685DF65BFEE -:10CF900073BD66F8BDB610E489DBAE023C13ADBBD1 -:10CFA000A795F0F75A9CFCFD16F6AECB3678D785E0 -:10CFB00096BF03EFBA2401FDB3775DB6C0BB2EF474 -:10CFC000DB05EFBA9C0BF6B4865FF9D2427C7FF0AA -:10CFD000B35A82F1F14D297F25F1E055D465D67F12 -:10CFE000413DD9F20E9B59CF65CCCB3395BDB3CC27 -:10CFF000EFB67954F66EDBFF0164680340008000F1 -:10D00000000000001F8B080000000000000BDD7D09 -:10D010000B7854C5D9F09C3D6737BBC966B3B9924C -:10D0200040124E42081B0861810483829E84406343 -:10D030004D71435151A88D40314248285E1A7FF509 -:10D04000C94282841834A0585A2F2C378BB56AB441 -:10D0500051A922DD2052FAD5964551F152BFF55221 -:10D060002F40258A177C3E5BFF79DF99D93DE76425 -:10D0700013C0E2FFF8FDF1C1C99C993367E6BDBF5B -:10D08000EFBC332184906FE8BF04CF0412F410FC8E -:10D0900081BA433D9704EDD1FA23C3EB1C6A3A21D0 -:10D0A0005677A5E139F1F7115F22562D248390546C -:10D0B000DE365DBED71E2E26644DCDAC24520CFD4F -:10D0C000B450266D4F80469590D5566F968F3E4F43 -:10D0D000A85954435C84AC6A2124388A90F6163BE4 -:10D0E000962B726CDE601A2177BE2C7BE3E82B3620 -:10D0F000CDA7B969FFDE9C5B09A1CFD7B80919920A -:10D10000479FBB9711924F88423F20D1BA5233E3D9 -:10D110002352425F98B3849049D1F9ACA9B1788386 -:10D12000A584C4253BBDF07D52ACBC13A66D6EFA40 -:10D13000DF37F4FD6FE0E782681947583BAE13BE56 -:10D14000A3EAEA04BE676C6F7E537A74AFAE7DAC1F -:10D150009A98F63E2CF61C72CE37322DE579497539 -:10D160004E5A96A71092D5FF7B5FB69047F78E4434 -:10D170008012920E653D01782A7CCCD5C9B3ECC4EF -:10D180001985B378BECACDE01B27D1CAE4FEE3B649 -:10D19000015CE3A2758510AD1BF0915D1AB3BF2849 -:10D1A0002906082923A4B32578F03D6BF4B9730A46 -:10D1B0007DDFD9BFFF4C55C679CF55552C9D4A9080 -:10D1C000B869BF442F7D5F0717A77666DFA73FA525 -:10D1D0006974BD2E4E37E477920278B5F37A8254A3 -:10D1E00037572D037CF9081941FB956BA4AE987D48 -:10D1F0004F13EF49502AE41D41DF79AC74D3760612 -:10D20000522869BBDDD8AE6620BC705C25FABEF63C -:10D210008D34F0BCBFAB12F0F8CEC841DA6DDE7AC7 -:10D22000E0A77ECF558B80635F1A859BCCD71B030D -:10D230008E6DC0DF028EB293C1B14DCADB19A6FC60 -:10D2400066D55C5E8A115291A676035FB6694EE49C -:10D25000CBB6B4EE5025AD9F28B57861A8C49195A2 -:10D26000C88F6D43F71D5E08709DB9FFC36D08350B -:10D270002D5425E04BDB133DD5A12A9DBC11F88A26 -:10D28000E7BF778C7D20BC9296A917CF236E4A2AE0 -:10D29000CE21362253BC384656D9EB9C51FCD8E0FF -:10D2A00017FA3C3E6DC64732E5FB78AF0E8FF0EFC4 -:10D2B0001B564778D0C5DBB26FFDB904449119E91C -:10D2C0007700E6A3A8BEE8FCC8D9C717C94E43BE7D -:10D2D000278A3713E4657F7AF733BEE7FD06E60B4E -:10D2E000D66FBA5C93791585CB9A17987C241E2645 -:10D2F000176C7686CF354463EDD98A97BE41D664E4 -:10D30000AE44F9D1AECE6F07F9F979A685C8123CC3 -:10D310005F6F07F9A198E447BACF62D00743E6C42C -:10D320001BE4FE9A825928CF069A67569DF1FD614B -:10D33000F5C6F77396A518EAE23D6BE6452F55A5AD -:10D3400046EBAB943A3BC8915B33D74B753AFA1E28 -:10D350005254F73AD0ABA8DB3267E27B7139A53182 -:10D36000E7B5CFA3BD0572A25D65F326EED870BE0A -:10D370008BEBA1BBB91E3AD53A37F2FEBFE6FDEF03 -:10D380006D716319C167C13506BCACCEA2F29A8E2D -:10D3900007B0D77FFF29B5EE73985F14CF96287C2E -:10D3A00080698B175B805FC5386D59F90EC0DBFA59 -:10D3B000EAC1E727F4AAE867557CC44BDFB312A3A0 -:10D3C0001CB7A5590CF89890C7E5C6B66B0CDFDD05 -:10D3D0009B3C63631EA5ABF587648274F73BE3FA5D -:10D3E000FAD3AB711DEB33D9FA07A66FD3BAA944B0 -:10D3F00088D011D6534CF5A1A6FEF9A6F6D1A6F613 -:10D4000009A6FAB9A6FE95A6FA0F4DFD6799EA5747 -:10D4100098FACF37B52F36B52F37D5FF8FB17F2983 -:10D42000C3F3F5E2D920F205F4BAB9BFA268885F68 -:10D43000A1E7237CE536F2E30F722AB43C66671855 -:10D44000F02BE8F374F1B39ACAB810F093A23A50F3 -:10D4500099962F267A7A589F998FFAA38D4E0BF5BD -:10D4600037B75F52041D5773FB70CE12031DF5E6EC -:10D47000143AC07E24CE34944BA7A20B89A418DBA7 -:10D48000B5A1D1F67CF8FFD9A58B53D37180EBDD24 -:10D49000C1E72DE4C023C37DD7223E02D49E1E1BCC -:10D4A00085931AB1A7E9C728DF6D49238138AAEF10 -:10D4B000B6F82D58FF3C937E08EC952AC687237852 -:10D4C0007F42C2128C23E6D3CEE9651DC8295ADEFD -:10D4D00001728A96B7B56462B97AAD256B218C5713 -:10D4E00063433CA58EBBD5AF4059595E04FAFBB6E9 -:10D4F000B13B340BAD279E94497022B5174AAE2834 -:10D5000087E5244C9F9FB9173EF735FDCE24E04EAA -:10D510008246C6E62A12B08E2364ED9EAC1F7AE8DE -:10D52000B86A81E275405BB177859286FDFCE03692 -:10D53000A84ADFFE11B43EBCC082F685B5BCAF057B -:10D54000EC7731EFB53FA4844B3BE6557B2D7E0A4B -:10D550008215C3EB7E05701ADE492C1AADAB7E55E1 -:10D5600002B9F6469E8AF276EB1F28438E800FF5AD -:10D5700065819EFD62AD6D25CC73603C11D952FE74 -:10D58000ED4B310EDA9943F1B906F4AC2A484274F6 -:10D59000951F76C13C9D32AB3F9777CCB7B2385AD6 -:10D5A0007F2CEF987B256DEF9C986B8175E4A5B976 -:10D5B000B4400CBA3A0CF218D6B776D170BD1E340E -:10D5C000976A0D1D77082D8B7909B4760EC09F9749 -:10D5D0002A7F9EC9EA0738DCD466DE9EC6CAB3FD40 -:10D5E0001DF3F8AFE5B9855D3A94FB8FC5CE8C414C -:10D5F000EDD3C37965FDED532AE886029D6FB27ABB -:10D60000875AE8D89BD6DA889FF2D4A61C827EA2DD -:10D610007F8D2DB01DF84351875EAAB3BB026B32DC -:10D62000AED0E8FB0189CCD1CBC97B399CEFCA973E -:10D63000707ED3E5637E99D2EF263F413B6B137139 -:10D640003BC01E89E0DBFFB90FE990E3BB2ABF6A4C -:10D650001DD02959C8F4667E549EAD50E8389B61B0 -:10D660001C5ADFDC6EC1F96DDA45F9977EEAF39B4F -:10D67000DFB180DD3C96042DB0BE312480A5872C1F -:10D68000B30050BAB91EDFC6F9B790F237FA3B20A3 -:10D69000FA68FBA5C3EBBE06BE48222AD655BF1BBF -:10D6A000E9A9715772652CFBC0966FE17E26A957D8 -:10D6B00026713F87C1D9965FD61FFE56B20CE17E18 -:10D6C00093C767CF07FF6EE7C1E030DAF4C4AB461B -:10D6D000BA05A8CCD2C99D1CFE9D24AF4F93E93852 -:10D6E0007B72EB92E1FDC6FA4FF665C0D07E3FBE7D -:10D6F0003F39DF8DFDAE08764F8761C679C395400F -:10D700000B63AB7BF700C98CD136839B413CE53F73 -:10D71000DF93AAC23CEA86C23885A17005908FB318 -:10D72000FE603003E773BE05E86204CC87D3472D63 -:10D73000D2978A7422F00DF4504BEB573430F850E6 -:10D740008310DB89E236CC7FCB2A4A27CEFE749247 -:10D750009ACFEC236F148EC43AB87FE5CD8F41BFCA -:10D76000022EB37ABC560817F87EE75E053ED0CC91 -:10D7700040DF5E077DDE9E5B770EACB374A3AF1512 -:10D78000E8CFB92BE4877E024ECE29214DC27EDA46 -:10D79000B9D06FD3CD9595A817BA08FA4B427F9AA6 -:10D7A000F16F9D62B4F708E9C2F58CEC32DAE994C6 -:10D7B0008E519FF7A3E39B23741CAF8F4B08FD137F -:10D7C000E8B4C47BC0CFA0FE078E35801C7980EB07 -:10D7D0002541D7E27901891D67B8323FE2CF66CA99 -:10D7E00083C3FBCAFC18FEAC0BF86304F2CB7CC00D -:10D7F000879BF461FBF09B8DFCD2B8F3937DC3E86B -:10D80000FC9DA5EA04C08FF87E03C737A5E3C54891 -:10D81000C71BFBF6815E1B7E33A3E36BC1D6488F2B -:10D82000D2E34D1E6D297C47D099793D4BF87ADAC9 -:10D83000737DD7C278576CEC7EDE81EFF9AE473E40 -:10D84000DB180A3A4814BEC3397CE36E89E0D90D6F -:10D85000F263568DF779D0CF3E8F7B3A9433D5BEA5 -:10D8600036302DE6D6CB06BBCF8C5F4A5FAD485F26 -:10D87000C4374D92C09AEDB6A2FE1C806EA27AD338 -:10D880002FE8FEE653C8ED3B62E1E174C73F99EB38 -:10D89000BB1BDE4FA9F611E4D3D39DD769F61371F4 -:10D8A000B3A81D1BB0EBED5841F71DEDB3D04F16DB -:10D8B0007810CF57B5CFAACE033A772ADE58FE4F5D -:10D8C00044DF703ABF9FD3F97A6E7F7571FBEBF638 -:10D8D0001615E57B678B07CB8E162F8F879663B95E -:10D8E000AA45C37EF29A4F2BD07FBF99605C6B65CF -:10D8F0004289148BAEF2FC467B7F78B311EFA9D539 -:10D9000046FF3B596F2FD37F49E5F986F644EF6810 -:10D9100043FB69C48B0F00DDDBD22A0DFD48F813F1 -:10D92000837D2BE0385D9E87F1620A4FB4AB853D65 -:10D930002BDA09A9C378AED5E467769AECD80E80C5 -:10D9400023C297C1B10BE088F02DE7F0AC667E13DF -:10D95000F77BE285DF53B47ECE7C8C8B1094572B03 -:10D96000726CA89F3BF298BDDD8F7E3275F293F208 -:10D97000FCEA354C9F0B7BFCF99C57AAC1AEDD92AB -:10D98000694139B9256D8F672BD6E3BD4C9FFABB32 -:10D990003C147F560F8F57538ACDA2EB4DE47CB3D6 -:10D9A000DA4A30FEDD91EEF4421C2CD1B3A806FB1E -:10D9B00099BE4BC8CF89DEFF23EFD51BEC0EA25CCE -:10D9C00063586764FEA536368E44241827A5D866AA -:10D9D000C09F9DE8EA79305F5B148F79B05E8E2737 -:10D9E000939D23E214663CB96B8CFA6675117BBF7C -:10D9F00037E701C4BB19BEAE2A23FD7670BA684B67 -:10DA0000DF827C68EE6F1E9F4C8937F87F1D9EC1B8 -:10DA1000E324C29F16FDC08F76C7E86FF6A3CF86BA -:10DA2000BFEEC6EF19F55D0C7F7DD2085D3C49C0A5 -:10DA30003B8207115FE47E98885B8BF114C2C6C3FA -:10DA40003AC6B7FD28FF7E99E0423FB2C0690B801D -:10DA50002C2CA0F3003A6EFB55426025ADAF4B98DD -:10DA6000D99744EB05DB6415DB9DBEA11067EEDDA5 -:10DA7000306368987EF71EA9EEA211BA38DCB6E4CE -:10DA80001B32993DA0BC13F600934BE8E7FAD74D43 -:10DA90000C69608F1711EF76025E306B17F444F457 -:10DAA00075B97FFDB3114CEF66CE25CBBA63E07F2D -:10DAB0000D6F8FCA715F3CCA6B2EC70B38BCB6772F -:10DAC000CD8AD7CB71DDF3A4587475B6E4771BC843 -:10DAD000EF51F09D1735D4DBA584CBEF47C8F75144 -:10DAE0007E2FCBAB5B3DA22CC67E9F1246F93D51EB -:10DAF000D5DA01EFE9E0EF015E7E4AF112631DCF56 -:10DB00008E60F6CDF7152F42AF6EEF7A9CE1A558E7 -:10DB1000E0E57612CBFFFD1EE0E569807B3FBD4A64 -:10DB2000C2B80FFB45B6F60CB43FA56ABB007F1127 -:10DB3000FC5C169B6FFEF91DE3E77EEEB7AEE7F8DF -:10DB4000E9E2F1F1DB397E3AB9BEEEE0F869E7FAD5 -:10DB5000FA56C04FDC99F3CDF066237E52ABE34D0D -:10DB6000F830E227A9DC889F44AF113F099ED126F7 -:10DB70007C18F1935EA022FCE2328D78EAC737A7C9 -:10DB8000F057D2609C187672765DA802F6B886CE01 -:10DB9000E9EEB5C220BEAE0A28C57AEF35F9A5A2D6 -:10DBA0004C2F6078CD9C161BEF16DE1EC8D7A40242 -:10DBB0003D9DFC20361FDB79FF63AA1667E87F5185 -:10DBC000ECFE2EDEFFF5E15AA2BE3FFDB94B1EC4AE -:10DBD0005F30AF3F41D2D20B701DEACE30C5FDB6EB -:10DBE000156C1F729B43ED86FD7CFF0AA777BB8AED -:10DBF00023F9ECE01FF171883F09C7CDE59F19EECD -:10DC0000DCFF15ECFBE52DC81E7A356DCF5B9E79E8 -:10DC1000A48E96A30B46E03CF3EBBD7B00CEB26B2B -:10DC2000CE50B67F3CCFFDFE184A6AC154E91B7046 -:10DC3000B8DDB1F7ED4529F42995836807D2890449 -:10DC4000B6533A8D5388929802EBD5705D56B06307 -:10DC500065586F17D6E34937964E1262FBD7DC1F23 -:10DC60003DAF200FC7731337FAAB29C48BA5E06310 -:10DC70007B1A51D227E0F86D7113082AFCF3C05FBC -:10DC800075666FEE009F46A3509884AC82F090EECC -:10DC9000DA87EB271EA2B278DBCD6ECC4FF8335D6E -:10DCA000DF98D35FDFE9F6FBD2E12A21498434DB38 -:10DCB00059F98B78D71628BF74E4062068A58DA87B -:10DCC000FB31E0D55F49D0FEF0BF951068C5C92E85 -:10DCD0003B87F907A73DCEBCB334CECFCED2388D2B -:10DCE00005E9A71EE736F87532EC63FA9643FFB6EE -:10DCF000E44968778AD20CD77D1EED06989F627F33 -:10DD000029F7BDD4A8DDE67C5342BBAD4D0A12888D -:10DD100053FADF96D0BE22C50C4F4E9578F2C64519 -:10DD2000C7717A970D67F12E16EF59F1F75F8C02E4 -:10DD3000FBFB970933C349F4FDAD07A99D0779346F -:10DD4000D3BCAFD7537A4A4FB579B750FA49E57E7D -:10DD500072DCDA4907EAE9AF9F8C62FCBDA365BFBC -:10DD6000BB8D0AA444C57BE104FA9E93EFDF12B990 -:10DD7000260C7663E22445853D8E2239580DF32525 -:10DD80004D16027C714F83713FB7B3B008E122EAB0 -:10DD9000C3F87E2E2955FA227936D48EDF58C0F387 -:10DDA0006A5CC40576A1F26F2D2956DE8328C5FC76 -:10DDB0004AD3A8DE4A82B820E5145A96760631F98D -:10DDC000A3D21BB4831DBB2140FC360AA707E7FB87 -:10DDD000AE81F13ACB7D0960976F3834EBA2B17414 -:10DDE000DEA1B0E205100447A5E0BA439ABC368133 -:10DDF0003EDFF9A6C50DEBDBCADFEFF449C8FFF73C -:10DE0000CC23013F85C7D6863D7619ECDE90858C04 -:10DE1000443B973A5C93B82854215ECBF8FE965168 -:10DE2000E9F8B027B43C19E0B22EE1FC9046C7AF48 -:10DE3000AD6671E71972F6F3306EA8D386F849E73C -:10DE4000F94712A945FB39659ECE5EA6FF123B99A4 -:10DE50005F19BA8E60DE535299D3EBA7DF7B22CCD9 -:10DE6000F68DEEA96671671709E2F767C8BB1C1645 -:10DE7000FABCA75A71033D2599EC73278C4749AE2C -:10DE800067231BCF359E8D9768CA83B28B79B9E91A -:10DE9000BC28FEE44405F1ECAE36E64FB94CEF3950 -:10DEA0004DDF7B59E0399B14029E4FF86E98F812B3 -:10DEB000B67AD558F9139D2D2454A5CBB7700E1002 -:10DEC0003FFCB290F909B6ACBD7698D709DF2B6953 -:10DED00010EE7AE15FFBDEBB03CA7FFF574F135D95 -:10DEE000D75FBF3ABCED518063F36D2F221D72BF27 -:10DEF0006A084C81CEE7F95A1BC2B14C63F101525A -:10DF0000DABBD75A8AEDB8AFB5768F03DB87959326 -:10DF10008083C27398A265FD0CF835247B57A83026 -:10DF200088E6CC9A44D85615ADAFBD92120E950F27 -:10DF3000E9F334D95F0CF190174822C5F7064D522A -:10DF400059FE9BF43CF0534E95847E58CE219F039E -:10DF5000E8E1C46C0BE6BFACA8BDF4C29174FCFB55 -:10DF60002A148C375457555C0EEDC30E317A715D0F -:10DF7000C7F047E114ACA2FC30E2108B279492B0BA -:10DF80003748DB877989350DF4C73C0A60985F27ED -:10DF9000C70F8F0F949686FC00D444AF118F6E1379 -:10DFA0001ECD78758DA47804FD52448A985FC7EC25 -:10DFB000C75ADE6743D544F45FEF5189DF3AAE3F7D -:10DFC000BE5EA4F6A346EDBF10B51FA1FC1BB51F96 -:10DFD000A1ECA1F62394895AC545A574BEA1743A53 -:10DFE0002EF05F4DD94AD81FB86FEAD537FD93960A -:10DFF000657C9F8D726A4A25FDCE2CE062565FAF2C -:10E00000519BE4A552D9505F9BA6887D3C3FE8D444 -:10E01000C42C0BDFE79971A746EB9D990ADFD76304 -:10E02000F511C5C450EFA9B118EAE7EDD18D3F0550 -:10E03000F01387F5092377AEF71744DBEF28A475B3 -:10E04000DA7E80DB73B54B2DBE2D31E877D948469B -:10E05000BFCABF895FA2F8FAAC80A09F2E5B349440 -:10E06000DFA4505141BEF6D7CB540EEAFDEB022A95 -:10E070005775F191C3853CAEEEAB60713612FDF978 -:10E080007A12CFB322F0BC330476C4ADAF5EE90D93 -:10E090009281E5AE355339A2A7938B051D8C2423BD -:10E0A000D19F27530E54009D754D54801E4A391F31 -:10E0B000106EC761889FD2CF539FDEFD174D053F7D -:10E0C000ADDDDD3612F37E2E1FA9CB935995BE68C8 -:10E0D00022E83391F7434895FB7DBA2EC97FA90505 -:10E0E000ECB681ED1485BCAF83476FED8C24D00373 -:10E0F0004E2EC7CDFD57B5EC7C05BEBFBAA51B4B58 -:10E10000679A0F858C5DF163FC669FA7AE11E6658B -:10E11000CFA6ED3A396C4BA3EF19FC806C667709FA -:10E120003CB809C683C4BEC986CE09F17114189DD6 -:10E13000545F807CDE109A8579159DDE0983C6AF19 -:10E140004EC5275BAB5E2269148E4FBE3AF32FB3E8 -:10E15000697910F88DEAC12738DFE4943FF6DAB523 -:10E16000067E396AE297A3267E397A0A7EB9E04EA6 -:10E1700068EFC9540CF51CE0175D7D6B845F583D5A -:10E18000CA2F47915FEE79D986F58D238F1AF865EE -:10E190004521AD67EBF865BAECDB12C30E78E53BC1 -:10E1A000E2975F9F29BFBC7166FCF2C4D9E3973F39 -:10E1B0008E4CFFEEF8C5779AFCE2EBCF2F87605EBE -:10E1C00067CA2F9DEE20E60376CEB6540762E0FBC9 -:10E1D0007A8E6F11F72EE3718A69F3B4CBC7823D53 -:10E1E000CBF3D6443E4DE73CA6BF57D4CE407DB9D5 -:10E1F000F520D397423F97713CFE8DC731CA424C00 -:10E200006FA6974BF8FE4C4D0AA8F4D74E6A12A49D -:10E2100082BE9E22912E1596BAAC76A414B59BE8C8 -:10E22000F7D06EBACFCBF266C92166EFD8E97F404E -:10E230004F17975B0D7A7588D9FE32D5C53EA6D8A3 -:10E24000BFBC0FF212283CBE1EC9ED2693BE15704E -:10E25000D870A812ED90CFB36D83EE5775F2F546E6 -:10E26000ECA9525F45AC78587DA184F0BEC9A3C526 -:10E270001796813EBE0AF5AED0E766BDDC53F59237 -:10E2800051CEF8C7A75616EBE48C7F3CEACD889CAC -:10E29000E1F501E50C3907E546442FF37A442FF305 -:10E2A0007A442FF37A44CEC0F8D951BD3CF281F1C3 -:10E2B00077FA757A7B19D4B34FAD9717707970B62A -:10E2C000E5CC1FB8BDFA5DE9E5CA424E2FFFB99C07 -:10E2D000A929FC0EE54C2DC899A453CB995A90332B -:10E2E000C506397355E1B7D0CB890DBD7ED8BFBF08 -:10E2F0006200BA77707C371568D7C0F8A4E6F4F2EC -:10E30000B6CD74D55BFBC0AA0CA0172FF3F3067A29 -:10E310003FB1F9F7AFB4E9F2A21395103B5FD1FC1E -:10E32000243E9FDB7010E365A79A6F7D21C1D2ACBC -:10E33000477B6BF7D9916EBD16DC13FFB6F3E89CF3 -:10E34000CDF8F28DED4FAF073EBA8FC7FDCC76AE5C -:10E35000C0EBE9DA3FE6EF5E3F52C571CDDF3F1516 -:10E36000DD523ADD0C747A22FBBA31E0E7C98977D5 -:10E370002500BCBE07FAF0C96F43A7AF8C64F83C18 -:10E380008D750761FCEF6ADDFF017FBEFC6DD6BDB8 -:10E39000A090D1D569ACFBBFBF4B7CFF07FEC26725 -:10E3A000DF66DDCB04BE093B2FE3865F289FACFF11 -:10E3B00057E1DB10BF58FFEFD18FC13ABBBEB26F40 -:10E3C00086F805F9FA1BD9AD3F3F45D8B99944FE07 -:10E3D0005EA28F9D877157EBCE4791E879295C0F3C -:10E3E000C63722ED07629D97FBAE4BB047DEB10EFC -:10E3F000D26E63713BF3F3FF2E90D83936A9D60164 -:10E4000079F1BDB3F760BE41E7EC09B86F65B6536B -:10E41000C47B3D2D1AC6933A5B7C58DEDE521D82CA -:10E42000B8C9932FBD25413E58E94B0DA8DFD64E04 -:10E43000FAE130CCE39B5A1A0FF5DB4D768A8BDB81 -:10E4400029DE51AFDFA9F75F9EFC4D13CA4111874A -:10E45000BA2362BFD0F7549D9F44EB400E113F0991 -:10E46000EA063F69D97AB05F7AC07EA1FDA78E5ACD -:10E47000B63ED677D65A483DD82F6B1B2CD5B1EC7B -:10E480009770416CFB85D671DFCD91680FACCC03E2 -:10E490007B86D4E9E36AA7B25F1E1EF5DDFA495711 -:10E4A0008C3A3B7E52846FB9DD32A4485B0821D997 -:10E4B000B32527869DA69C18D65F4EDC38EA5BF80C -:10E4C00049E102965F2DE86BABEAC578726735C10A -:10E4D000F8636768656A09AD3FD1602112AD5FFFDF -:10E4E000328B0B6F2827013847BB219B603DE465C9 -:10E4F00074304376FE08E2E03D55D47F52216EF73A -:10E50000E35A80EDBA8499B73928BDD4962B04FC20 -:10E51000A619F214FC4E4863F9A1B54EF2A338F0E7 -:10E52000ABA62A64E519C4AD13E562897224E54FF0 -:10E530003519F876A078B439FE4CE417BC802F73F7 -:10E540001CFA4CE3CFDB055D7DFBF833F2DF970F60 -:10E5500034CD8278EEA9E871C12815F599594F9903 -:10E56000F958D0D340F4E7043B69A2AECECFE186A0 -:10E57000F93EB513ECA48951BAE8AD9D94142BFF74 -:10E580004A9409CD7F78457F1E2F41E9C6F1129A42 -:10E5900077E1F3BB206F00D6A778519E3E5849E53E -:10E5A000708CF9ED6E597608E4E7AE96662C2F5024 -:10E5B000FAE414DAFFE916FF2180DBCE96762C9F71 -:10E5C0006CE9C2F69E968D58DED112C0726DCB0EEC -:10E5D0002C6F6BE9C6F2C17CF69D294A10C7B9E0E1 -:10E5E000241D5F474753FBE87774F83EEF43BFA114 -:10E5F0007D72B8DDD07ECEE12E43BD2CB4D1D0DF0C -:10E600003D2560686F2AA83B067CE92ADD6178EE2B -:10E610002CEE36BC77BA7EC1D9EE976B7F04B6C9B3 -:10E6200049329CBBA0AFC8706E88F2F190662A5E3A -:10E6300069FDFE441EE7E866FBE49924F283740951 -:10E64000A964601FF426B23CC8D62CF67EEB8DACD4 -:10E650007E7F0EDB3F12799AB23D42D744CA88EEE4 -:10E66000E7DF9FC8CF2915B0BCC8DCE200442448CE -:10E670002E24A8C17E4829DB2713FBDEAD3CEE70BB -:10E68000BF95EC94A83DD9AAB0F9B76A24B082F638 -:10E690006B2D66F57BAA48C002F3D7A814CFD0ED46 -:10E6A0007337EFFB4A2A89EE9793D11AEED7C87CCD -:10E6B0009F3DB2EFED7897E0BE3E87D7CA848F3199 -:10E6C0008F36B9B94F02FE1AD2DCD70BF3BBFF1657 -:10E6D0009B1ACB1FEABDE58B2CE09B4D377E910545 -:10E6E000CCBE29923FD3E7D0E7CFE472B86C6ACEB4 -:10E6F000C7FC854DF52E2F87B3C5D48EF90C9FD757 -:10E70000F3FB0988827ED1307714AE01913F22431A -:10E71000DE1D5DFF88E8F9D3FF34BF6653F37296C0 -:10E720005F934D787ECD4CF427051E364139AEFF00 -:10E73000B9DEEF3ABFE6947935A63C0703FD42DD2A -:10E740006FA66F15F112C7E95BBA99E5456499E8C0 -:10E7500046E45D08BA14F919225F43E46FD8785E85 -:10E7600007FD2CCF6B8E4D5FB63DC403E7DE644BD7 -:10E77000BC774BDEA9F3089A3DF95C392C1BC7C660 -:10E7800065F903FF334AFB85A72C3A6E9E47BB51C0 -:10E790005F17E556F875321DC21BAE027BB5A85C4B -:10E7A0006B85F37C29A504CFE994964B58161D621E -:10E7B000F5DB3C327EAFCDC3E24DA27EB1A63D0774 -:10E7C000EF2799DEBB38F29E15FBFDDE63E1A5C2A3 -:10E7D000E6CDF3906772FA5E3D5966F9D155129312 -:10E7E0001BB0A13A89EB430ABF8B89FB92025DDC27 -:10E7F000F5C71C5BB7B7B0FC3E910FFDB79765CC72 -:10E80000877696FBA6C1D9B3B2502808FBEBA5DBEF -:10E81000883B4585F98535E0C7153977EF817C88D8 -:10E82000272E647BB6171F62F6C28FCBAFC6FB469E -:10E830005C5FCB188F754F49F406E0433556A6FF51 -:10E84000453E74B9D15EA835D90B179FE2FE8F14EF -:10E85000D2E7073DF988C7148FE5F7800C24BFA3E2 -:10E86000F78030F950CAC77496BB1D10BF2E3A64AA -:10E87000C1E39EF2364DC6F3B19D2CCFE389906F74 -:10E88000D0F3A82F723886B89CF81BCF93ECE172B6 -:10E89000E2752E270E839CA0E52B3C4FF210CF9300 -:10E8A000349F97D8D152FD92DEDE319745927F1684 -:10E8B000E6416D56089EBF1BE0BE8FA2001DC790AB -:10E8C000C7B802E9676FF2DD15401CEB350BDA952E -:10E8D0005D5348562CFFAEEBC2CA41F30F3B5BE6DB -:10E8E000BCD43688DFE8B4517F26D6FB1E71AEABB0 -:10E8F0000BCF5BA4955B08E45565D9FBD8FE43AF0D -:10E9000003E97988D78EFBFB649E93BCABCB53B9EC -:10E91000DDD7350BE6FFE03605CFE7887113BD7410 -:10E920003E3A3A499BB22713E6DF39359809F64C4F -:10E93000D7F87D1B0B205FE4A04C800CCCF3B21603 -:10E94000717F96AF2B4DD1A45879EA03ADEB038FBD -:10E9500064B867C20CFF01ED0EC80818FCBC95B383 -:10E960002846FEE269CC13EDDB6F765C3B1BCF4D96 -:10E970009EE6FD17099C0EB3161207FADD408F8341 -:10E98000E0D9650D21DED62EB454C73A5F5B54C47E -:10E99000F0BDB6F453B48B4971EC7924959BE9959D -:10E9A000CDE70E858E4FDFEB2A8D3DFEE51C6F9483 -:10E9B000AE5F0379D5556D41BB22092E62C0FC1CA8 -:10E9C0006A074948EF28973E2BB5313BC1242FFAFF -:10E9D0007DBF54474FF9FDE5D0F9454E437CFF44D8 -:10E9E000F6ECA4600C3C8B52C051C8A1FE70247898 -:10E9F000FEB58BC39114C7E6EB28BE56887855DD6B -:10EA000029CEEBCD2E2A8B714E6C003C98E9E18E1D -:10EA1000853E5C1779EE35A282BE2CA5FCA88B43FF -:10EA20000C043F33BC167EC7F032B7FFA888C74737 -:10EA30004E739DA7DD8FDA456E9D5D0C87A2155A3A -:10EA40009FCAEB3FF64BE17BA85C9576FD09ED9EF6 -:10EA5000A9BCFC3194543FEE9282EFBE415F9E22EE -:10EA6000A93980B4594F8F820819B9555A66B07FB9 -:10EA70003A24EFE167302ED4970AFDA6933A852118 -:10EA80003980EBFA93146E05857529D15641D94822 -:10EA9000BA6CF05E63CF9F0EC3771A7B1C4119825C -:10EAA000933BADC7F471A36BF4E747F2E0168D6EAC -:10EAB0005B1E9DCF921DC67DD20612C2F196761BBB -:10EAC0009F9BCF8F4832050C5C4E10C97F9D82F909 -:10EAD000BDC4C1DAE3478BF3E87D85FAFBCCEA39A4 -:10EAE000BCEAEDCE20DC2F4402C6798A7B739EA758 -:10EAF00072CC3E01CFC33C0C74FC91DBEEB7507B73 -:10EB00003923A5AE11E07115516DAC647683589729 -:10EB1000B887668173B60DE0BBA0DDBC0ECD06F3F1 -:10EB2000F959D7E0EB1378FF4711C175DC5EA46299 -:10EB3000B934BE66BF06CDA5A15CFD7D104D5C3F1E -:10EB40009065A906FE7D51D023D1E4D3597F7FB8CB -:10EB500016609C4CC075603A35C6C976C121D77421 -:10EB600084DFCB7AF811A5AE04C615EBF96759E836 -:10EB70008120ECAB26B27BA0DE4DA97B03FAE71C1B -:10EB80000EBF2FD1A913A75A08EBFC78E747AFC8EF -:10EB9000F9D1F51112BE1BF2A3EB77CAEE0E58CFD6 -:10EBA000CEE70E03BD0FB42E911F4BE901E146E7FE -:10EBB000F521E837F3BC8EDE407E0A76C974B9D8F9 -:10EBC00010477986C3F19E62DFC7F05EE94BD92E0C -:10EBD000BC7F27BF7BDF503A8FBEEB25CCAB4D937C -:10EBE0004915C04FE4237CEA54D0CF4E4BF0CB2ED6 -:10EBF0005AEFBB8A78B7C034BCCBBC402A724EB146 -:10EC0000B783D24DC6F5B20FE4C9DFAF5B90BC80CD -:10EC10009619890B9347D0F28238E277D0F13224EB -:10EC20008BAF1B8350F3932FA1F3FC491C9D27ADA1 -:10EC3000E7DD90101C41F9ED8F3662077A4D4BA845 -:10EC40005B371DBE932CE37C8E503B51A172ACE22E -:10EC5000F2CF26DAE9F7867EED9C00F3C96A9E467C -:10EC6000DEA5A03C5CC4F8E4E8C35F4E8473E0F228 -:10EC7000374E2F9E33E7F4973682C1C38CEFDD1CED -:10EC80001E6FC6337FA731DD762BC4DB3FE6FE0F58 -:10EC9000D13CE82F5CC7FD8537E3991FF466A18856 -:10ECA0002F05D3F5F66DA3434BBA0C9C076A274199 -:10ECB000BEF3676E2D2919FA111FF2ED75DC6FFE98 -:10ECC00098906AA0F3EBD64C1B9242DF4F6F6570B1 -:10ECD00030CF6FEC68A69F1B4E5282D6C5CF1A94D8 -:10ECE000A00DE477C3499BE1F9DFA91DEDD79D573E -:10ECF000FFC98787A6C3FCAE24E155D0FFCAEB123B -:10ED000058E09EF36B0F9FC74070694C568842E1F4 -:10ED1000D12811DF60FD9EF9B71C13BEB34733FB4A -:10ED2000257D5AECF55DC4D7376D75CD2F81CE1A90 -:10ED30004356B4E5AFFB43C590C1ECE7C693E791FA -:10ED4000802EFED7A884111E8D27CFC7E7D3561F6C -:10ED5000B301DDC3382A7D7E9D431B02F1DA81E0D9 -:10ED6000BC9BDB418D2793893F55FF9CF17774FC59 -:10ED7000346CFF2D87DB6FF75BAA63E577358F6611 -:10ED800070199DAEF8201F684C90689B637C57F407 -:10ED9000CB4831EE5F98E7D55319BE12E67D4E158C -:10EDA000D1627D6F3187A3986F4F4A78910FE9B395 -:10EDB000AF10EE9988D4DD7DB9FA7B24B672FCF5EC -:10EDC000FC309C0BE37F7C61EC733B02CF9394653A -:10EDD000682FBF9052F734C8B77997D10AA58F2111 -:10EDE000F38216763EC53F28BEA370964960E26066 -:10EDF00070B661BB18EFA317393F523F1CF2D4AF76 -:10EE0000E2F2FFAA6D4B30EF49C8A98F36CA28A796 -:10EE10003E42DD42CB8084F6EBFC3A0A6B2A571661 -:10EE20006D9FB60FD4C15599D4064D61CF6F86B290 -:10EE3000CD6A88F78BEF2D38CCECB7859D463D57D2 -:10EE40004F3A3F01FBE0A317993CA0FC6D0379BC4E -:10EE5000E82EE338F5DB2EFA00E6576FF2CB33B835 -:10EE60007E36DB799B47F3F8FE2432E94CFCF24610 -:10EE7000A2ED188D7AC127C33CCA14E33D5BA24CB6 -:10EE80002F61F05FBEFD84CDA50E3CEE112A470A2E -:10EE9000E8B8C7A83F0EE51F476BBF1F4DF170FCD8 -:10EEA0002083CB81D1754FC1F78E1F64EBFFB4E196 -:10EEB000D345704F0C99C3EC8638387C407F8D9BCE -:10EEC0006B0FB4D2F5AEA662CA01E782E2983D228A -:10EED000EC3059BE5676D1F6C9FF58980CEB4C7BF6 -:10EEE000E807D5305EFA43091AC0ADA3421B0FF202 -:10EEF000BEA3D6E985F32A9B291996D3F7ED741C96 -:10EF0000D02781DF4EDE03DB9105DDEB2AE1DE1742 -:10EF1000F7AEDEE030BAAE760BBB27A3FD7CE26D28 -:10EF200025D1EF35EDAA7D0CE6953B9BEA0709CE8E -:10EF3000D16BE3DDBAF109B7AF1A394E8E3F3BEA28 -:10EF40008EF3E05CC27E19CDC74F1BF2D1AF1F4DCF -:10EF5000183D89FC7BF836D891027EC7A8BE22BA3C -:10EF60003CB5D1DD52D04AD7B5B4E731BC8FA361EF -:10EF70006530632EE8DB0715A647F9FCD2FE9855ED -:10EF8000A9BAA2FA77AEE4463B52D8C99713F15317 -:10EF90008CF1C2399C0F2EE7F6F1DC0406E7F9C4C8 -:10EFA0009B0BEF5D61272E0B85D9DC69DD65CB40BE -:10EFB000EF2EB126837D036B898577519AED20C1B1 -:10EFC000878D0F24FA21EEFAB1D45708831CB13291 -:10EFD0003EEB7B362EB025AFFF38D631CCAF6F2C51 -:10EFE000E4765D01D1E0FC40E3EE51781E2C2E9ECC -:10EFF000E27102CA3F3BE0F579D0FF74DDD73CE314 -:10F0000008E2B930715F999BF813E9779A760FD9C6 -:10F01000027646DA086DFC723ADEC7D6702ECA0B4D -:10F020002ADF24AA5B73C7ACB944A17CD53894DA33 -:10F030005DB47ED14377B37A7E789185D6AF7DE893 -:10F04000D14B144A9F8DA3C3EF43FD96879E66F56F -:10F0500009E14532AD6F7C683FEB0F7BD894B0B6C9 -:10F060003F74E012F0FF8F2433FB8178C35702FD19 -:10F07000343E3DCAD2A15BEFBA314C3E1E71B07E28 -:10F0800047F2C84F6701BC3DE1C259BA7DB9EBC731 -:10F09000083B96D971629DE23D92197BFCB1639861 -:10F0A0001EBD661AEB7741026977B0F3757EB0C773 -:10F0B000F6EE1A8570491993C2E145C7298D8E2352 -:10F0C000E028C613DF5D0C7A1DE4BE95CA7D9D9CC9 -:10F0D0003997E38D7EA70DBF53AC8D877BAC1A6744 -:10F0E000658F07BC517C291C5F8A1D2F57DBCCE63E -:10F0F00047C74D2E413D3311E2CA7BBFA6FDF3A2A7 -:10F10000F336D3C78C314C1E5DD3CACEF7F7258FAB -:10F11000403ABA2081D98BA494C28FCAB38D1C6E99 -:10F12000EBC624333F32828721128EDFCAE197CDAE -:10F13000FA9FE97AE7F0799CEDF5EAF0A4417C6565 -:10F14000EFCE22C4D3C6081DAC338C736485E9BDF1 -:10F1500072CA78308F9411F8DE6A07B1E373B22572 -:10F16000F25E1E7DEF82697D13811F96727B98F897 -:10F17000CFC7BC86062E2D96B6876C10975EDACD6B -:10F18000E2E4A480AE0FE863564D295F9F9BAFCFAA -:10F19000CDD61730D02739D4973B3BB13FDD46E081 -:10F1A0001E19AF78021FCFC0CFB1C603BE18081F0B -:10F1B0001D671B1F629E267846E06C9A9F8027F091 -:10F1C00031BE576CE42731CF5BC644E2B1467ECEF8 -:10F1D000FB96DFAB60EF2DBD91E211EC1FD548CF60 -:10F1E0004B7BF22CF38BA3EFB577AFF0819C4F9064 -:10F1F000541607EFA9F583FE6BDA558171AAA54F66 -:10F200003DFCA49FBEBFF8D10D2E48AEFA48E9CA16 -:10F21000003BB861FB2A17DC33F7A1E27781FCFCE5 -:10F220002820C7CC5B7F9BCB01617735727D73E46F -:10F23000B7B7CD04787CB1DD8AE70C9B76C405E3D3 -:10F24000306E720DDA63B4FE36ABAFFE04FCD8A6A6 -:10F250009D46FB69F16F3664A8484FFE6116DC04D9 -:10F260000B0E83CDB0C66D56DC4F693C247BE9673D -:10F270004813E9BB15E6677E1FE67192E2BDA95B04 -:10F28000BE0AF2FBCCED5492A03DD6D4731BDA69D2 -:10F290004D3D177E00764593299FA27E003BECC52D -:10F2A00031DC0EE3F7A40BF890403ADA37AD0FFEED -:10F2B000B2E46D3AAF63DBFEE2928AF57A7325E23F -:10F2C000E9D3EE059B9E5607D6AF1F837D10A77F1F -:10F2D0008FE157DD29B18DA15DAC6CB0065D101FCB -:10F2E00068D86CF5520D4C1A1EDEFAC0AFC1BF7C57 -:10F2F0002DCE0BA9A64B1E7EFE9573697DC963D6E4 -:10F30000B41A367D27EC730B3C41CE06D829022F68 -:10F310008B7FFFBC0DE290F01CEC5E819F258FF58A -:10F32000DAE09C9F198ED3BA7B6D980F6BC653F7AA -:10F33000DB33C004697DF04B1BD0F747BB25BCF71E -:10F34000DEFC7EFDE6E75D40870027F04305BE2238 -:10F35000F8EB87B7E0CCA74BB11FC6434E85BFC7BC -:10F3600001476548E78F3C0D7194D7E3BC0087FAED -:10F3700047AE75C17A3E5096317ABF6F5506DC971D -:10F38000576FF567B8B164CFEBEFBF1EE9F0EA83C2 -:10F39000D767B07B24B42C768FA63F0BD6F9B37B0E -:10F3A0002FC1752E22754887F5F7B1F8C6E70AA96F -:10F3B0007E2C06BFCC2D66FCF2C19638480E221F6B -:10F3C000C03E02EC9BBC28E3B9FB7EF72291E558D6 -:10F3D000FF9CC717C61547EEEDB3837DD7C47B35B9 -:10F3E0006D5B1D023C1DC9D186403C9FC2C1CFE16F -:10F3F00026C1BDEFF2C1E943189E880AFB21F81E21 -:10F40000B5C7A7C173E81FB26A8E12C37BFC7E1B0F -:10F41000F67D11DFA0F38E87FDF40F32585E9E79E2 -:10F420007D1DC5421E9010D1D3D940FCBF6D0DD2B9 -:10F43000D7678718FF34066AABB13D640D0E81F6BD -:10F4400040EF6C09E5439C61FF3C421FDBAC9CBF75 -:10F450008DED749E8AA487EF6E09EFD314F4B2E8A1 -:10F46000AE38C37E7D947E8CF745097E157ED6D559 -:10F470005C1E98D76D960F97169BFE8EC2BDE9A7AE -:10F4800015FF6EB0061EF835F033E55FBF0AFC6C61 -:10F49000C5F8C0D1DF3DF7CA1594EE8F760B3E3626 -:10F4A000CA5B331FD73F5E4662F1F151A797C4E4B0 -:10F4B00063FA3C261F3BD9B9E9FF57F2F6EA01E4AB -:10F4C000ADBFD8286F3F27C549E711D0334BF0BEF9 -:10F4D00057337C85DF6B96A399C56A4C394A7F0EFA -:10F4E000111D3C051C057D2E7E68297E2742C782A2 -:10F4F0004E051D47E8D4BC6E233CCDED5530775DFD -:10F50000FE837525F563C0CE7D560E6CA1533B4E30 -:10F51000E7722B85FFF1DFE561BED12AEE071C778C -:10F52000F7B9207F6C15F73BFA202E99147DDEE7A2 -:10F5300060F6D2715F9F2B596737BDBD4B76819DB9 -:10F54000170E90EA58F1242AB1711E6132503BDB4C -:10F55000173BCEE3A1C779BC73BAECCC6D8638708B -:10F5600017BBD77FE18ACB5CB02F707CD7883B80FC -:10F57000FF7EF66799DDEBE9D714C89358C0404089 -:10F580003E24FEBBA7D0752ED8B504F31BCC7194D6 -:10F5900045CE6DB8BFF039B9194B73FC6431C4590D -:10F5A00080DEEF353DDF7511D2D762137DD5017D49 -:10F5B00065F5A7AF1704BF8E27E3F5E7CF9673B9BC -:10F5C000375D2EBE03EC99E3D4CFC75C02B9F800D7 -:10F5D000E8DDCFC1EF07C6F0A723DD2EA9FBD0C61B -:10F5E000EF71467A177468F6F7CDE5B127FE3EE96C -:10F5F00026DAA5E1C9374AEEA1E5B1275F2B7C06E3 -:10F60000EA4FBD9AFB06E9DF7FDAEEAFD0BF39BE25 -:10F610003B0EE7737CF79F726F82FAD37198877500 -:10F620007C651CE645F9772706E03CDFF11C16B740 -:10F630006B7DF6CB12CCBF206D88C793C536668F25 -:10F64000ECFA9FB7207FFAD35D712AC4299A7627F6 -:10F65000A0DFDEF4B403F35E8E3FFBE5247D9CE97E -:10F660003F5D4FA38DC5338F2792398F033D2733DD -:10F67000FFAEE999C95B215F6E694FAF0DF607A632 -:10F68000FDF15F2520978E3FCEEC0FEACFDF0F37DD -:10F690001DCA639BEEB652787F0C3622F5C3378DB8 -:10F6A000EDBE14FCF0FE706170384EE100EBA2700C -:10F6B000A907793A103C868EB521FD7FFFE0F1095C -:10F6C000FA170DBBCE413E8AC245D2D8F3C4805D45 -:10F6D000C2F5B3E7BBBF2C017BEA68F70AB40B4E57 -:10F6E000B5EEC963BFAF74F06DD72D054F67DD73FD -:10F6F000BEB7F866F4FF16D757663EE84FE74FDD12 -:10F7000080F54712BD38DFD3E4FFE6FFDFF0FEB837 -:10F7100084FBF2A7C2FB2FFFD7E2FDCF1CEF896E5F -:10F72000C82F3BFEECBF72896EFDA75AF793FF4BC3 -:10F73000D71DB18F649F1DAEB8EF24C1109C5F5FD1 -:10F7400035809DF2EE5849E4EFA01F22F277E4B431 -:10F75000C56867C8691D6837AC22EC1E64BF6AE1E2 -:10F76000F7B1B1BCEFF66C6F00E3A28AAF7E33ADA8 -:10F770005B8737783B7004A37F2667D454439CA5EE -:10F7800075059D171DA735DDE26E55E19A764B3064 -:10F79000AE04CBB7A15C9DF1C3FDF05DC569BCAF04 -:10F7A000D669F237E20B6CC6BC62B2C70DFBD50E50 -:10F7B000AF0277B95353D678BF6DEF58B6AF1D4F30 -:10F7C0000298B779A6704A2D191C4E66F808B8F54C -:10F7D0008313F747C57DFC4A5A4708F85021D49F48 -:10F7E00064EB413F14FE8E14ECD7589316793BD846 -:10F7F0007E8A1AB9C71FF220B8BF19B96756B5A0DB -:10F800005F2AE0AC1B0FD76F86F399C257E0C54162 -:10F8100066219E1DD94E6F80CE7F95CAE0BE8AC2FA -:10F820001DEE1717F0157033E3E17DA0519D1D1FEC -:10F830002D8DF93AFE4AE2817D96E9F294B01FECF3 -:10F84000E5F204B4978F49242851FFED5845462529 -:10F85000F815C7726C0A9453FBE89A74F3BDE0A4E0 -:10F860003DF237F4A05E41920DF5633985F8FE3420 -:10F870007B96E1BD0390B74DFDF66359E576DC0F4D -:10F8800075E719DE9B99E0DA02ED07208F1BBF3F79 -:10F8900003FD9B1F641619C699F9CEB17BAFA2E593 -:10F8A0004EEE57F74DB5623CFED89FE755021C2F30 -:10F8B00054C71BFA1F24EE74202ABABE2A58DF450B -:10F8C0009EC986EF36BCBDA710E2103FF256189EC7 -:10F8D0005F5C7EA1611C9F3D1C04F2AED56A0DCF1A -:10F8E0001B9ABF204A2A21E7357F4D9489D47C0F8B -:10F8F000761BC699B87FA7A1BF37E49E0626E3848E -:10F90000C3DEE7A014F9ECB654BBDF42CBB16F57AE -:10F91000CAB0EF59F65E5D2B84A1CF3B463C400751 -:10F92000E79078DC0F1C28EFFD4B4BA00ED6F90BAF -:10F9300039E081327ED8A21258D747999D326C4B5C -:10F94000DF23D55D5E0276D6678156A85FF075B776 -:10F950000CFE64EB0E19CFD74D976B12FE0AF2B86E -:10F960005BC21CFF06A705E3F04753BA4BAED5D1E7 -:10F970009DC8DB31F371D1C48A25307E5BA6D6D514 -:10F980000BF2B4F2EF57CA31CEBB12B7F15EBAA296 -:10F9900089BEDB619F5EE425C54F935972FB0FACB6 -:10F9A000182FB9D5E27570A1807AD73DC3BA19F87E -:10F9B000DD3A8EC98DF8BF1015E241F1A975329C70 -:10F9C000B323774898D722BEB7A09CE5DBDF5E2241 -:10F9D000EE3771A7FF642CBC9FC8F205209606EF96 -:10F9E000D558D04E711DF6EE83FBC8EEF41C728321 -:10F9F00078E8A979C70FFB223D874353258A9721D1 -:10FA00009D15270A587F02F1CD1E4F55C258D46F5D -:10FA1000E59887B39CE7CFF44EFD8D07F4C7F2A2BB -:10FA2000D14306CB2F779D9488AACB33B08E5371E8 -:10FA30005E2E258CE7C55C27156C27E1F1CC1FE411 -:10FA4000E3BBE6A9AF5E0BF3D86FC57C67A2684B3A -:10FA5000601D1DA3DF543B701D84FF5D9130FEDDF2 -:10FA60003CC84FC20BD19470E64F629CC33BB2A31B -:10FA70002C19FCF2D40A2F9E1B4C7D588E9C9B05A2 -:10FA800038DC0EFFC373B597BE5A45C7DD01B2928D -:10FA9000B50709A5EF0E9B68A7A2C6C3EF3DC4F644 -:10FAA0004B2F831843BC6CEC3F2E3FD25FB36746AD -:10FAB000C7FF43C9A5AFB6C584671CEAEB8E1956CC -:10FAC000CC9F38355C134E01571783EBD7542B640A -:10FAD00044E38BEF496A2ED0DB9D705C80FAD1BF86 -:10FAE0004CAE0B96A4C3FC8363E1F97C9736642A81 -:10FAF000A5BF1E9B967B23C6491C98FF55FBF3A30D -:10FB00001BE1C8986BE6114F1BD08DA2254C8038A5 -:10FB100095FB0B940B22CF2D0A474ACFF49BB75B82 -:10FB2000A2759013AE285C35B82BB84307673BAD80 -:10FB3000D772B8FECF23F597B5017E17DA912EAEB6 -:10FB4000E53CD5964CBA20CFEE84FB814B811E4E0E -:10FB5000ECB062326B0F34821EF5D8D9DFF5490B59 -:10FB600067C2DF71197BD082F1BD37297D68401FE4 -:10FB7000C1F1087731DE8929AFA6C0F98913694A36 -:10FB80000AC06771D88670FB894282707F6A4FDA3B -:10FB9000C26915C81F2AB677F371264FD4FE518269 -:10FBA0007A9D9FFFD5CE95E1BED481F065DECF87EB -:10FBB000F8F0B92903D3415B851DEF1F6A2A5F5115 -:10FBC0000C7A62797221E663355549A8879B9A3F82 -:10FBD00043B88BF1959332517579533D104D4CD705 -:10FBE000DD237FD286ED0DCD27509ED3E9E401DFE2 -:10FBF0001CE3FB9D5D56F2D35A5A36FC5BFE69ADA1 -:10FC000013F72DDB419F34903DB6E53A7948BA3F72 -:10FC100089C8FF71147777D6BC180F72B656725F19 -:10FC200002970ECCEADE7B19ECE7D73ADC97C0FEF0 -:10FC30007F8EF71156CF715F02FBFD631F4D9A0354 -:10FC4000FBFBB559EE0DF09741AFF016CDC1F63C78 -:10FC5000F7CB509F316E06AB27323A4879347F8E0E -:10FC60001FF5B913E1F2697B4260B07B48AE6E7E4E -:10FC7000C600977EEDB284795198B841E9E79F6B51 -:10FC800086B17B710B4298A735721C8BAF67A4B00D -:10FC90003FC92BF277D346100DF657D39E72B07B37 -:10FCA0005BDF0BE502FCAE7ECA1184B8E4D2FB9E9A -:10FCB000B3813E9A2FAB85C057B3CBEAC68C2B835A -:10FCC000F84908EB5737EFC679754C70F3FB72FBB8 -:10FCD0008A217E55CFF39EEB4DF9BF8B9D7B311E64 -:10FCE000B7789B31EEB68484DF023E6DF8DDE079B3 -:10FCF000BFEF58D83C140E8FF972E84A1B9BD7F916 -:10FD0000E3E8F797A6F462DEB1E20E65D4217C1B2E -:10FD10003CE8AF64C6E3B99A5B87BE5E12EBBE985F -:10FD2000EE16AAFF29CB3DDEB2134BE77882EB1922 -:10FD3000A2846D5E3A4E2397CB9342EFD8F4F983B9 -:10FD400073395C9376B2FD6F735EEC5CD05700172D -:10FD5000BECFBC74D60B53002F029F1724906ECCDD -:10FD60005F4D215E8E172FE045C03FBADF4CDFCBE1 -:10FD70008B451702FE84E5DBC53379D1F78403EDAB -:10FD80002BF3FCAFE3FA57ACA39DD7079A7F3BD781 -:10FD9000B7677BFEED5CAE9BD721F8583C177C6CB7 -:10FDA0005EB798F799D359C8763A7426E44C23A9DC -:10FDB000F3605C96CB150167314F01AF9E01F25D98 -:10FDC00095E63F18D6A3842AF1B0FC7650A420C74C -:10FDD000BA2FC4942BA57917F63BD3F508793BD0FD -:10FDE000BA849C35AF4FC85BB14E2177C57AA75214 -:10FDF0004182F210EE7E90C07FA833D8C3157062A6 -:10FE000041BF0F64FFB9A13EDD7DA3A1FF0F3257B3 -:10FE100018DA2F54D718DA2FF2AC33D47FE4FD95DB -:10FE2000C9AEDF6C68AFD51E34B44F0987A681DD3B -:10FE3000FDB7966ACCE73EFFC3BEE7A01E6C7163B8 -:10FE40007D4F4B26967B5B54E4EF7D2D1E2CF7B740 -:10FE500078F1F97FB59463F9428B8665A8C587A5CB -:10FE6000592ECCFCFD650AD8EDE5A12EF407C68F0E -:10FE7000AFFB0CE4E1014BA03591C2E99C37997DC1 -:10FE80004E02667DFCE55B37815E77B37BE8DA7A0C -:10FE9000274B6A0C7BCE45F59DA6A317574D98C0FE -:10FEA000FEB28BC4CEBBFC6A1CCBF7C17C3D4A9B27 -:10FEB00073ECEC5EDB397324CC4F9C43D879055A44 -:10FEC00006EB68FB4C85F841FFD73A15DC8F22FC26 -:10FED000FCF0256C9A70BFBA3F0EF4775A2A9E57F1 -:10FEE0009A0D0FE97C654DC6BCD64BCAFF82F980DE -:10FEF0005738D9DFCDBA7CFFCA7FDE44DB499BBFD0 -:10FF00008C9D8710F786BC6E3913BBE12B386300DC -:10FF100079A09297FDDD9464C5ABF70744F9D771DA -:10FF2000CC1F98D9CACF0B1C2468C7097EA4EB6BE1 -:10FF300087F90BBEA8752BC1512ED0F7EBA641FF58 -:10FF4000FF0B270420E00080000000001F8B08004A -:10FF500000000000000BB55A0B74146596BED5D591 -:10FF6000AF904EE88400411E76886020AF4E271D7A -:10FF7000C26B2812C01762A3B2038A52A0189E490E -:10FF80000CCC8AA37BBAB11904D6B39B193DAEAE93 -:10FF9000E869705076D6738890B8194D980695C761 -:10FFA000ACA3514141B3D820F258133A121470381F -:10FFB00087BDF7FE5574572701F4ACC9C9B9F9AB31 -:10FFC000FEFAFFFFBEEFFDAA961D70B98300505DDB -:10FFD000B63A0F0A904E918EDA902E5BF50398FB9D -:10FFE000E178D5393017034C95DF08A696009C3D83 -:10FFF000046E1BCE1FD3AE9EDAE1C27F2E5D9660EB -:020000021000EC -:1000000000C04A3BFE8FE3B2CEBA8ABEF86F51B849 -:100010001ECC740D7F2EE35FF1BE2630E7C4C6E32D -:100020002ED4BF4BF376FA55305B009AFDB3998618 -:10003000FD8BC03C0260B7BF86C7EFF957F1788FE0 -:100040003FC0749F7F1DD3BFFAEBF8FE07FE177801 -:10005000FCA13FC4B4D5BF95AF37B89D00FD01CE1C -:10006000B5560C54F3F06834F6E286F6C999BE141E -:10007000A4664167D3813C48ED60C9C8403A5B62E1 -:1000800079E0F500A4330DAB787F59E63B2C0FFCEB -:10009000F1D991DF59A0FD64F4334329C0BD20F8A4 -:1000A0009F55F6DF17A5541AA83912CAEBBECC3EED -:1000B000B04102B81F02F9F391CEAEACB38C97E811 -:1000C000FE14E709948714F8C274391765423F9308 -:1000D000BA533C289CD0E526032C71ACB1C2700009 -:1000E00094D2B108CAD704125CCE02580C612BD04E -:1000F000FD3F5A8E45E2E4BC14200BB2F1FC6F5870 -:1001000078BE7E1DE8F9B875E50A19CAD2496E2E87 -:1001100096DB7288F07A36F951778D83F6ABB3D2DD -:100120003A89FB2E71BC67C5410FFBB6F2F3D7DAF3 -:1001300057D75315C07C9ABF2653A9DB85EB2EEF0A -:10014000D3F6A06CEA411E4E73E795F5500EFF32D0 -:100150004AE8554E9962571D64A70E30A11EA3218F -:100160003964C3751665D5A5D2BA6898A980D71722 -:10017000B7C8AC0F302BE641A8B74A4D6FED10FE63 -:100180008CF45239A1723AA0FE166D34F2B3C471E8 -:100190009CE5FE3D34F7C86F153CF39D9CDA9DDF6E -:1001A000AA09B79CA4F5AA34B9F1753CD7AA366957 -:1001B000DB7B71F356B853324E249363C118920B14 -:1001C000F2E10E93BF1D90D9DF7AB38F337E607B4F -:1001D0003FEF876DEFA1FD9FB984176E0078D23D88 -:1001E000ED85C0845F4E6FFD8A7DEBDDE44F6827AF -:1001F000E447BA1ED7A20D019E7B6DB93D1440792C -:1002000046BD4E33ED1F9542C154D2CB4570AF462B -:10021000794F6EDE7B88FC64B2DD1126B92113EDC7 -:10022000F17A9DD42E2E4F3C1E0AA6E0FCF16D0102 -:1002300099DC76EC0135E8C0F1980F14D434C699F6 -:10024000F77C32E97DBBBF89E550EFAF671AF39FBA -:100250009BD8CF60105ECBBE7E3F8387ED268A6B36 -:100260002BB43305D3A0CE8401ABCB314D4E413EF0 -:10027000BAC2E0A6EB45075C413A57719B22A7E260 -:10028000B9BCC7D5209D7B2DAA41B1519C0CC87D1E -:10029000F1BACD0C611BC6115BA6099438B98E3D2D -:1002A000170A521CD4E35A7392B0E74997EA658A59 -:1002B0005B4EABBA7513CA13DE4E726F71753FF7A2 -:1002C0003B6E13CBFDEB74DF3B6EA4E0708DF4E569 -:1002D00093FDB4BFF612D94F43B2DB86CF25C66972 -:1002E0003D2EEAEBE872D3E558EDECE2B8BF6C5571 -:1002F00017C7BDC47DAB4DA0D6A3DC3D15AEE25AF9 -:100300005CA77D35CC9B89E33A0BD2BCEEF33FF181 -:10031000947F48F632559ED0AAD0B99CA6ABDA7528 -:10032000F5AAEF78FF5EEF6BFB57B7789D0B1CB11A -:10033000EB8E2249C479303B4FD863FABC5EBD4F87 -:10034000EC9C6DC85B932EA886BC3519236DFCFD13 -:100350000AFBA386F154E7E386F9B764AE36DCBF47 -:10036000CDB5DE70FF8E9CDF1BC677BA5F34CCBF85 -:10037000AB6C93E1FE4CE53F0CF767C8A048E8730F -:10038000F952C8427E3607EA99CE8556A60F422713 -:1003900053152D89E80270337D187C4C977B54B936 -:1003A00008ED266AE91C407EDFF1D6DFF3C82E3A5D -:1003B0007E35DE99E58AE5653D4FFFD47CDCC78A52 -:1003C0007AEAC11E061409BBD5E37DAFFA4988F766 -:1003D000D1228C2778CE686332C799684A9F9024CF -:1003E000C5E2095AA489F2B1EEB77A7C299EEBFEE8 -:1003F0006805F9D107328C70758F3753CD581A784C -:10040000E8BA3BE781FCD8FE41132C223BDB8AF49F -:100410004DE4A3EFDC88D915C74F01F181F6367999 -:10042000CE1488E0F5194E5042387F861D322E508A -:100430002CBCD495370B03C48C0BA828B4E71FD36E -:1004400095429277E0E909692772B5B87423EAEF1B -:10045000A889F981C5526804CAA3A9418CF317A6DB -:10046000317FF74398F5F800442CC4FF3C008ED34D -:10047000F3C1C5F42150589FB8727201C6A7850D0B -:1004800066CF06E4B330BD7338F967FED8C3E9120E -:100490009E0B4B3B85F82934C13AAA6F743E6A35EE -:1004A0003E3614291574BEC2F4D60DCFE2FE9D8DE2 -:1004B00026D88CEB9C1CFBF82310978FB77ACA6F59 -:1004C000A579DB245028AF065A6CA12D59B47FE7DB -:1004D00000CA07FABCE59E8A1945B8EEAC22607DD9 -:1004E00043EB5F80F433D329640F53FAB30CF0B9B4 -:1004F00061BEFC9EFC33C0CF15922C6F0071A18CA5 -:10050000F7E5F1236FBE317B4D1EF313A03A6EABBE -:10051000479DC7E7B7622CA0F3BF6C0B6DE67AABC3 -:10052000669884E7AC7CC566A2FC7F18E333DC0CDC -:10053000F0A5DFCEF47FFC4EA65FF933991EF5BB24 -:10054000987EEDCF61BAF0023280FA3B59A4541183 -:100550003FBDF1D17B9C117C4425985DEFE87EBFC7 -:1005600052F3878286E34F25931D34C96EB2D3FCC4 -:1005700046344C3CF799E63121392B5EAEEA13C480 -:100580006741D3A77F185F42CF999D12CE3FD3D446 -:100590003580FC37F17C57E4D16215F2D0CEBB2D0B -:1005A000AD75033DBFAD71389D10E308083B247D58 -:1005B0004A3DF1B19AEDE4574522DFDF65EB2C713E -:1005C0003A62FC01951898676AB53C3355BE944A67 -:1005D0007E3193D61D4B767DD347B45F609FF04349 -:1005E000D4EB3C5F9C3FEDD0E4A0D3FC16AB8FFC7A -:1005F000695BCB6777DF81729831EE36AFEC8ACDDD -:100600007F9584E025FBBEF8EFCF66F07C276D3543 -:1006100007364D75E2BCFBEDBBDE27113CE03C3AF2 -:10062000350DC7F332A53D44E7BBB2A6A5531C80E8 -:10063000103FFF50CEE43D6462D3DD33AD544F4CE8 -:1006400026A78A8BBB15768C378638DFCF30BE2540 -:1006500073B061FE6DAE6CC3FD3B72720DF7F57D3C -:10066000A7BB8B0DF3C85FA9DE463E58EFB0450E21 -:100670008D90C80ECE7DB194F99F5342FC47517EB8 -:10068000562C1C4E95AD7FFE590A1B8DBB53C93F9E -:1006900013EBDA652DAFEE515CBDD7B555E0EB1B22 -:1006A000967AAF677BAB07AFB7AEC538F2078A2340 -:1006B000856FDDEB0CE239B68DBD78830BF9FBB8A5 -:1006C000A8E77A37AAD5BB897674C55E2597B09F0F -:1006D000FD32503DA4D7BD897604F094560708FA40 -:1006E00053FD7DC627226F7D437EDF2FDEBE351A88 -:1006F0002A32E499422BE617D44FE7DF64D84C172F -:100700002EE139743D64C7EC1F1EDEF4FEA012BE5C -:100710001EA0BAB68AF202AE9FEC91C4BACB76BDE7 -:100720003F2823761F561E35CC8727A53D86F19A94 -:100730002CE3F899C97BE29FEF2D1E556E7CD4AA5D -:10074000629CAE7C4EE27C95785F3FCFD4DD490A57 -:10075000C54D73B38DFBA92AA7028A83AA26CC2391 -:100760003DE4753D3ECC91A1A6A73837405B77FAB2 -:10077000EE24907FC6BA87D156E83C81FF12F9E695 -:10078000705F057C71FB647944FDD79156F74F3F4C -:10079000E0BC8E3F839B44DF9126E26E41C34993C8 -:1007A00089F25F1F612F05CE88291D69745172007F -:1007B000D09FAA17A7044C85787F78E7677654FD09 -:1007C00028CFA017EDA8B72F4C2643FE8952CCC3E3 -:1007D000B1677BE61CCA3F77EC4E0A9B7E063F1E44 -:1007E000AA399016960BBF7F90EC46ECA300FA470F -:1007F000F5EF40DF57A13841FCD378A967C8E1E79E -:1008000070DDEAFD220EE06D47623F7B7F5C3F0BAF -:100810001B85FFDAF197EA9D2A084D73106E10468A -:10082000FF875FCEFF67781C195CE7909FDFDCDDF8 -:10083000AF75BFAF3E28FCFE6CF3F79F509C3F8B1B -:10084000F92FDEEF75B9E9FE5EFD82CC7EA95F3F30 -:10085000D32CDF1AEA41CE65BA5F296EF6D75AA7C4 -:10086000D8B776E2F9BB29CFD5B6A086A4EEFBE8CF -:10087000B47A9D0CAEB87DB6EDB42D0A39627C44D5 -:10088000F5FCDAF27DFAE43C415753FE853A2DFE41 -:1008900088BA06F3AA2583F2EA4CC9BD05C9C196F8 -:1008A00081E524BF8312845D1E5EE25E3B9EEF1EE7 -:1008B000B11C5D77507D06993966DAE76E4DAFF76A -:1008C00068F8D2AC96592328DE7FD6B0E0A042511A -:1008D000CE93CDFBFD1A025C1F1E4CF30D5D4175DE -:1008E0006850D8F9C1B4CE76C2A30E4E4C9682128F -:1008F000AFBF26BEFE3B68F10DAD61BE345C4A1948 -:100900002D5F4EFE09FDB21617519F0149F477EC99 -:1009100007E641CF30CEB018427B14DCB7CA1DE6E3 -:100920003A7529085C20B1BEAF9AF0AD95F24362EA -:100930003F3AB969D721A9A0071C23C16EAF855BD7 -:1009400024F6C1BDE10F3FA6FBB678E2F0C3C47A3E -:10095000FD4A5DAAD7555B92439BF13CEF4EFCB735 -:10096000334B71BC724BB293FAEED3AFD802149FE3 -:100970004F6FB68524BC7F3ABDB38DFA90D3DBF3BD -:10098000DDB802549A5CFFF906E5F93F59D82E000C -:10099000DCC23FAED8E9634728DED56E499180EAD4 -:1009A0006B55DCD77B40F9F514AE1316EF1814B273 -:1009B00049B13C43FEE1C2D2E2D4CB490A15FDA7BE -:1009C000F7DDD397F0AB76D39BC3180F939F3CF220 -:1009D000383EB7F4B5140FD5139007ACB7459B4715 -:1009E0006DA2FAF8258BBA97F8AF78FDCE8159B48D -:1009F000FEA7FD81F88936EF1840F551AC6EEFB9CE -:100A0000DE3BDB9CDD17F26272D2F1C4757F5CEDD8 -:100A100023BD274B2EBE6E861A6530D945D34CA018 -:100A2000753DB2A4905F76AE4FE63A35D1EE8E7842 -:100A3000449FB24CC71FFA813D93FC47059643740F -:100A40007DEEE60D28A71F3CE95ABEEE1C79777EA5 -:100A5000BC7DB655BD43F6B9D1C6B8487B92B16EE0 -:100A6000D0E9FF7AD2789F4AFB39030E51B5EAA24A -:100A7000719C87FD1E3EEF09BA8A1F45BA42937FDB -:100A8000D7685F87079F5F52FFFBB73E60B96CFC7A -:100A9000C72F68DF7D0E81C77C20E497D80F54DA1A -:100AA00005EE01B089CFAB5F3FF9F2E70564872718 -:100AB0001B7347921E17C8AD275E423ECFA4B41EDB -:100AC0007902E9F67D9FB05E12CF9B88DFB44B12AE -:100AD000F3BB8CF8C0EBF77A7D72717F7667EEE33B -:100AE000166CC867F94D95F3FA921EA3A77BE957D8 -:100AF000B473EAEBEBE7D3D7D7E7398B85BE3ED4A7 -:100B0000F0F70E6BEB19D26FC75BB912E18357AEEA -:100B1000A7B716A4C5D9CB2F85CBDFA7E123874C78 -:100B2000AB7F63457B6CAF7FD6A2C6C7BD9F88C72E -:100B30005FA907157039078854C2790B9933E37898 -:100B4000A23E2667C0F104ED78129D07FD72A24611 -:100B500061899AC9783BAD873409423C0E4E76BB19 -:100B6000884E927C8C7BE87DC334A819427C98EC3B -:100B700011C609D7103E8975CBACB4B57766E17E56 -:100B80006BFAC35AAA67D658845F04E627733FA757 -:100B9000CB49CF33E0CC33E497354E7099719DD972 -:100BA0006658674917F36E44391FDCB7E07DC25DB4 -:100BB0003F37D7F4A77D0F3B9ECB974C54E7855228 -:100BC000A867FCE2933F79FF8673BF046522D515C1 -:100BD000F7EEB573DC4FC4271682CAE34A8858CEB5 -:100BE000E1735F8DFD71CB6E88F1F5D5B81F1AA941 -:100BF0004FB83FED292F3D1F28871CCA4BE7935262 -:100C00000B889F5576411FEB93BA99E869A723405B -:100C1000B8ECF9A46121CAA72F49EA8364CFF81C74 -:100C2000F7B18123C921CA778FC96A15E3D0695604 -:100C300090707EB4BF26970E60B9442DDAFCEF5C4D -:100C40003C2EA9F0304E09E75D1C97C727E49D9222 -:100C50005C93E8CF2E8BF9133BCD86BC5352A8E1B1 -:100C6000397F77719D3AE982F9AA79E952B1E8773B -:100C70004BFA996A7AAA179FD5EE07212C0B9C474D -:100C8000D40BE3AFD89722931EABB47115E535B4FE -:100C9000AB68AA3D2023BFE39B859D8D37877711E5 -:100CA000C5280BABA8BE68C2BCA79F03E30A64E6D5 -:100CB000B23D8CD3ED14D79A8BF3D64A35DCC7D826 -:100CC000A9AE41BA416AE573FC0A3A992A5A3E2F05 -:100CD0000737D329E0638A76CAF456A8637A3BD4EF -:100CE000339D0EAD22FF8F0E0739AFC1934EEE0735 -:100CF0006FAB3451DD51F2EB9EFB87462D9EF42EF7 -:100D00000774BCD29F2E876980FE97DD833C86E402 -:100D1000701C499447A29F4E8488CC7E4A01229B36 -:100D2000F00317FB6B05283C9E7A9D72288BA86602 -:100D3000C66F12E551D1B35DECD4ECA2966CAD7FD9 -:100D40004C4F5DC52E1EEBFA42FFCAA43A34518FB8 -:100D5000FAF592E4F22E1786E22F761C9F63C6BC4A -:100D600054525CBE221BC7EDC5DFCF31633E2B1949 -:100D70005FBE63388ECFECF8418C0BCB8B2D6EECC5 -:100D800062569F9F3305E7ABE49F8544D10F299EB0 -:100D9000A9A23F5EA9D531EAEADFB89DE82FEA5063 -:100DA000879BF8B463B19F847294B3C57BC761B766 -:100DB00086775B70DE718B7A90FC77B93D9CEA4256 -:100DC000F9AF5C3D752085CEA7AD62BECD26705AC9 -:100DD0009D3FBC1E48C2F1F6EDB92BA4E1D73E07FA -:100DE000AEFF35ADAFAE1E1120FF551B25B7D06C41 -:100DF000F9C0D928C3F6560B106EAAEFF7D468F5E0 -:100E000014E747979BE3F760ADCE69DF9E9B4B7A73 -:100E1000EA2A163818646415931C8F8EF675D1FC77 -:100E2000688AB0B72ECAE5DEDEE9E012E53B9A9F9C -:100E3000783DFA0D1E009F3797A8E7E97E75F225E9 -:100E4000CEFB678A3E5D1BC98AD9AD844A9B8BFC69 -:100E500007150859393F4C705EA95329DE2DC4751A -:100E6000501E253E3548216ECCDCCE528AABB8AE42 -:100E7000A904F7A9B6468615E173CFDD73C42AEC41 -:100E80006E88B03B2D2EB5ECDCFFC46031F4419C84 -:100E90009F55EFBCF8C39728BFEAB30E374D8FF9C3 -:100EA000D78B2BB8DF0487218EE87E37AEC9C6F515 -:100EB000F6F8E6510B69DEC44FDBB289AF496D111C -:100EC0007E8F166DF97CB03887DE879C977E4E3E0C -:100ED0003EA9E58993769117E8BD30F77B8DE2BD99 -:100EE00070AD8673D6B648A100C71FD13F2FD2F888 -:100EF0005BBEBF710FE1278B363E349DED2824FA8F -:100F00000A17FE525C587248F4CD4BB71AFB8D6A33 -:100F1000EA9B693E84AD640FCBEB13EE6FACE0BE91 -:100F2000B93A3EFEF7D0377B4B347C6C280C65BE5B -:100F3000E4B97DD51EE261625F5C05CA8412AE7BB6 -:100F40007D32EDEF35F78C3FF42FD0DF9389FABD7A -:100F500052DB9BE4E460B958B99FA87D7985DB49F1 -:100F600063CD6F3799A8A7C689EF7D04F1CFE97EDD -:100F7000BC789DC47D076CECC73658F89A4D217E2D -:100F80000B5F1BC87D08F64B5C1F6E7ACDB68EC614 -:100F9000C1DFF509C885844377DE40384C3009EB62 -:100FA0004D81E783E4611C867191474BB4B8AFD59E -:100FB00001102E32F4F3412DFFD7A68C1C889D73AF -:100FC0006CDEBE4186FE24A8D5DB25744EAA1BB775 -:100FD000DE20EE27093E767DFC0FC954F7369A7D58 -:100FE000C9846B9F3D309CFB98DEE4EEC53404570A -:100FF000794FE9FD7C7AF6D5F456F28259C84BB3A5 -:10100000DBB7FD0A7C6D89E945E76FAAFC4685954B -:10101000709187C1493849EDFE578376EA0BD703B3 -:1010200023106741D8F3D953267EEF5E0A39FF3A81 -:1010300001C7DE536677089F6FD0E222BD7F76C579 -:10104000D9994DC37F935C7DC015D74727E7A41B73 -:10105000C629EE1B0CCFF52D1B6EB88FF2DE4CEBC4 -:10106000434069CD2B8DD5BD69CA68C3734FA74E68 -:10107000DBC77EDFFA08E352FD6EF518CF2337CBCE -:10108000140FE09CA897CAF097FC6D0C0482A48F03 -:1010900071EDC63AAA2C52C77D63D201B30107B0E5 -:1010A0005D0397DA44FE457172080C11712351DE1D -:1010B000C6EF2F6AF7CB5CEFD50EC54235AB27796B -:1010C000DF6490B7EE8FBADCFBFB8C721F38DB2835 -:1010D000EF41AA51DE831719E53DB4C628EF1B572F -:1010E00019E59A1530CA317BDD38C3FC1175E586E8 -:1010F000F1CD2FDC6E983F2A74B7619CBBF53EC3DF -:10110000FCFCFA0586FB854D4BAE4BFF45E15AC30F -:10111000BC44FD17EFFBED55F51FC05FA17F607D5F -:1011200094A13EC2AEFF3F3B38A6C759DD0EAE3399 -:10113000CEBE4D3ECB78C2844880ECA02C99ED64A5 -:1011400046B2883B1FEE3B7B40C1F147AE624B2667 -:10115000D5595AFDE0D3E290DECF24F68D7795493C -:1011600009EFFB930CEFFBAFF55D9DB7356C1817DE -:101170001D00FE6EC673C8FD2E51EF7185E1AED223 -:101180005335EF121D7B8ED376B77E55FF3E2FB1C0 -:10119000DF826507F8BDE25CFDBD0C394569777CEF -:1011A00052EFC7F43E37B1FFD5FBDEEE7D9AA86360 -:1011B000BAF71BEE4C33D7D12AD7D57B259571CE04 -:1011C0004DA3D4C15E2F3501D8279BA84F8E04852F -:1011D0003015A0F7D051FA9F8A90C0B3F7111E1FA7 -:1011E0004D03C6CF15A9EEBE401E1FDF192915F00D -:1011F00011FD147BD5115ED4EB31C9B9B698F089D5 -:1012000071DF0EA37A24C72BEA3C9B8C92C2BC34BC -:1012100070AE0274FDC7746594D71BC34B7AB39B41 -:10122000C4EF931AFC61A666A79BBF5F4AC417234D -:101230002617D7A781DF4AFCDDCFB774B8B1B13A22 -:10124000E6EC3A0BD731A0F5F30F68F2D7718FB9FE -:101250001A3FC770894598971F68DACB7A599AD98F -:10126000AEE125355C8F3F34C4E1E1EFE19462B734 -:10127000C0C9741C64B0FC53EAAE6BF1BF34F3B464 -:1012800001878237FA5DD7FBF218DF62FD63EB0559 -:101290009E796CFD50C6CF63EB9F613CEA819A8FCB -:1012A0000DFE316FD561833FCC0F1C35DC8F64742C -:1012B0005A087F8CBC3568DAFD28BF8E465B29E969 -:1012C00003EDE011D2ABBE7E647DEE14DAF7DA7C7A -:1012D0007ECBE768F3B7B27E753E8FF80FF138E248 -:1012E0008F247C9F26F8D4710E9D5A77438E99DE09 -:1012F000274A7DDC842BF7867FE87E662A1DCEEBAD -:101300009C37B94E089CA8660CD57F6D930794D383 -:10131000B9DB865ACD828E14E3416576319E762BF9 -:10132000D1A8C5B18E709136497C4F3457525E9921 -:101330008FFB3E314A7D9AFCA17A496701F95F75BE -:1013400061E44109D7EFEAAF6E20F948D85E0C4A54 -:10135000673EF8BBB353A6408184AEB2C7FBF57DB0 -:10136000D4279EEA13384315CACEC623626C15FEF5 -:10137000F8A1771FFBDF715C8CF80CFC5912F89414 -:1013800023629D89EB64F4579FA77DE97B327ABF86 -:1013900047D7C93E75BC346A11756254AB175FF606 -:1013A0008A7AF69504DA44352EE18F44395E3F336C -:1013B00092F0F4B31B6D40F52DEEAF984A62DFAFAB -:1013C0000C405EA88E7DDF2AFA4CCF5F6C618A5399 -:1013D0003AAEFAA6378BD7CBC8167869C63F63DC1E -:1013E000223F8CB40E9B991277DE03C0387607E15A -:1013F000D17138F69B5ED1AFC3C322EE75AC1FCC62 -:1014000078FBF2FDC78E50FCBAD7AB36925C1798CA -:101410005CA5FC7D56EA2EC6CDF67A5DBC2F9E9764 -:10142000F9C538B486F4B4DC1E619CED5AB87A6F05 -:10143000FC772C6C7D3E8F71645701D98DBE2F9E39 -:1014400063AF370EFFD6CF115BE7EA7EA0E3C3FAA6 -:10145000F8E4CB4F8FD4F0FD79BE1EF2EB114D2E88 -:101460006D969EF1F88B5EF11EAF9B7E6E0620FCA2 -:10147000DFD607733FD26FBD82FF8E39C80FE31BE3 -:101480004A11E977F9DD0E37C9595F1FD751DFBC23 -:10149000CA3E5DA37DDF10FF4B6A047EAFDF8F4A3B -:1014A00042AF81F5024F5DBEF3F091277097C5AF53 -:1014B000E717533ED09F4F9433CA77247F7F278B03 -:1014C000F75F28DFB3B47E226EFF73E51A1D2ADEB4 -:1014D000D346375D1C46DFA72DA7EFE10AC83E04BF -:1014E000FE050D465C0BE515207CA3FB7B2DE0F78C -:1014F00063362D9FD8F4E787980DCFD7A7F8924A87 -:10150000F1FC6F697103E7874CF43DB7169F1AB47D -:10151000BE3B117F696815B86943A695EB68AA7F41 -:10152000E8BE5EFFACFC58E0A62BB3449D4DE7241B -:101530003D4B87F670BD7005179730DFA31CD3AD08 -:10154000EA9052F2277505E733F946D433BD0FF917 -:10155000EBED1A8E20F2A357CB875E5A87CE95D734 -:1015600097F36489B62FF6178CDF8D0555AB1F34C2 -:10157000FC6DFD1E03FEF07FDDF5EC49303100000F -:1015800000000000000000001F8B080000000000A9 -:10159000000BFB51CFC0F0030947B0A3F20FA0F13D -:1015A00067B2A1F2D3B850F9875950F9FE68FAD161 -:1015B000713B13030323137E35F8B0083303830C08 -:1015C00010AB00B10E33F9E680B0BE2803438104AE -:1015D00003033B90FE23CEC0E00E641702B11790C8 -:1015E000DF02C45381581C287E16484B8931303C99 -:1015F0001185E8B300B23F8B9167A7192F656E1E66 -:10160000C594611359543EAF1A03839B3A03439F19 -:101610000684AF8D24BF1428C6A70661EF976760C4 -:10162000D004F29564B19B7B0028AF0594DFA681BE -:10163000DFFECD3AA87C0733547E269A7CA30B2A82 -:101640005FC30D95AFE30EA101C062BAC4D8030019 -:1016500000000000000000001F8B080000000000D8 -:10166000000BCD7D0B7C54D599F8B98F99B933997E -:1016700099DC241398BCE02604081A7012C243C4F3 -:10168000701322468D6182687197BA23AD36A240ED -:1016900040D6C647CDE41D5E1AC4EE22B874E213EC -:1016A00094D6D462FFB4AB7402B8D2966A54ACB488 -:1016B000B5DD485D6BFD2BBFA0A2D4D2B2E7FBCE57 -:1016C000B9997B6F2601B4DD5FE3E3E6DC7B1EDFC7 -:1016D000F9CEF73EDF39718A0EA2CE23E40CFCD09E -:1016E000E71B84FE64269E84741332039E03727883 -:1016F0002A3CA3FC3D7B0696F60AA4008BFD6426DB -:10170000217984FDE43576AC16A7113296847E3AB1 -:10171000399F96076EAC217E5A7EEB8A3FC2B36337 -:101720007165F5651A21594B7A5FBD9C3E03E198BE -:10173000102926640B1109C986FE0AA3155E42DA38 -:10174000A0B339848C8966E9D16228E8B440C8BF67 -:101750002A7C20226A322DFBF0D7C43C8C27214EF4 -:10176000122FC28AC219D7F0F6F6FAC6D307ED8C4B -:101770003AF9F0FF3504E677B676642D1B2F4AFF61 -:101780003943F19293181FFBC9AA379509E0C7FAAC -:101790005D1FC2FBEAFF93F1B249A95B2BA3F3AD36 -:1017A00011D518D427BD69322D076E93495CA0DF8F -:1017B000CBBA058776F675E920A4BAD78BF815EA77 -:1017C0007C09F8AE2502CE67DC5DEFF474060839BB -:1017D000B9D41B42FA5009C9481F3E9F6F371112F6 -:1017E0007799CA8B2B85088E17FA69216D1F5D2C9E -:1017F000861E07786A16A5C17BA3DE37F938C3E9D0 -:10180000836832C5A3CCE943AE1175F7B42F4F1FDF -:10181000F217A48FCCB5A676E4FCD70BF13EE3DC3F -:10182000E9E3CB8E67ACEB70BE6A4638C6DD55E89F -:101830002674FD1FA85E941A49526FE4752D457EEB -:101840000FD4103D96A4DD3A584F9C67D4226FF018 -:1018500049D7471A5ADEDB2DEB258D9DB9A46714B5 -:101860007C4801EB7C8D7E9D8D92F64E062DCAAA9A -:1018700008FDC9BCBF0E75599400DD026D537C484C -:10188000DD257142F9830449E8710E8148CB4E553C -:101890008FAD17A014C37531E0530A45CB788E5C29 -:1018A0008F653DC892A86086DFD9E844386460132C -:1018B0002EEFC228DC18DC30C4990950BEDBB2FE22 -:1018C000B297C4DD54AEAE2B2C25E67530E854102B -:1018D0000C3ABDFBDCE48A7DBCC55638CFB99D57B8 -:1018E000D6DE35DA148CD64E26EF1A78A2C87B1DC8 -:1018F0007E31AD7BA783EC152E22A435B7230A6F6A -:101900003BE17F17237D82D0229DB9A52AD013D930 -:1019100029C800A7DB208F603AD6EB211AD2535496 -:10192000B883403DC91B463C19DF47868BD35D54C5 -:10193000EF2BA4FD5ECDBBBD9AEB3352E67867C0BA -:1019400080BB00E79128D3797C7827FD1FA58F689D -:1019500089107B5C18FEBD06F421954735F0DE2426 -:101960004F5C82559ED5F06F079E7B73D2744A8F71 -:10197000FD218980B86A79CEA557D1FE5FBD548814 -:10198000B9040E2FAD5FCBE13CAC67E4017DF657A7 -:10199000B9907E6B2FFF2C00E47B7CEFEB72327EE4 -:1019A000AD9DEB48C041FF5B659E1FFD6F0C8C81B8 -:1019B0007C59857464C0B5A2544238FAE70A3118DC -:1019C000E7E06FFF70DF2514CEC36542C8A521BCD8 -:1019D0003E42C7EBD73F0E8C26278831BE4654C007 -:1019E000A77DFCA1F550424B802FEB55A7B69E8EEC -:1019F00077AB143A047A8C8C65FAA15E9D5405EBA2 -:101A000023098C3EE60B59D8AED5DB3206D75D5A9A -:101A10009A545ED55345A196C2F78D93468533E619 -:101A2000181C30D175E35BF9F71D34C13955F00549 -:101A3000DE4DA1BFCC22B3609D3FF22E4A8D939123 -:101A4000FB7BBF4969961D847CD6A4DD77D031FC31 -:101A5000FBAD1269E82D1EFEFE4A41E1F8883AC14D -:101A60003E33E63D344F6F00E9FB5610BF94D46F10 -:101A7000DDE96E96CDF2C7368F21FC7EC1764A60D5 -:101A80004D345B037E8B2C14A01F99FE3333C18F22 -:101A9000B7EEAE637C6783B73DF0B781F76C7CFC33 -:101AA00091B7A503ECD55607A397B64C31D442861F -:101AB000D38BB11E061ECF753D360A6EE40F838EA2 -:101AC000EAC5A5A3AEFBD9E8E80EA0A30BFFFE7400 -:101AD000B405E868C63F241D6DFD47A4A344F97210 -:101AE000B41716F2BEFA067EFF20C8E75FEA12CAF4 -:101AF000BD5FCE65F2FF97112617FB4964D30CD06A -:101B00000747249453FD7AAB0FE1A52631CC03FDA2 -:101B10002E4A7FAF83BD3499CAF526059F74F679A6 -:101B20008BE8F7572FFB2C17F4D7AB746DC1FE264B -:101B30006450D769FB5786CAD40087B29B95079B30 -:101B40004F45C13EEF1758F927CDA7F4288EB7B1FE -:101B5000E3728ACF85F02B8563F15C418F25A18BE1 -:101B60009F094E86972A62D1AB745D7E26507A51CA -:101B7000C2ABD1AE26244CD03F2CA47682C9BE681D -:101B800004050672B9CA85FACFDEFF2BDC2EB4DB62 -:101B9000718BE79638405FB8C227E401FA5C1816EB -:101BA000B00CF8574D708BBAA0831E08CF753D025C -:101BB000FA2F2C13879A845F17EA2E8BDD7582EB40 -:101BC000318A9725CC6F51F3EAA626EA9F30F4AF0D -:101BD0006D3E23D185310FA37CCDDC13073360DE4E -:101BE000D54268223454D4BC1B7CE6FE530CFBC6A1 -:101BF0000778FBE5926B52191D4450AF1AF4F4D3E9 -:101C0000B7BFE180F993C51948978B6B248B3DB919 -:101C1000A82AC552BE6EEE35A3DAE12462C28389DA -:101C2000EEFD3904E994FC37B553289D462B072374 -:101C300068B71C13B4565A4E2D6F1C0FFDDE2DA62F -:101C4000637DA1BC71F200DA5B0B90FE53789FA913 -:101C5000CE863F14805C9D28924734B04747F70BEF -:101C6000DA399D1B6547201215E87A6A51B5541A76 -:101C700005DF315DAC4EE6374C10D9BAB54717A930 -:101C80008500D041ABDC48AB6A40FBCFA84FE97878 -:101C9000829809E346F1FD101D77D179D1761E6651 -:101CA0008B90D40B16A59251E6D1665B7F2AFEF588 -:101CB0006472F6560E1FD9CBFA3764526A3AED3F7A -:101CC000497DE3D9C9FB3F1512493FC0298715E477 -:101CD00087A24A62EE87E8255876F2A22B1856F2C0 -:101CE000293E5DC5224C83B4173FA2CB1AE0218A5E -:101CF000EBBD81AE6DAE892F37FC45423FFF56B13B -:101D0000A019E4C686BE5B8846F1E109C60896A71D -:101D1000DEAC009E365027AB1FC6977B09C0919260 -:101D20004B7FA7E3A4A824A6D1FE64AD372ED2B280 -:101D30005C4D423AFDE453438287CA89FDC1826605 -:101D400099BE6F5B4A503E12901E26FA690BBEA6E2 -:101D50004B403F4B4808006E0B2CC37976142FEB99 -:101D6000CAA7EF4FD6C8183F20A729BC865F4FFDF2 -:101D70000C4F11D161BC0D5924E6453B5847FC3A44 -:101D800055B67EDAD642129F4EBFA7CDEC83F1A3A3 -:101D9000DF228C2F09936B32972744A6F407E33791 -:101DA000AAA1F549E84F21915BC419A67556C3E86D -:101DB000C7DAF196EA2457027EDB4A281F24917B7A -:101DC000778822D2412CB46861419271EE16359425 -:101DD0004F46593BE544F847AA9FA82793780674D5 -:101DE000AD0B8017120EE0FCD2C9D08F0EE50C3E71 -:101DF000DF31A401EB056777F701BF65EBBD158007 -:101E00008B6FFBAE7B15D78D3CAC821D4BA12D3C5F -:101E100093919017A073607E1F8544F43B7C625CB5 -:101E2000D569073E777F109D5F8D605C2E159A50B7 -:101E300080D737296D6097F8494880EFBE901C35F0 -:101E4000DBF5A984962DF11472A4702661221FBFC0 -:101E5000AB7DC03A6A51C34500CC16BFFE5FE03788 -:101E60006DF445D00FFBCCED9F06837DD3E37F045B -:101E70009E9FB9C7C5D03F0B317F4BA1FF80BC4BA4 -:101E80009D2D5BFC9B34DD5ACEB0F9610B242FCE27 -:101E900033ED6AC2FD2BBD66E298045C14A23AA041 -:101EA00097CD553201FFDFEB65F018F06548F7CCB0 -:101EB00042FD18928F011C142D08C749723A0E4B2F -:101EC000EC2F22183FA5701DB3C175CC06D7313356 -:101ED0005C8D0A9BAFDD5E8C5692A2060ADC0B225B -:101EE000F73FA8DD0476E349F2815E0D8413BE124C -:101EF000F5AC5F656DBC4A3F062B54A2221DD8EDA0 -:101F000046BA4E1F59FCAFD9BCAC1101E641E1B451 -:101F10007E27B9482F5896C8505C78D96C035FDA91 -:101F2000577E43F9EF96430E02FC45F95882EF0EB7 -:101F3000FEF5161E1F5E06FE35C5DFD749D80FF029 -:101F40007D48448C437D485EF34F37C9C9E322B7CF -:101F50004F6089CD7C4C424190E3B2B7A35FF2233E -:101F60001A0C7A13CEE03A86989CF732BA8B12A5F7 -:101F700019F56117F33F8D78EA4DDD567FF81B5B4D -:101F8000ADE59BC9A231102FBDF9410789D17E6F04 -:101F900031FBF7749DDE105584EF1BA4A103EC9276 -:101FA0004E07B33796A94486F8E78AFFF71F336FC9 -:101FB000A4F33909F26006D8EF147C931E591E88E9 -:101FC00039F5E2E1F36B1542B5970823CFAFD3D1D2 -:101FD0005F0BFE77749303ED4C628F83EE91300EAE -:101FE0006A6A87F07EADCB3ABFB3CDDF3E5F421E5B -:101FF000C0F92EDF7923DAE723CDC7B933B9BDE9BC -:1020000095044BDCC7E06B83DEEDFC5D26692CAEEE -:1020100043D520DA2BBF4B89B5E2FA36CC82F53DA9 -:102020005BFB8BA17DE6176F5FFE25C79F7F96F652 -:102030002B94C105B0DEEB02DD61E04F238EB5923B -:1020400044F51CFAABE3F9D55130DD86EA05CFB192 -:102050005E2EAD279D43BDC2D1FB3BCEED92977660 -:102060003FEA043BF5C3A7DEAE053BE0D6FF94880C -:1020700042E9E1F86E1F89A3BD1273827DB39CD241 -:102080005D0CCBF199D798EC614AD1B80EB73EE31D -:10209000433B62F9B3AE580D6DBFFC87BF9F462826 -:1020A0001E8EB70CFE570ED0F353028BBB4607A60D -:1020B0005D43DF2F97C9BF8493D0D18D12E3A70F63 -:1020C0007E94B204EC446167DF0DD86FEF571C2E8D -:1020D000933E5E2239705C5A0FFD88E82E213651FE -:1020E00060F099FD0123DEFDC12E81C1B7D71173C8 -:1020F000037C3B7B9C115A6FD5CE1348D7F39FF9D5 -:10210000AE1FF0B06AAFD54E5FB5538ABBA6E1F300 -:102110006D7882061566023E193FAFDCB302F5C644 -:10212000CADE0D27809F57ED7558E43FC54B280E3A -:10213000787D530AD540F9074FFA358AAAF7FB1F75 -:10214000F7035E69BF373A295D2D9C6D6D07FD9FD2 -:102150004A1FDE1FF50CD16F5ED5BB8E8DB7E7EA47 -:102160003F80BC5D45989E32F8F97DF8256BB89E9E -:10217000592759E35B27C9E199B80FB83323A9FF61 -:102180006CE81583AF6FFDEEC91D513AFE07CFFE17 -:10219000FF1D513A8FDBFEFAF18EBBE9FCC83EB75A -:1021A0000AF26AD5536FF88909FF8F496C3FE0F84E -:1021B000AE279FD846F9E4F8AF5C68071E7FE10FB1 -:1021C000E3343AFFE3DFFFD318B053D7BE70D958DA -:1021D000C0C7DAE7E68F1DCD5E07BA8DB9CCEB1B21 -:1021E000C3FEB5BD026C8210F23C7FDAD6E9C01E98 -:1021F000290E21820F8FBA622E8A9F55F45D6329C2 -:10220000ACDB0AD45750BE87E27BE5EECE13D2B4E6 -:1022100064788FE6884178C6734810D6FD9A859712 -:1022200096C1D311D2804EC820EA097BBB5547E83E -:10223000FA5E34F27A527BC209F85FB57B1D1BB798 -:1022400097AEA77FF87A7E08BF5C3C7C3D0F48D6EE -:1022500038D34972DB77B6C1C73D19B8FE23ADE765 -:102260008AE7AE1DD5BF33E4C3D9F05C2F30B8EE9A -:1022700097F4D725E0C7679F7E625B80AD730D45FD -:10228000CCF1EF9E1C079BBCEF39066F003939F883 -:10229000824B05BB7AF90B6F22DF1D7FEE55A786B7 -:1022A000FBD3C42B503D799C0CFDF483DE5C29B03C -:1022B000C2AAC77C71973FB15E2B6375D59A1FDFA9 -:1022C000BF8DEF638C1F56C6FA160B49D6CF2B175E -:1022D00030FD14CB44BCACD0FA9DAAD7BAAEC26CC8 -:1022E00058CFB71700FD8DB49EC6FC5598FF2CD370 -:1022F000BA3EC6F878247E3DDEE39285D4E1EB7CDD -:102300009CDB15AB62C29BC9D69D901616DF1B21C4 -:10231000EE6D3CED74E194AD7C6EB437E67F363EF5 -:102320003FFBBCCE0F6F27B9BEB6E3EF83D3C9F531 -:1023300040812C70BDD55D9D6DD2776E07D563F958 -:102340006077364473F213F076F44A28DF3FD829D9 -:10235000A1BD6F97132B47F0EB43C6387BFBA681DB -:102360003CFB60FF8F383D327A5FB9FB6D6794EBC1 -:102370008598592F407F49D6630EEF6FD5F3C9FB7F -:102380005BB5FB44D2FEDE97F5AF00FCEFF73B48B0 -:102390009476F17EAF94344E52283B2C7656876F5C -:1023A000E6D154DA4EF27B3498776B8BFE6614ECF0 -:1023B00091D71C04ED4739F49E8B7E6FF57970BF81 -:1023C000A5D57F33D14CFABBCD86273918463F5A65 -:1023D0000E84CBD85E68CCE2CF3A54D1023791A3B9 -:1023E000B9B0CFF972FE1F64E817E2699A292EF49A -:1023F0008A4CDA219EF68A2E849A4992B896ADFFCD -:10240000F05C8968663AD3C78BE6F8A27FFF9D1817 -:10241000D768240D718837915CD2FBB8A9DF879B00 -:102420003416770D8F17CDF13F574383EEA270E43A -:10243000AE550BC07F1B69FCBC06EBBEAF31FE1A6C -:102440001E8F203B9F7AEA295A1E0FDF44A0C3B09B -:102450008E709C66FBCAF3B93C7C89DBCFFB0572AE -:1024600010ECB0EA7B2232C83B217823C64517E442 -:10247000DE282F33D1E382E0892CD0ABDFF98BB497 -:1024800024199DEEE574D5FCAD27B2A0FD36F757B3 -:102490007299331B46F87278BCEB60E6E55E88EF14 -:1024A000F5DDB2E0F0243ADF6C552210AFC92615F5 -:1024B000DE120A67CE1129E44EB20EC673078FEB07 -:1024C0003DD2A4A2FC7FAC2988E527385E7736157B -:1024D000E1F3A9A6107EDFDD341BCBBD4DD5F87C22 -:1024E000B6298CEFFD77FDB8CF0978B997F442BCD7 -:1024F000664FD312FCFEC3A6083E1FE7F3590078CF -:10250000F15AE68FF198BD6DF35A201E63E0D18E2B -:10251000F779247AD085FBF9820678BF5366F2C535 -:102520008EDF71AE5E01E44BE36D04EDD71D3C6EB2 -:102530006CCCF72199D99B7B383C3F7447BE27C3AD -:102540007E53756131DA45241C02F9BD4308A79614 -:10255000D02A2F66CE0A9AE570B62FB24736ED2BF9 -:102560008CEB62F19E6D329357E3B5137D69140FC6 -:10257000D5B98206E10463BEFB2BB45C9093FB05E6 -:1025800001D7BB3A57224526BA37FAFB0F59E4FB6D -:102590001BC9E576828E993C48BF422E02BFF624C5 -:1025A000F18424CAEFFBB2C81E42ED8F7D40972014 -:1025B000177E9B827162C3BFD9C8D73B1D8802F2C8 -:1025C00025DEF2C540FE8CE4F774F0FA1F71B856B0 -:1025D000C8E1D765DC57E6F15712C73826A41C01BD -:1025E0003D6E732FBDBF8A3EEF9BF3FE51880F7E79 -:1025F000F89C5B03B836951DF39BF148EAE50FCCD8 -:10260000FBF143F2E6540EC6C5FE8744DE96CD725A -:102610002830E884F6FB046D33EC5F47DF9090FFD1 -:10262000F609B12918C79209FA05FB6E09627E877F -:10263000D1CE17B2F277BA7B60FB2A9877BD3314FC -:102640004DC217BF4ED12CFB46AEA0B57D1074E62F -:102650000C56D6287D96F07987645D02386690081E -:102660003E67110D9F598EC8E7308FE9A4370BCA1A -:102670002D29E32E61FB077F37BC298E7F40BC19D3 -:10268000F41A9C53847090BBC4D0440DBD490B9D7B -:102690002F74081CBF0ACAF3ECA1FDA98697F202A9 -:1026A000D80D8B93A8292807B3DD0C7F8D03273025 -:1026B000BE1B1C472C71F7F67A11F960DB5B6C5F6F -:1026C000EF647DC1E649B47E05D1EEAFCA1F3E0F6F -:1026D000833FB629E1D464FB53C6D3E00BA3BC7996 -:1026E000FC0D04E4D0BF8FBF01F38EB2DF726BE04C -:1026F0007754FC6E5733C8C5F6B7597EC5514F6441 -:10270000AE634642CEB4DFD2301EFC20B72F5C0E43 -:10271000EFC3B9B1EB41DE9DAC5EEBC2A97B59DEE4 -:102720004BE33DDAE6C9DAC8EBB3A371F4FD1B63F2 -:102730005E3B605EA3EC5F18F332D6EB64F5E2C15A -:102740009B35903385A99124ED86E4C9158B471DEF -:102750007F07D72B74FE4BCDF439AE51C5FC16A3C1 -:10276000BD315F7B7BFB7C13FBC0E79617D4EB206E -:102770001940EFDFFFF3B81FBC82A2312C819EA667 -:10278000FCB912E099491AB04CE4DE2CB06F0C7A17 -:10279000DED6F14416EA0539968FF95DE7385E3BDF -:1027A00009872B80DF4262C86CAF18CFD6213A8FE1 -:1027B000635CD5C5E58098724F30199E87FACFB516 -:1027C000F2FF4642989C8F2B28E72150A8D272FE38 -:1027D0002152BA9EF6570F49A1749C0A99C543A687 -:1027E0001FD27A24165795EA7C263CF2FD0623BEBA -:1027F000DB4EEE21AA067E45491F5437F8F480339C -:10280000F2A003F2F0821AE67B3A021181EDC7B121 -:10281000FDA1226E975C262D55C02E692461E5022C -:10282000E0DB23126179788CAF5DC63E18E7631751 -:10283000E763CAC1589EC4BF3FCFE96B2FD8276852 -:102840004F303ADAC3ED93AAC1C1033EDAAEA8BF56 -:10285000BB12A6F32CD82B2EB04F42F8FD7B60AFF5 -:10286000D0F281B47FBFF2028A979DBA18025CEF62 -:102870006ED2193F34D5E3F74612F5AC06B9F4B081 -:10288000A8029C9D0FB7487E5ADEA50818BF78B8ED -:10289000A901EBFB4F7BE2E06FEE52E202D8232767 -:1028A00043241405B8A97B04F39AC4E751F14E3FC1 -:1028B0006E973F11FBE8F7F7D37A5B667B709FCC8E -:1028C000E0AF498D83EA95C0578F1FD35603FC3381 -:1028D000D6E8507F63A800F7299EA4F88275DAB97C -:1028E000F5A3ADFDF4BB5FEE5C0D7EF0E4BC456886 -:1028F0000FF9957FBF1DCA7EF5E97FC5A7F2A36FCB -:1029000082BE9E1C132DFBE77EE5E777C2F7CA81E6 -:1029100050552AED67CA91FEAE2BE8B33DB456047C -:10292000124F4DFF23EE6BEC17D4AF77435CED46AF -:1029300027D2AB7E546F0676749459F320330F4739 -:10294000206D818C3D48F14E00EFBA0CFDBEE7C80A -:10295000473A0BFAB3AAFCB4FCC463C77E7A05FD00 -:102960007E60EB1A948BAE8765B4C726FFC75AF218 -:102970000D939C703D2627CD2B7DCFE1627CF4F03A -:10298000E2EE291A234FE0BF298F572928270E5B33 -:10299000F31C8C7DE11E1279CF81F4CCEC135965C8 -:1029A000FBC8B0E705FB8964BBC8F8241CF198F3A9 -:1029B0009F8B1E12C3C9E2DCA71C32CEAB2D56552D -:1029C00004EB209FB903F7C948B7757C633C3AFE16 -:1029D00029B37C935506571EA87EBA9E7DCEDF6430 -:1029E00001FCA71A0C3D15473D75B0448C8FA7F02C -:1029F0003DF0A01883A4CC03D54C6F6D9259BEE076 -:102A0000265E7EEC348909F9093E9ACCF9EDB1874E -:102A10004566CFC508EA3972FA0CDA175EFE3DBD8D -:102A2000E43505F727A2BAB762266605F21F13BD83 -:102A3000501C5D14F558E4ACD8986E59FF3C6AB14F -:102A400058F3A90B12F52590E34714A0DF93D46F38 -:102A500005FA9DC7F789AA8C3C4CE9F47498FF7677 -:102A600043CF1A7933B63CE9C71B9679205EF8A2AA -:102A7000413FF50D3AFA3FAA0BC733F6098B6E0BAF -:102A800047417F3A72ADF9D315B6FCE879B6F2F951 -:102A9000C6574A9DF638EAC62948079A1FE55521C8 -:102AA000C7F3E31753773E75789C65A85F1E4720F0 -:102AB000DD7E5CBF424E40F7DD25D5835FE07FA021 -:102AC00034CD9C5F70B993D9DD077FEB2260E7EFCF -:102AD000AA52309E69E4753AF8B8B54E0DEBED7A1E -:102AE000F00E05DA77060ADC80AF0373967B30FFC1 -:102AF00083E7A71A72B765CEF22B6F01799829A2E6 -:102B0000EE69CF6DC9867DF907AA14CC3FF5A70CF5 -:102B1000F41EA065EF93CED023F4FBAE8AF81273B7 -:102B2000DCE60E27D35FD73BF93ED0466BFE06E5C9 -:102B300083EB9D901FE66DC07D4B51E179BC36FF64 -:102B4000DEC0877FFFF562BE8F3D0B7CE08F32FADF -:102B50008871FAD8C1FDD38741FEBB806E98FCDF37 -:102B6000C8FD537BBF13EBC3FB9D6087DDA6964278 -:102B700028CABEBE13BAACF6447ED42AE7C6DBE947 -:102B8000BE21DB523FA7BEC0F2DD17BAC0669FC4AC -:102B9000995E236C7D3ADDDE0920B74BA9DE6576B0 -:102BA000862A86CDFB2A36BD5EEFD09B9CE761DF8F -:102BB000F853C20DB03E767B7A035F9FAFCAFA3AF4 -:102BC000E70CF4DF36C093DAC73C5FDD6A7F0C8325 -:102BD000935038A78E0AE783E703E7D9F6D9ECFBD1 -:102BE0006BDF94C25B5FA1CFF254960FD9EE63FE08 -:102BF0007C3BC45169F9C79C0E9F764AD8FF5E3E64 -:102C0000DFF2145A3F097F1BF1D5E721F106EA8D67 -:102C10004D9E670916107ECF49FEFD7927DBCF2E2A -:102C20001F3FFA38FB601CFADCE8D07FE434C5F1C2 -:102C3000DA9CFA7F9ACB7127DB7F1E5A179E476971 -:102C4000D8637738F43E73FDC4D32A378D7D904C1A -:102C5000BE9E3EC2F8EFC525CBD64DA4FCECCCF50C -:102C6000A2FD93B9A46DB5E887FCA37E15FC814C49 -:102C7000BE8F4F1633396AECABA7D758E5AAFDBC17 -:102C8000958BE7C5BBECE76CB87CB5D3E348F2F5B0 -:102C9000774EEBBEC650FC7A04BAB2C7AF1BE15701 -:102CA0006667723B389CBA68EAC8F4F872D3E0A64B -:102CB000831313E557E0FC4C523A60FB89FEFD7F1D -:102CC000AC595C06FB762C9ED6DF142F7F676242E0 -:102CD0007E85E7A6BD0871CF70551ACA9BDAE0A7BA -:102CE0009B0E527FBC4EEF2B7FC734CF7E95423B6D -:102CF00061143ED11D9F9BF9EB4981D14F3B1FEFE2 -:102D00007E8E4FBB1DDD29465DD0EF2764401792B4 -:102D1000F8B5E679B721DE06BC406723CD3BE46217 -:102D20007CE59FDD1082389DEB8C847CE01A6FD8A7 -:102D30002D21B45BA6BBD2D8B90F6F01EEE3513F92 -:102D40007DB00FD6C1CBF2FB0DFDF8B1114FE57A86 -:102D5000EFF63456DED0C4E2C7AE0317BFA9D17672 -:102D6000BEC30EE2A6EFD751B90E71C02E6AC7C31B -:102D7000777FD90081387A2BAD1F31F9DDADA14ABB -:102D800015EC84B6E25245A3DFA5A9655896F34B2E -:102D9000D54A3AE605AE6FCFCF843878A18879B5A9 -:102DA000C5B4DC4C4DBA54978AF37BB9E81D2FD8D3 -:102DB00067A9E09CCF48ACA7A32CA24B141E475098 -:102DC000AD845C8C21BDCDE98CBE7F04E2254F0A29 -:102DD00091992E3AFF97F9F9AB4E6743D11AF07BE0 -:102DE000E4A80BE2078D0ADB87007A689B9E807B54 -:102DF0001EC7AF938F3BE407F1F5FC441E88426A7F -:102E00006BA748EA93ADCF152E26E7DA545D1D95E2 -:102E10009E54F9734BFEF45CC64FCE00A5A724F177 -:102E200047BBBC26AE709D2B3391AF441756453E31 -:102E300025CCDE33CEF7BCE3D4AF75D1797CCBCBD8 -:102E4000E5586E3AD2297D5FE9F942729FC567F66F -:102E5000CF2D7BB50AFC927E07C68BFC13C8BF84BE -:102E60004DF2F6900B836EF4C9ECA4F5943E629398 -:102E7000595C8200DDA450450CFB907962EC917C9A -:102E800080B7A77A02EDAF539E482DF3443F1579E2 -:102E9000CCFEDF54E9A937FB01EFA5B0FD97B5DE05 -:102EA0008A67010FC5DE5825BACF909D39869D9F50 -:102EB000023ABE502503820872304C98DE0C294C31 -:102EC000BF56A9705E4A201172266534FD683D57D1 -:102ED000F5941C6BF1003E022CDEE5DB2A6032A08B -:102EE000D4ABC73DB44EA977519B8BE98B2218A771 -:102EF0006FA6877869FD4FFB9C681FF6FA7264C065 -:102F0000EB3E71D97720FE34F82B17E637F6FEE555 -:102F100002CCBFEFF55DB200E476AF400E51654FD5 -:102F20002A4EE5F064439202FB7CFEF93A817D8EE5 -:102F3000C1174908F2831DC19F97BF331D279E22E9 -:102F4000CEA6EDDCA4CB4DDB853EF77C3C8FD2D505 -:102F5000B3DED22D1791445CC588A754A444B603B0 -:102F60009CED637E5D0F7CD345E194D07ED58300DC -:102F70007769A688F14792E98D4D8478D9A14015EB -:102F8000E48F56C825981AEB9FCFD6FBA827F238B6 -:102F9000F453A5D655417CBDEC888672764170F518 -:102FA0004128CF7C8B95DB9D8C5F205E444C72B7B3 -:102FB000E2D4389C5F2FA793B6A0DEAF0BA3F28DAF -:102FC000EDDC81355FCE4C0790E76EA28388C34C61 -:102FD00007B3291D4C35D3812E9C0F1DDC8BCAFAFB -:102FE0008BF08FFE66959088DB0DE783D54A7AF1EA -:102FF000707E31E0585F961E00396AF0853AEB1E0C -:1030000094ABAE1B9D61F0D70D3E31F8E353B7038F -:10301000F990F2C9551EFA5CECD52E4BC627E08715 -:1030200098F9E19A11F8A6960C1E0CD046B5328993 -:10303000A65251F2F2C5EF158E33F1811D6FB573B3 -:103040000572CC22CF58D9845775E87CA374EEF86A -:103050007F4DD6DA03263EECA07E0818CB5D628851 -:10306000805E29F52EFB14E852AEF97E10FC4187F4 -:103070002B5C8F79B3B33E48B999D2E5A763440D71 -:1030800026DFAE2D7B06F9F9680A01FB64D3CCE597 -:1030900018F7FDF496C878D013EB28FE8FA15E8E4A -:1030A0008D15310773602CDB6FD782EC1909B2F7ED -:1030B000847F8FF1B2CEEB0D603DBACE16F9B8DE4B -:1030C000CDF6BBD6BB99BE59E7EC5680DF06F315AB -:1030D000D59CEF3C4F62766C89C2F79F4EB76A1061 -:1030E0001F2951989ED9D2D48BF6C7BAA6BDF8CC69 -:1030F000A88911C8A7F2144535D8F756FE3A5F7073 -:10310000001F5FC0F667E17DB3C9FECA51181CCA33 -:103110005FA508F0A7D212D5D24D7256118548325C -:103120003B7AA39BC55F941682DF95FD0FE17E7607 -:10313000466148B809CA2DDD2404F1F3387B1F2805 -:10314000D485AF9BFA0DD4F45AF45C2D5D82D45231 -:10315000B49EF0BC4BBBE6C1FDAFDA40E51FE569AC -:10316000C3E9087E8E99E8C180DFD8875DCBFDEF8B -:10317000AA0205F9AFBDD1D903AAF92A85D9459F7D -:10318000042A473D2F00FBAFD472433F179EB00F78 -:103190001B9DCCF661A10CFBB0F0847D5878C23E3B -:1031A0002C7C877D58287FAF49C732ECC74219F67F -:1031B00063A393D9FE2B9461FF159E7B9BEAF1F9E3 -:1031C000E3A606FCFE7C532396E7B9987F438AA2C8 -:1031D00041B097BBEE74EA9067D3C2D7EB805E90A4 -:1031E00011A2EBEA0EB03881FBF00378DED91D1492 -:1031F000316ED7117C807C8D3EBB66F8BA20EEA183 -:103200003CE3C5A75BDE42C01EDB2144EB4988904E -:103210005BBA4AAA646A2714065757A6D3F2AAAE25 -:10322000596D907738496B0E2D531365CD57BAFC05 -:10323000FBA6F2F8E21ED913023CCF6903790070B5 -:10324000C0A6D9BD5D73AB9A0BA9DF54400D159094 -:103250006BF9CE18D0F3D761BD2602FCCCBEBB8A79 -:10326000B40621AE315E7396021FD2FA7146FFE7B3 -:1032700056BF45D1F0BDBDDD68F5C4B273AA47A401 -:1032800051FA83EFC228FDB49356B59FC2BE0164C4 -:1032900006D8476EB6CFDBE560FCDFE566CFB7DD6D -:1032A0008C7F7FE8AEAC74D367A59BF177973B5CCE -:1032B0000DE74D06A78A18DFE975D02EE0F04163CF -:1032C000FEEB702EE88E9FC904F60F1EE27430717B -:1032D000BC8FE9E9BB15D4D3978FFF6E5B3A2D4FB6 -:1032E0007C341402BDBB81843C4027D18D22E6A1F1 -:1032F0003C5D3621BD8E56BF70C673E9A07F3E553A -:1033000098FC89717FA3B9FDE6F11097FAF4552670 -:10331000FF7672B9D3E3E86FC0F59CE1457B853A4F -:103320000C688F340765CC1F12B3D8D3E950FF095E -:10333000EA39A9C28F52789C7F99A560FCE3948BEF -:10334000DF6FD18F768AD31D51D3E8FBEEA888FCBE -:10335000DEAA7A6260576FF096E2B9D268B18CE764 -:103360004B3614B3F8698AEFBA18D827F7F7B9992A -:103370007CF02A983F1A2BDE73A832004F51057E4D -:103380008FE98BAA11EFAAA8621E2AFD0DBFD707ED -:10339000F03CCA06C2D7A55EC4F374ED633EFFF9E4 -:1033A00045909773931AE2770E609E379A5C22ECF1 -:1033B000070DEE4F0178BE6ADC5730D09242EBB772 -:1033C0002D5343B00ED3D4CA6AC82368572BD1CF2C -:1033D00049995AA5DC887268E83C06DE8BD1562CE8 -:1033E000631E117C07BE246DE4209C87CFE1B22CC4 -:1033F00025AD5400FBAABD06C37C705EC19257DEAA -:10340000967E259E43926AD311CE76A22B503F5AC8 -:1034100023A3FECBF12A71B037728C782E1CB13009 -:10342000C51B326EB39ED3C8AA972DE7C2C746AC60 -:10343000E54C1E3FC8B49DE7F85831F6C7AC78B2EA -:10344000CF3723F0481AC09B010779B5E1F3D912B1 -:1034500028AD8379E6A81E843BA8B65480FC1A4B9D -:103460001A9A81EECE1B5E1B9CD38ADBFA61DDA724 -:103470006932D1E8F81791C116E87703A7F3AE7C5B -:10348000AB3E7E48910C7EBC10F8717CA348A2A68E -:10349000F1210E19358D37A12BDD529ED89D6DA9D6 -:1034A0003F796B81E5FB94D80596EF17EE2CB59428 -:1034B000A7F6CEB1D4BF686FA5A55C12BFD2527F6C -:1034C000FAA14596F28CFE7FB2D49F757499E5FB04 -:1034D000C503CB2DDF2F796F8DA57CE9E05D96FAD2 -:1034E00086BD6ED78B13B9DD72BE76BA0BEE89B08E -:1034F000C465AD7E80DD8E57FEDAAAB5805CF33BF5 -:1035000091BE65D0E3B4BCE64EE64729E5210DE463 -:103510004A0E97A3D93EBDD40DFBA97E05F581ECDB -:1035200065F564EF02B43FC66DA5F2683A589B6436 -:10353000E87B0AC8E5A66879A129DEE456BBF16CF0 -:103540005685BF1AF7378CF6B2AA93880FC6D3D820 -:10355000F96AEAA5423DB746DB9BE6B54F14F10890 -:10356000F420F5F71E31F97B23F977767FEE5CFDC9 -:10357000B77122F1E0B90221DC00CFE286572B219E -:103580001D98FA75D701FD6E7286EB7B68BF9B0AAA -:103590003C6C1F94FB755DF9BDC81783F932EA17BF -:1035A000226BC5E6785C33D74329CAD3E85752BCAF -:1035B000A3BC35F0BE411888B582DCB9D383F27064 -:1035C000DC7FBB5E03FE520A941C85BE0F1D70EAB1 -:1035D000B0BFB485E3B5402DA984905261B06E3F71 -:1035E0003C2769D4CEA0CFA2A2CDFBE179BB9BE55D -:1035F000035F10FA7E25C812A59CD97FF23467AC10 -:1036000085F623A9148E247E85F194FC5BD9FE45B2 -:10361000A1FC2ED01B58F567E8142AD215CCF77000 -:10362000031D08F844FA7107BCA837DC70B815CA46 -:10363000B21083FD3FB04F611FAE227D2BAEBB6148 -:10364000B7823D1B617E6E33D057A0C6BADE29CA51 -:10365000F7104F6D028B7B77A569872BE9B85D99D1 -:1036600005E9106385B8489D49DEACE7FAF49F3D53 -:1036700022CF7363F2E6CFD0E78C84BD43E97FAB02 -:103680003801E0EB2620B7DCF77413A077B74A5770 -:1036900013EDFAA816467DCAECDDDB394C55054B17 -:1036A000707FFFE34029DAB7EEC67D49F1E71E904F -:1036B000883E7D64BCFA276D437D4F0A9C1AD8155D -:1036C0008D9A53EF49220FA6703F64DD38E33C2BFF -:1036D000CBEFE9E2F830E2A14371461E4F33E28CB2 -:1036E000463FB767968E1DCD1E7753FF32628277B5 -:1036F0001D1D07F0D27EBAAE1AF12013761EF72FE9 -:10370000C53DEB719F95F9495338BE4B387EC7399B -:1037100009FA09F3216E92015EED55D5C097469CDA -:10372000E537606CD17AA12891585CCD61E82DF124 -:10373000CC4508B3E634F2C3D0E4657A8DFEDB07EE -:10374000E7C6267459CF654EECB696276FB596A797 -:10375000C4AC656A351F01BB006C348C5BECB47E75 -:10376000AF33F603AAD83932858E7C86E95FCBBDAC -:103770003884EB7F238F2DAF375E01E23577AD556F -:10378000AF66733D9F6DD39FA53E09E30915870280 -:1037900007C17E34E23E473D9A259FCC88DFD8E5BD -:1037A000B9E7ADCD847E41BF3CE262710C880F7FEA -:1037B00096C7E325B93C5E328EC74BF258BCC42194 -:1037C00069AF2C1530FFF3B81B8D97868B589C86FC -:1037D0009DE7FAA85A7E51D0D87811D378DF2C8A89 -:1037E0005ECED010CB827A46DCC4880BB87D7A25B9 -:1037F000F0EF86D06B0D07289D54FECA45A09FCBE5 -:10380000A4C3879A40BEE5C998B7ADCEBAED3B1EBA -:103810008843C2775AAECCD7C6221FFCD481F1812F -:103820004E4ED7C6394423CE92E2617691CB63D80F -:1038300047510FCFCBF780BD7BE14E2AA32DFA8EE7 -:10384000C5F38CB8DDD45EEBF75E2264A8B0EFBFA1 -:10385000242632FB4AF75698F21A2FE0EB366D69B0 -:10386000FC81A5B4BC9BC44AE1BEB9124E1FA18322 -:10387000D6F3AF638880E79FC61C9142315A7FDA46 -:10388000F3D6EFC5B6F3B117D8CFCBDAF6857C12F5 -:103890003971231D6FA3D620801CDDB894DAF2B4F1 -:1038A0005CE8E1FB4593C824A0C3CB246F280EF845 -:1038B0007D43C2FD2DD7DB93DFBC11F4FAAB2CEFB7 -:1038C000489DA06D8638B2FA7309F5949A424A4A27 -:1038D000BC897DA47F3B1322B02F62C4B59EA2EBAE -:1038E0000A7A6537F5CB0B1DE067AB58EEA57E393C -:1038F000949FA57E393CF750BF1CDEFF90FAE5503F -:10390000DE4BFD7278FE98FAE5F0FE79EA9743798E -:10391000ADB7A212E262FDB43ED08BA7648F3281B4 -:10392000C2DBA93854A00FBB1CAAA8B85D594C49EA -:10393000EA2B9D4FE3FE45E5652C4FBA72FDD3B8E7 -:103940007F618EAF99E38F89F8DA8060C4D720E475 -:10395000F93BBECF3014678BB038DBD9FBD18D7EFD -:1039600030AE39AC1F1EDFFCF0CE5F3FD14A3FAD19 -:1039700098F14097A700CE6D34F0789E9117A35927 -:10398000F2EE57EC69C6BC1867D6910658D73D656C -:103990005ECC17713A222AC85BBB3F67F871767B11 -:1039A000DA78DAF59B8FDB1546DC749383609E74BE -:1039B00054A0F604D8174DB1F2771C23C7535FF714 -:1039C000F0F34336B930743E80C77D5C60CDD27968 -:1039D0003A058E0F9EB78EA2B180C5F5CC71554FBA -:1039E000610C0FA57BBC3ADA7502B5F7D0FE532304 -:1039F0004188A375C0798024F38B7998FE6BCE72D1 -:103A0000A2BDD191C5F240AA72434168DF9A353315 -:103A1000683E1F609C5F38E89BA90C98FA5BE32B1B -:103A20001855FF49545F6BA3E86BC9C5CEEFB4EEE0 -:103A3000BF588173195DDE65FDE047770503187F88 -:103A4000EFCB9A49064CFD4BC1D9787E43F2327BCD -:103A5000580A2A680FCB30FFE2447DA3DE3D1E46A4 -:103A600027949D31BEE8F676633D971CC67B235CA8 -:103A7000015099F4A9B2FD384FA1481493BC30C647 -:103A8000FD570F93975DC51115E22C5D4159837366 -:103A9000205D5A29E2B995E3B935CFB0274268C70E -:103AA000ECE17836FA69E57180D67A27DA73E1C6F7 -:103AB00034B52A03F37577C1BE5697B745817D4962 -:103AC0006756D9A8FDFE84CBEB91FB2D1953351D0C -:103AD000FBDD03FD3A7DCB54E8D731C2B9A3C31C4B -:103AE000CE2F6AB7DAF7F128B441733E8AFDE9E3D5 -:103AF000F6A7BDDD8AE20127ACFBBAC7ACE7941D8F -:103B0000849DDB5AB97735F2F926B91FEDA84DA788 -:103B100085A4E7BF325204CE6F43FEBDC50ECAE195 -:103B2000FC94C3BF03A981BE28895BED96E987ACED -:103B3000E519FDD6F2ACA3763B487F03ECA0C55C4B -:103B4000EEF55379CF92610665C047381AAB00B8DD -:103B5000EB486F33E44938789C7C31D77F0BB97ED2 -:103B600074A7B0786F4EBDC7E27F127ECF5F2EEF95 -:103B70003FAFEAE0EA3610B261C3AED2D06FCDBB40 -:103B8000E2D90A149736FBAA4EB79EE35F68B39F4B -:103B9000EC765685DC83F9B8D9B6B886B19F0BF3BD -:103BA00084FB0CECE39FEFB8467F908705F2CDB81D -:103BB000E705EF15A6EDF3E4B810A278CA6E60E74A -:103BC0007072D612BD27091DCF49617C310C6FD1AF -:103BD0007988B7F9FC5DB697DDCF955D25C5343A98 -:103BE0007E767D2FDA038B6EA3F3413BFC0CE6C19E -:103BF00018F5D3D37AF13CD2B61A81E7E712B46B49 -:103C00008C75DEE665E707EB2E156222B46F28C0DF -:103C1000F111AE82C4FA523C1D637862F986D75422 -:103C20005BCF39D6D9EC17831E16DADEFFD6C3F682 -:103C3000C50D3EF8F0E2A393C651385608DDD529EC -:103C400013CE5D5F9AF8C37106F8107E1FC3525FF2 -:103C5000308F57F9818AE73DD206B6134A92B529CB -:103C6000245A3517E4CFE085022D5F9BF2BDF6AEF6 -:103C70004BE1F8F6E0D360E4B95C3FB8AC3A2F51C1 -:103C8000F6787E82E5001F07B616D97A9BEE7DA1F5 -:103C9000A8DBCEF3E337E864B304B9B5A2BA39942C -:103CA0009F68970EED8451DA85C96639493BAFD1DB -:103CB0008EA2AB03EE75E2F3F2F0EF2287C73CBEB3 -:103CC0000C7853352F9E635C20AB9097F165E1181B -:103CD00073B67947C866C784E1ED28D8CD06FC6283 -:103CE00072F863F0DD3CBE6314F8FFD6F8385B7FF2 -:103CF0004EFEFDBCE1A3D55BC68C3C5F80CB81F75B -:103D00000D695ED1D4CFFD7D7FC2B8B87C3D09413D -:103D1000C84B76E82AECE715AB0FA27F2FA755A971 -:103D20006007ACA365B003D6F57663FCBBB8F08141 -:103D30002E20FAE2B887803C984AD4B4DDB4DFA9DB -:103D4000AA0C27AB887CE94111E2E9E46A82792375 -:103D5000A97D1E763F50FE9C47C1DF4A4B53703F02 -:103D600023256DE6A3CCE865716603FE948A23954E -:103D7000107F97EB484800B88418A900269B427032 -:103D80007FC3A3EFF9269C032032D34F78470EE878 -:103D9000551E6F1FCB48867439D53ACC5FF9998C84 -:103DA00071ACB170051825CAE2E2F4CD004F718400 -:103DB000762000FC2C5E36352286E2B4FFD213ACAE -:103DC0001DF9053B3F427D9325CF79137835E4CA31 -:103DD000581E870F2EB5C6A9C9209D336D5FFA8B7B -:103DE000458F439C62CC30F9CDFC760F8733F504C8 -:103DF0000943FF811AABDEF0F0FC6D8FEDFE988B6E -:103E00007C0EEBBDCF76FFE1DE30EA011709294ECB -:103E1000B42F96A2DD60F825DBA022D8E37984DDFB -:103E2000B76B6F3F93B52741E6A7B83C44514AE9C9 -:103E3000F7E51E1DF30D5DB44CF12838899245DF7E -:103E4000678B2CDED22C1019CA89F1E29867E052F8 -:103E5000AE6A03FB65BF321DEF4533FCEA5635847D -:103E60007910A4A8D262371BF95E6B4A0AC6C2F762 -:103E7000D43143712715E8724D6621DAD1FE8C8169 -:103E80007F0639FB598A6F81027215F230E6C0B5A0 -:103E9000B4AE8E2895BBAE53394433D9672EB901E1 -:103EA000E36CAE53E32CEFE34DD673D4BA57AC8238 -:103EB00071B2BD1A3BBF43D436685741ACE7A55D2C -:103EC000A7B22CF67AA2FF5CCBFB38B56BCCF7FB24 -:103ED0008CDC7F0AD18ACCFD4F18A1FF49B6FED5F4 -:103EE000A4FD27FACDB0F4DB2EB3F86B34E0497AA9 -:103EF000DF64A9B772BC77C6C8FB03255E16D7EC92 -:103F00000C36E0FE4025A18C4FE965DEE963123BEB -:103F1000C74BD07E23B9D6FD814A4EC722A50C3CA3 -:103F200017205BEF2D2E27F67B8CAD76D111086E16 -:103F3000517A177D65FDB84FF0272F9EF31BC96E90 -:103F4000EE6F22189F2E4F19B81DF6C1AFF48E7375 -:103F5000B607319F19FDF925DEE90BF8BD9F2CAF9F -:103F60003920225EC29563F19C96D14FD8492682B2 -:103F70005C0C8B2C0F027FE8F8FD99D98FAC4F8237 -:103F80003FFB39F73A5D282F34CDAB1FF20ACDE362 -:103F9000CDCFE9914CF308BBC80C1C8FDBBB43E3CE -:103FA0008DF962E3BDCAE359C678750BACF3AB7308 -:103FB000AA38BF3ACEC7C678AFC2FC92E0F7ACE3EE -:103FC000F1BCC9A1F12EB7CEAFCEA5E2FCEAF83D17 -:103FD000BB43E38DF962E319719D4E674303D0E162 -:103FE00048F11D23AE734DE72E4B5C874477CDAF70 -:103FF000282464B3C0E4C7F68DF33AC0FFFBB8666B -:104000004D11EA156E5FE37DAA541F2F9419BCB5BC -:10401000B9DE58B3098FDBA81CD127C3390985C085 -:1040200081323837A1E3398A203E1FA1F6BA8EF9D2 -:104030002545F8FD89A610967736CDC6A7D14FD174 -:104040006C76EFD794B94252BBFD752FB3DB37675F -:10405000A9D77F1DF45B8587E5FBCEBE84E8263BB0 -:104060009A1AD6FBDDB03F741D29011D39692B83D7 -:104070003B50352606EBEF2939D8DF047150D9A122 -:1040800061BEAB96FCEF18BCEC65FEBCCBC5DA9309 -:104090004BD8FDA7B55C3F11A906F38F6A17A6613F -:1040A0003EC2A2C5BA4FA5785B2C086F14727D077B -:1040B000E79EAEE54B6DF71702A079E87A05742903 -:1040C00006F7C35D9B7B788940FB0DFBAE413F2328 -:1040D0004C1BA6D37EAEE5FAB6E26D17817804B923 -:1040E000CC89F26BF162AB5FB0D91D57C1CED95C00 -:1040F0001220CDB4DDA21AEB77978BF155D876FF5D -:104100004BED59EE8331F26DEDF8B1C74D0F79F9F2 -:1041100079251E1F3D498AEFC7335F3C2FD7DEDE6E -:1041200088833679997CEB7432F9309C0F183CEF18 -:104130007139B8ADE928C6D10CF8B2E59800F23E65 -:10414000A7FEA825EF9D22168D6A639F8048BB4B72 -:10415000500FDBE6B34DD89D35DA7D50D9447E77DC -:10416000A088FFDD0261F8BCFFE0B5C6854F92B9BB -:10417000AF149264FCC3E2C1B587A450B396C08B60 -:104180008187FF6B3EDA0278A7CF57E67F52C6FCE5 -:10419000C05CCBDF0730CE6F5D335496896CA2E7ED -:1041A00085CB9D3AF357078B812E8F5C9A12627FE5 -:1041B000E782DB41F15F8960077DF9FEF53C4B5EEC -:1041C00033EF77A4F5B2E7539ACE1B27EE3F80FC7E -:1041D00097E65010ED814C91003F65433E9E9F7DD8 -:1041E0003F66B55B2DF978AD7DBB04881B6E87FCFF -:1041F00044D339BB9CFA5EA11DECBBE6188B43C4CB -:10420000693D0A776E7D5C682B4EE47DD9E57AEED8 -:104210006DD67CC1F6B98BD5DD1AE4D55476C3C50D -:104220005FEBB6B23897517F28DEC5CF9F3A48037F -:1042300081F3179297C59B83FC5E8EB3E5EF7E26D4 -:1042400046D5FC7CC8DB8D291574FE0F65442A7C9D -:10425000B4DFAE4069430FD0A71CC23CEFA58D77F9 -:1042600087214EA866248F832FE5F6418D8FC5D315 -:10427000DE72C4F3206EFE8B8CCA1ADF8C24F51B11 -:10428000EFC5FECA47B86FFE261FA3CFED62727955 -:1042900070031FE72B2B44BC47C84D7C783ED55D8F -:1042A000D83D1BF0B17DE5B650B27396D3D5C85753 -:1042B0007DA638ABBB90DD034048EFC530CF757F9E -:1042C0007EB8F7193AEFF43F7B51CEA64BAC5F5363 -:1042D000FB9BCCF331DAEFFBD32FF1FCFC3E7EAF3E -:1042E0003A89165C0E71F64D4619B600A09C3654FC -:1042F000BE1CFCCA44F9C70BE0EF266D021AA5C428 -:10430000F7DEA6C3A887370984EBE95F2CC0FEF867 -:104310003DEE2FF2EFE5577EF0E8FDA00F663AD1B3 -:10432000DFDCC4ED1D03BEF77DEC9CC2FB1C5F23EC -:10433000E1B393E3DB0BF80C9C173E3B93E1634145 -:1043400040EF023CBB21138482E0FEB3B216F2AD13 -:104350001F6A22E1AFD3396C0FEDD905678A68FB7C -:10436000FB93ADC70F33F46E1FC2730CE7E72BF45A -:10437000860015EB6611EC27091C5B475BD7A96922 -:104380004CCEC11D63F04CE7F6A5E4EA0F42FE8275 -:104390005AF66FB7AB54CE74E4F72F4916277EC296 -:1043A000CFECFEB411E2E22F70FC55A5877702DC5A -:1043B0006DEA03E8EF39051286FAEB660F10C1D4F7 -:1043C000EE2D3F5B0F0A772FC0EDBC98DD4FEDA3BC -:1043D000788704395F19837F9D768440FEBB2F78F0 -:1043E00004F35A7D6503C8EF280AB3195D813FA81D -:1043F00070FBED854D6F2F00BA48970C3ABCBD138A -:10440000E84C4A9491EE7AD259FB63F7DDDE09FE5F -:10441000E20E276D037230DB89F68D7D7E8738BC16 -:1044200082AA1F80F90DC3A76BE051B86F60D34417 -:10443000764F4BB9D8BFE46B4097577AD13EA3EF84 -:104440009798CFDB9FE4F83AE963F6D5A63F29F8C1 -:10445000DDBE1E23D1EB6FBF38BDFE76047AFD9D15 -:104460008D5E3F21C9E9F57F46A0D777E1BD1D2FBD -:10447000F6B244F4ADB0AF2C7FBE6027F4275F35B1 -:1044800077EB33F4297DBE318AAB19122CE79913EF -:10449000F23EF209F46FDC2B60FC7DA2BB7C23F4BE -:1044A0003B6BE6569063E7D0EF19C087BDDF5FF046 -:1044B0007ECBAFF44692DD93B0CBCFF2E37FE067E3 -:1044C000F546E29B5FF9597ECA487C13F70FF14D20 -:1044D000AA3FF3EC7C33C8EBD37518EB9F712E7CAD -:1044E000F3203EDD858C6F70FE7386F30D2111E4A1 -:1044F000938E7CC61745FE159DD15C131F917BAD35 -:104500007C44EEB5F0D1A7FE7B918FECEDFD23DC72 -:104510000778D110FF87A7C13CF40BD536763E69EA -:1045200000CFE1F690C13E17E609B3BC5C4F34AA58 -:1045300033F3A09FC0BDB3B378FB1DE0A3811F344C -:1045400093C7B3E47EB2C8379C9F7D65F132F3FD1B -:104550002E2FF3F6AED47039E0BD870C4C01FB6C06 -:10456000A4759ACFEB9F4ED7E7FB93D0F9D9F450BF -:10457000BD9FE9A17ADE4FFA9F9506B04FEDFC5E34 -:10458000BEF2C77F7C62947E6EE2EBFF55DECF17F2 -:10459000E0FFAFFA93F02FE5FF1B601D4CFC5F2698 -:1045A0001424E5FF9BFC49E407E5FF9BFD7F5B7E50 -:1045B0005FE34FC2975701BF659E1DDFCF717C3F00 -:1045C000F725F1BD85E37B83FF0BCBDB0DC9F04500 -:1045D000F1BDF11CF1BD65047C3FE8C7F57F16E134 -:1045E000F7695E8C9777CD227BA09F24703C6CEEA0 -:1045F00047D1583F94A73E1128DD977FDE154A76B4 -:10460000FF116DF768B276F3FDAA917CBE1AFC87A4 -:10461000ED5779715F81EAC72793F1C797A0831F90 -:10462000F893C8FD7291C921C77D1777421CEF4BE3 -:10463000F4FF9364FDDFC9E5FAD9EC82D7385DD089 -:1046400079FF977FC670F9D7C3CF270B6AE4177E2F -:104650008CDB0F5C01F26AC75DE902C4BB72F5B87E -:10466000007E025EEA43E1980B97F8CC48B4DB2168 -:10467000C705B83F6747832AC07929537F6FFA334C -:1046800047EECF0E0785EFD77E9477FA6FE0399F1C -:10469000CFEF7CEDA47DE9FAEFFD4C6EFF0F3CF50A -:1046A000C956B96DCC430C77B33CDBD9C9FF7EE565 -:1046B000019FCCF558F8B859FEBF3B4457ACBFF347 -:1046C000D53F14BECF387C7FC27E6DF0D9F17236F3 -:1046D0003827819E67FD49A999C3F594BD3FC3CF93 -:1046E00036D609AEC530C77DD4D421FD9D0AFD79EB -:1046F000DB453C4755CBE549EDEC346EB7AB1EE8E6 -:104700007F3B8FC36FBFED810AD857EFB9472D01AB -:104710001464D733BDA7DD360EE3ABD9BC5F3BFCD9 -:1047200043ED9DBD53E0EF42D071C7C1B8F3E692AF -:1047300038F88DA9603760BC42C5BF5F9CEEEA0EB9 -:10474000427C769DD0BD6419E8D52BBCEC5C4C70E6 -:10475000F159EEC56CB1D02D09969DA57E33D65783 -:1047600053BAF1FE9473AEEFEA4E6A67CD4B150D66 -:104770007F62CEA8780D0630EE65E077F8386CFDE4 -:104780002AC20D02E0DB5726A8907AE7A37402F64E -:104790009258D88F79535797317A21D42F19FDFE2B -:1047A000950E03AEABFF167019F5461E8FD7B39D5D -:1047B000B718FA3B635E26C7B0222D7F742823E921 -:1047C000BE82F1EC6C5275B80AF92355C37B193BD4 -:1047D00087F2BE43C145BEBF7FBDC4BC626CDFC9AA -:1047E000567FE8FE91A082F61FFEFD0E131D75A4F4 -:1047F00032BF554A0BDF9D8AF23784F73FD2F2B7BA -:10480000B0ACD0B20FCB4DB03E441D2A37E3F720F9 -:10481000AB4F54F59CF04EDB75613B79A89FF5D802 -:10482000AF7768DC8D580E0C95EFC3FAB9ACFEB9C2 -:104830008E33ECFE957E09E7FF89ACA7C2BEE97511 -:104840008D5FC3F8D2F58DB7E0B3AB49AD80389D2D -:10485000710FC975D77F4D057FFAFA9BB6E0BEBED2 -:10486000D1FF42F03B80FF35B91AEC2567BE187EB8 -:10487000CC9BE0BF041C6D58AE95D97DFE0B679FA5 -:10488000D8D4668ADF29F077D121BF4633DD834152 -:1048900012F2F04941DF9D7A1EF43C7C9E841CA4F8 -:1048A000F4FB89B73016457AAE5493F18D31DF9120 -:1048B000FA37E63B92BC31F066BC5F57C8FF8EAE5C -:1048C0002D7EE99E5885F93F0B050EA78FDF0BC99A -:1048D000EBD5D2719E2D46BAD0806E6BB97F67D76B -:1048E0000FC6B84F0A91D7013F1027BEA774387E74 -:1048F000CF156F46FF63235102F772798A09EE8B59 -:10490000057CC6BE3A936B0F7A8D7214934BC285A9 -:10491000DD28E7DC9A21F7989E54537A75B184FA22 -:1049200041A97FBD3C3805F2402341F8133EB4FC59 -:1049300012DCCF9C2EB132217F7DE920DA3FEA05DF -:104940007093A3227FFED2A13CC28E2E62DCE6F3DE -:1049500097209ED733542671385FD0E3192AEB4A4B -:1049600090960B86CA5128EFE076DFE9D4CF5F6AD4 -:10497000437D16FE0CF8C790AB155CAEFEADE4E9C6 -:10498000FF02CED174B20080000000001F8B08002F -:1049900000000000000BE57D0B7854D5B5F03E73A8 -:1049A000E695642699BC27BC721240A23C9C040286 -:1049B00041B14E78355E790CF51524C824E1119E7D -:1049C00001A432ADB60C24202868AC2FEA833B2822 -:1049D000F66AAFF682C55BFE16F907410B2D62AC95 -:1049E000A8F840C3A3151F2511B44CAD2D77ADB564 -:1049F000F7CE9C733203C1B6FFDFFFFBC3D72EF7A0 -:104A000039FBECC75A6BAFB5F65A6BEF612CCC583B -:104A10002E639BB566CFE8618C85BD565F7F8DB1F7 -:104A2000750CFE0A183B877F5733D6D76367AC9C5B -:104A3000B1473283291EA83FE98E0EAB13EA398BAA -:104A400072DC41176385DE2FC295F07DE128C63404 -:104A5000FCB65F166323A15DEF32C59E037010F3B1 -:104A6000288CDEADF240FD1C3763AD009935C2D80D -:104A700020C61E70C9328C0760A024C2DAE079AA71 -:104A8000C6DF5BB00CCF55075BBC15CA6925CC1FD0 -:104A900081B2C7C1660400F6F258681E033DAA80C1 -:104AA0000A8D37C3DBCC34A8EFACB2F82300331047 -:104AB000BAE2F362AC99EA0DF4580932818FF13908 -:104AC000C1011E286F66AC6A2B8E8B450325308F83 -:104AD000D44B73B2EE825265897519832EFF7D0522 -:104AE0000BCCB43136D413B0637D57694E6A701065 -:104AF00095875079B525CC002F95CC1D518AE27849 -:104B00008191A706DCF171C4C7C3FB7F6B453030D0 -:104B1000D6D6F5BD84374E5503FA79485889788042 -:104B20007E4F55FFFE219CCE4267879D15033DFBBE -:104B3000DD17602ACE47A3F7CEED53A23DE1FDA2DB -:104B40001D4B188E77555AFA28A4A3B9DFB7BE7E3D -:104B5000D81380F7297F7604B626E86F0EE219C6CF -:104B60007B6845357D07CD6BD63CC666E0548A1917 -:104B700011B4CD899029E71C34BD43FDE0FD2D8C97 -:104B800033C3F581DA890CF05A57AD32B508BFEB63 -:104B9000ACCFCE41F996B6DA096C081442B613F8D8 -:104BA000DC09FFCE41BB419639DE038F6BC3FC3974 -:104BB000D587FFCD62BEF1B9F05DFD5AD3F3F7AFF3 -:104BC000F998A5E37BEB89B69278FB3755D706C6F3 -:104BD0008A7A67E8FF23849FEB35E647BA5DEF4B9F -:104BE0008B84618A3704A606C696C4DB7BFBAFEADA -:104BF0000CC48B191FDB05DF1D5A11088CEDDF1566 -:104C00001F7501C5EED12E8C97EEE2A1D65A3A3E21 -:104C100057EB8A07F3FC01631B10CFB300CF771566 -:104C200025C707D4237ABC3D15EAC154C6AB136C23 -:104C300016C043FD14853914C26F3AEB8BF5FC1393 -:104C4000C6E9C66BC6A3195FF52F325F14DAAD7FD4 -:104C5000D0ED030E67BF93F88902D286833CE155FD -:104C6000F5F33C86E3F7C03F9CE7772A4A5FCE81A5 -:104C700071049B151FE3F33DA69F5F1D0B64441554 -:104C80009AF7B124743FA69FA7797CE6F1A7A0B05C -:104C900002F9177ABFE89EBDBA7ACC1A1D1418CC57 -:104CA000D8331E77CE1FD2A03C84F9CEC1BAFA9277 -:104CB0008DCA188AEFFBE5D0FA36F3C5D915DA3D6F -:104CC0007B6DFA75CEF96C46684A67BFD8BEC28262 -:104CD0009D650FE0393055DD7003FCF75BFBB25783 -:104CE000E3B3A55E553B918DF882F912BDFC8C496A -:104CF000FE6208C3BB55C0DF14E6D45CD0CED5201D -:104D0000A4CEC15C26F95334976E1EA75B942A94F7 -:104D1000A340BC8CEB07C7E76B1EF752AF9DFA03AD -:104D20007EFC42CF8F66BCBC55DD3703E5C88138B9 -:104D30005E865C0C5E46E3620639E2C9665105E8B0 -:104D4000DCA138234FC0986A42B707C60E45BCB0F5 -:104D5000B01D44E7514F11D593F3B631F9B798A17F -:104D60003CADB1B320CEEB7D1BABDEE64218ED5D72 -:104D7000A6935B27B22B8FA25C96E59AD00FA97DF4 -:104D80006044E243C9CFB7385D5195F3E1679D7C3C -:104D900043F2ACC6F387814427760EE6A9662CD091 -:104DA00070DE6A5AFA1096C1D85AAC02F354330333 -:104DB0007F443DA9A6F58920FFA54E7D722DA7E36E -:104DC000FD5537EAE89832EBE7616A5CCB32E03FA9 -:104DD0004DD0AF52D02FA5C469A61FC3751A2E613E -:104DE00091A7148102289FEEE78FE0BA4DA63724E1 -:104DF0003D534AAC5FB5E9F99AB5103F4A3AB2BDA6 -:104E0000C33A70BD06BD567617BD2F21FC043D1276 -:104E10003F1D36D4273342B6D3FA76820533232B8F -:104E2000F1BB750E1F3EABB36879580FF0E4413DFE -:104E3000CE4A7C3E5C3F2C0CDF497E42BCA231A1B5 -:104E40006BBF0DE6505086ED81F4C4EFD6EAFA2927 -:104E5000EEDA6FE7BA32B76BFA4E55C17E203BC22D -:104E6000E7F3E9E4779F4C6E3F9CF60EDB6A294E30 -:104E70008EBF3A67B6DF9A1D2F1F2B70564712E878 -:104E800001D99ED4E7596AD06BC1B9B127F7ED1D9E -:104E9000857AD87319483276F7EAC7F7EDEBCD90EB -:104EA0004518EB81D51FDFE77791DDC1CBC898307E -:104EB000FECDA99D65BFD30BE5E2CE7218CB9BA0BA -:104EC0003B7605C8EBFB1EDFD70CDF9F3DE220FDE4 -:104ED00075BA2A35828B273B34861D87715BC1CC1E -:104EE000C90056031046E80CF5A4F92856C01CE08A -:104EF0003B5BF32988EFC9991AF183556351370C4D -:104F00002EDBEA53105F3FB2B30621372E9DA2B3CA -:104F10005F266772BB43F6E370B2704A59BC5DC648 -:104F20007C2B518F582730D22BB0CEC96E93EB5BC0 -:104F3000B6332D93EBCFCEF579E1F53C2D33C17A25 -:104F40003E6059FCE10FD09EFD8DCA9E82A94CF7B0 -:104F50007E8F9EDF18AA2738353497E0AC4C6EBFA1 -:104F6000FC9E056765026CAD7E63FA72E0DFC6EDFC -:104F70000E1FAAE585B77D7C4FB9867802BAE37724 -:104F8000B3EA1F2C87F7F6FE16B267D7F666D5C8C8 -:104F90004FF6950AD947EB347BD576800F6454DE03 -:104FA0008FEDC9713D903196CAAC4AB3209F2F75E1 -:104FB000723E3F7BE44E6F1DDA952E17AD17FBCA8C -:104FC000A27B2D5066FB61DC0CE507233B4375702B -:104FD000B83A93DBA9AB05BE7F20F8CC1943227306 -:104FE000BE5E0CFD3BAD618676B63366A5E7760501 -:104FF000C697804F657BCE182CD2A1D89FF97B3BFA -:105000003DC779E1F76A3633D83DF7E0F7B908E5EF -:1050100038D2F838B2CDEDA4F3E762FD99C771D26A -:1050200033E647889F0732FCF767921DDE664379B7 -:105030007E8BEB37879521DD91C76D0ACAE3495F07 -:105040002BD142C05F4AA51A5955847ACD337118C5 -:10505000F001ABB4F9109FADFD72DCC5BAFE9F1232 -:10506000F47FDDEA71E33803E3C0AE26FE66B9D70C -:10507000633BE3EA8773F90706974ECFBEAE6D59DF -:105080005B8CF2376CA3FDD20C673882E3D3D96D09 -:10509000CA392E9735EBF0B8FD3763ACEA4F49EFCC -:1050A0006ADFC136642FD97F529687A10CDF7D203D -:1050B0008A1F8E3D73034EA38D79ECC57A7B1077E2 -:1050C0004BC3D1BEE17F334246BBCF6C17D655945C -:1050D000BE026400BC44AA86219F5D6A213EEBAEFD -:1050E000BDCCD87D9CCEE39A3CB8AF7A04E504EE03 -:1050F00007C71E1F4B72034C2B6C77F258D51385D4 -:10510000DAEB4316E687811FF4AB1105E676B0A40F -:105110006DFFD588B70A9B467AAB846DB82E07DF42 -:105120000FF5209E03C20E81FA5CBF799D91FEF0BF -:10513000ACD57FDC55AFE3BB8315C72FC5FD0AC8CF -:10514000BD8644FCC4D84AE2EBBDDF4FA5763E7C69 -:1051500040893860FCE3D4AF5F1D81F6EC0F6C3EF4 -:105160008746D3B2205D27F898D8B8FA5DE3747605 -:10517000C07116184E7665E9914A07DAAFAB155A39 -:10518000A712FF3342467B33B818EC32ADAB7D0A31 -:105190008DD9919FBB6B9F9AEDABB399C2AE2A6339 -:1051A000657ABB2A999E92769595F9FF467287B5E6 -:1051B0005951EF4E820789E4C04D195CEE8E533F82 -:1051C00023FA9CAE5035C4D7C1D0272EDC8F1FFCEC -:1051D0005AE5FB607FAEC18ECBC9E27E814D763051 -:1051E000C8E0BB4D3D9C9195D0D4EEEF5F96DF4675 -:1051F000F4D11E1E8574FC8D8DE470B2F1BA432A81 -:10520000EB078C3931A41094F42B0CA530AB4E3F36 -:1052100014B2C4E3EF9FC5C79F7B07B368D06F6626 -:1052200098F913ED8F653DD8178FB732AA1FCD843B -:10523000F12DEA6721FE94FBE3145BD8DF13E66FE0 -:10524000DBB9248CFBE442181F8E4383F1A1BE2CF2 -:105250000AA551B938944DB06F289360BF504F7A6A -:10526000DF3FD497E025A1227A3E203490CA25A1C1 -:10527000A1042F0D9512BC2C7425C181A037B1DE7D -:10528000A05025C1C1A16BE9F990D075042F0F4D35 -:1052900021E80B4DA3F7A5A17A8265A15A7A3E3485 -:1052A000349FCAC342B752B93CB484E0F0D0ED0495 -:1052B00047849A0856845652BD91A1BBA97C45E803 -:1052C0007E825786EE23382AF428BD97764BAA585B -:1052D0008F776B333DE8EF000ED7908F93ADBB997E -:1052E000595C2F1DC8F44FC82A8FD7B35B408FBBC2 -:1052F000BAD60B6671BD9189744DD0DE3441AF537F -:10530000BE630F0D6071BAADF39EDF9FC14A12EF0D -:1053100037E2F281CFEFDA2C2EBF36595BFD2AF24D -:10532000EF62E60BC3A389C35E5750BE6CD6AC5583 -:1053300089ECBB07B26CF4DD2399C1F95900D38A1B -:105340004EEC45793239EC797534F2CBA09CDF8C88 -:1053500086F60A9B2DB4DDD7986737FAD7B4B18C9F -:10536000E4A2F42B815D67D0A7EB055E18DBBAAF32 -:1053700098D653BF32AE7FDAAEC1F565FF7E31ED10 -:10538000DF37D9A38A15ED9BA5A0C374F6FFA63518 -:10539000753FC1F7F1F6EC34CEC2B5EC2534B18BD4 -:1053A0005AB4D12900FB6EF4BF94029FF48F0447D6 -:1053B000A74279C0D3E197105EBA35323A0DE0C00A -:1053C0001DD19750DC0C8EB68D7641F9F27D6C0FB5 -:1053D0002EFFD2566D8C1BCA430FFBF7001BB0F299 -:1053E000B6E098740DC713694A87F16CFA000C3D5A -:1053F00028577CD6A2C276284E7FB0E3D07E937425 -:10540000710F6B1D9B0DFFD96B99A754C5EFAD6D47 -:10541000299983BAD26733CE1BE7097AE4299857D2 -:105420002F7F54F1E8F864479622E9F018F29BF4D4 -:105430004B6E6ECE22BFE4E6544F2576D9318E797D -:105440009ED0908FAD8427FBEA62F2C749BE03FC71 -:105450001AECD9F582EF3675DABB89F1BB43C8BFC8 -:105460007F15FC7E5BF07332FC3A9157465E781DE7 -:10547000EF17EB12D6F1CBC8DFC9EA9D12F837E37C -:1054800079B385ED035D05FD029FF275C5D08FF6FA -:10549000B1E0EF0BE1F5F8BF18DF462F8057A6E526 -:1054A000909C047EBD14FD63C9E48D5DEC67CCEF78 -:1054B000635DE51CF7DB7A40CEF54D2EE7F666F12D -:1054C000E749E597903376937FC796CDFB1BEA09B2 -:1054D000A8D989FCD4DE1C839F7A82EAA94479C3C7 -:1054E0000630B2A3D30645C2B84F290C6B652A56C5 -:1054F00043A18C78EC5142FE8722B033AC407F68E8 -:105500002A8AD0A9792C75E87F97EBCD53EBD5AFDC -:1055100037A9EFE3EB51F245D6E6BBB85F529B02E9 -:10552000F6CB5831EE783BDC0FB2E67B3D36DFA59B -:1055300093839BBD5E2ACBFAC9F8B72E5BF06FF35D -:105540002AC2A7735462BBE15BD9AAE0DB0E3FF22B -:1055500079F85BCC83F64C66F331924F99209F1417 -:10556000924FBCFF5EA1D49F84A17C55769EF00330 -:1055700078526F74FFDFE3E72CB4A9703D8DF2EC35 -:1055800056314E037A48C3753A0AC63E0CF1652778 -:10559000BA6B8CD3511BC52268F702DEA2B86F0F1D -:1055A0005BDCE467B2DB5BFCB89E993D93E63FD4DD -:1055B000139C907D9E75E149D34A91A8D3EFFFD902 -:1055C000352EE0BF35459E542CDF0CE5F515D06F28 -:1055D000561B13E575AE91DFDCEF313DFBB9FDCD18 -:1055E000D0DFAE2CFF341C0FF0F57484FE011E2BAF -:1055F000F9ABBDDDB307E4FA8CAF274FA95C4FB51B -:1056000083481ECEC176657BC9EC9BA26C2EE74217 -:105610000226B36F24DF5FB47D23C63B3BFBFCEB6C -:10562000FFAD7DF76FDCC274FEC61E0FB55A35F4B0 -:1056300067703F8DC5D94AEDB985BFD18FFE46E071 -:1056400003673F5EC6BF44FEE2E4788CD078A49F37 -:1056500051FA13D3055F31AB12413D9E5EE1B1D6E5 -:10566000517B6DEC3BD0DE83024F725DA3DC7A7E12 -:1056700010CAA52C2BEED7D19FE4CE8AB78FE58C2C -:10568000B2B87C62621F77AB1873CB2A5F06BA9CF4 -:10569000C307B91FA5E5877C5D4EECC522AB504E14 -:1056A000F899E681FA294CFEF90DFEE4095F29CC50 -:1056B0000FE33FF0954A50E9C7A26ED8EF4DF429A9 -:1056C00051DC07DA2DCE08EAD2CA1E4E86F14D7B98 -:1056D000BA2582F111FB3185E6692F4B8BA0F01BB7 -:1056E000DBA32203E398670EEC710513D0FFA660DD -:1056F000ADC1FF65C66367BDE92F7B108F8F5E204C -:105700004EBB37BB334EBB0BF974D2CC8E66BB1687 -:105710008FD3CAF8638177FBBA4A54590BB87DDA44 -:10572000834556EAED2A5D1C741FB6F3683C0EDA19 -:105730007A893E0EDAD86327DABB3FEE8C83067F88 -:1057400085FAC49FBDB514F9F751DFF667EE457CC5 -:105750003A44BC62E81197867EFAF23DB9389F5709 -:105760004DE39750FAF1CCFBE0C3D9C6F8C219DF7C -:10577000751951E2ADEC84EB5BFA17E57E18FD87F5 -:105780009E84EBD0886FD97F8DC2F7B5CCA670F917 -:1057900027F428C8974F480E4418E94DBF437902B3 -:1057A000F5CD19DF501FC53D93C81B391EC063FFDF -:1057B00044F15FE82F619CD59AC3F5588D8DFB4D60 -:1057C0009525E58B715C356E97E2D0F9FB3B84BE85 -:1057D00033C785D48CAFCB83C2EF9D68FEE6F84E0D -:1057E00087D017882FBD9FFC42F83A6C6BA1F8E177 -:1057F000E1592A5B09ED9C098EC86709BE97F05DE7 -:10580000E49BFE0073787F9DF44C122F3ABCA2817A -:10581000E2CCE6785AE7FBDA946AD4DFD588475DB4 -:10582000BFE5395CCF4F129039829A07DEDBEB1E61 -:10583000F4308C7FF5FFA23CEC46BF58C70B18BF75 -:10584000603F7093BFA2BAF6CBF2958375F8AC6057 -:105850003C3EBBE7C71E0D9E57F76FCE0DBB92E3D4 -:105860007112B60578BA1B1F8C247F8C2F87FB37EB -:10587000BBE58F6183785C88ED49A1F869CA9BAA72 -:105880000FED06EC97EB01EE4F5E26E226E6385E62 -:1058900075689141BEA4C51416D1C52FD2AC5BC9A1 -:1058A0003F9B16B3D273F37ACBCA81F53630BEDE96 -:1058B00024FE93D153E2DFFC7CB0C0FBE1DAB91ADD -:1058C000FA0DEDA989EDE066514F96CDF908C9E2D0 -:1058D000EEB5627D9C098ECC477F55B53DDCBF3B64 -:1058E000EB5CE2E742790E37E7F0FD907BEA1B22A2 -:1058F0008EA736636B52AFA659CF1F8FF59BE2B1CF -:1059000069C3BAC4F3FE29F1D81F9AE8D7DD78EC51 -:1059100078B11E2F94877293DD68F748789DA0E3D5 -:1059200099600A0B837CBCB552A53814F007E9C70F -:10593000C30F2A646F466B1DA497EB6B53C83F5B84 -:105940005FAAD2FBFA0D2AE9CF28C88705201F5E7F -:105950001572C2EC9FAD648A217E3E69588AA13CD3 -:1059600075D6FDAFAE40FF72854DC3FE0E6ADCDF1B -:105970001CF6AB64BF421BBE28FAA71FB8CA87FA41 -:105980004CF2C341BF4AEB2D7C48F561B7ADC21F55 -:105990007D706D6904F35498128FD36B7DB1FD7ADD -:1059A0008A03BFE3DD4871CE94BF3E1C08D0FE31B0 -:1059B000A89592DEE4F1D314B14EC7F4A8B811F55E -:1059C000F887EB6D0CFD461FDE7186D673DB8AC54A -:1059D000941721FDCBD23F6CF6339BFDCB5DFCCA07 -:1059E000267F72B27C86977212C7EBA5BC4AC61F8F -:1059F00020B6F67F133926E5C7BB629E637A6CDC5E -:105A0000B012F0903653253C48BE7CE7EB3B1F4775 -:105A1000399C02FCB18A213EFFE365DC87B0B94ABC -:105A2000423F72AA94EB983F5112A7CBD4E0DCCE50 -:105A3000322EFF690D4B0C791F66BD925CAE9D5FE7 -:105A40006EADCFE1FE0AB3DE31AF877FB4DEA9AE23 -:105A50007DB004BFAFAE9D1541B8AE87B301E5AFD1 -:105A6000593E98F5C47526391BD70F2A8B0CD58F54 -:105A70005BA37A713D61A7F7675378BE43C8C9E15C -:105A8000F2D4F427109E4DE1F90E61340AD14EFD97 -:105A9000202DD244FBF2C523904F42CCD716C679B5 -:105AA0007A53C98FD0D28BD753AF49E576F9DE4A06 -:105AB0009AAF2A0DF3E64A5A374D622E3FCE0EF6C4 -:105AC000C885F134F92D29185F18E3B6EE47D74B96 -:105AD000CB680B73B038BEE27921CCA3C0F7F44E8B -:105AE000C1FD67A9D3DE97ECD4E25CE4CB1FC2FE14 -:105AF00010F8FEC00175FB6698EA01DFD08C447691 -:105B0000BA84E638F291EFBEDD07D7EDEF59703079 -:105B1000B6D75A5DBF01E3C38D3B548A2F4DBFED0D -:105B20009D4BC8EE36C529D5746709FA539A94542B -:105B30001FCA1389C7DD6E3BC999A62369B49F6844 -:105B40003AAA88B29BE4A1C4FB5EA857300C7395B7 -:105B5000DC243725FE615E57217E241D2A59F4C0BE -:105B6000A8A2BF6B5E55E79F572F0FC90FE43335CF -:105B70003E0FD56DA5F9B5B3541F8E2F24FC43EC11 -:105B8000FD34DAFF493A370A7E94745E24E8DCBEBD -:105B9000F3CB7BAE84FA2DFE2C8A3AA8BD19E1A185 -:105BA000FD7D37F189C4839C37F0C574FDBCF7ECEB -:105BB0001C7A3888DFA7A7521C5FDADD32EFC03CC1 -:105BC000FF1AB17F6FC8553AED5EF45FBC9A3DBADB -:105BD00021B73C417D61EF02BEE763BF951EF645EC -:105BE00084C5F779C9F21B96E72A179BDFB05CDF03 -:105BF0007F677EC337A7E7AA8BA167A3D5B556C930 -:105C000088E35BEE9B69496B5DD7BF79FD497A28D4 -:105C10003B77FF19E3F866B9B05C5DCC14E867CD5B -:105C200060BE2ED91D4CA3FC20D37AB990BC01FADA -:105C30003F8E74482677BA4BFFA7BBD2FFE9F3D15A -:105C40007F4376E0A7F81EBBEA5946FBC267B18CDA -:105C5000F2C45E4CFD11DF766432CA6793F931728B -:105C60003C324FE65798B49AABCBC329F129A82709 -:105C7000BAC11FBFFA07F3C72BE7E78F28ADD3855B -:105C800082FE0B655EC6F6F3E76574837E6F26A21F -:105C9000DF72D5D7112CEA3EFDDABAD2AFEDFCF4B3 -:105CA0000B1E277D62675F90FD5E51EB457E19EA12 -:105CB000F14FC6B8F9AE9542EE1401FDE0FDCB39C7 -:105CC0002AC9B51FB1CB486E7FCB62A1F1B683BCA8 -:105CD0007E42E9D63CCF90DE61616B16B4BBFC3AE4 -:105CE00046F13DAFB652C172BE067A5AEBFE7CFF5A -:105CF000D675BE7FBB80BC52F272893F97217F3A36 -:105D0000358FF57CF2CA9D67B413BAC18FEEBCDC47 -:105D10007F283F7AF32E42AF7603FFC5D85E323933 -:105D2000D1DD3C5058A7AC6756D7FE19F3515CAD96 -:105D300032DDC9F5F63645E8F1D22095DD4E121672 -:105D40007B859E3FBD9DBF574727B62B07E6651154 -:105D5000FE176E5D12B01AF249C2F4FC5EFF694F85 -:105D60003F15F3B45D349FEC89DC0F29E72FF3B4C2 -:105D7000D3C57CB27BF379671FE179ED125FE962ED -:105D8000BF91516135EC2324DE96AB0105FDE89906 -:105D9000390CD324609F3048413F57A6DF585FE25B -:105DA0003B97ADFF5CC594AF2AE3FB5CDCCF0CC135 -:105DB000F7BAE709F6AF409F12CC1FBB314FEC4F4B -:105DC000ECCC8BFA88A935E7E523DDFE647A5E37F3 -:105DD000F627F57932DE6ED47B5B5358423FC3E73A -:105DE000623D80BD42FE6655E8B9B16D4594EFB2A3 -:105DF000D4AD91FF41557DCE09455DBFCFF4C3F2CF -:105E0000D6E123BB2A9569BA79E706B20CE5FCEA2C -:105E10001E86FA05C162C3FB9E0D9719DEF75E5C14 -:105E200066281786AE30D42F02C4EACB7DD7FE9BFE -:105E3000A17EFF96EF18CA0336DE6CA87F69A4CE58 -:105E4000F07EE0D3F30CEF076F5D6A285FBEE3FBE3 -:105E500086FA4DC28F6CC6CBF63C6E173559B91C0D -:105E60005AE92A23FF6693CBE8DFBC47D4ABCC18B2 -:105E700055827EF5A663A52588EFBDE957909F3D25 -:105E8000195F98E55A32796A7EFE9CA0F7A997ECD3 -:105E900016E4EB457B60DD5E0E65D7BB6B704EEBA9 -:105EA00006F1F8AC8DF17C2119AF91DF77C66BACB0 -:105EB0003EEEAF4D77B1BB12F0C53D795A427FAA95 -:105EC000E4A3647893FC7821BCBD20EAFDBD787B17 -:105ED0005FE1F9AE7A7DB02DC1B84E897505FAE65D -:105EE000B53C6E0F0D4B254BDE43EBF162F5811C8B -:105EF00007E8837751BF98F3744F55BF31FB610DAD -:105F0000EBCFE6F52DBE12A44B327FFAA9BC2EFED4 -:105F1000F406EE4F4F35E0ED7DB9DE4D7EBDA6F4C3 -:105F2000AFC89FDE64F79574C79FFE3E7C8BFDBDB6 -:105F30008074CED5D157F8E393EDA3428CEDC7F32F -:105F400010CC65D5F4FBA664FB6329CF617F5C822E -:105F500071DA16DC7F2909F5A035BF9CF6CFA40FB6 -:105F60005A400F3AC84FC0F66B505E3EC6C2EED2E2 -:105F7000E2F396F6BC83F99C7695E89A9A8F78F9C5 -:105F8000215B96A2FE43F699B9F917A1E7D985E3FB -:105F90007D64A74D84F9AFD2EDAF257ECCF13D896C -:105FA0009F893E1EBF5B0DFA11E37BBB73B99E5EFA -:105FB0000DFB6FC4A3273BE0ED83F63C3C7F02C999 -:105FC000913B9CD68FC4AB39CED75DB933229FF3BA -:105FD000A3CE8E1B919FC03F133FAFC2E7BF54ECCF -:105FE0009FC7A983B6A21FF374CC4E785319CFBBB9 -:105FF0006CDC676311A223CF5F9674B4C5D6B4A2DC -:106000007EB63173BEB29681F3B7EDE3E7C4580EA6 -:106010007F1F66CE9568F7645418F557A6DFA8BFB2 -:10602000B2ABB24CFACCA8BFF2AB8DFAAB2068D4BD -:106030005F3D1BCA4CFACCA8BF0A43A34DFACCA8BB -:10604000BFFAAEFD8E499F19F5D7808D46FD756963 -:10605000C4A8BF063EBDD4A4CF8CFAEBF21DAB0C96 -:10606000EF4BA37719DE0FDDF72343B9BCF51143DE -:10607000FD39FB7F4E793D230E3F61A837B2EDA776 -:10608000867A80F056CCFF9E492461ECCA93CF1BE0 -:10609000DECF14F6DA551DBF34B4C35A781E771814 -:1060A000FE21BD3E62413B1A2956D6F14A4FA0EB74 -:1060B000A288E28B42B5B93BB60DC7717CFAC135F7 -:1060C000FBB09D391B8DF9DF7323C672232BCE40A5 -:1060D000B9D0087C11013E998F79E13AF9369F2DAC -:1060E00016E702BBC76773F65FC7289F34EC6FC51E -:1060F000BC77394FC96F7EC16F727C72BEF3C1FE2F -:106100008B6AF179FAE11FDF6FB6D9916F67EF50B3 -:10611000D8234AD7F934ECBC6F4DCF04F332CFC348 -:106120006C87FE24DF183F19A7BA285E70FA90EA40 -:10613000E3FE46E33A5CBA9FC709963EA790BFCEFE -:106140008C0F699F26C38B1AE6FB86C61C1689E84E -:10615000D69F26F0E1F01AD7DF69FC0F1CCF636AE7 -:1061600004F38D52B45433BF0D8FB2AE784E2B3141 -:10617000AE53339EDDBE1E09F94A837F388ED9E2C5 -:10618000FCA199AFCC785FB4E33E3BCAC38BC5FB9F -:106190009BF989E312A0ED86D913E4D749BCC2BEAE -:1061A000FD3DD423C9F6B31FE55FF47EF6A3FC7F63 -:1061B000EC7EF6F4F9F45C3BFADBC0BE34FBD9CCE0 -:1061C0007A58D9B9E7CF4A3AF9B5DB1CB8EE823E26 -:1061D00027CF8331E9C99212839EECDCF71E536806 -:1061E000DFBB2DC3AF78613CAF64F82D08A766F81C -:1061F00055AF6EBE4D80173AF7037A6A5B023BF1EA -:106200006AAFB48F02E437595DC9EB9BEB0DF0F236 -:106210007342BB73877BC9FE3C5AEA25FBD33DFC26 -:10622000BCF6E7BD224E7437C621FBC7F383368820 -:10623000780D2C3B3FD26DB52DE0D5E70FA77A3313 -:10624000499FA68F7CBE15F3A89B3C168FA221E424 -:10625000F9DCCD2E6BD516F15D8EE13B3E4E15F18E -:106260000D78B5BAAC5FE9F9F66A2FE3E7AF92CCE7 -:10627000F36A2F8F13DB587003DA43323E6C3B56C0 -:10628000E94479D7C4FC1E2E277D1E7DFE878DF143 -:1062900078F068111F96CF55CF37CBC3FA6D46F013 -:1062A0005BDE047958CB32FC57237D43D6B003ED37 -:1062B000CE9033F1BE789C57C4EDC47CC10025BE9E -:1062C000A271A8171FFF017B3380FD2E57C39427AF -:1062D000D9E41E5E127475DFCF35CDDBC53E9AE67C -:1062E0003D8F7D04F6E9643C47E6CFE861A56D8704 -:1062F000D55782F85E8BFF3D92FCB475889F2E794E -:10630000AFE21C2EECE3CE9BC72BDBD995E59FEBD0 -:10631000E5F986F3B13DFF004FB3AA6B27FD02ED0F -:10632000483F4737FC56DFF326F05B2D577D27515A -:10633000BF77178FCDDE2EFEC266EF79FC85678FA3 -:106340000CC8C078B6F47799EBC97391B2BC36D358 -:10635000D8FF9A325EBE57D0EF77E27E8A27C538E3 -:106360009CA6F3A2CE098CEEE990E74C653B4F7AF0 -:10637000DD54FF8EECD14FE278D71429B40F5D9332 -:10638000A918F6A3B7782B9F447A3C2EFA7B52F0DB -:10639000EFE662EECF31E761CE11F5E7784713C43F -:1063A00073AD28C7ECAA9A108F4F7BF9F8274343A7 -:1063B000941F27FC6EF50F2A62FF64BC1701D6F903 -:1063C0005B69207F8EAFB7D1B9D759AA6B0DF26345 -:1063D000B27B0E6A070528FFE9EF3D3F86F84CCBFC -:1063E000EAAA57A3DE4E7BC67791E7C87ECDF1D3EC -:1063F000BD787F5B2AE7D30EB78BFCE6E67A4705CC -:10640000FDD70BBF06CA75D42F592A5B9C48CF1CF9 -:106410001572F59B9F6BE6F77964BB5CF49DF95CA4 -:10642000739BBD6D753E8EF72AC587E717F26B3CEF -:10643000BBF373F01CA3463EBE35452CBD02DF976F -:106440005AE87DE6F59E3536CCFBD61866EE331B52 -:10645000F4E3867E520A781C677DF8BADDF9502F86 -:1064600043EB60C583E8BCF7782FAEDB6A9E3F6FD5 -:106470009EDF57021FAED5B0BF407C6889F3D0BF06 -:1064800012780079F367A447A5C6B6F373593C0F99 -:1064900016D992F2157D3C5F3B0DF39DFA7279831C -:1064A000EFBFCE1A730EBF93EB4B15F8369FE74E36 -:1064B00029B8B8F3DC936B128FB75F01E787C31974 -:1064C000818C02E877F2A895DC1FF6F5B973EA70C3 -:1064D000348EF93A81EF19FA2B5272B81C4ED1342E -:1064E00092CBCCA3509EAB53F3356039C57585472D -:1064F000453BD9C1E3926CA685E1FD2A63443BFE8E -:106500006AA6FCA184FB65B99CB5B23F48FE57055D -:106510007286A39EE57F603FAD4F83F98C711DA00D -:10652000F8644ABFC59578AEE1E519BC8D1F2539E1 -:106530003720CFBB779EEB0F470E18CEF5DB1E3D05 -:106540006038D7CF1E3DF0F79CEBAF2C78F4C03FFE -:10655000F35CBF946787D5E0E1DB01FF370053852B -:10656000CA105A590DD1DB4B78BB5EE039FC15E0FF -:10657000D919C7F30D3BF713FE0EDB60DCD0BF6DFE -:106580003447B5EDFB199126928B11EAF74667CB9C -:1065900038DC77B6DB3B8660BFED2FBEDD3B0CF20F -:1065A000E4C80FCEB819F0DF87D60E373E3F79C763 -:1065B0001B6EC4D7913B54B2D7E85CB42E1FA95EC2 -:1065C000F0D54B05819B91AF66ACF8EB70BD3DCE2D -:1065D00042B9A47FE746544ABD92F26FFED3698266 -:1065E000E97879E1D66C4359EAE5858EC4E7D41F92 -:1065F00011EB62EEB39BED3D35EC3FB800FB3F295C -:10660000F21B4E6E77D33E4C8EA7EED9523BEE3B3B -:106610003FDCE96051F203B7DA18F9B3FC13943C9C -:10662000BCC788FF99C7F9CAAE346A6FD6832AF906 -:106630009D6AA1AF10E035B8732EDF079BE631EB02 -:1066400088361EE5D5AC750A0B6BBCFE1D787F46FF -:10665000E84E8AC398E769D62F7392DC9F3367E7C9 -:10666000DDF4FD4CE6BF1BEDD9592DE6F7D77C8450 -:106670004C3EE702F19C7B0B84DE19CE469CEB4B33 -:10668000F1A38CC1DA85F5CEC9157C917EB2C249E1 -:10669000F0B3151E823717703E9EBF63F72B3D691E -:1066A00099B70E47BDF4D6BEFAB49BB5B8DD3D7CB4 -:1066B000F3AD7B1EA5AAC6FCCC1A81F711222F735D -:1066C0008E38F7507EF8FC799935888F215DC72B7D -:1066D000EDEC1A93DF57DADD667C9CDE37260DF988 -:1066E000E3F902B1CF1D017851FF7EBC24FB6EA1FE -:1066F000CAEF4D333F97EBE866C1D733B74C59D358 -:1067000003FA6F7AF1A33E6DC4A7DC7F512EF055DA -:10671000EE5AD38AF32F6726BF61981D623A7E0630 -:106720007E5251EF98F956F2133BC4BF770ABF4629 -:1067300027BFEEDC40F8957C85271D2C68C381E5DA -:1067400062A9B8F03D57B35A8CE553B6B63E284F10 -:10675000E698FC0DA794C4FBB7BD05C51C0F9A7F36 -:106760003CE65FCC628135DC3FCFEFC739696D799C -:10677000E5765CE75BF83A5BF88BE7FE1BE5D7BC98 -:10678000FF7A301DE5D7C7D6963CEC6FC153ABD32B -:10679000FD28C7ACE174FCFEE3889AF01C71510F30 -:1067A00045E6EBBB304F6D11B11AFC6F667812CA2B -:1067B000CF3F3D65F3A01FB6F16947D401F858B447 -:1067C0009DE311CA4779F94EC257E30EE3BA9CF72D -:1067D0001F0FE669E40F08F714F8EB89227CD11645 -:1067E0001BE5B52E3AA4FAB09B46D641F3337F8F12 -:1067F000E38801DD1AB7AAB5F68CAEEFC112B2E399 -:106800007A6BDCCEE9D9B89DD3ABD164873608B9B1 -:106810006DE6FFCC1E46BE07FC905F4DE6DBB2087E -:1068200097DF4DCF3C3CE4288CEFB32DBF4D57068E -:10683000C5F99F615628E0EDF4D6FA19F6F3DCD7D6 -:10684000734AAC934EBD20F490B60306960FC59DD7 -:106850001C2EB045D3AF04BC2CD86CF385E1F1827B -:10686000E754BF0BEDA8771C74FFC4FCE75E7EEB1A -:106870000A18DFFC6DB69C097C1A2E94DF925E8D9F -:10688000C8E76571FACCFBF9CB76CCD3C4E7776463 -:10689000C5E9347FDB6E3BE67D9AF13966EB6E3BF2 -:1068A0005F6F267A6D3D3A1EF576D33367EDC80FDC -:1068B0001FEF52587E51D7EF1B36BF9C8E7206F1E8 -:1068C00084FA45D2AD938E5DE8179DF4CB6154CF29 -:1068D00083719E0BD1F1733C83504EFCFEB35FC2BB -:1068E000381ADE75F8100F0D3FBB351DE7F39175B3 -:1068F00031E7FBC757E7A1DE6EB085F33C04F9F33F -:10690000864DDF257E9CF3FA77F97D4ECC5F80EBD8 -:1069100019E65B80F39CF5D80D34CFD92C48FCD810 -:10692000F038BFDFF04B2BAB4AB41F784CAC9B8FD9 -:106930009E70D0E6E1233BE3F785FC4E15F7612D11 -:10694000217BE5BB62CE20A1A9FCA553D0AB878CEF -:10695000FB73F9D6286A356EB993E4DB27BDFDF9E0 -:10696000B8FE010F46FFECEBE3F2855CA47B5DE82B -:106970003BE0BF31F81CEBB7DAFC29430CDF89FCA4 -:106980005BDEFF32D13F8C3B15FD7C1FE519F7B96B -:1069900012FEB687F4ABB156A6E7B3647260CB3A89 -:1069A000E2AF2F0E7139B32832A58ADEB7DAA2F929 -:1069B000F83EB2FB7A85E404D82189D6F9169B58B3 -:1069C000E7C6F7304EABA2C7EF2E7E7E4FF2CBEC80 -:1069D00007A0BE6E5DC7F9C71E7F5E145FAF327F32 -:1069E000638EC99E93D02C271E32C909F93D7B2C9A -:1069F00037E1F988B87C0813FE16D8223F7904D70E -:106A0000F53B0E3A17B9E0391BDDEFF3E9B37BDE56 -:106A1000BA19F8FFD3AD723D1BE5AF793D373C7F26 -:106A2000034BB49E3FCD09B084EB199E275CCF3950 -:106A3000FCBCC1FF29F93B2789FCDDDD43D8633A63 -:106A4000BBE34A287EF2D3F985B43F33E157E2D560 -:106A50002C4FABD158C8ED2A4FE1EF10D3E153E2F0 -:106A600051F2E9BCFF5C48FD74F2B3E457C9CF9D15 -:106A7000FC6A9EB7119FE6F7CDB877CA8DD3DFB613 -:106A80000AF6E518AF7D51A5FCBC76AD233D0BFAA7 -:106A90005D2DF27BDA3DA29CC9CB1DB9F635284F9E -:106AA000E4F38E149EEFD01EE848CFD4ED078EEEAF -:106AB00054D3F13C405B24715E06656CE4E2E9D698 -:106AC00064EF57D27A684FE5FEBEF654EEE71BA797 -:106AD000BAFA84707FD7C2E34B3357DE948EFBFB48 -:106AE000F69D7D2757E37E60BFCA738EC27E6B0121 -:106AF000E0B79E4F9D9D64E18746A1FDBE73FE04F5 -:106B00006C67E67A235E66BBB6D8B19D2FD91D04AB -:106B1000673F608BF309FC6F1EE66B219F3F667A2F -:106B2000BEF35AE2AB7926BE0A225F25384FE2EA6D -:106B300029F8AA9495F2FDB6888F09B9374E1D340D -:106B4000B91AF329F7F1F31EA777AA6C0DCEF759FE -:106B5000112F0BE712BF2E02FED6FB4D3F43BE1B8B -:106B6000905CCF7FF6C291E1B7439505FFFDDE90C3 -:106B700047017EF6DFEF5CF22B2CFFE2ED3EEFB13A -:106B8000AEF5C7ECFAF32D94D7B9CB41F79AB6EF2F -:106B9000FA759FDBB1FC4B07DD2FDABE8AEFB3C37A -:106BA000BBDCA4FFDB7B737BB1E9C5B343DA487F71 -:106BB000F17B8347F4E4E73E4EEFFCCB070AE6F3B4 -:106BC000ED8459A17C14FBB7C65FA6D03EBDFDC5C0 -:106BD000B386FDE9DF3B9F45E2DC55BB9B55E339BE -:106BE000E9F64C7E4EB5F157239FC473970BB7EF70 -:106BF000B6D7C3FB31FFFBAF43500EB53FCFED0E11 -:106C0000B08737311F63A31FBD67830DE8770A6D17 -:106C1000445833EF3D7A7062785022BC703CB40324 -:106C20001E705E809706949FC9F031B5273F7FFCA8 -:106C3000AF878FCF6FC1FE17EC1C41F70CC7F1A2D5 -:106C4000F8F97337E57BC0FCF9F35D6787A01D7524 -:106C5000A1F92EFFFF6CBE0FFECBCE97F37BEF9E0C -:106C60005C1F99F9BE2B5FFFE2362AFFCCEDA3F142 -:106C70007673BDBFF02FBBDEFF39F47EE35F76BED7 -:106C800017A2F77E416FB707E332ED2FFEB50FBBBA -:106C900088799FFE7F74DE9D768FC5E71C06E37BB7 -:106CA00097456EA85492E78F16F632EE33E43DDC3A -:106CB000937266931D31C9CFFD314DAC6C1F9EB3ED -:106CC0000BFB558A5F50F20EE0A1F5FAD208E58978 -:106CD00059C3FD1FC2BCB11B17FAF87D65C6FDD7AD -:106CE000A4BCAA2AB4E70EAE847141BD836E8BA703 -:106CF00009A630D9AF92FD0790ECBE37475F4B79BC -:106D000028932B8CFB909B4DFB899BAA8DEF6F6486 -:106D10004FE462BEDF8D0D36CA4FBAC154FFAF3D9E -:106D20003D44D79BD8E2D5DC9F7371789A2CF0D480 -:106D3000150FE7C75B173C89FD26E50E695DF1E697 -:106D400008F2FDA7035E087B4BE4E52DED163E99A6 -:106D5000D8973A44D712BF0E3FBF7754D72EE1459C -:106D6000E2FD62F12DE964C6BBC4AFC49B990EC5B8 -:106D700078DE53679FC7A1F15E6D26ECC6499D760C -:106D8000A38BF0F8DA167E5EE2B58AFAF5A5587E96 -:106D900096DF07FFE5A8A1CC09F33D68633B282EE9 -:106DA000E4F76B9EE1F1FC19A5E2D7149FC0FC4506 -:106DB000FD7E15F317F5F3C2FC457D19F317F5F5C4 -:106DC000317F51FF1EF317F5EF317F515FC6FC4550 -:106DD0007D7DCC5FD497317F515F1FF317F565CC74 -:106DE0005FD4D7C7FC45FD7BCC5FD4BFC7FC457DD6 -:106DF00019F317F5F5317F51FF1EF317F5EF317FCA -:106E0000515FC6FC457D7DCC5BD4BFC7BC45FD7BD7 -:106E1000CC53D497313F515FFFEAD84B867225FBA4 -:106E2000ADA1FE18E71B86F238CF7B86FADFF61E8F -:106E300037BCBF46FBD4F05ED2FFDA923386E71848 -:106E4000FB080FC77D0CFF9BE8FB8BA11D2B0B5094 -:106E50009CD4CE161374A2BF17602ADB4AD005CB90 -:106E60001CE18901C1677A21BF6E0AAF41E63A3859 -:106E7000F26C1F94FFAF8DBA8EFB25447C6132FE0D -:106E8000A7064C9CF6752FDCE7CAF8697A4C65D1E9 -:106E9000A1C0873185A02796C6A2D9C087B1148228 -:106EA00059B16C7A9E1DCB249813EB49CF736305BF -:106EB00004F3627D09E6C78A087A63030916C42EC3 -:106EC00025D8233694BEEB192B25D82B76253DEFFC -:106ED0001D1B49B04F6C0C3D2F8C5512D462D7123C -:106EE0002C8A5D43B038761DD5EB1B9B42B05F6C9E -:106EF0001A3DEF1F9B4AF092583DC101B15A8225BD -:106F0000B1F9042F8DCD257859EC56FA6E606C09D5 -:106F1000C141B1DBE9F9E0D8F7080E893511BC3C75 -:106F2000B692A02F7637D52B8DAD235816BB9F9EDA -:106F30000F8DDD477058EC517A5E1EFB31C1E1B117 -:106F400027098E886D265811FB4F822363CF10BC12 -:106F500022F673FAEECAD83682A362BFA2E757C5FB -:106F6000FE17C16FC5F6D0F3AB63BB09FA63BFA5CB -:106F7000E795B1FD0447C7DEA0E76362AF131C1BB2 -:106F80007B8F9E8F8BBD43707CEC38C16FC78E1298 -:106F9000AC8A7D4AF09AD8C704FF2D7686BEBB36F0 -:106FA000F639C109B1BFD0F389B13F13ECDCFF8FD3 -:106FB0004AFABB029673B87F766575EBBEB2FBD218 -:106FC000D2492E4EBA83CBC587D34EED253939D25F -:106FD000A13948F86D34C4BBE8472460DFB77BE4CF -:106FE00047BDD0DE595379FCFD5B519F2D7130A117 -:106FF000CF4C72F76B97F07732CC479C2EF8FAB5EE -:107000008A3DB96847AD296B5B807E930D456D3530 -:1070100008F37A73BFAC5BC09CDE3C5FE12F03B822 -:10702000FEAD59D29FFFBE404EF7E6775D2FFE9D25 -:10703000ACFF751F0FD717AE8E3E745EAF9BED741D -:10704000B7DE85F2B062BD8297F5CE3DDFF9C16E45 -:10705000B733B477827CAE6FD0CEA8EEB4F3A1A0E4 -:10706000FB63BD037E1C3FB3FA87E0FBD1AB0A5440 -:10707000FC5D95DAF58A07F9A5BEB9743CD2B58CEA -:10708000F9C92F393D493ED96C41D7BAC53686FE7C -:10709000C93A8D917FB86E3BCF43467FEA44E09773 -:1070A00006C12F0BD77D4E7EA786C57378DE53842D -:1070B000FBA7E4EFD8CC6FD9FC0ABAF5BE64072869 -:1070C0003F7EFED346FF55A3F04F2DDC6A7ABEF813 -:1070D000DB09FD9E66BFD48CDEC22FE5E3794F4C01 -:1070E000ED45F3FE12E68DF924C1DBDC4ED41B80A6 -:1070F0000F8AC3483C48BFA7C407EB7AEE82F25719 -:107100004FEFEB4F7972A7352D1FEB05D3F9EF59F0 -:1071100029D6E0087C0E78A47C968E9569940F752C -:1071200014F4808689579EE008BC3FAEEDDDDE4C4E -:10713000DC5F698C4738D7539E782D8C01F3526AF7 -:107140009FCAA6739BD0DE901DE8D77CCA46F9483B -:1071500061B6D4CB2ABAC62B02AB6DC417753B32CD -:10716000797E5AD87F08CF1548BA1C6DEE3B1EF3C6 -:107170009AEAD6169592BB6E878DEC43199795F4D3 -:10718000EA9ABFCDF3051A59640DA62E01BD4E240F -:10719000A457CB6EA22BD0ED4412BA9D381FDD1E32 -:1071A00032D10DFDD437E1CB3BB2693DD7AC8AF685 -:1071B0005FACE34FB3FF9FCDBC82EE3D91F9CF555D -:1071C0003DE4EF8CF9F290BE67D69713DDCCF4AABC -:1071D000FA5B3DD185BDEBA67B87A7F76533BE0380 -:1071E000CF6708BFE7F4A66BC8FEFEAFDE7C5FF09A -:1071F000DA0ACCFD64ECF5154EE607E3FB8D151EAF -:107200002ABFB9C24BE5B7576804DF595142F08431 -:107210009DE715C9F5058C40F97D2FF4E671A91796 -:107220007ACBB8F0322FFAB9ABFEF64639E619E55B -:1072300086DF9B34EE2AB2DB0DF922D5D71BF34152 -:10724000DA6C22DF6C9DE2C3FB64EA02571AEAB3F0 -:1072500092A1F132EA1F91BF52B73693EEB19B3A39 -:1072600021DB50FFC6B53D0DE5577B6B34BE29557C -:107270007D0DCF6FAE196828D78ADF8F605A05ADB4 -:107280001B19FF02CDCDE9E2E175BF583C227F39E1 -:10729000F4FFC5011BBD37D3E3843D4CFBF9F0136C -:1072A0000E1FC6F74EE2F937289F7C53A5FCA29328 -:1072B0003616F680883FA9B06684CCCAD7D59787A2 -:1072C000F9BAAAFA9BCA701FCF7EEAA0F860FD4601 -:1072D0008585F16E860EC03CF4BBEC1907CD7BE6CC -:1072E000469505E97C95B615E3E4CB9E1AE0C3F814 -:1072F000E8F4BED1DE78DEB0E385141F9EFBAA6FF2 -:10730000E3DF9F84FD7926E6472965148FF8E3C4FF -:1073100096D916CCB7530FE4E27AFDE3F3FC77CDB0 -:10732000E62E7973B807F03CEF95AD6F55403F27D7 -:107330005A54EAF7D3A71D9B555AF7FE7CBCDF369B -:107340003EEF08F929C6F708FC09E5FB27B32343FC -:1073500048FEDCC1FDE35DF103F3457A23BFEAE4B7 -:10736000595CBFF1F81B08A1029413F5361FC565DF -:107370004FACB751BC10F401E51B9C68C9B670391D -:10738000F43CF15D9D55B3EBFBAD5BAFFAF9EF63F8 -:1073900068761C2FBB4F0DB21158E6F911E1B54AC2 -:1073A00090C77F8CF4BD75C9083A176DCEE392F093 -:1073B00014ACA9A02EAE34EF451EFF65C3DAACFABB -:1073C0003C77E99F61C10AC37D460B8A1FBE6714E3 -:1073D000C0D37E7EF5E2975BDC24273FB3BC347CD0 -:1073E00039C04F2786FF6005BABCAE068BFB60DE56 -:1073F0009065FD2685E22AC7EFC1B8FF27CFD97C6B -:10740000B40C45DED8BC9FCEA5F854727B81797947 -:10741000FC3A9AA778F1766246F922D3D856E15F12 -:1074200088F03C031C04E0C7B380C7C58E97BBEF50 -:10743000C2F3C3F5A6F3C6C7C5398BF23E8A415FD6 -:107440002F13E57A0B5F9F6C17BF8752FE5E9C94EB -:10745000E352DE4A793DAE4F317D27E52C635B492F -:10746000BECC16F7252F78DAC1CF1769CC83789C6C -:10747000CBC9C456F5D1E8BB79F6E71E42B69EC328 -:107480005A49EF7D628BCC6E2DC2EF373767D1F74B -:10749000365F04D77144FE1E9D95E4C81CC6C7B96B -:1074A000B045894475FE0EF9FB240CF5844EEE744C -:1074B000D10B267D304BE8BF59CC946FD462D453A6 -:1074C000813437CD6B5E8BC8C3EE1C97CACE61BCCE -:1074D0002B187965128D5BF145128C630EEB88E2F7 -:1074E000BDC80B9FE5E798CCE332CFA3BBE39CED8F -:1074F0009B3216EF57EEECD7346E896F8607AB746C -:107500007490789F1DE6F89CBD53217AFD5ED85B90 -:10751000F27CA099FE73586012CAB9390FC03EB30D -:1075200028CE0F920FE66E8BD079C04F594BBA0B15 -:10753000D6C3828DDB6E1C09DFCF79EC753BF27B05 -:107540004D56B4BF25137FAA67F4BD55BD13E87D22 -:10755000939EFF47E18909BF157D077899B545A539 -:107560003C0A5D3D914710267C3584F9EF09361CB5 -:10757000527D4DF0B4017FE6A8ECE2C72BF1F6CFC7 -:107580001EB7D9AED9D6E7FC768D59DE74B16B4CF7 -:10759000FA14CF73A0FEECC8E5F9E95F58FD19595C -:1075A00024A74D7238B78CEE63957278B6D083B24B -:1075B0009F59A8FFA0FC878D3F4F477FC6EF1FF85C -:1075C000791EE56BA0BE1914D737B7D5F3FE6EFB55 -:1075D000450AE54BFD7162EB10B4076B1EFF75BAEF -:1075E000FEBED79305C1D7FAE078857E5CA86EEE23 -:1075F00083BF6B28E5EC05F76DC9E6E9BEC03CDD4D -:10760000C679D6E13C75E754EAC53C8FADE5F33B5E -:10761000BE9ECF776697798629AE72DB930E5F9810 -:10762000EC8E28E9F593DB5486FBAC4EBBC36407B4 -:107630007CC95A36213E162E7DFB032BF0C5DC4B50 -:10764000003FC00735F73948EFCF7D81C7533F5121 -:107650002AF329A0BF379AFE3D783E0FEC05B437D8 -:10766000E2E3E8B403CE221E3BED806EE26F91F0C0 -:107670006B2DDAF96BFA1D2DC5CFF33117C97B6D70 -:107680007698EEB5D15006F073FE4EA4532FF37DDD -:107690005CDC3FFBA7FE9FDFB294F8BFE312FD392D -:1076A000B6C6D4A80DF3903BB62964272D5C569935 -:1076B0005EC9F07C1BF7ABE51472BB56F1FB29BF2A -:1076C000C601744D85FEF20B35FE5CF3F07CF3C70A -:1076D00018DDA323C76B7E8EFE7627EA439785F4D9 -:1076E000A179FEE30BB9DE5CA85AC8BE5E60E776FE -:1076F00076BBB8BFA29F1847BF426E6F5F56C8FDEA -:107700000AED685762BCFB2A07FD8E116363C9EF5F -:107710006E659CFFAC126F1EEBA9CEF54DF673475C -:107720002FC4D32DAC957E177152C5140DCF337C69 -:1077300090E7A47BA2E02F80ED4C13ED1CB4F1F395 -:107740000B1F601F30AF69C23FFD015E8F0AFD7FD6 -:10775000506027BB36FCA283EC863B53B9FF90E513 -:107760006458713DDC2CE4D4F4510E3FCAF569A392 -:10777000EE0C2084F6C20CF055E3EC585D0AFDAC2B -:10778000B4707DBF328B71BF40735B39E2EF7230F2 -:1077900093317F1F66BFFD5CF6F9F8C8787E620101 -:1077A000FA19AE609CC12A08BF86F2023B7F5F5384 -:1077B000F893C90FF462EC779835857A0671847C6A -:1077C000519B41FBDFC978BE200BA195F8ED3B56DC -:1077D00016B670B8D645F72A790DBF0B7B43058BDB -:1077E00066C0FCA2FB8DE73B6E8A5AA203305E6442 -:1077F0008DEE46FC599C9ACD03FD04AA9432C4FB3D -:107800008255DD1B6F63E1361AEF02BCCF0BC7F95F -:107810003D85F285A6C1A2473EBDC5CAF6AA659CB4 -:107820007EC8878D595A98EA2DE17C2ECF9548BAAB -:107830009442F37AFC4E13E38376D6A6E3F7F6C4BC -:107840007E95DB0BE5BE8FDB6BF3C5BA9D2FF9EEA2 -:1078500059E37A7D1CD70DF02DDAB248F76902267C -:10786000E3FB4744FB8F08BE5F5328E37FDDEB6FEC -:10787000A1834569DE2F3A888EB2DFC9026E2CE4FF -:10788000F9D3721C927F67B3C594CF335BF8692C30 -:107890002049283FB8E549EE1732E51D81A144F99A -:1078A0006DF3B6989FEBFC3CAA412E91DF54B17763 -:1078B000CCC4F129DF4AF121BF4FB36F25FF80B956 -:1078C0009E0D7F3F15E36E6BC1AE5244BC0CCA8E59 -:1078D000F50AFDEEC5B45E1D83519F83B41E4FE7CC -:1078E0004285BD3D5BD0D721EEB79A8DF615C6D542 -:1078F000D0BE427C6DE476A555D8C375EB8DF6C637 -:10790000B4669DDDC981E17E0087294FDD26EC8EBE -:107910000FED1D8351EE9BEF0BF8D0C2E711CE6344 -:10792000FC5ECD1CFEDE2AEC4BC9573F2DB419E29C -:107930006DF2DC690DCA2B7E6F83294FCB45F7C7EB -:10794000D428FCFE4EE9877C5FC0D36087D27D39A6 -:1079500047D2280E6EF64FB657BAC3169D9F727A5D -:10796000C66D93103F35E9762BC2F73BEF156BA33D -:10797000FE8F788AC9FE5953397423E6271D2BFCE4 -:107980007CB2B3374553C479A83FBD86F9F4D77F9D -:107990000DF3A1F2D9C97ED847B5BFDC718B134472 -:1079A00077ECDFCF4EB6829E6F7FB0631396532382 -:1079B0002C6005FDD8BEA1A30FDEB99CAAD902F4A4 -:1079C0007EA56CCF16C0F6DA7FCCCB1F15DA027815 -:1079D0009F6E8D38B754738542F2D721D697F43312 -:1079E000D5585EE27034FF5D940BD5CBD6028EC2C3 -:1079F00072BC0FF504FDFE429F62BFA310EAA5F51D -:107A0000099E46386F8A12B6E379FF43914B845E34 -:107A10004BF83B218E42EE6FCD2B0AD0F7D28F0E62 -:107A2000EDFCE59BB4B3458CEB7F0053DFF7AB0077 -:107A3000800000001F8B080000000000000BE57DA7 -:107A400009785445B670DDBEBD656FB260622076C0 -:107A50001212020668208100419B84252C810E2889 -:107A60004689DA2C02622091D131333A7F77D844AB -:107A70007434A84F19079D169161E6A92FA32C41D4 -:107A8000B60EA0823ADA282A3AC04445058D4E4403 -:107A90007813FF87FA9F73AA2ADD75495866E6BDF9 -:107AA000EF7DDF1F3EBECAB955B7EEA9B39F537530 -:107AB0006FAA6ECF49F0E6331693E1353B53185B5E -:107AC00050A1F9AD0318638702B99E38C62633E684 -:107AD0006E8C65EC27FCB93ADCDAAE303106E36F28 -:107AE000CFF4D8AE2864AC2A3C4FDC3F32CF21C360 -:107AF0003C376970EF30F8CF5C4EBCFF866C771F67 -:107B000027F4DFF67F9817E761A34798D810C67E61 -:107B10006667F4F35DEDD65C7B01B4CFD99258264D -:107B20008C7B615BC65C9887D5C1E4698C7DD5FC94 -:107B3000A1D509F32C6AD7993B89B19A768DDA459C -:107B40009B9AAD63615C0DB4A511F8550B7C196B64 -:107B5000314F8D0B5FEFEF047C0BF1FA6AC2FBB67D -:107B6000174E9ABD30EE3653E3E74F24C3E5E19A52 -:107B7000EB59E7B9EBECEEE4EB3CC6585963FEB9C0 -:107B8000FD054E8DFA7F9DE31E8CF44B8139F03953 -:107B9000BA89AFD738FE57028FAA6876B307FA675B -:107BA0000F89B33B81DE8587BC4BE3008FB96B3314 -:107BB00007E93047FF8C929148373667B842AFB239 -:107BC000CB190BE1FACC6DDD19B4DFED284C6080E8 -:107BD000575562E80E3610C8E6CC69B08F646CE287 -:107BE000E330E672BAC5CDE0DE329B848B3DA38BD9 -:107BF00001FE51277846A0B0C10FF3EC477C609E90 -:107C00001B87F68B66FD817A993126470263237BB9 -:107C1000CEACC375DD3874E458BC3ECA16973B93AE -:107C2000E8CB483E46F6F44C433C713C837578AD56 -:107C3000C194EB601DDED775971FD6E1ED1FE30DF4 -:107C40007442B70A41D73AA783E8B1DF04780E0A35 -:107C5000E3219FCF98E38E10CC777C49DAC0553072 -:107C6000DFDA9EA3EE427CE4F3D7F6F4CE897C3EC5 -:107C70002CB73F5EBF583C660A3CEE42BE41EB2942 -:107C8000063913B4FE09FE4F1D1DA3C0D74C4A622E -:107C9000EEBC303CFD9A7405AEACCA56C6DF30E788 -:107CA0004AA5BFDC162AA88D0DCBB7111FD932E625 -:107CB000277C6AE236C63340F1E88E33EFCF003DD1 -:107CC000F9DB7ADDA501AEB7EE7CF6FD1130EA14E2 -:107CD0002C3809E876CA0D00ACF7D4263DE0CF4435 -:107CE000F9709BCBBB33361FA782F10B0FBC641D11 -:107CF00005BFCEAF9D3709F9786BC0F2494B049EA2 -:107D000067D8592BCB027DD8A85EAF610F7CABF74B -:107D1000472868F5F483791A0DFDB5E3BE60F138A4 -:107D2000CEFC498B5C273CBFEE48E683FB22D6BDE8 -:107D3000C61997FCF995F0CB2036E8271D9FD7FA96 -:107D40002AAC90953635139F961ED05D28A24B7BAA -:107D50006A4C83758EDB640B44816A7DBDED63AB39 -:107D600013E8F5779FF3C17D16D4FF7AC692F0BE73 -:107D70008FAD2D70BDC8E9243A2DDAF1AD9501DF44 -:107D8000C7EDB89DF47A2CD8B104909F5033EBB76F -:107D900009E6F767C6B99E85F96F5B399EB1C18C5C -:107DA00025B4CFA0B6BA613CCDB7B07D1AC18BDA8D -:107DB0006308DE1F1D1ACB008FFD5BBAB1A580C71B -:107DC000DB7A30F7B7388F2D8EEC4479FA8D4B7013 -:107DD000DDFBA3FDF93F83E795FFC7B832A4EBA213 -:107DE0004D9A1BE5AC5C67FBB544C4378AE62BD7DC -:107DF000DF29B81DAE4F2C8DF39B12A89F31E8D719 -:107E000087C4AD6200EB56B0179DC8E73E615F2C9A -:107E10002D1CEF31ED15349FEC7FDD9945FD12B639 -:107E2000A4AC37CF8A0DAFC7D2A2513BA1FD4A6A9D -:107E30006B3655989DF09CD7F39E49463AC1F85849 -:107E40006FA776796802EBC47E75D87F618F67A0D3 -:107E50003D86799BB3DC2DA88793EF6931DBD19EFA -:107E6000C6DA1DCF821C4C2E1AE89C1BB12E7DCF8A -:107E7000F5CC0972644B6EB3B861FE19D046DAEFE7 -:107E80009BBBF0379F0B3D65AC9EEC85F44BACC7BC -:107E90003D0CF1BEC9C1F1967AF5AE182FEF0F690E -:107EA0005C3FFC9B6D8167E1F78FB2BCED68474298 -:107EB000A358E58B644F43191571FF3AFC81BF76D7 -:107EC000E47FBCB98525C2FD3F74E0CFF5FA42F8E6 -:107ED0007F25FCC4DB3AAB43B978FBEAAB436EC009 -:107EE000ABF9EEC183D13FC8E7C5675AF9BC8EB67E -:107EF000B328AF35BB629CAB607DE5C01B84DB76ED -:107F0000DA02EB32E93AD392B1B5ADD3A0BF26BEC7 -:107F10002D17FD4FE9EEA820CA6DF3EE2833FA9134 -:107F20003D39DEF8CC14BCDE7BB406F2EDDE613305 -:107F3000A31C2439DD0978BD2B7C2F64C7A43E1A0D -:107F4000E5CCBB92EB9F57E8E14C21B7B3841ECE42 -:107F500034BB12EE02BC6F7E536768C767DDA3F5C2 -:107F6000DB5480362DCE9513A18752DF2C289783C2 -:107F7000513EB95C56B77713FA9D29E6E57A500E63 -:107F80000E1AE9537E65B700EAF7A2F6241A27F520 -:107F900055EA696AB6F7AA4CE043F952D06F788E79 -:107FA00077495A01EA4B584EAC0E94279093D4B9B6 -:107FB0001172B0B4F97B33CA89A5582339B1415B3A -:107FC0001A21479E8E38C531B63BE0317959A669F2 -:107FD000150BF79766CA78E5E2E4DD95C9E56B56BF -:107FE0006C30C704F3596AA35C4B00AF53C94EB25F -:107FF000638BEF030048B0D8E229C53863F16F34D2 -:1080000017DA5F8C3FD0FE0C395C6BF546E0777D6C -:108010007B7FE6043A4D6BEF456DFF0C6F05F27FF9 -:1080200066FB7441C7FED432679189819FB9C3CE84 -:10803000FDCCE9DA7B6FC2E79D0ED85CF83CB0D08E -:108040009CDF02DF42B7EBB2BB10BF372DEC6918E3 -:108050007F22CAABA35E9EE8C91C8F008AB3D700FB -:108060009F61DE1316E677003FE700EC45B81B730F -:10807000771B847A07EB8CF02B67CC0D192C1BF83F -:10808000BBF88363663085B7E686FA07E1B955A386 -:10809000B8FF6F5D6F21FF5FDDFCCE1013F47F9999 -:1080A000E9BE8C81ED1D7BB9F7365CCF82A98117C3 -:1080B0002C00DFF6EB97E28739C3F46C340773CCFE -:1080C000707F23D0D10F78353EA0970578DC13530D -:1080D000D1EFC272BDA03D9BE823FD8DB4DF5B7D77 -:1080E000A9B088B01DBF901F92F2BD50E8C142D424 -:1080F0000316E96F2A3CA3500EF334570E8BF43766 -:108100005C1FA49D067927BD29CFEEE95ACAC27625 -:10811000DBE88FF6EA8D8F0C87F5FAB2BC4FA2DC54 -:1081200097FCFB7FBDF4117455BFF887D1C8A751E8 -:10813000576A4CD72EC64E7E6F213B794F05233BA5 -:10814000096DA49DB47411A7AFBB44B96F10720F31 -:10815000F12DC58D68C723E7FB28AB6413F2795B6B -:10816000A6C6E7FB17E16DB4EFDB3AF0BE38FBFEC5 -:10817000FBCC8BB3EF6FA27D2F3CD79E33980FEDD6 -:10818000F9DF76F609A0BD3FC6C0FEA37FDB11E391 -:108190007C56D87BF207D10981F3D9FB5FE7CC7E0F -:1081A000B30B7BFF67E4FF3F6BEFA57C19F5C1A81C -:1081B0000746B99F783FC45FC8A7AD1A43FB1A8E24 -:1081C000B718C9F1FE2C2EC7526F22E22FF2F3A08E -:1081D0000F819CCC73F5F2BBDA0F0A9C986F16C422 -:1081E0000D645A58DEA5BE487937FA913959DE1F19 -:1081F000C90F083DA97ED1E807BA92A76D16CC5FDA -:108200002DD5DF723F006DA41FE82ADED1B32E2DDD -:10821000DEF9F622E5A97B168F17FE1BE5A97B5632 -:1082200061A7F27459D63F113F9C878FE467A49CE5 -:108230004D7C83CB07CBE6F13EC80BE1BDDFDA33E3 -:10824000B03413ED1EB787137F62B548CF9B453D11 -:1082500041CAEBA86CEF88AC083E637C8F71FBC50C -:10826000C68533926B991BAEDF0C6DA4DDB021FF88 -:108270003A89EFDD599766EFFA0BB9B8109F2BB228 -:10828000FEE5716155677C656EEEFFC37CB14D43C1 -:10829000B9F92E6866A85F5DF1D5B286D35DC2CB11 -:1082A0008366E95F93D0BF82BCDC98F54FD89FF21C -:1082B000D2C6D37608FDEECE1A5E611E06797A111B -:1082C00013F58F11ABDD66B42FF0EB709A91EA23B2 -:1082D0006FEB122E3E381AF098F84847BF1FFBC7C5 -:1082E000142774D453309590E37F9935ECE00384E0 -:1082F0007703E7A3B7C5ECE9170117001C170117AF -:1083000019E0B57C3CFA1107CD13E0F61EE6D7065E -:10831000212CE7137AC0DAC676C3787193E6C07A67 -:10832000C80DC57FB3227FCA4B5B5E4D87F53E9873 -:10833000555A110B21C00D680701DFA7B226AEF612 -:108340009BC5FDDDA93E463FB646CDAD039FAA8B3A -:10835000B44056E6B9747C2A4BF567F86356EF676C -:10836000D6824BBB1FF948F767D1FD41DB253CFFA7 -:10837000BA62E60E7462279F9376F22CC0727EA0DA -:10838000DDB4469E871BC76F12E34326D34206F433 -:10839000DA9175F36AAC978D615C3E7665DD54E1E8 -:1083A000CFE7E8BA0DEB3D1FBEEB3A59AF53BD3FE7 -:1083B000783E7A6D3CE77E211FF3557949307BF694 -:1083C0007D077824246B0E8C6B1779A21EC0F8BD34 -:1083D000BC54CAF7AD15EE62585F1453EA7F61F9D9 -:1083E0005E50311AD6B788C9FEEAD5E8973CA68E0A -:1083F000F15CDE77681DF7E781FC50290EEE3F9CAB -:1084000075DB6AA40FF083FA09369F47DE1B0D70F7 -:10841000B1413F847C937EA2DD06FAE4746237CEDC -:1084200008BE7DADB14AB47BA1121EEF85B2789B28 -:1084300092CDEB243F083A5AB2791B8A8EA0438F23 -:10844000309FE127887944C4BA894ED7278B75FBC2 -:1084500057554CEA05F727B27E1AC849C2332B5646 -:108460002FEB19BEBFDB33AB484E3AE6F3AF3C8887 -:1084700074BC5ED029E599FB0E0A39D250EF1692F2 -:1084800040801C6CD2FC3AAC7321CA4127EBFCEB58 -:10849000B972E437DCEFB69CE7FECFCEBDDF6DB836 -:1084A0009F59922FE57EC1A749063E9619F838DA02 -:1084B00000574938A0D83369E76635AD5EDE3D190F -:1084C000EB8D1ABA09B4D7566D20637DB31FAD8802 -:1084D0001D86F2EAB4A483CDEF9FFDD8413BC8725C -:1084E00005DA3392DFC7C97E4F437D27784D857B00 -:1084F00000CA4FEDF254185F90FD9BD576D0AF1BAC -:1085000096ADB6604C5394FDDBD56698F7FA82FFC2 -:108510007815E7336B4F1E9C94791E796D30AC63F0 -:10852000AD01F61BC63F7A01FBBECC70FF3D86FE57 -:10853000070CF01A03BC52BD7FE61C8DF46426F0D4 -:108540000F097721BD999CDD111776F8332D96E23E -:108550002445EE272EE57065F6BF57AC8C8D809FC5 -:1085600079AE22528E2D8CFFCC48667EF41F962E5B -:10857000ECD9D86CB5DED5B19E3CA3BFE3FD7FC579 -:108580005FD3689F45F1CB7B75156ED6A5BEBD7CCC -:10859000F08E58BC28E16D1558BFE872DFC3BFB537 -:1085A00002F73D263E24FBB756B823D629C78FFDD8 -:1085B000E1271D9FB7E8992D15EBA1BFAA24988349 -:1085C000F5FAAA44DE829FD1D18FD5887AC7D89D8B -:1085D000BA07FD4C55743067717EC43A59632EAEAC -:1085E000B3F96E9DF8E35FCAF39159CC65C57A453E -:1085F000734242DD0618BFF76EBD0EFDDAB1BAA4B4 -:10860000EE984FECCEE6F9DEDE842BBADF02707313 -:10861000CCCD56ACD736DF3B86DA3DBA7B451BC89E -:10862000F103D9AF56C4F6C1FE04A2CFCA679A2B94 -:10863000EAC15EDD9FEDA4FBBD898EEE4D18AFAEA5 -:10864000B230AC5733E67A8AE4E6D7B681AB008F16 -:1086500099F557D2FED1AC7FAB189B06E3662DB7D8 -:10866000D0BE02FCF447BCBDABC658B17FCE32D100 -:10867000FAC751BBFBC797DEE80FE3DBEED35DEB38 -:1086800060F0AEF6ACF85980D7A751DC0E7FD2DA95 -:108690002B1EF1ECD5CBFB7836CA6B7C5CB486CE56 -:1086A000C3E18C9F0AF366E6B8D7E075397EF78F91 -:1086B0003AED836D6F9DD51DF9B74EC8CDAEF65915 -:1086C000DD6745F8FBB95F9B89CEBBADCE3B30BEC5 -:1086D000DC1DDD53C3BA0CD03909EBB673447C0DF5 -:1086E000F252F752277EFFA16C9DE872DC56C73E1E -:1086F00005216EBE3FA518F194F7C9FD374B0FE772 -:10870000A0C838FA775794BC909D122967470E622B -:108710007C4F7134C0DBB23F5CED07BFC2F642FC58 -:108720008F7824BBC7A25CB17B92F83E686A636E07 -:10873000643D221CA72E11F6808F3BEA8FA3BCF567 -:10874000E8735101CC678EFAFF1217597F977A327E -:108750002F3ECE8FCEF88BB83833D2F598D9F7F9B3 -:108760002F70DFF0490BD9D1B94FA6DCD386F600C4 -:10877000F889F520E373937A59689EAEF707BF54E2 -:10878000F5C47FF2BC7AF26EF6C98AF5F95DEBC9E1 -:108790003C11B78F7DD2E241399F571867C67DBA29 -:1087A00092275F7916E571DEED51836C80F8BC2766 -:1087B0006DC4DF96B838BF03F711E3E3CCDDA03D0D -:1087C00021EC574B7D14E5297A772BD93D7D45A1C6 -:1087D00013E953AA33B31DFC8A1EEF727A38BC0C1E -:1087E000EB86CBE38A9CC85F472FAE0F1DFD099532 -:1087F00013B4FEE17DB393758F3C361457CD02D38D -:108800008766FEF3FB6835CC9380F5C7FFAE7D34F9 -:10881000AD575CF2E7908A87F7D1F213AE43F1AB24 -:10882000D3096F7D495400E9A967703F318E69B45F -:108830008FC61CB0FE7EE17D34FD9783893EC77DE7 -:108840002057BD812EF1761AAFFF520FD8E0B9A59F -:1088500049BCDEAA3F56C1705F0DE8EA77003C2EA6 -:10886000B996F6D77E25ECCC4C8D791A49FF5D1967 -:108870009827CF7D328AF838EFA95BDFFF4D01F2F0 -:10888000AD3C39529F7A08F983F9983D313CCF17B6 -:10889000F5BFCA407C4A7F07F925E69DBAF7B1EBE0 -:1088A000C96EC6D07E1B73B4FC7A28CA4B7DCC40FF -:1088B000AC93CF7B322D232B3F7CFFBC2577E7F297 -:1088C000FB216F8D47BB1545EBA9DE6423799979B0 -:1088D0009FEE263FD9D34A7EF29365510457F7287D -:1088E000227D9B69E2FB6F1013A6927DE72467D57A -:1088F000B1CCFD522CDAFB07423AE78F5FF0CD8A0C -:10890000FC19DA2B899E7F33D218FCD77542DE66BC -:108910009AB81CB15D1AED373156EB443B5065D225 -:10892000C8DE19F5B2AC178F5F6766B86EC2FB166A -:108930003E68732DC9E438E8121FC89B169A42732B -:10894000711F926DB1517DA306D61115CFCF3DBCDD -:1089500008F8D79899D98AF52927B76B129F1A6713 -:10896000C5389457E83F6C86FE8571DC2E2FECC627 -:10897000EB3E2CCE1E7836F279887336BFCF198F36 -:10898000FA368CE405F5DF04FD7F63BCBF34BEC856 -:10899000D9924FFBF72BB15E82F8F4E91FF15C80AE -:1089A000D3FAA33CDE6ECE8A433E244DAFC4E73DEE -:1089B000AF937D02A57AB008E3C0E7F5C198CFCEAA -:1089C000BC6FEFD83508FF69A0035198F9C2BBE42A -:1089D000A76E1372D682F13FFA2D80FF046D6D2FC2 -:1089E0006E1FBC3AAFE7D4F6E2755E4957D9BFF0C7 -:1089F0003E0BF163E1722E0F0BEB3FA07917C6859A -:108A0000BA233F166EB60C41B9FE85C07B567DCFAA -:108A1000E2C3201FB32C090E0D2E55FBCBAD08571A -:108A2000376804CBE72DBCEFBDEEA67C3E1FB63603 -:108A30002147E1795332D0AF7DF55C52C6CC08BEF8 -:108A40007FB56C6B3CEE6B7F1A15CC71603DE6F622 -:108A500028D73AD253CE8FAF96E5ACC37ACD1C4718 -:108A6000280EF7C3E7DC919D88FEEE982368C5FECB -:108A7000638D992684DD0E4731C26EF30082BF12EA -:108A8000E754E807F8B448E37253FDDC5E6B163C2C -:108A9000EF29419FAF9F7F3717EB060B3342B9E8B1 -:108AA0008741AE72D3912F7FD4285E58F49CEE8E0E -:108AB000EA1F96AB452857A0FF0B845C2DDAB4F56E -:108AC0002ED4D345284F83CE954BC82FF7D1F51719 -:108AD0009F1ECBF8FDFB50EEA4DF07789905EB6BEA -:108AE0005601C37310FE1DD23F85FA47F37E7F3EC9 -:108AF000F913D662C5B8B846E7F102703615E389B6 -:108B00009A268BBF25C23E2EC2FEFC707F57721381 -:108B1000EC25F6CBEA6DE4978242FF5AEEDB1C8F20 -:108B200072F1F5F37B5F1D8E79D68B9A03EDFE39DA -:108B30007A28E85683748AA775527C548374890F07 -:108B4000D3A943DF845CD4304E0749971AB3A0936E -:108B5000EC17F7370B39AC6682AE9B7A737D17FA48 -:108B60000D12437E44AECF9BA89E1F3825E4FE6DB8 -:108B7000B1CE6A901B573EC997DB3A44E4FFD0F56B -:108B8000F59F9EA6FA91E4A7C43B3A873F1FECB439 -:108B9000BB5B6298CF2D2636BFB37AF56742AE2C09 -:108BA000B1DCAE7C5C9F7E531DD06FC173BA8B88E5 -:108BB00087B957C4736DA696388A4F7FA93B705DFD -:108BC000A5FF5E3101D72DE5CEB2513337E13E210D -:108BD000EB46F497F8955EE699D08DCB5D10F19158 -:108BE000787EAC05895FFE3F690E1EEFB658B18EE8 -:108BF00028F5D488EF2981AF1EAF0DD706203E2E71 -:108C000027EA37033F48F8C41EBE9B9EE73F7A77AA -:108C100066FFF0738EF9E3CC38EE18E37640CAE5D0 -:108C2000C7A22EF1F1F2AD140FCBE7D873B85C45B3 -:108C30003CC75B977CEE733AE2BC1C8E97D48BFDED -:108C4000895CFE4B977D40E3A49DC51FACC7497A64 -:108C50004ABA45E8A5421FA95F529F245FFF51BD54 -:108C600062F7A450DC7AAF5837E948F7B05F40F9B3 -:108C7000447F67B3F27370117E93E29A713DBEB583 -:108C80007A3BB92EE964BC1ECEAB1C1948FF71B10A -:108C9000A9B45FCE96A5EEEB15119F7D8A752FB412 -:108CA000A77FD003644F196865843F97715BFDED22 -:108CB000E31CA350BE9ED3E8DC91F4DFF0F34087C1 -:108CC0009CC27CF30B6ECFC57862794E16F767C9EC -:108CD000EE93787FF589D0D87867387F19793AA8EC -:108CE00027607D7053A6923F54B7EE233D5FC84284 -:108CF0002B30DF9D79DFBBE54391FF7FB0D0F98555 -:108D0000390D99E4FF4EAE9F3D1853DB99CB7308A4 -:108D1000BEF5D95B387C1F8FEB662E2FDC80F5F912 -:108D20004FA3DC6351CEDB566B0ECCBF463C5B7869 -:108D3000CF0DD03F22EE8A6E88EFD1F59F960FC7F8 -:108D40003CA24E27BD71AF7F643AF6BB9B74172ED1 -:108D5000710E73DC7303CAB93981F44E9E6B5C6A81 -:108D6000E1F2E6CDE176A33287DB8D4A21BFA54B48 -:108D700097E6E2B982B6A7C14FE1FEBAD5D918C4C9 -:108D80003C70E765AE75F09C1A485B53419E4E6897 -:108D90003C1E9F6F657694AF0396D09D88FF813B04 -:108DA000E306D62302FAD921A81F6E9177411E450A -:108DB000CF95F492CFBF59E8819C47DEB71FE32AD5 -:108DC000F42302DF93CBFE301DE385931B7312590E -:108DD00004DD4FE2BA80DEB7827D7CB1937CB03A8D -:108DE00047D6B902FC39A28E78C0D2D003F77321DE -:108DF000AE3F1E199F7FF174941DE512E27AF5BA19 -:108E000085FB1588E795EBA03F0ADC91EFE9550952 -:108E1000DE4EEC916C8DF1BE2F27B6D3785FEA9FC2 -:108E2000F17E19DF77D45D7A5DDAB9AE561F300670 -:108E3000146228066780EFE8981F5EC2F397731BE1 -:108E40006C0E1BD0F738EA17EE0B6ED679BC68E7CC -:108E5000FA767CE7C000D615E61E61AE20C0730F1F -:108E6000E92E278CDFB7FA5E3ADF71CB5A8D5DA60B -:108E700045E45D8FAE9E8EEA76CAE55D9106E34FCE -:108E80006DE4E751A03BD6906FBD9AE6EC3ADFFA6D -:108E900057E559B2FE64A4FF7FE4887CCBC55C2A09 -:108EA000FD79DEBE1BC4A868D0B9F46FF57929AF8F -:108EB000FAC6379FDA618D4F97A6C33AFEA67DFCAE -:108EC000E008D4A3B804AA9FB4FA6A6973F09BA619 -:108ED000C16727039DB6C72638D07E7CE3ABA3EBE2 -:108EE0001D7223E474E4A6663D9DD1F81D2360FC49 -:108EF000AED804DCEEE8641F8EF3D978FEE667B7DF -:108F00000FBD0CAFCBF57EF90BCE6F89FF971B67BA -:108F1000C763BCDAFCDBA41DC390CF31090E1485F6 -:108F200079E21CCEE76BB83D3A614FD88075D41317 -:108F30006BA775C7FCF0164B9BD505F3BA7656C4E4 -:108F4000637DE433734BBC035B181F443CCC011DB1 -:108F5000EDE0F03246FB83C38366E6CCA4AD7B92A2 -:108F60009F61ADE600E6CD5FE1BE21FAF1B3D17CB1 -:108F7000FF5EEC07DEB28DD7D93AEA2AA2BE3042B4 -:108F8000AC37363751EE03D1F5D2227EFD8BB52FAB -:108F90004DC6F94EAEB73810DF6FD65B68FE059050 -:108FA000DF9B401E4F6CE4E70516EC803C3913ED67 -:108FB0008846F2BB00E4D78EF277BBC56D4D3857BB -:108FC0002E4B37F2FC7A41A346F9B694CF05EEC09A -:108FD00058A2BB90533BFCFB095C4737D6B802E96B -:108FE000D195BCFEA3F5003DB7F37A80511E24DD78 -:108FF000A45C84E594917C4AFE27360E1C954E377E -:10900000F8899EFE129687F1C2522BCBC3F3507E95 -:1090100053B40BF5FEEF51F1FDB10E5567E7ED5D71 -:10902000D1F1EBB0FD7B544600F1FEBBC9F10AE67D -:1090300059BFCCCD24B9BD4B775A34F8755A72CB91 -:10904000687203A526B709FDE0521BD911A31D7252 -:10905000E672FFB32D97D1FDC5B9FC9CB885D552FA -:109060007C215B88077A62FC52119378068F92F715 -:10907000CB4D996606B9AE1891786736449E85B98E -:10908000E9D370FFB76270E2E62C80876E48E3FD9B -:1090900003120B2D00D76B3DA68D86FE6B72DD573C -:1090A000E6463C47CE0BD7FBE3F59234EFC0DC1429 -:1090B000F473B12BD10FFC4D6B5B64D2C3E30F6A29 -:1090C000ECD8762D0CB7585806C6DBC5887F4AD732 -:1090D000EDD25CF770FE5CF5FA2C0839B02E31CB7E -:1090E000FFDA618DEC19F3D8819F5384FCCDB2C7B0 -:1090F00006C9CEADB4B476C84716DAA90433F27DFA -:10910000B260FB1473B019EFEFC396393EB753A8A2 -:10911000B8F6A7A4AEED3F282AFB5CCE07EBFB9B7D -:1091200005D60B7CD5DCC06B50310D885C05F64E46 -:10913000DBF1DAF738EF523F6B89223E5439F07C8D -:10914000B7C6BCA69FA05D18037231005B900718DC -:10915000B778F3D7FB502D6E957196B788E2C53B73 -:109160001C7C3DCC3B9CE4F54E21AF5FF82075079D -:10917000F99C120AC5E351D8D6C9C15CB40F65BACF -:109180007736F2E18BB54B7B2C06F9F9FA459B6BF0 -:10919000128C3F1178291EFD6AB588F7D9593D78A0 -:1091A00035F4EFCFECB36E55847C55E772BFDF9A90 -:1091B00019CCB81BED4C26CF57D9D9BD1977C3F8B8 -:1091C000B2ACF185AB880AEE45B911FB9393CD9D06 -:1091D0009FDFA8E8C1E323B69EFB639B99F9E312E6 -:1091E000A965F140A7F1804B119E4B0558A7FDFCE6 -:1091F000003D1FC7C5635CE39C9DCAF77B9807EDE4 -:1092000096E4AFE4DB39FC049431AE37D99905D745 -:10921000DB87AD75A0FE4BBE7E21F4F10B3BD7C3BF -:10922000317A2CD9A9C59B795D6FB1C6EDEDE29D70 -:109230001AAF6F9EE36F37AF409B3C7FED6CB26718 -:10924000D28E39E11FCAD702872721E8FC07FCEE3E -:10925000DAD28BB2674FE68AF70406B281287F170D -:109260008A97A41D03F6ACBF247E21C960DDF304F8 -:109270008E63F42AA719E9926277A13D5FFC6436F8 -:10928000F94976620D8B1CC7D62691FCAEC8D489ED -:10929000AFE54DE9CC09976E6DD2E89CECA4A6240D -:1092A00082E3DBD3082EFFFD6525B8EE8E7DD0DF8F -:1092B000F726F8E486370ABCBC4E63C7F93D4CE29A -:1092C00091DF88FEE7542CE00174F6C4AEA4BAA383 -:1092D0008775E443DA4F1AC22035A8776E8B9FF367 -:1092E000C75E4FFA2FD6B558E8D5E203DC5F2F1ED4 -:1092F000C5F70BCDFE3E09C87FCB7E9D0500BEF6AF -:10930000805E1884A14B853DB7A59A9833826F5132 -:10931000CE68E68CE00FF3BB43986F550A79B937F6 -:109320008ADBFD98BC44655C65EC5C929F50C6D8B6 -:10933000FDB8DE38D7E5CABCCCCBE3632957D345AB -:10934000DD7C326B5B867EF2DA4AE88F98CF52FC86 -:109350002DF90D4BB11A57035D8E9F4F9EBE90FEA7 -:10936000B10FEB43F264A00FE807F9FB5387F8FB5A -:109370002710953C5E0CF0F4FD161680FEE5822E5B -:1093800018B762FE73CA1D477A23E52E847E0FEC60 -:109390005C42914AB76E6E956E49652A7D523C2AB1 -:1093A0003D2EABCC52FAD3BC7D95FEF4F98314B8B4 -:1093B00067ED7065FC1575250A9CE99FA08CCF5E52 -:1093C000395581731A6E50C6F75E334BE9EF135867 -:1093D000A0F45FB971B102F76BFCA5327E40D312E5 -:1093E000A57F607095D23F78FFC30A5C187A421956 -:1093F0003FF4F03AA57F58CB1F95FE11275E54E04D -:10940000916D2F2BE3AF6EDFA3C0A3D81BCAF85218 -:10941000FBBB0A3CC6F11765FCB8D44F95FEF1CEF4 -:10942000AF94FE8979DF29F07211E794BBFE4BB946 -:109430002FC496E5A01C3B7B788B7A53DDE784191B -:10944000F5EFF08D1A4BC2FC67FF3407E9FD25E606 -:1094500081EEDEAA1C9F61B137E179F60BD9C50C0C -:10946000114F8CD127D17B55A71A79BDC3E8D76599 -:109470003C97006ED91CF1DC6E6E3B24F46138A978 -:10948000CCA1C0299E5465FC65954EA53FCD9BA7F8 -:10949000F4A7CF772970CFDA2265FC15756E05CE5B -:1094A000F49729E3B3577A1438A7A15219DF7B8DBB -:1094B00057E9EF1398AFF45FB9B15681FB35D62960 -:1094C000E30734F995FE81C1954AFFE0FD0D0A5C82 -:1094D000185AA38C1F7A38A0F40F6BD9A8F48F38D0 -:1094E000D1A8C023DB9A94F157B7071578143BA095 -:1094F0008C2FB51F54E0318E0F95F1E3523F56FA91 -:10950000C73B4F2AFDD55FB982B42FB59DBFEF2A67 -:10951000E3B98979DF2AE32CC910EF63FD9B45BBD2 -:10952000F0BC7F5771BE8C03CB5DDF2BCFFDBB89B9 -:10953000C7E7BFEFCDDF4FBB4BE771E252BF87CE2E -:10954000E725E28157D09304BF46F287295615D507 -:10955000239369DF825CA613CFBB411C0440A22980 -:109560003313F39098701CDBE3A7C1171FC76E86F7 -:109570001C07F138DEDBFBC7DE8598B7FD692CE6FA -:1095800039B732FF0AC403FC6E02EE63BD15A5D6DF -:10959000A3643BDE0E748C78DE81A8861E83CEA386 -:1095A000BFE3EDAD34BE635E51AFD2607D8B23E689 -:1095B0007F10F22F33E869830FF40C12ED877D0ED4 -:1095C000821FF5A512FC98CF49ED1A5F1EB54FF822 -:1095D0005CD4BFD65744F0533E37C1015F19B5EB99 -:1095E0007C1EBABEDE5749F0069F97DA8DBEF9D4CD -:1095F000FED1574BFDCFF9EA087EC1E7A7B6D1B738 -:1096000092AEBFE86B2078936F0DC15B7C016A9BC3 -:109610007C1BA97DD9D748FD3B7C4D04EFF20509A1 -:109620000EFAF613BCC71722789FEF30C1AFFA5A73 -:10963000A8DDEF3B41EDEBBE36EA7FD3D74E70ABF2 -:10964000D84FF8A4B7A6BCAF2761C646933CC8F86C -:109650007732E63D281C45966F94BCC7907F18F979 -:10966000F1A5788EA504C25F8C7F2ECF5DB7342222 -:109670002FF8463CEFDE68E68F027DA837F1BA404E -:109680007D22A3F7C39888CFE709B964C93C2E9F10 -:109690002BF09A27F4A010E5338FE4F3CD4BC9B338 -:1096A00064BE1D93E1FD91E4B3A7C94F758758FED1 -:1096B0001E7EFF0CAF9607FDA76A6F79959EE77037 -:1096C000E5E243CA6DC194EBB09E7440A73A6C5773 -:1096D000CFAB11EF4974D9BFEB640FF447653FEA94 -:1096E00054AF7FCB125789F596A43C5E874DCA33A1 -:1096F00029EDD60C4F621EEEDBE7D46EF899167E8C -:10970000FF7F0AA6E6A0E715CC69A173B8CCFD0AD5 -:10971000BE7A732D047C085FC7FCD48EECE94DC77C -:10972000F55C0F0906C2DEE1B68CCED663C42747CE -:10973000E09323F090EDA10C4F2FC4E7788E5BC12E -:1097400027EA0AA73857DFF614E2F59F3BBFFD5C16 -:10975000CB0ED35BD637568C12E7B46ED7E43E38C7 -:109760008F13ED4CC689D45F7527AFF7487F79A476 -:10977000A3E5F6F054AD85EC669516EDC278FB5482 -:10978000ED9D0370BFF046C8F770FF54DAD12A8010 -:109790004D0057317EEEA2EA481CC999D1BEC27D68 -:1097A0000CF7FBAA2004C0FCF16C06AFA7BCE5F9DE -:1097B000D682F3B2E4367A6F15E4660CAE7FC13020 -:1097C0009DBEDFF0962990ABE9242F560DF09F97B0 -:1097D0000CF2D249BC20E56291782F475E07799B55 -:1097E00082FCF966DBD03CDAA7D935CC89F45C6A17 -:1097F000E2EFD5F95FD7F9B90C2CE5E3B99184FC18 -:10980000A7E9FD020C2E907FC3E2E8FD82669DD59C -:10981000FDA9137B5A2BF8F856AAA52C40F3AAFBF6 -:109820008AB7E6F1FACFAD795C2FCBF71CE889EF68 -:109830000D2EDA6FA1BC8815B4E47B3A3957555325 -:1098400077FFCF7B45C8794DD3C7FC3C166BC98FDA -:109850003C87B552CC2BE54BB7C6799F8E8DC4AFF4 -:1098600043CE6B849C7F8E71FF649B33E13AB8B525 -:1098700005481384D6FB3B079DE793E7FAE6300FD4 -:10988000B5F380DD28D71EFF6A7AAF7E016BA4EBAB -:109890008B8A6667205CC3DA46A7C27CD7AEAC7FF2 -:1098A0002515B09BD6B07A0CD6B9A70666BE826DD8 -:1098B000C57AED73BF93F4C48FCF6FD16A975F0EF3 -:1098C000CFBBE1B951CBB18E3C59E77C606F703EA4 -:1098D000803CB9F5C473D7077A71AFD00BC25FEA89 -:1098E00045D512E6D692C3EF8174E849D16D7F4D1C -:1098F000C73D16731B9D43A9D9654BC4FAC902C65F -:10990000FD76B80EC4FDB5D4832F2D9CEF5F3EAF1E -:10991000D17B365F6A8CBEE7D055DC20E34FD03F69 -:10992000AE77C762B8FCEBA2AE97E14D1D941DF671 -:10993000CF5F9A0243E2B3C97F3F83EBB194781FB4 -:109940001888E7F55ED05C4B01972FBB0532F839DC -:10995000810E3FC07E8A09D7091FB4F0BA9D31DE5F -:1099600095EBE80A4F9B95F9713F4B2B7AF57B8C71 -:1099700043CEC5D79B3A04E8B214598475C9128FF7 -:10998000B3333C9689E7EFFF81E7E3FE9E8CCE057B -:1099900019E9A939F873BAAAAFDAA2393ED24F4908 -:1099A0003CCFC58BF3EBADBC4C5E6714F831E6C819 -:1099B00073C0F3CDE66817EA6B85D9FB67D473599A -:1099C0007F9379F1FECC2FC81FB0B34B7BF0F3C768 -:1099D000C1AEFC706B473E9E15F693B28EC58A3BB6 -:1099E000AF477AEC0EB25F53998BFC451F7644D299 -:1099F0008BEA583AEE10529DD74BEBB0A1BD86369C -:109A00000AEB28E42F0324AF318817AD2B841511FE -:109A1000B63A269EE830FC30233B3D1CD700EBDDF8 -:109A2000F9310BE079AAE633D34BE3A07FE7D766A1 -:109A3000CA831E8F79211DBF23B1F3E4FBE958EFE0 -:109A4000A93FB385E021AD634FF2FAD9911938DF10 -:109A5000F6D356A78DE280DB890EB24EB99D311741 -:109A6000EE83167D184BEF19171E6A8C21BA89BA3E -:109A70005AB15877F1695E0FD985C030C803DAACA6 -:109A80002C18112F5B1C2A5CC422E04C7C24C011D2 -:109A9000758E4BCD1FED7D445D6D281B1A595763A4 -:109AA000ED899DBE4F65DC472CD038DE9FE679BA44 -:109AB000F5A13ADB549DD3FB471DE975756C200D6C -:109AC000E3DBE65B37A461BCFB78CC8F44C7277E21 -:109AD000B0A6215D1B46FD27F99106B83784F9AF82 -:109AE0003910C5A8FEB590EA6B570B3FFBC4D94FA0 -:109AF000582AD0B3A18891FF64C20FCBFE86B3A7CA -:109B0000E6233FCF14DB9D681772453DB4FEAAFFE4 -:109B10009BDA12418F9D10570781C1DB21AE0E42A7 -:109B2000ECBF0DE26A84F1BD536C37435C8D6D0070 -:109B3000E26A6C9F82B81AC7615C8DED131057639F -:109B4000BB06E26A6C1F83B81AC73D0A7135B60FAF -:109B5000435C8DD71BCECE2A257C0E337ABF7E493F -:109B60004CBC09ED2BE01F8D75A1B7DD83A2911EC2 -:109B7000579D3629FC2D6E8D56E0E1C713C3FC4579 -:109B8000FE1FB95CE91F72284BE9CFF4F755E02BB3 -:109B9000EA062930D68722EF4F9F5FA2C069DE090F -:109BA000CAF8CB2AA72A708AE706657C52D92CA569 -:109BB000FFA178031F03D526958FFCFB0A678A63F4 -:109BC000E97C655772FAB0E08B841FF9855ED9593C -:109BD000DD766E1FB95FCFF381CB056E8BFA384906 -:109BE0003EF71D1DFA87DC02E487896F9BBADB62B2 -:109BF0007A015F721F31313C5748270E003F87B80A -:109C0000EF9192533128977BCBAD51C89FDDEE92F7 -:109C1000688497945BD322E5A821D33B88DE53F078 -:109C2000F2F5C9FB1F2A997ADE7DF48751FE7A9FEF -:109C3000A77FC2822CD48773E8C8E6D37E6D988E46 -:109C400053E9FB4ECC3B5FC1DFA8170C37E9D3F0DB -:109C5000B976959EEEACFB900E4F3C6AA673581DEC -:109C6000F389FBE57C63F4B3312DF9E7E2BFDBCD8B -:109C7000C743FC1B8574816729F825BA9CA3903ED5 -:109C8000BF11FAF66F42DF1E177CC53C1661E6E095 -:109C9000F749BE35CC7F787C2EEA4D11C76BDD3598 -:109CA0000F6B686E9298ABDE1141D747051E4F8946 -:109CB00075ADC579014EB9C6AD21FD32EA3C1AEA4F -:109CC000DB15F7B410FC84D0EF1EB56D74BDE71D35 -:109CD000416A2F9F1FA2FE31FA73B48E0E3AB85418 -:109CE0003A1AF91410EB91F386EF7FF100CADB19F1 -:109CF00037C73FDE1FEB467F11EF77B878EB14AD27 -:109D0000CB85763FDEEF16706D3EC2DBC4BAE2FD56 -:109D10007E8203625D0DF3930F6C70869FC79C3546 -:109D2000A6487FD3953C6D15F4DF2CE864BC6F9B8F -:109D3000A576B0A313BD92ADF4A745474C06BB135F -:109D4000ADE8FD01FC85FB8177C80FF83DBAD8BFAF -:109D5000223A4EEBC897AA489E56C7DCF406E6DBCB -:109D6000D71CD219F7B7935F417BF9EE781BF9D373 -:109D7000E6F1E37A46CA5D9358C75641F7617EF72C -:109D8000D13B60FC448F8DEAF14399BBE79D30DF06 -:109D90008449BA2B08F31DEAF0279E187EDE81FB6A -:109DA00093A9620D7B264DBB1F9FFFEE21B00BCE0A -:109DB000309EB27F73D9B489FD908F21CEC7AEE8B3 -:109DC000F39AE0D72B02AFBD825FCD42BE770B7F07 -:109DD000B253F893EDE84F6CC8E722B11EEE4F3650 -:109DE0000B7F12427F02ED5BC29FBC89FE04DA82C8 -:109DF000F1D9A3C96EDA35E14F2041A1F3048B9468 -:109E00007549BCCA7AE80ABFC626C728FC1A1D9B3A -:109E1000A4F49798D315D87D364B81AF3ADDD7E0BF -:109E2000A754BF32FCF870839F2A51E0218726286F -:109E3000F757B8A729FD538A6628FDE5AED94A3FF2 -:109E400013FB6185FC775618BD56A73C57EC3BC900 -:109E500078EADD329DF66D86BDA7BB22F5B690751A -:109E6000EC9399709F0CC217A759CE97A5F4531C79 -:109E700075C8E249C7F37BF5152087D0161F8238D5 -:109E80008D8A8F20D710F7167AC6511C08F1D26040 -:109E9000E2431BDF6F92FB56C30CFB4F13F2D5FD61 -:109EA000A9C20BEC4F8DE8DB455CD62BE9A2E23270 -:109EB000D02F8ABF1E8FB9692FCACDB60F214EC5CC -:109EC00038F7C39F53FC25E3B6AD9FFD9CE2DBADA5 -:109ED0001DFAE255F4A550E8ED9643594D2DA06FBB -:109EE0009B5335972035E94B91D497166137CB6A50 -:109EF000E8FA1071DF568B2706E3BFCD8797887984 -:109F000023EC08C5EB117604F34896A8F6A7A687BC -:109F1000FBB338B322C733D6D730DF20033CDC3065 -:109F2000BEC4004F308C9F6A806F308C9FA5F43781 -:109F3000C1BACF176F6F16F6418E2B347B7457273B -:109F4000F676C821D5BE324F8D72EEA1F9E85CB22B -:109F50009B5B8EAC10749CAFF0678F7CCE21A0739E -:109F6000FEB9F79798FD31FD410E4A0E9B5DF5CE87 -:109F700030FF249F18E6C311F395DA7545FF9A0E5A -:109F800073FE76B5CE5DC23EEF107EE66543FCA65D -:109F9000FF70FADD29203F5B5A4C945F6D393435F0 -:109FA00009E7DB7D760EE1DB74D844EF91ADFFE38A -:109FB000A46BF17D45899FC4A7F0BD2531B8CF7A48 -:109FC000A6C544F6AFD0E24972744277A37C7535DA -:109FD000AF945B08A092902EBBC10FD1B961614FC5 -:109FE000255DF61C7D8CE8BEEDF0E224A4FBD5EDEA -:109FF00026852E23DBD4787DC48944051EFA318F53 -:10A0000007C1EF2AF4BD10DE46BDC09D1115BE5C30 -:10A010001D7F91F1C076C1A76D824FDBA35C959D3A -:10A02000ED6B6C3B669D1FF95D854FFBF2BAD1A7C6 -:10A030007D79FD6D33F011EDEC99E326B2B3231C6D -:10A040008D7A6D27FC286E3519FC841A375C6ABE40 -:10A050007AACAFD8EF34D8C5AEEE9776B1447E3F38 -:10A0600025744DA7E763C37C10E72A0DF49471F4BF -:10A0700085F926CFA31BF8D7C5FDE179FCC67CFA8C -:10A08000BFFA62FDA5A582FCCDEA98B7843D7F8B1F -:10A09000ECF93BDF0B7BFE7D778A930E8EBFAC27FE -:10A0A000EAD1C10E3BCEE222EDB83C0F196A7D2702 -:10A0B0002632CEF70879DCE97E77E200E4672FFDEF -:10A0C0007F34DE794BC43B6F62BCD31BF78178BC15 -:10A0D00073C03D9BC73BA91A7D2F6649CC55666F5F -:10A0E0002772FABF3DCE9952A4C639E52E35CE91DE -:10A0F000FB07BB1D1A9DC39A98A7C63DBBF117ACC1 -:10A1000033D9B500BEC7B5DD3DEDBC763828F4FBCC -:10A1100080E0CF6BC20EBF22F2861D487FE24B99D2 -:10A12000E00BAF57149F76C5BA9CC89FF93C2FCB64 -:10A13000ABA17C7AA4F4EFBE5A1A7FF0CCACD3F872 -:10A140007EFF6E470CD55976233EB0848316EF69A7 -:10A15000FC7EC56EB7E65CD2495E3FA24DB50332C8 -:10A160004E9072B9BBF51392CB5DEDE7F7A7D27EA7 -:10A17000C971AFB1974A913E57B5328679C385EC24 -:10A180008FD12F5EE839C6F123CC8D7A677EC7F870 -:10A190001C4F7B50C7F3CF3BDB4249B85DE7091E3C -:10A1A000D0F13DF0E2B620E1BBCFAD39F44C1A5707 -:10A1B0008AE7A25F3BFBCE44BCBEEBB4D964A37D6F -:10A1C0002607E96DB1D0CF37CF9A625D445F9DF627 -:10A1D00039826D9FDC8FFAEAB7EBF4BEC8EEB38329 -:10A1E0009223E9B6EA4A9DECC9F6D13613D697B761 -:10A1F0009F368BF3D6418A1F76B467C562BBDD0DEF -:10A20000FA43F62244F47FEC4A07DDB713E6E3761F -:10A21000C249784839089E369575F6BD9DC7AEE4AB -:10A22000EFD18F38FBD718A4CFABA7F7C4A0BDDA06 -:10A23000D5C69F33E29E9618CC33DF6837C5F1BA96 -:10A24000CAE064BCDE3CE6DED841B8AE3613DFBF00 -:10A2500011718D7CDEEED1F3A89EBFBB8DE761BB93 -:10A260004FF3FAD1F6003FB7C6841D93E3B79F9E24 -:10A270003AB11FD60F02161A3F820556C4C3B8570B -:10A2800052B65E49E76BFCD52CD2EE953AD438A78E -:10A29000A4CDE09FBCD5A407920F07BF9D7A4D05C2 -:10A2A0009DAFE77672BC59B52FBB4E2F499E8ACF22 -:10A2B0008FE5CF67017EBFCCCFF0C71CF1DD95FAEB -:10A2C00031D74D2BC7F936F373662362557B767011 -:10A2D000D4ECDF2EC4F3FF9B62C8CF6EC7F5E3FC5E -:10A2E0008718D5CF76973D521A8F75EB56E6E271F7 -:10A2F0009C6AD74BCF6CDA1B0FE3DF59AF117DC7D8 -:10A30000E5A9EBDDE9CEFE35E6C1675A397D653D4D -:10A3100049EAE59ED6C41BC93E8D86BB818EEF946B -:10A32000BD4475EC5B03EA3C4337C628782F6C4983 -:10A3300034E46F6A7D1CE24D591F882D1F12CEDF59 -:10A340000ADB797D7DE80F53070701DFE2D1FCFCD2 -:10A35000BCB12E3EDE6C53E32C435DBCD0581737A6 -:10A36000FA73118F0D11FB1AE7C43FC2CFC97AC32C -:10A37000364B7086E712E2876166485DE85CAF376E -:10A38000A900E8FFB2882F87591B7E9606AAB2550E -:10A39000F78F6011710173F859F290707E3BFCB831 -:10A3A0009A0F141D51E512F2C7CF319F5C897B9A39 -:10A3B000A4077E7E2EE222E38CD531FD9B5A80AF2E -:10A3C000430F31B1DFF17FF6A25C357D26F73320F4 -:10A3D000F4E88EFBF38CE2EDE6CFAC24775BC6703D -:10A3E0003F25E314B94F730D6B5956AAE1B96CFBC5 -:10A3F000F216A0E7A68373D317C1FCEF7D44DB9D63 -:10A400006C4BA1FC3E7D83925F0E9575A823267F41 -:10A410005201C6EB3645AF657FD3912531F87D916A -:10A42000332113C969F38756867F1FA069878DF68C -:10A43000739A0E5B69BF65DB0EAE27B2EE2CE3FCB0 -:10A44000D7853DDF2FE2DE5745DCB24FC42D7B447C -:10A45000DC121471CB2E11B7EC1071CBCBC26F6E26 -:10A460003A22F4EF9E9800FF8E2DAFCB4A3C6FEE60 -:10A47000DD72D40C0BAEF968C89A20437FAEEAC9EE -:10A4800078A7AA27E35255FB31C691AE8C2FB5674A -:10A490002BFDA3D8954AFFD5ED830CF9C870433E38 -:10A4A0005262884726AA7A792822DFA5FC5ACD77FE -:10A4B000AF8DCC7733914F3C0FDCD6F230F171DBAE -:10A4C000F1AC84C8B8EC65A137DB8E73FFFCF28970 -:10A4D00053719DC56D27043FBE14FC6815718A2712 -:10A4E000CD7D7D7E0AE615A7AC78EEA32B7996F795 -:10A4F000CBFB4E043E8D8FF47F9F51D21886BFDE7A -:10A50000F2975CAA9F5CA47E2C8DE3E7DC366BD1CE -:10A51000F4FEFD85DE6BA9CBCF12E7926A07F07DD2 -:10A52000D1DAA1D86EB078D2F1FDA7CD9A6706DA5C -:10A5300071FF6FAC9DFE3D095FBE3CD7C49AD03F12 -:10A54000F023C9F0F39C6646F98A12E0D3CCEB43C2 -:10A55000FAD8315F87417AAC87E1BA36595813FA95 -:10A5600079E6664E4777C655089E73AA9F77398E5F -:10A57000D7427CFF18DC2B7DEF038F66E177B7B005 -:10A58000C57D329B9DBF7760C9F7DE9F5FC8BF67FF -:10A590009B3008E72DC9E6FBA841B2DF33C4BCA657 -:10A5A000981D3DC99F7665570D792EAB56DF473113 -:10A5B000CA4B93B0B32F677A6674F61D8C67F3F9B4 -:10A5C000B9906D5F4CD6F1B905F67837FF2EA45BD4 -:10A5D000C7F7C05EFE7242CCCC4EE42CD87FE6B307 -:10A5E000F911725010AAD5C5DFA930A9F52D531065 -:10A5F000F97D26D64A7A3D1C179C78EE7C234EA81E -:10A6000071DEB01635FF0FEFEF376878DEAC439E92 -:10A610009021C8FF83FC7B1A179227E3BEFD07F940 -:10A62000F2BCA4F72F788E584F88A5F3359B0EDA2D -:10A63000D7611C69ACF7BDFD1EB7E346FC9BDF9BF1 -:10A640009E8EF1D7E691D7A5A31E6F41034FDFF38E -:10A650005934DD1D09E3FA63D1DE33FE9D2D7FF50C -:10A66000743C2FB365BC8417F2F1A3F8F8F79F7B15 -:10A67000EB31FC1ED8961B453F7B808F97B0BF66A1 -:10A68000FA28ECB79808AE781EC6437F7B5FF707C1 -:10A69000246FF9EEC328A71B5077001ED5D7FD11F4 -:10A6A0005EFF00650CAEBFDDC77D24128EEFE33E7A -:10A6B00016096FEEF02F6DB191FBC7520EDF3E3CD5 -:10A6C00055F81DCEF72932AF29BEB83AFF9F859CB9 -:10A6D000BE21ECD501E13F5E13FEE315F41F940F9C -:10A6E00073FFD12CF68D770BFFB153E4BDE1BCCBEA -:10A6F00023E28B4A910FF33CAC606429CF7B1DB2FF -:10A70000CE9F61EE2C1F9A5CA0C68993F255BF3292 -:10A71000A1579222A7653DD20D7972B6214F56FD01 -:10A720004A8979B0214F1E6EC893D5BCB7B87582DF -:10A73000214F9EAA8CFF20DF29F6916E30E4CBB327 -:10A740009471613EAAFB36617ECDEE948F5B8A6781 -:10A75000DFFFBF8B8F9DEFD7FCFFC7C77F501F6305 -:10A760004DCAFE8DB17D53F8FFD785DFD82FE2802B -:10A7700057459D639F88E7F6201F7B635CE7127156 -:10A780001D3FC721EB202F8B3A549338C7B145ECBE -:10A79000BB6D1275A8A5C5DFF1731C6799E0E35B7B -:10A7A0009DF2B1DCA5C67913F3543E8E772619E2EB -:10A7B0003E35CE1BE350E3BC52BBCAC7516CB0213F -:10A7C000EE53F938B2ADC410F74D30F829F51C0737 -:10A7D000C405ABFA15E27B09EA798EC2907A9EC372 -:10A7E000E8DFE5FB8A326EE888137CEA3EF326F464 -:10A7F000A1B85F9466E5DFDB307B2FC7B843D2EBAF -:10A80000B7FDB83FDFF2979B889E85E8CF3BF1DF2D -:10A810001BFAF1B868433F5E97C0F723A30761793D -:10A82000D3CFE39F84490E7EAE8A85F0FB53E78940 -:10A830009B36F44B09C74B66472DC33842B799FC8A -:10A84000F8FD5DA6DBE9DCDDDB5DC451C7FA65CA56 -:10A85000EF9F6A38EF5FC4BC5AF16B14579DEAE76B -:10A860006EA4F94B5D6D5817DFFCA1D5558FF21C16 -:10A87000C5BF83628CB75EEF97CBFF7E8FA01F9E14 -:10A88000FFFF39FA4BFC502CF9DF16D57F6220010F -:10A89000F36C88E6F09BFD3E9E8EDF1794FEFAFD7A -:10A8A000E74F913FCD8DBD7C36E6CBDA1A7F22DFB4 -:10A8B000AF0C927E19E3B62EE35F439C7624CFFD66 -:10A8C00006AEEB1BE19773F1935283BABE7F43B49C -:10A8D000E736FE3D18B78ECF957492FDFB04DF5F1F -:10A8E00017F375D045CA157E9F2631E23D5803FE09 -:10A8F000925E2B0EEE0DE111C64B5D8F5C4727F289 -:10A90000E3B940DCFD4D67F2C326B9C47BBA9DC7ED -:10A910007D16114746F27F38AD2B20D7CFC60CC22B -:10A92000F75FE47BEBDC1ECA7766121D0D8E4CD000 -:10A93000A39B0EE974CE81897D7073073F8B35F43C -:10A9400033E6B11A4B8AA8BB1AF7138DF503E3B9A6 -:10A95000B2E2D6CB15F8AAD3EAB932F7D9BEE7F5F9 -:10A960002BA3634718FC52A9C16F4D34F8B5690693 -:10A97000BFA7D6C5CDCC2CBF3324F6EB35277E7FC1 -:10A98000C7CC2914D92FBE03C4E9BDAC0BFD95E794 -:10A99000674FF57312DD3BF4632D7372FEF995F783 -:10A9A0004CF4582FF1F9A121D28FB928EFB50687C1 -:10A9B000D1F73CAD2EF5EF33047CF68F46E7E07B14 -:10A9C000368CDAA77C8E8F46D3FB38A9D43EE17350 -:10A9D000D2F535BE3C6A1FF3B9E8FAA3BE226A1F5E -:10A9E000F6B9A96DF09551FB80CF43E356F92A09DA -:10A9F0005EE9F3529B05E10DFEBD812C3F7301C65C -:10AA00002C7B253C2F82CE997EC023828E57D43951 -:10AA100014B8676DAA323E7DBE53E94FF3E629FDB7 -:10AA20009755BA1438C553A48C4F2A732B703777B7 -:10AA300099323ECEE551E098BC4A657C94D3ABF4A4 -:10AA4000EFB96A7842CB79F4B9C1E73E8A7458E528 -:10AA5000F31CE5742A3BCAE95349ED2DFDBB117F78 -:10AA60001DE64637FA6D47BE83E1F976AB9DBFF729 -:10AA7000DDCDECD0BA45CCDFCD0DF329F8C27C4A50 -:10AA80003E17E0E789F33C4755BC2B95FB4007C9CF -:10AA90004FCA38668CDE230EF3B1FB2D8E3F0F06B6 -:10AAA0003CEE1BA3337C6FE5E0E8695417C12D4CE5 -:10AAB000D6891DFD4CC4A731FDED942F4E7954A3CA -:10AAC000FC0E56528E75C4B987B25D917F0F4AB69F -:10AAD0006FFF8A7F6F2866CF3627D6C5A614CF4C66 -:10AAE0008A8AC8FFA604BF1F9D46F30D1C12057875 -:10AAF0004C5933D33A3B3FBC3E396EEEA36A3C1A05 -:10AB000096FF805DC4E3B44E699F5639D6D1F555A2 -:10AB100079E7DFB73929D6F58588D73E13F1DAA76B -:10AB200022EEFE58C4DDC744DC7D44C4DD1F89B875 -:10AB3000FBB088BBDF17F1DA2111AFBD23E2EE15C0 -:10AB400022EE5E95B78EFEAED5998D1AD3CF73BE29 -:10AB500074C17A759DF3D7AAFB86731F55E3EE394E -:10AB60000FA8F1DAAC656ADC7D739D1AAFDD58ABD6 -:10AB7000C66B33E6ABF6F17A6FA9025F57A9D6E54B -:10AB8000AEF5A8FB86924FD3CA543B694B55E3B54B -:10AB9000AED6BB35385EC7BF4382CCFC34C21F463D -:10ABA0007C0F5E39EF58E07097E27E4D21F32CC5A3 -:10ABB000FD9C91A6D0BBB8DFC4DED7E93B904D78B1 -:10ABC000C730D0D73343264D7146F81DBF4AD7AAA8 -:10ABD000236A7DE4863BD438B8A25ACD67AC656A57 -:10ABE0001CECEEA1EEC74E33F81D26FCA195FFCE5E -:10ABF000467BCEEF874C31D5F4BED2A5FA232B335A -:10AC00009E1FE3FE889E9BA5F4933F320FE0E7244E -:10AC10008688F714EAA386BE89FB777B3EE4EF17AC -:10AC200000D943BDE0FEAB18A7B7D53E8EBE1FB717 -:10AC3000D3C2DF1BD89D16EB5A025D579DE5EF0787 -:10AC4000B076339D1FF3E27B235938AF7A7EAC3068 -:10AC50006456CE97590DFD97A14F3C2F3EFC1CDD4D -:10AC6000FF1C3EE21CC7003680CE47B474FEBE41D6 -:10AC7000471C679053697F0A823C3E2AE8323EAA0D -:10AC8000A2EF8C99DF67F49EBDCDD476E2197C3FAC -:10AC9000EA735E871DC5D4BCED9A496ADE36C6717B -:10ACA000FEBC6DBC5395D78979AA1D2877A976E09B -:10ACB0009CB8A6859F43EC2AAEF10CC892EFE91030 -:10ACC0007DA272F6C5F07D4C2E3F23C43A1FB27AA6 -:10ACD000E8FD95653D19F16984839F57ACC77D1BDD -:10ACE0003CFFF71E7FEFC5CC3C4903B03D3E569C70 -:10ACF0005F9CE4A2F95A39BF8AE0DF4F59E79E4FC3 -:10AD0000B485CCCA7737CC2C82BFD03F07E5AB30B7 -:10AD10002C47FF7BF012E728A59CC5265E60FFCE7E -:10AD2000AFC481B21D1572EBB88E571C7C1FF59510 -:10AD3000506D08BF13F95D2AAF53DCDB63AA997F1E -:10AD4000B7C51D3B06F83256ACBF48EC936DF1B168 -:10AD500010C6739B7C766AE5FEE78AD4C549E8375E -:10AD6000B76478D3F15CE096946ECB18D8E9CD96B1 -:10AD70006E3D3A7B8FA0D93294FCEC96E63433C614 -:10AD8000A1A3CC0E33DE37AAC72C1DEBB1E3F07DB7 -:10AD900093648419EDD36DF20543A3E95CA897CEC3 -:10ADA00011C13A4A318E1DED98497FEFB1F93DFC52 -:10ADB0009B4A181F77ABC2FBF6A5F0F3D736073FC7 -:10ADC000DF3A36791EF1ABC0C5BFDF57D023D615A9 -:10ADD000C0E952F9777CE6C33FCE17EE2740EF95E6 -:10ADE000EFFB0C651130F2CB00AF31F2C7702E7162 -:10ADF000C561717EAEA5F37D9BBF8AB8628BA83B0F -:10AE00001C1171C54722AE3828E28A15863AD0BB9C -:10AE100022AED827EA40AF8A7ADE7E51CF7B5DC46E -:10AE200015F2FCB5948BD495CC694B60ECAD999C34 -:10AE3000CE692BB54019ACA3740E8753EBF8FEE82E -:10AE400015DE064F4901F65B5CE3601DA9950D63B5 -:10AE5000701D69556DF49E52A5D7EA746BF87ED2C9 -:10AE600013F45E947C2FEC164E1A76D39CB1647F5B -:10AE70006FF18A73C77A6B21C9D7A316FA4E92FC79 -:10AE80007E5CE51CF57B4AB30CF4BDC9005B356EF6 -:10AE9000475E93741FCC0647D23D4D8C8DBA459CBE -:10AEA000E7C597AE3AD1973582EE922ECD574D88B1 -:10AEB000E3EBE0FBA13631CFA1E21BE2709EF77A13 -:10AEC000F0F9A60A7D30CEB74ACE27DEA78916FC58 -:10AED0007FA8EFF9CF9DBEED63CA39D3B7057F3A9E -:10AEE000E62DB9DF82DFD3AE0CDED713F525FC5E8D -:10AEF0008D3B8EBFBF32E9CF99C0A755E23D0469B3 -:10AF000057AF13FA6B7CDE7BBEF3BFBFF35EC90C99 -:10AF10000B7E0FFDDAE02FF8DF0336D7A6469EF74B -:10AF20007D0FF1035B79EFB53FA3BF2319CAE0F2B0 -:10AF300060BBC6E6C4EF0C5ED1C3BD1CE998DAC3A2 -:10AF40003546D447C99FD9043EA698B55A0A8E1FE4 -:10AF5000AE91DED65F3581CEFF5D770D3F27F1FFE5 -:10AF60000010785941008000000000001F8B08008D -:10AF700000000000000BED7D0B5854D7B9E8DA3320 -:10AF80007B1EC0A0838A1912B003A819531F230F78 -:10AF9000051C70A39812436410548C8803A2D0D669 -:10AFA0001892A6B7F4D4731804110951D3A63DDA48 -:10AFB000F818CDA3BDB9DE9698DCA64D73CE21C698 -:10AFC000A4696F12B1471BED6D0DBE92F46BBF1EED -:10AFD0006DD236A7ED77BCFFFFAFB566F6DE0C6825 -:10AFE00052D3263D852FD9AEBDDEFF63FDCFB5B967 -:10AFF00072057EE633E6606A78C8C7F0C77245819D -:10B00000FF4798579D83EFF18DA19E5DC9C4FFB79F -:10B01000B26032BC0F7EEA176C266335ACD53F00B8 -:10B02000EF7BF3B454F774A8AEB35D187232E683C5 -:10B03000DF2B59D047CC239F354CA57A39DE920AB5 -:10B04000682FC767349FA17E6B0FF33AC642E14F6A -:10B05000B0BA89D05FD46D55234E9CAF37F839A76D -:10B06000E6622C2BDDD2E080F554666C5ECD264086 -:10B07000832A877B0AF60F2CFA796E1E3C7DEBBD86 -:10B08000B83D6CD70CED4E4DEBCEF04E8FAD6BEB6B -:10B090003656128279B666FC0FCFFA646CF7BBF6AF -:10B0A00010B6B3B1DA7E18BF77C12FD3335DB1F6D6 -:10B0B0008766954EF3E7C380E5A98CA53136D51E8A -:10B0C000CAF24F1FBE5FC6C28C41938E9244C660C7 -:10B0D0001DE71B948803D655DB07F01B83F5975AB1 -:10B0E000F07D439FC3DB8B0B649AEB0ED8E77ABEEF -:10B0F0004DD630A52B7F009EEBFB9A2BA8FD2EDBB7 -:10B10000398497137E11BE19ADEAB928BCB03DD37E -:10B1100095711E53D98E73C07A17F89327BCF949DD -:10B12000F8772ECBBD62E5F847F8D68AB6090DD57B -:10B130006319E2D303C02C1CBEAF95EF59D9C07878 -:10B140004604C3F263EF4F37652786B01FD28D5395 -:10B15000D0D52CF8BF9779ED7310FF9CAE6A045DD3 -:10B1600079197B9EE82A6C0B47D709FB62F7D962F5 -:10B17000749765188FE17A97EBCBD45F3B3919D67A -:10B18000BF9AD15C6C75A085C3EB3E4E8F4E78297B -:10B19000C689D11B8C1334D11FE16BA258278CB305 -:10B1A000ACACECFFFC1060F6E8CEAC3B104FCBFE35 -:10B1B000D1CAAC305F3534C37275AD12894079792C -:10B1C000E056E287E5FAF1E17D4D8DED821E3F6F9D -:10B1D0006CCAA671D694F371D826DDFCB4BE9D046A -:10B1E000CF20635BDC3A7A7B33934D6600C7E77709 -:10B1F00037EFC3FE171F7430A423867DE720DE39A6 -:10B200005C4F02ED22FDBFB54D891C84755FD8ED02 -:10B21000A075BEB94E8930C43F733F3E00EFBBFD01 -:10B22000294497171342FBBE08F58D5B93FC61D848 -:10B230006FCFB8D68D4198F7624AA81EC769DCFA6D -:10B24000494B18DAF724869D59386EA3D57F10A68E -:10B2500058A9024CC7C113FE7D133C1B7A74F883B6 -:10B26000FF8EF9151A7F898585FA5DC3E9C7319B81 -:10B27000D723C01DBAF52FC9B2D07A4F3DE4A0F54F -:10B2800026CCF6123C1A0A12B484318847A6A93992 -:10B29000B09E746D12AEF38202FC09F4767E9912B0 -:10B2A00046F83095E3C57ED38D07909F1E15FBBCF5 -:10B2B000F0C0DC4948CFE75378FD394F6204F77599 -:10B2C000CECBCB618F2BF218F2861AF22D4FE6FB14 -:10B2D00050800E1AC5BA1ABD162D01F0DBF8D08ABF -:10B2E000CF229E1B3D7DF7E0F36472385981FE6FDB -:10B2F000EDB6328437C2C39983F545CD586F86CBFE -:10B30000257F16ED07E1371EE0F6E6AECEE410EC41 -:10B3100083B959C83E310687869DCF7C419949FC47 -:10B320001CE6FCCEF94461BAF318E877A5D71E2EC7 -:10B330008771D8D1C944B72BDD9C6EED855B52B3C4 -:10B34000783357943EBC54EEC3F3BD51941B906EBA -:10B3500001AE2B915F66223CC6CD1980F7B54D46F4 -:10B36000BADD3261F303D5B0CF7505366685FA755F -:10B370001ED5C037556D463E827D1BCA636633DAE3 -:10B3800077CF38419FDD9C3E81D2270567C4E862B4 -:10B3900097DF42ED7075B651E06F86EBC70D0EE793 -:10B3A000905E41DE9CCFF0EE2B24B900F4C3D7C5EC -:10B3B000AC3A7E68E87110DD33200F8413D0A7BD4E -:10B3C0006A468C5E247C1A7675103D3608BA6BECA2 -:10B3D00003FA19A3A32313BC70CFAA9C273B46678B -:10B3E000541F87CEBEE767C44792FF1A58B09E59D4 -:10B3F00087F3B57C129E8B109F9FA90DA7E3286150 -:10B40000EABFA3A4682CD1BBC007173DF4E344BC3A -:10B41000254BFC84D9093CCF5DA2D2DDA69C2E032E -:10B42000796315E7AC5D1B8C0CC0FB94362BBD47D4 -:10B43000F9A2427B9C9621C29F9BFBEDA9504E1026 -:10B440006597C0ABD5EA4A43782533A3DE338E999E -:10B45000E4899FE355CAD99D369686E7718238DF25 -:10B460009B17652BD86EA7A2907E602F33D281D513 -:10B470002407BCB32DE2BC0BCB738FE4ADDDC9F761 -:10B480009B906621BEF86D3A085425060FBBD8FF85 -:10B49000B8016FFF00D4D77B9CFE0894C73337C92F -:10B4A0008752986940376F4D45121BD0E179917BE7 -:10B4B000BCA1FC29CF4D86F6B779B30DF5B7FB3E9D -:10B4C00069A8BFC39F6B28DB994EAEE33A8738DC8F -:10B4D000ED02CEBA7A299707118FD5621F3BEC2176 -:10B4E0004F10CEE16ACF7A92CF1D259FF10CC13E5D -:10B4F0001C1ECE7F76D42761DC84294D6ED2238436 -:10B500007C2E805FC443270E9216A333BB09CE6600 -:10B51000FE33EB930DB385DE730BBB85F41ED7B8FA -:10B52000B8FA8D597F031961417A4D14F85A647540 -:10B5300091DCD85A03FA9C82FAE552AE2FF9EE2636 -:10B54000BC06453B16B690DEBA5CEC5FEA5FAFB571 -:10B5500033367033C06301D7B396175CAA41FA340F -:10B56000CFDF2BDAC97262C1014D8B234FDB057D22 -:10B57000250578FD722753510EC9FAB090B7CB85D7 -:10B58000DC5E027C8C745B894F9DDEDA27C6E98B1A -:10B59000D22B1BCCD1F3E9214545382488E2011692 -:10B5A000EA9B9D8A700E5323AB2BC888BFFF04D043 -:10B5B0009D437A0CFD94CE6EDAFB79A05F474DB2C5 -:10B5C0001F6D0B87D6F0D857017E8935497E8B37A2 -:10B5D00046EF64774079828FD37B6DBAD34FD561C4 -:10B5E000EDC4E43931BDAC46E877A9AC95F8609874 -:10B5F0001DE3E47439B21DC3CF1F399F439CFFCCB8 -:10B60000BAC94F7417E4E7BE057E91EE96D51AE9E4 -:10B610006A4568743AFB96A4B3B96C2ED159680395 -:10B62000D18543B4D93109E885C389E82351C2578C -:10B63000E8DB36950DA880A763887F58A4CBC69217 -:10B64000719F83DA0BC417833E66D3D3413060D534 -:10B65000223A3C0E16B24437C897411BCB7810DA19 -:10B660008DD1562C76C3FE064B1DC90D74A8460C11 -:10B670007AFB3118F7AC8B8DA8EF9BF9612AFC039C -:10B68000E5C0D68C373DB89EAD3646E73D0B5FAA88 -:10B69000D5A0BC5D96D92F6A4B61DCED09B2FCEEFA -:10B6A0002EAC7F3C91972F3FF9A75D241F805E1140 -:10B6B0001F49021F49527F9FAE832BE0C13921876A -:10B6C000CE19A709DE66BD5ECA09F3396C9EF74D37 -:10B6D000139E46DAF7B0F50269DE323A5FFCC76CBA -:10B6E0009297AD06BE183ECE00E9EFABC4BE2D4921 -:10B6F000CF6584E2D89151F86FB0FD4A6F2F009C5E -:10B70000BFABA0DEAB41EF398C8B0E18472978E92F -:10B710003F51FE2BBBC2E3108E56688072DEC642DC -:10B72000B41EC9AF0948075684FB00D583FC1D52DF -:10B73000B271903A37C24581F6571029D77A4E96A2 -:10B7400073B9B6529C7F9538258C57D9C34AD13EE0 -:10B750004F58B7F6E03694739A03350A787FA914E8 -:10B76000D707F59A839E9734C41BD0B341EE3C5F54 -:10B77000F287B71F817EDD8356BF03C6ED0E3CCB3B -:10B7800050EF7E673AF3E3A6BBB021ACAF3EE45E78 -:10B7900064F722DF0C9CEA9AC2D8D9763658661B29 -:10B7A000BEDEC12309762F6C36144E99F9348CD342 -:10B7B00053E070A33EF7C626AB1DF134B8B9218C17 -:10B7C000C0389D16EE57E07D8F1A6268DFDB377553 -:10B7D0002E42BE3B6D0BFBC7C1B36773F82EB4435B -:10B7E000346F457926ACFF608F5A1E89733E6FC84F -:10B7F0005188DF5E7BFED3B4FF6369767F028C3BAA -:10B8000084FE0DC0DF31DBCE0C3F8EDBF1950C1CCE -:10B81000FFD8BAADFE23B0AE631D0EB4A4D8B1DD1F -:10B82000CE5A1CF75871B367BD6E7CE74DF6567C57 -:10B830003F78A3DD9E4DFBB99CECC1FD6CCA1D8F0A -:10B84000B4D99D669FB416EBD73733DCAFDDB3D3E5 -:10B8500086FB73AA6C179E2F9FF05C7A752EDA4BCD -:10B860005ECB9C4F41FBCFFB43B7E6001E57B69D16 -:10B870005D8472C95E96B2059FDD629DF2BC92F84E -:10B880001D4A6B74E239D6DDB496FB613C9606C264 -:10B89000639A2588E75177609D73EA74FEBE79CC80 -:10B8A00070B874A3DF6516AE73BD67FD0C6CF7BB93 -:10B8B000F610B41B2A76D4C68363630E9763CECE8C -:10B8C000E6AC365877F76EA71BE1D3AD847635002A -:10B8D0005CC3992EFF63DEE1FDBE25FA49FA003C08 -:10B8E000111F6E387CC3EEB08AFA2AC723C0C5691F -:10B8F000D3C9CD43B34A9B111E51789BE74DEB262C -:10B9000079D1AD70BEFED6E159BBC3509EE90FDDC3 -:10B910008DFD8EF500AFCDA27D4E427D7F24FE19B8 -:10B9200012F5DD1DB0EF38FC3FD46465378FE5CFED -:10B930001BE03975B3759212073E43C56BB3D04F08 -:10B94000750CEA2D30CED06E277FC2FB2CA4AF1130 -:10B95000E873560E97F7BE99C12D39687F4DF7935E -:10B960009FEFE5D9C1AD39A407B47AB0FC31A0DFAF -:10B970007D1F11FA65EC46A4D7E9BBC3609232F78C -:10B980003883DE3AD2F91964432A9EC71D257F68A1 -:10B99000417BA07786DDEBD0F905A51EBDC4C7E5C8 -:10B9A0005B70CA853C38B959F5F4F564DF80BE4C4C -:10B9B000FE4137FCC6F30F06D11FA893874B4C6599 -:10B9C000A99FBE94037211CF7DA127A77B7706178D -:10B9D000A0FDF18AD51F01B86560072857552811C9 -:10B9E000D4D73B4A9E203D9E093D6E8958E74FDBE8 -:10B9F0009DAC6C0A8BDA732BC5FBA496B38FA27D2A -:10BA00009D84FE4FF4D7B638BCE47F41E4C3FCD537 -:10BA1000627FD2AE233D12F6B3B245F841D9835CC2 -:10BA2000DE5803F9480FB00F835D1264263BA4C9AA -:10BA300066B0E75699F407B3DD506DD21B76A0EEE1 -:10BA4000847AA1DAEF447A7A777ACEB12C2F5587AF -:10BA500007A47E0FED420527B60CE9CE9F1342FEE8 -:10BA6000FCB85D3B8DF2684BF011E710FAADD5885C -:10BA700013E5496FF9E79291EE7AEBACE5486F83F5 -:10BA8000EDE5D4EEB5F6203DAF08B951E1D77E4FD4 -:10BA90007C29F4B3EAF2D2D35D3ABC5669B79DEE85 -:10BAA000D2ADBFB2A0CA5096F4556965ADFD71CE56 -:10BAB0009759B9D2EFA231833E6A3DE40FC5392FC1 -:10BAC000E43391A9EFEAE1989C2BE846E853F74F5D -:10BAD0005F3076347D46EE53C247EE5FD68FB4DEDC -:10BAE000DFE55C9FF566BFCFF59AD719C5D308EDA2 -:10BAF0002BF1108373E077873B56A25CA8F0877226 -:10BB000073010FD565CA96F140273F16FECA1F077D -:10BB100092236158CF8B3EEEFF4C6CE17665625903 -:10BB2000D5223C9FDE2FBEEF2C50883F6B024A444B -:10BB3000837FDE2AECD59FFA18C51F805F5F4D8694 -:10BB4000F2EBC536EE47665AC51D7362766A621D12 -:10BB50008F4FECB033FF00F69BE6F26F86F7CB25F4 -:10BB6000FFD51AE310353536C33953698A3B249A19 -:10BB7000CE99A512EE7300EED931B88F647F8C4454 -:10BB8000274CBD94877E31337C369AE063B6772AA2 -:10BB90009F33F1C735DA3D077BF25E9C807A469988 -:10BBA000E29F82F8C32AE897A83D49E1905EC94721 -:10BBB000C2DE93F1AA1D4BABC9DE7B0DF581B1143A -:10BBC0006F9A84FE6A39BEB4F366FAB5FB725347C6 -:10BBD0005EC709D16F6B557C3DE104EA09B3F8F308 -:10BBE00006784E5DBA30239E9E70A250E809508FB1 -:10BBF000FAC189DDE5FC5968D4135879EE55E0D2D5 -:10BC000041FB4D989237361EDF1D9B157A30570742 -:10BC1000F7245F2B2BD3C17DFD6CEDCBB8DF2AE180 -:10BC20008790F3817C3FAAD7C3CCF33D95E316F60A -:10BC3000C6789217F27935FCA9EE56867476BF4D18 -:10BC4000AB457DCFEC4F3A9CCBF5C49E2CAD05EBBC -:10BC5000992BE72AE376487FB56FF6441E7E20BF16 -:10BC60008FC91E94F6D301ACCC8FD985AA9BDB85F6 -:10BC700089E9978EBAA1AA3937F40CC2A3F85224E5 -:10BC80006C01BE735428A43F39D219E93DD76C87A3 -:10BC90005D63BB1E646AA0E7AD8DDC1F5F3A5BA5E8 -:10BCA0007262C87A90CE05931F2751BB4C76D8128A -:10BCB000D00384DF86F4A953429F0AB256B2F75CE0 -:10BCC000B68813FD1566BF4D6DBA65602AC8F5DAF2 -:10BCD000824B35DE99D4DFE0F7A9F5661D4D15F5E9 -:10BCE0006E782E09723FD072F403E1F835919E2CE4 -:10BCF0008CC3F955BFC6B89D87FAC58AB55F98F160 -:10BD000035EFF5F30349FF92D417A53E03F2A5677B -:10BD10003CE265A1E225DBDFE42732FB85A45FC6B8 -:10BD2000EC3F32FB8BDECBCD247C48FD4BFA7F7E93 -:10BD30009F6BD4C3FE0BD803DBF516C2910AFCDD62 -:10BD40006B63193BA773FF0EEA4BC74A7FE046FDC2 -:10BD5000E2BF4CFDAEF57CEB8673E83C9EAB2F2436 -:10BD6000D850DF0E7A42E44F5CA218F9242D4FF828 -:10BD70001BF35C7C1E1147EE6E6F93FDC3286F8230 -:10BD8000E9F64882121B8715E45F133F8D9DADA530 -:10BD9000E6E5933D72431ED2B31FEC9119688F08FC -:10BDA000BE2F48A5FD302D959DD7C78DC5BAA3EBF5 -:10BDB0007082DD32E3FDCF3F218F19E6B91ADC76C0 -:10BDC000941439EDE88F001C5B395DB9A3FEFB2CA0 -:10BDD000F4EB6CF0EAF58A7A8C5BE4A2DEC9E31A34 -:10BDE000F2BDCE7FAE22FD26A687B4609C73F5CE51 -:10BDF000BC689C8CE2A751FFBB8F51BC488EA3321C -:10BE00004F07F101F2AA5C8F358E9F5EACB749F007 -:10BE10000100DCE9009259BBD3CA785E02E713192E -:10BE20008F500B83E599B0DFB5DB148A1BB370ED3F -:10BE300051D4EFD7897ABBF0BF99E348EB441C8615 -:10BE40005937909ED6F49031BED6D8672C9BF572A8 -:10BE5000E9EF576191B8EE7F403C713844ACA3C321 -:10BE6000E100EDF36F140E920E2B723FEBC1BC9606 -:10BE7000EE84D0AE068C6BEF75923F846C48E497ED -:10BE800001F885FD6CDB53F008EE675B9E95E0D70B -:10BE9000ADF03C97A3695F730EE9E86D9BE0F35B3F -:10BEA000F2BCDCEF82E7128844963E81F848E6B5A2 -:10BEB0001C4BE37AA53DC0F5C643938F2CE5715723 -:10BEC0009EDFE20BC4F25B4A013E33047C7C539A52 -:10BED000FC03F09C116826784C7FDA68AFDEEE3305 -:10BEE000EA953EB3BD6A2AEFCD8B9FD7128BB3097B -:10BEF000BFBB58BF99AFBED9CEE32D4F80DD8ACFEF -:10BF000043ED6E7A7EABDD43CFFE762FE96987DBAA -:10BF10007DF49470BFDF16ACC7B896F4434AFFF8BF -:10BF2000F7F3B8FDC6027C1D95622F8BACE9C908FA -:10BF3000E7E301AE178E74BE54971BFDA0CB82C6FB -:10BF4000F8DE8A5A637CEFEE99DA73785E26CDF4D8 -:10BF5000D842BA78D43AB1FF1D5FE3F12639FEF139 -:10BF60007FE47897E58B62FFAF0ABA483A9266F3AE -:10BF700002B2AA1EAABA15FDF6CC9D734DFAE0498D -:10BF8000C197499BDD36F40B550DACB4E338EB7625 -:10BF9000C138AE6B1F676BC6C40C637CE1EE3BB16E -:10BFA000FFF1687C61E39DA5507F5CC417DE7EBA1B -:10BFB000F5EB6117D2ABF673941FD63CED0CC2E3E0 -:10BFC0006D719E437908DFCB32FCBC9C3271543FCB -:10BFD000FEDB79F9C3FDF8D6854A6BBCBC96CB79FC -:10BFE000513FDAAF496E39A37EB44BBCCCE5919A90 -:10BFF000CFE7EFFC296BC1713A9F652D87E3E8F32A -:10C000007FCC53E478EFE591FD2FE560F00FF1C6AA -:10C01000B33AAA2621BC2FDA785E8C793C35DF2E24 -:10C02000C7B3E463FFF4E8FAD47CDD783B00068311 -:10C030008827D59D4C714D7617C53F251D25D5BB4D -:10C04000EFC0BC05302C199E2F49DF71DF91877E30 -:10C050009C9F64FB1F6323E3F51782BEDE12FC7511 -:10C0600011F90BF8E8BCE0AFB3C85FF03C23F8EB84 -:10C0700067ED7E2AFFB4BD80CAA7DA352AFFA4BDCA -:10C080009C9E27DA83F4FEC7EDB554EE6E0FD1F314 -:10C0900078D923B7E2B9F3DB6F2A248F475ACF67E9 -:10C0A0001EB51AF8A7654F9281DFD63F34DE506E79 -:10C0B000EA33C6CF1BBBB20DE5356DC6F8F9EA56BB -:10C0C00063FC7C55CB3CC37C2B430B4DFC7CBB8978 -:10C0D000DFAB0D652D9FEB89D5E5AB0CFD1C9E46B6 -:10C0E00043BBA4A52C140FFFE5F99C3E8F94148D3F -:10C0F0001D1AC5CF616FBBFDE7A89F44CB6A88A11D -:10C100003E6F6F5B42EFEF4FE0E79DB95F7D3E3FD3 -:10C11000EFBACB9A820B18EA458BAD7ABDE7D3B361 -:10C12000424BF375F6A0DDC3EDB17726D7583D40FD -:10C13000474BCB2EBF7803D051689091DDA381BAD5 -:10C14000E7013DB8A0F5C1853740B9267C8FC17E97 -:10C150002C6A79F205605F16283BDE3901FAFB672D -:10C1600087EA71FC12CFA517B0FF828AD92A92F50F -:10C17000FD298CF4D18B19F6C8C138F4706FBE62FA -:10C18000885FBDDF73DA1CA7CFF2B152F42367F9E1 -:10C190002E95A25C83B286F1AF43B342F7229FC1D2 -:10C1A0007B0DE5E4FD33D667E1793252DCE86B02C2 -:10C1B0005FD29F20D7B5A384AFE7B8882F0C99E250 -:10C1C0000B3A7FC23FE58FE24FB828FA0D7D35BEAE -:10C1D0003FE1A2883B5C947187AF55C78D3B5C5CA7 -:10C1E00024FC09508F7E848BBB6BF973D1E87107F7 -:10C1F000B93F388F1EA2F3271A77107ABEF09B1F23 -:10C200009BA5FD33D6AF9FADEDC2E76F6668BB114E -:10C21000CFC775F14FF7445DFCB3EC0786F8E753E1 -:10C2200039A103F93C6ECDD0AEEA0CB3A1846C8C7D -:10C23000C70637C6A3E3FF9D2FF5EB813F2B3EAB2F -:10C240008BA35AAE7C925D731CE09ADB15F0BC1494 -:10C25000B37E9384101917D3FB9EC80B1D417875CC -:10C26000A57CC7CBF3AF2CB1F30385DF08FA907937 -:10C270003E391ECA2B945B278063F09CD99E72A91D -:10C280000EED94410137F3F3DFF3DD029EEE0988F2 -:10C29000DF27F2823F267C3FDDEFA5BC36F1FE5A58 -:10C2A000D7F1B83DF873D463BB1BADDE835C6F2759 -:10C2B000BFC5CD819448AF2E1EFC6B3C2FF3D1FF40 -:10C2C0003834D90EF8EE0CBDE0C27CF037F6A898F1 -:10C2D00011C3BE911CB621FE6B7DFC7C5BE0097D29 -:10C2E0006268143E077A186FF1D03A2C96023E2B02 -:10C2F0007F86157C9ADB0FEE7937D50BE37D632FB4 -:10C300008F7FDDBCB7C9D9A81B3F6B0E3F77BA91B1 -:10C3100066F2303EA9443051BD3670F9D5B9185F88 -:10C32000F15AC8CFF1C6A6DF9E5C817E47CD4A7E1A -:10C33000C73736BD43E5535E4B2EA2EF0DCF6F4E90 -:10C3400062FB9BFF71DD446EB77078ACD994FB78CB -:10C350006F26C5C59439008753DA3BC9D9D363F139 -:10C36000B3350A0BC6D363D2E670BC2DD65AEFC4E0 -:10C37000752D0E3918E6399F6AD8FA732C7FA354AD -:10C38000F15AD1AEF7F1796AF7A8944F0BF0D98042 -:10C39000E557FC490CE75D107A52C5F6BF9BA1B08A -:10C3A0001B94EB0857ED9D54E4C33790FEE2ACFFBD -:10C3B000D7F2DC147C345505BECF41F81F75E9FD7A -:10C3C00094929EBE94A765CF21BF5FA825487AEEC0 -:10C3D000D2ABE8A79B799EF6372FA9187B487CB48F -:10C3E000F546F42F0D5BE708EBCB9BC3E5E46F0448 -:10C3F0005FDCBC577DF536A4E74D36CA43B8252F20 -:10C400003807F115B5B7AEF3B921F3D7060BF87DB0 -:10C410000450A7691E58AF4F8575242889FE30E760 -:10C420002BF2CF39C5F907EDB4B1D06E0DEB1F403B -:10C430003F1F53B59D56F41F16DAC83E5EB1DA961B -:10C440008C7889C5CBFC067BC3FC3C8FF131CAD309 -:10C4500070D27310EC6C8C97E00F68E250A90ABDA3 -:10C460007FC6C31AFCF37191577A6FC16D0F8703B2 -:10C4700060675878795DC16D376D862D9D9FD47A40 -:10C480007219ECABF741C5DFE1C5E7815D8D78BF7F -:10C49000A24DF19743D3FA8169F518626CEE719061 -:10C4A0008E7F6EDB176E457A7DC7C3DC48CF2BD2FB -:10C4B000383DAF3DC12216287FAAEF418A7B064F47 -:10C4C000A894B726E3B267D2785CF6CBED03B46EDE -:10C4D000B46B17CDE12636FE8CF3C33AD08F5AA643 -:10C4E00052BC743C7377E3F992A86596727DDA6D5D -:10C4F000A7384F05635F473F4F1BB79B0B455EA4B3 -:10C500008C63B10BDCBE6D815F9427E3CB8DF6713C -:10C51000BEC9FE95F2CD1C6F01FA0FE3FB8E3946C2 -:10C52000FB7824BFBD7C3E0D7A04EEEF3B228EFBF0 -:10C530005DD0D7319EF92CE8EBF87C0EF4757CFFCA -:10C54000AFA0AFE37300F4757C1E017D1D9F4741D2 -:10C550005FC7E74BA0AFE3F365D0D7B1DF8F405F94 -:10C56000C7E72BA0AFE3FBA78BF9F9D73DC51ED9D1 -:10C570000CEBEDB6B19F215D854B455C58C4C9B647 -:10C58000A54CA5F3DDF927A072D0A70695D06710BA -:10C590001FE10C27B51B4CBEF4C7FFC0F2B64CB26E -:10C5A0004398EAFDEE10F4EBFA62A6BF178A3D76D7 -:10C5B00046F2FEEC71E656409F796B993213FDA866 -:10C5C000E7EF50FAB13C788742FAC45464BD9CD876 -:10C5D000395AF4AEF7209E679DC94CD0E3237BB552 -:10C5E00074E88F6B237A1D5B8F76E97C872CBBEA1E -:10C5F00035A0CFC63645D8A9EE7D48BFDB14D93F5C -:10C600006D2FB6EF92FD45F98445F6FFCC1EB4B709 -:10C610004F46E76B5885E39DCC92F54D75583E1B10 -:10C62000CDAB2B5E8DED07A3E3E7EEC5F2F90C3938 -:10C63000FEFA5554B6C9F2E3D4FE7C2A6F7F4B71E3 -:10C64000EA7EB49BAFF7789D217EFEC139A6E9E36F -:10C65000399B8AACE67C70F2BBC938BF25C935E589 -:10C660005AFCA5BA383FF94B613E1BF2D9E74B5350 -:10C6700026A1DC3D9BE18F6BA72C2C1AC17FAA2938 -:10C680003CDFDECD42981F9F28DE27F6F13C7ABBC7 -:10C690004F1D96477F2DFE4499F720FD89B54DA388 -:10C6A000FB136B4B8DFEC435A27E247FE21A933FB1 -:10C6B00071E526531C22F4FEFC89756CC086761841 -:10C6C000D314E2A33A77FF8B13D1DEBFE0257F229C -:10C6D000F3BE4CFE56797F02FF6F9983F7CD78F950 -:10C6E000ADBB140FDA15BD772913F179E62EE546B7 -:10C6F000E4AF0B77296EE4B7CB73F93D98FCB7FD37 -:10C700002F7BF1BCF558FC1C1CC17FC15045B029E2 -:10C71000C5DB0BE39CBD4B1987FD57DF9769477A53 -:10C7200000BD53D023DB83FC624D520CE5BC499223 -:10C730001EF73E8CFC317FBCE497657B905F4BED30 -:10C74000B27F3B95578614D1FEDE3DDA64E0AF053B -:10C75000B2FD843AAC5F962DC7DB4FE3CF4F92E535 -:10C76000AF12FFF544C7FB5F34DFEB2821A9FC00C3 -:10C770008D575A25E5D9742A77D7C9F15BF7625EE0 -:10C78000EC2A8BEC7F1BF1FF5A26CAA8BFC37EFFA1 -:10C790009F381FD6CDFDE32AE4A73BA3F57F7C1885 -:10C7A000F9AD4E949B9F79620FD6FFCDEFEF2F3CF2 -:10C7B0009FB9BC9A0D2EBA212FC617E673A5AE906D -:10C7C000EB9D052D4FA2F86275AD07ACC88FB1B8CF -:10C7D0005A5A4D10E9DB69A5FCB9A087DD1A2F9FD5 -:10C7E000FF0F73F9F9F485B92E83BC1E39BE167F8D -:10C7F0009C86423E4ECF0216D7CE3D346BC1E6B981 -:10C80000F931BD0155443B3C4BE06981E77B334244 -:10C810003D588FB20BFD30D2AFBD44E41377947C0A -:10C820003DB800EF2F15DAFCC21D3EA88FF7AAE233 -:10C830009EEBAA053CCF2BD4EB207BADA647E49121 -:10C84000585D148F506FB21FA0B89988A78630EF3B -:10C85000388BF2BA46BDDFA19AE2A89D62BFA5B3AC -:10C86000DFA538F5DA5778BEB08C63D78B75AD4548 -:10C87000B90CEB6E6C522216E8D7888207E3BA3EF9 -:10C8800016F166C6E2CA2BCBD4013BDE0B13F7339D -:10C8900098D087A3F1F01A6F3FE6C7A85A825FC30A -:10C8A00079D84090F2E2305E94C9A2F1672947AA94 -:10C8B0009A6FB80BE3D43AB94571EA44364C6E909E -:10C8C0005C88E63589387A343F47C801199F6E1075 -:10C8D000FB5A1E9503154B50CF4DBC5FC4A945FCB8 -:10C8E00059C6A9AB4CF7DA1A030BC7903FD7AFFA7A -:10C8F00029AD26DD789F29D18487A945FC5EA58CCA -:10C9000053BF32D7186FBEDFC648EEF66419E9AEE2 -:10C91000A488DB3D9F2C927EC8C48104D4BF999328 -:10C92000EC905EF4E78CE5F6085DE632F975D4B676 -:10C9300055E47FC47A05E850F1BDF49F2897B15CB7 -:10C9400004ED55BCDF82F87059C81E95FE1F545384 -:10C9500016E5901FE8DC5CCC0369ABA771E47DF6BB -:10C96000C713E3F3C7AFE74A3DA1DF86ED56795E13 -:10C970003A85F3FDD97E20618745F5182FCF7F4991 -:10C980009DEB9571091BBFEFC76C4B6790BFE4BD72 -:10C99000B9E41FEBF7E23AE4B9B4EC7B4FD1397656 -:10C9A000ED7170DEAFA1F0DF5685278C1CC7981A99 -:10C9B000E078F2CD0C3A3064CE26C8B883E6C49055 -:10C9C0007854CEE2460A0C72B6AEE5BF819C8DE982 -:10C9D000FDDE3A1CEFE3B67EA0A70584D772EE7F9A -:10C9E000FBB8ADFF07F9DA4AA4C30F7B9EEFE5075A -:10C9F0009B719EAD8A56EBA27B31CCAF8C1E2FDC97 -:10CA000088EDCDF1C2ABF931FEEEB718DD6FB1ABF9 -:10CA1000E0A3E9B7F832C00ECF6BE0A743C44F01E3 -:10CA2000CE4F7FEBE71FECF747B8DFAD4A7F24D14D -:10CA30007AFDFD064FE4855EC7F1A7A63B1B509F1C -:10CA40008179BCC87F517F08AEBBC0E00FD9D3F25B -:10CA500021F843609F6F115ECB385EFF06F0A6148D -:10CA6000E27E34AE47FC0DD2654621E2B09FEFEF87 -:10CA7000AF30FF0C9AFF10A797287C849EA4834FA9 -:10CA80005DCB5F073EA5B4BEEFF2F57D0CF0B98239 -:10CA9000E8D5CFD77B35FB7BC35CAEB742BF7AEA24 -:10CAA00097C7E960A3D0ABC12E5F78833766978FB5 -:10CAB0009DAD3516F2F87353A121CF545B87E55134 -:10CAC000ECE64F17A68E6A37DF8DF51F17BB798FFF -:10CAD000805B2C6E13A17B7120C129BE5C2FDAF61E -:10CAE000B6552F9E867935007F2C3B703F56DD7EF4 -:10CAF00032546E6F9BEEABC9EF1DC87DA9D6BAB19B -:10CB000003DE183C5F1BD36AC7FB50CD5A4A37DEA1 -:10CB1000BB5DD87599F206ED9AC38B76E1273CDEB2 -:10CB20006E8CCB566B7CFFF61637DDEF93F7DDE4AA -:10CB30003D94E681692FD9F1DE1CD82F69307E65DE -:10CB400099ED9C7EDF0ED3BD14D5546EFB59E6F6ED -:10CB5000A3BAF6DF284C36E437837E534EDFE9E88C -:10CB600052DC22CF97F2329AC5181D25772E46FF48 -:10CB700025E8715E84C3C29D0F0E623CCDDE65A5C3 -:10CB8000D8F9EFDBBDDB8F024B25ECB592BFE1B7E7 -:10CB90006D0AFFDE47058FE3AF15717C66F23348FF -:10CBA0007FB88463C2033CFFC35E70B68CEE37D699 -:10CBB000AD1BCCE7B443FE0695AF8CC9EF6F5409AB -:10CBC000BAAA0F5CEEC27ECB3D1643FE90D91FA1E0 -:10CBD00032739E3CCFE354359EC7A9FA789E7C22DF -:10CBE000D3E87B1D895BAA099F551ACFE304254929 -:10CBF0007C778BE3A532700FE5F998FD088E02A3D0 -:10CC00001FC24C97667C9C36E1E33195DF4FEA3ECC -:10CC100061F587E175F7434D3DE83F0F3F64213FE4 -:10CC2000C605991F028B447FFE0A16852FE9CBDDCE -:10CC3000AD3C5F40E265C54E9E3742AD0C7EFB7455 -:10CC4000A6FF8EC70AE157B893F5D37D87D56CC888 -:10CC5000867CB0065DE956F4C778E9B99685B730A9 -:10CC6000825FA82713E67BAC75BC1FFDDA0337DAB9 -:10CC700052DEF4713B229EFE1A8BD7AAEC4D9D9F8B -:10CC8000FFEF7EADF7EBD7B286E97EA9C71E99A26A -:10CC90005CDDAFF5238C4BE8FC5A17768AEF6D8884 -:10CCA000FB1683B6D6493B5DD8CE4BE7E5983D2BC6 -:10CCB00016231D1CDBFB03B7B8FFBA69E2E8DF856A -:10CCC000C8298A934F7A7C2EE379209943748FFA8E -:10CCD0008CCD98971BF51305ECC22F139A57941A15 -:10CCE000D38F993B9AC7595C44FE237E5F5BFA99C8 -:10CCF0009A73430BF07DF125410F154A4481FD568F -:10CD0000BA9417156F6C7E66CEA3FF7B3C8CCB0963 -:10CD1000840FE63325F0BCDAC14C567B380E7E26F4 -:10CD20001773393A383B3EFE643DE827F716A57283 -:10CD3000FB690CF72BFCCA3EBA5FE18BF1E846E2D7 -:10CD4000F7D07CED4B1CEFBC9C9413EAC0F69DA180 -:10CD500020E5EBBCD567F57620FC075A5F2B80F207 -:10CD6000927FB2BA311EFE61C7F952E7665E539CEC -:10CD7000EFB280EF99685EF7A67AD4077BA57D268F -:10CD8000F4C755E3746538928B4EF0F6DF7B76EE90 -:10CD9000BEB03AB2BE79F773757BF1FEADD437A160 -:10CDA000BC1ACBB23F0B574C2A057D766D8B8C2776 -:10CDB00056EC43FD363A5F78F93EB4872ED88CE3C3 -:10CDC0004B7DF5FF3EBB681F8E1794F38717ED432D -:10CDD000FDF7ACA93D7D9F12C67BFDD9526ADFC825 -:10CDE000E4F8A5B4DFA85F31BC7135F63F6997E57B -:10CDF000CF523EC1F64C3EDEB1E736EE45BFD147DD -:10CE00006D3D1FF6F8EFB7FD487AFF191BCF1F0CD9 -:10CE1000839EF65826A651F65B39F369762BD07FB0 -:10CE200091A6D079F45BF48343FFA0CB22E8EE1FF8 -:10CE3000F6A24EBFAA44EEF320E5818C44771B0294 -:10CE4000CF3C6CF4173FB3CAB06EB6B11EFBCB75C6 -:10CE50009FC0F6B0EE551B3FEDC175AE92FE8D70D2 -:10CE6000E75EDC5F778AEC376DDF68F38602DBF71D -:10CE7000E2BCABA2F37C85FAAF4A94E37DDD98BFB8 -:10CE800012DE4FFE8FD8BAD61BE0F9FC73FB099E69 -:10CE90004177640B9E0F410FA3F3F8CE960ECAEFB5 -:10CEA0008EF2117B2083F8C8132DEF35F2D17DB4BB -:10CEB000EEEBBD2E384FD3E7E1F9E7E376E2F5DF9D -:10CEC000379C93B8EF3E2E87241DD5B9653F803F30 -:10CED000C893B55E39EEDDF52DD3AFC7BCDCDE0DF2 -:10CEE000FE8A917E2BF90938C9C43FD7365EA7EB7D -:10CEF0005ECAA36806B91E2F1F7BE35C45FA336F39 -:10CF000025781648FB9949BD63F13C9D5F8E79A356 -:10CF10007A47C53C32408C7A4737E659CDA27C2E01 -:10CF2000929B1AD4787479403717F3F85AA7C893AC -:10CF3000CCDBCCD6EBEDEDFF399FAFE71BF3B9DCD3 -:10CF400094DFB73DBF41A13CB1CEBEEC3178DFEDFF -:10CF50005CBA773BCAB5C14C0B7DA7E08CF8BEE646 -:10CF6000E0171D19F7C1FB53194E3FCAAB53293BBC -:10CF7000E93B6AE7FC56419FDF7903F959E7570C13 -:10CF8000A35C917EC396EF77911FF0B4979773FFE0 -:10CF9000ED9937F01C633EF3FDCE00E931F65BE11D -:10CFA00018C1BEE2FB9C45A2BE6ADB535FADC63131 -:10CFB00084FE22E5A7F9BE27FED8F4FA578F95EB39 -:10CFC0005F1EDECEC3863AAE58705C5E768EF05D34 -:10CFD000D85A797FD9A44F5599EE2733F11D54A91A -:10CFE0008F174D68F4A31D57B4C1A81F9DEB79A1FD -:10CFF000AF00ED5ABFD58DC7E4ED3E63BDD4C31677 -:10D00000F73C42F628E885867964FEEDEDACBF8BEF -:10D01000EE857B5F3E6A9D18B35B3ADD55A4A7346D -:10D02000FBA004FB39F9A5D2E47CD40FFAACF84597 -:10D03000589E7BAFDB07B4B35926D039ED57147D2A -:10D040005ED0E6FDC6BC205E8EF9E3DBF61BF2E89F -:10D05000C277AFC172D4CFC956EE473E8AFAC5D85F -:10D0600052AA3FAF0A3F186BD88FE759CCAF779AD7 -:10D07000F83AEA27634BF6233D05A3E7DF0ECAFB28 -:10D080005BEE16EB613F23F9D1A97179F2DCF7135E -:10D09000CEE0F781DE6F7BE0CF67893F83FCBC3356 -:10D0A000D7179D88748E117A1DE68B9BF93C39C089 -:10D0B000F3EFCAB4D95DA95EEEBF72007EB4D5D6D7 -:10D0C000D5E83788E5AB14D277D2D68E905F725B05 -:10D0D00080F3EF2BF346CF53592BF254461AA7A9EE -:10D0E00084E7030C2AEE1A2E97AD0CE572E983D97A -:10D0F0002E8C4DC976A525FC1C786F86761ACF1B21 -:10D10000B33FED02FAD388CFB8DF63A9A01D75271E -:10D11000FF5EBDFC9EC9F914977F33BC5FDA27FC24 -:10D1200015E57F9EFFEC57F38CDF151D29FF2120AD -:10D13000D69F57727DF21F1E4FD43484D710B4454A -:10D14000FFE0B07C0891E720F32012033CEF4EE6AD -:10D150004374865B097ED7FD9E8B38FF814EC706E0 -:10D16000904E6BB91C917476749E97D3DFDB7EA2D0 -:10D170003F4977D03E358072A486B72F7A9B7FF7E0 -:10D1800042EA17C9CF0DEDED984C72E8A6805E0E0D -:10D19000B9A2F722330271E4D0F185DA27023AFB13 -:10D1A00008FA670752E3F69F1288633FFB66067D25 -:10D1B000346EF43EA7360DCBFFDDF320589F39EFD8 -:10D1C000849F17E6BC13A90F36FDEB2F5663DEC90B -:10D1D00095055A15C713876F54AF1CE27A4E4C9FC2 -:10D1E000F4733BECFAEB8B8D34BFC8A7F910C6DFA4 -:10D1F000A81F5FEA4FF0FE9E802E8FE7A366BFC197 -:10D20000FAB6047471930FD0FF01DA9F88D7FC053A -:10D21000D6FB30AD57E8FD1F41787E3B90FA915E1A -:10D22000DF0BB4BE0A713ECF63F2DC7E89DE0FA352 -:10D23000836BA6FFD702BAB8B96EDCE3FAF946B23F -:10D24000CFA1DD4FA87FC530FE39AD1F7794FE67B3 -:10D25000689E68BB68FFB37AFABC0E7CFE4B3D7ECD -:10D260003F8473E4F7B4DFC97CFC378BA270FC0306 -:10D27000CD2BDEFFDD4F76553AF71623BC5A393DEC -:10D280005D837E3DB598FB6743DC3F1B96709F2610 -:10D29000DE0FE17DD2A5F3385DDD92179C5E9C1F09 -:10D2A000B36FA3F6087B781FAE376A8FE040D30DCB -:10D2B000727E9FDEDE58F82F07F7E17AAD0B79FB1F -:10D2C0008262F71A94B3E632E82345B49F585EE6CB -:10D2D0003C2C5F6D5C8CFFE33ACDF17F5DFDA2627B -:10D2E00063FE02E9AFA0B7391D80E3D7EBAC131A98 -:10D2F000A15C59CCF557D03FE2DEEBAE2C8EFA1193 -:10D300002A8B75F918278256BA1F18D553C209649B -:10D310004FC5F4A843FB8CF736BE4DE51281DFC63E -:10D32000E2C3F5629D77D23E26887D5CBD7D88DABA -:10D330007B78FB38F54DB4CE74BE4EE67AF9825553 -:10D34000170F434EB3609C17FF05E74CA96D593189 -:10D350007E23EA488FE2B542B9718FC4EFF7F7191F -:10D36000ED43CE7F2B05BD6F2E3E528FF85BF9AE9D -:10D370005CAF8DECC5BC681ED311E29FD3C21FE128 -:10D380002E81F6E9B4BE365ABF97AFEF4318BF8B74 -:10D39000C6671C3EB52C6C9B384A9E459FC03FF427 -:10D3A000BB9FFA39F9BA6A430AE9EBC126E068C0C3 -:10D3B00073FD0916D7CFF49562BBECFF15EAEF12A7 -:10D3C00076AC3FFE7DD9DDB1B8C96E6AEFE6F359A0 -:10D3D00041FE23DE02A1E30BF13B10B5E27BE3B596 -:10D3E000652A7D6FA1B6E0D252E107A1F8A68C8331 -:10D3F000973E3099E29B896509DC5E741AFF8E4581 -:10D4000070AD83BE2727BF5B2BF332AA98F1FB7266 -:10D4100071E25B067F8BF48B44BF27674D27FBD6F9 -:10D42000BE5FFCFD27D3F7E312DB18F9B71C5DFCE8 -:10D430001EB8394ED5B0A9F5B542CCFB506D149746 -:10D4400035C733CD7F0F63BE93696372281FE5F93B -:10D45000E2D4581ECA5B7BB25DC88766FBF9AD910A -:10D46000ECE73D46FB7950DACFDAF5B19F4F141B5C -:10D47000EF0FECCF0DFE84F0AC6A74BE1D29295A63 -:10D480008A7E8477441EC5D987262C417F54B88F65 -:10D49000DF573827E2FC32DE7FB690B9DCF8DCE2F9 -:10D4A00020789E5D9712C123784C5773057E5750A4 -:10D4B000DAD10879F47F558A7D9AEDEDC402C0E790 -:10D4C0002C6233B2B3CFBADD1417A8EC11DF97107A -:10D4D000F902D2CEAE14F7F8D796F17BD5E8B14376 -:10D4E0007A90DF0FAC1476B8B4C7077EC8147D1EDF -:10D4F000C052E627FAAD01C2C0E772F13DC55A3706 -:10D50000DB828BFACD8CD01FE99CDAC3E9846D579E -:10D51000E9EF5C9DED7B90CED591EE313884BF81F3 -:10D52000E4D8C40FC5CE7795E8CE8F6B386FC6515F -:10D530007B95F37117DEFF4D8D7D5742DE9BDF9E9D -:10D54000C2FD283797703F93F929BF1BF17EE5078D -:10D55000C8CFAC128447CC9ECF2EB936F9398DFA9C -:10D5600089EF56A4611C889F4BD34BB85EE01DC366 -:10D5700083B83DF6D1F300724B4689E7B2ABE711B1 -:10D58000CCC3F9CCFD2F0B7DA43937A495F0783F9F -:10D59000D1AD39DE2FDB9D44FF549CF3F673255C3F -:10D5A0007E9702895A7286DFE77FBD5D3B833ADE54 -:10D5B000C9F6727A9E52C3C998BFF59AB8CF0F8A3E -:10D5C00016E533C9BC28396E6D5DE9990BBAF3AC29 -:10D5D00072D1A39467D6E93BF8B202EB3C27F2BDC7 -:10D5E0000693BD74CE858FF3EF4B2DAFB9EDCC050F -:10D5F000DDF9615E2FE6458581D5379470BFE60B76 -:10D60000A58E81F979F8BD26CE874D7D67E93E4C20 -:10D610007D5B030BCDA0BC2915F17B6A1EFFFE428A -:10D620006581958575EB1A3B5B5B57C2FD3ECD442A -:10D63000A7B1BCC0167C5F6AD3C6E0DF9F94FE49E9 -:10D64000192F282DF915C5DD065318CD1FF4B00884 -:10D65000C6DD176AF7D88730EEE2F1927FA4A1C445 -:10D660004BEB6CEC3940EB490C5CA6F594AA00EF4F -:10D6700071C3E12DF9A25BC05BB76F82F748FC5B19 -:10D68000B9484D46F8BE86F882763D826F8EA997DE -:10D690005CEE38788FF62B2835C0DBE12937E0AD1A -:10D6A00053FBDC18DC8FC473A3A87BABC7FA2AE258 -:10D6B000F15DC023233CC6CF83388EF8BA99B17F81 -:10D6C0002FE1DF9993F8AAEFE2DFBDAEEF2AA5EFD5 -:10D6D000C5D517DC664FA33880D28FF725D796358E -:10D6E00030D4F7ED5A0A7DDF4EE26F6919E04FB78B -:10D6F0005EE0C77D253ABDF303F8D71F27BC0B3D7D -:10D70000F8C3F6FFC37C4F97C4D1CBFF52F187E13A -:10D71000DFF3E1E7EECF84DC303FE5B93B627E33F7 -:10D720005BB2A6E503AC43F20DF26D8782F9938AF2 -:10D730000DE92C88FC8BF7D70A7EB105E3A1CD1E3D -:10D74000D68F67E16EE423809BBD3CD38EFCD3B8BB -:10D750002793E802ED7F82A738A75F8E9DD367E904 -:10D760007D0BA78BBF76DC07D6F30EADA74EDC2F63 -:10D77000F888C5A56E2A0F3AE6A37F563B40F2E52E -:10D78000E83CB7944F19FCBB4DEF2F0E5AA4F1BCE7 -:10D7900031190F8D13FFF42A1F20FE698EAB8E14F2 -:10D7A0000F8D13FF34E8EB23C53F99294E6A8E7F16 -:10D7B0002EEEC9A6F8F3629F85BE532DF57E19F7AC -:10D7C0007CA5E72995BE8B345D612999C3E3A33B12 -:10D7D000857F8CA156A7DBFFA90CFEFDEBDE34276D -:10D7E000FDDD55FCC17C2C094F900F4E07CCDBB5FD -:10D7F00088E76556651E36C3D52EEC926B82AB8CDE -:10D80000AFDB7B94C866240D0F8BE6FFD97578B625 -:10D81000FBBE437864EA800BBFC7DDE81F4FF964A5 -:10D82000663C14F5F0BF4B59E49E437F9752E2BF2C -:10D83000C8333C6F5095EB8B9337F817C7A777B376 -:10D84000336B147CCA38F64878BC252FB811F946DA -:10D850007EBF49BE3F95C1E17B7E1A137FFFD4880E -:10D860004F80BF46F7FA7DECC06665383D14897C71 -:10D87000CC225FF81ECA834FACF060DC2C0ADFF4C8 -:10D88000EF127C3B5BBDDBD13E3A5E66A37C9538F4 -:10D89000F4407FDFF66AF4300CEF7D1F0C7FAB0A9B -:10D8A0001F5B9819873E3E305EAF824FBBF5504FED -:10D8B00081371E9FBED0477CEAB7BA11AF129F12C4 -:10D8C000BFC3F1C9F50B89EF53F9DA37E7E7EBF19D -:10D8D000AC3D81788EF16F98DB312CFE776F0E8B2B -:10D8E0007C1618E749ECF7D4FCE8384FE1B8D59F2F -:10D8F00088FFF74E0E9772B95BC7FA5F9C8876DF98 -:10D900000526F235FD2F7BD14FD3961D375FF3E40B -:10D91000FD0AFF3B3D1E76C022CE578BCEDE3D8BEF -:10D92000799B60DF9EC6BC4D78FE707E26EDB717F2 -:10D93000F337C7823E2EF23BEB706C9C07F4598C98 -:10D94000CB3335C4F05EFA207E9F65167E9FA5839B -:10D95000E46E2C0FE31D531E062F5705A4BC714522 -:10D9600028EF261AFFF4840CF14F363362947705C2 -:10D970002143FC53E4E948F9B6595B100A1BE29FC6 -:10D98000E534FE993AD97E47A474BA3EFE591DD1BA -:10D99000F4F1CDF01D54AE8B968354967EE8C70605 -:10D9A0001E08A11FDA3733F44BC493BC370F02486B -:10D9B000C3BF436775B90FA21D0EF601D3F247D658 -:10D9C000AB3F2ACFFF0F526BA57D00800000000007 -:10D9D0001F8B080000000000000BE53C0D7454D5BF -:10D9E00099F7CD7BF39364422621E200415F02E880 -:10D9F000D442187E020109BCF94932B62003048DD5 -:10DA000005E903722C746D1B6CA9B4AB9B81C4989F -:10DA10000485D0B2DB9F6DB72342CFB1DAB371EB8F -:10DA2000A944A41DA4555A2AC6363962976AA0296A -:10DA3000075ADBA295D5EEE929FB7DDFBD77E6CD60 -:10DA4000CB84A0D03DF674389E97FBEE77EFFDBEF9 -:10DA5000EF7EFFF73E972F54185BC0E0E74D1A1A90 -:10DA6000630361F87302B6FDA651C6D8AAC9B25DB8 -:10DA70009934A631B6B840B6AB4D6321631D2E264E -:10DA8000C6B30403F8579893DADB8DB09998C2585F -:10DA900068B92AE06334FF6B6B24FCAE6408E65B74 -:10DAA000ED10EDC4CAA4E165EC634CB697527B4D12 -:10DAB000BA1DA7F69D8CAFBF3FF5B09980F1DF99F5 -:10DAC000139F605C03EFA23D7A7CFADF1FFEA7156F -:10DAD00089CF6413FB3FE8F802BF6346154ECFF9C8 -:10DAE000FD7780EF5A928F031CDF0F207EF7103FE7 -:10DAF0009FE0F87D00F069237C7A009FC2BFFD7A29 -:10DB00002F5419BB71BDBF011DDFA47D9FC6E9B8AD -:10DB10000CF84789EE20DF077BFF84908F31EC9F64 -:10DB2000C3E77BD529E428D164A2DC9F725AF60DA5 -:10DB3000DA0BFAE57A5BF49066C57F0BE9C9EA1265 -:10DB40003EFE77A97BCD4459A60D3F03F75D8EFFBE -:10DB50003DF6678DFF3C8DEF72A6E1693D97E85772 -:10DB60000E6F237C33F42608BECF06DF28E82B3A5D -:10DB7000DC914C58F8C1120F127FD27629F130D9BE -:10DB8000A501976CEF20BDD959CEE71F7FF8E1249E -:10DB9000E20FFC3B46FC9EC2F9F78FCE8F3F184246 -:10DBA0005E029C1F520EBF33C7F823CAD9070D5F10 -:10DBB000D83F35744D46FEFF1FD62BA6F5843EBDDB -:10DBC000D7F1697D147E9F2D49F3776208DE8F0FB0 -:10DBD000EBD45FBDF1C9C8B5F0E79AE6475413E747 -:10DBE000051856CA587C9025B7C39A37B3A4CAC043 -:10DBF00087C58326F34DB3E835FB0AE1E1F23A44E9 -:10DC0000FB5B64FF562F92727D2289F145066FEF10 -:10DC10003ADCA734DEEC9B59782F3CEC7D44D01DD8 -:10DC20000C59F4E46ACFEF0F035F2CF150BA2DF8D2 -:10DC3000B3FAD35F9B847C585D21E7FD7612E779C8 -:10DC4000B558CEFB24ADBB3ABDCE0F783B5FC2FFCB -:10DC500094E033780D985978257E417197C4EBB1E3 -:10DC6000C303B45F2E5FF2817173E0D9A40413B0D3 -:10DC70001F1FDBB84D35AD7681F5E821F06F77B029 -:10DC8000749BE42A63077A68DDAB8DD7E690E08F5A -:10DC9000D0D3349E832C986056FC0EF0FDB9CAEBAD -:10DCA0005BECC23D28B7579FEF29E7B516BE4B3D49 -:10DCB00058E34BEBB7C13CC0775DCEF36373A3F77A -:10DCC000CAD705397FD86A4FAE9C8EBE5AA2E30DE3 -:10DCD000BE2F19FBF392996D7F2E1BBF4742167F13 -:10DCE000FE9EC787B2F5CC627F1E47BA5BBD252E6C -:10DCF00094EF757E662401BF8BF85B9C798E0F2BA9 -:10DD0000649FD2FA59CDC7AFDCC59A7BA60D87BFF9 -:10DD100036EC20B8D667D8C61E982FE43ADF14B781 -:10DD2000C0A542BCFF5048A127D07788F8BF95E333 -:10DD3000772CA4D37A21A6310374AA61E5A4329486 -:10DD400083D65FF2F9983FC8561466E63B2BE693FC -:10DD5000EB1C5E5ED868A5E327629D63214E07FA3F -:10DD60007FE2E77D9C0EB5E86E3FCEAF16C8FCF2B1 -:10DD700077C4D776A76827DE22BF3690B6437F24C4 -:10DD8000795FE59672F90EE9BF8CD7DF0AFD6F3235 -:10DD9000B110F167CC31CB3AEE0F6407471B37283F -:10DDA000FD459BD8AF447ABF4E21DEA38D57234A51 -:10DDB00033F1C9C3520AF80FD5EBDBDB05A4042A03 -:10DDC0008D7338FEE84CE3B797330FF0E93CEDCBA9 -:10DDD000E7B2F3114BFFDBA1AC7CE0FCDD719C07EB -:10DDE0005676C3BEBDB2462D5D0F7CFB2BEE4F15A4 -:10DDF000E507B15CF2F5D7CCBEFC359415CF470AE8 -:10DE0000AB408FD8784770AA3E7C9C37AC4839131A -:10DE1000FBA43D8274B4A7F58DB77716F3FEBCE77B -:10DE20009CEB843E1584719DA7047F99AF14D76342 -:10DE3000D38EA6D4B9E05F59FA6738A0BD1EFF8221 -:10DE4000F50722A79C28076B3B14239943EE87E92B -:10DE5000498798FFA1F4FE8D0F5F43F39A6CAEF0F3 -:10DE60001FF01BF8C4369AB7B14921FDB3EBCBE4E0 -:10DE700030E7DFE4709A4F93097F43C8EF9CF85472 -:10DE80006C032873CFCACCBF56E01D72C60F5D0B62 -:10DE900072D0DEA6E8688FD66D5DD7510E6DA639BB -:10DEA0008353E17103720AC6B5FB2BBC68075E148D -:10DEB000EBE17C2ED847F425FE1282631A3CE7C6BC -:10DEC000361FC1E1EF4E37AB909EEAF8EE0892B5EF -:10DED000A0F1C923F8BC15CC34C629DB167D3D1E44 -:10DEE00086FDEB9BEF0CA2A84174D63705F06A10B3 -:10DEF000786946FD393606B228170BA6E6A05FF70B -:10DF000006B7C3FB86A64F2C61950013770E0D7ADA -:10DF10009018935DACC079B5A1C100E7D945B07147 -:10DF2000CBB73A336DC40DFB3D99FE95D773FBB467 -:10DF30003A0CFCB4C8DD0F057D3F14FCDC0538F459 -:10DF40004DA3090A19EA0DDBE840FEAD1373F5B5E0 -:10DF5000ADFCC88700BF0B0116C4B61BE95333F4F0 -:10DF60009D9AA471FA98E15D3A0ED615FB7ABC052C -:10DF70006CDD8D306D1BD009F468EA9AA294458E51 -:10DF80008F8F315910E3B640E20106721231773BB0 -:10DF900007018FEB9BDEDC8871DF5AD3ADD7038A94 -:10DFA000776CF4D5625CBBD2147C59E23C8D747BF7 -:10DFB000E01FF2C5953AF76317F279A1C2C6C3FC18 -:10DFC000CBA2BC5FF2C5CDB4D356BE68B6F6D6932D -:10DFD000E53B7F6481FF4CB8B0F4CC87E18FD96C0E -:10DFE000F645A0130CC852C4E74287E253CB09CCD4 -:10DFF000C1804E9787EFE3FE8ECD2FA29EAEF56BCC -:10E0000041878EF831E25FA358E39D167DE78F20AC -:10E01000568D6CDDDD8D727747BFCADC00D7BE66DA -:10E020003FCE843F0FCEA709B970147CA34F0338AD -:10E03000ED8B2AC3F5241F81DFBEB9F0FEF4008CFE -:10E0400007D03BAA814FB0EEAD865BD7012E7FE1B2 -:10E050009B6DC8A77CD69C1A0BEDDBFC0E96F26478 -:10E06000E802BA13822F8E8B0AADA56B725D4756FC -:10E070003FF125FF0B11C6D076278CBE2900B75C77 -:10E08000CA6D07DFCFE506DF0FB9AF2CCAE555EE45 -:10E090004BBE4D5EDDD5CE8C7CE69057FB3E246DAD -:10E0A000FBB05FE37A72AA5FA5F8E8D49ED25BABBF -:10E0B000811F893D0ED263C8D30E2845F0474A61BF -:10E0C0001AF0FF76812FFD006E7F7371B2AB3CB307 -:10E0D0001FB7079EFFB352C938D4B88C3D6298C4AD -:10E0E00042FB36D1BAFDAB8912D4D38FB11E27EAD9 -:10E0F000F59D6CD089F2FF714C0555B48F4117BE68 -:10E100006FF4F85CC8C7FD7B9E2B443B929AE02CD1 -:10E110003E13205561563B697F2227CE48BA01380D -:10E1200025EDA7C7F4935DF6C293ECB4C1B05D5C76 -:10E130001BF59839FCC8E1D9E60B6807655BF33538 -:10E1400033C4E35BB3E33F217B29C6EB95C64FB1F4 -:10E15000FDBD59C6317C7E1BE33DF00FE7C3F7518F -:10E160005EF2EE74E338DA35BB1D3B8D764CCFC8DA -:10E17000C30A9B3C483B7602ED1874AD407D05BE5A -:10E18000B1D895D9B153520E6E6237217F809E5F10 -:10E19000931FD1801EE0CB6BB8EF331856DF52AC23 -:10E1A00084C8D47D809F22F0C3F70AD87765EB0B33 -:10E1B0007F56C6F0F6028053C4BE621A598B7EE3C6 -:10E1C0003F821ECF64B417E609A4DBCE1770CC4E95 -:10E1D000CACBFCCF9F40B971143C3BC9CCE107D3FB -:10E1E000FB7AB7F38D345DA84710C9231D0A331D90 -:10E1F00017911E1F2031FE5272912039685FAA10BC -:10E200007DEDE5AC11ED791B76CD07795FAAF4A021 -:10E21000BC3F1E29E1F1D2141E17761527FD415E81 -:10E220006721781608B295D333F33E1E5109FEA636 -:10E230003946013A2E88FB285E92F1AA84F345788C -:10E240005C3936C2E38C4065BC841C5D6990F80E75 -:10E2500071D4586A7B5349C7385117E13FDD618952 -:10E260002306262619C621F946EEB8E1BA48DAAFE8 -:10E270005F17413AF648BF6E5C8FEDC5637D0D6850 -:10E28000E75C80F7DEF28CBFFEFED2FB5558967D30 -:10E2900038524EF85537ED6E1D07FB1D0A4DF662DC -:10E2A000D894AA49FA318EE81A0F7CC8A12F5B23B3 -:10E2B000DC0FCEB94EC0097E49BFEF81F0DB09EB20 -:10E2C000609AEFC038A08CC70177462A689C8C07FB -:10E2D000003EE102B8D00D26CDD33E35F77A770A5D -:10E2E0007E66FC6DB008ED3563CDE42FE2C29FBCC5 -:10E2F000D262BC36044239D012A327D8FFBE2818F8 -:10E30000B8135AA23098837FCB6AF779D06FB706DB -:10E31000D67B0631FE3322346FE39AD06B43167BF3 -:10E32000DB55C626611C705BC32DAF0D59F4ADAF34 -:10E3300090E38B7E26E1CECCBB0AE504F03D127261 -:10E34000A7160343F3FD2CE956E8E9D4510F223A0E -:10E35000F5C78D75CCC47CBCFA9446F5AF62968641 -:10E36000DF065B13093027E215F727198ECB8736B6 -:10E37000C2C717BE49F0CBAA5596B0E009F6672D83 -:10E38000C9812D5EDA850206F3B6CF5792DB61DED6 -:10E3900006FF5DE47FB62DCAA7F7B06ED20DEF6F12 -:10E3A0009DDA447E4BC657EDD16890FCD315C65319 -:10E3B0008767C7EF41BC5CFEB45DFD1CC97FC6AE7C -:10E3C0006E8970BBFA797C2FEDC7DE23AF90FD809C -:10E3D0001C84F8DC05FCFEAF1CFBB84DE84157314E -:10E3E00097437BFFD784BCBE3B3DDE8AF31BE0D363 -:10E3F000FCB3DE7FBCD92EE34DC1C72BE50FF0E3A4 -:10E40000DF2216BB0CFCF84AA46A381FE0D786F658 -:10E410004295D6E2094543F9CF13CD479899C47187 -:10E420001ED64C40AA37CED0DF0D9F27C570DC6AC0 -:10E4300041DF7BB5C7FF09E10DB76BC61311CA0BEE -:10E44000B93C4BBB0C7AC9FDEFFBB4DBFD0EB0A7AA -:10E45000804F07BE9A9FE93F24F6B9B7CA3C84EBC8 -:10E46000DE50E65987FC7F5031FC5E15EB9E66233B -:10E47000DA11A6CFCA1A377C9D6D34CF4085B91109 -:10E48000F59AE92B4681DF2ED6D5B9BFD0391DB01C -:10E49000EE57F32767DAA3D1F5FD88F173C4BBD536 -:10E4A0008CFF0AF5EEA580434F28F4243DECAACE5C -:10E4B0004B2AD02E9865BECAF711EC284CDD157892 -:10E4C0008BE2A2654B148AD396792083CB6127CF48 -:10E4D000087FB34CE7FDECA4E1B7D63B8AA38EECF2 -:10E4E000BC1744C2B0D62FA28EF5589797FE0CEBFE -:10E4F00026B9F4EDBCD027D5FD6619DAD5979CB9BD -:10E50000EDF65B1117C12951519710FE6F959BE7EE -:10E5100057EC67809FC5BFF65685FF47D8AF84622A -:10E52000F18B0313CF93BDA31ECBFB65A2EEC4FA00 -:10E53000B3E79174964459D6BA20AF8E28AF63A83A -:10E54000514BFF2A95F1BA475F36BF001F4F94E247 -:10E550003F3634023EFB72E273221B9F9228DF9704 -:10E56000DE2AA304E703FF3C16D7EF0883FCE5E0AF -:10E57000EF1333C2D762BFC6121D15E5978C5BAF90 -:10E580004338D9B6C4AD7A34DBBE9647B97DAD8881 -:10E59000927DCDBD6EA5E0DB95DA87F7ABF73B6CDE -:10E5A000FA2E9F5D834F1554021E6E77E2B3A4AF1F -:10E5B000D32E4FBF3F7E5DDF44A4F390904FB4ED68 -:10E5C000186F183A8F473E1DE5721CBA214970CF6B -:10E5D0008C107FA4E1803158971B290E99FF3EE3F0 -:10E5E00090AE850305384FEBDB7B0B308F7F6628C1 -:10E5F0009C330E3954D64D78DAE390DE11E290BBAD -:10E60000A23C5E3DF21B17C5153567B99FAF39DBDC -:10E61000ADEA209F7747B9DD9E3FD4A79A202735E2 -:10E620001887C03CBD220E41F86D20BA91B7BB558A -:10E63000C46BFED93E1A57036D8C43E68F108700DA -:10E64000162ACADD819AAE5FE0BED9E97DA1D2DC8F -:10E6500012B5E45BD5837D744E22C77505B6179855 -:10E66000B4CFD972737836B7BF99715CDEED702381 -:10E67000C957ADEA0D607DA093E507910FEFE48DDA -:10E68000A964453CAFC1B8B8134181EECE9305C92A -:10E6900004E6D51EDE7F6FFE98BDF894F6C723F41E -:10E6A000E29DBCEB92220F328A60FCBDAA915A0C0B -:10E6B000FEA073CA977C9C9ECDA4475B046FC2BB2F -:10E6C00035CAA76FF6F37D90F1D78BAB148A0F6133 -:10E6D0009A254B017E9E98DF3587E78775AA97E0DC -:10E6E0007604781C7973E23CD52FE60FBA741DDAF4 -:10E6F000F306EFE2F9A2FAECD1028CF73FAC311548 -:10E70000DEAF6A8BB7927C9E74513DC3807FA89F19 -:10E7100055FD3DC4B7822157569D231F2C59CA125F -:10E72000B7B86C6DA6AE29CA6587E4D35E87783228 -:10E730002AF2CF4A36E322F0E502BBAF0369734FFA -:10E740000D1F79940D1F2FEB0B9B66184FA37C4C6C -:10E75000710E7EF769E057EF1B2EAA5BF4EED9F33A -:10E76000D14AA02FD1AD515D57E6334059C972CC83 -:10E7700067910754973EBE1EE5F260A16C8341038A -:10E78000BC0FA6CFEB37AD372CED63D1074EA3DF1F -:10E790003B788D843FC7C7CB7662703DDED7383873 -:10E7A0009EB72F44D54713B4BF831AE5D15B7FEDE5 -:10E7B000CD651F8FD772FD92ED5BAB3773791D6509 -:10E7C0001CD8F557ADFA21C7E52D35774C077E1CCF -:10E7D0001C72D0F910E459298C0F36CD305F47F800 -:10E7E000074F70BE1E7CE31E1FEE937BECE0E772CA -:10E7F000D9F9DF0B7F94CEF36672FB016E4E43BFF7 -:10E80000B56BD133C72A619DE3F3A7CE528104E0F3 -:10E810008507E36539DE5D5B91A587B756BFACAE72 -:10E8200047FBF3C6E9865CFA5E1535FF944D0F3F52 -:10E83000176DEDD688FF25CFD7EFC57B3FA99AEEA0 -:10E840003E0DF6B7F7F70E86794AEF7491878F84FD -:10E850005710F02AB92CBCF6CCCB216F8097ABF6C1 -:10E860009AE178BD54CB883F2F541A9EDAAAE178FA -:10E870003251C75C20EC7DDEB92F51DDB177D0413C -:10E88000C5930B437B55143D59FFEE3A518111104E -:10E890005BBCE4948A2265DEA766E9DDBC13F95906 -:10E8A000ED3B9BC766B5576F9C98D143F86F457495 -:10E8B0007256DBEDBF29AB1D62B3B3DA0D4B6ECEE2 -:10E8C0009AAFD617C96AD7FB3F9A057F8BBE32AB8A -:10E8D000FDD1C0EA2CF8A5C10D59FD35BEDD0F6094 -:10E8E000F9283E6DA63696913CCE44BE16F41B2404 -:10E8F0008F0F9EB8C7877291AA894F42791B28EC67 -:10E900002BC3FAF58BCEDCF9DA7DB5AAF4DF65E826 -:10E91000EF0DC6F335091FAA18CCAACB6FA8E5FEE8 -:10E92000796DAD92B34E60F7C7D20F4BBF6C5FDF0E -:10E93000EE77EDFE76D987F67A78BD9FFBFD5542DE -:10E940000E5A033FF762BEFE6203AF237495C5A95A -:10E950006E3020FCF39155B74FC273B5FC8039D6A9 -:10E960005D9EF1D7914092FD1AEB3CBE249B3C1D6D -:10E97000FB936CC374AA4B6B9169FCFD0DE2FD5DCA -:10E98000F8043F5D67E19BDDFF863C337F5CC4326A -:10E99000F14AC3BB46B408F0FB48D3935A293C2341 -:10E9A000DEC39AD50E1DAFF96DE9087EFA93B53630 -:10E9B0007DC271BD432B2EE9075E6FE175F7EFB79E -:10E9C00078580AE83BD9E2A3E72F5BFCF4FEE51692 -:10E9D0009D9EED2D017AA65A82D4FF8B966A7AFE0F -:10E9E000A8C5A0E7F32D317A1E6D8913DC4F5B1AA1 -:10E9F000E9F9B31693DEEF147AFA41C1C708C8BA31 -:10EA000042FC884321BE36E055DD05670DD56AE737 -:10EA100081AFFF9A8BAFEFD79FA46A7A26A29C8121 -:10EA2000BFCAA94F3DB532AE4FEF37E125E361CC08 -:10EA30005F504E649D0EF07B0CF173637DAEE4CAB3 -:10EA4000F13BA870BC0E16F3FA0DCEB3BC10EDF975 -:10EA5000D7E361B2E7D7CC247BEE675AB63D2F1FD0 -:10EA600066CFD791DEB1A35827C5FA229D53D8EAC5 -:10EA70002045753A8D93759045EFF23AC868F403D6 -:10EA8000DD47D16E49BB7DB974DBE93D3CDB7809DC -:10EA9000E791FE7998FF30EF26FF512D7496696F4C -:10EAA000539C5820E8D9757A4511DA173722C8F3F4 -:10EAB000748355E33E33791F60EFC6B2E1F3BE5E67 -:10EAC000D343FE7C473ACE7993E298E1FE2B9B0F2D -:10EAD000180B59FD3BF0E15CB65FE47CA8559F1D27 -:10EAE000DC0EFEF9E020E375B239FCBC4EFAC183BE -:10EAF00067791DE382A624196C5D983577CF83E78B -:10EB000081FB59691CCF9B263982FB01B4E0B95EB9 -:10EB1000DD0370A141736C1EF457A7F2685C78C9DD -:10EB2000CC24B61BE26F927D0A6BD97E1223D4B43B -:10EB3000DFA1225889AD3D2103AFE2FE5664DA30F1 -:10EB4000EF27669B5A1DD0B5E27C33D3617E7719DF -:10EB500073D2FD90E1FEFD6EC55267D358B003E954 -:10EB6000D0BEB0839FEBD9E44DF249D6DB641EFEE4 -:10EB700008337C7539E2873671EE623F6F796BBA84 -:10EB8000E94778C5F73C9DB7B08D8CDF8F70407E2C -:10EB900082FC1BE34AEE2F1F2E77DF9B75CBA43A36 -:10EBA000AA532494AB93B7772B94B78BBC89E99F76 -:10EBB0007158F3189937D9F3A387849DDD897616A8 -:10EBC0009E0F3919E55BED4A7E70AF92C997C06F11 -:10EBD000CE40BA16D589F317D63C8F9FD3DD9F95CB -:10EBE0002F8D88B7C84B9CE97D2FF39D29C8ECBBBE -:10EBF000D7D5EDC77B8E9D33BFD1B81EF936D34331 -:10EC0000E79C4C4BE96877ECF4305F8295CECDEC15 -:10EC1000B7CAB433589FED806006CF7B1FC62F0163 -:10EC200060BEC2A0232BEE29AACE8EDB6EAF9376F8 -:10EC3000F6EAD0810240E7DB124F1617E7993CFE57 -:10EC4000F488F76D3AB7170CED9DE57CBDCD6B7878 -:10EC50007C96FD7F10F7C73D323E6A799B0FEBE053 -:10EC6000DD5E07E97787AE759643BBC3ABF1F84627 -:10EC700077C4729D43EDAA5304DD1C2F9FC04B0D3A -:10EC8000ADA03868A4F5BA84BCC876FE34D3207D24 -:10EC9000D48371CC935BBDA50AD64765FFA63A45E0 -:10ECA000C84B37F1A153C455F9819E9403E56CFC20 -:10ECB0005DB3916D1E8893CEC07BCFB41E8AABBC72 -:10ECC000135C662EBCBF2CE6EB74066394F7173A10 -:10ECD00018E6FD9DE5B9FDE83FD7F138B3559F151E -:10ECE00047F804F065AA321CEE53420E1E70821CD7 -:10ECF000C2FA9D536FA37B629D9318D9EF8AFAE9FC -:10ED00008F6EF3E69043FD33B47F4E1F93E7EF59C8 -:10ED1000F7255AF586C675B0AEF6320BA2CDB0EB2C -:10ED20009B73FC8AC67578DFA23A3F88F0B5EACFBC -:10ED300012C8C7F620A37A8756DCE441BC1F2CD347 -:10ED4000E87E449AAF33CCC7D07E8C26DF767C60D9 -:10ED50003D92BB91F6D78E1F85F2B32E015F6C36C4 -:10ED6000C673CCF7CBB45E65CB977314F91A8D9E3E -:10ED70002CFF5A96F1AF3FA9DBBC01EFA93DCC783F -:10ED8000FFB1BA30E5FBF6F6D5D2F356ADBB11F7BD -:10ED9000A5758A8BE4CF3EBEB39CE3D5F57C8D5838 -:10EDA000D7A7A0FCEFAC2EC943FBEE45436DE16B4A -:10EDB000AAD23C5567F1DFC5D1661EB7D731925F45 -:10EDC000AF1EF74D01B9F0F6AB2053C077C75FDE39 -:10EDD0003DA5BF7F3EB26E83E4964C3B975BF61732 -:10EDE000E04B9110EB31ECA13E7E5F640BC1497E9C -:10EDF000EDBAFE0FC1D425F8366661767DEABDD640 -:10EE00009F94FAC252E2731ECB433E5F60F729E43F -:10EE1000BFA306E99D2F6D57F9BD9552D90472B075 -:10EE20004D22A764EA520CCF3D50BF4C46F10D4134 -:10EE30008E13475E44B78FC64D14D34CC00B352A92 -:10EE4000CA3FB7BB17D81B7C7D1886F756948483BE -:10EE5000FCECF528D70057CECC3F9FCA719F679234 -:10EE6000AFE9C90DF09C582FEA69829ED1F821F1D3 -:10EE7000FE5BC9AD8C0FEC755459677D1AEBACCABB -:10EE8000E87554A69D27BEC9F8D75E5705BF5680C2 -:10EE90007C7FE7068D7511DF79BC90C9F34D8FF546 -:10EEA000FE9DF497EDBE1559F5F97923D0FBD428D2 -:10EEB0007EB1AB1FEC26C6D1FEED549F3F7072FDB4 -:10EEC00051CCE32FF85D3AB3D8FFF6C2ECF3033927 -:10EED000EFF67A51871F5FC770BCD66732BCB7E7C1 -:10EEE000F207C92FB42AB9CF1DBAEA1DE2BCD1E698 -:10EEF000276CE733FF9DE74DBA2A58DA7FA8C23E58 -:10EF00004BFFCA34F0A2E3ACE3B91D95FC3820E214 -:10EF1000D1AEE736D13D03E6B7D47D2B72AC6F8F0F -:10EF20001B0D43F7CDCDC4B1CA208F5FE5FAED22AA -:10EF3000EF6E3DC9F7235FDC37B2D30BF1EF17EB70 -:10EF400081DE8280C356DFCAB637F678D8ED618994 -:10EF50007C8BFD8378B8A59EE284EC7876428CF1B8 -:10EF60007B41C526C3FA4FC46FAA58AF99DBDFAC0B -:10EF700032A07BDEC94BEF47633D8F17DA03EBE32B -:10EF80009837C9FAF3AE451F21FB0A7EB4BBDE6297 -:10EF900077E57D87F75A8F92F23A57EC637A7DFBDB -:10EFA000BD94855BF8B9D1C97B8EA13C1E00794424 -:10EFB0003FDF5E98D8311DE3939755B65F1F5EBF64 -:10EFC000B2D325EB506363FCDE8ACBDF7E64B1C332 -:10EFD000C29FC1665527FE180CCF8934714E64AFAD -:10EFE0003BB9DD4633FAEF548DD168AD3B4BBE35AE -:10EFF0000A797EBDA699CEB19E1EE1DC58C2E1E73A -:10F00000659887CB3A56D90CF359E4EFDCD86615EE -:10F01000CD48757C33DDBF2CF81746F923CB5792CA -:10F02000FB61A9E7163D43F9E59FFC8CEA6C2ECC09 -:10F030002F4B319FE4F9A5CC5BA59DA8559FE8A86F -:10F04000C07B1DFD1ADDD32B786E9307E3DE50FFE6 -:10F0500006CAF10C655501EEA3BCB724F1BCD2FC85 -:10F06000B40AF353CBF94AC66EC47E8572D0D5126A -:10F07000FF5514E4A3B7C5A0767B4B233DABB4A4E6 -:10F0800081F4540528E3630B86A0DF8247555F2C8B -:10F09000ABDD5569FE86EB553CEBBDDB0FF359E468 -:10F0A00002F2E3730837F724E7A76B8942F711965A -:10F0B0000DB207B86EFFC3D8A182D8D5B143BED870 -:10F0C00025ED103F67750D8A73569BBE3D5EAF936D -:10F0D0001EA4F50ECF5BC9CF25683C9D19CE077ADB -:10F0E000C67C92DBADCCBD0EFA9E3124BEB3BEF120 -:10F0F00068CD3E8C67DB5F95FDCBF719967E9688D1 -:10F100003661EDEF3026C71067761E2D6DA2EFB089 -:10F11000C5773491C6E2B20196B9EF68E7D74331BB -:10F1200047D67D9A10E3F534D9BF3926F24320073C -:10F13000EB76F2BE443EDE97C811BFFF9398EF5EB8 -:10F14000E453157E1FC2EF2B2CB67D1F62C42EFD2B -:10F150007D4842F48FF63DC81D319E5F98623DFCAC -:10F16000FE3F86F8C6F97718EBC57E2DE84FB68EC0 -:10F17000C120D1CF72CE138F713FFF428CDF7771E8 -:10F18000F90D0DF705E65B4172D0C8EF67CAFE05C1 -:10F1900067D3FDB7D17A0DBC7FC15993EA48F2BB62 -:10F1A000BC78ECC67DDBB4CCBD9C76AC4778F1FB7B -:10F1B000147EDFE9DF059DF6A7FC3EE5369FB8DF4C -:10F1C000C326EFC3DA66ABC1BFC7BC2576D35042B6 -:10F1D000A3F5EFA2F5C5F738D5825E78BF89DEDBEF -:10F1E000FEBF024DB1B27DE23B9E4F115DCD1CEFE3 -:10F1F000F4FF2721319BE44BC257C7663509F8CF8E -:10F2000012FC460E9F431E843C56119E9731DFFD33 -:10F2100084DF1A8EDF87627AD6F75F526E016E3B0B -:10F22000C189EF83FAE31B3C68CFD3DFFD27A6ED4E -:10F2300033A65C169F76D03CA65C8FF3497573BDF0 -:10F2400090F22FE5E1BB621F66C61429575FA6F155 -:10F250004D578DFE6F123F6DDF238D4647A032BEA6 -:10F260008FF0F0A7EF23EF8FE5D6CFF7848FFC7EEA -:10F27000CCAE17CF0AFA61DDEFD13A6541BA9704F7 -:10F28000EB3E7535D685797F407CF0A4E7FD21B54E -:10F29000AF705E56567A59F74AFE0FED913B6F609C -:10F2A00046000000000000001F8B08000000000066 -:10F2B000000B93E46660F8510FC181486C62F11A4B -:10F2C0007606866816068699AC0C0C15402CC74944 -:10F2D0009AFEE540FD8B80782E10CF00E2C940DC1D -:10F2E00007C49D40DC02C49240F34480981F88B953 -:10F2F000809815881980F8370703C3370E8439378B -:10F3000080620F48B41B84AD7810EC3340FF6F046B -:10F31000E2AB6484C3281E1E389D9F81A15A00C1A0 -:10F3200017104495CFE047B0B94429B34B1AA81F32 -:10F3300000656D40B4800300000000000000000084 -:10F340001F8B080000000000000BE57D0B7854D5F2 -:10F35000B5F03A8F79666672124298842027103091 -:10F36000680A4380088AF51022624BED48A9622F93 -:10F37000B5038D80104854ACDC4ABF0C4C8020286B -:10F38000415141910E0816156D44AC58D13B20B542 -:10F39000B4B56D6CB9D55AED0DB5AD2F0C8852FDD5 -:10F3A000FBEBE5EEB5F63E9973CECC24E0EBB7F778 -:10F3B0000F9FEEECB35F6BAFD75E7BEDB577DCB242 -:10F3C0000B0A07029CC49F0B006E7103C098743A2D -:10F3D000F2C66FCC7F6834FBFDFFBA23DBF5743DCA -:10F3E000331D0812D50330008A012EF0B25F59BDDB -:10F3F000893F3FF2A7114500FB40010FFB945227C4 -:10F40000F6F91AEB67DF8710C172F9E781B2CE0017 -:10F41000B68B53BB2F036F972AD7CBB42ACC808CE3 -:10F42000DF0D2FFDCEFA19BCA989B53FF14180DA75 -:10F430003BE13053F850869468737210F6ABBED738 -:10F440005929F2E5C00607016F1D404D1ADE03AFD2 -:10F45000BC46F0EE5719BC7A96F1BD0CFEA234FC06 -:10F46000FBE01BF950C5E1376AD2F09F2E3C34FF18 -:10F47000BE002B9BF5272B5C003737C39315430049 -:10F4800056377B29BFBC59A37CA2394CF9952A6B0E -:10F49000C2F0B0721B24E3AC7D6834AB6FF6C7FEDC -:10F4A0000B54796D7977116BEF4DE7D540D896F70E -:10F4B00096E9B63C03E75098CDFB2C319FE5CD0C87 -:10F4C000071E1CDF0BC69958FE6DC28B4FE02D1135 -:10F4D0001C7AF9208697D6E715466900976E4C4747 -:10F4E000F82A026E3DC958E3ACC0EC29309C8D1B54 -:10F4F0008A01B07A89DB016E65700F0B4C7A03428A -:10F5000000F7B1FE5B59FF4AA8F5450F2B5F55EE9A -:10F51000D615C4CB0EF52F9D6C0C2FFB87783B7353 -:10F5200003CFA7E7C5F296790E034B396BFFCB8269 -:10F530003B5E94181C890AB7EE91D2E374D3A59769 -:10F54000FE87B4D9F3CEFE2B74A316F9D4EC77085A -:10F55000449769812F6EBF6731DCF6294CF76B8EBB -:10F56000D36BBF8CFC51D676C80648A6CA33C7A950 -:10F57000D02393E3ACBC62830AC972FEBD88C94341 -:10F5800005FF155696D5FA635599F080759C41692B -:10F59000BA54E8EE9932E38B8A8ACBE64B8C6FA0A3 -:10F5A000CD42E7419C41515ED6366BC48F37375709 -:10F5B00052BAAD596B27F9F94899DE5E9529877FD4 -:10F5C000453DC5DADDE202E2C3F876486E97B0BF8A -:10F5D000E8F4992CBF666471F54D3AE6A7CBA817FD -:10F5E0004CFE5E23E9C4DF71C6DFA8FF9CF271B355 -:10F5F000CBF80AF6B76AA42C2D433C57707EAF7047 -:10F60000A5BC83B1DFB64123E3D84FE4779D58AF63 -:10F6100062C8505D61E30EABE0FCFFCB31777851FF -:10F620000F76CF7F71717BC528807C071F68A7C8C4 -:10F6300007DAF89EF9C01CE7D39687CF8EBFDA7A37 -:10F64000E4AF35915BDF40BDB1AD82EB0D275C25AA -:10F650000353E1682093DF2A2A189F219D223DF35E -:10F660009933BDBD3909AF321EBAAD394C7CB7AE46 -:10F6700059A774B5E04317F25409CB0B3E84A2D1CD -:10F6800094CFB95EC1525A8FFA4E4B428CC1791B4E -:10F69000F2E7B9F87DB96194B1E695661E5232D3AE -:10F6A000FDEBB0BC94F20694217F9AE58FC40DD691 -:10F6B000BE50D49F243D124F3024DDE6E3F9C952F9 -:10F6C00097112FB3B65F6D18E3D3F5593E555B61C3 -:10F6D000ED8FF55F6585E719AA6FF6572F1D36E2A6 -:10F6E0002CBFCEC7FB6B955EFC5CFABF496A0BE38F -:10F6F00042B3CAD1CF4D663EDE661855E971CA974E -:10F700003E6CC4ADE5F0B0ADBC66695B3CCEF07656 -:10F710002744074B8CBE2553A26160F4F7459371D3 -:10F720005C6AD3F0717CA7E77707C1EBAFE0E555E2 -:10F73000D2EF8D84853E13A4DFC4117ED3BE510465 -:10F74000BFCA3F2FBBEE39C6AF4ABE3B4276461119 -:10F75000CB8C63E34D8B81CEE090C331407DA084A0 -:10F76000D5BF5BE5C0E43F06E75882B32E3A3D07BC -:10F770009C712B9C261CBDC16DC2919B4FF9F84E0C -:10F780007EAABD64EC6FC73316F775B82268E7F53B -:10F79000413C313D001FDE66B8D8F73E5319EE7587 -:10F7A000A2DB74189CD96FD19452485AD6F14F9B62 -:10F7B000AE83313F86F0F61D694C9ABE2C3FD38A4A -:10F7C000C7B1A29E93FFCCF9B933E6F75DDBFC40ED -:10F7D0006D0B4783BDCF6F9D2F323D1AC8ACF74BE1 -:10F7E00089DBD1B593C67E1DF878E061FAAB00C71E -:10F7F000AB4E8F57F015361E76A626B38E5758C7D8 -:10F80000C6F37E76F874CAA309AF2F03DEDB6CF073 -:10F81000DEE462729B85FE9F35BCA72A7F7EA67FB1 -:10F8200049FE2A7B96BF4FBBBF02FC95F1D3BB2A92 -:10F83000A42E60F85A74A1371997D27AEEF3C657FE -:10F840001F2C62F45BF4EB51872F9031C3F8FA4B15 -:10F85000E9F1174A3AC19D8BBF73CD072069EBE7E9 -:10F86000FFD57C72E1F5B3D643A7AA5F97FDC14FE0 -:10F87000FBBBE5159044795A7EF042DA672E7F6E25 -:10F88000623F60FDB85ACF06834DAA40D819CBD14C -:10F89000CEC0FEEB4ECDCEB8A919DA5B98D1F558A3 -:10F8A000284A76D17209A8FD1A66B72599FD32FA61 -:10F8B000F96DDE9901B2AB285DEE02B263463F7F7F -:10F8C000409BC8A6E01F523812797FB9CFFC7E68F2 -:10F8D00032DAB9AB2BD877C61ACB83BC3FF63D8A58 -:10F8E000F5F386F0EFB9E0CAAB64F058F0EE732799 -:10F8F00063D9F4E3976599F0B351D85D37A3DDC5BB -:10F9000014B2CFDF1643BBDA5FECD6B74A99EDA647 -:10F91000CBDCEE5F3FE427717469AC42FB8DCD7F99 -:10F92000FFA5F7416715AE836D868CED23DC35B0FE -:10F93000D1B1DE07D086A375332C4D646BA6DF9161 -:10F94000BFD9AC1FD727A0BD16AAE4E513969D3FEB -:10F9500021612D87111370DD35CBAF5C3686CA4B24 -:10F96000BCD117C7B3F14B98FE4C303C95A86D52F3 -:10F9700013D1333BBFACBFCA3B3DC960587FE91DC3 -:10F98000E55765C113A322D1D9CC97D6DBE56BA38C -:10F99000C0DBCD028F6194718B5EF3F1AADD7ACD6D -:10F9A0007726D76BFECAB6A588E7D27A88A09DBD18 -:10F9B0009EE12F6619DF5769D76F25AA7D5E9FD517 -:10F9C0007CEE04E30AB96FEEFE9DF27527C4666211 -:10F9D000FD12B18EFB2B9352ACAAF7F93BE79B6B60 -:10F9E000DE5F15F864E32CCC36CEE7859792001BDA -:10F9F00067F4A73F8EBFDEAE274F15EFD0B0CDC066 -:10FA00007D359A9AB86FF6415D2445FBB91BC90F45 -:10FA100077BD801D621B35B46B120059F5995AE110 -:10FA20004EFBD3F07FCA8CFC6C7431D3C52FBF530F -:10FA300070C0523F29078BFE9EC77E3907CE39A979 -:10FA4000A4DB83F0F7A9261C8142DBBCDE6F3E56A7 -:10FA50007000FD72DAD47CE861BCED4C8FA6987C16 -:10FA6000DDDBEC851493AF2DCD1AE57FC8E40DD313 -:10FA70007B98FC617A37DB2F62F9C6E608E5EF6C0C -:10FA80001E4BE9EDCD067DBFAD7932E5D73547296F -:10FA9000BFB6793AE5BBF1F9211BAF46F02B9BC706 -:10FAA000908A645C463FED6888303061257EB7C03F -:10FAB0007FB33CE16919FD9ED37DE4DF0808FF8632 -:10FAC0009FD17730B63BA4C076C83DAF04CE8BC182 -:10FAD000F11545E6FE53B592E4C56FCACB7A20BF57 -:10FAE0008A2FC2D62DA672D582BA42E4775F847F70 -:10FAF0000F54AA4974C1048160C40D7C727B39958E -:10FB0000A77CC3A90B15FB1B21F8A3352053BD35DA -:10FB10003B787F4E3E1951BD4B6614036F50E5F59F -:10FB2000927CBDAC1A752B7D6FD5641A77CD06DE3D -:10FB3000DE57C9F8C6C2B7616510CD6367E8406992 -:10FB4000391BEFC7C1FD8306B3741DDBDAE0FA751C -:10FB5000EF9AAD85332D7E24AFC2EDF360DDD6A9DB -:10FB600015AC1E1BD6C0719535FEE4D672A28782F5 -:10FB7000F09DE5E3F007BD7CDE4A0324715D32CBE6 -:10FB8000CF2EE03004B58811ADB27C178A27A827A4 -:10FB900097F9B15D2B44B6EAE9F24AB39D616F571C -:10FBA00069B68BB7EFA7764B583B48970F2B10F0F1 -:10FBB000C0485BBB61269CB04CA676717BBBA1A202 -:10FBC0009D39FF61DB3A24AB9C0DDDD02971B9B1C1 -:10FBD000D32517FF8C0021B7FBE3D249C4473BCFA5 -:10FBE0004B92B7F52423D5D93BEC723D2CE990F329 -:10FBF0000D6E9B1F3D8AB2CBE8B156D06B53537646 -:10FC00007AAD558F1D44FB44D9A1DAF069D269ADB4 -:10FC100057D0B1C94E47934E6B3541C7A8838E026A -:10FC2000EF6B4D7ACDC84EAFB539E8B5D6A457CCF9 -:10FC3000DECEA4D7DA1CF45A6BD26B5A767A39E945 -:10FC4000316C5B8CD69D34DD2294FFACE8E1D40BA3 -:10FC5000CFC93A7D97D71BDA04D40FF52ADF275591 -:10FC6000A600F7035056D88BDD1A17F64913E0BAF1 -:10FC7000700BFE6AB1CBEF75F3FC9589C313D00E00 -:10FC80000F75DBE1FB27A03F6C9328BF2E7182CA62 -:10FC90001F97A33185FA4BF2F11DF8F24493B0811E -:10FCA0008154AE6A175730BE285F2347E21639F0F9 -:10FCB00080892710E737A7C6FF005CFF2078270759 -:10FCC0009F129CD72B84CF24CD3B034EB6BFDCC004 -:10FCD000F635A582BF4B9B189CF0E9C309F57CBDA6 -:10FCE000E85E9F859DE482ECFD54AC916D7A765080 -:10FCF0008BDF96D79714DAF2672C2AB5F15559C3E2 -:10FD0000205BBEB4FE2C5B3E3CA3DA962F9E76AE03 -:10FD1000ADBFA229B5B6F20C7E11F96DCA4B4B6D81 -:10FD2000FC121F5A8BFBB64DA27C4762682DEEDB9E -:10FD30007A2BFFFA55AAE165F8578BDCB4FE300A3E -:10FD4000127E4C7CE56B1077A3BC16059217B1723E -:10FD5000BF66C4C91FA019807684ACC528EF0ADB32 -:10FD6000D7A7AFA1A1C4F8F4EBEB54E8A57FE3E378 -:10FD7000F4DFDBBC9CFC62AEEF4A115F4FD7B1ED04 -:10FD80009284E7224C3FE23AEE62668E2F847C2119 -:10FD9000F887F133EA154D9584FC9E9E9C0D6CB559 -:10FDA000EB9B01717BBEFF62FB7C4E95BF3F2FF941 -:10FDB000ED0D7F6B2112574E017F115512E7D5A72C -:10FDC00027FFE11976FC144F733BE4C4A1CF3F67D2 -:10FDD000FCB598EB0568B5B8FE065AB80FE5DE35F8 -:10FDE000FBB55816FC99FCB2AEAEDA6FB543206293 -:10FDF00099D7A0F4389457B2E5BF687C929C40F63E -:10FE0000F15C36FF72B46372CC5FD07BEDF8FDBE5F -:10FE10007FA5F9A7E9FC83D36A1FEE86B74CA3FD43 -:10FE20009A9977ECCB32DBC7B9BE89F964AB9E6493 -:10FE30003F952AE3B310F82388E7F77DA1E190CF3F -:10FE4000F6875E9E7ED6FBB67BEBF87E26FE725E64 -:10FE50007208E253C471DCF2F2979244F7F132DC9B -:10FE600081E5553295DFE00F6D45B8BEA9C46E50EF -:10FE7000FB22BC6724F1BC18D44E6DEA972CF31416 -:10FE8000769139FF5CF6D1B296EBECEB194CABB541 -:10FE9000F2E39D2D2BA99CD91D2D2AD1EB8B621F3E -:10FEA000E58473A3FA05B68FCCF30167FB7F15FBDE -:10FEB000E8A0DAB0CC6E1FEDE17410E5CFB5ECA987 -:10FEC0003D9572D33EF207DC621FEFB05F2A997D49 -:10FED00084E7470161BF5426C95EF15526B9FD523A -:10FEE00069DA33F6F5EA1A3440C7A4EDA31EFA37EF -:10FEF0003E4EFFBDCD2BD7FAEE0B98F6511BB78FB8 -:10FF000018EE31CE44A9E47E0EC5B1BE8F76E55819 -:10FF1000DFFFD7D847D9E5B737FCAD85366E1FF57B -:10FF200082BF69B9F0F72F6E1FED50E1FF33FB2858 -:10FF3000179FFCEFB68FD274FE74EC1CA75D63DADA -:10FF4000119FB57D63DA27CC8EA954516E999D859A -:10FF500076CCFB72BBF70E369F1B944E2F2E8AB7C2 -:10FF60000A795DAC46D7B968FDEE247FFF06D4E779 -:10FF70007D859EC5F601119FA74600ED9DC56A6C63 -:10FF800083CB720EA1043AB558E08B870766E7D998 -:10FF9000E72FF062E261B7AB40D0BBE99C289FD766 -:10FFA000A38407E8E4768CDAE9C5F449B1BEDD9BA9 -:10FFB000810F20BB5119AB27511FB0F64FBAFADAA7 -:10FFC000F0E2B5E185AD437C3C50A236BB91A7FE83 -:10FFD000D19A84FE7296ED40FEA5F3721DFDC26DAE -:10FFE000938732F8FBC4565C83F198C1972F7E0348 -:10FFF000E31AFB74CEA4F8C696AAEA83B5AC5E7E7B -:020000022000DC -:1000000044BB74928EEB2A905F71157646EB2624E2 -:100010002604C4394E29C06F969F10EBA60176BB0B -:100020005CD655D39F3428B7BCB01FE9A427B37D55 -:100030002EF97059E59AE4F3DA53934FA1F7E3EC04 -:100040001FEA8B02473FF9867D5D088225CFCA3FB4 -:10005000107CCC2C94CF653C0D6EF5EA8C3F5C1582 -:10006000B286F191F9A01520FFF9EB5448A1FFA544 -:10007000E8581C5DB0BDD1A505FDE87C3F0A975A44 -:10008000F613413797D7F0AC96F215ACDF13A3798E -:10009000FC7D1F8DFD579D399FD542BEBAF3555B40 -:1000A000E9DC34C1F86910DFDFD03D825515BB347F -:1000B000AB9E1EE1966CF7082CFB365DAD11F63455 -:1000C000C38F52211B68077C52FE503E267FE44DB1 -:1000D000B1DB09A74BAFF1E25EC5A9F2C7271DCF7F -:1000E000A46BA65C2D1574ADF7A2DDBF223CB5C78D -:1000F00073D44CBADE4A74F5578091CCD2FF04B762 -:1001000094357ED6B93F72DAEB4ABF9AE95B7AA2A0 -:100110005B91D3AEE5FDFA162BFA5F5179A91AADC2 -:10012000035ED1DF2AFDD638EACF13A813193E9417 -:10013000B6912971FE18D9CEAB50FC874F37489F36 -:10014000D279774D1A3E77997DBFA616F9ED76E103 -:10015000F4B86485DFB7D84D7078713CD4D31AD029 -:10016000B9A71AE0FEBD8CFDA3C36E5859569D3544 -:10017000CE40FDB4F6ABD3ECF09E72BB80AAFFDD9F -:100180006C93454FA7DBA9F0778B3DB506F9DD42AF -:10019000FF152ED823B1753811BE0C623ACB6351CE -:1001A00009402BA6E3900FABB97DB743A2F36012D1 -:1001B000691DFFE3E74457B875EA47F6C6084F4A9A -:1001C000C000AAAF9FDA39D2FB0378DCD220096CD9 -:1001D000F51F74BBA95C8528609CE2FBAF5C14A68C -:1001E0007E0DF6A9260D87B3DF2BDCB107DDD84ED7 -:1001F000E3F060035AC7C772BF40D8CBDBBD3F7383 -:100200002AC571E5826F43333F5FEFCE8BB82C6810 -:100210003DB5B8AEF7D9981D55C4FF7EDCD7421B5B -:10022000B787060A9A6D595248DFB7B4F42CE777BE -:100230000939DF8CF69187EE55D8E47E9B8837DB51 -:100240002E81ED9EC5100F8FCF7A4BC8FD166FDC47 -:1002500047F7159E59E51B8AF12E8794888FE1A1F7 -:10026000E22AA330D6031E86B4D9E5ED74E33B5EE3 -:1002700076678FEFC8D5DE8CEBF8A47821DBAC1461 -:10028000F1303B41FB96D405249F25826F4AD8FE6E -:1002900005F5D0C0382475ACFBE149B0F207FBD9B5 -:1002A0008F7E8AD27A3616D22B26D3B974E9EDEE38 -:1002B000A44CF2AEDD84EDC387141E6B0846606665 -:1002C0000DB12AB50F2BCF4D40511B2CEC33586389 -:1002D000BF7751B6C47E5FAAD4714F228CF65D08F9 -:1002E000FDAE967AE59F9C1E210FA3C7D99F3F3D87 -:1002F000B6A9865FB3B4AF9020DA9EA5BF0A0FB748 -:100300003B2AD6ADE77160F50178D5B25FDC2E19D6 -:1003100085B8186C6EDBBA14CFD9E2F51019C2F0AB -:10032000DDBF01642B1F8FF2E4513F2E30E26732B4 -:10033000BC2DFFF6659D4F215DC7834D8F65D11F95 -:10034000A33C4C5E5C455C7F6C6B9BCAD30F155A1B -:100350003FC24B20B98C8158178B2D7521FDE702C8 -:10036000C5A187EB9BF6617C754903447018C6579D -:10037000C45FE1E99034885FE05098F1C7003E1512 -:1003800018807C81EBCF224E5F932F4A1BECF76DD8 -:10039000C2F5F67CB1B0FB8B9DF7B71CFD94E8FC71 -:1003A0001E94BE4406BCF707D3ECF76DC2D079FFAC -:1003B0008F10BE0381480AF935EE18C7D1BF0AB1C4 -:1003C000CB3C0C9F8F7D7FCA2FCF64F57FB8A4B63E -:1003D0000FE2658B379A4FF78A5AB3C79D65F0AB2A -:1003E0006977E4A89FD6A3715B5CB3335D31A4F851 -:1003F000BA590C8E55410348AFC5AF20FDAE08F980 -:100400007DA6E4322FC6932E0F54537CD83ECCB336 -:10041000747978683F6BBC9822E277CD7C42E853D0 -:10042000E778D77BB81EFD3B18D7231E467A62615A -:100430009CB72B5CFCE84C9DCE0B8D649676733C90 -:100440007E6E5FEAEA3FADF8670BB8467208705AF5 -:10045000FE85599E582BF267BC966D2790FF074189 -:100460003281F46F6A137EF7EE7A378B7A71BC773C -:10047000D95D2FD606D67D27AB772BCE87D5336CAB -:10048000F5A219F5EE14F5C036AE9131EE26133E05 -:10049000B0F617C9E86F8BE88FECC1EE7A7A467F29 -:1004A000F789FE0C5B3D2DA3DE83267CB671C13E31 -:1004B0006E77F959EE6482F4368FA7DF3F6412F14C -:1004C000CB81219326CF62E35CF70B97D01157D2F3 -:1004D000BA6DF2D53E51AF05F9AA8AE2F05A1BF087 -:1004E0001EB0B8279C084CF5C62CDFBBF92A305546 -:1004F000CBFE7D96ADBEDAEA0363147DA7FA2D1F0D -:10050000293CBE395E5087FEB89545B28877FE5BC0 -:10051000C250991EEBABDAF2AD615E3EDCFBB74434 -:100520001CEF14897B304C573E596591EFEEF13F3B -:100530002FF8C579461AFE77134685157E9E37E15A -:1005400037F3DE125E5EDDFAEE44BC5865DE03185A -:10055000DCDAA785FC175FD8F9492DF6F9F17C7A2A -:100560007E3C6FCE6F74AB54F7AF35BFFC163BFFCC -:10057000F17C7A7E3C6FCEAFA635FFB4E6E7AC8760 -:10058000F79550CFAF1A725F18D79D55B890B27ECD -:10059000C7B6BE9058CAF237F535ED6D9DF4FB48ED -:1005A00030CEF28EE9BDDDAF30F8AD2FC6ADF2F33F -:1005B0006018E216E7C16D61F473BEE6D1441C1DFC -:1005C0008753F1DAF30331DF379D67BFFC13D7613F -:1005D0000C53E4FB49879EEF655D5B5EC2D79315C4 -:1005E000C1886C5DD7CC38E867FAD690FE49685C64 -:1005F000FFECEB2BF451115BD7B83F8FEABB84BE05 -:10060000BAB599BF17D026EEC3268AAA093F6DE670 -:100610007DD8F8249B7EDB3F61D241F45F1D3FC44F -:10062000DF8978C2CBD7BDE5CDD0CEDF3DF0D2BDDE -:10063000EEA759BF3156612FB3F730FD29B3F7301C -:10064000DDD31CA6F427CD3AA5BBD8B8983EDC1C58 -:1006500081181B7F67F3584AEF14FBABDB85DFF78C -:10066000CB4532F92DB634334BD985FE5F2FA5F734 -:10067000346B6BD421E8FF0D53FEB834758E97F6BA -:10068000AF9D897C06E763BFABA07BE2E38B545A46 -:100690007F414D29F9A3D3DF4DBC1E976A1BB0DD06 -:1006A000B96199D7F32613A1ECF5AEC17A63C32AD9 -:1006B000C10381B8122ACA5AEF7BC85F3501D19FA6 -:1006C000164B04B3F77723F6571D10FD15E9894043 -:1006D000F6FEE2D8DF708DE301C29DCBF2B2D75BAC -:1006E0008EF5AA3431DFB2949C977DDC9BB05E61BD -:1006F000611BDDDFB96006903DEA2AD2B790CF4298 -:10070000D44BF68D82CCF8BCB04F5B13D63B3F1672 -:1007100081416C7C3D140199F1B32BC0CAABF02E22 -:1007200039EB87A5E74D63E5AC5E12CBBF6429C703 -:10073000F62C1D375DB4CFB7979BE3B95AA1FBFEEA -:10074000345E1A77B5D8F3053297CF075AAFA8436E -:10075000B92F10E74FBFC63C1BD7B5044C7DC4EB87 -:10076000FB79F95366FD102F7F45E40B0BF9BC7D37 -:1007700093BC142F7CCFF5434B6655A5E73BE07B3C -:1007800095C36659E677CFF7CE2D991548CF67C048 -:100790000DE387CDEA61DFD367B2DCFD2609EAAD60 -:1007A00082B62AD29F233D51B20F47F6AB31509EFD -:1007B00095351CAEB7BDE52DCB54822B4EF73405D5 -:1007C0005C772FB0C3D57FA11DAEBB17DAE1EADF9E -:1007D000D8335C4F78B95ECB051F1BDFB08EBFF9F5 -:1007E000DFEDE39FF17DFBF89BBF6F1FFF8C1B3F8D -:1007F000F1F8292B5D365D631FBFEC5AFBF89BAE09 -:10080000B58F5F76DD271BFFD3B2C7CFF7C6FEE9F2 -:1008100015F6AE62B53B9B6236FB94D53B29EAF1F7 -:1008200073F46E7B3C66B34F593DD527EC5D5BBDE1 -:1008300068463D9F4FD8BBB6718D8C7143A2BF9463 -:100840006CED2F92D15F1F518FEEADA4EDF18CFEB8 -:10085000C2625CC3564FCBA837C084CF362ED8C7F0 -:100860000511077603C6814942DE59FDC533D83EDE -:10087000BB1CF7A15109F7FB5A1F1879807D87C16E -:10088000FCDDA382498B07E27A2E4D5A7C26AE7F8F -:10089000AD0560DBB74DF2713FC2189F42A99607C4 -:1008A0004DE4BFF336955C6AB9F7BA59D4EB2E0F15 -:1008B00034957CC3527E9168DF2AEE0DD6F97E4BCB -:1008C000F688D69FD5CFE237BBD8EC4F944351A4DE -:1008D000C36070DF79C5D43156FDBCD9E7A2F96B8E -:1008E00003C5B865D9E16A2DE7E3DE83E306F0BB13 -:1008F000697F349510BE359E9ADF6F0FCE96FE8AC3 -:1009000058DDE6A575DD2DD6F50277D38FCA191C03 -:10091000890132E0FD8695653DFB735A9AEDE70B40 -:10092000AA163570DF573A57AB46F1C8D5EEAEC9B7 -:10093000F2E46CE70FF5623E2D736BDBF0BE0E1C2C -:10094000B0FB71198383F53EF215EE58BD2F9B1F46 -:10095000B7C56BB36F0A8A7BBEFF65DE93EA9E075D -:10096000EB281BDD56FBC4F9C821AFCDDE2A289445 -:1009700069DF79A28A9F1B40BC84FC84DD782DADA1 -:10098000F55AC75FE518CF07530D5C077099427998 -:100990007157F07755FC456D5AB98EFE830E3A0FAC -:1009A0000471DFCDECB7253C95F6E327C43D5835FF -:1009B000DC3681FB1D057C9AD055629CD20D2AA4A1 -:1009C000FAB0B15DB1D5BE3156BAC5E95ED0FBAE65 -:1009D000E4C5F4DE5339A3BF9439FF3B7CDC5F7C74 -:1009E000973EF5B7E559E87B373A8B2DFD967EE0CB -:1009F00086D4A8DCF5D3F5385CDD7C1B66FC8AF276 -:100A0000AF0BBE751B3FF4658BB730F58338079F7E -:100A10003516C48F7EF99FD83CAE3EE8E2EF2E88B3 -:100A2000FB36E6F9D0D5C26F3A4BF85DEB211AC21E -:100A3000C2B741A67B496FC3EF42A32CF47FD2E734 -:100A4000E670B5BAC8DF659EFB5ED5E6B2F9C3E6CF -:100A50006CB0E767C3D462D45BB3D7BBC8BF76B50D -:100A6000C34FFBA098EF1C685A8176BC796F7B96C8 -:100A7000062ABECBB3E0F17B6AF07ED47E1FBFBFF7 -:100A8000F726E31BDD226FF3024937DE037875F7A3 -:100A9000A8CBCE036C9F5C518AFAB600B2BEFBF6BF -:100AA000DD563B7CBDC1EF841760598F70A83BA415 -:100AB000ACFEAD0E9F794ECCE9952BCEC38CBB38E6 -:100AC0002EF8A8DB0FF3E73CE187E1F117BDB57F16 -:100AD000BF97F60BBC9D6E949F46B569B224A7CF15 -:100AE000A73CAE98D19FCDD3B56742AA3FD8EAB50F -:100AF000F65CEFD824207DD914453E32EB2D045608 -:100B00000FE572EFA5715BBD0A566F70EE7A5D421C -:100B1000AFFE7CE7BD6EF447BEFDC0E14B502EE753 -:100B20003FA980978DDBB5330829DAC726DDB89F4A -:100B30009BB75BC97A9E4B1103ACFFF93F0ED27A8B -:100B4000396F97273985B59FF793578703C343D7E5 -:100B5000B263CFF6C775F701899FABC63B87E3BA8F -:100B6000364F85EF44B3F4D7D7CFF9F0C81379D314 -:100B700091CED28E7D5752BFED97BB3C167D11F0C2 -:100B8000BBCC7ADC1F77BF941C92459F98E76047E7 -:100B9000EE97387C7B5C491FC2B7638B3BC6E0682D -:100BA000DCF10EF1D5C41F3F14423C34EE516C7E93 -:100BB000E2C61D4ACA339CD2C31EBA8F6A04A41A65 -:100BC000C427D78F0B772F20FFF9C2F6D5EF282146 -:100BD0006C6FE76F8697480AF1FA82129982F9479B -:100BE0007F14D219AADEECD81E42BCB27E67BAF3DB -:100BF000F11CD8EEF7C6FE3F28CCEC0FE0981BF9AD -:100C0000ABB17D151F6FF7D75E43FDD2E890A337D8 -:100C1000F19792CC7397F3FD8E73B01D7D4EC9BED4 -:100C20009CFFD089CD7136EE915D6F6D8E33F81BD0 -:100C3000FEFBDDCD37A21DF4B44F433DD0F8C07F9D -:100C400086C0B26E5EEEE7F2D875FF8FEEBB8BC941 -:100C500047D71F3DB47E743DF5DA193A9B77D72309 -:100C6000FFA75867F5173D7521F90B163D36B15FA3 -:100C70004FEB27F26BD2FA2E99B87FAEEF61E3F417 -:100C800063D9BD2275D0E799DD0AF8189C6FBFE8DB -:100C9000A17B528DECDBE26AA4D702D2CB985FC273 -:100CA000F0BC70E7CA7794E1D9F01DEF2FE3A503FC -:100CB000606218467A7FE3EBE78FC6D445E72B8D59 -:100CC000708CF4AAB35DE32146D711B9E978023EEE -:100CD0007463DC4AE3CE557CDC7646C750261DDFC4 -:100CE000C65FC665D2F17B0E3A9E80861FE2F92070 -:100CF000ECEE93F55CD83C3F5BF0D8377BB4B74C57 -:100D0000BDD01B9EE74A1CAE5ABFB1C28FF2B5EBF5 -:100D1000C1FBEE2AE2749EC210D3F5D08933F052A3 -:100D2000F7EBAE6357A27E3CF69447C3F57EDE53E5 -:100D30002F90BC753DF6BC5B27FB1B0212B337BA84 -:100D4000A0FBA703ED8F8512CF346E0BA63CA13418 -:100D5000BD16262F9DAC87E8FB61FA9EE472B03089 -:100D6000B96F9A94857E4FFBF97D6E48F625BC2CB1 -:100D7000D8F627379D835BE82A8D457A1E9E84DF4F -:100D800073D1D39CBF86F33FC742D76D5C7E73C9D6 -:100D900069D7168F8A710D4E3A77B9F83EA131297D -:100DA000BD908DEEE63A78BAE7AA4F38E55BCCBB4A -:100DB00037F9EE7D3EA787AF1D7EDDC63726DE8E76 -:100DC0007C985DEF1FF24B028EA6C9A58333D741F5 -:100DD00015A2F1FEE569788FD0DB642C7D40A1F788 -:100DE0004E57B43F43FADBA92716E6B0B3FF26F40B -:100DF000D3C23DFB86A33E3BB2FF09E2C7853B0F52 -:100E0000BB717FF3EC8E47DD9D5569FEC775C1FA56 -:100E1000BEC59187F70D27FD8DFD67A1CF71D17FED -:100E2000E35E7BFF8D3BDFB1F53F3FDEEE26FF6AE1 -:100E30002FE3BCA91A97E37CDFEC7001BE9BF4663C -:100E4000BB32399B1DF4825817BBE36A82352FA24F -:100E50007F522974EBA8FF5A961A2FE0BB89F1E75D -:100E60005DFCDD4AD578D1C3E43351E0D671DFDBD8 -:100E700012BC0C748B1E6F73E0532BD226E07E40A5 -:100E8000AB8B8EB6EEBF4CF80B0CD906FFA2E0E49C -:100E90007EF8DE15EEE3747C27568D70FF7568D200 -:100EA00064BAF7A8C99A2FEBBACDFB43BF1DF2BFB6 -:100EB0004B9341B7F0D7C889979D8D2E3B1574DBB6 -:100EC0007E605D1D3F0F36E7BF6E006CC2C723D644 -:100ED000493CDE3F7E318F3334ED3B70DCFF72DA0C -:100EE0007B60183AEA2352473A1FDFB0DC734EC7E3 -:100EF000F1822E533C738436012AC42808C38B71B7 -:100F0000B68371DFD54E6980A9374CC7E70DE2FC87 -:100F10000DC7287FEBE4BF50DC63515E74645E5FF5 -:100F2000CC178A771452B4CF13CF06809C5756D271 -:100F3000933E803AF588D59FE4814DB49F4177E692 -:100F4000C93E69BC98F17666BFEB7CE3255C8F7087 -:100F50009EFDF19D367CE4A8989F1FF0791B94EFCD -:100F60006BE61DE3604DAD462CC1249A31C935189E -:100F7000CFF7DB249C5F29B4535A061D94167A35AB -:100F80004925F85E267F970C7F8193790EF84EC134 -:100F90008E77DADF3728FA4B3146C784D8E76C2DD5 -:100FA000B0C7237D3B8FEB996BF26433FE3966DD6E -:100FB000B725A08170E02BE2CF9375CB415EECAA00 -:100FC0003C0B9F29810E1E5FE6D82F5FA82CA1F352 -:100FD000FD95E19EE3BA968BF8F05CE56D7DBD333F -:100FE000B700C1CFFD609297C7791BA06B567EC436 -:100FF000589E1A6BDCA4617B4FC7857CA8209EE3BA -:1010000094FA50AE589A877CC5E8B05AF061103A0D -:101010004527C7C8FFB1D91D4B201FF6AB88493CF7 -:1010200098282A71BF9AA158F940CE9B51D253DC1F -:10103000164C637C62899BD92AE8A2AAA0FAAB115C -:101040009E4D82FE4EFEB4C7C19A765D40E43C22BE -:101050001EEF67A37F47EF8CA945018A7F098C6E3D -:10106000B906DF6F55A14943BD1A30E35BC47D0F5C -:10107000735FED7CF7C5E3888F7589FD7B46BCB84F -:10108000588FE97E5C16BBD9B91E3F98973DCE09B3 -:10109000C6668F4B34EDB48FCBFFE6FEB3C1DBF1F8 -:1010A0002C01A11914D7A90ABFC584691AF9DB8FCD -:1010B000EE94F87B1B0E7E3ABA2B7F387F6C47A3E9 -:1010C000F7CBF3C47769E7BE7D685FB584C0282895 -:1010D00024FDA72B0CFF2BA4915E89A50B76BFF3F3 -:1010E0009B27D18FBF57017CD7ED289B6307CE5339 -:1010F000350A906879B0C646E78F3BAFCC734C2E6B -:101100007FD76AA6FC05A8DDF19D12DD1753E0EC40 -:101110003BF1BDABC6832E48B2F2E3C0FB3DBE89B6 -:10112000DB0D737EF1680D9304D820E0C1F5CBBAD6 -:10113000CEF499EC07DDC22761735D881B1DF8DED4 -:1011400073BDC04FDF68A1AD9E39BFB7664D3E4845 -:10115000FE9F187FFFB9DFF4525BFF20FC233AFBB0 -:10116000877C99E16790636EA075259A9F223B88E2 -:10117000EDA771FF91942208B7D39FB2708F44EB13 -:10118000D9D56C3DC3F7D8AE4E3AF6A38E782A1364 -:10119000FF4EBE9503C28E0C4020079E23A9D1743A -:1011A0003E4B7277ED2F14B2C7AE7D484A523C7564 -:1011B000E799F9407857C82FF51A34DDC1569834AD -:1011C0007F3BF0E709DBF1EED3ED78CFABB4E3374B -:1011D00018B1E3D189E7FCB1836CF5E72B0D6E62A2 -:1011E0003E81EF4AF60FF1CDF424CD63219B474AAF -:1011F000CFC4E7DCBDEB56A0BFA4573C3AF07796CE -:10120000037F2760EF3E5E0A516FB125FE534D917B -:101210005C39E5D0C45399D63181BE4582E4A70E2E -:101220008B4EA47ADEAED4DBCE85AA3A427268C673 -:1012300029E775AFABAFC249965E77E981C3B320AA -:10124000B7DCB5377B23F52E3C1F8748FD103C2FBC -:10125000D728DD84F547F4B4DE1A349E0B221AA693 -:10126000B7887393A355FC5DA4F6D47BC568FFDDF6 -:10127000527DEC12B4FB1BAF8228EAFF6490AFBF33 -:10128000BB455A17E471D637456530D05FB0574932 -:101290004AE887D28C5F5C8076DB5E974EEB9F7668 -:1012A000EC37FF46E5A3343CC72891DB46E2B8ACF7 -:1012B0003EF9FB8FEE7D35F45D8B7DD4B5E7B661ED -:1012C000B83E6D94616EB67D407D808FDF55F99795 -:1012D0006264CB05DE63B42F5FD969F7B3B9777366 -:1012E0003FDCC23D97923D7A60367F8FF3B123FC9D -:1012F0005EEA2465C657BFC4F2E3FE53BC6304C66E -:101300009499C53C9403E999F0313C333CAE17F114 -:101310009B8D7F95297E73DCF920A1BC8EFB23D0A9 -:101320003DD4D14DB369BD7A3234E920A6757B2511 -:10133000F21F351EE1EBDB980EBB9FE89C3AA61727 -:1013400058FF357BB97FABA6939F0F9CF3A2BDDE00 -:10135000B84E7BFEBC5EF8775940AC5B21283E9DC1 -:10136000F8DCBD2E6355809FA7D1BDB2889A7DFF62 -:10137000D519E47618C307CDFFE831882C63F3381C -:101380005A5F3A01EF291D7D8F9F371CFD50999CB4 -:101390006D7FB539C0F965A39B9F1F6F9C1D482EBB -:1013A00065F3D83F7BDE40DC57FDE3DF6303B59E8A -:1013B000EC12A622645A138D7C188BF2D1C2EFBBBB -:1013C000415B49B6F7934DB930E5C4948F92D9FE8D -:1013D0005836BFE8A020DFFFD5CEAE94307EBBEB01 -:1013E0006989CE98BA9631B87AC0631C96F5477869 -:1013F0001AF7BC4B7E0AEFDEECFEEEA703219A7FC4 -:10140000D7B2F8D2F318BEBEC7843B8EF2E06E2B83 -:10141000CFD67F1CD693FF6A7B80F3739797EFC379 -:10142000416D2B991A44399978F10A06E75D4CFE13 -:1014300070FDDEE88A10DCF10540EFFF81B85F58EF -:1014400076096CB9C9B25F3B18987008E97D28C06D -:10145000E38FFAC42212C21DF9E8FD10F67FF403EF -:101460000FD1AF54F88BCC764703E21C2E68FC8674 -:10147000F8656E1129C5482C14A91F0530620FC3E9 -:10148000B7457FA7E916A7710A634C0732780A03AC -:10149000323F0F63FB34DC7F3482F913A7FD8A29C6 -:1014A0007F78E94DB5C4DD4B7BA55490E9CFD1DE03 -:1014B000400AFD328573657C8387D9A35EDE5F8732 -:1014C000DD6E450D8CFA177500509EEF8F4C7D6CCC -:1014D000EAF19602AEFF5AD6A9A41F37A99D3EF4A1 -:1014E0004B971B7AADCAC62D54758AB7183097CB67 -:1014F0007BDEE07B0ABAEDA2F3001EF948C9EA1FC1 -:10150000393368E22BF60FC4D7F083C7F6A37915F9 -:10151000F1411FA4F72461F78C7B5BBC8B28EE198B -:101520003476DF23B0EBA38D3E61C740DBEFF1DC07 -:10153000FE89BFAA747FA05BFFCC9E44EB2928558F -:10154000CF207F9DF72BB13D10FA87EDF6082FE7EE -:101550003C174B201C4E7D3316985E927AD73B4E3B -:101560003A3323BC3B5FC69032EA2093334B7BA7D0 -:101570009EEA1714EBACD05327607CBF0BF5343FC9 -:10158000552F8E3CE3B1F08FA9A7D2FC9424BC3A2E -:10159000C791C0DB9DD706A37E794E413FCAD109D2 -:1015A000FCEFFCA4841C15BC97BC18F961FDDE8B14 -:1015B0007CC8F7BB0E4EF4A2585D1BE6F7CED47D77 -:1015C000D3E220D8C77AAEEC02AF1EA8447CC88410 -:1015D00007456379CBF8C7DB2471EF52CF9F96E5BF -:1015E0007D6C33BD36CCEF95ED3A38289FEF4753ED -:1015F00044F76EBE17FE0B532E4C7E77F2B7290FC1 -:1016000009D64AB6D8118AD42EF68F763F4242D8F0 -:101610001109F3FD997809D9878B847D98080C5DB1 -:101620008D7FE6A02555ABE1B9C7A2E0208AAF5E69 -:10163000D497E3CF890F336DFC80D98B9638F84669 -:10164000F518F9C71A3F70DBBE9BF8CD851713BF9D -:10165000E7227EA58F8FDF73829CCE4E3C7FD2F92E -:10166000975D3B36EB7DBE7F95F99F07B1273BC960 -:101670001FCBEF9398FC66EA8F9AEB5A13797A5A4C -:101680005F98F7414CBD63EA97731ADA9EC9CBA203 -:101690003F9C7A23E2D2BEBB86E12FF2B300BD7736 -:1016A000E2D423EFE12F25E477BB3BC8E07DE4D90A -:1016B0003765F49B3CF6533677561ED957C7FD82E3 -:1016C0001DA776DE65DAADA6BDEAAC67DAABE6BA91 -:1016D000639E37FD3A187B00C797F630790A617C24 -:1016E0002CDF271F0CC41EC2EF790C663FC60256C2 -:1016F000A6CAF97ED62EAFB9E433CF217FED299566 -:10170000D6BF385BFF8648997098E3D707C5BB0200 -:101710008CEBD0AE29AB013ED842FE6E40D970882A -:10172000E1FA8CD74B719EBF1276D97362BD31D36B -:101730008381E80184DFA542DC53FDF1E136FD8BB6 -:10174000BF0E1AFBB13FEF6483E6D15F8308DAFB7B -:10175000FDD57629C2E0286CD0A56E678FB9AEB3EF -:10176000FEFA4FD1E9DD8FFE78A700EBA37D9485CB -:101770003E7F0EF2B8A605DECE67D1846F9CD234D0 -:1017800039D4C3F97AFA3D8488F073D9E3408E3EA8 -:10179000F5C2003CFF7CE507EF06F15CEBBFD463CC -:1017A0004184F3F525BF0FE27D885796F0FDC7957C -:1017B0000E3BE784C0DFB450F44890A5DF69FEA873 -:1017C000C6F60EC9627E3E737552C14D6937BFCFF2 -:1017D000DF9147BE3D33BFA0BD8F2D6FF2E9020FF1 -:1017E0008FDB72CEBF2AC4E368AEDEB9C5DD5FC74A -:1017F000F163FF8DE3BF2EECB8D77707C9FF61C255 -:10180000336BE74837E2E1BFF67AC4B97F878BE3F1 -:10181000DF9882E77331410A279CCF3E9D47FD5DEB -:1018200075BB4276C74C36D662C6DFB1BD57D33ED4 -:10183000DC398FAB5ED127F563F4BB6A9544F62A99 -:10184000D65FC2F821B678259DE339E73933EE88B3 -:101850001F11768533CE64CE5E7EFE5E0FFAEAF10E -:10186000E559E24EF65E4CE76E737AD9F7948784B9 -:101870003D5103E760DCFC09A85A5BA5F7BEEF7990 -:10188000BD192888ECCD662FA5479A359E0AFD39EB -:101890007FCFBE6789CFD48E1A94FB5D075FCDFBE7 -:1018A000969ED6E35FDEF2EE3377B3FC28E07E1E31 -:1018B000D3DF3E43E0FD02A1CFE7087B61D4073DC3 -:1018C000EBF319888FE199F09A7A7C06FEBD410B03 -:1018D0001E4CBDEEC4C7F18383F3903FEA42CEF3C2 -:1018E000E64F86975CED1628D9E3194D393A12E494 -:1018F0007C5DBFEDD215A56CFCC453AF9DD1C9F57D -:10190000C421D413269F0234B9518E9DFC68F2493C -:1019100037DFEDBD99F064F20793ABB038E70CE325 -:10192000FED0C97FBDC53775B93ACF40BDE0E4B33D -:101930002EC7BD6833BD2CC4FDEFF5BA3109F7AB36 -:101940006CB959C1CF03B93E7A5D6D7BF64694D729 -:101950006D5C5E163CFED04F500FCDFBF1ED21D4F7 -:10196000436FA86DC5385EC3F6E5213C577F5D8D9A -:1019700087B0FD1B49256BFCE3CE9064BEA7618B4D -:101980009380D6F82528C7FFD8EED2F01CAC71871B -:10199000879FBBEFE67863797EDEBE3B7B9CC4BC51 -:1019A0001FDD5EACF3B85B7BBCC43617F92FD0BF2C -:1019B00086C3E43A2FEE3E7F6EEFF93CBD71B788E7 -:1019C000B3D97D71D67809332EC1C9C79B1CFCCB16 -:1019D000F0437EBF38838BDCEDE29C3C71FF9DC3FE -:1019E0000F33F88E6CFB5548AAB2FAE3F979FCF193 -:1019F000F6EFFED02BE7E6DF2EC1EF697B229935AB -:101A00007EA2C1950AE1BEAA618B8BF6810D0F29DA -:101A1000F45E1DFCD143EBF9FC877EF68773197CDD -:101A2000F31F71154DE1D3A03809935EDD712C824F -:101A30003EF31EFD193F5FD6453C8BA0D3FC47F615 -:101A4000B9312EC789CF89EDFBDC9D8E3808A257AE -:101A5000FBE149749FF0FEF7DDB8CEBEF1B404FDA2 -:101A6000CA33DBCFDDF2B310EA0BC413C50108BAE9 -:101A7000E58E5B4A5DF2D3D1548FFC76BDD17109FE -:101A8000CAE218E2F7877FCAE098FB9287E2A7E6EE -:101A90003E7C1DC519BDA63671BEBF677931AEBF8C -:101AA000735DF1628D52FE7DEEE6EB891FE73C7FB0 -:101AB0007DB1B88F54C2FD3DF1129CE7559BBE49E4 -:101AC000F39C0D31E2C7B9F72851F4B39C5061F291 -:101AD0002359E466683E979BD7B67AF0311D784D5E -:101AE000F839E3BF53C4DF8B749E57F177634E8898 -:101AF000FDF73F43DDE78D5EEB7EAC71DBCA0EA4E4 -:101B0000D39B038C7E1AC513A87181377A7F5D79C8 -:101B1000FEC27E42BFD17B37A61D3411BF63FD0ECE -:101B200017BD7B6369677BB76691189FC1ED9746C8 -:101B3000B0B438BB1FF49BF9921907CFE36F4C3E4A -:101B4000CBA507B6F17896F70E713D83713954DE57 -:101B5000E14AF5B3C5E3786CEFA2A4E34C5C42CE56 -:101B6000EDE50C4E8A97E9C6EFD312FD3D08935F71 -:101B700066AFF7D8E3F3BAF9C7F96E8F3D7E668E8C -:101B8000C32E33D38CF53FDF715EB7E9D4E2671A19 -:101B90005C498A7F6AF8A387F6270D0FB9A2889758 -:101BA000B7763EF3876F31BE7FABDD9463BBDE75E6 -:101BB000CAF1DC5D63209B1CBF158840563966DF87 -:101BC000B3CA71207DAEA1C367AF77E7E4D0BB5F36 -:101BD00075E093D90DF91847FCE603F30792BFC2ED -:101BE000815F53DF3AF5E8AB219DF09C19EFC7D731 -:101BF000FD743C26C7A3C99FF31E5C40E374F3B198 -:101C0000C9A7261FE7881B73E2D3599E8FBEB33145 -:101C1000997E91782D54E2DF694AB881BFF726FB9F -:101C200023C8BFBD9D77FE36BFDC7CFF6D04DF1788 -:101C3000F2F3CE4840C3BF5881F7E5946CE7EC91CE -:101C4000897256FBFF07F9DC4E42B72CA68FE7736B -:101C5000FCB52851E1C86BA77B0C74B68A7016845A -:101C600048CE5C224E85F54CF7D12379F2BB3AEB96 -:101C7000E3AEB5072E52D13F3B4ABE6E30CBEF5A92 -:101C8000FBE2452AA377E43CF9D1412CBF7BED1F51 -:101C900079F90879948BB1EA8EF84B17D5B1FC42EB -:101CA00031EF85A69FA4658CCD4FA2CA87EFC0F304 -:101CB0001CF5A7FCEF11AD6672EFAD4E9F33E779CF -:101CC00020EE63F93C374B597E45F9EF57E026F299 -:101CD00057FED8867CC257AD8E783EA279297E67A2 -:101CE000D11317521CE9E3F9DC1F7DF6A3E7D1DF1E -:101CF00075FC0CE1B83FBF6F6E385A5CBC9F23BBCC -:101D0000CE9E88783E7B20FAD4D2F4A85675FAEE9F -:101D100063688F73BB3F8CF75B12056EEAE771C196 -:101D200067A79A9A712F4A1EE70B255F6E7A84A5E2 -:101D30004F0B7EF88F7CCD5C8768DF7DF4A97E5BDE -:101D4000F9BB31C7CE407A2BCAF13FA3BD79ECDB9A -:101D500079F4F7475EF273BCBDE4E778BB3C7F8D56 -:101D6000EB2CF6BDDA7BC675C8F42F493BAFC774C0 -:101D70008B16FB25A707A4B0DF6F5DA9F07E034D8E -:101D8000417C374E32B81D2E31669AC1F0913040F9 -:101D9000770F4611B6C77F284AF5B1148D1FB48D51 -:101DA0000F656CDD64727EF9384E2F865B5A475F93 -:101DB00018CBF3267CD39383129D3AC1F327846713 -:101DC000A4273900F753DF626615E77BFBBEBECB65 -:101DD000CFCF37BBB0FDF074FC40E3DF64DACF3621 -:101DE000E21C58FED12320FE5E217F5FC7F47B8C6E -:101DF000FBF5B5E4FF1EBD673E8F3311FE2EF33CAD -:101E0000BFE6003F9F73FAB7CE8335A44FC739F4BE -:101E1000E8797BBE4AFAB5B7F3B97F987AB5144A28 -:101E20004FF37CEEA3FC53389FFB1F7622B26E006B -:101E3000800000001F8B080000000000000BB55A56 -:101E4000097454559AFE5FBDDA92AA54AA2A45082D -:101E500004E34B0224210B45122004D42220D0316C -:101E60004A801681F64881B298AD98B4DB699D43EB -:101E70008520D2DAA319756CCE69BAE785D611250B -:101E8000E92924D1E05432C52204254E9045A01DF5 -:101E90003BED7423DA64313D824BF761FEFFDEFBDC -:101EA000A82541E93E67C8E1DCBAEFDD77DF7FBFF7 -:101EB000FFFBB77BDFBA4409600CD03F1D2403D47D -:101EC0009BF19702307C3C2311F200F47A00D9098F -:101ED00060546428C1F62AFDBB0DA06D338E338596 -:101EE000FB6F252A6C9EFC53F6FBC1462DAC868207 -:101EF0008879ED7CDEDB652B4031CE7F1154533A7F -:101F0000C0B4BEEC9FCFC1BEA1DB002ABD979EA08E -:101F1000FB6775AA1F459B71ECD74521BCB435CE34 -:101F2000560053F195293A50CC6C5EB88AFFE39481 -:101F30007850B2C37D4BB633AA2FC7DB764122FE61 -:101F4000F07B7A53508E227E0B12DCE3A3E679DB22 -:101F5000B6A89BE42EB2AFAF20B9134B32A2E681F4 -:101F6000E3FA4FFAB09F8D7F573300A643656208AE -:101F7000E52F844A8F84F2BA3F027708E59F718A81 -:101F80008FD39E7387FCB217712CF928FA7A2944F3 -:101F9000F4719EC73EFAC27138429EE9F604D70535 -:101FA0000BFE180FE3AFCAA3E2E80E114EA7643789 -:101FB000AA01EA8FE12017B69F810A88DB342848FE -:101FC0000486AB0C2AF6DF04EF0B73B0BDB279C800 -:101FD000717852184F87271ACFA445D1788EA98CD3 -:101FE000C673EC8A68DCC679A3714ADD3825EAFE3F -:101FF0004D9B0AA3FA373F561A353EDD5F16D5CF03 -:10200000DC5E1E357E52D3D2A87ED68E5551E37348 -:10201000D4B551F7737757DD90FEF303F551E362C2 -:10202000F53FB5E32751F396CAF7CA9011E6811F31 -:10203000FF880785A462D23FEA210423F53FD3E558 -:1020400027C6FFCDFA7F98F49F1BA17FF9DE44AF2E -:10205000356C6FB1ADA6D79FD05AC7905E714E1444 -:10206000EE0AE919AF0D1AACDB256C1DC89D7BF19A -:10207000FA63667EFD5181CF95B83495D6EF081E80 -:10208000FD5AC216D5C2ECD0FFB1456D44DE3C2AE4 -:102090002B0DC4AB17E54A09509E54549D2E13795D -:1020A000A4838D01E4F7B33ADDEACA08F99EB3735D -:1020B000BFF29C5DC7DA5F18D156F1BDA916F09B3F -:1020C0000BD973B436FAE7015CB72D8981822F2CC6 -:1020D000DF3E7F0EDE77F4652B0E0033F56F01389F -:1020E0001FCFE53D1FCFE55C65521AFBC87FC8EAEC -:1020F0002492A7D9EEDD69C7F79C979E30E09BC17B -:10210000E0F21BC8EE52CDE0B7E1FB1A0DB0BA12F7 -:10211000FB0E7049F5D826C24E3BE18B62285791E1 -:102120001487AA7213FBF0FAFB24D138B231B70E30 -:102130006600ACD4FCE1C61CE60F87718DBDA450CF -:10214000BD9208D80E3F90C9AE9FBB0FAD10EDE910 -:102150009C91E3A1E17051F8C9CF379B597B69B3DA -:102160003DCA6F6E6C7E2141C179CE65C3A2400429 -:102170007E5D84DF746A6586DF80FAC7648267707B -:10218000DDB79349689FD4BBCD8A439EDAF10F95A2 -:10219000807A30B62DF1A34E60A55161E3B5797C0C -:1021A000C1B940381063E9FA3D1FC22692EF9E6F15 -:1021B000B18D785F8FDDC0DED743EFC376393676D9 -:1021C000C46D39EAC541EDD1390BC82EF07A48C249 -:1021D000FEE26E30903D2CF1A61B489E93E03EDD62 -:1021E0008EF29CB52BECF91F42A581E43A735F6D2A -:1021F000028DBB369F360F0AEBC078F2A1C36F4841 -:1022000046BF35748BE4DEA5B0F799E97AE5BDA940 -:102210004F5A95F0FBCE80B7FF34EA7B29B8D9BC82 -:10222000DAFC6879517EF18D8DD5BF4BCA207FA82D -:102230000333F9C34E13F3878355575A5FC2FBAB81 -:1022400053FB6E32E273E7ABBE9D4CB8ACDC21832E -:1022500082FAFF24C1FB07FBF4301EE71EF873026D -:10226000DD5F65525F7909ED00F698DCAF003DB7A0 -:10227000873DA78D1BB0CFFD8C78072508D4ACEB2C -:10228000DBA786FFBCD773C612CF347E3D28F85536 -:10229000FF5AD658E2537DC2357EF1FE2B996389F1 -:1022A0005F3324CECBD879BB905F4A16AE1B79A59D -:1022B00020AFBABE2A4B223FB1EFB8B388E4D48333 -:1022C000F76AE4BAF6BDBF2A97EEC359D70DC94BDA -:1022D000B6E94739EF012E678FB08F15C1A422D21E -:1022E0003BDA9DC581E356FDC76BFDBF257C3AF700 -:1022F000BCF2388D29BE313C34FFB4379EC7231061 -:1023000071CE2D70C13897AD47510721DE4DF9C20E -:10231000F5FCD65EF20BC8AB2B3A747C99E4AF2A7D -:1023200081FC8205DC0AB5E865DE9B8D7A6C3CA0F9 -:1023300083A7B16B23A7A6F99F12ECCB3AEE7FB02F -:102340006F4EC13822FCD324C7BF2EDACAECC76354 -:102350005D3383B9442657F1E1AA0A7A2FF4A21F0C -:1023600047592BF18FE2C16CD874280EE59CB1035C -:10237000F3031C37F32CBFAFF9F55921DD1A6322A3 -:102380008DFBD917B28D208A8E03B30F977F4AF346 -:10239000CE8688E746890FB31C7F5F7C98EFE0FE0E -:1023A0002190CDFD7B2014AFFAD3D9B44595F9C85F -:1023B00017278F1F2D8839D9B1511AC836A31F5E30 -:1023C000E468DEBE7D02D26122C785FA8DF45B2906 -:1023D000623CBE96371E9EC2FC21FC05A522BCECC9 -:1023E00042E618798AD1EE78307647E59DA123DF61 -:1023F000D8FA701DAD4EE5BF485F4398D7905F880F -:10240000D3F7191DA3ACEF4DF2AFC8FFE71C3A2676 -:10241000AFB943F2A8F87EB3E20109D71067B74F0E -:1024200093A5F0F832078F4BB547CEA719515FFD42 -:10243000BAE3B63C9CBFA6FD0D1B2E1F7E6CF3AE0F -:1024400073E03CD5E73E9841A10B199E5699403860 -:102450006524923DE5EBC1AF2F1C29876F072E063F -:10246000295FB72389B5391D125B9F2FC4D739D097 -:10247000D1E88CF41BD79EFBCFCEF1A4B73D6360AF -:1024800005F9E3FC60D106E231C962405DBCFE554E -:102490002E9BEF09473ACFAFF5A0A7EB00AA6E2914 -:1024A0000EDA63C0E770DE81AF64364E9B37BF63E0 -:1024B000AE6C471EE5859A0E525E18173429A4E7C4 -:1024C000B89781E3128C637ED1D7B510287F1D7435 -:1024D000805BC2FBADF1431F132F863A4DCA2E8994 -:1024E000F06B0227CEDF6AE4F133070DE10D6BF8E4 -:1024F000BAF6BEB8E0CF81FC15F2C3A3D27D7D133E -:10250000DC628DC43D81C9FF4B07E7576B7C486790 -:1025100025BF8F9CDCC5E40ACB09ECBD9A9C39AC85 -:102520000E68350E5D78DCC5E4B2131F7280CB09EE -:10253000C12CE5157ADEEE61EB88B32B6EBF345209 -:102540002E5F01E6C56877CF6E816B764E76EF8B96 -:102550000FF7CD6813AD1920FCC229968784FBE8DC -:10256000B04AC2CFBFF1CF67B66F9DC3EA23BF8C1D -:102570007CB0609BE0A47572FBC2B2C933A690E345 -:10258000E0469C2C667EFFDA78E4BB95FA563ECE98 -:102590009D68B7944BCC6E80ECA64EF89987A4D07A -:1025A00085DB50B55F860E1628284BCDD1B7196F45 -:1025B000AB75C197F2F17E59BC3748FEF7AD8F7409 -:1025C00060C3F57FFE5A9C5A817864EF6F4EF658CF -:1025D00047CEF7D4D92DCFA792BEF74B0A228D79DB -:1025E000E1501AC95717FCD4E8C17661C7EF8D14C2 -:1025F0009F5639BD47C80E4A3A1AE6117EB3A0A9C4 -:10260000D16E657ED14B3C0DA470FF317C6AF2AE79 -:102610008608BC2F3978DE0243DE9BC96E82C23E3B -:10262000BB28FFC1B65DE461ED0756662AF9E1E714 -:10263000FC70301570CE2D70389570D6AE0FAAFA9A -:1026400045C4A7DC33E6D59E08BE5D10F67E41BCCE -:10265000EF1F9DDE8F0887EA039F186DB82EDF1FDE -:102660000269149F0298A7D9BFC32FFA62ECC6A7CC -:102670001F32D278DF45607E04F5BA3511F5B4E734 -:102680004CC7943556263F24E2BADBCF9998DF6CCD -:102690004FE7F6D770FA7201F9ADCB9DD537135ECF -:1026A000EF3B0C1ACFCBE2C99EF602F3639A3DE6EC -:1026B000913DA2E879C4F362EAE7B0F95A8DBDE52D -:1026C000CCFEDA7540F6873C67BC479EDB29FFC825 -:1026D000B323EFD9F359CC9E5B7B31E061DF8F7E72 -:1026E0007C12EB972DA37E6BEF7C3BB3671D425BA7 -:1026F0004876193AC8E609604C23D549501999A77C -:1027000096396C4C5ECD3F563AB8FF0F642B896EFC -:102710005C8F4596A3EC20225EF2BE88A72B9F37E4 -:10272000FCF4C509644D222E88BCAC4BE4C1E02DFD -:1027300062FEFEC72296D5BF53BAB805D75BDF232A -:1027400073FF2F787250E4C98737A7B03EC50B05D9 -:10275000F5341D5B0FFAD3199E4DF3D0C6A064511A -:10276000D3216A4B2B03F3107198B3A2F790819B8E -:10277000732EF1AFEDE00F72F5C4F77326884311A5 -:10278000DBBE19FAF875C4E1912EC47F94B884CBEE -:1027900061FC4304181FAFC79B41A9EFAED96E4C33 -:1027A000F99F1FFB037D1CDA0F1103F1C87B7ECC60 -:1027B0004FFD2850BBD333D58938FE36C93BD58968 -:1027C000380E9EF826997C7AFBA94F6CE4EFDB8CDF -:1027D0009E5CE2595B06D60BA3F0738293F3A7D8F5 -:1027E000149DA76BED5227E7FF643F3C43FCA96BA8 -:1027F00093ED2AEABBBF4DF618318FBAE0F126EB14 -:1028000011D28BE05F3E9BE2BBA87FD771D8611DE0 -:10281000E52F1867D6BF6888AA4B6BC4BE4616F46E -:102820006D4B459C7C2F4BACAEDD18938FD450FE86 -:102830005240F545B391D653F572CC3C94C714D0B1 -:10284000B8EFAE73973AC53E472664521E833C628A -:10285000F5F4D069D9BD8B62A01EBA4DC8DF3D3AF0 -:102860008E13FA4D668F5A3E637279E691DDCFD3AF -:10287000E28AA85B875A2595D9CF6EF4F3D82FBD8D -:10288000A83403C7E154CA0C5A0FE765A99E8F2FDD -:102890000DA633FB2BF1603D8FEB5E8FF5BC4AEB51 -:1028A000D6F23CD5C0D68FE197E579B3406DB4E15F -:1028B000B80DBB25B6EF53BDDB1095E7F9043E35E7 -:1028C0003B4E1CA172B23610735FE0E38BC1E70D83 -:1028D000FA316B244E8F3A45BE97066991F91E7402 -:1028E0003B47AD0B347CB43CFB4F069E5F7C20E63F -:1028F000D7C6FD8B93D7E7751E60FB4735AAACAAF8 -:102900003C1FB4AE41BEDC2FF872BFE08B0FF8B8AD -:10291000DADD921AA278F533AE7733FE112EEB0290 -:102920006B16A42A23795525F0D8D86260F92FC0F8 -:102930002623D9E7C69D31E3042E5531B8D479A5B5 -:1029400018F9783EFEB7CA576DE0FB35D5C82FBFE2 -:10295000F2FF276FACFEFE5DD3DF149812A5BF45D2 -:102960004937A4BFD83C79EF9129167A7EB83B83CA -:10297000ED4368BC899D6781C8B317EEE0F9687FB5 -:10298000C73C4B3ED553C7F56E09E729EAF95F5BB3 -:102990003EE251D82943054E31182C7AC68FEBDC24 -:1029A000D73D719982F1A1B047CFE24B514FA14A77 -:1029B000754D614FA1253381194F12D50B380F8BFF -:1029C000CF83C7279ECC233FDB3DBF98606F385E27 -:1029D00068A13C621FF07D0DA9A738A92F22DE74E3 -:1029E0003BF9BEC6B694FF7996F2FC857B0D6ECAA4 -:1029F00047161A86DE9FEDA2F7EBDD0DD8AFE95939 -:102A0000BB258EF4FE9AE4A674FC486FBDEB47A488 -:102A1000DFA0C16E62F23E7C90EEFB5B24F7241CCB -:102A2000EFEBBC3DB715FB85CD456E82597B5FA1B1 -:102A30004379A182F2C5711656C72FBCC9C0E2EE18 -:102A4000A5F1965F53BE54E5695E40FEF8D2DBFB0C -:102A50008CE40F065B2548C1851C4939F41B3FAE49 -:102A6000F3D29B278C9494CF6B3B61ECFB8E7CA2C2 -:102A70005F9521C4EAF72623D541B5CD5ABFCF488B -:102A80007AAA14F955DDCBBF67FD2AAA13F07D554C -:102A90003B6555C19F873ADF3212DE752D128C4D92 -:102AA0008FB8FFB2C4EE6BBC5F0B9C076B857FAA2F -:102AB00016FB90D5B40F89D7613BF7371AEF1FD8B3 -:102AC000BDE40885EF754DD17EE841C1F30D549703 -:102AD000B2FADB6B24BD6ED811334EF0FCC1EFE1CE -:102AE000B93549F8F31CC8219E5F9ECBE3C9E513B5 -:102AF000F1963C5CD7E563B21BE03BF9CEE2EF71A7 -:102B0000912F0C87742C9E69E3063AFECCE28DEF80 -:102B1000F8B091F2DB05C12F983E2A8207E613DE5A -:102B20007782B786F0BB3368B193FD57F4717F505D -:102B30001E34A9B40F7E2704B6929E07BB5EDDEA61 -:102B400024DEFC1BE70D087FB741E0BA41E0BA0183 -:102B50001D7E12BAD8AABC032F61BA0FE5C0FD5082 -:102B60007940F8A19DD13863E4B98FF4551734C189 -:102B7000D378FF0EE18FEE68E1FE28364ED6897DD0 -:102B800080C171B98BD97E2BD6BB94C7D5B444E331 -:102B90005F27F605EA62E2F0CD497CDFEEFBEAFF53 -:102BA000583DCD8DD153C510E74F39C53D5C7F777A -:102BB000684B1EEDDB6978C5EAA95BC94C1CAD9E6C -:102BC000D5DAF745DEAFF517237129DF0CD89BACBA -:102BD0009175FCAB493CFE54CD92FDA4E76BF5CE5C -:102BE000C443058A2E5CEF609DB332690CAF7BA6AF -:102BF000E1D44727C8E07285EB9DA7525EA828A4C0 -:102C00007CA585FB9181129C2F91F27960FECBD738 -:102C10006252A94EF1217F589D43BCC1B63228DDD6 -:102C20004EBCC1FA611DCDBF84B68E1187251D3CF7 -:102C3000EF5932FF0BC6B76313F97A87F5CAD8D1BB -:102C4000EA09AD8EA8FB8AE7A9DAF53AB47B1A5FE8 -:102C50001794585DDC76F0EBB474F49F839D57D2E3 -:102C6000D660FBA258BF96A70E619E9A21F214CAA5 -:102C70009FD77395C1064C871F431EAE17710EA4D4 -:102C8000ADCC4EEA28D925BEB54B7C1F673F5E9878 -:102C900089FEF7837896C70C9CE1E743F4FC139810 -:102CA000470DAC0D1C76E2F8CBAD128B7FEB31C734 -:102CB000BDB570A4BDD70A5E36C01651976D656D5F -:102CC00079F6DE4F1E277FD46256C8BF0E74341AC1 -:102CD000D9FEB21AF17CC6C87CA856F0B7F67BF6CE -:102CE000B55E4D127152F012D7C1F2DBC163B2DD95 -:102CF0002431FC7E353E122791FFB41D8C637A1E71 -:102D00003C615529CFFF5CF0EF92D8776F2891197D -:102D10002EBA59BCCDED7A2B83F44A7AF0D23E4AD2 -:102D2000D75B533C6C9F4F65F654BD5BA6C3BEB0EA -:102D3000FC010BDB0BD5FA1ABE3E812FCA35D9E850 -:102D40000ACBD5AEEFB3B947B11B493AC8F4A69345 -:102D5000A2EB5CDF7EB9528DB0275CCF6AF26FFBCD -:102D6000053F403F944C7EB9334961F23504B99E2A -:102D7000759DBCC5F72FE7FB3606F6FE11F7CBFCB9 -:102D80003574FF72BA05184FBEF25750FF910C9977 -:102D9000F9A9473EA8CA8288F783C4EB719F6128CE -:102DA00099D5C327744C3EDF89E1E48956F283CD7F -:102DB000F3ED79E4DFB87F389261D948FCF6D37B34 -:102DC000C786E75998C4E33CD07A53289B7991CFC2 -:102DD0002BD6BB0596321CB6089E75897C14EBA6D3 -:102DE00033648FB175D3F5F2DD88FA8D3D7F79AE0E -:102DF00072F247C883C2637A3FD5EBFBCE723FD1F4 -:102E0000D0B9E1775407FBCE9B80FCC4235D1BB295 -:102E1000280E83D73B95F2BBCB5D0F4E65FB97D257 -:102E20001626979FE44BA1BCE97432E543B59DA7F4 -:102E300093595C6F9FFE02E5499817DD41D7315FDA -:102E400061FC2BEC2966FCDB77BC3829930407B7BF -:102E500085E6AD3DA6AF247C6A8F15BF5741F94B7F -:102E60004F19CB93B4BCA888EA71CA938E4D8CCA13 -:102E700093FA057E8307E2D8FE8704199C3F303120 -:102E80008A3F356DEFB07CA2A643F644F2E8DA73D0 -:102E90002E3DE38DC1A5B0F91A029287F1632F6F21 -:102EA0006B3AF6B1F5551B024CDF0D2D067EBF9532 -:102EB000B7004DEC793F38FD84C77B7409F5506E3F -:102EC0005427D0FEFABBE9BCBE88D5C77617DF4FC2 -:102ED00078F79CF766E2CBBB73BD59F651E2861FCB -:102EE000CA78DD2D09BCDB0C2CAF8C1DB7CDC5F726 -:102EF0007B6C491075DEA8B5F52ECE9F7223DFA737 -:102F00008ABD7FAB8BD7CDF8EF191DF2E26485C186 -:102F1000FEB4A827C6A1BFBD4BF8DB65771A58DE03 -:102F200071529C33DDA5F9DD121EBFB5FDFE253BB8 -:102F3000E1492CFFE14BC863E7604B3CD17EEF6E6B -:102F4000915F2D5B14735DE453777F4F3E35C3254E -:102F5000FCE16498CCEB06AB85F645BFEC36D86552 -:102F600026B73AB1327FE43A357F73449C0F75A39C -:102F70001FA4B621E743B64FF5EE8173BF71303F12 -:102F80001A07197CDF91EDD7D75E67BFBEE19A9D26 -:102F9000FE308A779A9EFA29CFCF1BA9A7A502EF08 -:102FA0005AF325233BB7844DDB7572F89CD264F04D -:102FB0007A52711D868EB9213ABF6CC831B17CA995 -:102FC000FF7649257F8F72A69922FC7DFF389E7F70 -:102FD0003DB25C62FBC207723E6471BC36D46B24A6 -:102FE0005E4D6E5BF324B35F3F9CA27A49D3E762E8 -:102FF000338F9FD7F4A8AD976E2AB43EA79FFB6589 -:10300000176B693CC5CBBB447C5C5C12ADBF2CE844 -:103010005D40FB23F77824962F5D4FEF4B574C7B99 -:1030200087DCDF8DEAFF9F5CDE875D64EFBDC3CB8D -:10303000697FF7DD9C4FD328BED65D87CF7E81AFF9 -:10304000CFC2CFC57C167E1EE6CE521AFB101FBD26 -:10305000C3BBD945FB4FBABFD8A600CDD3F7AB7AD7 -:1030600089F4030CFFEBD9D13631EF36979DDB8B1A -:103070008B9F0FC5519FECD9A04E203F0179377629 -:10308000CED7B0FF6801E969E0C0B10263843E2F8A -:10309000D5A33FA0F8D2792859B146F24D27F8A61A -:1030A00067AD242D1571339A7F97887FA4FFBD8764 -:1030B000EEA2BAB0BF6D994B5222E26AFB49DBA483 -:1030C0008879FB83321B8FF5D8E4BB1322E57C9211 -:1030D000C9D91FE0F301F44D5E961F79BF919F1B84 -:1030E00099FB188F9FCADEC4CEDD351EEB81F3B885 -:1030F000AE6309B03825D61D30E20FAA33BA4C2A88 -:103100009D53D07EBB23C24E8E0A9C67627140FCE9 -:103110009C057E99E69D8933DE4B7D3D84E84C6EAF -:103120003684647EDE3D0188D73304AF67EA430707 -:10313000A402368E9D4B95422F1B772B0CB1D603E4 -:10314000763DB565E0666D89397407B993BC4080FA -:103150007D97144AD63B2E98D951298CA6BFF0FAF8 -:10316000F57041E3290EC6A487EDE3C78E1B1676E2 -:10317000EFA6DA82F4DC0F6C1FEE16E893E925B3B4 -:10318000F5B088BE27BB450FE6789477EF611DB395 -:10319000E7AE3E45257FE64E12CF7D86CF617FA606 -:1031A00087DB2D8520FA6E455B6F2C0EA5381FED51 -:1031B0000BCED463E5CB700CB1F7DD4682E3BAE702 -:1031C00082A2A7FE1F5DE9623F85D769F3449DA6F1 -:1031D00033FB191E7F12F191CE736C384F69930443 -:1031E00067E97C2693AF579BBF14B3C1C4421ACF83 -:1031F000E31B6D859F75F2731E1B3B9F9B6F27BC66 -:10320000A450B2EEAAE5C6711D4C0626B7EDFEA18C -:1032100081C78BC3E75DEEE0D1B3F45D8EE4F1B01E -:10322000EF7ADC666B88F27364C7A5C8BCFBAA6B37 -:10323000ED5FC9DE25C5CEF0022F28947F8C0D7F6F -:10324000EF025793C2DFD3108C1793C3E7FBDAF773 -:1032500035BBD5A58A0EF5B2C26576935E0ACD69F7 -:1032600045540F36DBBD7F75B1EF6C5A26B1C9F4FA -:10327000EAF4CA8430DF2DE02921BCB5737D49E82A -:10328000EF7AE7F664ABC4730BBA7DFA2EE819B493 -:1032900017B373B4EF8FF8793E5AA142DF1DC11303 -:1032A000F314FA2E609BC3EC7E5AA2141FD7670951 -:1032B000AFAFD1CCBF276834F3EF0260EB74B67FB9 -:1032C000F690388F68B4EAB2A9DE6A84783795F44C -:1032D0009ABC0F25703E3EF4DF16763E1A2BF7D7C8 -:1032E000F1DE9C31D3C3F23F2ABBCF62EE1385E7F8 -:1032F0001C0D4F5D18CF156A46639FC2F09B46CFE9 -:103300004F33A937D1BEC82A13FF7E49C30D15CA52 -:10331000486D17FAD0F0B393BE691D1ED4B7C69797 -:103320008C307ECFC473DC0CF4E544267B56217FC1 -:103330001D8BCBFF01AF6B7F8EF0290000000000DA -:1033400000000000000000001F8B080000000000CB -:10335000000BFBCACFC0F0A31E8143D1F8E8389D13 -:103360000F534C941182D7B3E0D78B0D5B3122D829 -:10337000FEDC0C0CCA9C0C0C2A40DC07C4FD40FC93 -:103380001E880DB818180C81380DC84E07627B20B6 -:1033900076E386E869666760E806E2C9403C9B9D83 -:1033A00074FB39241918A6C822F84F806C4505D241 -:1033B000CD19C54313F31BA1F235B451F9C1BAC0FD -:1033C000F481A446539B34F34F01F59E36C22DAFD2 -:1033D0006E8ECA97B344E52F3343E55F7487D00000 -:1033E00093DDE134B803000000000000000000009D -:1033F0001F8B080000000000000BC57D0D7C54C52C -:10340000B5F8DCBB77EF7E6F361F840D24E1260410 -:103410001230C125060C56DA4D0405451A502BA86A -:103420004F970009C857502A69C57F2E49080102E5 -:103430002C186B50C4E553ACD006053F5EAD5D1053 -:103440002DFA7C362A2AEDB318104129D014A56C28 -:10345000DFD3F29F73666EF6DECD6EC0E7FBBF7FF3 -:10346000FAABC3DC993B77E67CCF39676665D14C14 -:10347000D206107209FE7E44C81813216444B42495 -:1034800015AA404612F2532BC13FAD5F6CD9584785 -:1034900048D842486426211D4EDA51AAB192425AB8 -:1034A000DE7EB348D2094982F715429A849A4303D3 -:1034B0004B0851B344B29D3E5A9E393929E04C3CE9 -:1034C000EE2E3EEEAFEAAC58B6D779B07CBECE8BCE -:1034D000E5DE3A8584F30979B1AE00CB97EB7CF851 -:1034E000FC5FEB4AB17CB5CE8FE56B75E3B00CD7D2 -:1034F000556079A06E0A9607EB02F8DE9B75B3B0B3 -:103500003C545783CFDFAEABC5F29D3A159FBF5BEE -:10351000D78C65475D10CBF7EBDAB03C5C17C27E09 -:103520001FD5EDC4F2485D3B3EFF53DDCB587E52C4 -:1035300017C6F24E924C481F42EEB8E382751A5DF0 -:103540006FFE538BDE1F9F46C8DA11A20FC095FF96 -:10355000D4096FA030BAEEB5DF9AA6B4C781CB4FBD -:103560008880E3AC75116C5FBBFF8F44292264CD6A -:10357000884EAF4AEBE3F977866C3F6C9D5618EDA9 -:10358000173BCEE7C4C4C631D376DA6FF006D65FF8 -:103590006B1F0FDF19116DDFD1F6BE75BA53DFCE89 -:1035A000DE7F66E3FB56C0DFEA8844C28877951069 -:1035B0005ADA95AEB63E14CFB6231662C9A1F857B3 -:1035C000DA49271D67CDA85F84C5125837EDA6C01C -:1035D0003A3F20028583EA22480F0A8C716DF43B42 -:1035E000D71211E791FFD461F69DDB2F60F9DA3F26 -:1035F0006442E87B6BEE10420E3AFE9AD1E7BD7E44 -:10360000A037F55913D01B92AB02FFE9F456D0B1A5 -:10361000D78EFEC8AB5238ADFEF68329D381FE8625 -:10362000131F7C6FF5FE578802ED455D08BF06BE8F -:10363000EED553A70DF01426A64B4A49442CA5CB32 -:1036400075127F280E7CFF058040E163F284704D87 -:1036500076DA2F1E1EFE85C8D86FB5ABE243808B8D -:103660007A87D9B79DCEFB065F989C7446E70DF527 -:10367000CF68DDF97598985C30EF2FBD26BA7E478C -:10368000A97C8D8DCEC6D9D57504DE775E5FE587C2 -:10369000B5AF19DEE9ADA2FDAD051DB85EE223BEF2 -:1036A00041745C7B814AA617021C4C88D7D8F94C20 -:1036B0000778F7013CFDDD0B38D1E8F0C3DB3FB004 -:1036C00056EAFA3FA3D187C0E88BB484AD935CD1AE -:1036D000F6A7B4761BA31F6235B66F88A1639299D3 -:1036E000A0DD4C018DF81243DB0584BB757251CF10 -:1036F00079B784DF423E70FAC2D6409C75513EB124 -:1037000082DC492A117D00AF35A329BF1446D77941 -:1037100039BE6BE670595D32D905E35F4E6E15B563 -:103720008B245CC06526FDFFD52FDBE9CCA3F5E13A -:10373000E11443FD9A43FD0CFD4774E41ADAAF3DF2 -:1037400032D4D03EAAB3D850FFC117D719FA8FEEA2 -:103750002A37D47F14B9D9D0BF8CDC66A8DF60BD0E -:10376000DBD07FAC67BAA1FD26EF1C43FB78E541B7 -:1037700043FD9682870DFD6FF53518DA7F5CBACA76 -:10378000D03EC9FFA8A17EDBB8270DFDEFA8D86AFF -:1037900068BF73CA7386F6A981170CF579F6C05114 -:1037A000C0CFDDB37E6378EF5F6A5E37D43F2464B9 -:1037B0005C3CFC1281C9194A419E9357F1FE54C4E6 -:1037C0007980E6808EFB303A2DD89C404EF2F66729 -:1037D000B7BD6F9D6990936646C719AC7D67E8FDDC -:1037E000F8EF67713E211DD6C92E7D3B9BD755FF53 -:1037F000A0F215DA25F53BC95797C787FD35B94AB9 -:10380000E99B90EB287CD5FEAA8ADFA3E351796976 -:10381000624B26B584C929421EC4E79ADE27992443 -:103820006CA2E336B83237AF0498D0B1A534A817EC -:103830006E81BAA8F849671CB89A3CB2014FB1F042 -:1038400025CE144ACCBDC95915E1A78E2505127C99 -:103850005FB0FB96D2F54A24D04FA0CF2F8A012F1C -:103860004C7EB149FD7D2027DA7FE968FA4FE87F79 -:103870004C08D5637F05E1D85044FCA037D40C39FF -:10388000B43D07E1690179A2BD471F289D6CBEEADE -:10389000A581863A9BEF65EBDFE41BEBDAB83F3797 -:1038A000C293C219EAF7F14A8F75FBE428DD9AA0AA -:1038B0001FAB2BA2402EA11C34B66BDFB968730F6F -:1038C0002349148F56562EB6BBB74079D1961D2288 -:1038D0006E420AC54039C04D2D67F0518F3A420DF6 -:1038E000385ECDB5154500DFF8F60221F58C3F3E78 -:1038F000192FEAD791086F0D60B7E5EBE820D38761 -:10390000729CAE1AF55B6CFF3B05998DEFA4A8A2E3 -:10391000E35B08A3B12453E04E6104ACB68248389F -:103920004F1FA9407C8D2360975A3578066762DD6A -:10393000C9EDCCFDAE91470214CFABFDB20FC6AAC4 -:1039400014148E079F17F480A554242B696DB5F2CB -:10395000BE15F8A33947CE00B96E916A8887D62D77 -:1039600079940FE2E89105DD72E211722576712CEF -:103970009E0AE8EB6C1E04E1A8CD3F98D561CD0509 -:10398000BA1C4DED623AD5B5D7F7AE5F9671F8AE79 -:1039900002BB98966B94C94904F9964C05FA6ECE11 -:1039A0004917914F399CBAE192F39115F874057F4C -:1039B0007FB5EF7DB4D357687A3C068ECDC38F2395 -:1039C0007CA6094C1FAF2AB24F09C581CB34C18DEB -:1039D000EDCDC05369685F31FE8AA117DAE2ADA46C -:1039E000ED56C553BC928E3FA6489A0A74E12A252B -:1039F0008A05F9D7EFCCA0DFB7F3DE92221AE4876D -:103A00002B8DD1ADF51321A4D0FE4E2FFB9EC549C1 -:103A1000427E7C7FA1012FF6D2C004328CDA49FFAE -:103A200030E17B748ECC8E383C1EF9D1EC61EB24F6 -:103A3000050C4F1EFABF4BB9743C4536E88DA565A1 -:103A4000B22F4CBFB3D8ED447A32EBF14ABFEBF85A -:103A5000F6850A187F79E603F6A574FC8B654DCBD5 -:103A6000812D4D9F8CFF12F8CE14DB3F6BF21F06A9 -:103A7000C6E103AD7474BA49381506B8A7573A7051 -:103A80007FB2F9ED83BA79BE2AB8D250BE5E4BAE92 -:103A900045B97099F72FD685DE3E3808E1215E09D9 -:103AA0003D2F8BE1EBA61C4D6FA9DE493ABBEC82A2 -:103AB000C0F41A51CB10CE12E7E7A6D1A40BECD676 -:103AC0003539B2524FBB48A572184807FEBAE8F71D -:103AD000C1362320AF95A60EF6FCA706B9B9A2EF12 -:103AE000445FB817B8497931FAE632EBAF05F8E927 -:103AF000FA9F00F839A2F0B3908AA430D04B709CA2 -:103B0000611FBBBCEC21254CFFB9BCDF2FFCC78873 -:103B10000E8E3FA27CA8E30F4B6688E8BFAFC9C5F5 -:103B2000DB447F17C86193EC4339457265DC8FC471 -:103B3000CEAF4064F2260A67AB4474FC4126841081 -:103B4000EEF4AFC29ACEE147FF6CDE37FF01F0A37F -:103B50003A3AEC1886CF1BA5623A9F34A23AAEA639 -:103B6000EF4B44827A9698837C4BDBC7C829C0BF51 -:103B700037FA400E36F17D1FF16CF6EAEDF22C912A -:103B8000E135DA1EF2DE616867F64E9366D77BB6E2 -:103B90001AE8A2FBFD641277FFD14764767696E8B7 -:103BA000E1F4B315F76F2BD22644000DB68C1B7DC4 -:103BB00095C0AF1E8270D0F484A617A8BEC812FBB1 -:103BC00044C793F32A8880ED46FD9B505EC7E85DAD -:103BD0005B81510E10BD3D930BFFCDF420BD90587D -:103BE0007DCFCB8A9BAF88AF7AE84B127FBF384935 -:103BF000647298A869B87E8DAF08B727CC1A5D109B -:103C000046AF6EFE5D19E63310F01CC2C11D745B39 -:103C1000057517A9C1FA85D2E230C0C922753613DD -:103C2000AE1FD59C38FB28EE8749B48EB5A3E3EBD5 -:103C30008732D18DF834396B4800E9F81EB403059A -:103C400035402EA13D18E47AD5E7053C2EAFAB25D3 -:103C50009FD1C5D80F8CC7FDB994E9F7C3FEDE0428 -:103C6000449041FFEF2C61A5E453F4F4D98D47B2A1 -:103C700014C73353B0C03ACD4EEB34D00366A767B8 -:103C800012960543670A5026DD582B225BC5A727ED -:103C90006D3C4A57B344182F2D80FC2C792AB02450 -:103CA000CE34B45F697FA522EE3C381DF07E09E971 -:103CB000AE9B6E343828328C174B4F361FDD308860 -:103CC00058ED80F9A6F3F9A6DFD3B41040EC24AA8E -:103CD000753085517AE734D47B4EAE7F1A0B8A9BC0 -:103CE000CB693F772149BE9196B6BC2E9C3FEE6BC7 -:103CF000FBC178772F2D43FF07C17A637D4519DB20 -:103D00001FF863EC565191343ACBEDD5DE112E59A4 -:103D10007ABE9F68FDB1FA949007AECCBE9AC2F805 -:103D200051A5FF037EF4101D7FD271DCD71BF581F6 -:103D300033E63BBF025822BC17FEAF7C2F89D45B11 -:103D4000154A0A6645F484289E286A92611F65F325 -:103D5000D3FD1DB4A775FA45E5F27869847D6C2121 -:103D6000A3173DFDBFCEE56BDF7B171D5B46C7BDCF -:103D7000E073FAA0573A15A7A9C53DD7B33246EE6E -:103D8000AC2C588F74D140E92817F6070522EAA514 -:103D900066658B47EF57F95C93433DE88328D2482B -:103DA000BE9FA4F03129A2DFE6FEFEF4116B3F5D59 -:103DB000297DD8A718F1F15DF175FE3BD2C7F7FD5B -:103DC0009E86D744F28CE215EDF1CBF99F7AE2B5ED -:103DD0001EE5AE4D89EFAFBCD88D4FB56769F0A732 -:103DE0001AFD02D6BB9BDAE2D92D5A69BD2776FFB0 -:103DF000CFC6B5D59A941360DF4A1EC33E6885B21C -:103E00005E057BFE02D8E5601F06CBD03F4CF298E2 -:103E1000BF160610815F147F88ED6F4244AF07E53F -:103E20004CA3DFCD946637EAEF29AAA09FBFAD5619 -:103E3000C67958E17B69E8CF0DC1774D1E12B6B93E -:103E4000A3F40A9F62FE8087AF880E347A05339808 -:103E5000D1ABF1BDE599C5241EFE7A7CEF76E37CFB -:103E600013CAA5D8F79C92725267A7247E4F2227C7 -:103E700075F64EB916F7E178A276DECB42129507B9 -:103E8000DE9F9000856F133465807C22A8CF9ABC9A -:103E9000C52817C84E2166DFAE30FA5152B0BF6850 -:103EA000657A53AB279E0FFB6E348EA4E0BE36516D -:103EB000FF86BAD2C724AA8C1CB5AFB74A148F8D1F -:103EC0004BFD532A707F7BA8551A14ED37CFA4ED14 -:103ED000DBA9FA1C19A56789D07E0837915CBA0660 -:103EE0001E7A883212A0C9E99B74603B7DCAF148F2 -:103EF00084EEFD0C1DB20DD689FE8923D80F06BABB -:103F000084FEA64E56A72F427D95D9EFC779494129 -:103F1000EB03145EAB6CBCAEF07A32AF7B783D87BE -:103F2000D7C97AAC3B645A07FE35073D58B7F37AD8 -:103F30000EAFA7F07A32AFE7F2BAB01EEBAB643641 -:103F4000DE4A29C4C6B7F3BAC2EB29BCEEE1F55C80 -:103F50005E275BD8F72DAC6E3787D8F80E5ECFE1C1 -:103F6000F5545E4FE6F581BC2E6CC17A42799947D3 -:103F7000E16F900F1DD13A2A110ED7EE7A674C3BB4 -:103F8000A3975481703B2C940176D3FED9BFC8000F -:103F90007FE88663D77A613FD670AB464F3E949FE9 -:103FA00024F3169463197CAC86195BD00FD1304B87 -:103FB000C6FD27E1FE99687BF12185B65F08883E42 -:103FC000A09B2792E3FBC97E51C7E295ADDC4E5E14 -:103FD000C7E3956B215E09FE161EAF5C05F14A0B27 -:103FE000D0A90FEBCB215E990FFB6B16AF6C8078DD -:103FF00025AD3F07F14A5A3E0BF14A5A3EC3E395BD -:10400000DB79BC722BC42B69B919E295B47C9AC7D1 -:104010002B9FE2F1CA2779BCB26D46F15B7930FF84 -:10402000B96CFE89F0D1778A517EF6A930C62D523F -:10403000C6A418DA3DD71BE316EE925C43DD59683F -:104040008C5BD8F38A0DE35933AF33B4CB69E58683 -:10405000BAE434C62D0A774D36D4876EBBCB502FC9 -:10406000D85869187F70EBFD86F6BC96070CEDB941 -:104070008D3F37D49525F586FE4F9A7291BEB217C3 -:10408000AD34F4CB9CBBDED06F9EDD7FDA04F26EE4 -:1040900042DA15C937F2B59AAE9797B1FAC1944D85 -:1040A000FC7ED4734C1FA18F16FC6A59CC7F65FD32 -:1040B000E4A643B07FB1E4313D15EBAF8A1D4F76E6 -:1040C000EE38A2D2EF94B90F793B75FC48BCBAF731 -:1040D000E85293242627573EC2F6E72D8FC4DFA768 -:1040E000A326A0EB68F9363E1FB82493418F68FBE6 -:1040F0009A964704ECFF7DC7D7DA63C78D7E8FD2CF -:10410000DE48FD7E38C4E7437584CE5E3077264FA7 -:1041100027A8E7D97ED9C4FD3B65134B8F35527E66 -:1041200059E6213E0BAD2F7396FB995D42AD73C0EE -:10413000C5925B715FAFF5D7E6D5E89CCCE40BD1B7 -:10414000F92D514ED90D7E856569BDDB6F72C48432 -:10415000FE3F53442061AA9764A9625C0E9D8F7C48 -:10416000D8E45B4A503FC5F50F10B29EC59DBD46D1 -:10417000BF69E38C18F9C7F332CC7CFE0D69E5F812 -:10418000BCD1D3FBBC2C302F980F9F9739E2C0D203 -:1041900014B1E17C474552B15E1A49C6F2DA487F54 -:1041A0002C474632B01C11198865492407CB6B2275 -:1041B00057E17BC59121580E8F5C83CF7D91E158EB -:1041C0005E1DF9013E1F1619856551E4067C5E18D7 -:1041D00029C3F2AAC82DF87C68643C964322B7E153 -:1041E000F382C8242CF323776339383215CB4191FD -:1041F000E958E645A66139303207DFCB8DCCC632AF -:1042000027F2203E57220BB11C107918CBECC8CFF7 -:10421000B0CC8A34609919598A65FFC82A7CAF5F8F -:10422000640596199147F1B937B20ECBF4C8062C44 -:1042300093235BB1DD13D98C6552E4397CEE8E3C5F -:104240008BA52BF2023E7746F660E988FC069FDBE1 -:1042500023AF60698BBC8ECFAD91FD585E0E4F973A -:10426000B3834B4F18E3CF233F31CAF192C3C6F853 -:1042700073F13B4639EE3B688C3F0F7BD5187F2EA0 -:10428000DC6B8C3F0FDD6594E305DB8C727CF0C644 -:10429000BB0CFDF35A2B0DEDB92DF71BE574A351A3 -:1042A0008E672FF9B9A17FE6A27A437BBFB92B0DA8 -:1042B000EDDE1946F99D4E9E30ECD33C63B618F501 -:1042C000DAF5BF34EEDB4A9E8FD9D78450BED80BC7 -:1042D000FFD5F09E35EF408C5C56997C8AF1B70390 -:1042E0004820BEB998D87DB0AF89C5670A9707A99D -:1042F000C077B44CE37CD707F88E9629B7CCF5028B -:104300003DA44E2C9D0676CCC5638202BE3261620E -:104310006D3EC47B52FA138CFB1275C80D7E5A6F2A -:10432000CAE075FA44807A1661FE06B2B41CFC6CD1 -:104330004D39ACFE56E39272C88B6932F376B5B153 -:104340001CDFB7B1FA91C619F5D09E92E4EBE7A352 -:10435000EF6D35C797D79F4A2CBED75FF2FF41A2BA -:10436000EBFF6B59E743E097FB776BE003893E9FD8 -:104370006B0D0C80D0DA5973E019501DB982FF30F3 -:10438000F42B12FC1F4A28B78D7ED609A038E9F31A -:104390001CC9FF4768D7D6DFE4EA7D1EEF72BDD4A3 -:1043A000944C709FA93E26F3BC1282FA52F36B3DE7 -:1043B000EE70A3BC5FFE98BC05E252E6CCF4E9E0E7 -:1043C0004F833F83FE686D5A087E762BE8A18120DB -:1043D000E5DBB174920E2CDDA40B4B0F64120C8C38 -:1043E000AEBB7BBD596CBD140E5F4BB88FA8C1FE30 -:1043F000F58E89A5B01E0A870B1C0E7F97FA2486BE -:1044000003FDABF08E642E51B4277609067F6692C9 -:104410002940CC3C8E0ACE998C193EDC8FFD49F2A6 -:10442000203D6AF0A37F8B524646F301E87B56732A -:104430009F9EE369E320C0E0FB5C1F6AF45C9B4045 -:104440003F697E6EA2DEFA9DE24DBF97C5B8DF31AF -:10445000493E8CD7C6BE27398DF2CFEC0C601E8446 -:104460002CC58FEBCA161EAFDA38F18AE2DB3BB8F7 -:104470009D4F1A6FBDA2FE5BB475534A80FE591A58 -:10448000D76FBC15E96E107F3F0BEC3A4A4FAFFF78 -:10449000B9BABE05E80F62D2F1FC07AD22DA835942 -:1044A0000BA9E0C989C23BB390DA83C3A2DFCD5C1C -:1044B00064F4BF8465165F21AD57067F2DAF338B43 -:1044C00012FCBFA6F49C07D93691AD87C751A50D44 -:1044D00015CD362A7F0639593DB3B5F7F9101EB709 -:1044E000C8E47495E9E47E979DC6717B7CD7F4CED1 -:1044F000F078795E09BFF31DE38033CDF1E3A814B2 -:104500005F88EF81DA3C6AE91F9DD7603E7F6D3C92 -:104510002D1EA8D5293EAD607737B554A29DD5E4B0 -:1045200065FA9B7C43471F892C4FE2EDCB421CFE72 -:104530009BF87E32A49663FE23D965A45365A964D3 -:104540000FA0FD26A640B9B991F5CB59966607385C -:10455000357A5252A0DC542BD6DB28DD34AAC40FA6 -:10456000CBCAFED9091B6B3F9E0C654E5BD75BF92E -:10457000147F391ED127D1F964A8E7DFBA09CA161A -:10458000BF3507FC704B24CC23CC6E23F602DA2F08 -:104590007B2EC17E0444209DCF931A1ED556611CEC -:1045A000FD67664BD7521BBE47FC8374FD3670F027 -:1045B000E5353E50066C9AD7E2993C0EE2F385C48D -:1045C000378844FB3DCEC773403B8C3386E5316A68 -:1045D000EDEB78BBA5F6BC9A0F654BE7BA9BA05FE5 -:1045E000AB719CB5BCDF20ADBDC4D8BE5A23AB2592 -:1045F000CF87611C534BD77B37C17CDA58BF6EB96C -:10460000C5FBAFE2FD63E5C560788FFB2BF5F35C7E -:1046100011835F4D7E84C03F900FF865FE018B755E -:10462000EB53E08FD4FA2D17D8FE4889C9337DC5E6 -:10463000CCE46197CCFCB61A3D25A26F3257B71F68 -:1046400080B8E50CBBB17E4F8A611F48C6F433B613 -:104650005F9F6B6C2F196AAC17161BEB79D719EAA1 -:1046600017BBFD2F411BE68573FFCB60FE8D0D6DE3 -:1046700095988712F5FBF9EDFA7D4A26EFB7ADA6BE -:1046800018F9A7C1C9F987FB691CBCBDA9B0D2AE96 -:104690008FBF6BFCD30C7E100BF85958DEF68EB62C -:1046A000DEE1B589E37B23CFAF7982E3A98DE3E92E -:1046B00017DC8F13E47E9C353CEFBC85E79DAFE4AF -:1046C0007E9C469E77FE02F7E3ECE17E9C6DDC8FDC -:1046D000F36BEEC7D9CDF3CE9FE37E9C15C3BBA68B -:1046E00082FFEC59EECF7986FB73C670F9BD62ACE0 -:1046F000AF1FF8F7B68E8DBF7F1EC3E9E2C7E0C8D3 -:10470000EC037ADB536F06BAF4B13CEB9C5A8F682A -:1047100029013B97D165CE2C8F2897809DCBEA93BA -:10472000B8BE05BD827933993C6F26936A9D74EEBD -:10473000FF85AEAA4AC01FDF778A6738B842DD32EC -:10474000D7A30AF1EAE3067DD58000712DC9E44FB5 -:104750009247C0F86C5EF9C1AE0390A7E8EBE82879 -:1047600007740E3BD45E0FFD0A0B83109120E6B454 -:104770009008726945990FFD6F4F7F68F26D813126 -:10478000D388812EE81C519FE5F1FD2CB9DE481736 -:1047900096C826B49B9B6A587E06ED1377FFAE95AC -:1047A000C97EA3FD90546AF483350527F7EA97F68E -:1047B000BD6A7C7FD85EE3FEABA9D09827125B165A -:1047C000EE1263FC5C31EF3B7BFF7E7E6422AE37F2 -:1047D000119DDF66AA2C97757912CEC80F711F1133 -:1047E0006B0F4A60E70DC4BC1A3FD8BF529EC70F7B -:1047F000FE12294FE1A58F3FF7F37A05D6A9DDF820 -:1048000063189FE2C560379A480063222B8610BE6A -:104810001FF967BD9F2AFF157710DC4F789AEC3798 -:10482000A84083FE99881F99E32755AE7906FC1F9F -:104830004FAF1609E07F6B4BEFFCDB239FC2E9C74C -:104840003852D6224F31E8BD44EFB52E12C7C58B82 -:104850008FCDE774BD6CD1640FEA8D8397CD179827 -:104860000FEBD7F205FADCCEF305CE8C37F8955373 -:10487000AB7AC7E3062EBFB47A06896FBFEEE1FCC0 -:104880004E9C2CDF44A3FBD461BD8FDF7D6E2724BB -:10489000920EE00B2980F2B3CFED01CC8B27145F91 -:1048A0007A3E69FA76FADBC087EA3A96A748FB892E -:1048B0007A3B4C9B4786275C2640FFFDA3307F63F5 -:1048C000B0332042DCBA693FE1DF69477BDC31A3CA -:1048D000C6CFFC65ED04FCF68E1A9F0ADF077C61EB -:1048E0001E5246777FD40FAB8222A67E349430BB13 -:1048F0005793FF1A9D34788B0F417CFD4289847158 -:104900006F6A5F5DBAA4ED67E87F06B7313A68EA7F -:1049100043F0DC8D54A086811E897F1CC20DC81F08 -:10492000FE9A5C3FF1E3B99422A6FF4D70DE03FAD4 -:10493000491D7ECC830E787C90BF98D5360CF94CFF -:10494000F2D40880DF87C4C06E3D5F999C2CFFAB1A -:1049500029C1B982162E67FB25C0EB87BC3D55EEF9 -:10496000180F72F8E9C728FDC7C9CBF903D70B4F59 -:10497000B54EFE438112E55FADFD4F60A4E9E695BB -:104980001591597E61DB77DB078C35139E7F647C44 -:10499000CF2C5518F6615966E3F7E434A33FF2CA09 -:1049A000E729A15C2285371BF09CDAAF77F9A9F1E2 -:1049B000FFC5AC18BB23AF00E9396A7794233D6C7F -:1049C000F412462F9C9E343DE2EAF4ABE2C09EF422 -:1049D000B13178C00676B246671667C80F7E038786 -:1049E000378CE9823A7AF82BD04356DB4884B7AB50 -:1049F00044C5E7FBB8FECBADED2AF3C7598766DFA8 -:104A0000C1BECB5B0C5F88D9FF908A20D8D559599D -:104A100010C303B5CCFC0B999997DB6F5D59FC5A19 -:104A20008B2767D33FD8FFBCA2E1FD8B18BF9587CA -:104A3000AA785D3CB5EF17D30531A7271E62DF6B5F -:104A4000F4947BE2C96FC91448B7E8F01FBB8F8F9D -:104A5000DD6F13BE7F94BBAB8B500E5B268CC3F80F -:104A600048F7BE7BE3445CB785E34F6ED1E2FBB110 -:104A7000FBCAB9BEDEFDAADF6F5FE9B318F34BAF27 -:104A8000383FF73BFA25B672BB35767F113B8ED89F -:104A90001610E39DDBC86F33C23DAFC568FF0CE362 -:104AA000FC9DA31AFDC8036AFBC5F777F27CB5CA63 -:104AB000520D4FCA9DFF41E977F62133E6E16BFBCA -:104AC00060CDEF349BE7AD55F23CB619A4C20D8D15 -:104AD000678988E777CE92F7DDD7E8F8A6CAC2CE15 -:104AE000D19166F371387FA1E567CD0CB2BA369FDC -:104AF000EA3663BD8A4C4E07BF6B55AB99403ED634 -:104B00006C221DEFD4E64FE9F8271696875A4D6AB6 -:104B10009A40BE2DE379AF951E22A5A61032EFA5CF -:104B2000A746C2799E7916267F4F53F82B3A7D7D92 -:104B3000BF3324037F7FB6F79A9FFC80C0FBA1A6FA -:104B40007EA03F93E39F8398DE6C9CDFE5E61F3BEE -:104B50005FED9C46A279483B85B8F93F0F6BFEAFED -:104B60002B3C47B215826223129F23B9DCFB3B2DFD -:104B70008C7EFEBBEFEFFE9EEF3F7F99F9CFB376C1 -:104B8000DD8879DE6935152057B57C96F924E00774 -:104B900057BAE9D5496A7F45D7CF7B85FD32693F52 -:104BA000D315F4CBEB7DBC739CCF7FBF6BAB0CFC00 -:104BB0007BF697C726823F70CE6F4CC44AE9E0DC93 -:104BC0002E173F2F169241EFDDBFD7E40F613D3C1A -:104BD000F2365DBE206616D2F1E7FCDA85FEC4FB34 -:104BE0009FB78426D0F7EF7FF1B36184C2E15C7D8B -:104BF000D79BFDC10EFAA5C0F2AFD4CE61B7D1E705 -:104C0000F74BE4BE8A387AAB83F3C199571C5380C3 -:104C1000CE849DFBEFC571DBEF345B74718DDF5B80 -:104C2000CC087FDA8F9DC77A56080D12D8FCF4F9AC -:104C3000E25ADEDB99670536BF97CD211BCC6FE7C3 -:104C4000663940FB2DD8F937A4EB1B7EBDDB0D7018 -:104C500058F0B2C9207F16EC34852DC3B03C6641B4 -:104C6000FFBDDF298C047812D457F3F7CE9B00F4F4 -:104C700030BF7DD5DF4C6E78DFC85F142E78EE63D1 -:104C8000CEC726DF04A8BFF08C1BECD9D31DDBDD1B -:104C900000573AEE3499D2D50FBFD6F12161E347E0 -:104CA000527A8E071E1BA0AF05ED2BD8F7F6DE7AE1 -:104CB0000AE4DB82183E3E0DFFC8E8A93F2216A396 -:104CC0005FF202796724D81D64676ADCFCE26EFD3E -:104CD000C1F97ACEEE0B9BE03CF199E7FFB209EC0B -:104CE000FBB9FFFC6AD3C3E01778CDE60179B4E0E5 -:104CF000971FBA890EFEA95666CF9F7BF6991D4F66 -:104D0000503E39F7470BDA3BE77E7B2A5BA1EB3F4E -:104D1000B7E71FE970EE76D16FC7F605782CDA7722 -:104D200043DFDEF61B40B7218B1EBF21C4AFF2323A -:104D3000FD4E5F020758581983A7D7F7BE9E0DF3A3 -:104D40003C7BC482E76F16D067B5C580B779A81FD2 -:104D5000A0BE84C27BFEAEE57F330D8B0777B5BF67 -:104D600008678548B83FF102DE6FFBF1E81228CDF5 -:104D70003E05C6235D28DF63DF5B7098E2F7EAC477 -:104D8000F8BC40BE9101FE0B76AD60DF6DA7F874F4 -:104D9000F7C4E759F8C7A89EF82CB6C6E273EED35D -:104DA0004F40E3DED4B879241A3EE7EDBBA357BBEE -:104DB00041930F9783F32C9E37F54F8BBFDC0A7C12 -:104DC000F6BC43F5323C8726D0B673BB2F64134A3A -:104DD000275F98BBEE0539D9F55B8B670B7D7EFFAE -:104DE0006F3F46BE3BB7EF3D5961E74F9C02B52B85 -:104DF000CE91EEBF0EB033E6F3D8DA826DAEB0C519 -:104E00001DC5D7FCD0A4718A1B9F1FC3E721C60F05 -:104E1000F343FB6F17E2E06F893597E9A7501F84D2 -:104E2000CB3CD221C3F97C3D5E8552C0E7B11B81EA -:104E3000FE12E1535BBF07D67FAD0EAFDB181FC775 -:104E4000F69F4FF915E4700FFC86848FA13CB7D90B -:104E500022417EE4391E6F8CC57B14FEFCFCE47796 -:104E6000B4171FB226884370385C8EDF2FB7BEEFB1 -:104E70000ABF195605C78D85E3996FE2EB83F55C90 -:104E80007ECC2735E3FAE9F499C54CF5590ED87B69 -:104E9000156A7F213ADFA67613CAF9333B4D21D03C -:104EA00017B1F2627E827D72C8CAEC97F92FEF1FAC -:104EB0000672EDCC8157385D32BA9FBFEB98AC7269 -:104EC000FD10D2EB870471CA5FF2F116BC1A7FBCE9 -:104ED00005BBFE1677BCD392FF4E98FFE90E335107 -:104EE000E910A7DB4D71FD49AD56B331CFD635F290 -:104EF00048127DCFE4B62BB0EE867AFFC72AD825BC -:104F0000EF9BD1CF4224DF17163C6F6D575652B836 -:104F100035B8ABD0AFA28DD7180327C95BA10A253E -:104F200070FEABA284D9D46CDE5ABBD9231AE64DED -:104F3000F56E26E8A5A3C34F99619D9FC6D88F9FA4 -:104F40004AA4A92F1DEF5355F02D55E2ED178DE31F -:104F500007969888A2D78796AEA3301FF23B1B0115 -:104F60003FB2E9359B0AF264C1265B08E29BAFEFD2 -:104F7000BBB803E076EE690B8F77B23CDB6ABE5FAD -:104F80003BB5EFE2A6FFA2EDA7E065FAFDEA4DB45E -:104F90003FD8EDBB1C98F4FCD7E79386112AA7AB4A -:104FA0007FF7F044902FD5B0C7A2FDAB7FDD37D49B -:104FB00040C73BD987D54FEECE0A015EE6BEF0DB97 -:104FC000F9A04FE6FCCA4180245FDFF7F1BD503FF6 -:104FD000F73B17E67B9DFBDDA91F021F507B5BD1D2 -:104FE000EBF5D9FAF3DE74DC395067EDC2255D1EAE -:104FF000C11C2829BDCF7939C90FFB715D3F7C6F7A -:1050000081A5EB21744011B59F887BA2703FE0C35E -:10501000393B8DDFFBAB95D9530BE4AE2AD63FD895 -:105020008FF16B07BEF78D46A7BC3DF67DADFF7FC8 -:105030005A7363C661EFCFB7909A78F46FB1B171CC -:10504000E7ECFC36DF381EA3D79EDF61CF7F2AB0A6 -:10505000FC7CB2C786E77FE7CAE1C129945F5F9411 -:10506000C92CE0DBB9EEF0E064FABDDF707939D726 -:105070004EEBF4793F3E0FE80F7562EDFC15E077DB -:10508000DE4B3602F43EEF772EF42BCF7BF1E2C9F4 -:1050900027E9F333FB1C98C73AEF778B11DFF32C2A -:1050A000E17BC18FD3B5C782FEB1337BDECA067BFD -:1050B000E48C399C9DD28B9F685EBB853B2F8CEB2B -:1050C000A0FB82821A27F839595E4E2D61F70ED463 -:1050D00042E207D0F12736160FE1F1A907B8BFE881 -:1050E000FC0C2509E77FFD2DEC398F5F3F70ABD2BB -:1050F0003759370FC89B23D7D07D895C930F72D661 -:1051000014B98528B42E450662A9F533C1FD0DE01A -:105110000F4D2368BF9BD37CA49A968B534800CF36 -:10512000FF386FEEE6B33F50143FB041E90BE3F9AF -:105130006C4CBECCB3FB47DB306FC478EF82BA8FC8 -:10514000ADEB22BF4F2176BE17CDAA05E479346EB0 -:10515000C7F2066B25E563F0FF92435C2EF5583FDE -:10516000E3B3F39E14E4336D1DABEA3C284F56D4F1 -:1051700079B15C5E574014CC77F661DDC4E16129FA -:105180005409F8578107E1CFE2ACF0C37D16302611 -:10519000C4534DCE00D297C55B83BE022B8F8B9A32 -:1051A0009C2AA976429E078393C959817092795DA2 -:1051B0006A9B8070A5EFE3F3B1F6C00CDB08C83F33 -:1051C0001E6A9053725AB1A1DE036E1A5DECFEDFC7 -:1051D000861F4178ADA8B36209F9E20037C8178786 -:1051E000FAFF07F8B530F85D47141DFF40FEB662C0 -:1051F000E0A704F0DB40E19716E5AB5838D4F23C69 -:105200001D8D9F12F12FE4DB4310667D5D1B96DA46 -:10521000F394047AFDAC8DD923B524B014E3A11E18 -:10522000E68721692AC9D4F99F8857C5732078DE9B -:1052300014DA336F41FFA5865F93473A69947FCABA -:10524000C7B09EC56F9B459057A6DAADE4335D1C91 -:10525000DF34A1C2A6209C7D02C4351AB87E5DD67B -:105260008D4F237FACAA53B05CCDF9642DE79375C5 -:1052700080775A6FF0B1FC9F967104F5E763B4CE66 -:10528000F6FB61A2F78B27FBDAC3668A7F94490A93 -:1052900096EC1E8E2396D020FA9EA390603C23F9B4 -:1052A000C8CF42B856D28EE7AD93B57B605ECD4D88 -:1052B0009E8A712062667A8A98581934C33E2A16EB -:1052C000BE0DBE0378BF44A2F9941D9D2DC0F72EDC -:1052D0004E65B1B3B47BDA8FC07D10CE16073BA705 -:1052E000E8AB19908DF2D582F4EAF405846A1D1EAC -:1052F000D313D87F4BECE3FF03E8F113C84BA4F8BA -:105300005DDF3610F35A5699DBBD200F57F1F31AC3 -:10531000CA140A05DDFD626F7039E92E31CA014DEC -:105320002E7BAE2F36D0B3267753C618E95E93BBDB -:10533000BFEE96BB156741EEA64636225FC6F24128 -:1053400083595685ABF13E1AE67F3A26B0FB327A96 -:10535000CA038CBF9FEFCCD902E7B135FE895DBF90 -:10536000D43C1EBFD36D0F26C87FECCFEF6568A677 -:10537000F446F2215F414144ACA174066590D21914 -:10538000E3A7522C353AAE274C86A87B45364FEE24 -:10539000AFD5CEE2D45B8BFD80C765ED8C87B2ECD8 -:1053A0008CCF96A589A0BB8844F7934EFA48DA3F84 -:1053B000CA0AF6A56466F1FC2E97D80EF1DC65CE1C -:1053C000C956C82B15924B907EFEEEAA1CD05B7C72 -:1053D00007EE5F03FAF3387DE438EDB78CDFEB645A -:1053E000F21413D897EE7676603E94D32E1AE249E3 -:1053F000F3EC815CBBAE5E045FE77887617727B82A -:105400001F6A185F0FC954499E4E4E74DF97A4A8B7 -:10541000A440272FEA07DD88F731F5941309E4E16A -:10542000F6FF1979D83020847835C7CA9F343FDE1B -:1054300001454B15AE56A0D6F9B2BB87239DDE6061 -:10544000877D88734BB71DF4A3DC9EF38C957F5149 -:10545000BDA6A01F8CEAB5C74B419E26D46B35F77D -:10546000211DB7F457808EF7AF79F869A87FB6C6CB -:1054700082F7BE5445561085CEB73A320ACB596DE5 -:105480008F6259D9B6993211214B5757AF990AFDFE -:105490003798D0FF733274CDB95A5A3FD96241FB65 -:1054A000FDE4C6070780FD77B2C5A198C0DEDF38EE -:1054B000C2D8DECCEE7F39D9660E9918FD5E324136 -:1054C0003C8270F90E5E20DD7C49898276FCF99879 -:1054D000784BE55A8B5F7027867F655B7C7B12CFAC -:1054E0006F63726E4D3EC8D7B2A33F1B00F4A1C9D3 -:1054F00099C52954EE01FC8E5A48BCB8C058FBD857 -:105500000580A7B176FF6286AF2BBB37EB3391DA0C -:10551000DD88A7807B92C1EFCBFCAA9F71BB9C5812 -:1055200013B4BBF9FB9EF8EDF35AFEF2E62304F246 -:10553000548D7E6D13F8AB05D88F4F62790F5A1CCE -:10554000A8275D337BBAC582726506F74769741E6A -:10555000A5B3809B9FDB33D0E1ECC83A947BC2AA11 -:10556000A2C74751F87D45E90FE8435835BA2FC027 -:1055700077E9CA1FACBD878EFFF53B267C3E2B62C8 -:10558000C3FE5F3EE27BFC1ED82FFCBB19F349BE75 -:105590003E3416E3C95F9A8D7E8C32079397AF71C4 -:1055A000FEAF8AAC32D8E755CDD365F0835645D6E9 -:1055B000E0F32A0822619EFC5D6F9449105F2298F7 -:1055C000E7F29AFDCEB1F5A84F8BD18F56BDDA1216 -:1055D00037CFFF35BB629057D59D2D382EA1F65998 -:1055E0005A3A1F4F2777AA23A9C81FC4A312C8FF7E -:1055F000AEE2F2A77B7E1BCD06F9F3A52DBE9FE69A -:105600005D3B5B6755E407C8773DD7F7437C5EA5F4 -:105610007DB793F169743D8F8F8AB79EE83AAEC724 -:10562000FE5F26C7FFFE050EDF9375B3889FCAAFE6 -:105630004A0BEDE784EF3FD8540AFBFC8DC9298261 -:105640006E5DD56D73885FB7AEEA8DD364FDFD9452 -:10565000513C2C32E0E1C2CA05888725F68A63A056 -:10566000072A578D1E16C07DFE0A84F367665F36D3 -:10567000C8E3536D0FBAE3E5175F88C54F1BC70F2B -:10568000B5BB4B74F8D1F012FBFEC93F57FFFD11BB -:1056900090531B5C06B9125BF6C05B4E7CB825715B -:1056A000FA3C49F57700E1A6BC7804E87AB503F343 -:1056B000E412C3EF2A12E80D7E09EC676A67591DF0 -:1056C00023E0BB04E150DDC6E8E072708B7E97D327 -:1056D0004159FCF58C766874504B54CAB0C7E5CB81 -:1056E000D1C1C344B5F6B28E6E3A687BA32C2F4A63 -:1056F00007A31DC1B1F5B4DF1760FFE4F7C4FF7164 -:1057000059755F07F6CE4A13C6BD8EDBD5F4BB587C -:105710007D38C8E7E3EEE0C4EB4AA2F5D9DB07B970 -:10572000F5F73A9E6AA6708803BFD18E04F493A75A -:1057300092C291FFEFE8E73373FC3CD1B1F6B2328D -:10574000C02709C6F7276BA526BF4D49CEEE7D2F92 -:10575000E8D1E3CEDCBF8768EB1A7BE056076D6FBC -:105760004C7E08F5FCF1E302EAE1A57F5E9C0F7236 -:10577000B887FD5B1779E2C420F45B3E79C28CF6F2 -:10578000148E4BA8FD037A00CFD7E03EA03FFA5914 -:1057900012C5731F84CB7F4744E3BA5AFC76595D28 -:1057A000C7A3303EB1AAC4A39DD757A064F6D87F43 -:1057B000C23C74FE79D91CF0C0B92159201540F7BC -:1057C0006629D00CF986666FDA705507E7850E9664 -:1057D00097633B78B03987BE6F9BF9070FF8F92CB8 -:1057E000F43B505A33A5F37A7FB939AD9DDD7794F8 -:1057F000A77B9E0BE7A269DDE077A0F3ED65DFFCF8 -:105800001BA1FB9E35BCDF78AA76D117808ED2CD46 -:105810001FB5FC15A991B5276BCD8DAC9DFB51171C -:1058200054323FE9EBD392107EDABAA6BEBA1CEF2F -:105830005B9BFA6A069E739AEACCFF1CE0F91BC8D0 -:10584000FB01BA4F66FA39962E1EE5F2E7EECDA2BD -:105850006AA6E31D34771D70005FFC54C07DF55DC2 -:105860001F1E3403C9FFE9F07133DC97701FA4EAEF -:10587000D0F54C238ACC8CE810BE3F9DB4BB58BDFC -:10588000BD0FDC7F1A1D8F6E9961BC852CFE7CD705 -:105890008787C7821AA5E32D83F2BE77880CE34F72 -:1058A000DBAB34B163517CBC57E9786274BC6EF8F1 -:1058B00049568447143E568497061FB85E04DBA3FE -:1058C000F0457B45836F03C08DC26F6AD2949BC93C -:1058D000B0C4FC32D539F873765E8CCD2716BE5F26 -:1058E0004313E5B7A71CFE3DC07F8D0EFFF3C03FFD -:1058F00073AD5DD9522E9E077B119ECF370506A44E -:105900000FC47362F97D200FAD237E9C37964F8FB5 -:1059100002BF5C0D25E50B98073FB7722F5FE7EBE1 -:105920003F3BE5C2F328FB3ECE86729EA973F59DF0 -:10593000C06FFF6642FBF3FCDEFC5EF3EB8E72BFD2 -:10594000CBBB0E7E9E88AFF33E6ECFDDB7D7118204 -:105950007B10EFAB3575EFAF80AEEFAB65F9274449 -:10596000EA1876BBC19E6CE4F1909EE3C07E21767E -:105970001C6D9D07B2FB5D05FBCBA747C8B88FD850 -:10598000FFCEF93F56D3BA3DCB8AFB84D5C99C7E66 -:10599000CBD8BEF5E964BFA308FC5F2B537C2A5D1E -:1059A000E7CA3748BB48E17460C843A1F212B81790 -:1059B0005A44DFD9DAC8D66039BC57C8EE9DF170B9 -:1059C000BB746DC7F136A0C753472C1877F8D2C502 -:1059D000CE13AE345764831DFFF96639EEFD679F21 -:1059E000BA249CEF66A153003A9F4E825690177BD3 -:1059F0003B26F785F9B87DC403E47F6AA34964F7C1 -:105A0000A369FE96B0C4FCFDAAC4EA7E5E7A6CFA75 -:105A1000FBC6568C1B83791E335ADEC3BC5A7709EA -:105A2000F3DBC5CE23C9C9E6EBEA48C17C52D718DF -:105A300011F3B15DBE2E01DE1BD0512EE3FB41A15F -:105A4000D7F7072CF18C07B8C2FB20E7075CE1FB16 -:105A50001627CBD35AC7F7D99BCDBEA631749CCDA0 -:105A6000AB9305C087D64F7132B9726A8CE6470A8C -:105A7000A21F293BCF63837B2CB2FDC8DCC4551227 -:105A8000C4FBBEB7403FE66745386C1EF26218E2C1 -:105A9000D82BC1BF027836337A5AB95A40BF2A850B -:105AA0005F3FD0139F3F66B905D631A059F0C0DEE5 -:105AB0009D9671E73DC5656574DEF238EE0BC14D0C -:105AC0000BE3666FFC00E7E54AB0DE7A17BB27FF01 -:105AD000F3CBD0C7570E766F62766D07BF1F2F8C42 -:105AE000F7E005B57BBEFC25EC7E13C9AFE8F36398 -:105AF000A2FCB394D321F1439CADB2540E811F415B -:105B00006CDE3C05D63D3D682137D1F5B5081D7EDC -:105B1000E0177584C8EF53F21F0538AD59D717F356 -:105B2000F0968BFE6CD0C3EAFF91314E77C07F7E3A -:105B300003DC1FBFA95446BE380070A7F5A797E441 -:105B40006E8638A5ABB6BC6D3A1D2FE49151B234C8 -:105B50009490B7F3214EB944F408B47FB042CBDF40 -:105B6000F6E0799EE1A6AFC617401C2F43449FD2B2 -:105B70002981DDDBB06C49B907F0BACC9326E8F790 -:105B80002F77723A389A5271A793C2C7FBC87A0F1F -:105B900035E3287FA65E057E44B55956B6B3782115 -:105BA000DEF790CAF192DA2186ABDC5877CE4A81D3 -:105BB000FB7499BFF4D19B03CCCF09B1D191E8E735 -:105BC000E47F5EC46B1AAFAD1C6AC74A6B7D15F6E5 -:105BD0008771D2E938A9256278241D774BB27F13EB -:105BE000FAEDC65A114E44EA6C033885C6F6C3BCBA -:105BF000F0F5A306BF07E758520F754D063D1ACAC8 -:105C0000B2FF6933C8A965B2027C9EBAE4E43D786C -:105C1000F99BEF170F4299DAF8D1C320A7933BFF06 -:105C20005687CFC7C906FF62EA275F7E0BEDA9152D -:105C3000B2C14FF94D4AC5CF012E9B0A8341BC1713 -:105C400013309A1E5DC7EEA51DE3E0BEE3539344F7 -:105C5000DF16DE8EEB6AF5845632B895805ED0E0B2 -:105C6000B65C54DAC3B0AE8956A48F3CD281F22A16 -:105C700003A2D903A37849FD64C542C8D7889DCF44 -:105C80001AA7D07DFF06DC1308B882FC1839630C14 -:105C90009E43DC53DCE1057B7E7582FB73DE75B1D0 -:105CA000F72D22F3B3C6B6BFED62F40022B1AD18F2 -:105CB0004B7F11944EA226419969C5FBE6F688CA2E -:105CC0007F209DAF3729801FE86FA6F8DBFFF669BC -:105CD000F42FEE0F7E80E5B3AE02FC1E6D0FA7D34E -:105CE000F7D794B0FB8ED778188D5437337951EDB0 -:105CF000EDB442DCA4BA9078B6707A53353883BFDD -:105D00008CEBABCADB195CD30A09C67DC11704F75B -:105D10004DA5433F0ABFB4E6A50B118FA4431D4810 -:105D2000FBAD8171013F8D2CAF9F904E2BF26FD058 -:105D300084714FCAEFEF825FABB2A52FC6FDE1F8C9 -:105D4000308C97C2BF9BC2C7DB4CC701FFE1A9667D -:105D500013D982F2AD03EF675796505A46FAEC2AF0 -:105D600083F39A4A89C7B352A3034D8E51D6984103 -:105D7000F505C06D86AA2E04FA3B6EF5BC0DF370D6 -:105D8000B45A1458FF8CD6971683FDE2F07636830A -:105D90007CA82E65F34D69A1CFD1CE51DE85FED50D -:105DA0002D16857D8FC3AF84D31987C34C3EEF99E1 -:105DB0001BD9BCED59A120D067F5120A57680B30EA -:105DC000BA0797E82511F9EA10ACDFA5A6E3B87D7C -:105DD000A6C4F0450CFD69EBAAE4EBAA5CC2D6456B -:105DE000383FD1698561DCCA12B6CE1984BD2FC295 -:105DF000733AFE4CBE9E4AF5452C67365B0CE36F4A -:105E00002AD8D601F3C92994153C3742D87D87D9C1 -:105E10007C5DD98DEC7BD9852F22BC48AD6EBEE868 -:105E200057D5D5295F9D7A8B3216B573856C2B12A9 -:105E3000D3F19FC918CFC96B35AEEBD48AFCAD70D6 -:105E40001EFCB3C7648C7BEF117D4707E07E545680 -:105E500098FCF17D3001E4F4CC461FC8F1DD650CFF -:105E6000FEA76E2521A08741872A5200DE830E05FA -:105E7000785983F1740A10A15BEED1F9D12D53B397 -:105E800000F23232F0B95920074AD9399F2CFDBCB3 -:105E9000E9FC529BD3CB211F2AAD34A55CC6AB5D78 -:105EA00063DA0F3D315984F6834F3C08DFC920BACD -:105EB000F5D076D93D909D6B39485BA15FEDC94720 -:105EC000001F2DFC1EF24130B3142C0F42994AF9E9 -:105ED0007B550ACC53226374F7586E7F6C249E0363 -:105EE000C794A7622CC324CE3D97BAFE43787F5552 -:105EF00088D3CFE5560CFBF3ED8FDD3804F6F16B5C -:105F0000C04E4C8273BC9EAF204F47F58908F735D1 -:105F1000E6B0B590D69753BB11EC97B5051F89C075 -:105F2000776BF6121FD0476AC53F2D7A3CDEE462DC -:105F3000BFCF23C96415F0FF812127C7019E42FB13 -:105F4000A9DD49FB97FFDEF98403ECA13FB23C9841 -:105F5000CD6FD5A0FE7E285B8E7B1F2FB98C9D1840 -:105F6000DB3F65D064F4E70D685D370EEEF7AC1EDD -:105F700027F96EA2BDD35ACBCAC08E512A2875F517 -:105F8000A5F3DE387C2930A13281C5CB9471ECB900 -:105F9000328695ABEA0E3D0AFBF6E04EC99647E71E -:105FA0003B7405BB576C55E1796B80DAA52565CF4D -:105FB0005B6FA5CF4F94502D489F9FB8FEBC0DE25C -:105FC0003B4F9794A7023CF7361BED3A02975DD101 -:105FD000FD509125E877D179B57C48109E264BB8C5 -:105FE000AD92D64D2F39C1C2E9B1CF59D1B2790A9C -:105FF000D0E98C0219DDF6B1EBFD88EB93E9B55DD4 -:10600000E3E07EFD1C9530FF7EF07114CA33B9C801 -:10601000C8513B50E8B85AD9FE2428F9DF04B91C0E -:106020002C0CC8F08A26CF5A0655EE0079F6676E1A -:10603000D7919A5978BE0CF9DF04F6505759BC7DB8 -:106040005389D38EFD4F6DBCED63F053CFA865F639 -:10605000FE808D5F09880F6AF765D0F10794E055DF -:106060008364C692A0B508F09327124581F9B41352 -:10607000D82704A9FED1C3411BF7BFFBFE429705F9 -:10608000F9B0046C67DD7A9C7C3DD93EBA9E387AC3 -:10609000BA987FF7A74F7DB57F14C07F09DB220D2B -:1060A000081E13ACBA790C50AF6C1ED7C07860BF15 -:1060B000BAD8F9535749279E938A95EF60CE03DFEC -:1060C0006E729C1BCEF6F74679DAA3CEE92AF679F2 -:1060D000768CBC2AB2B4DF8CF8DDCDEEBD868C5850 -:1060E000681788A8B07B3F43DAFDD435D06FA8CBC2 -:1060F000E9013A6819F25131C06735B717661612CF -:10610000DCAFCECCEC407B617A23B717245F130859 -:1061100059C7C664B252673FA0A9045BE8466E2F18 -:1061200068FA9FEBED6A6F4733EA55B00F747AB5A2 -:1061300052657A758097E9F5EA66FA1D8513F3488A -:10614000BD5DC2F4B8D2CAED07AE8753F977D39AD2 -:1061500099BE4A053BC20D69102AEA658C61A547C4 -:10616000ED963E854C5FA6B6EC41BDD60E87B64790 -:1061700080DC60FA32EBBDC32A80C94B1FB75139AE -:10618000FD246FF77AA87D9612B5CF968B3CDE443E -:10619000987D8839FF749E8F427F9DDDB88DCF6FCB -:1061A000CFC1945B40BE6E0FE6E2F9728D6FD1FBFA -:1061B00049EBD9252C7F25BB96C5C95DBEAA1D26F6 -:1061C0005D1C62968BDD3B344BA3ABDAB017C60D7A -:1061D000C2FB28C7D9FD3F2BE0BE1EA017BEBFBA29 -:1061E000CEC9FD1A9C7E12E9134D0EB988DF5D48B9 -:1061F000E17B22B403E5B54AF74BB0B613C1867E06 -:10620000F703BF072795C0FCD78CFA3BE67F0C4805 -:10621000B05FFC54DB677E47B9EE1A7798ED433BDD -:10622000C4B8E77B32DDCCFFD02E1107C0D3166493 -:10623000F7C8D94AE5B8FD93DCCCCE3ECDE1B666D1 -:10624000D40E3CA799503F4B4435C5D1A79ABE6D9B -:10625000013C5F47FBBBDE6E52719F1EAA30A17CE2 -:1062600025B8EF0C924EDC47AA0532FA0D5BCC4103 -:106270002BE0636D09C7ABC7BA19CEFB7E67BC5074 -:1062800078009E57F8C5909003780E798A985F073A -:10629000EF413845F7EFFA78C510B7C8E1A4E00F31 -:1062A000F30D6866F4B566948CF358393C7DB329D8 -:1062B000472F7F052E3FD939B195A3DE44FABAD2D4 -:1062C000F955D53EF7D4095D3CF1E486677201CEFD -:1062D000BA7B307A3D4F5155FBB7D66D71E204DD84 -:1062E000EDB08F72C23E30749721AEC9F13BC62D1E -:1062F0001AFC6E205FCDB8B908F503FFD2EED121AC -:1063000037BC4796B0B8ED6C1EB73DBDED363C5777 -:106310005E44C9CA1C07EF5FD619CFDF7FB9FD996C -:106320007ECCAF1132E409CFDEF1CA50437CD84FA6 -:1063300094B491EC1E63D4D36FFA548B297A0F81F5 -:10634000763FD695DEB79542CD30DC77910A2CD3D7 -:10635000490D965E12C4B21F6967E766619F3B10E4 -:10636000F44217960AF1884427F773890FEB79A452 -:10637000024B09F0961A8D4B483BAD98BF01F10BCB -:10638000E0FB44E7CE7CEECA856EE4EF9AABD9EF32 -:1063900018B178C564B7FF0137E2218CF27B3A1758 -:1063A000E5877E35B41DCE1F3DB09A9D7BD1E43B81 -:1063B000EE6FE8779E4B61FA405D2FA01CAB774CE7 -:1063C000FC21C2B3C57C461F6F20566B1EFC3E8865 -:1063D00036EE74EE6798CEF520B8BBD9F9411F9E12 -:1063E0004F9A0EFE065D3BE96E67F7D968E3888E2B -:1063F000EB07F716EFD3BD8FF9D19531FB80CBEAD0 -:10640000EF98FA8CD8F7BFA1134A8FFAE39EFBA14D -:10641000928DF4CAF537252805DF6BB61CC3FD58ED -:1064200070AC5F0F9767391F687A65464CBE476C42 -:106430003943E2FC11330ED580C970AE17EF96D008 -:10644000F1B7763FA9F6BB5AB3FD013983BDE60526 -:106450003C7AF8BC83646379062DBF80BACEBF7FD7 -:106460003829F0925BB71FF1F86B44FDBD377339E3 -:106470003F8E35B594819C3B15203ED847CC2635C0 -:10648000EE1F803FFFB009E55C7F3A6FB918EF1D42 -:1064900053C514ACABF07B2F67EBD839A193FC7ECE -:1064A0009A1DFC7E9ABFF07B858BDA164F043A3832 -:1064B000CDEFA529D8BBA202FC3E45ED8E69A0F721 -:1064C0008BDA4757437BD14E0BFB1D1F2E27B47928 -:1064D000C1B96C3BFD4E26FD9E3505E40941BD7BEF -:1064E000B6C51E82DFFF39DB6E62F7AA168A789F77 -:1064F00003DC8B66E2F34B4A81EFFDD7BD608F9CD6 -:10650000E6F2E48C3B99E14B5205350DD252880FEF -:10651000EC9A758EF9780EB2CA19DAF1441AE4874A -:106520005B7DF5F4FBFBF7BC940DCF1F77CCC7F276 -:106530002F1B3ECE06B97576DFC7723CBA9D278504 -:1065400065F04FCDD92B88103F296B9F26437CA443 -:106550006AD77EF42BCFF304B07D6EDB1EAC8FD9EF -:10656000F51EC64F06262938AFB31901F4F3E6B578 -:1065700059C2F07B1CBB7383F7C78DDB27313DB35A -:10658000CEF11A8EFFB8E3B537112E1B2C78FE63BF -:10659000FF86DFE3B867F6BDC4E74B305FF0ACAD14 -:1065A000FDE8CF417FEDE1E731AD1D6EBD3F584ABB -:1065B000120CF2F5AC8BC7BD322FD38FE70B1267ED -:1065C000879BC9A50E37C4CDAADA191CFE620ECB73 -:1065D0006047CE691714F83DBDB25D9BF13CE09C6D -:1065E000BD563C2F3107E00170A3F042B8B4EDC7AF -:1065F000F9E7025CFAC03A3EC07CFCBCBD142EC375 -:10660000A2EB9EE30C20BF6AEBA57060EBDE7D3948 -:106610003C058C786A7B4F06BFCCDCBD02C26FEEB6 -:106620002E368FAABD6C5E63764D43FC9FD947140E -:10663000F0B79CDCF3F16958CFD97D56BCCF579B9E -:1066400017A553E22E06FE61744AF632B9AAD9DDC7 -:10665000F342E9F8BB03DDEDBBD8EF9202C86C94BE -:106660005E8BF64EC2B86009102FF0BFA77D28FBE5 -:106670007DC16036C075F7E87036CCFB8CF6FB4800 -:1066800052301BF0E273074A9274F8F8F2D84BA824 -:10669000170BC49A4F1F013E7E5E44BB68F127EB87 -:1066A0000CF7ADDC003F483502E0F6AE1BE1D67DCD -:1066B0008F4B90E54B9100F26315E7C7B39BE9BEA2 -:1066C00093AEFFCBB617B0FD6C8631BFEA2F6DAF2E -:1066D000A700DC2AF9790C12BA0DE511854BB33508 -:1066E0008E9EEF3ED71662E715CF09FC5ECDA7342C -:1066F000B8D5C8930D713E260F3337E61CC47D46CE -:1067000028FE39C7583B29F6BED444F900C7B93C26 -:106710003BC1EF3FD0F4EE6477605A529FC4E7BDAF -:106720002B57CDCB067857C2D948BC0775FF4DE033 -:10673000AFC07343EC9ED430C0E7A4760F2A79E94A -:1067400026C8333D99CCEAB5491DCBC1AE3DA9DD84 -:10675000ABAABEC1DECF61EDADD04EFBFFCA5D512D -:1067600093C4EC7B81FDBE8F39197EA741D31B8971 -:10677000E160FC9D8667E85A012E74BC9FE37812A5 -:106780001DAFE8FB8FA7C9E9EF3D8EF57F761C4D65 -:106790007F017F42EA23F1F986FE4FC0EFBFFB3E47 -:1067A00009CE34F0D5C50D039B208E7681DF23639F -:1067B00069594A409FCF6C5D17F7F7DFBAEB3C2F62 -:1067C000471E48F94DC7D78792985D7E88CB69F8F8 -:1067D00083F89676CF24FCB5A463EA12EE9FF3F912 -:1067E0003DE6052488F6E950D28E6521E9C072188D -:1067F000E9C212C3CC03C155EA33F1FB6847C2E2D8 -:10680000E75A034FDB44CC3B7803E410DC4B2B9876 -:10681000C09E9C7F1DCCFFED240F8757D8F07B2BAB -:1068200044FF7B180AD88313BCBDD983C4239DE9D8 -:10683000CE7BC9C57B6DDF4BC2F525FA1DB5853111 -:10684000F7DEB073E11A1CE69176CC237963E3039B -:106850006F0FA1F0BF7F970BEDE4C11B1B17823CAC -:10686000BF9F74A4C339E1C1FC1E11D266FCFDA612 -:10687000216D16E3EF08C7FC5ECF1CB88704CFEF8D -:10688000199F6BE770F11EC838F918B1E778FF9AC5 -:1068900014FFDE175218FFF75062CFF1EE6A17317E -:1068A0003FEA01C8BBD2ED2F866CABB118E94BF9BA -:1068B000B73CB3AE2EF8983FC265F76F177A7EE704 -:1068C000FF020F2194E60080000000001F8B0800EB -:1068D00000000000000BDD7D0B7854D5B5F03E3391 -:1068E000679E99849964924CDE131E2128E004432C -:1068F0008C68EB49881811EDF0A845DBE20404022E -:10690000249940D1E22D2D131220206AD08840090D -:106910000EF828D64727BDA888813B20225AED0DC6 -:10692000D5B6D45A3A20554484F145B9BDF57AD745 -:106930005A7BEFCC83A460AFDFBDFFF7A79F3DEC90 -:10694000B3DF6BAFF75AFBCCE50E85B14CC69E5654 -:1069500094DBBC2319FB12FFAE893D6FB1EB181B12 -:10696000CBE0AF8D4D2C67ACB541B5AF81526BD04C -:10697000AAE99DF0B4EB824A316379A9D5E6F950D2 -:10698000660E9D7D989BB109FAAB0FBAA1BDB151BE -:10699000BDDC04E5FDDBE6F71AB0BF4B6526983297 -:1069A000CF01E34299E5E882C3A0DC66FFA5631648 -:1069B000CC5F6283F7304E819D05DD30EEDEAD7732 -:1069C000EAB0DCDACC5836CEA3F87ADDD44F658F46 -:1069D000E1B29836A92C8BB122FC27CCA3B2B51F0B -:1069E000EBD318AB693C6E89D8E07DA46E121BCD49 -:1069F0005895BD98F6A9BE73FD0758DEB2E498C35A -:106A000007F3BDBA75E56F26C0788620AC0B8628E3 -:106A1000FDA2F5ED09305F74AB916D633138142E32 -:106A2000558F45CC3421FB12FECB5F9C5836322863 -:106A3000978A7231AE23AE1ECA978BF9199BCEC2CC -:106A400059582FD6EBD418837532BBCDF9DEA58CFF -:106A50005D6357D8978363E5B1A2BCDDD0516D85E6 -:106A6000756EFF93E26981EA7D5BE714E1FECEBEBD -:106A7000E02BB2C33E9698D346B341E79F9FC1EE49 -:106A800016E717B0E85CF80C5B982BD67EC4A3CD54 -:106A9000261F8CD3B68C798E0F63CC1CDC6FBD1493 -:106AA000CFF1A0C10345B64261D34350AFDA981687 -:106AB00082792E17F892FC5CB1CCFDABA186D8BCD4 -:106AC0002BBE983A1DCF379A6AD5B629E7AF4BF659 -:106AD00053EDEE009EAF219F7952603E83B337D7CE -:106AE0000EFD2E7DDEE8B101C826FC62E4A008CCD4 -:106AF0007BE94BB730772A8717AE575D62F41CCF1E -:106B000060CCB4C4E9512FC77636C2C74F6CC6A05B -:106B100009E1BFE4EE0EAC6FDD5AE172C7E1F5CAE0 -:106B200065768F0AEBDCBCCCEC5161832BC5FE9201 -:106B3000D757E0D07983D0CFA8633EAC5F04E7801D -:106B4000705C644FA1E74251EE52035370FD5D80CB -:106B50003F2D88AF8B39FE2ECA310711CF17BD3AB2 -:106B6000249BF54357F2F9F832976728AC63F3E2B8 -:106B7000992E065DAB16EEB75C07FB5F946AB623F1 -:106B80003EEAD34A1EBA1AF1FD350343BA6A4DAD47 -:106B900070CF8A1B4F9F56E94278E875815C666723 -:106BA0006C957D46AD9A83F812D8C43C8CDDD771C4 -:106BB0002D2FA7067215A87FA8E37A5ECE0C6C5223 -:106BC000A0FEE18E1B79B92090AB83F2CF3A26F379 -:106BD000F2B0C0262CFFA2E3DBBC3C0AD690CBD897 -:106BE000F31DB7D40660FE568367BA07E67D06D666 -:106BF0003F12D61F12CF17ECFC5C65FD2FF13DC094 -:106C00007B877826D73F27FAED1CA07E97A8EF193F -:106C100060FC3DA25F7880FEFB44BFFD03F43F2093 -:106C2000FA1D1CA0FE3551FFFA00E3FF5AF4EB1DDC -:106C3000A0FF6F44BFB706E8FF3BD1EFF000F56F50 -:106C40008BFA7792C63F22DA47C4FBFCD4F6B7032F -:106C50008077F9C0B7F0AF34B53D1DF16E7373396D -:106C6000E17FEB58C0F391317CCF579817CBA31D30 -:106C70002A8D371AF9313CDF14E3572D1C7A1FE2B5 -:106C8000DDA237F41EC4C356C573D807E30716EA5E -:106C90003CC87717BDAAE778BE500DB238FA7E33EC -:106CA00069FD5BC4FADAC47A7F651F4C7453B4C4BF -:106CB000E59924F925D2BD3DB16C067AD260FE3645 -:106CC00027972FA50BABCDC3517E807C41BEB9C2A7 -:106CD000660C9B60FE157695EADB9CD576AC0FD8EA -:106CE00055923F2B9CD5E659C8576DC0EC2A603EA3 -:106CF0003B1FBBCDAED606917F386AA87EC22F2639 -:106D0000D9918FB6B1A8A30AF7B714E40AF4DFDB70 -:106D10005C4DEF8B1C9F39903F1F4AE7FBDA9F7A4F -:106D2000C0520CEDD43B74242F4AEC2AC9B1C14B9C -:106D300075413734D96F5FA4C3F2236D5C5EC15FC8 -:106D40006A19CC3F944FCFB6DF59F15A29CAB37BA9 -:106D5000548FDBCDDFA971F26028CAAB349C373D7C -:106D6000415E7595330DC70DB8CCC1C760DCA12A53 -:106D70007365A4C7E05EE4D073F9A29FE441B9361D -:106D8000A423513E15B7C7C92786F232513E25CB01 -:106D9000AB8266E08F71FD4D2E7B42D9E24825F92A -:106DA000043CC6F3254CBDA87BD1755616E3D7C964 -:106DB000F2A855C807C9775BBFB83C413E48BE9CA6 -:106DC0002C1F2ECC5FDFBC7E38E121702BF785F9BC -:106DD000EC9B8807807F069F42F283A93E9737F598 -:106DE000C2F03218BC76BBEDC2703364BE457A8502 -:106DF000C1A7D2F8E7C9950BC055B6339A1FE93A37 -:106E00000E72EDB3777E58CA806456026CE8FC338C -:106E100075C1C760DFF94B9EECC2F1F30E58DB1071 -:106E2000CE46D7ACAE36DC4FC7438C013EE9CD1C15 -:106E30009F8C39D576ECAFEA3457FA10283FF1BB76 -:106E40005B15C0277D46B387C1B91D7CE6B5F41B31 -:106E5000107E6F1888CE4D3AAF9D0DA1E510BEADE6 -:106E60002AB06E5D4378EC33239CF2B79B490EB099 -:106E7000C0A3AB3540EA56380E360EEBA7AFD6604E -:106E8000DFDB95BEF2F5580E058DBC3DB068FCBF4A -:106E90006E9D22EA99A6BA48EF14F5BFACADB91AB7 -:106EA000DAABF64B55903B8BD63DDB6E28C07A9D16 -:106EB000ECAFB14AD82FCE27CA2A9CCF93FB457D91 -:106EC000E0A5F61A20A26EA39C9F05B07DB74EC721 -:106ED000CB819E761CFFE96AD13FF0F86A2D9FD6E0 -:106EE0007383DE0145C72BEDB62B63EB5D97FE4642 -:106EF0007B0BECEF2377240DB6C11AB71ECF42F9F6 -:106F0000BC6A7AB317E18688EF05993848EF263CCA -:106F1000ED3BB71D930379507BE6C0DFD246429527 -:106F20005F1F399002F06BDCD96C36407F93C11B38 -:106F3000C82B8EF56BDC5147FA8CBFA78C9EFDF4F5 -:106F40003BA80EFEA7FA998D1731DF47E1DF343DEC -:106F500005558DFAE6769B9EDA337EFEFDEF4FF601 -:106F6000FFE8A9DFDC8CF39D7647B22642EB556142 -:106F7000804B3FFD64FBA69D93E9793845BBCF016B -:106F8000EFE702EF227EA5367BB07DC8DC61F7001B -:106F9000A02D860E2FCA0D007D5057197BDEEF18ED -:106FA0004AED93DF27D357C8CC3226211F6F5049B3 -:106FB0004E85CC8194D1505E0B76480B2C6979D9E3 -:106FC000EFC68CC4F2B3368676496BC37ED748A42D -:106FD0002B8F91A1BEBBF6CA500ED2795BA371FA7A -:106FE000A388BFE145AED971FAD6BA7403AD63F593 -:106FF000CB407797C1D3107228D87F18C80D05F9F8 -:10700000A2CF8C768E25279D058AB19D6D2DD2E766 -:107010006A83AFB61ADBE5E848BE58864DABAD864D -:1070200075B832758A9ED65173780ECA37BB112552 -:10703000283B923E7327C2E949D5D38C74F8A4CD7E -:10704000660F4005F0480DF99F3ACC19C4B249CFFC -:107050009A518EE795813C8FD3638F08FE79C46186 -:10706000247EB7D6129A5C05E35817E9EC01986FB5 -:1070700075E3FADE0930CF4F1B9F3BD402EFD76494 -:10708000A90CD76173AA6123C81FC38DB04658F7F6 -:10709000D32D5E3BF2D768A6CAB641BD75A891B99B -:1070A000E3F8956D2494E3F8648653D52CD0FFEF74 -:1070B000E9BE7F77C0BC97BFF19619FBBBC6EA74E7 -:1070C000483621959F735A79E238F6AB13C749AF1A -:1070D00049AC774E4AACCF9A9658EFFA5E6239F7D0 -:1070E000F6C4F274896FC0736C208FADBC8A5923CB -:1070F0001F2F43790BF0F903C2DF5AA2F3207C2C37 -:107100008D8F9E9803F579C84FD01E1ACD48EEEEAC -:107110002BFC1737EA05A6F466B763E4F9F0C82B31 -:1071200030DF80E7651BAADA19B4B7BDF3C11738A1 -:10713000BE8DC5B52B46F8685147262FBB603DA9CB -:10714000F80F37C2BBF9CF3F46B97848EF4178E72F -:1071500035AA34FF3DD3DC413DD7275CA8CFA489B5 -:10716000F669E6B5BD7AE0E769EFAC5E88766F3226 -:107170005CB358B3827409F8C1EDED3A46F26395F9 -:107180008ED523DEA08D80E3917A04FC626A86911D -:10719000E0644A5784DDA8EAB03E4BE84FC69CDB6A -:1071A0002D48C72B0E70FC5F61E4E3F48DE7A64920 -:1071B00011E519F2C98C745DC238EBEDA28D286718 -:1071C0003A78B97B7FFA0D4897EBA7A58F413C3100 -:1071D000A1DD05E30DCA376B23607F96578D01054E -:1071E000061DA4B2FD0638CB6E2BBBCD0BEBD878B9 -:1071F000D01AD0C37BCBECFBEDA8A7958B75772F6E -:10720000F7BC897C205AA7121C2D991DF63123F951 -:107210001E02B03E4407948B55C33A49CFB3547510 -:10722000907CB7947574209C364ED291BE917EBBF3 -:107230008EF0D952103A3414FD04B375761C2F1D0C -:1072400004BF11067920BFC38B7E130630D755705B -:1072500054C1716987304F8680ABD3B9E3870A8CFC -:107260009381E38DE6ED114E0E01A7ABD3DD0477DC -:10727000A718376328B41FCDC769AB888D23CF719A -:10728000632D0BE2FAE4BC729CBEF199A6205F3537 -:10729000FC0AE006E7A4149A69712BE633B28FBBAF -:1072A000977B9BB7125DDBC8CF91EBCCAF463CCA56 -:1072B0003DB8698A6E34F6B3D23C86D92C88789C66 -:1072C000AB32F337D351BFF1121C93E935677FC757 -:1072D00054D453E5B924D36F8ECADAF5E9E7D371F4 -:1072E0008ED3595D32BA1F7A4EA2979C83D13B1040 -:1072F000E993E97A4BCAE932840B8B6FAFBF7059BF -:10730000AF0F1D423F0FCB063901A02F4C9A8FB112 -:10731000FF326159613AF7974390EF3B84FF06E4EF -:1073200015106BF718FB781BD2E94246F855FDFCA7 -:10733000DA5B7F05E39D1D66B4A35C2938D8D18B49 -:10734000F291EDF40DC773D8ACFA1E4E81FACD87D9 -:10735000B319F2EDD5166E8FA902CF93E5CB3A4162 -:10736000376E9473AE7FFE29F5C3D0D0AC4BED40A1 -:107370007BEBEEAF7DD59CF9BFA867B1A749CFCA1B -:10738000DFDFDB62C3F9D71D6C37037C2D6FF0F6AE -:107390001D500EA808BF06F267ED2B98437052DF10 -:1073A0003631C4D3517A2D8865F6470B43FEBBFDB9 -:1073B000D9EFD5BB91FF644D74231FDA26E83D2831 -:1073C000ECB3E4FDAB46CD87FA44F2FB4DE93A71EC -:1073D0009EDE1375708EA31E31B2355059AA9BD90B -:1073E0008EF65D7435F05FA89DA97737DD1D67DFE8 -:1073F000DE6BAD0AA5A35DB2CCCC7CA030E79F5379 -:10740000980F88B3C0F99B2AE43F852CACA09C2D33 -:107410006C068517F16AB195F9E2F03DFF9C4AEDE3 -:10742000EFB56AA1F4B1FCBD19F88081FF933D99D5 -:10743000EE65754ECEA3507F313C653D8A7C833925 -:107440006BB43E7B6430E22FC87D986FB7D8B7012C -:1074500060681803FFD97461D3E8F3DBEF1370524F -:10746000CDB630F24BD5F6FA61E22F76F5547C3B7F -:10747000B4BB89893530F2CB225CA8FC033B95F381 -:1074800080FF9AC690DE1F40FB3B90C6ED11A669B7 -:107490006E6716D20B2320E79B59BB19DA11B6038E -:1074A000BDE5B05E0BE9CDFB991BE9013D6CEFA595 -:1074B00010CB6208D7CD8CD5C6D3817C4ABF84BAA5 -:1074C000444FF6D4A52F59683D866616B4A03E8475 -:1074D0006B0378AB8B59502D8EF905473BDCD4CF2D -:1074E000C89A499F7DFA8B23B9C8A7AD07401FBB37 -:1074F0000CCF59477CCA6A4DA43FC65A084E5181E9 -:107500001F5DCBEC74CE7DF69BEF2D71CE91169462 -:1075100017858BD313CE57B6CB3F97C77C97C78FB2 -:107520001BA471F387EE57D02F937FAE90EABB96E2 -:10753000B92F30FEE001C6CF213C1A78FC7CAAEFBF -:107540000ABFE5B80940B139BADFE175C7F4EB64A9 -:1075500038E72F4EE4CB97ED4C2C4BB8580C9A7370 -:1075600032C0DC7287CEB315C6BBE27062BBDAE212 -:10757000DF92FD1B6B1F764EC5F6609F6F85B75778 -:107580009D486CEFAD7AD981741C6BCFD777CDB99C -:10759000C476C9E793BC5E5857E6B7E3D635DE6CD0 -:1075A0004AA89F5E77DEBA32BF13B7AEEB5C89EDB7 -:1075B0007D2DFDAFEB8652D33F5C976CF7ADCA8B48 -:1075C0006B97BC8FA9B5A601E0CEDB7F67FAC58DAE -:1075D000FBDDFA7FDCEEB625C9F30408DF17E9B45A -:1075E000F119503F135FA1BE68B392DE7B9E9D25CB -:1075F000E4D344543CA09F274D9B88FD6A25DD09B8 -:107600003FC3C1672EC946BE9E27FCE84CF815BA99 -:107610001B5CE457F089F6204FDA905F746F877E29 -:10762000697C5DF1FA534603B72BEC2C4AF42CF538 -:10763000A5746657B83DCEF59D81E6491EFF1E54E0 -:107640000061BDB3968C67EF021D3E67B457A96811 -:107650009F6D51481F9855A3E953013FC6B52BE4D0 -:10766000579A75D79B0FA03FE6CAE3EE9D11783F6E -:107670002BE8F0E0B44DBD4CC33841B67E61D98FE4 -:10768000E1F9E03E4671342C2F447CB3696EB43787 -:10769000EA704530CE294373991DF9E6F76D1AF269 -:1076A000CDBA69DA1F68BF7F07AD04DACDE65B6744 -:1076B000CF774E3662BCA3EE7BEE4AD47BEA42160D -:1076C0008D9E66A65A611F75A08FE133DBC8540BEF -:1076D0003EADCC8CCF8AE55CFF4AABF41AEB60FE82 -:1076E000BA9E9F7D8EFDE6AAE1BD5C9F0CD2BEEBEB -:1076F0007A5EFD0FD4D7666B5E23F28B4BB71BB956 -:107700004E2AF0615428B18CFC20BE5C164E2C5FD2 -:107710007E30B1FC710687EF38E1C7DAB7DB447C15 -:107720007BC18756D23F7781C0433B39F0B489E4AF -:10773000C7F805363AAF0F4F5AB7A25F6FEFDB5667 -:107740006A3FFF490B6FAF0B3D83E5C03329646788 -:107750002FC80855A4C3BA5FFC424FF0C66D19701C -:10776000FC67466C5D83F597872A302EF6DC258C06 -:10777000F562BD1A1C8DFB7CEEBFB8DF3AFA842996 -:10778000B80DC6FDF0859F3DF3239CF789BC7405B9 -:10779000CEE72A940BD06EDC23662BDA1BE33E7C0B -:1077A0006A08F28D05DB4D09FB7B264311FA833B0A -:1077B0000DF16E20BFE3B1D53FA3FEA5270E13DE6A -:1077C000ED32047418C70BACE678B6CBC2FDA4BB8F -:1077D0002C85413CA7DD199CAEAED26DFB6913EA46 -:1077E000976F703D64A0F14B5DB3BA6AFAF133F65E -:1077F000D5C3BCC570CE673EB0DE86FEB8E11B12B5 -:10780000CF694430B1FC7206D71366B2B8F7C5B879 -:107810009EC12B5DB89EAD8CD6537AE29D5B8B5199 -:107820001F37713D2479DE5F6770F9F9F39FC33824 -:107830009CCFE8B91E0E1003BA5E20E8E14585EB47 -:10784000C1F0B7380FF07F012A108363EF1724AD22 -:10785000438EDF22E0F4A9396D1BCA73A791E3FDC3 -:10786000C965071FC038A66CF7DE324DAB89F32B14 -:10787000CFD9B0F0400E9C7F437726D999F27DC3D3 -:10788000132F657D17DE9FDAAE7A50F56DB8E5F1FE -:107890007BC761BB27F4215C27D66B30FEA9D0CB18 -:1078A00069D86ECE66C718F497C8FE73375CABD53F -:1078B000C4F1D3AF4A4F92FE1B847DFC7C65EF84FC -:1078C0003C80F7820D8A079B2D087D7BEA8DA8EB13 -:1078D0006CD67B30BE51A132AF7E0C99EED3F0D97D -:1078E000D0FDEC815CA8F7EF1E5B81FB5AA3F3DEB1 -:1078F000300AE9658B81FC60C9E7637472FC85FE20 -:10790000611DF45F73B3AD1EE32230EE7E2CEF2BCE -:10791000DDA6473F7EDA09E06FFCFD611DF0CC1368 -:107920003D2B4683CD02786C6B47FAD8858E0B9C35 -:10793000E7693DC90916E6FB1827FCCF0BFED469A1 -:1079400054E179E2C4F2B42A4E7F744EC8D49DB09B -:10795000BFFA474611BDCEDD90485FB29D5CEFBCDB -:1079600060627D325E9438A5BF8295C6E35772BBD4 -:107970008C490123D263C312E0E77174D370BCC396 -:10798000887A57F23CA8413279AE7AC24BE6A6FD1E -:107990005AF87E41E535C37E4FE2BFB8DF5C41BB9C -:1079A0007EBE425B640B2E61356E80E78229AC1689 -:1079B0009F921F9EAA0C8DC6F6BB0C91C77F4A7C76 -:1079C0003095F8C1297B380DFD4AB9C2AF77CA1D81 -:1079D0004E433E7746C4EDB01ECBF37B401E005DA8 -:1079E0007FF89191E4424BE8A5343CAF53CF5874F3 -:1079F0003A38970FBB33AAD11F742AF4AB34DCD7C3 -:107A0000C9504635FAF506E213C9FC4DEA0347F1C1 -:107A10009F5782DEE3D4263811BE1864C8017993DB -:107A2000D15CD6DC0FDDCB7E4E637319E66944BFB3 -:107A30006FF3209F9DEA74D3FB3A858F877F18DF11 -:107A4000FBE460C6363CFF837B4B06A19EF00973C6 -:107A50000F42BEBD20CB7B33CEE7AAEEA5B8BE6BEE -:107A600022F3B4429F77F59E3BED00B7DB19C82D9A -:107A70007C96FB8CE46F69CBA475CD525958053CBC -:107A80009D8572753495498F99B55909B6C23A6E7C -:107A90005F9BB8CF399DA6D8F9C27FF31830442434 -:107AA000A0CD71ED60FC79283F017EF3CD2C9C02C6 -:107AB000E3CE7F34B1DF0216A6F5343CF5A5A93F2D -:107AC000387E2EE0B8204BF33BA1AC4C31D3BA7ECC -:107AD000F0B442F2CD29FC8CD1070705311EB64027 -:107AE000C8EBD9A6BDB41EFF5D75DAED8037679689 -:107AF000CCD26ECFE0292364976D50080F17D4B015 -:107B00007001AC6F418F121E85FAC45BFC9CE4B817 -:107B10006C0B6F77ABD07766035C507F18F79412CD -:107B20004805FE39DB0CA61CF211B13FAC1F04E581 -:107B30007AD641FB6A64115AC75A3C47EECFA3F587 -:107B40007FFE163FBF71F55BF5B8A8837B2B28FE3F -:107B5000F729F3D039825EC22CE9E7E309C25D8BD5 -:107B60008353FDE6C4327B34AE3C18E10AE5387835 -:107B700037EDF8D2A4F503E707FBE44970C4E451FC -:107B8000EC3CBDF788388707BF3D2707F9C07DA8C3 -:107B9000BFE68A012A916F32E9D7089B617CEBE549 -:107BA0002CC1CF01FA15959F704E9BB8219FB1F55E -:107BB000061FC50B66E9BD0730B49592ED7B1AF13F -:107BC00076964E2B54891F682564EF2EE1E7F1D09D -:107BD00098E611CDFDD8B972FDEB95505887FCE0C1 -:107BE00005AE1FA496470DBE383A7B45F0B941FB60 -:107BF0002207F2105F9E55C82FBF51616D0AC0D990 -:107C000005C782F260A372F400CA8F8DD7BB592BCF -:107C1000D497EF98BCF065B295AD94D7D3B8A34A8A -:107C2000DF68A3FD737D35A579AB0EEAB36F2B1D1D -:107C3000837402FBBE6D0ABC7F5DD06D8E8DE383C5 -:107C40006B79A07811FA65F77917BE8CF43DCA4AB2 -:107C5000FEAF6C80556A3A3DDB510F75B11605DBFE -:107C6000ADCC5478DE411D9BFECB918435EAA074E7 -:107C7000FE3C0C4F45656DE8CFCD5641AFE5EFDBDF -:107C8000709E07D3F8BA3275FADB26A35E3D86975D -:107C9000D3972ADA3642FE75B4AE6C13ABC57DE3DA -:107CA0007BD4C361195A37D507094ED9E39BCB70F2 -:107CB0001DD943F8D3690CE7E338AFF7E1894F8763 -:107CC000FC7AB190BB8BB75667237F7DFD945945F5 -:107CD0003EFABA4BEA8F611BEA8F6C68296F2FE47A -:107CE000DBE2B2F1D988F7CEC2C476670CDAA0CB5A -:107CF000514E1CD253BCE7339B36C801EDAE32B2B5 -:107D00007EF3ECBE10E7EA3FA7B0609CDFC03FFD0A -:107D10002CE9E7FE736AC2FB53CBCC2C18E737681B -:107D2000A8DF3701DB35B2DE95888F8DA114168C64 -:107D3000A38FABACFDCF2BE9C27F4ECF02FDCE6B44 -:107D40004C7C7F2E830532FA6B9795F81EF6915086 -:107D5000DEF9D7BE7DE07B561949433FEA2494877C -:107D6000503E13D4050CC0875E37703977DA1E4950 -:107D70009083A7DD112E07D14F64E37AFA643C6744 -:107D8000359A362535368FACC7FEE971FB3D3DDDB2 -:107D9000C8C2743E515A07C22F309CB14D3D1F1BC3 -:107DA000313FA6A1672FC14FE24D3C1C03F171A7E3 -:107DB000D6DEB00E784665E64FD78C1C0128B84F4A -:107DC000F287AE35E8E7CCD2EB12F8454A791FFFCF -:107DD0002076F52046C188DF6C59837ED25899B74A -:107DE0008FF57F78620D8C573E92F7AFCE0CBEB602 -:107DF0009C92443A38FF55A385DED4B8B239A96CB9 -:107E000083F2A8B8B23DA9DE9954EF4A2AE7F3F607 -:107E1000A752C3857A0F6337663E3A5105BE792A69 -:107E2000273C03F3C6D6B63E3EB106F859633997F0 -:107E3000CF4D3D8A877C7F027E4D1EAE37DA3C11E6 -:107E400023E6ABA594F71E40FED2B053B12B400FF2 -:107E5000B6507798CAD8CF1DD72FA450BF86D0511F -:107E6000EA37E0F8A53AA2F735A5C778BBD0FBA45E -:107E700007AC6A5B48F179197FD6339F96A7C4E2B5 -:107E8000CF92CF9ECED15E223EBB5BB1237DF6E189 -:107E9000298E1BE7F791EDFF38AAE7B7A866A42C57 -:107EA000FEB805F5D93F35BE3F16F5BB3F0A79B29E -:107EB0005E098EC0793731DF089497DF6F1CB657A3 -:107EC00007ED8E18225D18635B9BD93311F3E88EA2 -:107ED000A4460A300FEFDE070F103C8F6446BA103D -:107EE0009EC71F7C85D717440A30EFEEFECC4F7833 -:107EF0007958A40BCBBB1EFC132F8F8A14E8A1FF6B -:107F0000E0C0918935D0FF317BFF74DD9AC9F57BE4 -:107F1000B9BE2B866A3FC9447BB581CBA12EB089FF -:107F2000CCC03767CC3FF9F463008719FF9242FC5D -:107F3000ECB153532772FD3CE0552BD07FCBFF486B -:107F40004E12BF57C96ECE41D9981E3B8FD4C25E28 -:107F500037C9914B9ABB51DFC89E3192E4488D538B -:107F6000FB0BCE2B9FF7E7C113DAFF25D3CEF9B772 -:107F70005E47F1ECEC1FA5927E769F85EF07E886C1 -:107F8000CED726CE6383D8CF864C6E57363AAFA570 -:107F9000716E15FA74E7EAE0131680FFDB324F6664 -:107FA0001DD7CFBFBB15F80AF0F14E879683FCE4CE -:107FB000BB22EF4DF20F7C9F1E6797749641D91636 -:107FC000B33F3B276B3956273EB37418B791FCA8D3 -:107FD000B398F7937229BB95CF9B7DDF886DB88FDF -:107FE0001495FB9F664F2FD9D6427AC1145A2FD3CE -:107FF000B41C05C63B3E6FB00EFD52F27CA60FD5F9 -:108000007E89F0B955F8F5E539C9F3FC8BD8F72C22 -:108010003DE815B0CF77B37C341EE819A385FF8BFC -:10802000F48CBFE019C7C197A991B1F8FEFF2338BE -:10803000FDFEEB8053E312E017BA8BE017027EEBF4 -:1080400095B0219BF30BB2A7F13DCA9D5F3A7D1F0E -:1080500066C6E5C7CCF85123E995725D293F7CBE21 -:10806000F63BEC7C3A4BD6FB3EC7F38AD34F3DD26E -:108070008F29E639F2B699E216478C21E29B47C078 -:108080001E6A41FE22E2EE15FFB2E075B407E5B8C4 -:10809000DFCDD2737FB03C77C5DB3DA718F35058D6 -:1080A000C08CFB986CA4739772B7D3C1F34A3AEFB4 -:1080B000CAA3BC92332CC2C81F5AC9883F021E50A3 -:1080C0007DF4962CA27F681FB060FB7997507BC02F -:1080D0008B00F1875BAC64BF74629C1AEB6F290D57 -:1080E000621E0CDACD846FF374346F3FF8C2FDCD9D -:1080F000C3799E85C49BAC56EED761AA367A729C32 -:108100009CBF228B9F734A79E4D9DFA35EBBD64222 -:108110007A2DCA588A097564D33870FEEE2CEE1792 -:10812000203CBBFDDE5491CFE6A940B8AE4AE578CD -:10813000B9D9C2E3559B418F26BE28F057E6D3F943 -:1081400084BE17A9D7A5A1BE303AABCFDFA0A1FD51 -:108150004FFE72A89F19518EA2DD3633A00F9BD01F -:108160000E6BBF568BC4D931F887F1BEDB045F6557 -:108170001B18F90F6FC37E6938BE350DE39BB761DD -:108180007FF4D72EBD36218EA76571FA96EB4BE6AC -:10819000FB5A96F04B763CA4C5CF23C74F1E0FEC7D -:1081A000D12A840FC0393C08CFB7454FE797BCCEE2 -:1081B000C806EEF78E6C2822BC93E30DB4CE3FEBDD -:1081C000A377282007E78CE776BAB47F660B3B9A43 -:1081D0002D4DB4EFD0CFD257D69F5F4EB617313E5C -:1081E0009FD89EEB2D2923A346A25BB792B07E09B0 -:1081F000AF81E030F72BC24DCABD872C4007E9683C -:10820000862B84BF1BEE4A2139E6340647205E2DBB -:10821000CA7253BB4D9827437295DBCD9FBE2EFD8E -:108220001E89F6B2DF1ADD82F0F25B19D1D3E9DDE7 -:10823000A9443F6C686406E6999DD9656288BF4D84 -:108240004AA404F9D66945ABA3762D296EA423E987 -:108250005778F739EE57F02324617DFEC07F529E98 -:10826000937F67A21D7D1AFEAB07BC3FAD8B54E028 -:1082700078921F801EAD917E54CFE33F4D3A164059 -:108280003BEB2ADDCC799CCE73D9367A7FB464512E -:108290009C9E0EEDF62BE91C7D906E1A041C9B74BF -:1082A000C7A85D03E62B213CD1DE423F1956C6F933 -:1082B000759BD67E48F9524D3B12CFBB21860FCA23 -:1082C000970AF68BC30FA2E780E0078CFB3B6A7826 -:1082D000FC3A5594536A7B297FCA2FFC1F99FB22D5 -:1082E0001390AFA49687D84C78FA4F707D635CCF1B -:1082F000D697D0AE76D4F6162019F8859F509EB743 -:108300005CE7953DEBC8DF21F59438BB73C494045A -:10831000BFC372EA87762CCE17C1573988065CBE78 -:10832000AD17F22D050D6294831DC3490EA29C4228 -:10833000FE24ED60E457C82752B2ABF720BD3E9251 -:108340005DFD02E76B8067A8D7A35175E5C0FE3DD0 -:10835000091FD90EEDE17FE4BF7B55E0ADF4ABD34F -:108360008ACA31DF3A53FAEB28AEB748716723DE89 -:10837000BEA7F7915F6E2E0B909F681EFAC3E0D9DF -:1083800020E87D8EF02FCD117E25F4F7C6C71FD1D2 -:10839000EF1A5F9ECF7A39DFD86E8AE5E5A01FA875 -:1083A00086855361BC46F453E13394D8AF8945A91F -:1083B0009F7FE797A684F86627DFF76DE2FC1D35FF -:1083C000413DF2898D16EE9F92FC63DC52EEC71A96 -:1083D00034462B5E8178FEAA81FC1B7F11E7D6E72D -:1083E0002FCDAA7E290BE064D5F37B6CD11526E254 -:1083F0009BC7411E770BBFCA14B44397310DF3DE00 -:10840000996A2F8CB753E573CD2E4B3DE2CF67426F -:108410009EC9F7DBB30CB41EF237115F4E21B90BC6 -:10842000EC6334E257C5602917D968F4731D1576DB -:1084300073D3CD361F8E17D1717EA3647339A564B3 -:10844000F3BC3E59EEB3F304FEC8B821FA7DE2FD59 -:10845000EEE6BEF6EB843EC968BFEBE789BCF03EB2 -:108460003CD6115F4A19E925FE7B95AE9AF852F485 -:10847000039B1BE152FB61C33CDCC727D3AD74FFF8 -:10848000EF76E10776653B687CE9F7BD503CAD7659 -:10849000CD08E297B27D1E1A2863CFF71FEF127C3A -:1084A0006C17E3EB0D9CB0F23C15950590AFED0A0F -:1084B0008D08E27AEB84FF01F51BE4AFD167F9394F -:1084C0003295EB43BB7A460511DF8F1A7C1B67A3FD -:1084D0003FA7DB407E39A6069F781CC7D993E3C12E -:1084E000BCA1D3BAE8965F43BB5D277E9E8771A28D -:1084F0005DC25FDF600C9790DE2CF2241BD2C22598 -:10850000E8077A519C578315CAF03EC3E22BCF1E71 -:108510001B8BA7613F7C7F2CC8F5F2638CE3416025 -:108520002D8F97027C7366E37A5767533C0ECF0515 -:10853000CFE1DDDDA3685FEB0DA2FD0B0AB557A609 -:1085400094CE20B9B0C69481F03FE335529EAFFF80 -:108550003EAE37CED2B9B72C415EB92785F637BBD0 -:10856000F310C549FCF7CEA5FB93FEF94B6F62FFF4 -:10857000207E807225DEEF7D9A450BC91EAE1F1C42 -:108580000AC33A4EF78CF0F0F01FBF8FD324F249A4 -:108590008F1B9886EB8EEE3604FBBB2738D0F8E4B1 -:1085A00040ACE0F28DFCE3F1711A920789719B0BEC -:1085B000954F1B222577C1FC6B337C73B2E3F445E6 -:1085C000FF9E1CE277EFDEF3D742D22B3A789CE194 -:1085D000B8419B8174E2A8091B67C6E9613FC916CF -:1085E000F68749E88FC007E3E95ED6575427D2994A -:1085F0007CFE389BEB21A922AFE0FC7A99B736D5F7 -:1086000084F293BB96705C37BD2F12F1BA7127A22A -:108610007B313FAB215446F1C0A2A561A24B8077CC -:1086200018F5FFE31B53393F816DE238732A19E9CE -:10863000AF73F43C4F628E09F4612EC7A9FD7B1B1A -:10864000B3090E15CBB91E187D5621BE28E39675C9 -:108650008CF77FBEED68400FEDEBB62B65C05A5925 -:108660005D5B15E551CCDF5C4CE73F4EF0DF5926F2 -:10867000AD6423E2DBF33CEE05F391DEDD80B9620D -:1086800063882F19511ED66F5718DE3796FB4F8E11 -:1086900013B260629C665C88F36F941B2C4E5F93F0 -:1086A0007208E5054BD22313F12220E257FC7C7EB1 -:1086B0002EE02AF93F41EC1FC841D0A79F44FCA9F6 -:1086C000A8E6F417ED5608CE8DAC99C795841CEA40 -:1086D0005B8F9063EFE9B9DC9C635A47CF305E1E35 -:1086E0001B8B7230C2E520C835E48B03E14578006E -:1086F000BC90F8B017F701E3359C60E16FC07C0DCA -:108700004B59B871347FA68E26B9CCE5B399CB67A7 -:108710007C5A2F424E27CBE764799C2C87510CA1C1 -:10872000BC957810EFA7477D64DCD2A09EFB61F377 -:10873000ED981F28CFA5D1A91DCE1B1BD3B7FC8751 -:10874000CD66F76558F6B2C136F42F55DD5E00FBF5 -:10875000F7ABFC9E720AC0692BBCEF12FAF9E40277 -:10876000BE7F97C80332A85E5666C373EA257B3A7C -:108770009AC928AF5BC2B72B15FA8DC17E5CFEF596 -:10878000F537B3366B5CFFEA5D16922F675F48A53D -:10879000FB684CF5153960BCAC3F829E0EE5D3BB3F -:1087A0005249BE9F16FCDE29FD166C259DD76778C1 -:1087B000CE998875D579E8FF65CAC43C46F7B4B947 -:1087C000DED8E818C86F2FEA8B7B6FE6786622390F -:1087D0007BD611B913CBB01ECA333E25CEDDBF63A5 -:1087E0007CD98F303FC06BF370A8FACA506F30E964 -:1087F00017DF6CD6E37DFDA5D1BB601F8D0536CAA2 -:108800005FAE297AE777B740F9831D06BAE738EFFC -:10881000B1A983C2D84DD55CFDC9E7794143C2FDFA -:10882000B905DB13CB8DA1C4B23FE9BEFC9277B68C -:10883000BEB63FAE3ED395EAA4F377330FE65F337F -:10884000FDF706F9FAE197F2F9D765C1D7F60FA35C -:10885000FCB57C17CFCB31A25E3313F1A19F7E6FA5 -:108860000ABDC6646A3E8179F0A6174D74AFFE4416 -:10887000B66F18F66FD2450FE0799A8A4E8D463959 -:10888000585DF4778AA79DFD31F3207CCE5AAA4823 -:10889000BF39BBD1E246FBACB3D04678D0B947096B -:1088A0002A5C7F9F34B602E3A7B407E6DF70FD07BA -:1088B000FCD20633F37BF860BDB890CF68644FBD3F -:1088C00037D96A5F0EFDEA377079DBC07AD3900F33 -:1088D000CC7771FEE3D73F6534C33F8BDBB4112DFA -:1088E000B0DE055E2BDDD751BF50E99EFA2A1C325F -:1088F0004EFFAF72093FA93962ACC2F9FFBEB8168C -:108900005D63D2CF6532F834BC1766D85916CE8372 -:10891000577397BC44764E5F1C7A37E75B73EFDA88 -:108920004BEF9529B5B4DFF760BF089797369A6883 -:10893000BFEF15D8C8CE7CAF8BDBBF73EDC6A09957 -:10894000F48D7319789FF6BD2E03DD633F1F1ED78C -:10895000D1BDD6F737BF427EB8F7199F37B0434F26 -:10896000FACAFBF6684518E1E86E4E437DB77EC350 -:108970003CBA173BB74BEF457E36B7EB8E5F5F894E -:10898000FEA329B796E396AE712CCE72DB62F55248 -:108990004F55D32B1F473ABCE68BF1BDD7A0BED4B1 -:1089A000057452CCF3EE514FDFDF751DE9A5732737 -:1089B0005B1DB82FF7E6C726A0FC787F722EDDE39B -:1089C0009DFBB4C2F0D30D731D4BB2F0FD5C45F5B9 -:1089D000F6874FCCC5FD6D5545364F18FBFD564FFC -:1089E0007802747533CACFC62E03E9BDFBA7BCFD60 -:1089F000BB5B9C31BA52A66CB8691CB6FF9981DA90 -:108A0000F7E93B9B6F94F8C2C215685771B825D33C -:108A100099A9686909AE2B99DEE62E6F2EE1F1ABBC -:108A2000AF46776C33BFD7DBE652D897BAAF4477FF -:108A300077BBC65E3CDDB1FCF4047BEA7CFE16200D -:108A40003C95FE7FB387698FD928DEAB29C07F773D -:108A5000B8F8BDF51D2E7EBF4DFD8F45DBDF00F85C -:108A600054BA7C5DB88E22A695A1DC7447EDD5780A -:108A700017C926F439B6D924ED00D2EFD767B2C7AB -:108A8000D7C4F91F422E6E27011F781CC739FD87F6 -:108A9000BF1FC0736A2A3C351AFDBEFE739F51BCCE -:108AA000D0D6C3E3CD364F94E2F006A797F050F24C -:108AB00077BF87CB9FF3E0E5E2F73BFCCE288DF351 -:108AC000560EE7CF9D22BEB2698995FCA99B9C41B9 -:108AD0000BF72F0418CAA749957A1E2713FAD68DCB -:108AE000C21F692E7F89617C8C5DCDF3C2DE287F39 -:108AF00049CD80F2AF2BAFF5D07DBEF247DA07E368 -:108B0000BEAF3688FA21F4BD8D7FD7AAA87E914BDF -:108B1000EF46FA9E54CEF322597D1AF94DDE287F96 -:108B2000D7797BDCFABDCCECB601DE4C01628DCF8F -:108B3000C3BBE96A8BDB16873F9F7428B55CEF7572 -:108B40000F9A368AFB45481E9727C26391CB48F39C -:108B50003E925D7508E17CCD37F9799C7CDA14444E -:108B60003E7852DC8F49865FC425F0471D9110B7CF -:108B7000771A438528273F5412FBCD6FD753DC7CEF -:108B80005EBBC28230DFC9279E2F447EFEC163CF09 -:108B900017CE8C5B4F723FF93C29E7137EC1643FCF -:108BA000EF40FE5DD9EECC06E6330F89B53F53FFAB -:108BB00037F2EFCEEC11FE614D1BEA447B48B44F17 -:108BC0001E2F3397F36B65A7427E0FE9DF3C76F0EB -:108BD000118CA4F49D9FA5A758179FCF289FE3C48D -:108BE000B94DC57383AD58DA7979A0F31A881E7F21 -:108BF00021E4903CB763ED4306211C8D4D3695F181 -:108C00007B6AA5A8AF7731AB07E9E9AF22AFD56999 -:108C10008527E869C65C970DF999FC2EC00FAD69F0 -:108C2000DBF0F95791F7EAB4C213C629C82DA5F1B4 -:108C3000FEAAF3925DF7437D07DD5F74093AC966CA -:108C40006145C14F1D2C784EA1BCAFF6447867B585 -:108C5000723912AD3392FC9270BF6AE69D64BFF622 -:108C6000735E1B108F722BF9BBC939C5C2DF11A10E -:108C70003882A592D9D1BE6FBD3240EB90E7E5E7CF -:108C8000CD99D2A390FE8CF92F29E9142F0D8827B6 -:108C9000B3A5B3BEF8418AB0775952BC201BF46E1D -:108CA0006C27D70965CAA3B9CF11EA28E1F156D2DA -:108CB0004B715C7C3F73A44AFE766C671C7361FC4D -:108CC000EBC35391973849BEAFB7F61B9F9884F713 -:108CD00083F01C403EA25EC83C8684FB419B419FC2 -:108CE000463B4DC67FF5BA50998BEC93DE08FA4FA0 -:108CF0008C156637CADB147DA814CF2F391E0CEDF6 -:108D00008A791E42BE03E58CBCFFD3B464BC17E372 -:108D100054A07F04CC787E93F9F935DD5545EF9565 -:108D200029A52D885FFEA58CBE5330BEA79BF2A45B -:108D3000FCB55C1FF3EF3C6A6480BF33853F870955 -:108D4000FF739638D76342FF8EC5BB225B30EFBB03 -:108D5000735E3EDDF74DCE2BF9AAF1CE33A900901C -:108D6000CBE2E25883CC5CCE88F397F42DE35AA98A -:108D700023BDC5A889FF2E3BFA2BEBD8AF90371245 -:108D80003878CF3FCE1B997613E68D9851CB17F5E7 -:108D9000B80C90A37DF7F92C6E8A7BF5D5E3771894 -:108DA000CC3B15717F8FDD74ED50CA3715E5D7D6F2 -:108DB00062DEF87D1696305FFCFAD4A4F10D30BE69 -:108DC000CD2DDA074EDE70AD4AF15F513F712DE6D1 -:108DD000C9DC67481C8F5050DE3F34C7E6BB7DF3CB -:108DE000867BD6E6C7E439C8F78D396363727DD5D3 -:108DF000DB933A2E73237D7D4AF9BB523EFB9D3CAB -:108E00008F24998F3D9AA348BD78028ADC55D317E9 -:108E1000D2770BFAE2BF3D751AEAC332FEEB5FEA86 -:108E2000A53C5ED007B6E7903E70EABDBD0CF5CE1E -:108E3000936417F8CFA9DC4F047A057E87C6DC530C -:108E400045FE504C4F1D1677FEF3859C421D1EE9D2 -:108E5000C1BFF93B8FE9B13E57EBCEC98CD987C969 -:108E6000EB7D2D87E7B9FB4BAB37223F608F2AF4B0 -:108E70001DA835A59F90DED1F4C2B563E3F3D0E71A -:108E8000ED7C90E7316F37F4BBFFD772F877629AC9 -:108E90005E7896FC9D2783FCFA4CBD1A5C8D7A683F -:108EA0007DBD0E352F561EACBB85F481E9B00FD8C1 -:108EB000572887C3C7BF7D6A00F3E2FDF09F02AF6A -:108EC0003679E7905DB069BAD986711C7FE9CC85A7 -:108ED00084FF76AB86FB4F5E672CCE6CA5FBCB6B1D -:108EE000761A6A518FAA00BDE95F61BD05E9136B6F -:108EF0003DC097F2F4DD653FB061DCBD7FB9ECCFDA -:108F0000E3E7D8A67803DF2A273F278BCFE329DAC8 -:108F1000C9F5B3A339C604BFFAD11C95E07975A091 -:108F2000773CE2DC1E3592827AB29F691FA3FDCBAB -:108F3000BC3637F977198FB33B97B9C9BF6B764603 -:108F4000EEBE8CF42895E2CCD2BE38FD02F78B4DF4 -:108F5000CDF59D46FCA8D0471EF816C2ED6E55F81B -:108F600089399F299C6A1B837E2C8B33F240AD9BF1 -:108F7000F26FC82F31E81B6D740E7B9CCC8EF019FC -:108F80001FA85395383923F9C6F8BEFB3B4EF29F14 -:108F90005673B6C686C169BD6726146DFB3223A61B -:108FA000271CFCFB34155F4AFD4167F6919D533346 -:108FB0001DEC46C4BB95D1033AF4D73B7B497F6C8B -:108FC0000C29344F63E92F293F6E81C8C3EACB8750 -:108FD0005223941F66CE4D117EA6368E97AC97EC29 -:108FE00062F614873FC84DCA1B8BE9F12DD44E8E13 -:108FF0006714718646E1C70140517D46AE22C65DC9 -:109000009E189F10F332D55D11EF77583F19240950 -:10901000ADCB9D86EBBDD7EACDCF85F6C7EA75040B -:10902000A263ED29F45DAAF54AAF86FEC84019CFC8 -:10903000A74DC6A33231EFA07DD109284FA22F0C36 -:10904000944FCBF367378EBD84F2D0CB777E3C0153 -:10905000F183D532A2C7A69D17974F5B81E731F602 -:10906000FFA17C5A8FA26D83E775B98EC47C5A0F1D -:109070003F2F19D74CCEA33D9D135679BE5B64CBD1 -:109080006368B7EF34519EC8A49DAF1C46BFE62469 -:10909000330B519C37497F38E29CEACD8579CE7CF1 -:1090A000F4DE96150CF3B09FF3F07B9989FAC0407B -:1090B000F600C53AE2ECC699126FBE267B40F26B11 -:1090C000BFB0AF3E54A2F796E0FE76EBEDFDDDA318 -:1090D000F1E7CAF8D80079203DFDE781C87B66B585 -:1090E00091E284B8D55D7D74F0D5E2604B5176F69F -:1090F000130753455E97AA70D6C11C3CEF47C6C103 -:10910000D4EE1114DF32C5E26061D64F1C4C1571EC -:10911000A55506AD8EFC34BB4D6E6E477B897FB581 -:1091200075677A90BFF9E79F7C063F05A03A26B89D -:10913000506F6813F06FB8F838D883B9FDC4C1B662 -:109140000ABDEDDD525DD80870DDCA38FF0DF4C8E8 -:1091500078988EECDAE83D05B46E658A99D6FDEE16 -:109160001ED336F44FCD9271AE3DDCBF364BC4B347 -:10917000DE9D5242FEA781E03CAB3D315EF0330103 -:10918000E7B3962AF2D3DF79FF64F2CFCF41FFFE37 -:1091900090D87D0926FC7CEE767E9FDEBD5DA1EF3A -:1091A00099229AE84827B5D3774D17001BDD84AC88 -:1091B0003700587305BC56740AEA43EE362883D24A -:1091C000AFAE56032E68B7F5700AF9155739DD2290 -:1091D0006F8DC79D036B95E0303E2E7DC72CD0A6CA -:1091E000D3709C5772B93FEACFB9C67EBF23D16610 -:1091F00010F163315F0B837387A74EE1CF55E23BDC -:1092000079C9F090E3B5199ACDE8DF8B16F0EFA19C -:109210009C356AD3C9EF9C5E42DF3D6A4B6D6EAFF1 -:10922000E5F544B3672D512FD57F43E50A2973A790 -:10923000E37A77E772FD2619CEB33B12CBC9719F53 -:10924000E47B5AB3986F78CE90F3EF31ED16FCF6CD -:10925000EC9A62712E1E8AA3B419DCBF29A6F829E4 -:10926000FFAE514B3E879BAE803F073B6AE8FB74E5 -:10927000402F5C8F637CFD83BFE154905EDA1C1C41 -:109280006FFFA7EB4E5EEFFBB9251CBE0E4EAF6D18 -:10929000AB952087175FF7C5FA490C795F2F5F7C84 -:1092A00057F13C1E2EA67EC41F02F71888EE765991 -:1092B000F8FD4BC9AF28B107ED4F61EF0E42651ABB -:1092C000E3A12756D2F78936D50F4EC378E9F8A91E -:1092D00036DA47D31E7EBFB77169A410F1BAA93A36 -:1092E00052D2DC0F5C710255F2576837D3C9F87758 -:1092F0006EDA13E37FC971DDB5195A415E26DA4B88 -:10930000EF76BF82E7DD6D21F9DAB434FA38FA0F6F -:109310007C19BEA1587FEAAEB727286EEA46FAFC50 -:1093200099DDC3E95EE2CCB6C47B5E6C6D625C9194 -:10933000B5A7F3FB6C9D89EFF13E5342BFF3E28C7E -:109340005CBF596FF48D40FDF39A6FF23C8A8FE653 -:10935000E9189EEB47167EFE817B5205BFF694C44A -:10936000CB83AA01CF17DA8DC4783ECF1F95ED1BB2 -:10937000F17CE15C1BC4F97EF4EC152578BEA7BA3C -:10938000AF28C1F35D6FE8D0903E52B27DD7629CAA -:10939000EDF8B55ED20F65BEECC5E2DDB4BCAFD76B -:1093A0003FF755E5719D9CFF2BCA63FC8BF79BEC47 -:1093B000F9BB3E6021F9C2EFB5C6FC7727E9FB5E39 -:1093C00067CEE914E4C7038DF789B0975C66164051 -:1093D0003DACA23A42FD2AFEA663A80F4A3D387969 -:1093E000FD8BC5B9AEC8D30EA35D28FDBDF5626C7B -:1093F00073F053AE6F3FAA903FD7EC0EA48D23FBC2 -:109400006AF6E57AE22FFF4AF725588F62473B65F7 -:10941000DEA32D547F7AE72CAAD799C361B4C71A6B -:10942000A11ECBABAE4ECC7F36EEE0F12069FFC281 -:109430003ADEC275A438A346C4CF26D4AF61894DA5 -:109440002AF77B37399927C0501F4EB417655C77D0 -:1094500093977F3F66538F42DF91CA32FA8AF3F1C6 -:109460005C93E2BBF7E769DD887732CEBE204BEB39 -:10947000CCE3F9678508A79FE2A2A01C31C87B5BFB -:1094800089F70F0FEEBD99F4A1CF997750FFF968D6 -:10949000C184F8FB1C714F748EB8278A7C3A9CC437 -:1094A000A7E3CB0D71F968E1FEF20AE2F2D1E2FB2B -:1094B000C5E7A38513F819A7FF6CFD228A7BFB0182 -:1094C000CF978C89E16103137F1BA2EFD2FD97ED4B -:1094D00026F2AB35887C547FFD31B257FC789F86ED -:1094E000D3A3C6EF61737DA801EC40CACB0D25E67E -:1094F000AD1EFC9AE953B61BC87FFE66123DCA7DBD -:10950000C97D34F4289C7E92D6996CFF26FBC1A5B8 -:10951000FD7AB17CE9FDAF591E7E55BEF4D9D7C4A2 -:1095200097CE8B270C8DA679BE8678C207EE8E2C3F -:109530007429CAFCE1F6DD3C7F7882DEA6F1F8A54D -:109540009EE73724C771DD13284E29E3C6E6E7F40A -:10955000C1E5C5D4DE83795F8DBB5329DFA0DE5D15 -:109560004F7A7772FC723EEB9E8047F1397B9DEE1D -:109570006FFD4FF306F2F3C57789DDACF82BE60DEE -:109580000CC9FF0AF1CB976C9F66F8E2F0A57A242C -:1095900028F02307CEEB2ACBE7F89722F24BCC6AD0 -:1095A0008039E2FA0FD4EFCA7CAE1FBF24F291EEED -:1095B0004B4DA17BFF2E23BFAFE0D2F1BC2996EB30 -:1095C000BD2A3F13E5013FCF875FF80EC3FB670F4E -:1095D0001B42740F3FD068F3A01C937E2739FE8393 -:1095E000397C3F174B47DEFCFF5DFE71AB9CEF62A1 -:1095F000E36F1B000671F4954C0F03F51B88BF2C1D -:10960000C8F7CEC9277B5C1B4D718B8BE44B29E5DA -:10961000C0B7514EEF30B9D17E403F0AC9C7B53906 -:10962000D2FEE6DF25B8AF80E4D747166E4FC8FB01 -:109630003F72FF3F1910DEFF9C9EF76E96378078D1 -:109640007EBC4AA3FB03AB52B97C893EC1F387922F -:10965000EFC124CB15798F43CE777FFEFF2D5F7D41 -:1096600058C2E77FC85741CE92FD32609CF6BCFEDF -:109670000191C7D9AB897C19BA0F21D7E5EFE579FC -:1096800077BF10EB93EFD70939F059BE1642BC3AB9 -:10969000F507B319E3A0E5E59C7F36796D144768BB -:1096A0000AF1FC9AA6A58CEC7E79DFB5D2E5DB85C4 -:1096B000FD56BD6DA3EF9E36EDDCDA3E98F20F7CD1 -:1096C000A4DF9DFE037F7F22DBB707DBF9974612FD -:1096D000E215155F7EBAB2B69CD64B76BBD39478B2 -:1096E0008F2892CFF386E4F34F7DF005FB04FA9DBB -:1096F000AAE779DE7EA766AFA2BC03EE0F4F71F733 -:10970000921FA8690709094649A758FFA37CC29B75 -:10971000A61D5565F4FD8190A58CBE5FF347FEBD87 -:10972000A75377E506F5DC7FFE5B5C6F6A79F07A1C -:10973000D4338B601E54494F755F5F46FEC124BA17 -:1097400093F4D6777FF4BBE660AB12A3C7F5062E81 -:1097500027A57C7B39DFCDFDD54E913FD83399CD00 -:10976000B6C5CA3667625EE58ABC6B5FC6F5BC9C4F -:10977000CFE30532CE5E6C06EB73F0F978582CE23D -:10978000EC93457E040B98637911832F1C6797EB4C -:10979000936519674F39277E5FC06E24BC486DE71B -:1097A0007C83015EA09E7D75B4773CDEDB1ADA19FE -:1097B000BE1AE13508C14F79AA91BB2FC3F845867F -:1097C0007A35C62FB62C19B30FE3AAEAEADE6FE0AA -:1097D000D1B83BECD5686256BABCBA02E22FCDA52F -:1097E00088FFD5BF35F07CC6D52924EF3B0B1B285D -:1097F0009FF1F4DBA6847B3AC9CF005BEE42BFD178 -:10980000E0F637297E90BA43E9374FB5AAC046FB48 -:10981000C4F6E8874A6DEF0D54A25FE51E857F3BD5 -:109820001256AFB8D0FE5775A877CCDAC9EF7DCF06 -:10983000EA70549B899F2A3CFE72B593F8A4BAFA49 -:10984000061DDA696A0BA3EFB45516703FF6B04EE9 -:10985000BB0ECFFDDFBED0F71B571B5E10CB8F4377 -:1098600070359AA2075CC5B178A0CC8B1BE8FBE7EA -:10987000521E25EBB3E7E9B1421EF5E9F349783C06 -:10988000503F89DF129FFFCDC0480FFB37C54CF713 -:10989000C1245EB7C93CFF2FB85FB748E4DB1C5B4F -:1098A000F39FA3F97D77194F09F23C294364651EA4 -:1098B000C12BF2CD00EE7B8743D73492FC614D344F -:1098C000CE6AFE7DB5A2F621CB2BCBF169670A2CBF -:1098D000E1D8AE0545489701C08361FDE081B180C4 -:1098E000DF575157A7D0B9A9EBE8CBD24C7564D15B -:1098F000B9A90FF2F361057C3F329E2BFD969FE5DF -:10990000FB6E463CECBBBFB5C4CAEF6F89FBC1A977 -:109910004BDE7E1AEF456D11FEE37D7B2EA5DF85C4 -:1099200038BB5A55504F3DEBA8A3DF41AA2BE0FAB4 -:1099300052AADACBECB678FCDC4779B58377F3FC36 -:109940004055DC7F56573BB7223C6B9C3ECA1FFEFE -:10995000465B987E3A618FFD38C5E9402FA27BAE09 -:10996000275F50A45E94200FA5DD966C8FDD51F02B -:10997000BFAB2705E47C5FD5CE6289F6665F7B6965 -:109980003F26DB1349FD07D27F981648C8937940DC -:109990009CBB94EFB98237CAFC99BEFBCE2C68C140 -:1099A000FB12239028C7C6F28898C82FDAA0583D2A -:1099B000A82F0D9447D497E7C39A2FE3FEC8E62B50 -:1099C000F029F390649E9105F34D32CECF37B1600C -:1099D000BE4906FE7E06BF372DF3455A0D6ECA3FBF -:1099E00009FC98511C5199524BFEBA74AF91F0EF9B -:1099F0000C0B6EC4EFC707A6D9E87E38DE2742BC41 -:109A00008F2A2E1A777CAD26DBEBB07DDF7708EB53 -:109A100018D5A70FD572500FB3403D7E1FB9EFBECA -:109A2000F46CFEBDF6E47C1399F724E3C0B9C39F40 -:109A300053D02F8A6E7FCA3FF881E857CCC7E9FC24 -:109A4000BE9BF846562BCF6B8A5EC9ECE897AF9663 -:109A5000FCC79C78AEEB155F31D2E77A2BFF5E40F6 -:109A600017F3B4EBA17C77C160EED761EEBD3A622B -:109A7000D81DF47B0F9B9CDA6B0599317C92EB62CD -:109A80001BF8BECFE0FD302536DF99797F2B44FDF2 -:109A9000AABAC7C4F13269FE4D7DDF6B095A509EE8 -:109AA000FCB980F1EF8C26E9BBF2F96789FF822FC0 -:109AB000CBF907DA9FC4CF0BE9F112FF06C2B7401A -:109AC000B538A72329A47F487CDBB76C3B7D877022 -:109AD000FFB2103DCF5894901EEFD55AA233903369 -:109AE0001EDFF25F37E1F73CCEA4460BF17B20D1BD -:109AF00087F55E2A67468F6099155DC1CBC3A25B6F -:109B0000F0FB20590FBFF82D2AE379E63276AE201C -:109B1000F4AD808DBECBB5B217E55679521E4BD24F -:109B2000770C52C4EF0765DB8CA44F668BB81EAB75 -:109B3000117A3D46A0A0DC9A5346713C1B73EFE8B6 -:109B4000C5FA7C13FFDE0103FCC7FA61C53C1F8226 -:109B5000F17DB37CE19F669100FD1E60B183FAF751 -:109B6000F1F11D26119FE2F31F7A96C711655E2F52 -:109B700063F602D4876C6E965096DF0161AABD0031 -:109B8000EFFDB74ABF9F28BF98E2CB2D8CD3970E2D -:109B90005DFBC391F4BB24CFFD6828F2CDEB8C892B -:109BA000DF7596CF3F14717BE58CF87EE11D29BEF1 -:109BB000218599F8BB243326E0A768A76754191DAF -:109BC000A4BF3DA1473E9529F0C3318DAFCF51E3EE -:109BD00055F0F740E4F703337D2AF90998AF538F26 -:109BE0007235F3B897F2051BCCD142FCDD9637CC29 -:109BF000BECB70FCB37547EFA47861EEA12398DF6C -:109C000071C8D0313E0DE548B1F89E040664A17CD0 -:109C100020AF88ECC13EFE304CA178E6A469FCDEA2 -:109C2000EB441652F19C27D8F93DAC09E5C59E5688 -:109C3000986F92C80F9970D89B86FC6DC277222AC4 -:109C4000FFDE45548DCFC7904FE632B8E3E9E17AA5 -:109C5000775C99E1778E13CB377A12CBDFAAFC625F -:109C6000787C7994A24DC47DBEA888EF46007FE140 -:109C7000FBE279873F17F6DCA52E662E427F8553DF -:109C800009A0BD70E9F3B9146779BE9251396BBB75 -:109C9000799B397EFFEB743C0E2DFCE0F2778DB0A2 -:109CA0000EE5ED737FC8227865D980DF3A89FB1015 -:109CB000BEED1374BB4FD069459ED98AFC7F9FC10E -:109CC000BD99F03CD5EC463FD5DE54237D37B675C3 -:109CD00021FF5D0425CDCC8C30AE7E262F433BF694 -:109CE0004DA8D75798299F649FC8D36EFDB14A7E6F -:109CF0002EACC7EFF9EAEFB5927FBB26ADF47B58E7 -:109D0000AF4F33D23D89BDA9153E311F7DCFFED166 -:109D10005473187F5F21F9FB9D87705D083758D712 -:109D2000637C1D448FFA0A23E9E1F2DE3A8C43F1A9 -:109D3000377DAE99E6DBE7B0EF45BC6BFD80343D87 -:109D4000A8AF7463FE97C4EF9AB44AFABD12A0BEDE -:109D5000A1F1DF67D76779DCFCBE2DFF1D8ED2BE77 -:109D6000DFE58069A11DFE861123BAE5F1BC020979 -:109D700077A66AD83E87C932BF6F96D557AE52E9EB -:109D8000BB418A2CB750F921512FBF37FA4EA19B06 -:109D9000DF4BEE79E53F106F87A6015CE09C3C2924 -:109DA000FDDF777AB290F3F7F3CFAFC2857E7F0500 -:109DB000F73932B6FF7D0E8FCB1B57EEE75C8288FA -:109DC0006FC9E7B2CFE271A39FEDC2E371B8CA7D5C -:109DD000E873393CFBF691D1FF3EDE11FB0889FBAD -:109DE000D9C9F5070B755FF73EFBC5BF7F7A9F5951 -:109DF00089FBFC1AD71951BE8675EA0B617DB6D86E -:109E0000FAE867C72A906F72FC9B28F29B59696237 -:109E10005E12ABF498B9BE989887749DB2B90DE5FF -:109E2000EB4322CEFD8AA0AB03293F198AFAD62B39 -:109E3000334AF613BF1DD4D286C425F9B3E4FF67B5 -:109E4000738E566019E44014E5D59D830FCDC0C1D3 -:109E5000F73B1E1A8AF20AF8E6C78599E7AF53D294 -:109E60006FDF7A817E918E24FD26AF5FD211BB29F0 -:109E700044099D5D2C4C4F17E3F9F3A097D0F7D11F -:109E800099BB20B63F20F209E666BE8F9600ADFB77 -:109E90003AC7039437682DF6198B605DD32FFB9872 -:109EA000BEA3C45C75C3518EC07A4D4563FFEFD627 -:109EB0000BFC2907DF4B3D3F59AFBF501EB95C6714 -:109EC000323F94EB51A66C273DDE0F7A3CCF3357DF -:109ED00088DFFBEB759C0FEF5448AF6F023983723C -:109EE0004A7ECFF79A126B1B7E2F729781FB53032A -:109EF000CF9ADC89DF574ACE3717F6C45226ED05D4 -:109F0000FE1D89463BFF7E9290339D770C96DF576E -:109F1000E2F210E454C2F795EADC89DF571AC05E1A -:109F200000BB80F433364827EC022EA73BAF74DB2E -:109F3000038CFCCFFCF7256F310A7D10609115FB77 -:109F4000FE1BD801F45DBB1B8A8AC5F7B582FCF7FE -:109F50003C84FE9FEC8F4EC9F6DD8478327BA4569C -:109F6000883F2D33CBC8FDCD806F9B7B19A64D3626 -:109F70003F8ADF47BD9E35BFA51B42F8360DDB4F3C -:109F8000BFF463FEDDD418BE7DBB2893CB2514320D -:109F900017A2E3234EDF0C1CA7D311FA237E3F7DCB -:109FA000538F89E02DF35293E93B6E3DC70D7C3D05 -:109FB0004EBD9ED63387F03F693D1783F7F1789504 -:109FC000CD387E0F84FF78FF23754C0CFF4729BEE8 -:109FD0003B70DE3E3A58C9EDAEF3D6ADB7D179DF6E -:109FE0007C0B8FCBF953A49DAC4DCAC9423F249F33 -:109FF000FFE6D51C2F6EAEE37944937B1A290EC77A -:10A000006A785CCD03FFA3DF8711FC6D9AB3CC8027 -:10A01000A8F739FB9E01FD9CD32625C6DFA69BAF82 -:10A02000A378DFCDD30C09BF8F29E1305DFCFEF6AC -:10A03000F4A4DFC54C864B72DCAE8F1F88FDE6E1D1 -:10A04000EFC5C0339FF17B3739E277CC3614F5C5C5 -:10A05000F7867FC5F8DEC31C8F2E2EBEB7DF10A596 -:10A06000EF3BBC9C3977F342A09BE13F1D49DF7B6E -:10A07000BF366BDEA3EBA0FCB34D9750F9E5ACEF18 -:10A080002E3E84F55B4AA85CA3FB7806D24169C5E5 -:10A090002D13F1FBF8FB2D7C1C97D5D789BF9BE2D4 -:10A0A0001A3D780CE60FD718A3D4EE86CB1A2FC72B -:10A0B0007CA81A2B2FBF5EF6FB31541E2CCA635EA0 -:10A0C000BC04CBFB958F67F4171FBCB45409E3EFB6 -:10A0D000A3D5A4F3F693C63C918BFEA29A6A5EBE0A -:10A0E000D453B57A08D6EB3E99D19F3EF286B0871D -:10A0F000A47EED15F4FEBC76B40DEF117A6D8A07DF -:10A10000EF8B782B8FF2EFAA99795E89572B53F159 -:10A11000BB9BD51AF7F38EB7B5E4205FBCC9672C9B -:10A12000477FBEDD56DC867AF1A0CAAAB178DEE3AD -:10A13000CD8CF009E8EA10D1D5151F17A62132DB26 -:10A1400012E94AE2ED64494F35897403FCE0F7FCFB -:10A150001C13E901C67D87F8C75589F2AA8FDF274E -:10A16000D16D323E0EA817B0443E18C3D390128F63 -:10A170009F5D48AF9C7E3FC2751875BD6E7C5FA425 -:10A18000782EA1449B01F40BB93E745BB231E7AF6A -:10A190000BFF54A98FF315D8ED59382FAF877E1ACE -:10A1A000FE989D5C17CCFF05C167255F4F97D22CA9 -:10A1B0007E1F85DB61D2DFD124F6FBDF798429C3E2 -:10A1C00000800000000000001F8B0800000000005D -:10A1D000000BE53D097894D5B5F79F7FB6249364CD -:10A1E000929090100893044280244CC222CAE2B09C -:10A1F00004A32C0E9B8022FE095BC84202E833B602 -:10A20000D80C844D8B6DA8A8A8A80302A2450C0AFF -:10A21000881AE8B088585163D5D6A5D244ADEC1061 -:10A2200083B6D8FAEA3BE7DC7B33F3FF498AF4BD17 -:10A23000F77D7DDF83DACBFDEF7ECEB9E79C7BCE69 -:10A24000B977D83ECBB9C64C467F7E48636C503850 -:10A25000F385E53196C8DC6B54153E76CAEDE3CD47 -:10A26000C6D2AE315FF5650C3FFD703D63172D8E94 -:10A27000354A346315E15139AC1F6353ECDE076C8A -:10A2800026C6A6C6CCB630E8671AF3ED894967EC56 -:10A2900085082DDA3510DA997CFB1B15C6E6328F5E -:10A2A00095C1F76CC5E3C4EF8C056050C616E23F5C -:10A2B0005DC17EBB415F0CE6B1D0EE08A839F06FFE -:10A2C0000FEBD129813145D4638679437D0F8B858E -:10A2D000F2FA37BE53B0FEAA3A05C7E9CA1A92305D -:10A2E0004D6295946F5D97613D3591B856C69A73EE -:10A2F0006DFECD388819FE1BC0D8F1C20CFFFD4A97 -:10A30000705EC7159669867A3E25DCBD3595B1BF6E -:10A3100086C1FAE17B2701872145FF318145B59D43 -:10A320006F959DD7BB3B3C6A33A6D76784AF30455A -:10A3300063FB143FD6EF140E694E70FE7F3531CDAE -:10A340000EF3BD5B8575A8B88EE6656618EF0956F5 -:10A350004BF9492E5834C0AF73EB7A7C0AE2C96AD4 -:10A3600052EEF03A604DF8E7FA603AC905008D27E1 -:10A3700070292C21086FE652981DF245222FE1DD4D -:10A38000C9EAEA8AFD18E15C64B735117CD7E47B41 -:10A390001AEDC1EFACF6114F683F1DD55300AEC9A1 -:10A3A000B16DE10FF3A7F98DAF1AE5FD320EC717B6 -:10A3B000F8B82792F031FE9E11F45D9994A934C249 -:10A3C000BC4615B8288D1DF09E9965135EA6D7650D -:10A3D00005F1F475BC368BE8CBDC387022E0F6ED85 -:10A3E00081CFE46A507EC2C48AB19E113E25089F87 -:10A3F000816DE1D34A7F06387434FFD722BC6538BB -:10A40000EE79A5611016C677710AB86BA9889F18F6 -:10A4100067EA881884FBF7302ED0FD142C023C3FED -:10A4200096A0DD89EDA6316FBE19D61B5BA059340D -:10A43000070D67C2F92C76F2F9E4AB0EA2CB961D9C -:10A440008ADF06F5467B7A3F3214F215C72CCC0F13 -:10A45000E52D8CD36DCB46D5EF037A99FFE64B8380 -:10A460006087B12F049DF6DA60622E890FF8AFB7CE -:10A470003F9CB93283F9BEDB6375F9ECBA2EBAFAA8 -:10A48000FDF6A5E9CA73037D74E5FD8FE5E9F203E6 -:10A490001BAED3D5BFE6A391BAFCB58D37E9EA0F61 -:10A4A000393549971FD67CABAE7E4D18EC9F7E08A0 -:10A4B0006E4F4326C0658EC0D3F5978B74EDCE46A4 -:10A4C0008D3986FB6ACEDAF9E3705F8D60A5BA7EBE -:10A4D00058ADE573A4CB4AF88BF89CC7BCD101807A -:10A4E000573E6B3E9A0CF05BE857DC08B7F91B78D7 -:10A4F0003DD96EC1BE45236330F5EBBF9732733053 -:10A500000FFD54FD71D36F8F84948F76169A90FE51 -:10A51000EA5C919D906ED835EC9A1FD476F1EB0EE3 -:10A5200020FE3E50DD36F8B4F84D95F6C1E2E71551 -:10A530003F837E3358CF68CC571C53991FF07F92CE -:10A54000553E3C14D2BF56FB7F7BA467103EB644F9 -:10A550003D9EC35C7A3C4764EAF11CE9D6E3397A54 -:10A56000B01ECF311E3D9EE30AF4788EF7EAF1DC8F -:10A5700079BA1ECF499A1ECFC9C57A3C77ABD4E3CE -:10A58000B97B951E9FA9BE123DFE0CF897FC377D46 -:10A59000CD625DBD563AF0168FC3B467ED4F74FDC2 -:10A5A00096AA6556660AD2830FFE223DF462CC1D40 -:10A5B00000382F043C045C6DE9A0B87EDDAAE47F7E -:10A5C000810E9A11FF1121F85767466BEDF06B99D8 -:10A5D0004ABC82BCFC8B0BF84878AAF61DA6D37B3C -:10A5E0007D9D6206BEC1BC85BDBC9141BE6794A77E -:10A5F000528EA23C320F0ACAA38EF85A1B393A4136 -:10A60000CA9F0EE4A8AB5B900F02403E665CCE335F -:10A61000B6D684F39821E8FA5038A7CB4B58742D5E -:10A62000D4833A83615E1FE3BC619C8FC3FB1EC170 -:10A630007D7A2BABB360FF335903A5B35833A51A0A -:10A640007392DE50C4DC94CE615E4ADFB66BC9A95A -:10A65000C037CBEC8D8350EFF84BE17B27149CCCBB -:10A66000F1389C6C877095FCFA7DFC27D4F3A67AB0 -:10A67000D353213FDAEEBAF321F87408E504F2DF90 -:10A680007171345F66F6664FCA6EAF9FE524375E20 -:10A6900053340DF9AE2FC9EEDE0A6BEB9BCCEC49BF -:10A6A00028E712FD6993003F79A97AF9D247D0C40F -:10A6B000F35DEA16A39EC4983F16E5C3D58E3B3CD6 -:10A6C000D5732DAE5FD6BFD27AADD6BA4538CFE6B8 -:10A6D00072877B33D0E707021F4FDF620BA851411F -:10A6E0003AFA2862D6D178C0DB5D11DA0DD8FFF4D2 -:10A6F0006937AEC2BC7228CEB518E677B110E0CD8E -:10A70000E13F96C35FEB9E004B3CDF4DEB158DF0B8 -:10A71000F772F8C33FB2BDEDCE9FCF6794C2C77F3B -:10A720002D429B82FD1C3235A4B8111EE68641A441 -:10A73000773AE2A99FF3560E978EE03032A2DB4CB7 -:10A740005CD71C9BCDAD429F23158ED72FE3EE988F -:10A750005501FF9C6BF2260454DDBC8B10DF65CEE7 -:10A76000C2EE494037E72D62DEF67801775716EEE4 -:10A77000AB8EE65D83FDA31E78AFE2473D90FE40C1 -:10A78000FE655F8CFF7EC8DB4C973E988CFA4BB61B -:10A79000C9BD198A368643D740EFEF0A783F6181F9 -:10A7A0007C2C7D5F83DF13C379FBC4874DFE1A6861 -:10A7B000EF1DF90AE1E9E9850E5A4F2173597193AA -:10A7C000CD16FAF39F47FC7D7F23E0C397AAFD14C3 -:10A7D000D771479C29E5039A87D617F51D36F4C72C -:10A7E000D1BFDCA7939C7C097305DC26330FEDBB3E -:10A7F000A94CB3E0B8BFBB60F520FFFC9DE027A0EB -:10A80000DFD3F719CC4FE96D2C40F56F678D947F3E -:10A810002F22A75B15CC6FE223BD7A227F0D81FB2F -:10A820003A82BB5DBBA313A797939D11EEEBE37F29 -:10A8300014FD4E14F402FBF551A417D8AF0372D3E4 -:10A8400042F6CD684E2FCCECECF9CFF64D430B978A -:10A8500017C0181D49B0FE1B040A6FF094929C406B -:10A860003DAB13C0BFC1A5929E5530A2C98CF3DF8A -:10A87000F635E7636F2C63913E287F6384CA105FCF -:10A8800013368C398DED8EB340A701503FFFB27661 -:10A89000241AD63F01F83B706456D015E444885C16 -:10A8A000BA2971DD68D4236EEAA1FF3E96D5AA08C5 -:10A8B000BF71597AB93201E58AAC07E31D4438C447 -:10A8C000B6952FF5A942BEF4617DAE46BE2C367911 -:10A8D0000E131F013A43BA2F32334F7BFBCDD54BBA -:10A8E000917C8CF4969BC5D82DE32E592FC27AFF0C -:10A8F0009EAABD83FD2C1EFFE759C88FE11CF5768B -:10A900007F94A3EFA8EC7E28FFBC1A200EC2F5CBE3 -:10A910006A3BF38082F355B593F2A7AA13293D53FE -:10A92000EDA2F45C7526955FA876533E2DCDFB070E -:10A93000ECB768CDD766D4A3568749FCF1792C11C2 -:10A94000F4BB3A8C9FA396442EF9A810C65D420230 -:10A9500010E4755DED18044BC9BEBAA398C277D553 -:10A9600081E5EB1437CAA7B947B455483EF38F3792 -:10A970004E40B633F0C32F13106EE59715A6C1569F -:10A98000BABFA7E72B1CFF64F5609AD7E96A0FCD21 -:10A99000CB53DF74340EDA9FAD2EA0FC9034EF3928 -:10A9A000ACE7615F5BB1FDF81D4DE66428CFF72889 -:10A9B0001EDCDFC33DCCEF07FC6DB07079B101E464 -:10A9C00005D2CF88EC494FDCC9909F6B7FC1FD3128 -:10A9D0003576767E1CD2D5E04233D69BF63DE85CD8 -:10A9E000A941FABED23E397F4021F89C3F1043F086 -:10A9F00090702A17F83ABFB7EFCD43A0DF03A04706 -:10AA0000AA30BF96CB269A5FCB47E17E54128CEDDD -:10AA100017EF49EFCC1CB84E686CC37CDFCE0CF04E -:10AA200010617FFA093C979D7DFEEE44C4CBD9D8D6 -:10AA3000BABF7C827CEF33CEF740E3FDEA31E48B92 -:10AA40005D13DDF743EE8205CE6974AEA98C40B983 -:10AA5000B8D0CA349ED7FA62FE6C38A3F3EBA09D3F -:10AA6000C923713FE178AE5E41BE96A9B85815D0B2 -:10AA70007DC6CE47D27E0AF3DE5E37F793C7203D10 -:10AA8000EF37F92C20B7CEB3BA0BAF225FDEE270FE -:10AA90006F6558DF1C8EF57F6EE1F3F26D8573BB39 -:10AAA0000BFBF3131D43B915CBCB5E7CB40BCEFF70 -:10AAB00035D44B20FFDABA08E277AF59DC27AAB0C9 -:10AAC000DD13BCBF677E71CFE7FB307DA03CEF1E7E -:10AAD00048FBA7C5523F737EB5A00FB607B9CF920A -:10AAE000803FFEFA6525100670CB5E7F7079128C70 -:10AAF000D76F6393A90BA4B95B941A4CFB762B38E0 -:10AB000086F2F6DA3417E1ABFF8E5415F5C93E5DD7 -:10AB1000FC9F5C4FFA805E4FC85AFFF5C82E2CA8E8 -:10AB20002FF451EACE2C037A58DDEDF779FC9C58CE -:10AB30004BF3D8533FF9FDDB18AE0334119C77A1DA -:10AB400095EC14B85C0BE4CFEF4EDF84F68CBD2699 -:10AB5000DF26925F455C5F39EFF53D8A74560EF54E -:10AB60007D902FCFF5455D07E5E59FF5700345B175 -:10AB70006E4FDE5080F058B8FBA1315DA0DEF9A128 -:10AB8000CC0DA860C57B2E8DC176AC1BE8D6D8CF86 -:10AB9000EE9A845BA1DDCFB3460E44BAF2AA7534B7 -:10ABA0000EABE0E33C22E41E6B04E024081104F544 -:10ABB0007E0E9FF17B6C7DCCC16416C44F45FDB207 -:10ABC00054B4B70CD0EC6E15F74DAA2FA9D211943E -:10ABD000A320FF6E4B837A4956D1AF73728AF72A4E -:10ABE000E49F55C833D9DF2356E60B8BE57AB38251 -:10ABF000F2D9CAE5F656E02F557941B90DE396E250 -:10AC0000B856A12F278390CE8579263F62F3936EA5 -:10AC1000F023C737DAD1A4DE323DAE667F23DA7B7C -:10AC200022B4BB711C69376366B70BF5A215119E80 -:10AC3000AA34D2BB9A53700D205797A6417F0B556B -:10AC4000D0C3D243F430FB8F93AB2F447896637F0D -:10AC50003FB6BE91EF2EF9D6C472810E963C64A326 -:10AC6000736A8DB037D408FB564DE4203BF20B7667 -:10AC7000C4547614E4ED30DE436BBF4B22F3889F5F -:10AC8000D430D62EDC0E001FD080EF04406E68C09A -:10AC90000F865F6E5639DD371C8E1E80FC9679223A -:10ACA0005D680730312D449E1AFB01BC6DC6758E60 -:10ACB00060114C0B919B1E1663C5FDCB1CB1FFD2DE -:10ACC000FA870AFCC9750C15F6BCA12D1F4520DFBB -:10ACD0005CF26D1EF1CF8ED6B75FACEF37B83E4851 -:10ACE000937A79F7E03C877DE334E33A879927A6A6 -:10ACF000A09E03F37F0DF13CFC1B937EFEDF87EBF0 -:10AD0000F23F761D7729CC67C2FDF9B5D58FFBB32D -:10AD10001EE81BF773FD822C3FF281BDB01FEC785B -:10AD2000AE9964253DB75ED849EBE39D645F7ACD6B -:10AD3000C2F3BE19A27D182339523FA30BB5EF62AF -:10AD4000AB7C2B1BFBAF8920FE596FF1AF49C3FED3 -:10AD5000EF8D73FB005F2ACA8FFE70DE10FCBBC64E -:10AD600012B84DC5FEBEB6321C6F7D4C20B902EA4A -:10AD7000AF5FD085EA7F04AA14DAEF86984C774C4F -:10AD80007460B9272916F27BFFA192DC589F0B79DA -:10AD900007F171B207AE9FE8490AEF84698289E63C -:10ADA000A3B24AFA9ECADB7D62E1F56E15F8FB5844 -:10ADB000E007F639F1016D428419E9D8945EF46D2B -:10ADC0001AE1DD93A4C07C1E9BD393211FBDB5E483 -:10ADD000C654A29BDA47889F4D173890FD6103FB4C -:10ADE00020D4A3F99F1973B786213EA71687917DBA -:10ADF000F4A3E2E5912E683F55530336B41B4FC9C7 -:10AE0000F7849EC74DE91E1AB7BCAE77FA97217436 -:10AE10005D6403BE01FDFF225CFB9EF6EDBE5C2A75 -:10AE2000DF07CACD0FB0AF3E9FD37327D935E6C831 -:10AE300073646036E2F540B39DE1F9A4237AA8413A -:10AE40003C40BFDD855C277A45FC4F0FE7E71C33AC -:10AE5000D00BE46BEA7AD339E7290BF32888AF3DAE -:10AE600036C27FC124BB87EC8FD3C337D9A0FC0E79 -:10AE7000C1CF6AA687D3F79AFD917E9342E727CA8E -:10AE8000FB7659A85D99D5FFEC36E8A7EC406F92A8 -:10AE9000377BAD62DC57237879942775E5002CEF7A -:10AEA0004C74F09AC5154DE56FAA8CCAC3031931CD -:10AEB00000C7B830AD5BFA40A43BC0B303FBE5DF8D -:10AEC0004F08FA3A01DD22FE7C9591D42F6D7DC8A2 -:10AED0006B35DD36233E352B2F673F51A9FC84D3DC -:10AEE000933417F2272A93695ED2CE74C26B25BAC7 -:10AEF0003F51A690BEF4C72A35600DB5E34FDA7E08 -:10AF00005F06B4FBE28085EC78337F597A1CBFCFB3 -:10AF10005C5E4EF6C899254BC94F7061E9178336C0 -:10AF2000C07A1A977F9AA285D8A5679641AB90FD03 -:10AF30007C43BA67503AE06776BA762DAEAF22AB63 -:10AF4000711EEAD717AC0D4FE27921A3933614BFD7 -:10AF50005F7CE5E436AE773767A09C5868E67422DC -:10AF6000E56D85A0C34BE9DA48AC0F709B8572256F -:10AF700022AB81F3BFA53F8EFF9FA9DFBA57817136 -:10AF80004AC3EB1752AAFA73B09FB34A204A492723 -:10AF9000386AB8AFCE390351087FCDC4F5BCD2EDC5 -:10AFA000FA75E11F7302DACD18D9C14BEB544F1873 -:10AFB000EE03E6B7E2FC4B9935583F35882FE8871A -:10AFC000F0C51C7F9CF553C043C9B3BDF3F07C5161 -:10AFD0001AB3EF1743A81EB493FB456D9B97EB691B -:10AFE0003B1FBEBE73621F9C832F16A4971D36792C -:10AFF000CEA7F12FBCD299C64F10FBE48222E8F510 -:10B00000D9304E576E5817CEF3054E570F4B3EF9B9 -:10B010002CEFA734CE6742BE545AED24BA927C0975 -:10B02000E642FBEBECCE646A27F918F33246F5777B -:10B03000266DE6FA9B38EFE284A17EC9AFF9389815 -:10B04000477E7EE6B964392EE9DB46796C5CF7EA27 -:10B05000746E9F0239DDF99F9D173313673F31A747 -:10B060007FC87A22AD822FB8132766A37FC1AAEBCF -:10B07000F742A4F50E8F03FD0CFAEFB2BF07D3F928 -:10B0800079B2BB01CF5DD4E68336DC874F33921BA8 -:10B09000C6793C26DA3DF75C2B5E55614F672E4939 -:10B0A0004F2EAECF13FE3EB64AFCDD990CFCB81411 -:10B0B00061951684E3DE5C2D19E5C605E11FDA1BF8 -:10B0C00003F92CD4A7385E645EE2C34897CB3F9E59 -:10B0D000978CFEA837D2B99FCD08EF6500572CAFEB -:10B0E000B1C0F9260BCFB9C71EFCB267703D5F55E2 -:10B0F0007B3C7342F2F336E4DA713FCEDF986B2F7C -:10B100000AC147CDF6FEC75C00F773DBCD6E64EF76 -:10B110003566FF2F504FAFD9AED6211D41B91DE185 -:10B120007DCE71E81DAC376F634C1EEAE1B2FDFCC9 -:10B130000DF99E392178E8BB5D8F97EC3A7DBEDF33 -:10B140003E7DFE3DD441E3AFBE5D6E409FEF7F4C40 -:10B150009F67CD80BD41A80F70BCBD3CD87DCC059C -:10B1600078EBEE57DDF8A9BB63D2E4F1A8476C5445 -:10B17000DD3DA1BCFB52EF58D42B4E6D9CEB46B489 -:10B1800017ABBE853F059C167F3AE618CAD5B3AC0F -:10B19000EEF7E3012FF3EAD759CD2E5CB79EDEF729 -:10B1A0009A04FD3EC7ED770BFCFAF2B67C6199B4C8 -:10B1B0007B6486D297910E60DC5B3C30A1B2AAF72B -:10B1C0001F44BE503C0E081FE8ECDABA7556D4FF97 -:10B1D000AE3C8E8FEB970E8F0BE1513898975D57F1 -:10B1E000358A7D01FB8EAD7D6F0CCEBBF0E70AE9A1 -:10B1F0001F852FF53A82F4D5B46BC64D94DE5240CC -:10B20000EB9776C2F9F54A2012F2CEC1AE7D8DD011 -:10B210006EAE9FDB3B8A56D882FC90A19FCC308FCC -:10B22000F521E530FFF9FB0E7EA740FFC51BF5EDCC -:10B2300016009F46F953B2E5075BE877791EBDAE6D -:10B240007E938AEB9E2BE62FE527F30D273FC575EE -:10B25000BC09FB12FF0FE44E698216DF233E28472C -:10B26000AF5BCFDB03DB2DC475973BAC2E5C77B9AE -:10B270009D0522603EC722AD1E277CBFB42192EC03 -:10B2800074F36CA0AFE651CA308E011831F9CBBE11 -:10B290007A5725BDA73C8EE3BDFC2985CE69E568BC -:10B2A0005CC5FCD33CBF8005683D482F9ED075FA35 -:10B2B000F57956CBCF7765E6C041844B096BE4E75F -:10B2C00033C0A727C4DF5D06EBFC2816F537437BA8 -:10B2D000E6D6C88FE7E0FA58C5BE1F6CA1E5F29C20 -:10B2E00029CFC1D27EFC5486371CC7B108BD79FD79 -:10B2F0007D9E0C9CEF4A8B2703E1E05B1746E7FD40 -:10B300005B3771F9B53E06F4D84EA43F933E7EAB51 -:10B31000C2F5733683F3C321A61703286F9A1F8AD9 -:10B32000716F76517D9263EB1FE8CDF5FF7FA8A486 -:10B330000F35AFE37111EB7339FCD63F90CDF57F3C -:10B3400029F7E219F5D756DFF664A01D823DC8E75C -:10B35000F5092E2944BF8EE8AC4D467CCBF549BD9E -:10B360009C15FF387FC65611A7D1BC2ECC8FFE8C02 -:10B370002F15EF5153887E3BA707971383467AB664 -:10B38000897AE4F798639A78FFF530AF390F9B5CC0 -:10B39000687F6B85B7C79381F2F3CB756179486796 -:10B3A0008346727BD4895CCEF72306308F1FD2721E -:10B3B000D16F790F932E4D0C07FA837EBECCE7F642 -:10B3C000F0C8015EB2036E7571BE6F5CC73DA29F8F -:10B3D0003956EF6F87B5331F0917369AEB1D5F2E6D -:10B3E0005236F37901BE213FE85761643FFC52C8F1 -:10B3F00025095FA01B8A7B907C2BA6955EFCCF86DF -:10B4000001BDACB3703A90E7B6107A11F8EF46F888 -:10B41000BD55E0973D1026E8C5C4FE8670CC777216 -:10B420007AB8CAF317E07B5D8F816DCF6112DFCCF4 -:10B43000EC1FF8CFFC2EE52F3FBFD7077A46C90B8C -:10B440000F4531A877DA5C9BE086F6655B57467955 -:10B45000203D65F6453961FCD37EB5C0DF0EBCDF0B -:10B460004578F3739C4309F1939E79EEE713709D41 -:10B470007FD96A71224BA8D86EA3F3D8C2DD0B48DE -:10B480005F877C13CFAFFE1AFDA615FBF4F6F99289 -:10B49000671E4A7011BC7DC9A6444C03C90CD285F5 -:10B4A0005B2CAD7E641806F4EFE655383F637B9C59 -:10B4B000C765C077459D5A688D6E5B5E21F84BC5A8 -:10B4C000EE9F7F8D76C38ADD379E447E5F61F00BF1 -:10B4D000140BFF88D12FF09B1E7ABF33C087E20C7C -:10B4E0007C30AF9E442EDCAE5CF3EC23394DA83F9C -:10B4F0006C792B4AC90AFA07A4DFA4A56EF653AFEC -:10B50000BA3ADE9717847D388837CEBF5CFB140CBF -:10B510005682833F4FCB2C81A82178DEDB6421FD4E -:10B52000B7ECF9A7B73D8674F6B18DE47BE9F3AFCC -:10B53000FFFE3AD49F77593A8DE3CB7028217139B9 -:10B54000152E6E8F93F82979E975AB2B9B7F5F1AC7 -:10B550001BC453E9AE83568C0F32C27354DD416B6A -:10B56000A3A31D7CD5358D213BD4B37FB5E2FE3836 -:10B570007D40619D53DBB62FDEF47A14EA6708271D -:10B58000944F126FAD7834D487FE27BC3A80EA39E5 -:10B59000F19C72253C3ED58371BEF272248B817979 -:10B5A000147F62F38F43FCEE5C1285EB3969AEE4E5 -:10B5B00074FFC4CA04D4F78A2DBE0427A5FC7BF10E -:10B5C0009377113DCE572A139C5944EF4926D22533 -:10B5D0007C49B8CEB91BA7D23AE7318DE8B1F8095A -:10B5E000D5EB87F45B332BD8D5CEBE19DB93F3A90B -:10B5F000939B01B9B0CE93223ECBF73B559CA3174A -:10B60000913CBF4BAC99B1C594FF56E873DD7AB657 -:10B61000FABFEDA1E7D08A2DAB1B104F67BA793A7C -:10B62000E33C010E3E0137E507E8577D2FBF33C7E6 -:10B63000137361FC02B503B93A0ABF63FD068B07B9 -:10B64000EDEC21EDC439918F7FA7181FE61D8EE721 -:10B65000E09309EDC77FFDA4A7E40BAC2134FEAB5A -:10B66000433EB0E53EA2AF6F3EE07C66A17F620143 -:10B67000953758029DB1DC7F708A427CC2C602EDCC -:10B68000EDF32D16B1CFF5E5304FB3120ADF035CB1 -:10B690003F95F4320FF4B240889E10A41F6BF03B2C -:10B6A000ADFF57623D8DE4CF937EC0F9823F18D73E -:10B6B0006FE417F93D0D714AA23DDBD8BEFF29C8E2 -:10B6C000277C346E19C877D447CA3EB6911E51F60E -:10B6D000BCC58B703ABBE3F0EF6FC5F36D9DDCD753 -:10B6E0007A3E6CDCD7C52F0E6C775F9F5D9BDBFECF -:10B6F000BE86EFEDEEEBB50AF1BBFF2E1F06C94784 -:10B7000076892BEDDFF91DF0E14A035CBF6559D165 -:10B7100043B0D059D89DF06480AF84AB91AF5A91BB -:10B7200049B6C35719867484C053C251D22B631AC9 -:10B730008DD34AD7926E255DB7D2AD71DD7A781A76 -:10B74000CBF310F7301FEF2B16D217CAEA797C2201 -:10B75000B4A378BA0AB4CF53EDDAA3C99D42F37EFD -:10B7600043BECE50DF63C87B0DF53543BE5257BF95 -:10B770006CDF612B3F3F0474F56C5563E93CD25696 -:10B78000CFF073BFD3EEAFAD3EA48FAECD56E493F2 -:10B7900096E5CC1709ED9BF7ABA4F75C743547A190 -:10B7A000DEB2328CEB75179D221FC3F3CDF1D65557 -:10B7B000C827E5F7E6306E87B9E86D8E8A0939CF7C -:10B7C00037D5AB5168FF6DF4B382F6E35B6A683F2F -:10B7D00035B28ECAB97E77319CDB1B2E86737B43D4 -:10B7E000BEEA48A9423B6C2D8F239CB36C5A14C50A -:10B7F00061D4A7DF3C1DBECF7D93C20C308ECE8CB2 -:10B80000F10FB3392AD929E6A378C2D9F53C0E62E3 -:10B81000CE5A3D9EE739B650BCDCB76C29A5F3D6AD -:10B82000EBE3174AD85AA2B3E28D86EFF563699F1E -:10B830009418F68926ECC3C67DF2A1DC27B92C57F3 -:10B84000172729F879BE9A75F374C0C7C5632AB360 -:10B8500041BEA55E65AB06F0B858F43FE18104F740 -:10B86000DF42D8AFA83749789DC37DD4AB63FDE5EF -:10B87000DC9ECF06FD14E966EFA7398F437A6EEFA1 -:10B88000C719AF61FEE53FA47CCADAD61F75E0BBDD -:10B8900059C8A72F1EB031A4F78B07DE48417BE4BF -:10B8A000C5576D74CEBEB8DCC6EDDC0722FD28623C -:10B8B0002E76E37A71CDFEBFE634925C5EC1E5621E -:10B8C0008695F0DC52FFF713684F6FA9875521DF8B -:10B8D0003F1041FBA9E2D530B2335FDCFFD741A175 -:10B8E000F6B9FFEE7AA4FFFD62249BFE22D2710C12 -:10B8F0003F1754BC76EDD3E85F2EDF7DD03A1BCAEC -:10B9000047FDE63F7390AF5E7C91EB53172C8D4F54 -:10B91000A28D3322E3D2AF2C4968E783CEBA30B68A -:10B9200025A3FF645F567B70E170B80870C0750195 -:10B930005C8A511E74048FB47F5B787C3D8BF3B7B7 -:10B940006B18FAA38370513CFC7BA4DFAED0FAF9EC -:10B95000F7037FCD41FE73A5F57A70BD03FFFFAC01 -:10B9600077D6BFED7A39BD7F85F235BE2DDDB7A51F -:10B97000EB97FF83F23B23DD34DF1FB9DF7FF6FF58 -:10B980008CBE37FEDBAEF74AF87E53E03BD289FE31 -:10B99000CC8BFBFF33855DC5BA5FFB3FBA6EA9C791 -:10B9A0008F54DDC772A1FE5BACEE03772A6923EDED -:10B9B000EA21A7321479BEA3F3D328C6E5F4287B85 -:10B9C00029E99FA3BA3E40FA720DCB23FF85AFABA6 -:10B9D0004A7E1D0A020138BC91984BF7AC9839D0C9 -:10B9E0007509E447269753BC98F15C392A7C7C01A1 -:10B9F000EAA78797C1BCA09FC3912627FAA84777DB -:10BA00005503B61C4A9B303D9A3296E2FE473BF402 -:10BA1000E7ABB18673D28D2E7D79017BB113FAED40 -:10BA20000AB22C74BF620CD60F39571ECD70D23AB1 -:10BA30006F64B52B9C8EAB8753622F7ECE6C0B87C9 -:10BA40007F0EB7367012E768B3A86F849BD9717FF9 -:10BA500003B633333817F3F5D2795A9E8BAF044FC0 -:10BA600026CEDB6631B484AFB92BF7CF86F44B70AA -:10BA70009170BF5A784B3C19E12EE12BE166C4C3AB -:10BA8000D90C26CEB71CFE5DCDB966DC77C3845ECB -:10BA90003FDA1CC3F35D1B542FED473FE16DD437F4 -:10BAA0006E33EAF5231C3114476ABCBF5034386644 -:10BAB0009002EB4D36339F0DCEA1E87B23BBEB7D8F -:10BAC00066FFF2541C87DB77BB99B9FD1A76B72F56 -:10BAD0003C8FEA7BAC902F7C703EF340FDC264E665 -:10BAE00056787D161D4BE1714CC5383148B15D610A -:10BAF00034EFB7B033F32FE7F824BCA0D907ED1B20 -:10BB0000D0AFC714CBDB47E5517B9F89B7F79821AE -:10BB1000ED9ECEE3149A5772BB7CE1EA6E19C83FE2 -:10BB2000C68DD4DB996B7B717FA44CBFEFC5F7BB8F -:10BB30006A7227D27D8A15BDE97CA4867BCBF7A0EB -:10BB40009D7E278FD3295C75FBF88138BF9D716E70 -:10BB50009CDE9909BB06F1FA33EEFA10BE6BDBC32B -:10BB6000E8BB2B531BDB0BE30114D7AC3DF0A16802 -:10BB7000EA616B220CA1D54D3C8F76C209BE5DEF08 -:10BB8000A07F72C21495EA4F603C0E93AD88A03836 -:10BB9000CCF1BEAFCD89D0DF78387460795398335B -:10BBA0006511CCBF50D887A7897863359C692F3A37 -:10BBB000705EDD32D2E0FB78D67E7CF243627FA9F4 -:10BBC00023958DE867EA3E8ADBEF657DEC07FB7D18 -:10BBD000BC17B747158954E601AE547FCE1A5B53A4 -:10BBE0003A9E7FD65802BD20FDB0F7C879BDA07C33 -:10BBF0005C1A1BB301E17E8FCA36D37C9B0BC9AFA5 -:10BC00001099E9423C6840D2E45FA94D75A15DAC52 -:10BC100069445D00FD094D8FA6BA6B5C84658A0797 -:10BC200092E7ADA611811E68C76FCEE57E8913CE5F -:10BC3000C6483C2FCE76D8F9FD4911573457DCA3BE -:10BC4000E95ED3F8C035780E7D48257FCDDC87F8D6 -:10BC5000FDB03F3BEC7E05CF6DEBF93E656BF571BA -:10BC600044CCE9263BD0ECDA11563C6FCE7178AC6F -:10BC7000B84E7FA6B602D725EF23F641244097851C -:10BC8000B58514AFA246C1BEC37D627645E139D801 -:10BC900018875421E28E64FE17E1DA03D85F51B4AD -:10BCA0006B27D2CBE755E9641F3D2EE86E1CC655C5 -:10BCB000A23FC3DC9884F3198EDF11AEB1CE0C071E -:10BCC000D17318433834599C1948DF4D2BC34CE8C5 -:10BCD000971BB79CD335EC33BB19DADF6766E1E815 -:10BCE00067B84DB49FB9CCECDD04F9AE76668E8CA6 -:10BCF00045BACA25BA4EECA315E17C4EDDCB06232E -:10BD00003DCC5EBB8EFC31922E98B961741C8C7355 -:10BD10006A6B6A1EF2CD563EDD67E4965EA1F43092 -:10BD200045213A80F4603AD1C3A46791EEC78D0CE7 -:10BD3000F4589C85E7D132E641F99EC8DCA827B4C7 -:10BD4000B066F257B638AC2EB47F497E22F986BC75 -:10BD50002F2BE9601BC87BB385B1EDD5764A9FAB2D -:10BD60007632734FC6765427527E67B58BD2BAEAC5 -:10BD70004CFAFE62B59BF2BBAB07537E6FB587F200 -:10BD8000FBAA0B287DB5DA4BDF255F02B8101F92A6 -:10BD90007C45F2A3D90E6B13FA2F255F32D2CD2C3E -:10BDA00000EFF03C6A4F7C4FF23B5C87292FC88F35 -:10BDB000247ED314AF2F3115F958E30CC47FBE7A1B -:10BDC000EEF997F15C5EEC70D3399D71BED702F449 -:10BDD0008A7049B1B27D6897AD59E4695A9D1A8459 -:10BDE000FF6DC50A3387D0D5ED9561CC1C2237EEA7 -:10BDF000A88AD1E56756BDFF7A67DC0FF1DA67885C -:10BE000097133FFBEA893FC0F7A77E76A627E21B80 -:10BE1000E6B1F5111C776978EB3C6231BFC2427E16 -:10BE2000AEEEC27ED25DD84FF04FE87DE6A77EF63B -:10BE300037DAE74D553617EAC59F20BE00BE7F149E -:10BE4000F82AAAB2111C0B577EF1FCCBB8DF975A27 -:10BE500089DF15AD10FBD1700FFAF324467609D0B7 -:10BE6000AA299EFDF37BAD8108E8FF7385EF63058A -:10BE7000948399187FB8E68D8F900F2855C7C8FF17 -:10BE8000AEE1BD3D9C9FCF724E77AFBAEA28D56335 -:10BE90008D5D63D0CF23EF25470CF0585DB07EA4B5 -:10BEA0006DC45F51E62196847E965AC589AADF1C2F -:10BEB000F17DCE1A85FC9A18C73305EF9167AAB4B5 -:10BEC000AF46F432135E9FC2187CD2EF6A494E49E6 -:10BED000BA9DB316DAE1FEA8CDB5CE0BE1C745E2B7 -:10BEE000FBEC4C13A5F27B02F60BFD7559933B1D41 -:10BEF000F58A2E589E8569DE74846F17C718B312B1 -:10BF00004207CE4CB398071FFF29442EFCEFFECC0E -:10BF100034EBDC2CBA0F48724C8E539499B70AE379 -:10BF20004B8BD68E402ECC6A2CEEC44E502FA9B52A -:10BF30001F711FDBCEE3A8CB3A9023D2AE760AFF67 -:10BF4000792DAD9BECBE253B7FBD13EF17947C6A2A -:10BF500023FC96F413715B59FE4193C900A9B7679E -:10BF60008FFEF56751E4A7D8CDE33B21E576D6A552 -:10BF7000C5DC2EEB86FDD58EBFE8C8CE4FA3DAB563 -:10BF800063EF567F941DBB42F93E0AF508B99EFC4B -:10BF9000FDDF26D03C94CBE427AAD8BF32A1BD3820 -:10BFA0002FA31DBBD5DE2DEC7A154B0BDAB5771B15 -:10BFB000ED77E3330DFE0333A37B66D27EC7D4ACAB -:10BFC00068F4037C2BEE9F7474CE91F6EF8A0DD04B -:10BFD000491CEC57B32B1AFD5B173BD0AF1FCAE4CB -:10BFE000F2FFBCB0975FDCA1D2B9E7E28E48DA5726 -:10BFF0000B773C7814FD8E0BB728348D72D640F049 -:10C0000003B8327BA85CC338B6B8B6F36EF1F78CD0 -:10C0100046B952FAEBC84AA4B705758A672BCCA774 -:10C02000C5EE8A8E0F99CFA24CBE6F4A6D758308FC -:10C03000DE62FEF3335D4457B2DE82FA07C9BE0CFE -:10C04000F52E905EF44204E3F7539ADFC1799EDD4A -:10C05000D8DF8DFEC20575BB16925EB123C289760C -:10C060008533226E59F673AF18EFDE4CAEE79D159F -:10C07000FEA3B33BF93B00384FDC6767146E87962D -:10C08000ED6AC4BEA8C9E47A5606C2203E587F4174 -:10C090005D53540FA87F72DFFB943E20C659E068C1 -:10C0A000C841797C727704F9BF4EEE7E7CCC6B3050 -:10C0B000DEF9BA119D705FC8FE1FCFB4707C6C545E -:10C0C0000B105ECCCFE366CA11BEFD43E719B7C9BA -:10C0D000971ABAFF78FCD0D9DD2F4599B282F82C97 -:10C0E000B757DA934CB88F167991BEA39178A07F99 -:10C0F000EBEE893E946115F5B90CE99AF65F12D51D -:10C100005F630AA967B3B829CED4B2AFD0C3EF99A1 -:10C11000887B51228E3F5FCD22BFE2AC7EAE69B7F5 -:10C12000219F7CCB42F858DCDB350DF9D3A5069571 -:10C13000E13C17A7B200EA274BEE89DC84724CCEB3 -:10C140007B567FCE0FCAD628CC03EB2BF3AB4C83A8 -:10C15000B40BE0DF87F494D83810E3249B52B95E27 -:10C1600021E3471F2B3679AC20075FCF8C157C5617 -:10C170007B742EFACF2665D279EE8495F954B42BD0 -:10C18000BDC8E34BCBD2785CF363221EBE2C369045 -:10C190001107FD9D13F82D9B14C8C0B88BB21793DF -:10C1A00028EEE29C95FB3DF13BFA59CBF2A0BD8312 -:10C1B000DED9D064FB98107A2A2B72BBB09E1AEBA2 -:10C1C00076E53A70BECE0BA4E7EE8964A8E79A5EE6 -:10C1D0008EE47153CF846DB685E0EDE34CAE47CB72 -:10C1E000F73BD8AD3CCEE8610B8F4B7D786B92DF8F -:10C1F0001F02AF872DDA0C8403AE03F5FB05D6DAF8 -:10C200000CD47FE57C1744D5D23CCF097A5F105E11 -:10C21000CBE3B9C57D60AC8FF9261187DEFCAC8D10 -:10C22000E280CE2435ECC5F1CF3CDB9BE1FA9B529A -:10C23000FDF3F65139E89780CF92E76C015CCFE9C6 -:10C2400067B93DFAB485EB6BA72726BA10BF0593F3 -:10C2500036CC227BCD169B8276BED30AB32662F9FA -:10C26000D6788A3F2FA9AEA2F8ED12601B787F081E -:10C27000D202BC07747A6B6F8A373B8DEF3628F495 -:10C280007D0D7ED758EDAC9F203CB6F3F3D599E7F2 -:10C29000FEDE3B34DE5BA6255BF4F175924E64F95D -:10C2A000DF047FFB9BD8E7FFC8E4F688F288BA87F3 -:10C2B000D3689D1CEE8027FE8E0D6B8C7C7C00C6A7 -:10C2C00053F454908F3CC602198FA3DD613B3F7F2E -:10C2D0009DD961A1B8F59297233D14C7B6FA1A13F8 -:10C2E000C553A85C4F2F3101F820557EB69DE2CB97 -:10C2F0003A3D17966723FD9CD139B779AB2AC661C1 -:10C300000CEF539EDEC6E38EC7A12E49E5D9547EBD -:10C310005AE44FEFCD26BD0FFAF7E0FDAA929FFC3D -:10C3200094C37172F171AE77D989DF96B5FA7986C7 -:10C3300046A31C2C5F3D241AEF2BB27755867A8BCF -:10C34000114E97CCEECEC867C7F7E6FCAC74EF137E -:10C35000E49F2A15F7084A9F53B81F1AF621DEE713 -:10C360002C5D35E411A2CF772CAC27ACE75CDD83E4 -:10C3700051A1F8B8A637E773ADF5AD6EAA5F0AF51F -:10C38000B19FD2556F45D17CB659285EC588C71F6D -:10C39000DDFE39F547B56FA58F3A6E6769B37ED676 -:10C3A000F01F9F42FFDFEC0873FBE86B1DDD833B52 -:10C3B0006BA99B87EB3FFB7C18F1ADB3319C3F9C95 -:10C3C000047EEAEB85F318FB4B8AEFFADD64BABF13 -:10C3D00037DFAFEF578E3BB437E7E3E571EE688C9C -:10C3E000172C7F97F341C0CBCDD4FE5D0BB537AE94 -:10C3F0002359B46BDD9FCF47103D9CEDC2F172769F -:10C40000672F924F4D319CCE61BE2978DFEFECF360 -:10C41000BD72E91E1D2A3D400F25E2FC7B36A62E8B -:10C42000C51952DE6411E7B800D444BAC136C0DF82 -:10C430004BAAB8BE556A5F4BF12518AF3B288FD287 -:10C44000802DB66DDC2DD02B9D2F1FEC2DEC983858 -:10C450005E828813273DA8CE8A7C5B13FA62D90ED0 -:10C4600063DC2E2F5F2CDBC36C3BC93861A4439F78 -:10C4700042712AA52B162DA0F8FBCA75B7E13E9391 -:10C48000F32F35B3023CA735292ACDA3298CDD3102 -:10C4900009F5CAD07142F4B97B83E3306702E9B190 -:10C4A000A4F42FEBEDA2EF98AFC57BAD2B94B53480 -:10C4B0004EAA3CEFF27549380138AC1827D83442FF -:10C4C0009477B06E394FE3BA5BF5AEDE9CEF37A5DB -:10C4D000BA7E3914F1FCB64AF77F2F7DDF3F3AB6BA -:10C4E0001D3D2D28E7ADC1785998FFE6DE8CFA99FD -:10C4F000D79BF3B5528CC78579666CD4C78B676EB2 -:10C50000D1E7FBECD0E7B376EBF339F5FABCFB8867 -:10C510003E7FBF1817CFE178DF18CFE198E239DC12 -:10C5200065E3E770CCE3391C533C87E3773C8763D2 -:10C530001ECFE198C77338E625BCF13C8E793C8F5D -:10C5400063F9FBBD39DF2E13F1968807A477F64A0D -:10C5500098EE3ED2C5FDFC7E09D001DF3733ACB486 -:10C560006F1EC31A741EE176A72E93ED2E8C1F5EEC -:10C570001BA7EDEF1D8FF7501A562521DECC8D1429 -:10C58000C75AF12A8F632DCB0B73A0FDA371E5C9A8 -:10C5900055181EAAC56987B0FE454BF336846F79DE -:10C5A000D561BAAFDFB8CCF5EEF51C7F648761C505 -:10C5B000B1A44715A29C8BED188FC67872B6561F92 -:10C5C0003F6E8C2737C6911BE940EA7F4F599A93FB -:10C5D00090AF7FF1AC7D2DCEFF8B30711F66BADD41 -:10C5E000100FE0207EB2F8016533CAEB2F7A733D5D -:10C5F000AAE518E8EBEDC85999CEBEDC9FF4F2D657 -:10C60000FC5AC544F1E99A87E4D01231A714A5B9C0 -:10C610006935F2B90526929B97405F237DF003951B -:10C62000F4077C572B743DF8AE56287DE1BB5AFACF -:10C63000FB125D74F5F15D2DFD7D893EFAF8FC2954 -:10C64000CB0EE2B97FF2DAFEBA7A73BC430C7014F7 -:10C65000F316FAEC1C901F1ED42F976E4841FC2E47 -:10C6600059D0D2B41AF0BB644F981BCB8BF1FF802A -:10C670002F16439F78EFB278B7B8BF5CA597C3B3C6 -:10C68000851C2A36339F33364887C54EE68981F6A6 -:10C690000BFA34E4E0FB590BDE7C7F90330DCF19AD -:10C6A000233A233F4AB17828AEB66C57CF9865D06D -:10C6B000EF373DB4D83E80972F6B0FFF6226CAC379 -:10C6C0005DFCFCF7C5DA97A228BE4CD05B8AC51981 -:10C6D0008E78DF54CBE3EBD07EA6C606E962536DBD -:10C6E0005C780F4770BD413AF89EF004F8E1769E01 -:10C6F000E243E41769A913EB1DA1F850CF96EB9321 -:10C70000EF6EB115BC9F3B45FE4B71DE90EB3CD705 -:10C71000FB608E0BEF7554EF4B51919F9B766CC372 -:10C7200073C83F6C5A769F788C07EDF9077C87AD0C -:10C73000E443BE9E3FAF1F15752DEA9FCF5BDCE340 -:10C7400020BFBAF6692B9E2B4ACC7E2BC5673EBB19 -:10C75000C98AF1CA376CDF44DFE76D2FA478CCF9C2 -:10C76000AC92CEA3A7E43B09021EC523958D4E983B -:10C77000F7837D389F2D0EE7FE3DD08F5EC7774A49 -:10C780002E6D577231CE678A7797B510BE8FE9C389 -:10C79000F98C719FB41C9F9C1F4FF0E0F7403E64E2 -:10C7A00070BA4F6FBB2F265F4EA57D31E5725F3AA1 -:10C7B000A74D0DF4E6E7E12CC379F8B8CAED79F599 -:10C7C0007C1F145B039D26E33E3960213DB7DCCC22 -:10C7D000DF792A877F5F07A977A8AAA3D78AD11113 -:10C7E0003A7A9ECE6275F7696EC1A09290FC947100 -:10C7F000E9BAFAD3A6F435D07F5EB09CF8C875BA12 -:10C800007B7FE54B7D2E85F4CC91FAEF8CC71732F8 -:10C810007693AE7D399B14AC87F4BD45E1E79EDD90 -:10C82000319BD10E586CE2E7A7E91AFFBE701FFFDB -:10C83000CEA633DD3EEC9EEEFE03978B16F21B4830 -:10C840007BFB74FC773BF0672CBCF51E3BDEE347BB -:10C85000FB84EE7EB7F017E2BC110FE5C29E549E3A -:10C86000C9ED49E5BE062BBE9300F037C7C5523D62 -:10C870007B1CC655D62A646FC47429C559EAE3B433 -:10C88000B03F8C7F5C784C2DC47D622C2FC6778A9C -:10C8900010BFAFF2B8D48568178A6AFB3EDA42B49B -:10C8A00013A17DCBF01EDA877D5CC26FE75FD505F3 -:10C8B000E1384EC9A57B9B3B0E5A313E6FCA949816 -:10C8C0005CDC3F463A93FC1DF635C515B61C3F4C63 -:10C8D00074D6526C263ABE123C167AB89DD5487F63 -:10C8E000F3588315EFA7CCDBADB8F15C8AF5102EB9 -:10C8F0005D902E0D70898B6D0B0F09A756B819CA64 -:10C90000E7330EAFF9FB143FF2C7367012F033CEA7 -:10C91000BF23F8C975CDD3B431C827E4FAE6E33AAA -:10C92000701C58078E23FD166CB071BFA693FD6A6C -:10C93000A197C7D91AE963D2656E97B9E5B299D2C2 -:10C9400029E3F4FB13DBE13E997A3981CAAF967E85 -:10C9500016C23C512E5C2DDDC8F5487E1CDC27FC40 -:10C960005EC295DE3932DA279BFA88FB1003D94084 -:10C970005D7CB3E0B7C6F6C6F866A91F18E54E6140 -:10C98000A489E22D5B1C69A47748FEAB09B9A2AD6E -:10C99000FC96EA69508FCFC6A393439AB0132E8EAC -:10C9A0004CA377245296C52520BE0AC39C14D75F9A -:10C9B000B84CA538EA42A8E70AD15B56AD484F41CA -:10C9C00039F2F97DBD9EF4813EFFF93D9D1206C30B -:10C9D000385FACB474B2BB82F53E5F999F82F11DA3 -:10C9E0005FACB34DF7B703AF88BEE23ED3CF3E2274 -:10C9F0003977DE743C6A3AB42F5BB9270AAF0F94DB -:10CA0000AEE4F2FDE11E5A78DF8128E7376D73222C -:10CA1000FC9C9B72D04E9C8436DFF8A05E51B232F3 -:10CA2000BF33EA1D65FF38FCA413EF852FB324A0A4 -:10CA30005E7AFA0390930AC939D2274E854117E4EA -:10CA4000878BA4F7CF4E29CC83FEA873A6837F598A -:10CA50008DE7C5DCBA8C8082CE532DA92FDA5557CD -:10CA60003E4DFA4CC9FDCB32F01D426D59CFE8F670 -:10CA7000EC2932DD26E439EAF598A25E8FF135A87B -:10CA8000D7631EF57A4C51AFC7EF151BF47A619A44 -:10CA9000F06F49BB73F79AE65CF4FBF946B2CC4AF7 -:10CAA00092C30E7A17788912EE46FEB4047528CC2C -:10CAB0007F16417607F6C18D3A3CCB7783E5BBC044 -:10CAC000C39A41570BD927D75FB6B3D07BBA235847 -:10CAD0008C2E3FCA9EA4AB9FEF4CD595DF90D85BC0 -:10CAE000577EA32B57971F9B79ADAEFE78F7085D55 -:10CAF000FEE6C137EAEA4FF44CD4E52717CCD0D58F -:10CB00009FEA2DD4954F9BBE40573E435BA4CBDF9D -:10CB1000567C8FAEFEED95CB74E5F29DE47A3C8FAA -:10CB2000D9F0FD173BA5F2BDE4BB5546EFB10D1D95 -:10CB300065E276461B97474BDEEEE908A583D97D73 -:10CB4000B91E7430CB330BE955BE8729DFB95CD4ED -:10CB500097E3359905147E1E6E48423A36D63396D1 -:10CB60000F8D3874C905B8FCA4EFDB53CDC02F86F8 -:10CB70005E73A87F3AE4D3B2E26EA1FC90432FA586 -:10CB800039F15C3AE31633F0ABA1FD0E5DC2F2DD84 -:10CB900059893C3F99916A3268C7BEA9182F3BF466 -:10CBA000FAB4B56E6E4769F7BEBB4C111E784F1CC8 -:10CBB000E1816900E818D34340C7981E013A9E639B -:10CBC00061EC28D031A6C7E07C8ADF7F0BE7534CAD -:10CBD0008FC3F914D377E05C8A69039C4B31FD5D08 -:10CBE000F5744A3FA8D6A8DDEFAB8B29FDA8BA9211 -:10CBF000BE7F525D45E91FAB7DF4FD81BE8A90E3A7 -:10CC000001DD7BA31DBD2B2AFD9CD2AF5953C91A50 -:10CC100023906F349A63BEB207FD951DDB09CCECFF -:10CC2000AB107D2D5BF16CE84BE37775121F17DFBE -:10CC30005DA9DA1388E70F5327F7ECAFA21CAB7C92 -:10CC40001D436D3E34B5FF7EE422411FEBB33C9B98 -:10CC5000B1DD303BBF9F3CCCCEEF1F0F3337D4202C -:10CC60007DD57CC75C18FF733092BFFB51739FD991 -:10CC70008F7650E532DFE7C33B31CAD77CD748F720 -:10CC8000958739DD8928AF64BED5EF8F7F42E27C7E -:10CC9000A41F5EC6F78CBEDC300AF585E10EAB0B37 -:10CCA000F94868DC00FADB0F467E25E7C3703CE9F3 -:10CCB000DFDFF21D0B9872827EFC61F68654B41B96 -:10CCC0000CBFD3EE0E8D5B92FE7AE572A38A765589 -:10CCD000199F24C791F38D34437F79C1F8A361CEA6 -:10CCE000BA5CF477D4943BA8BFCEF0DD9A47F53C0C -:10CCF0002AB5ABCB45BBDCF03207C5C1CA3881CE03 -:10CD000062DD508FD639FAB2467112C3459C04F6E3 -:10CD100063E7E53EEC6778A74012C6810DAFE4EF0C -:10CD2000903DA1F0F7E865DC02D68F08D9B7384FFF -:10CD3000ECB7C7DF60BEA847793C04DFC9F25CE707 -:10CD40001279E977B48F24FBD628C16B1E4ED5BE6D -:10CD5000403AF2DA9C9F45D0FE4EEF8676D3894268 -:10CD6000AFFF27F4720ADBFDF7E9C5C3F1DD95914A -:10CD7000BDCD4837122F12CF1DD191C47B489C19CD -:10CD8000E1B9356E4CF463A4AF8EE84AD2D3303BA0 -:10CD9000C73BE215E3D4241D2997F9BB6EC3CBEC46 -:10CDA00024EF241D19E9A02D1D71BAACB9CB4EFD9D -:10CDB000B5A5A320FE111EFF3A1D35AAE8BFBA5A39 -:10CDC000FAB9A3998D8986A26969DA22C46FE165EF -:10CDD000D751CCCF6623C62049C9720DCB07B62DDB -:10CDE000D7BE69B64487D0D9304167AB3BA82FEB9B -:10CDF000C9772F64FFCF7430FE5B426F782B4CC62F -:10CE0000A9781CB9838271A34BF2397D15A4AAA419 -:10CE1000778CCAE2EF9F3307D7B35DF017F9F14D76 -:10CE20004C3B129D8AEF947AE97DD2319D0CEF93B1 -:10CE30000AFDBCC0E0E7BF29EB06D2CF6FBAC23B08 -:10CE4000D7E3B3847E9DCA52AFF21DD2295964D76D -:10CE5000FEB1EF90F2F76B478BFD9E2CE829DDA524 -:10CE6000B2A1B1F89EBB6646E17204DFAFCDC177D7 -:10CE70005E7D94BF91F9291DCB02A4478C074184A4 -:10CE8000F99B19A37BFB872326CCC43B87A3FA8F8E -:10CE9000EA81DF43DED95B90154FEFECFDC919F253 -:10CEA000CEDEA1D12EBABF7AC89E4E7A28EE574B5D -:10CEB00088BDF44D90CF3D607D87417E63FA3AC8CE -:10CEC000EF1E2047DF00F98DF99B3297316C37C692 -:10CED000A58F7B92EDC73A47C141AD63F88DCD79FF -:10CEE000A52BC2F7AD985EA3912EDE8AB96634AE4B -:10CEF000F7AD98CE269EDAAC9466BFDCA33D3D59D3 -:10CF0000EE87E07863683C237C253C8D7094F0FDCF -:10CF100017E0F9607BF05C84E708B4DFDADF8F4A62 -:10CF20004C43FF26E7B3E51129E23DD2B773D43471 -:10CF30008CF71D42F31C5E752D33A3BFDDCEE1746B -:10CF4000B29AF910BEA7710968F036D8F79879A49B -:10CF500029340EFA659BB615E9EEE44695EEEB9F93 -:10CF60007F318CEC76A7FCDC2EB9D8A43D87E56533 -:10CF7000AA6BAD1BF5CDB754FE8EE8F78753264557 -:10CF80005E05BD6EE1EF1C94D9C7B48B4F79BEAC82 -:10CF90004CF310BF6086DFA3E86AE3EF41C877294E -:10CFA0003BD2B7E4EFB874B5717E2DF1BBD12AF452 -:10CFB00000E86710F0D9E45F86D379EBB104CF21A4 -:10CFC0005C1F9C63E8FDA996AE91249F0E89B8B8BA -:10CFD000E181BEF4DE5A81F8DD8137C47BEE8744FF -:10CFE000BCDC910CED6D6CFF86EB5057B43F5CCF11 -:10CFF000B81FE846077F3FFF6ACFE71F6689F8A1A1 -:10D000001C967355BF9310AFD27D8AE12C83FCF040 -:10D01000A370BEC8E7DE9C6D463919F23B09B4AE79 -:10D02000FF6BBF93C058B38AEB4A762AECB1D4ABFE -:10D03000FFDD04559CABE4EF2714F0A236BF9BF054 -:10D040007854018FCB77CC6BF7771392C5BBD6CCD6 -:10D05000C5E586FCDD84FC44BD1C19E51C71C44992 -:10D06000A9DECE937C85F8B1F86C213FAE16FFE5C2 -:10D070008CF0DF1A67DA89C73F0DD7FAFC12EDF39F -:10D08000A33A59DC7E575B3AF877FB5D948EF064E7 -:10D09000FCBD14239E8CBF9F92AC9699E91D4881DC -:10D0A000A7E9F017F174BDF87D8BD1F8FB16EC7F82 -:10D0B0000E6FE30C78FB96AD1D88EF965E2CE47C3A -:10D0C000BD23B91F9EEA99940DFC6396B01F49FBDE -:10D0D000888CCB35FE7E92B403C8785DDF488E6FB6 -:10D0E000DF8908F25FDDAD3646A29C3961E2BF9769 -:10D0F0009411AF69D8FF1D59950AC223917977CD54 -:10D1000083F9CFFA8D2D05F3B3BAF3F7225916FF41 -:10D11000BD2039BF59C93C9EAB385BF06F378FDFFC -:10D120002ACDE676B248B793E2CC0BB398889F65D8 -:10D1300029B3B2913E8F87F542FA5BCFED818DF82E -:10D140005E65A7E07B95A8A7A35EDC4DE8A5351F2B -:10D15000DBED9C0E994EFEF7F6DB7571CE7DB73B8D -:10D1600075F9ECBA445DFD7EFB5CBAF2DC40A6AE1C -:10D17000BCFF31B72E3FB061B0AEFE351F7974F9F8 -:10D180006B1B0B74F5879CF2EAF2C9ACF95184EF82 -:10D19000E6EC34C25B7745D8495C1C1FB3EE4EA069 -:10D1A000FB4AF2FC21E3DE3541CFC6734D772BD726 -:10D1B000EB6B92183FB7DAC5F994E9CF379A885BE1 -:10D1C000977A3DF3E9E3D665BC7AEB39489C73E482 -:10D1D0007922245EDD83F397F1EAAD7817EF871AA1 -:10D1E000E9F5856CE15733ACA3BB95DFAFABB9C7AD -:10D1F0004AF784E4FC8CF33A2EE298B7DADB7F0F2F -:10D200006A7F36B7AB44F6F0EE417A7D12D815C18D -:10D21000B3CD78EE46FCFD819A7BADEEE5AE2B8F6B -:10D2200037AB1F5FCF4C7C37378BDE5FA57B8172BE -:10D23000DCB7057DEFE9A7B4BBBE59D13C3E8E45B6 -:10D240005BE95E4BC7E371B8265AD90A7AB74ADC64 -:10D25000F3B87D6DDD035834D35A6BE10F0FF82D11 -:10D2600068471B3712F4C45CC0C3334B1E72805E28 -:10D27000F4649599EC621F3C7FEE16D0305BEFEDC5 -:10D280007487731AD2C938C43FF47B533F1E9FFE84 -:10D290006D365F5FBEFA7DEB7D0B9B8EFF33E2FF49 -:10D2A000EDD01DD1A35CC7FFD6FD0B49BF4638C9E1 -:10D2B00073391372AD879897849FDC17127EF2FE44 -:10D2C0008B6B91C5BBD941F7680A302E4FE2EFF660 -:10D2D0007E9C2E7BE57078603DE4471DD5CB57B32F -:10D2E000A2D15FD0C25CD1CE2BD8CDFF97EEA510D6 -:10D2F000FC3BBA4FD7119F68C31F3AB85FD7117D67 -:10D30000D29FABB86717C22778BC94C087BF878904 -:10D31000E2125647EAF7F1B41C2E17FE2EE5850FF0 -:10D32000CEE77A3EC1D0FF51B352157C625EEBEF7F -:10D330008DE0F7B92B2DA47733E67D18E334FEBCDE -:10D34000DE42EF3C0EF730D26F8A362AFE4D4AF0AD -:10D3500077BE0A7D86775AD4EF493FFC76ADE2C4AA -:10D36000DF8B98BD465F3EDFC17FA764AEF1BD1A7B -:10D37000E98FBBC2B9BE2047E8E56EE626BD4CC4C6 -:10D3800051148B3A46BDACC5CFFD8D782E57B91DD3 -:10D390008BE2EFA4DC77A1BF2BE41D16806B78260F -:10D3A000CAF115E676E3225BE1DA41DCC73987880A -:10D3B000FB70F0389796DD61DC3F2CFD70A2FE39E2 -:10D3C000DF252AC7FAD8DBF95C1EBF22FD6F46FFB6 -:10D3D0005E8BC344FEA996DD9114E7807EAF68A002 -:10D3E0008733A65D09835383F3D31A559DDFC8980D -:10D3F0006ACBF6D079F2E11EDAE21C8C6F37BBED16 -:10D400006EC8DFE73844EF788D137630E37C5B7FBE -:10D41000F76F287F57A7C5C7F5DD9602FEDE09F036 -:10D420004786FB49C6734C64A0DD415A18B896E69E -:10D4300073B5FEAFC99773B9FFF7F2106AAFADB914 -:10D4400096F2DD573CB008EF194DAD996FC1508091 -:10D45000C64797E68743D3C66EFEE5E188B7114A13 -:10D46000BBFE8B0773B85C6934DC5B90A9DA8FEF85 -:10D470001B573FC9CF453CD73285F6C36285C9F8F3 -:10D480002EE2E7327FA956E4F3797EC94A9E6F14F3 -:10D49000BFABB04DD85B70DD98E2BAD12EB043D8A7 -:10D4A0006370DD98E2BAF13BF22FCC23FFC23CF26D -:10D4B0002FCC23FFC214F9177E2F62DE945C95FBFC -:10D4C000ED4687EC0FF4DB8D0ED18FD06F179A47A6 -:10D4D000BF5D687DF4DB8596A3DF2EB41CFD76A1CD -:10D4E00079F4DB85D647BF5D689E0DBE3198477ED7 -:10D4F000E799A8CB4F06FD7F74C8FE46BF5D68FF65 -:10D50000E8B7D3F5A72DD2B5BF8D55E9DAA3DF2E45 -:10D51000B4FE1D558ACEAF7787788776F68638A217 -:10D520001F5FAAB701E9FE4F11FFB8CB82E745B5EF -:10D530007E013FB785BB399E6B0B38DE4DFC9E8567 -:10D54000D23C83F0BCD4CAF3F93CCEDB483FE817A9 -:10D550001B6DE17E314CD12F8629FAC53045BFD8ED -:10D56000E89EDC2F8629FAC5F03BFAC53045BF1886 -:10D57000A6E817C314FD6298A25F0C53F48B613BBD -:10D58000F48B618A7E31FC8E7E314CD12F86DF4F49 -:10D59000A07FCE129C17EAF33D74E74AA043DDB9A1 -:10D5A000D2A9CBA33E1F5A1FF5F9D072D4E743CBC3 -:10D5B000519F0FCDA33E1F5A1FF5F9D07C748E8B5F -:10D5C000F621EAF5A1ED50AF0FCD67D7FA5E47DB44 -:10D5D000D9F88D178E60DA18A93CA900CB8879613B -:10D5E000C534F45F3686292931C0392DCAFDD346AA -:10D5F0002701998838CA1CD66CA2DFEBC3C323C6A7 -:10D60000390418C5AD667F9744E569F2FE1DFE0139 -:10D61000BCE7EE66F47B34D2BF2EDBBB9953C55416 -:10D62000D60FE6DBAF671C5FD623FE19320FBC694D -:10D630008DF13EB94B1D791837BB4DFC5EEEB6E55A -:10D640003CDEDA4857F9425FDA66DA7508EFD33420 -:10D65000172A74EF3AC3CC8E59F2104E9579A84729 -:10D6600064F78B11EBAABC0E7F774CCE5BDA41815D -:10D670004FD0FDC4A1CD0DA3A2A11FCD37827E1F27 -:10D68000679C95EB0FD80ECF957D7D8A6773087DDB -:10D690005F23F471CDC7C77FE6A909BC5D386FF77A -:10D6A000CC535104C7092B148A3B1BBA8379F01E53 -:10D6B000B447CCBBEF8E808AE315AEE0E3C97E0BA6 -:10D6C00037A6D0BDD042D6381AEFB5B0010A43BE56 -:10D6D0002DE106EB3B82EBCB80AD8276EC1F7B9F8E -:10D6E0006AD880987C8C4764F58CDE151D3FE03D40 -:10D6F000DD7A09ED83A85F926BBD7C0ABDE33CC176 -:10D70000B76C39826FBC6FD1EBF1587F0B73A7BA3E -:10D710004814D1FD63399F3E9E5D26108B2C8B35BE -:10D7200098C214C4373B1C17423FB0F3A720BE7306 -:10D73000DD167A5779A2D969A1773A3A88D7B9E440 -:10D7400090F13A067DC1109753B3F4A314B4372F68 -:10D750008E3491DD64F19E08D21BB40D0AF135A917 -:10D7600007158A78BF4B2B5E8F9F8670DF65A1FE01 -:10D7700064BC4E79BA3FC584F713BA6CCA8955495F -:10D780000F58D20FF500DF4BB70CC67A2BF9BBA2AE -:10D790009756ECE1BF4B2AFC3BF2774EE788F8AF97 -:10D7A000C26C6F34C6C3C8DF5393F764E4EF984A82 -:10D7B0003B4FE1DBFD8F227E0B9F10EF7EAF29A454 -:10D7C000FBEFC6B8AB52A1FF2D5861A1B8AD05065D -:10D7D000FDB054C4655DE9F74DD7F633E887F277BD -:10D7E00072441DA676FD3DDA85E5BDCF9916CE07BC -:10D7F00066EE62E4AF9AB96C9409DFAB667B38FDE4 -:10D80000CC5CC6F59C99AF78E8FEA6D41BDF15FA70 -:10D81000CCA4CBC904FFF785FE3215E35501CEE356 -:10D820001AC3441C5B12A5D32EF3F8D5490ECE0FB4 -:10D830001AF7F377375A7C36AE571D61FCDD380393 -:10D840007D4E34FB4D78A1D13D14E813F2E3511F16 -:10D8500082FEA6A37E1487F49E9A4FF190050ADDFE -:10D860002332D2FB384BE5EB186F3B6E2B73FB5822 -:10D8700028BD031D637F3E85DE63D0C43957D2B116 -:10D8800091EE674508FB9483DB9F5AED14A8ABD259 -:10D8900023EA7F9A86F1C4B3D066D88596E1C1B8F1 -:10D8A000BDC82C5E7EB4DF9FA6ADC0BB1F1DD82DAA -:10D8B000D49F58091E9A7C77A2033B02DA0F905F2F -:10D8C000DE7E67AEB528845F3E9C3BF22BF7C0201E -:10D8D000BE8B0CF72917DFD7937EFFA823BD7836C0 -:10D8E000C015F7C7ACE8C6BB8052D99FFB31CFE863 -:10D8F000C1F8FB92727D2C80F198B78A7C6C9DED0B -:10D90000A3350E820BE59BFA9D9F867134E5F6C622 -:10D9100031487615599505189F1DE4539A273915F6 -:10D92000F9546E007F8FEFB8944306FB44AC9BD74D -:10D9300037DA29666771FECDC47BE39FDFF7F24ECD -:10D94000945B72FE9F5BF4F76A651AEE16F2A3FA17 -:10D950007FE65E89F13EC9AF92B5BFF783FE1F3601 -:10D96000F1F713BAA8B54CD88BC8AF2CF90613EF52 -:10D970008E04F1EEA1F78DFF0B290E70D50080000B -:10D98000000000001F8B080000000000000BED7D70 -:10D990000B7854D5B5F03E73E69564122621210F1D -:10D9A00048980402A94698BC20BC0F9147B068076C -:10D9B00092286812268447B068236A0D2D2D139291 -:10D9C0006040F0068D82D4C780CA45A51A955B4198 -:10D9D000693B48B56A513148F5D6DE303C7DB535F6 -:10D9E000E2F5AAFFE76DEF5A6BEF9D99733213F0E2 -:10D9F000D1FFEF7FBF8E9FDF669FBDCF7EACBDDEC8 -:10DA00006BED93960D8A735D36635E87F5849200A5 -:10DA100065BB12B08D618CF9666AC13C46BFBFE53B -:10DA2000307678B48BB114A8E4F5DEF3703263B5C8 -:10DA30006BAD6C233C7A6014D318D41FF891D5EFEA -:10DA40008371AAAD475EB04399E4E6FDDF69BAC3CE -:10DA5000C24C384A20D705FDAE6E8C716F84F6BB80 -:10DA60000B3C896E688FCB775BBD0EC6CEBA19F5BD -:10DA70009F91E249C6E7D76D3A78FF5BF0E8070768 -:10DA8000B2ADDE7CC6EAF615AC4F73E17BDE74778F -:10DA900009D41D4EAB07DEBBBE35D1EA82B2369546 -:10DAA0003576E5E33CBD59F3E361CDF89BC658817B -:10DAB0005B610CFA7F50C0A8FCC8C216F07E1D96B0 -:10DAC00079BA7E266A671D5B35FB108003DF3ACB8F -:10DAD00034339FA990B1E1562FD360FD2DE9CC8D51 -:10DAE000F01A0ACF6D85BC3D2629043F23DCAC8C9F -:10DAF0006926681F0AA5B53004C74C6857E1B925E7 -:10DB0000EFE442968370638B703F723DB25C2CD61B -:10DB1000CF16D84D0CD6B5D40EFF862166AAF9B320 -:10DB2000528B195BB54571DAE0D11287EBAA095027 -:10DB30005FF29285AD83FADC2497351DEABD70BE95 -:10DB40003BA1BEF8A602AB0BF65D8D6701EB58B2A8 -:10DB50006D02730D86D20F6551FF796579CD9643BD -:10DB600099FB5D787C9AD503F05AE2D4AC49F9A1CF -:10DB7000F6FA0E45F33BFAD7E7BB55DA67351C29B1 -:10DB8000C2AFE6A66CEB6207D65FB2ACCAC77DB97E -:10DB9000685FF23DE817C07E7373D88B0CD70DFB1E -:10DBA000DA99CDE72B0C1B7F318E1F363FF45FE4F3 -:10DBB000C17DB9E369BE3A27EC3B1B4B27AD13E0AF -:10DBC0004070EADD0CE3B9681E3A8FFA80DFE2C6E6 -:10DBD000F598615EA85FEDF45B709EC5AD055606D5 -:10DBE000A577139FC7DB9E68BD04EA7566A735134A -:10DBF000E789055824D3FAFC3BE16896005C921C47 -:10DC0000380F5B34DFD11F3E7562BD4B3A12AD4B0E -:10DC100075CFB758F03C16C27ABA229CFBED78EE6D -:10DC200029B89EE95686EF9B35AB1BD723E07BE6F0 -:10DC300086988D6C10BCDFB9D5920DF59F22FEA69B -:10DC4000E07B1CBFE6E6047215DCF70D316E5CE785 -:10DC5000426707EDAF0FBE77013CE0F952A787E0BE -:10DC60000B78E1630087259DFAF30CAD87C37749F4 -:10DC7000671DD1DB32B3D7EA0C5FC7B683B90AC0E0 -:10DC80006521D0B702F0674E6F16E2CBD9BBAECAA2 -:10DC9000A27DC23A11AEF16ED7ACB462C213C263B8 -:10DCA000892FB5459C7EE57CBBDC669A6F97D8577B -:10DCB00074BAD45E4C43BA84F35DE78A4E97560635 -:10DCC000E3C1BCD6258ABF45E94FA7923E255D4AF0 -:10DCD0003A95F47BBFC5134853427CA676106B7C03 -:10DCE0002A029CCE0A3E72B5385780EB6F10AEB256 -:10DCF000FD7571AED5397A7AC7F170DCE7647B596E -:10DD000020F786FC507F396F75127F0FF11EF1ED01 -:10DD100039011FECBF8AFA0B78097E51DFC72FF655 -:10DD2000B40D417EF1A4E2467EB16AF3A1CC5B0062 -:10DD30006EAB7E1E879C977DB8F2E1EBD3010ECCD3 -:10DD4000ECA77393EB5AFA7901F189659F4FE2FCD6 -:10DD50002210995FB8F2BC87916FCBFA923B7F3E5D -:10DD6000CACBF94D00F9CD1F7FFEDCB189C84798B9 -:10DD7000DFE2B924B49FC5ED6F58EA1CE1F0E3FC83 -:10DD80006E63DEB93A3CAF7A87D5A5C2A3FAD63A1C -:10DD9000E2BF2C8DB97395D0F91BF1A2AE55D1E835 -:10DDA000BDA6717EF55BE4D3F59BE6319453F2DCBE -:10DDB0006062C6C6C13E1987AF5CFF4762FDE704DB -:10DDC0007FBB5AE0F7D50DD3ADE9C9B8DFBA22E081 -:10DDD0008C6CA178BE7089FE79DFB939FBF8FC7ACA -:10DDE000A497735DFCDCCE6DB210FF39B727DECF90 -:10DDF000607F1FAE7AE6B52BA1DF0777EFC862AA76 -:10DE0000FEDC58113F372C97C3B9B1C111CF4D2D4E -:10DE100008E3C3CB1FE0E756FFF8ABFFF1AC8BF68E -:10DE2000CBF9DD669B1FF9F1E2AE27E91C17B66F4F -:10DE3000B16443BFC105D93A3E5EDF58E06400DFFC -:10DE4000ABDB7758904F0C2EE07034D203941A0B52 -:10DE5000A333944B4A12E25F301DF14FF647FEF8B0 -:10DE600024CC73D30D31096C6C689EC9059CCEEA35 -:10DE70001B139370BEFAC6BADBD998903C30EEF310 -:10DE8000540CA797C5301ED2EDA9E9EEAC55849F7E -:10DE9000A68872B7A8809FE3CF00DC31800F43E3F0 -:10DEA000BA1E41380CFD41AC1BF9C7C891413FCEA9 -:10DEB0008BF88DEBB602FFB443BF912B831FE33A7F -:10DEC000460286E17B58C62751C986407D272CBB78 -:10DED00014CA1C95970B0B389E407B00DB5972B01F -:10DEE00004F72FF1DB88BF56F6507B0EF2B164E6E3 -:10DEF0006E7185F0558E23F155E273B4FDCD2BE0A4 -:10DF00007CE57CFB3B95CDE1698D85FD257D85FD1F -:10DF100001B2962685F625D7C7F2605DA83FFEF8C8 -:10DF2000921D1B619E53CDEEAC46C740FBED9C3964 -:10DF300024C27E8DFB9474B3C4CE691AE866501077 -:10DF4000D67DAE63C420943BA714906FF0DEA91B6E -:10DF5000624CB87EB9AF5D6BA133AC75F75A3B9597 -:10DF60008FAE05C21BCDD89EB569547F7CAD8BCAE0 -:10DF7000AEB579F4FCE68224BE0F168C473D13F44F -:10DF800001CE0F029C4E7A9A46D0BEE473A917F4D4 -:10DF90003883F14961FCFB74A3909B2CB819E99B71 -:10DFA000358D600FC3543D1DA7E24DF9889F7C7DE0 -:10DFB000F2BD9B2CBDC40F59BCD5F530905CDC4D37 -:10DFC0006FCC4C85F99676661728F05E4D53514F0D -:10DFD00013B4D7B4A6BA916F2C75B8D6A35C5CEA1B -:10DFE000CB76A35C8CEB2C38BB0DDA97B65EECC617 -:10DFF000FE3729CC83F405FC9321DC96B1BE9F66E5 -:10E0000007BEB65CF0B5E5C82F015ECB9A0E8D74E5 -:10E01000C2FBCBDC310528DF976FE376C25C136B64 -:10E0200057500EB77866211FEBBD4771A3BEC9EEEE -:10E0300005FE6A0FF1577F9EA7A300E5D297807F68 -:10E0400030FE45288355DC579786FB60A08F3CCC7B -:10E0500070DD1ED2EB07097CE9E93C11EFCAE7F05D -:10E06000467D9D793513F2DD5542AE0DB7F69EB86B -:10E0700015F59978937B27E797AFBB709F2FABCCB3 -:10E0800046F246F417FC74F84F4BEDC8DF56C5E76F -:10E09000A4925EB54D25FE28F1A741AC79E98E8AA0 -:10E0A0002188374BA11DE5DD767C082C747DE7A522 -:10E0B0004310AF966C9979B70FE4589680E3697373 -:10E0C000701E9ECF7B3B52939A512FBCAE6514833A -:10E0D000F6253B6ECDC2F2BD1D310B90DFCF70CE69 -:10E0E0009B9108FB5D766F62811A26377E2DE8F1E1 -:10E0F000DAEB2E4D457B60E55F0FDDEF1C01F3038E -:10E10000AC11EE9F76C5F97DD065E5DA7D592AD050 -:10E11000D85F6DDE67916F7FDF74E0CA09C8FF15B5 -:10E12000FFAE74EAEF4A7546A0F73EF90AF8EE0230 -:10E130007CBEEEA76FD3387F361DBE6221BCBFF216 -:10E14000BAA713709CEFDF75749C139EDF3DD2FB62 -:10E15000229ED707CA8E5D4E144CDB768C41B9FDEA -:10E160005B6147CD4DF25CB910E1FEB24A708F366B -:10E170005FC33E85E02BEB35FE41A4CF7A03CCEAAA -:10E18000C4D2C9485F7E4F654DA80F48BD463EFFCB -:10E190008380CB7B833AB2102F56ECDA9A8572E5F6 -:10E1A000FD785EAFDE75D52BC8A7BC0FD9B8DE6E83 -:10E1B00066A427D7FBB8DECD1A805ED343F39F2E2B -:10E1C00088A3F5AFD856A4938780A1F4FC7D332BA8 -:10E1D000C7750C6FE92D40FDEB1D7360299EEB3B6D -:10E1E000A0D7A27DFB6B21CFDEE95067E1731F1042 -:10E1F00012EA23EF743C1D3FD211D2E3E28BBB0243 -:10E20000C8E7AEDB9B58A8729422FCBADE29F993CA -:10E2100063D6D064D2C79C88A7ABF6BF308BF13AE7 -:10E2200008C2E8F0BC56E8617DF5BD4F925DB7725B -:10E230000FD72756763DF962068C73FD3EA14F0835 -:10E240003DE53A41CFD7EFE570B96EEF096B7DB888 -:10E250003D9297B47E286882B6C2410BEE72A1BD92 -:10E260000D8B9808F8DD655AD80C4C3CCBEDE47A60 -:10E27000A5B997F4C38D79DD64975FD72AC6CBEB38 -:10E280005E9F43FB9D37385C1FB2175A08AEF27D84 -:10E290008007BDF7594CC218E47F81EB62DB51AEB9 -:10E2A0006BD73BCC58B65CE720397F6FA329CF0CE6 -:10E2B000F0D5945837EA714D76DEFF96D8849D5894 -:10E2C0001E88E5F5CF62B2484E7D66F23CB90CFA85 -:10E2D000DDA21E896123F0C87B0F99A03E2AC53BB1 -:10E2E000BC10E64F65403D2ACA8F8082ED1FFDF2CB -:10E2F000DD225CC7D4E1C14F182CCDA2242E9C0195 -:10E300007832BAD0C9F97B7EB008F13DE579CEAF5D -:10E31000EFB3B0769477CCEC61F3E17900F9179E16 -:10E32000FF17263FF2E3034AE0C170FDABBA90EB62 -:10E330000F1E9BA35D81752ECFF6BA711DDF532C86 -:10E3400097A0EAC25C6A2E8EFF9185B74B3DB64C12 -:10E3500030E14C618F5933D21CB8BF16012F45D321 -:10E360005813AC635DFEF3F5882FB7F5DA990DE627 -:10E370002FEB8D25BD3633A39CE45B8B808BE24A6B -:10E380004699C39ECF37F96CB0DEDB98DD8FFD99DF -:10E39000DDA0FF9A62347C4F39F0DB2F90DF0F5500 -:10E3A0003F3E3408FA0FBD4571B7409FDA7367EFFF -:10E3B0007B9DA1FDEC2F40F82D4DF15E5608E7D96D -:10E3C00073AEFC8417CEFB366797DD9DCFC70BDF9E -:10E3D000C781D55F24249942EBFBA8F7ECCF9F2996 -:10E3E000C6D24E72A8EC80CAFD4D86F57C94E6320A -:10E3F000D339F5DA0326ECEF30F91505FB1F7A1B4C -:10E40000D75766770454D4E3ED963F85CB1976242D -:10E4100033F1ECC5245AD8DF405918D2C2CF6FEA85 -:10E4200020BD7DF98342AE3FFE409C9384AF841BA8 -:10E4300073692C5CCEFCCAB1AB86FBB1381DFF40C2 -:10E440003C3FF7790EE917E70E809E1141EF94E506 -:10E4500051D433407F08E468B7149684E46C9594F3 -:10E46000BA420EAB62DC2A01AF2A8789C3A7D20069 -:10E470001F813746BC309EBB3C4FF6A3232F0CCAEE -:10E48000A673BCE45F189DDF3A5C47CF1787DB803B -:10E49000DC5886AA9DF066FF239E5F206634EA154D -:10E4A000779948AF40BD0FF544C93FBCC807C6D2F5 -:10E4B00073AE07E631E21BB56A2CF9198D7C43F285 -:10E4C0000B6F2C9463906F74103FB845ED7DC1A421 -:10E4D00084F8C4F0F2E02528877BC0F4C7F6A0A931 -:10E4E0008B9EBF549843F8328C1D49C7E760AF94A8 -:10E4F000A01EA8DA1FBCEF348894CE0D9C3E5A2C87 -:10E50000FE7B96217FA872B851AFFBC86FF25960AD -:10E510009D9D899C6F74AEC82079FE11137C648127 -:10E5200095F8C82493C947F6D6C20CB2B7FAFAE7F1 -:10E53000BAC8BFFA8BBFAAA3B661FB3C3BC9DD4E8C -:10E5400094C750EFDC7C09B53F27F9D20ACE973A41 -:10E55000E769E9B1D83E6F8809E7DB9EEC7D1ECF05 -:10E560003D43F53F1283FAE4F763D9C3F0BC335B54 -:10E570004B47797BB7E259B814DFBF84AF3BB83063 -:10E58000F6F15DFC7802E84FEA698ADFB9314C3E6A -:10E590001D1ECDF9FA70DF897B105EBE329687FAB8 -:10E5A0007C0FE2E7D8D0798155CE9A9242E7966CFB -:10E5B000383789AF3E0B9C5F323FBF754AF4F34B4F -:10E5C00016E7A734017E13FFE7E7738BCAF93BFB1D -:10E5D0001518E0507E9CE20DE27E5B6E8073218117 -:10E5E00018BC19E175DFEA780DF7D163620D5D1192 -:10E5F000E8F643C11F184A63A08745821E1649BC2E -:10E600005D63C0DBE0B0C4B371026FE1FDE7E23CE3 -:10E610007FC679FFAC1C1D870F0FFFB7BA20D23C15 -:10E62000FF25F8CF41BBF7D34292AF653A7DF57035 -:10E63000C1BB9928A7D8978786A1DC7D2AD9F33951 -:10E640008E1B33B297FCE63DE9BD16DC67CFC20FE7 -:10E6500032512F5AD4F45BA2AF0B5DE7BAB85A0B14 -:10E660008E9358996D0942995A99FD02E2CFB139BA -:10E6700036972D821E7270CEE84CD47FBBAB4667B6 -:10E6800022DFEB86033C82EB33BBE291FFB17D35A9 -:10E69000C4C7AA041FEBAE1CC19F0BBE19F67C7346 -:10E6A00031EAB50E933B5C5F3096EF03DF0C00DF81 -:10E6B0007C17EC332CCF807D1600FDF514D86758FD -:10E6C0003F01F61996C7C13EC3B27BAD9BDA5B2A08 -:10E6D00047EC0BC2397FDAAED0F8E8BF8DA4175FE4 -:10E6E000FB90CA02123EF07FC3BD712C9017AA2F77 -:10E6F000EB1CACAB2FD93454575FDC3A4257977AB6 -:10E70000A477CDC5BA712BCA8B74FDD6C58DB1E087 -:10E71000B926961770B8971710DCBB2F8F02F7CB6E -:10E72000C713DC8FCE199F89F03C8A7047FBCDEC74 -:10E730008EC77390709F2FE63C5A5EC49F0BB887BC -:10E740009E570C28A73E4478DB10EE762ADF4578EA -:10E7500013DC39BC4F21BC6D08F73C2A8F23BC4722 -:10E76000E3B800EFE2F3C37BE51E5507876B1FD2CA -:10E77000C3BBE1DEC106F80FD5C171C9A611BABA93 -:10E7800084F7E2563DBCBD6B8A0CFD18DB0470A813 -:10E79000C07F001D1C2D994D7129B39DF9E280AFFA -:10E7A0002422BDC1FACD950AD78FE0D70174381F56 -:10E7B000FF01F46576F0F6D6858A1FF912EA4468FF -:10E7C00057005C0371406715CE5167902F5D851C23 -:10E7D0004C45BBDE4FE5352C40F459C382545FC431 -:10E7E0007AB3AC505EAF06D6A3FFEE55BBF7C62298 -:10E7F000A0FBFF9AF3468F8244E9AE1B8D74CE1CBA -:10E8000049646F463B27E0945C1FC7AEE3C4BEE09B -:10E810005789FC1FDEEB8E1B73F3CD700E1FD505E1 -:10E82000C7E1FC2BEDDE07924D345F7311F2258BAF -:10E8300077F46078FE6AC9F84CA47FE649D1D949DB -:10E84000D1E6DB829B0538D495039C148CC371B848 -:10E850009CAEE27039B8C566457FC6E90D16F25721 -:10E860006E8DCBCA42BC3DDD363B0BF1AE79CBE8B9 -:10E870002CC4F7F9EDB3DF47FE3D539D5B8BEF9F53 -:10E88000ECE078CFD80DA477DD2CCEEEA48BB903C5 -:10E89000D05E3527DEED83FD787DD909B45EA639DB -:10E8A0000AA05FBDD8777DC7F2B9389EDCFFE24D84 -:10E8B00036DDF97FAF545FAF62D6109E65E3395BFA -:10E8C00043ED78FE6AF520EF007674D31F77BCF233 -:10E8D0009BB0F11E2B8A4F46BECAC6B3F17F53438D -:10E8E000EF4783EB676BFDAFFC26370457894FEB8F -:10E8F0008B3C7B111FE031C5DB8096481E5CDFE757 -:10E90000D73A9080F0DB12F7ABDB27215CDEE47EA8 -:10E910008EAD71B5C43F3E44BE9D8D7CFAAACC60DD -:10E92000185F90EF07053F3DF6F3AB888F1CAA4AAE -:10E93000A5784CF75EEE5F3E2EE8BEBBF2AA9A9B2E -:10E94000817F76EF5149CFEBDEF7C90BE8A7E9EEFF -:10E9500052DC02E4A6F071BBF7013F477EEBB150F9 -:10E96000FBC13D4FD33ABF2D7E5EB95FF0F36D7CA6 -:10E97000FEA5660FF117E65DA0DBDFDF8BAF9F8F93 -:10E980009F1FB3703CED3EA692BF8DF9B42379432F -:10E99000C2F0B39CE36773958D71F9CAF9CCFC4A58 -:10E9A000A003D4F399AB046DCA0FF755A490BCDC57 -:10E9B000643989FAB413FE43B96D846315339F0C2F -:10E9C00086E1EFCABDD03F6C7DF3B13D0C9F8DF861 -:10E9D000AA1403BE5E1CC2D74FD99759D61CDE7E3F -:10E9E000644888EFE12F9CBF48BE25F117F8562DEB -:10E9F000F235E02B8E62C0DB1F1666FF32A884F171 -:10EA0000950BE4635BE2FE4A72706BDC5F098F8FEB -:10EA100056093C063D039F775FCEF50DE65F40F457 -:10EA2000B048EA11164F3CFA498FAD199C80ED278A -:10EA30005A2B88EE243D19E73B2EF04FF65B64EE2F -:10EA4000B5B823C843EF1A3DFEB0DD0B08DF6F36C3 -:10EA5000E059B4F18DFDE53C8B0CF15EE33C938B0A -:10EA600085DED9557341F32119F6BD4FFA6D6C0857 -:10EA70002F55E4039FC50749FF5AA0D3CB8E978F2C -:10EA800027BDEC68E52711F5B3E3959FBC3A1EE975 -:10EA9000ADDC22E8BD81DEAF10EDC675BC2BF4867F -:10EAA00033827F9C12742DDBD51D6D43AE46BC5F57 -:10EAB000A3BA915F1D9B5B4478FE9EBF8AE63F5ED2 -:10EAC000A992BFA976EF77AE467F935C8F9CAFE2A9 -:10EAD000F24FE2D19FF629C00BFD631516774A2449 -:10EAE000FDC2088F68E34AFC017DF618EEF328F2B8 -:10EAF000516CF5EAE17414DF87F6F93B548AB719D3 -:10EB0000E17468CE68E24BC7770BFE0970453DBCE7 -:10EB1000E15EFDB92EEB8C33F09BC1BAF6F9555C82 -:10EB20002F93FC5AAEEFE89A1129CC71E1E72DC77B -:10EB3000B9507CB956BC8F62F36F247F9374E38124 -:10EB4000A568982FC7D07E91A1BD505FBF403C3EC5 -:10EB500021F047CA9F1331EE9A4871BCE397D91A46 -:10EB6000C2F313FEB598FB87FFB558C4BDBFA2DC46 -:10EB7000DE69E083E77B5FF2BDA622CF23C8EF58B2 -:10EB8000A082E2D917CAE7C2E4FC93C548E741C5B1 -:10EB90008AEF4BBDEADA722E17B6C63D4E791A7F60 -:10EBA0006EE67AD1C1661BE1E15F2EE7ED7FF9B732 -:10EBB00077499F3AB47F6B42B89C9778F9FEBED9EB -:10EBC00009E8173E5DF96042B81D20DB3FA87CF0E4 -:10EBD000F68944DFAA7BA073F9BAF64077A5B0079F -:10EBE00084BEF07D73D7FF157BC06807CC54EF4D12 -:10EBF00040FE67B407DE7769094E828FA03B21573C -:10EC0000AE15F0F98B454BA038DDEE222E570CF8EF -:10EC100029E17056C26153C580787346C805595FB3 -:10EC20006A66040FAF9D91BECC3A1537C6BF304D12 -:10EC3000A514CEE54865C183E8BF92FD7F54C2F3B9 -:10EC4000A9E43CC7EE53BAD0BFF2DBD68A9A9B3117 -:10EC5000DF616E1CF155D97F996F60F9756C73E2B5 -:10EC600015388F779BEAC6475EDF8994F0F54B3DF8 -:10EC7000CDF8DE0A73C705D9D15EDF8E04B46F8389 -:10EC8000629DC1833156577CFFF7305E83FB5F3155 -:10EC9000577537C3FA576CE2EBAAF2A9EE1CA8FF2E -:10ECA000B6E3C12B900E4E35594CDC3E70EAF0FCB9 -:10ECB0007047D16BD8FF7439972B272A2F4DC03C52 -:10ECC00038DF368B3BD7D57FBED108478CF3ECB30A -:10ECD00099D07FFA7E938505C87FE1217BF9D8A67C -:10ECE0001154BE8FF0E3F6359D7F5109F7739DEA0D -:10ECF000A81FC2E9C945EB90F87262B75AEE8FC0FF -:10ED0000AF8AC47C67BE7C82F0EDC5DD15248F4FD1 -:10ED100055F279CEAC7127203C7FB749253A3EEDBC -:10ED2000E3E31FDC7F6BC244D8C7FB957C5FEFEF4A -:10ED3000BBE5B509B0CF60A594C75C4EC9FC9EE0A9 -:10ED4000A61114EFFD732BB7BF25BDCB78F8A5AB8B -:10ED50008F25D0FB52CEED59A05B7FF7EE53648731 -:10ED6000BDBF0966E372CE5180F986FC75B66CAE04 -:10ED7000FE7CE757C6E9EA8BDAF5F2AC793FE75754 -:10ED8000463D77E926D083D12F65B0F3EA9B8B12FD -:10ED90004A917E510FC63C93872B5E48C57D74D542 -:10EDA00050BF4A1137ABEFB4E9F84155ABDEAE5B6B -:10EDB0006CB0E3FAD975067924E1745D14F924F591 -:10EDC000B96E61AF1CB7786A22E553AC2EE17ADBED -:10EDD00022A0DF348C1331AD6A9280F746848FB560 -:10EDE000F7D35CD0A7BB55F714D4ABFBD181410F4F -:10EDF000AC28D7C397B97DAC54FA235CA4DF9F45F8 -:10EE0000FDBF7DB090DB3E9043F12897B41F97A0E3 -:10EE10005CBA50FFC105EBE7B5423FAFD5E9E7DD8E -:10EE2000D825ECFD835557919FEAD8E55791BE7ED2 -:10EE3000ACCF4FE5D1F9A9A45E776C6E854EFF0C7F -:10EE40007B3E880DC04FA3E99B27901F139FE6725E -:10EE500069BDB0235B851D796CAEB0239319D19148 -:10EE6000D9ACB148FCECABEA6F8B5BF572C9BB4621 -:10EE70006F3F3E33DDFB5409E0872DED22DD738BC0 -:10EE8000B350EF3F34E0E750C6FDE7B7A22F00E0F4 -:10EE9000DE52C5F34EF139E6BF48B9C4A03FF28B4C -:10EEA000AA4D17F937F2769F5A88E9720C553AEA5B -:10EEB0006FE6754DE1759F43B4AB22EFCD02F513BC -:10EEC000D9EE05A877615E4F5C126F4714190A7876 -:10EED0009D9014927FE8D78FE1A1755F02BC37AC9B -:10EEE00032FB3748D798EF330AEAC74AB2096FD2E4 -:10EEF000D0A55F48E30730AF27D8328DFCCD15F69B -:10EF0000041E9F073B7A60FC6BE6F650F9609A6C32 -:10EF10009899AF272A3E8B7EE7C3E7303DEC24D19A -:10EF20000B3391BF654BDC180BE2EF7C872713E1B5 -:10EF300000F84EF2B5FB9756E2C307ABB81FB67B9D -:10EF4000CEF8FB6E82E7639E70902FBD7BA9F483A1 -:10EF5000F7C687E3EDF135A74CC8977FBF8FB9316E -:10EF60008FF1F89EEA175E81710EADA9DF5C8274A5 -:10EF7000745825BBC1E8BF9DFEC464B2BFAEBC5C83 -:10EF8000A5FCEEA3E52A43B9767453ACCE0E09F97D -:10EF90007555C28F4F0F98A91D4D9D3CCCBF42FFA8 -:10EFA00026E66995F3737956F0B32E718E8F083D7E -:10EFB0006697A09B4E41377708BAD960F4EFDECB55 -:10EFC000E9E6E83E301C40AEBF3EB7BE8CFCD6DB67 -:10EFD00018C5A1B3E7A81B8B617F17DBDC1684DFA4 -:10EFE000F4B9051C9E958A09E33715E50516A4F7C3 -:10EFF0008B07BB2CC8472BCAE7517D466536D9F92C -:10F0000007D7807C447B3FDE9D89743972AE2D60CA -:10F010004A40BBB188F8C4A4F74C3A7A2908C4EA3C -:10F02000E8EEA2879274EDA3B765E8EA299E1C5D1D -:10F03000FFC1E57A7A8C1D59A8E7BB8CEB8512CE0F -:10F0400033D5C9E4E73A1E92A3D42EF511E9AF9364 -:10F05000FD015A3ABED62EE4C818A8633EDD86CA22 -:10F06000163BE64D7CDA6576F3F1AB493FB067EFCE -:10F07000B5239D606815F3ABDAA5FE29FCF74C6358 -:10F0800086756D6218673D5ECE089F62463205F553 -:10F09000AF4E71DE778A7981AF4EB7909F8E9FE336 -:10F0A000E0B91EEAC73C7AFB200DE9AC10F184BF41 -:10F0B000FF88787F97C097E3E50FAE8B457C58C0FB -:10F0C00048DF98A9AE5C87F1C4E37319D14957E0D2 -:10F0D000F9585C3F8E83F981CF461BA7F2E977AEE2 -:10F0E000C7F5ECB6D238150FB1A98827177DEFC444 -:10F0F00007AF21F8B6390FC5B0FE7278CC439A1B22 -:10F100008193F71E0B58A80C68C87FF2DE3BA26102 -:10F110003CF0A2BFECFEE07186F372B9D02EF0DBBA -:10F12000C85F1F7BF8178B513E3FB66B7BE1DB500E -:10F130007E67DD3D194D503EB2EEFBDB6F7285FC04 -:10F14000A5BBAE58BEB313EAA3BFFB9347F7225E3D -:10F150005DF1933FECC5F55EF1C57F3860FDA35AC4 -:10F16000E219D2B75C9F719E34D6AE605C14F92868 -:10F17000F165B38FEA753EBDFD6394FBD8DF0CF0FB -:10F18000AB687A8CE2CB69E2FDA397DFAAA830EFE7 -:10F19000DB759CAF74AFEDED9C61A1FE01EC0F7CC3 -:10F1A00092F235870E03B682EF5B7D0AC6C54141F8 -:10F1B0007263BC371DDA919F33978BF4AB2C89BFF8 -:10F1C00082AFE0350746FE4033E1599E884722FF73 -:10F1D000457E7FE7381E071FEA601A9E6FF9739B12 -:10F1E00014CC537BCBEB72935EB096DD3503ECE42D -:10F1F0008B549E779157FED6D5782EB055B3B73045 -:10F2000034EE6EA1D7953FE7A0BCEDB7763B769084 -:10F210009E7FE40A53B87E58F6D89F9EFA1DE257A7 -:10F220005D0CE197516FE916F4D157B7B8EEBB0901 -:10F23000E0E3FBA59DDB559A2B93EC74B72B13F3FE -:10F2400077FAFAFD44C6D3DCFF81FC7C7E751CC5D1 -:10F2500019645C492DFFB80DE97151696309EAEF42 -:10F2600019780E834371ECB7575829DFC0A7C452F1 -:10F270005E7AB478F5A171D9229EDC3896D6C11A8F -:10F28000C763F9C98296FBACAEE8F2AA559C6BB491 -:10F29000768B957923C5950F8DE3FE90163C074B31 -:10F2A000D839387E7F35C687A39D0333FB0B29CF22 -:10F2B000D26E1F897920A9E2F1D6B89FBE8AF2AA40 -:10F2C000E7189757A94D9FAD45FA937E8BDA34D650 -:10F2D0001737D3E03D8B782F55C459908651FFAE38 -:10F2E00015F1A29E1A46F1A2D4A677FF1BE1B34501 -:10F2F0008C5FFB261FDF6A0E1C447CA975B848EEA4 -:10F30000F4A424B8F15E13FB92E7A764308E8F72E9 -:10F310007C26C6C795B3B075A7C656BF4ED7A7A65D -:10F32000B2401CE28F62A77933D6D828AF55EA578E -:10F33000A94DB7DEA08ED18DA7A05EFD5635B7B71B -:10F34000D1ECEC1B375BA757919E655C877CAFC700 -:10F35000C2F6A1FD1BA667911EC6C2E719A1AB0BA1 -:10F360003F9ABE6E49B3EAF8C45B5F560C6AE4721A -:10F37000C0953C8EFBEF101E521F937A5BBF710548 -:10F38000BD87E9973EE417328FA24F4F6A08B39BBF -:10F3900072FABF27F3D5E4394878467BFF99E95ADA -:10F3A000C278D2B302348E570C638A7364117C0D19 -:10F3B000FC12D816CFA7177A286891BA3C06A9572D -:10F3C0004AFEDC23F86E303B487E4399273E0CDE34 -:10F3D000C9423D687C22D183D44F8FAFFD88E2EFD4 -:10F3E000B5A887C2FCC1751FEAEEA114974D1F395D -:10F3F0009EFC73FA7C89B0B82BADD72BF8E64CD5C0 -:10F4000041792B3D2CD68DFCABC727F4B13FC6917B -:10F410003E26F985913F5CEED6F3FFEF95EAF9FFC2 -:10F420003C6DB0C12ED4C7A9AA3C8678F89B7374F2 -:10F430007C53F29F5BD0CDA7A27BC943719DC38251 -:10F440005FBE26F4402B6BA4E776CC171D81FCBF72 -:10F450008B4A073B426502EBA5D2C99C945F93C4DB -:10F46000DC5426330F9543582395698CE75365B0D8 -:10F470002E2A87B1235466B15E2A5DCC69C23287D9 -:10F48000B9A91CC93C547A9893E2E46FC607338F3C -:10F4900002FCE65EC5C86FCF7C7BAFD1E09C7AAA48 -:10F4A000441D1108E96A26E3C8E77B8AB7CF91F5C6 -:10F4B000A7AFD1B07D3AEF5F3F7EFFCF7C0EE23742 -:10F4C000A2FD17BCBDAFFE6FD74CC7F72D26AAFF14 -:10F4D00040F47FBC585B82F8DA349ED17927166BF2 -:10F4E000CBC2EB4F16690DE1F5E325DAB5E17556B0 -:10F4F000A4AD44FC91F5B145DAF5E1F5B612AD9154 -:10F50000D779BEE99B168DF45DF8ED56C6717CC3C4 -:10F51000DF20D5DB4474B34731E3B9DA04BD59F1D8 -:10F520001C55A423B7DD86A587E7FD04631CC138FD -:10F53000D300F68F818E82C89F000F2F51BC6D348F -:10F540008F819F283E913F98AC8F9B00BE935F3583 -:10F55000B886DBE98C456E97F39E0FCF9916E6E7E8 -:10F56000CD098D1B6D1F46FC3D22F4BC6EA1E7BD8D -:10F5700029E2C87DFB0E9A13CFDA43741CDD3E34BA -:10F58000B3B3E1FCB2DFBEFF546301BA0E36D99CBF -:10F5900028EF7A62D86B68A7F98EA90CF58CAFBA00 -:10F5A000DE9AA2594F72BE38CC49F903725EC16728 -:10F5B0007AF09FA0E75C3C48DA976E3B8737B73B11 -:10F5C00012C5BA5A66245D9647FE7CAED7E75B8EBD -:10F5D000CC9B0DEB4CDDC4FDAA0948DF183A7BE259 -:10F5E0008F4E8CA375CC3431E4536DD2CF6BF0C702 -:10F5F0006D99B1CA19EE0F6E4BF02B18BFCC08C431 -:10F60000703F4432F3C7A01C2D779753DE8C4F75A3 -:10F610009663BD9A5D9107F5C59DAAAB1CE63DD4E6 -:10F62000F9F42AF4032EA9B6521CC3A2CD7A9FFB8B -:10F63000FF78FE4692C0F3D60D367700E198E220BF -:10F64000BF6D7E5B6139DABB2D8EA424C4C5A4EAEC -:10F6500065E4376C71B85FC2FB1D3EA789F2139950 -:10F6600053B35780BEB2E3267339F2F1CC278B1324 -:10F67000D4B0759F6A3D17837190079C266A7F609E -:10F680004D997D9903EF3182BD00E521E7490DF5E4 -:10F69000F7EDD007FD8DB7379CEC1835C0392694AF -:10F6A0005B75781BE7D6D76D067FA3C5A017F48ED0 -:10F6B000177922E3D8383CE7B18F7E49F6EF2287ED -:10F6C0008BFCEA65ED0AE5C7040FBAB350DF3CB521 -:10F6D0007934E5BBB4B6EBFDD1C14C9685F77DEA34 -:10F6E0003A14D257D5D68F9BF1BDE179AE741C6721 -:10F6F000B8BB37DD19467F0FFCE4873128EF5AF19C -:10F70000C21AE111E3712161AFCA7BE575CE733591 -:10F71000A8F72FE978C383F04FD44C4433C72DFEAC -:10F72000343CFF8DD3E7135DE23D2DD463FAE9A3AA -:10F730009FC33AC3EE27B425E7C4E2BC21FCD5122F -:10F7400070BFA73B8A483FDAD95E46F7018CE3DCFD -:10F75000B69675A1DEDAB6D6DE1549FFBD2DCB9380 -:10F7600085F7B7CF6C99BE9EC1F99F39B8220DEFCE -:10F77000BB2FEDB0B11857FFFEA7B78CA7F996E2E3 -:10F780003D6A9CB7639E15E5C6ECCEE95684DB6DF9 -:10F790006B173C193ECFCFCABCA34A81FEE23A9E0A -:10F7A000243C71B0800FE1FAEB295A16EA17A773CF -:10F7B00059C47C4E77A942FCFC77533C743FE54C1E -:10F7C00066E47EC5A55C3F7FA4D445FDEBCCECB5DB -:10F7D000E5C9640F3A915E4FB51751FCCE8271773F -:10F7E000908B967D5FAE45FCFFA4BAFEEDE5D0DEC2 -:10F7F00036E7CAF7B01C6B6D24BD99FD5E257A0013 -:10F80000BD90EE89FD67A5DDD912964788FAA3A6BB -:10F81000F36B7818DA1F9676356005FE6E397096B0 -:10F82000F470C4572D0C7FE9374EE8F3223F246D66 -:10F830001CDDBBA35FDB6557FA03509E6CAFB74777 -:10F840003AC7E8F3878D8BFAED0CA6C584CD0F522D -:10F8500031407E6D2F9FAFAF9F68073354A3F509EA -:10F86000BDDCD82ED73F7A9B9E3E9789F391FA79DB -:10F87000B4F57EC7AF7FAF058313949771858E5E15 -:10F880002E52BB56615C85BDC5F93FD875CC13219E -:10F89000CE15E2B3B0F621027E00CFF5C9F3C93E22 -:10F8A00089B60EABFF88963D2664BF7D274DBF2EDF -:10F8B000D9AFA594C7C16D7E16B0246019A0FB1CFA -:10F8C00036781FE5F7A7D5373A2F8B4017B234F2B9 -:10F8D0002DFCB9C2E23F463E81683052EA2326FE43 -:10F8E000BE16C6E7E2EFE2FAEFE96D0AE9BF1BB721 -:10F8F000F03C8A4FFD5027E5829F13AA167F13CA5A -:10F900008E23ECDEE1B2E7DA6FBFC8A583DB128A93 -:10F910006789F6F71EFDD16BD8FEEEE33FF2E07289 -:10F920006F4D5E92C0F9D689C538CF998BADE48F03 -:10F93000C19F5DE207745CEEB7E9F070E3FE47B784 -:10F940002D46B9B3DFEEC674BCA5DBF4EDB6B4B09A -:10F950007D318E5F3E1D9C8239F3808E8EFFE45F89 -:10F96000E97E782CF24FA4C73536BA17D68F0E4AE7 -:10F97000FBBE334278BB381487A2FB2092AE4E6E9A -:10F980006A39A3C238EBD7585DF43D0583FD75DCB9 -:10F99000354F4B0B8B0F5BD7F07B9A2CDC4ECC0991 -:10F9A000ED5F8E7BDC576F7739FA8FD70FEFA28C24 -:10F9B00037A84CFB2DF2C5B432CFCBA5148FAEA720 -:10F9C0007D37ED5B73FC15E8737BACF7D5D2125C29 -:10F9D000FF88710ADE9731BBE8DE606BAB2906F960 -:10F9E0007E4797396624C2BBD54472BEA32B3976B5 -:10F9F00024CA258789E2A72857D430FF3E9BC0F947 -:10FA000064487E7812C2F59F58818F67F284FE3376 -:10FA100083EB3FCA130748EF686DE3712AA96F387B -:10FA200005FE385B791C329AFE838C07D71D5FB2C6 -:10FA3000C4897CAD2D817F7F63C90CB70FEF735EE6 -:10FA4000EA60243786E3A50AD4B31CCC3F1BE651F9 -:10FA50009D5CBFF17630D267921C0E37823AB5D3E7 -:10FA6000EFA3756B9CCEECF01FC233364F6338BEEC -:10FA7000D9A057580D7A836AA87F51AAD72398D066 -:10FA8000BF653C387EF3C07940D2AFDB21FC13A0C8 -:10FA90003FF9E8DE4829F323DE324D73250F09D9FB -:10FAA00001E877C4F6B452B6A3252CFEA4682F92C1 -:10FAB000DF40FA25A5FF41FA39C69482BD9610E6CB -:10FAC0008FF81598962AC5C39226009E64033B20A2 -:10FAD0007B329F29FC7AC6D7D4D39B2E2CEEF3B36E -:10FAE000E7F9FDA05653AC7B6776FF7EC593397D61 -:10FAF000C61EC21C4998E52A3BDDC399A9EEA17B2D -:10FB0000F75B8B4D3CAF991D71A23E903F81CB932B -:10FB1000EC32CFC5B81FE6F06423DE003C7C16BC97 -:10FB2000BF27FCB69937E7C4A23EFC76FAD92DA8C8 -:10FB300097FBDA4CC46F241CB39B4D77201A86C503 -:10FB4000E702E6C2509C6DA3E79C0FEF0BA74EE6C1 -:10FB50007ED7D879A70FA21F74C34813F9D96F8D28 -:10FB6000D7286E07F4635779BCEE258CB7B5BB92E6 -:10FB700092F0BB3B8F27F27626CEF1EEF8213BC206 -:10FB8000F34BE2C4BEEF5622EB2B7F9CC4E54BCF78 -:10FB90007E00E420F26B097BFC0FD59A23BC0E702B -:10FBA00083F7FFC5C7EDE97913FE50ED33939D242C -:10FBB000ECF9981AB2D7D1C708ED7B263C58ED83F3 -:10FBC000FAFDD991E7ED98CCE7BDFF65EF70D467FA -:10FBD00083FB017F06453ADF003395D2B859189769 -:10FBE0000AAEB62D88F41D9B33629F5BA1CD3628EB -:10FBF000A4C76EAD36EAA97EE2579F349C7C81D2C1 -:10FC0000B4817F94003D24B2C8FCF2FCFAAA3B0DFB -:10FC1000F5CE96D5CA7AE41F2DA0AF625C30D569C7 -:10FC2000257DB535F187D3F15C3E69604EBCEFBAF6 -:10FC300013D43EE45FE857C57BACB39B389FF13AE1 -:10FC4000B99F15EC38CFA5888FE966C247A9BF9A3E -:10FC5000AB39FFB9D8C6F3917B121DE4374D6CE286 -:10FC6000F9C7713ED067717F3378FEB006FF211F60 -:10FC700092FAAD23DFACCB23B61AF28CCD86BCE270 -:10FC80008D13F47C28BEA47840BDEA5760FFE23AA9 -:10FC90000F00FFC13200763096CF83DD8EE56FC056 -:10FCA0006EC7B8C18B6BF3A87C69AD9B9EBFB2B623 -:10FCB00094CA6959418A2B921F999C8F2CA0901F3E -:10FCC0004FE2D71BC3CA10DFA7F3F65F4EAC7EC06E -:10FCD000370CDA9365FFB1847F7D755F750DF6AFE4 -:10FCE0004DE3F551CF5E5D83FE9FDE99DA4313004D -:10FCF000EF524C9EBA36ECFB239B3B927D5F30511A -:10FD0000DE138B6CBF33FC4482DE9FF314F1892831 -:10FD1000FE9CBB15BE8E3F4E7AF05EA48B41F3CCA9 -:10FD20001EC4E3AC1CBD9F7FF044CE77168B32EB34 -:10FD300015A08F01E02EE9235A7BCB7E4081087409 -:10FD400025CBADF16C2ADDCFAEB12E8894E774409F -:10FD5000D055D4F11DCC651B1BA2B7168791DE824E -:10FD600014DFFDA4E9C683282FBF39BD31B20F834C -:10FD7000351AC9EB20D01BF273B581D39B6AE6F725 -:10FD8000336B0F73FFC84EA42FCC87437A837FCE8B -:10FD9000F6F17AAA81DE5A8CF4E6D0D35B10E90D35 -:10FDA000C64BF471FD22AEBAEB5BA5B7CFBF21BD48 -:10FDB000FD7A4A90F21A7AB21BD3113E5BC5F7F076 -:10FDC000BE2A1DDE35D1CABFCF7189467E81561C41 -:10FDD000C741FAFC26FCCECAEC61CDE62480DFDC0C -:10FDE000E402FA0EC1E48943043D1C71A0BF266100 -:10FDF000BAE69C88F475E57B74BF31C5C4E9B7E009 -:10FE0000D937491E64B675CF9B8D74B75A253969A9 -:10FE1000DC57EB548E6F2D0A9F174E2E3D3CAE37AC -:10FE200042D0A56B758B62477DBC8EB973B3E9BBBD -:10FE300032F4BD9B7F69FD4F278EDB3A3589D6E5CD -:10FE40006A7E33D1CBFD6B6968BFD195E6C2FEF403 -:10FE500008BF2ECB101D3DE74F1CC03F7B3EFEF17F -:10FE6000C80445F209CA03F68AFB9B322E12959EFE -:10FE70000D7EDCA8FEC34B387C8CEFC74FE1F3B698 -:10FE800008FFAF51DF93FB3F3ADD3B1BF7A7385E1E -:10FE9000E47EE003CC85EB9471B3BE3C23A91FFA4A -:10FEA00098BF05F56D33A83243B8BA81E3F5E51F75 -:10FEB000093D714599773E8EBB83B90EA27C73B81C -:10FEC00079BEC233D3B50A82E7D7D4034BCBB46B28 -:10FED00006C2AB15B3B54503B5B32F619471A1B894 -:10FEE000D6F47966CE179A14C1071CEBAD50DF9A91 -:10FEF00008FCCC857A3BDFB713F8868BEC0CBD1D74 -:10FF0000310B9D91C837908F1070B5B998579920D3 -:10FF1000C60FC9EBE00BA8970601B6774053828F56 -:10FF2000CBEB96C39CAF5881AF505CBA94DB09F21F -:10FF30005E505CBE9BEC2F551BD87E301BECFBE665 -:10FF40008922EFBD901523DCB24CAE3B27C0F3A253 -:10FF50007B661E9D008F4BEE5B3A18C5E9F81D6D60 -:10FF600015F8BDAF150F9FD9817ED209FF6E63E2F0 -:10FF7000BB6A9467F0779433742E07269FE1FA6387 -:10FF800076643CBE620A977F32CE3A001EFB098F30 -:10FF9000459CF32BE0B1E33C78FC58143CDEF30DB8 -:10FFA000F178EF44D8D7357808304ECC6CED17583F -:10FFB0008F86B7B36669CF0ED41E163FE0F943AC07 -:10FFC00081EC6719BF34AEA70DE56BEE007EA90D7D -:10FFD0003B63D09E6D69D8F9327EF7B1A589DBD934 -:10FFE0003DF16E7B29DA376FA8F43DAB68EFA3DDF6 -:10FFF000ED036639730ACF8F3EB4DA169806E364D0 -:020000023000CC -:1000000038B8BCCD70680CF3C5CDCEA0C51B8FFA37 -:100010009A87A19D614D36315F983F66ACE508C96E -:10002000E51E90E3481F409F9CDE12F938523E4F78 -:100030005B7D274672D8945E90836174F2F2FE5223 -:10004000F2C3C597EC5D85EFA9355617E2F7B4CF3B -:10005000416E86CD331D3491F0FAA5F674DD383348 -:100060009DD9BAF6D969DFD1B55F06F862A53836F1 -:10007000BF1728F59A39AE025DBF4411E7F86EDE6E -:1000800004DD7866F5CB3BC623FD0B3D6232FC8771 -:10009000F4AF1AF405A33E61D41FD824FD3DD53139 -:1000A00066918766E6F9115B999DBE4B017C90BE17 -:1000B0007B501BCA13203A19630DEEBC0DFD2A0BB1 -:1000C000ED6E1F3C6BDD7F595A5D71C87FB6B589F7 -:1000D000FBFD5AF6D977203D6C177429E92B3FFEBA -:1000E000E4424672DDCA501E1BE955E63B497F815A -:1000F000F427280DDCCFF0D4D46CA207C97FB65604 -:1001000073FBF7674A204619C1E9D29514FA3E5DA0 -:100110001A537C73387D6B49A254453EAACC7BC5EB -:1001200071D0CE4EE3F3B19778DE64F38FF17D2783 -:10013000F30D13FE8CCCA4909F02F31356F2F77CC0 -:1001400073C47BC345BEE520BEFEC04C31DF18281A -:10015000D5464DF8A7BD54DA301E0E658EE28E45A9 -:10016000FFC708D543819604115FCF10F1F43825FD -:10017000C099C7D7E42363818D625E024BE2DF172B -:10018000297BCCC154A20FEB4E9447B79E70BF8E13 -:10019000A9BAADF13F7C751A3C6F7F4375A39FF4FC -:1001A000D64CDFDB48D76640061FF9B53C75786E44 -:1001B0006AA5DD391BDE537D3B9A31BE3BD6EA3F53 -:1001C00048E7B9CE46F41E84F7101FB6C7039D2238 -:1001D000BEA2A76B5C281F48C6318213DC7694A3AD -:1001E00041ECC7FDCD3AFF67847C13F2979A45BD79 -:1001F000D5B193F4F7F5C956FCE226E6F76435214C -:100200005EA6C4F2FBB78CC70D86E33FC2F2EDAD2C -:10021000CEC87E4DD0D7080EC1E6E56903E95D5131 -:10022000E3280E53C09A70E17194B66BAFF407C225 -:10023000D629F7BDDEB15359CCBECAFC4C1F476965 -:10024000605ACC98087194A05FC1750E6FE07196EA -:10025000E1C25FFF75E3285953BF5E1C45EEF7729C -:10026000F1EFB980D8E29E31C513E8BC4CA1F58509 -:10027000C1EF21E247841B0245A0FE3D517F754F2F -:10028000F79F1E857F1EDEFDFC1E2CA51E374FB47A -:100290005F31FAB30398BB356FC32A11C7D2C71FAA -:1002A0002E07AB2EDCCF8FDF0B08AFCF33ACA7CC44 -:1002B000AC8F13CC70E8FBCF4AD6B7970FB3F53BA2 -:1002C00037F4CBD37E95FEFBBD35EE76C6BF371532 -:1002D000760EEAF9EB76CC9BC3B88FAB3F9E84C712 -:1002E000013CBF34B3A462C41713E9A5DB7DCBEF97 -:1002F000AA02FA590F7294F362978EFE42718F72BE -:100300000DF149FAFBA3D1D349470EF9FF87371DF9 -:10031000EC9A3198F5C5016E8FF5BE3109BF17E42F -:1003200038A7A01E32BCE937D47EE5C29201F1287D -:10033000B7E950D78CB0EF08E69A3D26B49F739B7F -:100340005EA4E751F5F9FE7C84F2D672055EC8BC66 -:10035000C0ED98170870CF6D10DF07EE1C38FF4D09 -:10036000CAC3D6B0FC3E4A6670292C7C7C29F7FAB9 -:10037000F9D319F7FBCAF9FAF2020DF3F6C93F27D0 -:10038000977FCF4CF77E312925EC5E86B8C701FBFD -:100390008E9807CA268B7BB1D1F3D8B8DD59F9D234 -:1003A000DB38FE57B63BA38C3B2D2B18F19ED4A017 -:1003B00089C28F1C13CC44BF418F25B25EFFB39915 -:1003C000B392270F60A761DE2CC232DA3ABF6EDE2D -:1003D000EC04116F92F156993F2BF362CF973FFBDC -:1003E0004DFDF065C21F10379951698C4318D73BFA -:1003F00059F8C7B3CB3C9326D37DAEC8F107D9FFDC -:10040000ED746B44BFF8FD53059EF4BF7F44F9A122 -:10041000B0DEE4703B48BE27F3F28DE3815D74C526 -:10042000E4307FA0B73997FC7D61F696CC8725FA3A -:10043000D82AFC107D7460D40B453CC4A817CAF8B8 -:100440008852CDFD13401F350807D4BB302F5DDA2D -:1004500079329F54E68D625E28C5A3BEA65EF5ADD7 -:10046000DB53CD3329AFABC559F6D237B1A7DAA7E5 -:10047000F27BC2D29EF23AB8DFC18BF6D425FDEDF5 -:10048000A9E2326F2BC2CB68571DFFE987941F0B7F -:100490007668DBE46F834F18FC53232670FC96725A -:1004A0005AFAD30E8E34E9FCAEB3D43507295FBCBB -:1004B00081FB5B32B42EB2D3AC0EAB0BFD2DE61933 -:1004C0009C8E2CF9CCAFF1382FF957645E599263AA -:1004D00059C4FBA6D24E0C4A3BD1C7EFA7F61CE687 -:1004E00071DB38F4B760C7722ED7A4BFC5922CFC5D -:1004F0002D867CEC38837FC5E86F7962B2DEDF72CF -:10050000BFE2BA0D49FDE96D337F87A0F8B77B974D -:10051000C6A1A9FF8CBFEDBBC2DF728F03D6B7FFA8 -:100520006DBDBFC518FF8A10F722E7D599034F901C -:10053000DF44C257D2ADF4676534F1EF37CD52F7DF -:1005400028C85FB63A387C55F4672587FC59CA132A -:100550007FEAF34BD17DDC7E71F2C697719D6660B8 -:10056000381B23F9B7045C8DF1A88426710FF85B62 -:10057000F267BD63806FE13D4577E2778D8BEFAB2E -:10058000388AE5B81D370EBE1ACAD287EFACC0F262 -:10059000BF5E0E66A3DE69F463BD821F414EE90FA4 -:1005A0005F231C259E7A1B249E3AAC44B7D51C8E33 -:1005B0004638A56A1C4F73014F4145E8C3BF9E44AE -:1005C0004E9F1933DC2FA17F6D78BE9945C26373AE -:1005D00013FF5E9684E37601C7A48665E42734E2C0 -:1005E000E9F0CEAF869FEA14E11710F07B6A5BD189 -:1005F0006D08B7BDF756FC0ECB5FF86F8C43B8EDB6 -:100600007BE8CEEF0AF8A5D3F7740DF05B14057EF6 -:10061000D3DCDCBEFEB8CC9B3805E4C265C021D07B -:100620001FB2B3BDD0AE8F03E9F969EAB7E49F0A00 -:10063000F6F153F65AEE57E0A74F1BFC53A93E4E76 -:1006400037A9BE13449F19409F31E8AF6AE07A246E -:10065000887D7F9C823637E7AF52AE21CB3181F067 -:10066000D9EEE471E7087ECA007DEFD7C087D1815B -:10067000138E772057274C4909C9BBED0D3C8E7668 -:10068000E34CCF2484AB8CAB3D335D9B3C85EE2F9C -:100690007C6DFFE30C9C47FA1F014F69FF2AE03B8A -:1006A0007EDFFC52902768FF9B1B8216942BB54D72 -:1006B00037285E28DF9EC8CF3F35CDCB30CEDADF7E -:1006C0005F178C47BD7DDAC83E7CA808C787B1ABF1 -:1006D0003FB913FD5CD1F021234ABED2F9F1A14C00 -:1006E000275FB7F6E143E38651C9178E0F478DF8B0 -:1006F00020E83FB521780FD2AF59E083D9097C0CAF -:10070000E0A1221EE487E29E921E8222FFC0089F83 -:10071000A06F44943C84554AE900EBBBE0FC031114 -:100720000F6D11F1506F13CF97ED596D9BA5CF3F12 -:1007300070D3BA673B1A95F03CFE0879B2B7E1F97D -:10074000C938A78C6B7E5CE6D98CCFA7E5F1730E18 -:10075000468F3305F07E2BA09FD380E777139ECB87 -:10076000FB07428FBB71A6B6159F8FB1FA29CF192F -:10077000F4BD7BB1BE7DFFA3FC7BBBC20F29F3F2AE -:10078000BEB1DF2CC1EAC7FB92D26FB635DEBA1319 -:10079000CFBB8E0567D2777E314E817EA7CD36CA1C -:1007A0006BAC57C0F046BE78A9B76B0AE94D1ECABC -:1007B000C7F556DA9DA8E7B726CE4A43BE51BB5EC1 -:1007C00025B91ECDBE91F4560BFC86E8AD89F39B8E -:1007D00054C02FC2379F42FC2603F80DE73F1A434F -:1007E000BDCE8C74E7E8CF6FB60E00FF0BE43B2F55 -:1007F000E17946E03BAFE03EC3F8CEEFA67C83B89C -:10080000C7A553188FE788FD633C80F68FF415BEAB -:100810007FA33EDBB76F3D7D49BAFB5F40679F23F7 -:100820005C23D0D9FFF98674A64E8D4C67E6A97A71 -:100830003A8B99FA8F496799534BCE4F675D02AF58 -:1008400064FEB6D42B2E52BBCEE5E2FCFF8FF3B78D -:100850006F9FC4FDA9E7CBDFC6DF85F84F8DF9DCBC -:10086000FFF4A7FEAFF5A7FE78EAB7E04FFDF74922 -:100870002ED2DB8C7ED5BDE3B5B6A903C495259FEA -:10088000364B3E0DFC18796F2DF033E4CFA9D5BD62 -:100890007F7E86DB9BEE3817F91BEEC0F566087E7F -:1008A0006DE4CBA077DE39F5EFE86FF87BF90DCB7F -:1008B000265FD87DFBB2C92EE1778D7CEFBE45D88F -:1008C000F72D3006DED3DBBEDAEA6F8505A78BF3A2 -:1008D00019D370E5654864AFAFB0C60607B09BE4B6 -:1008E000DF91E858EB7DEE746EF8FE5844B9D5B749 -:1008F0003F839E1C6E37B9BE82DD94324DEF873246 -:1009000037703BD70CF28EE2FA5A6900F975864FC0 -:10091000E9C2D4606F72A3827230B5C143F9F05F4F -:1009200035AE6FC4A36871FE6F3BAE6FCC1BF8474A -:1009300089F3FFF754FD772D659C5FFA5F8D71F9A0 -:1009400031D68E7292AF3526FC0B18AC75FF073B83 -:100950006FC3F35E68A77B1AC67C806871FB314960 -:10096000D6605C4EF4F8BDF417DC6F697C19EDF0CD -:10097000FB9B4D74BEC6BC81FC789E3FFED4AF3657 -:10098000DD47F93F521FAE167CA649B1D2771DABA9 -:10099000FDC467BCDAEE668C27A73A5817EA5947B8 -:1009A000A7727A51D334E233E66A2FE1958C4FD4A3 -:1009B00066F17B733102BFD4918DAFE2F889475461 -:1009C00037C6B7376357E019F1282B518F9860A2CB -:1009D000BC884EA591FC1E1D8A8BFEFE4762BE930D -:1009E000F4A3C713DDBF5F80EB4FE17FA7E4D09C8A -:1009F0006569C807D73737A7E1FDC4E2693C1FF135 -:100A00008E39676B288E9E07FA9F42A5EEEFD9CAF2 -:100A100072A7A688BFB7E4A77C4458F7367A6FA4BC -:100A200095FC6CAA76F78DC807D451B308AF3B1478 -:100A3000E7C2C5785EB956D2635A73C72D5802FB18 -:100A4000DA90E229CFC6734D1C49FB6C4D1C928095 -:100A5000FAE886F41C9ABF5DF19667E37BE926A26B -:100A60006B55C4E737E42E7B09FF0E484B8689E1BE -:100A7000BD83CEDCB3EDD8AF7302FF2338C6F5AA31 -:100A80004EFD3D29FCF011F26F358DC7C55511178C -:100A9000570D71E5324D917F6783E20E31826FD53C -:100AA000E6AE5B40DF4F70589D88642DF1C12AC2CD -:100AB0008FD51686713A66EED0E969B7ADD57FFF5E -:100AC000C591AF5F4F7BDFFD846C2FF219FA1BB02D -:100AD000942F9EE845FC407ECB93FEE2783D46D4C1 -:100AE0000316AF2FC2F9FCB3FC67F9CFF29FE5FF05 -:100AF000EFE5FF00834DEAE8008000000000000001 -:100B00001F8B080000000000000BC55B0D741CD596 -:100B100075BEB3333BBB2BADA459FDD82B90CDC8CC -:100B200096880C421E0BCB488D8D66A595B4322E4F -:100B3000D938FC98C476D6D8B8E43427559D26B168 -:100B4000135AADAD95254BB62C09829C43CFE9DAFB -:100B500024396DF00125E9690C01CE1A1C420834D4 -:100B60000A10427A92208CE39496E698828968690A -:100B7000E9BDF7CD6877462BFFC53D1187F3FC66CD -:100B8000DEDCF7DEFD7BDFBDF72D0078600180EC59 -:100B900007001D6073912709E500676B200DD5D80C -:100BA000F74E576841800FE9AF35DB0EF702647CE2 -:100BB000D97EB05E05B30EF8EF43D1B8E88E9B1630 -:100BC0005DF863D21DAC5537A48373E9DAE3DA4CE0 -:100BD00009A029EF3C205DD43CA77FA6E3F8E4CF31 -:100BE00064A8D5E7CEE7FEDEFE6E73D1FA12A8FF49 -:100BF000FF1B3F1F5F979A1E800AD18755B86F6A07 -:100C00009788AE8E7C5040F0A1AF73553A83FF9C1D -:100C1000901283D5B4BF90C7F806CCE583DDCADA5D -:100C20001CF965E9CB827CB94D1F9720EF0C9881A8 -:100C3000627A85DF21EF355CF6872812A5DCC3CF09 -:100C4000C1A2170678E6435CDFD1ACBC405B90A53F -:100C50002B6F5479FC72B5E785A695F8EC15D9F899 -:100C6000869EA5CBEBA9069E00ECEFAAB3EF156B11 -:100C7000DE8F1C5221638FC7FF8F9921E6D3C4A654 -:100C8000FB2181FCFDF9C64F9424F2E881DD2E4B57 -:100C90003BBF7F036902F30DD2DFC07FA77E312AFD -:100CA000F1E4C7C4F3D40A2D3D84CF87A4F4D03532 -:100CB00034EE2EC15F5B0E85961CF02F5C837CF4B6 -:100CC0005A72F2BAF7857FCA02E693C59C1C392C8A -:100CD000611A35B4EF3E9B9E6E6400F934BCBC6172 -:100CE000C5904EFB1FFD876FE13A0E1DDDF3E6B7A1 -:100CF000F075A0BE61A419D75360780C99F4F9532C -:100D0000C78EA1B860A0FE0BA34476DBA8646AF886 -:100D1000DEAF058FC8B447BF64123DE5E042DE4F49 -:100D2000789B530F2624634125ED6F4C02924BA113 -:100D3000E17CEFD373F683FF1F2239B37EE63C4795 -:100D4000BE21F7364CD6CFE5FB2B963E2B383E69BD -:100D5000D345BE8C7BF59B89CFE3FB644822C9F168 -:100D60005D68145700FC5BE6BE4FEF46DBFE42BFFA -:100D700097E5301151D3128E9F28D26EDB40FD0AC9 -:100D80008F7184998AFFE3BE46975DCDFBB2E76B16 -:100D90006AD579BEB1C8824AB2471C5719BF6EAE38 -:100DA000FEB9D77FB1FA77B7596AE9FB28107D9869 -:100DB000BCD943F6E4B7C65C234F362EA1F97E2E8C -:100DC00083D09B1E8817CDE54F3FF9838F64F54490 -:100DD000B5F4686FF9FA9F10F9F9F4594D4F99D5A8 -:100DE0000D340FF410DF97859DEBB3C77DCE92973E -:100DF0002F0D196F31B519131AA89D32256CCF6EBE -:100E0000FCBCB6569F7F1E1FE4D0AD267AC0FBF611 -:100E100042829945723573E4BAA7B0E10E924BFF56 -:100E20004D2AB0FEB9F97C9EBEAA648E4BC5A40FB4 -:100E30001F61FD48A27ED4221D6FD8A987F12756D5 -:100E4000C27450C829C9CF6326C96959AB77D67F08 -:100E5000FA73FC25E8BB7F2323BD7B63AA3E84EBAA -:100E6000BC37BEFDABB7929D3F2F1B12BFD7D91F1A -:100E70007EC19A034627581F4AAC7367E7B17B5E71 -:100E80007B8E6414535F27BE911DCFF245F867D364 -:100E9000BF2A3BDFC1E693834B910FA9C1FCF4EF5E -:100EA0002CD33F47FCB3F93C1FDD59FFBDF3F86479 -:100EB000F4FA6C7FA4201188A01C4682063A017ABD -:100EC0007F82DFC34AD4CBCAF9E5891C65FEBC46E4 -:100ED000FFC471DD51538B605F3E864B5F8E7EB1E8 -:100EE00048BF793DBEEA287F7D13F17F5BD0A3C95F -:100EF00039F6D5B7DF0B99203102E745BD5B07D343 -:100F00009BD6E338A8F1B29ECBE52BF8F9D6A2B870 -:100F1000E2C1F6EAC8129ECFFEBE1BEE5376E0F3A6 -:100F2000E55EED15D29354B9442BC2E7C8405CFA94 -:100F30005A05CC626CBBF4889FCEB5D8E33411401F -:100F40006B68BC9CCEA586C70E5525C8AE93E654EB -:100F50001DCA276489EB5ADF54BC1DE9F5BD201B6F -:100F60007BB01F0A6E5F07A847D22341F6137DE8C6 -:100F7000E77D287725D8F9263D5F7306209AA34F91 -:100F8000AD337E88E6F8BD0852CEEDB7FB2B1DE3EE -:100F90003BB46AC77B194C23837CEA0A2F738C2BE2 -:100FA0006A5AA9D17ABBF5158EE737D5B538BE8711 -:100FB000A872721AFBABF13F92BB0CA2CFEFAB0948 -:100FC00027603FE77B0572FAF87E6DA4A8FC341D0C -:100FD0004A37C00D6447289723C3E47F36F8F9DC0D -:100FE000EAF3C231A904C8F493D048CC36F9BC97CF -:100FF0002C7D4D46AA594E52F099F7590F1F9FF676 -:1010000010CE82C7A091FCEBDF6AFA710F0EB99285 -:1010100048E2F76154741DE584AE3A1968E4E7E6E6 -:10102000D2523AE7A46437F617E1B8B05045789643 -:10103000C6F961F757C4385844E3344856615F3302 -:10104000A080E45A85743E5BCADF25BBADEFAE12CB -:10105000DF254B4A05FD86463E47331DD81E060355 -:101060007CEC7FE2089AC88BF4707B15AD0A9F3F39 -:10107000084623F56B619AFD148A5FA2FE4298D45C -:101080008493CF08BF3DAD844EFB85DFCF672F59DA -:10109000BB51E0B42D0F1C7C55ABF925B2BFDBEE84 -:1010A000683A27EE50763EEDB0DBEF4474711EEEE9 -:1010B000EC623B51763EC3EF5F8AC4F7901D12EBA2 -:1010C000FD8D73F9DDA06680FC572A02461249A403 -:1010D0001E5D1BDE82F24D3EEA376AE1F2C9E36231 -:1010E000E59006AD80F82AF75CAA1C80CFF9E031C4 -:1010F000FFE121564693CFC93F402EDFBA14B9B85D -:10110000E501F79401B49CDF8F3E206502D252E6E0 -:1011100087196ECCF21FFBC96516BF4A2D79C8A28C -:10112000CDC8D673A5747EB910BDB2D2AC7CCE2723 -:1011300097701CDF3766E523F798CC3CFB9CF6C123 -:1011400019C6B74B2483E5B5548E7BA85F28652C60 -:10115000D093E673BD183496CF15D0C36DB9777AA6 -:101160000BE3E19D3811E1D90FF094CD89C752C14D -:10117000367F35F9D73AC5F060BFBEC8134F231F7D -:10118000AF542043FBAB542049FE1C9101D34F3D8B -:101190008AA7159E33293CA63DF4DD2E7F3A2565AE -:1011A000E76FB0FCF64F8ABEA94DD767F97C92FC79 -:1011B000D772C10F0FFB9FC90C7D1F8E81D1A7CFA6 -:1011C000F567382E295B7E8ADACDF4A285F9962C54 -:1011D000C6BE34F8C3F70967103D05FBDF8B24DE7C -:1011E00021BD219C1E2C65BF345D48C07A2E2E3057 -:1011F00009576CB1E6D970A3BE388EEBDC32E87BC0 -:101200009DE841CAE7C405EEEF750972BFB7BF9B01 -:10121000D52BF7F7976807B0B3E2827040E491D519 -:1012200025D37970FB2CCE243B29CBFD4EC8492D0C -:101230004F30EE50C95ECACE4FC7EBC22F361D2FBE -:101240002A2ED1F15AF8C53EA7B6C319AFB2D45A67 -:1012500027F26B2BD87FE5CCCFCD16FF3E4DE7555F -:1012600031F1130315DCF73688ABA4B77F86109AEB -:1012700070FC927DDB8A192F405423FE48998FCA57 -:101280001F5E7B117CB4F8B439F3A65727BFB4B303 -:1012900008DEC88DDFACF7EF6CFC8488D3FDFE1A46 -:1012A0007F4E7C5878EC835E72EA7B0AFFE68556B7 -:1012B0005C7AFF4BB22157D37B819B0320CEEF4258 -:1012C000B2535C77E1E3A7FF87C617BA7035518642 -:1012D0001CBA9EC2FD8C670B8B559D71B64BCF6CB3 -:1012E0001C0D1F081C1CB4B897435722BC6CC73D8B -:1012F0004C579A3BEF75163EC757910F2F00CFBB47 -:10130000713ACCE273F13E1854859D609C9971C48A -:10131000C17A5E3BB3D76D7F57A1C6AB8DFA3CDF78 -:101320005B72A8A7401CFDC2C22A48EFC6F50E0E8C -:10133000EE8814627FAC02748C3061A0F38B12E1F2 -:101340008DB672A14AA166810B690AB0E378FC0BE5 -:10135000FDAB3E5487EFB757050D5C192C7C0B7124 -:1013600032D2B9ABCA6F98F82005E27DB2D923E238 -:10137000C924BC4C78749B251FEFE30267B26CD084 -:101380000EF7B7097CB5EDD867D7917C474A6F3126 -:1013900032386E1BFAA732C263A35EC67388EB1C99 -:1013A000B8DFD79C8303F1FFBB0E791D7DAF0B2700 -:1013B0000EB7210E44FDB671E0FD6DC07646EBA27E -:1013C000F3E472CD03C172F6A7D729539E7CF93797 -:1013D0005B1E36FE7EA242F0D9FBAEE00B06CC3B94 -:1013E000E8B9EF5D118FA1030F362DA0D35FF0CFC9 -:1013F000D784FCA1A7EF8AF300BFE4759BF81FAD6B -:10140000DB8D877D2E3CEC5EAF2D87476CFEAC827A -:1014100055C41FC4E78C13ECFDB8F7F138C6E7518B -:10142000548A277BFDDC667A356E9FEA0D737BA2BA -:1014300057872802B0677AEBB87DB6D7E0E7CFF5DB -:1014400036736BF3612E7F445EF32A6BCD4AFD54F5 -:101450009CCED12BA21E3685B17B3CCCB7B3A89FC6 -:10146000647CC506E5DE707CCC93A690DE8E7F168C -:101470005AFA7AADEFCC711F8E1FA904630F7EBF9D -:10148000B0793BEBD99A339EAC9D00C539058E3CB3 -:101490004104CA1CFD76FF958EF11DDA52C7FBD2BE -:1014A000C834FBA9AEF0B58E71B69CFF8EE22C5C01 -:1014B000DF58F4A4467CEDD6AF778C53EE41F93774 -:1014C00050FCF351075D90D719E4A74B373AF5B0BC -:1014D000D82557F5EE73C741B69CDF6A73C643F350 -:1014E000C9D7ADAF365F4B67F92AE2CA14C595C8B4 -:1014F000D7524DF0D5DEEF88B55F7B5EA559ECEF96 -:1015000072C797C5145F56E78B2F4F597C3E4F7CAF -:101510001973C6976EBE9E2FBE5CD0EEF42B17CA11 -:10152000CFCD8B45DEADF47999E31639D6C3E760AC -:10153000D9946C74914BB4705911F9001CB7B94926 -:101540004D13CE1C83E9309DE70725E42AEA5B5959 -:10155000BD51497EE6E190F1CA06C28DDD220FF849 -:1015600074E4B630E18EFEDD87C37858414BBB870B -:10157000FDDD68E434E72F141D387F81AD99CE83FB -:101580004FECF176BEF1E026352DE1F88356BEF141 -:1015900060F76CBE91EB1B134D22DFF827EDBA9577 -:1015A000FF4B86295EB977D3AA4A3EAC14EC5F475D -:1015B000C30DB693A180564C71746A9347A37DC93D -:1015C0002BEFFF3CE9C701A9675F0DC56F151ECE64 -:1015D000BBA642AB2AB7E0387933C218EA6F5AF596 -:1015E0002AF9EC890A7D5F0D7D1FAA61FEF5AFBE69 -:1015F000CD4FF38C841674537E64A4C3C332920916 -:101600006714339DBA73C53DEE3A804C1E97E2B71E -:10161000724F46A5F38AF0474EDEDF96FF5048E54D -:10162000FCECD6F6870E276BF831FBAF85765D664E -:10163000531BE799CF129E90E6AFCBECB5F29DB36A -:10164000E74ED8B99E3CF3302EB0EB12F4A7DB790D -:101650005AFC4BDDDC99A673741CE231F29FC9E0A1 -:10166000B9EB204AF0DC7590F9EA1EBBDA451EF5AD -:10167000CB2477915F74D44B94985517B1E2D783FC -:10168000940F277D70D549EC75F459F452B37AE480 -:10169000AA9BAC562D7A06E4CB5FFFA1F593FBDB4A -:1016A00045BDE662EB26DF6D07B15E2BDFEDB5E4ED -:1016B0007F8D3CB983F4F18F9DEFFE6EFBE5CD7716 -:1016C000CFAD13A5D95EE0D89937D8AE972DB0F03D -:1016D000CBB9EB404304F4517EE32B109752FDC38A -:1016E000EA27AF1374DD75A1809547F951FB5211BC -:1016F0006F913F21E12AC662E26B50F97652C37DB9 -:101700001404C72084ADAF7C4B92DAD6C53AD78794 -:10171000C69779F8BC1A2F4A1CEEA7F52F0BE6B531 -:101720008B572DFF3768D56F48813D646F926D1CD4 -:1017300090F0A09C2640C8F9ADF6108F57B4D1E6C2 -:101740003B516F4E913E54F07EF2D67F4EB78BFAEE -:101750004F0EFDAF939EA62CE244670BD2F90F4BC0 -:101760001F810E8E0514EC88F9FCFA6833E182DFE4 -:10177000B56BE2BDB2C2207B180FE59FEF77D67E36 -:10178000805231ABB2F868E1464107FCE2FB83D2FC -:10179000990D2757B25CD99E681DF4DE5DFF72D3A8 -:1017A0000FD439E31BB5CA39FE83D97D38E3A203D0 -:1017B000F3D4C7164585BEB62E167A46FAB1278FE2 -:1017C0007EB8ED5DA5BC27C553D190359FF03B4158 -:1017D00065AA8DE29D603D185C53548EF37EE34F05 -:1017E000D41C9B5E497EBED8A03848F1A3AB6CCC1C -:1017F000C689EE7D9F2FCE5314487A1BE7C67B48DF -:10180000D72C6914E74C3287DE5551A127726E3C04 -:10181000584DE1887E33D7F1A80E48FD5DBE0DF925 -:10182000CEE9DA76EFAC9FCC57D73914C73882822D -:10183000D447F6EFDB8AFD77348FE6E3317ADEBA00 -:101840008E66F567EB3AF10BABEB8C464BBB6B2E20 -:10185000A6AE330FDDD9F3786E5D271AC57D8E05F0 -:10186000457D65B6AE734BF905E573C03A974B2DD0 -:10187000BF5CD46DC5113B258E239E6AFAEDF072D4 -:10188000D2B3262FEB01EC9F805C3B59B751FF5A36 -:10189000199D33AFFAA056F83593E8D971B1CD3F11 -:1018A000D5A2DFF6D0F30A8D1FAFF4AC627A90F1C7 -:1018B00079B8D89D54AD56A676B99A914B886E29C1 -:1018C0005875F48C44CF23C8ACDCF86064E6C5F6E8 -:1018D00012CA9304C120173412D17697D03FA80AB8 -:1018E0004478A75A4F93BF6DF7173AFCFF48B72AC1 -:1018F000FC6BADB82F337E5CFFDA361C3FB033C0D3 -:10190000B8E9409547D85752E27A7287E68C7BC691 -:101910002797083CB6DF6BD03D91A39362FCD6C8F5 -:10192000AAB4CCB8DB191775EBCEB8686B65E32B9E -:101930008417A1DFCBF978CDC2B537D539E3A4A29E -:10194000EA9E6709A76CEE1778786FB874C156F4F1 -:101950007FBF8AEA8E38714BFF5D5C37EA5781EBB7 -:10196000A9239B54B68F11EFEB87B6326E2C603EE5 -:101970004E6C522B1339F652D6E1B3EE4508FC817A -:10198000F0323199E77D5987F03BA8D87C8EDBFA9D -:10199000F2A79F117C2EAE82B44E38AE7B4786E212 -:1019A000CAF12ADC13BEEF0FD7741FA7F95F968127 -:1019B000F6E9D6C3EA8E5AB6D3D9F3B4D9E3E093A5 -:1019C000D717EF21FA7013E8E4D7A231EC531E6069 -:1019D000A30A941FF085FF8AF75B8AFD00F6FDB12C -:1019E000D1A4827D7F4DE27AC2C54FEFBA7D3052DD -:1019F0004EE79DB06FDFC6EDF14FD0F8955E08D091 -:101A0000FA4097C2B4BEA4B8CFE0B687BDA91F44C0 -:101A1000494E7B0D8945B4B97BFDDD7C6FA9BC8047 -:101A200071D3A837BE85FDD1AD7E2DC967E034C71F -:101A300011DEAFF880F46E62D76F2A087FFF382A74 -:101A4000EA9A01DD195FFB6194CFEDD5E6D446FA41 -:101A50006E75B34A150F78AAE534CB6DA2C967F845 -:101A6000701D132D12F3F9BD266F9AE679529D92DF -:101A700069DE27DFC3B9ABF3D9777EBBB2EDC83DD2 -:101A80007EA479BD9FF4622F4CDD42FC49CE883C98 -:101A9000957B5CBC439C577B53B7D6299CCF52B9EE -:101AA000DEAE9C31CC12A41E9A89FF3DE55E9351B7 -:101AB00045C449959EA484F406BAC5BD8C81A2C4D0 -:101AC00020E9F300EA3DC749E5E23ED27865B93145 -:101AD0009433DF78CB6D75E4CF5E680A30BEEF3BA0 -:101AE000F1177712BE6F93DFFAEE23145755A92C26 -:101AF000CF016FCFAB1407259B02BCDE138B54F0D4 -:101B0000933F28BFF3418AB3E1E846C8D5D7899807 -:101B1000B0D3892A61F7D2231B390E189764E6B334 -:101B2000597144223CE68BD9792791678A58EE6C2B -:101B300062E377380F7545B7C8A3466256BE490EB3 -:101B400026592F6F083C48F66F2A5E477CBCE68C0E -:101B5000335EBEC2152FBBF351FF1BB5F21156DE2B -:101B6000C9D6CB626BCC44B3E5A757FAD2420F7B00 -:101B70002AB5FAB9F6FDCF167E9EEAF5F33DB21707 -:101B80007B35EE179B6FEF2E433A2FF786F9F9C797 -:101B9000561F9672BF1B5979AB5F677F321D26BAFD -:101BA0006E3FE2D68BA16881E33CB1D759D4D226EF -:101BB000EEDF9D618F0C6B82D3ED7C36C254301703 -:101BC000EF677AC53DB7A7AC759EA075FA284F267A -:101BD000D6F76CAFCEED73BD75DC6EEA00510FB079 -:101BE000FDC355E81F900FD12AD1277F40F22F2D3A -:101BF000BF93F364BEB0A291BDFBAB4633528E7F60 -:101C00009828EAF9C55DE4F72B82AC8FEE7DADE94B -:101C1000F0E4DDD7E6961DEC77CEE23CC47FF433EA -:101C200077B31F42BFC0F36E54EFE07598E897D8C2 -:101C30002FF47CED76F60B5E203D77FB81D2A4B0CD -:101C4000EF842EF277F63DA159BF80F3A4719EA7D1 -:101C5000D0AF537F00FD00CD33D0F2FA9FD3BCEF5D -:101C6000BD5FC0F7A22636BDC27EE185B3E8B32FC3 -:101C7000A35FB0EDF0B5139123B9F17C56CEEB6FB5 -:101C80003F26F8A181E0EB86789E38F162E50CE60C -:101C900085E198B4327D87A83BAACC8779EB8E4941 -:101CA0008F416981BE492566D51D81EA8E76FD3159 -:101CB000A7EE58E0AC3BAAE914E39BB45577BC6DA2 -:101CC000ADA83BAA05D3C1EC3AEC7A633F3DAACC60 -:101CD000D6E7EFEC48ECEA68CAD6197549D4C15F7B -:101CE0008A985FA6E7505ECAE7BFBB4E69D723114B -:101CF000DE49899CFA66033EF79766EB5FEE7AA6AB -:101D00007D2FA3419D3E328C7CE9BBC3CFF8C15EE1 -:101D10005FDFA37FF26AA23C7B1FC0AE77DAF54C8F -:101D2000BBEE89EB1ECB5D373C0EEC77E031FF61FB -:101D30003ADFDCEBFD5E24717F47459E755F607D79 -:101D4000711D58F41177913DBF66F1D11EF7906572 -:101D50008FCB5591DF866295E39DB687822013CEA7 -:101D60002E528F905D6C81E90EE26F5F48E0BCD42B -:101D7000012FFBC9A31D3ACBAF4235F93E44C597AD -:101D800003C66E24933AAE1553FEA93B6A1EEDE0DE -:101D9000758CDEB29ED681B89DFCDDAF6BBF5ACE8E -:101DA000F57EBAF75442F19FB198F220CF77E4BFA5 -:101DB000AFD4BAF8CC7A9EB7C803149FA502C6B3B5 -:101DC0007CAFF80985E9752309B391EF2F45D5520A -:101DD000A223EEA7F6054FB2BC5A6B7D2B38AF5746 -:101DE000943F0E7CA643C4AD6B91968A743ED39605 -:101DF000F801AD9B72A561D66311DF3D4F7E52F8AD -:101E0000AF7B3CABB279B01239F13C8D87A39242E3 -:101E1000E7A3CFD21B3B4E7CBBCD7C81E48EF2305E -:101E2000697EFB1E903DFF4B961C921DE68B34EEA7 -:101E3000756B9E062D19213B6C48A03E486C3FAE49 -:101E40003ABCD00BB7BEDAFA365B87B7F450D2444F -:101E5000BD16F5EA755EEF93FA718F44F5F6C4E1AD -:101E600061FAF612EBDD57B69B6FD2BA4BDAE2FF9E -:101E70004E747FBDEB76BE177CA1F7385A17F784F6 -:101E8000A98E3F1010B8F9E188E1F0778B3A857C94 -:101E900016750ABC742DEACC14DF2F35F8DE37C076 -:101EA000DD8CA36DFF34DA9BF8FEA9DAECF7A95EAE -:101EB00098A47AD07CEBF0EEDBC179DDBEAA363F88 -:101EC000F91FF46F25D41FA832C3B9EB4815093D9B -:101ED0004F2E12790BCAA72573EE939776CABC9F33 -:101EE000F62AC890EEF882A2EEE643C3D5F1FCF1E3 -:101EF00099CD7CBF189F4F528AE18A4E5DC4E5E5BB -:101F00000698146F56C581ECDBA765BFA73A6A7BBC -:101F1000550FDFB79C8F8E1CB6BF4FF0F737766A30 -:101F20004C572DF738F200E7E39B9B2FFDC4B7DA3F -:101F3000F9F9A65E30DF84DDB9F9B5CAE2D7D3A1DD -:101F40002FF2FEE08376B6339F86FBC47675A7F04A -:101F50002F72D0844411F9A8382248CAB3F700D5AB -:101F6000A16D3ECB9AE0B3ACF5F077BE2A0312D751 -:101F7000115F12CC17371FD04F00F9891F3D7AA887 -:101F80009CF0692BF6C3C27F800FDB073A845C6C40 -:101F90003B5D073F0D8AFCB7F3BC70FB53BB7DD89C -:101FA000CA3FBB9F4B5D01E13F7470F0BDC8FAFDB5 -:101FB000C291C146C607787E26E95E4C67656D0111 -:101FC000F52F771DD15D3F74D709DDF5C1ACDE98E3 -:101FD0007E5AE73BDAC9E4C7F3E88BDD0E5BF6D641 -:101FE000DFEBCF6B77C368EF24BF8116334975A34E -:101FF000BDA1E930EBCDF13719172BCFCB06E14B63 -:10200000451172EE5C34CD72EC6A3681EA4DC3BD87 -:102010001BBE9D4BF781B6C4573A514F0AB5499341 -:10202000E8042193A4F3676D99D9930F370D587E77 -:10203000E4EDB6F86EFA8EAEAD93FC4F45CC3DD4D0 -:10204000BF50BF359F3D2936EF2EDA9E4E0A7B6A80 -:10205000DEC1F63452D5C3386BE4A73221A92C8EE9 -:10206000B4EC69A4E534DBBB6D5769DBFF340BBB13 -:10207000A03C029DDFC55526FB8D6F5AF6A4A09D9E -:10208000903DF92C7B2AD6B2E3293FDE4E7CC6E791 -:102090004AD5347F57DC6CD91FD95390EE0F03E338 -:1020A0008001B43BCA8BB8EDABB5469C9B8FB7257E -:1020B0001EEE247CB1683DE7E507AAFEB38CF18BE8 -:1020C000A5FF59BCDBC8E7F9D9418F41F6D04000E4 -:1020D000BA316B07F6BE57CFC89041D1AC9991B8D1 -:1020E000BD71A690DBD69900B7E64C19B79199104F -:1020F000B76D335772DB3E53C96D7406EDE07AB4A9 -:1021000087996A6E3B67AEE5B66B6619B7B199EB16 -:10211000795CF7CC0A6ED7CE7C94DB9B665AC43CC4 -:1021200075625F79EC81CA6097C11E8C2414911D81 -:102130007CE655F6EF9ACA779452A1555C27F229AE -:10214000D36C0F479A85BFEF0A0A39B9EDE1EDB6B6 -:10215000C4AFF2D9C32CBE554023FEAB60FDB9F02D -:1021600003E29FDFD0F736EE55C326EB19E293D397 -:1021700024CF4BC509B33873B1CA78D4C699238B21 -:102180001067566771E6408B88CB52077C1CBF6D89 -:1021900095C4FDB22BDB13FFC5F609224F94B8C5D9 -:1021A000AF116E4E853AC341CAEBED9581F20588B9 -:1021B000433EE0752A71719FF502EDF95444F87DB4 -:1021C0007B7C039CF4F45C048EF935FDB3657EBF23 -:1021D000507AA9E7ACB75DF8054DF8855455CF2086 -:1021E000D7A55D7EC13E67911F0EBFB0B4CBF20B89 -:1021F000969D975689F3B294FC02F2675997ED17B2 -:102200009CE7AC62E390988D432CBF1013DF216EE6 -:10221000779CB3286E3FE4E062D4A3E55D79700853 -:102220009FE739E75C5F4D6D847E4B103A03115296 -:10223000CFE2197DAD91E7DC49698D6C07C79576D2 -:10224000C8CDAF5CB49D85EC73C7E473C73DCEB613 -:10225000B781E3DD629FD639741CF76FE6D85B97D0 -:1022600026CE233C7F6EA27DBAEDAD75B19988E78D -:1022700059E727BB04DEFFF11A0BF722AE34828C3C -:10228000EFF3E2864F92FC9AC4EF341E43FFD31162 -:102290004BA6149DEDFC9334EFEAE8944C79A01B17 -:1022A0009B475FA69208DAE9A7BA9A2EDD4E9BDB20 -:1022B000AC7ADFCE3271D9D96ACFA7FF362EB2ED14 -:1022C000C03DEEE16A73433E7E3C63F1A36FD0D321 -:1022D0004D17FE6CBD38AE2C65FC93C7DF9AC66502 -:1022E000F1B717863F8EE33948723F07FE18CE27B5 -:1022F000FFF9F0C778D72CFE182339B5D60BFCF1BF -:102300004C179C33BEB9645C1139C97CBB545CF179 -:1023100050D7B971C5B7BB84DF54B469F61FC597F0 -:10232000882BDC7E02F1C33F317F0C71EEDABF37C0 -:10233000E10B9439E717FA99EFD338C20D7479ECB1 -:1023400048B02D29B11DC49FA0E7A3E612D6A3CBA8 -:10235000650F88137FD895D33F9F5D5CF0B8C94D5A -:102360009C07B4EB99BF0F1437507E64A75FB45F2E -:102370002A283E42ED58AFC843EFB7F27E635EE0D5 -:10238000FA41BF54601C91E8BBC569916FEF594E8B -:1023900079CFDF76D9BF97ECB9817F77037FEDA83E -:1023A0009BCEBF2E71CF97487DC8F7C1AB34CEA36B -:1023B0005B7CA174109DD343CBFC8C03873A8E1EAB -:1023C000BA93F2321D220F860A51FD713A7F11D65F -:1023D00034E79C0B3228A7293F3F4877DB19746C00 -:1023E00010F7A035F1BE348AF17B6EDDCEB8DBD1BB -:1023F000072B5F6AFF3EB070CD7ADB4E988E6D275B -:102400008545939A96E36F067B9DBFFF76B772ED85 -:102410007D71BA9B3C5AEFE1FAC5BE1A2540F5948E -:102420007D7522CB3E5CE389E5AB8F5F1B931C7906 -:102430006DBBBE5D1011EB9A6FBE01D77A7C7ADC62 -:10244000243D1DD6D371FE1D725DB994CCC93B7B72 -:10245000AD79862423D38ACC1C2A12E785AF2A09BA -:102460001EC203A1EDD7138FFD553D703A48F737D3 -:1024700092F006B6A1523591CEE38796C7841F1A13 -:10248000F24EC6588ED77938DF8B982A6F9E6C61D2 -:102490004CF8E9E19A23BCBE24F285EA55EE7101BD -:1024A0006B5C813ACAF58E7DB5DFD4695FFBE807C6 -:1024B0003757A07CBBFFFBC1DD41D2DFBB394F33B7 -:1024C00046F91AF4A705D71C8BB521DDFD372A1A6A -:1024D000EDA343AEDA4DEB1A8D82C17500975E9481 -:1024E000AC51025C2F353D7C07D4AD2705C554198E -:1024F000213D9CF20BFD107A16B4F4E68021EA3EF1 -:1025000007A2A27E65CB2FE77D80EAD267A30AC728 -:102510002576FD8A6A3DF970DC7ECB2EFB2DBB440F -:102520009CCA7587D9F78B337CEEEC6FC984E99C24 -:1025300029D2FC468CE81E75AE6B6FD39403971CB2 -:1025400058F1A2DFBA8CEF5A9FD02FE5A95FB03FB8 -:102550002D52A6F8BC2A5A7D8AFDE97DD67ABA9A10 -:1025600081F759BCD2F2DB713322E8FDA5C30F48D5 -:10257000D7BC6A7AE95CB855DC49F0368BBA5D8124 -:102580000A4606F97CA022C8F79ACA565A75BA7547 -:10259000E25E857D2FBC22EEBC1716829CDF0954BB -:1025A0008B7B59B97D90379EF3FEDBCE5F1E7EEEAE -:1025B000440EBD2FC59CF7C7CFF7FDEF7BD3CF9D52 -:1025C00040FD1A35CE6D87B6BCEEED6D667ED9FA4C -:1025D00068EB6788B6D838FFF763A178DEFACC31AC -:1025E000CB0ECEE7CFCA7CF11EC245F7AD893BF0DA -:1025F000D103967D3E1013F94F75F119CEAB1DB482 -:10260000EE5F1D0CC086EFE499371353797C56FFBB -:102610009D38C2D69FB97C380F8E5813B5E2104F43 -:1026200080CEF151A3ED59AA47BEABA93AE4F80117 -:10263000779EDDC61105DD76BEEF3DC65125C12969 -:10264000A1B72B9D71871B070C2BE90D64E7C375A0 -:10265000AAED9FD88F5CFD6CE1D7938C939252EEDC -:10266000B9B93F7307D30DB9F2EC50EEFCDDCAFEE9 -:1026700018F07A42FA9929BA671E8A29E2DED6A8AA -:1026800009B9F76EC63CBF9C3965FDFB031B77B0EB -:102690003EEF9FE2DFD3C0172077FEBD1FDBCCBF2C -:1026A0002F399FDC67FD7A5875E4DF2ED62EFE2584 -:1026B00066D5B7031020BB380BF770DD1D46638E5F -:1026C000F3882B100BF8C8167FB84D6595757449C3 -:1026D000597B817651D73F9B98F58B0A7D67589F30 -:1026E00055D2AD0A8AC721C3BF53B4EF959E855F0B -:1026F000F2BCC9A7246916675D89E13EFDFE712918 -:10270000A99CE6A1D6BDFE2560F0F31A88737B353F -:10271000F4705B07A3DC5E0393DCD6C314B70D70C3 -:1027200086DB15A0CB34C9F560CAC0573513DCBFB2 -:102730000192DCB640E2FD53B8FEFE8AED2B385E16 -:10274000B4FD87C5279BCF79EC9D71A4CD0F9BEF7E -:10275000FF48CEFA02EC3915127EB87D6586F53C4D -:10276000181438D98EAF6D3AF3E1DECB85CF6C5CAF -:10277000F97FE7ADB141E048000000000000000033 -:1027800000000018000000000000000000000040F1 -:102790000000000000000000000000280000000011 -:1027A0000000000000000010000000000000000019 -:1027B00000000020000000000000000000000010E9 -:1027C0000000000000000000000000080000000001 -:1027D00000000000000000000000000000000000F9 -:1027E00000000000000000000000000000000000E9 -:1027F00000000000000000000000000000000000D9 -:1028000000000000000000000000000000000000C8 -:1028100000000000000000000000000000000000B8 -:1028200000000000000000000000000000000000A8 -:102830000000000000000000000000000000000098 -:102840000000000000000000000000000000000088 -:102850000000000000000000000000000000000078 -:102860000000000000000000000000000000000068 -:102870000000000000000000000000000000000058 -:102880000000000000000000000000000000000048 -:102890000000000000000000000000000000000038 -:1028A0000000000000000000000000000000000028 -:1028B0000000000000000000000000000000000018 -:1028C0000000000000000000000000000000000008 -:1028D00000000000000000000000000000000000F8 -:1028E0000000000000000000000090000010000048 -:1028F0000000000800009008001000000000000226 -:1029000000009000001000000000001000009DA8D2 -:10291000000000000000000880000000000000002F -:102920000000000080000000000000000000000027 -:10293000800000000000000000000000000091A0E6 -:102940000000000000000008000093C00001000427 -:1029500000000001000093C8000000000000000219 -:10296000000093D00000000000000008000093D495 -:102970000000000000000002000094980000000029 -:1029800000000008000093D80008000000000008C4 -:1029900000009B3800400000000000400000941838 -:1029A0000008000000000008000094580008000023 -:1029B00000000008000094A800C800000000009873 -:1029C000000096380098000000000028000096786B -:1029D00000980000000000280000C0000540003002 -:1029E000000005400000CB200008000000000001AE -:1029F0000000CB21000800000000000100002008BA -:102A00000010000000000010000020000000000086 -:102A10000000000800009D600008000000000002A7 -:102A200000009DA000000000000000010000000068 -:102A30000000000000000000000000000000000096 -:102A40000000000000000000000000000000000086 -:102A50008000000000000000000000008000000076 -:102A600000000000000000008000000000000000E6 -:102A700000000000800000000000000000000000D6 -:102A80008000000000000000000000008000000046 -:102A900000000000000000008000000000000000B6 -:102AA00000000000800000000000000000000000A6 -:102AB0008000000000000000000000008000000016 -:102AC0000000000000000000800000000000000086 -:102AD0000000000080000000000000000000000076 -:102AE0008000000000000000000000000000000066 -:102AF00000000000000000000000000000000000D6 -:102B000000000000000000000000000000000000C5 -:102B100000000000000000000000000000000000B5 -:102B20000000000000000000800000000000000025 -:102B30000000000080000000000000000000000015 -:102B40008000000000000000000000000000000005 -:102B500000000000000000008000000000000000F5 -:102B600000000000800000000000000000000000E5 -:102B700080000000000000000000000000000000D5 -:102B80000000000000000000000000000000000045 -:102B90000000000000000000000000000000000035 -:102BA0000000000000000000000000000000000025 -:102BB0000000000000000000000000000000000015 -:102BC00000000000000012C800800000000000802B -:102BD0000000000100000000000000000000A00054 -:102BE000071000000000071000001EC800000000D1 -:102BF000000000080000AEC000080000000000084F -:102C00000000AE4000080000000000080000AE8098 -:102C1000000800000000000800002008001000006C -:102C2000000000100000200000000000000000086C -:102C30000000A01007100040000000400000AF405E -:102C400000080000000000010000AF410008000083 -:102C50000000000100001ED0000000000000000184 -:102C600000001ED8000000000000000200001EDA74 -:102C70000000000000000002000012B00008000088 -:102C800000000008800000000000000000000000BC -:102C90008000000000000000000000008000000034 -:102CA00000000000000000008000000000000000A4 -:102CB0000000000080000000000000000000000094 -:102CC0008000000000000000000000008000000004 -:102CD0000000000000000000800000000000000074 -:102CE0000000000080000000000000000000000064 -:102CF00000000000000000000000000000000000D4 -:102D000000000000000000000000000000000000C3 -:102D100000000000000000000000000000000000B3 -:102D20000000000000000000000000008000000023 -:102D30000000000000000000800000000000000013 -:102D40000000000000000000000000000000000083 -:102D50008000000000000000000000008000000073 -:102D600000000000000000008000000000000000E3 -:102D700000000000800000000000000000000000D3 -:102D80000000B00000180000000000180000B300B0 -:102D900000400000000000400000B30000400002BE -:102DA000000000010000B30100400002000000002C -:102DB0000000800000400000000000408000000093 -:102DC000000000000000000000008000000800403B -:102DD000000000040000800400080040000000041F -:102DE0000000BB0000280000000000280000BC40DC -:102DF00000100000000000100000880000800000AB -:102E00000000008000008800000800800000000230 -:102E100000008C00002000000000002000002008BE -:102E20000010000000000010000020000000000062 -:102E30000000000800001108000800000000000861 -:102E4000000011680008000000000008000011A840 -:102E500000080000000000080000127000080000D8 -:102E600000000001000012710008000000000001D5 -:102E700000008D000010000400000004000013207A -:102E80000030001800000010000013280030001867 -:102E900000000002800000000000000000000000B0 -:102EA000800000000000000000000000000011E8A9 -:102EB0000000000000000001800000000000000091 -:102EC0000000000080000000000000000000000082 -:102ED00080000000000000000000000080000000F2 -:102EE0000000000000000000800000000000000062 -:102EF0000000000080000000000000000000000052 -:102F000000000000000000000000000000000000C1 -:102F100000000000000000000000000000000000B1 -:102F200000000000000000000000000000000000A1 -:102F30008000000000000000000000008000000091 -:102F40000000000000000000000000000000000081 -:102F500000000000000083080080000000000080E6 -:102F60000000000100000000000000000000200838 -:102F70000010000000000010000020000000000011 -:102F80000000000800008D1000080000000000088C -:102F900000008D7000080000000000080000845050 -:102FA000046000280000046000008EA000080000FB -:102FB0000000000100008EA10008000000000001D8 -:102FC0000000840800080000000000080000844899 -:102FD000000000000000000100008DF40008000067 -:102FE0000000000200008DF6000800000000000252 -:102FF00000008E04001000000000000480000000AB -:103000000000000000000000800000000000000040 -:103010000000000080000000000000000000000030 -:1030200000000000000000000000000000000000A0 -:103030000000000000000000000000000000000090 -:103040000000000000000000000000000000000080 -:103050008000000000000000000000008000000070 -:103060000000000000000000000000000000000060 -:1030700000000000800000000000000000000000D0 -:103080008000000000000000000000008000000040 -:1030900000000000000000008000000000000000B0 -:1030A00000000000000030000040000000000008A8 -:1030B00000003008004000000000002800003390AD -:1030C00001C00010000000080000320000200000D5 -:1030D0000000002000003720000000000000000871 -:1030E0000000102006200038000000080000A000AA -:1030F000000000000000200000003EA900000000C9 -:103100000000000100003EC80000000000000002B6 -:1031100000001C4000E000080000000880000000E3 -:103120000000000000000000000040000008000057 -:103130000000000100004001000800000000000144 -:103140000000404000080004000000020000406051 -:103150000008000400000004000040000008000017 -:10316000000000040000400400080000000000040B -:10317000000040400000000000000008000040483F -:1031800000000000000000080000800000000000B7 -:103190000000001000005040000100040000000189 -:1031A0000000500000000000000000200000500857 -:1031B00000100000000000040000500C001000008F -:1031C00000000001000052C70000000000000001E4 -:1031D000000052C6000000000000000100003000A6 -:1031E0000030001800000004000030040030001817 -:1031F0000000000400003008003000180000000249 -:103200000000300A00300018000000020000300CFE -:1032100000300018000000010000300D00300018E0 -:10322000000000010000300E003000180000000116 -:1032300000003010003000180000000400003014BE -:103240000030001800000004000050000100008061 -:103250000008000400005004010000800008000481 -:103260000000000A0000000000000000000050689C -:103270000100008000000001000050690100008092 -:10328000000000010000506C0100008000000002FE -:103290000000506E0100008000000002000050702D -:1032A0000100008000000004000050740100008054 -:1032B00000000004000050660100008000000002D1 -:1032C0000000506401000080000000010000506018 -:1032D0000100008000000002000050620100008038 -:1032E00000000002000050500100008000000004B7 -:1032F00000005054010000800000000400005058FD -:1033000001000080000000040000505C010000800B -:10331000000000040000507C01000080000000015B -:103320000000507D010000800000000100004018F6 -:103330000010000000000004000040900010000099 -:10334000000000040000409800100000000000048D -:1033500000004110000000000000000200004112C7 -:103360000000000000000002000041140000000006 -:1033700000000002000041160000000000000002F2 -:1033800000006040000800000000000200006042F1 -:103390000008000000000002000060440008000077 -:1033A0000000000400006080000800000000000829 -:1033B000000060C00040000800000008000060003D -:1033C0000008000000000002000060020008000089 -:1033D000000000010000600400080000000000027E -:1033E0000000634000080000000000080000638047 -:1033F00000080000000000040000638400080000D2 -:1034000000000001000063C000080000000000028E -:10341000000063C400080000000000020000640017 -:103420000008000000000004000070000010000010 -:103430000000000400007004001000000000000400 -:103440000000700800100000000000040000700080 -:1034500000080000000000020000700200080000E8 -:1034600000000001000070040008000000000002DD -:1034700000007040000800000000000200007044DE -:103480000008000000000002000070460008000074 -:10349000000000020000764800080000000000085C -:1034A000000070800008000000000002000070842E -:1034B00000080000000000020000768800080000FC -:1034C000000000080000804000080000000000012B -:1034D0000000804100080000000000010000804260 -:1034E0000008000000000001000080430008000008 -:1034F0000000000100008000000800000000000241 -:1035000000008002000800000000000100008004AC -:103510000008000000000002000080C00008000059 -:1035200000000002000080C200080000000000024D -:10353000000080C40008000000000002000080803D -:103540000008000000000001000080810008000069 -:10355000000000010000808200080000000000015F -:10356000000080830008000000000001000080844B -:103570000008000000000001000080850008000035 -:10358000000000010000808600080000000000012B -:10359000000060000008000000000002000060025F -:1035A00000080000000000010000600400080000A6 -:1035B000000000020000604200C00018000000028D -:1035C0000000604000C00018000000020000604CD5 -:1035D00000C00018000000080000604400C000188F -:1035E000000000080000605700C000180000000143 -:1035F0000000605400C00018000000020000605687 -:1036000000C0001800000001000066400008000033 -:1036100000000008000066800008000000000008AC -:10362000000066C000080000000000080000D94249 -:1036300000180000000000020000DE400000000052 -:10364000000000000000E000000000000000000496 -:103650000000DD4000000000000000040000DD4428 -:1036600000000000000000040000DD480000000031 -:10367000000000040000DD4C000000000000000419 -:103680000000DD5000000000000000040000DD54D8 -:1036900000000000000000040000DD5800000000F1 -:1036A000000000040000DD400000000000000020D9 -:1036B0000000DA0000000000000000040000DA0052 -:1036C00000000000000000680000BB600000000077 -:1036D000000000000000D000000000000000000416 -:1036E0000000B0C000000000000000040000B0C4F2 -:1036F00000000000000000040000B0C8000000004E -:10370000000000040000B0C0000000000000001035 -:103710000000D6B000000000000000040000D6B495 -:1037200000000000000000040000D6B80000000007 -:10373000000000040000D6BC0000000000000004EF -:103740000000D6B000000000000000100000D348C8 -:1037500000000000000000080000D3580000000036 -:1037600000000080000000100000000000000000C9 -:103770000000D35800000000000000080000000016 -:08378000060205000000000034 -:00000001FF diff --git a/firmware/bnx2x/bnx2x-e1h-6.2.9.0.fw.ihex b/firmware/bnx2x/bnx2x-e1h-6.2.9.0.fw.ihex new file mode 100644 index 000000000000..ba1ce53df1d8 --- /dev/null +++ b/firmware/bnx2x/bnx2x-e1h-6.2.9.0.fw.ihex @@ -0,0 +1,13192 @@ +:1000000000004F48000000680000070C00004FB8D7 +:1000100000001ED4000056C800000094000075A027 +:1000200000009F4C00007638000000CC00011588CD +:100030000000DC5800011658000000940001F2B8DE +:100040000000400C0001F350000000A400023360E7 +:100050000000F4240002340800000FFC00032830E4 +:100060000000000400033830020400480000000FC4 +:1000700002040054000000450204005C0000000679 +:100080000204007000000004020400780000000078 +:100090000204007C121700000204008022170000F6 +:1000A00002040084321700000604008800000005E6 +:1000B0000204009C12150000020400A0221500009A +:1000C000020400A432150000060400A80000000489 +:1000D000020400B802100000020400BC001000007E +:1000E000020400C010100000020400C42010000030 +:1000F000020400C830100000020400CC40100000D0 +:10010000060400D000000003020400DC0010000020 +:10011000020400E012140000020400E422140000B3 +:10012000020400E832140000020400EC4214000053 +:10013000060400F000000003010401240000000098 +:1001400001040128000000000104012C000000004F +:100150000104013000000000020401D00000890603 +:1001600002040004000000FF02040008000000FF79 +:100170000204000C000000FF02040010000000FF59 +:10018000020400140000007F02040018000000FFB9 +:100190000204001C000000FF02040020000000FF19 +:1001A000020400240000003E0204002800000000B9 +:1001B0000204002C0000003F020400300000003F59 +:1001C000020400340000003F020400380000003F39 +:1001D0000204003C0000003F020400400000003F19 +:1001E000020400440000003F020404CC00000001AF +:1001F00002042008000002110204200C000002008A +:10020000020420100000020402042014000002195D +:100210000204201C0000FFFF020420200000FFFF5A +:10022000020420240000FFFF020420280000FFFF3A +:1002300002042038000000200604203C0000001FBB +:10024000020420B800000001060420BC0000005F8A +:100250000204223807FFFFFF0204223C0000003F97 +:100260000204224007FFFFFF020422440000000FA7 +:1002700001042248000000000104224C000000009C +:10028000010422500000000001042254000000007C +:1002900001042258000000000104225C000000005C +:1002A000010422600000000001042264000000003C +:1002B00001042268000000000104226C000000001C +:1002C00001042270000000000104227400000000FC +:1002D00001042278000000000104227C00000000DC +:1002E0000C042000000003E80A04200000000001C4 +:1002F0000B0420000000000A0605400000000D006D +:100300000205004400000020020500480000003201 +:10031000020500900215002002050094021500203D +:1003200002050098000000300205009C0810000043 +:10033000020500A000000033020500A40000003008 +:10034000020500A800000031020500AC0000000218 +:10035000020500B000000005020500B40000000620 +:10036000020500B800000002020500BC0000000207 +:10037000020500C000000000020500C400000005E6 +:10038000020500C800000002020500CC00000002C7 +:10039000020500D000000002020500D400000001A8 +:1003A00002050114000000010205011C000000010B +:1003B0000205012000000002020502040000000105 +:1003C0000205020C0000004002050210000000407F +:1003D0000205021C0000002002050220000000139C +:1003E0000205022400000020060502400000000A69 +:1003F00004050280002000000205005000000007F4 +:10040000020500540000000702050058000000002B +:100410000205005C00000008020500600000000109 +:100420000605006400000003020500D80000000675 +:1004300002050004000000010205000800000001A0 +:100440000205000C00000001020500100000000180 +:100450000205001400000001020500180000000160 +:100460000205001C00000001020500200000000140 +:100470000205002400000001020500280000000120 +:100480000205002C00000001020500300000000100 +:1004900002050034000000010205003800000001E0 +:1004A0000205003C000000010205004000000001C0 +:1004B000020500E00000000D020500E80000000059 +:1004C000020500F000000000020500F80000000036 +:1004D000020500E40000002D020500EC00000020F1 +:1004E000020500F400000020020500FC00000020CE +:1004F000020500E00000001D020500E800000010F9 +:10050000020500F000000010020500F800000010D5 +:10051000020500E40000003D020500EC0000003090 +:10052000020500F400000030020500FC000000306D +:10053000020500E00000004D020500E80000004058 +:10054000020500F000000040020500F80000004035 +:10055000020500E40000006D020500EC00000060F0 +:10056000020500F400000060020500FC00000060CD +:10057000020500E00000005D020500E800000050F8 +:10058000020500F000000050020500F800000050D5 +:10059000020500E40000007D020500EC0000007090 +:1005A000020500F400000070020500FC000000706D +:1005B0000406100002000020020600DC000000011A +:1005C000010600D80000000004060200000302201B +:1005D000020600DC00000000010600B80000000078 +:1005E000010600C8000000000206016C00000000C7 +:1005F000010600BC00000000010600CC0000000065 +:1006000002060170000000000718040000910000BD +:10061000081807D800050223071C00002BF700006C +:10062000071C80002DD10AFE071D00002F461673FF +:10063000071D800016342245081DB13049DA022515 +:100640000118000000000000011800040000000074 +:1006500001180008000000000118000C0000000054 +:100660000118001000000000011800140000000034 +:1006700002180020000000010218002400000002FF +:1006800002180028000000030218002C00000000DF +:1006900002180030000000040218003400000001BD +:1006A00002180038000000000218003C00000001A1 +:1006B000021800400000000402180044000000007E +:1006C00002180048000000010218004C000000035E +:1006D0000218005000000000021800540000000141 +:1006E00002180058000000040218005C000000001E +:1006F00002180060000000010218006400000003FE +:1007000002180068000000000218006C00000001E0 +:1007100002180070000000040218007400000000BD +:1007200002180078000000040218007C000000039A +:100730000618008000000002021800A400003FFF1D +:10074000021800A8000003FF0218022400000000A5 +:1007500002180234000000000218024C00000000E1 +:10076000021802E4000000FF061810000000040058 +:10077000021B8BC000000001021B8000000000343F +:10078000021B804000000018021B80800000000C4B +:10079000021B80C0000000200C1B83000007A1206A +:1007A0000A1B8300000001380B1B83000000138824 +:1007B0000A1B8340000000000C1B8340000001F472 +:1007C0000B1B834000000005021B83800007A12053 +:1007D000021B83C0000001F4021B14800000000112 +:1007E0000A1B148000000000061A1000000003B36A +:1007F000041A1ECC00010227061A1ED000000008B1 +:10080000061A2008000000C8061A20000000000296 +:10081000041AAF4000100228061A3718000000041E +:10082000061A371000000002061A500000000002ED +:10083000061A500800000004061A501800000004B0 +:10084000061A502800000004061A50380000000460 +:10085000061A504800000004061A50580000000410 +:10086000061A506800000004061A507800000002C2 +:10087000041A52C000020238061A40500000000656 +:10088000041A40680002023A041A40400004023C84 +:10089000041A800000010240061A800400000003D0 +:1008A000041A801000010241061A8014000000039F +:1008B000041A802000010242061A8024000000036E +:1008C000041A803000010243061A8034000000033D +:1008D000041A804000010244061A8044000000030C +:1008E000041A805000010245061A805400000003DB +:1008F000041A806000010246061A806400000003AA +:10090000041A807000010247061A80740000000378 +:10091000041A808000010248061A80840000000347 +:10092000041A809000010249061A80940000000316 +:10093000041A80A00001024A061A80A400000003E5 +:10094000041A80B00001024B061A80B400000003B4 +:10095000041A80C00001024C061A80C40000000383 +:10096000041A80D00001024D061A80D40000000352 +:10097000041A80E00001024E061A80E40000000321 +:10098000041A80F00001024F061A80F400000003F0 +:10099000041A810000010250061A810400000003BD +:1009A000041A811000010251061A8114000000038C +:1009B000041A812000010252061A8124000000035B +:1009C000041A813000010253061A8134000000032A +:1009D000041A814000010254061A814400000003F9 +:1009E000041A815000010255061A815400000003C8 +:1009F000041A816000010256061A81640000000397 +:100A0000041A817000010257061A81740000000365 +:100A1000041A818000010258061A81840000000334 +:100A2000041A819000010259061A81940000000303 +:100A3000041A81A00001025A061A81A400000003D2 +:100A4000041A81B00001025B061A81B400000003A1 +:100A5000041A81C00001025C061A81C40000000370 +:100A6000041A81D00001025D061A81D4000000033F +:100A7000041A81E00001025E061A81E4000000030E +:100A8000041A81F00001025F061A81F400000003DD +:100A9000041A820000010260061A820400000003AA +:100AA000041A821000010261061A82140000000379 +:100AB000041A822000010262061A82240000000348 +:100AC000041A823000010263061A82340000000317 +:100AD000041A824000010264061A824400000003E6 +:100AE000041A825000010265061A825400000003B5 +:100AF000041A826000010266061A82640000000384 +:100B0000041A827000010267061A82740000000352 +:100B1000041A828000010268061A82840000000321 +:100B2000041A829000010269061A829400000003F0 +:100B3000041A82A00001026A061A82A400000003BF +:100B4000041A82B00001026B061A82B4000000038E +:100B5000041A82C00001026C061A82C4000000035D +:100B6000041A82D00001026D061A82D4000000032C +:100B7000041A82E00001026E061A82E400000003FB +:100B8000041A82F00001026F061A82F400000003CA +:100B9000041A830000010270061A83040000000397 +:100BA000041A831000010271061A83140000000366 +:100BB000041A832000010272061A83240000000335 +:100BC000041A833000010273061A83340000000304 +:100BD000041A834000010274061A834400000003D3 +:100BE000041A835000010275061A835400000003A2 +:100BF000041A836000010276061A83640000000371 +:100C0000041A837000010277061A8374000000033F +:100C1000041A838000010278061A8384000000030E +:100C2000041A839000010279061A839400000003DD +:100C3000041A83A00001027A061A83A400000003AC +:100C4000041A83B00001027B061A83B4000000037B +:100C5000041A83C00001027C061A83C4000000034A +:100C6000041A83D00001027D061A83D40000000319 +:100C7000041A83E00001027E061A83E400000003E8 +:100C8000041A83F00001027F061A83F400000003B7 +:100C9000041A840000010280061A84040000000384 +:100CA000041A841000010281061A84140000000353 +:100CB000041A842000010282061A84240000000322 +:100CC000041A843000010283061A843400000003F1 +:100CD000041A844000010284061A844400000003C0 +:100CE000041A845000010285061A8454000000038F +:100CF000041A846000010286061A8464000000035E +:100D0000041A847000010287061A8474000000032C +:100D1000041A848000010288061A848400000003FB +:100D2000041A849000010289061A849400000003CA +:100D3000041A84A00001028A061A84A40000000399 +:100D4000041A84B00001028B061A84B40000000368 +:100D5000041A84C00001028C061A84C40000000337 +:100D6000041A84D00001028D061A84D40000000306 +:100D7000041A84E00001028E061A84E400000003D5 +:100D8000041A84F00001028F061A84F400000003A4 +:100D9000041A850000010290061A85040000000371 +:100DA000041A851000010291061A85140000000340 +:100DB000041A852000010292061A8524000000030F +:100DC000041A853000010293061A853400000003DE +:100DD000041A854000010294061A854400000003AD +:100DE000041A855000010295061A8554000000037C +:100DF000041A856000010296061A8564000000034B +:100E0000041A857000010297061A85740000000319 +:100E1000041A858000010298061A858400000003E8 +:100E2000041A859000010299061A859400000003B7 +:100E3000041A85A00001029A061A85A40000000386 +:100E4000041A85B00001029B061A85B40000000355 +:100E5000041A85C00001029C061A85C40000000324 +:100E6000041A85D00001029D061A85D400000003F3 +:100E7000041A85E00001029E061A85E400000003C2 +:100E8000041A85F00001029F061A85F40000000391 +:100E9000041A8600000102A0061A8604000000035E +:100EA000041A8610000102A1061A8614000000032D +:100EB000041A8620000102A2061A862400000003FC +:100EC000041A8630000102A3061A863400000003CB +:100ED000041A8640000102A4061A8644000000039A +:100EE000041A8650000102A5061A86540000000369 +:100EF000041A8660000102A6061A86640000000338 +:100F0000041A8670000102A7061A86740000000306 +:100F1000041A8680000102A8061A868400000003D5 +:100F2000041A8690000102A9061A869400000003A4 +:100F3000041A86A0000102AA061A86A40000000373 +:100F4000041A86B0000102AB061A86B40000000342 +:100F5000041A86C0000102AC061A86C40000000311 +:100F6000041A86D0000102AD061A86D400000003E0 +:100F7000041A86E0000102AE061A86E400000003AF +:100F8000041A86F0000102AF061A86F4000000037E +:100F9000041A8700000102B0061A8704000000034B +:100FA000041A8710000102B1061A8714000000031A +:100FB000041A8720000102B2061A872400000003E9 +:100FC000041A8730000102B3061A873400000003B8 +:100FD000041A8740000102B4061A87440000000387 +:100FE000041A8750000102B5061A87540000000356 +:100FF000041A8760000102B6061A87640000000325 +:10100000041A8770000102B7061A877400000003F3 +:10101000041A8780000102B8061A878400000003C2 +:10102000041A8790000102B9061A87940000000391 +:10103000041A87A0000102BA061A87A40000000360 +:10104000041A87B0000102BB061A87B4000000032F +:10105000041A87C0000102BC061A87C400000003FE +:10106000041A87D0000102BD061A87D400000003CD +:10107000041A87E0000102BE061A87E4000000039C +:10108000041A87F0000102BF061A87F4000000036B +:10109000041A8800000102C0061A88040000000338 +:1010A000041A8810000102C1061A88140000000307 +:1010B000041A8820000102C2061A882400000003D6 +:1010C000041A8830000102C3061A883400000003A5 +:1010D000041A8840000102C4061A88440000000374 +:1010E000041A8850000102C5061A88540000000343 +:1010F000041A8860000102C6061A88640000000312 +:10110000041A8870000102C7061A887400000003E0 +:10111000041A8880000102C8061A888400000003AF +:10112000041A8890000102C9061A8894000000037E +:10113000041A88A0000102CA061A88A4000000034D +:10114000041A88B0000102CB061A88B4000000031C +:10115000041A88C0000102CC061A88C400000003EB +:10116000041A88D0000102CD061A88D400000003BA +:10117000041A88E0000102CE061A88E40000000389 +:10118000041A88F0000102CF061A88F40000000358 +:10119000041A8900000102D0061A89040000000325 +:1011A000041A8910000102D1061A891400000003F4 +:1011B000041A8920000102D2061A892400000003C3 +:1011C000041A8930000102D3061A89340000000392 +:1011D000041A8940000102D4061A89440000000361 +:1011E000041A8950000102D5061A89540000000330 +:1011F000041A8960000102D6061A896400000003FF +:10120000041A8970000102D7061A897400000003CD +:10121000041A8980000102D8061A8984000000039C +:10122000041A8990000102D9061A8994000000036B +:10123000041A89A0000102DA061A89A4000000033A +:10124000041A89B0000102DB061A89B40000000309 +:10125000041A89C0000102DC061A89C400000003D8 +:10126000041A89D0000102DD061A89D400000003A7 +:10127000041A89E0000102DE061A89E40000000376 +:10128000041A89F0000102DF061A89F40000000345 +:10129000041A8A00000102E0061A8A040000000312 +:1012A000041A8A10000102E1061A8A1400000003E1 +:1012B000041A8A20000102E2061A8A2400000003B0 +:1012C000041A8A30000102E3061A8A34000000037F +:1012D000041A8A40000102E4061A8A44000000034E +:1012E000041A8A50000102E5061A8A54000000031D +:1012F000041A8A60000102E6061A8A6400000003EC +:10130000041A8A70000102E7061A8A7400000003BA +:10131000041A8A80000102E8061A8A840000000389 +:10132000041A8A90000102E9061A8A940000000358 +:10133000041A8AA0000102EA061A8AA40000000327 +:10134000041A8AB0000102EB061A8AB400000003F6 +:10135000041A8AC0000102EC061A8AC400000003C5 +:10136000041A8AD0000102ED061A8AD40000000394 +:10137000041A8AE0000102EE061A8AE40000000363 +:10138000041A8AF0000102EF061A8AF40000000332 +:10139000041A8B00000102F0061A8B0400000003FF +:1013A000041A8B10000102F1061A8B1400000003CE +:1013B000041A8B20000102F2061A8B24000000039D +:1013C000041A8B30000102F3061A8B34000000036C +:1013D000041A8B40000102F4061A8B44000000033B +:1013E000041A8B50000102F5061A8B54000000030A +:1013F000041A8B60000102F6061A8B6400000003D9 +:10140000041A8B70000102F7061A8B7400000003A7 +:10141000041A8B80000102F8061A8B840000000376 +:10142000041A8B90000102F9061A8B940000000345 +:10143000041A8BA0000102FA061A8BA40000000314 +:10144000041A8BB0000102FB061A8BB400000003E3 +:10145000041A8BC0000102FC061A8BC400000003B2 +:10146000041A8BD0000102FD061A8BD40000000381 +:10147000041A8BE0000102FE061A8BE40000000350 +:10148000041A8BF0000102FF061A8BF4000000031F +:10149000041A8C0000010300061A8C0400000003EB +:1014A000041A8C1000010301061A8C1400000003BA +:1014B000041A8C2000010302061A8C240000000389 +:1014C000041A8C3000010303061A8C340000000358 +:1014D000041A8C4000010304061A8C440000000327 +:1014E000041A8C5000010305061A8C5400000003F6 +:1014F000041A8C6000010306061A8C6400000003C5 +:10150000041A8C7000010307061A8C740000000393 +:10151000041A8C8000010308061A8C840000000362 +:10152000041A8C9000010309061A8C940000000331 +:10153000041A8CA00001030A061A8CA40000000300 +:10154000041A8CB00001030B061A8CB400000003CF +:10155000041A8CC00001030C061A8CC4000000039E +:10156000041A8CD00001030D061A8CD4000000036D +:10157000041A8CE00001030E061A8CE4000000033C +:10158000041A8CF00001030F061A8CF4000000030B +:10159000041A8D0000010310061A8D0400000003D8 +:1015A000041A8D1000010311061A8D1400000003A7 +:1015B000041A8D2000010312061A8D240000000376 +:1015C000041A8D3000010313061A8D340000000345 +:1015D000041A8D4000010314061A8D440000000314 +:1015E000041A8D5000010315061A8D5400000003E3 +:1015F000041A8D6000010316061A8D6400000003B2 +:10160000041A8D7000010317061A8D740000000380 +:10161000041A8D8000010318061A8D84000000034F +:10162000041A8D9000010319061A8D94000000031E +:10163000041A8DA00001031A061A8DA400000003ED +:10164000041A8DB00001031B061A8DB400000003BC +:10165000041A8DC00001031C061A8DC4000000038B +:10166000041A8DD00001031D061A8DD4000000035A +:10167000041A8DE00001031E061A8DE40000000329 +:10168000041A8DF00001031F061A8DF400000003F8 +:10169000041A8E0000010320061A8E0400000003C5 +:1016A000041A8E1000010321061A8E140000000394 +:1016B000041A8E2000010322061A8E240000000363 +:1016C000041A8E3000010323061A8E340000000332 +:1016D000041A8E4000010324061A8E440000000301 +:1016E000041A8E5000010325061A8E5400000003D0 +:1016F000041A8E6000010326061A8E64000000039F +:10170000041A8E7000010327061A8E74000000036D +:10171000041A8E8000010328061A8E84000000033C +:10172000041A8E9000010329061A8E94000000030B +:10173000041A8EA00001032A061A8EA400000003DA +:10174000041A8EB00001032B061A8EB400000003A9 +:10175000041A8EC00001032C061A8EC40000000378 +:10176000041A8ED00001032D061A8ED40000000347 +:10177000041A8EE00001032E061A8EE40000000316 +:10178000041A8EF00001032F061A8EF400000003E5 +:10179000041A8F0000010330061A8F0400000003B2 +:1017A000041A8F1000010331061A8F140000000381 +:1017B000041A8F2000010332061A8F240000000350 +:1017C000041A8F3000010333061A8F34000000031F +:1017D000041A8F4000010334061A8F4400000003EE +:1017E000041A8F5000010335061A8F5400000003BD +:1017F000041A8F6000010336061A8F64000000038C +:10180000041A8F7000010337061A8F74000000035A +:10181000041A8F8000010338061A8F840000000329 +:10182000041A8F9000010339061A8F9400000003F8 +:10183000041A8FA00001033A061A8FA400000003C7 +:10184000041A8FB00001033B061A8FB40000000396 +:10185000041A8FC00001033C061A8FC40000000365 +:10186000041A8FD00001033D061A8FD40000000334 +:10187000041A8FE00001033E061A8FE400000007FF +:10188000041A62C00020033F061AD0000000007254 +:10189000061AD24800000010061AD6B00000002038 +:1018A000061AD47000000090061AD46800000002E6 +:1018B000061AA000000001C4061A30000000001043 +:1018C000061A308000000010061A310000000010D7 +:1018D000061A318000000010061A330000000012C2 +:1018E000061A339000000070061AD4580000000257 +:1018F000061AD34800000002061AD3580000002040 +:10190000061AA710000001C4061A3040000000109B +:10191000061A30C000000010061A31400000001006 +:10192000061A31C000000010061A334800000012E9 +:10193000061A355000000070061AD460000000023C +:10194000061AD35000000002061AD3D80000002067 +:10195000021AAE2000000000061A5000000000022B +:10196000061A508000000012041A40000002035FB3 +:10197000041A63C000020361061A7000000000042C +:10198000061A320000000008021AAE24000000000F +:10199000061A501000000002061A50C8000000127B +:1019A000041A400800020363041A63C800020365B6 +:1019B000061A701000000004061A32200000000809 +:1019C000021AAE2800000000061A50200000000293 +:1019D000061A511000000012041A4010000203679A +:1019E000041A63D000020369061A70200000000484 +:1019F000061A324000000008021AAE2C0000000057 +:101A0000061A503000000002061A51580000001259 +:101A1000041A40180002036B041A63D80002036D15 +:101A2000061A703000000004061A32600000000838 +:101A3000021AAE3000000000061A504000000002FA +:101A4000061A51A000000012041A40200002036F81 +:101A5000041A63E000020371061A704000000004DB +:101A6000061A328000000008021AAE34000000009E +:101A7000061A505000000002061A51E80000001239 +:101A8000041A402800020373041A63E80002037575 +:101A9000061A705000000004061A32A00000000868 +:101AA000021AAE3800000000061A50600000000262 +:101AB000061A523000000012041A40300002037768 +:101AC000041A63F000020379061A70600000000433 +:101AD000061A32C000000008021AAE3C00000000E6 +:101AE000061A507000000002061A52780000001218 +:101AF000041A40380002037B041A63F80002037DD5 +:101B0000061A707000000004061A32E00000000897 +:101B10000200A468000B01C80200A294071D29114D +:101B20000200A298000000000200A29C009C042475 +:101B30000200A2A0000000000200A2A4000002090E +:101B40000200A270000000000200A2740000000069 +:101B50000200A270000000000200A2740000000059 +:101B60000200A270000000000200A2740000000049 +:101B70000200A270000000000200A2740000000039 +:101B8000020160A000000001020160A400000262E6 +:101B9000020160A800000002020160AC0000001811 +:101BA0000201620400000001020100B40000000113 +:101BB000020100B800000001020100DC0000000189 +:101BC0000201010000000001020101040000000107 +:101BD0000201007C003000000201008400000028A7 +:101BE0000201008C0000000002010130000000042E +:101BF0000201025C00000001020103280000000055 +:101C0000020160580000FFFF020160700000000741 +:101C10000201608000000001020105540000003054 +:101C2000020100C400000001020100CC000000011C +:101C3000020100F800000001020100F000000001B4 +:101C4000020100800030000002010088000000282E +:101C500002010090000000000201013400000004B5 +:101C6000020102DC000000010201032C0000000060 +:101C70000201605C0000FFFF0201607400000007C9 +:101C800002016084000000010201056400000030D0 +:101C9000020100C800000001020100D000000001A4 +:101CA000020100FC00000001020100F4000000013C +:101CB000020C100000000028020C20080000021195 +:101CC000020C200C00000200020C20100000020494 +:101CD000020C201C0000FFFF020C20200000FFFF70 +:101CE000020C20240000FFFF020C20280000FFFF50 +:101CF000020C203800000020020C203C00000021D3 +:101D0000020C204000000022020C204400000023AE +:101D1000020C204800000024020C204C000000258A +:101D2000020C205000000026020C20540000002766 +:101D3000020C205800000028020C205C0000002942 +:101D4000020C20600000002A020C20640000002B1E +:101D5000020C20680000002C020C206C0000002DFA +:101D6000020C20700000002E020C20740000002FD6 +:101D7000020C207800000010060C207C00000007F8 +:101D8000020C209800000011020C209C00000012A0 +:101D9000020C20A000000013060C20A40000001D6F +:101DA000020C211800000001020C211C000000019F +:101DB000020C212000000001060C21240000001D5F +:101DC000020C219800000001060C219C0000000775 +:101DD000020C21B800000001020C21BC000000012F +:101DE000020C21C000000001020C21C4000000010F +:101DF000020C21C800000001020C21CC00000001EF +:101E0000020C21D000000001020C21D400000001CE +:101E1000020C21D800000001020C21DC00000001AE +:101E2000020C21E000000001020C21E4000000018E +:101E3000020C21E800000001020C21EC000000016E +:101E4000020C21F000000001020C21F4000000014E +:101E5000020C21F800000001060C21FC0000000724 +:101E6000020C221800000001060C221C00000007D2 +:101E7000020C223807FFFFFF020C223C0000003F4B +:101E8000020C224007FFFFFF020C22440000000F5B +:101E9000010C224800000000010C224C0000000050 +:101EA000010C225000000000010C22540000000030 +:101EB000010C225800000000010C225C0000000010 +:101EC000010C226000000000010C226400000000F0 +:101ED000010C226800000000010C226C00000000D0 +:101EE000010C227000000000010C227400000000B0 +:101EF000010C227800000000010C227C0000000090 +:101F00000C0C2000000003E80A0C20000000000177 +:101F10000B0C20000000000A020C40080000101109 +:101F2000020C400C00001000020C401000001004D5 +:101F3000020C401400001021020C401C0000FFFFA6 +:101F4000020C40200000FFFF020C40240000FFFFB5 +:101F5000020C40280000FFFF020C40380000004641 +:101F6000020C403C00000010060C40400000000243 +:101F7000020C404800000018020C404C000000F029 +:101F8000060C40500000001F020C40CC0000000175 +:101F9000060C40D00000003A020C41B800000001DD +:101FA000060C41BC00000003020C41C80000000107 +:101FB000020C41CC00000001060C41D00000001AC8 +:101FC000020C423807FFFFFF020C423C0000003FBA +:101FD000020C424007FFFFFF020C42440000000FCA +:101FE000010C424800000000010C424C00000000BF +:101FF000010C425000000000010C4254000000009F +:10200000010C425800000000010C425C000000007E +:10201000010C426000000000010C4264000000005E +:10202000010C426800000000010C426C000000003E +:10203000010C427000000000010C4274000000001E +:10204000010C427800000000010C427C00000000FE +:10205000010C4280000000000C0C4000000003E86E +:102060000A0C4000000000010B0C40000000000AB8 +:10207000060D400000000A00020D0044000000327E +:10208000020D008C02150020020D009002150020A8 +:10209000020D009408100000020D009800000033AB +:1020A000020D009C00000002020D00A000000000D4 +:1020B000020D00A400000005020D00A800000005AC +:1020C000060D00AC00000002020D00B4000000028A +:1020D000020D00B800000003020D00BC0000000269 +:1020E000020D00C000000001020D00C80000000247 +:1020F000020D00CC00000002020D015C0000000196 +:10210000020D016400000001020D016800000002E0 +:10211000020D020400000001020D020C000000206C +:10212000020D021000000040020D021400000040E9 +:10213000020D022000000003020D0224000000181E +:10214000060D028000000012040D03000018037F3A +:10215000060D03600000000C020D004C00000001A1 +:10216000020D005000000002020D005400000000AB +:10217000020D005800000008060D005C000000047D +:10218000020D00C400000004020D00040000000164 +:10219000020D000800000001020D000C000000010B +:1021A000020D001000000001020D001400000001EB +:1021B000020D001800000001020D001C00000001CB +:1021C000020D002000000001020D002400000001AB +:1021D000020D002800000001020D002C000000018B +:1021E000020D003000000001020D0034000000016B +:1021F000020D003800000001020D003C000000014B +:10220000020D011400000009020D011C0000000A6B +:10221000020D012400000000020D012C000000004E +:10222000020D013400000000020D013C0000000B13 +:10223000020D014400000000020D011800000029F9 +:10224000020D01200000002A020D012800000020DC +:10225000020D013000000020020D013800000020B6 +:10226000020D01400000002B020D0148000000207B +:10227000020D011400000019020D011C0000001ADB +:10228000020D012400000010020D012C00000010BE +:10229000020D013400000010020D013C0000001B83 +:1022A000020D014400000010020D01180000003969 +:1022B000020D01200000003A020D0128000000304C +:1022C000020D013000000030020D01380000003026 +:1022D000020D01400000003B020D014800000030EB +:1022E000020D011400000049020D011C0000004A0B +:1022F000020D012400000040020D012C00000040EE +:10230000020D013400000040020D013C0000004BB2 +:10231000020D014400000040020D01180000006998 +:10232000020D01200000006A020D0128000000607B +:10233000020D013000000060020D01380000006055 +:10234000020D01400000006B020D0148000000601A +:10235000020D011400000059020D011C0000005A7A +:10236000020D012400000050020D012C000000505D +:10237000020D013400000050020D013C0000005B22 +:10238000020D014400000050020D01180000007908 +:10239000020D01200000007A020D012800000070EB +:1023A000020D013000000070020D013800000070C5 +:1023B000020D01400000007B020D0148000000708A +:1023C000060E200000000800020E004C0000003243 +:1023D000020E009402150020020E00980215002043 +:1023E000020E009C00000030020E00A00810000049 +:1023F000020E00A400000033020E00A8000000300E +:10240000020E00AC00000031020E00B0000000021D +:10241000020E00B400000004020E00B8000000002C +:10242000020E00BC00000002020E00C0000000020C +:10243000020E00C400000000020E00C800000002EE +:10244000020E00CC00000007020E00D000000002C7 +:10245000020E00D400000002020E00D800000001AD +:10246000020E014400000001020E014C00000001B8 +:10247000020E015000000002020E020400000001E2 +:10248000020E020C00000040020E0210000000408C +:10249000020E021C00000004020E022000000020B8 +:1024A000020E02240000000E020E02280000001B93 +:1024B000060E030000000012040E0280001B0397AA +:1024C000060E02EC00000005020E00540000000C95 +:1024D000020E00580000000C020E005C000000001C +:1024E000020E006000000010020E006400000010E8 +:1024F000060E006800000003020E00DC000000036E +:10250000020E000400000001020E0008000000019D +:10251000020E000C00000001020E0010000000017D +:10252000020E001400000001020E0018000000015D +:10253000020E001C00000001020E0020000000013D +:10254000020E002400000001020E0028000000011D +:10255000020E002C00000001020E003000000001FD +:10256000020E003400000001020E003800000001DD +:10257000020E003C00000001020E004000000001BD +:10258000020E004400000001020E01100000000FC6 +:10259000020E011800000000020E012000000000E1 +:1025A000020E012800000000020E01140000002F9E +:1025B000020E011C00000020020E01240000000099 +:1025C000020E012C00000000020E01100000001F8E +:1025D000020E011800000010020E01200000000091 +:1025E000020E012800000000020E01140000003F4E +:1025F000020E011C00000030020E01240000000049 +:10260000020E012C00000000020E01100000004F1D +:10261000020E011800000040020E01200000000020 +:10262000020E012800000000020E01140000006FDD +:10263000020E011C00000060020E012400000000D8 +:10264000020E012C00000000020E01100000005FCD +:10265000020E011800000050020E012000000000D0 +:10266000020E012800000000020E01140000007F8D +:10267000020E011C00000070020E01240000000088 +:10268000020E012C000000000730040000C9000009 +:10269000083007D8000503B207340000332B0000D0 +:1026A0000734800030A40CCB07350000351A18F52C +:1026B000073580002A8A263C0736000018D830DF0C +:1026C00008364630373A03B40130000000000000FD +:1026D000013000040000000001300008000000008C +:1026E0000130000C0000000001300010000000006C +:1026F0000130001400000000023000200000000142 +:102700000230002400000002023000280000000314 +:102710000230002C000000000230003000000004F5 +:1027200002300034000000010230003800000000D8 +:102730000230003C000000010230004000000004B4 +:102740000230004400000000023000480000000198 +:102750000230004C00000003023000500000000076 +:102760000230005400000001023000580000000454 +:102770000230005C00000000023000600000000138 +:102780000230006400000003023000680000000016 +:102790000230006C000000010230007000000004F4 +:1027A00002300074000000000230007800000004D5 +:1027B0000230007C000000030630008000000002B0 +:1027C000023000A400003FFF023000A8000003FF19 +:1027D0000230022400000000023002340000000039 +:1027E0000230024C00000000023002E40000FFFF53 +:1027F000063020000000080002338BC000000001FA +:10280000023380000000001A023380400000004EB6 +:102810000233808000000010023380C000000020DE +:102820000C3383000007A1200A3383000000013825 +:102830000B338300000013880A338340000000003C +:102840000C338340000001F40B338340000000058B +:10285000023383800007A120023383C0000001F40B +:1028600002331480000000010A33148000000000CD +:10287000063280000000010206322008000000C875 +:10288000063220000000000204328EA0001003B6C1 +:1028900006323EB00000000606323ED800000002BC +:1028A00006323E800000000A04323EA8000203C641 +:1028B00006323E00000000200632500000000400F6 +:1028C0000632400000000004043274C0000203C855 +:1028D00006324110000000020632D0000000003035 +:1028E0000632DD40000000440632DA00000000D06D +:1028F0000632DEA0000000020632E0000000080000 +:1029000006328450000001180632100000000188D1 +:102910000632500000000020063251000000002066 +:102920000632520000000020063253000000002052 +:10293000063254000000002006325500000000203E +:10294000063256000000002006325700000000202A +:102950000632580000000020063259000000002016 +:1029600006325A000000002006325B000000002002 +:1029700006325C000000002006325D0000000020EE +:1029800006325E000000002006325F0000000020DA +:1029900006328DF00000000204328E00000203CAED +:1029A00006328E08000000020632DE9000000002AF +:1029B00006321C4000000038063288B000000118C2 +:1029C00006321620000001880632508000000020E8 +:1029D00006325180000000200632528000000020A4 +:1029E0000632538000000020063254800000002090 +:1029F000063255800000002006325680000000207C +:102A00000632578000000020063258800000002067 +:102A1000063259800000002006325A800000002053 +:102A200006325B800000002006325C80000000203F +:102A300006325D800000002006325E80000000202B +:102A400006325F800000002006328DF80000000290 +:102A500004328E10000203CC06328E1800000002F1 +:102A60000632DE980000000206321D200000003809 +:102A700002328D50000000000632401000000002BB +:102A800002328D5400000000063240200000000297 +:102A900002328D5800000000063240300000000273 +:102AA00002328D5C0000000006324040000000024F +:102AB00002328D600000000006324050000000022B +:102AC00002328D6400000000063240600000000207 +:102AD00002328D68000000000632407000000002E3 +:102AE00002328D6C000000000632408000000002BF +:102AF000072004000091000008200780001003CE8A +:102B0000072400002AFF00000724800015090AC0DE +:102B10000824A9F0692803D001200000000000006B +:102B20000120000400000000012000080000000057 +:102B30000120000C00000000012000100000000037 +:102B4000012000140000000002200020000000010D +:102B500002200024000000020220002800000003E0 +:102B60000220002C000000000220003000000004C1 +:102B700002200034000000010220003800000000A4 +:102B80000220003C00000001022000400000000480 +:102B90000220004400000000022000480000000164 +:102BA0000220004C00000003022000500000000042 +:102BB0000220005400000001022000580000000420 +:102BC0000220005C00000000022000600000000104 +:102BD00002200064000000030220006800000000E2 +:102BE0000220006C000000010220007000000004C0 +:102BF00002200074000000000220007800000004A1 +:102C00000220007C0000000306200080000000027B +:102C1000022000A400003FFF022000A8000003FFE4 +:102C20000220022400000000022002340000000004 +:102C30000220024C00000000022002E40000FFFF1E +:102C4000062020000000080002238BC000000001C5 +:102C500002238000000000100223804000000012C8 +:102C60000223808000000030022380C00000000E9C +:102C70000C2383000007A1200A23830000000138F1 +:102C80000B238300000013880A2383400000000008 +:102C90000C238340000001F40B2383400000000557 +:102CA000022383800007A120022383C0000001F4D7 +:102CB00002231480000000010A2314800000000099 +:102CC000062210000000004206222008000000C872 +:102CD00006222000000000020622B000000000C60C +:102CE0000422B318000503D20622B32C0000000B07 +:102CF0000422B358000503D70622B36C0000000B72 +:102D00000422B398000503DC0622B3AC0000000BDC +:102D10000422B3D8000503E10622B3EC0000000B47 +:102D20000422B418000503E60622B42C0000000BB0 +:102D30000422B458000503EB0622B46C0000000B1B +:102D40000422B498000503F00622B4AC0000000B86 +:102D50000422B4D8000503F50622B4EC0000000BF1 +:102D60000422B518000503FA0622B52C0000000B5A +:102D70000422B558000503FF0622B56C0000000BC5 +:102D80000422B598000504040622B5AC0000000B2F +:102D90000422B5D8000504090622B5EC0000000B9A +:102DA0000422B6180005040E0622B62C0000000B03 +:102DB0000422B658000504130622B66C0000000B6E +:102DC0000422B698000504180622B6AC0000000BD9 +:102DD0000422B6D80005041D0622B6EC0000000B44 +:102DE0000422B718000504220622B72C0000000BAD +:102DF0000422B758000504270622B76C0000000B18 +:102E00000422B7980005042C0622B7AC0000000B82 +:102E10000422B7D8000504310622B7EC0000000BED +:102E20000422B818000504360622B82C0000000B56 +:102E30000422B8580005043B0622B86C0000000BC1 +:102E40000422B898000504400622B8AC0000000B2C +:102E50000422B8D8000504450622B8EC0000000B97 +:102E60000422B9180005044A0622B92C0000000B00 +:102E70000422B9580005044F0622B96C0000000B6B +:102E80000422B998000504540622B9AC0000000BD6 +:102E90000422B9D8000504590622B9EC0000000B41 +:102EA0000422BA180005045E0622BA2C0000000BAA +:102EB0000422BA58000504630622BA6C0000000B15 +:102EC0000422BA98000504680622BAAC0000000B80 +:102ED0000422BAD80005046D0622BAEC00000005F1 +:102EE0000622BB00000000530422BC4C0001047207 +:102EF0000622BC50000000030422BC5C00010473E5 +:102F00000622BC60000000030422BC6C00010474B3 +:102F10000622BC70000000030422BC7C0001047582 +:102F20000622BC80000000030422BC8C0001047651 +:102F30000622BC90000000030422BC9C0001047720 +:102F40000622BCA0000000030422BCAC00010478EF +:102F50000622BCB0000000030422BCBC00010479BE +:102F60000622880000000100062280000000020006 +:102F7000042212700010047A06223000000000C003 +:102F800006226700000001000622900000000400F5 +:102F900004226B080020048A022212C0FFFFFFFFF8 +:102FA000062211E800000002062212C800000009F3 +:102FB000062212EC0000000906228C000000000826 +:102FC0000222114800000000062213200000000623 +:102FD000062233000000000206226040000000309C +:102FE00006228C20000000080222114C0000000084 +:102FF00006221338000000060622330800000002F3 +:10300000062261000000003006228C40000000080B +:10301000022211500000000006221350000000069A +:103020000622331000000002062261C000000030BA +:1030300006228C60000000080222115400000000EB +:103040000622136800000006062233180000000262 +:10305000062262800000003006228C8000000008FA +:103060000222115800000000062213800000000612 +:1030700006223320000000020622634000000030D8 +:1030800006228CA0000000080222115C0000000053 +:1030900006221398000000060622332800000002D2 +:1030A000062264000000003006228CC000000008E8 +:1030B0000222116000000000062213B0000000068A +:1030C0000622333000000002062264C000000030F7 +:1030D00006228CE0000000080222116400000000BB +:1030E000062213C800000006062233380000000242 +:1030F0000622658000000030021610000000002843 +:1031000002170008000000020217002C0000000354 +:103110000217003C000000040217004800000002F3 +:103120000217004C000000900217005000000090B1 +:103130000217005400800090021700580810000089 +:10314000021700600000008A02170064000000807F +:1031500002170068000000810217006C0000008068 +:10316000021700700000000602170078000007D068 +:103170000217007C0000076C02170038007C100466 +:10318000021700040000000F061640240000000291 +:10319000021640700000001C0216420800000001E8 +:1031A0000216421000000001021642200000000139 +:1031B0000216422800000001021642300000000101 +:1031C00002164238000000010216426000000002B0 +:1031D0000C16401C0003D0900A16401C0000009CF6 +:1031E0000B16401C000009C4021640300000000805 +:1031F000021640340000000C021640380000001097 +:1032000002164044000000200216400000000001A9 +:10321000021640D80000000102164008000000011C +:103220000216400C000000010216401000000001D0 +:103230000216424000000000021642480000000052 +:103240000616427000000002021642500000000004 +:1032500002164258000000000616428000000002DC +:1032600002166008000012240216600C0000121002 +:1032700002166010000012140216601C0000FFFF0E +:10328000021660200000FFFF021660240000FFFF0E +:10329000021660280000FFFF0216603800000020C0 +:1032A0000216603C0000002006166040000000028C +:1032B00002166048000000230216604C0000002443 +:1032C000021660500000002502166054000000261F +:1032D00002166058000000270216605C00000029FA +:1032E000021660600000002A021660640000002BD5 +:1032F000021660680000002C0216606C0000002DB1 +:1033000002166070000000EC0216607400000011EC +:1033100002166078000000120616607C0000000FA4 +:10332000021660B800000001021660BC0000000137 +:10333000061660C00000000C021660F000000001DC +:10334000061660F400000031021661B800000001AA +:10335000061661BC0000000D021661F000000001BD +:10336000061661F4000000110216623807FFFFFF25 +:103370000216623C0000003F0216624007FFFFFF9A +:10338000021662440000000F0116624800000000AF +:103390000116624C0000000001166250000000009F +:1033A000011662540000000001166258000000007F +:1033B0000116625C0000000001166260000000005F +:1033C000011662640000000001166268000000003F +:1033D0000116626C0000000001166270000000001F +:1033E00001166274000000000116627800000000FF +:1033F0000116627C000000000C166000000003E86B +:103400000A166000000000010B1660000000000AB0 +:1034100002168040000000060216804400000005ED +:10342000021680480000000A0216804C00000005C9 +:103430000216805400000002021680CC0000000436 +:10344000021680D000000004021680D400000004A0 +:10345000021680D800000004021680DC0000000480 +:10346000021680E000000004021680E40000000460 +:10347000021680E800000004021688040000000420 +:10348000021680300000007C021680340000003DEF +:10349000021680380000003F0216803C0000009CAD +:1034A000021680F000000007061680F400000005F8 +:1034B0000216880C010101010216810800000000BB +:1034C0000216810C000000040216811000000004A6 +:1034D0000216811400000002021688100801200460 +:1034E00002168118000000050216811C000000056C +:1034F000021681200000000502168124000000054C +:103500000216882C200810010216812800000008ED +:103510000216812C00000006021681300000000710 +:1035200002168134000000000216883001010120DB +:1035300006168138000000040216883401010101DA +:1035400002168148000000000216814C00000004B1 +:10355000021681500000000402168154000000028F +:103560000216883808012004021681580000000560 +:103570000216815C00000005021681600000000553 +:1035800002168164000000050216883C2008100124 +:1035900002168168000000080216816C0000000617 +:1035A00002168170000000070216817400000001FD +:1035B00002168840010101200216817800000001F6 +:1035C0000216817C000000010216818000000001CB +:1035D00002168184000000010216884401010101E5 +:1035E00002168188000000010216818C0000000490 +:1035F000021681900000000402168194000000026F +:10360000021688480801200402168198000000056F +:103610000216819C00000005021681A00000000532 +:10362000021681A40000000502168814200810016B +:10363000021681A800000008021681AC00000006F6 +:10364000021681B000000007021681B400000001DC +:103650000216881801010120021681B8000000013D +:10366000021681BC00000001021681C000000001AA +:10367000021681C4000000010216881C010101012C +:10368000021681C800000001021681CC000000046F +:10369000021681D000000004021681D4000000024E +:1036A0000216882008012004021681D800000005B7 +:1036B000021681DC00000005021681E00000000512 +:1036C000021681E40000000502168824200810017B +:1036D000021681E800000008021681EC00000006D6 +:1036E000021681F0000000070216E40C0000000042 +:1036F00002168828010101200616E41000000004CB +:103700000216E000010101010216E42000000000A1 +:103710000216E424000000040216E428000000045D +:103720000216E42C000000020216E0040801200446 +:103730000216E430000000050216E4340000000523 +:103740000216E438000000050216E43C0000000503 +:103750000216E008200810010216E44000000008EC +:103760000216E444000000060216E44800000007C8 +:103770000216E44C000000000216E00C01010120DA +:103780000616E450000000040216E01001010101D9 +:103790000216E460000000000216E4640000000469 +:1037A0000216E468000000040216E46C0000000247 +:1037B0000216E014080120040216E470000000055F +:1037C0000216E474000000050216E478000000050B +:1037D0000216E47C000000050216E0182008100123 +:1037E0000216E480000000080216E48400000006CF +:1037F0000216E488000000070216E48C00000001B5 +:103800000216E01C010101200216E49000000001F4 +:103810000216E494000000010216E4980000000182 +:103820000216E49C000000010216E02001010101E3 +:103830000216E4A0000000010216E4A40000000447 +:103840000216E4A8000000040216E4AC0000000226 +:103850000216E024080120040216E4B0000000056E +:103860000216E4B4000000050216E4B800000005EA +:103870000216E4BC000000050216E0282008100132 +:103880000216E4C0000000080216E4C400000006AE +:103890000216E4C8000000070216E4CC0000000194 +:1038A0000216E02C010101200216E4D00000000104 +:1038B0000216E4D4000000010216E4D80000000162 +:1038C0000216E4DC000000010216E03001010101F3 +:1038D0000216E4E0000000010216E4E40000000427 +:1038E0000216E4E8000000040216E4EC0000000206 +:1038F0000216E034080120040216E4F0000000057E +:103900000216E4F4000000050216E4F800000005C9 +:103910000216E4FC000000050216E0382008100141 +:103920000216E500000000080216E504000000068B +:103930000216E508000000070216E03C0101012024 +:1039400002168240003F003F021682440000000041 +:103950000216E524003F003F0216E52800000000A3 +:1039600002168248000000000216824C003F003F11 +:103970000216E52C000000000216E530003F003F73 +:10398000021682500100010002168254010001005B +:103990000216E534010001000216E53801000100BD +:1039A00006168258000000020216E53C00000000E6 +:1039B0000216E540000000000216826000C000C050 +:1039C0000216826400C000C00216E54400C000C0B8 +:1039D0000216E54800C000C0021682681E001E00E4 +:1039E0000216826C1E001E000216E54C1E001E0010 +:1039F0000216E5501E001E000216827040004000B4 +:103A000002168274400040000216E5544000400057 +:103A10000216E558400040000216827880008000BF +:103A20000216827C800080000216E55C8000800027 +:103A30000216E560800080000216828020002000CF +:103A400002168284200020000216E5642000200077 +:103A50000216E56820002000061682880000000299 +:103A60000216E56C000000000216E5700000000080 +:103A700002168290000000000216829400000000EE +:103A80000216E574000000000216E5780000000050 +:103A900002168298000000000216829C00000000BE +:103AA0000216E57C000000000216E5800000000020 +:103AB000021682A000000000021682A4000000018D +:103AC000061682A80000000A021681F400000C0805 +:103AD000021681F800000040021681FC000001007F +:103AE0000216820000000020021682040000001767 +:103AF00002168208000000800216820C00000200FC +:103B000002168210000000000216821801FF01FF59 +:103B10000216821401FF01FF0216E51001FF01FFEA +:103B20000216E50C01FF01FF0216823C00000013A3 +:103B3000021680900000013F0216806000000140E4 +:103B40000216806400000140061680680000000232 +:103B500002168070000000C0061680740000000786 +:103B60000216809C00000048021680A00000004859 +:103B7000061680A400000002021680AC0000004877 +:103B8000061680B000000007021682380000800090 +:103B900002168234000025E40216809400007FFFA4 +:103BA00002168220000F000F0216821C000F000F69 +:103BB0000216E518000F000F0216E514000F000FA3 +:103BC000021682280000000002168224FFFFFFFF79 +:103BD0000216E520000000000216E51CFFFFFFFFB3 +:103BE0000216E6BC000000000216E6C0000000025B +:103BF0000216E6C4000000010216E6C80000000339 +:103C00000216E6CC000000040216E6D00000000612 +:103C10000216E6D4000000050216E6D800000007F0 +:103C2000021680EC000000FF0214000000000001FA +:103C30000214000C0000000102140040000000010A +:103C40000214004400007FFF0214000C000000007A +:103C500002140000000000000214006C00000000CC +:103C600002140004000000010214003000000001F2 +:103C700002140004000000000214005C00000000B8 +:103C800002140008000000010214003400000001CA +:103C90000214000800000000021400600000000090 +:103CA00006028000000020000202005800000032DE +:103CB000020200A003150020020200A40315002048 +:103CC000020200A801000030020200AC081000004F +:103CD000020200B000000033020200B40000003015 +:103CE000020200B800000031020200BC0000000324 +:103CF000020200C000000006020200C4000000032F +:103D0000020200C800000003020200CC0000000212 +:103D1000020200D000000000020200D400000002F5 +:103D2000020200DC00000000020200E000000006C9 +:103D3000020200E400000004020200E800000002A9 +:103D4000020200EC00000002020200F0000000018C +:103D5000020200FC00000006020201200000000038 +:103D60000202013400000002020201B00000000162 +:103D70000202020C00000001020202140000000115 +:103D80000202021800000002020204040000000106 +:103D90000202040C00000040020204100000004077 +:103DA0000202041C000000040202042000000020A3 +:103DB0000202042400000002020204280000002085 +:103DC000060205000000001204020480002004AA7C +:103DD000020200600000000F020200640000000701 +:103DE00002020068000000000202006C0000000EE9 +:103DF000020200700000000E0602007400000003C2 +:103E0000020200F4000000040202000400000001AD +:103E100002020008000000010202000C0000000184 +:103E20000202001000000001020200140000000164 +:103E300002020018000000010202001C0000000144 +:103E40000202002000000001020200240000000124 +:103E500002020028000000010202002C0000000104 +:103E600002020030000000010202003400000001E4 +:103E700002020038000000010202003C00000001C4 +:103E800002020040000000010202004400000001A4 +:103E900002020048000000010202004C0000000184 +:103EA000020200500000000102020108000000C8E8 +:103EB0000202011800000002020201C4000000001A +:103EC000020201CC00000000020201D40000000246 +:103ED000020201DC00000002020201E4000000FF17 +:103EE000020201EC000000FF0202010000000000DD +:103EF0000202010C000000C80202011C00000002C6 +:103F0000020201C800000000020201D0000000000F +:103F1000020201D800000002020201E000000002DB +:103F2000020201E8000000FF020201F0000000FFB1 +:103F3000020201040000000002020108000000C8A3 +:103F40000202011800000002020201C40000000089 +:103F5000020201CC00000000020201D400000002B5 +:103F6000020201DC00000002020201E4000000FF86 +:103F7000020201EC000000FF02020100000000004C +:103F80000202010C000000C80202011C0000000235 +:103F9000020201C800000000020201D0000000007F +:103FA000020201D800000002020201E0000000024B +:103FB000020201E8000000FF020201F0000000FF21 +:103FC000020201040000000002020108000000C813 +:103FD0000202011800000002020201C400000000F9 +:103FE000020201CC00000000020201D40000000225 +:103FF000020201DC00000002020201E4000000FFF6 +:10400000020201EC000000FF0202010000000000BB +:104010000202010C000000C80202011C00000002A4 +:10402000020201C800000000020201D000000000EE +:10403000020201D800000002020201E000000002BA +:10404000020201E8000000FF020201F0000000FF90 +:10405000020201040000000002020108000000C882 +:104060000202011800000002020201C40000000068 +:10407000020201CC00000000020201D40000000294 +:10408000020201DC00000002020201E4000000FF65 +:10409000020201EC000000FF02020100000000002B +:1040A0000202010C000000C80202011C0000000214 +:1040B000020201C800000000020201D0000000005E +:1040C000020201D800000002020201E0000000022A +:1040D000020201E8000000FF020201F0000000FF00 +:1040E00002020104000000000728040000A30000F1 +:1040F000082807B8000904CA072C000034F10000A2 +:10410000072C800038A60D3D072D000037B61B6731 +:10411000072D800032632955072E00001C6835EEFC +:10412000082E48B036EA04CC012800000000000048 +:104130000128000400000000012800080000000021 +:104140000128000C00000000012800100000000001 +:1041500001280014000000000228002000000001D7 +:1041600002280024000000020228002800000003AA +:104170000228002C0000000002280030000000048B +:10418000022800340000000102280038000000006E +:104190000228003C0000000102280040000000044A +:1041A000022800440000000002280048000000012E +:1041B0000228004C0000000302280050000000000C +:1041C00002280054000000010228005800000004EA +:1041D0000228005C000000000228006000000001CE +:1041E00002280064000000030228006800000000AC +:1041F0000228006C0000000102280070000000048A +:10420000022800740000000002280078000000046A +:104210000228007C00000003062800800000000245 +:10422000022800A400003FFF022800A8000003FFAE +:1042300002280224000000000228023400000000CE +:104240000228024C00000000022802E40000FFFFE8 +:104250000628200000000800022B8BC0000000018F +:10426000022B800000000000022B8040000000189C +:10427000022B80800000000C022B80C00000006632 +:104280000C2B83000007A1200A2B830000000138BB +:104290000B2B8300000013880A2B834000000000D2 +:1042A0000C2B8340000001F40B2B83400000000521 +:1042B000022B83800007A120022B83C0000001F4A1 +:1042C000022B1480000000010A2B14800000000063 +:1042D000062A9AF800000004042A9B08000204CE73 +:1042E000062A9B1000000006062A90800000004865 +:1042F000062A2008000000C8062A2000000000024C +:10430000062A91A800000086062A900000000020DE +:10431000062A93C800000003042A93D4000104D0A5 +:10432000062A9DA800000002042A9498000404D1E3 +:10433000042A9D58000104D5062A9D5C0000001146 +:10434000042ACB20001004D6042A3000000204E620 +:10435000062A300800000100062A40400000001034 +:10436000042A4000001004E8042A8408000204F82B +:10437000062A9DA000000002062AB000000000509E +:10438000062ABB7000000070062AB150000000022F +:10439000062ABB6000000004062AD00000000800C6 +:1043A000062AC00000000150062A94A8000000322E +:1043B000062A502000000002062A503000000002A9 +:1043C000062A500000000002062A501000000002D9 +:1043D000022A520800000001042A9B28000204FA65 +:1043E000062A963800000022042A96C0000104FC28 +:1043F000062A96C400000003062A976800000022DF +:10440000042A97F0000104FD062A97F40000000337 +:10441000062A989800000022042A9920000104FE30 +:10442000062A992400000003062A99C800000022E9 +:10443000042A9A50000104FF062A9A54000000033F +:10444000062AB14000000002062AC54000000150C3 +:10445000062A957000000032062A5028000000024B +:10446000062A503800000002062A50080000000208 +:10447000062A501800000002022A520C0000000117 +:10448000042A9B3000020500062A96D00000002274 +:10449000042A975800010502062A975C00000003D1 +:1044A000062A980000000022042A988800010503CB +:1044B000062A988C00000003062A9930000000228A +:1044C000042A99B800010504062A99BC00000003DB +:1044D000062A9A6000000022042A9AE800010505D5 +:1044E000062A9AEC00000003062AB14800000002E8 +:1044F000022ACA8000000000042A9B38001005062A +:10450000062A50480000000E022ACA84000000005B +:10451000042A9B7800100516062A50800000000E21 +:10452000022ACA8800000000042A9BB80010052651 +:10453000062A50B80000000E022ACA8C00000000B3 +:10454000042A9BF800100536062A50F00000000EE1 +:10455000022ACA9000000000042A9C380010054678 +:10456000062A51280000000E022ACA94000000000A +:10457000042A9C7800100556062A51600000000E9F +:10458000022ACA9800000000042A9CB800100566A0 +:10459000062A51980000000E022ACA9C0000000062 +:1045A000042A9CF800100576062A51D00000000E5F +:1045B000021010080000000102101050000000015D +:1045C000021010000003D000021010040000003D93 +:1045D0000910180002000586091011000010078656 +:1045E0000610114000000008091011600010079625 +:1045F000061011A00000001806102400000000E0C2 +:104600000210201C00000000021020200000000109 +:10461000021020C00000000202102004000000016F +:10462000021020080000000109103C00000507A648 +:1046300009103800000507AB09103820000507B045 +:1046400006104C000000010002104028000000107D +:104650000210404400003FFF0210405800280000B4 +:10466000021040840084924A02104058000000006A +:104670000210800000001080021080AC00000000DA +:1046800002108038000000100210810000000000BD +:10469000061081200000000202108008000002B510 +:1046A0000210801000000000061082000000004A86 +:1046B000021081080001FFFF061081400000000287 +:1046C0000210800000001A800610900000000024F4 +:1046D000061091200000004A061093700000004A66 +:1046E000061095C00000004A0210800400001080EF +:1046F000021080B0000000010210803C0000001099 +:104700000210810400000000061081280000000251 +:104710000210800C000002B502108014000000009E +:10472000061084000000004A0210810C0001FFFF07 +:1047300006108148000000020210800400001A8068 +:104740000610909000000024061092480000004AD5 +:10475000061094980000004A061096E80000004AEF +:104760000210800000001080021080AC00000002E7 +:1047700002108038000000100210810000000000CC +:10478000061081200000000202108008000002B51F +:104790000210801000000000061082000000004A95 +:1047A000021081080001FFFF061081400000000296 +:1047B0000210800000001A80061090000000002403 +:1047C000061091200000004A061093700000004A75 +:1047D000061095C00000004A0210800400001080FE +:1047E000021080B0000000030210803C00000010A6 +:1047F0000210810400000000061081280000000261 +:104800000210800C000002B50210801400000000AD +:10481000061084000000004A0210810C0001FFFF16 +:1048200006108148000000020210800400001A8077 +:104830000610909000000024061092480000004AE4 +:10484000061094980000004A061096E80000004AFE +:104850000210800000001080021080AC00000004F4 +:1048600002108038000000100210810000000000DB +:10487000061081200000000202108008000002B52E +:104880000210801000000000061082000000004AA4 +:10489000021081080001FFFF0610814000000002A5 +:1048A0000210800000001A80061090000000002412 +:1048B000061091200000004A061093700000004A84 +:1048C000061095C00000004A02108004000010800D +:1048D000021080B0000000050210803C00000010B3 +:1048E0000210810400000000061081280000000270 +:1048F0000210800C000002B50210801400000000BD +:10490000061084000000004A0210810C0001FFFF25 +:1049100006108148000000020210800400001A8086 +:104920000610909000000024061092480000004AF3 +:10493000061094980000004A061096E80000004A0D +:104940000210800000001080021080AC0000000601 +:1049500002108038000000100210810000000000EA +:10496000061081200000000202108008000002B53D +:104970000210801000000000061082000000004AB3 +:10498000021081080001FFFF0610814000000002B4 +:104990000210800000001A80061090000000002421 +:1049A000061091200000004A061093700000004A93 +:1049B000061095C00000004A02108004000010801C +:1049C000021080B0000000070210803C00000010C0 +:1049D000021081040000000006108128000000027F +:1049E0000210800C000002B50210801400000000CC +:1049F000061084000000004A0210810C0001FFFF35 +:104A000006108148000000020210800400001A8095 +:104A10000610909000000024061092480000004A02 +:104A2000061094980000004A061096E80000004A1C +:104A3000021205B0000000010212049000E383405E +:104A40000212051400003C100212066C0000000166 +:104A5000021206700000000002120494FFFFFFFF24 +:104A600002120498FFFFFFFF0212049CFFFFFFFFEA +:104A7000021204A0FFFFFFFF021204A4FFFFFFFFCA +:104A8000021204A8FFFFFFFF021204ACFFFFFFFFAA +:104A9000021204B0FFFFFFFF021204BCFFFFFFFF82 +:104AA000021204C0FFFFFFFF021204C4FFFFFFFF5A +:104AB000021204C8FFFFFFFF021204CCFFFFFFFF3A +:104AC000021204D0FFFFFFFF021204D8FFFFFFFF16 +:104AD000021204DCFFFFFFFF021204E0FFFFFFFFF2 +:104AE000021204E4FFFFFFFF021204E8FFFFFFFFD2 +:104AF000021204ECFFFFFFFF021204F0FFFFFFFFB2 +:104B0000021204F4FFFFFFFF021204F8FFFFFFFF91 +:104B1000021204FCFFFFFFFF02120500FFFFFFFF70 +:104B200002120504FFFFFFFF02120508FFFFFFFF4F +:104B30000212050CFFFFFFFF02120510FFFFFFFF2F +:104B4000021204D4FF809000021204B4F00050005E +:104B5000021204B8F00010000212039000000008D6 +:104B60000212039C00000008021203A000000008CB +:104B7000021203A400000002021203BC00000004A1 +:104B8000021203C000000005021203C4000000046A +:104B9000021203D0000000000212036C00000001AA +:104BA000021203680000003F021201BC0000004036 +:104BB000021201C000001808021201C4000008031C +:104BC000021201C800000803021201CC00000040DC +:104BD000021201D000000003021201D400000803F9 +:104BE000021201D800000803021201DC00000803D1 +:104BF000021201E000010003021201E400000803B8 +:104C0000021201E800000803021201EC0000000398 +:104C1000021201F000000003021201F40000000380 +:104C2000021201F800000003021201FC0000000360 +:104C3000021202000000000302120204000000033E +:104C400002120208000000030212020C000000031E +:104C500002120210000000030212021400000003FE +:104C600002120218000000030212021C00000003DE +:104C700002120220000000030212022400000003BE +:104C800002120228000024030212022C0000002F4E +:104C90000212023000000009021202340000001962 +:104CA00002120238000001840212023C000001835B +:104CB0000212024000000306021202440000001922 +:104CC00002120248000000060212024C0000030615 +:104CD00002120250000003060212025400000306F2 +:104CE0000212025800000C860212025C0000030649 +:104CF00002120260000003060212026400000006B5 +:104D000002120268000000060212026C0000000697 +:104D10000212027000000006021202740000000677 +:104D200002120278000000060212027C0000000657 +:104D30000212028000000006021202840000000637 +:104D400002120288000000060212028C0000000617 +:104D500002120290000000060212029400000006F7 +:104D600002120298000000060212029C00000006D7 +:104D7000021202A000000306021202A400000013A7 +:104D8000021202A800000006021202B00000100485 +:104D9000021202B400001004021203240010644046 +:104DA0000212032800106440021205B40000000142 +:104DB000021201B0000000010600A0000000000C7B +:104DC0000200A050000000000200A05400000000FB +:104DD0000200A0EC555400000200A0F055555555B6 +:104DE0000200A0F4000055550200A0F8F0000000F9 +:104DF0000200A0FC555400000200A1005555555575 +:104E00000200A104000055550200A108F0000000B6 +:104E10000200A18C555400000200A1905555555533 +:104E20000200A194000055550200A198F000000076 +:104E30000200A19C000000000200A1A000010000EF +:104E40000200A1A4000050140200A1A8000000006C +:104E50000200A45C00000C000200A61C000000037D +:104E60000200A06CFF5C00000200A070FFF55FFF75 +:104E70000200A0740000FFFF0200A078F00003E031 +:104E80000200A07C000000000200A0800000A00042 +:104E90000600A084000000050200A0980FE00000BA +:104EA0000600A09C000000070200A0B8000004005B +:104EB0000600A0BC000000030200A0C80000100013 +:104EC0000600A0CC000000030200A0D800004000B3 +:104ED0000600A0DC000000030200A0E800010000C2 +:104EE0000600A22C000000040200A10CFF5C0000E0 +:104EF0000200A110FFF55FFF0200A1140000FFFFF8 +:104F00000200A118F00003E00200A11C0000000054 +:104F10000200A1200000A0000600A124000000055E +:104F20000200A1380FE000000600A13C00000007CD +:104F30000200A158000008000600A15C0000000368 +:104F40000200A168000020000600A16C0000000320 +:104F50000200A178000080000600A17C0000000390 +:104F60000200A188000200000600A23C000000042C +:104F70000200A030000000000200A0340000000089 +:104F80000200A038000000000200A03C0000000069 +:104F90000200A040000000000200A0440000000049 +:104FA0000200A048000000000200A04C0000000029 +:104FB00000000000000000000000003000000000C1 +:104FC00000000000000000000000000000000000E1 +:104FD00000000000000000000000000000000000D1 +:104FE0000000000000300031000000000000000060 +:104FF00000000000000000000000000000000000B1 +:1050000000000000000000000000000000000000A0 +:10501000003100520000000000000000000000000D +:105020000000000000000000000000000000000080 +:105030000000000000000000000000000052008995 +:1050400000000000000000000089008D008D00912C +:1050500000910095009500990099009D009D00A188 +:1050600000A100A500A500A900A900AE00AE00B1F6 +:1050700000B100B4000000000000000000000000CB +:105080000000000000000000000000000000000020 +:105090000000000000B40309030903130313031DF8 +:1050A000031D03240324032B032B03320332033990 +:1050B00003390340034003470347034E034E0355A0 +:1050C00000000000000000000000000000000000E0 +:1050D00000000000000000000000000000000000D0 +:1050E00000000000000000000000000000000000C0 +:1050F00000000000000000000000000000000000B0 +:10510000000000000000000000000000000000009F +:10511000000000000000000000000000000000008F +:10512000000000000000000000000000000000007F +:10513000000000000000000000000000000000006F +:10514000000000000000000000000000000000005F +:10515000000000000000000000000000000000004F +:10516000000000000000000000000000000000003F +:105170000355035B0000000000000000035B035CBC +:10518000035C035D035D035E035E035F035F036017 +:1051900003600361036103620362036300000000B4 +:1051A00000000000000000000000000000000000FF +:1051B00000000000000000000000000000000000EF +:1051C00000000000000000000363036D036D037B1B +:1051D000037B0389000000000000000000000000C5 +:1051E00000000000000000000000000000000000BF +:1051F00000000000000000000000000000000000AF +:10520000000000000000000000000000000000009E +:10521000000000000000000000000000000000008E +:105220000389038A00000000000000000000000065 +:10523000000000000000000000000000000000006E +:10524000000000000000000000000000038A03D6F8 +:10525000000000000000000000000000000000004E +:10526000000000000000000000000000000000003E +:10527000000000000000000003D604010000000050 +:10528000000000000000000000000000000000001E +:10529000000000000000000000000000000000000E +:1052A00000000000040104330000000000000000C2 +:1052B0000433043A043A0441044104480448044FC6 +:1052C000044F04560456045D045D04640464046BD6 +:1052D000046B04A4000000000000000004A404A863 +:1052E00004A804AC04AC04B004B004B404B404B81E +:1052F00004B804BC04BC04C004C004C404C4051342 +:105300000513052A052A05410541054305430545C1 +:1053100005450547054705490549054B054B054D1D +:10532000054D054F054F0551055105E805E805E90F +:1053300005E905EA05EA05EF05EF05F405F405F9C9 +:1053400005F905FE05FE0603060306080608060D18 +:10535000060D0612061206130000000000000000F1 +:10536000000000000000000000000000000000003D +:10537000000000000000000000000000000000002D +:1053800006130624000000000000000000000000DA +:10539000000000000000000000000000000000000D +:1053A0000000000000000000000000000624063994 +:1053B0000639063C063C063F0000000000000000E5 +:1053C00000000000000000000000000000000000DD +:1053D0000000000000000000063F0675000000000D +:1053E00000000000000000000000000000000000BD +:1053F00000000000000000000000000000000000AD +:1054000000000000067507780000000000000000A2 +:10541000000000000000000000000000000000008C +:10542000000000000000000000000000000000007C +:105430000778077F077F078307830787000000003F +:10544000000000000000000000000000000000005C +:10545000000000000000000000000000078707C8EF +:10546000000000000000000007C807D107D107DADC +:1054700007DA07E307E307EC07EC07F507F507FE94 +:1054800007FE080708070810081008670867087C67 +:10549000087C089108910894089408970897089A3E +:1054A000089A089D089D08A008A008A308A308A6BC +:1054B00008A608A908A908B2000000000000000022 +:1054C00000000000000000000000000000000000DC +:1054D00000000000000000000000000000000000CC +:1054E00008B208B800000000000000000000000042 +:1054F00000000000000000000000000000000000AC +:1055000000000000000000000000000008B808BB18 +:10551000000000000000000000000000000000008B +:10552000000000000000000000000000000000007B +:10553000000000000000000008BB08C100000000DF +:10554000000000000000000000000000000000005B +:10555000000000000000000000000000000000004B +:10556000000000000000000000000000000000003B +:1055700008C108D008D008DF08DF08EE08EE08FDF3 +:1055800008FD090C090C091B091B092A092A0939FC +:10559000093909AA00000000000000000000000016 +:1055A00000000000000000000000000000000000FB +:1055B00000000000000000000000000009AA09BF70 +:1055C00009BF09D009D009E109E109E209E209E3CB +:1055D00009E309E409E409E509E509E609E609E75B +:1055E00009E709E809E809E90000000000000000F7 +:1055F00000000000000000000000000000000000AB +:10560000000000000000000000000000000000009A +:10561000000000000000000000000000000000008A +:10562000000000000000000000000000000000007A +:10563000000000000000000000000000000000006A +:10564000000000000000000000000000000000005A +:10565000000000000000000000000000000000004A +:10566000000000000000000000000000000000003A +:10567000000000000000000000000000000000002A +:10568000000000000000000000000000000000001A +:10569000000000000000000000000000000000000A +:1056A00000000000000000000000000000000000FA +:1056B00000000000000000000000000000000000EA +:1056C000000000000000000000010000000204C013 +:1056D0000003098000040E4000051300000617C0F7 +:1056E00000071C800008214000092600000A2AC08B +:1056F000000B2F80000C3440000D3900000E3DC01F +:10570000000F42800010474000114C00001250C0B2 +:105710000013558000145A4000155F00001663C046 +:105720000017688000186D4000197200001A76C0DA +:10573000001B7B80001C8040001D8500001E89C06E +:10574000001F8E80000093400000200000004000F9 +:1057500000006000000080000000A0000000C00009 +:105760000000E000000100000001200000014000F6 +:1057700000016000000180000001A0000001C000E5 +:105780000001E000000200000002200000024000D2 +:1057900000026000000280000002A0000002C000C1 +:1057A0000002E000000300000003200000034000AE +:1057B00000036000000380000003A0000003C0009D +:1057C0000003E0000004000000042000000440008A +:1057D00000046000000480000004A0000004C00079 +:1057E0000004E00000050000000520000005400066 +:1057F00000056000000580000005A0000005C00055 +:105800000005E00000060000000620000006400041 +:1058100000066000000680000006A0000006C00030 +:105820000006E0000007000000072000000740001D +:1058300000076000000780000007A0000007C0000C +:105840000007E000000800000008200000084000F9 +:1058500000086000000880000008A0000008C000E8 +:105860000008E000000900000009200000094000D5 +:1058700000096000000980000009A0000009C000C4 +:105880000009E000000A0000000A2000000A4000B1 +:10589000000A6000000A8000000AA000000AC000A0 +:1058A000000AE000000B0000000B2000000B40008D +:1058B000000B6000000B8000000BA000000BC0007C +:1058C000000BE000000C0000000C2000000C400069 +:1058D000000C6000000C8000000CA000000CC00058 +:1058E000000CE000000D0000000D2000000D400045 +:1058F000000D6000000D8000000DA000000DC00034 +:10590000000DE000000E0000000E2000000E400020 +:10591000000E6000000E8000000EA000000EC0000F +:10592000000EE000000F0000000F2000000F4000FC +:10593000000F6000000F8000000FA000000FC000EB +:10594000000FE000001000000010200000104000D8 +:1059500000106000001080000010A0000010C000C7 +:105960000010E000001100000011200000114000B4 +:1059700000116000001180000011A0000011C000A3 +:105980000011E00000120000001220000012400090 +:1059900000126000001280000012A0000012C0007F +:1059A0000012E0000013000000132000001340006C +:1059B00000136000001380000013A0000013C0005B +:1059C0000013E00000140000001420000014400048 +:1059D00000146000001480000014A0000014C00037 +:1059E0000014E00000150000001520000015400024 +:1059F00000156000001580000015A0000015C00013 +:105A00000015E000001600000016200000164000FF +:105A100000166000001680000016A0000016C000EE +:105A20000016E000001700000017200000174000DB +:105A300000176000001780000017A0000017C000CA +:105A40000017E000001800000018200000184000B7 +:105A500000186000001880000018A0000018C000A6 +:105A60000018E00000190000001920000019400093 +:105A700000196000001980000019A0000019C00082 +:105A80000019E000001A0000001A2000001A40006F +:105A9000001A6000001A8000001AA000001AC0005E +:105AA000001AE000001B0000001B2000001B40004B +:105AB000001B6000001B8000001BA000001BC0003A +:105AC000001BE000001C0000001C2000001C400027 +:105AD000001C6000001C8000001CA000001CC00016 +:105AE000001CE000001D0000001D2000001D400003 +:105AF000001D6000001D8000001DA000001DC000F2 +:105B0000001DE000001E0000001E2000001E4000DE +:105B1000001E6000001E8000001EA000001EC000CD +:105B2000001EE000001F0000001F2000001F4000BA +:105B3000001F6000001F8000001FA000001FC000A9 +:105B4000001FE00000200000002020000020400096 +:105B500000206000002080000020A0000020C00085 +:105B60000020E00000210000002120000021400072 +:105B700000216000002180000021A0000021C00061 +:105B80000021E0000022000000222000002240004E +:105B900000226000002280000022A0000022C0003D +:105BA0000022E0000023000000232000002340002A +:105BB00000236000002380000023A0000023C00019 +:105BC0000023E00000240000002420000024400006 +:105BD00000246000002480000024A0000024C000F5 +:105BE0000024E000002500000025200000254000E2 +:105BF00000256000002580000025A0000025C000D1 +:105C00000025E000002600000026200000264000BD +:105C100000266000002680000026A0000026C000AC +:105C20000026E00000270000002720000027400099 +:105C300000276000002780000027A0000027C00088 +:105C40000027E00000280000002820000028400075 +:105C500000286000002880000028A0000028C00064 +:105C60000028E00000290000002920000029400051 +:105C700000296000002980000029A0000029C00040 +:105C80000029E000002A0000002A2000002A40002D +:105C9000002A6000002A8000002AA000002AC0001C +:105CA000002AE000002B0000002B2000002B400009 +:105CB000002B6000002B8000002BA000002BC000F8 +:105CC000002BE000002C0000002C2000002C4000E5 +:105CD000002C6000002C8000002CA000002CC000D4 +:105CE000002CE000002D0000002D2000002D4000C1 +:105CF000002D6000002D8000002DA000002DC000B0 +:105D0000002DE000002E0000002E2000002E40009C +:105D1000002E6000002E8000002EA000002EC0008B +:105D2000002EE000002F0000002F2000002F400078 +:105D3000002F6000002F8000002FA000002FC00067 +:105D4000002FE00000300000003020000030400054 +:105D500000306000003080000030A0000030C00043 +:105D60000030E00000310000003120000031400030 +:105D700000316000003180000031A0000031C0001F +:105D80000031E0000032000000322000003240000C +:105D900000326000003280000032A0000032C000FB +:105DA0000032E000003300000033200000334000E8 +:105DB00000336000003380000033A0000033C000D7 +:105DC0000033E000003400000034200000344000C4 +:105DD00000346000003480000034A0000034C000B3 +:105DE0000034E000003500000035200000354000A0 +:105DF00000356000003580000035A0000035C0008F +:105E00000035E0000036000000362000003640007B +:105E100000366000003680000036A0000036C0006A +:105E20000036E00000370000003720000037400057 +:105E300000376000003780000037A0000037C00046 +:105E40000037E00000380000003820000038400033 +:105E500000386000003880000038A0000038C00022 +:105E60000038E0000039000000392000003940000F +:105E700000396000003980000039A0000039C000FE +:105E80000039E000003A0000003A2000003A4000EB +:105E9000003A6000003A8000003AA000003AC000DA +:105EA000003AE000003B0000003B2000003B4000C7 +:105EB000003B6000003B8000003BA000003BC000B6 +:105EC000003BE000003C0000003C2000003C4000A3 +:105ED000003C6000003C8000003CA000003CC00092 +:105EE000003CE000003D0000003D2000003D40007F +:105EF000003D6000003D8000003DA000003DC0006E +:105F0000003DE000003E0000003E2000003E40005A +:105F1000003E6000003E8000003EA000003EC00049 +:105F2000003EE000003F0000003F2000003F400036 +:105F3000003F6000003F8000003FA000003FC00025 +:105F4000003FE000003FE00100000000000001FF12 +:105F50000000020000007FF800007FF80000014010 +:105F600000003500000000010000FF0000000000FC +:105F70000000FF00000000000000FF000000000023 +:105F80000000FF00000000000000FF000000000013 +:105F90000000FF00000000000000FF000000000003 +:105FA0000000FF000000000000000000140AFF00D5 +:105FB00000000001000000000020100100000000AF +:105FC0000100900000000100000090020000900419 +:105FD00000009006000090080000900A0000900C5D +:105FE0000000900E0000901000009012000090142D +:105FF00000009016000090180000901A0000901CFD +:106000000000901E000090200000902200009024CC +:1060100000009026000090280000902A0000902C9C +:106020000000902E0000903000009032000090346C +:1060300000009036000090380000903A0000903C3C +:106040000000903E0000904000009042000090440C +:1060500000009046000090480000904A0000904CDC +:106060000000904E000090500000905200009054AC +:1060700000009056000090580000905A0000905C7C +:106080000000905E0000906000009062000090644C +:1060900000009066000090680000906A0000906C1C +:1060A0000000906E000090700000907200009074EC +:1060B00000009076000090780000907A0000907CBC +:1060C0000000907E0000908000009082000090848C +:1060D00000009086000090880000908A0000908C5C +:1060E0000000908E0000909000009092000090942C +:1060F00000009096000090980000909A0000909CFC +:106100000000909E000090A0000090A2000090A4CB +:10611000000090A6000090A8000090AA000090AC9B +:10612000000090AE000090B0000090B2000090B46B +:10613000000090B6000090B8000090BA000090BC3B +:10614000000090BE000090C0000090C2000090C40B +:10615000000090C6000090C8000090CA000090CCDB +:10616000000090CE000090D0000090D2000090D4AB +:10617000000090D6000090D8000090DA000090DC7B +:10618000000090DE000090E0000090E2000090E44B +:10619000000090E6000090E8000090EA000090EC1B +:1061A000000090EE000090F0000090F2000090F4EB +:1061B000000090F6000090F8000090FA000090FCBB +:1061C000000090FE00009100000091020000910488 +:1061D00000009106000091080000910A0000910C57 +:1061E0000000910E00009110000091120000911427 +:1061F00000009116000091180000911A0000911CF7 +:106200000000911E000091200000912200009124C6 +:1062100000009126000091280000912A0000912C96 +:106220000000912E00009130000091320000913466 +:1062300000009136000091380000913A0000913C36 +:106240000000913E00009140000091420000914406 +:1062500000009146000091480000914A0000914CD6 +:106260000000914E000091500000915200009154A6 +:1062700000009156000091580000915A0000915C76 +:106280000000915E00009160000091620000916446 +:1062900000009166000091680000916A0000916C16 +:1062A0000000916E000091700000917200009174E6 +:1062B00000009176000091780000917A0000917CB6 +:1062C0000000917E00009180000091820000918486 +:1062D00000009186000091880000918A0000918C56 +:1062E0000000918E00009190000091920000919426 +:1062F00000009196000091980000919A0000919CF6 +:106300000000919E000091A0000091A2000091A4C5 +:10631000000091A6000091A8000091AA000091AC95 +:10632000000091AE000091B0000091B2000091B465 +:10633000000091B6000091B8000091BA000091BC35 +:10634000000091BE000091C0000091C2000091C405 +:10635000000091C6000091C8000091CA000091CCD5 +:10636000000091CE000091D0000091D2000091D4A5 +:10637000000091D6000091D8000091DA000091DC75 +:10638000000091DE000091E0000091E2000091E445 +:10639000000091E6000091E8000091EA000091EC15 +:1063A000000091EE000091F0000091F2000091F4E5 +:1063B000000091F6000091F8000091FA000091FCB5 +:1063C000000091FEFFFFFFFFFFFFFFFFFFFFFFFF4A +:1063D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD +:1063E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD +:1063F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD +:10640000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C +:10641000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C +:10642000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C +:10643000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C +:10644000FFFFFFFF0000000300BEBC2000000000B3 +:10645000000000050000000300BEBC20000000009A +:10646000000000050000000300BEBC20000000008A +:10647000000000050000000300BEBC20000000007A +:10648000000000050000000300BEBC20000000006A +:10649000000000050000000300BEBC20000000005A +:1064A000000000050000000300BEBC20000000004A +:1064B000000000050000000300BEBC20000000003A +:1064C0000000000500002000000040C000006180C6 +:1064D000000082400000A3000000C3C00000E48070 +:1064E0000001054000012600000146C00001678050 +:1064F000000188400001A9000001C9C00001EA8034 +:1065000000020B4000022C0000024CC000026D8013 +:1065100000028E400002AF000002CFC00002F080F7 +:10652000000011400000800000010380000187008E +:1065300000020A8000028E00000311800003950013 +:106540000004188000049C0000051F800005A300C3 +:10655000000626800006AA0000072D800007B10073 +:10656000000834800008B80000093B800009BF0023 +:10657000000A4280000AC600000B4980000BCD00D3 +:10658000000C5080000CD400000D578000005B0010 +:1065900000007FF800007FF8000000D50000150023 +:1065A0000000FF00000000000000FF0000000000ED +:1065B0000000FF00000000000000FF0000000000DD +:1065C0000000FF00000000000000FF0000000000CD +:1065D0000000FF00000000000000FF0000000000BD +:1065E000000019000000000000000000FFFFFFFF96 +:1065F0000000000003938700000000000393870061 +:1066000000007FF800007FF80000068E00003500D3 +:106610000000FF000FFFFFFF0000FF000FFFFFFF64 +:10662000000000FF0000FF000FFFFFFF0000FF0061 +:106630000FFFFFFF000000FF0000FF000FFFFFFF44 +:106640000000FF000FFFFFFF000000FF0000FF0041 +:106650000FFFFFFF0000FF000FFFFFFF000000FF24 +:106660000000FF000FFFFFFF0000FF000FFFFFFF14 +:10667000000000FF0000FF000FFFFFFF0000FF0011 +:106680000FFFFFFF000000FF0000FF000FFFFFFFF4 +:106690000000FF000FFFFFFF000000FF0000FF00F1 +:1066A0000FFFFFFF0000FF000FFFFFFF000000FFD4 +:1066B0000000FF000FFFFFFF0000FF000FFFFFFFC4 +:1066C000000000FF0000FF000FFFFFFF0000FF00C1 +:1066D0000FFFFFFF000000FF0000FF000FFFFFFFA4 +:1066E0000000FF000FFFFFFF000000FF0000FF00A1 +:1066F0000FFFFFFF0000FF000FFFFFFF000000FF84 +:106700000000FF000FFFFFFF0000FF000FFFFFFF73 +:10671000000000FF0000FF000FFFFFFF0000FF0070 +:106720000FFFFFFF000000FF0000FF000FFFFFFF53 +:106730000000FF000FFFFFFF000000FF0000FF0050 +:106740000FFFFFFF0000FF000FFFFFFF000000FF33 +:106750000000FF000FFFFFFF0000FF000FFFFFFF23 +:10676000000000FF0000FF000FFFFFFF0000FF0020 +:106770000FFFFFFF000000FF0000FF000FFFFFFF03 +:106780000000FF000FFFFFFF000000FF0000FF0000 +:106790000FFFFFFF0000FF000FFFFFFF000000FFE3 +:1067A0000000FF000FFFFFFF0000FF000FFFFFFFD3 +:1067B000000000FF0000FF000FFFFFFF0000FF00D0 +:1067C0000FFFFFFF000000FF0000FF000FFFFFFFB3 +:1067D0000000FF000FFFFFFF000000FF0000FF00B0 +:1067E0000FFFFFFF0000FF000FFFFFFF000000FF93 +:1067F0000000FF000FFFFFFF0000FF000FFFFFFF83 +:10680000000000FF0000FF000FFFFFFF0000FF007F +:106810000FFFFFFF000000FF0000FF000FFFFFFF62 +:106820000000FF000FFFFFFF000000FF0000FF005F +:106830000FFFFFFF0000FF000FFFFFFF000000FF42 +:106840000000FF000FFFFFFF0000FF000FFFFFFF32 +:10685000000000FF0000FF000FFFFFFF0000FF002F +:106860000FFFFFFF000000FF0000FF000FFFFFFF12 +:106870000000FF000FFFFFFF000000FF0000FF000F +:106880000FFFFFFF0000FF000FFFFFFF000000FFF2 +:10689000000000FF000000FF000000FF000000FFFC +:1068A000000000FF000000FF000000FF000000FFEC +:1068B0000000FF00000000000000FF0000000000DA +:1068C0000000FF00000000000000FF0000000000CA +:1068D0000000FF00000000000000FF0000000000BA +:1068E0000000FF00000000000000FF0000000000AA +:1068F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA8 +:10690000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97 +:10691000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87 +:10692000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77 +:10693000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67 +:10694000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57 +:10695000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47 +:10696000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37 +:106970000000100000002080000031000000418075 +:10698000000052000000628000007300000083805D +:10699000000094000000A4800000B5000000C58045 +:1069A0000000D6000000E6800000F700000107802C +:1069B0000001180000012880000139000001498011 +:1069C00000015A0000016A8000017B0000018B80F9 +:1069D00000019C000001AC800001BD000001CD80E1 +:1069E0000001DE000001EE800001FF0000000F80CA +:1069F00000007FF800007FF800000344000035002D +:106A000010000000000028AD00010001000902068E +:106A1000CCCCCCC5FFFFFFFFFFFFFFFF7058103C41 +:106A20000000FF00000000000000FF000000000068 +:106A30000000FF00000000000000FF000000000058 +:106A40000000FF00000000000000FF000000000048 +:106A50000000FF00000000000000FF000000000038 +:106A60000000000000000001CCCC0201CCCCCCCC5A +:106A7000CCCC0201CCCCCCCCCCCC0201CCCCCCCC80 +:106A8000CCCC0201CCCCCCCCCCCC0201CCCCCCCC70 +:106A9000CCCC0201CCCCCCCCCCCC0201CCCCCCCC60 +:106AA000CCCC0201CCCCCCCC00000000FFFFFFFF1F +:106AB000000E0000011600D6002625A0002625A005 +:106AC000002625A0002625A000720000012300F367 +:106AD000002625A0002625A0002625A0002625A00A +:106AE0000000FFFF000000000000FFFF00000000AA +:106AF0000000FFFF000000000000FFFF000000009A +:106B00000000FFFF000000000000FFFF0000000089 +:106B10000000FFFF000000000000FFFF0000000079 +:106B20000000FFFF000000000000FFFF0000000069 +:106B30000000FFFF000000000000FFFF0000000059 +:106B40000000FFFF000000000000FFFF0000000049 +:106B50000000FFFF000000000000FFFF0000000039 +:106B60000000FFFF000000000000FFFF0000000029 +:106B70000000FFFF000000000000FFFF0000000019 +:106B80000000FFFF000000000000FFFF0000000009 +:106B90000000FFFF000000000000FFFF00000000F9 +:106BA0000000FFFF000000000000FFFF00000000E9 +:106BB0000000FFFF000000000000FFFF00000000D9 +:106BC0000000FFFF000000000000FFFF00000000C9 +:106BD0000000FFFF000000000000FFFF00000000B9 +:106BE0000000FFFF000000000000FFFF00000000A9 +:106BF0000000FFFF000000000000FFFF0000000099 +:106C00000000FFFF000000000000FFFF0000000088 +:106C10000000FFFF000000000000FFFF0000000078 +:106C20000000FFFF000000000000FFFF0000000068 +:106C30000000FFFF000000000000FFFF0000000058 +:106C40000000FFFF000000000000FFFF0000000048 +:106C50000000FFFF000000000000FFFF0000000038 +:106C60000000FFFF000000000000FFFF0000000028 +:106C70000000FFFF000000000000FFFF0000000018 +:106C80000000FFFF000000000000FFFF0000000008 +:106C90000000FFFF000000000000FFFF00000000F8 +:106CA0000000FFFF000000000000FFFF00000000E8 +:106CB0000000FFFF000000000000FFFF00000000D8 +:106CC0000000FFFF000000000000FFFF00000000C8 +:106CD0000000FFFF000000000000FFFF00000000B8 +:106CE000FFFFFFF3318FFFFF0C30C30CC30C30C329 +:106CF000CF3CF300F3CF3CF30000CF3CCDCDCDCD66 +:106D0000FFFFFFF130EFFFFF0C30C30CC30C30C3AB +:106D1000CF3CF300F3CF3CF30001CF3CCDCDCDCD44 +:106D2000FFFFFFF6305FFFFF0C30C30CC30C30C316 +:106D3000CF3CF300F3CF3CF30002CF3CCDCDCDCD23 +:106D4000FFFFF4061CBFFFFF0C30C305C30C30C3AC +:106D5000CF300014F3CF3CF30004CF3CCDCDCDCDEC +:106D6000FFFFFFF2304FFFFF0C30C30CC30C30C3EA +:106D7000CF3CF300F3CF3CF30008CF3CCDCDCDCDDD +:106D8000FFFFFFFA302FFFFF0C30C30CC30C30C3E2 +:106D9000CF3CF300F3CF3CF30010CF3CCDCDCDCDB5 +:106DA000FFFFFFF731EFFFFF0C30C30CC30C30C304 +:106DB000CF3CF300F3CF3CF30020CF3CCDCDCDCD85 +:106DC000FFFFFFF5302FFFFF0C30C30CC30C30C3A7 +:106DD000CF3CF300F3CF3CF30040CF3CCDCDCDCD45 +:106DE000FFFFFFF3318FFFFF0C30C30CC30C30C328 +:106DF000CF3CF300F3CF3CF30000CF3CCDCDCDCD65 +:106E0000FFFFFFF1310FFFFF0C30C30CC30C30C389 +:106E1000CF3CF300F3CF3CF30001CF3CCDCDCDCD43 +:106E2000FFFFFFF6305FFFFF0C30C30CC30C30C315 +:106E3000CF3CF300F3CF3CF30002CF3CCDCDCDCD22 +:106E4000FFFFF4061CBFFFFF0C30C305C30C30C3AB +:106E5000CF300014F3CF3CF30004CF3CCDCDCDCDEB +:106E6000FFFFFFF2304FFFFF0C30C30CC30C30C3E9 +:106E7000CF3CF300F3CF3CF30008CF3CCDCDCDCDDC +:106E8000FFFFFFFA302FFFFF0C30C30CC30C30C3E1 +:106E9000CF3CF300F3CF3CF30010CF3CCDCDCDCDB4 +:106EA000FFFFFFF730EFFFFF0C30C30CC30C30C304 +:106EB000CF3CF300F3CF3CF30020CF3CCDCDCDCD84 +:106EC000FFFFFFF5304FFFFF0C30C30CC30C30C386 +:106ED000CF3CF300F3CF3CF30040CF3CCDCDCDCD44 +:106EE000FFFFFFFF30CFFFFF0C30C30CC30C30C3DC +:106EF000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD98 +:106F0000FFFFFFFF30CFFFFF0C30C30CC30C30C3BB +:106F1000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD76 +:106F2000FFFFFFFF30CFFFFF0C30C30CC30C30C39B +:106F3000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD55 +:106F4000FFFFFFFF30CFFFFF0C30C30CC30C30C37B +:106F5000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD33 +:106F6000FFFFFFFF30CFFFFF0C30C30CC30C30C35B +:106F7000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD0F +:106F8000FFFFFFFF30CFFFFF0C30C30CC30C30C33B +:106F9000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDE7 +:106FA000FFFFFFFF30CFFFFF0C30C30CC30C30C31B +:106FB000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDB7 +:106FC000FFFFFFFF30CFFFFF0C30C30CC30C30C3FB +:106FD000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD77 +:106FE000FFFFFFF3320FFFFF0C30C30CC30C30C3A5 +:106FF000CF3CF300F3CF3CF30000CF3CCDCDCDCD63 +:10700000FFFFFFF1310FFFFF0C30C30CC30C30C387 +:10701000CF3CF300F3CF3CF30001CF3CCDCDCDCD41 +:10702000FFFFFFF6305FFFFF0C30C30CC30C30C313 +:10703000CF3CF300F3CF3CF30002CF3CCDCDCDCD20 +:10704000FFFFF4061CBFFFFF0C30C305C30C30C3A9 +:10705000CF300014F3CF3CF30004CF3CCDCDCDCDE9 +:10706000FFFFFFF2304FFFFF0C30C30CC30C30C3E7 +:10707000CF3CF300F3CF3CF30008CF3CCDCDCDCDDA +:10708000FFFFFF8A042FFFFF0C30C30CC30C30C37B +:10709000CF3CC000F3CF3CF30010CF3CCDCDCDCDE5 +:1070A000FFFFFF9705CFFFFF0C30C30CC30C30C3AD +:1070B000CF3CC000F3CF3CF30020CF3CCDCDCDCDB5 +:1070C000FFFFFFF5310FFFFF0C30C30CC30C30C3C3 +:1070D000CF3CF300F3CF3CF30040CF3CCDCDCDCD42 +:1070E000FFFFFFF3320FFFFF0C30C30CC30C30C3A4 +:1070F000CF3CF300F3CF3CF30000CF3CCDCDCDCD62 +:10710000FFFFFFF1302FFFFF0C30C30CC30C30C367 +:10711000CF3CF300F3CF3CF30001CF3CCDCDCDCD40 +:10712000FFFFFFF6305FFFFF0C30C30CC30C30C312 +:10713000CF3CF300F3CF3CF30002CF3CCDCDCDCD1F +:10714000FFFFFF061CBFFFFF0C30C30CC30C30C396 +:10715000CF3CC014F3CF3CF30004CF3CCDCDCDCD1C +:10716000FFFFFFF2304FFFFF0C30C30CC30C30C3E6 +:10717000CF3CF300F3CF3CF30008CF3CCDCDCDCDD9 +:10718000FFFFFFFA302FFFFF0C30C30CC30C30C3DE +:10719000CF3CF300F3CF3CF30010CF3CCDCDCDCDB1 +:1071A000FFFFFFF731CFFFFF0C30C30CC30C30C320 +:1071B000CF3CF300F3CF3CF30020CF3CCDCDCDCD81 +:1071C000FFFFFFFF30CFFFFF0C30C30CC30C30C3F9 +:1071D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD75 +:1071E000FFFFFFFF30CFFFFF0C30C30CC30C30C3D9 +:1071F000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD95 +:10720000FFFFFFFF30CFFFFF0C30C30CC30C30C3B8 +:10721000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD73 +:10722000FFFFFFFF30CFFFFF0C30C30CC30C30C398 +:10723000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD52 +:10724000FFFFFFFF30CFFFFF0C30C30CC30C30C378 +:10725000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD30 +:10726000FFFFFFFF30CFFFFF0C30C30CC30C30C358 +:10727000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD0C +:10728000FFFFFFFF30CFFFFF0C30C30CC30C30C338 +:10729000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDE4 +:1072A000FFFFFFFF30CFFFFF0C30C30CC30C30C318 +:1072B000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDB4 +:1072C000FFFFFFFF30CFFFFF0C30C30CC30C30C3F8 +:1072D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD74 +:1072E000FFFFFFFF30CFFFFF0C30C30CC30C30C3D8 +:1072F000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD94 +:10730000FFFFFFFF30CFFFFF0C30C30CC30C30C3B7 +:10731000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD72 +:10732000FFFFFFFF30CFFFFF0C30C30CC30C30C397 +:10733000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD51 +:10734000FFFFFFFF30CFFFFF0C30C30CC30C30C377 +:10735000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD2F +:10736000FFFFFFFF30CFFFFF0C30C30CC30C30C357 +:10737000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD0B +:10738000FFFFFFFF30CFFFFF0C30C30CC30C30C337 +:10739000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDE3 +:1073A000FFFFFFFF30CFFFFF0C30C30CC30C30C317 +:1073B000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDB3 +:1073C000FFFFFFFF30CFFFFF0C30C30CC30C30C3F7 +:1073D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD73 +:1073E000FFFFFFFF30CFFFFF0C30C30CC30C30C3D7 +:1073F000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD93 +:10740000FFFFFFFF30CFFFFF0C30C30CC30C30C3B6 +:10741000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD71 +:10742000FFFFFFFF30CFFFFF0C30C30CC30C30C396 +:10743000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD50 +:10744000FFFFFFFF30CFFFFF0C30C30CC30C30C376 +:10745000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD2E +:10746000FFFFFFFF30CFFFFF0C30C30CC30C30C356 +:10747000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD0A +:10748000FFFFFFFF30CFFFFF0C30C30CC30C30C336 +:10749000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDE2 +:1074A000FFFFFFFF30CFFFFF0C30C30CC30C30C316 +:1074B000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDB2 +:1074C000FFFFFFFF30CFFFFF0C30C30CC30C30C3F6 +:1074D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD72 +:1074E000000C0000000700C000028130000B815832 +:1074F0000002021000010230000F024000010330C0 +:10750000000C0000000800C000028140000B8168F0 +:10751000000202200001024000070250000202C0E7 +:10752000001000000008010000028180000B81A80B +:107530000002026000018280000E82980008038031 +:107540000010000000010100000281100009013854 +:10755000000201C8000101E8000E01F8000002D895 +:10756000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC5B +:1075700000002000CCCCCCCCCCCCCCCCCCCCCCCC5B +:10758000CCCCCCCC00002000CCCCCCCCCCCCCCCC4B +:10759000CCCCCCCCCCCCCCCC040020000000000067 +:1075A0001F8B080000000000000BFB51CFC0F00350 +:1075B0008AB7B13130ECE644F0E98159181818F86F +:1075C00099C8D7BF1168C04E20BE01C4075948D71B +:1075D0007F551AC15E26C9C0700A8827883330B427 +:1075E0004A21C4ED651818EE01F92BA16272403DE5 +:1075F00073A4C977F3281E3CB8D014951F620CA160 +:107600005F9840E82234F950A8BCB81E842E36C5D5 +:107610006EAE841E71F6A7A9A0F2BD55F0ABCFD512 +:1076200040E5C7A2A90F81F2017EE9B234D8030078 +:1076300000000000000000001F8B08000000000098 +:10764000000BED7D0B7455D5B5E8DA9FB3CFFF6421 +:10765000278470123EEEC400C1063C4280A0A83BC5 +:10766000FC1A7DD41E1025E5A11C446B004922A6FE +:10767000D78C96D76CC8870450E3E751BD457BA0F3 +:10768000D88B0E5BA3A68ABDB43D887AA9C3DB2242 +:107690005AA52D7A83FA2C58A0B1572ABD4FCB5B3F +:1076A00073AEB592BD77CEC9C74F47EF788D43769D +:1076B000D6DEEB3BFF6BCEB95634D94FF22E27E422 +:1076C0001CFCD0A7291142A6F73DC92D5932C92368 +:1076D000E41B3E823F1FF923534816210D3EF6BCA2 +:1076E0003D10D905CF2D8D84A426C2F771491221F2 +:1076F000244848899A0B2D02B1870BE15977617CA8 +:10770000323E67C23387C8848C84F218FDBD20EBFB +:10771000FB9C42FF399AA880F114F68AA8A43C96F3 +:10772000C2F6DF226446DF3C48DD57F578B86FDEED +:10773000EEA7A26B24C5EB9E837F94E5598950E6A2 +:10774000FA0D47A5C79FB7D51F4FC2B9382F95A8C7 +:10775000382FDE9E108BD8E7E7EEE7A346F2F8F36A +:10776000E3FBC32DD3B8026E6D8D3E7CB636EA24A2 +:10777000E5258436333B4BE93344CC5DA5FDDBCDB9 +:107780002312871F9F0F8C63D0FAF47F42E1DE9CA7 +:107790004B9241C0214938E0D61C5AEC33D3F42730 +:1077A0009E2497C2AD84CFB9A8FF7AFD302F0A0777 +:1077B0003FCC2B0D3C97C2BCA6F79F97BFD83DAFDF +:1077C0006A6287CF70E7159844C821C0876A128221 +:1077D00078B9CDD19FAC9B56779AFE08A70BD5E020 +:1077E000EB1B229E822572DFF8000723E0A02F6F9B +:1077F00034C7496F6EBA067820BE3A387CE20AE395 +:1078000007AB0F8FF4199A1D93803568F110E02DA6 +:107810009F30F8E557B7DE2A4F2194D53A0F4EA096 +:10782000F0CBEF5EB99040F9E8152780DF9ACBA640 +:1078300056CEA5F5B2CB63AF2CA04D423143027AB0 +:10784000DD0A9D15407F5FB32A68B909FAA365CBAD +:10785000BACAB4106EA6036E1472864ACB1EF8B56F +:10786000280DFC482F1EA473DEFEED33C1CF436C00 +:10787000F8437E5EEFA0CB8C78BF91E1CBA2FF01F5 +:10788000BE46101B5FD37EB22B35075EB25CE33C75 +:107890000ABF20BC6FFD9B8C97439EF41994CE3D8C +:1078A000A5B29EA478CA26B16CB58CE263A14A4009 +:1078B0008EE5E4EA1290C360786926A412F89F4A24 +:1078C00007B2C826E77ECEF9AB60CDEE9DAD749CC5 +:1078D00033B34331A895AFD3B94EEDBF9E3B40BE05 +:1078E000786DE5B2E74802C7EB3C5844E76595C9B7 +:1078F000B18729DD6C2D3DACDBE5E3B15EF9E2A695 +:107900000F62A833B83CA0F0514A65D31FF9ECF4DC +:10791000A17C4AFA08DFE8C4C770F1757A98F4F1DF +:1079200059C71378EDCF571B055E7D847EDF52B2B9 +:1079300078407DD51FAF4F92046D172A2566324DD2 +:10794000BBFFB4EB0BF7D326DFDD72541935A36A06 +:10795000E74078CB75AE57F4EB6F508C7747D0A2E9 +:10796000AAA37CD5B81E688FDE63114A776740F6FC +:107970005078281D17A5A04C8A49EC61D64D4AA223 +:10798000657FD44C6E413A48225EC4FCBC86EC90C4 +:10799000B36AAE530E932A4BB2CFDFDFA0E13C3483 +:1079A000182F17EC02DA2105851A2229A05B41AFB6 +:1079B000A092CE9D0F65A79DD1664C25E9F0A072DF +:1079C000BC4B92A0D76F0D4DBEB8C75BE29CEF9049 +:1079D000DB8554E33DD1268D9CEE6BA792F7047EA8 +:1079E00028102F13761DC7D3660FD92B5D48E5C12C +:1079F000986BC152209BE1D32C6A87C0932A9FCDFC +:107A000063A6EA4057648FA4C23C71488A4742F596 +:107A10001DD40B4A06F623FBEA90FE9490894FF1A1 +:107A20003DF3BCD8F8BD655FA206F0531DD58C2D83 +:107A3000748E6B15D3D80874318DC9A7EAE88479A0 +:107A4000A0EF3C129BD7B7A57C5C879AD39687762C +:107A50005906FBAE5AA52A7F2A7CDF3661207E229A +:107A6000494F4FB70D9E6E7BF06689DA835FA2BFE8 +:107A7000CC2433018E7F8A2DCE4A0D80AFF71B0FA9 +:107A8000EAEAF83E7BD0FD7DAD42EAD2C98156C913 +:107A9000C7F8D26769601F8875AF0576A720DD1625 +:107AA000DBC4D69B9B8BF05DBBE717BA6AE3BFB51F +:107AB00054CD78A7F65F8F80B7E8A7B77DF2A0A373 +:107AC000BDBB5D6F7F425E507B18E85CD041504A81 +:107AD0006C95E87B6F6CB105EA6CED63150CFF19D2 +:107AE000E6DF8BAF4F397FD16E30BAFAD3EEA656B0 +:107AF000D04FEF691D575D4CE9E8F74F28B14DF4C1 +:107B00006BF58E89F3C05E7A8FD3B7C0D389DD4D14 +:107B100079E9E823139E7E21F9711C415FD5F2F2C9 +:107B200001E96130FA7ACA4D5F9D577F21F475C82B +:107B30004D5F1C1E273BD9FAC9FD23185E38BEDCF9 +:107B4000F8C988974FDBAE3F3DFD5AA27CEDEDBCF6 +:107B50003A3D3DF1F90A7C7DD6F90E4647798669B2 +:107B6000EA74FC51D48E91407F9491588ACE53A7E9 +:107B70000FD45B31A6B7845C12ED4F4BCC4E53C98A +:107B80006BD85E21294B477BDB6967CC57E84BDA22 +:107B90004F7309497A715F64FA504F95A884E93FA1 +:107BA00033943F03EC08FEA3CC8EC1BAB3C0FE07EA +:107BB000FD359BEB5F89DA5B747DA132E7BE37E070 +:107BC000B23F14BE5FE8676F0D737FEC97F9FE3824 +:107BD0004842A88FC4FE38037FF6EE8B395C476AB3 +:107BE000C494E9BAB5839EE42609B41B41FD4C8ECA +:107BF0004A49E62F20256037AF970A62A00FE83E7A +:107C0000AF278B7E7FEF070AEA878668DD8A1658E2 +:107C1000F6B50D13BBE9B8F7349269C59EBEF1EE17 +:107C2000513B7C00EFF6E2F50EBBF6BB52A250B61C +:107C3000E91D7F549B563C0D8653DFEEA6F090293C +:107C40002081FF02A1FBA22F18003FF6BE174EF6BF +:107C5000B2D2BF9C0B364F011653B02F6DA7B63B67 +:107C6000B9188AA3A50A4A07ED1EFEDDFA4D05ECF8 +:107C700077DBFDACBC63D3AC8D169447F2FA561596 +:107C8000FB9ECFCAB76DFA4105EC0BDAB2E99AA9AF +:107C9000BE6EF324ABE269F8FB365976D85F4DC669 +:107CA00082F2FF43D7E1F79917BD40E1498112B352 +:107CB0000CD26B97150ABF41C7DD952500FFD7147D +:107CC00002F4EC3762F19B0CA43FA47B7FAE19DB7E +:107CD000424B0DF4850CF528DE1E96605FC7EC3133 +:107CE000F0E79C43FAA57C41BFAFCFD6B13ED16D42 +:107CF000F659519F3DD68B2717DEEE557BFC80B79A +:107D0000EF8DF9F01713693FD642390664F3BD0DC4 +:107D100045D92B6D787CCC37A70AF0489A73D12EC1 +:107D20008992DE1F13CA62DF5C403A2BC0781C4385 +:107D3000251FA1743A2EDE53012830AAF4E7708F74 +:107D40004BE6E9EFA15DA548E7BE34743BCA0D07D9 +:107D5000DAE3A845543E8D90483C9DDC5DA9E6A041 +:107D60003C185149D73B809FE09B549F30FB2CE14E +:107D700003FF56A67132CDF333C073934CC71D4D2C +:107D80009208A7C1E09A099EADD127B3515E7FCE7C +:107D900070CDD4DE0DCF1112E397956A39F2CB5036 +:107DA000FD3B6D7C3FD5027E38FA6CE27E38777BF6 +:107DB000BFDA416269F0EB379CFE210DF625B67201 +:107DC000BD6C307D1072FB89189EDD7A6101D70B86 +:107DD0002D51AA17983C5C087A20C8E1DF02BB7ECF +:107DE000909F6192B4E8F720F707915226FF7DF447 +:107DF0003FE0B751554E7DA00D511FBC2BC55F9084 +:107E0000910E8904F3BB5FEAB86202D04F3EB3C75C +:107E1000A337B445133638D4CB4CDF097D962C16E6 +:107E2000FA8C20FCCEE37348920E3FE8C307362C51 +:107E3000CE42BFDD8D41871C8AB62EC6FDAF8D9E1A +:107E4000D12FDAC1FDA399F0A76BC9443A7958A89C +:107E5000307918317B52E0F34342CEE32E434ED6C5 +:107E60000CFEC4B10F8B4CED39783E5DEFCE8BE448 +:107E7000D826DA4E9DADA63C14BE6AF98B55127D0C +:107E8000EE2C64F0B76611A4D390B1E08402FA58E6 +:107E9000ED467F4DA8D2BD2FB69515E8A7E77AD459 +:107EA000DF763FF500FBB8A13E9B28BCDEB6F13F74 +:107EB000855C4AA1EB50371003EC09D5A4223102AE +:107EC0004F3D0FE8453563217C765754C2F3BCD94A +:107ED000F14AD9A6075433BE05EA8FF8CA7DEDB042 +:107EE0005EF526595624C6073936789B4AA1633F6A +:107EF00097ADBBFCA589D62AD4EF8646C617F69F58 +:107F000077BDAC72B9E7A417412703C8BBCF441FA4 +:107F10006FCAC25FEDC4BF834E8AFAF02BDA85FACE +:107F2000F9AB9CF875973F6FBCFA014F141FE751EE +:107F30003C017D9E379BD123B547D17E7AC0D76166 +:107F400002BC1F2836644BEA6B175672989FF92CB7 +:107F5000DD6851BBE7FE95DB4D68975F4C6580841B +:107F6000CFB4FEA37A59C376542E542ACC6E97C050 +:107F70001E9FAF6CAB82F63B295E81DF77027F43A9 +:107F80007C20A1A11CAE97DB2B36D2BE5B8F4AB200 +:107F90000246ACBE14F1EBE7FCFE912751097EC806 +:107FA0002DFF4B26BB0CD04B03FBBD9A38BE4519A9 +:107FB000FC0D609F8CA9D3A702D833B5DB5E275791 +:107FC000A65B57B5C2F07F47DDE10E344F9F77EED9 +:107FD000473CCB4DA048D897542B36FA0E97317FAB +:107FE0000749D0F5407D4E371F150E4CAF0FBAE64E +:107FF0003F96C753DCF55E56B8BFCE60F03244FF03 +:108000001B07EE5FC0E76C9BC2E323D40043221E34 +:1080100049ECFA5BB9F15005BCA75CB709F0B55D56 +:1080200026D5CCDF1C473D14E1E3ED2CCFC1F60B88 +:10803000552647C79AFA16C0F7D866192C05F2B824 +:1080400062E0FB51CBEBF67B281EDA0B492C64E097 +:1080500010D8EF8BE335A4CBFC5CA6C7F2EB290963 +:10806000D07AF9A52469D0F6EDFB1FA8D068394273 +:108070003754600AFBCA193E7D252406A690C72204 +:1080800029997D4F424C5229EFB140951E183F036C +:10809000F75F77E69298D7E8931B82AEEE6CBEC787 +:1080A0000F7AE481E27BAE9800FEC65215FDE4E44F +:1080B000630A27E14F54205E163761BCF6596CDE27 +:1080C000F40DE253D5D9FAC7DC3F1BF9A43DFC34CB +:1080D000CEC35A4762E3B15E8C60FC860A54F05707 +:1080E0003655337BD78D8FF524F1B832DD4EAF870F +:1080F000906EDA3F51F8BEE0C58D60E78F835F690F +:10810000F9974D7FDC381CBB45C40F85DDB245EDCA +:1081100044BEB728CF815E12768CBFB813C7FDBFAF +:108120009CDE87DABFBFC4E96F75DB356E7BA65E68 +:10813000D61DF6AB7B5D1F795257C0FCB6E4537E6B +:108140004FA3077E03FA9AB6DF115DFCAB89465F49 +:108150003F7D72C8C0EFA23CE6AC86F8197A7D2A52 +:10816000F7608F6632BE1A2BE4D037285F0D107F80 +:10817000147CF511151287804FD40EA42F6296201F +:108180005F097E51BA3BDACFA7F460D4CBE0B906E1 +:10819000FE2239B45C48E93D65B38784BC504B3B53 +:1081A000E313A5FE74F7A021231ECF94317F7596AB +:1081B000D56D4293606927C6F5285DFD17D095AA55 +:1081C0002725C0EB98FB17E0BA7EA93056F7AB2CF9 +:1081D0007EEC5EC7CF397C89BE1BED793F1B8EB22A +:1081E000F87D31363F579CBDFE5703C6D9FD319708 +:1081F0009D334C3F428ECAFD08DCEF3558FBE1C68B +:10820000D795B323903E7ACB19E4ED4D2AE78BA3A3 +:10821000BB1C70E9070F65476CA0F9F9859FFE53F9 +:10822000C60550870D010E6E385EA23AFD879F3756 +:108230001CDDF1EF97B8DC1F4C1E044D33252BE0FD +:108240003F23CCBF1322DCBFE3A4F79DCD32DA215C +:10825000C1B0BC134CC9ACFA6ED4C1627C4AEF55B4 +:10826000AA8DDE47971E4A413BB73ECAA4870693B4 +:10827000B7AB7CE60D2ACAADF4FBF1BE7C03CA2580 +:1082800069F20D32E2B5EEF3C937182ABC7BFD9BCB +:108290003C7FE0867241C7C6D2DF51B8AC3EE821D0 +:1082A000E897F998AECE16575BCDF78137F07DE4AD +:1082B0008D241E818FA7885C09FC728A1C8E4CB3AA +:1082C000C993FB548DF14B9BE76DF0AF8A78F94D64 +:1082D0001DAC2CE673F3FDCEF2D7C9E23CF0EB7D8A +:1082E000FD3E0FE26BB5CBBFD6AC32FD7133A96B4F +:1082F00005BCB5784815C8B11B74A28EA0A6EBBA10 +:10830000671E9CB19296BFCBED91F7A95C366C715C +:10831000D035A1A406F87DA76BDAB59710689F6CDD +:108320002D807D5A36C17DAB1BCEABDA9CF31B6C26 +:10833000FEEEF952F2C2F9669A87BA474A6B4F3F8E +:1083400022E40DC757A6BC2A914FF50B20205ADF17 +:108350009A43D8BEF3AD60B209E535CBA71AACFDA0 +:108360002F55463F9FB6FDAB83B45FE7EB5900CC7A +:10837000D6966BC5C12F24E28235A4CE1C4D7F5505 +:10838000F72DB246135BBDE810EB150F5C2FD3BC85 +:108390004FE83E4BBEB06FFEDF9512C7D434F3BF3B +:1083A0005D49D440FF5EC083024F15F18D7E608A27 +:1083B000DF5A35D4266541BE5317EE03FD86EAA089 +:1083C000875AF805E45A09936BC112E777B77FF82B +:1083D0004355C4E153C87F188236C07E08A514F007 +:1083E000DF94AB277BEBD3F16A605D1742298E7275 +:1083F000A35E67F56B8871D7EC32E43F8C3FD4B74E +:108400009F8F71F5FA9106FA77551233B10F17DD88 +:10841000D59E9548D2A60F6BD51E0DF8AC96DA45C1 +:10842000F6F7EBA38AC34FEB7E7AA8E51C2A817D81 +:1084300092CCFC483A2DDBD6FDA70E89E7AF185940 +:108440004B06F0DFAD8F327FF00DEDE3B398DFD058 +:10845000297F4F3732BFDCBF3DF67D0DFCFCA71EE8 +:108460003D7615C07BEDBF2AC407F91B8F85490AED +:10847000EDB1A406F6D89A2EC54CA6CDAF6862F130 +:10848000CFC7C388AF354F7A930B69FB354FBF33E6 +:1084900085D0F99DDED4F3E268B09B1F95581E820B +:1084A000D53DE56AFA7E8D4A56A4F31B4CF630F9A9 +:1084B00073F2D96015F0B7B467FFF5D86FE7528F44 +:1084C000D7B6DF2EF678906F693D66973F2225C7B5 +:1084D0004BE9E6C7F23F4E3E22B1F9EDF524FD30FF +:1084E000BF3D3BB5049D47ED9E0F509ECC7DFC8764 +:1084F000118043ED5EC5A1076AF72829EF147C1EA1 +:108500008327C48DA41940279C5EBAD661BCA8A657 +:1085100073EB07E0C7A8DDEB946B142EB114C0F524 +:108520000D25B610CA4FFD4BC4A0A07AFFD0C311D1 +:10853000802BED77A59605FAC649DFD0FFD99CFEC2 +:10854000FD11D283F1BADACE76365ED7577E0F7A36 +:10855000A5D6253FDF875FF2FBDB33D7785CF6CC0F +:108560009EA1C5EBD6FEF0CC43161DF7E4937F78B1 +:10857000C8A2F3BFE5AFFFF9D0B7803F7FE6D74190 +:10858000FED73EFAEB08B1D163AD87F1E3E9B1C4A0 +:10859000A27B5472FA37DE24F84B4EFFF4F7E30C5B +:1085A000BAEED34FFC25CFA0F5EB7F3A7F14C0A1E4 +:1085B000FEC773470DB4FF067A4D7AEDF34A225E8B +:1085C0008DBD123382F6F1A70B3F07BA0E8C83796B +:1085D0009E3AE28D81DBB996BE6B980AF85A87FA0B +:1085E00018CA1B289C6B1EDBFC01C889FEF0B6462E +:1085F000CBE8AC4F8D06A77D4DD73B0B106FA40782 +:10860000F5A8BB7EED6B149F1766C6DF19F2B106A5 +:10861000F2AEF6B176365E27C55FA43FFE4EC12F9F +:10862000B3FAE3EF0E17FECE905BBE970F798D5D28 +:10863000231C7152F1EC8B0FC6B3E203C80B210F60 +:1086400006836FB5C4E6B5CC633EE801BE7A32D886 +:108650008BDF8580DF1F9E1947287D1CF7F45C0F98 +:1086600072B3E7A75E7D177DBFE6A76F209F9DFED3 +:10867000F12B9A81F9992424E5F13C31F67308E451 +:10868000700DDBCB91DADDE19437D287A79AE4A2B3 +:108690004A2382EF8FE1FB24A3FF9AE4FE25521ABE +:1086A000BCBDE1296276407224C265DDEEDF69CC93 +:1086B000BEECC3A7540EF83CB600DE67C2A758BF95 +:1086C0000EEB9F69C3EB6EC6B7EEFA35943F41EFF0 +:1086D000F5C36F527A039EA7777A55D07BA7C1FE68 +:1086E0000AF5C77B1FFC99FD33DCFDCA2B6EFE1615 +:1086F000F1630E87CCF461713B60E0F50D177E3FAE +:10870000F7180E3A12703CF9717AF97F8ACB8D1AFC +:10871000625516D8EC139F87DA27905F46E2D6E8B9 +:10872000C2BEF99E847D04A5BF938F2A18AF69ED60 +:108730003C8072DC2D2F6A48FA7DFB5F3DCC5EAC3D +:10874000D9BB7F0AC8B593CF3D8BF459F3D8310D0F +:10875000F62F2FEE794AEB2EEDE307D00F499B7EE3 +:1087600038F9A3FD53983C48BFFF0D6AACFFDA7D92 +:10877000CEFE6B1FFBC0D1FF5AAB5363790C038F46 +:10878000F3BE6A2E85F5BE7FC843409EBEDFA9A416 +:10879000F5BFF670FD28E0D4FACA82DF419CBFEC39 +:1087A00070C0003DDAB5C91C7507D86B873D04E47D +:1087B0003751CD3F7869B9EB9500C633BA0E5FAB40 +:1087C0001836FFC4332E78CE7CCD9A1BA6FDCDEC97 +:1087D0008E97C116CA2D37CA8FD27DA3DD7FF54A89 +:1087E000E52890FBCD60CF4F84F16251F07F289156 +:1087F00005952C7F50D6FD69F537EBCF138A63BE04 +:10880000A047977B7DB6488F62BFC5FD4DADA1F4F3 +:10881000FEE8059AD817D0716D7290DAAA55E9F082 +:10882000364B637648A6EF976ACCDF93E97BC52089 +:10883000ED7BF99BE3470BCBF174F39EC6FB71FB19 +:108840005733C9030FEFA74C331CEB05782FB2E564 +:10885000C58F26C98D90274A4221773C3AEEB3C78F +:10886000A3AB0EED87F873EED5FBF201FE11D2AC8F +:10887000BF87763C899D1BC08E75C79FDD7989991E +:10888000E2D1BE50CD9114E9DF5FFFF8BB897928B2 +:10889000CD63E6F90A6DF1F766BD5FFC7DBD46C7A5 +:1088A0006DC9808725DA9C7FD280BE649248F77DAF +:1088B0000BA79BCB49F7532B619E3116BF9FED82CF +:1088C000D7A51C5E3F3B9F2E9CAA9E0A62A81E0A4B +:1088D000DFB94BCC661081F397F7ACDD0F7C26E255 +:1088E000F7D644F95C70E8F01B6E5EC42ADFE27BC9 +:1088F000B521E445103D27AD5EE89B87C5F755518E +:10890000DC2779389F1D78F3661FC82D95242A0B24 +:1089100061BFC4E39A986F4FFBCB4BF98949E7AB32 +:10892000E906DADB79A9D50FDC0471757D0CC62365 +:1089300094B397A0FFD0DDAF128D59980F16322A4D +:1089400014DB38ADB92C3EA3EAF1B479C3ABB4C49F +:1089500013B05EE5EC65D8AFEC8B613D121A5ABEE0 +:10896000EC77AE8E207C7D14BE201F1164B02E9E4D +:108970003775F7D511D433FE839E9DF0DD1F6279E4 +:1089800054B7CB8118E459B9F3A82ADE6A27D05F1F +:10899000EB3109E328827E5B0BEBCE03393E401EB0 +:1089A000D54B9ACDAF9E298FCA1FBA11F3A8FC9F51 +:1089B000368FCA2A9807F6586B361179559644E7D0 +:1089C000D1CAF3A2FEA3F5A5B9A09F5AFDE2FBCB45 +:1089D000734D7BD95A7F00CB3CEF6AB4B7BD09EA2F +:1089E000E78E26759DE8CF33C93536391BF1AA08C5 +:1089F000E77FD6CC7735479E7CD4115F3AF0E666A8 +:108A00001FE86FFAAC2C02F851BA02BB3D2FD54ECD +:108A1000ECFA483C051DB5160F1CBF53CF5E847E93 +:108A20007C51F6E949D34C537FBE8FD91F827E7D9E +:108A3000B924097AC967241EB809E83937140B32FA +:108A4000BAC438595B08DD53FDD6D1567C03C6DB6A +:108A5000CEE804B95ED071FFF95FC6E75F64615C80 +:108A60002244309E96791D65B88E559A19F6DAE043 +:108A7000987B5EFABCD4BBBD6C3D2DF1E52CEFAC10 +:108A8000DA198715791AA27E504A1478411EE6B287 +:108A900038ACEC63FCD6872FAA2A6CFECD26B2DC5C +:108AA0000212509777E2D146554F62FD127FE27C69 +:108AB000AF233ED7CDE2BAAE78E27CE516C6DF83BF +:108AC000E04F9CCBD80A71B789109F8BF2F37D06DB +:108AD0008FD3992CAF28033DB5150F1C87EA688CFE +:108AE00061FBBB1ACB59BE9244B85F3BD9047402F8 +:108AF0006E0946F73F6802BE092B822F7E88E53B50 +:108B00002556BEC9FBCC5CC8373CF0E61B55AB28EC +:108B10007DB49A01E4FFC1D6A72767205E873B4E4C +:108B2000FFF5B271DBCC10EE77075BB79E62E30E08 +:108B3000751C115FEB5B9F0FC769350619A7838D05 +:108B400033F8FC199FDCB17F35E62FF828FFFBE9ED +:108B50007BDFEC1E9248D37F16E79F036F7A515E4E +:108B6000B7E5B2FC284F49C8644E4067FF9ED2BCAF +:108B70003978DEA1EC02CC9FBF637F3BCA190DC6DA +:108B8000A1553CB1D04AD62E61C239DBC83C82F136 +:108B9000674F49DE2A78DF403AE273400F97CB2CCB +:108BA0003FB9A4E426E8271BF892CEA3DCC7F69DC4 +:108BB0009E928B6F86FAFBA7BF9E68023895333A68 +:108BC0002007F31D706C358AC4B99D01F9DE53EEA0 +:108BD0008C5B109F33FF93A84B306E4EE54287D7D6 +:108BE000665752BD781FF23329B3C0DEDBFEB56B8A +:108BF00063767EFE672DFE1D565FE46B093E4F9F38 +:108C000037D79A2BF2E6123EA50CCE29F5E6532F64 +:108C1000CCB7E77FF17CEA90C8A7E6F1CC0EFA5F0B +:108C2000BAFC39F739C6CF2B9FFA292FDF0F07C9B6 +:108C300058C8A7FE8987C4529017F36B250679316F +:108C40006EFA70F7E73E07D06B8F64E0E7F7013804 +:108C500036B9979F70E1ED463FC6E7C478CF837C75 +:108C60002A1D9C4F47573BFB195BE73C9F755E8372 +:108C7000335E55681538EA9FDF56E4F83EBEE302DE +:108C8000C7F789F74F759427252F76D4FFD29E39E1 +:108C90008EF2E4CE2B1DF52FDCBBD851BE28B5CC0F +:108CA000517FDAC11B1CDFA71F5AE3F83EF3C87AD5 +:108CB000477956F7371DF51BA87902F92C7040004B +:108CC000F7ABDB46CB76FA6CCFA67A250BF3B8353B +:108CD0009ED48FF166968BDC9767E06EA7146BA627 +:108CE0004EF9573126CCD331CFF046E423A5386F67 +:108CF0008E81EF672C00BF132963E7B444FCDA537D +:108D00004C527EC8EF0BB9F0EB8A4B7B946D29C0B7 +:108D1000B376F4CB07A5487FBC7AA2EE7CC6A1C58A +:108D2000B555E3B3E507E4F9385F8CA57C817EC4D3 +:108D30008F15D8B7907961B40F6CFB1B84A3D8DF73 +:108D40005CE623CD0053C11715CB7B46BF80D5C44D +:108D5000BEC62B0F272FB9BF5EF1A2DD25E4CC6084 +:108D60007A45494E73E421B89F54FE95F9609F1EE1 +:108D70005986F2A8775FD02B1FE333E1BB478DA163 +:108D80007CEC957F7B0A1C7261A8F6995B4EDF052F +:108D9000421FCF05A597D711C80BA372E9CEABAF81 +:108DA000C23818A9278EF3807955711FE83D6A975C +:108DB0007DC567DB3F47CA997DF6F766A78660BD2C +:108DC00036F927EC5501D7118575718CEB85650255 +:108DD000FBAAA6D9B128F801DBA08A6D9FF65DDF5A +:108DE000F958BF39A4C9E02F6D3E381FE3035E7FF9 +:108DF000DC0779CE4D9E7825ACAB295BD6D3E53B1D +:108E00006DF631FF8CD6109CB67B00FAD034BAEFE9 +:108E10004FB3DE7FF131BF4BB3BEF820E8B99CB051 +:108E20006640FE44EBFE598B305F77A1AAC3BE9625 +:108E3000D04DDC3BB6B8222171F46769B932EA45FE +:108E4000AD2182E30F36DF5B7DCCCFE06DF00F38D4 +:108E50005FAF96DE4F9169BE9B61BEB983CFD70BE2 +:108E6000F39560FC108EBFC9C7F0E886BF87986D88 +:108E7000F368BD96635FEE28468A61F97AF72E9C07 +:108E80008A744A05B5837EC53E82D2EFC340BF6275 +:108E9000FF2ECEB3DEE263790902AFC460FE881113 +:108EA0000915F7BD3909B6FFED931F8C8E723C3161 +:108EB00082E7BFC6A8189704378DDD8FA1F8D9BE09 +:108EC000C77B690CF1D5FE15956C027A2BA6EB8158 +:108ED00073B90759DCA9DD13AB8A87FAC613EDDF36 +:108EE000E1FB40952CC9C27B529485D174F6672F63 +:108EF0009D73B8B9E5EC011FCFC3CA27F94CCE96D4 +:108F00002E85A34499FA71DB1B0DDCAF3CFCF329E1 +:108F10001D08CFF631F7A11D2DFC63245A3688BFFA +:108F200087C54BFBF0BCD448513CAA574C45A75FC2 +:108F30007B31C7739D2B9F97E359E057F8ED493478 +:108F400017F95AE05B017802AE94D9D181F495C249 +:108F5000F9C60DCF53FF4DE17904D600743B96AEB0 +:108F60001FF8E6C01504E3602E7E14ED04DDBBD7C8 +:108F70001FF6FFF75EBFA087CCF5ADB4FB0F11D78E +:108F80000D737AF371BDF942F9DB6D709E44CD65C6 +:108F9000FBDD7079F3AD329CC320960EFEB5B03880 +:108FA000BF53E6BC7F2450EADC7FF85CF74D78F8CD +:108FB000FEA3DFFD2ADCCE12E7F9DDF377E36BAE2B +:108FC0003F7D1E261993DEEFEA8EC789F886C88397 +:108FD00015710084035DBF67961C47F95746CC9D09 +:108FE00069E4D3323FD30B5DCFF9314F225CA5A1A9 +:108FF0003FB6A02C5501E5823A12033D71F1F143D1 +:1090000024413BBD20C0E47E41595202BF47C149C3 +:109010009617B89DC72B0BEA93D24ADB38969FE987 +:10902000AD8FDEBC1DE5E37363595EFA6D15CC7E32 +:109030003B14BDA1A302C62D67F9E461BA5F84BCED +:10904000B1F0116F12EDADB26E027E54AA05AC30D4 +:10905000FD7EBC914CBD713CE47DF9F079B251C705 +:10906000E781B1DAFECB69BDF5850103FA6D290A06 +:10907000B0F3BD611FEEF7FF9CFD75F4AB9E6E8CE7 +:1090800062FDB66F9B685734EF3F817EC3A0392DD8 +:10909000C6FCA8A642CA613E874CF0731035662C08 +:1090A00086EF077E83F5142DF11B0BEC93651AEE0A +:1090B000EF010E104F68F2B37CB9CDFEBA68363CB2 +:1090C0000BC98A4569E0BD82EB1D4A518A96D79744 +:1090D00087A495A7942CF02797914EC873F7B424D2 +:1090E0002B404F93D5BA01E38CF1252BC07F3CA6D2 +:1090F0005A8F810F5D2B67E745043E3C7E127F222D +:1091000004F552D2AD74DC89011DC7293892C4BC64 +:10911000E58FDE9C99D6FEBFFD68057EDFD65879C7 +:10912000789E8D9F4319E2951B8BE73CE0A7E3BD3A +:10913000EA67FC9AA95FF11C6ABFAF723A39F0E6A0 +:10914000C451605F3664C8A356748AA7114C3E812F +:109150003F62FD78635476C8DE0F8387F2DCB30C80 +:10916000AFA58C3E9B7E3C310BFA7DFECDA53AF837 +:10917000FBFE945B8CFB86534F7B4DB05F4EE590BE +:109180006ACCB77C7AE68BB03FFC43E3C11CD526A2 +:10919000174FFDE895191EDADFA9275F99A1227301 +:1091A000251D76ECBA73AFCE003BC19A434AEAE87C +:1091B000B356D708F45BEB63EB107972DBF3B4566C +:1091C000785E19CCC6F679A3E43BA1ACF85E1DF736 +:1091D000EE345C378B2BF0380E5D5F5308E95AA7ED +:1091E0001B1088175ADE7110CF7AD38BF4F75121F8 +:1091F0002929BC10FC820AB6EB594D92904FA1A5CB +:10920000EA803D89FFE52401BE09BEA6EF475AE387 +:10921000F7C1DDE9E7F90F3C8F70E39BB74F04F826 +:1092200008B9AECE2518CFE8F99A2F09F6E83DAA7D +:10923000F19DE560075EA7E23C6819CF1BB9F1B369 +:109240003C58E488E3E5F0F884C06B263AD9DA4864 +:1092500062C514DE3F6BF4C560FC7D8D3A967FD20B +:1092600018C5F2DE46039F4F3796E0B3AB3186DF79 +:10927000F73496E353E4F5E1D65E417B3A5E017A3A +:10928000E81AE687D30DD9847C852C95F8E0BE26B4 +:10929000FDE8BF55C17E1BE44A560EF2BD04ED73D6 +:1092A000799EDFC8FC39ED15469F7C15F2B4C943A1 +:1092B000249047D62CE66708437FB47DEE1242DE49 +:1092C000B6C9F573F49FB74BF8FAE87CB24CE77770 +:1092D00077FD884A1790D3BF1D958B58EEEB373D2D +:1092E000FC86FB047FF9DB36FADE3E9DAE9AD2D1D6 +:1092F0007689C9B13BF9F73BA6CFC8BA01CAB366B4 +:1093000064815CDF3E8B183A85E35D866C79B2FA46 +:10931000EAEF683C98376F3CD74120A7EAF59D5BA0 +:109320006CFB9831165911B7D1CB5D756AE52EB437 +:109330003312F98B2763BE31F76BEF9E678EC17EC8 +:10934000B13C21F0E23C8BEB159033979D657AA8F8 +:1093500057FF7CCCDE0BBDA771FC6F9BBD4989001C +:109360009F803C057959962073E83C4397B2F8F703 +:10937000AC775304F2FBB4187D0FF6A8C6F24D0A81 +:10938000A24909CA3FF2C7670620EF3DE7FED42E87 +:109390008AEF0FBBBC06C41BBB9EFB0BE6672853C2 +:1093A000341FF077C1BE6398B7A4C8DD1AEC789774 +:1093B0000526CF57C19E8589607C802A6A8A6725E9 +:1093C0008FAF8F3CD5322F04E7BE1227ECF5B707DD +:1093D00012B7B21D33317D51CA0F7ED1FE82168085 +:1093E000C7560F2B2F0B4C6AB1B04CEB67B37233DF +:1093F0006DBF35BB332A6743D2D4C4968397425995 +:10940000D49FD862CD26E41AAE0F48285108FCDE5E +:109410005BD669396C2BABAC4C7CEC29D6BBEEC06F +:109420005F5E1C4DE150B34FEAC410DFBE9D12AC2D +:10943000BB60EF4E94AF054982FBFE82A49484A3E7 +:109440009D7B1A0FEACDC2B926F04245C3A428BBC2 +:109450005F484B7A62B0BD9CC4EF0F1174F17490F9 +:10946000E9C74949DADE1E9776DD273289DF57835F +:10947000200579B98D9D0776D37929EFAF81585BA7 +:10948000E03C2E79CCA3637C9CFBD94F0ABB89FBC3 +:10949000736EE10E3CCF262B7001C8BF952AFA816E +:1094A000D7162637521B8AAC7DB630462D56D2E2EF +:1094B00067F4B236BB336F2AC5674BB6B3DCC4F36F +:1094C000E7A3D956369CD7ADD97BF738C8EFA92189 +:1094D0001DD77F13E6FB328B879FD83F2BEB125AA9 +:1094E0005EF7328B63ACEB7A4503FABE27C0F38E8E +:1094F000BA2EBA12D657B34D267221E34B73229D72 +:10950000AED971019CAC7B7EEB5BF3FD630979A462 +:10951000C8D4E58B08E90E9E68F151FC3FA2E9939F +:10952000803EBA833D2D405F6B67C99C9E7A5E305A +:10953000559EFF5800E35CDE027196DDCB2AAF0436 +:10954000732B4F66FC4B0912E3DA4A76B30FECF942 +:109550003FB6C8683F838B7403857BB14A0EAAF47B +:10956000B95DA3F8043E6B55511ED2F76D1EC44B76 +:1095700007DE3342DAD83D2DE3F77957829D5D5CF3 +:1095800067AE467B5B2F453FC038D2FB837912E73D +:1095900011267F27EAA442A5F566050B117FC55564 +:1095A000D7AE85764A784900F83D4F495AD8FF77BB +:1095B000991CDE2E273B7D2097234588DFED114641 +:1095C00017D63DA54817BBE53917805DD422ADDC21 +:1095D000F20BC06B76119E7B85F7EB61FD1C9F4DF6 +:1095E0007ACC07F8DBCDF1A9EC942DC8D714EFB7EE +:1095F0004A37AC06B89ED8523FDF47E19AE735DBE1 +:1096000046503C1CDF52DF129D857828F2D1EFC70F +:1096100003F52D3E8A97DD1BCD02DD569EF8099598 +:10962000EA48B4F52DE66CF09FDCB7069410FDFE19 +:1096300002F83F1EC9117CCFBE1717F5CA1113ECF3 +:10964000D226AB4FAEF8A85E28B6D59F47E5C20F2D +:109650001E5210AFFF4EC7033941D76101DDF74CF1 +:1096600052D12E08D0B904683930B908F36DE9BA7F +:109670004900EC86C92AEA7911C7D126C96837435F +:109680007DA087407E11E6CF51791D87733E4A94B5 +:10969000C5751465874979980479FEBEA42FC2FB6D +:1096A00048FC25B6BC0290BFAE3C04C5551EEFED8C +:1096B000CE97A97ECD3DBA481A47F1F25E80EF8B76 +:1096C00072E93E96BE7F3FC0FC40B7C7AD2F43BE98 +:1096D0000C31BAF3593C2A3E159EA3AE2B1E359091 +:1096E000FFA5FF7E3586F6CBBD63D4B4F960FF1AC3 +:1096F00064FE41EFD862BC57A38150FE07BE08F15B +:10970000FBF2B8FCF0707BC17D4E40C8134F365B56 +:10971000637DFBDC5139A1BE73704AC8F4813CD82B +:10972000AF4FCD027B743C9753CDA9595F05BB4524 +:10973000E5F260879F9DCBEDC9269DBB08D8BF3160 +:1097400062CF4B10F2605BA30F9F0F5F3601E39770 +:109750000F5F963707E215072E7E1FF7BF6776303B +:10976000FE3D73E805B84B899CB1A8B6311859A1E4 +:109770005F3E752FDE17F27D357E17E6CB43BE0EBA +:109780009DD25DD9CE3CCC47395CCE0578DE808752 +:109790007D17F778A867BF847EE06D7C3DBEC43C32 +:1097A000DC57821B0FCE1DFB4907DEC724E0E0BE5D +:1097B000BF433D3B85F9EB036C5F2AF297DC794AA6 +:1097C000623EFB8219EE3376E143F835041E44FB1A +:1097D0007AC91CA50F4037B5671592B4E585F49D8D +:1097E000DBD0F0FD6938EF9205F7AF243A2E29045B +:1097F0003E48A29DE80F353BEE712551B5C77EBEB0 +:1098000024E83AEFE2E617B83F18F4B4660C7CAEF1 +:10981000E57DBACD1579B998A7AE9207C0AE3D15D2 +:109820007C6B06F8E36AA998005739512D3C4F7AB2 +:109830009AEF4BD47DB7E2791E313FE18F13E59A61 +:10984000BD8BD04F57BB3B84E7796A924C0EAEF389 +:109850005907BDB23DEFD64C41BEAD672FEB6F3C13 +:10986000E080D2C7877A753EAC3FD870FE4C38672F +:109870009227D79D370EE0A3323CC07EF9C9109ED7 +:10988000D355BDB6FB53DFE2FBE365DC1E09124B8B +:1098900006782A8158376167164D95DA474AAFDC5A +:1098A0009BDC02FCB0DD656F6D0FB0726B70724BAC +:1098B0007329EA67948BCB023F437BA8C52FCACF9D +:1098C000A29CDCAEB1FB3AACA7BD06E83DDA1ECFE8 +:1098D000A75BCB4A507F2845A400E0360F1C2D2003 +:1098E000FF9EF6EE023FC38FFC896B0236B89D0ADD +:1098F0001F1907FBCA34FD598EFEC60DAF3F3A7ED5 +:1099000017E0417C9F17B91FFBA7EDD0DF41C61CB4 +:109910007A8BDABA24EF692F9E33DCE171DADBE26D +:10992000F920E7CB36D7BD1DBE44B3099B73C19F59 +:10993000EE7B9605BFAA672739F2A4C607593C5BA0 +:10994000554D7055D2EFA5EC7B80D1411BCFC7C9D7 +:109950003C4E4E86719C71BBFEE3CCE07282F07D82 +:10996000ACAAF7DECB3940FEAB3BBEE8966FBD4FED +:109970002EDFF2393DC7A5C4B3415A5E93EC5C10AB +:1099800060FC3905F87335A7D3923D773F076AFD30 +:10999000319FF967D837ACF2991704A70F9F7FBAA8 +:1099A00083623DFDE417B3CBAA999D5BDF3EED4A90 +:1099B00028D7DF51A45B69E245E2597D36E8905F24 +:1099C000F7707F51B56AA11CAB3E1BC1EF9FDF78DA +:1099D0007EC779B6FEE385F0BB18EF16977C3E7024 +:1099E000F14BDBCB291DD73FE191BDB671EA9FE07A +:1099F000E780FC545E3BF9DD047E570B496F9E22E5 +:109A0000C887BB3451565AC12E7AC42E1FCAC16EA4 +:109A1000EB6B0FF716DE15E0F5AD60FAFA4157FD76 +:109A200022D17F2ED677CF47C81F28839DA67EE2FE +:109A300015F343F975B7ECEA2F478C3F06FB13F695 +:109A4000FAB703E35F843B25EECA4E568C66FE1DD3 +:109A500003EC80EFABB180FD3EAC6F737AAD3E7B23 +:109A6000BE03DF7D709FE078FFFBC6A8235FFFE6A3 +:109A7000443D9ED3F87680D16535B5E8B1DD8ED111 +:109A80008E3CFD7FCCE3D3CEE3920CF3B8EC6F3C7D +:109A90008F42077FF6CDA3D8F1FED3CE631FF70B1D +:109AA0003FC79FF375762FC07C4342BFF57C5AD7E2 +:109AB0004F69FDCBF4E9A3CFF92AB14278CF6D927B +:109AC000DD6346CBE00FF8EA27B7BD7B39DE0B6DCF +:109AD000623E8E57E4E3F0731E9BC70C7C5F91FBE4 +:109AE000EF3BB8BF0733DCD3DA1862FBEEBB2FBC09 +:109AF0008A60FE7A28817182FDF90BA260A77FE758 +:109B0000C21A7C36E7CF88823C6A0A7FDD916F4EAD +:109B1000F70869CFC1FE91F74BCE7E59B69F47D962 +:109B20000CE751D2D41771B1CDBE3ACC03FFA2D607 +:109B3000FBE017B4DE4BC38CDE36FB1218176C8DBE +:109B40007E31F37F26C4C6B9FBC2CB089BEF6529E3 +:109B500016F7D10CFB7960F1DC1F9E118575366517 +:109B60002F88023D3767CF70AC47C9B09E5561065C +:109B7000A7CDFA17BB9EC39F793D0BD2E6C1AAB908 +:109B8000E9EF176B17788A2690CEBEA8759DFA1B51 +:109B9000AF6B14C7577588F90D361B8C8F824AFC42 +:109BA0005785D2E07C38D8DF1D21C5863C943CBC6B +:109BB000DF727865E2DF659EE44898D79146B67F0C +:109BC0007E9DDF27F5DBEAA630FAB55DE36C1EB3B8 +:109BD0002B3C909FE37F563BCFA70F26375A422C52 +:109BE0005EF3B584B3DDD2AA60DAFB4D28FCEE2A21 +:109BF0002CEC83673FFC7FCE70CB448FC3855B6BBF +:109C00007478701B8C0FAAE1929BE983C34DD05BE3 +:109C1000A67EFE7FA1B307870E2FA4AFBF15BCFEA3 +:109C20005EE9EB1980D710F8F21FF03AC7F5E6D0DD +:109C3000E025E4D81E8DDDBBE8EEE74498DDAF34C7 +:109C400051AA3B7C05C417BEA2A0BFF7F08E79EBEA +:109C5000886CAFC7F4D9E1CAB9EB30DF351EC47BDD +:109C60003C5F9363FF5E067187C5AC5DBF7972F898 +:109C7000BC14CEE67E4B6324F8115E8B5F3DE0FAA8 +:109C800048A56D5D989769BB8F4AE90FDFC3C4B8DB +:109C9000A30CFC4D0BD3CF43E033D3B8C3C5E76B64 +:109CA000F1EF0F0B9F83ADF7D970D190E485D837D2 +:109CB000E492DEBF977101C0738FCCF2398EC2ABD4 +:109CC0007CB89F8C60A5A555A376029ECA223CEF66 +:109CD0004933D6819FCC7BF5C2AD618AB7D7AEC977 +:109CE00096BC367879230CCF3396A7B70B73233CF9 +:109CF0002FB7B7BD44E03E44773D85D7BB6639BB3F +:109D0000978AA8E6D8C5B67375535CDFDDEDC74604 +:109D100022F8FD351E6F777FCFE2ED972E19B83D03 +:109D2000A963F7B950BA1B9BEE7E41C11F9DE14468 +:109D300034429FAF4B8907BF01743429C4E21E2A05 +:109D4000298478BDE8275725298DC2FD5D8F3116FE +:109D5000FCB469FA291CA89F4C7015EB11E3002B89 +:109D6000C2BD2C74FF88FBC5329390D9B04FF4C6A6 +:109D70006E65870D191DE4F0FC999975C1E446B034 +:109D8000F354BA4EDB7CBBFE6BEEFF80EF5D876564 +:109D90007D53617F380C261F1670BAC955129BFC83 +:109DA000E01F5B21A5BDDFECF208FB3B251F847B98 +:109DB000E3EA38CE84FB121EB8E7E05A9EDF44483F +:109DC00062ACFDEF8C7DC0E58ABB5DAEC2E2D1E442 +:109DD0000DC6CF7B76AD199B8E7F5EE57CFA41B8D0 +:109DE000C4919FB4247EAB07F873C9C2451E2304F7 +:109DF000DF99BCBC86CF638F96187B51A80F4E1994 +:109E0000E510874FD7914413DCEFB0A241C238521E +:109E1000E90646772B36EC97D7D1E74ECE7F8B00FD +:109E200007B6FE6EE578DDB32B300EE6BFA7D74F41 +:109E3000473BA6F3B8FE7E827EAFD591AB3683DF7B +:109E4000AB5B22FCEF32FCA412F20DBA799E480BF8 +:109E5000FDBE11E63B6F24F2F7840D1FD4837CEE28 +:109E6000D2089E97FB8F762FFE7D0B412FBD72622D +:109E7000C3478D907477AF969A0C7433B2A9EE1BDA +:109E8000E9FCE416E7FB0F43F1AC7476AE780A798F +:109E90002EEA2D560D4FBAFA57573AE59898F7081B +:109EA0006FEA54BAFB1A7AE93039B0DEFB3597E332 +:109EB00002EFBDF83E927E5FB423C2E2777B9273DD +:109EC000D6A2DEB2BC06C843311F01AF5C8BC1E92C +:109ED000DA258A43DEAE5818749D476270FDAAD712 +:109EE0007808D671EFAE9726E3DF5174E987809248 +:109EF000D0E0FBCD24E50139715C31F0F97AA3F3B0 +:109F00005EE6D749E28EE9A03F1B94B47CF50CA72E +:109F10009FD7AB565D83F36F567498FFB1E523AEC0 +:109F20002A07F952E5C17B828F35DF16BEC9B67E9E +:109F3000A1EFDCF3FA6DF5AA01F5D6D22A27DEF6F9 +:109F400068CC2EB0AE647CB89ACA9BD9485FDD77E6 +:109F5000CCA4E31F4EE65CB4855527F0F71CAFE6B2 +:109F6000BF1F971377CEA4F2E684CCFC61D63F31B5 +:109F7000B9B1E4BE780BC4794F344CFB6937ADF707 +:109F8000325FDF5B0D03EB47373D4DB8CF793FE5DF +:109F90008C234483F689FAF4FAE0FAEC2093AF6A52 +:109FA0006C1CC897EB36A4AFB709922B69BD137F21 +:109FB00055AAD3E56D7EA2333E59114FDFFE133D06 +:109FC000CCBE835E4A03E7BD59412EE7F47120A75A +:109FD0005764986F575604EBBDD372FB7510EF3B77 +:109FE0002E3BE5F30FB278FC3C8BC9E713BB9679A7 +:109FF00046029E5A251DE8E1EDECD824A0B795CD88 +:10A00000C7D08FF02D5EFFBA50FC43D04F4B8E2C43 +:10A010009E3F92E2A56B3989494666F9FF31E79F79 +:10A020005C85DD6340F5DFBBA0FF68D377D1FE50D0 +:10A03000CD715F9BCCAE6C84BCC213B2B506F3503D +:10A04000760558DE11894DB7DF2F13E0F338B17B69 +:10A0500078F8BE261E1CD08E3F4C3A6A70DCDD417B +:10A060001DE28F872B95D4E57492EFED0EE23DAFA4 +:10A070006EBEC834FE70EDC013BB8767070EB6EE28 +:10A080005856E190ECC03395F7DE59067CA4754C28 +:10A0900049277F859C7E8DFBADDCF4239EB3393E42 +:10A0A0008E27079ED7CDF73BE7735D9D733E825F9A +:10A0B0008E279B02901F4E479F6CB74BC9BCE9830C +:10A0C000E859E6FFCD34CF389FA790134079104F61 +:10A0D0005BCDE5CD5B0DF746EC7870AFFF84CCF738 +:10A0E000070FB1BCADF1F19573461A7DF4795D1699 +:10A0F00093439F375D0A3DE3EEE7EF9D0E859E1B80 +:10A100008C0E855C70B7FF00E2FC23E1EFE3E81AF8 +:10A11000C4653E8818AC4CF40570448694F373CB48 +:10A12000C41807E76E4EEC0AE0FDF6D6166F12FE75 +:10A130006EC7F15D974CB2AF6707C7FF8A25D97824 +:10A140005DCA713976C528CC2F50F0BEAED78FE4EA +:10A150002C80F2BD876490D0E4BAFA950AACEF8106 +:10A160002C9677BE62C32B680F0E97CE57D439F565 +:10A17000FF277C1DBD7696DA5306F493090EED5940 +:10A180003EB6CF892F9A0FF279D50609E5ED962CC8 +:10A1900003DFAF524D94DBA499E947E2A3F0A02A74 +:10A1A000E4182C02E0F1BFF9DF2953E39AFD7CD2D9 +:10A1B0004DDB6E9F0FF6A19B5F46EB8C8EE15E3010 +:10A1C000785E174A3C9935B24F3EBF2DD5ED1F45FD +:10A1D000AB5C9EC5ED6DCEA7623D9767B1F5513B77 +:10A1E000ED87F8F799F8FA48CC456F7247CD4F00E4 +:10A1F000FE737C681704BC54EE43DEDCF7033ACBF5 +:10A200009B637C25EC1D77FB6BD584C36E3C94551A +:10A21000E8C8C771DB21FFD017E9EBFFF96FAC2F5E +:10A2200064FDD3E98BFF0778BAC08E008000000080 +:10A230001F8B080000000000000BDD3D0B7854D59B +:10A2400099E7CE9DB9994966924932933738930080 +:10A250000625780321449E370991A0A803040C1A0F +:10A260007044D4282144C54ABFD2CD0D893120DAAB +:10A27000505DB4D67587885DB6D235586AD1D2762E +:10A28000B0828FEA365A45DA8D1A1FA5800FA2AD2B +:10A29000ABDB8FAD7BFEFF9C93B9F76626046DFBAD +:10A2A000F12D7C7ED733E7FDBFFFFFFCE7B0A22591 +:10A2B00085449D04FF7C49FF3B9C1A20C44FC8F194 +:10A2C000BFCA8DBD6E428E45DA93AF81AF4D5D90B2 +:10A2D000ED2344EF94C9A3B4DD3B473EAD81F2BD0D +:10A2E0007D36AF44CB2BD65F238769BB4C28F9A1C1 +:10A2F000DF9234287F097FE60EFFDEF0804CA2C596 +:10A30000B179AF867518CAC77A923502F3CDF14498 +:10A31000C60709D9AB109D9411F2F6E6ECC8265A8F +:10A32000AE7112DD3D8590B9696CBDBE8D9FB77A67 +:10A3300027D3F5F4FCBA8414D2F5DD7DFB8AF0A4B2 +:10A3400038F37B6D844CA3130402369245C86D7CB0 +:10A35000EFAB528906E3133ADFA386F145BFC3ADE5 +:10A360008444CFA5F5E368BFF2583FEBF8CBAEBC11 +:10A37000702CECFBF09533C75E3329D62F111C9659 +:10A3800049E17F5E0AF3B6C92AC075D73D498D3DC4 +:10A3900071E0A673B85AE7873F76BA8F25FCFF971E +:10A3A0006EACBCC34341B22965CEEC709CF90F93EF +:10A3B000F0DDD3E87CFA46369F759EC57C9EC3F5DA +:10A3C000D72E05F87FA6CB5E99C263A0414EAD8023 +:10A3D0007EF50E753C1D7F40BFD5739D619DBF4FBF +:10A3E000009FDF375EEB898B07FEBDA2DE4C076F57 +:10A3F00093C197A7C33C3BE3AFEF16581FC5DF31AE +:10A40000257CCF85747DC72F96559DAEE7B88DF618 +:10A41000037A7990F60B0CEF773DEFF7F6C691E9EA +:10A420007249AD793D4B8F249BE9D2461A7BE3EC10 +:10A4300067685D6748F72B2CFCB74B191CE3A5FD3B +:10A44000DFDE71EACDDB613F3B9211DED67132D3A4 +:10A4500065C6A7C02700AF2D499C4FBA9B9FA6FD9C +:10A46000DEBE344FDD4486F30721DD97CDA0F5FD38 +:10A470003DB6D22DB46A574F4A6324CE7A27A7330C +:10A480003AF0C97AF279B43D7983E103C80DF866F0 +:10A4900029A7376FCF0F5B882DD6EF0DA0832442FD +:10A4A0007EDBEAC4EF36AF13C7A95BB84809D079A1 +:10A4B000AEB3130DE0877FE8B8DEF30A766CA153E4 +:10A4C000BD6E63657D15E53F69F87A1EE674B92BAC +:10A4D000B27844F8D637C82678D62D34C3D74A9FE9 +:10A4E0004723B6DA78FB17F49C68BE2B1D113FE0BA +:10A4F000E908DFEF61BEDFDF37B67BA0BD759E5D8B +:10A50000919E11F9E0AA46335D9C6E9F6F7A830895 +:10A510008FE56173BF2BEACDFB5D4A5A66134A2A69 +:10A52000CB88EA806F1D6929799A82F2E8034B7023 +:10A530003DAF13520B729E9CBAB56451496CFC1727 +:10A54000393D7F5677EBA5202EDF505A4ABC71D695 +:10A55000F33A8793C0F7EB09E019E572F70DC033C2 +:10A56000D0EB32392E9EFF8BCFFB46C3C87CB4ACF8 +:10A570006E643C9FF07A113E6F34B427C33E8F89DE +:10A58000791F64F3825E33E2E3C457D45B56FE1D49 +:10A5900020FA4D48C791642FE8111F9087418F74AE +:10A5A000A4DB981C2F1E598F88EF6F855CB5B4AF64 +:10A5B000B36B0E233ECABD01849B28D72D34AFF365 +:10A5C000BD54060FCA7163431E83DCE0FA55E8BB35 +:10A5D0007B7F70FE5BA03FC7A7333CD4853E7100F4 +:10A5E0003CA87CBDC303FB7AD5E605F95A7E4473CB +:10A5F00018E137278DB53FBE7364F8CD4963EB3C56 +:10A600009D9CB5EEF7ED6FDF3905C67DFBDB9F3B0B +:10A610008CE32FFB229F443363E5ABEB252D1287A0 +:10A62000CF36789551C17D83058E577F3116C7F798 +:10A63000C9A4A537CEBEECE94E6CBF3454E9F05343 +:10A64000785EBB5152253A84239DC9DD6B85BCB32E +:10A6500007C62EA270F7B7B7DC168A33CE6C0EEFA2 +:10A660003FBB4369F1F84C7C853E17ED96D9C38E0C +:10A6700078EDAD7A7580F3B9B55DE80CE971C80E77 +:10A68000B2B41FED3AE6A6313ACC4C8A7E04F28889 +:10A690004C32DB61A79DD7D2DE3AEF651CEE89E62E +:10A6A0001776AD757C9DC33F1CA2F413B7DE83F50E +:10A6B000AF12A65FF5480AEAC3633BAFBD07CCB74C +:10A6C000EB17DC7608D4E4CBA9416CD7107AA50649 +:10A6D000D9EDD4BD9301EF9FD5DE7B4F195DDA71C3 +:10A6E00025DCEEA11D8E6F92D06EB1CEF32AD72756 +:10A6F000AF813C3D17C623CC5E9D4747CBA56097F5 +:10A70000B5352054C8B79202463BD5B7E1F356326F +:10A7100019EC87D0260FFD7DC2C64FD6835E262456 +:10A7200082FDDF75A83722BC09B373FB7BDC3BB627 +:10A73000D076AF825C80F1893A3654629013762FDE +:10A7400096478B9FDF26C0CF99CA29B1CF44F350DB +:10A75000C8E3FA1657B9BBA434B07702D7C17E0656 +:10A7600017B8BC3D14858B15ED1280CFABAFD86CFC +:10A770006D411C16ED15611F072F0BDE755E19C8A4 +:10A780001F87E6A24B5904CECB85948EAADC3A8C67 +:10A7900057F6DB858F017EEEAD4F0AC830DE9CC0D8 +:10A7A0009B322D2FBE3829007E47795FE1011F1DA6 +:10A7B0007FE942C94B68FF790BC6FB07E8FE5236BA +:10A7C000D071F26079C76AABC711F243986C066129 +:10A7D0000BA6B0582CF1B2EEDB3C8FB63FCFBFD703 +:10A7E000E6A6A09EF85DDF66271DF78EB6508E3771 +:10A7F0009DDA13E91F743967139295A5F5CD5509B4 +:10A8000071677C540BE5BD0F8AF13EEED20A08F960 +:10A81000992D1C9468FDD48CA405760A2F5F91981D +:10A820003F6FB3368BEEE7E21B1F5D4FC75FFEDD68 +:10A83000490BECB0EE06317FE90258DFD259A25C39 +:10A84000EE82B22F85F787F55650F955185BBF3D5C +:10A8500087CE9F21DACF58308FF63D5CD9526DA755 +:10A86000F3FFE8BBDAE649130999BEB0D2ABD1F2E7 +:10A870001319F50B52287EF6124AA7B4FC64C6954C +:10A880000B60FD3ED9C6C7BF6A33ACBFBC413F0FAA +:10A89000EA257DE5E65ABAEFB5CE814340AEEB3608 +:10A8A000E8CE2CFA3F2912E363A7A345CBA7B073E8 +:10A8B000ECAB8CE6E372BA19BD16444B408F0D9594 +:10A8C0008B69B9C450CE61E5BD9BC8D5F1E4ED6D8F +:10A8D000994CEEED4D8E5FAF64307B80C20DF54933 +:10A8E000DA11A2ED8EA3573E4A77E37C079389EEF7 +:10A8F000CC88F1DBE594872B285F12275BA71867CC +:10A9000098FEC8607287E89767803C5D0843D0ADC9 +:10A9100017A912FABBA42525321E688744ED4B40C7 +:10A920007FC8365CAF5F96AE5E44C7CB4A26E13D3A +:10A93000F4EBCF2458A6FDB53DEED8782F71BAAF11 +:10A94000290AED84F16AB2734BDB83B171E8BA3B3B +:10A950009C534CEBB6576440FDE2D29B2719E0397B +:10A9600089ED83D201F6A3D33C3697F2C1DEBEF364 +:10A970000AC17EFFA945EE96F72D7610DAEECA4C95 +:10A980002E5F02ACBFBF9AC99FC19B53223DC09F9F +:10A990004EB53464B03B031C1ED5772EBC1FDA3590 +:10A9A000F53948126DB77E4F653619412F367D3126 +:10A9B0009344A61ACAF6A80272A7E98B39F87BF568 +:10A9C0009D2F29C0A7304E80EE6BBD4BCB56016E3C +:10A9D000EDF1F14F1D725C47D317E9449F6AFC9D6E +:10A9E000C12936BE0FEB4FB7AFD8783289648E34A9 +:10A9F0009E82F54370B773B82BF1D7395FD02985A4 +:10AA0000B7CD405F4B39BD51E9877194FECB26F538 +:10AA100080BC8FCDBB09C7DF6BA778043BB02F3953 +:10AA2000007671B99DC9CFF2BE0CAF2EC5E843D0F8 +:10AA300085C0EBDE8C964ADCEF22C9DB131CBEAE70 +:10AA4000CBC4BAB83ECD6E08CBD718D627F8818EC6 +:10AA5000BF978F5F5681FCF32F4CFF50BE5901FC0E +:10AA60000B760BEC438D962CF60C5FFFCFA8EC8099 +:10AA70002FC52383FFA5EE08E80101B7E1F0CF3F22 +:10AA80000D3EC7627D79DF330AECB32901DF8632E0 +:10AA900053B15FF691682AF8B5BF4C677A6D6FEFD6 +:10AAA00054D74CE08B853602220CF60DF66AB9902D +:10AAB000B764D70B5576FAFB5099CADB00E06148C2 +:10AAC000FE469DCE58FBAACC5D0B3A689D2F89E2CD +:10AAD0007F12DAA14E62F027BE9DC1E4584598C4AA +:10AAE000B55B966532BB45C0FB7B1BAAC97B747FF7 +:10AAF000CFA533BEAC18D025C08BE06BAB9C7A8859 +:10AB0000E3F17BFCFB8F9753D269E4D4222EA7D8C4 +:10AB1000EF07A9990FEDB2B2A22512D589AB5E98C5 +:10AB20003A1EFC995B72E4C0FB94AF9648EA981F0A +:10AB3000D171EB9C018C93093AA923CE801BE04E86 +:10AB40008DA62F41EF2F746119FE805DF269B7C4A5 +:10AB5000E89004D2EA4A12CB21B18E5B72149C6F4A +:10AB6000D5E6F16961E3FAB89EB83C29FA2352347C +:10AB70009CCF4599AE7FAD4D36D4BB993EFBD0A35B +:10AB8000FD3483E2E15589D4E37A2CF6D26F78DC88 +:10AB9000C66A2FD5733BD20FE625F2B10D9DD3ECDB +:10ABA000AEA408615D74F053B37B09E7D7A8ADC9C3 +:10ABB0004007BFCE286076ED15B4F202CA94CE6A83 +:10ABC000ED7D831C7B1ED6837A213A0DF8F4A50C0B +:10ABD00062B2F31AE4508104766B76920A7286E2CE +:10ABE00009E170D045EC2E3AEF73F40B78AB916F1E +:10ABF0003EE0F0011D486A3B427F07F75B4914F4D1 +:10AC0000CDE57353D06E25A76E1D07F10A7F0AA309 +:10AC10005B3A8E938FE3443AE172EF376327F68015 +:10AC20007E12F253E0819C92713C517F505A54E065 +:10AC3000A5E583FE734BDB25B3FD03F650CC7E5AAE +:10AC4000BF793EB597A6D7F6466D5E902AB72FB866 +:10AC50009DB6AFA1F6938BEEE78F194C0F1E0CEA51 +:10AC6000722A8C379EEE83FE7428393CA9C51DC319 +:10AC700007B571C280BF2C857EDD8C3FE0DB99C9B2 +:10AC80009091E163DF06FECD4A65ED87E93D5EAF59 +:10AC9000490CDE5B2A999CB0B6B3F171D73AF5DA6C +:10ACA000AC42A37D1522408776C2EC2C19748F1F0D +:10ACB000F519C2ABFACE8634D09B9FF52D4D239368 +:10ACC0006272D4E1FCEDD8F7A91C899225DF017EE0 +:10ACD000555E9709D8CB7738185D2AE9616F06FD74 +:10ACE00066A6C4F79B27F2F564825F4DDBDDC3FDEA +:10ACF0001EC717E7A3BF9D9FC9E245A9397528D78D +:10AD00000196018AF73432A87B0D784CABB099FCE0 +:10AD100007C71793B1FF99DB0FA509EC873293FDA5 +:10AD200020E6B5DA116FB6E6E0FA45FF1539AFD582 +:10AD30001043FB9564E00E186FE5FA7C53BC289134 +:10AD4000FD3137531AB217F4B8EB524CBFBF49FD6F +:10AD500045DD38FF31367F6CDE14CA70B179E54CC1 +:10AD60004DCB44BF6F96F7E8F9F4E3A2BFCBA877C9 +:10AD700050FE53FDA4ED70A35EAA05B92DFC24E09E +:10AD80007F6F1AF077656DA6DFA027793FAB3C3A5D +:10AD9000C0FDEA035CDFA41D117663724092627A03 +:10ADA00067B8DEE276B1453E9ECECEA674AB1BED13 +:10ADB000806178CEFCAAF6655102FA98F00FB12FA7 +:10ADC000CB6785E512909FB512194F3FD3E799F5F0 +:10ADD000BD9EC9FC109D329CD16F59DC606ED701BD +:10ADE000EDFCF04D1995DF62D447920C728F8DD730 +:10ADF000CCE92178E2552540E57094DB43BB7CDA51 +:10AE00005D40171DC9A993414F74248F8D405C622A +:10AE1000C7FF5617EFA0EB1F7CD9A1F6C0B0FB18F7 +:10AE20009D542E5FDF6EA7BF3B7A256F1289ADD38D +:10AE3000BD41D256533EBE9FCB89261FDB4F932F79 +:10AE4000AA8CA3F3E735B17514F41E90EC0679577C +:10AE5000D0C8DAEDC87498F4CFA350A6E33C22FC26 +:10AE6000111269AB2983F69A1DCE41F27A258C0F17 +:10AE7000E7B55040507AC853D9F86E35225D3B296A +:10AE8000B6DF2EDBA249A027BAB25254D013277DD9 +:10AE9000E1C760BF4DFDD128806B7A7F9F1DEC3DDF +:10AEA000975FDB0DBF8B7D06646F1EC8D9947EB69D +:10AEB000BE6E0BDD1372175F570F93BF32799E0082 +:10AEC0005E4086D0F9B23615A39E12EDB332B8DEDD +:10AED000C822E127D0CE225D04F146701F599B267F +:10AEE000A0BD2FF01AB3AB264E01BBAA686BD4BE2F +:10AEF0008AF67BFAA1F8F1FA17399FD07D1C34EE5F +:10AF000023117F08BD26DA3912F8D582EE536AE3A1 +:10AF1000DBAB5413607DE572DF95B0EFA60E8524A0 +:10AF20004931F8BBFCA12320B7F27A7748001B2BEC +:10AF30009D7564FC50CAA7FBBCF546E29549E275D5 +:10AF4000376D90B5D5467EEE5018DD28E6F33DE12D +:10AF5000677CC2E305B3FDA163008FE67DDB14C00F +:10AF6000F38D3BDF51463AD7192DDCA446E6BF34BA +:10AF7000D53B23B0DFCAE576C4E39A0E2502F2A9D9 +:10AF800069F79EA80DECEC8D4405FE6FEADD732891 +:10AF90008FC227BF499B260762E3E5374524584FF8 +:10AFA0001625C63EF4FFA20AE86D2B7D839D0CF6A4 +:10AFB000CA2117E3FF0F2BDDBA44E1F8A123DC041B +:10AFC000ED3ECC4D51F5600CEECFED99FFBC4459F0 +:10AFD000DCF3445214BE5DB69E1C276DD7759EA24D +:10AFE000023DB9FC618F8FC229C31EDA0BFDD37DF0 +:10AFF0001EB58DF60D249129A8AF470987E916BA29 +:10B0000098BE91F1CB5C5FAAB003A7805C3AD7E70A +:10B01000117614CAAB430EB68F0EC2D6DB99A915B2 +:10B02000C07A883703E7CD6B8A4AE00758E78DD1AD +:10B03000955688ED47BDCE5E05E4FC1A2E6F2A9723 +:10B04000EF94DE33D041A98F9DCFE6EDDE21817FE5 +:10B0500048EBDB6A7CD89E2481BCD9CDCE29D6D0E2 +:10B06000FAEB0CF245EC238E9CA980F5B9FBFB9E14 +:10B070006572268AF427D66BC5E73C1FB3EF2EA274 +:10B080006602FEAEE8C5013ADEA1C2641C4FF0BD07 +:10B09000954FE7F9189DE7D5EF94209EE04B61F6B8 +:10B0A000A4589F68B7CB5755EB4338F4211CD6D62C +:10B0B000DB116F623D354A681CF865CBF878CF5CD0 +:10B0C000F1963240CBF7FDF415A4C7B5DD9286FEAC +:10B0D00042F72BCA5288DBE9FF2E439CF61266A288 +:10B0E00090ED3F7905F5CA257B59FC60EDDE3DF614 +:10B0F0006BDD313A0D9E786625D0D9DADE24E292F6 +:10B10000007F01E4532B9D523983744F7405CFB9EE +:10B11000A89CD451AE927010FC1421873B397F1348 +:10B1200037FBFD46BE6E316E4C7EBA90DE8327A69D +:10B130003CE3A4F05CAB4AAA0BF891C39B8E1F457D +:10B14000394C4821F86B627C2BFCFE99DBED71F0E9 +:10B150007C1BE0D9AA4F849E0D3E5C45E02BF06736 +:10B16000E7701FD2EF3E05D7DBE1B3333D5FC9E2A5 +:10B17000DA1D0EA6473ADA9C11E0EBE7D22F7A5E91 +:10B18000A2F2D293A144E17BD0B6AA09EA0FE6B1BC +:10B190007574D93615B7303D76870FF1974A987C8C +:10B1A00062F2E8BE1F3379D2A4BBD17F6C0AD7AD5F +:10B1B000C673099F4B857309127E5659EA89D1835C +:10B1C00015BF81270E28015A7F492FE38318DC9889 +:10B1D000BE12744BE51CE2BD33539C5F868300575F +:10B1E000EAD7B741FC41F8F5A90D21DD1318CEAF20 +:10B1F00099DCAF9FC6FD7A4785F36FEAD7AFD9F0E8 +:10B200006BF4836ECA7901BF825FA8FF68E2AB2747 +:10B2100038BEEFF731BDFA948FD1D59AB25EE4878C +:10B2200035EFB7201FB96B993C71F79BE52021776B +:10B2300073FB602B8E5393D27B910C7EF2BF4ADE60 +:10B24000769278DD37482DFF097932640FCFDF38E9 +:10B2500045ADFC720A571787016FF76B1FF3B73EB6 +:10B26000DC4511017C696F5146B2874F372E89BE8C +:10B270002601BED770587FB8BBFAC23F409C7157B9 +:10B280001AE6B37CB07BC937FF40FB7FB873AE0AC8 +:10B290007ADAD71E42FA19F4BB54882752F1592B97 +:10B2A000517A68EBFD55EA4C382F7BEC8229203728 +:10B2B000DFE57C79E2C7F20680CFA67F7B7C0ED4E7 +:10B2C000AF894899603F7EB8EB5FFF0A7AB171E7BA +:10B2D0003ACC4B6B7FEC976897DB223BD8EFBBD225 +:10B2E000D0CE3CFEC8B63900F7F6DE76AC3FF1C8EA +:10B2F0000E2C3FF36F8FFFE22F60778452556877F3 +:10B30000E2C7DBFEE92F40E775A92AECA3296C67A9 +:10B31000E7B982BEAD726BCF01E453412F9780DE57 +:10B320000538D533F923E8F95D7EDEB4AADADD0508 +:10B33000F2ECDD2D9EC6787146C5CFF002B11894AF +:10B3400063F512C6D9BA28D540BCA32B9954C0378F +:10B35000655254C9A7F35CD1B0670EDA3DFA3BD70A +:10B3600043FB25FB5C640BC6E520A84BFD0124755F +:10B37000424AA8183C4AFD663AFACE2F29DD1EA69D +:10B38000F201F58EC51F58D2F5C2FF801CAD730EB9 +:10B390001C0051287EEFE2F11BDA1EF54EF9FAF897 +:10B3A00071D254BF9BD32DD39B797B171504504E7C +:10B3B00024A9E30DF6E998232D5B203D29AFB1EFD9 +:10B3C00022D8C7C5C5D74C45BA80F81FE81FDD8D08 +:10B3D000E3AF85F825E5BF73FC3C2EE225BE19746A +:10B3E000FE1A3BF1B9E14BC86B0E94238FE2B8D43F +:10B3F000FE40BB2AF0CB2B1E057B64BB239C3B0D80 +:10B40000C6E9E27A6B275B37EDEF8573543A9E7796 +:10B41000C6141CA7CF9181FD75D67FFECE3629B606 +:10B420005E4AA963416FC178656ED0337A3DE227E9 +:10B43000A0E0BE4E40935CDCF7E4152531FEB5C6B6 +:10B440007D409EC1F9F06C7F65857F5AEC2BE2410F +:10B4500056786EE4F53FF36BF825BB324D7A2591B3 +:10B46000BDF2CC151F33FDFBB37750DE34031DC393 +:10B47000FCE1F74DFAF75A41C74FBD83747CED3EAE +:10B48000A67F9BF7952A40B71FB46AE43D6A8036D1 +:10B49000F3F3D7EDD2C0F598EFF294CB0B71BD8FDB +:10B4A000B9BE59B3F59DA3706E5AB82F17FDFC8F26 +:10B4B0009F72D5C338076D3684E7C19EF377B44BCE +:10B4C000C67532BF80DAC148AACDD44E6576F0EA9F +:10B4D0006DE0A7AD6D242AF07FB3857E9AF7BD821B +:10B4E000F422ECE0E0C38B5733FBD3A5BAC08F9BAB +:10B4F000C7EC5142ED51689F3E2FD2A6207D959614 +:10B50000037D3D73C52F3A418F37CF235E187FFBF4 +:10B5100018EDA97CDC8F4420CF65BBA3BBCA4EFBD2 +:10B520006FAF0978292429DC76A2DD4B8A15AEE7B6 +:10B5300056A3BDDC9C73958A7C6695074FB5A1DD4B +:10B54000D51C48C6F55CB24FBA85D9236EC2D62F3A +:10B55000217D5E12991981F8D9471C7E028E1F3B0E +:10B56000FA56023C3EFE0925445A7FC93C46AFE9E3 +:10B57000F37A518E3CF7D47CD4E3822E3D4F26A142 +:10B580003ECFB07B2515F5DA9224235EBB1D4C2FF0 +:10B59000A5733D53B495E1B793F353A7DFC6BF8AB4 +:10B5A00039FEE2D52783DEFD88E31FC508C8772E64 +:10B5B0004FD6AE8E223F35ED66E3F992B4D25B0DE5 +:10B5C000F4EBAB667A519C07C0F9C0A238F2E231C5 +:10B5D000BE8EE0C3ABB681BD7C31C53BA894BC62D6 +:10B5E0002E47295D00DCF21A43480717FB6E5021F5 +:10B5F0003FD59F49D05F1C6C5348BCB8CFE35C8EED +:10B60000FA3343651087F6677BD0CEF1CB953617BA +:10B61000F42B95D49E009E7BA29D37E8CF557B4CA2 +:10B62000FC1E2AB3D176C7B23C0CCF91DFD8179756 +:10B63000001F06D8B816BB6FB8DFCDECC685DDFAA3 +:10B6400064F043C4B9868043A42DB9DE283F7FC28D +:10B65000E11099C8E2A9D4BE77635CDB4BE701FF38 +:10B66000BE67E623CCBF6FC7760FFB997D5443F7C7 +:10B6700007769BBF28B49EE9538F1A0F1EB3FDC2F5 +:10B680002E5F590A7E65739D5B057EBBEF67D22AEC +:10B69000A467081682DF1D5E8D7820140FC00F246A +:10B6A000CCFCD2E69650243EBD2F42FE6B06FE93A4 +:10B6B00090DE310E4FE93DC2E89DE93FE1FF837C1A +:10B6C00034E61D0A3920E44BB3323001E858F04328 +:10B6D000F39C810900B7D1CA938F1D94FF817F2805 +:10B6E0001C807F04BF789E667CB2A52D5009F55B57 +:10B6F0006A88B7DDA08FACFE12AC13FC4E21D74F89 +:10B70000FA42C7FD1007B0453B21BF42C8E1E6A79A +:10B71000374F8897FF26E4B0D3CEE49B339212696B +:10B7200037D0179CF979A6E017F3795236C48F8F7A +:10B730009CF2BB791C7F74F91259A0CB41DEF4A4B2 +:10B74000605EBB881759C7FDD82F99E232C26F815E +:10B750007307689F93C5F827258BF3679688CF46B4 +:10B760004CF41FB085DF813CA344FA4BF4FB5BC56E +:10B77000AFC43C428F5AF12FCE4D603F8B26256ED1 +:10B78000D77D80C9272B3D4EE47C72147C0FDAEE06 +:10B790003FF839D770FCB2714878A2292FAECBB6EA +:10B7A000A7315E1C4C9C779087268E2AEFEE402BAB +:10B7B000CBAFFA0F9E674B564F34E559B9D5401BB6 +:10B7C000C451AB9CC15219E765712CCF1CF209E83A +:10B7D000E1C9FBBA8B217FC91F329F9764D7279B92 +:10B7E000CE2372C319A6727E639EA9FD989642531A +:10B7F000FD391BCE33D507F529A67251D70C53FB63 +:10B80000F1DD55A6F2B90F5C6C6A3F31B2D854DE57 +:10B81000D2D65B0F78397FD795A67E5576AFBD948B +:10B82000C2B5A47795397FCC02CFB4BFCA71E9B055 +:10B83000292B8878ADB29BF3882FD8678607A4CBD5 +:10B84000019C27133EDE9C635346CA6F9D4CEC7FE0 +:10B850001E10FD83C3E9813807D4501C3F53D0B973 +:10B86000285BCFB584FC3853FA4BB44E417F89EA4C +:10B8700013C1ED3B9CFF055C1C4370A95747828BAD +:10B88000E3747021142E9EAF0E17EB789B529A3101 +:10B890004FF8352818ECE38156F37D98657A1AD372 +:10B8A00043A125A7B1A3591C389CC4CE2BADF5FFED +:10B8B000C9E1F2218509E261947CFD16C7437F222C +:10B8C000BEDEF0C9C16C90DFB504FD666F4BDB27AF +:10B8D000A0B7AEB64709D0FF7D7C3FDB79BEE80359 +:10B8E000AD5E1CE7417E1EF9506B007F7FB8B51836 +:10B8F000BF9156157FEF69ADC0EF4E6ACFC1F70714 +:10B90000ADB5F8DDD51AC2763F6CADC7EFEED630D7 +:10B910005BD7307C9172B473429971E3A5D7E8F29A +:10B92000A8F044E482B8FA32E13872C388F9E51B22 +:10B93000FAA5C79F35F0EF5B591EDF51C86D9C4ECD +:10B94000A6C3F9E6E9FA7FDE4A1E7F76FCE8F948ED +:10B95000D013399539211E5F87795EE563DB57DDAA +:10B96000A54F4A0CAF189DC587539DF3E33C70D695 +:10B970002783CD60E82FEE9F88725D382DAEDD9075 +:10B9800097CDF46E7D123B8F5F6EE1EF6F6533FAFA +:10B99000FD5636D377BF4B2067D2793D5DA703CFE5 +:10B9A0000787F1DD3DB3E3C1F7AEEC80292FC57AFF +:10B9B0006FC53ACEEF1CDD63D4387C76BA71C4FE15 +:10B9C000ACFDAEE2FBFF663661EBFF7FC69FBFBBFF +:10B9D000CE83FE03C0CD6FD8FFEFAE4BA98F179774 +:10B9E00069CF66E7A1D43A27C10C34F575056CC55B +:10B9F000621260E7BEE3BC101F12790189E9D58E9F +:10BA0000712484A13C1CAE141F01A5888E6F1F9A5F +:10BA1000276A8779545B4CCF42AE0D31DCFF9087AB +:10BA2000D303EDAF2B98D7339007EB3B537A22F239 +:10BA300043E3473AA71BD6FF0CE5CC9AECBFAF9C7B +:10BA4000117C4E4EDD3B3E9E9EAC87B967507BEC31 +:10BA5000FE87989C39CDB8670ABF7A7900CFAF4787 +:10BA60000DBF7DBE51C5A53E77A54E26D4AFDBE008 +:10BA700064DFDB93537BE0FBB96B6C84A4527E8163 +:10BA80007552BED5AB08BBBFF596F09B5AA683BCDA +:10BA9000DD9E1B7A309B8EB34A61FEE29FB2B4EF0B +:10BAA0004339999F0B27F37361255BE98432D18A6F +:10BAB000715F17F07D75DA0263615FEF4BEA44F066 +:10BAC0005BBCB6880ADF54122D61F9799130F86BAE +:10BAD00099E72707C0DF4D9E40481FC6C75517C4CA +:10BAE000D19494C117C701FFFFD286F7A21FF7B206 +:10BAF000753EFE403E9EB350818FF26232FC4EB7DF +:10BB0000B205EC72DAFFFB52F8896CBAAFE35EA7BC +:10BB10006EA3EB9ABCF9BD8C0CFAFBE3FBABF05CBB +:10BB200021BA4BD615B8DFD0F7E1772FA1E35DD06E +:10BB3000E7C0F8F3054446F9BEC64EB6021F25829B +:10BB4000EF07DF889F07E6C8914CF95DD6FAF7B991 +:10BB50001EF82041BEF16BBC5EE4CF3844FE8C5F22 +:10BB60001B317FC661C99F71D84304CE851D43F93F +:10BB7000330D04F367E838C6FC990FAAE2AFA39F20 +:10BB8000CB73C7172909C64DC5DF3F281C799F8E87 +:10BB90002F5CA67CEC587F37FE9E287FE73301A7F9 +:10BBA00004F94B9F0CAD2F97E899C67E8CEF62F39A +:10BBB0001460BDC3920714AB67F93F1DE98C4E0EAC +:10BBC000E4787DD7D0A1AF2103789FF36AB7CF0186 +:10BBD000F1A41051F7E0FD1EBB637040F06121B489 +:10BBE000B3BF0B76B78D4A5EB0BBAFDEE07877C0EF +:10BBF00020B71669E63281F60639BC1862D8741F80 +:10BC0000C9E71563FEDFA72490E61D418E3638E5AF +:10BC100090DDB08FFE0476C4859C0EFB73E3C3AF4A +:10BC200030C766CA631ADE9FE703F07B68B77A47BE +:10BC3000969F00DF70A6717C2B1E7C587F3A38FBE4 +:10BC4000E1B00DE26A9512CBF3FF9BC33B9DE7BBCE +:10BC5000B1FB030E4BBEFAE25CEBBA59BEFAFDE94A +:10BC6000A19939D82F30C1785F60AF5D4B9942BF41 +:10BC7000FD5CEE58E1B289C3D9BAEFBD3CEF3E5945 +:10BC8000262D7B0CF0B7EEF71B398CCE45FB0E074B +:10BC90003BCF02C1E7A4726F0561726F454E21CFA1 +:10BCA0001F4FB703BE1AD8106485F7109E2F0938AE +:10BCB0000F831F87BB158E21125809F9DDA783E773 +:10BCC000865C6D450E9DF79A57921590FF2B9D83CC +:10BCD00007C1671DE8B31D1E47BFEFB8C71DDD498B +:10BCE000E03CAEF8C967E837B542657915641EDAFD +:10BCF0003F929E2F7F79FEE8ED9FCED47031F0C742 +:10BD0000FB3C3F5BE8A5CEBC131320CFFEBD8CCA25 +:10BD100029B97E8CC36B9940473F4F6274F4001D74 +:10BD20008996D7FD6222DE87BF2A37AC423B91E776 +:10BD300047B4C109909770A670A27F1C4047A783A3 +:10BD4000D39A1CC2F831353E9DF4E4B0F8DFE9F82F +:10BD500003EFA195FDFDF843C0539C6388F5A9B995 +:10BD60008C0EC557C0CD9A4FA4E6DA783B96AF78D3 +:10BD7000556E08E17C72CC27475D74EDFD4AFCF7F7 +:10BD80001D9E1CE5FE05BCFF5E72B83F39FEFA5EE3 +:10BD90004CC0C7FFA8F54DCDE5F43339FEFADE1EE1 +:10BDA00025FC4264F0ADF4BF831EA3789E0A78267A +:10BDB0001D83281FFB33E2AFF3AFA35E67D8F1F713 +:10BDC000D0B782BE897E4D239EDFE724C73DBF5F8B +:10BDD00046FD29F087ACE7F8E2BC9ECA0FDC6F9DF8 +:10BDE00073706526E07D1EDF771689A6C3F9E62FFE +:10BDF00092F03C60989EE4FC41E195920BFA64E17C +:10BE000020C635FA27C4970B29B98CEE86DA77B1AC +:10BE10007912DD43C8CC9546750F819485311E5843 +:10BE2000E97447658A875B383E94FC9B54B00F2BBE +:10BE3000735E3A02FBA4F0FF70089E86FCBE13AD51 +:10BE4000CF7BC73912CBED35F213E52D71F63321D7 +:10BE50002B3C21D7106F5CB3EB05EF3803BE4AC80B +:10BE6000808DDDA31EB499FCE46C72467EF27E17D1 +:10BE7000E397F73242A80F403F80DEE97CFAC252D6 +:10BE80004026D81990DF33E8494639DA9E37A3387F +:10BE90006080676DAEB02FE50476E3D7BB1F10B3AB +:10BEA0009B2493FD1A1BDF8EBF0BFC54BA5F8C8B57 +:10BEB0008F0959DAA500CFBF646897C1D70A3FFD43 +:10BEC000CE59E978FF00E0373736DE10FE13E0F98F +:10BED0001B595A3DC04DCD0CB0BC0191D73714BF92 +:10BEE000B07B8F3A63F01E2D5E92797C8DDA0DABBC +:10BEF00061BD4A12E747E2C67BE4C26E2116FB86AB +:10BF000014337F7745CE4BFF03F19FCE54C6B29DCD +:10BF1000FFE4423FF06AC9ABC0BEA9FDF1E6F76994 +:10BF2000FB3089BEF92DF40F859D91227F9932FA5D +:10BF3000750AFFF97479D6CF803D46D7536573E310 +:10BF400079E733747FB9546E5429EC5B399F5215ED +:10BF50001DAF4A2ED83F40D7F51939953C9B7EBF7F +:10BF600043181CD6BFF2870CF047ABEC8E1346B9D2 +:10BF7000658D7FDC956B8E7F7C4616FEE67C80CBE4 +:10BF8000AC0C84CBE4A7E6651BE32F43F10FBE8F17 +:10BF900025FA354C9E5AE49C906736277B6F84685F +:10BFA00024E0CDC2381283BB2EE1FB57B345199C68 +:10BFB000145A9EC59124417FBAEFD9FC4B56857324 +:10BFC00040CE405A0FCC47BDBF1CF8B65FA806E074 +:10BFD0003B570AD9D93A222C0F91B414407B9B735A +:10BFE0004086F945BC02579205E3887959D9C3CBFD +:10BFF0001D759FAEBC2E303CAE41DC1EB47F15BE1D +:10C00000BEE35EB76E33C43B92DCD1E398BFCABFD8 +:10C01000D6B8C7EDB2AE43FE7632E94579E9767F10 +:10C02000A40330BCC42B41F9FB52F8E7C017479575 +:10C030006E12A4BF9FFCF9E704DF65831B6245F025 +:10C0400035EB27BF7B3DE645FB43768B5E0A4BC055 +:10C0500047D9F5D6DFCDFACA49FAF1FE90140DE5BD +:10C060007C9979FA784EA2388EA38AA17EF0466632 +:10C070000F1F4E66FD0F27B37E6F71BDD49CA110BC +:10C08000CC8BC9723AC19EFFD8730CAE6C823EE96C +:10C09000027DE274688857A157D6EEBD9900DE9AFA +:10C0A000F72D4238FC5E62E7A4FA0A09F319C4BB13 +:10C0B0000FF593C8CBB4279991C7FC94A5CF8757A8 +:10C0C00034D172DD4BA4244ADB95CE0DD5C0FB2EB6 +:10C0D000ED2544DD44CBEDAEF08F7E02FB7885BDCF +:10C0E00037B68EDFABA59858B39B8EBFE3CA31EA53 +:10C0F00016D852F56027E40B0D6E265EC82F194640 +:10C10000BFA7283F507A7804CA74DDEB5687FFE555 +:10C1100036DA3EF725A2621B5E0F3E0AE04FE2745C +:10C1200001BFCFA5BFAFE37454B45F62E7FC3EF636 +:10C130000E180E0EEF7439D9FFAEDB5F79F934BA01 +:10C14000AEA2BEA948DEE3687BC883824C04D69EBB +:10C15000D8E2B51F07ED0370AECFF043F2147C3F79 +:10C160008970F937DDC2873363FC80F5A5BCBC8ECE +:10C17000EB2913DFC038D46FD7CAD9B13FF6F331FA +:10C18000FE5089F8C3F8790689FD8171AB63F3A08D +:10C190005C9EC7EB0E2E5F80F9DFD3EDD103C0EFBD +:10C1A00033F9B7947F81DF9D148E57D85B0EFAE97F +:10C1B0007ED23710B50D666908B4C37865242403B0 +:10C1C0009CCBBD9BDB617D1736BC9209F475735E19 +:10C1D00011D2DF2CA75AE4A224D25EA1AADE2278D3 +:10C1E0006F4C42B82CAD774620CF6DE9D07B3FE154 +:10C1F000E032CA3F5784257E0F3F1C6C30C46D452A +:10C20000FEDFB224EA5FC791DF37E731FD2EFAAFD8 +:10C21000E3F75344FDDA3C37CBCFCCBB68461E9ED8 +:10C22000C7B0BC68CAFFB3F3A6C5E40A9D17F356AE +:10C230009610CD01FB5AC2F957F0FF52ED56B46784 +:10C240009786CC76E9EF25866F7DB98476E215F581 +:10C2500023DBAD0BF3C4B9708117F500117A8AD1D5 +:10C260009590E78B41BF831CAEA5FADC603737DCC5 +:10C270007E2A1DFB65FF60ED97E7C4EEC3ACB3DC1F +:10C280008769E6F761D6ED6B736401BDF3FB30EBB4 +:10C29000F6BFD369CC0314701A7E1F6610F31F9784 +:10C2A000299103704F68D94D748FB4FDAFF8FD89A3 +:10C2B00067E1FEC494181D79AE7445597E9D867958 +:10C2C0007E05DE1415F252BA6C5330AFA82BD5A3FD +:10C2D0001AF378B6B4B5D4403B914F24EEBF2C4B43 +:10C2E000706EFCCD3C663F6F97585E97BEDC89F060 +:10C2F000F6CBE488F19EBFBF2884F97433F202388C +:10C30000CF761E5F80FCD3A9F41BA1661AC317EB7E +:10C310006F950F74BC0E18AFBA48C53C9AEA3496B4 +:10C320008FE6CF0C95DE3229366EDD7E96BF57172D +:10C33000FAE410CBC35D5406F04C24D7ADFA8BD28F +:10C34000DF3D408FC3F556B819E8CF51155A7E1D11 +:10C350001DF7E4CB0AE6DB918D9AE4A0ED7EFC822A +:10C3600057857B781D95A14535586FC77B8259F558 +:10C37000249A44EBCB5E527A20CFAF91742B304E8F +:10C38000A3458FDDE47E56013EBD69A72346970491 +:10C39000F213D52210784DBB87C545500E09F964BC +:10C3A000A56732CE2C874A85DCA5F281E5F73530CA +:10C3B000BD477E20417CE8A4E798CCFD6B947BD3FD +:10C3C00084B0B2C8FB69FB9F437B46C0730E9517D0 +:10C3D000E0C749F0FB64EC87652A4F8B21EF742698 +:10C3E00049467A1B6647F0F5950DAD9FD94D424EF3 +:10C3F00056561002EF2358F143E7433A17E77D7092 +:10C40000B402E70833F9FC9FDBB449D120E08B4448 +:10C410006C14CE9D520BEA1D27E481D2EF16298CB5 +:10C4200072F1A7BA2E035C2F242D4B160611EF2FA5 +:10C4300001DE6739FB52000F4715D509F5359030FD +:10C44000885F33BEE6BBEFB303BCE6E758F1A2DB7F +:10C4500001BE0B02C3F085F70BB404F8D2845C2153 +:10C4600066B91224A7D8FDE6CD876E03FFF874F6EF +:10C47000C9F7B2C247E3D1AFB05312E5E59DE4F28C +:10C4800078B47979271DCCAF984106AEDF2D0DA782 +:10C49000938F0F6E90730CF424E8F4699EA72FFD20 +:10C4A00092E7FD967950FFC5F425A383725E9A0149 +:10C4B000F465A083D9FB5C5199EEB394F79F01F426 +:10C4C0003025A62FA33677402904BCAB5DB23CDCF7 +:10C4D0004ECECA0820FEA7DA34C4FF34EA8171BB0D +:10C4E000D39D4FF75FE1EC6DB70710FFDF07FFA6A5 +:10C4F000920410FF9516BD53EDAEB3039D543BADB2 +:10C5000078D610FF35DE61BFDBBE0AFECF01FC0B23 +:10C51000BD320AFB94E27F42FE08E78D89F07F413D +:10C52000BEFB8CF23205FEAD781772608FCB5BEDEF +:10C5300086787023CB4B9EFAF2B8762867AD0DE271 +:10C540007D993DE9EAAFB0BE85D597F56932BCCF9C +:10C5500058B49ED6D3F29E60A81ACAEB3648284734 +:10C56000A7BD166E87F2B88DACBE7453CBAFE09DFD +:10C57000B3753AEBFFF4F14E7CAF22D2C9FB57768C +:10C580005743795D17EBFF478F5307BFBCFC48A4A7 +:10C590001D7E9FB895AD43D87D7339BDED919EF852 +:10C5A00015F6EB66FD6E38E44C66FE12B3E3E6F07A +:10C5B0007DCE7D88EDD3F7DEC5B5010AF7EB0675B4 +:10C5C00007CA0D5B5339CAD1047E5AA5D45D00DF7A +:10C5D000F9544E10C43BA5D34296B7DA43A75893FB +:10C5E000CFEC2691EF0979E78B0CF85A93CFFC0832 +:10C5F000D12E2B83B0FCE407D9BBB3221F357A3F81 +:10C6000091207E007B44FD9B203F757E510BEAD339 +:10C61000F9E788BCD401FB2A3A6FE9977FBA289ED4 +:10C620005F7E4B3EB3938EF13C7AF17B63246803CB +:10C63000FF640F100FBE03147D19EC963DF0BE9100 +:10C64000E11D923D4156D6F3F7DFDD459DDC1B6CC5 +:10C650002D761D94C05809DF55B9AC8F44D352874D +:10C66000AF7FBE9D4459FE045BFFF5ED4ACF1683B4 +:10C670001DBF54888F59E351AFD4713C09B9B194AF +:10C68000E38BF2F9E67CBAFE65CE16B41B9713A6CF +:10C69000D76F24118C6FDC68E1F335EE3FBF65B3D3 +:10C6A000411CCDCCCF6BE972D8F9FAE0C3BFA3F03F +:10C6B0006F7CC0E305FDBFB6D7DCAEF181978F304C +:10C6C000FBCBCCEF8D82DF23667EA70605E3F7FB6D +:10C6D000CFC3731B713FD0E51C7C4B27B1FD0EE926 +:10C6E0007D0BFFB9E0BE6031F8353696A7C8CB6246 +:10C6F000DE4FBB995ED6A95EE67E108ADC4FFB2F2B +:10C70000C17CF852A147B99C11FC5CCAF5FC303DD4 +:10C710005E6BF577EE433E99CA4B56FD2DF4B6B8E5 +:10C720008748C745FD4DF5F5CB1A5D6F9FCD1D01BF +:10C7300078C7F47604F9688A93CA6B1BE2EF00E0CD +:10C740006F1AC75B3BD7EB09FD03F7FAB8FE01F59B +:10C7500037F01C61B85F1035D9FBC3CE3112D8FF5A +:10C76000437873517B2A05FC7DC2ECE23C32AA3C43 +:10C77000112AB7DFCC1F416F2BCFB0DF0777B8305E +:10C78000BE20E2EC82FF5E2F6076F8B65CED3D9055 +:10C79000FFFD7CBE7E3E7EFFCDF3F1FCFBCF44C3AC +:10C7A000F36FC867CA8F937F01E7DF1D8678697FC3 +:10C7B0007AFC38F8275CFE941610FCFEC9AF7D0A9F +:10C7C000EB3FA6B038FBB164FE4D65E714FF3BD4E8 +:10C7D0009EC98F4CFE15EF911FCB30C7E7453B3FFD +:10C7E000FFBEDFEA0C7518E2E181FB935A408FF936 +:10C7F0008B785EFC7A46C7279F4ADF617C272E50E4 +:10C8000050595A300DDA694A2EC4679E62FAA2D98D +:10C810003EA0C0FB3E3E7F38A5C00FF79B88F604C4 +:10C820008C1318509650789FE4E7FE27F97B402739 +:10C830005DEC2BD6152858540AFD4EDE3C80726301 +:10C84000A8BC6800E542A02084F39E5C2AEA79F93E +:10C850006E5626DCAFACE47C8271E33871E2E171A4 +:10C8600061F37B37EB94F8E7D5A4C0638AF7AED8C1 +:10C87000CFE2902B9DA4339FD65FBD3F1BFD8DC69D +:10C88000547D02D0C3D78DE39E1CD387FBDA523987 +:10C8900038F6C1323C17C678D1DAFDCFA1FC5B2B4C +:10C8A000F866AF996F66178CEE3CC51A671F053F97 +:10C8B000CD2F18C10E7A12F4972386875B787E53AA +:10C8C0008DDC540D71A54F5713BC677BCB0B32D257 +:10C8D000D52D3F92F0DD0961C7ADE5704EB42FB89C +:10C8E000A71030C815B8A71030F875704FC158861A +:10C8F0007B0AC6F6704FC1580FF7148CF5704FC104 +:10C90000582E25D7B6439C6E5D17F14602ECDE82A9 +:10C91000B13FDC5B3096E1DE82B13FDC5B30963FBD +:10C92000250C6E9F3E2463FC1FEE2F18FBDFF0C228 +:10C930008FCBA3B06D17CB536B7751F8031DEA5A19 +:10C94000DF240A9FD51C3E70BFC138EE07A9173DF2 +:10C950000FF859DD77FD42F85EB0EF26D3B8A49BFF +:10C96000C9E316FA17E0783D09A5813F37850C1E0B +:10C9700082784773445261DE1B1E30CBEDA1F74C29 +:10C9800022E6DFD71043FC37383CEEBFA5C0E343B7 +:10C99000BACA2379C6784F8C1EDC6A14E0F09AACD0 +:10C9A000C6A38752726E1AC6799E97218641FE48A9 +:10C9B0005AB6CF920CE703167824E598E9C21530F1 +:10C9C000D3454AB1992E3CAA992ED22ACC7491AE65 +:10C9D0009D37227C336BCD74B2466E42BE1770AE6B +:10C9E000A07F01CE53E0854A802FDD27C48BADF0B8 +:10C9F0006DDCBFAD13ECFE3385EF9316F87E466613 +:10CA000055BB03585DE72C8FD93165CFB7E021B016 +:10CA1000357E2AE028EC081107A5FA1FEDE9985F9A +:10CA2000CFFC3D6A1F1C2CC0F303E6E7012581DC27 +:10CA3000BC8E84513E5D67B10F6E70DFA7807D3084 +:10CA40006CBFD43283F70BADFB057B8B18E25256DB +:10CA5000FB40DA2F453D9361BBFB859C0E7F89C669 +:10CA600090268D466EF47AB4FF02B9058EA2B3DC2F +:10CA700014378E6BF7897508B888F993488B9C0337 +:10CA8000F45C6CB5CFCCFEB5F0C745BC5DC4B585D4 +:10CA90003F2DFC182B9CE57382ED40FF53BDC28FE8 +:10CAA000EEBB0A7E17FEB3D56F1DBA170090857BCB +:10CAB000373C4E7FA77F9593BDCBC7F84EFCDEE990 +:10CAC0005B9C36523EE61DADE67B30741BDA88F780 +:10CAD0008A00645970EE4420A842B65E7A6800DE8F +:10CAE000DAD97AD98B83CFD2EF96921F0C6C82BAA7 +:10CAF000535FCA00D7A1783E61F78415DE4F29E85D +:10CB0000BC19F468B26A27EF1AE8C24935D5BBC52B +:10CB10007C5ED0133943F5BF319EEBFFA3BE775146 +:10CB2000F8BC3B7E847A456D8C67D759E1259EC35E +:10CB3000704DBAE838D8272E62D837EA4343598E69 +:10CB4000C10B55AB8CF7A644BD06EF977CDD7D018C +:10CB5000DEDF7518CBD157DE7718D71F617905F660 +:10CB60001081FC5BC547EB8DFA65880E2943951B48 +:10CB7000F6378A7D01D380FBC9EC1286EFBFD5BEA4 +:10CB80003A2CF88271435967F5FAF4B37C7DD1B33E +:10CB90001CBF64D1D90D3F6DD1D90D3FFD2C5F5F16 +:10CBA000F42CC72F597C76AF4F5B7C76E3573FCB95 +:10CBB000D7173DCBF14B969CDDF0D3969CDDF0D39F +:10CBC000CFF2F545CF6EFCEA6807BA2BA204DE97D8 +:10CBD0000874103518A0262BFD19FCF92295609ECB +:10CBE00006E17E4921F74BB66D6DA90717EA115D85 +:10CBF00009603C88FAF739B47E2261F58F742DC63E +:10CC0000386BDB980979F05E95BBEBA2E3707F6F20 +:10CC1000A2CEFC71EBBF1BB64833FFFB6B9757648A +:10CC20009ACAD3FACCEF575CD55864AA5F1E3EDF90 +:10CC3000F2EFE74D35FFBB64A19996F7206E26C64B +:10CC40007B918524AA427CA5F06E5B159C9BD9C183 +:10CC500067BE90FEB753C17E1AFD6BF45F0AA92729 +:10CC600034347E10E0A698C6775BEACFF41EEAFE65 +:10CC7000B1F1EFA112786432CEBD736B1E26B1DF25 +:10CC800088F13981AF3B37DBD0E5FD6C2BC1771ED6 +:10CC9000AB23011BBE83CEF1763E273DB1EF48ABFF +:10CCA000F93E7AA14EAA009F451DC406F1B5E04E9B +:10CCB000A26A04E34248278FE8F1E9E411E2AD8279 +:10CCC00077B91E8910FC77B2045DDCE908E4C1B9CC +:10CCD000DAF95D8C1E049D04804E52212FC8FAEEB5 +:10CCE00080155F644A94AEF591AD8519C67C54B247 +:10CCF0009BC1DD49FF8E84AFE29D667C0588A1FC67 +:10CD000015F0F5E9D7C497E20B45D37C10CF240189 +:10CD1000C8933A3866820DE011EC52D1FFAFA5CD31 +:10CD200000CEC12EF69E9AC093186F6B2B89CE331E +:10CD3000F87F4135AA019C6BE44955907FBEA30C56 +:10CD400043C6C3F0B383789321EEBDA3CB968C6F1B +:10CD500054EFA3782921E4BF372F4B2BA6F53D4193 +:10CD6000920CEF6CF5B4D9F0DDB29EA7A47AF3BBB8 +:10CD7000CAD1245B0EEE23C956815F3BFB6AFC4B94 +:10CD8000ECAC3E2A4379ECC661EF7EC8509F5E6BE7 +:10CD9000F97703892641FBE473581E679A667ECFB4 +:10CDA000C651619607148C7D39E5106FE1F4CEDF32 +:10CDB000498DD490C826BAEE73B8DCB1D251FA1DB1 +:10CDC0008B9198DAC67C03E5594F9B82F077707996 +:10CDD000453632BAD0E95FA0A7740B1D7954331DD4 +:10CDE00039E402CCC3157C25D623E66F1B93956CE2 +:10CDF000C775D9F13D6C87554E58D6E7866020C57A +:10CE00009DDB4722115AEFD0197F10B91F7F774C55 +:10CE1000272433F815D6F935E553E89CBF8D7CF20D +:10CE2000F031EF9CC6F6F999CADEB5AEEE60F4EECD +:10CE3000D9CAE81D6E74B37C2D6D61AEE15C752FAF +:10CE4000975356B879FAB46AA0E78BE49734C88F41 +:10CE5000B8FB3546FF6D630E3F0FE5AD7733F8073E +:10CE60005586674A2F6A942EFDEE3BDC98173CB539 +:10CE70008CE20BF0FF92599E4CEB33C3B1C82237C2 +:10CE80008209E06AE5D74470FD96806B39856BD1E5 +:10CE900099C355D1997C4E9FC5DE593C384661FFF8 +:10CEA0003EAFCEE098AEA9287F2F924F45D368BB06 +:10CEB0006D1A9537749DB51A83B7779690E36678A7 +:10CEC0000AF922E05FC8E1EF55BD2FC0BFF3E2D6FB +:10CED000ED2420017CFF5B033BA27B9A9037830407 +:10CEE000F096A631BA1570EE9ECDE05CA871387749 +:10CEF00071B8494402385BE9D52A9FD3BE269C7796 +:10CF00009DC3E3F159A4FCABC0795B0A7B47D931DF +:10CF10008EC1D5E11E8C829CED0ADA715F07820A10 +:10CF2000D67795B0FAFB5356E680BEEDF277E60071 +:10CF30005DB605AFCF01F9EECAE1728668EEDCF2AC +:10CF4000D8BD831A792BBE43DA1950103F9E407C1E +:10CF5000F995362BECC47926D9898C7078488D07E1 +:10CF6000076799629297F98D66F8A658E0EBFA9AEE +:10CF7000F2E1B5AF291FEE216CFD778E17EF347407 +:10CF80003B513F55DC8471F34C3ED7E685DF65BFEE +:10CF900073BD66F8BDB610E489DBAE023C13ADBBD1 +:10CFA000A795F0F75A9CFCFD16F6AECB3678D785E0 +:10CFB00096BF03EFBA2401FDB3775DB6C0BB2EF474 +:10CFC000DB05EFBA9C0BF6B4865FF9D2427C7FF0AA +:10CFD000B35A82F1F14D297F25F1E055D465D67F12 +:10CFE000413DD9F20E9B59CF65CCCB3395BDB3CC27 +:10CFF000EFB67954F66EDBFF0164680340008000F1 +:10D00000000000001F8B080000000000000BDD7D09 +:10D010000B7854C5D9F09C3D6737BBC966B3B9924C +:10D0200040124E42081B0861810483829E84406343 +:10D030004D71435151A88D40314248285E1A7FF509 +:10D04000C94282841834A0585A2F2C378BB56AB441 +:10D0500051A922DD2052FAD5964551F152BFF55221 +:10D060002F40258A177C3E5BFF79DF99D93DE76425 +:10D0700013C0E2FFF8FDF1C1C99C993367E6BDBF5B +:10D08000EFBC332184906FE8BF04CF0412F410FC8E +:10D0900081BA433D9704EDD1FA23C3EB1C6A3A21D0 +:10D0A0005677A5E139F1F7115F22562D248390546C +:10D0B000DE365DBED71E2E26644DCDAC24520CFD4F +:10D0C000B450266D4F80469590D5566F968F3E4F43 +:10D0D000A85954435C84AC6A2124388A90F6163BE4 +:10D0E000962B726CDE601A2177BE2C7BE3E82B3620 +:10D0F000CDA7B969FFDE9C5B09A1CFD7B80919920A +:10D10000479FBB9711924F88423F20D1BA5233E3D9 +:10D110002352425F98B3849049D1F9ACA9B1788386 +:10D12000A584C4253BBDF07D52ACBC13A66D6EFA40 +:10D13000DF37F4FD6FE0E782681947583BAE13BE56 +:10D14000A3EAEA04BE676C6F7E537A74AFAE7DAC1F +:10D150009A98F63E2CF61C72CE37322DE579497539 +:10D160004E5A96A71092D5FF7B5FB69047F78E4434 +:10D170008012920E653D01782A7CCCD5C9B3ECC4EF +:10D180001985B378BECACDE01B27D1CAE4FEE3B649 +:10D19000015CE3A2758510AD1BF0915D1AB3BF2849 +:10D1A0002906082923A4B32578F03D6BF4B9730A46 +:10D1B0007DDFD9BFFF4C55C679CF55552C9D4A9080 +:10D1C000B869BF442F7D5F0717A77666DFA73FA525 +:10D1D0006974BD2E4E37E477920278B5F37A8254A3 +:10D1E00037572D037CF9081941FB956BA4AE987D48 +:10D1F0004F13EF49502AE41D41DF79AC74D3760612 +:10D20000522869BBDDD8AE6620BC705C25FABEF63C +:10D210008D34F0BCBFAB12F0F8CEC841DA6DDE7AC7 +:10D22000E0A77ECF558B80635F1A859BCCD71B030D +:10D230008E6DC0DF028EB293C1B14DCADB19A6FC60 +:10D2400066D55C5E8A115291A676035FB6694EE49C +:10D25000CBB6B4EE5025AD9F28B57861A8C49195A2 +:10D26000C88F6D43F71D5E08709DB9FFC36D08350B +:10D270002D5425E04BDB133DD5A12A9DBC11F88A26 +:10D28000E7BF778C7D20BC9296A917CF236E4A2AE0 +:10D29000CE21362253BC384656D9EB9C51FCD8E0FF +:10D2A00017FA3C3E6DC64732E5FB78AF0E8FF0EFC4 +:10D2B0001B564778D0C5DBB26FFDB904449119E91C +:10D2C0007700E6A3A8BEE8FCC8D9C717C94E43BE7D +:10D2D000278A3713E4657F7AF733BEE7FD06E60B4E +:10D2E000D66FBA5C93791585CB9A17987C241E2645 +:10D2F000176C7686CF354463EDD98A97BE41D664E4 +:10D30000AE44F9D1AECE6F07F9F979A685C8123CC3 +:10D310005F6F07F9A198E447BACF62D00743E6C42C +:10D320001BE4FE9A825928CF069A67569DF1FD614B +:10D33000F5C6F77396A518EAE23D6BE6452F55A5AD +:10D3400046EBAB943A3BC8915B33D74B753AFA1E28 +:10D350005254F73AD0ABA8DB3267E27B7139A53182 +:10D36000E7B5CFA3BD0572A25D65F326EED870BE0A +:10D370008BEBA1BBB91E3AD53A37F2FEBFE6FDEF03 +:10D380006D716319C167C13506BCACCEA2F29A8E2D +:10D3900007B0D77FFF29B5EE73985F14CF96287C2E +:10D3A00080698B175B805FC5386D59F90EC0DBFA59 +:10D3B000EAC1E727F4AAE867557CC44BDFB312A3A0 +:10D3C0001CB7A5590CF89890C7E5C6B66B0CDFDD05 +:10D3D0009B3C63631EA5ABF587648274F73BE3FA5D +:10D3E000FAD3AB711DEB33D9FA07A66FD3BAA944B0 +:10D3F00088D011D6534CF5A1A6FEF9A6F6D1A6F613 +:10D4000009A6FAB9A6FE95A6FA0F4DFD6799EA5747 +:10D4100098FACF37B52F36B52F37D5FF8FB17F2983 +:10D42000C3F3F5E2D920F205F4BAB9BFA268885F68 +:10D43000A1E7237CE536F2E30F722AB43C66671855 +:10D44000F02BE8F374F1B39ACAB810F093A23A50F3 +:10D4500099962F267A7A589F998FFAA38D4E0BF5BD +:10D4600037B75F52041D5773FB70CE12031DF5E6EC +:10D47000143AC07E24CE34944BA7A20B89A418DBA7 +:10D48000B5A1D1F67CF8FFD9A58B53D37180EBDD24 +:10D49000C1E72DE4C023C37DD7223E02D49E1E1BCC +:10D4A00085931AB1A7E9C728DF6D49238138AAEF10 +:10D4B000B6F82D58FF3C937E08EC952AC687237852 +:10D4C0007F42C2128C23E6D3CEE9651DC8295ADEFD +:10D4D00001728A96B7B56462B97AAD256B218C5713 +:10D4E00063433CA58EBBD5AF4059595E04FAFBB6E9 +:10D4F000B13B340BAD279E94497022B5174AAE2834 +:10D5000087E5244C9F9FB9173EF735FDCE24E04EAA +:10D510008246C6E62A12B08E2364ED9EAC1F7AE8DE +:10D52000B86A81E275405BB177859286FDFCE03692 +:10D53000A84ADFFE11B43EBCC082F685B5BCAF057B +:10D54000EC7731EFB53FA4844B3BE6557B2D7E0A4B +:10D550008215C3EB7E05701ADE492C1AADAB7E55E1 +:10D5600002B9F6469E8AF276EB1F28438E800FF5AD +:10D5700065819EFD62AD6D25CC73603C11D952FE74 +:10D58000ED4B310EDA9943F1B906F4AC2A484274F6 +:10D59000951F76C13C9D32AB3F9777CCB7B2385AD6 +:10D5A0007F2CEF987B256DEF9C986B8175E4A5B976 +:10D5B000B4400CBA3A0CF218D6B776D170BD1E340E +:10D5C000976A0D1D77082D8B7909B4760EC09F9749 +:10D5D0002A7F9EC9EA0738DCD466DE9EC6CAB3FD40 +:10D5E0001DF3F8AFE5B9855D3A94FB8FC5CE8C414C +:10D5F000EDD3C37965FDED532AE886029D6FB27ABB +:10D60000875AE8D89BD6DA889FF2D4A61C827EA2DD +:10D610007F8D2DB01DF84351875EAAB3BB026B32DC +:10D62000AED0E8FB0189CCD1CBC97B399CEFCA973E +:10D63000707ED3E5637E99D2EF263F413B6B137139 +:10D640003BC01E89E0DBFFB90FE990E3BB2ABF6A4C +:10D650001DD02959C8F4667E549EAD50E8389B61B0 +:10D660001C5ADFDC6EC1F96DDA45F9977EEAF39B4F +:10D67000DFB180DD3C96042DB0BE312480A5872C1F +:10D68000B30050BAB91EDFC6F9B790F237FA3B20A3 +:10D69000FA68FBA5C3EBBE06BE48222AD655BF1BBF +:10D6A000E9A9715772652CFBC0966FE17E26A957D8 +:10D6B00026713F87C1D9965FD61FFE56B20CE17E18 +:10D6C00093C767CF07FF6EE7C1E030DAF4C4AB461B +:10D6D000BA05A8CCD2C99D1CFE9D24AF4F93E93852 +:10D6E0007B72EB92E1FDC6FA4FF665C0D07E3FBE7D +:10D6F0003F39DF8DFDAE08764F8761C679C395400F +:10D700000B63AB7BF700C98CD136839B413CE53F73 +:10D71000DF93AAC23CEA86C23885A17005908FB318 +:10D72000FE603003E773BE05E86204CC87D3472D63 +:10D73000D2978A7422F00DF4504BEB573430F850E6 +:10D740008310DB89E236CC7FCB2A4A27CEFE749247 +:10D750009ACFEC236F148EC43AB87FE5CD8F41BFCA +:10D76000022EB37ABC560817F87EE75E053ED0CC91 +:10D7700040DF5E077DDE9E5B770EACB374A3AF1512 +:10D78000E8CFB92BE4877E024ECE29214DC27EDA46 +:10D79000B9D06FD3CD9595A817BA08FA4B427F9AA6 +:10D7A000F16F9D62B4F708E9C2F58CEC32DAE994C6 +:10D7B0008E519FF7A3E39B23741CAF8F4B08FD137F +:10D7C000E8B4C47BC0CFA0FE078E35801C7980EB07 +:10D7D0002541D7E27901891D67B8323FE2CF66CA99 +:10D7E00083C3FBCAFC18FEAC0BF86304F2CB7CC00D +:10D7F000879BF461FBF09B8DFCD2B8F3937DC3E86B +:10D80000FC9DA5EA04C08FF87E03C737A5E3C54891 +:10D81000C71BFBF6815E1B7E33A3E36BC1D6488F2B +:10D82000D2E34D1E6D297C47D099793D4BF87ADAC9 +:10D83000737DD7C278576CEC7EDE81EFF9AE473E40 +:10D84000DB180A3A4814BEC3397CE36E89E0D90D6F +:10D85000F263568DF779D0CF3E8F7B3A9433D5BEA5 +:10D8600036302DE6D6CB06BBCF8C5F4A5FAD485F26 +:10D87000C4374D92C09AEDB6A2FE1C806EA27AD338 +:10D880002FE8FEE653C8ED3B62E1E174C73F99EB38 +:10D89000BB1BDE4FA9F611E4D3D39DD769F61371F4 +:10D8A000B3A81D1BB0EBED5841F71DEDB3D04F16DB +:10D8B0007810CF57B5CFAACE033A772ADE58FE4F5D +:10D8C00044DF703ABF9FD3F97A6E7F7571FBEBF638 +:10D8D0001615E57B678B07CB8E162F8F879663B95E +:10D8E000AA45C37EF29A4F2BD07FBF99605C6B65CF +:10D8F0004289148BAEF2FC467B7F78B311EFA9D539 +:10D9000046FF3B596F2FD37F49E5F986F644EF6810 +:10D9100043FB69C48B0F00DDDBD22A0DFD48F813F1 +:10D92000837D2BE0385D9E87F1620A4FB4AB853D65 +:10D930002BDA09A9C378AED5E467769AECD80E80C5 +:10D9400023C297C1B10BE088F02DE7F0AC667E13DF +:10D95000F77BE285DF53B47ECE7C8C8B1094572B03 +:10D96000726CA89F3BF298BDDD8F7E3275F293F208 +:10D97000FCEA354C9F0B7BFCF99C57AAC1AEDD92AB +:10D98000694139B9256D8F672BD6E3BD4C9FFABB32 +:10D990003C147F560F8F57538ACDA2EB4DE47CB3D6 +:10D9A000DA4A30FEDD91EEF4421C2CD1B3A806FB1E +:10D9B00099BE4BC8CF89DEFF23EFD51BEC0EA25CCE +:10D9C00063586764FEA536368E44241827A5D866AA +:10D9D000C09F9DE8EA79305F5B148F79B05E8E2737 +:10D9E000939D23E214663CB96B8CFA6675117BBF7C +:10D9F00037E701C4BB19BEAE2A23FD7670BA684B67 +:10DA0000DF827C68EE6F1E9F4C8937F87F1D9EC1B8 +:10DA1000E324C29F16FDC08F76C7E86FF6A3CF86BA +:10DA2000BFEEC6EF19F55D0C7F7DD2085D3C49C0A5 +:10DA30003B8207115FE47E98885B8BF114C2C6C3FA +:10DA40003AC6B7FD28FF7E99E0423FB2C0690B801D +:10DA50002C2CA0F3003A6EFB55426025ADAF4B98DD +:10DA6000D99744EB05DB6415DB9DBEA11067EEDDA5 +:10DA7000306368987EF71EA9EEA211BA38DCB6E4CE +:10DA80001B32993DA0BC13F600934BE8E7FAD74D43 +:10DA90000C69608F1711EF76025E306B17F444F457 +:10DAA00075B97FFDB3114CEF66CE25CBBA63E07F2D +:10DAB0000D6F8FCA715F3CCA6B2EC70B38BCB6772F +:10DAC000CD8AD7CB71DDF3A4587475B6E4771BC843 +:10DAD000EF51F09D1735D4DBA584CBEF47C8F75144 +:10DAE0007E2FCBAB5B3DA22CC67E9F1246F93D51EB +:10DAF000D5DA01EFE9E0EF015E7E4AF112631DCF56 +:10DB00008E60F6CDF7152F42AF6EEF7A9CE1A558E7 +:10DB1000E0E57612CBFFFD1EE0E569807B3FBD4A64 +:10DB2000C2B80FFB45B6F60CB43FA56ABB007F1127 +:10DB3000FC5C169B6FFEF91DE3E77EEEB7AEE7F8DF +:10DB4000E9E2F1F1DB397E3AB9BEEEE0F869E7FAD5 +:10DB5000FA56C04FDC99F3CDF066237E52ABE34D0D +:10DB6000F830E227A9DC889F44AF113F099ED126F7 +:10DB70007C18F1935EA022FCE2328D78EAC737A7C9 +:10DB8000F057D2609C187672765DA802F6B886CE01 +:10DB9000E9EEB5C220BEAE0A28C57AEF35F9A5A2D6 +:10DBA0004C2F6078CD9C161BEF16DE1EC8D7A40242 +:10DBB0003D9DFC20361FDB79FF63AA1667E87F5185 +:10DBC000ECFE2EDEFFF5E15AA2BE3FFDB94B1EC4AE +:10DBD0005F30AF3F41D2D20B701DEACE30C5FDB6EB +:10DBE000156C1F729B43ED86FD7CFF0AA777BB8AED +:10DBF00023F9ECE01FF171883F09C7CDE59F19EECD +:10DC0000DCFF15ECFBE52DC81E7A356DCF5B9E79E8 +:10DC1000A48E96A30B46E03CF3EBBD7B00CEB26B2B +:10DC2000CE50B67F3CCFFDFE184A6AC154E91B7046 +:10DC3000B8DDB1F7ED4529F42995836807D2890449 +:10DC4000B6533A8D5388929802EBD5705D56B06307 +:10DC500065586F17D6E34937964E1262FBD7DC1F23 +:10DC60003DAF200FC7731337FAAB29C48BA5E06310 +:10DC70007B1A51D227E0F86D7113082AFCF3C05FBC +:10DC800075666FEE009F46A3509884AC82F090EECC +:10DC9000DA87EB271EA2B278DBCD6ECC4FF8335D6E +:10DCA000DF98D35FDFE9F6FBD2E12A21498434DB38 +:10DCB00059F98B78D71628BF74E4062068A58DA87B +:10DCC000FB31E0D55F49D0FEF0BF951068C5C92E85 +:10DCD0003B87F907A73DCEBCB334CECFCED2388D2B +:10DCE00005E9A71EE736F87532EC63FA9643FFB6EE +:10DCF000E44968778AD20CD77D1EED06989F627F33 +:10DD000029F7BDD4A8DDE67C5342BBAD4D0A12888D +:10DD100053FADF96D0BE22C50C4F4E9578F2C64519 +:10DD2000C7717A970D67F12E16EF59F1F75F8C02E4 +:10DD3000FBFB970933C349F4FDAD07A99D0779346F +:10DD4000D3BCAFD7537A4A4FB579B750FA49E57E7D +:10DD500072DCDA4907EAE9AF9F8C62FCBDA365BFBC +:10DD6000BB8D0AA444C57BE104FA9E93EFDF12B990 +:10DD7000260C7663E22445853D8E2239580DF32525 +:10DD80004D16027C714F83713FB7B3B008E122EAB0 +:10DD9000C3F87E2E2955FA227936D48EDF58C0F387 +:10DDA0006A5CC40576A1F26F2D2956DE8328C5FC76 +:10DDB0004AD3A8DE4A82B820E5145A96760631F98D +:10DDC000A3D21BB4831DBB2140FC360AA707E7FB87 +:10DDD000AE81F13ACB7D0960976F3834EBA2B17414 +:10DDE000DEA1B0E205100447A5E0BA439ABC368133 +:10DDF0003EDFF9A6C50DEBDBCADFEFF449C8FFF73C +:10DE0000CC23013F85C7D6863D7619ECDE90858C04 +:10DE1000443B973A5C93B82854215ECBF8FE965168 +:10DE2000E9F8B027B43C19E0B22EE1FC9046C7AF48 +:10DE3000AD6671E71972F6F3306EA8D386F849E73C +:10DE4000F94712A945FB39659ECE5EA6FF123B99A4 +:10DE50005F19BA8E60DE535299D3EBA7DF7B22CCD9 +:10DE6000F68DEEA96671671709E2F767C8BB1C1645 +:10DE7000FABCA75A71033D2599EC73278C4749AE2C +:10DE800067231BCF359E8D9768CA83B28B79B9E91A +:10DE9000BC28FEE44405F1ECAE36E64FB94CEF3950 +:10DEA0004DDF7B59E0399B14029E4FF86E98F812B3 +:10DEB000B67AD558F9139D2D2454A5CBB7700E1002 +:10DEC0003FFCB290F909B6ACBD7698D709DF2B6953 +:10DED00010EE7AE15FFBDEBB03CA7FFF574F135D95 +:10DEE000D75FBF3ABCED518063F36D2F221D72BF27 +:10DEF0006A084C81CEE7F95A1BC2B14C63F101525A +:10DF0000DABBD75A8AEDB8AFB5768F03DB87959326 +:10DF10008083C27398A265FD0CF835247B57A83026 +:10DF200088E6CC9A44D85615ADAFBD92120E950F27 +:10DF3000E9F334D95F0CF190174822C5F7064D522A +:10DF400059FE9BF43CF0534E95847E58CE219F039E +:10DF5000E8E1C46C0BE6BFACA8BDF4C29174FCFB55 +:10DF60002A148C375457555C0EEDC30E317A715D0F +:10DF7000C7F047E114ACA2FC30E2108B279492B0BA +:10DF80003748DB877989350DF4C73C0A60985F27ED +:10DF9000C70F8F0F949686FC00D444AF118F6E1379 +:10DFA0001ECD78758DA47804FD52448A985FC7EC25 +:10DFB000C75ADE6743D544F45FEF5189DF3AAE3F7D +:10DFC000BE5EA4F6A346EDBF10B51FA1FC1BB51F96 +:10DFD000A1ECA1F62394895AC545A574BEA1743A53 +:10DFE0002EF05F4DD94AD81FB86FEAD537FD93960A +:10DFF000657C9F8D726A4A25FDCE2CE062565FAF2C +:10E00000519BE4A552D9505F9BA6887D3C3FE8D444 +:10E01000C42C0BDFE79971A746EB9D990ADFD76304 +:10E02000F511C5C450EFA9B118EAE7EDD18D3F0550 +:10E03000F01387F5092377AEF71744DBEF28A475B3 +:10E04000DA7E80DB73B54B2DBE2D31E877D948469B +:10E05000BFCABF895FA2F8FAAC80A09F2E5B349440 +:10E06000DFA4505141BEF6D7CB540EEAFDEB022A95 +:10E070005775F191C3853CAEEEAB60713612FDF978 +:10E080007A12CFB322F0BC330476C4ADAF5EE90D93 +:10E090009281E5AE355339A2A7938B051D8C2423BD +:10E0A000D19F27530E54009D754D54801E4A391F31 +:10E0B000106EC761889FD2CF539FDEFD174D053F7D +:10E0C000ADDDDD3612F37E2E1FA9CB935995BE68C8 +:10E0D00022E83391F7434895FB7DBA2EC97FA90505 +:10E0E000ECB681ED1485BCAF83476FED8C24D00373 +:10E0F0004E2EC7CDFD57B5EC7C05BEBFBAA51B4B58 +:10E10000679A0F858C5DF163FC669FA7AE11E6658B +:10E11000CFA6ED3A396C4BA3EF19FC806C667709FA +:10E120003CB809C683C4BEC986CE09F17114189DD6 +:10E13000545F807CDE109A8579159DDE0983C6AF19 +:10E140004EC5275BAB5E2269148E4FBE3AF32FB3E8 +:10E15000697910F88DEAC12738DFE4943FF6DAB523 +:10E16000067E396AE297A3267E397A0A7EB9E04EA6 +:10E1700068EFC9540CF51CE0175D7D6B845F583D5A +:10E18000CA2F47915FEE79D986F58D238F1AF865EE +:10E190004521AD67EBF865BAECDB12C30E78E53BC1 +:10E1A000E2975F9F29BFBC7166FCF2C4D9E3973F39 +:10E1B0008E4CFFEEF8C5779AFCE2EBCF2F87605EBE +:10E1C00067CA2F9DEE20E60376CEB6540762E0FBC9 +:10E1D0007A8E6F11F72EE3718A69F3B4CBC7823D53 +:10E1E000CBF3D6443E4DE73CA6BF57D4CE407DB9D5 +:10E1F000F520D397423F97713CFE8DC731CA424C00 +:10E200006FA6974BF8FE4C4D0AA8F4D74E6A12A49D +:10E2100082BE9E22912E1596BAAC76A414B59BE8C8 +:10E22000F7D06EBACFCBF266C92166EFD8E97F404E +:10E230004F17975B0D7A7588D9FE32D5C53EA6D8A3 +:10E24000BFBC0FF212283CBE1EC9ED2693BE15704E +:10E25000D870A812ED90CFB36D83EE5775F2F546E6 +:10E26000ECA9525F45AC78587DA184F0BEC9A3C526 +:10E270001796813EBE0AF5AED0E766BDDC53F59237 +:10E2800051CEF8C7A75616EBE48C7F3CEACD889CAC +:10E29000E1F501E50C3907E546442FF37A442FF305 +:10E2A0007A442FF37A44CEC0F8D951BD3CF281F1C3 +:10E2B00077FA757A7B19D4B34FAD9717707970B62A +:10E2C000E5CC1FB8BDFA5DE9E5CA424E2FFFB99C07 +:10E2D000A929FC0EE54C2DC899A453CB995A90332B +:10E2E000C506397355E1B7D0CB890DBD7ED8BFBF08 +:10E2F0006200BA77707C371568D7C0F8A4E6F4F2EC +:10E30000B6CD74D55BFBC0AA0CA0172FF3F3067A29 +:10E310003FB1F9F7AFB4E9F2A21395103B5FD1FC1E +:10E32000243E9FDB7010E365A79A6F7D21C1D2ACBC +:10E33000477B6BF7D9916EBD16DC13FFB6F3E89CF3 +:10E34000CDF8F28DED4FAF073EBA8FC7FDCC76AE5C +:10E35000C0EBE9DA3FE6EF5E3F52C571CDDF3F1516 +:10E36000DD523ADD0C747A22FBBA31E0E7C98977D5 +:10E370002500BCBE07FAF0C96F43A7AF8C64F83C18 +:10E380008D750761FCEF6ADDFF017FBEFC6DD6BDB8 +:10E39000A090D1D569ACFBBFBF4B7CFF07FEC26725 +:10E3A000DF66DDCB04BE093B2FE3865F289FACFF11 +:10E3B00057E1DB10BF58FFEFD18FC13ABBBEB26F40 +:10E3C00086F805F9FA1BD9AD3F3F45D8B99944FE07 +:10E3D0005EA28F9D877157EBCE4791E879295C0F3C +:10E3E000C63722ED07629D97FBAE4BB047DEB10EFC +:10E3F000D26E63713BF3F3FF2E90D83936A9D60164 +:10E4000079F1BDB3F760BE41E7EC09B86F65B6536B +:10E41000C47B3D2D1AC6933A5B7C58DEDE521D82CA +:10E42000B8C9932FBD25413E58E94B0DA8DFD64E04 +:10E43000FAE130CCE39B5A1A0FF5DB4D768A8BDB81 +:10E4400029DE51AFDFA9F75F9EFC4D13CA4111874A +:10E45000BA2362BFD0F7549D9F44EB400E113F0991 +:10E46000EA063F69D97AB05F7AC07EA1FDA78E5ACD +:10E47000B63ED677D65A483DD82F6B1B2CD5B1EC7B +:10E480009770416CFB85D671DFCD91680FACCC03E2 +:10E490007B86D4E9E36AA7B25F1E1EF5DDFA495711 +:10E4A0008C3A3B7E52846FB9DD32A4485B0821D997 +:10E4B000B32527869DA69C18D65F4EDC38EA5BF80C +:10E4C00049E102965F2DE86BABEAC578726735C10A +:10E4D000F8636768656A09AD3FD1602112AD5FFFDF +:10E4E000328B0B6F2827013847BB219B603DE465C9 +:10E4F00074304376FE08E2E03D55D47F52216EF73A +:10E50000E35A80EDBA8499B73928BDD4962B04FC20 +:10E51000A619F214FC4E4863F9A1B54EF2A338F0E7 +:10E52000ABA62A64E519C4AD13E562897224E54FF0 +:10E530003519F876A078B439FE4CE417BC802F73F7 +:10E540001CFA4CE3CFDB055D7DFBF833F2DF970F60 +:10E5500034CD8278EEA9E871C12815F599594F9903 +:10E56000F958D0D340F4E7043B69A2AECECFE186A0 +:10E57000F93EB513ECA48951BAE8AD9D94142BFF74 +:10E580004A9409CD7F78457F1E2F41E9C6F1129A42 +:10E5900077E1F3BB206F00D6A778519E3E5849E53E +:10E5A000708CF9ED6E597608E4E7AE96662C2F5024 +:10E5B000FAE414DAFFE916FF2180DBCE96762C9F71 +:10E5C0006CE9C2F69E968D58DED112C0726DCB0EEC +:10E5D0002C6F6BE9C6F2C17CF69D294A10C7B9E0E1 +:10E5E000241D5F474753FBE87774F83EEF43BFA114 +:10E5F0007D72B8DDD07ECEE12E43BD2CB4D1D0DF0C +:10E600003D2560686F2AA83B067CE92ADD6178EE2B +:10E610002CEE36BC77BA7EC1D9EE976B7F04B6C9B3 +:10E6200049329CBBA0AFC8706E88F2F190662A5E3A +:10E6300069FDFE441EE7E866FBE49924F283740951 +:10E64000A964601FF426B23CC8D62CF67EEB8DACD4 +:10E650007E7F0EDB3F12799AB23D42D744CA88EEE4 +:10E66000E7DF9FC8CF2915B0BCC8DCE200442448CE +:10E670002E24A8C17E4829DB2713FBDEAD3CEE70BB +:10E68000BF95EC94A83DD9AAB0F9B76A24B082F638 +:10E690006B2D66F57BAA48C002F3D7A814CFD0ED46 +:10E6A0007337EFFB4A2A89EE9793D11AEED7C87CCD +:10E6B0009F3DB2EFED7897E0BE3E87D7CA848F3199 +:10E6C0008F36B9B94F02FE1AD2DCD70BF3BBFF1657 +:10E6D0009B1ACB1FEABDE58B2CE09B4D377E910545 +:10E6E000CCBE29923FD3E7D0E7CFE472B86C6ACEB4 +:10E6F000C7FC854DF52E2F87B3C5D48EF90C9FD757 +:10E70000F3FB0988827ED1307714AE01913F22431A +:10E71000DE1D5DFF88E8F9D3FF34BF6653F37296C0 +:10E720005F934D787ECD4CF427051E364139AEFF00 +:10E73000B9DEEF3ABFE6947935A63C0703FD42DD2A +:10E740006FA66F15F112C7E95BBA99E5456499E8C0 +:10E7500046E45D08BA14F919225F43E46FD8785E85 +:10E7600007FD2CCF6B8E4D5FB63DC403E7DE644BD7 +:10E77000BC774BDEA9F3089A3DF95C392C1BC7C660 +:10E7800065F903FF334AFB85A72C3A6E9E47BB51C0 +:10E790005F17E556F875321DC21BAE027BB5A85C4B +:10E7A0006B85F37C29A504CFE994964B58161D621E +:10E7B000F5DB3C327EAFCDC3E24DA27EB1A63D0774 +:10E7C000EF2799DEBB38F29E15FBFDDE63E1A5C2A3 +:10E7D000E6CDF3906772FA5E3D5966F9D155129312 +:10E7E0001BB0A13A89EB430ABF8B89FB92025DDC27 +:10E7F000F5C71C5BB7B7B0FC3E910FFDB79765CC72 +:10E80000877696FBA6C1D9B3B2502808FBEBA5DBEF +:10E81000883B4585F98535E0C7153977EF817C88D8 +:10E82000272E647BB6171F62F6C28FCBAFC6FB469E +:10E830005C5FCB188F754F49F406E0433556A6FF51 +:10E84000453E74B9D15EA835D90B179FE2FE8F14EF +:10E85000D2E7073DF988C7148FE5F7800C24BFA3E2 +:10E86000F78030F950CAC77496BB1D10BF2E3A64AA +:10E87000C1E39EF2364DC6F3B19D2CCFE389906F74 +:10E88000D0F3A82F723886B89CF81BCF93ECE172B6 +:10E89000E2752E270E839CA0E52B3C4FF210CF9300 +:10E8A000349F97D8D152FD92DEDE319745927F1684 +:10E8B000E6416D56089EBF1BE0BE8FA2001DC790AB +:10E8C000C7B802E9676FF2DD15401CEB350BDA952E +:10E8D0005D5348562CFFAEEBC2CA41F30F3B5BE6DB +:10E8E000BCD43688DFE8B4517F26D6FB1E71AEABB0 +:10E8F0000BCF5BA4955B08E45565D9FBD8FE43AF0D +:10E9000003E97988D78EFBFB649E93BCABCB53B9EC +:10E91000DDD7350BE6FFE03605CFE7887113BD7410 +:10E920003E3A3A499BB22713E6DF39359809F64C4F +:10E93000D7F87D1B0B205FE4A04C800CCCF3B21603 +:10E94000717F96AF2B4DD1A45879EA03ADEB038FBD +:10E9500064B867C20CFF01ED0EC80818FCBC95B383 +:10E960002846FEE269CC13EDDB6F765C3B1BCF4D96 +:10E970009EE6FD17099C0EB3161207FADD408F8341 +:10E98000E0D9650D21DED62EB454C73A5F5B54C47E +:10E99000F0BDB6F453B48B4971EC7924959BE9959D +:10E9A000CDE70E858E4FDFEB2A8D3DFEE51C6F9483 +:10E9B000AE5F0379D5556D41BB22092E62C0FC1CA8 +:10E9C0006A074948EF28973E2BB5313BC1242FFAFF +:10E9D0007DBF54474FF9FDE5D0F9454E437CFF44D8 +:10E9E000F6ECA4600C3C8B52C051C8A1FE70247898 +:10E9F000FEB58BC39114C7E6EB28BE56887855DD6B +:10EA000029CEEBCD2E2A8B714E6C003C98E9E18E1D +:10EA1000853E5C1779EE35A282BE2CA5FCA88B43FF +:10EA20000C043F33BC167EC7F032B7FFA888C74737 +:10EA30004E739DA7DD8FDA456E9D5D0C87A2155A3A +:10EA40009FCAEB3FF64BE17BA85C9576FD09ED9EF6 +:10EA5000A9BCFC3194543FEE9282EFBE415F9E22EE +:10EA6000A93980B4594F8F820819B9555A66B07FB9 +:10EA70003A24EFE167302ED4970AFDA6933A852118 +:10EA80003980EBFA93146E05857529D15641D94822 +:10EA9000BA6CF05E63CF9F0EC3771A7B1C4119825C +:10EAA000933BADC7F471A36BF4E747F2E0168D6EAC +:10EAB0005B1E9DCF921DC67DD20612C2F196761BBB +:10EAC0009F9BCF8F4832050C5C4E10C97F9D82F909 +:10EAD000BDC4C1DAE3478BF3E87D85FAFBCCEA39A4 +:10EAE000BCEAEDCE20DC2F4402C6798A7B739EA758 +:10EAF00072CC3E01CFC33C0C74FC91DBEEB7507B73 +:10EB00003923A5AE11E07115516DAC647683589729 +:10EB1000B887668173B60DE0BBA0DDBC0ECD06F3F1 +:10EB2000F959D7E0EB1378FF4711C175DC5EA46299 +:10EB3000B934BE66BF06CDA5A15CFD7D104D5C3F1E +:10EB40009065A906FE7D51D023D1E4D3597F7FB8CB +:10EB500016609C4CC075603A35C6C976C121D77421 +:10EB600084DFCB7AF811A5AE04C615EBF96759E836 +:10EB70008120ECAB26B27BA0DE4DA97B03FAE71C1B +:10EB80000EBF2FD1A913A75A08EBFC78E747AFC8EF +:10EB9000F9D1F51112BE1BF2A3EB77CAEE0E58CFD6 +:10EBA000CEE70E03BD0FB42E911F4BE901E146E7FE +:10EBB000F521E837F3BC8EDE407E0A76C974B9D8F9 +:10EBC00010477986C3F19E62DFC7F05EE94BD92E0C +:10EBD000BC7F27BF7BDF503A8FBEEB25CCAB4D937C +:10EBE0004915C04FE4237CEA54D0CF4E4BF0CB2ED6 +:10EBF0005AEFBB8A78B7C034BCCBBC402A724EB146 +:10EC0000B783D24DC6F5B20FE4C9DFAF5B90BC80CD +:10EC10009619890B9347D0F28238E277D0F13224EB +:10EC20008BAF1B8350F3932FA1F3FC491C9D27ADA1 +:10EC3000E7DD90101C41F9ED8F3662077A4D4BA845 +:10EC40005B371DBE932CE37C8E503B51A172ACE22E +:10EC5000F2CF26DAE9F7867EED9C00F3C96A9E467C +:10EC6000DEA5A03C5CC4F8E4E8C35F4E8473E0F228 +:10EC7000374E2F9E33E7F4973682C1C38CEFDD1CED +:10EC80001E6FC6337FA731DD762BC4DB3FE6FE0F58 +:10EC9000D13CE82F5CC7FD8537E3991FF466A18856 +:10ECA0002F05D3F5F66DA3434BBA0C9C076A274199 +:10ECB000BEF3676E2D2919FA111FF2ED75DC6FFE98 +:10ECC00098906AA0F3EBD64C1B9242DF4F6F6570B1 +:10ECD00030CF6FEC68A69F1B4E5282D6C5CF1A94D8 +:10ECE000A00DE477C3499BE1F9DFA91DEDD79D573E +:10ECF000FFC98787A6C3FCAE24E155D0FFCAEB123B +:10ED000058E09EF36B0F9FC74070694C568842E1F4 +:10ED1000D12811DF60FD9EF9B71C13BEB34733FB4A +:10ED2000257D5AECF55DC4D7376D75CD2F81CE1A90 +:10ED30004356B4E5AFFB43C590C1ECE7C693E791FA +:10ED4000802EFED7A884111E8D27CFC7E7D3561F6C +:10ED5000B301DDC3382A7D7E9D431B02F1DA81E0D9 +:10ED6000BC9BDB418D2793893F55FF9CF17774FC59 +:10ED7000346CFF2D87DB6FF75BAA63E577358F6611 +:10ED800070199DAEF8201F684C90689B637C57F407 +:10ED9000CB4831EE5F98E7D55319BE12E67D4E158C +:10EDA000D1627D6F3187A3986F4F4A78910FE9B395 +:10EDB000AF10EE9988D4DD7DB9FA7B24B672FCF5EC +:10EDC000FC309C0BE37F7C61EC733B02CF9394653A +:10EDD000682FBF9052F734C8B77997D10AA58F2111 +:10EDE000F38216763EC53F28BEA370964960E26066 +:10EDF00070B661BB18EFA317393F523F1CF2D4AF76 +:10EE0000E2F2FFAA6D4B30EF49C8A98F36CA28A796 +:10EE10003E42DD42CB8084F6EBFC3A0A6B2A571661 +:10EE20006D9FB60FD4C15599D4064D61CF6F86B290 +:10EE3000CD6A88F78BEF2D38CCECB7859D463D57D2 +:10EE40004F3A3F01FBE0A317993CA0FC6D0379BC4E +:10EE5000E82EE338F5DB2EFA00E6576FF2CB33B835 +:10EE60007E36DB799B47F3F8FE2432E94CFCF24610 +:10EE7000A2ED188D7AC127C33CCA14E33D5BA24CB6 +:10EE80002F61F05FBEFD84CDA50E3CEE112A470A2E +:10EE9000E8B8C7A83F0EE51F476BBF1F4DF170FCD8 +:10EEA0002083CB81D1754FC1F78E1F64EBFFB4E196 +:10EEB000D345704F0C99C3EC8638387C407F8D9BCE +:10EEC0006B0FB4D2F5AEA662CA01E782E2983D228A +:10EED000EC3059BE5676D1F6C9FF58980CEB4C7BF6 +:10EEE000E807D5305EFA43091AC0ADA3421B0FF202 +:10EEF000BEA3D6E985F32A9B291996D3F7ED741C96 +:10EF0000D02781DF4EDE03DB9105DDEB2AE1DE1742 +:10EF1000F7AEDEE030BAAE760BBB27A3FD7CE26D28 +:10EF200025D1EF35EDAA7D0CE6953B9BEA0709CE8E +:10EF3000D16BE3DDBAF109B7AF1A394E8E3F3BEA28 +:10EF40008EF3E05CC27E19CDC74F1BF2D1AF1F4DCF +:10EF5000183D89FC7BF836D891027EC7A8BE22BA3C +:10EF60003CB5D1DD52D04AD7B5B4E731BC8FA361EF +:10EF70006530632EE8DB0715A647F9FCD2FE9855ED +:10EF8000A9BAA2FA77AEE4463B52D8C99713F15317 +:10EF90008CF1C2399C0F2EE7F6F1DC0406E7F9C4C8 +:10EFA0009B0BEF5D61272E0B85D9DC69DD65CB40BE +:10EFB000EF2EB126837D036B898577519AED20C1B1 +:10EFC000878D0F24FA21EEFAB1D45708831CB13291 +:10EFD0003EEB7B362EB025AFFF38D631CCAF6F2C51 +:10EFE000E4765D01D1E0FC40E3EE51781E2C2E9ECC +:10EFF000E27102CA3F3BE0F579D0FF74DDD73CE314 +:10F0000008E2B930715F999BF813E9779A760FD9C6 +:10F01000027646DA086DFC723ADEC7D6702ECA0B4D +:10F020002ADF24AA5B73C7ACB944A17CD53894DA33 +:10F030005DB47ED14377B37A7E789185D6AF7DE893 +:10F04000D14B144A9F8DA3C3EF43FD96879E66F56F +:10F0500009E14532AD6F7C683FEB0F7BD894B0B6C9 +:10F060003F74E012F0FF8F2433FB8178C35702FD19 +:10F07000343E3DCAD2A15BEFBA314C3E1E71B07E28 +:10F0800047F2C84F6701BC3DE1C259BA7DB9EBC731 +:10F09000083B96D971629DE23D92197BFCB1639861 +:10F0A0001EBD661AEB7741026977B0F3757EB0C773 +:10F0B000F6EE1A8570491993C2E145C7298D8E2352 +:10F0C000E028C613DF5D0C7A1DE4BE95CA7D9D9CC9 +:10F0D0003997E38D7EA70DBF53AC8D877BAC1A6744 +:10F0E000658F07BC517C291C5F8A1D2F57DBCCE63E +:10F0F00047C74D2E413D3311E2CA7BBFA6FDF3A2A7 +:10F10000F336D3C78C314C1E5DD3CACEF7F7258FAB +:10F11000403ABA2081D98BA494C28FCAB38D1C6E99 +:10F12000EBC624333F32828721128EDFCAE197CDAE +:10F13000FA9FE97AE7F0799CEDF5EAF0A4417C6565 +:10F14000EFCE22C4D3C6081DAC338C736485E9BDF1 +:10F1500072CA78308F9411F8DE6A07B1E373B22572 +:10F16000F25E1E7DEF82697D13811F96727B98F897 +:10F17000CFC7BC86062E2D96B6876C10975EDACD6B +:10F18000E2E4A480AE0FE863564D295F9F9BAFCFAA +:10F19000CDD61730D02739D4973B3BB13FDD46E081 +:10F1A0001E19AF78021FCFC0CFB1C603BE18081F0B +:10F1B0001D671B1F629E267846E06C9A9F8027F091 +:10F1C00031BE576CE42731CF5BC644E2B1467ECEF8 +:10F1D000FB96DFAB60EF2DBD91E211EC1FD548CF60 +:10F1E0004B7BF22CF38BA3EFB577AFF0819C4F9064 +:10F1F000541607EFA9F583FE6BDA558171AAA54F66 +:10F200003DFCA49FBEBFF8D10D2E48AEFA48E9CA16 +:10F21000003BB861FB2A17DC33F7A1E27781FCFCE5 +:10F220002820C7CC5B7F9BCB01617735727D73E46F +:10F23000B7B7CD04787CB1DD8AE70C9B76C405E3D3 +:10F24000306E720DDA63B4FE36ABAFFE04FCD8A6A6 +:10F250009D46FB69F16F3664A8484FFE6116DC04D9 +:10F260000B0E83CDB0C66D56DC4F693C247BE9673D +:10F270004813E9BB15E6677E1FE67192E2BDA95B04 +:10F28000BE0AF2FBCCED5492A03DD6D4731BDA69D2 +:10F290004D3D177E00764593299FA27E003BECC52D +:10F2A00031DC0EE3F7A40BF890403ADA37AD0FFEED +:10F2B000B2E46D3AAF63DBFEE2928AF57A7325E23F +:10F2C000E9D3EE059B9E5607D6AF1F837D10A77F1F +:10F2D0008FE157DD29B18DA15DAC6CB0065D101FCB +:10F2E00068D86CF5520D4C1A1EDEFAC0AFC1BF7C57 +:10F2F0002DCE0BA9A64B1E7EFE9573697DC963D6E4 +:10F30000B41A367D27EC730B3C41CE06D829022F68 +:10F310008B7FFFBC0DE290F01CEC5E819F258FF58A +:10F32000DAE09C9F198ED3BA7B6D980F6BC653F7AA +:10F33000DB33C004697DF04B1BD0F747BB25BCF71E +:10F34000DEFC7EFDE6E75D40870027F04305BE2238 +:10F35000F8EB87B7E0CCA74BB11FC6434E85BFC7BC +:10F3600001476548E78F3C0D7194D7E3BC0087FAED +:10F3700047AE75C17A3E5096317ABF6F5506DC971D +:10F38000576FF567B8B164CFEBEFBF1EE9F0EA83C2 +:10F39000D767B07B24B42C768FA63F0BD6F9B37B0E +:10F3A0002FC1752E22754887F5F7B1F8C6E70AA96F +:10F3B0007E2C06BFCC2D66FCF2C19638480E221F6B +:10F3C000C03E02EC9BBC28E3B9FB7EF72291E558D6 +:10F3D000FF9CC717C61547EEEDB3837DD7C47B35B9 +:10F3E0006D5B1D023C1DC9D186403C9FC2C1CFE16F +:10F3F00026C1BDEFF2C1E943189E880AFB21F81E21 +:10F40000B5C7A7C173E81FB26A8E12C37BFC7E1B0F +:10F41000F67D11DFA0F38E87FDF40F32585E9E79E2 +:10F420007D1DC5421E9010D1D3D940FCBF6D0DD2B9 +:10F43000D7678718FF34066AABB13D640D0E81F6BD +:10F4400040EF6C09E5439C61FF3C421FDBAC9CBF75 +:10F450008DED749E8AA487EF6E09EFD314F4B2E8A1 +:10F46000AE38C37E7D947E8CF745097E157ED6D559 +:10F470005C1E98D76D960F97169BFE8EC2BDE9A7AE +:10F4800015FF6EB0061EF835F033E55FBF0AFC6C61 +:10F49000C5F8C0D1DF3DF7CA1594EE8F760B3E3626 +:10F4A000CA5B331FD73F5E4662F1F151A797C4E4B0 +:10F4B00063FA3C261F3BD9B9E9FF57F2F6EA01E4AB +:10F4C000ADBFD8286F3F27C549E711D0334BF0BEF9 +:10F4D00057337C85DF6B96A399C56A4C394A7F0EFA +:10F4E000111D3C051C057D2E7E68297E2742C782A2 +:10F4F0004E051D47E8D4BC6E233CCDED5530775DFD +:10F50000FE837525F563C0CE7D560E6CA1533B4E30 +:10F51000E7722B85FFF1DFE561BED12AEE071C778C +:10F52000F7B9207F6C15F73BFA202E99147DDEE7A2 +:10F5300060F6D2715F9F2B596737BDBD4B76819DB9 +:10F54000170E90EA58F1242AB1711E6132503BDB4C +:10F55000173BCEE3A1C779BC73BAECCC6D8638708B +:10F5600017BBD77FE18ACB5CB02F707CD7883B80FC +:10F57000FF7EF66799DDEBE9D714C89358C0404089 +:10F580003E24FEBBA7D0752ED8B504F31BCC7194D6 +:10F5900045CE6DB8BFF039B9194B73FC6431C4590D +:10F5A00080DEEF353DDF7511D2D762137DD5017D49 +:10F5B00065F5A7AF1704BF8E27E3F5E7CF9673B9BC +:10F5C000375D2EBE03EC99E3D4CFC75C02B9F800D7 +:10F5D000E8DDCFC1EF07C6F0A723DD2EA9FBD0C61B +:10F5E000EF71467A177468F6F7CDE5B127FE3EE96C +:10F5F00026DAA5E1C9374AEEA1E5B1275F2B7C06E3 +:10F60000EA4FBD9AFB06E9DF7FDAEEAFD0BF39BE25 +:10F610003B0EE7737CF79F726F82FAD37198877500 +:10F620007C651CE645F9772706E03CDFF11C16B740 +:10F630006B7DF6CB12CCBF206D88C793C536668F25 +:10F64000ECFA9FB7207FFAD35D712AC4299A7627F6 +:10F65000A0DFDEF4B403F35E8E3FFBE5247D9CE97E +:10F660003F5D4FA38DC5338F2792398F033D2733DD +:10F67000FFAEE999C95B215F6E694FAF0DF607A632 +:10F68000FDF15F2520978E3FCEEC0FEACFDF0F37DD +:10F690001DCA639BEEB652787F0C3622F5C3378DB8 +:10F6A000EDBE14FCF0FE706170384EE100EBA2700C +:10F6B000A907793A103C868EB521FD7FFFE0F1095C +:10F6C000FA170DBBCE413E8AC245D2D8F3C4805D45 +:10F6D000C2F5B3E7BBBF2C017BEA68F70AB40B4E57 +:10F6E000B5EEC963BFAF74F06DD72D054F67DD73FD +:10F6F000BEB7F866F4FF16D757663EE84FE74FDD12 +:10F7000080F54712BD38DFD3E4FFE6FFDFF0FEB837 +:10F7100084FBF2A7C2FB2FFFD7E2FDCF1CEF896E5F +:10F72000C82F3BFEECBF72896EFDA75AF793FF4BC3 +:10F73000D71DB18F649F1DAEB8EF24C1109C5F5FD1 +:10F7400035809DF2EE5849E4EFA01F22F277E4B431 +:10F75000C56867C8691D6837AC22EC1E64BF6AE1E2 +:10F76000F7B1B1BCEFF66C6F00E3A28AAF7E33ADA8 +:10F770005B8737783B7004A37F2667D454439CA5EE +:10F7800075059D171DA735DDE26E55E19A764B3064 +:10F79000AE04CBB7A15C9DF1C3FDF05DC569BCAF04 +:10F7A000D669F237E20B6CC6BC62B2C70DFBD50E50 +:10F7B000AF0277B95353D678BF6DEF58B6AF1D4F30 +:10F7C0000298B779A6704A2D191C4E66F808B8F54C +:10F7D0008313F747C57DFC4A5A4708F85021D49F48 +:10F7E00064EB413F14FE8E14ECD7589316793BD846 +:10F7F0007E8A1AB9C71FF220B8BF19B96756B5A0DB +:10F800005F2AE0AC1B0FD76F86F399C257E0C54162 +:10F8100066219E1DD94E6F80CE7F95CAE0BE8AC2FA +:10F820001DEE1717F0157033E3E17DA0519D1D1FEC +:10F830002D8DF93AFE4AE2817D96E9F294B01FECF3 +:10F84000E5F204B4978F49242851FFED5845462529 +:10F85000F815C7726C0A9453FBE89A74F3BDE0A4E0 +:10F860003DF237F4A05E41920DF5633985F8FE3420 +:10F870007B96E1BD0390B74DFDF66359E576DC0F4D +:10F8800075E719DE9B99E0DA02ED07208F1BBF3F79 +:10F8900003FD9B1F641619C699F9CEB17BAFA2E593 +:10F8A0004EEE57F74DB5623CFED89FE755021C2F30 +:10F8B00054C71BFA1F24EE74202ABABE2A58DF450B +:10F8C0009EC986EF36BCBDA710E2103FF256189EC7 +:10F8D0005F5C7EA1611C9F3D1C04F2AED56A0DCF1A +:10F8E0001B9ABF204A2A21E7357F4D9489D47C0F8B +:10F8F000761BC699B87FA7A1BF37E49E0626E3848E +:10F90000C3DEE7A014F9ECB654BBDF42CBB16F57AE +:10F91000CAB0EF59F65E5D2B84A1CF3B463C400751 +:10F92000E79078DC0F1C28EFFD4B4BA00ED6F90BAF +:10F9300039E081327ED8A21258D747999D326C4B5C +:10F94000DF23D55D5E0276D6678156A85FF075B776 +:10F950000CFE64EB0E19CFD74D976B12FE0AF2B86E +:10F960005BC21CFF06A705E3F04753BA4BAED5D1E7 +:10F970009DC8DB31F371D1C48A25307E5BA6D6D514 +:10F980000BF2B4F2EF57CA31CEBB12B7F15EBAA296 +:10F9900089BEDB619F5EE425C54F935972FB0FACB6 +:10F9A000182FB9D5E27570A1807AD73DC3BA19F87E +:10F9B000DD3A8EC98DF8BF1015E241F1A975329C70 +:10F9C000B323774898D722BEB7A09CE5DBDF5E2241 +:10F9D000EE3771A7FF642CBC9FC8F205209606EF96 +:10F9E000D558D04E711DF6EE83FBC8EEF41C728321 +:10F9F00078E8A979C70FFB223D874353258A9721D1 +:10FA00009D15270A587F02F1CD1E4F55C258D46F5D +:10FA1000E59887B39CE7CFF44EFD8D07F4C7F2A2BB +:10FA2000D14306CB2F779D9488AACB33B08E5371E8 +:10FA30005E2E258CE7C55C27156C27E1F1CC1FE411 +:10FA4000E3BBE6A9AF5E0BF3D86FC57C67A2684B3A +:10FA5000601D1DA3DF543B701D84FF5D9130FEDDF2 +:10FA60003CC84FC20BD19470E64F629CC33BB2A31B +:10FA70002C19FCF2D40A2F9E1B4C7D588E9C9B05A2 +:10FA800038DC0EFFC373B597BE5A45C7DD01B2928D +:10FA9000B50709A5EF0E9B68A7A2C6C3EF3DC4F644 +:10FAA0004B2F831843BC6CEC3F2E3FD25FB36746AD +:10FAB000C7FF43C9A5AFB6C584671CEAEB8E1956CC +:10FAC000CC9F38355C134E01571783EBD7542B640A +:10FAD00044E38BEF496A2ED0DB9D705C80FAD1BF86 +:10FAE0004CAE0B96A4C3FC8363E1F97C9736642A81 +:10FAF000A5BF1E9B967B23C6491C98FF55FBF3A30D +:10FB00001BE1C8986BE6114F1BD08DA2254C8038A5 +:10FB100095FB0B940B22CF2D0A474ACFF49BB75B82 +:10FB2000A2759013AE285C35B82BB84307673BAD80 +:10FB3000D772B8FECF23F597B5017E17DA912EAEB6 +:10FB4000E53CD5964CBA20CFEE84FB814B811E4E0E +:10FB5000ECB062326B0F34821EF5D8D9DFF5490B59 +:10FB600067C2DF71197BD082F1BD37297D68401FE4 +:10FB7000C1F1087731DE8929AFA6C0F98913694A36 +:10FB80000AC06771D88670FB894282707F6A4FDA3B +:10FB9000C26915C81F2AB677F371264FD4FE518269 +:10FBA0007A9D9FFFD5CE95E1BED481F065DECF87EB +:10FBB000F8F0B92903D3415B851DEF1F6A2A5F5115 +:10FBC0000C7A62797221E663355549A8879B9A3F82 +:10FBD00043B88BF1959332517579533D104D4CD705 +:10FBE000DD237FD286ED0DCD27509ED3E9E401DFE2 +:10FBF0001CE3FB9D5D56F2D35A5A36FC5BFE69ADA1 +:10FC000013F72DDB419F34903DB6E53A7948BA3F72 +:10FC100089C8FF71147777D6BC180F72B656725F19 +:10FC200002970ECCEADE7B19ECE7D73ADC97C0FEF0 +:10FC30007F8EF71156CF715F02FBFD631F4D9A0354 +:10FC4000FBFBB559EE0DF09741AFF016CDC1F63C78 +:10FC5000F7CB509F316E06AB27323A4879347F8E0E +:10FC60001FF5B913E1F2697B4260B07B48AE6E7E4E +:10FC7000C600977EEDB284795198B841E9E79F6B51 +:10FC800086B17B710B4298A735721C8BAF67A4B00D +:10FC90003FC92BF277D346100DF657D39E72B07B37 +:10FCA0005BDF0BE502FCAE7ECA1184B8E4D2FB9E9A +:10FCB000B3813E9A2FAB85C057B3CBEAC68C2B835A +:10FCC000F84908EB5737EFC679754C70F3FB72FBB8 +:10FCD0008A217E55CFF39EEB4DF9BF8B9D7B311E64 +:10FCE000B7789B31EEB68484DF023E6DF8DDE079B3 +:10FCF000BFEF58D83C140E8FF972E84A1B9BD7F916 +:10FD0000E3E8F797A6F462DEB1E20E65D4217C1B2E +:10FD10003CE8AF64C6E3B99A5B87BE5E12EBBE985F +:10FD2000EE16AAFF29CB3DDEB2134BE77882EB1922 +:10FD3000A2846D5E3A4E2397CB9342EFD8F4F983B9 +:10FD400073395C9376B2FD6F735EEC5CD05700172D +:10FD5000BECFBC74D60B53002F029F1724906ECCDD +:10FD60005F4D215E8E172FE045C03FBADF4CDFCBE1 +:10FD70008B451702FE84E5DBC53379D1F78403EDAB +:10FD80002BF3FCAFE3FA57ACA39DD7079A7F3BD781 +:10FD9000B7677BFEED5CAE9BD721F8583C177C6CB7 +:10FDA0005EB798F799D359C8763A7426E44C23A9DC +:10FDB000F3605C96CB150167314F01AF9E01F25D98 +:10FDC00095E63F18D6A3842AF1B0FC7650A420C74C +:10FDD000BA2FC4942BA57917F63BD3F508793BD0FD +:10FDE000BA849C35AF4FC85BB14E2177C57AA75214 +:10FDF0004182F210EE7E90C07FA833D8C3157062A6 +:10FE000041BF0F64FFB9A13EDD7DA3A1FF0F3257B3 +:10FE100018DA2F54D718DA2FF2AC33D47FE4FD95DB +:10FE2000C9AEDF6C68AFD51E34B44F0987A681DD3B +:10FE3000FDB7966ACCE73EFFC3BEE7A01E6C7163B8 +:10FE40007D4F4B26967B5B54E4EF7D2D1E2CF7B740 +:10FE500078F1F97FB59463F9428B8665A8C587A5CB +:10FE6000592ECCFCFD650AD8EDE5A12EF407C68F0E +:10FE7000AFFB0CE4E1014BA03591C2E99C37997DC1 +:10FE80004E02667DFCE55B37815E77B37BE8DA7A0C +:10FE9000274B6A0C7BCE45F59DA6A317574D98C0FE +:10FEA000FEB28BC4CEBBFC6A1CCBF7C17C3D4A9B27 +:10FEB00073ECEC5EDB397324CC4F9C43D879055A44 +:10FEC00006EB68FB4C85F841FFD73A15DC8F22FC26 +:10FED000FCF0256C9A70BFBA3F0EF4775A2A9E57F1 +:10FEE0009A0D0FE97C654DC6BCD64BCAFF82F980DE +:10FEF0005738D9DFCDBA7CFFCA7FDE44DB499BBFD0 +:10FF00008C9D8710F786BC6E3913BBE12B386300DC +:10FF100079A09297FDDD9464C5ABF70744F9D771DA +:10FF2000CC1F98D9CACF0B1C2468C7097EA4EB6BE1 +:10FF300087F90BBEA8752BC1512ED0F7EBA641FF58 +:10FF4000FF0B270420E00080000000001F8B08004A +:10FF500000000000000BB55A0B74146596BED5D591 +:10FF6000AF904EE88400411E76886020AF4E271D7A +:10FF7000C26B28124054C446650714A540313C9317 +:10FF800018981547F774633308AC6737337A5C5DAC +:10FF9000C1D3E0A0ECACE7102171339A300D2A8F69 +:10FFA0005947A3828266B141E4B126742428E270E5 +:10FFB0008E7BEFFDABE8AE4E02E859939373F35797 +:10FFC000FDF5FFFF7DDFFB552D3FE4720701A0BA71 +:10FFD0006C4D1E14209D221DB7215DBEFA3B30F7EB +:10FFE000C3F1EA0B602E06982ABF164C2D01387F0C +:10FFF00004DC369C3FA65D3DB3CB85FF5CFE5182A1 +:020000021000EC +:100000000100ABECF83F8ECB3AEB2AFAE2BF45E1B8 +:100010007A30D335FCF911FF8A0F34813927361E27 +:10002000F77DFDDB346FB75F05B305A0D93F876966 +:10003000D8BF18CC2300F6FA6B78FC8E7F358FF78B +:10004000F9034C0FF8D733FDABBF8EEFBFE77F9EB0 +:10005000C7EFFB434C5BFDDBF97A83DB09D01FE084 +:10006000426BC540350F8F46632F6E689F9CE94BEE +:10007000416A16740E1DC883D40E968C0CA473248A +:1000800096075E0F403AD3B08AF79767BEC5F2C0B5 +:100090001F9F1DF99D0DDA4F463F339402DC03820A +:1000A000FFD965FF7D494AA5819A23A1BCEECDEC1D +:1000B000031B2580FB2090BF00E99CCA3ACB7889BE +:1000C000EE4F719E42794881CF4C3FE6A24CE867E3 +:1000D00052778A078553BADC6480A58EB556180E10 +:1000E00080523A1141F99A40821FB3009640D80AD3 +:1000F00074FF8F96139138392F03C8826C3CFF6BC5 +:10010000169EAF5F077A3E6E5DB94286B274929BCF +:100110008BE5B60222BC9E4D7EC45DE3A0FDEAAC39 +:10012000B44EE2BE4B1DEF5871D0C3BEADFCFCB562 +:10013000F6D5F55405B080E6AFCD54EAF6E0BA2B1B +:10014000FAB43D209B7A9087D3DC79653D94C3BF98 +:100150008C127A9553A6D85507D9A9034CA8C7681D +:10016000480ED9709DC55975A9B42E1A662AE0F5B6 +:10017000252D32EB03CC8A7910EAAD52D35B3B8458 +:100180003F21BD544EA89C01A8BFC59B8CFC2C757B +:100190009C64B97F0BCD3DF25B054F7F23A776E7CB +:1001A000B76AC22DA769BD2A4D6E7C1DCFB5BA4D69 +:1001B000DAF14EDCBC95EE948C53C9E4583086E4F9 +:1001C000827CB8C3E46F8764F6B7DEECE39C1FD88B +:1001D000DE2FFA61C73B68FFE72EE3851B009E70A8 +:1001E0004F7B3E30E197D35BBF62DF0637F913DA0E +:1001F00009F991AEC775684380E75E576E0F0550E9 +:100200009E51AFD34CFB47A5503095F47209DC6B7F +:1002100050DE939BF71F213F996C7784496EC84449 +:100220007BBC5E27B58BCB134F868229387F7C5BE6 +:100230004026B71D7B480D3A703CE63D05358D7173 +:10024000E61D9F4C7ADFE96F6239D4FBEB99C6FC5F +:10025000E726F6331884D7B2AFDFCFE021BB89E2BF +:10026000DA4AED4CC134A83361C0EA724C93539022 +:100270008FAE30B8E97AD1215790CE55DCA6C8A907 +:10028000782EEF493548E75E876A506C1427037271 +:100290005FBC6E3343D88671C4966902254EAE6347 +:1002A0002F84821407F5B8D69C24EC79D2E57A998C +:1002B000E296D3AA6EDF82F2843793DCDB5CDDCF7B +:1002C000FD96DBC472FF32DDF7961B29385C237D77 +:1002D000F9643FEDAFBC48F6D390ECB6E173897199 +:1002E0005A8F8BFA3ABADC7439563BBB38EE2F5F23 +:1002F000DDC5712F71DF6A13A8F528774F85ABB87C +:1003000016D7695F03F367E1B8CE8234AFFBFC8F89 +:100310003CE5EF93BD4C9527B42A742EA7E9AA7645 +:100320005DBDFA1BDEBFD7FBDAFED52D5EE7424787 +:10033000ECBAA34812711ECCCE53F6983EAF57EFDD +:10034000133BE718F2D6A4EF5543DE9A8C9136FEA4 +:100350007E85FD11C378AAF331C3FC5B32D718EE5A +:10036000DFEADA60B87F7BCEEF0DE33BDC2F18E6E7 +:10037000DF59B6C5707F96F21F86FB33655024F4B3 +:10038000B97C2964213F9B0BF54CE7412BD307A097 +:1003900093A98A96447421B8993E043EA62B3CAAA0 +:1003A0005C847613B5740E20BFEF78E3EF796417A1 +:1003B0001DBF1AEFCC72C5F2B29EA77F6A3EEE63F4 +:1003C000453DF5600F038A84DDEAF1BE57FD24C484 +:1003D000FB6811C6133C67B43199E34C34A54F4810 +:1003E0009262F1042DD244F958F75B3DBE14CF73ED +:1003F0007FB092FCE83D1946B8BAC79BA9662C0DA0 +:100400003C74DD9D737F7E6CFFA00916939D6D4744 +:10041000FA3AF2D1775EC4EC8AE3A780F8407B9B7E +:100420003C770A44F0FA4C272821CA4376C848A2F0 +:100430005878B92B6F36068899DFA3A2D09E7F48E3 +:10044000570A49DE81A726A49DCAD5E2D28DA8BF4E +:10045000E326E6079648A111288FA60631CE5F94C1 +:10046000C6FCDD0761D6E3FD10B110FFF301384E85 +:100470002F0017D30741617DE2CAC905189F1635C1 +:10048000983D1B91CFC2F4CEE1E49FF9638FA64B58 +:10049000782E2CED14E2A7D004EBA9BED1F9A8D593 +:1004A000F8D858A454D0F90AD35B373E83FB77368B +:1004B0009A602BAE737AEC630F435C3EDEEE299FAD +:1004C0004EF37648A0505E0DB4D842DBB268FFCE42 +:1004D00001940FF4792B3C15338B70DDD945C0FAAC +:1004E00086D6BF00E9679653C81EA6F46719E07365 +:1004F000C37CF93DF967809F2B2459DE00E2421945 +:10050000EFCBE3875F7F6DCEDA3CE6274075DC7684 +:100510008F3A9FCF6FC55840E7DF6C0B6DE57AAB24 +:10052000669884E7AC7CC966A2FC7F14E333DC0CDC +:10053000F0B9DFCEF47FFC4EA65FF833991EF7BB0F +:10054000987EE9CF61BAE87B6400F577BA48A922C2 +:100550007E7AE3A3F73823F8884A30A7DED1FD7E00 +:10056000A5E60F050D279F4C263B6892DD64A7F991 +:100570008D689878EE73CD63427256BC5CD5C7899E +:10058000CF82A68FFF30BE849E333B259C7FAEA9D1 +:100590006B00F96FE2F9AEC8A3C52AE4A19D7747C5 +:1005A0005AEB467A7E47E3703A21C611107648FA34 +:1005B000947AE2630DDBC9AF8A44BEBFD3D659E259 +:1005C00074C4F8032A3130CFD46A7966AA7C39958D +:1005D000FC6216AD3B96ECFAA60F68BFC001E1873E +:1005E000A8D7F9BE387FDAA5C941A7F92D561FF95A +:1005F000D38E964FEEBA1DE53073DCAD5ED9159BF8 +:10060000FF3209C14BF67DE9DF9FC9E0F94EDA6A96 +:100610002E6C99EAC479F7D9F7BC4B22B8DF797C04 +:100620006A1A8EE7674AFB882E70654D4BA7380023 +:10063000217EFEC19CC9FBC8C466B86759A99E98B3 +:100640004C4E1517772BEC186F0C71BE9F617C4BCD +:10065000E660C3FC5B5DD986FBB7E7E41AEEEBFB13 +:10066000CE70171BE691BF52BD8D7CB0DE619B1C26 +:100670001A21911D5CF86C19F33FB784F88FA2FC26 +:10068000AC58389C29DBF0DC3314361AF7A6927F7D +:1006900026D6B5CB5B5EDEA7B87AAF6BABC0D737DB +:1006A0002CF55ECFF6560F5E6F5D8B71E40F14472D +:1006B0000ADFB8C719C473EC187BE90617F2F761B3 +:1006C00051CFF56E54AB7713EDE88ABD4A2E613FEA +:1006D0000765A07A48AF7B13ED08E049AD0E10F432 +:1006E000A7FAFBCC8F44DEFA8AFCBE5FBC7D6B347C +:1006F0005464C8338556CC2FA89FCEBFC9B0952E61 +:100700005CC673E87AC88ED93F3CB4E5DD41257CF0 +:100710003D40756D15E5055C3FD923897597EF79E7 +:10072000775046EC3EAC3A6E980F4F48FB0CE3B561 +:1007300059C6F1D393F7C53FDF5B3CAADCF488557B +:10074000C5385DF9ACC4F92AF1BE7E9EA97B93142D +:100750008A9BE6661BF753554E051407554D98477F +:100760007AC8EB7A7C982B434D4F716E80B6EE8C35 +:10077000BD4920FF8C758FA2ADD07902FF25F2CD47 +:10078000D1BE0AF8E2F6C9F288FAAF23ADEE9FBEF9 +:10079000C3791D7F063789BE234DC4DD8286D326EB +:1007A00013E5BF3EC25E0A9C11533AD2E8E2E40070 +:1007B000A03F552F4909980AF1FEF0CE4FECA8FA58 +:1007C000519E412FD8516F9F994C86FC13A5988755 +:1007D00063CFCECCB9947F6EDF9B1436FD0C7E3C8C +:1007E0005473202D2C177EFF00D98DD84701F48F2C +:1007F000EADF81BEAF427182F8A7F132CF90A3CF7A +:10080000E2BAD507451CC0DB8EC47EF6BEB87E16A4 +:100810003609FFB5E32FD53B55109AE620DC208C36 +:10082000FE0FBF9CFFCFF43832B8CE213FBFB9BB1B +:100830005FEB7E5F7D58F8FDF9E66F3FA2387F1EC3 +:10084000F35FBCDFEB72D3FDBDFA7999FD52BF7E39 +:10085000AE599E1EEA41CE65BA5F296EF6D75AA7F9 +:10086000D8B776E2C5BB28CFD5B6A086A4EEFBE804 +:10087000B47ABD0CAEB87D76ECB62D0E39627C44F0 +:10088000F5FCDAF26DFAE43C41D750FE853A2DFED4 +:1008900088BA06F3AA2583F2EA2CC9BD0DC9E196F0 +:1008A00081E524BFC312845D1E5EE21E3B9EEF6E97 +:1008B000B11C5D77507D06993966DAE72E4DAF772A +:1008C0006BF8D2EC96D92328DE7FD2B0F0B042513B +:1008D000CE93CDFBFD1A025C1F1E4EF30D5D89E722 +:1008E0009C1914767E38ADB39DF0A8C31393A5A0D0 +:1008F000C4EBAF8DAFFF0E5B7C436B982F0D97520F +:1009000046CB3F26FF847E598B8BA8CF8024FA3BB1 +:10091000F603F3A0A719675802A17D0AEE5BE50E66 +:10092000739DBA0C042E9058DF574DF8DA4AF9211E +:10093000B11F9DDCB4E78854D0038E9160B7D7C255 +:100940002D12FBE0DEF0871FD27DDB3C71F8616287 +:10095000BD7EA52ED5EBAA6DC9A1AD789EB727FEA9 +:10096000DBB965385EB52DD9497DF7D9976C018A19 +:10097000CF67B7DA4212DE3F9BDED9467DC8D99DEC +:10098000F96E5C012A4DAEFF7C8DF2FC9F2C6C173A +:10099000006EE11F57ECF4D16314EF6AB7A548402D +:1009A000F5B52AEEEB3DA0FC6A0AD7094B760D0A95 +:1009B000D9A4589E21FF706169716673924245FF08 +:1009C000D90377F725FCAADDF4FA30C6C3E4278EF5 +:1009D0003D86CF2D7B25C543F504E401EB6DF1D6B3 +:1009E000515BA83E7ED1A2EE27FE2B5EBD63601652 +:1009F000ADFF717F207EA2CDBB06507D14ABDB7BAB +:100A0000AEF7CE3767F785BC989C743C71FD1FD755 +:100A1000F848EFC9928BAF9BA146194C76D1340BA5 +:100A2000685D8F2C29E4979D1B92B94E4DB4BB6332 +:100A30001ED1A72CD7F1877E60CF24FF5181E5100E +:100A4000DD90BB7523CAE93B4FBA96AF3B47DE95B5 +:100A50001F6F9F6D556F917D6EB2312ED29E64AC2B +:100A60001B74FABF9E34DEA7D27EC1804354ADBE54 +:100A7000641CE761BF87CF7B82AEE24790AED4E4CF +:100A8000DF35DAD7E1C1E797D6FFFE8DF7582E9B09 +:100A9000FEF133DAF78043E031EF09F925F60395EB +:100AA00076817B006CE1F3EAD74F6FFEB480ECF007 +:100AB0007463EE48D2E342B9F5D48BC8E7B994D653 +:100AC000638F23DD79E023D64BE27913F19B7649DE +:100AD000627E97131F78FD1EAF4F2EEECFEECC7DBA +:100AE000DCC28DF92CBFA9725E5FD263F46C2FFD5E +:100AF0008A764E7D7DFD7CFAFAFA3C67B1D0D7FB51 +:100B00001AFEDE616D3D47FAED782357227CF0CA6C +:100B1000F5F4D682B4387BF9A570F97B357CE4888E +:100B200069CD6FAC688FEDF5CF58D4F8B8F713F1F5 +:100B3000F82BF5A0022EE700914A386F2173661C4E +:100B40004FD4C7E40C389EA01D4FA2F3A05F4ED433 +:100B5000282C5533196FA7F590264188C7C1C96E57 +:100B600017D149928F710FBD6F98063543880F9347 +:100B70003DC238E15AC227B16E999DB6EE8E2CDC8B +:100B80006F6D7F5847F5CC5A8BF08BC08264EEE7CF +:100B90007439E979069C7986FCB2D6092E33AE33D6 +:100BA000C70CEB2DE962DE8D28E7C30716BE4BB8F4 +:100BB000EBA7E69AFEB4EF51C7B3F99289EABC50AD +:100BC0000AF58C9F7DF427EFDF70EEE7A04CA4BA06 +:100BD000E29EFD768EFB89F8C42250795C0911CB28 +:100BE000057CEE8BB13F6CDB0B31BEBE18F75D238D +:100BF000F509F7A53DE9A5E703E5904379E96252D8 +:100C00006A01F1B3DA2EE8A37D52B7123DEB74040A +:100C10000897BD98342C44F9F445497D80EC199F20 +:100C2000E33E36702C3944F9EE5159AD621C3ACD91 +:100C30000A12CE8FF6D7E4D2012C97A8459BFF8DE0 +:100C40008BC725151EC629E1A28BE3F2F884BC539D +:100C5000926B12FDD98F62FEC44EB321EF94146AD9 +:100C600078CEDF5D5CA74EFADE7CD5BC74B958F453 +:100C7000BB25FD4C353DD58BCF68F783109605CE4F +:100C800023EA85F157EC4B91498F55DAB88AF21A6D +:100C9000DA5534D51E9091DFF1CDC2CEC69BC37B11 +:100CA00088629485D5545F3461DED3CF817105327B +:100CB00073D91EC6E9768A6BCDC379EBA41AEE63AD +:100CC000EC54D720DD28B5F2397E059D4C152D9FBB +:100CD00097839BE914F031453B653A1DEA98DE069F +:100CE000F54C6740ABC8FFA3C341CE6BF08493FBC8 +:100CF000C15B2B4D547794FCBAE7FEA1518B27BD05 +:100D0000CB011DAFF4A7CB611AA0FF65F7208F219F +:100D1000391C4712E591E8A7132122B39F5280C8DE +:100D200026FCC0C5FE5A010A8FA75EA71CCA22AACC +:100D300099F19B447954F46C17BB35BBA8255BEB48 +:100D40001FD35357B18BC7BABED0BF32A90E4DD4F3 +:100D5000A37EBD24B9BCCB85A1F8B35D27E79A314A +:100D60002F951497AFCCC6717BF1B773CD98CF4A4E +:100D7000C697EF1A8EE373BBBE13E3C2F2628B1BFE +:100D8000BB983517E74EC1F92AF9672151F4438A18 +:100D900067AAE88F5769758CBAE6376E27FA8B3ADF +:100DA000D4E1263EED58EC133E2A678BF78EC3A69E +:100DB00087F75A70DE498B7A98FC77853D9CEA422A +:100DC000F9AF5A33752085CEA7AC62BECD26705AD6 +:100DD0009D3FBC1E48C2F1CE9DB92BA5E1D73E0771 +:100DE000AEFF25ADAFAE191120FF551B25B7D06C56 +:100DF000F9C03928C3F6560B106EAAEFF7E468F570 +:100E00000CE747979BE3F760ADCE69DF999B4B7A80 +:100E1000EA2A163818646415931C8F8FF675D1FC76 +:100E2000688AB0B72ECAE5DEDEE9E012E51B9A9FBC +:100E3000783DFA151E009F3797A817E97E75F26571 +:100E4000CEFBE78A3E5E17C98AD9AD844A9B87FCF0 +:100E500007150859393F4C705EA95329DE2DC2751C +:100E6000501E253E3548216ECCBCCE528AABB8AE62 +:100E7000A904F7A9B6468615E173CFDE7DCC2AEC2E +:100E80006E88B03B2D2EB5EC3EF8F86031F4419CF5 +:100E90009F55EFBEF4DDE728BFEAF30E374D8FF91B +:100EA000D70B2BB9DF0487218EE87E37AEC9C6F594 +:100EB000F6F8E6518B68DEC48FDBB289AF496D115D +:100EC0007E8F166DF974B03887DE875C947E4E3E57 +:100ED0003EADE589D3769117E8BD30F77B8DE2BD55 +:100EE00070AD8673D6B648A100C71FD13F2FD6F884 +:100EF0005B71B0711FE1278B373D3883ED2824FAF1 +:100F00000A17FE525C587A44F4CDCBB61BFB8D6AAF +:100F1000EA9B693E84AD640F2BEA13EE6FAAE0BE34 +:100F2000B93A3EFEF7D0377B4B347C6C280C65BE5B +:100F3000E4797DD51EE261625F5C05CA8412AE7BF6 +:100F40007D32EDEF35F78C3FF42FD0DF9389FABD7A +:100F500052DB9BE4E460B958B99FA8DDBCD2EDA494 +:100F6000B1E6B75B4CD453E3C4773E80F8E7743FF7 +:100F70005EB25EE2BE0336F5631B2C7CC5A610BFD5 +:100F800085AF0CE43E04FB25AE0FB7BC625B4FE3BC +:100F9000E0EFFA04E442C2A13B6F201C269884F5DE +:100FA000A6C0F341F2300EC3B8C823255ADCD7EAF5 +:100FB00000081719FAF9A096FF6B53460EC4CE39F4 +:100FC00036EFC020437F12D4EAED123A27D58DDBED +:100FD0006F10F793041F7B3EFC8764AA7B1BCDBE7A +:100FE00064C2B5CF1F1ACE7D4C6F72F7621A82AB06 +:100FF000BCA7F47E3A23FB6A7A2B79DE2CE4A5D9D0 +:10100000ED9B7E05BEB4C4F4A2F337557EADC24A53 +:10101000B8C843E0249CA4F6E0CB413BF5851B8097 +:101020001188F320ECF9FC1913BF772F859C7F9D65 +:101030008063EF19B33B84CF37687191DE3FBBE229 +:10104000ECCCA6E1BF49AE3EE08AEBA39373D20D90 +:10105000E314F70D86E7FA960D37DC47796FA5F5AF +:1010600021A0B4E695C6EADE3465B4E1B9A752A77B +:101070001D60BF6F7D9871A97ED33DC6F3C8CD3288 +:10108000C503B820EAA532FC257F1B038120E96354 +:101090005CBBB18E2A8BD471DF9874C86CC0016CB4 +:1010A000D7C0A5B6907F519C1C024344DC4894B73E +:1010B000F1FB8BDA8332D77BB543B150CDEA49DE01 +:1010C0003719E4ADFBA32EF7FE3EA3DC07CE31CAF1 +:1010D0007B906A94F7E0C546790FAD31CAFBC6D55F +:1010E00046B966058C72CC5E3FCE307F445DB961F7 +:1010F0007CF3F3B719E68F0ADD6518E76EBFD730CA +:101100003FBF7EA1E17E61D3D2EBD27F51B8D63012 +:101110002F51FFC5077E7B55FD07F057E81F581F6D +:1011200065A88FB0EBFFCF0E4EE87156B783EB8CFE +:10113000B36F92CF329E302112203B284B663B99F1 +:10114000992CE2CEFB07CE1F5270FC81ABD892499E +:101150007596563FF8B438A4F733897DE39D655200 +:10116000C2FBFE24C3FBFE6B7D57E76D0D1BC6451E +:101170008780BF9BF11C71BF4DD47B5261B8ABF42B +:101180004CCDDB44C75EE0B4DDAD5FD5BFCF4BECEB +:10119000B760F9217EAF384F7F2F434E51DA1D9F44 +:1011A000D4FB31BDCF4DEC7FF5BEB77B9F26EA98CF +:1011B000EEFD863BD3CC75B4CA75F57E49659C734C +:1011C000CB2875B0D74B4D00F6C926EA93234121B1 +:1011D0004C05E83D7494FEA72224F0CCBD84C7479B +:1011E000D380F17345AABB3790C7C777464A057CC1 +:1011F000443FC55E758417F57A4272AE2B267C6239 +:10120000DCD7C3A81EC9F18A3ACF26A3A4302F0D7C +:101210009CA7005DFF215D19E5F5C6F092DEEC2686 +:10122000F1FBA4067F98A9D9E9E6EF9712F1C588EA +:10123000C9C5F569E0B7127FF7F3351D6E6CAC8E4A +:1012400039BFDEC2750C68FDFCFD9AFC75DC639E3F +:10125000C6CF095C6231E6E5FB9BF6B35E9665B6E8 +:101260006B78490DD7E30F0E7178F87B38A5D82D30 +:1012700070321D07192CFF94BAEB5AFC2FCB3C6B34 +:10128000C0A1E0B57ED7F5BE3CC6B758FFC4068105 +:10129000679ED83094F1F3D8FAE7188FBABFE643C7 +:1012A000837FCC5F7DD4E00F0B02C70DF723199D20 +:1012B00016C21F236F0C9A761FCAAFA3D1564AFAE3 +:1012C000403B7898F4AAAF1FD9903B85F6BD369F76 +:1012D0005FF339DAFCADAC5F9DCF63FE233C8EF843 +:1012E0002309DFA7093E759C43A7D6BD9063A6F7E7 +:1012F00089521F37E1CABDE11FBA9F994A87F33A65 +:10130000174DAE530227AA1943F55FDBE401E574DC +:10131000EEB6A156B3A023C57850995D8CA74D2792 +:101320001AB538D6132ED22689EF89E649CA4B0B57 +:1013300070DFC747A94F913F542FED2C20FFAB2EF4 +:101340008C3C20E1FA5DFDD58D241F09DB8B41E942 +:10135000CC077F7776C6142890D055F679BFBC9716 +:10136000FAC4337D02E7A842D9DD784C8CADC21FA8 +:10137000DFF71E60FF3B898B119F813F4B029F72FD +:1013800044ACB3709D8CFEEA73B42F7D4F46EFF7EB +:10139000E83AD9A78E97462DA24E8C6AF5E266AF41 +:1013A000A8675F4AA04D54E312FE4894E3F5D323A7 +:1013B000094F3FBFC90654DFE2FE8AA924F6FDCAE1 +:1013C00000E485EAD877ADA2CFF4FCC516A638A50F +:1013D000E3AAAF7BB378BD8C6C819766FC33C62DD6 +:1013E000F2C348EBB0592971E73D048C6377101EB6 +:1013F0001D8763BFEE15FD3A3C24E25EC786C18CB3 +:10140000B7AF3878E218C5AF7BBC6A23C975A1C9EC +:1014100055CADF67A5EE61DC6CBFD7C5FBE27999E1 +:101420005F8C436B494F2BEC11C6D9AE85ABF7C629 +:101430007FC7A2D6E7F21847761590DDE8FBE239C0 +:10144000F67BE3F06FFD1CB175AEEE073A3EAC8F54 +:101450004F6F7E6AA486EFCFF7F5905F8F69726950 +:10146000B3F48CC75FF28AF778DDF4733300E1FFE1 +:10147000B63E98FB917EED15FC77CC457E18DF508B +:101480008A48BF2BEE72B849CEFAFAB88EFAFA55EE +:10149000F6E91AEDFB8AF85F5A23F07BFD7E5412C1 +:1014A0007A0D6C1078EA8ADD478F3D8EBB2C79353A +:1014B000BF98F281FE7CA29C51BE23F9FB3B59BC34 +:1014C000FF42F99EA7F51371FB9F2BD7E850F19EC1 +:1014D00036BAE5D230FA3E6D057D0F5740F621F061 +:1014E0002F6830E25A28AF00E11BDDDF6B01BF1F20 +:1014F000B369F9C4A63F3FC46C78BE3EC597548A11 +:10150000E77F438B1B383F64A2EFB9B5F8D4A0F551 +:10151000DD89F84B43ABC04D1B32AD5C4753FD43F7 +:10152000F7F5FA67D58702375D9525EA6C3A27E922 +:10153000593AB28FEB852BB8B884F91EE5986E55F1 +:101540008794923FA92B399FC937A29EE97DC85F36 +:101550006FD37004911FBD5A3EF4D23A74AEBCBE34 +:101560009C274BB47DB1BF60FC6E2CA85AFDA0E156 +:101570006F1BF619F087FF037A5FA88030310000F7 +:1015800000000000000000001F8B080000000000A9 +:10159000000BFB51CFC0F0030947B0A3F20FA0F13D +:1015A00067B2A1F2B3B950F9875950F9FE68FAD180 +:1015B000713B13030323137E35F8B0083303830C08 +:1015C00010AB00B10E33F9E680B089280343A904BB +:1015D00003030F906604D23E405C06C4FE407E27A3 +:1015E00010CF0262197106864B405A5E8C81E1A5CC +:1015F00028449F2D90FD438C3C3BAD792973F32803 +:10160000A60C5BCAA2F285D41818BCD51918266B93 +:1016100040F80648F2AB8062C26A10F611790606FD +:101620003D205F5D16BBB94781F2FA40F9DD1AF83B +:10163000EDDFA183CA773543E5E7A1C937BAA0F248 +:1016400035DC50F9AAEE101A00B1C92A3BD80300C4 +:1016500000000000000000001F8B080000000000D8 +:10166000000BCD7D0B7C54D599F8B98FB9736732D7 +:1016700033B949263079C14D081030E02484808A7E +:10168000701322449BC204698BBB6C77C4D646148A +:1016900008EA6A7C6C33790701096A77295A3AB1FA +:1016A000A2A0B44D5DDC3FB5D69D40DCD2D6D6A01D +:1016B00058E9AE6D23F5DF5A57D9A052A9D2B2E747 +:1016C000FBCEB9997B6F2609E8EEFE363E6ECEBDA5 +:1016D000E7F19DEF7CEFF39D1345F4106D0921E7D1 +:1016E000E1873E5F25F4273BF924A48790F9F01C9D +:1016F000922373E019E3EFD933B8B64F2045581C55 +:101700002495841410F653D0D4B9599C4BC8641254 +:10171000FEF1CC425A1EBABE8E0468F9F5ABFF004A +:10172000CFCED5D5B557E984E4ACE93BB69C3E8332 +:1017300091B8102D25E4412212920BFD15C7AA7C09 +:1017400084B44367971332299663C44AA160D002D8 +:10175000217FA7F28188A8CBB4ECC75F93F3309FB9 +:1017600084282451821585F3EED1ED9DF5CDA71F78 +:10177000DA99750AE1FFB71298DF44EDC8ED6CBC49 +:1017800018FDE73CC54B5E727CEC27A7C152268052 +:101790001FFB776304EF9BFF57C6CB25E51EBD8279 +:1017A000CEB74ED4E2509FF465C8B41CBC452609A0 +:1017B000817EAFE8115CFAC4EBD249486D9F0FF10E +:1017C0002BD4FB93F07D8E08389F2977BFD9DB158A +:1017D00024E4CC5A5F18E94323242B73F47CBED64F +:1017E0004C48C26D29AFAE16A2385EF8C7C5B47DAD +:1017F0006CB518DE0BF0D4ADCA80F766BD3BF93886 +:10180000A3E983E832C5A3CCE943AE130DCFDC4F87 +:101810004F1FF227A48FECDB2DEDC8C5AF17E27D7B +:10182000FE85D3C7A71DCF5CD7D17CD582704CB9BC +:10183000BBD843E8FA3F50BB2A3D9AA2DED8EB5A08 +:101840008EFC1EAC23463C45BB2DB09E38CF984D38 +:10185000DEE093AE8F34B2BCB7D9D64B9A5CB9A652 +:10186000771C7C4841FB7CCD7E9526497F338B16C7 +:10187000654D84FE64DE5FA7B62E46806E81B62974 +:101880003EA49EB204A1FC414224BC974320D2B2A4 +:10189000A219F1FB0428C5715D4CF8D462D1369EC3 +:1018A0002BDF6B5B0FB2262658E1579A1484430650 +:1018B00036E1F22E82C28DC10D439C9F06E57B6C02 +:1018C000EB2FFB48C243E5EA96E272625D07934E56 +:1018D00005C1A4D37B2E4CAE38C75B6D87F382DB8A +:1018E000F964FD77669BA2F1DAC9E477269E28F2B7 +:1018F0005E815F2CEBDEE52287844B0969CBEF8CA0 +:10190000C1DB2EF8DF65489F20B448577EB906F446 +:1019100044F60932C0E931C9239489F57A898EF4F5 +:101920001413EE20504FF245104FE6F7B1E1E27488 +:101930001733FA8B69BF9FE5DD7E96EB3352E17A70 +:1019400073C884BB08E7912CD379BC7B17FD1FA516 +:101950008F589910DF2B8CFE5E07FA90CAA33A7855 +:101960006F91276EC12ECFEAF8B723CFBC36631E26 +:10197000A5C7C1B044405CB53EE3366A68FFC7AE58 +:1019800014E26E81C34BEBAFE070BE686415007D5E +:101990000ED6B8917E572CFF3008E47BEAD02B722C +:1019A0002A7E5DB1C8958483FEB7C93A3FFADF2429 +:1019B0001803F9B206E9C8846B43B984700C2E127F +:1019C000E230CEC0AF7E7FFF1514CE172B84B05B04 +:1019D0004778FD848E3768BC1F1C4F4E10737C9D6A +:1019E00068804FE7F823EBA186D7005F36688A7ED0 +:1019F0001F1DEF66297C14F41899CCF4438336A399 +:101A000006D64712187D2C1572B05D9BAF7512AECD +:101A1000BBB436A5BC6AA08A422B87EFDB668C0B71 +:101A200067DC353C64A1EBA6D70BEF1FB0C039478C +:101A3000F0077F97467F594016C03ABFE75B959EF7 +:101A40002063F7F776B3DA22BB08F9B059BF7FC03D +:101A500035FAFBCD1269EC2B1DFDFE1A41E5F88825 +:101A600029609F99F31E99A72F88F47D33885F4AD8 +:101A7000EA37EFF3B4C856F9E398C7087E3F613BF5 +:101A800035786B2C57077E8BAE14A01F99FE5399A7 +:101A9000E4C79B0FD433BE73C0DB11FCEF81772208 +:101AA0003E7ECFD7DA09F66A9B8BD14B7BB6186E98 +:101AB00025A3E9C55C0F138F17BA1EDB040FF2874D +:101AC00049470DE2DA71D77D223ABA03E8E892FF7E +:101AD000793A7A10E868FEFF493ADAF57F918E92FA +:101AE000E5E5682FACE47DF50FFDF62190CFBF3022 +:101AF00024947BBF58C4E4FF2FA24C2E0E92E8F62C +:101B0000F9A00F8E4B28A7068D363FC24B4D629829 +:101B100007FA5D94FE5E017B692695EBCD2A3EE9CE +:101B2000EC0B56D1EFC7AEFA301FF4D731BAB6601E +:101B30007F13326C18B4FD4B23656A8043D9C3CA46 +:101B4000C32D6763609F0F0AACFC2F2D678D188E25 +:101B5000B7AD7339C5E74AF895C2B17A9160C453FD +:101B6000D0C54F0485E1A586D8F42A5D979F0894D7 +:101B70005ED4C866B4AB098910F40F8BA99D60B11F +:101B80002F9A4081815CAE71A3FE73F6FF12B70BF2 +:101B90009D76DCEA45652ED017EEC86979883E57F8 +:101BA00046042C03FE350BDCA22118A007228BDC97 +:101BB0008F82FE8BC8C4A5A5E0D79586DB66779D8E +:101BC000E67A8CE2650DF35BB482FA39C9FAA74D67 +:101BD000FDEB98CF587461CEC32C5FBBE8F4401680 +:101BE000CCBB56084F8786AA56F045BFB5FF34D305 +:101BF000BEF103DE7EB1E6DA74460751D4AB263D72 +:101C0000FDF88DAFB860FE647516D2E5EA3AC96694 +:101C10004FAEAA49B3953FBFE8DA71ED7012B5E057 +:101C2000C142F7813C82744A7E43ED144AA7B1EA6F +:101C3000E128DA2D2705BD8D96D317374D857EEF28 +:101C40001133B1BEB0B869E610DA5BCB90FED37841 +:101C50009FE94AE3EF8B40AE4E17C9A33AD8A3E3FE +:101C6000FB051D9CCECDB22B188D09743DF5985601 +:101C70002E8D83EFB821D6A6F21BA6896CDD3A62C1 +:101C8000ABB4620068C02E37326A1AD1FE33EB5310 +:101C90003A9E2666C3B8317C3F42C7DD745EB49D70 +:101CA00097D922247DF6AA7432CE3CDA1DEB4FC5BB +:101CB000BF914ACEDECCE1238758FFA64C4ACFA481 +:101CC000FDA7A86F3EBB78FF67C322190438E588DB +:101CD0008AFC50524DACFD10A30CCB0A2FBA431115 +:101CE000B590E2D35D2AC2344847E9A386AC031E0F +:101CF00062B8DE5BE9DAE65BF872EB9F25F4F36F1E +:101D0000168B5A406E6CEDBF89E8141FDE509C6044 +:101D100079CE8D2AE0692B75B206617CB98F001CE3 +:101D200069F9F4773A4E9A46E23AED4FD6FB122221 +:101D30002DCBB5246CD04F7E2D2C78A99C381C2A35 +:101D40006A91E9FBF6B504E52301E961A19FF6D0AC +:101D5000CB8604F4B3868401E0F6E03A9C6767E939 +:101D6000BAEE42FAFE4C9D8CF103728EC26BFAF50C +:101D7000D4CFF0961003C6DB9A43E23EB4830DC481 +:101D8000AFA2B1F5D3771593C43CFA3DA3B21FC6F9 +:101D90008FFD3D617C49985C93B93C2132A53F1889 +:101DA000BF490BDF9782FE5412BD499C6F59672DC6 +:101DB000827EAC136FE90AB906F0DB5E46F9208536 +:101DC000DCBB4314910EE2E1552B8B528C738FA830 +:101DD000A37C32CBFA5905E11FAB7EB29E4C12595F +:101DE000D0B521005E482488F3CB24233F0694B36A +:101DF000F87C279146AC175AD8D30FFC966BF45554 +:101E0000012EBEE6FFFC315C37F28806762C85B6E3 +:101E1000F87C56525E80CE81F9BD1716D1EFF08B5B +:101E200009CDA01DF83D8321747E758271B9746857 +:101E30004201BEAF596D07BB2440C2027CF787E563 +:101E400098D5AE4F27B46C8BA790E3C59584897C59 +:101E5000FCAEF503EB68258D9702300F068C7F05ED +:101E6000BF699B3F8A7ED8879EC05C18EC4E6FE0AE +:101E700051787EE8991247FF2CCCFC2D95FE03F299 +:101E80002E7DA16CF36F320C7B39CBE1872D937CD7 +:101E900038CF8CCF12EE5F1975D32725E1A210D56C +:101EA00003BDECAC9109F8FF3E1F83C7842F4BBAEA +:101EB0007701EAC7B07C12E0A0684138CE90730980 +:101EC00058E24009C1F82985EBA403AE930EB84E41 +:101ED0005AE16A52D97C9DF662AC9A943452E07E03 +:101EE0002872FF83DA4D60379E21EF18B540389194 +:101EF0006B50CF0634D6C6A70E62B042231AD281E9 +:101F0000D36EA4EBF49ECDFF5AC8CB3A11601E14D9 +:101F10004EFB77928FF48265898CC485D72D34F17E +:101F2000A57FE1DF29FFDD74D44580BF281F4BF07A +:101F3000DDC5BFDEC4E3C3EBC0BFA6F8FB12890456 +:101F400000BE77898871A877C9CB81791639794A1B +:101F5000E4F6092CB1958F493804725CF6750E4A87 +:101F6000014483496FC2795CC73093F33E467731B1 +:101F7000A2B6A03EEC66FEA7194FFD728FDD1FFED4 +:101F8000CA2E7BF946B26A12C44B6F7CC845E2B4D4 +:101F9000DF9BACFE3D5DA757450DE1FB0A69EC04F4 +:101FA000BBA4CBC5EC8D751A9121FEB9E1FF7DA3D1 +:101FB000F27A3A9F33200FE683FD4EC1B7E891F5E0 +:101FC000C1B862948E9E5F9B105E718530F6FCBA3C +:101FD0005C832BC0FF8E6D77A19D499C71D08312CD +:101FE000C6412DED10DE1BBAEDF39B68FECEF91253 +:101FF000F200CE77FDBEEBD13E1F6B3ECABED4F6DB +:10200000A64F126C711F93AF4D7A77F27785A4B308 +:10201000B80E558368AFFC3A2DDE86EBDBB800D6F0 +:1020200077A2F69741FBEC4FDE7EF1A71C7FE90417 +:10203000ED37A8C3CB60BDB7047B22C09F661C6B85 +:1020400023891979F457D7739B6360BA8DD40B5DDC +:1020500060BD7C5A4FBA807AC5E3F7778ADB253FAB +:102060003AF02D05ECD4779F7C6305D80137FF400B +:10207000222AA5875307FC2481F64A5C01FB663DB2 +:10208000A5BB38961395D75AEC614AD1B80E377F65 +:10209000D78F76C4FAA7DDF13ADA7EFD3FFF762EC0 +:1020A000A17838D53AFCAF7940CF4F0A2CEE1A1BF5 +:1020B0009A7B2D7DBF5E267F1B494147D74B8C9F66 +:1020C000DEF97EDA1AB013857DFD5FC47EFBBEE0CB +:1020D000725BF4F11AC985E3D27AE847C4F60BF1D2 +:1020E000E90283CFEA0F98F1EE77F60B0CBE43AE10 +:1020F000B807E0DBD7AB4469BD4DFB4E235D2FFD38 +:10210000EEB70380874D87EC76FAA67D52C23D1765 +:102110009F6FC01334A85009F864FCBCF1E006D4EA +:102120001B1BFBB69E067EDE74C86593FF142FE171 +:1021300004E0F535295C07E57F7A22A05354BD3DC4 +:10214000B8370078A5FD5EAF50BA5AB9D0DE0EFAA6 +:102150003F9B39BA3FEA19A2DFBCA96F0B1BEFE026 +:10216000677F0FF27613617ACAE4E7B7E1979CD1F3 +:102170007A668B648F6F9D212F56E23EE0BEAC9451 +:10218000FEB3A9574CBEBEF9DB67F6C4E8F8EF3CD6 +:10219000FD1F7B62741EB7FCE5FD3DF7D0F991E7AA +:1021A0003D1AC8AB4D4FBE1A2016FC3F26B1FD802C +:1021B00053FB9F787C37E59353BF74A31D78EA8760 +:1021C000BF9FA2D3F99FFADE9F26819D7AFB0FAFB6 +:1021D0009A0CF8B8FD99A593C7B3D7816EE36EEB5F +:1021E000FAC6B17FFD90009B20843CC79F8E753A54 +:1021F00072504A4088E0DD13EEB89BE267137DD74A +:10220000540EEBB601F51594EFA5F8DE78A0EBB40B +:10221000343715DE637962089E893C128275BF7679 +:10222000E59515F0748575A013328C7AC2D96ED3FA +:1022300071BABE978EBD9ED49E5000FF9B0E6C61FE +:10224000E3F6D1F50C8C5ECF77E197CB46AFE71183 +:10225000C91E673A436EF9E66EF878300BD77FAC4B +:10226000F5DCF0CCE7C6F5EF4CF930119E1B040607 +:10227000D70EC97845027E7CFAA9C77707D93AD725 +:1022800051C49CFAF69929B0C9FB966BF88B2027AC +:10229000877FE8D6C0AE5EFFC3D790EF4E3D734C4C +:1022A000D1717F9AF804AA274F91919F41D09B1B2F +:1022B0000556D8F4983FE10E24D76B63BCBE560F89 +:1022C000E0FB37F07D9CF1C3C678FF6A21C5FAF9BF +:1022D000E422A69FE2D988970DFAA0A2F9ECEB2A96 +:1022E0002C84F57C6319D0DF58EB69CE5F83F92F1E +:1022F000B0ACEB638C8FC7E2D753BD6E59481FBD9E +:10230000CEA7B85DB1292EBC966ADD096965F1BD1D +:1023100031E2DEE6D349178A6CE773B3BD39FF8932 +:10232000F87CE2795D1CDECE707DEDC4DF3BE752C8 +:10233000EB812259E07AABA736D7A2EF3C2EAAC791 +:102340000AC1EE6C8CE51526E1EDEC9350BEBFB3EF +:102350004F427BDF2927368EE1D787CD710EF5CF2F +:102360000579F6CEE1EF737A64F4BEF1C01B4A8CB6 +:10237000EB85B8552F407F29D6E372DEDFA6E75202 +:10238000F7B7E9C0E994FDBD2D1B5F00F8DF1E74AF +:102390009118EDE2ED3E29659CA45876D9ECAC4E3F +:1023A0007FE58974DA4E0A787598775BABF15A0C41 +:1023B000EC91975D04ED4739FC969B7E6FF37B7142 +:1023C000BFA52D7023D12DFABBDD81273914413FE4 +:1023D0005A0E462AD85E68DCE6CFBA34D106379169 +:1023E00063F9B0CFF9F3C2DFCBD02FC4D3744B5C09 +:1023F000E8259974403CED254308B79014712D47AA +:10240000FF914512D1AD74664C15ADF1C5C0E1BB6D +:1024100030AED1441A13106F22F9A46FAFA5DF4775 +:102420009A7516778D4C15ADF13F7763A3E1A670D1 +:10243000E4DFAE1581FF36D6F8058DF67D5F73FCBF +:102440005B793C82EC7BF2C92769792A7C13810E87 +:102450002306C2718EED2B2FE5F2F047DC7E3E2C79 +:102460009001B0C36AEF8DCA20EF84D0F518175DD4 +:10247000967FBDBCCE428FCB42A77340AF7EF3CFD9 +:10248000D29A54747A88D355CBDF3F9E03ED777B85 +:10249000BE90CF9CD908C297C7E35D03D9CB7D100E +:1024A000DFEBBF69D98B33E87C73358940BC269755 +:1024B00054F9CA289C79C7A5B027C53A98CF3D3CA6 +:1024C000AEF768B386F2FFB1E610961FE778DDD766 +:1024D0005C82CF279BC3F8FD40F3422CF735D7E24F +:1024E000F3E9E608BE0FDCFD6CBF0278F92AE98348 +:1024F00078CDC1E635F8FD9F9BA3F8DCCBE7B30CA4 +:10250000F0E2B3CD1FE33187DA97B4423CC6C4A3EF +:1025100013EF4B486CC08DFBF9820E78BF4B66F20F +:10252000C589DF29EE3E01E44BD32D04EDD73D3CB8 +:102530006E6CCEF7EB32B3370F72787EE0897E4750 +:10254000A6CFF76A8B4BD12E229130C8EF3D4224A3 +:10255000BD8C5679217B41C82A87A7FAA30765CB92 +:10256000BEC2946E16EFD92D337935553FDD9F41AC +:10257000F1509B2FE8104E30E77BB84ACF073979EE +:10258000581070BD6BF3255262A17BB3BF6FC82298 +:10259000DFDF482DB79374CCE441E6D57209F8B576 +:1025A0006788372C517E7F3E871C24D4FE781EE836 +:1025B00012E4C2AFD2304E6CFA37DBF87A670251C0 +:1025C00040BEC4EBFE38C89FB1FC9E4E5EFF3D0E80 +:1025D000D70639F28A8CFBCA3CFE4A1218C784948B +:1025E00023A0C7DD9EB53B6AE8F3FECBDF3E01F1D9 +:1025F000C1779FF1E800D7F68A93012B1E4983FC2F +:102600008E753F7E44DE9CCDC3B8D8FF27D137649A +:10261000AB1C0A0E2BD0FE7941DF09FBD7B1572541 +:10262000E4BFE785F82C8C63C904FD82E76F0A617B +:102630007E87D9CE1FB6F377A667E8E14D30EF0667 +:10264000251C4BC117BF49D36DFB46EE90BD7D08DD +:1026500074E67C56D6297D96F1798765430238E683 +:1026600093283E17101D9F39AEE847308F79A42F6D +:1026700007CAAD6953AE60FB07FF6378535DFF0780 +:10268000F166D26BE8F2128483DC2D86A7EBE84D6D +:10269000DAE87CA54BE0F855519EE78EEC4F35FE0D +:1026A000A82088DDB0388996867230D7C3F0D73439 +:1026B000741AE3BBA129C41677EF6810910F76BF97 +:1026C000CEF6F5CE3414ED9C41EB57117D474DE12C +:1026D000E87998FCB15B8DA4A7DA9F329F265F98BA +:1026E000E59D53BF48400EFDE3D42F62DE51EEEB73 +:1026F0001E1DFC8EAA5FEF6F01B9D8F106CBAFF8B3 +:102700009537BAC8353F29673A6E6A9C0A7E50C031 +:102710001F59ECA2F889E4C7AF037977A6F676379C +:102720004EDDC7F25E9AEED577CED4C75E9F3D4DA3 +:10273000E3EFDF98F3DA03F31A67FFC29C97B95E01 +:10274000676A570FDFA8839C294E8FA66837224FF0 +:10275000AE5E3DEEF87BB85EA1F35F6BA5CF294D71 +:102760001AE6B798EDCDF93ADB3BE79BDC07BEB044 +:10277000BCA03E17C9027AFFDEC753FEE925148DBF +:102780001109F434E5CF8D004F2569C43291FB72F5 +:10279000C0BE31E97977E7E339A817E47821E67715 +:1027A0005DE0781D2412A9027E0B8B61ABBD623EF9 +:1027B000DB46E83C81715537970362DABDA1547856 +:1027C0001EE93FDFCEFFDB0861723EA1A29C87407D +:1027D000A146CB854749F97DB4BF06480AA5E35415 +:1027E000C92C1E32EFA8DE2BB1B8AA54EFB7E09186 +:1027F000EF3798F1DD0E722FD174F02BCAFAA1BA1F +:10280000C9A74794E84340A74A48C77C4F57302A96 +:10281000B0FD38B63F54C2ED92ABA4B52AD8254DD1 +:1028200024A2CE06BE3D2E119687C7F8DA6DEE8340 +:10283000713E76733EA61C8CE519FCFB739CBE0EA4 +:10284000817D82F604A3A383DC3EA9191E3EE2A784 +:10285000ED4A067BAA613A4F83BDE206FB248CDF7A +:10286000BF03F60A2D1FC9F8C76B6653BCEC33C40F +:1028700030E0FA40B3C1F8A1B901BF37919877337E +:10288000C8A547440DE0EC7AA4550AD0F27E55C0A5 +:10289000F8C523CD8D583F70CE9B007F73BF9A1033 +:1028A000C01E391326E118C04DDD2398D70C3E8F8A +:1028B000AA370771BBFCF1F87BBFDD41EB3DB8D017 +:1028C0008BFB64267FCD681AD6AE01BEDA7B52DF61 +:1028D0000CF0CFBFD580FADBC245B84FF104C51765 +:1028E000ACD3BE5DEFED1AA4DF0372D766F0836749 +:1028F00016AC427B28A0FEE36D500E684FFD1D3ED6 +:10290000D5EFDF09FA7A665CB4ED9F07D49FDE0548 +:10291000DFAB87C235E9B49F59C707BBAFA6CF8EDF +:10292000F0ED2290787AE61F705FE3B0A07DA907F2 +:10293000E26AD72B48AFC609A305D8D15561CF832A +:10294000CC7E310A690B64F200C53B01BC1B32F43A +:10295000FB96AB10E92C14C8A909D0F2E38F9DFCBB +:10296000F1D5F4FB915DB7A25C743F22A33D36F331 +:102970001BB793AF58E484FB3139655EE95B2E37B2 +:10298000E3A34756F7CCD2197902FFCDDA5BA3A2B5 +:102990009C78D19EE760EE0BF792E85B2EA4676609 +:1029A0009FC81ADB47863D2FD84F240F8B8C4F22B0 +:1029B00051AF35FFB9E4EB6224559CFBAC4BC679B3 +:1029C000B5C76B4A601DE4F377E03E19E9B18F6F3C +:1029D0008E47C73F6B956FB2C6E02A00D54FD7B37D +:1029E0005FF9F71C80FF6CA3A9A712A8A706CAC4A9 +:1029F000C4540ADF030F897148CA3C52CBF4D6761F +:102A000099E50B6EE7E5C7CE91B85098E4A3999C81 +:102A1000DF1E7B4464F65C9CA09E23E7CEA37DE191 +:102A2000E3DF33CB5E56717F2266F8AA2A312B9002 +:102A3000FF58E885E2E8D298D72667C5A64CDBFAAE +:102A400017508BC59E4F5D94AC2F811C3FAE02FD8D +:102A50009EA17E2BD0EF12BE4F5463E6614AE7E69B +:102A6000C1FC1F36F5AC9937E3C893DEDBB8CE0B5B +:102A7000F1C2174CFA696834D0FFD1DC389EB94FE7 +:102A800058724B2406FAD3956FCF9FAE72E4472F4E +:102A900071942F36BE52AE38E3A8DB66211DE801E3 +:102AA0009457C51CCF7B2FA3EE7CFAE838CB48BFE8 +:102AB0003C8E407A02B87EC59C80EEBF5B6A00BF48 +:102AC00020F040798635BF60B9C2ECEE815FB9096C +:102AD000D8F9FB6B548C679A799D2E3EEE0A45C758 +:102AE0007AFB1FBA4385F65DC1220FE0EBC8E5EB28 +:102AF000BD98FFC1F3534DB9DB7AF9FA6B6E0279D9 +:102B0000982DA2EEE9C86FCD857DF9076A54CC3FB8 +:102B10000DA40DF51DA165DF134AF851FA7D7F550F +:102B2000628D356E7387C2F4D7750ADF07DA66CF18 +:102B3000DFA07C709D02F961BE46DCB714559EC7CC +:102B4000EBF0EF4D7C040E5F2716FAD9B3C80FFEE9 +:102B500028A38F38A78F3DDC3F7D04E4BF1BE886A8 +:102B6000C9FF6DDC3F75F63BBD217258013BEC1689 +:102B7000AD1C4251CEF59DD66DB7270A6376393725 +:102B8000D549F78DB9B6FA790D45B6EFFEF06C87E9 +:102B90007D92607A8DB0F5E9F2F8A681DC2EA77AF5 +:102BA00097D9199A18B1EEAB38F47A83CB68562EC0 +:102BB000C2BE09A4451A617D9CF6F456BE3E7F2331 +:102BC0001B5B94F9E8BF6D8527B58F79BEBADDFE32 +:102BD000180527A170CE1917CE872E06CE89F6D9F3 +:102BE0009CFB6B774A915D2FD1E7E274960FD9E198 +:102BF00067FE7C07C45169F9594E874F2912F67F49 +:102C000088CF77711AAD9F82BFCDF8EA73907803B1 +:102C1000F526A7CEB3040B08BFE7A5FEFE9CC2F6BF +:102C2000B3174F1D7F9CE7611CFADCE632BEAF583C +:102C3000E278ED8AF1036B39A1B0FDE79175E17996 +:102C400094A63D7687CBE8B7D64F3EED72D3DC072E +:102C5000C9E6EBE9278CFF5E58B36ECB74CACF4A46 +:102C6000BE0FED9FEC35ED9BC500E41F0D6AE00F34 +:102C700064F37D7CB29AC951735F3DB3CE2E579DEC +:102C8000E7ADDC3C2FDEED3C67C3E5AB931EC7929E +:102C9000AFBF56ECFB1A23F1EB31E8CA19BF6E82C5 +:102CA0005F999DC9EDE048FAAA3963D3E3CF9B87CA +:102CB000B70F4C4F965F82F33329E980ED27060E5C +:102CC000FFA16E7505ECDBB178DA607362F19BD31E +:102CD00093F22BB228E305887B466A3250DEAC08BB +:102CE000FD71FB00F5C7EB8DFEC56F5AE639A851A3 +:102CF00068A78DC32786EB232B7F3D2130FAE9E0BF +:102D0000E3EDE0F874DAD15D62CC0DFD7E40860C17 +:102D100021855F6B9D773BE26DC8077436D6BCC3D7 +:102D20006EC65781858D6188D3B9CF4BC807EEA990 +:102D3000A6DD1246BB659E3B839DFBF015E13E1E62 +:102D4000F5D387FB611D7C2CBFDFD48FEF9BF15443 +:102D5000AEF76ECB60E5ADCD2C7EEC3E72D96B3A12 +:102D60006DE77FD1453CF4FD162AD7210ED84DEDF5 +:102D700078F81EA8182210476FA3F5A316BFBB2D25 +:102D80005CAD819DD05E5AAEEAF4BB34A702CB7233 +:102D900061B9564DC79CEDFEDAD26C8883178B98CB +:102DA000575B4ACB2DD4A44B776B38BF9F97BCE9B8 +:102DB00003FB2C1D9CF3F9C9F57455440D89C2E33E +:102DC0000A69D5908B31A2B7399DD1F78F42BCE407 +:102DD00009215AE9A6F3FF393F7FD5A53496DC0ACD +:102DE0007E8F1C7343FCA04965FB10400FEDF392EE +:102DF000702FE1F855F8B8237E105FCF0FE4A118CB +:102E0000A4B67689A421D5FA5CED6672AE5D33B4C2 +:102E100071E949933FB2E54F2F62FCA404293DA517 +:102E2000883F3AE5357147EADDD9C97C25BAB01A41 +:102E3000F22961F69E79BEE74DC5F89C9BCEA3D5DD +:102E4000C7E5587E26D2297DBFDCFB89E43E8BCFC7 +:102E50001C5E5471AC06FC924117C68B02D3C8DFCE +:102E6000462CF2F6A81B836EF4C9ECA4FB287DC4A3 +:102E700067B2B80401BA49A38A18F6210BC4F8A3B3 +:102E800085006F6FED34DA5F973C9D5AE6C97EAAE4 +:102E90000A98FDBFBDDADB60F503DE4D63FB2F77DB +:102EA000F9AA9E86F995FAE2D5E83E4376E62476BD +:102EB0007E0AE8F8128D0C0922C8C108617A33AC89 +:102EC00032FD5AA3C179298144C9F9B4F1F4A3FDB3 +:102ED0005CD59372BCD50BF808B278977F9780C900 +:102EE00080529F91F08298F4AD6A77337D5102E36E +:102EF000F4577A898FD6FF63BF82F6619F3F4F06F2 +:102F0000BC3E2FAEFB26C49F867FE9C6FCC6BE3FF3 +:102F1000CFC6FCFB3EFF15CB406EF709E42855F603 +:102F2000A4EA6C1E4F362469B0CF17586A10D8E750 +:102F3000187E8184213FD815FAE9E237E7E1C4D34E +:102F4000C485B49D87747B68BBF047DEF79750BAA1 +:102F50007ADA57FEE0A524195731E329CBD2A20F24 +:102F600003DE3A26FD5B03F04D37855342FBD5085F +:102F700001DCE5D922C61F49B62F3E1DE265478315 +:102F800035903F5A2597616A6C60295BEF5F79A3A2 +:102F90007B61BE355A7D0DC4D72B8EEB2867978594 +:102FA000360F40B9F27556EE5018BF40BC8858E451 +:102FB0006ED5D92938BF3E4E27ED2163D010C6E526 +:102FC0001BC7B9037BBE9C950E20CFDD42075197EE +:102FD000950E16523A9863A50343B8183AF82A2A70 +:102FE000EB4FC23FC66B3542326E379A0F36AB9904 +:102FF000A5A3F9C584E3BE8ACC20C851932FB4059C +:10300000F7A25C755FAF44C05F37F9C4E48F8F3DB2 +:10301000237C12017E5FEDD3AF4AC527E08758F9C4 +:10302000E1DA31F86605191E08D2462B64124BA767 +:10303000A2E4E797BD553CC5C2074EBCAD582490ED +:10304000933679C6CA16BC6A23E71BA50BC7FFCB0C +:10305000B2DE11B4F06127F543C058EE16C304F494 +:10306000CA02DFBA3F025DCA75DF0B813FE87247D3 +:103070001A306F76C13B693752BAFCE3245187C9D5 +:1030800077E8EBBE8BFC7C228D807DB2BD723DC6A5 +:103090007DFF7853742AE8892D14FF27512FC72705 +:1030A0008B9883393499EDB7EB21F68C86D87BC2A7 +:1030B000BFC779D9E0F586B01E5D679B7CDCE16116 +:1030C000FB5D3B3C4CDF6C517A54E0B7E142554B21 +:1030D00095EF5CA9B2FA4BDCA4221CC4D1705FB995 +:1030E00043956A7B599C2FB184BE5F32ADE451EBAE +:1030F0007E81D9EEC1E63EB453B6341FC267565D39 +:103100009C40DE95B724A6C3FEB8FA97A5820BFAB9 +:103110009DCDF671E17D8BC54ED355C69FEA5FA468 +:1031200028F0B1DA1AD3332DF2581585682A7B7B43 +:10313000A787C569D45682DFD5C35FC77DEFACE2F0 +:10314000B0F06528B7F69030EDC79360EF83C58681 +:10315000F0254BBFC1BA3E9B3E5C41972ABD1CADDA +:103160002C3C17D3A17B719F6C45B0FA0FF2DCD1D8 +:10317000F4063F272D7463C26FEED7DECEFDF49ABE +:103180002215F9B4A349E9C573302AB39F3E085606 +:103190008F7BAE00F669A98587FE303C61BF36366D +:1031A00093EDD74219F66BE109FBB5F084FD5AF8AF +:1031B0000EFBB550FE4EB38165D8B78532ECDBC649 +:1031C00066B27D5A28C33E2D3C0F3537E0F3D9E671 +:1031D00046FCFE5C731396293DA0FD474A6221B070 +:1031E000ABBBEF520CC8C7E9E2EB7EC428CA027A37 +:1031F000F104593CC1F3E203782EDA131231BED741 +:10320000197A80DC409FDDF3FDDD101F51BFEBC359 +:10321000A7477E9080DDB64788359030211BD58A40 +:103220001A99DA13C5A1CDD59961C0DBE5ED909F60 +:1032300038436F09AFD39265DD5FBEFE7B96F2D453 +:10324000D25ED94BEBDFD5BDA81DE406C0019B6B58 +:103250006DEA929A96624AB445D4A001F957A8C47F +:1032600081EEBF04EB351DE06776E067485B08E25E +:103270001F5375A51CF895D64F303EB9B0FA5DAA1C +:103280008EEF9DEDC6AB27565C503D228DD31F7C43 +:1032900017C6E9A783B4698314F6AD205BC08EF22C +:1032A000B0FDE06E179313DD1EF6FC9DC7DC0FAF7B +:1032B0005EEEA1CFE51EC687DD9E482D9C4B199E74 +:1032C00023621CA8CF45BB80430A4D85AFC0F9A13E +:1032D0003B7E2213D867D8C3F976FA543FD3E7F779 +:1032E000A8A8CF974FFD767B262D4FFF56380CFAB6 +:1032F000792B097B814E62DB985C79AA625A663D24 +:10330000AD7EC9FC6732414F7DAC32BB36CEFD92FB +:10331000968E1BA742FCEA8FC7989CFC361FA7D746 +:1033200035D888EB39DF87760D752CD06E6909C9E1 +:10333000986724E6B0A7E2D2FE0AEA29D430885181 +:1033400078943F2F50314E72D6CDEFC118447B4652 +:10335000F144B50CFABE272622BFB769DE38D8DFA4 +:103360005B7DE578FE34562AE33994ADA52CCE9AE0 +:10337000E6FF7C1CEC981DFD1E261F7C2AE699C6E4 +:103380004B0F1EAD0EC253D480DFE3C6AA5AC4BB96 +:10339000266A98AF4A7FC3EF0D413CB7B295F075EE +:1033A0006910F1DC5DC7A48F7E7A29E4EF7C590BAC +:1033B000F3BB09301F1C4D3311F68D860FA7013C5E +:1033C0007F63DE6B30D49A46EBB7AFD3C2B00E73D7 +:1033D000B5EA5AC837E8D0AAD11F4A9B53A35E8FDB +:1033E0007268E4DC06DE9FD15E2A63BE117C07BEF4 +:1033F00024ED6400CECDE771599696512E801DD6EE +:103400005187E14038D760CB3F6FCFBC06CF2B4907 +:103410002B3211CE0E62A8503F5627A39ECCF3A9A3 +:1034200009B04BF2CCB82F1CC5B0C425B26EB19F09 +:10343000E7C869906DE7C72747EDE56C1E67C8765A +:103440009CFB38CBE9C58927E77CB3828F6600BC3B +:103450005970E0571F3D9F0783E5F530CF3CCD8B7A +:103460007087B4D62A905F9349630BD0DD45C3EBD8 +:1034700080736E69FB20ACFB5C5D263A1DFF523207 +:10348000DC0AFD6EE574DE5D68D7DB7B54C9E4C7FA +:1034900030F0E3D42691C42CE343BC3266196F5A52 +:1034A00077A6AD3CBD27D7567FE6AE22DBF759F1B4 +:1034B000D9B6EF97EC2BB795E7F45D6EAB7FE9A13A +:1034C0006A5BB92C718DADFEBCA3AB6CE5F9837F53 +:1034D00065ABBFE0C43ADBF7CB86D6DBBE5FF1D687 +:1034E000ADB6F295C377DBEA9B76BD532FCEE6F6F9 +:1034F000CDC5DAF36EB84FC216BFB5FB0B4E7B5F7E +:10350000FD4B9BDE0A722DA0207DCBA0C769F9D6AA +:10351000BB98BFA52E0EEB2057742E47A9185C0050 +:10352000EB561550511FC83E564FF62D43FB63CA4C +:103530002E2A8FE681554A46BEA7815C6E8E2D2EBF +:10354000B6C4A53C5A0F9EE1AA0AD4E23E88D95ED1 +:10355000D60C12F5C3783AB37BA8370BF53C3A6D1D +:103560006F99D7F3A28847A587A95FF8A8C52F1C34 +:10357000CB0F74FA7D17EAE74D118917CF1F089119 +:10358000467896361EAB86B461EAFFFDB587F2E752 +:103590007625D2D04BFBDD5EE465FBA5DCFFEB2E90 +:1035A000EC43BE182E9451BF10592FB5C6ED3AF911 +:1035B000FAA6A94FA1FF49F18EF2D6C4FB566128A5 +:1035C000DE0672E72E2FCAC329BF71BF0CFCA516F9 +:1035D000A9792A7D1F3EA218B00FF520C76B91561E +:1035E000560DA1A7E250FD6178CED0A99D419F253F +:1035F000253B0FA35AF314E178B3C3DFAB0659A2FE +:103600002E66F69F3C5789B7D27E248DC291C2FFA9 +:10361000309F526017DBE728967F07F406D6FF79C4 +:103620003A85AA4C15F3423C4007023E917E3C414C +:103630001FEA0D0F1C8285B22CC4619F10EC53D879 +:10364000AFABCADC85EB6EDAAD60CF46993FDC09E3 +:10365000780DD6D9D73B4DFD0EE2A95D60F1F1EEB4 +:103660000CFDC56A3A6E77765126C462217E526F90 +:1036700091373BB83E8D7AD9D39437B891333F69AF +:10368000EF50FADF254E03F87A08C82DCFBD3D0470 +:10369000E8DDA3D1D544BB3EA647509F327BF73629 +:1036A0000E534DD11ACC03783F588EF6ADA7E9F9E9 +:1036B00094F8F30C49C49837365E033376A3BE27DB +:1036C000458A0E764593AE18BD29E4C15C95FB3959 +:1036D00053CC73AF2C0FA89BE3C38C9B8EC4237970 +:1036E000DCCD8C479AFDDC965D3E793C7BDC43FD6E +:1036F000D0A805DE2D741CC04BC7B9FA5AC4834C40 +:10370000D8B9DD3F97F6DE87FBB16D3AEC37CFE5F0 +:10371000F67225E087E27B8A42D04F580AF1952C59 +:10372000F07E3F530B7C69C663863CEC1C773846C1 +:1037300024167F73997A4B3C7F29C2AC2B661E19E5 +:103740009ABC4CAFD17FFBE17CD9B46EFBF9CDE9DB +:103750003DF6F2CC5DF6F2ACB8BD4CADE6E36017D9 +:10376000808D86F18D7DF6EFF5E6BE410D3B6FA6AF +:10377000D291CF33FD6BBB3F8770FD6FE6BB15F475 +:1037800025AA40BCE6DF6ED7ABB95CCFE73AF46759 +:10379000B95FC2B843D5D1E000D88F667CE8575EE8 +:1037A000DD967766C6799CF2DCFBFA4E42BFA0FF3D +:1037B0001E75B37807C4913F2CE071957C1E579914 +:1037C000C2E32A052CAEE292F497D60A9827FA3E75 +:1037D000F20569BC94C573D8B9AFF76AE517049DC3 +:1037E0008D17B58C7767496C3943433C07EA99F1EB +:1037F00015337E10F01BCB817FB7865F6E3C42E9AC +:10380000A4FA976E02FD5C25BD78B419E45B818C47 +:10381000F9DDDA825BBEE98578257CA7E5EA427DA1 +:1038200032F2C18F5D1847E8E2746D9E5734E33180 +:103830009A97F181CF6BDA47312FCFDFF782BD7BCB +:10384000C93E2AA36DFA8EC5FDCCF8DE9C3EFBF77F +:103850003E226469901FB0262E32FBCAF05559F201 +:103860001F67F3759BBB36F1C05A5A3E40E2E570C4 +:103870002F5D19A78FF080FD9CEC2422E039A94927 +:10388000C7A5709CD69FFB9CFD7BA9E31CED6CE754 +:10389000B95AC7FE915F22A7AFA7E36DD31B05906E +:1038A000A3DBD6525B9E966779F9BEFD0C3203E826 +:1038B000F02AC9174E007E5F95701FCCFDC6CCD78D +:1038C000AE07BD7E8CE52769D3F49D106FD67E2AA6 +:1038D000A19ED2D24859992FB9DFF40FE7C304F65D +:1038E0004FCCF8D793745D41AF1CA07E79B10BFC2F +:1038F0006C0DCB7DD42F87F2D3D42F87E741EA9785 +:10390000C3FB7FA67E39940F51BF1C9ECF52BF1CB4 +:10391000DE3F47FD7228DFE5ABC278F920AD0FF43A +:10392000E22D3BA84EAB0039ECD2803E9C72A8AA97 +:10393000EA36753525A92F743D85FB1CD557B17C1A +:10394000EAE5F73D85FB1CD6389C354E998CC30DB6 +:1039500009661C0E42A3BFE6FB1123F1B8288BC7F2 +:103960004DDC8F61F683F1CF51FDF038E8BB77FD78 +:10397000DBE36DF4D386F90F747B8BE07C47238FF8 +:10398000FB99F933BA2D3F7FC3C116CC9F51728E7C +:1039900037C2BA1EACF0615E89E28A6A206F9DFE72 +:1039A0009CE9C739ED69F3E9D46F7E6E5798F1D57C +:1039B000ED2E82F9D43181DA13605F34C717BFE985 +:1039C0001A3BEE7AC25BC4F3F8EC7261E41C018F1F +:1039D000FBB8C19AA5F354048E0F9EDF8EA2B18866 +:1039E000C5FFACF1576F711C0FAF7B7D06DA750216 +:1039F000B5F7D0FED3A22188A375C2B98114F3DB39 +:103A0000CBF9BD2547417BA33387E58BD4E48743BE +:103A1000D0BE2DA732643D47609E7318F057AA436D +:103A200096FE6EF5178DABFF24AAAFF571F4B5E4E1 +:103A300066E77CDA0E5FA6C2F98D6EDFBA41F0A3AD +:103A4000BB43418CD3F7E75492214BFF5268219E30 +:103A5000F3907CCC1E96422ADAC332CCBF3459DFB5 +:103A6000ACD7C2E53E65678C2F7A7C3D58CF2D4799 +:103A7000F07E09771054267D6A6CDFCE5B2C12D560 +:103A8000222FCC71EFF63279D95D1AD520CED21D16 +:103A90009275382FD2AD97239EDB389EDB0A4C7B84 +:103AA000228C76CCF7B97C35FB69E37180B60605CC +:103AB000EDB948538656938579BDDF017EEEF6B5A4 +:103AC000AAB07FA9E4548CDBEFC084FD964DAA997F +:103AD00087FD7E1FFA55FCEB34E8D735C6F9A463A1 +:103AE0009C1E3EA9DDEADCEFA3D086AC792BCEA7E5 +:103AF0009FDB9FCE761B4A871458F72D8FD9CF3383 +:103B0000BB083BDFB5F1D066E4F3EDF220DA51DB20 +:103B1000CF0929CF8985D204CE6F23FEBDCD0ECA31 +:103B2000E3FC94C7BF03A981BE284BD8ED96794723 +:103B3000EDE5F983F6F282134E3BC87815ECA0D57B +:103B40005CEE0D5279CF92668665C0472416AF02AF +:103B5000B8EB495F0BE453B8249617B29AEBBF95C4 +:103B60005C3F06D23210FEBC06AFCDFF24FC3EC047 +:103B70007CDE7F41CDC0E67610B211D3AED2D16FDC +:103B80002DB8FAE92A14970EFBAADEB09FF75FE979 +:103B9000B09F9C765695DC8B79BBB98EB886B9EF11 +:103BA0000BF3847B0F9CE35FECB8667F90AF05F26C +:103BB000CDBC0F06EF1FA6ED0BE48410A678CA6DEE +:103BC00064E775F26E27466F0A3A5EC2D77D14DE4F +:103BD000624B106F4BF9BB5C1FBBC72BB7468AEB20 +:103BE00074FCDC863EB40756DD42E78376F879CC78 +:103BF0009731EB6766F4E1B9A5DD7502CFE325687F +:103C0000D798EBBCDBC7CE19D65F29C44568DF580F +:103C100084E3235C45C9F5A5783AC9F0C4F212AF34 +:103C2000ADB59F87AC77D82F263DAC74BC3FE96516 +:103C3000FBE7261FBC7BD9891953281C1B849EDAFD +:103C4000B46917AE2F2DFCE13A0F7C08BF4F6229F3 +:103C50003298EFABFE9386E74232861E269424AF5D +:103C60004D23B19A4584FC8B77F8128196FF6A6BDD +:103C70005F4777011CF31E7E0A8C3C77D73357D5FC +:103C80005E992C7BEFEBC772908F035B906CBD2D20 +:103C9000F7C350D4C5D3187C5B0DB253821C5C5162 +:103CA000DB192E4CB6CB8476C238ED2264A79CA2D9 +:103CB0009DCF6C47D1D509F73FF17979F97791C359 +:103CC000631D5F06BC69BA0FCF3B2E9335D8BFFA90 +:103CD000B4704C9A68DE51B2D3356D743B0A768B62 +:103CE00009BF981AFE387CB78EEF1A07FEFF6E7C6C +:103CF0004CD49FC2BF5F347CB47AEBA4B1E70B70A5 +:103D0000B9F05E22DD275AFAD9D1FF278C8BCBD7A9 +:103D1000913084BC6497A1C17E5EA9F610FAF77257 +:103D2000468D0676C0165A063B604B5F0FC6BF4BEA +:103D30008B1FE806A22F4D7809C8833944CB384041 +:103D4000FB9DA3C970028BC8570E88104F279F2573 +:103D5000985F92DEEF65F708155EFE2DF0B7323200 +:103D600054DCCF48CBA8FC16337A599CD9843FAD9C +:103D7000EA7835C4DFE57A1216002E214EAA80C9F2 +:103D80006611DCDFF01A07EF84F3024466FA09EFEC +:103D9000D201BDCAE3ED9319C9906E45ABC73C97FC +:103DA0009FC818C79A0C578551A22C2DCDDC09F05D +:103DB0009446690702C0CFE26573A2623841FB2FC7 +:103DC0003FCDDA919FB17326D43759F38C2F8957A1 +:103DD00053AE4CE671F8D05A7B9C9A0CD339D3F68B +:103DE000E53F5BB517E2149346C96FE6B77B399C94 +:103DF000E9A74904FA0FD6D9F58697E7797B1DF72D +:103E0000CC54F85DF6FBA19DFEC35723A807DC2424 +:103E1000AC2A685FAC45BBC1F44B764345B0C70BD9 +:103E200008BB97D7D9BE92B52721E6A7B8BD4455A0 +:103E3000CBE9F7F55E03F312DDB44CF1282844CD4D +:103E4000A1EF7345166F6911880CE5E47809CC473A +:103E500070AB9F6907FBE5B03A0FEF4F33FDEA36D1 +:103E60002D8CF912A4A4DA66379B7961B796154DAB +:103E700086EFE99346E24E1AD0E5ADD9C56847070B +:103E8000B286FE1AE4ECB9ADE9CB5490AB90AF71B9 +:103E900039E4477B3B6354E9BBCFE611DD629FB950 +:103EA000E5468CB3B9CF4EB1BD4F34DBCF5B1B3E83 +:103EB000B106C699EA637C5845B476685745ECE785 +:103EC000AADD67736CF67AB2FF7CDBFB04B56BACE2 +:103ED000F7008DDD7F1AD14BACFD4F1BA3FF198E70 +:103EE000FEB594FD27FBCDB2F5DB21B3F86B2CE8D2 +:103EF0004D792FE5025F75311C951D6B7FA0D2C7F0 +:103F0000E29A5DA146DC1FA82694F129BD2C3977E1 +:103F10005262E77D09DA6F24DFBE3F50CDE958A435 +:103F20009481E70764FBFDC68B89F3BE63BB5DF438 +:103F30004B8839507C89FE8A41DC27F8930FCF03E8 +:103F40008E65370F36138C4F2F4E1BBA0DF6C157A7 +:103F50006ED3958E10E63DA33FFF37DBE62F033B84 +:103F6000DFBC07B32328225E22D593F13C97D94FBB +:103F70004421D3412E46449607813F74FCC1EC5C3A +:103F80005BBE86F9749E87AF3784C5C596790D42AE +:103F9000FEA175BCA579BD92651E1137998FE3719D +:103FA0007B7764BC499F6CBC633C9E658E57BFCCDD +:103FB0003EBF7A45C3F9D5733E36C73B06F34B8106 +:103FC000DF09C7E3F99523E32DB7CFAFDEADE1FC01 +:103FD000EAF97DBC23E34DFA64E399719D2EA5B106 +:103FE00011E870ACF88E19D7B9B66BBF2DAE43622D +:103FF000FB97561513B25360F223EEABEE04BA787A +:10400000BFEED612D42BDCBEC67B57A93E5E293349 +:104010007857E4FBE22D163CEEA672C49809E72916 +:10402000540207CFE07C8581E72D42F87C94DAEBDF +:1040300006E69794E0F7C79BC358DED7BC109F668F +:104040003F250BD9FD60B3160929EDF6133EE67F37 +:10405000EECCD1AEFB12E8B72A2FCB0B5E78053140 +:104060002C763435AC0F7B607FE8F3A40C74E48CC1 +:104070005D0CEE60CDA438ACBFB76C60B019E2A0A7 +:10408000B24BC7BC583DF5DF3B78C5C7FC79B79B41 +:10409000B52757B07B525770FD44A43ACC3F5AB174 +:1040A0003203F31156AD36FC1AC5DB6A4178B59878 +:1040B000EB3B381FF539BED44E7F21089A87AE57A7 +:1040C000D090E2708FDCE7F25F5C23D07E23FE6B42 +:1040D000D1CF88D08699B49FCF717D5BF5869B4008 +:1040E0003C825CA5A0FC5ABDDAEE17ECF42434B097 +:1040F00073769605490B6DB7AACEFEDDED667C158D +:1041000071DC13B362827B63CCBC5C277E9C71D371 +:104110009FF9ECF1D133A474079E0DE3F9BBCEF601 +:10412000661CB4DDC7E45B97C2E4C3683E60F0BCC4 +:104130000B7DA3FF7702E368267CB9725C00799F50 +:10414000D770C2961F4F118B46B5B94F40A4036577 +:10415000A8871DF3D92D1CC819EFDEA85C22FF6EBD +:10416000A884FF7D0361F4BCDF1935EF452F15935B +:1041700054FCC3E2C12B8E4AE1163D8917130FFF91 +:10418000DB7CB4CBC7F0F9D2D20F2A981F986FFB13 +:104190003B02E639AF6B47CA32912DF4BC72BD6267 +:1041A000307F75B814E8F2F8956961F6F730B81DFC +:1041B00094F8A50876D0A7EFDF28B0E53FF37EC7D7 +:1041C0005A2F67DEA5E55C72F29E04C87F690987F5 +:1041D000D01EC81609F0532EE4E305D8F79376BB3A +:1041E000D5968FD7D6BF5F80B8E1C3909F68398FCF +:1041F00097D7D02774807DD71267718804AD47E1C7 +:10420000CE6F4808EDA5C9BC2FA75CCFBFC59E2FB8 +:10421000D8B168B5764087BC9AEA1EB8206CCB2E20 +:1042200016E732EB8FC4BBF83955176924704E433B +:10423000F2B1787388DFDF31519EEF87624C2B2C0F +:1042400084FCDEB85A45E7BF272BBACC4FFBED0EF6 +:104250009637F6027DCA61CC075FDB744F04E284B7 +:104260005A56EA38F85A6E1FD4FB195DBDEE4A144F +:1042700040DCFCE5ACEA7A7F768AFA4D5FC5FE1633 +:104280008F712FFD7A3F8BCF3C2CA6960737F0EF2E +:104290005FD820E27D431EE2C773AC9EE29E85801C +:1042A0008F8737EE0EA73A8FB9508BAEF35BF0EEE7 +:1042B0002966F70510D27719CC73CBC78FF47D9799 +:1042C000CE3BF3631FCAD94C89F56B69BFDE3A1F39 +:1042D000B3FDF37FFA059EB37F9EDFBF4EC8F4E5C2 +:1042E0001067DF3E52263138E8BC3D839763E272A7 +:1042F000F02B93E5E796554119689412DFBBFE97C2 +:104300003AE1FE9AED02E1C43AB80CEBF3FBDE7F32 +:10431000C2BF2FBEE69D6FED007D50A9A0BFB99D25 +:10432000DB3B267CFFE967793FFFC9D7652C7C6EB4 +:10433000E3DF7D80CFE045E1735B2A7C7E26686CFD +:1043400087F71EC804A120783E566F87BCECAF37B4 +:1043500093C897E81C1E0E1FDC0F678F68FB8752FF +:10436000B5FF4196F1353FC27312E7E72FF685019D +:10437000155B1610EC27051CDF186F5DCB33989C7E +:104380004B4B67CF4C6E5F4AEEC110E42F6815FFB0 +:10439000709B46E54C67E1E09A5471E2A702CCEECF +:1043A000CF18232E7E98E3EFEACCC8B701EE76ED66 +:1043B00001F4F7148144A0FE96854344B0B47B23F6 +:1043C000C0E897C2FD0CC0AD5CC6EEB1F653BC436D +:1043D000829CBF82C1BF453F4E204FDE1F3A8E797F +:1043E000ADFE8A21E4771485B98CAEC01F54B9FDA7 +:1043F00076D8FF26DAF5999249777774011D4AC974 +:1044000032D2656F266BFFFBC01D5DE02FEE516859 +:104410001B9083B90ADA37CEF9FD2CC0E6A768C62F +:10442000518077143EDD43DF827B09B64F67F7B9D1 +:104430002C1607D7DC0074798D0FED33FA7E8DF5DD +:104440005CFE479C7F3FF233FB6AFB9F54FCEE5CB3 +:104450008FB1E8F5246FFF09E8F5642AFEA5F4FAA8 +:104460005B786FA1D70F486A7A7D7B0C7AFD0F6865 +:10447000EFC48BB32C116317EC2BCB1F2DDB07FD87 +:10448000C99F59B4EBBBF4297DB42D86AB19166CCA +:10449000E79E93F23EFA2718D7BC7FC0FC3B46CD7F +:1044A0004008F353F4BBA07217C8B10BE8570E6471 +:1044B0008FEEF7653F8377F135BE68AAFB14BE1314 +:1044C00090D9F9D800AB3716DFFC3AC0F253C6E2F8 +:1044D0009B17381F50BE0906E64FCC3767927C9376 +:1044E0001FB820BE79089F9E62C63738FFCB47F3BE +:1044F0000D89ADEB02F9DA59C8F862CEFD9B902F19 +:1045000046F82816C3EF52B28CF2DBE4A38FEF8F8C +:10451000617D67FBC018F70656707E5AA845E60114 +:10452000FE8D4BB476768E6908CFEBF692E17E373E +:10453000E609B3BC5C6F2C6630F36090C0FDB48BB1 +:10454000381EF6808F067E50258F67C98364957F5D +:10455000343FFB2B1215D67B605EE1E3FBD2234B8D +:10456000018FBD646816D86763AD532D1F4FC832E5 +:104570006A0329F87F223DB421C0F4D0063E6EE6DE +:10458000C76A23D8A74E7E5FBCF1D93F3C3E4E3F61 +:10459000EB391CEB029F585FAD0BA4D6573704ECE8 +:1045A000FAAA42284AC9FFEB0329E407E5FF9B5317 +:1045B000E1E553F0FB9D8114FC1E095C18BE9FE5EC +:1045C000F87EF653E27B176FDF13F8C4F2B62715B7 +:1045D000BE28BE7706B22F08DFBB52AD17C5F7D78E +:1045E00003B8FE4F23FC7EDD87F1F2EE05E420F4F4 +:1045F00093028E5E6B3FAACEFAA13CF58140E97E24 +:10460000F147DDE154F724D176FB52B5AB0D683CA0 +:104610000EAD6F06FFE1E1CFF8705F81EAC703815D +:10462000FF5EB97F28151D2C16991CF206167581A0 +:10463000BEFF14FD0FA492FF5FE57436915DF01A82 +:10464000A70B3AEF9F029C4EF9D7CBCF312B5AF4F0 +:10465000E500E26BE86A90577BEECE1420DE956FA2 +:104660002404F0138E723D560597FDCC4FB6DB2324 +:104670002704B867674FA326C079294B7FAF07B2DD +:10468000C7EECF090785EF3730BE2FDD188276B52C +:104690007C7E176B271DC934DE0AA0FE89BC0D4F36 +:1046A00063A65D6E9BF310233D2CCF7661EABF734A +:1046B00079D42F9BF2FF7DABFCFF8F11BA62FD5DB9 +:1046C000ACFEA1F09DE3F0FD25157C4EBC4C04E74B +:1046D000250199EBDB889A9E424F39FB33FDEC9123 +:1046E00075029D6489FB64A78FE8EF603AAC478749 +:1046F00088E7A8567079B2626106B7DB352FF4FF00 +:10470000308FC33F7CCB0355B0AFDE7BAF5606285E +:10471000C86D607A4FBF650AC657A7F27E9DF08FBD +:10472000B457FA66C1DF8FA0E34E83792C59441247 +:10473000E037A683DD80F10A0DFFCE71A6BB27040A +:10474000F1D92D42CF9A75A057AFF6B17331A1D5EB +:1047500013DC9FD96AA35B12AA98A07E0BD6D7D28E +:104760007AF09E950BAEEFEE496967D5A48B9C9EBF +:10477000A24BC6C56B2888712F13BFA3C761EB5727 +:1047800015691400DFFE0A4183D43B3FA513B0979F +:10479000C4E241CC9BFA6C05A31742FD92F1EF698C +:1047A000E934E15A0578FFB47099F5C61E8FD773C6 +:1047B0009CB718F97B643E26C7B0222DBF77342BF7 +:1047C000E5BE82F9EC6AD60CB832F93D4DC7FB1B49 +:1047D000BB46F2BEC3A155FEFFF97AC979C5597C23 +:1047E000D4517FE49E92908AF61FFE9D0FEB7D3D93 +:1047F0009C2ED48C482C1DE54A18EF89A4E5565808 +:104800000FA2D2B21FCBED58D646CA9D583FC4EA7C +:10481000134DBB20BCD376DBB11F79A49F1DD88F6D +:104820006F64DC9D580E8E941FC4FAF9ACFE858E21 +:1048300033EA9E964109E7FF816CA4C3BEE9E79B7A +:104840006EC0F8D2754D37E1B3BB59AB82389D7954 +:104850005FC9E7AFBB41037FFABA2F3F88FBFA6617 +:10486000FF2BC1EF00FED7E55AB097944231F29882 +:104870002FC97F4938DAB1BC4266F7FEAF5C787A5F +:104880007BBB257EA7C2DF4F87FC1ADD725F06491E +:10489000CAC32704E37BE91741CFA3E749C800A5B2 +:1048A000DF0F7CC5F118D273B5968A6FCCF98ED51F +:1048B000BF39DFB1E48D8937F3FD9662FEF7761DCF +:1048C000F14BCFF41ACCFF59297038FDFCFE485E3D +:1048D0006F051DE7E952A40B1DE87605F7EF9CFA7A +:1048E000C11CF709217A02E804E2C4F7968FC6EFEB +:1048F00085E2CDEC7F723446E0FE2E6F29C17DB19A +:10490000A0DFDC576772ED219F598E617249A4B810 +:1049100007E59C4737E51ED3935A5A9F2196513F8E +:10492000A887D48666411E6834047FEA87968FCABA +:10493000684FB0321DFEE800DA3FDA6CB8F1516D15 +:104940003FF7A3A35712767411F7DDCEFD08F5B734 +:1049500059860B7C4B68D93B5236D4102D178D9459 +:104960006350DEC3ED3EA1E7DC8F60CF84EAE573E0 +:1049700056795FC5E5EA44F2F4BF00B9E905CA001B +:10498000800000001F8B080000000000000BE57D88 +:104990000B7854D5B5F03E73E695642699BC270490 +:1049A000C8090F098A38090482623BE1D558790C9D +:1049B00015359628938447782620D5B1D2322180A8 +:1049C000A0D886AA156BC509C57B69AFB6A0B4E5AA +:1049D0007AD17F10B4D0521A2B55B4A25150F15154 +:1049E000938294A9D572D75A7BEFCC39273321B45F +:1049F000DEFFEFFF5DF874B3CFD967EFBD1E7BAD6F +:104A0000B5D75A7B0F6361C6721963DE1CC6C63107 +:104A1000761EFF7CB967C944BB366DAD67C268A816 +:104A200079ADBEA11A631BF15541BC5D89C74EED3E +:104A30001ECD0CA67BCA199BBEAACBEA8476CEE219 +:104A40001C77D0C55891F79370257C5F349E310D4B +:104A5000BF1D9245E3B679572A769842DB08E651A6 +:104A600018BD5BE381F6396EC6DAA164D60863230C +:104A700018BBDF25EB301F28032511D601CF533596 +:104A8000FEDE827578AE3A58D34EA8A795307F04E3 +:104A9000EA1E079B1380B2D863610CE6E5F3A834E5 +:104AA0004F1F8E06F50CEF5AA6417B6795C51F81F7 +:104AB00032034B971EFEB5E23B2B95121FD7E6043F +:104AC00047209C6D8C55EDC479B168A004E0481D69 +:104AD0009E937537D42A4BAC2B190CF9E86A1698BB +:104AE0006B63ACC21348C3F6AED29CD4E008AA8F65 +:104AF000F2403FAE75963003BC54327744298EE3C2 +:104B000005669E1A7027A7C7CBAB838149B6E474AC +:104B1000BBE12635A087439653100FF0FDC7D5EFB4 +:104B20007C1FC159EAECB2B34140CF219B034C45F5 +:104B3000783482D3B97B66B410DE2FDBB39CE17C82 +:104B4000D7A4A58F473A9AC77DF9B3073D01789F4F +:104B5000F25747606782F196083C1F5D5D4DDF416B +:104B6000F79A358FB13908CA204604ED7062C994AE +:104B7000F30E02EFE810787F0BE3CC302B503B8D27 +:104B8000015EEBAA55A616E377DDEDD979A8DFD251 +:104B9000513B958D844AC876129F3BE1EF79E83707 +:104BA000C832A778E0716D983FA7F6F0DF3CE69B2E +:104BB000920BDFD56F303D7FFD9AF7593ABEB79E15 +:104BC000EC2889F77F63756D6092687786FE1F21F8 +:104BD000786669CC8F749BE54B8B8401C4EB0337FB +:104BE000052695C4FB7BE573750EE2C58C8FFF44EB +:104BF0007CE4223E028149437BE2A32EA0D83DDA29 +:104C000085F1D2573CD45A4BA7E46A3DF160861F28 +:104C100030762FE2791EE0F9EEE2E4F88076448FF8 +:104C2000576E827600CA1475AACD0278A89FA93063 +:104C30008742F84D6783B19D7FEA64DD7CCD78348F +:104C4000E3ABFE19E68B42BFF50FB87DC0E1ECF790 +:104C5000123F5140DA189027BCA91ECEB771FE1E34 +:104C6000F88B707EADA2F4F91C984770ADE2631C1E +:104C7000DEB7F5F0D5B140465421B8DF4E42F7B764 +:104C8000F5709AE7679E7F0A0A2B907FA1D78BBFAA +:104C90007340D78E59A323029733F6538F3BE7DD3A +:104CA000CBA03E92F9CEC3BA3ACBC6678CC2F743CB +:104CB00012CBDB73ABB5EF1CB0E9D739E7B339A141 +:104CC00099DDE362FF0A0B76D73D80E7C04DEABD70 +:104CD000D7C3BF5F3E98BD0E9FADF0AADAC96CC4C2 +:104CE00017C04BF4F23326F98B6119DEA702FE667A +:104CF00032A7E6827EBE0C42EA3CC032DD9FA2B9FA +:104D000074709C6E55AA508E02F132665D1E87D774 +:104D10003CEF155E3B8D07FCF8899E1FCD7879B975 +:104D20007A7006CA9117112F69849791178397AFEC +:104D3000E0628675E3C9665105E8DCA53823DB60CF +:104D40004E35A13B039346215E58D80EA2F35D4F2A +:104D5000B190D31C6E1B937F9A18CAD31A3B0B22B7 +:104D60005CAFDB58F52E1796D101653AB9F57E7622 +:104D7000E5BB28A765BD26F46DEA1F1891F850F22F +:104D8000F32D4E5754E57CF85137DF903CABF120C2 +:104D9000DD814EEC3CC0A9662CD1106E352D7D24F2 +:104DA000CB606C033601389D9981D328FFD5B4813F +:104DB00011E4BFD49B7EB481D3F1BEAA1B74744CA2 +:104DC00099F754983AD7B20CF84F13F4AB14F44B4C +:104DD00029719AE9C7709D864B58E43145A000EAD5 +:104DE000A787F823B86E93E90D49CF9412EBA71D5E +:104DF0007ABE66AD8457494776607417AED7A0D7A0 +:104E0000CAEEA6F725849FA047E2A7CB86FA644E98 +:104E1000C8765ADF4FB0606EA419BFDBE8F0E1B38B +:104E20003A8B9687ED004F1ED4E3ACC4E7C3F5C3BD +:104E3000C2F09DE427C42B1A13BAFE3B00868232CF +:104E4000EC0FA4277EB74137CEA09EE376AF2B733D +:104E5000BFA6EF5415EC07B2237C3E9F4E7E0FCECB +:104E6000E4F6C369EFE89D9641C9F157E7CCF65BDC +:104E7000B3E3F5B70B9CD591047A40F627F5799604 +:104E80001AF45A10B6F063070FF4473DECB9142436 +:104E900019BBC71639787000431661AC1FFE2F721C +:104EA000D0EF22BB43D4813161FE6DA9DD75BFD344 +:104EB0000BF541DDF530D6B7C270EC4AB05B32235A +:104EC00007D7C27CCE1D7790FE3A5D951AC1C59377 +:104ED0001D9AC84EC0BCAD60E66400AB4111C6D29D +:104EE000192A2478142B600EF09DADF914C4F7AC88 +:104EF0004C8DE66FD558D40D93CBB6FA14C4D7F7C2 +:104F0000ECAC41C88DE13375F6CB2C01AF1CC7E189 +:104F100064E194B278BF606135A31EB14E65A457B9 +:104F2000609D93DD26D7B7EC2798C9F567F7FABCE3 +:104F3000F07A0E662658CF872D4D6F7E0BEDD95F28 +:104F4000ABEC3100E566EF1DF4FC86503D953785EE +:104F50001652B9488CF70E0B2ECA84B2BDFAA59B27 +:104F60006F07FE6DDCEDF0A15A5E7ADBFBDF29D71F +:104F7000104F4077FC6E5EFD03E5F0DE3ED442F656 +:104F8000EC8601AC1AF9C9DEAC907DB451B357ED93 +:104F900086F2A18CCA2D993A381ECA98447556A536 +:104FA0005990CF5738399F9F3B7E97B70EED4A9760 +:104FB0008BD68BBDB9F8BB16A8B343306F86F2838E +:104FC000919DA13A78797726B753EF16F85E93C989 +:104FD000ED3D670C89CCF9BA09C6775AC30CED6C64 +:104FE00067CC4ACFED0ACC2F019FCAFE9C3158A452 +:104FF000A3703CF3F7767A8E70E1F76A3633D83DCA +:10500000F7E1F7B958CA79A4F179649BFB49E7CF76 +:10501000C5FA33CFE34F9E890F227E1ECAF06FC9B7 +:10502000A475D36143797E8BEBD7C794917D91C7EB +:105030001D0ACAE3E99F29D122C05F4AA51A595324 +:105040008C7ACD336D34F001ABB4F9109FED43721F +:10505000DC8374E3FF44D0FF45ABC78DF30C4C06F3 +:10506000BB9AF89BE5CEC27E26D78FE1F20F0C2EBD +:105070009D9E7D51DBBE6110CADFB08DF64B739CE7 +:10508000E108CE4F67B729E7B95CD6AC63E2F6DF3B +:105090009C49AA3F25BDA77D07DB900364FF4959C2 +:1050A0001E863A7CF786A8BE39E9CCF5084607F398 +:1050B000D807E9ED41DC2D8D41FB86FF991332DAEB +:1050C0007D66BBB0AEA2F4052003E02552351AF987 +:1050D0006CB885F8ACAFF632639B399D27B7787012 +:1050E0005FF528CA09A84F9F746212CA8D19605AC9 +:1050F00061BF3326A99E28B4DE14B2303F4CFC8831 +:105100005F8D2800DB91928E435F46BC55D834D228 +:105110005B25ECDEEB72F0FD280FE23920EC106825 +:10512000CFF59BD719190ACFDAFD275CF53ABE3BBC +:1051300052716238EE5740EE3524E227C69A89AFA5 +:105140000F7C3395FA79F37E25E280F94F563FFBC9 +:10515000ED58B467BF65F3393402CB82749DEA63BE +:1051600062E3EA774DD6D9012758600CD995A5C7D7 +:105170002B1D68BFAE53689D4AFCCF0919EDCD6069 +:1051800013D8655A4FFB143AB3233FF7D53E35DBAE +:10519000579F650A7BB38C95E9EDAA647A4ADA5584 +:1051A00056E657B3F87AB2A2DE9D0E0F12C9819A65 +:1051B0000CBE0E26AB1F117D4E57A81AE2EB48E835 +:1051C0000317EEC78F7CA6F27DB03FD760C715648A +:1051D00071BFC0563B1864F0DDD67ECE483374B53F +:1051E000EF9B97E677107DB407C7231D7F6D2339AA +:1051F0009C6CBEEE90CA8600634E0B29544AFA1589 +:1052000085529855A71F8A58E2F95F9AC5F7A1B948 +:10521000AB9845837133C3CC9F687F2CDBC1BE78CC +:105220008A9551FB6826CC6FD9100BF1A7DC1FA71C +:10523000D8C2FE4280DFB6777918F7C945303F9C67 +:105240008706F3437D591C4AA3FAA0503695834341 +:1052500099540E0915D2FBA1A1C1545E122AA6E7EA +:10526000C3429751BD24348ACAE1A1522A2F0D5D51 +:1052700045E565A037B1DD885025959787AEA5E750 +:105280002343D7517945682695BED06C7A5F1AAA18 +:10529000A7B22C544BCF478516537D74E856AA9776 +:1052A000879653392674279563432D5456849AA9BB +:1052B000DDB8D03D54BF32741F9557853653393E03 +:1052C000F430BD97764BAA588FF768733DE8EF002E +:1052D0000ED7908F93ADBB85595C0FBC98E99F8921 +:1052E0007C27DBD92DA0C75D3DDBCD136526D235EC +:1052F000417FC12CCE971FFBDEFEFE3016A7DB469A +:105300006FEFFE0C56D237BF57208BCBAFADD676A2 +:10531000BF8AFCDBC47C6178346DF48B0ACA973693 +:10532000CD5A95C8BE7B28CB46E33E9A196CCA82FB +:10533000EFD38A4F1E40793223ECF9ED04E4971144 +:1053400039BF9E00FD15ADB5D0765F639E7DE85FE9 +:10535000D32631928BD2AF04769D419F6ECE92764A +:10536000E3CE8383683D0D29E3FAA7E31A5C5FF679 +:105370006F0EA2FDFB567B54B1A27DB38231BDFD01 +:10538000BF757DDDBFE1FB787F7C7D166D60CFA1B1 +:10539000895DDCAA4D488172F016FF7329F0C9D0EF +:1053A0004870422AD487ED083F87E5F09D9109694E +:1053B000505EB627FA1C6EE32E8F764C7041FD8A44 +:1053C000836C3F2EFFD2766DA21BEAA38EF9F70302 +:1053D0001BB0F28EE0C4740DE713694987F96C7D48 +:1053E000030C3DA8577CD4AAC276284E7FB0E3D0E8 +:1053F0007E9374718F6E9F940DFFECBFD253AAE21F +:10540000F7D68E94CC113DE9D38670239CA0471E1D +:1054100003B8FAFBA38A47C727CF08FE003AB42196 +:105420001DA45FB26D6D16F925DB523D953864D72A +:1054300064E6D9A6211F5B094FF67583C81F27F9BB +:105440000EF06BB067370B39B1B5DBDE4D8CDF6723 +:1054500010BFE5FF3AF89D9AC5D74332FC3A915701 +:10546000C65D781D1F117C08EBF8D788D764EDCE98 +:1054700008FC9BF1DC6661074157C1B8C0A77C5DA1 +:1054800031F4A37D2CD6FB85F07AEA5F0CAFCF0B0D +:1054900039910CAF4CCB213909FC3A1CFD63C9E4AE +:1054A0008D5DEC67CCEF3F17FCA69373DC6FEB01CF +:1054B000393738B99C3B7421F925E48CDDE4DF49A8 +:1054C000CDE6E3557802CEECF2047E6A1137907E89 +:1054D000EAA9AAA712E50D1BC6C88E4E1B1109E347 +:1054E0003EA528AC95A9D80C8532E2B15F09F91F19 +:1054F0008AC1CEB002FDA1AB28964ECD63A943FF71 +:10550000BB5C6F9E5AAF7EBD497D1F5F8F922FB2ED +:10551000DAEEE67E496D26D82FD764737E8BF7C30B +:10552000FD20EBEFE8D776B74E0EB679BD5497ED78 +:1055300093F1EF02F1BE6DED1AC2A7737C62BB61FD +:1055400062B62AE441971FF93CFC25E6417B2673AD +:10555000EDDB249F32413E29249FF8F8FD43A9FF4B +:105560001686FA84EC3C21CF3DA937B8FFDFF173F2 +:105570003EDA54A807C67BF6A918A7013DA4E13A74 +:105580001D0F731F8DF8B213DD35C6E9A88D6711A5 +:10559000B47B016F51DCB7872D6EF233D9EDAD7E50 +:1055A0005CCFCC9E49F057788233B37B91379E34E1 +:1055B000AD14895A97BDEB1A17F0DFFA624F2AD65D +:1055C000E7407D53058C9BD5C1447DA36BDC3FEE4A +:1055D000F7A8BBEF6787D0EFB13FCB1FCCE67C5D70 +:1055E00087A57F98C74AFEEA3EC6C1E4FA8CAF277A +:1055F0004FA95C4FB523481E2EC17E657FC9EC9B29 +:105600004BB2B99CFB56B6C5C0D73DC76D36AFFB94 +:10561000BED93762BE8BB37B5FFF2F1FBC6FCB76CB +:10562000A6F337F6FB7EBB55437F06F7D3589CEDB8 +:10563000D49F5BF81BFDE86F043E700EE175FC9390 +:10564000C85F9C1C8F119AAFF4334A7F62BAE02B7B +:10565000665522A8C7D32B3CD63AEAAF837D0DFA14 +:10566000FB81C0935CD728B79E1C817229CB8AFB33 +:1056700075F427B9B3E2FD633DA32C2E9F98D8C7DC +:10568000DD2AE6DCBAC697812EE7F011EE4769FD08 +:10569000365F97D3FAB3C81A94137EA679A07D0A11 +:1056A000937FFC067FF2D44F15E687F91FFE54A5C1 +:1056B0005219C2A26ED8EF4DF32951DC07DA2DCE74 +:1056C00008EAD2CA7E4E86F14D7BBA2582F111FBE3 +:1056D000DB0AC1692F4B8BA0F09BD4AF2203E39868 +:1056E000670EEF770513D0FFC660ADC1FF65C663D7 +:1056F00077BB9B9FF7201E1FBE409CF65076779C81 +:10570000767F36DA4373BBD6DAB5789C56C61F0B64 +:10571000BCBB3756A2CA5AC2EDD37E2CD2ACB7ABB3 +:105720007471D0DF22BF3F1C8F83B65FA28F833698 +:10573000F6DB8BF6EE43DD71D06014C7F567EF2C16 +:1057400045FE7DD8B7FBC7DF457C3A44BC62D471C7 +:1057500097867EFAF2FDB908CF6F4DF397A5F4E373 +:1057600099F7C1C7B38DF18533BEEB32A2C45BD9C3 +:1057700009D7B7F42FCAFD30FA0F3D09D7A111DFC1 +:1057800072FC1A85EF6B994DE1F24FE851902F9D15 +:105790002407228CF4A6DFA16C437D73C637CA4769 +:1057A00071CF24F246CE07F0383451FC17C64B189F +:1057B000674DC9E17AAAC6C6FDA6CAF2F2269C5771 +:1057C0008DDBA53874FEFEB342AF9BE3426AC66729 +:1057D000E541E1F74E04BF39BE7356E80BC497DECE +:1057E0004F7E217C1DB3B552FCF0D83C9535433F2C +:1057F000678263F35982EF65F91AF2CD50C6DECCA9 +:10580000E1E375D33349BCE8D8EA068A339BE36900 +:10581000DDEF6B53AA517F57231E75E35E29F077A6 +:105820009D289923A879E0BDBDEE010FC3F8D7D01C +:105830004FCAC36EF48B75FD1CE317EC5B6EF25719 +:1058400054D79E2D6FBE5C87CF0AC6E3B3FB1FF211 +:1058500068F0BC7AE8DADCB02B391ED1B78578BAAB +:10586000071F8C237F4C79CE45F863D8081E17623A +:10587000FB53287E9AF207D58776038ECBF500F787 +:1058800027AF147113731CAF3AB4CC205FD2620AF5 +:105890008BE8E21769D69DE49F4D8B59E9B979BD34 +:1058A000E5E774C73969BD49FC27A3A7C4BFF979E7 +:1058B000590EE7CB63B50B35F41BDA5313DBC11B71 +:1058C000453B5937E723248BBBCF17743D131C97F7 +:1058D0008FFEAA6A7B78685FD6B9C4CF85F21CE6D2 +:1058E000E4707DEEBEE92511C753D7626F52AFA6B3 +:1058F000597B8FC7FA4DF1D8B4D13DE279FF23F13E +:10590000D8969C7F2C1E7BADE0DB0BE5A1DC6837D5 +:10591000DA3DDD7815743C134C6161908FB756AA5F +:10592000148702FE20FD78EC0185ECCD68AD83F490 +:10593000727D6D0AF967EB4B557A5F7FAF4AFA3398 +:105940000AF26109C887DF0A3961F6CF5632C510FD +:105950003F9F3E3AC550BF69DE7DBF5D8DFEE50AC3 +:105960009B86E31DD1B8BF39EC57C97E853E7C517B +:10597000F44FDF7FB50FF599E487237E95D65BF86A +:10598000A8EAC361DB853FFAC886D208E6A93025BC +:105990001EA7D70663FFF514077ED5BB85E29C29B9 +:1059A0009F3F1808D0FE31A89592DEE4F1D314B1E0 +:1059B0004E27F6ABB801F5F89B9B6C0CFD466FAE1D +:1059C0003A43EBB9637513E54548FFB2F40F9BFD0D +:1059D000CC66FF720FBFB2C99F9C2C9FE15749F85C +:1059E00043CAAB64FC0162EB484EEEC5CB31293FA4 +:1059F0005E13704EECB7E5DE66C043DA5C95F020CE +:105A0000F9F2D5CFEE7A04E5700AF0C71A86F8FCF1 +:105A1000F7E7711FC2162A09FDC81952AE63FE448A +:105A2000499C2E37051776D771F9CF6E586EC8FB93 +:105A300030EB95E472AD77B9B53987DB5D66BD6350 +:105A40005E0F5FB4DEA9AE7DA004BFAFAE9D17C1EF +:105A500072633F6703CA5FB37C30EB896A939C8DA6 +:105A6000EB07954546E9E7AD51BBB89EB0D3FB7354 +:105A7000293CDF21E4E4E5EDA9E9DBB03C97C2F382 +:105A80001DC26814A29DFA465AA485F6E54D63919D +:105A90004F42CCD7114638BDA9E44768EDCFDBA90A +:105AA000D7A472BBFC4025C1AB4AC37C6D25AD9B1E +:105AB0001601CBD6EC60512ECCA7C56F49C1F8C2F8 +:105AC00044B7F510BA5E5A27589883C5F115CF0B25 +:105AD000611E05BEA7770AEE3F4B9DF6C164A70E77 +:105AE000CB457EF936EC0F81EF0F1F5677B701A833 +:105AF000877DA33212D9E9B234C7918F7FE39581B4 +:105B0000B86EDF61C1B25C8A1FD7DF8BF1E1C63DA1 +:105B10002AC5976EBEEDD54BC8EE36C529D574673C +:105B200009FA535A94541FCA1389C77D6E3BC99909 +:105B300096E369B49F68794B117537C94389F703B8 +:105B4000D0AE6034E62AB9496E4AFC035C13701E7D +:105B5000920E952C7A787CF13F05D734C47772B8D1 +:105B6000FA7B487E209FA9713854B795E0EB64A971 +:105B70003E9C5F48F887D8EB69B4FF93746E14FCC1 +:105B800028E9BC4CD0B973EFD9EF5C05ED5BFD594A +:105B90001475500730C243E7EB6EE21389070937EB +:105BA000F0451DCE53C2BD7FEFA86341FC3E3D953D +:105BB000E2F8D2EE9679073DE494D8BF2FCD55BADE +:105BC000ED5EF45FFC3E7BC2D2DCDC04ED85BD0BF8 +:105BD000F86EC2712B3DEC93088BEFF392E537AC76 +:105BE00012FD77F773E1FC8655B989F21BFE717AD5 +:105BF000DE7531F46CB4BA362819717CCB7D332D47 +:105C000069ADE7FA37AF3F490F65EFBEBF621CDFF2 +:105C10002C176E579B9802E3ACBF9CAF4BB68A69BA +:105C2000941F645A2F17923740FF6D085732B9D32B +:105C300057FA3FD193FE4FF446FFEF65077E86EF9C +:105C400071A8C232DA17EEC23ACA13FB201A8FF8D3 +:105C5000B62B93513E9BCC8F91F3917932514C5A94 +:105C6000CDD5E5E194F814D4137DE08FA87E7E5F56 +:105C7000007FFCA6773916A575BA54D07FA9CCCB86 +:105C8000D8DD7B5E461FE8F75A22FADDAEFABA820B +:105C9000C57DA7DF3B3DE9F74EEFF40B9EC2F72D24 +:105CA00076F609D9EF15B55EE4970A8F7F16E6A15F +:105CB0003CDB2CE44E31D00FDE3F9FA3925CFB1EF9 +:105CC000BB94E4F6972C169A6F27C8EB6D4A9FE0B9 +:105CD0008CE5D2FE2F6CCD827E6FBF8E517CCFAB18 +:105CE000352B58CFD7404F6B7D8757CDE37A5C0774 +:105CF000AF9A9740AFEBE4953D8FF3E74AE44FA7A7 +:105D0000E6B1F626AFB2F28C76421FF8312BEF8B5C +:105D1000E5C70179BDCAAB8BE6B36138BF6472A237 +:105D2000AF79A0B04E596156CFF119F3515CAD3245 +:105D3000DDC9F5F62E45E8F1D220D5DD4E12160765 +:105D4000849E3FBD9BBF572724B62B7D7959C4CF76 +:105D50004B772E0F580DF924617AFE5DFF69CF1045 +:105D600015F3B45D044FF634EE8794F0CB3CED743C +:105D7000014FF6000E77F6719ED72EF1952EF61B89 +:105D8000191556C33E42E2ED7635A0A01F3D33877C +:105D9000619A04EC134628E8E7CAF41BDB4B7CE766 +:105DA000B24D7F5631E5ABCAF83E17F73323F1BD4C +:105DB000EE7982FD2BD0A704F3C766E709FF839D28 +:105DC00079511F31B5A6573ED2ED4FEAF2FAE0679E +:105DD00069C8B3887D8351EFED4C6109FD0C7F11DB +:105DE000EB01EC15F237AB42CF4DEA28A67C9715B4 +:105DF0006E8DFC0FAAEA734E2DEEF97DA61F96B7A5 +:105E00000E1FD955A94CD3C19D1BC832D4F3ABFB8F +:105E100019DA17040719DE17365C6A783FA0A9CC97 +:105E2000502F0A5D69685F0C88D5D7076FF8AAA163 +:105E3000FDD0D6AF19EAC3B67CDDD07E78A4CEF013 +:105E4000FEB21D8B0CEF2FDFB9C250BF62CF370DF2 +:105E5000ED5B841FD98C97FFCCE372BBC5CAE550BC +:105E6000B3AB8CFC9B2D2EA37FF33E81FFCA8CF13C +:105E700025E8576F79BBB404F17D20FD4AF2B327C2 +:105E8000E30BB35C4B264FCDCF9F14E37DFC9CDD31 +:105E9000827CBD6C3FACDB2BA0EE7A6D3DC2B47151 +:105EA000048FCFDA18CF1792F11AF97D77BCC6EAC2 +:105EB000E3FEDA7417BB3B015FDC97A725F4A74A22 +:105EC0003E4A8637C98F17C2DBD302BFFF2CDE5E86 +:105ED0005778BEAB5E1FEC4A30AF337916115F0EB8 +:105EE0001E15FA66742A59F21E5A8F17AB0FE43C3E +:105EF000401FBC9997DB334FF7E3EA97E63FA86171 +:105F0000FBF9BCBDC557827449E64F3F23F0A6F3A9 +:105F1000A737707F7AAA016F6FC9F56EF2EBB5A44F +:105F20007F4AFEF416BBAFA42FFEF4B7F218E1FFD0 +:105F300069A473AE8EBEC21F9F6C1F1562EC109ECB +:105F400087602EABA6DF3725DB1F4B790EFBE312F4 +:105F50008CD3B6E2FE4B49A80753F2CB69FF4CFA4B +:105F6000A015F4A083FC04EC9006F5DB275AD8DDDD +:105F70005A1C6E69CF3B98CF695789AE19F83DFB23 +:105F8000365B99A27E21FBCC7EF917A1E7D985E388 +:105F90007D64A74D03F8D7E8F6D7123FE6F89EC414 +:105FA000CF341F8FDFAD03FD88F1BD7DB95C4FAFEE +:105FB00083FD37E2D1931DF00E447B1E9E6F43722A +:105FC000E48EA1F523F16A8EF3F555EE8CCFEF61E7 +:105FD000B78ECFEFC56E95F0AF10FBE7C9EA889D8D +:105FE000E8C73C1DB313DE54C6F32E1B0FDA5884EA +:105FF000E8C8F397251D6DB1F5EDA89F6DCC9CAF5A +:10600000AC6520FCB683FC9C18CBE1EFC3CCD98CEB +:10601000764F4685517F65FA8DFA2BBB2ACBA4CFEC +:106020008CFA2BBFDAA8BF0A8246FD55D85066D23B +:106030006746FD55149A60D26746FD3578C3D74C44 +:10604000FACCA8BF866D31EAAFE111A3FEBA6CC7E6 +:106050000A933E33EAAF2BF6AC31BC2F8DDE6D7860 +:106060003FEAE0F70CF5F2F61F18DA2F38F414E5E2 +:10607000F58C3DB6CDD06E5CC74F0CED00E1ED98D0 +:10608000FF3D9748C2D855A79E34BC9F2BECB5ABBB +:10609000BB9E36F4C35A791E7718FE22BDDE6341DB +:1060A0003B1A2956D6F54221D0755944F145A1D95C +:1060B000C23DBBC6E03C3E7CE39A83D8CF822DC66E +:1060C000FCEF851163BD910DCA40B9D0087C110168 +:1060D0003E598C79E13AF9B698358973817DE3B3FD +:1060E0000587AE63944F1AF6B763DEBB8453F29B09 +:1060F0005FF09B9C9F847731D87F512D0EA71FFEA8 +:10610000F2FD66871DF976FE1E85FD40E9094FC345 +:10611000DECDEB0B13C06586C36C87FE47BED13F57 +:106120003E597551BCE0F451D5C7FD8DC675B8E236 +:10613000108F13AC7842217F9D191FD23E4D8617D8 +:1061400035CCF70D8D392C12D1AD3F4DE0C3E13583 +:10615000AEBFD3F80F9CCF0FD508E61BA568A96684 +:106160007E1B13653DF19C56625CA7663CBB7DFDC2 +:1061700012F295067F711EF3C5F943335F99F1BEA4 +:106180006CCF663BCAC38BC5FB6BF989E312A0EDEC +:1061900046DB13E4D749BCC2BEBD03F548B2FDECF3 +:1061A00047F917BD9FFD28FF8BDDCF9EEB4DCF75C7 +:1061B000A2BF0DEC4BB39FCDAC8795BDFBFFAAA44E +:1061C000935FBBC381EB2EE873F23C18939E2C299E +:1061D00031E8C9EE7DEFDB0AED7B7F91E1B77B61B2 +:1061E0003EBFC9F03BBC00E72D197EA757076F0BD8 +:1061F000E085CEFD809EDA95C04E9CE495719700B7 +:10620000F94DD655F2F6E67623BCFC9CD1BEDC31C6 +:106210005EB23FDF2AF592FDE91ED3ABFDF95D11B9 +:1062200027BA07E39043E3F941F78A780D2C3B3F07 +:10623000D26D9D2DE0D5E70F67783369BCF4714FBF +:10624000B6631E758BC7E251342C793EF75A97B569 +:106250006ABBF82EC7F01D3FCFA422BE01AF5697F0 +:10626000F5533DDF4EF232EA37199C93BC7C3F690F +:1062700063C17BD11E92F161DBDB954E94772DCC0F +:10628000EFE172D2E7D1E77FD8188F074F10F161A5 +:10629000F95CF5FC637958ED19C189DE047958770A +:1062A00064F827E1F39035EC40BB33E44CBC2FFE9F +:1062B000AA97AF139B80170C50E22B9A877AF1F1C3 +:1062C0001FB037AFC7716F57C39427D9E21E53125F +:1062D00074F5DDCF15F4F6B08F82DE5EEC23B04F9F +:1062E00067E179327F463F2B6D3BACBE12C4F706A7 +:1062F000FCF738F2D32EC0EF7BE4BD8A73B8B08FC1 +:10630000EB358F57F6B33FCBBFCCCBF30D9BB03FF4 +:10631000FF30CF5A55D74FFA05FA917E8E3EF8AD31 +:10632000BEED4DEC1F3D85FABDAF78DCE8EDE12F09 +:10633000DCE8EDC55F78EEF8B00C8C674B7F97B961 +:106340009D3C1729EB1B328DE3AF2FE3F5FBC5B85E +:10635000AF887B3A7688BAD3745ED43995D13D1D27 +:10636000F29CA9EC6787D74DED9BB327ECC0F9AE43 +:106370002F56681FBA3E5331EC47EBBD953B900E4C +:10638000DB44FF3B907F73296F94FC39E63CCC25BE +:10639000A2FD12EF042AF15C2BCA31BBAA26C4E38A +:1063A000135E3EFF5999BC5FE977AB7F4011FB2735 +:1063B000E3BD08B0CE5F4E03F97362938DCEBDCEC0 +:1063C000535DEB911F93DD73503B2240F94FFFEC7F +:1063D000F931C4675A564FBDFABC37F1BD05C9E45F +:1063E00088CE9F76D87B11794B1DA99C4FBBDC2EA4 +:1063F000F29B9BDBBD2BE8B349F83550AEA37EC9B9 +:10640000525953223DF3AEC0FB3F7EAE99DFE79178 +:10641000ED72D177E673CD1DF68E75F938DFAB15C9 +:106420001F9E5FC8AFF1ECCBCFC1738C1AF9F8D6C1 +:1064300017B3F40A7C5F6AA1F799B33CEB6D98F748 +:10644000AD31CCDC673618C70DE3A4171473B8C29E +:10645000D7EDCB8776195A171B3482CE7B4FF1E2EA +:10646000BAADE6F9F33DF02DE49B6B1DEC2F101F48 +:106470005AE23CF4F342BF80BCF93BF26BA5C6760E +:10648000F373593C0F16D992F2157D3C5F3B0DF327 +:106490009D06737983EF95EC89D682DCF8FA520574 +:1064A000BECDE7B9D30BF8387D3DCF3DA326F17CB7 +:1064B000871770B88E67047270DC19E39BB93FECE4 +:1064C000B3F3E7D531681CF37502DF33F457A4E466 +:1064D00070399CA26924979947A13C57A7E66BC0E5 +:1064E0007A8AEB4A8F8A76B283C725D95C0BC3FBC5 +:1064F00055268A7EFCD54C79B784FB65B99CB5B22C +:106500007725FFAB02396350CFF23F603F6D4A03FE +:106510007826BA0E537C32654853259E6B787E0EE2 +:10652000EFE37B49CE0DC8F3EEDDE7FAD98F0E1B02 +:10653000CEF5AF7BE4F0C1AB75E7FAC38F1CF68FE5 +:10654000F8C7F3DBA73CF4C8E1B5AEFFB973FD5261 +:106550009E1D5383C7EE04FC5F0F4C152AC3D2CA9D +:106560006A88DE5EC2DB2C81E7F0A78067671CCFFC +:10657000D7EF3D44F83B668379C3F8B6091CD5B61E +:106580006F66445A482E4668DC1B9CAD9371DFD978 +:1065900069EF1A89E3763EF3CA8030C893E3DF3AA5 +:1065A000E366C07F6F5ABBDCF8FCD4AA97DC780F97 +:1065B000C2F1552AD96B742E5A978FD420F8EA5716 +:1065C000058139C85773567F3E466F8FB3502EE909 +:1065D000DF85119552AFA4FC5BBC234D301DAF2F5E +:1065E000DD996DA84BBDBCD491F89CFAA3059CEE37 +:1065F0000B1F6FB3176A387E70398E7F4AE4379C61 +:10660000DAEDA67D989C4FDDE3A576DC77BEB9D7A1 +:10661000C1A2E4076EB731F267F9A72A79788F1122 +:10662000FF639EE70BCFA6517FF31E50C9EF540BBB +:10663000638500AFC1BD0BF93ED804C7BCE3DA14D3 +:106640009457F3362A2CACF1F6ABF0FE8CD05D14E7 +:106650008731C369D62F0B92DC9FB360EF3DF4FD09 +:106660005CE6BF07EDD979ADE6F7D7BC874CBEE055 +:1066700002F19CFB0B84DE19C3C69E1F4CF1A38C58 +:10668000CBB50BEB9D53ABF922FD60B593CA8F568A +:106690007BA89C53C0F978F19E7D2F14D2326F1FD6 +:1066A000837AE9E583F5695FD7E276F798B65BF719 +:1066B0003F4C4D8DF9993502EF63455EE60271EE70 +:1066C000A1FC58EF799935888F913DE72BEDEC1AB5 +:1066D00093DF57DADD667C9C3E38310DF9E3970590 +:1066E000629F3B16F0A2FEF37849F6DD5295DF9BE0 +:1066F000667E2ED7D11CC1D773B7CF5CDF0FC66FB4 +:1067000079E6BD811DC4A7DC7F512EF055EE5ADF1E +:106710008EF0973393DF30CC8E321D3F033FA9A814 +:1067200077CC7C2BF9891DE5DF3B855FA39B5FF769 +:10673000DE4BF8957C85271D2C68C3B1A8D7527114 +:10674000E17BAEE6B51AEB1FDB3A06A23C5960F2DC +:10675000377CAC24DEBF1D2A1844F898ABF9A7603B +:10676000FEC53C1658CFFDF3FC7E9C53D6D617EEE3 +:10677000C475BE9DAFB3A5BF7CE21728BF16FDEC64 +:106780008174945FEF5B5BF370BC258FAD4B4779F1 +:106790007FCA1A4EC7EFDF8FA809CF115FD24FEE25 +:1067A0009FFD2ECC535B46AC06FFCD0D4F47F9F94C +:1067B00097C76C1EF4C336EE70441D808F65BB39DD +:1067C0001EA1FE16AFDF45F86ADC635C978BFEFD09 +:1067D000813C8DFC01E14281BF4214E1CBB6DB2854 +:1067E000AF75D951D587C334B22E82CFFC3DCE23AD +:1067F00006746BDCA9D6DA337ABE074BC88EEBADD4 +:106800007137A767E36E4EAF46931DDA20E4B69961 +:10681000FFF3FA097920F81EF0437E35996FCB22F9 +:106820005C7EB7FCF8C1916FC1FC3EDAFE9B7465DB +:10683000449CFF196685023D4EEFAC9F63EFE5BEB9 +:106840009E8FC53AE9D60B420F697B6062F950DD35 +:10685000CBCB25B668FA558097256D365F181E2F6D +:106860007942F5BBD08E7AD541F74F2C7EE2F9976D +:10687000AF84F92DDE65CB99CAC170A1FC96F46A8C +:10688000443E2F8BD367D153CFDB314F139FAFCA19 +:106890008AD369F1AE7D76CCFB34E373E2CE7D76AC +:1068A000BEDE4CF4DAF9D614D4DB2D3F3E67477ECA +:1068B00078FF5985E517F7FCBEA1EDF9749433888C +:1068C00027D42F926EDD74EC41BFE8F4A747533B09 +:1068D0000FC6792E44C7BFE019845CE2F79F3E0DD6 +:1068E000F36878CDE1433C34FCF4D67484E73D6B27 +:1068F00013E7FB47D6E5A1DE6EB085F33C54F2E723 +:106900000D5BBF41FCB8E0C56FF0FB9C98BF00D7A2 +:1069100033C05B8070CEFBE1F504E77C16247E6C0F +:106920007884DF6F78D6CAAA12ED07DAC4BA796F15 +:106930009B83360FEFD919BF2FE4F7AAB80F6B3935 +:10694000D92BDF10308384A6FA5927A7D7CA7EF245 +:106950009C3D976F8DA255E3F6BB48BE7D30C09F2E +:106960008FEB1FF060F4CFBE38395FC845BAD785CA +:10697000BE03FE9B88CFB17DBBCD9F32D2F09DC8B8 +:10698000BFE5E3AF14E3C3BC53D1CFF75E9E719F65 +:106990002BCBF66EB9C0DA999ECF92C981ED1B89D7 +:1069A000BF3E39CAE5CCB2C8CC2A7ADF6E8BE6E3AB +:1069B000FBC8BE590AC909B04312ADF3ED36B1CEDA +:1069C0008DEF619E56458FDF67F9F93DC92FF3EFD3 +:1069D00087F6BA751DE71F7BFC79717CBDCAFC8DFB +:1069E00005267B4E966639F1B0494EC8EFD90F7334 +:1069F000139E8F88CB8730E16F892DF26F3FC07572 +:106A0000FDAA83CE452E79C246F7FB7CF8F8FE97A7 +:106A1000BF0EFCFFE14EB99E8DF2D7BC9E1B9EBC03 +:106A20009E255ACF1FE60458C2F50CCF13AEE71CC3 +:106A30007EDEE0FF96FC5D9044FEBED0AFA7DD7128 +:106A400015543FF8C9E222DA9F99F02BF16A96A714 +:106A500037A3B190DB539EC29FA34C874F8947C990 +:106A6000A78BFE63298DD3CDCF925F253F77F3AB04 +:106A7000196E233ECDEF37E2DEA93C4E7FDB1AD8FC +:106A80009763BCF61995F2F33AB5AEF42C18779DDE +:106A9000C8EFE9F4887A26AF77E5DAD7A33C91CF3F +:106AA000BB5278BE4367A02B3D53B71F786BAF9A9C +:106AB0008EE7013A2289F332286303FD2049F2363A +:106AC000E4B9DFCE54EEEFEB4CE57EBEC9AA6B60B5 +:106AD00008F777AD3CBE34B7F9C674DCDF77EE1D3E +:106AE0003CA31AF70387549E7314F65B0B00BFF5A3 +:106AF0001C74768A85BF3F1EEDF7BD8BA7623F737E +:106B00003719F132DFB5DD8EFD9C65ABA89C7FBFE8 +:106B10002DCE27F0DF22CCD7423EFFA1E9F9DE6B74 +:106B200089AF1699F82A887C95E03C4966A158AF50 +:106B3000A5AC94EFB7457C4CC8BDC9EA8819D59877 +:106B40004F79909FF738BD5765EB11DEC745BC2CD8 +:106B50009C4BFCBA0CF85BEF37FD08F96E58723DA0 +:106B6000FFD1CF8F8FB9139A2CF9C51F473E0CE583 +:106B700047BF78F592FFC2FA2F5F19F847D6B3FDE9 +:106B8000C467FF7A0BE5753EEBA07B4D3B9FFDD5BF +:106B9000C03BB1FEB483EE17ED5CC3F7D9E167DD0E +:106BA000A4FF3B07707BB1E59973233B487FF17BE2 +:106BB00083C717F27B2A4EEFFDDB1B0AE6F3ED05D8 +:106BC000A8503E8AFD5BE3D329B44FEF7CE69C617D +:106BD0007FFACFC2B34C9CBBEA74B36A3C27DD9901 +:106BE000C9CFA936FED7B81FE1B9CBA5BBF7D9EB02 +:106BF000E1FDC4FFF3F94894439D4F72BB03ECE100 +:106C0000ADCCC7D8570A37DF6B03FA7D8C3622AC80 +:106C1000998EC217A7E179929E78E178E8043C202A +:106C20005C809706949FC9F0714B213F07F3AF87B3 +:106C30008F3FDF82E32FD93B96EE198EE345F1F3C8 +:106C4000E76ECAF700F8F9F367CF8D443BEA42F0EC +:106C5000AEFA5F06EF0FFEC5F97D5021D74766BE3D +:106C6000EFC9D7BFBC8DEA3F75FB68BE7D5CEF4FB7 +:106C7000FF2FA3F7B1FF6FE97D48D0DBEDC1B84C22 +:106C8000E7339F0F641701F7B97F593AF70E77B7CB +:106C9000DD63F13947C3FC5E6391EB2B95E4F9A307 +:106CA00043FA2B721F44FB0C790FF7F49CF96447ED +:106CB0004CF7737F4C0B2B3B88E7ECC27E95E217B9 +:106CC00094BC0378689F551AA13C316B78E8F73182 +:106CD0006FEC86A53E7E5F9971FF353DAFAA0AED48 +:106CE000B923CD302F6877C46DF1B4000833FC2A86 +:106CF000D97F5092DDF78709D7521ECA8C0AE33E2E +:106D0000E4EBA6FDC48DD5C6F737B06DB998EF7723 +:106D100043838DF293AE37B5B7F4F7105E6E644DD2 +:106D2000EBB83FE7E2F034AB3FDF8FF5C443EF78D9 +:106D3000EB8127B1DFA4DC21AD27DE1C41BEFF744F +:106D4000C00B616F89BCBC157DC22713FB5287182D +:106D50005AE2D7E1E7F78EEAFA25BC48BC5F2CBEC1 +:106D6000259DCC7897F8957833D361189EF7CC8D14 +:106D7000E33F5E1AEFD566C26E9CDE6D37BA088FB0 +:106D8000BFDBCECF4BFCAEA27E5329D61FE7F7C1A7 +:106D90009F1D3F8A3901DE2336B687E2427EBFE679 +:106DA0001913CF9F512A7E45F109CC5FD4EF57319B +:106DB0007F510F17E62FEAEB98BFA86F8FF98BFA78 +:106DC000F798BFA87F8FF98BFA3AE62FEADB63FECC +:106DD000A2BE8EF98BFAF698BFA8AF63FEA2BE3DA5 +:106DE000E62FEADF63FEA2FE3DE62FEAEB98BFA89E +:106DF0006F8FF98BFAF798BFA87F8FF98BFA3AE675 +:106E00002FEADB63DEA2FE3DE62DEADF639EA2BE33 +:106E10008EF989FAF65F8E3D67A857B2DF18DA4F10 +:106E200074BE64A84FF6FCD1D0FE2BDE1386F7D7D4 +:106E3000681F1ADE4BFA5F5B72C6F01C631FE131FC +:106E4000B88FE17FA6F9FE66E8C7CA021427B5B37A +:106E5000262A9DE8EF853295EDA4D205CB1CCBF711 +:106E600087057FDA1FF9756B783D32D79171E70698 +:106E7000A2FCFFDDF8EBB85F42C41766E03F356067 +:106E8000E2B4CFFAE33E57C64FD3632A8B8E023E5D +:106E90008C29547A62692C9A0D7C184BA1322B965E +:106EA0004DCFB3639954E6C40AE9796EAC80CABC8D +:106EB000D8602AF363C5547A63975159101B4E6505 +:106EC000BFD828FAAE30564A65FFD855F47C406CDE +:106ED0001C95036313E97951AC924A2D762D95C523 +:106EE000B16BA81C14BB8EDA0D8ECDA472486C3623 +:106EF0003D1F1ABB89CA4B62F5540E8BD5525912ED +:106F00005B4CE5F0D8422A2F8DDD4ADF5D165B4EE3 +:106F1000E588D89DF4FCF2D81D548E8CB550794587 +:106F2000AC994A5FEC1E6A571ADB486559EC3E7A09 +:106F30003E2AB699CAD1B187E97979EC212AC7C42A +:106F40007E44E5D8581B9515B1FFA0725CECC75480 +:106F50005E197B8ABEBB2AB68BCAF1B1FFA2E75786 +:106F6000C7FE93CA2FC5F6D3F32FC7F651E98FFD9D +:106F7000869E57C60E513921F6123D9F187B91CA45 +:106F800049B13FD2F3C9B157A99C123B41E55762C1 +:106F90006F515915FB90CA6B62EF53F9D5D819FAA6 +:106FA000EEDAD89FA99C1AFB1B3D9F16FB2B95DDA3 +:106FB000FBFFF1497F57C0721EF7CFAEAC3EDD57E5 +:106FC000B6392D9DE4E2F4555C2E3E98F6F101921F +:106FD00093E31C9A8384DF1643BC8B7E4402F67DC8 +:106FE000FBC6BDD71FED9DF595275EBF15F5D97280 +:106FF0000713FACC24773F73097F27C37CC49B0512 +:107000005FFFAE627F2EDA51EBCB3A96A0DFE4DE73 +:10701000E28E1A2C0B07703D9925CA8201C2CF5A05 +:10702000C2F56FCDF2A1FCF70572FA065FB5D0DBB1 +:10703000B2BD5224EAAEAE81745EAF8FFDF4B5DD11 +:1070400085F2B03EEF1FBC62406E6FE707FBDC4F7E +:10705000C517D44FE580047961E67EDE14746F1B9A +:1070600010988CED99D53F12DF4F5853A0E2EFAA4C +:10707000D46E523CC82FF56B4BA7205DCB989FFC7C +:10708000923727C9275B2CE85AD76463E89FACD3B3 +:1070900018F987EB76F33C64F4A74E037E6910FC85 +:1070A000B274E39FC9EFD4D0B480E73D45B87F4ABE +:1070B000FE8ECDE2D6B617D0AD77961DA6FCF8C5EC +:1070C0003B8CFEAB46E19F5ABAD3F4BCE92B09FDD9 +:1070D0009E66BFD4DC01C2DFE9E3794F4CED4F700F +:1070E0009F05B8319F24789BDB897A03F0417118A2 +:1070F0008907E9F794F8603DCF5D50FEEAE98343E4 +:10710000294FEEB4A6E563BB603AFF3D2BC51A1CC0 +:107110008BCF018F94CFD2D59C46F9506F811ED072 +:1071200030F1CA131C8BF7C775BC368089FB2B8DD9 +:10713000F108E726CA13AF8539605E4AED63D9745A +:107140006E13FA1BB907FD9A8FD9281F29CC5678E0 +:107150005945CF7845609D8DF8A26E4F26CF4F0BD5 +:10716000FB8FE2B9024997B7D60E9E82794D751B07 +:107170008A4BC95DB7C746F6A18CCB4A7AF5CCDFFE +:10718000E6F9028D2CB21E5397805E2713D2AB75A1 +:107190001FD115E8763209DD4EF646B7874D7443A8 +:1071A0003FF58DF8725536ADE79A35D1A14D3AFECF +:1071B00034FBFFD9DC2BE9DE1399FF5CD54FFECE03 +:1071C000982F0FE97B665339D1CD4CAFAABFD713A7 +:1071D0005DD86B6EBA77F8E6C16CCED7E0F91CE1EA +:1071E000F7BCB9E51AB2BF770B39F7BBD598FBC925 +:1071F000D88BAB9DCC0FC6F74BAB3D54FFC36A2F6A +:10720000D55F59AD51F9EAEA122A4FDA795E915CFD +:107210005FC00894DFF7B458574F0F90FBB2955EEC +:10722000F47357FDFDA5720B89BE37A64F1E40763D +:10723000BB215FA47A96311FA4C326F2CD362A3E25 +:10724000BC4FA62E7095A13D2B1915AFA3FE11F9C9 +:107250002B751B32E91EBB9BA6661BDADFB0A1D0E3 +:1072600050FFFD008DE09E5935D8F0FCEB359719A5 +:10727000EAB5E2F723985641EB46C6BF407373BAAE +:107280007878DB4F9AC6E6DF0EE37F72D846EFCD03 +:10729000F438690FD37E3EBCCDE1C3F8DE293CFF54 +:1072A00006F5537F5029BFE8948D853D20E24F2994 +:1072B0006C2D96CCCAD7D5D9637C5D55FD5D65B87C +:1072C0008F673F71507CB07E8BC2C27837431760A6 +:1072D0001EC65DF96307C13D778BCA8274BE4ADB67 +:1072E0008971F2958F0DF3617CF4E6C1D10178DEEE +:1072F000B0EBE7293E3CF755DFC1BF3F05FBF34C40 +:10730000CC8F52CA281EF1A769ADF32D986FA71E26 +:10731000CEC5F5FAA727F9EF9A2D5CFE87311EC07E +:10732000F3A21776BE5C01E39C6C5569DC0F7738DD +:10733000DA545AF7FE7CBCDF360E7784FC14D7F69D +:107340000BFC0DE5F507F3232349FEACE2FEF19EAD +:10735000F8017891DEC8AF3A7916D76F3CFE064245 +:10736000A800E544BDCD4771D9939B6C142F047DD3 +:1073700040F906275BB32D5C0E3D497C5767D5EC81 +:10738000FA71EB36A97EFEFB189A1DE7CB36AB41AE +:107390003616EB3C3F22BC4109F2F88F91BEB72E66 +:1073A0001F4BE7A2CD795CB2FC18D6545017575A40 +:1073B000F40C8FFFB2D11D567D9EBBF4CFB060851B +:1073C000E13EA325831EFCCE78284FFBF9D58B67C1 +:1073D000B7BB494E7E64796ECCED507E382DFCAE45 +:1073E00015E8F2A21A1C3610F3862C9BB62A145705 +:1073F00039F11D8CFB7FF084CD47CB50E48D2DFA05 +:10740000C9428A4F25B7179897C7AFA3798A176FD4 +:107410002766942F329BED14FE8508CF33C04900B8 +:107420007E3C4B785CEC44B9FB6E3C3F5C6F3A6F42 +:107430007C429CB3B872A062D0D7770CE472A0DE15 +:10744000C2D7277B96DF43297F2F4ECA71296FA5AC +:10745000BCFEEA409EC722E52C633B49BECC17F731 +:10746000252FD9E1E0E78B34E6413C2EE4646277D6 +:107470000DE4EB7A91FD89EF235B2F60EDA4F73EDD +:10748000B045E6B717E3F76D6BB3E87B9B2F82EB54 +:1074900038227F8FCE4A726401E3F35CDAAA44A2F9 +:1074A0003A7F87FC7D12867A4227777AE805933EF9 +:1074B0009827F4DF3C66CA376A35EAA9409A9BE010 +:1074C0005AD42AF2B0BBE7A5B2F318EF0A465E9889 +:1074D0004EF3567C9104F358C0BAA2782FF2D2C76B +:1074E000F93926F3BCCC70F4759EF37D3327E1FDAA +:1074F000CADDE39AE62DF1CDF060958E0E12EFF322 +:10750000C31C9FF3F72A44AF7784BD25CF079AE9C0 +:10751000BF8005A6A39C5B703FEC338BE3FC20F996 +:1075200060E1AE089D07FC90B5A6BB603D2CD9B2CA +:10753000EB8671F0FD821FBE68477EAFC98A0EB52B +:1075400064C2FE333CE9BB555727D0FB263DFF45BF +:10755000E18909BF157D077899B75DA53C0A5D3BB8 +:10756000914710267C3584F9EF09361C557D2DF0A6 +:10757000B4017FE6A8ECE2E72BF1F63F3D6FB35D87 +:10758000F38B81BDDB356679D3C3AE31E9533CCF94 +:1075900081FAB32B97E7A77F62F56764919C36C9A0 +:1075A000E1DC32BA8F55CAE1F9420FCA71E6A1FE99 +:1075B00083FABB5B9E4A477FC63BF73F9547F91A64 +:1075C000A86F46C4F5CD6DF57CBCDB7E9942F952BF +:1075D0007F9AD63E12EDC19A477E95AEBFEFF54F2A +:1075E00005C1A30371BE423F2E55DB06E2EF1A4AE6 +:1075F000397BC17D5B3238DD1780D36D84B30EE1FA +:10760000D49D53A91770BEBD81C377621387776E6F +:107610000F38C31457B9ED470E5F98EC8E28E9F583 +:1076200053BB5486FBAC6EBBC364079C65AD5B115A +:107630001F4B57BCF28615F862E125801FE0839A44 +:10764000CD0ED2FB0B7FCEE3A91F2895F914D03FB6 +:10765000104DBF039E2F027B01ED8DF83CBAED80EB +:10766000CF108FDD76401FF1B74CF8B596EDFD15C4 +:10767000FD8E96E2E7F998CBE4BD367B4CF7DA68ED +:107680002803F8397F27D2A9BFF93E2EEE9FFDCB04 +:10769000D03FDFB282F8BFEB12FD39B6C6D4A80DD9 +:1076A000F390BB762964272D5D59995EC9F07C1B48 +:1076B000F7AB151471FDA6F8FD945FE300BAA6C2FE +:1076C00078FD8B34FE5CF3F07CF31F32BA4747CE73 +:1076D000D7FC1CFDED4ED4872E0BE94333FCD716A7 +:1076E00071BDB954B5907DBDC4CEEDEC4E717FC572 +:1076F00070318FE145FC9CC315C2AFD0897625C699 +:10770000BBAF76D0EF18313689FCEE56C6F9CF2ADA +:10771000F1E6B17EDCBDBEC97EEEEA8F78BA85B5F2 +:10772000D3EF224EAF98A9E1798637F29C744F14BB +:10773000FC09603FB3453F476CFCFCC21B3806C0E8 +:10774000355BF8A7DFC0EB5161FC370AEC64D786E4 +:107750009F7190DD70572AF71FB29C0C2BAE87AF3C +:107760000B3975F378871FE5FAECF17705B084FEE5 +:10777000C20CF055E3EC5A570AE3345BB8BE6FCE47 +:1077800062DC2FB0B6A31CF1770598C998BF0FD063 +:10779000EF3E9FDD1B1F19CF4F2C413FC3958C330C +:1077A0005805E1D7505F62E7EF6B1FDD31E3FEF173 +:1077B000B04FC0AC29D4338823E48BDA0CDAFFCE87 +:1077C000C0F30559585A89DFBE6665610B2F37B87B +:1077D000E85E25AFE17761AFAF60D10C802F7AC84A +:1077E00078BEE3C6A8253A0CE345D6E83EC49FC55B +:1077F000A9D93C304EA04A2943BC2F59D3B7F9AE82 +:107800007CF4A919F7F7873ADEE785F3BC43A17C3E +:10781000A1D9B0E8914F6FB1B2036A19A71FF26105 +:10782000639616A676CB399FCB7325922EA5D0BD35 +:107830001EBFB3C5FCA09F0DE9F8BD3DB15F252C6F +:10784000F852DA6B8BC5BA5D2CF9EE71E37ADD265E +:10785000D70DDA8780B7D9A24CC6F78F8A75F16841 +:1078600011DF67DE5324F7997D1B6FA9834509EE6D +:10787000671C444739EE0C513E523488FA93F3901A +:10788000FC3B9F35513ECF7CE1A7B18024A1FCE0B9 +:10789000D61F71BF9029EF080C25CA6F5BB4DDFCC1 +:1078A0005CE7E7510D7289FCA68ABD6B2ECE4FF9BD +:1078B000528A0FF97DB67D27F907CCED6CF8FBA94C +:1078C0001877DB00769522E26550776C52E8772FC7 +:1078D00066F7EFBA1CF53948EB29742E54D8DBF360 +:1078E000057D1DE27EABF9685F615C0DED2BC4D7B1 +:1078F000166E575A853D5CB7C9686FCC5EABB33B1B +:107900007961B81FC061CA53B709BBE34D7BD7E5A6 +:1079100028F7CDF705BC69E17084F318BF573387AA +:10792000BFB70AFB52F2D5CF8A6C86789B3C775A58 +:1079300083F28ADFDB60CAD372D1FD31350ABFBF63 +:1079400053FA215F17E569B043E9BE9CE369140768 +:1079500037FB273B2BDD618BCE4F7973C66DD3117F +:107960003F35E9762B96AF77DF2BD641E31FF70C37 +:1079700022FB677DE5A82D989FF4DEA36766380794 +:107980005034459C9F8AFD0EF3E9677D06F050FD5B +:10799000AF33FCB08FEA7CBEEB162788EECF8B3E70 +:1079A0009D61053DDFF940D756AC67686A80EAF70C +:1079B000760DC43B9733220E5E6F96FD3902D85F79 +:1079C000E743BCFED1A38E4018ED5F716EA9E64A75 +:1079D00085E4AF0BD75779DCCF5463798E9713F8D2 +:1079E000EFA25CA89D570BB88ACAF13ED493F4FB72 +:1079F0000B8307F95D45807FCFC0E0392C17CD544C +:107A0000C2763CEF7F347289D06B097F27C425D6BC +:107A10006B617180BE977E74E88769E53DFBF96F05 +:107A20008E8B3EA000800000000000001F8B08002D +:107A300000000000000BE57D0978545596F07DF5B7 +:107A40006A4B52498A244042162A090901031490BC +:107A50004080A04512202C810A28A2A0168B10106D +:107A60004840EDA65B7AAAC226E216D4B1691B9DF6 +:107A700012D1C66EB5A3B204D92A6C823A5228DA62 +:107A8000A8A041504163774418E30CB6FF39E7DE04 +:107A900097AAFBA8B0F4F4CC37DFF7878FEFE6BCEA +:107AA0007BDF5DCE7ECEBDF7651C63AE7A1B633F88 +:107AB000E3CF0DA1D2D6D5C05821632F3ADCB6AEA4 +:107AC000504E5D9813EFC967CC9EE18972003CB7B8 +:107AD00052F199FB30C68EFA73DDB18C8DBB423FFB +:107AE000BFC8BCA49F847FA49F8F74FDDCAEC0BBC5 +:107AF00083E03F733AF0FD3BB25DBD1D1D19BBEB4A +:107B00005F9807FB6165430C6C0063775B19FD7C34 +:107B10005FB335D75A00E54B96449609ED5ED9968A +:107B2000310BFA618BE1A514C6BE69FCC8EC807EFE +:107B300016B4AACC95C85875AB42E5824D8DE611B6 +:107B4000D0AE1ACAD2B0F9CD13F365ACC93821361C +:107B5000F4BCBF83CF97B1358CE17C5E396BF440C8 +:107B6000BBBB0CF55F3E95048F072BCEE71D97AE90 +:107B70003355BCF72963E5F5F997D60F722854FF02 +:107B8000588EAB08D7D905FA405835F0F5EADB2F07 +:107B900015FD4D8D6677B8A17EC68058AB03F05DAC +:107BA00078D4B32C16E6316B5D663F15FAE89F5129 +:107BB0005282FDB19983257C9577612C88EB33B691 +:107BC0007462507EBFA3309EC1BCA62604EF617DC7 +:107BD00019FB8DBF7B9D752863637E0B6DBAD02B1F +:107BE0002E06EF965B04ECBBDE5D560CF0DF558293 +:107BF0003D8EA23A1FBC7F10E703E56D037B45B3C2 +:107C0000DE80BDCC18833D9EB192F469BF41BEB801 +:107C10006DE0D011F87C982536771AE197117F94A2 +:107C2000A4BB27633DB667B00E8F39D0F166588785 +:107C3000E72DD5E98375787AC778FC11F03649E0ED +:107C4000E1370E3B95070D30CF7EA17968E30367DE +:107C5000DE1384FE4E2F4DE9BB1AFA7B367DD81217 +:107C6000C28B18FFD974CF9CF0F161B9BDF1F9D581 +:107C7000CE639698C71241377731F099C0F5CFF0AF +:107C80007F42598C04DF383691B9F242F0A41B537D +:107C90002578F2D46CA9FDAD33AF93EA2B2CC182C9 +:107CA0001A5B88BFF5F3D14A2014F16975ECC63828 +:107CB00006533CB1E3C28753404EFEB641752A30AD +:107CC000D7393B9FFF7008B43A070B4E04BC9D7335 +:107CD0000100EB3DB749F5FB32913F5CC68A4E8C03 +:107CE000556157D07EFEA1D7CDC3E0D7AA9AD963FC +:107CF000918E73FCA6CF9BC2E679815D34B32C9044 +:107D0000878DF2F36AF6D0776A6F840266772FE880 +:107D1000A75E575F33F22B1687ED8C9F3769EB8494 +:107D2000F1171FCF7C645FD8BA9F76C4267D791D7A +:107D3000FCD28FF5FB59C5F19A0FC00A596943234C +:107D4000D169D921D5892CBA2C5D610AAC73E4269E +:107D50008B3F0A44EBDB6D27CD0EC0D70F5EC723E8 +:107D6000FB4C28FFB58C25E27B27CD4DF07CA8C3CA +:107D700041785AB0E33B3303BA8FDCB190E47A0424 +:107D8000E8B178E09F6023EBB509FAF765C63A9F42 +:107D900087FEEF5A350A848BB1F8D62954CEAB1B37 +:107DA00045FDCD6F9D48F082D618820F46074730BB +:107DB00098C7C12D1DD83298C7613590FB7BECC7A1 +:107DC000124B7AA222F5B6A5B8EE83D1BEFCBB61F8 +:107DD000BC8A3F8F2C47BC2ED8A4B890CF2A5476AB +:107DE0005049C0F946517F15EA7B050BE1F998D25D +:107DF000589F219EEA19837A7540EC6A06B06A069C +:107E00007D11813F0F09FD626AE2F31EDE5A49FDD2 +:107E100069F5871D59B47E0D3675DC609C6E0BAD1F +:107E2000C7D4A45039BAF53A2AAB37551A1D30CE0B +:107E30005B79CF25219EA0BDCD13512F0F8C6711EB +:107E4000F497565A843E9E82FA18FA3D90E5FA025B +:107E5000E572DC9226A315F5A9CD6A7F1EF8605C59 +:107E6000515FC7ACB075A97B6E610EE0234B528B9E +:107E7000C905FD4F81325C7FDFD18EBDF9A64D7FF4 +:107E8000D752A9D925E65CC218F0F9ED763E6F4DC0 +:107E9000AE8E89F6DAFB4185CB876FB3C5FF3CFC1C +:107EA000FE5996E7279C6F70189BFC1AE9D3604631 +:107EB00065EC3F6FFE405F2BD23FCED8C412E07D11 +:107EC00043A6367F2ED7579A7F8B98FF61952D4614 +:107ED000BE387CC30D4117CCABF1BEFEFDD13E6870 +:107EE000E325669AA93F666FB988FC5ABD2BC6B1D7 +:107EF0001AD65701B441B865A7C5BF3E939E332536 +:107F0000094BCB7A05EAABE35A72D1FE94EE8E0AA6 +:107F100020DF36EE8E32A21D7933C79398D9119F98 +:107F2000772F5380BF5D3B2C46E48364872B29B3B6 +:107F3000B0FDF95E498F69F2A8E733CF2A2E7F1E84 +:107F40002187D304DF4E177238CDE88CFF25CCFB98 +:107F50008E7754867A7CFA12A5D7A602D469B1CE60 +:107F60009C3039D4E4CD847CD91FF993F3E5BCD699 +:107F70000E42BE3345BF5C0E2AC040237E2AAEEBC4 +:107F8000E047F95ED09A48ED3479D5E4343DDB53CF +:107F90008AEBAE5806F20DE37896A614A0BC84F8DE +:107FA000C46C477E023E499E15C607CB1A7F342219 +:107FB0009F988A15E2130B94A5617CE46EF353EC51 +:107FC000233AC13CC62DCF34AC66A1FA72E4978E39 +:107FD00057CFEF85A2FD745B20C700FD996AA29C74 +:107FE0004B615EE7921CA4C7163D0000A06091C9DA +:107FF0005D8A7EC6A2DF294ED4BFE87FA0FE19703D +:10800000ACC6EC099BDF2DADBD9903F034B1B51BB7 +:1080100095FD333C93100FD35A27093CF6A69239AD +:108020008A0C389F7BACDCCE9CAFB9FF761CEFBCD2 +:10803000DFE2C4F1182BE2F416F32D74393BFF1282 +:10804000E7F78E893D0BEDCF44795494CB33E9CCDF +:10805000FE384C71C65AA033F47BC6C47C76A0E7C8 +:108060004C803D087760AE0EFD50EE609D6176E578 +:1080700082B12E8365037D17FDE55323A8C239B96C +:10808000C1DE011877EA306EFF9B3798C8FECF6BD0 +:108090007C6F8001EABFCE747566A07BC774F1D493 +:1080A000E07AE64EF0BF6202F8AE875F8F1BE4080D +:1080B000E1B3DE18C831C2FBF580471FCCABFE210F +:1080C000B5DCCFFD9E98CA5E57E6EBB9ADD9841FEB +:1080D000CDDE68FA7BAB37191611D2E357B2431ADB +:1080E0007FCF1772301FE58085DB9B4AF730E4C3F2 +:1080F0003CC599C3C2ED0D97074D4F03BF93DC54A8 +:1081000064A73B97B190DED6DBA3BD6AFDE3836134 +:10811000BDCBB33CEB510F94FCE9BF5EFF18AAE660 +:10812000BDF66219D269D8750A5395ABD1933F9ABF +:10813000484F2EA964A427A10CD793A676FCF43F40 +:10814000645E9B9EFF57C1F7E0DF92DF887A3CBCFC +:10815000BFCFB24AB6219D77652A5CEFFE93E6ADAC +:10816000D7EFBBDAE4F5EAF4FB4BA2FD95F4FB1183 +:10817000D4EF8597EA7306FDA13EFFDBCE1E7ED4C9 +:10818000F79F32D0FF68DF76C4389E17FA9EEC4125 +:1081900074BCFF72FAFEB19C1947103F11F4FD7BCD +:1081A000FF0C7DAFF1975E1EF472A0E7FB310F82EA +:1081B000FF8574DAAA30D4AF217F8B111F1FCCE268 +:1081C0007CACC94D98FF45761EE4C19F9379A95CAC +:1081D0007E5FF3970207C69B05B17D9912E2774D4A +:1081E0005E347ED7DB9139591E35AB302427F35EE0 +:1081F000D3DB81F6F8699B09E357D3BCEFB81D8048 +:1082000032DC0EB4E7EF58B3AE4D0EFEE32AF92987 +:1082100035EB7F9C9F52B322F3535A56C77F9C9FE6 +:108220002E4347B2331A9F8D799BF307CBE6FE3E70 +:10823000F00BCDFBA039DDBF2C13F51ED787637E75 +:10824000663588CF3B443E41E3D711D91E17CE5344 +:10825000A333FAF7E8B75FAD5F3825A986B9E0F92F +:108260001D5086EB0D0BD22F827F3FFC1AE9DC3FBD +:10827000EBEAE83C49D0F99FE8174ECB8AE0173289 +:1082800017B7FF21BA582622DF7C1F303294AFF691 +:10829000E86A5ACBF1AEC12B0246CDBE26A27D05BF +:1082A0007E99FEDFE1978AD2FAF35670FD7CEB8B64 +:1082B0002B8D83001F454CE43F86AE717543FD0254 +:1082C000BF0FA61E293F725815B0EFFA2365308FF5 +:1082D000318FB7D5FBB07E78717C5B3E054309AD2D +:1082E000BD77FD90230FD1BCEB38BE3D4D4677AF37 +:1082F00030B800E0D830B84807AFE3EDD18ED8A948 +:108300001F3F974FE85FE987B0D69F9003D632A210 +:1083100003FA8B9B143BE6436E2DFE9B19E95351E8 +:10832000DA742015D6FBF8FAE195B61EF01CF5209C +:10833000CCF7B9F5156B7C46F17E27CA8FD18FA596 +:108340005E71A940A779458A3F2BF3523C3E9725A1 +:10835000DB33FC31CAEF3373C1B5BD8FF24BEF672E +:10836000D1FB01CB358C7F733173F923E8C957B545 +:10837000761701D6FA07DC4DACE771B8BEFD3621A1 +:108380006F4183613E037C35AE9FB606F365C3192A +:10839000E78FBDEB3D95980F2342EBD67BB9F9FEF5 +:1083A000214B8EEFF0C721BF1FB81CBE5EBEE47D1F +:1083B000C11F5532BFC41BDDFBBE8779C427297698 +:1083C000F46B17B8A31E42FFBDA254E3EFBB2A5DB6 +:1083D000C5B0BE2826E5FF42FC3DAF12F97B01D3B4 +:1083E000DA2F588376C96D686BCFF97D87D2F67E18 +:1083F0001EF00FA5E2E0FD13EBE7AFF1D9881E54A4 +:108400004F70B7CBF07BBD0E2ED6C987E06F924F71 +:10841000D4DB809F9C087AE33F059DBF55D864D488 +:108420007BC112EEEF05B378D9259BFB77866CDE16 +:108430002E3A5BD0393A0C0F69213AC34F00E388DA +:10844000B075139E6E49D2D6FD70E55858573081ED +:10845000F552804F92B21F58B33C8C4F3A653F5C47 +:10846000897808F5F7E011D4FBB7083C75C97EE8B8 +:10847000888FEB3305E56E3E3104F0C126C5A7C2F7 +:108480003AE7231F4458E7E94BE5C6A77BDF65BA07 +:10849000CCFB5F5FCA872EDDFBCC94742DEF0B3ACB +:1084A0008DD5D1B15C47C7321D3C5583FD923ED37B +:1084B000F4DCF486352B3A2561BE51413381FADA7A +:1084C000ACF465ACCF734F56DA0621BF3A4CA9A085 +:1084D000F3FB3FB7F6881578B912F519F1EFEFD62F +:1084E000B8801F27A2BC13FC54A5AB0FF24FCD8A56 +:1084F00064683FE8B9DFAFB142D35B97AF31A14FBA +:1085000033F4B9A7D718817EB714FCF900F667AC2D +:10851000FDB72363332FC3AF75BA75ACD3C13E5DCE +:10852000FB27AEA0DF97EBDE5FA2AB7F4807AFD59E +:10853000C1ABE4F7A7CD54484EA601FD1071579288 +:108540009B89D96D79A4367BA6D8C84F92F87ECC8A +:10855000320EDFF6DCCB95ABF2C3E0EC3F5786F38F +:10856000B189F19F2949CC87F6C3D48E3E1B93DD98 +:108570000E1FE5E9ED1DAFFF0C7F4DA17D16C92E45 +:10858000EF5565B851D5E6BDF3C83D367CA8C13B73 +:108590002AD11F6F77DF83BD5189FB1E631E15B083 +:1085A0006F5B25EA3D6D9D5AFB113FFDACE278778C +:1085B000676FABDC80FB2A25811CCCD74F4DE025B3 +:1085C000D81915ED58B5C8778CD8A9BAD1CE4C8D2D +:1085D0000EE42CCA0F5B27ABCFC57536DEA7127D24 +:1085E0007CCB783C329D39CD98AF688C8F5FFC0294 +:1085F000B4DF7B9FBA18EDDAA78B133BE1FCF7657C +:1086000073BF6D6F7CD74E7702DC18738719F3B593 +:108610008DF70FA7728FEA5AD9027CBCE6B9836442 +:10862000E71B63E2093F0F67EFABAC05B9A8CB7658 +:10863000D0FB9E047BA706F457579B18E6ABC1916D +:108640007A86F8E6614BDFD5308F69B5D7D1FED198 +:10865000F47FAD1C9102EDA6AF30D1BE02FCF4C692 +:10866000797B560F3763FDCCE5A2F48DA472F7DF5A +:108670005F7FBB37B46F794075AE87C6BB5AB3E234 +:10868000A6C3BC4E45713DFC7973B7389C678F6EAD +:108690009E75D9C8AF71B1D10A1A0FBB236E02F40F +:1086A0009B9BE37A3ABB63A8FDEEBFABB40FB6BDAC +:1086B000797A27CC3FFD41E8EF5DADD33B4D0FB359 +:1086C000F7B3BE35129E779B1DF7A07FB93B3A5D8D +:1086D000C1BC0CE03911F3B633857F0DFCB2F8F55F +:1086E0000876FF896C95F072DAB2989D02266E7C4E +:1086F000B06331CE537B4FDB7F33A539FA85FBD195 +:108700001BBA96BC8EEB08F1D96747906FC88F06ED +:1087100078D7739FACF1A12DDC0BFE3FCE23C9357A +:1087200002EBD99244BE0F9A5C9F1B9E8F08F9A959 +:108730004B853EE0ED4EF862296E3DF152941FE309 +:108740009913BE4F62C3F3EF9A9CCC8E8BF5A13187 +:10875000FE2A36D68878FDD4E8FDF257B86FF8B413 +:1087600089F4E8ACA73B2E69417D00F4C47C907E7F +:10877000DCE46E261AB7FDFDC1E6CAB2B430396139 +:10878000CD95AEFCF6E5E4D873DF546EB0B52F2777 +:10879000B385DF3EE269931BF97C7661AC11F7E9A2 +:1087A0004A9EDEFF3CF2E3EC8551FD2C30F1D94FBF +:1087B0005B88BE4DB1B13E3BEE23C6C51A3B40F9C6 +:1087C000ADD0234DB55114A7A89DCCA4F7D4958561 +:1087D0000EC44FA9CA8C56B02B6A9CD3E1E6F07246 +:1087E000CC1BAE882D72207D3B76E3F2D0561F3F26 +:1087F00079B4D23BB46F7676F1E34F0E84F97DCD38 +:10880000FC930666FEF7F7D1AA993B1EF38FFF5340 +:10881000FB68E66EFA7DB4FCF89B91FD16AB346FF5 +:108820007569941FF1A966703B319229B48FC6EC2B +:10883000B0FE5EA17D34F5D7FD093FA7BDC057DD71 +:10884000012F71566AAFFE5AF55B60DCD2449E6F11 +:10885000559FAC64B8AF0678F5D9011E995443FB17 +:108860006B4B859E99A630773DC9BF3303E3E4592E +:108870004F47111D673F33E7C3DF1520DD2A92C242 +:10888000E52953F01FF4C7AC09A17EBEAAFD4D0631 +:10889000CEA7F4DF20BEC4B853F53C790BE9CD1860 +:1088A000DA6F63F6A6870722BFD4C6F4C53CF9EC9D +:1088B000A75332B2F243EFCF5E7A5F2E7F1FE2D62C +:1088C00038D45B51B49E799B2CC42FD31E505D6469 +:1088D00027D3CD64273F5F1E45F0BCB42292B76911 +:1088E00006BEFF063E6132E9778E7236CFC65CAFB8 +:1088F000DB50DF3F1454397D7C826E66A44F71B724 +:108900004492CB3B10C760BFA622BF75A4FE781E61 +:108910006A9742FB4D8CD538500F4C3528A4EFF4A4 +:108920007259D18DFBAFD3329CB7E37BF31FB138C3 +:108930009766F239A8DA7C206E9A6F08CEC27D481D +:10894000B6C542F98D6A5847541C3FF7F01ACCBFA0 +:10895000DAC88C66CC4F39B85ED3E653EDA81C89D3 +:10896000FC0AF5C78C503F3F96EBE5F91D78DE8792 +:10897000C55AFDCF878F8773CEE6EF39E250DE060A +:1089800011BFA0FC1BA0FE6F8CD797C615399AF2B9 +:1089900069FF7E15E64B703E3D7A878D0B704A6FFE +:1089A000E4C785C6AC58A443E2A4C938DECB2AE9A3 +:1089B0002710AA478AD00F7C59ED8FF1ECB407F647 +:1089C0008E588BF0AB7DED388569AFBC4F76EA2EC3 +:1089D000C1674DE8FFA3DD02F85528EFEDC6F5832A +:1089E00047E5F99C7BBB29D2BE9F563FFF0113D1BF +:1089F00063FE0ACE0FF36BFF42FDCE8F0D76427AF7 +:108A0000CCDF6C1A807CFD2F62DED36BD38B8F01A1 +:108A10007F4C37C5DB157834CF576146785E9D4271 +:108A2000B036DEFC073EE864C8E7FD6169117C14DE +:108A3000EAB76306DAB56F5E4ACC981646F76F96CA +:108A40006F8DC37DED5351811C3BE663164639D7CC +:108A5000939C727A7CB33C673DE66B66DA83B1B86F +:108A60001F3EF39EEC04B4779FDA0366ACFFB43E7E +:108A7000D380B0CB6E2F46D865EC43F037E29C0A2A +:108A8000FD009D16289C6FE6BDB4D79C05E33D27ED +:108A9000F8ECDB97DFCFC5BCC1FC8C602EDA61E05F +:108AA000ABDC54A4CB1F15F21716BCA4BAA27A876C +:108AB000F86A01F215C8FF5CC1570B366DFD25CA77 +:108AC000E902E4A77E97F225C497FBE8F96BCF8E05 +:108AD00060FCFD7DC8779ADD0778B909F36B660104 +:108AE000C338086F10FA1AEACB78BD2F9FEC096BD8 +:108AF00032A35F5CAD727F01E42919FD89EA069318 +:108B0000AF294C3F2EC0FAFC507D7B7CB3BF9BD875 +:108B10002FABB5905DDA2FF0D2F4C0E638E48B6F5E +:108B20005FDE7B6030C659AF2976D4FB97C8A1C001 +:108B30005B35E2298ED649FE5135E2252E84A736D3 +:108B400079137C51CD381E34BC541B059EB47AF188 +:108B5000FE01C187F398C0EBA6EE5CDE857C03C7FF +:108B6000901DD1D6E74990CF0FFC20F8FEA858E71A +:108B70003CE01B673EF197CB3C40C4FF50F5EDABAA +:108B8000CF52FE48A3A736EFF81C87A6A75D1D129B +:108B900042746E32B0AA48F9EAAF85DC996C5CAFDA +:108BA0009CAC4DBD7D31E06FEE4BAA939087B157E1 +:108BB000D8B81643532CF9A7BF56EDB8AED23F55DF +:108BC0008EC6756B7C67DAA8181B709F907520FCA9 +:108BD0006BF32BEDEC1EDD81F35D00E7A3CDF3A479 +:108BE00012207AF95E55ECDCDF6D32631E5193532F +:108BF000FD7C7F10F355E394C14A1F9C8FD381F213 +:108C0000CDC00ED27C6CC7EEA3F17C27EECBEC1D61 +:108C10001AE7535FAC11DB7DCAB81ED0F8F2A4C8C6 +:108C20004B9C5CB195FC616D9CD81CCE5761E37880 +:108C300016275D3A8ED6DE94C3E7A5C9C5C104CE1A +:108C4000FFA5CBFF42ED343D8B3F988FD3F0A9E1D8 +:108C50002D4C2E25FC68F2A5C99346D77F54AED87B +:108C6000928EE4B7DE2FD64D32D2296417903FD1D1 +:108C7000DE59CCFC1C5C98DD24BF6664DA77664F55 +:108C800084E71A9EF4CF4371953D03F13FD2964C91 +:108C9000FBE56C79F2BE6E61FED929CC7BA13E7DED +:108CA00051F5933E65209561F65CF3DB6A178EB44F +:108CB0000F43FE7A49A173479AFD869F87DAF8141D +:108CC000FAAB2A58988BFEC4EA9C2C1ABF3AC97595 +:108CD00016DF9F77263822CE118A5F869E0FA8F175 +:108CE000981FDC9429C50FF39AF7919CCF67C19523 +:108CF00018EF4E7BE0FD8A8148FF174D747E616658 +:108D00005D26D9BFB31B66F4C7D076DA8A1C82E72A +:108D10003C7F27871FE07EDDB415852F607EFE54E3 +:108D2000946B04F279CB1AC58EF1D790E70B97DCE0 +:108D30000AF54362BB76C0F99ED870AA6230C611AC +:108D40008B55921BD786C72761BDAB4175E2126771 +:108D500032FB925B91CF8DF12477DAB9C66526CECE +:108D60006F77E670BD715B0ED71BB709FE2D5DB640 +:108D70002C17CF15B43C0B760AF7D7CD8EFA00C668 +:108D8000813B3B3BD7C338D510B626033F9D51B836 +:108D90003F5E656656E4AF43A6E0BD38FF43F7C6C5 +:108DA000F6ADC509A81707A07CB844DC0571148D81 +:108DB000ABE14B1B7FA61857EB477BEF20FA5568BA +:108DC00047C47CCF2E7F7112FA0B6737E624B03090 +:108DD000BC9FC57501BEE7807E7C2D423CB8304704 +:108DE000CB4FF8A9AC1279C443A6BA34DCCF05BF87 +:108DF000FE74B87FFED5B35156E44BF0EBE5E726A1 +:108E00006E57C09F979E83FC48705BBCA74E8DF742 +:108E100044D0475AA9F7F797E7D822FAFB9AFC5DA6 +:108E2000A2D7847FDF9677E9766DE7BA9ABD4018BE +:108E300010886274CEE0FDB2989F5EC7F397B3EAE4 +:108E40002C760BE0F734CA17EE0B6E56B9BF68E507 +:108E5000F2767A675F3FE615661D67CE00C0B38E77 +:108E6000AA4E07B4DFB7E67E3ADF71E73A8575565A +:108E7000C2E2AE27D64C42713BE7F4AC4C81F6E738 +:108E800036F2F328506DD3C55B07521CEDC75BFF6C +:108E9000AC384BCB3FE9F1BF2907E2AD18F8C5C9A3 +:108EA0009C32FE79DCBE1BD8A8A8DFA5F86FF67A45 +:108EB00028AEFAABB78ACA41F5CF96A6C23AFEA64B +:108EC0009C7C6408CA516C3CE54F9ABD35B439F8B6 +:108ED000D786FE17C7019EB6DBE2EDA83FFEEA5D2E +:108EE0004CCFDBF846F0E9D04D8D6A2AA3F63B86DD +:108EF00040FB5DB678DCEE88B00FC7E9AC3F7F730E +:108F0000F7C2819DF1B9B6DEAF7FC5E9DD66C7372F +:108F1000CE88437FB5F1F7893B06219D63E2EDC81A +:108F20000AB3C5399C2FD7727D74C61AFF02E65169 +:108F3000CFAC9BD809E3C33B4D2D6627F4EBDC593E +:108F40001987F9822F8C4D71762CA17D00E761F491 +:108F5000ABA807079733DA1F1C1C303247266DDD9C +:108F600013FF0C6A36FA316EFE06F70DD18E5F8C58 +:108F7000E6FBF7623FF0CE6D3CCFD6965711F985F0 +:108F80002162BD1D7213B47D207A5E5AC49F7FB5E5 +:108F9000EEF571D8DFD90D263BCEF7AF1B4CD4FFD1 +:108FA0005C88EF0DC08F6736F2F3027377409C9CAC +:108FB000897A4421FE9D0BFC6B45FE5B687299E348 +:108FC0002FE5CBD28D3CBE9E5BAF50BCADF1E75CD4 +:108FD000977F04E15DF0A915FEFD0CA6A303AB5F2E +:108FE00089F8688F5FFFD17C803537723E40CF0FA4 +:108FF0001ADE34BE08F12923FED4E89F50DF7758EB +:109000002ABDE0237CFA4A581EFA0BCBCC2C0FCF9A +:1090100043F90CD14E94FB1FA2E27A631E6AB1950C +:1090200097BF8C8E5B8FE50F51197E9CF70F06FB67 +:109030007E8CB3BCB999C4B7BF541D26057E9D98DC +:10904000D4544666A0D4E032A01D5C66213DA2D770 +:109050004339B9220F98CBA81C96CBCF899B580DCA +:10906000F9175A09FE403AFA2F95310917F0287975 +:10907000BF173A4FC4FDDECA2109F76683E739F806 +:1090800085F48946E0F3CAFE099BB3002ECE4DE37A +:10909000709F844213C0B5B51913CBA0FD2DB92E16 +:1090A000676ED8385ABFF0BC3F3E1F99E219908BCB +:1090B000F6DF6C5B8576E06F4ACB02831A6A7F44E9 +:1090C000619F6E574270938965A0BF3DAC6DFE9164 +:1090D000CB55B9AE1B72233C9FCED80ACC4B4CF774 +:1090E000BD794C217DC6DC56A0E778C17FD3ADB6F3 +:1090F00000E9B955A6E636FEC8423D156F44BA8F61 +:1091000013641F6F0C34E2FB3DD872FB9756721547 +:10911000D7FD9CD8BEFE0741655F6AFDC1FAFE66B9 +:1091200082F5025D1517D01A444C01244F057DA726 +:10913000EC78F347EC77998F3545111DA6DA910F3E +:1091400015E631FC0CE5FC18E08B3E58023F40BBB5 +:10915000459BBFDD87623147F3B33C45E42FDE63B7 +:10916000E7EB619EC1C4AFF70A7EFDCACB6A3055FA +:10917000343E188CC3A3B0CDE302B9A81FCA554F23 +:1091800015D2E1AB75CBD21601FF7CFB9AC539161F +:10919000DA9FF1BF1E8776759EF0F7D945357003CB +:1091A000D41FCCECB17E75187F2DCCE576BF39335A +:1091B00090711FEA994C1EAFB28B7B33EE83F6E5BC +:1091C00059A30A5713165C77E786ED4F8E33463E58 +:1091D000BF31298DFBEB6C03B7C71623F3C52650AF +:1091E000C9E2004FA3602E45782E156095F6F3FD79 +:1091F000D41EDBC5A15FE39891CCF77B981BF59655 +:10920000465F8D6E97D013A68C7EBDC1CA4CB8DE6A +:109210001E6C9D1DED9346D7AF843C7E65E572388C +:109220005CB5919E5AB499E7F516295CDF2EDAA950 +:10923000F0FCE625F676F34AD4C955EB66903ED3AA +:10924000F49803FE217FCDB5BBE3038E7FC0EEAE65 +:109250002BBD2A7DB65ED3677D595FE4BF2BF94BEA +:109260009A1E03F2BC98DBF11AE885288375CF16A5 +:10927000731CAE4E7518112F1DAD4ED4E78B9ECECC +:10928000263BC92EAE65E1EDD8BA44E2DF95992AB6 +:10929000D1B5A2219539E0D19C0685CEC98E6D4805 +:1092A0002438AE3585E08A3F742EC175B7ED83FE54 +:1092B000A13BC1675F78BBC0C3F33456ECDFCDB4CC +:1092C00079E4D7A3FD39678379009EDDB65594779D +:1092D00074B3B67848F9594118B806E5CE65F2710D +:1092E000FA586B49FEC5BA1609B95A7488DBEB45C2 +:1092F000C3F87EA1D1D7231EE96F3AA8323FC03709 +:109300001D520B03D07499D0E79664037384D12D5A +:10931000CA11CD1C61F4613E5710E3ADC9825FEE06 +:109320008FE27A3F262F416A37D9368BF82798315A +:10933000E220AE37D6D945EA9779B87FACF1D5248B +:1093400091371FC75A96A39DBC6932D487F5672A07 +:10935000FE8EEC86A958F6AB012FA72FC74FCD1A6A +:109360003FF5603D889F74F801F9207B7FEE28BFB0 +:109370007F025EC96F8B019E74D0C4FC50BF42E077 +:1093800005FD568C7FCEB962496E34BE0BA2DD035B +:109390003D175F24E3AD834BC65B62B98C9F8E6E35 +:1093A000191F9D276749F5299E9E527D6A553F09E1 +:1093B0004EAF192CB5EFBAB84482337DA3A5F6D9C8 +:1093C000AB2648704EDDAD52FBEE6BA74BF53DFC76 +:1093D00073A5FAEB362E92E05EF5BF96DAF7695880 +:1093E0002AD5F70DAC96EAFB1F7C4C820B834F49C4 +:1093F000ED071E5B2FD50F6AFAA3543FE4CC6B1226 +:109400003CB4E50DA9FD0DAD7B2478187B5B6A5F4C +:109410006A7D5F8287DB3F91DA8F4C3E25D58F7264 +:109420007C23D58FC9FB5E8257083FA7C2F95FD264 +:109430007B4188D8908F73D23C43BB53DEE78C11BD +:10944000E5EFD86D0A4BC4F8E7E0443BC9FD35C6EB +:1094500081C3BB8B3844F0F10566BB1DCFB35F49B8 +:109460002F66A33F51887C3E96EE559DABE7F90EE3 +:10947000BD5DD7FCB97830CBC6B0713BB8AC10D06D +:1094800087E0C472BB047774274BED3B4F7648F5F9 +:10949000299E3CA93EB5CA29C1E9354552FBAE8B90 +:1094A0005D129CE92B97DA67AF724B704EDD64A9B1 +:1094B0007DF7B51EA9BE87BF4AAABF6E638D04F7AC +:1094C000AA5F2CB5EFD3E093EAFB065649F5FD0FF2 +:1094D000D649706170ADD47EE031BF543FA869A316 +:1094E000543FE44CBD040F6D6990DADFD01A90E070 +:1094F00061EC90D4BED47A448287DB3F92DA8F4C01 +:109500003E29D58F729C95EAE77DE30CD0BED476D8 +:109510007EDF55F3E7C6E47D27B5332581BF8FF99C +:109520006F16EDC4F3FEEDF9F99A1F58E1FC511ADC +:10953000F70703F7CF5FEA9E25FC7FEE272EF3B9EE +:10954000E97C5E021E78053989F729C47F18624DCF +:10955000A57C6412ED5B90C974E07937F083004814 +:10956000306466621C1213F263D37EEE7FF57EECEC +:109570001B10E3A05F7DB6BBE7CF289773EB5F1DA1 +:109580008171CE1CE65B89F300BB1B8FFB58EF4655 +:10959000C9F928AD1C65053C868D7728AA2EADDF5C +:1095A00065E47794B599DAB7F52BF2550AAC6F51AB +:1095B00058FF8F40FC650439ADF3829C41A0FD98B3 +:1095C000D74EF013DE64829FF43AA85CEBCDA3F291 +:1095D00029AF93EAD7798B087EC6EB22D8EF2DA767 +:1095E00072BDD74DCF37782713FC82D743E5466F3E +:1095F00015957FF4D650FD4BDEC504BFE2F55159F9 +:10960000EF5D45CF5FF3D611BCC9BB96E02D5E3F41 +:10961000950DDE8D54BEE1ADA7FA1DDE0682777989 +:10962000030407BC0709DEE30D12BCCF7B8CE0030B +:10963000DE262A0F7ACF50F996B785EADFF1B61207 +:10964000DC2CF613BEEAAE48F7183598B132E207C3 +:10965000CDFF1D87710F324791E9AF52DCA38B3FDD +:10966000F4F4F85A8C632A01F717FD9F2EB9EB9793 +:1096700085C505DF8BF1EE8F66BE2890875A03CF34 +:109680000BD42630BA1FC6847F3E5BF0254BE27EAA +:10969000F92C31AFD9420E0A913FF3883FDFB996DA +:1096A000384B8BB7ED191E350FF933DDE0A3BC83C2 +:1096B0008DDFC3EF9FE131E7811C9DABB9F3008DD6 +:1096C0006777E6E220159640C79B319F7448A53C1A +:1096D0006C7BE3558B7B12EDD6EF3A9B86F6A8FCAC +:1096E000EF2AE5EBDF35C54EC67C4B721EC74B72C9 +:1096F0009E412A7764B83BE33CBFCAA979E16E2555 +:1097000074FF7F3C86E620E795CC61A273B8CCB5A8 +:109710001FAFDEDC040E1FC237331F9525E91E077D +:10972000BE7F0B0418087B065B3222AD473F9F9E2D +:1097300079DC7FEF996790CA8F32DC3D103FA773C9 +:109740005CD27CE2BA3AC47D9C9667705EFFB1F34E +:10975000BB2F95EC10BEB5FCC6CA61E29CD6424553 +:10976000DB07E77EA295697E22D54FBD97E77B3464 +:109770007B79BCADE4FAF05C8D89F4E65425DA8996 +:10978000FEF6B99A7BFBE07EE16D10EFE1FEA9A643 +:1097900047A7026C00782AE3E72EA61E8F253ED34A +:1097A000EB57788FE17EDF54F03F317E54BAF27C84 +:1097B000CABBEEEF4CD82F4B6AA17BABC037A3716D +:1097C000FD7307A9F4FD86770DFE5C45257E312BE0 +:1097D00030FFD949C02F11FC058D2F16887B39DA4F +:1097E00073E0B71B913E7FDD36308FF669760D72E0 +:1097F000203E9719F8BD3ADF5B2A3F9781A97C3C50 +:1098000037129FFF2CDD2F40E702E9372896EE172D +:1098100034AA6CF1AB11F4E9BD828EEF269BCAFD30 +:10982000D4AFBCAFB840D075816857B1E7503ADECD +:109830001B5C70D04471112B68CA7747385755BDEF +:10984000F8C15F740BE3F3EA8693FC3C166BCA0F16 +:109850003F87F5B0E06B8DBF5473ACE7595BF8FC04 +:10986000F8F8C0E7F7083EFF12FDFE711647FCCD81 +:10987000F06A13A02600A5E7DFEC749E4F3BD737B4 +:1098800093B9A99C0DE446BE76FBD6D0BDFAB9AC1F +:109890009E9E2F289A918170356B294B86FE6E5AB9 +:1098A00055BB3F196637B16ECD70CC734FF04FDBAF +:1098B0008F65E506E54B9F83E464058EDFA4D4AC99 +:1098C000E802E3DDFAD2B01598471EA7723AB0B7A6 +:1098D000391D809F5C6AC2A5EB03B97848C805CDE5 +:1098E0005F938BA94B994B490ADD03699393A2BB04 +:1098F0003E4BC53D16630B9D43A9DE6549C0FCC9BF +:109900005CC6ED76280FC4EDB526075F9B38DDBF3A +:109910007E59A17B365F2B8CBEE7D09EDFA0F99FDE +:10992000207F5CEE3E8DE1FCAF8ABC5E8627B95F8E +:1099300076C83E7F6DF00F88CB26FBBD11D7632A1A +:10994000F13CD417CFEBBDA23897C15CBEEEE0CF9F +:10995000E0E704DAEC00FB392694277CC4C4F376F4 +:109960007A7F575B477BF3B498990FF7B394A203C0 +:109970003FA21F72E97C3DC903002FCB904498970A +:109980002C713B22CD63B918FFE04F3C1EF7A53385 +:109990003A17A4C7A762E7E3B4975FB544F3F96841 +:1099A000764A9BE7A5F3E2F47A3F2F93E8AACD0F1E +:1099B00034459E1DC6371AA39D28AF9546CF7B8898 +:1099C0004F2DFFA6C5C50733BF227BC02E2E4BE30C +:1099D000E78F03EDD9E1E6B6783C2B6427B53C165A +:1099E0002B8E9C8F745BEDA4BF263027D98B1EEC89 +:1099F000B8862FCA63A9B84348795E0FADC382FA0F +:109A00001ACA28CCA390BDF4937CC6E0BC685D4123 +:109A1000CC88B03531718487C1C718E9E9C1B8066F +:109A200058EFCE93CC8FE7A91A2F4C2A8D85FA9D3B +:109A3000DF1A290EFA6DCC2BA9F81D899D673F4CC2 +:109A4000C57C4FED852D040F681E7196E7CF8E4FB4 +:109A5000C1FEB69F373B2CE4072C243C6879CAED45 +:109A60008C39711FB4E8231BDD332E3C5A1F437819 +:109A70001379B562B1EEE2F33C1FB20B81411007DE +:109A8000B4985920CC5F36D965B88885C1993824F7 +:109A9000C061798E6B8D1F637B883CC84036303C3B +:109AA000AFC65A1322DEA7D2EF2316287CDE67F258 +:109AB000DC9D7A50FE6C82CAF1FD7715F17583CD7D +:109AC0009F82FE6DE39C1752D0DFFD6DCCDF098FC6 +:109AD0004FFD644E41BCD60DFB0FB22375F06E10E6 +:109AE000E35FA33F8A51FE6B3EE5D76E1076F6A981 +:109AF0008B9FB364C0675D1123FBC9841DD6EAEB5D +:109B00002E9EAB427A5E28B63A502FE48A7C68EDEE +:109B1000F5FF99DC14868F9DE0570780C0DBC1AF4D +:109B20000E80EFBF0DFC6A84F1DE29969BC1AFC6A3 +:109B3000D20F7E3596CF805F8DEDD0AFC6F229F083 +:109B4000ABB15C0B7E35964F825F8DED9E00BF1AE8 +:109B5000CBC7C0AFC6E77517A797D27C8E31BA5F67 +:109B6000BF3426CE80FA15E61F8D79A1C3AE7ED113 +:109B7000888FEBCF1B24FA1637474BF0E0D309212F +:109B8000FA22FD8F7791EA071CCD92EA337D3D25BD +:109B9000B8EBE27E128CF9A1F0F753AB4A2438C53A +:109BA000335A6ADF79F20409EEE8BE556A9F583EDF +:109BB0005DAA7F344E4747FF3C834C47FE7D850BB3 +:109BC000C5363A5FD91E9F3E26E8A2C18FFF4A9D47 +:109BD0001C296F7B570F83140F741173BBBB8783D2 +:109BE0009EEF3B31F0C5DC02A487816F9BBA5A62BD +:109BF000BA015D721F37303C5748270E607E76F100 +:109C0000DEE325E762902FF75698A3903EBB5D25D3 +:109C1000D1082FAD30A784F3515DA6A71FDD53F007 +:109C2000F0F569EF3F5A32E1B2FBE88F21FF75BFD3 +:109C30004CFDE8B959280F97E09155D17E6D088FFA +:109C400013E8FB4ECC5325CD5F2F170C37E953702B +:109C50005CAB8C4F57D6038887A79E30D239ACB601 +:109C6000FEC4FB5A7FC3D58B314DF997CE7FB78B9E +:109C7000B707FF370AF1026349F34B703A86217E3A +:109C80007E27E4ED5F85BCFD56D015E35884999D91 +:109C9000BFA7D1ADAEEAB151B92837457C5EEB6FB5 +:109CA0007C4C417593C89CB5F630BC3E21E6F18CE6 +:109CB00058D73AEC17E08E37BA14C45FC662B78241 +:109CC000F2D6754913C14F09F94EAB69A1E7E9F71F +:109CD00004A8EC5215A4FAE1EA4BB48E363C386580 +:109CE0003CEAE9E417EBD1FA0DBDFFDA21E4B70B4A +:109CF0002E3EFF389FCD85F622CE6777F2D2214ADD +:109D0000A713F57E9CCF25E09A7C84B78975C5F9A9 +:109D10007C04FBC5BAEAAA920EBDE0088DC71CD52B +:109D200086707BD31E3F6D15F8DF2CF0A47F6F9BF0 +:109D3000A9A6BF3D825C69A5664F8B8E1B747A27EE +:109D40005A92FB43F80BB7037FE981F2E873AB62E9 +:109D5000FF8AF038B12D5E9A4AFCB426E6F6B73198 +:109D6000DEBEF1A8CAB8BD1DB71FF5E5FBA32C6484 +:109D70004F1B478D4C0FE7BB06B18EAD02EF837CC6 +:109D8000AE13F740FB316E0BE5E3073257FABDD057 +:109D9000DFE8B1AA3300FD1D6DB327EE187EDE812A +:109DA000DB9309620D7BC64E7C10C77FFF28E80558 +:109DB00047689E5AFDE6F289637A211D839C8EEDE9 +:109DC000E1E74D41AFFD625E7B05BD1A057FEF16F1 +:109DD000F664A7B027DBD19E5890CE45623DDC9E4D +:109DE0006C16F62488F604CA77853D7907ED099448 +:109DF00005A3B2CB486FE22536B22710A0D07982F6 +:109E000005D2BAB47995A7A912BD4624C548F42A4B +:109E1000B3254AF525C65409765DCC92E0EBCFF721 +:109E2000D4D929D9AE0C3E3D5867A74A2478C0D171 +:109E3000D1D2FB95AE8952FDF8A229527D85738659 +:109E400054CFC47E18DFA283327A9D4A71AED87790 +:109E5000D2FCA9F7CB55DAB719F481EA0C97DB42AB +:109E6000D6B64F66C07D32705F1C46ADBF2CA99E32 +:109E7000FCA8A326772A9EDFABAD043E84B2F82867 +:109E8000F869947C04BE06BFB7D03D92FC40F097C1 +:109E9000FA131D5AF87E93B66F3548B7FF343A5F10 +:109EA000DE9F2ABCC2FE94AB673B7E59B7C4ABF2BF +:109EB000CB40BEC8FFFA6DCCED7B916FB67D047EC2 +:109EC0002AFAB91FFD82FC2FCD6FDBFAC52FC8BF60 +:109ED000DDDA262F1E495E0A85DC6E399AD5D0045C +:109EE000F2B63959710A5493BC1469F2D224F4665B +:109EF00079353D1F20DEDB6A72C7A0FFB7F9D85263 +:109F0000D16F981E217F3D4C8F601CC912E4FAE48A +:109F1000D4507D162756787BC67AEAFAEBA78307DA +:109F2000EBDA97E8E0D1BAF61374F0ADBAF6D3A540 +:109F3000FA0658F7E5FCEDCD423F68ED0A8D6ED587 +:109F40001941DF0E382AEB57E6AE96CE3D349E9887 +:109F5000457A73CBF195028F55127DF668E31C05A7 +:109F60003CE75FFA7E89D117D31BF8A0E498D1595A +:109F7000EB08D14FA313C37838ACBF52AB2AC95FEB +:109F8000C3314EDFF6D6B94BE8E71DC2CEBCA1F314 +:109F9000DFD49FCEBF3F1EF8674B9381E2AB2D47C6 +:109FA0002724627FBB2FCEA4F9361C33D03DB217D5 +:109FB0007B8EBFA9B65B687EDA7C0A3F581A83FBAA +:109FC000AC179A0CA4FF0A4DEE447B04BCEBF9AB32 +:109FD000BD7E35BE05072A11F1B21BEC109D1B1684 +:109FE000FA54C3CB9E134F12DEB71D5B948878BF23 +:109FF000A1D520E165688BECAF0F399320C1034FE9 +:10A00000727F10ECAE84DF2BCD5B2F17B83322C3E9 +:10A010005DE4F657E90F6C1774DA26E8B43DCA39E7 +:10A0200039D2BEC6B64FCD55E1DF5538D393E7DB05 +:10A03000CEF4E4F9AFCD4047D4B3174E1B48CF0E52 +:10A04000B1D7AB3511E851DC6CD0D909D96FB8D68E +:10A0500078F5543B7AB1BDF735BD58A27D3F2578E0 +:10A0600063C4F3B1213A8873953A7C6A7EF495E92A +:10A07000A69D47D7D1AF9DF743FDF8F4F134BB0E51 +:10A08000FB69AA247BB326E65DA1CFDF257DFEDE3A +:10A090008F429FFFD889FCA423A33AA7A31C1D6964 +:10A0A000D3E32C365C8F6BE72183CDEFC584FBF9BE +:10A0B0006EC18F3B5DEF8FE983F4ECA6FEAFFA3BF8 +:10A0C000EF0A7FE71DF477BAE33E10F7770EB96623 +:10A0D000707F2759A1EFC52C8DB9DEE889C0A7FF95 +:10A0E000D7FD9CF145B29F53E194FD1C6DFF60B715 +:10A0F0005DA1735863F264BF6737FE827926ABE2D5 +:10A10000C77B5CDB5D132FAB870342BE0F09FABC34 +:10A1100029F4F07E1137EC40FC135DCA055D78BE72 +:10A12000A2F8BCD3E674207DAA785C96574DF1F472 +:10A1300050CDBE7B6BA8FD910BD3CFE3FDFEDDF6CA +:10A1400018CAB3ECC6F9C0128E983CE7F1FB15BBF8 +:10A150005D8A636984B87E488BAC07343F41E3CBAA +:10A16000DDCD9F135FEE6ABDBC3DD5F497D6EE4DB5 +:10A17000F67A29E2E7FA66C6306EB892FED1DBC500 +:10A180002B8DA36F3FC458AF46B23BFA71DCAD01D3 +:10A1900015CF3FEF6C0926E2769D3B7048C57BE00A +:10A1A000C52D019AEF3E97625733A95D299E8B7E9C +:10A1B000F3E27B63F0F9AEF3468385F699EC24B7BE +:10A1C000C5423EDFB968B03909BF2AED73045A3E73 +:10A1D0007F10E5D56755E9BEC8EE8BFD92C2F1F65A +:10A1E000E8752AE993ED651603E697B79F378AF37A +:10A1F000D601F21F76B466D9B0DCEE02F9217D11EA +:10A2000024FCFFFE3A7E4E7527F4C7F58483E6A151 +:10A21000F141E0BCA13CD2F7767E2FC61B72F1B3B0 +:10A2200018C4CF81F37B62505FED6AE1E30C59D231 +:10A23000148371E6DBAD86589E57E99F84CF1B8758 +:10A24000DF6FEB87EB6A31F0FD1BE1D768E3ED2EA2 +:10A250009B4DF9FCDD2D3C0EDB7D9EE78FB6FBF9B7 +:10A26000B93526F498D67EFBF909637A61FEC06F92 +:10A27000A2F643987F651CB4DBDF71EB7574BEC634 +:10A28000378F85EBBD52BBECE794B4E8EC93671EC7 +:10A29000C981468723DF4DB8B192CED7733D39CA05 +:10A2A00028EB975DE797264DC0F16D7C7CE6E7EFE4 +:10A2B0006BF119FE18C3BEBB523BFCE68915D8DF13 +:10A2C000667ECE6C884DD6674786CDF8FD7C3CFF18 +:10A2D000BF2986ECEC765C3FF67F9451FE6C77F9F3 +:10A2E000E3A57198B76E664EEEC7C97ABDF4C2A6F3 +:10A2F000BD71D0FEBD0D0AE177649EBCDE9DAEEC63 +:10A3000087310EBED0CCF1ABE59334B9DCD39C7071 +:10A310001BE9A732781BF0F85EF9EB94C79EE39730 +:10A32000FB19B831469AF7FCA6045DFC26E7C7C1C5 +:10A33000DFD4F203B68A01A1F8ADB095E7D707FEE6 +:10A3400034A17F00E65B5CC6CFCFEBF3E2A38C16B3 +:10A35000D9CFD2E5C50BF57971BD3D17FED800B157 +:10A36000AF7189FF23EC9C966FD8660A4C715F83AE +:10A37000FF30C808A10B9DEBF5241600FEDF10FE90 +:10A38000E52073DDDD29202A5B55DF1016E6173046 +:10A39000BB8F250D08C5B7834FCBF140D171992FE5 +:10A3A000217EFC12E3C955B8A74972E0E379D0AB2E +:10A3B000F433D6C4F46E6802BA0E3CCAC47EC7BF7A +:10A3C000EC45BE6AF842DBCF00D7A313EECF33F2E1 +:10A3D000B71BBF3013DF6D19CEED94E6A768FB34D1 +:10A3E00037B2A6E5A50A9ECBB6AE68027C6E3A32BD +:10A3F0002B7501F4FFC1C7B4DDC9B6146ADFA7AF7E +:10A4000093E2CB815A1EEAB8C1975880FEBA4592B2 +:10A410006BADBEE1F8D218FCBEC885A081F8B4F1DE +:10A420002333C3BF0FD0B0C342FB390DC7CCB4DF59 +:10A43000B26D0797132DEFACF9F96F097D7E50F8D7 +:10A44000BD0784DFB24FF82D7B84DF12107ECB2E48 +:10A45000E1B7EC107ECB1BC26E6E3A2EE46F498CD6 +:10A460009F7FC796E765B579DED1BDE98411165C9B +:10A47000FDF180B50186F65C9693510E594E462645 +:10A48000CBFA63B83D556A5F6ACD96EA87B1EBA413 +:10A49000FA1B5AFBE9E291C1BA78A444E78F8C9188 +:10A4A000E5F26858BC4BF1B51CEFDE141EEF6622D6 +:10A4B0009D781CB8ADE931A2E3B6D359F1E17ED95C +:10A4C0001B426EB69DE6F6F98D33E76223F96D67A0 +:10A4D000043DBE16F468167ECA4D29AEDBF30B317F +:10A4E000AE3867C6731FEDF1B3F6BEF6DE19FFA9ED +:10A4F000B870FBF705058D21F8DB2D9FE452FEE4D3 +:10A500002AE563592C3FE7B65989A6FBF757BAD716 +:10A51000F29BFC2CB10F51D387EF8BD60CC4F20504 +:10A52000933B15EF3F6D56DC53508FFB7E678EF8E3 +:10A53000F72496E72B9AF037A07DE04792E1E725D4 +:10A54000C588FC1525C067996739E2C78AF13A3496 +:10A55000526D6E86EBDA64620D68E7998B39EC9D7B +:10A5600018172118E7875E9ED5F9302F25C8F78F79 +:10A57000C1BCD2F73EF068167E770B4BDC27B35890 +:10A58000F9BD83E87C4F5D7E21FF9E6D7C3FECB77B +:10A59000249BEFA306487F4F11FD1A6276A4933DDA +:10A5A0006D4FAFEAE25C364FBE8FA2E79706A16718 +:10A5B000DFC8744F89F41D8C3F0AFC6CFB6A9C8ACF +:10A5C000E31658E35CFCBB902E15EF81BDF1F5E876 +:10A5D000986911F86C7FEF697FCC0FE38382608DFF +:10A5E0002AFE4E8541CE6F190248EF0B3633C9F56E +:10A5F000605C70C2A5FD0D3923FB79839AE4F83FB6 +:10A60000B4BF5FA7E079B3367E428220FD8FF0EFC2 +:10A61000695C899FF4FBF6C7F3B5F3929E4FF01C7B +:10A62000B11A6FA3F3359B8E58D7A31FA9CFF71D7F +:10A63000FE80EB71FDFC1B3F98948AFED7E6A137A4 +:10A64000A7A21C6F41054FDFEF5938C925C1B07E65 +:10A650001BEA7B26BEB355CDEB476970CD243C3F4A +:10A66000B365186FFF49FE9127F17B605B6E13F5B0 +:10A67000BE4778BD06B3459386216C32103CA917BE +:10A68000B487FE7EEAE93A8EFC199DEF3A81E59F98 +:10A690005076A01CD1D3F519C2C791C760DD477BA6 +:10A6A000B84E86C3893D5CA7C2E1CD6DF6A5C5163F +:10A6B000BE7FACF1E1E1631384DDE1741FAFC5350A +:10A6C000C55797E7FF77C1A76F0B7D7548D88F37C0 +:10A6D00085FDD88FF683E2616E3F1AC5BEF16E61CB +:10A6E0003F768AB8371477B9857F3159C4C33C0E99 +:10A6F0002B185ACAE35EBB96E7CF30468A87C61549 +:10A70000C87EE2D87CD9AE8CEE9628F169795AAA37 +:10A710002E4ECED6C5C9B25D2931F6D7C5C98375CF +:10A7200071B21CF716378FD6C5C913A4F6C7F31D2F +:10A7300044D7A2E3B7EAE2E5E952BB101DE57D9BF1 +:10A7400010BD6644A4E396E2190FFEDFA263E4FDA8 +:10A750009AFFFFE8F80FCAA3CD20EDDFE8CB77849E +:10A76000FD7F4BD88D83C20F3820F21CFB843FB78E +:10A7700007E9D81DFD3AA7F0EBF8390E2D0FF28648 +:10A78000C8433588731C5BC4BEDB2691875A56FCD0 +:10A790003D3FC77191093ABE1B918E154ED9CF1B13 +:10A7A0009327D371942351E7F7C97EDE70BBECE7A2 +:10A7B000955A653A0E63FD757E9F4CC7A12D253ACB +:10A7C000BF6FB4CE4EC9E738C02F78B45721DE4BE7 +:10A7D00090CF731406E5F31C7AFBAEDD57D4FC86EC +:10A7E000363FC12BEF336F421B8AFB452966FEBD06 +:10A7F0000DA3A70BFA1D1ABEFCBDF839C42D9FDCB2 +:10A800004EF82C447B1EC17EFFA917B7FB7FEA657B +:10A810006FBB1F19DD0FD39B3EEEFFC48FB5F373E3 +:10A82000552C88DF9FBA8CDFF4275CAFE62F19ED3B +:10A83000350CFD08D562F0E1F777996AA573778743 +:10A84000DBF1A34EF5CAD4BEBFAA60BF9F887E9538 +:10A85000E237F9B9BC5EAECDBDF05E4FA9B305F3EA +:10A86000E29B3F323B6B919FA3F87750F4FED6E119 +:10A870005EB9D49F863F3CFFFF0BB48FF8A158FA16 +:10A88000DEDEE73AFB090B867E5E88E6F091974FA5 +:10A890004DF2A585ECF527BD2E903DCDB57599817E +:10A8A000F1B2B2D697C0F72B03245F7ABFAD5DFF3C +:10A8B00057E7A79DCC7305116FDFA35D2EA47355D9 +:10A8C0002E63BFF6DF7F21DA7D17FF1E8C4BC5712B +:10A8D000353C69F58704DD0F8BFEDAF0A2F1157EB9 +:10A8E0009F2621EC1EAC6EFE1ABE561ED91BC42339 +:10A8F0008CD7BA1E6D1D11F8C77D05BFFB7BA2AFBB +:10A900008E7FD858A7B8A71BD9EF33093F329CFEDA +:10A9100083695D7E6DFD6C783FBCFFA2DD5BE7FA6D +:10A9200050BB339360AFB367821CDD7E54A5730EBA +:10A930004CEC831BDBE859ACA09D318E505862581B +:10A94000DE55BF9FA8CF1FE8CF9515377791E0EB75 +:10A95000CFCBE7CA5C177B5ED6AE94D986E8EC52C3 +:10A96000A9CE6E8DD1D9B5893ABB27E7C58DCCA8C4 +:10A970007D6748ECD72B0EFCFE8E916328BC5E7C75 +:10A980000788E37B793BF2DB767EB69783F0DE26A1 +:10A990001FEB9883D3CF27DD33516D1EA2F3A303A2 +:10A9A000343BE6A4B8D71C1844DFF3343BE5BFCFF3 +:10A9B000E0F75A3F2ECBC17B368CCA67BCF68FCBF3 +:10A9C000E83E4E32954F791DF47CAD378FCA27BDD6 +:10A9D0004E7AFE84B788CAC7BC2E2AEBBCE5543E2B +:10A9E000E47553BBD5DEC904AFF27AA8CC02F706F2 +:10A9F000FFDE40968F3961C62C7B158C1786E74C9D +:10AA00001FCC230C8F5D17DB2538BD26596A9F5A52 +:10AA1000E590EA533C79527DE7C94E09EEE82E9263 +:10AA2000DA2796BB24B883AB5C6A1FEB744B704C7F +:10AA3000DE64A97D94C323D5EFB97E707CD365E431 +:10AA4000B9CEEB3A817858ED759FE0782A3FC1F195 +:10AA50003399CAB9BD3B107DEDC67A17DA6D7BBE5E +:10AA60009DE1F976B395DFFBEE60B42B1DC2FAEFE2 +:10AA7000E082FEA4F9427F523CE7E7E789F3DC2756 +:10AA8000E4794F96DE0319243BA9F931C3D5B458B4 +:10AA90008CC71E34D9FFBD3FCCE381E12AC37B2B99 +:10AAA00047CA26525E04AF6CB2087AF40BE19FC627 +:10AAB000F4B652BC38FE0985E23B584905E61167F9 +:10AAC0001DCD7686FF3D28AD3CFC1BFEBDA1983D0B +:10AAD000DB1C98171B5F3C2D312A2CFE1B1FF8B185 +:10AAE0002C85FAEB3B200AE6317EED34F38CFCD06A +:10AAF000FAB476B39E90FDD110FFFBADC21FA775CF +:10AB00006AFA69B57D3D3D5F9D77F97D9BB3625DD6 +:10AB10005F097FED0BE1AF9D127EF749E1777F2A58 +:10AB2000FCEEE3C2EFFE58F8DDC784DFFDA1F0D7ED +:10AB30008E0A7FED3DE177AF147EF7EABCF5F4773E +:10AB4000AD2E6C54987A99F3A57337C8EBAC5A279D +:10AB5000EF1BCE7A42F6BB673E24FB6BD397CB7ECE +:10AB6000F71D8B657FEDB61AD95F9B5225EBC75B4E +:10AB70003CA5127CF364392F77935BDE37D4E8343D +:10AB8000B15CD6939664D95F6B6FBD5B03A354FC35 +:10AB90003B2448CC5361F630EC7BF0D279C702BB42 +:10ABA000AB14F76B0A997B19EEE70C3504DFC7FD90 +:10ABB00026F6A14ADF816CC0370681BC5E1830766C +:10ABC000BC23CCEEF864BC4E3D2EE7476EBD47F685 +:10ABD000832BE7C9F18CB95CF6835D69F27EEC44A6 +:10ABE0009DDD61C21E9AF9EFACCC7D793B648899FA +:10ABF00047F795AED51E9999FEFC18B747346E9667 +:10AC0000544FF628AA0F3F273140DC53A88D1AF87D +:10AC10000EEEDFEDF988DF2F00B407BBC1FBD733A1 +:10AC20008E6FB375247D3F6EA789DF1BD89D62733D +:10AC30002E85AAEB2FF2FB01ACD548E7C73C786F15 +:10AC4000240BFB95CF8F15068DD2F932B3AE3E0D96 +:10AC50006DE265E7C3CFD1FDEFCD479CE3E8C3FAD2 +:10AC6000D0F988A6C8F70DDAFC381D9F6AFAA7202C +:10AC7000C0FDA38276FDA3A9F49D31E3878CEED9B4 +:10AC80005B0C2D679EC3FB515FF23CEC3026C76D19 +:10AC9000378E95E3B6E1F6CBC76DA31C32BF8EC9E4 +:10ACA00093F5408553D60397F8354DFC1C627B7EA7 +:10ACB000CD4D7DB2B47B3A849FA89C7D317C1F939F +:10ACC000F3CF10B1CE47CD6EBABFB23C9D119D8679 +:10ACD000D8F979C55ADCB7C1F37F1FF07B2F46E660 +:10ACE0004EEC83E5E911E2FCE25827F5D7CCE955B3 +:10ACF00004FF7ECEBAF47CA2256894BEBB61646179 +:10AD0000F485FA39C85F1D437CF47F675EE2FB0877 +:10AD10001A9FD912AEB07FE793FC40AD1C1674A900 +:10AD2000B88EFD76BE8FBA3F5813C4EF447E9FCCD9 +:10AD3000F314F7A74D30F2EFB6B86CC3812E23C4DD +:10AD4000FA8BC43ED9162F0BA23FB7C96BA552DBB5 +:10AD5000FF5C99BC2811EDE6960C4F2A9E0BDCD2C5 +:10AD6000B1C372067A7AB3A9435AA47B048DA68133 +:10AD70006467B734A618D10F1D66B41BE97B52690E +:10AD8000D355CCCF8EC4FB26490833DAA7DBE40DBC +:10AD900004CBE85CA887CE11C13A4AD18F2DB34FBE +:10ADA000A3BFF7D8F801C88503FDE30E53F1BD7DBD +:10ADB0001DF9F96B8B9D9F6F1D91349BE855E0E465 +:10ADC000DFEF2B48B339FDD85D32FF8E4F15FCE322 +:10ADD00074E17602E45EFABECF40160623BD74F03D +:10ADE000D37A3DA03B97B8F298383FD71479DFE685 +:10ADF00033E1576C117987E3C2AFF858F8154784EF +:10AE00005FB15297077A5FF815FB441EE880C8E7E8 +:10AE10001D14F9BCB7845FA19DBFD6F822791573C4 +:10AE200058E2197B771AC773CA2AC55F0EEB289DB3 +:10AE3000C9E1E4C57C7FB4ABA7CE5D5280F526E7BF +:10AE4000485847F2E4BAE1B88E94A92D744F69B21C +:10AE5000C7EC7029783FE929BA17A5DD0BBB93A38E +:10AE600086DD3E7304E9DF3B3DE2DCB1DA5C48FCA1 +:10AE7000F58489BE93A47D3F6EF24CF97B4AD3756D +:10AE8000F8BD5D079B15AE47DED1E4A23FEB1F8EF8 +:10AE9000F714D136EA4E719E172F5D459097B50293 +:10AEA000EF1A5E1AAF1F1DCBD7C1F7432DA29FA388 +:10AEB000C5B7C6623F1FA4F1FE260879D0F7B75A7E +:10AEC000EB4FDCA78916F47FB4E7E5CF9D1EF63281 +:10AED000E99CE961419FB67E4B1E34E1F7B4270738 +:10AEE0001E48477909DDAB71C5F2FB2B63FF3D13AB +:10AEF000E8B45ADC43D0F4EACD427EF5E37DE0BD10 +:10AF0000FCFD9D0F4AA698F07BE837057EC5FF1E25 +:10AF1000B0B12639FCBCEF07383FD095F7DF743766 +:10AF2000FD1DC96006E707CB8D16077E67B06B9ADB +:10AF30006B05E23139CD395CE447C99EFD3FEE81B6 +:10AF4000191B0080000000001F8B0800000000009B +:10AF5000000BED7D0B7854D5B9E8DAF34E32810958 +:10AF6000049C604227E161AC04262FF260083B108C +:10AF7000344524131221981026099068D11BAA3D4C +:10AF8000D27B68B321218418799C6B3D50090EF85F +:10AF900068CFB99E1AACD7D27EEA8D8AD6DEA312CC +:10AFA0007A430B6DC5F092F66B7B2F5ED49ED3A3D4 +:10AFB0001FF7FFFFB5D6CCDE3B93800AADF634F920 +:10AFC00074B3F65E7BAD7FFD8FF53FD78E93C18F57 +:10AFD0008F314BC25E65423263CE62858D87F6A6A5 +:10AFE0009245694333185B5EDDBC98CD64EC12FE7C +:10AFF000CC83E7CCA60D65E24BCC724981FF8799E3 +:10B00000CF361BEFE31DC37376291DFFDFCA82898C +:10B01000703F78CB6F719C6AD6EAEF87FBDD79EAE7 +:10B02000040F8CCFEAEC67875C8C65C2EFA58CE8D7 +:10B030003CF25ACD6CF45C8EB76431F497E3339AEA +:10B04000CFF07C6B17F339C742E323806E22BC2F0D +:10B050009E6DB5855D385F77F05E97EA662C23D5E7 +:10B06000D2E004782AD236AF64B06E56E9F44CC30D +:10B07000F7030BDFCECD836BE65A1F2E0FFB354354 +:10B08000BFE33776A6F96644E1DABA8D9584609E0F +:10B09000AD697FE75D9B88FD3E6C0B613F3BABE993 +:10B0A00083F1BBE7FF2E35DD1DED7F7056E94CFFC8 +:10B0B0000418B01CFE97C2D8744728C33F63F87ABF +:10B0C00019D3189B80F88F670CE038D3A0849D00BB +:10B0D000574D0FE06F0C3EBFD082F71B7A9CBE6EBF +:10B0E0000490A9EEDB609D6BF93259C3B48EFC7EEF +:10B0F000B8AEED01BA61FFDDF6D3882F17FC227ED2 +:10B10000D35A6DA723F8C2FE4CD7C6794C6D07CE33 +:10B1100001F0DEE24F4C7EF726F8772ECBBD64E5DA +:10B12000F447FCD688BE710D556319D2D30BC82CD9 +:10B130001ABEAE15FF6665FDE319310CCB8FDE3FFD +:10B14000B17A4A7C08DF43BE7109BE9A453CE97377 +:10B15000CC46FA73BEAA167C05ACF912F19566D7F7 +:10B160002270C2BAD87DF628DF6518C66308EF32B0 +:10B170007D9BDE578F4D05F8570AFE5F1968E1F891 +:10B18000BA8FF3A30B6E8A71A2FC06E3044DFC4751 +:10B19000F49A28E084716E2F2BFB1F3F059C3DBE67 +:10B1A00033E336A4D3EDDFB4322BCC5705DDB05DED +:10B1B00055A384C3D05E16B899E461997E7CB85FCC +:10B1C0005D6D3FABA7CF3B1BA7D038ABCAF9386C3E +:10B1D000A36E7E826F27E133C8D8168F8EDFDE4DD7 +:10B1E000675319E0F1A53DCDFBF0FD73BB9C0CF955 +:10B1F00088E1BBB391EE1CAFC7807791FFCF6F534F +:10B20000C20700EEB37B9C04E7BB6B943043FA3378 +:10B21000CF93FD70FF017F12CD732E2EB4EF1BF084 +:10B22000BC716B825F83F5768D6BBD2708F39E4BF7 +:10B230000AD5E3388D5B6FB268D0BF2B5E7365E0D3 +:10B24000B88D56FF019862850D703A0EAEF0EFEBA7 +:10B25000E1DAD0A5A31FFC37E85788EF975858A824 +:10B26000CF3D9C7FDCD90ACD8F0877EAE05F926101 +:10B2700021788F3FE42478C764FB689C86C2383508 +:10B280006E0CD291A9B61C8027559D8C709E55409E +:10B290003E81DFCEDCAE68881F66E374715C3F6977 +:10B2A0003FCAD33F89759E7DB06032F2F39924FE88 +:10B2B000FCB4373E8CEB3AEDE36DCDEB0E3F81B243 +:10B2C000610B652E4BE4EB50800F1A055C8D3E8BB5 +:10B2D0001A07F46D7C68F95791CE8DDE9EF5783DA6 +:10B2E00096A8252AF0FEF93D5686F8467CB872F0FD +:10B2F0007971333E37E3E5037F06C183F81B0F788E +:10B300007B77777B6208D6C13C2CE49818C543C391 +:10B31000CE1FDEAFCC2479D6B8BC733951986E3FBE +:10B3200006FE5DE17368E5300E3B3C95F876858757 +:10B33000F3ADA368CB840CDECD1DE10F1FB57B7090 +:10B340007F6F14ED06E45BC0EB0A949799888F71C8 +:10B35000B3FBE17ECD6A23DF6E49DEFC6015AC7382 +:10B360004DA19D59E1F91AAFCD2037951B8C720480 +:10B37000EB36B4C767335A77D738C19F9D9C3F815E +:10B38000D32707B3A27CD1EBB748BEF0D947C1BFE2 +:10B3900019AF5F343C9C467E057D7326CDB7AF88E0 +:10B3A000F402F00F878B5975F2D0D0E524BE67C048 +:10B3B0001E8827E04F476556945F247E1A766F22D9 +:10B3C0007E6C107CD7D803FC3346C747267CE19AB5 +:10B3D0006D729E29513EA3E731F8EC453F875BCA69 +:10B3E0005F030BD633EB70B99657A27331D0B36FAE +:10B3F0005D8D16C0513492E31D25C56389DF053D7F +:10B40000B8EAA11F17D22D51D2476383B89FBBC59D +:10B4100043CF06E54419E81BABD8671DEA40B81FC7 +:10B42000EE276DB0D27DD42F36E88FD33224F8F3D7 +:10B43000054F4F87769C68BB055DAD56770AE22BBA +:10B440009119ED9E71CCA44FFC9CAE52CFEEB4B3DB +:10B4500014DC8FE3C4FEDEBC708A82FD762A0AD932 +:10B46000078E32231F584D7A605AB685D62FF1C009 +:10B4700084BE75B8F87AE3522C24171FA482425573 +:10B48000A2F87088F58FEBF7F5F5C3F37AAFCB1F11 +:10B49000463E621ED20FA53053BF6EDEEAC509AC30 +:10B4A0005F47E7859EF186F62DDEEB0DFDBFE29B43 +:10B4B00062787E6BE64D86E7B7F9730D6D07D3E9C9 +:10B4C00075847388E3DD21F0AC7B2EF5F200D2B1F8 +:10B4D0004AAC638723E40DC23E5CE55D4BFA7953C9 +:10B4E000C95DDE215887D3CBE5CF81F6248C1B378D +:10B4F0006DB587EC08A19F0BE117E9D08E83A444BA +:10B50000F9CC61C2B359FECCF6E4DA6CB07B12A080 +:10B51000F165F665B27BDCE362DA3766FB0D7484B5 +:10B5200005F9355ED06BA1D54D7A636B35D8730ABA +:10B53000DA974BB9BD94F95F88AE41D18F6916B2E5 +:10B540005B9789F54BFBEBAD36C6FA6F007CCCE719 +:10B5500076D6B2C20BD57ABB5C5EBB453FD98E2F87 +:10B56000DCAFAA31F4694736DF371302FCF9321732 +:10B57000B3A11E92CFB764737DBC4CE8ED2520C704 +:10B58000C8B71578D5D9ADBB049FEE8AF02B1BC880 +:10B59000D1CBE9538A0DF110279AFB596857F6046D +:10B5A000C4B3469DACEE2023F9FE08B03B9BEC18DB +:10B5B000FA29CD5EDDFB75F447AA13FDE85B38D5AB +:10B5C0008627BE0DF88BAF4EF05B7C517E27BF0304 +:10B5D000DAC9999CDF6B525D7E7AACA983536747C9 +:10B5E000EDB26A61DF4D60AD2407C3FC1817E7CBED +:10B5F00091FD18BEFFC8F99C62FF67D68D7EE2BB45 +:10B6000020DFF72DF08B7C777B8D91AF968746E717 +:10B61000B31F640BFBBA8015109F85D6115F3845A8 +:10B620009F1D93815F389E883FE2257E85BD6DB763 +:10B63000B17E1BD0E908D21F8074DB5922AE734063 +:10B640007D85E4622093D9F57C100C58D5B08E8EA0 +:10B6500003452CDE03FA65C0CED27641BF31EAF253 +:10B66000451E58DF40A933B18136D5B0C16E3F02C7 +:10B67000E39E72B311ED7DB33C4C877FA01ED89A38 +:10B68000F6AE17E1D96A67B4DF3376B106E1DA2E98 +:10B69000DBDAEF6A4AB11D27DB1FEE56A1FF93F1FB +:10B6A000BCFD61F6A5DD5A2AD18BF82A41D0234191 +:10B6B000DAEF337478053AB89273689F7199F06D38 +:10B6C000B6EBA59E30EFC3E6797F27F70341A7913C +:10B6D000D63D0C5E60CD2F8F2E17EFA35CB8C05FF8 +:10B6E000D6CBC5F071FAC97EAF15EBB6243C9F16D8 +:10B6F0008AE14746F0BFCEFE7BBDBF00783EA4A0E6 +:10B70000DDABC2DBB319571D308E52F8DABFA3FE92 +:10B7100057766BE3108F56E8807ADECE42048F9422 +:10B72000D738E4032BE2BD9F9E83FE1D52A6E02086 +:10B73000751EE45F05FA5F42FC5CE93E59CEF5DA1E +:10B740000AB1FF55E094305E45172B45FF3C6E4D26 +:10B75000D3816DA8E754275A1470FF4229C207CF3E +:10B7600055275D2FA84837E06783DE79A9E44FBFEE +:10B77000790CDEEB1CB0FA9D306E67E0C70CEDEE85 +:10B780008B33981F17DD811D01BEFA9067A1C38717 +:10B7900072D37FBC631A63A7DAD840997D38BC03A3 +:10B7A0002FC7397CB0D8909634F35918A7ABD0E99D +:10B7B000417BEE9D8D5607D26960738386C83891B0 +:10B7C000A2F52970BFCB1662E8DF3B36B62F44FEE8 +:10B7D0003E61D7FCE3E0DAB559BB1BFD10D5B7B825 +:10B7E0003C1DE03FD0652B0FC7D89FD7E7707FE7A0 +:10B7F000AD97EEA4F51F4971F8E360DC218C6F0072 +:10B80000FD8ED877A6F971DC4DFF2D0DC73FB266CE +:10B81000ABFF6580EBC826277A52ECC81E570D8E09 +:10B820007B646EB377AD6E7CD7F58E56BC3F30C966 +:10B83000E19842EB792FD18BEBD9983B1E79B3334A +:10B84000C531B9099FAF6D66B85E8777A71DD7E789 +:10B85000B2B1DDB8BF7CC97BE1CD02F4977C96D94B +:10B86000B740FFFFEA0FDD9A83FEC986530B512FC5 +:10B8700039CA92B6E0B553C029F72B49DFA19446E7 +:10B8800017EE639DAB9B781CC66B69203AA6588265 +:10B89000B81F7506D6B8A6CFE0F79BC70CC74B27D5 +:10B8A000C65D66219C6BBD6BB3B0DF876D21E83749 +:10B8B00034D759130B8FCD395C8FB9DA9B333600EF +:10B8C000DC9D7B5C1EC44FA712DADD0078D5D2DD8B +:10B8D000FE277CC3DFFB81784FF207D089E4707DBF +:10B8E000CEA43D9A0DED554E47C08BCBAED39B07F2 +:10B8F0006795AECBD1ED93C3E64DE9247DD1A97018 +:10B90000B9FE414ECE1E0DC6C9F587EECB81F98E2C +:10B910007481ACCDA2754E467B7F24F91912CF3BC2 +:10B9200037C1BA63C8FFD06A2BBB612CBF5E07D793 +:10B93000E99BAD939518F8199ADB948171AA23F0CD +:10B94000DC02E30CED71F12BDCCF40FE1A813FF3FA +:10B9500072B8BECF9A19ECC6F5B2197E8AF3BD99BA +:10B960001DECA1366BF562FB0BC0BF8F7D4EF897C7 +:10B97000B149C0AFCFCCDCA3814BCA3CE30C76EB22 +:10B9800048FB67900DD9703FDE54F2A716F407BA52 +:10B99000B31C3EA72E2E28EDE825995CBF05A79D78 +:10B9A000CD839D9B55CD584BFE0DD8CB141FF4C0B5 +:10B9B0006FACF86010E3813A7DB8C4D496F6E9BF65 +:10B9C000E608FB45D8C9A9BE9DC1F9E87FBC61F571 +:10B9D00087016F69F802B42B172B61B4D73795FC38 +:10B9E00033D9F14CD8714B049CBF6C73B1B2692C44 +:10B9F000E2CFAD10F7135A4E3D8EFE7502C63F31B1 +:10BA00005EDBE2F451FC05890FF35789F549BF8EDF +:10BA1000EC4858CF8A16110765BBB8BEB106F29143 +:10BA20001F601D06BF24C84C7EC86ABBC19FAB35D2 +:10BA3000D90F66BFA1CA6437EC40DB09ED425B9FBA +:10BA40000BF9E9FD193947327CF458EB97F63DF4D0 +:10BA50000B150E6E19D2ED3F8342FFFCAC4D3D81BC +:10BA6000FA684BF03117C6E1BB6D6117EA93EEF24D +:10BA70007B1391EFBAEBACE5C86F036DE5D4EFAD86 +:10BA8000B6205D6DB95C6F54FAD58F703F91F65951 +:10BA90005579E9890E1D5D2BD5AF9CE8D0C15F516A +:10BAA0005869684BFEAAB0B2D6BE18FB4B5EAE8C8E +:10BAB000BBA8CC608F5A9FF28762EC17F21ACF6C4A +:10BAC000EFEBF1382ED768F73E3063FED8D1EC1992 +:10BAD000B94E891FB97EF97C2478FF2347FA279F46 +:10BAE0000DDECC4F08AF194E09FF48FD2B70139B9C +:10BAF00084F076ACD066201D4385B980E7AA326514 +:10BB00000BE6657E26E2953F0B24863580E7D54C13 +:10BB10001EFF8C6FE17E657C59E542DC9F3E29BDAE +:10BB2000EF2854483EAB034A58857FDE2CFCD55F96 +:10BB30006632CA3F80BCBE9908ED5FCCB5F338329F +:10BB40005317DF363BEAA7C6D7F1FCC40E07F3F75D +:10BB5000E37B37BAFD9BE1FE32297F35C63C447555 +:10BB6000B5DDB0CF5498F20EF1A67D6679AEB0BBCC +:10BB70006703DEA744F13E92FF31129F30DB853C24 +:10BB80008C8B99F1738F093F667FA7E279937C5C78 +:10BB9000A1DF73A02BEFD564B433CA14FF34A41F04 +:10BBA0003E82F7E2D583940ED921E548F87B325FD7 +:10BBB000B5636915F97B6FA13D3096F24D93315E07 +:10BBC0002DC7977E5EAE5FFD466EFEC8700C8AF78D +:10BBD000B656C6B61306D14E98C5AFD7C175FAD2C0 +:10BBE0000569B1EC84C1226127C073B40F06F794D4 +:10BBF000F36B91D14E60E5B997C1CB265A6FDCB497 +:10BC0000BCB1B1E46E7056E8E1DC09D17642662B36 +:10BC10002BD3E1FDABD9EA3FE27A2B451C42CE079C +:10BC2000FAFDB0DE0E33CF7728C7C3F15C3E9EF439 +:10BC300085BC5E8E7E364F2B433E7BC0AED6A0BD0C +:10BC4000678E27FD3097DB895D196A0B3E67EE9C96 +:10BC5000CB8CBB49C6AB33B327F2F403C57D4CFE96 +:10BC6000A0F49FF6E3C3FCA85F68F370BF303EF515 +:10BC7000C2610F3C5A971B7A1EF135F74258B380C8 +:10BC8000DC39172B643F395319D93D57EC875D6177 +:10BC9000BF2E146AE0E7AD8D3C1E5F9A6DA3767CE3 +:10BCA000C87A80F605531C275E7D8FFCB02560079F +:10BCB00088B80DD953C7853D1564ADE4EFB9ED6182 +:10BCC00017C62BCC719B9A544BFF74D0EB3585175C +:10BCD000AA7D33E97D43DCA7C69771788278EE812F +:10BCE000EB92208F032DC338108E5F1DEECAC03C2F +:10BCF0009CDFE65719F7F3D0BE58DE747FD6C3BE7B +:10BD0000AB170792F125692F4A7B06F44BD778A42D +:10BD1000CB02C547BEBF294E648E0BC9B88C397E95 +:10BD2000648E177D9C9B4EF490F6978CFF7C946BF1 +:10BD3000B4C3AC3037F6EB2E822D15E4BBDBCED28C +:10BD400076CEE0F11DB4978E94FEC483F68535CF90 +:10BD500014E7BCC2FDAD13F6A133B8AFBE126747FE +:10BD60007B3BE80D513C7189629493C9797C9FF3C8 +:10BD7000E4B9F93C228FDCD9B641BEAFA1BE09A619 +:10BD80003AC2714A741C56987F45F2949CAD4ECAD3 +:10BD9000CB277F2415AFCC0FFE4816FA231ECEDF2B +:10BDA0008513683D4C9DC0CEE8F3C602EE081C2EFC +:10BDB000F05BB23EF9FC2988E7FCE83C97C3DB8ED8 +:10BDC00092629703E31140632BE72B4F247E9F8100 +:10BDD000719D753EBD5D518F798B5CB43B795E433F +:10BDE000DED7C5CF6DC8BFF1A9213518635F5D955A +:10BDF0006731E44F23F1F74C46F922398E8D7937BC +:10BE0000911CA0AC4A78AC31E2F402DED5420E00BF +:10BE1000E12E27B04CD34E2BE375095C4E643EC235 +:10BE200056142C4F87F5366D53286FCCB49AC368DF +:10BE3000DFAF11CF1D22FE66CE23AD117918665DEE +:10BE40004776DAEA878CF9B5C61E63DB6C97CB7848 +:10BE5000BF0D8044B8DB249D40C15B47C7C37E5AF9 +:10BE6000E75F291E241F2ECEFDAA17EB5A3AE342A4 +:10BE7000BB1B30AFDDEBA27808F990282FFDF00B4B +:10BE8000EBD9B6B7F0315CCFF63C2B977B85D7B9B1 +:10BE90001C4E79D835A4E3B7ED82CF66E5F978DC9E +:10BEA00005F72550892C3599E448D6B51C49E1762B +:10BEB000A523C0EDC6A7A6BEBC94E75D797D4B6601 +:10BEC000205ADF520AF8C912F8C99CB6DADF0FD738 +:10BED000AC00AF4B9AF1ACD15FBD35D36857669AD1 +:10BEE000FD5553FB405EECBA96689E4DC4DD05FCE3 +:10BEF00066B9FA5E1BCFB7FC33F8AD787DAACD43A7 +:10BF0000D7EFB779E9DAD7E6233BED99B64CBA4AD1 +:10BF1000BC3F600FD6635E4BC621657CBC3F8FFB88 +:10BF20006F2CC0E1A8106B59684D4D443C1F0D703B +:10BF3000BB70A4FDA5AADC1807BD3D68CCEF2DAFF2 +:10BF400031E6F7EE9BA9BE9407F024CCF4DA43BAAD +:10BF50007CD41AB1FE1D0FF37C931CFFE83739DD4A +:10BF600065FB9C58FFCF045F24BC9C62F701B12A9B +:10BF70001FAABC19E3F6CC937345F6E02F855C2627 +:10BF80006CF6D8312E54D9BFC281E3ACD90DE3B8D9 +:10BF9000AF7C9CAD6913D38CF985AFDD81701C8DAE +:10BFA000E4175AEFC0FCC251915FF843DEBDDF4198 +:10BFB0003F6B569E7A1AF5862B4F3D83F8F883D057 +:10BFC0009BD03EA76FC3CFEB4913478DE3FF212FD3 +:10BFD0007F781CDFBA40698D55D7F2A19017D05BEE +:10BFE00017711EE68AC4D13EE06DAE8FE2F2397E53 +:10BFF000DA7FC95A709CF61FB3966762D8F32C5F3C +:10C000009171B98F490F7AA51E0C5E8A359ED5595C +:10C010003919F17DCECEEB62CCE3C5E53B247CCE75 +:10C020007C7C3F35025F5C7E7E74BC1D808301A4F6 +:10C0300093CD9348794D7637E53F251F25D47B6E08 +:10C04000C3BA05702C19EE2F09CF796ECBC338CE49 +:10C05000CFA7F89F6023D3F5B782BFCE0BF93A87FD +:10C06000F205727446C8D729942FB89E14F2F5EBE6 +:10C07000363FB57FD95648EDE36D2AB57FDE564E83 +:10C08000D7C1B620DDFF595B0DB53BDB42743D5A8D +:10C09000F6D8CDB8EF7CF03D85F4F148F0DCF5B88A +:10C0A000D5203F2D7B130CF2B6F6A1F186F6EA1EE1 +:10C0B00063FEBCB1638AA1BD6A83317FBEB2D598ED +:10C0C0003FAF6D9963986F456881499E6F35C97B15 +:10C0D00095A1BD309FDB8955E5B586F79CDE4643CB +:10C0E000BF84A52C148BFEB7E5F3B8C9CB25C56377 +:10C0F000874689733836DCFA36DA2791B62DC4D0F4 +:10C100009E776C5842F71F88E3FB9DF9BD26C1AFAF +:10C110009D65AB83F319DA458BAC7ABBE79E59A1D9 +:10C12000E5F93A7FD0E1E5FED8C5A9D5562FF0D183 +:10C13000D2B2F75EBD0EF82834C0C8EF51C1DCF3AF +:10C14000821D5CD8BA6BC175D0AED6D61BFCC7E2D7 +:10C150009683AF80F8B240D9D1F664783F3F3BD4A4 +:10C1600084E397782FBC82EFCF5F9C6D43367F20AE +:10C1700089913D7A2ECD113E10831FEE1770CBFCB6 +:10C18000D527DDA7CD79FA8C4C568A71E48CCC0B7F +:10C19000A5A8D7A0AD62FEEBE0ACD0FD081FDC5730 +:10C1A000514F3E90B53603F79391F2468FE41BE36F +:10C1B0000912AE1D251C9EA322BF3064CA2FE8E2DF +:10C1C00009EDF9A3C413CE89F786BE1D3B9E704EC0 +:10C1D000E41DCEC9BCC3C35531F30EE7168A7802FD +:10C1E0003CC738C2B93D35FCBA70F4BC835C1FEC67 +:10C1F000477BF20D790761E78BB8F9E02C752F3E8C +:10C20000FF6AB6DA8BD73F66A9FB108F4775F94FE7 +:10C21000CF445DFEB3EC2786FCE7A19CD093F93CAC +:10C220006FCDD0AF6AD7D850DC14CCC706EF89C524 +:10C23000C7CFE4CBF862FF67CACFEAF2A8964B37C4 +:10C24000B12BCE035C71BF425E9762B66F121023B2 +:10C25000E3A276DFD379A19F20DE3A929EF3F1FA32 +:10C260002B4B74FF40E537823D649E4F8E87FA0A60 +:10C27000F5D620480CEE33DB932ED4A19F724CD020 +:10C28000D37C3D9E2FE8C93CC948DFA7F382BF207D +:10C29000FDF36C9F8FEADAC4FD2B85E34947F06D0F +:10C2A000B4633B1BADBE03DC6EA7B8C50D81A470A3 +:10C2B000B72E1F7C11F7CB7C8C3F0E4D7500BDDB7C +:10C2C00043AFB8B11EFC9DBD36AC8861DF4DD4ECE8 +:10C2D00048FF9A4CBEBFCDF786BE34348A9C033FDC +:10C2E0008CB778090E8BA590CFCAAF9A825773FF8F +:10C2F00081BDEF4FF0C178DFEDE5F9AF1B7A57BB99 +:10C300001A75E3DF305BEC97C83379989F54C258B5 +:10C31000A85E1378EFCD02CCAFF82C14E77867E372 +:10C3200007C79663DC51B552DCF19D8D17A97DDC02 +:10C3300067C945F2BDE3FD7FC7B0FF0DDF5C3391F8 +:10C34000FB2D1C1FAB36E63ED99D4E7931C76C984C +:10C35000E7B87A3171CA8C68FE6C95C282B1EC98EC +:10C36000C9B339FF2F525BEF40B816859C0CEB9C8C +:10C370008F376C7D1BDBDF2D557C56F4EB33F93C9E +:10C38000357B6D544F0BF85987ED37FC090CE79D51 +:10C390001F3A68C3FE1F6629EC3AE52AE255BD380C +:10C3A00001E5F01DE4BF18F05F94F22BE468BA0DCC +:10C3B000E43E07F17FD8AD8F534A7ED2F2D4CCD978 +:10C3C00014F70BB504C9CE5D7A19FB7433AFD3FEF5 +:10C3D000DE051BE61EE21F6F9D84F1A561708E00D5 +:10C3E0005F91A0FB1FF3791CF3865EDB9B5F417EB0 +:10C3F000DE68A73A845979C139B3F5FED655DE37E0 +:10C4000064FDDA40213F8F00E634CD03F066DA00A8 +:10C410008E3825DEAF71B9A2F89C4BEC7FD04F1D52 +:10C420000BFD56B1BE7E8CF3319BBAD38AF1C32289 +:10C430003BF9C7CB57DA13912ED17C99DFE06F9887 +:10C44000AF67303F46751A2EBA0E809F8DF912FCE9 +:10C45000014B1C1EDA84DDEF7F449D0A722FEA4AED +:10C46000EF3F74EB2358577ACCC2DB771DBAF5FA4D +:10C47000CDB0A433935B8FDD0EEBEADEA5F837F980 +:10C48000F0BA7F77239EAFD8A0F8CBA16B7DFF8D4C +:10C49000F598626CEE72928D7F7ADBFD3723BF5E7A +:10C4A000F4320FF2F3F214CECF4D832C6C81F62DC3 +:10C4B0003DBB28EF191CB451DD9ACCCB9E4CE179E1 +:10C4C000D97F68EB27B8D1AF5D389BBBD8F833CEA6 +:10C4D0000F70601CB5CC46F9D2F1CCD389FB4BBCB4 +:10C4E0009A5ECAED698F83F23C8B19FB0EC67936D2 +:10C4F00070BFB948D445CA3C163BCBFDDB16F845A6 +:10C500007D32BEDCE81FE79BFC5FA9DFCCF916E0BB +:10C510007F0DEF77CE4E34C4EB468ADBCBEBB360B6 +:10C5200047E0FA9E1379DC4360AF633EF3C760AF28 +:10C53000E3F579B0D7F1FE8B60AFE3B51FEC75BCC6 +:10C54000BE0CF63A5E0F83BD8ED7D7C05EC7EBEB4D +:10C5500060AFE37BFF0BEC75BCBE01F63ADE7F7685 +:10C560002EDFFF3AA739C29B01DE4E3BFB35F29529 +:10C57000562AF2C2224FB62D693AEDEFAE8F80CB2C +:10C58000C19E1A504277213DB43417F51B48BCF0C8 +:10C590001FFF17DBDBD2C90F6136DFA12178AFE3C4 +:10C5A0001BE9FE6E68763918E9FB53479947017B12 +:10C5B000E6FCEDCA4C8CA39EB94DE9C3F6C06D0AEA +:10C5C000D913D351F472A2FB68F1FBBE03B89FB537 +:10C5D0002732C18F4FF6AAC07FE71136E4572DA945 +:10C5E0001EFDD2794ED91E538FCF1B3728C24F1D47 +:10C5F000B74F85356C53E4FBA9BDD8BF43BE2FDAD6 +:10C600008316F9FEBABDE8271F8BCCB7BA564D8505 +:10C6100076867CBEB60EC73F15A9AB9BB712DF1F4F +:10C62000888C3FBB17DF3F9326C7BFB396DA76D916 +:10C63000FEA795D49EC0FBCF7AE1BA47B16EE56AFA +:10C640008FD71EE2FB1FEC63AA3E9FB3A9D84AFB1B +:10C650009EAE1E9CE26E32CF6F49704FBB9278A99E +:10C660002ECF4FF15298CF8E72F6F5D2A4C9A8778B +:10C670004FA5F963FA29E5C591FA5663FC5455783C +:10C68000BDBD8785B03E3E5EDC8FEFE175F48E4C1C +:10C69000DBB03AFA2B8927CABA07194FAC593D7A51 +:10C6A0003CB1A6D4184F5C259E8F144F5C658A2739 +:10C6B000AED868CA43843E593CB18EF5DBD10F63D6 +:10C6C000AA427254E7E97B7522FAFB677D144F6436 +:10C6D000BED729DE2ACF4FE0FF2DB3F1BC196F9FE3 +:10C6E000BF5BF1A25FD17DB73211AF27EF5626A114 +:10C6F0007C9DBD5BF1A0BC7D589041F8CFFF8DFFC4 +:10C70000751FEEB75E8B9FA323F802A62A82AB9318 +:10C710007CDD30CEA9BB9571F8FECAFBD21DC80FD7 +:10C7200060770A7EB4EE45FEB426288676DE64C9BC +:10C730008FE147503EE68D176D6DF95E949F5287ED +:10C740007C7F33B5578414D1FFEB7B51BF1C9B2FEB +:10C75000FB4FACC3E7B74F91E31D20799C9720DBDB +:10C76000BB49FEBA22E37DFF11ECFF0BD490D4DE6F +:10C77000B917E5BDB452E8336D268DDF5927C7FFE1 +:10C780005A2FC6AD6A2DF2FDC524FF4D4CB6C17EB1 +:10C7900087F6AFC4FE70D70F3FAEC5B8D61DF2B94D +:10C7A000F6F123084F9D68AF2BF897BDF8FCAF7EDC +:10C7B0007D7FE6F9CCED956C60E1757951B930EF8C +:10C7C0002B0D45DCDF296C3988EA8BD5B5EEB7A295 +:10C7D0003C46F36A29D541E46F9795EAE7825E7695 +:10C7E00073AC7AFE4B057C9C8D05579A5F8B3DCED2 +:10C7F000DA22BECF75CD6731FDDC83B3E66F2DC87D +:10C800008FDA0D68223AE05A02570B5C3FCE0A3DA0 +:10C8100088CF91D618879171ED25A29E7853C9775C +:10C8200082F3F1FC5291DD2FC2E103FA7CAF4D9C03 +:10C8300073AD9DCFEBBC42DD4EF2D7AABB441D8940 +:10C84000D54DF908DBF58EFD943713F9D410D61DBC +:10C8500067505DD7A8E73B6CA63C6A97586F69F6AE +:10C86000FB94A76E7A83D70BCB3C76BD80AB09F5E2 +:10C8700032C0DDB85A095BE0BD46543C98D7CD6460 +:10C88000615F7A34AFBCA2CCD6EFC07361E27C06A4 +:10C8900013F670241F5EEDEBC3FA189B1AE757716D +:10C8A0001ED61FA4BA38CC17A5B348FE59EA91CAC0 +:10C8B000E6EBEEC63CB54E6F519E3A9E0DD31BA4DF +:10C8C0001722754D228F1EA9CF117A40E6A71BC4EF +:10C8D000BA9645F4C0E22568E7C63F20F2D422FFAD +:10C8E0002CF3D495A6736D8D810563289EEBB7F963 +:10C8F000A9AC26D5789E29DE44879B8AF9B94A9946 +:10C90000A73E5A60CC373F6067A477BB328C7CB7B8 +:10C91000A098E743FCC5320E19DF1F87F6377391E5 +:10C920001FD28DF19CB1DC1FA1C35CA6B88E6D43F4 +:10C930002DC51FF1B9027CA864BEF6EFA897B15DC2 +:10C940000CFD6D78BE05E9E1B6903F2AE33F68A68D +:10C950002CCCA138D079E467DB867A1A479E677FB2 +:10C96000323EB67C5C2C9079D63E3BF6ABF5BE767B +:10C970001CE7FBCC7120E18745EC181FAF7F995471 +:10C98000E09376899D9FF763F6A559142FF9B800B7 +:10C99000EFCFE8F3211C725FBAA3E839DAC7AE3CE7 +:10C9A0000FCEDF5BFBA3976AB5E491F3183705223E +:10C9B000790737A6C059B2CC3BA889D88EEA595816 +:10C9C00048A141CFD6B5FC27D0B351BB3FA30E9FA2 +:10C9D0007FD1E0077EBAA590EAA778FCED8B06FF31 +:10C9E0001BF96A3DF2E1B59EE7C5FCE03A9C67ABF6 +:10C9F000A2D6B8E95C0CF32BA3E70BEFC5FEE67CEF +:10CA0000E1E5E2187F8B5B8C1EB7E82D34E6F53F3D +:10CA10002F718B7F04DCE13E09F27490E429C0E5BC +:10CA2000E9AF7DFF83F51EC1F56E55FAC2F1D6ABB5 +:10CA30001F37783A2FF46B94A3E9A9AE06B4676068 +:10CA40001E1FCA5F341E0270171AE2217B5BAE41C3 +:10CA50003C04D6F97BD27F659CAE7F05747314E1EC +:10CA60007A546E47FC15F26506ADAF8FAFEF2F30ED +:10CA70007F4E11EE034F717E89E287DB493AFCD489 +:10CA8000B5FC65F07333C17788C3F705A0671DD186 +:10CA9000D3CFE1BD9CFFBDBE80FB17F05E13BD97F9 +:10CAA000C7F9E05E6157835FBEE03A5FD42F4FCE97 +:10CAB000569B8BB89D7B6791A1CE54BDAB6874BF6C +:10CAC000F99EA2D1FDE6FBF0FD2F8ADFBCBF80DB23 +:10CAD000FBD1BC4DD8C53FBED142F9E57AD1B77B79 +:10CAE00043D5A21BB1AE06F08F6D27AEC7AA5B4F30 +:10CAF0009A8DFBDBA6F36AF27B07725D366BDDD89D +:10CB00007E5F149F6F8D6975E079A86635A913CF94 +:10CB1000DD2EE8788FEA061DAAD3877EE197BCBE9A +:10CB20004ECCCB56A97CFD8E160F9DEF93E7DDE42E +:10CB30003994E6FE1B5F73E0B939F05F5260FC8AFE +:10CB400032FB69FDBA9DA6732936537BC3AFD3B7B9 +:10CB50001FD6F57FAAC8544F687DAA9CBED3D1A129 +:10CB600078449D2FD565348B313695DCB108E39739 +:10CB700060C7F9100F0B76EE1AC07C9AA3C34AB9AE +:10CB8000F33FB6F9B61F06918AEBB552BCE1830DAF +:10CB90000AFFDEC7629EC76F12797C668A33C87847 +:10CBA000B8C463DC83BCFEC35178AA8CCE37D6AD43 +:10CBB00019C8E7BC43F1061B878CC9EF6F540ABE46 +:10CBC000AA0FBCD781EF2DF35A0CF543E678848D7C +:10CBD00099EBE4791DA74DE5759CB64C5E271FCFF8 +:10CBE00054FA5E47FC962AA267A5CAEB38C14812E0 +:10CBF000DFDDE274A908ACA73A1F731CC159688C29 +:10CC00004398F9D24C8F93267A3C61E3E7933A0735 +:10CC1000AD7E0D6E773EB4BA0BE3E7DA43168A6356 +:10CC20009C95F5210024C6F397B3087EC95EEE6C8F +:10CC3000E5F502922ECB77F2BA11EA6588DBA732CE +:10CC4000FD773C968BB8C21DAC8FCE3BAC6443766F +:10CC5000948355184AB7623CC647D726A66D6184AF +:10CC6000BF50573ACCF744EB783FC6B5FB27D99372 +:10CC7000DECDE47E442CFB359AAFB5B1777571FEFD +:10CC8000BFC5B53E695CCBAAD1F952AF233C4DB9C3 +:10CC90007C5CEB88C84BC8B8D6D99DE27B1BE2BC54 +:10CCA000C580BD75F24E37F6F3919E19B377F92220 +:10CCB000E48323BD3FF188F3AF1B278EFE5D88829E +:10CCC000E218F5A43F2F60345E67FA109DA33E6919 +:10CCD00037D6E5CAEBED0159BF19528B75F631F322 +:10CCE00044EA38E717D346C0CF6BCB38D3BADCD091 +:10CCF0002D787FEE05C10F8B95B002EBAD702BAF99 +:10CD00002ABEE8FCCC5C47FFB77C18C11D87F80140 +:10CD10003C0EC4F1BADA817456F34C0CFADC389745 +:10CD2000EBD181ECD8F493CFC13EB9BF7802F79F25 +:10CD3000C6F0B8C2EF1DA3C715BE551C23AE20E92F +:10CD40007B709EAA71BAF3B62727D489FDDB4341D5 +:10CD5000AAD739DF63F56D42FCF7B7BE5508ED255C +:10CD6000DFB27A301F7EADF37C930AD289AF2E9763 +:10CD7000E7FB50E0F764A4AEFB5B944FEF8EF867DF +:10CD8000DC7EAC1DA76BC3965C3CC8FBBF585CBC8B +:10CD90000FCFD98F646FDE1758D58BFE9CB437A1A7 +:10CDA000BD12DBF27D9084C9A5A0349B5A643EB1CC +:10CDB00082F2F5D1F956EC43FBF8ACDD38BEB4573E +:10CDC000078ACBF7A1BD1A8CCC5FBE0FEDD953A655 +:10CDD000FEF47D4A18EFD7C565D4BF91C9F1CBEAFF +:10CDE000B17F24AEC8D6933F7ACC21DBF7D4A33DE4 +:10CDF000BE3D9D8F371858DFAB7D0EE1B9D6E37F7E +:10CE0000D2FE23D9FD27EDBC7E50033BED89742C67 +:10CE1000A3ECB372E1531D78C6AE5855683FFA9340 +:10CE2000888307DD16E1E76CEC45BFA7B644F2E95D +:10CE3000E354073212DFAD7FFE478F68FA756A3F11 +:10CE4000AA35C0ADB5529D8884FB04F68775D4DE43 +:10CE500073A717E1AC95F10DD6D98BEBEB4C92EFA4 +:10CE6000DDB40FDB23CDBBE6F99DBD88EFDAC83C0E +:10CE7000DFA6F76BE3E578BDD48EE2F300C54BA2E5 +:10CE800070B518E07A2D70A017E10A7AC25B707F46 +:10CE9000087A19EDC777B46CA2FAEE881C693BD208 +:10CEA0004A510EBD9136C757448EEE2739BADA7013 +:10CEB000C17E9A3E07F7BF4CEE275EFD75C33E89E3 +:10CEC000EBEEE17A48F2519D478E03F8077DD2E4FC +:10CED00093EDAFD5B7B8AFC6BCDCDF0DFE9E917D3C +:10CEE0002BE58969AB4DF27365E3B5BBBF4675149D +:10CEF000CDA0D763D563DF5B10D14FB7123E0BA532 +:10CF0000FFCCA4DD5181F72376872F627754CE8939 +:10CF1000617774629DD52CAAE722BDA9C213AFAE7A +:10CF20000E68C65C9E076C177592799BD95ABDBF77 +:10CF3000FDFD79DC9F7F6A1E874B7EDFF6CC3A854C +:10CF4000EAC4DA7BA68CC1F36EA7537DDB51AF0D2B +:10CF5000A45BE83B0527C5F73507BEE14CBB0FEEE8 +:10CF60001F4F73F9515F1D4FDA49DF513BEDB70A8F +:10CF7000FE3CF40EEEF3BAB8A2867A45C60DEF9EDB +:10CF8000B3F55194A3133EDE2E9CF7E377509E59E0 +:10CF9000A6F97C6780EC18C7CDB08DE0BBE2FB9CA6 +:10CFA000C5E279E5B61F7CBB0AC710F68BD49FE6B5 +:10CFB000F39EF863D7DB5F5D566E7F79793F2F1B59 +:10CFC000DA74C982E3F2B66B84EFC2D6C8F3CB261B +:10CFD0007BAAD2743E9989EFA04A7BBC38B9D18F25 +:10CFE0007E5CF13AA37D74BAEB959E42F46BFD56DC +:10CFF0000F6E93B7661A9F4B3B6C51D763E48F82D9 +:10D000005D689847D6DFDECAFA3AE85CB8EFF5C348 +:10D01000D68951BFA5DD5349764A7326B4603DC712 +:10D02000FEBE34311FED831E2B7E1196D7DEEBD66C +:10D0300001FDEC9664DAA7FD8AA2AF0BDAF228CAEA +:10D0400045B42E88B7A3F1F8BF7FD45047C7BEB60A +:10D05000CA10E7D46A1FA53A3E1917D3AAE9F919ED +:10D060009B8883694D8FE27E16899369BFEA35C438 +:10D07000C9B4203D0F46F6BF5DFBB0BDCC23E0D167 +:10D080004EF622BFB5AB5C9FBC34C77D52B37DF278 +:10D09000FE209FFF730EC6B7827CBF333F2F1E0C4E +:10D0A000B78F11761DD68B9BE57C5C80D7DF95A969 +:10D0B000D91D137C3C7EE504FAA82BAD2B316E10F4 +:10D0C000AD5729A2EFA4358D505FB224C0E5F7E833 +:10D0D0001CB7C12F37D7A934893A9591C6B9B38403 +:10D0E000E7D907144F35D7CB56867AB974D714379A +:10D0F000E6A664BF9B4BF83EF071967A12D76F8E0E +:10D10000A79DC5781AC9198F7B2C15BC63DBC9BFD5 +:10D11000572FBF677226C9EDDF0CF797F688784561 +:10D12000F9678B9FBD37C7784E7FA4FA87D212BEAE +:10D130009F1589F57ED6FA8727E35515F135047DCD +:10D14000313E38AC1E42D439C83A88B1810C5EB742 +:10D15000C1783D44BBD64AF8BBEAE75CC4FE0F7C0D +:10D160009A1C403EADE17A44F2D94FE7F838FFFD12 +:10D17000C64FFC27F90EFA4F0AA01EA9E6FD8B7FC9 +:10D18000C3BF7B21ED8B718133BD9BA6921EF2053F +:10D19000F4FEAF3B722E322310430F1D5DA04E0DE7 +:10D1A000E8FC23783F33901FF3FD2F13BCA6F7B3A1 +:10D1B0006606B3E8FDC8794E7566E06F7510A03D50 +:10D1C000CC75277CBF30D79D487BF0CE92DFAFC4B3 +:10D1D000BA934BF3D5651CCF1CBF11BB7288DB39EA +:10D1E000517B3287F6C36B602F36133D453DCD35FD +:10D1F00018FF5EFDF8D27E82FB7FA7BFFF79F3DFC9 +:10D2000000BE6E824FE44D3EC5FBFF40EF8B7CCDF0 +:10D210009F01DE30F191B0FB3F87F87CF6730EDFA3 +:10D22000EB44AFC59CDE657398DCB7FF35361F5CF9 +:10D2300031FFFF6F7A5FE4CD75E3FE5C3FDF48FEB0 +:10D2400039F4FB15E16DF130F93919D0E5E347798F +:10D25000FF8C7E7EDDFBEFEAF9F32AC8F9053D7D00 +:10D26000AFC13EF2118D3F958FFFBBE2C83A2EE968 +:10D27000EFFF2D4E76593E9F3617F1D5CAF9E90AD0 +:10D28000ECEB9BE6F2FA96108FCF6A927F678AFBEF +:10D2900043789E74F91C26BE8F12CCC6FB2AE3FE8F +:10D2A0006DC41FD17AF719FD1118688641CFEFD3ED +:10D2B000FB1BE5739FD88774B72EE0FDE7BE306E89 +:10D2C00015E2DFDC067B64DE5C635DA68AEDCB8D58 +:10D2D0008BF97F7ACF94FFD73D5F44CFA3F50B64E2 +:10D2E000BF82DDE672028D7F51674D6E8476B5F0A8 +:10D2F000DBC1FE8879AEBB3A1AE7AE9EABABC7186E +:10D300000C5AE97C60C44E61EE4711FF113B4AFBA9 +:10D31000FE3EE3B98D8314E72A11F46D7EE1D97ADC +:10D3200001E72AC4374B16EBB87CFF35D4DFCBFBC3 +:10D33000C7787E273D4FE57032F7EB67ADBA7C18B2 +:10D340004A9A05F3BCF82F1FC06FBF7D6E32D82BF1 +:10D350002F77293E2BB41BF74A7E7A81E44157F799 +:10D3600041F2B742F0FBD6170ED7233FAF785FC22A +:10D37000EBE4EB8FD4311DA6F59F10F188092F4205 +:10D380007FCEBFDF24F87C1CBE6B30FE36A213E3D9 +:10D39000F8A9619A7DE2287516BB04FDE1BD9D04E4 +:10D3A000978BC3551352C85E0FAE06890638EA073D +:10D3B00059CC38D3EEB90EB98FEDA679DDC28FF511 +:10D3C000C73E2FBB2FCA4FFBA8BF87CFE702FD8FF9 +:10D3D000ED40E8E802FC0E448DF8DE784D998DBEF4 +:10D3E000B750537861A98883507E53E6C14B1F9C88 +:10D3F0004AF9CDF8B238EE2FBA8C7FC722D8E4A410 +:10D40000EFC9C9EFD6CABA8C4A66FCBE5C8CFC96E2 +:10D4100021DE22E32291EFC95953C9BF753C2AFE90 +:10D42000FE93E9FB71F11B18C5B79C1DFC1CB839B4 +:10D430004FD5B0B1F5AD22ACFBB0D9292F6BCE677B +:10D440009AFF1EC63C1753C7E4503DCA6B73F3A343 +:10D450007528E7F74E71A31C9AFDE7F323F9CF7BFC +:10D460008DFEF380F49FD5ABE33F9F986BF49F1F35 +:10D47000CF0DFE8AF8CAA6D2FEF67249F1528C236D +:10D480005C147514A71E4A5E82F128AD879F573839 +:10D490002DF2FC32DF7FAA88B93D78DDE2247C9E44 +:10D4A0005A9314C62D784C47F362FCAEA0F4A31136 +:10D4B000F318FFAA10EB34FBDBF18540CF5924664B +:10D4C000E4679FF278282F50D125BE2F21EA05A4CA +:10D4D0009F5D21CEF13795F173D518B1437E90DF72 +:10D4E0000FAC107EB8F4C7FB7FCA147D1DC052E696 +:10D4F00027FEAD06C6C0EB32F13DC51A0FDB8240F8 +:10D50000FD312BC44A102F7B399FB0ED36FA3B57C3 +:10D51000A77A76D1BE3AD2390677893CC7A0517E28 +:10D52000F61AF8F9490497D83FAE60BFB98EFADB16 +:10D53000B81C6FC3F3BFF9D1EF4AC873F3DB93781C +:10D540001C654609DF6FCC57F9DD884FAA3F407F45 +:10D55000DE5082EF47FDF94C84E70AF4E74C825B2A +:10D560007CB76232E681F8FAB34B783ED73786272C +:10D5700071BB1CA3D70114968C92CF6597AF235033 +:10D5800063BDFFA1B0B3D7E5861696F07C3FF1AD41 +:10D5900039DF2FFB1DC3F8548CFD76838853950229 +:10D5A0008B5A72869FE7FF459B7A126DBC636DE5CF +:10D5B000743D6ED312B17EEB2D719E1F0C2DAA67A8 +:10D5C00092755172DC9ABAD2936775FB59C5C2C77E +:10D5D000A9CEAC3DF3C0EB0AC0795AD47B0D24FA36 +:10D5E000689FD38EF2EF4B2DABFECAC9B3BAFDC311 +:10D5F0000C2FD6456920EAEB4BF877CB5E2975F600 +:10D60000CFCBC3EF3571395CDD738ACEC3D46F687D +:10D6100060A12CAA9BB2217DDF9EC3BFBF50516881 +:10D62000659A0EAEE46CF5AE121EF759477C12AD4A +:10D630000BBC1BDBA576750CFEFD49199F94F98286 +:10D640009B5FFC3F94771B4862347FD0CBC29877B6 +:10D650005FA0AE770C61DEC5EBA3F8C8DA121FCD70 +:10D66000DBD8B59FE0890FBC47F0806DDD8FF58377 +:10D67000667C4BB9E814F8D6AD9BF03D92FC562C75 +:10D68000B425227EDF427A41BF07C53E70C476C111 +:10D69000ED8941F7C87B85A5067C3BBDE506BAB59B +:10D6A000ABF78EC1F5483A378A67E7BBAC6F221DEE +:10D6B000DF073A32A263EC3A88A348AF1B806F4C75 +:10D6C000F4AAEFE0DFBDAEEF28A5EFC5D5177EC504 +:10D6D00091427900A50FCF4B36953530B4A71D6A1E +:10D6E000127DDF4ED26F6919D04F072FC8E3632434 +:10D6F000A7C2EEFC14F1F5FF5EA2B383AF75FC1F69 +:10D70000E6FB51490CBBFCCF957F18FE3D1FBEEFD9 +:10D710009E12FC62BECA7D77C4FA662DB8AAE55394 +:10D72000C021E506E5769382F5938A1DF92C88F2EF +:10D730008BE7D70A7FBB05F3A1CD5ED6877BE13EA1 +:10D740009423C09BA33CDD81F2D3B8379DF802FD42 +:10D750007FC2A7D8A7DFC47D5AF8FF74BF85F3C581 +:10D760005F3AEF03F0FC1BC15327CE177CCEF25279 +:10D77000C9E541F73CC05B50DD4FFAE5A742DEE06A +:10D78000278D7FB7E993E5418B555E3726F3A131AD +:10D79000F29F3EE553E43FCD79D591F2A131F29F5E +:10D7A000067B7DA4FC2733E549CDF9CF455D5328A1 +:10D7B000FFBC28D342DFA99676BFCC7BBED1F50350 +:10D7C0001B7D176986C292D287E747BF2DF431438C +:10D7D000AB4EB7FEE369FCFBD7DD292EFABBABF8F5 +:10D7E00083F558129FA01F5C4E98B76321AFCBAC56 +:10D7F0004C7FC68C5787F04BAE08AF32BFEEE85275 +:10D80000C29B9135BC2C52FFE7D0D1D991F91CD1E4 +:10D8100091D9FADDF83DEE46FF78AA2733D3A1B8B7 +:10D820008BFF5DCA62CF6CFABB9492FEC5DEE175D8 +:10D830008336095F8CBAC13F3B3D7D9B5D19A3D008 +:10D8400053E6B147A2E3ACBCE0BDF32644BFDF24FE +:10D85000EF1F4FE3F83D7323137FFFD4484FC0BF42 +:10D860004AE7FA33D9FECDCA707E2816F598C599D5 +:10D87000DA7AAA838F5FECC5BC5904BFA98708BFB9 +:10D88000EDADBEEDE81F1D2DB353BD4A0C7EA0BF0C +:10D890006F7B397E1846F79E4F47BFDAA22716A442 +:10D8A000C7E08F4F4DD7CBD0D3617DAAABD0174BFC +:10D8B0004E5FE92139F55B3D4857494F49DFE1F4B7 +:10D8C000E4FB9DA4F7DBF9EABFE07E18A5B3FA34C8 +:10D8D000D2392ABF9AA19EC5FCDD9B1F8A3A161831 +:10D8E000E7391CE710FA58143F540FE138555F8AA6 +:10D8F000FDF74E9E29E5FE4E1DEB7B7522FA7D67F6 +:10D9000099A8D7F4BFEEC338CD862931EB358F3DCA +:10D91000A0F0BFD3E365FB2D627FB5E8FCDD535873 +:10D92000B709FEED09ACDB84EB5BF3D2F9F7E5B1A7 +:10D930007E732CD8E3A2BEB30EC7C679C09EC5BC09 +:10D940003CB385189E4B1FC0EFB3CCC2EFB36C2223 +:10D95000BD1BADC3F890F45534EEC9DB9501D97603 +:10D9600087A9EE46E63F993764CC7FCE0C1BF41DA9 +:10D970002B0C19F39FBC4E47EAB7CDEAFC10C6B595 +:10D98000A371C5721AFF649DECBF235C3A4397FFF5 +:10D99000D4AAC2AA5B9FDFBC2DACCF6F82BEA4B657 +:10D9A0008C433FD1FF6008EDFAAC99A10B48377961 +:10D9B0006E1E14908A7F87CEEAF61C403F1CFC0343 +:10D9C000A6E68F6C575FEBEBFF07133449A100808D +:10D9D000000000001F8B080000000000000BE53C69 +:10D9E0000D705467B5DFDD7BF727C9866C42A04B0D +:10D9F00009ED4DF879692561F909044AE06E76135D +:10DA0000B62D9405429B0AC50B64101D5E0DB5280A +:10DA10003EEBCB42421A420BC1E1F937AFBE2D05B6 +:10DA2000677CD631386AA1485DA0459496A63699A0 +:10DA3000521FD280790CD5AAB496577554DE39E7B7 +:10DA4000FBBEDD7B6F3685023A75DC4EE7E6BBF741 +:10DA50007CE73BE77CE7FF7E9745B315C66631F868 +:10DA6000F99386C6585F2DFC79338E83A651C2D8B0 +:10DA7000D2B1725C9934263236374F8EAB4D633655 +:10DA8000631D1E26E6B30403F8D7989BC69B8D5AE8 +:10DA900033318EB1F02255C0C708FF99E5127E4799 +:10DAA000320CF896B9C438B12469F819FB2893E30D +:10DAB00005345E9E1EC769FC00E3EBEF4D3D6E260C +:10DAC00060FE77A6C56F3646C0BD68B71EAFF8C703 +:10DAD000A3FF9C22E9196BE2F30F3BBD20EF9851A5 +:10DAE00085E8B9BCFF01E85D41FAB19FD3FB21A4F1 +:10DAF000EF2192E7D39CBE0F013D6D444F37D09389 +:10DB0000FFB75FEFC52A6327EECFDF808F2768DF7F +:10DB100027723EAE02FE29E23BC4F7C1F9FCE67073 +:10DB200080317C3E8DE37BDD2DF428D164A2DE9F25 +:10DB3000755BF60DC6B37AE57A1BF4B066A57F0374 +:10DB4000D9C9B2223EFFD7A9CF9A8992CC187E06B6 +:10DB5000EEBB9CFF1B7C6E9BFF199ADFE94EC3D383 +:10DB60007A1EF15C39BC89E8CDF09B20F81E077C59 +:10DB7000A3E0AFE07047326191074B3C4AF249FBAA +:10DB8000A5C4E3E497FA3C72BC8DEC667B29C73FE1 +:10DB9000EAF0E349A41FE47782E43D8ECBEF9F5D7A +:10DBA0001EBF3584BE947379483DFCCE34E377A81C +:10DBB000671F367A61FFD4F0888CFEFF1DD62BA438 +:10DBC000F5843D7DD0F9697B14719FCD4FCB77747F +:10DBD00018EE8FAAD5E979F5DA7D919BE0CFE5CDF6 +:10DBE0004FAA26E2051856CC58BC9F2537C39A7712 +:10DBF000B0A4CA2086C543260B4CB4D835FB32D11D +:10DC0000E1F1BBC4F8BFC8FF2D9B23F5FA5412F312 +:10DC10008B0CDDFE95B84F69BAD91336BA671FF67B +:10DC20003F29F80E852D7672A3F1076B412E967C65 +:10DC3000283D16F259F6E057C7A01C969549BCDF5F +:10DC400048229ED70B25DE7DB4EEB2F43ACFF171B7 +:10DC5000AE84FF29C167E8EA336D74255EA5BC4B2D +:10DC6000D2F5CDC37DB45F9E4072CBC869706D5252 +:10DC70004209D88F8FAEDDA49A56BFC0BAF530C422 +:10DC8000B7FB597A4C7A95F103DDB4EE8DA66B7D26 +:10DC900058C847D8699ACE7E164A302B7DFBF9FECC +:10DCA000DCE0F52D7EE121D4DB1B2FF794FB268BE6 +:10DCB000DCA51D2C0FA4EDDB603E90BB2EF1BC60FB +:10DCC000AEF55FFFBAA0E78F5BFDC9F5F3D153470F +:10DCD0007CBCC5F725E37F5E36EDFEE7AAE97B3223 +:10DCE0006C89E71F74FE7F87ED7666F13FDF42BEE9 +:10DCF0005BFD451ED4EF9541662481BECBF89B9B0E +:10DD0000B98EAA55C83FA5EDB39ACF5FB2833577D8 +:10DD10004F1C0C7F53AD8BE05A9F656BBB015FD8E6 +:10DD200073B1296E814B85F9F3436185AEC0DF2164 +:10DD300092FF464EDF89B04EEB8599C60CB0A9869E +:10DD400025634A500F5A7FCEF1B160882DCECFE0C7 +:10DD5000BB20F0C9750E2FCA6FB4F2F113B1CE8992 +:10DD600030E703E33FC9F311CE875AB02E88F8D5C8 +:10DD70003C595FFE9AE4DAEE16E3C43B14D7FAD2BC +:10DD80007EE877A4EF4BBD522FDF23FB97F9FA3BD8 +:10DD9000E13F2513B3917EC65C53ACF37E4B7EF01E +:10DDA0004AF3FA65BC6813FB9548EFD759A4FB4AC0 +:10DDB000F3D588D24C72F2B19402F143F50776772D +:10DDC000022B1595C69B38FFA5C9C6AFAE060FC876 +:10DDD000E922EDCBC3F67AC4F2FCDDB0AD1EB8B8D3 +:10DDE0002E8E7860652FECDB6BCBD5E25520B7BF6C +:10DDF000E2FE54517D10CBA65F7FCDECCB5FC3B666 +:10DE00007C3E925F0576C446B942E3F5C1F3FCB5AA +:10DE10008AD433B14FDA93C8477BDADEF8787B21B6 +:10DE20007F9E73C4BD52D8535E2DAEF33D215F1665 +:10DE300028C6F5D8C4E329753AC45796FE192E189A +:10DE4000AFC2BF60FDBEC85937EAC18A0EC5486679 +:10DE5000D1FB4176D221F03F96DEBF51B52308AF0A +:10DE6000C9A68BF801BFBE8F6F22BC8D4D0AD99F0A +:10DE7000D35EC6D672F98DAD4DCB692CD16F70BC17 +:10DE8000BE69F1F188174099774A06FF0A4177D8B1 +:10DE90001D3F7413E8417B9BA2A33F5AB9716547AC +:10DEA000298C99E60E8D87CB049414CC6B0F96F9D0 +:10DEB000D10FBC24D6437C1ED8478C25C122826357 +:10DEC0001A5CA7C7D61FC5E97FA930AB70DDEAF899 +:10DED000CE08B235AB71DF51BCDE036E1AF3944D40 +:10DEE00073BE16AF85FDEB99E90EA1AA4176D63334 +:10DEF0000EE86A107469C6BC37D930A8A23C2C94CD +:10DF00009A8671DD1FDA0CF71B9A3E3E9F55024C34 +:10DF1000DC3DD0EF43664C76B90CF16A03FDE55C5D +:10DF20006697C1C72DDAE8CE8C91367CEECB3C5F8C +:10DF3000722BF74FCB6A419E16BDFB91E0EF474233 +:10DF40009E3B80869E8984209FA1DDB0B52E94DF04 +:10DF50004A81ABA76DC95DB7017D97CA5908C75EF5 +:10DF6000E44FCDF077768CC6F963867FC148585769 +:10DF7000ECEBC916F075FF0268DB804FE047539762 +:10DF800017A42C7A7C7298C94298B79527B630D0DE +:10DF90009388B9D3DD0F74DCDAF4F65ACCFB5698CB +:10DFA0005E7D1E9078FFDA401DE6B54B4C2197F957 +:10DFB000EE73C8B70FFE43B978526FBEE04139CF58 +:10DFC00056D828C0BF30CA9F4BB9789976CE2A1749 +:10DFD000CD31DE78BA74FBF316F84FD5E6179FFF04 +:10DFE00008FC31954DBD0C7C82035980F45CEA50ED +:10DFF000026A2981B918F0E9F1F17DDCDBB1FE2577 +:10E00000B4D315412DE4D2913E46F26B146BBCD7CC +:10E01000A26F7F1E72D5C8C69D5DA877F7F7AACC00 +:10E020000B70EDCBF72226FCF9109F26F4C295F772 +:10E030009F3D1AC069FFA6325C4FCA11E41D980EBD +:10E04000F7CFF5C17C00BDBF1AE404EBDE63787541 +:10E050001DE07267BFDD8672CA65CDA9E130BE37AB +:10E06000E862295F862FE03B21E4E2BAACD05ABADD +:10E0700026D775D99E935C723F17610C7D77C2E8F5 +:10E080001907708BA4DE76F0FD5C64F0FD90FBCA8E +:10E09000A25C5FE5BEE43AF4D55BEDCEE867167DA1 +:10E0A00075EE43D2B10F7B356E27677B55CA8FCE95 +:10E0B000EE2ABEA71AE491D8E5223B863A6DBF52FC +:10E0C000007FA414A681FCEF13F4D20FE0F63617FC +:10E0D000263B4B33FB715FF9B13F2A958C438DCCC6 +:10E0E000F82386452C8CEF15A3FBBE9228423BFDFE +:10E0F00028EB76A35D3FC0FADDA8FF1FC352504551 +:10E10000FF18F2E0FD465FC08372DCBBEB483EFACD +:10E1100091D4CDEEC2F3E5642ACCEA279D5794C48E +:10E1200079C93700A7A4FFF49941F2CB7EB8929F3A +:10E1300036188E0BEBA23E334B1C3936D5FC31FA28 +:10E140002339D602CD0CE9D83335FE13EE77F9FC2E +:10E15000F195C64FD17FEE9F629CC0FBDFC07C0F64 +:10E16000E2C3C5DA47A82EF94B857112EF3BFDD803 +:10E1700039F4637A461F163BF441FAB153E8C7E01D +:10E18000D162B457901B8B5D9F1F3B2BF5E07676D9 +:10E190003BCA07F8F925F97F0DF801B99CC17D9FAD +:10E1A000C4B0FB966245C4A61E00FA14411FDE5798 +:10E1B000C0BF2B1B7FFC4765181FCF023845EC2BD7 +:10E1C0009691751837BE1EF2F9C6A2BF304F21DFF7 +:10E1D0004EB9406076535D163C760AF5C695F7C396 +:10E1E0003166963898DED775EEB7D27CA11D4126F0 +:10E1F0008F7C28CC745D467E0240C4A8F7D38B0484 +:10E20000E941FB0285F86B2F658DE8CFDBF0D14C3F +:10E21000D0F7054A37EAFBB722453C5F1AC7F3C27D +:10E22000CEC26430C4FB2C04CFCA436C494506EF10 +:10E23000B7222AC14F9A66E461E082BC8FF2259929 +:10E24000AF4AB84084E795C3233CCFA8A88C1751A8 +:10E25000A02B0E91DC218F1A4E637F2AE91A29FA2E +:10E2600022FCA7BB2C7944DFE824C33C24D7C89EFA +:10E2700037DC1249C7F55B22C8C72E19D78D5B1151 +:10E28000FFDCE18106F4731EA07B7769265EFF60E8 +:10E29000C1175458967D24524AF45537ED6C1D0928 +:10E2A000FB1D0E8FF563DA94AA4906318FE81C0531 +:10E2B00072C8622F1B233C0E4EBB45C00979C9B8FA +:10E2C000EF83F4DB0DEB6099EFC23CA084E7010F14 +:10E2D00044CA689ECC07003EE101B8F00493F0B454 +:10E2E0008FCFBEDE03429E99781B2A407FCD5833E4 +:10E2F000C58BB88827AFB51867064029FB5A6274EA +:10E3000005FFDF130507774A4BE487B2C86F61DD6D +:10E310001E1FC6EDD6F255BE7ECCFF8C08E16D5CAB +:10E320001E3E3360F1B79D256C0CE601F736DC79B3 +:10E3300066C0626F3DF99C5E8C33096F06EF52D464 +:10E3400013A0F768D89B9A0B02CD0DB2A457A1ABCE +:10E350005B473B88E8F43C6EAC6426D6E3D5673572 +:10E36000EA7F15B234FC26D89A483973235DF160F0 +:10E3700092E1BC5C18237C7CF6DB04BFB05A6509D3 +:10E380000B9DE07F56901E38F2A51DA86080B77DDA +:10E39000A692DC0C781B826B28FE6C9A934BF7617B +:10E3A000DDA417EEDF33BE89E296CCAFDAA3D1103D +:10E3B000C5A7EBCCA78E4D8D3F84FAE809A6FDEAF0 +:10E3C000C34467C6AF6E8870BFFA19BC4AFFB1FB81 +:10E3D000E86BE43FA00621397782BCBF9B651F37FD +:10E3E000093BE82CE47AE87CFE55A1AF7FA988B709 +:10E3F000221D06C4B4E0946BCF37DB65BE29E478F8 +:10E40000BDF201797C2962F1CB208F2F679303FC49 +:10E41000DAD05FA8D25B3CAD68A8FF3962F824333C +:10E420009338CFC79A0948F5C719C6BBC178520CB3 +:10E43000E72D13FC7D507FFC1D486FB85F339E8E27 +:10E44000505DC8F559FA65B04B1E7FAFD16FF7BA72 +:10E45000C09F023D1D786B66E6F921B1CFCF55997B +:10E4600087701F2794F856A2FC1F558CA05FC5BE6D +:10E47000A7D9887E84E9536CF306AFB389F0F4958D +:10E48000996BD1AE99BEF80AF09BC5BA824F9DF345 +:10E4900001EB7E25776C667C25BE7E10317E86F290 +:10E4A0006A35E3BF40BB7BB9DCA52714BA921D7661 +:10E4B00056E724151807A698AFF37D043F0AA83B3A +:10E4C000CBDFA1BC68E17C85F2B4853EA8E0B2F860 +:10E4D000C9F322DE2CD4F97376DA085AFB1D855174 +:10E4E00097BDEE059530ACFD8BA86B15F6E5653C48 +:10E4F000C3BE49367BBB28EC49F5BE5D827EF5651F +:10E500007776BFFD4EC443704A54F42544FC5BEA61 +:10E51000E5F5157B11E8B3C4D7E7AA6AFF8FE2627D +:10E520008225144B5CEC1B7D91FC1D3DB1DC5F280A +:10E53000FA4EACD78E47F2591465B675415F5D51FE +:10E54000DEC750A396E74B55C6FB1E3D7679013DCD +:10E55000BE28AFBB9B94E959E919C7A667A1E79408 +:10E560009D9EA228DF97E7AA8C22C407F17938D2B2 +:10E57000D1510BFA9745BEFB26D5DE84701A4B7439 +:10E580009495BE6FDE7A0BE291634BDEAA47EDFEF7 +:10E59000B534CAFD6B5994FC4AF6752B85DCAED7B1 +:10E5A0003F5CABDD6F73D8BBBC76F67F2FAF12E854 +:10E5B000F07A139F267B9D7875F6FDB15B7A462332 +:10E5C0009F87847EA26FC77CC3D0793EF26094EBB4 +:10E5D00071784292E09E1D22FF48C38160B02F37C0 +:10E5E000541E32F31AF390CED97D7988A7F5DDDD7C +:10E5F0007958C73F3B509B350F3954D245743AF395 +:10E60000900343E4216BA23C5F3DFABF1ECA2B6A14 +:10E610002EF0385F73A14BD5413FD745B93F9B39A9 +:10E62000D0A39AA027359887009E03220F41F84D6A +:10E63000A0BA9177BB54A46BE6851E9A570363CCAE +:10E6400043660E918700152AEADDFE9ACE5771DFE8 +:10E650009CFCBE58696E885AEAADEAFE1E7A4F22CB +:10E66000E775966FCE33699FED7A736C2AA73733BF +:10E670008FEBBB136E28FDAA53FDE5D81FD8CA72D5 +:10E68000432887F7728655B2025ED7605EBC15419B +:10E6900081EFADA7F39209ACAB7DFCF9677387ED11 +:10E6A000C6ABF43F3E6117EFE5DC92147590510064 +:10E6B000F33FAB1AA9B9100FB68EFB6280F3B39E7D +:10E6C000EC6883904DED4E8DEAE93B827C1F64FE41 +:10E6D000F5D25285F24340337F01C0CF10F83DD3CD +:10E6E000787D58AFFA096E5B39CF23EF485CA4FE02 +:10E6F000C5CC7E8FAEC37846FF1A5E2FAA3F3C9EE4 +:10E7000087F9FE4734A6C2FDA56DF156D2CFD31EC0 +:10E71000EA67C8FE42556F37C92D6FC063EB73E4DB +:10E7200082274B59F2168F63CCD4E505D9FC90BCF7 +:10E730003AFB10FBA2A2FEAC64932E835C2EB14781 +:10E740003A9037EFF8DAA34FB1C1F3657FE1C149E1 +:10E75000C633A81FE3DCFDDF7E06E475E02D0FF570 +:10E760002D0EECDA757725F097E8D2A8AF2BEB19D0 +:10E77000905BD122AC675106D4973EB90AF5F2609E +:10E78000BE1C834303BA0FA6DFD77F629561199F32 +:10E79000886E398771EFE00809FF269F2FC789FE31 +:10E7A00055785EE3E0283EBE14559F4AD0FEF66BD6 +:10E7B00054476FFCA53F9B7F3C5967D7D77BAAD7AF +:10E7C000737DBDC23CF0EBAF47B3CCCB59606EABB1 +:10E7D00000791C1C70D1FB21A8B352981F3C38C98A +:10E7E0007C03E11F3DC5E57AF0AD8702B84FDEE15D +:10E7F000FD0F67F3F3BF11F1285DE74DE6FE83B12E +:10E80000010DE3D68E39CF9EA884754ECE1C3F45B0 +:10E81000051640163ECC97E57C6F1DAFE332F4BD84 +:10E82000A2AE42FFF3D6B9866CF65E15357F1FB5F2 +:10E83000C1F3F7A2AD5D1AC9BFE8D8BCDD78EE27F9 +:10E8400055D3D5A3C1FE1EF88D8B619D72A042D415 +:10E85000E143D11502BA8AAE8AAE5D33B2E81BD06D +:10E86000E5A91B3198AE97EB18C9E7C54AC387CF16 +:10E870009D7432D1C79C25FC7DCE9B5FA4BEE381F5 +:10E880007E17354F2E0DEC5651F564FFBBF354192E +:10E8900066406CEEFCB32AAA94F9886AB3BB19A748 +:10E8A000726DE3079A87DBC6CBD68ECED821FCBF2C +:10E8B000383AD636F6066FB78DC36CAA6DDC30FFDA +:10E8C0000E1BBEBA40C4369E17BCDB067FA7BEC473 +:10E8D00036BEBB7C990D7E4168B5ED794D60E7167B +:10E8E0006C1FC5274ED68633D2C7C975B00F79BD08 +:10E8F00006E9E3A3A71E0AA05EA46AE26350DFFA5A +:10E90000F27B4AB07FFD923B7BBDF6489D2AE377C0 +:10E9100009C67B83F17A4DC287CBFA6D7DF9D57537 +:10E920003C3EAFA853B2F6099CF158C66119979DB9 +:10E93000EB3BE3AE33DE2EBC6DB78FF7FB79DC5FCC +:10E940002AF4A0B5FC677EACD75F6AE07D84CE92E6 +:10E9500038F50DFA447C3EBAF4BE31F85E2DB7DCD2 +:10E960001CEE2DCDC4EB487992FD12FB3C81241B9B +:10E970005B81CF936C7505F5A5B5C8447E7F82B8E1 +:10E98000BF06AF10A7EB2D7273C6DFB06FF20B0599 +:10E990002C93AF34FCC18816007D7735EDD38AE126 +:10E9A0001AF11FD6AC7EE864CDAF8A8788D39FB4B6 +:10E9B000DBC72B641F070616BF6F1C78A385F7DD26 +:10E9C0007FD0E26329E0EF744B80AE3F6F09D2FD48 +:10E9D000575A74BAB6B794D335D512A2E7AFB65426 +:10E9E000D3F5F91683AEC75A62743DDE1227B89F7D +:10E9F000B634D2F5C51693EE6F1776FA61A1C72823 +:10EA0000977D85F8519742726DC0A3BAB32E18AAAC +:10EA1000D5CF835CFF239B5CAF359EA46ABA47A326 +:10EA20009E41BCCA6A4FDD7532AF4FEF37D125F337 +:10EA300061AC5F504F649F0EE8FB26D2E7C5FE5CD9 +:10EA4000D1F5D37750E1741D2CE4FD1BC4B3281F0E +:10EA5000FDF9D7E2B5E4CF474C267F1E649ADD9FCF +:10EA6000970EF2E72BC9EED871EC93627F91DE53DB +:10EA700038FA2005F53ACD937D90397FE07D902BD3 +:10EA8000F10F7C1F47BF25FDF6D5F2EDE4F7D85412 +:10EA9000E365C423E3F3A0F861AEA3F8512D6C96AF +:10EAA00069EF529E9827F8D9716E7101FA172F12EB +:10EAB000C8EB748355E33E33791E60F7DA92C17870 +:10EAC000DFA8E9A678BE2D9DE7BC4D79CCE0F865BE +:10EAD0009703E642D6F80E7278B3AE6AB07ED6A936 +:10EAE0003FECDF0CF1F9603FE37DB269FC7D9D8C6A +:10EAF00083072FF03EC6254D4932D8BA5AD6DC35A9 +:10EB000003AEFBBFC08AE3F8BE698C2BB41740F399 +:10EB10008E1CD07D0017EE3787E7C0F3EA540ECD88 +:10EB2000AB9D3F3989E386F8DBE49F6A357B9CC463 +:10EB30000C351D77A80956E418DF9C8157717FCBEF +:10EB40003263C0BB6EAAA9D5035F8B2F36331DF08D +:10EB50007B4B989BCE870C8EEFEB144B9F4D63A1A4 +:10EB60000EE443FBDC36FE5ECFA16F524EB2DF26D1 +:10EB7000EBF0279911C0F59CF8DBC47B17E7FB96F7 +:10EB8000F72ACC20C22B8163F4BE85AD65FC7C8462 +:10EB90000BEA1394DF304F726FE960BDDB3FE5CEC7 +:10EBA00031F564DF09E5C6D4ED5D0AD5EDA26E62EC +:10EBB000FAA75CD63A46D64DCEFAE831E167655DF4 +:10EBC000F4989B51BDD5AEE486761393CD93F8FBB4 +:10EBD000B8E61978ADA9977EE90BB63AC91FA83FE8 +:10EBE0003330355B1DC7EB11777ABF4B02E7F33249 +:10EBF000FBEDF798413CDFD83E79DD5756A2BC4685 +:10EC0000F8E8FD26D3E23AFA9BC7F1443FDA7320D5 +:10EC1000C18AA767F65765DA79ECC77640F282EFCA +:10EC200077E3F53C9F70D2E5BE46BA7023E93DB567 +:10EC3000B4771617EF25791EE913F7DB746EF70C1E +:10EC4000FD96E53D799BDFF0052CFBF828CAD93B02 +:10EC5000F4BEAAA56D01EC6777F95D64A71DBAB68D +:10EC6000B514C61D7E8DE729BA2B96ED7D5247BDA2 +:10EC700022F8E67405045D6A7831E53343ADD7299F +:10EC8000F65D8E73279A06D9951E8A63BDDBEA2F3F +:10EC900056B0CF299FAFAA57C4BE77911CB68AFC45 +:10ECA00028B7BC3BE5427D19B5662A8ACD07F9CE67 +:10ECB00079B8EF9BD84DF951FB089FED7C96BC3E8F +:10ECC00026F06D75876254BFE7BB18D6EF5B4BB378 +:10ECD000C7C387C5FEB6EA53E2089F00B98C570642 +:10ECE000C3AD11705BDC5DC100ACBB75FCBD74DEF7 +:10ECF0006BEB1872356CF48F6F7B6A937FB07DC0BD +:10ED000098F6CF1D60F23DBAEDDC43ABDED0B81211 +:10ED1000D6D55E6121340B6937DB313F81AB7BD4C3 +:10ED2000E246D4DF4BD5B92184AF535F4CA01CDB46 +:10ED3000438CFA165A61930FE97EB444A3730E9282 +:10ED40005EC8BB77A3FFC80FB96CF9794175AEC334 +:10ED50008FDAE981F548EF86DA5F277D94924F7963 +:10ED60001FF842B3319E05DFAB697BB7EB97FB0A17 +:10ED7000FA75257E6C71B22413278F1CFBD7D5F84A +:10ED8000BEE371C69F3F7F6C0ED5EDCEF18DB2F321 +:10ED900056ADAB11F7A5759C87F4CF397F6B29A7CA +:10EDA000ABB57E965837A0A0FE6FAF2ECA413FED9F +:10EDB00047876B91EB0B95E6CFEB2D71B830DA4CB2 +:10EDC00071F8BBF58CE4E8D7E38171A017FE5E15FE +:10EDD000740AE4EEFAF31FCEEAD72E47D66590DE2A +:10EDE000FA59E6F76790CB30C6F5C4CF1EEBA1B851 +:10EDF000C436109C94D7F65B4F86526CE875FDD5EF +:10EE0000F63ED307ED23FDA93EBF98E49CC37250A4 +:10EE1000CE97D8230AC5E1A841761748FB557EFE58 +:10EE2000A4580E811D1C93CA2999FE12C3F71768B6 +:10EE30005F26A33C8520478A57573AED0BCD1B2D03 +:10EE4000D0DC8C076354D47FEE772FB1B7F8FA305B +:10EE50000DCF9F280917C5CB5B51AF01AE94997FA9 +:10EE60003C9BE55CCE9840D3BED5702D9E27FA62C0 +:10EE7000829F2BC943D2FDB7D25B19E79DFD50D9C4 +:10EE80002F7D06FBA5CA95FBA14CBB48729379ACBC +:10EE9000B33F0A712D0FE5FEDE048D7592DC791EFD +:10EEA00090A9D74D9FF51C9D8C97ED81C5B63EFB73 +:10EEB0000CA94B0E3EBF7785B8D8D90B7E13F3E172 +:10EEC000E066EAB3EF3FBDEA38D6E397821E9D596C +:10EED000FC7F7BBEFD3D80C4FBF979A29F3EAA9ECC +:10EEE000E17CADC76478FECE130C515C6855B2BFAF +:10EEF0003F689D27F209679C70BC67F99F1C7FD211 +:10EF000053C6D2F14315FE59C657A641141D699D3B +:10EF1000CFFDA894C77E9157761EF9049D176041D6 +:10EF20004BFFB62CCBFACEFCCF30F4C0F44C3EAA4B +:10EF3000F4F33C54AEDF2EEAE7D6D37C3F72C5B97A +:10EF4000A141FA5A617E7A1EF67FCA5D8E3E95DD3A +:10EF5000DF38F35AAF8F25722DFE0FF2DA8DF328CA +:10EF60001FB1E7A5C3638C9FEF293419F6712241C5 +:10EF700053C5BECBF4DE669501DF334EBFFF7E2C5A +:10EF80009AC7F39CF6F25571AC7F641F79C79CBB9E +:10EF9000C8BF421CDD3ACF52C7CA730B1FB4AF249F +:10EFA000F575BAD847896FD0F992D91BF8FB9FD372 +:10EFB0000F9D407DDC0FFA8871BE3D3FB1AD02F37D +:10EFC000935754B6571FDC8772F225FB49FE18D7BA +:10EFD000534FB0FDE85C97453EFDCDAA4EF2311887 +:10EFE000BEEFD1C4FB1E67FFC8EB359A317EA76A1E +:10EFF0008C466BFF58CA6D91D0E7376A9AE97DD489 +:10F000003343BCFF9570F89918D6D3B21F553AC94F +:10F01000FC3EEEEBF4D87A15DD48757C3D9DA3CC23 +:10F02000FB77467520CB55927B61A923739EA53A49 +:10F03000F1F74146FD320FD689C55817F23A51D63D +:10F040009FD24FD4A94F7794E1F98C5E8DCEDBE54A +:10F050001DF9840FF3DE70EF6AAAD50C65691EEE08 +:10F06000A33C7F24E9BCDE3AB30AEB4CCB7B928C09 +:10F07000DF88FD02F5A0B325FE8B28E8C781168343 +:10F08000C6ED2D8D74ADD29206F253554E951B9B55 +:10F090003500CF2D7454F5C46CE31D95E619D4CB1F +:10F0A000BCF2B8EDBE3708F82C7A0175EE3992EF54 +:10F0B000692E4FCF7C85CE152CEC675BB86DFFD3E6 +:10F0C000F8212D7663FC504EEC7DFD107F5FEAE960 +:10F0D00017EF4B1DF6B6679E4E7690B63B7C6F4A97 +:10F0E000712E41F3E9DDDF4CE067D827B9DFCA9C18 +:10F0F000CFA0EF12C3E27B693D366B0FE6B3EDAFF5 +:10F1000033F99DF01EC3F21CFE6AC2EF440E63B1D8 +:10F110000B79E6E65861137D4F2DBE87893416962C +:10F12000F4B1CCB945A7BCB6C45CB6733161C6FBBB +:10F1300062F2F92763A26E03765C96730FB978EEDC +:10F14000214BFEDE24F0350B397578F8B983B98E82 +:10F15000EF3C66C6785D30D4771E9F1378AEF45DC1 +:10F16000C76201773FAE5745E722C331A4372EBEB1 +:10F17000CF1274CCEA4DB60EC32431C8B2E2B93313 +:10F18000C6CFEFA562FC3CB1276868B82F80EF6E50 +:10F19000C2D7C8CF59CAE7B32EA49F2F243D69E038 +:10F1A000CF675D30A91F24BFAFBBF3F8D83D9BC626 +:10F1B00065CED7B4633FC28FDF99F0734BBB04FDBC +:10F1C000CEABFCCEE4DE8038A793B8758F81780C87 +:10F1D000FE5D65EDF10903098DD6FF18D127BEABA1 +:10F1E000992CF885FBAB882EC7BF0FF0C0F1E01E4D +:10F1F000F13DCE1A9AD7CCE9CEFC7B07A13DD6EFE4 +:10F200007B261FAF6C12F0EB087E2D87CFA20F423A +:10F210001FA7ECC15EEA55E0FB0CD1B79CD3571693 +:10F22000D3F977590EBD05B8CFD3BAE23B9FDEF8CC +:10F230006A1FFAF3CCF7FBB7D17A5721A736C2631E +:10F24000CAF59838CFC4ED42EABFD4876F08FDBC39 +:10F250003DA648BD7A8CE86DBA61FC7F89E8717C77 +:10F260005774253E2A2AE34FD0BC60FA5CF1D78957 +:10F27000AEEBA4477E07E6B48BEF0BFE61DDA7691A +:10F280009D92109D2F8275BF7D23D605BCCF101E89 +:10F290005F1AEFFE58767FF381F0B292E2AB3A1F2D +:10F2A00022C7FF0F94B0BE363046000000000000B9 +:10F2B00000000000000000001F8B0800000000009C +:10F2C000000B93E46660F8510FC181486C62F11A3B +:10F2D0007606866816068699AC0C0C15402CC74934 +:10F2E0009AFEE540FD8B80782E10CF00E2C940DC0D +:10F2F00007C49D40DC02C49240F34480981F88B943 +:10F30000809815881980F8370703C3370E8439377A +:10F3100080620F48B41B84AD7810EC3340FF6F045B +:10F32000E2AB6484C3281E1E389D9F81A15A00C190 +:10F3300017104495CFE047B0B94429B34B1AA81F22 +:10F3400000656D40B4800300000000000000000074 +:10F350001F8B080000000000000BE57D0B7854D5E2 +:10F36000B5F03A8F79666672F2204C4280134830CD +:10F370006A8A03840882F52420C696DA9152C5FE73 +:10F38000D60E34224A2051B1722BFD726002040164 +:10F390003BBC1414E9E00D8A8A362256ACE83F20C3 +:10F3A000B5B4B56D6CB9D55AED0DB5AD2F0C88520D +:10F3B000FCFBEBE5EEB51F99734E661250F1B7F703 +:10F3C0000F9FEEECB35F6BAFD75E7BEDB577DCB232 +:10F3D0000FF287029CC49F8B00EE7003C0D8743A72 +:10F3E000EAB66FCC7DA49AFCFE7FDD916D7ABA9E61 +:10F3F00048878244EB01180045001779C9AFA4DEA5 +:10F40000A49F1FFED37985007B41010FF9945227F9 +:10F41000157C8DF4B3F7238860B9FCF3406957007D +:10F42000DB99B4DD9781B54B95E9A55A156640C6C1 +:10F43000EF8697FE4EFA19BEB999B43FFE6180B6C9 +:10F4400077C22152F84886146F737218F6AB7ED0DB +:10F4500055C9F3654006070EEF64809A34BCFB5F24 +:10F460007B83C2BB4F25F0EA19C6F712F80BD3F025 +:10F47000EF856FE4421583DFA849C37FBAF0D0F966 +:10F480000F0058DEA23F5DEE0258DD024F97570095 +:10F49000AC6CF1D2FCD2168DE6E32D619A5FAE9290 +:10F4A00026040FCBDB216992F6A16A525FF447FE76 +:10F4B0000B54796D79772169EF4DE7D540D896F7F0 +:10F4C00096EAB63C01E76098CCFB1C3E9FA52D0454 +:10F4D000071E1CDF0BC65958FE6D8A171FC75B3C01 +:10F4E00038E2CA61042F6D2F2A84D2002EDD988164 +:10F4F000F09507DC7A92B0C63981D9536124193767 +:10F50000140320F5E21B00D612B8CF0E4C790B4243 +:10F5100000F793FEDB48FF4AA8ED650F295F51E62F +:10F52000D615C4CB76F52F5D640C2FF987783B6B2D +:10F5300023CBA7E745F296799E0D9672D2FE977976 +:10F5400077BE2C1138E2E56EDD23A5C7E9A14B3F5C +:10F55000FD5724EC7967FFE5BA51877C2AFAAD8024 +:10F56000E8122DF0C5EDF71C82DB82FC74BF629CB3 +:10F570007EFB25E48F92B6151B21992AEB3D4EB9EF +:10F580001EA9374979F946159265EC7B219187725E +:10F59000F62B2C2FADF3C7AA7AC303D67186A5E943 +:10F5A00052AEBB67CA842FCACBAF982B11BE8184E1 +:10F5B00085CEC31883A2BCFCB045A3FCB8BAA59203 +:10F5C000A6ED2D5A07959F8F95191D55BDE5F0AFF6 +:10F5D000A8A748BB3B5C40F9D0DC06C96D12F61702 +:10F5E0009D3193E4578D2A1A7DBB8EF91932EA05B5 +:10F5F000C1DFAB249DF2B749F81BF59F533E56BBC4 +:10F600008CAF607F2B46C9D212C47339E3F77257AF +:10F61000CA3B1CFB4D0C1B65623F91DF7561BDF25F +:10F620008A11BA42C63DBB9CF1FF2FC7DEE9453DBA +:10F63000D833FF85451DE56300721D7CA09D221F08 +:10F640006813FBE60331CE672D0F678EBF127DF284 +:10F65000D7AAC8DAB7506FB49733BDE184AB7868E6 +:10F660002A1C0DF4E6B7F272C26748A748DF7CE6B1 +:10F670004C37B424E175C243EB5AC294EFD6B4E8D8 +:10F68000345DC9F9D0853C554CF29C0FA1B09AE687 +:10F69000B3AE57B098AE4703A6272146E05C87FC7F +:10F6A00079017E5F6A18A5A479A5C8434A26BA7F66 +:10F6B0000D9697D0BC01A5C89FA2FC31D320EDF3D5 +:10F6C00079FD29D263669C20699D8FE5EBA56EC309 +:10F6D0002CB5B65F691813D3F5493E55576EED8FBB +:10F6E000F45F6585E7395A5FF4D7201D324C925F8D +:10F6F000E363FDB5492F7F2EFDDF2E25C2B8D0ACC8 +:10F7000070F473BBC89B09C3A84A8F53B6F851C3A2 +:10F71000B496C3A3B6F29AC509D32478BB0BA2C38F +:10F720002542DFE2A9D13010FAFBA2491397DA345F +:10F730007C0CDFE9F9DD49E1F597B3F22AE9F746F8 +:10F74000DC429F5AE93726C22FEC1B85F3ABFCF352 +:10F75000D29B5F20FCAAE4BA23D4CE282499F1647A +:10F76000BCE931D0091C723806A80F94B0FA77AB07 +:10F770001C08FE23708EA3704E8ECEC802A769852A +:10F7800053C0D11FDC028EEC7CCAC677F253DD6514 +:10F79000E37E3B91B0B8AFD315413BAF00F144F4E9 +:10F7A000007CB4CE7091EF05D308EE754AB71930DE +:10F7B000BC77BF85534B206959C73F6BBA0EC7FC56 +:10F7C000588AB7EF4863D3F425F999563C8EE3F590 +:10F7D0009CFC27E6E7EE35BFEFDAE6076A221C0D50 +:10F7E000F63FBF35BEC88C68A077BD5F4ACC8EAEF1 +:10F7F0009B32EEEBC0C6030FD15F7938DEE8F478B8 +:10F80000795F21E361676A32E378F993C978DE337F +:10F81000874FA73C0A787DBDE05D6783F776179137 +:10F82000DB0CF43FD3F09EAAFCF989FEA5F257D970 +:10F83000B7FC7DD6FDE5E1AF849FDE57217511C190 +:10F84000D7828BBD49534AEBB9CF1B5F055844E8BB +:10F85000B7E0D7630E5D246386F0F597D2E3CF97C8 +:10F86000740A7736FECE361F80A4AD9FFF57F3C9CA +:10F8700086D733AD874E55BF2EF9839FEEEF969610 +:10F880004312E569E9818BE93E73E90B930602E9CE +:10F89000C7D5762E18645279DCCE588A7606F63FA4 +:10F8A000F9D4EC8CDB5BA0A395185D4F84A2D42E19 +:10F8B0005A2A016DBF8AD86D4962BF54BFD8EE9DE8 +:10F8C00019A076154D97BA80DA31D52FEED726914B +:10F8D00029F82BF24721EF2FF589EF07EBD1CE5D09 +:10F8E000594EBE13D6581A64FD91EF51AC9F53C1C7 +:10F8F000BE67832BA792C063C1BBCF9D8C65D28F9F +:10F900005F96658A9F4DDCEE5A8D761751C83E7F13 +:10F91000228676B5BFC8ADDF27F56E37436676FF22 +:10F92000FA8A9F98E8D25881F61B99FFBECBEF87E1 +:10F93000AE2A5C0713868CED23CC35B0C9B1DE0747 +:10F94000D086A3EB66589A44D64CBF23BF5AD4370F +:10F95000F55AB4D74295ACBC76C985B5716B399C64 +:10F96000578BEBAE28BF66C9585A5EEC8DBE3C91F2 +:10F970008C5F4CF4679CE0A9584D48CD949E99F952 +:10F9800065FDB5DE194902C3FACBEF2CBB36039EE9 +:10F990000815299D45BEA4C12E5F9B38DE56733CD9 +:10F9A0008651C62D7ACDC7AAF6E835DF594CAFF996 +:10F9B0002B138B11CF250D10413B7B3DC15FCC320A +:10F9C000BEAFD2AEDF8A55FBBCCED47CEE02E32ABA +:10F9D0007940F6FE9DF27517C46662FD62BE8EFB2D +:10F9E0002B9352ACAAFFF93BE79B6DDE5FE5F82451 +:10F9F000E3CCCF34CEE78597E20019A7FAB31FC74F +:10FA0000DF60D793A78A77686C37705F8DA626EE84 +:10FA10009B7D303992A2FBB9DBA81FEE160E3BC4CA +:10FA2000366968D7C40132EA33B5DC9DF6A7E1FF39 +:10FA300094AB7333D145A40B5F7D2F6FBFA57E526E +:10FA40000E16FE3D87FC723E9C7F5249B707EEEFD3 +:10FA500053051C817CDBBC4EB41CCDDB4FF4C61AB5 +:10FA60006D1AD5C7D9C67B90E8D11491AF075ABC9F +:10FA700034DDD6A2418AC8D9BF1379C3FC56227F90 +:10FA800098FE88EC1731BDB72542CBEF691947F3D3 +:10FA90009B5A0C9ABFABA59EA61B5AA2F4FBBA9622 +:10FAA0001934DF83CF8FC87835946501EDAAB36729 +:10FAB000244DD463B003221504BFCBF1BB05FED5A2 +:10FAC00072EDB332FA3D67F8A87F23C8E7E987A44F +:10FAD00081FA1B0E2AB00DB2CFEB0E3EAFAF28322B +:10FAE000F39FAA957470414FB91DA85FA5A89AAC61 +:10FAF0005B44E5E65ED89A8FFC5E54CDBE07038476 +:10FB000091C877A51A52BE101D5AC5F61A6FDF3676 +:10FB10004EA6F5566B2A6DEFE48B73A193AE33605E +:10FB2000782308A777BCCAEA57B1753278FE3EA49D +:10FB300020B44D94E9FAB9BA9CC1A168767E09D681 +:10FB4000DC0768EF879561741EAB2F50370D473681 +:10FB500080CE9787937E3690AD0DAE6B0F6CDEA98D +:10FB6000CDB4D0D9AB30FBFCDCE93BA315088F4A00 +:10FB7000E49A8C5FB8D99FC47587D0434178737C71 +:10FB80006C3EE7E298048EC24590BCAF2C5D1EC867 +:10FB9000E3F3D18C5AEA9710DFB9E23957EF48C93D +:10FBA000D86E2344EE8374B94FB433ECED7CA29D40 +:10FBB0009942DC42E12A7B3BBF6807B5B6767ED12D +:10FBC0000ED61A74BC0469A7A7CB15DEAE47EE2B80 +:10FBD00035D92A674A409799DCD8E9948D7F34E07B +:10FBE00074D8674A27115FD52C2F49DEB69332AE01 +:10FBF000B3763AF951CEAD7A2660C913D245517623 +:10FC000071BFC6E9953433D36B9D1AF94539CEAF30 +:10FC10004AB5CD4FD0699D97D3D1F467A4D33A8D1F +:10FC2000D33106363A0B7AAD13F46AB4E34FD06B96 +:10FC30005D167AAD13F46ACE4CAF7559E8B54ED067 +:10FC4000ABC1DE4ED0CB490FB1EEA4E9D62C21DDFD +:10FC5000CE143D9C7AE10559A7DFE5F6A39D680F18 +:10FC6000162D50D93EA9B21350CF43697E3F76ABD3 +:10FC7000C9ED93665A7F2DFE2AFC5F28A76E96BFBA +:10FC8000267EA816EDF07C4994EFAB457F5812CB49 +:10FC900089FD7573FC382D7F528EC614DA5F1270A1 +:10FCA0003FE2C497279A848D04A40A357A6905FA3D +:10FCB0002537CB11F4DF0A783C20F004FCFCE6D4B5 +:10FCC000F81F80E10BC13B39FC94E0BC45A1F84C26 +:10FCD000323C39E124FBCB8D645F3384F3F710F3BE +:10FCE000CCC0090D6CBDE8599FB99DE482CCFD5490 +:10FCF0006E966D7C3362BDDFC637E5ABF26DE5C352 +:10FD00005A4B6C797DD1305BFD210BCEB195973686 +:10FD10008EB69597345C60CB87AFAEB3E57BF10BC5 +:10FD2000CFB72BAF2CB6F18B39A20EF76D496074AB +:10FD3000D81E1F5187FBB6FECABF7E8B6A7809FEAC +:10FD4000D542375D870805297E04BE723530DDE86F +:10FD50001F280C242F21E57ECD30A93F403300F72A +:10FD600073B216A37957D82E5F5F4301227CFAF550 +:10FD7000AD2A780BFBECDFF824FDF7372F27BF887F +:10FD8000F55D2964EBEA06B25DC2F33593E8C76D11 +:10FD9000645C97C6D67597E01FC2CFA8573455E26A +:10FDA000F27B7A72367CA31DDEB2843D3FB4CD6116 +:10FDB000079E227F7F5EF2DB1FFED641C4544E01B8 +:10FDC0007F1155E2E7D5A727FFA58D76FC9434B8BF +:10FDD0001D72E2D0E79F33FE5AC57A01D13AC44B77 +:10FDE000CE7AE64341BB2B935D21F865C3F49BFCBF +:10FDF000D6F50CACEBD4B0F43834AF64CA7FD1F88C +:10FE0000A4AB16ED8B9C8564FE65CC8EC9387F4E05 +:10FE1000EF755365BFD50EFBA2CF3F4DE71F9C5634 +:10FE2000FB700FBCA51ADDAF89BC635FD6BBBDC933 +:10FE3000F44DCC275BF524F9A954ABD135E98F20DB +:10FE40009F9DF08546422ED91F7A597AA6F76D0FED +:10FE50004C67FB12F3D59C6405E293C771AC7DF54A +:10FE60004B4984273955863BF19C79B29CAC20F9EB +:10FE70005BFDA1FB10AE6F2AB15BD50108EF9024AA +:10FE80009E1783AAE74D0B5AE6C9ED2231FF6CF6A7 +:10FE9000D192D69BEDEB194CAFB3F2E35DADCB69DC +:10FEA00039B13B5A554AAF2F8A7D9415CE4DEA178A +:10FEB000D83E12E703CEF6FF2AF6D101B57189DDEF +:10FEC0003EDACDE8008C0E2FB4EEAE3B9572611F8A +:10FED000F9036EBEAF77D82F95C43EC2F3A300B727 +:10FEE0005F2A93D45EF1552699FD5229EC19FB7ACD +:10FEF00076231AA063D3F6511FFD1B9FA4FFFEE6D5 +:10FF0000956D7DF705847D9460F611C135C69928FD +:10FF1000446DF846225FD8D7F76A5796F5FD7F8C77 +:10FF20007D94597EFBC3DF3A4830FBA81FFC4DCFC0 +:10FF300086BF7F71FB68BB0AFF9FD947D9F8E47F72 +:10FF4000B67D94A6F36763E738ED1A61479C69FBB9 +:10FF500046D827C48EA1769649EC2CB4734EC89A25 +:10FF6000EF4E32CF5B15DD877EEAB55C5E17AAD116 +:10FF7000352EBA7EEB7968676C447D3E80EB59B4D0 +:10FF800083023C3E4F8DC0B42F61FDD84697E51CDF +:10FF90004209E8793DE7365F203C103BAF522DB473 +:10FFA000CC9FE345E061972B8FD3BBF9FC289BD70F +:10FFB000E3140FA04BD4DE52751FA64FF3F58DAEA0 +:10FFC000C7D5567CB0BC52AF27511E48FBA75D0376 +:10FFD0006C78F1D9F042D621361E28CC9E336DF1D3 +:10FFE0006CFE6A4D42BF39C97622FFD2F3721D20E2 +:10FFF0000889FA11A4FF82D8B21B311E33F8EAA592 +:020000022000DC +:100000006F615C6341D74C1ADFD85A35FA401DA99D +:10001000971BD12E9FA2E3BA0AD4CFB8023BA3E725 +:10002000A110AF0DF0731C22DFBF597A9CAF9B0665 +:10003000D8ED725957853F69587679213FD2494F9B +:10004000EFF6D9E4C365956B2A9F379D9A7C4E6580 +:10005000726D927FA82FF21CFDE41A8EF304B0E4B7 +:1000600049F9879C8F8985F2B98CA7C15AAF4EF8A0 +:10007000CD552E6B181F990B5A1EF29F7FB20A297D +:10008000F4BF141E35D105DB1F5D5AB91F1D25F0C5 +:1000900072CB7E22E866F21A9ED55AB68CF47BBCEF +:1000A0009AC5DF1768E4BFD1BDE7B392CB574FBE07 +:1000B000EA3E7A6E1A27FC340CF9B84AA6F70856BD +:1000C00094333D2EEA9DE7966CF7082CFB365DAD28 +:1000D000E1F634C18F522E1B68077C5AFE503E2138 +:1000E0007FE44CB5DB05A74BAF89FC5EC5A9F2C721 +:1000F000A71D4FD0B5B75C2DE6746DF0A2DDBF2C07 +:100100003CADCF73D4DE745D4BE9EA2F072399A190 +:10011000FF5AB794317ED6B93F72DAEBCAC09A194A +:100120005BFBA25BA1D32E63FDFA162AFA5F51791D +:10013000A91A5D07BCBCBF15FA5A13D793E36833FD +:10014000107C28895129D49F500EF41C111906CF18 +:100150004D7DBA41F7E17405AA49C3E72E956DE3D9 +:10016000A9857EBB5D3DC394ACF0FB16BA291C5E2D +:100170001C0FF5B4C6CE3DD58038F774EC1F1D7644 +:10018000C3F2D2D119E30CD4CF6ABF3ADD0EEF2906 +:10019000B70BA8FADF2D7654F6762AFCDD624FAD58 +:1001A000427EB7D07F990B764B641D8E87AF8098C7 +:1001B0004EF258540CD086E978E4C3D11A5DBFB62C +:1001C0004BF47C988AB48EFFB173A2ABDC3AED4756 +:1001D000F6C6289E948001B4BE7E6AE7482706B31F +:1001E000B8A56112D8EA3FEC76D37215A2F43CFDB3 +:1001F000C46B978469BF06F9549386C3D9EF55EE53 +:10020000D8C36E6CA73178B001F5478C637E81B09E +:1002100097B53B31B3EFB8818D285F6759F23C2E1B +:100220000BDA4E2DAEEB0419B3B38AF2BF1FF7B54C +:100230009060F6D0504EB3AD8BF2E9F7ADAD7DCB0B +:10024000F9DD5CCEB770FBA81DED238BDCB7F3782E +:10025000B36D12D8EE595478587CD63B5CEEB77A21 +:100260004D1FBDAFF0DC0ADF088C7739A8447C0451 +:100270000FE5D71AF9B13EF05091B0CBDBE9C67764 +:10028000BCEACE1CDF91ADBD88EBF8B478D9C6F7D7 +:1002900031159ED971BA6F495D44E5B398F34DF1BC +:1002A0001CA076ED5013923AD6FDE82458F983FC51 +:1002B000EC433F454903190BE915930DD41F251B4A +:1002C000DC4999CABB763BB60F1F5458AC21188144 +:1002D0009935945569FBB0F2422D8ADA706E9FC150 +:1002E0002AFBBD8BD245F6FB52258E7B1261B4EF03 +:1002F00042E877B5D42BFBF4F40879083DCEFDFC39 +:10030000E9D1AE1A7ECDD2BE5C82684786FECA3D78 +:10031000CCEE285FB39EC5813504E07531DF6148BE +:1003200057231F17832D89FB16E3399BD9C0E26B36 +:100330000635826CE5E3319E1CDA8F0B0CF32C82C0 +:10034000B7A5DFBEA2EB19A4EB44B0E9B10CFA6388 +:100350008C87C88BAB90E98FF6C434967EA4D0F519 +:1003600023BC08924B08889363B1C52EA4FF1CA040 +:1003700071E8E186E6BD185F5DDC08111C86F015AA +:10038000E5AFF00C481A945FE06098F0C76036154E +:10039000188C7C81EBCF02465FC117258DF6FB36AA +:1003A000E1067BBE88DBFD45CEFB5B8E7E8A7576E3 +:1003B0000F4A5F2403DEFB83E9F6FB3661E87AF03F +:1003C00001846F7F2092427E351DE338FA572176F3 +:1003D0008587E0F389EF4FFDE559A4FE8F16D5150B +:1003E000205EB67AA3B9F45E515BE6B8B35EFC2A30 +:1003F000EC8E2CF5D37AD4B4C5353BD3651545378F +:10040000CF2270AC081A40F59A7915D5EF0A97DF1C +:10041000E78AAFF0623CE9D2C0E85CD4B37B314FED +:10042000D2A5E111346E57F4A3F0F85D918F737D7E +:10043000EA1CEF160FD3A37F07E316C4C3284F2C83 +:100440008CF376858B1E9FA9D3F3422399A1DD758A +:100450001E3FB32F75F59F56FC93055CA372087081 +:100460005AFE85599E581BF2A75947B613C8FFC3B9 +:10047000201947FA3727B8DFBDA7DE6A5ECFA47E12 +:100480004F512F9600EBBE93D45B8BF321F50C5BA1 +:10049000BD68AF7A77F17A601BD7E835EE66011F49 +:1004A00058FB8BF4EA6F2BEF8FDA833DF5F45EFD9A +:1004B000DDCFFB336CF5B45EF51E16F0D9C605FB37 +:1004C000B83DE5E7B89371AAB7593CFDBE8A2994B7 +:1004D0005FF6574CA99F45C6B9F9172EAE23AEA1BA +:1004E000EBB6E0ABBDBC5E2BF25515DEC385B64660 +:1004F000BC07CCEF09C703D3BC31CBF71EBE0A4CF7 +:10050000D3327F9F65ABAFB6F9C01843BFD3FAAD06 +:100510001F2BDCEF9D3719FD71CB0B65EE9FFB5B4D +:10052000DC50891E1BA0DAF26D61563ED2FBB7B8D3 +:1005300089778AF83D18A22B9FAEB2C877CFF89F73 +:1005400017FCFC3C230DFFFB71A3DC0A3FCB0BF82F +:1005500045DE5BCCCA47B7BD3F092F56897B00C338 +:10056000DB0A5AA9FFE20B3B3FA9D53E3F964FCF8E +:100570008FE5C5FCAADBA4C9FF5AF3CB6DB5F31F09 +:10058000CBA7E7C7F2627E356DB9A7353F673DBCA3 +:10059000AF847A7E45C5FD615C7756E0424AFA1D1C +:1005A000D7F6527C31C9DF3E40D8DB3AD5EFA3C045 +:1005B00038C73BB6FF76BFC2E037D2D61B64E7C16F +:1005C00050E1E6E7C18930FA39DFF0683C8E8EC130 +:1005D000A978EDF9A1981F90CE935FFE89EB308644 +:1005E00029B2FDA443CFF7B3AE2D2D66EBC9B2609F +:1005F00044B6AE6B220EFAB9013554FFC435A67F5E +:10060000F60EE0FAA890AC6BCC9F47EBBBB8BE5A95 +:10061000DBC2DE0B48F0FBB0F1C2D1143F09711F01 +:10062000D69C62D36FFB6AA71C40FFD5B183EC9DBB +:1006300088A7BC6CDD5BDA021DECDD032FBDD7FDA6 +:100640002CE937462AEC21F61EA63F25F61EA6BB4E +:100650005BC234FD498B4ED39D645C4C1F6D894059 +:100660008C8CBFA3651C4DEFE2FBAB0D682F92F4A1 +:10067000CB8532F55B6C6D2196B20BFDBD5E9ADECB +:10068000DBA2AD522BD0DF1BA6F963D2B4EBBC7456 +:10069000FFDA15CF25703EF1BB727A4F7C62A14A1A +:1006A000D75F50534A6E75FABBC0EB31A9AE11DB70 +:1006B0005D1096593D6F321ECA5CEF46AC372EACCA +:1006C000527820602AA1C28CF5BE87FC5513E0FD4C +:1006D00069B17830737FB7617FA303BCBF423D1E11 +:1006E000C8DC9F89FD8DD4181E20DCB5242773BD7E +:1006F000A558AF4AE3F32D4DC93999C7BD1DEBE5A8 +:10070000E727E8FD9D8BAE066A8FBA0AF5ADD46780 +:10071000C1EB25074441267C9E5F9068C67A17C6C8 +:1007200022308C8CAF872220137E7605487915DE27 +:100730002527FD9074C274528EE74258FE254B392E +:10074000B627E9F819BC7DAEBD5C8CE76A839EFBD9 +:10075000D37869DCD56ACFE7C94C3E1F6ABB6A32E1 +:10076000CA7D1E3F7FFA35E6C9B8AE4520F411AB0D +:10077000EF67E5CF88FA2156FE1ACFE7E7B379FB9A +:10078000A67869BCF0BDB78C289E55959EEFE0EF2A +:10079000559E3DCB32BF7BBF7741F1AC407A3E8363 +:1007A0006F9D78F6AC3EF63D05F572CF9B24A8B759 +:1007B000F21255547F8EF244A97D386A608D81F221 +:1007C000ACAC6270BDEB2D6B5DA252B84C7A4F930E +:1007D000C375CF3C3B5C83E6DBE1BA67BE1DAE412F +:1007E0004D7DC3F59497E9B56CF091F10DEBF85B95 +:1007F000FECD3EFE90EFDBC7DFF27DFBF8436EFBE4 +:10080000D4E3A7AC74D97CA37DFCD29BECE36FBE90 +:10081000C93E7EE9CD9F6EFCCFCA1EBFD01BFBA791 +:1008200097DBBB8AD5EE6C8ED9EC5352EF24AF67C1 +:100830002A563B3616B3D9A7A49EEAE3F6AEAD5EC0 +:10084000B4573D9F8FDBBBB6718D5EE386787F2901 +:10085000D9DA5FA4577F05BC9E295BFBD37BF517D4 +:10086000E6E31AB67A5AAF7A83057CB671C13E2E9A +:10087000F038B05B791C189577527FE1D5649F5DA5 +:1008800086FBD0A884FB7DAD0046EDC7FB26C3D90F +:10089000BB477953160EC5F55C9AB2F02C5CFFDAB3 +:1008A000F2C0B66F9BE2637E84B13E85A65A0E34D9 +:1008B00053FF9DB7B9F872CBBDD72DBC5E4F79A061 +:1008C000B9F81B96F24B78FB367E6F70B2EFB7D457 +:1008D0001ED10691FA19FC66978AFE783914463AB9 +:1008E0000D02F75D574D1B6BD5CF5B7C2E3A7F6DAC +:1008F000281FB734335C6D656CDC7B71DC007E17C0 +:10090000F6477331C5B7C652F17D4370B6F457C48C +:100910006ABB97AEEB6EBEAEE7B99B1F282370C4CF +:1009200007CB80F7229697F6EDCF696DB19F2FA880 +:100930005AD4C07D5FC91C6D348A47B67677D7CB51 +:10094000F599CE1F1AF87C5AE7D425CAC9F8B0DF4A +:10095000EEC7250C0ED6FBC857B9630DBE4C7EDC26 +:1009600056AFCDBEC92B9A960B7DCC23DE62F7E342 +:1009700012D56B64A2DB4A1F3F1F39E8B5D95B79FA +:10098000F932DD771EAF62E7066016533F610F5EF6 +:100990004BEABCD6F15738C6F3C13403D7015CA685 +:1009A000505EDCE5EC5D157F61422BD3D17FD049F1 +:1009B000CF0381DF7713FDB686A7D1FDF8717E0FD7 +:1009C000560D276A99DF91C3A7715DC5C729D9A8BC +:1009D00042AA808CED8AADF48DB5D2CDA4F74B4EF2 +:1009E000B89297D2F79ECA08FDA5DEF3BFD3C7FC25 +:1009F000C577EBD37E5B9681BEF7A0B3D8D26FC923 +:100A0000876E488DC95E3F5D8FC1D5C3B761C2AFE8 +:100A100028FF3AE75BB7F1235FA6780BA11FF839EF +:100A2000F8AC71C07FF42BFF44E671FD01177B77B2 +:100A300041DCB7E1A5D773BFE92CEE776D8068087C +:100A40000BDF05B91EE5EC5DF85D688C85FE4FFB9C +:100A5000DC0CAE3617F5778973DF6B132E9B3FECFA +:100A6000BA8DF6FC6C9856847A6BF67A17F5AF5D02 +:100A7000EFF0D33ECCE77B1D342F433B5EDCDB9EA7 +:100A8000A5818AEFF2CC7BF2DE1ABC1FB5CFC7EE90 +:100A9000EFBD4DF846B7C8DB0D81A41BEF01BCBE0E +:100AA0006BCC151300DB279795A0BECD838CEFBED2 +:100AB0007DB7CD0E5F7FF03BE10558D2271CEA766B +:100AC00029A37FABD327CE8919BDB2C57988B88B4E +:100AD000639C8F7AFC307FCEE17E18167FD15FFB5E +:100AE00013FDB49FE7ED72A3FC34A9CDF5929C3EB3 +:100AF0009FF2B862C620324FD7EEDAD420B0D56B61 +:100B0000EBBBDED12940F5657314F948D49B0FA4E3 +:100B10001ECAE59ECB4D5BBD72526F78F67ADD5CE6 +:100B2000AFFE7CC7BFBBD11FF9EE43872E43B99CF4 +:100B3000FBB4025E326EF78E20A4E83E36E9C6FDB5 +:100B4000DC0DBB948CE7B9346280F43FF7C741BA3F +:100B50005EDEB0D3939C4ADADFF093D74702C143FD +:100B6000F792A3CF0FC275F721899DAB9A5D2371D0 +:100B70005DBB4185EF4433F437C0CFF8F0F0533913 +:100B80003390CED2F6BDD7D07E3BAE74792CFA220C +:100B9000E077897ACC1FF7A044E3A37BC3C7CEC11B +:100BA0000E3F2831F876BB923E846FFB56778CC09F +:100BB000D1B4FD3DCA57937EFC4808F1D0B45BB177 +:100BC000F9899BB62B29CF489A1EC214CF57A41A75 +:100BD000C427D38FF377CDA3FEF3F91D2BDF534248 +:100BE000D8DECEDF042F9114E2F525253215F38FE0 +:100BF0003F10D209AADEEEDC1642BC927E67BA73C1 +:100C0000F11CD8EEF7C6FE3FCCEFDD1FC05137F226 +:100C10005753C70A36DEAEAFBD81FAA5C921476F6B +:100C2000E32FC5BDCF5D2EF43BCEC1B6179C927DA0 +:100C300039F791E35B4C32EEE19DEF6C3109FC8DAD +:100C4000FFF5FE96DBD00E7AD6A7A11E687AE83FA4 +:100C500042605937AFF43379EC7EF081FBEF26F236 +:100C6000D1FD470F5D3FBA9F7963884EE6DDFDD821 +:100C7000FF29D249FD05CF5C4CFD050B9E9834B091 +:100C8000AFF513F935697D978CDF3FD77793710600 +:100C900092EC1E9E3AE8F3DC2E057C04CE775FF6DC +:100CA000D07B524DE4DBC2D148AF79542F637E1123 +:100CB000C1F3FC1DCBDF534666C2B73948C64B07AC +:100CC00040C4308CF4FEC6D72FACC6D445CF579A5B +:100CD000E028D5ABCE764D07095DCFCB4EC7E3F00C +:100CE000911BE3569A76AC60E376103A867AD3F19C +:100CF0005DFC657C6F3A7ECF41C7E3D0F8233C1F93 +:100D0000845D0519CF85C5F9D9BC27BED9A7BD25F6 +:100D1000F4427F789E2331B8EAFCC6323FCAD7CE70 +:100D200087EFBFBB90D1792A414CF723C78700E1F9 +:100D300093375D47AF41FD78F4198F86EBFD0DCFFA +:100D4000BC44E5ADFB8917DD3AB5BF2120117BA37B +:100D50001B7A7E3AD1FE982FB14C537B30E509A522 +:100D6000E9353F7979BD1EA2DF0FD1EF492607F3A0 +:100D7000937BA74B19E8F7AC9FDDE786E4008A97E1 +:100D800079ED7F72D373700B5DA57148CF4353F03B +:100D90007B367A8AF96B38FFF32D746D67F29B4DC1 +:100DA0004EBBB77A548C6B70D2B9DBC5F6094D498E +:100DB000E9A54C7417EBE0E99EAB3EE5946F3EEF7E +:100DC000FEE4BBFFF99C1EBEB6FB751BDF08BC1D15 +:100DD000FE28B3DE3FE897381CCDF525C37BAF83F3 +:100DE0002A44CD416569780FD3B7C948FA9042DFEC +:100DF0003B5DD6F11CD5DF4E3D313F8B9DFD37AEBF +:100E00009FE6EFDE3B12F5D9E17D4F517E9CBFE3BB +:100E1000901BF737CF6F7FDCDD5595E67F5C17AC15 +:100E2000EF5B1C7E74EF48AABFB1FF0CF439C6FB20 +:100E30006FDA63EFBF69C77BB6FEE79A1D6EEA5FA4 +:100E4000ED679CB755E34A9CEFDB9D2EC07793DEA0 +:100E5000EE50EA33D9412FF175B127AE2658F3325F +:100E6000FA27957CB78EFAAF75B1F112BE9B68BEBA +:100E7000E862EF56AAC6CB1E229FF13CB78EFBDE7E +:100E8000D6E015A05BF478C2814FAD50ABC5FD80B4 +:100E900036395A6DDD7F09F8F30CD906FF8260FD03 +:100EA000407CEF0AF7713ABE53A14698FF3A34A549 +:100EB0009EDE7BD464CD9771DD66FDA1DF0EF9DF88 +:100EC000A5C9A05BF86BD4A42BCE45979D0ABA6D3B +:100ED0003FB066323B0F16F35F33183603D1C36B56 +:100EE000A4A307F09D08F352166728EC3BE0FBFE35 +:100EF00010EEFBCB7ADB7B60183AEA23AA8E7436BD +:100F0000BE61B9E79C8EE3055D56309E39423701DC +:100F10002AC468108617E36C87E3BEAB83A601A2E0 +:100F2000DE309D98338CF1371CA5F9B5F57FA171A2 +:100F30008F8539D1513903309F2FB179A4E83E4FC5 +:100F40005CE397734A8BFBD20730593D6CF52779E8 +:100F50006033DDCFA03BF364411A2F22DE4EF4BB99 +:100F6000C63751C2F508E73908DF69C3478E2CEF51 +:100F70007088F8C90122EF18076B6A357C09A6A2B0 +:100F800019935CC3F17C3F21E1FC4AA083A6A5D064 +:100F900049D37CAF26A914BE57A9BF4B86BFC0C991 +:100FA0001C077CA760C73BEDEF5B15FD9518A1639F +:100FB0009CEF73EECBB3C7237D3B87E9991B73642A +:100FC00011FF1CB3EEDBE2D04871E02B64CF93F548 +:100FD000C8414EECDA1C0B9F29814E165FE6D82FD4 +:100FE0005FAC2CA2E7FBCBC37DC7752DC5F8F0B372 +:100FF000B297270678676E050A3FF383495E16E7C6 +:101000006D80AE59F91163796AAC719386ED3D1D1F +:1010100017F2A182783669EA43B922690EF215A166 +:10102000C34ACE8741E8E29D1CA5FE8F2DEE581CD9 +:10103000F97060794C62C1445189F9D50CC5CA0771 +:1010400072CED5C57DC56DC174C22796B899FB38DF +:101050005D541554FF68846733A7BF933FED71B0AB +:10106000C2AE0BF09C87C7E3FDACFA77F4FD17B571 +:101070003040E35F02D5AD37E2FBAD2A346BA857B1 +:101080000322BE25C2E216C5BEDA57698F17F538AE +:10109000E2635D7CFFDE2B5E9CAFC777E0870C765A +:1010A000B3733D7E3827739C138CCB1C9728ECB40C +:1010B0004FCAFF62FFD9E8ED7C9E02A11934AE53FE +:1010C000E57E8BDAE91AF5B71FD921B1F7361CFC9A +:1010D000746467EE48D49728CFF87E790EFF2EED22 +:1010E000D8BB17EDABD6101879F954FFE90AC1FF48 +:1010F0003269945722E9BC5DEFFDE669F4E3EF51F4 +:1011000000DF753B42E6D889F3548D3C245A0EAC7F +:10111000B2D1F993CEABF7392693BF9B34217F012F +:10112000DAEED80E89BDF303E7DE85EF5D351D707D +:101130004192941F03D6EFB1CDCC6EB8EE178FD786 +:101140001049808D1C1E5CBFACEB4C41BD1F740B65 +:101150009F84C5BA601A9DF8DE7303C7CF8068BE4E +:10116000AD9E98DF3BB3EA0F50FF4F8CBDFF3C7044 +:101170004689AD7FE0FE119DFC43BEECE5679063C0 +:101180006EA0EB4A343745ED20B29FC6FD47528A28 +:1011900020DC4E7FCAFCDD125DCFAE27EB19BEC747 +:1011A000767DD2B11F75C45309FC3BF9560E703BD6 +:1011B0003200812C788EA4AAE9F92C95BB9B7EA1E4 +:1011C000507BECA647A4248DA7EE3A2B1728DE15FA +:1011D000EA977A039AEF242B4C9ABF1DF8F384ED1B +:1011E00078F7E976BCE754DAF11B8CD8F1E8C473E0 +:1011F000EEB861B6FA73954637653E8EEF4AF20F48 +:10120000F14DF4249DC77C328F94DE1B9F73F6ACA6 +:101210005986FE927EF1E8C0DF390EFC1D873D7BCA +:10122000592944BD4596F84F3545E5CA2987024FEF +:10123000A55A672DFD1609523F7598772235B0766D +:1012400025DE0E2654A323540E459C724ECFBAFAC7 +:101250003A9C24E9CD97EF3F340BB2CB5D478B37F7 +:10126000D2E0C2F371883454E079B946D3CD58FF47 +:10127000BCBED65B838EE7828886E91DFCDCE44831 +:10128000157B17A923F54111DA7F778C3E7A19DA9D +:10129000FD4DD74294BECB1464EBEF2E9E4E0EB2A2 +:1012A00038EBDBA33218E82FD8A32425F44369C612 +:1012B0002F2E42BB6D8F4BA7EB9F76F437FF8B969B +:1012C0008FD1F01CA3584E8CC271497DEAEF3FB21A +:1012D000E7F5D0772DF651F7EE7567E3FAB4498656 +:1012E0003999F6010D01367E77E55F8A902DE77911 +:1012F0008FD27DF9F22EBB9FCDBD8BF9E1E6EFBE1B +:101300009CDAA3FB67B3F7389F38CCEEA54E51AEFD +:10131000FEEA97487EFC7FF0778CC0983AB38885C8 +:1013200072203DE33E826782C7F53C7EB3E9AF326F +:101330008DDF1C7F214828AFE3FF08111351DB3CF0 +:101340009BAE574F87A61CC074F21E89FA8F9A0E67 +:10135000B3F56D6CA7DD4F74FE64A21748FF357BB3 +:10136000987FABA68B9D0F9CFFB2BDDEF82E7B7ED7 +:10137000423FFCBB24C0D7AD10149D4E7CEE1E979F +:10138000B122C0CED3E8BDB2889A79FFD515647674 +:1013900018C1079DFF91A3105942E671A4A1A4169C +:1013A000EF291DF9809D371CF948A9CFB4BFDA1287 +:1013B00060FCB2C9CDCE8F37CD0E24179379EC9B4C +:1013C0007DC350DC57FDE3DF6243B5BEEC12A222C1 +:1013D00064BA261AB9300EE5A395DD77834471A669 +:1013E000F793855C083911F2513CDB1FCBE4171DE4 +:1013F0001664FBBFBAD99512C66F773F2BD133A6BF +:10140000EE2504AE3EF068C29241084FD3EEF7A934 +:101410009FC2BB27B3BFFBD94088CEBF7B89B978B9 +:1014200002C1D7F788709B280FEE4459A6FE4D588D +:101430004FFD57DB028C9FBBBD6C1F0E6AA218DFED +:101440008DE8DE3DE9D26504CEBB89FCE1FABDC979 +:1014500015A1709BF380BEFF07FC7E61E965B0F5C6 +:1014600076CB7EED40A0F620D2FB6080C51F15C470 +:101470002212C21DF9F84408FB3FF2A187D2AF84C3 +:10148000FB8B44BB23017E0E17347E43F9654E214E +:10149000558A915828D23006E0BCDD04DF16FD9D48 +:1014A000A69B49C7C98F01BD479F1F90D97918D9FD +:1014B000A7E1FEA309C48F49F72B42FEF0D29B6A35 +:1014C00089BB97F648A920D19FD5DE400AFD32F9A5 +:1014D00073647C8387D8A35ED65FA7DD6E450D8CD1 +:1014E000FA177500D03CDB1F097D2CF4786B1ED3F6 +:1014F0007FAD6B54AA1F37AB5D3EF44B97197A9DB5 +:101500004AC6CD57751A6F31780E93F79CE1F7E60E +:10151000F5D84513001EFB58C9E81F392B28F015D4 +:10152000FB07E26BE481A3FBD0BC8AF8A000E93D95 +:1015300085DB3DE3DF65FA48DC3368EAB94760D70D +:10154000479B7CDC8E81C4EFF1DCFEA9BFAAF4FED0 +:10155000408FFE993D85AEA7A0543D87FC35E157ED +:101560007C7BC0F50FD9ED51BC9CFF422C8E7038AE +:10157000F5CD38207A49EA5FEF38E94C8CF09E7C53 +:101580002941CA980344CE2CED9D7A6A6090AFB38E +:101590005C4F1D8789032FD6D3FC347A61E4398FE1 +:1015A000857F849E4AF35392E2D5398E04DE9EBC39 +:1015B000361CF5CB0B0AFA518ED4B2BFF393E2720C +:1015C00094F741F252E487F57B2EF121DFEF3C30B6 +:1015D000C98B62755398DD3B53F74E3781B38FF556 +:1015E0005CD9055E3D5089F890291E148DE42DE3E9 +:1015F0001F4B48FCDEA59E3B3DC3FBD822BD29CC3A +:10160000EE95ED3C302C97ED475394EE3D7CCFFDAD +:1016100017422E04BF3BF95BC8439CB4922D7684DD +:101620002275F0FDA3DD8F10E776445CBC3F6316A6 +:1016300053FB7001B70FE381112BF1CF1CB4A6EA65 +:10164000343CF758101C46E3AB170C60F873E243C8 +:10165000A44D1F127BD11207DFA41EA5FEB1A60F59 +:10166000DDB6EF02BFD9F022F07B01E257FAE4F8D1 +:101670003D3FC8E8ECC4F3A79D7FE94DE332DEE7C8 +:10168000FB5799FF04883DDD45FDB1EC3E89E0370D +:10169000A13F6A6E6E8BE7E8697D21EE8308BD236A +:1016A000F4CBF98D89E77232E80FA7DE88B8B4EF82 +:1016B000AE22F88BFC2C40DFEB70EA910FF09762C2 +:1016C000EA77BB2748E07DECF9B765F49B3CF15322 +:1016D0003277521ED93B99F9053B4FEDBC4BD8AD43 +:1016E000C25E75D613F6AA5877C479D3AF83B18793 +:1016F000707C693791A710C6C7B27DF28140EC11AA +:10170000FC9E4360F6632C6065AA8CED67EDF29A4F +:101710004D3E731CF2D79152D93B3201F62E9413F1 +:101720000E317E4390BF2B40B80EED9AD21A6083E3 +:10173000CD67EF06948E8418AECF78BD14E7F92BF1 +:101740006E97BDC0D71B911E0844F723FC2E154C85 +:10175000CFE84F0EB7F02FFE3A68ECC3FEBCF5069B +:101760009DC7200D2268EF0F523BA4088123BF5173 +:10177000977A9C3D625D27FD0D9AAAD7A21C0DC2E7 +:101780003B05581FEDA30CF4F97390C535CDF376E6 +:101790003D8F267CD3D4E6FA501FE7EBE9F7102201 +:1017A000DCCF658F0339F2CC4B83F1FCF3B51FBC62 +:1017B0001FC473ADFF548F0611CE3717FD3E88F757 +:1017C000215E5BC4F61FD738EC9CE31C7FD343D16A +:1017D000C341927EA7E5E31ADB3B240BD9F9CCF594 +:1017E000490537A53DFC3E777B0EF5ED89FCBC8EA7 +:1017F000025B5EF0E93C0F8BDB72CEBF2AC4E2686D +:10180000AEDFB1D53D48C7F163FF85E3BFC9EDB891 +:10181000377705A9FF43C0336BC72837E2E13FF7AD +:1018200078F8B97FA78BE1DF988AE773314E0A27F2 +:101830009CCF3F9B43FBBB768342ED8E9964AC8586 +:1018400084BF637BAEA7FB70E73CAE7D4D9F3290BB +:10185000D0EFDA1512B557B1FE22C20FB185CBE930 +:10186000399E739E334D47FC08B72B9C7126D7EDEC +:1018700061E7EF0DA0AF9C589621EE64CFA5F4DC94 +:10188000EDBA7EF63D65216E4FD4C0F918377F1C46 +:10189000AA7E58A5F7BFEF79B3056810D9DB2D5E96 +:1018A0009A1E6ED158CAF5E7DCDD7B9FA77CA67631 +:1018B000D6A0DCEF3CF07ACEB7F4B41EFFF2D6F738 +:1018C0009FBB87E4C700F3F3087FFBD51CEF1771BC +:1018D0007D7E1DB717C67CD8B73EBF1AF131B2372F +:1018E000BC428F5F8D7F6FD08207A1D79DF838767D +:1018F00060780EF2C7E490F3BCF9D3E1255BBB79C5 +:101900004AE67846214787838CAF1BDA2F5F564221 +:10191000C68F3FF3C6902EA6270EA29E107C0AD03B +:10192000EC463976F2A3E0931EBEDBB39AE249F0AF +:101930000791AB303FE70CE3FED0C97FFDC537759B +:10194000BBBA86A05E70F259B7E35EB448AF083107 +:10195000FF7B836E4CC1FD2A596E96B1F340A68F72 +:10196000DE5413CFDF86F2DACEE465DE938FFC041B +:10197000F5D00D3FDE10423DF4969A28C2F11AB719 +:101980002D0DE1B9FA9BAA19C2F66F25958CF18F3E +:101990003B4292784FC31627016DE66528C7FFD8F2 +:1019A000E6D2F01CAC69BB879DBBEF6278237976E9 +:1019B000DEBE2B739CC40D0F6C28D259DCAD3D5E8E +:1019C000A2DD45FD17E85FC361B29D17F79C3F7725 +:1019D000F47D9EDEB48BC7D9ECBA3463BC84884BEB +:1019E00070F2F16607FF12FC50BF9F49E0A2EE764D +:1019F0007E4E1E7FF0AE9187087C87DB7F1592AA12 +:101A0000ACFE78761E7FACE3BB3FF2CAD9F9B79B38 +:101A1000F37BDA9E48668C9F6874A542B8AF6ADC97 +:101A2000EAA2FBC0C64714FA5E1DFCD143D7F3B946 +:101A30008FFCEC0F1710F8E63EE62A9CCAA641E39D +:101A40002404BD7AE258387D6E78FC67EC7C59E757 +:101A5000F12C9C4E731FDBEBC6B81C273E2775ECA0 +:101A6000757739E22028BD3A0E4DA1F7091F3CE1F8 +:101A7000C675F6AD67251858D6BBFD9CAD3F0BA1CA +:101A8000BE403CD138004EB7EC714BA9CB7E5A4DCD +:101A9000EB51BF5D7F745C84B23896F2FBA33F25A7 +:101AA00070CC79C543E3A7E63C7A338D337A436D36 +:101AB000667C7FEFD2225C7FE7B8CC228DA6ECFB60 +:101AC0009C2DB7507EBCEEC55B8AF87DA462E6EF24 +:101AD000318B719ED76EFE269DE76C88517E9C737C +:101AE000AF12453FCB7115EA1FCB2037237299DC2B +:101AF000BC719F071FD38137B89FD3FC9DC2FF5E87 +:101B0000A4F3BC8ABD1B739CEFBFFF19EA396FF4C5 +:101B10005AF7634DEDCB3B914E6F0F36066A349EFC +:101B2000403539DEE8FBEBCA8B170FE4FA8DBE7740 +:101B300023ECA049F81DEB77BAE8BB379676B67769 +:101B40006B16F0F109DC7EE93C921665F6837E3374 +:101B5000571271F02CFE46F059363DD0CEE2593E78 +:101B600038C8F40CC6E5D0F24E576AA02D1EC763E4 +:101B70007B17251D67E2E2726E2F2770D278991EBF +:101B8000FC3E2B25F11D64C12FB3D77BECF1793DD1 +:101B9000FCE37CB7C71E3F739DC32E1369AFF53FAF +:101BA000D7715EB7F9D4E2671A5D491AFFD4F847D6 +:101BB0000FDD9F343EE28A225EDED9F1DC1FBE4596 +:101BC000F8FE9D0E21C776BDEB94E3393BC7422654 +:101BD000397E2710818C724CBE6794E340FA5C43D7 +:101BE0008733AF77AFCBA277BFEAC027B11B723183 +:101BF0008EF8ED87E60EA5FE0A077E85BE75EAD152 +:101C0000D7433AC573EF783FB6EEA7E331191E0507 +:101C10007FDEF0F03C3A4E0F1F0B3E157C9C256E8C +:101C2000CC894F67792EFACEC6F6F68B9875508917 +:101C30007FA729EE06F6DE9BEC8F20FFF677DEF914 +:101C4000DBDC32F1FEDB796C5FC8CE3B23010DFF9C +:101C50006205DE9753329DB34726C919EDFF1FE495 +:101C6000323B09DDB2983E99CBF0D7AA44B923AFF5 +:101C700083DE63A067AB08675E88CA998BC7A990AB +:101C80009EE97DF4488EFCBE4EFAB8FB87FB2F51CF +:101C9000D13F3B46BE7938C9EFFCE1CB97A884DE43 +:101CA0009109F2E3C3487ED70FFFC8CACF93C7B8E4 +:101CB00008AB6E375FB96432C9CFE7F39E2FFC24BF +:101CC000AD636D7E12553E74279EE7A83F657F8FFA +:101CD0006825917BEFE8F439738E074C1FC9E7B88C +:101CE000494AF2CBCA7EBF0C3791BFF2C736E652E3 +:101CF0007CD5E988E7C39A97C6EF2C78EA621A4741 +:101D0000FA642EF3479FFBF804FA771DCF201C0FCF +:101D1000E60EC80E47AB8BF57378E7B99310CFE7A3 +:101D20000E459F5A9A1EA3559D7EF711B49BCCEE8B +:101D30000FE3FD96789E9BF6F324E7B3534D45DC05 +:101D40008B92C3F842C9959B1F23E9B39C1FFE7772 +:101D5000AE26D621BAEF3EF2CCC0FBD8BB314787C6 +:101D600020BD15E5D89FD1DE3CFAED1CFA774B5E1D +:101D7000F133BCBDE26778BB327795EB1CF27DB4E2 +:101D800077C8CDC8F4AF483B6EC174AB16FB25A332 +:101D900007A4B0DF6F5DA3B07E03CD417C374E3228 +:101DA000981D2E1166BA9AE0236E80EE1E8E226C6C +:101DB0008FFF5094D1475374FCA06D7C2825EB26EF +:101DC00091F32BC7337A11DCD275F4A5712C2FE077 +:101DD0009B911C16EFD2293C7F4278467992837101 +:101DE0003FF52D625631BEB7EFEBBBFDEC7CB31B6C +:101DF000DB8F4CC70F34FD4DA6FBD9269C03C93F92 +:101E00007E18F8DF2B64EFEB08BFC7F85FDF44FDF7 +:101E1000DFD5BBE7B23813EEEF12E7F935FBD9F99E +:101E20009CD3BF350156517D3ADEA14727ECFE2AEF +:101E3000D5AFFD9DCFFD43E8D5122839CDF3B98F3D +:101E4000734FE17CEEBF013359118B00800000001D +:101E50001F8B080000000000000BB55A0974545590 +:101E60009AFE5FBDDA92AA54AA2A450804E34B02FF +:101E700024210B45122004D42220D0314A8016811F +:101E8000F64881B298AD98B4DB699D438520D2DADB +:101E9000A319756CCE69BAE785D61125E92924D135 +:101EA000E05432C52204254E9045A01D3BED74231D +:101EB000DA64313D824BF761FEFFDEFBA82541E984 +:101EC0003E67C8E1DCBAEFDD77DF7FBFFFFBB77BA2 +:101ED000DFBA4409600CD03F1D2403D49BF1970264 +:101EE000307C3C2311F200F47A00D9096054642854 +:101EF000C1F62AFDBB0DA06D338E3385FB6F252AFD +:101F00006C9EFC53F6FBC1462DAC86828879ED7C35 +:101F1000DEDB652B4031CE7F1154533AC0B4BEECAA +:101F20009FCFC1BEA1DB002ABD979EA0FB6775AA0B +:101F30001F459B71ECD74521BCB435CE560053F1FB +:101F400095293A50CC6C5EB88AFFE3947850B2C3BE +:101F50007D4BB633AA2FC7DB764122FEF07B7A5346 +:101F6000508E227E0B12DCE3A3E679DBB6A89BE45D +:101F70002EB2AFAF20B9134B32A2E681E3FA4FFA8B +:101F8000B09F8D7F573300A643656208E52F844AD2 +:101F90008F84F2BA3F027708E59F718A8FD39E73D0 +:101FA00087FCB217712CF928FA7A2944F4719EC77C +:101FB0003EFAC27138429EE9F604D7050BFE180FAF +:101FC000E3AFCAA3E2E80E114EA76437AA01EA8F75 +:101FD000E12017B69F810A88DB3428480486AB0CC1 +:101FE0002AF6DF04EF0B73B0BDB279C871785218CE +:101FF0004F87271ACFA445D1788EA98CC673EC8A57 +:1020000068DCC679A3714ADD3825EAFE4D9B0AA338 +:10201000FA373F561A353EDD5F16D5CFDC5E1E35EA +:102020007E52D3D2A87ED68E5551E373D4B551F7E4 +:10203000737757DD90FEF303F551E362F53FB5E3A7 +:102040002751F396CAF7CA9011E6811FFF880785CA +:10205000A462D23FEA210423F53FD3E527C6FFCD92 +:10206000FA7F98F49F1BA17FF9DE44AF356C6FB106 +:10207000ADA6D79FD05AC7905E714E14EE0AE919EB +:10208000AF0D1AACDB256C1DC89D7BF1FA63667E33 +:10209000FD5181CF95B83495D6EF081EFD5AC21672 +:1020A000D5C2ECD0FFB1456D44DE3C2A2B0DC4AB4C +:1020B00017E54A09509E54549D2E1379A4838D012F +:1020C000E4F7B33ADDEACA08F99EB373BFF29C5D48 +:1020D000C7DA5F18D156F1BDA916F09B0BD973B4BE +:1020E00036FAE7015CB72D8981822F2CDF3E7F0E07 +:1020F000DE77F4652B0E0033F56F01381FCFE53D19 +:102100001FCFE55C65521AFBC87FC8EA2492A7D9A5 +:10211000EEDD69C7F79C979E30E09BC1E0F21BC8DB +:10212000EE52CDE0B7E1FB1A0DB0BA12FB0E7049CA +:10213000F5D826C24E3BE18B622857911487AA72CC +:1021400013FBF0FAFB24D138B231B70E6600ACD4E1 +:10215000FCE1C61CE60F87718DBDA450BD9208D866 +:102160000E3F90C9AE9FBB0FAD10EDE99C91E3A16E +:10217000E17051F8C9CF379B597B69B33DCA6F6E87 +:102180006C7E2141C179CE65C3A240047E5D84DFAF +:10219000746A6586DF80FAC764826770DDB7934929 +:1021A000689FD4BBCD8A439EDAF10F95807A30B612 +:1021B0002DF1A34E60A55161E3B5797CC1B94038DA +:1021C0001063E9FA3D1FC22692EF9E6FB18D785FD2 +:1021D0008FDDC0DED743EFC376393676C46D39EA7A +:1021E000C541EDD1390BC82EF07A48C2FEE26E30FF +:1021F000903D2CF1A61B489E93E03EDD8EF29CB5EF +:102200002BECF91F42A581E43A735F6D028DBB365A +:102210009F360F0AEBC078F2A1C36F4846BF3574F2 +:102220008BE4DEA5B0F799E97AE5BDA94F5A95F0A0 +:10223000FBCE80B7FF34EA7B29B8D9BCDAFC6879D9 +:10224000517EF18D8DD5BF4BCA207FA80333F9C3D2 +:102250004E13F3878355575A5FC2FBAB53FB6E3265 +:10226000E273E7ABBE9D4CB8ACDC218382FAFF245D +:10227000C1FB07FBF4301EE71EF87302DD5F6552F9 +:102280005F7909ED00F698DCAF003DB7873DA78D7B +:102290001BB0CFFD8C78072508D4ACEBDBA786FFFD +:1022A000BCD773C612CF347E3D28F855FF5AD65896 +:1022B000E2537DC2357EF1FE2B9963895F3324CED4 +:1022C000CBD879BB905F4A16AE1B79A520AFBABEBA +:1022D0002A4B223FB1EFB8B388E4D483F76AE4BA5B +:1022E000F6BDBF2A97EEC359D70DC94BB6E947399A +:1022F000EF012E678FB08F15C1A422D23BDA9DC5A6 +:1023000081E356FDC76BFDBF257C3AF7BCF2388DE3 +:1023100029BE313C34FFB4379EC7231071CE2D70D7 +:10232000C13897AD47510721DE4DF9C2F5FCD65EA5 +:10233000F20BC8AB2B3A747C99E4AF2A81FC82057E +:10234000DC0AB5E865DE9B8D7A6C3CA083A7B16B97 +:1023500023A7A6F99F12ECCB3AEE7FB06F4EC1389F +:1023600022FCD324C7BF2EDACAECC7635D3383B91E +:10237000442657F1E1AA0A7A2FF4A21F47592BF1FC +:102380008FE2C16CD874280EE59CB103F3031C37AF +:10239000F32CBFAFF9F55921DD1A63228DFBD91754 +:1023A000B28D208A8E03B30F977F4AF3CE8688E7DB +:1023B00046890FB31C7F5F7C98EFE0FE2190CDFD36 +:1023C0007B2014AFFAD3D9B44595F9C817278F1FCE +:1023D0002D8839D9B1511AC836A31F5EE468DEBE14 +:1023E0007D02D26122C785FA8DF45B29623CBE96DC +:1023F000371E9EC2FC21FC05A522BCEC42E61879E2 +:102400008AD1EE78307647E59DA123DFD8FA701D9A +:10241000AD4EE5BF485F4398D7905F88D3F7191D4D +:10242000A3ACEF4DF2AFC8FFE71C3A26AFB943F2B9 +:10243000A8F87EB3E20109D71067B74F93A5F0F86B +:1024400032078F4BB547CEA719515FFDBAE3B63CB3 +:102450009CBFA6FD0D1B2E1F7E6CF3AE73E03CD51A +:10246000E73E9841A10B199E569940386524923D4C +:10247000E5EBC1AF2F1C29876F072E06295FB72315 +:1024800089B5391D125B9F2FC4D739D0D1E88CF4A0 +:102490001BD79EFBCFCEF1A4B73D636005F9E3FCEB +:1024A00060D106E231C962405DBCFE552E9BEF094A +:1024B000473ACFAFF5A0A7EB00AA6E290EDA63C0AA +:1024C000E770DE81AF64364E9B37BF63AE6C471E4C +:1024D000E5859A0E525E18173429A4E7B89781E370 +:1024E000128C637ED1D7B510287F1D74805BC2FB30 +:1024F000ADF1431F132F863A4DCA2E89F06B022788 +:10250000CEDF6AE4F133070DE10D6BF8BAF6BEB821 +:10251000E0CF81FC15F2C3A3D27D7D13DC628DC4B4 +:102520003D81C9FF4B07E7576B7C486725BF8F9CF0 +:10253000DCC5E40ACB09ECBD9A9C39AC0E68350EBB +:102540005D78DCC5E4B2131F7280CB09C12CE515A0 +:102550007ADEEE61EB88B32B6EBF34522E5F01E65C +:10256000C56877CF6E816B764E76EF8B0FF7CD68AF +:1025700013AD1920FCC229968784FBE8B04AC2CF6C +:10258000BFF1CF67B66F9DC3EA23BF8C7CB0609B61 +:10259000E0A47572FBC2B2C933A690E3E0469C2C5E +:1025A000667EFFDA78E4BB95FA563ECE9D68B79416 +:1025B0004BCC6E80ECA64EF89987A4D085DB50B545 +:1025C0005F860E1628284BCDD1B7196FAB75C19712 +:1025D000F2F17E59BC3748FEF7AD8F7460C3F57FCA +:1025E000FE5A9C5A817864EF6F4EF65847CEF7D466 +:1025F000D92DCFA792BEF74B0A228D79E1501AC987 +:102600005717FCD4E8C17661C7EF8D149F5639BDCA +:1026100047C80E4A3A1AE6117EB3A0A9D16E657E6C +:10262000D14B3C0DA470FF317C6AF2AE8608BC2F02 +:102630003978DE0243DE9BC96E82C23EBB28FFC1F1 +:10264000B65DE461ED0756662AF9E1E7FC703015E6 +:1026500070CE2D70389570D6AE0FAAFA45C4A7DC9F +:1026600033E6D59E08BE5D10F67E41BCEF1F9DDEB1 +:102670008F0887EA039F186DB82EDF1F0269149F29 +:102680000298A7D9BFC32FFA62ECC6A71F32D2782F +:10269000DF45607E04F5BA3511F5B4E74CC79435D3 +:1026A00056263F24E2BADBCF9998DF6C4FE7F6D786 +:1026B00070FA7201F9ADCB9DD537135EEF3B0C1A62 +:1026C000CFCBE2C99EF602F3639A3DE6913DA2E8C4 +:1026D00079C4F362EAE7B0F95A8DBDE5CCFEDA754C +:1026E00040F6873C67BC479EDB29FFC8B323EFD980 +:1026F000F359CC9E5B7B31E061DF8F7E7C12EB97E0 +:102700002DA37E6BEF7C3BB3671D425B4876193A85 +:10271000C8E609604C23D549501999A796396C4CE5 +:102720005ECD3F563AB8FF0F642B896E5C8F45969D +:10273000A3EC20225EF2BE88A72B9F37FCF4C509CC +:10274000644D222E88BCAC4BE4C1E02D62FEFEC776 +:102750002296D5BF53BAB805D75BDF2373FF2F7816 +:102760007250E4C98737A7B03EC50B05F5341D5B31 +:102770000FFAD3199E4DF3D0C6A06451D3216A4BF2 +:102780002B03F3107198B3A2F790819B732EF1AFD6 +:10279000EDE00F72F5C4F77326884311DBBE19FA1A +:1027A000F875C4E1912EC47F94B884CB61FC4304D6 +:1027B000181FAFC79B41A9EFAED96E4CF99F1FFB05 +:1027C000037D1CDA0F1103F1C87B7ECC4FFD28502E +:1027D000BBD333D58938FE36C93BD589380E9EF830 +:1027E00026997C7AFBA94F6CE4EFDB8C9E5CE25966 +:1027F0005B06D60BA3F0738293F3A7D8149DA76B47 +:10280000ED5227E7FF643F3C43FCA96B93ED2AEAB6 +:10281000BBBF4DF618318FBAE0F126EB11D28BE039 +:102820005F3E9BE2BBA87FD771D8611DE52F18677B +:10283000D6BF6888AA4B6BC4BE4616F46D4B459C48 +:102840007C2F4BACAEDD18938FD450FE5240F54533 +:10285000B391D653F572CC3C94C714D0B8EFAE7395 +:10286000973AC53E472664521E833C62F5F4D06910 +:10287000D9BD8B62A01EBA4DC8DF3D3A8E13FA4D0A +:10288000668F5A3E637279E691DDCFD3E28AA85B08 +:10289000875A2595D9CF6EF4F3D82FBDA83403C736 +:1028A000E154CA0C5A0FE765A99E8F2F0DA633FB82 +:1028B0002BF1603D8FEB5E8FF5BC4AEBD6F23CD539 +:1028C000C0D68FE197E579B3406DB4E1B80DBB2573 +:1028D000B6EF53BDDB1095E7F9043E353B4E1CA126 +:1028E00072B23610735FE0E38BC1E70DFA316B24EF +:1028F0004E8F3A45BE97066991F91E743B47AD0B62 +:10290000347CB43CFB4F069E5F7C20E6D7C6FD8B33 +:1029100093D7E7751E60FB4735AAACAA3C1FB4AE3F +:1029200041BEDC2FF872BFE08B0FF8B8DADD921AE7 +:10293000A278F533AE7733FE112EEB026B16A42A84 +:1029400023795525F0D8D86260F92FC02623D9E71E +:10295000C69D31E3042E5531B8D479A518F9783ED7 +:10296000FEB7CA576DE0FB35D5C82FBFF2FF276F02 +:10297000ACFEFE5DD3DF149812A5BF454937A4BF56 +:10298000D83C79EF9129167A7EB83B83ED4368BC39 +:10299000899D6781C8B317EEE0F9687FC73C4B3E5D +:1029A000D553C7F56E09E729EAF95F5B3EE251D8D6 +:1029B0002943054E31182C7AC68FEBDCD73D71992F +:1029C00082F1A1B047CFE24B514FA14A754D614F03 +:1029D000A1253381194F12D50B380F8BCF83C72711 +:1029E0009ECC233FDB3DBF98606F385E68A13C62A0 +:1029F0001FF07D0DA9A738A92F22DE743BF9BEC6B2 +:102A0000B694FF7996F2FC857B0D6ECA47161A863E +:102A1000DE9FEDA2F7EBDD0DD8AFE959BB258EF4B3 +:102A2000FE9AE4A674FC486FBDEB47A4DFA0C16E1C +:102A300062F23E7C90EEFB5B24F7241CEFEBBC3D86 +:102A4000B715FB85CD456E82597B5FA14379A18285 +:102A5000F2C5711656C72FBCC9C0E2EEA5F1965F4C +:102A600053BE54E5695E40FEF8D2DBFB8CE40F06F2 +:102A70005B2548C1851C4939F41B3FAEF3D29B2727 +:102A80008C9494CF6B3B61ECFB8E7CA25F9521C450 +:102A9000EAF72623D541B5CD5ABFCF487AAA14F913 +:102AA00055DDCBBF67FD2AAA13F07D553B6555C1A7 +:102AB0009F873ADF3212DE752D128C4D8FB8FFB230 +:102AC000C4EE6BBC5F0B9C076B857FAA16FB90D591 +:102AD000B40F89D7613BF7371AEF1FD8BDE40885DB +:102AE000EF754DD17EE841C1F30D5497B2FADB6B1F +:102AF00024BD6ED811334EF0FCC1EFE1B93549F871 +:102B0000F31CC8219E5F9ECBE3C9E513F1963C5CA4 +:102B1000D7E563B21BE03BF9CEE2EF71912F0C8752 +:102B2000742C9E69E3063AFECCE28DEFF8B091F288 +:102B3000DB05C12F983E2A8207E613DE7782B7862F +:102B4000F0BB3368B193FD57F4717F501E34A9B4C4 +:102B50000F7E2704B6929E07BB5EDDEA24DEFC1BD7 +:102B6000E70D087FB741E0BA41E0BA011D7E12BA15 +:102B7000D8AABC032F61BA0FE5C0FD507940F8A177 +:102B80009DD13863E4B98FF4551734C1D378FF0E63 +:102B9000E18FEE68E1FE28364ED6897D80C171B99D +:102BA0008BD97E2BD6BB94C7D5B444E35F27F605FB +:102BB000EA62E2F0CD497CDFEEFBEAFF583DCD8DC5 +:102BC000D153C510E74F39C53D5C7F77684B1EED8B +:102BD000DB6978C5EAA95BC94C1CAD9ED5DAF7451F +:102BE000DEAFF517237129DF0CD89BAC9175FCABD8 +:102BF000493CFE54CD92FDA4E76BF5CEC443058A53 +:102C00002E5CEF609DB332690CAF7BA6E1D4472701 +:102C1000C8E07285EB9DA7525EA828A47CA585FB21 +:102C20009181129C2F91F27960FECBD76252A94E0E +:102C3000F1217F589D43BCC1B63228DD4EBCC1FA9C +:102C4000611DCDBF84B68E1187251D3CEF5932FF23 +:102C50000BC6B76313F97A87F5CAD8D1EA09AD8EE6 +:102C6000A8FB8AE7A9DAF53AB47B1A5F1794585D96 +:102C7000DC76F0EBB474F49F839D57D2D660FBA250 +:102C800058BF96A70E619E9A21F214CA9FD77395DA +:102C9000C1064C871F431EAE17710EA4ADCC4EEA81 +:102CA00028D925BEB54B7C1F673F5E9889FEF78308 +:102CB0007896C70C9CE1E743F4FC1398470DAC0DE4 +:102CC0001C76E2F8CBAD128B7FEB31C7BDB570A49B +:102CD000BDD70A5E36C01651976D656D79F6DE4F29 +:102CE0001E277FD46256C8BF0E74341AD9FEB21A9A +:102CF000F17CC6C87CA856F0B7F67BF6B55E4D12DF +:102D00007152F012D7C1F2DBC163B2DD2431FC7E17 +:102D1000353E122791FFB41D8C637A1E3C61552904 +:102D2000CFFF5CF0EF92D8776F2891192EBA59BC7B +:102D3000CDED7A2B83F44A7AF0D23E4AD75B533CEE +:102D40006C9F4F65F654BD5BA6C3BEB0FC010BDBA8 +:102D50000BD5FA1ABE3E812FCA35D9E80ACBD5AEBB +:102D6000EFB3B947B11B493AC8F4A693A2EB5CDFB5 +:102D70007EB9528DB0275CCF6AF26FFB053F403FB2 +:102D8000944C7EB9334961F23504B99E759DBCC53A +:102D9000F72FE7FB3606F6FE11F7CBFC3574FF7212 +:102DA000BA05184FBEF25750FF910C99F9A9473E4A +:102DB000A8CA8288F783C4EB719F612899D5C3277D +:102DC000744C3EDF89E1E48956F283CDF3ED79E47A +:102DD000DFB87F389261D948FCF6D37BC786E759C4 +:102DE00098C4E33CD07A53289B7991CF2BD6BB056E +:102DF00096321CB6089E75897C14EBA633648FB19D +:102E000075D3F5F2DD88FA8D3D7F79AE72F247C851 +:102E100083C2637A3FD5EBFBCE723FD1D0B9E17765 +:102E20005407FBCE9B80FCC4235D1BB2280E83D7C6 +:102E30003B95F2BBCB5D0F4E65FB97D21626979F55 +:102E4000E44BA1BCE97432E543B59DA793595C6F8F +:102E50009FFE02E5499817DD41D7315F61FC2BECFD +:102E60002966FCDB77BC3829930407B785E6AD3DBE +:102E7000A6AF247C6A8F15BF5741F94B4F19CB93EE +:102E8000B4BCA888EA71CA938E4D8CCA93FA057EA9 +:102E90008307E2D8FE8704199C3F30318A3F356DA5 +:102EA000EFB07CA2A643F644F2E8DA732E3DE38D40 +:102EB000C1A5B0F91A029287F1632F6F6B3AF6B190 +:102EC000F5551B024CDF0D2D067EBF95B7004DEC6E +:102ED000793F38FD84C77B7409F5506E5427D0FEC6 +:102EE000FABBE9BCBE88D5C77617DF4F78F79CF7E9 +:102EF00066E2CBBB73BD59F651E2861FCA78DD2D61 +:102F000009BCDB0C2CAF8C1DB7CDC5F77B6C491011 +:102F100075DEA8B5F52ECE9F7223DFA78ABD7FABE5 +:102F20008BD7CDF8EF191DF2E26485C1FEB4A82756 +:102F3000C6A1BFBD4BF8DB65771A58DE71529C33D2 +:102F4000DDA5F9DD121EBFB5FDFE253BE1492CFFD5 +:102F5000E14BC863E7604B3CD17EEF6E915F2D5B28 +:102F600014735DE453777F4F3E35C325FCE16498CD +:102F7000CCEB06AB85F645BFEC36D86526B73AB143 +:102F8000327FE43A357F73449C0F75A31FA4B621AA +:102F9000E743B64FF5EE8173BF71303F1A07197CD6 +:102FA000DF91EDD7D75E67BFBEE19A9DFE308A778D +:102FB0009A9EFA29CFCF1BA9A7A502EF5AF3252382 +:102FC0003BB7844DDB7572F89CD264F07A52711D68 +:102FD000868EB9213ABF6CC831B17CA9FF764925EC +:102FE0007F8F72A69922FC7DFF389E7F3DB25C6286 +:102FF000FBC207723E6471BC36D46B245E4D6E5BBF +:10300000F324B35F3F9CA27A49D3E762338F9FD703 +:10301000F4A8AD976E2AB43EA79FFB65176B693C79 +:10302000C5CBBB447C5C5C12ADBF2CE85D40FB2390 +:10303000F77824962F5D4FEF4B574C7B87DCDF8D65 +:10304000EAFF9F5CDE875D64EFBDC3CB697FF7DD80 +:103050009C4FD328BED65D87CF7E81AFCFC2CFC570 +:103060007C167E1EE6CE521AFB101FBDC3BBD9458F +:10307000FB4FBABFD8A600CDD3F7AB7A89F4030CC7 +:10308000FFEBD9D13631EF36979DDB8B8B9F0FC588 +:10309000519FECD9A04E203F01793776CED7B0FFB3 +:1030A0006801E969E0C0B10263843E2FD5A33FA067 +:1030B000F8D2792859B146F24D27F8A667AD242DEC +:1030C0001571339A7F97887FA4FFBD87EEA2BAB0AF +:1030D000BF6D994B5222E26AFB49DBA48879FB83DE +:1030E000321B8FF5D8E4BB1322E57C92C9D91FE0CF +:1030F000F301F44D5E961F79BF919F1B99FB188FCA +:103100009FCADEC4CEDD351EEB81F3B8AE6309B0D5 +:103110003825D61D30E20FAA33BA4C2A9D53D07EF3 +:10312000BB23C24E8E0A9C67627140FC9C057E994F +:10313000E69D8933DE4B7D3D84E84C6E3684647EAB +:10314000DE3D0188D73304AF67EA4307A402368E19 +:103150009D4B95422F1B772B0CB1D603763DB56561 +:10316000E0666D89397407B993BC40807D97144A35 +:10317000D63B2E98D951298CA6BFF0FAF57041E3C1 +:10318000290EC6A487EDE3C78E1B1676EFA6DA825A +:10319000F4DC0F6C1FEE16E893E925B3F5B088BE9A +:1031A00027BB450FE6789477EF611DB3E7AE3E4548 +:1031B000257FE64E12CF7D86CF617FA687DB2D85EA +:1031C00020FA6E455B6F2C0EA5381FED0BCED46335 +:1031D000E5CB700CB1F7DD4682E3BAE782A2A7FE29 +:1031E0001F5DE9623F85D769F3449DA633FB191E35 +:1031F0007F12F191CE736C384F69930467E97C2696 +:1032000093AF579BBF14B3C1C4421ACFE31B6D8564 +:103210009F75F2731E1B3B9F9B6F27BCA450B2EEA1 +:10322000AAE5C6711D4C0626B7EDFEA181C78BC36A +:10323000E75DEEE0D1B3F45D8EE4F1B0EF7ADC66E9 +:103240006B88F27364C7A5C8BCFBAA6BED5FC9DECF +:1032500025C5CEF0022F28947F8C0D7FEF02579367 +:10326000C2DFD3108C1793C3E7FBDAF735BBD5A5C4 +:103270008A0EF5B2C26576935E0ACD6945540F3663 +:10328000DBBD7F75B1EF6C5A26B1C9F4EAF4CA848C +:1032900030DF2DE02921BCB5737D49E8EF7AE7F6F0 +:1032A00064ABC4730BBA7DFA2EE819B417B373B4C8 +:1032B000EF8FF8793E5AA142DF1DC113F314FA2EA5 +:1032C000609BC3EC7E5AA2141FD76709AFAFD1CC65 +:1032D000BF276834F3EF0260EB74B67FF690388F47 +:1032E00068B4EAB2A9DE6A84783795F49ABC0F25EF +:1032F000703E3EF4DF16763E1A2BF7D7F1DE9C3196 +:10330000D3C3F23F2ABBCF62EE1385E71C0D4F5D9E +:1033100018CF156A46639FC2F09B46CF4F33A9373B +:10332000D1BEC82A13FF7E49C30D15CA486D17FACE +:10333000D0F0B393BE691D1ED4B7C6978C307ECF34 +:10334000C473DC0CF4E544267B56217F1D8BCBFF38 +:1033500001AF6B7F8EF0290000000000000000002C +:103360001F8B080000000000000BFBCACFC0F0A3B9 +:103370001E8143D1F8E8389D0F534C941182D7B386 +:10338000E0D78B0D5B3122D8FEDC0C0CCA9C0C0CF8 +:103390002A40DC07C4FD40FC1E880DB818180C81BB +:1033A000380DC84E07627B2076E386E86966676061 +:1033B000E806E2C9403C9B9D74FBCD251918CECA96 +:1033C00022F8B2720C0C510AA49B338A87267633FA +:1033D00042E5C76BA3F2BB7419184E23A949D02646 +:1033E000CD7C466306062663DCF271E6A8FC504BF2 +:1033F00054FE5D3354FE4577080D00AEA32483B818 +:1034000003000000000000001F8B08000000000007 +:10341000000BC57D0D7C54C5B5F8DCBB77EF6EF6AF +:103420002B9B0FC20642721302040CB8C480C14A1F +:10343000BB89A0A0C85B502B585F5D02242004828A +:103440005A492BFE73212104126041D4A0881B3EEF +:10345000142BD8A0A0B6B576F9D0529FCF4645A57B +:10346000ADA50115D4024DB5C8F63D7DFCE79C998C +:103470009BBDF76637E0EBFBBF7FFAABC3DC993B44 +:1034800077E67C9F33676665318564E6117211FECD +:10349000BE47C8040B21644CBC244155206309F984 +:1034A000919DE09FD6CF5C36D61312B511129B4B7F +:1034B00048A78B76946AEDA49896B7DE28922C42A2 +:1034C00052E17D859026A1F6C8E05242D44122D92E +:1034D000491FADCA999E1A72251F77371FF7B97A0F +:1034E0003B961DF55E2C9FAFF761B9AF5E21D161B0 +:1034F00084BC585F84E5CBF57E7CFE8BFA322C5F72 +:10350000A90F60F96AFD242CA3F5412C0FD6CFC07A +:10351000F2707D08DF7BBD7E1E9647EA6BF1F91BDA +:10352000F57558BE59AFE2F3B7EA9BB1ECAC0F6347 +:10353000F94E7D1B9647EB23D8EFFDFA5D581EAB85 +:10354000EFC0E77FA87F19CB0FEBA358DE4ED20860 +:10355000E947C86DB79DB7CFA2EB1DF6C47DEF4C10 +:10356000CE2464FD18D10FE01AF6C4C7BE50717C9A +:10357000DDEBBFB1CCE8480097EF1301C759EF2648 +:10358000D8BEFEC0EF893292907563BA7C2AAD4FE7 +:10359000E6DF19BEF3A87D5671BC9F799C4F8885E4 +:1035A0008D63A5EDB4DFD0CDACBFD63E19BE3326BA +:1035B000DEFE54DB3BF6D92E7D3B7BFFE92DEFD8B9 +:1035C000017F6B63128922DE554268E950BADBFA4B +:1035D000513CA71CB3115B3EC5BFD241BAE838EBE2 +:1035E000C63D12154B61DDB49B02EB7C9708140EAF +:1035F000AA9B203D2830C6D5F1EF5C4D449CC7B056 +:10360000278EB2EFDC7A1ECB57FF211342DF5B77A8 +:103610009B1071D2F1D78DFFC217007A539FB10072 +:10362000BD21B92AF09F2E5F908EBD7EFCFB3E959A +:10363000C269ED37EFCE980DF4379AF8E17B6B0F46 +:10364000FC9C28D03EB21BE1D7C0D7BD76E6AC3C8F +:103650006F7172BAA49444C432BA5C17094412C0A0 +:10366000F75F0108143E166F04D7E4A0FD12E1E1F4 +:103670005F898CFDD6BA83EF015CD4DBACFE9D7410 +:10368000DED7F9A3E4942B3E6FA87F44EBAEBF478F +:1036900089C50DF3FECC67A1EB7796C957A5D0D9A4 +:1036A000B8BABB8FC1FBAE6BAB02B0F675A3BB7CE7 +:1036B00055B4BFBDA813D74BFCC43F848EEB285232 +:1036C000C9EC62808305F16A9ECF6C80773FC0D3DE +:1036D000573EC0894687EFDDFAAEBD52D7FF698DF0 +:1036E0003E04465FA4356A9FE68EB73FA1B5A7307A +:1036F000FA217663FB66131D939C24ED560A68C479 +:103700009718D92920DCEDD347F69E776BF4B7C81C +:10371000072E7FD41E4AB02ECA2776903BA9A5A2B9 +:103720001FE0B56E3CE597E2F83A2FC577CD1C2E29 +:103730006B4BA7BB61FC4BC9AD911D2289167199DA +:1037400049FF7FE5CB0E3AF3787D7434DD50BFEA54 +:10375000C80043FF319D0586F6AB8F8D30B48FEBEB +:103760002A31D4BFF3E93586FEE3BB2B0CF5EFC558 +:103770006E34F42F27B718EAD7D97F60E83FD13BE2 +:10378000DBD07E836F81A17DB272AFA17E53D10366 +:1037900086FE37FB1B0CEDFF52D662689F1678C879 +:1037A00050BF65D2E386FEB705B71BDA6F9FF1AC59 +:1037B000A17D66E80543BDC6113A0EF8F9C1BC5FAC +:1037C0001ADEFBD7DA4386FA7B844C4A845F2230C8 +:1037D000394329C87BEA0ADE9F8A382FD01CD07172 +:1037E0003F46A745ED49E4246F7F66C73BF6B9061F +:1037F000396965749CCDDA7745DE49FCFE20CE2719 +:10380000A4D33EDDAD6F67F3BAE21F54BE42BBA442 +:103810007E2BF9EAF6FAB1BF2657297D13720D8582 +:10382000AF3A5055F17B743C2A2F2D6CC9A48E30D1 +:103830003945C8BDF85CD3FB2487442D74DC06777A +:103840004EFB1A80091D5BCA847AF136A88B4A8028 +:10385000742580ABC52B1BF064862F71A55362EED7 +:103860004BCEAA083F75222992E0FB82C3BF9CAED3 +:103870005722A101027D7E410CF960F24B2DEA6FC7 +:1038800042F9F1FECBC7D37F42FF13426405F657DE +:10389000108E0D234900F4869A2D4776E6233C6D61 +:1038A000204FB4F7E803A58BCD57BD38D85067F348 +:1038B000BD64FDEB61C6BA36EE4F8CF0A47086FA9B +:1038C0005DBCD26BDD7E394EB716E8C7EA8A289018 +:1038D0008B28078DEDDA772EA4784691548A473BE2 +:1038E0002B973A3CDBA0BC90921B211E428AC5500C +:1038F00005C04DAD60F0518F3B230D385EEDD5C155 +:103900009100DFC4F602212B187F7C3859D4AF23F5 +:1039100019DE1AC06E1BA6A3831C3FCA71BA6AD4F3 +:103920006FE6FEB70B321BDF455145C7B711466343 +:10393000A996D0EDC218586D9048384F3F0922BE65 +:103940002611B04BED1A3CC373B1EEE276E601F7F7 +:10395000D863218AE7B501D90F63550A0AC783DF07 +:10396000077AC056269235B4B65679C70EFCD19C5C +:103970002F67835CB749B5C44BEBB642CA0709F45D +:10398000C8E21E39F120B91CBBD88CA722FA3A9B99 +:103990000741386AF30F0FEAB417005D8EA776313E +:1039A0009DEAFA6BFBD62F2B397C5BC02EA6E53A3D +:1039B000657A2A41BE253381BE9BF3B344E4530E9E +:1039C000A71EB8E4BF6F073E5DCDDF5FEB7F07ED5D +:1039D000F4D59A1E37C1B179F44984CF2C81E9E33B +:1039E00096918E19910470992578B0BD19782A1393 +:1039F000ED2BC65F267AA12DBE4ADA6E57BC256B29 +:103A0000E8F813464A33812EDC6544B121FF065C99 +:103A1000D9F4FB0EDE5B524483FC706732BAB57F8B +:103A2000284414DADFE563DFB3B9482480EF2F318F +:103A3000E0C551169A4246513BE91F167C8FCE9144 +:103A4000D9114727233F5ABD6C9DA488E1C94BFF7C +:103A500077B1808EA7C806BDB1BC5CF647E9779602 +:103A60007A5C484F563D5EE9779DDFBC1084F15784 +:103A7000E5DCE3584EC7BF50DEB40AD8D2F2E1E429 +:103A8000CF80EF2CE6FE83A6FF6E70023ED04A6721 +:103A90009787443360803BFBA403CF87ED6F1CD630 +:103AA000CDF315C19D89F2F56A7235CA854BBC7F8D +:103AB000A13EF2C6E121080FF172E879A589AF9B1A +:103AC000F235BDA5FAA6E9ECB2F302D36B442D475B +:103AD000384B9C9F9BC6936EB05BD7E5CBCA0ADA86 +:103AE000452A93A3403AF0D74DBF0FB6190179ADDF +:103AF0003475B2E73F32C8CDD5FDA7FAA37DC04DDE +:103B00002A34E99B4BACBF0EE0A7EBFF31C0CF19C5 +:103B1000879F8D0453A3402FE149063F7655F9FD59 +:103B20004A94FE73D580470227880E8EDFA37CA8B7 +:103B3000E30F5B4E84E8BFAFC9C55BC44037C861C3 +:103B40008BEC4739450A64F447CCF32B1299BC89B6 +:103B5000C3D92E111D7F902911843BFD0BDAB33898 +:103B6000FCE85F8AEFF57F00FCA88E8E3A47E1F310 +:103B700046A984CE2793A8CE2BE9FB1291A03E48FC +:103B8000CC47BEA5ED13E474E0DFEBFD20079BB846 +:103B9000DF47BCED3EBD5D3E4864788DB7477CB7DE +:103BA00019DA99BDD3A4D9F5DEED06BAE8793F8DCF +:103BB00024F43FFA89CCCE1E247A39FD6C47FF6D80 +:103BC00075E69418A02125FB7A7F25F0AB97201C81 +:103BD000343DA1E905AA2F0689FDE2E3C98541220A +:103BE00060BB51FF2695D726BD9B52649403446F5A +:103BF000CF14C07F73BC482FC4ACEF7919BCF1B2AD +:103C0000F8AA97BE2489FDC5692293C344CDC4F5A3 +:103C10006B7C45B83D61D5E882307AF5F0EFCA306B +:103C20009FC180E7080EEEA46E15D4DDA416EBE765 +:103C3000CB4AA200279BD4D54CB87E54F313F8513D +:103C40003C0E936C1DEBC727D60FE5A207F16971F7 +:103C5000D59210D2F19D68070A6A885C447B30CC0B +:103C6000F5AADF07785C555F473EA28B711C9C8CE0 +:103C7000FEB9941308807F6F0122C8A6FF7795B222 +:103C800052F22B7AFAECC123598EE3592958609DE0 +:103C900056977D16E801ABCB3B0DCBA211730528DF +:103CA00053AFAF1391AD12D393361EA5AB79228CCF +:103CB0009719427E96BC412C892B13ED57DA5F0988 +:103CC000269C07A703DE2F29DDF5D08D0607458644 +:103CD000F1CCF4E428A51E8988D54E986F7F8EED2F +:103CE000FE739A960088DD24DC3C94E2AD7FD7AC6D +:103CF00029A077DCA07FE83A5716971C01932FD5AF +:103D0000EFDD70BD02710022001E56C360D7C0787F +:103D10003F585E8EF10FFA37800A8B15C172E61F8D +:103D2000044C76ABA8489A7D26F669EF08176DBD5E +:103D3000DF4FB67E1BD1F115EAF17B2ECFBEBA93D1 +:103D40007D4FA5FF037E4C33E9D9D480511FB84D78 +:103D5000DF790E6089F05EF2BFF23D2FD96857C05F +:103D60005E2914BD114ACBA9C49B067E946302F55B +:103D7000EF68DD9BD3ADC2942E859795DC8F25949B +:103D80009FF5F47F88CBD7ECAA4DB39AE8B8E74B00 +:103D90005D7EA0E7FE549C66A4F75E4F4B3D31F07C +:103DA000734BF136A4EB06AAF00AC03F2816D15E89 +:103DB0005F5DF8BC57AFC73ED1E4502FFA208A347C +:103DC00096FB93143E9642319032EA9FA70FB3FDC3 +:103DD00074B9F4E1BCD3888F6F8BAF2FBE257DFC07 +:103DE000B3DF5B992C3EC1E559765523F35794BE5A +:103DF000FD83DE78DD88787550BF26917CBED08348 +:103E00004FB57769D02BC6B880F586EFCFD8D107EC +:103E10003CAC33CCFE3F1B37A5CEA27C0CF6ADE408 +:103E200035F841AB958D2AD8F3E7C12E07FB305CFE +:103E30008EF16152C8E2B5308048EB294A20C2FCBD +:103E40009B08D1EB4139C71877B3643A8CFA7B866B +:103E50002AE8E79F5227E33CECF0BD4C8CE746E0B4 +:103E6000BB162F89A6A0FDC9F0079F62F180072E1F +:103E70008B0E347A053398D1ABF1BD553925241119 +:103E8000FE7A7DEF56E37C93CA25F37B2E4939A554 +:103E9000B35392BF2791533A7BA742DBF7E178A255 +:103EA00076DECB422A9507BEEF9310856F133465FB +:103EB000433C94A03E6BF29578519FEF124C7EBB31 +:103EC000C2E84749C7FEA29DE94DAD9E7C3EECBBD2 +:103ED000F17D2405FDDA64FD1BEACB1E9628713ABC +:103EE000EB0E6D92281E1B97076604D1BF3DB249A9 +:103EF0001A12EF5763D1FC76AA3EC7C6F7072442D1 +:103F0000FB21DC4472F12A78E825CA588026FBB3ED +:103F1000934E6CA74F391E89D0E3CFD021DB609D33 +:103F2000189F3886FD60A08B186FEA6275FA22D45C +:103F30005BAC8100CE4B0ADBEFA1F06A49E17585ED +:103F4000D7D378DDCBEBF9BC4EF505D49D32ADD39C +:103F500032C51AF662DDC1EBF9BC9ECEEB69BC5EE0 +:103F6000C0EBC246ACB7C86CBC3552848DEFE0756F +:103F700085D7D379DDCBEB05BC4EB6B1EFDB58DD91 +:103F8000618DB0F19DBC9ECFEB19BC9EC6EB8379D1 +:103F90005DD886F564F8731452F81BE44367BC8E51 +:103FA0004A84C3B5A7DE656A67F49221106E87A9BB +:103FB000D960B71D98757F36C4431F3D71B50FE8B2 +:103FC000A7E1668D9EFC283F49CE4D28C7FA737F36 +:103FD000AEE1CE1518876808C98C89787C26DE5E2C +:103FE0007204F4F6F919A21F1ADB92F82FCF723B74 +:103FF000FE191E97799AEF57EEE4FB95DBF97E6583 +:104000003BDFAF7C92EF573EC1F72B1FE7FB959B41 +:10401000F97EE526D8AFA4FD36F0FDCAF57CBF7267 +:104020002DDFAF6C81FDCA6140EF7558AEE2FB95A4 +:104030002BF97E6503DFAF7CE4CE92DF16D2F59DCF +:104040007789680F24C347F16EA3FC1CB1C3283FD6 +:104050008BB6A41BEA43370D30C8F7C256E3BE4502 +:1040600041E308435D595662A8E7DE778D61BC9C49 +:1040700085C67D8B01736E34D4FB05A71BFAA74F51 +:10408000B8C350F75E5B69A87B4AEF36D45DC5F7CD +:1040900018C67314FEC450B7E7AC30F47FDC52800E +:1040A000F42567AE31F4935C1B0DFD6A1C81CF2DA6 +:1040B00020EFA6645E967C237F57B3F4F2D2AC1F48 +:1040C0002CB92410403DC7F411C66821AE3688C50E +:1040D000AFEC1FDE7004FC175B21D353E6789579B3 +:1040E0003CD9F5D431957EA7DC73C4D7A5A35BE298 +:1040F000D3BD47979A2A3139B9E64146DFAD0F263D +:10410000A673D404741DADDF248E17BB258B418F9D +:10411000687E4DEB8302F6FF67C7D7DACDE3C6BFF3 +:1041200047713D566FB744F87CA88ED0D90BD6AEF8 +:10413000B4D904F53CF3972D9CDFCB27F84F3452CC +:1041400078AFF412BF8DD657BA2A02CC2E1115942F +:104150000FCB6E46BF5EEBAFCDABD1359DC917A27D +:104160008B5BA29C7218E20A2B33FBB6DFE4980546 +:10417000E37F969840A2542FC95270523EE55FF9F2 +:10418000A8C5BF9CA07E4A181F206423DB77F619C0 +:10419000E3A68D734CF28FE7655835F9965981CFB8 +:1041A0001BBD7DCFCB06F382F9F07959634E2C2DE0 +:1041B000B1149CEFB85806D6CB6269585E1D1B88B7 +:1041C000E5D8583696636283B12C8DE5637955EC5A +:1041D0000A7CAF24361CCBD1B1ABF0B93F361ACB39 +:1041E0002B63DFC1E7A362E3B01C19BB0E9F17C7A7 +:1041F000CAB1BC2276133E1F119B8CE5F0D82DF876 +:10420000BC28360DCB61B11F6039343613CB21B1D8 +:10421000D95816C666613938B600DF2B88CDC7324B +:104220003F762F3E57624BB0CC8B3D80656EECC71E +:10423000580E8A356099135B8EE5C0580BBE372047 +:10424000B61ACBECD843F8DC17DB8065566C339696 +:1042500069B1EDD8EE8DB563991A7B169F7B62CF5D +:1042600060E98EBD80CF5DB1BD583A63BFC4E78EB3 +:10427000D8CFB14C891DC2E7F6D8012C2F85A74BAA +:10428000D9C1651F1BF79FC77E68DC7F2E3D6A94EE +:10429000E3256F1AF79FFD878DFBCFA35E31EE3FBD +:1042A00017EF33CAF111BB8DFBCF453B8C727CE815 +:1042B000963B8C7A6493518E17B4DE6DD4238D4671 +:1042C000399EBBEC27463D72DF0AA31E59B8C6D003 +:1042D000EE9B6394DF59E431A39F3E619B518F5C59 +:1042E000FB53C378AED2E74D7E4D04E58BA3F817A0 +:1042F00086F7EC85074D725965F2C9146F0790C0B7 +:10430000FEE652E2F0835F63C6673A970719C0770B +:10431000B4CCE47CD70FF88E96E9372DF4013D64D8 +:104320004C2D9B0576CC85138202B132616ADD305B +:10433000D8EF491F48583C818CB80EE2684DD95AD5 +:104340009DA8026D6F1A4430BE40D4E5150117C612 +:104350009BB1FE5BE9C10AC88B69B2F276B292B535 +:10436000A7B0FAB1C6392BA03D3DB5231B12991E4B +:10437000B72696E75D12DBDF1B28057E27D1F5FF08 +:10438000B5BCEB7E88CBFDBB3DF4AE449F2FB4871C +:10439000F2606BEDAC35F434A88E02217014FA8D06 +:1043A0001402EF4928B78D71D629A038E9F37C298A +:1043B000F807E89731D527C0FA353834B9FB9ECFD6 +:1043C0005B5C3F35A511F437D5D57C3F18FE34BD75 +:1043D00041F5E1A34E0FCAFDC86A799B8DD9854688 +:1043E000FDA166CDC6786273D312D4C7805F4BA29D +:1043F000386B17D653C1BA1C0C7181EE5C89968B51 +:104400006CD126D0275FA5751E172C088FF3B09EA0 +:10441000FB6F0C61FF15CEA965B01E0A8FAF383C4B +:104420002EF4050FFA17F4D1F9F934AADA2D18E2AF +:104430009AA9969060EDC7F653617C5FC88F7ED9CC +:104440001F25166FD7E047FFEE4BD7E23804DF4B4E +:10445000B18EE93D9E368E000003BAE67A51A3EB99 +:10446000BA247A4A8B7713F5E66FB5EF7444E67E8B +:104470009CE93B16C98FFBB6E6F72497510E5A5DAF +:1044800021CC8790A5C4FBBBB28DEF5B6D997A59A7 +:10449000FBDC3BB47534DE7C59FDDBB5FED43184E6 +:1044A000FE391C8E64CBCD4877055C1FE770FBEEB0 +:1044B000D09F6E58D14AF939429FD912C41122CDEA +:1044C00022EE6BE6D45082CB8FC37BA0C2EC42EDD0 +:1044D000BB036B8D7198031A1C375D1EFCB5FCCEB7 +:1044E0001C4AF8BF28E93D0FB2632A5B8F9755A598 +:1044F0000D417B0A9D5701A3253290BA23FA38A0BB +:10450000793E84EF5F0CE4C30D74B1FE649771DCF7 +:104510005EDFB5BC32BA2F3DD8EB3BDF723FB0CA8D +:104520009A783F95E20BF13DD064FF69A5B61FA8CC +:10453000D50FFDA9DA0E7677D3C24ADC6F6FF23160 +:10454000FD4DBEA6A38E8DAFDB3CCE4E0EF7EDDC4F +:104550009FDCB9A902F31FC96E237D0E79F8564777 +:1045600088D96FE9503ED5C6FA0DDD3C873FAFC410 +:10457000E7DB5BD9F3C16B4BF9F3127CBE23CC9E16 +:10458000176E98E080784EA3B7221DE33A75F44F7A +:1045900027EF86784322C4E386B491003C1BECF5F8 +:1045A0008B20FF0BBD012CB5790FDAB4AD7C38ED53 +:1045B0003F6861703AE4B952C2C4FC430221153A23 +:1045C000EFC7F87A73B5F690B1BD8D7F2FAFAD729E +:1045D000F970FACFBC85A18D934BF1997F0889F7CB +:1045E0007B848F63D7DA03C6F6306F575A4FA21811 +:1045F0005016FADF9904FD9A8DDF5BC7FBB928B32B +:10460000C1BC0B16061CC3615E45ACDF131ADF9AF2 +:10461000E482146E249375DF6BE5F3B62C64715657 +:104620004D3E6CE37180AD10071816EFBF46EB6F7F +:10463000DFFEC4C7548F4B0B593EA9D6DECCE7A58D +:10464000E5E514DC678CDFFEC2CAF8B85B66F15B97 +:104650008DAE92D13799271AFC3D127218EB337444 +:104660007621D403038CED6505C676FF0863BDA8EB +:10467000C45857AE31D42FF4C4613A53F471182D95 +:10468000A6F384B712FD9078FCAF3B459F479ECBC5 +:10469000F9EDC9BA12ECD7E0E27C64CAA769522AE4 +:1046A000ECFA7DF8BD9C8FF6413C84962F40FE3697 +:1046B0002DF78F0ED8F341BFBF67F16F23C9E1B665 +:1046C00095E3710BE7C3C7009FB46CE3F87C84C724 +:1046D00075D6F3B8CE5A1ED76981B80EC667585C36 +:1046E00067158FEBFC8CE7A1EFE1719D67795CE7C3 +:1046F000191ED7799AE7A1EFE479E8DB795CA79DE9 +:10470000C7752672F9BD7F624736C4D91E9F98D8F7 +:104710004F9E28337D168480262DAF224A8315E8CC +:104720009AC206F6754AEA148B0DF262030CAE25A6 +:10473000F3148BCCF271F06F3AFF0EE815CC9F7931 +:1047400093E7F5E450AB4847EFA30F4709E47564DE +:104750004DF08E8690682AA747DAE6837E5C0D903E +:10476000ACC35E307388640978E57E303EC17EF963 +:10477000BBC307C19C1911ADAD70D2F78B5E0E564D +:10478000504F9B0C2DF21F1414C8170A8880E7FDA8 +:10479000E5FE234A691C5F741606BAA073447D9631 +:1047A000A7E9876B8D7471556C2BDACB4D753C5F27 +:1047B0004A2109FD78ADF45E2B9AE249463FAA6989 +:1047C0009931DFC35C8ED861F4C38BB698DE57FA9B +:1047D0007E7FE826D1145F33E61137B9A6F7191F9B +:1047E000CF8F4DEDD35FBCC552799D3C265E77C619 +:1047F000BE8BFDCDF6A004761EB557A5A37200ECC6 +:104800005DE9A837007113E9A8C24B3F7F1EE0F5B0 +:1048100020D6A9DD1884F1295E0C76A3850A7CD800 +:104820001BD90FC21DFD908B2B02D418DA7F1B41C0 +:10483000BF224D765EA7827114988BF891397E3233 +:10484000E4DAA7210E12A911C9365A7F7C61DFF282 +:10485000AE575E852B80FB4939B5DE124B1FFCBE7F +:10486000A9569C94689F6C31A7EB95B5D3BDA83F22 +:104870000E5F326F60B1ACCB1BE8772BCF1B38C318 +:10488000F2E20669EBBABF6F3A78D4B48EFE49EC17 +:10489000EAE735BE73B1BC138DEE330AFAA6935521 +:1048A0005C3EC62222E904792B05507EF6BB358496 +:1048B000F9F1A0A0F57CD2F4CD75C887EA83EC1C91 +:1048C0004FBF5B03449F77AFCD63504E17B875A4BD +:1048D000E9C03896C741E10FFBD74D0708FF8E8A24 +:1048E000C2C17E1FA980EFD9492DB1437CB3CEAFA1 +:1048F000C2738B8BC10BFC55DE1FE7D5BC4CC49437 +:104900008A86092C3EAAC97F8D4E1A7C3C5E3F41A7 +:10491000C278B7E4AD8D02DE9B46133C6F43EDAE2B +:104920008B1735FF06F2BC323BF1DFD6A26814E8E4 +:1049300092042621FCB4FCC026775639ECD3ABF3A5 +:1049400035FB82E7A14A7E3CB790D3368AC5C33295 +:10495000C3985771BF187A4EEEA7A7BB0E844F536A +:1049600092F3056B6596F7E44B82D7F7B91CCE90AE +:10497000A393993F4AE93F419CA093F7DBD23CFDCA +:104980007743499C7FB5F63F4A0AB66BF59C988CF5 +:10499000F3266DDFCE0FB85EF3F74CFE9B550A1A77 +:1049A000FCB05CAB82FDB4BA9C699467973F4F89B9 +:1049B000E54316DF68C073C680BEF9A689F3CD85CE +:1049C0004126BBA3B088ED1BF7D81D22F150B86E6D +:1049D00035D193A647AC45DE0DC3F27BD3C5D66572 +:1049E00095AA00FB2A7E82FB426E7F4700F6055D9A +:1049F000399172B08F291DFC15E840A38B9CB6B18C +:104A000008EF1735BD57472A0209E6AFD975E06FA1 +:104A1000F9D2616493DF43825EF0AF7296331B720A +:104A2000208F2B0C54FBF6FB2E77FF5ADB4FCEA5C5 +:104A30007FE0F7FC42C3F7A7A6B89597B2EC589D64 +:104A40007EFF3443B0E8E8B2C7CF37BD47FD0B6FF8 +:104A500022B92D594259361DBD98FD77B39F4D7A25 +:104A6000E5BD9512C89BB24C997404F21F7BFCED16 +:104A70002D5399FCE278B3727FB4B73F79A7BF2F6B +:104A80007D627599F659BEA53FE9B719F34B2F3BE7 +:104A90003FF75BC6231A789E5E2FBFC3348E180E75 +:104AA0008889CE6D0C091BE12EB98C76C79556C648 +:104AB0009F839B8D71E4BCBA0189E39D3C5FADB2DD +:104AC0004CC39372FB1F29BFCD3F62653E10F78335 +:104AD000B578D37C9E375D09796C144F7348D00349 +:104AE0008D678988F93167C93B9EAB747C536563D8 +:104AF000E7E848B3F5249CBFD0F2B3E686595D9B46 +:104B00004F759BB15E45A66741DCB56A9395403E03 +:104B1000D67C229DECD2E64FF9FDFB366607559315 +:104B2000DA26906B2B793CB1D24B24C8A7AA79E93D +:104B300089B1709EA7C6C6E4F7E714FE8A2EEFE699 +:104B40006E574406FEFE68DF55DFFF0E81F7234DEA +:104B500003406FA6253E0731BBD938BF4BCDDF3CA4 +:104B60005FED9C46B27948BB8484E7151FD0E25EB6 +:104B700097798E64BB8DE13FD939924BBDBF0BDE77 +:104B8000EFE31CCAA5DEDFF34FBEFFFC25E65F6343 +:104B9000EFBE1EE4C4AACCDA20C8552D9F651109CA +:104BA0000520566379659A3A50D1F5F35D66BF1CCE +:104BB000DACF7219FD0AFB1EEF1CD7C3BFD9BD5D4A +:104BC00006FE3DFBD31353C12E58F04B0BB1533AA5 +:104BD00038B7DBCDCF8B4564D08F77EFB360DC8007 +:104BE00048D1B1B7E8F20531B3908EBFE0676EDC13 +:104BF0005FBEFB795B640A7DFFEE173F1A45281CF8 +:104C0000CEADE87E7D20D83D3F1558FE95DA35EAD9 +:104C100016FAFC6E89DC154CA0B73A391F9CF9B91D +:104C20007306D099B0EBC00F71DC8EDBAD369D5EA4 +:104C3000F88DCD8AF0A7FDD879AC6784C81081CDF6 +:104C40004F9F2FAEE5BD9D794660F37BD91A498110 +:104C5000F9ED6A9743B4DFE25D7F43BABEEE677B4E +:104C60003C0087C52F5B0CF267F12E4BD4360ACB84 +:104C7000133694F701973016E049500F2CDA57831A +:104C800079B28B3A5AFE66F1C0FB46FEA270C17340 +:104C90001F0B3EB0F8A740FD85A73D60C77EDEB97B +:104CA000D30370A5E3CE92295D7DF7EF3A3E246CE5 +:104CB000FC587AEFF1205203F4B5B86335FBDEBE41 +:104CC0009B4F837C5B6CE2E3CFE11FD9BDF547CC02 +:104CD000668C479E276F8E857D0AB22B23617E717D +:104CE0008FFEE07CBD60CFF9AD709EF8CCF37FD92C +:104CF0000A76FDC2FFFA72EB03100F7835C50BF28E +:104D000068F14FDFF3101DFC33ECCC8E3FF7CCD3B2 +:104D10004F3D46F9E4DCEF6D68E79CFBD5E95C8527 +:104D2000AEFFDCDE7F64C1B9DBFB7E35B13FC0E3A3 +:104D3000BEFDD7F5EFCBCF00BA8DD8F4F88D207E2D +:104D400095970596CCFC0A2F4D783AB4EF502ECCAF +:104D5000F3EC311B9EBF594C9FD59500DE6A503F46 +:104D6000407D1985F7A2DDABFE66199508EEEA4095 +:104D7000113745A203C1C85EB4EF967F195F0AA53B +:104D8000D5AFC078A41BE5BBF9BDC547297EAF4CA4 +:104D90008ECFF3E46B19E0BF78F76AF6DD0E8A4F29 +:104DA0004F6F7C9E857F8CEB8DCF12BB199F0B9F25 +:104DB000C4D8E8BE8C8479241A3E6BF6DFD6A7DD12 +:104DC000A0C9874BC1791ECF9BFA2F5BA0C20E7C76 +:104DD000F6BC53F5313C47A6D0B6737BCEE7124AFA +:104DE000279F5ABB7F0872B2FB57362FF81D77FFFB +:104DF000EA03E4BB73FBDF961576FEC42550BBE2E5 +:104E00001CE9F9EB043B6311DF335BBCC31DB579CF +:104E1000E2F85A14993649F1E0F313F83CC2F8610C +:104E200051E4C0AD4202FC2DB31730FD14E9877088 +:104E3000A9A19E0E9CCFD7E35528037C9EB81EE8FF +:104E40002F193EB5F57B61FD57EBF0BA83F1B1B98F +:104E5000FF22CAAF20877BE137227C00E5B9769B31 +:104E600004F991E7AC2CFE66C67B1CFEFCFCE4B7A3 +:104E7000B417EFB727D97FE070B814BF5F6A7DDF42 +:104E8000167E73EC0A8E6B86E399AF13EB838D5C11 +:104E90007E2C22B59306E8F499CD4AF5593ED87B8D +:104EA0004175A0109F6F538705E5FC995D9608E852 +:104EB0000BB3BC584412EFDB45ECCC7E59F4F281C5 +:104EC0005120D7CE1CFC39A74B46F78B769F9055C7 +:104ED000AE1F227AFD90C4DFFE291F6FF12B89C718 +:104EE0005BBCFB6F09C7FB5C0ADC0EF3FFBCD34A5B +:104EF000543AC4E71D964989ECAD4D76AB31CFD617 +:104F00003DF6582A7DCFE27128B0EE8615810F5408 +:104F1000B04BDEB1629C9648FE4F6D78DEDAA1ACF4 +:104F2000A1706BF054613C451BAFD10427C91744F5 +:104F3000BF54CA0C96329B3A62F0A7ADD4DFD5CFEE +:104F40009BEADD1CD04BC7479FB6C23AFF6CB21F2D +:104F5000FF2C91A6FE74BC3FAB827FB992C85F3430 +:104F60008E1F5A66218A5E1FDABA8FC37CC8AF5380 +:104F700008E4AF595E4D51419E2CDE9A12817DCDE1 +:104F800043FB2F3C05703BF7A48DEF73B23CDB6A0B +:104F9000BEEF777AFF85ADFF49DB4FC3CBF4FBD57E +:104FA0005B697FB0DB773B315FF3AFCFA78E2254D5 +:104FB0004E57FFFA81A9205FAAC1C7A2FDAB7FD6D9 +:104FC0003FD240C73BD58FD54FED191401BC2C7C87 +:104FD000E1578B409F2C78CE4980240FEDFFE0876E +:104FE000503FF76B37E67B9DFBF5E9EF021F507BE7 +:104FF0005BD1EBF5F9FAF3DE74DC055067EDC245E1 +:105000002EEBC08F590025A5F7052FA7E2F9075D04 +:105010003F7C6FB1ADFB7E1688520788E8134507C9 +:10502000001F2ED865FCDE5FEDCC9E5A2C7757B161 +:10503000FEE1018C5F3BF1BDAF353AE5EDE6F7B53A +:10504000FEFF612F308DC3DE5F6423B589E8DF96F4 +:10505000C2C65DB0EB9B61C6F118BDF6FE0E7BFECD +:105060002381E5E793BD29B84FB0508E0E4D2FC672 +:1050700078C73CE0DB859EE8D034FABD5F7279B931 +:10508000D041EBF4F9003E0FE80F7562EF7A0EF0B5 +:105090005BF3520A017AAFF9B51BE3C9352F5E38CD +:1050A000F5387D7E66BF13E37A35BF5E8AF8AEB110 +:1050B000457F08F1BDEEBD36B28DF63FB3F7B7B907 +:1050C000608F9CB14673D3FB880FD574D87832B803 +:1050D000711DD42F28AAA5F35137B0BC9C3AC2EE5B +:1050E0001DA883A00ED0F18729EC1C31DF97BA8769 +:1050F000C7A3BE98A3A4E2FCAFBD893DE7F1867BC0 +:105100006E56FAA7E9E6017973E42AEA97C8B5C3AF +:1051100040CE5A62371105F6FF6283B1D4FA59E0E6 +:10512000FE8662C8DF62FB7ED64C3FA9A6E5D2743C +:1051300012C2F397AE1B7BF8EC7714C5F76C56FAE6 +:10514000C378FE14265F6A1C81F129980F69BC7729 +:1051500041DDCFD67581DFA7609EEF05AB6A03798D +:105160001EDFAF6379837592F201C47DC9112E975A +:105170007AAD9FF1D917DE74E4336D1D2DF55E9481 +:1051800027ABEB7D58AEAA2F220AE629FBB16EE1D0 +:10519000F0B015AB04EE99001E843F9B2B1880FBEA +:1051A0002C604C88B75B5C21A42F9BAF16630576FF +:1051B0007EFF8EC5A5926A17C467189C206E0C707E +:1051C00092795D6A9B8270A5EFE3F3898ED09C94FF +:1051D0003190EF3BC220A7E4CC1243BD17DC34BAB8 +:1051E000D8F3BF0D3F82F05A5D6FC772557D19C26B +:1051F0006D657D00EBFF1FE0D7CAE0770D5174FCB1 +:1052000023675618EA49E1B799C22F33CE5766385B +:10521000D4F1FC1C8D9F92F1EF23F504375F36D655 +:10522000B761A93D4F4FA2D7CFA6307BA48E8496FD +:10523000E33EA897C56148A64A7274F127E253F18C +:105240001C089E3785F69C9B307EA9E1D7E2954EDF +:1052500019E59FF201AC67E91B5611E495A56E3B79 +:10526000F92843C7C75382290AC2D98F71E006AE15 +:105270005F57F6E0D3C81F2DF50A966B399FACE750 +:105280007CB201F00EF13DBF88386D9D44507F3EE9 +:105290004CEBCCDF8F127D3C3CCDDF11B552FCA333 +:1052A0004C52B064F7701CB34586D0F79CC52400FF +:1052B000F49276ECC7115C2BE9C0F3D669DA3D3085 +:1052C000AF14A4CDC4FD1F62657A8A585819B682FE +:1052D0001F65866F83FF20DE2F916C3EE5C7E70BCD +:1052E000F0BD0B33D99E59E69D1DC7E03E0857AB74 +:1052F00013FDCA2C7F6D5E2ECA571BD2ABCB1F127B +:10530000AA7578CC4A62FF2D734CFE23D0E38790B8 +:105310009748F1BBB16D700AC0B9C5DAE10379D81D +:1053200092C6F48D3283424177BFD86B5C4E7A4A85 +:105330008D724093CBDE6B4B0CF4ACC9DDF40946A7 +:10534000BAD7E4EECF7AE46EF02CC8DD8CD816E440 +:105350004B331F34586555B812EFA361F1A7130200 +:10536000DB57EF2D0F70DFFD8BAEFC6D701E5BE326 +:105370001FF3FAA5E6C9F89D1E7BD09A381F60205E +:10538000BF97A199D21BA174D44AE90C10B18ED257 +:105390001994614A678C9FCAB0D4E8780561324499 +:1053A000DD27B279F278ADB67FB2C25E12003CAEB4 +:1053B000EC603C34C8C1F7493345CC0B90A83FE9B9 +:1053C000A28FA403E3EC605F4A56B68FDFED163B75 +:1053D000601F7FA56BBA1DF24A85B452A49FAFDC53 +:1053E00095797DEDEBC0FD6B407F5E979F9C2C8E89 +:1053F0009F9BB4784B08F8A57B5C9D98DFE472888E +:1054000086FDA71A47A8C0A1AB8F84AF73BCC3B0F9 +:105410007B929CBF1CC5D743725452A893133DF78F +:1054200025292A29D2C98B1543AEC7FB987ACB8987 +:1054300024F270E7FF8C3C6CC88B205EAD66F9935C +:1054400019C03BA068A9C2D50AD43A5FF983D148F4 +:10545000A7D739C00F716DEBB183BE57D07B9E6665 +:10546000F917D76B0AC6C1A85E7BB40CE46952BDBC +:10547000567B17D271EB4005E8F8C0BA079E84FA54 +:1054800047EB6C78EF4B556C3551E87CAB63E3B080 +:105490009CD7F61096956DED94890859BEB67ADDC5 +:1054A0004CE8BFD982F19F5391ABCED5D1FAA95622 +:1054B0001BDAEFA7B6DC9B07F6DFA956A762017BD4 +:1054C0007FCB18637B33BBFFE5549B356261F47B74 +:1054D000D102FB1184CB778802E9E64B4A15B4E38D +:1054E000BF30EDB754AEB705044F72F857B625B6C6 +:1054F00027F1FC36E45C93DA61205FCB8FFF380F35 +:10550000E84393334BD3A9DC03F81DB79144FB0266 +:10551000131D1317039E263A024B19BE2EEFDEAC65 +:105520008F446A77239E429E6986B82F8BAB7EC4D8 +:10553000ED72624FD2EEE1EF7B13B7D7B4FEE5F523 +:1055400007696D55B131AE6D8178B500FEF83496BE +:10555000EFA0ED03F5A66B664FB7DA50AECCE1F1E4 +:10556000288DCEE37416F2F07C31031DCE8F6D4092 +:10557000B927B48C7C741C85DF9794FE803E84969A +:10558000F1FD01BECBD77C67FD9D74FCBFBF69C137 +:10559000E7F36229D8FFB307FD8FDE09FEC2BF5BC8 +:1055A00009C89FBF1F9988FBC89F598D718C7227AE +:1055B0009397AF72FEAF8AB518ECF3AAE6D932C45E +:1055C00041AB62EBF079156C22611EFD1DAFC10687 +:1055D00070152CFD1A78FFF6892B509F96601CAD34 +:1055E0007AAD2D619EFFAB0EC520AFAABB5A715C90 +:1055F00042EDB3CC2C3E9E4EEE54C732903F8857BE +:105600002590F75DC5E54FCFFCB6580DF2E7B39492 +:10561000C4719AB71C6C9D55B1EF20DFF55EDF7742 +:10562000F17995F6DD2EC6A7F1F53C3A2ED17AE256 +:10563000EBB816FB7F9696F8FBE7397C4FD5CF2366 +:10564000012ABF2A6DB49F0BBE7F6F5319F8F95B17 +:10565000D2D205DDBAAADB1690806E5DD55B66C935 +:10566000FAFB29E378B8CF8087F36B16231E9639AF +:105670008227400F54B68C1F15423F7F35C2F92355 +:10568000AB3F17E4F1E9B67B3D89EE913C6FC64F25 +:105690001BC70FB5BB4B75F8D1F0627EFFD49FAA34 +:1056A000BF7A10E4D466B741AE98CB5E78CB4F0C8E +:1056B000B7544E9FA7A8FE0E21DC94178F015DAF53 +:1056C00075627E5C72F85D41427DC12F89FD4CEDB3 +:1056D0002CBB730C7C97201CAADB181D5C0A6EF196 +:1056E000EF723A284FBC9EF14E8D0EEA884A19F6A9 +:1056F000A47C293A7880A8F63ED6D143076DAF95B1 +:1057000017C6E960BC333C7105EDF729D83FC37A71 +:10571000E3FFA4AC7AAE017B678D05F7BD4E3AD4AA +:10572000AC3B587D34C8E7939EF0D46B4AE3F5F95F +:105730003B8778F4F73A9E6EA6704800BFF1CE24FE +:10574000F453A892E2B1FFEFE8E7A324E760263A1A +:10575000CACB019F249C389EAC959AFCB6A4BA7A19 +:10576000FC5ED0A3275D055F4568EB3A47E86627F6 +:105770006D6F4CBB1FF5FCC99302EAE1E57F5A3A15 +:105780000CE4702FFBB73EF6D8C743306EF9F8C76C +:1057900056B4A7705C42ED1FD003986F8E7EC04058 +:1057A0008CB324DBCFBD172EFF1D13DFD7D5F66FCB +:1057B00057D6773E04E313BB4ABCDA797D054A66C7 +:1057C0008FFD07CC43179F97AD21AF1FFC5D810470 +:1057D00081EEAD52A819F20CADBECCD1AA0ECE4BC3 +:1057E0009C2C2F27E5F0E1E67CFA7ECADCDF7921EC +:1057F000CE67A3DF81D29E237DA18F975B3359DED5 +:105800001729D43D2F8073C8B46E883BD0F9F6E1D8 +:1058100037FF52E8B9670DEF379EA95DF405A0A3E5 +:1058200074F37B2D7F456A64ED695A73236BE771CE +:10583000D4C5952C4E7A68562AC24F5BD7CC5756A2 +:10584000E17D6B335FC9C6F34C335DC33E0178FE27 +:1058500012126B80EED3987E36D3C5435CFEFCA05B +:105860005D54AD74BCC3D6EE834EE08B1F09E85780 +:10587000DFF1DE612B90FC1F8E9EB4425ED45D9002 +:105880005844D7338B283233A223F8FE6CD2E1661A +:10589000F58E7E70FF697C3CEA32C3784BD8FEF30C +:1058A0001DEF1D9D086A948EB712CABBDE24328C90 +:1058B0003F6B9FD2C48E43F1F15EA1E389F1F17A8F +:1058C000E027D9111E71F8D8115EBFEF395FA2A28F +:1058D0007DA1832FDA2B1A7C1B006E147E33536755 +:1058E000DC484625E79799AEA19F9051F1F998E1E0 +:1058F000FB7768A2FCF68433B017F8AFD119781E95 +:10590000F867A1BD3B572AC073602FC2F34596507C +:105910005E16A5ABB38342C3FAC1BD1E9D89F7795C +:10592000CD7C7A1CF8E54A28295FC03CF879951FA0 +:10593000F2751EFAF169379E47D9FF412E943596CC +:10594000AEB5B703BFFD9B05EDCF2FF60DEB33AF23 +:10595000EE388FBBBCE514F9796BB6CEBBB83D779A +:10596000D73E6704EE41BCABCED2E35F015DDF55AD +:10597000C7F24F88D439EA56833DD9C8F7437A8FA6 +:1059800003FE82791C6D9D0773075C01FEE593633E +:1059900064F4230EBCF9C5EFAB69DD31C88E7EC25D +:1059A000DA344EBFE5CC6F7D322DE01C09F1AF3506 +:1059B000E97E95AE73CD6BA443A4703A38FCFE48E3 +:1059C0004529DC0B2D62EC6C7D6C7BB802DE2B660E +:1059D000F7CE78B95DBABEF3641BD0E3E96336DC79 +:1059E00077F8CCCDCE11AEB10673C18EFFA45D4E5B +:1059F00078FFD99FDD12CEB75DE81280CE6793B0F5 +:105A00001DE4C5BECEE9FD613E1E3FF102F99FDEF9 +:105A10006211D9FD685ABC252AB178BF2AB17A80B3 +:105A200097DE14FD7D63AB274DC03C8F39AD6F63AE +:105A3000329EA734F13D3FA92E365F7767FA64BCEA +:105A40007773828879D86E7FB700EFE57556C8F80E +:105A50007E58E8F3FDBC655ECC4385F741CEE75D3B +:105A6000E6FB3617CBD3DAC0FDEC76ABBF69021D7F +:105A7000A77D6D9A00F8D0FA292E26574E4FD0E216 +:105A800048618C23E5167A53E01E8BDC00323771B7 +:105A90009786F1BEEF6DD08FC559110EEDC35F8CA7 +:105AA000C23EF61A88AF009EAD8C9ED6AC1530AEC5 +:105AB0004AE13700F4C4270FDB6E8275E4350B5ED4 +:105AC000F0DD699970DE33DC7646E7AD8FA25F08C2 +:105AD000615A183777CBBB382F7792F5AE70B37B0E +:105AE000F23FB9047D7CE964F726E6D675F2FBF156 +:105AF000A2780F5E18E004F54029BBDF440A28FABB +:105B0000FC9838FF2CE7744802B0CF56592647203E +:105B10008E2036B7CF8075CF0EDBC80D747DAD42B9 +:105B20006700F8451D23F2FB9402C7014EEB36F4E3 +:105B3000C73CBC55622017F4B0FA7F64DCA73B1861 +:105B4000F86233DC1FBFB54C46BE381860E70D9FC6 +:105B50005C56D00EFB94EEBA8AB6D974BC88574610 +:105B6000C9D2504ADE1806FB94CB44AF40FB878372 +:105B70005ADEB6D7017431DAF2E5E422D8C7CB1683 +:105B800031A6745A60F736AC5C56E105BCAEF466DB +:105B90000A7AFFE5764E07C7D383B7BB287C7C0F14 +:105BA0006EF452338EF267C6151047549B65453B21 +:105BB000B70BF73D6470BC64748AD12A0FD65DF3CD +:105BC000D2E13E5D162F7DE8C6108B73C2DEE85829 +:105BD0008C73F23F1FE23593D7D68C706065D38A01 +:105BE0002AEC0FE364D171324AC5E8583AEEB6B4F4 +:105BF000C0568CDB4DB4239C88D4D506708A4C1CCF +:105C0000E0877B6D378E1BFA369C5FC938D23D1D0D +:105C1000F4686490E30FED20A756CA0AF079C6B283 +:105C20005377C2F334FF23F74299D1F8FE0320A73C +:105C3000D3BAFE568FCF27C986F862C6879F7D03E9 +:105C4000ED1941D910A7FC3A3DF81380CBD6E2708C +:105C500018EFC5048C66C5D7B16779E724B8EFF8AB +:105C6000F434D1BF8DB7E3BA3679236B18DC4A41DF +:105C70002F68705B252A1D5158D7543BD24721E924 +:105C80004479950DBBD983E378C9F870F512C8D76C +:105C900030CF679D4BE8B97F03EE09045C417E8CF1 +:105CA0009CCDCE15EE2DE9F4813DBF362D717CF2F1 +:105CB0002D377BDF26B238ABB9FD0D37A30710892E +:105CC0006D252C5F7E24942EA2A64299630F40FE80 +:105CD000F35E51F923D2F9468B02F881FE568ABF52 +:105CE000036F7C8EF1C503E177B17CC65DA4E5DD71 +:105CF00047B3E8FBEB4AD97DC7EBBC8C46AA9B991E +:105D0000BCA8F675D961DFA4BA9878B7717A533513 +:105D10003843BC8CEBABCA5B195C338B09EEFB429E +:105D20002C08EE9BCA827E147E99CDCB97201E490B +:105D3000A73A98F65B07E3027E1A45C2C6EDB22386 +:105D4000FF862DB8EF49F9FD2D886B55B6F6C77D56 +:105D50007F38360CE3A5F3EFA6F3F1DAE938103F0C +:105D60003CDD6CC17301907E03756519A565A4CFF8 +:105D7000EEF2223AAE52EAF5AED1E84093639435A2 +:105D8000E6507D01709BA3AA4B80FE4EDABD6FC02A +:105D90003C9C9B6C0AAC7FCEA6979682FDE2F47584 +:105DA00035837CA82E63F34D6FA5CFD1CE51DE8213 +:105DB000FED5AD36857D8FC3AF94D31987C35C3EC6 +:105DC000EFB95BD8BC1D832261A0CFEA6514AED0C9 +:105DD0001662740F21D18B22F2D51158BF5BCDC250 +:105DE00071FBCD30F18589FEB47555F275552E6382 +:105DF000EB229C9FE8B4A2306E65295BE71CC2DEF3 +:105E000017E1391D7F2E5F4FA5FA2296739B6D8691 +:105E1000F1B716EDE884F9E417CB0A9E1321ECBE26 +:105E2000C35CBEAEDC46F6BDDCE217115EA44E37A5 +:105E30005F8CABEAEA94AF4EFF9632165C0A00071D +:105E4000D8E8B8277F2CE37E4EE126E3BA4EAF1E9A +:105E5000B6BD95B67FF4B08CFBDE7B45FFF13CF41C +:105E6000476585C91FFFBB53404ECF6DF4831CDFD0 +:105E700053CEE07FFA6612017A187224980EF01E53 +:105E80007224C4CB5ADC4FA700117AE41E9D1F7503 +:105E9000999A059097B1C1CFCE033950C6EE231F12 +:105EA000A49F379D5F46735605E4436596A557C882 +:105EB00078B5ABA9FDC863D345683FFCD8BDF09D5C +:105EC0006CA25B0F6D973D83D97996C3B415FAD553 +:105ED0009D7A10F0D1CACFB90E8199A5637918CAFD +:105EE0000CCADF2DE9304F894C2889CB839D0F8F59 +:105EF0001D0D7205539E4AB08C9292DE7243D77F7D +:105F000038EFAF0A09FAB93D8AC13FDFF9F0F5C3AE +:105F1000C18F5F0776622ADCC7E6FD12F27454BFB8 +:105F200088705F678DDA8B697D15B51BC17E595FFF +:105F3000F4BE087CB76E1FF1037D6404FFCBA6C7D7 +:105F4000E30D6EF6FB3C924C5A80FF0F0E3F350975 +:105F5000F0143940ED4EDABFE237AEC79C600FFD5A +:105F60009EE5C1B4FFB616F5F7FDB972C2FB78C95C +:105F700025EC4473FFF421D3319E97B76903DEEF1C +:105F8000593D49F2DF407B676E2A2F073B46095295 +:105F9000EAEA4FE7BD65F4726042650ADB2F5326DB +:105FA000B1E7CA0456B6D41F7908FCF6F02E29A52D +:105FB00090CE77C46A76AF584BF117F610B54B4BBD +:105FC000CB9FB7DF4C9F7F5C4AB5207DFEF1B55F6C +:105FD000A4C0FECE93A5151900CF7DCD46BB8EC0C3 +:105FE0006557D41F1A690B07DC745EADEF1184A7E7 +:105FF000C5166DABA475CB4B2EB0707AF939AB5B7F +:10600000DB67009DCE2992316C6F5EEFFB5C9FCC0D +:10601000AEEB9E04F7EBE7AB84C5F7C38FA2509EAF +:10602000CB4546BEDA8942C7BD89F9276129F03AD6 +:10603000C8E570714886573479D63AA4F22990673A +:106040007FE2761DA99D87E7C890FF2D600F7597A9 +:1060500027F29B4A5D0EEC7F7ACB2D1F409C7A4E37 +:106060001DB3F7F3B67C29203EA8DD974DC7CF2B93 +:10607000C5AB06C99C6561FB48C04FA1481405E645 +:10608000D341C04F0853FDA3878336EE7FF7FD252C +:106090006E1BF26129D8CEBAF5B8F87A72FD743D5C +:1060A00009F47409FFEE8F9EF8F2C03880FF32E6E3 +:1060B00022E5854F0876DD3CF2D4CB9BC755301ED8 +:1060C000D8AF6E2F8EEB2EEDC2FB5CCCF21DCC79DF +:1060D000E0DBADCE73A3997F6F94A7BDEA9CAECCF5 +:1060E000CF734DF26AA4ADE346C4EF1E76EF35647C +:1060F000C442BB404485DDFB19D1EEA7AE857E23AB +:10610000DC2E2FD041EBF0F74B003E6BB9BD30B722 +:1061100098A0BF3A37A713ED85D98DDC5E90FC4D72 +:1061200020649D5BD2C81A9DFD80A612B8D08DDC7C +:106130005ED0F43FD7DBD5BECE66D4AB8DECBC5F72 +:106140008F9DA132BD9AE7637ABDBA997E47E1C4BB +:106150003C566F97303DAE6CE2F603D7C319FCBBDB +:1061600099CD4C5F65801DE181340815F532EE61F3 +:1061700065C5ED967EC54C5F66B4EE45BDD6013F64 +:106180002E3306E406D39783DE3EAA02987CF47190 +:106190001B95D38FF3769F97DA67E971FB6C95C8EF +:1061A000F79B08B30F31E79FCEF321E8AFB31B771E +:1061B000F0F9ED3D9C7E13C8D79DE1023C57AEF14E +:1061C0002D463F693DB794E5AFE4D6B17D72B7BFC8 +:1061D000EA29FDF9B3796E76EFD03C8DAEEAA23EA6 +:1061E0001817EF8540392E637C7135B59730FEC4A2 +:1061F000FDAB6B5C3CAEC1E927993ED1E4909B04BA +:106200003CC514BE1F479E4279AD527F09D6F67138 +:10621000B861C0DDC0EFE169A530FF75E3BEC2FC27 +:106220008FBC24FEE29F353FF35BCA75F7A4A3CC75 +:106230000FED14139EEFC9F1B0F84387449C00CFD3 +:106240009430BB472EA54C4ED83FD5C3ECECCF398C +:10625000DCD68D7B0ACF6726D5CF12512D09F4A944 +:10626000A66F5B01CFD7D0FEEE379A54F4D323410B +:106270000BCA57767E314CBAD08F548B648C1BB6C8 +:106280005AC376C0C7FA528E57AFBD1DEEB7F9D6C6 +:1062900078A1F0003CAF0E8811211FF01CF18E6434 +:1062A000711D3CB77C9AFAEFFAFD8AE11E91C34951 +:1062B000C11FE6CB6B66F4B56E9C8CF358333AABDA +:1062C000DD92AF97BF02979FEC9CD89A71AF237D68 +:1062D0005DEEFCAAEA9EC57B3FB4E7A7363F5D00B2 +:1062E000708EDF7F11E8F33C4555DDDF36ED48B0B9 +:1062F0004FD0D30E7E940BFCC0C81D867D4D8EDF23 +:10630000091ED1107703F96A45E7223200E24B7B80 +:10631000C6473CF01E59C6F66DE7F37DDBCF77DC50 +:1063200082E7C94752B2B226C0FB67F5C6F3EA9FBF +:10633000ED7C7A008B6B440C79C2F39FFAF908C3A9 +:10634000FE7080289963F915ACC0EFAFFB559B2513 +:106350007EFF800CBF57007176E0E0C170AB620732 +:10636000962EE05F5A7A4837965E504783C14FF2C7 +:10637000639949825866915A2C7D248CE500D2811C +:10638000650EF8B983412F7463A910AF487472BFCA +:1063900080F8B15E4882584A80B78CF8BE84B4CB8E +:1063A0008EF91BB07F017C9FECDC99DF53B9C4836D +:1063B000FC5D7B25FB1D23B65F31DD13B8C78378F9 +:1063C00088A2FC9ECD45F991E74674C0F9A37BD61F +:1063D000B2732F9A7C47FF867EE7D974A60FD48DBF +:1063E00002CAB115CEA9DF4578B65ACFE8F71B88A7 +:1063F000DD5E08BF0FA28D3B9BC71966733D08E1A8 +:106400006E767ED08FE7936643BC41D74E7ADAD959 +:10641000BD34DA38A2F3DAA17DEDF7E9DEC7FCE896 +:106420004A931F7049FD6DAACF31BFFF359D50566D +:106430003C1EF7EC77955CA457AEBF294129F85E66 +:10644000B3ED04FA63E189013D5C9EE17CA0E9952E +:1064500039A67C0F733947E2FC611A876AC0343869 +:10646000D78B774AE8F85BBB9F54BBBF677E20247D +:1064700067B3D77C80472F9F77986CA9C8A6E5A7FC +:1064800050D7C5F78FA6865EF2E8FC116FA056D4F0 +:10649000DF77B390F3E3444B6B39C8B9D321E207FC +:1064A0003F623EA9F57C07E2F9472D28E706D2793D +:1064B000CBF07B2FB0C1918E75157EEFE56C3D3B27 +:1064C00027748ADF33FC14DC4743CBBFF07B85475E +:1064D000B62D9D0A74F039BF5FB868DFEA20C47D2D +:1064E0004676386781DE1FD931BE1ADA47EEB2B17F +:1064F000DFF1E172429B171C7377A4E33976D59ED6 +:106500000EF284A0DE3DDBEA88C0EFFF9CEDB0B068 +:106510007B558B45BCBF0CAE21B4F0F9A5A6C3F7E3 +:10652000FEF387608F7CCEE5C9194F1AC397A40A82 +:106530006A26A4A5103FD8351B9C8BF01C64952BB4 +:10654000F2D46399901F6EF7AFA0DF3FB0F7A55C60 +:1065500078FEA87311967FD9FC412EC8ADB3FB3FDE +:106560009013D16D8D1495213EB5609F20C2FE49D8 +:1065700079C72C19F647AA761FC0B8728D3784EDFB +:106580000BDBF6627DC2EEB771FF6470AA82F33A4C +:106590009B1DC2386F619B2D0ABFC7B1A7207C77B6 +:1065A000C27DFB54A66736385FC5F11F75BEFA3A47 +:1065B000C265B30DCF7F1CD8FC1B1CF7CCFE97F82F +:1065C0007C09E60B9E4DE938FE13D05F7BF9794CD0 +:1065D0007BA7471F0F965205837C3DEBE6FB5E3998 +:1065E00097E8C7F30589ABD3C3E452A707F6CDAA52 +:1065F0003A181CFE628DCA60472EE81014F83DBDA3 +:10660000F2DDED781E70C13E3B9E975800F000B859 +:106610005178215CDA0EE0FC0B002EFD601DEF626C +:106620003E7EE13E0A9751F1752F7085905FB5F57A +:106630005238B075EFB9149E42463CB5BD2D435C4F +:1066400066E13E01E1B770379B47D53E36AF09BBE7 +:106650006721FECFEC270AC45B4EEDFDE07358CFF7 +:10666000D9FD76BCCF579B17DCB7E02901FE6174DA +:106670004AF631B9AAD9DD35912CFCDD819EF6DDD3 +:10668000EC7749016429945E47EE9B86FB82A54026 +:10669000BCC0FFDE8E11ECF705C3B900D73DE3A304 +:1066A000B930EF33DAEF2349E15CC08BDF132A4DB9 +:1066B000D5E1E3B3132FA15E2C126BFFFC20F0F1A8 +:1066C000F3EC7738967EB841D4C3E33AF841AA3167 +:1066D00000B7B73C08B79EFB5BC22C5F8A84901F53 +:1066E000AB383F9E6DA77E275DFF676D2F60FBD99E +:1066F0006C637ED55FDA0EA503DC2AF9790C12B93A +:1067000005E511854BB33D819EEF39D71661E7153D +:10671000CF09FC3ECD2734B8D5CAD30DFB7C4C1E27 +:10672000E66CC93F8C7E4624F13947B39D64BE2F89 +:1067300035593EC0492ECF3EE6F774697A77BA27BD +:10674000342BB55FF2F3DE952D35B900EF4A381BD7 +:1067500089F79C1EB801E215786E88DD931A05F85A +:106760009CEAB907F5A51B20CFF4541AABD7A57640 +:10677000AE02BBF69476AFAAFA1A7B3F9FB56F8242 +:1067800076DAFF394FB03695D9F702FB7D1F6B1AC9 +:10679000FC4E83A63792C3C1F83B0D4FD3B5025CC4 +:1067A000E8783FC1F1243ADEC87F7E3C4D4EFFD3EE +:1067B000E3D8FF67C7D1F417F027A43E12BF7FC408 +:1067C000FF04FCFEBBEF93F05C035F5DD83CB809AF +:1067D000F6D1CEFBD83D30B6D6E504F4F9DC4D1B3E +:1067E00012FEFE5B4F9DE7E5C88329BFE9F8FA4832 +:1067F0002AB3CB8F70390D7FB0BF0577E5A05D4C14 +:10680000FF5AB3307509FDE761FC1EF3221246FB07 +:106810007404E9C0B2987462398A746389DBCC83EA +:106820002154EAC7F2AFE55D6361F10BEDA1275397 +:1068300044CC3B780DE4D0D941A1A7E1A2B615CE56 +:1068400045D7C0FCDF48F57278450DBFB742F4BFAD +:1068500087A1803D38C5D7973D48BCD2999EBC974B +:1068600002BCCFF6ED545C5FB2DF515B62BAF786D3 +:106870009D0BD7E050433A308FE4B52DF7BC319CE7 +:10688000C2FFEEDD6EB493876E695C02F2FC6ED2DD +:106890009905E78487F27B44481BBB0F47BB1F6405 +:1068A000789BCDF83BC2A6DFE359C07F3F6B81F9EF +:1068B000F7A9F839DC167890201FC37C8EF7AFA9B2 +:1068C00089EF7D21C5897F0FC57C8E77778788F911 +:1068D00051F740DE95CEBF18BEA3D666A42FE5DFE4 +:1068E0000AADBABAE067F108B723B053E8FD9DFFDF +:1068F0000B82D8B2B4008000000000001F8B08009B +:1069000000000000000BDD7D0B7854D5B5F03E3360 +:10691000679E99849964924CDE131E21C86B0221F4 +:1069200045A47A122246A43A3C6AC15A9C8040800F +:10693000BCA068B1C59F8144081425D488400107D4 +:1069400044C5FAE8A417E561B00344448BBDA15ADD +:106950002F522F1D901F1111466DD1F66AFDD75A87 +:106960007BEF6466480AF4FADDFFFFFEF4B3877D2F +:10697000F63EFBB1F67AAFB5F70C77288CA532F668 +:1069800082A2DCE31DC4D837F87753D773AA5DC75A +:10699000D808067F8D6C5C31630DD5AA7D15941ADD +:1069A00002564DEF84A75D1750F219CB4A2C33CF16 +:1069B000853273E8ECFDDC8C8DD58F3EEC86F6C617 +:1069C0001A75B809CAEDDBE67618F07B97CA4C3029 +:1069D000649603FA8532CBD005FA41B9D1FE1BC7C4 +:1069E0000C18BFC006EFA19F1C3B0BB8A1DFFD5BDD +:1069F000EFD761B9A19EB1741C47F175B8E93B9519 +:106A00003D85D362DAF8A234C6F2F09F308ECA56C2 +:106A10007FAA4F62ACBCE6B4256C83F7E1CAF16C87 +:106A20000863A5F67C5AA7FAFEAD1F6179CBA25385 +:106A30000E1F8CF7C6D6E57F180BFD1902302FE824 +:106A4000A2F0EB86E36361BCC85623DBC6BAE090D4 +:106A5000BB583D1536D380EC1BF82F7B616CD9C831 +:106A6000A05C28CAF9388FA87A280F17E333368537 +:106A700085D2B05ECCD7A93106F364769BF3CC40C7 +:106A8000C66EB22BEC9BDE5DE511A2BCC3D05C668A +:106A90008579EEF84FC5B314AA0F6C9D9587EBBBB3 +:106AA000B4C7976787752C32270D61BD2EDF3F83F2 +:106AB000DD2DF6CF6FD1B9F019B2305757FB01DB9E +:106AC000EB4D3EE8A77109F39CEEC79839D06E1DD7 +:106AD00088FB78D8E081227B4861538250AFDA98F6 +:106AE000168471860B7C897F3EB4C4FDBBBE86AE26 +:106AF000711FFA7AD214DCDF48A255DBA65C3E2F68 +:106B0000F99D6A77FB717F0DD9CC9300E3199C1D29 +:106B10009976F86EE02EA3C706201BFBEB41BDC2A1 +:106B200030EEC08353993B91C30BE7AB2E327A4EC4 +:106B3000A730665AE4F4A8C3B19D8DF0F1339B31C0 +:106B40006042F82FFA7933D6376C2D71B9A3F07AF9 +:106B5000F912BB4785796E5A62F6A8B0C0E5627D2E +:106B6000F1F3CB71E8BC01F8CEA8633EAC5F00FB4B +:106B700080705C604FA0E77C51DEACFA27E2FC3706 +:106B800003FE2C457C5DC8F1774186398078BEE0F4 +:106B90008D3EE9AC1BBA92CFA797B83C7D611E9B96 +:106BA000164E7731F8B4747EBBE51658FF8244B3B5 +:106BB0001DF1519F54F0F868C4F7370D0CE9AA2174 +:106BC000B1C43D23AA3F7DD24817C243AFF3673219 +:106BD0003B632BECD32AD40CC417FF46E6616C4D03 +:106BE000F3CDBC9CE8CF54A0FEF1E65B7939D5BF6C +:106BF0005181FA279ABFC7CB39FE4C1D949F699EDD +:106C0000C0CBFDFC1BB1FCEBE6EFF3F26098432632 +:106C100063BB9AA756F861FC0683678A07C67D1195 +:106C2000E63F08E61F14CF3D76BEAFB2FE37F81E32 +:106C3000E0BD533CE3EB5F16DFEDEEA17EAFA86F46 +:106C4000EBA1FF57C577A11EBE3F20BE6BEFE1FB56 +:106C500043E2BBC33DD4BF29EA8FF4D0FFEFC57731 +:106C60001D3D7CFF07F1DD3B3D7CFFAEF8EE580F8C +:106C7000F5C745FDFB71FD9F10EDC3E27D7662D344 +:106C8000713FE05D36F02DFC2B4C6C4A46BCDB546A +:106C90005F4CF8DF3002F07C5017BE672BCC8BE5E1 +:106CA000210E95FA1B82FC189E6F8BFE4BE7F75D59 +:106CB0008378B7E02DBD07F1B041F11CF341FFFE31 +:106CC000F93A0FF2DD056FE8399ECF57032C8ABEE3 +:106CD000DF8E9BFF1631BF4631DFDFD97B13DDE44A +:106CE0002D7279C64B7E89746F8F2D9B819E3418CF +:106CF000BFD1C9E54BE1FC32737F941F205F906FD9 +:106D00003E6433864C30FE437695EA1B9D6576AC37 +:106D1000F7DB55923F0F39CBCC3390AFDA80D99562 +:106D2000C07876DE77A35DAD0820FF709453FDD860 +:106D30005F8FB7231F6D64114729AE6F31C815F8F7 +:106D40007E7F7D19BDCF73FCC581FCF968325F572A +:106D50007BE2214B3EB453EFD391BC28B0AB24C7A8 +:106D60007A2FD605DCD0A4DDBE4087E5271BB9BC51 +:106D700082BFC42218BF2F1F9EEDB8BFE4CD42943E +:106D8000670FAB1EB79BBF53A3E4415F94574938CD +:106D90006E728CBCDA5CCC34ECD7EF32079E827E0C +:106DA000FBAACC9592DC05F73C879ECB17FD780FAC +:106DB000CAB53ECDB1F229BF294A3E319497B1F20E +:106DC000295E5EE5D4037F8CFADEE4B2C7942D8E93 +:106DD00044924FC0633CDFC0D00B5A17DC62655D44 +:106DE000FC3A5E1E3508F920F96EC3D7C363E4830D +:106DF000E4CBF1F2E1CAFCF5ED5BFB131E02B772C6 +:106E00005F99CFBE8D7800F867F029243F98EA7328 +:106E10007913AF0C2F83C16BB7DBAE0C3743EA3B62 +:106E2000A457187C2AF57F995CB9025C653BA3F9ED +:106E3000C9CDA741AEFDE5FD9F14322099E5001BA9 +:106E4000DAFF545DE0295877F6A2E73663FF5987E9 +:106E5000AC8D0867A36BC6E6465C4FF3E38C013E3E +:106E6000E9CD1C9F8C196576FC5ED569AEE43E5079 +:106E70007EF6DDBB14C0277D4ABD87C1BE1D7EF1F5 +:106E8000CDE4DB107E6F1988CE4D3AAF9DF5A1E9B8 +:106E900010BEADC8B16E5D4578EC33239CB27798D7 +:106EA000490E30FFF6951A2075036C071B85F553C4 +:106EB000566AB0EE1D4A67F9562C070346DE1E5887 +:106EC00034FE5FAB4E11F54C535DA4778AFADF5464 +:106ED000948F86F6AA7DA00A7267C1DA979A0C3958 +:106EE00058AF93DF6B6C24AC17C7136515F6E7B981 +:106EF0007651EF3FD8540E44D46A94E3333FB66FD3 +:106F0000D5E978D9DFD684FDBF5026BEF73FBD5204 +:106F1000CBA6F9DCA67740D1F17A93EDFAAEF9AEC3 +:106F20004D7EAB6929ACEF1377380996C16AB69EDE +:106F30004E43F9BC624ABD17E18688EF0599D84BEC +:106F4000EF263CEDDCB79D13FC59507BF1D0DF936D +:106F50000641559D3E7C2801E057B3BBDE6C80EFB7 +:106F60004D06AF3F2BBFEBBB9A9D95A4CFD4B51573 +:106F7000D1B39BEF0EABBDFFA5EFCCC6AB18EF9323 +:106F8000D01F6A9F87AA1A7D7D934D4FED19DFFFB1 +:106F9000EED727BFFFE4F93FDC89E35D7087D3C6F6 +:106FA00041EB1521804B37DFC9F6B5BB27D0F3582D +:106FB00082B6C601EF6703EF227EA5D67BB07DD0F7 +:106FC000DC6CF700A02D86662FCA0D007D4037B21D +:106FD000EBF90B475F6A1FFF3E9EBE826696321E2C +:106FE000F978B54A722A68F6270C81F26AB043969E +:106FF000C2949615BD3B6C10965FB231B44B1AAA81 +:10700000DB5D8390AE3C4686FAEEEAEB831948E7F7 +:107010008D35C629DB117F430B5C33A3F4ADB5C9B5 +:10702000069AC7CAD780EE86C2D3107428F87D3F6F +:10703000901B0AF2459F19ED1C4B4632F3E7633B68 +:10704000DB6AA4CF95065F4519B6CBD0917CB1F42D +:107050009B5C5106F370A5EA143DCDA3FCD82C949B +:107060006F76234A50762279FA6E84D373AAA71ECC +:10707000E9F0399BCDEE870AE0911AF23FB59F33D4 +:107080008065939ED5A31CCF2A02791EA5C79E10AA +:10709000FCF384C348FC6EB52538A114FAB12ED098 +:1070A000D9FD30DECA9A751D63619C5FD6BC7C74C5 +:1070B00029BC5F95A6329C87CDA9868C207F0CDFEA +:1070C0008339C2BC5F58EAB5237F8DA4AA6C1BD458 +:1070D0005BFB1A993B8A5FD90641398A4FA638551E +:1070E000CD02DF7F95ECFB77078C3BFCAD77CCF8CE +:1070F000BD6B844E87641354F93E2715C7F6631F92 +:107100001DDB4F72796CBD737C6C7DDAE4D87AD765 +:10711000DDB1E5CC7B63CB5324BE01CFB1813CB65E +:10712000F22A660D7FBA04E52DC0E73D84BFB54065 +:10713000E741F8586AB69F9D05F559C84FD01E1A09 +:10714000C248EE1EC8FDA91BF5025372BDDB31E833 +:10715000727864E5986FC3FDB2F555ED0CDADBDEAD +:10716000FFE86BECDFC6A2DAE5237CB488239597B1 +:107170005D309F44FC871BE15DFFE707512E1ED564 +:107180007B10DE59352A8DFFF0647740CFF5091763 +:10719000EA3349A27D927975871EF879D2FB2BE7F5 +:1071A000A3DD1B0FD73456AF205D027E707BBB92F0 +:1071B00091FC58A1635588376823607FA41E01BFE6 +:1071C00098946224389992156137AA3AAC4F13FA11 +:1071D0009331E35E0BD2F1438738FE3F64E4FD74E4 +:1071E000F6E7A64111E519F2C994645D4C3FEBEC5A +:1071F000A28D28A73A78B9B53DF936A4CB759393FB +:1072000087219E98D0EE82FE7A659BB501B03ECB79 +:107210001B46BF029DF65259BB01F6B2D5CAEEF12C +:10722000C23C361CB6FAF5F0DE32F31776D4D38AB8 +:10723000C5BC5B9779DE463E10A954098E96D4668C +:10724000FBB0417C0D7E981FA203CAC5D27E2DA43F +:10725000E7594A9B49BE5B8A9A9B114E1BC6EB4875 +:10726000DF48BE5747F86CC9091EED8B7E82993AFC +:107270003BF6970C82DF089D3C9ADDEC45BF090385 +:1072800098EB4A38AA60BFB442182745C0D5E9DC5C +:10729000F91305FA49C1FE86F0F608278780D3E87E +:1072A0006437C1DD29FA4DE90BED87F07E1A4BBA40 +:1072B000FA91FBB8A18205707E725CD94F67FF4CD2 +:1072C0005390AF1A7E0770837D5272CD34B987E632 +:1072D00032B28F5B9779EBB7125DDBC8CF91E9CC07 +:1072E0002E433CCA3CBC71A26E087E67A5710C336C +:1072F0005900F1385365E61B9351BFF1121CE3E9C5 +:1073000035A3BD7912EAA9725FE2E93743654DFA08 +:10731000E4CBE938C3E92C2B18D20D3DC7D14BC6BD +:10732000E1C87D88F4F174BD25E14211C28545B7FD +:10733000D75FB9ACD7078FA29F87A5839C00D0E702 +:10734000C68DC7D83F4C585698CEFD4D1FE4FB0E56 +:10735000E1BF017905C4DA3ACC3EC686743A9F1182 +:107360007E95ED5A7DD7EFA0BF4BFD8C76942B39DF +:10737000879B3B503EB2DDBEFEB80F9B54DF130926 +:1073800050BFE9583A43BEBDD2C2ED3155E079BC99 +:107390007C592BE8C68D72CEF5AF3FA57E18EC9BCD +:1073A00036D00EB4B7F617156F9853FF07F52CF6C5 +:1073B00002E959D9ED1D4B6D38FEDAC34D6680AF39 +:1073C000E52DDEBE19CA7E15E1574DFEAC0339B37B +:1073D000084EEA7113433C1DACD70258667FB230A9 +:1073E000E4BF3B5EBABBCA8DFC276D9C1BF9D0364F +:1073F00041EF01619FC5AF5F356A3ED427E2DF6F81 +:107400004CD689FDF49EAD847D1CFCA491AD82CA4E +:1074100042DDF426B4EF222B81FF42ED74BDBBF6B2 +:10742000E751F6ED23D6D26032DA254BCCCC070AF1 +:1074300073F6970AF30171E638FF508AFC279785A7 +:107440001494B3B9F5A0F0225E2DB4325F14BE6778 +:107450007FA952FB47AC5A3079047F6F063E60E04B +:10746000FF64CF257B59A593F328D45F0CCF5B4FE6 +:1074700022DF60CE72ADD31EE98DF80B721FC6DB22 +:1074800027D66D00181A86C17F365DC834E4F2F63F +:1074900007049C54B32D84FC52B51D3946FCC5AE7F +:1074A0009E8F6E87763731B16A467E59840B957F01 +:1074B0006CA77216F05FD330D2FBFD687FFB93B8E8 +:1074C0003DC234CDED4C437A6104E46C336B3243FE +:1074D0003BC276A0B70CD66121BDB99DB9911ED033 +:1074E000C3762681581643B86E62AC229A0EE453D6 +:1074F000FA25D4457AB2A7061EB4D07C0CF52C60D0 +:10750000417D08E706F05617B2809ADFE5171CE2C6 +:1075100070D37746564FFAEC0B5F9FC8443E6D3DE3 +:1075200004FAD850DC671DF129AB3596FE185B4A8A +:10753000708A08FCD8BCC44EFBDC69BFF9DE11FBC5 +:107540001C5E8AF222776172CCFECA76D95F663100 +:10755000DFF0E87E03D46F76DF7605FD32D95FE693 +:1075600052FDE625EE2BF4DFBB87FE33088F7AEE63 +:107570003F9BEA3787DE71DC0EA0D814697778DD8F +:107580005DFA753C9CB317C6F2E5A1BB63CB122E26 +:107590001683E69C0030B7DCA7F36C85FEBE732C27 +:1075A000B65D45FE1FC9FEED6A1F724EC2F6609FB2 +:1075B0006F85B7379C8D6DEF2D7DCD8174DCD59EA9 +:1075C000CFEFA62F63DBC5EF4FFC7C615EA9DF8F99 +:1075D0009AD718B329A67E4AE565F34AFD41D4BC83 +:1075E0006E71C5B6F72DED7E5EB7159AFEE9BC64E7 +:1075F000BB3B465E5DBBF8754CAA30F50077DEFEFE +:107600000753AEAEDF1F56FDF376F72C8A1FC74F28 +:10761000F8BE40A78D4981FAE9F80AF5459B95F433 +:10762000DECBEC2C219FC6A1E201DF7992B471F888 +:107630005D85A43BE16738FCE275E9C8D7B3841FD8 +:107640009D09BF426BB58BFC0A3ED11EE44923F273 +:107650008BD61DF05D129F57B4FE9452CDED0A3BC0 +:107660008B103D4B7D2999D9156E8F737DA7A7711E +:10767000E2FB7F18154098EF8C4563D80740872FB1 +:107680001BEDA52ADA675B14D20766946BFA44C037 +:107690008F514D0AF995663CF0F6A3E88FB9FEB418 +:1076A0007B7718DECF08383C386C6D07D3304E90AE +:1076B000AE9F5FF4203C1F3BC0288E86E5F9886FA3 +:1076C00036CD8DF64625CE08FA396FA82FB223DFC6 +:1076D000FC914D43BE5939597B8FD6FB156825D097 +:1076E0006E265F3ADBD532C188F18ECABBDD2351ED +:1076F000EFA90C5A347A9A996A857554823E86CFDE +:107700007423532DF8B432333E4B9671FD2B69A48C +:10771000D75809E357B63DF357FC6EB61ADACFF5E2 +:10772000C900ADBBB2ED8DBFA1BE3653F31A915F58 +:107730000CDC61E43AA9C087C1C1D832F283E87297 +:107740005128B63CFC706CF9D3140EDF51C28F7512 +:10775000609F89F8F6BC8FADA47FEE05818776B275 +:10776000FF0513C98F31F36CB45F1F9FB36E45BF24 +:10777000DEFEE3566A3FF7390B6FAF0BBE8865FF3D +:107780008B096467CF4B099624C3BC5FF95A4FF04D +:10779000C66519B0FF17076C5D85F5C383251817FB +:1077A0007BF93AC63AB05E0D0CC175BEFC0FEEB760 +:1077B0008E3C6B0A6C837E3FDEF3CC8B3FC3719FA4 +:1077C000CD4A56607F6E40B900ED463D69B6A2BD18 +:1077D00031EAE3E7FB20DF98B7C314B3BE175314B5 +:1077E000A13FB89310EF7AF23B9E5AF90C7D5F7877 +:1077F000F618E1DD5E835F87713CFF4A8E677B2D63 +:10780000DC4FBAD7921BC07DDA97C2E9EA06DDB633 +:107810005FD6A27EF916D7437AEABFD03563737973 +:10782000377EC6CE7A18371FF6F9E247D67BD01FCF +:10783000D77F7DEC3E0D08C4965F4BE17AC274168B +:10784000F53E1FE7D37BB90BE7B395D17C0ACFBEDA +:107850007F573EEAE326AE87C48FFBFB142E3F7FA3 +:10786000F52BE887F3193DD7C3016240D7F3043DF8 +:10787000BCA2703D18FE166601FECF4305A277D765 +:10788000FB7971F390FD2F1570FADC9CB40DE5B90E +:10789000D3C8F1FEDC92C38F621C53B63BB344D312 +:1078A000CAA3FCCAB3D6CF3F9401FB5FDD9A4A76E8 +:1078B000A67C5FFDECC1B41FC2FBF33B540FAABE14 +:1078C000D5539F7E6414B67B561FC47962BD06FDF6 +:1078D0009F0FBE9684ED666D720C437F89FC7EF629 +:1078E000FA9BB5F2287E7AADF424E9BF5AD8C7BB1B +:1078F00046768CCD0278CF5BAF78B0D9BCE0F72765 +:107900007D0F759D4D7A0FC6374A54E6D50F23D3A8 +:107910007D323EAB5B5F3A9409F575FB4694E0BA65 +:1079200056E9BCB70D467AD962203F58FCFE189D37 +:107930001C7FE1FB900EBE5F75A7AD0AE322D06FFE +:107940003B960F146ED3A31F3FE92CF037FEFE9831 +:107950000E78E6D9B6878680CD02786C6B42FAD86D +:107960008B8E0B1CE7053DC90916E2EB1825FCCFF1 +:10797000F3FEB3C5A8C2F3ECD96549A59CFE689F88 +:1079800090A93B617D554F0E267A9DBD3E96BE6403 +:107990003B39DF3981D8FA78BC28704A7F052B8CB7 +:1079A000C6AFF87629E3FD46A4C7EA45C0CFA3E8F1 +:1079B000A6FA74B311F5AEF871508364725FF58462 +:1079C00097CC4DEBB5F0F582CA6B86F59EC37F71FF +:1079D000BFB98276FD5C8596C8E65DC7CADD00CF7B +:1079E000791359053E253F3C3F323804DBEF35849F +:1079F0009FFE25F1C144E207E7EDA124F42B650ABF +:107A0000BFDE79772809F9DC4511B7C37A2CCF6D31 +:107A100003790074FDF12746920B4B83079370BFE7 +:107A2000CEBF68D1E9605F3E6E4D29437FD0F9E05B +:107A3000EF92705DE7822965E8D7EB894FC4F33791 +:107A4000A90F9CC47F5E0F7A8F531BEB44F86290A2 +:107A50002103E44D4A7D517D37742FBF731AEB8BA0 +:107A6000304F23F2239B671B8713C5F33E3B9CB229 +:107A70000DF75BF2D94A85F72FBF9FEABC3ABE5A91 +:107A8000B16A00C5993E63EE5EC8E7EF46DA80F959 +:107A90001DDE5FD00BF50DF9FEC134EF3D4EE8CF92 +:107AA00055D641F901AE71CCD3004D3FD07BEEB736 +:107AB00003FCEF6520FFF059EC3392DFA63195D639 +:107AC0003743652115F07D06CAE72154267D68C637 +:107AD0002625D000EBB977752CBC66B598BAF004B2 +:107AE000FE9BC380B122216E8A6A07FDCF41390C0B +:107AF000FB30D7CC4209D0EFDCEDB1DFCD63219A6A +:107B00004FF5F3DF98BADB8FBF8AFD78304D5B8489 +:107B1000FBA14C34D3BC7EFC824272D229FC9591ED +:107B2000C77A0530AE364FCAFD77F8BED53D50A9AD +:107B3000DD0BF87771D10CEDDE144A3DD1501F6199 +:107B40002D8984CFF3CA592807E637AF4D090D4E6A +:107B5000EAEA8FFD46E1761EE3F1CEBFBEC3F7F140 +:107B60002EA13FCD84D7A88FDCA0E3793D910D0AEB +:107B7000C9D751CF2BFE44E0CF33CD602A229F12CC +:107B8000EBC6F6BDA03C9BF9094EBF74E6D3FAE6FE +:107B9000B00E23A7A340431A8C5B7B167813BB1A45 +:107BA0007CB89EF6FD73E6A17DDF82734E457C288E +:107BB000213C91EF414F6296E4CBBFC7FDD3A2E0D9 +:107BC0005DB529B6CCB647957BE3FE40396ADF6ADE +:107BD000777E63D2BAD9AFC73AE55B60C084C1D1C2 +:107BE00074C2F5F013623F1FFBFEAC0CE44B6B500C +:107BF0009FCE141D8C443ECEA49F256486FEADC34B +:107C0000598CDF05F43D2ABFE2FCD1B8F5D98CAD23 +:107C100033F8287E3143EF3D84A1B6A274DF6F11A3 +:107C20004F66E8B45C95E0AA1590FDBD88E3C3E318 +:107C3000C3EA07D4776377CBF9AF5382211DF2A74C +:107C40003D5C5F492C8E187C5174FF9EE0BBBD0EDD +:107C5000840F6521DEBDA4509C6083C21A1580B3D9 +:107C60000BF619E5D306E5E42194671B6E75B306A0 +:107C7000A82FDE3961FE6B64BB5B29CFA86667A9BC +:107C8000BEC646EBE7FA7342FD561DD4A7DF533854 +:107C90000CE90DD67DCF44787FC2E9A67965D83846 +:107CA000FEB896F9F317A09FF88077FE6B8877836C +:107CB000ADE48F4B07582526D3B309F562175BAAAD +:107CC00060BBE5A90ACF83A864537E3388B059ED21 +:107CD00095CC9FC7E0A9A8AC11FDCBE92AE8D9FC57 +:107CE0007D238EF358129F57AA4E7FCF04D4F3877B +:107CF000F172F26245DB46F26C2DCD2BDDC42A70A9 +:107D0000DDF81EED029886D64AF5018253FA98FAFC +:107D1000229C477A1FFE741A43D9D8CF914E3CF16A +:107D2000E9507E2C147AC0C2AD65E9C8EF8F9C374C +:107D3000ABC8D78FB8A43E1BB2A13ECBFA16F2F661 +:107D400042DE2E2C1A938E44EDCC8D6D77D1A0F5AA +:107D50001A8E72EBA89EE24F7FB169BD1CD0EE0671 +:107D600023EB36EFAF572ADFD7BA2F151688F26309 +:107D7000D44DB944F642DD976ACCFBF34BCC2C10C2 +:107D8000E5C7A8AE3A3016DBD5B08EE5888F35C191 +:107D9000041688A28F1BACDD8F2BE9A2EE4B3DF3BE +:107DA000773BAE31F6FD9729CC9FD25DBBB4D8F7B7 +:107DB000B08E98F2EE2F3AD781EFD9C87012FA75CB +:107DC000C7A37C86F2C580CE6F00BE75C4C0E5EE49 +:107DD000057B38462E5F7087B95C46BF958DCBB367 +:107DE00009B8CF6A24696262D738B21EBF4F8E5A73 +:107DF000EF85294616A2FD89D03C107EFEFE8C6DD3 +:107E00006CFBD488F93AD56DFB097E126FA2E1E8CC +:107E10008F8E8335748474C033C6A56E5F35680059 +:107E2000A0E001C91F9E5EA58D867ABD2E865F24C7 +:107E30001477F20F62578F61548EF8CD33ABD06F49 +:107E4000DB55E6EDBBBEDF310EEB8B07F1EF27A76D +:107E50003EFBE6324A6A69E67A971AC9F5264695E4 +:107E6000CD71651B94074795ED71F5CEB87A575CD7 +:107E7000399BB73F9F18CAD57B18BB27F585712A58 +:107E8000F0CDF319A16998C7B6BAE1D7E3CA819FCB +:107E9000D51473395FDBA678485C09F8D57AB81E2B +:107EA0006BF3848D983F9750DC7108F94BF56EC5E4 +:107EB000AE003DD882AD212AE377EEA8EF820A7D9D +:107EC000571D3C49DFF5D87FA18EE87D55E129DEBD +:107ED0002EF821E9132B1AE753BE808C87EB994FBC +:107EE000CB52BAE2E192CF5EC8D00E129FDDA7D886 +:107EF000913E3BF114FB8DF243C9F67F1ADCF64745 +:107F0000545712167EBA14F5EBFFACF97004EA9BD5 +:107F10007F12F2649D121880E36E64BE01284F7FC9 +:107F200054D36FBF0EDA9D30843763CC6F4BEA6B4E +:107F300004BF1389E11CCC0B0C3CF6EFBC9C1ADE91 +:107F40008CF0BCF458C738CCFB3B9113CEC13CC07D +:107F5000EDA9FFC5CBFDC29BB17CE4B133BC3C387D +:107F60009CA387EF7BFB3F1C570EDF3F65EF9EAE68 +:107F70001F13FC44CEAFB6AFD69C8A7A5E359743CA +:107F80009BC1463303DF9C36F7DC0B4F011CA6FD7B +:107F90003481F8D953E7278DE3F682DFAB96A03F13 +:107FA00099FF919C247EAF929E9181B231B96B3F33 +:107FB00012733BDC2447AEAB6F45FD257DDA209282 +:107FC00023E54EED0B1C573EF767C113DA7F916A2C +:107FD000E7FC5BAFA3F87AFACF1249CF5B63E1EB22 +:107FE00001BAA1FDB589FDF89558CFAF52B91D7AF8 +:107FF000BFF366EAE72EA1DFB7AC0C3C6B01F81FBC +:1080000097793B6BB9BDF0C3ADC057808FB738B41B +:108010000CE4273F147978927FE0FBE4283BA9A584 +:1080200008CAB62E7BB86582966175E2334D8771BA +:1080300024C98F5AF2F977522EA537F071D3D70C95 +:10804000D886EB4850B93F6CE694826D4B492F9827 +:1080500048F3659A96A1407FA7E7F4D6A19F4CEE1E +:10806000CF9ABE5A3BAD47C419E43EC9FDFC2295E8 +:10807000DBF733F4A057C03A2DE93EEA0FF48C2128 +:10808000C21F477AC617B8C751F0656A7804BEFFA9 +:10809000FF084E1F7D1B70AA5904FC427715FC4255 +:1080A000C06F9D1232A4737E41F63DBE47B9D3EE38 +:1080B000F47D9D1A95AF33ED6735A457CA7925FC39 +:1080C0006457C50FD8E57416AFF799D2F87E49FD0D +:1080D000D423FDAA629C13C7CD144739610C12DF6B +:1080E0003C0176D552E42F220FA0E4A7F38EA07DA9 +:1080F0002AFBAD49D373FFB4DC77C5DB3A2B1FF302 +:108100006298DF8CEB9860A47D9772B7C5C1F35C71 +:108110005A1EC8A23C978B2CCCC83F3B92117F04BF +:108120003CA0FAC8D434A27F68EFB760FB39D751BE +:108130007BC00B3FF187A956B2835A306E8EF55340 +:108140000B03989783763CE1DB1C1D8DDB0DBE7025 +:10815000FF777F9EF721F126AD81FB9998AA0D99B3 +:108160001025E76F4DE3FB9C501C7EE93F50AF5D4F +:108170006D21BD16652CC5A89AD3A91FD8FF6169CA +:10818000DC4F417876EF238922BFCE5382705D9118 +:10819000C8F1729385C7CF36811E4D7C51E0AFCCBC +:1081A000EFF3097D2F5CA54B427D414B937633C89D +:1081B000F512E1BF87FAE961E524DA7FD3FDFA9091 +:1081C00009FDCC4D376BE1283B06FF30FE788FE090 +:1081D000AB6C3D233BEB1EFC2E09FBB72661BCF5C7 +:1081E0001EFC1EEDC8C537C7C41527A671FA96F345 +:1081F0008BE7FB13E5BC9A1FD7A2C791FDC7F70712 +:1082000076EDA4B4548273A817EEEF523DED5FFCF7 +:108210003CC3EBB91F3EBC3E8FF04EF6D7D33CFFBC +:10822000AC8FDCA7801C9C3586DBFBD2FE9929EC49 +:1082300071B638D6BE43BF4F67597F7939DE5EC409 +:108240007C81D8F65C6F4918143112DDBA9598F923 +:108250004B78F5048707AE116E52EE3D6E013A0081 +:108260007C598F7995805FEB1F482039E6340606EC +:10827000205E6DC47C1D92A7DC8EFFFC48AC3F26BF +:108280007EFF7E9E26FD6AD7667F3F8278D18DFD78 +:108290005D678D6C41F8D75919D1E7857D89448F89 +:1082A000AC6F781AE6D15DDC6B62480FB54AB80056 +:1082B000F9E00545ABA4764B13DC4897D2DFF1C15A +:1082C000CBDCDF51873B03EBADF3FF17E571D5ED59 +:1082D0008EB5CB2FC07F5540471774E112EC4FF29B +:1082E00017D0CB35D2B7AA787CAB56C7FC68B7DDC0 +:1082F000A09B3E87F38D4CB68DDE9F2C5810A5F7C2 +:1083000043BB762599A323D261B5D8975ADD296A54 +:10831000578DF958B83F68BFA11F102BA3FCD6B5E5 +:10832000AB3FA67CB0DA9DB1F853DD855FCA370A52 +:108330007E17856FC41FFC82BF30EE8F29E7F1F9ED +:1083400044514EA8E8A0FCB03AE18F493D101E8B85 +:108350007C2AB138C8A6C3B3EE2CD75F46B56D3DB5 +:108360008876BAA3A22307C9AA4EF84125FEC87988 +:108370005EDFB6568F76A4D47BA2ECD8011363FCE3 +:1083800018CBE83BB48B71BC30BECA40F4E2F27249 +:108390009D9097096860A35C6DEE4F7215E51EF223 +:1083A0003B695723FF43FC2A4A2F3B8EF4FF467A52 +:1083B000D91F399F04BC453B018DB4EB7BC63F09F7 +:1083C0001FD90EEDEB7FEE9F147C9C71BFE48237CA +:1083D00052FF291D9CEFE4AF57F44BA623BE2F504C +:1083E000DCE988EF17057F3CBCBF80E2A0F2FD19F5 +:1083F000BD8FFC8FD2FF3507FD7EF0AC16FC689672 +:10840000F097CD927EB2F5B1F15AF4534797E74A0F +:10841000BFD90E53571E13FAA9CA592811FAAB41F6 +:10842000BF1B3E83B1DFD5B2087D57B7FB1B534C52 +:108430003CB885C3F11E814F8EF2801EF9D8060B21 +:10844000F79F49FE366AF156C2935EC3B4FC87902B +:108450006EDE3090FFE57F0B3C90707930ADECCF55 +:10846000B8AF56BDF00F3E6422BE7E1AF48556E1C9 +:10847000F7998876F212A6E13901A6DA73A3ED68BE +:10848000F95CB5D75285F89899AE8BC1D7F634030D +:1084900095C91F46722381F402607343105F4B7AC3 +:1084A0004BB9CD86A01FEEA4B0EB6BEFB4F9B0BF13 +:1084B000B08EF3C5FEE97C9FFBA7F3BC5959EEB41F +:1084C00043053ECA382BFAA5A2E314433ADBAF15A5 +:1084D000FA2EA3F5AE9B23F2E83BE942477C2E61DE +:1084E0009097E4C30DBA32E273918F6C6E844BC5E2 +:1084F000C7D573701D9F4DB1D279C97B859FFCC6CE +:10850000749E8726FDDBD7EA272F4DEFC4C7183F9F +:10851000F95EC117F7323E5FFF592BF7F7AACC8FF0 +:108520007C726F704000E75B29FC23A87F21BF8E1F +:10853000BCC4F791A95C5FDBDB3638807474D2E091 +:10854000DB3013FD4DAD06F21B3235F0ECD3D8CF46 +:10855000AB191ECCB3BAA08B6CF93DB4DB7BF657DC +:10856000591857DB2BE21BD5C65001E9F522AFB4F1 +:108570003A2954807EAA57C47E555BA10CEF532C38 +:10858000BEBBD253BBE28FF81DBE3F15E076C329B8 +:10859000C6F1C0BF9AC79701BE193371BE2BD3294C +:1085A0007E89FB82FBF0C1BEC1B4AE7506D17E0FE1 +:1085B000F7732B130BA7919C59654A41F85FF41A86 +:1085C000292FBA6E0DD76B67E8DC5B1621EF7D357E +:1085D00081D637B3E528C595EA1E994DE74DEBE600 +:1085E0002EBE9DFD93780BCAA968FFFE0516C9250E +:1085F0007BBDAA773004F3B8D036C0C3C3A5FCFC5A +:1086000052ADC8BF3D6D601ACE3BB2CF10E8EE5CF4 +:10861000654FFD9383B384CB4B1CA72E3AAE45F236 +:108620002536CE75A5F20543B8E001187F758A6F2F +:1086300075BAD03B115E75AF66101FFDE0E12F7279 +:1086400049EF69E6F194D3066D1AD289A33C649C84 +:108650001EC55FB70B3A9E6112FA2DF0C168BA973A +:10866000F52565B174269F4F0A7A4B14791897D770 +:10867000CB3CBF492694C7DCF585FDBAF9393411E6 +:10868000DF1C7536B21FF3D9AA8345143FCD5B1C9E +:1086900022BA047887D03E39BD2191F3135826F6CB +:1086A000336B2423FD7A969EE795CC3281BECEF5BE +:1086B000026A7F66433AC1A16419D753232F29C4A4 +:1086C00017659CB792F1EF77359EF4EBA17DE50E2F +:1086D000A508582BAB6C2CA5BC93B99BF269FF473E +:1086E00009FE3BC3A4156C407CDBC5E384301ED976 +:1086F00005D5985B378CF89211E56BD50E85E22590 +:1087000072FDF1715516888D478D0A72FE8D728348 +:1087100045E993520EA1BC60717A6E2C5EF8AF4AA7 +:108720009EC6CB8377D3AF56AF8C95A7EF21FF4A78 +:10873000BD5C9E82DD701CF1B0A48CD371A495C782 +:108740009F6A583D8FC30979D6B92E210FCFE8B95A +:10875000FC9D655A4BCF8BE93C0E359785451C2A0D +:1087600062C4F9F5845F17D3657E7B2C7E49BC8A91 +:10877000209E417FD56759E8BB305EF56216AA1985 +:10878000C29F894348BE73396FE6721E9FD6AB9075 +:10879000F7F1723E5EAEC7CB73146728B7253E452E +:1087A000C723504F1AB538A0E7FEE66C3BE665CA12 +:1087B000FDBDDFA939B253BBF4C0BA6366B37B28F1 +:1087C00096BDACB70DFD68A59B73A0BE4EE5E7C393 +:1087D00013004E5BE1FD666187ACCAE174E612F9F5 +:1087E0005706D5CB8A6CB84F1DE43788A432CAA788 +:1087F00097F0DD9C08DF613E420EC78FCEEFCDAC17 +:10880000D11AF57DD95E0BC9A94B7B12E91C205307 +:108810007D790EE82FED4F603F40F9C2DE44D21360 +:108820002E08B9E194FE19B69CF6A38F8BEFB39F87 +:108830009565A19F9B29E3B2189D8FE7FA6C8DA3E4 +:10884000A7F884A8CFEFB893E39989E4F52547F812 +:108850007E2CC37C28BF3BCBC5F7BD6EE798A29F9B +:10886000615E86D7E6E150F515A1FE61D22FBCD33B +:10887000ACC77B1216471E8075D4E4D8286FBC3C69 +:10888000EFFD77A742F9A39D063A5F3AE7A949BDF4 +:1088900042F899AAB9BAA393390143CCB9C5793B37 +:1088A00062CB35C1D8725DDC3D058BDEDFFA667BBD +:1088B000547DB94B9CEB74330FE6BD33FDDDBD7CBD +:1088C000DDF05DF9FC6249E0CDF67E9437789B8B54 +:1088D000D3B311F5A3E9880FDD7CA773F17D35993A +:1088E000EACFE2F903D32B26BACF20DDE59BEC4A91 +:1088F000453B2A7208F7D394777E08CAD3B2BCAF3F +:10890000286E78E941E641F85CB294929E746983DE +:10891000C58D76634BAE8DF0A0E55525A070BB628A +:10892000FC08E0AF55341558EFFA5B3FE2876598D5 +:1089300099DF7F0056950BF9954676DE990956FB2F +:1089400032F8AE6A3D97DBD5AC2309F9C006B97F92 +:10895000FAE78D66F8677EA3366029CC779ED74A02 +:10896000E7A4D4AF55BA1F600576196597D4BB3814 +:108970003FA831878DA538FE570B2BD00528FD79F0 +:1089800026834FC3F37886DD45A12C78357BD14112 +:10899000B2BF3AE3F6FB38DF9AFDC07E7AAF4CAC4B +:1089A000A0F59E81F5225C0E6E30D17ACFE4D8C856 +:1089B000FE3DB399DBF9B3EDC68099F4962F53F0E1 +:1089C0001CF399CD06BA3FE07278DC42E7893FDCC0 +:1089D000F43AF91B3F647C5CFF4E3DE93D1FDA230E +:1089E000252184A3BB3E09F5E6AAF573E83CF2EC29 +:1089F000CD7A2FF2B3D99BEFFBFDF5E8279B785793 +:108A0000312EE926C7C234B7ADAB5EEABB6AF2C805 +:108A1000A7910E6FFA7A4CC74DA8776D063AC9E751 +:108A2000E71D50DF6FDF7C0BE9B7B327581DB82E69 +:108A3000F7A6A7C6A21CFA7042269D9F9EFD82C281 +:108A4000F0CA8CD98E4569F87EB6A27ABBC3A7A1BD +:108A50002E7EEEB934CFE609E1777FD4139E005D18 +:108A6000DD8972B866B381F4E7F689C7DF9DEAEC69 +:108A7000A22B65E2FADB4761FB670CD4BE536FDAC9 +:108A8000F43D892F2C5482F619875B3C9D99F21690 +:108A900017E0BCE2E96DF6B2FA021EA7BB36BA6374 +:108AA0009B38DDFD9B4BDCFF71F574B7D7957AF5EC +:108AB00074C7B29363E4F0E5FCCD4FF094710EB34C +:108AC00087694FD928AEAD29C07F3FC080FE087CA2 +:108AD000F27362EADF16EC780BF1D8E53B82F3C85B +:108AE000635A11CA4D77C45E8667C06C422F649B7F +:108AF0004CD29E203B615D2A7B7A55945FE4CFA2E5 +:108B00003FE0037FC47E2EBCF7D521DCA7DADCF37F +:108B100043D0BF5DF7E55F282E6A6BE371759B2735 +:108B200042F90606A797F050F2F73A0F973FF1EB9C +:108B30002AC8E0F6619D3342FDE833DD546E1171C1 +:108B4000A48D8BACE437DEE80C58B8DFC3CF503EC1 +:108B50008D1FA9E7F140A1B77D4FF85DCDC507197D +:108B6000C601D9689E8FF756F1413505CABF1F79F6 +:108B7000B387CE51163FD9D41BD73DDA20EAFBD0BC +:108B80003D27FFAE9552FD0297DE8DF43DBE98E77E +:108B9000A3B2AA24F2E7BC55FC81F3DEA8F97B99C5 +:108BA000D96D03BC9908C41A9DFF78FB688BDB164E +:108BB000853F9F352B155C7F76F79A3C98FB6B4879 +:108BC0001E17C7C26381CB48E3BE915ECA3200CE96 +:108BD00037DDC8F7E3DC0BA600F2C173E25C523C60 +:108BE000FC7A6508FC5107C4E427388DC15C949376 +:108BF0001F2BB1DFCD6DD2537EC09C26850560BC96 +:108C000073CFEECA457EFED153BB72A747CD27FE78 +:108C10003BF9CCC888F57FC6FBB37BF263CB7617F4 +:108C2000D7339FB94F57FB8B557F273FF6F436E17B +:108C300007D7B4BE4EB4AB44FBF8FECA057E28BBD2 +:108C400015F29F483FEEA9C34F62C4A873FF2C6D75 +:108C5000F9BAE83C52F91C25F66D12EE1B2CC5D270 +:108C6000C4CB3DED574FF47842C821B96FA79AFAAB +:108C7000F442381A6B6D2AE3E7030B51EFDFCCACFB +:108C80001EA4A72F443EB1D30A4FD0D38C992E1BDC +:108C9000F233791FC34FAC49DBF0F985C837765AF8 +:108CA000E109FDE46416527F5FE8BC641FFE44DF07 +:108CB0004CE7466FC9E0704867214541563BEF6578 +:108CC00085F2E49A62E19DD6C0E548A4D248F24B11 +:108CD000C2FD86E9F7931DDCCD7EAD473CCA1CC9B9 +:108CE000DFF933F2851E1DA678896524B3A39FA002 +:108CF000E17A3FCD43EE571D6FCE943685F467CCB5 +:108D0000F34948A6B8B05F3C992D9975C6491284BD +:108D1000DDCCE2E222E9A077633B394F2853BED095 +:108D20001A47B0B980C795492FC57EF1FDF4412A95 +:108D3000C515B09D71D895F1AF134F453EE878F950 +:108D4000BECADA6D1C663C9ECBC27D00F9887A21D2 +:108D5000F31862CE656D027D1AED3D19E7D6EB8200 +:108D6000452EB24F3AC2E887319698DD286F13F44A +:108D7000C142DCBFF8B837B4CBE7F916D90E94334B +:108D8000F2DC55EDA2315E8CC781FEE137E3FE4D8A +:108D9000E0FB57FB4029BD5726162E45FCAA5BCCAD +:108DA000E87E88316DAD940F5657C1F5B1BADD2715 +:108DB0008D0CF077BAF00B31E1174F13FB7A4AE8CC +:108DC000DF5D71BDF016CCB76F99934DE7ACE3F35F +:108DD00067AE35AE7B31110032342A5ED7CBCCE59D +:108DE0008CD87F49DF327E9738C89B8F9AB861BD97 +:108DF000E98875C4B5E4C7841F2ECFFE27F931FE7C +:108E0000FADB313FC68C5ABEA8C769801CED3C47CF +:108E10006971537CAFB31EEFBF30EF56C47839B7DA +:108E2000DFAC529EAF289F5A8D7EB1351616335E49 +:108E3000F4FCD4B8FE0DD0BFCD2DDBEBC6637F8F25 +:108E40000D13657FE56ACC075A6388ED8F50509EFD +:108E5000FB34778DB7393BF8F0EAD15DF21CE4FBC7 +:108E600061941752AEAF383EBE79A81BE9EB73CAC6 +:108E70009B96F2B9CEC9F365E2F9D8DB829F835E97 +:108E80003C1645EE8A29F3E9BE88CE38775BA58685 +:108E9000FAB08C73D72DF652FE34E803FF9141FAF5 +:108EA000C0F933FB19EA9DE7C82EA8FB52E5FE2660 +:108EB000D02BF0FE1F735B29F955319DB75FD4FEAF +:108EC000CF15720A7578A487BA4D3F784A0FF543DB +:108ED00033B530F56BE8FEFEAFBF65703DBEAEB09A +:108EE0006C03F203B65DA1FBB756157E467A47EDDB +:108EF0009E9B4744E7FFCFD9FD18CF1FDF61E8767F +:108F0000FD7FCBE07A6AED9E97C86F7A2EC08F2DD9 +:108F100055A98195A8875655E950F362C581CAA91C +:108F2000A40F4C8175C0BAFE9CC1E153B763921F78 +:108F3000CF23D4C17F0ABCDAE89D4576C1C6296635 +:108F40001BC697EA0AA7CF27FCB75B355C7FFC3CC2 +:108F5000BBE2E9563A37BE6AB7A102F5A812D09B28 +:108F6000FE0DE69B933CAEC2037C294BDF5AF463B3 +:108F70001BE617742F97B764713DA051F1FAEF28E3 +:108F8000267F298BCE57CADBCDF5337BA631C63F72 +:108F90006FCFE4F74C8DF6778C419C7B550D27A065 +:108FA0009E5CC7B44FD1FE655E9B9BFCC48CE713EF +:108FB0003897B8C94F6C76867F3E94F42895E2E9DD +:108FC000D2BEB8B087FBD79665FA7232D13FA80FF0 +:108FD0003F7A07C2EDE7AAF037733E933BC9360CE0 +:108FE000FD611667F8D10A37E519915FA2D7771BA3 +:108FF000691F5E75323BC2678CBF5255A2E48CE498 +:109000001B633ACF4D39C90F5BC6D91AEB07BB7545 +:10901000C64C28DAF84D4A979E70F8ABC92ABE9420 +:10902000FA83CEEC233BA77C0AD88D8897CB238785 +:1090300074E8F7777690FE581354689C9AC2DF5014 +:109040001EE03C916FD699F7A586290FEE3B990952 +:10905000C28FD9C8F19275905DCC9EE7F007FE44AF +:10906000F9715D7AFC526A27FB338A78458DF0E30B +:1090700000A0A8BE2C53FAE19689A7CCE7E3E3321F +:10908000D55D12ED775837012409CDCB9D84F37D52 +:10909000C4EABD2D13E6750AF017D779AA2981EE27 +:1090A000035BA77468E8D7F417F1BCE1783CF28958 +:1090B000717B1D888C457912D9D353DE30CF13DEF6 +:1090C00030E23ACADB2FDEFDE958C40F56C1881ED4 +:1090D0006B775F5DDEF04CB11FFFCFE40D7B146D4D +:1090E0001B3CEFCF7470FD4AE60D7BF87EC9786BB0 +:1090F0007CBEF0858C90CAF3FAC25B9E42BB7DB702 +:1091000089F261C6EF7EFD18FA35C79B5990E2CF10 +:1091100071FA43C4396909D2C9C54FCE6C798861E7 +:10912000BEF9CB1E7E1E36561FE8C91EA098499474 +:10913000DDB83653E8E7DF923D20F9759DB0AF3ECC +:1091400056228F14E0FAF6E9EDDD9D5FDA22C7EFD3 +:1091500029DFA5ADFB7C17E98FAE08E7C7C4BF7652 +:1091600074F6776DF1B4E7507676134F5345FE9A57 +:10917000AA70D6C11C3CBF49C6D3D4D6011427332C +:1091800075C5D342AC9B789A2AE2532B0C5A25F929 +:1091900069F699DCDC8EF612FF6A6C4DF5207FAB28 +:1091A0009B7BEE453C7AA13AC6BAF09C5FA3807FD8 +:1091B000F5D5C7D3DA33BB89A76D157ADB0785BA36 +:1091C0009011E0BA9571FEEB6F9371351DD9B59191 +:1091D000877368DECA4433CDFB83574DDBD03F3500 +:1091E00043C6CB5EE5FEB519222EF6C1C402F23F9E +:1091F000F504E7194DB1718777059C2F594AC94F7E +:109200007FFF2F26907F7E16FAF7FBA07FAB59F8E1 +:10921000EBB99FCFDDC4EF3170EF50E81E59441316 +:109220001DE9A476BA4F761EB0D18DC87AFD80357F +:10923000DF81D78A4E417DC8DD086550FAD595AAF1 +:10924000DF05EDB61E4B20BFE20AA75BE4E7F1F8AD +:10925000B57FB512E8C7FBA5FBE3FC8D3A0DFBB962 +:1092600094C9E57C5296B1DBFB281A0D224E22C62A +:109270005BCA60DFE1A953F87385B89F301E1EB248 +:10928000BF4643BD19FD7B911C7E0FCD25A33685BE +:10929000FCCEC90574DF5463627D5305AF279ABDC8 +:1092A000648978A9FEBB2A5748993B99F2A83345AF +:1092B0005E621C9C6736C796E3E347F1E7E36630DE +:1092C0005FFF8C3E979F1F3B8FFC16FABFB42A5F4F +:1092D000EC8B87E2288D06F71FF2290ECBEF935A0D +:1092E0009ACDE1A6CBE1CFDE8E72BA1710E885EBFE +:1092F000718CCFBFF7779D0AD24BA383E3ED7F77C5 +:10930000DEF1F34DCB2AE07A8D83D36BE34A25C09F +:10931000E1C5E77DB57E92E2AC6FD74FF281E2798D +:109320003A944FDF117FF03F6C20BADB6BE1E75ED0 +:1093300025BFA28423B43F85BD7B232AD318573D84 +:10934000BB9CEE85DA58D53B09E3AE6326D9681D90 +:10935000B5AFF273D5358BC3B988D7B565E182FA5D +:109360006EE08A03A892BF42BBE94EC6EF176A8A35 +:109370008D23C6C78757A768E3B346A0BDF441EB6A +:10938000EBB8DFAD1692AFB58B234FA3FFC097E2CA +:109390009B9405F871FE81E36315377D46FAFCC5A1 +:1093A0007DFDE93CE8F4C6D873716C756C7C923530 +:1093B0002593DF9DB5C4BEC7735B31DF5D16AFE497 +:1093C000FACD3AA36F00EA9F37DDC8F3313E99A387 +:1093D00063B8AF9F58F8FEFB1F4E14FCDA53102DF4 +:1093E0000FEA7BDC5F683708F302789EAC6C5F8322 +:1093F000FB0BFB5A2DF6F79397BE5380FB7BBEF514 +:109400003B05B8BFEB0CCD1AD24751BA6F21C2E36E +:10941000F4CD5ED20F655EF0D5E25DC3B78C77D731 +:109420002A8F9BB3FE35798C7FD17E9357BFD2FBB9 +:109430002D245FF879E22EFFDD39BA57EDE2973A35 +:1094400005F9714FFDE50B3DCF65667ED4C34ACA71 +:10945000C2F45DC9DF750CF541A907C7CFFF4931DB +:10946000FF9D599A09E5A0F4F75689BECD81CFB981 +:10947000BEBD5D217FAED9ED4F1A45F6D5CCE17A60 +:10948000E22FFF46E742589B62473B65CEF6A55464 +:109490007F61F70CAAD7994321B4C76AA01ECB2BD2 +:1094A00046C7E6791B77F27890B47F611E7AD4D7ED +:1094B000129C1123E2672DEAD730C55A95FBBD6B8C +:1094C0009DCCE367A80FC7DA8B32AEBBD1CBEFEDF3 +:1094D000D9D8A6D0FD5D69465F7E36EE6B5C7C77A1 +:1094E0007F96760EF14EC6E71F4CD30E22DD3A8DE5 +:1094F0002C97F2F90CF25C5AECB9CF9EF2E48E761E +:10950000E2C195F4A8A9A42FFD9579495F7A072FA8 +:10951000CD243DEA4ED2AFE4FBCBF3E40231F1FCC3 +:1095200059E29CEE2C714E17F97E288EEF4797ABCF +:10953000A3F2E442DDE53B44E5C9457F179D2717CB +:109540008AE18F9C9FA4EB17501CBD0EE866D1B03A +:109550002EBCAE66E26F7DE4033A37B4C3447EBAF4 +:109560006A91C75B57758AEC9F3A3C87C4E95BE315 +:10957000E7E9B97E550D7625E5330763F37D95EC74 +:109580006F57FF96ED7AF2C7DBB2A59DC8E95BAED7 +:109590004BAEA3BA4DE1F41837CF787B3ADEAF2E4D +:1095A000EDE1ABE573EE6F79DDD7CAE706C7C1E140 +:1095B0005FE57397C527FA46923CDF427CE223774A +:1095C000731ABA28659E74D33E9E273D566FD37892 +:1095D0003C54CFF325E2E3C2EEB114F7947168F383 +:1095E000CBFAC0B27C6AEFC17CB49A7D8994BF503B +:1095F000E5AE223D3E3E1E3A97B58EC5ADF82B3BFB +:1096000042E7DEFEBB7908DFCF4E74129F72B3FCD7 +:109610006BCC43B83BFB1AE2A1076D9FA7F8A2F001 +:10962000A56C101804837ACE379B2BF63F41E4AB30 +:1096300098553F73447DDFD3770BB2B93FF1A0C893 +:10964000935A939840F737B88CFC9C874BC7F3B973 +:1096500086667A17E2FCCD6EBE9F4FECF901C373AC +:109660007B4F1882749F82BFC6E641B928FD58B26D +:10967000FF76E15FBD5A3A5AF93FCC3F1E957473AD +:10968000B5F1BCF5008328FA8AA7879EBEEB89BF97 +:109690006CCFF63EC1F1421B427190ABE44B09C561 +:1096A000C0B751EEEF34B9D11E41BF0CC9DBD5199B +:1096B000D29EE7F742ACC921B9F88985DB27F2DCF5 +:1096C000945CFF2EB9FE6F496FB4A47BF764437FAF +:1096D000A74B353A27B12291CB97C8B33C1F29FE3F +:1096E000FC50BC5C91E75FE478BFFBBFCC578F7D3B +:1096F0004B7C15E42CE91D3DC67D2FFBDECFEFC171 +:1097000029EBD044FE0D9DFB90F3AAEBE0797C673A +:10971000C5FCE4FB90D07306E7681F215E9D7FCFF8 +:109720006CC6B86A7131E79FB55E1BC5256A833C7C +:109730005FA77631233F823C273CDBE5FB1CF76FBC +:10974000C5711BDD5F5BBB7B6B536FCA67F091BE5E +:1097500078E13DFE3EDDE5FB02DBD52D0EC7C43FC3 +:109760004ABEF97C794531CD97FC004E53ECF9ABFC +:109770008C1CCE6FE4332D47C217EC1DF8EE7C1520 +:10978000CF3FAF736AF652CA63E0FEF5047707F97C +:10979000956A77929060940C8BF53FCB26BCA9DD3F +:1097A000595A44F736042D45740FD19FF8BD5DE733 +:1097B0001FC80CE8B93F3E2967049E3B09DC8A7A42 +:1097C0006B1E8C832AEEF9D65B8BC8DF1847779225 +:1097D000DE3ACFDDFED01C6850BAE8719D81CB49DE +:1097E00029DFFE91EDE6F110A7C8476C9BC066DA51 +:1097F000BACA36676C9EE6CEAC9BFF81FBF38F6CDA +:1098000055C4D179DC3EDF0CD66CEFCBF1305FC4B0 +:10981000ED27887C0BE63777E559F4BE72DC5ECE27 +:10982000AF93EF8BB87DC297E27722EC46C28BC430 +:1098300026CE3718E005EAEDA3231D63F0BC5BDFFD +:1098400096D06884572F043F9EA361E19F0FC5788F +:10985000488A3A1AE3215B160D3B80715A7565C739 +:1098600077716BDCCDF632345967BBBC37E4107FBF +:10987000A92F44FC2FFBA381E747AE4C2079DF9250 +:109880005B4DF991178E9B62CE23C53FFD6C990B02 +:10989000FD50BD9BDEA67844E24EA5DBBCD79FE61B +:1098A000D844FEE43217FAB5129B3AFC23D14FF3A9 +:1098B000B0C2EF0085D92B2EF427A83AD43B66EC32 +:1098C000E6E7E567343BCACCC44F151ECF19ED243B +:1098D0003EA9AEBC4D87769FBA94D17D7BF373B819 +:1098E0005FBC5F8B5D87FBFEDBAFF5DDC6E97C39D6 +:1098F0003A19573422B86A4C914398DA29E38B32EB +:10990000CFAEA77BECA53C8AD7672FD363853CEA13 +:10991000D4E7E3F0B8A7EF247E4B7CFEAD81911E27 +:10992000F65BC54CE7DE245E37CAF3075F733F7111 +:109930009EC8DF39B5EABF86F07B02647C26C0EFA3 +:10994000713584976711BCC237FA71DD3B1DBADAF5 +:1099500041E45FABA57E56F27BF2F29AFA2C1B59DA +:109960008C4F3B53600AA7F6CECB43BAF4031EF4E8 +:10997000EB060F6ECAE17952EACA04DA37752DDDBB +:1099800010CE54471AED9BFA18DF9FEB73383C65F5 +:109990007C58FA4107E7F8D6603E70E739B545567E +:1099A0007E4E4D9CAB4E5C74FC053CFFB545F8A368 +:1099B0000FBC3A907EDFE3D24A55413DF592A39227 +:1099C0007ECF6AA3D8D744B583D96DD1F87980F218 +:1099D000747BEFE3F986AA3837AEAE746E4578969D +:1099E0003B7D948FFCDDC610FD04C6ABF6D314F7A7 +:1099F00003BD88CE079FDBA348BD28461E4ABB2D6A +:109A0000DE1E7B51F2CDFF213D694F279FBE463BB5 +:109A10008BC5DA9B9DEDA5FD186F4FC47DDF93FECE +:109A2000C3347F4CDECD11B1EF52BE670ADE28F39E +:109A3000713ACF89B38005CF714C41A21CD1959763 +:109A4000C444BED27AC5EA417DA9A7BCA4CEBC213C +:109A5000563F94FB37EBBF834F99D724F3962C984E +:109A6000BF927279FE8A05F35752F07750F87973F6 +:109A7000997FD26070533E8BFF4146714965620504 +:109A8000F9FF92BD46C2BF8B2CB0017F07C03FD902 +:109A900046E7EAF19C13E27D447151BF632A34D951 +:109AA0005E87ED3BEF93AC64549FDC57CB403DCCDD +:109AB00002F578CF75E739F399FCDEFDF8FC1599CE +:109AC0004725E3CA99FD5F56D0CF8A6104CA67F87B +:109AD000B1F82E9FF7D3F22337F18DB4069E2715E8 +:109AE000B99ED9D1CF5F26F98F39765FD729BE7C51 +:109AF000A4CF75567ECFC266E669D243B93DA7377B +:109B0000EDE346E6DEAF2386DD4CBFDBF1BC53D38D +:109B1000E7A676E1939C175BCFD77D11CFAD295D8A +:109B2000E35D9CF3F75CD4AFCADA4C1C2FE3C6DFCD +:109B3000D879CF4DC082F2C495CBF1C113A7EFCA3B +:109B4000A72B5789C9FB93E3F7B43E899F57D2E30C +:109B500025FEF5846FFE32B14F271248FF90F8764C +:109B600060C90EBA4FB27D49909E172D4A508FE7BB +:109B7000872D9169C81973F2B2EEC07B502E26462C +:109B800072F11E95016EB717EF51B9981A3981E538 +:109B9000EB9FF8BE97EAFB45B6E0BD2A77E41DBB14 +:109BA00083EA713F33192BDA72E40EBF0DCFA9841B +:109BB0009777A0DC2A8ECB8B89BBFF2141FC0E540A +:109BC000BACD48FA64BA8813B272A1D763440BCAFB +:109BD0000D19451417B431F7CE0EACCF36F17B22F8 +:109BE00018E03FD6F7CBE7F9158CAF9B650B7F37B5 +:109BF0000BFBE9771DF31DF47D271FDF6912F12EA2 +:109C00003EFED197785C52E6093366CF417DC8E6C7 +:109C1000663165797F0A53ED39785F4283F4278A8C +:109C2000F22B09BE49B95172F9E8CD3F1944BF2F53 +:109C3000F3F2CFFA22DFBCC5187B3FB77C26BB39D5 +:109C40009FBC28EEA1BC2FC17777EE08FC7D9969F7 +:109C500063F14AE12929A54607E96FCFEA914FA5AB +:109C60000AFC704CE6F373947B15FC5D17790F6466 +:109C7000AA4F253F01F3B5E851AEA69EF652FE610C +:109C8000B539928BBFBFF396D95785F3BC5479F29F +:109C90007E8A3F661E3D81F922470DCD6392508E2C +:109CA000E48B7B3830C00BE5435979640F76F2873B +:109CB0007E0AC547C74FE6E771C7B1A08AFB3CD60D +:109CC000CECF878D2DCEF734C078E345BEC9D8639B +:109CD000DE24E46F637F1056F93D2111353ABF430E +:109CE0003E99CBE08EA6875BDD516586F755C7961A +:109CF000BFE7892DDF31F2EBFED1E5C18AD680EBDB +:109D00007C4511F76D007FE1EBE2798CBF12F6DC48 +:109D1000401733E7619EA553F1A3BD30705726C5A8 +:109D20006D768D64544EDB61DE668E5EFF5A1D8F4C +:109D30006B0BBFBAFC7D2AAC4379FBF27B6904AFA5 +:109D4000341BF05B27711FC2B703826E0F083A2DD8 +:109D5000C9325B91FF1F30B837119E279ADDE8A703 +:109D6000DA9F68A4FB7F1BE6F3DFB75092CCCC08E8 +:109D7000FDEAA7F332B4633742BDBEC44CF92907EC +:109D800044DE77C3832AF9B9B01EEF41D43F622580 +:109D90007F797952E1DD58AF4F32D2B98BFD8925F9 +:109DA0003E311EFD2EC1F64473087F2723FE1ED6CA +:109DB000A3382F841BCCEB293E0FA2477D8991F459 +:109DC00070793E1FFAA1789E3ED34CE31D70D8F700 +:109DD00023DE357C449A1ED48F74633E99C4EFF21F +:109DE000A491F4BB33407D7DA3EFD9D7A779DCFCE8 +:109DF0001C30FF3D95C2CEDF578161A11DBAD51938 +:109E0000D12D8F0FE648B83355C3F6194C96F9F9A2 +:109E1000B5B4CE72A94AF72D29B2BC94CA8F8B7AF9 +:109E2000796F6C6A1EE7534ADBEB7F43BCED9B0402 +:109E300070817DF224747F7EEAB4E0EF97EF5F8952 +:109E40000BFDFE0AAE7350D7FA0F383C2E6F54B993 +:109E50009B7D0920BEC5EFCB018BC78D7EB62BF74E +:109E6000C7E12AD7A1CFE4F0EC5C474AF7EB48CD35 +:109E7000E3EB088A73E3F1F54A9EEEDB5E67B7F821 +:109E8000F72FAF332D769DDFE23CC3CAB7304F7D4D +:109E90002ECCCFD6353FFAF9B812E49B1CFFC68909 +:109EA0007C6956189BE7C4467ACC5C5F8CCD6BBA54 +:109EB00045D9D488F2F57111377F5DD0D5A184FFE3 +:109EC000D517F5ADD7A715B413BFEDB5B411894BB0 +:109ED000F267C9FF2F659C2CC132C88101792067C8 +:109EE000EEEF7D741A76DEEE78BC2FCA2BE09BD79E +:109EF000E58DB87C9E927E3BE70BF48B7424E937AA +:109F00007EFE928ED8ED414A10DDCC42F474319E33 +:109F10008F0F7A09DD73CFDC395DEB03221F6BAE47 +:109F2000E7EB58EAA779DFE27894F2106FC9F7DD22 +:109F30009407FB3D65E8A774FF147355F6273B4D66 +:109F4000D1B4FF9BF3C58C7F7C2FF5FC78BDFE4A16 +:109F500079E9729EF1FC50CE4799B883F4F83AD073 +:109F6000E379DEBA42FCBEAE4AC7F9F06E85F4FA78 +:109F70005A903328A7E4BDCC3715581BF19ECDBDB0 +:109F800006EE4FF5BF6472C7DE4B159FBF2EEC89FE +:109F9000C54CDA0BFC7E8B1A3BBF774AC89996FBFF +:109FA0007ACB7BA9B83C043915732F55A53BF65ED7 +:109FB000AA1EEC05B00B483F63BD74C22EE072BA16 +:109FC000E57AB7DDCFC8FFCC7F2774AA51E88300BC +:109FD0008BB4AE7BF3C00EA0FB001BF3F2C5BD64D7 +:109FE00001FEBB2C42FF8FF74717A5FB56209ECCE6 +:109FF0001CA4E5E24F04CD30727F33E0DBA60E8671 +:10A000006998F5DBF15ED95B59FD3BBA3E846F0F71 +:10A0100013BE0DFC94DF37DB856F8FE4A572B98426 +:10A0200042E64A741C71FA1EC7715B1CC13FE13DD8 +:10A03000F81BDB4C046F99E71A4FDF51F3396DE0E1 +:10A04000F371EAF5349F27BA9BCFD5E07D345EA546 +:10A05000338EDF3DE13F9E27491CD685FF8315DF08 +:10A060008B386E271D2CE776D765F3D6DB68BFEFFC +:10A070009CCAE3727509D24ED6C667A4A11F928FFF +:10A080007FE74A8E177756F2BCA4096D35148763B3 +:10A09000E53CAEE681FFD1EFFC08FE36D9596440BD +:10A0A000D4FB2BBBDB807ECEC9E363E36F53CCB71D +:10A0B00050BCEFCEC98698DF39957098227E477DD7 +:10A0C0004ADCEF9BC6C3253E6ED7C90FC47AB3F0F6 +:10A0D000777FE099CDF8399E0CF17B7447F33AE332 +:10A0E0007BFDAF31BE772CEF1AE27BED8608DD3BBE +:10A0F000F15AEAEC4DF3816EFAFF7210DDDB7F73EB +:10A10000DA9CED6BA1FCCCC6EBA8FC5ADA0F171E4B +:10A11000C5FA2D05542ED77D3A0DE9A0B064EA3872 +:10A12000FC9D83760BEFC765F5B5E0EFDFB886F4ED +:10A130001E86F9C8E5C608B5BB6D68CD70CCAF2AE0 +:10A14000B7F2F291A2FF1846E5DEA23CEC95EBB027 +:10A15000DCAE7C3AADBBF8E0C0422584BF73579EAD +:10A16000CCDB8F1FF66C26FA8BCACB7879A0A7744C +:10A17000651FACD77D36AD3B7DC428EC21A95F7B44 +:10A1800005BDEFD24E36E2B944AF4DF1E0F913EF21 +:10A19000C893FC3E3A33CF53F93F722300BD008091 +:10A1A000000000001F8B080000000000000BE57D90 +:10A1B00009789445D270BFF3CE9564924C0E20215D +:10A1C000102609840492300987288703048C0A38F2 +:10A1D0005C028AF08633E42011748DBBEC6620802B +:10A1E000E8A28615151574404070118302A206BEC0 +:10A1F000E1505151E3B1AEE82E7FA2ACDC1283AE48 +:10A20000B8EBAE7F55757766DE37C902FBFDDFF32D +:10A21000ECF7FCF8EC76FAEDABBAAABAAABABABA7D +:10A22000C7EBC935CFCA626CB847F1F8211DE158B8 +:10A230009268EFC7D858CDDA4F5518733A5296390D +:10A24000E3198B1E38AC3F7341B99D59582A6337C7 +:10A25000A468E1AE0E8C4DB9E6DBE4289531E62822 +:10A26000ECE98D849405181BC0D838FC13EA8FB331 +:10A270003B026A0EFC9D6F39D790C1E8DFCFD03E1C +:10A280005BF1385DFD31D725E6EBDE8C61173F5F72 +:10A290004FFD76C0EF53067D9B6CC68F09BCDF0B6C +:10A2A00016C74A253AD8FF4DA27FE661DDE33B326F +:10A2B000A688FC4D72BC0CFD78F84F817A9D98F809 +:10A2C000BBEEAD1F15ACB7A25661690005F351BADC +:10A2D0009ED528084CB6A2A5E3FCACA67A177EEF63 +:10A2E000A6B87B39119E816EBB37BB35DC12BEAE82 +:10A2F00026F890D71A2EFC67867C1293FF14A7B31A +:10A30000238ECBCBA19D87C506E182F107107E5637 +:10A310007078D62B1594624306ED1688760BE47C94 +:10A32000F7EAE73B209CF9C2008E04E65EA962BB17 +:10A33000F8DC5EFF0AEEF2F0A81CD687B18976EF52 +:10A34000833698C3A4985944E7C9CCB73B06E6FFC7 +:10A3500062845680F0A826DFBE0698D41CE6B1229F +:10A360005E808E37723A72BA48B88CF86881D388AA +:10A370001703DC463C04E9539F886922ABA07CCBE1 +:10A38000BC0CF3A9461E047E6DCAB5F937E22066FF +:10A39000F81FF0F3D1C274FF034A10AEA30ACB300A +:10A3A000433D9F12EEDE9CC2D80F61307FF81E2F16 +:10A3B000F03068E62FC6B2A8D6F056DA79BD7BC277 +:10A3C000A336627A7D7AF8325334B64FF663FDF8DD +:10A3D00070487382F0FF60629A1DE0BD47AD25FAB8 +:10A3E00075614D4BCC29413E7BD80593EE8F7C297E +:10A3F000E7E353904E569332C3EB8039E1BFEB83D2 +:10A40000E9C32E4068078E2F3BC0354370D38C06BE +:10A41000A55141785D290E5C2F33EC6AC096D39A22 +:10A420005F704676A0D3CCCBF00FAB799C61BBE1DB +:10A43000765E6F26F68FF5168FF484D69B89E3E05F +:10A44000B82BE1BB3DF85D01BC27C5B6A60FCC8F8C +:10A45000E01F5339C27B220EF06515F4BA3792E83B +:10A4600035E6DE61F45D199FA134C0FC4714B828BD +:10A470008DEDF7A1996513DDA6D46605E9A876D41C +:10A480009EC275CACC0DFDC7C1BCDFEBFF5CAE063A +:10A49000E5C74DAC08EB19F1F75C107F57B48EDAC5 +:10A4A00083FFF508EF36E4FBF34AFD002CCCEFEC1C +:10A4B000243A32A6A520FD629C29C36210DF3FC169 +:10A4C000B880EF8958047CB0A7A3B613E19DCCBC3B +:10A4D00023CD30DFD802CDA239683813C2B3D0C93A +:10A4E000E119A93A886F9BB72B7E1BD4CBF7643E4A +:10A4F0003E18F2E5472CCC0FE5CD8CF375F33AD539 +:10A50000EF037E9AF7F6CB036005B2AF041FF75C4A +:10A510006B622E490FF85FA63F9CB93282F9DE5B71 +:10A520006375F9ECDACEBAFA7DF6A6EACA7303BD12 +:10A5300074E57D8FE4E9F2FDEBAFD3D5BFE6B3E17F +:10A54000BAFCB50D37E9EA0F3A355E971FD2749B16 +:10A55000AE7E7518ACAF3E886E4F7D06E065B6A046 +:10A56000D3F59766EADA9D8D1A7504D7DDEC55F3BD +:10A5700046E3BA1BC64A74FDB01ACB97C89715F0CC +:10A580001FD2732EF34607005F2359D39B4980BF28 +:10A59000057EC58D789BB796D793EDE6EFBD7378B2 +:10A5A0000CA67EFDF712660EE6A19FCA3F6D78E706 +:10A5B000704879BEB3D084FC77DE1519FF7504228C +:10A5C000825DF3B3DA267DDD01A4DF27AADB069FD7 +:10A5D00016BEADD23A58F882E267D06F3AEB118DD1 +:10A5E000F9F2232AF303FD4FB28AC70643FA4395D3 +:10A5F000FF9DC33D82F8B125E8E91CE6D2D339229C +:10A60000434FE748B79ECED103F5748EF1E8E91CBD +:10A6100057A0A77307AF9ECE9DA6E8E99CA8E9E9DD +:10A620009C54A4A773D70A3D9DBB55EAE999E22B38 +:10A63000D6D3CF407F299FD3562ED4D56BE1036F5D +:10A64000D1684C7BD4FC52D76F895A6A65A6203FEB +:10A65000F8E03FE4879E8CB90380E705408780AB34 +:10A66000351F14D5AD5E91F46FF041760AD0BF77F7 +:10A6700008FDD569D15A1BF25CA692AEA04FFBA68D +:10A68000F4273B6800A6537A821D04728379DBB6F7 +:10A6900083A4FC0AB53BCC0382FAAA3DB9D64ACFC3 +:10A6A0008E95FAA91D3DEBEA1A94838090638CDBAA +:10A6B000018CAD32211C53055F1F0CE77C79118B97 +:10A6C000AE857A506720C0750CE186718E85F73EA5 +:10A6D0008CEBF436566BC1FEA7B17A4AA7B3264A73 +:10A6E00035E624BB622673533A9B79297DCFAE4D64 +:10A6F0004901B9596A6F188076C95F0B3F3CAE209B +:10A700003047E310D876F12AE5F5C7F827D47B3037 +:10A71000C5AB215EF3EDAEBB1E854F07514FA0FCCC +:10A720001D1D47F032B3377B7C765BFD2C25F9FE8F +:10A73000BAA26928777D8976F766985BEF24664F21 +:10A74000443D97E04F1D0FF4294FD1EB975E8227D0 +:10A750005EE85CBB10ED28C6FCB1A81FAE76DC5FDE +:10A76000A5787E8170CBFA979BAFD55A7B27C2D94B +:10A7700054E6706F04FEFC44D0E3D95B6D01352ACA +:10A78000C8479F454C7FB303D0EDEE086D19F1DB50 +:10A79000E41B57605E3918E75A08F05D28047C73A3 +:10A7A000FCAFC4F252BBD6AD234CF17C57AD67343D +:10A7B000E2DFCBF10F7F647BDB849FC33342E1E3B5 +:10A7C000BF1EA1ADC67E0E9AEA93DD880F73FD0011 +:10A7D000B24B1D1DA89FF3568E97F6F0303CA2EBAE +:10A7E000349CD76C9BCD8DFB93E10AA7EB89B819FC +:10A7F000D3CBE1CF39266FC780AA83FB1982DB59FF +:10A80000D82D11F8E6BC45C06DEF20F0EECAC27538 +:10A81000D51EDCD5D83FDA89BF56FC6827D23FC8A1 +:10A82000BFE28BF13F00799BE9E22713D07EC93666 +:10A83000B93742D1BA70E81AF8FD0381EFF516C8AE +:10A84000C7D2F795F83D219CB74F78CCE4AF86F698 +:10A85000DEE1AF129D9E5DE0A0F91432971517D985 +:10A860002C615FFF65D8DFF735003DF6A5687B7189 +:10A870001E33E24CC99F101C5A6FB477D8E02BE30B +:10A880007FB94EC73BF914E608BC4D601E5A77935A +:10A890009866C1713FFAC6EA41F9F991902760FFC5 +:10A8A000D3F7A9CC4FE9ED2C40F5EF600D94FF30C4 +:10A8B00022A76B25C037EEF19E3D50BE86E0FD7DA0 +:10A8C000BE5EB519F19C5F4E7642BCAFE97045FCA7 +:10A8D0003B4EF00BACD74FB11F58AFFD725343D670 +:10A8E0004D3EE7176676F6F857EBA6BE99EB0B10D0 +:10A8F0008C8E4498FF0D828437784A484FA09D156E +:10A900000FF8AF77A96467150C6B3423FC5BBEE5C9 +:10A9100072ECAD252CD207E56F0D5319D26BECDA32 +:10A9200051A7B1DD511688EF07F5475ED20E47C338 +:10A93000FCC7827C0789CC0ABA809E08D14B372598 +:10A94000ACCE473BE2A6EEFAEF37B31A15F1373A31 +:10A950004BAF57C6A25E91F560BC038887D8D6FA84 +:10A96000E547A95F7AB15E57A35F169A3C2C95EC38 +:10A97000549715F97EA69979DA5A6F937B2AC29E6D +:10A98000E576CB2D62ECE6D117AD1760BE0353B56B +:10A9900008EC67E198BF4C47790CFBACF7FAA21EB4 +:10A9A0007D5F650F40F99755807150AE27AAECCCBA +:10A9B0000306CED7554ECA9FAA4AA0F44C958BD217 +:10A9C00073551954FE4D959BF25353BDF1D8EFCCFE +:10A9D00095DF9AD18EBA2F4CD28FC3B148F0EF7D5C +:10A9E000617C9FB52872D1678530EE225280A0AF7E +:10A9F0006B6B46A1D955BCB7F64D4CE1BBEAC0F232 +:10AA0000D58A1BF5D39CC3DA0A649F79471BC6A27B +:10AA1000D8E9FF87131D116F659714A6C1523AD06C +:10AA2000C39386E39FAC1A48709DAEF2105C9EBA49 +:10AA3000C637E3A0FDD9AA02CA2F4CF566A6764018 +:10AA400075FBAD15DB8FD9DE684E82F2911EC58392 +:10AA5000EB7BA887F9FD40BFB516AE2FD682BE406E +:10AA6000FE19963D7EFD5D0CE5B9D617C799143BDE +:10AA70006B641CF2D5C04233D69BFC13D85C2941D1 +:10AA8000FEBEDC3A39BF5F21FC9CDF1F43F89078A3 +:10AA90002A13F43ABFA7F72D83A0DFFD6047AA0071 +:10AAA0005FF32513C1D7FC59B81F8D0463FB85BB29 +:10AAB000D33A3107CE131ADB30DFBB13033A9C7D48 +:10AAC000E19E04A44786623655825C381B5BFBD747 +:10AAD000CF51EEFD99CB3DC66ABF7E12E562970469 +:10AAE000F70390FBC602FB34DAD75444A05E5C60E7 +:10AAF000651ACF6BBD317F369CD1FE76C08EA4E146 +:10AB0000B89E703C57CFA05C4BDFF178EAAF5CC1D8 +:10AB1000F96E79E189E6D75C58EE27BEDCB6637D35 +:10AB2000E7A72057BA737938C2F53ADA19B04E5E02 +:10AB30005F1D41F2EB758BFB7825CAEDF50EF766CC +:10AB4000A8F7DC43F77EB917D307CBF2EE45FE48F2 +:10AB50008DA57E66FF6E7E2F6C0F7A9C25C2BC7E13 +:10AB6000FF8A120843FFCB9A034B1361BC3EEB1ADA +:10AB70004D9D21CDDDA45463DABB6BC111D49F156B +:10AB8000A92E6ADF777B8A8AF661AFCEFECFAF2728 +:10AB9000FDAED7FB596BBE1DDE9905F57F2FA5F6DF +:10ABA000CC12A0EF7D5D3FCDE3FBBE1AEA6777DDF7 +:10ABB000848F6F67380FB02C10EE422BF92570BAD6 +:10ABC00016C89FDF95B601FD177B4CBE0DA48F669E +:10ABD00072FBE3BCD7F704F24D19D4F741BE2CD772 +:10ABE00017751D9497FDB9BB1B3884757DFA8602D5 +:10ABF000C4C7825D8F8EEA0CF5CE0F666E05402FBE +:10AC0000DA7D7114B6635DC156C67E765577BC0D8C +:10AC1000DAFD366B787FE413AF5A4BE3B0723ECE69 +:10AC2000E3428FB1861CF20B904A817ABF85CFF840 +:10AC30003DB62EE600F76D71FA94D72D4941FF4AD3 +:10AC40003FCDEE56711DA4F8122B1C41BD08FAEC45 +:10AC500077B87E12ADA25FE78464EF55E833ABD0DE +:10AC60004FB2BFC7ADCC1716CBED6005F5AD95EB78 +:10AC7000E1CD202F905FA51E867137A6F2F664FF06 +:10AC80002681D2CD0538931EB7F949D75FE1F84642 +:10AC9000BF99B443A6C455EF6B40FF4E84B603C7BB +:10ACA000917E326676BBD0CE5916E1793195ECA80B +:10ACB000A6649C03E8C997B1DE0215ECAAB410BBE8 +:10ACC000CA7E657AF2C508CFABD8FE4AEB1BE5E831 +:10ACD000A2EF4D2C17F860D1A336DA77560BFF415F +:10ACE000B5F06755470EB0E3FA67874DA56F82FE52 +:10ACF0001CC27B68E97751641EC9876AC6DAC4DB67 +:10AD00007E58D71AC89100E8010DD6F7D04B4D2ACE +:10AD1000E7FBFA43D1FD507E324FA40BF7F526A690 +:10AD200085E847633F40B76338CF612C8269217A59 +:10AD3000D0C362ACB87E9923F6DF9AFF60413F39F9 +:10AD40008FC1C27F37B8F9B30894838BBECF237904 +:10AD5000D8DEFCF689F9FD17CE0F526F4FEF39841C +:10AD600073C8774E33CE7388795C32DA2D007F3327 +:10AD70007E1FFA9D490FFF4FE1BAFC95CEE36E8529 +:10AD8000F94CB83EBFB5FA717DD6017FE37AAE9B30 +:10AD90009FE54739B007D603FAF17DE3AD64B7D636 +:10ADA00009BF685D0727F98B5EB7F0BC6FAA681F03 +:10ADB000C6482FD44DED4CED3BDB2ADECDC6FEABB5 +:10ADC00023487ED659FC2B53B1FF5FC7B97D402F76 +:10ADD000D5FEECFA137D61FFE037F92CC82F96C041 +:10ADE000ED2AF6F7AD95E1786B620249E5507FCD2B +:10ADF000FCCE54FF33308DD01F37C8649A31CE81DA +:10AE0000E59EC458C8EFF9A74A7A604D2EE41D2488 +:10AE1000C7C9BFB7669C27313C1ED38E26824765C3 +:10AE200015F43D85B7FBDCC2EBDD26E8774CD00797 +:10AE3000D639C9016D6C8419F9F8DAB49959696485 +:10AE4000C778121580E7C9D93D18CAD1DB8A6F4C83 +:10AE500021BE117ECE298206B23F26FCA493F8675C +:10AE60003675CEE630A4E7A4A230F2837E56B43421 +:10AE7000D205ED2769C2FF3951EF17BD36CD43E347 +:10AE800096D566A69D08E1EB9936901BD0FF43E16D +:10AE90005ADF34E4C7BDB954BE178C959F615D7D00 +:10AEA00039BBC70EF253CC96FBC2C02CA4EBFE26D6 +:10AEB0003BC3FD467BFC508D74807EBB215DE2046C +:10AEC000BF22FDA784F37D8B19F805F2D5B599B49F +:10AED0006F79C6C23C0AD26BB78DE85F30DEEE21D7 +:10AEE0007FE294F00D36289F21E459F59470FA5EC4 +:10AEF000BD2FD26F52683F4479DF4E0BB52BB5FAA8 +:10AF0000B76D817E4AF76792BED96315E3BE16C15D +:10AF1000CBA33C29CBFB617927E283D72DAE682AEE +:10AF20007F5B65541E1E488F013CC6856913111F47 +:10AF30009D6D406707F6CBBF1F17FC751CBA45FA1D +:10AF4000F92A22A95F5AFA90D7AABB6E447A6A56A8 +:10AF50005ECE7EA952F971A727710EE48F57241196 +:10AF60005CD26F74DC6B25BE3F5EAA90FDF3A74AEE +:10AF700035600DF5DB8FDF7A7F3AB4FB6ABF85FC65 +:10AF800072D31E2E398ADFA72D2D23FFE2B4E2C52E +:10AF9000742EF0CDE2AF06AC85F9342CFD22590BAE +:10AFA000F1334F2B855621EBF937699E32E4832725 +:10AFB000D3B40A9C5F7956C35CB497BFB1D63F8DBA +:10AFC000F67F7ABCB608BF5F78F5E4166E4737A502 +:10AFD000A39E5860E67C22F56DB9E0C35EDDB57BCB +:10AFE000B13EE06D3AEA9588AC7A2EFF165F99FC87 +:10AFF0003F53B7798F02E39484D72DA054F5E760CF +:10B000003F67954094924678D4705D9D7306A21078 +:10B01000FF9A89DB6D255BF5F3C27F789E55827FB1 +:10B0200040BB925AD51386EB80F9AD087F09B30671 +:10B03000EBA704E905FD10BD98E34FD37F05742805 +:10B04000DE969987FB859298BD0F0DA27AD04EAE01 +:10B0500017B5755ECEA7353C7C7EE7C43A38075FEE +:10B060002CC82FDB6D72DF4EE37FF36A271ABFA374 +:10B070005827DF28825FB78571BE72C3BC10CE1718 +:10B08000395F3D26E5E436DE4F499CCF8472A9A4A2 +:10B09000CA497C25E512C042EBEBEC8E246A27E519 +:10B0A00018F33246F577246EE4F69BD8BF22C050E1 +:10B0B000BFF8F77C1CCCA33C3FF37C921C97EC6759 +:10B0C000A33E36CE7B7F9A89EC2DD0D39DFED5FE54 +:10B0D0002F2361D6FAD97D43E613691572C19D30DD +:10B0E0002E1BCF0BACBA7EBF89B4CEF038F0DC405B +:10B0F000FF5DF6F74E1ADF1F7633D0B9B3DA74C0AE +:10B1000086EBF059467AC308C787A2DDF3CFB7D0E4 +:10B110005515FE71E692FCE4E2F63CD1EF9855D26B +:10B12000EFAE2490C72588ABD4201EF7E46A49A867 +:10B1300037BE11E73D7B62209F85F614A78BCC4B71 +:10B140007A18F972E9B1B94978BEF4CF34EEB73361 +:10B15000E27B09E015CBAB2DB05FC9C27DEB914717 +:10B160004EF408CEE7EB2A8F6776487EEEDA5C3B3A +:10B17000AEC779EB72ED3343E851BDB5EF1117E07F +:10B18000FDDC56B31BC57BB5D9FF10DAE9D55BD51D +:10B190005AE42328B723BECF390EBE8FF5E6AE8B17 +:10B1A000C9433B5CB69FB776A46776081D7A6FD516 +:10B1B000D325BB569FEFB3579FB7776734BFAB6DAF +:10B1C000971BD0E7FB1ED1E75913506F00DA039CA1 +:10B1D0006EAF0C741F7101DDBAF955377EEAE618BF +:10B1E0003F610CDA11EB54770F28EFB6D87B33DAD6 +:10B1F00015A7D6CD7123D98B54DF825F014D8BBE4D +:10B20000187504F5EA5956FBE918A0CBDCBAD556F7 +:10B21000B30BE7ADE7F73D26C1BFCF737FDC7CBF43 +:10B22000BEBCB55C5822FD1819A1FC65E40318F7F3 +:10B23000560F00545AF9F12328178A4603E3A31E38 +:10B24000AF5D6D45FBEFF2E3F8B87DE9F0B8101F94 +:10B25000850379D9759523D857B0EED8AA0F472121 +:10B26000DC85BF55C8FE287CB9E761E4AFC69D53B5 +:10B270006FA2F4D6029ABFF4FBCDAB530291907744 +:10B280000E74ED6D807673FCDC7F3173992D280F81 +:10B29000199E7B19E05813520EF0CFDB7BE0473C40 +:10B2A000172E5AA76F371FE434EA9FE24D3FDB4267 +:10B2B000BFCBFDE875751B549CF71C01BFD49FCC18 +:10B2C0003794CE1DAEE34DD809FC3FD03BBFEEA86E +:10B2D0008DEEDE3FA847AF5BC3DB83D82DC47997E3 +:10B2E00039AC2E9C77999D0522009E2391560FC65E +:10B2F000955C5C1B497EB7B936B057F3286518B723 +:10B30000008298CEBFBEFE4025BBA72C8ED3BDECDD +:10B310001985F66965E82CC5FCB33C3F9F05683E7E +:10B32000C82F9ED079FAF57956C3F777A5E6C00104 +:10B33000C44B316BE0FB33A0A727E4FCBA14E6F959 +:10B34000592CDA6F86F6CCADD1B99C83DB63E57BF3 +:10B350007FB68596CB7DA6DC074B7FF033E9DE70A8 +:10B360001CC722ECE635F77BD211DEE5164F3AE238 +:10B37000C1B73A8CF6FBB76DE0FA6B4D0CD8B1F162 +:10B38000643F933D7E9BC2ED733695CBC341A69738 +:10B3900002A86F9A1E8D716F74517DD2636B1ECCA3 +:10B3A000E4F6FF3F55B2879A56F3388835B91C7FCB +:10B3B0006B1ECCE6F6BFD47B1D18F5D7DADEF6A4FB +:10B3C000A31F823DC2E1FA1CA714625FE776D21E7A +:10B3D000E81E323F6997B3A22B3B9FD82CE2329AEA +:10B3E0005687F9F17CE284E27DD31462DF3ED59D7D +:10B3F000EB8901C33D5B443D3AC7986D1AF7C0F530 +:10B4000000D7ECC74C2EF4A7B5E0DBE34947FD7944 +:10B410006275581EF2D980E1DCBF743C97CBFD8881 +:10B420007E8CE29B36897E377537E9D28470E03FA7 +:10B43000E8E7C448EEDF8EECE725BFDE661797FB32 +:10B44000C679D48A7E665BBDEF0C69031E891796A8 +:10B45000CFED8E13772A1B395C406FC80FF85D184B +:10B46000F9034F08BD24F10B7C43710C526EC5B437 +:10B47000F08B7F5B18F0CB6A0BE703B96F0BE1171A +:10B4800041FFAE44DFDB047DD98361825F4CEC6F0A +:10B4900088C7914ECE0F57B9FF027A1F417A1BF72A +:10B4A0006192DECCECEFFFAFCE51CA5E79618F0FB7 +:10B4B000EC8CE2171F8D6250EFB4B9A6A31BDA978C +:10B4C0006E5E1EE581F494D917E584F14FFBD50239 +:10B4D0007F1BF8B6F690FE688F430939F73CF3FC02 +:10B4E0006FC7E23CFFBAD9E2449150BED546FBB1EA +:10B4F00005BBE693BD0EF9469EBFEF5B3C072DDF13 +:10B50000ABF7B7173FF7684717E1DB97644AC034DA +:10B5100090C4205DB0C9D2722E0CC380FDDDB40290 +:10B52000E133B647382E01BDCB6BD5426B74EBF2DD +:10B5300072215FCA77FDF65BF41B96EFBAF124CA5D +:10B54000FB72839FBF489C7718FDFC7FEDAE3F47A1 +:10B5500006FC50DC800FE0EA41ECC2FDC4D5DB1EE6 +:10B56000CF6944FB61D3BB514A56D0DF2FCF419AFC +:10B570006B673D83FED3F6D6E537C2DF1BA41B976E +:10B580005FAEBD0A0F9AABE369A925103508F77BBA +:10B590001B2C64FF96BEF0EC962791CF8ED948BF46 +:10B5A00097BCF0C6A7D7A1FDBCD3123F9A4FC3A149 +:10B5B00084C4D994BBB83F4ED2A7F8E537ACAE6C83 +:10B5C000FE7D716C904E253B0F5831DEC788CF1140 +:10B5D000B507AC0D8E36E855DB388AFC50DB7EB003 +:10B5E000E2FA38BD5F619D525AB72FDAF04614DA9D +:10B5F000678827D44F926E2D7434D487FEC7BED689 +:10B600008FEA39719F72393A7E2AECACB2572259CF +:10B610000CC051F4B9CD3F1AE9BB635114CEE7A475 +:10B62000B982F3FDFAE51DD1DE2BB2F83A3A29E5ED +:10B63000DF8B9EBE9BF8719E52D1D19945FC9E68CE +:10B64000225BC29788F39CB36E12CD732ED3881FF2 +:10B650008BD6AB5E3FA4DF9B59C1CE36D6CD52B15F +:10B660006E4E6E04E2C23C4F8A782BDF47AAD84761 +:10B67000DF49FAFC6E3167C61652FE7B61CF4DEC96 +:10B68000D1729E6D0FDD87966FBAAF1EE974A6ABBF +:10B69000A713C20978F009BC293F43BFEA87233BBF +:10B6A000713A3117C623503BD0AB23F03BD6AFB72E +:10B6B00078D0CF1ED24EEC13F9F87789F101EE70F5 +:10B6C000DC079FECD8763CD7CE16B9C0EA43E3B985 +:10B6D000DA95039BEE27FEFAEE132E6716F8C715D0 +:10B6E0005079BD25D009CBFD07262A24276C2CD004 +:10B6F000D63ADF6411EB5C5F0E709A9550FCEEE772 +:10B70000F6A9E497B960970542EC8420FF5883DFDF +:10B7100069FEBF13F86EA0F33979AE374FC807E35F +:10B72000FC8DF262718FB6E34ED8BAB6CF938272B7 +:10B73000C247E396827E477BA4F4988DEC88D217AB +:10B740002C5EC4D3D9ED873EBD0DF7B7B5725DEB66 +:10B75000E5B0715D17BDD4BFCD757D76556EDBEB61 +:10B760001ABEB7B9AE572924EFFEBB7218341FF9C1 +:10B77000252EB77EE7B523879F33E0F57B96153DF1 +:10B78000080B9D85DD884E06FC4ABC1AE5EA1014BC +:10B79000921D5ACB5586211A21F8947894FCCA98A8 +:10B7A00046E3B4F0B5E45BC9D72D7C6B9CB71E9F14 +:10B7B000C6F2F9487B80C7FBAA85EC85D23A1E6F9A +:10B7C00008ED283EAE1CFDF354BBE6CDA4F8D0BC7A +:10B7D000DF90AF35D4F718F25E437DCD90AFD0D572 +:10B7E0002FDD7BC8CAF70F015D3D5BE5CDB41F6956 +:10B7F0006D67F8F9B9D3AE6FAD3EE48F2E4D569418 +:10B800009396A5CC1709ED9BF6A964F75C703545B6 +:10B81000A1DDB23C8CDB75179C221FC3F34D1DAC20 +:10B820002B504ECAEF4D61DC0F73C1DB141513B200 +:10B830009F6FAC53A3D0FFDBE067056DC7AB54131C +:10B840005E1B587BE5DCBEBB10CEFD0D17C2B9BF39 +:10B8500061A4EA48AE443F6C0D8F0B9CBD6472142A +:10B86000C555D4A5DD3205BECF795BE561E03E8FDD +:10B8700019E319667152B253CC47F181B3EA785C8F +:10B88000C3EC557A3ACF756CA2F8B7EFD9624AE7A4 +:10B89000AED1C72314B355C46745EB0CDFEB6EA6DE +:10B8A00075526C58279AF00F1BD789235DC43DE66B +:10B8B000B25C5DDCA390E723D5AC5BA6003D2E1CFB +:10B8C00051990DF2CD752A5BD18FC7B9E2F9136E8C +:10B8D0004870FD2D80F58A7693C4D7395C473DDBEF +:10B8E000B75FCEEDFEF3805F21DFECF92207CF8555 +:10B8F000CFED3996FE3AE65FF963F217AC75FD11AC +:10B90000FB7F9C8E72FAC27E1B437EBFB0FFAD648C +:10B91000F4475E78CD46FBEC0B4B6DDCCFBD3FD2E0 +:10B920008F2AE642576E1757EFFB21A781F4F232B8 +:10B93000A2DF35E9566E5FD5FDFD38FAD39BEB608B +:10B940005628F7F747D07A2A7F2D8CFCCC17F6FDC6 +:10B950003020D43FF7DF9D8F3C4FBF10C9A6BC8479 +:10B960007C1CC3F705E5AF5FFB2C9E2F97ED3A607B +:10B970009D05E523FEEB1F3928572FBCC4EDA96FA9 +:10B980002C0D4FA38F73F896A8472C89E8E783CE38 +:10B990003A33F6C596B1137C596DE185E3E102E0D7 +:10B9A00001E7057829427DD01E3EA6223E3AFC27BB +:10B9B000E2E3DBE95CBE5DC3F03C3A8817C5C3BF78 +:10B9C00047FAED0ACD9F7FDFFF430ECA9FCBCDF72D +:10B9D0009EFFCFE6FBE87FEC7C39BF774D77119C6B +:10B9E00046BE6FCDD7AFFC82F23B22DD04EF15AE31 +:10B9F000F7DDFFB1EBFD7F86DE1FFFC7CEF772F4E8 +:10BA00007E5BD03BD289E79917F6FD23995DC5BCD3 +:10BA10009BFF97CE5BDAF1C355F7915CA8FF2EAB85 +:10BA2000FDC49D42D6489B7648B7609C1FED9F465B +:10BA300030AEA747D84BC8FE1CD1E541B297AB59F1 +:10BA40001E9D5FF8BAA874AE4341208087B712727A +:10BA5000E95E153307BA2C82FCF0A4328AFF32EE7D +:10BA60002B47848F2940FBF4D012800BFA391469DC +:10BA700072E219757E177E4F09D2464CDF4CBE9993 +:10BA8000E2F8F31DFAFDD5CD867DD28D2E7D7901AC +:10BA90007B291ECFED0AB22C745F6214D60FD957E2 +:10BAA000FE23DD4978B991D52C733AAE1E4FB70805 +:10BAB0003CB5C6C3BFC65B2B3C897DB459D437E2C5 +:10BAC000CDEC78A01EDB9919EC8BF97C693F2DF742 +:10BAD000C597C32713FB6DB3185AE2D7DC859FCFF8 +:10BAE00086F44B789178BF5A7C4B3A19F12EF12BA2 +:10BAF000F166A4432AC6F8F50FE2BF8B39D78CEB69 +:10BB00006E88B0EBF3CD313CDFA55EF5D27AF473ED +:10BB10003EFFCE6D46BB7E982386E2428DF71166CE +:10BB20000E8C19A0C07C93CCCC67837D289EBD91E0 +:10BB3000DFF57EB37F690A8EC3FDBB5DCDDC7F0D73 +:10BB4000ABDB179E47F53D56C8173E328F79A07E76 +:10BB50006112732BBC3E8B8EA5F038A6C6F27B9B80 +:10BB6000D8AE309AF75BD889F997727A125DD0ED2A +:10BB700083FE0DE8D7638AE5EDA3F2A8BDCFC4DB51 +:10BB80007BCC90764BE3710A4DCBB95FBEF0BEAE75 +:10BB9000E9283F460FD7FB99DFEAC9FDD232ED9B7A +:10BBA000E1227CA9267702DD8F589649FB2335DCFC +:10BBB0005BB61BFDF43B789C4EE18A3BC6F447F82C +:10BBC00076C4B911BC3363770EE0F5A7DEFD07F844 +:10BBD000AE6D0DA3EF9333B4A53D311E40714DDF23 +:10BBE0000D1F664E3A644D8021B4DA71E7D14F38AB +:10BBF000D6B7F37D3C9F1C3B51A5FA63198FF764C0 +:10BC0000CB601C281FE3FBD69C00FD8D814D079661 +:10BC100037863993EF04F80B857FF8215C2F086F86 +:10BC200038D35E72205C5DD353E1FB18D676BCF14D +:10BC300051597FB8B20ECF99BA8DE0FE7B591FFBE8 +:10BC4000C17E3FEAC9FD514F8854E601AF547FF6EB +:10BC50004A5B631AEE7F565A023D2175F41ABEBE46 +:10BC600027E06F742A1BB516F17EAFCA3612BC4DA1 +:10BC70008574AE1099E1423A68C0D274BE5293E224 +:10BC800042BF58E3B0DA009E27343E91E2AE76110F +:10BC900095291E48EEB71A8705BAA31FBF29979F9B +:10BCA0004B1C773644E27E7196C3CEEF498AB8A228 +:10BCB00039E25E4CB7EA8607AFC17DE8A32A9DD77B +:10BCC000CC7994DFF7FA8BC3EE5770DFB646DCD73A +:10BCD0005CA58F23624E37F98166D50CB3E27E7383 +:10BCE000B6C363C579FE31437B1DE725EF17F642E6 +:10BCF00022409785358514AFA246C1BAC3756276D6 +:10BD000045E13ED81887542EE28E64FEA170ED30D6 +:10BD1000F2C3CC68D70EE4972F2BD3C83FAA0ABE34 +:10BD20001B8D7195789E616E484478EEEEE922BED7 +:10BD30001C1DEB4C77103F8731C443A3C5998EFC83 +:10BD4000DDB83CCC84E772A39772BE867566374334 +:10BD5000FBFBCD2C1CCF197E27DA4F5B62F66E8081 +:10BD60007C173B3347C6225FE5125FDFD24B7B0275 +:10BD7000E777EAD76C20F2C3AC55ABE93C46F20555 +:10BD800033D7E7C7C138A736A7E4A1DC6C91D3BD90 +:10BD9000867F81ED5AF861A2427C00E98134E28716 +:10BDA000F10D38CFD1C303DD1766E17EB49479502D +:10BDB000BF273037DA09CDAC89CE2B9B1D5617FA39 +:10BDC000BFA43C917203E8EAC17BB7920FB680BE74 +:10BDD000375B18DB5A65A7F4F92A2733F7606C7BC9 +:10BDE0005502E57754B928ADADCAA0EF2F55B92952 +:10BDF000BFAB6A20E5F7547928BFB7AA80D2D7AA8B +:10BE0000BCF45DCA25C00BC9212957A43C9AE5B0F2 +:10BE1000D27D5F29978C7C331DD03B348FDA93DC45 +:10BE200093F20EE761CA0BCA2349DF54C5EB4B48B6 +:10BE30004139D63015E93F523DF7C22BB82F2F724A +:10BE4000B8699FCEB8DC6B067E45BC245BD95EF436 +:10BE5000CB56DFE969BC2F2588FFDB8B14660EE12A +:10BE6000AB3B2AC29839446FCCA88CD1E5A7557E4C +:10BE7000FC4627E8FF9E0E5A7C06C071FC375FAF78 +:10BE8000FF237C7FE637677A20BD018ECD8FE3B834 +:10BE90008BC35BE088C5FC320B9D737513FE936EFC +:10BEA000C27F82FF903EF27EF333BFF91BADF3C633 +:10BEB0004A9B0BEDE2CF915E80DF3F097ACDACB4B7 +:10BEC000111E0B977FF5C22BB8DE175B49DECD5CE8 +:10BED00026D6A3E15EF397898CFC126055B34AC065 +:10BEE000DF97BFB60622A0FF2F15BE8E15300EA617 +:10BEF00061FCE1CAB73E4339A0541EA1F3770DEFB0 +:10BF0000E1217C3ECB39DD3DE9CA37A91E6BE81241 +:10BF1000837E1379CF38A29FC7EA82F9236F23FD6E +:10BF200066661C648978CE52A338D185385B7C9FC5 +:10BF3000BD92BFDB80713C13C1FE1B92A1123D2B51 +:10BF40007B9A29FD14F52DF9936B484F49BE9DBD91 +:10BF50000ADAE1FAA8C9B5CE0D91C733C5F7591968 +:10BF6000264AE5F731D82F9EFFADCC9D82764567F6 +:10BF70002CCFC2346F0AE2B7B363945909E1831B33 +:10BF800032CC020E46ED3EC54507E90319A9D63964 +:10BF90005974BF8FF4981C676646DE0A8C2F9DB9D2 +:10BFA0006A184A61566D7127C4433D6F4B3FDC7E72 +:10BFB00063761E475DDA8E1E917EB553F8E7B53481 +:10BFC0006FF2FB16EFF8FD8ED7A0E7E22F6C44DF8F +:10BFD000E23E226E2BCB3F60023920F5FEECFCDF07 +:10BFE000FF398ACE2976F1F84E48B99F757111F75D +:10BFF000CBBA617DB5715E7478C717516DFAB177B0 +:10C00000A957E4C72E577E8A423B42CE67E4BEEF73 +:10C010003B121CCA253A272ADFB7BC635B715E4618 +:10C020003F768BBF5BF8F5CA1717B4E9EF36FAEF26 +:10C03000966518CE0FCC8CEE8D49FF1D53B3A2F13F +:10C040001CE07B719FA4BD7D8EF47F97AF854EE28F +:10C0500060BD9A5DD178BE75A11DFBFA6806D7FF59 +:10C06000E785BFFCC27695F63D17B647D2BA5AB0FF +:10C07000FD9137F1DC71C12685C02863F5843FC08E +:10C080002BB387EA358C638B6B0D77B3BF4734EAEC +:10C090009592DF475620BFCDAF553C9B019E66BBB6 +:10C0A0002BBA43083C5B91DF807F4A6CB50308DF05 +:10C0B00002FEA7514EF60FD69B5FF708F997A1DE57 +:10C0C000376417BD1881B10288F7F711CEB3EBFAC8 +:10C0D000BAF1BC707EEDCE0564576C8F70A25FE143 +:10C0E0008C885B96FDEC12FCBD2B83DB3167C5F9B8 +:10C0F000D1D91DFC5E3FC289EBEC8CC2FDD0B2DD14 +:10C100006B02CED732F8BEE48E0CBECE65FDF9B51B +:10C110008D51DDA1FEC9BD1F537A58D49FEFA8CF22 +:10C12000417D7C7257049D7F9DDCF5D4A8D761BC0E +:10C13000F3B5C3E2715DC8FE3FCAB050FDF3EBD466 +:10C1400002C417F3F3B89932C46FDF5038E336F8FE +:10C150005242D71F8F1F3ABBEBE5285356909E657E +:10C16000F60A7BA209D7D19D5EE4EF68641E80D7F2 +:10C17000BA6B9C0F7558795D2E43BEA6F59748F5AE +:10C18000579A42EAD92C6E8A33B5EC2DF48837548D +:10C19000F83D2711C73F52CDA273C5E97D5C936F6F +:10C1A0004739F9AE85E8B130D33519E5D3C57A956D +:10C1B000219C0B535800ED9345F7466E403D26E118 +:10C1C0009EDE97CB83D2950AF3C0FC4AFD2AD3208A +:10C1D000ED0CF4F7213F2534F4C738C9C6146E5767 +:10C1E000C8F8D1278B4C1E2BE8C19F3262E5FB0FAC +:10C1F0004FCCC1F3B3F119B49F3B6E653E15FD4AB8 +:10C200002FF1F8D2D2541ED7FCA488872F8D0DA40D +:10C21000C7417FE7047D4BC707D231EEA2F4A544A6 +:10C220008ABB3867E5E79EF81DCF594BF3A0BD8365 +:10C23000DECDD064FB98107E2A9DE976613D35D62F +:10C24000EDCA7520BCCE6FC8CEDD1DC9D0CE35BDC0 +:10C2500012C9E3A69E0BDB680BA19B3393F39F7C73 +:10C260008F83DDC6E38C1EB3F0B8D4C73627FAFD42 +:10C2700021F87ACCA24D453CE03CD0BE9F6FAD4941 +:10C2800047FB57C23B3FAA86E03C27F87D7E780DEE +:10C290008FE716F77BB13EE61B451C7AD3361BC5EC +:10C2A000019D49ACDF83E39FD996892FF200FCFE04 +:10C2B000B97BA91CEC4BA067F1F3B600CEE7F436CE +:10C2C000EE8F3E6DE1F6DAE971092EA46FC1F8B583 +:10C2D000D3C95FB3C9A6A09FEFB4C2AC0958BEB919 +:10C2E00003C59F17575552FC7631880DBC3F046932 +:10C2F00001DE033ABD3993E2CD4EE33B0C0A7D5F8C +:10C3000089DF355633FD97888FAD7C7F75E6F9BFA1 +:10C310006786C67BCBB478933EBE4EF2892CCFCDD8 +:10C32000E4F22D57E0B97F267F2FA42CA2F6B1545A +:10C330009A27C73BD089BF5BC31A229FEA87F114B3 +:10C340003D1494234FB240FA53E877D8CAF75F6799 +:10C35000B65B286EBDF895480FC5B1DD778D89E2D3 +:10C3600029546EA7179B007D902ABFD94AF165F129 +:10C37000CF87E5D9C83E67B4CF6DDAAC8A71C026E5 +:10C38000C6796FE171C7A3D196A4F26C2A3F2DF252 +:10C39000A7F76493DD07FD7BF07E55F12F7FC5F194 +:10C3A00038A1E828B7BBEC246F4B5BCE790647A3D6 +:10C3B0001E2CBB6F5034DE3F641FA80CED16239E6D +:10C3C0002E9ADD9D50CE2ECB147277CF7A3A9F2ACB +:10C3D00011F7084A9E57F83934AC43BC9F59B262F2 +:10C3E000D0E3C49FEF5B580F98CFB9DA47A242E978 +:10C3F000B12093CBD396FA5637D52F81FAD84FC9AF +:10C400008A77A3089E2D168A5731D2F18ADB3FAF77 +:10C410005E51FB16FEA8E57E9656F367F5BFF8025F +:10C42000FAFF6E7B98DB475F6BE91EDC594BED5CD6 +:10C430009CFFD917C2486E9D8DE1F2E124C8535F7D +:10C440004F84E3E68729BEEBA309747F6F9E5FDF0D +:10C45000AF1C77512697E36571EE688C172CFB8033 +:10C46000CB41A0CB2DD4FE030BB537CE63BC68D730 +:10C47000B23E5F88207E38DB99D3E5EC8E9EA49F88 +:10C480001A63389F03BCC978DFEFEC0B3D73E91EDC +:10C490001D1A3DC00FC562FF7B36A636D91952DE84 +:10C4A0006811FBB800D444BEC13620DF8B2BB9BD68 +:10C4B00055625F45F12518AF3B208FD2802DB675B0 +:10C4C000DC2DF02BED2FDFC9147E4C1CAFA388139D +:10C4D000273BA8D68A725B13F662E97663DC2E2FBF +:10C4E000DF26DB03B4F1324E18F9D0A7509C4AC9BD +:10C4F000B23BE753FC7DC5EADB719D49F84BCCAC00 +:10C5000000F7698D8A4A703486B119E3D1AE0C1DEB +:10C5100027C49EDB151C87E1FB5FA5F807ACD9BDDE +:10C52000992EFA8EF91AE8AF7499B28AC64991FB2E +:10C530005D3E2F8927408715E3041B8789F276E645 +:10C540002DE134CEBBC5EECAE4FEA5C614D7C38325 +:10C5500091CEEFA9749FF7E24F7DA363DBB0D38246 +:10C560007ADE1A8C9705F88F6532EA677D26B7D395 +:10C570004B301E17E04C5FA78F17CFD8A4CFF7DA48 +:10C58000AECF67EDD2E773EAF479F7617DFE8018EC +:10C5900017F7E1787F18F7E198E23EDC65E3FB707E +:10C5A000CCE33E1C53DC87E377DC87631EF7E1981E +:10C5B000C77D38E625BE713F8E79DC8F6379782F91 +:10C5C0008EA752116F8974407E67AF86E9EE235DB6 +:10C5D000D8C7EF97001FF07533D54AEBE649AC4159 +:10C5E000FB11EE77EA3CC1EEC2F8E15571DA7799BA +:10C5F000FDF11E4AFD8A44A49BB981E258CB5FE35A +:10C6000071ACA579610EF47F342C3FB902C343B5F8 +:10C6100038ED47AC7FC1D2B405F15B567988EEDFC7 +:10C62000372C717D703DA71FF96158512CD9518568 +:10C63000A8E762DBA7A3319E9CADD2C78F1BE3C9DD +:10C640008D71E4463E90F6DF3396A64494EB5F6D21 +:10C65000B3AF42F8BF0A13F761A6D80DF1000E92EE +:10C66000270B1F5436A2BEEEDC8BDB51CD47C05EDC +:10C670006F43CFCA74D6A5BE6497B7E45729268AFC +:10C680004FD73CA4871609989295A6C6FB50CECDED +:10C690003791DEBC08F61AD9839FA8643FE03B5966 +:10C6A000A1F3C177B242F90BDFC9D2DF97E8ACAB97 +:10C6B0008FEF64E9EF4BF4D2C7E74F5C7200F7FDF0 +:10C6C0001356F5D5D59BED1D64C0A3805BD8B3B3DD +:10C6D000417F78D0BE5CBC3619E9BB687E73E37DD0 +:10C6E00040DF45BBC3DC585E84FF0772B108FAC463 +:10C6F0007B9745BBC4FDE54ABD1E9E25F45091992C +:10C70000F99CB1413E2C72324F0CB49FDFAB3E0717 +:10C71000DFC39AFFF6C7039CA9B8CF18D609E55125 +:10C72000B2C54371B5A53B7BC42C817E7BF7D06E2F +:10C73000EC05EBFA44CDA187A6A13EDCC9F77F5FEB +:10C74000AD7A398AE2CB04BF255B9CE148F70D3511 +:10C750003CBE0EFD676A6C902F36D4C48577770493 +:10C76000E71BE4839F884E401FEEE7293A48E72203 +:10C77000CDB562BEC3141FDAD9727EF21D2DB68C00 +:10C78000F77397C89F10FB0D39CF739907725C78C8 +:10C79000AFA36A6FB28AF2DCB47D0BEE43FE69D3BD +:10C7A00066F7EA8FF1A03DFE88EFAA15FF81CFE77B +:10C7B0002F6B46445D8BF6E70B16F768C8DF57F31F +:10C7C000AC15F715C566BF95E233B76DB062BCF224 +:10C7D0000D5B37D0F7B95B0B291E731EABA0FDE8CC +:10C7E00029F9EE81C047D170659D13E07E47C88F5F +:10C7F000A2707EBE07F6D11BF8EEC8C5AD4A2EC6A4 +:10C80000F94CF4EEB416C2F75F8B7AC675D27C741D +:10C81000C2C80E840F7E0FE40F0C76F769ADD7C542 +:10C82000844B29B42E265EEA4DFBB449814CBE1FD1 +:10C83000CE32EC878FAADC9F57C7D7419135103F86 +:10C8400001D7C97E0BD9B96566FE6E5319FC7D1DF3 +:10C85000A4DEC1AA8E5FCBF32374FC3C85C5EAEE4F +:10C86000D3DC8A412521F989A3D374F5274FEC6DD8 +:10C87000E0FFBC6039C991EB74F7FECA16FB5CF4AB +:10C88000BE211BAEFFCE787C21BD086A0FFD3E3E67 +:10C89000580FF97B93C2F73DBB6236A21FB0C8C4E4 +:10C8A000F74F5334FE7DC15EFE9D4D61BA75D82DA4 +:10C8B000CDFD47AE172D746E20FDED53F0EF36F031 +:10C8C0000F9AA2E51E3BDEE347FF84EE7EB7382FCA +:10C8D00044B8910E65C29F5496C1FD4965BE7A2B3E +:10C8E000BE9300F837C7C5523D7B1CC655D628E419 +:10C8F0006FC47431C559EAE3B4B03F8C7F5C7044B7 +:10C900002DC475622C2FC2778790BEAFF1B8D405C5 +:10C91000E8178A6AFDDED902F413A17FCBF0BE9935 +:10C92000A3B74BF811FD2B3A231E472BB9746F7335 +:10C93000FB012BC6E74D9C18938BEBC7C86752BE13 +:10C94000C3BAA6B8C2E6A38788CF9A8BCCC4C797D0 +:10C95000C3C7020FF7B31AF96F2EABB7E2FD94B954 +:10C96000BB1437EE4BB11EE2A533F2A5012F71B116 +:10C97000ADF121F1D4823743F93CC6F1356FAFE216 +:10C9800047F9D80A4F027F46F8DBC39F9CD75C4D1E +:10C990001B857242CE6F1ECE03C78179E038F2DC70 +:10C9A000820D34AED734F25F2DF0F2385B237F8CEA +:10C9B000BFC4FD32B75E32533A71B47E7D623B5CD8 +:10C9C00027932E75A4F2ABE59F050027EA85ABE51A +:10C9D0001B391F298F83EB84DF4BB8DCBB4546FF37 +:10C9E00064426FE19FECCFFAEBE29B85BC35B63732 +:10C9F000C6374BFBC0A8770A234D146FD9EC4825E6 +:10CA0000BB43CA5F4DE8156DF9F7544F837A1C1A82 +:10CA10008F4E0F69C24FB8303295DE91485E12D703 +:10CA200011E95518E6A4B8FEC2252AC55117423DA2 +:10CA30005788DDB262595A32EA912FEFEFF9B40FFD +:10CA4000ECF92FEF8DEF3810C6F96AB925DEEE0A42 +:10CA5000D6FB72F9C8648CEFF86AB56D8ABF0D7C9D +:10CA60000DEFCDFD0A65BFF98CF4DC79D3D1A8298F +:10CA7000D0BE74F9EE28BC3E50B29CEBF7F7BA6B0F +:10CA8000C37AD3B9EF862DF49EB173430EFA89BDF4 +:10CA90001CA72D7645F1F2919DD0EE28FDE7A1A7C8 +:10CAA0009D782F7C89A523DAA5A73F013DA9909EFB +:10CAB000237BE254187441E77091F49ED92985795B +:10CAC000F03CEA9CE9C05FEFC3FD626E6D7A40C145 +:10CAD000C353CDDB1BF7F7CB9F257BA6F88125E958 +:10CAE000F8AEA0B6A447745BFE14996E11FA1CED63 +:10CAF0007A4CD1AEC7F81AB4EB318F763DA668D721 +:10CB0000E3F7F2B57ABB706A4F2EB7A4DFB95B7555 +:10CB1000532E9EFBF986B38C0AD2C30E7A07789106 +:10CB200012EE46F9B4086D28CCFF3982FC0EEC9366 +:10CB30001B757496EF04CB7780873481AD16B24EA7 +:10CB4000AEBF6467A1F77487B1185D7E843D51570D +:10CB50007FA43345577E4342A6AEFC4657AE2E7F98 +:10CB600073C6B5BAFA63DCC374F95B06DEA8AB3FE3 +:10CB7000CE334E979F503055577F92B750573E79DE +:10CB8000CA7C5DF954ED4E5DFEF6A27B75F5EFA80B +:10CB900058A22B97EF22D7E17ECC86EFBFD82995FC +:10CBA000EF23DFA3327A5F6DF00813F733DAB83E74 +:10CBB0005AF45E0F47281F3C29F8F95296E751E4D2 +:10CBC00057F9BEA57CB7722BEAA3FE788E1950F8F0 +:10CBD0007EB83E11F9D858CF583E38E2E04517D01C +:10CBE0003266FBA94966901783AF39D8370DF253E7 +:10CBF000B7E7DC4AF941075F4E857C61D6DDB79A1D +:10CC0000415E0DEE73F022969FDDDE97974F6064D4 +:10CC10009A94657D3209E365075F9FBACACDFD2806 +:10CC20006DDE779729E203EF89233E300D001F6305 +:10CC30007A10F818D3C3C0C7B32D8CBD097C8CE91A +:10CC400011D89FE2F777607F8AE951D89F62FA3E58 +:10CC5000EC4B31AD877D29A61F554DA1F4932A8D4C +:10CC6000DA7D5A5544E9675515F4FDF3AA4A4AFF9F +:10CC700054E5A3EF877B4BFF4340F77E687BEF844F +:10CC8000CA734E79AE595DC11A22506E349863BE94 +:10CC9000B607CF2BDBF71398D9D721F65AB6E2F9AE +:10CCA000A0378DDFC54971E2E2FB1D29DA2748E78D +:10CCB0003FA44CE8D157453D56F10686DAFCC1D475 +:10CCC000F67B905B7B733BF9DD2CCF31EC6F889D5D +:10CCD000DF4F1E62E7F78F8798EBAB91BFAA7F64A7 +:10CCE0002E8CFF3910C9DFFDA8BEDFEC473FA872CC +:10CCF00089AFF3A1F18CF2D53F36D07DE5214E7797 +:10CD000002EA2B996F39F7C77F21713EF21C5EC68C +:10CD1000F7E45FAA1F81F6C25087D5857224346E6E +:10CD200000CFDB0F447E2DE161389E3CDFDFF42332 +:10CD30000B987282E7F843ECF529E837187A97DD0B +:10CD40001D1AB724CFEB954B0D2AFA55657C921C22 +:10CD500047C21B6986FEF282F147439CB5B978DE73 +:10CD6000515DE6A0FE3AC1776B1ED5F3A8D4AE366E +:10CD700017FD72434B1D14072BE3043A8979433D99 +:10CD80009A67FE258DE224868A3809ECC7CECB7DD2 +:10CD9000D8CFD0F84022C6810DADE0EF90AD57F866 +:10CDA000FBF3326E01EB4784AC5B8413FBEDFE3783 +:10CDB0008017ED288F87F03B41EEEB5C222FCF1DD3 +:10CDC000EDC3C9BF3542C89A8F53B4CE59786FC5E9 +:10CDD000E6FC7304ADEFB4AEE8371D27ECFA7FC173 +:10CDE0002FDDB0DD7F9F5F3C9CDEF8807F4A6BBE0D +:10CDF000917491746E8F8F24DD43E2CC88CE2D71B7 +:10CE000063A21F237FB5C757929F86D839DD91AEA5 +:10CE100018A726F948B9C4DF751B5A6A277D27F978 +:10CE2000C8C807ADF988F365F5DD76EAAF351F05AB +:10CE3000E98FF8F8F7F9A841C5F3ABABE59F194DB9 +:10CE40006C5434143D94AA6D45395278C9F526E6E0 +:10CE500067B161A390A564F9E358DEBF75B9F65DCB +:10CE600093253A84CF86083EDBDF4E7FB29E7CF767 +:10CE700042F67FBC9DFAEF0ABBE1DD3019A7E271F3 +:10CE8000E40E08C68D2E1AC9F9AB204525BB6344B4 +:10CE9000167FCF9C39B89DED82FF501EDFC4B4C30E +:10CEA000D129F8EEA897DE1B1D156F786F54D8E7CF +:10CEB000058673FE9BB26E20FBFCA6CBBC5BBD2C33 +:10CEC0004BDCDF49612957F9AEE86FB3687F78A57D +:10CED000EF8AF2F768F3C57A4F12FC94E652D9E074 +:10CEE000587C9F5D33A372398CEFD1E6E0BBAD3E39 +:10CEF000CADFC8FC94DECC0264478C014584F95B30 +:10CF000018A37BFB8722C64EC33B8723FA8EE88E8D +:10CF1000DF43DED9F3237C0B54EDFF3843DED93BEE +:10CF200098EFA2FBAB07ED696487E27AB584F84B12 +:10CF3000DF06FDDC1DE67708F437A66F80FEEE0EF7 +:10CF40007AF42DD0DF98BF296309C376A35CFAB8C1 +:10CF500027D9FE66E708D8A8B58FBF9B735EED8220 +:10CF6000F87D37A6673EF2C5BB31D7E4E37CDF8DA1 +:10CF7000E964E2A9CD4A69F62BDDDBB293E57A08D4 +:10CF80008E378AC633E257E2D3884789DF7F039F13 +:10CF9000EFB485CFADB88FC0FB21F68FA31252F14D +:10CFA0007C93CBD9B28864F1BEE87B396A2AC6FB90 +:10CFB0000E223887565ECBCC78DE6EE7783A59C5BC +:10CFC0007C88DFD3380574781BFC7BCC3CDC141ADE +:10CFD00007FD8A4DFB13C271729D4AF7F5CFBF144E +:10CFE000467EBB537EEE975C68D21AB3D06FAFBA61 +:10CFF00056B9D1DE7C57253F30FBE950F2F8C8AB7B +:10D00000E0D74DFC9D8352FBA836E929F797CFA5C1 +:10D010007A68FD33C3EF4B74B1F1F720E4BB94970A +:10D02000FBDD962E362EAF257DD759851D00FD0CD4 +:10D0300000399BF47038EDB7F674F4FC88F3837D07 +:10D040000CBD3FD5DC2592F4D34111173734D09B6A +:10D05000DE5B2B10BF23F096789FFDA08897FB7BAB +:10D06000BA66CE0678DF721DEC82FE87EB193F07A9 +:10D07000BAD1C1DFC3BFDAFDB9235BECCF7358CEA1 +:10D0800055FDEE410795EE530C65E9740E3F02E144 +:10D090004539F7F62C33EAC990DF3DA079FD6FFBE7 +:10D0A000DD03C69A549C579253614FA65CFDEF2056 +:10D0B000A8625F257F0FA18017B5FA1D84A7A20A79 +:10D0C000785CBE636E9BBF839024DEA9662EAE376C +:10D0D000E4EF208C4CD0EB9111CE61879D94EAFD5A +:10D0E0003C4997891F1B9D2DF4C7D5D2BF8C11FDDC +:10D0F0005BE24CE379FCD350ADD7C3E89F1F116FBF +:10D1000071FB5DADF9E03FED774EDAA393F1F74F98 +:10D110008C7432FE1E4A925A6AA67720059DA6C0DC +:10D120007F48A7EBC5EF55E4E3EF55B0FF7774AB4D +:10D1300036D0ED7BB6AA3FBE5B7AA190CBF5F6F474 +:10D14000FE0D299EFBB341FE3C2AFC47D23F22E361 +:10D15000728DBF9724FD00325ED7379CD3DB773CBE +:10D1600082CEAFEE511B2251CF1C37F1DF471AD8C8 +:10D17000417B1CE5D38CAC0A05F191C0BC3BE702B6 +:10D18000FCD3FFCB968CF9E9DDF87B912C8BFFFE6D +:10D190008F846F7A128FE77A265BE17E3F378FDFCD +:10D1A000DA98CDF701916E27C599176631113FCBFB +:10D1B00092A767237F1E0DEB89FCB786FB031BF04C +:10D1C000BDCAF8E07B9568A7A35DDC55D8A5D5C797 +:10D1D000EC76CE874CA7FF33FD765D9C73EFAD4EAA +:10D1E0005D3EBB364157BFCF5E97AE3C3790A12B1B +:10D1F000EF7BC4ADCBF7AF1FA8AB7FCD671E5DFE45 +:10D20000DA86025DFD41A7BCBA7C126B7A02F17B23 +:10D210002C3B95DF9F50849FC4C5E931FD9E8E74E1 +:10D220005F49EE3F64DCBB26F8D9B8AFE966E57626 +:10D230007D7522E3FB56BBD89F32FDFE461371EB92 +:10D24000D2AE673E7DDCBA8C576FD907897D8EDC04 +:10D250004F84C4AB7B107E19AFDE4277F17EA8917C +:10D260005FBF167437CEA39B95DFAFABBED74AF72F +:10D2700084247C46B8D40CCEDF9BED6DBF07F55DF2 +:10D2800036B713F2BB7BCF21BF3E0DE28AF0D96ADD +:10D290003C7703FE9E40F5AFADEEA5AECB8F37BD1C +:10D2A0000F9FCF347C37378BDE5FA57B81725C7339 +:10D2B0000E1FF75C1FC1E786F1A647F3F838166D1D +:10D2C000A57B2DED8FC7F19A6065CBE8DD2A71CF84 +:10D2D000E38E55B50FA20B759AB5C6C21F1EF05B43 +:10D2E000D08F367A38D889B9E85F7DF85107D86988 +:10D2F0004F579AC92F1691639FECEB1EBCB7D30D05 +:10D30000F669C827A391FED0EF923E3C3E3D0B6DDF +:10D310009F0EE47F6FB96F61D3C97F46F2BF0DBE28 +:10D32000237E94F3F89FBA7F21F9D78827B92F6716 +:10D3300042AF75177049FCC97521F127EFBFB8EEF0 +:10D34000B478373AE81E4D01C6E549FAADE9C3FDA8 +:10D350009CD3053EB01ECAA3F6EA8D54B3A2F1BC1D +:10D36000A099B9A29D97F19BFF0FDD4B21FCB777E8 +:10D370009FAE3D39D14A3EB473BFAE3DFEA47F5748 +:10D3800071CF2E444EF07829410F7F7713C525DCED +:10D3900017A95FC70FE570FCE689F504FADB91ABCE +:10D3A00097130CCF3FAA97AB424ECC6DF9FD10FC02 +:10D3B0003E67B985EC6EC6BC8F619CC65FD658E8E7 +:10D3C0009DC7A11E46F6CDCC758A7F8312FCDDAECB +:10D3D000429FE19D16F527B20FBF5FA538F1F71FF9 +:10D3E00066ADD497CF73F0DF1D99637CAF469EC7BF +:10D3F0005D665F5F9523F4BB9BB9C92E137114451D +:10D40000A28ED12E6BF6F3F346DC97ABDC8F45F1A1 +:10D410007752EFBBF0BC2BE41D16C06B7806EAF127 +:10D4200065E636E3225BF0DA4EDCC7398788FB70AD +:10D43000F03897E65D61FC7C589EC389FAE77C175B +:10D44000A91CEB636FE77379FC8A3C7F339EEF3551 +:10D450003B4C743ED5BC2B92E21CF0DC2B1AF8E15D +:10D460008C6967C7812941F8B40655776E644CB55D +:10D4700025BB693FF95E776D5B0EC6E99BDD7637AC +:10D48000E4EF771CA477BC460B3F9811DE96DFF1E2 +:10D490001BCCDFD569F6717BB7B980BF7702F291FB +:10D4A000E17A92F11CE3185877901606AE2578AE13 +:10D4B000F6FC6BC2A55C7EFE7B6910B5D7565E4B51 +:10D4C000F96ECB1EBC13EF194DAA9E67C150808622 +:10D4D00027168F0C87A60D5DFD4BC3916EC3943646 +:10D4E000CF2FDEC9E17AA5C1706F41A6D7F5E17AE9 +:10D4F0007532C6E6F40F89E75AA2D07A58A83019D7 +:10D50000DF45F25CE62FD688FC489E5FB49CE71BA3 +:10D51000C4EF2A6C11FE169C37A6386FF40B6C17FB +:10D52000FE189C37A6386FFC8EF20BF328BF308FA5 +:10D53000F20BF328BF3045F985DF67326F72AECA50 +:10D54000CFEDF243D6079EDBE587D847786E179A72 +:10D55000C773BBD0FA786E175A8EE776A1E5786E5E +:10D56000179AC773BBD0FA786E179A67036F0CE6E9 +:10D5700051DE79C6E9F213C0FECF0F59DF786E177E +:10D58000DA3F9EDBE9FAD3EED4B5BF9D55EADAE384 +:10D59000B95D68FD19958AEE5C6F86788776D6DA74 +:10D5A00038E29F7D295E5B1FA0EFFF89F8E7DD165B +:10D5B000DC2FAA75F3F9BE2DDCCDE95C53C0E96E12 +:10D5C000E2F72C94A6A944E7C5569E1FC9E3BC8D7B +:10D5D000FC83E762F9167E2E86299E8B618AE762BC +:10D5E00098E2B9587E0F7E2E86299E8BE1773C17F4 +:10D5F000C314CFC530C573314CF15C0C533C17C319 +:10D6000014CFC5B01D9E8B618AE762F81DCFC5306F +:10D61000C57331FC7E1CCFE72C41B8D09EEFAEDB4A +:10D6200057021FEAF6954E5D1EEDF9D0FA68CF87D6 +:10D6300096A33D1F5A8EF67C681EEDF9D0FA68CF8E +:10D6400087E647E5B8687DA15D1FDA0EEDFAD07C6C +:10D65000768DEF0DF49D8D59F7CD614C1B2295A76A +:10D66000151019057DFC93F1FCB2214C498E01C9BE +:10D670006959B279723EE435114799C39A4CF4FB6B +:10D680007BB879C4388700A3B8D5EC1F13A97CAA4E +:10D69000BC7F87FF80EEB9BB18FD1E8D3C5F97ED08 +:10D6A000DDCCA9622AEB07F36DD7338E2FEB91FC0B +:10D6B0000C81036F5A63BC4FEE62471EC6CD6E11DC +:10D6C000BF8FBB65298FB736F2D562612F6D31ED03 +:10D6D0003C88F7699A0A15BA779D6E66472C798857 +:10D6E000A78A3CB42366F789117AA9E23AFC1D3176 +:10D6F00009B7F483829CA0FB89839BEA4744433F9C +:10D700009A6F18FD3ECE682BB71FB01DEE2B7BFB2A +:10D7100014CFC610FE5E20EC71CDC7C77FEE99B165 +:10D72000BC5D386FF7DC335184C7B1CB148A3B1B27 +:10D73000BC9D79F01EF43D429EF6DE1E5071BCC2C7 +:10D74000657C3CD96FE1BA64BA175AC81AF2F15E27 +:10D750000BEBA73094DB126F30BFC338BF74582A6D +:10D76000E8C7BED2FB5443FAC58CC4784456C7E818 +:10D770005DD131FD3ED4CD97C83E80FA25BDD6D3CC +:10D78000A7D03BCE637D4B96225B8CF1DDF946073B +:10D79000ACBF89B9535CA48AE8FEB184A79767A798 +:10D7A00009D422CB62F5A63005E9CD0EC585F00F70 +:10D7B000ACFC8948EF5CB785DE551E67765AE89D5C +:10D7C0008E76E2752E3A64BC8EC15E30C4E5542F6D +:10D7D000FE2C19FDCD0B234DE43759B83B82EC06E6 +:10D7E0006DAD42724DDA418522DEEFE2B2373A4C3E +:10D7F00046BCEFB4507F325EA72CCD9F6CC2FB09B4 +:10D800009D37E4C4AA64073C8FF2F0ACEFE55B07F8 +:10D8100062BDE5FC5DD18BCB76F3DF1915E73BF2FA +:10D82000774B678BF8AFC26C6F34C6C3C8DF4793C2 +:10D83000F764E4EF924A3F4FE17B7DDF44FA16AE96 +:10D8400017EF7EAF2CA4FBEFC6B8AB1261FFCD5F24 +:10D8500066A1B8ADF906FBB044C4655DEEF74A0FAA +:10D86000F531D887F27772441DA676F914FDC2F21D +:10D87000DEE7340B9703D376323AAF9AB664840965 +:10D88000DFAB66BB39FF4C5BC2ED9C69AF7AE8FE4B +:10D89000A6B41B3F10F6CCF84B4984FF8F85FD32B0 +:10D8A00009E35501CFA31BC2441C5B22A5932FF1B2 +:10D8B000F8D5F10E2E0F1AF6F177379A7D366E579E +:10D8C0001D66FCDD38037F8E33FB4D78A1D13D18FA +:10D8D000F813F263D01E82FEA6A07D1487FC9E3250 +:10D8E00092E2210B14BA4764E4F7D1968A3730DE0E +:10D8F00076F466E6F6B1507E073EC6FE7C0ABDC7EA +:10D90000A0897DAEE46323DF4F8F10FE2907F73F28 +:10D91000B5F829D056C547D47D7F9B8CF1C4D3D1AF +:10D9200067D899A6E1C1B8BDC82C5EFE8F17FF3637 +:10D9300079196E7ADAF15BA8BFB4123E34F9EE447D +:10D940003B7E04F41FA0BCBCE3AE5CEBCC1079F9C9 +:10D950007F018165E5A90080000000001F8B0800A1 +:10D9600000000000000BED7D0B7854D5B5F03E7340 +:10D9700066269364122621901048980422A906383E +:10D980007941401E87C82358B40349143009C33B6A +:10D99000A878236A0DBDB499908001C11B340AA2F6 +:10D9A000E880CAA5966AB4DE0A4ABD838855EB03AF +:10D9B0008354EF6F1B86A7A0B546B8D6F67E5EFDF2 +:10D9C000D75A7BEFCC9C9399006AFFFF7EF76BF8E8 +:10D9D00074679FB39F6BAFF75AFBE4ADFCD28CFC2E +:10D9E0007E0C7F2CAC3F630B5CF43B9BA2E6A50650 +:10D9F000F3185BB12E27953919FB067F26F62C17F5 +:10DA0000FEF54AE6EECB584D9FE01D8AC6D8208D24 +:10DA1000E993D3189B83838CA5A1022C97B1B9A25B +:10DA20003E5D1BF2410B8C5713CFEB69ED8ED93E57 +:10DA3000A82F7704A7AAF0E89FF2EACA065818EBC5 +:10DA4000A3BA198375C5D8BCFAC02CC66C7BF20387 +:10DA500003E1919AEBA2E7CC1A1CE04960AC7A434F +:10DA6000FBC6616E1C17FE57CC5895BDD5C67020FD +:10DA7000E6B77986C3FAF298EE77627BF8AF88B1A1 +:10DA8000E3EB9E7F6ABD125AFF711B9BDD1E617F17 +:10DA900093340BCDB3B38131F730C6763538A87CDB +:10DAA000B2C1C5DC318CED6E48A3FA530D6E2ADB92 +:10DAB0001B72E9F9B30D1AD59F6B28A1FAAF1B743D +:10DAC000AAEF6928A3F285060F3DDF3FD05BA0C116 +:10DAD0007A1FB0E8C7EE82FDA5ABAD8C0D8135B6DF +:10DAE0006E66780E8B700B6E829FEE18C598971F2E +:10DAF0000B1B6CD7ED2C85B1A6758A6B35F4F33A08 +:10DB0000EDC79444285B9440CC0868E09BA207735F +:10DB100079DB6FB2115E1C8E2CB7EBC127A05F4D75 +:10DB2000839DAD87478F5EC6741CE7D19FD8FDBE2D +:10DB30002C84DBA1838EAC101C3FACBFD7061881B0 +:10DB4000C797E3867673EB62B5F5F0FEAD7C4F19AF +:10DB5000AE3B3E4FB37B016E19F98CC6BFAE9FE75B +:10DB6000871A94CB37EC7FE47D3CC77D59762FE054 +:10DB7000CFFC3DF96BD3DCD8CFEBC17EF39D2EBB40 +:10DB800007FADDD29C6477231EA4B2BAF63C9CA7A8 +:10DB90002B73564208FEB59A42EBC82AE0E37F8613 +:10DBA000E744ED5A6D330DED2CD40EE0A63BFA8719 +:10DBB000E09461653E4B01C2CBCB7484D700A621B3 +:10DBC000BC06C2F39802FE3E3639043F33DCEC005B +:10DBD000770BBC1F08A5BD2004C70C78AFC2735BD0 +:10DBE000EEF1392C1BE1C6E67922E0CF83B87E84C2 +:10DBF000FB6C07D1D562073F4FA0ABA9A980872B4B +:10DC000036292E4003B6C8E9BE7E0CD417BD666324 +:10DC1000ABA13E23D96D1F00F52E38DF1D505F707C +:10DC20007BBEDD0DFBAEC2B380752CDA3286E86DAB +:10DC3000911FCAC2E87479C3A603197B117F02BA87 +:10DC40001DE964914BB727E785D16DAB427461AE96 +:10DC5000AFD3545A77156393117ED5B767D9173868 +:10DC6000B1FE9A6D451EEE8BC341F68376016C378B +:10DC7000239BBD8AF4D505FBDA91C5E72B081B7FF2 +:10DC8000018E1F363FB49FE781FA7D5A028D37DF40 +:10DC900005FBCEC2D245EB0438109CBA36C2786E72 +:10DCA0009A87CE6361C06FD3703D569817EA735D53 +:10DCB0007E1BCEB3A039DF8E7CCABB81CFE36D491A +:10DCC000B20F87FA7CABCB9E81F08B0358A4D0FABD +:10DCD000FC3BE06816015C929D380F9B37CBD91353 +:10DCE0003EF3C57A17B526D9171B9E6FB2E17900AE +:10DCF0007FD323F18D83E2DC17344FB233EC6FD541 +:10DD0000ED1AAE47C0F7D4ADB1EB591FE8DFB6D975 +:10DD10009605F57F13F87B50C07546762047C17D88 +:10DD2000DF1AABE13AE7B85A697FDDF0BD1FE001C9 +:10DD3000CF17BB3C045FC00B1F03382C6A339E67B0 +:10DD4000683D1CBE8BDAE613BD2DB17AEDAEF075E1 +:10DD50006CD99FA3005CE6007D2B007FE6F2662273 +:10DD6000BE9CBEFFFA4CDA27AC13E19AA0B9A7A675 +:10DD700015119E101E4B7CA929E4F42BE7FBA3662A +:10DD8000A5F9FE28F86774BAD45F4D43BA84F35DF1 +:10DD9000ED8E4E977664DC30AF7D91E26F527AD291 +:10DDA000A9A44F4997924E25FD3E62F304D29410E8 +:10DDB0009FA9E9C3EA9E8D00A78C7C7E0E73C5B92E +:10DDC000025C5F41B8CAF7F67CCE8FAAB28DF48EA2 +:10DDD000E3E1B8E704BFAA2A0DE4DC9A176A2FE74B +:10DDE000AD4AE6FD10EF11DFCE8973C7F62BA8BD53 +:10DDF000E063825F2CECE617BBD7F4477EF18CA280 +:10DE000021BF58B1F140C69D00B715BF8CD7100691 +:10DE10009FDCFCC42D03B251BEF9E9DCE4BA16FF65 +:10DE2000359FF8C412219F170522F38BEB73BD6A4F +:10DE30007E71A8BEE8BE5F5EE6E5FC2680FCE60FCC +:10DE4000BF7CF1C85877489ECAFD2C6879D736DF69 +:10DE5000190E3FBEDFF5B9E7E6E3792D74DADD2A66 +:10DE60003C5AD83C9FF82F4B635A8E123A7F335E50 +:10DE7000CC6F5674EA573FCAAF7E8F7C7AE18699A1 +:10DE80000CE5943C379898B15121F92AD77F593E37 +:10DE9000A7DB1FE4F3FE73057ECFAD9D641F908268 +:10DEA000FB9D5F886AC51CF17CCE22E3F3EE7373A1 +:10DEB00075F3F9B5482FE7DAF9B99DDB6023FE73F6 +:10DEC0006E77829FC1FE3E59F1FCDBD741BB8F1FAD +:10DED000D89E89FA4AF8B9B1427E6E582E8573638E +:10DEE0007D239EDBD8F0735BFA283FB7854FBDF5E5 +:10DEF000C717DCB45FCEEF36C6F8911F2F687F8658 +:10DF0000CE714ECB265B16B4BB3A3F8BCEAB9BFF9C +:10DF1000D7E5BB18C0776ECB761BF289AB251C4CBE +:10DF2000F400A5CEC2E80CE592921CD2C7647BE453 +:10DF30008FCFC03CB7DF1A9BC84686E6B92D9FF34A +:10DF400085857549C938DFC2BAF9F7B01121796002 +:10DF5000DEE789584E2F0B603CA4DB1393B4CC153D +:10DF6000849F968872F74681870F01B863011F0668 +:10DF7000C6B7FF1CE130F09FE234E41F438706FD83 +:10DF8000382FE237AEDB0EFCD301ED86DE1CFC1C25 +:10DF9000D73114300CFB6199904C25EB0FF51DB077 +:10DFA000EC1228B3555EB6E6733D09DE07F03D4B33 +:10DFB0000916E3FE257E9BF1D7CE1E6FC9463E961D +:10DFC000C2B42677085FE538125F253E47DB5FCB9A +:10DFD00045EEEF441687A73D0EF6977C09FB0364D8 +:10DFE0002D490EED4BAE0F7478DD82FAE33F0FDF63 +:10DFF0008EFAF389462DB3CED9DB7EDBA6F48FB043 +:10E000005FF33E25DD2C72709A06BAE98376C7B9B4 +:10E01000D6217D50EE9C5040BE41BF13B7C65A700A +:10E02000FD725FA897B318AE9763897A391BC6F55E +:10E0300072ACA35E8E25EAE5F43C3F99CB23164CE7 +:10E04000403D13F401CE0F029C4E3AEB87D0BEE464 +:10E0500073A91774BA8209C961FCFB649D909B2C5B +:10E06000B811E99BD50F614FC0549DAD27122C7993 +:10E07000889F7C7DB2DFEDB62EE2872CC1EE7E025A +:10E08000482EFEF677A7A4C27C8BDBB2F215E857C8 +:10E090005D5FD8590FEFAB9B5335E41B8B9DEEB5FD +:10E0A000281717FBB234948BF16DF9A7B7C0FBC5E5 +:10E0B000CD5768D8FE76857990BEA49DB08475FF53 +:10E0C000909DB054F0B5A5C82F015E4BEA0F0C75BA +:10E0D00041FF255A6C3ECAF7A55BB89D30C3C25AB2 +:10E0E0001494C34D9EA9C8C7BA1E5434D437D9C39B +:10E0F000C05F1D21FEFA7EAEE7B7C867D857807FA4 +:10E1000030FEE5288355DC57BB8EFB60A08F3CC1F9 +:10E1100070DD1ED2EBA70ABED1D9762CC19DC7E116 +:10E120008DFA3AF3EA16E4BB2B845C1B6CEF3A766B +:10E1300017EA3309166D07E797EFB8719FAFAB2C5D +:10E1400086E48D682FF8E9E09F953890BFAD48C808 +:10E150004E25BD6A8B4AFC51E24FAD58F3E2EDE526 +:10E16000FD116F16C37B94775BF121B0D0B56D576D +:10E17000F547BC5AB469CA033E906399028E27AD35 +:10E18000C199783E67B6A72637A25EB8BCE93206C9 +:10E19000EF176DBF2B13CB33DB636723BF9FEC9A65 +:10E1A000393909F6BBE4E1A47C354C6EFC45D0E37B +:10E1B0008DCBAF4A457BE0E6AF0F3CE2023B6E31D0 +:10E1C000C01AE1FE457BBCDF074D6E6ED893A902F5 +:10E1D0008D7D1DE3FD1CE1799365DF756390FF2B59 +:10E1E000FE9D03A8BD3BD5D58B9D7D1AED50C0E7A4 +:10E1F000E53FFB80C6F9D4F2E6B573A0FFCDCB7F37 +:10E200009588E3DC74FFE1512E78FED650EF7FA3B2 +:10E210003DFFB1B27DA70B05D396ED23506E7F8DE8 +:10E22000765A31E2B5E7BA3908F7D755827BB4F9A7 +:10E230006AF728045F59AFF6F7217DD61B60761781 +:10E24000962E46FAF21995D5A33E20F51AF93CA967 +:10E2500080C3E54C9FD64CC48B653B3767A25C39C5 +:10E260009BC0EB553BAF7F03F994F7F118AEB75B5A +:10E2700019E9C90B7D5CEF66B540AF0342F30F2C83 +:10E2800088A7F1966D2934C843D04BE8F9592B2B58 +:10E29000C3750C6EEACA47FDEB436B60319EEB879A +:10E2A000A0D7A27DFB17C1C73E6C55A7E2731F1014 +:10E2B00012EA231FB6FE2A61A833A4C72514B507A6 +:10E2C00090CF2D7F2EA940E52845F8754BB75FC448 +:10E2D0003975600AE9632EC4D3157B0F4E65BC0EF9 +:10E2E00082303A3C6F147A5877FDB967C8AEBB7973 +:10E2F00037D7276E6E7FE6D57418E7963D429F109C +:10E300007ACA7241CFB73CC7E1B2FCB963F685E186 +:10E31000F6486EF2DA81A0094E78F6F2D9F7BBD151 +:10E32000DE56C8AF52A965CE691C8AA5F4977491D0 +:10E330007EB83EB783ECF2E5CD62BCDC8EB5D9B4D5 +:10E34000DF997DC3F5A1890536EA27FB033CA8DFE9 +:10E3500097B1892390FF0596C7B5A05CD76F715A16 +:10E36000B16C5AEE2439FF709D25D70AF0D5953847 +:10E370000DF5B87A076F7F675CE20E2CF7C5F1FAEE +:10E3800097B19924A7BEB4789E5902EDEE540FC5FB +:10E39000A2FF6300EB3A60817A493FEF7505306F69 +:10E3A0002A03EA51517E04147CFFD96F3E2AC475BA +:10E3B0004C181C3CCF6069B6C6BC3993014F6A0A41 +:10E3C000C43EF3828588EFFD5EE6FC7A9B8DB5A0A6 +:10E3D000BC63560F9B05CF03C8BFF0FCFF66F1235B +:10E3E0003FDEA7041E0BD7BFEE1378EB8971B6286A +:10E3F000B0CEC7B3BC4B711D3F526CC35175616E3B +:10E400003507C7FFCCC6DF4B3DB65430E10C618FFA +:10E41000D9D3D39CB8BF26012F45D7593DAC6375DE +:10E42000DECB0B115FEEEE72B01898BFB42B8EF4FA +:10E43000DA8CF432926F4D022E8A3B05650E7B39E1 +:10E44000CFE28B81F5DECD1C7E6CCF1C26FDD71272 +:10E45000AB633F65DF6FFF86FC7EA0FAF9813ED09B +:10E460007EE09D8AD6046D6ACE9DDEF60E43FBD912 +:10E470009F8FF0BBB39FB7B100F6D779AEEC98177A +:10E48000CEFB6E57BB43CBE3E385EF63DFCABF250B +:10E49000265B42EBFBACEBF42F9F2FC2D24172A85C +:10E4A000749FCAFD4DA6F57C96E6B6D23975390241 +:10E4B000166CEFB4F81505DB1FF800D757EA7006A5 +:10E4C00054D4E31DB63F85CB19762823E9F41524EF +:10E4D0005AD837A02CF46FE2E737A18FD1BEDC59B0 +:10E4E000C0EDA49DE29C247C25DC985B67E172E68C +:10E4F00025E7CE6AEEC7E274FC4FE2F9B9BF669336 +:10E500007E716E1FE81911F44E591E463D03F487C3 +:10E510002FB3F5A7106E52CE564AA92BE4B02AC6E7 +:10E52000AD14F0AA745A387C2A4CF0117863C60BEB +:10E53000F3B9CBF3643F3974B04F169DE3F07F61BC +:10E54000747E7B111F3BFFF6E61A203796AEEAC7B2 +:10E55000BC59FF13CF2F103B0CF58AFB2DA457A0FD +:10E56000DE877AA2E41F5EE40323E939D703731937 +:10E57000F18D1A358EFC8C66BE21F985370ECA11D5 +:10E58000C8375A891FDCA9761DB428213E31B82C22 +:10E59000381CE5702798FEF83E6869A7E7DF146429 +:10E5A000137F18C40E0D203FAB35588C7AA0EA7843 +:10E5B0006CDB4910296DEB387D34D9FC0F2E41FE00 +:10E5C00050E9D450AFFBCC6FF1D9609D6D499C6F81 +:10E5D000B42D4B2779FE19137C64B69DF8C89516A7 +:10E5E0008B8FECAD39E9646F75B7CF71937FF5D739 +:10E5F0005FAB976DC1F7331D2477DB501E43BD6DB4 +:10E60000E3707AFFA2E44BCB385F6A9BA90F88C303 +:10E61000F733FB5B70BEDD29DEBFE1B9A7ABFE9F20 +:10E62000C7A23E79531C7B029EB765E90350DE3ECC +:10E63000A078E62CC6FEC3F9BA8373E29EDAC98FCE +:10E640002780FEA4CEFA841DE17E6FE9471FEC3BD4 +:10E65000F620C2CB57CA72519FEF44FC1C193A2FC7 +:10E66000B0CA597D72E8DC524CE726F1D56783F3D6 +:10E670004BE1E7B75A897E7E29E2FC947AC06FE2CB +:10E68000FFFC7CEE54397F672F696E2CD5FEDED4FB +:10E6900042585FD3AD702E2410837720BCB6AD4CAA +:10E6A000D0711F9D1656DB1E816EB30B85DF09A549 +:10E6B00031D0C33C410FF324DEAE32E16D7050D255 +:10E6C000E97881B7D0FFC578CF509CF753E5F028A3 +:10E6D0007CF8E67FABB323CD33BC90FB0BF68356BF +:10E6E0005A48F2B5D4A0AFBE99FF5106CA29F6D553 +:10E6F000814128775F49F18C2C04FE113BB48BFCDF +:10E70000E69D03BA6CB8CFCE391F67A05E34AFFE6A +:10E71000B7445F17BBCED5F135361C27A922CB16DF +:10E720008432B522EB20E2CF91E931EE98087AC825 +:10E73000FEE9C33250FFEDA81C96817CAF030EF0BA +:10E7400010AECFEA4E40FEC7F654131FAB147CAC9C +:10E75000A362087F2EF866D8F38D45A8D73A2D5AC4 +:10E76000B8BE602ECF02DF0C00DFFC08EC332C4F6C +:10E77000817D1600FDF504D867583F06F6199647C7 +:10E78000C13EC3B2A341A3F74D1543F604E19CBFBC +:10E790006851687CF4DF46D28B6F7C5C6501091F91 +:10E7A000F8AFF6E17816C80DD597B4F535D4176DE6 +:10E7B0001868A82F681E62A84B3DD2BBEA0AC3B8EE +:10E7C000E565858676ABE347D8F05C93CAF239DC21 +:10E7D000CBF209EE1DD74481FB35A309EE87A78F45 +:10E7E000CE40781E46B8A3FD66D512F01C24DC6727 +:10E7F00089390F9715F2E702EEA1E7E5BDCAA94FE7 +:10E8000010DE31087707951F21BC09EE1CDE2710AA +:10E81000DE3108F75C2A8F22BC87E1B800EFA20B3B +:10E82000C3FBE6DDAA010E373E6E8477EDC37D4D56 +:10E83000F01F6880E3A20D430C7509EF05CD467803 +:10E840007B57159ADA31B601E0508EBF001D1C2EA1 +:10E850009E467129AB83F9E281AF2421BDC1FAAD97 +:10E86000150AD78FE0A715E87016FE02F46575F259 +:10E87000F7CD73143FF225D489D0AE00B806E281FB +:10E88000CECA5D979D42BE743D723015ED7A3F95BC +:10E8900037B000D167350B527D1EEBCAB443798B7C +:10E8A0001A588BFEBBB71CDE27919EFF32FDDD4E52 +:10E8B0000589529B3F0CE99C3993C9DE8C764EC08A +:10E8C00029257F62CE51625FF05381FC1FFA75C427 +:10E8D0008FB8E30E3887CFE60747E1FC373BBC8FA4 +:10E8E000A65868BE3D38DFA736EFB0BEF0FCADE2FB +:10E8F000D11948FFCCD3CF6027459B6F136E16E02C +:10E9000030BF0CE0A4601C8EC3E5642587CBFE4DB0 +:10E910003176F4679C5C67237FE5E6F8CC4CC4DB7A +:10E92000936BA66522DE356E1A9689F83EAB65DAE2 +:10E9300059E4DF53D41935144F6DE578CFD8ADA421 +:10E9400077DD21CEEEB89B6901785F393D41F3C197 +:10E950007EBCBEAC445A2FD39DF9D06EA1D8F7C26D +:10E96000D6A533703CB9FF051B620CE7FFA3126309 +:10E97000BD92D943789685E76C0FBDC7F357ABFAC4 +:10E98000787BB1A3EBFFB0FD8D57C2C63B5E98907C +:10E99000827A0B1BCD467FA386FA4783EB970DFE49 +:10E9A000375EC909C155E2D36F0A3D9FE0F9C063E4 +:10E9B0008AB7012D913CB8A5DBAFB52F11E1B7297E +:10E9C000FEA57BAE44B8BCC7FD1C9BE36B887F7C77 +:10E9D000827C3B0BF9F4F519C130BE20FB07053FE3 +:10E9E0003DF2CBEB898F1CA84CA5784CC773DCBFDC +:10E9F0007C54D07D47C5F5D57700FFECD8AD929E0D +:10EA0000D7B1E7FC41F4D374B42B9A00B9257CDC70 +:10EA10008E3DC0CF91DF7A6CF47EFFEE5FD13ABFBE +:10EA20002F7E5EB157F0F32D7CFEC5560FF117E631 +:10EA30009D6DD8DFDF8BAF5F889F1FB1713CED38D4 +:10EA4000A292BF8DF9F443B9FDC3F0B38CE36763C1 +:10EA5000650CE3F295F39959154007A8E733773130 +:10EA6000DA949FEC29EF47F27283ED38EAD32EF85F +:10EA70008772DB0CC74A663D1E0CC3DF9B9F83F683 +:10EA800061EB9B85EFC3F0D98CAF2545467CFD82B9 +:10EA90007D9569CFE6EF0FF50FF13DFC09E72F9269 +:10EAA0006F49FC05BE55837C0DF8CA554580B73FBC +:10EAB0002EC8FA4D5009E32B17C9C736C57F4D72D2 +:10EAC0007073FCD784C7872B051E839E81CF3BAE16 +:10EAD000E1FA06F3CF267A9827F5089B2701FDA4D3 +:10EAE0004756F54DC4F7C79ACB89EE243D99E73BCD +:10EAF0002AF04FB69B67EDB26911E4A17795117FBB +:10EB0000D8AED984EF7798F02CDAF8E6F6729E79D1 +:10EB1000A678AF799EDB8A84DED95E7D51F3211918 +:10EB200076F727FD362E84972AF2812F1382A47F51 +:10EB3000CD36E86547CB46935E76B8E27C44FDEC83 +:10EB400068C5F9B74623BD95D904BDD752FF72F108 +:10EB5000DEBC8E8F84DE704AF08F1382AEE57B754B +:10EB6000FB9AFE7311EF57A91AF2AB23330A09CFB0 +:10EB7000CFF82B69FEA3152AF99BEE2F9A3217FDC9 +:10EB80004D723D72BEF26BCE27A03FED0B8017FA9F +:10EB9000C7CA6D5ABF48FA85191ED1C695F803FA3F +:10EBA000EC11DCE761E4A3F8D66B84D361EC0FEFE2 +:10EBB000676D5729DE6686D381E9C3882F1DDD2561 +:10EBC000F827C015F5F0DA878DE7BAA42DDEC46FFB +:10EBD000FA1ADECFAAE47A99E4D7727D87570DE955 +:10EBE000179E3775A1F396E35C2CBEDC28FAA3D8F8 +:10EBF000FC86E46FB2613CB0144DF3659BDE5F6E42 +:10EC00007A5F60AC5F241E1F13F823E5CFB158ADC7 +:10EC10003A521CEFE8D531B5E1F9099D45DC7FD3C7 +:10EC20005924E2DE9728B7FFA328B2DC8ED65FF224 +:10EC3000BDA70B3D41E4772C504EF1EC8BE57361A1 +:10EC400072FE4C11D27950B1637FA957DD58C6E5E9 +:10EC5000C2E6F8A7284FE3D346AE17ED6F8C213CF0 +:10EC6000FCF335FCFD9FFFED23D2A70EECDD9C18D5 +:10EC70002EE7255E9EDD332D11FDC2272B1E4B0C8A +:10EC8000B703E4FB8F2B1EBB672CD1B7AAF5762EFA +:10EC9000DFD61EE8A810F680D0176EB2B6FF3FB1DF +:10ECA00007CC76C014F5E144E47F667BE0AC5B4FB3 +:10ECB00074117C04DD09B972A380CF9F6D7A22C5DF +:10ECC000E9761572B962C24F0987D3120E1BCA7B4F +:10ECD000C59B53422EC8FA622B2378781D8CF465AD +:10ECE000D6A66818FFC234951238974315F98FA13C +:10ECF000FF4AB67FA65825FC96F31CD9A6B4A37F7D +:10ED0000E5B7CDE5D57760BEC38C78E2ABB2FD1236 +:10ED10005FEFF2EBC8C6A46B711EEF1655C3475EDA +:10ED2000DFB17EE1EB977A9AB9DF326BEB45D9D14F +:10ED30005EDFF644B46F83629DC1FDB1767742CF4A +:10ED40007E18AFC1FD2F9BA16A8DB0FE651BF8BA7E +:10ED50002A7DAA960DF5DFB63E762DD2C1897A9B23 +:10ED600085DB072E039EBFD95AF836B63F59C6E554 +:10ED7000CAB18AAB12310FCEB7C5A6E5B87BCE5764 +:10ED800053CCF3D2CEEE89B1A0FFF46CBD8D05C893 +:10ED90007FE1217BF9C88621549E45F871FB9ACE0C +:10EDA000FFC662EEE73AD1BAB03FA72737AD43E2DC +:10EDB000CBB15D6A993F02BFBA519CDBA9AF9E26D9 +:10EDC0007C7B755739C9E313157C9E53ABB44484DF +:10EDD000E7EF36A844C7277D7CFCFD7BEF4A1C0B80 +:10EDE000FB385BC1F77576CF9D6F8F817D062BA4B5 +:10EDF0003CE6724AE6F704370CA178EFA7CDDCFEBB +:10EE000096F42EE3E157AD3C9248FDA59CDB3DDB3B +:10EE1000B0FE8E5D27C80E3BBB0166E372CE998FB4 +:10EE2000F986BC3B5B32C378BEB32AE20DF5792D7F +:10EE30004679D6B897F32BB39EBB7803E8C1E89721 +:10EE400032D9790B1B0B134B907E510FC63C932785 +:10EE5000CA0FA6E23EDAABA95D85889B2D6C8B318B +:10EE6000F083CA66A35DB7C064C7F5B0EB4CF24847 +:10EE7000C2697914F924F5B90E61AF1CB579AA23DA +:10EE8000E553B41773F9330FE8370DE3444CAFBCC7 +:10EE900052C07B3DC2C7DEF5450EE8D31DAA361E23 +:10EEA000F5EA1E7460D203CBCB8CF0659A8F95483F +:10EEB0007F849BF4FBD3A8FFB7F41572DB0772289D +:10EEC00001E592FE6C31CA958BF51F5CB47E5E2322 +:10EED000F4F31A837EDE814DC2FAEFAFBC9EFC5480 +:10EEE00047AEB99EF4F523DD7E2A8FC14F25F5BAD2 +:10EEF0002333CA0DFA67D8F33EBDE58B47D3378F6E +:10EF0000213F263ECDE5D25A6147360B3BF2C80C75 +:10EF10006147A630A223AB556791F8D9A5EA6F0BDC +:10EF20009A8D72C9BBCA683F3E3FC97B16CF252662 +:10EF3000ED72C3739BABC0E83F34E1E740C6FDE729 +:10EF400077A12F00E0DE54C9F34EF139E6BF48B98E +:10EF5000C4A03DF28BCA0D97FBD7F3F73EB500D3A3 +:10EF6000E518AA74D4DECAEBBAC2EB3EA778AF8A22 +:10EF7000BC371BD48F6569B351EFC2BC9EF864FEE9 +:10EF80001E516420E075627248FEA15F3F9687D6ED +:10EF90007D89D06F5045D62B48D798EF735901DA49 +:10EFA0008C3C2F2C0D5DFA05347E00F37A824D13D4 +:10EFB000C9DF5CEE48E4F179B0A37BC7BF46AED7AA +:10EFC00095F5A5C90659F97AA2E2B36877217C0EB6 +:10EFD000D3C3068C223F9A85FC2D9BE247D8107F35 +:10EFE00067393D190807C07792AF1DBFB1131FDE07 +:10EFF0005FC9FDB01DD3476FBB1D9E8F78DA49BE38 +:10F00000F48EC5D20FDE95108EB747579DB0205FA6 +:10F01000FEFD1EA6611EE3D1DD5507DF80710EAC3B +:10F020005AB8B118E9E84D95EC06B3FF76D2D3E3B0 +:10F03000C8FEBAEE1A95F2BB0F97A90CE5DAE10DFE +:10F0400071063B24E4D755093FBED867A5F768EAA7 +:10F05000E462FE15FA37314FAB8C9FCB0B829FB524 +:10F060008B73FCB9D063760ABA69137473AFA09B33 +:10F070007566FFEEC39C6E0EEF01C301E4FA3B33ED +:10F08000169692DF7A0BA33874D674757D11ECEF67 +:10F090008A18CD86F09B34239FC3B342B160FCA68F +:10F0A000BC2CDF86F47E455FB70DF96879D94CAA90 +:10F0B0004FAEC8223B7FFF2A908F68EF2768194820 +:10F0C000974367C4042C89683716129FB8F28CC521 +:10F0D000402FF9813803DD5DFE78B2E1FDB02DE906 +:10F0E000867A3F4FB6A17DDF32233DC60D2D30F22B +:10F0F0005DC6F54209E729EA38F2731D0DC9517A58 +:10F100002FF511E9AF93ED015A06BED622E4C808E7 +:10F11000A8633EDDBA8A2607E64D7CD16ED5F8F8A5 +:10F1200055A41F38B29E73209D606815F3AB5AA496 +:10F13000FE29FCF74C67A6756D6018673D5AC60836 +:10F140009F62873205F5AF3671DEF7897981AF4E60 +:10F15000B2919F8E9F63DF191E6AC73C46FB200D4C +:10F16000E9AC00F184F7FFB9E8BF53E0CBD1B2C7F7 +:10F1700056C7213ECC66A46F4C516F5E8DF1C4A37F +:10F180003318D1497BE0E5385C3F8E83F9812F4409 +:10F190001BA7E2571FDE82EBD965A771CA1F671351 +:10F1A000104F2EFFD1B18FDF46F06D711D88653D88 +:10F1B000E5F088C7750D81937B86056C540674E471 +:10F1C0003FB9670EE9180FBCFCCFBB3E7E8AE1BC9D +:10F1D0005C2EB408FC36F3D75F3CF1EB05289F7F2B +:10F1E000B1736BC10750FE60F583E9F550FE7CF505 +:10F1F0004D5B6F7787FCA53BAF5DBAA30DEAC37E7D +:10F20000F8D3279F43BCBAF6A7FFE7395CEFB57F79 +:10F21000FBA313D67F59530243FA96EB33CF93C621 +:10F220005A148C8B221F25BE6CF5517DBECF68FF12 +:10F2300098E53EB6B702FCCAEB7F41F1E534D1FF59 +:10F24000F03577292ACCFBC17CCE573A1ABADA2698 +:10F25000DBA87D00DB039FA47CCD818380AD607F34 +:10F26000BB4FC1B83828481AC67B07C07BE4E7CC3F +:10F27000ED26FD2A53E2AFE02B78CD81913FD04AB5 +:10F2800078962BE291C87F91DFBF312A9BF8F2403C +:10F2900027D3F17CCB5EDCA0609EDAFB5EB7467ABA +:10F2A0004103BB7F32D8C997AB3CEF22B7ECFDB925 +:10F2B000782EB055ABB72034EE2EA1D795BDE8A47B +:10F2C000BCEDF77739B7939E7FE85A4BB87E58FA72 +:10F2D0008B3F3DFB3BC4AFF9B1845F66BDA543D016 +:10F2E0004777DDE6DE763BC0C7F71B07B7AB747721 +:10F2F00006D9E99A3B03F377BADBFD54C6D3B43F92 +:10F30000223F9F55154F7106195752CB3E5F83F42C +:10F3100038AFA4AE18F5F7743C87BEA138F607CB1A +:10F32000EC946FE053E2282F3D5ABCFABF843C6452 +:10F33000AC6E24AD83D58DC6F2FCECA66D767774E9 +:10F3400079D52CCE35DA7B9B9D7923C595FF6B143F +:10F35000F72336E139D8C2CEC1F9FBB9181F8E7632 +:10F360000ECCEA2FA03C4B876328E681A48AC79B7A +:10F37000E37FF616CAABCE235C5EA5D67FD980F4B8 +:10F3800027FD163569AC3B6EA6433F9BE8972AE202 +:10F390002C48C3A87FD78878516735A378516AFD78 +:10F3A00047FF8DF0D924C6AF798F8F6FB706F6234C +:10F3B000BED438DD24773AFB256A78AF897DC5F362 +:10F3C00053D219C747393E13E3E3CA59D8BA53E3B6 +:10F3D000AADEA1EB101358201EF14771D0BCE9AB97 +:10F3E0006228AF55EA57A9F577DDAA8E308CA7A021 +:10F3F0005EFD7E15B7B7D1ECEC1E37CBA057919EC2 +:10F40000655E87ECD769637BD0FE0DD3B3480F638D +:10F41000E1F30C31D4851FCD58B7A5D90D7CE2FDA1 +:10F42000AFCAFBD47139E04E19C5FD77080FA98F1B +:10F4300049BDADC7B882DEC3F44B1FF20B9947D16B +:10F44000AD27D586D94DD93DFBC97C35790E129EA5 +:10F45000D1FA3F3F499F329AF4AC008DE315C3586F +:10F46000E29D99045F13BF04B6C5F3E9851E0A5AED +:10F47000A4218F41EA95923F770ABE1BCC0A92DF06 +:10F4800050E6890F823E99D0FF86D149DD79F6A8F2 +:10F49000071D6DF88CE2EF35A887C2FCC1D59F1817 +:10F4A000EEA114954EBA81D66BCA97088BBBD27A5F +:10F4B000BD826F4E519D94B7D2C9E234E45F9D3E48 +:10F4C000A18FFD219EF431C92FCCFCE11ACDC8FFDC +:10F4D0007F5462E4FF33F5BE26BBD018A7AAF49888 +:10F4E000E2E1EF4D37F04DC97FEE44379F8AEE25BC +:10F4F0000FC575DE14FCF26DA107DA591D3D77309A +:10F500007E7F348EB553E96487A84C645D54BA9805 +:10F510008BF26B929946650AF350D99FD55199C6E3 +:10F52000783E553A6BA772103B446526EBA2D2CDCC +:10F530005C162CB39946E550E6A1D2C35C14277F34 +:10F540002F21987118E037E37A26EEFD1EBA418725 +:10F5500073EAAC64A17BC04857539840BEB7F9FB2F +:10F56000E9B2FECE0D3ABE9FC4DB6F7DFEBD87F0D3 +:10F570005E30F01BF1BE83BFEFAEBF7BC324EC6FE8 +:10F58000B3507DA7687FAA487F08CFFFE9D18CCE12 +:10F59000BBAC48DF36BA38543F53A83F1A5EEF3F42 +:10F5A0004ADF1E5E1F5DA83F16DE7F49A1FE44F8BC +:10F5B000FB7DC5FABFF2BA8BF0F23D9B4EFA2EFCF2 +:10F5C000EC5246717CC39F3EAAF769C2C3DD8A151F +:10F5D000CF3546D09B1DCF51453AD21C31587A7851 +:10F5E000DE4F30D6198CB7F462FF98E82888FC0902 +:10F5F000F070B8E2DD47F398F889E213F98329C681 +:10F60000B809E03BF95583ABB89DCE58E4F772DEFC +:10F610000BE139D3C3FCBCD9A171A3EDC38CBF8767 +:10F62000849ED721F4BCF7441CB97BDF416BD269BF +:10F6300047888EA3DB8756763A9C5FF6D8F79FAA59 +:10F640006D40D7C1FA1817CABBCE58F636DA69BE74 +:10F65000232A433DE352D7DB5638F50CE78B835C16 +:10F66000C867BAE7157CA6137F053DE78A3ED2BE80 +:10F67000D41C1CDEDCEE4812EB6A9A9C7C752EF9D9 +:10F68000F3B95E9F673B34731AAC337503F7AB264F +:10F69000227D63E8ECE93FB8308ED63AC5C2904F80 +:10F6A000AD917E5E933F6ED3E415AE707FF09A44C9 +:10F6B000BF82F1CBF4402CF743A4307F2CCAD13267 +:10F6C000AD8CF2667CAAAB0CEB55ECDA5CA82F682B +:10F6D00053DD6530EF81B65FAD403FE0A22A3BC508 +:10F6E000316CFAD4B3DCFFC7F33792059E37AF8B8A +:10F6F000D10208C77E4EF2DBE6AD2928437BB7C9AD +:10F70000999C8CB8985CB584FC864D4EED35BCDF79 +:10F71000E17359283F91B9744739E82BDB6FB796ED +:10F72000211FCF78A628510D5BF789E673B1180722 +:10F7300079D465A1F78FAE2A752C71E23D46B017DA +:10F74000A03CE03AAEA3FEBE15DAA0BFF19EDAE31C +:10F75000AD97F5728E89657603DEC66BC67A8CC965 +:10F76000DF6833E905C34A1252E89C47B15178CEAD +:10F77000239FFC8AECDF794E37F9D54B5B14CA8F97 +:10F7800009EED73251DF3CB17118E5BB34B718FD33 +:10F79000D1C10C9689F77DE6B72AA4AFAACD9F37D1 +:10F7A00062BFC1B9EE0138CE60AD6B802B8CFE1EFE +:10F7B000FDE98F6351DE35E38535C223C6E342C2DE +:10F7C0005E95F7CAE7BBCE55A3DEBFA8F55D0FC2B5 +:10F7D0003F49B710CD1CB5F9D3F0FCD74F9A45740B +:10F7E00089F7B4508FE9A18FFE15D619763F614D88 +:10F7F0004A761CCE1BC25F3D11F77BB2B590F4A3D5 +:10F800001D2DA5741FC03CCEDD0DAC1DF5D6350DEC +:10F810008EF648FAEFDD999E4CBCBF7D6AD3A4B545 +:10F820000CCEFFD4FE656978DF7D716B0C8B75F7AC +:10F830006C7F72D3689A6F31DEA3C6795B67DA5149 +:10F840006E4C6B9B6447B8DDDD30FB99F0791E2A66 +:10F85000F5569700FDC5B73E4378E264011FC2F537 +:10F86000DFC7EB99A85F9CCC6111F33997962844C8 +:10F87000B7BF1BEFA1FB29A73222B7BBA984EBE7D7 +:10F88000C11237BFB76E656F2F4D217BD085F47ADB +:10F89000A2A590E277368CBB0FC1EF567CD580F8DD +:10F8A0007FBE6AE1074BE1FD9AE9D79DC172A4BD15 +:10F8B0008EF466F67B95E801F442BA27F69F150EA2 +:10F8C0005753581E21EA8FBAC1AFE161687FD85AF9 +:10F8D000D4801DF8BB6DDF69D2C3115FF530FCA584 +:10F8E0009F51429F17F92169A3E8DE1DFDACB9FACB +:10F8F0003A7F00CAE32D0B1D91CE31FAFC61E3A2E1 +:10F900007E3B99E9B161F383540C905FDBCBE7EB6D +:10F910006E27DE8319AAD3FA845E6E7EDF4D6F5B9D +:10F920008CF4B94D9C8FD4CFA3ADF7077E63BF177E +:10F930003038818644FBB5067AB95C6D5F817115FC +:10F94000F63EE7FF60D7314F84385788CFC2DAFBE5 +:10F950000BF8013CD7A6CC22FB24DA3AECFE437A22 +:10F96000D68890FDF68334E3BA64BB17C4BE62FC4C +:10F970002C604BC43240F73962A03FCAEF2FAA6E09 +:10F98000735D1D812E6469E65BF8E30E8BFF98F9C9 +:10F9900004A2C150A98F58787F3D8CCF25DCCFF5CC +:10F9A000DF935B14D27FD76FE279145FF8A14ECA60 +:10F9B000053F27542DBE11CA8E33ECDEE192175B52 +:10F9C000EEB9DC6D80DBA2F0EF999C79F2276FE352 +:10F9D000FB8F9EFA8907977B57CAA244CEB78E2D1C +:10F9E000C0794E5D61277F0CFE38247E40C3A5FEA2 +:10F9F00018031EAEDFFBE496052877F63A344CC7B1 +:10FA00005BBCC5F83E262D6C5F8CE397CF00A760EA +:10FA1000F64CA0A3A33FFD57BA1F1E87FC13E97144 +:10FA2000550CDD0B33C3795C49F77746086F1784B3 +:10FA3000E250741F44D2D5F10D4DA7541867ED2A3A +:10FA4000BB9BBEA760B2BF8EBA67EA6961F161FB7A +:10FA50002A7E4F9385DB89D9A1FDCB718FFA163AA7 +:10FA6000DCCE9EE3F5C0BB28E3F529D5BF46BE98A2 +:10FA700056EA6163281EBD90F65DBF67D5D137A0F9 +:10FA8000CD3D715EEB987EB8FE21A314BC2F63754B +:10FA9000D3BDC1E6664B2CF2FDD6766BEC50847775 +:10FAA000B385E47C6B7B4ADC50944B4E0BC54F51C5 +:10FAB000AEA861FEFDD16338BC42F2C39318AEFF1D +:10FAC000C4097C3C952BF49FC95CFF519EDE477AAC +:10FAD00047F31A1EA792FA864BE08FAB99C721A372 +:10FAE000E93FC87870DD09C58B5CC8D7D624F2EF32 +:10FAF0006F2C9AACF9F03EE7554E467263305EAA21 +:10FB0000403DCBC9FCD3601ED5C5F51B6F2B237DB3 +:10FB100026D9E9D410D4A96D7E1FAD5BE774E680C9 +:10FB20007F08CFB85C9DE1F856935E6137E90DAA76 +:10FB3000A9AE8D11792B428F6042FF96F1E0848D42 +:10FB4000BDE70149BF6EABF04F80FEE4A37B2325E8 +:10FB5000CC8F78CB74DD9DD23F6407A489EF1EA5BE +:10FB600095B0ED4D61F127457F95FC06D22F29FD1B +:10FB70000FD2CF31A204ECB5C4307FC44B605AAA77 +:10FB8000140F9B8E789205EC80ECC93CA6F0EB1923 +:10FB9000DF524FAFBFB8B8CF432FF3FB41CD9638FC +:10FBA0006D4756CF76378DE3F8167700F6867AEDF7 +:10FBB000F50EBA873345DD4DF7EE371759785E33CA +:10FBC0003BE4427D60E118CE77B34A3D0BC6503C22 +:10FBD000D593857803F0F0D9F0FE9EF0DB66DC91DA +:10FBE0001D87FAF007034E6F42BDDCB7C642FC46E4 +:10FBF000C231ABD1722FA261587C2E602D08C5D9BD +:10FC0000D67BCEF9F0BEF0B5E3B8DF356EE6C9FDC0 +:10FC1000E8075D37D4427EF6BB12748ADB01FD38FB +:10FC2000541EAF7B0DE36D2DEEE464FCEECE534924 +:10FC3000FCBDFC7ED50309FDB787E797948EE3FAF8 +:10FC4000C8034A647DA5EF3885E759ED0540F621E4 +:10FC5000BF16B7C77D5F54E9CEB03AD21EF4FF1786 +:10FC60001FB7A75BF67E51E51B4A7692789F534DEE +:10FC7000F63AFA18E1FD89BD2F55F9A0FE4856E481 +:10FC8000797F2BE67DE475EF60D467837B017FFA93 +:10FC9000443ADF00B394D0B89918970AAE8C991DF6 +:10FCA000E93B3683C6F37D6E8677317D427AECE69A +:10FCB0002AB39EEA277E75BEF6F8414AD306FE5166 +:10FCC0000CF490C422F3CB0BEBAB5A1AEA9D4D2BEC +:10FCD00095B5C83F9A405FC5B860AACB4EFA6A7323 +:10FCE000D28F27E1B99CAF652EBCEFBA03D43EE4B6 +:10FCF0005FE857C57BACD3EA399FF1BAB89F15ECE2 +:10FD000038CF55888F03AC848F527FB55671FE7300 +:10FD1000450CCF47EE4C7292DF34A99EE71FC7FB1C +:10FD2000409FC5FD4DE6F9C33AFC433E24F55B67B1 +:10FD30009ED590476C37E5195B4D79C5FBC718ED2B +:10FD40009984E2A25EF5AA97C0FEC575EE03FE8314 +:10FD50006500EC602C5F06BB1DCB57C06EC7B8C1F9 +:10FD6000AB0DB954BED6A0D1F3371A4AA89C981946 +:10FD7000A4B822F991C97FC3020AF9F1247E7D3A21 +:10FD8000A814EA4F4DE2EFFFF3853B1FF50D82F714 +:10FD900029A2BDEFEA6AC4D7EE3AABAFC6F6356921 +:10FDA000BC5E3DF6C7D5E8FFE99AA27F88F2AD9F19 +:10FDB000C5337F0DB6FD498C16C9BEAF1D2BE47946 +:10FDC00014FB9DE127128CFE9CB3637AF1E73CA003 +:10FDD000F075F4DDF7D2C348177D665A3D88C799A0 +:10FDE000D9463FFFD563395D3C3896F39FCC3780C9 +:10FDF0003E7A81BBA48F68EF9BF6020A44A02B5980 +:10FE00006E4E6013E87E76B57D76A43CA7F3827FC4 +:10FE1000441DDFC9DC312343F4D6E434D35B90E2E4 +:10FE2000BBE7EB6FDB8FF2F2BBD31B23FB3058AD8C +:10FE300093BC0E02BD213F576B39BDA9567E3FB31F +:10FE4000E64DEE1FD981F485F970486FF0EB341F51 +:10FE5000AFA79AE8ADC94C6F4E23BD0591DE60BCDB +:10FE6000241FD72FE2ABDABF577A1B39F6BBD1DBA1 +:10FE7000BF8F0F525E436756DD0084CF66F13DBCF5 +:10FE80004BA5C337C7DAB93C18AE935FA0597CFFC6 +:10FE90001058CC06FCCECAB4418DD66480DF8C9459 +:10FEA0007CFA0EC16D63FB0B3A39E4447F4DE224CA +:10FEB0007DDA58A4AFEBCED0FDC67E164EBFB5633B +:10FEC000BBAA90FE32D674CC9C8674B75225396991 +:10FED000DED78B1338DD35297C5E38B901E171BD81 +:10FEE000B963393EBA5736290ED4C7E7332D278B6D +:10FEF000BE2B43DFBBF997E6FF74E1B82F4EE0DF7E +:10FF0000737137BE97E4E5FEB534B4DFE84A734158 +:10FF10004F7A849F765B7F033D2FC47D44A3E70B1C +:10FF2000F18FE01845C085511EB057DCDF94719108 +:10FF3000A8F46CF2E346F51F0E8FFC5DCAC9E3F925 +:10FF4000BC4DC2FF6BD6F7E4FE0F4FF2FE6C2C8C5B +:10FF5000A3385FE57EE07DCC8DEB9471B3EE3C235E +:10FF6000A91FFA98BF09F56D2BA832FDB9BA81E334 +:10FF700075E71F093D7159A9771D8EBB9DB9F7A380 +:10FF80007C736A3C5FE1F949FA7A82E7B7D4034BA4 +:10FF90004AF57B71DC6878B56C9AFE406FEFD957F3 +:10FFA00030CAA8505C6BD24C2BE70BF58AE003CE2D +:10FFB000B576A86F4E027EE646BD9DEFDB057CC39D +:10FFC0004D7686D18E988ACE48E41BC84708B8FA89 +:10FFD0000CCCAB4C14E387E475F020EAA54180ED2E +:10FFE000BDF02AD1C7E575D39B9CAFD881AF505CDB +:10FFF000BA84DB09F25E507C9E46F697AAF76E3F04 +:020000023000CC +:10000000584DF6FD9EB1C27E28604508B74C8BFB6B +:10001000BE31F0BCF0C12987C7C0E3E26D8BFBA203 +:10002000381DBD7D4D397EEF6BD913A7B6A39F74E4 +:10003000CC7FC430F15D35CA33F83BCA193A97F327 +:10004000FB58B5CF8AFC2A321EAF19CFE59F8CB37F +:10005000F682C7EF131E8B38E725E0B1F302787CF8 +:100060001CF135021E9FF88E78FC09F6BF170F01B0 +:10007000D61D3B4DFFB437BC9D3A55FFBC377E1AA9 +:10008000163FE0F943AC96EC6719BFEC015794AF0B +:1000900039BDF8A5D6ED88457BB6A976C7EBF8DD66 +:1000A000C7A67A6E677726688E12B46FDE55E97B35 +:1000B00056D1FAA3DDED0366B96A3CCF8F3EB0326C +:1000C000263011C6497772799BEED419E68B5B5DB9 +:1000D000419B3701F5350F43BDCD9E6261BE307F38 +:1000E000CC48DB2192CB9D20C7913E803E39BD2577 +:1000F000F171A47C9EB8F23E8CE4B0F15DC0FBC20D +:10010000E8E4F5BD25E4874B287E6E05F653ABED9C +:100110006EC4EF897F05B91936CF24D044C2EB579E +:10012000390618C699E2CA32BC9F96F603C3FBABE8 +:10013000015FEC14C7E6F702A55E33DD9D6F68979B +:1001400024E21C3FCC1D6318CFAA7E75EF68A47F04 +:10015000A1478C837FF45D5E93BE60D627CCFAC343 +:10016000E82B8DF75D4658451E9A95E7476C660E5D +:10017000FA2E05F041FAEE414D284F80E864843DA7 +:10018000B8E36EF4ABCC71683E78D6BCF7EAB4F94C +:100190004521FFD9E67AEEF76BDAE3D88EF4B05555 +:1001A000D0A5A4AFBC84E37318C9753B43796CA692 +:1001B0005799EF24FD05D29FA0D4723FC3D90959A6 +:1001C0003CEF48F09FCD55DCFE7D4809C42A4338FA +:1001D0005DBA9343DFA74B638A6F3AA76F3D59948B +:1001E000AAC8479579AF380EDAD9697C3EF61ACF9E +:1001F0009B6CFC67ECEF62BE41C29F91911CF25375 +:10020000607EC2CDBC9F6FBAE83758E45BF6E1EB85 +:100210000F4C11F38D8052ADD3857FDA4B650CC640 +:10022000C3A1CC56B438F47F0C513D14684914F185 +:10023000F574114F8F57029C797C4B3E3212D828AF +:10024000E625B064FE7D91D25F38994AF461DF8182 +:10025000F2E8AE63DA3BC5F0BC39E1C76F4D84E725 +:100260002DEFAA1AFA49EFCAF07D80746D0564F08B +:10027000915FCB331FCF4DAD70B8A6413FD5B7BD11 +:1002800011E3BB23EDFEFD749EAB6388DE83D00FCC +:10029000F1616B02D029E22B7ABA4685F281641CA7 +:1002A00023384673A01C0D623BEE6F36F83F23E403 +:1002B0009B90BFD42AEACDCE1DA4BFAF4DB1E317AA +:1002C0005331BF27B31EF1B25F1CBF7FCB78DC6018 +:1002D00030FE12966F6F7745F66B82BE4670083619 +:1002E0002E4DEB4DEF8A1A47715A02F6C48B8FA33D +:1002F000ACB9F13A7F206C9D72DF6B9D3B9405ECAD +:1003000052E667C6384A2DD363474488A304FD0AE2 +:10031000AE73702D8FB30C16FEFA6F1B47A99CC0ED +:10032000F5C74B8DA3C8FD5E237E9F01882DEE1976 +:10033000533C81CECB125A5F18FC1E277E44B82155 +:100340005004EA3F12F5B77677FCE949F8F5CD5D40 +:100350002FEFC652EA7133C5FB6B877DB90F73B7B8 +:1003600066AE5B21E258C6F8C33560D585FBF9F16E +:100370007B01E1F599A6F5945A8D7182C94E63FB14 +:10038000A929C6F76583627A9C1BFAE569BF4ACF43 +:10039000FDDE157F0FE3DF9B0A3B07F5C27507E61D +:1003A000CD61DCC7DD134FC2E3009EDF58597211E7 +:1003B000E28B85F4D2ADBEA5F75702FDAC0539CA74 +:1003C00079B1DB407FA1B847998EF824FDFDD1E8D3 +:1003D000E9B8339BFCFF83EBF7B74FEECBBAE300F2 +:1003E000F7C4791DE3F07B41CE730AEA2183EB5F0A +:1003F000A1F7D7CD29EE158F72EA0FB44F0EFB8E01 +:10040000608ED56341FB39A7FE557A1E559FEFC913 +:1004100047286F2D47E085CC0BDC8A798100F79C5B +:100420005AF17DE0B6DEF3DFA43C6C0ECBEFA364A3 +:1004300006B7C2C2C79772AF873F9D71BFAF9CAF6F +:100440003B2FD0346FB7FC7371F9F7FC24AF36AE95 +:1004500038EC5E86B8C701FB8E98073A5AF8B37B32 +:10046000C963E37667C56B1FE0F8976C7746197729 +:10047000626630E23DA9A9C26FD5191BCC40BF41CD +:100480006794BF9BF0D094A93F1CD78BBE8B79B3E8 +:1004900008CB68EBFCB679B37522DE24E3AD327F7E +:1004A00056E6C55E287FF6BBFAE1570A7F40E93879 +:1004B00016310E615EEF6DC23F9E55EA598178118B +:1004C0002DFE20DB7F30C01ED12F7E6442E4EF0E74 +:1004D000C8FC50586F4AB81D24FBC9BC7CF3786037 +:1004E00017AD1917E60FF436E690BF2FCCDE92F960 +:1004F000B0441F9B851FA29B0ECC7AA1888798F5DC +:1005000042191F51AAB87F02E8A30DE745BD0BF3BE +:10051000D2A59D27F34965DE28E685523CEA5BEAD1 +:1005200055DFBB3DD53885F2BA9A5CA5AF7D177B08 +:10053000EADF2718ED29AF93FB1DBC684F0DEF696B +:100540004F15957A5F447899EDAAA33FFB84F26337 +:10055000C10EDD37EEFBE01326FFD4DC311CBFA556 +:100560009C96FEB4FD432D06BFEB5475D57ECA178D +:10057000AFE5FE9674BD9DEC34BBD3EE467F8B7524 +:1005800032A7235B1EF3EB3CCE4BFE15995796EC3E +:100590005C12F1BEA9B41383D24EF4F1FBA99D6F96 +:1005A000F2B86D3CFA5BB06119976BD2DF624B1108 +:1005B000FE16533E76BCC9BF62F6B79C1E27FCB63A +:1005C000C2DFF288E2BE1B49FD575BA6FC0E41F17B +:1005D0006F0F2F8E4753FF79FF9A1F0A7FCB834EF1 +:1005E00058DFDE0F8CFE1673FC2B42DC8B9C57838E +:1005F000C6FF8EE26E12BE926EA53F2BBD9E7FBFE0 +:1006000069AABA5B41FEB2D9C9E1ABA23F2B25E48E +:10061000CF529EFE53B75F8AEEE3F68893D7BD8E26 +:10062000EBB402C3591FC9BF25E06A8E4725D68B9C +:100630007BC0DF933F2B79BC11BE050F16DE87DF31 +:10064000352EDA567E18CB51DB6FEB3B17CA92275B +:10065000EE2BC7F22FAF07B350EF34FBB114047E7B +:10066000714FF89AE128F1D45B2BF1D46927BAAD28 +:10067000E27034C32955E7789A03780A2A4237FE94 +:10068000752671FA4C9FACBD86FEB5C17956160928 +:100690008FADF5FC7B59128E5B051C936B97909F79 +:1006A000D08CA783DB2E0D3FC79AE0F7EC96C2BB38 +:1006B000116ECF3D5CFE3B2C7FEDBF2D1EE1B6E7FA +:1006C000F1FB7E28E03780BEA76B82DF03F811E9DB +:1006D0007E3DE13751E3F6F5E7A5DEB2F100DFAB91 +:1006E0008143A03F64474B81C3180732F2D3D4EF54 +:1006F000C93F15ECE6A7ECED9C4BE0A71F9BFC5314 +:10070000A93E4E37A9BE63449FE9409FB1E8AFAA16 +:10071000E57A24887D7FBC823637E7AF52AE21CBA5 +:10072000B180F0D9EAE271E7087ECA007DEFD7C454 +:1007300087D181138E772057EB107E52DE6DADE5A9 +:1007400071B4DBA678568CEF178AAB3D3F49BF6D7D +:100750003CDD5FF8D6FEC77FC6FED2FF08784AFBB5 +:100760005701DFF1FBE657813C41FBDF5A1BB4A187 +:100770005CA9A9BF55F142D9E74A4E3FA9695E86F7 +:1007800071FE9EFEBA6002EAED138776E3C37A9C9F +:1007900047E2C3C895E7EF433F57347C488F92AF99 +:1007A00074617C2835C8D7CDDDF850B7EEB2948B94 +:1007B000C787B809FCFB11DDF820E83FB536F82003 +:1007C000D2AF55E083D5057C0CE0A1221EE485E282 +:1007D0009E921E8222FFC00C9FA06F48943C8415FD +:1007E0004A492FEBBBE8FC03110F6D12F1506F3D2E +:1007F000CF97ED5C1933D5987FA0D1BAA739EB9488 +:10080000F03CFE0879B22FE3F9C938A78C6B7E5E05 +:10081000EA79059F4FCCE5E71C8C1E670AE0FD5680 +:10082000403F9709CFDF223C97F70F841E77DB14F8 +:10083000FD6D1C7784DD4F79CEA0EF1DC6765BF78A +:100840003EC9BFB72BFC90322FEF3BFBCD12ED7EA4 +:10085000BC2F29FD669B13EC3BF0BCE7B3E014FA18 +:10086000CE2FC629D0EFB43186F21A172A6078232A +:100870005FBCCAFBD1788AEB79281FD75BE170A1F6 +:100880009EDF9C34350DF946CD5A95E47A34FB460B +:10089000D25B0DF01BA2B77ACE6F5201BF08DF7C8E +:1008A0000AF19B74E0379CFFE80CF53A2BD29DB31C +:1008B00027BFD9DC0BFC2F92EF7C83708FC077941D +:1008C00009C506BE6399F01DF8CE4FC6336E1F8A68 +:1008D000FD633C80F68FF415BE7FB33EDBBD6F2316 +:1008E0007D49BAFB5F4067232744A6B3FC09DF8D2F +:1008F000CEC662FF087476E504239DE913FE67D235 +:100900005905E1DB05E8ECA3F14CD8B7D71AF48A16 +:10091000CBD5F6733938FFFFE7FCED8357723BFE0A +:1009200042F9DBF87331FE53733EF73FFCA9FF6BCE +:10093000FDA9CF4EF81EFCA9AE716EC23FB35FF5A4 +:1009400093D1FABE09BDC495259FB64A3E0DFC1849 +:10095000796F0DF033E4CFA9555D9F3ECFED4D2D5E +:10096000DE4DFE86D771BC74C1AFCD7C19F4CE3795 +:1009700026FC1DFD0D7F2FBFE14AE167BDD07DFB49 +:100980009502CED1EEDD3709FBBE09C6C07B7A5B8E +:1009900057DAFDCDB0608FD0AB47D45E773512D932 +:1009A0003BCBEC71C15EEC26F977245A1BBC2F9E21 +:1009B000CC09DF1F8B28B7BAF767D293C3ED26F7B0 +:1009C00025D84D33261AF5646B2DB773AD20EF286B +:1009D000AEAF9704905FA7FB94764C0DF6A6D42992 +:1009E0002807536B3D940F7FA9717D331E458BF310 +:1009F0007FDF717D73DEC0FF94387FD14461CF9B70 +:100A0000E2FCD2FF6A8ECB8FB0B796917CADB6E098 +:100A10005FC060CD7B3FDE71379EF71C07DDD330B2 +:100A2000E703448BDB8F48B607E3B3A3C7EFA5BF4B +:100A3000E0115BDDEB68873FD268A1F335E70DE499 +:100A400025F0FCF1B313766DA3FC1FA90F57093EE7 +:100A500053AFD8E9BB8E557EE2335E7D5723C693F4 +:100A6000539DAC1DF5ACB8896EC23F354D273E6332 +:100A7000ADF2125EC9F8444D26BF37172BF04B1D5F +:100A80005AF7168E9F7448D530BEBD119B02CF48D1 +:100A90004059897AC4180BE545B42975E4F76855BF +:100AA000DCF4F73F92F25CA41F3D95A4FD7E36AEC8 +:100AB000BF1FFF3B2507A62F49433EB8B6B1310DF6 +:100AC000EF27DE3491F3877BA79FAEA6387A2EE816 +:100AD0007F0A9586BF672BCB1DBA22FEDE929FF25E +:100AE0001161DD5BA8DF503BF9D954FD81DB900F2C +:100AF000A8974D25BC6E555C7316E079E5D8498FF3 +:100B000069CE19357B11EC6B5D3F4F59169E6BD248 +:100B100050DA677352FF44D447D70DC8A6F95B1467 +:100B20006F5916F61B6021BA56457C7E5DCE92D772 +:100B3000F0EF8034A55B18DE3B68CB39DD82EDDA5F +:100B4000C6F03F82635EAFEA32DE93C20F1F21FF21 +:100B500056D3785C5C157171D514572ED51599FF55 +:100B600048718758C1B76A7256CFA6EF2738ED2E65 +:100B700044B2A6846025E1C74A1BC3381DB3B61A28 +:100B8000F4B4BB1B8CDF7F71E619D7D3D27D3F2134 +:100B9000CB8B7C86FE062CDD5F48F2227E20BFE5F3 +:100BA000497FF1BC1E2BEA019BD717E17CFE51FE69 +:100BB000A3FC47192AFF2F0D22483C0080000000AB +:100BC0001F8B080000000000000BC55B0D701CF5BA +:100BD000757F7BBBB777279D4E7BD2C93E816C5614 +:100BE000B6446410F25AB68494D8684FDF322EBDF2 +:100BF000387C88C476CED8B8CE34932A4E49EC845B +:100C00005667EB64C95FB2A414E44C3AD3B34932DB +:100C10006DF08042661AF33967700821D028811080 +:100C200032930461885B529A310127A2434BDF7BE8 +:100C3000FF5DDDEDEAE4AFB81331CCDFFFDDFFFE91 +:100C40003FDEE7EFBDF73F00F0C00200D90F003AEA +:100C5000C0A6224F122200E7AA200D95D8F74E9782 +:100C60006941800FE9AF25DB1EE807C8F8B2FD60D7 +:100C7000AD0A660DF0DF87A271CD3B6E5AF3C29FBD +:100C800073DEE16AB5371D9C3BAF3DAED594001ACB +:100C9000F2AE03D225AD73E6673A8E4FFE4C866AFC +:100CA0007DEE7AEEEFEDEF3615AD2F86DAFFBFF170 +:100CB000F3D175A9E90128137D68C47353BB44744B +:100CC00075A48302820E039D8DE90CFE73424A0CCB +:100CD00057D2F9C21EE39B30970E762B6B73F897B1 +:100CE0009D5F16D347ECF9710BF2CE801908D12B1A +:100CF000FC0E69AFE1B63F449628110F3F076BBE6B +:100D000028C0B31FE2FE8E67F905DA82ECBCF2065A +:100D100095C72F57FB5E6C5885CF5E918D6FEAD9D2 +:100D200079793F95C00B80FD5D65F6BD62ADFB91A5 +:100D3000232A64ECF1F8FF0933CC749AD8783F2465 +:100D400090BE3FDFF089E2441E39B0DB6569E7F70A +:100D50006FE09CC07483F437F1DFA95F8C4ABCF864 +:100D600009F13CB5424BEFC7E7FBA5F4FEEB68DCAD +:100D7000DD82BE361F0A2D3EE05FB40AE9E8B5F811 +:100D8000E4759F0BFF94054C278B38397C58C27350 +:100D900054D1B907ECF974230348A703CBEB56EC05 +:100DA000D7E9FCA3FFF26DDCC791E37BDEFA36BE28 +:100DB0000ED4D68D34E17E0A0C8F21933C7FEAC499 +:100DC0000964170CD5DE334AD36E1D954C0DDFFB3D +:100DD000B5E03199CEE8974C9A4F39BC90CF13DDEE +:100DE000EA948309C958504EE71B9380F85268383B +:100DF000DFFBF49CF3E0FF4788CF2C9F39CF916E47 +:100E000048BDDEC9DAB9747FC5926705C727ED7999 +:100E1000912EE35EFD16A2F3F83E199238E5F82E06 +:100E2000548AAB007E6B4E7E7A3732FD9E412FF3A3 +:100E30006122A6A6251C3F51A4DDDE4BFD328F7139 +:100E40008C898AFFE3B946975DCBE7B2D7FB6C8B01 +:100E5000CEEB8DC51694933EE2B8F2F80D73E5CF54 +:100E6000BDFF4B95BFED668925EFA340F3C3E42D8D +:100E70001ED227BF35E63A79B27E09ADF7731984E1 +:100E8000DCF441BC682E7D06C91E7C242B27AA25D4 +:100E9000477B23EB7F4CD3CF27CF6A7ACAACACA376 +:100EA00075A08FE8BE2CEADC9F3DEE7316BF7C690F +:100EB000C87843D4664CA8A376CA94B03DB7E10B7A +:100EC000DA5A7DFE757C90336F25CD077C6E2F241A +:100ED0009858C4573387AF7B0AEBEE24BE0CDEACC8 +:100EE00002CB9F9BCE17E8AB4AE6A4142279F80800 +:100EF000CB4712E5A31AE7F1469D72187F72154C95 +:100F000007059F92FCBCDB243E255ABCB376C89FE4 +:100F1000632F41DFFD1B19E7FB6AB7AAEFC77D7E90 +:100F200035BEEDBEDB48CF5F900D89DFEB6C0FEF78 +:100F3000B1D680D109968762CBEFEC3C71EF6BCFD5 +:100F4000138FBAD5D7896EA4C7B37411F6D9F43705 +:100F500066D73BDC747A7829D221359C7FFEBB4A68 +:100F6000F5CF11FD6C3ACF37EFACFDDE7972B27D73 +:100F700065B63F529008C4F09C2341038D00BD3FED +:100F8000C5EF6115CA65F9FCFC448AB23CBC46FF5A +:100F9000C4713DEDA616C3BE7C02B7BE1CED6291C6 +:100FA0007ECB7A7CD511797D23D17F6BD0A3C939D3 +:100FB000FA3570D00B99201102D745B95B07D31BC6 +:100FC000D7E338A8F2B29CCB9115FC7C4B515CF175 +:100FD000607B6D6C09AF677FDF03FFA0ECC0E7CBE0 +:100FE000BDDA2B2427A988443BC2E74840DCFA5AE3 +:100FF00005CC10B65D7ACC4F7EADFB095A08A02512 +:101000003C1E21BF54F7D8918A04E975D29CAA41AD +:10101000FE842D765DEF9B8AB7E17C032FCAC61E46 +:10102000EC8783DBD601CA91F47090EDC400DA79C5 +:101030001FF25D0976BE45CFD79C0568CF91A79674 +:10104000193FB4E7D8BD18CE9CDB6FF3973BC6774A +:1010500068958EF732984606E9D4155DE61857D4A0 +:10106000B04AA3FDF6E82B1CCF6FAE69767C0FED7E +:10107000CAE969ECAFC6FF88EF32883EBFAF249C57 +:1010800080FD9CEF15C8E9E3FBB5B1A2C819724A0F +:1010900037C28DA447C8976307C8FEF4FAD96F0D0D +:1010A00078E184540CA4FA49A827629BECEF254B05 +:1010B0005E93B14AE693147CF67D96C327A63D84E1 +:1010C000B3E031A827FBFA8F9A7ED28343AEA629DC +:1010D000F1FB280ABA8E7C4218960CD4F37373691C +:1010E00009F93929D983FD45382E2A44119EA37167 +:1010F0007ED8FD15310E16D1380D9215D8D70C2893 +:1011000020BE56E03C9F2DE1EF923DD677D788EF89 +:1011100092C52562FEBA7AF6A3990E6C8F82013EC3 +:10112000B63F71044D6445FAB8BD867685CF1F0081 +:10113000A39EFAD530CD760AD92F517F214C6AC2B1 +:10114000C86784DD9E56C267FCC2EEE7D397ACDE6B +:101150002870C6E6070EBEBDC5FC12E9CDED773698 +:101160009C1777283B9F71E8ED23315DF8C39D5DA7 +:10117000AC27CACE67F9FD4BB1F81E9A8F48EFAF86 +:101180009F4BEF3A350364BF523130923845EAD174 +:10119000B5D1CDC8DFE4A37EA31AAE1C3F2E950FB8 +:1011A00069D00A88AE72DFE5F201D8CF074FF88F19 +:1011B000EE676134D94FFE097CF9F6E5F0C5CD0F35 +:1011C000B8B714A0F9C276F4EB5226202D657A98B0 +:1011D000D1FA2CFDB19F5C66D1ABC4E2872CDA8CCE +:1011E0006C3D574AE6E70BCD575A92E5CF85F8128A +:1011F0008DE3FBFA2C7FE43E938967FB691F9C65B6 +:101200007CBB4432985F4BE5B887FA8552C6023DF5 +:1012100069F69B21D0983F57411FB711EFF466C67E +:10122000C33B7121C2B31FA097CD89C752C1567F5E +:1012300025D9D71AC5F060BFB6C8134F231DAF56C6 +:101240002043E72B572049F61C9101CF9F7A14BD0C +:1012500015FA9914BA690F7DB7CB9F4E49D9F5EBB2 +:101260002CBBFDE3A26F69D3B5593A9F26FBB55C51 +:10127000D0C3C3F6673243DF47BBC118D0E7DA33C8 +:101280001C97942D3B45ED267AD1CC744B86B02F1C +:101290000DFFE07DC219349F82FDEFC512EF923F32 +:1012A000259C1E2C61BB345D48C07A2E2E30095718 +:1012B0006CB6D6E9BD495F1CC77D6E1EF6BD4EF308 +:1012C00041CAE7C405EEEF750972BFB7BF9B952B06 +:1012D000F7F797A907B0B3ECA27040ECE1D5C5D3FE +:1012E0007970FB2CCE243D29CDFD4EF0498D24187C +:1012F00077A8A42FA5179EC7EBC22FF63C5E145CFF +:101300009AC76BE117DB4F6D83B35E65A9B54FA438 +:10131000D716B0FF224CCF4D16FD3E4DFE2A44F4A9 +:10132000C44005CFBD15E22AC9ED5F2184261CBF4C +:1013300064DFD610E30568D7883E52E663F287D7AC +:101340005F021D2D3A6DCABCE5D5C92EED2C823742 +:1013500072E337EBFDBB1B3E21E274BFBFCA9F1394 +:101360001F169EF8A09F8CFA9EC2BF7FB105B73EA4 +:10137000F8926CC895F45EE0E60008FF5D487A8A52 +:10138000FB2E7CE2CCFFD0F84217AEA69921675E17 +:101390004FE141C6B3852155679CED92331B47C38E +:1013A000070207072DEAE5CC2B115EB6E31E9E5718 +:1013B0009ABBEE0D163EC757B10F2F02CFBB713A45 +:1013C000CCE273F13E1854859E609C9971C4C17A39 +:1013D0005E3DB3F76D7F57A6C62B8DDA3CDF5B7C95 +:1013E000A8A5401CEDC2C20A48EFC6FD0E0FEF884B +:1013F00015627FAC0C748C3061A8F38B12E18DD632 +:101400008810A57093C085B404D8713CFE85FF4355 +:10141000DF5F83EFB755040DDC192C7C1B7132CED6 +:10142000737785DF30F1410AC4FB649347C4934965 +:101430007899F0E8568B3FDE2704CE64DEA01E1EAE +:101440006C15F86AEB89CFAE23FE8E94DC6A64706B +:10145000DC56B44FA584C746BD8CE710D73970BFA2 +:10146000AF290707E2FF771FF13AFA5E174E3CD02B +:101470008A3810E5DBC681F7B702EB19ED8BFCC9A2 +:10148000955A078211B6A73728539E7CF9379B1FC0 +:1014900036FE7EB24CD0D9FB9EA00B06CC3BE8B901 +:1014A000EF3D118FA1010F362C20EF2FE8E76B40A5 +:1014B000FAD0D3F7843FC02F79DF26FE47FB76E3CF +:1014C000619F0B0FBBF76BF3E1619B3E8DD048F43E +:1014D000417CCE38C13E8FFB1C4F607CDE8E42F1DA +:1014E00054BF9FDB4CBFC6EDD3FD516E4FF5EBD023 +:1014F0008E00ECD9FE1A6E9FEB37F8F9F3FD4DDC48 +:10150000DA74984B1F91D7BCC6DAB3523B15273F0C +:101510007A55BB875561EC5E0FD3ED1CCA27295F56 +:10152000C8A0DC1B8EEFF6A429A4B7E39F8596BC68 +:101530005EEF3B7BD287E347CAC1D883DF2F6CDAEB +:10154000C672B6E6AC27AB2740714E81234F10839D +:101550005247BFCD7FB5637C87B6D4F1BE2436CD6C +:1015600076AA2B7ABD639CCDE77FA2380BF737D6DE +:101570007E5A23BAF6E82B1DE3947B91FF7514FF86 +:101580007CCC312FC8EB0CB2D3251B9C721872F1A6 +:1015900055DD7EFE38C8E6F3DBADCE78683EFEBA98 +:1015A000E5D5A66BC92C5D455C99A2B812E95AA293 +:1015B00009BADAE71DB1CE6BAFAB3489F35DE9F858 +:1015C0003244F16565BEF8F24D8BCE17882FBB9D76 +:1015D000F1A59BAE178A2F17B439EDCAC5D273D3C4 +:1015E0006291772B7941E6B845EEEE633F583A2594 +:1015F0001B5D64122D5C56443600C76D6A50D3845F +:1016000033C7603A4AFEFCB0845445792BAD35CAE5 +:10161000C9CE3C14365EE925DCD823F280CFC46EF7 +:101620008F12EE18DC7D348ACE0A9ADB3C6CEF46D2 +:101630006367387FA1E8C0F90B6CCD741E7C628FA4 +:10164000B7F38D8737AA6909C71FB6F28D877B6606 +:10165000F38D5CDF986810F9C68FB6E9569E29199C +:10166000A578E5AB1B1BCBD95929D8BF81861BAC0C +:1016700027FB035A88E2E8D4468F46E79257DDFFFE +:1016800005928F4352DFBE2A8ADFCA3C9C774D8584 +:101690001BCB37E3387913C218EA6F6C7C956CF674 +:1016A0004499BEAF8ABE0F5731FD0657DFEEA775CE +:1016B00046C20B7A283F32D2E1611EC98433423CD4 +:1016C0004FCDF9E21E771D40268B4BF15BC4935141 +:1016D000C95F11FEC8C9FBDBFCDF1F56393FBBA544 +:1016E000EDC1A3C92A7ECCF66BA15D97D9D8CA7982 +:1016F000E6738427A4F9EB327BAD7CE7ACDF893A53 +:10170000F793671DC605765D82FE743B4F8B7FA9FC +:101710005B3AD3E447C721DE4DF633193C7F1D44C5 +:10172000099EBF0E325FDD63579BC8A37E99F82EDA +:10173000EA338E7A89D26DD545ACF8F530E5C349E8 +:101740001E5C75127B1F03D67CA9593972D54D5684 +:10175000ABD67C06E4CB5FFFA9F593FBDB44BDE68B +:1017600052EB26DF6D03B15F2BDFEDB5F87F9D3CBB +:10177000B983E4F1CF9DEFFE6EDB95CD77CFAD134E +:10178000A5595FE0C4D93758AF972DB0F0CBF9EB2E +:1017900040FB09E823FFC657202EA5FA87D54FDE68 +:1017A00020E675D78502561EE5876D4B45BC45F68C +:1017B0008498AB188B89AE41E53B490DCF51101C85 +:1017C0008330B6BEC8E624B52D8B75AE0F8D2FF3D2 +:1017D000B0BF1A2F4A1C1DA4FD2F0BE6D58B572D29 +:1017E000FB376CD56F48803DA46F92AD1C90F02004 +:1017F0009F2640F0F9EDB6308F57B4D1A6BB506E9E +:10180000DE247928E3F3E4ADFF9C6913F59F9CF98E +:10181000BF41729AB226A77936E33CFF65C923908F +:10182000E35840C18E58CFAF8F36112EF85D9B26FE +:10183000DE2B2B0CD287F170FEF57E679D072815F5 +:10184000D398C5470B378879C02FBE3F2C9DED3DFF +:10185000BD8AF9CAFA44FBA0F7EEFA977BFE408DE9 +:1018600033BE512B9CE33F983D87332E3A344F7D56 +:101870006C51BB90D796C542CE483EF6E4910FB767 +:10188000BEAB94F7A478AA3D6CAD27EC4E50996A94 +:10189000A57827580B06D71495937CDEF893552727 +:1018A000A657919D0F191407297E3495F5D938D183 +:1018B0007DEE0BC5798A02496FFDDC780FE7358B29 +:1018C000EB859F49E6CC774DBB901339371EACA40E +:1018D0007044BF85EB785407A4FE2E5F6F3E3F5DDA +:1018E000DD76FEBACE9138C61114A43E7C70DF16A8 +:1018F000ECBFAB79341F8FD1F3D67534AB3F5BD7D8 +:10190000895F5C5D67B4BDA4A7EA52EA3AF3CC3BB9 +:10191000EB8FE7D675DADBF19C6341515F99ADEB54 +:10192000DC1AB9A87C0E587EB9C4B2CB453D561C12 +:10193000B153E238E2E9867F3FB09CE4ACC1CB72A0 +:1019400000072720574FD66DD0BF564A7EE6551F59 +:10195000540BBB66D27C765C6CD34FB5E66F7DF0E2 +:101960000585C68F977B1A793EC8F83C5CEC4EAA79 +:10197000562B53BB5CCDC8C5346F095875F48C44E5 +:10198000CF6348ACDCF86064E6A76DC59427098294 +:1019900041266824A6ED2EA67F501588F04EA59E00 +:1019A000267BDBE62F74D8FF911E55D8D76A715F6E +:1019B00066FCA4FEB5AD387E68678071D3A10A8F3E +:1019C000D0AFA4C4F5E40ECD19F78C4F2E1178ECEE +:1019D000A0D7A07B22C727C5F82DB1C6B4CCB8DBF1 +:1019E0001917F5E8CEB8684B79FD2B841761D0CB79 +:1019F000F978CDC2B537D738E3A4A2CABEE708A7A5 +:101A00006C1A1478786FB464C116B47FBF6AD71D9E +:101A100071E2E6C1BBB96E34A802D7534736AAAC0F +:101A20001F23DED78F6C61DC58C0749CD8A8962722 +:101A300072F4A5B4C367DD8B10F803E1656232CFA1 +:101A4000FBD20E617750B0D98FDBF2F2179F117481 +:101A50000E55405A271CD7B3234371E578059E09DC +:101A6000DF0F46AB7A4ED2FA2FCB40E774CB6165DD +:101A70004735EBE9AC3F6DF238E8E4F5C5FB687E2D +:101A8000B81974B26BEDDDD8A73CC00615283FE04D +:101A90008BFE2D9FB704FB01ECFBBB47930AF6FDC1 +:101AA000558995848B9FD975C7702C42FE4EE8B737 +:101AB0006FC3B6F82768FC2A2F04687FA04B51DA61 +:101AC0005F52DC6770EBC3DED4F7DB894F7B0D8997 +:101AD00059B4A967FD76BEB7142960DC34EA8D6F6E +:101AE000667B749B5F4BB20F9CE638C2FB151F9060 +:101AF000DC4DECFA4D19E1EF1FB58BBA664077C6A5 +:101B0000D77E1865BFBDDA9CDA40DFAD6E52A9E220 +:101B1000014F379F61BE4D34F80C1FEE63A259622E +:101B20003AFFA1C19BA6759E52A7645AF7A93FE050 +:101B3000DA95F9F43BBF5ED97AE41E3FD2B4DE4FAA +:101B400072B117A66E25FA2467449ECA3D2EDE2187 +:101B5000FCD5DED46D350AE7B354AEB72B670DB3B1 +:101B600018670FCFC4FF9972AFC97645C449E59E87 +:101B7000A484F30DF5887B194345896192E721948C +:101B80007B8E9322E23ED27879C4D89FB3DE78F37D +:101B9000ED3564CF5E6C0830BE1F38F5377711BE67 +:101BA0006F95DFFEEEC3145755A8CCCF216FDFAB86 +:101BB0001407251B02BCDF538B54F0933D88DCF5E2 +:101BC00000C5D9707C03E4CAEB44B7D0D3890AA11D +:101BD000F7D2C31B380E189764A6B359764C223C33 +:101BE000E6EBB6F34E22CF14B3CCD9C48647380FF8 +:101BF00075558FC8A3C6BAAD7C931C4CB25CDE1879 +:101C00007880F4DF54BC8EF878CD5967BC7C952B76 +:101C10005E76E7A3FEB7DDCA475879275B2E43D629 +:101C2000988926CB4EAFF2A5851CF6956BB573F55A +:101C3000FBDF2CFC3CD5EFE77B643FEDD7B81F32D0 +:101C4000DFD95D8AF3BCDC1FE5E77FB9FAA894FB16 +:101C5000DDC8AADBFC3ADB93E928CDEBB6236EB9ED +:101C6000D8DF5EE0F027F63E8B9A5BC5FDBBB36C18 +:101C700091614D70BA8D7D234C0573F17EA65FDCBA +:101C8000737BDADAE729DAA78FF264627FCFF5EBAC +:101C9000DC3EDF5FC3EDC60E10F500DB3E5C83F675 +:101CA00001E9D05E21FA640F88FF2591BB384FE629 +:101CB0008B2A1AE9BBBF623423E5D88789A2BE5FAD +:101CC000DC4D76BF2CC8F2E83ED79A0E4FDE736D1E +:101CD0006ADEC176E71CAE43F4473BB39DED10DAF4 +:101CE000055E77837A27EFC344BBC476A1EF6B7799 +:101CF000B05DF002C9B9DB0E9424857E277491BFD4 +:101D0000B3EF09CDDA055C278DEB3C8D769DFA4368 +:101D10006807689DA1E6D7FF9AD6FDC3FB057C2F17 +:101D20006A62E32B6C175E3C8736FB0ADA055B0FB1 +:101D30005F3B153B961BCF67F9BCFE8E13821E1AC4 +:101D400008BAF6C6F3C48997CA67302F0EC7A495A0 +:101D5000E93B45DD51653ACC5B774C7A0C4A0B0C7C +:101D60004C2ADD56DD11A8EE68D71F73EA8E05CE2A +:101D7000BAA39A4E31BE495B75C7DBD78ABAA35A5C +:101D8000301DCCEEC3AE370ED2A3F26C7DFEAE8E0C +:101D9000C4AE8E866C9D5197441DFCA598F9657A5A +:101DA0000E9112F6FFEE3AA55D8F4478272572EA70 +:101DB0009B75F8DC5F92AD7FB9EB99F6BD8C3A75F7 +:101DC000FAD801A4CBC09D7EC60FF6FE061EFDE824 +:101DD000AB8948F63E805DEFB4EB9976DD13F73DB5 +:101DE00096BB6F7802D8EEC063FEA3E4DFDCFBFD98 +:101DF0005E2C717F47599E7D5F647D711D58F32372 +:101E0000EE227D7ECDA2A33DEE414B1F97AB22BFBC +:101E10000D2195E39DD607832013CE2E528F915E20 +:101E20006C86E90EA2EF4058E0BCD4212FDBC9E359 +:101E30001D3AF3AF4C35F93E44D99703C66E9C2644 +:101E400075520B51FEA9A7DD3CDEC1FB18BD753DE7 +:101E5000ED03713BD9BB5F57DF17E17A3FDD7B2A8A +:101E6000A6F8CF584C7990173AF2DF576A597C762A +:101E70003DAF5BE4018ACF5201E339BE57FCA4C2F7 +:101E8000F3F5E014663DDF5F6A574B681E713F75DE +:101E900020789AF9D552ED5BC179BDA2FC71E0B30F +:101EA0001D226E5D8B73A938CF675A13DFA77D5350 +:101EB000AE34CA722CE2BB17C84E0AFB75AFA7310D +:101EC0009B072B96132FD078382E29E41F7D96DCA4 +:101ED000D871E23BADE68BC477E48749EBDBF78052 +:101EE000ECF55FB2F890EC307F4AE35EB7D6A9D349 +:101EF0009231D2C3BA04CA83C4FAE3AAC30BB9703D +:101F0000CBAB2D6FB375784B0E254DD46B51AE5EB8 +:101F1000E7FD3EA59FF448546F4F1C3D40DF5E66D1 +:101F2000BDFBEA36F32DDA77716BFC3F69DE5FEFBC +:101F3000BA83EF055FEC3D8E96C57D51AAE30F0590 +:101F4000046E7E286638ECDDA24EC19F459D022FAF +:101F50005D8F3233C5F74B0DBEF70DB09D71B46D7B +:101F60009F46FB138FBF599DFD3ED50F93540F9A8B +:101F70006F1FDE7D3B38AF3B50D1EA27FB83F6ADC8 +:101F800098FA43156634771FA92221E7C945226FC5 +:101F900041F9B464CE7DF2924E99CFD35601199295 +:101FA0001D5F50D4DD7CA8B83AFA1F9FD9C4F78BC7 +:101FB000F1F924A518AEEAD4455C1E31C0A478B36B +:101FC000220EA4DF3E2DFB3DD551DB2AFAF8BEE5FB +:101FD0007CF3C851FBFB047F7F53A7C6F3AA118F84 +:101FE000230F7021BAB9E9324874AB9E9F6EEA455F +:101FF000D34DE89D9B5E8D16BD9E097F91CF071F37 +:10200000B4B19EF9343C27B6AB3B857D9183262441 +:102010008AC846C51141529EBD0FA80E6DD359D630 +:10202000049D65AD8FBFF3551890B881E89260BAF2 +:10203000B8E9807602C84EFCF0D12311C2A72DD892 +:102040008F0AFB013E6CBFDE21F862EBE93AF849EA +:1020500050E4BF9DFEC26D4FEDF6212BFFEC7E2EAE +:10206000750584FDD0C141F722EBF70BC786EB194C +:102070001FA0FF4CD2BD98CEF2EA02EA5FE93AA275 +:10208000BB7EE8AE13BAEB8359B931FDB4CF77B557 +:10209000D3C98FE79117BB3D60E9DB60BF3FAFDE7F +:1020A0001D407D27FE0D359B49AA1BED0D4F47595D +:1020B0006E4EBEC5B858794136085F2A8AE073E78C +:1020C000A269E663579309546F3AD0DFFB9DDC7930 +:1020D000BFDE9AF84A27CA49A13669D23C41C824D2 +:1020E000C9FFAC2D35FBF2E1A621CB8EBCD31ADFA4 +:1020F0004DDFD1B575E2FF9B31730FF52FD66ECD55 +:10210000A74F8A4DBB4BD6A7D3429F9A76B03E8D40 +:1021100054F431CE1AF9894C482A8B232D7D1A6943 +:102120003EC3FA6EEB55DAB63F4D422F288F40FE84 +:102130003B5461B2DDF896A54F0AEA09E993CFD284 +:10214000A790961D4FF9F136A2333E572AA6F9BB48 +:102150005093A57FA44F41BA3F0C8C038650EF28C3 +:102160002FE2D6AF962AE1379F684D3CD449F862FA +:10217000D17ACECB0F55FCBE94F18B25FF59BC5BB9 +:10218000CFFEFCDCB0C7207DA823005D9FD503FBFC +:10219000DCAB6764C8206BD6CC48DCDE3453C86D3A +:1021A000CB4C805B73A694DBD84C98DBD699ABB94B +:1021B0006D9B29E7B67D06F56025EAC34C25B79DE2 +:1021C00033D773DB35B38CDBEE99953CAE67660590 +:1021D000B76B673EC6EDCD33CD629D1A71AE3CFA4A +:1021E0004065B02BA00F46128A480F3EF32ADB77DA +:1021F0004DE53B4AA97023D7897CCA34EBC3B1268D +:1022000061EFBB82824F6E7D78A735F1AB7CFA30EF +:102210008B6F15D088FE2A587F2EFC80F8E737F4A4 +:10222000BD8D7BD5A8C97286F8E40CF1F37271C23A +:102230002CCE5CAC321EB571E6C822C49995599C6F +:1022400039D42CE2B2D4211FC76F5B2471BFECEAF2 +:10225000B6C47FB37E82C813256EF56B849B53E1B1 +:10226000CE6890F27A7B65A07C01E2900F789F4A5D +:102270005CDC67BD487D7E3326ECBE3DBE0E4E7BEA +:10228000FA2E01C7FC9AFED93CBF5D28B95C3FEB32 +:102290006D13764113762155D137CC7569975DB0B2 +:1022A000FD2CD2C3611796765976C1D2F3920AE11A +:1022B0002F4BC82E207D9675D976C1E967151B87EF +:1022C00074DB38C4B20BDDE23BC4ED0E3F8BECF6A1 +:1022D000430E2E46395ADE950787B03FCFF1730380 +:1022E00055D531FA2D41F82CC4483C4333FA5A23D2 +:1022F0008FDF4969F5AC07279536C8CDAF5CB29E34 +:10230000856DBF63B2DF718FB3F56DE8648F38A759 +:10231000E5874EE2F9CD1C7DEBD2843F42FF73335B +:102320009DD3AD6F2D8BCD443CCF3E3FD925F0FEE4 +:102330008FD658B81771A511647C9F17377C92F817 +:10234000D7207EA7F118DA9F8EEE644AD159CF3F8D +:1023500049EBAE6E9F92290F7453D3E8CB541241D0 +:102360003DFD5457C3E5EB6953AB55EFDB592A2EBE +:102370003B5BED85E4DFC645B61EB8C73D5469F644 +:10238000E6A3C7B3163D06863D3D74E1CF968B9319 +:10239000CA52C63F79ECAD695C117B7B71F8E324CE +:1023A000FA41E2FB79F0C7817CFC9F0F7F8C77CDEF +:1023B000E28F31E2534BADC01FCF76C179E39BCBA7 +:1023C000C615B1D34CB7CBC5150F769D1F577CA74B +:1023D0004BD84D459B66FB11BA4C5CE1B613881F88 +:1023E000FE95E96308BF6BFFDE842F50E6F82FB43B +:1023F000338FD338C20D7479EC58B03529B11EC46F +:102400009FA4E7A3E61296A32BA50F88137FD09570 +:10241000D3BF905E5CF4B8C98D9C07B4EB997F0C78 +:1024200084EA283FB2D32FDA2F15848E513BD62F62 +:10243000F2D07F0C2C4E53DE6CCC0B5C3F18940A10 +:102440008C63223FBA9C7F5F037D37527BA6CBAE65 +:10245000CBFF9DA35E1AD6B63DFE6669BEFD88FB26 +:10246000BD948AFF90EF8157689C3FB7E84169208F +:10247000F6CFD5058CFF00614B538EDD4F75AC1345 +:102480007172A59FEB79322867281F3F4C6BF1FED4 +:102490007AB98E19B0FC212849FDE3BC5F9107B5DC +:1024A0007FF7B76FF5FA627109793B8FB7E57F5F08 +:1024B00070D4AFD53AF4DDF1BB6E772BAF38A5B54C +:1024C000E17EC77485EBAE078D4880EB2615227B35 +:1024D000EE5FE489A7F3E8E9B5DDB3F722785F6141 +:1024E0006B5FBE0E11AFCDB7DEFE7EE73DAB82DA8D +:1024F000B849FEC45FD91727BAF9174524CAABCE2D +:10250000D2BB5BB2EE69189916A4F7B0A587053562 +:1025100093190FD139BC6D25D1D65F938633344FD3 +:10252000ED24BC41FEA2D2DF9B6FDFD759FB1EF624 +:1025300026E38493862B15AE5F0E57E6F72F25DD35 +:10254000C2FEFA17EDE0F1B048E1FAB37B9CD22D60 +:10255000E4689FDAC7758CA145F7F37DB721FA21AE +:10256000CD47D1EEFD70E681DDF8FC50FFF6C7DF08 +:10257000F4929C26B8DD77ED7E8DEE711EAAF76889 +:1025800094870BFB337EFA7D6678B5C87396B4E307 +:10259000B8DC7855AE08909D0DADC27972E2D031AD +:1025A000D002B4EEBE906D1FA7FDC23E0A792AB2DA +:1025B000C68EAC1275A9917576FE5FF02FFB7E7CFE +:1025C000BBB82FA7EAC079685197E2D49E4EF7674F +:1025D000EBC374AE324DD4A30E59F23568E5D9DDA4 +:1025E0007439B4788AFDC9A13553BDE43F429ADFFE +:1025F000E826B93EEEDCD7DEE66907DE1869386DFD +:10260000EDDFBD3F21F7CAD36F093B69E1FE90F1D1 +:102610007BC659F63DAEAED5420F8BAD7BF4C5916E +:10262000B849F3EDBEF6B749AA131D2EB7EF167CD5 +:10263000DE790F03A6191787565B7539F96DBEFF52 +:102640000BB78A7B12F63D6F35A23AF202A5AEFBBC +:102650005921571FE40DE7BDCFB6F397479F3F952C +:10266000C3CFCF773BEF835FE8FB3FF6A79F3F8564 +:102670007E6E6CD5F9F5CFE6D3E1FE266E6D39B4EA +:10268000E5324C47AC9FFFFBB1703C6FBDE5114B91 +:102690004FDCF2EA96D3625F9CFDFEE81AE73CF756 +:1026A000597A7E9F358FBA18CA090F8D86855E8E3E +:1026B00006A0F7913CE77AAC5BE5F159B977E28285 +:1026C000A2CBC5052B5AADB8A284F56D6C55EB7342 +:1026D0002437EF915EE4D82777DEDCC6054A8FC049 +:1026E000A5CF845589FCBA169C66BC3CEBD72D1C43 +:1026F000E0F6EB7E6FB297F4CF5FA9DA7689ED470B +:102700006577E01BC920FB0329D70F1ECADCC9F37C +:10271000865D797388387F87B2B71B984E61DDB2CA +:102720002FDD8AB887356A42EE3D9A31CFDB336FB1 +:10273000E8E2DF1FD838A292DE1F9CE2DFC7C03D6F +:1027400090BBFEDE964DFC7B880BF1DDDE17DDCB0A +:10275000CAD59B4BD58B976DBD084080F4E21CDC3D +:10276000CB757418ED76F821AE282C601320FEF09E +:10277000984AA365C7A4ACBE409755DF4E883A3D42 +:102780005198BE33ACCFCAE99604C5D790E1DF1D9E +:10279000DAF6E51CFC92D74D3E2D49B3B8E96A0C38 +:1027A000DFE9F78C4B690B9A875AF7FE9780C1CF08 +:1027B000AB20CEEDB5D0C76D0D8C727B1D4C725B1E +:1027C0000B53DCD6C1596E57802ED3222BC1948176 +:1027D000AF5E26B87F2324B96D86C4FB742774B01E +:1027E0006CDB0AB257EFBBE864D3398FBE332EB42B +:1027F000E961D3FD2132D20D17E66B2A2CEC6F5B19 +:10280000D314E3D7A2A01DFF0A39B7E7990FC7BABF +:1028100071979F70D7CAB9727021DC65E3C4FF035A +:1028200008E97101B048000000000000000000004D +:102830000000001800000000000000000000004040 +:102840000000000000000000000000280000000060 +:102850000000000000000010000000000000000068 +:102860000000002000000000000000000000001038 +:102870000000000000000000000000080000000050 +:102880000000000000000000000000000000000048 +:102890000000000000000000000000000000000038 +:1028A0000000000000000000000000000000000028 +:1028B0000000000000000000000000000000000018 +:1028C0000000000000000000000000000000000008 +:1028D00000000000000000000000000000000000F8 +:1028E00000000000000000000000000000000000E8 +:1028F00000000000000000000000000000000000D8 +:1029000000000000000000000000000000000000C7 +:1029100000000000000000000000000000000000B7 +:1029200000000000000000000000000000000000A7 +:102930000000000000000000000000000000000097 +:102940000000000000000000000000000000000087 +:102950000000000000000000000000000000000077 +:102960000000000000000000000000000000000067 +:102970000000000000000000000000000000000057 +:102980000000000000000000000000000000000047 +:102990000000000000000000000090000010000097 +:1029A0000000000800009008001000000000000275 +:1029B00000009000001000000000001000009DA822 +:1029C000000000000000000880000000000000007F +:1029D0000000000080000000000000000000000077 +:1029E000800000000000000000000000000091A036 +:1029F0000000000000000008000093C00001000477 +:102A000000000001000093C8000000000000000268 +:102A1000000093D00000000000000008000093D4E4 +:102A20000000000000000002000094980000000078 +:102A300000000008000093D8000800000000000813 +:102A400000009B3800400000000000400000941887 +:102A50000008000000000008000094580008000072 +:102A600000000008000094A800C8000000000098C2 +:102A700000009638009800000000002800009678BA +:102A800000980000000000280000C0000540003051 +:102A9000000005400000CB200008000000000001FD +:102AA0000000CB2100080000000000010000200809 +:102AB00000100000000000100000200000000000D6 +:102AC0000000000800009D600008000000000002F7 +:102AD00000009DA0000000000000000100000000B8 +:102AE00000000000000000000000000000000000E6 +:102AF00000000000000000000000000000000000D6 +:102B000080000000000000000000000080000000C5 +:102B10000000000000000000800000000000000035 +:102B20000000000080000000000000000000000025 +:102B30008000000000000000000000008000000095 +:102B40000000000000000000800000000000000005 +:102B500000000000800000000000000000000000F5 +:102B60008000000000000000000000008000000065 +:102B700000000000000000008000000000000000D5 +:102B800000000000800000000000000000000000C5 +:102B900080000000000000000000000000000000B5 +:102BA0000000000000000000000000000000000025 +:102BB0000000000000000000000000000000000015 +:102BC0000000000000000000000000000000000005 +:102BD0000000000000000000800000000000000075 +:102BE0000000000080000000000000000000000065 +:102BF0008000000000000000000000000000000055 +:102C00000000000000000000800000000000000044 +:102C10000000000080000000000000000000000034 +:102C20008000000000000000000000000000000024 +:102C30000000000000000000000000000000000094 +:102C40000000000000000000000000000000000084 +:102C50000000000000000000000000000000000074 +:102C60000000000000000000000000000000000064 +:102C700000000000000012C800800000000000807A +:102C80000000000100000000000000000000A000A3 +:102C9000071000000000071000001EC80000000020 +:102CA000000000080000AEC000080000000000089E +:102CB0000000AE4000080000000000080000AE80E8 +:102CC00000080000000000080000200800100000BC +:102CD00000000010000020000000000000000008BC +:102CE0000000A01007100040000000400000AF40AE +:102CF00000080000000000010000AF4100080000D3 +:102D00000000000100001ED00000000000000001D3 +:102D100000001ED8000000000000000200001EDAC3 +:102D20000000000000000002000012B000080000D7 +:102D3000000000088000000000000000000000000B +:102D40008000000000000000000000008000000083 +:102D500000000000000000008000000000000000F3 +:102D600000000000800000000000000000000000E3 +:102D70008000000000000000000000008000000053 +:102D800000000000000000008000000000000000C3 +:102D900000000000800000000000000000000000B3 +:102DA0000000000000000000000000000000000023 +:102DB0000000000000000000000000000000000013 +:102DC0000000000000000000000000000000000003 +:102DD0000000000000000000000000008000000073 +:102DE0000000000000000000800000000000000063 +:102DF00000000000000000000000000000000000D3 +:102E000080000000000000000000000080000000C2 +:102E10000000000000000000800000000000000032 +:102E20000000000080000000000000000000000022 +:102E30000000B00000180000000000180000B300FF +:102E400000400000000000400000B300004000020D +:102E5000000000010000B30100400002000000007B +:102E600000008000004000000000004080000000E2 +:102E7000000000000000000000008000000800408A +:102E8000000000040000800400080040000000046E +:102E90000000BB0000280000000000280000BC402B +:102EA00000100000000000100000880000800000FA +:102EB0000000008000008800000800800000000280 +:102EC00000008C000020000000000020000020080E +:102ED00000100000000000100000200000000000B2 +:102EE00000000008000011080008000000000008B1 +:102EF000000011680008000000000008000011A890 +:102F00000008000000000008000012700008000027 +:102F10000000000100001271000800000000000124 +:102F200000008D00001000040000000400001320C9 +:102F300000300018000000100000132800300018B6 +:102F400000000002800000000000000000000000FF +:102F5000800000000000000000000000000011E8F8 +:102F600000000000000000018000000000000000E0 +:102F700000000000800000000000000000000000D1 +:102F80008000000000000000000000008000000041 +:102F900000000000000000008000000000000000B1 +:102FA00000000000800000000000000000000000A1 +:102FB0000000000000000000000000000000000011 +:102FC0000000000000000000000000000000000001 +:102FD00000000000000000000000000000000000F1 +:102FE00080000000000000000000000080000000E1 +:102FF00000000000000000000000000000000000D1 +:103000000000000000008308008000000000008035 +:103010000000000100000000000000000000200887 +:103020000010000000000010000020000000000060 +:103030000000000800008D100008000000000008DB +:1030400000008D700008000000000008000084509F +:10305000046000280000046000008EA0000800004A +:103060000000000100008EA1000800000000000127 +:1030700000008408000800000000000800008448E8 +:10308000000000000000000100008DF400080000B6 +:103090000000000200008DF60008000000000002A1 +:1030A00000008E04001000000000000480000000FA +:1030B0000000000000000000800000000000000090 +:1030C0000000000080000000000000000000000080 +:1030D00000000000000000000000000000000000F0 +:1030E00000000000000000000000000000000000E0 +:1030F00000000000000000000000000000000000D0 +:1031000080000000000000000000000080000000BF +:1031100000000000000000000000000000000000AF +:10312000000000008000000000000000000000001F +:10313000800000000000000000000000800000008F +:1031400000000000000000008000000000000000FF +:1031500000000000000030000040000000000008F7 +:1031600000003008004000000000002800003390FC +:1031700001C0001000000008000032000020000024 +:1031800000000020000037200000000000000008C0 +:103190000000102006200038000000080000A000F9 +:1031A000000000000000200000003EA90000000018 +:1031B0000000000100003EC8000000000000000206 +:1031C00000001C4000E00008000000088000000033 +:1031D00000000000000000000000400000080000A7 +:1031E0000000000100004001000800000000000194 +:1031F00000004040000800040000000200004060A1 +:103200000008000400000004000040000008000066 +:10321000000000040000400400080000000000045A +:10322000000040400000000000000008000040488E +:103230000000000000000008000080000000000006 +:1032400000000010000050400001000400000001D8 +:1032500000005000000000000000002000005008A6 +:1032600000100000000000040000500C00100000DE +:1032700000000001000052C7000000000000000133 +:10328000000052C6000000000000000100003000F5 +:103290000030001800000004000030040030001866 +:1032A0000000000400003008003000180000000298 +:1032B0000000300A00300018000000020000300C4E +:1032C00000300018000000010000300D0030001830 +:1032D000000000010000300E003000180000000166 +:1032E000000030100030001800000004000030140E +:1032F00000300018000000040000500001000080B1 +:1033000000080004000050040100008000080004D0 +:103310000000000A000000000000000000005068EB +:1033200001000080000000010000506901000080E1 +:10333000000000010000506C01000080000000024D +:103340000000506E0100008000000002000050707C +:1033500001000080000000040000507401000080A3 +:103360000000000400005066010000800000000220 +:103370000000506401000080000000010000506067 +:103380000100008000000002000050620100008087 +:103390000000000200005050010000800000000406 +:1033A000000050540100008000000004000050584C +:1033B00001000080000000040000505C010000805B +:1033C000000000040000507C0100008000000001AB +:1033D0000000507D01000080000000010000401846 +:1033E00000100000000000040000409000100000E9 +:1033F00000000004000040980010000000000004DD +:103400000000411000000000000000020000411216 +:103410000000000000000002000041140000000055 +:103420000000000200004116000000000000000241 +:103430000000604000080000000000020000604240 +:1034400000080000000000020000604400080000C6 +:103450000000000400006080000800000000000878 +:10346000000060C00040000800000008000060008C +:1034700000080000000000020000600200080000D8 +:1034800000000001000060040008000000000002CD +:103490000000634000080000000000080000638096 +:1034A0000008000000000004000063840008000021 +:1034B00000000001000063C00008000000000002DE +:1034C000000063C400080000000000020000640067 +:1034D0000008000000000004000070000010000060 +:1034E0000000000400007004001000000000000450 +:1034F00000007008001000000000000400007000D0 +:103500000008000000000002000070020008000037 +:10351000000000010000700400080000000000022C +:10352000000070400008000000000002000070442D +:1035300000080000000000020000704600080000C3 +:1035400000000002000076480008000000000008AB +:10355000000070800008000000000002000070847D +:10356000000800000000000200007688000800004B +:10357000000000080000804000080000000000017A +:1035800000008041000800000000000100008042AF +:103590000008000000000001000080430008000057 +:1035A0000000000100008000000800000000000290 +:1035B00000008002000800000000000100008004FC +:1035C0000008000000000002000080C000080000A9 +:1035D00000000002000080C200080000000000029D +:1035E000000080C40008000000000002000080808D +:1035F00000080000000000010000808100080000B9 +:1036000000000001000080820008000000000001AE +:10361000000080830008000000000001000080849A +:103620000008000000000001000080850008000084 +:10363000000000010000808600080000000000017A +:1036400000006000000800000000000200006002AE +:1036500000080000000000010000600400080000F5 +:10366000000000020000604200C0001800000002DC +:103670000000604000C00018000000020000604C24 +:1036800000C00018000000080000604400C00018DE +:10369000000000080000605700C000180000000192 +:1036A0000000605400C000180000000200006056D6 +:1036B00000C0001800000001000066400008000083 +:1036C00000000008000066800008000000000008FC +:1036D000000066C000080000000000080000D94299 +:1036E00000180000000000020000DE4000000000A2 +:1036F000000000000000E0000000000000000004E6 +:103700000000DD4000000000000000040000DD4477 +:1037100000000000000000040000DD480000000080 +:10372000000000040000DD4C000000000000000468 +:103730000000DD5000000000000000040000DD5427 +:1037400000000000000000040000DD580000000040 +:10375000000000040000DD40000000000000002028 +:103760000000DA0000000000000000040000DA00A1 +:1037700000000000000000680000BB6000000000C6 +:10378000000000000000D000000000000000000465 +:103790000000B0C000000000000000040000B0C441 +:1037A00000000000000000040000B0C8000000009D +:1037B000000000040000B0C0000000000000001085 +:1037C0000000D6B000000000000000040000D6B4E5 +:1037D00000000000000000040000D6B80000000057 +:1037E000000000040000D6BC00000000000000043F +:1037F0000000D6B000000000000000100000D34818 +:1038000000000000000000080000D3580000000085 +:103810000000008000000010000000000000000018 +:103820000000D35800000000000000080000000065 +:0838300006020900000000007F +:00000001FF diff --git a/firmware/bnx2x/bnx2x-e2-6.2.5.0.fw.ihex b/firmware/bnx2x/bnx2x-e2-6.2.5.0.fw.ihex deleted file mode 100644 index aef9aa622420..000000000000 --- a/firmware/bnx2x/bnx2x-e2-6.2.5.0.fw.ihex +++ /dev/null @@ -1,15456 +0,0 @@ -:1000000000005310000000680000070C000053803F -:100010000000318000005A90000000B000008C18F1 -:100020000000C13400008CD0000000D800014E0850 -:100030000000F1F000014EE800000074000240E012 -:100040000000525C00024158000000B8000293B862 -:100050000001213C0002947800000FFC0003B5B8B9 -:10006000000000040003C5B8020400480000000FAF -:1000700002040054000000450204005C0000000679 -:100080000204007000000004020400780000000078 -:100090000204007C121700000204008022170000F6 -:1000A00002040084321700000604008800000005E6 -:1000B0000204009C12150000020400A0221500009A -:1000C000020400A432150000060400A80000000489 -:1000D000020400B802100000020400BC001000007E -:1000E000020400C010100000020400C42010000030 -:1000F000020400C830100000020400CC40100000D0 -:10010000060400D000000003020400DC0010000020 -:10011000020400E012140000020400E422140000B3 -:10012000020400E832140000020400EC4214000053 -:10013000060400F000000003010401240000000098 -:1001400001040128000000000104012C000000004F -:100150000104013000000000020401D00000890603 -:1001600002040258000000360204025C000000365F -:10017000020402600810000002040264081000007B -:1001800002040004000000FF02040008000000FF59 -:100190000204000C000000FF02040010000000FF39 -:1001A000020400140000007F02040018000000FF99 -:1001B0000204001C000000FF02040020000000FFF9 -:1001C000020400240000003E020400280000000099 -:1001D0000204002C0000003F020400300000003F39 -:1001E000020400340000003F020400380000003F19 -:1001F0000204003C0000003F020400400000003FF9 -:10020000020400440000003F020404CC000000018E -:1002100002042008000002110204200C0000020069 -:10022000020420100000020402042014000002193D -:100230000204201C0000FFFF020420200000FFFF3A -:10024000020420240000FFFF020420280000FFFF1A -:1002500002042038000000200604203C0000000FAB -:1002600002042078000000210604207C0000000F1A -:10027000020420B800000001060420BC0000000FAA -:10028000020420F800000001060420FC0000003FEA -:10029000020421F800000001060421FC0000000F08 -:1002A0000204223807FFFFFF0204223C0000007F07 -:1002B0000204224007FFFFFF020422440000003F27 -:1002C00001042248000000000104224C000000004C -:1002D000010422500000000001042254000000002C -:1002E00001042258000000000104225C000000000C -:1002F00001042260000000000104226400000000EC -:1003000001042268000000000104226C00000000CB -:1003100001042270000000000104227400000000AB -:1003200001042278000000000104227C000000008B -:10033000020422C00000FFFF020422C40000FFFFED -:10034000020422C80000FFFF020422CC0000FFFFCD -:100350000C042000000003E80A0420000000000153 -:100360000B042000000000030605400000000D0003 -:100370000205004400000020020500480000003291 -:1003800002050090021500200205009402150020CD -:1003900002050098000000300205009C08100000D3 -:1003A000020500A000000036020500A40000003095 -:1003B000020500A800000031020500B000000004A2 -:1003C000020500B400000005020500C000000000A6 -:1003D000020500C400000004020500D40000000172 -:1003E00002050114000000010205011C00000001CB -:1003F00002050120000000020205020400000001C5 -:100400000205020C0000004002050210000000403E -:100410000205021C00000020020502200000001C52 -:100420000205022400000020060502400000000A28 -:1004300004050280002000000205005000000007B3 -:1004400002050054000000070205005800000000EB -:100450000205005C000000080205006000000001C9 -:100460000605006400000003020500D80000000635 -:100470000205000400000001020500080000000160 -:100480000205000C00000001020500100000000140 -:100490000205001400000001020500180000000120 -:1004A0000205001C00000001020500200000000100 -:1004B00002050024000000010205002800000001E0 -:1004C0000205002C000000010205003000000001C0 -:1004D00002050034000000010205003800000001A0 -:1004E0000205003C00000001020500400000000180 -:1004F000020500E00000000D020500E80000000019 -:10050000020500F000000000020500F800000000F5 -:10051000020500E40000002D020500EC00000020B0 -:10052000020500F400000020020500FC000000208D -:10053000020500E00000001D020500E800000010B8 -:10054000020500F000000010020500F80000001095 -:10055000020500E40000003D020500EC0000003050 -:10056000020500F400000030020500FC000000302D -:10057000020500E00000004D020500E80000004018 -:10058000020500F000000040020500F800000040F5 -:10059000020500E40000006D020500EC00000060B0 -:1005A000020500F400000060020500FC000000608D -:1005B000020500E00000005D020500E800000050B8 -:1005C000020500F000000050020500F80000005095 -:1005D000020500E40000007D020500EC0000007050 -:1005E000020500F400000070020500FC000000702D -:1005F0000406100002000020020600DC00000001DA -:100600000406020000030220020600DC00000000D5 -:100610000718040000AD0000081807D800050223E1 -:10062000071C000029920000071C8000312A0A657F -:10063000071D000034A316B0071D80002E7A23D9B1 -:10064000071E000003502F78081E07F03F02022506 -:10065000021800BC0000003001180000000000007B -:10066000011800040000000001180008000000004C -:100670000118000C0000000001180010000000002C -:100680000118001400000000021800200000000102 -:1006900002180024000000020218002800000003D5 -:1006A0000218002C000000000218003000000004B6 -:1006B0000218003400000001021800380000000099 -:1006C0000218003C00000001021800400000000475 -:1006D0000218004400000000021800480000000159 -:1006E0000218004C00000003021800500000000037 -:1006F0000218005400000001021800580000000415 -:100700000218005C000000000218006000000001F8 -:1007100002180064000000030218006800000000D6 -:100720000218006C000000010218007000000004B4 -:100730000218007400000000021800780000000495 -:100740000218007C00000003061800800000000270 -:10075000021800A400007FFF021800A8000003FF99 -:1007600002180224000000000218023400000000F9 -:100770000218024C00000000021802E4000000FF12 -:100780000618100000000400021B8BC000000001CE -:10079000021B800000000034021B80400000001893 -:1007A000021B80800000000C021B80C000000020A3 -:1007B0000C1B8300000864700A1B830000000157B3 -:1007C0000B1B83000000055F0A1B83400000000034 -:1007D0000C1B8340000002260B1B8340000000011D -:1007E000021B838000086470021B83C00000022685 -:1007F000021B1480000000010A1B1480000000008E -:10080000021B944000000001061B944800000002F7 -:10081000061A1000000002B3041A1ACC00010227C5 -:10082000061A1AD000000008061A2008000000C8A6 -:10083000061A200000000002041A1BF8009002288B -:10084000061A371800000004061A371000000002CC -:10085000061A500000000002061A500800000004AA -:10086000061A501800000004061A50280000000460 -:10087000061A503800000004061A50480000000410 -:10088000061A505800000004061A506800000004C0 -:10089000061A507800000002041A52C0000202B882 -:1008A000061A405000000006041A4068000202BA0E -:1008B000041A4040000402BC041A8000000102C077 -:1008C000061A800400000003041A8010000102C10F -:1008D000061A801400000003041A8020000102C2DE -:1008E000061A802400000003041A8030000102C3AD -:1008F000061A803400000003041A8040000102C47C -:10090000061A804400000003041A8050000102C54A -:10091000061A805400000003041A8060000102C619 -:10092000061A806400000003041A8070000102C7E8 -:10093000061A807400000003041A8080000102C8B7 -:10094000061A808400000003041A8090000102C986 -:10095000061A809400000003041A80A0000102CA55 -:10096000061A80A400000003041A80B0000102CB24 -:10097000061A80B400000003041A80C0000102CCF3 -:10098000061A80C400000003041A80D0000102CDC2 -:10099000061A80D400000003041A80E0000102CE91 -:1009A000061A80E400000003041A80F0000102CF60 -:1009B000061A80F400000003041A8100000102D02E -:1009C000061A810400000003041A8110000102D1FC -:1009D000061A811400000003041A8120000102D2CB -:1009E000061A812400000003041A8130000102D39A -:1009F000061A813400000003041A8140000102D469 -:100A0000061A814400000003041A8150000102D537 -:100A1000061A815400000003041A8160000102D606 -:100A2000061A816400000003041A8170000102D7D5 -:100A3000061A817400000003041A8180000102D8A4 -:100A4000061A818400000003041A8190000102D973 -:100A5000061A819400000003041A81A0000102DA42 -:100A6000061A81A400000003041A81B0000102DB11 -:100A7000061A81B400000003041A81C0000102DCE0 -:100A8000061A81C400000003041A81D0000102DDAF -:100A9000061A81D400000003041A81E0000102DE7E -:100AA000061A81E400000003041A81F0000102DF4D -:100AB000061A81F400000003041A8200000102E01B -:100AC000061A820400000003041A8210000102E1E9 -:100AD000061A821400000003041A8220000102E2B8 -:100AE000061A822400000003041A8230000102E387 -:100AF000061A823400000003041A8240000102E456 -:100B0000061A824400000003041A8250000102E524 -:100B1000061A825400000003041A8260000102E6F3 -:100B2000061A826400000003041A8270000102E7C2 -:100B3000061A827400000003041A8280000102E891 -:100B4000061A828400000003041A8290000102E960 -:100B5000061A829400000003041A82A0000102EA2F -:100B6000061A82A400000003041A82B0000102EBFE -:100B7000061A82B400000003041A82C0000102ECCD -:100B8000061A82C400000003041A82D0000102ED9C -:100B9000061A82D400000003041A82E0000102EE6B -:100BA000061A82E400000003041A82F0000102EF3A -:100BB000061A82F400000003041A8300000102F008 -:100BC000061A830400000003041A8310000102F1D6 -:100BD000061A831400000003041A8320000102F2A5 -:100BE000061A832400000003041A8330000102F374 -:100BF000061A833400000003041A8340000102F443 -:100C0000061A834400000003041A8350000102F511 -:100C1000061A835400000003041A8360000102F6E0 -:100C2000061A836400000003041A8370000102F7AF -:100C3000061A837400000003041A8380000102F87E -:100C4000061A838400000003041A8390000102F94D -:100C5000061A839400000003041A83A0000102FA1C -:100C6000061A83A400000003041A83B0000102FBEB -:100C7000061A83B400000003041A83C0000102FCBA -:100C8000061A83C400000003041A83D0000102FD89 -:100C9000061A83D400000003041A83E0000102FE58 -:100CA000061A83E400000003041A83F0000102FF27 -:100CB000061A83F400000003041A840000010300F4 -:100CC000061A840400000003041A841000010301C2 -:100CD000061A841400000003041A84200001030291 -:100CE000061A842400000003041A84300001030360 -:100CF000061A843400000003041A8440000103042F -:100D0000061A844400000003041A845000010305FD -:100D1000061A845400000003041A846000010306CC -:100D2000061A846400000003041A8470000103079B -:100D3000061A847400000003041A8480000103086A -:100D4000061A848400000003041A84900001030939 -:100D5000061A849400000003041A84A00001030A08 -:100D6000061A84A400000003041A84B00001030BD7 -:100D7000061A84B400000003041A84C00001030CA6 -:100D8000061A84C400000003041A84D00001030D75 -:100D9000061A84D400000003041A84E00001030E44 -:100DA000061A84E400000003041A84F00001030F13 -:100DB000061A84F400000003041A850000010310E1 -:100DC000061A850400000003041A851000010311AF -:100DD000061A851400000003041A8520000103127E -:100DE000061A852400000003041A8530000103134D -:100DF000061A853400000003041A8540000103141C -:100E0000061A854400000003041A855000010315EA -:100E1000061A855400000003041A856000010316B9 -:100E2000061A856400000003041A85700001031788 -:100E3000061A857400000003041A85800001031857 -:100E4000061A858400000003041A85900001031926 -:100E5000061A859400000003041A85A00001031AF5 -:100E6000061A85A400000003041A85B00001031BC4 -:100E7000061A85B400000003041A85C00001031C93 -:100E8000061A85C400000003041A85D00001031D62 -:100E9000061A85D400000003041A85E00001031E31 -:100EA000061A85E400000003041A85F00001031F00 -:100EB000061A85F400000003041A860000010320CE -:100EC000061A860400000003041A8610000103219C -:100ED000061A861400000003041A8620000103226B -:100EE000061A862400000003041A8630000103233A -:100EF000061A863400000003041A86400001032409 -:100F0000061A864400000003041A865000010325D7 -:100F1000061A865400000003041A866000010326A6 -:100F2000061A866400000003041A86700001032775 -:100F3000061A867400000003041A86800001032844 -:100F4000061A868400000003041A86900001032913 -:100F5000061A869400000003041A86A00001032AE2 -:100F6000061A86A400000003041A86B00001032BB1 -:100F7000061A86B400000003041A86C00001032C80 -:100F8000061A86C400000003041A86D00001032D4F -:100F9000061A86D400000003041A86E00001032E1E -:100FA000061A86E400000003041A86F00001032FED -:100FB000061A86F400000003041A870000010330BB -:100FC000061A870400000003041A87100001033189 -:100FD000061A871400000003041A87200001033258 -:100FE000061A872400000003041A87300001033327 -:100FF000061A873400000003041A874000010334F6 -:10100000061A874400000003041A875000010335C4 -:10101000061A875400000003041A87600001033693 -:10102000061A876400000003041A87700001033762 -:10103000061A877400000003041A87800001033831 -:10104000061A878400000003041A87900001033900 -:10105000061A879400000003041A87A00001033ACF -:10106000061A87A400000003041A87B00001033B9E -:10107000061A87B400000003041A87C00001033C6D -:10108000061A87C400000003041A87D00001033D3C -:10109000061A87D400000003041A87E00001033E0B -:1010A000061A87E400000003041A87F00001033FDA -:1010B000061A87F400000003041A880000010340A8 -:1010C000061A880400000003041A88100001034176 -:1010D000061A881400000003041A88200001034245 -:1010E000061A882400000003041A88300001034314 -:1010F000061A883400000003041A884000010344E3 -:10110000061A884400000003041A885000010345B1 -:10111000061A885400000003041A88600001034680 -:10112000061A886400000003041A8870000103474F -:10113000061A887400000003041A8880000103481E -:10114000061A888400000003041A889000010349ED -:10115000061A889400000003041A88A00001034ABC -:10116000061A88A400000003041A88B00001034B8B -:10117000061A88B400000003041A88C00001034C5A -:10118000061A88C400000003041A88D00001034D29 -:10119000061A88D400000003041A88E00001034EF8 -:1011A000061A88E400000003041A88F00001034FC7 -:1011B000061A88F400000003041A89000001035095 -:1011C000061A890400000003041A89100001035163 -:1011D000061A891400000003041A89200001035232 -:1011E000061A892400000003041A89300001035301 -:1011F000061A893400000003041A894000010354D0 -:10120000061A894400000003041A8950000103559E -:10121000061A895400000003041A8960000103566D -:10122000061A896400000003041A8970000103573C -:10123000061A897400000003041A8980000103580B -:10124000061A898400000003041A899000010359DA -:10125000061A899400000003041A89A00001035AA9 -:10126000061A89A400000003041A89B00001035B78 -:10127000061A89B400000003041A89C00001035C47 -:10128000061A89C400000003041A89D00001035D16 -:10129000061A89D400000003041A89E00001035EE5 -:1012A000061A89E400000003041A89F00001035FB4 -:1012B000061A89F400000003041A8A000001036082 -:1012C000061A8A0400000003041A8A100001036150 -:1012D000061A8A1400000003041A8A20000103621F -:1012E000061A8A2400000003041A8A3000010363EE -:1012F000061A8A3400000003041A8A4000010364BD -:10130000061A8A4400000003041A8A50000103658B -:10131000061A8A5400000003041A8A60000103665A -:10132000061A8A6400000003041A8A700001036729 -:10133000061A8A7400000003041A8A8000010368F8 -:10134000061A8A8400000003041A8A9000010369C7 -:10135000061A8A9400000003041A8AA00001036A96 -:10136000061A8AA400000003041A8AB00001036B65 -:10137000061A8AB400000003041A8AC00001036C34 -:10138000061A8AC400000003041A8AD00001036D03 -:10139000061A8AD400000003041A8AE00001036ED2 -:1013A000061A8AE400000003041A8AF00001036FA1 -:1013B000061A8AF400000003041A8B00000103706F -:1013C000061A8B0400000003041A8B10000103713D -:1013D000061A8B1400000003041A8B20000103720C -:1013E000061A8B2400000003041A8B3000010373DB -:1013F000061A8B3400000003041A8B4000010374AA -:10140000061A8B4400000003041A8B500001037578 -:10141000061A8B5400000003041A8B600001037647 -:10142000061A8B6400000003041A8B700001037716 -:10143000061A8B7400000003041A8B8000010378E5 -:10144000061A8B8400000003041A8B9000010379B4 -:10145000061A8B9400000003041A8BA00001037A83 -:10146000061A8BA400000003041A8BB00001037B52 -:10147000061A8BB400000003041A8BC00001037C21 -:10148000061A8BC400000003041A8BD00001037DF0 -:10149000061A8BD400000003041A8BE00001037EBF -:1014A000061A8BE400000003041A8BF00001037F8E -:1014B000061A8BF400000003041A8C00000103805C -:1014C000061A8C0400000003041A8C10000103812A -:1014D000061A8C1400000003041A8C2000010382F9 -:1014E000061A8C2400000003041A8C3000010383C8 -:1014F000061A8C3400000003041A8C400001038497 -:10150000061A8C4400000003041A8C500001038565 -:10151000061A8C5400000003041A8C600001038634 -:10152000061A8C6400000003041A8C700001038703 -:10153000061A8C7400000003041A8C8000010388D2 -:10154000061A8C8400000003041A8C9000010389A1 -:10155000061A8C9400000003041A8CA00001038A70 -:10156000061A8CA400000003041A8CB00001038B3F -:10157000061A8CB400000003041A8CC00001038C0E -:10158000061A8CC400000003041A8CD00001038DDD -:10159000061A8CD400000003041A8CE00001038EAC -:1015A000061A8CE400000003041A8CF00001038F7B -:1015B000061A8CF400000003041A8D000001039049 -:1015C000061A8D0400000003041A8D100001039117 -:1015D000061A8D1400000003041A8D2000010392E6 -:1015E000061A8D2400000003041A8D3000010393B5 -:1015F000061A8D3400000003041A8D400001039484 -:10160000061A8D4400000003041A8D500001039552 -:10161000061A8D5400000003041A8D600001039621 -:10162000061A8D6400000003041A8D7000010397F0 -:10163000061A8D7400000003041A8D8000010398BF -:10164000061A8D8400000003041A8D90000103998E -:10165000061A8D9400000003041A8DA00001039A5D -:10166000061A8DA400000003041A8DB00001039B2C -:10167000061A8DB400000003041A8DC00001039CFB -:10168000061A8DC400000003041A8DD00001039DCA -:10169000061A8DD400000003041A8DE00001039E99 -:1016A000061A8DE400000003041A8DF00001039F68 -:1016B000061A8DF400000003041A8E00000103A036 -:1016C000061A8E0400000003041A8E10000103A104 -:1016D000061A8E1400000003041A8E20000103A2D3 -:1016E000061A8E2400000003041A8E30000103A3A2 -:1016F000061A8E3400000003041A8E40000103A471 -:10170000061A8E4400000003041A8E50000103A53F -:10171000061A8E5400000003041A8E60000103A60E -:10172000061A8E6400000003041A8E70000103A7DD -:10173000061A8E7400000003041A8E80000103A8AC -:10174000061A8E8400000003041A8E90000103A97B -:10175000061A8E9400000003041A8EA0000103AA4A -:10176000061A8EA400000003041A8EB0000103AB19 -:10177000061A8EB400000003041A8EC0000103ACE8 -:10178000061A8EC400000003041A8ED0000103ADB7 -:10179000061A8ED400000003041A8EE0000103AE86 -:1017A000061A8EE400000003041A8EF0000103AF55 -:1017B000061A8EF400000003041A8F00000103B023 -:1017C000061A8F0400000003041A8F10000103B1F1 -:1017D000061A8F1400000003041A8F20000103B2C0 -:1017E000061A8F2400000003041A8F30000103B38F -:1017F000061A8F3400000003041A8F40000103B45E -:10180000061A8F4400000003041A8F50000103B52C -:10181000061A8F5400000003041A8F60000103B6FB -:10182000061A8F6400000003041A8F70000103B7CA -:10183000061A8F7400000003041A8F80000103B899 -:10184000061A8F8400000003041A8F90000103B968 -:10185000061A8F9400000003041A8FA0000103BA37 -:10186000061A8FA400000003041A8FB0000103BB06 -:10187000061A8FB400000003041A8FC0000103BCD5 -:10188000061A8FC400000003041A8FD0000103BDA4 -:10189000061A8FD400000003041A8FE0000103BE73 -:1018A000061A8FE400000007041A62C0002003BF7C -:1018B000061A1AF000000042061AAF0000000008E5 -:1018C000061AE00000000540061AD0000000007271 -:1018D000061AD24800000010061AD6B000000020F8 -:1018E000061AD47000000090061AD46800000002A6 -:1018F000061AA000000001C4061A30000000001003 -:10190000061A308000000010061A31000000001096 -:10191000061A318000000010061A33000000001281 -:10192000061A339000000070061AD4580000000216 -:10193000061AD34800000002061AD35800000020FF -:10194000061AA710000001C4061A3040000000105B -:10195000061A30C000000010061A314000000010C6 -:10196000061A31C000000010061A334800000012A9 -:10197000061A355000000070061AD46000000002FC -:10198000061AD35000000002061AD3D80000002027 -:10199000021AAE2000000000061A500000000002EB -:1019A000061A508000000012041A4000000203DFF3 -:1019B000041A63C0000203E1061A7000000000046C -:1019C000061A320000000008021AAE2400000000CF -:1019D000061A501000000002061A50C8000000123B -:1019E000041A4008000203E3041A63C8000203E576 -:1019F000061A701000000004061A322000000008C9 -:101A0000021AAE2800000000061A50200000000252 -:101A1000061A511000000012041A4010000203E7D9 -:101A2000041A63D0000203E9061A702000000004C3 -:101A3000061A324000000008021AAE2C0000000016 -:101A4000061A503000000002061A51580000001219 -:101A5000041A4018000203EB041A63D8000203EDD5 -:101A6000061A703000000004061A326000000008F8 -:101A7000021AAE3000000000061A504000000002BA -:101A8000061A51A000000012041A4020000203EFC1 -:101A9000041A63E0000203F1061A7040000000041B -:101AA000061A328000000008021AAE34000000005E -:101AB000061A505000000002061A51E800000012F9 -:101AC000041A4028000203F3041A63E8000203F535 -:101AD000061A705000000004061A32A00000000828 -:101AE000021AAE3800000000061A50600000000222 -:101AF000061A523000000012041A4030000203F7A8 -:101B0000041A63F0000203F9061A70600000000472 -:101B1000061A32C000000008021AAE3C00000000A5 -:101B2000061A507000000002061A527800000012D7 -:101B3000041A4038000203FB041A63F8000203FD94 -:101B4000061A707000000004061A32E00000000857 -:101B50000200A2A4000002090200A270000000001E -:101B60000200A274000000000200A2700000000049 -:101B70000200A274000000000200A2700000000039 -:101B80000200A274000000000200A2700000000029 -:101B90000200A27400000000020100B40000000175 -:101BA000020100B800000001020100CC00000001A9 -:101BB000020100D000000001020100DC0000000171 -:101BC0000201010000000001020101040000000107 -:101BD0000201007C003000000201008400000028A7 -:101BE0000201008C0000000002010130000000042E -:101BF0000201025C00000001020103280000000055 -:101C0000020160580000FFFF020160700000000741 -:101C10000201055400000030020100C40000000170 -:101C2000020100F800000001020100F000000001C4 -:101C3000020100800030000002010088000000283E -:101C400002010090000000000201013400000004C5 -:101C5000020102DC000000010201032C0000000070 -:101C60000201605C0000FFFF0201607400000007D9 -:101C70000201056400000030020100C800000001FC -:101C8000020100FC00000001020100F4000000015C -:101C9000020C100000000028020C200800000211B5 -:101CA000020C200C00000200020C201000000204B4 -:101CB000020C201C0000FFFF020C20200000FFFF90 -:101CC000020C20240000FFFF020C20280000FFFF70 -:101CD000020C203800000000020C203C00000037FD -:101CE000020C204000000021020C204400000020D3 -:101CF000060C20480000001D020C20BC0000000162 -:101D0000060C20C00000003F020C21BC00000001B6 -:101D1000020C21C000000001020C21C400000001DF -:101D2000060C21C80000001C020C223807FFFFFF30 -:101D3000020C223C0000007F020C224007FFFFFF44 -:101D4000020C22440000003F010C22480000000069 -:101D5000010C224C00000000010C22500000000089 -:101D6000010C225400000000010C22580000000069 -:101D7000010C225C00000000010C22600000000049 -:101D8000010C226400000000010C22680000000029 -:101D9000010C226C00000000010C22700000000009 -:101DA000010C227400000000010C227800000000E9 -:101DB000010C227C00000000020C22D80000FFFF72 -:101DC000020C22DC0000FFFF020C22E00000FFFFFB -:101DD000020C22E40000FFFF0C0C2000000003E8CE -:101DE0000A0C2000000000010B0C20000000000382 -:101DF000020C400800001011020C400C0000100002 -:101E0000020C401000001004020C401400001021CD -:101E1000020C401C0000FFFF020C40200000FFFFEE -:101E2000020C40240000FFFF020C40280000FFFFCE -:101E3000020C403800000046020C403C0000000C40 -:101E4000060C404000000002020C40480000001850 -:101E5000020C404C000000F0060C40500000001F37 -:101E6000020C40CC00000001060C40D00000003AFB -:101E7000020C41B800000001060C41BC0000000348 -:101E8000020C41C800000001020C41CC000000011E -:101E9000060C41D00000001A020C423807FFFFFF79 -:101EA000020C423C0000007F020C424007FFFFFF93 -:101EB000020C42440000003F010C424800000000B8 -:101EC000010C424C00000000010C425000000000D8 -:101ED000010C425400000000010C425800000000B8 -:101EE000010C425C00000000010C42600000000098 -:101EF000010C426400000000010C42680000000078 -:101F0000010C426C00000000010C42700000000057 -:101F1000010C427400000000010C42780000000037 -:101F2000010C427C00000000010C42800000000017 -:101F3000020C42D80000FFFF020C42DC0000FFFF51 -:101F4000020C42E00000FFFF020C42E40000FFFF31 -:101F50000C0C4000000003E80A0C400000000001E7 -:101F60000B0C400000000003060D400000000A00BA -:101F7000020D004400000032020D008C021500200A -:101F8000020D009002150020020D009408100000C0 -:101F9000020D009800000036020D00A000000000B5 -:101FA000020D00A400000004020D00A800000004BF -:101FB000060D00AC00000002020D00B80000000297 -:101FC000020D00C000000001020D00C80000000268 -:101FD000020D00CC00000002020D015C00000001B7 -:101FE000020D016400000001020D01680000000202 -:101FF000020D020400000001020D020C000000208E -:10200000020D021000000040020D0214000000400A -:10201000020D022000000003020D0224000000183F -:10202000060D028000000012040D0300001803FFDB -:10203000060D03600000000C020D004C00000001C2 -:10204000020D005000000002020D005400000000CC -:10205000020D005800000008060D005C000000049E -:10206000020D00C400000004020D00040000000185 -:10207000020D000800000001020D000C000000012C -:10208000020D001000000001020D0014000000010C -:10209000020D001800000001020D001C00000001EC -:1020A000020D002000000001020D002400000001CC -:1020B000020D002800000001020D002C00000001AC -:1020C000020D003000000001020D0034000000018C -:1020D000020D003800000001020D003C000000016C -:1020E000020D011400000009020D011C0000000A8D -:1020F000020D012400000000020D012C0000000070 -:10210000020D013400000000020D013C0000000B34 -:10211000020D014400000000020D0118000000291A -:10212000020D01200000002A020D012800000020FD -:10213000020D013000000020020D013800000020D7 -:10214000020D01400000002B020D0148000000209C -:10215000020D011400000019020D011C0000001AFC -:10216000020D012400000010020D012C00000010DF -:10217000020D013400000010020D013C0000001BA4 -:10218000020D014400000010020D0118000000398A -:10219000020D01200000003A020D0128000000306D -:1021A000020D013000000030020D01380000003047 -:1021B000020D01400000003B020D0148000000300C -:1021C000020D011400000049020D011C0000004A2C -:1021D000020D012400000040020D012C000000400F -:1021E000020D013400000040020D013C0000004BD4 -:1021F000020D014400000040020D011800000069BA -:10220000020D01200000006A020D0128000000609C -:10221000020D013000000060020D01380000006076 -:10222000020D01400000006B020D0148000000603B -:10223000020D011400000059020D011C0000005A9B -:10224000020D012400000050020D012C000000507E -:10225000020D013400000050020D013C0000005B43 -:10226000020D014400000050020D01180000007929 -:10227000020D01200000007A020D0128000000700C -:10228000020D013000000070020D013800000070E6 -:10229000020D01400000007B020D014800000070AB -:1022A000060E200000000800020E004C0000003264 -:1022B000020E009402150020020E00980215002064 -:1022C000020E009C00000030020E00A0081000006A -:1022D000020E00A400000036020E00A8000000302C -:1022E000020E00AC00000031020E00B4000000033A -:1022F000020E00B800000000020E00C40000000042 -:10230000020E00CC00000006020E00D80000000102 -:10231000020E014400000001020E014C0000000109 -:10232000020E015000000002020E02040000000133 -:10233000020E020C00000040020E021000000040DD -:10234000020E021C00000004020E02200000002009 -:10235000020E02240000000E020E02280000001BE4 -:10236000060E030000000012040E0280001B04177A -:10237000060E02EC00000005020E00540000000CE6 -:10238000020E00580000000C020E005C000000006D -:10239000020E006000000010020E00640000001039 -:1023A000060E006800000003020E00DC00000003BF -:1023B000020E000400000001020E000800000001EF -:1023C000020E000C00000001020E001000000001CF -:1023D000020E001400000001020E001800000001AF -:1023E000020E001C00000001020E0020000000018F -:1023F000020E002400000001020E0028000000016F -:10240000020E002C00000001020E0030000000014E -:10241000020E003400000001020E0038000000012E -:10242000020E003C00000001020E0040000000010E -:10243000020E004400000001020E01100000000F17 -:10244000020E011800000000020E01200000000032 -:10245000020E012800000000020E01140000002FEF -:10246000020E011C00000020020E012400000020CA -:10247000020E012C00000020020E01100000001FBF -:10248000020E011800000010020E012000000010D2 -:10249000020E012800000010020E01140000003F8F -:1024A000020E011C00000030020E0124000000306A -:1024B000020E012C00000030020E01100000004F3F -:1024C000020E011800000040020E01200000004032 -:1024D000020E012800000040020E01140000006FEF -:1024E000020E011C00000060020E012400000060CA -:1024F000020E012C00000060020E01100000005FBF -:10250000020E011800000050020E012000000050D1 -:10251000020E012800000050020E01140000007F8E -:10252000020E011C00000070020E01240000007069 -:10253000020E012C000000700730040000D60000DD -:10254000083007D80005043207340000322A0000A2 -:102550000734800031300C8B0735000038D018D894 -:10256000073580002F82270D07360000263632EE11 -:102570000836710031E00434023000BC0000003045 -:1025800001300000000000000130000400000000E5 -:1025900001300008000000000130000C00000000C5 -:1025A00001300010000000000130001400000000A5 -:1025B0000230002000000001023000240000000270 -:1025C00002300028000000030230002C0000000050 -:1025D000023000300000000402300034000000012E -:1025E00002300038000000000230003C0000000112 -:1025F00002300040000000040230004400000000EF -:1026000002300048000000010230004C00000003CE -:1026100002300050000000000230005400000001B1 -:1026200002300058000000040230005C000000008E -:10263000023000600000000102300064000000036E -:1026400002300068000000000230006C0000000151 -:10265000023000700000000402300074000000002E -:1026600002300078000000040230007C000000030B -:102670000630008000000002023000A400007FFF4E -:10268000023000A8000003FF023002240000000016 -:1026900002300234000000000230024C0000000052 -:1026A000023002E40000FFFF0630200000000800B6 -:1026B00002338BC000000001023380000000001ACA -:1026C000023380400000004E023380800000001082 -:1026D000023380C0000000200C33830000086470C7 -:1026E0000A338300000001570B3383000000055FAD -:1026F0000A338340000000000C33834000000226B0 -:102700000B338340000000010233838000086470B3 -:10271000023383C00000022602331480000000014F -:102720000A3314800000000006328000000001021D -:1027300006322008000000C8063220000000000217 -:1027400004328520008F04360632875C00000009C1 -:1027500006323EB00000000606323ED00000000205 -:1027600006323E800000000A04323EA8000204C582 -:1027700006323E00000000200632500000000940F2 -:102780000632400000000004043294C0000204C776 -:1027900006324110000000020632D0000000007036 -:1027A0000632DB00000000D40632DEA0000000028A -:1027B0000632E00000000800063324000000011883 -:1027C0000632100000000188063250000000002090 -:1027D00006325100000000200632520000000020A6 -:1027E0000632530000000020063254000000002092 -:1027F000063255000000002006325600000000207E -:102800000632570000000020063258000000002069 -:10281000063259000000002006325A000000002055 -:1028200006325B000000002006325C000000002041 -:1028300006325D000000002006325E00000000202D -:1028400006325F0000000020063284F00000000223 -:1028500004328500000204C9063285080000000227 -:102860000632DE90000000020633286000000118E6 -:102870000632162000000188063250800000002039 -:1028800006325180000000200632528000000020F5 -:1028900006325380000000200632548000000020E1 -:1028A00006325580000000200632568000000020CD -:1028B00006325780000000200632588000000020B9 -:1028C000063259800000002006325A8000000020A5 -:1028D00006325B800000002006325C800000002091 -:1028E00006325D800000002006325E80000000207D -:1028F00006325F8000000020063284F800000002EB -:1029000004328510000204CB063285180000000254 -:102910000632DE98000000020232845000000000FF -:102920000632401000000002023284540000000011 -:1029300006324020000000020232845800000000ED -:1029400006324030000000020232845C00000000C9 -:1029500006324040000000020232846000000000A5 -:102960000632405000000002023284640000000081 -:10297000063240600000000202328468000000005D -:1029800006324070000000020232846C0000000039 -:10299000063240800000000207200400007300009F -:1029A00008200780001004CD072400002AF1000051 -:1029B0000724800027670ABD0824D35063FC04CF96 -:1029C000022000BC000000300120000000000000D8 -:1029D00001200004000000000120000800000000A9 -:1029E0000120000C00000000012000100000000089 -:1029F000012000140000000002200020000000015F -:102A00000220002400000002022000280000000331 -:102A10000220002C00000000022000300000000412 -:102A200002200034000000010220003800000000F5 -:102A30000220003C000000010220004000000004D1 -:102A400002200044000000000220004800000001B5 -:102A50000220004C00000003022000500000000093 -:102A60000220005400000001022000580000000471 -:102A70000220005C00000000022000600000000155 -:102A80000220006400000003022000680000000033 -:102A90000220006C00000001022000700000000411 -:102AA00002200074000000000220007800000004F2 -:102AB0000220007C000000030620008000000002CD -:102AC000022000A400007FFF022000A8000003FFF6 -:102AD0000220022400000000022002340000000056 -:102AE0000220024C00000000022002E40000FFFF70 -:102AF000062020000000080002238BC00000000117 -:102B00000223800000000010022380400000001219 -:102B10000223808000000030022380C00000000EED -:102B20000C238300000864700A238300000001570F -:102B30000B2383000000055F0A2383400000000090 -:102B40000C238340000002260B2383400000000179 -:102B50000223838000086470022383C000000226E1 -:102B600002231480000000010A23148000000000EA -:102B7000062210000000004206222008000000C8C3 -:102B800006222000000000020622B00000000330F0 -:102B90000622F400000000530422F54C000104D189 -:102BA0000622F550000000030422F55C000104D267 -:102BB0000622F560000000030422F56C000104D336 -:102BC0000622F570000000030422F57C000104D405 -:102BD0000622F580000000030422F58C000104D5D4 -:102BE0000622F590000000030422F59C000104D6A3 -:102BF0000622F5A0000000030422F5AC000104D772 -:102C00000622F5B0000000030422F5BC000104D840 -:102C10000622F5C0000000460622E2000000044043 -:102C200004221240009004D906223000000000C0A7 -:102C30000622670000000100062290000000040048 -:102C400004226B0800200569062211F0000000062E -:102C50000422120800060589062212200000000244 -:102C600006224000000005C00622C0000000000649 -:102C70000422C0180006058F0622C0300000000A9A -:102C80000422C058000605950622C0700000000A04 -:102C90000422C0980006059B0622C0B00000000A6E -:102CA0000422C0D8000605A10622C0F00000000AD8 -:102CB0000422C118000605A70622C1300000000A40 -:102CC0000422C158000605AD0622C1700000000AAA -:102CD0000422C198000605B30622C1B00000000A14 -:102CE0000422C1D8000605B90622C1F00000000A7E -:102CF0000422C218000605BF0622C2300000000AE6 -:102D00000422C258000605C50622C2700000000A4F -:102D10000422C298000605CB0622C2B00000000AB9 -:102D20000422C2D8000605D10622C2F00000000A23 -:102D30000422C318000605D70622C3300000000A8B -:102D40000422C358000605DD0622C3700000000AF5 -:102D50000422C398000605E30622C3B00000000A5F -:102D60000422C3D8000605E90622C3F00000000AC9 -:102D70000422C418000605EF0622C4300000000A31 -:102D80000422C458000605F50622C4700000000A9B -:102D90000422C498000605FB0622C4B00000000A05 -:102DA0000422C4D8000606010622C4F00000000A6E -:102DB0000422C518000606070622C5300000000AD6 -:102DC0000422C5580006060D0622C5700000000A40 -:102DD0000422C598000606130622C5B00000000AAA -:102DE0000422C5D8000606190622C5F00000000A14 -:102DF0000422C6180006061F0622C6300000000A7C -:102E00000422C658000606250622C6700000000AE5 -:102E10000422C6980006062B0622C6B00000000A4F -:102E20000422C6D8000606310622C6F00000000AB9 -:102E30000422C718000606370622C7300000000A21 -:102E40000422C7580006063D0622C7700000000A8B -:102E50000422C798000606430622C7B00000000AF5 -:102E60000422C7D8000606490622C7F00000000A5F -:102E70000422C8180006064F0622C8300000000AC7 -:102E80000422C858000606550622C8700000000A31 -:102E90000422C8980006065B0622C8B00000000A9B -:102EA0000422C8D8000606610622C8F00000000A05 -:102EB0000422C918000606670622C9300000000A6D -:102EC0000422C9580006066D0622C9700000000AD7 -:102ED0000422C998000606730622C9B00000000A41 -:102EE0000422C9D8000606790622C9F00000000AAB -:102EF0000422CA180006067F0622CA300000000A13 -:102F00000422CA58000606850622CA700000000A7C -:102F10000422CA980006068B0622CAB00000000AE6 -:102F20000422CAD8000606910622CAF00000000A50 -:102F30000422CB18000606970622CB300000000AB8 -:102F40000422CB580006069D0622CB700000000A22 -:102F50000422CB98000606A30622CBB00000000A8C -:102F60000422CBD8000606A90622CBF00000000AF6 -:102F70000422CC18000606AF0622CC300000000A5E -:102F80000422CC58000606B50622CC700000000AC8 -:102F90000422CC98000606BB0622CCB00000000A32 -:102FA0000422CCD8000606C10622CCF00000000A9C -:102FB0000422CD18000606C70622CD300000000A04 -:102FC0000422CD58000606CD0622CD700000000A6E -:102FD0000422CD98000606D30622CDB00000000AD8 -:102FE0000422CDD8000606D90622CDF00000000A42 -:102FF0000422CE18000606DF0622CE300000000AAA -:103000000422CE58000606E50622CE700000000A13 -:103010000422CE98000606EB0622CEB00000000A7D -:103020000422CED8000606F10622CEF00000000AE7 -:103030000422CF18000606F70622CF300000000A4F -:103040000422CF58000606FD0622CF700000000AB9 -:103050000422CF98000607030622CFB00000000A22 -:103060000422CFD8000607090622CFF00000000A8C -:103070000422D0180006070F0622D0300000000AF4 -:103080000422D058000607150622D0700000000A5E -:103090000422D0980006071B0622D0B00000000AC8 -:1030A0000422D0D8000607210622D0F00000000A32 -:1030B0000422D118000607270622D1300000000A9A -:1030C0000422D1580006072D0622D1700000000A04 -:1030D0000422D198000607330622D1B00000000A6E -:1030E0000422D1D8000607390622D1F00000000AD8 -:1030F0000422D2180006073F0622D2300000000A40 -:103100000422D258000607450622D2700000000AA9 -:103110000422D2980006074B0622D2B00000000A13 -:103120000422D2D8000607510622D2F00000000A7D -:103130000422D318000607570622D3300000000AE5 -:103140000422D3580006075D0622D3700000000A4F -:103150000422D398000607630622D3B00000000AB9 -:103160000422D3D8000607690622D3F00000000A23 -:103170000422D4180006076F0622D4300000000A8B -:103180000422D458000607750622D4700000000AF5 -:103190000422D4980006077B0622D4B00000000A5F -:1031A0000422D4D8000607810622D4F00000000AC9 -:1031B0000422D518000607870622D5300000000A31 -:1031C0000422D5580006078D0622D5700000000A9B -:1031D0000422D598000607930622D5B00000000A05 -:1031E0000422D5D8000607990622D5F00000000A6F -:1031F0000422D6180006079F0622D6300000000AD7 -:103200000422D658000607A50622D6700000000A40 -:103210000422D698000607AB0622D6B00000000AAA -:103220000422D6D8000607B10622D6F00000000A14 -:103230000422D718000607B70622D7300000000A7C -:103240000422D758000607BD0622D7700000000AE6 -:103250000422D798000607C30622D7B00000000A50 -:103260000422D7D8000607C90622D7F00000000ABA -:103270000422D818000607CF0622D8300000000A22 -:103280000422D858000607D50622D8700000000A8C -:103290000422D898000607DB0622D8B00000000AF6 -:1032A0000422D8D8000607E10622D8F00000000A60 -:1032B0000422D918000607E70622D9300000000AC8 -:1032C0000422D958000607ED0622D9700000000A32 -:1032D0000422D998000607F30622D9B00000000A9C -:1032E0000422D9D8000607F90622D9F00000000A06 -:1032F0000422DA18000607FF0622DA300000000A6E -:103300000422DA58000608050622DA700000000AD6 -:103310000422DA980006080B0622DAB00000000A40 -:103320000422DAD8000608110622DAF00000000AAA -:103330000422DB18000608170622DB300000000A12 -:103340000422DB580006081D0622DB700000000A7C -:103350000422DB98000608230622DBB00000000AE6 -:103360000422DBD8000608290622DBF00000000A50 -:103370000422DC180006082F0622DC300000000AB8 -:103380000422DC58000608350622DC700000000A22 -:103390000422DC980006083B0622DCB00000000A8C -:1033A0000422DCD8000608410622DCF00000000AF6 -:1033B0000422DD18000608470622DD300000000A5E -:1033C0000422DD580006084D0622DD700000000AC8 -:1033D0000422DD98000608530622DDB00000000A32 -:1033E0000422DDD8000608590622DDF00000000A9C -:1033F0000422DE180006085F0622DE300000000A04 -:103400000422DE58000608650622DE700000000A6D -:103410000422DE980006086B0622DEB00000000AD7 -:103420000422DED8000608710622DEF00000000A41 -:103430000422DF18000608770622DF300000000AA9 -:103440000422DF580006087D0622DF700000000A13 -:103450000422DF98000608830622DFB00000000A7D -:103460000422DFD8000608890622DFF00000000AE7 -:103470000422E0180006088F0622E0300000000A4F -:103480000422E058000608950622E0700000000AB9 -:103490000422E0980006089B0622E0B00000000A23 -:1034A0000422E0D8000608A10622E0F00000000A8D -:1034B0000422E118000608A70622E1300000000AF5 -:1034C0000422E158000608AD0622E1700000000A5F -:1034D0000422E198000608B30622E1B00000000AC9 -:1034E0000422E1D8000608B90622E1F00000000439 -:1034F0000622153800000002062211E80000000232 -:103500000622F3000000000802221148000000001B -:1035100006225900000000060622330000000002C7 -:1035200006226040000000300622F3200000000860 -:103530000222114C0000000006225918000000066B -:10354000062233080000000206226100000000305D -:103550000622F34000000008022211500000000083 -:103560000622593000000006062233100000000237 -:10357000062261C0000000300622F360000000084F -:1035800002221154000000000622594800000006E3 -:10359000062233180000000206226280000000307C -:1035A0000622F380000000080222115800000000EB -:1035B00006225960000000060622332000000002A7 -:1035C00006226340000000300622F3A0000000083D -:1035D0000222115C0000000006225978000000065B -:1035E000062233280000000206226400000000309A -:1035F0000622F3C000000008022211600000000053 -:103600000622599000000006062233300000000216 -:10361000062264C0000000300622F3E0000000082B -:103620000222116400000000062259A800000006D2 -:1036300006223338000000020622658000000030B8 -:103640000216100000000028021700080000000207 -:103650000217002C000000030217003C00000004C9 -:10366000021700440000000002170048000000029A -:103670000217004C0000009002170050000000905C -:103680000217005400800090021700580810000034 -:10369000021700700000000602170078000009FF02 -:1036A0000217007C0000076C021701C4081000001C -:1036B0000217034400000001021704000000008A02 -:1036C00002170404000000800217040800000081B3 -:1036D0000217040C00000080021704100000008A8A -:1036E0000217041400000080021704180000008173 -:1036F0000217041C00000080021704300000008A3A -:103700000217043400000080021704380000008112 -:103710000217043C00000080021704400000008AE9 -:1037200002170444000000800217044800000081D2 -:103730000217044C00000080021704800000008A79 -:103740000217048400000080021704880000008132 -:103750000217048C0000008002170038007C10045F -:10376000021700040000000F021701EC0000000225 -:10377000021701F400000002021701EC0000000231 -:10378000021701F400000002021701EC0000000221 -:10379000021701F400000002021701EC0000000211 -:1037A000021701F400000002021701EC0000000201 -:1037B000021701F400000002021701EC00000002F1 -:1037C000021701F400000002021701EC00000002E1 -:1037D000021701F400000002021701EC00000002D1 -:1037E000021701F400000002061640240000000247 -:1037F000021640700000001C021642080000000182 -:1038000002164210000000010216422000000001D2 -:10381000021642280000000102164230000000019A -:103820000216423800000001021642600000000249 -:103830000C16401C0003D0900A16401C0000009C8F -:103840000B16401C000002710216403000000028D8 -:10385000021640340000002C0216403800000030F0 -:103860000216404400000020021640000000000143 -:10387000021640D8000000010216400800000001B6 -:103880000216400C0000000102164010000000016A -:1038900002164240000000000216424800000000EC -:1038A000061642700000000202164250000000009E -:1038B0000216425800000000061642800000000276 -:1038C00002166008000012140216600C00001200BC -:1038D00002166010000012040216601C0000FFFFB8 -:1038E000021660200000FFFF021660240000FFFFA8 -:1038F000021660280000FFFF02166038000000205A -:103900000216603C00000010061660400000000235 -:1039100002166048000000230216604C00000024DC -:1039200002166050000000250216605400000026B8 -:1039300002166058000000270216605C00000011AB -:103940000216606000000000021660640000002B98 -:10395000021660680000002C0216606C0000002D4A -:1039600002166070000000EC021660740000000097 -:1039700002166078000000290216607C0000002A10 -:10398000021660800000002F061660840000000D03 -:10399000021660B800000001061660BC00000008B6 -:1039A000021660DC00000001061660E00000000462 -:1039B000021660F000000001061660F4000000032B -:1039C0000216610000000001061661040000002DCF -:1039D000021661B800000001061661BC0000000874 -:1039E000021661DC00000001061661E00000000420 -:1039F000021661F000000001061661F400000003E9 -:103A00000216620000000001061662040000000DAC -:103A10000216623807FFFFFF0216623C0000007FBB -:103A20000216624007FFFFFF021662440000003FDB -:103A300001166248000000000116624C0000000000 -:103A400001166250000000000116625400000000E0 -:103A500001166258000000000116625C00000000C0 -:103A600001166260000000000116626400000000A0 -:103A700001166268000000000116626C0000000080 -:103A80000116627000000000011662740000000060 -:103A900001166278000000000116627C0000000040 -:103AA000011662D400000000021662D80000FFFF79 -:103AB000021662DC0000FFFF021662E00000FFFF5A -:103AC000021662E40000FFFF0C166000000003E82D -:103AD0000A166000000000010B16600000000003E1 -:103AE0000216804000000006021680440000000517 -:103AF000021680480000000A0216804C00000005F3 -:103B00000216805400000002021680CC000000045F -:103B1000021680D000000004021680D400000004C9 -:103B2000021680D800000004021680DC00000004A9 -:103B3000021680E000000004021680E40000000489 -:103B4000021680E800000004021688040000000647 -:103B5000021680300000007C021680340000003D18 -:103B6000021680380000003F0216803C0000009CD6 -:103B70000216E6E8000060000216E6EC00006000B5 -:103B80000216E6F0000060000216E6F40000600095 -:103B900002168234000025E40216823800008000FC -:103BA00002168094000025E3021681F400000C0840 -:103BB000021681F800000040021681FC000001009E -:103BC0000216820000000020021682040000001786 -:103BD00002168208000000800216820C000002001B -:103BE00002168210000000000216823C0000001342 -:103BF00002168220008F008F0216821C008F008F19 -:103C0000021680F0000000070216821801FF01FF73 -:103C10000216821401FF01FF061680F40000000264 -:103C20000216811C0000000502168120000000051C -:103C300002168124000000050216812800000008F9 -:103C40000216812C000000060216813000000007D9 -:103C50000616813400000004021680FC00000000FB -:103C600006168144000000020216814C0000000488 -:103C7000021681500000000102168154000000026B -:103C800002168158000000050216815C0000000544 -:103C90000216816000000005021681640000000524 -:103CA0000216816800000008021681000000000072 -:103CB0000216816C000000060216817000000007E9 -:103CC00006168174000000060216818C00000004B4 -:103CD000021681900000000102168104000000001D -:103CE000021681940000000202168198000000056F -:103CF0000216819C00000005021681A0000000054C -:103D0000021681A400000005021681A80000000828 -:103D1000021681AC00000006021681B00000000708 -:103D2000061681B40000000202168108000000009F -:103D3000061681BC00000004021681CC00000004BD -:103D4000021681D000000001021681D4000000029A -:103D5000021681D800000005021681DC0000000573 -:103D6000021681E0000000050216810C000000042C -:103D7000021681E400000005021681E80000000838 -:103D8000021681EC00000006021681F00000000718 -:103D900002168110000000010216811400000002CA -:103DA00002168118000000050216809C0000004CDD -:103DB000021680A00000004C061680C4000000021D -:103DC000021680A400000000021680A80000000077 -:103DD000021680AC0000004C061680B00000000502 -:103DE0000216E6F80000020402168240003F003F7F -:103DF00002168244003F003F061682900000000435 -:103E000002168248008000800216824C00800080EA -:103E100002168250010001000216825401000100C6 -:103E20000616825800000002021682600040004020 -:103E30000216826400400040021682681E001E00C6 -:103E40000216826C1E001E000216827040004000A6 -:103E500002168274400040000216827880008000C2 -:103E60000216827C800080000216828020002000E2 -:103E700002168284200020000616828800000002BC -:103E8000021680900000004B021680600000014086 -:103E900002168064000001400616808800000002BF -:103EA00002168068000000000216806C000000000E -:103EB00002168070000000C0061680740000000525 -:103EC0000216880C0101010102168810010120046C -:103ED000021688142008100102168818010101201A -:103EE0000216881C0101010102168820010120042C -:103EF00002168824200810010216882801010120DA -:103F00000216882C200810010216883001010120B9 -:103F100002168834010101010216883801012004CB -:103F20000216883C20081001021688400101012079 -:103F3000021688440101010102168848010120048B -:103F40000216E6BC000000000216E6C000000002F7 -:103F50000216E6C4000000040216E6C800000006CF -:103F60000216E79400000001021680EC000000FF3A -:103F700002140000000000010215C024000000002F -:103F80000215C0EC000000010215C0F000000001A5 -:103F90000615C10000000002021400040000000128 -:103FA00002140008000000010214000C00000001CF -:103FB000021400300000000102140034000000016F -:103FC0000214004000000001021400440000FFFF42 -:103FD00006140004000000030214000000000000AA -:103FE000060280000000200002020058000000329B -:103FF000020200A003150020020200A40315002005 -:10400000020200A801000030020200AC081000000B -:10401000020200B000000036020200B400000030CE -:10402000020200B800000031020200BC00000002E1 -:10403000020200C000000005020200C400000002ED -:10404000020200C800000002020200D000000007C7 -:10405000020200DC00000000020200E00000000597 -:10406000020200E400000003020200F00000000170 -:10407000020200FC00000006020201200000000015 -:104080000202013400000002020201B0000000013F -:104090000202020C000000010202021400000001F2 -:1040A00002020218000000020202040400000001E3 -:1040B0000202040C00000040020204100000004054 -:1040C0000202041C00000004020204200000002080 -:1040D0000202042400000002020204280000002062 -:1040E000060205000000001204020480002008BF40 -:1040F000020200600000000F0202006400000007DE -:1041000002020068000000000202006C0000000EC5 -:10411000020200700000000E06020074000000039E -:10412000020200F40000000402020004000000018A -:1041300002020008000000010202000C0000000161 -:104140000202001000000001020200140000000141 -:1041500002020018000000010202001C0000000121 -:104160000202002000000001020200240000000101 -:1041700002020028000000010202002C00000001E1 -:1041800002020030000000010202003400000001C1 -:1041900002020038000000010202003C00000001A1 -:1041A0000202004000000001020200440000000181 -:1041B00002020048000000010202004C0000000161 -:1041C000020200500000000102020108000000C8C5 -:1041D0000202011800000002020201C400000000F7 -:1041E000020201CC00000000020201D40000000223 -:1041F000020201DC00000002020201E4000000FFF4 -:10420000020201EC000000FF0202010000000000B9 -:104210000202010C000000C80202011C00000002A2 -:10422000020201C800000000020201D000000000EC -:10423000020201D800000002020201E000000002B8 -:10424000020201E8000000FF020201F0000000FF8E -:10425000020201040000002002020108000000C860 -:104260000202011800000002020201C40000000066 -:10427000020201CC00000000020201D40000000292 -:10428000020201DC00000002020201E4000000FF63 -:10429000020201EC000000FF020201000000001019 -:1042A0000202010C000000C80202011C0000000212 -:1042B000020201C800000000020201D0000000005C -:1042C000020201D800000002020201E00000000228 -:1042D000020201E8000000FF020201F0000000FFFE -:1042E000020201040000003002020108000000C8C0 -:1042F0000202011800000002020201C400000000D6 -:10430000020201CC00000000020201D40000000201 -:10431000020201DC00000002020201E4000000FFD2 -:10432000020201EC000000FF020201000000004058 -:104330000202010C000000C80202011C0000000281 -:10434000020201C800000000020201D000000000CB -:10435000020201D800000002020201E00000000297 -:10436000020201E8000000FF020201F0000000FF6D -:10437000020201040000006002020108000000C8FF -:104380000202011800000002020201C40000000045 -:10439000020201CC00000000020201D40000000271 -:1043A000020201DC00000002020201E4000000FF42 -:1043B000020201EC000000FF0202010000000050B8 -:1043C0000202010C000000C80202011C00000002F1 -:1043D000020201C800000000020201D0000000003B -:1043E000020201D800000002020201E00000000207 -:1043F000020201E8000000FF020201F0000000FFDD -:1044000002020104000000700728040000B500004B -:10441000082807B8000908DF072C000028E9000079 -:10442000072C800036700A3B072D000035BE17D8D8 -:10443000072D80003B1B2548072E000035D8340F80 -:10444000072E80001B224186082EBFD0280608E1D7 -:10445000022800BC0000003001280000000000001D -:1044600001280004000000000128000800000000EE -:104470000128000C000000000128001000000000CE -:1044800001280014000000000228002000000001A4 -:104490000228002400000002022800280000000377 -:1044A0000228002C00000000022800300000000458 -:1044B000022800340000000102280038000000003B -:1044C0000228003C00000001022800400000000417 -:1044D00002280044000000000228004800000001FB -:1044E0000228004C000000030228005000000000D9 -:1044F00002280054000000010228005800000004B7 -:104500000228005C0000000002280060000000019A -:104510000228006400000003022800680000000078 -:104520000228006C00000001022800700000000456 -:104530000228007400000000022800780000000437 -:104540000228007C00000003062800800000000212 -:10455000022800A400007FFF022800A8000003FF3B -:10456000022802240000000002280234000000009B -:104570000228024C00000000022802E40000FFFFB5 -:104580000628200000000800022B8BC0000000015C -:10459000022B800000000000022B80400000001869 -:1045A000022B80800000000C022B80C000000066FF -:1045B0000C2B8300000864700A2B83000000015755 -:1045C0000B2B83000000055F0A2B834000000000D6 -:1045D0000C2B8340000002260B2B834000000001BF -:1045E000022B838000086470022B83C00000022627 -:1045F000022B1480000000010A2B14800000000030 -:10460000022B944000000001062B94480000000299 -:10461000062A9A7000000004042A9A80000408E325 -:10462000062A9A9000000002042A9A98000208E7DD -:10463000062A900000000048062A2008000000C852 -:10464000062A200000000002062A912800000086A9 -:10465000062AC00000000120062A9348000000033B -:10466000042A9354000108E9062A9FB000000002C2 -:10467000042A9418000208EA042A9CD0000108ECDD -:10468000062A9CD400000011042A9D20008F08ED0A -:10469000062A9F5C00000005042A30000002097C05 -:1046A000062A300800000100062A404000000010E1 -:1046B000042A40000010097E042A84080002098EA2 -:1046C000042ACF4000040990042ACF600002099414 -:1046D000062A9FA000000004062A60000000054092 -:1046E000062A9D1800000002062AB00000000050B3 -:1046F000062ABB7000000070062ABB68000000029A -:10470000062AB94800000004062AD000000008006C -:10471000062AC48000000150062A942000000032BE -:10472000062A502000000002062A50300000000235 -:10473000062A500000000002062A50100000000265 -:10474000022A520800000001042A9AA000020996D9 -:10475000062A95B000000022042A96380001099824 -:10476000062A963C00000003062A96E0000000227C -:10477000042A976800010999062A976C0000000333 -:10478000062A981000000022042A98980001099A2D -:10479000062A989C00000003062A99400000002287 -:1047A000042A99C80001099B062A99CC000000033D -:1047B000062ABB5800000002062AC9C000000150AA -:1047C000062A94E800000032062A50280000000261 -:1047D000062A503800000002062A50080000000295 -:1047E000062A501800000002022A520C00000001A4 -:1047F000042A9AA80002099C062A96480000002272 -:10480000042A96D00001099E062A96D400000003CF -:10481000062A977800000022042A98000001099FC8 -:10482000062A980400000003062A98A80000002227 -:10483000042A9930000109A0062A993400000003D7 -:10484000062A99D800000022042A9A60000109A1D2 -:10485000062A9A6400000003062ABB6000000002DA -:10486000022ACF0000000000042A9AB0001009A21A -:10487000062A50480000000E022ACF040000000063 -:10488000042A9AF0001009B2062A50800000000E97 -:10489000022ACF0800000000042A9B30001009C241 -:1048A000062A50B80000000E022ACF0C00000000BB -:1048B000042A9B70001009D2062A50F00000000E56 -:1048C000022ACF1000000000042A9BB0001009E269 -:1048D000062A51280000000E022ACF140000000012 -:1048E000042A9BF0001009F2062A51600000000E15 -:1048F000022ACF1800000000042A9C3000100A028F -:10490000062A51980000000E022ACF1C0000000069 -:10491000042A9C7000100A12062A51D00000000ED2 -:1049200002101008000000010210105000000001E9 -:10493000021010000003D000021010040000003D1F -:104940000910180002000A220910110000100C22A0 -:1049500006101140000000080910116000100C3210 -:10496000061011A00000001806102400000000E04E -:104970000210201C00000000021020200000000196 -:10498000021020C0000000020210200400000001FC -:104990000210200800000001021030D800000001C1 -:1049A00009103C0000050C420910380000050C47B6 -:1049B0000910392000050C4C09103B0000050C5172 -:1049C000021040D400000030021040D80000003037 -:1049D00006104C00000001000210402800000010EA -:1049E0000210404400003FFF021040580028000021 -:1049F000021040840084924A0210405800000000D7 -:104A0000021041380000000102104138000000018E -:104A1000021041380000000102104138000000017E -:104A2000021041380000000102104138000000016E -:104A3000021041380000000102104138000000015E -:104A40000212049001F680400212051400003C108E -:104A500002120494FFFFFFFF02120498FFFFFFFF02 -:104A60000212049CFFFFFFFF021204A0FFFFFFFFE2 -:104A7000021204A4FFFFFFFF021204A8FFFFFFFFC2 -:104A8000021204ACFFFFFFFF021204B0FFFFFFFFA2 -:104A9000021204B8FFFFFFFF021204BCFFFFFFFF7A -:104AA000021204C0FFFFFFFF021204C4FFFFFFFF5A -:104AB000021204C8FFFFFFFF021204CCFFFFFFFF3A -:104AC000021204D0FFFFFFFF021204D8FFFFFFFF16 -:104AD000021204DCFFFFFFFF021204E0FFFFFFFFF2 -:104AE000021204E4FFFFFFFF021204E8FFFFFFFFD2 -:104AF000021204ECFFFFFFFF021204F0FFFFFFFFB2 -:104B0000021204F4FFFFFFFF021204F8FFFFFFFF91 -:104B1000021204FCFFFFFFFF02120500FFFFFFFF70 -:104B200002120504FFFFFFFF02120508FFFFFFFF4F -:104B30000212050CFFFFFFFF02120510FFFFFFFF2F -:104B4000021204D4F800C000021204B4F0005000B5 -:104B500002120390000000080212039C00000008EB -:104B6000021203A000000008021203A400000002C9 -:104B7000021203BC00000004021203C00000000582 -:104B8000021203C400000004021203D0000000005F -:104B90000212036C00000001021201BC0000004080 -:104BA000021201C000001808021201C4000008032C -:104BB000021201C800000803021201CC00000040EC -:104BC000021201D000000003021201D40000080309 -:104BD000021201D800000803021201DC00000803E1 -:104BE000021201E000010003021201E400000803C8 -:104BF000021201E800000803021201EC00000003A9 -:104C0000021201F000000003021201F40000000390 -:104C1000021201F800000003021201FC0000000370 -:104C2000021202000000000302120204000000034E -:104C300002120208000000030212020C000000032E -:104C4000021202100000000302120214000000030E -:104C500002120218000000030212021C00000003EE -:104C600002120220000000030212022400000003CE -:104C700002120228000024030212022C0000002F5E -:104C80000212023000000009021202340000001972 -:104C900002120238000001840212023C000001836B -:104CA0000212024000000306021202440000001932 -:104CB00002120248000000060212024C0000030625 -:104CC0000212025000000306021202540000030602 -:104CD0000212025800000C860212025C0000030659 -:104CE00002120260000003060212026400000006C5 -:104CF00002120268000000060212026C00000006A8 -:104D00000212027000000006021202740000000687 -:104D100002120278000000060212027C0000000667 -:104D20000212028000000006021202840000000647 -:104D300002120288000000060212028C0000000627 -:104D40000212029000000006021202940000000607 -:104D500002120298000000060212029C00000006E7 -:104D6000021202A000000306021202A400000013B7 -:104D7000021202A800000006021202B00000100495 -:104D8000021202B400001004021203240010644056 -:104D90000212032800106440021205B40000000152 -:104DA000021205F800000040021205FC0000001984 -:104DB00002120600000000010212066C0000000151 -:104DC000021201B000000001021207D80000000327 -:104DD000021207D800000003021207D800000003E7 -:104DE000021207D800000003021207D800000003D7 -:104DF000021207D800000003021207D800000003C7 -:104E0000021207D8000000030600A0000000000CFA -:104E10000200A050000000000200A05400000000AA -:104E20000200A0EC555400000200A0F05555555565 -:104E30000200A0F4000055550200A0F8F0000000A8 -:104E40000200A0FC555400000200A1005555555524 -:104E50000200A104000055550200A108F000000066 -:104E60000200A19C000000000200A1A000010000BF -:104E70000200A1A4000050140200A1A8000000003C -:104E80000200A6A8000000000200A6AC000000007E -:104E90000200A6D0000000000200A45C00000C008C -:104EA0000200A61C000000030200A070FFF55FFFD7 -:104EB0000200A0740000FFFF0200A078F00003E0F1 -:104EC0000200A07C000000000200A0800000A00002 -:104ED0000600A084000000050200A0980FE000007A -:104EE0000600A09C000000070200A0B8000004001B -:104EF0000600A0BC000000030200A0C800001000D3 -:104F00000600A0CC000000030200A0D80000400072 -:104F10000600A0DC000000030200A0E80001000081 -:104F20000600A22C000000040200A688000000FC7D -:104F30000600A68C000000070200A6F40000000096 -:104F40000200A10CFF5C00000200A110FFF55FFF52 -:104F50000200A1140000FFFF0200A118F00003E00E -:104F60000200A11C000000000200A1200000A0001F -:104F70000600A124000000050200A1380FE0000097 -:104F80000600A13C000000070200A1580000080034 -:104F90000600A15C000000030200A16800002000E0 -:104FA0000600A16C000000030200A1780000800050 -:104FB0000600A17C000000030200A188000200009E -:104FC0000600A23C000000040200A6B0000000FCA5 -:104FD0000600A6B4000000070200A6F800000000CA -:104FE0000200A030000000000200A0340000000019 -:104FF0000200A038000000000200A03C00000000F9 -:105000000200A040000000000200A04400000000D8 -:105010000200A048000000000200A04C00000000B8 -:10502000020090C40000E000020090CC0000F300F9 -:10503000020090D400000003020091A000000001D3 -:105040000600917000000003020090EC0000600078 -:10505000020090F400007300020090FC00000003C6 -:10506000020091A8000000010600918800000003E2 -:10507000020091000000400002009108000053006F -:105080000200911000000004020091AC0000000139 -:1050900006009194000000020200919C00000001B3 -:1050A000020090D800006000020090E00000730051 -:1050B000020090E800000003020091A4000000013B -:1050C0000200917C000000010200918000000001BC -:1050D00002009184000000000200912800000300FB -:1050E0000200916C0003F0080200912C0000030004 -:1050F0000200913000000300020091340000030020 -:1051000002009138000003000200913C00000300FF -:1051100002009140000003000200942C00000001F6 -:1051200002009430000000010200943400000001ED -:105130000200942C000000010200943000000001E5 -:1051400002009434000000010200942C00000001D1 -:1051500002009430000000010200943400000001BD -:105160000200942C000000010200943000000001B5 -:1051700002009434000000010200942C00000001A1 -:10518000020094300000000102009434000000018D -:105190000200942C00000001020094300000000185 -:1051A00002009434000000010200942C0000000171 -:1051B000020094300000000102009434000000015D -:1051C0000200942C00000001020094300000000155 -:1051D0000200943400000001021300780000003047 -:1051E0000213003C000061A8061301080000000340 -:1051F000021301040000000002130134000000004B -:10520000061301080000000302130104000000005F -:10521000021301340000000006130108000000031F -:10522000021301040000000002130134000000001A -:10523000061301080000000302130104000000002F -:1052400002130134000000000613010800000003EF -:1052500002130104000000000213013400000000EA -:1052600006130108000000030213010400000000FF -:1052700002130134000000000613010800000003BF -:1052800002130104000000000213013400000000BA -:1052900006130108000000030213010400000000CF -:1052A0000213013400000000021100B800000001E8 -:1052B0000216E6E8000020000216E6EC00002000DE -:1052C0000216E6F0000065550216E6F4000065558A -:1052D00002168150000000000216817400000001D7 -:1052E00002168178000000010216817C0000000196 -:1052F0000216818000000001021681840000000176 -:105300000216818800000001021681B4000000012D -:10531000021681B800000001021681BC00000001E5 -:10532000021681C000000001021681C400000001C5 -:10533000021681C800000001021681100000000062 -:105340000216824000BF00BF061682440000000221 -:105350000216824C00BF00BF0216E6C40000000126 -:105360000216E6C8000000030216E79400000000E1 -:10537000042ACF40000A0C56000000000000000084 -:1053800000000034000000000000000000000000E9 -:10539000000000000000000000000000000000000D -:1053A0000000000000000000000000000034003594 -:1053B00000000000000000000000000000000000ED -:1053C00000000000000000000000000000000000DD -:1053D0000000000000000000003500600000000038 -:1053E00000000000000000000000000000000000BD -:1053F00000000000000000000000000000000000AD -:1054000000000000006000910000000000000000AB -:1054100000910095009500990099009D009D00A1C4 -:1054200000A100A500A500A900A900AD00AD00B134 -:1054300000B100B500000000000000000000000006 -:10544000000000000000000000000000000000005C -:1054500000000000000000000000000000B5031183 -:105460000311031B031B03250325032C032C033308 -:105470000333033A033A0341034103480348034F0C -:10548000034F03560356035D0000000000000000B8 -:10549000000000000000000000000000000000000C -:1054A00000000000000000000000000000000000FC -:1054B00000000000000000000000000000000000EC -:1054C00000000000000000000000000000000000DC -:1054D00000000000000000000000000000000000CC -:1054E00000000000000000000000000000000000BC -:1054F00000000000000000000000000000000000AC -:10550000000000000000000000000000000000009B -:10551000000000000000000000000000000000008B -:10552000000000000000000000000000000000007B -:105530000000000000000000035D035E00000000AA -:1055400000000000035E035F035F0360036003610C -:10555000036103620362036303630364036403651B -:10556000036503660000000000000000000000006A -:10557000000000000000000000000000000000002B -:10558000000000000000000000000000000000001B -:105590000366036D036D0379037903850000000042 -:1055A00000000000000000000000000000000000FB -:1055B00000000000000000000000000000000000EB -:1055C00000000000000000000000000000000000DB -:1055D00000000000000000000000000000000000CB -:1055E00000000000000000000385038600000000AA -:1055F00000000000000000000000000000000000AB -:10560000000000000000000000000000000000009A -:1056100000000000038603B100000000000000004D -:10562000000000000000000000000000000000007A -:10563000000000000000000000000000000000006A -:1056400003B103E0000000000000000000000000C3 -:10565000000000000000000000000000000000004A -:1056600000000000000000000000000003E0040F44 -:105670000000000000000000040F04160416041DC2 -:10568000041D04240424042B042B043204320439A2 -:1056900004390440044004470447047A0000000031 -:1056A00000000000047A047E047E048204820486E2 -:1056B0000486048A048A048E048E0492049204965A -:1056C0000496049A049A04EA04EA05000500051603 -:1056D000051605180518051A051A051C051C051ED2 -:1056E000051E052005200522052205240524052682 -:1056F00005260693000000000000000006930698AF -:105700000698069D069D06A206A206A706A706AC59 -:1057100006AC06B106B106B606B606BB06BB06BCAD -:105720000000000000000000000000000000000079 -:105730000000000000000000000000000000000069 -:10574000000000000000000006BC06E000000000B1 -:105750000000000006E006E206E206E406E406E6D3 -:1057600006E606E806E806EA06EA06EC06EC06EEB9 -:1057700006EE06F006F00705070507080708070B01 -:105780000000000000000000000000000000000019 -:105790000000000000000000000000000000000009 -:1057A000070B074F00000000000000000000000091 -:1057B00000000000000000000000000000000000E9 -:1057C000000000000000000000000000074F07E19B -:1057D00000000000000000000000000000000000C9 -:1057E00000000000000000000000000000000000B9 -:1057F000000000000000000007E107EF00000000CB -:105800000000000000000000000000000000000098 -:105810000000000000000000000000000000000088 -:105820000000000007EF082C00000000000000004E -:10583000082C08350835083E083E08470847085038 -:1058400008500859085908620862086B086B087408 -:10585000087408D508D508EA08EA08FF08FF090215 -:1058600009020905090509080908090B090B090EB0 -:10587000090E09110911091409140917091709203A -:105880000000000000000000000000000000000018 -:105890000000000000000000000000000000000008 -:1058A00000000000000000000920092600000000A0 -:1058B00000000000000000000000000000000000E8 -:1058C00000000000000000000000000000000000D8 -:1058D000000000000926092B000000000000000065 -:1058E00000000000000000000000000000000000B8 -:1058F00000000000000000000000000000000000A8 -:10590000092B0933000000000000000009330934AE -:10591000093409350935093609360937093709388F -:10592000093809390939093A093A093B00000000E8 -:105930000000000000000000000000000000000067 -:105940000000000000000000000000000000000057 -:105950000000000000000000093B09AC000000004E -:105960000000000009AC09AD09AD09AE09AE09AFF0 -:1059700009AF09B009B009B109B109B209B209B357 -:1059800009B309B409B409C809C809DB09DB09EF7F -:1059900009EF09F009F009F109F109F209F209F337 -:1059A00009F309F409F409F509F509F609F609F707 -:1059B00009F70A1600000000000000000A160A1984 -:1059C0000A190A1C0A1C0A1F0A1F0A220A220A258F -:1059D0000A250A280A280A2B0A2B0A2E0A2E0A3020 -:1059E00000000000000000000A300A330A330A36C3 -:1059F0000A360A390A390A3C0A3C0A3F0A3F0A4277 -:105A00000A420A450A450A480A480A4900000000B5 -:105A10000000000000000000000000000000000086 -:105A20000000000000000000000000000000000076 -:105A3000000000000A490A610000000000000000A8 -:105A40000000000000000000000000000000000056 -:105A50000000000000000000000000000000000046 -:105A60000A610A620000000000000000000000005F -:105A70000000000000000000000000000000000026 -:105A80000000000000000000000000000000000016 -:105A9000000100000002070000030E0000041500D2 -:105AA00000051C000006230000072A000008310042 -:105AB00000093800000A3F00000B4600000C4D00B2 -:105AC000000D5400000E5B00000F62000010690022 -:105AD000001170000012770000137E000014850092 -:105AE00000158C000016930000179A000018A10002 -:105AF0000019A800001AAF00001BB600001CBD0072 -:105B0000001DC400001ECB00001FD2000000D90001 -:105B10000000200000004000000060000000800045 -:105B20000000A0000000C0000000E0000001000034 -:105B30000001200000014000000160000001800021 -:105B40000001A0000001C0000001E0000002000010 -:105B500000022000000240000002600000028000FD -:105B60000002A0000002C0000002E00000030000EC -:105B700000032000000340000003600000038000D9 -:105B80000003A0000003C0000003E00000040000C8 -:105B900000042000000440000004600000048000B5 -:105BA0000004A0000004C0000004E00000050000A4 -:105BB0000005200000054000000560000005800091 -:105BC0000005A0000005C0000005E0000006000080 -:105BD000000620000006400000066000000680006D -:105BE0000006A0000006C0000006E000000700005C -:105BF0000007200000074000000760000007800049 -:105C00000007A0000007C0000007E0000008000037 -:105C10000008200000084000000860000008800024 -:105C20000008A0000008C0000008E0000009000013 -:105C30000009200000094000000960000009800000 -:105C40000009A0000009C0000009E000000A0000EF -:105C5000000A2000000A4000000A6000000A8000DC -:105C6000000AA000000AC000000AE000000B0000CB -:105C7000000B2000000B4000000B6000000B8000B8 -:105C8000000BA000000BC000000BE000000C0000A7 -:105C9000000C2000000C4000000C6000000C800094 -:105CA000000CA000000CC000000CE000000D000083 -:105CB000000D2000000D4000000D6000000D800070 -:105CC000000DA000000DC000000DE000000E00005F -:105CD000000E2000000E4000000E6000000E80004C -:105CE000000EA000000EC000000EE000000F00003B -:105CF000000F2000000F4000000F6000000F800028 -:105D0000000FA000000FC000000FE0000010000016 -:105D10000010200000104000001060000010800003 -:105D20000010A0000010C0000010E00000110000F2 -:105D300000112000001140000011600000118000DF -:105D40000011A0000011C0000011E00000120000CE -:105D500000122000001240000012600000128000BB -:105D60000012A0000012C0000012E00000130000AA -:105D70000013200000134000001360000013800097 -:105D80000013A0000013C0000013E0000014000086 -:105D90000014200000144000001460000014800073 -:105DA0000014A0000014C0000014E0000015000062 -:105DB000001520000015400000156000001580004F -:105DC0000015A0000015C0000015E000001600003E -:105DD000001620000016400000166000001680002B -:105DE0000016A0000016C0000016E000001700001A -:105DF0000017200000174000001760000017800007 -:105E00000017A0000017C0000017E00000180000F5 -:105E100000182000001840000018600000188000E2 -:105E20000018A0000018C0000018E00000190000D1 -:105E300000192000001940000019600000198000BE -:105E40000019A0000019C0000019E000001A0000AD -:105E5000001A2000001A4000001A6000001A80009A -:105E6000001AA000001AC000001AE000001B000089 -:105E7000001B2000001B4000001B6000001B800076 -:105E8000001BA000001BC000001BE000001C000065 -:105E9000001C2000001C4000001C6000001C800052 -:105EA000001CA000001CC000001CE000001D000041 -:105EB000001D2000001D4000001D6000001D80002E -:105EC000001DA000001DC000001DE000001E00001D -:105ED000001E2000001E4000001E6000001E80000A -:105EE000001EA000001EC000001EE000001F0000F9 -:105EF000001F2000001F4000001F6000001F8000E6 -:105F0000001FA000001FC000001FE00000200000D4 -:105F100000202000002040000020600000208000C1 -:105F20000020A0000020C0000020E00000210000B0 -:105F3000002120000021400000216000002180009D -:105F40000021A0000021C0000021E000002200008C -:105F50000022200000224000002260000022800079 -:105F60000022A0000022C0000022E0000023000068 -:105F70000023200000234000002360000023800055 -:105F80000023A0000023C0000023E0000024000044 -:105F90000024200000244000002460000024800031 -:105FA0000024A0000024C0000024E0000025000020 -:105FB000002520000025400000256000002580000D -:105FC0000025A0000025C0000025E00000260000FC -:105FD00000262000002640000026600000268000E9 -:105FE0000026A0000026C0000026E00000270000D8 -:105FF00000272000002740000027600000278000C5 -:106000000027A0000027C0000027E00000280000B3 -:1060100000282000002840000028600000288000A0 -:106020000028A0000028C0000028E000002900008F -:10603000002920000029400000296000002980007C -:106040000029A0000029C0000029E000002A00006B -:10605000002A2000002A4000002A6000002A800058 -:10606000002AA000002AC000002AE000002B000047 -:10607000002B2000002B4000002B6000002B800034 -:10608000002BA000002BC000002BE000002C000023 -:10609000002C2000002C4000002C6000002C800010 -:1060A000002CA000002CC000002CE000002D0000FF -:1060B000002D2000002D4000002D6000002D8000EC -:1060C000002DA000002DC000002DE000002E0000DB -:1060D000002E2000002E4000002E6000002E8000C8 -:1060E000002EA000002EC000002EE000002F0000B7 -:1060F000002F2000002F4000002F6000002F8000A4 -:10610000002FA000002FC000002FE0000030000092 -:10611000003020000030400000306000003080007F -:106120000030A0000030C0000030E000003100006E -:10613000003120000031400000316000003180005B -:106140000031A0000031C0000031E000003200004A -:106150000032200000324000003260000032800037 -:106160000032A0000032C0000032E0000033000026 -:106170000033200000334000003360000033800013 -:106180000033A0000033C0000033E0000034000002 -:1061900000342000003440000034600000348000EF -:1061A0000034A0000034C0000034E00000350000DE -:1061B00000352000003540000035600000358000CB -:1061C0000035A0000035C0000035E00000360000BA -:1061D00000362000003640000036600000368000A7 -:1061E0000036A0000036C0000036E0000037000096 -:1061F0000037200000374000003760000037800083 -:106200000037A0000037C0000037E0000038000071 -:10621000003820000038400000386000003880005E -:106220000038A0000038C0000038E000003900004D -:10623000003920000039400000396000003980003A -:106240000039A0000039C0000039E000003A000029 -:10625000003A2000003A4000003A6000003A800016 -:10626000003AA000003AC000003AE000003B000005 -:10627000003B2000003B4000003B6000003B8000F2 -:10628000003BA000003BC000003BE000003C0000E1 -:10629000003C2000003C4000003C6000003C8000CE -:1062A000003CA000003CC000003CE000003D0000BD -:1062B000003D2000003D4000003D6000003D8000AA -:1062C000003DA000003DC000003DE000003E000099 -:1062D000003E2000003E4000003E6000003E800086 -:1062E000003EA000003EC000003EE000003F000075 -:1062F000003F2000003F4000003F6000003F800062 -:10630000003FA000003FC000003FE000003FE00170 -:1063100000000000000001FF0000020000007FF804 -:1063200000007FF800000A90000035000000000126 -:106330000000FF00000000000000FF00000000005F -:106340000000FF00000000000000FF00000000004F -:106350000000FF00000000000000FF00000000003F -:106360000000FF00000000000000FF00000000002F -:106370000000FF00000000000000FF00000000001F -:106380000000FF00000000000000FF00000000000F -:106390000000FF00000000000000FF0000000000FF -:1063A0000000FF00000000000000FF0000000000EF -:1063B0000000FF00000000000000FF0000000000DF -:1063C0000000FF00000000000000FF0000000000CF -:1063D0000000FF00000000000000FF0000000000BF -:1063E0000000FF00000000000000FF0000000000AF -:1063F0000000FF00000000000000FF00000000009F -:106400000000FF00000000000000FF00000000008E -:106410000000FF00000000000000FF00000000007E -:106420000000FF00000000000000FF00000000006E -:106430000000FF00000000000000FF00000000005E -:106440000000FF00000000000000FF00000000004E -:106450000000FF00000000000000FF00000000003E -:106460000000FF00000000000000FF00000000002E -:106470000000FF00000000000000FF00000000001E -:106480000000FF00000000000000FF00000000000E -:106490000000FF00000000000000FF0000000000FE -:1064A0000000FF00000000000000FF0000000000EE -:1064B0000000FF00000000000000FF0000000000DE -:1064C0000000FF00000000000000FF0000000000CE -:1064D0000000FF00000000000000FF0000000000BE -:1064E0000000FF00000000000000FF0000000000AE -:1064F0000000FF00000000000000FF00000000009E -:106500000000FF00000000000000FF00000000008D -:106510000000FF00000000000000FF00000000007D -:106520000000FF00000000000000FF00000000006D -:106530000000FF00000000000000FF00000000005D -:106540000000FF00000000000000FF00000000004D -:106550000000FF00000000000000FF00000000003D -:106560000000FF00000000000000FF00000000002D -:1065700000000000140AFF000000000100000000FD -:106580000020100100000000010090000000010048 -:1065900000009002000090040000900600009008A7 -:1065A0000000900A0000900C0000900E0000901077 -:1065B0000000901200009014000090160000901847 -:1065C0000000901A0000901C0000901E0000902017 -:1065D00000009022000090240000902600009028E7 -:1065E0000000902A0000902C0000902E00009030B7 -:1065F0000000903200009034000090360000903887 -:106600000000903A0000903C0000903E0000904056 -:106610000000904200009044000090460000904826 -:106620000000904A0000904C0000904E00009050F6 -:1066300000009052000090540000905600009058C6 -:106640000000905A0000905C0000905E0000906096 -:106650000000906200009064000090660000906866 -:106660000000906A0000906C0000906E0000907036 -:106670000000907200009074000090760000907806 -:106680000000907A0000907C0000907E00009080D6 -:1066900000009082000090840000908600009088A6 -:1066A0000000908A0000908C0000908E0000909076 -:1066B0000000909200009094000090960000909846 -:1066C0000000909A0000909C0000909E000090A016 -:1066D000000090A2000090A4000090A6000090A8E6 -:1066E000000090AA000090AC000090AE000090B0B6 -:1066F000000090B2000090B4000090B6000090B886 -:10670000000090BA000090BC000090BE000090C055 -:10671000000090C2000090C4000090C6000090C825 -:10672000000090CA000090CC000090CE000090D0F5 -:10673000000090D2000090D4000090D6000090D8C5 -:10674000000090DA000090DC000090DE000090E095 -:10675000000090E2000090E4000090E6000090E865 -:10676000000090EA000090EC000090EE000090F035 -:10677000000090F2000090F4000090F6000090F805 -:10678000000090FA000090FC000090FE00009100D4 -:1067900000009102000091040000910600009108A1 -:1067A0000000910A0000910C0000910E0000911071 -:1067B0000000911200009114000091160000911841 -:1067C0000000911A0000911C0000911E0000912011 -:1067D00000009122000091240000912600009128E1 -:1067E0000000912A0000912C0000912E00009130B1 -:1067F0000000913200009134000091360000913881 -:106800000000913A0000913C0000913E0000914050 -:106810000000914200009144000091460000914820 -:106820000000914A0000914C0000914E00009150F0 -:1068300000009152000091540000915600009158C0 -:106840000000915A0000915C0000915E0000916090 -:106850000000916200009164000091660000916860 -:106860000000916A0000916C0000916E0000917030 -:106870000000917200009174000091760000917800 -:106880000000917A0000917C0000917E00009180D0 -:1068900000009182000091840000918600009188A0 -:1068A0000000918A0000918C0000918E0000919070 -:1068B0000000919200009194000091960000919840 -:1068C0000000919A0000919C0000919E000091A010 -:1068D000000091A2000091A4000091A6000091A8E0 -:1068E000000091AA000091AC000091AE000091B0B0 -:1068F000000091B2000091B4000091B6000091B880 -:10690000000091BA000091BC000091BE000091C04F -:10691000000091C2000091C4000091C6000091C81F -:10692000000091CA000091CC000091CE000091D0EF -:10693000000091D2000091D4000091D6000091D8BF -:10694000000091DA000091DC000091DE000091E08F -:10695000000091E2000091E4000091E6000091E85F -:10696000000091EA000091EC000091EE000091F02F -:10697000000091F2000091F4000091F6000091F8FF -:10698000000091FA000091FC000091FEFFFFFFFF64 -:10699000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07 -:1069A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7 -:1069B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7 -:1069C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7 -:1069D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7 -:1069E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB7 -:1069F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA7 -:106A0000FFFFFFFFFFFFFFFFFFFFFFFF000000038F -:106A100000BEBC20000000000000000500000003D4 -:106A200000BEBC20000000000000000500000003C4 -:106A300000BEBC20000000000000000500000003B4 -:106A400000BEBC20000000000000000500000003A4 -:106A500000BEBC2000000000000000050000000394 -:106A600000BEBC2000000000000000050000000384 -:106A700000BEBC2000000000000000050000000374 -:106A800000BEBC2000000000000000050000200047 -:106A9000000040C000006180000082400000A300B0 -:106AA0000000C3C00000E480000105400001260092 -:106AB000000146C000016780000188400001A90074 -:106AC0000001C9C00001EA8000020B4000022C0056 -:106AD00000024CC000026D8000028E400002AF0038 -:106AE0000002CFC00002F0800000114000008000D2 -:106AF000000103800001870000020A8000028E006E -:106B000000031180000395000004188000049C001D -:106B100000051F800005A300000626800006AA00CD -:106B200000072D800007B100000834800008B8007D -:106B300000093B800009BF00000A4280000AC6002D -:106B4000000B4980000BCD00000C5080000CD400DD -:106B5000000D578000005B0000007FF800007FF808 -:106B60000000022A000035000000FF0000000000C5 -:106B70000000FF00000000000000FF000000000017 -:106B80000000FF00000000000000FF000000000007 -:106B90000000FF00000000000000FF0000000000F7 -:106BA0000000FF00000000000000FF0000000000E7 -:106BB0000000FF00000000000000FF0000000000D7 -:106BC0000000FF00000000000000FF0000000000C7 -:106BD0000000FF00000000000000FF0000000000B7 -:106BE0000000FF00000000000000FF0000000000A7 -:106BF0000000FF00000000000000FF000000000097 -:106C00000000FF00000000000000FF000000000086 -:106C10000000FF00000000000000FF000000000076 -:106C20000000FF00000000000000FF000000000066 -:106C30000000FF00000000000000FF000000000056 -:106C40000000FF00000000000000FF000000000046 -:106C50000000FF00000000000000FF000000000036 -:106C60000000FF00000000000000FF000000000026 -:106C70000000FF00000000000000FF000000000016 -:106C80000000FF00000000000000FF000000000006 -:106C90000000FF00000000000000FF0000000000F6 -:106CA0000000FF00000000000000FF0000000000E6 -:106CB0000000FF00000000000000FF0000000000D6 -:106CC0000000FF00000000000000FF0000000000C6 -:106CD0000000FF00000000000000FF0000000000B6 -:106CE0000000FF00000000000000FF0000000000A6 -:106CF0000000FF00000000000000FF000000000096 -:106D00000000FF00000000000000FF000000000085 -:106D10000000FF00000000000000FF000000000075 -:106D20000000FF00000000000000FF000000000065 -:106D30000000FF00000000000000FF000000000055 -:106D40000000FF00000000000000FF000000000045 -:106D50000000FF00000000000000FF000000000035 -:106D60000000FF00000000000000FF000000000025 -:106D70000000FF00000000000000FF000000000015 -:106D80000000FF00000000000000FF000000000005 -:106D90000000FF00000000000000FF0000000000F5 -:106DA0000000FF00000019000000000000000000CB -:106DB000FFFFFFFF000000000393870000000000BA -:106DC0000393870000007FF800007FF800000BA30A -:106DD00000001500000000FF000000FF000000FFA1 -:106DE000000000FF000000FF000000FF000000FFA7 -:106DF000000000FF0000FF00000000000000FF0096 -:106E0000000000000000FF00000000000000FF0084 -:106E1000000000000000FF00000000000000FF0074 -:106E2000000000000000FF00000000000000FF0064 -:106E3000000000000000FF00000000000000FF0054 -:106E4000000000000000FF00000000000000FF0044 -:106E5000000000000000FF00000000000000FF0034 -:106E6000000000000000FF00000000000000FF0024 -:106E7000000000000000FF00000000000000FF0014 -:106E8000000000000000FF00000000000000FF0004 -:106E9000000000000000FF00000000000000FF00F4 -:106EA000000000000000FF00000000000000FF00E4 -:106EB000000000000000FF00000000000000FF00D4 -:106EC000000000000000FF00000000000000FF00C4 -:106ED000000000000000FF00000000000000FF00B4 -:106EE000000000000000FF00000000000000FF00A4 -:106EF000000000000000FF00000000000000FF0094 -:106F0000000000000000FF00000000000000FF0083 -:106F1000000000000000FF00000000000000FF0073 -:106F2000000000000000FF00000000000000FF0063 -:106F3000000000000000FF00000000000000FF0053 -:106F4000000000000000FF00000000000000FF0043 -:106F5000000000000000FF00000000000000FF0033 -:106F6000000000000000FF00000000000000FF0023 -:106F7000000000000000FF00000000000000FF0013 -:106F8000000000000000FF00000000000000FF0003 -:106F9000000000000000FF00000000000000FF00F3 -:106FA000000000000000FF00000000000000FF00E3 -:106FB000000000000000FF00000000000000FF00D3 -:106FC000000000000000FF00000000000000FF00C3 -:106FD000000000000000FF00000000000000FF00B3 -:106FE000000000000000FF00000000000000FF00A3 -:106FF000000000000000FF00000000000000FF0093 -:10700000000000000000FF00000000000000FF0082 -:10701000000000000000FF00000000000000FF0072 -:10702000000000000000FF00000000000000FF0062 -:1070300000000000FFFFFFFFFFFFFFFFFFFFFFFF5C -:10704000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50 -:10705000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40 -:10706000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30 -:10707000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20 -:10708000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 -:10709000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 -:1070A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 -:1070B000FFFFFFFF00000000000028AD00002918BE -:1070C0000000291900000005000000070000FF0073 -:1070D0000FFFFFFF0000FF000FFFFFFF000000FF9A -:1070E0000000FF000000FF000FFFFFFF0000FF0097 -:1070F0000FFFFFFF000000FF0000FF000000FF0087 -:107100000FFFFFFF0000FF000FFFFFFF000000FF69 -:107110000000FF000000FF000FFFFFFF0000FF0066 -:107120000FFFFFFF000000FF0000FF000000FF0056 -:107130000FFFFFFF0000FF000FFFFFFF000000FF39 -:107140000000FF000000FF000FFFFFFF0000FF0036 -:107150000FFFFFFF000000FF0000FF000000FF0026 -:107160000FFFFFFF0000FF000FFFFFFF000000FF09 -:107170000000FF000000FF000FFFFFFF0000FF0006 -:107180000FFFFFFF000000FF0000FF000000FF00F6 -:107190000FFFFFFF0000FF000FFFFFFF000000FFD9 -:1071A0000000FF000000FF000FFFFFFF0000FF00D6 -:1071B0000FFFFFFF000000FF0000FF000000FF00C6 -:1071C0000FFFFFFF0000FF000FFFFFFF000000FFA9 -:1071D0000000FF000000FF000FFFFFFF0000FF00A6 -:1071E0000FFFFFFF000000FF0000FF000000FF0096 -:1071F0000FFFFFFF0000FF000FFFFFFF000000FF79 -:107200000000FF000000FF000FFFFFFF0000FF0075 -:107210000FFFFFFF000000FF0000FF000000FF0065 -:107220000FFFFFFF0000FF000FFFFFFF000000FF48 -:107230000000FF000000FF000FFFFFFF0000FF0045 -:107240000FFFFFFF000000FF0000FF000000FF0035 -:107250000FFFFFFF0000FF000FFFFFFF000000FF18 -:107260000000FF000000FF000FFFFFFF0000FF0015 -:107270000FFFFFFF000000FF0000FF000000FF0005 -:107280000FFFFFFF0000FF000FFFFFFF000000FFE8 -:107290000000FF000000FF000FFFFFFF0000FF00E5 -:1072A0000FFFFFFF000000FF0000FF000000FF00D5 -:1072B0000FFFFFFF0000FF000FFFFFFF000000FFB8 -:1072C0000000FF000000FF000FFFFFFF0000FF00B5 -:1072D0000FFFFFFF000000FF0000FF000000FF00A5 -:1072E0000FFFFFFF0000FF000FFFFFFF000000FF88 -:1072F0000000FF000000FF000FFFFFFF0000FF0085 -:107300000FFFFFFF000000FF0000FF000000FF0074 -:107310000FFFFFFF0000FF000FFFFFFF000000FF57 -:107320000000FF000000FF000FFFFFFF0000FF0054 -:107330000FFFFFFF000000FF0000FF000000FF0044 -:107340000FFFFFFF0000FF000FFFFFFF000000FF27 -:107350000000FF000000FF000FFFFFFF0000FF0024 -:107360000FFFFFFF000000FF0000FF000000FF0014 -:107370000FFFFFFF0000FF000FFFFFFF000000FFF7 -:107380000000FF000000FF000FFFFFFF0000FF00F4 -:107390000FFFFFFF000000FF0000FF000000FF00E4 -:1073A0000FFFFFFF0000FF000FFFFFFF000000FFC7 -:1073B0000000FF000000FF000FFFFFFF0000FF00C4 -:1073C0000FFFFFFF000000FF0000FF000000FF00B4 -:1073D0000FFFFFFF0000FF000FFFFFFF000000FF97 -:1073E0000000FF000000FF000FFFFFFF0000FF0094 -:1073F0000FFFFFFF000000FF0000FF000000FF0084 -:107400000FFFFFFF0000FF000FFFFFFF000000FF66 -:107410000000FF000000FF000FFFFFFF0000FF0063 -:107420000FFFFFFF000000FF0000FF000000FF0053 -:107430000FFFFFFF0000FF000FFFFFFF000000FF36 -:107440000000FF000000FF000FFFFFFF0000FF0033 -:107450000FFFFFFF000000FF0000FF000000FF0023 -:107460000FFFFFFF0000FF000FFFFFFF000000FF06 -:107470000000FF000000FF000FFFFFFF0000FF0003 -:107480000FFFFFFF000000FF0000FF000000FF00F3 -:107490000FFFFFFF0000FF000FFFFFFF000000FFD6 -:1074A0000000FF000000FF000FFFFFFF0000FF00D3 -:1074B0000FFFFFFF000000FF0000FF000000FF00C3 -:1074C0000FFFFFFF0000FF000FFFFFFF000000FFA6 -:1074D0000000FF000000FF000FFFFFFF0000FF00A3 -:1074E0000FFFFFFF000000FF0000FF000000FF0093 -:1074F0000FFFFFFF0000FF000FFFFFFF000000FF76 -:107500000000FF000000FF000FFFFFFF0000FF0072 -:107510000FFFFFFF000000FF0000FF000000FF0062 -:107520000FFFFFFF0000FF000FFFFFFF000000FF45 -:107530000000FF000000FF000FFFFFFF0000FF0042 -:107540000FFFFFFF000000FF0000FF000000FF0032 -:107550000FFFFFFF0000FF000FFFFFFF000000FF15 -:107560000000FF000000FF000FFFFFFF0000FF0012 -:107570000FFFFFFF000000FF0000FF000000FF0002 -:107580000FFFFFFF0000FF000FFFFFFF000000FFE5 -:107590000000FF000000FF000FFFFFFF0000FF00E2 -:1075A0000FFFFFFF000000FF0000FF000000FF00D2 -:1075B0000FFFFFFF0000FF000FFFFFFF000000FFB5 -:1075C0000000FF000000FF000FFFFFFF0000FF00B2 -:1075D0000FFFFFFF000000FF0000FF000000FF00A2 -:1075E0000FFFFFFF0000FF000FFFFFFF000000FF85 -:1075F0000000FF000000FF000FFFFFFF0000FF0082 -:107600000FFFFFFF000000FF0000FF000000FF0071 -:107610000FFFFFFF0000FF000FFFFFFF000000FF54 -:107620000000FF000000FF000FFFFFFF0000FF0051 -:107630000FFFFFFF000000FF0000FF000000FF0041 -:107640000FFFFFFF0000FF000FFFFFFF000000FF24 -:107650000000FF000000FF000FFFFFFF0000FF0021 -:107660000FFFFFFF000000FF0000FF000000FF0011 -:107670000FFFFFFF0000FF000FFFFFFF000000FFF4 -:107680000000FF000000FF000FFFFFFF0000FF00F1 -:107690000FFFFFFF000000FF0000FF000000FF00E1 -:1076A0000FFFFFFF0000FF000FFFFFFF000000FFC4 -:1076B0000000FF000000FF000FFFFFFF0000FF00C1 -:1076C0000FFFFFFF000000FF0000FF000000FF00B1 -:1076D0000FFFFFFF0000FF000FFFFFFF000000FF94 -:1076E0000000FF000000FF000FFFFFFF0000FF0091 -:1076F0000FFFFFFF000000FF0000FF000000FF0081 -:107700000FFFFFFF0000FF000FFFFFFF000000FF63 -:107710000000FF000000FF000FFFFFFF0000FF0060 -:107720000FFFFFFF000000FF0000FF000000FF0050 -:107730000FFFFFFF0000FF000FFFFFFF000000FF33 -:107740000000FF000000FF000FFFFFFF0000FF0030 -:107750000FFFFFFF000000FF0000FF000000FF0020 -:107760000FFFFFFF0000FF000FFFFFFF000000FF03 -:107770000000FF000000FF000FFFFFFF0000FF0000 -:107780000FFFFFFF000000FF0000FF000000FF00F0 -:107790000FFFFFFF0000FF000FFFFFFF000000FFD3 -:1077A0000000FF000000FF000FFFFFFF0000FF00D0 -:1077B0000FFFFFFF000000FF0000FF000000FF00C0 -:1077C0000FFFFFFF0000FF000FFFFFFF000000FFA3 -:1077D0000000FF000000FF000FFFFFFF0000FF00A0 -:1077E0000FFFFFFF000000FF0000FF000000FF0090 -:1077F0000FFFFFFF0000FF000FFFFFFF000000FF73 -:107800000000FF000000FF000FFFFFFF0000FF006F -:107810000FFFFFFF000000FF0000FF000000FF005F -:107820000FFFFFFF0000FF000FFFFFFF000000FF42 -:107830000000FF000000FF000FFFFFFF0000FF003F -:107840000FFFFFFF000000FF0000FF000000FF002F -:107850000FFFFFFF0000FF000FFFFFFF000000FF12 -:107860000000FF000000FF000FFFFFFF0000FF000F -:107870000FFFFFFF000000FF0000FF000000FF00FF -:107880000FFFFFFF0000FF000FFFFFFF000000FFE2 -:107890000000FF000000FF000FFFFFFF0000FF00DF -:1078A0000FFFFFFF000000FF0000FF000000FF00CF -:1078B0000FFFFFFF0000FF000FFFFFFF000000FFB2 -:1078C0000000FF000000FF000FFFFFFF0000FF00AF -:1078D0000FFFFFFF000000FF0000FF000000FF009F -:1078E0000FFFFFFF0000FF000FFFFFFF000000FF82 -:1078F0000000FF000000FF000FFFFFFF0000FF007F -:107900000FFFFFFF000000FF0000FF000000FF006E -:107910000FFFFFFF0000FF000FFFFFFF000000FF51 -:107920000000FF000000FF000FFFFFFF0000FF004E -:107930000FFFFFFF000000FF0000FF000000FF003E -:107940000FFFFFFF0000FF000FFFFFFF000000FF21 -:107950000000FF000000FF000FFFFFFF0000FF001E -:107960000FFFFFFF000000FF0000FF000000FF000E -:107970000FFFFFFF0000FF000FFFFFFF000000FFF1 -:107980000000FF000000FF000FFFFFFF0000FF00EE -:107990000FFFFFFF000000FF0000FF000000FF00DE -:1079A0000FFFFFFF0000FF000FFFFFFF000000FFC1 -:1079B0000000FF000000FF000FFFFFFF0000FF00BE -:1079C0000FFFFFFF000000FF0000FF000000FF00AE -:1079D0000FFFFFFF0000FF000FFFFFFF000000FF91 -:1079E0000000FF000000FF000FFFFFFF0000FF008E -:1079F0000FFFFFFF000000FF0000FF000000FF007E -:107A00000FFFFFFF0000FF000FFFFFFF000000FF60 -:107A10000000FF000000FF000FFFFFFF0000FF005D -:107A20000FFFFFFF000000FF0000FF000000FF004D -:107A30000FFFFFFF0000FF000FFFFFFF000000FF30 -:107A40000000FF000000FF000FFFFFFF0000FF002D -:107A50000FFFFFFF000000FF0000FF000000FF001D -:107A60000FFFFFFF0000FF000FFFFFFF000000FF00 -:107A70000000FF000000FF000FFFFFFF0000FF00FD -:107A80000FFFFFFF000000FF0000FF000000FF00ED -:107A90000FFFFFFF0000FF000FFFFFFF000000FFD0 -:107AA0000000FF000000FF000FFFFFFF0000FF00CD -:107AB0000FFFFFFF000000FF0000FF000000FF00BD -:107AC0000FFFFFFF0000FF000FFFFFFF000000FFA0 -:107AD0000000FF000000FF000FFFFFFF0000FF009D -:107AE0000FFFFFFF000000FF0000FF000000FF008D -:107AF0000FFFFFFF0000FF000FFFFFFF000000FF70 -:107B00000000FF000000FF000FFFFFFF0000FF006C -:107B10000FFFFFFF000000FF0000FF000000FF005C -:107B20000FFFFFFF0000FF000FFFFFFF000000FF3F -:107B30000000FF000000FF000FFFFFFF0000FF003C -:107B40000FFFFFFF000000FF0000FF000000FF002C -:107B50000FFFFFFF0000FF000FFFFFFF000000FF0F -:107B60000000FF000000FF000FFFFFFF0000FF000C -:107B70000FFFFFFF000000FF0000FF000000FF00FC -:107B80000FFFFFFF0000FF000FFFFFFF000000FFDF -:107B90000000FF000000FF000FFFFFFF0000FF00DC -:107BA0000FFFFFFF000000FF0000FF000000FF00CC -:107BB0000FFFFFFF0000FF000FFFFFFF000000FFAF -:107BC0000000FF000000FF000FFFFFFF0000FF00AC -:107BD0000FFFFFFF000000FF0000FF000000FF009C -:107BE0000FFFFFFF0000FF000FFFFFFF000000FF7F -:107BF0000000FF000000FF000FFFFFFF0000FF007C -:107C00000FFFFFFF000000FF0000FF000000FF006B -:107C10000FFFFFFF0000FF000FFFFFFF000000FF4E -:107C20000000FF000000FF000FFFFFFF0000FF004B -:107C30000FFFFFFF000000FF0000FF000000FF003B -:107C40000FFFFFFF0000FF000FFFFFFF000000FF1E -:107C50000000FF000000FF000FFFFFFF0000FF001B -:107C60000FFFFFFF000000FF0000FF000000FF000B -:107C70000FFFFFFF0000FF000FFFFFFF000000FFEE -:107C80000000FF000000FF000FFFFFFF0000FF00EB -:107C90000FFFFFFF000000FF0000FF000000FF00DB -:107CA0000FFFFFFF0000FF000FFFFFFF000000FFBE -:107CB0000000FF000000FF000FFFFFFF0000FF00BB -:107CC0000FFFFFFF000000FF0000FF000000FF00AB -:107CD0000FFFFFFF0000FF000FFFFFFF000000FF8E -:107CE0000000FF000000FF000FFFFFFF0000FF008B -:107CF0000FFFFFFF000000FF0000FF000000FF007B -:107D00000FFFFFFF0000FF000FFFFFFF000000FF5D -:107D10000000FF000000FF000FFFFFFF0000FF005A -:107D20000FFFFFFF000000FF0000FF000000FF004A -:107D30000FFFFFFF0000FF000FFFFFFF000000FF2D -:107D40000000FF000000FF000FFFFFFF0000FF002A -:107D50000FFFFFFF000000FF0000FF000000FF001A -:107D60000FFFFFFF0000FF000FFFFFFF000000FFFD -:107D70000000FF000000FF000FFFFFFF0000FF00FA -:107D80000FFFFFFF000000FF0000FF0000001000D9 -:107D900000002080000031000000418000005200FF -:107DA00000006280000073000000838000009400E7 -:107DB0000000A4800000B5000000C5800000D600CF -:107DC0000000E6800000F7000001078000011800B5 -:107DD00000012880000139000001498000015A009B -:107DE00000016A8000017B0000018B8000019C0083 -:107DF0000001AC800001BD000001CD800001DE006B -:107E00000001EE800001FF0000000F8000007FF8FD -:107E100000007FF8000005F60000350010000000AB -:107E2000000028AD000029180000291900000005F5 -:107E3000000000060001000100050206CCCCCCC900 -:107E40007058103C0000FF00000000000000FF0020 -:107E5000000000000000FF00000000000000FF0024 -:107E6000000000000000FF00000000000000FF0014 -:107E7000000000000000FF00000000000000FF0004 -:107E8000000000000000FF00000000000000FF00F4 -:107E9000000000000000FF00000000000000FF00E4 -:107EA000000000000000FF00000000000000FF00D4 -:107EB000000000000000FF00000000000000FF00C4 -:107EC000000000000000FF00000000000000FF00B4 -:107ED000000000000000FF00000000000000FF00A4 -:107EE000000000000000FF00000000000000FF0094 -:107EF000000000000000FF00000000000000FF0084 -:107F0000000000000000FF00000000000000FF0073 -:107F1000000000000000FF00000000000000FF0063 -:107F2000000000000000FF00000000000000FF0053 -:107F3000000000000000FF00000000000000FF0043 -:107F4000000000000000FF00000000000000FF0033 -:107F5000000000000000FF00000000000000FF0023 -:107F6000000000000000FF00000000000000FF0013 -:107F7000000000000000FF00000000000000FF0003 -:107F8000000000000000FF00000000000000FF00F3 -:107F9000000000000000FF00000000000000FF00E3 -:107FA000000000000000FF00000000000000FF00D3 -:107FB000000000000000FF00000000000000FF00C3 -:107FC000000000000000FF00000000000000FF00B3 -:107FD000000000000000FF00000000000000FF00A3 -:107FE000000000000000FF00000000000000FF0093 -:107FF000000000000000FF00000000000000FF0083 -:10800000000000000000FF00000000000000FF0072 -:10801000000000000000FF00000000000000FF0062 -:10802000000000000000FF00000000000000FF0052 -:10803000000000000000FF00000000000000FF0042 -:10804000000000000000FF00000000000000FF0032 -:10805000000000000000FF00000000000000FF0022 -:10806000000000000000FF00000000000000FF0012 -:10807000000000000000FF00000000000000FF0002 -:108080000000000000000001CCCC0201CCCCCCCC24 -:10809000CCCC0201CCCCCCCCCCCC0201CCCCCCCC4A -:1080A000CCCC0201CCCCCCCCCCCC0201CCCCCCCC3A -:1080B000CCCC0201CCCCCCCCCCCC0201CCCCCCCC2A -:1080C000CCCC0201CCCCCCCC00000000FFFFFFFFE9 -:1080D000030303031342020250505020706080508B -:1080E0000200020006040604000E0000011600D67D -:1080F000002625A0002625A0002625A0002625A0D4 -:1081000000720000012300F3002625A0002625A010 -:10811000002625A0002625A00000FFFF000000008B -:108120000000FFFF000000000000FFFF0000000053 -:108130000000FFFF000000000000FFFF0000000043 -:108140000000FFFF000000000000FFFF0000000033 -:108150000000FFFF000000000000FFFF0000000023 -:108160000000FFFF000000000000FFFF0000000013 -:108170000000FFFF000000000000FFFF0000000003 -:108180000000FFFF000000000000FFFF00000000F3 -:108190000000FFFF000000000000FFFF00000000E3 -:1081A0000000FFFF000000000000FFFF00000000D3 -:1081B0000000FFFF000000000000FFFF00000000C3 -:1081C0000000FFFF000000000000FFFF00000000B3 -:1081D0000000FFFF000000000000FFFF00000000A3 -:1081E0000000FFFF000000000000FFFF0000000093 -:1081F0000000FFFF000000000000FFFF0000000083 -:108200000000FFFF000000000000FFFF0000000072 -:108210000000FFFF000000000000FFFF0000000062 -:108220000000FFFF000000000000FFFF0000000052 -:108230000000FFFF000000000000FFFF0000000042 -:108240000000FFFF000000000000FFFF0000000032 -:108250000000FFFF000000000000FFFF0000000022 -:108260000000FFFF000000000000FFFF0000000012 -:108270000000FFFF000000000000FFFF0000000002 -:108280000000FFFF000000000000FFFF00000000F2 -:108290000000FFFF000000000000FFFF00000000E2 -:1082A0000000FFFF000000000000FFFF00000000D2 -:1082B0000000FFFF000000000000FFFF00000000C2 -:1082C0000000FFFF000000000000FFFF00000000B2 -:1082D0000000FFFF000000000000FFFF00000000A2 -:1082E0000000FFFF000000000000FFFF0000000092 -:1082F0000000FFFF000000000000FFFF0000000082 -:108300000000FFFF000000000000FFFF0000000071 -:108310000000FFFF00000000FFFFFFF3318FFFFFB1 -:108320000C30C30CC30C30C3CF3CF300F3CF3CF391 -:108330000000CF3CCDCDCDCDFFFFFFF130EFFFFFF3 -:108340000C30C30CC30C30C3CF3CF300F3CF3CF371 -:108350000001CF3CCDCDCDCDFFFFFFF6305FFFFF5D -:108360000C30C30CC30C30C3CF3CF300F3CF3CF351 -:108370000002CF3CCDCDCDCDFFFFF4061CBFFFFFEB -:108380000C30C305C30C30C3CF300014F3CF3CF323 -:108390000004CF3CCDCDCDCDFFFFFFF2304FFFFF2E -:1083A0000C30C30CC30C30C3CF3CF300F3CF3CF311 -:1083B0000008CF3CCDCDCDCDFFFFFFFA302FFFFF22 -:1083C0000C30C30CC30C30C3CF3CF300F3CF3CF3F1 -:1083D0000010CF3CCDCDCDCDFFFFFFF731EFFFFF3C -:1083E0000C30C30CC30C30C3CF3CF300F3CF3CF3D1 -:1083F0000020CF3CCDCDCDCDFFFFFFF5302FFFFFCF -:108400000C30C30CC30C30C3CF3CF300F3CF3CF3B0 -:108410000040CF3CCDCDCDCDFFFFFFF3318FFFFF2F -:108420000C30C30CC30C30C3CF3CF300F3CF3CF390 -:108430000000CF3CCDCDCDCDFFFFFFF1310FFFFFD1 -:108440000C30C30CC30C30C3CF3CF300F3CF3CF370 -:108450000001CF3CCDCDCDCDFFFFFFF6305FFFFF5C -:108460000C30C30CC30C30C3CF3CF300F3CF3CF350 -:108470000002CF3CCDCDCDCDFFFFF4061CBFFFFFEA -:108480000C30C305C30C30C3CF300014F3CF3CF322 -:108490000004CF3CCDCDCDCDFFFFFFF2304FFFFF2D -:1084A0000C30C30CC30C30C3CF3CF300F3CF3CF310 -:1084B0000008CF3CCDCDCDCDFFFFFFFA302FFFFF21 -:1084C0000C30C30CC30C30C3CF3CF300F3CF3CF3F0 -:1084D0000010CF3CCDCDCDCDFFFFFFF730EFFFFF3C -:1084E0000C30C30CC30C30C3CF3CF300F3CF3CF3D0 -:1084F0000020CF3CCDCDCDCDFFFFFFF5304FFFFFAE -:108500000C30C30CC30C30C3CF3CF300F3CF3CF3AF -:108510000040CF3CCDCDCDCDFFFFFFFF30CFFFFFE3 -:108520000C30C30CC30C30C3CF3CF3CCF3CF3CF3C3 -:108530000000CF3CCDCDCDCDFFFFFFFF30CFFFFF03 -:108540000C30C30CC30C30C3CF3CF3CCF3CF3CF3A3 -:108550000001CF3CCDCDCDCDFFFFFFFF30CFFFFFE2 -:108560000C30C30CC30C30C3CF3CF3CCF3CF3CF383 -:108570000002CF3CCDCDCDCDFFFFFFFF30CFFFFFC1 -:108580000C30C30CC30C30C3CF3CF3CCF3CF3CF363 -:108590000004CF3CCDCDCDCDFFFFFFFF30CFFFFF9F -:1085A0000C30C30CC30C30C3CF3CF3CCF3CF3CF343 -:1085B0000008CF3CCDCDCDCDFFFFFFFF30CFFFFF7B -:1085C0000C30C30CC30C30C3CF3CF3CCF3CF3CF323 -:1085D0000010CF3CCDCDCDCDFFFFFFFF30CFFFFF53 -:1085E0000C30C30CC30C30C3CF3CF3CCF3CF3CF303 -:1085F0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF23 -:108600000C30C30CC30C30C3CF3CF3CCF3CF3CF3E2 -:108610000040CF3CCDCDCDCDFFFFFFF3320FFFFFAC -:108620000C30C30CC30C30C3CF3CF300F3CF3CF38E -:108630000000CF3CCDCDCDCDFFFFFFF1310FFFFFCF -:108640000C30C30CC30C30C3CF3CF300F3CF3CF36E -:108650000001CF3CCDCDCDCDFFFFFFF6305FFFFF5A -:108660000C30C30CC30C30C3CF3CF300F3CF3CF34E -:108670000002CF3CCDCDCDCDFFFFF4061CBFFFFFE8 -:108680000C30C305C30C30C3CF300014F3CF3CF320 -:108690000004CF3CCDCDCDCDFFFFFFF2304FFFFF2B -:1086A0000C30C30CC30C30C3CF3CF300F3CF3CF30E -:1086B0000008CF3CCDCDCDCDFFFFFF8A042FFFFFBB -:1086C0000C30C30CC30C30C3CF3CC000F3CF3CF321 -:1086D0000010CF3CCDCDCDCDFFFFFF9705CFFFFFE5 -:1086E0000C30C30CC30C30C3CF3CC000F3CF3CF301 -:1086F0000020CF3CCDCDCDCDFFFFFFF5310FFFFFEB -:108700000C30C30CC30C30C3CF3CF300F3CF3CF3AD -:108710000040CF3CCDCDCDCDFFFFFFF3320FFFFFAB -:108720000C30C30CC30C30C3CF3CF300F3CF3CF38D -:108730000000CF3CCDCDCDCDFFFFFFF1302FFFFFAF -:108740000C30C30CC30C30C3CF3CF300F3CF3CF36D -:108750000001CF3CCDCDCDCDFFFFFFF6305FFFFF59 -:108760000C30C30CC30C30C3CF3CF300F3CF3CF34D -:108770000002CF3CCDCDCDCDFFFFFF061CBFFFFFDC -:108780000C30C30CC30C30C3CF3CC014F3CF3CF34C -:108790000004CF3CCDCDCDCDFFFFFFF2304FFFFF2A -:1087A0000C30C30CC30C30C3CF3CF300F3CF3CF30D -:1087B0000008CF3CCDCDCDCDFFFFFFFA302FFFFF1E -:1087C0000C30C30CC30C30C3CF3CF300F3CF3CF3ED -:1087D0000010CF3CCDCDCDCDFFFFFFF731CFFFFF58 -:1087E0000C30C30CC30C30C3CF3CF300F3CF3CF3CD -:1087F0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF21 -:108800000C30C30CC30C30C3CF3CF3CCF3CF3CF3E0 -:108810000040CF3CCDCDCDCDFFFFFFFF30CFFFFFE0 -:108820000C30C30CC30C30C3CF3CF3CCF3CF3CF3C0 -:108830000000CF3CCDCDCDCDFFFFFFFF30CFFFFF00 -:108840000C30C30CC30C30C3CF3CF3CCF3CF3CF3A0 -:108850000001CF3CCDCDCDCDFFFFFFFF30CFFFFFDF -:108860000C30C30CC30C30C3CF3CF3CCF3CF3CF380 -:108870000002CF3CCDCDCDCDFFFFFFFF30CFFFFFBE -:108880000C30C30CC30C30C3CF3CF3CCF3CF3CF360 -:108890000004CF3CCDCDCDCDFFFFFFFF30CFFFFF9C -:1088A0000C30C30CC30C30C3CF3CF3CCF3CF3CF340 -:1088B0000008CF3CCDCDCDCDFFFFFFFF30CFFFFF78 -:1088C0000C30C30CC30C30C3CF3CF3CCF3CF3CF320 -:1088D0000010CF3CCDCDCDCDFFFFFFFF30CFFFFF50 -:1088E0000C30C30CC30C30C3CF3CF3CCF3CF3CF300 -:1088F0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF20 -:108900000C30C30CC30C30C3CF3CF3CCF3CF3CF3DF -:108910000040CF3CCDCDCDCDFFFFFFFF30CFFFFFDF -:108920000C30C30CC30C30C3CF3CF3CCF3CF3CF3BF -:108930000000CF3CCDCDCDCDFFFFFFFF30CFFFFFFF -:108940000C30C30CC30C30C3CF3CF3CCF3CF3CF39F -:108950000001CF3CCDCDCDCDFFFFFFFF30CFFFFFDE -:108960000C30C30CC30C30C3CF3CF3CCF3CF3CF37F -:108970000002CF3CCDCDCDCDFFFFFFFF30CFFFFFBD -:108980000C30C30CC30C30C3CF3CF3CCF3CF3CF35F -:108990000004CF3CCDCDCDCDFFFFFFFF30CFFFFF9B -:1089A0000C30C30CC30C30C3CF3CF3CCF3CF3CF33F -:1089B0000008CF3CCDCDCDCDFFFFFFFF30CFFFFF77 -:1089C0000C30C30CC30C30C3CF3CF3CCF3CF3CF31F -:1089D0000010CF3CCDCDCDCDFFFFFFFF30CFFFFF4F -:1089E0000C30C30CC30C30C3CF3CF3CCF3CF3CF3FF -:1089F0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF1F -:108A00000C30C30CC30C30C3CF3CF3CCF3CF3CF3DE -:108A10000040CF3CCDCDCDCDFFFFFFFF30CFFFFFDE -:108A20000C30C30CC30C30C3CF3CF3CCF3CF3CF3BE -:108A30000000CF3CCDCDCDCDFFFFFFFF30CFFFFFFE -:108A40000C30C30CC30C30C3CF3CF3CCF3CF3CF39E -:108A50000001CF3CCDCDCDCDFFFFFFFF30CFFFFFDD -:108A60000C30C30CC30C30C3CF3CF3CCF3CF3CF37E -:108A70000002CF3CCDCDCDCDFFFFFFFF30CFFFFFBC -:108A80000C30C30CC30C30C3CF3CF3CCF3CF3CF35E -:108A90000004CF3CCDCDCDCDFFFFFFFF30CFFFFF9A -:108AA0000C30C30CC30C30C3CF3CF3CCF3CF3CF33E -:108AB0000008CF3CCDCDCDCDFFFFFFFF30CFFFFF76 -:108AC0000C30C30CC30C30C3CF3CF3CCF3CF3CF31E -:108AD0000010CF3CCDCDCDCDFFFFFFFF30CFFFFF4E -:108AE0000C30C30CC30C30C3CF3CF3CCF3CF3CF3FE -:108AF0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF1E -:108B00000C30C30CC30C30C3CF3CF3CCF3CF3CF3DD -:108B10000040CF3CCDCDCDCD000C0000000700C003 -:108B200000028130000B8158000202100001023067 -:108B3000000F024000010330000C0000000800C0DC -:108B400000028140000B8168000202200001024007 -:108B500000070250000202C00010000000080100DF -:108B600000028180000B81A8000202600001828067 -:108B7000000E829800080380001000000001010030 -:108B80000002811000090138000201C8000101E85B -:108B9000000E01F8000002D8CCCCCCCCCCCCCCCC94 -:108BA000CCCCCCCCCCCCCCCC00002000CCCCCCCC15 -:108BB000CCCCCCCCCCCCCCCCCCCCCCCC0000200005 -:108BC000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCE5 -:108BD00004002000CCCCCCCCCCCCCCCCCCCCCCCCE1 -:108BE000CCCCCCCC4100200003030303034202029F -:108BF0005050502070608050131313131342121200 -:108C000050505020706080500301020000000000AE -:108C100000000000000000001F8B080000000000A2 -:108C2000000BFB51CFC0F0038A0F093230688A2055 -:108C3000F8C4E05C760686751C0C0C5BB849D3075B -:108C4000C32C0C0C0CDA4CE4E905E1FBBC0C0CAFBA -:108C50008098850F559C871342FF015AC0C7CAC030 -:108C6000A0C1865DFF3A35043B408581A11C88D9AF -:108C7000941818CC5411E2D2EA0C0C3380FC04A8EE -:108C8000D81D201DAB46BE9B47F1E0C1378D51F981 -:108C90005B0DA169012A7E0B4D7E1B54BE4A074223 -:108CA000DF36C66E6EB50E71F69FB546E5AFB4C63B -:108CB000AFFEAE3D2AFF209AFAAD503E00C5D55B0F -:108CC000A7D8030000000000000000000000000022 -:108CD0001F8B080000000000000BED7D7F7C14D589 -:108CE000B5F8999DD9D9D9CDEE6608096C20E02454 -:108CF000861AFB82DFE577A841878034B63CDF8A9D -:108D00005AD3D6F6BB506C551456BF3EE1F56933C5 -:108D1000F941122262049FDAD61F2B554BFB6C8956 -:108D2000942AAD3FDE024AF1F5C743AAD5D7A22F58 -:108D3000FE80AA455FC4D2D87E51DE3DE7DEC9CEB3 -:108D40004C76930DD01F7FBCF081E1CEDC1FE79EF7 -:108D500073EE39E79E73EE8DEAF3C3C7CE05388E06 -:108D60003FECD913028059D9A771F5BCAEBE99006A -:108D70004721D2D35D0AD0A68009AC6C1D88A41F00 -:108D800094007F6A14565E2D7F3CDE5D097067D1CA -:108D9000D7EEC3FA6B2C0502ECD9DD0C9039837D3C -:108DA0000F453743314011A4B6E277F6937890F53A -:108DB00037109C9C866876FC32F0D1B80015FAA179 -:108DC00022AA07C765F6CF81E47C18072083FDB38C -:108DD000067A593FCAF3721AC795E5C5FA8B55D979 -:108DE0007EBC4F595721A389FEF01FF9B2E26438C7 -:108DF0007FFD35072AB73E5D93AD7F06444A0FFDE0 -:108E00001DFB8F020AC123AF07C4C3D130A4E5CA3A -:108E1000FCFD0C341B5B9FF6231EBF509C989ABF31 -:108E20009E8DA7AE668D9E1DCD3A6402000C64B384 -:108E3000B7963DC3606EAE1DDA6E0148842FCDB08B -:108E4000089EF6B02F5D5489502701187EFD881FBB -:108E500009DF2FD1CC1CEDED279432FCD8F36578D7 -:108E60000C02EF0FD8FC1E64FD0571FC1CF8BA085B -:108E7000C72F63DFAB878E6FCD3CF1F1436702EC08 -:108E80000B23BE4D84017C7A0AE282DE9F9486E940 -:108E900047D05931783F23E1BDA8C6971D97FD0DF6 -:108EA0001A21179F0462256EBEF1F225E2A90CE992 -:108EB0006548AF4FC9F6AB22DD72E0EB4A81AFFEE9 -:108EC000F989A604C3C7DA66B05E73B4936360A67B -:108ED00073E069B568678FA794B27A39FA076811A9 -:108EE000EBC772D52F14BE9B4E10BE9BFF42F0DD28 -:108EF00026F89D49287AF6CF4F129CDEFE72AD2FE0 -:108F0000B68807CB21256DF990BF4B21FE207BF859 -:108F100035BECEECEFDF073FF5B303250E1BA74DA3 -:108F2000C0D73F9FCBBFB5D3D4F46689E4910BCEB5 -:108F300087517EB1769224F0A1F502F25FD1070A43 -:108F4000C05884CF844404605D7583369CFC015D09 -:108F5000F9539FCD775543F9EEE36C18842B14CE6B -:108F60008DA7EF0FCAD1CBACD7583F5A90BD3F1D4C -:108F7000FB2D8D55CC069C1DFDF8C577907CF271BC -:108F80005CB7C758BDD942CECAD43FC911A8009218 -:108F9000F7B2A84FE3B0FA01362D733A7BE2FB1A21 -:108FA000318E34B45F6FBB0128E1F811F0D8725DE7 -:108FB0008627A89F41789404E1CBFBDECFDEEBE16E -:108FC000937F7FB265BF9167BC1E89F869A4F6AF35 -:108FD000087E19C29F79E8BA5FAC33057A4D383DF7 -:108FE000CB47367F9D281F9D349FB0E1495FE4E168 -:108FF000130B52B46E5835AB7BDAE8F925079F6442 -:109000009CF5174B63F83C9438F10B834721BED590 -:10901000393C65D34BA93F09D7F819D88328231EBB -:10902000D87C97D9ED214EEB3584768EA33D9B1CE1 -:10903000C12BC99290FBBCDE0D629DCF6BA8E0F006 -:1090400083E8DF032FEB4F73F627438587CF39DCA7 -:109050001B242EDF58FD0CE1D33BBE2211BC322471 -:109060002C1F6BB7598CEF955FF673BBE86FBD048F -:109070004DBD61BE9E9638F4618324E484C6D799C1 -:10908000573EF991AF669C385F152AD7174BB9F553 -:109090000EB38A621746F2EB9D629FAD0F323141EB -:1090A000B751D1FD74A9C445F742E15D7682F04E17 -:1090B0001C0A6F417C76A6E41B959EBCE104E10B83 -:1090C0007AE03B557C3D43F059A1F0DBEB60B4F016 -:1090D000CB43F15BD03A9A3B4AF8369F207ECB7C5B -:1090E000B69D24E0CBB36EE7097A5BC0F9436176A5 -:1090F00038EE730A85EFD191E103F804FB6BBD6A8A -:10910000990AD96B0013009E6E79D5B2942C7C26F7 -:1091100070B93EDAF1F78C4C3F31FE5B96599D1DDC -:10912000FFF996B75CE32B8C7F90D90A1DF7854237 -:10913000E70DEFB9E6FDBAF49E6BDC13C5FBC18207 -:10914000C7FFA36BDEEF4B7F74CF3BCCE67D7AE1AC -:10915000E3FEFE04F9B152AC97064977E9817CF64B -:10916000FB0C41D7BBEDFA36BC79EA9F29E06A2FA8 -:10917000B0FE44D1FFE70AACDF2BFAEFC5FA652356 -:10918000D73F5DD44F15585FF2F175984F7FCE975A -:109190006CFC816BFFD1A6713F88D9A640F09CA1E1 -:1091A0007E13AB21F5ED3E467BAB35A0B79592DF44 -:1091B00084FC226B0012E837F92624EB7CAC1F6399 -:1091C000C74DF761BD238AA677EBC01724FB1E3C71 -:1091D00010D9DC5D991D6FB59C6C929097DAA2FA5C -:1091E00083E45F493549EC59668575F4DB0C5425F9 -:1091F0005A9696E23C0CDD62FDFCFA8A8B76627927 -:109200009326E9322BFFCB39736FFB0C6B35F0E102 -:10921000CE974EC37AD3C655B592BC3425C44F6998 -:109220005C35E5287B5E7C71561FE03F8B1D6566D3 -:10923000077CB6E9122EFFC5F7CF27DDE54B1A2FC5 -:1092400071B5BF34E1FE9E9D0FF07DC7B9DCFF30E4 -:109250005095FA2F0ED7C72A2DEE5FA0F9EA565483 -:10926000EF66F35CFFE1B5545EDF52ABB7B2F2E7F5 -:10927000AEF4B72C65CFB004BACC9652715CA5F9A8 -:10928000029BAF5AC7768FE73CDB35DBC8BFFF2AAE -:10929000363DF38C5F9C8593CDB3E9EADC70ABFA85 -:1092A000FB13DE60F6D2C0CEA089F084F7CAE9A035 -:1092B0004474DD3909E9621527397D40AA66CF2358 -:1092C0008D3AA07FA4A13169C8ACBC31A6C5030604 -:1092D000DAC9190DF11E411ACC65EFE3BE20DA633D -:1092E000AAFE07EA5F17DF7BE255E3D13FF2E3E630 -:1092F000351315B6DE77345BF47CB4B98B9EDB9BFB -:109300007B262ACC88DFD27C173DEDF9A12431ECF5 -:10931000F9C9B8AF365B91DF06FCCC34423CCEF7DE -:10932000D1FE7603CA113FCAE1745B14DFD7C1B422 -:109330006E40B9C4E5CBC6F8B6DDF87E633D4C435C -:10934000926D3437B745D93CAE2B87E9D8F7CE9725 -:109350001FE3DF2B607A8095773536905CED89FBD3 -:10936000D2814A82FF7CE4E79E461F3093078AEB56 -:10937000185C0EBC0662EEF2AE4626B066123ED215 -:1093800001293B7F852D33C4C746B32AE8DC57CF7C -:10939000DAE76E7F66DA5DDE88ED87F14BCDED733F -:1093A000D79FF392BBCC24DB2B837CC0F1F8AF3E7C -:1093B000260F76BF3CDE67E1BC4D3E4FF6E4FEC2B1 -:1093C000982F8DC6E716813F1BBF03112E5F3636DF -:1093D000733F603E78367EEAAAD8707E03B5B1232B -:1093E00081FE54B5B1270167E1332D9EBD09A79FCA -:1093F000D57EBE88C68FC35FD211DB58B2B4360BA0 -:109400008FB7FE785925793750C6BF77C45ED3979A -:10941000D63AFB93BCDFB5CBC3CEEFDCAF32506E98 -:109420007F3FA22D0DE7683F897DCF4197A532FF91 -:10943000FEF4CB81863B901F057E77BFFC13AD1AEF -:10944000F1FDBC0CC8671BF73590BC453E4379B1B4 -:109450008BF1455F2DD27FFD2BCE755B5CE72E3304 -:10946000BEE2FCC5FAC5A17E86F4601DFEBBF0CB52 -:10947000EE157ED93DCD317A3EDD6CD07357730D3C -:109480007DCF34C7A9FC54731D959F6836A9FCE3B2 -:10949000E6462AEF684E50F9D1E6267A6E6F4ED234 -:1094A000734BF315F464FC4BFCBCA13925FCC06B79 -:1094B0005CFCF0F7F1808BFF3E5DE32E9F6F9C918B -:1094C0005DD7ECEF2763EEF279FA275DE5059ABBED -:1094D0003C1FBEE2EAEFDC0FBEEC2ACFEBEF70D50B -:1094E0003FFB4D77796EDF439EF5E22ECFDAB7C7AB -:1094F000B31EDDE5E2BA43AEFE023177F97E1432E7 -:109500005C4E117F74C45A4B72F2CFE0F78DA12FDD -:10951000B9BECBD47E64FE59D65589FC93F6C52DD1 -:10952000943B26E7275BEE78F9C4A6DB48FC65C3CD -:10953000F197E6ABFFE5A7E1F9A9607EA85772F2C3 -:109540008397EE5EFE18226704BFFC2F1FFC6DF0B0 -:1095500001CC64C42ECFAF5773D877649F061240F6 -:10956000F69D1FED34477B75722A69E6D09F57F947 -:10957000E66F95593F8152E8C0786840C9E3E795A6 -:10958000F93E25A0F1EFC16A93ECB26230A6CB633D -:1095900000AE796C5EF932F6FEE7421F765C089603 -:1095A000C4FA1B37414DE23EA6B8DABDDF7B46E682 -:1095B000FB18FBB9E9879126FC0EA5334798378F36 -:1095C000D7C8136737FDC660CF0B666F59CBDE86F1 -:1095D000AA9319F2019596927D9A0C19D4AF5997D6 -:1095E000B67CA518478338DA8972D884241B67AE05 -:1095F000CFFC05CE9BD947FF21CFCADA3D9BC4F3F0 -:1096000047621D5EE4337F29EA3D3F5C3D7BDC1110 -:10961000E905494BE2FEA9F8830C447F69DC653F0C -:10962000D9F353948499C8616FFC4EE04BD2E34D5B -:10963000DC0FA202CA877CF50FCAB6FFC972ED071C -:109640008BA13F23231C311E6F82631719174E1DF8 -:109650000A87AA2492380EC6AB37B371DAC77CC624 -:10966000483AC6F948E67E2A2966123CAACEE1515C -:1096700095B899C8C14703021EBB1F3B6E26C5FAA9 -:10968000A12F9C856F6D30D184FB256B8C4A786A45 -:109690008FB8EDAF190AEFA75A3CDBFDB9ED438057 -:1096A00056BE1F1E57A761FF6D750D1ADAD78C1DA8 -:1096B00068BFD21E5E523C9CBDBD5ED8BFDD280F88 -:1096C00003180FD785BC8AD1B33DBCAD11D7C1D12A -:1096D0005A8687CAFCFD44E2EEB86E514DC813C7E6 -:1096E0004D139C41A3C413EF9DE06AE71FA7F8EC5C -:1096F000B8364823C3DF21E0B7EB752A294DCF895F -:10970000273EBE5D0EC4DCF0FEF9F0C7DB17F97B27 -:10971000F55C709D2ABCE58BC3DA4F75AC9A4A7331 -:109720007F4ACCB90E3E2BF84B1DABA5483E69F9DC -:10973000BE8778FB7082FC5B5A38614055361EABA1 -:10974000E17A70E0E95AD1EED78A4FACCB540CFDE8 -:109750005C92916A427ED22AD83A9286B6B39F49E9 -:10976000D1BEF3C3FFF712AD93328DD68964B075C5 -:1097700094631C4931AF56D8F31DD9BC46C1F8CC0F -:10978000477232D77A5921E0D116270CAD8A427838 -:109790003CDFC303C73A85EB834336FC568AFC564D -:1097A00085C2BFA640F8ED7118FCED02FEB5C3C13D -:1097B000DF26E02901A3857C990697B300171ACE0E -:1097C000BC8B37C4F825424E314C11DDECEFFF2540 -:1097D000FA29743E1B059C23CDE78D2C3DEEC579FF -:1097E000B0F9DC87F3CA379F7B041C6F285CCF6815 -:1097F000898411AB22559F93AF9E1070F42B228E5B -:10980000665D3B2ABEFAD702E7F144962E8F09BA6D -:10981000EC186E1E8F8A79F4C830F70DF4339E2E43 -:10982000F40E2C71D1E5A8C04F4FC0A6CB752EBA4F -:10983000FC4ECCABD0F93C53209F1DCDD2E5393145 -:109840009FFDC3CDC751FF4551FF25519FFCE74701 -:10985000952B5AAD5AFC9E38A0CCCA8EC7EABDECF7 -:10986000AC776DFB2CBBDEABC80F5223D783ACDECD -:109870006BCE7A605DD08AF6DB5A8C897E02E081FD -:10988000F6AF3688766F52BBC583FDBF25D607B5C8 -:109890005BD73EBFD50A53BD77F07DCB828FEC7A84 -:1098A000EFBAE15D61C37184E04D0CC2F1BEB3DE7D -:1098B00013CAE7A9BF217947B19282EC1F7F699251 -:1098C000F2F74A20D283FEC50E2545FE640C36A071 -:1098D0001F7275204EA92A23F9A3CB2EE6ED7445FD -:1098E000237F6A005270177BBFA154A1F8C862257C -:1098F00019F1A31D21252D0AAE827E590BF63FD604 -:10990000A0FC2F1B9EDB8ABED845FD3078B0DF3B24 -:109910008BA23B91AF364E520DE4AB9D936E20BFB0 -:10992000F96D2D3C7FF0B6F355DA676D7A3942FA5E -:1099300077AD12FF2CD6B74CD5403FFAEAD0472F6F -:109940002D67E5BE96625D3A87E641705B3E48B49E -:10995000CD74E42332B80371CAA7233FDC6D8D3C7C -:10996000AEC37ECAB1FDEA0546BCDB40F1C5E418D2 -:10997000FBDE59A792FD7A5B45D57C1C6F539D4653 -:10998000F6C6A6C5552DE4C7AB0B91BFB2246C48F3 -:10999000E8678FCE519901CECAA5460BDA9B91D9C3 -:1099A0002140BF5349051F2F7206901FCA0F3D89E2 -:1099B0006AF68C76A990198BFD2DC97C09ED99BAB0 -:1099C00000F9E1D9C4F6D78EA39437FE23FF0C101B -:1099D0001EFF441910EF367DA33D83ED87CD638CC8 -:1099E000A60BAC9729AC5EA44B81CC8C02EAF51493 -:1099F000582F5D60BD0CAF17800B87CDE78338CF44 -:109A000023D4D81F9EC7E8C82BACE4F6BBD36EF1B5 -:109A10007BBE8F362FF42ABFC80B9D0373785EE898 -:109A2000F0EDED7CD091E60BE0CBC2298F5C7F6D31 -:109A3000F3F07E63FFB81B62987FD959F655F1BCED -:109A4000913FCBC5FBF2353194779DE5E27BF98DF3 -:109A50004DB9F6AF77FAB91CAE81C4B0742811F0D5 -:109A60001F62B0637E4F8DC2EA47F2D7574B7DC36A -:109A7000E6596A8AD540EB76B18FD66D008501AE86 -:109A80009B0ABE8EFD904A54F37855B4DCB17EFC3F -:109A9000F57B68FDFCA25C06A98EE813473C7AF9C9 -:109AA000C4CB170170942B4F9E4FB6FE99F8C4DFBC -:109AB0002517B47EFC3D05D64B17582F53583DB59E -:109AC0004B2A48AEA83D05D64B17582FC3EBAD9D8A -:109AD000AB727D0E7F68C578BFFF139AABBCF613DF -:109AE00021F7F7B3C3AE72C72C777B75B6BB7DC7C2 -:109AF0006C777B750E6F1FEC800518CF2F749D1C43 -:109B00003CC17552A30D5F3F5237C2BAD2F420B6A2 -:109B10002F510CC89492BE4A0BBD95331E7E9ACA33 -:109B2000D77F959FC7CF6F53F420EE23FFD6E72949 -:109B3000A93C9FC09EEF48F0DAF2F7B7B2B0B7F297 -:109B4000E47D438C9F7FF043288E768EB1506B78F6 -:109B500085E1D1FF2CCF7BF7F6FB8A9A9CA63AF6DB -:109B6000C5CC3E83A4C30F737E99C2F36D181DD07C -:109B70001E5221D158C9FA6BABF0913DA28447D057 -:109B80001B150EB995232F2FEB970213CF53D02718 -:109B90000360FE9B7CDC501C08EE08F4D166BA180A -:109BA00053E54E07180386C493BEE212CF13ACD719 -:109BB000519E95064F75BF9751BF92791B1C2F1A66 -:109BC00045BF4A1FE5CB9CF27E478037087753BFDD -:109BD0006C97547A7C6CB65F7F2C452F314F56764C -:109BE000E4CBE1B908CA37F1C53394DF30214AFB31 -:109BF000B2B5A5D7B9F2C1FF59AD72F98754BDE32B -:109C00005A09E3BA15579B7DC3F079331357E4F72C -:109C1000AC586EF6D5E4AF3798A78FF99E39D64188 -:109C2000879A4CA3FD6E4D0EF3FDBC92227F63A775 -:109C300054321DF32DEC7A4A0593B40CAEC84CD3C4 -:109C4000C2FD5EE7585F1CED5405D6EF93CE62ED82 -:109C5000E4C571A7FFD2FB542A94B79DF3B95D65A3 -:109C60007A12E1147AB26D047E1FD1EE51E3C95C21 -:109C70007ED16FAB7C5FEB0FE5FEDE176A78409D0F -:109C800035146F8F217E717F3B06BAA4FFC3D9873D -:109C9000F2A52AF6BC8478585BB62836DC7CD90657 -:109CA000EAF0205D18897F16321F4179300C1C3F85 -:109CB000CC0507840BF37FEB0BE3C48783F65229B3 -:109CC00088FD98199518DF870457DE32737306CF25 -:109CD00043F897864DA49F6C6E01F457DB76936C26 -:109CE000865EF5113DEBB9FD54C3ED2193FDC179BD -:109CF00044EB87B7AB654FF939D56D0FB535EF003C -:109D0000679E9BF75C85FD4C871A5ECC8D8FC2F6F3 -:109D1000C3B7337EC13CFB8DCD1A22057A9A752AD2 -:109D20006F688E51797DB341CFF6E61A7ADE8C4D9D -:109D3000E7E2F9A7545725C35B57EC81D8E5ACCAD5 -:109D4000ED283B288FEFDE05682F770F96D93690E8 -:109D5000C1DD3D09785E9F7AEB02DCE7770741F8C9 -:109D600015DA16A05D9D2DDFD1361FCBC2CF10EACC -:109D7000BC6F01EEF76F17F90FA098DA250EBD77CB -:109D80005AC04FFC477B576A6FB5617F414594E1EC -:109D90009105EE3298084F50E3E505816DD43F8977 -:109DA0000036DEA7033FE0E34D11F96DB54B46C029 -:109DB00023F7EF5BAAC1FD5DB525143F52E3717433 -:109DC000BFC2ED6304DC05F6034A92EB3B718E2FB4 -:109DD000FFBA1941AF093846A23F4307F9D1EDF365 -:109DE00069CA0BB9F5F4A91EF776FFE8F0A2D6F51B -:109DF0005B7886ED09353927C0DA47CCDE4C252B58 -:109E00004717672C5ABE058E3B3660E7392669FD39 -:109E1000DB7856746E77ACF0D0D15FCAE3754171D0 -:109E2000FEA4507893AA1847F4030F37940F67AF36 -:109E300095257C68840DCA8BB18D21E19CE1E531CB -:109E40006689AB5C5C37C1553F12AF727DF7EB1F83 -:109E5000777D3F513A5DE299C7A784DD6897CFF5DA -:109E6000CEB3C07E0F1627560570DD34404D8AE113 -:109E7000F5CE2F3C44F80F0DAED385ED6605E58396 -:109E80008B753D8F9775FB7B5DBB59CFCA86FD7D7A -:109E9000062F9BF6F738AF6FD9DFA7F2EF28F759F7 -:109EA000F96B9D67B45BF81D5AC96F0B152958E211 -:109EB000A0CFD8F10DAD08DFF8CBD2318BBDEFFECE -:109EC00050E6F2007A62CE7A776ADC0FFDCC943BE2 -:109ED00062E8AF5C77E64331207927E58C07FE3CEA -:109EE000C0F3C5CA42899E00AD77B3BF98F1E1A126 -:109EF000876483EB21E535D4873E8BE7E3AB10DF46 -:109F000067A25D54C3FDD521F19DE85899AD3F4846 -:109F1000574FF9EF34AED77F87491B0CCEEF159B17 -:109F2000F7D0B890961AD97AAFB0A01FCF1F81B0E2 -:109F3000FB26F2A6509A48939F6F12C3A7CCBE4F40 -:109F4000BEB8BFC5CF706D5CA6FB7089542D8FFB6A -:109F500048C00DDA9163A5E3ECF93DA417CAE39B71 -:109F60005280FA7BED990F35215E02997F0283E1E1 -:109F7000ED1F27A5C040FF6F80C315B8AC07483E52 -:109F800057F7109EBDF85A3788F7B40BEF3F0970AA -:109F90007F7E2CC9DB0DD65358BDA943EB75077BDB -:109FA000E6AB68BF4DE178F48EF35E4012E776DDF4 -:109FB00070D8FD7AEBDF1210716D2D4DF18D67CEEB -:109FC000BC21867EEDCE298CFEB5F9E97F4B80E77A -:109FD0005B19C76E22B9DB3D6923C533D7556F26A0 -:109FE0007BF228B323F0FC747765EEF69DCD3C3F01 -:109FF000E65CB8BBB18AD1A7F37999FCB4DE7ADF0D -:10A000000954B9E28D5A857B3FC8F8AF0FE5E8489F -:10A01000FC27471EE0EB72947C8766213FCF50D629 -:10A020008EF6805F94EF0E1C6F13FA9FE47FF9F2B7 -:10A030001E70E64BBE2FF82213E0722658C1F9A31A -:10A04000DB6F494EFAC5D8FBF98E76F9E8968F1F7B -:10A050001E17EBE17D25DE44CA5F49E9B9E4B3127E -:10A06000FBF42F173ACE7BB52B694D47F86B364A78 -:10A070004EBBF61B6632A439F627A1D805BF5C8813 -:10A08000FB1F259E739FFE29D38C6A6CFC9B9B61F2 -:10A0900046359E4B50AC00D6BB59C934D2BEA2DA6D -:10A0A00047FEF27515D7EDC53C2BABD617C76A6DC9 -:10A0B00015BB1AAB0CE4976D9467FAA6BE2486FD17 -:10A0C0000462EA8CEAB194DF9DC079876B59BF0EB8 -:10A0D0007ADBE3DE2DF8F65BBA3959E3F2E034EDD2 -:10A0E0002F200FDE87788C1B590CCF39F65743F1A0 -:10A0F000CCF3043A2B86E0798EE6E0EB00E27906B9 -:10A10000C9FB9CFE0B86E7B35D780686E7A9593C40 -:10A110007757703C77D66CEEAA72E2B966D7DE4A02 -:10A1200003C7E7787E48E3E773438867079C5E3C94 -:10A1300087255BFF7CAC1DF9D6CBF70CEF7F8FF04A -:10A14000D8EF3F0AFC82ECE1B1E313176AE43F4920 -:10A15000D1FEE94E29AF5EBA442B402F758A757443 -:10A16000A7C03FEBFF0BD47FA9E8DFD6B7421FFEA5 -:10A1700083F66F0B501FB27ACBA89E9EA27DF06033 -:10A180003D0B86D5A3ACDD95C447614FFF268C4AB5 -:10A190001FB37EAEA37E34CFF8069C949E67FDDE8F -:10A1A00044FD2A9E7E4FB13DC1C6E926FC81070FC2 -:10A1B0007F663B2696F4F083D2E3927B363F942F62 -:10A1C00077D7CBAFD77AB85E1B6AD710DFFEBC73E8 -:10A1D000CF6EDC27BDA99BDF46BC8E761DD876608E -:10A1E0005928B94DE376209D83B0BE51946E636DBE -:10A1F00095E33D511E7F77EBA3F1B63D54CDF5407D -:10A2000070947A699FB0D73AC6301955CC9EFE44F7 -:10A21000532E3FC3339A9DB7E6B69B7F8373243F8B -:10A220005182FC6BEDB1CFECE863B4331B7B20971C -:10A230009C4F86923FC7F9A9BA65927A15FE917C28 -:10A24000FD9626AC9D7B6792DCEDC7BC461072186C -:10A250004D6BF4C74519DE0E69E4C288A37FADECEF -:10A26000626B3ECAB10AC62F587F5CD33E29992B38 -:10A270003E6EEF7F10881CFB97719F9B9DA47CB85E -:10A28000C53347D8DFB4D8F6EB6F715E87D49E0B29 -:10A29000A638F06ED3E90E2971E179284FE7713ABB -:10A2A000158F924E03824EB098E7A19E7BEC5C8D99 -:10A2B000FC8B115F02FDF0417F8F5EE2E0A3713EF7 -:10A2C00048F68E02FE7AE8DF7D1CF77F611FED778E -:10A2D000BBC3CBBE83F7EF58BA1A9F6264C7ED6663 -:10A2E000FABEC4A17FBCFEAAC17DF4E2C2F265A79A -:10A2F000587328DE9FBD3FC89D7FC018AB06F3860C -:10A3000056CBDC7F7E67D1D7280F618D15D003A592 -:10A31000A4C7C8FE5B27F2D93A453EDB5A91CFE687 -:10A32000B7566FC5FA9B0012E8976C9997A2787F91 -:10A3300054D1F4D638C2919A837A225A6AAFCF1F89 -:10A340002FC4F53958B6BED1DEC0E61B8DD9E58DD8 -:10A3500064BFB5B77079F3D9E00B0BAD7A64C53E35 -:10A36000A2C7A6BA25C5308C3F325CEBCE9F0B55F9 -:10A37000875C65ADA2C455564B270C1BB7F819FA7C -:10A380008966E17CFA208E70E6C9179E12E476B6E3 -:10A390002C4FEBCF60BEC1D96A7CB381E7A8DD79D1 -:10A3A0009CED416E0F3E8A0E218AE30ABEA8E3713E -:10A3B000D5A2B955BD180782319C2F304FD0C90F97 -:10A3C000F9F8E2AF8D1F5FD1E118E65DDCD21A0526 -:10A3D000CC73B965EEAFE21903E56A5F0CF333DACB -:10A3E00098246965DF37CCFD9591CB9F7C404B2E3F -:10A3F0000F22FEC209B2BF223393F4FC6BCF6B2451 -:10A400007ADE19E47A6E8AA0A782F49C99A5E7BA4D -:10A410003A46CF99D975BE4EE9D10AA1E7F9387EFF -:10A4200019CAA1FFA67DDBCD75BE46944306F45242 -:10A43000FEED865A9F0FFBFF6BE1C5862B3C97C94B -:10A4400047A25326817A61435CF1A11CF99BE3C3C7 -:10A450008FFAE87D017CF8C35C7CB85CD0432EDACF -:10A46000D7942BEF6E4A5072E1653DD28BE3A591F4 -:10A47000E3C5F757C1CBA0BED0922B916FAE88A990 -:10A48000B4EF564ABA3A285EC4F41EC61B56C8A694 -:10A4900081F126F8969FDFC7847ADBA15FFE180C56 -:10A4A00072FB445EBF88E2186C6AB82F63E58F0DBB -:10A4B0001B0F4DFBFB9DF79478F3325E0BBAE31054 -:10A4C000472A961423BDF2F5F776F35E1DCFD5DA51 -:10A4D000F919DEEF2B6448E53AB72885346167F651 -:10A4E000AA84871B99AE9D86F8F8D8423C9FD9591B -:10A4F000D13A8EEC1871AE61C5966775C501E70A51 -:10A5000085A9BFE943E763E37705AAC91247FBF4CE -:10A510005E577B6FBBC1FE447B66B7F9430C3E536D -:10A5200049EDC578B37D7E43DD323F436A330FDCAE -:10A530008C8E270577A1E7388E3CD0D681FB6DB491 -:10A54000BF3EC1F8E4B78FC8F156F6F58ABBCF58C5 -:10A5500088E75A0F01E7179B3E6F3DD0362E175FF5 -:10A56000E4A3CF79A12087E714F3D759210F7FF512 -:10A570005E549C8153CF5F8BF3F197C0CFE15E8E29 -:10A580000FB86B6C4E3AE59BCF209DEC7682CFBC2A -:10A59000EDF3B5637C95E07C95899E5D085F097855 -:10A5A0006DFA9D2CBC23F155608D6CE079AE4A2587 -:10A5B0004172B3B3F43A4BDCEB48F99E72CFB48CE2 -:10A5C000B8D74AE4B54306ED8940A949767448DC1A -:10A5D000CFA355BBE5A612739F9B8835253276BF66 -:10A5E000E8BF0CAC5169DCC1F8711832C12896790A -:10A5F0009C14C51FEE2B02F04DF27BB27639FD9E06 -:10A60000F65311F96A98CB4BF7B2C1E747C86F719F -:10A610008F13BB78F8FC1A6F7D082BC62107DEF379 -:10A62000B753E090639FB341DC2B6AE3DFDCB29465 -:10A63000F2CA83E08BD3FE20D661E1BEAF43ACE724 -:10A640004E7CCEC573BCD375DAAF55F0788B257DC3 -:10A6500099FC0CF6B9337B3CFBBC995D6F24FAAFD7 -:10A66000C6F594637DEF0A717D3AF0B5D47FE33E81 -:10A67000C4FA1318780FC5E3CD1F509CFA9CCC5B2D -:10A6800032FAF79F098DA37ECEE9EF931738D6E50E -:10A6900039E21C0740AF9CEB9C97DF0AEC427E78C6 -:10A6A000EA30DF8F3D75F808D9E14FFDDE9746BEF1 -:10A6B0007BEA83E1F31E1E17FB22BBDEE3BFE7F656 -:10A6C000D9E34A6F512EFB2E3B7E9AEF070FBBF961 -:10A6D00015945E19F965E0A67D32FA071E6FD6A4BF -:10A6E000D799FC9927E679CEE13E19F74D23CD6B3A -:10A6F000AB87BEF63CB7D6737B746BFD9110FAFF47 -:10A70000B73EC1E77BB49E9F8FCD07EFAE669EDF5D -:10A71000B1F589DCF86898C7F7C70D7EA334A75D4B -:10A72000EB3967B54093DDE7BB4E317CBBEBB9DD60 -:10A73000B55B89874F049EBCEBBBAEA711DD08510A -:10A740004836CE9708BDFB5D7E92035F6FF932E617 -:10A750006B2C0D9B12EE65A12FF3249B5789A92525 -:10A76000F0DE98E2FA1E6932E677C4781EF937AF58 -:10A770007E2DF3322BDFDC5444655D379E5B84F81D -:10A7800028D5C99F72337A5C48407F732DE627D065 -:10A790007A64E5C0CD3DE7A13F4B012E2F98C56BF4 -:10A7A00028E3E85E3F72D2E4931BEC473A1EC8B63A -:10A7B000CB3B4F4FDE6D00960C2FC796F3FA16FB7E -:10A7C0008372A8C49367A22F74E7A5443DFD4F454B -:10A7D0005BB5AC80BCF2931C670C6CD30CDC67D708 -:10A7E000FAF434D607630CE60D861B9981C4E83968 -:10A7F000460709CDE591F0BE0EA091FBBF33E03CCA -:10A80000A7D350C4E5D584AB6E97709F7134CEB892 -:10A81000621A96DFCC997FD52EE4C76059DF45F2E6 -:10A82000B4037AF7525C20E9233BFCE6DAD631CE5A -:10A83000F64B8B24DB1F28E80F86323B4B7F363FDD -:10A840003378D65F8EFEB1E56EBC8F962ED714712D -:10A85000793512FD4F761C9B6E43D7478BA0DB03E7 -:10A860001417EDAE195EEE0FA5DB36D277E1DADC18 -:10A87000F9BAD715492E796C3F3548419CF1892C9E -:10A88000EE6796C7CF6EBA7F18F9233BEF67866CE9 -:10A890003FE38C1E13E356E3A1C7C473DF8CA7E329 -:10A8A0001940FE3601ED24661E111FC99EFDDC46CF -:10A8B000C14741789EDAB35560E9A45752A03BF2F4 -:10A8C00054CE93C371F45FACD3C3742F12CA4F9E9E -:10A8D000BFC3F3FC8B39480CBFFD80F22D542E838F -:10A8E000857EBF7A01AFC4F80EF3FB0FBC7500F78D -:10A8F0002BE1996E3A29078A28AF2DE43D2772E0B3 -:10A900009A6B687FE3A1E368F3FEBF5F24ECFF224C -:10A910000893DD24DAE7CBDFB3ED7E1BBFC6B108B9 -:10A92000E5ED741C90081F659313F7E3FE0C7E257C -:10A9300003CFCB0413F3F656FF74167D1F1A574846 -:10A9400054225DDE3A50A4B75616922F9948B6B0FD -:10A95000FAC68140BCD520D5E2D3908E7D12D1516C -:10A960001AA751BED6EA7FF7DF1F18265FCB8E3FAE -:10A970000E96158BE29B5DC674CD294FCA42C95F06 -:10A980001639E3F622AEEBF5AF07C3EDB16760F41D -:10A99000F18FD2F120E2F29F5F84F64B17AE019E59 -:10A9A0001747797A5DE5BCFC46D1944518DFE98A02 -:10A9B000F07271F8C8792D246713E4FF5BC3180E99 -:10A9C000F1087BFDE21E4963FC85C3C80BEFFCD791 -:10A9D0002BFB284FFE9EF0FEF3CF40FAC47DE48FA0 -:10A9E000BBE7FA6DAEFB93DED41BDE2FA2F5AAB750 -:10A9F000637C7A62D2CED774C74526A0D660F39B1B -:10AA0000C408E3677838ED626845B6A9BCACB71CEA -:10AA1000F7C96B4BB78DE1E7FD17EA87C86E972939 -:10AA20003E9D0F5EAF9D9E6FBE76BCDDDBFEAE0829 -:10AA3000BF47D51B17F3FA831E44FC9651FE2C60CA -:10AA4000FE6CA7BF2F673CEA8D22EED76CAF5894FF -:10AA5000B81CE7A598730F327CDC5B1AA57D90FFCC -:10AA6000A2DA4B7D0E7BC3CE6753C47ECE5F9A22A3 -:10AA7000B9A86866D719182F7A5EC61505153D3B2B -:10AA800025B4E7EDFB2010AD174FE5F3C579058040 -:10AA9000DBC5785EE1B863DE1073F8C1509E88FDB7 -:10AAA000DB29A0F7B4F0ACA1F49DDFC5F3D0635768 -:10AAB000F0F34D1395DCF41E7F99EEE3F1AF534BA9 -:10AAC000E77CEDF3C53DEF8AA8B47EA6E8ABF7E2DC -:10AAD0003D771D567112E33103FE5417CAAB0DFFCB -:10AAE000E883CD34FFD1E937454FD03D7A15297D34 -:10AAF0003A2EEF7CEDEE48ED0A129E2D9ECFE0FD42 -:10AB00007E7998EB9B9E94EF36FC6E3E9DDAE9C70A -:10AB10007D678CEFABED7D783294BC3CECB0CF75AB -:10AB2000D3223E9A92BC94E4C0405961F72F0CE2C4 -:10AB30002B4F1EF31D11AE97A718AB79BF9386F765 -:10AB4000CBDA78F9A04B16BF1721134438FC8C914F -:10AB500013B82E6EE472E2EE35BBE8BD7263DF7CA3 -:10AB6000FEBDBF05F5EA1D3EB82297DFA82DC2E362 -:10AB70004193CDCC3AD41B93533E40FBF4F688412D -:10AB8000EFC75FC6F1D43509E238EC69D81FFBCFB7 -:10AB90009E4A95F4D2D852A0FB92C6AE01D2DB6396 -:10ABA0006B206DB072D7CEB93BD1BE55AB218EAE06 -:10ABB000EBDD953758680F6CAA0013F5B8FF46B661 -:10ABC000C0587DD5F0A53150BC29B58CEE6959CB64 -:10ABD000D6255263ADD140F6C3D1182F072AF839D4 -:10ABE00098AE331582C3BE7F9CEC4EA61FFCB5FD0C -:10ABF000265EFD65C015D48F7F2EA7AB71573D9D96 -:10AC000053EB1AF310DD4B635D033CDE69C7A515FA -:10AC1000C65F6C9CF62BF49CFE9523A1E4B79DFCCB -:10AC2000C0F891E44C17E613E4C0676798E3F30EAD -:10AC300021E706FCF0298A97B4F8E83E176FFD6516 -:10AC400002FF775B4BFEE10C23AB6FECEF078B0C45 -:10AC5000977FA3E20395E6B348BE1174A43BB39378 -:10AC6000E8FE17BC18F4745A9617943BCEB3DC1B5D -:10AC7000EF85C98867DB2EAAE5F68C7DEE91E12190 -:10AC8000730FFBAED705E87ED1F14DB9ED23B5408A -:10AC9000FBA8ABC8FC6918F30D443EFFD7972F21E2 -:10ACA0007D9FEFDEDABB235CCEDF2559951D489FE3 -:10ACB00049FCFE196FBD83C25E64F620F1CD268B80 -:10ACC000DFBBB5896D7D1E45BEBA9EDFF3C7DEF3DF -:10ACD000730E06D079F1D80DCBB45CEBD51B57CEF3 -:10ACE000B7EE826A5F3257BCA556D0AD24AECFF71F -:10ACF000F1E983E9B0478B6A81EEFFD2197DD0F686 -:10AD0000AD805E4ABADFD858528971A15B6F540D8D -:10AD10007C7F5F65AFB510E72D41EF839823A3F4E7 -:10AD20009A781EBD223ECEE8769CF72EAE7894CE61 -:10AD3000C3DFFE54000275783FA9E7F7D938E9234D -:10AD400067E96CEBAB7CF32BF4790BC397F3F780DB -:10AD5000308833388F220B0CBA1FD9E8253BF4A872 -:10AD60001544DD0A467D2FD72BED2178308EF7CCA8 -:10AD7000F2F2A6F054C0FB6735A597EC754DAFA273 -:10AD8000725175A29BECF369DBF55CFAE153914AD1 -:10AD900097DF24E4895369C91B9AB89F56852939DE -:10ADA000D6D9C12285DBD3AC29C573ADE1E5EDC9A8 -:10ADB000F2C79B42DFE8D97D32F107C92E468F707A -:10ADC000C5A2B764C77D9C61EFF9622F3D3DE59355 -:10ADD000A5E73AA4A723BEA0D52735A49FC1EC249C -:10ADE000B2FBEB019CF7A66FD22C7E0F8361F82C8F -:10ADF000077ECB85DDA77CA0D079DBBB9676D0FE25 -:10AE0000632CEB03F37AD933E7BDD3078B785E78F5 -:10AE10005751624984F27281EE195E27E4C679F2D5 -:10AE2000CF8298871504A6E7908F16FBE0C11C74AB -:10AE30002D8F703CA743E6E722B3F2CFF77129F7D5 -:10AE40007DA276FB83C20F50B81CE6F39D620ED044 -:10AE500079D2819B0AD3DF036C6EFBD02E57E25C64 -:10AE60004FF719D03E93EE7F4AA3DEDD145B4278A4 -:10AE7000BF0FF529DA56B55C4FFA53DC4F0C864408 -:10AE8000F7CA86C4BD1BF7A58E3C8B76CFD11A05B9 -:10AE90003D3E10AC485AA85F8BABFB2C09F56C69A2 -:10AEA0009AE2C74C8F598867E3AE4504B75FE96DF6 -:10AEB000417D99562084FA7C008D4966C73D127EFB -:10AEC000A403F35DFCB5695064DCD70338EFF737B2 -:10AED000602FD9597EA687C96E52FA5A502EB5D71F -:10AEE000EB14D739EDC63E70EEEFD8B8B7E2B81321 -:10AEF0004AD97846567F7AED8D7C7606D3B3222FD9 -:10AF0000674107EEDF6829B1F2C3E1ED1D686F7E8E -:10AF10004B37BF4EFC93679FC1F8E29E48D9E8F9D2 -:10AF2000E2B9B09B2F06FD27C2EFBAAC4E087A30CB -:10AF30002EFD0D83FBCABD7EC0F99F7BECBE3DF7A5 -:10AF4000307CC8A84FC972E9D9F324FBBE1CFDB000 -:10AF5000AC7CE581A92ACABD5F4D90F1EC30F25975 -:10AF600014F9E71DF0917FE81DD81F9DE180676708 -:10AF700084AF13E8F2BFD6E7F03F5EDEC3CBB6FC8A -:10AF8000FBCA5DEEF29761C938B4BFBE7CBB1FD26D -:10AF900012FEDE29F7BEF99108CF37FF0AA43A1056 -:10AFA000CF6BC5F9A46B1E9BAAA2FD74E50CBD1264 -:10AFB000E39F361CCF0A3DFD36E363C3210FAF0A82 -:10AFC000A755CC977A7DFB8CCF9C0DD84FBA6302E6 -:10AFD000FA0FC7404E3DFEA52E379C23CDC30BB7BD -:10AFE0007DDE281F1CCA1629A71FECC588DB0F763B -:10AFF000B2F7B31F45FB7856F6F7D7D9796627DB4A -:10B00000EF9FF2F47B8D86175103AC527A1AA5AAF2 -:10B010006CDC2BE8B7CC8968FFED989FC1DC7547E5 -:10B02000BDAE02EB35FA86A937D27C5687EE8DA2EB -:10B03000BFA84F8244AEFB77CA42C931D15943EF12 -:10B04000E101F1FB820EBD62DF63DFBF08FD7C0121 -:10B0500060FB7B7A2AC407E4FF91D05EEDC9989526 -:10B06000183F565CFC5184F11466F7AE12F6655138 -:10B070008DFBBBD71F747A94AFEB7AE823FB3FAA12 -:10B080008533329E6BAD73E73FDD59F44592BB2BA0 -:10B09000F7F9C9CE5C09C6ADF533691D921FECFA0C -:10B0A00075A7539CF8FA32236EA15C83B8496D3DB5 -:10B0B0007CB7EA0309D20E3FC12AA55FC5F5B68A5F -:10B0C000E90FE7FBEB62B2F1468EDFDF643FFDA0E4 -:10B0D00019E11AC4838F9FA7D559D931CF233D5287 -:10B0E000238FCB19C5170FB37FBF2EA6D238CBD66F -:10B0F0004D29E6FE21B7DC7C57E8A99F3CFC2D9545 -:10B10000EEA3FAEEAB17201E563C2E83C6C67DF783 -:10B11000E10864487FA555D45F576D9773EA77CCF3 -:10B1200074A2BC94ADDC7F79D5B6407A316B7FD503 -:10B13000A3AF9F050CBE775BFBF74CC475F05DEECB -:10B140005704ABEFAC8BD8FBAB14F8BFB9ECA9CF6D -:10B1500047B9BD7DF847454DB8BEA52D3BBF48FD5D -:10B16000F65EEA0F38E2734BA2FC7C2CABC7FDA065 -:10B17000DF91D25372C4EF6CBFFBE1EF481CBE1DE0 -:10B18000FE7410E1DB72BF9A6470ACDAF21EC993F0 -:10B19000055BBF17453CACDAE18ED3ADD8FA610749 -:10B1A000E6A1AC90A17F31F2B37C8CCA474DAD5F74 -:10B1B00026B9CFCF57AF2492B07A3FF8EDA2DFB0D7 -:10B1C000EF6FC7640832D1FBF6BE83EAE3584E86C0 -:10B1D00053B8C35DB5C32DF7566D799DF222741F28 -:10B1E000F4579C8DF9016EBEF6D667EB4745FB69B7 -:10B1F00055EFBAF7D0AE5CB5FD9D5FA3FC58E59165 -:10B200009F6FE37FCA87FAA9DBA29EFB69B61496FB -:10B210003FB1E27B47EFB5D8B887B7FDEE5ECCB360 -:10B22000BFFAA3F7EFFD67B4179E0AEA28FF577D20 -:10B23000F7852838F8F11EB1FEDE9D045639ABF7CC -:10B24000EE7F06D278A0F5DD277F3B19CFC9BDFB85 -:10B25000C81FC719ACFEF54F9E47F7F25FFFC30545 -:10B26000E387B3AB905FD301275C69A2ABB143E244 -:10B27000C6CB13E2E9A1C7E1470654B477FF2041EA -:10B280003FEAB995BD1FAAB83FD963423FE267F7CD -:10B29000F6D7F77C9595DF61F409E4A00F9BFF4496 -:10B2A0001FE96F2626D973E5F6D71721BCABA09FFF -:10B2B000F4E9107A3ECFE839334B4FEFF7A3704CE7 -:10B2C000C57DC1AA8719FDCE423A32FA9D35947EDA -:10B2D000EFE07FE60EA5DFE351F7BD0947E1EAFBAA -:10B2E000CA7163BA7D6CCE3C886C9C61F87B506CF3 -:10B2F0007930127EAF90385C5D51F3A728EF0F6F65 -:10B300002B1AA4EF62A4EFF78E4E46E3ED4D7FFFBC -:10B3100017110FFD4F0674FCFD12573DF922ADB316 -:10B32000777FF89C6A505C07A2D26C5686C19FFD5D -:10B33000C0CA2BB90F1CAE79E0FF2FFA356B7F0D19 -:10B34000EB02F7998C6E54DEC3D61DD1217D61A32B -:10B35000817A335D46F35E99E6EB61657AE7C578FD -:10B360001F8517EFFE62FB3ED02C3DF1BE8395DBBF -:10B370005F5D847C978F9EF6FC759CFF1CF6FD013B -:10B38000F77AF5D65FC9D627E9292F7DD33B7F8190 -:10B39000CF77EF0F28783EE35D71AFAE97EE59FCA3 -:10B3A0008B73F3A38C431DF7F0C7601C4AE0293F61 -:10B3B0007FF0753ED2FC468BBF77A2868B8F6C3CAC -:10B3C0001E3E965BFE4F2CE6726325F434A2E9EC38 -:10B3D000B55714485A132BB3F01E46FB82C17BF8B5 -:10B3E000BB32F9853A7A77931CF7CA8B9590FBF7B5 -:10B3F0006FD516737B71E58E9D67A15C3BBCEB47F7 -:10B40000C49F2B1F7E55C57DC79E2D3F50FB6AB341 -:10B41000EB01F543DA81EFC3DFDF79169707B9FD5A -:10B420005E73C57C563DE1EE7FD5C3EFB9FA5F612F -:10B43000F592BD30D2386F2BE6A538DFB7F7F9E9C2 -:10B440001EC2B77BE5C65C76F0E462BFCB0EEE7839 -:10B450006ED16FF03CECCCFD21BA7F717BAB39FE35 -:10B4600016B4DFF6FB457CD1FC1DDAA5DB9F0B9102 -:10B470009F67FBFECF503E90DDDF631E7CCE79DE02 -:10B480005A1061FDCDE94BCC948DA172A3EE00DB87 -:10B49000EF39F8E0FAE71AC7A3DCC7FDB181BF5F57 -:10B4A0004E89D3392C39BA88F2CC65DDA70773EA07 -:10B4B0006FDE9F3FCCF7937EC698CEFBDCCF3DF688 -:10B4C0001FB47FEF88FB72E2E13E817FFBF73FD93B -:10B4D000EFD74B9C6FAC67793C24DFFADAD81C8B32 -:10B4E000573354DEDA5C17C7B8CFB5C5FCBE9EB182 -:10B4F0006F18129E2D99DB674CC7F917432FE0791F -:10B50000FFDB9BF5B8333E5476D86CC17A67BF0930 -:10B5100071AC87E3E27E6DB4E35AC5FCDCF3907155 -:10B520006B7B092F858CAB9DC0B8B79E8271C327FA -:10B53000806780CD058DEBCDB3F28EAF4EE379639E -:10B54000DEF192B63E10F1055A7AC3F8DBFCA29FF9 -:10B55000A5C586EBF7958192A17BABB3791769A955 -:10B560007326C6EF06CF1B2734C77963F69DCE1B23 -:10B57000B7993C0F96B5A375D025FC1318CF5CE6A0 -:10B5800080F705219F0215A918DA5F9D79E211AFB6 -:10B59000083EEF8C346838999DFAF4E2BE61F48677 -:10B5A000B2E69B339CE792153D23B9E2C8E6EB7403 -:10B5B0007F56BEF6DEF8A20D7FE7CE7F82AAA9985D -:10B5C000379B80D61C706E17EB07EB5562BD581287 -:10B5D0005A1CF5D4189FA75DEE147EA1576E7DA569 -:10B5E00093E2F679F0B443D0F30574CC97D1F64DDD -:10B5F000C3F86F57C44772B22B98FB1EFBFF2CF6A3 -:10B60000B9E4A48AE71FC90FBB8FF68DC6B1974D69 -:10B61000BC1FE9D65A95FC6091FAFD543E6AFAC8FF -:10B62000FACF871FFB3E83C1721EFF53BDCEE9BB1D -:10B63000DBDC46F9B1D74D558DE1F22D426BA6C545 -:10B64000316F425B73761CCF6B876AF8EF61D8303D -:10B650000FE26106DF863CFCF13F595ADE2D008087 -:10B66000000000001F8B080000000000000BED7DB3 -:10B670000B5C54D79DF0B93377EE3C813B30C0F082 -:10B68000BE8310D1623A28A2363E2E0F0D3E62468E -:10B69000C4A809D6D13C4A2218B436A11B1B2E02DD -:10B6A00082F8C2266BCDAE4D47A22D6DD31653DA6C -:10B6B000358FF61B4C74ED635B626CE2F6D30613B8 -:10B6C00037AB59D365B7CDD6ED9736DFF9FFCFBD90 -:10B6D000CCBDC30C68DAF4B7FB7D4B7EC9C9B9E7B2 -:10B6E000F53FFFF37F9FC77C4AE4089949C8EE2DD8 -:10B6F000840C151342F8B08DB808D95762B2433A9A -:10B70000284F4F1AA6E987F0B7606C6A6DFEDB1907 -:10B71000553322F9CEBC442E48FBD999F73819A6E7 -:10B72000A9F5831612A0EDAD3C91FB69EA96C960BC -:10B730009287E6E55B7C561F4D5D24C3544ADB953A -:10B74000DFC2EDF08DED7F30E711EF5BB45DBA4CF9 -:10B750003220ED2C17324C3A787ABED04402749CD9 -:10B760008E72612DC0690D7F9E480991F2274513A5 -:10B7700021A9F47B5D8F2CC3FC08C90824C03C4977 -:10B78000468DAE5E0F47D6F4178F1DFF10E087B6CB -:10B79000DFAD96EF9BF3CEA17B29FCA22C95986997 -:10B7A00037FB06AF92FC69341FBE2A73302F0F9906 -:10B7B0006E2763FB817A3E5A2FD11B241B00CEECEF -:10B7C0006112A4E327160D1398BF43229249C27E4B -:10B7D00010FEA4D92344A1F592E60E7B9569BA7EAA -:10B7E000FE608E09A719E649D7D1D15CEA2F48211E -:10B7F000C4D63CDF5F40D725811F2222ED2741625E -:10B80000F88F6EF7CF490C3F1A5E7ACA6F490AC6A5 -:10B81000E87F747D5BCEA4F1165DBEBC670DE0DFF2 -:10B82000E2092A30FFC4D90C2F5A79A2344C643A69 -:10B830006E2261F324A5443E4693845285C0387439 -:10B8400048593F9F07547A7C409D0FFCC969588F27 -:10B8500010FA29415E74D57C2BE479F256112BFF46 -:10B86000D0477041DFB2A979F3D87CBCF94C94EE93 -:10B870006A21E42DDD7C6DD974FE5ABFF4DF1E0B06 -:10B88000C900FC7E54BC09DE61A407EDFB3675FEE1 -:10B8900016CF30E2670CFE8A19FE9CC50C7FCE28BD -:10B8A000FCED55DBEFFD2F86BF513C71A63540877F -:10B8B000D178D4EA578CC2AD205DD276847C0AF26E -:10B8C000816AE0DF1E3BCB1F12EFAC06FE00BE9A82 -:10B8D000805F08C9A44D7AB82E28CF1545ECDF7AD1 -:10B8E0001F9507FA7C50930F6C5C97CF5F4D283DF6 -:10B8F000139F891CA328ED9AAB7861BDBA9153229E -:10B90000FDFFA33809EB774A8289FB244DCF2C4CED -:10B9100007B9D966EBB1C17CBB2C3DD84F5B8E49D2 -:10B92000EC8D21DF4EABF335373B671C9D111F8F2C -:10B9300066810463F1FDDBAA7C6B1B7CEA8C99D2E7 -:10B94000072F09929DC20B4CFFB6B6BEF9B43DE974 -:10B950001FF2F9609C441CC7A5C2E52A349156DF4A -:10B96000C4701E57E98A6FB68F0B270F70C69033CD -:10B970001A9CED00A7273E9CCE9C0AA453BED985F5 -:10B98000E30C8A125B0F4B936D239D9FAB35496A85 -:10B99000A5E92EBEA9AB0ED2210B5168150B91CF94 -:10B9A0005450B8F969D309A1FD745C9A659B04B43D -:10B9B000DFDC43023A391F74042F89B43F5E0C92D6 -:10B9C00020859377293280F1AC4A07DABA91A264D4 -:10B9D00042E6D0F182FC0C90A7CEA080A9D68F467B -:10B9E000274E8B4CC462E8C7248740DF416773222F -:10B9F000F5E6BB19DEDAE6860354F691EE129EEC0C -:10BA0000A09FDA8B28BD24D1BC45EEAAA3F8E87E1E -:10BA1000D5427A757CA08D9BEB66FAC74E6A93C2BD -:10BA2000D0B7F9B037388E3EB603DE68BBE60BBE42 -:10BA3000EFBCA2E115FE15133CEF38917633809FE1 -:10BA4000DF27C5AB4DA6F8FDFCAE45FACE2B3A7903 -:10BA5000D54C98FE20444A5F312D7EBBDD2D6446D7 -:10BA6000416124BF870F213EBB5DBD5DF9749E8A95 -:10BA7000DFE42FA4EB45B24B0D788A4E096965725D -:10BA800070CCBAAE96C2B47D779189B702BD1690DC -:10BA90009019F092ED41BED4D635E8607463F13070 -:10BAA000396976C998DA008F20EFCC7BBCE3C96B8B -:10BAB0001BF0490C3C16B9291E3FF1DF0F8F1E37D2 -:10BAC000C1D499509304F8232FEF22D23400C3C875 -:10BAD0007F5A3B8DDEA3E75FFDDF7CFE1A9DC4AF7E -:10BAE000AF68F6103F48AB660549A89BC37CC0967B -:10BAF000864D29E854A5D8C2ADA09A72EAFA334E11 -:10BB000011D0CFEDE23B36145DFE0F53C6EB9F27FD -:10BB1000EF68F83447C6D3E3C7047AE78C25748C02 -:10BB20008BE02941FCB47790DC089E9A6C208F3A18 -:10BB30005D5BCFF84A2378EACC7E4EDCA0A3F72BDE -:10BB40006285E2A6F8D809766D0C7972AFBBA21DAA -:10BB5000CA05536C797E48956B5480F30BE9380B1A -:10BB6000468C789AA7E2697EFA3B8FC134A994E4A7 -:10BB70000915C815017F15E0AD6A4D00C882085946 -:10BB80001F7C2288F45025025E3865B2E943E78DB8 -:10BB9000E32F1EBE5C1C09C482FB19B1E6881BF4AE -:10BBA0004931C59BCEFEA08421A27CD4D6C5E5999F -:10BBB00080AED8BABD7C31DDA4D0AA9D5E5308FC0E -:10BBC000190B69EA02BC93736602765A5A3803CBA2 -:10BBD000ADDEFC10E8BBB4B09DC8E82788213BADC2 -:10BBE0007F70ED5D7ED443D76F23614A3728CB4009 -:10BBF0008E65CB61B0A779512A374B30CEA336F092 -:10BC00006F3ABD354984D9DB24961ED8E20EFE007A -:10BC1000D68DBF3E1FFB33D998DCBBD1F97C69655B -:10BC200022013BC07E810B812E3BB0727ED77029F2 -:10BC3000C8CD841E2B4DDB78250C7A4CB96097005B -:10BC4000DF5B0B95DB4D342DFF95BD88A7DFBB383F -:10BC5000871FF0D05548979CF6F3BBA79C2142F371 -:10BC60003B572E1F49827E8E9A25287FF2C3A64F0E -:10BC7000823D65FB603FFA8736D53F247CD32C5844 -:10BC80003FFB479413BBF91EA4FF5D05D36D7AF902 -:10BC90009EEA080E035EB4BCDD4BE5DB0CA4A7B73F -:10BCA00086293D99148E7C48E9D3E6DAE63D25C124 -:10BCB0007CE9778D3E7C917A11BE35E63D14D760E4 -:10BCC0006712726431D8919D206FD06E250A07EB00 -:10BCD00096C1CADF3FB06231D8A19D76AD7CE562E6 -:10BCE000599F57FE7006F3AADDEB4FF6EC82FA9EE1 -:10BCF0002CD2C4F01320AB74F64C41328FEBD6E754 -:10BD0000967FEFD6D9CD1A5D761530BA7CF9626789 -:10BD100035C8CD4E4A975609E87097C14FD6528D17 -:10BD20000E3B0B189DC5C3BBE57A0909EBEC408BB4 -:10BD3000A707E9D1E609A01D1D5D7F450AB363345D -:10BD4000FAB77909F2834D0A3E753FF287CB0FECC3 -:10BD5000672D68221CA5138BC8FCE189E6110F3EF4 -:10BD60008DFE3B0BF215A0D7F745E227E3D4B75C75 -:10BD70002FC5F96C71CB93927578F4E451BCC798D8 -:10BD8000CF5792D97C3A027581FB69BF72BDA4205E -:10BD9000DF7889BF1BF412257FB03BA9BDF9C9E448 -:10BDA000543D9E983DA2F5AF704D8316E0730F6D24 -:10BDB00047BFB6939714587A8B2764E0EF2FA604F9 -:10BDC00067EBFBE145E61F2E34BB4CE423E0673F05 -:10BDD000F5CBC293A99FD82262BAA7C58B69578BAE -:10BDE0008469778B4CC256EAFE90EBE7EF053BDBAC -:10BDF000E540F826A28B8E163FB66F6F99CDFAE11B -:10BE0000343A9FBA0BE8C261D2F8C4BF0BE83CC910 -:10BE1000AC959761BE8763E58F242F58AC14E37C03 -:10BE200050EE754D30AE395486EB77F3FDABF25BD7 -:10BE3000C5DFFE798F54E703FDBD6126FA38C618C9 -:10BE40007A09B3F16EB4FFAE6C13CAD3FDF3769EDC -:10BE5000F1D1BCE575DAFF78F4D8C3FA8FDB9F0621 -:10BE6000EFE02E84D74AD7DB4EFBB38A4CDEC7E324 -:10BE700087E8F9D294207F7808CAE9FD836BC9CBA3 -:10BE8000C09F7458BB087C1A9021DE25B4531CFB5C -:10BE900041DF06C2CF80BEB571E418CD0B2ADF505A -:10BEA000B5AFBC4CFB11641BE9A6ED06E7DD45A070 -:10BEB0005DE72B360A13A5D3947CB417EC85B5A4A3 -:10BEC0008DD6DB596D2766FA3D69FE1A02FDEDFC41 -:10BED000991DFBF79D9982FCBA4B647C34A11CF23E -:10BEE0009A4858AFC76D8E483E1FE4E57D24300D5B -:10BEF000F9FA693D5F533DD90BFC24902A8570A067 -:10BF0000871FF0333B4451E569E05832DA81016C18 -:10BF10001FB10B9B8808FC7ACE1CEA06BFC4DC80EC -:10BF200046DF22F361DB30F2B5BC3CA38C10170373 -:10BF300081ECF287492EE025C34C6D31204B818482 -:10BF4000A9DEE8A1FF007CFC85AB17C8AD84A4AFD7 -:10BF5000110CF3E02F382F996E05F8587D4D0FF135 -:10BF6000171A1BA13E4F74F5D19FA94B1ACF2F8CE6 -:10BF7000B6E30793557FD0497240EFB5B79C206F69 -:10BF80005B22FDF05171252DD5ECF9875358DC6209 -:10BF9000949E2446DF2F503F1DE8B1E31766D21B65 -:10BFA00083BEAF27FB0CF66E46D014991FFDF795A4 -:10BFB0008BD68A8306FA1C7FFDB3EA8DED739A1C3B -:10BFC000063CE635271BF23E25D3507F5257BEA1D3 -:10BFD000BCB067AAA17CF2A1E986FC94D0A70CF5BD -:10BFE0003FD15761C84FEB5F62A8FFC91335867C0C -:10BFF00049F86E43FD1967361ACA670E3D64289FDB -:10C00000757EAB213F67F8AF0CF5BD41F1E409E067 -:10C010004F4A8F668AAF5D19CA21D09FC36DD48EF7 -:10C020009BCFEC63D0B7249BA8F631554C694057A1 -:10C03000ECAF1DF400C8F93D8F85BF807AD2E407CC -:10C04000FEE50B16C91BA15DBB68225E9D1C911607 -:10C0500011F85EB1C78DDFE5D256E40F81AA0D7BE2 -:10C0600022E86DE37A10F376D20FF0BDC1E0E3452C -:10C0700025A67C12B28DF46F25F72405C6B1FB2CE2 -:10C0800092B1FECDD2BF2F45A5FF1C4AFFE689DB4A -:10C090006B74FF90499E9CC2FCC3AA731E83DF830E -:10C0A000781DF57B6CA41DD8A9BC6E24EB14ABAE37 -:10C0B000FA3756D3879FB871FF269ABF684A714EE8 -:10C0C000D7C9CBE4B566DF8FD587330CF65974DA60 -:10C0D00096F810CA3B2A17CB530C72315005F31354 -:10C0E0007819E5A2F6DDD73715E57297C8EC944EBE -:10C0F00089F2E538F88A96CB5F4E9698BF18473E8E -:10C100000B54CE82C2DDB9F2D35D8037791B41BDBD -:10C11000447510CAD9E8FEA95D7537C2E965F4A473 -:10C12000F9439ABF65A3F203FC2B9B44105F568A28 -:10C130002F27DA478FA27D49E721817D64F550FBE7 -:10C1400013F43DB53F99BDF9E7B52FF361DE7AFBF6 -:10C150004FD5972187DC94921ABFFF17E3EC479DD8 -:10C1600049D6FCEEFF9EF427A718F1A1D1A146679E -:10C1700056203A3ADEFB125B77DA2291D3F62F246F -:10C18000F84F10E9E5D4ECB34A25AC5BD0255BA9A8 -:10C190005EDD37BB06DB0993780272266178C33215 -:10C1A000D093A494C90985FE03F4E62836CA0D5B32 -:10C1B000941E15401F278ED5BB9A7CD0FCF389E4D2 -:10C1C000CBB752D438D92C324B2F5FE2F9E19A7CAD -:10C1D000D1F0B0E0831611ED8E0F68B9664FD07EB6 -:10C1E0002C397C00E2CC829FC84762F0DFCBAA5E8C -:10C1F000EE3B6997812E5D6B04F4B332FDE172C8AA -:10C200006736113FE067F670980469FF3FF4B0F5B8 -:10C21000C8F48738B0CF332F873880F3A085C58521 -:10C2200032B785387DDCE89AEAC7FDEEE2A37E5896 -:10C23000F78A3C17F2E9671713A48F21EFC69E72A5 -:10C24000D857984BFCC03F2E0F4F32217FDE1A4249 -:10C2500079E21F51A8AF4392E944614DAFB490E930 -:10C26000F751FFFDDD161BA6D75A444C2BF38A0766 -:10C2700017D07A5B7D0E8C1774E43B709CCE5C010A -:10C28000C7F98F9C87F2C02EF8758B17EB773DDED0 -:10C290005404F184CE93FF8971CD083D53AC7901EC -:10C2A0009E30EEF710BEC90BFBBE49F20CDC27ED49 -:10C2B000B404FF7103C413D70AFE6331F837E9E50C -:10C2C0001FA19F0CF8013CB4DB195EACCE26BF1B4E -:10C2D000E2FD93C8FA15B1F854C513A530B340E98F -:10C2E0003789910611E686DA1241AFFA493F059B7C -:10C2F000583A421CEC8790074509E245D9B6D02050 -:10C300009467D78BFE36AC4F705F415B278B9D04E3 -:10C310008EBBA05E98DB42BFBFE811D9FA0D8570D5 -:10C32000DFFD37176E1FCC21F1F97B4F4BF5D92A72 -:10C330005D3CD64562EF0BFFCB6D15160FEDF77622 -:10C34000806D26ACF7AC71F5E38DF67BBB8753E3CC -:10C350001393D3C15E6EE663DB996691AD0FC47F24 -:10C36000C08FDE5A28A5BB5DFA7E183ECC279FC73A -:10C37000F57116B3F9B77DEF8DCD8F513AF977DAB4 -:10C3800010E255AF5CFC0CFA8FEF254BFBC1EF526E -:10C390007E6C26B0CEEF7D7FD669589431F36E392E -:10C3A00093CCEBE249EF7DFBD5320BEDFFBDE75EB1 -:10C3B0002DE3510885101F5A79E387AF9541FC4A58 -:10C3C00068FE4DE6650AAF52418A9A204F0D68E635 -:10C3D000876E591A1E076F07D31ED802F1C2509BF1 -:10C3E0004BE4A8BDF625E71F05A0C766809FA60FF2 -:10C3F000DB4676727489B9F4779754D1FEB6728AA7 -:10C40000E2E2006F8A15FC0A72C1EA07BAD95AC87B -:10C41000F4E5D607C59002722CDCC4C8DDF65AE6F6 -:10C42000652A87ED3F0DC11900D2CE052A13207E63 -:10C43000378D20BDDF76AD290FF695DD44C8073A6C -:10C44000B498CCD8CFC84567A817E56FD32C9043D4 -:10C45000AD171F9D0CEBF57B55BE6871B73453D3F8 -:10C46000813A1FC4DDFC1877DBCDF7639C3EDE7C90 -:10C470009D5EB6AFC0571235DEF5DBEE7076841EDA -:10C4800034FE8A6EB7B785F861BC975A6C98BED0F7 -:10C4900022627AA2C58BE9F75B244C075A8A30EDF9 -:10C4A0006BF1FB0B2C00E76C4C3B2C647D40476729 -:10C4B0005FF0B0FDC87B92CABF0074FE24EDF73276 -:10C4C0006DF745DAFE32AD3FAF366C86B8CCBC11A5 -:10C4D0002A2F2528EFC2EFFB697F506F6CB9AD049E -:10C4E000CA4BABFBC380C7D262FA9D407F7D587FA9 -:10C4F0007FCB093F2B1FAAB450FC96FE96953BE7D5 -:10C50000D27E68DEA9F643C72F61F567637F745C4E -:10C51000CCC7E8B784C173A224163CD1F5A9956FA6 -:10C5200026548F88F0BFE0EF59240EF75138123EA1 -:10C5300006F2F882B51CF4E79E12926FA2FACD9231 -:10C540005AC041FEA966229A4BA8CACBA8D9554E1B -:10C55000A09D8CDF95557CE8980FF513F6ABE9A705 -:10C56000E4EA30EA9D243FC937BB69CAD381A753A7 -:10C5700054DF4722E70D503EB13CAE076D2756937E -:10C58000C8790332717DAA5FA2CA63D3DB474D210C -:10C590003EA63FF771701EB1835F4B7DFD7E924BCF -:10C5A000F3AA7DF645B5DEFE7965491B21BFF8810A -:10C5B000A7200EFE1BE2E5603F7EB47D943D77B878 -:10C5C000E54C5A55A1AA1440DE6F138FE8EDDC6CE0 -:10C5D00085D2AB8E0F7A9AF8EA5E8C2F04336A7498 -:10C5E000FAADC312CCA0CC4BAE3FF18F8B413E8055 -:10C5F000BE06393D7784E9F751BDFE5B261F357BCA -:10C600004250D76B9FBCB12D01F7D3A83E92C0AE6C -:10C6100008920ADA3EB17CEBCBF09D9418BF270854 -:10C620008C8F32BD210EF2999EC04F3CB0DF907CC2 -:10C63000487E86CEF7B7035609E8AFEFE4DA7A888A -:10C640001B3E4C12253BED27F3A54B02C0D1611ACE -:10C65000168008473CCD4B786A0775089A9CA486DB -:10C660000F5DFF8E34552E90DF7757D1FA074DC1FD -:10C67000AB54578ED63FE8086E813CFD936D54AFA6 -:10C68000EF1D8DA36FEB96294DEC55E3E6239ECF6E -:10C69000762BD990A7F5DD2CDF4EDBEF750F794DAA -:10C6A000349FC86DE93E930379ADFE966E85B6BFA3 -:10C6B000EA61E700882BE803B9379A17693E41978A -:10C6C000E7599ED858DA77F23F05D0431D6923A772 -:10C6D000B3009F3FE4FA41BE36BEFCF541C86FAEE1 -:10C6E0002712C4E7324F1CC175F8AAB97C04F0D6F2 -:10C6F000D7724644431DFEB475A176EA142FC17863 -:10C70000B210E242F960BF15F798D07EDB4E49B017 -:10C7100004F0DD9506EB5C91C6FC812921DA8F8E51 -:10C720007FA650BEB34E0775651919D6FB5BC46F63 -:10C73000027811E5F01FE57F2F01FDD4375B714CC6 -:10C74000A5E36DDAC0FB5B25D03FA15601D6FF04FF -:10C75000877AC2772663C73768FE5A7F4A2FF81B4D -:10C76000961D8C3E37F9FAD3A6D3B4C3CEE86293B4 -:10C770005BCDBB8DF976D59EF4BA157732FDBEF947 -:10C78000C4815C3000AF1E9B857EE4660D1E720086 -:10C79000E1B93A3827E9363ADFC69FB2B866E340D6 -:10C7A000C912987FE31E13013F6EF300A5271D7F7A -:10C7B000ECA37C284FA6F3907BA6F2943E02070BD5 -:10C7C00096DAE9FA7E3D5F16015FF569B7EEB6517C -:10C7D000E7E8EB823805E8A13EAD7437D0D3A6393F -:10C7E0006F213D26A596FEA49AE2EBE8DDD54B40ED -:10C7F000ACA599185F5282433967766F43FCFF6B93 -:10C800003919B1BA119DB8CF9907FF47E19B2CCADE -:10C8100015505F5C465D22A053217012EC10A5C23A -:10C820008671D20A711996E7AE21A66E0ACF112938 -:10C8300039B99536B517C826B053F2030E8C7F9AD6 -:10C8400013AA76803F7AEC1CCB47D6E912E2C55199 -:10C8500014EAB7D17E6E71F122F8226966D906EB2F -:10C86000467979E85829F00BB303942F1663BCE797 -:10C870006022A97F8EB63B6ADAD8FD235AEF68B2F0 -:10C8800087805DD9C171EB6BF07BC5D4AD743D8EF3 -:10C89000AAEB6776FB4558AFA36E637E2FB7F141D5 -:10C8A000C0DB23A92F2E81F9A559E59E140ADFE7E5 -:10C8B000525FECF666209EF36DB4FC737FFD42B7C9 -:10C8C0008DE2FD68AB9C29EAF293FF40A536CEE3EA -:10C8D00005E453DEFDC587808F69F98F6D54FF7EB7 -:10C8E0003D59B307587941BEC6D7D4AF9D4DE168D5 -:10C8F0001DCD2BB622D8F78AD4AFA27CFED5A7CD0A -:10C9000044EB1FEC09C79C7E9BC38CF3200EB067E1 -:10C91000A6F168CF38DC6C5D1D53F2D14E3A6A67E0 -:10C92000F81AC93161F922F3B322C407AC53781362 -:10C930009EE5214D01D0CF7C364F58BCF7B03C4529 -:10C9400082B029DB1FE47A56A07F682FD2ED071250 -:10C95000F0638DFB877C54BED03A9C61A27AD87379 -:10C960006105974BFBFB6CAAEA2F7A4806C4631F4C -:10C970004D6572E6D18072BB45021A1B66E75649C7 -:10C98000603AA4E9EB0AD2C73BBF32F65C4018ED2F -:10C99000B23D2E938AB749BBC305D45E763D27824C -:10C9A0001CA16A7EC761D06F1E1EE9A610F89FE623 -:10C9B000B7B9591CDED7B7E44BB3C13E7CB5D00440 -:10C9C000FCCF8B7E11CED99527942681DDC68FD2E0 -:10C9D000E9EB4BC240378373EE043F5000FEA59F46 -:10C9E0000FDBD9F9D0910CD20F7161DE2B13FD3E14 -:10C9F000A1C6BF3B5B6C98527FFE5DD01F5FEB22F0 -:10CA0000B84F2078039897DA09077CF1F2A7EEC6B1 -:10CA1000719FE10349EB40DE9E63763D900BC63982 -:10CA2000C24F7010E778DF16488279EF771BEDBFB1 -:10CA3000B23466C776A632F9D9D9C2E2A0C2F54FA0 -:10CA4000605CA7C3A2C923D7D2F05CB0E783788E1D -:10CA5000D61ADC2683BCB21145117571725BB631F2 -:10CA6000DE255CBF95C58752D938D1E70D5C9CD6D1 -:10CA70007FC1EEF1FC032D8D3E9FD04C02288FC864 -:10CA8000103BF7B06D57657AB2AE9F6D9C9C2E8EB1 -:10CA9000431F0F5F379390EE9CCAC3FC8800F37965 -:10CAA000F8BA80DF897738B115F66528C175C33AC1 -:10CAB0003EFF5DD44B0ED213860373568853E8CEE7 -:10CAC00085122F3F324AFFF911FEC07D752E067F79 -:10CAD00048C67CF47EFAA3E03BD37F77387F2DC035 -:10CAE0003CDFAB242360871232BC08F8B7B1D28197 -:10CAF00071EA87498FCD06062EDF23EAE3C58D0351 -:10CB000097123794E23E960476F0C32F951BE254B9 -:10CB1000DAF9302DBFF9C4068C1F3E7CF49A30B58B -:10CB200014C118B2507FACD1D673C69A1FA96FB783 -:10CB300004952CA0FF975AE52CFAE95B00279CABE3 -:10CB40006A9E340BFCBFDF8AF519802727AFEA8F76 -:10CB50003536D41FED76EAAF019D5E9C8CFA9416B3 -:10CB6000F3A09FB5F15778181D8EA8FE7C023533CF -:10CB700001BF1D8EC01566B41399A7F64E47B24685 -:10CB800037CDDDA0FF0E0A11B908933DE860F9E446 -:10CB9000B4E6EE76A687B1FEC893FC6EB0873AEC99 -:10CBA0006ADE43307F50E8413F41F9BE5502380FFD -:10CBB0003A027EF007951D5324D02755E92E9C8715 -:10CBC000E5EFACBD200F333DC1AB60B7100FB38FA5 -:10CBD000DE4BBD904B5C31FB19E16EA41FAFB11F62 -:10CBE000FB5C36FE7B9C39B0A334528FB60FE3B9A1 -:10CBF000807B6C18FFD1EA1FB618ED642D9D92C69C -:10CC0000E20C204F80AFB5EF42F03EE45F2B69426B -:10CC1000FEB57A8DFB451A3F0BD7A718E297DF4A7E -:10CC2000F5E1FA687240B85E8CE59D2A9DEE847D40 -:10CC3000F471C7498E33CE0C9413F1C72953E5081C -:10CC400051E3493C9E33D3F824BEBC30C671A3E502 -:10CC50009F966AF2EF884AC7FF600F2E4CA3FFFF32 -:10CC600050A87F91035B076F85F5F9A36AF716F566 -:10CC70001D3809E47745945B5353E13C957C1CD205 -:10CC80009BE59BFA3436DE5839C6E20FDB1E945022 -:10CC90003F3FC3FB1DFE1870D75F771AE4577EAA8B -:10CCA00084FDD5F30ACAB1FAEB8958FED1FBB793DC -:10CCB000D08CF1FA7761F968FFFDACFF973FF5E39F -:10CCC00083B3A1FFE3169355E7CF6D3BBE301DE262 -:10CCD00095DBEC542E1BF95606BEE57D64D40F029D -:10CCE0003EDFAFF945CAA2DD5573C16ED5F1F96CCF -:10CCF000B0BF22ED79BACEFB1D5AFB3B77833D34A2 -:10CD0000A6BE33AA7EBED6FF6AEC3F1A1E4D8E40E9 -:10CD10001EEC2DFE0F560D3E9443074C51FD8DCA5F -:10CD2000A520F6B7690EB33392FEBAFE270A0FF4B8 -:10CD3000172ACF023BEB4122C139E768BC27A9740F -:10CD4000587F7D92615D23F8BEC5F0FD9F5BBC24DA -:10CD5000A4E3B7CF04B72D027E4BD2D689283BB1CE -:10CD6000DDE12C12D2F1DDFFC0F151E1B82D0E1C36 -:10CD7000F3FFC270F80C7C1981A3C0F0FDA3C2615F -:10CD8000B65DCFBCACCB5B4492A5CF97846D599771 -:10CD90007576CB8C33A2213F73C86BA83FEBBC6484 -:10CDA000289F335C6428BFED8ADF909F3732DB50C9 -:10CDB0007FC175D9902F278B0DF52B6D2B0CF98525 -:10CDC000E25A43FD696A9CFC76EF0643BDC5D283F7 -:10CDD000867A4273CA77C07E59F0C1021BF8173BAE -:10CDE0005DA6EA10C5CF4E3E684B8E211FCBD47E88 -:10CDF00047F59D370DDB2F149BDA411E2EA4AE7034 -:10CE00001BB5D7D2EB02EDA0F7AB45229AD16F0E3E -:10CE1000B1F8C9072BABE0FB9D8B89D8ED8EE46F91 -:10CE2000FF2B42206FCD96F15C9BBDD884E7067640 -:10CE300017D78CBBFFB04FB5DFF744E9FB51FA3190 -:10CE4000B3F393D1DF8BD3195D1D58B08FC03E81F2 -:10CE5000CD15C27B3E8353767A21FFA505DFF6828E -:10CE60009FD135E5112FD04F67CE570DE7F21C0546 -:10CE70006C7F26BADFBF55FB2DB8FEA80DF4E7EE98 -:10CE80006C86CFE87ADAF9F4DD361637FFB8E6B902 -:10CE9000F8639AE7E5746667EDB68530FEDF5DF40A -:10CEA000F1C07FAF3ACE81058F1306EFE3780EB95C -:10CEB0002B4790F47A564BE1DE28CCA7D3B7D30B9F -:10CEC0007AB7CBF788C1FEB7C27C628C63F3323C81 -:10CED000ED163FDEF93CFE27CF6767CC7D775B9C84 -:10CEE00079156BF3F2AAF7283EA6793DF5179E5700 -:10CEF000581D2F359DD9A7BB25C64749E6C0CFF39E -:10CF00007DF1F92F69B6F19C5282DFE807E417043E -:10CF1000C63D7F745EC54F3C7E5D635152018ED726 -:10CF20005BD839DB7380479A9E0F4EAA80FB0AAF0D -:10CF3000C3792D0EDAEF48186F1DD606CD063827B7 -:10CF4000920F25E9F9888FD56B8CED56059CC6F3B9 -:10CF500052EA39038AA7FD105FD6F036669DFF4C72 -:10CF6000788A476F378AA7EEA29BC3D344F49D9A71 -:10CF70002E21BD4C84278D8EE2F5F3FF2A1D2DBE98 -:10CF800071FC20FD7CDCF8F9AF463FF7A64B37C4B7 -:10CF900067FFBFE2E7F11BC4CFE8796B81D4C73AE2 -:10CFA00007D2E915900E27734D6717839FBDD88C64 -:10CFB000F1B3D70E1734927C7D3DA6075E5B36A990 -:10CFC00011CF8F553BF1ACD65953EC7E5F53F1F145 -:10CFD00090D7AD9EA7F3A782DD7BB67AE5B8F322A2 -:10CFE000CBCCC6F38BC411999F99F64BA40A8C9FA6 -:10CFF00051BC1E1B67DDB5758B37DE8DAEDBD9EA04 -:10D00000B69B5A376D3C8AA798EDEEF6E6DF10DF47 -:10D01000C309768637761EA0EF7166B7F701BE6941 -:10D02000BFBF84A20CB0FF09C6FD56AF493F02F056 -:10D03000BEE665F1F001416AC47741562EDB0DE78B -:10D0400051CEAD727310D2D0E038A6AE67595D6C88 -:10D05000BBF339B53CD29E2393A5B1F58EA876CF0C -:10D06000AA3A0EED07C2CB39FA773FFE21AA3CBAA5 -:10D07000FD4BDE442C3F17E73CE6B7D4F6AB6BC75D -:10D080006F4FEA53F0DC1F21528EFE3EFA285DA955 -:10D090007CB0C21BFCBE97D67F9D0B7EF973104FF0 -:10D0A0009DE2C2F33D84273ED8F71FED8797F1BC80 -:10D0B000C6E54686F7E87E75FD85BDA9F1FB8B8741 -:10D0C0005F6D5EDA78A524807E1DA926E27E36BEDD -:10D0D00019CE39DC59499A707C5E427852DEA4FE42 -:10D0E0009C2F421F174CD23ABC48A3F633F0FBCA20 -:10D0F000A5D0CFC05993B8C3171FEE78F2E09F5464 -:10D10000FAF198833BE05C0159CFC53CB7F72BAFF0 -:10D110001DEBEDF78EEED7E338B73C19B448B4DF1A -:10D12000BBD4736784047356E8C6DFAFCE3BBA9DA9 -:10D13000C7CCF6C7C91B66C45F5FEF4339B1F8E7D8 -:10D1400035D55EDEEF2D32F8C7B5812D16B06B6B8D -:10D1500097ADB0482E289718DDA970F409C19C122C -:10D1600057044F71E58F8A9F81F3413CB7B1BE9957 -:10D17000C373C7C5DB19FDADDF3E686AA4E911952D -:10D180000F57C03E93AE3F77069B5F5FAF2317E01C -:10D19000EFD39FBFA0707CFA10C1B89D2DE3E93D8D -:10D1A00010B71BE6881AE7332D87FD8661755FACE3 -:10D1B0009096B702BC55A9C8E7EBB7AF403FFF96C2 -:10D1C0006AE6E70F0804CF01BD392F2104EF1D10D7 -:10D1D0009B3CF828CDBFF58724D2ED8FD0C71342F2 -:10D1E000781AD0476A5BE073B1E2D35206E3F3DF0B -:10D1F000BAD83E5E3CBC9C55E5A956AF86972CB18B -:10D20000EAAFAC36CA350DFE146BF83D12239E3ED4 -:10D210004A8FA1F1F5DD2F5439FD5A94BF547B3E5E -:10D22000B6DF3237433DA71BAAD884FA4AB14A7801 -:10D23000B65885C7A3AC467C7EB8948890BFD32AE5 -:10D240003D0DF0DD556B8E92C321EC67FD32A76179 -:10D250005E4FF4FE781ADC4BCA2F60F2F7FD2217FE -:10D260009E137F80340970FEAB8E28F3912F896462 -:10D2700001FA3EA7E24F83EF1C91136682BC683629 -:10D28000C7E4AFBB543A3A17A85C85E7DFDBCD783B -:10D290001EE1526DCA72887F2B018B1F8E375D6A2B -:10D2A0005F9970BF6E5D35BDA7D935E78395E3EA19 -:10D2B000AF5501E37AF5093DB8FFA75490A66394F2 -:10D2C000CE267FF9F2DE59347F36642A61E7DCD856 -:10D2D0007CCF86B2B473F1844FA3EBAE165D350DEF -:10D2E000637DE56FD8BCD6D58516C296D83D877AC2 -:10D2F000F6CDA2F9860CB7BAEF387F1EF0EBAF9AE5 -:10D30000C7B707A2E9E996271D867CD97922E07B79 -:10D3100014DB62EB87F7B29C6C5F87F7E7C23AAC2D -:10D32000DB1EBB9E3BDB85F5AEFED15C1FCBEF3E2B -:10D3300090C5D6637D3D17539E1FC84A60E50DB169 -:10D34000FB5F95E954E59D980BEBB23E0EBC2B328A -:10D3500013118EB73B56AF83FDFB2B51F655452677 -:10D360008343CA64E72BAFF6BED09106F4B09313A3 -:10D37000E11CD95B6EFF14A0BF0DED97D0CF4F57C6 -:10D38000EB3BD2034F66D0F4EEF3CF9D82FA0375E8 -:10D39000C4CF49F1F5C0E10C4D0F68F7A2357DD837 -:10D3A00063077D04FF0BFBAB1404252919D65D79B7 -:10D3B00008CFC5F43A44760FCA3F536F577F43A551 -:10D3C000E7AB476F6EBDEFA937DA4567C1FEF3449F -:10D3D000ECBFAB82B4B7948E7B95D25B2B9D0FF9DB -:10D3E000E0895BF5FA46E38778E3DEA81D78F5E887 -:10D3F000CDD98113CDF36719BE1BB203DFAF7E62B7 -:10D400005FA904F3ECB93596BCD5E4F22F55B918F1 -:10D410004D2F5AFA4B55CE5F098D0FD7670E19E184 -:10D4200059D7648447E38F2BA13607BCAB45479F90 -:10D4300006EBACD9A5A46AE60DBD17120FCE5FAB03 -:10D4400074F2AB66338F72EF2887F1E95F353F9155 -:10D45000182B6E153DFFAB264A0F401F4FF3287F58 -:10D460000AEB379C4C9322F4F87F543CFCA974A837 -:10D47000C9574D9F44B7FFAF4A779A3E9B88EE3C11 -:10D4800071E28F07326C88BF0DBC28C0FED1810CC1 -:10D4900089E589B8C80BF6EB6C76EE9D4AA85C78F6 -:10D4A00057E26AAF03EF8329DDD650215DC72BBD5C -:10D4B000B74DD1AFE3EC4CB61EEB1BDC3B61CBFAB6 -:10D4C0008AC9BF381DD6AF86BDEF71EE7CF2A2745B -:10D4D000DAFE892113BC9045D66DDB6086F9CDCC90 -:10D4E000647A64FDF657D1EEBB59BA5EDF64D4E7C7 -:10D4F0005FCE10553DC1ECF03BA95D00E708E3E1CC -:10D50000A13093E1E19EFAE3284FEFDDCEA13CBDCF -:10D510002593E1E35E3E847299B433FB99D8283EAB -:10D52000A85CBA0493007CFC35C7CE77F30141FFB9 -:10D53000FEC6FD7B562F043B309A3FBEA7E2E92B87 -:10D5400099EA3B84E9C13B33D13F0C70D0DF5B9F4C -:10D5500067F0AEDFBE05CF275FCC50ED6B953F2F58 -:10D56000C23ACD8CCC2F459DDF05C7C836D0179465 -:10D570006F4C78BEE47533C275F5ABDF6C827AE22E -:10D580005417DEF7423B96E6FB9627845A75F13A2C -:10D59000CDAEC9F7337EA8E565835DD890E933D871 -:10D5A000E9D1F6C6FFE80396F6A878FA4BE983C3FB -:10D5B000AA5DF0A7EA834754FE8FD60BA37CBC93E9 -:10D5C000F1F1A5F3FFBE10F2D17CFCADCC8FA69794 -:10D5D000A2F9F74AEFDD48D7CA1222161AFCA39C1B -:10D5E00010F8C1A3F41FF1933838DFF644EF4FA6CB -:10D5F000419CEBD2DED5EB628DFF4416B3B33626E9 -:10D600004A267C1FF2754667D17222BADD285FC4B4 -:10D61000892FD6D6CC41FFF05CCD6DB970EF2DDAF5 -:10D620003F18539F935357817FDCAAFAC7FBACF591 -:10D63000BD31E0F566317CE6178C9C027CBFDFC013 -:10D64000E17D62F8D3DBE9779FF7FF60581A0BEFB3 -:10D65000685EF34FB6B3F1A2C779575DB751FF4487 -:10D66000A1FE09C5F370AD3911CEB16AFEC9B0F2A1 -:10D67000E7F54FDE2423FF300BD6F9686CB81CEABF -:10D68000FCAF08C17D73281C579798FD0AF08B8961 -:10D69000B6D3F925D1EDFEA8CEE7CDED37298FCE53 -:10D6A0001BE3C9F1F86D14AE3F91DFFA84911CE0E1 -:10D6B000FB378F7C70F15198CF1107BE3F16DDCF3D -:10D6C000D7B2CCAA7FE0403ED0F4EF80D0B3F905CA -:10D6D000DAEECD3B32FD3B888E2F08E50BFAFDC21A -:10D6E0001F295FF851BE211FF7F53AEB63F9298333 -:10D6F000AA3F141DB7117BBFD1047EB14CFC167D2F -:10D70000DCE90D75DD7FA1CAA5A22CA63FEFAA5DBD -:10D710002140BCE8FED1781141E7429C9A7D04FC8F -:10D72000CBD7D47B02CAC68498F1DE992A5E278AB9 -:10D730001FACA933FAF577D51AE5C73BA1FC513DDB -:10D740005238CE7E9446BFF1C6BB51FDD117BAB94F -:10D75000FD8089E6F7D9AC1BD31FAB48D33C8C7353 -:10D76000D0F581B496344D7B81C2F3CEA19509608A -:10D7700047FD82906AB4E33FF8EC34BD5D1254F18A -:10D78000FC7EED67EF00727943689A164BFF44C741 -:10D79000697E118A7D2EE32E55AEBEA1DDA7B82B82 -:10D7A000763C7F8B3AEE1B75E3F34D74DCA67699DD -:10D7B00071DE4A16B387DEA86B7304995FCDC6FD90 -:10D7C0001B362EE82DBD5DAA64FD79F4E330C4EF6D -:10D7D000619CED84403CA54F50A6EACF5DA5643323 -:10D7E0003CE4178DBF0FA5EDA768F5A2EDAC9F67D0 -:10D7F0004A867BB3B5CB8C70B569F62D11310E72AC -:10D8000015F4A527A22FEFB4FA1F043A202E09CB56 -:10D810004FA878BFBBFEDF2C307F2A3F3BF01EDBDA -:10D82000599308F2B3EC7CC8A2C7CB851BF4AB2E8E -:10D83000A8F6C2447234BF6804E5DBFB2117DE8F13 -:10D8400078F30BBFB3C4EAB7F67A96E11CF1FA405D -:10D85000ECB88A98258C8B6731CB88BFF5D773F1EC -:10D860005C703CFBFF10C8AF99608F1EE9D0DBFFF6 -:10D870004F6549AAFDAFCA339ED9FDF1E2AF432AF5 -:10D880009D4D147FD5F4B3562F7AFDB5345A5F0EF3 -:10D89000ABFC1C5DEF52D68DD1DDA81D1387EEE2E7 -:10D8A0008DABF91F5ADC37BF98B68FB12F33661C8A -:10D8B000B55EF4386F46ADCF183F224EDC2E299B63 -:10D8C000E13718276E9794CDE2766709D38B4AC863 -:10D8D000897AECCAD17BF781B9F7C0E2CF9D06F512 -:10D8E000D6A8C66BEAEA5F3D057EAAE65744ECF18E -:10D8F000601BEC935DDDC1A1BD113D4EB45DDE0842 -:10D90000EF15822055E307456619E3D4E43176BE6E -:10D91000DFD3BC1AED4B2D3EDD27047624D0EFB7C4 -:10D920006CFFB76DA05F353FFE2D8BFF411667661C -:10D93000F6EE855E17DE73DD3AEAFFF931DE38CAAE -:10D94000FF6AFC71A2F518953771D6632279132FFF -:10D950002EA2A5A3FB2C8254F80A9C4BE512FDBD18 -:10D9600034AD11080F78A859CEA19F5923C84B3167 -:10D97000DEFCAAC90479DF72DF6E3807BFB2DA2293 -:10D98000DBA5C8FE4BE96B0D85AF807F41270C7E80 -:10D99000ECC02FA57F82FBC1AF2FB64BB03F727694 -:10D9A0009E34E8A1F9B3777022D83D558BEF374FFD -:10D9B00083F15671F80E8DB399A8E7B56F5D5E5986 -:10D9C00040C8370044DDBD8F1A6D9F4659BB0FEE2E -:10D9D000CD4E4D1D30B9284ABF7B78ED3E1B85AB3F -:10D9E000A335E085FB78F76597EC83FB786969F2EE -:10D9F000D0026A471DCC9EB11CF2037FA3F557BA33 -:10DA00000FEEDFBD680AFA385AFE83EC65CB79D891 -:10DA10008F98A48DBF1ECBEF5AF2E0B16DB4FFB763 -:10DA20000F6F590E67D7CBEAB4F11F595EC953FA8D -:10DA30009FABE51F4B84BCC74922FB4CB309B144E3 -:10DA4000EEF7E179F781D1FB7C2DCBE1FCF8EBE53A -:10DA50004D95708FB3ECCB1DFB8AA710326B59B973 -:10DA600028D3FCDC9C2F2F77C2FE31A1F448F3723F -:10DA7000CE57107E8FD9A4F61FDA2767033CCA540D -:10DA800028E79467F655BBE13EC2F06920CB879B3F -:10DA90007B6C69867B098A0CA68970A23C9C85E018 -:10DAA000A8FBDAD9E169ECBE9D9A2F62718AD1BCDC -:10DAB00097E50776C4BE7FF2610E935F038ED8E5CB -:10DAC0003D2ADF6BFBAF49E789FC6C0CFEFF3CC4D1 -:10DAD000FD6746F8E914C4433CF8E45C532BECC3FF -:10DAE000DA189CF1F671F7A9E314B426E13B45CBB3 -:10DAF0009A9CF8AECE243F9337948BF89520FFCDB7 -:10DB0000268433D5CCE17B26690E123C4ED3D41447 -:10DB1000F6BEC9328A6A787764E1A4C0513CDF9BC3 -:10DB20009E51D206E7EB5A7FCE831DA6B51F0BA7E9 -:10DB3000B805E04C35D7946C29D6E1AF98C14DD7E4 -:10DB40005D6D277F13DE7B19189A9A0F767565B67F -:10DB50006488CB940DD558E05CEAE51C554E48AC82 -:10DB60007D6A25932B235BD4F72A6CFE12435C5FFE -:10DB70009D7F65E7B22F41BD86210B817388DB8EC7 -:10DB800097E33BFDF1F8BF01CEBBEBF476031FC674 -:10DB900073E60D70DE7D06F4F75301CE37423FE0A9 -:10DBA0001FC0BD0EB09B52DB62AFB716576EB8EE0A -:10DBB00026CA0CFD7786AF48FF1E2C9F685E91FE3B -:10DBC0008CF7F8C6F6A7DEE7D3F0CEAB781762C3C2 -:10DBD000F9AA469714DF261D3DAD52E98B4A3F7CDA -:10DBE000D7F7C2F2E25EFD7B0584EC60E73A78BAD3 -:10DBF0008E604F0E39F07DE0329EC9C7B2A16451EC -:10DC0000E1C6D285B6AE03C94DF83ED1C80A2EE6AC -:10DC1000EF0F9CD7E052EDA7F4BAA079830E3E8DAA -:10DC2000FE23FD0F7D41E38F75C8B77B197C606FC4 -:10DC3000C03CFCE169FA73201AFCB753D981E7496B -:10DC4000DB54FCDFE10AF57211BC8DC57FD604EB15 -:10DC5000998BE5654327059867431C3EFD650E3BA0 -:10DC600027927E3E9C08E703966633FD35D03FC37E -:10DC70007E1BF0C53213E124366FB033CB34F94A42 -:10DC8000DEFB590595AFE9A3792A5F2558875179BD -:10DC90001BB6D922F57F9AF3DEF276AA3F3C567680 -:10DCA0001F8CDA8F36A2BB8768CD61F1DBD9C1D872 -:10DCB000FBD6C3390906B9F5547325799BCE6F6538 -:10DCC00036D3E7B387157C2749E3EB68B95498C38B -:10DCD000D6D197C3ECF18F5F2E7113C8A515AA5C3E -:10DCE00062E5C4136880F234937A2F4164EBBEF18D -:10DCF00047330A210EB7D56B96E09EC34ACE9FF3F9 -:10DD00002D3A4EAD4DEA489022F4514B6C920BF0F7 -:10DD10004D47807BAF35CBEC98873FB03BFEBD874E -:10DD200063F447A4A4DA71EC5A0D9EAD5E01C7DB23 -:10DD3000B8AB3029A887930F3C8BF13DA70AA72DDC -:10DD40004A5FF1C67C5A5AB8D164D695BB98FEEAB0 -:10DD5000F6CAE539605FAAE79BA2EDA27BB23983E0 -:10DD60001CD6ECA2DF79199F50FE45FF319DFA8F3A -:10DD700004EE7BF407F03C183C605488F775D9FB3F -:10DD8000C66F1D2773C14FD2FAB92BA7D8D06FDD4C -:10DD90006ABA489FA4CC69AB942FEBE4D919F57DFE -:10DDA0007A4A0F33815F57E710633B73201BEE9570 -:10DDB0009374AB1FE4CD29217018D757246E58DF18 -:10DDC00085E62D87912ECCC4DD86E7A48E60FBEA24 -:10DDD000BA9152B4533F308741EFFC3C3703E339EB -:10DDE000A94E46B7A7EC4DD88E275232CA1155EE30 -:10DDF000FD3C770ABE7FA1C9CFC87D16AD1F567EF8 -:10DE00008A5B910DEFC49E4A9D5CD2C619ED1DB090 -:10DE10007F22F6D2F3FB6EA7FC38ABBA3F4C61A66B -:10DE200052E5A5E58FD2FA5B7298FE3BE50B0CC07C -:10DE3000B8A7DC4404F8670F079F85FC62AF13DFC7 -:10DE400071D3D623CDC47E1F264DFDFD15E01348AA -:10DE5000C55CC66F8773D93ABEA3E6D31263FF9E33 -:10DE6000CC7FA8F57AE0FE1FADD75D1EFBDEE81E75 -:10DE7000958F1B6D3DD570955E77CF13EF2DF38495 -:10DE8000DA55B4CADE1CD60FD56788AFCACE3AFCC5 -:10DE90003DB1F78756E1BBAEA3BFF301EF54D17597 -:10DEA0000F9395FB01EFC22FCC787EB3C3C2E8522B -:10DEB000700745B88794E28CEDEF7E578527C5CC77 -:10DEC000DEEBD6EE2F58D4FBFCC7547B2CD15B8BFA -:10DED000721DDE58937CF02EDB08DECFD5D631FAEA -:10DEE0003CAE45BDC77FF3F643491CFBA1D4603F60 -:10DEF00068E346DB1117E13D6E5DBC7B9DF7DC42BC -:10DF0000A2ABFF6932DC01FD7D7A5B96212E11CF39 -:10DF1000FEF8912A6FC15E5062C22518BE5FA47ED2 -:10DF2000A0A21FFF0A1B3F32AE9328BA71F7E6C8C2 -:10DF30003FCEC1F8CD5C11DFB1B0133C0F5BA6BE84 -:10DF40005F47F513BE5748F55235C86FCD2F02BE57 -:10DF5000179380AFCBCFE6A4EAF4A4DA2E5A1EDDE5 -:10DF6000A1DA0177A8FA26E9BC66373A248E8BE855 -:10DF70009DB17A8B53EDE868F918AD178C7635A50D -:10DF80005B456F078CE11715AF374F1F93E2D0C782 -:10DF90002D7F11FBB26C6ED03C0DE4663547601FDF -:10DFA00064569551DF3B7299DFE1C8751ACEE1D610 -:10DFB000D419EB25423DE0AB5CE70DF9297A7DC42D -:10DFC0009941EEB1FE36ABF4E07BF7AC00EF372EB3 -:10DFD000C965F650499E9C9A4BD3237FA8EC83DFFA -:10DFE000A11869E549AF07DAC97DC31E98974D04AA -:10DFF0003FB57C6D55D1115A6EF9A905DF9D2427D7 -:10E0000062FBF7AE664EBE8FF273BE2AE71A3C6C17 -:10E010005E0D9EB05040E1C86C60F064F70F72BCBA -:10E020004EEE65D7B37AC5B91683FEF1439EC2772B -:10E030006BAE16BF0CB5C2EFA164D7CB3CE8BBCC2E -:10E040007E8EA8EF6EE27BA9997ED6BFCB1FE2EE53 -:10E050002D8ECCBBCBB4A218F445579AD30FFAE25D -:10E060007379C1329877C3857018D036EBC2100F20 -:10E0700076DFFE3C79167CD7E62799C54CD81F770A -:10E080005E60F0F544D13F21BBD575E965F0B9027A -:10E0900025004F5AA284EF10D1BF7CD0AB69C9AA2A -:10E0A000DE482341782F88D8683DB0831CB49EFE9B -:10E0B000DE260994C23E412875DA74D0730B1DFE2A -:10E0C0009336D0AFD37DD3E15DA1170EC78EA7D70E -:10E0D000AA7A87C27FA71EFE78FC31FADEBA5ACF31 -:10E0E00012C78FD6E8DE591DDB5EA59A00CBCBD7D1 -:10E0F0007AEE86F934B40BF81B5D1ADEF7E70536C5 -:10E10000E6A6C23A1DE1805F33FBCB91AE32159E8D -:10E11000805DD1EEC80DC13BB2EDC99F4A07FCC777 -:10E1200083BBA1D92CDFA7E7E77601D7E348D4F971 -:10E1300035CDCF782C97E9A3D37981AD30FEE613A6 -:10E1400007F09CE083472F09E3BDEB73A378E3EA74 -:10E1500099FFD2B086BD9751BE96473ADCD42EE0E7 -:10E16000BBEA0DCF1E0FE37EF17682FBA00DFDC74B -:10E170004FC33BAD590DF24CFDEF126435B077E360 -:10E18000D212467F1F5400BD9DD9BFA201E95A2477 -:10E1900022413A0AA2DD956D63F6A886DFD34238A4 -:10E1A00017E267A74DC4DF46CBAF59942289E6AF8B -:10E1B000F91C7E787FE1EF8FBF213D067886B81885 -:10E1C000BC7B9017FC12E0A3BB959D27EF5E48ED4A -:10E1D0001E5A6FA1936C85FCC2361701FEB8513CE4 -:10E1E000CC8AA28B59DB199FFC283751E55782EF67 -:10E1F000291DCF4D50EDA8601DDAAF741E9D731020 -:10E200002E9C87982B7F15E9564CC671331BC29CF8 -:10E21000FEFE899646E84A7E3637F566E0ECC77D15 -:10E22000C64DAA9C295F7B947B5B47072FE69A919A -:10E230006E329F3DC2817F48CB5B177AB03EC607E6 -:10E24000339F657ED3265A7EBF41AE6CC0F97439C8 -:10E2500098FD48E5CA4980EB94690BBEEF776A3AAE -:10E26000C17766EFB8103E8DE25985F794C0D6931A -:10E27000A77868A5F99FE54A38FE6921781FACFBAD -:10E28000E94C76BFBBCBB403DF3BD5F83E9A4F7F5A -:10E2900096CBFCC9CC3547398827789CCC9ED4E0F6 -:10E2A000D3EA95E4559C05FCCEAA1E423C34AEE16F -:10E2B000D97D0D159E8542A000FCB461B5BF93AB1E -:10E2C000BF6D3E44E16B2CE6909E9FFCBB57912EA8 -:10E2D0001B7B38F6BB413DAF0AAB74FED5C1EFBD29 -:10E2E0008A7A65E9008B1F340E1CE7EF7581BE3911 -:10E2F00089F4D948E9CF5E0AEBC6ECD86B96702E4C -:10E30000E8CB68FA745633B90831D742F60E1CEEE2 -:10E31000FF86D6DAD0EED7E4AFA8C209EF08827C38 -:10E32000FD8DCAEF5AFF117FD5EE07FAF6BD3BFD12 -:10E3300024BCEBD6E8E7FC701EF93F46F50993D7FD -:10E340005222FC7660A4FF68FCE5E631F91A438F9F -:10E350007C184B8F687AD6F77405BE97ACAD1FAFAB -:10E36000E27D54BFE7B1FB578979BC0A8FEC853851 -:10E37000B644F9B9BB14DEF50B144B809F54A71FAC -:10E38000E23B7FEF7E5DDAA0C3D76981F23BCD9F90 -:10E39000CE77203C942F92F274EBD750CC7E67EA74 -:10E3A000C9EFAE40BC36C0DA51BC3604EFBB0FF14A -:10E3B000EC25E231902F4126BF1AD6DCC5DE05D709 -:10E3C000F4DF731CE2BF4171E13BD74BFB57207D6B -:10E3D000128FDD5FC8A15CC375D6F84CCCD5F61D95 -:10E3E000D8BB43D4AF6F857889E6D727D605940488 -:10E3F000692C9FA6A87EFD4CD5AFB7CCB6FD59FDC4 -:10E40000FA4DCD3F41FFE721EF8F30D5F884FA8DEB -:10E41000067EBA2D8FD92D929A56E431BEDC54DA9D -:10E420008FF4BFE97213F28FAB9AC911D705A3FC21 -:10E43000D3E260D4836374E8EC5F04FB110BBFC2CA -:10E44000892007E2C1FD19AEE967705E851C67E7A8 -:10E4500028167CF0F344FD3BA435798CBEAFF599CA -:10E460004918F0CD3709E3D9BFF1FACB0957CDF9F7 -:10E4700027BA7EFFD29784E782AE3DBBF2F3905776 -:10E480008E26E139929C702DD2C535CF1C3FD081AC -:10E49000A78DE1E95A7F25D2CFBBE99209DE096B4E -:10E4A000ED7F623EFC5E74BD0AD7BBDF3537031ECD -:10E4B000767CED3BF3E15DC94D212E05EE9B5DEBD6 -:10E4C000FBCA1F41EFD51F7D18CF7DB57DF37FA11E -:10E4D000DD6D0A1D61DFFB9244A877F59903F30116 -:10E4E000BF6DFD6D58FEEE3347307FF26BDF311F9D -:10E4F0002A8DD0F1BBDF3DF2C3DF433E9088F77237 -:10E500001A824F3E0E79529BC8EE5D055F11F4BF33 -:10E51000DF75F0F820F2A146174BFB39F5DD30012D -:10E52000CF7968F4FB56457119F01DA550BF793EAF -:10E53000CD7727D4C78A23EE51E7DB00B408E3AEDA -:10E54000E142C0075D82D287F25CECCF0579EE2C08 -:10E550000E0BF02EE9EABAE3F3D9CF10B662F94A0E -:10E560001B3B2F368DF20BBC1F457B3BFA21C4F7BA -:10E57000BA1E5C07FD1D3613D19C118177B320A113 -:10E580007FB4B986F3530E231CD9762A15F6C79AA1 -:10E59000897AAE8BD5EBA2EEA52D19F510B1D3B4C7 -:10E5A0006C5BEC38E893792E953E19BF660EACC8CB -:10E5B00006F9413C567FA12FD25FCEF9A66E78DED8 -:10E5C0003FB37E6811CC6349D18619300F0FC4FB6D -:10E5D00040BF282EECBF11E293949FBEAACAC73455 -:10E5E0003180EF8CD8E4402AFC269B640DE0396E24 -:10E5F000697DC0D20A72861FC95D858AF09861FF65 -:10E60000F0A025983113FAEB52F5D351063F6D8FE8 -:10E61000FD4995B207DAD3FEB13F5B9DCCE36FBEF7 -:10E62000D9D83AFCEB0F6E3F668C9787C6F45FEA49 -:10E6300002FDA2ACC17593049CEFBB5015F1ADDC9B -:10E64000AA8F6347C77B409EC17EEFE9BCF2C1BC85 -:10E65000D448AAC581A2F1CC4BB49CF65321C998E9 -:10E6600092BE1BBB77A6C9EDCD7B54BDFBE22594C2 -:10E670003B9B833CD3BBC1CBA877FFA545266F53FB -:10E68000C3F2E0F39790BEEF3DC1F4EEE61325022E -:10E69000D0B3F61EF2E68A6BA87F153341BADE2CA2 -:10E6A000F49FF642FFDDC44D2D7BB279FEF02D20A4 -:10E6B000FF7EFDBC7D0DB43F653221BD9DEAFDC4EA -:10E6C00091364E0F1FF303B8FA10F2E366D52E28E9 -:10E6D0005F7BDF01F0C71AEBD9EF116C1E50F98B8D -:10E6E000FA6380DFCD275E45FAD1EC5EDFD3354893 -:10E6F0006F6E4A6FF8BB095543081FFDF317D2D45C -:10E700005DC5DEC55D52545206F47672F50F778210 -:10E71000DEDE5C4544E8FF608EFC3CBEFFFB3C87D0 -:10E72000EF511EB4F454C03DC9830B2511F8637337 -:10E73000B076543FE1F9EA60ED00F28F679D1FEC7F -:10E7400087EED620DAD5DD194EB40B0E3EDF8AFAFD -:10E7500073B3E4F0C3EF992C3DC16DC5F68A8B30DD -:10E76000F839B4F397866EC3735B1A3E96560DE77D -:10E770003279C1E0FEB565E8D330EF5F7FCF0A6F35 -:10E780007E8FD2DFFF05D640AE560080000000002D -:10E790001F8B080000000000000BDD7D0B7854D5B6 -:10E7A000B5F03A73CE3C1226939327E1E9C90308EA -:10E7B00098841308EF872704102BB583F2B2220E3A -:10E7C000C823424846C48AD77E37830331526F6FCD -:10E7D000AC2FEAA576A06AD12B106DAC51030DA821 -:10E7E00014ABB5D1528A16BDA3222F918CE083DEE3 -:10E7F000D2F2AFB5F639C9CC640262EDFFF9FFE998 -:10E800005737FBECF7DAEBBDD7DE9336D9BFF18E85 -:10E8100032802BD561BAAC03A42B6DBE3B3201D242 -:10E8200000F435986FB07B9D3A9647FE430A6DCE53 -:10E83000C5EFD3C0081501E4DF23192137408A262C -:10E840000164516A335307C008C0BF0691AA811200 -:10E850006F31C027B5067C3800F84FCB0658CEFF85 -:10E860000058B1A8D5A1617F554F89FE329D46E978 -:10E870002D989EA3BFCB305F013778B13C4B966E8D -:10E8800098C1A98D53ABDC4A8799F3C87D64E1BD7B -:10E890005370FEDFA9043D0987E85D88DF310F7EF4 -:10E8A000080DC0F9F7AEF4F6D5A83C73A92E633E67 -:10E8B0002B03BE4FE591350ED82C75ED7724AD6B4B -:10E8C00004D5F39649582FAB678A1EA4A1E4725B66 -:10E8D00012B52B95F4CD1AE5AF7E14084E59BD74D0 -:10E8E000EA072064C2C15B66C37A47B353F4F5F408 -:10E8F0003DF407E56A84C7244DB5CA4BA99DE601DE -:10E90000585FDAD96E4ABE97FB9BD233490FE23C7F -:10E91000A737044A204FC0C1EBEE8443684DF2DCB8 -:10E9200050143CC6131CB07D6830CC6D2C22F87B93 -:10E93000ABA89F6C9B9EB11E3715DC81926B526811 -:10E940009C20C36B00CD03D329B83E3FF59BEF5D00 -:10E95000C5F0C84AD113C163CF25021EBBE76C9333 -:10E960003760BDEA2229E4C4F9DDFFE28C525A6720 -:10E97000F54CB70E98AFF6290B695C08B8E031CCBE -:10E98000836FD1BD53305F5DE9D5D76BBCEE455485 -:10E99000DE3733495F8FE50F3E2F1994AF0EB84332 -:10E9A0004998BFB259E04375F3D3CA8D98F620BC9D -:10E9B0007353BB40C98CE2CEF900ACE1F9544F3A35 -:10E9C000D1FF656C1F9041972762DE111EA8E3FA04 -:10E9D000AB27860712BC4E3E9F3497DABF62B30561 -:10E9E000689C57365FBA292875EDE7A4DDDB44EB58 -:10E9F0003F89EB0F60F96F9FFF7388E8612DD28329 -:10EA00009C837BB4462BA7F2F55340A57DB1F66BF2 -:10EA10008F23504878B5272F99F183E6E945381FB1 -:10EA2000A77FF602B8F5126F8D8670AEB6B5D629FF -:10EA3000D46E4B06C018CCBF70F7409FBB2B9CB167 -:10EA40003DEF8B4B01C65F57A847281885572E17F7 -:10EA5000D2DA304E036E4C7BAC16F089EFE74ECD28 -:10EA6000CDFDAC7085F7E0CE41CDEA065736E29198 -:10EA70002F59E3EF49F680D107E7E3682E6FED8366 -:10EA8000E5D9E9F81FDAB7CD3D42B46FD9D9E07BBB -:10EA90002641BFAB4C3CB3F6A5211D182FB33DA2B8 -:10EAA000FECF4DBAF98949975BCC348A2E62F1DEEC -:10EAB000EDCB253E919D0CBEC604E359ED717E5C05 -:10EAC0006ECD0B5CD84F26B5D36C8CDF717417CA32 -:10EAD0002A1E4674372559DFED227A1A963B2C08F8 -:10EAE0009DE320247267A474C5035A07D10FAD8B30 -:10EAF000E8ACBB7A0DBB047F8AC7CB674C3AA9222E -:10EB00005CC7796F93901E13EEB3E8A7DE966B7B1C -:10EB100010E7FBA3FD32F3D9F87A56BAAB16A0750D -:10EB20001040DEC66B53BDC5DDD7DB66D6FB71ADCD -:10EB30008B53B7AEAD51B0FFA12D5AA90C349E3600 -:10EB400089C60BE078B4CF2913E15319E1E319DD4D -:10EB50005078672EE179E35C5AD750256C2B25BE9F -:10EB6000EBB5416BA1E0DFE7F0FF3DE72643ABAB40 -:10EB700033DFCB971E93EF53D93BA67E3F7F5E4C8E -:10EB8000F925AB87C494E70686C5E4F3EBC7C6D482 -:10EB90001FD03029263F68C37762EA0F0E5D1D93B0 -:10EBA000BF74CBF763EA17372E8C299FF48FFCDDF7 -:10EBB0003F253CA7F527E073561AD17279FF8636B8 -:10EBC000C7AE3F7574ECFA158800D1FBA4E4BFEA28 -:10EBD00089E8D94A5341F92C6CB5233EE0D26C0F39 -:10EBE000E23CCAFF2C87D627988785CF567E922293 -:10EBF000C78C6BF1890BE1579EEFFCF8F263C217EB -:10EC0000E779E6FD0F39215DAAB9820F28E0E5F525 -:10EC1000A74E9C7BDEF5DBE3D70F1AE3BD87D69FBB -:10EC200000EFE3D79F3A3A761FACF5E7F90637874E -:10EC3000B19FCFE74A2C5FF651D198AEFDBD1BB70F -:10EC4000CED9AB52599F01EF3509EB77CEE34E9EFB -:10EC5000C7F54EF02782C374130E95B982DE2F4498 -:10EC60009FEF9BF3F81FA24F4CDD6B73991E619FC2 -:10EC70001C1A805D2DAC9776F544BC48F7B9592F26 -:10EC80005BA8B44269949CBFDFA4EF074DFADE5045 -:10EC9000AB723F0FD7E670BAB156E3EF8FD416725E -:10ECA0001AAAD5F9FBE6DAD19C3E8AFA18A58FD7C5 -:10ECB0004EE3744BAD97EB3D593B97D3A76A7DFC70 -:10ECC000DDDA9FEBCDFD016F06CBB3F8F5CC5F9598 -:10ECD000182F412EE2F6F391CEE4F3F0B52EEDE5D8 -:10ECE00079A9E7C3A3D50773B7BF1C8507D7E5A6E6 -:10ECF000641EEE81FF1805A3CEC9176EFF65ADB681 -:10ED0000FD65FB85E9C2C21738FBE18044F5AEA77B -:10ED100031C722BFC9DDDC1070770F9F4E3C8AC31C -:10ED2000572FE22B7E2D21D9DE8BCAC3BDA3C7F995 -:10ED300093B9CF567EE64C81AFF1FDDE6FE2DF2C5A -:10ED4000C24F2C9F1D47AFA77385FC3C9D2BF4F44D -:10ED5000FDDDF08B7B726DA6FC14FB3E6B9FE04BE0 -:10ED600077F6983FC197605C294F8BA1CFD9336369 -:10ED7000F771BF5DF0B7FD7F92436B12ECFF85DA50 -:10ED80005BEB896FF72773BD9FFE7F466FFBAF4D2F -:10ED9000617D7EBFDDD72F2B6A7FF65FDB636EA2BE -:10EDA0007DFFDF5CBBD8AF421548BE433A18A407CD -:10EDB000E192020ED2E5A0403D4C7482C610D145CE -:10EDC000F778A9C0618B9E64826712EBE39FCF4CFA -:10EDD000E1FD079F6A4054FFA0A8AC976EFB2EEAA6 -:10EDE0000A349E82E3A11E0ABAAD73FFF2E8BFC9DE -:10EDF0009DFC5AEE9EDE2E8407161F994D7CE43C46 -:10EE0000F2BA6BBB8BE32387888F5CFACDF3118B4F -:10EE10008EE1EC8D03BC295DCB67111FE90DF0D3AA -:10EE2000DCB7998F7C6D3859746BEA13F1FCA4DB65 -:10EE300076CD9917907F263F57FCF561C48BDBE4B4 -:10EE40009486F5D8E42EC5FF73CA07020A3C86A94A -:10EE500073F5E9DE878673B7850AD71BC2F69D5323 -:10EE6000F1FF32CCF6A053A57A0FF5F8F7ED945FD9 -:10EE70008D1CD389E99749FD4380B640699EE03FE8 -:10EE8000B2EB4CEF4351F3B3ABD0273A5FDAEAEA87 -:10EE900073286ADF86EF5563F223DA7262EA8F3AEB -:10EEA000A0C5948F0917C6948F3BAAC7E427444690 -:10EEB000C7D4BFEC8C11932F872B62EA57B866C476 -:10EEC000E4A7A8D7C6D4BF3C67414CF915DA4DB1C9 -:10EED000FD157887E7E1BA173ADCF5522ADA69B905 -:10EEE0004619E59393ABFD0BC84E5AE3516122D509 -:10EEF0000E85086E750E97BA1EF9D40792D11F10B1 -:10EF00004FEFB3A1D59D8FF5E530507AD0A697523B -:10EF10009A676CF1119D6E2F4CD6681F920702B450 -:10EF2000919C52F424407EE2E811F95D01EDCB6F33 -:10EF30006CF01826DB5554F4A97E736688ECDFACC0 -:10EF400064DF15348FF5B606CF1ADA671B781FCB4E -:10EF500064BCFAC968CC1F7E41B1119E6D6FB1DDF2 -:10EF60003316F39F61F7329637B59DF8C995981F10 -:10EF7000DA66D7A9F65090D94E5CAEC03D4A7AF712 -:10EF800078F6F10F843D15FFFD677982DF6755083C -:10EF90003B33BEFC8E3C21DF3E76242E5F6EB6AF47 -:10EFA000B86BFA43C4D7EC6D7620BFC5AA2CA32753 -:10EFB0009C4F5F3D930FA1E15179C50BAA9BBE0FFA -:10EFC000E4EF1577CD83B05BF4437EAC5549464FF3 -:10EFD000F23B7C3C29F13C6E31E7613FD3A39B7E41 -:10EFE0003DFCFDE3BCF3AFD37E2609421989DABBB1 -:10EFF000F97B563071FB7BCCF13F4E4F5C5EDFD12D -:10F000007F2F086444B7137CA7739CBE5C6E3F934C -:10F01000068184EBC8E4EF9063E410DEEC423A270B -:10F020007E519E96ED0024F1F91079C540F8CF206D -:10F030009300F1145C7A29F12950EC91B04517281E -:10F040003F1680F201D90B3644C67338B51B56DB28 -:10F050003F0847D1D10C23360F543F4ADE7C427D16 -:10F06000E37A928714A612BE9F022D554D805F56FB -:10F070003ACF257B95A8F51CEC464F6A33E178B072 -:10F080005762383E6FF2B191F320A1BED696E711D8 -:10F090007659A1DEF37C7283E0EBCB88EE377E1FDE -:10F0A00032B9FCABC219F182E57AE4BBEE10FB2960 -:10F0B000BF71785BF8DD27062F3EC98F9F777F2EC3 -:10F0C0002FE8EB7D2B8FE58A3690E4629349BF4DA4 -:10F0D0008AD163989BF8185426827F9F7C534F8D6A -:10F0E0005B771318390BC8AFA1D875E267C932F83E -:10F0F0009F4E00FFF875A79AF3C6F6735BA93D789B -:10F1000074C1E7C0EBCA463D9FFE854B280FBC6922 -:10F11000A7FEE7F93DFA7A54813ECF13FAF40208CC -:10F12000DB890F77819F3BD34E7EDB78387A419B1A -:10F130002FE55F189EE905C6E7041F9B4BCDDE8ACD -:10F14000EB9C1FF000F9696E98079E629C8FEFBBE5 -:10F15000E96F185877E155434AD6527AE9F83A9957 -:10F160005B4F66BD4F0AF491CF5DFAD5F5BE3A8F7D -:10F17000AF90E8E390A42D61384808079237BD8F1F -:10F180000F5C1005C715FDCA7F9F9F45E7036064AC -:10F1900090BF788793FD56B001580FADD9397813D9 -:10F1A000C9852FF27DAF51BD51934DFFAD11197837 -:10F1B00075CAC5C30BFFEC44271782976CD2FB417D -:10F1C0004F62BC19972FF6EBABD24B66BE8043045F -:10F1D000E1B0B9EC9BA717845F0CFF782D5FF05F5F -:10F1E0002BB5E0366A5AAC7FF735731DAFE57B3837 -:10F1F000FD22DFCB706EEFF7E9E12492FF0E5C7F1A -:10F2000002BCF7764337DDADBF3B7AF9A6F8F2C111 -:10F21000E4C4F35CFC2D99E71B344FE2F32589E746 -:10F22000F96F17894FB83F4B5CF9DFFC3CBFC8371B -:10F23000DEC8A779A6279EE74F2F129EC8EC96B48A -:10F2400062BDD9C807A9DE373D5F082C984272E835 -:10F250001A9FF0FF1723C7253E845379F4DC70D240 -:10F260006FF5751B88EFACF4E80195F9C81BF982BE -:10F270000F8281F399394D627F52FB884F97288422 -:10F28000EFD9D09A46FC6AA793FDD9F1EB0F99EB21 -:10F29000473A799CE004D32303899F1C1C98984F1C -:10F2A0003C1E5FBF3EC2F2697D7962FD749B49AF2F -:10F2B0002B5C0DD3B26DD1E72BB84099B86CC0E888 -:10F2C00043F2B64C5D4BFCC4817289E0EAE833A49A -:10F2D00027ED07E6BD12F981735E3F207918DE271E -:10F2E0003AE097D739CEF1DABD6A81BD7B7EBE5C4C -:10F2F0007E66A43FC17AB66ABE5DF95176E3F22D0F -:10F30000AFAA05D1FE7108DB800547C4E6E5F341ED -:10F31000D36FD0132ECA6F509C29E865453F2FCB81 -:10F3200007921B643FD7BD30A6943617F50F20FB1C -:10F33000209292CCF222D87B6CA11605CF0FF32D30 -:10F34000FD53EE46AF74C47C7FB7D685266567FE55 -:10F35000FAA3FBA6903E3F1FC2EBA8FEFC553DE87A -:10F3600008B2639D1DFD9D9162F4DBCEFE15FE5E2D -:10F37000EE72B7CA433175FF2EE17E6CD58CA304C3 -:10F38000CFB5FD8C63B4CE78F805EE1A9FC67E0427 -:10F3900082DF655DF7BDBB7DFEAB669CA6FE5EE8C9 -:10F3A000A75A7E1D9DCFE392ADF361453DECEA8403 -:10F3B000F757DD9764D3BF88FAC4399AB701557EF1 -:10F3C0009ACF3C8BBEE3F41C2814FE803A4FDBBA84 -:10F3D0005D517478832D9225E476781D3999FE6706 -:10F3E0004712F38FF61DBFEDE7E3F3344BEFE8214F -:10F3F0009FEBF1D5E767F917ECC989F569EB1C6359 -:10F40000B7BDA880F5123AE71D8D79495B44F6AA8D -:10F41000A2821EC4F5955F8ED884FD4D92FBB68402 -:10F42000711D9FC3D9E40998FE2788F5AF7AF3A32D -:10F4300074F2634E52ECC7A3F953BC1F684041AC51 -:10F440003FF914CC4B6D25B88C4F67B86C6F99940D -:10F450004AFD943C3FB927A5BB6AEB55C5DEE90FD1 -:10F460008A9F7F793776E9B002A177BE9E6C0C2B1C -:10F47000C0B4BC9BF58F32EB85938D5105599DFD32 -:10F4800051FD44F1106D832C3FAE80EB358105AC0E -:10F490006FD95CC857897FA2FE2AABE4272CB03312 -:10F4A000BD1BA0A9D9EC3714FB8F7C5DC1FC0433D4 -:10F4B0002FD5BF1DA4761B6FF1F03938F83420F931 -:10F4C0008080E173813AC9CF7E0717C57D60BA5E3F -:10F4D000D237902E26DB2219822E4222AE017C0AE0 -:10F4E000E57F2B85831427B0D6F5EF3F273FB81172 -:10F4F00054206922E615603F63E0600A9FCBF1CC9F -:10F50000701E4E6B5E663EC5CCB7CF9A3A6D00A6B4 -:10F51000B7253FE2213C0D4BC847B19F2F93FFBD5C -:10F5200095E9C69FACDB7B937FE93DCE4B2B937572 -:10F530002987FC4F9E42D2535743B2EEC4710C77D9 -:10F540007180C67568C0FEF86468E475B8DD9F0414 -:10F5500008282AA812DB4FC9BE65056CAF009F932F -:10F560001F7E2F6533AD3F493DD57A077ECA0083A4 -:10F57000EB65C4C9C72CF72A89E337BC4A9C5CF405 -:10F580004904FF9E73E3BFC7CA4B171C54899F48A9 -:10F59000ADDE9C73C89FDA086E659D706B53845D09 -:10F5A00067C12D30C9FF4B826BE04EA71ACCECDE51 -:10F5B000DF86001A45FA789BBA642BD547C3096CDD -:10F5C000D45F8E585FA0D229F641F16DA5F6EFD831 -:10F5D0007354B27B2C3C7B68A0C9AFBBF1773C5025 -:10F5E00020F4A3EAF4C3D524E70007B5F50738995A -:10F5F000727424F10D9497F5242F93EC06C3DB92DB -:10F600009B2B9AD600D15575F30220BEF28EE41BD7 -:10F61000F032DB23C076D99C6981576C1AF9B26647 -:10F62000AE7363FA49411EE3D7FE57A6BEC26C48CB -:10F63000761753BBD2CBBC53B270DC6031E8776233 -:10F64000BD60926FEBB3B4AE3765FD318DE2212A18 -:10F65000E0C3E12632E1F74DB333D86F9A5911A9CF -:10F66000A37881C8DDA0527C4F17FA388BEB1B09B9 -:10F67000F00B1E0BFB59A4B612FEF4427C93D4CEC1 -:10F68000F247A93C5FE42FC37C8DD852C86F29FF95 -:10F69000DE0882479B0C141655D322D968FCFC99CE -:10F6A000C359AF29A0F2CCE8F2B4E54F61BE60EED9 -:10F6B000049DC849B3F97E762B95BF01BC0E30F985 -:10F6C000F7A838FA1DD749375C5EDA91F757D07C36 -:10F6D0005FB919D88EAD31E56D0CBDD162B1CC18D2 -:10F6E00049F8D7D10F503F15667E9CA2723F7DFD31 -:10F6F00060F205EFC607F89CC0A6937FB24E6A6021 -:10F70000F840C0CFFA1EC5CD10BDF49FB76BB79DB2 -:10F7100006CB1474A7EF157457065E99E03552BDF9 -:10F720003B48E3CF9997CB7C66CC5160B830E5611C -:10F730007E429AC4FB943F209FF165BC4BAF97116A -:10F740008F64B9343F09C79B3B4FE2F38959735D1E -:10F750002109FF390BE983E3A1145FEE6CC4F7398B -:10F760003E499CFB627E5E943F1EB5613E379BED39 -:10F7700004FFD309F0397F80C077AB7DCD5A478C29 -:10F780007FE792016EE1E71830F59302E6BF22AE03 -:10F79000252BD91B117CA381F9D4611BEADFA4FFBF -:10F7A00082C1FAF63526BD5BFC6296710BDBC1B3F4 -:10F7B000BCB17AF43BB4274407D74AACE7CE997B77 -:10F7C0007E3DFB5C8164C6DDF455599E99DF35D0E2 -:10F7D000D89EBE9AF49C12FC380DF59028FD7EDE72 -:10F7E0006D67D3B87ECFC7579CBB0451A152F09729 -:10F7F0001A8427F1CBF26B15A697EAB50E8EFFAAF5 -:10F80000695E63CF267CFE21E8025FDFAFEB83F306 -:10F81000EC53658C90B528BF4D554822BACE269E34 -:10F82000C3F08F38C82F37DBA157D1BA66A7831A28 -:10F830004843BCBCF68A8DD4FF5A17A832CADBDE17 -:10F840002D6F8608AF9095EB849388391CD7D657D7 -:10F85000EDC1E70BF5B6611CB755EF49D1A3E3A4A1 -:10F86000D6AFE9C43B8AD7D29C304C35F737919D4F -:10F87000346480E0570F4AC0F22270AD8BE19C9552 -:10F880002FE295B2527547308DF88D66D5E338BBBF -:10F8900007EDBE5EC3310DA15A29F647B48BA7FB15 -:10F8A000AC0CB39F1E9A1444629CD9525A6623B87A -:10F8B000B953748A4FB4FAAD4836ECC4B72A8648B7 -:10F8C00023820CCF4DCA22D24F9362F9BEDD2EF6B1 -:10F8D00005DE157C3F5E0EA21C60BE4F7EFB6019EC -:10F8E000CBAF8A01592C0FB89FD58A4B75EAD0450A -:10F8F0009E657A2185FC5CC31064A4AFB7E5786788 -:10F9000050FC5EE07585FD6A6573F5EB1647EDEB1F -:10F91000E60E391099CFF1503FD4FB503CD4DAF2C7 -:10F92000CE3CC53D56428383F0BD324E3E2E73BF62 -:10F93000CC7AE4B247ED9DF80B1427AAE713FFA891 -:10F940007AAA8B3F88F954273F8BB32F417D89D604 -:10F950003302F931F121A3204566FF32CC13721432 -:10F960001E97C82F267B56D793DC6B97521AE4B2AA -:10F970004E3E39C2DCAFBB14EF4B141F1B407DE978 -:10F980003115BACA01F0B3FE3211E526E9D152CBE6 -:10F990001C99C6DDB814FBA6F37C255C41F9DB9607 -:10F9A0008A735208DCCCE760E3024E95E8FFCBE4B3 -:10F9B000FE6BCD71FD7664D6C7D41F727F80FB428B -:10F9C0007A8B44FC10CB7B4FC3A64807E35A8E705A -:10F9D0007F1B33045DC4EB312FDBDC219B8DF86E84 -:10F9E00080E54E128472087E4681E0B36507049F6D -:10F9F0007D2E801AB44CAAACFF9AE9B9AC0772F913 -:10FA0000D80870FCCC0EF0559BFACE5D034650B47E -:10FA1000A85FF071535FB0F4B82971FB78B9FB7E31 -:10FA200085F8D6E5395DF64BA6FEA781C4FAE21546 -:10FA3000DAF9F99661F12588E54BB97096F70FEE82 -:10FA4000DE732BF90982717A50F022F5A05EB9BEFF -:10FA50005FD0FAE2F5A1EEE2299F1A7071F194A845 -:10FA600041CC27F935D6B2B3E2F0A77ACFF1F9F756 -:10FA70004027DE75E07360D375B40E94E72AD97D14 -:10FA8000D26F1E62BA5E8BF5E4F104CD83C1FFC272 -:10FA90007CAB0DFC14AF003EF534E1A92577911342 -:10FAA000319ED42D1678374A11F9BEA8C8125E06C9 -:10FAB00047C7EBEBBE5CF2471B65C51C1F6BC9E378 -:10FAC000E13683F16404E81954CFC2939161518EF9 -:10FAD000F8F11AF19371D3105FF228CE76541FD249 -:10FAE000BBCA4163FC288F936B15EE990AD17985C7 -:10FAF0002B7EFF0D3E779C6CE2C714F5EBE1C7252A -:10FB0000841F96DC423DF9AE38FBE2AE38FBE22BB7 -:10FB1000E0C7918BC18FC845E247BBFD87EF05CA9F -:10FB2000D89EF5CBFDBBE287D472DB927B88DE8367 -:10FB30002940FBFE74925AE1C679D6548AB8F3E1A3 -:10FB4000BF2F08523E7B452EEB854FA7E92F71B999 -:10FB50005F9497B519720AE6F3576139E69FCEF5BF -:10FB60005650BE66359663FD11FB7C41CA17FC50AA -:10FB70009497DEE97F2985E47C40B47FE1589DECD1 -:10FB8000C1F2509DD9BEBCA182F235F5A2FDC803D9 -:10FB9000A120E507DF23C6B7F4CECB4CFEF9B47441 -:10FBA000EAA5DBA93FE49F9B917F8E3B61946EC3E6 -:10FBB000FC22D56623BC5D1C09D8091F0EDBAA46B2 -:10FBC00012FEC0425F0EE19993EC56B9937FD9C8FB -:10FBD000A983ED262A76D6FB5E95FC0AD59B4624A2 -:10FBE000417276B4EE22FE4EF1C89B51DE1499F2BA -:10FBF000C88ADFA57B0433A2F6AB68A090F356BD9C -:10FC0000EC748117F0B0C00B2BBEB8F52190C8DFA3 -:10FC1000426B633F449778633FCBEF50BFE2618410 -:10FC2000B797539C31965F3E56C419979E3B3D351E -:10FC3000915D347CA0B0E78F9AF722ACEF95A15C80 -:10FC40001BD1CFD3843CBD099EDA1F495F7A9AC687 -:10FC50001ACB200DC068DA47912F7FBCEF7DF57D70 -:10FC60000196DAFC0AE111F497749AFF556DFEC90A -:10FC7000BC9E2A80EFF54AB00E53DE2F093A368B30 -:10FC80003811C17F6699FB764C9DF7CAED6C3F7BBE -:10FC9000743B8E3369FC00A6FB9973258BEEBF3352 -:10FCA00090F4603AC1607FB68FE3DD6F8290830687 -:10FCB000B9298EEE97BB3F7B8FE4D2F22DB174BD94 -:10FCC000025A1DC2DF1C79E46DECBF72438A4AF20E -:10FCD0006745636CBDCA0DBF3F209574E50395165B -:10FCE0001F08C5F2015438041F7868089F7FADCC07 -:10FCF00091B54319E4FFF0B3BC4F0221EFEF52F48A -:10FD000030D35F8B53D851A67E7E9B2CF4F32470A6 -:10FD100069EE42E2C336335E55E4ADF1212ECEE505 -:10FD200054C3CDCC6FAC78180420CBFB5381CBD51A -:10FD3000683F5B079F8FA3F7D2969EAD74DFC0F23A -:10FD4000B3A07EC0F6152C424E378EF910EF9BB44F -:10FD50000CFF3F86D6E5E0753DD4A33FF3F7D548C9 -:10FD600010CE52B28B95E256EA7388A02717D111B4 -:10FD7000F1F769B1F65612083D7E789BF0E38CE806 -:10FD800094FB75B4BF4ED05D42EE3700D157B7F645 -:10FD90008A7B55427B852514F63F7B9AE0EB17B2B0 -:10FDA00057BAB3473AF63309F5364C67FA92B6D3E9 -:10FDB000BA2F3B9B9A92289E6A66B9EC25BB6CA62B -:10FDC000DDC84A4FA0E73F60EAD91DF57D6EEE4FD2 -:10FDD000F1656CA7F825ECB795F87FDBEB8E8471A5 -:10FDE000C98AD9BF6237D444FD5F454EA9287FBB7D -:10FDF000E2CBE67EBF017DE579DA977879E4D81D1C -:10FE0000774E098181D171054F0F12FC6E4281F14D -:10FE10009B81744E94D49FF99D568AF6541FCE73DD -:10FE20007F076FBE9CE3243E03E38271126BA3FC49 -:10FE3000E707D3129F8BBC61F2D7148A7DC3F47697 -:10FE4000CDF8038D7FD421CE5D8E269BA9479C5B88 -:10FE5000BDD3515FF0C788C5276DA2FC687AEC79E5 -:10FE60008D55EF94D9EE50ADCBBB36CAFFAA3DE419 -:10FE7000F4939CCECA37EF71AC02B69FDB9F4FDB89 -:10FE800014BDAF670796A70CA2F8A27CC3D18BE084 -:10FE9000F8BC907FD54AD841FBFBF025BEA334EFD8 -:10FEA0006A0D8C67A81F2DECB8A698EC06111FD21E -:10FEB0006E1776607B9248AD799D1D382365109D45 -:10FEC000CBDE1C66BED8919F1166BE7776A097C721 -:10FED0006D9F65959BF9FF10790D549DE65BEE32A1 -:10FEE000ED8742752DFB5D51EF23BF4DFCF901C03D -:10FEF00078A11F9BF19E46DFBFF3395E777E7E9B24 -:10FF0000ABED95FFC2EFF34D7FB0AFF9D357EED015 -:10FF1000187F0ED3B80B4249C071DFFFA45FBFBD8D -:10FF20005F1BAF677D79A4FFC3651C2FC07EB5152D -:10FF30002DBF65BEBEC2A2FBA658BAEF65C2F14294 -:10FF4000E76AF1E72DDF009D0D1C9440EFFB35C9FA -:10FF50006BC4AF29F274E66BA79A24F68768D05673 -:10FF600047705E29897D59F9EA8D150ECA2F0695CD -:10FF7000F97C533C3FF305494F585E0F2CEF4A2163 -:10FF80003F95E05DB357261F02DFB7D1A2F824DD0D -:10FF9000B7D1A2EC62BA6F139DA7FB36D1F5E9BECB -:10FFA0004D7439DDB7892EA7FB36D179BA6F135D51 -:10FFB0009FEEDB44E7E9BE4D747DBA6F139DA7FB4E -:10FFC00036D1F58F80FFC1F112C175E206826BD385 -:10FFD0001AA74A70C5ED7AAB289BC519E31FDDCB84 -:10FFE00089EE67B967AA6305C2614F8E0CD268BA01 -:10FFF00077B32CA6DFE57215FB0950ED6039E2C737 -:020000021000EC -:10000000FF313CE522B6933F6F962003F175E986F8 -:1000100038FDA1E5DE3AD2B76F0AC57E5F0E517E8C -:10002000F7DCAEE7404B0699F1C0BDA137E1F31410 -:10003000D9ADD33E9FDA27EB4E305D00B4CF5B8560 -:100040003FB214063D349EF7D10E218D8E4744F900 -:10005000A98D722890DB793E746AEFAF0EFBB0DE9B -:10006000D25EB24A74E7CC89DDEF242D76BF7B14D3 -:10007000C6EE778A1EBBDFA9A363F73B1ECE694697 -:10008000ECFE833C9DE1BCBC0F9A77387EC6B45829 -:100090007CB0E03B1AFF27F05563F82E41F83E2C68 -:1000A000D1B9DA3D7BFA685DE15CDD7CAF83F4D7E2 -:1000B0008B85F37D7170FE1CC657B819B830D335E7 -:1000C000B2535F2ADBEBE72081636ADF0AF35EAF9E -:1000D00038DF31E18AFA0BDB0B51E750F5B2CCFA8D -:1000E000CC26A267233385F980BEA107EFD73097CE -:1000F000E86F31F8983F2D8ED36B96BAEF77905E0C -:1001000013BF4E9A0DF95D2A5B845E13BFDE2EFE8F -:10011000A842B5B58FE0DB8D0FEBB4CC168B4FFB4F -:10012000C88F91096D0ED263BAE38333728C5F93EB -:10013000DC402E06040F610AF05F427DB2A6A35890 -:10014000F8E79D7EE1E787401ACF6314887970A3B2 -:10015000287FFF2825C47E073429D8BF64D963F1DE -:10016000F084BED2DAB7B05FF92530E1A8CB92AD0A -:10017000D37F8F56A041FAF5C8CF84FE34DAD51864 -:1001800054B4AEF6F927F9E639B762C67F5EE01CD3 -:1001900092E64F7E8E6BCCF8BB092DA35EA17CC787 -:1001A000B9E4CE57FBD07E8DDFF9FB0C4ADF92B469 -:1001B000C7EEC0F1AF96045EC4DB95C11DE334DA2F -:1001C000FFCB242FFB2BA682BFAFB047423CAF89A9 -:1001D0002E1FEBB5369761E7F328D37F09109E4AAF -:1001E0007AFA32DDC1F358AB7E3095FC31CBC1F4E5 -:1001F000C734C7EE5F177B28CE0EAAC2FDA77EE3E9 -:10020000ED9E047814170F102BEF17145AF7CA45F8 -:10021000BC8A06E2FE77A5E947AA746DF4887338B4 -:1002200094737DA18BDDA410E0C7F07985BD90EDBE -:1002300062B407F8BC5F73248AD7033593CFD56FB8 -:1002400074CF64BE7C637D17BF0EE3F5E2860BAC12 -:10025000CBD413C6D3379CFFE1419A90FBC9D3F7A7 -:100260001A545CD6D63F5A9FAD7188FBB9E0CF884F -:10027000B9B730B8509C7B97997A53A5CB8453611A -:10028000A08EF4E30EBDA98BBDF8F5EEC958F12E92 -:1002900008AFA242C6E306CF9ACCCEF31D6B1D9FDA -:1002A0008C687BBC15E125A74C76117F5CD1CF37DC -:1002B0008CEAF73B103E4C74036E8DF5F593CDC779 -:1002C000F6CB799DEB423C7B701CADA35956C5BD66 -:1002D000F940DD38ECB7BD54E05DF7F6AF8027CECE -:1002E000EBB2C2ACAEF3B2E2ECA7C845A9E128BDBF -:1002F0003DC3845FFB10EF146A57F6C7BE1E9AAF6A -:100300003DAF714F6FD28B6F157A31EE2BFB41648D -:100310003B48A4974E91CFDE42F95339A092FD9904 -:10032000D923207B48CF5B00EC2702DDAF13AAC89E -:10033000FD8AD84ECEBE15ED27ECF7DD5537A6D198 -:10034000FDFEEC944569F96E8A6FC2A90EC0BC64CB -:10035000F38AFBD9CFBCF76F65543E8FFDD2D73BF4 -:10036000C53973EE0FFEB69CE900B474E7181ACFD6 -:10037000C7EF0B44D2649E5FF9B59F0D27FDAAF726 -:1003800059F730D2CF7AD1392F8274A8491F9755A7 -:100390004486FBDD9D70CACC4F6CBF649BF03898DF -:1003A0007C72369D8758F7301EEAF1069F879F348E -:1003B000CF4FF28C69A984E707075AE75AAD59E491 -:1003C000B2AA4E3252E7D03CDF94F97EC567AA91BB -:1003D0009A86E527C1CBFA63A0CDCEE744ABEEAE5B -:1003E000E899EEEE3E6E7F4DA1B06FAAE2E2A2AABE -:1003F0009456079D6755FD9371514D6871273A0FCB -:10040000B3D65F9DA68032145309BCE7ABF7E23F39 -:10041000E48470DC629677777FE3E7E6FAACFB1959 -:10042000D5743F033FAD7ABEBC279CC70EAD3E33AB -:100430002EE61E04D96BB4BEEA3313F97BC55D27E3 -:100440001C84DFD40F3D8560DDCFE80ECED985C298 -:10045000DEA8A67B0D19D1DF051D77F69FC9E54FF4 -:100460009A707B72AF6DDAE604F37CBD50D8DD4341 -:10047000B214F6175CDA0AC6A604E35AF5ACF70D17 -:10048000BA9B57D3A4F07C9A37C505271A6FA709E2 -:10049000476BBE4DE9E1255E71CE3A90DE2FE8C88C -:1004A000AB91FE5747F1D3B3A67FA0E93BE1FEFC39 -:1004B0005EC615C28EED6E9FE7F4F3A5137F18A9F3 -:1004C000B4DEFA4A269B5D407EB49EF35A6D242723 -:1004D0003BF84F37FBDD096739E61E4C57383BB810 -:1004E000BCE3FE19181E299BE410B03EF0D01F4B50 -:1004F0001C0E1CFF980D22C477A6C87DA7BE4079AC -:10050000B41F882E8FB1ECC07483CCF7998E3D9ABE -:10051000EF20BB6C49394464E45BC7DEEA5F477196 -:1005200097DA02D424C7A1BAB336F6FCB1128C3DD7 -:1005300029D8EEC603DED456CC2FBA27568E1D7BA3 -:10054000EBC70EB207A4856E3FC515E13CA7BE8080 -:10055000F9C5CD0EBE9FB5E4FEF8FE62F5E06C5322 -:10056000DEC6EBC39F179AFAF048184972E685DA9F -:1005700066F17E8E791F11F53F23119E587A7028FF -:1005800079D2DF99EF43A34C7C699C92B8FE92220A -:10059000B10F2B1F3BEDF068DDD3D971E42705388F -:1005A000FE895A95D3ACC1866B30F63F60B02F659B -:1005B00030B697B548FF4FD8CF29CE4111DF385F0D -:1005C00043F7D448DECE157A8253BEB992F5D13EB8 -:1005D000A006597FF1FBD99F6E43FD248DE2376E53 -:1005E000913DEC6F10EF078DF968511AAD37F3BFED -:1005F000E73C4D70A53B0E40EFB0941BA5C4DFD780 -:10060000CF70F379FF265B80FBA140ADBB109EA1AC -:1006100027C7EC26F77941E3BD93C8EE535B76B567 -:1006200092BD526FFB740FC525D44F043DC8D00E48 -:10063000F138352D339EA6F6FD67BA75BA5FBA3E1E -:10064000D72855A3FAD720F21EE99927AB6CEC37CF -:100650003DD5FC0B3EAF42FB2E42CAF7A9AA3CF6A1 -:100660009B59713F7CF697C06F7802E51B44DDE72C -:100670005ED1B4C946FAF8A5B451517155D6BCAA99 -:10068000EE6CCDBE8EE4EE130ACBD1CCDF5CC1F1B3 -:1006900003B98A26113CAF9354A18F9A7AF2B560C0 -:1006A000FD35BC42FAE942D293110F3F94421CAF90 -:1006B00069839667A9FDDC1CA10F82D63882FCD71E -:1006C000E12AF37DA2E5F634D26FAC7382EEF0A19D -:1006D0003B3F0FF6B4E41D1CF7A404EC6FAAB14530 -:1006E000FAD3FC8EDB13CBD779834D3E30D01F621B -:1006F000799E0EEA6334AF025F2ED165B54D5BC9BA -:100700007EAF7D5E8E0F6997D4F498775ED4865F56 -:1007100093DE5D6353857D73C028A5F398F6194574 -:10072000FCEECB497BB83FF311E47B149775EB13D8 -:100730004D3315845B756FD4BB30BFF9895D3315BC -:100740007A87272FBCC486F95707FF45940F091FE6 -:10075000A6FC1F9FF848940F0B2FA1FD39F9C4691F -:100760009127030C11EC6F4FFCEFCC00AEEBB8E916 -:10077000FF043D3C9FE659FDC2205BB47FF1C86099 -:10078000C1378F27897AC773E186AB49FF280CF3FD -:100790007D18ABDE6B83CDFB0426FEDFF462522BAB -:1007A000C5095BED202771FF41B3DD4DE67B59485C -:1007B0007FBFA27A2FE768E9BCCF479147115C9EC3 -:1007C0001FCCE73D370D4EE7FA049FF4A2AEE32DB0 -:1007D00023394F72C01E7BFFADC1DC2F2812FD579D -:1007E000F756D3683FB2D3859D811B927617BF63BE -:1007F000B0C9D4ABC4FE64CA6A695065B9339CEC15 -:10080000E697CFF62D65BBB9A29BFB9E83851CBBEB -:100810002928C689F4D2D4CD7CEF1C0C8A4779B93B -:10082000396973F47B29274DF81E199C26E0D7B14E -:100830000F3D251E2768C2A52FC2BBB8137FACF69B -:10084000175AF7F67FD1BABBEC5399989FB51E8023 -:100850007B051C707E69A8E71F5F63B61B6DCD43E7 -:10086000637AB8E9C5DB3708FEA7A5B3DD0E3F11F3 -:10087000707059E316F1F9E40A530F96036F38C804 -:10088000DE5851DFC6EFAFAD6814EF6D75D29DB184 -:100890002A9ACE32F3C53A33652333C8F488EB6322 -:1008A0007A34CC788358FCE980773C1D77E94F4B4C -:1008B0008FED4FE3FEBADB87B08917DFD83E041314 -:1008C000C3B383BFC4C1AF831E73CD76458867654C -:1008D0005DE9F18FDDD171EED71CCFBC77B2E27646 -:1008E000335E558BC5E3154DB9B685459DF5EF6E65 -:1008F000BCD71B1D4FEB6A5A1020F957D352CE714B -:10090000B52B9EDBFAEB00B65FB6FD010F05531F5A -:10091000531AB2492FAE7A6C9DC7A0731625E021F9 -:10092000BE792C244F4B747F75D41029461FABA67B -:100930007F62FFC79FFC5BDDBFE1FCBF9050BF4201 -:10094000785737FDB58EECB73D862B4272FBA81267 -:100950009E4A72F4A6056E3FBD2F58D31CAB4F2D97 -:10096000FBE503D91A077707FAD8589F6AED43EDDC -:10097000AA1FB5EB64BF57EF93751C066A20524758 -:10098000F38B6F5FD3F8A183E0AAA23ED8775CD740 -:1009900072E4248CF7354D3FFA54F6507AEC1D285A -:1009A000A1FEA2FC1108F7CA6EF4B2C221B1F7028F -:1009B0002CF840288BF59BE0130F95BC8FF33AF190 -:1009C000E86B1EA9285A5EDE29CEA91A6FFCF90B26 -:1009D0005AF772F524E907CEAE7A80D62C0925BBEA -:1009E00045A455F6560FF905AA36D9F5007EAEDABC -:1009F000FA8BC7E95C05DE76EA74F458B5F5B48382 -:100A0000DE3FAB928C88C47A1678A4919DFBB47CAF -:100A1000EB47C25FD54B86E9B84FCB7EF5B9A86FDF -:100A2000402409EB2F7FFA7DF66F55F9DC7E578263 -:100A30007DAA68DCE508BB13EC53E3FB53490F0ABE -:100A40003EF125EFC3B19D12F4CCEDDABE72D3476F -:100A50000EA29B13B8211969025E649FD634CA0B9B -:100A60001CA989F6ADF52AD2FFB09CFD2017DA3F0C -:100A7000D7101074F1DCD66D640F54BEE3D4A7D345 -:100A8000B8DB6EF100EEFF11C52FF0FD67EBB20D84 -:100A90001CB7D21EC8563915DF2B1FB995F170E966 -:100AA0009BB766B35E07462FDB685E6F2F5AE7E29F -:100AB0008DB3789D4BC0C77858F933E1CFF85C818E -:100AC0006989EE1B6F1F22E487136E2E21FAF81C32 -:100AD0007B223FCC11078878DEB7C43B644EB83A1E -:100AE00035FA9DB93B8708391080D07BF4FE640D40 -:100AF000DAC5C417E4373F9F4AFDACCA55FC4E9592 -:100B0000D71F30E1259D13F11C9A62C59DE6E17E59 -:100B1000BD39A527D9C14E38E5B8BE8CDF69D0C82C -:100B2000FF1BD58EE17664B33359423BFF4876E232 -:100B30007B84EF99EBC0BFB7200A9F6AB61C617C2B -:100B400002B4BB527344FE61A243B48B52116E9F38 -:100B5000EDFBD0D19BFC1D99361840F36DFB88F35B -:100B6000A0676954DFEABFA6D919F32E49CDA31FA8 -:100B7000C5D1B333EEBD133FC3B3065235D2378F61 -:100B80003822535FA471705C8AD75C72BF33E6BDB4 -:100B9000B04E7C71747ECFEDA44FCBBE5A6AD27F2B -:100BA000FCFAE3F9C19371FC0036667DA5F79FAAB4 -:100BB000ECA1C7093E5548AF01A657417FA8A347FE -:100BC00006203D7CFCD44BFBBF4F7EBA467BE674CF -:100BD0001E2D96CF563E83F44BFE348477924E7C86 -:100BE000F64B07E9BD39156807E3BC3F76EB74297E -:100BF000AD2BDDE2F78474EB063ED7FABFC55F97F5 -:100C000076C35FF7C5C1F373284AA53B0CC79F5C49 -:100C10007E09FB15E2E06BD9BBF17CB37A88C67024 -:100C20008EE79BF8B71FA2E0B8ECBF3F61BCFDA206 -:100C3000973807AB7EF4AF2CBF10AC1127E26D756F -:100C4000E853CEAF23F9C5F95D33E9BCBAEBBA631B -:100C5000E1195FBEC1E4471DF7DCEE8400C5DD4548 -:100C600076C8FC0E433BCEA58EF4F3A772F99C70B8 -:100C70009DA9EFB7AB110FE9E7EBD2AC3CDC40EF3D -:100C8000C1B4074AD400B54F32E30FBC114F5A9498 -:100C90009EF47E8BEC21BD2E1C826989DF050CF24F -:100CA0003CC2D05DF91A715F4B3EBB2D6CDAF54E3C -:100CB0001C2FBCE6CB6D746E7E4871F1B9E5A23590 -:100CC000733C7CFFAF25FF3F092F16BF8A70247A43 -:100CD0000A188E5E08E71B0508D0FC08F079B09C66 -:100CE00052B6E745ACB704014CE724F1FE9465E049 -:100CF0004D6DCDEDEA374139E820F9BF14E511FB20 -:100D0000BD37C6962F6BF998F16C591C9EF908CF28 -:100D10007A75C5B3DC4B4DFF4A29949AE7BA6CCF7C -:100D2000B7EF95F93CFF940B58DFA0735EDC3138C8 -:100D3000D522F3FE9C7A4A0A71BC61204BBCDF8A43 -:100D4000F84E7A968587F1F67D7C7AE2D97747D29C -:100D50003DB1AA5FFFA5E4BF303DF1EBB707BE4848 -:100D6000F9E7FEDCFF2FD0B57EC5CEBFB21DD3BEE6 -:100D7000D3C9FED0F69DBFED4F72B9FD05A74EF861 -:100D8000DB7EA753C435EC4CE177CCDAFB09BF5DC1 -:100D900070C7972561965B6B791FA75FEAE0FD3E00 -:100DA000D5F2379623A75A9C1AADA366670FF68F24 -:100DB000D5BC901422FF40FB8E2F4746BF77F5CF5E -:100DC000AEA7DABC4FD39E0273296EA63D4DC4591F -:100DD000D6BC38E6176BC81E69DAE520FF7FC56F01 -:100DE000FE5E427CA9FD995D0EE25B68973E02883B -:100DF0001F732EFDE903F65E745F0CD8DE3E7DE9BD -:100E00003BB3E87DACAE701170684738D0BA102E95 -:100E100095A49775078FEA6F2D3C3E657BA2AA6566 -:100E200014D351275C24437C4F09B9245AFFF31E85 -:100E3000F21BB5E7A1FCD769DD5F9690FE74A17542 -:100E4000FFC7A5E27DEEFFE7D76D838B5AF753DF2F -:100E5000DA750BFC1F76A926DEA78AA383AE78FE7F -:100E6000DC0F38BF2D45E7F97E45FA7FFD5BBBFE01 -:100E7000AFBCEF25E4B7BDD87DFFF85BBBEE0BED53 -:100E8000FBABE6BEA7A874BFAE7DC7DFFBF37ABF9E -:100E9000E2BA938BBEADFCEDFCEBEED08F64AF8B72 -:100EA0009ED8BA075ADB344CD775A3A78C2AB2FC5C -:100EB00010C21E914D7D631D0C3336915D857A06FF -:100EC000D901EB3245BE1EF50799EF0F72B00AD477 -:100ED000F7D5C5BBB68A1F54CCDBFF7C23C7B3ACA8 -:100EE000CBFE0EE495D17985F06304D7E8BE5DD8DA -:100EF0003E9866D3823A3D57B5D2B709CBD5DEB21C -:100F00004AF6CD3AED6A57F43B168ADB1163A7B86F -:100F1000E3EC8DE402478C5D9204BB55F2C327E9F4 -:100F20000AC7FF3921AA3DD6CF2A12EFF42743285A -:100F3000A0BA2F1E4E8BBE3E9C5C7CAF5235E104A6 -:100F40008641EB766A0AEB610AA0FD28D621EC4EB9 -:100F500084A316054730ED50C504B9A20D6338A22D -:100F600001A14D1A4D70F5331C83BD6495E1DAD9AA -:100F70001FAF3B7E1FD6699320CFD4C725FD9B872B -:100F8000F3D822111F100F672BCDF795AF21FD77F6 -:100F9000D51A71CEF5CCEFBEC3F9263BEAC374CFA8 -:100FA00030D5B7A288FC8E5E43223A5D3543BC2F14 -:100FB0005846F7C032C9D41771B899AEBEA0B0BFB9 -:100FC00012ED0CF657AA40F69F3C091AD91FE855B6 -:100FD000E2E27A558E7B0ADE2CE29EA01034F14EBE -:100FE0004B6CFC4F601214525CC314B9AA81E675B5 -:100FF0000A521A28EED2616FEDCFFEE17E008F918A -:10100000BFA5FC8B8D549E8B7A3DD07D32A5F53DDE -:101010008A6FB84D4E058EAB8AE0A728B85D76C6BC -:10102000054A149CCB212D267FA2DFE126B213F2C4 -:10103000024E9582C72A5CBD62DA9FE87586C70BAF -:101040003A5D2AD94753D4DC98F6B267EF7B64D770 -:10105000BC916E63BBE0F29CC131EDAFFAE0C4C657 -:101060000526CED23ABEF7AEB8A78AF6D623AF632E -:10107000BB37EF0720BFF1155A694CBB66D3BF12CF -:101080009962E7F766AE2C1C13336E737837C3A5ED -:101090002A0B243A0FAEB2214960BDEFEAE531F5E3 -:1010A000BE37FA8A987E67183362F255ABBF0025C7 -:1010B0000360DCEAB340EF0796B636C6B41FBEB78E -:1010C00039A6BEE7753485302DDDA705291D75507D -:1010D000DC231D8EFB41E71BCDE1853AC5EB14D324 -:1010E00005D0323A16F0565018F2C8A3FE9728BD24 -:1010F00050FC3298EFB2269BE7AFEB6DA1C605B965 -:1011000014FFD3F0E35D12C743EE263C1D1D69A812 -:1011100048C5EA63CF34BE446953DBF87A7AC7B373 -:101120000AA08DE5AFDBC6E70253E4961289ED9F76 -:101130001EC39D51E72EDDBDD7F9A3D2F27D4548F0 -:10114000476B738C865DC4F727BD3B5FCEEB5A0FB0 -:101150005425128DE73F2AF51EA6384D2B4E2AB98D -:101160004216BF4771B98893A9B3E94926F362FDD6 -:10117000409D6AE738FE65C582BF8D6CDBDCE82EDA -:1011800023BBD3A5D1BE2667C4DEF3BE71B4B8B706 -:10119000F7459179BEA2A859D7931FBC3845B4270B -:1011A0001F1F8D37DDC6FA94E780BEC78EF9FB0A94 -:1011B000F7A9C4CE9AA67F10E0F74D0FB44D903436 -:1011C000809EF794DAC80E87BD76FE7D99A6C2C9C7 -:1011D000A70BA87CFA5B1CC3B86BC22F0B49BEAD32 -:1011E0001C3CE4BCEF8C7ACE48A045C5412C2BD6E4 -:1011F000783E1E25CCEF1279CE285CEE99A7DBFA5B -:10120000478DB77282D0FF560E4EDE4A78EB3960BA -:1012100088B8A842B73680E9239CC37C4209E75CC2 -:101220009F22E2ABB4F3BCF37F7CCB88349263198A -:10123000E57A1AF94133B6CA1DF7CE683D3FA6FFDD -:10124000D0C13AACDF3F19E7B58562D744792BF2BC -:101250002458EFB0CA9125613E43B2CAD7CF9E5CF5 -:10126000C4EF31C6D41F9AD751DF70E574F6AF15BD -:10127000AFDFBFB688E037CA467125EB7F67E777F7 -:1012800006709DAC4FAC447A06E97CF0EC710178B5 -:101290007AB8FC90A4C5BD9FDB5A4CF982BEBE4112 -:1012A000C558FF92B3A9FC0EC067F5492CFF2E3933 -:1012B000FB3D7EAFB3C961F4BF9DFD37491C6F365E -:1012C000E3E68F37AC26BABEEA7821C52858EF5737 -:1012D000D6A85F303FB0E2EC3AE187F88B78FF6345 -:1012E0005B679EF883A7139E06BDCFB53E0ABEF48A -:1012F0009B2F334C78FA8A37CE5E8BFD6B8BA6E53D -:10130000105D9E0637C7F59D561F9F4DF33DBDC529 -:10131000CE41B44D26BF0C149AEF11648673E85E7B -:101320007EF19B368E473A88F860203EE4B7BE993E -:101330005E4CED3295748A6F383DFECFFC6EC2E98B -:101340001F0207172F0B3B185E4D998B2ACA19FFF6 -:10135000B574F23F58F06D34FB79B8D4B8B298FD4B -:101360005CE67D1163EC45BD3FB96BC2977C2EB046 -:101370003617F5FC340A393E5347EF4BAECCB5B3C4 -:101380005C5A99F6C5D44CC2F7725784DE81A859CD -:10139000FD19C317BBC98DBE07A69C91418B8ADF7F -:1013A000D2868AFD571483F75F39E3E0F2AAD5A706 -:1013B000996F5BED4F98E7ABF42E23DD17AAFA8700 -:1013C000CCF746911FD64BC328DDED5819C54FA069 -:1013D000F1D30E3E3F14F7EABEE96F25939F728664 -:1013E000A4CEA2F9B56C3B339BE2056624A9B328D1 -:1013F000DEA06EDBFBB329BE60463F7516C517DC69 -:10140000573C790E97F7521FB0A1FC7AB964BEC859 -:10141000E7AA7FA2FC535BEF98C3F553C4BEDFB6C7 -:1014200075CE9C00F36337D3C1A9FA1E21E779E892 -:1014300060E9EA1721FA3DDB2EE5E6EF49C15CC120 -:10144000F73EB9BB0FBFDB09056D1C2FB6BE58F8C0 -:10145000FB3BCF5741A5F3D5CC7C30C8DF9CF95C72 -:1014600092F85DA2436DFD097E4736DEF203F2A7D6 -:10147000AE9080DFD1AF026D24D1D5425BF83D4AFA -:101480005F1CEEBBB798F5A9368E775DBA7A27CF89 -:10149000EF53DD8C5B562345DEAFF54E04F69FF02F -:1014A0009D88D838E30F6CDA40EA5731E1B2506ECC -:1014B0009BEF10F37A94E6B5227D17C7392B6A5B50 -:1014C000B64FE851856C3FE524F37BD175BDDF292C -:1014D00049F43B088DB528EF91E49EA96DE674F5BB -:1014E00050607CEBA9841D3AF6537D40C89D916DF8 -:1014F0001F38A2E319779BF04D357FEF2A3E1E7708 -:1015000037C9A5A8B88315BD5BFB927E68ED6BE774 -:10151000BEB4F635F70568BE99192F3D45EF9D50CD -:101520009CEB0FE93CE3B9A456F25B778F27D63EDC -:10153000887937250BBE11793689F5A6F8751C34E4 -:10154000E76DAD2762CADFEED61131E5EBBF6A1D4C -:101550001193BFC7AFC7A26FEBBB45DF5DDB8BF954 -:101560005F3CDE897B6D17C23B8BFF5483AF50DC41 -:101570009716FCC682B7354F0B6E4DDDC4E32AAB20 -:101580009F8F598FD236898C1E482D11EF5F298D80 -:101590005700ED87B2BA85EB75B71E39E5333EC704 -:1015A00059A6819FF4DEF875554123B7EBBAAE0812 -:1015B000F3E3159AE0C75DE3F823CC9FABD13E235C -:1015C0007DDC5A77079FC6F5137D4F4086C37C9319 -:1015D000EE124A645FF862F4E372BA31117D6EE58F -:1015E000BA39263F45BD3DA6FEE5396B62CAAFD08C -:1015F000EE8E29BFB2F0DE98FC77F59FC6E9F79B27 -:10160000E2F4FB2762CAC787DB58FF7EA3761AC7BE -:10161000A74F3C1A613DBCB556E5FCEEDA1C4E5FA7 -:10162000AED598FEF7D41672BAB756E7EFBFAB1D2A -:10163000CDE9EBB506A76DB55E4EE3F946595BB84B -:101640008CFCFBA33353F93C6AE350DFF525140708 -:10165000B92F5244F837F640E34B240AF2439FBEB9 -:1016600047F54EAB0E8E475CBB6BCC1F6EC17CC684 -:10167000EB322469E7D38B6430A2F0C7333D0C749E -:10168000FEED01F13E567CFD8525424F9E0B61F13A -:101690009EC06A3E0187B92EF5152393C54684EC9A -:1016A000F6B9E0673DD4B65ABC5333177428237B90 -:1016B000D607FE7B381E29F67D01AF3163DDAFB062 -:1016C0007C36DD3BC5F6DF7737F2BDF267F6A64F15 -:1016D0002EC5EFD77A25FE9D8F033BEFBAD5C5F611 -:1016E000AF75FFF41DDBC5E8130B4B047DB54B7ADA -:1016F0001BCD379026DE2F8A6F37CA5CE755C108AD -:10170000EB1F11D43F28DECCA2CB19EA2173FD9A3E -:101710002D750CD1C71ABEDF50D5A6E94184F798C4 -:1017200043822E46205DD0BE8D3D2AE86024D20142 -:10173000CB41D33EB4E800EDA997A8FDA983A03B17 -:10174000B17DDDC41FC9647F8DF92C14A4F4B2B33C -:10175000915DE7B07C5C9BF8DDA40BD993965EDAD3 -:10176000523B97F16867AD8FD3D6DA4A133FFD9CA1 -:101770007FB97635E7F7D40638DD5B5B6FE2670348 -:1017800097BF5EBB81F36FD4864C3CDDC2DF3592E0 -:1017900067089FBB4B4C39ED2A37ED0A917A8D359E -:1017A00076BEE78F9F889FCCA5B9127E544A21E26E -:1017B000DF75E9013BE5EB92690F68D601AE7F9DCD -:1017C0001B5A490E54E5BC28F4B0383C29CFBC86DE -:1017D000F164A619C77A20BDEE5607E2C389C6FB9D -:1017E000ECB1EF8D5E1C5E2C73AFE57B7DF17CF17F -:1017F000267A8F42EECA0F0174BDAC4CDCEFA238E2 -:10180000BDAFCAEF555B9B795F4CDC7FA9EEEBE681 -:1018100038DB7F9D9C514D39030BA87E87FD9D7C55 -:10182000703EBD8FD7052E71F6F7E141627F2DFB2B -:101830001BF54CF64BB58764B6BF2A731B3C6C7F17 -:101840008F8E78683F6FDA2103EB8B8A38EF5D4A21 -:101850001D6914D7D3BA7F1CCB99557B882F2D33A4 -:10186000CF7BE3CF6DABE9BC574A04EF30C7D52F30 -:1018700037CF7BE3D75D3DFE089FF7565FE05EE91B -:101880007B25B1BFE7137F7FB73B7CA17882E8F768 -:101890005C4F9EAD653BEDC8B63B1E0AF4FDD7ED2F -:1018A000DFADA5DECF4A441C35DF9BB3F6B3CEFCDB -:1018B0005DCEBA492EBEC7D03E42E5F76FDA25F1BC -:1018C000FE4EFB5F415FA3D1FB3AEACB24172ED338 -:1018D0001DCC574787C57B01E3E95E6282F702268C -:1018E0001C0A0553A8DDC100FBA3C6ECF305E9DE25 -:1018F000EDA8D70D99C8ABF465AF4C7860C9274BFC -:101900005E75D295796F8E6232F2BF3AFD698B4671 -:10191000E7907ED761B7BAA7F23B45A75B81A349A1 -:101920002DBFD8F083864CF712461CF20549DED64F -:101930009976E6A813013915BF4FF8CCCF76D018A9 -:10194000B453E552718FDA8882AFE5D7B2F89CC5FF -:10195000D7AC7B7BAAC3B785FCCFF04212BFFF1286 -:101960003FEF41436DD67BD6838612DF33EFE94DDF -:1019700091CFEE3A4776419B8817B8E46CFBE3645D -:10198000F7AC7AB607DF53BB907D50A39E4EA89F5D -:101990005A698D4D9CA30CABD08693BD497A2BD947 -:1019A000A1965D1A5FBFAC74D2D8A15934AFF16D66 -:1019B00006E1B76A3B2F7ED7ACFEF4BC76A1357E3C -:1019C000CD8E11EAC228BFD5EAA19219C7F2F5DE81 -:1019D000A19E10991B23C7BEED7A1FD26119E11792 -:1019E000D98624A7BE4F3B80EBB80E5A595FB9DEAB -:1019F000FC1D8B1B001CD1F7646F0483F9C39F741B -:101A00005F0DE1CD6288CCA77C8D14A97A1141F8D5 -:101A1000C9C4716AAED6555E5FAC7C4E36EFC1C6A6 -:101A2000C3FD4E136F2DFEDFEDFEC4F1FFF65295A0 -:101A3000EF41B73F3BCE46E738EDBF97F9FD54ACD9 -:101A4000C87C25384CDC3B1D3ECF7C8704F9CA009E -:101A5000BD2B5F393D7ECE64F61FD1C106C59F2ADE -:101A60007AE1F551F7CD82E6EFBA6CC194E22553E5 -:101A7000E78595E8F3B39F9AF32FBF7632903D74D4 -:101A8000952AECCEAB5C90798678E1D9D345B390BA -:101A9000415C45FAEC707E87FD618273C73B20C4D0 -:101AA0008F2EC17D7B5F9CF3C14D12FB4B9B9B44F2 -:101AB000BE78711AAFEBABEE23F6DCA304D7BFB848 -:101AC000491946F43D343D924774593CE6ED74099A -:101AD000E75562DEC7C269D743D4EF5BBD6BAEE3A7 -:101AE000F3A1C6369ADFD0F4B6F5F7917EF9AC0DC6 -:101AF000C86F7864CCED4B204A2E7B4A27FD8AEADA -:101B00006D97CC77EA7688DF33C016D9D1FEAD3F2A -:101B1000E915CF53BD56D3CF00AB9EE77BFC3354C2 -:101B2000B1073039CBFC3DC948FF44BF2F649D67E6 -:101B30000D25580AFF23BF2BB6DDF44FBE39F483C1 -:101B400039E45F84D6481ECDE34892B847ED29F5C5 -:101B5000FD8EF8CC50F2F3D23A7E26FC0347D2FC3D -:101B60007C8FE46DE4CF747EFC975A17A7EFA27DBB -:101B700044E9FFA07D44E9FB681F51FA21DA47944C -:101B80002E3E839DE2FECDD08DB799BF76B38EEE0B -:101B9000F94BC0D4EF13FF4ED35B26FC4B9A0EDDFE -:101BA000D983F0A059E6F8E8E26715D64F4FB68C16 -:101BB0008AF95D52A4D7C3B4BE92E63FFE84EE59C3 -:101BC000973429AAA4D1BDECD3D91C7F18373F8202 -:101BD000039D37447638C4EF2999F3DD9ED6B69E2F -:101BE000DA6F7F368F6648E738020F773813FEDEEC -:101BF000B0156FF7C450A17F7DCF19298B3E7F8C24 -:101C00008F4F633FF018C2E7823FD03881BD320C5E -:101C100060BC8CF56FF4D3C53D042B2DDEE1E038BC -:101C2000E5ED3BF65F7D25F6F77F00222F54BD00E2 -:101C3000800000001F8B080000000000000BCD7D1D -:101C40000B7854D5B5F09A39F34A32934CC2000957 -:101C5000123809AF00018664121212E024048A8A45 -:101C60007482D482A28EB462541E23D29ADED23FF2 -:101C700027244012830605CA558401C1C7FDFCAE66 -:101C8000D102175BF44E50A9F6B73422E2A354C731 -:101C900047552C4A8A62EBAD2DFF5A6B9F939933BF -:101CA0004C0222FC97F0E9CE3E7B9FFD58EFC73EE9 -:101CB0003BB3265E5E24C900A7E9670A80CBDB1729 -:101CC000A008604CE9D70FDCEFC1F2599BDB0400A0 -:101CD000F360DB3437F6BBCED1F1A21BEBD7BBDF11 -:101CE0009B968EF51B334D07A8BC49CE999E812546 -:101CF0004088DFFF515EC5810CACCDF456DB024E4F -:101D0000800A9000F2807F4EE37F531D29008E6889 -:101D10007D9ABB8FA1FEBDCCCB0CFD2F978718DA27 -:101D2000AFCC1B6D68D7E79DE92D34F41B97D19597 -:101D30001B74D23EBEBAA71CF70326080FA37DED85 -:101D4000FEF2EDDBB19C35719E8FF67F0CDAAE1999 -:101D50008D1BFDA4A479E3FDF4B245B165F503B88C -:101D6000857EC7F6E3103E5286ED926BF9813BF11A -:101D7000BDDB322590BC00359BADEF4762D6B10488 -:101D8000FC6961EC77DB0EE37380882DEC03B83DD2 -:101D9000E00CB62000173D81ED0E433B8FBB78AFC2 -:101DA000CD4DED4BC0126DCF01A83D9AF3E40B3140 -:101DB000E38DCBE8BCEF7E1C6FDC9E39EE065CDF6A -:101DC00093A55F0F90719FE55E97E723040D4C800C -:101DD00009A711E42039CD80FD4EBD2485245CD7B0 -:101DE00034E99BD4483E3EAF423C67E17B26F90F85 -:101DF00065D8AEBE2CC14E1CE76F75F2932F5869A3 -:101E00007CB8D19F1FA50B80950C5FBD7CAB0E7F6E -:101E10001D01F0C73A07977FAA7373F96E5D269785 -:101E2000EFD5C95C7E5097C7E5AC431068C7F1FE9B -:101E3000FCF7F1007D681C15A06FB41C67F39A07CE -:101E4000E03ABA7E2F85B6E37EBF289F9006B4CED7 -:101E50006F70FE620D0F4802D5448CA5F8DF8FB776 -:101E6000BD98E5E3E7AA0BA75AF27709141C77B9E6 -:101E7000D724C65DD4F1629627DA0ECBDF33F48720 -:101E800015A603867A638EB1DE5A7120F67D1D0E8B -:101E9000F1E52D9BEFB0055C58AE372921E799EDB0 -:101EA000FA7AA6ED4F524C389E659F3D64C7FD2DD2 -:101EB000712BA0607F0B80D29E7FE67B00F50CE744 -:101EC000791204DB138C5B47E312BDEF4F02E93C50 -:101ED000C67D0B6983D6A3FE973DB413DF7B2B4DE4 -:101EE000017FCC3C2DDAF89FA5B7FDE22BECF7D9AA -:101EF00033404FB00E73693D63777D6C3663392E86 -:101F000059D0C95877C49C81E5899A7F6C3CE261BD -:101F100032F59B26637B6ED71107A2FCBEF6AB366B -:101F200039106F6F9BCD00034020BE04FBE31854B3 -:101F30007FD07BD5DC46FCFDCAFD4961F379ECE737 -:101F400041E445A6A34AC1EF3710DD88791440511A -:101F5000B37415E8F32A241F68FF547FADDDFFE654 -:101F60007AA233E8DA48F2E13840B885D7AFA4C6A0 -:101F7000F2FFD2677FC2FCB9280BF99E04E066C16C -:101F8000BF0EFC773A97F83534DD89EBBD358CFC14 -:101F90000F179FFF9FF13AA37C3E22219F1FBA1289 -:101FA000EB4B9F91BC766C3EB96F98E0278DEF7537 -:101FB0003ED7E1B87493C47CA9D73FDF27CD08256D -:101FC00080F7368D2E86285DB369BE65CF5AA00591 -:101FD000D7B76CD288FEB1E3C7BFB7B44902396640 -:101FE000FC279FB3D710BFC8D0D5AF1AF967DCB3B1 -:101FF000A7322AF24559CFF868D3E44DD720FF180D -:1020000094D726FF9F7E8EF301E27127C2A7327319 -:102010006E36CD3FDB094ACB7806CB1C07CA89ABAD -:102020000588E0EA92EBB201E1B919D12521DDCDB5 -:1020300051AA5FBF0EF1F80373E02A92F3C7BC43C5 -:1020400078FC6B5CCBAD606672CD36E17873E7D817 -:102050000B693FB31A045DBF9EDE759C9EBF3E298F -:10206000C5D480EFBD6E8246C888EEE375AB3F9B5A -:10207000E80D37EEFE08F163524649A7537A9617EA -:1020800044C91FE97894A2F26F9AE454699E936E52 -:1020900033D3BD25ABD546EBBA154207149C7789DF -:1020A000376C23F9773BB82D5462D1D54D1F447F4F -:1020B000E5FFE8388DEF2FE9944226ECDF5ED70E7E -:1020C00016C4EFD3757BB91CFCCDE0C6CB101ECB7C -:1020D000C7DBBC2DA4B734FA32AB26389D405F9DD8 -:1020E000499F96683BAEBBC2E10C4BA9F4D87A3C41 -:1020F000761D8DD94ACA78DC8FBAA63C9DE99368D3 -:102100006170749FE36C004E92F33B5358CE1F7B7B -:10211000AED84C783AF63B6BC844F52D23DEB8D3E5 -:10212000C7752079732CC36BB6517B466E48C5F6D4 -:102130005BCCA0925C86ED426E3D3FE9AE77488E67 -:102140002DDFE932D94D828E653401A447D7BEF325 -:10215000EF38CEADC8AC766F546F2C9AF2E8C62734 -:10216000900E1699DBEE29C767A7203CD68DF0FCB0 -:102170008BA97D38E9ED8F1FB287CDF4DEC323B77D -:102180004B38FECBA98191B41FC854FAE7E0F39A0B -:10219000437DA105DF9FFAE83F0F92DEBCF5C9BE83 -:1021A000CC5F3ADD4F233EC4F59C403EA4F59CDC59 -:1021B0003784F92E8A7F0187C5280FC8246ADEB1CB -:1021C000CE4FF80C24CBFCDC02AA7219E17BEF4D58 -:1021D00040765381645288CEBB9A115EA633E9499A -:1021E000196FE6F7169951BF121D06E44282C7091E -:1021F000935CA0F105D07ADE7F6EE4F6167C7FAEAC -:10220000D63F4A774797FC86E86EB3DD6BC7251C3F -:102210004F32EA7DBD9C393E9DF9E516C79760298E -:102220008C3E5F52FBB5B19E0F0AC98D8206B9F094 -:102230000E2CEFD4E07EC548FFF7C7E3FBB7B5AF80 -:10224000DBF38A4CF36EFEE9DB34EF4B4E9E175EF8 -:1022500011F03B6112FAA55BBF3AFECAE3A3E4E1C9 -:10226000F5EACF3F7EE88DB1011CFFE3DDA38703D4 -:10227000D2DD02A9F3A307115F9FBB3ADFF93996BC -:102280004FBF74A81FC12F7EBD8B6ABF004B8C1C33 -:102290003A6E32F17E17D13EF0F96F0AFD3733BE48 -:1022A0002DA827106E0B5AC66C2779304DCA4F23C4 -:1022B000BBE9C431E3FAE2D7A98FAFAF4F1F5FEF9D -:1022C000B78CE08F709838CE2DF4ABADF373C2EFBE -:1022D000677B469B9015A3CF333AC7A6E747F1E447 -:1022E00057EAADD4EF1A12F5888AB90E81D7B935FD -:1022F000A650430EF7E3F6EBF039E1BDC2D3C0F5CB -:10230000394ED467D87F51E66F785D24E81CA8D792 -:102310007E00FA4FF5AA5F61BF3797A5B25C987B44 -:102320004B9B95ECDC6E79A6BE6D3E3DFADBCB3364 -:10233000849EECEE07CCC3A43F013767C1FA24ADFD -:102340006E2AF963C3AF483EDF99EA95D064841AD8 -:1023500019C2C4D7272144F05E6D0AB2BDE7203D03 -:1023600080658BC99B69C1523277F5019E27C47085 -:102370009A06010BD57F6B8A3400BEB7CA539949C0 -:10238000F4FF2638FD6417FD207DF51892A395EE25 -:102390009973E9F96C35D5DD82FB6DB4CA77E793A3 -:1023A000FDF303C94B76AF0E175D7FCCB578AD0456 -:1023B000DF7E41D9AB22FD16BEA2384C0C7F874A86 -:1023C000E3BE6109F6A575BDE55C3FC664263B2DFD -:1023D000E41A839B7DFBD07F14FD1EDFFF2328932F -:1023E000C81E98F35B07CBF19B40667EFF11282C3B -:1023F000C76F8600D76F8188F54B7CEFDDD2FFD9A0 -:10240000B91FA2FB7A77E257BBC9AE9F2BB5F7CDB8 -:10241000C176B512F248CFFCDAF17FB646701D4A9C -:10242000830592D0BEFA35D129D9EF475DA19DD859 -:10243000EFAEE42DA91D588F9884FDA556069FA4E4 -:10244000FEAA19FC0D58F64D0E3C4F7CF8CB14310A -:102450004EADC5E126F94806168DF3D13B2EA67781 -:10246000D2BB3761BD0CB145F03AD157D09BFA577A -:1024700060B97BC2EAED5468DC53B27727BD3AD528 -:10248000CCEFC36999D75116A75F7CA3CDFC3EFC66 -:1024900043E6F72775590CFAC537CE1C7C1AF73777 -:1024A000E5EF965EF5CECD05827F7C7DCCC144F60E -:1024B000E0FF68FC851092683D0D7B4DA116264219 -:1024C000611F94E9F40891D5446FE50041A27BD8DF -:1024D0008B7A4C9F2797F7FFB9EA233AC476B60761 -:1024E000DB9F2739690F0A3EC1FA54DA8F23085E51 -:1024F000B2D750218305EB49F8A290BB6E203BB6C2 -:10250000A502DAA93E092212E17B0A417A08F9C341 -:1025100032D3ED5450B8AED3F1F740E5F272087102 -:1025200079258485BE07B9F1299CFFAA4F40EC6745 -:102530005498E91D1D19F747686FC0E5B798C9EEB3 -:10254000F0FD30B1BF30A840870B22C473EE709904 -:102550000E814C31BF80879D9EFBA2F070C4C123C9 -:1025600089E0E18DC203E710F03803BE023E931408 -:10257000840FCAA7C9D025D13C8A66DF548297CB85 -:102580002AF073D90B5C5EA8F79C09979248C01299 -:10259000C84F009FA989E96684069F3F1600CB2F8C -:1025A0005DFE5C5B20F3735D0E217F66923D1A2F0A -:1025B0009FF4E7BE94CA2F64A487AA82AC7916D48C -:1025C00067BEC2CA3B8760FDEAA7F344BDACF257C1 -:1025D000B958FF41C128511F5759684578D59B46C6 -:1025E000CFABC2FA90806923F1E5F27AB4AB715FA8 -:1025F00081A47B8244C7A60C709BB03D505FE42D44 -:10260000C07A00E912106E7629A79EE06CFF397837 -:102610001B7015196981C905B8DEFCF99DAB053E33 -:102620002BFBCFC5FEC73BAD6CB7ACB10583842790 -:102630006477777D69747FC79FFE790D3D7F7A004F -:10264000B849BF80472EF4BBCE5C8FD9015C5F8C4C -:102650007283E21F38DF4C9A2F80EA49A6753D2528 -:102660008508FECBEBA7B13F7024CFFFFD82BE31C2 -:10267000E3E33EA4F134AFD073E0C92924B8958CCC -:10268000F45F4BFD4EB850BEA651BBC0434F6563CF -:10269000813297E68D7F6E4EF9E6862538CF52A4BB -:1026A0001192D38B0B0237D2B84BCD914185F86C88 -:1026B00065CA3B36A60B05E993E403F12BEDB7069B -:1026C000E991E87ABFE057E40077B7FD8AF8F5F8BA -:1026D000BB6E58E813224EC2FF15CF0D3E8F6635F4 -:1026E0008D7F3BAD63A9D4B590E8F2F3F4D76C7F4E -:1026F00066BE1C28E84E935B4B9FFB9AF9E7593363 -:102700000425CD3F8618BE5BFA5C9285FCC3A59F6D -:10271000422805DF2FDBF77803F93BA5E8FF939FFD -:10272000BC78D753CC6FFB485F22E896FEF7B3CF57 -:102730003F487C7A6512C7A126BD767408D94153FB -:102740008E461A106D70E2D9372E13F4AFFB257F39 -:10275000339D8F1E9F26ADB887F0BD0CF16FC7F972 -:10276000969982A26E75B855967BC24FAED1F6F19E -:1027700019746E9CCF72453D504AFBC99480E56345 -:1027800048F81332FE23FEBFFD686835AD13A46F11 -:102790006C246F4EA15F4CFBBAFDB178BFA3EB4038 -:1027A00029F9DDE417E33E17B71BDB97C6EA870478 -:1027B0007EF296022D1E960DD9B4AF5FA33FF4C1F1 -:1027C000309A777E1AD9871329AE90405EEAFE715F -:1027D00028B9F29102B697DB25E287324BE2FE0B75 -:1027E000F3855FACDBFFCB1E92D88F5BF6509F5119 -:1027F000EC276BFC0A612FF3EF93A45788CE022FCE -:1028000003D1C12DDA9E60731FA6B95B9B4CECC748 -:10281000D8A53BBCA4F7C73DD2FFB67F63BA4975C4 -:102820004326D527CC7DCCC3F655908435FA556C1C -:10283000673E99DE954BF33F992E838AF3352475D5 -:10284000E5929C559F757849EFC6AFFBED02E10F0D -:102850000C098FDF14F1083C139FE7BC54BA89F0D0 -:102860007C12F99CF0B7CC35BC3F38C96E989C19E6 -:10287000C1B241B3D3731E1B95361BE1E2A3F5C66B -:10288000D8D51DAF5E9342F6F26E8B3FC58DFD4EDF -:102890001ECE35F841F16551189153D84BFB1B33CF -:1028A000870412C05D2F7D9B2C0C2F9D6E7F5DA732 -:1028B000C00756C247B9D8876A77DB7D447FA1A994 -:1028C000E44F2EBB19DC2DD87BD9CB0F3738A8DECF -:1028D0000C4CCD27E97FD4FF137388ECF15FA68CF5 -:1028E000BDB71CEBBB8E59849FA22A87F263EC58BC -:1028F0007BA6196403BD764A8B491E13DD23BD26D2 -:10290000C9C920C7D0634A5E86A1EEF20E30BC9FD3 -:1029100056926B684F574619DA8BA13612C0F514E0 -:10292000654AEE10AEB8CF8C0243BB1DE93A4CEBC2 -:10293000FC52D85125F84FE8DB20DB4365118007B6 -:10294000900E261E37DA59259136F637930E5B0C1A -:102950007100FB59E250C9851A7F0D8481C45F481C -:10296000FF5E9263270F8BB893ACC17359B6D0CF7B -:10297000CB5E96D80E5C76CCCC7AE22478BBF14361 -:10298000F251E7BB78B8F7F51BE1DC7FAE11AE5929 -:1029900001235C2FAB31C2353B6884EBE05A235CEA -:1029A0007354231C87344D34F41FD65669A88FD82E -:1029B0007485A1FFC8D06C437DF463D71AFA8F6980 -:1029C0005F60681FB7F736437B3C5D8D0F2F33B4D4 -:1029D000DB538F305D1D40BA32A13E287CE9DFE237 -:1029E000E8C2C2702F1AE8F48662F0AFE23FC27FFD -:1029F00099969798006A03F1E385C2FF1584FF94C6 -:102A000028FE75B9DA139FEAF81D42FA9AE565794E -:102A100084F07EB22485E9E5E04B270F2B40F84F88 -:102A20008502DCEFAC29228E22C9C126A2934E700A -:102A3000B591FDB9C61264FF4545B3702729E53845 -:102A40007FF3FB25E86FC6ACB35A49024BCC7EC777 -:102A500087DB0DF5C297F61AFA1775860DF5F18723 -:102A600041227D55F0A6F7792A8B3E5438FC55FC5F -:102A700049F0792A4BBF0CDE45FA37DECFBD5AAD9F -:102A800097D2C8AFFF7BFBF368D6A07F364825BF3F -:102A9000377247AAD73400E191FC4E03F9DF807604 -:102AA000B4159511B80FB23E98EF10EFFF2D69F2F3 -:102AB0002AEA6F42FF9CF08E70C9237BAF1692BD4D -:102AC0000417B25BC80F832B843DBFDAA4B23D9AD2 -:102AD00084F628D9230D157EB697A74370203DBFF5 -:102AE000069455C4779219ED577CFE3F23028D85DD -:102AF0004562B1443F777D21B3FF3D85FC6906A661 -:102B000002A4F74ED0EFB43E78691EC5E34F902E75 -:102B1000C3F5B7B5BC304F253BC303EE08AE3B2031 -:102B200040069B0B03F7D0B8EF9BDCAB0BF1DD83CA -:102B300013FF3288EC917585C2EEB34B0829A4814E -:102B4000FEF315A0E78DD9CA7D8545D1384B4FF4EA -:102B5000A3C733F5F8E6AEBA309716B75722BA8B4B -:102B60008F3B46CCEEAAF1A4FF9699D8EFFC0B2D33 -:102B7000AE94E7496539EF804E7B3A2F99FDFFEB24 -:102B800035BC991D9DAB7E8EEFDD1014F6D60293F9 -:102B900097FDF5DB338F731CC52E99C047FE505A45 -:102BA000FE76117FD1E3259749DFC6CE3ADB7E6FF3 -:102BB000CF3C668857C1137D12C6D7A3E3ABACFFE9 -:102BC00062F6B9659347E835F2F3DF6FCEAE84D491 -:102BD00044F37CCEF1ABEB83AF1AF8E2C6DAB70C64 -:102BE0007C7093FA9EA13DE2E9B252BC32B2276BEF -:102BF0003AC5D73FDB6D2F263C20FE0F16C6C4EB2F -:102C000022CDA3AB60ECB9ECF72FBC8EA3759D8CE5 -:102C1000577DBFEFD4BDC9F5485D84CBF8FDEAF11F -:102C200011BD4471D844F6CC5D12CA0BF277495EEF -:102C30007862E405401ED9FF7749A3BC44EFB6FD96 -:102C4000C147A9BDABDEEEDEEEE3F808C74D6A91E1 -:102C50002EC86E00A7787F81CDC176E81D3EE12F9A -:102C60001EADF8EA06B25F7320D58B32107FC27FAB -:102C7000A2B8C97C531AEBFFD55907B8FE61338857 -:102C8000BC514DF821F25797A6A60ABB58C1FE5871 -:102C90003F9161E6FAA11181AF981FF3C39CDF5801 -:102CA000DA5FC4F3C01319447CF833D9FFB5E05799 -:102CB0007780DA6B32D0DF46FAFDC4AC8E35116B0B -:102CC000ED1A70AD05F1FE49B2FA395934637CFD55 -:102CD000AE253FF3139BE0DF49BB4ECF53113E1FA0 -:102CE0009A24F6CFD5674C1CAF0167C4568D7ED8A9 -:102CF000038303561F8EDF66457BD2299ECF1E13AA -:102D00008DCB9EB0624971D024513A7DC2EE75F9E7 -:102D1000449E532F4710CCB09CE4D3E57CEB708AE3 -:102D2000BF9DDC6C07925B38BF42FE96FAAC88E32D -:102D3000F7CBF02F028117F71A5CAF6788FC05F11B -:102D40009F4742BF16F721FB720CF167726053B1C7 -:102D5000FDFD3DF66D84BFEEF51E16F1B0CF9A472E -:102D600073BC5BA713D9A7C5BD7F0C20DA2FDB4648 -:102D7000ED8B5F7EFF1D8ACFFDA63030D487ED0B33 -:102D8000CC7231C9C9C5A91D1CA72BF6C93C2FAEF1 -:102D900097F78B72AB117D7158EC88705CEF6CF11A -:102DA000FB9EF6FFD9CD9D1BF3395E2D8F25B9A271 -:102DB000CF8BEB28A675E8FBD4D7111DA777FED1E2 -:102DC000E3D07AFDE387D60CD7F20837FA13E8E5AB -:102DD000AB743AB6268EFBD768F88CC74FC18860B3 -:102DE00088E3796E703760FD5A0D4E9FCDC3FD703C -:102DF0003C44194FF85D3CDBE92538EBE3F7CB8029 -:102E0000C053BDCC73C548FF1CA2BFDB82224FA0BC -:102E1000B723FD893867730AD3EBE2E7DE7AE7E789 -:102E200038CBAD8F8E2924FDA1BF1F0F6784EF70B3 -:102E30005ACF0249E4CF10BE37D1F8F1F981F385BA -:102E4000EB89EC4ED60B27B6FD2C44EB3B91056E7F -:102E500013F2E3E27DBF7DD33496E8C41996B084C3 -:102E60005DC6F857BC9E7243E03A92237694236481 -:102E7000DFD8F5F7065A0CEF55672A77F9D81F55B2 -:102E8000EE2679645785BF362450C1F5E556E1AF8B -:102E9000EDEA34CBC4DFBB2C10223DBEFCD50C9533 -:102EA000ECC7E56877B0A79317E4F54232FA41E939 -:102EB00009EC069357E6785C5A600DC14BFAD1D401 -:102EC000079FC889FAA3BABE2CD2F4BD927F6303D0 -:102ED0008DEFD3E281686772BCB314029A1DA1C55D -:102EE000E19A0F701C4297DB3698EBA0F8CF9ABEA0 -:102EF0000B1CE41FCA382CC7D73CB3D3A0173B72B6 -:102F0000551D4ADA11D1BAB5073F5E3F1FC06BECC1 -:102F100047DB0512D6D07AD5814823FEDA3AEB7723 -:102F20005D2F60D932E691C84A6AFBE6B44476A4C4 -:102F300043B303B8E847EB14EFD906AEBEC384FA37 -:102F400033D96B81F763F4A00339FFFD3C6D5EB2AA -:102F50000732BBDBFF4078EB691F17AB24F8BC6F6F -:102F6000EDA5DDE6AD49240F12C28BC8C433FD18B0 -:102F7000D16332C4EC9BED9E98BA14072F89CAEE38 -:102F800076E57482FCE577DDD7AABAF0AB1F1AECC0 -:102F90008110AFDF6AF18317E9C9E6C176C3390C46 -:102FA00055CB7F220117C7ECEF1CF64576B955DBF0 -:102FB00097F522EF8BC6F5F7BBA4D7A75EE2EB0B24 -:102FC0005FE2F885EA4B1B7E4AF5A50D3FF5125FDF -:102FD0005FF812C72FCCBEB4D7A7CCBEB4F1AB5E9E -:102FE000E2EB0B5FE2F885AB2F6DF829575FDAF063 -:102FF000532FF1F5852F6DFCAA6C073ACB81CFCD0D -:10300000A6379A4374CE46AA0A73DE3857058E4710 -:10301000A73603E72BB67B851FA5C7E947D2103239 -:10302000FA2D567716D9D1DB1BEFABFC318E732A04 -:1030300013174FF9FCEC230A8DB36D1A70FEC2D939 -:10304000F8D1518A7FE540D81BCEA1B89A04E11887 -:10305000BBF4FA600A8463FC896AA58FA15ED43947 -:10306000C0D0FF964D430CED37B78D36B4FFA8A9FD -:10307000D050BF492D33F4B7434E4B1EE55D1B2D99 -:103080005ECA8359686FA567C20D76D8F83D05FF03 -:10309000911F9383167DF7B8B88F74D56618D7192A -:1030A000D77EB67C407C3E614EB1964FE8FE7E41B5 -:1030B000BC0F6E4FC2B8A79E4FD0F139DC92C4F856 -:1030C0005AA78A7CD39A69C28F9C1A729B286FA9CF -:1030D000E36FB44672FABEB7D519FDC9F446772539 -:1030E000FBA34DC0F9DCDC2A7348C9A138C1C04A32 -:1030F00007E239B443D04708047D841A81F385A1DF -:10310000AADC95D47E2A047C0A46A78FD1550B678A -:1031100052DCB53EBB5F16C51972AA043D2CDD6BAF -:10312000A4034AE7D256D30F4BBCFEF4FA8C02CA72 -:10313000E79D819727049CF5F3E7E97170CFDB6188 -:10314000C44B3CDEBE2D5ED614C77F57F2EDF06255 -:103150009B2177A4519C540599E2322F660F373397 -:103160001C9ABC8C9F19D88DF830A70938DF134FF3 -:103170008FAD7510AE8AE1DF1C6F5821FC4C93F2C5 -:103180002B99CFF0DDFEC0A744195FDB9A44FE16F1 -:10319000CB641A1FF6CA0328AE105267F3BAB737CA -:1031A000DB92E93CDF57F566A0F3F2DB73E40194B0 -:1031B00017DBFE8C696EECF920A40ABB3993F7612A -:1031C0003797706911A5A2956011ED6189EA835660 -:1031D00098E3F0A94AD49E3E2339EEB962A2FE5B81 -:1031E0008A73193E694A86015FD61223BF23180FDE -:1031F000E5A37C1C4CBFCB4457824E42AF4BA195FC -:103200001C5FE932D510DD68E72DD257CD06CA47DD -:10321000D567FF742ECBAF7A1BC31D5608BAD0F307 -:1032200082D6264187F1F4E3F21AE9C72A0D3489E0 -:10323000FC96E01F7D1DDB146DDE2C0954967BB6D9 -:1032400001C467D6B8F1EC243C49DE78045F3A61EA -:1032500036D07BCE123BE7B1413ACAF8B74E00E810 -:1032600013734E217EBD675DE777A4F30FBF239DE7 -:10327000EBF267AD57933F45E25CE429A46B8A1FEC -:103280004DADEA04FEFE0ADC26A247A4835959C5C7 -:103290007CF4817F76911CB213BCAAD3A8DDD5A99A -:1032A0004C25FA9D2EBDA2B8709CB587059DA37EC6 -:1032B0007989EAADCD16A0732628674C3FA2794BD9 -:1032C000EDEE952479A481E369DD853E943B1447B6 -:1032D0007CC5282F8A3A8D70CB8D97EB3DC0B127E6 -:1032E0003D110F47D7040D8EC508C721DF1E8E364E -:1032F000AFD0C3E92542CEBE98FD537ED57D589C04 -:10330000AB495780E1FA852AF4F274E97898E4CB66 -:103310003A05E50BB6CFD0DADD25429EE870CED572 -:10332000E0ACCB9375F32183F8DE4DF2C44970FD18 -:1033300088F5765B9180334084F39FA98AE09335CA -:1033400056F0529CB6ADD4E9A57861AEA2C1B7499A -:103350008397094C04DF78BA9421A68EEB4B8DAB92 -:103360007F5BF8964ED0F4643F283E1FF8AE4B4981 -:1033700015FC3654C0C7EA8CF0B9E6A61C8B77253D -:10338000F275470EC21BDB9B5E17F0FEA5D67FD5FC -:1033900018E07A53DFD5990CAF9C859944CF4DD670 -:1033A0003695F2584D3AFD69E7C25C9A9C9886FCC6 -:1033B000BD00DF5F8DF289F290A92501078DD794BA -:1033C0006F0189F7BFD99B68FF0E9FCD20072FABF8 -:1033D00031C235250E8E49DF91FF7F3CE1BBF1FF05 -:1033E00076FA15FBAD1906D0C979C89083E0642B35 -:1033F00099984C74D4D2BA9DEB32849A7271FF0FB3 -:103400003B85FDD5D23ABBD7F351214D2E6CA97324 -:1034100070795F9D9BCBB6BA4C2EEFA993D97E698C -:10342000ADCBE3B2A5CECB65535D0997ABEA14EE05 -:1034300027ADCDA860395C051CCF5E99F239E7DF76 -:10344000E3E7CB518D7A6C706DB201EE7D6618F5B5 -:1034500055BA62D457748E29B6DDE51D65684FC92B -:103460002B30D493E48986FE5326047E3981E48090 -:10347000A7324E0F223F8E899EB36B6915DF4BE951 -:10348000F0D3F59353E3F33556EF00CA3B395B05B0 -:103490009F366B765E13C111CB6405F8DC8CEDB002 -:1034A000E40D01F1FF6AA6F38771EEFE488B1DD98A -:1034B000D7286427B4C8C28EB78238F76BCBF4879D -:1034C0006BF07912EA2FCAEBDAE6A6B05C78D8E3A3 -:1034D000F4D239DB96D6656E5E8F579CA771E3BF39 -:1034E000447980F8F3358EA1C67339D6B39C6FFC4E -:1034F000754FF4DA9491508E9C2167BBF32FEF6BDC -:103500007429F22FF778043CED3DC8A3D6387BD957 -:10351000A9E55F60A02F61FFA83D25F20BAD717199 -:103520007BF4C312E66FDE9A2071FF3F4F9085BF98 -:10353000660903C96B9717DF8FF53B14F17DE8B976 -:10354000CE8F3F3E4F8C7C0A2407FE3C019F2B4FC1 -:10355000083B254916DFA1D84051583E81C887D085 -:10356000591FD237A95ABEA75BCE908888A13BE7E6 -:1035700019FEAEC88BD06716443F96E8FB17C4BF50 -:10358000FDB66523F9C3C37A69A7FC5002B9E02AE6 -:10359000D1BF1F832E4F3180EEBA23FC5C2589E119 -:1035A000172678359AD6CDC8C5E7A95E8B173100A6 -:1035B0001525F25E3A5FB14A4965FDBEAA446E2701 -:1035C000FEF942717A091FADF955ACAC93867DC8FE -:1035D000A2B7B1C4C676BA8E87246D5E444F679594 -:1035E0000E67ECEFCC9B11ADE37FCD6336725EAF1F -:1035F000E5AA4738DFD732EB3F38DFB73A6B7A1EA0 -:10360000C9BDA492E9C7F82097861F660DD2237919 -:10361000C6FCDEE9D3A2CE70A0F8849607048F31F1 -:10362000CF6791FD86F92F349E60A0D0436051F89A -:103630007B8333E95BF0B5DEAF673E50F5EF4E5765 -:10364000D2F9E0268F90A34DE07D3340F55724AFAB -:103650002AD3F38237E9BCE9EA8116C6CBEACCD992 -:103660004DC28E177E53936725E76DE3F5369DD7E0 -:103670008C95DB745E3356BE37C9B37BD5CB59010D -:10368000739CDE37BE9F1D34EA1FFDBDA4CC2B5FAB -:10369000AB8A392FD56CF13B485EACF2DC678AD53A -:1036A000730F2881052531E793AC99B3F83D7BB6BC -:1036B0002FE1BAAE50948544DFB8FF5EED81F59AF4 -:1036C0005CDCA8E997B3ED7393D6FF01ADFF66D23A -:1036D000EB23A2F8193EF4F26496CFEB441C8379F5 -:1036E00020665EA524B082D615C5AB390A17A4D3CF -:1036F000E1F957B0DDD1B06E7632E169E7FADED795 -:10370000A3E7D5F57E7A1E353EBF6EF3980DF0DF48 -:10371000A3C985175C0B2B1F40D0EC6C13F4D4B0FD -:103720004EE891E14F887D9C4987C6F5EE6CEBDD54 -:103730000E8AEF4F91C56E3AE17A465C7D405CFFA0 -:10374000DCB8F65171ED0571F58971FD2BE3EA578F -:10375000C4F59F1D57BF36AEFF82B8F6DBE2DA979D -:10376000C5D5FFCD884FDFB56989E0188F3FBDDF34 -:10377000B9E2EF5D5FC57EA2A3E13083E945A7B75B -:1037800073C543D4DEF5339DD94A46B17CDF81F65B -:1037900015D9433BDB2ADDE27C4760E56E8D3E4870 -:1037A0003F58368879D0CE4AE6F89CD36390236799 -:1037B000C3B709328CEDB17668EE85C7F7D9E93326 -:1037C000A4D917BDAF5BE7E32913FC27490E414895 -:1037D000F899BA5DBB4D15FCB34D5D50B99EE46DD3 -:1037E0009359C49FB5FB50E86E1D11270F684A38E6 -:1037F000C2F18426CD4F68D3E4C95A4D9EDCADF9A1 -:10380000094943839B28EE9B7C988FE740B3AFE048 -:10381000AF0B103FF797166FA3EFC7EE1E53F2F8EA -:10382000C35877FD5D827021DAE9635B14B259DA1F -:10383000948C243A4F946272B4939FB8AAB0CD3F4F -:1038400014FBADDD7FACFD79C4B39C69F3A2CE0758 -:10385000D9D265227A837C2F7F9786EB54C9C6B272 -:103860009677D5253A77BAF60AB7898CB0F419B2AB -:1038700099CE11F79910E85B8AF018DC046605EB25 -:10388000196A98CFE25C532A0BFFEA196428DE6FAD -:103890005716C1EBAB66DB7EAAF68C0F90B438DD11 -:1038A0007995FA38698234E887E38EB245ABAB8FFD -:1038B0006CA6F3D04E49D4A73CF3F8FC95F9D1FAA5 -:1038C00098671E1FB812DB5B0B0799489EA67B52B8 -:1038D00013DE137375A9909FDB9B170E4EE48FE9DF -:1038E000A53C13383021E76B25D1D4042C876AA579 -:1038F000AC3DCF14F52B35B8C9B55ABB4794177AF0 -:103900009EF8F1E794BA753B7B809F8D6CC877F683 -:1039100033D88B5797F6622FA279CCF1DAAD56796E -:10392000009D23DCDA6C03BAFF616B3688EF905799 -:10393000D9F8DC2858DC03AE7145D71D5AD56F1E67 -:10394000D14DC80486386EA6065FFB4493768EF28E -:103950009B307DC7B755CBF36C8588DB9D1F8BE70C -:103960005FCD27BCEA78DE57FAAFCD449F1DD90B57 -:103970002B37E27BEB1ACD1C3759D798CB744EE32B -:10398000907D746AC52133D9ADF9D06E263B7F1482 -:103990007D793D84AE400A70D9AEC9E7FFD4FCF80A -:1039A00061A0F0F341D0C5C0F9B438F01382CB1058 -:1039B000126D12F18FDBE4C07996EC4BAF48A4B7DF -:1039C000EB4AF5EF7AA1C652ACF91732C3B78EF8BD -:1039D000281EBE74429FE38E8ABF9EDA9D7B5F0DD8 -:1039E0005F86D5DD6F18E993F0363B46CF6CD4E0A7 -:1039F000E7F6FA15C2E1B5C581167A7FC9A6BF1EE2 -:103A0000207354565533BDFF14E11D9F2F0C07A79B -:103A1000D33063BCE14AEA3FBA76DB7E8AA7E5058C -:103A2000EFA8EC8FEB1BAE54577A888694C0FD3418 -:103A3000CED0CE48850BEBCE4DAF86B3783D6379C3 -:103A4000BC5C7D3D480FD54C476E11C7D7F04BF895 -:103A5000A773CB0B370BF8607B16EFCFE2CE8A5DF6 -:103A6000FFB669FDF8BB8578BA68D5E0F758148EC3 -:103A70006035FA358F2582A34EA73A3C6E78A26B4B -:103A800015E53AE7873A5F2439E8DFE49EC6F2B0ED -:103A900038F024BDEF6BF337701E7057275D47D4A5 -:103AA0000D1FA7D249D7BB603FE569C2FBD615EF12 -:103AB0005772BC782F88B8589C3ED44BAB129F6786 -:103AC00010F7E58CDB6BB493915E958D9E587A353B -:103AD00073BE33A4E9935013D22FCDB742D06F48B1 -:103AE0005DE64E44678F687A658746B7FAF3A13D75 -:103AF0009CBB3C54DAED27664A46781EEA8DEFD32C -:103B0000C0CBFC807C7084FA65101F607DF00A37A2 -:103B1000D3A7CE074BF6FEF500DD67E3F4C905B188 -:103B2000F7D745343C227DBE43EF2FD9D475807C36 -:103B3000C5C12B047D7E4C77871545E90CFDC7F781 -:103B4000A89F4E3FF1FB78571B4F2EF67F4C785CB9 -:103B5000B829C8E321FF1C2BE5713AC349CC724A4E -:103B600025ED676B1BB8693FF65F1474905C3855A0 -:103B70006B62B8DE981F5E65C6F2FAA160A5EB869F -:103B8000AA33916C72298F6BCCFF0D6B33E20FE976 -:103B9000E76F344F91276013C1EBA08DE5690F7477 -:103BA00011D57BAA0EFF157172D73CB1177A3ED79B -:103BB00071D7162B8E8945DF621DE7D84F8F379D51 -:103BC000193F1DC5FE434BD36CFD9CF00CBA8F67AB -:103BD0003BC54F11AEAB9A7AB7572F58FCB4F9A436 -:103BE000889FAE008E03AD4C196B4A44379740FC5A -:103BF00074CAC444F1D3C87B063B735593900B3A07 -:103C0000FC86578D4C16792948A57C891E1FD3F751 -:103C100075B7664F3669706B21B8313C05DCDA0840 -:103C20006E0C4F1D6E33843F425F8853BCD66316C3 -:103C300079B1910B3651BEE054A6C893D767DB44E7 -:103C40007B8EC82F9C411F9931F634F2C19A667160 -:103C50009F08BECF79B517B30F3886509E33D3CCAB -:103C600071DAED9EFB6AB6733D99F9CF0A6A5B1E65 -:103C7000CE3BFCC3B9EA027A5E62E773F27A3EA7F2 -:103C8000A5AFC8E7B8F2B47C4EDC7C76B8A9B28D9B -:103C9000E6CB137E4B8F74ECD3F2115A1E2823DF30 -:103CA00098AF70C4E52BE2F3956B9A17ECDF2EE228 -:103CB0002B2C9F87FF7824FB63F1F3B8671AFDB7BD -:103CC0003523753FEA1147A2EF1852AB8CF4D8A206 -:103CD000E1BBA1AFC8479C6D7C284F36F8552D79C4 -:103CE000E71647D0FB911FEA4ED03FDE0F3D1FFF86 -:103CF000D6CDE31BEF074CE0DF6E99C8F11441DF2E -:103D00006B9AC5FEBBE3699A5FA59F3FD2C7B16AB4 -:103D10007E1CD773A2724ACF870D75DB985E876AC7 -:103D2000F74535FC7B4A68650EE5D76675513E72EE -:103D3000E80E89F3EE439D7ECE43746C98CEF9F184 -:103D4000BEC981A727C6C49F76B87E9AC9F9022D3D -:103D5000DECFF7E6A0DE53D715762A64EF8E04BED9 -:103D60006727392E1F107F3F4E7C7D4E99D0C39917 -:103D7000D741C27B4F3E9F28DACFF4DFAF6038A136 -:103D8000BF9B2CE4ADA2D7FFBFE4A976B61DE2EF3E -:103D90007D4EF94093B3FF0997A29C3D5112389E86 -:103DA00050CE5ABA58CE8627289F919E5C4E177DDA -:103DB000101E6E4C7C3F8F5C76A9E2E16981877CA6 -:103DC0001D0FF75C92F942C4437659223CA05F452F -:103DD000F06AF32983A85D29510653D98D8F1F26D8 -:103DE000E68B5965C2EEBB58F858A7E1E35EC207FF -:103DF000C769642D4E93C7CF9B357CAC39031FEF49 -:103E00000B7C94E8F878EEBCF09151956168779757 -:103E10001BF191EACB35D49DF9467C240F2D308CD3 -:103E2000B7BC4C16F7240D9C68E877263E8CFEC084 -:103E30009DF45E2FF6E8C04067057D4B34606E7BD5 -:103E400007C9E64C7F5B0595FA3E37C7F9737AB927 -:103E50005CC35FE6D4C4F85DA0F15BC644E526030D -:103E60003D7C2F317FD668FD979728B794C5F2F334 -:103E70009589FB2FD1FADF3641591CDB1F7FD64BCA -:103E800031F6784FFB0E242BCBCB78FD224FB6A317 -:103E90003E95F3663B92E476CA57ABF54EC3BD75CB -:103EA00083E937AC67FEE89B0E95CED9D13D4168DA -:103EB000596DBBA35FEE1A6CDA96317C25C1B1A9AE -:103EC0006C88B8BF7591FF6DCAEF28EA09ED1CD266 -:103ED0007CBEEFC814EE63A27BB2C09D714EF92385 -:103EE0009467E25EB7C120BE238620EB41C90FE98B -:103EF000F4DDB205FC225F4EFDC5F785BCF9140860 -:103F000073DD0511AEA7697EDE0365393C6E3AC8E4 -:103F1000260124AF89E4A8CEA70E4F90E9DF53EB2A -:103F200036AD245FCE0250467EA073207FCF0B9526 -:103F3000A0523ECB040EB6334DEB0F7CCD793AFD4B -:103F4000FBC397FB88EF0FCF717FE7DAAF91EEE508 -:103F5000F344EFE56BD4EC01FD5E3EB532C8DF976C -:103F6000AB2BEDEE06CF99DF973F3A31B08BF0FDEA -:103F7000B7A4412191640E4E98EDBAA0E3872FF2C9 -:103F8000F8AF5CE4F1DFEC6DFCBBE9D752CAEBF9AA -:103F90008F123F37B88AD9EED4CB78BC5DA12811F7 -:103FA000EA27395E1BF0619FA83DE73C6A627FA863 -:103FB000C124CE9FA9EF99D8EE827C41074E19F219 -:103FC00072C645C7717A838345DC49C45FEAFF74D2 -:103FD000D708B2BF7F99322B9286E31D7C55D87FDC -:103FE00096A991CD74BF73FF349B773BF2DD3DDA28 -:103FF0007AEDA513EEBD137FBD798A90172E8BF74E -:10400000F2023EB7343342F6A3ABD82253AEC01906 -:1040100097D76CB5B42553BCB275C77D15A3B0FB5B -:1040200063752FB91B137CEFE9D4F29A23A5C472F0 -:10403000F09F939244DCCB67BC4FD85AAE9D2B497E -:104040008554B2232DFF52D2129D07D04B7DFE2204 -:104050004FA48ABEBF8ED0256E88E7A292EAA464E0 -:104060000F9F8BE824F8567AC30EB27F1F5F10BCF7 -:1040700035F6FBD3D61270911DEF9B22CEC36E5046 -:104080002417DDAFF160C4C2F78E3FB8E8E9E6144B -:10409000ACEF3D6A76133C5AFDEF3993B1FE388E92 -:1040A0004BF2EEE00E71CE529D0FA16108BF56F2A9 -:1040B0002AB1BE5B11E7B2D9212BD6AEEA43F8FF95 -:1040C00075725F016F0856D3BD9DEB5226F37D9646 -:1040D000D973443C78BA74B483DE7FB0C4CEF81B85 -:1040E000A29DD331A9D57C9F65DFF9C6733A0F2E07 -:1040F000EF5409BFEE52BB5BE5F3974ED7587CDF18 -:10410000F5A8192456715D3CF974C929D6E5157EC8 -:10411000EEE37258A5FB8EFBE27BF56EBE35D170E7 -:104120001E68F726E19FA68D777A91D271BD71E75F -:1041300085F475B5E1BAE8DE63D7508E4764CC31BB -:10414000AE2F2DCE6F70C6D5A79677DFE3339CF0E8 -:10415000FD85FFA785AF71AB574EE47FB6D64167AB -:1041600055CCB904670F71C09AC982AE6D592F380A -:10417000C84EF9C27FC4433878E59F073EBC97CA52 -:104180007FFD6ED75284CFEFBF7E73C793B4BFDA83 -:10419000BB0F11BDEAFE189FC1C4F5BC586D63B8D2 -:1041A000F96768E7397D1D2F587DDCCEF9A5B5FB91 -:1041B00093B87D64398492B07DA445C9BA99E8AEBC -:1041C00053F2D6CB3488388FA8E37FED0D7E138C65 -:1041D000213CFA25BA0F639A76BE76C3229009FF76 -:1041E000B645ED7C5EDDB75C9C57F729D5497CDE92 -:1041F000748E99CF87D4575F73F930ACEFBA5CDC1B -:104200004F3563B9328FE75704BDA475169B9713DA -:104210005D6689FB9AF4F3A645D0C5DF7F8CF4B6C2 -:1042200077D848DECC4700D3FA5A357C69718322AF -:104230005FA74AF6A4CB6BC463461CDEE2F1BA4228 -:10424000C7E34818497894A12D99F4E14300ED742F -:10425000AFC086E54FCFA3F36C5FA8690CAF9EF8A3 -:10426000F91DB4579511740F8B83CB4EB457A9DC4D -:1042700085F62A95AE60C575CB71DD7BDE38F8D248 -:104280000F71BA594AF5957444AB48CB7B81BA7427 -:104290005025AEFF06E25E51DF4289C4777D92A1D0 -:1042A000BED66389FE3D00FCD595A5FF7D80D35B1E -:1042B00094A108964C8B968F11F559E487C4B4EFFE -:1042C0009E69EC5FB63F66FC81B8DEC5366E0FEDC9 -:1042D0005BBA45B5C4B43F87F572805735FBF1FA38 -:1042E0009D66FFF604F2EDDD7261475AFE052AC9AC -:1042F000B52FD14E23FF5E322B2CDF21D72227BAD8 -:10430000570F00E561AC5F2E1BE5EBE51A5F58FC2B -:1043100015A0E5C7E01B3DFE803F7BFE388BEF63B9 -:104320005A35C4C2F70FA13EF0F696AFB3782C9F72 -:10433000C6DEDBF5AC2EBF87C1309AFF4B28FF43AA -:1043400005F341CCBD0DC4F76DCF5FB614E7F11D89 -:104350004DE638AAE45A9FC2F731D535B13C7F40CB -:1043600009FCB63CE67C4963FAC242922FFA3999BD -:10437000E8BD47D798BFCDBDF71DD50780F4C297DC -:10438000485AF65EE8B0B16EEF115AC7EABA762E17 -:104390009D6E85858DDD12E4B8CF154AE04FB43EA1 -:1043A0007B26B6C7F089D58DEF19FC0EE37D9CB254 -:1043B0003BE224B86F28F9C049F3B71E167CBDE173 -:1043C000F0EC24E2BB56EFA124E29B2FE8E2C7EF1A -:1043D000C0273EE5559661BBDF48BD9EE8674F4369 -:1043E0001ADB150797DF7F2DF1CF8DBFF801C3BB17 -:1043F0009B6FE0E14195CE18BE818799AEBBF9462F -:10440000ABF7CC377F67BEDADDCD37A2EECB074303 -:10441000FDE04C63FF6EBEA0F1912F1EAFB073BBE9 -:104420007DD2C35BD418BE3A49F558BEF909F24DA6 -:1044300002B93F7D9246DF17986F522E32DF0C9DF6 -:10444000A4C9CFEFCE3763275D14BED9633A1FBE30 -:10445000B9EC4CBEA99AD4F7DBF34DAB3BCCE7E902 -:104460005AE79813FE7D900F347939757EA0B28D8E -:10447000EC1A45DCDF374D9A99E5F3109F497487B4 -:1044800034EA4FA1CF0F5EDFFD7D06EB67FDFEF541 -:10449000F58450B293160BBAE9AC1371DF6952F987 -:1044A000B4C5A477E93B024A3553F694EC02D4FB39 -:1044B00032D985D05EE1C179365499A04DA62D0739 -:1044C000AB87F1F861B6CF8668717FA7942FBE677E -:1044D0009A29FEEE85FE5D4CB562BC5FB6FF59ECD5 -:1044E000265C770AF931EE12F17750164D8AD7BF64 -:1044F0006887E0FA3A07DA984E362857F71A273ACB -:10450000E35CB52F98302FF9D6249376CFBEF233E3 -:10451000A2B3DD6F6C49A673127B24E0F339F383F9 -:104520004FCD23BE73A942DEB4AEF833A52361D7C5 -:10453000B41F1AF5347C6AD4D3F0A9514F6BF51E21 -:10454000E58D7AC2A8A7B57AB79ED6EADD7A5AABCE -:1045500047E5CDA7063DBD61D2A70679F31ED5CFAD -:10456000414F1F9E7471F4F4A88B2C6F9EBE70F2A5 -:1045700066DFA4BE1743DE1C392F79937DA6BC39B4 -:10458000743EF2C6B5B943A5F4CCC21EF8A056C31A -:10459000FB5B65CADB343E949C5BBC269EBE3AAA9C -:1045A00017AEA6BF2BF3A557F87F3DBDEFAAFDD5EB -:1045B00091C6183FDC65E914DF23D4EEE1E7B76C60 -:1045C0007E95E3B1675D2F5D105A74A65E45BBC84A -:1045D000C1F4EB35732EFC7CD7D13A47F0DB95CF95 -:1045E000DEC1FC945C6E9C4FB77F3BAA6D669EAFAC -:1045F00044C8E99EECA19EE6FDA05C16F7FFC5CD80 -:104600001F4FBF489FE9938B981E2D742FF8179D5D -:10461000C07FA7EABF4E6EFCBF8A7C49E9C51193F3 -:10462000CF834EA76BF84CB06FEFC5DDF705E3CF36 -:10463000E993CFC38E3E4CFBEE9B70DFDF67385EA5 -:10464000B47D5F30FFE1E6F3C1F7BBE5DDFBE6EFEC -:104650005132B47D6FF8E735EF515C63C3BFAE7D77 -:104660008AE21AF77D9DB78DE21AFABD726910FDD4 -:1046700091F5EF8F102E2EBFF89E24634ECC774518 -:10468000C0FE7DF4BB13B2377CDDEDFF2BF7CA9182 -:104690007DD2DBBD72AD36635C4F2FAF2A17F64A71 -:1046A000AB691DC72336A05F558F78EB9823E211C5 -:1046B000AD68A7B0DC9953D0AB7DB4AB4EE1B85335 -:1046C0006B9D9FCB7BEB6670B9EBB5256524777D41 -:1046D000AF2D62BDE7F3FAAF7B1881E4AEF8D049A5 -:1046E000CFEFF5E8FE90B05FD2C87EC1FAC393D792 -:1046F0006F8D8D0B8CFAEFE15BD481D178555B66C1 -:104700008CDD23C7FA51A012B944FD28AC1BEC9AEA -:1047100011EC47ED26BB06EBED934718EC1A7D9E96 -:10472000B566A821BB66ED0EF38C4476CDACF2C421 -:104730007E14D6390FE27039F8FB7F49FBFB5F51DD -:104740007EE9DDAEC99D7271ED9ADF4FBE30F18713 -:104750006E3ED6EC990714E50D4DAE7C47F9B1D10C -:104760004CF1E36F2B3F4692FCC837C88FCFCE4742 -:104770007ECC2A771BE2A20765B5CF58B2D37798D3 -:10478000A15ED6F42FD63BD1AF31219C7E5221B110 -:104790009FB3C10BFCF7FDA64BF35F267AD8BDC8CB -:1047A000CCDFBB3FA88873220FCD11E7A91E5E5E48 -:1047B000309B3E235A9772C3DD4914D72E17F70456 -:1047C0004C97CA39CEFDE00C61E7643BDB2FA7FDB7 -:1047D0001FACB000D1D5D9E2DC146EE778B5E6475E -:1047E00081B499FD0ED70F2D6E3AAF1A1FBF769682 -:1047F0007CCCDFCD83F40A7FDF7DB6F8F5B78D5B27 -:104800000F98F29DE3D6CC8F35CF0DBF41759E49F1 -:104810009F4726CBE25C620F7A2C9E9F3BAAA7A7FC -:10482000457A3917E524FB29E61E59FD7BD659E563 -:10483000621E27D94F8551BAE8A82EEEF55EDA94AC -:10484000DA678EC4E685522CED3C5E4AED3E7EBEB4 -:104850009ECE2F90CCB27859AE3E5E89F239C178A7 -:10486000FBEA8287092EBFAEAB3D4C71EA49964EFA -:1048700089FE9EEBDE3A95EB7BEA9AB8DC55D7C60B -:10488000FDD6D76DE2F2BEBA103FBFB7EE31AEDF54 -:104890005DD7CEF5C773C53C132D211E6752178E09 -:1048A0001FC30F659FE03C31782E8DA886F6096FF7 -:1048B0003619DA8B3ADB0CF5BEFE4D86FE7D66843A -:1048C0000CED6F950502538AE85CC363867ECEFCCF -:1048D0007643FD5CFD850BDD6F654AAAE51FC8AF19 -:1048E0008302484F4867E9B5B2CA79F31AC197FD08 -:1048F0006BBD61AA6F71D998BF75BAE433CB26B18D -:104900007E53CC3DB51D2E717EB2A1AF88A734FC7D -:104910004CD4B76489F391C3AB447EA461A0B8972B -:1049200044CFC36F7169F793F8C43D1A83F223FC37 -:10493000DDED20EDEFC139CB45FECC0D6ECECF378E -:10494000D481F67D6284F31D1960F68AFBD5159932 -:10495000FF9E920542F5385F43BE5BBD85E44C3057 -:10496000D56BF6F29F960D99298F48E2899330ED29 -:104970009ADED1F2F2491F009F3BE886CFE7E27B47 -:1049800084DA2EBEB7A97F6D17E7E3B6FC42DC637D -:10499000130FD78E5F7CC5F72A6DFDD95759C4D444 -:1049A0005BBBCFED7425C57E8FB6A52695EF5BD892 -:1049B0005A9BCBE728B6D688EF8D6510FBDDB2C8D1 -:1049C000C6E730B6D69ACD24274F2DB2305CF4F529 -:1049D000C7CFAB7FBFB94E3BD773AF76AE67AD766F -:1049E000CEEA6EED5C4FB376CE6A8D763E76159D3F -:1049F000EBB1133CC5B99EADB50B14ED3CAB7E2FAE -:104A000003C35742F8F2772A56D86B1A07F4870C7B -:104A1000196EF1DFC7665425C79DE7319EB74AF589 -:104A20000D30D49DF9C6F356C9434719CFA90E34AA -:104A30009EEFB1798CE77A2CCE4AE3F9D058FA444C -:104A4000609A566CAC27FC77FF7D477AD88FFF7E43 -:104A50005C37FD86F47340129D4349637ACDAC12F6 -:104A6000F499A17D0FE3864E2E53915EA874529E59 -:104A70005DA273902AD351F4FB37A5577A3ADFBF72 -:104A80000720AD4CFCF700F473087FD1ECA8A553C8 -:104A9000944FA71445E7BB7F8A723CB6AE973DC9D9 -:104AA00085FFADF2FF01C18CE32B00800000000008 -:104AB0001F8B080000000000000BB555CF4B1B41B9 -:104AC00014FEB2BBD144A35934B6865A481A520DCB -:104AD000A4B06D37A225D2D5869283C8163C78E85B -:104AE00021879CFAE358E86D635B904A24A9422F22 -:104AF00052C8C11E0A821EFC03621B7A8E680B52CA -:104B000029C18AE7405B7A11D23793AC899BC47A7A -:104B1000E940F2F266E6FDF8BEF7E6E50D68798158 -:104B200090A2DD137D40245A2A3848065468B930D3 -:104B3000305324E9A2FDB5AA94359114C0A9095CAB -:104B40009ABA1E2F4912D9C9163BFDD4CECEEF8D8D -:104B500031BB0126252EAF1F39000FB015B3E51666 -:104B6000FDC0C20E9DABC0EF315B0E7E96DC49A549 -:104B700032CA4D01917D69BDDE4BC02CFB49F17AF3 -:104B8000C73D0309F29F3180FC30BBF3D0CD745791 -:104B9000343BE5A33C427B4548E42F5284DC078646 -:104BA000AFAC81F6E7AFDE17258AFB6109B84CFB95 -:104BB0000BF652EC11DDDB1AEF945F28CCCFB4FD7D -:104BC000299DCF5C1121325DB71F962855D860AB67 -:104BD0005C237EA25255A755A1CF0334E894F70C6D -:104BE000D347EABAFB243029535ECF0FFC1B8591D3 -:104BF000BA5D805261FBB7B51ECF71376D8410AAC4 -:104C000088751C15B6EE36CB3F866FA360673821DA -:104C100030BED43D21E7A738BD5F96BB183EB1A892 -:104C20008B25B2478C508F13CE3DDD8D73FC7D6795 -:104C3000FC7502078683CBA22173B9650C72796C6F -:104C4000F8B83C3246B83C34142E4BC61897408A0C -:104C5000D7B3D3061E2F63C47763C1F6F1645B59E3 -:104C60006775C78484F7ACCE432AB76BBA17253F64 -:104C70000D7C115DBC190A3D6F2799FDBB27028F82 -:104C8000B91ADDF4EAE166FBD56753E7E24E1B7320 -:104C9000BBAFECEDCF5D1D486CB6F0FBB2D6C740A4 -:104CA00096E711880B58A43CBC0EC529D3FDF4B679 -:104CB00093F7754871E49C0CDF9A0B3F4C1CD43F72 -:104CC000CB696A19829CD524997AEAD46F8F42F90C -:104CD00034F45560FAE320AB677A223FA8138ED5EF -:104CE0009B9FE786C92EB5232288E6BC5E6B369E65 -:104CF00097892B202982DC027F3B5C8F6BF618F2B0 -:104D0000F0B960E5DF7ADFAC3BADB4345A7BA2B4D6 -:104D1000125D898C4675D2D66D9C07A70FFC7D77F6 -:104D200040CB33BC17C80FB8433CE7238994AB9EF4 -:104D30004FBB3A997974D7FACF9B2C3B12846FF909 -:104D40001F7DD8672F3A58BD9692423CD7228FF5E7 -:104D5000DA9C5B526F39D97B44B8751EFD716B9F2D -:104D600056F35991C83F9B4F2AF96FC1F737C67761 -:104D7000B59FF745AA6B46137CAC9FFB891B8D4200 -:104D8000F547904B116FD9A8A0E4E9FC97DAA17020 -:104D9000F796F9D0145F6DE8A36BCD73675B73551D -:104DA000E74D1041366F7E0ECDBAF32DEA6B4A9374 -:104DB0004773EE34F358AEE24C567122DCFA3DD71D -:104DC000EB355F1BEA488867FBE6EB797DD38E7F86 -:104DD0006B1FAC2475779EFE1FF0691FBE1B8C8F66 -:104DE000B3EFAF1D6F569E8EFF334FD6F3A23957E8 -:104DF0002E88F3A2F74CFD2FDBA790A6F00700004A -:104E000000000000000000001F8B080000000000F0 -:104E1000000BFB51CFC0F0030977F3A0F2BFA3F161 -:104E200057F1A3F2CBB851F99E68FC2634FDE7D1C7 -:104E3000E4591820B4233BAA38B158988381410E15 -:104E400088353950C5F3A1E6D6002DE807E215AC48 -:104E500084CD7A27C5C0F05F9681E12890AE06E246 -:104E60004B4036931C0303AF34038307104703F111 -:104E70003B190686A940FA25106F9086E8E3048A5C -:104E80009D9421CFFD6D42E4E91BC5D4C1B7955077 -:104E9000F993B51918AEE93030A8E941F8E791E483 -:104EA0009D806253B421EC70550686BDBA0C0C8708 -:104EB00095B09B1B0194DF07948FD0C36FBF831104 -:104EC0002A7FAB352AFF8B212AFFB2272ABFD61BA8 -:104ED000955FEA03A10135720CD6D80300000000EB -:104EE00000000000000000001F8B08000000000010 -:104EF000000BCD7D0B7C15E595F899C79D3BF79987 -:104F00004972031708308941A2061C204040C44959 -:104F1000081A6C8A17A44A5DAA576A2D228F2B6241 -:104F20004D5D6B26EFF0B08DE856FE6AF5C26A97CC -:104F30005AADD1D296B6DA26802EB61422A5D6B6B0 -:104F4000ECBF415D6D5965A35BD4B5B4EC77CE374A -:104F500093CC5C6E1EF6F1B371BBC337F33DCE77D5 -:104F6000BE73CE775EDF7715D107FA250067F08F25 -:104F70003DCF170160E6C0335A01A57239C0262122 -:104F800068848BD8F34FD2F2CE30FB06567CE9947E -:104F90008176578340F59F2F6A8DF7B2EFED93BE70 -:104FA0001A8732567FBC40F59D7ACEF30690000AF0 -:104FB000004A3A56AA09D6CFA6318D2AD66FD7B75E -:104FC0002D0736DEA91205241CAF287BFBD67A807C -:104FD000AEC90097C056B538C6CA47256333641BAF -:104FE000A788C671CAFEB8085DA5407F67D8FF369E -:104FF0007D290909366ECBA4AF2E47B895AE9B40EC -:105000008F00DC3626093A7B3F0D449A9752618126 -:10501000C9CAAA6EC5AD29678FD38E7829C35E3BF6 -:10502000E24B2303EF97387861F8C8C00BC05C00EF -:105030000DA67759580E00B5CFECD7B4C7D7E223E9 -:105040001BFFECF9F3F1A7824E7800B5239E880C84 -:10505000C0B3C9D7D725317C5B45603CC6AAE4B054 -:10506000712A5DFD648ED73F4FB9C3B3FE5310CE96 -:10507000029A8720BBFACB8467965D6F169B393EF8 -:105080009D79E5CCE3E30CD7FFE588E202ACDF11C4 -:10509000B7222E7A942D0FDE83767DCDF4D61B0CAD -:1050A0003F21C4CF4CC48F15477A74E8580AEB0DE2 -:1050B000356C3E0516F449B94436268C02C8C77FC4 -:1050C000B126B2A65722BD8E32595DF67D74CC6AE8 -:1050D00090D8FB31F3D282CC9E1178487B23040810 -:1050E0004DC9196A6471BAEF9CD1DECBE8F614445D -:1050F0003A36B36793CCFA45BC1D8BA41F632035A9 -:105100005C9C7AA4979523960C8DE5342EF1E1ED05 -:10511000D2F9C66646D29B6DFA6FAF57E9D95AAF3E -:1051200041971FA0B93E4ECFFB4377FD1BF65F674B -:10513000F9353F7BCA9DB73E85E52680048E1789E9 -:10514000F1FE4156B5C7342C8389788F94F0E74B34 -:10515000881706E7571926112F3FB0F1A44317F11E -:105160006B93B13407B2E0D379864ABD7C16D08305 -:10517000ACE540D91FCFF3947DDA584F7D8042C211 -:105180001B9599A85825707914917BC0403819BE99 -:10519000B2CA055BAE48D2B4BE2E36BFF06CC5D8DD -:1051A000C99ADE2D78F96B8CC0E9A34C50E91983BC -:1051B000BE7D67102F8698DECCC60A4E2BEEEC8A99 -:1051C000E1988A3189AD63D097D6F2B2F01794CBCB -:1051D0006FF53A70177FFCF891A4EE5422CBB87F9C -:1051E000B0D7EF92D38755E47F759A98489721BC42 -:1051F00056824D1EB6EAB288F3FEF8E01E7ABD8EE6 -:10520000DBFCDC0A2AD59771BDCA07D6ABDD60EBA3 -:1052100085FC53CED7AB5DB6D491ACD7E3001EBCB2 -:1052200084FAF1D2C9F152F631E3A569EFF244965E -:1052300079B4DAEB29836194121E141DE1DCDAC023 -:10524000E9D662749B4DFE0E860729E7583C5976D5 -:1052500036DEAF12F8380B6C3E71F0B4C9106BD269 -:1052600061C453470DCAADAD25A28872E9E3C2936C -:1052700003D7E67EB8D21CAED28F172E29D4B53C08 -:105280001B3FB666F0E316849BD35D0DA73BF1632D -:10529000A53B07AE00F2035FE7045F67F91F629D5D -:1052A0005BFBD739C9D739FEF1ACB3B39F836A2C06 -:1052B000C7755BA5313E6470DC2C59CAF5B8BF8652 -:1052C0000478CC607480F08F617A66B8F1655D0710 -:1052D000B84F08707D435A919374C1BB4A663ACB6C -:1052E000747CBFF5DCE410F380B4AFAFD78193F1E9 -:1052F0006FDDB186B6FD2E38BF24446204E76C989A -:105300008D70BE1B5E9AD30583F777A25E6D907D8C -:1053100000EFD75B6DFB7D677FBF59825436FDF28E -:10532000415B2E80DAA9D0FCEF643C380DF1706E41 -:105330003544D97A841B47E13C20CC3ECE61FDEC5C -:105340000A34C82EFC0E369F7EBC3AED98BAE3CFE5 -:105350003BBBFD60ED3E14928F080CBF2D31B11A9E -:10536000E1524B208D6BE0DFB5A46B2C0C0E6F4B24 -:10537000EC6F03EFA0EB66D77B37DCD80AAC5D930C -:10538000CF38A0333A692E108D461880C3A1176715 -:105390005D1C3C8E745D7EDB4F5F5B2F05D233411D -:1053A00097A6FDF5747500E9EA82BF3F5DBDF18FF8 -:1053B0004B572784827F5CBA52EA24FD75666714D6 -:1053C000C9269793DA4A8BD61FC7667249EA98D6E0 -:1053D00085F212E2CC3EE3C380C8CA8A6672BD176A -:1053E0000C40FD552DF1CA495FA1574EC6979B5DF4 -:1053F0004EBF9B751C57A171D13CC271E53074053D -:10540000A25856A81F24E733E7303CC18335C5BCFA -:105410009D81ED069B8F8CEDD878A87E9C29C27665 -:10542000FF9493C862F70ECCDF3B4E7C59222711C4 -:1054300019797D08CBFA1B2EBC0FDE4E86371CBCBB -:1054400030FA2F453F49C100FECD5DB790FF2200E5 -:10545000A241765D61AB855FDBF0FFCDC17D9FF33F -:10546000755BE1740DF52D60FB0DBEB7842F0096C2 -:105470003F1474E25B673C299C00A21BBBDE70EB0F -:105480007F3BF25316FE5E21727DE3FDBB52FF8D22 -:10549000F6A0B559D01F63783D54FF01BCC6F87221 -:1054A00065D7790AFA3DAE134751BD95F38A940545 -:1054B000AE7E5602B70B017AE52511F7B80D5C0FE9 -:1054C000ED94F6E2BC5FAD90D2B8FFBD5AF13FA4B7 -:1054D0009FBF6A4A6944F2ABED57E60C25770ED5BB -:1054E000737BD6A977C894687F3F24F786B3E9F128 -:1054F00003E3A769FC2B2A24EF3E2DF7CAB8FEEF81 -:105500007F097CA83F1FAA5785D72631E317E7C933 -:10551000E868654591827E87E1E6B5C8F68339F88B -:1055200075E6D91C16699ECDE12AF25B356BEF92C8 -:10553000FD788ABD47793018BC8EDFAA595B9A1571 -:105540001F4A84EB5B8A2F99DDDEB4E7EB9433FDD1 -:10555000590E7CAD616E17B586395CAD31318DFC6D -:10556000DF1ACF3EAEF36CB2E173EA35C7B85EDA4C -:10557000CCE4C948E091C35E7818DA8EA0BF64BC61 -:105580002D6BF26B7B1A3E8F7676326C4A06BEE943 -:105590001126B0F2B8B8049B35366E4D557B356395 -:1055A00081BC1589171918301A3A2AD10F38F14BD6 -:1055B0001BBBBFC6E6356E8E5FC3767935A9EEE7B5 -:1055C00058BBB14CCC49ACDDE8636BD7A29CFD174E -:1055D000B41351105B3736A01FAB1987980BF0B08E -:1055E000B8A212FD6C3270B9C0A49E2E8F42FF0C7F -:1055F00090736630F9C0FE8433FE817683E12D62BC -:10560000CB2B9A37C9ABA543CBAB8DBC7F8BFD872A -:10561000F266DCC078D47ECC2AC583C7D119DFF707 -:10562000DB74E987257FD771C6C2D200EA2791656E -:10563000A296C6FAD0998B7EA8516B64E8C2EFE5BA -:105640001D0D4C7C0C8B7726F76AB8DF38292C713E -:10565000C1FB2B91FB9926DC715410D0EF6B309578 -:105660007E1A96EBA665A3D36D367DF6976B560A28 -:10567000491A2FB16812CAB55A91ECDE7F59363DEE -:10568000D7DDFE037B9C81F5075D9E8565BEFEF23E -:1056900032D10C4CFDCBD75FFE88EB9FBF51F1ECB4 -:1056A000A71F755D64B43D0A865FFFBF761C67DD8A -:1056B000CEE60F2E1F27DC511D40F9775F6268B9D7 -:1056C00072F6BA2DA5751BB50CCC7416B9129004E0 -:1056D000CFBEEA3C554881C1D6593A2A917C9346BF -:1056E000CF5ABE03061F578A2919F69BDD9F65EE28 -:1056F0002B61EBFF4970FE7A649443B52887502EE6 -:1057000095FB5E77FB4718C607CA0CF76F7F71DF02 -:105710007E9447169347E83FCDFC5E8B65173D5C52 -:105720002AF1FD77EF777E79AEC0C6396CF8753F08 -:105730007B7550E87983FCBE9512EDC7089F3A0B44 -:10574000DB032927874DC9AC66F57BCA05DA47FD1F -:10575000F0D2B5FF4CED4314EFE899F7DA972F62DA -:10576000ED3F79B10F39876302DBC7D93F51AF39BC -:10577000DDFBE58B58FD8317E70FA96FD5E27C5D54 -:105780007472C5B3DEF20AA43784FF3FDEAC7D90AD -:105790008D771872127E7C5670F80E237C48F7BD08 -:1057A000BF7E03F5C243A640FEA8C3153F8FA13DAF -:1057B0005E690AA42F2E9E27A4FD59E6B978DE2D36 -:1057C0001327B0FE1246480BB0EF072BDFD97A1132 -:1057D00083F78AEF4B77E3F3E41EA920593638BCF0 -:1057E000CEFB2B4CEFFB7EBD189216E21D341E97AC -:1057F000F0C58CB89B5EFBF518396166F3B7AD91C7 -:10580000B8FF51D00CD2EFE4B002388FC1EADF38D4 -:1058100008FDE6405F97847038FAF7E92B75B73CCE -:1058200074E050E44412C791340576A29E917B95B2 -:10583000EE9E7FBDC4E34242DC2478148DC3A3C82E -:105840008699CDDF5467C3E3F403D061B7EF83DEFD -:10585000F0007C2D81C472F45B58B9DC7FD81CF158 -:10586000FA0377DBFD3CE6F4E783AC71158046EA8A -:10587000BF6A54858AFD3755703D490783FCE3CDE7 -:10588000CC6E8421F4BAADB6BCD88CF10D3FC639CC -:10589000343BCE11E7FA53F819F2939D2A13C9AE9F -:1058A00019AC9F88E1D54742A55E3BC6D15F027A1D -:1058B0005E861FC8EBF7F18D924547EF437A1D0EC8 -:1058C000FE7E3DCFAED726A7542D2B9ED243EA7342 -:1058D0007F3FFCF1F6215FA7960DAEBF15DE1CBA27 -:1058E000CAEC5FC95752698ADB25E21E7DC09693D8 -:1058F0004ABE9AC27D01D4C1BE0779FB30FB8EF14E -:105900008C7042477F8A043C2EA4221FB8F0F38E8D -:10591000DDEE1A59B4F5F914C541053D457E3BB598 -:1059200090F18F70763BE7D96BB76FFBD3ADAF10BB -:105930007F14A8C41F82CEF827CB388D92F996C465 -:105940009EEB24F36D7CFAFE2C25B3F1C97FD9724E -:1059500045AD4DE86A31C515C91EC9842320F37EC3 -:105960006F74E0B75214A71C29FC1F8C107E671CB3 -:1059700006BF2C1710FC3E7C0E06BF64C393077A4B -:10598000838C724DE7F2156089EED64B6E90B9BCF0 -:10599000C8B3E513C02D71B7BD759DDDCF48E79342 -:1059A000278F6C3ECEB86C3E1364BE1E13E521D625 -:1059B00063BC0DC70D32DFEFD4EA841E67EB923B68 -:1059C000085DCDB3E148C9A2AD57DCF291E8EA82A7 -:1059D00011CE63DEC0BACCB6D7A562A879CCB2E747 -:1059E000D121C19CD7512F3EC7F1F72CF5ACCB6D1F -:1059F000367E3AFCCEBA6CF0ACCBCDF6BC463A9FC4 -:105A000085767FC3CDE7B681755962CF67E950F3DC -:105A100071D5BFDAAEBFDCAE4F76C76D726923DADF -:105A2000198D5262855C30301EABF71977BD779ABD -:105A30004E35D8F5AEC7F7420DDFFF58BD95EE7A6B -:105A400060451BD13FD082B602B3634A9AE756D96C -:105A5000ED5651BBDAFEFE6FB2F983DA059A854640 -:105A60002B4CF5D662BD86057F76EAADF3C27B810D -:105A700003EF0682B7BA1F8E5BDDF5E6C9E3A8BF68 -:105A8000B3E20E23F407F962C9768CF3E741A4036D -:105A9000F33C5AE5D42398076059323C86F9047EDA -:105AA00043401F5BB422F56F582FD762F635AE5BCB -:105AB00055EA292C5B22249ACA299F80F205EA64C0 -:105AC00055F31B987F61C07656D662721AEDF316B5 -:105AD0002169E1BEF83329F96599E4ABB6A201FB6F -:105AE000CFD7B99E0EBDB46F3970DD13BA96F21FD1 -:105AF00072195CE88F6AC980EBFED0846EDC6FEFB0 -:105B00002D50484F66065629CA97DBA5A081FD7522 -:105B1000177C81E0DDD6C0F31BB67DF20B04EF7D70 -:105B20000250DCF63E1FCF6FB8C7A76A8D1AF61772 -:105B30001DF339CA87C8D1FCE5361C08DF278A095E -:105B4000BE7CD02A6F10487C75A37DDB52A190BE2D -:105B5000BC2D36BD92FAAB50494FBD2F31BD81F4FB -:105B60008E8A20F9E8F3C306D9ADD1D90A58588EE8 -:105B7000190DA867466605310706F20B01930B2045 -:105B80003219D258F6414747097B46DB995D924F5F -:105B90007613DC80766F05C33BDA11967904ED92BB -:105BA00030D87FD24113E7ED1B2701FA3D9CF58DDC -:105BB00076F4B71FD2EE8AA64758AF6B64F522ED94 -:105BC000CCEE9F31827A1D23AC971E61BD2E5E6F95 -:105BD000587F87C1ED3D95FD87765B20D36E0E7BA8 -:105BE000ED615FC6F7CC785CE633331E7242F6C6D1 -:105BF00043866BEFC441869B2F3A25FAE19486AF2A -:105C0000EFE89B837D57C65E153759FB9631D7C4A5 -:105C100049AE8D59C19FE3EDF7E397DBE56BECF2FD -:105C20008AE56616F93EDAC7E57029FA4386F23B43 -:105C300000D71FDF60B09F1130796968FF49A6DE89 -:105C40009B29EF54D9AA427EDD96E07E4D3F322358 -:105C5000F26121901FD607A98E1294136046178E09 -:105C60001AE01F9FF98289FC7C688C044205AD8F85 -:105C700041FEF40C3AC9A40B7F863FE7AFA5930B16 -:105C80007DDE78ECDF8A4E94766944FCA3748CB098 -:105C90005E7A84F5BA4656CFDF2E8CAC5EC708EB31 -:105CA000A54758AF8BD76B9DA3F0FD1CBEDB689654 -:105CB00030B8E7AA9E72EBDCA0F7FB45614FB96DE7 -:105CC000A642FBBF53F6CF523DE53626E73DDF67E0 -:105CD00087A9BCA9A5AB8A6D6523E693FFFC0BF9E8 -:105CE000A4541DC62F5D2166D86D197CA5EA016CF0 -:105CF0009F2FEB80F953F931BE4FB1A799CE82DFC8 -:105D0000476CFEDF29F3FCCD6DB21E40FBF11F7D19 -:105D10009E0D3E0EAF33DFE1E075E4EF9B92AD6F79 -:105D20000D96F751CDF3326508525E6649B5596557 -:105D300032B924BFC8E36099FD5EAB249FF6B9EC8D -:105D400061594BF2F89EDDDFA20299F41299C93530 -:105D5000D47B1448D414511C51247F9F1C1E66DF31 -:105D60002874C9ADE221E0B6F358E9930E50F93B2F -:105D70003E6ED00092AF11E825633A07B59E73508E -:105D80004FD305A0F686C0FDE7F334DCF76281BF90 -:105D900075BF2BA85FC1BC07CE843E42BF722FF9EE -:105DA0003BFFE6FD0E036F00F37B2FA01042CC9D5E -:105DB000DFEB8BA7E8259C3E73469A05BC09FD25C1 -:105DC00029BE2E8B06F943616C94ECB296D806D5A9 -:105DD000BDAE7FF4157BFC268AD67A8B1065CFC2C8 -:105DE0003566EF10747E068331E81F29BCC1EC1DB7 -:105DF000623FED8F6762BC3E0B1FB42AC934EAEFE5 -:105E0000D68430B7E7E514F919DB84BCE99BCB5D98 -:105E1000F45BA874215C9172D3427BAF2D5F345048 -:105E20004F95616B8F3095B5936A8D64163D62A076 -:105E3000BD7CC23D9F98E2D5A79A86A1F79661F4F2 -:105E40001E9F6224B3F943272BDCAEF505B37FBF59 -:105E500043AC2A51669E8D37A6E673FB3617DA856A -:105E60000B39F950BE43E10BAF201E5A0A2E8D0F9D -:105E7000355FD0BC7997378AE634656838666683C3 -:105E800063A4F9205AB54174D8AF2FC5385DA39EDD -:105E9000248CC27C0FFE7777F9CE2ECC03F15DCF38 -:105EA000E3B292B90BD04FEDE84D92193C2ED27A65 -:105EB000CEE3FA5329D7874CF61FCE233A6F68BD3D -:105EC0005ACA282F51BCFA5053FD1EC0F8BC03BF5C -:105ED000E3C7CB9CD75CB1EAEAECF818993D7C1F8C -:105EE000A317988CF1281591021DF51A95BF5C1F18 -:105EF000A7F2D67A9D9ECDF5A5F4DC824DE7209FD2 -:105F0000A7DA8B18DEDAE38FC63FC7AADC87B28335 -:105F1000F6FD6B17A09EBCB9BFCCCC4006F7660C53 -:105F200078333DE256E58A0568BF6F0E80ED57581D -:105F3000B0C0F494AF6AAAC4B2ED67D8DC7A1DD5BC -:105F4000BF6F3CD8E7204CF553AE7DEF11C547FC41 -:105F50008D7B0B6F6F36617F01D92EC32D0BBC6516 -:105F600030119E80CACBFB940DD43F890036DE4FA2 -:105F7000955BF97893B81F1FCA960E8347EED70733 -:105F800045E7F2B32C8FF25914C340F72BDC976B23 -:105F9000C33DD27EE424DFEF8E66DF2F07F86698DC -:105FA0007DCD8663B8F567E8B0FD1049B070DC5F61 -:105FB000F038E2DF7BDCFB7C1F0D2F4A459F85E735 -:105FC00047E629C9EF21BD47CCCEAE22568ED67604 -:105FD00059C4BE231CF75E45B3E79D24FE77F0EC61 -:105FE000E81DFFE5F3AEA32F66521E5220CCF96FD9 -:105FF000A4F0F6A27E3573A01F78A26ACC50FA5A9C -:1060000041424425AC5F5EE4D704D118EB2FE79AF8 -:10601000799E724EC5584FFD8851ECF9EED3CEF7FC -:106020007CFF4BD7E91719F3F889AD373AE51F67BD -:10603000CE7384FD3AE5EEDE0562295B87976B251A -:10604000D2EF5EAE7DEDBE19584E4814BF3DB5BCD3 -:10605000C9878C7414CCC84CF4872525DB9F6E8EC1 -:10606000477CFE02FFC9C67B09F73D269F0EDBE792 -:106070007F989C188FE79F0E5F3C7B3CAEEB611FC7 -:10608000E76FB03A483EFDDC071E79F0735BFE18FF -:106090006DDB9BD00F7954E065A96DFB028BE28329 -:1060A0005B5B2F637ACB951C85B0B456C86A0F44EE -:1060B000FC0AE1E3432119F1B3799AD57A4B0CF349 -:1060C000DF74207DD50F09D2CBEAC0AA1451DF615D -:1060D000F447716EB9AF309BDEF1737B3FF7C39528 -:1060E000A4EF2FADCDF5A131EFAF99E6433FEA958F -:1060F00035953EB0F565CD059F9810E8FCD4B25AB1 -:10610000FF4EC4EB32D9F4658B6B5D99F07BF6A939 -:10611000690C8708FF51FBDC03405FA13BDE34CDF7 -:10612000CFED9D78C9D0F68203B7535E523BED792F -:10613000C403C3369D4701B5AFF0DA88BBDF9013C7 -:10614000178E60BF2F2FFF2CDF9F195DA05FF1C559 -:10615000E39FF7515C7659BE87FF96564B1EF813A6 -:10616000F3429EF255B557E60CA97F24FD19F2CCF7 -:10617000B2CF618A2487371F13483EE44CE84B6353 -:106180009E26BC2C01D7FF1CFFEB5CF2BF46C7F577 -:10619000E9A82FC06F43DA632EF9D96CD3E560E329 -:1061A0003FE7E77AAD9C5743F1EDF78F0B3ACE57B7 -:1061B000C8AB9B8CF39515B311C76D2E12D318F78E -:1061C000BEBD789B8AEBBDA9E4A3E981BE188FF719 -:1061D000EB96361DD97FB07669939F23C87CBFC6E6 -:1061E000CFE32D2DD652AD049771BF5689F30F140E -:1061F00042D673A68CFED7F8D16F1FB380C7D713D2 -:10620000A45797A82B290F571E3B74BC36136FB2A7 -:106210001D07CCACF7A44D8F25153BA9DFF7CF1B8D -:10622000BA5F072F1F1822F4D8FA04D65781CD87FA -:10623000E17F4B29CFC36D2E7B86F02C9995A4CF9F -:10624000FAB49489F5B694AD24BA6C6175F2D9D0DC -:10625000B9D59D744E73CB9F787CE2C9B6FD4DA82D -:106260003F6CE9BE0930AF32184F03CA8F2D536E11 -:1062700054110F5B7600F4201DCB9DE4940BD9FEE6 -:10628000F0900669664941A8CC04940B791A3F53F3 -:10629000B9375E05B86E5BCAC140D6CC4FA71A307D -:1062A000F4B325CEE3DFC152B3A608E11E23921852 -:1062B000D021D98EE5E65A99E6D1AA717CA0DD7588 -:1062C000C6C9EFC23C98126E7795A07F9FF5AF7C50 -:1062D00089CF5BDF5E427EA22DB92F9BA8EF5A9F2C -:1062E00004631270BD96F40499D111F65FA7655D41 -:1062F000F7AD62F29B7E57FC5ED67401E934133F22 -:10630000EFFBE0729C77F334117666D137F6F879BB -:10631000BC2E6D2CBDA238CB38CFF9754F9E80FEB8 -:106320008142700F567FA09E4C7E7D343C16B17921 -:1063300014D4707F29649C638D4192ECDBD160356D -:10634000203F3AE757C755277E95644F29B28CF214 -:10635000E9063BCFEAE479AEACB00532E857FF86F8 -:10636000CDF7A6033E40BC5D72FA9117305FCA5765 -:10637000E1D728BF0A3A5EC0FCCD1B983A86E59B60 -:106380008E4D5130FFE7E5B112E6C620FF44910E75 -:10639000DF0691F2CFDE8623D1192E3A7FCBDE774E -:1063A00050B2A21C69CAE5F392C3AD3D5214D75D49 -:1063B000B67A9DFC3D5298785E3B84D97B95B28F2E -:1063C0001A48FEB5F37C21273FF2731DDEFCA1CFF6 -:1063D0006FF7966F84A5A3906F6E640A5D9AF57B44 -:1063E000933BEF8B8D7FD4CFF583CF43AA15F79FD7 -:1063F000363B3F66EDF7A62848D737CDD08AF01C4C -:1064000086338F3FF8B91D7A82F1A9EEE2FFD5B14C -:1064100034E52767CEEFEDDD0BBA92ACFC9A2EA7E0 -:10642000B89DED9D679BAF6731E67B5977FB6CBDEF -:10643000C19BE7B87A57A589F9620C7B7ABEB73D54 -:10644000C1FFD976EF7C87C347E6FC1D7D70B0F9AC -:1064500028BB84ACF97E21D59B2FD5A4F278A3D993 -:10646000244360FED9E7A3ADAA149D6FB61AFD5A66 -:10647000538CE29314FFAB638483F1BD7255A77E06 -:10648000DE0F4C48039D4348CD46FDE8AFED778EC7 -:10649000CAF9F06FDDEFFC41E05DABF62AC89FEB77 -:1064A000E58E1AA178E07C40C06799E318BEFD7BB9 -:1064B00096748D034FBDF611D63B8047A04750AF71 -:1064C000461CA2BF93F6BEF5EF4FFCAB82FBF7DB99 -:1064D0008F1F5F8C72EEE61F4AA0B27A279F88401A -:1064E00017ED3B6905E5F2EADD12AD3FC85DB3AEDD -:1064F000F4E4DB37D1FC6F7E2A42FBC3EA67FCE998 -:106500005AD67EF5775F9B0A8C6F4F36F6BD300EFC -:10651000F1F7B8C0F318ACDEA957B2F7AB65B82EE7 -:106520005B1EC2F52AE7ABB7BE1F5A8EFBBBB0ABF2 -:10653000FB5AEAB7F36A9FDF257F97ABDC9E66F5CF -:106540004CFC6E7D43484F12387CD9F2F2DEFA06DD -:10655000F7A3ACDEE34B639EE2EA5D3B9424ABB76A -:106560007ED73B44DF0B9E7A328A7858BFC77B1EAA -:10657000E1E6A7FED43AB79CCE3BF5D5A2FC934EFC -:1065800053F994A9F6F13C78EE8F59471CCBEA7D7C -:10659000FBCD4B7FC3BE9F884B106022E544CF7F6D -:1065A0002A3FC472329C62A28CF5EF7BD5CD87EB7B -:1065B00077BD46E78E349129B017E179888CEF19C1 -:1065C000F5999EABA03C5CDFB9E91D9497EB77BFD2 -:1065D000FD6BA4BBF520BFEAE6E713F88F3167C770 -:1065E000B336A95E3FDD2938388B1C00BBF2B3DA25 -:1065F0008B4E3CCBE1EF9B9F3CF530EA116F3DF3B6 -:106600005F0FE3FD0C6BFEFC3F0F635E2BFC28A0CD -:10661000A1DC5AFFF82FA2E0C2FFA3B67C38F98DA7 -:106620007FFBFA030C0F277FE527AC9D7CEECD099D -:10663000784FC7C9A7FF7714EA1F1B9F5B381AE979 -:106640006CE377168C1EEA1C28D26DDAEF5EDF341D -:10665000BFDF608F809B20C0B3F633635DE0609F37 -:10666000827AEF7B02F46DCE65EF3BFFA4A0FEF2D1 -:1066700082097D88A77DBB5F7BE10E567E9BAD9333 -:106680003FCB3AB1F98F13697F63ECC39EEB765F22 -:1066900079C5C5E5F8F419D8FD7AE8A37DE3ACF532 -:1066A0003DCAD6B77C607D33BF9F82D30AE27FFDAF -:1066B000136C3DA7E2BAB2F59C7AF67ABE8DFF98CC -:1066C00073F67AEE53BDFEB853B0E69107F0E3EEF1 -:1066D000FCACF6ADB39E6BBFF3A921F572473E0C3F -:1066E00087673ADFCBE0FA8A6AFE5C45BE7DE69BAF -:1066F0005F7F20C6D7B99621E6E493A726E0618D97 -:10670000DFF9FAAE453CF43DE7D7508F5AFDDC2F58 -:1067100089EF4E7EE7253AD7C3FEA202DBEF4E4259 -:10672000FFDF1160E575022FACD5FB2EFD35EB7751 -:106730002DEBC23268FD2EFD7539AE9FDA47EB9125 -:106740005E52A3A3FC4D17D0BCD7A5397FAC4B77C5 -:106750002F437F7626DE2301279F70605DD15FBACD -:106760006EF7F14B91FE065B4F67FE1ACE7F36FB4C -:10677000FEA8977F07E5577B7D4FEE785F41FDAA26 -:10678000EB878A26323BFFA4AF4F198BFBCDD39208 -:1067900086E78D33D77D00FF8D59CF1D673E33E9E6 -:1067A000C31FC81EBF76F0341CBF0F3FBF8F86BF0C -:1067B00053F63E9C89C7B74E67DF0FCE09707B6EDC -:1067C0001D74D4A08A99B99FF920658D2B1A80B7C2 -:1067D000B5532239FFD62EEEA7C99417EB06B1CFD9 -:1067E000A639E3ECE99E8A72EDADBDDFB7E992D33D -:1067F000FDBA278E2B96BD3FA45DF85D3F88BFFB99 -:1068000022BBBFF5CF66EF6FFD13EF64EDEF846C35 -:106810005E8DF09FE8F1515ED2894E29AB9D3B29F8 -:10682000E0F3E85DAD9159AFE4B076523448795762 -:106830004D8DE62FD14F6A1DF1D97E00E377986F19 -:10684000D51409D239F7A6E88D745F92D35F730629 -:106850009EE47882EC27399628E731B0B4C78EF1F0 -:10686000318270C30DB255887AFFA1A23765ECF76B -:1068700030EA912EBBFEB00C2DF9E5782E42301A8D -:10688000208B7F23A3FFC43C0974B79FB06B8CF8A7 -:1068900007D6DE7F544A236AEB20D545E7020AA1DA -:1068A000F3B12CFD3D54AF93FD5C94B88EFC3FFEDC -:1068B00054CA447DAD70A3562CEA838F3B3EE58DD0 -:1068C0005F8F6594FF071CE7808FF441D8F5F8E3EC -:1068D0008F8FE25B0AEAE52FE093C9BF4B56E9854B -:1068E000587EC89E37E3013AC738DE4AC828E78495 -:1068F000D81219F58B85A984BCD2B59E0B63C258FA -:10690000DC4FD383DC03F5BD00DF3F1B1AAEA23C96 -:10691000F607BF24125D3F18B8AC10F96C7FEEEC9F -:1069200030FAD7BAD7CE3A3899C1392E2C019A9C71 -:10693000FBC2439FDB7CD8F62FECB4EF1F7AD4CE9A -:106940002FFFBA8DB75DF5A5F47CBCDEA0EF4FD468 -:106950005750B9B3BE869ECFD427E87DF48E60121F -:10696000E97377FD727A3F0EDE1170FDBF5B9FA465 -:10697000F2A3815C827FE29D2026D9FB85888FF07F -:10698000C0BC1D78D2B6DDFDBDC08F9B912FFAF142 -:106990009881EF4BA04750D17F1513745CF7BA80F4 -:1069A000CEF35C33F03BC1DF27605CAEEE4E9E0F52 -:1069B000F1B0E03DEF70BF2DFFBF6DF3E93BD1E4D7 -:1069C0009301D6CFBB35CB4A491F02AD0CE9E66136 -:1069D0002171D828223C7BCE9DACCE4B7E3BE0F291 -:1069E0000F4F68E776FDF6802DDF368288F4363E5D -:1069F000053AD29B33EFBD957A21CAC5BD8240EBE3 -:106A00008DF456EAA2B77EFA0DD879C9F1ECFBF8FD -:106A100000FD72FE8FCF2DBDA71AF1B241243F4871 -:106A2000137E72B5FBD0A62366B78816D2F32A91DF -:106A3000FCB9138F1D172630F874ED9B01BCB72BE2 -:106A40003E016C7F536700E9EBC155DCBFF8B563CD -:106A5000FC1CD3A98DC54B26B3FA8B197E30189533 -:106A6000B7A8C4E3B774CE2F7C4D4DE46843F8B7A4 -:106A700032F3DEEE9F78D707396C9C71C7423A9E9D -:106A800087B967E28FBA15561EDB2B903F696C38C9 -:106A90003519D7B3F2FF7F634CAF6B1D1E589B9A1D -:106AA000887A63EBC46F09C807634FFF58C07D64E1 -:106AB000A2967C33C0D6619C6C9F139653B3D12EA3 -:106AC000B8262FF17B5CB74461FAD3484FA76A36EA -:106AD000FE3BF6EFC421EBEAF4DCC92EF990799E77 -:106AE000E2A1D4D0FE4C67FE0FE1FC87A8E7CCDF23 -:106AF00059BF5335B135281733F199D96FDEA265E7 -:106B0000438EFF907D8F189BBF3FE8A2CFC254AF4A -:106B10008CED9CF683C55D33E7DBEF271A619CB6ED -:106B2000D307F948174FFF71C2B70F03924E424285 -:106B3000FFD4DE40724C7026DE1F97A232938E94F3 -:106B4000CF7E412EE7DF07467D7D0CF19D9C2EA276 -:106B5000BC8F118ED702894425EE73866864DB07EB -:106B6000A60439DDCF8314F947C5D09D43C7F90B7F -:106B7000BD71FEAD409300AB4BB5E31F206BE80F3A -:106B80003B00D3D10F991FE4FC5E2973FB72C60151 -:106B90007D87C4FD56D292880B7FB6DFCEC7BB6619 -:106BA00070DF099A8EE7BEA6750B2E7E7D3F949C02 -:106BB0008FEBA6C4B93FD2174BD279CB855258245C -:106BC0007F6E0797FF759050CFE37119C079EB1076 -:106BD0001771BF7F68233FDFAE6B2182FBA1984E08 -:106BE000E53A5B4FF9B14D47DFB7E5FEF76C7AF94F -:106BF0000ECA7DF62CE935F7E730B8BE6DCBFFA79E -:106C00006DF9FF942DFF671EED856F94933C363030 -:106C1000EFF9CBDBE28D38CD27EB4DAAB7B37E156C -:106C20003DF7E58E16F7B07A8F6E1477223F3FAAB4 -:106C30008DBE1CEFBB4A9BA221B0C60F59DB164488 -:106C400019FC3B5481E2670FD7A7A8DD0E556F549E -:106C5000319EC2AC650BC9A0AE87C21E95BFEBD3F7 -:106C60006A58BDAF75E45D8E71B87B6B646AE7F0FE -:106C7000913E73033687689E3F886C9557D0A59EDA -:106C80008376FA4691FAF94AE033EA02F61C3FFEAF -:106C9000887A998E8B71DC4CB1EF0B1892711E15AE -:106CA000BDBD16964B5E0F53BEF6AC577AE16956E2 -:106CB0002E5A15A1F278CBCB175376F75A1D0C8EAE -:106CC000F16FF1EFD579BFB73A59FD9C0D51EAAF9D -:106CD000EAF55E01E9D957EE3D7FB5DDF7AB7D11F1 -:106CE000367EEC604240BCED15B4059812627D9A88 -:106CF0009FBF197D00AAF07D3CBA88D6615BB08841 -:106D0000E8E76BCD47E237219E36C69AD1CCD9B79A -:106D100071039D4FF06FDCC8F5A014F77F8FBF6D36 -:106D2000BFF079977C286C96B3FAEDB605FD3C4E22 -:106D3000B271596232076F7F18F5BD12EEAF2C6A3F -:106D4000A9F6E43539F1910F85E4B620D94D3C4ED2 -:106D5000226B297A7FB184BA227B7DBBC8F5A4441B -:106D60004FC0ED87D16FE3F7B365C2B13328131C71 -:106D7000CD56F52A941777CF54E400C231D9BE9F7F -:106D8000C58E43F6EF63427267D0E3B7E7708D6755 -:106D9000A80C21DC5D3D9FEE64FD7C9072F63133E2 -:106DA000487AD23D22F1C7D6727E0E709FF16E17DF -:106DB000DE73E1F0538B2112FF6E9385B4C0FAD9D4 -:106DC000565E9C7B1ED24F0C776F9AAF8A782E91BD -:106DD0007D3C8703CCBDE817F7A35F9CAD77C9B1B5 -:106DE000D07191FC7FDEFCEF22CBBBFE629DF7DC15 -:106DF000DD78A6F4B8F39581114D3F9DD1FE5ABDC3 -:106E0000F73F901F968788CEC032A395A3307DD1DF -:106E1000FE936AE9FC7349C63983076CFBFD61FB8D -:106E20001C219CBE05506E3D609FBF7E608D18D4B6 -:106E3000195E9EB78ED0BE39BEAEAB9202339ADFDA -:106E4000935FEDBF536BC4FDB528E5CD13AACCC845 -:106E50000B2AF92BF3AC8F05BD76EADE134103EF65 -:106E6000C34B1F950CD467BF7CC70C927FD66AAE0C -:106E7000B7A457E53D80E75DF20530F0BDD3AF63C1 -:106E8000BFBE1BCC23BE49CF61DF73985C89742ED3 -:106E90005A85EB05395A630CCF43DF0EDFC2FE572C -:106EA000F1F5AF2C04BA5FA7300674CE993D379F39 -:106EB0008BFCBF51C498389C41398F725CED7911BD -:106EC000DFE75E2ED2FD3945CDD67938CFBD73C709 -:106ED0008E45FAD81AE6E75E9A841468086F01E7CF -:106EE000871D912ECA07BDBB468446A428864B0346 -:106EF000FB5919DC49792C08EF4CA23BD2BB304638 -:106F000081FC685D1FE4FBCE69EB3CF42B4743BD7D -:106F10009DFB583FE136C5D8C9FAD951E9BDA76EE6 -:106F20005288EF778190E0C4F70321F634B702E589 -:106F30002DB2B9107F33BEB280F6058DEC2A27BE84 -:106F40001FDDBB482C9AC29FC52EFEDD69CBD9B48C -:106F50009DB7F0B0BD7F38FAC603B6DDB0D5DE37D9 -:106F60008ACC2B1A15A4DB55300DF154B2A6535818 -:106F700099CDBE6FF7CAD54C7E9998C92F29EF39A4 -:106F8000D571AB8A3DDF23C6F99EEF148AC17567C0 -:106F9000FB37E2B92D5026A1DE370312A65BAE0CFB -:106FA000B6FFE707CDA9A18FA0FF44438914EA9F4C -:106FB00099FAF745F6BA5C1B48CCC1F588CE5D4E10 -:106FC000793C6B03898BA87F392DA03C9D87ED62AE -:106FD00059E1A5E4AF11C05BFD51E005D9A0F35C18 -:106FE000B74BCE7DB6DEF35C90717F6DE6FDB4F3FA -:106FF000FF7827DD4FDB2230450FCB39F6FDB47E1D -:107000007E3F6D4B84DB5D2D761ED53A1B0FD785F9 -:10701000F87DAF6B6C3A9D1FCA7EFF91E3F74AA1E2 -:107020006CC07AA3B3DF3B861A15F6377F5CF6EFA8 -:10703000A9108F3BCE9F38F4381B701CD6CFACA064 -:10704000B936E4F2AFCC0899EBDDE55B43767E918F -:107050009C20BDD294F97E581434378666BAF06B02 -:107060003FF31695D379BE53F6793ED66EBB407882 -:1070700095B491E0DDD1FF5B04FD1E9283BF607A81 -:107080005F96F5783F18B5C49C817894A31FED0AEC -:10709000717B92D1DB263E8F34E5418741BF07EFFC -:1070A000811887F770EBE85738F6F0BFA2BCBDB87F -:1070B000A706F5A7B53F90E87EBBB3F0B586D19D96 -:1070C0002B1FC5793FF6837164074F9492F7875C55 -:1070D000F6C7D8557D0AD23BC25FCDE1E7F9D3426E -:1070E000FA3C6E0F00C5715A6E8A7BF20933ED913E -:1070F0003CBCE780E48A427A5D265C8E3DE19433B5 -:10710000CF231CB2E908FFF451784F38706556362A -:1071100025E4AF9990A4E76CD0E9C9EC964E9C07A2 -:10712000E33F1DE16C0C4DB808E7F177C4DB8F42FB -:1071300033FFF1F0E6D07151F2927E3ACE76FFF550 -:10714000FDA128C9DBBA6311D2FBA37BBF48742D14 -:1071500031BA0EC406F265EAC0CEA30F4327EABDDA -:1071600045C97A3A177A8AD131F62B69FC1CAB0CE7 -:107170005A02E336528CF3874F2ED5440DE3B29674 -:107180001FF30EAC623050D6A23FD20D6F7938F9A2 -:10719000A61B8FB71FBB87E4EDB581E4095CCFDB8D -:1071A0004B2C3F6A762E39FC965B0E0B10D691FF66 -:1071B000E69FE6FB65655297911E16304E47BC2F41 -:1071C0008424952F038B9E8B204DCF4FE09546A4B2 -:1071D000C7D9E716BAAE16DDE716FAF3B9CB9D7C30 -:1071E0000E1EA72AB0E9106C3BF5F9E54B1B16B251 -:1071F000F1D9E29B188FFAEA729ECFE39F2DD3F963 -:10720000D582DEEB6B314E04CBB85EE6E441E4D5CB -:107210007AF5B4B3EEB73AF6FB63D82EF39C9CA391 -:10722000AF65EE5BCE33535FCB0B673F3F39D8BEC4 -:10723000931957A8C37F72FBD5B6AB1339EE7BE326 -:10724000339F87EAFB9AF7BBF2CC0FE3FD4659F771 -:10725000011EEF8DEEFD7DEDB272BA5FCEC094C916 -:107260009EFAAEF9AF4F1AB08313F3729F477F7443 -:10727000A23A77BAC4F0BE38FE5EF3FE7C80256683 -:10728000F7FCD75DF3ECD118B459F484FEF14CDF70 -:1072900087EEFDF76D85CB97167BBC881D1F6B13A2 -:1072A0002D3FF1ABED7FFB4321B7D31DFB3EDB7CD4 -:1072B0009B095FBD61A487C1E6FBD930DF4F472D35 -:1072C00037E8BEFC26FBBEFCA6F14EFE96A1A13E11 -:1072D00079633897DF57102EA1F86A53F71CF2270D -:1072E000171CF4913F7DD4B2A460B9F6C57BEBB90D -:1072F000FFF52B4CBFC37C902D4CAFC3F2DECA59B7 -:107300002ADA0BB746A653BC7673BDE1C917719E46 -:10731000781F5DD2E5DF6B4A546918EF6DAE9DAE04 -:10732000A2DD217DB29CCAF279D33BAA183F7F66C9 -:10733000EBD44B0B302E51C6EF23BB8E951B4A98D6 -:107340001D1DE6FBEC21E3F530E2A92AAC3BF4433A -:10735000EBE85B96347D2817E25A15E6CA38EFC190 -:10736000A62FF69EF4EBB795E44D6136FF43F6BDCC -:10737000586D4AAA7443199E8B670207FDC42AF709 -:1073800013221D34CF18807B838DDFB9F6B84C20D3 -:10739000894FBBD64F89F3F56B136155B6F5B933F9 -:1073A000CCF59B66CDD486A4234DFED0737F68793F -:1073B0008CE7E7C7181DB9F8F96C7AE7FC541E4E44 -:1073C00034870B502E42698AE61F26F943EDA481CB -:1073D0007B2CE361B31DEBFD2CD7CE872EE479D057 -:1073E000EC7D6B0E96E514C977471F6C93B93E3759 -:1073F000527D306FD146D207DF65AC45F6D92737CD -:1074000092DCDEE853E9FEBFBDF3648A6745CF81B5 -:10741000EBDC768B14B1EFFF8F70BF3CFE4E427AEF -:1074200032D77BF09C47340474CEA56F3CCF2F6DD0 -:10743000831D35E7107C9334F77E56399EFB19EE99 -:10744000AE0AAE72FB1BE6E4F27C91FDB995BF4734 -:107450003A280BA7AB90352FD0A017F369A08A9FCD -:107460001F130AF9391B1F182AE7D76A0DEF0D15EC -:107470002049E7CF065D3FF0DE2FFAB89C6E0C2264 -:10748000DE62DCAF13D92E50D29ED46976E1D99D4D -:10749000C6DCA53F0813BE1306F277F7AC20D97BF4 -:1074A000EF752B647FBE7713FC06FD49EFF972C0C0 -:1074B000624BF52351FCCD536CBE7D8C597762FE37 -:1074C00097C6BF4FDB2A90BFE9471F06C721BD1BE8 -:1074D0005110F1F72C16337D8227094208E3B3D10E -:1074E00005D07509B6EF0E13FE7CF19FCE7F7D06A9 -:1074F000ED3F21B102CF6B890FE2FC9F89431EB69D -:107500009FF1BF5512FAAF1C7DE81E2D7904E19D55 -:107510000DD6AA6ED6FE6E85F3D7DD794A1AE394AE -:10752000D30B44D243C0174A4F62DF171F78BD1AEE -:10753000F33B17574CC39A383EADF7442D790CE90D -:10754000AF5A5B529DCBEA971FD549FE5E1ABF65C5 -:107550003F96671DE3659F9FEBF1A8C7B8CF072C47 -:10756000FE6002CDEBCD30D7679BE3668F290CC957 -:107570005719F7F27ACF173874C0B6751DF3D2E9F0 -:10758000DF3AD145D2270EF89FA0C2B0CF9F38F482 -:10759000600A1F851E7687F9BED086F966B1817CA8 -:1075A000B3365B7F1B69BE59263FE52D92691DDE10 -:1075B00065FA16DEE771369FDC42F77F66F29303C9 -:1075C000E7E6F2BC18CA61876FB4D977925CF65FC0 -:1075D000AFD07DA60E1F39FC332BA79F8FBE82F242 -:1075E0006259585FC853344C70F3C995C3F0D562E3 -:1075F000E8DB1F63E5C53258394C041D9AF3BB9292 -:10760000092E3EC9C4E7E27902BCEA9183BCECC210 -:10761000B7D67F0F70163B79B0753922F3730F0E12 -:107620009FE2EFB1E0F9B176D100DC8F1A73571AFF -:1076300011364FB936770DF2C3162191427E88CCB0 -:107640007E2B7423C3FB7BA3981689FE437DE553F1 -:10765000C4EFAF84C82EBB7BD66A8A4BBD7753720A -:1076600022EE2F9B18DE5FA5FD3C3D5AA45CDBDEBD -:10767000D13C6F428FF36732CEDF83FD3D6D974D76 -:10768000BB5E2FD563EBEB919B07A29C0F0E44F9D9 -:107690003EB549E950911EFA8A54CD9DAF7C897D53 -:1076A000BFF0CD113BAE78BA49C7F8C4CD11DEEEBC -:1076B000DEFA4ED25736D5EFA1677E6D1A303F2ED7 -:1076C000586AE9A857A87F5E20E03E0BE7F3783BB5 -:1076D000BE6F70E96B9FB2E5B68AF700B179AB8DEA -:1076E00096EEBE77561585ACF703FD24CAFDBF6A3A -:1076F00023D07775EFFFA3BC84FC1243F81C961BC4 -:107700003BE87763025DFC7DACC4146E70F51BAB87 -:10771000EDF4EC8FAAD82B933D54079A85C69DDCD7 -:107720005B8D7EB7F6A5C10ECC57CEA423FC7BD5CE -:10773000450FEA9FAF24BD088E70BDB4BA5825FA34 -:107740006DA95376A05FEF0FB12ACA536FB2F196BD -:10775000391F8CAB334D8FFC64969FC7D7ADC93CA6 -:10776000BE8E658CAFE313E3EBF8C4F83A7EC7F83E -:107770003A96BF556F5219E3EC58C6383B9631BE66 -:107780008E658CABE3734FFD2A7AFEA03E45DF9FEA -:10779000ADAFA3F225B6DC8452FE3B5FED5F544CE7 -:1077A000CC8BFAA1BD3EFBCCA5AB7E8E7E40881A69 -:1077B000B85F070E36BEF213BB4CF75FC78BF3D131 -:1077C0002F093111309ED01ADFC674CC81F905E43F -:1077D0007B41A778BAB50AF31977460E5D2A33FDC7 -:1077E000A1247E4B551E2BEF8A1C6DC5FCD173F571 -:1077F00086E53B5C653D327DF5D3DA407962D90E92 -:1078000039C8BE3F79F7CBAD28070231AEF77D2FDF -:10781000F2AB4B1B1849741533C506E558919246D7 -:107820003ABE01D76912CE83EB2D9F80A638E6EFD2 -:107830004DD495E9C87FAC7E17A7FB91D5FF2106F3 -:1078400061669EDD6EA87A62F988EAD1F9DBC1EA49 -:10785000E17761887E5AA049EB61B06FF1F1FDD507 -:107860002AE0FEDF761FE7FBF6007F4EC8E1F4F763 -:107870004EB4EAAE287BDE15E5EBDB1EE0F70EF436 -:107880004D11E9F778A04EF827ECE70B6341C3BC34 -:10789000C7E9538AF351FF3F62D3C3A48911BE6F76 -:1078A000FFB34AFBF665139F6CCE63E549FF6A1888 -:1078B000B80F6F012388F7B65A5B45CA23FA66F9F9 -:1078C00039794B58F50B667E270FF5DEE9B6DC49B2 -:1078D000DBF64943CB8D13D13E78EF252EF78EDBB7 -:1078E000E3ECF0F5A4683D6786E91C054007E9254F -:1078F0000D7199F2BFC431FCA9F8B46BE85ECC16E7 -:1079000085EE6152FE345B257FEA077EFB1EE21E98 -:10791000D257944052CB65EF3B2C91FC0F4D5A301F -:107920008DF7616D094FA7DF65B0CA648A876D293D -:10793000E3719D50E42ABAEFEA2BDD01AADF12566B -:10794000290F385DB6FB40550C9FA286FB7EDA5CA2 -:107950004AF7535A9AA8513E31FB177D5F13233FD4 -:107960000F9D2BC6EF6B781CC237FA20959B3EA566 -:1079700051FF60E7ED93EA25E2EF4424BABDF7CD6D -:10798000F6FDF442F483ACE6E752A66A4BBB9F6374 -:10799000DF9B4D3551CCF8A1457B776F08CB2B8011 -:1079A000E2A4A129AF3786B0FE0D9AC1F3B0F83931 -:1079B00008B0EF376E2E5BD6FD1FD8FFF2104C32A9 -:1079C000B07EB58AFC0ACDF002DE475568EB33A1E4 -:1079D000DCE902EA632DB574ED2683CF7B7EA03906 -:1079E000EF7215E9465A9C47E3B480A9627DAB5615 -:1079F000A67DB130AC76A1DFA0D0F63B38F2203FB7 -:107A0000E53A47C0FE37768DEC396730FA066FB934 -:107A100020E37EDD0B6DFAC9C45BE63CF363CFE483 -:107A2000223CF96BE844C459F0DF1B9BBE04E735E8 -:107A300046DB2BEC28279346D3F17E714835B8F30B -:107A400030FE5A78A79635F7203D4CD565D0195EA3 -:107A50002E84BE46EC7F8B4DFFED45DEFDF9886D33 -:107A6000D7303EFD7C7426C63344B05CFD63BCC396 -:107A700072C1734E7B9EA73CA963ACA7FEE4EDC523 -:107A80009EEFE7A5CFF77CBF60D7744F794AE75CDC -:107A90004FFD0BF75479CAD3BA2EF7D49F7160A962 -:107AA000A73CB3E71A4FFDD9AFACF47C9FD3BBDA48 -:107AB000F3FDA2DF6DF0942FEEBBC353DFD1EB33A8 -:107AC000F7CDEBA37F993E8FBFFBE33E4F9C692F21 -:107AD0009C756FCE9F9B748CFF4194DF932BE3FECC -:107AE000CECA1BBEC8ED2E75BEA1A3BCB9DAA6CB0B -:107AF000D579E63A94AF955195F60939CCEBC9E1C1 -:107B00004B491F99B09DC9A919648FF57FC7387477 -:107B10007BBD35BFC4E5AF0A681D80F95F95D11AFA -:107B2000BA2FD0692F6B26605EDCD5519DDF73C301 -:107B3000AC59BA074067ED5DF362F61F5D1DD1C712 -:107B4000EC43D4EBFBED3F3987E2BECCFE23FBD008 -:107B500008727B104E4BF4DDF88A40F7F333FB8E4E -:107B6000ECC367C2CC3E9C86F658EF1694437D3F2B -:107B700093298EC8FEC8FE2B67F6DFE65CB71FBCF4 -:107B8000B7089F69D0C6E2B35BE9124717913D7809 -:107B90001FD2F36736BEB40AFB9D52CEEFD56B1FE2 -:107BA000551B473DB9BDA893F8A4AF48E6FB909C90 -:107BB0002875FBF77E6CAF7748FD26D9A16C1D4870 -:107BC0002E3BEBB045E84DE3FD85D61783E4EF9EF1 -:107BD000F05BFF11E437B5581D87F97FC63EC5C479 -:107BE000F1EEB5F15CAC4DABC29F792C892FD98BEE -:107BF000CF7375A68FB06769E93D7BF1F974949FE7 -:107C00005F3DDF78BA0A658C3A9FFBADE5A94ABAB9 -:107C100051407F3383238BDDD1EF9F886EE7F7FDE3 -:107C200094C86F20FDA1D67F864DA1324FA5B871B3 -:107C300000E942A027D153400ED1FE12C043A858FC -:107C4000AE10D218EA42FD15F3412BF3B6131D38DE -:107C50007A2DEABB496E1FFF18F11AABF5AE7F48CB -:107C6000FD16E1A9D93EEFDC9EAB1FAC62E3B6176F -:107C700014E7A1CF16FD294B5CF2679FBDEF3E9242 -:107C8000237AE4CF6CCC519839A017317ED82E9E40 -:107C900083F02628BE1E3828913D1FB8B3837E5F2F -:107CA00035A0593A90FE6FE9D86F75F172F2FFFD79 -:107CB0004F6C3AE9C181BA1F65C55BA0570273C614 -:107CC000E0F88C9EFB00E903302AA8E33E5B170B2B -:107CD0009A3BB2D8079F8D70FFD9A6098E3F3341DA -:107CE000E75D5BD0DF16C6AD4D15314FE7D69F156A -:107CF000EC74DF07716B01F74F0E367E80D999491E -:107D0000177C9B58BF28C75B4E2FA9A1FB54719BC2 -:107D100029C7F3A0653BC84F6FDB4B9FB5F17A7362 -:107D200084E37182020B76A03CC963FA114369A512 -:107D3000ED5771FC2FF11C1ED7372C90B85FCEE7A2 -:107D4000EC5BE219BC8746075D99651FF127159822 -:107D5000EF6BECFFBAF15CE039EDAE7D0E703FF0F9 -:107D600096276FF796CF4B7BCB4C8B7E19F58065B2 -:107D700000DCAFB1CBFB3D0CA60FE328639DFBF30A -:107D800013FC9CA0CA2040FA2EEB4C777F8DCD2FA0 -:107D9000E1DC7399715FFE94DD69D25FAEB07FCF95 -:107DA00023F31EF7B1F8FB1E53695E9E7D74BA4F34 -:107DB000227F03FA890C979F68A2A67BEC2AC7DF73 -:107DC0009329D783C7EE01F685ECF5A41FEF43D5C1 -:107DD000CAD0AFD05A78D76F8F970FF8575AE5D4DB -:107DE0009BC7C97FC9F4AF18F77FA05FFAD69FDDA4 -:107DF000F6DFC75D7ECA77A2C9A9E8CFB87F226F38 -:107E0000EFDC97EA9CE77BB7467E5ED0391C4917CA -:107E10001CB7975A977175253D06FD438E7FC5F1B6 -:107E2000235C9367DE857CB7C53892DAC7FAADFA72 -:107E3000951FB09F85D2C103F528EFC6CB942FA222 -:107E4000CD5EF34810FD99F89D95AB8AF4D1C41F1F -:107E50002FFAC89FD066F3BD732ED5F1C77CC2B68A -:107E6000032ECB71F4282B689FC708A29E7CC12EDD -:107E7000B6869EFD90FB031DBFDF944EEFF7F3F136 -:107E80008837F93D77507E933187E7378D5A9EDEEC -:107E90008BEB7CA1BDCE18B7AA9C35103F1DBD222F -:107EA000BD17F5D0A9769E52D98BCFD34FF9825406 -:107EB00028217D9D8FF949AC9DB15FF69C0719057E -:107EC00002E5F98C3A2A1969D6CFD467BDDFCBC059 -:107ED000552E42F8BCE5CCB81453B7DEB95EC0DF0E -:107EE000454D0928CFB6AE6036022BAFCAB1F38B31 -:107EF000CE8573916E174A6103EFCDDBF00B89F2EB -:107F00008BFDC727FF12E3A3F012CFA7D4CEE1F178 -:107F100056EDA792C12420682198362D3C10C7FA4F -:107F2000EA1903EFD0EFF78F3DCED61DF7A12798C2 -:107F3000DD5FE2433B5EA37227B3FBB1FC0CB3FBF6 -:107F4000F1B99BD9FDF8FEBBCCEEC7F21E66F7E394 -:107F5000F307CCEEC7F7CF32BB1FCBFB732BC91F88 -:107F6000DF83F7194DC6DFB5DD4DF98C6DAA4F43A0 -:107F7000FAC994679595B7AACB187E378717521C14 -:107F8000A56A21CFA76FCD5948F674BF9F2EC3CFE6 -:107F900039E0B7EB151CBF1D1E6D8EDBF66CBFFF05 -:107FA0003369D0BD05C3F7633AFD90FFF4AC7E6C36 -:107FB0003FEADB5FFCF5D79BD8A7B533B7B5078B96 -:107FC000F13C4F8A7FB7F30A337F4F6BEDEE06CA61 -:107FD000F353C61C4DE1BAEE2E0F93BE81BFB7849A -:107FE000723BD34E74ECC34C7DDC7966EE87997995 -:107FF00030115B2F192E2FE36E5F8AE2D656039362 -:108000002FB85FD4A7E7BFEE3BDB6F3B56CBCB3837 -:108010007FCCF3AEFC07783E5E3B2435F7FC9D73C6 -:108020000F64F31573FFA1DB6F1B2C49D3BD0CC18B -:10803000B049FAA2C0F448D22BB524C5015B07F9B8 -:10804000DDEC376D39D130E62ADAEF5B5FF491BEB3 -:10805000556DE7BF358D51A9DC3466569CF2262359 -:10806000B3D4DE2CFD6C88140FB9BF4A6CFFD787E0 -:10807000D8FF253F3FEFD5B4778E8AE7A2DAC32B2E -:108080007BD06E6F8FC7C8FFDF3D6696E7DE712934 -:108090005E41F7544861AE674B7195F46C19E75F28 -:1080A0003650DFA9B72F87EF238CCDC98F190877FA -:1080B000503DBF9C30D1DFE28FF1FC62BFC6E3854B -:1080C000C11211D42CE7309ECDE1E7ACDACB921A85 -:1080D000FA75DAE3329DE768D7A70F166F25BDE87A -:1080E0008F3982877E9B6CBF43D32A85F4C2445D5F -:1080F000AE569D4FE711FA90CFDBC38D2AC65F9530 -:1081000031E543F6AB68BCDFFF03837E3D1F008093 -:10811000000000001F8B080000000000000BCD7D58 -:108120000D6014D5B5F09D9DD99F24BBC924BB9B80 -:10813000ECE68F09241A34E026243168C449083C4F -:10814000F4212E021A5A2A1B1045050968EB6AB55C -:10815000D9908010A4067F2A4F2CDD58B0F6ABD6FC -:1081600068E92BAF455E50E4F9839AAA55B0A8019F -:10817000ACD53EB511A4A5EAFBF8CE397726D9993E -:10818000CC26417DEF7BD832DC99FB73EEB9E7FF5B -:108190009E7BF7D429F87321636D7B52545609CF27 -:1081A000A58E784A1163E1687976C324C6BE951519 -:1081B000FE22C3CF98C3B3488EB919B333A676C392 -:1081C000F394D64E7F7A658131A827CABF98F29E74 -:1081D00077E877FD29A66F661168CF8AA5F7FB5C63 -:1081E0008CD914269CB24199B9E5F7CF66F4E7948F -:1081F000887FF706C29EE4FD785CBF9CF2DEA4A1F6 -:10820000ED9697F5394485B1F5DB3AC30CCA9F0B5F -:1082100050A842B8636A1ECCEB869D2B59A48CB142 -:108220008D52AF4B0638367E292C0C970DED7F31E1 -:10823000CEA70A7B95620827FCB19D3A07FE5698A7 -:10824000E2A8662C0FDF8CC527FF0EA3EC3905FDD5 -:1082500097F740B9548307FE3FE93963B9AAD75865 -:108260003EF780B1CC58C81E9EC0D8EB2DD0E999FE -:108270008CCD39F4E12196CED8DC58E8D9A77C8C96 -:10828000E5AAAE705C666C1E0B3DFB3694F31AD308 -:10829000584F0806B7B1A5B82E30CD378B01BE4672 -:1082A00046B0B2BCA5A98CB906FB9F2F67D23A3560 -:1082B000F635CD641319FBE1AD6D8C413FB17A21E8 -:1082C000BE1DE09FDDB06DF638783E50692B781802 -:1082D0001B45ECEFE1FC5CD0D929986FA66DE598C1 -:1082E000B1503F3C354D68837A3F3CEFACF5C5500B -:1082F000EE9D5E1242BC03BEDE1B980FE07F5E98CF -:10830000B7D7C77FA5F2D8DC71F0DC52F9E46C7CFA -:10831000CE49AC0FFDCDAAE96A75407F972E532A4E -:10832000B0BF7083B17D5EADB10C90F3F9C0BFBC3E -:108330005943E11D091EF3F87A7F0FB428847FF6B4 -:1083400025D003E0338C9FA07D58EA974280E7DC7C -:108350005A418D03DDE4A982DA65C10F1D1A3F98E9 -:10836000F12FC63218F259FD3C31DE0155725D76AF -:10837000C27FEE4C21AEC0F8B94BFB7B4E41F97287 -:10838000973D2EC2F7ACCC6E01BF3FB08CB1CE2270 -:10839000022FBD2E617D1F70ADB117C2F7794191DB -:1083A000D9800E58ED381A8FE0184BF838C2F1E139 -:1083B000227CE42D0B3DFB6318FF8A1AA72C42FD9B -:1083C0002B1AF9771DBE8D12D0197CDF0874162385 -:1083D0003A938E24E267CEA1E5CB911EE798DE1793 -:1083E000435D9CEFC7930F9C5108702D173A67A40B -:1083F000012829F666C670A1018348D73A3FEA787A -:108400005ABEA395F83181CFECA7909FF1DFD984B4 -:108410001AE2B3A75DBF92516EECCEECDBC2808452 -:10842000B7CA2CD690CFD8BFA7F69F2D4079BB7C7A -:10843000F9BA7517C0F794FE5FB072C69CCE6FCFC5 -:108440009891504E4DBD86CA3E6D1C98428CAFF738 -:10845000C0B8441FFF2973F836A86C930865C92675 -:108460006F0A150DB6CBC276C230EDC26C9364D1E3 -:10847000CEADB7033CAD85F54BD5E695AA7DB76982 -:10848000F0248E2F21DE64C52DC07A48D32519E94A -:10849000E5EBC2913DD2BC236C937DDCD0760076B7 -:1084A000AB0EBFCD1AFE387E4F1CDF3E0CFCDF3416 -:1084B0003E46EACFA17D3F6DF8A0FAEAECE4F34531 -:1084C000B8ECA8AF14C56D4BE8E7AE3DFF78F11CE2 -:1084D000205E693E0BA5401F925D954340E765F223 -:1084E000BD2EEC5CCA6C9023C00FEBA1ACC2FBF5B7 -:1084F000DD9D2E05DE9715DFBD0E89BEAC2795A14B -:108500003C98C0E4CC47A1DF09B2C47A70D52ED81C -:108510006B4B8332BB84854AA0DF8C3DA9244F324C -:108520008BCEFBA900E36666BA546C9F9659FD5347 -:1085300046F4C11429011F6975AFD7A7215CB3594F -:1085400008595112E2AC0E996C3CF0109433A76DAF -:10855000630D50AEF8D8A388C8D312D7771DD81EA4 -:10856000F5743BDB87FA25A8C99F750E7913E98F4F -:10857000EB2486FA236DC2BD02C2F3007425025FAC -:10858000969565CD6E8072D97E5B4851703E9D4256 -:1085900021CE272092DED2F1A9CB918A4F7B38D30E -:1085A0008F67F1ED007FBB3DDE83F22A36F90A7951 -:1085B0003BC0937B5582BCC6BFFA010708EF4B97BF -:1085C0006DEF2842FA96DE4BEC2FE3D3780FCA33D7 -:1085D00056D718C6F6BE999241FEA76AF22CD5A4CA -:1085E000075AB2EC24CF747DC054499161DE8236C3 -:1085F0006FF68330E903270BB91C64AF2C203B4492 -:10860000607DC2A934983F5644B80BF83C86B4AF9D -:10861000E6ED5920E4423BC799DADC8CF5E163567C -:108620002B2057B82E5545FD2C38982B5801F3B602 -:10863000B14837D049ABC0242C0F8ED7C3703CA7AC -:108640002BAD1DEDAEA75D6D36C45FDB73A03F6043 -:108650001E77D85923DA056D72C89505EDA39AFDEA -:10866000B6AA7C6C0E963380B67BD16E90C232D2A5 -:10867000E52A7F710E83F7E9DEBE6FA39CFDA7CCD0 -:108680005FCF7015801CAD873AE781DCDFF4F8BA64 -:10869000582D8C77328F2909769E536A66684F3938 -:1086A0004F161ADEF7B4C08CCE1C2CAB6E5B038E5B -:1086B000735DA64278AD63723BB6AB03642809EBE9 -:1086C000E23C1964CA24ABFEF30DEF7BC04E529C12 -:1086D000A3E93F8D29A589FD8F4BD2FF19A6FE6521 -:1086E000CBFE07FBF51AFA5D2331B2A3633E37AD2B -:1086F000BBD92E589D59BF2213ED51276BEEB6B052 -:108700003B5B336D04F71D81E65E15DAD733607C81 -:10871000A0930BBF3C2232B26760A5805E58BED4E6 -:108720003F40C763B11EA75F5B4C6028972E94EC57 -:10873000063E99C28C65B35D54026B8DE3DA3C95BD -:10874000BD483FABFCA98AD3027EFDD9DBC2A6148B -:1087500097C07C53C34B19F0F10399FB5C6B02503B -:108760004EE774F248E61F67A0BFD02B70FA5BE3B8 -:10877000B3115EC2F5395D6242BF61072B41B91882 -:1087800046FA76737870FC5E7FFE431D16E383D84D -:1087900035D80FB355614A71C2BC7A353B7860BC9D -:1087A000A9795DC80703E33959158D2702FE13C760 -:1087B000CBFE6AE3FD1EE7573638DEECE9C6F9CD9D -:1087C00076C834BFD91AFFEAE3FD1EE757F415C691 -:1087D000C3F9258EF74FC6F9CD76CA34BFD922A783 -:1087E000AF81F1B2BFDA78BD2DA56407DFE100F9F2 -:1087F0000474925ABEC3350EC6BDC365970565B0F5 -:108800005D5DDD8DAEB9A87BDD53A7FB619CFA6988 -:108810005039177B993ABDAE98B14D02A78BFFDC5A -:10882000F4E7754817C767AE2A257DA2D9D79762A6 -:1088300055D0C7974A1CDE59F9EE786B021E1F000F -:1088400039A2021C0F02BFABC08F5B812FB11C6F1E -:1088500009D0F321B0D7F1B90DE0C5EF0FB784A867 -:10886000FC484B0D3DF57E4A6BB8DD3EBED6DA6E58 -:108870003F238BFB7D9B82F2FCAB50AFD5A586508E -:108880002FB29AF3999A6857B3E6A753E0FBC6CB89 -:108890005939EAC6333673B87D0DD964B7A796EF58 -:1088A000ED6D81F21D925D41BD7C87C26658F9CDA8 -:1088B00045A867AAD05EE5EDD9F9DC0FF385FBF694 -:1088C000A2DE9B83763AE0D53FB76F2FFA7F978180 -:1088D0005D4E7A991DDEFB367C7F1DFCBF0E2C8B16 -:1088E0006E264379D61C3F8D0F7FD2EBB2D17EE747 -:1088F0007FEE99798CFC8A700AD70B3E36FBD93D06 -:10890000086FC8A1C4A93F765F18F940B52B1D2494 -:108910000AC276D4D37ED4D3F0BDEEB093D910BEC4 -:10892000690E926B73E71AFD864D293D32DA3F9B43 -:10893000CA7DAC15FABF6CA6F1BBD3C9F92D6CF298 -:108940001B6699CA2021B9DF2D2EC8407BFF0E7C03 -:10895000357928DEA2875AEFD89B40A779591E1F88 -:10896000C501CE6067A03C3BC1CAEE6AC08FF95911 -:1089700064AC98DBFFBD2576C75E40FD2B28F7AAC7 -:1089800090BEB9DC18CA1F1C9EC95ABD075A7AA7E7 -:10899000BC5732085FAE1417500FE42D85F709F36A -:1089A000957C7101FD1D263E5A8EFE8D791E0F08A5 -:1089B0008F0699C578FA339749EF235E7029519E47 -:1089C0009BE73B79C87C6B5F296656FCA46C427BB5 -:1089D0006ED67362A85519C4873EFFFF69BE3AAAD6 -:1089E000E919A6FA580FD0CB2B40EF1DDC8F616838 -:1089F000A7EAF40A15C87EBAF452F88E74A1AA0543 -:108A000088CF57C6F66FBB1ADB81EC68437F57B738 -:108A1000837A0EDAD00EFAAAFD5E7A9D83EC2DC61B -:108A20001AE4F74B07FB4BB63ED8EFFB09FA73C0CD -:108A30004EC43FD59AE843185B4301B2076E01FB71 -:108A400018FDFD68C387523AFF7E24C14EC53F47DB -:108A500012FA6BDBF3734101B8BA5ABAA7BC674F7D -:108A600090174B65DB1AB4E75AE302C5217AA01EC2 -:108A7000D80363972AB676C0FF55D80FD2A749AE60 -:108A80008F6D877E12ED94DAB9F2A3400FED65F594 -:108A90009D2178AEDFCCE3657AFD81B8992F46FE43 -:108AA000B99D353301E074A4FCE0277D301FB54D3E -:108AB000622953A06CE7F60E7BDB4372417437FFEB -:108AC0000CBF076220B770DEF5CD8F63396663E1B6 -:108AD0003678DE9FC6DB472597EC0C619CA47D06AB -:108AE0004E3F3318B92F0BF0B7263B95E4A0E31D9A -:108AF000CF4328A71C99154BD1EE5910FD7E18E3E2 -:108B000091B2972D0C5BD0D702CD7E8867F1B8CBA0 -:108B1000217B4F4126C05D17AC8F63BF43EA477F7F -:108B200040FD4D11ADEDB09D5A3F5B6CD672E10931 -:108B3000EDFB15CB9FFCF061984F5AB13B84E4B636 -:108B4000FE1CB643B00DADBFCB1FE94E8423A55824 -:108B500096280ECABA27A33DB7FE8B07BB1F079402 -:108B6000677DE126399B257AE24291A1FDCEACAA30 -:108B7000A1ED77FFE38D00AECFEE1446FA95B11765 -:108B80002F427F72E34099C5048C73666AE5D8234F -:108B900017A986F2E28BEAB08CB40B4439F99EEF48 -:108BA000AE8F617B819759EC7BBCBE9DD7CFD1BE88 -:108BB0004FB9F8A39FDE85FAA0DA417EE846CD0ED4 -:108BC000D2E13BDF2B12FD9CEF1D1E8F0735B9E074 -:108BD0001A3D1E0F5AE17177507D0BDFA7B06E0171 -:108BE000E938E50BD74DD8FE5F5A58F82A807D8BBF -:108BF000B2E3E77729D4FEB0151ECF0AAA47B0BD6D -:108C00006BF9919FDE0570787438CE65372581E366 -:108C10002FC3ADE78E6C2EE7E6F9B8DEC8D2EC4D77 -:108C200087A337301B9E72E58F6E9441DEAC2DEA30 -:108C30006EB48A3F9FF0DAA85D6692787B8697E3F0 -:108C40006D574EF87384A35D7ED285E3A70A2C8C02 -:108C5000F537D4F43121A1DFB37D7C1D006E9B1765 -:108C6000DAA54E662AD2998779E20CE8CC53C9E19D -:108C7000DF10789D29D0CE530A4F37BEEF23FE4731 -:108C800097830B351074507668F491714FC745483F -:108C90000F59A24E6F791D482F0E9B5E3FEF622C3D -:108CA0007765F172B92FAF23960F7AC6016D502EFA -:108CB000E43AC8DE31CF2F4783B7C3AFFABD7E0B8E -:108CC0007C3AFB689D364E708462B0AE536CBD8DAD -:108CD0008BF1DBC56EB2D7E07D633C61FED3353AE4 -:108CE0009CEEE5F6D6C67FB81AE316EB918C4E27BC -:108CF0007A4F9B4E277AADE9F41CC47F029D7EC655 -:108D0000ACE9B4DAAA3DD0E9B956F8309745A66E79 -:108D10006E0200A5CFA73F72176AAB7FAEDDFC38AD -:108D20003CA77CE196BC50473C83919D687371F9E8 -:108D30003E28F723D3B07F496EA6F7A23B4CFB3504 -:108D40002F65F1FE87F47B6EF566945BA3E8378CA4 -:108D5000F336F73BC6CBE19D72B13B12B7C0FB497E -:108D6000AFC4FD521F1F3F19BF94FAB8DF9C945F38 -:108D700074FACF0947108E91F8E5C2417E593A3A0C -:108D80007ED941FC9256C6F9252D09BFB09893F8BB -:108D9000636D112FDF728F8FF861807F622546FE31 -:108DA000899518F867DABD2554DFDC3E1DE76D8133 -:108DB0009798579F47B805E7A19E2DB78B646FF42E -:108DC0003194535DAC7F8F13F9B056086D87B7B3FC -:108DD00062BD0D2E05BFF7B2D9607FACD3E87E2B04 -:108DE000C283FE50B516CF927AD9659EA17CECA9BC -:108DF000EC298D24E0BF40C3E3E5BEF05D387E176B -:108E0000EB1B8F7669B275BA5783F7A6807AAF15D8 -:108E10009D8FA47776A2DEF1E393C39DF585AB1910 -:108E2000E58099CFA7DCF0DB0F1F1EA69F5F6B705C -:108E30003CA63D4F83EF1FF35AE9E9A0FA4B13DF3D -:108E4000570A632DF9FED756ED81EFFFD50A1F5F54 -:108E500083CF9FB6E2F307BDBCFF91F02CF9389E9B -:108E600025DFD7C3F3116D9DDE3A7D3CBF9504CF5E -:108E70007FF4FA4785E72349E4EB512FC1618BE189 -:108E8000BE00F23BFAEFEBCE8DF5E37EA8051CFFAA -:108E900099D88F4BE1FD8069FF9900743EE5F37529 -:108EA000A188055F42BB6389F0EBEDEEF5CA9A1F1E -:108EB000A1AC44BB7ACB3FBB693F01F4E0DFBCDF30 -:108EC000AC9CB7F92CE4F1141B974397DF73783D02 -:108ED000C669BE46FFE956FD3FAFD1D748FABF2865 -:108EE00041FF633F6679D7C5783CA5C31FC9F71119 -:108EF000BEFA2E42F9B4F5D62C01FDBA7CB5474036 -:108F0000FBDFAFE9978D5EEECFE8EDB64A3D828498 -:108F1000F59B65212618FA3B63B8FECC70007CE314 -:108F200011BECB7DEA59F8BCD73B60EF9D963D540E -:108F30001D502BB03DC8E94A1C5F3DD328A7F579E9 -:108F4000D8C2DDAC0FF50BB8DF710BBAF26BFA12B9 -:108F5000FAB980FAD1E47D954FA72BDEDFE9EA1B51 -:108F6000806FBA06DF0C7C9AE133E36524386F46E4 -:108F700038797F9725C299AC3FDDBFD6D789F46990 -:108F8000425C67E1A0BEBE12FB73ADB1C5986F90A5 -:108F90007F757D0D922915FBDFE2E071D42DCBEEBC -:108FA000AEC37C83AEDBE4724449EE52AEE7946517 -:108FB000851457BD56EBD70CFF407B47F7F8496542 -:108FC00034EE721CF7C25AD683722303ED048A3F33 -:108FD000C812C617B29C9D018CCBAE173A1B17A1C5 -:108FE0001EBDC84DFA9605E65AC6A7F4A71E7FD245 -:108FF000E7CD029523D46FA5FA725A6733DA49A3F5 -:10900000AEEFECB4B4AB7EA8D95530BFF5C3E235B2 -:10901000E0A3F8968EDFA1E3F0F5AB0B370B88EFFA -:10902000D4321812583235DC499BADB6E238EB43E6 -:10903000FBA914E885FA7BDD32EE37D8DF5A1DAE86 -:1090400007911EBF2E5C7ABDE4E3F17AB87F46F14A -:109050000E37975BF401CAC79EF35AEE1FE8CF3B69 -:109060005A645502FD734C5632305E7887A6071954 -:109070000B052EF3FCF7D71B9C479CC73B4DF5A374 -:109080008CD33D0BB8C8BEC3307C22DDBCE6E3FE0A -:10909000684776F8392E1F4321A46B28BF80F867F4 -:1090A0002E287BA8BC9FCAF240F965AA1FE0F5995B -:1090B0002C8F0ACFD0EE0FD44E1AE8E74DEAD73DF9 -:1090C00030EE41FAEE1B28FF91BEE7F3FAA31D270D -:1090D000615DF9FC7B459AFF67929A81FBA39747F4 -:1090E00017539C687EF45A7AAE6B91EB301EF77280 -:1090F0004B7F7B3B3C2F9FBF5846BB7FFE927B68DC -:10910000FF5EEFFF52F42B90DF156906D94545B697 -:10911000F036F720BF0DC2D1AEE599F535201DB967 -:1091200054D6DF510EED6B3E6D6F37E4397552FE4C -:109130004C8A227D9E1857D7E5E0C70EF573DFE90C -:10914000D1B169BE8CED85F13F7317C76344D7F584 -:10915000B215BFE8F34ED6BF3EEF647246C79FFE1E -:109160007E7D7185CCF37FE206BCA4943450BECFE3 -:10917000A58206A7C7A5F11BAF370BC679B28CE84D -:109180004341FA9DA5F97166BDA08FFBB12352E45E -:10919000F7E37E0363B75558E07794783BD0B23459 -:1091A000DC604779DC9D42FBF74CA638BF5EAF31EF -:1091B000C9FC2FF0733DC29C2ACD67C3ED1971B471 -:1091C0003B3634FD5AC6E04ADA84CFAA62F814FA74 -:1091D0004F2C42F972BB87F2311A9B4E54B526F4DC -:1091E000BFF0997F7361BCB771C26A3FC65D16322A -:1091F000E9B3C47C07F3B88DD11B886E63AD42A37D -:1092000095BFF56636E7EB85982223527F4712F724 -:10921000919B940A07C6279A62C6FD1CD0900EA4A3 -:109220008FC5EBCCEF13F67344EC9FD1BC63B899B8 -:10923000877A6F8D8DE86D0BE00DFDC0425097F879 -:109240007C333B4BE3C75EC2E77F373C6F66CB7C2A -:10925000DFCDC562695983749313E964A89F3C9577 -:1092600002ED6FFA3C7A7E4437E9A97BDD7A19F486 -:1092700016E03F5CA6D939C5FCBB0DCBE8FFA4F5D1 -:10928000EEB5011FAFB9EFE98B03E3A1BFB248C050 -:109290002653F905C98FF6172FB3D8D32FEC257BAA -:1092A000563E4B0801FFB7EF7EE1B902F2E7357B8E -:1092B0006CF70B648FE965C67A18CCA72B75A0AC48 -:1092C000BA02501E3B508E6179AB66C7AFB96FF7DB -:1092D0000BED649F8463FE043D59C7787CF99BD6EF -:1092E0008F5D81AB3A319F28566C237F2FD5C48F79 -:1092F0008FFA1D54AF28277237C233EBB67E09E3CD -:109300000D8EE0EB3E9403638A8FA96381FEC7D480 -:10931000F2341956CAC7ED2A5E45764397B62EF049 -:10932000BFD5A8F706D7A7D7B43E7C3DC295BDB43C -:109330003E9EB25E5A2F1B9629EEC7F7E32FA9E493 -:10934000F686ECE4FB0ADBFD9C1F76F8B97FBBC315 -:10935000CFFDD38CE2BB29BE9332C346F533B4A70D -:10936000598EEFF04B9A3CE7F8D81D8C74FB13EC48 -:1093700056781F2EAD44F9E6CBC27DD6BA62E926F7 -:10938000A4E79F68FE29ACD35DB44E45BED4085F08 -:10939000B7DFF8FD16EB563ABA757BA32542F22AE1 -:1093A000D9BA5D3E5F0C5BC5DD5ED0F0F049E39F4E -:1093B0007E84D359EEEA77E03ECCFAE24D86BC6A71 -:1093C000D78ED93D980BADE755AF4E4BAF45B96D34 -:1093D0001EF78D2FFFC387F89DF90FA7A57CFC54BE -:1093E000938FAFB734523B586045CA2639C078DEF8 -:1093F000CB409E9870CA49D37B03F3D0AE24D66786 -:109400006C6EF830ED572F0A880CF7C71732635E81 -:10941000198BEA79C13C0FF60D095C5340E11B3111 -:10942000210498624DD26C5DAE18F2C3E6CD9DBDAD -:109430000FF7E1176BFBF0205F0CDF9798F2C6AED9 -:10944000686C0A3768DF8FD3DF71C2D35C85DB8D30 -:1094500073DD6ED2AFF3C2F3C30D09FB716FFE97DC -:109460006899877E41B68E9770B8A164285E16858C -:109470000587AC8C8C1F333EEA248EAF260D5F66C9 -:10948000FC98F1B078EE6C5A7FF3FCDF7085093FF1 -:109490006F007E305FD88C0FC6229720DDBE395F0B -:1094A00064681F4F1767DA314F60F16C81617ED1BC -:1094B00012164AE7F9C1EAAC6909F09AF168C6D711 -:1094C000E2A758A807FA5D7C9F87D6EF550D3F624B -:1094D000CF5F695E619857079FD7119EBF2AD3BCA3 -:1094E0002E53CB9FF5C1F7483B485BC54A8FF0F937 -:1094F0002C82F974C843F5C90956DB8C74B2C49444 -:10950000B76086CF0CFF4C94839387EEE357646B70 -:10951000FBF8135948DBC7CFA0630D21FFB0790BCF -:10952000837CCEE96B6174F6C078D8AFC022036546 -:1095300019F03BF379EFC679F0EF550151C13CC109 -:10954000D9F3C7ADC1F9875938A3A708EDFD7E3B14 -:10955000CA91CB1898B1D0EE429824EADB70430A46 -:1095600095F57E8F757E6A273D1E61CDDB69FF5DB7 -:10957000C9983B21B97C591570D078663B656679EE -:109580004906CA0B333E743CCD43BCA4115E269EF3 -:109590000E5E5E445D85FE2CC6D1601DFBAF65ECA2 -:1095A000A1F2C1FD6396AF727B329BD1FEFFB5D9AC -:1095B000999ADDD14C7187059A5E3864678D4FB8F2 -:1095C000F93E7245827CFC56B0EEDAEC043B55DF86 -:1095D0004776B33EC2DF952E778F3891E8EEA30130 -:1095E000FA20F9A5E76B46285F53CC58A6505C2CAF -:1095F0002D7D22CB00BB98F179831F7353B61FDFFB -:1096000017C6D10898F9FC4FD7CD5306D76DFD5535 -:10961000DB3B511EA72CF9558C3A57783E479AB63A -:109620006E75DABA0DD8D1A5F03E01BFC73A353B09 -:10963000AC548BE3E31F281F2B56E3C3F9AFFA3A70 -:10964000A69482FF61C823EC247CEBEB094E443FD7 -:10965000F265242051CEB08DB9C83F8EDCC2F33103 -:109660001632652BE6072D8CDA8F25F613094A048E -:1096700047647D8A163709513F8B82BC1F56CAFD4D -:10968000BC01BA8F41FB84FC479B0B4C496C9FC9C2 -:1096900042E83F417FD9A8EFD9BA8471C60E1D3781 -:1096A000597FE676A2B67F2B3A43A150829CDEAE6C -:1096B000D9CFC70295DDB6B1C9F1B7C8E555A584C4 -:1096C000BCD8234157A3555C4CEF4FD7DF0376221C -:1096D000BBE6C5443BD1ED687AF1B90B12EC44D638 -:1096E000F422EEFB7F553BF1E5ECA617DB617E7FB4 -:1096F0007FFB9F287FFC5833084CC0A3373A951D49 -:10970000F5A27C90497F1536824785C9DF92321ECB -:10971000E93D259AA74A09F9B26F662B04BFB758ED -:10972000A5FD3268DA8DAEB8570A0988B7BBB5B85F -:109730001910EEF8D99EC4767CDEFA784E974C70FC -:1097400038F4F158A895F2EB6732D2237A1E88CE0E -:10975000D77A3F47B38DF1BA51F0F3D16CFF507E09 -:1097600016C5E6776F4739F1A2487ED87702B7D0A1 -:109770007B733CE0E36C6E1F8E11231FA35CE86DCE -:109780007CED3B3743BB153B9C2154C3CBBFF7E17A -:109790000FAB14C4135FFFF94B16DF5785F32A9103 -:1097A00064DADF28E0711847AB40FE6B4A9123BCB6 -:1097B000039E877D75B93909701DF6355079EC0C1B -:1097C0000ED731E8B343C1769B1AC95FF4F07DEF41 -:1097D000638A92C148AE30B22744277FBA73785C5F -:1097E000D89DC3E379520EC7B7EBA4408B8474DDD8 -:1097F0008CFB16528CF2A05D27257AEF10044B7B70 -:109800004DEFCF75128433E22BCDDCDE41EF713E9C -:10981000D85EF432837DE3CFE176B27F008E340EE2 -:1098200087D7DC4F3A7FAFF19F198E15D9538388C4 -:1098300097C33E353787C751B81C76BF70409838FC -:109840001A79CCF3F52F094A2E8AEBDD2EC44B4052 -:109850003E75941E5B4372ABC8D58CE7A412EC270F -:10986000819FBBE1E72A06EDD3FE69732A317ACDE9 -:1098700094074243EDAD772B4FCC9B8305EDFCC4A1 -:1098800095BAEC8D4119ECB977B4629332762D8696 -:10989000FA2FADE5F6D962B4CF4224B70C7697D94A -:1098A0003E7383BE9F0374B12420C94817663BAD45 -:1098B000A3721ED9351D60D760BEF6503B8DCB9B81 -:1098C0003BA336A642BD976B45F2335E2EED7BFE81 -:1098D00042D417357685F44569FF9D73E8FB241A59 -:1098E000C7ADF977509F9F7708A5C54BE0DD2BB535 -:1098F00047DD8B13D6FBE59AA3E3D12FD89A24BF7B -:10990000428FD3ECBD95E77FBD7BAF107722DE6E33 -:10991000136DD8EFC2720FE5AD4E13DD34CEE28D7C -:1099200062DC493854D3A7650FDA8D4CACCD7E0D7F -:10993000F170979DE1F9C1829BFA0C76EEC2A8D135 -:109940009E8B3483FDA39CBE1D68B6FFCC76CCF203 -:109950001CCD7EA9601568BFBCDCB2931D2D19B467 -:10996000636625D9FFD6ED98F36CF5DFD5E899F657 -:109970000F6649D6FBFB9768FE290B717F709AF83A -:1099800011ADD7B190A420FEDCB7BC40E73ADCFFB4 -:109990002586ADC6BB33C7A1EFC791BCDD5A914642 -:1099A00079D77B6E3D2BA78FD64BB9BF16D7FF0556 -:1099B0003BC9C164FA2D252AB2629898272AD05350 -:1099C0005FCF31D11496A81FC624C953F8710E9FDA -:1099D00087FF3666433F3B33C6542BBF54AF07FE69 -:1099E000E8748C5143FD9E4C80EF86621BC5FD756B -:1099F000BF34C5CECFFBDA77AD8CA17F3A06E0430A -:109A00003814800FE57051348DCA63A35E7A8E8B53 -:109A100066D2B3389A47DF4BA2E3E87946B488DED2 -:109A20009F193D9BCAA5D149F41C1F2DA7E759D109 -:109A3000F3E97936E82DAC5716ADA3E784E83FD3B8 -:109A4000FB89D139F43C273A9B9EA1E8B7E97B79A1 -:109A500074313D2BA24DF47E52F47A2A57466FA4FE -:109A6000725574253DABA3DFA7E7B9D1367AD6444A -:109A70005BA9DEE4E8062A9F17BD879EE74737D13A -:109A8000B336BA85BEEBFC9CA6D9D32F05B6C994D4 -:109A90006FCF7ACA503E26E3C3439A3CAECF51F70C -:109AA00022FDE9F5F66BE70ECCF50EE40C9F77F39B -:109AB0009AB65E9F848EFC088FD3EAEBB63E307C6C -:109AC0001C8195F946D8B7E2F37B2647E1F42B7564 -:109AD00092BDB1B599513E98A7B2574079D3159030 -:109AE0006658D1913BC0F3C08A722247517FB88338 -:109AF000EFEDC5FDA84B63BDBEA9482F215FEA5419 -:109B0000E86F4CBB8DDC6B85C90296950626F7B0D5 -:109B1000C1780ED85706BD260574FBAD77E62484C0 -:109B2000E7ACE20AB25FB5FDE4FDB78E65E8776C9D -:109B300075F40812CACB558C25DAE15BD72E7A383A -:109B4000F19C8614E0FC39661D7B1AE364459D4A4E -:109B50003D9E271CB7597D1A533C4BE291FA54287D -:109B60009FF948EC697C8EEF8ED7A7C1F3EC9D3D41 -:109B70004FA3F899D0D357EF86F239CFB16730FCB5 -:109B800054DEAB4CF54079D201F519DC26A9EA8BFD -:109B90004C4D57109E785B3AC0B3F51D30B4A05CB5 -:109BA000F351A7086EC9E0FA83DDF644C2BAA414E3 -:109BB000F7AA22FC33FF26B91CE5EC56A92F25B3E2 -:109BC0006CE8FA74E1BC719EA057B66BFBE872C2F8 -:109BD0007A8402821E0FF40512E2815DEDAF523CE1 -:109BE000B02B55AEC35057FF34263FA4201D733F02 -:109BF0002175CD58D24F3ADD017E0DF6A414E074E4 -:109C0000B775C0DEB4C66F08F15BF5BF07BFFF9E36 -:109C1000A3C9AF24F87D09E7111C998FEB029C2F93 -:109C2000818F2F085425AF77B5867F339EB74AF2D0 -:109C300059842F37B3C5CA07D7AD49A3EF91F0FABE -:109C4000EDFF65745B13181EAFACD2CBE3CC5A7E2C -:109C50005A3279B33FC93991E6C01039C7E3A5320A -:109C6000C8B971C9E55C6D6004F99524DFE1F6803F -:109C70009EEF10FE7E601471FD3B6D721DE6BBC44D -:109C80002632F213C0BE6CC7FC9D3131A582B6B13D -:109C90005028231E2BCE263FBD08EC0DA98261AAB9 -:109CA000630F3E2FA9CCB42D2AC3BC068DDFE4A6DA -:109CB0004022BFE9FA7E901F75BAC8EAA273164027 -:109CC000AF984FB84BC3D3603F3C1EB1F696DCAEA5 -:109CD0008E0439D815CAA3B25E3F19FDBEA57D0713 -:109CE0007941FBFD97D45AE79BFC6B40D4EC9C7EFA -:109CF00015E93C3685C974DEB9FD08C9A74C904FFB -:109D000042110F0FE1F8F9D1D487314EFBEB40B689 -:109D100026CFE5D4CB3DFFFFE8B9037C75E2A75A17 -:109D2000790F9EAB18037A484139590BB057A29E60 -:109D300073D0BA2B8CAFA352CBE23D02E1AD07FD4D -:109D4000E6988D9FCFD8EFE85649EF383265CC3F83 -:109D5000D9E58FEC0DF893F3859CA694E3A2FE6100 -:109D6000F37533DD41CCCB9153B1FC2A94EFACC1F8 -:109D70003CA13EA695EF744FFEEAF1873F04AEDDAD -:109D80008FFB54D501F535A467A0EB3F205CEA9921 -:109D9000B244F1E151EE3FE9FC39C84F72B9CE4F00 -:109DA0004D65240FDFC5FEF5FE92D937FFA2C9CF5E -:109DB000FEC0F0F68D4EF7A76DDF68F0BE3302FFF0 -:109DC000CF7CFEB5CDDBD860FCCF93FB46AFA4A023 -:109DD000BD3D951D9D8471AF5E4EF78CC7F9548CC7 -:109DE000FF011DA454BA4C715B6186167719365E6B -:109DF000ABC793F5789F1ED74BD7E80A2F0C403D91 -:109E00009E5E234B8BA8BF3E7619F4E709723CE9AE -:109E10007C8D720BF7E75D6BB2A4B16583FD82A404 -:109E20002439D5D5C8E48E4CBEFF9A01F2A573350E -:109E3000233F2FF6B248FD1F576D1F3AA1DEF14AAE -:109E40004020CA05952972B6760E81885C267A75FF -:109E500032D68DFE36FB41C8E5C038F7E702530124 -:109E6000EEFD9F8BF49430C20D8D2E099587B07155 -:109E70005D466D08F703C5A35006381B326A33B040 -:109E8000BC7FFFA410B388DF5D116932C497CC7822 -:109E90001AA8F79D3594AFB06584FDCF9AA043B75B -:109EA0003B2B8268EF5CD5DFEE5006F73FF57DBDBA -:109EB00060F19317E13D3BC165DCFECC65F1D64412 -:109EC000BB29617FB116FBD932B8BFD87B46E2FE11 -:109ED000E28ADCDBF0E8FEBF0CEC2F46CEC1FAAA2A -:109EE000B7BB1CE953CF87DDEFE0FB006CD28B3EA4 -:109EF000C5823E16943FEB277AD4FC8921DFB5B8A2 -:109F000099D90F9E1534C6F18F87E664F4E0C72413 -:109F1000717C3D9EA7FBC118AF932DF9CE887F7D44 -:109F2000FC0502F763995D2079A7EB4D902791A07E -:109F30009F9A513C5A750A94AF753CB45821BF287A -:109F4000897C19D837603D2556FBAC0BB4BC13F3A4 -:109F5000FB5B825C3F2FB0F338A5B0724904C75D4C -:109F6000107409CE043BE9EA20D75FFAFE8B23F791 -:109F70006415E2D9E1882856F336EFA35C1D64032B -:109F8000E7DD42167A2F199E0ED83B695FEEC012AC -:109F900091CEEB1E8F9C4BF73E24930B6F21FD94CB -:109FA0003016CEE5E30DAEA335DEF43C19F37ED5D5 -:109FB000C0F7A6143A7F63CE97794CC3DB3E0D2FD2 -:109FC000FFDDF932FB34FCBDA4C567F478D6254922 -:109FD000E4FD79B6FA47888E4688CB9CA1E7FB68FA -:109FE000F861CF8CA77B3936F4DAE32902C263A388 -:109FF000FDCBC63F8821B4BFF4766E93BCD0F37717 -:10A00000F472DA4981C513F611D2A46E8A93A69D23 -:10A0100094E8BD99FFEE30F19FBE2EC9D6595F1767 -:10A02000F3FB2E6D5D0E34FD5B00CFBB6C4861967B -:10A03000F9445F048DF177731E40B27DEE835ABB05 -:10A04000E391C93928971B1DB192D1F0BD8E9F377E -:10A05000BEFC8D0BF96CC349E70CABF57835C8FD38 -:10A0600016D0A7EB12F7413DF35F6BC75ED324E335 -:10A070003EA8AE4FF57DD0B44AF33E9AF53EE806D1 -:10A08000662D1F93ED830ED9FFD4F4ED896092FD08 -:10A09000CFB2E1CFB3EFD6E879A4BC8F2B1CFCBCC8 -:10A0A000ACF9FD8B03EBB0BEE047C05737363969DA -:10A0B000F7A9A7C9497CB8B82985E2B28BCB79BC8E -:10A0C00077F17D82B65F678CC3BE04F262199EAFE2 -:10A0D000D7F4CE5116AE467B7456A560D8270FD75D -:10A0E000A618CAF397DCF312DE9BF0728D5DA1F81F -:10A0F00033F41543BBA096E72932A5FF4E8C73EBD2 -:10A10000F1677DFD5FAE3D4AF7A0C5C0CE2F096166 -:10A11000FC5924FE7AF9F549FC5E3A61703F5C0116 -:10A120003B61C379E328DFE360D9B728CEBB01E305 -:10A13000E230D30D5FFE6606D11128E518F2EBC4BC -:10A14000AC38CAC7C5132AB2912E9F99F8B907E354 -:10A15000A2EFDE76DC8FEBD4D7D24C7907E67537E9 -:10A16000C799CDF1E5D38D279F9B3B902740F4F015 -:10A1700092299EACCB2BB3FC4888275F983B8A780A -:10A18000B22EB77439A1CBAF83651D6F3F04FF3C7E -:10A190001871124C6F69F31EE04B8D2E0FEA7CF89C -:10A1A000A593EC916726FE96F2ADF47A2DC14CE2B0 -:10A1B000C36F95C5EDB43F8B790AA583EB323F722F -:10A1C000ED4019BBFDF6D29506FA18905323CAB19B -:10A1D000E1E59498CBE313C9F235753E18AA7F4A9E -:10A1E000C84E4DFBBD3DEE2AFAEA7AA8B1E9D70A7E -:10A1F000B683E7666A3FD111895BE827333C69275C -:10A2000045169F94F85EE1EF07F48083BEC7EA9598 -:10A21000D5AB7DDC9E6E23FE8C3969FFDCA7B6E4EE -:10A22000427D9F5F8D213D3CEC535B7313E4699B42 -:10A230009DEF478A361679C2022F4FE56A7A9985D3 -:10A2400003D8DF9A3AE3792EFDB93D97EFEFEDF1B0 -:10A250005707D0BE6E3B5C1E40FED9EBA9267B3B68 -:10A26000D9BADDA5F313CAAF92417F62A3B6DEC0AF -:10A27000A22AEEE3AEB1870389F1C675B93C8F23FC -:10A280007DF293BD6837B7C936CA136C9379FE75F2 -:10A29000BB5B9AB14D6BE733B493F47354745F8630 -:10A2A000E436E6573FA5D93BC9E6F954AE4DBB5F4E -:10A2B000B4E7DE5A6150AFD88FD4B9E8FE07A6CA1A -:10A2C0003CBF2964C8A7B66BFAA5DE94AF21CA5F6C -:10A2D000CD6F0BFA23BB722DFCB63D3EF5295CEF2A -:10A2E000A81473227D445DD67CFF8CB6AE3FD0E6C9 -:10A2F0006BBE575534DDFB209AEE7D88D537FFAC19 -:10A300000FE96DB5536EF3D13D0F74EF4314AF5C9D -:10A3100082E7DF53783E0BF87FE7F2F306A13E9425 -:10A32000AF2CE0A2785467BEAAE64359F4D81E5A6F -:10A330000DFDB5A9F52A1E5DE974DBBA709F2F33B8 -:10A34000183988F398EA9148EF745E9C4A7A08BEFF -:10A35000A77039C264A19AFC41BA34057D703C5F94 -:10A36000660F38289ED516617DCE71FCFC3FF653F2 -:10A37000C77AF6D716A1BDEDAA443CED0F4DCA88A9 -:10A3800058C809FD69DEFF7FFBBB6F1652BEAA18D5 -:10A39000F908FBEB6D5CBC11F7F557EC1443B88F73 -:10A3A000F09DEF1D3C839F3732EE33DF9F36A50FC4 -:10A3B000F559D4EDA07A7B3CD59D88A736C1D389C9 -:10A3C000FE6EDBE1953F413CB6B5F238B719CF7B65 -:10A3D0003DDFA3FB358EC372627DF3FD1AAC73259E -:10A3E0005F27A78BF62D61BE2CAF8AAF23C5070F61 -:10A3F00079E81EA8E3FB9F71237C5F63DE697955D2 -:10A40000C3CD3B5F26FB45A31F2685D7E1BC6E1657 -:10A410003D9D1D3EBC270DD61BE1DE65277FFFFE5F -:10A42000B4745AD728C087EB2A7A1A5474C9FEBA72 -:10A4300053A4758E4ACD342F1693D8767CBFEBC4C7 -:10A440000FCF473A50B368574B2C6826BCFC15F029 -:10A45000B2DA022F403F4579B85FB4EB46EAA7D3A2 -:10A46000E192D1B269F354D379E5D1DE2F5296C788 -:10A47000F924E17E91B2BC2A8BFA9A9F85FE368E32 -:10A480005B27B3CFE26C10EFC9F257CED7FA1FE8C3 -:10A4900067E4FC95F313C7D7C7FD1AEB3AFD74D6F2 -:10A4A000B5CDF57FA7A39DA58AE9A1944228E33AFB -:10A4B00021FE719D70BDB4B80DA92005E940EEC91B -:10A4C000433AB8313D84F43992DC90185F77BB048D -:10A4D000F40C769D538E1CA0B38B5ABC479727660D -:10A4E0003E6B7319E5559B7E2FDFA1D1C92BA09739 -:10A4F000AB71DDCC726BB474B2324F30DF43B33228 -:10A50000CF9F9C4EECC1F08D8877C4535E05C52B60 -:10A51000BE8BF5F7EF177738C6E2783C6ED61F642E -:10A52000F2430979593A3CEDB8D9CDE3D414FF9000 -:10A530001A19C33C386F694890CB464547ED89F0FE -:10A540007D037474D77074E466BD745E63B99E9FB6 -:10A55000B363F8FC9CAFAB7F603DBB109E36CFF77A -:10A56000883ED7DA5D32BF47EDF4D6F5D1A1EBFADC -:10A57000E8F0EB1A791CBFAB79D5748F11AB692267 -:10A58000BB69975F7D13F3C5981432C8C521FCA33E -:10A59000C9ED9BCF54285F7577AB26E75A9D32DA19 -:10A5A000E3CFFA6E7C1CEBDFCD9430C643A7D856C0 -:10A5B000119EFE0AF37B284472B514F77DA22C3558 -:10A5C000A4E9D1A7110F339456210BDEFB162836D0 -:10A5D000BA8654D9C46C65A3C7C34B43E5E04B238B -:10A5E000C8C15E8D9E6F427AD6CFDB279383874E9C -:10A5F0005F0E1EFA86E5E09FF34E43AF7F03F2E65F -:10A600003384DF2C6FDC1A3F5F1962218C978F3601 -:10A610009F0DEC4D05F9AB2EDD45F4D3F68440F9E2 -:10A6200052608747A8EC7191B0D9EB71F0FCDF1D47 -:10A63000FCBB58CFF16CC6D39779593CEFA67B652C -:10A640005832E449C5881FEE528FC9C522E6F7D7B4 -:10A65000123D7B357B46CFEB4FD7E4FF809E9F6951 -:10A66000A3F1BC055CBE7BC1DE41BB88497D0CFD0E -:10A67000F89BF378FE3EF003D1378C12467EC8A8D3 -:10A68000914C795A9C5FFC12B777327D4C205D83E8 -:10A690007962F0FE04D813783F41A66A6C7773EABA -:10A6A0009502EAADBE2677B340E7F4C37B7E0CE5A6 -:10A6B0002CCCF702BEF1CE30D6F7B384B2857F1E24 -:10A6C000AB67A598B75896AFF9E90E1620FDA8F923 -:10A6D000E9FA7D81E2C8795F95F9A3882F9E97AF4B -:10A6E000E79918F571770AB38CAFFD473E975B0D7C -:10A6F0007D75F56857AFF230B2AB56A1EEC472A6C5 -:10A7000083EEB509EDA97459DD5791A9DA0CF7F379 -:10A710007A67A41AEEBDF587B30CE59CC65C43FDD1 -:10A720006064ACE17BDED2B30CDF0B9A2B0CE5311D -:10A73000D1F30CF58B00C189E571EB2E36D42FE9EE -:10A74000BCCC503E73F3B70CF5C7C71719BE9FFDBD -:10A75000C87586EF13BA5719CAE7ECBCD550BF8D40 -:10A7600059DFDFB9219FCB29E0779263ADEEFA463E -:10A77000FA1D0DD96188F32FD1EAEDC9AC2EC57849 -:10A7800048DB91F252F287D3CF1BD61F36CBC5647C -:10A79000F2D8FCBE5D1BEF93A7DFAF5E86748E42DE -:10A7A0001EE4D227EEB7D6E29CD697F1BC04FD7723 -:10A7B00031CCF7F20FEC534A2ACD67419683599D6D -:10A7C0000F5892AF58EE2FB40B2117EE1525C39BEF -:10A7D0004E8F23E1ED4EADDED7C5DB21C118074218 -:10A7E0007DF284055C7BF307EE3B78389FEBABCAC8 -:10A7F00054F230F83D0EA7AB4F7438409F3C915F48 -:10A8000035343FFC93C6D7AEBE5FC1FA57F3FAB6F4 -:10A810005029AE4BB27DA5BDF9E67DA5AAA528E7D6 -:10A8200016785285C4FB9A7FA5D5D3E3D96DE99FED -:10A83000D3BE529B23543A9A7DA55FE19D1B558858 -:10A840007F858FA7AFAB5D0DC896FE9DD98E61CF7A -:10A85000E33D1831B74479C366FF2EAAC96DDD9F69 -:10A8600093F6D691BFDFE61E4B791F6DEA2AD29789 -:10A870009D49FC5CD0977F447C4EF5DC64F0E70694 -:10A88000E3012A8D076DC96E6A4BF0FF715DD5FB40 -:10A89000F9BDDADF801FFC51FE69D8090AE37EF0BA -:10A8A00071C6F1745CB5919D701CEC0494BF6B246F -:10A8B00046FBDEB14A41B1F28B3B576BF6E16A8E43 -:10A8C00037F37EB7D9CEB824B492F0B606E8C955AE -:10A8D00089F1386EFFAEB1F3FB37656F3880FAB699 -:10A8E000DFEF600F01B47BFD3C3EA7E3E5ABCAA3FD -:10A8F000CC8221767266C13076F234B1AC1BEF6D3A -:10A900003D7692C745143C8AE8C37BC8F9FAAD7A14 -:10A910007E4E6C05EAA922A919F3D745A664205EEC -:10A92000563C27B2B88072CC989F6F67CD3FC278F3 -:10A930001CF3F1F731E66A453B29A3C6A8C7325597 -:10A94000A31EF3CEC832E935A31ECB6934EAB16049 -:10A95000C4A8C7F2965698F49A518F8D89D69BF465 -:10A960009A518F8D5B779949AF19F5D8999B8D7A5C -:10A970006C7CDCA8C7CE7E649549AF19F5D8393B0D -:10A98000571BBE97F77418BE4F7AEE6E43B9AAF7FD -:10A990000143FD730F3C64F83EB9EFFF18BE03A2FC -:10A9A0005FC5F30C780F2D2EE2F91F3C69FCCE54E5 -:10A9B00007E6E35F8FE733611D2FE8FFADA13FD6C8 -:10A9C000C9CF2DC4E03F5CAF3FB308DD0300726C1C -:10A9D0005F1EB4BB212E847A18EAA727DEC77D9BB1 -:10A9E0006B0322F9712B30D88AF4F0A8278EF4700B -:10A9F000CD66E3F9876BE3C6720CE847C1B802D0B5 -:10AA00000FD2D7F5A6DF8D007B90E8ED7A456A4638 -:10AA1000BBD24C5F7FD6E92BA6BE8AE739F4F9EAB0 -:10AA2000F3B3EBE74F35FA5335FA63E22E82FBFAC4 -:10AA30003C917E7F479FAF0AFFF1EF1F39701E27C1 -:10AA4000760ACC8BFBFB2CB62FCF623E37ECDCE4D6 -:10AA500040FE34CFCB3C8F21766A81715F719AE8DA -:10AA60000E11DFBD2E923EA229209F3DC6CFEBAD39 -:10AA70007A5EA47331C887E82F88B146C2CB0AC07A -:10AA80000BDE1BAEDBADC7B476C71E14E97CF34802 -:10AA9000FCA868F870068CFC98A2A49AE8C988DF24 -:10AAA000B452237F5EFFCE450E945FFB00DF420D64 -:10AAB000639E90915FAF1797D13E9F8E6705FEC34F -:10AAC0007125307571DE37C0BC7B94A1F85DBA6B1F -:10AAD000D3DA3C0BBA1909BF8F1618F7E9F4FDB9A0 -:10AAE0003AC08EC322AF54C7DF2EBFFA24CAC76450 -:10AAF000FEF0EE02E3BEFA28FCE1DD89F2F61BF07F -:10AB0000879F2F1856CFF5CF427FCAC9D2431D1653 -:10AB1000713F89C93D18AFB537F3B8DF60FCEE1B54 -:10AB20008FF3BC5B5045F7CE919E4B91F4384FE8C4 -:10AB30004004ED938CB342981735DA38C75F0A8624 -:10AB4000C439FE52307C9CE34D3C4FA866E436D8B5 -:10AB50009099A45029DDEF8C20F03CA44F118F4335 -:10AB6000F2758BB3B4FC6365D8FCE34BB4FDDDEA4E -:10AB7000807A12E180FE3EC7E7C07D6C957EEA27B1 -:10AB80007D847E62F5DC5E8BD93C9D6DDC5EA37DB1 -:10AB9000A66F208E915E887EA99BE3BFCDC1E3B6F0 -:10ABA000A71B670B160EC17BB07018BCFFFDED1C18 -:10ABB0007E6E3504D6417972FAD6CF61EAE5F59911 -:10ABC000467F796D0587AB441BFFDBD9DC1F985CA2 -:10ABD000C8F94FCFBBC4BCC5940A28CFE4E794F4AE -:10ABE00073AD7A3F930B3D54FFB340FDE4423FE623 -:10ABF000CDF2FB77D6661AEFE1F9B8A06E32CE6BD4 -:10AC000092D6FFE442C6F399C772B8CC79A77FD336 -:10AC1000EAFFADA09E9E788E16FD1287285AE27339 -:10AC20004A218F13E8F7DE4CD7CFCFDDC7CFD799B6 -:10AC3000EF5D003E79037F1FEAE89D76F2F7401F43 -:10AC4000D1F9B92579FC1CA2F93E8548A9BC0FC5EC -:10AC5000EB095666792FCF903C8743B750FEDDCB8A -:10AC600093992C0447CE7BB8BCD0783FC257384765 -:10AC70007765E128F21E166AE7E8FA52B91EEB0F73 -:10AC8000BAE20F59F8BB516D9DEED4FC5ADC9FC659 -:10AC90007D72BCDFDB6ABF3C5AC8E967B4E7AAEF44 -:10ACA000764422C8B7E673D5C9CE53F739FAD6E44D -:10ACB00020BCE35908EDF79C05F29E1CA897DAA08A -:10ACC000D0F9C7B5452CBD06BF97DB4278AE2373DC -:10ACD000AEBCD68E7C5ACCB20428F7C5E6D0F87745 -:10ACE00036325904B8BA0AF93EFAC2DB3EA5F1FC85 -:10ACF000B5303585CE9D4F47FF2CD6C8E8DE42F3F0 -:10AD00003CEFD6F8C5B586DF9393516C9D877FB72E -:10AD1000468F20B736215FD415B31DFCFC2C3FA70E -:10AD200080D7D253FE662895F6052F8575E3FBE79D -:10AD3000BDB47E3705A6DE8FEBA9F39B43CB533022 -:10AD40009F27EF2A3CBDF3E4A90BACE1FD9DB6DEE5 -:10AD50004DFEF0CF10DED4D24EFEFBA55F9E3A250D -:10AD6000566B3FEDA860FB4804F55F0AE83F019F82 -:10AD70008A4CE768994BA0F3B02EA599E82AA5263E -:10AD8000E4C5DF456357D918DEE332556BAF363281 -:10AD9000017F4F827201494E9B7E5F420DB5B742E3 -:10ADA000FB69B86F16C2BCEFD052ECAFC19D2A63ED -:10ADB0007C33A5B8B90ED7EBD985BC8FBB939C97D4 -:10ADC000D0CFD90FDE3FB5EC95BDB509F70AACBDC4 -:10ADD000FA15E3FD5357BFF275EE9F3AB8F5EA57FF -:10ADE000FE27EE15D0E51BA8213BDAF507447E8F40 -:10ADF000DE5F9FBAC28EEBB0B68E7523DE639F0313 -:10AE00009E5D8378B6D7879FDD8276C9AAF410FF4E -:10AE10003D91D87710CE77D2988CEDF57C43819513 -:10AE200092BE9EDB2890FDC0A4FE1BB03C7F579ACB -:10AE30008CFEC35F9F7AB32006F4F9F6EDC73D9808 -:10AE40009FFAAED4EF41B83EB8ED350FE2EFEDDB3F -:10AE500044CA43A173DF0979625F6AF4B5604CF8B4 -:10AE600038D2D7C296FFAA4EB4CF58D44FFAFEDAE2 -:10AE700038409C68F73E9266F85DD1E5DD5E435947 -:10AE8000D7F3CB9DD6E7E62BC770B974EDA35D8EE3 -:10AE90003C05C78FD8C7C03C3FD0CE017DB0C3436F -:10AEA00076BC0ECFA247CB1D680FBFBBCBC97A289B -:10AEB0002ED86B676EAE3F30EF22C2871E02E7BE10 -:10AEC000DD790EE4B32502EB771273B37D88EF3F93 -:10AED00069FE9F791E4BDE961DB8BE4BEA583F9E19 -:10AEE0003B5B7493B0F666A8BF28E226BFDF3C4FF9 -:10AEF000B3BEB906EFB311ACEE816BDEF73BE8E70A -:10AF00002AE807EDCF259DC6EFC79EBB71DF161857 -:10AF100077C74E07D98BD78C10EF1F3F46D34BD541 -:10AF2000ECDC53E348FF654C5092DB1DBA3EFAA0BF -:10AF3000855192CA5FF0F77DE1F9518B4CCFE385E3 -:10AF40000AADC7F53BF7ECA3DF16967AAB51DECD21 -:10AF50007C7E71DAB7D8605E517557DB335B88153C -:10AF6000F47CD51E8AEFD568F7BF5CA39DFFA83A95 -:10AF700060CE57DDF3ECEFD06E83F99FCEBD3D0B75 -:10AF800046796FCFB1E7A6A6D1F9001D2FE7025E83 -:10AF9000C4AF8F9764ED9627F9DD169D9F8E6B7A6F -:10AFA000F7AA6DB3D7E6C2F86D4FFDB910E3C7310C -:10AFB000C6E9BBEA41FEFB3F55EE6CA23717D267EC -:10AFC00010F16ABAE721C6DE6009F47DCDAE34A285 -:10AFD0009300D843CE1A7CC3E9B50AEFED44FA7E5C -:10AFE0009DB77769FE6D64D7EDBCFEEF1CB23340B0 -:10AFF0007C19B0D1B32760ABB1B867CB7CBF58A781 -:10B00000B1FC89BDAF10E5CA35263FF413C13A3F04 -:10B01000EDCA3163497E5DA5A8D3310F60090BAF3E -:10B02000E5F15B7E6FCF0752E7BEEF23BF6F13588A -:10B030000CF0B4FC378FFD2BCAB1EB1EBF2F1DE502 -:10B04000D8875267368EB76CFB9A74BC5FE60329CB -:10B05000968EED3F8C737936445F8E11B47D293521 -:10B060005D00997C03911AFCFFAAFEB5B7C2387F38 -:10B07000033C23DFDFB0E31F54DEA7BAFA5900FB1D -:10B08000ED9B8E705CDBE46E6E0DA17F69E4CFEB0F -:10B090007E765FB642791EB13C0D7F79D8EE866D23 -:10B0A00076CAF3453F1E8759C1FA697EE6F62BBA88 -:10B0B0008F3A505ECB36D69F7FFED0EF602139901D -:10B0C000DF56ECD8F0A9988ECF0FDFC2DF835A612C -:10B0D000B24F976AF2DB4CFFBF30D13DE087E20B05 -:10B0E00031808BFF1C1397E36D3FBF7FE26180EFE0 -:10B0F000A36D2FA6E3EF4DE8F4AFDFF37CAC7BF15B -:10B1000042C730F7087DA2F1C9807ED0F493B21314 -:10B1100000CB81E22EFE5C66EF493F1FE6BBACCB65 -:10B120001E429A5FF698A8BAD1AE3AE8247B64D959 -:10B1300063C7896E97096ABF407A8EA5A31CD7D7CB -:10B14000EBFAC7FE341DE5F4F54191CD0456BCEE93 -:10B150005727787DA0F314A87FFD1387A77F1FCB07 -:10B16000204F5C16EB35B57B8FA3CF6DB15EDD87CD -:10B17000A7637CBEEDE77FA7F5F870B7C0728A863B -:10B18000B65FDAF5278A837D040BE3CDE4F8427DD0 -:10B19000B3A25B6C726458AD5FCFACDF56D277CA96 -:10B1A0000B1F691D378C615C3FFEE6B15FFE16E048 -:10B1B00058FA96333413C7FDE58DE90CE8E0CF5219 -:10B1C00033A7FB1FAFC946FDBDD41ECB96E9C9DF2F -:10B1D0002FDDFA5DA2C76B7EFFDD6C6DBF2168239A -:10B1E00079100BE23C973C388FE679358B103D2E79 -:10B1F000FD31BF67F104F8D9567E42A5C2E59693AA -:10B20000AD9C78AB0FE526DED902703818BFAFEBE6 -:10B21000559EFFEE64976524DAB90E85DB7331160F -:10B220007F07EDCE15A09651AE89BF3F311DFBB90A -:10B23000A9486A76527CD4FAFE9AFF075C96D1033D -:10B2400000800000000000001F8B080000000000CC -:10B25000000BE57D0B741445D670F5F4BC425E43DB -:10B260001E100884CE3B488803492001D481400C3D -:10B27000CA63025151220C014380BC445670F5DB75 -:10B28000740820B0AC06659515740704C5E706047C -:10B290008135C2441483EEC128AC8B2F761004791B -:10B2A000C980B08EFFB2F2DF7BAB3BE99E2402BBCC -:10B2B0007EE7EC7FFEEC598BDB555D5D75DF75AB92 -:10B2C000EA4E1583BF04C6F23E1ED5DD9BCE98859F -:10B2D0005D30DF9BC5D845C6A467EC8C5531A3EC27 -:10B2E000B532FABB12CFD889F5962EC28D5076634F -:10B2F000650DD0FE0AFEDDD2564E9704C6B2A9F9FE -:10B30000276C106395F82F09FAD974227F0DF4CBBE -:10B310006244161EC3E167A218B395845487E7C040 -:10B32000F70E1E35F7847A39CAC0926D50DFF20DE0 -:10B33000C1CC1E2D617BB5FFAA1D16E651C703FFC8 -:10B34000AFDAF08D99613F06E6EB35B47D3D63D50C -:10B3500019BF8EC279844BCBA13C61F6E5BF85DF76 -:10B3600081EF6E84EF94AE82F6699AFEB69EFC9CE5 -:10B3700065607B73DBF378FCEF423E2FB138DC1560 -:10B38000C2D84C9826CB6D3FFF055FD63EFAAEA6DD -:10B39000BF0C2934EA7830FC63301B7C456C7B9F02 -:10B3A000AD8D66AC47FBF77FA8911F7DD7846FCB2F -:10B3B0008C41937293FB05C453F96716BB0C782C30 -:10B3C0007FED92D9003013982FB92B63A75FDDF37F -:10B3D000E93D309FD30DA6A831F4554798D0AD0D67 -:10B3E000EF655BBEC95F03ED4D80F720A067E5D632 -:10B3F0001FCC06681F93C77C1618FFE9282763FD3A -:10B40000116FA6AFBD1ABCE5C1736F088D23D610AE -:10B4100083A52796415919C5EC1E78BFF2A06897FD -:10B42000105FCCB7C416D2FEFDAA86A30174D1D793 -:10B4300033E6333BF1BB5B7F7B5E0CD3E2DDF8B5DB -:10B4400057837715CF8178BD3B00AF97587A387C0A -:10B45000869D7A794E1F577A7BFCAA78FDAE8621AD -:10B4600093B73EBFD047223C4B3BE043DDA1AE51FA -:10B470002919FB9469F038FB95B3C4BFFFE821326A -:10B4800011F8A672C38F4B90AF00AD3E0BF06FA5C5 -:10B49000FB3CC18B1D561F23B8A948C8E868DE7A5B -:10B4A0007C06D6F742A466B7D1DFB490C9A1D0AF6D -:10B4B000EF6DD1BD1E86764EF28545C0FC1607B1F4 -:10B4C000A94E28CFD914B8AB0AB3A9D3609CE7E43E -:10B4D0000C9B8CEF05B1490D409F734E5F58D79080 -:10B4E000B6791F6914C32468EF75B3828690F67C21 -:10B4F000C8581D7DDFCB3AABAFA5718E122FBFEEC2 -:10B5000085EF5D908DCC02DFF3D6FEF0BA17CA63EB -:10B5100046AB0DF134A3F6AE306680EF37268E9F32 -:10B5200004EDEEDB07F8A3E939CC3D00BFD3F9D435 -:10B53000D9B74C7E6A18CC4F0CCDDAFB16BC5F0A2B -:10B540008815815F67ACD0E3673673867BE2516E06 -:10B550004D6D7C42FF759B3DF0DE4C5748F572F80F -:10B560006ED95A7DFDECC6D3C45FB303F8CB85FC1E -:10B57000D5A33D7F6D54F96B001B80FC354A0C311F -:10B58000203F9F6B16DD1678E7C222135B02F08521 -:10B59000570537837E2E34422384777098C9D1C4EF -:10B5A000B72A9FAB783B83FC97DA1E9FADF5DBBED5 -:10B5B0001AF43034297FF38B8C35509E79F3B39491 -:10B5C000B710DEFEB7B82F58FBF679BB7E9C42E37E -:10B5D000DA656138AE73BBDE8F7B18E13F5BECC888 -:10B5E000B7E7165A1C0CF5DDAE507732D6F7067E5B -:10B5F00000BAD7BDFD4306EA7BC616111D5B243396 -:10B6000095171AFF7958C079345A249C47D52E4093 -:10B6100002BC5FF5E72037C3F7DFFE61902BE497AC -:10B620009B4FA599B9883F43D9A42DC8BF5D990305 -:10B63000E753F556EEF3B5F0FD8AAD4DE6E9509FC0 -:10B64000B7FB5F19A88FCE6D6932A3BEFACEE47D39 -:10B650008E017F7C214DAE37019EBF0B85CE7A32A5 -:10B66000362F7E8D530EE9082F1C0FE7000F382F61 -:10B67000C04B993BBD737C5CF8AFC5C7F929F8FD99 -:10B68000F2C6C14C8CD7E24570F0E7A16EAB40F337 -:10B69000E7CF77FD90C142AE3E5F5BBC99E4FDFF12 -:10B6A00097F966C4FFB7D297F3FB9B12B74B817C27 -:10B6B000DF9EAFB73F48F0EBA1761AEF35CAFBB873 -:10B6C000FFDAF9FFEFD0BBFCBF76BE57A3F73E858C -:10B6D000DEA1360BEAADB7FF15C7AE63DEBFFD7F57 -:10B6E00074DEADFE8FC16ECD82F17DCEDC770C179E -:10B6F000C82BE9D01FD9112F507BA6AC3BC6297EA1 -:10B70000451DFB7AE434F8AE0CFE04FAFB75215FAC -:10B710001B0F02DC027E02FA170C9D13C0434BD1B3 -:10B7200000F772B4DBC66A6603D8F4E97482279521 -:10B73000FC68CC82F677809F87EDF7D77A67D44292 -:10B74000FDFEAE06A90EE0F18E89C95B01B6F514C7 -:10B750006DB88EA973645A25CDF8C6E7E8D723F7EC -:10B7600004AC2BEE9AA4AFBF93AD8F36427F779691 -:10B7700099981BA6744740FBA7E26D34CFBB58F5E0 -:10B78000625BC8F5E3E9783C5F9FD5B181CD12E2F9 -:10B79000C521DA37B2F678638837C44B4C265B6E26 -:10B7A000C7AF788D0701B628FE15FC913CDE116508 -:10B7B0007D01F1646173D983D0DF25C9588DED2DEA -:10B7C0000CD68D7CDCC215A13DDEE04F320E225737 -:10B7D0009C4830DEF100433CE3F33E31BAF769DECA -:10B7E0008178BE7EBC2E4C7E0AF15A146A77235FA4 -:10B7F000389E8F36C2F7EA00CF82D0864F154F8130 -:10B80000787F0B7943E397AB653AF34D41BF338CB7 -:10B8100085D99743FF61D65ECCC8E7E1B3F4C0C2D7 -:10B82000C670BD268E600DCB61BDC6728C675AE7AF -:10B830009540F59E87E1BDBAFBE17DC46B2F2639AB -:10B8400089FF8B6DC7FBE132CFC5AE04B7F99F1FEF -:10B85000E580FF194F25F1ED471BB8BF7969D81B6B -:10B860004B0680283198B33C08FD5CE54FF616E3A3 -:10B870007B2233D871FDCB1C0EC93608FB65B4AEF4 -:10B8800009CF31E8D6BF5D1D5D74788B2C88D0C19F -:10B89000D1CE9EBAF6DD2725E8EA7BB86ED0D5C7B3 -:10B8A000960DD4C1BDAB87E8DAF759304207C7CB54 -:10B8B000B7E9DA272E9DA08393EBEFD1B54F5D5DFD -:10B8C000A2ABEFEB9EADABEFB769AE0EEEDFF06B68 -:10B8D0005DFB1B772CD4D50FF02CD7D567363FA155 -:10B8E00083B35B9ED1B51F7C68BDAE3ED7FBB2AEC5 -:10B8F0007EE8B75B74F04DBE3FEBDADFE27F4707CF -:10B900000F671FEADAE7590FE8E051B62F74ED6FC1 -:10B910008D391A10EFB0C90F64A11A037E02391BCA -:10B920002D9DD6B587155A31F28D49E187DBD3BEFF -:10B93000D7D58FB5FF53D79F9955031190ADEAA97D -:10B94000ECC21AA80C612D543ED4DF757B02CAC329 -:10B9500073F21264AAFDB93FC4A11DF968D803327D -:10B96000F2DDA518661307C07898CF887C6D08BEF5 -:10B97000DCCBA5891B85F945E6C9043EF40B54DAF6 -:10B98000FCC1CC13097CE80FA232C21F49CF23FDB2 -:10B990005DA98CF2C7D2F3687F0F2ABBF913A9EC1B -:10B9A000EE8FA732C6DF8FCA1EFEBE54F6F467D2F2 -:10B9B0007BB1FE0154F6F20FA5E7BDFDB954C6F9FF -:10B9C000F3E8791FFF702A25FFED54C6FB47539912 -:10B9D000E09F48ED12FD855426F927D3F364FFDD7F -:10B9E00054A6F8A75399EA9F46659A7F0E957DFD68 -:10B9F000B3A8BCC1FF00BDD7CF7F3F95E9FE87E963 -:10BA0000797FFF435466F8EBA8BCD15F4BA5DDFFFF -:10BA10005B6A37C0BF8CCA81FE27E979A67F25956E -:10BA200059FE35F43CDBFF072A07F99FA772B07F68 -:10BA30001D9539FE57A8CCF5BF44E510FF1BF4DE79 -:10BA400050FF662A87F9DFA2E737F9775279B37F8B -:10BA50000F3DBFC5DF44A5C3FF213D1FEEDF47E516 -:10BA600008FF017A9EE7FF98CA91FE2FE8F928FFA8 -:10BA70006754E6FB8F5279ABFF089505FED3548ED1 -:10BA8000F69FA4F236FFF7F4DEEDFEF3548EF1FFDD -:10BA9000939E8FF5FF48656B3C619829402FB6EA6D -:10BAA0003FC3152859484487F1B6D6F7157DBC32F7 -:10BAB000F83986718F71D502ADD39F0EFEEE5DD23F -:10BAC00093B91609E1C5D8B407FF8EAD1B63F7E241 -:10BAD0003F24C69A722DB47EDFFF3FFCBD25C38F85 -:10BAE0007EF900DAC7FB2D0CED63A0FE55BFFB51BC -:10BAF000CE9E68F4C3960CF49663FCE577F1DE62A3 -:10BB00002CB727707FE4F5046E6FB72518A87CBCAE -:10BB1000BF8DCAE2FB93C3294E15756DF3BAA4D845 -:10BB20007DB5FD1F921438C41747F6E21AFBB9D64B -:10BB3000768BADBFF923C6751C7546167433C046A7 -:10BB40006EEFE52F43DD1B614AF288EA1731CE2301 -:10BB50002FB4D8EAA210CFBFF913B65FC098D302B2 -:10BB6000E53309AEFDA8177E088A73837184BFEAA6 -:10BB7000C113427FD1FE3FFF5FEEFFF8CFF5FF77A5 -:10BB8000858F6E4D749E4A40BFC0E8C8403A8C58BD -:10BB9000D8438C82F7A7AD106CC847D3170DC847A0 -:10BBA000FE18C81C1427BD37924D7576E0974524C2 -:10BBB0001A14FF4232DF05E339CB9807FD89128959 -:10BBC000115F96340A6E99E2D08EB0B160BFCB148B -:10BBD000BE2D595A6B9E0FED2A7AF0781973F378BF -:10BBE0009915FE877234A77EDD5E0A378A97293E53 -:10BBF0007609FD5E609D399BDAC763E7639C7987B0 -:10BC0000D98676A3A221209E1B10370B8C9705277F -:10BC10008646A1BC323BB3F3387748E9DFF07B2C92 -:10BC20004C12A3AE8E17353E2B31A93BE27194988E -:10BC30001E8EEB980BCDC9E10C4B49EA8EED5C40B2 -:10BC40008B162805A36B303E077CCA48575F6DB042 -:10BC50007B3D8CEB08D813291385DB35D88CF1C8D4 -:10BC6000CF7BB3E502518DFCB0AA0D22F9F5DE853C -:10BC7000FF5C8271EC59F1465A074CC3983B8E6FBA -:10BC80006757B72C50BF8477DF6B02C55D653637C9 -:10BC900006E3BA9AFD10F26B9D8BA3C7E5209D9633 -:10BCA000761D68415AC98E4F93BA69E8B3A88EF0E1 -:10BCB0005A1213C9E9B3C3447E2DD0A716E933CB7A -:10BCC0006D3AA6C5F32576D98CFB31254BCF13BD34 -:10BCD00066B7D14BD7AEA2BE89E80A74D23DAFAAEF -:10BCE0003EA1C6D18FFD1CBD86272AF14D855E1869 -:10BCF0003FBF0B2B1F8924FD50BCD0935CADE1D31B -:10BD0000C07D89A41943C29D200F053D393D98D1BE -:10BD1000DE0DE9F9FD8A6CA257209D0A7E9A4EF449 -:10BD2000609F87B28D309E7B13D9D409F07CAA1214 -:10BD30007FBDB76E7401C6CBEF4EE4FAF223587F95 -:10BD40003A60FDF9718D953940351FA8B111FCD7C6 -:10BD50009A1882FF562351F9594D1A95C7CCACACAD -:10BD600041235FC000661CDF5445AEA626AAFB52E5 -:10BD7000F36230EE5EF0D3816C03AA50B9A170D4A7 -:10BD80004DB8BE002468F033A928987C6915F69A4E -:10BD90006CF931A83F9609F68D4857E7505D7B96C0 -:10BDA00096D906A3FD32727E02BE588FFC77F798B3 -:10BDB000485DFB3B97C6EAE0F989128DAFB0205190 -:10BDC000F7FC9EE27E3A789A1FD6F3F0A924A9C028 -:10BDD0002043FF17FF62227EBE583DB8FB7C0E1346 -:10BDE000DF05E2FF9859A63882BCDE6247FDF76D99 -:10BDF00010E7EF6FFF2ABAEB68DD2B53DCE592D535 -:10BE000026E13AE5C1E9721CD63F180C2EF900C4B0 -:10BE100097C8307EC05EB690FE9CBE5A6032CA881B -:10BE20008FD17A79DE4B169AE78CD5227365129FF3 -:10BE3000C461FB79D112F5776FA2D480FCECDB688A -:10BE4000B1AF87DAE95EE57D6120ED8354CCFDDB9F -:10BE50006123CA434A4B06C6F78BE33DD1A807CFFF -:10BE60006C30D1BE5785B8AE34044834E7776F8460 -:10BE7000E54A247E84DF531F47AFC3F9B7CDD74DC2 -:10BE800071116F1FE7B38980CF53A5EE0C5A273F7E -:10BE9000C2E3F1EDF1C2484FC986306923CE77BACB -:10BEA0006BB02D5D6B0FF9BEDF7493BD9B3D1DB96B -:10BEB0003FAB07EA81632B4C05187701BD3F0EF1BC -:10BEC00074AC3ED2B09C16555B88BF4A8C9259FB2D -:10BED000DD9215A283DA837E2F447BBD5274B1C1FB -:10BEE00008D753FFF252C185FB4E492CA73BF2ED18 -:10BEF00003F70FEE8EF398D2C93EE37720332ECDB1 -:10BF00003ED6ECB745A71BBF97E53516F5D78E9FF4 -:10BF1000C781925C4B7BCD453A6D0EB22F9750AFE7 -:10BF20002686E33AF5E441B01BF08D59754D1912A0 -:10BF3000B05EF903DB890E65E31A523CF0FC63AB9B -:10BF4000EBFD4498C2B73D1A9E1A8A71A2C6E7E378 -:10BF500064B4830BF8FEDAEC9767F5D1FAF3EDFDE4 -:10BF6000091663C8C1C2D34D00BCB824968FF89D92 -:10BF7000CC1A94F8859BC627A1D2057CD8CAF9FEB5 -:10BF8000DB74837DCA812C447FA80DE9A2F677D4A7 -:10BF9000C4E35C9F270A3A3B1C9DC4E57BBA81CB76 -:10BFA0001DDB25109F02C13E4DD2D8CB2AB682ECB4 -:10BFB000654CACC870DFEE646284A217B8FD9B8349 -:10BFC000F60FF7856D02C947F9268BDB0DFC9598B6 -:10BFD000C4E573B6F9B5A70662F3F86A337E67D68F -:10BFE00056813D034D4F99DCA52DB82F655BB728D1 -:10BFF00082DE33D9DDC8A78A7EB7824240BD3013C6 -:10C00000FF09F515AB04B787F8C549766806C64D34 -:10C0100070FD8F7A5EA347DAE9F700BD7E1FD3DBA0 -:10C020002356AFB72FCEE0502B8E73F62AEED7B63D -:10C030008D4764570057A52EF7DE71345E81E222EA -:10C0400081DF9F89E3C3F1C2F83CF6EB1F4FA99D46 -:10C05000CB6979BDE07677303E15AFE1C39884F6C1 -:10C0600079CE06C18DFC382AEA7EC2EF6CC06F24FF -:10C07000E2557686DD05702930929BE22B1CFF5538 -:10C080006B39FE81CE9F68EDEE37513E33E2F51BF2 -:10C09000B09F32EE0756FF4074DF0BF445F99DB5B3 -:10C0A000D96DC68DC8D3AC3E2C04F97EF5C77B7123 -:10C0B00059F0CDAA37BAE1FAB538C2936C00BD1574 -:10C0C00029473C5170531BFF05DAEB767639003F68 -:10C0D0003273921D6A8727EB8A16DCF76E473F257D -:10C0E0002E761FFE0BF073DF06D11194A16BA79C77 -:10C0F000479089FFCB641FF9096530CF3A1B3E9505 -:10C10000F3112FF7D919E9DDEB1D6FE03899584C81 -:10C11000FC89713DF443FEDDF106FA1F85493FEFCE -:10C120007F04EA9140FFE34B93C3B010FDBE8FF94B -:10C13000BEF845A3A737CAEFC5A8043BB468D3A38C -:10C14000D103BBA39E57F568A962B7D47EEF437BAA -:10C1500005F0F1D56F8421DD55FACF443B91DE66C1 -:10C16000271E9C0EFDC3F71EDC1E44FD9F1D0B7693 -:10C170000AFA2C7EF6FD30A6D17F0BFBB82A92502E -:10C180009FA8764D5C176703FE52F5E5D5D65D9DF9 -:10C19000CE2B24605EA1FA7995E0BC32DBFA9BAE2F -:10C1A000CCEBEBA57C3E4757F0F9CD68372F6EF707 -:10C1B0001F7CDE6297C92FF044A31C7EBB596475B7 -:10C1C000445FEE375CB2023F0DC0F8CD0AB2EB27F8 -:10C1D000A39984719D4EEDF74A0BF905B3B6F1FDB5 -:10C1E000D653C2F0EEB4F1FFAE27EC2194EB2D2232 -:10C1F000433BD4369E56BBBD2A295A63B7AF116F55 -:10C200001867457B5609A843BEAF6CECCEF09CCBBB -:10C210008AE1AC41A47D782FE93160218A4F831FE8 -:10C22000AE8B375898DD6A453A75127FFD47F2F9B3 -:10C230002973091FBE14C4BFFAFDAA2E1E5377F43A -:10C240006B360BE4D754CC1B1E369CE17778DC6C44 -:10C250004B12B753DB143D2738AA292E063E8DED2D -:10C26000711CD75A1E1F66EFB006C42FC2143F368A -:10C27000F07908928D150FE471792BDAB51003D996 -:10C28000B5403C7CAD7CA7423490FF5B6EE67EF00F -:10C2900039819FFF7847B18FEF24717FF8FD241E0D -:10C2A0008738877E20F47BEE268BBB5640B7D54877 -:10C2B000EB64E3308B1BFD19A335C42366207A8D14 -:10C2C000DFB5CA33E06B0A6B31213DC7E5DCBF093E -:10C2D000E773B827B3895DA9DA89FB08934933303E -:10C2E000B6DFF4E57B188F94A1AD086B85C93927BB -:10C2F0007A63FBB508C3FC0F0735BC877196C3F1A1 -:10C300004686FB02F2DB16B2FFA611DEDE14A7ECB6 -:10C31000C258DD008CC7EC598C7CB4372632CD0670 -:10C32000EDA71ABBD845AE7F469EC7F196097CFFA4 -:10C330006691371BE973235B643B6EA5AD85AD57F2 -:10C34000227F8E7F8CECB8CA0730A6F211F08F21C5 -:10C350008C33560EE15307035E09FE2169DE8455D6 -:10C36000BD70D344EA8F742E4FF019713FC527304A -:10C37000DF7AC0C31D393EA303E9E5600DE3817F89 -:10C380003DFB9880DF4111C0EFDEE54918857860FC -:10C3900069120B87FAF14689E05E052C4254F60DCE -:10C3A000308E7568A8407430582513CEDB59200CA8 -:10C3B000C47DD1F285D736CEA08DBF99B06A18C0A2 -:10C3C00006035FCF3EC4D7B393E523A3C84F1AC675 -:10C3D00004E4C3AA880613ADA3415E70FC03A01B4E -:10C3E0002DFE261BBD7C7C6530BE5C948B24E2E375 -:10C3F0007BAA05F227ABCC1DC735A293D57D399B0F -:10C4000084EDE7C0BF90AFE7346E4FC6EFAD103894 -:10C410001FCC51F9EC55BD5C0E4E66C4A79DF1755D -:10C4200096D27F56B2819FE36AFD5E03D9DD398DD6 -:10C43000EF1FC2756567FD57589887F0F2B685E221 -:10C440000782C19744744144021D26A33F092EE28E -:10C45000C064EE27AAFC598AFE4722963C2E620051 -:10C46000E589F6B0ACFE7933222DF0FC11383E742C -:10C470000E68F686C0E79AB88AA8D33B14F714CCA6 -:10C48000BE19381EE1E6203BEAE3C9E6065A9707E3 -:10C49000B633D5733FCBB494FB59B4AF06B0650542 -:10C4A000F73327F7F2F567A4E76CF9423C6BF58B9D -:10C4B0004BF9A7E179B9CE2FB6601C01E35EABB9A9 -:10C4C0003F6854FCD792157A7F61F2228DBF48DD18 -:10C4D000FA2A70BCA6478229EE62417F42E307FC3C -:10C4E000DD5028A31E96138C74FED2C402FD0927CA -:10C4F000E3F14CFEDCA8F88923934DBA7D3779042B -:10C500004B433C14A31E4A4455E35C8AF1BC0B2CFC -:10C51000B41EE366A3C44728FE575CCBCFA505C66F -:10C52000FF2E54BFF72CB6C77A7C3EBFCB4F71B8F5 -:10C53000BF09CB52A77033C87797C3975C281FA059 -:10C54000A84C28EF41FBBF41583084332107BFEF8F -:10C550007916FB97CD561BEAADA783C3A89F050BA1 -:10C56000048A0F2FB27179FBEACBD0F5A8A7D47853 -:10C57000EF92E199ABF1DCD26F92774FB0F646F5CE -:10C58000C0E8DC1218C64F1C309FA2CB203704BF76 -:10C5900037C1110E7CFE9E6F8A15F0B46AE37B13DF -:10C5A0008CC08FE77EEF7B0EE11736EEE7F0EF7C75 -:10C5B000714108271F986004393A57ABF6776082BB -:10C5C00003F7DDFFC0E13AA897012E46FD86F31E72 -:10C5D00022D0BA7F23DAA5E8B6784FB1E11D5E8E8E -:10C5E000601EB49F576BF7A764E746B4D762E8B103 -:10C5F00050F42FB6A63A08DE92E87C2C19FDA083F1 -:10C60000EE6ED118C732B016A40BD8314747FBD213 -:10C610001B93B8FC6E4EE1FDA9F8827E9E4E8EBE45 -:10C62000FE7E6E69DF8FFBDF194F9754E8275BD7DB -:10C63000CF4BFF4E3FE501FDA87E1B38C012EAA993 -:10C64000D3698E77719E737EE318B115F5CF7E9115 -:10C65000F8F4FBEAED2968F7BF7FD51289F66FCEB3 -:10C66000EB3BE34A318EA0F845A79B3E334BF07E6F -:10C67000A55F640ED0D3557E81CACAAD4DE6FC7469 -:10C680003C57DB64CED38CAB5C192770BA7182C681 -:10C690008FD997ACC69F57D278E7BC7ED288F49CDE -:10C6A0006368388EE78FD9101EF70A9CDF16E5BD48 -:10C6B000C378DEA08338C047C9DCEF88E9E7D88FAC -:10C6C000F3DB8CFA1CF9C5C0CF8704B6EF9EC2FB22 -:10C6D0002BEEC2F57CF6417BE9015AF76518442838 -:10C6E000071DAA3697C0F30389230E25771887F410 -:10C6F000F13864238F431647B4CC0363C622522E0D -:10C700003C81F276FBD3AA7C80E8817E29B0A870B8 -:10C71000D0C491C3789C0BE14B1B0D4FE239C2E6AC -:10C720002E2DBF3A80F66159285B0F7276EFE0D06C -:10C73000B82D308EE972B800B6930DB784A64C833D -:10C740007627128647A4F0F327E41F9E48709EC503 -:10C75000F179E3830DE08C309799C7B35C1F88149F -:10C76000CF726504BBDC1DE0EBB482CF8814EE9F72 -:10C77000351B609C03711CFC7C2FFCC56DC178D3FC -:10C78000C23E02F29DFAFD5B1387774DC96EFBFE38 -:10C79000AD89CE9F92A3B5EDC319B6BFD671FC5338 -:10C7A000B1A75D5338BD9CC380BF347A7FC2C860D7 -:10C7B0001D5C34269239B4F1CDA2581D3CA93851E4 -:10C7C000D7FE9E19FD74F5632D2D59D5D7E1EF8B5A -:10C7D0006169E1B4FECFE6EB90AF1A2F7D3A19FD07 -:10C7E000D80DA25D8079CD7A7BE3A743A97789E252 -:10C7F0005CA79A45B247E0DE9AB5FB2767590B9DC7 -:10C800003B36765D44F66F4E0C3FDF3DCBADDFFF30 -:10C8100050E3F21DED9BA03D2BC773311DED9BB482 -:10C82000C5E37F76FF243345590F0F6403F97AF887 -:10C83000CC5E9829CBDBD144F4AADB27DA9155EB07 -:10C840007A0B4C8071DEBAD5E20E82719FDD79C41D -:10C850002C69F64FAAFC600022F1BD23663C4F759F -:10C860002099EBEDCAC6F366867CD1783FC9754B3B -:10C87000932B2A1AED17F8ABDBB290BF1AB2D0FE99 -:10C88000351B6C4EDC0F9BB37434C599C3FD93A963 -:10C890002CAF1F4DFD56F827125CE90F26F823B187 -:10C8A00065EBC7D8CFD3E136B4E71546F955A44BAD -:10C8B00085149C89FB55955B3FBEF86BB4A3367E0F -:10C8C000AF63ACF84916D68FED6333D475C5F10666 -:10C8D000513F2D23BEC842BB5480EB02785EBE257B -:10C8E000D785723FBC2ED486722FE279B20EF874CF -:10C8F0006A0AD72F262F1FEF287F21F5D7BABE4F00 -:10C9000049A0F9ABB0297A8311F5873A0F13187C47 -:10C910002C6FF3F7A3B26A6BA111CFC57F90F67CA1 -:10C9200014E209DA876099347228E999EFAB078736 -:10C93000B30EF4965A5A143D3C19F530F45794E668 -:10C94000F835CAE5B847BC462BEAD110AB0DF73F26 -:10C95000C6E50C904A35F311DFB91B5712E0ABF86E -:10C960004CE8074C8652ABB7A776625FE41483E2CB -:10C9700017D5F2739DAA7E5FF504C375D8147E5651 -:10C98000AB55AE2A94F6EAFB2D02F707E46D3CAEF8 -:10C990005F91E67A12C7DB329C4DDA42FAB425AEDB -:10C9A00030F4971B7F98B185E81C66930CB8AFA054 -:10C9B000D6AF6E9D0797EFABCD63B1D2FE23912D1D -:10C9C00040BEF8E8965B5A1CD06FD3C39999A2C6B3 -:10C9D0004EBD94C2CF35339BEF32E98B5DC112EA75 -:10C9E00081B1B8F790D5E6F7E379488C6B54EDB296 -:10C9F000ACC7F3605561B0CE87EF8FE9E77A09F1F4 -:10CA0000D1B43BF722DEA371E0C20CE4DCD138F8EC -:10CA1000229EB3775841DBD8D10F72BC4CFABF933A -:10CA2000F15E4D9F258D9C1385FEC4F73024B4B76D -:10CA300060F7B30E72D889F8722DE5F2E752E47010 -:10CA40009AC2BF258A1C4E3372399CBA2ADC86F101 -:10CA5000CE924784FE785E8E49A176540126E4CBBF -:10CA60004CE44FCE97E5FEAE8A3CC72BFD70FE0F1F -:10CA700094CF4A7F24B553E5F4E534D7216EE75AC5 -:10CA8000B216C0B86E03B946BDE75AD8230BE5A469 -:10CA90008D4FCC36E427E09398520D1FD435FD68B6 -:10CAA000443E310D13884F2C50E669F8C8D9EA9FEF -:10CAB000D8F2BBA15FB528DEB09CB5D57F95A2FAB0 -:10CAC00029D7C6EF1F28ED4B42C08FA0F84F18C3DF -:10CAD000F8DA852889E2A47397C1200105734D9E79 -:10CAE000648CC3CCBD3F88E260A507AB97844AED58 -:10CAF000E975B73F83F69727FA93A83C90E83A8DFB -:10CB0000F898E6BF53C163C635EDCF653B78DCCD01 -:10CB1000E4B6D8D7C563DCCD25D27E5C6F667B9248 -:10CB2000EC94BA1FC7E36E18CFC3F85EE0FE1AC6D6 -:10CB3000E1703D6D8932E8F609DBC5E386EBF7D39A -:10CB4000CA9B3E196480FA53F10E8ACB79FBB88CEC -:10CB5000A9308FD913DCAF9BB4FB6C0A1E1B8C9ED3 -:10CB600064B4A30DD51C3F0D2BC402DA6F622CB840 -:10CB700050735EF76A7C3CDB9F48F851ED8BAAB797 -:10CB8000B7D7D0A1CF56FD7D35BB53A1F07B05F2C1 -:10CB9000BBBDBD9D51F935909F55FD6C8A3E487ACD -:10CBA000E8367805FD07555F17E40D1D86767EE8AB -:10CBB0004B895BFF0CF38F4C7365A502FFDCF24AD7 -:10CBC000EFAC3500DF66741B6D21D7A20F7F349167 -:10CBD0003E7CA490913E8452AB0F4D9DF8E1B9A9E3 -:10CBE000D7A7CF5395F6E0C772FF10F4B5B6BF8A4A -:10CBF000B4116370FC85A9DC4EFE52E3EE4C8F1736 -:10CC0000A6AAF2796D7AFC66A5FDD5F4F88C54AE2F -:10CC1000C703F5366863D2DBE7DEEE4B71B2C30CB7 -:10CC2000F43CDAB3C6606963BCE69C7B9770B75688 -:10CC3000AFC7F49B3E03F9FD1AF4FA7D88BF7F5716 -:10CC4000AFE7176E26BF0AFE9CE36F86F5C76F61DC -:10CC50007D87F047B0BE8B6F2F0F817210C8F7B081 -:10CC60001ED9FA318CAFF9A93E1477003920BEAF36 -:10CC700000BE473950E5A572EB8070DC37607F114C -:10CC800019EAFF403928C87BC588712AD4E388AFE8 -:10CC90003D20F3A86702ED843FD5B50AE7AFCA830C -:10CCA0002A0757E7A39D265C979ACACF733D0FA525 -:10CCB00056CF77E6CFFCE13AF9FFD1D46BF3035EB0 -:10CCC0004DE5F7207E41FE7935F5DAFC82D752FF3B -:10CCD00023BFE02DE21FD49FB87EBBFD437BF87CD1 -:10CCE000CE3F742E11F8210BE3CECD837ADB314E8B -:10CCF00073FB15EED7834E27BF3ED0AF9EACE8BF87 -:10CD0000A94A9CE0409AB32595CB2BF9EDC3138338 -:10CD100007A0BDBA567F6F725435C338D35428B5B7 -:10CD20007AC28274EBC05FFF6BEAF5D9EF3DD7485A -:10CD3000DFE3A9FFB19FE7BB167D90E4B04E447CD2 -:10CD40007EEF3132C4D3D5D603A6D51CCF2ABCD8AA -:10CD50006354ED6624DA4DE08FF3FF097F8CCD6BD1 -:10CD6000B86805BA86A7198B301E78279EB5A078BB -:10CD70008669952309F50D53F70528DEF191A8C2C0 -:10CD8000E68323611CB73FC9DAF60DA07ED4B0F06C -:10CD9000D6F888C0DADA87A5890757D0B8F97915A7 -:10CDA000E6F21AF93E990267011CAA817302E0B506 -:10CDB000BC7D98D1CB6CDA7E14FD33CEC6F705DA94 -:10CDC000F6F37CF95DD1FFDB2AD8707FE19E61E745 -:10CDD000CC18CF199BE7DD1B0BEDE2D3428B42C091 -:10CDE000C4DFB355A0F10ED814B54A4EA2235B0E92 -:10CDF0003C6F589EC3F74D2C0D4DF98E0EF87040C8 -:10CE00009ADE4EE19FB11BC5C7E8CFD22030731622 -:10CE1000EF2721FEDADE47FAD1FB09F4BEC712750F -:10CE2000EDEFDF358C39DC1DF0D12D698A3EC4B8B9 -:10CE3000B0DA3FD0646283E0E8286E73ABD2BEC53F -:10CE400060A86080A7F19BD25661DC6B14E37C5133 -:10CE5000B829B548E6FCC71C01F3FDB9F166A7E99E -:10CE6000D767F827E9DFF7FC1CBE86B6C39742FFF9 -:10CE7000323D9F841B9DEF7E0FE3088F126CE8A765 -:10CE8000563A8356B070A4BBC2D7F2C022C73098BE -:10CE90005F10D3C5F15AF95ACE2C42BEAE646AFB7C -:10CEA000EC55487FA7A1B53DE7F346A1F5FD342336 -:10CEB000C34FD0FB733665ADC23839D083EA09362B -:10CEC000FE0C9F3704C0C302E4827198E412F5326D -:10CED000E027B983FDDBA50A7ECF0AFC7C53CB0893 -:10CEE000EECFB524F0F2C534EEBF3DAEE0F169A55A -:10CEF0006CE9A2C143AF363AC39F07D7039A7913AF -:10CF00009EEE8E52E62D4F2C1A03F36A8960FD05C2 -:10CF1000E093759BC6AF5AA4E193E7374D2C423C92 -:10CF2000B4F627171E443CDEADE0E9C54D130E22D2 -:10CF30001FE1911394B78A1CBEFF6AD9FA7187F278 -:10CF400036B73DFFC8985FA1821809DF131CA62CD5 -:10CF5000DE4F4207F859D0FE7D47C0FBCC14753D2B -:10CF6000EF2BF4191340BF8200FA8D0C808BF57003 -:10CF70009B1F0C3D83FF54B263E5E26E183FDB2438 -:10CF8000D01D2BD0CF66019E37A6DD5B14D203F9EE -:10CF90005432C5425B4FDAD483D6BE208FA8BF4837 -:10CFA000FFBA485F4F443927785A91E346E49BEA39 -:10CFB000C531D07E6F5AC92ABCF77ACFA2952644D4 -:10CFC000FA0769335619A1DFBBB3FEB417FB330A66 -:10CFD000A507C7083FC3A7F501F3581B00CB01ED18 -:10CFE000575D459F2F0A78FF9180FA1501F0EA00FE -:10CFF00078A9FEFD6933F8FEE534A01F22EE6AF23F -:10D00000E24D6B5D37B4DA2F01EDD9877A7EBFBD73 -:10D010008EC327373D50B4344403A7FDAA48CBBF85 -:10D0200026C55E4C8E723A3AE2DF439DF14F5AA01C -:10D030005D9375E7120F33A6B3BF7B443DDC24AA92 -:10D04000F2B5F0E0BC74CD7EA05C5B84F194CEF7C9 -:10D050002BE422DCAFB8FD71B57D4D9143333FB574 -:10D060007DFEBFAE88F8BD2B6935451B68FF4FD9E3 -:10D07000BF8BE0E52D97AF84215DF2F1FC28D677D8 -:10D08000F124CF4DD7CC8F35A4E0FC9A1EE6F70DE6 -:10D09000E53AA007C87909B3D3FE775378F8821729 -:10D0A000A0FD9E87C50568BF0E2F88A4F346E3FB4D -:10D0B000727F7B4F789F6EF701DC143CD58C71D565 -:10D0C000A6474751F98EE858E203E4F7EAFB5851C6 -:10D0D000485FAC0F27BCC4BCB4ACA816E420B6AF04 -:10D0E00044EFBB226CDD76A01FBADCC470FF89312F -:10D0F000FB73C427BFB3909F3AADB61FEDF794FC06 -:10D10000BE30BF07B42B596CA2F83FFCD17D0CD7C1 -:10D11000F25166AC9FB14829E55BA9DCFDD31B1F2A -:10D1200066D0BE8E48E77676F9238E8324B3AFE5CA -:10D13000FE745FE1A8925F656B5F576A5F18C7D79F -:10D140006792285F0AB3496113D06FBBC191D6378C -:10D15000BAADDDEE9F44DAAF7AEB4C4937DCDF1B2A -:10D16000D897F3CB2E7F49B7128D5D2F3D6B243CB2 -:10D17000EF364BF3506FECEED25B90496E1B2231D1 -:10D18000CE3A43F19B814F16BCD1011FF6E92B1219 -:10D190005E8E5916E05958D6F4DBE861382EF5BD9D -:10D1A000EC83AE3ACC1763EA250DD4FAC7B9C9238C -:10D1B0006EC6F1B6F1D706D2E7E41F033CBAEFBA68 -:10D1C0005532D80FB607FC7A1C4794231FF9493D06 -:10D1D0008FC7621A52B47185363F74A122FFBCDD3D -:10D1E00057783818BEFFD5AB4174EEEB2BF98B5056 -:10D1F000AD7FACCAC7CCB0FF39DC42EBE2704988E6 -:10D2000003BE31D61C7F08DE2B7DD6447AB3F4D919 -:10D21000E8477C580FF4C42DC3C0EF3EDF979F074B -:10D22000E85C3EB6148DECA5958FCD4538DFCEE495 -:10D23000637ADFCD9DC8474D37E4A3FC674D74BECC -:10D24000BAB84BF59D18472C36DCC8EA607C239EA3 -:10D25000FD5537DC6799F9AC85E8EA0D0D3DCEE761 -:10D26000D5271EE7D56A7FFA727DE5ADCD257B21F6 -:10D270001AC03B03FD2D2E31D17A44EC6626BD2722 -:10D2800086D9797D1716BF10ECF2E2D01C09E9EBC4 -:10D2900056E401EA25E4B3BCF049B7E1B996C30B03 -:10D2A00012691FEC6416DF079BF5D0F361E87F7EFF -:10D2B000358F9FEF9E8DF976709DFB6FEE7B552924 -:10D2C000F976FEB7F6BD9EE8ABDC1B6ADDF7E2E758 -:10D2D00040F72CC8CCE278619205F1143780F072E7 -:10D2E000AB95494180173182A5A0FE51F7BDC45FBF -:10D2F00073FD241A045AA71FAB91297F415E9895AC -:10D300003FFF35BFB7273E55C8681F2CAA9AF6C104 -:10D310004211AF18BF159813E5E768903DEEFE7413 -:10D32000E4BF20A2E7CCE7667DFA872CA4DBD828EF -:10D330005D3C41E13FF5FD13B537D1F84E08CC8691 -:10D34000F63EEF8FA923913E4DA2EBA9BB496F0694 -:10D35000D3FE39B3797F3718E099B5B0CE66C837B8 -:10D360003DE212D2DBFA99B9F0E114A477DE1F8313 -:10D370003C78FE66C6A2A0D5780EA3BC91DFF39ED2 -:10D38000B6EC7B3A8FCBE28DD518E7FC7A51103F93 -:10D39000A7BE7530F1CF34033FE7C2E2CC145F2A59 -:10D3A0000F51E05E39046BEE2F99911EEAFD9BBD93 -:10D3B000A857E0FBC7557CA0DF887A573D47CFAA26 -:10D3C0002594FF6283D0E139AFBFF5E5FEE9B438BB -:10D3D0003B9D17AD78CC625F18CFE92C0EC2EF32BF -:10D3E0005A1755187CF9ABB15F0393B6D970FDD0CD -:10D3F000528AEB6DB63595F210541999D11C01CFB4 -:10D4000025AECFD4F1544985B7123F19D921630411 -:10D41000E2B1E5D316E48F85A112C6452ABADA5DDA -:10D42000D46FA8D5C6ED84F25D1C7B22F281DF1C8F -:10D43000817CF0A960B0F0FC030E03D49F63BCBEF6 -:10D44000F53B8B96A5D3BCAD36C3881EC877E7F3F2 -:10D4500057C37BB73229A107DE135B1679E724ACEB -:10D460007F4D24BD04C2F4580EFA7BAF8999B84EA3 -:10D470009DB66C0FCD6FCEE6017883804D7BFD00AD -:10D48000D9A7390A7F7995736B25006F463C2A7AB4 -:10D49000C125B26A8A8729786CC5AF525FB1CC4486 -:10D4A000F4A8586C213A57D4FE8DFAAD086DE98680 -:10D4B000F4A8D866A2FC1DD61BF83C4A6A7B0F3B39 -:10D4C00004E32E3185DB0478542E8F35235C5E2FE8 -:10D4D00010AC7EAF62D95FBB19D2797F585A0C7CF1 -:10D4E0009FB5ADDFE838B467A75F8D8C9BA6A1FB25 -:10D4F000E945DBC370DFF968902719CFF9FAEE0F21 -:10D50000B2E3B942359E767A5132BF0F646B09C5DA -:10D51000FDEA19F31223D0CE1DB679CC587FB8217D -:10D520001E8FCC3187CD360C6187F146824F2BE7B9 -:10D5300048E80FF3070A9C6FCA5FDD634E80EFF582 -:10D54000BF81E3E7EC6B47F70E417C001FD950FF2A -:10D55000C4B5A4A01DAE30B4A4C4227D5E16C85FBD -:10D5600080F5A903F38F54225F0D047DA8F055E5E3 -:10D57000D6EDF3513E2BDE3C998F783D3B969931A9 -:10D580003E56A1CC1FD68FEF1AA17DC59675F98C9A -:10D59000BFFF2EF29D6AEF015E6402B8D9CCE18C28 -:10D5A0001BB87E6E367B29EF5DF39D8CD1FE999181 -:10D5B0008DC47640797E0F401495FB69D531137880 -:10D5C000DE3D597B7EAE12EBD3DBEA3BE39BF137CA -:10D5D00018143A5BC82E8D47BC00EC5DB62D0CF9D3 -:10D5E000E2EC6B7BF60E41B9D822D898561E54391E -:10D5F0008CF3F17AC0DF1388BF2DE7F3310FC5EC50 -:10D6000033A112D250C5932A6F2A5EAA18C7838A03 -:10D61000972AA38227A5DEA9E0A19CF9A83F76A6B8 -:10D62000BFB411FB7FF347DA6F3B3B8D09FC9C30A5 -:10D63000CF8BA6CECF15A1DFDFAFBD81F3FD146583 -:10D640009EE5366E17CBA398543B80F8CC6156F319 -:10D650004B4293B39B8FE8C6BF5A9183567AE33C03 -:10D66000609C5E03BF2718A8BFE6297C75A476B22C -:10D6700007F5CA6C19FAC94279B04DC17D4EF6BAA8 -:10D68000A8E86FB0999AEFE6BD7284F81074971409 -:10D69000016B16D3261807FA5F677A53BC30AFBB0D -:10D6A00097E6BD718C8D19409F1C11BCA13BD01E0B -:10D6B0003C24929E52C7E9903F247A381AB87C22C3 -:10D6C000BF607CB0552F048CB75619AFC560F7E228 -:10D6D000B960B650A0FB6BE2C2B3A187B8BDA34846 -:10D6E000625BFF37BD8BFB918E8B61924035762359 -:10D6F000B6ABBC189680F6FB88127738B2787B58A8 -:10D7000089860E4F75F69D258325A47F5EC8A18767 -:10D71000518E1E53DA359BED2317A03EB81426E137 -:10D7200079A9E608391DFDA866035BCA22381F1ACD -:10D73000BBB5E10FE485F007F5D293B636B954C70F -:10D740000D74F320DDA0BD83CB919DF6312AA3F8A3 -:10D75000BEE8D5E529D34BFAA95690D667B5B5539F -:10D76000EFE53DAACC9B64A45B9B3D40FE447B67F8 -:10D7700051F21805E641BDB557D738C45F5588D575 -:10D78000804BB8C0FA40B86D3D556D443F9F2D8A1F -:10D79000D9ABBD97763448A6FB67BE1E225B0FF45B -:10D7A000A8BDFF7D7E9EB791DFDB52ED34FCAD68F6 -:10D7B000E53F78AF2CEB7C3EEAD717732D74AFA909 -:10D7C0006BBF04FACE29D6601E8EF6FFDB96FC30C6 -:10D7D000A96D7D72D3458F184EFE42BC6E7D507E82 -:10D7E000E65D92E70AD642F7B1A72D3B307630D2FC -:10D7F000FB25139D1F98511F4F76EEE486E999385B -:10D80000DF698B93099EB5F13E0E2FE3F90FA72D2B -:10D81000CE7E01FDAFA3418E7CE467DF4AC186EB7B -:10D82000ABA11BB31FB907EA8786F6E98AE3FE6A54 -:10D83000C3D1B148F7AF1688A49F1C1B9EBC13EB45 -:10D840001D3B44BC3106EB19DB2398D79419C36DFB -:10D85000E817A8E70BEB4C5CDF9E51F4C231454F53 -:10D860001C53F82FAFAE2E05FD25DF3AB047B8EFB9 -:10D870006DF695D2F96EC1665F0FFCF2AD2013CC48 -:10D880006CB684DA5CBCCFB296F2E39C4BB6D8D0CF -:10D890004FBED7C2ECE8D7DEBBBBF7405C2A38945A -:10D8A00075D5D848FE5D155FEAF74F2BDF65E28A34 -:10D8B00052DA7788941250BF352BE7C68F2AE33DA2 -:10D8C000B9E8A53BD12F38B929398269F07E52C910 -:10D8D000D3340BF4E0960ED67BFE1BD4B8839BBEEC -:10D8E00053A6C403F799EA7B61DECFC0FB5D27D660 -:10D8F0000559313F6FE03DAF13266E3FDADDF7DAB1 -:10D90000A18703F3DC068EA7753D1378FFBF5F4840 -:10D91000877EBC2A6781EFB7BB4F9E746DE7AB3043 -:10D920002F19DEF7DE7303A3F74606FFEB0DD4D7FE -:10D93000A5F5161BDEBF3F1624D17A48CE66D24627 -:10D94000B43356291CD7F3C7F665D2F9BFD22F19C5 -:10D95000C955E956D18DA98ADF5D99FAF83080EF73 -:10D96000DB6AB2E3FB2757ADBC938B993ECF420EE7 -:10D97000E3F23913D6491E5BDBBA2870BD347BF560 -:10D9800066BA47F84BAD97D4385220BE73FBE9F323 -:10D990002D04DE9FDB0D6C9333B03DBECFD4B86851 -:10D9A0005DF45D4D1995B90DEBF26225BC4F71E444 -:10D9B000B1A12837A1E1140F3953534D9B78DFED06 -:10D9C000C8BC8CF743DF0A09B7A1BEF8AE66817206 -:10D9D000B940E113852F6FDADA24C6326ADF3814D2 -:10D9E000DAEF0A09A7BB2E498E9C70B4F32A5D03B7 -:10D9F000EF37ABF33BF510A7AB3ADE539BA687A1FD -:10DA0000DFD9B426B23117FA9383C36DE86FCF54D0 -:10DA1000CEBF1C5FCDF5CDB7D6F017C6E0F999B5EE -:10DA200013BBE1BAEE3E93CF6C877EED6F1786E1B4 -:10DA30007AFF1BA3370CEF1B7F03ED3D68278C6E2D -:10DA400011F5DC900246FB78433C4626C5D3963957 -:10DA5000F145EE19A31BE97ADA7371CF15E4A3330C -:10DA6000068A770166F65C81F6F6D03E1427BC6F15 -:10DA7000275F6FB27F75E1F501F7169FE8C7F5D212 -:10DA800089B56F8CA3F5F906930DC7F9DD86BF76CE -:10DA9000C37338B3193F5FFFED2681E6311BF831C0 -:10DAA000281EF5038F83CE06BD6F15DAF361DEA65F -:10DAB0005AE2C3D9C08716F4D31C3C1FF36CCCC701 -:10DAC0002CB176F93FBA2A7C3707F80EEFEFFED279 -:10DAD000793F96F70B3CB7CAF950A5BB8A1795FE5C -:10DAE0006D7CC874F905231A060C8F656DFA40BD6C -:10DAF000DFC18CDE15784F63BE185A8FF9AAF61B6A -:10DB0000ABFF48795B6423DB48F69CA561BEBCF99A -:10DB1000E20D768C07D699AB5BF3BA607D605E1739 -:10DB20003184BF5F88F98961BE21E9F1F4BD09360E -:10DB3000FB2844B729CA4B710131CFE0A07B79752E -:10DB4000165A3707EAA15714FADE86BE03FA3DFDDE -:10DB5000F8796DF5DE9F5A82A1E98DFC5E181C7183 -:10DB60004982263B5EF9FC0EDCA72D1C1AF1AB4462 -:10DB7000F87E53BF2377E0BD8DC2CC886D0900EFDE -:10DB800079E5EFBCFEC6886C13FA01C2D7778C44E6 -:10DB9000BFB19FE3CD7E9AEFA8FDC2F39DF8FCF3E1 -:10DBA00038D7DBFDF8BE6929D2FB9C10C6F3BD2532 -:10DBB000F9280EAABEF7B1C00EBF25B4C15E138B03 -:10DBC000C3BC06CDFDB83EEDAC8C4A77ECE5DFD7A3 -:10DBD0003F470A7D8FEB4C65FFC76095CCE8FF3966 -:10DBE000ED663BCFAFC89C56F0ABC62BFC5B62BD6D -:10DBF0003C92EC6F35B35B3081C952FD7DACBE6D9C -:10DC0000F7F6D65ECFBD3D26F33C7C754A1EBECEF0 -:10DC1000EE510A8DEFFF88FE65E0FDA9CCBFB4BCD4 -:10DC2000897C320EF80AED45560B87C72B7C52B122 -:10DC30007D2CE57B9EFBB1C98D7EC22CC51F4B722E -:10DC4000756112B4BB04F28B7AE1CC384F0AEA8FCB -:10DC50001335AC3E09145681D5E543BA34C7BF4FDE -:10DC600079D14EACAD0B43BFE72CAC27C64017E5CE -:10DC70008A7FCF2E8B9E5BD00F8EEFBB7EB986DF67 -:10DC80007EECC7EDFF99784F1CAE6FE4780BCFD7D1 -:10DC900078790FE5792E48189D8D71A4FD353BD814 -:10DCA000D1E4B6F73ABB8F32C43082A56BF625C7F4 -:10DCB000193B3EA7F1AD9A4F7303B7DF16633DE5FD -:10DCC000D1025256D712ECA4B8520CF228C687A53E -:10DCD00007085E328BD9E81E6BDB3E1DDD0755E978 -:10DCE000EFB05F1989EDC601FD51DF18AC3E23C2CC -:10DCF000CE027E3EA52F100EF5894AFF51E2238FFA -:10DD0000211DE62AF7B8E60AD51C3659E99C6BA016 -:10DD10007EC4B86631E94D796F2EFA63A02729AF2A -:10DD200082A21725F81FE545CA5967A66657CF8B0B -:10DD3000B437F73FD08F19E9FA3CE22A9D54FFAA85 -:10DD4000333AA97A12E835E87AE8A5E6299BFB2C54 -:10DD50008F77CE7D767ACC40C21B481CFA43317F48 -:10DD6000A2B8CA4C650E6C6D24F1B1698453427D32 -:10DD70003B76472C93E0D1AC1D029D6F1DB32392DF -:10DD8000E0307F0F9E5749B1F7635FEC3E02E393AB -:10DD9000275FF8621EE6BD1FF35B46F16343700820 -:10DDA000E59B104728791CC490F7F01EEB05C95875 -:10DDB0008DF6CAC9DAE50F3010FD9BF9395958E5DF -:10DDC000C99C4EFCDEDFDC7DDCCECF1DCEF7052FFF -:10DDD000E01BD0FE429148799A9E0ECE20FFADEE18 -:10DDE0000E13DD8F60B2E3135C574D52F8C112037E -:10DDF0000B4B0DBD822490570D7D1E0D7AEC3D1707 -:10DE0000F4EF857597D013FCD8B4085DBD510EFAB8 -:10DE100006F3C79A62449B1BC61F6AEFA9EBCF2982 -:10DE2000969B309EC25CDC8F56F98B89678C746F31 -:10DE30007E18CF5F71C724FD3D49D3B0F323C9DEFF -:10DE40000CD3FBDFCEABE46D5AA0F2535FD657C9BB -:10DE50004B4FF6FFC2417E3F4462CED5AABCA0FE26 -:10DE600007EFE669C4CF9DCD26E696087FAF61FD3A -:10DE700005D962C37840AB1F9E04EF45A191B4124F -:10DE80009F635E50ED3C312FA8162F9817540B63FB -:10DE90005E506D7BCC0BAAADC7BCA0DA7ACC0BAAC6 -:10DEA00085312FA8B63DE605D5C2981754DB1EF381 -:10DEB000826A61CC0BAA6D8F7941B5F59817545BD6 -:10DEC0008F7941B530E605D5B6C7BCA0DA7ACC0B60 -:10DED000AAADC7BCA05A18F3826ADB635E506D3DE1 -:10DEE000E605D5D6635E502D8C7941B5ED312FA86E -:10DEF00016C6BCA0DAF69817540B635E506D7BCC47 -:10DF00000BAAADC73CA0DA7ACCFBA98531EFA7B646 -:10DF10007D0B5B948C766C67BCAB393D1AF79DBE6C -:10DF2000257E3E742FF033CA61F3441BE52FBCCE2F -:10DF300075624BBAB26E51F8F7120B9982E7D03B7B -:10DF40007B5FE5CF97F09D6CB2074B897F59683DA9 -:10DF5000FA738F1A1D741F4A6EE0F7139991FB0133 -:10DF6000F345C5FF51F242CC1725F2033077B0518B -:10DF7000339EAE0E2B336AF0105960D3C1D1CE1848 -:10DF80005DFBEE93245D7D0F579AAE3EB6CCAE831B -:10DF90007B57E7E8DAF759E0D0C1F17281AE7DE254 -:10DFA00052A70E4EAE9FA46B9FBADAA5ABEFEB2E35 -:10DFB000D3D5F7DB54AD83FB372CD0B5BF7187AC1D -:10DFC000AB1FE059AAABCF6CAED7C1D92DAB75ED65 -:10DFD000071F72EBEA73BD9B74F543BF6DD0C13769 -:10DFE000F976E8DADFE2F7E8E0E16C9FAE7D9EF5D6 -:10DFF000631D3CCAF699AEFDAD314774F5A3A593F8 -:10E00000BAFAF2D3DCBF6775B03EC0386508CFAF4F -:10E0100051E9610DE85FDC9E765ED7DE1405EB0505 -:10E02000E09F0AD087E8F7FDD0258EF231B3EA30C1 -:10E030003BDEFB964754FF517BCF7BACFD47DDF7C2 -:10E040009F0E0EF304D1FAC24AF6F6A6FEFCBE59A4 -:10E050006B3E11F53E3BF3B198280A09F9D03F1207 -:10E06000F01796000E73F0BCD0E00791FF6403BF79 -:10E0700008FDCDD67591213E1EED72709B5FDCEBE5 -:10E080008A26CFCBD5FCE2DBF1DBD994A7D7D11F11 -:10E09000CAD90D9BF3719D358BC94B703F51CDB3E0 -:10E0A000B83F481FDF52CBD156C0AFE67BFB82EAB8 -:10E0B0007B0DFC19791F6D3D43ED5BFB55E25F0263 -:10E0C0004C76AEA6FFC760FD6704B9AEAF01F90399 -:10E0D0007FE8891A1BC1AB6A62087EAA46A27275E4 -:10E0E0004D1A95CFD4D8A97E6D4D0EC1CFD5380825 -:10E0F00076D71450B9BEC649CF37D44C22F8851A0A -:10E1000017959B6ACAA87CB9A69AEA5FAD5940F0F8 -:10E11000EB3532950D354BE9F9969A7A82B7D6AC44 -:10E1200026F8CD1A37953B6A3651F9E79A06AA6F59 -:10E1300004FF0DE15D351E823D35CD04BF53D34252 -:10E14000F0BB358708DE5BE3A5B2B9E65B2A3FA8E2 -:10E15000F151FD5F6AFC049F51F621E6F71774F751 -:10E16000F154D8C88E717F0FF356601E861CD3778A -:10E170003F971F37900EA794FE4D23C05DC23872A3 -:10E18000CF94F5759A75455D7F1EB7AC35F0FC2DC3 -:10E19000B53D99AD8EFC7607E3E7B4B8DF3E13FFDB -:10E1A00025C1D3A89ABDB8DE28ADE679CAB3911FC0 -:10E1B000D3881FFF725DEB34655DB025D1F904F2A1 -:10E1C000230B717F1A9FD5768FFE40A2EBF7F8FCE8 -:10E1D00042F57D7BB1F54C9B3D053F32D6E289C6C9 -:10E1E000FC5FBE7DA27DBDD4F9F7AA94FB0F9DD63E -:10E1F000EF3AD90BED55C14F22C5F5F79B4227E108 -:10E200003EFF8B0A3E5EEC6FD0957725395FE88F35 -:10E21000FBFBC9D52F3C20B4DDDF1F8F4B7C90EF7B -:10E220004226511E9C89CCF11EBAE077802388F0EB -:10E230005D4CA6F24482EB4F389FBB610182B06B0C -:10E240008825AEA3F9048E67A7329E9DCA38D47282 -:10E250006E927307F6772CD9A11BCF8B4A7EA171E2 -:10E26000CCF71C8EEB1F6F9F3F2E24B6E1BB359E73 -:10E27000C2AA294F4631E3F19447312F46545B5EE1 -:10E280000C75FD50BC8FFFCE11FDA1FD9C1F4FEB07 -:10E29000DBC0BC194B86EFE17930603D86F77F8BA0 -:10E2A000EFFF15E95FFC3D28BCB73BBFCB61CA332C -:10E2B000E39D05BC1A4B793578DE1B17203096F2AA -:10E2C0006A50BD7003FCBF078ECB9A66A4F175A19E -:10E2D0007C274F07EFA7BC341853B074C5BCC7F1F7 -:10E2E00034CFFDCEF3DCEF8EF2D1FDD42D89AEAF6D -:10E2F000FAF338F953991827427EC2EFD8DC747EBE -:10E300000DF8C92C008A6646013F75E06FA87C5362 -:10E31000A9DCC3519F033F9E407C7FB773701AF204 -:10E320004DD5AE5C09F15D67E0F7E9E40F947D41FE -:10E33000E5F710C4F0F47574EF009D71A46F6E28BA -:10E34000DD3B6812D982CD1DE8576B06A7F3FE1896 -:10E350009E4FB22E607F52C8E07417947663DFD967 -:10E360004779C82A9B79BC9A6579D39D1D9CCBAA15 -:10E370005AF0DBA79234F3A8DA71849FE762DE7467 -:10E38000ED392E49E957E53FD11CEA5A17A21D5F26 -:10E39000AB1C5832B2490E8EE3BDEE711629FC2E2D -:10E3A000817E1FEC3BCC2FE3FAA38DCE03AAE702BC -:10E3B0006730279533C17222DF3BE595747F7E3647 -:10E3C0006BA0E79539D3E310AE62BE9131B83E5AE7 -:10E3D0005AFB1E868326D6AF1CD503E635C13DED1C -:10E3E0003D2C0B3708C76589E42806BFEF15AA172F -:10E3F000F784EFDDF3EAF0C518B71E27723AB00FC5 -:10E40000391D8A819FC588F6F303B9E993114D72CE -:10E4100043E357E5A6782173E0F903F57E48AB1C8A -:10E42000E5CCF97B2CEEE1803F89FC5AB5CB12415B -:10E43000EB53CC3383FA4A919FC546EE5FCA98DA14 -:10E4400094F427F7374C0E259F17E3FEC81C99AFAD -:10E45000C74E99B8BC9DFA2AD48DFC3DBFCBEB7159 -:10E46000241F26553E7E9A42E77B18F81F37B7F7E0 -:10E470003F5AF3CCF462E46FB03857CCC0C4367B5B -:10E480007ECAE01E14C6F3F23B105F7B63F8FA7994 -:10E490000EE6A1C1FAAE4E09E3A5A7A2AD745F28AE -:10E4A00030CF1963769A9F49991F8C6C12FAD31654 -:10E4B00025AE561730DF1F82E268BED270D6C0D0BC -:10E4C000B130DAE4E928F70F703B31BFCB6F5CF86D -:10E4D0007D6F10B30943693E148F950DCC59C7E386 -:10E4E000B334BF0546AB0DCFE52C99267A05B213A0 -:10E4F000304E8CE74559ED3CAFAA9A7F3B70BC0E7D -:10E50000FDF8AC710CE7E710992F68281F2F8E4F8C -:10E51000067A107D009EA6191FF4EBA6FC3FC1925F -:10E520000DFDB0E67F3DC0E3CBB5DC7F84F16F220B -:10E53000FAF480F1C75E7DFC26645118FFDC0CAE56 -:10E54000A7EA700751443BDB95F4EF8420E7FDC850 -:10E550008749AEE5BDE6625C23D762C7F81DBB5CA8 -:10E56000D70BF554089328AFD63807CFAB05DD2D70 -:10E57000427E28C4BC7536F203CE68F3B0B180F891 -:10E580001A9085E2AB1330BEC6EF12BD8BF1D9896C -:10E59000CAF9E6BEEC4B157F145F13717C14AF769D -:10E5A000D1382D4859288330CE437470D33C82999A -:10E5B000478967B7907FB052E1C3218718D9892175 -:10E5C00021DC4EEC3AC2DC78EEABE9C73BF342A16A -:10E5D0007ED77923E929C013E503FCF35FB95DD940 -:10E5E00075F2782CEE07D4FEB83716FDC45D269779 -:10E5F0005885EFE75A6C0BED6D718DC643213CAE2B -:10E60000A3C4F96E52E6D9C85AEAAAA03EA787C8A1 -:10E61000300E987DD0138CF28C396A3BDA6F1C7601 -:10E62000D1ACFB5D0B934D0FE7300D1C8F21B280F9 -:10E63000DFFFBCCE75EE6B199DFCEEE799A86BFA77 -:10E64000DDCF2C651E8F6638DFCC20BB364154F001 -:10E650002E20BE400F3421BE9FA930D3EF1A34556F -:10E66000987B7835E3AB9FF50FC2EFEE7FFD83EC2F -:10E67000D6EE6C353F4E43103E37CBA114777BE688 -:10E68000B281E26E6BCABEA6F5497D0EA3DF11AB67 -:10E69000BF5C427EC0A502869B48ACF6E6FF53866F -:10E6A000F0E33759E97B81E37F1BFC790F10EA2DFA -:10E6B000F0E73DA9E0AF803F8F30DE67C5721BF801 -:10E6C000F358BAC19FC7F239F0E7B11DFAF3583ECB -:10E6D00003FE3C96ABC19FC7F229F0E7B1DD2AF0FB -:10E6E000E7B17C02FC797C0EE3CAA3711D62746FF2 -:10E6F0007F6170D832F433243994FC8D8F1C03BBB6 -:10E70000783576F6E68B061D9D879DD1FFBECD90B0 -:10E710006311BADF3FC9F9B2A7AE7ED0C1045D7DF7 -:10E72000BCACFF7D9B3E0B7EFEF76D62CB4604FCCE -:10E730003ECE6D01BF9FA3FF7D9B68E73D01BFBF3C -:10E74000A3FF7D9BC7957C992A1D53A4D782902F48 -:10E75000D6944D08671DF8176AF984420F157EF2AA -:10E760002171524771E4F01BB9BD7FE72BCBBE0D81 -:10E7700080CFDD2CDC8971F7DD0E03E9A5675687B4 -:10E78000501CD6E21D7212F967B78349C83FCF5CAF -:10E790001ED105C7331CC888CF63CBB87DEA79A3E7 -:10E7A00044FC1C5BE613F1BEE82D977D76E4C72799 -:10E7B000C3F8EF6C41BFEE85D0DF3B6307F5C5388A -:10E7C000CE3321C0CF286F1E5F7012C0E1570C0CF2 -:10E7D000F523D84ACAF32FFF2144398F7A85EEC337 -:10E7E00085A34E07BDB4BB8C7F3FC57B3958EB0F6B -:10E7F0003DFED3D5F0C288AF3AADBF6D76028EB77D -:10E800000DEFA01AA14C6165EC31C44739979FFA0E -:10E810003203C9D3259027C40FCC9AE8C25AF4F228 -:10E82000FE04CA87960EE509CB709ECFAC32D26E3D -:10E83000D928F1D57D37C22B6B0E8AB4CD2ED97C69 -:10E84000C11DF977EAB8D738F8FC22ECCC80762ED7 -:10E8500002F0E9A6FD6C7BADF6F7ACFEA0C8E7EFD1 -:10E8600015F97C5AE1075C6F233C4A5C3B3A05C7CB -:10E8700091C3F535D053C0FB58976630FA1DD1DFF0 -:10E88000172574E928CFF72A651CCF29F35A8BFD89 -:10E89000923C73B91F25160FC77ED63819E9F1359A -:10E8A0008EAF6B316E77A988F7DBE711AF80F8ED9B -:10E8B00055ED13B0FFDEF33C54BA9571F62C6BA105 -:10E8C0007AB53FC9EEE6FC5EFE356B86F9E2215B68 -:10E8D00091ECC519CA8FBAC668646887519F217CBC -:10E8E000C96AC43312ACE7AC630CEF33D78718693D -:10E8F0009F624DE5298257DA381C2657A7E3F98B2A -:10E900009DCA7CC264996077C07C52A4A9E1DADF19 -:10E91000730D2CB72B78DEA6E063A7C965B800E3BA -:10E9200018FC37917EBFA3B3F7543B9BF3A521405E -:10E93000FF74D1C93FFEC69E62171EBA11D7CFB26F -:10E9400093EC82BA6EDB3686DBD795C1533EC47535 -:10E950007F91C2474F078F7B0FEB0F8CE6BF83D3AE -:10E9600034FAD6DE5A3DB94319F77605EFB9B2E36A -:10E97000AB79D0BED069C191811973F4FE15F4E76B -:10E980001C23DA3D40B783D9AA3C388351EEDE1907 -:10E99000339D1DC2FE0BF8BED3B68289F45C62CEF5 -:10E9A000DBFBC37B9FB418C99F81E73F2B8FFB150F -:10E9B000FCFF4519C7070AFE9B153EDD8B76241523 -:10E9C000E32C6954BEA3D8118F6247762976A451EF -:10E9D000B1233BD18EA4E2BC2651B94DB12359A33A -:10E9E0009F243FE912E6C515D08E54B22530CE7C67 -:10E9F00018BFD8817D1B9F2306FC4E56B08E4EB7A4 -:10EA0000A745EAE0D1526CC0EF742506FC8E573F53 -:10EA10005D7D9E3533E077C086EADADFE21F11F0D4 -:10EA20003B627A3B32E4D804BD3FF3E53DBAFA419C -:10EA3000074B74F532FE03E69B7D8CF1FCB2C1C33B -:10EA40007E87FC927DDCA8FE3E33EDA3A9FE56A096 -:10EA5000FF93CD5AF7F10CB48F273309CF75D256F7 -:10EA60006582AE9EFCA78326672C9E3FAC2D04BE1C -:10EA7000C37388074BC730DA8707FE0579CA769ECD -:10EA8000F892F28D8AC599E4275D34EAF6D37203D1 -:10EA9000F6C59C23F5FB66D957D937FBFB8DCABE5B -:10EAA000433B7F2CE29AFC31902711C7FD74F09410 -:10EAB0003D88B79D9F713BD5F4D983B1F8FC5D6C5F -:10EAC0000AFD6CFFE641F2BBB6B7CA872B58EB6F65 -:10EAD0006DF3727BF1E6C1841DB8CEC88A16480F6B -:10EAE000661D993B99F8F1A0817E9F33A5A02A1855 -:10EAF000F1B2EDD0C260FDFD298D7E204269F48324 -:10EB000088AC1CA1AF8FD2F06102278EB6FDFF0545 -:10EB10006B92E82C00800000000000001F8B0800B2 -:10EB200000000000000BED7D0B7814D5BDF8999D19 -:10EB30007D25BB81CD03DD401226E161541E9BF78C -:10EB40002624611202460DB0101E414298243C5208 -:10EB5000AB3655ABD18FDE4C08841051A2B515AC45 -:10EB60008F958AEDEDE316AD045494E5E903840531 -:10EB70008346455D10D1DBD2BF28D0DA7EF4F37F27 -:10EB80007EBF7326D9193601FAB8ADBD37F9747254 -:10EB900066CE9C39E7F77E9D0321D790809DE0CF1C -:10EBA000D722FC3FD3D02E2081F4F076A9A17D831B -:10EBB000A1FF4C43FB2643FF3ADDF3ADA19983153A -:10EBC00027FD1B7E265E78DDDC4C48E0AABE7E3940 -:10EBD000669FE8197361BFDC6E53DFB8F4BF1D1F79 -:10EBE0002C319D4B20A4AB5BF4DB52E9F5E812A27B -:10EBF00066D371BA4D7E22E0D544E8F3AD3DAC6DED -:10EC000023AA631C7DBEB9DBECE99008D9CEBF3BDB -:10EC1000DAB770B02F869089E6D311BF2B9F37F5F6 -:10EC2000AD8FC07833079308FDB4EB4E3E6EA0D98C -:10EC30008ED76DCD2E12B0F53D176372BA7D741E5E -:10EC40005D219387DEA6F32F8D2774DDBB9C8B1D82 -:10EC5000302E9D2F214329163C49552D230991E83B -:10EC6000BC4D741D9B4326D241D7997D847D3FDBEB -:10EC700022C7BB22C09510931EFE178C477F004E03 -:10EC80004ED1DF41E1B2F38339F1E3E8F82F748B21 -:10EC900004E663551A1CBEB1B4DDC3E6A58D3BC9BD -:10ECA0002EEAE050421C3A7C149D8ED3B5B38FD12E -:10ECB00079D2F7ADD2F47880EFC5E64948B4818EB9 -:10ECC000E20CEDA1BAFEA3258AB7B1FDE3E1058E02 -:10ECD00087CD8007BAB017A23C55BE08F0DAFCA178 -:10ECE000B5C11F76FF3F3C142843E06AC26BF63182 -:10ECF000932740E173AEDBE401E0E5BB3AC5C6080B -:10ED0000E3149CD0D3676E77B40E5E44AC1E900FB4 -:10ED10009A8EB6ACDA1DD6FF1E4F4CC24907FD23B2 -:10ED20008FE4E1FA2FF2FE1F9BD555BB2D948E295F -:10ED3000C96EA2FD88AB9290C4FEFB13B29C325BFD -:10ED40001F1C892B9E2EEE52F0D489EF5D80AF7E82 -:10ED5000DEEF1B4765F0A4E0857EABC6F97EE88157 -:10ED600071423344F8FE838EDBC4109DF7238EDBA3 -:10ED700076017DEEFF935502BEDEF1A7AE24B8BF4B -:10ED80002F634B12D0FD3EFA4E10D667A658A36DE6 -:10ED9000ABBAC001F4F546F761E41F89046F1C9F0C -:10EDA0000D6D93A783767B39BD723019006EAF71FC -:10EDB0003AD9CBF97537E7D79DCD6ECEC7125E5FD6 -:10EDC000694EC7FBDB9A3DD87EB1D98BEDADCD3214 -:10EDD000B6BB9ACBF17AA8D987F70F365761FBCD2E -:10EDE0006685D161FA1D65208FCE255100D0752D25 -:10EDF000774C3347C2E7F5929ECFAE73EBF96C3296 -:10EE00008573787B927D98812F47E89E4FFCEA1AA4 -:10EE1000DDF3A2D399BAF684CF0A74FDF343A5BA01 -:10EE2000765ECF0DBAFE33CB2A75CF7D85F3F5F331 -:10EE3000139D285FB6BB0494CBD3B2EB75CFB7C399 -:10EE40001F2087ED825F4D05B8540E284F03801FA9 -:10EE50001BC091F1F1AB1C3F7B003F36C00B83FF21 -:10EE6000CB007FDA7E09E04DAF3967955D83259051 -:10EE7000030DD8B6A60F767A28FC5F768A28FFB7EE -:10EE80003437E27BFBCED59D1571BE0E09F0B29DE5 -:10EE9000CF679F45392B26405B90960B17CE2BA74B -:10EEA00047CFEFA3CB17A2DCDCDE7DDC01F4F6CA92 -:10EEB0005797A6F7B47EAF92CA49401FC5DD545795 -:10EEC000A55E5CFF697AEB62E36BFD40AF46D2174B -:10EED000C6716FF84A11095DC7CB3DEA0F62A01DEC -:10EEE000F89628D1766E8F3209F0B63B5D708902B4 -:10EEF000F69B24C3BCCF1FBE11EEBF12329B60DE57 -:10EF0000FBCFC71158C776AA776DB4DF1B64C49ACC -:10EF1000F114DE819E2FF7015FAA4E8B6714B97042 -:10EF20001E291922CA87CD636C26613CE83B330950 -:10EF30008C013E57109E5D5FA539E1BA395DE4F75B -:10EF400083C8EF5767B8F0BD97CF672640DB448290 -:10EF5000280F02674DE5FE08EBBD1ABE436548CE9B -:10EF6000F98F1C2EDA7FEFD93A07C897577AD8F86D -:10EF700039CB420E80D3BEAF3638E1FEF6F42C1CFE -:10EF800077C7D8A5685F6C3F6B42BADE3E669533A3 -:10EF9000331BD7E901D86D3F5BB72603E8BAC78CAE -:10EFA0006D89282408F496CEF4ECE6B375E4307D40 -:10EFB0007ECE23FA81CE7248E7DE4170FF8A555635 -:10EFC00092C6E06FBE82905BD9CB64924B2F074A0A -:10EFD0007BF4FAC41AAA9E3503EC08A067DA9E6A8D -:10EFE0008ED73DDFF7EEF2849980170A6FB8F7CA23 -:10EFF000D9DBF78D05F9E367EDDF1F7DDA3A985E1F -:10F000005BC6AE1A761BF4DBECF0D82478A2902F06 -:10F01000693BEFACD90FF6468E533F8F7D57572291 -:10F02000DC379F65F6D5B974B69EED9E7AF2007D09 -:10F03000EF656E7F4D3A36B202BEB79FDA4F60572A -:10F04000BCE4F94D7C16C833AFA8A3370A1FA497B8 -:10F0500073DD04C7A13F83A6523814B22E940F7DEE -:10F06000ADDFA1CFF7E5DB5CCB29AAB79FDFB9EB1A -:10F0700076DACE4B14894857F22DBF7E7EF93F7366 -:10F08000E8DAB77EA6B74B6C44E0FADC8972A03FA1 -:10F09000FE9970DAAA7B6FAAD9A61B378F843D47E9 -:10F0A0007C5AFB9EA75EDC3ED9C2E59A669F6CB196 -:10F0B00028F37D40D7C15917D1A3CBB9FE6D447950 -:10F0C000B195104F470695EB578B32F0E1B9A37617 -:10F0D0008463DE23332610D4D7CA04E00724C63065 -:10F0E0007BC07BF422F68A4B2509B9FC5304AEE6BB -:10F0F0009321DABF9DAAF9AF4187737D6E1CB73F9C -:10F10000BDFFA06310CAFDC232A6171E711C403D90 -:10F11000DFF501D5F302FB4688E27D36FC017AFF7C -:10F12000032BF67FE97A01E58866375412D94255F8 -:10F130001C99E63D6BBE9FE2CF67AF197B2BBDBE2E -:10F14000F46ED730E0DF97C03E40F9D0E860F6417A -:10F150008C1A4FA7B8ADC7867CB8E5B489D8C16F03 -:10F16000D866433AA57C7ADF58FA9D6D41662F74C4 -:10F170009DE6F6DE3607F2C98EDFB379742D733063 -:10F180003FE39455067B7CCBB21884F36829266054 -:10F1900086F19AD8F83D1CAF6F73BCEEE3FAEA75BE -:10F1A000AEAF5E057B02F517B32776813D41AF3BDD -:10F1B000B83DB11DF419BD3E7FFAB9F7812FCF6D6F -:10F1C0008B42BB733449DF04F3DAE6B4E23C8D7062 -:10F1D0009EA7E8F9606E95DE6EA818A3B71B6E189F -:10F1E000394CD72E4F1AA17B7F4AC2B5BAE765CEFC -:10F1F0002CBD3C324FD0B5E5F37ABB61BAF7463D42 -:10F200003DC9617603CA3BBDDF383BDC6F4C053C32 -:10F21000313F674BCFED88C72D47D3062B6176C2B0 -:10F22000560EE72D4799FEDC1AFA32468960477C74 -:10F23000C6FBFD96E3E314C7C77FA7C82732860045 -:10F24000BF7CC9E46F3F74ACBDAFBDF799FFE3412C -:10F25000E17A7DB828219368EDDF77BD3F1A9E5F84 -:10F260002A5F503A6D0F513CDF2DC67476D0575649 -:10F27000991B9F84B6AA9AC9C66C0447BA199F5FA6 -:10F28000E30179DC1AD3F85378BEB9C5E6DA900009 -:10F290007CF41FBF86761365051BBDFE312AC54F62 -:10F2A00028AB59334D38AF672CBE611ED09B826F9F -:10F2B000FEADB4BFBADEEAD9285D381F67A6A0311B -:10F2C000FB56D04322E7FB3F0B8A3393DE977F291F -:10F2D000A09C8E9208EA051BF105807F48833C1FA5 -:10F2E000F8839828FFD0EBBD594A1CF42732915C73 -:10F2F000741C646DFA3D21B8F74F029D978534AABE -:10F30000308EAD814A18CACF0F662889D8DF3C13EA -:10F31000C77F7E2A2120CFE872B09D7D177175C40A -:10F32000D2F911C5F4256DCFA7FE3E7CDFE4B80508 -:10F33000F5D4FBFF6DF28B11ECA55E38DF62391559 -:10F34000D2E82CED42FAE9E274B135D587F2D7F86C -:10F350007E6626F307B77C344D04FACAB60F92C115 -:10F36000AEA00B146750F9BEF5F80D8EDA08EF4D1C -:10F37000CEAECDCC1CD2D7CE0E6E126B9DE8CF8B0D -:10F38000B0AECDF46F58D78BDDA600E0F79CD38AE2 -:10F39000F2A4BF75E487F471883CB007C2F88D9081 -:10F3A0006AD7C96B01DE9DC2D7D786D3977C5F38F9 -:10F3B0007D3D7F217D219CEF7E2B1DE1DA2A30FAF5 -:10F3C00052297DC173B5B411E94B35115F6B36D24B -:10F3D0001BBEDF64B6BB6C54422ECD4C43BAE98AE7 -:10F3E000A9783F20E1F746CC447FAE86FB733528F1 -:10F3F000E75F3FC2E4BC715D3B8ECC1916027B62B5 -:10F40000D4DC61C0E75DA00086C2F473E7817DD9DA -:10F41000DBA6E8423B70328190157D9E3D4F86FE13 -:10F42000D76BED1CD6BF84F55F92F9F07A159E2F4D -:10F43000E0CF4925EBAFB5D5BC7925D0DF62C2F668 -:10F4400007BCFF431E7929D0E383197203E02F0321 -:10F450008C167AFD64BC7C33DC5F9A4970BD778D75 -:10F46000976F096FFF669C7C5B787B73AF9FDAC9EF -:10F47000FDD45BD12E7DBD6726DAB312F1DD087AAB -:10F48000E7F5208B476D1E39B01F7480DBF3FBB9A5 -:10F490009FFA06C8A3AB409F303F750FF7537771B3 -:10F4A000BDB283FBA9DBB95E7999FB492F713FE9B6 -:10F4B00005F053AF023BA48AC749989F9A3D6A5210 -:10F4C00019DA112ECD4F4D89E8A74EF7EAF5CD5444 -:10F4D0008F5EDFDC981E6FD02F7A7D332541AF6FB2 -:10F4E000CA9CD71AF44B96AEBF7C5EEFA7169F2D31 -:10F4F000D5F52F3CA5F7530B4ECCD4F55F9A2921B7 -:10F500001EBD476FD2F5CBEDAED3F5EBC39B0FF12C -:10F5100064551F77821DB779643DC71BB31734BC90 -:10F52000755D046FAF72BCEDE178DBC5F1B683E3C6 -:10F530006D3BB7075EE6787B89DB032F70BC6DE11E -:10F5400078DBCCE30B0738DEF673BCBDC1FDDDEC28 -:10F5500051BBD03F3B779A70BC3D2146C25B79924C -:10F5600068C083C380073DDE4ACDC30C784833E0D2 -:10F57000E11A5DBBF054A6010F05BAB6F768A90100 -:10F58000FE3718EC864ADD730D6F533DF30DF455CD -:10F59000AFEB77C9FCE66476DE5FCB6F7BB91DB756 -:10F5A0009BE36D27E00DE3441E1E8FF0F2B82FB3EE -:10F5B000E35EE478DBCAE3425D8037B0EF38DE5AC1 -:10F5C000479E413BFEDC790D6F0722E2ED72F9EDBB -:10F5D0003AB73E2E34D9A58F0B4DB2EBF9AD84E886 -:10F5E000EDBB895FE9F9ADE8B4DEBE9BF0999EDF23 -:10F5F000F24333756D6A0724640D013D7593EEBDCA -:10F600009C609DAE1FF59398DFE2E17ADF5F89FA97 -:10F61000A86D2AD38F940FD1FE7EE67BD40EC8E866 -:10F6200083C7F306FFE9F97EF4F7E82C66D774BDCB -:10F630005F8370CD01FD1DA15F06EF9791E5C2AB21 -:10F64000CD4CD4E84C9CE6EEA1743EE691CCEE3174 -:10F65000C7AC812003FC044DB97D7692E8F4111803 -:10F660009FDA4B195961F6A0D9D548C06E106D0FBD -:10F6700055C3BA8868F2A0DE35D847A4C125DF0E8D -:10F68000F76F1FE4E9A0B05892158BF370934D16F5 -:10F69000B033EECD920B605C711283C7E664EABBB7 -:10F6A00053786C8E626D95C26B236D8B83AB117E2C -:10F6B0005D145E62068C9F40EEA2F3AACCB2323893 -:10F6C000CC235C9F6ED4EB43301868FB9968D69EC0 -:10F6D0009DF5CC3C35A94FFFD6FCA66BBD4AC7199A -:10F6E000ED1C5A4FC6D171D7A97160678EA1F30383 -:10F6F000F968726C4B8E647FF76787A9E3E4594021 -:10F700001F7771FD3A9A42C49CD9FFFBCF44FBBEE0 -:10F710000DF8CD067884C5BDA66631FBAC12C6C90E -:10F7200041FB520EB72F49B012DB6D198CBE7EB271 -:10F730006626D29B93C24B8C85F933F8CDBF93D10B -:10F74000D7E5AE439BFF0074E20BB7A7C3E8E4AE76 -:10F750004874422A3C6EF4D7FBB3E75436DF566E4A -:10F760003F6A76B22D49B39BFD1C0E24501087577B -:10F770003299C235CE45305E53E332F9FD146451FF -:10F78000B19902CA9D3281B852617499303C564891 -:10F79000E1F2C7181FF41E8D36C8F738831E1EAA63 -:10F7A0006B179F4D33F889D70CA8E7CB9C130CFA45 -:10F7B0006992AE7F79D28D063FB6D2E0E7EAF58452 -:10F7C0009998558E2F13C62D544132E7C27D82F889 -:10F7D000097B8E7E672F9C1F93AB905FB95F63E4BC -:10F7E000D77BB32484B3E0627E8DC60FDAFB1AFCAC -:10F7F000AC6E86D7B5B99A7EF2A0DEB105BE4520C3 -:10F80000AE4A6D68795318BD6D68B6BF5F368A9091 -:10F81000A79BC9FB651479FE66175E9F6876E3F5C2 -:10F82000B16609AF8F36A763BF75CD1E6CFFA8D92F -:10F830008BD7879B65BCFF507339B63B9B7DD85EE9 -:10F84000D35C85D78E6605EF8F342BAA9DAE6B6493 -:10F850003BF1A87429A33AE9F7C2E036A29DCE2372 -:10F860000CEEA9AA4BD71EDEE4D6F54F6E9474CFEA -:10F870008735A4EB9E272A1E5DFBCA2AAFAEFF1078 -:10F880009FAC6BC79797EBFAC7CA3E5D3BC653A5C3 -:10F89000EBEF485774CF7716170C0E0DC0C70F3516 -:10F8A00007820C2EC12083D36B41069F1EBC9E0293 -:10F8B000F94BF118670EA2BC88CB7651D2A1F8B2F1 -:10F8C000B3FC5ABCD923C4868D1F5F4EC74B0F9F14 -:10F8D0002F1D4FE79FF9915E623C41DD7D477A8F96 -:10F8E000EEBDC9A2B314F211870A458C7B1D2A8C88 -:10F8F0008F01FBE53E8B6B6A36A5C7834744CF0675 -:10F90000780F5E88202F8F71BDE8186747B9307D6A -:10F9100085B04144A265EFD7758F8818F73CF87D14 -:10F920005205EB72EC7C4102BA985E581B1F15E63B -:10F93000AF4D0FFCA9CC0DF75764E446D1D1A6B763 -:10F94000A75AEBC7F4AD4BEB57B7426F5FF6D1BD8B -:10F95000DF0EEB18AD7EDF0EF2AD236903B63BD2AE -:10F9600007CE93FC96DB619F713BEC248FC39CE038 -:10F9700076D871EEF784B81DF621B7C38E72FBF905 -:10F980003D6E87F570BFE76D6E3F7773FBF930B75B -:10F99000C33AD29F9B82F2F097021123F8A9DAF5BD -:10F9A000DB3FD3DB61DFF2EBEDB0A5EBF476D8E221 -:10F9B0004EBD1D56DFAEB7C36A55BD1DB6B0496F0B -:10F9C000872D68D4CBC3F90D9374ED798A3ECE367A -:10F9D000B74A6F3F6BF899EDD3CBC5CA72BDFDDC5A -:10F9E000DF7A5F0A5C8FF91F40E2C7617AAF379F09 -:10F9F0000B7A85D245F679AA57300EEE6B85FCC995 -:10FA000056E842F56F9129F816E47DC8DB2281B8EB -:10FA1000D3CE73B915D323D05FAEAAA79BEAA3FABE -:10FA2000F8C64D77EAE13AE316BD5F622DD7C355BC -:10FA30004ED2FB2595463DE3D3C355250A01BA3482 -:10FA4000EA1B93E31609E4F7E5EA1D2BA17A85B5D5 -:10FA5000757AC70A77D274CF51EFB467B3785D2E49 -:10FA60009D07180B2D5179FB3D146E3BDF35639DCF -:10FA7000089DE0E19154FF14C3DF147E2F5B14B5A1 -:10FA800011F26C3C2F42C453BBBE43FB5B87B1BC3D -:10FA900008F9CA7C02C657E82FE02B97D076989ECB -:10FAA000CB09B2E761F3D53DFF31E06CC0F9C887FF -:10FAB00047E6FE4FCE272601EC21329E8CC77A8383 -:10FAC00050DC25C5578DF7B303CC0ECA4E62769035 -:10FAD0003779A6C8F34F04421E5E13B1633C3385E9 -:10FAE000F837429C337ABF631A6DB6C29089E0271B -:10FAF000E9F97F56C5C0F979A31F76BD34C2E0B7D6 -:10FB00005D6BF0EBF4FC6F2306FB254424B027115A -:10FB10000726DD7384D3614E472DC7DAE6C3BA5E8C -:10FB200048E6F9154E3F1338BE08D9B4AB963EF7F8 -:10FB3000BA4502FE868DA8F1E3A1BE28D82843DE8F -:10FB400021CF6B7321DEC4651EB44B4F31FC78E9C5 -:10FB50002FE0CF4BC2F005F83BAAC79FCDF0FC24A5 -:10FB6000A7A70BE7C5E8E89F372F035D39E32EA968 -:10FB70008EC578BF24288B31747E7B5C02E651F7FA -:10FB8000041B8325B47DC6CDEA865625CD34E37C9F -:10FB9000893C6832C5C314BE5E2FCF6B753513B474 -:10FBA0003B9E6FB6E395904611E4519BFBF678D0EF -:10FBB0008F5D29CA30A84FEB1A12BB02F2F39B2DBE -:10FBC000B14991EA5A7658F2509F76ED48344BF499 -:10FBD000FD12B3CB0CEF9524D589E0EF5DD743D070 -:10FBE0002E28492298CF7ABE3970887D4FC13A1CA1 -:10FBF000BA8E49609F96B96A27C524407C96DA364A -:10FC000012D8B9B1E8BFEE1E6243BCD95C4BCBBE83 -:10FC10004BD7772051248297E2C7433C01D0034958 -:10FC20004E8F1F86735B8E039C1BE8EFD7697D7A2E -:10FC300081F2F9F1707CE491B036E615F4EDA1396A -:10FC4000BC0E8AE347220AD659B4F5B0FA32128ABA -:10FC50009C67F988DB0D5A7CFF28B71BDEE371B780 -:10FC600043DC6E6833C46FDEE276C36E6E37ECE55C -:10FC700076C36BDC6E7883DB0DFBB9DDD0EB2F1028 -:10FC8000B505F28AF3883D04FEC2815A0667F70A79 -:10FC9000C15F0EF970A5D3574AEFDB5658507E0E60 -:10FCA0004F525B203E6EAB5227C33ADCD59D2D7080 -:10FCB0006D29EE4884FBF3949347C1CF067A999A55 -:10FCC000CBF99DE261AD95C179DDE218CF72A067F5 -:10FCD000654905F64B6270B3D35F8077E222550029 -:10FCE0003A702B161DBC6B0DF09D07ED30F9110D10 -:10FCF000F448E179BD06F72C92C5E0AE4601DCA3DD -:10FD00006A39DCD31322F2C93A0E770D2E3B8A6F83 -:10FD100036A9B4EB5B49AC6EE2ADC29B4D07E8FC83 -:10FD2000BB6511F3AFDD49BC4E907FD738DE3BDCBD -:10FD30009E5D5B3A70BCEE20EFD7DB6E27926D7054 -:10FD4000D838A5F75924FA7E55607532F0C5DA41E6 -:10FD50005A9ED883F6F564B1F0CD543ACF20AF83E4 -:10FD6000D4E4E51CC26163F8DE5B7C9DFDCDE7ADAC -:10FD7000D21B2D121D7756E01E02DFB3991BDDE169 -:10FD8000F5A5DD7C7EAB66DC41802F8329A71BD0E7 -:10FD90008FF7D924B0BB87277956021DB89314CBAF -:10FDA000F7E8FD69541E4A2E9856E78E04E847DFAF -:10FDB000799400BD5CB309E8E1AD643BCA9DFEE601 -:10FDC00073811EF113B447FAD32354FEA03D64ABF4 -:10FDD000F8F428F8B595A4D113A0EF05B33D4380FE -:10FDE0008F499505F5733AFD0DCFAB69D74A83FE70 -:10FDF00076782D03CAE1E1E79BDBC1EF780BF807CA -:10FE0000F3A02406EA73821577D8013ED393D37604 -:10FE1000027E48893D348AC26155E1CA0500AF556A -:10FE2000154B5D02D055D1087C1E2CB19F848A9C55 -:10FE30009E9255C95218BC57AD26C50AC03BF92E33 -:10FE4000F712BAAEB4A43F342B946F7A2CCCEF796E -:10FE5000A7F47749A961FDC7E694FC2C07F8DACD31 -:10FE6000E87CB455498B541FACD1794B7134C665CD -:10FE70008ED7B27A057A7F65137D55A1FAAAC3D3CE -:10FE8000C7C78B393D458D3ADB00FD95D53609FD59 -:10FE900033B1BAAD89B6ABC05E02FBE9610BF2A526 -:10FEA000C6CFC98D7AB9A918F8B6CAC0D71A3FED1E -:10FEB000BC908F6300AF51B58C9FB4F519D735EF67 -:10FEC0002B6AE7C41362F4EFDE5D34229AE9B130A5 -:10FED000FB763CCA26C94AD7378BD3D32C4E4F94D6 -:10FEE0002477C07C0EDE33622AE04B6DA17E00CC0D -:10FEF0006D99A5CFFE4D837592415EBAFE594D6254 -:10FF000006F8A7E44E4B1F3DA6E9BE87F50273C273 -:10FF1000DB40AFAAFC0ED81110CE848FFEF1D8A121 -:10FF20003DADF47BDD43E3498B07C73BC1E4A384CC -:10FF3000E31D2C140779E1F9BDA33220854FC2E9F6 -:10FF4000958E1F52D9F39A7B4664A2B9C9DB1F2D47 -:10FF50001B021564C45761E9EB0FFF2B3323FE67C7 -:10FF60002F133640FC6FB4F8C5E95DB4FFAC4A9B73 -:10FF7000A7958E3FFBC13A0BD8FD95AAB2A79EF676 -:10FF8000ABA474E177E13A747C72D84C2C30CE612A -:10FF900059209DB43D6B969E6F6A96E9DB467BE4E3 -:10FFA000488C9262A2EF7F2AD8C8067ADDB17EE93A -:10FFB0001330DE270FDAB0AE90C0B772410F101EBB -:10FFC0009F949FB8873EAF5B6723901799C7EDFD5D -:10FFD00041B9A938AEC9518DEFD776C4A05F7C7204 -:10FFE000FD95E300FFED718DB7413DF527B14A0D59 -:10FFF000E0B56ED5B526888FB447774E86FE9F9ABA -:020000022000DC -:10000000886B43066D4B0F59603E3DD43E8078AB04 -:1000100036CFDAF630FCC37773591C779A89289B60 -:1000200022D8350FE6F6D627A8B6B0F93F9C2BE1CB -:10003000FD6969716D3F80EF50ECBB3C1C2EB0EE4A -:10004000C92C2EDA9EE4A91942DB2704E25A9E004D -:1000500057F943E04FF57E1BD988E827D8DF3A6C83 -:10006000E8531D61FEFF383EAF8F63D9F3E3EE68BE -:100070003FACF3B8C4DAAADBE9477A362BE97362FE -:10008000D87A842B6017049BDF9118C99A86F820D0 -:10009000D273745E750F3F82F8DD4CE103FCD9E347 -:1000A00092DA76D0799CA4CA5A85E7EE4727033CBA -:1000B000EFC8A4849A78219CEECD8DC3F99C5CD7BF -:1000C0001A8375262EA258AFE883476DE796BB8545 -:1000D00071A8E755263F18FF09244CBE53FC4ECBB0 -:1000E000FFA1A50ED61B453A012FA6DD2BEC30CF84 -:1000F00079B516CC8F3989AF1CE469EDC302B6E936 -:10010000CF1AD017759CBFDAA5B8BD40C7C7C11EAE -:10011000477FEFB13D501F50CBE557D5223D9D2E77 -:10012000769B75FC32A349CF3F749DBAF6FA5C56B4 -:10013000D7D9E3FD2401F4733B5D36C0E5D336C166 -:10014000BF01E5AB2F25BCBE2E35D7A4C5E1254B9D -:1001500018FCEB28FDD581DEB093CED24458F7A829 -:100160002940EFD623D1384F237CFFD5E1F071B27F -:10017000543384CEE7634AC750FF737C7D2BDA2F5C -:10018000F023EAF8DAD506F4BD84CEF25117D2A7EF -:1001900075C6D83E7AD1E053BB2E752FF4737F1EFF -:1001A0002351E789D4BA0B96823DD94B4706F8C054 -:1001B0009ACDDA7746F4D1193E8F406793685F6E27 -:1001C0001F23BFD496F5E6F55206AA5F467C1700BA -:1001D0005EC7CF873C9426E7D616BF817470C645AC -:1001E000FC22F36BDF06B91FC3E7A61239509F004C -:1001F000CA84EA5D17DE437F399EAF37B64978AFD0 -:100200002C8B90B826F1BD327A33B62C18003D61A4 -:100210007373BDBB2DEFD7A3AF80DD0D04E3348333 -:10022000A22B3C015C8D2B11F729585C8960FF3CA7 -:1002300028085510B71F44F47655BC011E24DB7CFA -:1002400022DC2E8FE6F27EE9E41102FA3BE57AFF2A -:10025000D46CB08B7EDE4BD76CFD12FC49E1D846E6 -:10026000FD3790537181CE4EA0CF1A6AB7FA71FD57 -:100270001ECCEB58CB04F2A8D017BFFA67C52F2EBF -:100280008883F1F8457F71302D1E50C96E517F472C -:100290007143DEAFD24DFD9C416067DDEC46BFC9C6 -:1002A0007D12ED522BB74BA3462D72B1FC19E31F03 -:1002B0002D1E60A42B635CC9C87F46BBF4B7B9DCB4 -:1002C0007EBA865C7339F1012D8EBF2A9DF93DAB54 -:1002D000D2EB9643FDDA39EEF7B85413E271CE2C27 -:1002E00001F1A8D96B73BCA76701FF69F50717F384 -:1002F0007B3A0C7E48B4F729598EA03FAD792C2E5D -:10030000E42864CFE7D889D91E963FB0E5313D3760 -:1003100087EA413B5DE234BE8F683AD1E7A7E2F855 -:1003200038DA95FE04337375F5827179EC3EE64355 -:100330006D3C1F6AE7F582251967777D0DF76556D5 -:10034000076C936B1FFF1E8543F4AC188F09E957A8 -:10035000D9F843F093673950DE26A44B58F75A95E5 -:1003600064F720EDABF2DBE097A19D29C194659481 -:10037000B77329FF065C03F83BF681E3664ECDDFD9 -:10038000296474D51B5FF231F96DA2BF404FB3AB46 -:10039000F4F4325719987E32F3787C89EFE31A1D12 -:1003A0003ABFE36BA40BC6BF6B53583EFA5C05ED36 -:1003B00003F9DB7EEC71CDBF755AA85F44F112944E -:1003C0007721BD07D389251CDFBE425157DF10CCF2 -:1003D00027D12EEAF7042D24F941DA6F903CF70675 -:1003E00017F8BE25B6985AD41B7E9D7D7F908E7BD4 -:1003F000CCD9FF3C8C74BE7AD4128CFF3F703D0583 -:10040000199DFF6A483863FDDE73F3C16F7B00DA24 -:10041000585FF08BF9506FF74094D6EEFAB11C5646 -:100420006F70E796977FAC1652BFC64EF52D1DCF65 -:100430002111CC5311B209E5B308F14090CF63C24A -:10044000E08B7E831EDE463B5E2C647114D1C0F7C8 -:10045000C6EFDE9CA7DF6FD7DFBA8DEFD19FAA6B07 -:10046000F4F47F7BDE00F5B2C6F79D503F1173F9BF -:1004700075075490627E5A24260FF8CBA494E0F7B7 -:100480000417A32B9030A0072D8D833C0837DA8EFC -:1004900002BDE0776871559C7414E05F847C620053 -:1004A000F5399D4A481801FDB5FA03857CEDB8740D -:1004B000B947E5318E2395B3FCF2BB3209C1F7464B -:1004C0003FBACE970BFEFA11AA6725D0E337AB10DF -:1004D0002F3BBB8C607EC0E152B04D3F156A754129 -:1004E000DC8AB56B288C402FDBDCFAFAD71DC58F70 -:1004F0009658E9F3B632166F3DD81C787705A5B546 -:10050000B6C20294972BA063D87C833BA3AC108720 -:1005100051D4EFDAC16EFE689968856B7079AD0AC7 -:100520008B7E3751DD244810775008F8F9D665AD39 -:100530009381AFDEB5A89E3827E655314FDCBE5C0F -:10054000BD15FC1E59AA284FA57CB4A1DD8CFB8CDF -:100550008E95FE2E490AE3C3535C9E1ED811F5000A -:10056000C06195600F45C1D5A26C589D00DFB37A7C -:100570005AE814DF6DF941327C67D5E2559E9DF053 -:10058000BCC5063B50C9AAF5F62A187755F212F7F2 -:1005900092B071EDC3AC8D703F38B40DEB5A9472CC -:1005A0008F352A16D6F5450CE467DB9765C5032D14 -:1005B000B6255A53EAA1DF923FBE990778974C9827 -:1005C000B7B5BA3B2DB0EEE16E4585FCF85F72948D -:1005D00057F3E83CE7351D9B8C757365B12BE13A09 -:1005E000FCFC77DA01FEEFF2784C28B10EF3B56D22 -:1005F0008BEAED30DFE98969CBC3E3316D858BEDA3 -:10060000A3E97B696E53EDD24117D2471BC45FC685 -:10061000C3BCE87AC642BF3F342BB45F28D95A1511 -:10062000699FD6F13CE6EFD95B97A6415CA46DBD0E -:100630001DD233A44D50D6417E404D7546AC631F4C -:10064000EB65EFD528AEC95609F183FC762AAFE7F2 -:10065000C7EA48B02B19FEEC6662B784E9BFB1392E -:10066000259FE685F9D1177C37B10DF5419BC0F880 -:1006700077ECD6CF7F0CF5C2BFCAF17D0EEFAD6A25 -:1006800057D601BC886A27838AFBE793D06A9242D7 -:10069000A83C6E6BB15545AA430B2D12A7019F5084 -:1006A0000E3A3628254C2E2FAF4F83F848A8E52A5E -:1006B000E4EEDEFEEBED1F021E42EBD363411F862C -:1006C00092EBD2D2806E395D1AC7DF94C7ECC95F56 -:1006D00067F92C5EB02BC7B0BC67459ECFE645BD21 -:1006E000DDE9063BF71B40B72930DF7F22DDA29E04 -:1006F0003B9E770AE98AB82E2D1FE9232133E65362 -:100700008BFF8CF1DE8EB1DAFE27161FD4ECDEA84B -:1007100051275680DFEACBD7F25D857BC05F9FA66D -:10072000E5532B587CD0457F23C5077D86F8E03400 -:10073000435BB337A778B97DC2EDDB24A9D3570A51 -:100740007277BFE8017F229930BD32A342F0839DCA -:10075000DD521C6DC779E7F33827F7BFE6F179BFA3 -:10076000D76C27904F32390A57C2FCA715B0F93B16 -:100770001A32720212C87716E7260D3609E3268070 -:10078000FC44D2EBA7F96010BA9E790D4BD1DEEF95 -:10079000835F0B8BF310BD3FE12306FF6111B3C7ED -:1007A000347F6BBEC13E30DAFBC638755F5E609346 -:1007B0001DE8E9EC98CC8369123E56035A3E80F658 -:1007C0005BE8ED5E190A933FDD5C3F1C6E96DF5BD4 -:1007D00041D7BFD2F7133BD06987D96F077DD2517C -:1007E0007E470CD05F47B5580E7C1F6C2EC77E0726 -:1007F0009A7D786DF6327DB12F47BEDB1B1677AE42 -:100800002C2F796F4578DD837CFD7B2BC2E63FDDA5 -:100810003B43D7D6E86CBA481A3745902FBFF2321F -:10082000FE3753BD8F7586E22F3D03D5DF507FF530 -:100830006C38FCD678F5F6EC7D634A070F64B76830 -:10084000EBD3E0A2AD5B7BDEDF3CEFFA1BE7F9D434 -:1008500065CED3383F6DDEFDF59F0EC28AF2FF5D97 -:100860005B4BAAA12E765F8EF22CC8A3CA326125FB -:10087000E44B0FF378E2E1C218DCE7BE279DF97B79 -:10088000D10D8C6FA2CB6660DEEF72F17B9397D9AE -:1008900095B30A05BF4CFF9CC2F7DBBF97CEF2B9F8 -:1008A0002DC53F7F13F2D0EF145958BC97C8D3A67B -:1008B00086E5B1D65AFD01C827BDD75BA771CBCA63 -:1008C000BB683B5A932B55FABCC3AC59FAFCE17494 -:1008D000439E21DA2057821ADC7329DC47F4C1BD1C -:1008E0003F7FA23FFA20E6D3D9A0878CF0B9CD0094 -:1008F0001FA3FF327D9B811F2ED18FD9D09EBD07B4 -:10090000F26A2AB5274701FEE0117D2F5A7E16D3E1 -:100910002051F98C1E47874EAD01BDD84D5500E8DA -:1009200097B533EF5807ED7354EF035EFAFB8EE68D -:10093000BFFD2A473EE38D503FD02B47C03E180FE6 -:1009400079C1C8F641F7A2495323DA0733EBD372D2 -:10095000605E33F4F641F7FAF2C7B3E03ED807F42D -:10096000A73BBF5E671F90F2AC8BC087C9DDA85163 -:10097000D911EBF47C398A2B3F6C3D8EF446125E24 -:10098000CFF879AE1C9B4FDF9FC1E308DAF7A8FDD3 -:10099000B5DB12A17E51FB5EA697C53D49793CD3DC -:1009A0000FFC7A313C6A75D4F759643CEF458B7B78 -:1009B00069FD3CF94CCEB6A7C90DF09C38332F32F7 -:1009C0006E8B16E748CFB882D70D4BA4D71FFAB36A -:1009D00020E1F308FE1E81BC6474D2E9DD2EDAE565 -:1009E00013AF920370283AED57211F62AB10D05E0F -:1009F000B22511B46B2ED5BFBAD47EED501C00FECB -:100A0000561D8B97976498B11DAD881B402E4C3CAA -:100A10003F5800B9E153C4A760BED1F2179FFD044F -:100A2000F435D5FB1087F19146DC67EDB4F8303E24 -:100A3000D1514147CE8038CC724B1AC6D3539F8DCB -:100A400071C3D7FCED102FB779D87EA82AAFBA12A0 -:100A5000CECD985E344A20F4F9341F8BDFCC81F878 -:100A60000D8C3BEBF40E88FFCCF632F9057E1BE8CB -:100A7000CDB9F5778FFD91F4D7C46DFCEDF1D918A0 -:100A80004F92305E60880FD90AA7607C48AB53F163 -:100A9000158AB8BF9B2439F11C0A637CC718CF3173 -:100AA000C67B8CF19DEFE6B37D1A9A3DD598AF8F4A -:100AB00017DE0D7B1072C05EA2A292F275878524AC -:100AC0007752FA3C58F229B993CEC3F94313D48034 -:100AD000D37E7A3BEC52E55690CA958F6121BB5E7E -:100AE000B7807F5B2DD7627CCF48F70FE5B378DD09 -:100AF0008A7CA72E1F1C6C6EE2EF47A980E7EA9163 -:100B0000567F546ADF3897CA1F8FE6CA0FE433BF97 -:100B1000A213E89C7814DC4F5091E7D2D12D691CC8 -:100B2000423E0E8BDF18BFABCD471BFF72E7713F14 -:100B300087F7A5F2C9DAE202BB957EFF0CC5B18842 -:100B4000FA921AD461F1692D7EAEBD570379832CD8 -:100B5000B02305CC1F68F7C3E2D866A0DBE82445C4 -:100B60008E74DED4A1FCDE3C15E631B5EF104141B8 -:100B7000B950CFF335DA7866E26E413E00DAD6E658 -:100B80002546889B138FDD4649A66E8D4820FEE3DF -:100B9000247227C49FADED166C13B56A2FD8E98B6C -:100BA000385F580BA7EC85B89AC617C6BC8D554C54 -:100BB0009A02C3D677EAF357C6FC94D19ED6E2EBED -:100BC00066FA1198D7FFD3F04115B57869EB7D0A25 -:100BD000D7F30D5DAF46571559DF7643FD495B945A -:100BE000B2AE96CE4B7DDC8EF10A07CC0D6012A022 -:100BF000BF20271FF7FE04E4EF5FF2D9F9376D023B -:100C0000AB47D99DF88784F0FD0B7FE1FCFB74BEF8 -:100C1000C4E222661280FD52644C02F285567F7255 -:100C20003091D981D38B1607EEA0ED5FF07AC96BB6 -:100C30008B366AF9FE4125B9044B3F002E6BADACF3 -:100C40002EEDE0D566AC2723E2FE9D7724F4D5EDAA -:100C50005EBB49EF57DE98AEB7078DF69FD5D08EB5 -:100C60002BE072ADB7FE44B1631D5922AF23E3F30D -:100C700037F2C9CF9A595EE3E7BCEEFF977CFFE5F8 -:100C80007FF1FABD4D7CFFE5737CDFAC06F7FB2CF2 -:100C90000AC6A38F5D4F6DBAD8BE38E0DAE27BDDBD -:100CA000C0C7E30B587C68B2E8DC097AAA6F9FC51D -:100CB000C0E7845596EBF366B37DFABCD9DC2A7D98 -:100CC000DEEC0F59B2A76008ECC368580EE714CCED -:100CD000582162BE726DDB19D4B3E70AD1DABE5077 -:100CE0003EF07D18DA3E0EED7E69013BB7C8B133A8 -:100CF000D102F5F83356C44E81F83971655E92FD24 -:100D00007603C4DC613ECB5D16380F62462011E3EA -:100D1000A1B5ED9737CEEA5157609CBA37CE4FAEAA -:100D20005900EF1FD2E2FC6AFA0288F31FE271FE5B -:100D3000EA826B1F07FFE8E97C7926C06359BE5C35 -:100D4000599003F7995CA0EDD9E16DFAF35AACFE26 -:100D5000FC896A78AFBF78BA3849688C542FB2B82A -:100D6000A037CE5507EF137B6F9C6B116B77E23E7C -:100D7000BB26FEDDD6F748038CD3FA2269782E8293 -:100D8000DDFD9D02411BEF16982F716BFACD775B4D -:100D9000A4F1445B6C0AF8FDC7787D9971BCA6028A -:100DA000B61F938E7717BE9FD43BBF261C9F8FD74D -:100DB000B77FC615034CEBA8514C3D949E489B88C9 -:100DC00075278E2ED754A84B225346601DCBA1B257 -:100DD000CA7F89FD3487CA7EF36FB99FE63705A9BC -:100DE000480717DB4FE398499448718D97385DEEBB -:100DF0002CCC1A1C1A004FD6A67D41B0337ADB6684 -:100E00008540DECFDA7400EFDF17E5AA89685F70EE -:100E10003A6D2B5BE48394D0AAE42962B8FDF2BB5F -:100E20006C654F4184FD8967469EDD05AA69669918 -:100E3000601612D0DEF608547E662F9B21BA25423A -:100E4000BC8D0F4EBA923E9F9544FDBBB0751734D2 -:100E50003CBB8BB22B292C3BD49A40FBBD98AB1CDE -:100E600082F18BDDD26E68CFF26560DDFB7DB1046F -:100E7000EDBC63A3ACFE0DA917CEFB049F3795CB49 -:100E8000CBCD972197DB9AF5F9EF55C9A397C3FC12 -:100E90004797921048D834F7E912C8FF8DCD514ECC -:100EA000005FA5B9896C1B87F7651296BF318E1B51 -:100EB0003581E9DBD1A1A4FB219E7C50F3F78B2F78 -:100EC000DBDFFF221CDEC6EB31CDDF5F19D9DF3F50 -:100ED000B6283E723EA0ADBE0EF201C756EAFDFD39 -:100EE00063EBDD35B0CFEF18F7F78F4DA6FEFE9818 -:100EF000FEF301DA3AA91CB24D00B9D39B0FE0769C -:100F00003B8F6BFB72E468784EFD79075CEFCD9206 -:100F10009D13E0B9EA5A80FB9149E47DB2E4319730 -:100F20000C7E8EB6AF3DD3AB0C81F7B5FDB2A341BD -:100F3000B4C5415ED4755B247A9626307EF9EBF316 -:100F4000A4BD794C13EEA3BEC438FDA5F693BC9B9B -:100F5000583D8E99D519462596BA213F756E8C1D40 -:100F6000F57B3BFC2F4CAFA61428B91386848F6306 -:100F7000385F55BAB4EF6A75FAA0AF40BF74135228 -:100F80000EF2E681D8468C7B9471BC1AAFD74D70B7 -:100F9000713DEB4A0078A614F8A620DE9FDF24E11D -:100FA00039B0FC7E7FF5FDC6793C63F57D80FBEBB7 -:100FB0004B4589D5E511E48BABD25DA8A735FBABDA -:100FC0006E422A3B578184465AE93A5BE55DCE2C56 -:100FD000DAEFA3C7CC19F0DA4F638805E6ED4BA72B -:100FE000728EAEA3D4AD0C1F483EC28944262F5C3E -:100FF0000382C98DD778765505B87F013F3E767656 -:1010000008D8E33F7D9CE5A7AE7A7C91BD2E6CFCB1 -:10101000472670B999C4E65F230B7E2915E6731A3B -:10102000F350332493472690373E77642EC409A9A2 -:10103000FD360ADB67B01D944C5990D7FEC8FDE51C -:1010400011E87FD5F7175F81F4CFE1B17059D6333E -:1010500068E7E728DF03FC070BCFC48C188376FC16 -:101060003AA0FF8502F145B213EEE778BB416EBCB2 -:1010700009E8EC06D94660DF5AB0C48670FF699172 -:101080002081DF3A1D681EE2398F9931DE4CE17113 -:101090000B3CDFEF71E0B9D1A5F2B36668FF61AC3C -:1010A00040AE1C401F5F365C0BCF0C017EFC08E895 -:1010B0002FC2FCEB38FF6AFC44E15E8AF39259BD13 -:1010C000487F74F579BEBC0EE8B23D4D69C073111E -:1010D0005D332FE95CC4E93FF363ED9EEDE9C6A102 -:1010E0002442FDD741CE27C6FBFF3981F9054B3895 -:1010F0007F5CF5F8D9FDD7035F2FB3B800AF4FE79A -:10110000FB7E0178EBF5BBFECE7264B2588DF80B16 -:1011100056D0B9E3390E2406DAD3469A117F6A29EC -:101120003FE7E32EE26A8DC5B7B06D5F26209F3999 -:101130009C9D5560349BF31B8FCC86F74A44DCD7CB -:101140001FB6CF65C03AB210DF7FD606FBCFA82D01 -:101150001F5C216AE76E1181CAB6609999DBF79F1F -:101160003E2ED33F9FE1F5991F14894F407DE61134 -:10117000136B1F2A125396D3EF8452D83C3A1E1495 -:101180003C2D125C9F5A07F9CBFA26C1534EDB3532 -:10119000817B7A20C4B5E4611B0157E1931F2E9D2A -:1011A00002EB39E32678BEECDC44C6374A90F84DB2 -:1011B000A97DFEED87C9C4AFE54B611F9D97EB99F3 -:1011C00087601F1B9DF775EA77D5BB216F4AFD5ECF -:1011D00088ABC579583E333A68F6F809F8BBAC3E9F -:1011E000B2ED7E813C04E3886B5AC13FB7F17ADDF2 -:1011F00068B916FDC7384A9F1268D09059B78FADAD -:101200009E2848BFF1E5943332E0AAF78FB32FB29E -:101210009F6DEE8221B1C02FE726E8F765F4175FD6 -:10122000D7AE70DE0DE0A78BE757B752BB1DD6FBDC -:1012300022B5DBE1BA8DDAED701FCEA9862BEC6703 -:1012400083EB4E6AB7C315F6B3C115F6B3C115F6F5 -:10125000B3C17BB09F0DAEB09F0DF71F16A981C122 -:10126000009F926802F9A1360BA33335D98AFE4656 -:10127000A08860FE3E986CDDB01CE27502C3931A34 -:10128000CB9E0763949BB19D3A86E577CD9E14D89B -:1012900047B842182381FDD46E55B07EF9D8723319 -:1012A00081FAE5D054E103C8BB10C1E411A97DB3B4 -:1012B000FDEBDB10FE8B656282BAF4E5706E28C828 -:1012C000E3CFC806169F0B8A70BE5C6B0CE1756499 -:1012D00037F9654A7F2705ADBD57017F7422C404E5 -:1012E000907E7729F07C7193C0DBAFFAE59150D7FF -:1012F000A03D7FF349882FAE30B4BB4DBCAD0E7F0F -:1013000012C63BA27D4F1D5603E31D49D39E272ED7 -:1013100084F6C751DAFB9F2F84F783BDF33989E345 -:101320008592B5FE520DB67BFDE7050AB687B0FE85 -:10133000EB77EE7B0AFCE5BFF778AD8A8A717C75A6 -:1013400016211B6323F0FF44511F0F95055D3C548C -:101350008BBF9B1CD557E2FEB3076C28173F4E2668 -:10136000E887F417170D8BD7635CF4E713FB897FCD -:101370001285C0B855100FF4E05795F0FD69446828 -:101380002450A7EE3B1523811D694D0A8BDF71198F -:101390003050BCB0B591C507838A85A8A97D75FD7D -:1013A000D6425ED7CFE3855A1D83B5F047BABC81DC -:1013B000315E48C45B301FED5BA48F074E572E2F64 -:1013C0005E584D02962B81FE65C103FE7BB54BF93D -:1013D000F00AB4F7AF61E7334AAF61DC54DB37069C -:1013E00077E0DCA92ABEE68E5B8F7D7005EDE75FB6 -:1013F0001E25C166FCF9B794E0FBF9748510DFAADD -:101400002E4A4378E77CE6794D0279EA3679989955 -:10141000E6FB7E22D80B8B62316FB2E0CE8C0F617F -:101420009CC5AA03DFA37625A7F7AE27809E4408B4 -:101430005C86B5B35334FA9BFD04D0FFC478AD1D70 -:10144000FDA45C484889557B3F07DBF314CE7F6AD7 -:10145000FA93C07F474A357A7DA3069ECF1ED13BC3 -:101460001ED2F74487D6BE71213C6FEF1DAF1EBF61 -:10147000F70E9C6C84ED494F823E2A99A1E9ABE3BB -:101480004FC0F86DD5DAFBA3FD108F9A6FD2F887A5 -:10149000F8819F15D2DB96412FBECFF9FFC8B64D1C -:1014A0003550D77593F65CDD84EBADE6ED77B62964 -:1014B0004F023FFDDBAFEF7FF87BC6F602129C7C4C -:1014C00065761F5F18E5D56BC54C8E781B9E05723F -:1014D00025D58D4FE1F96E100F60F9ACC4593E90DF -:1014E0001776D1433983F8DC2E8C731AC7595CC444 -:1014F000ECEB4F0BF579B136435ECCC7F353FD8D62 -:10150000F3269F4F7B69643F766C4EE99785503F89 -:10151000404E8B309E8B020CCE276BC952BE82FB95 -:101520009475F1DC4D2AB23C709FFAC52AD899D344 -:101530002838210FDB52FC28C6E943F916DD792053 -:101540005A9E73AD5546F9F809AFEB985F2A4FBE26 -:1015500087B66B878A6403D6793831DF601E667D73 -:101560000AE53ACF7B6AE7714CBBC8BE08E3BE947C -:10157000CFF97ACF147658403EAB449D5C968DF2FD -:101580003A08F5C626C71ACC03DB8A2D9847D0F255 -:10159000CF0A3FFF5BCBFB4E3C3F98E9F7742DAE83 -:1015A0003B70FE5769DAE143FBA0532426E1C27C7D -:1015B000F0629F9A0CF52CD3CA6270BF4055DDEBE8 -:1015C00038FEA11482E70447CF6AC4FD41666A1F52 -:1015D000CA00179E2FD6EA63869FFF0EEE1BADD77B -:1015E000EACDC58A0360A7DA1EA17E1674E0F96011 -:1015F0002D5F3CC320EF171756A29E25D48E1F15D2 -:101600000BDF1978DFF3031359FEF84427ABE7F734 -:1016100016E9F3C0F759589CAF3D4D4F571B273281 -:101620007FF5075C9FEE2CFE7915DACFC4E481BC10 -:1016300018798C9D0B073116DC6F653C8F397D0E58 -:10164000DA758F0DA74BA4B6B6B9E97D8C2B0AEBE2 -:10165000D87B9F8D238DE0B798CDAC4D2F2AE4FF2A -:1016600033BDCAD422A8B368FA10FBB7AAACDEBB5C -:10167000BFF8CDBC226D9F088BDFCC77EFED817D6D -:10168000657F731CC7B0EFD527B1FA929585929606 -:1016900047C0730929E15AC05E4C29F0D5C3BCC9C3 -:1016A000984D12CC4393373B5EF9760DC81B224709 -:1016B000CE4B6B7CDF66C84BFBDCECFD378BEFAEB3 -:1016C00081F30DFACB433C5C2268F1B53B8A605E46 -:1016D000095ADE40BE13DABD7A1416E4D5E9D18585 -:1016E0000DFF0BF4689FDDFE760D8CF74D9B3FA53B -:1016F000ABFF42BC96B3F8D9376DFE1326C87B60AA -:10170000FEFFE8EF8C99E07B0BBEB35A90AB9C2CAC -:10171000B9E711F479BE778B06C8F35D2CFEF07F34 -:10172000F18681E30D62F1BF66BCC10A7BA87290AD -:101730008FAE2C06F95CC8F8E8DF5DEED1F5E6C0A7 -:101740007A570B9BFCD123FEFEFE7E4A8132A918FC -:10175000F5A062DA49E96775899DD9330106DFDEB4 -:101760007806CCDFAB8B673CD9F00F8867D0F55695 -:10177000227ECBF8F7BFF9F8BB15E12B337BE2DF14 -:10178000903E57E3FA36B1F5FD13BEBF1EE9E5976B -:101790008C5E7AE1C3EDA430F82C6CF8E7C0E75713 -:1017A000089FAD6C7EDF007CEE42787AD87C2FE615 -:1017B0005F1F2D1434B9FC06BE97CDE8E043B0AFEF -:1017C00099DF3DE94AA9CFEF7E34573E50CCEA631A -:1017D00082C5BAFA4FF910B407F08B8FC0F3087EB8 -:1017E000F1FBC5DF40BFD859C4E0D69777F1B3739A -:1017F0006F49D50D57D3EF7C48E10DF1B68E261118 -:10180000ED8B734904CF03D0EC8D502CABDFBB7054 -:101810003F581981FD88B67C76CE88763E8059ACDB -:101820001E1C902E84EB81418A15EABC96C8196D66 -:10183000B0BF75D29A2F70DF9555B6E1BFAB39DCDA -:10184000EDB1DC097E34F573AF83786A830BF7D191 -:1018500069FBCAB4FD1F4B02F3F6C23EDB0E4A0F12 -:1018600089F43BD3CB2CC7C3D76FB437CC86B6F142 -:10187000DF354D98A8AF07A4F047FBE7DC3A561FC9 -:10188000D761263BA1FEA35E15FD2DB4BD718D80F1 -:10189000E7712EA270027F7F52672AD6935B93D89E -:1018A0007967DABF7B4AE9A0331FECBF2322C17FEF -:1018B000C78EEF27D3CEF98E9A7A1ACFDBFA98AE7D -:1018C0001FCEEFD1CE9998C1E9448367544B3CC2F7 -:1018D000E51C850B01B8F0FD36D39A583EB8AD7AB9 -:1018E0007110C8BBA6F08B1591EA52E6B8F5E7A5D2 -:1018F0001BE319C6F3C6CDC43718F6D54D2F2C51AE -:10190000C15EB5F17ACD6822E3B9161FAFF9093B84 -:10191000D7A2CCA23B47C4F8DD68039DDA0C71075F -:10192000239D1AF1729D012F1BCDEC9CC1B66ED187 -:10193000A3D2DB6D0F2F6A877DF9EAC32656374F96 -:10194000643CF7A98D5ABCB8FF9C4E16E2F573397A -:101950003C35BC10D268017EABD6F6A19B1A57C2AB -:101960007ED2797C1FFA4D6413EE3358001604FDC5 -:10197000EE4208918B70AE8C6465CE818BC03CEAE0 -:10198000ABD83919265803E4091E3621BFB6B977FA -:10199000E2BFFB15186A893D99CEFC8948F66C6F49 -:1019A0005C8142E264581CFFFFE2577F5BFC2AB770 -:1019B000889D47D5161570E5A7B2F326A09E29B7D6 -:1019C00048423918B42829B8DF61FDA72AD081B66A -:1019D000DF81FE2CBB427F6EC2FA8903F87F45454A -:1019E00004C76B4B0D25835CFBB09FBACAEDE03892 -:1019F000303DB46122E6DFA9FD9B0D728FD9BF1582 -:101A000079BEA7F13EDFE7ACC5913EF12AFF39313F -:101A100007F6E71094C3B60AC10FFB77A63B853DD6 -:101A200082D4F77D62AC63FF5F9AB7BA93FB6DC156 -:101A30002882E720055349D57311F0F1835216A788 -:101A40000C6644C697F69CDA19EF4CCC61FED020A8 -:101A50004614A7ACFAF8C00703D18786C7F8C9F2C5 -:101A6000471373FADA0FE4299F40BB55F17D0078E4 -:101A70003DA98A12E8151250F03CBF69FF21BA0057 -:101A80008EFFE83CDCCAC2D44BCAC355039D0D503F -:101A90002F78B9D7FF0FF9613D6B0080000000007F -:101AA0001F8B080000000000000BED7D0D7854D561 -:101AB00099F0B973EFFC24998409041C24C00D0229 -:101AC000461BDC81802440E0CE4C12124860F83581 -:101AD00002E285008D5DB451791458BAB921102005 -:101AE000A260BFB4B5EAA34310DCDDFAD4D475AD6F -:101AF00088AE23A2A55DD4A8A1C6556910E4B3ADF4 -:101B0000ED870A6BEBA7F57BDFF79C3B73EF64C2B5 -:101B10009FB14B9FFDC2A337E79EBFF7BCE7FD3FD8 -:101B2000EFB939EA648C4D82FF8CC2655A01632D8E -:101B300058BE9CE18FC6A0BCB8BFA59C0B4D3B799D -:101B4000FBD1DAFF891A2319D399E82FDABF23F1E1 -:101B5000F6478303A28697B145A21ECA3A96CDFEE8 -:101B60008C29794105FAD749667997A658E7CBDAE7 -:101B7000A5C17C279CF6F19788F18AB42F69FC48AF -:101B80007CFE2FA31A948F27C17F03E3E552EDCF8C -:101B9000D47E65BCFD9F755CEF49C92C8FD2B1FF27 -:101BA0001197D9FF8A6538FF3D79BC7E6A6854D4A5 -:101BB000B804E1F9A6C7BFD0F647A7A88C0D047CEE -:101BC000D4FD2C7C19FCBAA47E97AC43BFA3CEC82D -:101BD0007B2C07C8EC5E49DD037D8A58BBCC6402D0 -:101BE000DB258F87213489B5C05C2B42F0BF09808B -:101BF00047AF83CF6304A21AD0D9E2A9269DD64469 -:101C000071DEDEE8EE9DE0771FC27527E0FEEE5242 -:101C10001BDCC6A865DA9404DCE110B487F116DF9A -:101C200072931FE15C3CC25CDF249AA739DBECD7DE -:101C30007DD6795F7BA194F0BD383E4F25B55F9C82 -:101C40006E8E37278AF326E05A48FB91806BA80DE9 -:101C50009F81D042C267C417DD3C08F013F1B38006 -:101C600001F85C54D728EB05163E32C22AF1913FA9 -:101C70005E8EDAF9A880F8A8AFE11A3629B24D8352 -:101C80007D62F9ED6A64CC37B1EE98F3325CB7212E -:101C9000D1BA4D3A5AE2B3D0BB07D6AD9AE52B97ED -:101CA000D579FB62DE8E329AF723C0374BF01333BF -:101CB000062FD3BC173E5E9377B90BE15EA5495A58 -:101CC00014DA7F853FD312CFA35324E217C0E7BFB6 -:101CD000123E8B009F99F89E111F3C5E18F9B906C1 -:101CE000F54CD51D07002E97E6612D8083AA8991BA -:101CF0007DD49EEDF423FE01001AA7F975A6209F5E -:101D0000016F051C93A1EC6435ED29E6FD61C84126 -:101D1000ED9B18AB6807F8C66FF4AD8A7813F5BE73 -:101D2000320E5796781EC9ECBE6120CCDF0D551BD4 -:101D300061FC260398179E1FD4495109D6FC416EB9 -:101D4000645631943BF21C818D307DC73AF7D03513 -:101D5000D0BE2BCF1B40E8BAB27766FA60FC0F0208 -:101D6000B2C0D74DEF235F1FC98CF39381FAA5430F -:101D7000E0F7D75A711BF2D3DB2A2F3F50FAF7EF67 -:101D80001B05486FCCC706011EB007F0AA23638A63 -:101D9000C70DF3BACA419C605F1FD35D50EFC67A8E -:101DA00058E29C1FECFEC13C95E4C6CB23AF65AC6A -:101DB00006DFABD85F31BA3D34AFF295444FE6BC95 -:101DC0003631AEABB5E9A526809FF9651642DEF245 -:101DD000F3F67ED6DDF89503C787723E43127CE1A9 -:101DE0002B58BF24CAF8F3152CD1CB2215790857EC -:101DF0003E0BB4C07C7374E789783D7F6C57AE1599 -:101E000070223CF2868A6278A6D7D9DBCDCC87B225 -:101E100027519ED15A1B42BCCFD0A0DB58C60EB76B -:101E2000D6C66A01CEC3456E9F049876E52AB6F6FB -:101E30003359FB26C43B530F1D94012F4BC57C4DDA -:101E4000BE39EF31E8B72A1F4AB0FE23FF10CC9C01 -:101E50009083FC26071CA28DC3C407A3764E079768 -:101E6000D30109DA373D63EEDBC436E4033943B20C -:101E700095832EB37E4C1BF2E191B85C1DB91CCB4F -:101E80000BAE30F926B30DF96A5A8659762D473EC6 -:101E9000EA569C429E0D6C433AD96A8E67EC20F953 -:101EA000F21633EB1D541F89CBBFF25D585EE81369 -:101EB000F018DF2779D8A4717D72D50BB16EE322BB -:101EC000DA037F5E19447E8B7079975C3FA933DA21 -:101ED00094857C07F819A5F6E4B7F54199F828A28E -:101EE0007D2CE3FE95D603CE60FFC23552E704A4F5 -:101EF0004F850D45BE6F6E009D3E0ACA2FA6B9D410 -:101F00004C94EBBE722D05FFFE3CC8F97752D09B76 -:101F100073127157C80A91EE9A1BD69AFD0DDC5FB9 -:101F20007DA42B9A96D7FB38AF851D24673A24DF12 -:101F30007CAE9F6586FA3978EF15DE629668F758B1 -:101F400098EBE5C6426D7A10E69D05E297C11E3614 -:101F50004EBD3F1282794E143B036EE233ED0DE429 -:101F6000B3B9828676B834B60EE546B1DBB71165F3 -:101F7000B75CE05C0B656508F02B962B387DEBF0C9 -:101F8000EFAB1138AE92A07F8063CE5A3B3F28CC96 -:101F900042DF50BF28989973F25B50B89A5D8DEB81 -:101FA000BFCBE95B8A726CEB08DF2D5679F6689837 -:101FB000CBB1A858EF81A9FF5283F8F994390228D0 -:101FC0003FF6A647489E1DCB62AC0D75BEC654DFDA -:101FD00020E46BBE0E297F21C3F60F0E87250C0669 -:101FE00038D6BED3515A08EFEFE3FD3EBC86D53359 -:101FF0007CAFF0323C0C632CB63B4AEDEE0C8EA06D -:1020000079D943018F07691F9AE37E7B59BB139FE0 -:102010008E8C6787EA29F6C77CB2D5CE8FE27840EE -:102020005E024D88EB9698EEF80AD72FE43FD0E990 -:1020300006DC1F90FAA447267D78CA466FE3822A01 -:10204000C1914C77D0AF89FACD37FB31A76EB1D7AC -:10205000D7077F146D1C49FA681BB5F3823ECAB1DD -:10206000E9A3BB8229F4D1C84AED6EFE9E97A1FF79 -:10207000BDBDF4FF5FA9FA43FB1FD27B8F4EF8AAC8 -:102080009AA8FD08CBE38799F2041A1681FC186020 -:10209000CA8FF41BEBA658E48F31E1619437D7EB7C -:1020A00092A8CF7F98F44EC8ECFFABA57679B4E048 -:1020B00061BB3C9A7923D627E44FED4376F9137E32 -:1020C00018E545708ED06BECFD8770FCE62566FF49 -:1020D000D1D120DA250E531EB228F2A1CEE2659BA3 -:1020E0001D79E4D9F6A5A8E74CBF8919ED0F213C6D -:1020F000A69FF1D6B3FAC3A817412EB2E3261F8CD0 -:10210000E8C9EFA61C30E9C7B40F5F7B31AA1BD02A -:102110006E6E8516B3EE4BDCCEECE6764FC2BEFC9F -:10212000DFDCFEEE7BFBF1759ABF80D3DB3730FE40 -:102130007BD6F14D7B0ADE7713FD89F7979A3F072F -:10214000F09D26F8C673F82EA2FF17B4EE00D75301 -:102150007F0578D343163FE012C4E7B04B1CBE7135 -:1021600021DCEF2ABEDF8F69CC94E31308EE1E74E6 -:1021700070DEF45F42E396F2755BC6D5ACF3F5E62C -:10218000AF43BB327BBB38FF54105C62DCB3F4AFAF -:10219000B6B78BF78F842CF4D9077CBEC8BABFDFE3 -:1021A000801C5945E38FE4E3CF4BE0F126EBFBFFC6 -:1021B0001F373B279DEF207AAAE7F4741EF6F60F2F -:1021C00010BFDBA4763D8BE2448689F7FB701C7858 -:1021D000DFED82F731B11F8F14471EC0F658F48F20 -:1021E000B3F827C6DC5D085FC23F81810A2CFA9EE6 -:1021F0005DB70BD763EAFB27428B761940277298AD -:10220000B77FF4C0CBCB70FDC965B04BFE99F63FEC -:1022100007EC92316497FC0BC275AE7101FE76C279 -:10222000C3D39C6E52D43F49E33EC6EBB7BAB81D48 -:10223000FBD6924FC98ED36E551D68C7997AFDF9AA -:1022400010B767C11EA9887A7BDA8DCF8B781A8C7C -:10225000FB3CCDDBCEF1DF199133D1DE4CD82D31F3 -:10226000F2831276D50AA2A3B85DC5BE4DE5A96278 -:102270009FDF087D679980F7571C0F623DE76EDF8F -:102280004170F879FB14F59D345E2E8793790F9D8C -:1022900040BF95E895FF8C7440799528049D0B4AC2 -:1022A00072C06E39D02AA948262BEF33F7F976E2AF -:1022B0008BB8DD26F8F07A41C79F84D6D33E5E7F87 -:1022C000DAE4FFFDD47E7CDC4F5D4FF0BF2DE213DE -:1022D000DF0BAF37E1FB90E053397CDFC0F8A70993 -:1022E0003F8CE3A786194EB4CBD0AFDCC37AEEEFB8 -:1022F00017228E03FDFE2FF5F370B86A7489ECF790 -:10230000C88A634EA4F7A59D4C4B451F72D865F64D -:1023100097C364970BFF36C0E342C9EDD3C2717A0D -:102320004AA3F63E3EDF86E2480696A7E8AF870757 -:10233000F1ADF1A03D1A2995A22D79E8DF78CB4ABD -:10234000A13CC7C1BAC9EF636C33C67DDDCF2AACEF -:102350002540AD55C512D7012EFD35FA910BC43E6F -:10236000CF61F1F88A03E33596F80DF981EEF09D1F -:10237000F9AD2AC55D286EE3F2CBE45704EF5E4168 -:10238000F191F422B7CF8DF3C8B9E4E7BA1E10F18A -:10239000A2F9DCBF74C03FB4A3D3D732F2DF666DBD -:1023A00097A22AD4BB357BFCA576C3A926F2EF56AB -:1023B000309F067EA25264AF7725F9AF8D857A00F3 -:1023C000F172F2BE5A07E22358C9FDB093F75DE1FE -:1023D00045FE4BF6A34FA21F4D52AA871F6DACC3FB -:1023E000F89AC58F5ED3877E74386CF7A38715473C -:1023F000CAC248E78A46F2EDC0D44973C95FDE2EEF -:102400003337B43FDE3AFED522281BDB9500861B0E -:102410003E706A4BB1DE007F5A1E46DBC430BE35CB -:102420005BC07FBCF85429C2AFDD3E2C80F47EFC3B -:102430006E37E1F9F8CAEC68068C97B5FDB34D69C3 -:10244000D0FFE5E8100CB2C5FDEB643F1CDC2703B0 -:10245000E9E6381BCA5A701F141FC37195FAAC8085 -:102460001148F8DBB3F37D068EA7473318EE7BECFB -:10247000974C3A99CFE8C801E9780E539D5898C710 -:102480003427E27F01D3A97C1DF09B7405CE976FA2 -:10249000101D00DF61FC6E7DA17E13E1E3414E1F44 -:1024A000EC1E65179E571C37EECD443EDB9B6E8FAE -:1024B0003798CF3522DEE0413F7F4C9FFAF9EB0899 -:1024C0001E2127CE43AE34F0FDE4FC7A1AFDDF81F5 -:1024D000A427EB90CF3B441CF89E6C1E3F690D7304 -:1024E000B992FC0486CFC1FE17AA27405FEE08DB35 -:1024F000FDF89D583E0F7DF94392334FF2753687B4 -:1025000099297F7E1CE676809A45F11410C5D7F292 -:10251000FDC59FCF25FD611C5F7B4CA2FD4A531971 -:10252000C921378BC4383119623D6CC3207BBFBDD4 -:1025300067EB776390CFFF4191FE136C57720A28C7 -:1025400014DAB9AB781C7CB6577A495213ED8E6019 -:102550001C2A55DC5FC85168167380BDB2230BF688 -:1025600000E3DB4AA01FCAEBB71AB4A368C31D6916 -:10257000A8A06797524FF2A3EB3E39DA085D5F6D72 -:10258000601DA5A37A8E5BB32478F484451ECD2EFE -:102590007BC403429135E5B71D92305EAFB9553724 -:1025A000F4EFC88CDC83F17AE37599ED017817CEEE -:1025B000AF3C7AC2221F92C785F998012CFB56982E -:1025C000C7315F0CBA63D3009E1586144579B0C23B -:1025D00038E6C478E5D2B5CB980EFBE42A3AA6E0FB -:1025E0007E96077DB4CED94532332C70DD7FADD6D3 -:1025F00011E6F19D37687F03713BEA4D2C079D5A28 -:1026000096AF20118734CF051E0BEF267BB4239B9A -:10261000D1FC113F8B36A2FCD296B9BAF19CC51FF2 -:10262000A1B8E9E1B04AF3AE6CDD45F0A44FF998EA -:10263000E001DB39E6E8DF13DF261FBC2EF0DE2CDD -:10264000F0DE1B9E3F09F3789E599E5DA664229E94 -:10265000DF50543AE7E88DBFE796DAF7C7EDAFB041 -:10266000959BB4DB1D484F275BE528EE133C5FC10B -:102670007D3B0DFBC6F212E37464B21AAB7E36F7F3 -:10268000674AA94C7099FBB3743BDF9FA5DB838439 -:1026900097A5A595AEC1FC5CAD1D689BE945CB181F -:1026A000E2C5A51D53508EF5B65FC06FEE528BFD8F -:1026B0007811F1F37EA516BBF69B8EEFC37C4369C0 -:1026C000BE243BFBAF75BE60D25327CAD582845C63 -:1026D0002D2BE5FA20F969CA558B3D49714D0B1C2C -:1026E000CBEB2E020E934F904F516E84774ACEEE75 -:1026F00002DC7FE0D731689FFD76F36539C8378CFF -:10270000E8C151CAF9C635658E0BFDA695F77DACBB -:10271000A0BE027C4E277C0A393CB694997A6806A2 -:10272000D1451DA78BFFEE731D806709C1B984C316 -:1027300079A99D3B7DA73A525F4AE7402097BC1894 -:102740008FF789FD674379DCFBC2CE373F68BD9DBB -:10275000A11D38E70F992ADA818B8AF768796ACA4E -:10276000F34D55B29D6FD68618F9158C8506B37357 -:102770009E6F269F9FF63CEF345E6ACA49D8DDC93A -:10278000E79DC9E79AAC97F3CF9EE79D2F561503B7 -:102790009C3302B24F5513E799AE2927DF65D7F472 -:1027A0003CEFFC12D623F099C32CEBED1AAAB6C766 -:1027B00000BE96C19E401B6FCEE46B1378043DE0D3 -:1027C00071C33C9BCA007EB497F3DA7E308FD9F098 -:1027D000E8223C5C201EE97C1BF1D22A4537627F4F -:1027E000A5DE4079BE92F9D4FB0389FD8C8F977FDB -:1027F0008786F2F91F6ABDCC01FCBF39E736B60CFB -:10280000DAA71F4E6332B43FACDE46FB7DF8A34C23 -:1028100015CF7BDD7ECB3E085C2A267C724F3FE9DC -:10282000AFB08F1E64B91EFBA8B695A29E3DDFFD1A -:102830007BA4387204F9D803FA5A199778DF3594D3 -:10284000E3B3FB2A166D937AEE23E05B23BF339F3D -:10285000EDDA48F5F50CE3039B24C6F19D44178E91 -:102860008C0D069E6BBB967BC98F6AAAAF277CBF77 -:102870000EF8367C9CBFF09CEA2CFC65D2059306D2 -:102880009D3F5D24EFFBE1D65AB6F6D2DED75EF867 -:10289000737729DA3DE7BBAF5593B57E6513ACFB83 -:1028A000AC65970DB4F2AD21F2520CDA47633E638A -:1028B0007BB27BDA51978BBC14186F30F61F52C66F -:1028C000441C501B82E579C3597DAABC17E774EEFE -:1028D000C72C01139CE22A463ADB331EBDAC9DEFA8 -:1028E0000D42BFCEB84AC532530F4591AE6AF912B8 -:1028F000D8911DBBBAB07E362CD69143AF54870514 -:102900003F81B23C1AB778F5B15754AA0ED0F82ED1 -:1029100010FEE8A72EC197944FC2A27B480EE86C28 -:102920002EC8FB1BD648EF61BB1A2383A15F9BC84F -:10293000AB783429AF829767E78A7AE3DFDA6CE70E -:1029400098C60B49FAEDAD36AB3FC58C63A4DF6C7E -:10295000F685459F1D79E9F7CB0DEB39A6F1318D51 -:102960007F7489395FD16EFB39E69734BE19A7664B -:10297000EC332A2F89973F27FD6AC691FF5436B161 -:1029800096C74DF5B9B8FF7258AA47FB08148C26B4 -:1029900051BCC6D786FE34D8FFF3B0FE6F7D9D6074 -:1029A00087DC5C6639FFF85B83FFB819DF370E2FD1 -:1029B000D70A2E7D7801DF0F10BE2B38BEFF06E050 -:1029C000FD59598A73804B08BE9708BEF839C47FF9 -:1029D0003B3C6F9559FCCF6F7ABEC993B513484FF6 -:1029E000DFC03A4E9559F20FCEA3FD7F517B715E49 -:1029F0009A5C7F73B98FC7B1C439F1DBF173BCAC9A -:102A00005A1CAF3B71AE47E75E8973C4E157044778 -:102A10005AE11FBE1BDB9BE78853CBF36A292FBA11 -:102A200097734C0DEB156B7F95FAB724CDE712F534 -:102A3000F3CBBF556BD8F07335B5EF486A5F23D63B -:102A4000B7BC7CDC6EC3820FF038A97D5C2EB189E7 -:102A5000B5F673C709B5D673C7D5E513779BE7FFFE -:102A6000E5881F714EFB3F1D1FC172E16F8AF37233 -:102A7000930E874DD242E5132E3D7861FF16965B8B -:102A8000E8FFAF30DF8A724BDEC585F68FF3A3D047 -:102A9000FB66FE04E0F7165CC7CDD355C27F72BE5D -:102AA00084E92746BA5914FD96C92C2AE3B944246F -:102AB000A0338C83C6F9DAD06A295E17BF1F51B1E3 -:102AC000DB7E3FA27137DA1709FDFD54AD3DCFA182 -:102AD000DC06F78E979F32D7DD546EC967E8EBF1BD -:102AE000574FB7E3255E16F8597CCB8F87DAEF5F37 -:102AF0004476D33946FCFEC5229A3791DFF1EDDDED -:102B0000F6FC8E35544EEC5743D27E7DCF06D71758 -:102B1000E50D04974BE4BDB95648BDDCAFB89EE463 -:102B20008279AE0B659B5CA0F23700D741938E048F -:102B30009FC6E1EC919FB76C37C699FA7A7E8B5CA1 -:102B40007809E9A2EFF1CEEF779878EFED7EC7F53F -:102B5000AA59FE6E6D5DC1D79F17F3FFCA53E61FDA -:102B60005DEC3AF87D1157F27D11B6AED62E7FCED0 -:102B70001BBED3A9E5CFF9F5FFB277F9F317943F60 -:102B80004D5E07DD47D1FD2CE57D949BA7F373A92E -:102B9000387F8AFB28F376A4F6A7FF7E3A8F5F9BE7 -:102BA000F1EEA0EBD40AEB79D70051EF9B1ECF1BBF -:102BB000F04DC771D772F886A13CC4F31EA6300D44 -:102BC000786AFEBCA1B9085FD37FF2F1981FFCE4DC -:102BD000CCC47893C578E63C2FCCC9ACB1E635E4DB -:102BE0009AF34C97CCF8F4B0E988CF0D7C1D72BFF6 -:102BF000D574CF2BEE571BAD24BF9A9DA69FFDE049 -:102C00006E92677139F463A28B056E93FEA3BBAD20 -:102C100071E3B25FECE67A158A788E97E8775F2DDC -:102C2000F979E7E85768E27993D82F23BE5FE3117B -:102C3000EE73F5B7F8D1312927E1473F5EA84D4142 -:102C40003C833F5D723EE3009EC2B42F6BECFE8876 -:102C5000A57EFA745B5ED2A9D567CB4B9A3BFDEC9F -:102C600079497313F43077BACDAE0F674EC038C9C7 -:102C70006047CA7B14BAD8D7447ED74F69BF9A4DF4 -:102C8000BE13E57BB279FD0DBF78BC56C07FE374FF -:102C9000CBF98579DEC20A0EC530CE63C92FD21CAE -:102CA000D6B84FF89813C75BBA5D4A993FD3835F94 -:102CB000B68AF1B7C7F7F1E6E93C1EAD63DCF17AFD -:102CC00073DC6F37D2B8352BF8B8C97C73A788533B -:102CD000DD99A0E33B691C2D9E6FB30ECB9832E0CB -:102CE0001E9718DFBCDF1374469EC3739D66435264 -:102CF00051BEEA6B97D1B922AB606C14EC5370F003 -:102D000088ED283ACCF98657F0FD825F4BB19D1FC4 -:102D100024A43118F3C497D1B9F3B51ACF5B9958ED -:102D2000D5280F5429AFA505F7AD78FEAE265CF681 -:102D3000754B7E26A7CA67E988E7B3B037460E020F -:102D4000FE16F0E1BD903530CFDBF17C96AAB23BA8 -:102D5000ACF92C91AF97CF62C6FF168700AF967D76 -:102D6000CBAEE078CDAEE0784D9C03333ABF1DCDBD -:102D70006A665C85F165BCB705AF3BC43DB733B946 -:102D80002C8AE7FF8D53D3298ED79DCDE85C15366D -:102D900024ABFA5ACC23E13F69A34A298EEB86750E -:102DA000E13AF05C3676250C2F2FE9174B41CFAF77 -:102DB00066E92CE0C5B8BFB19901DD84F57BE97CFB -:102DC0006EF88A8FEB70DEA5BA5B4512B8BECE579F -:102DD00046795CAB03CE3B300EE9979986F1EC2A3D -:102DE000E7FBFC9CC643789A5DCACB265EDC4C7937 -:102DF000DF8A1725A9BCF6DDC62D072DED5DB1B420 -:102E00004C3C177C69BAC80712F78A98EC253A3807 -:102E1000E37744F11CAA4361071480A35697E9FCA9 -:102E20007DCFF65B5FC1FB634BFD4AC001EB0CAF8E -:102E30009528FFEB7A1FC7D3670DC6968360C3A69C -:102E40000D1E41E730677C1E8AC6372FD943717B40 -:102E5000A0970E05F37AD6C90CCFBDCDFCA7398259 -:102E60005E4C3CA62DFB94F07206CFC3112F45D9C2 -:102E70009407350BF0A1FAE89C7F13E2299DD5C792 -:102E800006C0BC0BFD0E16B3C4A161FDB63C3218E2 -:102E90009BF2CE147A63AB27FCA4AF0BF37C34B95E -:102EA0002A86FB7AA688EF2B940348EFAC94D3A92B -:102EB00089FFF4243A7527E58725D36932FE4F232D -:102EC000DE2DF7B9F6282C10437AEB94C9BEE86ED4 -:102ED00055B228EFAAD54179578C45E91ED31ED6A5 -:102EE0003FD082723326D139C175026F26DE19AB0D -:102EF000DFBC1CE3DCF559018CFF3347FD66CC8F4A -:102F0000BA3E9A41F9778B583BE541DD801E32CCC1 -:102F10007B23F3B9B0BC9C05E829B102BA5FB2507B -:102F200097882F7416ABBE0AF017BBDC996DCDAB3A -:102F3000EA35AF09567ED2721ED1BF42C84B8FEE22 -:102F4000E7799EBAB8F7A3517E507659A9474F2129 -:102F50006FA715EB832B0626CA8AAF9ED1F9747131 -:102F60006448C58444FF470BB55C6C37AE481B8A88 -:102F7000CFBD68E7813E081F1AF508EA83C6424DB7 -:102F8000C5F6C9F2EA78EFF977B1B540775D28AFB9 -:102F9000288FB080F8B0AFF2EF0A2B7AE4DF4DA8AB -:102FA000B0E4DF1D75F27B65948B3C99F5BC9FB650 -:102FB000F63AAA37EFA725DF4B630FF2322CC86829 -:102FC000198BF777EB69DD26DE93F1C3C4BDB4C579 -:102FD000FE97BBA46BFA206FCD07C6DDE0B3D187A7 -:102FE000C1EF2F57DFDA954379840AE51136E7F10F -:102FF000FBCB9BB00926028DE4F6E097425F6DC9DA -:10300000AEF707A07E8B93E7C3B07C9DCD1B9318D2 -:10301000F7CB0AD93C175A8A7400761FD94BA6BD44 -:103020006AB6AB157A6195D00B8F17465612FE1310 -:10303000F9DDABB03FF3C6A20EF3DC8EFFD03990C2 -:10304000693F1C19524FF9346E2DB5BD706B455C4C -:103050009FDF4AE3B79AFA5CBB0DCBD306F8E623B1 -:103060009FB9C2326B433D36FB6692BB4F61DE288F -:10307000D83413F5C6F020D8EF860A71DE54978D48 -:10308000E8621D1ACF278D95D4FB51DF6D199CFA8C -:10309000DEF761B1CEF1C34EC938EE96658C6D1C7A -:1030A0008BF833288FCD5800B204CAE0EE1FC473EA -:1030B000190FDA01C5A817797B5F1DB4817D6C17E4 -:1030C000F80F8E06FA41FB6B943D1FC97C9AED9276 -:1030D000F3AD409467E2BA93F3DCCC7CAB2EC5C869 -:1030E0000CA4807F76D91A0FE56BE52EF7A09E6CB5 -:1030F000D6C2345E72DEDB965C3614E14ACE6B33A8 -:10310000F3A6CC7C2973DC7FAAB0E7B5B9FD5C6F70 -:10311000C193F2647E5AA1F2EF5268F6FC3633BFD7 -:1031200006DB537E4D2EE3F935FE7A86FDDC50C674 -:10313000F611917F969C570572E86744573DEC2342 -:1031400046764673B1C81B60DAE665681FE1F96D23 -:1031500020857D050201F5A00BF413D62BF2EA0AB7 -:103160004CE5F9BA76D4B4E2C8CB48972E7F5CCE52 -:103170001E22781372F697580F72F65756397BE66F -:1031800090F108E66F6E91381D6E01BC3F91823E52 -:103190008E5448828F53D3CF1F04BD361646DEC2ED -:1031A00079B41C7EBFE342EDCCE6849DC9F1D847DB -:1031B0007626E0E377840F21A7011FBF473893F1FC -:1031C000003F9B506E58F24C3FC57EBDE59926F7F7 -:1031D000BFD87BC212C80DFE1D09ED2F0857D5447C -:1031E00095EB5D218F13F76D2F4E5E773A408E027F -:1031F0003C681358DBFB2AB99C2B98ACFB2A492F5F -:10320000F3FBBEDB82FCBE2F8B69A4F78F64EA352B -:10321000C8A72C7FDC39E66B14F9B47A5D84E4FC32 -:10322000DC73B4DF48ED0B268BF5E6F727FDB14DD7 -:10323000D2EE4B9713E573ADCF53A98DAA447F53BC -:103240008FD0F712B6E43B54039676CF44FD5BB8BB -:10325000AE2DF91B69FF5A80E024909BB31CA7EEAA -:103260001E21513EF0D3523F787AC0634B41D7457F -:10327000023F60C5523D7B57F35BE31CB595F1B847 -:103280008A884BFCF323D67B4C732B7FB202E3F18D -:10329000A61EC378C91329E82224C691DDB7DAF443 -:1032A0006472BBD24A7E0F645EA5381F107A6F81AC -:1032B0009BFB51EC30C067D1AB05934315955C6E19 -:1032C0001992451F9AFA8F6A2CEFDD7E7EFF847576 -:1032D000DAC731D7B942D0A9392FD0EBFC4A1EBF8B -:1032E000585069A95F20331EEFE8B0E30BE0594462 -:1032F000F03076A217781E49094F971D9E1571BAB6 -:10330000D556E078A09757E2736B08E82E057EC784 -:103310004C08DD84F50A33B68EC83BABDD5A8FEB23 -:1033200030CB16BBF5B64ABB3CBDBD92CBD3359571 -:10333000244752CFDB50C9E5629F7D3FE03CF9FD59 -:103340002EFC3505DFB4743F99710DB09ADB6DDC4E -:103350004EFC5930EE1CFCC5F9F9C661F5A4E79E98 -:103360001376C8734EA6607E0DF0582055DE4FAC24 -:10337000D2B43BA243102FCFF46277C4DBF5925F47 -:103380007F25DB997131F647CB942319647F9C6EBE -:10339000CB403DFFCC89504AFBE3B9DC9D4352D979 -:1033A0001FFB7AB13F9EAE14F6C7072EB2274A3EE6 -:1033B000E4F647C9873B65B423FEBD52A5F5149FCB -:1033C000E8907580BB04ED0F18679FB03FB03DD902 -:1033D0001FA777CA0857F1871DD4AF04CA687F14A6 -:1033E000F7627F001432E2E1E992963771FF92D7DB -:1033F0005B355EFF85956E8BBA3B28CE63F66BC955 -:10340000DF98A1D37EDBE9675A3197BB897E9CDECA -:1034100093DBF546676572D5D66E58D73696B99365 -:10342000F23295FA87B16C180AE56BE10736906EB7 -:10343000EE9C0D306463BBFA47BB51BF186E1F7E14 -:10344000DFE0B3F4A5DCDF59C37CCEC90979444B76 -:1034500007D08C9018CFE5F13581BDF4A38C2CC238 -:10346000E35A9F19D7D9593102FADF79E548BAFFF3 -:1034700013BA170682F2E44E99EACD38D02B83199D -:10348000E5E903FFCEAA86F1278AF141DF69B74358 -:10349000FB05C21E2B97BDD4FEAE7CDE7EB271AAA8 -:1034A0000ECBC5DD2E15EF993179837C0BC66FD11C -:1034B0002E81F6773D1B29F3407DFA118004C77BEE -:1034C000D745710C0DFE21FF4EE86C277C669C7081 -:1034D000D9E21BE920E16216FBC5955466F2927EA3 -:1034E000A9E493F9EC110F9A21E211D7B0BFFB0ABE -:1034F000ECAD336CC3565CA37B54E8C5DDAC677F91 -:1035000033DEF0FBF19A7706ECE348A74EFECBBE24 -:103510000AC035ECD3BED6D699D720DE772A14DF81 -:103520003DBA3E83F669FFBDCA2E8C2B1D053EE5D4 -:10353000F1F3B52B915EF7679A6516C3F8DCFEF8D8 -:10354000F70A07F07A515667043E40DF78FF40D112 -:10355000DE68E5F56699DDB512F337F60FE6E51995 -:10356000337EBA07DB63C637F9D76B8F7B53C9CF7E -:10357000513355DB3D8F5945B7723A3E473F90F77F -:10358000D7CC18D8B35F5A35F7B3F62F0110C7223E -:103590009EF4C21930FEBEAEDBB68E81A9C64F596D -:1035A000DF41727440F79A54723F3483DBCBB1929F -:1035B00028F95DE0CB73BF972907318F751653C784 -:1035C000A17FBF63EA33FF710DCCF36AF1A871727A -:1035D0000ABEBE61C688A475BD2E2F47B9F4D1FBC3 -:1035E000F353C981E64ABDC2BE1E7E4EDAB45321F2 -:1035F000FCD7FDC7278F60FE43AC6427C5F1F6FDFD -:10360000C1C1D06FD93786DBFF78534FCEE913F8AD -:103610005A27A6A03B806F492AF846CF643C4F74D6 -:10362000BCB614EB93E15531DE0DF08299154039AB -:1036300092F6DBEF77605C735FB783822B674EB4E3 -:10364000C948822D5D234AD16C9D56754C46922AFD -:10365000F1DDBB198F80F50DB28DFF2676A5DBCA93 -:1036600037D40FB09517D70D49F023C3FB4057D877 -:10367000CA6EFFD5B6729015DACAF3AB26DBC62B3D -:10368000F3856DE5E9FE99B6F695EA3C5B7966FE51 -:10369000625BFBEA40ADAD3E523056C1AB7C409719 -:1036A000CD88AF8C4E8DF87C4BD76D3EA48B58499E -:1036B00084FCEA23991DB918B77EA597EFCB75CC8A -:1036C00090857E07D308E524E8F38DD989F6C111EA -:1036D000DDB6B8FCCF67707DFD84A0EF73DF87E3B4 -:1036E000FAF97CEFC125EBE1D957DD4672A965BE39 -:1036F0001CC57B554DF96F78F1FED82BF3793CA1B1 -:103700002517D6E9A5BC0CE2AF17175C3714CFD745 -:10371000D2F3F50128FF4DFD1DCE8FB2E3509FEE91 -:103720008BB22BF09E19946BC57DB370017F3F5A0D -:10373000BC5F854FD0DBE5167C25EBE3A067EC4B47 -:10374000E036B0A97FF2D177FCE617F0B84FE9E98F -:103750006829DEAB9EA9BD70905F9FE6F2E7D59227 -:10376000DFE5F4A2B7FFDDCE0FAF133FEC3B31F73F -:10377000ACF2FF370D3CCEFE548387C5607DEF363B -:10378000F8E8F99F0D7E7AFF7A834ACFE6867C7A45 -:10379000C61A0254FF6643113D0F3668F47CB9A186 -:1037A000829E871A22D4EE570D35F43CDCA0D3FB61 -:1037B000F76770BEBC54E0D1F2CDB842E44587440F -:1037C000789D8F29BB933ED464AB7C07BCFE76C644 -:1037D000849E78BD583D122B691F12E17A2B251F5C -:1037E00039679AF76EB99D3C4B27991F87CF857132 -:1037F000BA9C449CCE8D264D7F82F32F7D09E77EB7 -:1038000011C7D99FCD6A9EE0FED42689F48D6F2C16 -:1038100097E7F7474224CF078E4D2DCFF37AC8F3B1 -:1038200065A4B7D8218C9F627A110AE395387FEAA4 -:10383000B888D12FEFAC78A0734B130F96FD1A3ECA -:1038400033051F9C0B0FC9EB9F56AC8D9E3981DF52 -:103850004771F6EFA94746777FA1616CEAE9020E4E -:10386000EF8EF7E7F6437BC58D4129F2DFC1702B60 -:10387000C2FD66665EC19EBADC9EE3FCA6A49DF412 -:10388000FA5D713BE701B26392DBC1CF41C203EA4B -:103890002D0B1E52C881693353D04199FC6CF746F9 -:1038A000E8BFBF9B51DC4C459B1AE07F46E1DF6BD4 -:1038B000D8FFA183F07CC623917C74AFBBDD83313C -:1038C000EEA7BFC7DB19D512DD63C838B04F453B43 -:1038D00035D8AD0FC0EF8E15C52A9DF89DD0D09478 -:1038E000B181340B1D8414BB9E444B35AE77282820 -:1038F000D63FA97C79A2BD8CFB3F2251CEA3FBD73A -:103900008B705D734FD533B540C459BD29F1B45A9E -:10391000B2C4DD1416D83A318FECCE8397E3F9CDDB -:1039200028169589AE0CF2BF4D78656F84EEE79945 -:103930007EFAE792B60AE7EB317E9D46E76FCCE16F -:10394000A0F3B7F585FA2D33E99C3EE97CC6F7F282 -:103950009F25D0695B1D2C86F68591E522FC25EF1D -:10396000D7B8A2CADBB1BFFF6BFBF53B25EBF70273 -:1039700046ABD3C89F3A03FE14DE476952F83D298F -:10398000E3DDCCE81E0292E5A3DD76A77C7500F7A7 -:10399000FF4719FF48FED15A5824FA5FDB851CBE49 -:1039A00007E5303CB73BB9BFD5DCE8F6B5E5A0BFCD -:1039B00095653840717D96362CCA609DAD33B93E11 -:1039C00077B31BFA45C69C057EE19F38E3FB9EEB6F -:1039D000237F4394BD2EDDF109FA7547E428C6DD47 -:1039E000B68D7DB06639E26FAC879F7F2A31750E48 -:1039F0001A683E83E558EEF1CB4C398971DAAD6037 -:103A0000CCE039EFDDE21E6E66C061B377FA15D9FE -:103A1000EDB59FF411DC2E9444E8B7E6B8A2988F78 -:103A2000A3A2DC02B8B7FA1DC45F9B542E1F3679DF -:103A3000358F2FC5FE6E417CBB7B9F5FCEDBE4C321 -:103A4000B8F74EAF83F877ABAA6CCB83F2562F371B -:103A50006A9B544745AAFCAEEE99DCBE8226699467 -:103A60000F159C4BF64E6FF3B4887D37CBE905BA42 -:103A7000467CA60622B89E266F8E84FB62D6EF9FF8 -:103A800029097DC5E3CADB84FD949EDF1EC3B84EC1 -:103A9000F3E05585882E0FD84327E1BDA7A09DEC04 -:103AA00027EFE52E3D15BC27C478DB9C810AC4E7CF -:103AB000B64C0733007FDBF27A39DF12FAB2491DC8 -:103AC0001721FA067C8C927AB67B5EECF366E74EA1 -:103AD0003FDE5BDB366A21E5856D1BCAE5F3EAC391 -:103AE000BFDED388FE83FA5DF609F24D8E42FBA657 -:103AF000B28007F55CB34FF1615C607CCE1D9EA087 -:103B000045CE25F38973F0DC1ABC4F78A6283D809A -:103B1000482F930FD377459A032077F3306FA9DEB0 -:103B200067FD5E00D8DD9F21FF9F8B4E55A67B1061 -:103B3000BF303ED1516FFB970C8F1725D3B8B3B46C -:103B4000CFD66B527DC7645415C7AB4937CE73D0FF -:103B5000CDB9E0B7E9C5DC845E1C5875D92A3C7F35 -:103B6000BE9BF1FACB0EFF8EFCF4E4F2D7E5CF2634 -:103B70006527C9EDA6912EA2A7E4FEDBF2383CEF43 -:103B8000CC3C29E20431E2DF6C0F8F37DD53D43FA8 -:103B90002D955C2E1BAF8FA9B2D81BD9A5EDA46FB4 -:103BA0005D558CC76BD5886F248CE3ED94814601FD -:103BB000DF8E2FFE744CBD783C2A3BEB5904C6CBFC -:103BC000EA94893EF1E70B9083FD841CDC32FC8F84 -:103BD0000CF347765CA10478DECA4781B3E993AC65 -:103BE00029F678D285C68BAAAA441E431A4BE379DC -:103BF00043552185F2751C5CCF6AF0DF2021222419 -:103C0000B1FF83C451948AAF789C2C670923B919FA -:103C1000CF5FC1EFCFE0383A237B042FD062BBCB1C -:103C200057737B2B97754B781E381CB37864A47739 -:103C30002E3FCFB05C07E5EFC034987F22190ED23B -:103C40008B3F1C7E540AC2DB7B8A578D457C24AF98 -:103C5000636595887BC5D771763C9870F6359D9ADB -:103C6000FABBC9C3F5B1068A3B0D8DE5A4F8679987 -:103C7000BC81EB63C3ED437DDDA4D43F8E65E81DBD -:103C8000A1786952FCF3B3341E1F95EE603EA998EB -:103C9000E29FF9B84F6B597A00E393FD14DD83F589 -:103CA000192315FABB0C60774FC4F396845FAE7A84 -:103CB00079BEDC5ACA2B7C1EF51AB43BF0C5D9E597 -:103CC000D193E7D06B2D9D23BD145FF7D466A03F41 -:103CD000FE947FC461F46FCE7878BE97D9EE40D25F -:103CE000F74F9A859C3B5C25E2E8699FC9D87F9A8B -:103CF0005F5530AF2EE4194BF2BD494A7D5ED05975 -:103D0000C5F5C168F5354E67ABCDEF96AD26F9FF29 -:103D10004EA6A0DF3A7D31C59585BDC7344DF55D12 -:103D20009BB0F34C7DE9577CC6CD388EC8B7EAB15D -:103D3000CE033731FC1E0BF35BE2B32370FE7EF142 -:103D40003C3BE2E724FBAE377CB608FFB8C91FA2B4 -:103D50003C8D3328B3529C9F984FB0530FA29C9A2E -:103D6000D061972F19F976F9B2D5514F795FC6D541 -:103D7000CC877921AC2AE0B7DAC960AFFEB28ACE2F -:103D800077ED76E74DD58C7F673B5B55304E13F66C -:103D900004199E4B28B93AC3FD70F90367DD8FB64D -:103DA0002AAEF79BF39747D0AFD931F53B8497F113 -:103DB000153C0FD56C07FAF29D2A8B7F63E6299C90 -:103DC000F7F7947C0ECA5F3CDF3852CB9495FC7BAE -:103DD0004AFEE5F43DA5A73CFC7B4A0732F50CB44E -:103DE000BF2EF47B4ACBAB39BD863CDF7E71DA084F -:103DF0000B9EBA74CA1F71F94FD1F9CD34916F92ED -:103E00001C2F72BBEBE9BC2D5652BFD81A2F36F1CE -:103E1000D726F4F66F4A74CA0BEAEDEF4198ED101D -:103E200063B82EB788876E29594FF89F5B914DF183 -:103E30002845C4A35CA774CA038E8ED733AA2DF875 -:103E400077E71AA4EF32FE91F1FBEE9FF3FBEE1938 -:103E50001B5908EFB787BE1847E754A1581AF1D984 -:103E6000D4D301FA5E7599FCD8D611507FA053A126 -:103E7000EFC81F989A9E837AEDD34E6EDF661CB80A -:103E8000EAF0DF41B9A4B316630220770096FE3D45 -:103E9000D731F5B4E36BF99913D0CFB49C9798E37D -:103EA000FEBCE110D1C7930D1DF4DCD710A3674B06 -:103EB00043173D8B142D8CEB29EAA0B34B36E90454 -:103EC000D45BE0287A17FA5BE8C1375E1F5F4DFCD0 -:103ED000D7616B9791DF656B077E6E11B653FC1C43 -:103EE0009F2EFCCE188C3FBB8B6D96D4FF51F26A8F -:103EF0005175DFC8AB1BAB079E4D5EF1F3D45097F5 -:103F0000F8AE58123FFE5795CABF8F64F2A53857D6 -:103F100035F5F456FC15F46953D677B87C8BE76F0A -:103F2000F0FB8AE677E9EF78E5E45ECCEB697E5B4F -:103F3000D41B9FEFC5F3DCC4DFCDF8E32ABC77F2D6 -:103F4000023AB76087BEFBCAB3ABF0FB410B6BB262 -:103F5000150DE00BE3016C76E2BE8C99D7988CB717 -:103F6000DF543BCCEFD0511CBE7904FFFB06C9EDFA -:103F70005EAC167E9B6AFFBB1FE9BDDC137AAE9A6E -:103F8000CB8B5F0ABC6D75F13C85DEEE837CBFFA9E -:103F9000ECF741DE14F5E7BAFFF113D1EE0931EF8A -:103FA000B04991FB51FE987F97E349F13EFEF73807 -:103FB000FC2CE5386D42EE5E3ECB27F653A3EF9F17 -:103FC000C1788F107D88BF9F60D64FFA305EFF4F5B -:103FD000541FFF3B093AC589CCFB786DD51D7B1B6F -:103FE0002DDFFF6A8E7F5791E739FD51E02DF9698A -:103FF000DE47897F3F8A1DDEAB59BE1FF540F59B2A -:1040000027C5F7AD9EA6F58A7B38DB70BD03E9FDB9 -:104010007E7A9FF43D81A75E39B8577C47F179825B -:10402000BB3EF93B5DEFEEB57E1F615BF53BAB44FC -:10403000FB97683CF15DAF147421E8F6E85EBC1FA5 -:104040007A1EE3BD46E389EF72ADABE67CD41B3D3F -:1040500043FB23046FFC7BC5B51ED42B897BFF4734 -:10406000083FE781AFA334AF6ECECBF125BB39BF9C -:1040700098F964265DB0597C3F3656C7F3744F12E9 -:104080001C2BFA0C0FA7089EA47B48E75AC7E385B0 -:1040900091CF080E7F3C1FF94F34CED784C7BC3F69 -:1040A00096CC1FFD6649661EB46B16CE931BFF6E41 -:1040B000A77B561FCC0BE366D33889EF81F69F951B -:1040C0005AFE5CD0B84C3DBFFC12B3FCFF0015C8D3 -:1040D0004EA0007100000000000000000000000081 -:1040E0001F8B080000000000000BF3176060F85100 -:1040F0008FC09C687C5AE3BF4C0C0CFACC0C0C971C -:10410000D818189C39191884F8C833E7229ABE7B4E -:1041100040B366F030302C636560D809C47A5CD84F -:10412000F5D90822D847817E5F01C417E91C06A390 -:1041300078F0E01A11068649A208BE9E18AA7CAD46 -:104140000882AD2345995D4E40FD008850BECB806E -:1041500003000000000000001F8B080000000000AA -:10416000000BD57D0D7854D5B5E83A3367CEFC26E3 -:104170003949069884104F42C0A84007080A1675AE -:1041800012C146E5B663DA6A6CA91DAC527F61B410 -:1041900056B956CC4908C92484101015A9CAE02F75 -:1041A0005A6D53456B9FE5DE09508ABDBE277AD50F -:1041B000AAD5DE5829AD566DBC9692BE8770F75AC7 -:1041C0007B9FCC39273393A14ADB875FBBB3CFFEFC -:1041D0005B7BFDEDB5D75E7B8FE27041F509004753 -:1041E000F1DF5900F7FB01605C3A9DF9BD2F5FFDDF -:1041F000781DFBDBEF0E3FC89299BF985F119B962D -:10420000AE3F0724AAD7F08BC57F0456EFDFC1A9C4 -:10421000B9D9A79D0543FE30CBEB9213B09D1BEAA5 -:104220004BFF25C8CA871DE16E964F1D760480F5A9 -:1042300033039CD80968A006A2D3D977F9CB45608F -:10424000EADF9E9EB949865429C0AE95204759BDE4 -:10425000D505A72D1E0C00BCD092FACBFE290091EB -:10426000D449B2C6FAD9DDB297F2FFD6B2EF2FFB2E -:104270005D003128A6711AE67F242F61ED76B9A082 -:10428000B99FB56B8848AE25A6F162623EBBBCA261 -:104290005CAD97339617B072F6BD217841C6F2181F -:1042A0009B11D52B16FD0C0F3AB19E06437E9AE763 -:1042B000E1A68CF39C20DA19F9BA413EDF9D6F1D0F -:1042C0003A1FE99082A2A81BD3C3D56F22BE073C38 -:1042D0009206550CBF83E7117E53885FD6C5A1B700 -:1042E00039BE777DE208B7327C3778D44098E54113 -:1042F00066F460E50D0188105C324B191CE70BB8C1 -:104300002F166913A644178DE832E06174098C0DED -:10431000EF599B1482D798E700CE338F76065DD98C -:10432000D740B480B583CC7C301A3F6CBCD9C70E63 -:10433000A781D7E8FC81BFECF700FD3BCAFEB75070 -:104340007DEE2FFB6BD3F9B386F759F28CA3C173C3 -:104350002A8317FFD43095FF3C689457F1721C27CD -:10436000D1A2FDB986F15F5F0BFCB986F15F6F8B5F -:1043700087F23D2D2AE5BB5B42944FC8AC09A3638D -:10438000A207923A6B5F1C61F54DE315CD65ED4CCC -:10439000F01584554BDE5F1BB2D4F76A9AA53CA199 -:1043A0005DEF4832BA774D73249D12C2C164E44474 -:1043B00084C3432903F7D5109B4F0D6F026B5DDA61 -:1043C000AFAA119E179DD0C6F2855AC47129CB574A -:1043D000869C900CB3F10B8700587F8995001B5881 -:1043E0007F3D334F755CCAF2DDF3DCAA530548B25A -:1043F000FE136ED6CF9194B60AFB99AE84B11FE836 -:10440000937F8B78F2B0FF8E56034CD694B71D8500 -:1044100000553AFB6E9E9F5B0FA15C17CDB57E9F4A -:10442000AC2DBD1658FDC960FA5E95A6A731AE91B8 -:10443000B78F671FE78415B6FE6DFD566A83F5EAF0 -:10444000B474BF27C050AB1AF867EE37D220219D55 -:10445000C2A025671E3FB8032B3E2EDE3F3B8DE7F3 -:104460001E17D78376791B0407E90F90C74184C1D3 -:10447000A5698E6437EBA7BBCA41FCA3AD8624EACD -:10448000ADB593F6C531DF5DA5686D2C5F55BBA753 -:10449000599A01B066924A7CD7BDC30D6D610E4733 -:1044A00090F169A5C1A74706EBAB910F25086F6096 -:1044B000E555DA8156ACAFBEEAD35C7347CF0F56F1 -:1044C000F0F9539ECD7F08FF9833BADF5FCE5122BB -:1044D00051E45B1D926E064F574D5BA3CEC6B95794 -:1044E0009701E5A77B65FF6B88E7C4140EAF7DDEFF -:1044F000959AB204F91ACCE3B3F12A6B2EBC1AE7F1 -:104500006587C3D017DF6F51491EEF6AA9A5F4DE96 -:1045100016B51FF5C45D9F3833E2F77C89EBE7CD14 -:10452000AEA803E1D3E739920F92FE896DBE92E502 -:10453000EFF9EEF859B80E5C3FCF41FAE5CF3D1CDC -:10454000DFF7487D1703D55734AA6F93FF7BE54803 -:10455000DBB758FD7B42A5A03379AE74ED3BF74441 -:10456000EC6F45F54C9DF577CF0D1BDEC6F695F348 -:10457000A66A4ED67EF2DC036FB2451CEE3A3218C4 -:104580008A0630CFE5BA72C5F8FE1AC62713B5BE43 -:10459000EB70FCCAB98A96AC4AF3650584699C1332 -:1045A0009AFD9052C7E6CF8A6B72F3E7F1D3037F8F -:1045B0001FB92A47B92A4DC3BD59D82776BA2F92B9 -:1045C0001CC42F23723597CBD513A7733A1B727572 -:1045D000D7A4BE778B58BEF71B9C4FED7C5E35F79A -:1045E000403DD2B587C94F4908A0CCAD7D2CB17CE8 -:1045F000EF122187730F484B59FB3FBDE2D300E513 -:104600006971667D9D8D9FD3A975DC7B6F70344485 -:1046100059BD5F5E3EF58F6E1C6FB1A2A19CF5CABD -:10462000B534BEF65D45D34DF4AC5CCCE489F157AE -:10463000E50D427E6C7235D6F8899624BCC3E468D9 -:104640007D4B08228C6EEB5A3492AFB542CED01619 -:10465000853296177206B5B3289FCDFE046825B93A -:10466000F368298831FAAC677D43397E4F4522F3E0 -:10467000014A50579D4EE0A41C6C6D5F37520E11DD -:10468000C6F4D02B89BCFE473DC2C653C33CFF6C69 -:10469000EB1FF5554C08D77B797E87545BAFCF373E -:1046A000B7DF43FD1BF5593ED55063EA0FFB9F660C -:1046B00086C7518FF58DFE5E6F2DAFD7D9F8EB44CD -:1046C0005E692BE6F9E3DC7F8FD41F624C0F6B6CC5 -:1046D000FDF448024FFA7F442281F438774AEF46CE -:1046E000744BF91F228827A3FC07ADFFA1EBACFE9A -:1046F0004710BD4B627498B520560E8CEEFEC61462 -:10470000A029B5DE86EFF4FC5EA4F905A6F1FC7DD8 -:10471000AD9F4410DF46F9D352412BE21BF92630FE -:104720001E20444202B0E9E73D573E8F7FD79600F6 -:10473000CC63E3687DA0B13E1C357109F71DA1C5AE -:10474000F2018B3C08BE63F03D2EB174D6FCD8D785 -:104750007029CC009F6E86CF187F2C780D38B2F36D -:10476000271FDFCE470DE7CC7D613E932FFF3E57DD -:10477000D8ADE13C5409F5780902C5F45AF1915DD0 -:10478000442790FB436847DBFB2D59500E49D33C2F -:104790003F6B7ADE85798EB797CD7465F957CD7802 -:1047A0007C1CEBCD19CD77C6FCBC383F403B98CD87 -:1047B000AFCE3CBF279B717ED9F0669FDF3A6F5F1B -:1047C000733483FE3DD321F6BB67CEFD12F6CFC610 -:1047D00003D45F5E6D88F4AF8AE3B1AD66D1915DBD -:1047E000CDB8B5CD369E3A9F8D577BFCF039161F5C -:1047F0000798FED2583D4738371FDBE5D998B71FD9 -:10480000E72D211FF1FD807DDE008C8F0AFEFF9DCC -:10481000F7C732A7E70DAC7F9DCF8BCBC73F685E54 -:104820001F3F5F4AF28AF038393F8732F1D73B9217 -:1048300066D9E7DAF93ADBBCFE517C3A7A5EB9F127 -:104840007CBCF550BEFAB5ED551FE1B1F732BE4F55 -:10485000E8DDBB90FC0EBDCF9F3D01E1284C9C02E2 -:104860001166FF4EC5FE597FBD867DB1A96E8CFED7 -:10487000B97D71670BF4B74F0178AA7090F6C30C3D -:104880004E6ABF99D99F49A6E0EA5EBCC1BB848D40 -:10489000B7F98A0D5EF42BF50A7BB1EEC507D69FFA -:1048A000C3F039E1F292994EC60ABD5EE3FBF6E72A -:1048B000A6B2EF9B2E13DF85FF8A7D7F11EB874425 -:1048C000FD6C70952983B128C90B83CB847FA3FC31 -:1048D0004907B74B9F403BEB44DCCF703BABCCD799 -:1048E000B704E95BB859D1EE9346F7FBBF853EBDEF -:1048F00013ED3436DFBB2EEF2847BB6AE7D653777C -:104900000510AECB80F4F989C987065C1A8EAF4BCF -:1049100088E7275C60D859B4CE975F66D0B5493A2E -:10492000BB86DA093B8BE7BF3FB2AE7E9DEC968A31 -:1049300018CF3FDDF6DDFA55B2A95CFF767DA422E3 -:104940005DFE42DBB5F5B8EECEF2C4DE98CF483757 -:104950008BE9BD550C8E59B2E68C23BF6C0A66B448 -:1049600017B73DE7694E32FC6EDB3A75F2E519D6B2 -:10497000114645A2B3919FBDD72A674F20FEDC8820 -:10498000476EB7F630F462FD504C5B85F89CBD175E -:10499000C2B81FCDA6EFB2D13174B755DFCD92ADFD -:1049A000F33A5EF3F90854BEDF16FDB375FD250733 -:1049B0009F8F13E568B6CCE5FFD3CE278578E276E6 -:1049C000C46F32F5FFF79AEFAC001B27F8D98F13AD -:1049D000B28D93AD5FBBBED21B4092D11F5F0E6103 -:1049E00084A778411CD08FEF0CEC0BE9CCDE93D57B -:1049F000414A5DC1A190CEF4AE12D2CA307557843F -:104A0000CBF03BDB1F09F9E86C25BD3A92EF6A4514 -:104A10003DBA0EF3247F6BA87CC3487E2DE56F9BC7 -:104A2000C4E5F304E7ED03A887AB51D930B8D60E3F -:104A3000BCDE8C7E80D2DD81309A1AA58130A01E2A -:104A400036CA7B07DE0D79D08EDB1D002FE3F7120F -:104A50003502E6F6EB06FE1A525979409407825168 -:104A60004BF9868193CA420C453E51EE0BC5A8FC1A -:104A7000B68179651ADA31BB032A7EF757C469DC3F -:104A8000B37F718D83FCB18B1C49B7495F2516CD6F -:104A900022FDBE588A9DE464F4A8FF458F07ED8788 -:104AA000C4EE6913F03BD93CE44F92FF2FEE47313F -:104AB0007B94ECA0807AE014412F679A1E3D785ECB -:104AC000417E607E4E9110E7147A432A85E3EB85A0 -:104AD0009C4E8CA3D3FE676ABF37EDAFA6FC3E4B5E -:104AE000BE404D46701F2D07997E60EDFD113D8241 -:104AF00074572A78DE1908A7507F6CFA0684116C67 -:104B000099E113EBAF9BC7F21AD23F4AEDBBE6F037 -:104B1000BC128AE9984FCCE47977453C85F9352772 -:104B2000F1FC2683CEF088950FE04F44F7AE91BCA0 -:104B3000B70DCB1306DF80BF0DCBD79CC1F56CB989 -:104B40005CBF13F1BF69A0AB6C29EBBF08F981F51D -:104B50005FB4384CF432E872A7E6A0F5D6A0CB9D3E -:104B6000DA2C3A279859C4304113D2881E334FB8F3 -:104B7000DEA1E279C7298EE483129E4FF5780759AA -:104B8000BD4DB5B3A8BC52760AFF00F7873F28FC9D -:104B900001D5CCBA40BBE341B15EEFBC7D6A11B632 -:104BA000DBB9F97F11BDCF741653BB35B5FCFCE6FC -:104BB00019B64EA39FEEE9160FA53F62FDC598BE3C -:104BC0007EBCC543E90F5A544A1F617A1CD31E5656 -:104BD0009E42BF032B4FB17CFFA0A311E5FFF61649 -:104BE000669AB1F6B7B5783E96A7A0BF42A5FCBAC3 -:104BF0009610E5BFED685AE1E4FE14FF3436AFA726 -:104C00005EAA21FF5EF875473489F356A174515DA1 -:104C1000FABB819F6F3B1A5622BFFE7050A67140AF -:104C20001EEC3E2573BD36AC37E37599F7171CDCD7 -:104C3000707E3063BD4EACF7D87E0E377852BE2CF6 -:104C4000FDF520BCD3DE12F085522559FA5B8FF5B5 -:104C50001EDD2FE00B24BB4FCE5CEF0E1CF7E4B73C -:104C6000047C15C90DE7651EF7FBD89FA784DB2BD5 -:104C70009F437F461DAD035B25933C6F5CA24B0EAB -:104C800046674FE9601CEB4DAF8B4BD56CFCE025C4 -:104C900071C9319DDB190E96F7623F2C3DA59695A3 -:104CA000B37A1BB1BCC0548EED597AD2345E1EFC6F -:104CB000A6B57C446F378361A7A6D0D91AFA8A3586 -:104CC0003FD5C1F5E3B3CEDFD623BF4F5578F97F8B -:104CD000631EEDAE45B6FA3E9EFFAD51BF90B7776D -:104CE000C83CEF29E1F32EDCEC49A2DDB57E61473B -:104CF000E8D2407ABEC5E7246A316FCC6FFD399B9C -:104D000043979AE653FC85BB6B2F9D967D5DF16AB8 -:104D10000E8898D6DDA97DD32052FACFAF5FBE6A48 -:104D20005A37705D9920D6850973F9BAC2F0A67317 -:104D30007B95E36DDD1956BC159D69C5DBBA33ADB6 -:104D4000782B3A2B37DE7E29C6CF863F367EC43C91 -:104D5000FE8673ADE3979C671D7FC379D6F14BCE7A -:104D6000FFD4E3A7CC7CD3576F1D5F6DB08EDFD728 -:104D7000601D5F3DFBD38D6FD0A76BE02EEBBA5E5D -:104D8000170533FD12035D21CBBA1EE6EBBA51BE07 -:104D900066E0A7215CDFBDB8BEA37FA696AFEF3368 -:104DA000DFF928847EFB7567EC09E13E631DABBB30 -:104DB0006F5A7ADDD879C68D8E4759BFDF3989AFF2 -:104DC0003303673CED41FDBFA696AF3309719EDB0F -:104DD000DD923A788D2B3DAF828497F67B467EC478 -:104DE0005E82DFD5231F266A1DC25E2A6B8B305B75 -:104DF000D473926CC9774DE3E537B797B5E9E84BC3 -:104E000091F5325C87FCB5F0E76919F65BC6F806E8 -:104E10003CD9C7E7FBE2F4F8936DE34FB68C6FE43F -:104E2000BDD379B92ED734203C9BC4BEF906F9779F -:104E3000A45F8E1F7CD3DB223566F8783E0D1FCF32 -:104E40001BF0DD2ACF68D06BFE9EF09D66C3DF6944 -:104E500036FC9D66C1DF0A79EE31E1CF5EAFC7C691 -:104E60009F5743E426791CCA1190BD199755711EAE -:104E7000C4FBAB93857CE1F818B7B344494EA9E273 -:104E8000E54D6C5D5B2C8B7D98A8DF68CB1BF62B0A -:104E90002E4747C90F93D97E5580EB6D6677841FE7 -:104EA00024BD1E26794AEF3BB81F4396A39168069E -:104EB0007D7087CCCF872535DC8C70CA0185FCA836 -:104EC000D9EAF7C992B0AF75CBF94E110CA59C0881 -:104ED0004708283E090E7F59BB60FA683814391A12 -:104EE000C3719CAA02F7B171DA8B2FD4CC714C8FAD -:104EF00018F08422048FA2727814391CC9E407BE0A -:104F00004FE67E0BA31F06A1683F0468271AF0AD89 -:104F1000F6469B97A03D5FAC109EDA0BACE7E5BF71 -:104F200011F37A41A4ED59CEFD00A331307E69FC26 -:104F30005CB24357CD6DF0205F6A10F6A0BFBE3D56 -:104F400090399EC848ED766782D9A598EF6076299A -:104F5000A6ED81271A71DD39887C9CE15C7B44CF0A -:104F6000851D9032ED3FFDB53E4859FCA74982D3DF -:104F7000AB9558BEBB43E59676AEF132D9F3ED0161 -:104F80004712438DC682BF43C06FD4EB94E31E35F6 -:104F90008FFDB23B6485F7F8E18FB7F7BBFAD54CCC -:104FA000707D567833F8CADEBF52AAC4C92E96A3C4 -:104FB0002133FF3B5D9C4F95524F9CDBEBD9CA7D63 -:104FC000BC7D8095A35D1C886A78FEC2449EE2C4C5 -:104FD0003C280726FC4C14EDDA5DE23C1AE2E4AF13 -:104FE00095B47833F291A742A1F3017B3B23F58975 -:104FF000F69D9F7CE735928F711E920F4963F29365 -:10500000619CC7E4C878174B37C9910998BA8E38A4 -:105010006399E4649C8BCBB1271AD53C3CD4242300 -:10502000FCB345BF7D06FC7A9CCEBDF285BF3A4FEE -:10503000F867A7E19FE19A43F07F0ED36CF04F171A -:10504000F094427800F7EDC8A0D82FC0059AF95C1B -:10505000AE57F45B2AE003B88EE8669477093CE427 -:105060003B9FF979CEA7373D9F46319F7373CDE7BC -:105070000B623EBD2EBE5E791AA35A88F1554916C1 -:10508000BA2C15FD6F1EA1CB75C7C4575FCD731E1B -:105090004BD3F35822F8EAD25CF3880978FA9C30B3 -:1050A0006F3FC6CF4C16EB0D3459E8B2C5E02B3735 -:1050B0005F3700AEB7D0E576D14FBEF3599EE77C9F -:1050C000B6A4E7F33D41975B72CDC754BF55D46F8B -:1050D00013724576CB16D78E36B43F1E93A31DAE02 -:1050E00039E9F158BD4E73BD89ABBB8D7A6BF0BB0E -:1050F000B468A45E8F185FD845F7D37E6C35DA1894 -:10510000CCBEF9E2EA171AD01E67ED3650FF51BE49 -:105110006EB276B799FB9FBDFA8E3651EF4EACD783 -:105120007AF611A3FF4DE6FEB7B852061C77131CA2 -:105130008D23FDDD63AEB7D4D5DFC6CF092BD403F5 -:105140007E935D13CAEFDCC7158C2506D15F090578 -:105150007D687774C8F12D83C80FCCC87B907DBF64 -:10516000C91D9124B67EAA91F8C358AF4477AB4EBF -:10517000A45B43FC4798D71D10C5B8C83BFDB76E6C -:10518000C1FC0AD9A3BAC3686F697434D41B9429CB -:105190009E67B514D3715D3C24C79E7191DDC3BA7F -:1051A00064E3DC54AA25BB25F4DF82C4ED0E0ED7E0 -:1051B0007AFF250984C3CDE0C2F8E0D536B8D878A7 -:1051C000B42FEF1AC7E36D40865A19FB73FAC2D8A1 -:1051D000DFC0B81B09DE44AB5BC5F689293712BCBA -:1051E000AC2C4AF179AE38C1DBE9F2A8188F77A769 -:1051F0007FD9268CB75BA117517D8203E73FB99A0F -:10520000E0F7423CB5A40AD5575FC481F02C522880 -:105210002E3911DC40FBDBEE456C9163E376D76EF3 -:10522000D0B1DDC1453E8AAFF306FA00E3AD4ACF07 -:105230005700E380BCC13EB2334BCEF3F17C05D0C6 -:1052400038259FE7F1B22E1854AB595A9AE071C72E -:10525000DDB54DFA12B463E6F27854D0232F617CA9 -:105260005B31887FCE8A01ECDF35D109CE709ABEE2 -:10527000A57D23ED8B6219E465A45E32CF7AA9FC8B -:10528000EA9524E4FCEAF5E5592F9967BD14AFE7E8 -:10529000860B8A32C57B8CF0FD0285EC0F23BEADF8 -:1052A0009059FE23F64915B7DBCDF68A0B94B4BDB1 -:1052B000827CE65C9C138E156FB606779BEC9BA0F8 -:1052C0005210A4FDC669701AC9E518ED0FB5E8C102 -:1052D000DDAEB1E78B129632F9C9C7AABF06ED3D24 -:1052E00077F672FF8C0B43A4CFA67F4DA48B793A3F -:1052F000937D9F8669B3C87F4DE4173747328C573B -:10530000AF703D5C0BD19C74F00AF80FE0993F6BD5 -:10531000522BB3FA19CEC78D3430CD61B31BADFA21 -:10532000CE23EB0D74CE51CBE307DD288C283761FB -:1053300020FDE282945A4DE78B91C225E3D3F2E33C -:105340000A8D27F9F93F654E90E6127DC288473BEA -:105350009FD8F92260E38B4FCB27171F273EF127F9 -:105360009C79C98FBF2FCF7AC93CEBA5F2AB174808 -:1053700048F9D5EBCBB35E32CF7A295E6FCDBF282B -:10538000C2DF7AFE2AF4C3F8BFE8B1E4D77CD16764 -:105390002DFF52C092EF39D7DA3E709EB57DCF799E -:1053A000D6F681F379FB273BBE7A36FA79F29593EC -:1053B000DFFD8D7252EBC95DBF64D11872E5D16912 -:1053C0003FE99535480571FD62EB9444692499C124 -:1053D000BE7B4EC8FFF32EEEC749C83AED6BFFD92E -:1053E000E7F90385FB8D8CF98E05AFA17F7FEF1464 -:1053F000F696DDFE1AF1EB1C3E7AF454D42380C1FC -:10540000D2A06A6C6AE8C7055F184345BC357D7455 -:105410003E6DEFBF0BCFEBB8DF25D46482E33937A5 -:10542000F7ABFCBCAA2344E7B553EE08E13EBD6BE5 -:105430009294D1CF7244E1E782D5313FD9199D9A38 -:1054400087F461D7247E8FA9CBD547FEE3AE2A6BC4 -:105450007B8FB01F8E287CBCAE957140FB7FF5948E -:105460003B9A715C77EA5F4163707F77529CE247B9 -:105470003BDC7C1FE08EE880EB8247D3E9FCDD0E4D -:105480004FC2881B82BE509369DE4D6ECE373F6798 -:10549000F3C9675EEF280AD557231C7FD9F0B5E31F -:1054A00018F175B99BF7AB85BC84AF837540EB09E8 -:1054B00012D2C9E84824D6F0FF06C1CC6FF6F51821 -:1054C000C027F8ED28E535F9E29CFCD425FC30EB4B -:1054D000D00FC352EDEEAFE5E4E74EB19EBBE1EB7A -:1054E000D4AF5B8B4750DFF96AFBE052C22F4460B8 -:1054F000BCE03B82B73DE2C0F30580F0666627FA68 -:10550000C675855339FC629E5AEB7A77ACEBD96C41 -:10551000375BCFFCE9F5EC20F49013768D03AEC831 -:1055200074FFC358CFB4E0C539E7DDD5C2FD5600DE -:10553000B7403FCEE76527F1B3A306F4F58C5EEEE6 -:105540005A99E21CDC913E5CA4C15303296F61F6B9 -:1055500079BD2AF84E0BE51E77ADC0F71AA4D389A2 -:1055600039EC2C7434B37DD9AB9DF7AFC2FD5BF140 -:10557000022E07237C2FF759F87358E17E8D2EAF4A -:10558000D64AF12C55DC3F62EFB75BC06997AB445C -:1055900096FB3486DCFE55D1B81EF2F491DFC19043 -:1055A0002F4DFB57D2735D93DA3C88A784B681FCFC -:1055B000C4076B14C07B30767D300287C0FF59D0A2 -:1055C000E3C1FB4ADD2F3BE9FEABBD9E17376526E5 -:1055D000BF9EBFD6AA7FC7D227777E4A7DF21343EC -:1055E000EE47EB135A7F2FEF6CDF85F4E9F272FF81 -:1055F0007549A30E4B4CF3ED11E32F768B75A18209 -:10560000C3D1E552EBCD742A66DFEBCD7A330B7D47 -:10561000B2D1FD220C069C9386C33EBF87DCBC5EE4 -:10562000098E3F6D6C3C8CA603C7C32A77663EF893 -:10563000ACE6D3E6CE8F8FEF16F5EE167835E6356D -:10564000969C18FDF70B7C152FB0E97D59B7D0DF7C -:1056500069E0ADD156CF63AD67E04776737BC5583F -:1056600027C6EAFF2D85F387BDFF6C72F89B1139C1 -:10567000D4C92F6B8CE3861F4448EE985EEE9E09DA -:10568000501018247F01DBEBF378A76014CCE73AC5 -:1056900076FD65E8FF6CFAC8BE6F19ABBE12547296 -:1056A000DA49865D5322EE4D7A443CF00629F339FF -:1056B000CFB09023A6D8F38AEBC33011DCB74114E6 -:1056C000C4FDBFC8402BCB8F0F2B5A37FA3FE48560 -:1056D000035B597EDCCFDCD01D4697CB82810186EF -:1056E000AF35114F14CB2778AA46EE69F59D8A7E17 -:1056F0002D6E7781F396D7F01EF0F88B6440BCBA1C -:10570000611EC5691F5CC174D8CCD1F08C9701268D -:1057100096B054F807E8FC10B7945FB1AD8B8B4C92 -:1057200079F4037BACEB5EBEF3B6C393ADDD98F0CA -:10573000A4F7A1FB717C37E45ED78E757E23766D6E -:105740009EF332EEA319DFAB869DA0E1FDF66189E1 -:10575000D21386FD94560E7B299D345C0A1A235A77 -:10576000C57031A5138727D2F7F2E1324ACB8627DD -:10577000531A1AAEA2B478F8144AD5E193285D2FD3 -:10578000E4B0687836E58DFB6F85C333295F30FC64 -:10579000794A03C3F378B9384F5DBF3206E8AF5694 -:1057A000701D62F2B17AE1525A97ECF35AEFE1EBD5 -:1057B0007087B827DC61D3DBFDA2FC510F97FBF5A6 -:1057C000422E408E83D96F7E8FA8B7BE3A46F677B9 -:1057D00087B11E962DB5AC87F6FA1D59EE273F6DA1 -:1057E000940B78A0B6690CFAF0F357773046F706B9 -:1057F0000062A497408E59F46E87017F9EF708D708 -:105800002F7C9AF8D8CB0419430BBD5FB8BBF901C4 -:10581000D43BE7DC78C56E26771FB863377970DC38 -:105820002F5C454CF7FD65378750BFAD5F7807DDCE -:105830006F42F31BE39A3BCFB925FE00711DA3CB4A -:10584000746A77ABC7740EDAB5F4E6E687587F5A08 -:10585000BB033413BF56DEE203CDACBF0E97966197 -:10586000FB8A1B4A2CDFCBAF29B7B433EE49842E19 -:10587000ABB6D453179C6CA957387F96B59D382783 -:105880000FD49D6E69E70E1878E5E7888CFE96F5D3 -:10589000A353CA4CC7B887EBCB6C7C73A187AF6BA3 -:1058A000E9FE73D32D5BFFF9DE0B49F347D6799000 -:1058B000BD1B4F2C5A80F6945B8DD13D9563AF7F15 -:1058C0007CE7916F3DBBBE2A447D558AFA44A234E1 -:1058D00080FAAA14F5889752A3DEB1DEB75D8BFA81 -:1058E0002660D2377398DC67E0878037B7BE3945CA -:1058F000944FF1727DB356F0959D6F42A2DE5AD45B -:1059000037D3C6D637216F6E7D33538CF78FD6379A -:105910005DB3EE887D8BE5BCA7DDDD7C3F4B3B674F -:10592000DE4879A62F642F2BEF3CF596F8FD263D37 -:105930000287FF93F3A5E087A2B956FD61F45F10DB -:10594000B6E911431EFE46B93E22F8351B7DF67FAF -:105950004AB93E729CE4FA88A77B019E2FE62BD7BA -:10596000A3EB1FDF79E45B4F6F80D459B82F99EA1E -:105970004BAE42BF9BA32FCCEFE5C5286EA7EB39FA -:1059800097F0F370FFDF2C4FE43CE49F599EE82230 -:105990002F6B7F7D953601D76996FF227E37E5A371 -:1059A000B67C93ADFE576CF90B6DF59BCDE5094DBB -:1059B0009B80E78B89BD2E3A1F4C688EC64CFC74C9 -:1059C000AE97F3CB5E4F3486FD9D983C7902D2852D -:1059D000E52FA5FEBCBC3F96BFCC965F4AE3A7F37C -:1059E00057D8CAAFB2955F63CB2F33D7EF3A32F9AE -:1059F0004E7A7FE3972EC07B0976385F117AA273C7 -:105A0000CACDB1362E973761FBCEA9B7C42F05E2B8 -:105A10000BF2A33903B6FD1FE33333BFEC15FDFCD6 -:105A20007CD28DB46FEA64FB278A63443F5E06FC38 -:105A3000FCDA2BDEE1D2AEA4FB0F89B2EBC9CFD1E9 -:105A400059D146710A073585CE67135599DB1B7E00 -:105A5000A6CE8ACCE708BFC6205C933D0235DCFFAA -:105A6000876270D481EF0971FDBEBAAA83F4AB924C -:105A7000BA92FB37CA62E4DFB84FD04F09C4C9AF4E -:105A8000E0AE8867DCD7778EE0C3EAD7DC69E04315 -:105A9000EC234DF820396CEBFA6037AEAF096F6636 -:105AA00039FBB197CB992B94DFF8A3E7CFD7872D9C -:105AB00078A925C3BE36E1E271F2FA24EE0790D947 -:105AC0003866BF827DBC9179DAF6D9F70A3C25BCED -:105AD0003CCEDEE8CF0ECFC3A2DEC35EEE5730E68B -:105AE00025AB7C9CB1FA7F162F6BA11F40B5FB2123 -:105AF000AC7AEE1651DF15B4D6CB869F9523F8E12C -:105B0000F15806FF8EC5EFC6387B112EDACF66DE60 -:105B1000876B87E752FCC64128E8EBC67DB3ACBE75 -:105B200086711C37B16D12FA4557C93AC527E81A74 -:105B3000A80FD2F9273F7FB8C9797218F59D47C4DD -:105B40005500C655044D7189C2CF79A7FFD687B1DC -:105B50007C85EE56F17D9361EF641EB77A7805C5BA -:105B60005374B19D3A8E7BC85B99C4F7AC9C453D9C -:105B700064CF3B9D33E399E24C651FE7DBB30EAF87 -:105B8000233DDBA1F17B371D72CC53320D5DD53A3D -:105B9000C96B97963B7ED11E07E952EDF187567C83 -:105BA0004DF771FA26C4FA9BF0869BCDF149219FEF -:105BB00097CA87BD56F83A11BE00C215A778D244DD -:105BC00085C381783B5EF019E32A558E28E22508CB -:105BD000318A57F184641AD7E1E7F8CD362E68F29E -:105BE000FBE6F7638E173E47D6DF18E727197CC41C -:105BF0004FDA024FC336CC3FE7A4F5D43ECE7E5FEA -:105C0000EC349FC92F2CAB317A77C6E8EFDC713CBE -:105C1000CE5BAE00F2E32B106DAC62F35F55C1DFDB -:105C200059940363C44554D8FD15D9CEE5F8F988D5 -:105C3000719E53FF073EAE4FC40B14C020058B1658 -:105C4000A14A9F8CF1029AC4DF81084B3CAE7C3E96 -:105C5000C59107BD9F75BF8BA95F29B21E8EFA8FB4 -:105C6000A15F7990FC5C9F79BF63C0EB85BBA95FA6 -:105C70000C4D3D5A9AEE17F52F39950E1F3D8AE7C8 -:105C8000664E30FE713B5C76F07B55505E48718706 -:105C9000AB83D77BCC746DF5555BD65745EDB84ECD -:105CA0002AC47B9FD7440673F0E56A9423F42356F5 -:105CB0005C1619ACCD5ECF805366D3CFE40FED50A8 -:105CC00062C956B4172B033C5E558ED3F948A754CE -:105CD00032ABBBCEC4BF154A0AE12AA88BE818CF65 -:105CE000D859EA08631C960C3DFBE87D27E7A270B3 -:105CF0002E79952BE4F7CCF3D9ECB3C681AC1A839B -:105D0000DF570B7D9DADDCA5846399F4F0E33EB1D4 -:105D10008EF932977FEC6F78D49761DDD921F454F6 -:105D2000673153A59FE3EC837C2057EC790DF1B0EC -:105D30007ADC39B9F5936AD54FFFE58FFC04C7C902 -:105D400001C7B399E0007C4C210FBB5F5D40C18867 -:105D5000E978A020E76B8C0392C6D37928FD5B5BC2 -:105D6000775F0AED6ED7924004E9E78C6C035C47DD -:105D70008DB82067C4F7B683E8399FC707D5723F4F -:105D80006B84FD477164F373C78D396DF95FD9E991 -:105D9000DCF20CBD1761C06FC4A9DBE7F5A4BFE15D -:105DA0002DDF9C4CF8C86F1FB491F10B307ED9C029 -:105DB000D6778614E86B5129DFDB12A27C4F8B4625 -:105DC000697B4B2DA56BB0E93C8CFF8827AA703FFF -:105DD000127A207439ABB2116942712D5B17E23E21 -:105DE000B27B240FBAC4E0EEC6FBF1CC0EFDAB6F64 -:105DF000C342B443BBC5BB3BA0772C44BB2C9DBF67 -:105E00006B35DA85DD228E565D73DF42DC3F6E9C9A -:105E100064EC93239EAF9AECAF297E17F11FEDD56A -:105E2000A8FDAAD5D89F571679D8BED09A8708C2A0 -:105E3000E3F5F0FCB9FEA7081E52016CBC0BFC4F49 -:105E4000537EE314E17798D634061EB91FA3C3A787 -:105E5000713B685A09F929947018AF17C0C66201DE -:105E6000779EFDE0FE87D6BB9733AF9769B919637C -:105E70005D13708C457F860EB22F500FEB38EE2BE2 -:105E8000FCFCFC788FBBD1756C7851E60EE978F597 -:105E90006BA72F76869FB52F88F4A7AA58BE70519E -:105EA0004A27F1CD73DC32BFB84FC6E68BF26FE004 -:105EB000D9B03BAE433A8E4BF7E70A46E8BCCD2B50 -:105EC000DE13CE17DEA53ED5D20F3CD65096EBDCC6 -:105ED000655CD481414623FAA2B4D127823578BECD -:105EE000385262C917CD2DB7D42F08575BCA5DEA67 -:105EF000C996F2BF954E5FF7A916BE8EDAE6B5D009 -:105F0000569E6FBFDE154E0DDF83AC920D7B740382 -:105F1000DD4B3E883846FDD83793EEE9428D710F50 -:105F200001285EC5AB45883F7D10A6755AA9B0DA39 -:105F3000A972D06AA7869AF594D12FC6677B572895 -:105F400034EEC83A15E0F120C63919EDD727A3AAD7 -:105F5000FBDEDE2ADE2E6CBE7F6F4F65715E4677FC -:105F6000EFABC63E4FB58F13FA4AEE38357B7D084E -:105F7000C8DA0193FC656F27C301D3BB1A5B91F6A6 -:105F800073D2F88F6C5B427E0F37303B9AE17955C4 -:105F9000E84288B17976601546BF04A68CCF3B42B3 -:105FA000B3548AC3D7385D1D1E2E27DFF16B967858 -:105FB0000E6780CB89516F2CFADFE48478A6F5EC6C -:105FC000153FDF271FBA35FE27DC5FEA2F01BDE34F -:105FD000DADF324CEF5CD6A5CE75A2DFE435FF7870 -:105FE0009A4FDDEE88F36C533F75C0DFFB66FF9C74 -:105FF000667FAAE11F86C31E8A0BDE9EE271C1DBAB -:1060000053FFBDEB28E6F73AE85DD1EDFB72DB57B5 -:10601000FDC2BE32EAF5EFE5FBD57E19FC25B9ECF1 -:106020001C71FF6D66CA1677288313E97F68A5E6A1 -:10603000447BA7BFC523E1BA3F4BCCB32E1571E219 -:106040007A3AD6BC76DAE86BCC13EF1FE23CDB037E -:10605000FC3E60BBCAE64B7CCDDFCBCE06EFC8BEB4 -:106060005FCD8C0FA580BF7BA1B8626AA6798F75C2 -:106070004FD180AF03E19330E5707504391D3A428A -:10608000B9E9B04AC067D46B0F723AB433FB201F32 -:1060900078E480151E66E34968170620D9486F9A90 -:1060A000E9F012EE8348556888879DA97B105EBC95 -:1060B0007781F67C719D7439DEFB8871FBB0A02E70 -:1060C00095DA1124F3248AF7324A0707526FB1F2A6 -:1060D0003DCD7E7AEC49BD7C7F0AFB91D521929F14 -:1060E0006E1C8CECA3C91D68EFACC63F994A9FD0CB -:1060F000133A07ED0F19B85E6012A7C9E3857D92C8 -:1061000041DE4DE7FBD25177BA5D36BCD9ED4E3753 -:1061100034E5D657E2BC5F67FFA1BE516DF723ECB3 -:1061200076AE3D0EFE0CD4E7E3F2B887F129C7291D -:1061300082FB3CF81E82B3D6A1E23BCC4CA517E310 -:10614000FD1F7F448614A3675160909ECE1A0BEF0B -:106150004CFF35F2B8D17E30DF236D0A703F50B06E -:10616000A94E92F83D020DDFDD0C36ED0D67E253CE -:10617000833F47F28127483FAE866402E34EF446F0 -:1061800007AD6BDDB5D5C5E6FDD1750149EC430D15 -:10619000FA83269F9AA63F9B5FC43BE3EF47FF929B -:1061A0004556BC1F2B5D5606B85E1A8BFE9F761CAB -:1061B000836EA3E5A355D06D23E9BFAE9AFCF44AE4 -:1061C0009A6EF791BCFA6B2192CCD0AE4DD0CB7EBB -:1061D0006FDF0371C0DFA3708A7854E784539BB7E5 -:1061E000420EBA8C8AB3E2FD3803DC9FB656F285C4 -:1061F00071A8B559FCCB350592D0FF833C9E6FDE6C -:106200009E109E1FF7CC3910C2738EDE4F329F4313 -:106210009E5B20CE4522AFD33EA0770EF70BE23F28 -:10622000D43B37F13FA15A7F7713BE63B6F64DBF1B -:10623000C51EEA68C9ED6F50CAAF88A19D71E86DAF -:1062400049C3F5462A5F7122C235306F29BD3BD262 -:1062500051B793CE617AC2B9E962C4997688B8E839 -:1062600091F1B39C1B1E12F25AAD5F4DF6656FD9CA -:106270004B34CEDABADCE3E07B59B9EE45791C1039 -:10628000237FB1ED5CF70D31DE1B01713EE18A7EAB -:10629000697215FE2E874EFEB1F1B5D10107C35BC1 -:1062A0005341ECD500A36BEFBC1BCB100E7C27C673 -:1062B0004CF720F69F01BEF1050E8BDD74A83AFE67 -:1062C0005F2BEBF0F729A6D2BBF546BD9E2C71ECF7 -:1062D000271B74D6BCB4EFE9C0B87F065F4F597E68 -:1062E000F837E87C163CEF998CEDB3C4F91AA97D18 -:1062F000BD1F0BEF763CF4BA06290EAA57CA3C9F85 -:10630000730BB8DCF5AE4CF173B57907E85C2D90F2 -:106310007A9DE227BE3B671F9DAB5516707A601CC5 -:1063200025DA518573F97B80D9E4E85E413F59B5A0 -:10633000D60379D072EEB32520CECB82B9FB33E001 -:1063400004CF203FEF192D97B4FE3CD8F3C01E7A3E -:1063500037055274AED0F18A13EFA68EE061945CDB -:1063600025F8EFC2F4E2C6E3741CE7D60EF493F40A -:106370001AE76C33F9BE49AE4BD1399BA740B3D86D -:10638000EB81B0F12E627EF30CE05AC4FDC332AE55 -:10639000ABE88F47F8DA675E48FEB46C74FD8E3F59 -:1063A00036BB609CD9AFCFF75DFF6C7C7828A059D5 -:1063B000EC433B3FBAE11BC7B4AFCBE65F3E24E4FE -:1063C0003388154DFBA46F162899F1FBD64563E180 -:1063D000F79B99F17BB10FE13D747BE6DF2732D269 -:1063E000BB6CFAEE2E231E057F24A48CFAABBA20D8 -:1063F000C3BC8D75F55081F17E4FCC87EB46B53E21 -:10640000DF87E33FD473A90FC77D68536E7A1AE321 -:106410006F11E78B49F1EE88519E147CB9D5A6E740 -:106420005F16727D8F90AF873C511FFD5EC5AE8BAE -:10643000CF3B89E1AF9AF105BA14B52E28C9357E54 -:10644000956EDB971CE3BD96DE025B7C6F9EF73496 -:106450003F2D5EB622FF9C8E78F877927B67AA88E4 -:10646000E4A9FA1ACE37D5970DA5705F3B79A3231F -:10647000A9511C4B8CF052768DAC514C9BB8F77ADD -:10648000A258DFC1798BA312CBF1DEB88A6E17F563 -:106490006B140F73B7F5F73F1EF244DA14B47F1391 -:1064A00014E908D53DD6DFCB9808A6DFAB60E396AC -:1064B000BDF92EFD7E4A99ED77413E2DDE77FC83B6 -:1064C000F09E94C167D6C79A04D14C7AFF3F055F0E -:1064D0006AADBBF93B06F100BC633AE760F42B41BF -:1064E000BB608BBEA11EF1A927203C25831EFB6D3E -:1064F00081DFF81D9FDDF8CE82AB82DF3F5BBDE41C -:10650000C2C11D4C656DB9A5C1721FC0A4177E5BC9 -:1065100040EB13D70B49BD89A7879DC427537A2029 -:1065200089BF83B260637CC085A27E0D7F87BA2C51 -:10653000A14B0ACB5733F395750F93AF005E7F31B4 -:106540002423C447F06A687CFAF74E2A07AF1BC0C1 -:106550007DF11EB62FC6DF51317EAFC4E097897141 -:106560002B7F4C4958F3136CFC626F5FADC17938D7 -:106570007E4D8F03705F37AED9541FFB83A1771F09 -:1065800066E34FD98D0F33B2B42F77FF32C45C85E9 -:106590000C9F4FDD1AF8652D9BE0FD3D0DA58897FA -:1065A000873C40711107A31E7A7701A299CF9346C9 -:1065B000F1AD61F767A99FD697BC9EB1EE75BE2974 -:1065C000F1772E2AD5B7ABD0CFF92AFFDDBAF4BBCD -:1065D00015A7D3BB15218873FB11A294B60BFE54EB -:1065E000CFAEA8427F68E22DBF8AF7B3D452AB3F4B -:1065F0004D2E69A4F7C046ECEE126677B3F244B1B3 -:10660000558FD61772BB355CC8EF85AA7EDE0F7832 -:10661000F432B3DEDF582859CB037AD9974DE50D14 -:10662000A27D42BC5B7E56E1799D68CFA81359FDDF -:106630000CFCB9408C6B944330BC0FDFFFD8F48D59 -:10664000A639E6F57C63213FDF514F10E35664869F -:106650002B51C5C7BD4D8CBBB1D0FA6E1CA83C35C3 -:10666000BEDF5170A3B49FE1FB900B1A305E65D57D -:10667000384712DF4DBB69BC1117965B4F18741871 -:10668000C1B7CAE391CAAF50673933C8B1916E6ED2 -:10669000E47E2AFBF74BC43CDAAF68E8AB61704597 -:1066A0007673B9730721E3391093EF4B0AE7645807 -:1066B000F7DB1B691F77A838F7BA6FDFE7CAC2BFDD -:1066C00068AFD72AE8A4BD1CA2A7B8DB43DC9F684B -:1066D000F47FA88CFB15EDEDBA6CFD7BA1298271CE -:1066E000C678BE8AE7AA4A0D24F1BEA92FD8A756BC -:1066F00069181FB04FC7FD91060C8FE8670B03D9CF -:1067000075ED21BE1F95437DF50E8C278146D56C16 -:1067100087958BDF5534F2AE40ACB590ECA1884440 -:106720007891F979FE2157F25CC4E7AA2A07647AC6 -:10673000A7BFA790DBB99BB5A617AA32D06F7DA1E2 -:1067400066B19FCB87B9FD9DAD7EBA1E876F841F52 -:10675000433ADD3F008DF3635341E4F6C24CE7B7A3 -:10676000865E117EC84BE70A850BDA45BF66F3B833 -:1067700072AF8B62D3CF3ABC650FEA5F27D3BFDD20 -:10678000F43B727D7BD00F7919DE7F62F92BDF9CA1 -:10679000AE54B2F257CB9DE2D1F968218EFB01389D -:1067A000C85FF201BC5438DB44BF270B15BEDE24A2 -:1067B0005CA4470D7FDCE57D2E8B5EFDF6266B7EAF -:1067C00029348D473FC5D28D2E4832FC5E69D3BB3C -:1067D000F717F273A26F43BC03D7CFD5E2FCEFDA11 -:1067E0009F4C57506EAE9CAD56394DF7AE9E2DE482 -:1067F000F6DD7B8C8F34939C5D15482AB88F7B67C0 -:10680000FBEC0B3F0FD84FB2A31CFD69C599E30009 -:10681000BF95B0C239D63CEC701BE779D9E090B790 -:106820004919FD42CF154A167FFC2A0F7F0F29B266 -:106830004A06EF9918870774CF4F7FB380DEEFD6F3 -:106840001BE21457A7B7B9D555418AB3A378BA1537 -:106850008C60F8FED001C17F465C1D33284EC37D9D -:10686000DAB59E4105FDCACBE57823FE749A712EF8 -:10687000E376C5221319FCAE67EA5313C1522F9178 -:1068800067BDBD52755EF51A1D39FAFB50E8C95F48 -:106890003C76BF82EBCF078FBEFD4594C3AB9F759F -:1068A000025ECDFBF0B10248D1FE21A9A09C5FB5EC -:1068B000DD99F11D098631EAFFEA1F15905EBCEAF9 -:1068C000097772116B7FD5D3EFCC00264F1FB60D21 -:1068D000ED9988F87B54E2E785FAE00C5C9FAE9274 -:1068E000E19B99DE1DF31671797FFFA7FE66A49FD9 -:1068F000B46DE012EAB7FF2297F95D7C28E2EB0F56 -:10690000ABC7E3261F91925332E80F633FF4FE2397 -:106910003CAEE4AA675C490C09BE6ADB5625C6E0BA -:1069200058BEED23E297B37FF47821E261F9334E4C -:106930008B1D71F58F3EE9389DD1F96A270C2D42E8 -:1069400039761EA6FCC18867C84972CDE35396917B -:106950000A60F59EFCFD39BF66E5EF859C8021AE9F -:10696000EFEDFB9DF22CE6630166B961FF56BE5E5A -:10697000BEED1D857EC7C80143159FC7F30FAB9DB4 -:1069800064AF0F30A4A09E5ADEDFF59193F1DBF2E5 -:10699000ED1FBC817CB7DC261FEFE11F65A3EDF383 -:1069A000994536FB7C5B695EF6D1D58F1FBC17FD20 -:1069B00011EF3FF1C77BF11EED35473EBEF77B1867 -:1069C00017F66F5E15E57BF9A3AF148249FF9F5F51 -:1069D000C4D7CD0F1F79F8A1CD6CFE1FBEEE266C7B -:1069E0007DB8E3F795E8FFF9F0C77F1D8FFEA01B88 -:1069F000762CA4DFADB9E1A9B327E45A17915F93D0 -:106A0000E6DF5714E746DA33121A93003F13A98DD5 -:106A10001ED037A4E0BAF6170986BA8BD9F7FE4F15 -:106A200014B4CFF6446008F1B36BFB3B7B6E66F9A0 -:106A30000F187DDC19E8C3E63FD141FA99890D4B67 -:106A4000976DFFF297CEA8C3D44576F8721822BD91 -:106A5000398AAE2F33BAD6A5E96A2F3F0887153C8D -:106A60003758FE18A3E30CA427A3E38CD174FC00D1 -:106A7000FF98379A8E571559E3920EC2355B3663ED -:106A8000E1F6D28CE7BCC63EEBDAA7BE9AD37E32E3 -:106A9000F4C25878BE42E2709D5A14B9B908E5EBC9 -:106AA000891F3CB439C8E9BC8821E6C3C70F560228 -:106AB000E3933FB8862E413C0CED70ABB8BE5FB59A -:106AC000E357246F1F3EF5A2A2517C0B144AA7B2D4 -:106AD0003C8CFC7B09587E99C433D73EF0FFCE79BD -:106AE00083B5BF167F3A5525FA517E0F933FA247D3 -:106AF000F282460DF56E721CCD7B5992CBC5B2E485 -:106B0000C05730AECF8EF7278B1C86FE1FA12BC639 -:106B10008D2DDBFEF639C87FD9E869CC5FC5F99FBA -:106B2000C6CA1FB0CA6D563915F4FD70EB2105EDCC -:106B300083D4B38AEA60F6F087AE2185D6C71F3BBF -:106B4000D507C3A3E99EC6BF883F3AC67DF80FEDBF -:106B5000722EF033969C8F3DAF63C3DBDD451ADFA9 -:106B60005FD9F0F7FEE1CCFAFF39A1379641BCB10D -:106B70007CF2E8F54B86A83EB12A0DEFFB183FC624 -:106B8000E07DFF5127ED0F3BFA77911EB7EB8B6548 -:106B900059ECE8378AB83DB0EC998119A8D7DEDF07 -:106BA000F953E2CB658FBDADA0FF66CFB62795C187 -:106BB000696939C0F5C1FC3B38EFFF706006EAAF88 -:106BC000E559E2007F2FE6B3FC67D6FE973FF691CA -:106BD000A5FFABF57E85FC64638CF39E1CB908E7CA -:106BE000FBDE3E179E60C07BFDCEC64C76CEF362C8 -:106BF0007D34F0D45170EA6B4578EE55C2DF616C9C -:106C00006F8DFC8A7EBFF74597D8DF465E437B6673 -:106C100055B142F711DA0B2E247FBDD15F9F0D9F36 -:106C20006A50ADC7FD80BA205A67DE5719F0174782 -:106C30001C16F86F28689CA005F8FE4C63FB8FFFBC -:106C400001AB8A1A34008000000000001F8B08008E -:106C500000000000000BD57C0B7C54D5B5F73A73CF -:106C6000CE3CC24C2627AFC9D37892F09480431211 -:106C7000DEB40E0491226A505AA9F5AB03F28821C2 -:106C8000C9A4F8E25ABFCB8444F4029F8D95166ADA -:106C9000693B70A152217690A0B10DDC012C060554 -:106CA0006F105F78B18D5A152B246314B4575BEFC6 -:106CB0005A6B9FC3CC9C4C84DEFBFBBEDFEF0BBF4B -:106CC00076BBCFD9679FB5D7FAAFD7DEEB0C28DEFE -:106CD000DCEA5400D93D6B366461AB5AD41409E048 -:106CE0002BFABB2AD6028400C603585DD5E0776133 -:106CF000AB5A407300FF7D45FFA7785B7BF0F97BC3 -:106D0000E5D4D6B5348FB5F157D4872605B657F2FA -:106D1000B0914A25DDBFC2BBB61860A3F39F1FA781 -:106D2000FB2B8376D58E6D73EA3DBFA5FE0609AABF -:106D300065EAD3F3383E6875A8DB55BC9E0E0BC2DE -:106D400065317AF25424321BA00CE9A016FFFC3006 -:106D500001DF2B488266A8031C012959A120B5C672 -:106D6000730FAAFE62757CAC2FBBBAC18FF35E2D88 -:106D7000BB2CB4FE07732D217B31B537A641D9401A -:106D80003E18ED03ABAA213262F0FBADD98E855BD4 -:106D900080E90E5A681D9223B49D08F181A67A807D -:106DA00069030DFF873C74C4D18D037CB40E45BFCD -:106DB0006FC565D14D3B04B94D213960EB84084066 -:106DC00029D2AD96B05C52A1479F240AD563006ECC -:106DD0004CF57F93D6993BB451A2EB1EA8E6B612B0 -:106DE000FC12DDB738EBF2FC5FB33E58A09CE9190A -:106DF000A9CB175FB1C12AF8AF28A00C29273A36D2 -:106E0000ABEF8FC679E87E268D0AB21CC6557D672A -:106E1000740BC181888FE3F323336764126E8C7126 -:106E2000CD8EA29312F2DB27A7A82945D85790331D -:106E3000C4A753A9CCA71F4DC399F1FE8F4FA56ED0 -:106E400095511E8F48024F41C213E10A1A1F277C39 -:106E5000B8113F6BE9B9198DBF65BC58A0BAB952DA -:106E6000E7A487F827FE106F8CA7958A43B57B8926 -:106E7000B73E4DA1796C105A2B11BD7EE6A7035A7F -:106E8000B91D02616E5DD0CDED5DC4E76C92839754 -:106E9000FB69D0D33A149F9BA356D7AA78FDC7B3FA -:106EA00033245A9F0B549DBF8579D41F94BF3391CF -:106EB000BF8E187FEDC44FE7407E3A40653EA47B0D -:106EC000C1BB761CCF0B115CC723D321243388545C -:106ED00050112F39FA3A33C127117D841F5A5FF6BA -:106EE00002B13EF3FB72A195C7E54398DB42E8E6A9 -:106EF00036C3A14A0AD3734A97EF3BF09533468FC6 -:106F0000D1DA09C138FFB9429CBF98B9ED963CB4BB -:106F10007EE3AF9A71F887CA83BE2A1CA7F85D3E4C -:106F20003B2EE5FF54CE201082F5720548AEAE9E92 -:106F30008573C18DC3BD36888CA4D9834C5FCA4884 -:106F4000D137EC8B1D051531E8C7E7ACA73E3C45B2 -:106F5000CF59216E1CD121DF9A467C7F982E4C1E82 -:106F6000C8F795A79AB29E8B9B77AB9A9A45EB840C -:106F70008930F12B39F63C4CCA402333F0F9CF5617 -:106F800005B39EB3C6F8D0E2F867C6A50F019CF220 -:106F90004DEC138EB36238465CB29D0BAEB6ABCDF2 -:106FA000598C43C6E94A64901DDBCF528A42BC7EAD -:106FB000689C7823DA618BC3274978BD4E75878832 -:106FC0003FF5AEF02CB61326BB317DBE1AC9C77192 -:106FD0007D8DE025BE6EDC73C369E26B9F07347B59 -:106FE000BAC0856F02D909C38E8026A37CD748E337 -:106FF0001C12B6F5ED1FBFF47B1C9FD229838CF7C2 -:10700000FB70CDDDB46EC5974E4274C2FA04FD6EBE -:107010007608FD31D669D6D77F749D28799E9FE585 -:107020002093FD5DFF2FF47C3FA4B6D2F84D0ABE3D -:107030009AE6EFB286B6231F561C91196F2BDAA47D -:1070400010909C152D8DFAF7BE2883C01FF0FD7B94 -:107050007F55CA789461F48FA6E1F381CD562F5AFB -:107060004C48F725FAABCCD943408BC301047D2FA4 -:10707000E722BF16EBFCDAE87C780BD1B3A949F81C -:10708000A7ECEA8C84F19FA55C6F5B8AF36B79486F -:10709000D714C24DE7F035D85F5E20AB329A889C9A -:1070A00005F989FEB1D5FA0EE99F86FF08DF86FD56 -:1070B0005A4AF68BEC907C3FFBBF7320FC9F02C2C8 -:1070C000FF35A0BD8AE07CCB3689E78DF96A3A1F8F -:1070D000595380ED1DA1C4EBCB4189F5D9CFBA47F7 -:1070E000921D580943BC766920FE2DE9887F0289EC -:1070F0000B5C420E2E2FD997FE5764AF5DB082F520 -:1071000095F84E7644EE19B1711ACE17E8B242489E -:10711000237989FBFD9BE550B038A61FFD5D7B9868 -:107120001FCBF2901F884F7B6E22FF53B444FE3B6F -:1071300047667CAD3C52BD267ECA7399FFC86FA0DE -:10714000F9D32695243EAFF37B24FE13FCF6319D44 -:107150004B3B24784C223EAF3F5CA00DE46B43C711 -:107160002336D2FF8BF1D5CCC7D1E9BA1DD1F9783E -:107170000E3A0FE8A8AC7678D894F03A14B5753A80 -:10718000E1B410F5967062D66B837FD62CD567C3B9 -:107190007197D1385C5FBE232C94D10BCA09C2CB46 -:1071A0002261779B551FFB23C3DE3A2FD8ED77E191 -:1071B0002B6CB3E6553E4438BA534A6D952B07EA1B -:1071C000EDBA31F7B0FD2A5C8DF698FD6A629C1627 -:1071D0005EE5F02E467A9E5C05DEC5C3009E5AA58C -:1071E000726B8EDF0C7DDF8CF19B5DF8679E5741E3 -:1071F000FCAE55C9FE7855A2F3611BB09EF69541D1 -:10720000682BBE3F1CF9D4A391BD2E8F5E5F8DF11C -:1072100045600954539CF1AF1922AE7B466F6765F8 -:10722000D8B85D5B6D011FBEA7B7530E49485FAF6D -:10723000EA3B7215D99D4EABC6F1951A7DE97B7C70 -:10724000BF425D8BFCCCB3B48EA3F7E2F8D9219C8E -:10725000B7AFF35DF7ED717EB9B7E3D1511407FD18 -:10726000CC0235E124F1D0F2740BC731BD23DFF13C -:10727000E0B2A1DE11B501E2E9C19EC66A8AA7EEBD -:10728000746A4C97AD7D7AA480F1338FE3E3E7967F -:107290000E61BCED3D0321D2BB59F2ADD78EC1FECC -:1072A000E45715AF9D95CA77FDC2093C84E5BEE160 -:1072B000CB8A4DC4BF00F273355F6C3D41F27AF664 -:1072C000CF0A90DE55363EFDAE1FD7793817D13044 -:1072D0000960822F5C11C151333BD3A7937E074EC7 -:1072E00001EBEBF86E2501B720D71D2A20BBF286F3 -:1072F000080F27BE61BA0F4199E2FFC93D89D7A7A0 -:107300005E04EFFF62D80D377808EF8FADEA807723 -:10731000C92FEAFE331F17988C9F06BEF738673CCB -:10732000922EE2769970EB55928F7F2743C4F91B1A -:10733000BE9425C2655F14BCAB915F7D8BF379DD94 -:107340007D9F524086ED97F2EC709278EBD7E9364C -:1073500096DFCF6C02F73F5BEA0A35E17A0E2EAD7D -:10736000BDBC07DF77FE9FFC97AB5F1707A369B132 -:107370004C6279A511DFEF9CD722B11E426B1EF142 -:10738000CD3CDED013436F0C7DC95B3AC41F4AF27B -:107390009EE1B43EA46FC6D291928D70BB5F029203 -:1073A00063EF6AA4EB6BE2C720AC2E207A021D9F2C -:1073B000D8C85F3B3A255F28C9F8C3E96EE65FEF9E -:1073C000EA60D354E4D73D8BF059D20B5B6B71B2BA -:1073D000F983B0A1008343684BD704EE1D701BE90D -:1073E0002528AD79E4B77B3BAABE4576FD31D44371 -:1073F0008A1B7E66F532DDC17A80EDC4160A3CB187 -:107400005F783D6C591B974776A74F3F958EF39D4C -:107410004A5779DE4CBF5722BABD7FFBCC4DF3F7FC -:107420007D6E67F9E5930EC7C56D9FA60BFEACC9CF -:10743000F0BDC678A9C96263EAF5BBBD8B2B00AE6F -:10744000EC407EC7E13226B720AF3BC31F647A32DF -:10745000BA3171E2FCCBA751BC1CD08D334424500F -:1074600026C4EC73A5A3305220F287700EF237A326 -:10747000E6C76CAF53D00E53280EDD8979115B64DB -:107480007C9E749FEC42B32AE2AC967461E75A1E6C -:107490005142CDF8DECD4A4FCA306C8B7DDA0C45B7 -:1074A000237B5FC6F3E6DE05ACDF164748223BE4EC -:1074B0002CFD45FA85B86B2AC0EEBFC9CC7FB39CC2 -:1074C00046EB7AB126C3FF05F1756C57F420856F42 -:1074D000DE14C824B9CE925DBCEEC96785FD31DBF0 -:1074E0001B39F2AB9F91BDE9D3F3A724F6E676F200 -:1074F000AF86BD01B9EC10E167EA8B7A9AA9DB1976 -:10750000CC3E980F138FFA9B5D49ECCB24A84E43D9 -:10751000165FD4BE98E588C1FE857E2132A3A20BFA -:10752000F528EE79B33D2AC8D0FDAF6E8FCEC1B439 -:107530009CABB5185ECA577A0FD9E3F061D8A11891 -:107540005E428C33F37B24705CE8ABA5643F8ECA4B -:10755000696477A6A3DC71FE2E5D4FD23F0D7D8B53 -:10756000E4BFA1F39A14C2F5535D550E529B15B9B1 -:10757000B2F6678C9F9503F383A0C385EC9DF15E03 -:107580002B3834D748E28785F920ABD88F7B7F7FB3 -:10759000AB349BEC220A2D6DFE98C1EDC18A5C1BB9 -:1075A000BFE7A9AE9234C2910B30BF45F955764A78 -:1075B0001C2798716DC67133BEC0C2796335C7137D -:1075C000B214D6F71D12F3D2E2E064F65377611ECF -:1075D0004E716B7F17FA2D6C9F423F4F714AB36B10 -:1075E00016AFDB58AF41DF5DA93372A06CE0FA8DB6 -:1075F00036F0B90CA1CCB8BE12B5118E039FDB12C8 -:10760000AE1BFC1C8C0F063FA7103FA5FF3E3FA7FB -:107610006608B99AF9FA3F5D7FE18A49906C5FE0AC -:10762000FF97F54F05FFEF7B44BEF55AAE27664F37 -:107630000A57CC9697211F26503CEE8DD90707FE9E -:10764000237C8DED68657B3309ED0DC5990575616A -:10765000B62F137345BE64B61B5776C24D641F2701 -:1076600047302EBD04FBF129FD471EEFE3FC32033A -:10767000E91EF7FC82E5BBF0D2580D32E7E27BC68B -:10768000762B5EF27BD09D99745FC0EC378CB8D4BA -:107690008847CDE38C78D4F0270D3A1FFE3DC3FF19 -:1076A00064065D57D520E91BEA55F8312FC35EA368 -:1076B00078A13BBD7A37DF1F190E721E50022AEDEA -:1076C000EBA0BE721C56E97045E4B103F5D369D254 -:1076D000C330F285F609822E4B689834900E0CB7B1 -:1076E0008314F7E103FCFEA5BABF28C4312CB4060D -:1076F000E0F8BF702CF8C9EF1696638BEB3CA6C779 -:10770000232F995AA4FB79E2AB5581A0BDFC1FA79A -:1077100097482C2827FEF8FE40EB77CCF631FD0584 -:107720002A78298E2F50C29217DF9F51A74917360A -:10773000910C3F8DF315CCD5D85F160CC53E8DA7A7 -:107740007827895C7A32ACBCCE7A47CF611BF221B4 -:1077500030B771B6DB128BD3ED56BFAF80F68F3AE0 -:1077600044BC0EB4DF379EED9244EB516608FE0434 -:1077700054915FB94065BB59A9CBB1D23197F77726 -:10778000C827DA270F5CB7A4F97870FE7CD0829303 -:107790006376D5C87F701AA0F798ED6ADFBED72F41 -:1077A0000BA23EBEF5BF3F4905BCFF27259A4AFC08 -:1077B000387DFF89541FF2E3ADFB45FEF27D537C1B -:1077C000A4640AB92ECEACFE82F87ADBAABF4D883B -:1077D000B72FB0329BF5E28E904CC9F005FD59BE33 -:1077E000C3C97BCF46BF3E9C99D037F4A0DE0E8D37 -:1077F000C9E2EA6999222FBA63D7161BE5D18B3308 -:10780000FDA999D83FADC77FA7DB53793FC0A067DB -:10781000D1AE7136E2F79F3AED106103D96D157262 -:10782000F65D2F4DA0CD7BF167A6F3F0FE021BEDB8 -:107830009F2F91202AF6B5E0F0CFB1FF5EAE0C6B22 -:10784000BD03D7B1E42DD56641F92C990ED120EABC -:10785000D5A2BBA435F7E2F8457E17457003D6B92B -:10786000309898E72FD3E395DB1FB29AF2A4C6C3F2 -:10787000B45FB618E7A17C76496BE2FDFEAE3B0F24 -:10788000FF9CFC40878DFDC0B28BE44FE332F5785E -:1078900065024CFCAA94E295B21F956983DB25230F -:1078A0005E39BD0A083CF097550E6ECFAC52B9FD5B -:1078B00042B7D7CB3B0E1C665C2BDD13C8CF3ED541 -:1078C000F5AEF3162DE637BEB9E593433FC77E0507 -:1078D000ADB398EC65C44A78BC4AF71BCBF438A426 -:1078E000E273B3DF38F087DF539E8DEBDFCE19D71D -:1078F000A5C523B782F2693C1F0C3F62E6477F575C -:10790000A99370323F33713FF67FCA97C19EAB9700 -:1079100011D749EC87A14F5F64087C2FDE366F4D8D -:107920003EBEBF79DF07453DC22EBD069E185ED123 -:10793000D033DE960144D7223EFD9DFF7498F87443 -:1079400098F03689FA97F1FDDC2AC42FEAEDB2CE21 -:107950000FDF84B1AC5FB9965C6A23B9945F9A710A -:1079600068C69F196FBDD69E22B20F669CF54A89E4 -:10797000E76446BB34539C5F2CD67CB328DF45B705 -:10798000B646E5F508FB775A693DFC43D2DB6D123C -:10799000E787F5CFB43D4DF6A8F6B73F71933DFAB2 -:1079A0005069F5D0FBEAB63FE0F6915D52826E7AFF -:1079B000FEC390B04BE6F775EA7C34CE052EF8A5F1 -:1079C00087A26BEE437E9C477D26FD6D68FFEB9A98 -:1079D000FB28CFF039A294779E567A66111D772C3A -:1079E0007435367929BF4D5C77EDE33FF168BC7F94 -:1079F0001C2CD0F9C7F96AC336AB3782F336BC22E8 -:107A00007BE9350188F2FACCCF07C2EFDAC87EAB4A -:107A10001688164E1D781FC56823BD09B4AFFB58E4 -:107A200076532BE415203EC79D33D4E876D88CE3FB -:107A30005D99FABE888E5FE40FEFA706912EDA3FBC -:107A40008290B0C7CDBFD938F66DA4EFCCB617DDA4 -:107A50005259FCB9C26A96477FF8F65F392C83E326 -:107A6000B757C77B2C6E09F1735A87240E833A45AA -:107A70005B678DB8296FABDB62F506F1725D9B0C1D -:107A80000EF25F27ED1C37D4B57DC2F8AC937C5164 -:107A9000691C2FC32DC5C511CBDBDE9B45F676795E -:107AA0009E0C7351A56AF79C13E37D104DC1F1CB79 -:107AB00077BF3DEB87D447BC3B92C8AB2A7CC0263E -:107AC000F4C624AFF0DBB3281E6EFECD672C8F0FFB -:107AD000F74B90533CF0F99A2DEFD9C89F9C41C1C8 -:107AE00064A60B7E91DF0884E585B6B464F28B5CF6 -:107AF000FFBB4ABECFFB7F1793E37A3A6B1BCF786D -:107B00007FF2774847CD9B76EF5C7AEF9377BA01A7 -:107B100071F081D22870FF8B073CE4876BAC418FFA -:107B2000CAADB85EF3CBBB198FCB8EDFED11F98DEB -:107B30002F4FEC1705F3689D4B367F9BD7B914FC8C -:107B40008CC79A5FC8D5B44F734E81D9BB93E84DAB -:107B5000659688B7ECF083B1F789F300A0FCFC03CD -:107B60007DDF34F8B2CC719B1D6E4C9B17B7FF6460 -:107B7000CF12F62A08A13FD2B96A00DD2B9F831CE1 -:107B80003F378BE6B9AB5869A473225C7F50E79707 -:107B9000F415EF0B80A6C4C55955C7AFCEA17D31F2 -:107BA0003BF4DBFE5725C7D51AC53D71CF31DF3E0B -:107BB000D86A1F225D89AD27F9BEE9ED5986FEC35B -:107BC000CB1087A7C08E0F184F80FE3B2D57F41F98 -:107BD000237D5CE46A4C43BE7DFACABB363AD70AC1 -:107BE000E27A8611BDDDEF711FBCD91A8D37E60F21 -:107BF00074D863E781A4D7DBDE33E975E27DF4DF77 -:107C0000CCCF00A46994B77D608BCE227F1EC4F7D1 -:107C1000527DC1D20DF684F3C6185E4CE78BBA7E56 -:107C20001AFB9CCB4CF198D19AEDC29559897601FB -:107C30003667273D5F34E72175D6D0AF893F75277A -:107C4000ED9CBFD4B509FDC3803A3A0CF5E1A35DC4 -:107C5000875EBB05D7F151D89A3597DF96686F6B71 -:107C60009E42FDC5F132F23B85EDED671C4F19FEDA -:107C7000E823175E1C93446FF17A52BD7501DBB3A4 -:107C8000FF577676D92076F6BB5903E284347C0D13 -:107C9000FCE589E597537C61E6AF615FCD76F393B0 -:107CA0004C2DA9DD04DDCF1B7CACDD7996717B3ECC -:107CB0004F9C37356CFB2BFB31646BD48EB86D0851 -:107CC0007DCCFD07C88F71FFC07C696CB27527F24F -:107CD000D37CFF32922DE723D1EF139F658BDB2BF3 -:107CE000F6E7543ECF6F26BF49765A5381E40833F6 -:107CF000204C7187D4F9FC5FE97DE6BC223803464D -:107D000036F2B92EAC8BAFCF092B7A3D4530797D59 -:107D10004EB32D769E4BF7073BCF7D5FB7575E97EF -:107D2000CAE508D62C4D4E5657E2ADB224CD237E7F -:107D30009225CE774AB3C5BA8F650979B4C8D5FA0A -:107D400046A3C897680F95ED5FBA9BCF83AD7A7D48 -:107D500006CE9CCBE7074ECB27C812D8BDA17A8EA2 -:107D600042FBC315963B4BB1DFB5E1F6390AE2C7DA -:107D70003BD5B2A704FB2F6C582CFA575A2AAC08F3 -:107D8000FDC7834BE6CCA47D03CBDB3FA5F529AB38 -:107D900015A0FA91D296F7B87F97559C5F353CBBFA -:107DA000B786DEDF20A12090FF2DEE7023D731E4CF -:107DB00082BA9A368FB53D7EBABF260FF3799447C3 -:107DC00024CDFFDB2CF22B8E885B2BA1BCD2B7F12C -:107DD0007B785F79D94A3921AE53EC838FDE333516 -:107DE00097ECEEFF85F7FF5B56F6E0EF3FF3D4B577 -:107DF0000B68FC68195419E72B57B42AEADB31BF2A -:107E0000A6BCCD9043B922F85EE6B2713ED792EEA1 -:107E1000CB253C1D239C665F7ADBACD70FC94E8116 -:107E20000339CDD2B81BDB5774F9BFAAF383FE68C0 -:107E30005FA06F5FCE56AE5B816811C95796B7B62B -:107E4000113FA24D0A6CA5FDD77D8FB7113E5FB7DC -:107E50003978FFE8E6B4F5D62B90E47247D19D045B -:107E6000FE37A55D7753BB2FDBDF9325E68DD0BCB6 -:107E7000B77C5F16F3BA1A53C97F820FF54AECD369 -:107E800070FC0E7ED42BA2F920EAD5383205897514 -:107E90004E663AE4B45D4CC7CD7641C78250497313 -:107EA0000FD231CE1EBA8CF22B7C7F94E4700B86FD -:107EB0005B84E760217491DC5EBFEDCA2D627D8535 -:107EC000ACAFACFF7CFE7EE6499A2F80F3D3396AD3 -:107ED00040EAE1FE1EC5A1065561DF17C6EDBB3DB8 -:107EE0000BAD27CAC4FE7E33E51D53F5BCD8D87F41 -:107EF00033EA0D2676F9AB5C64B0E54E99ECCA39ED -:107F00008CD7C88E99F7DD269BECEFD48E8FD82EB8 -:107F10005FEC3CD099ADDBE37CC8A77584E93C906D -:107F2000025EDD4F7AE93C3089FEC79D0766660B2D -:107F3000397DED79E09DBABDD1A84E0ED7D18F1312 -:107F400093DCFA8F2E82F24AAE476884F4C1FD6A50 -:107F5000BBC9FE1B381FF38A7A3BD9B331AFC06D62 -:107F6000B4DEABF5F393FED3C0F580E37A1C5C1F5F -:107F700068EDB28642525C3DCA490BD7A3F4833701 -:107F8000C4F52B41BB1A647B3996EB4F5A4EEAE796 -:107F9000BD7A3D438560D93F5C0F61AE7F98E29E1C -:107FA000242FACE4F31990260DAC7F9822DF2A939E -:107FB0005D81A3429E17EA20E43299D6752E0240D5 -:107FC00029DA8457E2E48DFF9B981594B9FCE954B3 -:107FD000E2F529265C98E57F6DB61EDFE8F21FB456 -:107FE0008EE443B1AF360EC6721D89D55C47F2866A -:107FF000850B366375241521D2B7094D62DFF8620F -:10800000753CE63A1D731D4E9E3F914F0535572432 -:10801000DCBFACB13CA17FF9CA2909E38BD1A1C671 -:10802000F74B1F9A93307E58EB8D09FD119B6E49DB -:10803000183F2AB428E1FEE81DB549EB5E0C9C8C84 -:1080400009AF48B8BFD1F9E4BB84AF963C59A578D5 -:10805000FECA8EFB4C7531D31817538C7D785DFEAC -:10806000465D1D9581119FC7A3FC1F2BA6B8E9FE95 -:108070002A491B88036F24C87EFC1FC5C17A931D43 -:1080800030F4FF62FB373FD6FD849C5224519CE3C1 -:10809000C3B82A652AD5118B737B784BD4AB7C96F9 -:1080A000F2778E8B34C9ED856FD25B5589E2A07B68 -:1080B000AB348E83EE1D527480F60F7A7EE0F64A62 -:1080C000F903EB42CD75A0190EDF64E0AD11510745 -:1080D000D982869EEC7F708683E38C872D96DBAAFF -:1080E000E3E87F225BD89F27B245BEF5735B783704 -:1080F000D901C5016A539E789E8A1F802A7B502E23 -:10810000EE4C10F561F0C6DA9985E43F7B466AE9EA -:10811000543F8BFD6FE06525C4FEE4966685F3BC95 -:10812000D5CE27D99F942BC29F8C9385DF403FD219 -:1081300041F6F14DE97EAB88B38256924F810382BE -:10814000EE72F6AF7C4E9C0E59D28A32AA4FBDE039 -:10815000B7B4AF104C876AA75A884FFD8B653E0FA6 -:108160007E8948427AFB6B46719D73FF85FA3F2DED -:108170008DF2EBFEC58F9EBDBB32A697276DC9F36E -:10818000BC8BEDBBD56C793495CE514E8E8484FA80 -:108190008C37B3457EF866B62CEA0C42EF79884DF1 -:1081A0007D4BBE184E4407A4EE352E1CF2E0A61FF0 -:1081B00054935C6CEDF382B4AF69ECE35FC8033BAE -:1081C000A773FDB6912FDDFCBAD8D7BBF98BC47D60 -:1081D000EB8FB2C5B9C047F43E6CCBBBFCE3496E34 -:1081E000379042F0BEB27F3CC507D52A68E4F71746 -:1081F000F817DE7D14FBF3D64B1CEFD37D1A7F23DB -:10820000CA90EE9F00EFAB7B91BECFB3053DF3A1CB -:10821000DA4A74BEF6FDFA54C2D3EBE9627C54022A -:108220006D6BDC7C37E8F3BDFEFDE57B294FA7F7DE -:10823000D1FB891E7AFF3C154AA8FF1AF8CFBE5A17 -:108240003CF0BD3781CFAAD77B59C94F9642A8EDE4 -:1082500069B2AB472CDEB5C06D2493FD929DFD52F3 -:108260005F53F4C97B90CE3FD5FE75AF847CFDE3B0 -:10827000C2E8AF9FC6EBDFDD248386B8F838C32F92 -:108280007BE2EAB44F2EFE2495F889F1CAF69F925C -:10829000DEEDB47BA9AEE3CDDA9DC3E3E3FA54CFC0 -:1082A00074073D07932EED3CADEA89C98CBF15DB01 -:1082B00005FE56FC66440EE16C45EA05DC89FEF6D7 -:1082C000523E279D2041D2FC783FE24D1BC17535BF -:1082D000A021CEF67F2EEACAF71CCDA820FA14F012 -:1082E0005F16BF9E3D2FDD329AEB79DFC8BA243A84 -:1082F000496783687F6F665389F181AE270B3A33F4 -:108300002BF478729487E2B9DFFFE6EC7F105FF61A -:10831000EDDCFE43D6914BE3C3C03A5A7527DB2709 -:10832000230FA3BA57CAD30E59D84F5E2DDFCF798A -:1083300018D56970DE35A488C7A3C151ADC2BE8906 -:10834000EF24300E6EF672BD27EBEB4A55C42D4676 -:108350009E245BBCB98AF8C8E0C5A93C7F09D0FE61 -:10836000989B122BC35E611CE1962DBABD029F0340 -:10837000F3D3D1BA3D9BE5F15EDB22CE6B12E24F27 -:10838000EC57ED4A127756E33F8E3B37FB9B53D8B1 -:108390002F6D96CB28EEF03922E4C7CD71E7545803 -:1083A000CFFB0003E2CFE7FE7249F1E7F73CFF3D68 -:1083B000BFB3D4A3B1FD098F14762E1C19C2790E58 -:1083C000FE55907E0DA5BD003A07CD13AD4DEA1DBB -:1083D000E940FDACF594AF7B681AC265A8E00FF5E3 -:1083E00051A450AA7D72E82B8A03BB15965FFF73D8 -:1083F000577CED772495A887E4EC2387A770BD739D -:108400005F97D08FB60CEDDFA7529E8171E65624A0 -:108410003145E9B1A52759CFD3647F511FC21E91C1 -:1084200047393AC4B9A843F301D99714551D478970 -:10843000B9317EB147D8DDFAC36F16D9503E672DEA -:1084400047DD74BE52B7F729372E179A33FD0F90C8 -:10845000FE2C3FF9F20495EBDCB61451FE1D8EBCE8 -:108460003C83E3B3D9C8DA7183AF27B0A9823E4217 -:1084700080864D99DC8EA27D15BC14888875F676B1 -:10848000346724DB1F08FCDB5B0769BD3B8FA570ED -:10849000DCB233BB9BF520380F603BF2FB89CF4742 -:1084A000F37C0830A6E38A6A4D227FFF0B7D3D3BBB -:1084B000F5FCB2F77399C719F38EE9982EAB88AB28 -:1084C000B248EB41AEE3EAB46B24DF946D20F8D3FD -:1084D00099C2756181FDD788BC335D9C47B70D8912 -:1084E000FE91DE13DD67D7A84E35456D850C9CBF28 -:1084F000CD26FCEC2804FE53AED875E37D299D1BE8 -:10850000F92308C405D7E3A528ADF00D573CFF5368 -:1085100099DEFD1E11EFB40D89585CE4273057DA5F -:10852000CA74C5E8047EAF41E7288E8BDB6CD1F7B7 -:1085300069BF1DE9520917A340D0099D23348A570A -:10854000525471AE9EA26ADEA03490AEC05808614B -:1085500070000FAF860B7ACE758443627D07EA42C6 -:108560005B891EC70417AF9B392DAE4F866C52EC4A -:10857000F9139E65EB5A0A695DC20F2A4A98CFC764 -:10858000DD0B40A5F3EF14C5C77952CA7CD09A50D1 -:108590005E4E878FEF7B708EA6C9DC8F10FD2ADDC3 -:1085A000A77D9B34D53907E94EFB328D9F6BE8B62A -:1085B00072DD79DDDF6F4A2BC3F59DB11CBC6717F7 -:1085C000B61F2D0C0FA773DA0969FEB7C81E3F73DB -:1085D0006AD1BA3138FE2F6D56EF5CB24B3DC11FE8 -:1085E000D3B97DED13568DFCE2836FF447BE22F9BB -:1085F0003E2BB15DECB38AFBD8D79AF07E43E707F8 -:10860000363AD7BAA6E36D1BED7FAFCCF1BF4F7AF8 -:1086100030A9A3A98AF836195A9B699F13ED21D76F -:108620004B847385BDE87F65F8D6A6383EBB72F4EF -:108630007DEFA8FF72D29B4E5D3FF7537C84ED5EC9 -:108640003D4EDB7BE0BBA55ADCF969100EF27EE003 -:108650006A788EEB3A8DEB7D216536E168F46B8E9E -:10866000DB7C7138B3E5087DB7E9EFFB798EFF4B12 -:10867000D6DB03EFD8DCB8FEC09FC345E4AFC21819 -:10868000CF7D5D1D69C0A42F17EA8E4E03DB919D3F -:10869000AF7570FCBDF33E359DF41EE98734ECEFF9 -:1086A000C5F882F4686FB1D0BBA657CF8FA5FDE2A5 -:1086B000F3FB965F4EFCEAF5580D7CCF18427AB476 -:1086C0001BD88E197A58467A28D1F77B62BFA78CBF -:1086D000F04D7A67EB9EC37AB7D702A477886FC64E -:1086E0003BE25BA538A44C45BCF3F323588FDBBABF -:1086F0005FBE82EBD991BDC3C651DFC2F86A8BCC95 -:108700000949F87CA53572909EAFC4F7376931BD31 -:10871000AC9412EB7A167B449DAC611F7FA0EB6793 -:1087200078A496E6C5F14E594EC07F9C9F147DDD1E -:108730008FDEBBF127EB36A0BE94FA2A2C1328DE7D -:108740003926B31FD8AFC7C92BFE30E5865DE23AA4 -:10875000FBCF888E8B837ADCFCDCAA5CEE935FD047 -:10876000502EE3B1F55550BD7763156DC54D9ADDBB -:108770007A88DA29D5E12A3A2E9CB6A0FB90F8C671 -:10878000CD379AF0D67EF05BA3B94EFAA41DE83B34 -:10879000CEF6FF8CFEF1095CFF3DFB91DF90342E9D -:1087A00061BCA1C766FC0D86933EA9E7FAA968974C -:1087B000AFDBF8EB6B1574E80D04045CFF9C8DDBFC -:1087C000D605D1079EC8F15D9783F8FB22D77F5D60 -:1087D0000EF2ADEFF87F7AC89FEC7DE51D37F9E129 -:1087E000769B6F34E1AABD04F38824789C9263657C -:1087F000FF5A3948BD49638EC8B78607611DE1A598 -:10880000A15D5643E4A77DDDD793DF781F5949FB6F -:10881000DA4BA707DD942FD5EC3DC475FA463EBD73 -:1088200004F43FF9D659C4FF73B9223F5EBAC19A26 -:1088300090DF8E80888DCE91037E5763044552630E -:108840008A3BEEE8D8C2DF8DD46E4B7CAE8EE2144C -:108850008450DD45F2E3C61C7D9FA4144A294E4195 -:10886000DCF03E49F455D9BB15B8BEAA8BEAAB760D -:108870005A049F9C0E6849CB88C52B23F27C4BC8B9 -:10888000DE2D31FC875EAF146D93F87B8A513B443B -:10889000BE3CE5B4B685BF930AFAB84EAF86084031 -:1088A000BAA728415EFF94DC5208E2FA27A1792694 -:1088B0007D59DA2985989FFA772F0AFE13FB459B8D -:1088C00065FECE6FB30499C5346F94F953ABEF1FB7 -:1088D0002EDF91787E51B7E9F8610A95EAC3A6F3D5 -:1088E000209D3FE6F39DA7E83F929CEFFC24478F35 -:1088F000E78AA028E1BBBCAE4BFB2EEF238A075CC6 -:1089000074F8080971F91E1D470DFABAEB42B25806 -:10891000378A82EAA36FD76112002FF3A91E714232 -:108920003880F542DE463D632D54DBA88EACBEBDDB -:10893000E9309DBF2DD5E35A339E90A1CCAF657A27 -:10894000DD50CDE6C4FBB53A5F6A4D7C69F04B263D -:10895000FA44DC7DA9F4A1E5FA0EE1A0769795EB47 -:10896000B9CFC1AD5C7F55DFBE85E959AACB6F2079 -:10897000BD415ECF325C0FE9D3A5D26B96DF3103E8 -:10898000E757C01509F29B9D7949F22B057539AD62 -:10899000AFBF4BE4B5FD5D25BC2F61E0C5FCFC2CF1 -:1089A0003D8EBE66938837CF765439291EE83BAAA0 -:1089B0007825C47DC5B14FDDF4FD4DF93E19E89C25 -:1089C000B4AFB3625D10EDE59EAEA13769E807CAAA -:1089D0008F29EC372A8E9587528AA95FEE2CE53ACB -:1089E000132D93F2009C87FD70DFD1A127CA384E6A -:1089F0009F5949296AD3D17227C50B7B40EC6F4838 -:108A0000C72A337BE2FCCA7B3962BF614DEEBB0FE4 -:108A1000939DBA66B795F783AFB1465FA23C6C4FA2 -:108A200097E26DC27EDDB145AB5348DEBF91BC1409 -:108A3000761FEE5E9145E735F59D56D5CEF4DE7D89 -:108A400090EE077749DE61383EB0EFEAD16DB44F62 -:108A5000B4A5C24BEC35DE579EAE3D4AF5AE90E76D -:108A6000E4BCFD9ACBACEC5FCFE43BFF752EAEAB24 -:108A7000D6B76516D9E133BFDBC375157D6D12E43A -:108A80004AB48F7CE849AAF739F3F4711B9D075764 -:108A9000B51FE7BA8DC1FCC1D910E28EF3F6561BA3 -:108AA000E537F55B8C7E0F7F8F52ADC7510DDBDE56 -:108AB000E67E2DE50184C7CD7248C3FF3CB4EF19B3 -:108AC0003E1F6ED825EA3E2EDCDF26F17D03EF8BBC -:108AD00074BBB51C34C6FB7203EF7A7D9481F773C7 -:108AE0003097EBB496EF7A84F1BD44C7B7B96E0AFC -:108AF0002DB0AD2C4BE82BEDB799BFFFBB43C7F7AB -:108B00001D17C1F7A85C1DDFA36014E1FBFC7451C5 -:108B10004F77FEF81027CD7FFE08EFBE7E1DCED921 -:108B2000EF1ED5E382FE88C567BB3236AEB7E313CE -:108B3000FE0E3170B4DF467527B33A3F6679CCED4F -:108B40003C3093F87D1DF8EB887FD7753A558A83C2 -:108B5000E7F6087B36A7D3CEE713D741B885E4DC28 -:108B6000B7FFF1960CC2CDAF056E0C3BB74CE7EBEF -:108B7000B5653F9845F97BADEE0FFBBBEE9CC57626 -:108B8000671C1453BC3747FFCE7B4E58B7439B132B -:108B9000F94EE7D424B7864E3BD79B5C0B3D36F2AB -:108BA00067D7EAFED3EC27FBF29C2CE720FAAB61F7 -:108BB00038BE6E97A98E52E9617AFA3B6C7CDED59D -:108BC00060F2BFD372AD09F51783E1D32CAFDB722E -:108BD000757FA2CB6B6E54D431CC7945F6D2F94374 -:108BE00057647519C50B06DFCCF2EAD24AD3BEEE44 -:108BF000F7125ED2E37CA37F83FEFD5B586D75C5E3 -:108C0000E7EDCFE75AF473CED04F2B709D7749D064 -:108C10004D38C4FCE6867229697EB33217C73F5FC0 -:108C200078FBFA71F1F98D6FCB708AF71E44BB5255 -:108C300051C9F53BDD7C5EA8B4CEA573B0C02EABA8 -:108C400097F29A4087CCF14060973D64C179AF219B -:108C50001C215DD59DD2D58423CC1B5A72D13ECD2B -:108C6000A32D651C37AF03E3117C6EDECC8F197F1B -:108C700047868A75F72B5A4EB23CC2C81F1A3E1758 -:108C8000F1AA71BD01ED008D6FD0BF4B6B3FF8D7DE -:108C9000A2E2543AB7FDAC6821C5A9B9227F31E2FE -:108CA000D528C6AB257ABC4275174B85E860E973B9 -:108CB000F7D9C87E1DA61FB6A0FA49D5BF86F261B6 -:108CC000D50F8D3FA240436A613D6A209D221CEE74 -:108CD00095C4FECDB356AA0D81A69787705D60EF4F -:108CE0006BE21CCAACEFBD8BBAD95E9C5FE86A240C -:108CF000BC2D2FDBB206230C18BDFF75B637A37F42 -:108D000067532D6A6C5D4DF4DD1DE7692D09F17225 -:108D10006F47B38DF7A1E3BF1B2E19181FD55F64F2 -:108D20001FEB79935D41FA39DEED3B22ABB42F8422 -:108D30007CFC657E3CBFF478A8FD600AFBAFBEE317 -:108D4000AE10C5FD7FD1F17846DF976F9A24333F8F -:108D50002C93453B7AFF3325245F92871FEDFDCE90 -:108D6000FDCF5CE1E37DF490A823DE9158875D1F81 -:108D70004EACB336F81AD0F98A740DA7EF950DBA38 -:108D8000F62A3D6E6F123D92A4832C2F8B9498E7A8 -:108D9000069E95ABE3EB48713DB791DD3B69E88BEF -:108DA00012F5901F7E2B5763DC34750AF95AF68949 -:108DB00016DFFF1DB15F63E5F70FB83F235847F794 -:108DC000CF173BB9BE013E0FCEA5FE3D25E2F7030E -:108DD000EE79B97644FC3E1D48221F0F58A35CEF84 -:108DE00017386E61FA02C7FB3D435D6417B7CCA428 -:108DF0003ADA6B757B71B8C45943380FD27B736212 -:108E0000F32CC915E71B40EBCD8D7D5F69AC773541 -:108E1000DCC87C58ADE3EA3FF4BC1EF3A8F3B949C3 -:108E2000F2A8C1E2DF0B74EBF1D3F9E9DA89EF21A3 -:108E30000ECA8F2841CAD7F7BC911222FFDFB46F48 -:108E4000D99F281F0EBC69078A43EED9BF6C04D78F -:108E5000E1FBFD57923D39BFFF8E2BB98E5112DFDA -:108E6000970689BE5C8AA75EF5509C54BFEF55AE4D -:108E700073ACDF3BFE518A9F305EBA96AE631CC373 -:108E8000F82B3F56C9F8DB73B432B3940807AF939D -:108E9000E6AD3FA270DD63FD91CA17E7525C736CCB -:108EA00006C74F46BC5441F938C54F478626C44FC4 -:108EB000A979827F7D075278FF438212811F189A19 -:108EC000809FBAF63F709C5187F62E1E47C673C529 -:108ED000790ACF332C4FC74F58F2313E768BB6AE5E -:108EE000630FAF6FB935CCF26EDA6515F7DB446B03 -:108EF000D44907212348FC78912EA11CE6D842854D -:108F0000946FBE502CF20DB33C9EC813E7852F9C86 -:108F100014DF19BF30DD3F22D9F7C6419821F27026 -:108F200049E777BB7576B2EF7977E489FD09772653 -:108F3000249C4B1AEDA379425FE6D8C43E95F9BE56 -:108F40003FCFF03FB08ECE634ECCB5AAC6EFB7E4AC -:108F5000A1DDBD1E8C3FEFABF3B3E89C4BE4D50025 -:108F60003D33C91E7E9BF6F929FE9A24FCBAB1CF87 -:108F70003F6F333C20F6F96FB5925D30EA4BE6F96E -:108F8000CCF157F5D534CF8DE8DF699E9B6627DE9F -:108F9000FFF645E2AE0579BA1F1F0EC3455EE172CA -:108FA000923F38D76555655E476868B2EF0B0DFB99 -:108FB000737895383FEA42BB486DD3A8D779DFEA8A -:108FC0008503279F4C67BB9A0225C8E2ABBEFC9382 -:108FD00027D93C4D17F4757E02FE0C799DA53CA067 -:108FE0006CA0BCEECCB3E8DF259DB1F1F926343E90 -:108FF000649107FF2EA969D4672DA44F67F5EF5E32 -:1090000090BE227B9CDD3F9BF731DFBF6706448328 -:1090100078FFC0283BFBBFFA99129F1FD447843FBB -:10902000AC9F2FFCE1F0F6792C97EFA05C7C5E36CC -:1090300013AF515DAE21EFABBEEC9B69E493748E30 -:10904000D34438673B9DC56D7DFBDB2D7C5E897EFF -:1090500097E2C21B2625CA6D04F81FC8C6FB37CF8E -:1090600096BCE84106C8FDE65BE7B1DC6FD2BF8F76 -:10907000B998DC7F9BE7FF691EE97D77FF77C62003 -:109080008B5E18F54111F9D7864170BD55E72F0C5D -:109090008D3E4DE765DE0BE7E97F7F3AFE3CBDC4C0 -:1090A000E3DF924776D5F2A5FB0AA0F97A7EB942B2 -:1090B000223901EBC5607AB5439F7F479E2ADE9334 -:1090C00025CE8746E9FD17ACA142FE9EA2ECD2CE8A -:1090D000019B9E7D7E2CD9B9DE0347C6DAE2E47A95 -:1090E0006605DA07F237FB0EF1F78731DC5974DCDD -:1090F00029DC4AD28DBA1F4DC4E119C221D9E7DD5E -:1091000087AEA7FCF16CFB4D599216E767F79E708E -:109110000F8B9BF7ACFEBB1898B70DFF766A3C9D92 -:109120000F309D67C3623ED4FFE1378D89BFDF6C8E -:109130007C67C7787E7064239FD31B785640E0D944 -:10914000F83D8C0BDF55DA80BF7B0CEEB7737D45A5 -:109150009F355A941EA72F1F1A7244981566312BFB -:10916000B9DE75226CA8E273024CDED74DA6CFEFB4 -:10917000C2B2A80F6DE4BAC5698DE025DC4AB0998A -:10918000FB13668BF3F229D02D135DDF8428B73EE5 -:1091900050156A67508519B6931C6199C2ADB6F631 -:1091A000834EC257C4A3A4BFEF10A5A7C9E4175BA1 -:1091B000BF02EF1B78C5C1180425FD4E3F2B5FD8B9 -:1091C0007FAF53E863F4ACF8DD936F400FD33F55A6 -:1091D000E9667A53352D83CE4B763FB742A6FA9790 -:1091E000FDA04549CFBC998DBCFF169D0EE1ADE9B0 -:1091F000B1F54EA2F5AAB1FE940560A1F54AB04BB7 -:10920000ACBF1132E87C6C3244F83D5711C1B8DE76 -:10921000E9A029D4B7E517EB7C16F95B959EBF59F9 -:109220001C41AEFB49CD17B8762A2139AF92B7B6AB -:10923000C38FD0F94CA958E744BCCEE7388D82EEF5 -:109240000BFE3A5FD8BB29106639430DA82FF28F69 -:109250002BCC54895F52C463A1DF13BB54BEF67993 -:1092600080E977DF1EEDFD6165ECDCCBDB99C3F5B2 -:10927000D0EB254B5426BA1C85A21E3A0261FE2E65 -:109280003392F87B67C5F9375E9E4F7ECF2FBEC302 -:1092900035D775EE086DE5BA9B0541640FCD5308CF -:1092A00070DA13AB03B09684F8BE95CED955AE33C1 -:1092B000ADA07C715FB6FFF2FC6CAE371DC6932982 -:1092C000A1F1D5A931BC2365FCFB3B4E486D257B44 -:1092D000D4ACD7D30655B75ECF54C4EBD0D0CEF3C1 -:1092E0008F4828A2AEFBDE2A517F7AEF90FD5CE723 -:1092F000DB23812A15D0F9FF7EAE03A61F86B316A5 -:109300007CCDF97F96FEBB0F25FE372696EA461EDA -:109310009F6B3E95CAF5AFCA0C9F4675BCE67AF1C5 -:10932000D296F10FF5705E6AD06BAA1357BC7CFF22 -:109330005EDDBE363BC4EF0049ABEDAA348DBE7F87 -:109340005FC1BF63D54CA141257DF7BE829FA73A7F -:10935000662A02ED4DF3DF44FC32FF2E15C2ABFF4F -:10936000059A376D38EFF72593C734431E968175FC -:109370005228875B49BE46DDAD516F4B80A0753BDF -:109380007DE277F054C409FFEE1F42C94EB8F4994C -:109390007FCF43D4FFB6E8FC47BA7670DDA7437CA5 -:1093A000A76D7CCF6BE69B81DFFF02B9D77EA25011 -:1093B00053000000000000001F8B080000000000A8 -:1093C000000B9B22C3C0F0A31E81F9A551F9E8F858 -:1093D000049A3C0B0303C34F205ECC835F1F2E1CFB -:1093E000CB8260BB883330E88A3230E801F1142048 -:1093F0009E0AC49F81585B8C814107887381EC3C35 -:10940000207607626BA0DA2F1C0C0CDDC20C0CD38B -:109410008078A130AAB92F1821B41217038329101C -:10942000333263B77FAA1A03C3011D043F5D9781DE -:1094300061AB3E797E19C5430F6F7344E51FB5429A -:10944000E57FB06160B07742F08F5991667E35500C -:109450006F8D136EF9A36EA8FCBD1EA87C0B34F9AA -:109460001D61101A00FB3B7C21B8030000000000C6 -:1094700000000000000000001F8B0800000000003A -:10948000000BED7D7D7C1CC59560F5C7F4F47CAACE -:10949000471ED9235B323DD2D8964186B62DDB32AA -:1094A000B6714B06472424194CE20802B9C136AC08 -:1094B000B3E1B809770B0EC1D1E8FBC3B219192F7C -:1094C000311C81417CC4102E281F9775127219031C -:1094D000C9CF9BCB651D4238270739A1F8D87C6ED0 -:1094E00074EC19CF5D08DE7AAFAAA5E9D67CD986DF -:1094F0004DFE38F9472AD5FDAAEABD57AF5EBDF744 -:10950000EA758D22BA48EC2242CEC2DF6642DE7294 -:109510001142D6CC96A976234B5A68F934317AE9B0 -:10952000A34BB46CBB40CB15FE4951D009B92C9C60 -:109530002644242436F1301129DC509D4246A28471 -:1095400078F46D55C43FDBAFB3ECED2224BBACF82F -:109550007BE9F9E1881EA0FD3DB5B6D3A4FD0C7DE5 -:10956000A5B5D36C9E7D5F0B8352FC1A08C5A686F9 -:1095700090FEFAFB89182664908EBD8CFEA7DE93C0 -:109580002071DA4EC90E137D05C085105EFDFA0903 -:10959000F166FA7CD0453A2768A91E4D657D14EF27 -:1095A0004B9FD35649941E8F6C8ABFA5754F44CCF0 -:1095B000A4808EC841ECF734A50B867AAFE8590D2C -:1095C000F4503A365648CFC662F43C974A013D976C -:1095D0001DD557E6D3A3D6317AD4BA1E9CA7D31192 -:1095E0004A4FF442E8F90CD233C8E91974D0F34178 -:1095F0004ECF768B9EDA01A467A09ED2431FB9EFAF -:109600004991388557819E00C0D9E919007A9A0B93 -:10961000D0A3FE79E8F92B2E6F49A0674D797A9295 -:10962000404F4D05F4F8D344A3CF3D4430279AE78B -:10963000E2E5E17C5CF1F5742445FB1DFE9384F3C7 -:109640004C576464DB8A59B8498ED7F7A203914915 -:1096500090AF25F74708ED6FB85E407867BF0F10F1 -:1096600005E1B53AB31BFABFF888BDFFE17A86AFD2 -:1096700005FF7B3E8FBF2712B65BE08F0F437D78DF -:10968000C9374802C671A5231AB48BB276FD4BD6F2 -:10969000764EFA0BB567F40CEF4DA13CABD9CF2059 -:1096A000BFFEA63E4D745AF71C4910E0BF1261F888 -:1096B00058ED295E845C0E64DF699A0C3F4216D235 -:1096C000794ADD994DD1F162E9DBD538E5C7706D96 -:1096D0008F0A740FE9073B416F9D8E29448A025E11 -:1096E00085F960C9C56632AA36D0F9EC7D59324693 -:1096F000C85CB8140857CD6C5DF68B24DB44F0EFE2 -:109700002C017A1238FFFD4BEE47BA15A06B05D03D -:1097100095243A7DFE2D2E3FEEAFA708C895AAA747 -:1097200022A91573C71902FE3743AFE9C8B63CFA40 -:109730007F6ECD2F9D57C7FC225F1E206636057CAD -:10974000F1D8E7CD2AFF9EF3FDB2BA14F2B7DCF8E8 -:1097500073E967E3FF1DD1B11FA2A623F1C02C3E20 -:10976000C3AEC91E906BBA268D2728C8A5749CB6B7 -:109770003C7E3BC79BA1534EDBE4F81B9C4FC39E32 -:10978000E9E7F3FB73E2F35D0EF75DA26169D17562 -:10979000E951364EB9FE7F022CAE0178C7BA92531A -:1097A00036BEDFCDE12F7BCE0E578C3F9F9DE14F24 -:1097B0002A02F268AD47F833E713C24506FFFC6B97 -:1097C00009590EFF8736F9C3CD9377C2D27A259C0B -:1097D000380DED6F23898BBC8D74BDB8125F847218 -:1097E000AB6CBE85FD12BFF6C6255CEE24D4036CBF -:1097F0003CDA3DA1FD07787FB2D041089567772B11 -:10980000C98C50D4AE925ECD0A949F070931166878 -:1098100079FBFA14DBD7D76B992DB09F6F90292174 -:1098200074BC2AA279A004F82C850BAEF11B742419 -:10983000E2261FAF8A17901B4F0B4979AAE8F8ADB3 -:109840008A6D5D78CC0401BD108890AC2748F58DF9 -:10985000100823FEEBC83A86BF2E407FD5B2DE2D1E -:10986000D371A498688CD3A7551BC9FA1D7972A827 -:109870000B4C7EBB63A208740D50FDEFA64B325813 -:109880004FD73BAC8708B5370AC8ED8C7ECF49244B -:109890003B8FF69B13487635ADFBC9FA046D97767E -:1098A00093F5A7705C628C1790B3ED029B5721363D -:1098B0007DF62CDA0524F33EB40BD2B88E9558DA37 -:1098C000847D403583861BA6FDED7B995E938909D7 -:1098D00072128AA5B355F05E5F1A057C17C492E434 -:1098E000F566564EE5E1ABFA5311B49FA24B859E47 -:1098F000BC7DEC18959FA93C791BDACBEC80FEE887 -:1099000000D7339F44FD69BDFF04E79332499101BD -:10991000BA7425D320CC95EB21A1B09ED8C9E98596 -:10992000BF2BD7DAE5559ECFE5950EE19609CAD74C -:10993000E0532403F8524E3E7F33AD5FF2A24A4615 -:10994000A87C35931322C8CFA5641A4B8368129460 -:10995000AB8881650B8963F987362AF7B4BCCDA43F -:10996000F2DE80F2FF51818EFFFBFAC4B2207DEE61 -:1099700089A52E87FD85CAFF76784EE5440079AA31 -:109980003649C1FD3224B0F53A266B1E801B3309DF -:10999000EAC743426F0AF689216E270D79886D1D4B -:1099A0001FE0740FF132144B9049985F3A2FA0D703 -:1099B0008F456FC575EC96597D80CE0BCADD26B6F6 -:1099C0008F39F150615E569CFF3C6CFFF3CFC38032 -:1099D0005053701E06611EB60B4C7F2ABF62E39780 -:1099E000A00FF7E99DDD8F22FF9553E7066FD1BFEA -:1099F000D6A137D7713DB7814C2F96A91EB9DD9DF1 -:109A0000556401F1FE02E0FDD6CF4E7C02E82193C1 -:109A10008965B04F51BC1F16504F26C9093ABEFC8C -:109A2000B294013F45F45DA3264AF82944A3FA4CB9 -:109A3000E5FAAC01FEB74E7BC33757FF2E9DF8AB5E -:109A400093686F10353102FA69535205B9E8ADDBFE -:109A5000A6821C0DD6D13AC84D445185CB68E92762 -:109A60001D207F96FD3110D931140D83DD63AC8547 -:109A70006EADF1B7441244C0E78979EEA8FDF92F25 -:109A800061FD6B898844E95332EF5381CE7E6D9B33 -:109A90009AEF7729FE4444A1723808E3C1F8AEE496 -:109AA000F1680BE84FB2BA07F4B99624AB41BE2374 -:109AB000ED88E796BAB80AEFDD9155C4AD038BE3A4 -:109AC00068570D84EDFEDC60DD1DE456844F92374F -:109AD000FC73ED6BB73F4994BC7D02C691F2E6D9A9 -:109AE0002D27B340971429AC77FF07977F518FE359 -:109AF0007E43D29F37552AF72E2E03AE08F9997070 -:109B000069DE3C85F3F61D3A4F031EA3B3D0BAA419 -:109B10003B88BD5F4320EADACAFB9DDD6FF9BCA735 -:109B2000D70D4DE2BC07D230EFBD54EFE3BEFA6A69 -:109B300020F30425A17B53F21178EF4AC9A4278CA6 -:109B4000DD34C13E779774B101F27700F846378E65 -:109B5000D12E15CB912E0DCBA1AE08969FF77DEEA1 -:109B60008B93B4DD9E945B73831CA4EF7A16FAA3E7 -:109B70005E777C04FA0DD3FEA15F59D59ED0A0CEAE -:109B8000F61D578C95378A8C8F55A217F16D119958 -:109B90001DAE1313E525AD95F6D3AB5AED766EC029 -:109BA000F0CEAE07FA9FAFA9DA56F7E80B6DF0CE0C -:109BB000F5F26391E90D971C2746339485F5F85922 -:109BC000414238495A390DF687BC4041BBA05FB0CD -:109BD000EBED8745B6DF3D26AA4867844CBF7096FB -:109BE000F2C3A58968F704430D1359E04F8D622C29 -:109BF000A145D035A95517188F84E5DF4DE6ADF3A3 -:109C0000A7043326FE05F0690EFDDDED36B9DE272B -:109C1000B2FDEE2C5F2F92DBEC043D13A1624850A5 -:109C20003EF447810FA26FA3D144F9D01F5274F0C4 -:109C300087FABAC582FB8E930F52D58D11D08F4E05 -:109C4000BE7F97CBD1339CEF9BDFFE30EA89FD9A34 -:109C5000D891F103DF4E74809EEF6B114590F3BFF6 -:109C600018FE39E8D833C3BF193A906F7D61663763 -:109C70008F6A547E603D8799FCE824DB81EF0D4AB2 -:109C80009730972E27FFDE6BFA2CBE5785C478A637 -:109C900019F09B8E237E1BE582F8FD6BF1DDC2CBB4 -:109CA0003F835796E165FC65E0F594901887F57D54 -:109CB00080CBEB01795205BD10B3E4C6C7D6D15CA9 -:109CC000BD24D8E49DF6F325E8E75EE887C2DF2BE4 -:109CD0004FDBFAB1E002C007B62EE26C5DC87FD65A -:109CE0007561E135C2F1D64986C9755361B97EAF58 -:109CF000F1B2F6D31EDF1504F44DC81F47FB7B817C -:109D00003F9E057EF5D6283AD83FD451C2FD1A9B16 -:109D1000EA797E52CDF608C0F707B6A35DDEEF8A7A -:109D2000A39D7EBCE61BE6CD94AEDEB7AB88DBA080 -:109D3000FE80EF8AE33AE8C5E312FA6BBD6F372E77 -:109D4000481698671FC4C728FE5EC00FED6A65C637 -:109D500008077C7BFD54F1D17EDE6C2619D0A72E3E -:109D6000BF1901BBBB77856AF420549C007F7B7CC4 -:109D70009F684D34CF6DEFF30F7C5ABA74761CFA9E -:109D8000279C05DB97EEE1E0C7237D82ED7D413C1A -:109D9000CAD55DB3750DFBA7755D85AE05F36CE3A4 -:109DA0002CDF292D4D32EC9BC46BC0FCC7E21D3D5E -:109DB0007F043EFDBD847AD0C99FBF93125E69CDFA -:109DC0006CDD154EE0BC59FD5D5D23A31E95EB488F -:109DD000C62DC0A8F10EB06F7BEB448CAFC9FE6DF1 -:109DE0005525EDEEBACAEC6EC2E31E963CB4FD8A70 -:109DF0008DEB3598FE0E90490271952AC2E21A2128 -:109E0000A20B04DB1B421C83251B319E12F6BCDB1C -:109E1000FDDE88FD0AE61839EB3B877E65DA6FE3E5 -:109E20007BD06F197C3DE421EC97AA87F0D979B3F8 -:109E3000FDBA22497C48DE3E7B565A4B5813FC4BF8 -:109E4000A07CCBA281EB932C0C1A4FD0A23F7C8735 -:109E5000CD9FFA88D4608B9B2ADAC0A785202DEB92 -:109E60006E3327F3F483737E3B6120F02FEB7699FA -:109E70009315E80D30BB0BC5A5069444A61BF6EF61 -:109E8000C57E8C2312398971E141A17A15D8CF168C -:109E90009C5CA76401AF408B99027D31384F34241C -:109EA00003FA1D3D01FE0091AE311225E24B729D79 -:109EB000FC9B7C7AFEAD1408239E3CCED55B46DE2F -:109EC00007BA4A9F4F288A9128E4CFA42466BF2866 -:109ED000DEC2EFAF54DAF74A6BE6F22D0DBCA3CF2A -:109EE0000743D4E5BE8C890FC8815CF7FD93C0871A -:109EF00081DAAD9152F4128DDA39797E91A19823ED -:109F000052693C0E14C283F8A9F0AC2F310E9F5F4A -:109F1000ED4A83C53B4029C2791CB7CF28DE416199 -:109F20003ED3D3F0B7BF653C0B7134D7CD7E13E67B -:109F30004F328F1089C2FFA85622422BD4BDAF8B5F -:109F4000389F1B0DD4574DCCBF33E93FA023B851E8 -:109F5000B1ED5BA03F67F6AD28C8BFBDFEB4648F0E -:109F600067F6761D25BF5C328B3F7D64168A17CB62 -:109F70004AFB44617E5457C48F43545E08959783CF -:109F8000D46FA44C2169EA3742FD00F51B09FA930E -:109F90003A967D5D4D58EE83A6EBE1FC2C39148D8D -:109FA00042BCF4F1C82D14E410E80E3C57F1B6435E -:109FB000FC7CC4AAD32702D4F939CB0F7BFFD80687 -:109FC000F198110FAB1332DD66DAEA520FC4FB478A -:109FD00002ACFD2F257F3B9C471CE2E7484436D569 -:109FE0008FE6F9FF39C98574800DC4DAFFBE1BFA0C -:109FF000F3C8BC9EAA477C66EA948F808F4765F5BC -:10A00000BABEC5D83FAA003A5EACEF2236DE126671 -:10A01000DF93E66D65F8D883F27F3D1CC201CDCD9C -:10A02000D570A84C14C320B0DD1C0A71BC2BEC8782 -:10A03000C809B6DFF1B852F17553665FE378949BB7 -:10A040007F027E29C42FA81E4EC1B83F2DBC4FBF32 -:10A05000DBE31E729D1B5F94D6E9944C59FCB7520A -:10A060004293693D604E64A3B41EBC269BC2E55B6F -:10A07000E1B8BF93341E0F4DE0FAB7F82C6BCCEE6D -:10A08000B8D2318FAEB089E7921E3F5B7F95E2BBBD -:10A090001EC6C9EB873CD35E1B0F146F571317679F -:10A0A000ED2DFADFBC0EEFACBD46FF0B99D5B67AAD -:10A0B00055EB421B7CC068B0BD776917DBDE9FEFB4 -:10A0C0003C5DEAA0A3D1E21FAF479C74562C77B247 -:10A0D000CEF7B914B31F67EA7C3F2E577F7B99BD3B -:10A0E000CEFA75931BAA987DC3EC987F43388C13E6 -:10A0F0000F234FFF4A00C7EABA2810CBBECD36CD9A -:10A10000EDBF57FD1CC6E1CC5E9978AE981BA74BFE -:10A11000B52731CE96EA716BBD618CBB619C6D0F2A -:10A1200035E4DDB4BCCD95D80DF27BC6B33843829F -:10A13000D06F721DC4AD7B1DF104A73CC51EBABE15 -:10A14000E07999550E75B1F89F5557EB0AE701DC98 -:10A150002DB3F3FAEFBB1277031EA01B09C66909E2 -:10A16000AE0397CEF6C763D1ADE4D7E8FFB3F331C2 -:10A1700085A44E36527AD2D45F1BD1816EB64E86FC -:10A18000A25BD5187D3E1612B94D378DF653BA6DC8 -:10A190007E2DACA72A791ACFEDAA6285F1B95716A0 -:10A1A000F9BCDD54923EE77CDC048156DA6EAC5E8D -:10A1B0001091FFF562E6098847D589B8AEF79BCACA -:10A1C000A370D4BEBFA5FA7A8CA79B8A28211D59FB -:10A1D000B5D03AECE776532F8F9F1EA8637EEBB184 -:10A1E000B6375438AF3960B4633E809CFE11B61F59 -:10A1F000E4FC4EAF9CC238F96091F3971E99F9F9CF -:10A20000BD016F67A6E0FB20BE4F47DB9E7F00E8E5 -:10A21000A0FAF709F4CF48ED2E4A87666AAB80DFD3 -:10A2200063F5A6F86B90AB4D22CA5910E272129CEE -:10A230008BDAFDE7B14D229EB3A635BF01F6FB696F -:10A24000F34D821B91ACD5C2F962D5AB1B34DC2B2C -:10A25000A9BD539B67E7576D4CAE83F9B2E8729383 -:10A260006B0BCE87B0784F02F879D72AA2833FE6EE -:10A270005EDC91FD02EDF7CC7AB706AAE0CAC09584 -:10A28000D9EF803CD16D05FC6477D8CC82DDE4E960 -:10A29000F4119DBE0F4626D08E52231231C1AEFA64 -:10A2A000BF12CE17D51948977C68FD89CDB4BDB2D1 -:10A2B000495C80765933DB6F34FA0FF61B3566B78D -:10A2C000AB245716FBBB77F2513C57561C76954C86 -:10A2D000F2E0C1EEDAB4EDC38D05F481554A934145 -:10A2E0003CD725D28D25ED6CFFAB9FFC8717F3F88B -:10A2F0003E253BEC746EBF59FD14B3DFCE74EDFE0A -:10A300008717A92C275C2C0E2A2BE66F605D4EF177 -:10A31000F3C53147DE4DC2C5D6CB19BE8E6166C1CD -:10A32000DF06FF18F8D577D576E66711C3E6C7D004 -:10A33000F57E46CEF3B3ADFD2E6D96F62766F35A45 -:10A34000FC9E5889BC966BE584EC2A91D762ADD708 -:10A35000E14D2689D0F91D0D914C0FCCEF6693ECA1 -:10A3600004791588D1A331F869EB1C250A72781598 -:10A37000D905EB57970D3887EC6FFC1075148BE3FC -:10A380002B87EDF2516E1EF738E67191CB6E87BBCD -:10A3900048BC2A1B853846E47AC0637F5831603D4B -:10A3A000BAC41B77EFD0E7CE2359C7F4862B9C2580 -:10A3B00085C6B5F879BBCB5CE68238BB629C4C8025 -:10A3C000FCB72BE8F73AE16F72F13C962891C13E59 -:10A3D0004BC13A81F5DB61B2BC31414B3E6820FA9A -:10A3E00071DBB956EC2DCC677B4822C9791B09B9C2 -:10A3F000CE15657AA66D3BB37B3E40042904F00977 -:10A40000DCBF6A4D4DA07D9361CB2ED36E8E5C9BDD -:10A41000A727AFE3F239FB3E11F9A8EDBD8BE11997 -:10A42000E076B3B63372ED8A02ED4385F5E407B802 -:10A430005C5FE7E2F6446A27E605F5EB37C681CFB5 -:10A440007D9B4D6317682D9011C847F1139B7D4C80 -:10A45000E5FB3AE0A7153F92B53896963D506CFE65 -:10A460009D76802B62CF3BA9F4DC3676E8FA92E346 -:10A4700038F7672BBF0D345F3E9F5C9C0FCD7CBDD2 -:10A48000CCDA4B69BEDE0DCC079214330171494919 -:10A4900020367B6B8CCB8BE465EF9D7850FFF94EBB -:10A4A00058A752D044FF9AF85B98DD261BFAB505F1 -:10A4B000F0B7CE391FE379BCB1F48770FF1B0DB53F -:10A4C000E3BED7A795D61FD6BEBA995CA342DCAE31 -:10A4D000BFB8FE18CDD71F4A58B4AF63EEDF53FAAA -:10A4E000F5427CB6F814E1F1D2DEC0F648C9B8A056 -:10A4F000E37CC550CC07902FC5F9F685F3E1DB2846 -:10A50000CFABDBDBFFD2F33C0FC1AEAF5716D5D7D5 -:10A51000FFC9A64FB9BE7E0FF9FFDCBBC1FF4AE3FE -:10A52000309E3D927E6A1E55F1720AE919D60FA639 -:10A53000301E03EB1BEC80741BE62B901841BD080A -:10A540000D41DF797413F9E6E57126A5CEBECF483B -:10A5500061AFAD1EE94C11C857837E816ECF1E05D9 -:10A56000C7B5F84D6D16CC27B3EC4B584EE08F14A1 -:10A57000CB4FB34A2B7E03C73867719FFAEC71E06B -:10A58000EF693FC1FDA138FDF671221F8997D64FB3 -:10A590000E78E297F5370A9C0BCE6D279337F2F4CD -:10A5A000DAFF71E813F3C8CD9DA847896840FCB273 -:10A5B00037B29D2428DE0384E9932128D7433EC97E -:10A5C0002A0DFCDFEFBB74D65E67FE9DA8F238BD96 -:10A5D0005E99BF7717DD870AD93F4B15661F9FF934 -:10A5E0005CF20F9097901A1174D8DF4E75E5D07E0B -:10A5F000DA915DAE405EDA72653EC2ED381455B652 -:10A60000E4ADCF1D849DFB5344947C3D6AAD3F2552 -:10A61000ED7E1EE89C4AB3B8C654FA9FF15C7FEA0F -:10A62000B09401A64E0D5D5772FD9CE27ADB823B31 -:10A63000755832A1BFD490905942DB9F92CD60C132 -:10A640003C009261E7C1BC7E4B5AB2C9E599BD0995 -:10A6500005F4CCA92E55F8259D9B5B814E8AFF8E73 -:10A660007454019FAC1C5DF314FB7C5A74F643BE1A -:10A670004274367FA73FFC26D27B9A3E974AC4930A -:10A6800046B89EE80F17D6275E7EFEEA75650AE794 -:10A690003D38E8F535D9D7A585DF20CFA718D418E0 -:10A6A0005E831111E761B0AEB41EEBE3F360C1F558 -:10A6B00047D8796BBF1C572BC1C7A5D9F129368E56 -:10A6C000BA71A203B6F92A92E8688F227B5F8238BA -:10A6D00002860E75F09F9E3A762BC4816FF69B42E0 -:10A6E000041E4E67BF43EB0BA8BF03F6A966668442 -:10A6F000C52D90D72911881B3F947C33FB1AF8A3F2 -:10A70000D4FF817A484F86DE077A289610605DED87 -:10A7100007E58F9D7FB0B7AD99AF3F5AFFD440FB9F -:10A72000168843CA24CEE319A20EF97AB8F4C5E21A -:10A730007A02B4E759F76CBBA2743AFC2237D956B7 -:10A74000DAFFDECDE053F41FE89D050E3F2BD46900 -:10A75000B7BBAB1CEFC7B8BC16F32BDFAD71E693EC -:10A7600097543897555B442D03F0241982FD3678B1 -:10A77000A34CC08E9FAF6BDD10E22BC7F77D84E545 -:10A78000B9C11711F9EBEF4985D9B18B6E7F5C80A8 -:10A79000FDE93478D92BA19E330AC9AFD3EE1BD281 -:10A7A000A7309E38404E7434823DBF4BC4F3A4FDA5 -:10A7B0002D0743F9EDBFC7C7999D7FA2CB6BF1541D -:10A7C00016FD79A5453461DF3ADFF977FAC9E5E688 -:10A7D000BF76B7DD2E3ED779F93120BEA6FCFC5FEF -:10A7E000E838D6BCCD5D1F4C6F2EBAFD458CE38C8E -:10A7F0001AA5F5CDDC797B09E72DD842CC42719CB6 -:10A8000057F83EE6CCEB53499218909FF832DB7F25 -:10A81000A4C6B591F112FA478A39FC0FDE4FEE1645 -:10A82000424EC07E2BEB65BE879B3824D37DD3B7C9 -:10A8300067C3217935E4679998E735DC65E2F399D8 -:10A84000F9778B1C5F81886BB95ED1F1FCF3908C3A -:10A85000F68648CE421C846844B7E48E005CC7216B -:10A8600019E3313ACF23A0A0F3A11D41BDB4129248 -:10A870003D6BF09C1EFB818E581CA693D569439CB2 -:10A88000279769225E725ABD83F2739F87D7755EE0 -:10A890000FF1BAC6EB515E2707B1EE53681DE2F225 -:10A8A000AEB486752FAF4779BD9AD743BCDEC0EBF7 -:10A8B000C241ACEF53587F237286F5EFE5759DD703 -:10A8C000AB795DE3F5065E27E36C7C37ABC37E882E -:10A8D000751FAF47797D1EAF8778BD91D78571AC65 -:10A8E000179B3F6FCC44FECECE7F07E31B21DCDFFE -:10A8F0008C3BEA9DB3F079FE687F972EE49F1FBAE8 -:10A900008AC49F56B9999E996E8B639E12F5175211 -:10A9100053F9E78E91C2F26EF27633E7E6610A5799 -:10A92000307EDD5D705D548ADFD6F3C4EF23FF4ACD -:10A93000F8DDE0B6D63DF3CFA7DB0CC4D3D99FB387 -:10A940001DD85B24EF9CDE2B675210AFA13612FAA4 -:10A950003B2ED59ECF7A979B9D7376BB593E6B2F2E -:10A96000C76FBA8D9D3FF42FF166C685B971C6BF1A -:10A9700071B378C20F2C3CD509F47B7C39BA62D113 -:10A980000F627ED470ACBD4CFEBAFCFFF2FD656771 -:10A990001CE49FE11D1DC7EB2FCCA7BB66F4CD8D3A -:10A9A000A9290AAB7AE873F067B470A42E3F6F9AB6 -:10A9B000BF278228A17E799BC259F92212F6CFE2E5 -:10A9C000C5752C5E2C71781C27CABE633057C13EFA -:10A9D000439F37F17184B9FD3ADB65DDD56CBE3834 -:10A9E0003E567E8A449EC37E66F091E3C82FE7738D -:10A9F000C843D6FC17FEFC42EB2EBDC8786976FE34 -:10AA000052AEFD17B9BCCC91CF22F3FA1FDD969D53 -:10AA10003261423E902547967C9DAF1C5DB09CC044 -:10AA200086D4525C4E522489EB46069773E5B9CB27 -:10AA30004B0139C9E6C3D7A8217E9E6FA0BC507CCC -:10AA400064945B8DE153B32A8CFD09B0C697410F26 -:10AA5000BC0E7CA0F45EA286381F589CC20BE78C0B -:10AA600079ED297188AF20095CEF33B8CD2A5BE717 -:10AA70009BDAEB18FE84F7EFC097F6A7E6F727916D -:10AA80003A879C33BC3FA6B2F9A5F0F89DDF9CF154 -:10AA90006501F195483C25D2769FE2F04EFD659523 -:10AAA0007B397EC322D9CDBE938C93FCEF2A7DAA3D -:10AAB000C8BF7B64EBCCA99F5C2057ABCF5FAE2AAD -:10AAC000D5EB356AE17D87EAF92688F715DB774E05 -:10AAD000AA33FB41139FB7739AF7DF811E5A333BAA -:10AAE0009F95E27B091FF75CF13D3517DF8AE4ECA7 -:10AAF0004DAE272AC56FF379E2F79203BF774BAECD -:10AB0000DFE6FB51A5F87FEC3CE5E18773F95BD10B -:10AB10003A12D573E3EFA7CE13BF5F38F12BB26EB5 -:10AB20001595F12B45987CC8FCFCA552FCBACAE3EC -:10AB3000C7F3C5B6F69931B4D7D01FDFAF6EED4B72 -:10AB4000C9B3F89984E9F5731DFFDE8AC7FF509FEA -:10AB500029CF8EFF05F543B6F165D94061AB74DCB2 -:10AB6000872B1D37F5511BDDCF0C7DD436EEF9F266 -:10AB7000FDCB158F7F938DEEE7866EB2D3ED373028 -:10AB80009FB8D271BF739EEBFD371C5F9FAAD9F6A9 -:10AB90008162F6FBDBDCAEBD45D56C725C0CFE4D14 -:10ABA0006EAF7CB042F853BCFF460B9F32F09FE182 -:10ABB000F87FA642F8DF717CD65788CF0FF83A2C81 -:10ABC000B67F7A39DF7DA023F3FC9A0BCD5BDAE503 -:10ABD0004E081E38E7FC7A177E27F8A6AC6A10EFFD -:10ABE000241D04ED71CFAB8171965792E2FE7F2256 -:10ABF00025303D8CF12D57D8B09DC7597E972CC775 -:10AC0000CD42E76D210FD37F826674B2F5AE10C8D6 -:10AC1000432A06EFF3148EBF549169CC3F21117E75 -:10AC20008EF4F6757AC17302398E792D92A69071E1 -:10AC30003A4E5F68BB9E9FB71CB3F08998888FA27D -:10AC4000317C14D9300BE529D77BD8BC5AFD58FE8E -:10AC5000A1109926EC1E07865FBF27DE0979E2A9BD -:10AC600090827CEA0BD8CFC7AFE7FDBC9FD3D7E774 -:10AC70002A9D27D63EBF15F3957A5B59BE924E0C9E -:10AC8000CCEFECF397BED760B48BC5FF4778FED30B -:10AC9000107C3F0ADF13C3F7A3CBA0FD57F13BBCE9 -:10ACA000D3CD62C9FB7102863DCEEE6BB27FCF631E -:10ACB000C5E53DBAFDBB1E77C4FE5D8F6BBE8C79CA -:10ACC0005D7D7E763E500E7F2BEFDD821B9493AA36 -:10ACD00056904F19DBB9803B62C7F7BDE31F6BEF9E -:10ACE000734D6885F07AB7F8562CDE30436F959235 -:10ACF000CC30BD61CBCFE8E2F2E5AE5293A097A98C -:10AD0000DE2DF2DECBDAFBE3981FA246E23AC6A3C1 -:10AD1000F93EA0C27AC8E3D3E7AD75E915AD7C630F -:10AD2000CCEB107413CF1F555847C2DC7633F36A4F -:10AD3000C9FD9FB644709DD4A8B84E047D1ABFEBE0 -:10AD4000728EB3CC631EF4C0F998C7BC0F4AD73BD0 -:10AD500052A2D07A19F3303DAA5E13D7D5067455A6 -:10AD6000D1EE71E2F12C5F7F7E0BFF9489F917958C -:10AD7000E2FF7085F85BE350FC9F063D4BF1FF124C -:10AD800094C5F07F8AEBA36AA277E39EAD333D4B77 -:10AD9000C8B57A7E7CDDEB65FD56733D45489B2D3D -:10ADA000AFC7C5E9AA949EA3965E2B438F352EA507 -:10ADB000E7453E1FDF2B351F2F707ABC5EB66FA9AB -:10ADC00087E33A5D9A6469917999E278CCF7F2B8B1 -:10ADD00052AAED9CE4EAC715D231353B2FAFF17989 -:10ADE000F945293A5EE5729596C8FA53B09F365AEE -:10ADF000F90BDB6CF3B288F327EDB6E6A5DD362F51 -:10AE0000A1739C97DF5648CFA2D97939C3E725575C -:10AE10004ACEF2E0FFC4E1DFE1F068272EF2FEB196 -:10AE20000FCECB9679E2A2B766767FA3709277CDEC -:10AE30002CDCE7878F5B706E84EB988153BD79FDC6 -:10AE400091D4EB7D70FEDDCFBFFFF8C170E02ADE4C -:10AE50002E88EDAE61F4D07655F9FD3F3BFCB2D5BE -:10AE6000FF3C80EBDEF28E0517CE875BE47DC78268 -:10AE70008BC073E1F04C7FB5F9784C79FEA98FE572 -:10AE8000EB38F2BDB4CAF21D5CE104DEE7504D02BE -:10AE90006989960332BB5F21458DEA27207FD69DC5 -:10AEA000C8920AEC2E5165EDDCD4DE82F3E3791A08 -:10AEB00039E6D1C10531C861FAFE4058467FE00E3F -:10AEC0004FA2C55BC3F0C43C80D7983DD6ED6FE17F -:10AED000711486D798EF1343D09F46F182FE3FEF5F -:10AEE0000B1E03F883F50AE6F31EABBF13EDC4B1E6 -:10AEF0006E99C0FBB1AB15B413EF7B2D80FB70BF17 -:10AF00006C5C8FF90FA6A283DD7897F79D9390A7CD -:10AF10003CD95DA50957203D887F4A24F15EEC9F0E -:10AF2000D99D7B28FE900F8C5B17F4DBC1FC18C207 -:10AF3000F39CEFDAA263DE8C4ED8FD4D83AD0AE6BA -:10AF4000298DD535B4C178F7B5AA6877DC774D433C -:10AF500037E673B77A31F7ADDAAF0B90DF135CA742 -:10AF600010F810A43AAC7783DD1958EB853BBF4845 -:10AF7000751D1B2FB08CE03D7F2E928EC768191C6B -:10AF800052F01EA7FBAED996DD09764D2BCB5FA6FE -:10AF900084BD145B4B889FB392483F24808F6B1114 -:10AFA0003BCFB7E639989E695FF21C3198A9102E05 -:10AFB0005B195C6048C6FCE4B270E90AE13215C274 -:10AFC00065195CD9F37B9E4FA9D27F1087F338F3C4 -:10AFD000B1FDA5BF8B3BD77CDD31AF3DEFBA5C7BCC -:10AFE0002B4FB71CBD70983983A7541EDECAB32BF4 -:10AFF000F6DE35FFCE087C97365873372FEF616544 -:10B000002D7F5EBB2782F745D6F2F7B5F7E0FD91BD -:10B01000CE7EFE0BD7C74D245E721EAA39FE6F503E -:10B02000DC219EDD2497C90770E6FB39F49E2AA730 -:10B03000DA71DD5EC3F28B66BE9FACE3DF8D906498 -:10B040003C86F12C33B872FEECFA716DFC3EAE1FFB -:10B05000EBBB493A3FEC7B49879C38E5C2EDC84FD2 -:10B06000B9503979E53D9213D79054D1FA71A52B97 -:10B0700084CB540897AD0C4E19122AD22B4ABA42EF -:10B08000B84C85705906D7BF5EE1FBFA703FC4B774 -:10B090005C97ABB67AFFE55EFBFB0D7E5B7D608D5A -:10B0A000BDBDB2D6DE7E60ADBDBDB28EB5377C878C -:10B0B000AE4AC52A5F27FFEB3CD749935A1A3ED0C8 -:10B0C0005A665DA99A07DA57CB3A81FB85E87E95E7 -:10B0D000E1FB56C1F8CF561F5BFF577B35DBFD7494 -:10B0E0007FE97436F918BE16BDE5F0B5F4EF3F4AB6 -:10B0F000DCEE2A92771F029D538B8F17417FC78EFC -:10B10000BDB510ECCA675F5F87F79AF67ED0CA9B21 -:10B1100031301F523EE9FD38E8AD67E97E0BF93862 -:10B120001321E3F82560CF044402F63275A3F05EE4 -:10B130008F678FCA687FF43E57DAEF7FA68BE509E9 -:10B140003D0D7E3FD5FF47F8BD5B4FF27BB71EEF4D -:10B15000D2B11CEF6AC2F7992E03EB0F77B562F9F3 -:10B16000509789CF1FECEAC0FAE1AE38D6EFEFEA8C -:10B17000C4F2DEAE0496FBBB7663B9AF2B89E570F3 -:10B18000D71E2C07BB522C6FB36B887FBF96C6F2BD -:10B19000D2EF4C8D5C0276925FC4EFC08AE1BF6251 -:10B1A000C21E77B8E4883DEEB03C638F372C3B6C11 -:10B1B0008F372C4937D8DE370E5D6C7B1F4DADB213 -:10B1C000D52FDA73B90DBE3ED96EAB2FDAFD7E1BDB -:10B1D0007C6D629B3D1FACF3061BBCB67187ED7D99 -:10B1E000B0E5AF6D757FF31D36786FEC6E5B1DEECD -:10B1F0007DCE87BFD6D7C0E281E1111B9CEC3F68B2 -:10B2000083DB35DF7CC4B706F2F183685F3EFBAABF -:10B2100080F95DF3161BAF03DFC92B12CA13B99275 -:10B22000E5C3CF6B485E06F7941139B9EEBA40F921 -:10B230007BA4AD788F146C4D80BC9E795DD0C1DE4F -:10B2400015827B964D1690C7DDA7936402E2923C6F -:10B25000CFAC7121314DDACE4BF5091E2E926476BA -:10B260002FC62D45FC8EEA312181F926D46636FEA3 -:10B27000B30679F4CEFD77C3CF7787F17E04B4CBE4 -:10B28000DB0EB44E0D51F8F1150ADE7733075FC7B8 -:10B29000FD76BFF5313F78DF5E16AF6C7C7E7D8337 -:10B2A0000A76784B621EB8AA337A23FB33FC4E2908 -:10B2B000A01B6BE10A80402C4D763603DC0913E2BB -:10B2C000B614FE6BBEBCF1028F9F4879E9F3E547E7 -:10B2D000128DF0D9C4F85E162F1D1F5E2ADE4AC7F4 -:10B2E00069C82E1797A2BFF324BBD77D48176FA557 -:10B2F0007AA1E1505CDC5A806FE37F2A1C4F9DF4F9 -:10B3000049D87EBC3B83F7CB79B3DFC47B38AD79BA -:10B31000F135EB6202FA3D9C10C15E1BDFCBBED360 -:10B320001B17A20B239CCE6E079D8017A58BDC0AF2 -:10B33000E5434971AB9F3D6F0CCCF60BEF77C2FB39 -:10B340004C4ADCE2AF887FA6179E3FCEF9772423D4 -:10B3500096E49F7EC2047EAB31CA3FBD14FFEE6708 -:10B36000FCA37CBBD53F975F33F0295D5CDB9CC7BA -:10B370006FDE1EF8726B01BECEF089B64F60FBA87F -:10B38000B89A8F0B7C68A074EF2CD44E88F271327F -:10B39000F671281F6FCD8BA7C39F3F2F4FC48287A5 -:10B3A000BF8EB53C4F91D2ED9A0CED84EFAFDB9A96 -:10B3B00013780F70BF5FC4FB85FAFD5FCDE23DFDE2 -:10B3C0001A41BD29CB66CF4FC22C0EDD23145AA7DC -:10B3D000763F01BE4CC9FF9EACCF6FE5E197B197B8 -:10B3E000F8BDC212BF575891E31D51B69E8D6E3203 -:10B3F0001B5F9D3BFE41A45B8AD8F7DFBE5DF67DF7 -:10B400002FA6DD8071ECDE7065DF0DB973CCBE5404 -:10B41000383EAE9C8FDD779CF3209E666E1E969B19 -:10B4200073212CAFC82DC2F79B72B558DF986BC43F -:10B43000FA865C14CBCB7397E0F3F5B9E5586FCD82 -:10B44000ADC6725D6E253E5F9BDB80F535B9F55864 -:10B450006FC96DC17275AE0DCB55B90FE0FB95B9D3 -:10B46000ABB16EE4AEC37279EE5A2C9B721FC7F774 -:10B47000CB72D7637D696E27D697E46EC67A2CF7B8 -:10B4800029AC37E63E896543EEDF6319CD7D1ADFCF -:10B49000EBB9CF62FDA2DC67B0BE38D78BF5FA5CA2 -:10B4A00037D6EB72FBB0BE28378CE5C2DC7D58D6B0 -:10B4B000E6C6F0FD82DC0358CECF3D86CF43B947C8 -:10B4C000B1D4725FE2F7453F856530F7352C03B99B -:10B4D000AFE07B7FEEDB58F7E5BE89A537F7029634 -:10B4E0006AEE1896E5E6A9DCF74F9BC93C9B5C6CBD -:10B4F000CA2DB4D5374CDBF7EFF5BFBAD8565F3756 -:10B50000B9CA565F73F2725BFFAB4FD8F7EF95C7BE -:10B51000DF6FB71FB2F6FD7B59E606BBFD7078877B -:10B52000DD7E48FFB5AD1E1DBAC36E3FA4ECFB77B0 -:10B53000FD1EFBFEBD283962B71F761FB4C12F2048 -:10B540000F3AF2C9C76DF055E6D336F840EB571DF8 -:10B55000E72B19A6FF8D6FD99EAB4DCF173C87897E -:10B560001DBA1ABFDB3F5D27F27B86F8BDADFC7EBE -:10B5700034E77C56733D302FC7FCA7305F7735B07A -:10B58000EEF2F29EC0CE88E6D919F31AF4AFBC48A9 -:10B59000EB67162B4637AD5B7686055FF6772B1487 -:10B5A000633245F174BDEAC67BE78460A70971B5D3 -:10B5B000BBA604DCEFAB17119E1FD1D1C1E213C4AF -:10B5C000BA4F07EFF719ACB7DEEF7C1FBE8FB2FAA8 -:10B5D00071FFDEAD10471D7459EFBFF43E8C7378D8 -:10B5E00058FDBFFB770DC0FBEAAA8908ECB3FB8AC4 -:10B5F0009C6FFE4FBFC2EC7DBFF923FF9AD97BA69B -:10B600005F09275EF2D3E7B7A9898BE0CA6EB8E776 -:10B610001EEE71DE2A9B3F01B86B65F3653FEE0BB2 -:10B6200076FFE15AC87D5D83F702FE0CDE4BC1A3B5 -:10B6300098DF5FFD817BF0BEAAC100C5C75F1C9F7C -:10B64000FFE69766F61B62ED370D184F457B7020BD -:10B650004AF0DE8CC1503C05F7F9A5BEA792270C35 -:10B66000A03BCD9295787EE2E072DD920BDBFE444A -:10B67000483C0B717C5FC2AF83BDE6272730FF22B9 -:10B6800048A6B1D48826D8EEDBB6E8AF67F4C3FD90 -:10B69000FF7E3C87378F4E629C3549F8FDD56FC1E0 -:10B6A00073CA9733FE35C5F97295740FD1E8F80F58 -:10B6B000537B12E87898307CF773FF5426C97823BF -:10B6C0008FF7E4DF2321BFFA4D941B2BDE234B1BA6 -:10B6D0003BF07A177E8F4307FD07F6614DBC74BCC3 -:10B6E000C7796FC3B9C67BC20167BCC78FE7C9A75B -:10B6F0009B4B7F0767C57DF63797BEB732C3FDBE4C -:10B7000087F979EF43FCBCF741EEF71DE67EDFFDDC -:10B71000E0F7E1BD5ACCEF3B007EDF32382F366DCB -:10B72000DF978C16B9FF251A12B89CED41FBDEC7D6 -:10B73000EF2BA29E2BDAF35E6ECFF7FA7BE6C3FD0A -:10B740000CBE10C9809FB0FBEA71FC7E969262C06D -:10B75000FD00B7FFFA8DF9FF8ED6631162BBDFC91A -:10B76000DBECB82FA1DC3872C6847E7DD46F481B19 -:10B77000C5F973CEFDAA19E239AF7ED93D3FD6BDDA -:10B780006DD4034F81FCF9806E0DE4EADB38CE699D -:10B790003E0E91361EC7FB0C2F934929399833CEA4 -:10B7A00039CADFAE80E3F7291CF2A7CBA407EFA9C3 -:10B7B000E1DF43EA7EC39B1F5FB1E4B0B799C51FC9 -:10B7C000BA5FFF18FE6EC08B355B17E6FB7FD6773E -:10B7D0004ABD2D0C8E5A7DB8CEF7779FD43FA9CFA6 -:10B7E000C23D65C169A5E3194F5870A30C2ED06204 -:10B7F0008885EEEFFB22DF4FBEEC3353819AD9717F -:10B80000F59E8E1B504FAC51F17CC6D9EECBBEC419 -:10B8100050202F3FC1EA3FBF3DC85789F6E952ED9E -:10B8200017DFDDF17352BAFDE1C09AE2EDEBEEE80D -:10B8300078B00CFE99C2E3A71EC173A608FBDDB267 -:10B84000EE5AA501FCE57D6BA8BF4CE7E1C5155B91 -:10B85000F15ED9BED02B7A2139A2FD7EA9145E9467 -:10B860002F9D65E8FA5AB9F64269BABE5D86AF27E0 -:10B87000CBF0E58552ED295F0F97C1FFBF16C63F9C -:10B880007511E01DA863F1BAEE7ACA57F0D7D6B0A9 -:10B890003884B51E1E1F2BCAD757CAF0A59CBCFE04 -:10B8A000E202E5F58D52E35720AFFF5486AFE5E4A1 -:10B8B000F5AD62F28AE7A4E72FAF42F0C2E4D513F8 -:10B8C0002CCDD772F21A2AD5BE0279AD2D857F050F -:10B8D000F21A2D34BE9B508508F67E333B17DBDD14 -:10B8E000C6EE237335B17DD7F7EA17D13EEAA3FB45 -:10B8F000D3BC56D8A7A7EEBFBD65765F76EE3BCE2C -:10B90000FE9CFBE6EDFFFB49DC37037CBFB3F0F1A7 -:10B91000E8CE7E4ADF6771AEE37AE17798F27EDFA8 -:10B92000E2E2C7EDDFAD5EF878F67DDDDB42C7A76A -:10B93000EF091D7F0B9E233E83E7884B0F5DE8B820 -:10B94000A5E19B1E727C8F7B8E76C02D41BB1DDADC -:10B95000B0E76B8FE0FD23BC9F06D9C4DFED93C930 -:10B9600095ECBE9321962F24EDF9CA23A756E7DD67 -:10B970002B4574313F3F481A9A78E4541E1D39888C -:10B98000F7B0F832E62DC6B4CBD19E181C2D6DC78A -:10B990007E99EFE3CFF0F38BA7B91D7B84E72D3EB3 -:10B9A0000976EC3238C760E717E360C7629E632B05 -:10B9B000CF7334799E630796CFF1F3876F751DC6F9 -:10B9C000F747BB32587EA3EB08965FEF9AC0F75F4C -:10B9D000ED3A8AF589AE2CB38757DE897A66960EE2 -:10B9E00067DCAA341D971DB5C741564CD8CF312E00 -:10B9F00039623FC7589EB19F632C3B6C8F832C49A3 -:10BA0000DBCF311A87ECE718BE26FB398647B7C76C -:10BA100041DC91F73BCE41B639CE41ECE718F54910 -:10BA2000FB39C6A2DDF638486DC27E8EB1A0F36E3A -:10BA30001B7CC8ECB17F17DF6A8F836C9AB69F5F5F -:10BA40006CF8D583F6B8CFA43D0EB2EEA43D0EB28D -:10BA5000E6C4576DF5D5C7EDF18F0FFB122F823E6F -:10BA60005D9975C641264598BF9FFBD9F99FE55F53 -:10BA700053F81F80FEBC4AF2673750B97FEC28BBF1 -:10BA8000DFFD31C2CE3309F90FE82FC833FE8289BA -:10BA9000FA47E2FA67ECCAA957C09F91F7337FE7EC -:10BAA00076615D56CDF7775CFF28E4AF6B4973FA9A -:10BAB0000D65FA970DF473E432FEC8DC7E99DE9AC8 -:10BAC000BDDFBC25057954F28C3FF201873F523728 -:10BAD0008CBF6335AFB43F32679C73D4436F058B23 -:10BAE000F8C31111F967F923FB5AB83F42D87752CE -:10BAF000567F961E1A8B945E87D63D2D63DC6F9120 -:10BB0000FD85CFB1AD7C99B196CAF2BA7F1064E7DA -:10BB100049149AFBC3FF5F3EDE4DF9B8BCAA88BF4B -:10BB2000FA1ECB4731B873950F197406C6236F19E7 -:10BB300084EF985C50BF7CB6AEF07AF0DEDBB642A4 -:10BB40005EC81EC2CE75C8CBECBED57278C436DED8 -:10BB50005432FFC18AAFFE496379BBB1D69B306FC7 -:10BB6000F2341DA3D47DDACE3C0B299C841FDB83E9 -:10BB7000EFD80B9EF7FCB49AE593C73A3F51D26ECB -:10BB800071FE1E58CC2C7DBFEE30C7FF85D716A0A6 -:10BB9000BDBA6F88E963B973C5F3208F8F833C1AF0 -:10BBA000184F5197035D4332DEA7E6D709C6051744 -:10BBB000FB49A63B0A7C3552708F17FDC373E5190C -:10BBC000F91CB2DB51672C3EC54BF3B5ECEF19AC59 -:10BBD000D7312F4DD649520BE1FA216F84113F5CCA -:10BBE000B783AD06FBDD3B8A8FA6CD6DEFC4CBB925 -:10BBF0003EE55D57603CA941B0D6A7CF803C9DD3C0 -:10BC00007E7FC97BDEE6F47B8EEBF19939EBF19A0E -:10BC10009E9FC2B8A32C7E44F6D0BFBC734E677FF4 -:10BC2000D67AB4EA2FBC76177ED732387A07BBAF04 -:10BC3000B88EDF0B36CAF46331BCAC78D0016E1F0E -:10BC40003E71A8BD07F8DB47D74DBE3E5AF2B71F7D -:10BC5000F126D8B96235944F1E66DF6B2F7D6017D1 -:10BC60007FBE039F1F68DDD68EFECF21620259C1C1 -:10BC7000F5A754F67E4A43F8F0F471B81769299590 -:10BC8000378885DFBBB1C584DFA8AC0A89ED504A8F -:10BC9000A393A877492B3197E830AE8CBF9FB33878 -:10BCA000451E057C168F2646403E499A18F0BE2A4E -:10BCB0001CDF763585AFA282095756A7087BBF38AF -:10BCC000A9E1FCC5461307AF06F86682BFCB45DF86 -:10BCD00063BD6EB786F93FBED1C921B8F79A8EC150 -:10BCE000DFD33A7DBF30C1DA074627D35BD02F9927 -:10BCF000799FDED202F70EB2F7F228A507DE4718C9 -:10BD00003E29327D02DECF0FB3F7CA28DB1FEFDDFD -:10BD1000B803EFD3A3E3E37D532EFEFC31CEFF58EF -:10BD2000E73B27601C2B1F2345E2B67BA99CEBDE7B -:10BD3000FAFDBF5E6EC7FBD4455F3895771FC33EE3 -:10BD40007E5FB577D4BE3FFFB18AEDB3C7B89E29F9 -:10BD5000772F1B247A839CFF0B555919960080007E -:10BD6000000000001F8B080000000000000BC53D14 -:10BD70000B7854D599E7DEB9F3CA4CC29D300993CC -:10BD80009099DC840422043A814041512711111515 -:10BD90006D44DB066B7508C8FB11514BB4DADC90BF -:10BDA00004921060B0AE44E43189A2A8A08382D28C -:10BDB00096DA01B3145DBB4DAD456AD146D0A808F3 -:10BDC0003452517657D7FDFFFFDC4BE64E2689D61D -:10BDD000ED6EBE4F0FE79EF7FF3EFFF9CF19C61875 -:10BDE000FB2A17FE5795C4A2058CFE285F99CAA2AC -:10BDF000B698FCFC4C637930D7982F1F69CC7BC672 -:10BE00001ADBBB2F36947F7E1D631D4EC8487E1BF8 -:10BE100083543A7AB3AD6C3463B5EEE5943F7FBB9F -:10BE20005E1E48C27C9E7CD28EE58F5555D8582127 -:10BE300063AB3C330605E1FB57F87779EFB4A19A81 -:10BE4000B1A895B135D5214A9BAA5B286D2E6222F7 -:10BE50002B666CED6831DC96C3D8EAC219D45FBD9D -:10BE6000BBFFFEDAB0BF118C85AB6D946EAD96A9A9 -:10BE7000BFCDD51E4A6BAB154A37551750DA52ED78 -:10BE8000A77A0F554FA434541DA0745DF5342A7F52 -:10BE9000BEBA8CF2BBABCB297DB63A48DF7755CF23 -:10BEA000A7F4E9EA4A4A9FACAEA2F4896A95D2EDBA -:10BEB000D50D94AAB2C8581AACE74A7F6619CCFFD0 -:10BEC000D12B5979A4B0F7BC5559E0F56480E578D9 -:10BED000C6925828CADC882FE84B61CCDE10623647 -:10BEE0008047E662F886F9AA10B342DE3387E7D7C7 -:10BEF000E138D0AE8AB100C28D15B0F076809B4D8E -:10BF000009B159305EC0ABB21B92199BAE8D83DF75 -:10BF1000118E6A8ECA105F272C81EBE434EC8751B6 -:10BF200079FEFE8E8388D6311D91524C0B0F8744CB -:10BF300009D291532A579A201D345915B1FD2A8FE1 -:10BF4000582AC078E7AAC4B009BA568AD94113E47E -:10BF50001F2B14C34D307E73091345C46306E05193 -:10BF6000E8596FD2F9AD2C3A0EF05A3563104B00F8 -:10BF70000F3D1D3A5FECA147F82F2398D443AFF053 -:10BF8000DFEA50FFEDC7EC110DF50B77C6B52F8436 -:10BF9000F6FDD0D3C8C78CED0B362719E6B3DAD33C -:10BFA000FFF8F9E7AFA775F645B7A72C153F43B8DB -:10BFB000EBF9F4F397B1E860C6DE72CA84CFD46BB4 -:10BFC000EFF3040B69B82926A007298B859B04CCC5 -:10BFD00006D86C80AB19FED524F33CC2DD04486A58 -:10BFE000F223BB2A019682A93FC0C6601AA0FC2199 -:10BFF00073B0591E8FF932FE5D0E121D345F045D61 -:10C000005C8CFD6437042643FEFBF0CF4CC6AE0FBC -:10C010005D344D85FCE7E6A05805E3AFF5727E5C24 -:10C02000E11B9B84EB7EB4B97F7EACD5F851CF9BEE -:10C030009C0126403FB90DF258A4A3BEDA3DD8209A -:10C040004E0B27E8F729A45F987F7DC30C391F5753 -:10C05000DD8E328B31AB9311BDC5D787F53E85F0B0 -:10C0600035BBF93AD36E2AA3346FE7245B19F0C3CA -:10C07000E7C9FDE3AF316EFE76183292605E1F6A4B -:10C08000F3CA7BED17241F3F1FDD3F5DE972EF7C94 -:10C0900058641D885FA98CE469DA4D419607EB5915 -:10C0A0000DFCE244B9F7E58D0D3980577583487270 -:10C0B000409F7FFCB826A5B34484F2D5071630050F -:10C0C000C6377BCA985A88795D3E4718F6EF707676 -:10C0D0000470BD0E160A98A07F475550C5EF168F05 -:10C0E000CA90CE56675CA84FF2764D481411BEAB8D -:10C0F000B2C4301328654EE4F76246F9E48CE702D7 -:10C100002292CD17309F09D00FFEDB84F05699881C -:10C11000EBC8677E27CCCB56D01D10A17E1EDB1747 -:10C120004579602B61FE26E49F8C2301A45BF50E0C -:10C13000E6CF27320F923C6252D086F22AB7650CC6 -:10C14000F1834D8908B8EE1F5882EFC5F28BC5C345 -:10C15000E5D8EA2F4D09E5EABF6A7231A90FBC396B -:10C160005CBCFC73B3720DE91BC8B725A023B38B6D -:10C17000CBF13679C6EF0B941EBED4CBDFC2458E11 -:10C18000EFC9E79EB7D0BCF36EFAF1205C4F5F7445 -:10C19000B04AA3AFF583B8DCCD9B7C6900E17D0E8E -:10C1A000E6DA24F4AEBF609042F5F4BCE434CAC7CA -:10C1B000AF3F3F89E452DEA97B381F78FBA7577D4C -:10C1C0009E9F7B8DF6809867233D5D1F12492ED57B -:10C1D000BA459602F9AD481F3928303BED17C17AB0 -:10C1E0006C6F9818E27B6B55A9A84279728E142661 -:10C1F000FAF37447519CD9257600E903F0ABB8D225 -:10C2000010EF13087E59C51101E9FA94A617E1AFA2 -:10C21000CE0374E6E34B46FE1EE182EF819D02975A -:10C22000031E2E07CCCCAF5A717CD0881118CFF1E9 -:10C230008689BE331689DE0FF92459F4A3DC5C5BD2 -:10C24000BC321DF9CDE162A4BFE65FDD46F209E430 -:10C25000AA7F13C8D1A51F75A52F837C9E87CB5DB0 -:10C260001D1E498516835E18701C291C403DE9106F -:10C27000983FE4EF1BCEDFB85F5B98D9FFA17E410A -:10C2800061A4135F687F3B549A1FAE1BFAB5B25F7F -:10C29000D138E7B47198E9D861846FD27724664ABF -:10C2A000C01F7D8E63BAA55FFD50756CC1EFDB6367 -:10C2B000E8F73657B2BB6B14FCE3BBECBB5FA18263 -:10C2C000303989BECE813D81E32A367610F375CDB3 -:10C2D0006238117F7C5E3DFFF7ED80BCB59A5EAFA2 -:10C2E00079D75A4AF4395E0C5BA17E7BDAD4CCCE86 -:10C2F00018BED0E5706D31D70340DD0CF9616DCD0E -:10C30000516581D253EF49BD9EDCBFBED8AED76B1D -:10C31000E6F5928BFD623041FD27347E7AC611B876 -:10C32000CF35BE675C65E5B49B490E8DB73153824E -:10C33000F53DE308D6B962F858EF3FB63DD26F3FFE -:10C34000ED9B5D697DB7F7DD3BED2DD67FFB07FBF0 -:10C350006B9FB57CDAA601E6BF39F1FCD56DD82E0E -:10C36000D9636148E7351996DC06C8AF196FF15BF0 -:10C37000010FEDA3A77A106F75AE234A227A827E51 -:10C380009FE86F5E0097F201D6F5EC00702D17FA6A -:10C390005FD78BFDB507B81E1D002EBF1900AE2D4F -:10C3A00003CCFFB789DBABD938EFE42C0BE9931A48 -:10C3B0002FC0D58DFC0070653DFCF0D8863EE1FABB -:10C3C000FA40F436C0BADE1A002F03D1EBF101E0D7 -:10C3D0003A10BD9EFC96F47AB60FB86EC3797F0B07 -:10C3E0007AFDF25BD2AB39F5DBD16B726AFF72601A -:10C3F000207A4DEBAFFDD7A0576FA2F95B9923A030 -:10C40000A2FD53C8F5F8FC1291F4BAB980EB5FC7EE -:10C41000B127488FD6819E1A3C11F5F5F187961603 -:10C42000F7E8E778FD13DF5FBCFE5CFAC9E3CC8E6A -:10C4300078D4F49E3E1FBB12DFCF8FFAB5E3BEE97E -:10C44000B8491E16B58FE9693FF2318BC18EFBF6F4 -:10C45000E319F57B52318C8FFE0418FF8A89A857A7 -:10C4600077FA912E873FF86DC7EDBF7EC16663FFF7 -:10C47000DFD41E98950AF680A3C71EC8AD7A7EDB6E -:10C480007B837BFAC995024C06BA91D814B2DB586B -:10C4900003F36FC7E2AADDDBDE1BD7630F0047881B -:10C4A000B89FD0C7313544B6BD17B38EF37398B675 -:10C4B0000FABA47D4F9E7C7112D2F1EAE6FEEDE255 -:10C4C00067343DBE53F3373D85FE264877A0BF094C -:10C4D000D2C7D1DF04E963E86F1A81FE29EE6F6AE3 -:10C4E000427F9315ED0FEE6F5A85FE2648F7A31F86 -:10C4F0000CD25F6A7EB07DD5614A5FA8DE41E99EBD -:10C50000EA08953F57BD8FF291EA28E59B8B7E4262 -:10C5100072A6671DDC3ECF93757F5DFFEBF8CE3EC4 -:10C52000E33E6274C4E82719B523D590BF289C69FF -:10C53000A83FA225D7509E1F1A69281FD630D69033 -:10C5400077145C6CA86F574A8D74E5B9C6503F47A5 -:10C550009D61C86757DD6CA8EFADAC30940F9DBFEF -:10C56000D0509E115C6EC80F29BFD750DF15586997 -:10C57000281F34B1C9507E69F70386FC251F6E322F -:10C58000D49FD4D96628FFEED1A70CE5E33B9E33B8 -:10C59000E4C71DFEA5A1FEF71CC128CAC3A2E8413D -:10C5A00023BFB04E11F1D79EC268FF6387FD7B2089 -:10C5B000813DF95F83F83ED6CA4691BD7B0EE459B2 -:10C5C0005311B6AF0CE1FE3A17CA9A14DC9A8705EC -:10C5D000368CA1AF286A4F89E5876F260770A78F31 -:10C5E000F57DF0877CF95FFAFE75875DBD0CC7CFDE -:10C5F000E3F2589555D207F1ED75BF50DE8E998361 -:10C60000B0BC4E2E9513C9851396E089583D11BFD5 -:10C61000DFCD0B24B3008ED7A0FBC5B8DC33F12AE5 -:10C620002CF7D8558705F483958F49C5F5E8FE9C0E -:10C63000D51ABFD66B7C6A6597A8E8AF38A7EDFB23 -:10C640009869B2BF3F39150FAF6F2AD7BE488DDF4B -:10C65000E74C8FBE8FE33748E144FA524F75799625 -:10C66000F7C66DFDE24787AF8E4793DC1140FD6A48 -:10C67000532A5985B3379C4C599C1EFED9EB1E3A60 -:10C68000D828CFCFB1C2D240EED7586FF9ADB40E93 -:10C690001D9FF1F5D655F37D5733E295CE1164CD4C -:10C6A000DFCFF12B4E0CAC44F8A6C03E1AFD02A21F -:10C6B0003FCA3A13CC7BD044237D25FB8D72D051E9 -:10C6C00060948392D32807CDFE4A16413F2D8CC338 -:10C6D000881E830CFDB6F81FF19F3C10DF5D121021 -:10C6E00062E87020FEC321BE1A3630BFFEA3FCDD17 -:10C6F0003E279DFABF47E36FE0689EAAEC75A49FB2 -:10C700008A891A0131E5877F81792F386C263FCFDE -:10C71000E55F6C3BB405FDD113AD32FAA3190B1DD7 -:10C72000FA3594CF09D8CA30BFE0D8688B0FCA8FCA -:10C7300064021178B0BC2C05E5C069264E433FDD8C -:10C7400069F67ACAB81839B764B085FB7F1ACCC7C6 -:10C750003B6D38BC4AE753B787785E5FD7BC16633A -:10C760007E2E9B912EC138731F34A3E4630B987403 -:10C77000BC538703D0C18F07CBB49E79AC72950CA4 -:10C78000E3D69BF9F9CC9217475B100F0BC6C9395A -:10C79000A6A29E79DC3D98FB014F02BD29D69EEFF3 -:10C7A0000B9D610BCAE5137BC6FDE01286FD845725 -:10C7B00065A25FD305F688D21BBEB31B8CF31C6841 -:10C7C0001DF1F3666C25C1A3AF79483B844022FF7D -:10C7D00079ED60C180C75ADBCFB675C23C03B51294 -:10C7E000B35F0679899F1FA9C792C3DB517E975615 -:10C7F0003ED1097050575AE55A48373A7EF62CD642 -:10C80000AF0284E1F9D3CEC10AF79FDA7D613C5FC4 -:10C81000007DF3DD19C9DFBEDFDDFFA47E5FC07ED2 -:10C82000D37AF7BBC4D669C173B46552E5344144C9 -:10C83000BF22AF6735070343D19FB8AF283A5431C1 -:10C84000D46BF89AF50E0BB95FABDE34B19FFECE18 -:10C8500068F2EDB73B1FB5A0DC3AFDD4BBD7E3BE11 -:10C8600068D1AF4CCC06F5CEEC4C6651B2FBC2168B -:10C87000B45F17EE3105C2948F4EB8313996AF6B65 -:10C88000A9FF45CF26D3BE6AE173D6F07468BFF026 -:10C8900085136318C883332BBB0F0D45F83D2590D6 -:10C8A0001DCDD4CE3137C2F78512BBAD2C81DDF161 -:10C8B000678D1F4EFDC2518EF426EC38702BF51B90 -:10C8C000F9A1D91AA3C73A069B099F508FFCDBEA4E -:10C8D0009342385FE0F3BB6174ECFC6A78BD27B922 -:10C8E0003F77E13E73D88EF3DBD16A0942BD653BE9 -:10C8F0003E21FABEE2D95D29088765FB4C06B9B630 -:10C90000E8D92F575D0C785E6462DDD3498F7F4193 -:10C91000F973015BB789E450204500B9B59444161A -:10C92000D47BFE83A97F81F2931E13B3832838D969 -:10C93000F1BEE557980F3A2B991FFB37F2E1B21D74 -:10C94000272C382F5964DD59C0E8977D1AC397AC5E -:10C95000777DC6BA2D286797451A3F3101BD2DDB7B -:10C9600073FA2DA4BB6571FC7C12FF91D15B5F0A49 -:10C97000EE787DF9DA0486E7F43B601334A96F7D25 -:10C98000A9F3F7A25DE7B6AA30FEA9E73EDEAA0248 -:10C99000CA17FFF7DFB7FE14F7492FD965944BCBC1 -:10C9A0009EFA530A8B817F969B9F279D79F289C7B8 -:10C9B00037011CCEFCD94A503BF3EB0F7C0AC0FD7B -:10C9C000CCEEFF48C7F3A5BB7E7DE510A4B3BBF654 -:10C9D0005E31A4BF7D05D26DD81A8BDF30F5AFEC88 -:10C9E0008371864076BF96C6E1E5D4EECF2D784EB2 -:10C9F000F499C0BA51FE2E8D7C6941FBEC508075D4 -:10CA0000239C5EDE73E2D0BD903F0D78B226C0134A -:10CA1000AC7FA8487A253A14F5CBD23D377EEFD2C9 -:10CA2000624CCD7E05F1C4BA49DEF7C2EF1B80DF50 -:10CA3000E21EFCC6979F635F5810FECB76023EC78E -:10CA4000205E019F637AE3F334FE63526F7C5ED213 -:10CA50000B9F8BB76DC2C23D8309FF7DE173C9DEB9 -:10CA6000EFF76B67E9F2612038CF17F8BCACEEC086 -:10CA7000B56EE4B3E71CAA87E3393C1DCACEEC3A95 -:10CA8000E74367C887E6EE5B110EDDBFB6CA786E76 -:10CA9000BFF0D76F12DF9DD9FB070BE21FFE528458 -:10CAA00009906717FE5E67905FCA6D70B684754F18 -:10CAB0007DAB1853D6ADFA097F943F047C48F80843 -:10CAC000DF304D41F91B4EA3752F0D73FE581A3EF2 -:10CAD000709330A637DCEBDDA276FED3835761225C -:10CAE000E2F3DDA9487F7DE1535FBF8CEBFF2E941D -:10CAF0003F66E4DFF8FA4B815F717FD40BBFE1033F -:10CB0000FF8EE99956AB24802D7406ED04676FBC47 -:10CB1000F7C09FEBE76F6A1F57C7D187DE5E87D3E9 -:10CB200040FC3ED0FABE29FC96B815031DE9703CC6 -:10CB3000F545627DF088263F96B2CA6999C37AEBC3 -:10CB400033132B53870A3DF35D1531919C3FB5C3D9 -:10CB500044E733F1F262299EDB2618E74937B763D1 -:10CB600096EE3B3006E5DAA983BFD0E892D3FDD23A -:10CB70009DEF5A544D3F8463E5731FE7C0CF6BF3BD -:10CB80005EB63F717FCB767E92B0BF9352E087381E -:10CB9000FF931D66A642172723A684710B5BDC66F4 -:10CBA00083DDB52A79C2D141B82F48495270DDB52D -:10CBB0002B036FE2B9A8FABA99CEF999E4FFD00A2B -:10CBC000E5B5C9490AFAF36A53E63225468FD7C557 -:10CBD000C149F294D1F99DE42E2BE67BBAB0E1BCB9 -:10CBE000D70C04113B6FD0BB59A897DE29FAC08C33 -:10CBF000EBFC6B9C1DF95789AD1A02FDFD5515FC28 -:10CC0000354AA2FD81B1FFE07D26A6C4F4BFD4DA87 -:10CC1000FD0ECE87FDC6CED02E33BD6417509E2CA0 -:10CC2000DB6AA6FDD732D85621DC3ED8620FAB9026 -:10CC3000DFF87CF5ADA897FEB6D5CAF05CE2E5BD9D -:10CC40002BBAEE41B9F488C0D09FFEB75F547F86FF -:10CC50007A79C166581DC893798EEEC7B1FDBC675D -:10CC600087B25A68FFB11099809BD9AEB4E804DC52 -:10CC70008774EDCAF0ABD4CF8B4BB1DF33CF3AA87A -:10CC8000DF33BF7993C639F39B64D26BFAFCC1DE04 -:10CC90005662F538D8DBCA053E207B3B260FE32CD5 -:10CCA000C23CAF2F7CA5C93C947F8B3005BA5FB4E2 -:10CCB0006F5000FDBB31F5A89F65D6EE9FF869FF68 -:10CCC000AD668AB4778A66223F2EDA611CFF3FDCAC -:10CCD000DCAE5A66E99ECBEB873239DF76503B4BB0 -:10CCE0009A46AF5A797C7BBDBE94966BA8A7B75F76 -:10CCF0006A659589F8C0A5F5BB68C797238CFD7157 -:10CD0000BAED3D0EFF7EB7C0C87FC276DB29EE6C60 -:10CD1000B1253A3C15F8F6050B9B8FFCBB38253A3C -:10CD2000DC05E3FD4A939B8B93200FDF33B57960DD -:10CD30007DCC335BE719C4EB9217ED74AEB2E4859A -:10CD4000373F437C9E421803C64EA5757CF653A020 -:10CD500083535B4C4C057B6D8935EA7B04F5D46EBF -:10CD60002B6B43FE7EE915D25BA79FB38AFD9D53D3 -:10CD70002F890035D87AAF432D6505954E8CB709BC -:10CD800088ADB86F386C0AD7C0D8555260E5B3B8D3 -:10CD9000BEC366DA679C9DC30A705F799665FA55D3 -:10CDA000C2BFF2A604E52B5E350B89E290CCE741C9 -:10CDB000A88F033E387F2D532095CE0FA37485A5F1 -:10CDC0007204CA5D930C8B2B243F01D9ED66B79F8B -:10CDD000CD8374452A0B22FC98F39A0BFCF57B401B -:10CDE000E9F2879521D86E521A972B73D20357A672 -:10CDF000917C71CAE457D2E854DDCBE7F9B990E4ED -:10CE0000AF8179E59DBFF73684EFF2770525F6FC13 -:10CE10003C3ECEB34A52DE548A69BD248FF2E424EC -:10CE200086703D2BF3B8BEB3739441AE18B9BCA65F -:10CE30005A26F9D158EDA17475750153C8BFE6A7FC -:10CE4000BC495BBFB550A53835E469FCB33ACB02A9 -:10CE500068E7E19CF2153CEE0F121D593D95E49BED -:10CE6000B23919ED634D4E95CD83D4ECE4F03139F0 -:10CE7000CB083E162D2FB54C2778427BFA7E797A67 -:10CE80007011C2C39635D220972CEEB1867C2F78D4 -:10CE9000E9F8DFF57F053746706AACB651BABA7A61 -:10CEA00022C1ABBE3A40F9FF07B83DC0E17631C6BA -:10CEB0005AC4C0ADD490EF136E0F03DFB863F90608 -:10CEC000E0887CC392FCDB13AC3F3E7DA81A17C7F9 -:10CED000D803D52D94EADF53FBD0DB9FA4713BA090 -:10CEE0008A056BCC74BEC5FD2DCCADB2AC093DFE40 -:10CEF0004DE651998279E455C4CBD12482DDF2B755 -:10CF0000EDE43736C95257AC5C5B7E9D3204E59741 -:10CF1000A9EA517662708C1F6D7A995D21B8FA0585 -:10CF2000F4A7D66A7AB3FE02FE8C7CB0A65AA1742E -:10CF3000ADC60FEB357ED88078867CAD9F9F6F366F -:10CF40004F63A417FF05F27C1F1F65B171262E7F6A -:10CF5000246A067C938C54288D529CEF516B381FA9 -:10CF6000E3A80A19C5D1B98EDE43FE63C6221EF4BA -:10CF7000A7B934B8B1FDB9AE99C9B43C33D73BCCED -:10CF8000C4D39019EDF178B8D6FA0FDA707FDDD7F7 -:10CF90007C4ADE5920E0789FCF243431F72D91A3CD -:10CFA00015B00E67B383F46ABABF321BFD7BEC98F1 -:10CFB00095E8D3E90F0AF362F097DE875D7767FAA9 -:10CFC000D57F45FAEB4459067AE88196617684F379 -:10CFD0001A73C483F26E8D8BEB0FA51CA0F0DD9E3F -:10CFE00076AF687230A5D8C8EFBA7C95278F35D058 -:10CFF000AF2E5753A718E95C97ABCFA7717FC59C9D -:10D00000F4B24FD2201D7C7E33F1613CDDE7C917BD -:10D010009707DDA80798BF09ED35B419D18E7B5766 -:10D0200008737AE7FEA9B39D396D68E7C0AE80E466 -:10D030008A8AFC4078EA7EF92B68B74B930F2B6DF8 -:10D04000336CB8DE06A02386E77A403F08E07540DF -:10D050003F9886807E387F4CA454A74F4F7A8E210C -:10D060002ED0947748E4F1F222F99E25D8DF396179 -:10D070003CE9C0241BDA7B92D97F18E55477B218BB -:10D0800041BD59EF9C610BA0FFC6554C78FF2CB9F0 -:10D0900022BBBF3827B05BC86F2B3BFDEC388EC37B -:10D0A00018F96D4DF25886FBC45DCE8E24DCB7585E -:10D0B000D345C3BCE6A407BDE931F9D138BA862F00 -:10D0C000EC7697D64FFC7817A56B7ECB2C95056236 -:10D0D000CE2DAA74FA5654362586BF57E64F6518EA -:10D0E0007F11CFD77DCAADEDDF4E6ED56687095F64 -:10D0F000E67879E10639EEA45415659CB777CD8FB3 -:10D100008A88AE2E4DC7FDA1B3ED821D72796E02E5 -:10D11000FA3A3A7208C5675ED033B06B2E243DB33D -:10D120007122B747343DC3F5D3D96607E9A7B37376 -:10D130002A299EEA6CF31005E9EEC0BA4BC6203CE2 -:10D14000E69E6F640ACC6FDEF94994CE6FF939A57B -:10D15000152DAD40E48CD5AC9DB76E26B43BF1B037 -:10D1600089E283BAC2E3CE5441BEABD9CA4C304E39 -:10D17000D7E63BB3D12FDE05E3A07DD5B5399FE8D7 -:10D18000AB0BE046F906637D8C0B36015E2A18C7AF -:10D190000BFC2F80F5E7BE626A4D642755ACB706DD -:10D1A000129DEF5C286F496CB7D5E23F33F07F9555 -:10D1B00023105E25EFDC938DEBD5F97F452AC8233C -:10D1C00084D73B5696C81F7F79FA9573912E2F4FBF -:10D1D0000F2CE578494DE85FEBA17F3EEE0911EC9D -:10D1E0005BC24B30E506839F95FB314F68F62FB34A -:10D1F000F5519EA2B59713972F69FEF8D0FD0CEF5D -:10D2000029549621D1EBFB691383FDB480FBDF1B0E -:10D2100028FE599F0FD8A944C70CF081F2658EE60D -:10D22000EF01B87FCF02DF4FBC6212903E7AE8294F -:10D230009882768BB0E6BA95BBA0FCEF87F9FE6CBE -:10D24000C1F90D24EF8435A3374E82EF77BE6226F5 -:10D25000395FD374C9FA5B00BF9FBE66A2FCFCF3C2 -:10D2600076AAF7D1FDFE8DB740BDEEDF99C90EFF5E -:10D27000F4F09514FFF891D9E827983084F3F1F38E -:10D280001A3FCF3DBF86EC0FBD7C6EC36C8B4274E2 -:10D29000BA8EBECFC5439B4C9CFFF7FFAD44C2F393 -:10D2A0001C46F7149E7FE8866B57925E1B4BF6FE7A -:10D2B000BCB5567FA278D0E7D31583FC99D7D94C5B -:10D2C000FD32B08BDCE95A7F317264DEF9C1C407EC -:10D2D0004C5619C619CFD5E4C985F96D361BE4C97A -:10D2E00047F6C47E9097D3F93E6AEEF94B88BF7A31 -:10D2F000AFEF32FA3E571FB793F363CF7A364E4AF9 -:10D30000B49E9E754CA6FA1FB9128F7F52836F5739 -:10D31000F57C1600B95461857A4E1CFFCE55138BEF -:10D32000711DAE5421665DF35A16B140CCBAE66D5C -:10D330009E65A988E9B7070FCB0C783899BE90F0A5 -:10D3400070677AD911E49B8A35978E417A9CD7D23F -:10D3500048703E61F6FB50BE7ED072674AA238D854 -:10D3600093F1F869D1F003F66E710C7E74BCC4B70A -:10D37000EF7A7BDE6718D7D4F530376EFA82572FF5 -:10D38000BCE524869B3484E3AD0BF46D90E0A6BC31 -:10D390007014E97AADC38F74DD37FC46B1607FF05D -:10D3A000EBC37E057BE74B943B12FA68F11CB28518 -:10D3B000D3C14070EB1957A38392C4EB197B613D35 -:10D3C000554C05863D6E19880E7ECA545B3FEBB8FE -:10D3D00040073F37D0C1D88D4DD7AE847A1FA2BD4C -:10D3E00032A237FE8F5BD4948BF1DCA7C944E74AA5 -:10D3F000C793D4F49B79BE08E5F1F194D0F5784E4B -:10D40000A3E7176CCF4F991533EE070D008704F093 -:10D410001B3B4431F8A12ED04F9ECA0A27FCF3E8EB -:10D42000E78439F13DBECBD34B260C413B2594D844 -:10D430005FABA7BABC360D725ED867A2FE3CEECCDD -:10D44000FD2C0CA5F5E9C1D221E3317EF427B7A16B -:10D450003C387E5C207D5BF3F68A11A8D7E2ED04B0 -:10D46000D87F36E0B9E70A537288EC50A9721B9D49 -:10D4700083AA12DB5E8CFB94CA4DEFE5A3DFB08A72 -:10D4800052A6D9A12B4C23FD4DE497AD7C02CF4988 -:10D49000814864AC2FB14A3A3705415886F98D0E60 -:10D4A0007EEE5A25D9646B4C5CC2624D9ED757976D -:10D4B000FDFC3DF443DB5426A7637B2E3725C6EDE8 -:10D4C000AFFFC479C6E87B8B3928FB711F2AB032C5 -:10D4D000E40BB314A47B4E668FBB488DC1C3C2213D -:10D4E000DC7EB4B7B737E4407BFBEDBF93510F5AF6 -:10D4F000611CF4B3D9B2A4B3B1FE6AB33B42F7984E -:10D50000585ECC77B0AB9C859037F80160BEFDD8F3 -:10D5100085BF12FC9ECF901E6B383C26228820FDD2 -:10D52000F39C61AD2897274A75268C3B9A797B3E00 -:10D53000E537CEFE6A7867027A98B97F7507DA33E5 -:10D5400033F767CCC6F38399CEE1EF630ADB055B63 -:10D5500012B47F5960912648A7D81EA5B8C6973542 -:10D56000FF583BE663F462BB466F60E74CDB0DE9B6 -:10D570004C5BC87C47618F3F2D7EDC0D1ADFB79B6B -:10D58000236923910E601C5CC78FF787BF0FAA9F8A -:10D59000DD12095F371AF0732BEB36231C834CA680 -:10D5A000730FDDAF5BC1FC5A9ED1FEF42F8BCD6DA6 -:10D5B0004827F1FDDD12E5FDFDB81DFA83F4D6C361 -:10D5C000DDFF8A6A391891A73A584C7FFBFC871C0B -:10D5D000AC777FF170F64B36931A03574091180BD6 -:10D5E000F75EF01D547E0D1BD3379FF5C09BCF23F4 -:10D5F0001E1F9F6211F0E9234302BB906FEF1D12C3 -:10D600007806D3C5B66E9F047473C41D7C0EF34BAD -:10D610004DC1EC7480C7696F70441AC2A523F1F93B -:10D620006B3C7FE7959FDE827C736B8DC410CFAB24 -:10D63000F67EB005F9F2B419F808F6032FDFF341CE -:10D6400032D2CD1260C05879F24E553ED94F67F7AD -:10D650008CE8F7BEC93B9ABFE4558D4FF475DE8662 -:10D660000C08E3DDB6C741FB99DBAA4C17F6594815 -:10D67000EFB755F1F81026758CB9C96077D669E710 -:10D680006CBDFBC17D447C3F5DD5C16DC4F752705C -:10D6900002DADD27AAE76F43F9123F4FC5137C7BFF -:10D6A00008E9B75986B8DB39CD0BB6C5F2A15EBF24 -:10D6B000B60FF9BA7FB8B64E1B1F8F29DF29714EFE -:10D6C000A07B99F4678FDADE1562E861A0F158DE7D -:10D6D00094C005B940F7E545E64CEFDD5F7C3DBD04 -:10D6E0007F4FD515ECC4385C5FE0DC90F103CF9F31 -:10D6F000793479A6B5D3BFDB83218676A1FD8B4132 -:10D700006427EC1FCEFD0F9F6A760173C27A91C128 -:10D71000421B03FF1FEB8581E95EA67DB335615C8B -:10D72000519A47E274133954624B30BF5EFD452570 -:10D73000F675EAED1FCEA85F749391BF6B7812ED7A -:10D740006B2AAA6A699FDD08F203F541FC7C8E37DB -:10D750003DA2A01EB05B420AFA451B87A7E7AC8436 -:10D760007620D5C8EF634F0A2952EC77CD1F645F4E -:10D770001952707FDB989F49DFF5FE1A052E6775F9 -:10D78000BE68847DDF73E417F37B66605CE91BE1B0 -:10D7900069C9D0AE6D158B9A7C8C1DF4658EC27DE7 -:10D7A0006EA8DE42E77B8D0562C61CC8A7786DE4D3 -:10D7B0001F6B754567E23D5A559048BF865CCAD5D8 -:10D7C000C9E8DF5D39A403E5DFC13B2CB4DE359346 -:10D7D00044DA8F592F7E2F7405F67F17F3A35E6D01 -:10D7E0003BFF7C8B13E5F051D8CFA2DF103B0579CE -:10D7F000D436EDAC1DF773A918570774B3D91CA123 -:10D80000796DAAB152BF9B5A2DE589F0F77E864407 -:10D81000F5C34227C5070F66113BC2F58169333650 -:10D82000E641BB9C3C26E37E7E4DE1596DBF19303D -:10D83000F1F328DD8FC8ECDA79964D3BA7B2C5C667 -:10D84000173E12DA43FE43C7F4084FA789E47F8EE0 -:10D850009FC7520FF7E33926774C433DE1281699CD -:10D8600080FECD3C26E0BAE4696D748F39A780F55F -:10D87000D19EAF5B0E40FB62DE1E7D42F2D76C3F55 -:10D88000D7C3E30CD7A21F0ACAC366BF7035CC2327 -:10D890007C9D2CA84A4FBD6A0FD7AFDBA0FF28C9DB -:10D8A000D130ADCB57108922BDF9168B84A7B513A3 -:10D8B0008FD3B9C003C5BA1FD54FF3D85C73E4004A -:10D8C000DA5F9BEF6664276D46190AED365FC7C2C3 -:10D8D000FC3C8965A27CDBB4C0722D9DE71702FC7D -:10D8E000054A13CEFB4719365AB7EFBE07A2784F49 -:10D8F0003FC9CFEFDF429AB07E6D8689E6BFC91C73 -:10D90000CE40FF485F743143C387AF4AB3AB58C8BA -:10D9100083785DA7C187DD3496FB17A480121BC7EF -:10D92000D5A34FB81F03D64771AD83EB2CA48FC48A -:10D93000E9D199B8AED4020BBB2A07F98BC34D1DB0 -:10D940002DF2B833166E41FE6CBD289DE249578B0F -:10D95000610FDD132FB5D079F2C189E2CCF950BE49 -:10D96000BECE427E08C813BF8402B9ADC86F8EC94F -:10D97000A5E5F321BF41B6C808DFDA42D98E745C51 -:10D980001B106501F2EBCAF47B128CDE3128329950 -:10D99000EC0550BE2D43441F2DDB2608C4EFF58156 -:10D9A000D2D030F85E2FBB85583FC05E0DFF8BB2E2 -:10D9B000CBF67A906F020F8486291C97D20422310D -:10D9C000FA4B66D1F91873D35AFFF851BA0F556460 -:10D9D000A3FBB3DEBB42E574DFF1228B82786D3BA3 -:10D9E0003F7814ADAFCEA2203F6F10C25723DF6F38 -:10D9F000BEE3908A7E75FBFB4E8C1D66CECE4FAA91 -:10DA0000317ECC596C893BC76222CA717D5CE71BB1 -:10DA100051A2A74E21F8C764F2FF143615B8299E0B -:10DA20007902C273DDC56F15CC4D4017D0DE993E2B -:10DA300016ED65313A610CCA29AEC7982467C4E275 -:10DA4000778337F3CFE867DA5A02F3C7F1AABA6EE1 -:10DA5000A179058EFC14ED2AE7B18FBE4C3CCFD7DF -:10DA6000498F241F7344C531982E994EF6596C3D49 -:10DA700090FB8DD981BF7A00BEBB6AB8DC6FBE9DBA -:10DA8000D1BB13F8571003DFE64290D2F4000140F7 -:10DA90001EEB15CAE4475F2D2A9128C2738C8DE8CE -:10DAA00069080B925C8B5FAFE358E31D1877E4F0D5 -:10DAB0001BE77956C32FFE49E9745E819628B3644B -:10DAC000CCB1A3FCDB3D56C9C0FDF603AEC47AFE63 -:10DAD0004F197C5FB44B486C9FFF2DC3CEFB075999 -:10DAE000199D40A86214D70779319DCE6DC8C96DC4 -:10DAF00015B95C60D730D27B29459D767FCC784FB5 -:10DB00006BE3D01FF433486BC7E4EE680DACBF1570 -:10DB1000A816EFB5A578391C9D6A0F1CB1BEACAD37 -:10DB20000BF8A06644310251A6FAACCC42E72220A1 -:10DB30000DD5AFC41E38246BF5374D94041BCC2B88 -:10DB4000178021407DD7348BE11C45AE3BA262F9A2 -:10DB50004F4D4C499DD833FE9622165E09E30F0ABD -:10DB600018E19D7CD70B2BD02E8FA7039CC1857EFF -:10DB700031547C8EB15DFA2DBDF880E049F304D0BC -:10DB800034BFC1DA2C0094E61D921E1F4BF277BC05 -:10DB9000A943457F280624ED85F98F7CF28DC04E80 -:10DBA000C83707399F2517BCB002E9D291C9F1F4F3 -:10DBB00047F42D43FA0893FF8E713B6A95A8203EE7 -:10DBC000B64673498F3732A90CF1D458794444B919 -:10DBD000BE660FF30B02D2FF7F5B63E77753460EFF -:10DBE000C7BBA490FC937CFCFEE89A42D181F2F57D -:10DBF000E01D2F90DEDB724064C8FFA5BF3DF6B08C -:10DC000003E9FACF56CA37BF524972E327D04E4DC7 -:10DC1000E03F1F482FC7D7CF5BD226E0F944F6FC80 -:10DC2000C82BC3513E8724FF55888FF91D0184936B -:10DC300052CCCFD99CD3A3F44E88825A0D6C522576 -:10DC4000A4A5CDBC9CDD944AFBA8D1D6CE866B6042 -:10DC50007E8F3C2931D497266B24631EF46B7AD1D6 -:10DC6000899AA0D7FEE891E9D10C94E3499514066E -:10DC7000DD6B7E6F67703EF44D575E1D0EFDBA265C -:10DC80007358DA43430EA0BC449B19EF553854AE89 -:10DC9000E7D649E100C679AFBB2B68C1F199B67FE1 -:10DCA000695C52F138C2F984A6F758E57C7AAFC4B2 -:10DCB000A7F18BA38A9524DA673DE049E2F12DF7BD -:10DCC0008B07903F7C0146FA43AE8A4447687A1935 -:10DCD000272EDFF75C23EA17E76291D6B14EEAA858 -:10DCE000C17725D6DDC5E41AA5777FFF68FBE51966 -:10DCF000567E2E8A384EEB5907B9E440BEF9E62726 -:10DD00005E4708C71DDFB38E247D1D059D94D7E7B0 -:10DD1000B12D10F95AF3D8A0AD634D067FA7C851B5 -:10DD2000D849EFB3C4CBFB958E77E8FD9830D8EA9D -:10DD300026BA8F16B906F3CAB322E3F7B58CFCDD19 -:10DD40002BAFD155FC7785C58C938374C7F10C74C8 -:10DD5000A7D94FC077361401A2F215F93142FC9DC4 -:10DD60009C387AFCA7CBC5D87943FFC90D4CA0B825 -:10DD7000B8C54C29CDE82D179926176D4C8DA2FCFE -:10DD8000FBBF968B2007492E36C34A07C34E25B9E1 -:10DD9000BDE90ED4E3BA3C1C8F38C177A254F375A9 -:10DDA000A585B42FA27CD1C3AF36D37B43A276DE48 -:10DDB000A5C105DD500897CF3D8A419F3E84FF8075 -:10DDC00075EC6E4FBDB610C6DB589E5B84FB0B7BBB -:10DDD000E845B20F7C853C7EC557C5CFCF1D797312 -:10DDE0001F8FBD17B730C342F4B750A7BFAA900723 -:10DDF000C75987FDA27CCEB390BE7C8445B83ED483 -:10DE0000ECD3168F1647ACD1553C9FC4CBA771BF3E -:10DE10007397A27CCF10AC32EEE7503F1F4C37EA2D -:10DE20006BA4175D5FB774AC74A13F2C47F3F7E7A1 -:10DE3000D88C710E45995C5F7FA5F901568B95B41E -:10DE4000DF544B45DAC7E9F477418FC7C1311E7EF5 -:10DE500048A8AB26507C0CE5534ABA19F2EF56207D -:10DE6000D90D5066CB5034FB402638B7FE581C8B7A -:10DE7000F272777B851DFDEB82CF7635EE0FD70BE7 -:10DE80002C8A72737DC9EB1457D254053DC3A29CF2 -:10DE900005E22CCB98DE78063EA6FDAA43B576A017 -:10DEA0005F2B126DA3B885A6F0A1998CDBB10CE3B2 -:10DEB000529A0A56662E44F95E50568CF86DADB7EC -:10DEC00050DC8C5CC012FA11DED7F631DF548F398A -:10DED000F4FDE5E2C4FBCA6B32F9FE362281A8826A -:10DEE000F96415887EE4FFAC3A4BC2795CAAE1295B -:10DEF0002D93DF0F6BAD3F9441EF63899561D61F82 -:10DF0000BE60FA2BD363F031A90F7C78747C483A59 -:10DF10003E5CB3880F3B3B442E6F49AFAD63F2CDFF -:10DF2000A81FD54A0BD9B18D66BE2F6F2BD4F842EE -:10DF3000B6B522B17D53BA4E5922D23D1CEF449161 -:10DF4000F6898EC5CF515CD323ACFB1594778063E3 -:10DF50001A2FBE7D79A6A8C15111FCB49FE67804A2 -:10DF6000BCD27C36E7A7B7C6F2E9039A1DFD8087CD -:10DF7000F3E9E6FA87884FBFEE3C75B95DABD9D1BE -:10DF80000B02410BAA0355289B9A81FAF331E6470D -:10DF900038319393ECF20FB1498C5FF6CEACE0C20E -:10DFA000CC98F345395049EF165E89EF0A41FB0FD3 -:10DFB00022FC3EE80791E74BE8DDAD2023665EC01A -:10DFC0003A04627290A1DB21EF912254EE990F7313 -:10DFD00071D1ED48CADB6CA0176142A7ABF9FD8B8C -:10DFE0002EEDBDC8C7B5F7223FC6F721211DDDB212 -:10DFF000BAF4111C4F918228334EE27B9178FF795D -:10E00000E25B14177D0A646D930BE3617E5542F762 -:10E010004FEE65B23809F36B4B31EEF9CE97ACDABF -:10E020003DC98E9578EFE55111D60D6DD648A0EF1C -:10E0300087615183501943C7BB2EED48C173BED3CE -:10E04000911BFBF51FE3FD417A2F3393E369836353 -:10E0500029DD2F9BEB8CFAB0FD81DD4F3CBE09C65C -:10E06000FB78AF8DDE35D9E858EAC3F28F1F7ED337 -:10E0700087FAE2F4DE372D89CE27974891A9788F69 -:10E080006CB13A88AD84F99744665928FE64E7017B -:10E09000BA9FB6440E5AB0FFC52DBB293F65E71F96 -:10E0A0007C58FE6626D713A733823EF44BE4B5585E -:10E0B000A322E89F5DB9A18509CFD933456DDE2F35 -:10E0C00051FF1B1D2F1D42BC9C7ED84A7EB7030FFB -:10E0D000FF96FA3DB5F7459AEFC7BBDEBC15EDE9F3 -:10E0E000C58CF9519E9FB66B7E3D5B474AECFE7630 -:10E0F0009F060F3D7F3A59DB07670D504F3B8F61FD -:10E100004E803FDD1FE848C1FB851F9B831684C7F7 -:10E11000228407A425000794FB8B2202CD73514B68 -:10E120002BDDB75AB487FB071701BC082E2D0768F3 -:10E13000FE4732B9DC38B5F78F3E7A9F628F95F68D -:10E14000CFFABA1739833E848FBE5E80035FF7AE85 -:10E15000AF87A7B93A9E5AFE40F35ABC87CF6BF1FE -:10E160004E3E8FB97B004F4EC4D32CC2FFA9BD4C8D -:10E17000C17B305DBBDF3C89F6CCE9BD3605ED0ADD -:10E180007D5E59206E53C6221F717DCCF608A48F88 -:10E1900099D441E7394B6459C6F7092E94872D610C -:10E1A0002E4F3B4A8742F9D30F8AF48E25932323BF -:10E1B000D1BFFA61A67EFFA7C3877EB15D9786882F -:10E1C0003E3F4AD6E02D75F8307E66C3D0E0879991 -:10E1D000B1F878F7C591B8EE15A6CADF7A719C2719 -:10E1E000787CE8E7B9957FBD9FE63DCC70DE189F4F -:10E1F00002DC52F0FCBB406441BA97BCE7E5A4D80E -:10E2000073E82F33B9BEDAE87887EE239EC6F71C91 -:10E21000693E118AD31A1EA8F0E139DF47CC19C430 -:10E2200073D98F1F7B99E26DBA3274FF5307D53BC8 -:10E23000B5E7E5544C2BB4787816BE91E418C0B11C -:10E24000C13636917CD4EE1785F9BDB13302084C46 -:10E25000D4135B7438575A6618CE75B81CCDDA9C47 -:10E26000D34EFE9670E2FB66F1F237EFC14974AE11 -:10E270007C8E253E57665A9CDC0A5312C5DF6C74AF -:10E28000FC8CEEDF56A95619EFAF1CD7E4E27BDA1F -:10E290007B0B9F27A5A822D0CDF34383DEA169BDC8 -:10E2A000EFE156AC59E243F856E0B9076D6AB65D46 -:10E2B00087F1845D694C7B9F9445097E66BDFC5F58 -:10E2C00078B98BE78B873EB316ED13842FB7531FB6 -:10E2D000BD0EE31ABB7278791996437E566659E1F2 -:10E2E00050EE3711E81C89995D5D36AEC213C1A3AB -:10E2F000072E12EBD2ED6AA83C7B2823B8427F138D -:10E3000086D2BE1EFA1BFDEDFB03BCABB6D4FF8567 -:10E310007E6CFF5BFD44482F89417CEB0ABEF9B956 -:10E32000FE7BB494C94DAE6FDFFF3FDA7E852920B6 -:10E330007E8474384824BAD7F9BAEBE11145B8FFA6 -:10E34000B734DC1145B5D9955C6AC980EFE7147E16 -:10E350007E72FB831B0CEFA8EA69FC7BB5FA399E41 -:10E360006598F17C76D5502E8F560DEDF113E2B9FC -:10E370001C1E57D1C619FE9AD3291486DBE9AC526C -:10E38000C4F8C382761BBDD77B11034101F31FC5BF -:10E39000A222EAEFD1AC93F2DF411040BE882926D9 -:10E3A000CC8F63DD3E69189E3F4757A19D76C41D03 -:10E3B000AC43BAFDECE18E770428FF4966F0979DE7 -:10E3C000E8EF1CCAED5427988548CF32A64087A2B3 -:10E3D00063BA2791DCBF004F593A157BDE76831470 -:10E3E00058C7F9224BEE72F4C05997070BB5F7974F -:10E3F000F4F6279F7C2297DE1DEA7907BCDFFBC07D -:10E4000073AB163CF8D8B87ECA3539BBAB267C73E3 -:10E41000ACBE6FD3E0BC7DA868B00B6154B2E39E84 -:10E42000BA81DB4FBB2E0DAC7C14E56D8B89F6D326 -:10E430001FB5FC91BF8753C6C8AEEB6BDC8FE2F013 -:10E44000FED1F62732F97947D8A0DF173CFE8B9131 -:10E45000B1F1960066C53D81BFC341783FE457AD39 -:10E4600026A4D232F2C75858258F53C1F90EC3F7EC -:10E47000B822943A5907A529AC9B5299C9E49F4EFA -:10E48000657E4ADDAC8CD274562970FB2E44692619 -:10E490008B509A85F629FA7B5837A50ADEF88C89C5 -:10E4A000DFC8C513D361F8DE6E19FF1E171F2421C4 -:10E4B0001EC72590E7717141D28E2A92E7181794F2 -:10E4C000EFEEFD9E822EBF370C2DFD13CABFE787EE -:10E4D000068E20FD1C7EE6557EBF62AD40F6F50936 -:10E4E000FB748B02A87B3A3540EF80A8222BDB0E11 -:10E4F000FA7D8EEEFFC73F3D4E1881D96C3E151B4D -:10E50000BFC36CCE023C2F9EAD559DAD9D83CCD636 -:10E51000FC20F8CE19BFA7E7A7FBF6B3B5F387D960 -:10E5200071FE1716B21AFC282AFE03D6313B24D0FE -:10E53000B9C1ECA4E92F75B2BEE924A63FBAF757DA -:10E5400011E7871AD09F15979F13DFDE26305B3ABD -:10E550007EE7F4F4F4650AD975BA3F0B084EA1764C -:10E560000DD677C92F14BA32100BA7E42CBE6FB5A5 -:10E5700087AE4A49F4EE929ECE01FBCC9CDABB3DBD -:10E58000EC085DC8F7BA1CD6E93C0737B6C84705A2 -:10E590009684EFAEEAE91A4DDF37DD1F62386F7BF4 -:10E5A000F41E7A8FFA6EAF4ABE5A5B6198EE07246A -:10E5B00015843D6A82F935E13BCEC05F4DC9C67313 -:10E5C00093C5599CFF1767F1F3DD4317A597E279CF -:10E5D000F66A85BFEBBA5AE1BF47B03A6BA0F7C8FD -:10E5E0006D867BF2AB066FA57780EC5F6C63684F3E -:10E5F000DAA5C4F7526ED2E0BA41ABBF71F056F261 -:10E600009334E4F3F3FDF8FA07F21FA2F71F1B732C -:10E6100060BF8BE9FD2AF55F9FFF5039B6B7451BF8 -:10E620000DF7797F94C5E59A6D0FA747539E259CFA -:10E630008BF4208528BE40AFD7D8C779D2B42CAE92 -:10E640008F9ACC61BA27D3A4D9438BB31CEBC82FC4 -:10E6500097D57614F9F55C1EA3F3467BF4493A4747 -:10E66000B01558985DD07E0F00E33B0A23841F74D9 -:10E6700036450D741BF3EEBDA977FF755F853CB879 -:10E68000BEC69C108D3FD07A2FD5E0D9A8E9D746D9 -:10E69000BBF11C6DAE86EF2B75B8EC67244FFA8189 -:10E6A0000BD97BD336E75E8FF3B1ED1B108E86FA64 -:10E6B00039AC7C50227E8997FFCE4231EE1D2581F8 -:10E6C000E6756E8FA0BDBBC8DFB1E8B1032216ECC2 -:10E6D000F75F37571CBC1AE6B330E80C60FCE41354 -:10E6E0009BDBE89EFEA217CD149F30BC7316978368 -:10E6F0002DFC7D45FD7DA38B5AAC86F7A696B09880 -:10E70000F71761BC45C73E3AC6E89EB1F1BBFE6E45 -:10E71000C01AFC90204E2DFEDD8175597DBC3B500A -:10E7200098D84F13FFEEC0CE88487A6339C6B1D26D -:10E730003E606B29EE7BAA8E09E437E8CD87CA9646 -:10E740003C734C5EF0133DAAC94981ED09F8E94FCD -:10E750005E4E0FBBF0508DECFEFBD645B330AD6383 -:10E7600078DE547B9724E3B9766D3889EE97D4CA66 -:10E770006218E346BCC9A536F43F329728E33DB49E -:10E78000A9A6C974EFC972B7348EDE696D5BD881F2 -:10E79000F7EA6A3D12433EF6BA781C01CB10E97DD8 -:10E7A0009A3AF975D76CDCC739F93DBD6C99851576 -:10E7B00001EDBA00C3F365D8AC5446C1F4F20A8146 -:10E7C00028BE77C52659E5EDFC9D99EB8B26901F59 -:10E7D00098FE0EB44E8DFE1AC709D8CA10FF53EE2C -:10E7E00076933D18F69818C6011ECFCA21385A9262 -:10E7F0004BA36FE3FC663AC8B71B56C554C4C32B82 -:10E80000ADAB665C05DFCD6189E21D0ABEACBDF92A -:10E810002A68DFDD6AA1FB163A9C943AC9F07E8330 -:10E82000EF3E63DE12F75E85C462CA21FFC72CED9E -:10E830007C9295B3686C1CAF3BC00FDD6527BD5B58 -:10E84000D709FC49E71F5AFE4F5A7E87394478DFC3 -:10E85000F1B640FED583AD73B3495E3A966E73E070 -:10E86000BEF0283FC7EC4B3E3F9AA5E8EF7CD8B5F9 -:10E87000772AECE8F78AA7A7BA6AE6C738435BB8F5 -:10E880003D6914E2F7B0997E3FA05E938F9293CBDF -:10E89000719D6EE2D3FA38FAAB37FB0B4250BFFEE4 -:10E8A0004B93B66F3C797D7432863D28B4AF3667A2 -:10E8B000313FB287D9DD9129C33C46BD68F1E3EF12 -:10E8C000334C7DB67010CAF9512FCF24F9867042AF -:10E8D0007C4955163FDAC9D62AB75F1A87F59C449A -:10E8E00097679D16B287A42A4788ECAFD6091E25E4 -:10E8F000765F512DFB2533FE6E8D8DD2557DC8FB85 -:10E900006C9758867E578B662FBBBC5C9EBABC0E3C -:10E910007EBEA8AD739BA4CE407ADE0674837137A9 -:10E9200007EEE3F4BD3CC3467A73F92BC386F4E7E4 -:10E930001F7CBCDAE3CF03C06EBDAF82FCB625F707 -:10E94000BCD78874B73CD926231D9A52866F9C8CFD -:10E9500074FFAA99EE79D6264F5066C7F4674A9994 -:10E96000E8417898443513E979F8965DD74B939050 -:10E970004ED44D789F7F8CF75FAE9740BEEC4856E3 -:10E9800033F1BC6C82F7619E4F533709507E997703 -:10E990000BCF7BD54C11F253BDAD3C9FAF6EC2FC8B -:10E9A000F5DEED3C3F9AEBA31F789F24795E6BF672 -:10E9B00097A37FFA19987F613EBE93CAD3720D2E3A -:10E9C0007AF973F8DD8CEFAAF234BEFC05ADDDBE3A -:10E9D0003ECA7FA995EFEFA3FF97B476D13EDA1F29 -:10E9E000D4DAB5F7D1FE90D6EE701FE5AF6AE5AF89 -:10E9F000F5D1FFBF6BED3AFA68FFBAD6EE8D3EDA7D -:10EA00001FD1DA1DEDA3FC2DADFC585CFFEF68F5BE -:10EA10003BB5EFBEE486B7D05EF381BC427952903D -:10EA2000DC40FEAEAD55C544FFB5E3B9FED7E9DD28 -:10EA3000A7DD0BE8F0F2B8D20E2FB76F966B745EBD -:10EA4000724FDEFAC94887BFE3F714417F1CC57BCC -:10EA5000B8EA3D22F9F796BFC2DF95597E8F44E7A9 -:10EA60001B3A3DEAEDF5F987B579D669E9422F7F82 -:10EA70002F2347F5F8A7C7E847B36CCCDB809F305E -:10EA8000FEBFCECDF54CC13DA50D786E520B7A067A -:10EA9000D757EFB444D1FF552F4B545EE72E0DE10D -:10EAA00079BF2A4BA487EADDA9517CAFB9AEAED8B5 -:10EAB000F0DE679D2CD1FB31926B8A6DB613E5C6F3 -:10EAC0007419E5671D93534BE85C0DF669A84FAACE -:10EAD0004A65943B392E772ACAE55BB3F9BADA93D3 -:10EAE000BBEC788F42BA5FA4B70286CB12F17B5E93 -:10EAF0009D1856601EEDF272F2BF6E6FD6CE1419DD -:10EB00003F4FD4E5FC8E9F4D253D560B7A4C213D61 -:10EB1000C60615A5F7DCDF948E8DB2A0DE92334DCC -:10EB2000CC0C72F9803795C6DDFE20D75BF9A0B713 -:10EB3000F09DB56DC58CBFF3E6B1915FB742629EA3 -:10EB4000C1317ECC035E6EC733D3743FEEB3F3F1B5 -:10EB50003DC418F80E0B19F556CE007A2BBB0AE40B -:10EB6000654C7DAB4736E49FF26AEFADFA991FED35 -:10EB70009BA9CF6E267D7216F50943FDF2EF49A3DE -:10EB800050BF801EB1B2DE725097C7BADDA2CBE98A -:10EB90005A4D6FD4C6E98D81E5EEDF5F1941F42946 -:10EBA0001ADEA1E94BFE2EC73801A04B735020BDE1 -:10EBB000C2A420DDEF1F086E6673998CF6F840F052 -:10EBC00033A77DEA42396D0E4AFEF712DC931A082C -:10EBD000BE7A3D8B6DE816D46B9F1E5B51807EAF75 -:10EBE00055E68E593B916E854174BF43D1FC0E5B57 -:10EBF000ABF7B113F9F8FB3D7FD95C87BF8FC50236 -:10EC000032F94B324A156C67877DFA60B2E3F87EC1 -:10EC100093C9C1D042B4E75FB428782E70F819EDDB -:10EC2000FD06AF93E079E7EEBBA89D59A8F4F0F399 -:10EC30007E46F05E9D994A76B9B2C3A6D98D1FAFC4 -:10EC40000FE441BF62A780FAE7F7D95BD7DB501F1B -:10EC500069FB0198D9F770FF13095BB4FA78D19D6D -:10EC6000B1DDF8E334DCFF1C903CB176A8E97B53BE -:10EC7000B2F03C541E25417FEEAD96F5662F968B83 -:10EC80007AFB005E1E42F1A5E725C0C3D3ED5AB959 -:10EC9000EA5E3F05E6B3DBA28F0F06F5441C4FD4B6 -:10ECA000E829793DF6BFAB546F7F7A3DFE3E17CC25 -:10ECB000E75A13ECC1727D9EF5CE8C9EF97AB37D36 -:10ECC000EB6BA0BFD34A670A6EE396B4BE978E7A09 -:10ECD0007B7539BF3F8C0C80FE11FD1EF105BCED2C -:10ECE000B9414557ECDF0EFD674A21142D33751EDF -:10ECF0007200DC96ECABB499457CBFAB4CC5F7BB5E -:10ED0000F4764BF6CC223B67D9FE224A13B43B8CF7 -:10ED1000F767FE817636CBD718EF74F4F5A53B156F -:10ED2000BC3753D9E034517DC6FD5F89D7A7B73FC3 -:10ED3000BDF3F51FE0786794CEF46BA0F6EA28C027 -:10ED400025413BBDBE7EBFBAD81328F2C1F74F3173 -:10ED5000600CE59654E9C7FA115B88EEB1D9CDA1F4 -:10ED600032D42700FA30C629E869B12F8F9FA3C497 -:10ED70007D8FE7AF888D0D9E8EF2F22E89CEDD233A -:10ED800036D53106F2CDB04FA98129AD2C3A3216D5 -:10ED9000E3059AF73A49AED7DED5EE2944BEF25BD9 -:10EDA00018DABDCD977664E03BF875775BCA1F43F0 -:10EDB000FA8D2EF7DC1E638779B3791CB7D7152A35 -:10EDC000477EB4033FA23E6E34076DF86E8A9A21E7 -:10EDD000525CB51DCA5FA372AF56EE9F7615EDCBA0 -:10EDE0004419E7559F37675A29EA354F2AFF1DC254 -:10EDF000FC29E5F3A03C2C5B6424AF45D9153723EF -:10EE00009C9E96FC95C87F4F3B9D32C66381AC2487 -:10EE10007D20E5BB293ECBAADD77F216713D7F410F -:10EE2000FFF9B81EABF3F138FCE6E48E1B4AA05D97 -:10EE3000D2BDA2AC42FF8D773F5486F1895BEE3E96 -:10EE4000F2078C6F6D4A97E89D815D35D100D6EB56 -:10EE50001658471BFE2E52D58C0EDC8FAE658A826B -:10EE6000F6FA2E614608F573779AC4DAA07E529EB0 -:10EE7000315ED559688C97CA5A6CCC376607EFF665 -:10EE8000513C5071098E9326280A3E1D5CDCC12836 -:10EE90003E3F3D2F4FC6B8EE94E2B838D8C9C67E83 -:10EEA00052A718CBDDD3E3E2B66E32967B6E31E625 -:10EEB00033E718F3EFEBF4E8E1E70FFAEF3D6CB955 -:10EEC000FB71867ABAF18B4114CF8A7044BB3D69DD -:10EED000B8E4C77311AFA56326C6C1B19149642FC9 -:10EEE0001DF4253105F2D6A58CE4A935357200F75D -:10EEF000AB56512E534943450EBCEDC6DFEB32D124 -:10EF0000B96C3CFCBC5EEE1F7456F2DF858B485139 -:10EF1000B223ECF70C926BFCB8758CF3C32E8EC940 -:10EF2000F378EF2D3EED1CC5A3C7A9115E6165887E -:10EF3000B7498C7E3FD27BF77B6A14E6B156C9ABEA -:10EF4000443B63B5D849E3A815CE20EEBBD330CE01 -:10EF5000DB84F1DE2AA5F1F8D8A9D197C2E68410A6 -:10EF60008F9E5922C58FD41F4AAAC3C3977AEDBD7D -:10EF7000063D8E4DA7CBBD3E6E7FEE6E17C500FAE7 -:10EF8000C16FC96B437CEBF996A0BB95E2FA8B2A63 -:10EF90003B912ED975DC0E053D40F7B2F538313D79 -:10EFA000AEB0339BD3F707D9A2210E9CE28862E270 -:10EFB000C0E9E8CE8447172119CF7BBC456532CA2A -:10EFC000999FEBF72F18EF179F2FA47383E962E047 -:10EFD00022CD9F8E76DD606DBCC16E2940EFBBC334 -:10EFE0009C44A8FF20E3F507E7ED5981F7AE7623AF -:10EFF000E120FFDCCEE11C4FB719EDA1B2D1082F03 -:10F0000001F461566F3A167C2D741E587F2F4BB554 -:10F0100016F5A6EBF1266EFF742F5028CE72203A1B -:10F020003FE173713F76DA2619EDDBCCBC076BE864 -:10F030001ECCBD4C467D97D9DE7103FABDE2F921A5 -:10F04000EC4819CBE3E4BE991FDE64E2FCC18648BC -:10F0500084B7F8F8D2F878526FB64B3B87023D90F0 -:10F060008CF701E42B304EB0FB1E46EF0494BED863 -:10F070007CF3BF417F9FE55B6494D7D96F049F7099 -:10F08000C0BC3EFB45301BE5F456A9D3EE8AF17BAC -:10F090004A22BF7FD64B5E6BF4A1A0DEF0FCE3A951 -:10F0A00017E91B882B92973E4A467FD5B675BFB7A6 -:10F0B000A5FD1FDA2DAA3984768BAF5DCF67901D31 -:10F0C00096FD06CF8FDD9AB15E95106E8BC95F7489 -:10F0D000D03B97FC45D25BDC5F34DA1408639EFDBD -:10F0E000C54E71773BF6DE321FE3D5EAD3AFA1DF21 -:10F0F0003D1993CDF79D85D93A7F1BD72F590241F2 -:10F10000E49BF8EFC3B3F5F3C4B20F6701FE463FCB -:10F110006AA1B8BB02B1A22107F9A1D144F8AC3071 -:10F12000294BD7C4ECD3EAD34B2667A7D1BE8005C1 -:10F1300061C3A09C17581098CDE73E5E82F49A0DEB -:10F140006C86F2255BE506647655120BC6D0A97273 -:10F150005EA2FAF5E981C9D99ADCC3731FB3C6D29E -:10F160004FA796B159A897E11BEA5DF3CE247EDE46 -:10F17000E336DE8F349978BCC8D5DABACD78AE33B1 -:10F1800016DF7B13A3D631BDEB5FAFC149B239A304 -:10F19000A641E8277BED28DDBB8C3B07C6FD2DC5CE -:10F1A000E52C66E40745B850FE4E99BFDB5DC5E32C -:10F1B000016AEF63029E05D46AF754D45BF9EF0E3F -:10F1C000B34040C1F755688BA9E0FFA2C4BF1E1B26 -:10F1D0004BC5FA19AC83E218593B5378BC84F1DC77 -:10F1E000696B1FEF40E97E00A9CA44FB94512FDBF5 -:10F1F000F9EF4355317A279CDE6CC2FDEF7D2C2C54 -:10F20000093D7EB80EAF42EDF4F3D85D5FBE43BF5B -:10F21000C75C20B6055F23BB21596E43FD9864E4AB -:10F2200043FDFEDAFD1A1FE2EF490763CE8F7CEA49 -:10F23000718AB7CF66DD35B8CFCAAE4A35E0F982FC -:10F240005FF6FC50161C17DB6F98F3759E44EF7445 -:10F2500029E77D54BEB55A19A0FFDC3EFACF207ACB -:10F26000EABBFF2C2ADF16FDD4753D80626BF77B6D -:10F27000AE32A5C76E8D87B3EF3EA3FCFECEBEF8BF -:10F2800078720E17BB39E0BE01E066BF5FF4B7329B -:10F29000FCDD1B63BD6939E75CFCBC5CAF1F75DF3F -:10F2A00088F561DFDBAAE0EFE818EB9795BCEFE2A9 -:10F2B000E7EE7A7D3EBFCBCF1BEBC5E3277EBE30AA -:10F2C000AFB4EFC7CCEB0A9BD5505E3EABD7BCD2F8 -:10F2D0007E1833AFAB3CC6FAC19AC4F3BAB6C0DAF3 -:10F2E000EFBCF47ADF9BF8F5EAC5AFE3C669D63E1A -:10F2F000E0CEEBFFB0FCEBF5FBA3F9FDD7BBAD2AED -:10F300007E1C95E409C8CD0E944F154C5985EF84A9 -:10F31000336752C2B8E0C91A7F9C423F059E930EE4 -:10F320000DBC89F2F1A497C7FD1E7E666108CF610E -:10F3300096EFB52878DEE1D5FCD620781621FFEED1 -:10F34000B6C92E8C07147D8A763FAA2307E3F97687 -:10F35000EF387233C93D66B46760BF5682FA1A440B -:10F3600018DDCB780DDBA5C5C65104C8FEAB17FD73 -:10F370007FA47DD50FF8BE4A8FDF8FB5B3D8841E2A -:10F380003B4B8FDFDEA08D733E9BFB03C1CE570549 -:10F39000B2F3258A6FFEB9AD6303DE3FFAB9DBED48 -:10F3A000C2FDCC416DDEBADDA8DF6B18322BAFC8D1 -:10F3B00094005E17F44852CF7D098CA374E5E5D123 -:10F3C000BB1868E78D2DC47E395CFF07CA89A75634 -:10F3D00000800000000000001F8B080000000000FB -:10F3E000000BDD7D0B7C14D5B9F8999DD957B2BBC4 -:10F3F000990D4B1E3CC26EDE8100130831A095258D -:10F40000448C96D20D3E0ADAE292F094BC00ADF143 -:10F41000CAAD13121110356A44A0800B8A62AF681E -:10F42000E8450D08DE1035B5B7D886B6B6D67AF9F8 -:10F43000AFC0452A086B1FEAFD17CBFFFBBE339315 -:10F44000EC4E7655AAB7F7FEFEF187B367CECC79BE -:10F450007CE77B7FDF3973AF893156CA989A2F8555 -:10F460007609F05B666C4D19636EF8C9B2197B447E -:10F47000EE734B50FF88479255A8EFC9F232368998 -:10F48000B1BDAF994C7E0F638F7D3777A7E81B28FE -:10F490006F0A7A766079A489053B1DD888BC8CC137 -:10F4A000FDBD36D9BDBE048A529FAFDA09E5DDBF86 -:10F4B000B949703196398A517BB5CDD3D989898CB8 -:10F4C000BD6889BC7A11C7B35108ED82765EEA281F -:10F4D0009921C1FB0B4F336687476BEFBCEE9193CD -:10F4E00043189B7C529E86F76BB7BA1511EE37F422 -:10F4F00035CDC07E581353F214C6D2C569A213DAB3 -:10F5000049BFEFA8D20A437EB4C7DB158672648771 -:10F51000A0ECF462FDF292E5C5F0BCC3EF75C07CCF -:10F52000E7E350E9BE7B8619DFBBCEA2B4413B675F -:10F53000CD6C4E273C7711FFA60E5CE77FD75BCEE4 -:10F5400060FCF33BEF9C4FFDCA00B24C28DB641A11 -:10F5500087CD2BA7B640393D89D9EC13182B5B2DED -:10F56000F7DE85FD2F75CA3B01C6AE72B9F7873845 -:10F57000AFA62C5954B0F310C1416F7FA13F606119 -:10F58000D0EF98DD16688CD1DF45F837B633B63C3E -:10F59000BE2BB65CD21D5B9EF8466CF97998231B96 -:10F5A000CAD814DBF06D2701DE3D87AC0CC7BBEC7D -:10F5B0004C52C80AF03E60660CE7AFEEB1123E4C0A -:10F5C0005FE6F0237E9CF920698715CA87DF49A290 -:10F5D000E76FFD173B7FDED4F91C96D5E792193E05 -:10F5E000BF6C4867592A8CFBE5CFC45B02C57C5AC7 -:10F5F000666CFFB9A21DEBB17E6267990CF75F1CC8 -:10F60000CD581FD64BA17138CF17FF2652BB91673B -:10F61000ACA19DD0EE99FD4F3F87F03AF3CCF0546A -:10F6200001C67CB969E7C4F558DFE2F4EE84FB5308 -:10F63000CE3C9B138C5A9765BBAD31F35CE61568E5 -:10F640009ECD927FF513B83E47CC844F2B17866A28 -:10F65000BBE1FD954296A2623B16C0D3622C2BE91A -:10F660006EC0D7292E8EB72BED508EB3EEFAB5664D -:10F6700093C8821307CAC7D73D4DE3293CFD36E145 -:10F68000F501B36A4A4238AE13945D30FE0376D773 -:10F69000389682D7AC10E2CD3F794D343E98D70FE3 -:10F6A0001B102FDE14959D2C717F8519BFDF5A39F1 -:10F6B000F173EAA15FDF38C6CEFF21E9163F8CA3C4 -:10F6C0006053ECBA178562CBAB113E806F352CEAE4 -:10F6D000BE0FC793BD2683E884D1780A4FBF7B93C2 -:10F6E0000FC63BCCCA9A102EC67EEFC379403B3F73 -:10F6F000FA11B45348CD881745DE9E370DD641A385 -:10F70000AB97054E47F077DB70A0B76502E72FFA9D -:10F71000FD658671E8ED976A70F2589407C3B4FEF0 -:10F720005619D7FF83BBAB1E39691E3C9E5377FB2E -:10F73000FD9551F7176D5ADE9B09EFD5ED1D3A4146 -:10F740008C826FDD33AFA6DD0CF7CFEE96146481AB -:10F7500075739F7A600A3EF78CD889E3C57A3FCCEF -:10F76000F76CE7EB2E7C6ED156F704D13BF0FEE24E -:10F770004D57F92B0B07E079A974FA5239E773CB8F -:10F780003ACD211BD245E75B3386239E6E12943C13 -:10F79000E8A74C0A8A4877CE52BF599DCCD8D40BE3 -:10F7A000FFD63B0CEA1B0F4D2A5B0FF5EB4D81EBAF -:10F7B000BE8574B75D5476C16B2FFC7A455A306AAA -:10F7C0007D7A34FC5F7F631DB5A3026EE40153EFC5 -:10F7D00029AC998EE529C54CB0023F769D66FE9016 -:10F7E00003FB636F9B52193B7DF09E719289F8D1A8 -:10F7F000CD482767984B41BA3BE06CFA15F5B7C77F -:10F800004CFD4DED4E1190FF1E785250D63384477B -:10F810002CFD9D3EBDDA358DD3F52D01920326E6F4 -:10F8200081F6963C3196F8807EDFB87E4B43063AEF -:10F8300036E0C5096D5E889AD1F8657C6EC84CD5F6 -:10F8400082F458D70CF2228A6EEA4EB65B98637047 -:10F850003F8CF5E32F43FC05BC645E9AAF9DF80630 -:10F86000FC0936C0DB0FF0570E2F33E8FF5681A698 -:10F87000C6968DEECC473E274872455BE6007F6515 -:10F88000E521E2F367E1E77A05F942E731A47794ED -:10F89000A5BB50BEC8DDE7B660BD3ACA8FFC68188C -:10F8A00022295CD9F3C9C47FCF7AC34FD1FBCF8E55 -:10F8B0005554B87D1EE9C541EFB952A3F8534BE743 -:10F8C000ABAE3094CFEC1D5221BA106F7FE6C279F7 -:10F8D0007ED039A4C2E24ACC378C7C134646F07DF8 -:10F8E0000F7F02DE25F9FC661FC2BB0D842ECAB352 -:10F8F000214D254D71D64D7FCF63692AF122FFF846 -:10F900009E43413E9E6AAB7D1CE535FEF9E1FE1F3C -:10F91000DF18B213D7FF614DAECE17783F7A3B4365 -:10F920007D9C9FBC71383F250CFDFC917953505E46 -:10F93000ECC90964F8E07E46459F5F0478645CCBBF -:10F94000945678F584A87C5F86F558C0405EE2B591 -:10F95000346841BEC2DA86D278195366203C17CF8C -:10F9600004F897F032CAB7A5018BB21EE470ADC49B -:10F97000E15DBB5B08B5C258166C8885C7A20EEB6B -:10F98000005EE0FFB646D5433F4BA5D01A945B23FB -:10F9900040F318520EF8F064ECF3CB58378DABEE11 -:10F9A000D98BD67870FE8B06E73D39FE09383F616A -:10F9B000B68DC6B3728F40F2D563E9247D22B21CA6 -:10F9C000F8318C97FD9AAFC34D9ABED478E77CFF8F -:10F9D00002B89E6FAEF52F802A2235E4231D2984BC -:10F9E0003FCB2A3B7B89AF30F9C73767607BCC2F91 -:10F9F0006379A393EB7BECC95791AFFC85C99D88D4 -:10FA000087539608F4FE945F8B3B01C3D94DFDEB01 -:10FA1000172038D679998C707CC71CA079AB4B998C -:10FA2000BC0BF84A9D2DA0EB5FF2D5309F45AC8909 -:10FA3000E65DEDCBA6792E61ED54AE67610B1371D7 -:10FA40007DCB52105FFFC4145A5FD093983D753040 -:10FA50005E21FCFD51705BB235B6CC9E8C2A6723CB -:10FA60009CA11C05FF867D17ADFE38707FB45F1E1C -:10FA7000858AAAC746E3710BE1DF316D5D1EBD616A -:10FA80005126F2910751211EA635508EFC177E4D4E -:10FA9000A172B70DDA4F9AD85FA6FAB2D5BCDCB026 -:10FAA000E3C5C0A62B00DCE660A60C8B532B067AC0 -:10FAB0004D00D739B9C1154857B5267F9644FCC4C7 -:10FAC0009F1F8071B066BEBE8F4D682A6A8AA37F71 -:10FAD000E8E3DF2874769B908FECE7FA85B3346215 -:10FAE0008EE6FF1B7C5CBEA7F48469FD232F080C07 -:10FAF000F5DECDC24399B88E9B33BD422BCCA974A1 -:10FB00005FCB34E237C08BF2605DEBF7BDD73B1CB7 -:10FB1000CAA5557DB84C30EFC0F2D7919E2725710C -:10FB2000BD39B9698709DA4BBFA570422BE0E743BD -:10FB30003E2FF59334B1FD30B61359EE9577423B25 -:10FB400019AB55DF8A62ECBFA985F0B79AD1FDA148 -:10FB5000DF59D582CFDD378CA58AF81C6B11F0B93F -:10FB60003543055A8F35F3D99C1FC3556232E99D41 -:10FB700023E6C842CB642C374D23FCF2CAEE9F65C6 -:10FB80006299B5A5805EFDA88B919E39D424DE5282 -:10FB90000DD74727F072EA2AC1BF9388E121825727 -:10FBA000BA955509A9FC7EA89848D8BF97EA43346E -:10FBB000FEF4E94D25388EF41C7EF55882A65CE8EB -:10FBC000FFC851736835CCF388862FB7EDA8488FEE -:10FBD000E6BB47CEDA2413E8754732747DB6DB8185 -:10FBE000FAEC6D25D3D39118B373AB52705D3D59C8 -:10FBF000B1F5E7CDFE9489483F474586EBF7678727 -:10FC00003F05F5CFCB2D7CFCC6753FACAD67E3A7B8 -:10FC1000020B45C9B3C6391F939DD0F8A91473FFD1 -:10FC2000ECDD368622AE5FEE2DE99981CFD5B3BEED -:10FC3000358887F59DC92C1445179727C5EF57A719 -:10FC400087C64F45A6C6EDD7127BFFD3214C1D12A8 -:10FC5000EFB9B4D8FB308F9872D727FDF3C0FBAC57 -:10FC60003CEC0A809D3813E52894CF874CAA793C58 -:10FC7000AAF15CFE9D93C32ED4CF415E36E1BA9CBF -:10FC8000F386491E9E67AC0AEB2F37996EA9C6F51D -:10FC90009522AED9CE817EF47A7C3F7A1DCFCDB14C -:10FCA000B06E5A9F088D03E1A71630B6E5E04716FF -:10FCB0002FEA11070F13FC747C8986A31AC56FD233 -:10FCC0005AFBBA4D4057177C9FB51783C13AB447CA -:10FCD000E70B17DBFD2024D244530C9F482EEDE7A1 -:10FCE0001BC4A61E35893A9F79A872444C999E1F61 -:10FCF000785FA8AE04BE525ACCDFB7649B8EAE4686 -:10FD000059C6DA697C308F2C845F7FD966283BA086 -:10FD10003C36AA2C1BEA3D86FA0C4379047FFEACE4 -:10FD2000B33B0BED5777B6A55A023A3D9BD93D4FF1 -:10FD300080F286565B752594EB4BB9BC6E3828284B -:10FD4000246E34F835285CEF7428614B6D31C2A104 -:10FD5000AF17F94A5D97200B400F8ECEBDDD54C61C -:10FD6000F7BC51EF750AF45E5DE77BF45EC2F60BFB -:10FD70004D44E7EB0B8FF3E73ADF27BDE0DEB6E556 -:10FD800001646CBD662FF105B0E2FCC3E1C586AE2F -:10FD90006A16740CF0D77399FE5789BF1E1264A4BB -:10FDA000CF7E3CC5761D0374A13FFFFBB107DF4248 -:10FDB000B523F9B68F5A2478FE3FEADF9F847AE1B3 -:10FDC000EF3539B251081561BF5B58B008E5E0F76F -:10FDD000EAF30E9BE0B963E6F036E4BDD5D959D518 -:10FDE00012F0B563CEF04801E4FC75D945BC3C3453 -:10FDF000BC0DE1F92FD9A309BEC74686479AA0FCDE -:10FE00009D9D37F0725E781B96D59D7EFEFCD8F0E6 -:10FE10004811DECF51A755574279971C9FAEAFCE00 -:10FE2000E67AB43EBEDF4FF45764A39E57C7E5CFD2 -:10FE3000BC5BDF998BFC769E89C90CF8F4AEB327C6 -:10FE4000F6EC0278EC6A4E663B393A0624D087D34A -:10FE500039EA839C6827BE1EF1019F27E7515F584E -:10FE60008072F2249B77BD6F605DF4FED34737ED5F -:10FE7000C5F6D3E715931C117DFE67B17FFDFA76B9 -:10FE8000115CE1F967B365CEBF45939F9EBFCB1967 -:10FE9000C2E71FB4F37901FDD03A3BB475F95E3681 -:10FEA000E793DFCBE67AA4E2BB8ADABB49D7C7D7B0 -:10FEB000760E1D0DE3EA105827DA35EF98996A2778 -:10FEC0003D2689F4A10E1C3BD63F941952A19F9B5D -:10FED000051640FEA2F3930EB73F3335CAAEE928AC -:10FEE00081B263C08EEDA8F6672679F09A66421D4E -:10FEF0005FE74F1D3EFE9E2E9FD25B793FE90F16B6 -:10FF0000EDC4F9244B8CE4DDC239F93B5B483F98E2 -:10FF10004DF3677E7FA600ED9D5C9A6D4238EAEB5B -:10FF20007561A2BF99E62572BB5C5F371DBECF66C7 -:10FF300073BBB95604FD02F04EC90D527BA06F8C05 -:10FF400023C1AEE91BCF22D246C19949E14978FFCE -:10FF5000FF43786DC7FAAF0AAFFA66E023A62FC158 -:10FF60004734386E14BACDE99C8F90DD8CF7511E62 -:10FF7000DDE10BFE383B8A1EE6DD554F7AA63EAE2C -:10FF8000E43B5EAAFA0E433AFC80E86EDE3F25931E -:10FF90009D6BD40375FB4AD7571F4EE0AFECD6E6F6 -:10FFA000A7E87E596D1CC9C5E13DF703BC529953C2 -:10FFB000463E7ACC121EABC0FBC74CC1275EC27155 -:10FFC0000F1365E02183DA6BCE11A93DBB8E272C80 -:10FFD000E21AED19C093758027367CBFDA42F673BA -:10FFE000873BB47911E2C90D2314D54B7298E859B7 -:10FFF0006D4EA6FACB4DC719FA9923936519F54CA6 -:020000023000CC -:10000000C02BAAEF989B1F52B9BF40B593FF34296C -:10001000B413F1AE040080EDCD1D4DF568AF939F94 -:1000200063AE8DF73718AFB85D5DC078BD4FC3DBE9 -:10003000A5D984B769AD8CFB2924FFB8EA287D6176 -:100040004C0EE723C9A5E1177E8BFAE706BB92C7E2 -:10005000B80988FE0FD69E4EED01BE7C48F8C73821 -:100060005E2E78C0B983F33DA50CE17CAFB39DDD76 -:1000700049FE2B338D7FABBD9BF47093CDEB463F98 -:10008000F13C916DCCC7F65ACD32E28911DE2939A7 -:100090009CAF0DF667866F8FF667CEB3AAD62CACF1 -:1000A000BFDB4E7681EED79C97C2E94AF76B227D83 -:1000B000C6930BBA5FF3160DAF06D5AFFFAFBC1AF0 -:1000C00068EFFF6878A6F47C9A37DFC1E78DFE9170 -:1000D0001AFC05FDD6ACB2BF877ED01AD5DC6D7593 -:1000E000211FB9CA1F8EB2D3D8263E8FE09BE610DF -:1000F000C2A959621B9FC2F551F9FC572E0C2D8DD8 -:100100009ED7160B9F97FA4FCE98796D71B1255FE8 -:10011000CFBCFE3029765EA72769F362B634784FEC -:100120009373B7343BDF13C6C115E70557B60AE62C -:10013000553830AFABD1961B4AEBD9148F0EAF4E6A -:10014000B88EFF4BE6DBFE983FDE7C8DF3DC93E35D -:10015000AFCA994474D32D970EE0757033CCAB14AD -:10016000D77568A885D695E327632E05F9D8CA8583 -:10017000302FBCB6A4933F6B9ED5DB857E5DF6C366 -:10018000146D9E8CF8C0CACD23892E016F39DD3ED7 -:10019000C6E3412BEDDCCFB072B9ACA832CEFFC7BD -:1001A00064074780BF925ED21CCBD7BF180EF6AC57 -:1001B0009AE26838D8B2E617C75977D54AF89C68EA -:1001C000DDFF8F18B95DC849EC6763AB62FD14E8C9 -:1001D0006FEC2F8B83CB46BF07637FB3C63EAF2642 -:1001E000886F84BF178D47C7CC1A1EDD6927F9A316 -:1001F000E3D131279FAF118F1868D148C7FABC8D62 -:10020000709C87708C1387007CCA43381ED3EC33F4 -:10021000C0A73C84A34E07B734737E6084DB338968 -:10022000F9DA579B87018FBFEA3CF4FA44F3D0F523 -:10023000DB4DC2F2CD889F9B3299DC4A7A70782CD4 -:10024000DA491E4BA808C7B5C502F40BEDD668FD08 -:10025000932703E6F7A723DC2F7A5CEBD738AEAE03 -:100260001CDD2F1AEB376B7445B6A31ED298C4E57C -:10027000E1B9434EA21B961B9E87FAF7F9035686F7 -:10028000FCB54108E7E373E704FF7C7AAE25D98B20 -:100290007251F7379E7891FB1B5506F62FFAF982BB -:1002A000DC5FDAA8FE6C0DAEC3C51CA909EDCFC694 -:1002B000AE58FF1ACCCF85F33D67627DF87C83187A -:1002C0005A8A26EB460BD707369A5827AEDF805D51 -:1002D0007E3C9FEC844C99A13FA8C1F45EFE8A2825 -:1002E0003BBE41AB6FC8E2FE298C47939F1DBBF21A -:1002F0000D864BC386339F613CAD619F915E62E981 -:10030000A96EA02C5C14B0BDA87ADF003D913D8E93 -:100310007858C9427902FAD57839B9AA2F8471ED93 -:1003200046CDEF3AB4273C03F505676927433EDA2B -:10033000789ADB21530EEE7815FD6DEEAABE91A8DA -:1003400092346AF107A3FD33F9E04322FA8774FB84 -:1003500025CA1F55343BC61FB99ADE43FF16F61750 -:10036000C65BE8D796B89EBB51D373411F26BEB972 -:10037000B0BD80F461D45751EFD0FD63A887A03E93 -:100380003A27B7C2920BF3FC6B6E85903B89F74717 -:10039000763F3A5D267F0EFFD2E0A33F877EB2CF45 -:1003A0008F03707D6A8AC1FFBFE2A74309CF0F2484 -:1003B000D05387E6F6FBFFD3D1FFBF42F0A6239EC2 -:1003C0009F1283E4E75FCC54F21F2F45BF3AF1C17F -:1003D0006EF24BDFDAC494F514470FAEC172FD1212 -:1003E00026AF47BF746590EAD12FFDCDC93C4EE5DD -:1003F0008DC25F8C034597D96E28C7F0E93EF27332 -:1004000037400B5B14F423C43EDFC842D325C48BB2 -:10041000AE8BD698763A389C6ED1F065B39DFBB71B -:10042000A7ACDA21B2283F43CA04BFEF1EA4879FBE -:100430009AC9BFFA9FDAFAEAF0D89353918CEB95F8 -:10044000847E1F7CEE1E2BC9D99326B604F1E541AC -:1004500037BB6536FAB3EE66FE5C33E2859C15ED7C -:10046000EFD2AFEB0FD897209E4DCBE576807E3F45 -:100470009263A632F9AB493F4DA6F83BB0A571880F -:100480008765D9BA5ECCC6A19FFC3D8D3F35DCE8BF -:1004900008627B6113E767B372B93F6156AE85D6D8 -:1004A0004F2FF7FB8B343C837EA8BDA4892C26FEFE -:1004B0007743FFF30F697628A3F96E5C9AC4F5E8D9 -:1004C0007E7C37113F4B2E0E5882C44F2A889F45A1 -:1004D000FEE0F0225CAACED42DC579FC714E12C389 -:1004E0007C85055A7CA929D74DEDEAF1A438FAD7C5 -:1004F000CDDD9E0179A3E3A72E670E38F9BC2F3519 -:100500002FC078AD5A5F44FC5B1FC714835E92888E -:100510002E9AB57533C6C500AEC9C8670F98B8DD49 -:100520007500108BFC569D5ADC12EC64940307F6A0 -:1005300015909E3D5FF3A7829C24FB2A02F282AFB6 -:100540007770F3427CAE338FE2B9EF9943CF3C85AD -:10055000F2F610B723F4F53870607808E977CA9995 -:100560000B5908FF03A77F341CE3E407B4B8649D6C -:10057000A53B9FEC7D0BD753EB5CDDF908BF9735AE -:10058000BCA94B8232DC1F3934F830F21F3DAF007A -:10059000DF73D37CBC2EF4379CD0ECC8E36057E209 -:1005A000B8805AFA305E0AEB9D89E5C8BA74AEEF9E -:1005B000C1B8102F4E1C1A4BF3DB68E678ACEE176F -:1005C000C83F71DC1C39D50CCF1FCF9CC85A64942E -:1005D000779F3ED58BED6F179955C6BC8D4F3EEE7C -:1005E00082E7CF839D8B7EB35A53604626F28B17EA -:1005F000B9BD6E5C07947FD171BC732C92457EBDF2 -:1006000025D99D883FE70E16513E12F3C84C8572DE -:10061000E37E6EDF18E3CB27CDB1F86F6C17E7856B -:10062000FEB546FC8DF23DFAFD38ED7D51F99C3961 -:100630009C7F27C063AA37D8931B65A736BE924913 -:10064000FCF8C4FD9FD07AB2761E373D69F6CFC361 -:10065000F1B92BBB2D3551F8F83B8D3FD75AB9BCBA -:1006600006FE6B89E6377A7D59058B1BDF7F5BA31E -:1006700073671F977B83EB399EDFCE9E10915FFCE3 -:100680002ED74BED8DD2F2146E677F3A6C45FDA4E8 -:10069000B384F22046ADEA263E00E325FC3CB9399E -:1006A00085F823DBC0F175D10FADC43F1681FCE0A6 -:1006B000F636CFCB621B78FEC5A97B7C84CF65ABB9 -:1006C000BBCB881EDC4C41BDE4A5B6F75411EAE76C -:1006D000EF164A30EF6C7E9B8FEC945BF7F9687DE8 -:1006E000A7687CBDD6EAA73C33F6388FC32D78784F -:1006F00029F5539FCCDC22E97F210BCAE525BB05F8 -:10070000867435A593F3FF3AA9FB30EA91C6BC097C -:10071000168A8D2FA33C62517A26CA1F66B00B62DF -:10072000D75DBD24F96B9437E6BCF8F217EC3D4B6E -:100730001E5F572E27F60A9C6F68F2B71EE52FEA58 -:100740006A9ADCD3E5E6624D6E9E12B9DC5E647D8A -:1007500088AEC3F37C34CE5B311E4CF1CF8805F5F7 -:10076000934478315C1B978E1723304966E8005E0E -:10077000D49DEEEEB5929DA9BC8871EEBA55ACDB66 -:100780000976DA22A989E4C33099C9948F373D48A4 -:10079000E34A5F09FA39ACF3228CDD4EB874BD60D0 -:1007A000901E6090FFFAB8753C31EA7F535685443D -:1007B0008A33E533BAAF5F65D65982E3ADB671FDD2 -:1007C000BBDAE6E816D1DEAC349F8DB637AA257FBA -:1007D000791EC9CB11EE53638845306C57F1F9ABE4 -:1007E000464F1AD02B934B236BEE87F6CC6C9C09AB -:1007F000F9A4DEBFE89BB6B818E37A521FD92B2CB8 -:1008000083C9BBA0BFEB8B395C93611D76005CCDC7 -:10081000924AF033DB64778B1BD7BF8FE23291A112 -:100820008CFC74FA7A6D733215F31CAF2FE6F47DED -:100830007D31F727C3FB14FF3517C2FBD07EC501FE -:100840003BD1E5C7FB9D2194CF207746B9A13EED72 -:10085000F760A740F9DC0127E929E73479E1D1FD08 -:10086000B56C0DB5779386372AAB188EF60813AEA4 -:100870001D0E6367BA9E5CEF4E14C7D4EA7D7D37C8 -:1008800072FCB592BEF0B13BFC7D2CC37828276783 -:10089000B686578DFBA697DC85FC3BE05038D483A9 -:1008A00025A8FF58C5DB6EB401B06788AB2277225C -:1008B000DE8F74C85678A572D4BBBF990BE53FECA8 -:1008C00033332BE2CFAEEB52BAF135C99F11183B4F -:1008D000783C4B43E6E3E1283A5EB63BB65CDF1971 -:1008E0005B6E64D2F17014FF6F7E77E92F5E8BC26E -:1008F000B7BBF29C9E53C90C7D6FCA45A0A79377E6 -:1009000077B113280BC5EFA6207F5C00E41F4FAF23 -:10091000F8E4EE25BF780D9E932C15AD1C9FBC16F8 -:10092000A4AF1AD01BE2D9A125797C7DADD6A6D380 -:100930003B003ED697AD4A0BBC352B2FB801DF6F7D -:1009400030457A715DADA3CE8E437F76C5A80B94FA -:100950004FF0F13F3305E1F4B17D1AE1D3C79BEDD0 -:100960005EB4533BB21CDC0FFB8A1012B8DD326B55 -:10097000521AE68BD05C808F45D66C463E3DD92A14 -:10098000AF9669BA3613AD37586F70EDB0A86BD01B -:10099000AFDA0106648B82765E9F0B89E197B88E91 -:1009A00088DFE2B3161BFCF4B5F98B5AE0B9658118 -:1009B0002486797CD2675200F1EC5E6C2ACAEED9AB -:1009C0009DC7E54FBD2D6C9906CF355EB8AD6AA8C1 -:1009D00069C0CF6F3507FDC361DCE6AE92EEE17012 -:1009E0006B71F374B2EF80DF72BE7888F3C5C577A0 -:1009F0004EA3FBC2EC2A9AEF29982FC2E5D5CD561B -:100A00009AEFA9910EB2B74F6D13A8BC58B6501EFD -:100A100020E82743A679F0BE59B6B2C1F068DC746D -:100A2000EF9ACD50FFF34C910980FFEF6FFD09C5A0 -:100A300023DE67BC7F759F487ACFFB72A4AC1BE1B5 -:100A4000E96D7245DB938BB78901E4978BB7DDFEC7 -:100A5000F3C908B7D93795223CA6BA6F4BF33A06CB -:100A6000EA757D4F4A2D7F0AE972EA67D3FBA6A299 -:100A7000DEB50DE806C62D995810ED8FD7B65D4D41 -:100A8000FAF6E2EA2437CECFBB75D70C946FEF5756 -:100A90000F33D1BCF6084C4678B89BD3F0FE6241C8 -:100AA0000AC4C3AB45793C9E306D9443417FC3E299 -:100AB000B744C217A0B31B318E50BFCD4CFAFC6BAC -:100AC000B3DFF9CD5CCF009D09B337CD9A82CF3F1C -:100AD0006DA6E7FBF5A9AD1FBE8B7E01FC03C98E99 -:100AE0007288E067A43BEBA855F9382E23FD2D5EF4 -:100AF000DD94CFE3FB9746876C2BD021F0E3B34026 -:100B000027174D7F171DFEF952E8908D488D91DF14 -:100B100083F99E4ACFE9F1519BC2FCBB1C940FE3C1 -:100B200017805F8FCC97884E46E65BE839E9BF5661 -:100B3000EC7E13E0F4785ED0928F7A17F397A07C66 -:100B4000F646E40A74C53A34BD916DE5F9E1685F93 -:100B5000E0FA6F1CCA9E5A1FE59FC9CCD7ECC0BCF7 -:100B6000600AB673EE77177A71BD1AB2CE8E43BDA6 -:100B7000BAF1D33F535E85E320CFC7712811CA5322 -:100B8000327B02848F3ADF6F54B81C32CEAB2D9F7C -:100B9000DBAD8D9E08B5B3BF80D3BB1E8FDCD29C6E -:100BA0004471A12D9E909DFB5940DF83F667968A84 -:100BB000C4676CA5AD0CE5182B17299E33F5C22F21 -:100BC00018C6BF7E7EC57405F54A47E9ABD2109CB6 -:100BD00067B959AB7F7E6D36D4FFE28AABC83E5A07 -:100BE00091217A51AF9A599AA392FCF4F3BCDDA9F2 -:100BF0001752880E672D9D457AA53EDE00B3791DFC -:100C00008027B38158A3F39B675D61F73AA2F0EBAD -:100C10008FED4215D7ABBD29D78FE57EA1CE622ED1 -:100C2000CFA3E1B022C342FDFF3577DA6484EFD46D -:100C30002BF93A7CB0C71A5A0DFD7E608F6F47566C -:100C4000E5737F6BB6740DF1A5DBF658293E7F4640 -:100C500088FFFCAD6B45CA2B5ABA566021E8EF837A -:100C6000675ECA42BEFE875D2F65D5448D27D1FBE6 -:100C70000BF313F977BB1744DBDB332D3C2EC02677 -:100C80005863FCBB335D5A7EFE978C777C2BA19F0B -:100C9000FFA72370BC6FF6FBF9DF18111DEFE88F7B -:100CA0005B29DCCF6F8C57E596FFBB365E9E0FDD70 -:100CB0002C69E355AC3C6EB190C7C5571E1A4278FB -:100CC00037D3127980E259AF88B216D7F0DBE8FD4E -:100CD0000C5E9F605ECCEFCFF59491BF89C6237404 -:100CE00009DD4ED757981FE3710CE3FC6A0E8A7139 -:100CF000E3727F2D9079BCB3384276D5F1379EC030 -:100D0000C87B3FBEDB0FFA4CD179F4FDFAAC86DF2D -:100D1000D7217EC3FCEC6B7939115E27E25719F9B4 -:100D20009C8E75FC3EBE362705F1ED1E5B43B81761 -:100D3000E0E71753987D1894B5F8BFFA2ECF6315E6 -:100D4000A3EC1CA4836DEF3AC9CE6935373D8EFB09 -:100D50007ED41689ED82FB9EA486500B94BD662737 -:100D6000E54DDD91346B07DA7561507005287F928F -:100D7000746C07EA09CC96C2CCD08F5AA1BD6FB172 -:100D8000C9ADA05F3C96EC22FED2BC8091FC4E67C0 -:100D9000DD82000039989FCDFDB4CB5E1428FF188A -:100DA000281EF53E2527BE3EBA57A38B5F61020D74 -:100DB000C6E5A7C77FEE60BEEE179382E1283BEF42 -:100DC0005E41F112DF813FCC8F34B3BEB9C497418D -:100DD0008FFF05C883E1E28FC93F7BE2EEE0E3F1DC -:100DE000F649E8D705D3E3DBE9AF6BE32B6C174299 -:100DF0006617D1AF69470CFD6A713C679A0212060B -:100E0000E3B73C4E97CBF47CF94DE8B71F56CEC7FD -:100E1000E8F28719EA1719EDD7B0E010A4A729E97D -:100E200028DF562E8CF5A765D4ACCD24BF5ECDF758 -:100E300067A1FCDE6476AC1552F01AEB8FDB64F030 -:100E4000C77D115FC84848379333D0BFB16920FED2 -:100E500047F8D33A5F0E8902CD8245C7B5D35ABD54 -:100E6000BD41D483A6D9949DCA60FA61E54A06CEF5 -:100E7000ABBC80C34FA7E7460D35858302D9A58358 -:100E8000F9A106CFFA11044F7BFB1D64372597703B -:100E90003F76F2D29A20F29F64E03F68C7592C4D0A -:100EA00002ADFF146EB7AD147879E5345956E17987 -:100EB0008B4BCB97BD96E767AFB40783D1F1B4CB2B -:100EC0004D2BA645E7E5CA0CDE473E3C87F737D3F6 -:100ED000B68AE705074147CA1C80638506C7DCF26E -:100EE000249EA77EBB8DFC5B5BEDED345E9397DBB0 -:100EF000D935EBEDC4EF868B851437E93173FC509F -:100F00009D36A257A5E76DCA0F1B7E598657F4453B -:100F1000E1CF6DBC5EC70B66C82BB058BCBDE8BF47 -:100F20008381289897B252F0F656D0BCE488AAE0A4 -:100F3000BC35BE3C2E89CB11303733385C795CCC64 -:100F4000B05E8037DCAF3ED6C1FD462CE825BDCB78 -:100F500030DFC178B3BF10F96D4F3FDE7415C6E3C3 -:100F6000B70FBABDBD3BA3F18579D7A05FF53E139E -:100F70008BAC8F873F4AAC9D6FCC9333DAFB0DCDA2 -:100F8000D3039AFDA1DA683D2D647F34DC392DC08E -:100F9000ED8FC216F43F35AE024905EF4C3F28D81D -:100FA000B0BDC6392EB2BF1BBBF652FCBCA18A290C -:100FB000388C1ACD3FACCFF3B899C7F14066756253 -:100FC000FCBEC31DDE8EFBF23A96EA793C3CAF458F -:100FD000ED12B43C1E3DEF2B720CFD9F1D8297FC61 -:100FE000A0FDFBFB60FD79FECEA5E581398B033EBC -:100FF000B4C42FCF7BE29749932E218F563DD381E6 -:1010000079B289F3685FBF01EB6DB8165A3DA20152 -:10101000E8CB7AD96FF762FECE40BD0476A7AD4B20 -:10102000E0EFABD7DE709544FB72B4F2A147D01F5E -:10103000FEA09DC5F4173D3EC9D03E9A960EAFFE68 -:10104000FCB6D9D8DEA313B4B2FAB787FD30BE0719 -:10105000CDB1ED11CA68EF6341EFCF3BE6998E0D3C -:101060002306F476D0E3EF2E9834A0BFDFFBCECC7E -:10107000F6F1D057B2FC27DA07A5EBE18D1E9E579B -:101080006BC4F3F51A1F037B7806AAD6F7CE591E58 -:10109000C076FBF3DE0ECEF7A31DACE7BD35AE0A7E -:1010A000D07E28D0FB1F28C03CDADF9D3D7598A17B -:1010B0009DF901F9031A3F95B8DF19EC0701F0C556 -:1010C00076F021C21FB6DB1C42D74E875B65888F46 -:1010D0001D878449885F8C3565DD00B03F55E0DFB2 -:1010E00088F33897203EFE7C01B7DB1B0B2B36E7DD -:1010F00023AC9F1418EAE3EB0BFF487645C3FEAB25 -:101100002645EFDF5BDAF528DF07B6DB1C77DECF9D -:1011100017883C8F78FF0B143FF9202410CD2D91B8 -:1011200042EBD0DE5CB2C48496152B0DCDA73C59A2 -:1011300036C7C270FC8F1670B834EEBE4EC5FD8443 -:101140008DF00F48806D092C227D7BCB1C9B03E327 -:10115000D88D8535CB89DFC9497E34E58CE3ECCF6A -:101160007FBB3389F268D67799ABD04E2A03BAF8A1 -:101170005707F2D5A3BE1DC83F874C105B65CC3323 -:101180008CAF7FBF50C4F5873621A07EBB94E2228E -:101190002C3A9F795417B7BF7A0B2C31FEC9DE0267 -:1011A00089DEBB42ED9B8EB8F68A144E467BB89121 -:1011B000F93F42BF170B38BC1417629DE40FF4DCF3 -:1011C000ED25BBC9E609DF371EEBAF90C86ED2FD37 -:1011D00008E7F6A7933E36A530F82BC48B3231FCD6 -:1011E000C8B7116EF7495A7C89F395ACEB1C13D044 -:1011F000BE327BB83E63077D06F7895CB9EEE4CF6B -:10120000A6236FF504488F6020E470BFF9749BC07B -:10121000E32B06BD99C94A25BE3F43F34BE7C16A9C -:101220009DB2116AB65D1C82FE0C8F8AF07E032689 -:101230003004EAAF62FE365C97BF6A76E4460BD7AD -:10124000D7379A6CA4AFEBFA70B2A78FECC4FA4E02 -:1012500081FAA92FFC31ED1758A6E5A5F7E7874BD2 -:1012600061CA973F5790ACE96F6DDC1FC5FAC81F84 -:10127000C69EE5EB009A27E5D1EB70D7F3CAF5F6E9 -:101280002C5ABCB45EF3E702C0A8FEBF0A74BD705E -:10129000B5165FD5F3FE79BF4CF29645FB1D375668 -:1012A00033D647E3F2BA70BCF7A4054C85F0FE7163 -:1012B000C063C4B3E36B9343B8DF6BA3D0E7C7B895 -:1012C000875AC2E319467C4A2FE4FDA6F4446650CF -:1012D000DED5FE04FB8ABA62F715017F58FE3AF4A8 -:1012E000535AFA8E82F8FDA05B7BFF1A46F9E4C6DA -:1012F0007D45230ABDFF3BF71529827F275CC71672 -:10130000BAF9BE217D5F91C2D74BCFE330EE273AC9 -:1013100097D92DF1FCFFF0F65D242FAD6417BEFCCC -:10132000616F1BFA99CF975814DC479176D31B6DE8 -:10133000944F23484D188F34EA034FF8A65F563870 -:1013400009F7A5BDA850BEB0411F48E407A05869E1 -:10135000949FE89AC2AFD70F606FFFC485F87646B6 -:10136000883C8079ACEA21316E1EEB92C244FE00CB -:10137000FF9C68FDB44DCFF77227C5E43FB625C882 -:10138000F74AA4F74B09F3BCAE21FDADAD3FCFAB9F -:101390004AD7DF62F358E5A4CFB597F5FEABC2BEDE -:1013A00098B8FC3F6B74F2C5F3D4EC9804F34B642B -:1013B000B75D6A9E81110E6D09E4E83D85F1F7DFA6 -:1013C0000258648CCBB7615C1EAE92C054F29FEDA4 -:1013D000EDCF33E8267FF10B05E4F7B226CC33E0FE -:1013E000F967D2A1022F3E77AF39E0477B46DD6B2C -:1013F000D6E440E819F49BB41DCA243F1B2B0C8F84 -:1014000043FE28B96764E0B9066D1A7ED67DF93CC3 -:1014100083C791CF19F30C7684263C90CDEDE7BEBF -:1014200064D0CB76302EA7D483DCAF09E326BF5E31 -:10143000E4FE91A4AF0AB36D348F13AF58775A49C5 -:101440000F57286FA026439451BE7454979D42F9BC -:1014500075021457A4E3DA5B5791FD9A687D6AD749 -:10146000C6C671F5FB5F769D5E29E4FACE71B4EFD6 -:1014700049D0AAE42F5EB256384CF9BA8638723792 -:10148000F2109213B179011FDBA7513CF6FB0F5705 -:10149000531C56DFB7ABEFD7655ABCC5BB562239D4 -:1014A000E1DD2D84BC3E4E2626B2ED65139D1F0264 -:1014B000E26D0B8A4415A8E632B82D9804D453BDCA -:1014C0006D504E8779AD93D40C786EC7DBC9E47F3D -:1014D000BDD7E3D5F65170FB4BDD2090FE07ED92B2 -:1014E000FDACB601DE403BE1421E17F8B490FBA70D -:1014F000014542341EEDDAA6E551E8FDB53053371B -:101500005E4D02BFDE2B4B55F1F43BBDBD367393F0 -:101510000DE32D9191268A677E6CF1CFA178606AE8 -:101520003E437BB1CDD9B4B68AD7130FFDD81E097F -:1015300050FD37246E28306F2A8EF7371ADD18D702 -:1015400075617B6CD918EF379E4350CB8205993972 -:1015500083F7E5FF4693871FAFF769EBA250BCBC4A -:10156000CDECFDA50FE5E33A89E470CB080E37D347 -:10157000487ECD7657CE2139EC06FD94C6CBC79F69 -:10158000FD0D8F80F4D7E6E6F8F555C73DE81C81E0 -:10159000A27C1A6F1B1A0DD05FDB3A21C4E1C5C7CC -:1015A000FD65FDD559455FAF9C3A21284F75239EB7 -:1015B00039423F44BF5F6D8B55467E7646D0E87F0B -:1015C0009D48FC6CCB92542A1F5F9B477EA07EBA3D -:1015D0003DBD66399EAFF065F3B694228E173F3756 -:1015E000F8E16ACA85A3D88E11EE8850922E7FE06A -:1015F000D5E9D715CF40FED86062DE74D407D61A7D -:10160000F2430CF43CD51BBCB208ED0F4B5F2FE747 -:1016100053E17C89F46FBB82707BD47462EF4F100E -:101620005FF6DA29DFB06155E429F457BABDC1ABE2 -:10163000F0BDB377BE3343F05273A4279D3F5440AF -:10164000E775D4B419CE41D8109B97C2D6A6F2BC88 -:101650008F8ED8FBB85F3FE6BD41F92AED9ABE1DDB -:101660002C42FB62EA953CCFEFC3A5268678F1A118 -:101670009DE38F7ABF5393334A7EB45E5BA3D93721 -:10168000FDF871BF9DF0A356DBE7645C8F7AC40F51 -:1016900058B73A0D3F3E7CE1B27CC48FB37B2FCB71 -:1016A00047FCD8686EF7237DCDC90D2E2A82719D27 -:1016B000BC2AD06BE27C29FF52F0F676E3B8FE41FB -:1016C000FA55475122BDC3FBDDE8784B8F99FBC922 -:1016D000547BEC3EA19E4BF4AB26F68F15E5C6FA83 -:1016E000C70A73E3EA5736FBE7EA57973E0F46FB14 -:1016F000C4F4384C8F33F2C05351F05A69E7F928DB -:101700002B8B64592DC1F9D5E4D0BEB3DFD9949D9C -:10171000C2D73ACF183FE02B1772D6B4E338FCDCBF -:101720006FF98AE4EDBD1CFA7D8571BFA571DEBF3E -:101730002DE0F933BADDADDB81C6FE0F68EBFDB3FA -:1017400022FF21B4ABA75EB8487E84D3782E0FF475 -:101750006B0BFD2BD973ECA020D3BE352F8F8336B6 -:10176000EC5FF804FA5D9786B4F8E53E81ECF5A5E8 -:101770004F7E44F5E7BA6AA9DE7150E8C63868E3DF -:101780000813C96D3DFF41F7FF341E2C21BF8FEEBA -:10179000FF8171EC473F4DB2276221BE85F625BC23 -:1017A000D720F1F86E8387292AB2DAAE58BF899E16 -:1017B0001FB52560217ADF725008A13D9E6609FAA7 -:1017C00046103C47C894DFA2F18DB78BFC17905FA1 -:1017D000E9F96B7B72FCEF14F1BCB72CCA93D7D636 -:1017E00023D81F17E2FB2CFEF26BBECF229C805F3A -:1017F000FF67919E677B23E9CF7F618194F8F9E7CA -:10180000219E7FDE9FEFC6F3CCEB6632B6DECDCBFA -:1018100078CE4C3D9E33A370F9D96D909FD165CCA5 -:101820002FEB8EE29B75521FE5B1EBE7CA60BE5904 -:10183000F4F30DB84F2387E79DC5B4A3F1D37471BA -:1018400005C57FE2C45DBF1B6D7F1CD1EDAC127D71 -:101850005F4DC482FE9D952D9E08C6118E38B5FD44 -:10186000BE5A3EED4A7BE404FA3F563E934EFB4798 -:10187000FAF5FB3D56CD7FCEF1BE8EFF648D4B8ECB -:10188000939DDF88FBFA85017A9A99D02EFB692E09 -:10189000C6638EF4DB656FE4E2FE1B9DCFD6299C08 -:1018A0005FD475097C1F5667EC3E9CDCD15FAFBEF0 -:1018B000A03F97E8FD8AD189ECD92F8233E7B7475B -:1018C00012ED5FD2F8A40E47233FBA54F8E9F5FDB4 -:1018D000F003BA267E6B809FD18FA6FBC3589B4C2A -:1018E000FE32D0493A319F53F7877D5979F89DD11F -:1018F000FF33F2F0FBA313C9C3AFB63E89E4C4A51E -:10190000AECB207988EB332EB13CCC2DFF776DDC4C -:10191000C63C046DDC863C8423E6C82C7E8E05C064 -:10192000C737380F2121FE7D411EC2DF314F431ED4 -:10193000C2E7CFD39887F0F8A1C75C18AAC3FD6AA5 -:10194000E877E8D965A6F8FB0CD1E1E7F96122CF89 -:1019500027657E3A8FB3D16627FF82317F0E38D557 -:101960009A26D42FCB41EFC7FD3CDB5A492ED767CF -:101970008AE4ABC47C41D91B273F53AA4EE9F60E3B -:10198000CE13C3FC773A17E012F3C4F68EEECFD72E -:10199000F4FD9DF99AFB477F893C31258FF3A757CA -:1019A0001D7F1A127D5E66453118EAC589F3F47F02 -:1019B000A2D14DB296DF6B935416ED8F4AF4DE2F11 -:1019C00046737BE7554BE4ED4ED4ABA0198C7B6698 -:1019D00058C09A2E1DD8EF7EAA207014F394411F90 -:1019E000A1F53DB7FFB7E4EF7F3C93C99837FFB847 -:1019F00059A575568732C26B3D9F41EFE72ECDFF4B -:101A0000FD65F9CFFBFF60B9208DF9EF910B5F1BEE -:101A1000DF1994F7C4E9F1EFE037447FFDFCC4CC53 -:101A2000E341FA79175F28E7BE6E3E63C8D74834B2 -:101A3000AFBF1630C29FC23181EC31E417F3939FE0 -:101A4000F152E55F7229E843088F7D562F929A4D37 -:101A50003BD7826DC8D4FDA2FC7CC1074792DEF95A -:101A6000A19D8F573FAF439FCFE5630CF8F915ED6C -:101A7000582537F08D3130BF93D3FCB4EFF75E2794 -:101A8000D7DB22CFF0BC77E3F9134037FC3C0EEDF7 -:101A9000DC5FE33EFA6F1BC7F70F92DF0DFFDBE958 -:101AA000E812E5F7A5CF23D69E3DE2E4798503F65B -:101AB000EC7FDBBC2E495EEB79C665157D9ABF5F76 -:101AC00060E8EFD7FB69ECE3FB741ED2D653BFFF8F -:101AD0005BCDBFF7D618FFC388AFA5A5DDDB71BF0F -:101AE0004A0373318CBB3774DEB1FB4D0FDF7F4B84 -:101AF000E5421EAF640107EDCF7E3C2FB8750CC9DF -:101B0000C1F01AA4CF511E56867183F585B359AD25 -:101B100083F21042583F6A5578FB9BA59487D58481 -:101B2000F4AAE721975DFCD39AAA521A2FF97F3DB8 -:101B3000D6D8733B0E8FE1F24CBFBE3246D0E2AE38 -:101B4000FE4C1CCFD9257C3F6AA3C72FA31F598FFA -:101B50007B277BFB286FA0611F378ACAD056C4FA47 -:101B6000BB46107D35EC9B5682F150D6692FA1F310 -:101B70007E7FCFCFD93E7BE730F2374E290CBE8433 -:101B80007CC9591ABA06EDE851D00FC64DCFEEBD4B -:101B9000A62418876FA68BA92AC695D345D6F9889F -:101BA0003CC0B7C07E9E4BFEE23511F2633D3D86E0 -:101BB000DF6FF470B9DE78B09A2D740C941D9ED846 -:101BC000FD573F2BBAEA691CC7D363242D2F93E737 -:101BD00081FA400D43BFA1119F7C5A1E68B596E75C -:101BE000CC54DB407E73F617E781EAE3D3CB7A1E51 -:101BF00068F2A7DC7ECF962D9437E25CCBF92A5BA6 -:101C0000C5286E7045A46F7A0AC029B7A3FB0A8461 -:101C1000530A829DCE7F0DDF371EEE7B864857A08C -:101C20003F647BF3841ED47FA5757DDFC025F1B6AC -:101C3000CB15E8627C3C2F7082E480D454887CA968 -:101C4000E22D33DFA7B42E99F4CA8EAC3ADAA7742A -:101C5000EE1D6BDC7308F4ABCA566760DC217BEDCC -:101C6000AF282FC0B94F88BB9FADB2D8A1ED635A42 -:101C70009D81710CE7DA3EB51CDACFBE5F609A1920 -:101C80009D2964A07F5832A17CADEDE2E7DBD5B69B -:101C9000BB2B6C246FB8BF865DE1213922ADFBA65A -:101CA00009F984D4025A2CCCF3F2621E9FCEEB9039 -:101CB0004D28A7FEED33316E1CC9563CB0DF05C17F -:101CC000556F8DF466F806F27CF47D2EBABFA75FDF -:101CD000FEEC9B4FFE9E4BCFEB8EDC4C79839FA599 -:101CE000517C65A68BDB232088B4F35D62DF1F7413 -:101CF000BE8BA6B7E876B1910E8C79D2B9E5C388D0 -:101D00002E808F766E9163F85EDC7CE96689EBDD70 -:101D1000300FCB4A1CC7B40C05FD735F363FDD683E -:101D20004FF7EB399A5EA28FFBEFCDE7D6EBEB30A6 -:101D30008F3B8EFF43D76BDAF47DD09FF1F3B7462C -:101D400069F6C4F1F57F1DC7CF39D4F346427495C7 -:101D5000CCC03F097FC257AA8807FBDCA686628AEF -:101D60002F35503BEBF8F9FEA3D6E6AC2E2FC5ABD2 -:101D7000CC0480F7F103CB4651FC16E8222F0E5D10 -:101D8000BC3FC6CCDB5F974C782C3DC4280B52720D -:101D9000A7111E4B8F727C7D6F0CC72F3D6F4D8F2F -:101DA00003BE35263817F729F69FCBD19CC4CFE563 -:101DB000D0F2BF9DCDEFECC1F32EB66B71E09E5714 -:101DC000C6CCA6F8DC3A4940FBF063F7FC51E8BF0B -:101DD0005BA0E1B953EA63B2239A5E7B68FF60F6C9 -:101DE00021BEEF49D2F254A5759E1D889FA22F48AF -:101DF000FB24BFD1D62D521E947CF2912A2FDA1DDE -:101E0000110BE6AD7DD0224556BB497F8AF193196F -:101E1000FD5E4CEAA4BC9CE6E27FAC1DB2B138A1E9 -:101E2000FEF495F65FB02FF04F7D55BC4EE49FBA9F -:101E3000F47918F75D70FB84BDC2F39BE2CC2BC62E -:101E40007FF9B5CF4BF75B1AF3D506D131F77FE8B1 -:101E5000F6901E7F607E35269FBCC72C77A3DE835D -:101E6000F9B92F28A8573F6D8FCE27FB370DEFFB11 -:101E7000CFFD63213BEED73FAFED376692B216E35D -:101E8000A07788CE76B4EF5A31CF1FF54B84AF10D0 -:101E9000B5DFE15D27E53D344B7C3F0453F97E8A95 -:101EA000950B9B9EC6F757B6A4CB087FB5A2E979E0 -:101EB000DA2F61628156B87EA27DEF421F8F9EFFAE -:101EC0009F487E0ECAFFFF82FD0B9909F62FFC8703 -:101ED00086F7850B18ED5F606BFD3B705C1D2D1266 -:101EE000C3786F6A152F8F926CF4FD153BE6510F86 -:101EF000A1FDA694EF1C017862DEB61DF3A887E071 -:101F0000FE127ECEA130BB8AF02F15E0837A41AB62 -:101F1000999F6BA8DEE0207C9A5EC5E397A9010B30 -:101F2000F19FF34CA1BC7B15CF3FF3209EAD26FC67 -:101F30008C38D328FE9A9ACBF5487BC062B2F92838 -:101F40004F9AF03522E879D29CEF75CCF752FE7AA1 -:101F5000FF39870B19ADCFBABC1999F8DD8161D76C -:101F600059048CD7E872A642C38F8E1DDAFBF5FCAC -:101F70007D3C0711C7C756F2F7FBCF41FC1EAF6F80 -:101F800096C2748E10E830DA397CBC7EE5DC34A26F -:101F90001F51DBE7CA6ED2F2F4057EEED4CAB9C394 -:101FA00078BD8BF341766B9226CFB5F76F4F0D69F5 -:101FB000F1029E6FBFD4A49D1FD0CE62E2B91A9DDC -:101FC000A57EC17E8D8707F2EE899E5BAF9129AF1A -:101FD000503FC7B1C261E1FBB86CB174F542712AE0 -:101FE000C7FB72C586FDDEE2F3FBC6C6F50F87E6CA -:101FF00047F395613A5FB9D562B0CBD2395C5D9158 -:10200000ED7CBF97F592ECB2C471C5673263E38A89 -:10201000BB33A3E38AFAFA562CB1105FE9707B5FF9 -:10202000C3FCA32D005A3C17CF38EF2DFDE75B878B -:10203000ECA8971AEDC12309F28CE68FE5768F9212 -:10204000C00F317F6C22F992204E5B62FD6F8A37A0 -:1020500073FEDB93607F5F3FBC74BDC9668C7BA859 -:1020600097E4F7E9B1FD80F8A0BF5562F62BA16CAB -:10207000D88F067C90F8A2BADA2AB77A908FFE80C1 -:10208000F8623358AED628BE08E6E865C88F7BEE06 -:102090002EA4EFD9BC76B742D7F376A1531C8FD7C5 -:1020A000C83CD498163F77F8463CEFF9BC3392858C -:1020B000E743DFF3FC9BDFA1F2D0C8312CB73D270B -:1020C000CDA1725E643B9E17BDE5B935BC1E696C3F -:1020D00018633F187BD77754077D7F614D1FEAF760 -:1020E000A5863C7EC3F9B5B8DF14E793EEB050DCAB -:1020F000375DDBE7CB2A35FF10667A21DD65965028 -:102100009E9E8379F7F561FD082E77A1BE05CF4726 -:102110006DCDF3F13834E37C808DD0F238585845DA -:102120007F54ABCF4DEFF7EB77FBAC5A1E18EFFFA8 -:10213000E80BFC5C1F7DFF3263F248B41B1D5E168A -:1021400053D6CF8366923C12CF6F6DD5F0402FBF30 -:10215000941E0C8D8DB22B8F5E754731CEF3C31755 -:10216000EFCA457DEA6AED3B5046BC6A1CCFF17B65 -:1021700075F2DFE6211F7F5B7429E43F480FFE08FC -:10218000F9C6424FCB2437E04FA53C8DBE373345CF -:102190009D2B205F715FCFC7E7AE0C080B8B07BE8E -:1021A00043333428919F9E053B44D4B7879E0CC887 -:1021B000089F3A5B244B82767EE309BE80E3FC787D -:1021C000FE7BDFA7BCBC61478FE1B99247CDEDD361 -:1021D0005D884F3EED1C6126D1BE9ADEE1A3766A92 -:1021E000DFD3E1FB6BF2042D0EDB5D8972E15AC691 -:1021F000F116CB58FF4DED9CB419323F777346A9C9 -:102200008FBE8F368B4524C487196F075C0CE9E3BA -:10221000FA6069BC732BF42BCB307BA3E9E71A6F10 -:102220005419FE7DB330B6FC2D25B6FCEDF2CF0A75 -:10223000A2CBD592FF9708CF97052E7FD4C95CFE1D -:10224000C8AC7335CAC71F35C91328AEEE11542C5C -:102250008F796918E525B10C9ECF30DA951DE270B3 -:10226000C8D98AF38A809CDFE9C1EF2CF1F3AFD2A1 -:10227000DEB6ECC0F31598D7BB15E9F0457321E540 -:102280006DA6396AFEB585F41927CB233EE5DD4AF4 -:1022900078EDB479F1BB0F879D3C1FA1F52113C5E3 -:1022A0009B0497CDE487E7C49D1297FFCE25D3B159 -:1022B0005E2C83050159DDE3E6DF6D6A9DC4CCAB7E -:1022C0004B70DD94B7492F72DA28DFBFD255F85D25 -:1022D000AC175D163A0FE2B0B32CA8F5C7B0FD27D6 -:1022E0009D4BE87DE4D16630C87BECDCBF2E827D5F -:1022F000BC9AF74FDF67135730AD7F1BB360B986C9 -:1023000051FE7E8F5BE6E3BDDD44F110ACBF92C6AB -:1023100067A37AFDFCC281FDB2D3243AC75D605A3F -:102320007CAC85CA8F697CB0D52C1F463C55FFC05C -:1023300018AE47A5EB53A203D1E452E8BC1D3FCB36 -:10234000F5A431EEB380E7C534B91BF3D9C5152E1A -:10235000B29B51F3C1FAE1F893E85AF2B332CD35AA -:1023600043FDF98F231E8F125800D723388EEFA319 -:102370007DC2747413E55738025605FAB1DCC4689F -:102380007D95E4F8FB64C78FE3743A78FDCA323078 -:102390008F4370957BF1DAEA2CF7E2BE9F1EB7926D -:1023A00011882AC7599710E2CDC0BAD8BA4DE37048 -:1023B0003D142FEA175FDC1ED43B703E1A7F1DA62A -:1023C00078D10ECD75413BC0F79521F1E7111CC7BF -:1023D000FD8B9DDAB97AC6FA99E34C5FF73C0DF8AC -:1023E000F715E799163BCFAF719C61E16B18A79881 -:1023F00005E3730C8C0F7ED2395FD73A4C845FD7DC -:10240000EAE72D15C6EEBB30EEB3606CD566E4335B -:10241000576BF9A315C9FF4C7EFC6B40CF47B9D66B -:102420009BFC835CCCDF9C91D2D2C689A3E9EC42B1 -:10243000E4C73681F8CE3759F71ABC7F7E5AF0715F -:10244000770EF1FDDBC60DC5F3538305A950FED011 -:10245000DC9EBBDC477CF1F67193709C11A2BB6BD8 -:10246000F17B6C487733436D58863E9AE8DC2DA0AB -:1024700043A45B9D0E078F1FE8129E1FDEE4A2FDA2 -:1024800050DB58376D68CB60ED02F7B73491DC62F2 -:10249000DE9103F304A29D616BA279FCA44525F9AA -:1024A00070B5FB1109CB4F2AC1F538AE39E33FA215 -:1024B000F3F259C6FC02B43B61BCF7E13CFEA7C68F -:1024C0003B789FFAE7EFA3F847D9A3CF6B74ADDB56 -:1024D000A39E24D027609C5EC1A530D01FFBED5386 -:1024E000B38DF21206F6F5466A69FFB09012407994 -:1024F000A6EFEB35F2DDA95772BEFBE17297B29AF7 -:10250000CE39DC4D7669E3F50E7DDF2FE95F8D4B2B -:102510004CDABE5F81E44A03B3D1B943FDDFAB833C -:102520003F216DE0BB1E0770FF6FE9E7EDFFF5D2BD -:10253000FE6275158FD3F7DB77F532B75FF5EF43A2 -:10254000DC9EAD9FE3CFF594E5EC4BD9B771F60572 -:1025500093DEC8524C9AFDCAF5858EC95E59651442 -:102560005FE57AF85C0BD56F4C0AD1F7566AC576F1 -:102570004292E3E3DCBADFD34EDF65B228F9C82725 -:10258000F438EB9CDCE07F225E2F2CF66709309557 -:102590005A0B8F9F021D6CED83B7AA58D393F8BDD9 -:1025A000AE6B58D3AF4D3944076710DFE78CF9881D -:1025B0007FC76B800ECE623B36C6FD01D76A71A223 -:1025C000973F7CAA0DD7FDBCC0F8FEAE42E3FEAE3D -:1025D000C09FC7F17896F63D9E58BE13358E936620 -:1025E0003E0E8F28D2382EC41BC7203A6421EA1F22 -:1025F000D6B789F69F1BF0C8381EE1E01DB43F6EC8 -:10260000EBCD4C1627A31CEFB3233C472046E4E058 -:102610003C83C9E327913C0FE2B968BA5D3D68DCB1 -:10262000A283D6F5C6B9FD793AB332CB304EC4FB9E -:102630007D2CB9E151F47B34DE6C26FE5E7D702C7E -:10264000E969BDAA55C6244856C9F36B14F80FC7EB -:102650003587F9AF72433BD7C9D574CEDAF5338DE0 -:102660007939EA3D4DF0FE0D5A9ECF8DD79B8F47AD -:10267000EB9BE7CD1BCC0807B5D6D1244EC1F6A401 -:1026800081F77D83E132E89CA736CE9F18E839D8E0 -:102690007E6B7927F1A7447C6AFC787E2E14B455B2 -:1026A000F077E6FB5C36FE4BE4FB4CD0CE857ACD72 -:1026B0001CA1F33B5F1FBA78EB729867C10F8BE9DF -:1026C000FBA557A52D7DF221283FBD6534955F4FB1 -:1026D000BBF9B6A358BF3D9FCA95A68FE6213D140E -:1026E00096CDBD16BFFBFA9A9DB7939114ECA886C0 -:1026F000E732C6654FC003612A2D117AEE9BE3EBEA -:1027000027A23FA63289978F94FC760295B3B5F243 -:1027100084974763F935E1A379F1F8E29842A1BBC8 -:1027200008E46D652A7F7EE6846786A11D5F59C136 -:10273000CB639469EB72B0DEF4C779F1F4A505E3DD -:10274000F97CA75E38DF36C4836161FE3DD297FC19 -:10275000EFD1F73902206F71FF7EA09CC7E102FE26 -:102760001209BF0755E1E7E5E98E964CE483B38291 -:1027700096528CBBCA0E5F1B7E1F31A57CDA245C8F -:10278000F7E9A06E639C13E86B09C27FCE651F65F5 -:10279000B9482FD5E94B3613BD273EA7B19EAF5B95 -:1027A0002C3D407B2B906EE65C1E2B3F07D1AB018E -:1027B0000FAFB58DE0780772D15A3E985E8DFC9BC5 -:1027C000ADE914A2E9751BE2A54874BB1AC76531CF -:1027D000F579F1FE2841192D7F0EFD9E37BFEBA341 -:1027E0003810DC102F8FC337E04FD2F57C3E0A59EA -:1027F0004EA3FC659ED773F0B7F43E6E071133A964 -:10280000FF8771FE6C0D1FCF363CBF44447B2FF811 -:1028100004F289860CFE9D498CEB239D66E8FCAA98 -:102820002B76BEADE5CAAD6E71F0784D360EC7EBB6 -:10283000357DECADE6C0D01218EC8DACC98CF37DC3 -:102840002CD9A5623CB7B1869F43F92FE9C1271166 -:102850001EA2493D1486F242E6E7DFAF94FCBBC6F8 -:1028600047E95F0DDABA34D8DEA57C36FCC3F351F4 -:1028700006C1A3CBC84763E73FB02E7D9978CDC48E -:10288000F35772709ECA5A31CE7C98D4B42EDA4F68 -:10289000FFD817FAE919F7B72856ED3C95C8BC6878 -:1028A0007F5CABB3E9F1683B19CC323A07E9484B9E -:1028B0002E8B8777BA9E7444D0FC5AA0F7A23EF0C4 -:1028C00049D2DF483F018A0998B3D0AF358BF4185D -:1028D000C16293317E9D519341F8BA09F412F4B369 -:1028E000AB159D39E42FDF2E323CB760000E30125D -:1028F000DF007E7E383E9B7FF7AB1F1E2AF1518B97 -:102900004988AB5F7D38DEA49D9FCAF79736D8AC67 -:102910003CFF53FB9E859EC7D2602B5ED344F3B32E -:1029200071FA31ACD3A0BC16639E9C2D9DF40B793B -:102930000253501E0ECE8331DA092ACDE35BFDF13E -:1029400005C6F59F3B9DA4FF7C4B8B2F08B33FA58D -:10295000F54905FCB27A308EE015D05E492D3D2A4E -:10296000B1B103DF9FC4EF36A13FAB2B3BF87FC76C -:1029700047C5E3DF9CF434E5851C33F138A8113EEC -:102980006685C7816416A67CD5068D5FFD3F379CA2 -:10299000204A0080000000001F8B0800000000009B -:1029A000000BE57D09785445B67FDDBEBD25E924E1 -:1029B0009D104242583AAC4102762721806C4D80EE -:1029C000880A4C585450841B886C59059D41C73166 -:1029D0001D02880ECE84272A4F511B0444079846B7 -:1029E000D9D4C8B48088CF2D6E336E8F495C5925F9 -:1029F000864171C637FECFEFD4BDA46F13067CCBE2 -:102A0000F79FF73DF8B438B7EADEAA3AE7D4D9EA37 -:102A100054B5D8633BD19825F8CF8FDDF0FF4E49F0 -:102A20005FF61542053C02704088F642ECEE50E439 -:102A3000F052795269C847E5DF7ABB8518807A2D54 -:102A4000B3A89F1049EECC91491E027FF8F1C71F31 -:102A5000F3859882AAEE427CDA5D4BC47BD78BA2C9 -:102A600031564588E4B19A4D73093146A5FFE50911 -:102A7000D1B245093AE8F9687F8C45A4085179C874 -:102A8000160C12BCF055EA84E0858FAA4141708B88 -:102A9000F0AE6944FB80C31DA0F2A1B8FEBF1D4A81 -:102AA000E5678FDABC0EF41BF0BF9345FD96A05F7F -:102AB000827BAFB1088F539F17FDD727182B3C5946 -:102AC000AD70DFCDC926B85FA8A3A9FDE57BBA9993 -:102AD000EA7DE1CB4CF5B987724CF080862B4CED4A -:102AE000077E50608207375E6D6A3FE4C824133C5E -:102AF000ACF90653FB11676799EA4B130A0F2EA630 -:102B0000F91E4C538532488891A2D4D4BE542DB3BB -:102B10000B0BFDA3CEF66923BD57457F999EEA7442 -:102B20002BF07C668F22DA650A31778DAC37DE9B1D -:102B300057BF6A790695F383E6E7A5C2DA0AD37B25 -:102B40008B3F99FFD68188FE7AA7145B92A8BCDAE6 -:102B50001B9FF2651C262C06FEA8325DBD61D0E9E4 -:102B60003DD5EB90A4603A2FDCAA04EF253AF6128B -:102B70003D1F02DD88CE22E8015D657DCB5A351808 -:102B8000A07EBEAB9EF7D6011BC18772D73412FD63 -:102B9000E7D638DC2AD53BD2CCF48CF198E91997EA -:102BA00065A667BCD74CCFC441667A26F9CDF46CD4 -:102BB00037D64CCFF645667A76986AA667BA66A687 -:102BC00067C63C333D3B5799E9D975B1999E9981C8 -:102BD00005A6FA68FEEDBE62A1A9FEA1B8BD5F6AB6 -:102BE0008487948EAADB414BAF67DD1DA6EF097584 -:102BF0009C7D19E1AB344315AABB950F02F457AE87 -:102C0000EB2A5E5F73880F1E263A9C112B0F6678A5 -:102C1000CEE7878A3DABEC589F3F951F7E0D3EE87F -:102C2000DBCA07C47789F8CE8FF833E2FCD2A0F371 -:102C300044AB7F9597E4C806AFB61AE5D4DEDF74DF -:102C4000B192DC1045C5BD8BE2857089E619E0A71D -:102C50000A91E0BD17A5F3934CF00BFE38D2E97F43 -:102C60007ED1C34A785374BC892879A6D4FF29132E -:102C7000F35E4BCCA8A2FD849002F9D54934A4435D -:102C80003EA58B2A05659AF0AE50316E4FE756F996 -:102C900097C184B184E9FD0F4B6CCCBF4BE2FA6F56 -:102CA000015F7E502BF9F2349A0C16E20611B2E164 -:102CB0003B1FC63ED219FD1510C295C1A8ACBB0979 -:102CC000E39F8EF17B85B84934DAF0F19942D8510F -:102CD000160B0F97B385DF8EF76F16E1E598CC1FC3 -:102CE00053B45DC04785AA754D053E3A3574819C45 -:102CF00015AFB7C3A02F8857435EBF8B7F52BBE38E -:102D0000DEA2BDF8CE28A7E7D607083FFB2C625EFF -:102D100088E822C6B5E3710B6B51BF49FDDAFACEE4 -:102D20001296EF2F289A067C07D29DDE8D40725AAC -:102D3000E81985E67759B227E7DEA4D6F66F782D35 -:102D4000DC9E582FA050FBA777C432BEFA76589766 -:102D50008C79FDD47E3FF4FADFC3B88DF6179BAFB4 -:102D6000DDEE5D701BF5DBAC88AAF53488F774BA2C -:102D70006438887F68BC196A82B716748B9B71B0FF -:102D80003DE1A1A283F629F4D2D4EBAF5A0E58D973 -:102D9000D7CEB390C677AAB8311FE325FC7F89FE52 -:102DA000CB9C847F9ADAC9CE5AEF44304591C43F18 -:102DB000FDA35F519BE397E339A0E37F7707ED1411 -:102DC000FAD96769E8E2051DAD0DF94C47B79CD704 -:102DD00049BBC4CB85F05010D7793AF05FE27078E8 -:102DE00055C2678122BFFB79E2CC199534EE9B2D49 -:102DF00045A961D534EEFFE071BB8ABBA663DC3622 -:102E00007DDCCEF63ADE3DD95857171A772DBE4FE6 -:102E1000780AFC4A096ECCC4F3F05380770BB7FBF9 -:102E20005E1FAD398BD4CBCD354A703DD5BFA5E300 -:102E3000F9511BB5C3BA748AE41A1ADFCF862D5B29 -:102E40008776BFD69C3CEE8DC27BD9EA4CD043B08E -:102E5000BCCFB85B09D6123C4B7899EF4B445197E5 -:102E60001DD42EC3A7A5FA681C7F8EFBFB804C0BDC -:102E70002FE301EFD177762DE9E0BD17D0D04BE3FA -:102E8000FF2C921CE87FD278A9776ED6F1364514D4 -:102E9000F13ABD4E5471490BFE6405B59B4AFFC221 -:102EA000FA24B81FC6370DB0AF755D4F170D5CCE55 -:102EB00010EE171BE95BEFD474B8ED766A33C9D214 -:102EC000DCC5AE629DD2BACD64FCF7F311FEBF1D26 -:102ED000F3F6610578BF93E418E8BDBAFD25F1F17A -:102EE0004445E293D6ED00E081D66D9ECF12B17ECF -:102EF00046B797FC6775F7FC47EB870463427AAAED -:102F000010574A51281E3A9D2052689E0DDDD4A0CC -:102F100023137AFA4EEB0E9A6703D9130ECCDB5FBC -:102F2000DCF114D58F257D7BAF94AFF1018227F8BA -:102F300055712FF341E3D2F9F4FCF541544FED5FA5 -:102F4000A911F17904BFE2B3796B890FC79CD50E43 -:102F500024523981E47E985A5F9DB66A34EC83B17D -:102F60009D488F44E889AB7B98615A089D40A76BC8 -:102F7000747C8FCB36EB9D09D03B46FB36F40EC9F3 -:102F80005715F8BDD1A7EB9FCBC465D03FFBABF77E -:102F900088CF48BF187A6814CD30947D613D64B500 -:102FA00017CCF631DE3C76AC8F59566A0F7CBBB538 -:102FB0008E1323D6CB4BF90AE3D7438AC742F37F5C -:102FC000EB901A047EACFEF010E06FE18B0AF3E99F -:102FD000233EAD02DFFBDAD638077CD330343751DD -:102FE00050FF9F56D3407AD3FAAD760A3FAD852F76 -:102FF000ABDD0C1FA94EE3F258B587CB13D5595C56 -:10300000FF75B597E1FDBEA25FE07BB3567C63D54B -:10301000B2D17F15DB478B6AAC02F45A14BF50C2A1 -:1030200036A71B42F8EECE072D7104DF1D54BCD02D -:103030008BF3770497C34C2BADF7DB5D042FEA9C31 -:103040003CCA85F60F28CCF5730E551DC474BF7E9F -:10305000EFD3EBC68BD6F9969F5584464B2E7B80DB -:103060007F39FAFFAA7A108FEB68B59FC7E5AF6F7B -:103070003AD88EBE77BC7A2CC3FFEE2B5A09BEF528 -:103080008B6FD88E18BFA5C90A3B638C5FF183CEC6 -:10309000C3FD2218247CADB149BDB286F40AE4C058 -:1030A000C87E931EBD5540EE6B0FA29F6B93678F3A -:1030B00081BD3A615031DBAFD7FF20D87E35F8FFB4 -:1030C00062EBC8231ABECEA0FE4E06247E5A76BC02 -:1030D000CB708B95F04333DEBBA3B454907DD0729C -:1030E000F61DF99CDAB19DBA53B65B6893ED16EE06 -:1030F000FC75323F57946611A1EF8E131D05E12137 -:10310000CE99F1E8E7849FE35B7F91A645F0D7F184 -:10311000E4D0B71F414EFEBBC5BB9EF954FBEC7912 -:10312000C8D1A56E96335FDB425F3E0C39DB99F464 -:103130002AD757C54D223EABB00B8DF94E687D01A5 -:103140001F8F15338B5CB23F4F6FF91CFCD86BDBC4 -:1031500043DD7EE969ED6F73E8E68F1E061DB67DDF -:103160009C70198DB78F2A422AE62FE438021B6221 -:10317000B99FB267EE49F613FC94225A54E6F72041 -:10318000F3F3AF6D622AFACD52ACF6C5C9E457DD50 -:10319000B73B03F3EEAD8A2A95D6E5ECDF3C97F119 -:1031A0001CBDF724C92295C6FF82CDFBF51E7CF716 -:1031B000511A3FF5FBE47DE539908725FF32FF3258 -:1031C000E0E18F105A4487DFEDDECEF602F1A477FE -:1031D00014C9B57EAB5F5A924EED2F5FDB64E948B0 -:1031E000A56F83528BB274CBF6776AA8BF5CB7A584 -:1031F0000AF6EBC73E0F8F2B27B46EBD023DF0C31E -:10320000131DB12EB3577F53D0515CD8CEF85D97C4 -:103210000F5A8A3D2C17F8FD9DF593DFBD51C08EE6 -:10322000210B06E32DB67B59AFD1B46DC0CF8EEE26 -:10323000EBF0FE2E4B80F5556096B4734E1605FEEE -:1032400015F32FA7F60182CB7D0D4DB7537D795233 -:103250003711A0F91F092E9A86FA818A70033F154B -:103260003B1E28EC48F0C9A1C2AB50FFF3769E2E5E -:10327000647DD8996C757C6F476DEA0DD087D90550 -:103280000354AA2F5243DC9FA894FD55D66F7702B2 -:1032900026D427ABC46749F523F767785AE96369F1 -:1032A000FC4DA695BED79EF429C6BB2633905EE59D -:1032B0006AD5BF19BEA21F587EB9EF2FC677BEA030 -:1032C00071C13EBB547D69B754CDE7F1A409776065 -:1032D00070EB773B5BC2F3310F5A1DEE007D67A3A5 -:1032E000BB611AB723F8B7DCAFE6CA1900FB8AB096 -:1032F0009E22F57B2DFA754FEE027A5D6AFF0FC5AF -:10330000FD9DEDB44A4B82D791D76AE74C6D57FBD0 -:103310006223D1EB910E5A1AFAB959B79385D5EBBE -:1033200081DCBFA3833F3D87ED34D2C316D6BF9D5A -:103330007322ECE673769BF3D2F4EFEF3AF8BBE33B -:10334000FD4B6DEFD1E312E7E4F0991C931CAE8DB9 -:10335000B70B1F3DAF5DEDE038863860293B48FE76 -:10336000CA307CC2D2FABD45F1391DA01F6A8568FA -:10337000135F7B69FD6B84DB30E90D8DE4C0F0B336 -:10338000CDAAC672A2617F621EE4ADF0C77B103782 -:10339000B0082D423F467F87E85580F98D14714271 -:1033A0008BD0B37E9164C7BA15AEE44B9C77F80915 -:1033B000B3FED9F744E4BC87B67C1007138CF0D178 -:1033C00001E585E6F5A23EAF3F605E543E9F5F3467 -:1033D0002587BE3FEC2F6E2BE637CC3AB18BAF1B67 -:1033E0008FFB068C7BF85F2CE671FF106B822F75CC -:1033F000FCB729E4D8818FBFB107B1FEEA612BD0B9 -:103400003CEAE76707B1DE77D945C009BF67929DFF -:10341000EDE0FAF8403CE46ABDE20E21FEF482AD34 -:10342000619AF48B847BA30FFCFBE623E0FF1B5A1D -:10343000EC0AE2591D1DE24BD857424D141B532292 -:10344000BEDFDECD710E157A2397E0C1FAF36976FF -:103450007E5E6B13AC2703D362795CAB93AA5EEB01 -:1034600047F5AB6B32BC3472F18108AEE886FA3BAB -:103470005596E7432CEB373E08BF67621AEB99D5A8 -:1034800049E18C4AB49F7F993740FCB0EBEF2AEBBF -:103490008FD53E7F7AB20B7290E43CD179F5447FB0 -:1034A0007A6C0ACA540BE6DB91E43C3FCFA4765415 -:1034B0007E6493ED3ED4E946984E87BC7DB8A4A7C0 -:1034C00080FC599753703FE8840A27F1F3B59204C2 -:1034D00062DACD0F88DBD14E53836A26F0F29BFB74 -:1034E0007A117CC32CD58D38DDB5F3629A94FE54E5 -:1034F0006A6AD891402F4C19E38FF4D7D7E5F8EFDB -:10350000079DCB437DBA7F1EC1C7D36EEEF973C84A -:10351000874FC98F86DFBD2C557B84D7E91E1FB727 -:10352000DB43C6CD8FD0134E4F7FB6B74B0C3F3326 -:103530003C1BF8DDDBEC643BF642FC2084D77919B8 -:103540007DFF418B08819FBBEA7ABD160100D0390F -:1035500014C37C307692D3CFF12A97653DECE8C74F -:10356000895ED06F819D0EA617094AA6DF837B3B3B -:10357000B35E9AA9CBB1DAA9B1FC5EED765BD0025D -:103580003A2BC1A736E1BD1763587F96D905FB2BAF -:1035900065CFF7653ED865F7672E43BF7B1D526F39 -:1035A000277812B9FEDFDA09D4BFA0EBEBB2D870EE -:1035B000AF24A253E7F65A3DE8417C57C5CFEDF260 -:1035C000F9E160C13AAC4B41F64DDC7082857F1D5C -:1035D000E45580ECA08D5E493F8C4BABEDBC1EE307 -:1035E000D5681CA0B3B843E5F91CA6B58CF91DAE8F -:1035F000EACCE352268D4DBF99EA3F5B18C771D7DD -:10360000C34507CFC00E389CA6F2BA270975DF4024 -:10361000AA279DDB702FC195F33F7D73203DADA898 -:10362000FDB0CB1E4F2BDEA72F291F27880FA62FFB -:10363000B8738248B8F07A9D5EE6804FD9BABE85ED -:103640001DCE9D8449AE1FCBF17F8879DB73B54FCA -:10365000C00F95D9646F131F7D6D6F780C7195CF76 -:103660003CDA9FF1FCD4735F6DC273616DEEC5FCF3 -:10367000E16C2C445CA6CC22E34A0FE56A5FE03B98 -:1036800096C604A65F65C8C1F48BCB6E9072F1CE6E -:103690004BD307C7EA37EE52A89FD2D8FA0A2ED5E5 -:1036A000607FE8ABE34A3841E9CEF8D5B0AE4EB81A -:1036B000C309A08F6691F65EE9E6E879D25053110E -:1036C000771342FAA921FB101AD70212BD0FBBF1E2 -:1036D000DCDEDA3EB3958EF41DA6A3707D32E3974F -:1036E00068FF549F9C7B09EFA5497B7E3324F37CC4 -:1036F000FC45C3C67CCE1F8FBE4E8AC2095827C761 -:1037000015B94E4E0829BF029B63F478811CC7D7B8 -:10371000CF75E071A4EAEBE86B456FF79443B623ED -:10372000DE833D53FA7BC9770FDABCAC3703A44F75 -:10373000202F4BDB49B8D491E686BDD5510D586298 -:10374000C197D582D70B8D8DD7E5F16D19FCBE21C0 -:10375000D7449110906BA5DBD2D74BBB4EF79B3172 -:10376000016ABFE077B23FC090FFC79ECED0FB9703 -:10377000EB299AAED178C8CE9571AEDAF8FC0EFF7F -:1037800028BE9995F6F15A88A0076D725D07E2A5EB -:103790001E21BB256D623FEC4FD84DDFFD3ADE3E6A -:1037A000D3EFC23E85F9B9F1BD41B9D2EFEC1A456C -:1037B000F78E6AF34BB097C41382E544F43846E0C1 -:1037C0003DA2DBD34F9FA3B32AE94E8C64F09787C9 -:1037D000F1276CA0CF8776838EB766905C2F05AEFD -:1037E000BAB5E271974FCB801EF91A30E17B5712C0 -:1037F000C1D9B0B7A4FE3060831ED17CBAE4C3390E -:10380000198D904FB9D23FA88D49E82F12517609F2 -:10381000420ED4105E514F7A70665136FCE1B1F71A -:103820007F6E6B9DCF97D57E3FA9A073F09C353EF0 -:1038300027D6E7DCB53EE7AC087AD46ECE3DE4216E -:10384000BC9FD86C456452D45A83BFB92205CFD5EA -:10385000504070BD13F83EE1DAF726DACD599B945B -:10386000A346C8A7B96BC6F84B22E8D077B3992E08 -:10387000FD4266F8F23D66F8E7A4DB31BF9FFA9E91 -:103880002F6C86730F99E1DD839AD51FA19F5C96FB -:10389000A05341D9A2FE08F91E5483F033BADE5971 -:1038A00034793CC147D6CEF682CC73DF5F920FFAF3 -:1038B0009DDC79F7AE727AEF48B2C50BFFEAB80823 -:1038C000FD713CD1634EFD2ABBD583F99AF97C97F3 -:1038D00045E7DBA7651C707ED05C7FBE7CA8D1E38A -:1038E0004E222B92AFA2E94FFD5EE7A781952D9E58 -:1038F0007C3FEC9F79E388E1697C8343ABECC27544 -:1039000029FD0418AFD604114EA3F135DD1DCFF10A -:10391000972B168F129FD1F7CAADEEFC5FD23C6792 -:10392000391577C0DD1A576FDA9E5E017DBAD16D09 -:10393000F1928F23DC83AA0E66E4C19F1021B71792 -:1039400071FDBB96C3EF9F5795C0F8992F821C97C6 -:103950009FB5D4D12A1FE9BF929551E3591D514F0C -:10396000F398B7D6DC7EC1861F1D91B0E1975E51FA -:10397000BF4EC57C6FD6C7AD0626B05EBE428F5720 -:103980007C8EA6A46FB6762FDA9D8BF6AB47CA7AEB -:10399000AB53D7B37EF6F3CA5D760FCB33EBDBCBFD -:1039A000797F87D621F4C3A1F8393F87BC3BED145A -:1039B0006E870FED3586BF6C27FD42DEB7A0F6A7F8 -:1039C000D72AACD7CBDB49B8FC09258818703982D7 -:1039D000B6809F9471DA321D1FE0137FC47C40AF24 -:1039E0004858D419F1F130FBBF1555C20B3B4010BC -:1039F0001DFD06DE783F2A6C3F023D1B50420FFB47 -:103A000060EF99BF53B9E74747247C2EBE4CA4AB67 -:103A1000E1EF07198FAA5DF821C7D5BB62D96E27E0 -:103A200005100BFD6ED3ED6BB122D81EFA6A35F48A -:103A30001595CB743B3CB04AEAABD549FE5E6ED4DB -:103A4000AF4AF7020F3728BA7F0BBB3E09F6F53EA7 -:103A5000EEB75971BBD727A1BD08C4A4B07D2DFD19 -:103A600084BFABACEF9AC97E5F0F7BDD170A633C66 -:103A7000AB1FC8647BFD0543EFDD1723EDF9F3EDC4 -:103A80006EB6AFC4FDD27EFC4808E9F7F6D0BE039F -:103A9000DD67AB45BC1955B2C49F8EEF964CB25B47 -:103AA000400F31EFD2F645365A65FFCD345FC4EB97 -:103AB0003F578A0E5A22EC60679ED40FF905FE4DDF -:103AC0007A3B2FDA9558DE663C9458841BFEFCC680 -:103AD000B3AAB012BCB1CE115C42AF9474F3F75AE2 -:103AE000988DF7647CEAB04FCAFBB83CE10F52995D -:103AF0009427F555529EC5548AD132CEF2798CE482 -:103B0000C3E9A2A890F7073C52DE47CFA3B3FE9DBE -:103B1000127B83793C9FEC67BA90CE732F017F8F25 -:103B20009676C7E7B728ACCF693EBDDC04E7FF4B0C -:103B30000CC7173FD7F591815FE29F0188A31972E7 -:103B40002B49E797D5F7049F8A217CAFB211DF801C -:103B50006EC4371BF398EE6C17AE9E96CA74BF41C5 -:103B6000A7ABB82F9EE936C4629178BE2F9DF14C69 -:103B7000EDC55FF1DE188FB4E72FD10F23BA0FC860 -:103B80001B70BE3F66D05B588303FED1FE4DF9EE3D -:103B9000ADBB02C4FF0B7EFF4082A07647AD75A986 -:103BA0005E7ABF6CE3B2043F9547AC810437F57F82 -:103BB00034A88E0DB681EF453A3F60FF4049C5BE3F -:103BC000AB94E3C79EFEDBF23B689CDF2AA219F2AE -:103BD000B162C7F7CBEFA0F91DF43B9B214F8F5883 -:103BE0001B0B2177E717BBAA6ABC58BFE638FE82D9 -:103BF000271F48F530BE031996345EFF1978AF626F -:103C000083CD0BBFAEE23DD5EBC1BA17CDCB31BEF4 -:103C1000E8F72B439FD9817FB74534771AD246BD49 -:103C20006864395FB9E3D7DFA809288F7E04FFA253 -:103C3000326AFF609EBEBF12BD8F303BCF9CC74033 -:103C4000F8E13C86008DAB27B38B8C3BD73EF5501B -:103C5000FF26D80D1B5E4B50B25BF70F8C7D9796FD -:103C6000D0ECC79FF75C785D7EADC78D5BE926E53C -:103C700098670F0DAC83408081CB325B3801F67EB4 -:103C8000D93A1BCB91B2AD4F6C7A18FCF6A1C3DBCD -:103C9000D303F8B41DF2A04CF1372B2CDF458292F0 -:103CA000DF4AAFD2AD5F143E02FB3A5D15E3885E9A -:103CB0000B9E3D23DBFB45730CB52FDDDE5408FF67 -:103CC000A04C735539DBA0D7A8D04BF646571BF450 -:103CD0000A3515729CEAA9EF981E47F72AA243E617 -:103CE000F9EFCF5BF7855D48FFA0B95D92C417F48B -:103CF0005D65482DB6279EDF9EBE3FE1F93CAE775D -:103D0000C35FB9181D4701178813EC8E1749D0DB24 -:103D10001F3982E340DF6D8B1204F1FF57D62AC9A9 -:103D2000F78F2E4B859D37CF16487573299FCF7B14 -:103D3000EC36E6C7B94A55AA3B9BF93DDD3288E728 -:103D40009B8E79DEBCF65A9EE71CA1313FCE7B5498 -:103D50002D0A5279C62AC66E6F63DD9CD4E5944362 -:103D6000DCD21FEBE40C7D097AFC2BDDAF0FBC230A -:103D7000FD6987989418B99FB457978B01113C0C33 -:103D80003D50D960E33885FAF699427CE7D64C6B12 -:103D900015F23D68FE011D5FCA8FD27FF120EFA1B1 -:103DA00012FF227D3AEAED311D1AB3F1FD16FB4DEB -:103DB000D4EF5FE0277A4DEF31DEBE5AEF88552E03 -:103DC000A73255DAEFD1F3E8344031ECB877440448 -:103DD0003F556EFE8AF949A4A922314DC2D8BF7061 -:103DE000CF72552512DEFEF2DE6776C4BF032916B8 -:103DF000D113E36DF88261E16DEF417BE3FB957BCD -:103E00001C221CB96E377C11B5AECDF54254313E43 -:103E10002B45A207FAFB2B7B73E10BE887FADD4801 -:103E2000FDCC21FB2B6CB2AF9A0B1F813CD9637781 -:103E300073FC81ECCF7004DF9CDB1FD5F705E7EA4C -:103E4000F2201A0FD1F2E1AB28F960BC2FD6B6BD33 -:103E50001FD52A17022C4FCB6C22003BA3EC430743 -:103E6000EB8FB2AD723D0A92A73D697D1CDFB2FFB8 -:103E70008F37C09F0DD952C671AF66F93BEF992FAE -:103E8000785EB309FF315EC8DFEFECF07FD346897F -:103E90006607F68B57FAECE0FBF3D6313D6F731DE6 -:103EA000AF5458BEFD57E52EE1DB0E7BEB62EB75A0 -:103EB000EE05E46EF20073DED019919D380495EEA4 -:103EC000E2AEBC7F10855F03AFD172F4E93C4F9B3B -:103ED0007294FEFC5144E0518846E6E36F492E623D -:103EE0001FAE62C3F7ACD708ADCD0EE2E38AE03770 -:103EF0000C2F835E63F8A52988579E3F6F333EA33E -:103F0000EBDF03EFD3D08B9EB3B15D50562FF31C84 -:103F1000E93DF63B2A11AFE7D67507335222E1603F -:103F2000141C8A6AEF8F828BA2DA6B517095A97D7F -:103F3000D99EFDEC67D1B84DED1C8BAF613FE47CA1 -:103F4000BB22C878ADDCF18D3D00FEE8D46C875C07 -:103F5000B42D1181787ABFF94595EDDE539EE604C4 -:103F6000D829CB62A41D77CAADC349062C6616D3E7 -:103F7000384E05FABB9157D01C23E32DA78A9A131C -:103F80009222FCF6A67A35C143ED1B83626CDB7985 -:103F900031B58CD74671A17A69CF8D517FD826F380 -:103FA00045ADC241FD35D67CB70DF1A4CFC97F82A6 -:103FB000FD5252737D02F65F4ED577FFD954F881DA -:103FC000AFAA9CF325027E3BF226664B528A23223F -:103FD000F0E0509A9F1A9F77F005F857C428D8FF51 -:103FE0002C591965DF88A2C430FCE9D5D1F90D41FF -:103FF0003BEC9BB9A467218FE6AD35D72FA83FCE08 -:10400000EB6541D47AD1F4B871F47A596CAC179F4E -:10401000F0E9F9969CD777EA90CAFCD5B2D42696F7 -:10402000A7C8BC5AE4A3B4D4CB7C9D963D1216011C -:104030003D0F485FB706DE4E603DF5BEB0DD7262F3 -:10404000E7BFE7FF12FCB3EBE3FE8F507962D7873F -:10405000BD5E00BCFB4F5D3E16E7B71FB5F7FB1911 -:104060003CAEBD0E81719DDAFB4A17D81BA79E7727 -:10407000703EC2A9250EB6D7037BE3396E71AAB391 -:10408000B4876B5FFCAE7F23EBE3A54CC72706D854 -:10409000A55D55FF37D68F2DF50E0FE651B9378E3A -:1040A000D755E5F331BCAF76EAC5EFF223E371FFF4 -:1040B000D5F918FBF0A7E2C5D467C0BFBAFD5FF918 -:1040C000C2E0276AE02FEF78C93E1B79257FF88F81 -:1040D000FE90AFA79E7989E5EFD7B6C6C710DBDCA7 -:1040E000B6F3C0C3B674C4F5E8631D85B87297F51E -:1040F00046AC9FF3F122F1708AF08079115EE6C13F -:104100002EBF103E5EFEA7C5C73733A49C1B28B048 -:10411000EFD38A17C52F9FC773BC8AE62F9FEFFD89 -:10412000AE3FE4D0C5E6FB19E6DBFEFFCE7C95FC96 -:104130007FD6F94A7EBF678087C719CDF7E7F3F5C9 -:10414000EE9F33BC2DDECBE3BDC4F59E99FF7F8B84 -:10415000BF47FCD3CEF762F47E55A777BC1BFBA00C -:10416000A75EFC8F2EE227CC7BC6FF523E37ECF9D0 -:1041700002D57BC847ED5F13A1F7BC996C95B46974 -:104180008FFC3ADF88A7487F6A14FEE541FB9CA5B7 -:1041900021AC07B227E0C7D4BA720EBC4DF02B6435 -:1041A00027A8BC2F2BE349AFA4F98232BE5B2510B0 -:1041B000CF2AF8D36C865FF75D7900792585AA8CC4 -:1041C000C7ECAFF16E68A079EC4FB2786A091EDDDA -:1041D00069F6E7DBA9DEDD5175C33FABED94EBF487 -:1041E000448C6FB4CBEC675D13E5275DE531D78F69 -:1041F00015CFA460BF6E6CB64DE07C4E21DA47F857 -:1042000095F3F3DD3CCFAB44DD52B7EBA7E3E939DF -:104210003DAF92F0C2FB36814EAA9E1767C69B0047 -:10422000DE5280975CB6DF03C27BE06D82ADBA7D63 -:1042300025F4FDC74267FC26F8D10E51100E127C02 -:10424000C663AD427BAB207F58CE93FDE868BC09C6 -:10425000DDAFB6EA2418DD69541878C6F3AE69A656 -:10426000F779DED178FEE978DDD76911F09A16EF9B -:104270000D822F3A3D9B82386B2DE159515AF169DD -:10428000E0291AEFBFA1B14A7F5DE2BB93D567C5B4 -:104290003A1BA6DBF3A3AD4912EED4A016F1FA0B3C -:1042A0004ABEFE8BD70A7B64A42B89F349857ECE58 -:1042B00042D5F7C39161C7E320FF1479B913ADDA92 -:1042C000ABF99C8FEF1605F05B0B4408F15BA5FE84 -:1042D00095EFE11FE17C4911EF6B1EFC00706FA7A9 -:1042E0002B0C7F50ACB59E38672723EE1F75BE623E -:1042F000C2A0ED2341AF598BE919E2586ECF41AC12 -:10430000C7E2FB1D1ED0AF93B581EBC9D772D70CA6 -:10431000C66E7588E1D812B2F4D3D1EE9591DC7EE9 -:1043200091702B4948B70B29805D6E99AF46CEEB53 -:10433000B780ED4BE33DB5326E22C04F3D5076C3A2 -:10434000F765FBB4D1F43DE4BB098DEDE5D81E1C47 -:104350000912DD9422DE7FEFDA5DE645342F73B07B -:10436000BF537C77E75E904BE30ACC71EBA103650A -:104370003CC7289F1A28E5886AF1A6E13BB396F668 -:1043800061FF4B8D2D2ADF093C6E8B633E2F5E7ED5 -:10439000D3F801F4FDE26DEDBC18E6B109DBF3657D -:1043A000FB69B7BD4FCFB5CD31FCFCF581DAF7F92C -:1043B000C833503C3376D28359D7EEB7A751175A3A -:1043C00068E249C41D2704B6BF897DCE0953546EE7 -:1043D0003F41CFFF144BE378DF7C7CE01B6B1A7D01 -:1043E0006F3C3935A86F8A7177B985C65FACC79BBA -:1043F0006D03E53A546385F68C0BE3EADCAB1B3DB9 -:104400001F2F643E74F4BA1DA9B7EF3ACAEB4901F5 -:104410007E9418F7FABCD6F6F80EBE7BA58E0FF781 -:1044200040B9EF6BC084578E8B97AC7034754F409A -:10443000690BF7A6B27A7041CA40AA1FD74D14AED5 -:10444000C1776F57C57A1E6F7331C7D9E3B33CA0EC -:104450008326EA38DF48ACEEC9FB394D2305F34F1C -:10446000D3AA4C83DE9C9F64F8734D23BD0791BF94 -:10447000D53CD2E95DEF457E4B288C38CAE13572D8 -:10448000BFA66B6DB807E46CB34FEE837CB138D731 -:10449000033EB9F981C909909FB357AB6107F87D15 -:1044A000A5396F49B8BD9C373EBB6EA41DFE6B8914 -:1044B000CB6FC7BCAE1AA4790742FEEBE7222FC32D -:1044C0009870EEA7AEF875F87D6A02AD67AC3FABA9 -:1044D00027017E7574DE53A59EDF64C0CB52B5C143 -:1044E000F8DEAC44CF363E5FB9B83BC7556F1F28E6 -:1044F000E5AFB0867B003F8FD15AC0FA3C912FF9CF -:104500006F5CB2BB978BF93746605E4D36772FF004 -:1045100073D3B2180BF0346E89E4E37BAC727D0583 -:10452000FD1E4B80DE8FD1F9777A8DB5681DF5D3EE -:10453000C929ACF1C9C85BD3DC18C7F840CD61F814 -:10454000D7B3757D357BA53C3FD67594A4ABB0360B -:104550008C6E47CF8F6CCCCC415EBCC137F5830BE2 -:104560008A0646D07F5C81BFB03D7D679CC5D30283 -:10457000395C324579A9BBE4836B07B23F5FCFEB6F -:10458000BC85E4842309E7061B248C7C55C88DBABE -:1045900087FCCE08BFDD2E7670BDBD44E6A376B5A0 -:1045A000876B38FFEA16E15E42F026B223AC362173 -:1045B00036573BB97CBA9AE45D4F21B654A731BC5B -:1045C000ADDAC365A83A8B9F3F53ED657847F52078 -:1045D000867755FB19DE533D96CBE7AB8BF879B464 -:1045E000FC99ED9AC3F2C4DD8B683DF87CBE99E17D -:1045F000A17141FE3885FB6EE4D30A29EF92B2A483 -:10460000FC11BA3CEAD647F0F99BDB410FC2BB6D07 -:10461000C5480B9FF7B436A683EFC6A827B6EE466B -:10462000BC639E8BF3B25A4423AF931661F106F23A -:10463000A4FC7110DF75BD6B6C66649EFA8DF3147B -:10464000618DE0AF9BAA628435423FCD5C9C648261 -:10465000A72F7EF7E50EF4FD3EDDB47B41FFC37767 -:104660007DF9E89FE8F9E3771DEB29CFF5FEB02E41 -:1046700032EED2229A256C75F27EFCE377A4A7B6BF -:10468000EB26BF077ACDC23F3CA04FF3D127B10E36 -:1046900097A9DE25047F04FA103E3FD1E953BCAC54 -:1046A000FBF25F605DFB9D5E85BE73F88EBE858309 -:1046B000A8FDE3FA7E945841788DD43369527F7D0A -:1046C0000AFD9524F55901E46858EAAD4F7F951A23 -:1046D000B81BF5B724787102425BD1213097E09581 -:1046E0003EBB57455CAF5E2C47DC86702CED8A8064 -:1046F000CDACC71A3B25211E6C9C938ECB0B3AF98F -:104700009C167584FD985959FB443AE4529DE2C6C3 -:104710007E0DCE753A9321DF14DE1F451ED014D2D4 -:1047200097CF0E54797D9DCAB772790D92E508AF87 -:1047300031C2CBF1999295D41EF2B1CE679F13216D -:104740007F67E9CF676759B8349EEFD3BFD77185CC -:104750006F2AF8A323EAB351E64CC5F83ABA0AAD7A -:104760004AC4FE6FFD402BF7772A5FF67B0D884A1F -:10477000EFDF9BD5CD7E73369FCF62BD65F4332BC3 -:104780002B677937E8EB9523811D516BF3A6A55074 -:10479000BB97075AF579E8E7C29D323FBBEC027A36 -:1047A000C388D31DC13FE539499EEF826DBFDB86CB -:1047B00073120B3E76B0FE5A70B9D44B223B983F31 -:1047C00099039AE6B8F8E8DF9D3C78378DE724CE68 -:1047D0003121DEBFE3333BF24369D95425A60356AA -:1047E0009B90671A1D9F3DB0EDE38436E3E23BD416 -:1047F0004B8B8B2B3F24402F18F319F3E29954D89D -:104800005995CA59DE67AA7C9124751BF38E8E8B4D -:104810009F8B9F8B95DFA88833DF79A4CDF87974BF -:104820001CF0FB81D1FB11AE02C8893387D420F67E -:10483000D35B823D13451BFD1BF1F3CA35F4523B9C -:10484000AC4B4F22F6C34E5DC02E1F3E48FA2F27B9 -:10485000F578FBA92D2AFB4BA7B6C407619F566CC0 -:10486000B9FF20F6292B36286C9E978B06C617E1D8 -:10487000513823F518F2DDDAC1B8F624425E19E3A7 -:104880002BFD5D7C15F86A7E48F16FA471B4383D4C -:1048900089ED23C6D17190E4CF5247289FF1AA8FAA -:1048A000DB3D48CA41A3DDFCFAFB392E4DEDBE6667 -:1048B0007BE7F77182F30445F39B18DFF1B5B95E2E -:1048C000EC2BCE0F6DAFE0FC8E2D716EC4218EE906 -:1048D00079CEC6777AE9FDF51A24ED94E3FAFEDD88 -:1048E000F16DF27C3AC689F5744C31E70B66EBEF5B -:1048F00065EBF87A475FC746FBF9A1A6841ED4FE94 -:10490000AB3DEF72993F48AE97F9AE86FED0BB5FE4 -:10491000ED88E3FDF8AF763C528838F3C9D0C8146F -:10492000F0FF397F6D904DD261AD3A16F812419982 -:1049300067530EBCE6468EB3DDBA4066E43A93F99F -:1049400046C7773C9B60C96EA563B9B3CA89F3A11A -:10495000953B6E29021F1FB4497CDA774C0CE0D8D6 -:104960007365BD4F807F799DA573FB159688760E84 -:104970009B97ED62DB9E623FDA1B71E8853B6D7CA5 -:10498000BE70C6E59EEB6FC43A7CCDC67458D8C7DE -:10499000733DE72335A89CBFBC305384617F2CBA9C -:1049A0003D7E1DF6C38CF1CEC895EBBD6C8522FC17 -:1049B00034AFB2A02A342A3B12DD03C8514A6B1C23 -:1049C00080FCC9A6CCE03DBD52F8BC6F787D4A6B37 -:1049D0009E29ADE35E3817593E2899E7FDE0B442C1 -:1049E000D67787ED2200B9107846E6E1947593F901 -:1049F000D10F83EFD15F72B8573B9AEF099DAE6537 -:104A000093C2BD909751F64C3AE7659CB0CBFD52EE -:104A10003CC77E71590EBD4FED52F47C5EBC9F14B5 -:104A2000C14765B3BC1EB45393BD1E9F0BE3757F96 -:104A3000CD76EBCE7801BBD5B23B5ECFAF8AE13C01 -:104A400072E3BD9A41D22E4ED1E9296E90F9980FAA -:104A5000DA64BEEA831BD3F97E0CA3FD83366D1A9C -:104A6000EC27CC03F6FA7C7B5D2FECBB18E39D9F13 -:104A700050C7E33CA1F3F9FCD83A9917AE9F3B46E7 -:104A80007BC04D7A1E7BF3530ECE5F3996DEF02D40 -:104A9000C67BECA93EC88101BEE7ECE17AB21F8972 -:104AA0009E0B9E7684517FF42919B73E6A0B7E0BCC -:104AB000397CF4D1767C3EEA68FB603EE707286EDD -:104AC0000BECB3A38A0EDBDC6C5776B5134CED53BD -:104AD000628505F93B6327AD9981FC86960D0EB082 -:104AE000A738B6E9A154F66B842791F36C0EA9029E -:104AF000743BF6F4DFFA44DA2F46B9608339EFAE3F -:104B00002953DA9546FD3A7D5DAED3D7F5C64152BD -:104B10004F95C7851EECC6F393F826FAB07F470A77 -:104B20003E9EF327B6F65420371E16C19F7F9CC7C2 -:104B30005EB60779F365CF3CF526F66B8F594403D3 -:104B4000EC0FE5AECD3FC7FD1C29BF49643D24C431 -:104B5000069EDF51B73CD74A0B96E73FBF838417C9 -:104B60004CDEDC0BF041D2390AADAF051685FB5F98 -:104B7000B0AB1FE7DB113D2CBC4FB65DD5C743364C -:104B800025F0B749E62B8F4B0E6E82BDD7FC6877B8 -:104B900081F3EE63D4B5FD41BFD31BE22CE0A7F255 -:104BA000BB87240E01DEDE5205EC8FD3566F87C81B -:104BB000384234BEA2F3C0BFD5E55319AD3B9CFFCC -:104BC0002CDDF528DF2F520ABE045E9E56781FBBEF -:104BD00074F99087984FDFB4899ED4EF89D0FD098E -:104BE00091F469D4E5E2B9EFD8BDDCBE94DACBF735 -:104BF0005F4BE0716EB2715E4B345D2FF9FDA7D54E -:104C00004B7AFFDCFC436417F43F1F0FA745C3CF6B -:104C10003FA6EFFF654B0CFB83E401F039B6E3B62A -:104C2000D01CCCFBF8D618965FC793A49CF88AE4F6 -:104C300069A037C671CD6F994FDF99CCE7FDE606C5 -:104C4000CDDF35FAFD02721C7CD7CE9B08BFB3FCCA -:104C50002D290F895E3FE3F7DFB2F1FBD1F338A0D6 -:104C6000BF776E9D6E8D63BE38DE51D2E3F8B6DE3F -:104C7000AC9F9A92DC82F9E6299BACB785BAC00E4C -:104C80003EBEB5B7AF36E2BBC793425DDC11CF9BEA -:104C90006CC1E503A53C6D865F2CC2246AF3915F6D -:104CA0002458CE1BEF953A5736C04E417E6F7E0E8C -:104CB000976147F2F979BAE392A53F396CB08C0F4E -:104CC00070CE6AAA9E4FCE764FC80E39AEE9F66115 -:104CD000D996E83C5F59DFC9789FD65D8A91576CB9 -:104CE000C17843F6348E3708CF3334DED2A5B7CC43 -:104CF00047FE7869D5AA1B613F955AC5583B8DABD5 -:104D00004951791C4D3162E624D89191FD44D86F08 -:104D1000BD079F8BD30A772ADBAD6CDCF71D2CF522 -:104D20001DE03AFA5ED9526525BE6FC8170E14A66B -:104D3000B6E20979ADC8EF691AA9D75F60DE4D36D2 -:104D4000591F3D6F633C23064B39D594E9F9ED506B -:104D5000D0E50D95CF779DFE213731B90D3BAD558F -:104D6000DFDB5BF36C69FCE3605BD377DC83A5BCC2 -:104D70002BA5F1619CBDD69AF3CAB33698E1CBB6A8 -:104D800098E1EC1D66B87FBD19F61E30C3797ABF75 -:104D9000F0B3716E197E364AF8D91E87F4B301C399 -:104DA000CF46093F1BCFE16703869F0D187E366013 -:104DB00003DFF0B701C3DF46FDAF743C097F381550 -:104DC000F99A151699E74BF4F0F339A66976D3B939 -:104DD00094532FCA7329C40F52DECF77F13A791852 -:104DE0002D06432FC9F594F2BC23B884DE1BE1D114 -:104DF000E60EC67A5DF3CD1CF05D45B746CE7B6D01 -:104E00005AF64AAFFBA95DA3122F605754ACF9665E -:104E100006ECA8248F568EF695B10DCB0772DC3EBA -:104E2000CCF2A3B1C6F3D60849478EBF14ABB8295C -:104E300083EAE725B7993F149D772E569AF3CC2F36 -:104E400096771ECD07861DF8B8AD39DDCD7EFAD038 -:104E5000C710E75DA8C4BBE1A77F162396E0FEA0BC -:104E6000C0AB324FADE5904DE60DAC54D68B08FB90 -:104E7000E4D73ABE0D78F6D95CB6C7CFC12B158BF7 -:104E8000B85C881E5A7313FCEBD3F32C6C779F9E8F -:104E90005750D81EF61FF9655813B89F2B72BCB82F -:104EA0009F2B927F703F97F9DC4447537BDCCF65A3 -:104EB0003E377199A97EF2CA5C537D49D110537D6A -:104EC0000F21C7B768BE1C5F09E9077F3BC04B389D -:104ED0006F71116847764A1725B09CE5F23A85CF85 -:104EE0008D7B16AF28045E4E103B238E60F0CD6C98 -:104EF0005DBF086BC00EBE3B9322EB8F2A0D5FDEB9 -:104F00004DEF9DF4D56DC2D529272D6B1F1CEA41AD -:104F10007EFDBA2E6E5A87B72AA154889E3579DA5B -:104F2000AEC1ED919FD23891F713B7B74FAE81DD87 -:104F30007968C09B83D0DF1695F3260C7EE96293D7 -:104F400071BA75838866644FACAB93F9BCEBEADA4F -:104F5000C5F688D87F31E6D9023A08944B525338C7 -:104F60002E241A300FB2DB97C06E3B7D48DAEDC6B7 -:104F70007C7A2C0D775A44F5B76E8F61FC7CAEFBC2 -:104F80000D27FABCD4DF83F31BD57BBAA8B0072C5E -:104F90005B36C18F70A4686F82EFE7ADEBF927DC59 -:104FA000EFB5E07D55E03CCD17AB47250CA6EF1CD7 -:104FB000DB6AF38E23F8EEBA27ECF093175883766A -:104FC000CEC37C6A9D1D79C9576E5EC7CFE76C2E34 -:104FD000E6BCCBB9A28AFDC823FAB92C63DEF30A7A -:104FE00094B56EE22FEF15920FE7C5CAFD3CE2E7DC -:104FF0009731AFD39B151FECC72945DBEDC5D0CF4B -:105000003ABF7AA64E1D03FE6B09C9FB395A5E579B -:10501000E5BD63535499177381FB7C269FCD64FED5 -:105020009E72B62FFB59D786FB483F365BCA8F96D8 -:105030007A95F7E35A5EDF9F3219DFABB7F1EEDD09 -:105040003C7B833CFF6F11553847E099DA20F92A01 -:105050005354C1FE5BF4C6BB07B1EE16653A3D582A -:105060000F454355137F568E8E33F1EF54916C3AB2 -:1050700047731D924A22E029E3BA9BDA5F3FA56F8E -:10508000943CC869AD67797045D439C002135C4E51 -:10509000E59D904FE26AD37BE562526B3BF8C31B00 -:1050A000A4DD5ABE23693DF6C5E759A43F345593A4 -:1050B000CF2BF6C8E742C49E3B978EF3F8880F9833 -:1050C000CE6DEBFB7CE897E381DD1B38AED39C4EC5 -:1050D000F292305A9ED568473C8DCCE566C449CBE8 -:1050E0000304A35FBF68AEC5F911ABC4AFCBEBEE51 -:1050F000B624BD952F2A7698F3AD2A0EBDCBED8C44 -:105100007CC6E87AB2D39777C4B8C7293E3E37B990 -:10511000A5C98E78D014AD13DF4B117D5F5A59A805 -:1051200089C779ED9E5437F66D2BA2EE495B7885E1 -:1051300047EA273DFE8F7B86A49DD06097715BD7A1 -:105140003E0BAF3F792FCF39BE9C6791F70544E105 -:10515000659CEF7DEEAF63BACC43035EAC117889FA -:10516000E623E0C91A81A73942E2690E499320C1BA -:105170001DC16791F8F989F89A8B7F50FDDC3D4A93 -:1051800010F96FD1F899A33532FEE668AEAAA0FBFC -:10519000FCF954DCF9C141C8A76DE9F25EC368FCB3 -:1051A000CD150DCBE1F7CE25BD114E62BEB03BD97A -:1051B0004F53BCD0DB9E418D769B94671CE76D7985 -:1051C000FD5D5E772D5E5AD5E00B41F5D4DEE5F747 -:1051D000342F6923CF77D259193FB9EEAC95CB293B -:1051E000E3CCEBEEDAB3A9FCFCA7E2A50278069FBC -:1051F00023AE97D0C63D7B88F3259C3F5F633FC4B9 -:1052000090C3AD769D396FF942F65F749CF0AE2B7A -:10521000F47CC1016280296FF902764774DEB2A185 -:10522000C75B5C524F8E51B3DFF2D0BC8B5F55D958 -:105230004FF74C1D6BE1F3E3AFCAFBF1B465679A1E -:10524000C09F5ABC85E5E0C2F86E7CAF85A6C7ED6D -:105250008C7EBAD4B44B45FCAF38C6CDF9F8C53511 -:105260006A11F45731B5F344B45BBEB47B17E885DB -:105270004FEFE9FD5880D6CBA7B7A7A422EEFFD900 -:10528000325B0A49CE73ED3E5D36A60BF2333E5BD0 -:10529000E5981A6C033F9B747D517ED707ACB74EDF -:1052A0005A5E4F984AEF972DDB9980B4FFD265EF95 -:1052B000E6BBC9A4B8224FDB7805EFAFAEDBE4064E -:1052C000BEDCEBF83E815D242EF17EF1B2654CF739 -:1052D000058ADCAFBE55097F3982DA9D8859953041 -:1052E0003513B7A10ACED338B3215E3F8F56C379A9 -:1052F000432762C91EA0F64762243E8F6C8FF7F2E7 -:105300009D18DE4017F6DFDACBFD9D524BFD751878 -:10531000CF5529DAAE2B06601CC14D692AB7E3735D -:10532000EB5A4DCFC4B6E21FE7E6A9EB69D8DB28FC -:10533000616F235F06F63660D8DB28616FE379E59D -:105340001AB3FDD6A0EF171AF1E0AEB5CD3ED8BB2B -:1053500081029155C57A765CC1BF426FBD2AED8549 -:10536000458A774523DB4BF175F03B6BADD2CE0E12 -:105370007C22CF45D19F2CC8A75FA89779B19FFF0A -:1053800050DC5D8FA3FD62EC0FE5E1DE53B2BD2280 -:10539000F875C459A7883C773B928CB04878943311 -:1053A000DDD47E8C3BD3547F655A1F53FD551E9F21 -:1053B00009BE266BB0A9FD78EF4813FCB34157999D -:1053C000DA4FF44F34C193C74E33B5BFB6A8D854A3 -:1053D0007FFDD4F9A6FA69DA2D26F8C679B79BDAEB -:1053E000DF545563AA17A2EA49E0C71F90F7B0D56A -:1053F000C37F72E0FE17279754FF7BE4318F24515F -:10540000CFF7AEBC71DBE380F721AF9956DCD0510A -:1054100096AAB6E2F8B62132AEA80DF5FF7805FBE4 -:10542000B90D7C8F2662B7E0BB94211EDDCF96CFED -:105430003B598DB855433ADF9710D5FE42ED86C6ED -:10544000ED3BED2196BBF385C76EB20E461EC4BE82 -:10545000DCEE04EF1DD2749395E4CDD021FB9EEDDC -:1054600046F0C117FACC60F8F27DA7513FA5FE0BBC -:10547000593F59B069D230E4DE9B02C47743477488 -:105480005BE995719136CFB71B25F08473E1C013AA -:10549000CA30F13DCA7DC4F7280F10DF97905C3BFE -:1054A000487C8FF210F99978FE6FE467A27C9DFC2E -:1054B0004C946F927F89B281FC4B94EF544FE5F28C -:1054C000BD6A8DDFFB63F53C2E3FA8AEE2E71F55BA -:1054D0002FE6F293EA003FBF7C888C23B848EF4068 -:1054E000BF57200F06F902D1F72C57B9F9FE835A9E -:1054F0005D6F897A3DAF661FF9AFC067A335E94B91 -:1055000067EBFEE285FD7DABF832C26E9B68F50F5E -:1055100019C2F4EDE4E6FD21FDF90B5ECD3F84E810 -:10552000FB7EE6E49EB92AF45DD5CB8954F7BEA58F -:10553000EDFB2753747EF10DF58FC17BC39C8779FA -:105540003FDD934ED6EA108615D05FC991F1CB614D -:10555000D6865AD4D77E2F3CF09B5F8AFF23EF83F9 -:10556000D792B98CF3C7CA59E9AF0CD7F7EF6BBF25 -:1055700097FBF7C33176AA1FE696F5B53793A6F3E6 -:10558000A13EC4DF1F8ED3CEF27C9B296F67F4D976 -:1055900086515CEFB27B906F3ADC1996DF730A3765 -:1055A000E2CB2FC5EF92FD8F91FD6FF83ECCDF87E8 -:1055B000F7691B8CF1B78E67098FAF41DE4F972DCE -:1055C000DBD7EAED876BD47F12C65725C7574CED62 -:1055D000E5F859CE0DC73793E06DCBFAD834793E54 -:1055E00079F459BDDE2BE7DBC12A619C29417D4658 -:1055F0003B4DF8A9BF8C0CE145FC6D784A433AB7A6 -:10560000D7F319E2ADF27B895E791F578FBF6A72BB -:105610003F801080F11B7949C6BAED9C1C4E879DD6 -:10562000D779A19DBF97A16EF7415EE7F8B400E876 -:1056300067755A787EB57E795EFEED173D9D711FC8 -:10564000E944DD5EFF07F45F26E9BF57D21F97BC30 -:1056500065B4C2CA1CFA6F709BF497F8227EC1FC35 -:1056600089FE4C0FD053A7BF62E047A7FF397A2DC0 -:1056700089ACD7F9E37CFA8724BD757E1AEE94795C -:1056800013680FFA0FB34A7EA88D91F91E2FC51724 -:105690003E8C7BB208374588CF0F33F8A54A9E1F52 -:1056A000FEDF4AFF3CABBC47CE51E6E47BEA2EC6A8 -:1056B0000F339B4521EEE93CEBD35220278ACF7A6A -:1056C0000E029E2D4616C23C37EA959CB6EBB5BF3E -:1056D00034DB001BCFB3D06E406BBDD5F94E1CE45C -:1056E0009EF11DA3DD95E7B5CB71425F2C1A135ACD -:1056F0000BFD35B6C6CA716BB24C183E44FA4CE687 -:1057000073FA137CA991F99FDE030BF370BFA83CD9 -:10571000BF255CD2AEF6D05FC8D5C21F8A96A23F25 -:10572000A16EB1C2EF38837C5AFA4E618AD93E1F0E -:105730001BB5BF7E75F6576C8F5F7D917BAE8F0C6E -:10574000D1F7DD3345E67FF29ED1E621AC672FED40 -:105750009ED12C51CF7C30BA58E673D1FC2D3988BC -:10576000DBF84515E0425165051F8C157556E95764 -:10577000FA4F54E4B1D7CEF8B94684F9F9785228F3 -:1057800050263F23F601BC3F6EC274DC1F3C2A77D3 -:10579000540F3C8FB83FCF36B43DDF9FF76777C4D7 -:1057A000FD79FB46CBF5B6F05A196FDAE7ECDEA6C9 -:1057B0001DFA2AE9DB1E3D8117C1E5CBA48F7BD002 -:1057C000BC5F217D0CF8EAAC1A81F70A3DE6BC23E8 -:1057D000E3FD6BDCA384B5DD85F5DD35FD9FEB04D2 -:1057E0003CBF96D47B34E8F55AD2C0D188C7BF9667 -:1057F000D4C1224B879DCB7EBB7BB4353E637DB449 -:10580000F657C8FD19F7058F6E2FEF0B8EC6EBD537 -:105810002264C2EF381DBF3F01AFDEB6F09A82C3EB -:105820008EED81CF77771979538827F758DAC0F052 -:10583000AD36B90ECA778F2F405EF4C2F7657EC7CA -:10584000510C057A77F1101EFFF0C583853597F767 -:10585000A302C0779953E2F164E0A5FEB8D73CDC1F -:105860004E1B89FEBF5AABF279FB93CFC4703CEE5E -:1058700048F0D904E0D3E0E332D5B3D28B75F89A7F -:105880002AEF59FA617F17DC437A21BE267EBE7A61 -:10589000685BFCEC227EEE773E3F8B0DF21E83327E -:1058A00067619B7436FCCEA41C3FCB1FB708DF0298 -:1058B000FEAF10D23FAA70BE2EEFA92418E75EA358 -:1058C000EDAAFC586A4FF576A7CC1736E89DE19013 -:1058D000F75866C40937E22042CBBD0CE3FDB4BBE8 -:1058E000BF187821BF764B64DEDAF0705FDE771E7A -:1058F0007B48E57CF75762E5BDEF8D440F85ECD31F -:105900002BFB56B9BA111DE7E66B65785FA83FA877 -:10591000E8F7F59E8A68C7F1F35C17FBD93FD15FC2 -:10592000BF75A8EEAFF717FDFFE1EF29B497F70EAB -:105930002F7C353788712FAC21AD96C2BF8BC1F754 -:10594000C4D5C23FCF6C953BC3452FFEBD8C5129BA -:1059500036CE33FFDFF67B0A1942E3F5F79FFD5D94 -:1059600085B1F2D179BFAB9091B0E28096D2FABB0B -:105970001AD1BFAB90A1DF672D3C527F18BFA73073 -:1059800042F8392F7F4C9A59AF8C728F3CE0E6D2A7 -:105990001CEFC9B8483ED7B34375BD7231BA970BF7 -:1059A0009DEEF25C27F840FF7D9420F8D3F87D143B -:1059B00083EEC6EFA4D4B697BF93F2CFF6BB28D13F -:1059C000F489FE9D9468FA44FF6ECA702D96F134F6 -:1059D000AACCC57C6DD0692AFD657B00E77295FF76 -:1059E0007E7A1D8DA2D719B17200EE293D552CE5A6 -:1059F000FA85F4FF06AFFF14E4C58F8827E1BC8B5E -:105A000053C643FCB55611335CE07E42CE97FD454C -:105A1000ADBC07AAD62AE30101A22BEEC5FB2EF6E8 -:105A2000EFF23E47B28F6C1D1197A9E2F70376A7FC -:105A3000BBD60B7A27309F2C5E2CCF031FB6D4F138 -:105A4000EF5DCCCCAE52B07F792C535386B547BCBA -:105A5000B868FB1C8ECB570D847C9FF1074717D489 -:105A6000CFE82AEF8F14D98D0322ED911919322F27 -:105A70002B66982EC7BD320FCB354CFA09F15E3735 -:105A80009F6B28CE167A7EABE832A31FF8F813B6C8 -:105A9000E35B3CD2AE6EB4C97B2C03AFCA7C9EB52F -:105AA00055EFB0DDBF91EC5A55DA376BEEE3384372 -:105AB00082C03EEEE331CD49187FEF35C2642FF44A -:105AC000093A4D79C97D37BB4D70BF509AA9FDE5A4 -:105AD0007B3CA67A5F38CB549F7BC86B8207340C23 -:105AE00032B51FF881DF040F6E1C6B6A3FE44891EA -:105AF000091E3DAC9B8CFB8327693E3316B983F2AC -:105B00001E7D1927E96A97F654EDEDD29F30F2D742 -:105B1000357D1D44E7AF77B6CAFC757B95D46B9A8B -:105B20004BFAB7EE64E156F95C4C03C3B81B82F341 -:105B3000C603E63CF34E4EE95F59464BFFC3AEE762 -:105B400099C766C9732F465E39F9157EE0BB876831 -:105B50009CC6BF77A0DF271ACDCF453ADDA3C7DDAE -:105B6000D52ECFD3D5DE6EE7FD73CD656F5212CE45 -:105B70001FCFED0325FF6F74B67DEFD38C61328E9E -:105B800012CA2DBA6E18B57B8CD416DB5FE7F5E729 -:105B90006D84BCABFD959DF3C62FD6DF8CCBE57C29 -:105BA000A65B2C332766B33FC8E7008D7E2BF47EBF -:105BB000278D50DA9CDF8CC466BE774D24DA3DE039 -:105BC0005FCDB59C6177AC4852DBC07BEBB90C99DB -:105BD000A77FD3CAD07DBD699CD3ED753679E140EE -:105BE000D0067E18574076A40FF1D782475D448FC8 -:105BF000C7165B390E76DB8B2FCEC0D5F4E3453369 -:105C0000F3031251B09F08FB53CD691DF7B1E13288 -:105C1000EFFB415C2CCDF6CC0F3CAE163D3ED222C4 -:105C200042E7CE4F04DAE037CD7590CF21B8174A5E -:105C30007EEA1C71CE0AFEE7FFD47909811D52EA83 -:105C4000C75627E439C78BE0CF38A7E2B9C556B4A9 -:105C5000DE85F32262AC128187FF182EE3FC878673 -:105C6000497AA31DE4D185DA91DD9788FD8516E197 -:105C700049745F24AEFE3F31FF0CAB8C337471CAA4 -:105C8000F3229DAD1ACB0B7B967ECFDD79FCAECB9C -:105C90000D3D4ED6C92AD77D27AF5CD7E7CB85030C -:105CA000FC7DBB26EF4D8BC62FFF8988AB18E757CD -:105CB00062474B3962C88573E7507A4A3FD4A6CB16 -:105CC00087600F0BE71DDC1D6F5EC7DFEBF261AD78 -:105CD000A12F02E4C7E79BE484C0BE5EED3295E5E8 -:105CE00004C9C9831A8DB318F7B2B85B7F1FEEE6FB -:105CF00007A41E1BEE2F7A10FB26B356DBC43ADE38 -:105D00005790F7C3CED5E3E4C581A8FB59747BFC5B -:105D1000CC4AC58DDF8D98BDC25C3FD7F5E527F035 -:105D20001F6F8EBEA7C6D8AFBB481CE0E830DD4E63 -:105D3000F70AAF9E7FBF04E33B1394F75E9F3BAF30 -:105D4000A4C77F5A82CF4AF84E21227F47C2B00BA8 -:105D50000CD8837DB2887B5808BFB159D0EF4BADCA -:105D60006DE6371AF83D97E7A1EFD351B96419FBF7 -:105D70003332BF81E401EFCB9DA07AD8812702A7FF -:105D8000B9FD891D319C5772D2D7D01FFBB7C63ED3 -:105D90005D0F4DEE63B5EC8897F90D2E8B8437CBF4 -:105DA0007BEC17FC35D81F7E6C63E059D33907AD07 -:105DB000D1BCCF175D6A353BD9DFBC224F4B1E8E5D -:105DC000BC74ABD7E925F81ED73EBEA76B1CF98F74 -:105DD000906BC84B599622C7CFF22B705AE2AF4A4C -:105DE000E2EF6764E8417EBE2F487A228E29C8AB75 -:105DF000A5B2383C98FBFFA9FB6093CFFAE4FEEF15 -:105E0000D921FCBEB66230C359C1E6911F50BFD73D -:105E1000692E0FE248D7D6FE624C2C7DBAF15F5D49 -:105E2000CBB8EC6C3E3F6094BEE1528F34DADAAE10 -:105E30005FAFCB9F3F0C17FA7D3592DF17D628BC9A -:105E4000AFB6103C0EF83E793FA7019FAED3E131CB -:105E5000125EB44CC2504DB08367E9BF93B6498F10 -:105E6000BF60FE28317FC405B6E8F119CC1F25E6D6 -:105E70008FE790578021AF00435E0186BC420979CD -:105E800085E75F248DE27D6DECDB8D8E584FD8B7B2 -:105E90001B1DB13EB06F170963DF2EB23DF6ED2238 -:105EA000EBB16F17598F7DBB4818FB7691EDB16F41 -:105EB00017098B4157B5C2906BFE89267832F903DA -:105EC000A323D633F6ED22BF8F7D3BD3F7B45B4CD3 -:105ED000EFDF28169BDEC7BE5D64FB998B15D3BE32 -:105EE0009E10CDACD767AF69C77C94E12BAA04BFE5 -:105EF000FF39EEEFB7D9BAB17CE038C6C2F258AF7D -:105F0000A477DD58497F8B3C1FA134F3EF0B9CBE77 -:105F1000D32EE131E6FC6DA3C4BED7689BDCF7420B -:105F2000897D2F94D8F742897DAFD13DE5BE174AD0 -:105F3000EC7BE139F6BD5062DF0B25F6BD5062DF28 -:105F40000B25F6BD5062DF0BEF61DF0B25F6BDF0D0 -:105F50001CFB5E28B1EF85E787691C2511720CF6E2 -:105F60007A0F939F497C68F233DD2618F67A647BBA -:105F7000D8EB91F5B0D723EB61AF47C2B0D723DBA5 -:105F8000C35E8F8443C33CBCDE60B747BE07BB3DE6 -:105F900012EE57177819B1B5F16BBF3E80B2315E82 -:105FA000790CE70D43C3A7CCC47E66638CD22589E8 -:105FB00064BAAD66DACCD1B0C3F5FCC7FEA2D90293 -:105FC000F9A3C199CCE373869C57DAEFFB74AE6FEB -:105FD00030CEC5E10FD1DDB743F0EFCE18FBEDC6F3 -:105FE000FB5E52DBFC7B517AFB56B8ED76D1FD1B94 -:105FF000ED38B72A621C38D18CBC19DF9DAE1CF875 -:10600000219B2C0AE7996C5A22F3A2A3F9EA0B5DB3 -:106010003E6DB26CDF877330CDC58A17E73E7AD408 -:10602000697CCEACDF7461517DADF3E9FD7802E7A8 -:10603000D5BEA1CB3D63FC467C94E4059F1F1CDAD2 -:10604000DC302A91DA6B8191FC3B38E3ECD26E2094 -:106050003FF40AF8937D038A7F7D049FFF69B8D4DB -:106060006F5A408EE3C9C727C8F762E57B4F3E9E53 -:10607000C0FD4F58AA709ED9D02DC28F73CA8DFA19 -:10608000F8FB6E09ABE8AF78A9ECCFF86EF1DA2E29 -:10609000769CE736F0552C1A47E33E6991A7E04E0F -:1060A00059D1CBAAB15DDA61BADB023BE852CF41EC -:1060B0000DCB4B1A833C44512FF8DED0F1796F9B06 -:1060C000E6CBE8CAC7EFA00AF60DB5C02D16F43B23 -:1060D0008110D00EF16482311F4D13559984DFEB8E -:1060E000A61633BEB3A60B05F8EE337D9D2585DEDF -:1060F000EBABBD6481BDD6AFAE914B631EDEA14953 -:106100002AE07136F7188C7FDC1885E547741E0F7E -:10611000EC038697DA589F1BF6C3C2F873793E7F6B -:10612000429ECFE94336CEF339BDF40CD717EF8C3E -:10613000E1BC1E6D8DC272CDB01B8CBC9DB25BDE0E -:10614000CF077E8E6506372575673D9F3802F93487 -:10615000DDB627E008CE89A53BAFC3D1BDD34B77D1 -:10616000CADFABD5F7778CDF3D15D97ECE0733EC90 -:1061700040A1D6DB23F7718CDF4F23F9C9ED4EEF39 -:10618000B1BBF9F7EBF4DF3B35E23EC56FE41E042B -:106190005E8B1F95BF7F366BC5AAC2A904CFF13BAA -:1061A000C3F85DACE87CACF95176E0C57EEFB4CFC6 -:1061B000083DFED36AFF31BF9C795DDA7FC56FEC85 -:1061C000BF56DA2B36CEFB9F5E23E37562BBE0FB46 -:1061D0008FA6D78CB2E01EE9E93BFD5EC5D36A0706 -:1061E000BEA5DB2D93CE66307EDFD5ED946B917F1F -:1061F0004AF81DD718A3E7ABA57379FD59998F3AD3 -:10620000C925D77BE37382EDE9968043E611D60B6F -:106210003DBFD5CC773E41FC41F4B9CCAFEC47DA79 -:10622000F278D83DF4BDA9B083DA818F8B97215FD6 -:1062300096DE66BB339A8F2759C353F0FD495E1B28 -:10624000F3D73FE263DCCB714E2E89AA9771CE5F04 -:106250006C90BFE3305593FCDD57E7EF19717AFC82 -:10626000C925E34BE7E2011824626681AD33912F23 -:106270003C03C90B1D795A7EE4EBC567CBFAD97F85 -:10628000D83A73299C990BC425D43BEC7C7FB5E6A6 -:1062900072F2EFD05C284E80F800E4E34DB7FAECE0 -:1062A000B322E463C1C882D5FE0111E71DEF9179E5 -:1062B000500BEFE9D9A1ADF3B646399BF08BF53120 -:1062C00023B1F1369C37AF1921FCA307C9DF99E44C -:1062D00079E1C44D167E6F52C25B47BCFFE715D90A -:1062E0008C0F867F35E28599C8872977361682DD3F -:1062F0002AB3ABC622EFBA550E69FE8C4CC8215F9B -:1063000018BF1B76A1B8C3D611920ED1F187D9D987 -:10631000523E0BFDBEF04FEFD9BD0DF2DC18FFA7CA -:1063200017F87D8C8D232CFFADE73CA2CF777CD076 -:10633000477B6804E21A167F13F2E83BAA757AFEDF -:10634000ACBCD7C3A06F4CDD771CEF28D1EFC327BF -:1063500079C2FEE42CBFD35B0339922596E3BCD00F -:106360000C5534F3BEF1797497787C7CDA5FE723BF -:106370001FF7F15FC5CAF33A3AFEA6DB1B5E7666ED -:10638000B6E2EFE3C5FF6293F22BDC13FB723754E6 -:10639000C5707E5BC1C8A22D186F5CB697EFC1585F -:1063A000ED97FCE4EC56F47BC8C1F2952F3D86FBDB -:1063B000122AEB33F977658AF7F896E39C63C148B4 -:1063C0006D07DE2B76B9F9DE908AA549AC9F66741D -:1063D000D0CFBF8B66DE8733F0FE861E9FBA7FA4C8 -:1063E000FCFE29DDCF80209C686A77A1389DCCBF58 -:1063F000417E0EE28F9A6B17C709DC77C87B2AECC7 -:10640000E23D197F4C6B3B6E90A1C71BD3BD323E62 -:1064100064E0EFDEAC592CE76C463CF71CFECCE7A1 -:10642000318DD2ED97F6C2AC5B15F6574B56AB7C6F -:10643000AE7C8C3A8EEF7159B84AF1F0FA7AA03BF3 -:10644000E77B2FBC87AC310FCE97790A3BE4E1BEE6 -:1064500075C50DBB643A681111DF29593398D75BB4 -:106460004990CA36EE3535CA1B57EDEFFC9C0764E0 -:10647000F4F3FE6589DB6F4F8E58EFB3EB14D3FD59 -:106480000A062CF02316ED717F3D29481AC7F41E29 -:106490001E05FB8A6EBFC4C34DB766DAF17B24D3F9 -:1064A000E9CB969C0BF7FFFFBBFC7FC4BFEF53000B -:1064B000800000001F8B080000000000000BED7D35 -:1064C0000B7854E5B5E8BF67CF2BC94CD879910458 -:1064D00048D80904C2439C109EF5C1CE0B2610601B -:1064E00092808227840904091EF446D4126C940910 -:1064F00099C41051138D0629EA80C0A16A25564F10 -:106500008516DB017C8B8A20D6B636191E8A6D7DF6 -:10651000A470A8F67C54EF5AEBDF3B99D99904D0CC -:10652000F6DCDEFBDDF8E1CEBFFFF7FAD77BAD7F0F -:10653000A7289DBDCA2631D6DD2A48DBD318AB94E7 -:1065400014F3441B63DFE2CF0CC696B5088A6F7C58 -:106550006FB9289D2D75413952B1333699B10A4929 -:106560003627A7E15332C7C2FB65B71F30B178C6E3 -:10657000968F644CC882F6B10EB30DC75F05E30B6E -:106580008CDD20F90BB0FE86F132AB8B81F6DE2C70 -:106590003383F9DC9BF83CEEA618F31550AE304A75 -:1065A000E6142897453286ED617D3EEC5FE957CCD5 -:1065B000B1361C972D2DB1F1F5C606ADAF425D6F1A -:1065C000654B8C7945C8FB56930CE5C58C291D415C -:1065D000FBD39E331481F6B3CC5B9CDA0EEBADF4A7 -:1065E000D8259CB7D2A8981DB82E1C17FA2D6E6B13 -:1065F00037A505F5BF423150BF198A4CCFA2747F31 -:106600008680FBBD35C281EB5D2CB598109E451A86 -:106610009C1FE6705821F93370FC15560E076DBCAF -:10662000CA363E4FDFF5717857B6559865A8BFD189 -:10663000E84A6D87FE37C23A3DF05CBCF94086807F -:10664000CFEA088700E7C12477AACBDEDBFF938778 -:10665000AF4FA5FDC3FA11DE76873C3309D6B3BC34 -:10666000051623D393E62DCF66D51D4170BB5E3151 -:106670003296804F033D594BBB621D0CF060FC67A6 -:10668000B8F9480EEEA37E0C631B601F6EDBCF7360 -:10669000709FD29D8C89D361BD9BDEA3FAE5494CE6 -:1066A00012A0DECC5E10B0DE5C097DA0CC3C054AB9 -:1066B00020938FF56D3A63293832B4B701FE789292 -:1066C000195B3755A67917B3C0623602C6D9540C88 -:1066D00073C03A13F93ACB07B1EA9F8581579BBA49 -:1066E000DE1BD4F32E33B097596C6FFDDDEA79973A -:1066F000213E07F5C7F170DCD55A7DAE3FE3D6F1F8 -:10670000BDEDB579CB62793FA407C4C3D52A1E601D -:10671000FB35D49E970B44DB8606D8CF9AFB449F6B -:1067200045C0E7930D83B1FC9CE040B8FF79CD8B69 -:10673000EF5C07CF3F3DB2AD1CF7A7AD63C5D7599E -:106740004C8E83F3FDFA2A7A56FAA73339BBEF3E13 -:106750000F4F75FF48991C843F0FFD74941BE6FF93 -:10676000F3B36F65209C3F021C1001CEFFF6D327C8 -:106770004D2CBD77FDCB9ADE3355D882E12510BC78 -:106780009A338FD2F92DCFE4FD967BFF5281E7C17A -:106790006C663923ADEFF957789FE3ED6B1CD4DEBF -:1067A0006DFB809FFF102689C9173F6FED7CF5E7D1 -:1067B000FEB8C9E54F12F07C5A42E85FBFFFC7D46C -:1067C00075FB54FABB41C5E31BAA5AA9DFB2A68ADE -:1067D000274558F7628D7E2B43DF6BE773769389ED -:1067E000CEE7ECA68CC6242C77F0F3F977B163C220 -:1067F0005A68F7E7D53B6F494EC755FB525D57F0D6 -:10680000F361D9FC7CF0B912CE87C5853D9F3DC1AF -:10681000E7B3F2097E3ECB9F7DFB0FBF9009FFF8E7 -:10682000FEEEB3F890FF2EEB78EEF80FE0FDE2A657 -:1068300056531AB4FBB59246FBD2FA2FAFCE9258FC -:1068400034ECAF699B09F9C0AF15392C9E6B7065AC -:1068500046CE671E37C1D9C6503D13627BDB2F661B -:106860004A22F211E619C676C6F75DFF9F543A2A0E -:106870004A779813917F3544B1ED12AEA3E27E368C -:10688000A16F7BED792A82D3C5329807E9F3548E44 -:106890002315E9A2CC6008A137ED7942A5AFA1513B -:1068A0001D8B71BD43E398540F20FE71A4926B8041 -:1068B000797FFC03AB54EFC0FE6E19EB2D562679A1 -:1068C00000E4DB0DF244C24FC6AAEF494658062643 -:1068D00023DF1BB93AF0175C1FA253C444FEB4C3B4 -:1068E000BE2D391C4FA0CC06F3F77E7CA6183B8842 -:1068F0004F45D670FC33B3F7A96C06BE8578ABF56F -:106900001BCA8E08F83E19D682F337672EA3F333DD -:106910008DE4F4D2DFFEBEBDC4FD9D4A73FB484E3C -:106920004430697B0CED6F0D967BF697C91403F428 -:106930002FFFD115DB9A61C85375CA4133D49F5AD2 -:1069400067A3FEFFA8FDEAF7B9B8B222649F3D74C1 -:10695000D3027C2D0D9FD9A9B8CEB3569808EA4F23 -:10696000DD1A6140F89F4AE3FA0263017B099CCB80 -:10697000AEF5F0AB85B1DDEBADF47C6A3D20D368BC -:10698000C69E599F44E567D7CBF4EC589F49EFD397 -:106990007338FE95452AD12897BBEBECD2768487D5 -:1069A0009FD34D67CD088203E8099C1FAB7A41A7AE -:1069B00014B0C706F169901FF7A1BC633523D84E08 -:1069C00098A2B3E594DD301EF192AF4F6B7FBBA967 -:1069D00085ADC3768F0ABE9D306ED4EDEF1524A22F -:1069E0009C6E4BCB12A0DF929A73C40F97D806CB44 -:1069F0000CE5B8CDDD3815EB37A7491BA05B545B20 -:106A000056670DF45FE11DEDC0F6B70B7223CD5B49 -:106A10002738705EF851AC53800FE06F505E697B91 -:106A200075A4CA2F0DC82F97DFBFAE3119CA270C26 -:106A3000AC5B04D014198A6762B9684B8CA31EE55D -:106A40006D3DDF0FDB0A7CD4DACB470BA7B9AECEA6 -:106A50008173661700DF60FCB1B03626E27E3A141F -:106A60005C3F03BD6327C3F5BACCD8FF972ABFECC0 -:106A70006C3B6197D5F32946BA71779FB807CFD59C -:106A8000667034CB28DFE5776584FB1B22DB2E2381 -:106A9000FEF0FA35765E0FCF0D0D50BF669BE843D2 -:106AA000781488658303A87F6D16892FAED8563A6F -:106AB00018F58D155046F9B505A7027C6A6CCBE335 -:106AC000ED5A0B1EF1003F4D15980BF9D16963A0EB -:106AD00018E1F1E9B6C4D83AD4F76EAE1FC5A0BE2E -:106AE00072DB3DA9F8FC745BC422E4E3F952717EC9 -:106AF0000CEA3F5B63B244B997CEAA72389DDD744D -:106B0000735E22CABBD5DF1C7A5C02B9BA0270542C -:106B10008271CF7744F93CD064F5FABDA922A096E2 -:106B200025DEBD3C07F0EBDF0DFBAF9B8E7258F00E -:106B3000ED4AA6F672A2148E8E357D0AF058063CF8 -:106B4000BDF9EE0F699CCF0D87E72D86FEAB6F7EFA -:106B50003E1AC7F9F7878F4D91E0FD0F26B9FF1751 -:106B60008EFF2761DB2E0940C2366F9B80F2A33A6D -:106B70008771BE1AEBBA6E3187AF63BBDCFF7C5501 -:106B80007B0582A7565EE21B6466A897FA9959C2F4 -:106B9000A7C4480FFE54643528DF35BD447B5FAF82 -:106BA000C2E5D3412DA978FEAB76B5A7A2FCF8A328 -:106BB0009D97DD3B5E5B7127ACC3DD669018E09D61 -:106BC000DBC848EF5DEEE1FA34AB026692DC3BFFD6 -:106BD0007D3951B4FE559BB343E41EC8479AE78FF5 -:106BE00046E6C4750CAFEFCE42FDE9F746FF0A3C1E -:106BF000D7DF837EEA49C373E2F8F7FB167126BE3E -:106C0000F7DC2EB00C01CBCFDB47DA480F33105F37 -:106C1000FFA5C9B713DADB2775F891EFDDFC42CC8D -:106C200044046381383E11F167CD3ED3CCA15C9F13 -:106C30009270F6D546BF39DCB9DDA4EA513DE517BF -:106C40009E3323DEAF7E06F401A4CF17041FEA377C -:106C5000AB3B9E7B75088C77CBDE8A6C9C476B7F49 -:106C6000CB0B1C0E112C602E0DD2AB2B32631B876D -:106C7000028F7CF6C0474B1F862D55E039FD80B151 -:106C80007D333E70D78DC4A744FB64C66ED2C74126 -:106C9000BF32A3FCBFD9CBC7BB39F368633AEDABB6 -:106CA000388E059DFF9E1C13F5D3FAC3BEA95FBDA8 -:106CB000F5EE2702B05EA5DEC822AE85B2917DB4A6 -:106CC0000BE1C7A2A59DB80F233BFD2A3CD78A83C1 -:106CD00058333CB756AFF90F6A5F67914478D6DFF7 -:106CE0005CBB2700F3C9227331E8EFC9ADA6F13CC4 -:106CF000662E7FDAA39E7DF44628D72CB03900BDDE -:106D0000A11C4DF0D9FF4303F1F964D67DC800CF33 -:106D10004406540400FA539AFB30E237FDC0B86BC6 -:106D20006F937DC88F81830B88E75FBE74261BD766 -:106D30007DEDF0C039C42B53DD19773ED0FFFB3910 -:106D400012D74FC607B2B15DC24195AF198F907C83 -:106D50003425C9B1A8AFF8712C5CDFDF0C8407FBC8 -:106D600005FF9338AF06A7885CAEFF19B2DC7F4001 -:106D7000FEA708A63BFCD07EBE10EDC0FD1E891507 -:106D80003326023D7F69FA280DC7F500DA8A437B76 -:106D9000F5D85C75E9E621D336235C7200A0EC6A75 -:106DA000B065C6C7322394EF65866E0BAC23B7FB84 -:106DB00077DBEAA02C3D38888920AAEA2352592E95 -:106DC0008C2F1C848DC27E0E8E3FB81CD7796FB776 -:106DD00095219C983554CF351B92FD3F427CAE8E59 -:106DE00076B02494431D59C88FD82D364733B45FED -:106DF000722190F1BF502EFDED30E9E963D2DD5FE5 -:106E0000E17E8688CA0937D4DF2BF9473C80E3D777 -:106E10004439EAB81C61C1EBDFBFEE6FD171D0EF2E -:106E2000CBEE51C63DD0EE4BC5EA000D9675DE396E -:106E3000EEE5ABA07CB52A4FF4EBFA324936A2DD81 -:106E4000F165B7D58F7AC89736834F0090E6EE3F4D -:106E5000F4A100F23BD76AF38BD1D8CFF459B0BC80 -:106E6000614752623E194722867D0BF01CACCAA5D1 -:106E70006B0785DA8F4372B91D342497F31FA3EC97 -:106E800020389FF5185933E2218332CE6BB44ACDB6 -:106E9000B0BE5FD9762D01CA6767BF4E1F8472E30B -:106EA000ECFE1183D8F8FEF9E231D427404F583A6E -:106EB0005149CB9DDC2B5F17AA708968B9DE84F03D -:106EC000A8077834033C16DA0C7E0BEC8B2D088572 -:106ED00003ABE92E47BC61866807D20D9E2F9EBF8B -:106EE0002C18BAD9557DCF7BC605C9FF23282F8121 -:106EF000F344B8969FFDE48A07189DDB15B9097421 -:106F00008E0D57B2DEF3FB573B2F667434E139AC7C -:106F100015ED2D780EF546AEEF7900B776C650B771 -:106F20005D782E6BEB47D2390DAE073E81764A9DD8 -:106F3000916D8F47BE7294DAEF54F54196594D7CAE -:106F4000A6BCDE2221FCBE8A8CA6FE0CCED5342443 -:106F50001C9FE17CA5A692115F593ABE5AC0734F9F -:106F6000C219603F9D86801DF71988002D129EEB87 -:106F700072D389CE87224718C1CF19FB3FB6CEBE48 -:106F80001DF98D681DFAD8691045ACA93B7A2CAC67 -:106F9000AB4D601DB42F93CA3F56D9489F6B8BF100 -:106FA000117F6B5B38CC817BFD92A9F55591C45F55 -:106FB000AE3218A8DCBD7830D9636D31C05A71BCCF -:106FC000C563496FF8F93722B7D73218AFCF62A33C -:106FD00036637D71268DF74B8D5FDD67A7F1DA8A09 -:106FE00095E448AA1F6CC0FE4BD3DCB7217E0C1180 -:106FF000793B503CA8DD962D4A329EE7961233B578 -:107000007B44702D5E81E35C6123BD31B038F2D9E1 -:107010005DFC38FDE85FEAACE1FBD6E860DD54CE0C -:107020004F877B4E3C8AFCC3930B27624379F1C5A3 -:1070300012C46B458C76000AF739E7AF7AF09C757D -:107040000370597C6427D9EB72064360C3F9492C5D -:1070500017F1E410C013DA7B4C70CEF1FC9C37C4FE -:10706000E339CFDB167CCE309E672DBC17D6443B70 -:10707000846974CE99387E0D8B74A07DDD737EBFDC -:10708000F265E1533438922C008BBDE9EE8755FA56 -:1070900025F83EF607D81FC0A5DC1298DC82FAB9A5 -:1070A00081557584E1034FE472FB4062DD2694AFA5 -:1070B0004B35FCAFD5E17F6058CC27512AFE43BF4A -:1070C00017135DDBF01C3E178E4DC19787FF2E2EE8 -:1070D0000A37FE4F54F9F266BC6B37B61F693C386D -:1070E000EC36D437D65948FF65170E0DC379D7A6AD -:1070F000B99EC6FA8891DD66F44F7526779B707F3E -:107100009D8BFF94827AD6D29AD7883E2F757D1BAD -:10711000A22698506EC638B34C01E89FE8CC7A0599 -:10712000CFE5E85C8B6C09E3073930776A0AEA43FC -:10713000C70AA7A620BF3C9602244FF2D461473E5F -:107140006ADA7B851DD779CC994D6599C96AB9747E -:1071500040FEFA67E0AF7E5004FE08F61A3ECF808C -:10716000BDE6077EFB31D86BF83C05F61ABE3F0141 -:10717000F61A3EBBD63BE8FD31E788BD8817E75BD2 -:10718000B81F65B9D111562F5BFD8CC8FC1A7F83DF -:107190007F37ED880A29576D8D0B29DFD8061864D3 -:1071A000ED2D576E1A1152D6F4CF65DE7121EFDD49 -:1071B000B5D921E5FF67E0DBC4E18BFEF27F25F85E -:1071C000E2CF269077A5F80BE0F7DB9367111F3D20 -:1071D00026B0EA3878C6489CFF195D02F9DDF0A7B1 -:1071E00005E47609FE027463B4C90D58EF85F60F05 -:1071F000425BB47DD1FE60CC61AA80F70B9D111279 -:10720000CAF3EB5835D1D922D642CF1B58073DCB14 -:10721000D8117A96334E875F5604A6E0F3837877C9 -:107220005A1EAC7FB5D5FD443CDA6D29EED171C84C -:107230008F6CB16497F6774EA8613355CFB54D5139 -:10724000F7053F0B70EDD0EF68D4843BEE907BE701 -:10725000D1C687F9AECC433E63E2F3BC3D796A0AFE -:10726000F207E64A08B1A7FA9BAF559593154E0E63 -:1072700027F4D962F9F442C1B701CA075A2D66F45E -:107280002F9CDE6852F5F5BBC9CE3D719CFB654E67 -:1072900037CC4A45FCAB6B1D9D8A787EDA2437D407 -:1072A00000FC4F4F07FEED203F8E03E5C349A79D2D -:1072B000FA83A488CE82735BAEEEEFA4EC30AF838A -:1072C000F60B9345E681F66E4F5A34AE5FDBB77E20 -:1072D000DDCB365942F060FEB4D0F24266EEC5B75F -:1072E000343C6F736F3DEA4962D920F7007677CD61 -:1072F00047ABDE7D39085F6FC8B3C723DF6453D95E -:10730000D46FC5DEFEFDC1F7ABF555EFBE6CEA8567 -:10731000AF865793F25CCBF19CE0B519E916E062B9 -:1073200040797C6C2F87636BD4B5F75D0570287945 -:107330005F641CCEE59EDF233EEFE37E7DFD3C01D6 -:10734000A4EBD148AF9CAE2BBCEF91FDB6B4B6D840 -:1073500084EB2BB175A7A0DFE9C05DA353F05C8E71 -:10736000CE1D9D827CE350E1E8C76E8771BB8A44E5 -:107370008705F0E940D1B9FBB07CAC569470DEAE25 -:10738000BDE754FED2FDF65458DF174E13C9A1AE27 -:10739000BDFF1C3E53B20FF80CCC7FDEC7F9CC4AC0 -:1073A000A38B35C2BC2B012E68C7FFB3F9CDC5F83E -:1073B000CC5193AB2001E1552738D0FF56576821B7 -:1073C000FDE128D08785E353C3EDC827A781FD2BB6 -:1073D00021BEB926A34D796CEF88048417F32847A2 -:1073E00033A7F4E2FBF2DA9545E85F679B4C27513F -:1073F000EF466708CAE712663C1908C253F70BA6A6 -:10740000DE32E1B5F1642008AFF578BA4787A7E727 -:10741000D98554733AAF3F32B897EFE14F307FB917 -:1074200045F437B2B45EBCFD6BE17BE5A824005F98 -:10743000F905E2EB0F27A6BD141082F8CA25F2B1B8 -:10744000D6A86F48EEB5477D4372EF7821977B074A -:107450000AAF3FF83BC4FBBB38DE1F5B3895F0F248 -:107460009809E419C0EB686D7634964F6D2A253A79 -:10747000D3E8473F4F978AFF5ABBA5C66E93230CAC -:107480007EBA6BC590F3CC7861C920F407F4B77E5F -:107490006D5CAD9D36EE525D5C573FEE27795C4FDB -:1074A000CCD85136E0F86000F6F6437EC2227BF17C -:1074B00055443DE07AE601F87439397CBA8AAE2742 -:1074C0007A3CEED4E8D2CD301E7B7481E843FDB522 -:1074D000CB798EE8F43CD0298DD1CFBC9FAAF4F9AA -:1074E000894A9FA755FAD4EAC59D0F5F77038E5B43 -:1074F0002B129F3EBA203B01E7FBE38E0C9A17D676 -:10750000034605E8212FFFBD024C34E40F76E45F0B -:10751000C7010E6827942E2C257BBAD4E44808A70F -:1075200027E8F7AD1FEFC05C8B81F1F188DF95DCB8 -:1075300055CA1A912F001C103F8F637BA82FD9C901 -:10754000FDC087B07D7C309C4693BE727CB7E04026 -:10755000D161DAFB773B9EC32A5F28BF58B9392A2D -:10756000E4DC56B4C485944B0AF93E8ED78EA0FD58 -:107570005FEEF969FD2FF5FC6F52FBE39ABF253DE5 -:107580002536643C0452E87CE9BAFAB1BAFA89219A -:10759000E58BE1E309152F34397222425E122EBECB -:1075A000D435CF52159CA7313B9FFB5B66E773FF39 -:1075B000CBE5CAD582FCF072B5BFFE1A7F1A95E7FB -:1075C0002ACA4739EA2F35E1BE2E951F05C9E105C4 -:1075D000D43F2098B17FAB2A67AB3A38DEB547DDA0 -:1075E000FF2AE2D5E7AA9E0E7849FCFE0B95DF7FC5 -:1075F000F19F6AF9A702E1E5A17D6BA3516F3FB34B -:10760000777434DA61273BEAA391EFCBCC13FD0307 -:10761000C0C7CF5C203F61BA4F3B06969F7F54F9AD -:10762000CE193C07929B129DC729557E9E40F94971 -:10763000F23E939E47517E42FD82E7543D7DB74026 -:10764000F4BFCAD812DE3FBD23945F556D8DD2C9F9 -:10765000C950B959B96968487999774448D95D1BC7 -:107660002A370BC432E2EB677C1C8EA5CEEC90F679 -:107670006764395A22F870387C6192A311CF4EFAB0 -:10768000E2A283E945E3BF477570388D7040FCF492 -:10769000960E8827A7D4FE5A19EC4213CE5B6A7562 -:1076A000BC128F7E844D8203E3540C78CE3438C7ED -:1076B000230BB29E6C0ED233A40291F0F984F750E2 -:1076C0007932F21F30C0D0CFFB5AEDA154F4AF563F -:1076D0003C13457A937EDECAA2503EF3594371EEC5 -:1076E000EFA15FE9FBA2CF8AF0288A21FEB5E0393D -:1076F000D12742B9AB362F3A781F67543AD4E4CE3B -:107700004A6375D873ACDA1A7A8EA5457534CEB152 -:1077100087850E61103C0F4C0749DAB75FA991EFDE -:107720007FE53322F977577AFFF236C61557821E66 -:10773000886AC26B4DF5F310AF4FB84C06E2A71D37 -:1077400071F3103E9E05A22303DA1F6E1A41787E64 -:10775000B2296F30CEF772BE48747566AFC5205C33 -:10776000094F9789F9C95EF5D3797EE62D25B97160 -:1077700006E1827A905122BA78379FFB914EC03849 -:10778000586F003A417DB8CB273A7D61E8E3DD7C54 -:107790007E1EA72E3C40F8F3AAEF5034EA15273A94 -:1077A000F8F8A76AA5688C4FBDE5CDB6D3FA8A6014 -:1077B0005CD47BF75D4F72F28C97E323AE93ECC3FE -:1077C000262E3F8E7997DF3F1DE0F1F92691F4CE0A -:1077D000CF9B4AE74DC7F3DE64A2725EF1428A6F27 -:1077E0001CF371F972DC77AA1CCFEF8C174E1FCAFD -:1077F00075FBA6BE3D291ECFD944F850F94CE8B917 -:107800002CDC144A5FF0139D057A5725FE26E3FF12 -:10781000949968272D4B02F909947BA2A8D484FE81 -:10782000C9124FA83CB2B06213E21DEA97D86ED9D4 -:1078300063A593FD487F1E81E4E5D217009F603D5C -:10784000A61D5793BCAB68B184CC5B521B6A1F2D3D -:10785000D3D9437A7BE9B2E585A9BA3C9CBC1854DC -:10786000A0CA0526CD44B89F04C3BA390BE0F982FB -:10787000A860F9BC3782F867C5D2B3D7A87AE9B552 -:107880008807CCE161D3343B3D88CE9679459D9EF7 -:107890001E0A5FD09F3F41FDB8294E95A39E52F22C -:1078A000D78DCA53620A701D976A7F5FB27E5BAE46 -:1078B000EAB7E5A4DF1E5B08F202F673149B04F539 -:1078C0003FB0F07AF2EB1C9F7B3DE9B9C77BFC3AF5 -:1078D0002ED5AF730D9DDBF122C067921B0EAD3C20 -:1078E000A01EA1F18B8FD57338A5F2C9132A9FEC86 -:1078F00052EDAD46555E78557971BC48B5B7E21981 -:10790000C90BA3516197C2676E6C8BD2C987389D32 -:107910001D3554773EA1F262B7CB3DB300E0664916 -:107920001A1BF2DE244D0C2967ECD84FFEE3F3322C -:10793000CF27BA077102E3250B797E16B37690FF45 -:1079400078A143A6FAA1182784F66852611E898699 -:107950009FDA7B299EBFD7CAB1B0EB3A6C97D6416C -:10796000E5FA858C611ECC486D1C00471DE8094373 -:10797000D18F0DF324818186ED357C1FB6A095DA79 -:10798000E5563149807655056984E7494C21FE3238 -:1079900078355330DF85F99EA7764FDE0DFB00BCAE -:1079A0000FD4CF20BBBCD41ACDE3DD201F07C6B354 -:1079B0003A4E3FCE38D25B8619396AF68BB76ABB2E -:1079C0008BE16D901E7407D10533903FA2356A821A -:1079D00009F1B4C4E622BF01E0F5923BD05FF99211 -:1079E00099FB091672FFE4D1C2A98FA1BD3B618F3B -:1079F0008D7CC94757003E137FEFE676426DA9079D -:107A0000E5DE074E2EE7C6EDF9CC80F96E5D7B9979 -:107A100003CB876A9F3FFB26D2CB0281EC8C63B5F8 -:107A2000799C2F33E6C2FCCD63CEBC0D549E0686F6 -:107A30007116D283B2C188EB00B83653FDF2FB2633 -:107A4000A3BE735824FC4D52F38C243CD7E4DE7261 -:107A5000BCA296D95E2A2715F1FCC05FA8FA41871F -:107A60007A9E3F51EDA05D2ADDB4A974F3A04A3798 -:107A70001BF5FED0AD9C6E46191DF745417994C7A4 -:107A80004E72E6DDA253B46EA07F09E3B969856248 -:107A9000F32480DB384B80F8742988BD0DB09F9C9F -:107AA000A23ACA5F2C75338A57942CA8A3F50530E7 -:107AB000B67415EA4D7582A8D6237F1C17E7A7F682 -:107AC00025562661FF52E77307300F77A11B40034D -:107AD000E5FC057502C1A702C683F6076A1FA2F17D -:107AE0008E57F1751CB5F3FEC72A98E481720673B0 -:107AF0001EBC9DAFD385F1D0E3B5CF1F20782FE01A -:107B0000F0BEEA5343083D66F92343E87AEC8ED889 -:107B100090FAD19B878494135CE921EDE39CA1F456 -:107B20001E39726248FD3167A901E5ECF9055A7EFC -:107B30000FF78B69765DCE1E9B01E171DD5C51F321 -:107B4000E31AD860B4BA18F97D9B543D91B58C60A6 -:107B500098BFF1E49D06CA0FD8B8A0DE8A790FE776 -:107B60003B8C745E302EF191E3FB8D34AE35CD2B22 -:107B7000A01FF35E80B318A4FF3569F24DF5ABE3A7 -:107B80007A8C41EB899519668CF5B46F53F1E92134 -:107B9000751DC0B7734C38AF8BE3495C113398A0A7 -:107BA0007FC2022EA7F574D9A1F6FF89DA7F978AE2 -:107BB0008F5DCE273744225C1631D2470AC4D51BCD -:107BC00022701D458CE8B1C37F3032587FFC457F61 -:107BD000E32CC82EA0713C9C8F8E9D2FD447E0B91A -:107BE0006E0DFCE91D78FEF2F3C60DD1B0DEA704E0 -:107BF000D68114A5F14F4DFFBEEA8B26AA1F3B117B -:107C00004C34A8FFE517CDBCFD1426A3BFEB17AA83 -:107C1000DC6952E92763C778F22F9EDF6C26BB67C9 -:107C2000D7BC95DBDB60BDA3E7DCF5D40B882FF375 -:107C3000EEFADD0B72AF9E5F3A2FB913F3F747AD43 -:107C4000B733E40FDABC193B3ECBA5754B468678BB -:107C5000FAF4CE9F2FC3F17EB22BD2A0C0F84F6FA3 -:107C600037127F1973EF63DB37B3BEFE985267A8F4 -:107C70009DFF938DED4FEDC5F735CF3F713A284FFE -:107C8000E7D8DC7B52D06F7A747D555B7E46FFFC73 -:107C9000B3D4CCDC18BF73FEF2B39FBD05F3FFC6AF -:107CA0003D6662B01D306A26F7FF1C5D5FD3960FFC -:107CB00076EA5891E72930A36703C263EC8B8365AA -:107CC000D4DF80148C6E80A57376844181FDFDC65F -:107CD00067DC467C60F6C60C3CCFDCA78B0E7E8A48 -:107CE000E77C5CC5F77EF491A3EA39F5944D32C187 -:107CF000DDF39295DB378A9C42F6B1434E2909D2D7 -:107D0000E78EDEA5C5971C7F403E5E521645716525 -:107D10002DEE223AFFD2807C7EE9B4EAC912AD3F53 -:107D2000348E3F04E1978D715E1EAFF7788C8CF234 -:107D300082606B48276BC5B1946FF2E1AA1F52BCF9 -:107D4000DE53679132E2296EB007CB35C0772C93B2 -:107D5000288EEB43A1BD7826F7239C5B54FF9859EE -:107D6000EE1FFEDE8B9C8F493D1FFDFBC533B91E08 -:107D70005A8FE79211722E07DD93C29C4BB495F097 -:107D80004B3B1731BA89CE85596D9998F791C851F7 -:107D90000AF7F336CAA1CEE3DC5FF69BB2DBEAD684 -:107DA00042F9EC85410CE9428BAB9427F1FC033A94 -:107DB00012E05B26B57FA2AA77231F43BDBB5C8D73 -:107DC000BB742E611477D1C63B5F3348E2E3DD42DA -:107DD0007A737935D03FCA92A85F917ED13082E71D -:107DE0004794DBBA9750BEAA607060DC3C51A7D7BD -:107DF0007B5835AD37F17D91FCF986A84DD43F1104 -:107E0000C02366612B330181DAA36007A315F34910 -:107E100086E00B3948CF52F375136B5EE4FA511EBE -:107E2000F44C0E994FF896D65FFFB1887CA0C6221D -:107E300023DFC3DC2CE4DB04BF34C4A376EA2FDDEC -:107E4000C424BCC7C11426C74FE17E309C4FBF7EFF -:107E5000188FEB85A09FE17E855A3EFFD639FC1E28 -:107E600008DBCFE460BB8505AF67444859F59385CF -:107E7000964D49E61039F59B0BA583AA07F0D7E884 -:107E8000FB1B64D7C07EDFAA20BB2BBDB7BD9627E6 -:107E9000A6C179488DE58410DD7FBFDD2EE5E99927 -:107EA00080CF36E6CA7D13E0E17E5F247967883AA9 -:107EB0004CF0084470F8F4E8B38BB8BE0BDA791DC7 -:107EC000E55B83BCC3F3C33CED5180EFCC139A2731 -:107ED000A0CDABC5973A557E1C480B2C718581C748 -:107EE000C1993C7FA16BFD9714EF2E47FD167039A9 -:107EF000B0E1CF21F73F4616E71C9C497EB7D03C46 -:107F0000044D2F45394BF8EBE172B6D3934D7CE726 -:107F10003CB3B790FEAFE7374646791F6BC548477D -:107F200033F9EDEEA6BC911A8F45B2C073AE23D4DF -:107F30001F337F5AA83C2856E274F222D4DFB5D012 -:107F4000151A271AD9B68EF8D779D49B88DFF1F5A0 -:107F500018D5BC3213DE2F11D15EF7D0F3B0CA9F13 -:107F6000DF51F5CC08E4AFF03E0A13CB011FED2C36 -:107F700040E54188F22330A55DA67CC738A650397C -:107F800081B9A9ACE54126331F3DB5FC961416A076 -:107F9000F270D487442429999E23D00E19817A9EA9 -:107FA000A327DE4379937969142F2866CA1FB05D31 -:107FB00051F6E724F78AAE67944F0A9C64B9827938 -:107FC000250BB5322C14CB054C45CE7A5E5FA895B7 -:107FD000BDCB15E8DF99C3DB1B5FDBF8A4C746FC0C -:107FE0004BADBF87D7F7941B97E760D964A0B2A4C5 -:107FF000B62FCE574CB3009F936731C2835FE729FA -:1080000096E0B23B4F89082EAF2950A26625F49620 -:108010009FCF55ECC1E5AE5C655070FBA1054A0CE5 -:108020002FF33CD7F74D4A0ADABBF0B35B98C2F1A5 -:10803000107F5E35B993711CE51981E06501BEDDE5 -:108040004C7CDBC5904E816CAC9847047CC67C07A9 -:10805000D4B38966CAF73344D95207F247EAE92B09 -:1080600060627BD14F576C748FC675E9F99EE079D9 -:10807000ED6F98C703F4908B7A7E408D87046AB9C0 -:108080003F40A313EDBD7EBE8BE13D5382FCBCE9B6 -:10809000BDE3F6B77E3D1E1F51F5BDA3AABEF7BED8 -:1080A000EA97EED96FC018F389B597BEFBE79F46F4 -:1080B000F64910FFECBBDF534B4C5C7E48282F3A4F -:1080C00023D8A270F72AFB5B5F54DE4CD72CCAA7DB -:1080D0001826519C81697C9FF39B4EFC15F8E0B8F3 -:1080E000419AFDEAB0221C3258D2EC4C98B7D5C95F -:1080F000487FADCF3F5882FCE77C19483058D7A95C -:10810000DB4F23C531610FB7275A5218ADD79E26D2 -:1081100045A0BED4A0F24D0B8B291C89EB1F662411 -:1081200079AB5F7743B44FC0B8E2107F04F76FC4F8 -:10813000335F048C33C4E97052DE8A47949C582E16 -:1081400063F332A1BCAC4D949D30CEA1B65256091A -:10815000E3564E033E4719E93C9F2256C5E371168C -:1081600046F916ED09368A577B378E3EB002F9661E -:10817000B2C832A0FDF886894EF47BD6DB62632953 -:10818000E6A4AEA7DEE6781DEF61782403BF4722A0 -:108190002956CC43DF76BBD189FC3CE5B949D16295 -:1081A00010FC4F79CF46607EFB139281EA9FA8CDE9 -:1081B000B5DE68C37B847E85F20CA4938A0DE6DD70 -:1081C000026D1261BCFBAB4EB68C62FDE343B4D3CF -:1081D0001C82A7510EB3CE0F1AEAB734E9F4830715 -:1081E00066A9F1A4296C0A9EF3954F5D30A19EBB50 -:1081F000D426931F3DB749A0FC94C001472A9ED3C3 -:10820000A9FB4693DFDCDB24AA7E6B07F9AD0329CB -:108210002C15EFD754B408A4178BDEBFD461BFE18F -:108220009972328E337C527772B0BFEC89BB7E1864 -:10823000817CD45B6650FDDC8CC69165C59A06FBDB -:10824000FFD82BF0FC099324E03D66FBC36204AE2B -:10825000ABCBC4FD14CDC04FF17E6E734EC980749C -:1082600068FA1AD61964B734C4A747E2BCBDF8ABA4 -:10827000907FFD744B36C547B637E5523E887E9CED -:108280007BD7B30EB44F1AD65BE9D9A73ED595EA92 -:1082900080FE1FB7E6348290621F1F589584F783D3 -:1082A00056B4585844183C3EDD3A95E65B81F79841 -:1082B00071DE966233F2FD596D396684DBBDEB9554 -:1082C000E782E7692E76BF827C2FAAE539C2131BAD -:1082D000F37B109EBFBE464945FDE274060B9B270B -:1082E000F9EE2CAE67BC758D8BEE937C9C12BEDDD7 -:1082F000B1595CDF9F8DC43219F3D6D83B2B01CE28 -:1083000015404F75F0EA54537634E2AD89AD262618 -:10831000F59BB2520FDA73E7506F077EDE78D775A0 -:108320009B2BA15DC3DDA3DE45F67CA599EBCDECCF -:108330000391E802F4C20AA4CFFF5A6095EA83F8D9 -:108340002FEA8F4A487E1A971BA626D16F067E6EAB -:10835000DAFFC9DFD1DE41BC5582F0987EA6A8764F -:10836000819AAF913485B471FA69987D9DCFCF30F1 -:10837000EEB2DC8AE7A9D7D3FBE0499F75048D8F65 -:108380007A6E3E532282D6012CC14FFE72379FB7C0 -:10839000A79D5A6F0406F36D90FEAEAFD7F6317A03 -:1083A000B38E5E9DDCAE03F80E18AF1BE30BED97AA -:1083B000E16474CE6345E5E0272867DB45CAAB1E60 -:1083C000D7CEE3FFE78731F213F5379EC67FF1C7BB -:1083D00038588523C0B531BE84CEB3BF7E66DF1169 -:1083E000256D42AF7D382629745D5ABB8C9E7DDD9C -:1083F000C622B93ED881F699C5077C6F023E8F2808 -:1084000028BF33B7DD2E0DB46F3D3FC31F19D6BB58 -:10841000423D3219700DF9C3C79B05550F614923C1 -:10842000A7D0D545923FD85F09E27FC05778DE9E3E -:108430004F20F834B79EDA7E2FF961EC0EDE8A9F6A -:10844000D704A6C9419E07A4DD1364189A1ADC1B41 -:108450009FD2E0F8E9EE0DCF3E05AFCE3CB3E60B80 -:108460007C5A129645233CEF895F706D32B49B6055 -:10847000F625213F5DE9B3F4C13BAB862F69783F18 -:108480002FB4DE9214B47EF8D7BCEFA9CDCB504EFA -:10849000EDB33A30351CF1CB13029F407A31D05303 -:1084A000D75DFF41F7F323A5B34B28BFBDD642F7F5 -:1084B000BAF4F07D729641CBA7A4FB1A1A3D45B4DD -:1084C0008C66E85F3CA9DA4D2737819D0AE5C65ADC -:1084D000B38CDF35E872142B4961C633D79A4FE06D -:1084E000B9B2603B31BD779FDAF85D1EEE876C84D0 -:1084F000F18530FEBE8B8DF7AD4B59E904FCB21609 -:10850000BB56E1F3D4A6E5B4DF9ABDB55D6F429BDF -:1085100086C1EE9B9D09B8EE11530474441A65BAE6 -:10852000EFE7F5FE8CE449CB347807F67C4B8731D6 -:1085300002F50F8FD740F1DB968EF8C89128A76C13 -:1085400086B071D6279C1C5EBDF2C4151DAC0F35DC -:10855000E7737D48D853767F3AC0CB7B9CE7296A86 -:10856000FA87A4E2CD388B44FC59F2F23CB75E7D29 -:1085700088EBD5E751AF467D6972A5142C9F1AA2EE -:10858000F977302AF31D1EBC87996763243F86E381 -:108590006505F45BD8986F561A7E27C3C1303F3704 -:1085A00016F41F19303BB18DEB3B91369B43413C98 -:1085B00056385D59E13F846764A6C2701EA34EBF62 -:1085C00030EBF40751577ED409FAC438D6A34FC80C -:1085D000CC118D70B6DF37701E87E6CF05BD89EEF2 -:1085E000997918C01FF1D4EAA1F389064382E859AA -:1085F00051E4F8C1BD7A3FDE67E3FE1589E24582AA -:10860000D2487EFBADD9DCBF91CC78DC6B88C2ED63 -:10861000F909D33C5406FB81E250EC572C12F9F2D5 -:108620006E97FB39C48F34600368FFC58E67029173 -:10863000FB77D4CB59CDA5C5957E7C90FBFFBC863E -:1086400048C7F63078FFCE1C2E97230FC1DE50BFEF -:10865000BDDE4AF75B0AC4679A089F2619C8AFEDCA -:108660006547248AE7AB7C36A6D8F5A693E2B2AE7E -:1086700034847F92112C2A5076CDAA1F37E58EF4D0 -:108680004814F51F26FF9CE0E101D865C0BF6D3599 -:10869000F1B199F0FEF19A0D04573981FBC9B47B11 -:1086A000E77112BFDFDFEC3AEBC1FBBD1D73F8FDD4 -:1086B0009FC862E3EC74280FAF0D084877F7D89590 -:1086C00045A89734C93FA3F348CB920DE82F1B6A06 -:1086D00064AF5B2632F66C0CAF474189F58FD80743 -:1086E0006F0BCE27D9A1EEFB1121BCBEB2760ED7FF -:1086F0006B3AF7012007A17DCC54FBFBA94AB2B726 -:108700007BCA0037E8FF8087DBCFDDCEA72A3D2379 -:10871000C92EE2F59EDFF2F6182F85FAA237D6545D -:108720007AA0FDE369E1E7CD2CE2F07DFC8DEEC798 -:10873000308EF5D73A1EC7EAFF9CFDCC00BC658B96 -:108740009DA5B22B81CFAD322F0AF71D9975459C9F -:108750008F74DA3A085E0CE479F455748F5EAFAF2B -:108760005A918ECE49DBEBA6CA9C8F4C9E4257FB9A -:1087700039EEE9C6BDB8DEEA4842FDB37E5577035F -:10878000F28FFA03AB3EC47BE9E56566D25BCB8D25 -:10879000D5BF453BC87898E7BFE03726100F860065 -:1087A0003FC2FBA6B3AAF8F92D95B8BF56D8F391EE -:1087B0002B0FFDB1C946C24B4D8F1D67513CE89749 -:1087C000DDA2E6B73371581DDEF7320E15C9EF1B77 -:1087D000550B7A2DEE2F9FE7EB2AF01FF2214DCF9C -:1087E000B58D3786E4F59A7579BD465D1EF0D8C221 -:1087F000503E649F3C69407DEA576007E33AF703C7 -:108800001FC2A71FEC617C1E047B1D9F2F83BD8EA2 -:108810007EF057D767D2F3F5F50E7AFFE6FA69F4E2 -:108820009C911A30213E933F9AFC36CC2F905F4F9B -:10883000C3B36D2373A1EED91C5EBF68F6C8FFF009 -:108840005C0DF5F16A7BCF3784873D65367645EE62 -:1088500078F28353F9D5C2CC15E4275AA0E4170265 -:108860009E24185C15F89D0776A785E216FAFDBCD4 -:1088700057A8E59184B7E3197EC220D48F535238AC -:10888000B97F3FCE23025FC7DAB7D6EC40FA18545F -:108890006C74211EA7A687C60F9E2FE47429CCE610 -:1088A000CFD437DDC307BAAFAFD1477FF5F5FB00B3 -:1088B0000506F55FEFB5B36BB1BE3E263C5D95A8EE -:1088C00074D5EFF8366E4FB2D9406F43B1ACB70FE5 -:1088D00003945F72AE26CF4FE4F6BDE9AD3B05E9E8 -:1088E000AD2BC657877662D781559BF13B2122D2AB -:1088F0001B9205D21BC63F347AABE1E7B114E90DF8 -:108900007E9D55FB9E2B0FE93189D397B067FF1AE7 -:10891000CAC7B88BE7D168F416A3E6CB47491D64F4 -:108920002FD28739B01FD0DE1601EFF17CF211256E -:108930007F88450E7738BABB4C7ADBFC3DE9EDD732 -:10894000D704287FA2334D49427DC66BE27EABCB74 -:10895000A5C3ACD966FEFD8C2B7CC938CE16759CA0 -:1089600059C34E90FFAFC8EA10519E39650ED782A9 -:1089700049D9F4BDA18F0A79BF6FE62B1D445FD79B -:108980007D4A7EDE0403A7DFF7DED8417221A5E130 -:1089900068F12CC4977522E9DBFA7DC5CD53E366F7 -:1089A000029F1734AFE4E038E221952EE575C73811 -:1089B0009F8F615206AC27C9239538312E74B5813B -:1089C000BE2732A8F8680CCA676D3C38B824CC378B -:1089D00041D5D73AB12F3DC24F876970083D1F2E50 -:1089E0001CC02F7B31FE51A8D2311E3DF971D57BC1 -:1089F0009297EBB7EDD78F784578BFA44F95AFF539 -:108A0000269EFF01AD25FC2EC0CB2EF79942F2FB2E -:108A1000EAF4BFFD92DF8DFB58134D7EE52423D78A -:108A2000F792649EB732947908CE5AFC4DD31765FD -:108A300085E717DD50ECFE0BC2691B930FA03CB31A -:108A400039D8228AAF813C43BCD8ED52CED2BCDFAC -:108A5000510FCC2C56FE7B207C2ABE4EF906C7EF68 -:108A6000AF3EA7F8BF0E7D8BF45FC6FDA54BCBAA2A -:108A700029376B08D849B8DE996A7E46FD305EAF6B -:108A8000F957BD095AFC549987F993D12ABCC659A4 -:108A90005CAC02FA77A11CC6FB7B87037EBC176C1B -:108AA000C17B6412FA5119F58FA9117C32F6173F78 -:108AB0007B05E345A63CFA9C0863D3B83DA0DDBF27 -:108AC00091F22FCFDF98325BF5374E6493103EA9B9 -:108AD00006F9A1E9F03EFBD18263783C931F5B115C -:108AE00087E272EAB68652FCDED6AA9D1F6F437FEC -:108AF000E8F4DF5A189E07E88F7E63D87CAE7F9833 -:108B00001C21BA2A29FACF4A8F11F951783CED2A53 -:108B100052F54FC4D3F8103CBD7A76783C25FDE77A -:108B20007BE0E9CCD9A1785AA4C3D359B313BE17BB -:108B30009ECEC775FF37C6A9609CB30B95E2D903DB -:108B4000E065F64265E140F541F101B2FB46B169ED -:108B5000D6E0EF1E6ACF56949703E427C46E3C49D3 -:108B6000F971F535E7284FB9CB76F26DB483FEABDA -:108B7000C62207FBB3407F0FD1D75B40AE78C09EC3 -:108B8000FCA088E7411F5A67F1CF40BDB696DF478A -:108B900028AFDD2660BEF790AA6AC10DFC2D5101F9 -:108BA000D311FAC728865EFF09FCBBD27484F4D9BE -:108BB0007690C71E625FFC5E9A26FFC759AADF4007 -:108BC0003BB5FEEF46C7063C67261D407E5408F4C1 -:108BD00084F1CD6BBA41BE058DF7C6BE69E4579BE3 -:108BE000F135C8BF203F4E0E8C185CCEB32687F4FB -:108BF0002B90D242EA67258D09A9D7E8BE33468D6E -:108C0000AB4CDE918FF82356F03C8542392BA47D86 -:108C10007B592E7D0FE0CAE9FCFEDD9CCCE921E307 -:108C2000EBF582ABE13FA47751A707E8F504BD5E01 -:108C3000F0E3D9AA5EA0DE57D9680CE4127F623C4B -:108C4000AF6EF8855F131DB4CB1CCFBD6567291FC0 -:108C5000A31EEC7FF4370D0DCA2F45BA98600E9015 -:108C60007F6ECB622B9DC7967D4FD1772334FF1744 -:108C7000D00DD1D1845C89F25CC7DB1FA4FE6C15DA -:108C800097B37ABA146A5F24FD6FEB7CD81BD8EBDC -:108C9000B9F3D2B8BCDD1F203F04BBD3CC506E7AF1 -:108CA0002503E58DFD58F0470823907E15924F2C43 -:108CB00089495ECA977C8F7F4F9131C7C66434FD66 -:108CC00015CA6B04B4EF7E43CDA345BC8D7032C78B -:108CD0000628478DE7F41D3B899F8FCDC1CBD2D5A8 -:108CE000BCACD9DB3149AC05F36287E278D036BE43 -:108CF0008649F5E4D7F053FD30273B524FF3F3FE9E -:108D00008995CCD50465B15A51FDCD6E35BEDE4D89 -:108D100071EF74C11189FE8D11A28BE2DED14CA2DC -:108D2000B8F810564DCF28C1CF99C777E423570222 -:108D300000505EB09BCCF4FD8CDCA76D8CBE6FB494 -:108D4000CABC9DF2B20232F911EF39CEEFE16DB13A -:108D5000FF90E2044D6FF3FB04F7A4783EC478E67D -:108D6000905A81E13D56B18AC711C4D745C72CA896 -:108D7000176B5BE93B70895506F26B5D69AE3E404F -:108D8000E770B785BE1FD705FDD1CFD56E3730A2AE -:108D900057601E3DFE54F8E9BAC645718BAEBF0F51 -:108DA0002279C7747ECE7A37D7BFEBE3CD1CBF6C78 -:108DB00067FF807CBB313E92EEC72DBAB6FA6DE4F8 -:108DC000235BDE131D1B54FF33FAFF87E32F987FCD -:108DD0006076A5A1DE69AE0AEFA73433D7BB93D185 -:108DE0005F7AD7CAA481F4A87EE3223683DF1C7D94 -:108DF000E9719186721E07D1D6A9EDB3D1B6465856 -:108E000026E36FDF332E52D64F5C24502D20BF1F38 -:108E10008EF513103EDC6FFD5DE322CFCCE5F2F65C -:108E200072E322DABEE7AABF170162ABF91D14177D -:108E3000A07333F4AE2F088E3B707DE5F89BCCDF3A -:108E4000639C61BE5A7EFB99A39FA15FFFF0EE83F6 -:108E5000CFE073C68527CAD6005E144FB393BFF721 -:108E6000DD1FC53CCC870B8D1FCC755842FCF7F835 -:108E700083F849EB10F8BDFCE0FA62DDBA728DA10F -:108E8000F1807C5B68FB99F1A1F5CE61A16533AB04 -:108E9000263CD5EF7743D4DD9427D7781B73F00CAD -:108EA000F1A0F3102F5E360F3387DD97866FCC91DC -:108EB0004674DFFE3EA77BD74BB7BFB196EC580395 -:108EC000DD9F3FB7A8E19EB764C40F33F3D0384E9F -:108ED00005F1E8AB9F8E7F87623A92DB7323B45F24 -:108EE00096C7BF17D5279EA0FAF387D71CE8C80FEF -:108EF0008EF70E76AF9E03FC7CB8EDAC807AC8F09E -:108F00009A97A9FEBAC59307C4A38C9A431DF94149 -:108F1000DFF5CB30BA0CE8C7C8A87995DEF7A7F71C -:108F200018640FCFDF2B33CB646FA9796A192ADE5F -:108F30006494717FAB94CEE5CD1613976F1EA8167F -:108F4000AF82FFB5E9F3DD385F3F3F8DDFEB60C0F7 -:108F500085905F69E3E9E59926076C0AD72333CA50 -:108F60001EE17245CB176CD3E7C5B91F44F808550D -:108F70008DD46E6B9EDA6E3FD74FD96C26A15C867E -:108F80007D86CD137D748E1A2FEA273F8D69F6E317 -:108F900082D73FC4FCBCCBB61FFB1977466A20ECD6 -:108FA0007DDB3D85DC7EEC8C08A4201FEE3485D76C -:108FB000DF1B17CCFCE99C01F457CCAB4598F66B52 -:108FC0002F7CC7BCDA0FD57891162FD5F26B99D1CB -:108FD0003711BFF39969FBE0068A83F693577B8FBD -:108FE000DD11C07BEEDE8A08C776F6DDFDEB279C3F -:108FF0009C9FEE98C3B8FF5E175FD0AFFB83393DEF -:109000007185E373E85E58F8B842CF3E93C3FBE343 -:10901000AE98A7DDF757EF2B39B9DEA79814162EB7 -:109020000F54CB77D7BF077BE8CC9C20BF9EBB2ECD -:1090300083FC76F5268EB71E997F4F50D31F6DA8FF -:109040003F921ED542F5D1555C9FD4F42C498D6BCF -:10905000E8E909E8E3AF388F60E374ABE9893DF4F0 -:10906000711DD007D0E530C6E34A06356F74989578 -:10907000A7A07F573DAAAFFDF4B5FD3BD94F753B87 -:1090800023C87EAADAFE06EA55ED35DC4FD869AF73 -:109090007E03BF7FE0794F24BDA9BFFE9A1D95389E -:1090A0002FD48EC2B822E263A2CD27C857A01D15C7 -:1090B00030B9617DE56847D9306FD53DAC28A1AFA7 -:1090C0003DD575F79F29DF15ECCD94A27F047FD0A5 -:1090D000F9970EAA791007469E25BF8958C3ED3D22 -:1090E000B186C7438D653C6E6154B81FC50CF2084C -:1090F0005D819A1F658B23D48FD295C2FD2889F993 -:10910000D57ED4034DD32C9242F291FB55B4BCF6DC -:109110007116DF1B781FA33ECBC8300F1D1455B24C -:10912000032D6A7C83957179A5F94DF479D3369D29 -:109130009F44EF47C92F0AF59B3C2EC8F74E87790D -:109140009EDF5CF016A2ED7F6E5D11857E93177D2C -:109150000D7354BFC9A3B89E7D1F72BF49D73E6E21 -:1091600017B95181B92A1CFEF58953911F64DDE1BD -:10917000F5142FD3FC5089552A3CD4B80FC217E1FF -:10918000293A393C6374F0F40ED3E2422A3C133896 -:109190007CCB8B5CE47792109E522F3C353F95F749 -:1091A00070077D5FDBB2CE227B089E9F91BD6A4235 -:1091B0007822FCBFA71FEA9622D52E55E139F1D1BE -:1091C000EC87F03BC1931E2B3D86CF29DB6E8BBB1A -:1091D000019ED3763E548A4FF63A8F13FC752EE7E4 -:1091E0005798D91D4C8F3715CA21DF83D7E0A9E1E5 -:1091F00061AFFF8E913FB65CE2FEFC72150F33103B -:109200006EC1FE3C4728DCB6A8F992C6FC6A0FDAAC -:10921000BBC37570D3F0B01EE186FC2EC62C7BC894 -:109220007F572BA03DD41F1E0E6FBB3C3C7C588744 -:10923000873FDB9C7D2FC2EB85ADA56FE1F3E7BED9 -:10924000DBA2105E7B773C34A71FB82587F07974CA -:109250007227F485DB8962F70EE40F331C3E23F19D -:1092600059C037B47BB7374DB486C66734FEE8B40F -:1092700086931F17F72FADA1BCC2FAB235C41FBB2E -:109280007AF863B71DF3102F953FE6CDE5F7FACBDB -:109290006BBE7A6506C035AFE604D19F11E88FCE6C -:1092A000ADF68441CDC76011202F12CB981FE3C7C4 -:1092B0004398D51725507E02F14D2FE639E3074A32 -:1092C000F57E0AE9D5BF09441C4C3024011FC7DCD8 -:1092D000A92B490EBE5934B92F9F6D2F3390FF67CC -:1092E000BBEA1F2C5BE03A8CEDB4F8D66E97F276B1 -:1092F000D1F7F36B1F2F0AF21776C6B01EFF1A7E46 -:109300001F3CAF669B807928436A6F25F99058A669 -:1093100030940FB7CEE67462CC9768BF7DFD6DDDEB -:1093200079682774E28DF62CC2838F110F3A6B9EF9 -:10933000243CB87215F78F74D69C8B0B8F073511B0 -:10934000DFCDCFB83D444E7A6BF8774C3AEDCAEB9F -:1093500019978107CB543CD0E424CA1BC427635916 -:10936000E051F4630F017C88484379C9F9B108F2F0 -:109370002A0AF623F6E37FD4E8A10BD6661984F710 -:1093800084F5F900D5B4EE7365B9FEA903ACEF928C -:10939000F300D4B864BD1A975C5AC3F3573BD77D2A -:1093A0005580EB3D5706F601C0657B9983E1F9CD09 -:1093B00002C52A600B9EA74FDEEAB0B909BD71480D -:1093C0002D9E7FA2D8958AEF67004E25C5625EAFBD -:1093D0001AEF19A67E075A87FF80E7A3E6925F4E31 -:1093E00022B9A1F9D119EA8D76C46F6534D64F3010 -:1093F00057274B84DFEEF1586EDF7727E52FF4FA1D -:1094000007793EDCF7F66F459B29BF52F36F79ED84 -:10941000DCBF55C10205685F531C01F976AB85BE00 -:10942000D75029C866F2AF95B895B9A4F7B8281FE8 -:10943000D6BDC02A911F6CD5AE64E417E58D22C954 -:10944000EBFEEC92BE7476997C46A5BBEFC067AE8E -:109450009F7B697C6631EE2F88CFDC30F77BF099FB -:10946000F78B42F90BEA9D75304F9E4A4F3DFB56F4 -:10947000E3F818BF8AC80AD247D5FDEAE9A88F5E8B -:10948000FA7F1F5DDD83700D43571BF1FD65D055DD -:10949000EB45E8EA413CCF20BA6AFF17A5ABA72FFE -:1094A00085AE94B92C344F3A8E7FE7795C9C81E786 -:1094B00059FE1FCE931EA3DAD9FA3C69C6AAA95C4D -:1094C000046743E7A396E74D6232C6992CDB5EDE64 -:1094D0003456E6E305FB3B99CECFC9747E4DBD7E85 -:1094E00017C60F1AE2F73CFCD4EF0E8F855F9F7E04 -:1094F000F6BF49AF7D7BA640F7C9E78DFE6A3FEA1C -:10950000A0C51B97A9F30CECF7FC67FB39F127D832 -:10951000AFAADF5763D4DDEABD81CBF37332C7ADA9 -:10952000F47DF3F66AE640B85FCCEFD95ECBF3A6E4 -:10953000B5BC66D74B950F2F9CC4F3E9D0EFA9F7C4 -:10954000776AF9CAF5B665A4E79F54ACDC1FABF3A4 -:10955000772E8B936FA17B8C7DFD9D91F3FE01FE99 -:10956000CEDBE7C8DC4FA3F37B96CE52E2E70D904B -:10957000CFD019E360C8EFF26C3E01E3B5EC4236A0 -:10958000F97586D802F47DADF29A1CD2034716BB5A -:10959000D3701C637EF7E72F4EA27C03070EA5E76E -:1095A000CBA067A6CFA33CB67F8E9FE09FE5E7FBED -:1095B00068CEE5DD9FFF08E13D79807BF472E0B184 -:1095C0002878FF789D9DBEAFF5FC6C59CD3FE84EE5 -:1095D0006981FA77EF3A7310FD13BE3603C3FB6D52 -:1095E00097EA3F6AB8885E6CD6D9475B7AF462DF47 -:1095F0001B5383F4E286F5CE7DA7C38CA3E9C5BBDC -:1096000074FEA3721BD78BCB6DDD26B40FCAE3BFEC -:109610007E05F34E8D55AC03E5E210A59AF4E144C6 -:1096200089513EF1FF8FCBB37F685CFEFE79A1715B -:10963000F9096A3E0AF278FCFE4F97E6479DC6F5A7 -:10964000868D466EAF78157817268EAE8FCB0FBFFE -:10965000B087E2F2ED7BAD748F6FCBBE663E5E0EDF -:109660009330CF3C99A9FA5A11F797EAF58FC74D75 -:109670008A356D12E2BB81EE13E23D41F28BECB50F -:109680006E437FD3783BCFE7CE7D67F14ECAE7D6F6 -:10969000F443D043492F2E0BD07799CA250723BE18 -:1096A000133FCD4FF1F15A81F06BD93C4E6F4BF324 -:1096B0007DA41F0E2993047E4FCCC3EDF8541E7772 -:1096C0008E44FC82A662268FFB4A474407C69DEF64 -:1096D000C3A6D3F1FE2AE3DFAB986EA0BF43D12E21 -:1096E0007427215F6E1594647C82CE44F71E9F8D93 -:1096F0005106E3DF93AA4F31D0DF933A54D09884D8 -:10970000EB6BAA6B4D42BDF015D52FDE5AF009E583 -:109710003F98C6833E9846CFB07F77F4C1F982FA6E -:1097200077043B92E87B08ACE543C2AB4C33E37F64 -:10973000E7C7E15F8EF474DA46FAC203828FDF1363 -:10974000B25BE93E5ECB18737225ACA7D96E266D6D -:10975000C23B66E6913478DF9C2045631CC09B9633 -:109760002EA1FFC81BD3F83AFA419AD3D219E6FBCF -:1097700037954DA1F879D3056030D0B37EECA8774A -:1097800027C3FB8D4280BE1BE4996E60984FD8368C -:10979000666672F0BD4C51D2CB4907C9055136D02F -:1097A0003D3F518D678B7DE2D9A1F1E949EABE6564 -:1097B000D6B288EE81C69B25DC6FF998920FE99EA0 -:1097C0005BBC99F282CA4D8C7FF7630CA373D1C343 -:1097D000AF7E7D685CC1680B5DDF460C4C531EF6A6 -:1097E0009695881F0D0853CAE3BE7725F2A5869E7D -:1097F000FA465E8EE0E5AFE7D5AD44392833FEF793 -:10980000491A3279DE65794209F1E1725320EC7729 -:109810007E2FB61E99F914753CF63F39DEC631E647 -:1098200045BEF1171FAFF75C407DFE0EE36AEDF415 -:10983000E3EAFBFD4FB5EF6F9F89F3B5BC7A46793C -:1098400010A422AAF7D9504F36AAFCB03E778ACF8F -:109850002F233FF070BA883184CDB3ED9F3E82C68E -:10986000E749BDC46F697CFCF64C4DA11FF923BECE -:109870002F49EAA59B9EFC0B753CA87A15E5C3D63B -:10988000F942CFBAA5C1BDE3FEA62CDB8F761CD86A -:1098900019729C230CFDA9791AD43E8DF26D283FD4 -:1098A000868D65C447B4F646755E7DDEC66E152F9F -:1098B0002E376FE334EE6112C91AB207BDBF6DA136 -:1098C000FC25861FA342FF5C9644F7E1EED5DAD96A -:1098D00019D971DA3944B0DE1FB4D392B482CC46C0 -:1098E000E23DC38DA327D0DFA77C74F7833FC1FC83 -:1098F0008DCDCF6CF8233E23474EB87FDA24BC478A -:109900006F70A8B9D4643F69F934B67FDBFC35EADF -:10991000A9FA7C95C6F12B5AE8F882CF311DFF2EAB -:10992000B2A0A07FDF62B36DA7EFF95805B21FC4E4 -:10993000871269FD4995A1E7DE2E281FE077FF3CDD -:10994000F709C447231CA1F9377A7BA3A9E75C4335 -:10995000ED940784F071EFD7E6733923EAEE89B608 -:109960009A64FA8E6DEB46112399AC759D85F8D9F2 -:10997000EFE72F5989DF19BF03191ED4B75F63A61C -:10998000BF6BD56E97AE5B8465559E6971E607AE79 -:1099900018E50BFEFB47AFA29C85F95AAE31933C0C -:1099A00060C66ECA63D7DF0FEF6367E9F0EE6278D7 -:1099B00076C3FC5835DFC04772A5C7BE1F6DE0F700 -:1099C000A0471BFE25EE41BBE787B7EFBFEF3D6821 -:1099D0008AEB25F4A55F2DFF6F4354EA62DC7FC359 -:1099E0002C337D2FEE72EDDED6752B495E786E65D9 -:1099F0008E0C47DFBC30D74B23097FC42691FC7106 -:109A0000BDF8C5EDDA5FCC33F5FC9D166B109FD425 -:109A1000F2821E52EF153FE46AA4FC19AF93DF2BCC -:109A20008E685949F6722BE8619857A5D9C727A7C0 -:109A3000A54F1128EF47F1E0773D4EE6AA79415254 -:109A4000687E0B53F3FBB4F95AA7A5D37C5EB4C769 -:109A500007C003A353CDDFD38DD7C3AFD1EE0EB272 -:109A600097C1EEFEDB7CD8DFFD36073AE3A0FE654A -:109A7000AA6793622FE91E6817FE0AED7E50AAD0EE -:109A80009F48F9DF0A551CCD00800000000000004F -:109A90001F8B080000000000000BAD3B0D7054D57B -:109AA000B9DFFDD9BB1BB29BDC0D9BB8C1106F02A7 -:109AB000D1203F5E304913C572F303244AEDCD0F28 -:109AC00009BE01DEA26871ECD4ADB5BED03ACDC5F9 -:109AD0006C4888084BC4065F1D8D54FBDAB1D5D4A1 -:109AE000D7D7878EED5B90E7F84FDADAAA333E1BC3 -:109AF000D1F2FA3A9D37E96BB1E98C2DEFFBBE73D9 -:109B00002FD95D36809438E3E1DC73CE77CEF9FE51 -:109B10007FCEB655D53AF91180E350080AB61F85B5 -:109B2000CC35610078DF6706CC2500A7E86F1540CB -:109B30007FD20729EC836A0260BB0E263775E07C72 -:109B400058E88327B15122CBF9FBD690ADCA4180AA -:109B500012BB12A078667D1BEC57EFC2F1AB7C63A1 -:109B60002D500390D80ABA834BB684922AF5570336 -:109B700038801BAF351A031508B7F505DA086055AC -:109B800078240232C0B2E70F94C5687FC7FA7975AE -:109B90001DD054FE5BEC9FB09B717DFF1B8A791F2B -:109BA0007FD10FC770BD1A5560182148CFAC8C4EBD -:109BB000E279D4E089F7A000E0BA29809680587B4A -:109BC0008AE04F07A0A57AA6DF8890D3FBCD81D28B -:109BD0008CF9ABF58A8C71052C3325E1B9A38B3256 -:109BE000E6856A6B743A6F9BB13CE3FB0DD50D19AA -:109BF000EBA1453D3E89FD95F8DFA94A8227FA3C55 -:109C00005E01105C82FDB4F52AA4F571FC1A3B14C8 -:109C100039B1183B9F81CF9C52882EE60620BA802E -:109C20006C3E897829793E30998FF803CB32222512 -:109C3000880F1A3200BE6CE3E25AEC074FC884FF6B -:109C400047F271EF52C4B33E29139D401F97F83B72 -:109C5000C0F830223BAA5A3C0FA2A02770DEA5E034 -:109C6000483AF6435148527F3E24793EFE251F6C08 -:109C700040B60888F5051D60EEC5F1FC258E24610F -:109C8000BFA8154C05E105CD0989CEA9E37A05F9F0 -:109C9000A01452DC2F6B85897E866FDD47EB4B7BF2 -:109CA000411F2825B00E8F8F6D0487CEF33898E0C2 -:109CB00057081F36C002000DE2DC5E064611221175 -:109CC000BE0DE60AEA57C1242115A93A2651FF1212 -:109CD00018D7A90F90027B2936936AF84480A70011 -:109CE000F1A9C7AFD92DED74C2A30B4E1EBFD1DAB7 -:109CF00066237F77DF545B180BCEBE4EED7D71BCC3 -:109D0000E5EA99FEB76D83E542ED5DCBF2A2F6BEC2 -:109D1000C4E3476DFB2B36D26319C20FACF8F4F8DD -:109D20005FA6097C2624301D9C9F78EEFAE8161C5D -:109D3000779E0B985540F8457C125FD407A65E6964 -:109D400010EB891E11A407E1BB6809488483F9441C -:109D500007FCAE211D76311D930CB73C0EE60E7745 -:109D60005FEA97221D882E63A0CF21BC2AF14F47BE -:109D700007FE4338971C0A3C3E2C1176912E0B2E81 -:109D80000A5DBE752174C9A607DC3B17A0E16CFB18 -:109D90003A4CC76F49A93C69019105E983F7919055 -:109DA0003E84CF28087A680026E12917FEA99F572C -:109DB00003C67DDC17F3899E4EC30CFF1722FF8B71 -:109DC000BE90AF30D241F4059D22242FD88FDAE324 -:109DD000BCBE682BD80F94123D2C469E0F62DCFA55 -:109DE000614AA2B65232995E0B145BA67EBE9412F3 -:109DF00048464A923E28009DE9330FE2DC467C53F8 -:109E0000874F91BE0ECA634E05B5CF36D23EFDEBED -:109E100050C390CA0F8D34325FDE0E7A15F25DB9F1 -:109E200066B1FE2EBF52351D231D5FF7317C30AC6D -:109E300003646FCAE5100CD7CCEC9BF099D124D207 -:109E4000EB58E8C491187E9F53AA80DF9CC1F37140 -:109E50009FB81FC1542E257910F211ADC7B384CF1E -:109E6000D46F5155F06D701BE20FF1B19906104F90 -:109E7000D2D0BFF3F7479A85BEFBAE1DFB88F885AD -:109E8000F413E3CF029DF4936E02EB4DD9707E4341 -:109E900076F1E490DF203E85E4A815C07DB6B8FBDE -:109EA0006C19F27F2015A4DD33E18794A79F2B69FD -:109EB000BD5DC8FC6C4A10A83BFF7517CAFFD05B9C -:109EC0004CCC764EBE6D7C6665E1E492D9E76924A0 -:109ED0001F73D3D7093A6911E4A7208DBFC4E3E704 -:109EE00082E3EB3D9C21671E1C5FD46638BEDEA377 -:109EF00042DEC86E213D6F43BB358CF8FE474BD721 -:109F0000045F4EFD27D9F39BE30526D9734611CE96 -:109F1000BB25298D0D233FDE0A718DF85482850EF5 -:109F2000D16FB32399C338A572D7D602F617A045CF -:109F300027FC48A96B95538B3F051E5D3C6D4EFD7C -:109F40008FCF08115E43F0A1375E3933FEC78D0B0A -:109F50008ED51AA4B483D544DF7C97BEA8899CD73C -:109F6000F09CBE4F0A615847EECFFFC61BABF07C9A -:109F700003BF504CA582E6696021BC3920EC783ED5 -:109F8000C9E902E297F1D41DC46FBD853ADDD79BC4 -:109F900007EE3C076216DD331FF500C195F37733FA -:109FA0007FE6176886C2CC8F1A27FD1E01E4BB121C -:109FB0004635FF156BA914C9577153C0DC91095F71 -:109FC0003A45EB112694B8F790CEDC7F29F5033C97 -:109FD000D478CADDCF0AA4ED97D5F745D3FA20C6C9 -:109FE0009DF4F9A606A934BC9E961757CEBC7307FC -:109FF000835AA6BC64ADF3E8B1C427F8635E198C3C -:10A00000EDC0F30E0D1D6C247D335A0C861F8706A0 -:10A01000377F47029CDF44BA98EC4F0B8CF925DA66 -:10A02000C718AEC6BEAF2CC8FC73C96FEDD41D08EF -:10A03000E70BF57EDD409CCCFBBDA537E2F86D65F6 -:10A0400001D342FA26DCF94E0BFA5962FB5F915FAD -:10A050007AAB7B5EA605CAE1BDEDC2CF52C35D3BC4 -:10A060005FC3F9FBE629A0905E53369A649F6E5554 -:10A0700001E616617FBF8FFD3EF4EFF83EFE964C81 -:10A08000BFEFB6477C197D5F969FF8F576F403899C -:10A0900068AE1F38D00EBC2F9D67EE8ABF1F3E04EE -:10A0A00023AC3F97AA13B29EC3AE7AF8979E0932AB -:10A0B000FE7F528C78A575605B7762DF8F78247E97 -:10A0C00045455D508B78B2E89F06F9C93FBA8BE6EB -:10A0D000FB4F22FFD27C25D87227D1E152174F20A7 -:10A0E000CE65E17F74EE6C7FD89FE50F679FDBA3A1 -:10A0F000C3631E7EEAA08EF083FE39FB07DEBDB28D -:10A10000EFF3421F6A0EE4A59FF605B84DF5E9DCB2 -:10A110001EE98B727BB4CF801674AC5EEAABE6F6B8 -:10A12000E53E93BFBFDA57CFAD878FD9F44DA8581E -:10A13000667F61DFBDF2180993BA447FE50AE2DB6E -:10A14000B714561F3A1879EA02B643A0E2BCCB5ABC -:10A15000D5318BEEE2C63F97B87CB6D83F75D88F25 -:10A16000EB92A560DE470BD16E6FAD99897FAE9BF8 -:10A170009267E40428DE9933636780E29DB919FD94 -:10A18000E6C0A519F357EB0B32C63DFA3ED628E4DC -:10A19000666D7471C6FC7D2D4DA92F905FDFE0D7F1 -:10A1A000159DE29FAB33C66FA8BE36031E28EB4C4D -:10A1B000D2D3451BD3E8C6F7CFA4ABB6EDEC719074 -:10A1C00047E7F7DA33E3A1D9E89BCDB71E5E8B4EA4 -:10A1D000E355C495098A2B0DBAF712690B82DA731D -:10A1E000DA2FB1C00ECDECABD6637CB9ECE2C797E9 -:10A1F00005145F56E48A2F3FD2897FCF195FB66678 -:10A20000C6970559783B577CA97564EA95F3C5E76D -:10A21000E6F2F81BB514EFBDAEB01FA8B4C6D9FE68 -:10A22000CD9D50CCB508B7D8F5C74224F3386F732D -:10A23000ADC6FEE53E988C92DDDF2B215691FFE7FF -:10A240002E314B49DF3C1DB64A6EA238BF4D360F4A -:10A25000E292171BBF1925BF63D78EC7A36894600E -:10A260005187CCFB261B4F6C22B9520DF4E3246EB0 -:10A27000ADB11CFE8937FFAB033EB6037B37696384 -:10A2800012CEDF1BD2BB3750DFDD0711C2F676B42A -:10A29000F6F231F2FFAEEC3004BF801325FA3FB87E -:10A2A000A9AE948D948AFDA534DD643B3E1C32AD8D -:10A2B0005B887F7E1304073F3D20E90512D98B4D53 -:10A2C000B2FE24DE73B475C5BB5BB1BF2BA8992465 -:10A2D000F089705D29F197B219DD1EEC8FB48EBC48 -:10A2E0004CEBD52A99FB894D971F23F779B4586F0A -:10A2F000ABA4386F7525611A94439FF4515E231106 -:10A300003E11A5F5FDD788F5B3D147D1D3EC39700F -:10A31000FE82CFAB2C94531AC2515E38F15782A7FC -:10A32000A4DB71D6E3997EC57058A32001D6FF7CCB -:10A33000E1F71C9554B965111D4751E6094F9B374C -:10A340007514523CB5D937599CCB5E0CA07E4D5D3F -:10A3500091E66F4632FD846CF8FC5747F8C53F59CB -:10A36000748D123774C1BFC48D6BC652843748B622 -:10A370005652DC1B147679363CA8C14C3C78F01957 -:10A380001EFE4FE9CDB3F2D2F080D74A91BF73479A -:10A3900087C4F4FF22F141AD3806C51DDEB9D4569D -:10A3A00099D779FA01F978C338F1878BF7289A0C95 -:10A3B0009243EF1C5F75E1DD739AAF706A49DA3939 -:10A3C000566A2E3C93E3E2AB342157F02BC57CD286 -:10A3D000C84127D77FE3F51533E3AA7BFE2B0E6830 -:10A3E00019FA7788F6C77BBCBDB1F3ACF1F2A2B124 -:10A3F000CC75DFE9003EEF958A75E404F95257C841 -:10A40000634F22A8C557C82CCF27D1FF22BB361BCC -:10A410003C8FFE2C6225CC5D407ED9CE4807F3F9F7 -:10A420006CEBB4B109AB6219ED0BF171E4AF45D13E -:10A43000CC7379F3BE73FA5E5F8139741E74C8C938 -:10A440001EF9C75216E9693FC291B0AD7EFC6EFDA0 -:10A450006CF7F6431A7CC4E74792D0574E18F8BE03 -:10A460008977C7587EE0D0D48724DF894525C63058 -:10A47000CB0B4417D6913F22EEE5CBA2D3709E8042 -:10A4800033B25CF8A9236EDF592AE042BA9CE2FAA3 -:10A490003C37AFF242C702C6BB467A8688AC5AE563 -:10A4A000C41741F5878E8EFC3027B80FC2D8FA2327 -:10A4B0005B1C6A57951B7BEAF15C238B64B66323B4 -:10A4C000A1D8E303A487160573CAC76BAE5E1C222E -:10A4D000BEE5F8092C99E44EF284046232D26B9402 -:10A4E000391FE0FD8EB0C867E9C9FA9B118F6FBBB9 -:10A4F0007C81F7E1F5D9F0DF3D13FE13C4AF0917F6 -:10A5000038C1D982707EEDCA0590412971E33EDCE5 -:10A510002F6024EBC95F98ECD0C5B8BADCA4FB8FE0 -:10A520008473EF37E9EE67C97189E65DB251AC8794 -:10A530008058B7579ADA705CD093E589F6A7F17C1A -:10A5400033533F64C3CDABCED4575A59E6FCFF75A5 -:10A55000F92F3B1E7A40CA7DCEC24E71DF55E5C051 -:10A56000F688F8E2BE1C7C912DEF1AE53F11EEDF74 -:10A57000880EBC9FD03B4175A229BF86EC3B98FD5D -:10A580008CD8C37CDFFBF26FE43879E00691E7D02A -:10A5900054A1B7CB362018B4C7F64F5A1CEA2B7714 -:10A5A00083EE0F9F89874F1BEF91BD71D2D6873BFA -:10A5B00081CFA9A4C781788FA4CFB891F64DEE5270 -:10A5C00080FC80E476FF865C76BBB8C3E7E95D8EED -:10A5D0006B55972FC0AC0019D71F784BE1BCC081D9 -:10A5E000FA9D1C17276CCD902A284FF1086CC7F1F3 -:10A5F0003F5A32FBADBD87EEFDF5ABB8EC784B654D -:10A600009D24B31CC1AD38FF38C6C5E43793FC6543 -:10A61000E46310B181BA99FD922D95BC5F02F79366 -:10A62000CEA2E7541BE3D66567C23B6D8FB3F2231E -:10A630000325B1DA4EBCDFBEA0A8B3285E7EA42BF2 -:10A64000725E791D0392A95ED22B1B81F1106A1BE9 -:10A6500081ED944F888A38E348AD5FF0D776C98D95 -:10A66000CFA0053C3D857FEB361A0FCF25FBF28E40 -:10A670001FAA70BCE9A9D755EA8F94CA75143F5F29 -:10A68000A54DDE7F158DD7F9587F3422255319FC4F -:10A6900091F2CB513E8FE6B68A685312B5CD81FC5C -:10A6A0000C7DBD5ACF8C3FF64C1F510A893F753047 -:10A6B00025C4F39E46D32A24DD634EF6D3F73DAB83 -:10A6C0000D73D8207F38334ED9D3A6097D5A21EC9B -:10A6D000CEC861E361F2AF067BF3D8FF7CA04C16D5 -:10A6E000F75E0863C40F6D46665C33325EB96B215A -:10A6F000C959D2C7F9F2EF8F8BF95B772C1FA3B83A -:10A700005477FDD5ADA54DEC87C280987743F5E22F -:10A71000ACFB4FE8C417C9ED3E20FC0F96DD3C446E -:10A72000F9D00F12BEAB495C5EED3432E2C22D03AC -:10A73000B7729D6840839BE8FC7B3669CCFF7B8ABF -:10A740003F38700BE9E9E2398CE7D14D5A692C4D5D -:10A750001EFED6E9673918DD24FC8B621962E339E5 -:10A76000C6FFD629F4D0E76E07BE4F01DA65033F76 -:10A77000196A3CE5277C9401FC335D27FAD1437CC0 -:10A78000FF5619AAF08823918DECBF65F359B0AB41 -:10A790008AE19DB68FF572061E7D7E3BCE79EE1B5B -:10A7A000C0207DD5D28A7D8AEF376A40FCE68FDEF5 -:10A7B000CDF72CC27E1EF603AD4947C57E6061EC25 -:10A7C0006AF25B5FDCDE334479167F44D689DFFCB6 -:10A7D0001B6FB33B697E8D0FF2707C000C294AE73A -:10A7E0007424207D6D40AC95FCF591A8AC53DE66D9 -:10A7F0005D62FD36DA7F5D640E109D37B7C9BCDF40 -:10A80000494BE3A45531391A94FF2A09B2DD7DDFA3 -:10A81000177FB807E7BF8FF47260E65E873A2BF9BF -:10A820009E794666FC1C8024DBE195D6C446DA6737 -:10A8300065BD46150D38D270E200F9EBA3B57ED3A5 -:10A840008FE71A6D9018DF1FD7FAC6F0A8F0536D86 -:10A8500042A17D7FFA31F246452EF93DBBDC64CF43 -:10A86000DF53DF11207ED809135D841F675A66FB12 -:10A87000953DAFA14BD07F27E285F0ECE079AB2886 -:10A880002E9A42B942E8E169FBBBB760FBA54E9541 -:10A89000E77DB55476A82E34D8A6B19C0C866243C9 -:10A8A00015D4477EE7782812637E1E298DB01C7A66 -:10A8B000FB8C34745713BFBC519BC77EFB973B4F37 -:10A8C000DCEE2C44FDA1FCFE5F9FA1F8A94C637A4D -:10A8D0000EFAECD4ABC4D76DC25F3C3AFF1E96BBF8 -:10A8E000818D3703E10D9CF83B54B71AA86960F8D5 -:10A8F0005EBE6164BEC8270D44EE7228BF91AA17E0 -:10A90000F905ABF820E7F3BCBC52A3ABC716FBE3D9 -:10A91000AF54D1BADB55511756CA12A40FFC945745 -:10A92000A2756A66BEEBBAA9CC38785E561C9C9DAF -:10A930006782C0C4C24EB4A7BFEBCCCC2BD1155894 -:10A940008E6BFC1C2F8ED68B3828E98B97EA4BCE6A -:10A9500094E3375D3F78A22F801C00F0F33E9DFB0F -:10A9600005D61F76CC45506FF545F9FBE7573E2ECF -:10A97000A5AFDB53B33E60B0DE988C12DC6C7D91EA -:10A98000CD07BD9D7398BE18A701D177CF14307E37 -:10A99000430D2B52C4A727FF041C877EB6652208EF -:10A9A0009567AE4FD139FD94FF12E73C4AE7F45367 -:10A9B000FE4B9CEFE53E83DB57FBAAB95DD3052236 -:10A9C000CFEFE983CB501F20DE5ACA449FE49FECAF -:10A9D0007051E4669BF8CB1F557592EF40593225B4 -:10A9E000A5E983D150FC5DB2CB83C541E6BFEC73D2 -:10A9F0005DDE25BB762F7E13C1DD837009EF2F6EE0 -:10AA0000FFEF8716D03E6F29CC57451BBBB7B1DE91 -:10AA100041BD90C7FE86D087C9E220E71D46B757E3 -:10AA20004951EC6FDE211CDD73CA3DEE3386EB8E9F -:10AA3000A0BEA6FE20CA39DD67B0E1833B689F8FC8 -:10AA4000FF32872A7C48EF5FB1DCBF8101C8DC8B15 -:10AA500028F79E9CBDFE8B43DF233933C0EE39249B -:10AA6000EECF7A70343491A4FB0FFE52815C78BB38 -:10AA700050BA82757E7EC8983A75F8542447DDD066 -:10AA80001275C3FEF11F71DF59075085FD477D56D2 -:10AA900080F8E0D11DF259EB868FEE387BDD706CCB -:10AAA000BF0C7E7DE61C97C224E7592984A73AE0B3 -:10AAB000000D617B4357EC962EF623455DD168A0CF -:10AAC0009C03F5F539E43F1FB5ADAD3C1E2962BBD3 -:10AAD0001F55C75364D7A3542F37E8FD82C3754F62 -:10AAE000CACFD2FB85ECFBF7FB269BF87E3885EAC4 -:10AAF00095D9F54929F86351DF5F20EA905E7D72B0 -:10AB0000993679F07EC2D34D01C643FF73D7BC435B -:10AB1000F52FAF8E1F75EBC0FA36D077887BDCDB64 -:10AB20004571D00BA21E0AD7E03D96D3269395ED32 -:10AB30004BB9BEB983EE71AEF39F6FDD709DABDF95 -:10AB400090B9C7489E7FEDE2D39BF74D92C75AF26A -:10AB50001345DE1A0A34D6F34D4F0541217F39A43F -:10AB60001D2439D90293AB499EFAC3C26F4BECF353 -:10AB7000B1DF36DA65F03EC59AC5EF178ABF966732 -:10AB8000EE403089C37A01E591AEE9B446BBF81CCA -:10AB9000C9AE0E3AC790C2FAEEFDAAD5FC8EA94DF9 -:10ABA0002A64795475AB3C5D5F1EEACAFD1E695587 -:10ABB000F95407EF1F9281E2AD449EF9B241F8FECD -:10ABC00089CA70DB40BC5782ADBA3484F7EC0F1EE3 -:10ABD00067FAACAAF22F27FD74C8B5AF8950EEB85A -:10ABE000EE59171FFFD01EFB21D1E17A986A26FD8E -:10ABF00086A26D3AFCAE45C46B87485F8A78F75EE3 -:10AC0000B96E26AFF5922F7688EE6B7D5FF813FE56 -:10AC1000A8F0EB3152E37CD007EDD67304771DF139 -:10AC2000790D2B2A7872790E3977CF714797F51FF6 -:10AC300004EF98BBDF32DDE2BAEB3290CDFE485A2A -:10AC40005DDD38BFBABAA4FF58D4D3AF157C0C2F42 -:10AC500038820F9B40277942FE3B46E7F3DE972C74 -:10AC60007B7E5B05D75D2EB0BE9DDF61BD4DF04E96 -:10AC7000D9F6BBD4BEBFBD0718DE79BED758551E66 -:10AC80008FDA48A7C13CE1373FDD686EB0D3F23FB1 -:10AC900073D60B7B3267BD88C717233B4D88776F10 -:10ACA0006CC72F87FA00D12B1BFE401F8C531D68E9 -:10ACB000B6FDB55D7705284FDC5FD614A0F768892F -:10ACC000605321F507CBAC28ED3FD0D7FADC4755D0 -:10ACD000C44782EF9DF9221F9144FDECA4E5494F42 -:10ACE00075297CAEE63248513EDD1F147E911FE38C -:10ACF000456329F9CDF56CCFF1FB38A50EFCEB0DC2 -:10AD0000116F5B265841728340227CA18E3CBD9E10 -:10AD10004C5E73591CE85CB3C1515A703DC5A365C4 -:10AD20003AFB2157AED7196ED89267E278387F7C0C -:10AD3000ED3B07BE8ACE812F6F9E2777D978AA5C1C -:10AD4000AFF0F95E0CDFC3F7824F9A59CEFCA8F042 -:10AD5000A89E5FBD5EE8192568412CC4E1BF44F898 -:10AD600049D0039B2533F8455F91F1ABE8715EE76D -:10AD70002F3321B694F0A14B848FECFB2F7BFEBBCD -:10AD80002D84B757B608BDBA4A75F5471CEF82FC4B -:10AD9000B9D3D56FE0DAA5B63C6177D6C1CF8222B0 -:10ADA000AF2DF87419BAE381A233F5ABD73EEDE6C7 -:10ADB00095B3BFFF6E7D9EF0878C71D6EFFDAD021F -:10ADC0007E2824FCD083432BD87F58535A35275DE7 -:10ADD0003F5EEC3A61765DF05C75C019BEB10274FD -:10ADE000CE3FEA7739EDC6ECFC713FF18F8FE42658 -:10ADF000C0ED19E3E576D424B99A6F398074DB1974 -:10AE00008E47897F060E6F7F87EA24EAEB8A49FE28 -:10AE1000A6AADA40F3D614C7593ED696594075A56E -:10AE2000FBFBAC1FA6C31D6E8F6D5B4FEF84F471EF -:10AE30008BE00421E5903DBA7EAE15B773D0E16E8C -:10AE4000577F7CD06E7F693DF2E12AD29D2B007E38 -:10AE5000695B7752FF7CF5D599F2D41A20BD7FE16A -:10AE6000F2D411A0FB0D96D9FC4E6BF0670A79580D -:10AE7000A7E70DBAF23438FF1E88A5C9D5EEF559FB -:10AE80007A27E2EA9D88C57231E2EA1955B7593E40 -:10AE90007C244F4BD2F44CC4D33316CBA31AF1E429 -:10AEA000C9953F92A720BD0F9E6A263F6500C43B0F -:10AEB000C66CF9FA7E7BEC61A2C355C5FFD7596118 -:10AEC000CCBCFF340C214F83652EBFCF7F96F9FF9A -:10AED00024F23F3D16EE0F5666F0BBD7AE9C5620CF -:10AEE00085A4B86E5AE2F6B3D3F9DCAE9ACEE3D6B7 -:10AEF0009A9ECB6DE37498DBA6E94BB96D9E2EE567 -:10AF0000B6651AF9FE6AE4FFE90A6ED74C2FE676B9 -:10AF1000EDF4226E5BA7AFE6796DD3CBB9BD7EFAB7 -:10AF20005A6E6F986E10FB504DA82827FF5339EBCF -:10AF300022F0BFE9507D74E0F0EDEF107E7CBAC6E0 -:10AF4000799444B88EEB3D3E35CEFC7FB04CE8F7AB -:10AF5000B541419F6CFEFFA03DF632F16D36FF8397 -:10AF60004FBCDB52E9DD560DFB396F327F9FE1EFBD -:10AF7000BEF417CA83A2FF718CE877A1F6FFB45F15 -:10AF80005992E9570E1667FA9503F33DBFD23F4633 -:10AF900075B0AD92C1EFC4F23B621FF2FE606FA1CB -:10AFA000F1585740277F2A115E130D627FF34E053B -:10AFB00028DF87FEC56F781EEA07B21BE72BAFBFFD -:10AFC000B4851C78F397C17139FE29FC93F7E99F8A -:10AFD0000D67CAFD6CEB3CB9BF1CAAF372D9D9222C -:10AFE0005FB3907B5DC87DA2CC1EA27C4B224BEE52 -:10AFF0003D3B8A78C890FBFC6E57EE5D392E8A88FF -:10B00000771F4524F7C857E16EC3ADFF64DA51D509 -:10B010009DEF6B15F5ADE688D0AB6AABD017AA9E55 -:10B020006947916F8ABB73F8138E2AFCE3B6AA7F37 -:10B030003B6DCFC8AE1645C252216EADFF69D2A19D -:10B040003CD6617501CB77B61C25F415CCE787D5C6 -:10B0500066C825FFE72D4761CF8E586C47B2E77968 -:10B06000F23470B88DF1E2D995C3786F2BCD9EACD8 -:10B07000D5051ED09EACE8CE614F56955B313BC7DF -:10B08000399BBA855FFADA75B6F017D14F243F25A0 -:10B09000E1CBED0734750BFFA7A8D5FD7D8501F148 -:10B0A000B9A8075B5B53CD54C340796EA2FDAFB323 -:10B0B00026FB4906FB8323113A3FCA6733D1E1429D -:10B0C000E5B3BA5DF885D03B97FD16AF3D17DF7B42 -:10B0D000FE8EC7FFD9F39EAEB036E4C2CB0FBA45A1 -:10B0E0005C7370E8D90CFED8A32EB8DE3472EA5532 -:10B0F000CBBC287AF5FCFC8AC368E758AFCEEE5784 -:10B100007C25171FCCE6577CAD5BC49BE8576C27AA -:10B110003AAD5A22FC8A1F74C3C5F5171AEE627C39 -:10B120005DA8BF30D27D767FE140B7E72FC4596F6D -:10B13000F85DBDF169FD851CFEC1A3CCBF30A550F3 -:10B14000FD0F516D8A7C88D023A8670ED238C6F1D6 -:10B15000EC2F1C0C0A7EB15C3D734797FD04D16354 -:10B160004FBDF0172E961CA0DFF734C13D5F793834 -:10B17000DF79554FAC1C9A243F0742497A37DD4F9F -:10B18000EF95287E7C2F24DE11E05128EFFF4FCA77 -:10B190009526D9B9D1FC6F3C46F37B1D15E8DDE05F -:10B1A000FE3E917FDEEDE6FFF6FBE2FF328970EEB8 -:10B1B000DFE1D70FE2F89FE7143832F2D49FF3CAE9 -:10B1C000C7E85DD031570FF96153612EBE9A399FA0 -:10B1D000789F4B4F574EF1EF3ACA74CE93BBF88924 -:10B1E000683638087FE77C99EB233BDBBF7880E447 -:10B1F000C76917792E2EB4E278645E54E43BD08D93 -:10B20000A94FCB8B28A09EA07CFC10BD514FABBF9B -:10B2100016DB1847A7C51921D3CEE81B100307F783 -:10B22000D91B91393F3FB852C44583C17840CFA163 -:10B230005F76F565BE53CA6E95454F24E92DF183BF -:10B2400051D5A4F4E870754D1BE53113BA78B4A458 -:10B2500085653B571D3BDC23B9F97893EDB6FAB908 -:10B260008EC25C76C56B87FA449ED6EB07168E5B62 -:10B27000C49F5A8565F3EF75C211C949CB2FFFDE14 -:10B28000D5133B2533B50A91B63324EC44C0485A54 -:10B29000329E77A0F836AE47060C074ED0F78549A8 -:10B2A000F810DB488916CB5977EF11F1CC4E5F8C43 -:10B2B000F7DB59AA729D726745EEBCD75F5DBDACE6 -:10B2C000859B6CCEFF8755AE2767CF9B72F949D31C -:10B2D000ACA8CEF1F76D06DD2B311F389739D57349 -:10B2E000E7533B82C49F36E747F6BB79126DDE36E3 -:10B2F000C6FBEE7255A73CDC6A65DD0EDAE7415409 -:10B30000BBE49F64F3817F7E4D1ED73FD7C9FC66A7 -:10B31000339B2FE8EDDB04F9696A8AFD251FBCC366 -:10B32000798BDD3547B86FC084DB17FCE2D59B22F3 -:10B330002E3F9E61275C7A2549AE72F0CFFDE51362 -:10B340006CBF1F6898D840759B602460B6E23DF6DC -:10B350002DB739BFBDBB5666BF35DFFD3DCE83EB94 -:10B360008AC28497DDB547582F679FC777E415F6E3 -:10B370003B826A8AF317C1B28F389E7DC83DC7DA17 -:10B380007A214F05A6D0C3055D71D071DFE2B79475 -:10B390003103FBD2BC971D1FD50F6E126F8B352D5D -:10B3A000C57E467EFD1A89CEF766A90212C1505E9F -:10B3B000E0F7BA600BF9F6DE6597746919F17D184C -:10B3C000D2FA15E27704E9EFA840D978D6F766BD3E -:10B3D000EFDD7EEC681ABC9E1EF75DAF5B673BD766 -:10B3E000FA3FF76D3B761495FF83356797ABBDAE9B -:10B3F000DEDBD357CF74F2F8CBE3B7085D71C5EC51 -:10B40000EBF787C773FA25A33D82AFCFA58F0AFC60 -:10B41000E36CE7F75E379E9187FCBAAB1FBEDE2375 -:10B42000E4482F9FE2BCE55EF79DD3DE3CD8F06C8C -:10B430008E7B3DD6A309793ACDCF9E1FF0CE85F9FC -:10B4400001F3BB44FC105991477E00E2F3657AE7B3 -:10B45000F6A78866409A3C0F8432FD50CF0FF86DF6 -:10B460008FF0035E2CFE98ED786130C5763C6866FF -:10B47000E609B2EDB8E68B715CA9956A9E9EE17A09 -:10B4800057F0ED6F3CE5903E48EDE2FA513EF26F29 -:10B490009E488D3BB9E8044B32DFDD7CB107F83CB8 -:10B4A00011233ED148F6A54BE57AC87EF9BD431F6E -:10B4B00012BA9271B05DB8C3CCB7BB27F8FD8ECB82 -:10B4C000F7E7A227FD7D52E7FE6E85DE715CFB6625 -:10B4D0007DAEB8C36BE97D55E67BF84F2717CF7B70 -:10B4E00072910779422ED6C903E40FAC93F9DD0AB5 -:10B4F0003DEF55EBDC9423D5FDE964746F7A1F248E -:10B50000B9F5A40533F2029F17EF5E4E6E13EF6894 -:10B51000F877860BE877A193FCFBC1CBE895AB32BB -:10B52000A3DF4E42994CF562E788249DF6932EA541 -:10B53000278FA64CEB1682CD6DF6B92F87387FAFDB -:10B540008624B757C238B74B6082DB6530C5AD057E -:10B55000426F994745DD6305980A7DAF019BDB3A51 -:10B5600088735B0F496EBF79ED97FE70332EF9AF8C -:10B570001EB72E7F1A2F02AF39E43B458FFEBDFB6D -:10B580007B787EB0C760B93B17BD07C242DF369BF0 -:10B5900013ECDF878236EB615F44F0B707C7374BA8 -:10B5A000BEF8EFF5A3B27F67F2FF2B2134C6D03F80 -:10B5B0000000000000000000000000180000000073 -:10B5C000000000000000004000000000000000003B -:10B5D0000000002800000000000000000000001033 -:10B5E000000000000000000000000020000000003B -:10B5F000000000000000001000000000000000003B -:10B600000000000800000000000000000000000032 -:10B6100000000000000000000000003900000000F1 -:10B6200000000000000000380000000000000000E2 -:10B630000000000000000000000000000000000802 -:10B6400000000000000000000000000000000000FA -:10B65000000000000000000C0000000000000000DE -:10B660000000000E000000000000000000000004C8 -:10B6700000000000000000000000001800000000B2 -:10B68000000000000000001C00000000000000009E -:10B690000000001C0000000000000000000000137B -:10B6A00000000000000000000000003A0000000060 -:10B6B0000000000000000001000000000000000089 -:10B6C0000000000200000000000000000000000177 -:10B6D000000000000000000000000010000000005A -:10B6E000000000000000005000000000000000000A -:10B6F0000000000000000000000000000000000347 -:10B700000000000000000000000000AB000000008E -:10B710000000000000000008000000000000000021 -:10B720000000C00000100000000000080000C00879 -:10B7300000100000000000020000C0000010000027 -:10B740000000001000009FB0000000000000000892 -:10B750000000C08000100000000000040000C0884D -:10B7600000100000000000020000C0800010000077 -:10B770000000001000009120000000000000000800 -:10B780000000934000010004000000010000934805 -:10B7900000000000000000020000935000000000C4 -:10B7A00000000008000093540000000000000002A8 -:10B7B00000009418000000000000000800009358EA -:10B7C000000800000000000800009AB000400000DF -:10B7D00000000040000093980008000000000008EE -:10B7E000000093D80008000000000008000094202A -:10B7F00000C8000000000098000095B0009800000C -:10B8000000000028000095F00098000000000028CB -:10B810000000C480054000300000054000009D206D -:10B82000000800000000000100009D210008000049 -:10B8300000000001000020080010000000000010BF -:10B8400000002000000000000000000800009CD85C -:10B85000000800000000000200009D180000000029 -:10B8600000000001000000010000000000000000D6 -:10B8700000000009000000000000000000000002BD -:10B8800000000000000000000000CF2000000000C9 -:10B89000000000200000CF46000000000000000172 -:10B8A0000000600000200000000000200000730085 -:10B8B000000800000000000800009FA00000000039 -:10B8C0000000000100009FA800000000000000012F -:10B8D00000009F60000000000000001000009F6357 -:10B8E000000000000000000100009F610000000057 -:10B8F0000000000100009F66000000000000000141 -:10B9000000009F67000000000000000000009F682A -:10B91000000000000000000400009F6C0000000018 -:10B9200000000004000000520000000000000000C1 -:10B930000000000300000000000000000000000301 -:10B9400000000000000000000000000500000000F2 -:10B9500000000000000000020000000000000000E5 -:10B9600000060000000000000000002000009F70A2 -:10B97000000000000000000100009F900000000097 -:10B98000000000080000005300000000000000005C -:10B9900000009F98000000000000000200009F9C33 -:10B9A000000000000000000100009F9D000000005A -:10B9B000000000010000000900000000000000007D -:10B9C0000000000100000000000000000000004432 -:10B9D0000000000000000000000000010000000066 -:10B9E0000000000000000050000000000000000007 -:10B9F000000000890000000000000000000012C8E4 -:10BA00000080000000000080000000010000000035 -:10BA1000000000000000A000071000000000071058 -:10BA200000001AC800000000000000080000AEC0BE -:10BA300000080000000000080000AE400008000000 -:10BA4000000000080000AE800008000000000008B0 -:10BA5000000020080010000000000010000020007E -:10BA600000000000000000080000A01007100040C7 -:10BA70000000004000001BF800080000000000016A -:10BA800000001BF9000800000000000100001AD0AF -:10BA9000000000000000000100001AD800000000B3 -:10BAA0000000000200001ADA00000000000000029E -:10BAB0008000000000000000000000000000AF0057 -:10BAC000000000000000002000001B78002800009B -:10BAD000000000040000E000002000000000002042 -:10BAE0000000F300000800000000000800001AF049 -:10BAF000000000000000010800001B3700000000EB -:10BB00000000000100001B0F000000000000000109 -:10BB100000001B70000000000000000400001B7407 -:10BB200000000000000000040000005000000000C1 -:10BB30000000000000000003000000000000000002 -:10BB400000000005000000000000000000000006EA -:10BB500000000000000000000000000700000000DE -:10BB60000000000000001BC80000000000000001F1 -:10BB700000001BE800000000000000080000005169 -:10BB8000000000000000000000001BD000000000CA -:10BB90000000000400001BD40000000000000004AE -:10BBA00000001BD8000000000000000400001BDCA7 -:10BBB00000000000000000080000B00000180000B5 -:10BBC000000000180000C00000400000000000401D -:10BBD0000000C00000400002000000010000C001A1 -:10BBE00000400002000000000000E2000020000011 -:10BBF000000000200000E204000200080020000213 -:10BC00008000000000000000000000000000E200D2 -:10BC100000080020000000040000F40000280000DC -:10BC2000000000280000F540001000000000001097 -:10BC30000000F5C000200000000000200000F5C05A -:10BC400000020020000000020000F30000200000BD -:10BC5000000000200000200800100000000000107C -:10BC60000000200000000000000000080000110893 -:10BC70000008000000000008000011680008000033 -:10BC800000000008000011A80008000000000008E3 -:10BC900000001240000800000000000100001241F6 -:10BCA0000008000000000001000040000020000427 -:10BCB00000000010000059000030001800000010C3 -:10BCC0000000590800300018000000020000570072 -:10BCD00000080000000000010000570100080000FB -:10BCE00000000001000011E8000000000000000159 -:10BCF000000011F00000000000000001000011F839 -:10BD000000000000000000100000124400080000C5 -:10BD1000000000040000400000200000000000209F -:10BD20000000530000100000000000100000153853 -:10BD300000000000000000010000000300000000FF -:10BD400000000000000000000000000000000000F3 -:10BD500000000001000000000000000000000004DE -:10BD600000000000000000000000150800000000B6 -:10BD7000000000010000152800000000000000087D -:10BD800000000050000000000000000000008308D8 -:10BD900000800000000000800000000100000000A2 -:10BDA000000000000000200800100000000000104B -:10BDB00000002000000000000000000800008410C7 -:10BDC0000008000000000008000084700008000067 -:10BDD0000000000800060000046000280000046065 -:10BDE00000008520000800000000000100008521FF -:10BDF00000080000000000018000000000000000BA -:10BE000000000000000084080000000000000001A5 -:10BE1000000084F40008000000000002000084F626 -:10BE2000000800000000000200008504001000006F -:10BE300000000004000087600000000000000020F7 -:10BE400000006000002000000000002000007300DF -:10BE500000080000000000080000000300000000CF -:10BE600000000000000000050000000000000000CD -:10BE700000000006000000000000000000000007B5 -:10BE80000000000000000000000088080000000022 -:10BE900000000001000088280000000000000008E9 -:10BEA00000000050000000000000000000008810AA -:10BEB00000000000000000040000881400000000E2 -:10BEC00000000004000088180000000000000004CA -:10BED0000000881C00000000000000080000300086 -:10BEE0000040000000000008000030080040000092 -:10BEF000000000280000339001C00010000000087E -:10BF00000000320000200000000000200000372068 -:10BF1000000000000000000800001020062000388B -:10BF2000000000080000A000000000000000200049 -:10BF300000003EA9000000000000000100003EC813 -:10BF4000000000000000000280000000000000006F -:10BF50000000000000006000002000000000000859 -:10BF60000000400000080000000000010000400147 -:10BF7000000800000000000100004040000800042C -:10BF800000000002000040600008000400000004FF -:10BF90000000400000080000000000040000400411 -:10BFA0000008000000000004000040400000000005 -:10BFB00000000008000040480000000000000008E9 -:10BFC0000000800000000000000000100000504051 -:10BFD000000100040000000100005000000000000B -:10BFE00000000020000050080010000000000004C5 -:10BFF0000000500C0010000000000001000052C7BB -:10C000000000000000000001000052C60000000017 -:10C0100000000001000030000030001800000004A3 -:10C020000000300400300018000000040000300858 -:10C0300000300018000000020000300A0030001834 -:10C04000000000020000300C003000180000000169 -:10C050000000300D00300018000000010000300E1C -:10C0600000300018000000010000301000300018FF -:10C07000000000040000301400300018000000042C -:10C08000000050000100008000080004000050047F -:10C0900001000080000800040000000A0000000009 -:10C0A0000000000000005068010000800000000156 -:10C0B0000000506901000080000000010000506C89 -:10C0C00001000080000000020000506E01000080AE -:10C0D0000000000200005070010000800000000419 -:10C0E0000000507401000080000000040000506651 -:10C0F0000100008000000002000050640100008088 -:10C1000000000001000050600100008000000002FB -:10C11000000050620100008000000002000050504A -:10C120000100008000000004000050540100008065 -:10C1300000000004000050580100008000000004CE -:10C140000000505C01000080000000040000507CF2 -:10C1500001000080000000010000507D010000800F -:10C160000000000100004018001000000000000462 -:10C170000000409000100000000000040000409803 -:10C18000001000000000000400004110000000004A -:10C190000000000200004112000000000000000248 -:10C1A00000004114000000000000000200004116E1 -:10C1B00000000000000000020000604000080000D5 -:10C1C00000000002000060420008000000000002C1 -:10C1D00000006044000800000000000400006080CF -:10C1E0000008000000000008000060C000400008D7 -:10C1F00000000008000060000008000000000002CD -:10C20000000060020008000000000001000060045F -:10C210000008000000000002000063400008000069 -:10C220000000000800006380000800000000000417 -:10C23000000063840008000000000001000063C0EB -:10C240000008000000000002000063C400080000B5 -:10C25000000000020000640000080000000000046C -:10C2600000007000001000000000000400007004D6 -:10C270000010000000000004000070080010000022 -:10C280000000000400009000000800000000000210 -:10C29000000090020008000000000001000090046F -:10C2A00000080000000000020000904000080000AC -:10C2B000000000020000904400080000000000029E -:10C2C00000009046000800000000000200009648B0 -:10C2D0000008000000000008000090800008000036 -:10C2E000000000020000908400080000000000022E -:10C2F0000000968800080000000000080000804050 -:10C30000000800000000000100008041000800005B -:10C310000000000100008042000800000000000151 -:10C3200000008043000800000000000100008000C1 -:10C330000008000000000002000080020008000069 -:10C34000000000010000800400080000000000025E -:10C35000000080C00008000000000002000080C251 -:10C360000008000000000002000080C40008000077 -:10C3700000000002000080800008000000000001B2 -:10C3800000008081000800000000000100008082A1 -:10C390000008000000000001000080830008000089 -:10C3A000000000010000808400080000000000017F -:10C3B0000000808500080000000000010000808669 -:10C3C00000080000000000010000600000080000FC -:10C3D00000000002000060020008000000000001F0 -:10C3E000000060040008000000000002000060423D -:10C3F00000C00018000000020000604000C00018EB -:10C40000000000020000604C00C00018000000089E -:10C410000000604400C000180000000800006057E1 -:10C4200000C00018000000010000605400C00018A7 -:10C43000000000020000605600C00018000000016B -:10C440000000664000080000000000080000668050 -:10C450000008000000000008000066C0000800009E -:10C46000000000080000DA4200180000000000028E -:10C470000000DE4000000000000000000000E000BE -:10C4800000000000000000040000D0C00000000018 -:10C49000000000040000D0C4000000000000000400 -:10C4A0000000D0C800000000000000040000D0CC54 -:10C4B00000000000000000040000D0D000000000D8 -:10C4C000000000040000D0D40000000000000004C0 -:10C4D0000000D0D800000000000000040000D0C020 -:10C4E00000000000000000200000DB000000000051 -:10C4F000000000040000DB000000000000000068F5 -:10C500000000B94800000000000000000000D0005A -:10C5100000000000000000040000B0C000000000A7 -:10C52000000000040000B0C400000000000000048F -:10C530000000B0C800000000000000040000B0C00F -:10C5400000000000000000100000D6B00000000055 -:10C55000000000040000D6B4000000000000000449 -:10C560000000D6B800000000000000040000D6BCA7 -:10C5700000000000000000040000D6B00000000031 -:10C58000000000100000D348000000000000000878 -:10C590000000D358000000000000008000000010E0 -:10C5A00000000000000000000000D3580000000060 -:10C5B0000000000800000000060205000000000066 -:00000001FF diff --git a/firmware/bnx2x/bnx2x-e2-6.2.9.0.fw.ihex b/firmware/bnx2x/bnx2x-e2-6.2.9.0.fw.ihex new file mode 100644 index 000000000000..8405e719e7fb --- /dev/null +++ b/firmware/bnx2x/bnx2x-e2-6.2.9.0.fw.ihex @@ -0,0 +1,15473 @@ +:1000000000005310000000680000070C000053803F +:100010000000318000005A90000000B000008C18F1 +:100020000000C13400008CD0000000D800014E0850 +:100030000000F26400014EE800000074000241502C +:1000400000005250000241C8000000B40002942099 +:10005000000121EC000294D800000FFC0003B6C898 +:10006000000000040003C6C8020400480000000F9E +:1000700002040054000000450204005C0000000679 +:100080000204007000000004020400780000000078 +:100090000204007C121700000204008022170000F6 +:1000A00002040084321700000604008800000005E6 +:1000B0000204009C12150000020400A0221500009A +:1000C000020400A432150000060400A80000000489 +:1000D000020400B802100000020400BC001000007E +:1000E000020400C010100000020400C42010000030 +:1000F000020400C830100000020400CC40100000D0 +:10010000060400D000000003020400DC0010000020 +:10011000020400E012140000020400E422140000B3 +:10012000020400E832140000020400EC4214000053 +:10013000060400F000000003010401240000000098 +:1001400001040128000000000104012C000000004F +:100150000104013000000000020401D00000890603 +:1001600002040258000000360204025C000000365F +:10017000020402600810000002040264081000007B +:1001800002040004000000FF02040008000000FF59 +:100190000204000C000000FF02040010000000FF39 +:1001A000020400140000007F02040018000000FF99 +:1001B0000204001C000000FF02040020000000FFF9 +:1001C000020400240000003E020400280000000099 +:1001D0000204002C0000003F020400300000003F39 +:1001E000020400340000003F020400380000003F19 +:1001F0000204003C0000003F020400400000003FF9 +:10020000020400440000003F020404CC000000018E +:1002100002042008000002110204200C0000020069 +:10022000020420100000020402042014000002193D +:100230000204201C0000FFFF020420200000FFFF3A +:10024000020420240000FFFF020420280000FFFF1A +:1002500002042038000000200604203C0000000FAB +:1002600002042078000000210604207C0000000F1A +:10027000020420B800000001060420BC0000000FAA +:10028000020420F800000001060420FC0000003FEA +:10029000020421F800000001060421FC0000000F08 +:1002A0000204223807FFFFFF0204223C0000007F07 +:1002B0000204224007FFFFFF020422440000003F27 +:1002C00001042248000000000104224C000000004C +:1002D000010422500000000001042254000000002C +:1002E00001042258000000000104225C000000000C +:1002F00001042260000000000104226400000000EC +:1003000001042268000000000104226C00000000CB +:1003100001042270000000000104227400000000AB +:1003200001042278000000000104227C000000008B +:10033000020422C00000FFFF020422C40000FFFFED +:10034000020422C80000FFFF020422CC0000FFFFCD +:100350000C042000000003E80A0420000000000153 +:100360000B042000000000030605400000000D0003 +:100370000205004400000020020500480000003291 +:1003800002050090021500200205009402150020CD +:1003900002050098000000300205009C08100000D3 +:1003A000020500A000000036020500A40000003095 +:1003B000020500A800000031020500B000000004A2 +:1003C000020500B400000005020500C000000000A6 +:1003D000020500C400000004020500D40000000172 +:1003E00002050114000000010205011C00000001CB +:1003F00002050120000000020205020400000001C5 +:100400000205020C0000004002050210000000403E +:100410000205021C00000020020502200000001C52 +:100420000205022400000020060502400000000A28 +:1004300004050280002000000205005000000007B3 +:1004400002050054000000070205005800000000EB +:100450000205005C000000080205006000000001C9 +:100460000605006400000003020500D80000000635 +:100470000205000400000001020500080000000160 +:100480000205000C00000001020500100000000140 +:100490000205001400000001020500180000000120 +:1004A0000205001C00000001020500200000000100 +:1004B00002050024000000010205002800000001E0 +:1004C0000205002C000000010205003000000001C0 +:1004D00002050034000000010205003800000001A0 +:1004E0000205003C00000001020500400000000180 +:1004F000020500E00000000D020500E80000000019 +:10050000020500F000000000020500F800000000F5 +:10051000020500E40000002D020500EC00000020B0 +:10052000020500F400000020020500FC000000208D +:10053000020500E00000001D020500E800000010B8 +:10054000020500F000000010020500F80000001095 +:10055000020500E40000003D020500EC0000003050 +:10056000020500F400000030020500FC000000302D +:10057000020500E00000004D020500E80000004018 +:10058000020500F000000040020500F800000040F5 +:10059000020500E40000006D020500EC00000060B0 +:1005A000020500F400000060020500FC000000608D +:1005B000020500E00000005D020500E800000050B8 +:1005C000020500F000000050020500F80000005095 +:1005D000020500E40000007D020500EC0000007050 +:1005E000020500F400000070020500FC000000702D +:1005F0000406100002000020020600DC00000001DA +:100600000406020000030220020600DC00000000D5 +:100610000718040000AD0000081807D800050223E1 +:10062000071C000029920000071C8000312A0A657F +:10063000071D000034A216B0071D80002E7A23D9B2 +:10064000071E000003502F78081E07F03F02022506 +:10065000021800BC0000003001180000000000007B +:10066000011800040000000001180008000000004C +:100670000118000C0000000001180010000000002C +:100680000118001400000000021800200000000102 +:1006900002180024000000020218002800000003D5 +:1006A0000218002C000000000218003000000004B6 +:1006B0000218003400000001021800380000000099 +:1006C0000218003C00000001021800400000000475 +:1006D0000218004400000000021800480000000159 +:1006E0000218004C00000003021800500000000037 +:1006F0000218005400000001021800580000000415 +:100700000218005C000000000218006000000001F8 +:1007100002180064000000030218006800000000D6 +:100720000218006C000000010218007000000004B4 +:100730000218007400000000021800780000000495 +:100740000218007C00000003061800800000000270 +:10075000021800A400007FFF021800A8000003FF99 +:1007600002180224000000000218023400000000F9 +:100770000218024C00000000021802E4000000FF12 +:100780000618100000000400021B8BC000000001CE +:10079000021B800000000034021B80400000001893 +:1007A000021B80800000000C021B80C000000020A3 +:1007B0000C1B8300000864700A1B830000000157B3 +:1007C0000B1B83000000055F0A1B83400000000034 +:1007D0000C1B8340000002260B1B8340000000011D +:1007E000021B838000086470021B83C00000022685 +:1007F000021B1480000000010A1B1480000000008E +:10080000021B944000000001061B944800000002F7 +:10081000061A1000000002B3041A1ACC00010227C5 +:10082000061A1AD000000008061A2008000000C8A6 +:10083000061A200000000002041A1BF8009002288B +:10084000061A371800000004061A371000000002CC +:10085000061A500000000002061A500800000004AA +:10086000061A501800000004061A50280000000460 +:10087000061A503800000004061A50480000000410 +:10088000061A505800000004061A506800000004C0 +:10089000061A507800000002041A52C0000202B882 +:1008A000061A405000000006041A4068000202BA0E +:1008B000041A4040000402BC041A8000000102C077 +:1008C000061A800400000003041A8010000102C10F +:1008D000061A801400000003041A8020000102C2DE +:1008E000061A802400000003041A8030000102C3AD +:1008F000061A803400000003041A8040000102C47C +:10090000061A804400000003041A8050000102C54A +:10091000061A805400000003041A8060000102C619 +:10092000061A806400000003041A8070000102C7E8 +:10093000061A807400000003041A8080000102C8B7 +:10094000061A808400000003041A8090000102C986 +:10095000061A809400000003041A80A0000102CA55 +:10096000061A80A400000003041A80B0000102CB24 +:10097000061A80B400000003041A80C0000102CCF3 +:10098000061A80C400000003041A80D0000102CDC2 +:10099000061A80D400000003041A80E0000102CE91 +:1009A000061A80E400000003041A80F0000102CF60 +:1009B000061A80F400000003041A8100000102D02E +:1009C000061A810400000003041A8110000102D1FC +:1009D000061A811400000003041A8120000102D2CB +:1009E000061A812400000003041A8130000102D39A +:1009F000061A813400000003041A8140000102D469 +:100A0000061A814400000003041A8150000102D537 +:100A1000061A815400000003041A8160000102D606 +:100A2000061A816400000003041A8170000102D7D5 +:100A3000061A817400000003041A8180000102D8A4 +:100A4000061A818400000003041A8190000102D973 +:100A5000061A819400000003041A81A0000102DA42 +:100A6000061A81A400000003041A81B0000102DB11 +:100A7000061A81B400000003041A81C0000102DCE0 +:100A8000061A81C400000003041A81D0000102DDAF +:100A9000061A81D400000003041A81E0000102DE7E +:100AA000061A81E400000003041A81F0000102DF4D +:100AB000061A81F400000003041A8200000102E01B +:100AC000061A820400000003041A8210000102E1E9 +:100AD000061A821400000003041A8220000102E2B8 +:100AE000061A822400000003041A8230000102E387 +:100AF000061A823400000003041A8240000102E456 +:100B0000061A824400000003041A8250000102E524 +:100B1000061A825400000003041A8260000102E6F3 +:100B2000061A826400000003041A8270000102E7C2 +:100B3000061A827400000003041A8280000102E891 +:100B4000061A828400000003041A8290000102E960 +:100B5000061A829400000003041A82A0000102EA2F +:100B6000061A82A400000003041A82B0000102EBFE +:100B7000061A82B400000003041A82C0000102ECCD +:100B8000061A82C400000003041A82D0000102ED9C +:100B9000061A82D400000003041A82E0000102EE6B +:100BA000061A82E400000003041A82F0000102EF3A +:100BB000061A82F400000003041A8300000102F008 +:100BC000061A830400000003041A8310000102F1D6 +:100BD000061A831400000003041A8320000102F2A5 +:100BE000061A832400000003041A8330000102F374 +:100BF000061A833400000003041A8340000102F443 +:100C0000061A834400000003041A8350000102F511 +:100C1000061A835400000003041A8360000102F6E0 +:100C2000061A836400000003041A8370000102F7AF +:100C3000061A837400000003041A8380000102F87E +:100C4000061A838400000003041A8390000102F94D +:100C5000061A839400000003041A83A0000102FA1C +:100C6000061A83A400000003041A83B0000102FBEB +:100C7000061A83B400000003041A83C0000102FCBA +:100C8000061A83C400000003041A83D0000102FD89 +:100C9000061A83D400000003041A83E0000102FE58 +:100CA000061A83E400000003041A83F0000102FF27 +:100CB000061A83F400000003041A840000010300F4 +:100CC000061A840400000003041A841000010301C2 +:100CD000061A841400000003041A84200001030291 +:100CE000061A842400000003041A84300001030360 +:100CF000061A843400000003041A8440000103042F +:100D0000061A844400000003041A845000010305FD +:100D1000061A845400000003041A846000010306CC +:100D2000061A846400000003041A8470000103079B +:100D3000061A847400000003041A8480000103086A +:100D4000061A848400000003041A84900001030939 +:100D5000061A849400000003041A84A00001030A08 +:100D6000061A84A400000003041A84B00001030BD7 +:100D7000061A84B400000003041A84C00001030CA6 +:100D8000061A84C400000003041A84D00001030D75 +:100D9000061A84D400000003041A84E00001030E44 +:100DA000061A84E400000003041A84F00001030F13 +:100DB000061A84F400000003041A850000010310E1 +:100DC000061A850400000003041A851000010311AF +:100DD000061A851400000003041A8520000103127E +:100DE000061A852400000003041A8530000103134D +:100DF000061A853400000003041A8540000103141C +:100E0000061A854400000003041A855000010315EA +:100E1000061A855400000003041A856000010316B9 +:100E2000061A856400000003041A85700001031788 +:100E3000061A857400000003041A85800001031857 +:100E4000061A858400000003041A85900001031926 +:100E5000061A859400000003041A85A00001031AF5 +:100E6000061A85A400000003041A85B00001031BC4 +:100E7000061A85B400000003041A85C00001031C93 +:100E8000061A85C400000003041A85D00001031D62 +:100E9000061A85D400000003041A85E00001031E31 +:100EA000061A85E400000003041A85F00001031F00 +:100EB000061A85F400000003041A860000010320CE +:100EC000061A860400000003041A8610000103219C +:100ED000061A861400000003041A8620000103226B +:100EE000061A862400000003041A8630000103233A +:100EF000061A863400000003041A86400001032409 +:100F0000061A864400000003041A865000010325D7 +:100F1000061A865400000003041A866000010326A6 +:100F2000061A866400000003041A86700001032775 +:100F3000061A867400000003041A86800001032844 +:100F4000061A868400000003041A86900001032913 +:100F5000061A869400000003041A86A00001032AE2 +:100F6000061A86A400000003041A86B00001032BB1 +:100F7000061A86B400000003041A86C00001032C80 +:100F8000061A86C400000003041A86D00001032D4F +:100F9000061A86D400000003041A86E00001032E1E +:100FA000061A86E400000003041A86F00001032FED +:100FB000061A86F400000003041A870000010330BB +:100FC000061A870400000003041A87100001033189 +:100FD000061A871400000003041A87200001033258 +:100FE000061A872400000003041A87300001033327 +:100FF000061A873400000003041A874000010334F6 +:10100000061A874400000003041A875000010335C4 +:10101000061A875400000003041A87600001033693 +:10102000061A876400000003041A87700001033762 +:10103000061A877400000003041A87800001033831 +:10104000061A878400000003041A87900001033900 +:10105000061A879400000003041A87A00001033ACF +:10106000061A87A400000003041A87B00001033B9E +:10107000061A87B400000003041A87C00001033C6D +:10108000061A87C400000003041A87D00001033D3C +:10109000061A87D400000003041A87E00001033E0B +:1010A000061A87E400000003041A87F00001033FDA +:1010B000061A87F400000003041A880000010340A8 +:1010C000061A880400000003041A88100001034176 +:1010D000061A881400000003041A88200001034245 +:1010E000061A882400000003041A88300001034314 +:1010F000061A883400000003041A884000010344E3 +:10110000061A884400000003041A885000010345B1 +:10111000061A885400000003041A88600001034680 +:10112000061A886400000003041A8870000103474F +:10113000061A887400000003041A8880000103481E +:10114000061A888400000003041A889000010349ED +:10115000061A889400000003041A88A00001034ABC +:10116000061A88A400000003041A88B00001034B8B +:10117000061A88B400000003041A88C00001034C5A +:10118000061A88C400000003041A88D00001034D29 +:10119000061A88D400000003041A88E00001034EF8 +:1011A000061A88E400000003041A88F00001034FC7 +:1011B000061A88F400000003041A89000001035095 +:1011C000061A890400000003041A89100001035163 +:1011D000061A891400000003041A89200001035232 +:1011E000061A892400000003041A89300001035301 +:1011F000061A893400000003041A894000010354D0 +:10120000061A894400000003041A8950000103559E +:10121000061A895400000003041A8960000103566D +:10122000061A896400000003041A8970000103573C +:10123000061A897400000003041A8980000103580B +:10124000061A898400000003041A899000010359DA +:10125000061A899400000003041A89A00001035AA9 +:10126000061A89A400000003041A89B00001035B78 +:10127000061A89B400000003041A89C00001035C47 +:10128000061A89C400000003041A89D00001035D16 +:10129000061A89D400000003041A89E00001035EE5 +:1012A000061A89E400000003041A89F00001035FB4 +:1012B000061A89F400000003041A8A000001036082 +:1012C000061A8A0400000003041A8A100001036150 +:1012D000061A8A1400000003041A8A20000103621F +:1012E000061A8A2400000003041A8A3000010363EE +:1012F000061A8A3400000003041A8A4000010364BD +:10130000061A8A4400000003041A8A50000103658B +:10131000061A8A5400000003041A8A60000103665A +:10132000061A8A6400000003041A8A700001036729 +:10133000061A8A7400000003041A8A8000010368F8 +:10134000061A8A8400000003041A8A9000010369C7 +:10135000061A8A9400000003041A8AA00001036A96 +:10136000061A8AA400000003041A8AB00001036B65 +:10137000061A8AB400000003041A8AC00001036C34 +:10138000061A8AC400000003041A8AD00001036D03 +:10139000061A8AD400000003041A8AE00001036ED2 +:1013A000061A8AE400000003041A8AF00001036FA1 +:1013B000061A8AF400000003041A8B00000103706F +:1013C000061A8B0400000003041A8B10000103713D +:1013D000061A8B1400000003041A8B20000103720C +:1013E000061A8B2400000003041A8B3000010373DB +:1013F000061A8B3400000003041A8B4000010374AA +:10140000061A8B4400000003041A8B500001037578 +:10141000061A8B5400000003041A8B600001037647 +:10142000061A8B6400000003041A8B700001037716 +:10143000061A8B7400000003041A8B8000010378E5 +:10144000061A8B8400000003041A8B9000010379B4 +:10145000061A8B9400000003041A8BA00001037A83 +:10146000061A8BA400000003041A8BB00001037B52 +:10147000061A8BB400000003041A8BC00001037C21 +:10148000061A8BC400000003041A8BD00001037DF0 +:10149000061A8BD400000003041A8BE00001037EBF +:1014A000061A8BE400000003041A8BF00001037F8E +:1014B000061A8BF400000003041A8C00000103805C +:1014C000061A8C0400000003041A8C10000103812A +:1014D000061A8C1400000003041A8C2000010382F9 +:1014E000061A8C2400000003041A8C3000010383C8 +:1014F000061A8C3400000003041A8C400001038497 +:10150000061A8C4400000003041A8C500001038565 +:10151000061A8C5400000003041A8C600001038634 +:10152000061A8C6400000003041A8C700001038703 +:10153000061A8C7400000003041A8C8000010388D2 +:10154000061A8C8400000003041A8C9000010389A1 +:10155000061A8C9400000003041A8CA00001038A70 +:10156000061A8CA400000003041A8CB00001038B3F +:10157000061A8CB400000003041A8CC00001038C0E +:10158000061A8CC400000003041A8CD00001038DDD +:10159000061A8CD400000003041A8CE00001038EAC +:1015A000061A8CE400000003041A8CF00001038F7B +:1015B000061A8CF400000003041A8D000001039049 +:1015C000061A8D0400000003041A8D100001039117 +:1015D000061A8D1400000003041A8D2000010392E6 +:1015E000061A8D2400000003041A8D3000010393B5 +:1015F000061A8D3400000003041A8D400001039484 +:10160000061A8D4400000003041A8D500001039552 +:10161000061A8D5400000003041A8D600001039621 +:10162000061A8D6400000003041A8D7000010397F0 +:10163000061A8D7400000003041A8D8000010398BF +:10164000061A8D8400000003041A8D90000103998E +:10165000061A8D9400000003041A8DA00001039A5D +:10166000061A8DA400000003041A8DB00001039B2C +:10167000061A8DB400000003041A8DC00001039CFB +:10168000061A8DC400000003041A8DD00001039DCA +:10169000061A8DD400000003041A8DE00001039E99 +:1016A000061A8DE400000003041A8DF00001039F68 +:1016B000061A8DF400000003041A8E00000103A036 +:1016C000061A8E0400000003041A8E10000103A104 +:1016D000061A8E1400000003041A8E20000103A2D3 +:1016E000061A8E2400000003041A8E30000103A3A2 +:1016F000061A8E3400000003041A8E40000103A471 +:10170000061A8E4400000003041A8E50000103A53F +:10171000061A8E5400000003041A8E60000103A60E +:10172000061A8E6400000003041A8E70000103A7DD +:10173000061A8E7400000003041A8E80000103A8AC +:10174000061A8E8400000003041A8E90000103A97B +:10175000061A8E9400000003041A8EA0000103AA4A +:10176000061A8EA400000003041A8EB0000103AB19 +:10177000061A8EB400000003041A8EC0000103ACE8 +:10178000061A8EC400000003041A8ED0000103ADB7 +:10179000061A8ED400000003041A8EE0000103AE86 +:1017A000061A8EE400000003041A8EF0000103AF55 +:1017B000061A8EF400000003041A8F00000103B023 +:1017C000061A8F0400000003041A8F10000103B1F1 +:1017D000061A8F1400000003041A8F20000103B2C0 +:1017E000061A8F2400000003041A8F30000103B38F +:1017F000061A8F3400000003041A8F40000103B45E +:10180000061A8F4400000003041A8F50000103B52C +:10181000061A8F5400000003041A8F60000103B6FB +:10182000061A8F6400000003041A8F70000103B7CA +:10183000061A8F7400000003041A8F80000103B899 +:10184000061A8F8400000003041A8F90000103B968 +:10185000061A8F9400000003041A8FA0000103BA37 +:10186000061A8FA400000003041A8FB0000103BB06 +:10187000061A8FB400000003041A8FC0000103BCD5 +:10188000061A8FC400000003041A8FD0000103BDA4 +:10189000061A8FD400000003041A8FE0000103BE73 +:1018A000061A8FE400000007041A62C0002003BF7C +:1018B000061A1AF000000042061AAF0000000008E5 +:1018C000061AE00000000540061AD0000000007271 +:1018D000061AD24800000010061AD6B000000020F8 +:1018E000061AD47000000090061AD46800000002A6 +:1018F000061AA000000001C4061A30000000001003 +:10190000061A308000000010061A31000000001096 +:10191000061A318000000010061A33000000001281 +:10192000061A339000000070061AD4580000000216 +:10193000061AD34800000002061AD35800000020FF +:10194000061AA710000001C4061A3040000000105B +:10195000061A30C000000010061A314000000010C6 +:10196000061A31C000000010061A334800000012A9 +:10197000061A355000000070061AD46000000002FC +:10198000061AD35000000002061AD3D80000002027 +:10199000021AAE2000000000061A500000000002EB +:1019A000061A508000000012041A4000000203DFF3 +:1019B000041A63C0000203E1061A7000000000046C +:1019C000061A320000000008021AAE2400000000CF +:1019D000061A501000000002061A50C8000000123B +:1019E000041A4008000203E3041A63C8000203E576 +:1019F000061A701000000004061A322000000008C9 +:101A0000021AAE2800000000061A50200000000252 +:101A1000061A511000000012041A4010000203E7D9 +:101A2000041A63D0000203E9061A702000000004C3 +:101A3000061A324000000008021AAE2C0000000016 +:101A4000061A503000000002061A51580000001219 +:101A5000041A4018000203EB041A63D8000203EDD5 +:101A6000061A703000000004061A326000000008F8 +:101A7000021AAE3000000000061A504000000002BA +:101A8000061A51A000000012041A4020000203EFC1 +:101A9000041A63E0000203F1061A7040000000041B +:101AA000061A328000000008021AAE34000000005E +:101AB000061A505000000002061A51E800000012F9 +:101AC000041A4028000203F3041A63E8000203F535 +:101AD000061A705000000004061A32A00000000828 +:101AE000021AAE3800000000061A50600000000222 +:101AF000061A523000000012041A4030000203F7A8 +:101B0000041A63F0000203F9061A70600000000472 +:101B1000061A32C000000008021AAE3C00000000A5 +:101B2000061A507000000002061A527800000012D7 +:101B3000041A4038000203FB041A63F8000203FD94 +:101B4000061A707000000004061A32E00000000857 +:101B50000200A2A4000002090200A270000000001E +:101B60000200A274000000000200A2700000000049 +:101B70000200A274000000000200A2700000000039 +:101B80000200A274000000000200A2700000000029 +:101B90000200A27400000000020100B40000000175 +:101BA000020100B800000001020100CC00000001A9 +:101BB000020100D000000001020100DC0000000171 +:101BC0000201010000000001020101040000000107 +:101BD0000201007C003000000201008400000028A7 +:101BE0000201008C0000000002010130000000042E +:101BF0000201025C00000001020103280000000055 +:101C0000020160580000FFFF020160700000000741 +:101C10000201055400000030020100C40000000170 +:101C2000020100F800000001020100F000000001C4 +:101C3000020100800030000002010088000000283E +:101C400002010090000000000201013400000004C5 +:101C5000020102DC000000010201032C0000000070 +:101C60000201605C0000FFFF0201607400000007D9 +:101C70000201056400000030020100C800000001FC +:101C8000020100FC00000001020100F4000000015C +:101C9000020C100000000028020C200800000211B5 +:101CA000020C200C00000200020C201000000204B4 +:101CB000020C201C0000FFFF020C20200000FFFF90 +:101CC000020C20240000FFFF020C20280000FFFF70 +:101CD000020C203800000000020C203C00000037FD +:101CE000020C204000000021020C204400000020D3 +:101CF000060C20480000001D020C20BC0000000162 +:101D0000060C20C00000003F020C21BC00000001B6 +:101D1000020C21C000000001020C21C400000001DF +:101D2000060C21C80000001C020C223807FFFFFF30 +:101D3000020C223C0000007F020C224007FFFFFF44 +:101D4000020C22440000003F010C22480000000069 +:101D5000010C224C00000000010C22500000000089 +:101D6000010C225400000000010C22580000000069 +:101D7000010C225C00000000010C22600000000049 +:101D8000010C226400000000010C22680000000029 +:101D9000010C226C00000000010C22700000000009 +:101DA000010C227400000000010C227800000000E9 +:101DB000010C227C00000000020C22D80000FFFF72 +:101DC000020C22DC0000FFFF020C22E00000FFFFFB +:101DD000020C22E40000FFFF0C0C2000000003E8CE +:101DE0000A0C2000000000010B0C20000000000382 +:101DF000020C400800001011020C400C0000100002 +:101E0000020C401000001004020C401400001021CD +:101E1000020C401C0000FFFF020C40200000FFFFEE +:101E2000020C40240000FFFF020C40280000FFFFCE +:101E3000020C403800000046020C403C0000000C40 +:101E4000060C404000000002020C40480000001850 +:101E5000020C404C000000F0060C40500000001F37 +:101E6000020C40CC00000001060C40D00000003AFB +:101E7000020C41B800000001060C41BC0000000348 +:101E8000020C41C800000001020C41CC000000011E +:101E9000060C41D00000001A020C423807FFFFFF79 +:101EA000020C423C0000007F020C424007FFFFFF93 +:101EB000020C42440000003F010C424800000000B8 +:101EC000010C424C00000000010C425000000000D8 +:101ED000010C425400000000010C425800000000B8 +:101EE000010C425C00000000010C42600000000098 +:101EF000010C426400000000010C42680000000078 +:101F0000010C426C00000000010C42700000000057 +:101F1000010C427400000000010C42780000000037 +:101F2000010C427C00000000010C42800000000017 +:101F3000020C42D80000FFFF020C42DC0000FFFF51 +:101F4000020C42E00000FFFF020C42E40000FFFF31 +:101F50000C0C4000000003E80A0C400000000001E7 +:101F60000B0C400000000003060D400000000A00BA +:101F7000020D004400000032020D008C021500200A +:101F8000020D009002150020020D009408100000C0 +:101F9000020D009800000036020D00A000000000B5 +:101FA000020D00A400000004020D00A800000004BF +:101FB000060D00AC00000002020D00B80000000297 +:101FC000020D00C000000001020D00C80000000268 +:101FD000020D00CC00000002020D015C00000001B7 +:101FE000020D016400000001020D01680000000202 +:101FF000020D020400000001020D020C000000208E +:10200000020D021000000040020D0214000000400A +:10201000020D022000000003020D0224000000183F +:10202000060D028000000012040D0300001803FFDB +:10203000060D03600000000C020D004C00000001C2 +:10204000020D005000000002020D005400000000CC +:10205000020D005800000008060D005C000000049E +:10206000020D00C400000004020D00040000000185 +:10207000020D000800000001020D000C000000012C +:10208000020D001000000001020D0014000000010C +:10209000020D001800000001020D001C00000001EC +:1020A000020D002000000001020D002400000001CC +:1020B000020D002800000001020D002C00000001AC +:1020C000020D003000000001020D0034000000018C +:1020D000020D003800000001020D003C000000016C +:1020E000020D011400000009020D011C0000000A8D +:1020F000020D012400000000020D012C0000000070 +:10210000020D013400000000020D013C0000000B34 +:10211000020D014400000000020D0118000000291A +:10212000020D01200000002A020D012800000020FD +:10213000020D013000000020020D013800000020D7 +:10214000020D01400000002B020D0148000000209C +:10215000020D011400000019020D011C0000001AFC +:10216000020D012400000010020D012C00000010DF +:10217000020D013400000010020D013C0000001BA4 +:10218000020D014400000010020D0118000000398A +:10219000020D01200000003A020D0128000000306D +:1021A000020D013000000030020D01380000003047 +:1021B000020D01400000003B020D0148000000300C +:1021C000020D011400000049020D011C0000004A2C +:1021D000020D012400000040020D012C000000400F +:1021E000020D013400000040020D013C0000004BD4 +:1021F000020D014400000040020D011800000069BA +:10220000020D01200000006A020D0128000000609C +:10221000020D013000000060020D01380000006076 +:10222000020D01400000006B020D0148000000603B +:10223000020D011400000059020D011C0000005A9B +:10224000020D012400000050020D012C000000507E +:10225000020D013400000050020D013C0000005B43 +:10226000020D014400000050020D01180000007929 +:10227000020D01200000007A020D0128000000700C +:10228000020D013000000070020D013800000070E6 +:10229000020D01400000007B020D014800000070AB +:1022A000060E200000000800020E004C0000003264 +:1022B000020E009402150020020E00980215002064 +:1022C000020E009C00000030020E00A0081000006A +:1022D000020E00A400000036020E00A8000000302C +:1022E000020E00AC00000031020E00B4000000033A +:1022F000020E00B800000000020E00C40000000042 +:10230000020E00CC00000006020E00D80000000102 +:10231000020E014400000001020E014C0000000109 +:10232000020E015000000002020E02040000000133 +:10233000020E020C00000040020E021000000040DD +:10234000020E021C00000004020E02200000002009 +:10235000020E02240000000E020E02280000001BE4 +:10236000060E030000000012040E0280001B04177A +:10237000060E02EC00000005020E00540000000CE6 +:10238000020E00580000000C020E005C000000006D +:10239000020E006000000010020E00640000001039 +:1023A000060E006800000003020E00DC00000003BF +:1023B000020E000400000001020E000800000001EF +:1023C000020E000C00000001020E001000000001CF +:1023D000020E001400000001020E001800000001AF +:1023E000020E001C00000001020E0020000000018F +:1023F000020E002400000001020E0028000000016F +:10240000020E002C00000001020E0030000000014E +:10241000020E003400000001020E0038000000012E +:10242000020E003C00000001020E0040000000010E +:10243000020E004400000001020E01100000000F17 +:10244000020E011800000000020E01200000000032 +:10245000020E012800000000020E01140000002FEF +:10246000020E011C00000020020E012400000020CA +:10247000020E012C00000020020E01100000001FBF +:10248000020E011800000010020E012000000010D2 +:10249000020E012800000010020E01140000003F8F +:1024A000020E011C00000030020E0124000000306A +:1024B000020E012C00000030020E01100000004F3F +:1024C000020E011800000040020E01200000004032 +:1024D000020E012800000040020E01140000006FEF +:1024E000020E011C00000060020E012400000060CA +:1024F000020E012C00000060020E01100000005FBF +:10250000020E011800000050020E012000000050D1 +:10251000020E012800000050020E01140000007F8E +:10252000020E011C00000070020E01240000007069 +:10253000020E012C000000700730040000D60000DD +:10254000083007D80005043207340000322B0000A1 +:1025500007348000314B0C8B0735000038C518DE7E +:10256000073580002F90271007360000268F32F5A0 +:102570000836716031D40434023000BC00000030F1 +:1025800001300000000000000130000400000000E5 +:1025900001300008000000000130000C00000000C5 +:1025A00001300010000000000130001400000000A5 +:1025B0000230002000000001023000240000000270 +:1025C00002300028000000030230002C0000000050 +:1025D000023000300000000402300034000000012E +:1025E00002300038000000000230003C0000000112 +:1025F00002300040000000040230004400000000EF +:1026000002300048000000010230004C00000003CE +:1026100002300050000000000230005400000001B1 +:1026200002300058000000040230005C000000008E +:10263000023000600000000102300064000000036E +:1026400002300068000000000230006C0000000151 +:10265000023000700000000402300074000000002E +:1026600002300078000000040230007C000000030B +:102670000630008000000002023000A400007FFF4E +:10268000023000A8000003FF023002240000000016 +:1026900002300234000000000230024C0000000052 +:1026A000023002E40000FFFF0630200000000800B6 +:1026B00002338BC000000001023380000000001ACA +:1026C000023380400000004E023380800000001082 +:1026D000023380C0000000200C33830000086470C7 +:1026E0000A338300000001570B3383000000055FAD +:1026F0000A338340000000000C33834000000226B0 +:102700000B338340000000010233838000086470B3 +:10271000023383C00000022602331480000000014F +:102720000A3314800000000006328000000001021D +:1027300006322008000000C8063220000000000217 +:1027400004328520008F04360632875C00000009C1 +:1027500006323EB00000000606323ED00000000205 +:1027600006323E800000000A04323EA8000204C582 +:1027700006323E00000000200632500000000940F2 +:102780000632400000000004043294C0000204C776 +:1027900006324110000000020632D0000000007036 +:1027A0000632DB00000000D40632DEA0000000028A +:1027B0000632E00000000800063324000000011883 +:1027C0000632100000000188063250000000002090 +:1027D00006325100000000200632520000000020A6 +:1027E0000632530000000020063254000000002092 +:1027F000063255000000002006325600000000207E +:102800000632570000000020063258000000002069 +:10281000063259000000002006325A000000002055 +:1028200006325B000000002006325C000000002041 +:1028300006325D000000002006325E00000000202D +:1028400006325F0000000020063284F00000000223 +:1028500004328500000204C9063285080000000227 +:102860000632DE90000000020633286000000118E6 +:102870000632162000000188063250800000002039 +:1028800006325180000000200632528000000020F5 +:1028900006325380000000200632548000000020E1 +:1028A00006325580000000200632568000000020CD +:1028B00006325780000000200632588000000020B9 +:1028C000063259800000002006325A8000000020A5 +:1028D00006325B800000002006325C800000002091 +:1028E00006325D800000002006325E80000000207D +:1028F00006325F8000000020063284F800000002EB +:1029000004328510000204CB063285180000000254 +:102910000632DE98000000020232845000000000FF +:102920000632401000000002023284540000000011 +:1029300006324020000000020232845800000000ED +:1029400006324030000000020232845C00000000C9 +:1029500006324040000000020232846000000000A5 +:102960000632405000000002023284640000000081 +:10297000063240600000000202328468000000005D +:1029800006324070000000020232846C0000000039 +:10299000063240800000000207200400007300009F +:1029A00008200780001004CD072400002AE400005E +:1029B0000724800027670ABA0824D35063FC04CF99 +:1029C000022000BC000000300120000000000000D8 +:1029D00001200004000000000120000800000000A9 +:1029E0000120000C00000000012000100000000089 +:1029F000012000140000000002200020000000015F +:102A00000220002400000002022000280000000331 +:102A10000220002C00000000022000300000000412 +:102A200002200034000000010220003800000000F5 +:102A30000220003C000000010220004000000004D1 +:102A400002200044000000000220004800000001B5 +:102A50000220004C00000003022000500000000093 +:102A60000220005400000001022000580000000471 +:102A70000220005C00000000022000600000000155 +:102A80000220006400000003022000680000000033 +:102A90000220006C00000001022000700000000411 +:102AA00002200074000000000220007800000004F2 +:102AB0000220007C000000030620008000000002CD +:102AC000022000A400007FFF022000A8000003FFF6 +:102AD0000220022400000000022002340000000056 +:102AE0000220024C00000000022002E40000FFFF70 +:102AF000062020000000080002238BC00000000117 +:102B00000223800000000010022380400000001219 +:102B10000223808000000030022380C00000000EED +:102B20000C238300000864700A238300000001570F +:102B30000B2383000000055F0A2383400000000090 +:102B40000C238340000002260B2383400000000179 +:102B50000223838000086470022383C000000226E1 +:102B600002231480000000010A23148000000000EA +:102B7000062210000000004206222008000000C8C3 +:102B800006222000000000020622B00000000330F0 +:102B90000622F400000000530422F54C000104D189 +:102BA0000622F550000000030422F55C000104D267 +:102BB0000622F560000000030422F56C000104D336 +:102BC0000622F570000000030422F57C000104D405 +:102BD0000622F580000000030422F58C000104D5D4 +:102BE0000622F590000000030422F59C000104D6A3 +:102BF0000622F5A0000000030422F5AC000104D772 +:102C00000622F5B0000000030422F5BC000104D840 +:102C10000622F5C0000000460622E2000000044043 +:102C200004221240009004D906223000000000C0A7 +:102C30000622670000000100062290000000040048 +:102C400004226B0800200569062211F0000000062E +:102C50000422120800060589062212200000000244 +:102C600006224000000005C00622C0000000000649 +:102C70000422C0180006058F0622C0300000000A9A +:102C80000422C058000605950622C0700000000A04 +:102C90000422C0980006059B0622C0B00000000A6E +:102CA0000422C0D8000605A10622C0F00000000AD8 +:102CB0000422C118000605A70622C1300000000A40 +:102CC0000422C158000605AD0622C1700000000AAA +:102CD0000422C198000605B30622C1B00000000A14 +:102CE0000422C1D8000605B90622C1F00000000A7E +:102CF0000422C218000605BF0622C2300000000AE6 +:102D00000422C258000605C50622C2700000000A4F +:102D10000422C298000605CB0622C2B00000000AB9 +:102D20000422C2D8000605D10622C2F00000000A23 +:102D30000422C318000605D70622C3300000000A8B +:102D40000422C358000605DD0622C3700000000AF5 +:102D50000422C398000605E30622C3B00000000A5F +:102D60000422C3D8000605E90622C3F00000000AC9 +:102D70000422C418000605EF0622C4300000000A31 +:102D80000422C458000605F50622C4700000000A9B +:102D90000422C498000605FB0622C4B00000000A05 +:102DA0000422C4D8000606010622C4F00000000A6E +:102DB0000422C518000606070622C5300000000AD6 +:102DC0000422C5580006060D0622C5700000000A40 +:102DD0000422C598000606130622C5B00000000AAA +:102DE0000422C5D8000606190622C5F00000000A14 +:102DF0000422C6180006061F0622C6300000000A7C +:102E00000422C658000606250622C6700000000AE5 +:102E10000422C6980006062B0622C6B00000000A4F +:102E20000422C6D8000606310622C6F00000000AB9 +:102E30000422C718000606370622C7300000000A21 +:102E40000422C7580006063D0622C7700000000A8B +:102E50000422C798000606430622C7B00000000AF5 +:102E60000422C7D8000606490622C7F00000000A5F +:102E70000422C8180006064F0622C8300000000AC7 +:102E80000422C858000606550622C8700000000A31 +:102E90000422C8980006065B0622C8B00000000A9B +:102EA0000422C8D8000606610622C8F00000000A05 +:102EB0000422C918000606670622C9300000000A6D +:102EC0000422C9580006066D0622C9700000000AD7 +:102ED0000422C998000606730622C9B00000000A41 +:102EE0000422C9D8000606790622C9F00000000AAB +:102EF0000422CA180006067F0622CA300000000A13 +:102F00000422CA58000606850622CA700000000A7C +:102F10000422CA980006068B0622CAB00000000AE6 +:102F20000422CAD8000606910622CAF00000000A50 +:102F30000422CB18000606970622CB300000000AB8 +:102F40000422CB580006069D0622CB700000000A22 +:102F50000422CB98000606A30622CBB00000000A8C +:102F60000422CBD8000606A90622CBF00000000AF6 +:102F70000422CC18000606AF0622CC300000000A5E +:102F80000422CC58000606B50622CC700000000AC8 +:102F90000422CC98000606BB0622CCB00000000A32 +:102FA0000422CCD8000606C10622CCF00000000A9C +:102FB0000422CD18000606C70622CD300000000A04 +:102FC0000422CD58000606CD0622CD700000000A6E +:102FD0000422CD98000606D30622CDB00000000AD8 +:102FE0000422CDD8000606D90622CDF00000000A42 +:102FF0000422CE18000606DF0622CE300000000AAA +:103000000422CE58000606E50622CE700000000A13 +:103010000422CE98000606EB0622CEB00000000A7D +:103020000422CED8000606F10622CEF00000000AE7 +:103030000422CF18000606F70622CF300000000A4F +:103040000422CF58000606FD0622CF700000000AB9 +:103050000422CF98000607030622CFB00000000A22 +:103060000422CFD8000607090622CFF00000000A8C +:103070000422D0180006070F0622D0300000000AF4 +:103080000422D058000607150622D0700000000A5E +:103090000422D0980006071B0622D0B00000000AC8 +:1030A0000422D0D8000607210622D0F00000000A32 +:1030B0000422D118000607270622D1300000000A9A +:1030C0000422D1580006072D0622D1700000000A04 +:1030D0000422D198000607330622D1B00000000A6E +:1030E0000422D1D8000607390622D1F00000000AD8 +:1030F0000422D2180006073F0622D2300000000A40 +:103100000422D258000607450622D2700000000AA9 +:103110000422D2980006074B0622D2B00000000A13 +:103120000422D2D8000607510622D2F00000000A7D +:103130000422D318000607570622D3300000000AE5 +:103140000422D3580006075D0622D3700000000A4F +:103150000422D398000607630622D3B00000000AB9 +:103160000422D3D8000607690622D3F00000000A23 +:103170000422D4180006076F0622D4300000000A8B +:103180000422D458000607750622D4700000000AF5 +:103190000422D4980006077B0622D4B00000000A5F +:1031A0000422D4D8000607810622D4F00000000AC9 +:1031B0000422D518000607870622D5300000000A31 +:1031C0000422D5580006078D0622D5700000000A9B +:1031D0000422D598000607930622D5B00000000A05 +:1031E0000422D5D8000607990622D5F00000000A6F +:1031F0000422D6180006079F0622D6300000000AD7 +:103200000422D658000607A50622D6700000000A40 +:103210000422D698000607AB0622D6B00000000AAA +:103220000422D6D8000607B10622D6F00000000A14 +:103230000422D718000607B70622D7300000000A7C +:103240000422D758000607BD0622D7700000000AE6 +:103250000422D798000607C30622D7B00000000A50 +:103260000422D7D8000607C90622D7F00000000ABA +:103270000422D818000607CF0622D8300000000A22 +:103280000422D858000607D50622D8700000000A8C +:103290000422D898000607DB0622D8B00000000AF6 +:1032A0000422D8D8000607E10622D8F00000000A60 +:1032B0000422D918000607E70622D9300000000AC8 +:1032C0000422D958000607ED0622D9700000000A32 +:1032D0000422D998000607F30622D9B00000000A9C +:1032E0000422D9D8000607F90622D9F00000000A06 +:1032F0000422DA18000607FF0622DA300000000A6E +:103300000422DA58000608050622DA700000000AD6 +:103310000422DA980006080B0622DAB00000000A40 +:103320000422DAD8000608110622DAF00000000AAA +:103330000422DB18000608170622DB300000000A12 +:103340000422DB580006081D0622DB700000000A7C +:103350000422DB98000608230622DBB00000000AE6 +:103360000422DBD8000608290622DBF00000000A50 +:103370000422DC180006082F0622DC300000000AB8 +:103380000422DC58000608350622DC700000000A22 +:103390000422DC980006083B0622DCB00000000A8C +:1033A0000422DCD8000608410622DCF00000000AF6 +:1033B0000422DD18000608470622DD300000000A5E +:1033C0000422DD580006084D0622DD700000000AC8 +:1033D0000422DD98000608530622DDB00000000A32 +:1033E0000422DDD8000608590622DDF00000000A9C +:1033F0000422DE180006085F0622DE300000000A04 +:103400000422DE58000608650622DE700000000A6D +:103410000422DE980006086B0622DEB00000000AD7 +:103420000422DED8000608710622DEF00000000A41 +:103430000422DF18000608770622DF300000000AA9 +:103440000422DF580006087D0622DF700000000A13 +:103450000422DF98000608830622DFB00000000A7D +:103460000422DFD8000608890622DFF00000000AE7 +:103470000422E0180006088F0622E0300000000A4F +:103480000422E058000608950622E0700000000AB9 +:103490000422E0980006089B0622E0B00000000A23 +:1034A0000422E0D8000608A10622E0F00000000A8D +:1034B0000422E118000608A70622E1300000000AF5 +:1034C0000422E158000608AD0622E1700000000A5F +:1034D0000422E198000608B30622E1B00000000AC9 +:1034E0000422E1D8000608B90622E1F00000000439 +:1034F0000622153800000002062211E80000000232 +:103500000622F3000000000802221148000000001B +:1035100006225900000000060622330000000002C7 +:1035200006226040000000300622F3200000000860 +:103530000222114C0000000006225918000000066B +:10354000062233080000000206226100000000305D +:103550000622F34000000008022211500000000083 +:103560000622593000000006062233100000000237 +:10357000062261C0000000300622F360000000084F +:1035800002221154000000000622594800000006E3 +:10359000062233180000000206226280000000307C +:1035A0000622F380000000080222115800000000EB +:1035B00006225960000000060622332000000002A7 +:1035C00006226340000000300622F3A0000000083D +:1035D0000222115C0000000006225978000000065B +:1035E000062233280000000206226400000000309A +:1035F0000622F3C000000008022211600000000053 +:103600000622599000000006062233300000000216 +:10361000062264C0000000300622F3E0000000082B +:103620000222116400000000062259A800000006D2 +:1036300006223338000000020622658000000030B8 +:103640000216100000000028021700080000000207 +:103650000217002C000000030217003C00000004C9 +:10366000021700440000000002170048000000029A +:103670000217004C0000009002170050000000905C +:103680000217005400800090021700580810000034 +:10369000021700700000000602170078000009FF02 +:1036A0000217007C0000076C021701C4081000001C +:1036B0000217034400000001021704000000008A02 +:1036C00002170404000000800217040800000081B3 +:1036D0000217040C00000080021704100000008A8A +:1036E0000217041400000080021704180000008173 +:1036F0000217041C00000080021704300000008A3A +:103700000217043400000080021704380000008112 +:103710000217043C00000080021704400000008AE9 +:1037200002170444000000800217044800000081D2 +:103730000217044C00000080021704800000008A79 +:103740000217048400000080021704880000008132 +:103750000217048C0000008002170038007C10045F +:10376000021700040000000F021701EC0000000225 +:10377000021701F400000002021701EC0000000231 +:10378000021701F400000002021701EC0000000221 +:10379000021701F400000002021701EC0000000211 +:1037A000021701F400000002021701EC0000000201 +:1037B000021701F400000002021701EC00000002F1 +:1037C000021701F400000002021701EC00000002E1 +:1037D000021701F400000002021701EC00000002D1 +:1037E000021701F400000002061640240000000247 +:1037F000021640700000001C021642080000000182 +:1038000002164210000000010216422000000001D2 +:10381000021642280000000102164230000000019A +:103820000216423800000001021642600000000249 +:103830000C16401C0003D0900A16401C0000009C8F +:103840000B16401C000002710216403000000028D8 +:10385000021640340000002C0216403800000030F0 +:103860000216404400000020021640000000000143 +:10387000021640D8000000010216400800000001B6 +:103880000216400C0000000102164010000000016A +:1038900002164240000000000216424800000000EC +:1038A000061642700000000202164250000000009E +:1038B0000216425800000000061642800000000276 +:1038C00002166008000012140216600C00001200BC +:1038D00002166010000012040216601C0000FFFFB8 +:1038E000021660200000FFFF021660240000FFFFA8 +:1038F000021660280000FFFF02166038000000205A +:103900000216603C00000010061660400000000235 +:1039100002166048000000230216604C00000024DC +:1039200002166050000000250216605400000026B8 +:1039300002166058000000270216605C00000011AB +:103940000216606000000000021660640000002B98 +:10395000021660680000002C0216606C0000002D4A +:1039600002166070000000EC021660740000000097 +:1039700002166078000000290216607C0000002A10 +:10398000021660800000002F061660840000000D03 +:10399000021660B800000001061660BC00000008B6 +:1039A000021660DC00000001061660E00000000462 +:1039B000021660F000000001061660F4000000032B +:1039C0000216610000000001061661040000002DCF +:1039D000021661B800000001061661BC0000000874 +:1039E000021661DC00000001061661E00000000420 +:1039F000021661F000000001061661F400000003E9 +:103A00000216620000000001061662040000000DAC +:103A10000216623807FFFFFF0216623C0000007FBB +:103A20000216624007FFFFFF021662440000003FDB +:103A300001166248000000000116624C0000000000 +:103A400001166250000000000116625400000000E0 +:103A500001166258000000000116625C00000000C0 +:103A600001166260000000000116626400000000A0 +:103A700001166268000000000116626C0000000080 +:103A80000116627000000000011662740000000060 +:103A900001166278000000000116627C0000000040 +:103AA000011662D400000000021662D80000FFFF79 +:103AB000021662DC0000FFFF021662E00000FFFF5A +:103AC000021662E40000FFFF0C166000000003E82D +:103AD0000A166000000000010B16600000000003E1 +:103AE0000216804000000006021680440000000517 +:103AF000021680480000000A0216804C00000005F3 +:103B00000216805400000002021680CC000000045F +:103B1000021680D000000004021680D400000004C9 +:103B2000021680D800000004021680DC00000004A9 +:103B3000021680E000000004021680E40000000489 +:103B4000021680E800000004021688040000000647 +:103B5000021680300000007C021680340000003D18 +:103B6000021680380000003F0216803C0000009CD6 +:103B70000216E6E8000060000216E6EC00006000B5 +:103B80000216E6F0000060000216E6F40000600095 +:103B900002168234000025E40216823800008000FC +:103BA00002168094000025E3021681F400000C0840 +:103BB000021681F800000040021681FC000001009E +:103BC0000216820000000020021682040000001786 +:103BD00002168208000000800216820C000002001B +:103BE00002168210000000000216823C0000001342 +:103BF00002168220008F008F0216821C008F008F19 +:103C0000021680F0000000070216821801FF01FF73 +:103C10000216821401FF01FF061680F40000000264 +:103C20000216811C0000000502168120000000051C +:103C300002168124000000050216812800000008F9 +:103C40000216812C000000060216813000000007D9 +:103C50000616813400000004021680FC00000000FB +:103C600006168144000000020216814C0000000488 +:103C7000021681500000000102168154000000026B +:103C800002168158000000050216815C0000000544 +:103C90000216816000000005021681640000000524 +:103CA0000216816800000008021681000000000072 +:103CB0000216816C000000060216817000000007E9 +:103CC00006168174000000060216818C00000004B4 +:103CD000021681900000000102168104000000001D +:103CE000021681940000000202168198000000056F +:103CF0000216819C00000005021681A0000000054C +:103D0000021681A400000005021681A80000000828 +:103D1000021681AC00000006021681B00000000708 +:103D2000061681B40000000202168108000000009F +:103D3000061681BC00000004021681CC00000004BD +:103D4000021681D000000001021681D4000000029A +:103D5000021681D800000005021681DC0000000573 +:103D6000021681E0000000050216810C000000042C +:103D7000021681E400000005021681E80000000838 +:103D8000021681EC00000006021681F00000000718 +:103D900002168110000000010216811400000002CA +:103DA00002168118000000050216809C0000004CDD +:103DB000021680A00000004C061680C4000000021D +:103DC000021680A400000000021680A80000000077 +:103DD000021680AC0000004C061680B00000000502 +:103DE0000216E6F80000020402168240003F003F7F +:103DF00002168244003F003F061682900000000435 +:103E000002168248008000800216824C00800080EA +:103E100002168250010001000216825401000100C6 +:103E20000616825800000002021682600040004020 +:103E30000216826400400040021682681E001E00C6 +:103E40000216826C1E001E000216827040004000A6 +:103E500002168274400040000216827880008000C2 +:103E60000216827C800080000216828020002000E2 +:103E700002168284200020000616828800000002BC +:103E8000021680900000004B021680600000014086 +:103E900002168064000001400616808800000002BF +:103EA00002168068000000000216806C000000000E +:103EB00002168070000000C0061680740000000525 +:103EC0000216880C0101010102168810010120046C +:103ED000021688142008100102168818010101201A +:103EE0000216881C0101010102168820010120042C +:103EF00002168824200810010216882801010120DA +:103F00000216882C200810010216883001010120B9 +:103F100002168834010101010216883801012004CB +:103F20000216883C20081001021688400101012079 +:103F3000021688440101010102168848010120048B +:103F40000216E6BC000000000216E6C000000002F7 +:103F50000216E6C4000000040216E6C800000006CF +:103F60000216E79400000001021680EC000000FF3A +:103F700002140000000000010215C024000000002F +:103F80000215C0EC000000010215C0F000000001A5 +:103F90000615C10000000002021400040000000128 +:103FA00002140008000000010214000C00000001CF +:103FB000021400300000000102140034000000016F +:103FC0000214004000000001021400440000FFFF42 +:103FD00006140004000000030214000000000000AA +:103FE000060280000000200002020058000000329B +:103FF000020200A003150020020200A40315002005 +:10400000020200A801000030020200AC081000000B +:10401000020200B000000036020200B400000030CE +:10402000020200B800000031020200BC00000002E1 +:10403000020200C000000005020200C400000002ED +:10404000020200C800000002020200D000000007C7 +:10405000020200DC00000000020200E00000000597 +:10406000020200E400000003020200F00000000170 +:10407000020200FC00000006020201200000000015 +:104080000202013400000002020201B0000000013F +:104090000202020C000000010202021400000001F2 +:1040A00002020218000000020202040400000001E3 +:1040B0000202040C00000040020204100000004054 +:1040C0000202041C00000004020204200000002080 +:1040D0000202042400000002020204280000002062 +:1040E000060205000000001204020480002008BF40 +:1040F000020200600000000F0202006400000007DE +:1041000002020068000000000202006C0000000EC5 +:10411000020200700000000E06020074000000039E +:10412000020200F40000000402020004000000018A +:1041300002020008000000010202000C0000000161 +:104140000202001000000001020200140000000141 +:1041500002020018000000010202001C0000000121 +:104160000202002000000001020200240000000101 +:1041700002020028000000010202002C00000001E1 +:1041800002020030000000010202003400000001C1 +:1041900002020038000000010202003C00000001A1 +:1041A0000202004000000001020200440000000181 +:1041B00002020048000000010202004C0000000161 +:1041C000020200500000000102020108000000C8C5 +:1041D0000202011800000002020201C400000000F7 +:1041E000020201CC00000000020201D40000000223 +:1041F000020201DC00000002020201E4000000FFF4 +:10420000020201EC000000FF0202010000000000B9 +:104210000202010C000000C80202011C00000002A2 +:10422000020201C800000000020201D000000000EC +:10423000020201D800000002020201E000000002B8 +:10424000020201E8000000FF020201F0000000FF8E +:10425000020201040000002002020108000000C860 +:104260000202011800000002020201C40000000066 +:10427000020201CC00000000020201D40000000292 +:10428000020201DC00000002020201E4000000FF63 +:10429000020201EC000000FF020201000000001019 +:1042A0000202010C000000C80202011C0000000212 +:1042B000020201C800000000020201D0000000005C +:1042C000020201D800000002020201E00000000228 +:1042D000020201E8000000FF020201F0000000FFFE +:1042E000020201040000003002020108000000C8C0 +:1042F0000202011800000002020201C400000000D6 +:10430000020201CC00000000020201D40000000201 +:10431000020201DC00000002020201E4000000FFD2 +:10432000020201EC000000FF020201000000004058 +:104330000202010C000000C80202011C0000000281 +:10434000020201C800000000020201D000000000CB +:10435000020201D800000002020201E00000000297 +:10436000020201E8000000FF020201F0000000FF6D +:10437000020201040000006002020108000000C8FF +:104380000202011800000002020201C40000000045 +:10439000020201CC00000000020201D40000000271 +:1043A000020201DC00000002020201E4000000FF42 +:1043B000020201EC000000FF0202010000000050B8 +:1043C0000202010C000000C80202011C00000002F1 +:1043D000020201C800000000020201D0000000003B +:1043E000020201D800000002020201E00000000207 +:1043F000020201E8000000FF020201F0000000FFDD +:1044000002020104000000700728040000B300004D +:10441000082807B8000908DF072C000028CB000097 +:10442000072C8000365D0A33072D0000347017CB4F +:10443000072D80003A9424E8072E000036C7338EFB +:10444000072E80001CE94140082EC5D0274608E110 +:10445000022800BC0000003001280000000000001D +:1044600001280004000000000128000800000000EE +:104470000128000C000000000128001000000000CE +:1044800001280014000000000228002000000001A4 +:104490000228002400000002022800280000000377 +:1044A0000228002C00000000022800300000000458 +:1044B000022800340000000102280038000000003B +:1044C0000228003C00000001022800400000000417 +:1044D00002280044000000000228004800000001FB +:1044E0000228004C000000030228005000000000D9 +:1044F00002280054000000010228005800000004B7 +:104500000228005C0000000002280060000000019A +:104510000228006400000003022800680000000078 +:104520000228006C00000001022800700000000456 +:104530000228007400000000022800780000000437 +:104540000228007C00000003062800800000000212 +:10455000022800A400007FFF022800A8000003FF3B +:10456000022802240000000002280234000000009B +:104570000228024C00000000022802E40000FFFFB5 +:104580000628200000000800022B8BC0000000015C +:10459000022B800000000000022B80400000001869 +:1045A000022B80800000000C022B80C000000066FF +:1045B0000C2B8300000864700A2B83000000015755 +:1045C0000B2B83000000055F0A2B834000000000D6 +:1045D0000C2B8340000002260B2B834000000001BF +:1045E000022B838000086470022B83C00000022627 +:1045F000022B1480000000010A2B14800000000030 +:10460000022B944000000001062B94480000000299 +:10461000062A9A7000000004042A9A80000408E325 +:10462000062A9A9000000002042A9A98000208E7DD +:10463000062A900000000048062A2008000000C852 +:10464000062A200000000002062A912800000086A9 +:10465000062AC00000000120062A9348000000033B +:10466000042A9354000108E9062A9FB000000002C2 +:10467000042A9418000208EA042A9CD0000108ECDD +:10468000062A9CD400000011042A9D20008F08ED0A +:10469000062A9F5C00000005042A30000002097C05 +:1046A000062A300800000100062A404000000010E1 +:1046B000042A40000010097E042A84080002098EA2 +:1046C000042ACF4000040990042ACF600002099414 +:1046D000062A9FA000000004062A60000000054092 +:1046E000062A9D1800000002062AB00000000050B3 +:1046F000062ABB7000000070062ABB68000000029A +:10470000062AB94800000004062AD000000008006C +:10471000062AC48000000150062A942000000032BE +:10472000062A502000000002062A50300000000235 +:10473000062A500000000002062A50100000000265 +:10474000022A520800000001042A9AA000020996D9 +:10475000062A95B000000022042A96380001099824 +:10476000062A963C00000003062A96E0000000227C +:10477000042A976800010999062A976C0000000333 +:10478000062A981000000022042A98980001099A2D +:10479000062A989C00000003062A99400000002287 +:1047A000042A99C80001099B062A99CC000000033D +:1047B000062ABB5800000002062AC9C000000150AA +:1047C000062A94E800000032062A50280000000261 +:1047D000062A503800000002062A50080000000295 +:1047E000062A501800000002022A520C00000001A4 +:1047F000042A9AA80002099C062A96480000002272 +:10480000042A96D00001099E062A96D400000003CF +:10481000062A977800000022042A98000001099FC8 +:10482000062A980400000003062A98A80000002227 +:10483000042A9930000109A0062A993400000003D7 +:10484000062A99D800000022042A9A60000109A1D2 +:10485000062A9A6400000003062ABB6000000002DA +:10486000022ACF0000000000042A9AB0001009A21A +:10487000062A50480000000E022ACF040000000063 +:10488000042A9AF0001009B2062A50800000000E97 +:10489000022ACF0800000000042A9B30001009C241 +:1048A000062A50B80000000E022ACF0C00000000BB +:1048B000042A9B70001009D2062A50F00000000E56 +:1048C000022ACF1000000000042A9BB0001009E269 +:1048D000062A51280000000E022ACF140000000012 +:1048E000042A9BF0001009F2062A51600000000E15 +:1048F000022ACF1800000000042A9C3000100A028F +:10490000062A51980000000E022ACF1C0000000069 +:10491000042A9C7000100A12062A51D00000000ED2 +:1049200002101008000000010210105000000001E9 +:10493000021010000003D000021010040000003D1F +:104940000910180002000A220910110000100C22A0 +:1049500006101140000000080910116000100C3210 +:10496000061011A00000001806102400000000E04E +:104970000210201C00000000021020200000000196 +:10498000021020C0000000020210200400000001FC +:104990000210200800000001021030D800000001C1 +:1049A00009103C0000050C420910380000050C47B6 +:1049B0000910392000050C4C09103B0000050C5172 +:1049C000021040D400000030021040D80000003037 +:1049D00006104C00000001000210402800000010EA +:1049E0000210404400003FFF021040580028000021 +:1049F000021040840084924A0210405800000000D7 +:104A0000021041380000000102104138000000018E +:104A1000021041380000000102104138000000017E +:104A2000021041380000000102104138000000016E +:104A3000021041380000000102104138000000015E +:104A40000212049001F680400212051400003C108E +:104A500002120494FFFFFFFF02120498FFFFFFFF02 +:104A60000212049CFFFFFFFF021204A0FFFFFFFFE2 +:104A7000021204A4FFFFFFFF021204A8FFFFFFFFC2 +:104A8000021204ACFFFFFFFF021204B0FFFFFFFFA2 +:104A9000021204B8FFFFFFFF021204BCFFFFFFFF7A +:104AA000021204C0FFFFFFFF021204C4FFFFFFFF5A +:104AB000021204C8FFFFFFFF021204CCFFFFFFFF3A +:104AC000021204D0FFFFFFFF021204D8FFFFFFFF16 +:104AD000021204DCFFFFFFFF021204E0FFFFFFFFF2 +:104AE000021204E4FFFFFFFF021204E8FFFFFFFFD2 +:104AF000021204ECFFFFFFFF021204F0FFFFFFFFB2 +:104B0000021204F4FFFFFFFF021204F8FFFFFFFF91 +:104B1000021204FCFFFFFFFF02120500FFFFFFFF70 +:104B200002120504FFFFFFFF02120508FFFFFFFF4F +:104B30000212050CFFFFFFFF02120510FFFFFFFF2F +:104B4000021204D4F800C000021204B4F0005000B5 +:104B500002120390000000080212039C00000008EB +:104B6000021203A000000008021203A400000002C9 +:104B7000021203BC00000004021203C00000000582 +:104B8000021203C400000004021203D0000000005F +:104B90000212036C00000001021201BC0000004080 +:104BA000021201C000001808021201C4000008032C +:104BB000021201C800000803021201CC00000040EC +:104BC000021201D000000003021201D40000080309 +:104BD000021201D800000803021201DC00000803E1 +:104BE000021201E000010003021201E400000803C8 +:104BF000021201E800000803021201EC00000003A9 +:104C0000021201F000000003021201F40000000390 +:104C1000021201F800000003021201FC0000000370 +:104C2000021202000000000302120204000000034E +:104C300002120208000000030212020C000000032E +:104C4000021202100000000302120214000000030E +:104C500002120218000000030212021C00000003EE +:104C600002120220000000030212022400000003CE +:104C700002120228000024030212022C0000002F5E +:104C80000212023000000009021202340000001972 +:104C900002120238000001840212023C000001836B +:104CA0000212024000000306021202440000001932 +:104CB00002120248000000060212024C0000030625 +:104CC0000212025000000306021202540000030602 +:104CD0000212025800000C860212025C0000030659 +:104CE00002120260000003060212026400000006C5 +:104CF00002120268000000060212026C00000006A8 +:104D00000212027000000006021202740000000687 +:104D100002120278000000060212027C0000000667 +:104D20000212028000000006021202840000000647 +:104D300002120288000000060212028C0000000627 +:104D40000212029000000006021202940000000607 +:104D500002120298000000060212029C00000006E7 +:104D6000021202A000000306021202A400000013B7 +:104D7000021202A800000006021202B00000100495 +:104D8000021202B400001004021203240010644056 +:104D90000212032800106440021205B40000000152 +:104DA000021205F800000040021205FC0000001984 +:104DB00002120600000000010212066C0000000151 +:104DC000021201B000000001021207D80000000327 +:104DD000021207D800000003021207D800000003E7 +:104DE000021207D800000003021207D800000003D7 +:104DF000021207D800000003021207D800000003C7 +:104E0000021207D8000000030600A0000000000CFA +:104E10000200A050000000000200A05400000000AA +:104E20000200A0EC555400000200A0F05555555565 +:104E30000200A0F4000055550200A0F8F0000000A8 +:104E40000200A0FC555400000200A1005555555524 +:104E50000200A104000055550200A108F000000066 +:104E60000200A19C000000000200A1A000010000BF +:104E70000200A1A4000050140200A1A8000000003C +:104E80000200A6A8000000000200A6AC000000007E +:104E90000200A6D0000000000200A45C00000C008C +:104EA0000200A61C000000030200A070FFF55FFFD7 +:104EB0000200A0740000FFFF0200A078F00003E0F1 +:104EC0000200A07C000000000200A0800000A00002 +:104ED0000600A084000000050200A0980FE000007A +:104EE0000600A09C000000070200A0B8000004001B +:104EF0000600A0BC000000030200A0C800001000D3 +:104F00000600A0CC000000030200A0D80000400072 +:104F10000600A0DC000000030200A0E80001000081 +:104F20000600A22C000000040200A688000000FC7D +:104F30000600A68C000000070200A6F40000000096 +:104F40000200A10CFF5C00000200A110FFF55FFF52 +:104F50000200A1140000FFFF0200A118F00003E00E +:104F60000200A11C000000000200A1200000A0001F +:104F70000600A124000000050200A1380FE0000097 +:104F80000600A13C000000070200A1580000080034 +:104F90000600A15C000000030200A16800002000E0 +:104FA0000600A16C000000030200A1780000800050 +:104FB0000600A17C000000030200A188000200009E +:104FC0000600A23C000000040200A6B0000000FCA5 +:104FD0000600A6B4000000070200A6F800000000CA +:104FE0000200A030000000000200A0340000000019 +:104FF0000200A038000000000200A03C00000000F9 +:105000000200A040000000000200A04400000000D8 +:105010000200A048000000000200A04C00000000B8 +:10502000020090C40000E000020090CC0000F300F9 +:10503000020090D400000003020091A000000001D3 +:105040000600917000000003020090EC0000600078 +:10505000020090F400007300020090FC00000003C6 +:10506000020091A8000000010600918800000003E2 +:10507000020091000000400002009108000053006F +:105080000200911000000004020091AC0000000139 +:1050900006009194000000020200919C00000001B3 +:1050A000020090D800006000020090E00000730051 +:1050B000020090E800000003020091A4000000013B +:1050C0000200917C000000010200918000000001BC +:1050D00002009184000000000200912800000300FB +:1050E0000200916C0003F0080200912C0000030004 +:1050F0000200913000000300020091340000030020 +:1051000002009138000003000200913C00000300FF +:1051100002009140000003000200942C00000001F6 +:1051200002009430000000010200943400000001ED +:105130000200942C000000010200943000000001E5 +:1051400002009434000000010200942C00000001D1 +:1051500002009430000000010200943400000001BD +:105160000200942C000000010200943000000001B5 +:1051700002009434000000010200942C00000001A1 +:10518000020094300000000102009434000000018D +:105190000200942C00000001020094300000000185 +:1051A00002009434000000010200942C0000000171 +:1051B000020094300000000102009434000000015D +:1051C0000200942C00000001020094300000000155 +:1051D0000200943400000001021300780000003047 +:1051E0000213003C000061A8061301080000000340 +:1051F000021301040000000002130134000000004B +:10520000061301080000000302130104000000005F +:10521000021301340000000006130108000000031F +:10522000021301040000000002130134000000001A +:10523000061301080000000302130104000000002F +:1052400002130134000000000613010800000003EF +:1052500002130104000000000213013400000000EA +:1052600006130108000000030213010400000000FF +:1052700002130134000000000613010800000003BF +:1052800002130104000000000213013400000000BA +:1052900006130108000000030213010400000000CF +:1052A0000213013400000000021100B800000001E8 +:1052B0000216E6E8000020000216E6EC00002000DE +:1052C0000216E6F0000065550216E6F4000065558A +:1052D00002168150000000000216817400000001D7 +:1052E00002168178000000010216817C0000000196 +:1052F0000216818000000001021681840000000176 +:105300000216818800000001021681B4000000012D +:10531000021681B800000001021681BC00000001E5 +:10532000021681C000000001021681C400000001C5 +:10533000021681C800000001021681100000000062 +:105340000216824000BF00BF061682440000000221 +:105350000216824C00BF00BF0216E6C40000000126 +:105360000216E6C8000000030216E79400000000E1 +:10537000042ACF40000A0C56000000000000000084 +:1053800000000034000000000000000000000000E9 +:10539000000000000000000000000000000000000D +:1053A0000000000000000000000000000034003594 +:1053B00000000000000000000000000000000000ED +:1053C00000000000000000000000000000000000DD +:1053D0000000000000000000003500600000000038 +:1053E00000000000000000000000000000000000BD +:1053F00000000000000000000000000000000000AD +:1054000000000000006000910000000000000000AB +:1054100000910095009500990099009D009D00A1C4 +:1054200000A100A500A500A900A900AD00AD00B134 +:1054300000B100B500000000000000000000000006 +:10544000000000000000000000000000000000005C +:1054500000000000000000000000000000B5031183 +:105460000311031B031B03250325032C032C033308 +:105470000333033A033A0341034103480348034F0C +:10548000034F03560356035D0000000000000000B8 +:10549000000000000000000000000000000000000C +:1054A00000000000000000000000000000000000FC +:1054B00000000000000000000000000000000000EC +:1054C00000000000000000000000000000000000DC +:1054D00000000000000000000000000000000000CC +:1054E00000000000000000000000000000000000BC +:1054F00000000000000000000000000000000000AC +:10550000000000000000000000000000000000009B +:10551000000000000000000000000000000000008B +:10552000000000000000000000000000000000007B +:105530000000000000000000035D035E00000000AA +:1055400000000000035E035F035F0360036003610C +:10555000036103620362036303630364036403651B +:10556000036503660000000000000000000000006A +:10557000000000000000000000000000000000002B +:10558000000000000000000000000000000000001B +:105590000366036D036D0379037903850000000042 +:1055A00000000000000000000000000000000000FB +:1055B00000000000000000000000000000000000EB +:1055C00000000000000000000000000000000000DB +:1055D00000000000000000000000000000000000CB +:1055E00000000000000000000385038600000000AA +:1055F00000000000000000000000000000000000AB +:10560000000000000000000000000000000000009A +:1056100000000000038603B100000000000000004D +:10562000000000000000000000000000000000007A +:10563000000000000000000000000000000000006A +:1056400003B103E0000000000000000000000000C3 +:10565000000000000000000000000000000000004A +:1056600000000000000000000000000003E0040F44 +:105670000000000000000000040F04160416041DC2 +:10568000041D04240424042B042B043204320439A2 +:1056900004390440044004470447047A0000000031 +:1056A00000000000047A047E047E048204820486E2 +:1056B0000486048A048A048E048E0492049204965A +:1056C0000496049A049A04EA04EA05000500051603 +:1056D000051605180518051A051A051C051C051ED2 +:1056E000051E052005200522052205240524052682 +:1056F00005260693000000000000000006930698AF +:105700000698069D069D06A206A206A706A706AC59 +:1057100006AC06B106B106B606B606BB06BB06BCAD +:105720000000000000000000000000000000000079 +:105730000000000000000000000000000000000069 +:10574000000000000000000006BC06E000000000B1 +:105750000000000006E006E206E206E406E406E6D3 +:1057600006E606E806E806EA06EA06EC06EC06EEB9 +:1057700006EE06F006F00705070507080708070B01 +:105780000000000000000000000000000000000019 +:105790000000000000000000000000000000000009 +:1057A000070B074F00000000000000000000000091 +:1057B00000000000000000000000000000000000E9 +:1057C000000000000000000000000000074F07E19B +:1057D00000000000000000000000000000000000C9 +:1057E00000000000000000000000000000000000B9 +:1057F000000000000000000007E107EF00000000CB +:105800000000000000000000000000000000000098 +:105810000000000000000000000000000000000088 +:105820000000000007EF082C00000000000000004E +:10583000082C08350835083E083E08470847085038 +:1058400008500859085908620862086B086B087408 +:10585000087408D508D508EA08EA08FF08FF090215 +:1058600009020905090509080908090B090B090EB0 +:10587000090E09110911091409140917091709203A +:105880000000000000000000000000000000000018 +:105890000000000000000000000000000000000008 +:1058A00000000000000000000920092600000000A0 +:1058B00000000000000000000000000000000000E8 +:1058C00000000000000000000000000000000000D8 +:1058D000000000000926092B000000000000000065 +:1058E00000000000000000000000000000000000B8 +:1058F00000000000000000000000000000000000A8 +:10590000092B0933000000000000000009330934AE +:10591000093409350935093609360937093709388F +:10592000093809390939093A093A093B00000000E8 +:105930000000000000000000000000000000000067 +:105940000000000000000000000000000000000057 +:105950000000000000000000093B09AC000000004E +:105960000000000009AC09AD09AD09AE09AE09AFF0 +:1059700009AF09B009B009B109B109B209B209B357 +:1059800009B309B409B409C809C809DB09DB09EF7F +:1059900009EF09F009F009F109F109F209F209F337 +:1059A00009F309F409F409F509F509F609F609F707 +:1059B00009F70A1600000000000000000A160A1984 +:1059C0000A190A1C0A1C0A1F0A1F0A220A220A258F +:1059D0000A250A280A280A2B0A2B0A2E0A2E0A3020 +:1059E00000000000000000000A300A330A330A36C3 +:1059F0000A360A390A390A3C0A3C0A3F0A3F0A4277 +:105A00000A420A450A450A480A480A4900000000B5 +:105A10000000000000000000000000000000000086 +:105A20000000000000000000000000000000000076 +:105A3000000000000A490A610000000000000000A8 +:105A40000000000000000000000000000000000056 +:105A50000000000000000000000000000000000046 +:105A60000A610A620000000000000000000000005F +:105A70000000000000000000000000000000000026 +:105A80000000000000000000000000000000000016 +:105A9000000100000002070000030E0000041500D2 +:105AA00000051C000006230000072A000008310042 +:105AB00000093800000A3F00000B4600000C4D00B2 +:105AC000000D5400000E5B00000F62000010690022 +:105AD000001170000012770000137E000014850092 +:105AE00000158C000016930000179A000018A10002 +:105AF0000019A800001AAF00001BB600001CBD0072 +:105B0000001DC400001ECB00001FD2000000D90001 +:105B10000000200000004000000060000000800045 +:105B20000000A0000000C0000000E0000001000034 +:105B30000001200000014000000160000001800021 +:105B40000001A0000001C0000001E0000002000010 +:105B500000022000000240000002600000028000FD +:105B60000002A0000002C0000002E00000030000EC +:105B700000032000000340000003600000038000D9 +:105B80000003A0000003C0000003E00000040000C8 +:105B900000042000000440000004600000048000B5 +:105BA0000004A0000004C0000004E00000050000A4 +:105BB0000005200000054000000560000005800091 +:105BC0000005A0000005C0000005E0000006000080 +:105BD000000620000006400000066000000680006D +:105BE0000006A0000006C0000006E000000700005C +:105BF0000007200000074000000760000007800049 +:105C00000007A0000007C0000007E0000008000037 +:105C10000008200000084000000860000008800024 +:105C20000008A0000008C0000008E0000009000013 +:105C30000009200000094000000960000009800000 +:105C40000009A0000009C0000009E000000A0000EF +:105C5000000A2000000A4000000A6000000A8000DC +:105C6000000AA000000AC000000AE000000B0000CB +:105C7000000B2000000B4000000B6000000B8000B8 +:105C8000000BA000000BC000000BE000000C0000A7 +:105C9000000C2000000C4000000C6000000C800094 +:105CA000000CA000000CC000000CE000000D000083 +:105CB000000D2000000D4000000D6000000D800070 +:105CC000000DA000000DC000000DE000000E00005F +:105CD000000E2000000E4000000E6000000E80004C +:105CE000000EA000000EC000000EE000000F00003B +:105CF000000F2000000F4000000F6000000F800028 +:105D0000000FA000000FC000000FE0000010000016 +:105D10000010200000104000001060000010800003 +:105D20000010A0000010C0000010E00000110000F2 +:105D300000112000001140000011600000118000DF +:105D40000011A0000011C0000011E00000120000CE +:105D500000122000001240000012600000128000BB +:105D60000012A0000012C0000012E00000130000AA +:105D70000013200000134000001360000013800097 +:105D80000013A0000013C0000013E0000014000086 +:105D90000014200000144000001460000014800073 +:105DA0000014A0000014C0000014E0000015000062 +:105DB000001520000015400000156000001580004F +:105DC0000015A0000015C0000015E000001600003E +:105DD000001620000016400000166000001680002B +:105DE0000016A0000016C0000016E000001700001A +:105DF0000017200000174000001760000017800007 +:105E00000017A0000017C0000017E00000180000F5 +:105E100000182000001840000018600000188000E2 +:105E20000018A0000018C0000018E00000190000D1 +:105E300000192000001940000019600000198000BE +:105E40000019A0000019C0000019E000001A0000AD +:105E5000001A2000001A4000001A6000001A80009A +:105E6000001AA000001AC000001AE000001B000089 +:105E7000001B2000001B4000001B6000001B800076 +:105E8000001BA000001BC000001BE000001C000065 +:105E9000001C2000001C4000001C6000001C800052 +:105EA000001CA000001CC000001CE000001D000041 +:105EB000001D2000001D4000001D6000001D80002E +:105EC000001DA000001DC000001DE000001E00001D +:105ED000001E2000001E4000001E6000001E80000A +:105EE000001EA000001EC000001EE000001F0000F9 +:105EF000001F2000001F4000001F6000001F8000E6 +:105F0000001FA000001FC000001FE00000200000D4 +:105F100000202000002040000020600000208000C1 +:105F20000020A0000020C0000020E00000210000B0 +:105F3000002120000021400000216000002180009D +:105F40000021A0000021C0000021E000002200008C +:105F50000022200000224000002260000022800079 +:105F60000022A0000022C0000022E0000023000068 +:105F70000023200000234000002360000023800055 +:105F80000023A0000023C0000023E0000024000044 +:105F90000024200000244000002460000024800031 +:105FA0000024A0000024C0000024E0000025000020 +:105FB000002520000025400000256000002580000D +:105FC0000025A0000025C0000025E00000260000FC +:105FD00000262000002640000026600000268000E9 +:105FE0000026A0000026C0000026E00000270000D8 +:105FF00000272000002740000027600000278000C5 +:106000000027A0000027C0000027E00000280000B3 +:1060100000282000002840000028600000288000A0 +:106020000028A0000028C0000028E000002900008F +:10603000002920000029400000296000002980007C +:106040000029A0000029C0000029E000002A00006B +:10605000002A2000002A4000002A6000002A800058 +:10606000002AA000002AC000002AE000002B000047 +:10607000002B2000002B4000002B6000002B800034 +:10608000002BA000002BC000002BE000002C000023 +:10609000002C2000002C4000002C6000002C800010 +:1060A000002CA000002CC000002CE000002D0000FF +:1060B000002D2000002D4000002D6000002D8000EC +:1060C000002DA000002DC000002DE000002E0000DB +:1060D000002E2000002E4000002E6000002E8000C8 +:1060E000002EA000002EC000002EE000002F0000B7 +:1060F000002F2000002F4000002F6000002F8000A4 +:10610000002FA000002FC000002FE0000030000092 +:10611000003020000030400000306000003080007F +:106120000030A0000030C0000030E000003100006E +:10613000003120000031400000316000003180005B +:106140000031A0000031C0000031E000003200004A +:106150000032200000324000003260000032800037 +:106160000032A0000032C0000032E0000033000026 +:106170000033200000334000003360000033800013 +:106180000033A0000033C0000033E0000034000002 +:1061900000342000003440000034600000348000EF +:1061A0000034A0000034C0000034E00000350000DE +:1061B00000352000003540000035600000358000CB +:1061C0000035A0000035C0000035E00000360000BA +:1061D00000362000003640000036600000368000A7 +:1061E0000036A0000036C0000036E0000037000096 +:1061F0000037200000374000003760000037800083 +:106200000037A0000037C0000037E0000038000071 +:10621000003820000038400000386000003880005E +:106220000038A0000038C0000038E000003900004D +:10623000003920000039400000396000003980003A +:106240000039A0000039C0000039E000003A000029 +:10625000003A2000003A4000003A6000003A800016 +:10626000003AA000003AC000003AE000003B000005 +:10627000003B2000003B4000003B6000003B8000F2 +:10628000003BA000003BC000003BE000003C0000E1 +:10629000003C2000003C4000003C6000003C8000CE +:1062A000003CA000003CC000003CE000003D0000BD +:1062B000003D2000003D4000003D6000003D8000AA +:1062C000003DA000003DC000003DE000003E000099 +:1062D000003E2000003E4000003E6000003E800086 +:1062E000003EA000003EC000003EE000003F000075 +:1062F000003F2000003F4000003F6000003F800062 +:10630000003FA000003FC000003FE000003FE00170 +:1063100000000000000001FF0000020000007FF804 +:1063200000007FF800000A90000035000000000126 +:106330000000FF00000000000000FF00000000005F +:106340000000FF00000000000000FF00000000004F +:106350000000FF00000000000000FF00000000003F +:106360000000FF00000000000000FF00000000002F +:106370000000FF00000000000000FF00000000001F +:106380000000FF00000000000000FF00000000000F +:106390000000FF00000000000000FF0000000000FF +:1063A0000000FF00000000000000FF0000000000EF +:1063B0000000FF00000000000000FF0000000000DF +:1063C0000000FF00000000000000FF0000000000CF +:1063D0000000FF00000000000000FF0000000000BF +:1063E0000000FF00000000000000FF0000000000AF +:1063F0000000FF00000000000000FF00000000009F +:106400000000FF00000000000000FF00000000008E +:106410000000FF00000000000000FF00000000007E +:106420000000FF00000000000000FF00000000006E +:106430000000FF00000000000000FF00000000005E +:106440000000FF00000000000000FF00000000004E +:106450000000FF00000000000000FF00000000003E +:106460000000FF00000000000000FF00000000002E +:106470000000FF00000000000000FF00000000001E +:106480000000FF00000000000000FF00000000000E +:106490000000FF00000000000000FF0000000000FE +:1064A0000000FF00000000000000FF0000000000EE +:1064B0000000FF00000000000000FF0000000000DE +:1064C0000000FF00000000000000FF0000000000CE +:1064D0000000FF00000000000000FF0000000000BE +:1064E0000000FF00000000000000FF0000000000AE +:1064F0000000FF00000000000000FF00000000009E +:106500000000FF00000000000000FF00000000008D +:106510000000FF00000000000000FF00000000007D +:106520000000FF00000000000000FF00000000006D +:106530000000FF00000000000000FF00000000005D +:106540000000FF00000000000000FF00000000004D +:106550000000FF00000000000000FF00000000003D +:106560000000FF00000000000000FF00000000002D +:1065700000000000140AFF000000000100000000FD +:106580000020100100000000010090000000010048 +:1065900000009002000090040000900600009008A7 +:1065A0000000900A0000900C0000900E0000901077 +:1065B0000000901200009014000090160000901847 +:1065C0000000901A0000901C0000901E0000902017 +:1065D00000009022000090240000902600009028E7 +:1065E0000000902A0000902C0000902E00009030B7 +:1065F0000000903200009034000090360000903887 +:106600000000903A0000903C0000903E0000904056 +:106610000000904200009044000090460000904826 +:106620000000904A0000904C0000904E00009050F6 +:1066300000009052000090540000905600009058C6 +:106640000000905A0000905C0000905E0000906096 +:106650000000906200009064000090660000906866 +:106660000000906A0000906C0000906E0000907036 +:106670000000907200009074000090760000907806 +:106680000000907A0000907C0000907E00009080D6 +:1066900000009082000090840000908600009088A6 +:1066A0000000908A0000908C0000908E0000909076 +:1066B0000000909200009094000090960000909846 +:1066C0000000909A0000909C0000909E000090A016 +:1066D000000090A2000090A4000090A6000090A8E6 +:1066E000000090AA000090AC000090AE000090B0B6 +:1066F000000090B2000090B4000090B6000090B886 +:10670000000090BA000090BC000090BE000090C055 +:10671000000090C2000090C4000090C6000090C825 +:10672000000090CA000090CC000090CE000090D0F5 +:10673000000090D2000090D4000090D6000090D8C5 +:10674000000090DA000090DC000090DE000090E095 +:10675000000090E2000090E4000090E6000090E865 +:10676000000090EA000090EC000090EE000090F035 +:10677000000090F2000090F4000090F6000090F805 +:10678000000090FA000090FC000090FE00009100D4 +:1067900000009102000091040000910600009108A1 +:1067A0000000910A0000910C0000910E0000911071 +:1067B0000000911200009114000091160000911841 +:1067C0000000911A0000911C0000911E0000912011 +:1067D00000009122000091240000912600009128E1 +:1067E0000000912A0000912C0000912E00009130B1 +:1067F0000000913200009134000091360000913881 +:106800000000913A0000913C0000913E0000914050 +:106810000000914200009144000091460000914820 +:106820000000914A0000914C0000914E00009150F0 +:1068300000009152000091540000915600009158C0 +:106840000000915A0000915C0000915E0000916090 +:106850000000916200009164000091660000916860 +:106860000000916A0000916C0000916E0000917030 +:106870000000917200009174000091760000917800 +:106880000000917A0000917C0000917E00009180D0 +:1068900000009182000091840000918600009188A0 +:1068A0000000918A0000918C0000918E0000919070 +:1068B0000000919200009194000091960000919840 +:1068C0000000919A0000919C0000919E000091A010 +:1068D000000091A2000091A4000091A6000091A8E0 +:1068E000000091AA000091AC000091AE000091B0B0 +:1068F000000091B2000091B4000091B6000091B880 +:10690000000091BA000091BC000091BE000091C04F +:10691000000091C2000091C4000091C6000091C81F +:10692000000091CA000091CC000091CE000091D0EF +:10693000000091D2000091D4000091D6000091D8BF +:10694000000091DA000091DC000091DE000091E08F +:10695000000091E2000091E4000091E6000091E85F +:10696000000091EA000091EC000091EE000091F02F +:10697000000091F2000091F4000091F6000091F8FF +:10698000000091FA000091FC000091FEFFFFFFFF64 +:10699000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07 +:1069A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7 +:1069B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7 +:1069C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7 +:1069D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7 +:1069E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB7 +:1069F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA7 +:106A0000FFFFFFFFFFFFFFFFFFFFFFFF000000038F +:106A100000BEBC20000000000000000500000003D4 +:106A200000BEBC20000000000000000500000003C4 +:106A300000BEBC20000000000000000500000003B4 +:106A400000BEBC20000000000000000500000003A4 +:106A500000BEBC2000000000000000050000000394 +:106A600000BEBC2000000000000000050000000384 +:106A700000BEBC2000000000000000050000000374 +:106A800000BEBC2000000000000000050000200047 +:106A9000000040C000006180000082400000A300B0 +:106AA0000000C3C00000E480000105400001260092 +:106AB000000146C000016780000188400001A90074 +:106AC0000001C9C00001EA8000020B4000022C0056 +:106AD00000024CC000026D8000028E400002AF0038 +:106AE0000002CFC00002F0800000114000008000D2 +:106AF000000103800001870000020A8000028E006E +:106B000000031180000395000004188000049C001D +:106B100000051F800005A300000626800006AA00CD +:106B200000072D800007B100000834800008B8007D +:106B300000093B800009BF00000A4280000AC6002D +:106B4000000B4980000BCD00000C5080000CD400DD +:106B5000000D578000005B0000007FF800007FF808 +:106B60000000022A000035000000FF0000000000C5 +:106B70000000FF00000000000000FF000000000017 +:106B80000000FF00000000000000FF000000000007 +:106B90000000FF00000000000000FF0000000000F7 +:106BA0000000FF00000000000000FF0000000000E7 +:106BB0000000FF00000000000000FF0000000000D7 +:106BC0000000FF00000000000000FF0000000000C7 +:106BD0000000FF00000000000000FF0000000000B7 +:106BE0000000FF00000000000000FF0000000000A7 +:106BF0000000FF00000000000000FF000000000097 +:106C00000000FF00000000000000FF000000000086 +:106C10000000FF00000000000000FF000000000076 +:106C20000000FF00000000000000FF000000000066 +:106C30000000FF00000000000000FF000000000056 +:106C40000000FF00000000000000FF000000000046 +:106C50000000FF00000000000000FF000000000036 +:106C60000000FF00000000000000FF000000000026 +:106C70000000FF00000000000000FF000000000016 +:106C80000000FF00000000000000FF000000000006 +:106C90000000FF00000000000000FF0000000000F6 +:106CA0000000FF00000000000000FF0000000000E6 +:106CB0000000FF00000000000000FF0000000000D6 +:106CC0000000FF00000000000000FF0000000000C6 +:106CD0000000FF00000000000000FF0000000000B6 +:106CE0000000FF00000000000000FF0000000000A6 +:106CF0000000FF00000000000000FF000000000096 +:106D00000000FF00000000000000FF000000000085 +:106D10000000FF00000000000000FF000000000075 +:106D20000000FF00000000000000FF000000000065 +:106D30000000FF00000000000000FF000000000055 +:106D40000000FF00000000000000FF000000000045 +:106D50000000FF00000000000000FF000000000035 +:106D60000000FF00000000000000FF000000000025 +:106D70000000FF00000000000000FF000000000015 +:106D80000000FF00000000000000FF000000000005 +:106D90000000FF00000000000000FF0000000000F5 +:106DA0000000FF00000019000000000000000000CB +:106DB000FFFFFFFF000000000393870000000000BA +:106DC0000393870000007FF800007FF800000BA30A +:106DD00000001500000000FF000000FF000000FFA1 +:106DE000000000FF000000FF000000FF000000FFA7 +:106DF000000000FF0000FF00000000000000FF0096 +:106E0000000000000000FF00000000000000FF0084 +:106E1000000000000000FF00000000000000FF0074 +:106E2000000000000000FF00000000000000FF0064 +:106E3000000000000000FF00000000000000FF0054 +:106E4000000000000000FF00000000000000FF0044 +:106E5000000000000000FF00000000000000FF0034 +:106E6000000000000000FF00000000000000FF0024 +:106E7000000000000000FF00000000000000FF0014 +:106E8000000000000000FF00000000000000FF0004 +:106E9000000000000000FF00000000000000FF00F4 +:106EA000000000000000FF00000000000000FF00E4 +:106EB000000000000000FF00000000000000FF00D4 +:106EC000000000000000FF00000000000000FF00C4 +:106ED000000000000000FF00000000000000FF00B4 +:106EE000000000000000FF00000000000000FF00A4 +:106EF000000000000000FF00000000000000FF0094 +:106F0000000000000000FF00000000000000FF0083 +:106F1000000000000000FF00000000000000FF0073 +:106F2000000000000000FF00000000000000FF0063 +:106F3000000000000000FF00000000000000FF0053 +:106F4000000000000000FF00000000000000FF0043 +:106F5000000000000000FF00000000000000FF0033 +:106F6000000000000000FF00000000000000FF0023 +:106F7000000000000000FF00000000000000FF0013 +:106F8000000000000000FF00000000000000FF0003 +:106F9000000000000000FF00000000000000FF00F3 +:106FA000000000000000FF00000000000000FF00E3 +:106FB000000000000000FF00000000000000FF00D3 +:106FC000000000000000FF00000000000000FF00C3 +:106FD000000000000000FF00000000000000FF00B3 +:106FE000000000000000FF00000000000000FF00A3 +:106FF000000000000000FF00000000000000FF0093 +:10700000000000000000FF00000000000000FF0082 +:10701000000000000000FF00000000000000FF0072 +:10702000000000000000FF00000000000000FF0062 +:1070300000000000FFFFFFFFFFFFFFFFFFFFFFFF5C +:10704000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50 +:10705000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40 +:10706000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30 +:10707000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20 +:10708000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 +:10709000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +:1070A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 +:1070B000FFFFFFFF00000000000028AD00002918BE +:1070C0000000291900000005000000070000FF0073 +:1070D0000FFFFFFF0000FF000FFFFFFF000000FF9A +:1070E0000000FF000000FF000FFFFFFF0000FF0097 +:1070F0000FFFFFFF000000FF0000FF000000FF0087 +:107100000FFFFFFF0000FF000FFFFFFF000000FF69 +:107110000000FF000000FF000FFFFFFF0000FF0066 +:107120000FFFFFFF000000FF0000FF000000FF0056 +:107130000FFFFFFF0000FF000FFFFFFF000000FF39 +:107140000000FF000000FF000FFFFFFF0000FF0036 +:107150000FFFFFFF000000FF0000FF000000FF0026 +:107160000FFFFFFF0000FF000FFFFFFF000000FF09 +:107170000000FF000000FF000FFFFFFF0000FF0006 +:107180000FFFFFFF000000FF0000FF000000FF00F6 +:107190000FFFFFFF0000FF000FFFFFFF000000FFD9 +:1071A0000000FF000000FF000FFFFFFF0000FF00D6 +:1071B0000FFFFFFF000000FF0000FF000000FF00C6 +:1071C0000FFFFFFF0000FF000FFFFFFF000000FFA9 +:1071D0000000FF000000FF000FFFFFFF0000FF00A6 +:1071E0000FFFFFFF000000FF0000FF000000FF0096 +:1071F0000FFFFFFF0000FF000FFFFFFF000000FF79 +:107200000000FF000000FF000FFFFFFF0000FF0075 +:107210000FFFFFFF000000FF0000FF000000FF0065 +:107220000FFFFFFF0000FF000FFFFFFF000000FF48 +:107230000000FF000000FF000FFFFFFF0000FF0045 +:107240000FFFFFFF000000FF0000FF000000FF0035 +:107250000FFFFFFF0000FF000FFFFFFF000000FF18 +:107260000000FF000000FF000FFFFFFF0000FF0015 +:107270000FFFFFFF000000FF0000FF000000FF0005 +:107280000FFFFFFF0000FF000FFFFFFF000000FFE8 +:107290000000FF000000FF000FFFFFFF0000FF00E5 +:1072A0000FFFFFFF000000FF0000FF000000FF00D5 +:1072B0000FFFFFFF0000FF000FFFFFFF000000FFB8 +:1072C0000000FF000000FF000FFFFFFF0000FF00B5 +:1072D0000FFFFFFF000000FF0000FF000000FF00A5 +:1072E0000FFFFFFF0000FF000FFFFFFF000000FF88 +:1072F0000000FF000000FF000FFFFFFF0000FF0085 +:107300000FFFFFFF000000FF0000FF000000FF0074 +:107310000FFFFFFF0000FF000FFFFFFF000000FF57 +:107320000000FF000000FF000FFFFFFF0000FF0054 +:107330000FFFFFFF000000FF0000FF000000FF0044 +:107340000FFFFFFF0000FF000FFFFFFF000000FF27 +:107350000000FF000000FF000FFFFFFF0000FF0024 +:107360000FFFFFFF000000FF0000FF000000FF0014 +:107370000FFFFFFF0000FF000FFFFFFF000000FFF7 +:107380000000FF000000FF000FFFFFFF0000FF00F4 +:107390000FFFFFFF000000FF0000FF000000FF00E4 +:1073A0000FFFFFFF0000FF000FFFFFFF000000FFC7 +:1073B0000000FF000000FF000FFFFFFF0000FF00C4 +:1073C0000FFFFFFF000000FF0000FF000000FF00B4 +:1073D0000FFFFFFF0000FF000FFFFFFF000000FF97 +:1073E0000000FF000000FF000FFFFFFF0000FF0094 +:1073F0000FFFFFFF000000FF0000FF000000FF0084 +:107400000FFFFFFF0000FF000FFFFFFF000000FF66 +:107410000000FF000000FF000FFFFFFF0000FF0063 +:107420000FFFFFFF000000FF0000FF000000FF0053 +:107430000FFFFFFF0000FF000FFFFFFF000000FF36 +:107440000000FF000000FF000FFFFFFF0000FF0033 +:107450000FFFFFFF000000FF0000FF000000FF0023 +:107460000FFFFFFF0000FF000FFFFFFF000000FF06 +:107470000000FF000000FF000FFFFFFF0000FF0003 +:107480000FFFFFFF000000FF0000FF000000FF00F3 +:107490000FFFFFFF0000FF000FFFFFFF000000FFD6 +:1074A0000000FF000000FF000FFFFFFF0000FF00D3 +:1074B0000FFFFFFF000000FF0000FF000000FF00C3 +:1074C0000FFFFFFF0000FF000FFFFFFF000000FFA6 +:1074D0000000FF000000FF000FFFFFFF0000FF00A3 +:1074E0000FFFFFFF000000FF0000FF000000FF0093 +:1074F0000FFFFFFF0000FF000FFFFFFF000000FF76 +:107500000000FF000000FF000FFFFFFF0000FF0072 +:107510000FFFFFFF000000FF0000FF000000FF0062 +:107520000FFFFFFF0000FF000FFFFFFF000000FF45 +:107530000000FF000000FF000FFFFFFF0000FF0042 +:107540000FFFFFFF000000FF0000FF000000FF0032 +:107550000FFFFFFF0000FF000FFFFFFF000000FF15 +:107560000000FF000000FF000FFFFFFF0000FF0012 +:107570000FFFFFFF000000FF0000FF000000FF0002 +:107580000FFFFFFF0000FF000FFFFFFF000000FFE5 +:107590000000FF000000FF000FFFFFFF0000FF00E2 +:1075A0000FFFFFFF000000FF0000FF000000FF00D2 +:1075B0000FFFFFFF0000FF000FFFFFFF000000FFB5 +:1075C0000000FF000000FF000FFFFFFF0000FF00B2 +:1075D0000FFFFFFF000000FF0000FF000000FF00A2 +:1075E0000FFFFFFF0000FF000FFFFFFF000000FF85 +:1075F0000000FF000000FF000FFFFFFF0000FF0082 +:107600000FFFFFFF000000FF0000FF000000FF0071 +:107610000FFFFFFF0000FF000FFFFFFF000000FF54 +:107620000000FF000000FF000FFFFFFF0000FF0051 +:107630000FFFFFFF000000FF0000FF000000FF0041 +:107640000FFFFFFF0000FF000FFFFFFF000000FF24 +:107650000000FF000000FF000FFFFFFF0000FF0021 +:107660000FFFFFFF000000FF0000FF000000FF0011 +:107670000FFFFFFF0000FF000FFFFFFF000000FFF4 +:107680000000FF000000FF000FFFFFFF0000FF00F1 +:107690000FFFFFFF000000FF0000FF000000FF00E1 +:1076A0000FFFFFFF0000FF000FFFFFFF000000FFC4 +:1076B0000000FF000000FF000FFFFFFF0000FF00C1 +:1076C0000FFFFFFF000000FF0000FF000000FF00B1 +:1076D0000FFFFFFF0000FF000FFFFFFF000000FF94 +:1076E0000000FF000000FF000FFFFFFF0000FF0091 +:1076F0000FFFFFFF000000FF0000FF000000FF0081 +:107700000FFFFFFF0000FF000FFFFFFF000000FF63 +:107710000000FF000000FF000FFFFFFF0000FF0060 +:107720000FFFFFFF000000FF0000FF000000FF0050 +:107730000FFFFFFF0000FF000FFFFFFF000000FF33 +:107740000000FF000000FF000FFFFFFF0000FF0030 +:107750000FFFFFFF000000FF0000FF000000FF0020 +:107760000FFFFFFF0000FF000FFFFFFF000000FF03 +:107770000000FF000000FF000FFFFFFF0000FF0000 +:107780000FFFFFFF000000FF0000FF000000FF00F0 +:107790000FFFFFFF0000FF000FFFFFFF000000FFD3 +:1077A0000000FF000000FF000FFFFFFF0000FF00D0 +:1077B0000FFFFFFF000000FF0000FF000000FF00C0 +:1077C0000FFFFFFF0000FF000FFFFFFF000000FFA3 +:1077D0000000FF000000FF000FFFFFFF0000FF00A0 +:1077E0000FFFFFFF000000FF0000FF000000FF0090 +:1077F0000FFFFFFF0000FF000FFFFFFF000000FF73 +:107800000000FF000000FF000FFFFFFF0000FF006F +:107810000FFFFFFF000000FF0000FF000000FF005F +:107820000FFFFFFF0000FF000FFFFFFF000000FF42 +:107830000000FF000000FF000FFFFFFF0000FF003F +:107840000FFFFFFF000000FF0000FF000000FF002F +:107850000FFFFFFF0000FF000FFFFFFF000000FF12 +:107860000000FF000000FF000FFFFFFF0000FF000F +:107870000FFFFFFF000000FF0000FF000000FF00FF +:107880000FFFFFFF0000FF000FFFFFFF000000FFE2 +:107890000000FF000000FF000FFFFFFF0000FF00DF +:1078A0000FFFFFFF000000FF0000FF000000FF00CF +:1078B0000FFFFFFF0000FF000FFFFFFF000000FFB2 +:1078C0000000FF000000FF000FFFFFFF0000FF00AF +:1078D0000FFFFFFF000000FF0000FF000000FF009F +:1078E0000FFFFFFF0000FF000FFFFFFF000000FF82 +:1078F0000000FF000000FF000FFFFFFF0000FF007F +:107900000FFFFFFF000000FF0000FF000000FF006E +:107910000FFFFFFF0000FF000FFFFFFF000000FF51 +:107920000000FF000000FF000FFFFFFF0000FF004E +:107930000FFFFFFF000000FF0000FF000000FF003E +:107940000FFFFFFF0000FF000FFFFFFF000000FF21 +:107950000000FF000000FF000FFFFFFF0000FF001E +:107960000FFFFFFF000000FF0000FF000000FF000E +:107970000FFFFFFF0000FF000FFFFFFF000000FFF1 +:107980000000FF000000FF000FFFFFFF0000FF00EE +:107990000FFFFFFF000000FF0000FF000000FF00DE +:1079A0000FFFFFFF0000FF000FFFFFFF000000FFC1 +:1079B0000000FF000000FF000FFFFFFF0000FF00BE +:1079C0000FFFFFFF000000FF0000FF000000FF00AE +:1079D0000FFFFFFF0000FF000FFFFFFF000000FF91 +:1079E0000000FF000000FF000FFFFFFF0000FF008E +:1079F0000FFFFFFF000000FF0000FF000000FF007E +:107A00000FFFFFFF0000FF000FFFFFFF000000FF60 +:107A10000000FF000000FF000FFFFFFF0000FF005D +:107A20000FFFFFFF000000FF0000FF000000FF004D +:107A30000FFFFFFF0000FF000FFFFFFF000000FF30 +:107A40000000FF000000FF000FFFFFFF0000FF002D +:107A50000FFFFFFF000000FF0000FF000000FF001D +:107A60000FFFFFFF0000FF000FFFFFFF000000FF00 +:107A70000000FF000000FF000FFFFFFF0000FF00FD +:107A80000FFFFFFF000000FF0000FF000000FF00ED +:107A90000FFFFFFF0000FF000FFFFFFF000000FFD0 +:107AA0000000FF000000FF000FFFFFFF0000FF00CD +:107AB0000FFFFFFF000000FF0000FF000000FF00BD +:107AC0000FFFFFFF0000FF000FFFFFFF000000FFA0 +:107AD0000000FF000000FF000FFFFFFF0000FF009D +:107AE0000FFFFFFF000000FF0000FF000000FF008D +:107AF0000FFFFFFF0000FF000FFFFFFF000000FF70 +:107B00000000FF000000FF000FFFFFFF0000FF006C +:107B10000FFFFFFF000000FF0000FF000000FF005C +:107B20000FFFFFFF0000FF000FFFFFFF000000FF3F +:107B30000000FF000000FF000FFFFFFF0000FF003C +:107B40000FFFFFFF000000FF0000FF000000FF002C +:107B50000FFFFFFF0000FF000FFFFFFF000000FF0F +:107B60000000FF000000FF000FFFFFFF0000FF000C +:107B70000FFFFFFF000000FF0000FF000000FF00FC +:107B80000FFFFFFF0000FF000FFFFFFF000000FFDF +:107B90000000FF000000FF000FFFFFFF0000FF00DC +:107BA0000FFFFFFF000000FF0000FF000000FF00CC +:107BB0000FFFFFFF0000FF000FFFFFFF000000FFAF +:107BC0000000FF000000FF000FFFFFFF0000FF00AC +:107BD0000FFFFFFF000000FF0000FF000000FF009C +:107BE0000FFFFFFF0000FF000FFFFFFF000000FF7F +:107BF0000000FF000000FF000FFFFFFF0000FF007C +:107C00000FFFFFFF000000FF0000FF000000FF006B +:107C10000FFFFFFF0000FF000FFFFFFF000000FF4E +:107C20000000FF000000FF000FFFFFFF0000FF004B +:107C30000FFFFFFF000000FF0000FF000000FF003B +:107C40000FFFFFFF0000FF000FFFFFFF000000FF1E +:107C50000000FF000000FF000FFFFFFF0000FF001B +:107C60000FFFFFFF000000FF0000FF000000FF000B +:107C70000FFFFFFF0000FF000FFFFFFF000000FFEE +:107C80000000FF000000FF000FFFFFFF0000FF00EB +:107C90000FFFFFFF000000FF0000FF000000FF00DB +:107CA0000FFFFFFF0000FF000FFFFFFF000000FFBE +:107CB0000000FF000000FF000FFFFFFF0000FF00BB +:107CC0000FFFFFFF000000FF0000FF000000FF00AB +:107CD0000FFFFFFF0000FF000FFFFFFF000000FF8E +:107CE0000000FF000000FF000FFFFFFF0000FF008B +:107CF0000FFFFFFF000000FF0000FF000000FF007B +:107D00000FFFFFFF0000FF000FFFFFFF000000FF5D +:107D10000000FF000000FF000FFFFFFF0000FF005A +:107D20000FFFFFFF000000FF0000FF000000FF004A +:107D30000FFFFFFF0000FF000FFFFFFF000000FF2D +:107D40000000FF000000FF000FFFFFFF0000FF002A +:107D50000FFFFFFF000000FF0000FF000000FF001A +:107D60000FFFFFFF0000FF000FFFFFFF000000FFFD +:107D70000000FF000000FF000FFFFFFF0000FF00FA +:107D80000FFFFFFF000000FF0000FF0000001000D9 +:107D900000002080000031000000418000005200FF +:107DA00000006280000073000000838000009400E7 +:107DB0000000A4800000B5000000C5800000D600CF +:107DC0000000E6800000F7000001078000011800B5 +:107DD00000012880000139000001498000015A009B +:107DE00000016A8000017B0000018B8000019C0083 +:107DF0000001AC800001BD000001CD800001DE006B +:107E00000001EE800001FF0000000F8000007FF8FD +:107E100000007FF8000005F60000350010000000AB +:107E2000000028AD000029180000291900000005F5 +:107E3000000000060001000100090206CCCCCCC9FC +:107E40007058103C0000FF00000000000000FF0020 +:107E5000000000000000FF00000000000000FF0024 +:107E6000000000000000FF00000000000000FF0014 +:107E7000000000000000FF00000000000000FF0004 +:107E8000000000000000FF00000000000000FF00F4 +:107E9000000000000000FF00000000000000FF00E4 +:107EA000000000000000FF00000000000000FF00D4 +:107EB000000000000000FF00000000000000FF00C4 +:107EC000000000000000FF00000000000000FF00B4 +:107ED000000000000000FF00000000000000FF00A4 +:107EE000000000000000FF00000000000000FF0094 +:107EF000000000000000FF00000000000000FF0084 +:107F0000000000000000FF00000000000000FF0073 +:107F1000000000000000FF00000000000000FF0063 +:107F2000000000000000FF00000000000000FF0053 +:107F3000000000000000FF00000000000000FF0043 +:107F4000000000000000FF00000000000000FF0033 +:107F5000000000000000FF00000000000000FF0023 +:107F6000000000000000FF00000000000000FF0013 +:107F7000000000000000FF00000000000000FF0003 +:107F8000000000000000FF00000000000000FF00F3 +:107F9000000000000000FF00000000000000FF00E3 +:107FA000000000000000FF00000000000000FF00D3 +:107FB000000000000000FF00000000000000FF00C3 +:107FC000000000000000FF00000000000000FF00B3 +:107FD000000000000000FF00000000000000FF00A3 +:107FE000000000000000FF00000000000000FF0093 +:107FF000000000000000FF00000000000000FF0083 +:10800000000000000000FF00000000000000FF0072 +:10801000000000000000FF00000000000000FF0062 +:10802000000000000000FF00000000000000FF0052 +:10803000000000000000FF00000000000000FF0042 +:10804000000000000000FF00000000000000FF0032 +:10805000000000000000FF00000000000000FF0022 +:10806000000000000000FF00000000000000FF0012 +:10807000000000000000FF00000000000000FF0002 +:108080000000000000000001CCCC0201CCCCCCCC24 +:10809000CCCC0201CCCCCCCCCCCC0201CCCCCCCC4A +:1080A000CCCC0201CCCCCCCCCCCC0201CCCCCCCC3A +:1080B000CCCC0201CCCCCCCCCCCC0201CCCCCCCC2A +:1080C000CCCC0201CCCCCCCC00000000FFFFFFFFE9 +:1080D000030303031342020250505020706080508B +:1080E0000200020006040604000E0000011600D67D +:1080F000002625A0002625A0002625A0002625A0D4 +:1081000000720000012300F3002625A0002625A010 +:10811000002625A0002625A00000FFFF000000008B +:108120000000FFFF000000000000FFFF0000000053 +:108130000000FFFF000000000000FFFF0000000043 +:108140000000FFFF000000000000FFFF0000000033 +:108150000000FFFF000000000000FFFF0000000023 +:108160000000FFFF000000000000FFFF0000000013 +:108170000000FFFF000000000000FFFF0000000003 +:108180000000FFFF000000000000FFFF00000000F3 +:108190000000FFFF000000000000FFFF00000000E3 +:1081A0000000FFFF000000000000FFFF00000000D3 +:1081B0000000FFFF000000000000FFFF00000000C3 +:1081C0000000FFFF000000000000FFFF00000000B3 +:1081D0000000FFFF000000000000FFFF00000000A3 +:1081E0000000FFFF000000000000FFFF0000000093 +:1081F0000000FFFF000000000000FFFF0000000083 +:108200000000FFFF000000000000FFFF0000000072 +:108210000000FFFF000000000000FFFF0000000062 +:108220000000FFFF000000000000FFFF0000000052 +:108230000000FFFF000000000000FFFF0000000042 +:108240000000FFFF000000000000FFFF0000000032 +:108250000000FFFF000000000000FFFF0000000022 +:108260000000FFFF000000000000FFFF0000000012 +:108270000000FFFF000000000000FFFF0000000002 +:108280000000FFFF000000000000FFFF00000000F2 +:108290000000FFFF000000000000FFFF00000000E2 +:1082A0000000FFFF000000000000FFFF00000000D2 +:1082B0000000FFFF000000000000FFFF00000000C2 +:1082C0000000FFFF000000000000FFFF00000000B2 +:1082D0000000FFFF000000000000FFFF00000000A2 +:1082E0000000FFFF000000000000FFFF0000000092 +:1082F0000000FFFF000000000000FFFF0000000082 +:108300000000FFFF000000000000FFFF0000000071 +:108310000000FFFF00000000FFFFFFF3318FFFFFB1 +:108320000C30C30CC30C30C3CF3CF300F3CF3CF391 +:108330000000CF3CCDCDCDCDFFFFFFF130EFFFFFF3 +:108340000C30C30CC30C30C3CF3CF300F3CF3CF371 +:108350000001CF3CCDCDCDCDFFFFFFF6305FFFFF5D +:108360000C30C30CC30C30C3CF3CF300F3CF3CF351 +:108370000002CF3CCDCDCDCDFFFFF4061CBFFFFFEB +:108380000C30C305C30C30C3CF300014F3CF3CF323 +:108390000004CF3CCDCDCDCDFFFFFFF2304FFFFF2E +:1083A0000C30C30CC30C30C3CF3CF300F3CF3CF311 +:1083B0000008CF3CCDCDCDCDFFFFFFFA302FFFFF22 +:1083C0000C30C30CC30C30C3CF3CF300F3CF3CF3F1 +:1083D0000010CF3CCDCDCDCDFFFFFFF731EFFFFF3C +:1083E0000C30C30CC30C30C3CF3CF300F3CF3CF3D1 +:1083F0000020CF3CCDCDCDCDFFFFFFF5302FFFFFCF +:108400000C30C30CC30C30C3CF3CF300F3CF3CF3B0 +:108410000040CF3CCDCDCDCDFFFFFFF3318FFFFF2F +:108420000C30C30CC30C30C3CF3CF300F3CF3CF390 +:108430000000CF3CCDCDCDCDFFFFFFF1310FFFFFD1 +:108440000C30C30CC30C30C3CF3CF300F3CF3CF370 +:108450000001CF3CCDCDCDCDFFFFFFF6305FFFFF5C +:108460000C30C30CC30C30C3CF3CF300F3CF3CF350 +:108470000002CF3CCDCDCDCDFFFFF4061CBFFFFFEA +:108480000C30C305C30C30C3CF300014F3CF3CF322 +:108490000004CF3CCDCDCDCDFFFFFFF2304FFFFF2D +:1084A0000C30C30CC30C30C3CF3CF300F3CF3CF310 +:1084B0000008CF3CCDCDCDCDFFFFFFFA302FFFFF21 +:1084C0000C30C30CC30C30C3CF3CF300F3CF3CF3F0 +:1084D0000010CF3CCDCDCDCDFFFFFFF730EFFFFF3C +:1084E0000C30C30CC30C30C3CF3CF300F3CF3CF3D0 +:1084F0000020CF3CCDCDCDCDFFFFFFF5304FFFFFAE +:108500000C30C30CC30C30C3CF3CF300F3CF3CF3AF +:108510000040CF3CCDCDCDCDFFFFFFFF30CFFFFFE3 +:108520000C30C30CC30C30C3CF3CF3CCF3CF3CF3C3 +:108530000000CF3CCDCDCDCDFFFFFFFF30CFFFFF03 +:108540000C30C30CC30C30C3CF3CF3CCF3CF3CF3A3 +:108550000001CF3CCDCDCDCDFFFFFFFF30CFFFFFE2 +:108560000C30C30CC30C30C3CF3CF3CCF3CF3CF383 +:108570000002CF3CCDCDCDCDFFFFFFFF30CFFFFFC1 +:108580000C30C30CC30C30C3CF3CF3CCF3CF3CF363 +:108590000004CF3CCDCDCDCDFFFFFFFF30CFFFFF9F +:1085A0000C30C30CC30C30C3CF3CF3CCF3CF3CF343 +:1085B0000008CF3CCDCDCDCDFFFFFFFF30CFFFFF7B +:1085C0000C30C30CC30C30C3CF3CF3CCF3CF3CF323 +:1085D0000010CF3CCDCDCDCDFFFFFFFF30CFFFFF53 +:1085E0000C30C30CC30C30C3CF3CF3CCF3CF3CF303 +:1085F0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF23 +:108600000C30C30CC30C30C3CF3CF3CCF3CF3CF3E2 +:108610000040CF3CCDCDCDCDFFFFFFF3320FFFFFAC +:108620000C30C30CC30C30C3CF3CF300F3CF3CF38E +:108630000000CF3CCDCDCDCDFFFFFFF1310FFFFFCF +:108640000C30C30CC30C30C3CF3CF300F3CF3CF36E +:108650000001CF3CCDCDCDCDFFFFFFF6305FFFFF5A +:108660000C30C30CC30C30C3CF3CF300F3CF3CF34E +:108670000002CF3CCDCDCDCDFFFFF4061CBFFFFFE8 +:108680000C30C305C30C30C3CF300014F3CF3CF320 +:108690000004CF3CCDCDCDCDFFFFFFF2304FFFFF2B +:1086A0000C30C30CC30C30C3CF3CF300F3CF3CF30E +:1086B0000008CF3CCDCDCDCDFFFFFF8A042FFFFFBB +:1086C0000C30C30CC30C30C3CF3CC000F3CF3CF321 +:1086D0000010CF3CCDCDCDCDFFFFFF9705CFFFFFE5 +:1086E0000C30C30CC30C30C3CF3CC000F3CF3CF301 +:1086F0000020CF3CCDCDCDCDFFFFFFF5310FFFFFEB +:108700000C30C30CC30C30C3CF3CF300F3CF3CF3AD +:108710000040CF3CCDCDCDCDFFFFFFF3320FFFFFAB +:108720000C30C30CC30C30C3CF3CF300F3CF3CF38D +:108730000000CF3CCDCDCDCDFFFFFFF1302FFFFFAF +:108740000C30C30CC30C30C3CF3CF300F3CF3CF36D +:108750000001CF3CCDCDCDCDFFFFFFF6305FFFFF59 +:108760000C30C30CC30C30C3CF3CF300F3CF3CF34D +:108770000002CF3CCDCDCDCDFFFFFF061CBFFFFFDC +:108780000C30C30CC30C30C3CF3CC014F3CF3CF34C +:108790000004CF3CCDCDCDCDFFFFFFF2304FFFFF2A +:1087A0000C30C30CC30C30C3CF3CF300F3CF3CF30D +:1087B0000008CF3CCDCDCDCDFFFFFFFA302FFFFF1E +:1087C0000C30C30CC30C30C3CF3CF300F3CF3CF3ED +:1087D0000010CF3CCDCDCDCDFFFFFFF731CFFFFF58 +:1087E0000C30C30CC30C30C3CF3CF300F3CF3CF3CD +:1087F0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF21 +:108800000C30C30CC30C30C3CF3CF3CCF3CF3CF3E0 +:108810000040CF3CCDCDCDCDFFFFFFFF30CFFFFFE0 +:108820000C30C30CC30C30C3CF3CF3CCF3CF3CF3C0 +:108830000000CF3CCDCDCDCDFFFFFFFF30CFFFFF00 +:108840000C30C30CC30C30C3CF3CF3CCF3CF3CF3A0 +:108850000001CF3CCDCDCDCDFFFFFFFF30CFFFFFDF +:108860000C30C30CC30C30C3CF3CF3CCF3CF3CF380 +:108870000002CF3CCDCDCDCDFFFFFFFF30CFFFFFBE +:108880000C30C30CC30C30C3CF3CF3CCF3CF3CF360 +:108890000004CF3CCDCDCDCDFFFFFFFF30CFFFFF9C +:1088A0000C30C30CC30C30C3CF3CF3CCF3CF3CF340 +:1088B0000008CF3CCDCDCDCDFFFFFFFF30CFFFFF78 +:1088C0000C30C30CC30C30C3CF3CF3CCF3CF3CF320 +:1088D0000010CF3CCDCDCDCDFFFFFFFF30CFFFFF50 +:1088E0000C30C30CC30C30C3CF3CF3CCF3CF3CF300 +:1088F0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF20 +:108900000C30C30CC30C30C3CF3CF3CCF3CF3CF3DF +:108910000040CF3CCDCDCDCDFFFFFFFF30CFFFFFDF +:108920000C30C30CC30C30C3CF3CF3CCF3CF3CF3BF +:108930000000CF3CCDCDCDCDFFFFFFFF30CFFFFFFF +:108940000C30C30CC30C30C3CF3CF3CCF3CF3CF39F +:108950000001CF3CCDCDCDCDFFFFFFFF30CFFFFFDE +:108960000C30C30CC30C30C3CF3CF3CCF3CF3CF37F +:108970000002CF3CCDCDCDCDFFFFFFFF30CFFFFFBD +:108980000C30C30CC30C30C3CF3CF3CCF3CF3CF35F +:108990000004CF3CCDCDCDCDFFFFFFFF30CFFFFF9B +:1089A0000C30C30CC30C30C3CF3CF3CCF3CF3CF33F +:1089B0000008CF3CCDCDCDCDFFFFFFFF30CFFFFF77 +:1089C0000C30C30CC30C30C3CF3CF3CCF3CF3CF31F +:1089D0000010CF3CCDCDCDCDFFFFFFFF30CFFFFF4F +:1089E0000C30C30CC30C30C3CF3CF3CCF3CF3CF3FF +:1089F0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF1F +:108A00000C30C30CC30C30C3CF3CF3CCF3CF3CF3DE +:108A10000040CF3CCDCDCDCDFFFFFFFF30CFFFFFDE +:108A20000C30C30CC30C30C3CF3CF3CCF3CF3CF3BE +:108A30000000CF3CCDCDCDCDFFFFFFFF30CFFFFFFE +:108A40000C30C30CC30C30C3CF3CF3CCF3CF3CF39E +:108A50000001CF3CCDCDCDCDFFFFFFFF30CFFFFFDD +:108A60000C30C30CC30C30C3CF3CF3CCF3CF3CF37E +:108A70000002CF3CCDCDCDCDFFFFFFFF30CFFFFFBC +:108A80000C30C30CC30C30C3CF3CF3CCF3CF3CF35E +:108A90000004CF3CCDCDCDCDFFFFFFFF30CFFFFF9A +:108AA0000C30C30CC30C30C3CF3CF3CCF3CF3CF33E +:108AB0000008CF3CCDCDCDCDFFFFFFFF30CFFFFF76 +:108AC0000C30C30CC30C30C3CF3CF3CCF3CF3CF31E +:108AD0000010CF3CCDCDCDCDFFFFFFFF30CFFFFF4E +:108AE0000C30C30CC30C30C3CF3CF3CCF3CF3CF3FE +:108AF0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF1E +:108B00000C30C30CC30C30C3CF3CF3CCF3CF3CF3DD +:108B10000040CF3CCDCDCDCD000C0000000700C003 +:108B200000028130000B8158000202100001023067 +:108B3000000F024000010330000C0000000800C0DC +:108B400000028140000B8168000202200001024007 +:108B500000070250000202C00010000000080100DF +:108B600000028180000B81A8000202600001828067 +:108B7000000E829800080380001000000001010030 +:108B80000002811000090138000201C8000101E85B +:108B9000000E01F8000002D8CCCCCCCCCCCCCCCC94 +:108BA000CCCCCCCCCCCCCCCC00002000CCCCCCCC15 +:108BB000CCCCCCCCCCCCCCCCCCCCCCCC0000200005 +:108BC000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCE5 +:108BD00004002000CCCCCCCCCCCCCCCCCCCCCCCCE1 +:108BE000CCCCCCCC4100200003030303034202029F +:108BF0005050502070608050131313131342121200 +:108C000050505020706080500301020000000000AE +:108C100000000000000000001F8B080000000000A2 +:108C2000000BFB51CFC0F0038A0F093230688A2055 +:108C3000F8C4E05C760686751C0C0C5BB849D3075B +:108C4000C32C0C0C0CDA4CE4E905E1FBBC0C0CAFBA +:108C50008098850F559C871342FF015AC0C7CAC030 +:108C6000A0C1865DFF3A35043B408581A11C88D9AF +:108C7000941818CC5411E2D2EA0C0C3380FC04A8EE +:108C8000D81D201DAB46BE9B47F1E0C1378D51F981 +:108C90005B0DA169012A7E0B4D7E1B54BE4A074223 +:108CA000DF36C66E6EB50E71F69FB546E5AFB4C63B +:108CB000AFFEAE3D2AFF209AFAAD503E00C5D55B0F +:108CC000A7D8030000000000000000000000000022 +:108CD0001F8B080000000000000BED7D7F7C14D589 +:108CE000B5F8999DD9D9D9CDEE6608096C20E02454 +:108CF000861AFB82DFE577A841878034B63CDF8A9D +:108D00005AD3D6F6BB506C551456BF3EE1F56933C5 +:108D1000F941122262049FDAD61F2B554BFB6C8956 +:108D2000942AAD3FDE024AF1F5C743AAD5D7A22F58 +:108D3000FE80AA455FC4D2D87E51DE3DE7DEC9CEB3 +:108D40004C76930DD01F7FBCF081E1CEDC1FE79EF7 +:108D500073EE39E79E73EE8DEA0BC2C7CE05388EEF +:108D60003FECD913028059D9A771F5BCAEBE99006A +:108D70004721D2D35D0AD0A68009AC6C1D88A41F00 +:108D800094007F6A14565E2D7F3CDE5D097067D1CA +:108D9000D7EEC3FA6B2C0502ECD9DD0C9039837D3C +:108DA0000F453743314011A4B6E277F6937890F53A +:108DB00037109C9C866876FC32F0D1B80015FAA179 +:108DC00022AA07C765F6CF81E47C18072083FDB38C +:108DD000067A593FCAF3721AC795E5C5FA8B55D979 +:108DE0007EBC4F595721A389FEF01FF9B2E26438C7 +:108DF0007FFD35072AB73E5D93AD7F06444A0FFDE0 +:108E00001DFB8F020AC123AF07C4C3D130A4E5CA3A +:108E1000FCFD0C341B5B9FF6231EBF509C989ABF31 +:108E20009E8DA7AE668D9E1DCD3A6402000C64B384 +:108E3000B7963DC3606EAE1DDA6E0148842FCDB08B +:108E4000089EF6B02F5D5489502701187EFD881FBB +:108E500009DF2FD1CC1CEDED279432FCD8F36578D7 +:108E60000C02EF0FD8FC1E64FD0571FC1CF8BA085B +:108E7000C72F63DFAB878E6FCD3CF1F1436702EC08 +:108E80000B23BE4D84017C7A0AE282DE9F9486E940 +:108E900047D05931783F23E1BDA8C6971D97FD0DF6 +:108EA0001A21179F0462256EBEF1F225E2A90CE992 +:108EB0006548AF4FC9F6AB22DD72E0EB4A81AFFEE9 +:108EC000F989A604C3C7DA66B05E73B4936360A67B +:108ED00073E069B568678FA794B27A39FA076811A9 +:108EE000EBC772D52F14BE9B4E10BE9BFF42F0DD28 +:108EF00026F89D49287AF6CF4F129CDEFE72AD2FE0 +:108F0000B68807CB21256DF990BF4B21FE207BF859 +:108F100035BECEECEFDF073FF5B303250E1BA74DA3 +:108F2000C0D73F9FCBBFB5D3D4F46689E4910BCEB5 +:108F300087517EB1769224F0A1F502F25FD1070A43 +:108F4000C05884CF844404605D7583369CFC015D09 +:108F5000F9539FCD775543F9EEE36C18842B14CE6B +:108F60008DA7EF0FCAD1CBACD7583F5A90BD3F1D4C +:108F7000FB2D8D55CC069C1DFDF8C577907CF271BC +:108F80005CB7C758BDD942CECAD43FC911A8009218 +:108F9000F7B2A84FE3B0FA01362D733A7BE2FB1A21 +:108FA000318E34B45F6FBB0128E1F811F0D8725DE7 +:108FB0008627A89F41789404E1CBFBDECFDEEBE16E +:108FC000937F7FB265BF9167BC1E89F869A4F6AF35 +:108FD000087E19C29F79E8BA5FAC33057A4D383DF7 +:108FE000CB47367F9D281F9D349FB0E1495FE4E168 +:108FF000130B52B46E5835AB7BDAE8F925079F6442 +:109000009CF5174B63F83C9438F10B834721BED590 +:10901000393C65D34BA93F09D7F819D88328231EBB +:10902000D87C97D9ED214EEB3584768EA33D9B1CE1 +:10903000C12BC99290FBBCDE0D629DCF6BA8E0F006 +:1090400083E8DF032FEB4F73F627438587CF39DCA7 +:109050001B242EDF58FD0CE1D33BBE2211BC322471 +:109060002C1F6BB7598CEF955FF673BBE86FBD048F +:109070004DBD61BE9E9638F4618324E484C6D799C1 +:10908000573EF991AF669C385F152AD7174BB9F553 +:109090000EB38A621746F2EB9D629FAD0F323141EB +:1090A000B751D1FD74A9C445F742E15D7682F04E17 +:1090B0001C0A6F417C76A6E41B959EBCE104E10B83 +:1090C0007AE03B557C3D43F059A1F0DBEB60B4F016 +:1090D000CB43F15BD03A9A3B4AF8369F207ECB7C5B +:1090E000B69D24E0CBB36EE7097A5BC0F9436176A5 +:1090F00038EE730A85EFD191E103F804FB6BBD6A8A +:10910000990AD96B0013009E6E79D5B2942C7C26F7 +:1091100070B93EDAF1F78C4C3F31FE5B96599D1DDC +:10912000FFF996B75CE32B8C7F90D90A1DF7854237 +:10913000E70DEFB9E6FDBAF49E6BDC13C5FBC18207 +:10914000C7FFA36BDEEF4B7F74CF3BCCE67D7AE1AC +:10915000E3FEFE04F9B152AC97064977E9817CF64B +:10916000FB0C41D7BBEDFA36BC79EA9F29E06A2FA8 +:10917000B0FE44D1FFE70AACDF2BFAEFC5FA652356 +:10918000D73F5DD44F15585FF2F175984F7FCE975A +:109190006CFC816BFFD1A6713F88D9A640F09CA1E1 +:1091A0007E13AB21F5ED3E467BAB35A0B79592DF44 +:1091B00084FC226B0012E837F92624EB7CAC1F6399 +:1091C000C74DF761BD238AA677EBC01724FB1E3C71 +:1091D00010D9DC5D991D6FB59C6C929097DAA2FA5C +:1091E00083E45F493549EC59668575F4DB0C5425F9 +:1091F0005A9696E23C0CDD62FDFCFA8A8B76627927 +:109200009326E9322BFFCB39736FFB0C6B35F0E102 +:10921000CE974EC37AD3C655B592BC3425C44F6998 +:109220005C35E5287B5E7C71561FE03F8B1D6566D3 +:10923000077CB6E9122EFFC5F7CF27DDE54B1A2FC5 +:1092400071B5BF34E1FE9E9D0FF07DC7B9DCFF30E4 +:109250005095FA2F0ED7C72A2DEE5FA0F9EA565483 +:10926000EF66F35CFFE1B5545EDF52ABB7B2F2E7F5 +:10927000AEF4B72C65CFB004BACC9652715CA5F9A8 +:10928000029BAF5AC7768FE73CDB35DBC8BFFF2AAE +:10929000363DF38C5F9C8593CDB3E9EADC70ABFA85 +:1092A000FB13DE60F6D2C0CEA089F084F7CAE9A035 +:1092B0004474DD3909E9621527397D40AA66CF2358 +:1092C0008D3AA07FA4A13169C8ACBC31A6C5030604 +:1092D000DAC9190DF11E411ACC65EFE3BE20DA633D +:1092E000AAFE07EA5F17DF7BE255E3D13FF2E3E630 +:1092F000351315B6DE77345BF47CB4B98B9EDB9BFB +:109300007B262ACC88DFD27C173DEDF9A12431ECF5 +:10931000F9C9B8AF365B91DF06FCCC34423CCEF7DE +:10932000D1FE7603CA113FCAE1745B14DFD7C1B422 +:109330006E40B9C4E5CBC6F8B6DDF87E633D4C435C +:10934000926D3437B745D93CAE2B87E9D8F7CE9725 +:109350001FE3DF2B607A8095773536905CED89FBD3 +:10936000D2814A82FF7CE4E79E461F3093078AEB56 +:10937000185C0EBC0662EEF2AE4626B066123ED215 +:1093800001293B7F852D33C4C746B32AE8DC57CF7C +:10939000DAE76E7F66DA5DDE88ED87F14BCDED733F +:1093A000D79FF392BBCC24DB2B837CC0F1F8AF3E7C +:1093B000260F76BF3CDE67E1BC4D3E4FF6E4FEC2B1 +:1093C000982F8DC6E716813F1BBF03112E5F3636DF +:1093D000733F603E78367EEAAAD8707E03B5B1232B +:1093E00081FE54B5B1270167E1332D9EBD09A79FCA +:1093F000D57EBE88C68FC35FD211DB58B2B4360BA0 +:109400008FB7FE785925793750C6BF77C45ED3979A +:10941000D63AFB93BCDFB5CBC3CEEFDCAF32506E98 +:109420007F3FA22D0DE7683F897DCF4197A532FF91 +:10943000FEF4CB81863B901F057E77BFFC13AD1AEF +:10944000F1FDBC0CC8671BF73590BC453E4379B1B4 +:109450008BF1455F2DD27FFD2BCE755B5CE72E3304 +:10946000BEE2FCC5FAC5A17E86F4601DFEBBF0CB52 +:10947000EE157ED93DCD317A3EDD6CD07357730D3C +:109480007DCF34C7A9FC54731D959F6836A9FCE3B2 +:10949000E6462AEF684E50F9D1E6267A6E6F4ED234 +:1094A000734BF315F464FC4BFCBCA13925FCC06B79 +:1094B0005CFCF0F7F1808BFF3E5DE32E9F6F9C918B +:1094C0005DD7ECEF2763EEF279FA275DE5059ABBED +:1094D0003C1FBEE2EAEFDC0FBEEC2ACFEBEF70D50B +:1094E0003FFB4D77796EDF439EF5E22ECFDAB7C7AB +:1094F000B31EDDE5E2BA43AEFE023177F97E1432E7 +:109500005C4E117F74C45A4B72F2CFE0F78DA12FDD +:10951000B9BECBD47E64FE59D65589FC93F6C52DD1 +:10952000943B26E7275BEE78F9C4A6DB48FC65C3CD +:10953000F197E6ABFFE5A7E1F9A9607EA85772F2C3 +:109540008397EE5EFE18226704BFFC2F1FFC6DF0B0 +:1095500001CC64C42ECFAF5773D877649F061240F6 +:10956000F69D1FED34477B75722A69E6D09F57F947 +:10957000E66F95593F8152E8C0786840C9E3E795A6 +:10958000F93E25A0F1EFC16A93ECB26230A6CB633D +:1095900000AE796C5EF932F6FEE7421F765C089603 +:1095A000C4FA1B37414DE23EA6B8DABDDF7B46E682 +:1095B000FB18FBB9E9879126FC0EA5334798378F36 +:1095C000D7C8136737FDC660CF0B666F59CBDE86F1 +:1095D000AA9319F2019596927D9A0C19D4AF5997D6 +:1095E000B67CA518478338DA8972D884241B67AE05 +:1095F000CFFC05CE9BD947FF21CFCADA3D9BC4F3F0 +:1096000047621D5EE4337F29EA3D3F5C3D7BDC1110 +:10961000E905494BE2FEA9F8830C447F69DC653F0C +:10962000D9F353948499C8616FFC4EE04BD2E34D5B +:10963000DC0FA202CA877CF50FCAB6FFC972ED071C +:109640008BA13F23231C311E6F82631719174E1DF8 +:109650000A87AA2492380EC6AB37B371DAC77CC624 +:10966000483AC6F948E67E2A2966123CAACEE1515C +:1096700095B899C8C14703021EBB1F3B6E26C5FAA9 +:10968000A12F9C856F6D30D184FB256B8C4A786A45 +:109690008FB8EDAF190AEFA75A3CDBFDB9ED438057 +:1096A00056BE1F1E57A761FF6D750D1ADAD78C1DA8 +:1096B00068BFD21E5E523C9CBDBD5ED8BFDD280F88 +:1096C00003180FD785BC8AD1B33DBCAD11D7C1D12A +:1096D0005A8687CAFCFD44E2EEB86E514DC813C7E6 +:1096E0004D139C41A3C413EF9DE06AE71FA7F8EC5C +:1096F000B8364823C3DF21E0B7EB752A294DCF895F +:10970000273EBE5D0EC4DCF0FEF9F0C7DB17F97B27 +:10971000F55C709D2ABCE58BC3DA4F75AC9A4A7331 +:109720007F4ACCB90E3E2BF84B1DABA5483E69F9DC +:10973000BE8778FB7082FC5B5A38614055361EABA1 +:10974000E17A70E0E95AD1EED78A4FACCB540CFDE8 +:109750005C92916A427ED22AD83A9286B6B39F49E9 +:10976000D1BEF3C3FFF712AD93328DD68964B075C5 +:1097700094631C4931AF56D8F31DD9BC46C1F8CC0F +:10978000477232D77A5921E0D116270CAD8A427838 +:109790003CDFC303C73A85EB834336FC568AFC564D +:1097A00085C2BFA640F8ED7118FCED02FEB5C3C13D +:1097B000DF26E02901A3857C990697B300171ACE0E +:1097C000BC8B37C4F825424E314C11DDECEFFF2540 +:1097D000FA29743E1B059C23CDE78D2C3DEEC579FF +:1097E000B0F9DC87F3CA379F7B041C6F285CCF6815 +:1097F000898411AB22559F93AF9E1070F42B228E5B +:10980000665D3B2ABEFAD702E7F144962E8F09BA6D +:10981000EC186E1E8F8A79F4C830F70DF4339E2E43 +:10982000F40E2C71D1E5A8C04F4FC0A6CB752EBA4F +:10983000FC4ECCABD0F93C53209F1DCDD2E5393145 +:109840009FFDC3CDC751FF4551FF25519FFCE74701 +:10985000952B5AAD5AFC9E38A0CCCA8EC7EABDECF7 +:10986000AC776DFB2CBBDEABC80F5223D783ACDECD +:109870006BCE7A605DD08AF6DB5A8C897E02E081FD +:10988000F6AF3688766F52BBC583FDBF25D607B5C8 +:109890005BD73EBFD50A53BD77F07DCB828FEC7A84 +:1098A000EFBAE15D61C37184E04D0CC2F1BEB3DE7D +:1098B00013CAE7A9BF217947B19282EC1F7F699251 +:1098C000F2F74A20D283FEC50E2545FE640C36A071 +:1098D0001F7275204EA92A23F9A3CB2EE6ED7445FD +:1098E000237F6A005270177BBFA154A1F8C862257C +:1098F00019F1A31D21252D0AAE827E590BF63FD604 +:10990000A0FC2F1B9EDB8ABED845FD3078B0DF3B24 +:109910008BA23B91AF364E520DE4AB9D936E20BFB0 +:10992000F96D2D3C7FF0B6F355DA676D7A3942FA5E +:1099300077AD12FF2CD6B74CD5403FFAEAD0472F6F +:109940002D67E5BE96625D3A87E641705B3E48B49E +:10995000CD74E42332B80371CAA7233FDC6D8D3C7C +:10996000AEC37ECAB1FDEA0546BCDB40F1C5E418D2 +:10997000FBDE59A792FD7A5B45D57C1C6F539D4653 +:10998000F6C6A6C5552DE4C7AB0B91BFB2246C48F3 +:10999000E8678FCE519901CECAA5460BDA9B91D9C3 +:1099A0002140BF5349051F2F7206901FCA0F3D89E2 +:1099B0006AF68C76A990198BFD2DC97C09ED99BAB0 +:1099C00000F9E1D9C4F6D78EA39437FE23FF0C101B +:1099D0001EFF441910EF367DA33D83ED87CD638CC8 +:1099E000A60BAC9729AC5EA44B81CC8C02EAF51493 +:1099F000582F5D60BD0CAF17800B87CDE78338CF44 +:109A000023D4D81F9EC7E8C82BACE4F6BBD36EF1B5 +:109A10007BBE8F362FF42ABFC80B9D0373785EE898 +:109A2000F0EDED7CD091E60BE0CBC2298F5C7F6D31 +:109A3000F3F07E63FFB81B62987FD959F655F1BCED +:109A4000913FCBC5FBF2353194779DE5E27BF98DF3 +:109A50004DB9F6AF77FAB91CAE81C4B0742811F0D5 +:109A60001F62B0637E4F8DC2EA47F2D7574B7DC36A +:109A7000E6596A8AD540EB76B18FD66D008501AE86 +:109A80009B0ABE8EFD904A54F37855B4DCB17EFC3F +:109A9000F57B68FDFCA25C06A98EE813473C7AF9C9 +:109AA000C4CB170170942B4F9E4FB6FE99F8C4DFBC +:109AB0002517B47EFC3D05D64B17582F53583DB59E +:109AC0004B2A48AEA83D05D64B17582FC3EBAD9D8A +:109AD000AB727D0E7F68C578BFFF139AABBCF613DF +:109AE00021F7F7B3C3AE72C72C777B75B6BB7DC7C2 +:109AF0006C777B750E6F1FEC800518CF2F749D1C43 +:109B00003CC17552A30D5F3F5237C2BAD2F420B6A2 +:109B10002F510CC89492BE4A0BBD95331E7E9ACA33 +:109B2000D77F959FC7CF6F53F420EE23FFD6E72949 +:109B3000A93C9FC09EEF48F0DAF2F7B7B2B0B7F297 +:109B4000E47D438C9F7FF043288E768EB1506B78F6 +:109B500085E1D1FF2CCF7BF7F6FB8A9A9CA63AF6DB +:109B6000C5CC3E83A4C30F737E99C2F36D181DD07C +:109B70001E5221D158C9FA6BABF0913DA28447D057 +:109B80001B150EB995232F2FEB970213CF53D02718 +:109B90000360FE9B7CDC501C08EE08F4D166BA180A +:109BA00053E54E07180386C493BEE212CF13ACD719 +:109BB000519E95064F75BF9751BF92791B1C2F1A66 +:109BC00045BF4A1FE5CB9CF27E478037087753BFDD +:109BD0006C97547A7C6CB65F7F2C452F314F56764C +:109BE000E4CBE1B908CA37F1C53394DF30214AFB31 +:109BF000B2B5A5D7B9F2C1FF59AD72F98754BDE32B +:109C00005A09E3BA15579B7DC3F079331357E4F72C +:109C1000AC586EF6D5E4AF3798A78FF99E39D64188 +:109C2000879A4CA3FD6E4D0EF3FDBC92227F63A775 +:109C300054321DF32DEC7A4A0593B40CAEC84CD3C4 +:109C4000C2FD5EE7585F1CED5405D6EF93CE62ED82 +:109C5000E4C571A7FFD2FB542A94B79DF3B95D65A3 +:109C60007A12E1147AB26D047E1FD1EE51E3C95C21 +:109C70007ED16FAB7C5FEB0FE5FEDE176A78409D0F +:109C800035146F8F217E717F3B06BAA4FFC3D9873D +:109C9000F2A52AF6BC8478585BB62836DC7CD90657 +:109CA000EAF0205D18897F16321F4179300C1C3F85 +:109CB000CC0507840BF37FEB0BE3C48783F65229B3 +:109CC00088FD98199518DF870457DE32737306CF25 +:109CD00043F897864DA49F6C6E01F457DB76936C26 +:109CE000865EF5113DEBB9FD54C3ED2193FDC179BD +:109CF00044EB87B7AB654FF939D56D0FB535EF003C +:109D0000679E9BF75C85FD4C871A5ECC8D8FC2F6F3 +:109D1000C3B7337EC13CFB8DCD1A22057A9A752AD2 +:109D20006F688E51797DB341CFF6E61A7ADE8C4D9D +:109D3000E7E2F9A7545725C35B57EC81D8E5ACCAD5 +:109D4000ED283B288FEFDE05682F770F96D93690E8 +:109D5000C1DD3D09785E9F7AEB02DCE7770741F8C9 +:109D600015DA16A05D9D2DDFD1361FCBC2CF10EACC +:109D7000BC6F01EEF76F17F90FA098DA250EBD77CB +:109D80005AC04FFC477B576A6FB5617F414594E1EC +:109D90009105EE3298084F50E3E505816DD43F8977 +:109DA0000036DEA7033FE0E34D11F96DB54B46C029 +:109DB00023F7EF5BAAC1FD5DB525143F52E3717433 +:109DC000BFC2ED6304DC05F6034A92EB3B718E2FB4 +:109DD000FFBA1941AF093846A23F4307F9D1EDF365 +:109DE00069CA0BB9F5F4A91EF776FFE8F0A2D6F51B +:109DF0005B7886ED09353927C0DA47CCDE4C252B58 +:109E00004717672C5ABE058E3B3660E7392669FD39 +:109E1000DB7856746E77ACF0D0D15FCAE3754171D0 +:109E2000FEA4507893AA1847F4030F37940F67AF36 +:109E300095257C68840DCA8BB18D21E19CE1E531CB +:109E40006689AB5C5C37C1553F12AF727DF7EB1F83 +:109E5000777D3F513A5DE299C7A784DD6897CFF5DA +:109E6000CEB3C07E0F1627560570DD34404D8AE113 +:109E7000F5CE2F3C44F80F0DAED385ED6605E58396 +:109E80008B753D8F9775FB7B5DBB59CFCA86FD7D7A +:109E9000062F9BF6F738AF6FD9DFA7F2EF28F759F7 +:109EA000F96B9D67B45BF81D5AC96F0B152958E211 +:109EB000A0CFD8F10DAD08DFF8CBD2318BBDEFFECE +:109EC00050E6F2007A62CE7A776ADC0FFDCC943BE2 +:109ED00062E8AF5C77E64331207927E58C07FE3CEA +:109EE000C0F3C5CA42899E00AD77B3BF98F1E1A126 +:109EF000876483EB21E535D4873E8BE7E3AB10DF46 +:109F000067A25D54C3FDD521F19DE85899AD3F4846 +:109F1000574FF9EF34AED77F87491B0CCEEF159B17 +:109F2000F7D0B890961AD97AAFB0A01FCF1F81B0E2 +:109F3000FB26F2A6509A48939F6F12C3A7CCBE4F40 +:109F4000BEB8BFC5CF706D5CA6FB7089542D8FFB6A +:109F500048C00DDA9163A5E3ECF93DA417CAE39B71 +:109F60005280FA7BED990F35215E02997F0283E1E1 +:109F7000ED1F27A5C040FF6F80C315B8AC07483E52 +:109F800057F7109EBDF85A3788F7B40BEF3F0970AA +:109F90007F7E2CC9DB0DD65358BDA943EB75077BDB +:109FA000E6AB68BF4DE178F48EF35E4012E776DDF4 +:109FB00070D8FD7AEBDF1210716D2D4DF18D67CEEB +:109FC000BC21867EEDCE298CFEB5F9E97F4B80E77A +:109FD0005B19C76E22B9DB3D6923C533D7556F26A0 +:109FE0007BF228B323F0FC747765EEF69DCD3C3F01 +:109FF000E65CB8BBB18AD1A7F37999FCB4DE7ADF0D +:10A000000954B9E28D5A857B3FC8F8AF0FE5E8489F +:10A01000FC27471EE0EB72947C8766213FCF50D629 +:10A020008EF6805F94EF0E1C6F13FA9FE47FF9F2B7 +:10A030001E70E64BBE2FF82213E0722658C1F9A31A +:10A04000DB6F494EFAC5D8FBF98E76F9E8968F1F7B +:10A050001E17EBE17D25DE44CA5F49E9B9E4B3127E +:10A06000FBF42F173ACE7BB52B694D47F86B364A78 +:10A070004EBBF61B6632A439F627A1D805BF5C8813 +:10A08000FB1F259E739FFE29D38C6A6CFC9B9B61F2 +:10A0900046359E4B50AC00D6BB59C934D2BEA2DA6D +:10A0A00047FEF27515D7EDC53C2BABD617C76A6DC9 +:10A0B00015BB1AAB0CE4976D9467FAA6BE2486FD17 +:10A0C0000462EA8CEAB194DF9DC079876B59BF0EB8 +:10A0D0007ADBE3DE2DF8F65BBA3959E3F2E034EDD2 +:10A0E0002F200FDE87788C1B590CCF39F65743F1A0 +:10A0F000CCF3043A2B86E0798EE6E0EB00E27906B9 +:10A10000C9FB9CFE0B86E7B35D780686E7A9593C40 +:10A110007757703C77D66CEEAA72E2B966D7DE4A02 +:10A1200003C7E7787E48E3E773438867079C5E3C94 +:10A1300087255BFF7CAC1DF9D6CBF70CEF7F8FF04A +:10A14000D8EF3F0AFC82ECE1B1E313176AE43F4920 +:10A15000D1FEE94E29AF5EBA442B402F758A757443 +:10A16000A7C03FEBFF0BD47FA9E8DFD6B7421FFEA5 +:10A1700083F66F0B501FB27ACBA89E9EA27DF06033 +:10A180003D0B86D5A3ACDD95C447614FFF268C4AB5 +:10A190001FB37EAEA37E34CFF8069C949E67FDDE8F +:10A1A00044FD2A9E7E4FB13DC1C6E926FC81070FC2 +:10A1B0007F663B2696F4F083D2E3927B363F942F62 +:10A1C00077D7CBAFD77AB85E1B6AD710DFFEBC73E8 +:10A1D000CF6EDC27BDA99BDF46BC8E761DD876608E +:10A1E0005928B94DE376209D83B0BE51946E636DBE +:10A1F00095E33D511E7F77EBA3F1B63D54CDF5407D +:10A2000070947A699FB0D73AC6301955CC9EFE44F7 +:10A21000532E3FC3339A9DB7E6B69B7F8373243F8B +:10A220005182FC6BEDB1CFECE863B4331B7B20971C +:10A230009C4F86923FC7F9A9BA65927A15FE917C28 +:10A24000FD9626AC9D7B6792DCEDC7BC461072186C +:10A250004D6BF4C74519DE0E69E4C288A37FADECEF +:10A26000626B3ECAB10AC62F587F5CD33E29992B38 +:10A270003E6EEF7F10881CFB97719F9B9DA47CB85E +:10A28000C53347D8DFB4D8F6EB6F715E87D49E0B29 +:10A29000A638F06ED3E90E2971E179284FE7713ABB +:10A2A000158F924E03824EB098E7A19E7BEC5C8D99 +:10A2B000FC8B115F02FDF0417F8F5EE2E0A3713EF7 +:10A2C00048F68E02FE7AE8DF7D1CF77F611FED778E +:10A2D000BBC3CBBE83F7EF58BA1A9F6264C7ED6663 +:10A2E000FABEC4A17FBCFEAAC17DF4E2C2F265A79A +:10A2F000587328DE9FBD3FC89D7FC018AB06F3860C +:10A3000056CBDC7F7E67D1D7280F618D15D003A592 +:10A31000A4C7C8FE5B27F2D93A453EDB5A91CFE687 +:10A32000B7566FC5FA9B0012E8976C9997A2787F91 +:10A3300054D1F4D638C2919A837A225A6AAFCF1F89 +:10A340002FC4F53958B6BED1DEC0E61B8DD9E58DD8 +:10A3500064BFB5B77079F3D9E00B0BAD7A64C53E35 +:10A36000A2C7A6BA25C5308C3F325CEBCE9F0B55F9 +:10A37000875C65ADA2C455564B270C1BB7F819FA7C +:10A380008966E17CFA208E70E6C9179E12E476B6E3 +:10A390002C4FEBCF60BEC1D96A7CB381E7A8DD79D1 +:10A3A0009CED416E0F3E8A0E218AE30ABEA8E3713E +:10A3B000D5A2B955BD180782319C2F304FD0C90F97 +:10A3C000F9F8E2AF8D1F5FD1E118E65DDCD21A0526 +:10A3D000CC73B965EEAFE21903E56A5F0CF333DACB +:10A3E00098246965DF37CCFD9591CB9F7C404B2E3F +:10A3F0000F22FEC209B2BF223393F4FC6BCF6B2451 +:10A400007ADE19E47A6E8AA0A782F49C99A5E7BA4D +:10A410003A46CF99D975BE4EE9D10AA1E7F9387EFF +:10A4200019CAA1FFA67DDBCD75BE46944306F45242 +:10A43000FEED865A9F0FFBFF6BE1C5862B3C97C94B +:10A4400047A25326817A61435CF1A11CF99BE3C3C7 +:10A450008FFAE87D017CF8C35C7CB85CD0432EDACF +:10A46000D7942BEF6E4A5072E1653DD28BE3A591F4 +:10A47000E3C5F757C1CBA0BED0922B916FAE88A990 +:10A48000B4EF564ABA3A285EC4F41EC61B56C8A694 +:10A4900081F126F8969FDFC7847ADBA15FFE180C56 +:10A4A00072FB445EBF88E2186C6AB82F63E58F0DBB +:10A4B0001B0F4DFBFB9DF79478F3325E0BBAE31054 +:10A4C000472A961423BDF2F5F776F35E1DCFD5DA51 +:10A4D000F919DEEF2B6448E53AB72885346167F651 +:10A4E000AA84871B99AE9D86F8F8D8423C9FD9591B +:10A4F000D13A8EEC1871AE61C5966775C501E70A51 +:10A5000085A9BFE943E763E37705AAC91247FBF4CE +:10A510005E577B6FBBC1FE447B66B7F9430C3E536D +:10A5200049EDC578B37D7E43DD323F436A330FDCAE +:10A530008C8E270577A1E7388E3CD0D681FB6DB491 +:10A54000BF3EC1F8E4B78FC8F156F6F58ABBCF58C5 +:10A5500088E75A0F01E7179B3E6F3DD0362E175FF5 +:10A56000E4A3CF79A12087E714F3D759210F7FF512 +:10A570005E549C8153CF5F8BF3F197C0CFE15E8E29 +:10A580000FB86B6C4E3AE59BCF209DEC7682CFBC2A +:10A59000EDF3B5637C95E07C95899E5D085F097855 +:10A5A0006DFA9D2CBC23F155608D6CE079AE4A2587 +:10A5B0004172B3B3F43A4BDCEB48F99E72CFB48CE2 +:10A5C000B8D74AE4B54306ED8940A949767448DC1A +:10A5D000CFA355BBE5A612739F9B8835253276BF66 +:10A5E000E8BF0CAC5169DCC1F8711832C12896790A +:10A5F0009C14C51FEE2B02F04DF27BB27639FD9E06 +:10A60000F65311F96A98CB4BF7B2C1E747C86F719F +:10A610008F13BB78F8FC1A6F7D082BC62107DEF379 +:10A62000B753E090639FB341DC2B6AE3DFDCB29465 +:10A63000F2CA83E08BD3FE20D661E1BEAF43ACE724 +:10A640004E7CCEC573BCD375DAAF55F0788B257DC3 +:10A6500099FC0CF6B9337B3CFBBC995D6F24FAAFD7 +:10A66000C6F594637DEF0A717D3AF0B5D47FE33E81 +:10A67000C4FA1318780FC5E3CD1F509CFA9CCC5B2D +:10A6800032FAF79F098DA37ECEE9EF931738D6E50E +:10A6900039E21C0740AF9CEB9C97DF0AEC427E78C6 +:10A6A000EA30DF8F3D75F808D9E14FFDDE9746BEF1 +:10A6B0007BEA83E1F31E1E17FB22BBDEE3BFE7F656 +:10A6C000D9E34A6F512EFB2E3B7E9AEF070FBBF961 +:10A6D00015945E19F965E0A67D32FA071E6FD6A4BF +:10A6E000D799FC9927E679CEE13E19F74D23CD6B3A +:10A6F000AB87BEF63CB7D6737B746BFD9110FAFF47 +:10A70000B73EC1E77BB49E9F8FCD07EFAE669EDF5D +:10A71000B1F589DCF86898C7F7C70D7EA334A75D4B +:10A72000EB3967B54093DDE7BB4E317CBBEBB9DD60 +:10A73000B55B89874F049EBCEBBBAEA711DD08510A +:10A740004836CE9708BDFB5D7E92035F6FF932E617 +:10A750006B2C0D9B12EE65A12FF3249B5789A92525 +:10A76000F0DE98E2FA1E6932E677C4781EF937AF58 +:10A770007E2DF3322BDFDC5444655D379E5B84F81D +:10A7800028D5C99F72337A5C48407F732DE627D065 +:10A790007A64E5C0CD3DE7A13F4B012E2F98C56BF4 +:10A7A00028E3E85E3F72D2E4931BEC473A1EC8B63A +:10A7B000CB3B4F4FDE6D00960C2FC796F3FA16FB7E +:10A7C0008372A8C49367A22F74E7A5443DFD4F454B +:10A7D0005BB5AC80BCF2931C670C6CD30CDC67D708 +:10A7E000FAF434D607630CE60D861B9981C4E83968 +:10A7F000460709CDE591F0BE0EA091FBBF33E03CCA +:10A80000A7D350C4E5D584AB6E97709F7134CEB892 +:10A81000621A96DFCC997FD52EE4C76059DF45F2E6 +:10A82000B4037AF7525C20E9233BFCE6DAD631CE5A +:10A83000F64B8B24DB1F28E80F86323B4B7F363FDD +:10A840003378D65F8EFEB1E56EBC8F962ED714712D +:10A85000793512FD4F761C9B6E43D7478BA0DB03E7 +:10A860001417EDAE195EEE0FA5DB36D277E1DADC18 +:10A87000F9BAD715492E796C3F3548419CF1892C9E +:10A88000EE6796C7CF6EBA7F18F9233BEF67866CE9 +:10A890003FE38C1E13E356E3A1C7C473DF8CA7E329 +:10A8A0001940FE3601ED24661E111FC99EFDDC46CF +:10A8B000C14741789EDAB35560E9A45752A03BF2F4 +:10A8C00054CE93C371F45FACD3C3742F12CA4F9E9E +:10A8D000BFC3F3FC8B39480CBFFD80F22D542E838F +:10A8E000857EBF7A01AFC4F80EF3FB0FBC7500F78D +:10A8F0002BE1996E3A29078A28AF2DE43D2772E0B3 +:10A900009A6B687FE3A1E368F3FEBF5F24ECFF224C +:10A910000893DD24DAE7CBDFB3ED7E1BBFC6B108B9 +:10A92000E5ED741C90081F659313F7E3FE0C7E257C +:10A9300003CFCB0413F3F656FF74167D1F1A574846 +:10A9400054225DDE3A50A4B75616922F9948B6B0FD +:10A95000FAC68140BCD520D5E2D3908E7D12D1516C +:10A960001AA751BED6EA7FF7DF1F18265FCB8E3FAE +:10A970000E96158BE29B5DC674CD294FCA42C95F06 +:10A980001639E3F622AEEBF5AF07C3EDB16760F41D +:10A99000F18FD2F120E2F29F5F84F64B17AE019E59 +:10A9A0001747797A5DE5BCFC46D1944518DFE98A02 +:10A9B000F07271F8C8792D246713E4FF5BC3180E99 +:10A9C000F1087BFDE21E4963FC85C3C80BEFFCD791 +:10A9D0002BFB284FFE9EF0FEF3CF40FAC47DE48FA0 +:10A9E000BBE7FA6DAEFB93DED41BDE2FA2F5AAB750 +:10A9F000637C7A62D2CED774C74526A0D660F39B1B +:10AA0000C408E3677838ED626845B6A9BCACB71CEA +:10AA1000F7C96B4BB78DE1E7FD17EA87C86E972939 +:10AA20003E9D0F5EAF9D9E6FBE76BCDDDBFEAE0829 +:10AA3000BF47D51B17F3FA831E44FC9651FE2C60CA +:10AA4000FE6CA7BF2F673CEA8D22EED76CAF5894FF +:10AA5000B81CE7A598730F327CDC5B1AA57D90FFCC +:10AA6000A2DA4B7D0E7BC3CE6753C47ECE5F9A22A3 +:10AA7000B9A86866D719182F7A5EC61505153D3B2B +:10AA800025B4E7EDFB2010AD174FE5F3C579058040 +:10AA9000DBC5785EE1B863DE1073F8C1509E88FDB7 +:10AAA000DB29A0F7B4F0ACA1F49DDFC5F3D0635768 +:10AAB000F0F34D1395DCF41E7F99EEE3F1AF534BA9 +:10AAC000E77CEDF3C53DEF8AA8B47EA6E8ABF7E2DC +:10AAD0003D771D567112E33103FE5417CAAB0DFFCB +:10AAE000E883CD34FFD1E937454FD03D7A15297D34 +:10AAF0003A2EEF7CEDEE48ED0A129E2D9ECFE0FD42 +:10AB00007E7998EB9B9E94EF36FC6E3E9DDAE9C70A +:10AB10007D678CEFABED7D783294BC3CECB0CF75AB +:10AB2000D3223E9A92BC94E4C0405961F72F0CE2C4 +:10AB30002B4F1EF31D11AE97A718AB79BF9386F765 +:10AB4000CBDA78F9A04B16BF1721134438FC8C914F +:10AB500013B82E6EE472E2EE35BBE8BD7263DF7CA3 +:10AB6000FEBDBF05F5EA1D3EB82297DFA82DC2E362 +:10AB70004193CDCC3AD41B93533E40FBF4F688412D +:10AB8000EFC75FC6F1D43509E238EC69D81FFBCFB7 +:10AB90009E4A95F4D2D852A0FB92C6AE01D2DB6396 +:10ABA0006B206DB072D7CEB93BD1BE55AB218EAE06 +:10ABB000EBDD953758680F6CAA0013F5B8FF46B661 +:10ABC000C0587DD5F0A53150BC29B58CEE6959CB64 +:10ABD000D6255263ADD140F6C3D1182F072AF839D4 +:10ABE00098AE331582C3BE7F9CEC4EA61FFCB5FD0C +:10ABF000265EFD65C015D48F7F2EA7AB71573D9D96 +:10AC000053EB1AF310DD4B635D033CDE69C7A515FA +:10AC1000C65F6C9CF62BF49CFE9523A1E4B79DFCCB +:10AC2000C0F891E44C17E613E4C0676798E3F30EAD +:10AC300021E706FCF0298A97B4F8E83E176FFD6516 +:10AC400002FF775B4BFEE10C23AB6FECEF078B0C45 +:10AC5000977FA3E20395E6B348BE1174A43BB39378 +:10AC6000E8FE17BC18F4745A9617943BCEB3DC1B5D +:10AC7000EF85C98867DB2EAAE5F68C7DEE91E12190 +:10AC8000730FFBAED705E87ED1F14DB9ED23B5408A +:10AC9000FBA8ABC8FC6918F30D443EFFD7972F21E2 +:10ACA0007D9FEFDEDABB235CCEDF2559951D489FE3 +:10ACB00049FCFE196FBD83C25E64F620F1CD268B80 +:10ACC000DFBBB5896D7D1E45BEBA9EDFF3C7DEF3DF +:10ACD000730E06D079F1D80DCBB45CEBD51B57CEF3 +:10ACE000B7EE826A5F3257BCA556D0AD24AECFF71F +:10ACF000F1E983E9B0478B6A81EEFFD2197DD0F686 +:10AD0000AD805E4ABADFD858528971A15B6F540D8D +:10AD10007C7F5F65AFB510E72D41EF839823A3F4E7 +:10AD20009A781EBD223ECEE8769CF72EAE7894CE61 +:10AD3000C3DFFE54000275783FA9E7F7D938E9234D +:10AD400067E96CEBAB7CF32BF4790BC397F3F780DB +:10AD5000308833388F220B0CBA1FD9E8253BF4A872 +:10AD60001544DD0A467D2FD72BED2178308EF7CCA8 +:10AD7000F2F2A6F054C0FB6735A597EC754DAFA273 +:10AD8000725175A29BECF369DBF55CFAE153914AD1 +:10AD900097DF24E4895369C91B9AB89F56852939DE +:10ADA000D6D9C12285DBD3AC29C573ADE1E5EDC9A8 +:10ADB000F2C79B42DFE8D97D32F107C92E468F707A +:10ADC000C5A2B764C77D9C61EFF9622F3D3DE59355 +:10ADD000A5E73AA4A723BEA0D52735A49FC1EC249C +:10ADE000B2FBEB019CF7A66FD22C7E0F8361F82C8F +:10ADF000077ECB85DDA77CA0D079DBBB9676D0FE25 +:10AE0000632CEB03F37AD933E7BDD3078B785E78F5 +:10AE10005751624984F27281EE195E27E4C679F2D5 +:10AE2000CF8298871504A6E7908F16FBE0C11C74AB +:10AE30002D8F703CA743E6E722B3F2CFF77129F7D5 +:10AE40007DA276FB83C20F50B81CE6F39D620ED044 +:10AE500079D2819B0AD3DF036C6EFBD02E57E25C64 +:10AE60004FF719D03E93EE7F4AA3DEDD145B4278A4 +:10AE7000BF0FF529DA56B55C4FFA53DC4F0C864408 +:10AE8000F7CA86C4BD1BF7A58E3C8B76CFD11A05B9 +:10AE90003D3E10AC485AA85F8BABFB2C09F56C69A2 +:10AEA0009AE2C74C8F598867E3AE4504B75FE96DF6 +:10AEB000417D99562084FA7C008D4966C73D127EFB +:10AEC000A403F35DFCB5695064DCD70338EFF737B2 +:10AED000602FD9597EA687C96E52FA5A502EB5D71F +:10AEE000EB14D739EDC63E70EEEFD8B8B7E2B81321 +:10AEF0004AD97846567F7AED8D7C7606D3B3222FD9 +:10AF0000674107EEDF6829B1F2C3E1ED1D686F7E8E +:10AF10004B37BF4EFC93679FC1F8E29E48D9E8F9D2 +:10AF2000E2B9B09B2F06FD27C2EFBAAC4E087A30CB +:10AF30002EFD0D83FBCABD7EC0F99F7BECBE3DF7A5 +:10AF4000307CC8A84FC972E9D9F324FBBE1CFDB000 +:10AF5000AC7CE581A92ACABD5F4D90F1EC30F25975 +:10AF600014F9E71DF0917FE81DD81F9DE180676708 +:10AF700084AF13E8F2BFD6E7F03F5EDEC3CBB6FC8A +:10AF8000FBCA5DEEF29761C938B4BFBE7CBB1FD26D +:10AF900012FEDE29F7BEF99108CF37FF0AA43A1056 +:10AFA000CF6BC5F9A46B1E9BAAA2FD74E50CBD1264 +:10AFB000E39F361CCF0A3DFD36E363C3210FAF0A82 +:10AFC000A755CC977A7DFB8CCF9C0DD84FBA6302E6 +:10AFD000FA0FC7404E3DFEA52E379C23CDC30BB7BD +:10AFE0007DDE281F1CCA1629A71FECC588DB0F763B +:10AFF000B2F7B31F45FB7856F6F7D7D9796627DB4A +:10B00000EF9FF2F47B8D86175103AC527A1AA5AAF2 +:10B010006CDC2BE8B7CC8968FFED989FC1DC7547E5 +:10B02000BDAE02EB35FA86A937D27C5687EE8DA2EB +:10B03000BFA84F8244AEFB77CA42C931D15943EF12 +:10B04000E101F1FB820EBD62DF63DFBF08FD7C0121 +:10B0500060FB7B7A2AC407E4FF91D05EEDC9989526 +:10B06000183F565CFC5184F11466F7AE12F6655138 +:10B070008DFBBBD71F747A94AFEB7AE823FB3FAA12 +:10B080008533329E6BAD73E73FDD59F44592BB2BA0 +:10B09000F7F9C9CE5C09C6ADF533691D921FECFA0C +:10B0A00075A7539CF8FA32236EA15C83B8496D3DB5 +:10B0B0007CB7EA0309D20E3FC12AA55FC5F5B68A5F +:10B0C000E90FE7FBEB62B2F1468EDFDF643FFDA0E4 +:10B0D00019E11AC4838F9FA7D559D931CF233D5287 +:10B0E000238FCB19C5170FB37FBF2EA6D238CBD66F +:10B0F0004D29E6FE21B7DC7C57E8A99F3CFC2D9545 +:10B10000EEA3FAEEAB17201E563C2E83C6C67DF783 +:10B11000E10864487FA555D45F576D9773EA77CCF3 +:10B1200074A2BC94ADDC7F79D5B6407A316B7FD503 +:10B13000A3AF9F050CBE775BFBF74CC475F05DEECB +:10B140005704ABEFAC8BD8FBAB14F8BFB9ECA9CF6D +:10B1500047B9BD7DF847454DB8BEA52D3BBF48FD5D +:10B16000F65EEA0F38E2734BA2FC7C2CABC7FDA065 +:10B17000DF91D25372C4EF6CBFFBE1EF481CBE1DE0 +:10B18000FE7410E1DB72BF9A6470ACDAF21EC993F0 +:10B19000055BBF17453CACDAE18ED3ADD8FA610749 +:10B1A000E6A1AC90A17F31F2B37C8CCA474DAD5F74 +:10B1B00026B9CFCF57AF2492B07A3FF8EDA2DFB0D7 +:10B1C000EF6FC7640832D1FBF6BE83EAE3584E86C0 +:10B1D00053B8C35DB5C32DF7566D799DF222741F28 +:10B1E000F4579C8DF9016EBEF6D667EB4745FB69B7 +:10B1F00055EFBAF7D0AE5CB5FD9D5FA3FC58E59165 +:10B200009F6FE37FCA87FAA9DBA29EFB69B61496FB +:10B210003FB1E27B47EFB5D8B887B7FDEE5ECCB360 +:10B22000BFFAA3F7EFFD67B4179E0AEA28FF577D20 +:10B23000F7852838F8F11EB1FEDE9D045639ABF7CC +:10B24000EE7F06D278A0F5DD277F3B19CFC9BDFB85 +:10B25000C81FC719ACFEF54F9E47F7F25FFFC30545 +:10B26000E387B3AB905FD301275C69A2ABB143E244 +:10B27000C6CB13E2E9A1C7E1470654B477FF2041EA +:10B280003FEAB995BD1FAAB83FD963423FE267F7CD +:10B29000F6D7F77C9595DF61F409E4A00F9BFF4496 +:10B2A0001FE96F2626D973E5F6D71721BCABA09FFF +:10B2B000F4E9107A3ECFE839334B4FEFF7A3704CE7 +:10B2C000C57DC1AA8719FDCE423A32FA9D35947EDA +:10B2D000EFE07FE60EA5DFE351F7BD0947E1EAFBAA +:10B2E000CA7163BA7D6CCE3C886C9C61F87B506CF3 +:10B2F0007930127EAF90385C5D51F3A728EF0F6F65 +:10B300002B1AA4EF62A4EFF78E4E46E3ED4D7FFFBC +:10B3100017110FFD4F0674FCFD12573DF922ADB316 +:10B32000777FF89C6A505C07A2D26C5686C19FFD5D +:10B33000C0CA2BB90F1CAE79E0FF2FFA356B7F0D19 +:10B34000EB02F7998C6E54DEC3D61DD1217D61A32B +:10B35000817A335D46F35E99E6EB61657AE7C578FD +:10B360001F8517EFFE62FB3ED02C3DF1BE8395DBBF +:10B370005F5D847C978F9EF6FC759CFF1CF6FD013B +:10B38000F77AF5D65FC9D627E9292F7DD33B7F8190 +:10B39000CF77EF0F28783EE35D71AFAE97EE59FCA3 +:10B3A0008B73F3A38C431DF7F0C7601C4AE0293F61 +:10B3B0007FF0753ED2FC468BBF77A2868B8F6C3CAC +:10B3C0001E3E965BFE4F2CE6726325F434A2E9EC38 +:10B3D000B55714485A132BB3F01E46FB82C17BF8B5 +:10B3E000BB32F9853A7A77931CF7CA8B9590FBF7B5 +:10B3F0006FD516737B71E58E9D67A15C3BBCEB47F7 +:10B40000C49F2B1F7E55C57DC79E2D3F50FB6AB341 +:10B41000EB01F543DA81EFC3DFDF79169707B9FD5A +:10B420005E73C57C563DE1EE7FD5C3EFB9FA5F612F +:10B43000F592BD30D2386F2BE6A538DFB7F7F9E9C2 +:10B440001EC2B77BE5C65C76F0E462BFCB0EEE7839 +:10B450006ED16FF03CECCCFD21BA7F717BAB39FE35 +:10B4600016B4DFF6FB457CD1FC1DDAA5DB9F0B9102 +:10B470009F67FBFECF503E90DDDF631E7CCE79DE02 +:10B480005A1061FDCDE94BCC948DA172A3EE00DB87 +:10B49000EF39F8E0FAE71AC7A3DCC7FDB181BF5F57 +:10B4A0004E89D3392C39BA88F2CC65DDA70773EA07 +:10B4B0006FDE9F3FCCF7937EC698CEFBDCCF3DF688 +:10B4C0001FB47FEF88FB72E2E13E817FFBF73FD93B +:10B4D000EFD74B9C6FAC67793C24DFFADAD81C8B32 +:10B4E000573354DEDA5C17C7B8CFB5C5FCBE9EB182 +:10B4F0006F18129E2D99DB674CC7F917432FE0791F +:10B50000FFDB9BF5B8333E5476D86CC17A67BF0930 +:10B5100071AC87E3E27E6DB4E35AC5FCDCF3907155 +:10B520006B7B092F858CAB9DC0B8B79E8271C327FA +:10B53000806780CD058DEBCDB3F28EAF4EE379639E +:10B54000DEF192B63E10F1055A7AC3F8DBFCA29FF9 +:10B55000A5C586EBF7958192A17BABB3791769A955 +:10B560007326C6EF06CF1B2734C77963F69DCE1B23 +:10B57000B7993C0F96B5A375D025FC1318CF5CE6A0 +:10B5800080F705219F0215A918DA5F9D79E211AFB6 +:10B59000083EEF8C346838999DFAF4E2BE61F48677 +:10B5A000B2E69B339CE792153D23B9E2C8E6EB7403 +:10B5B0007F56BEF6DEF8A20D7FE7CE7F82AAA9985D +:10B5C000379B80D61C706E17EB07EB5562BD581287 +:10B5D0005A1CF5D4189FA75DEE147EA1576E7DA569 +:10B5E00093E2F679F0B443D0F30574CC97D1F64DDD +:10B5F000C3F86F57C44772B22B98FB1EFBFF2CF6A3 +:10B60000B9E4A48AE71FC90FBB8FF68DC6B1974D69 +:10B61000BC1FE9D65A95FC6091FAFD543E6AFAC8FF +:10B62000FACF871FFB3E83C1721EFF53BDCEE9BB1D +:10B63000DBDC46F9B1D74D558DE1F22D426BA6C545 +:10B64000316F425B73761CCF6B876AF8EF61D8303D +:10B650000FE26106DF863CFCF13F58523CAB0080B4 +:10B66000000000001F8B080000000000000BED7DB3 +:10B670000B5C54D79DF0B93377EE3C813B30C0F082 +:10B68000BE8310D1623A28A2363E2E0F0D3E62468E +:10B69000C4A809D6D13C4A2218B436A11B1B2E02DD +:10B6A00082F8C2266BCDAE4D47A22D6DD31653DA6C +:10B6B000358FF61B4C74ED635B626CE2F6D30613B8 +:10B6C00037AB59D365B7CDD6ED9736DFF9FFCFBD90 +:10B6D000CCBDC30C68DAF4B7FB7D4B7EC9C9B9E7B2 +:10B6E000F53FFFF37F9FC77C4AE4089949C8EE2DD8 +:10B6F000840C151342F8B08DB808D95762B2433A9A +:10B70000284F4F1AA6E987F0B7606C6A6DFEDB1907 +:10B71000553322F9CEBC442E48FBD999F73819A6E7 +:10B72000A9F5831612A0EDAD3C91FB69EA96C960BC +:10B730009287E6E55B7C561F4D5D24C3544ADB953A +:10B74000DFC2EDF08DED7F30E711EF5BB45DBA4CF9 +:10B750003220ED2C17324C3A787ABED04402749CD9 +:10B760008E72612DC0690D7F9E480991F2274513A5 +:10B7700021A9F47B5D8F2CC3FC08C90824C03C4977 +:10B78000468DAE5E0F47D6F4178F1DFF10E087B6CB +:10B79000DFAD96EF9BF3CEA17B29FCA22C95986997 +:10B7A00037FB06AF92FC69341FBE2A73302F0F9906 +:10B7B0006E2763FB817A3E5A2FD11B241B00CEECEF +:10B7C0006112A4E327160D1398BF43229249C27E4B +:10B7D00010FEA4D92344A1F592E60E7B9569BA7EAA +:10B7E000FE608E09A719E649D7D1D15CEA2F48211E +:10B7F000C4D63CDF5F40D725811F2222ED2741625E +:10B80000F88F6EF7CF490C3F1A5E7ACA6F490AC6A5 +:10B81000E87F747D5BCEA4F1165DBEBC670DE0DFF2 +:10B82000E2092A30FFC4D90C2F5A79A2344C643A69 +:10B830006E2261F324A5443E4693845285C0387439 +:10B8400048593F9F07547A7C409D0FFCC969588F27 +:10B8500010FA29415E74D57C2BE479F256112BFF46 +:10B86000D0477041DFB2A979F3D87CBCF94C94EE93 +:10B870006A21E42DDD7C6DD974FE5ABFF4DF1E0B06 +:10B88000C900FC7E54BC09DE61A407EDFB3675FEE1 +:10B8900016CF30E2670CFE8A19FE9CC50C7FCE28BD +:10B8A000FCED55DBEFFD2F86BF513C71A63540877F +:10B8B000D178D4EA578CC2AD205DD276847C0AF26E +:10B8C000816AE0DF1E3BCB1F12EFAC06FE00BE9A82 +:10B8D000805F08C9A44D7AB82E28CF1545ECDF7AD1 +:10B8E0001F9507FA7C50930F6C5C97CF5F4D283DF6 +:10B8F000139F891CA328ED9AAB7861BDBA9153229E +:10B90000FDFFA33809EB774A8289FB244DCF2C4CED +:10B9100007B9D966EBB1C17CBB2C3DD84F5B8E49D2 +:10B92000EC8D21DF4EABF335373B671C9D111F8F2C +:10B9300066810463F1FDDBAA7C6B1B7CEA8C99D2E7 +:10B94000072F09929DC20B4CFFB6B6BEF9B43DE974 +:10B950001FF2F9609C441CC7A5C2E52A349156DF4A +:10B96000C4701E57E98A6FB68F0B270F70C69033CD +:10B970001A9CED00A7273E9CCE9C0AA453BED985F5 +:10B98000E30C8A125B0F4B936D239D9FAB35496A85 +:10B99000A5E92EBEA9AB0ED2210B5168150B91CF94 +:10B9A0005450B8F969D309A1FD745C9A659B04B43D +:10B9B000DFDC43023A391F74042F89B43F5E0C92D6 +:10B9C00020859377293280F1AC4A07DABA91A264D4 +:10B9D00042E6D0F182FC0C90A7CEA080A9D68F467B +:10B9E000274E8B4CC462E8C7248740DF416773222F +:10B9F000F5E6BB19DEDAE6860354F691EE129EEC0C +:10BA0000A09FDA8B28BD24D1BC45EEAAA3F8E87E1E +:10BA1000D5427A757CA08D9BEB66FAC74E6A93C2BD +:10BA2000D0B7F9B037388E3EB603DE68BBE60BBE42 +:10BA3000EFBCA2E115FE15133CEF38917633809FE1 +:10BA4000DF27C5AB4DA6F8FDFCAE45FACE2B3A7903 +:10BA5000D54C98FE20444A5F312D7EBBDD2D6446D7 +:10BA6000416124BF870F213EBB5DBD5DF9749E8A95 +:10BA7000DFE42FA4EB45B24B0D788A4E096965725D +:10BA800070CCBAAE96C2B47D779189B702BD1690DC +:10BA90009019F092ED41BED4D635E8607463F13070 +:10BAA000396976C998DA008F20EFCC7BBCE3C96B8B +:10BAB0001BF0490C3C16B9291E3FF1DF0F8F1E37D2 +:10BAC000C1D499509304F8232FEF22D23400C3C875 +:10BAD0007F5A3B8DDEA3E75FFDDF7CFE1A9DC4AF7E +:10BAE000AF68F6103F48AB660549A89BC37CC0967B +:10BAF000864D29E854A5D8C2ADA09A72EAFA334E11 +:10BB000011D0CFEDE23B36145DFE0F53C6EB9F27FD +:10BB1000EF68F83447C6D3E3C7047AE78C25748C02 +:10BB20008BE02941FCB47790DC089E9A6C208F3A18 +:10BB30005D5BCFF84A2378EACC7E4EDCA0A3F72BDE +:10BB40006285E2A6F8D809766D0C7972AFBBA21DAA +:10BB5000CA05536C797E48956B5480F30BE9380B1A +:10BB6000468C789AA7E2697EFA3B8FC134A994E4A7 +:10BB70000915C815017F15E0AD6A4D00C882085946 +:10BB80001F7C2288F45025025E3865B2E943E78DB8 +:10BB9000E32F1EBE5C1C09C482FB19B1E6881BF4AE +:10BBA0004931C59BCEFEA08421A27CD4D6C5E5999F +:10BBB00080AED8BABD7C31DDA4D0AA9D5E5308FC0E +:10BBC000190B69EA02BC93736602765A5A3803CBA2 +:10BBD000ADDEFC10E8BBB4B09DC8E82788213BADC2 +:10BBE0007F70ED5D7ED443D76F23614A3728CB4009 +:10BBF0008E65CB61B0A779512A374B30CEA336F092 +:10BC00006F3ABD354984D9DB24961ED8E20EFE007A +:10BC1000D68DBF3E1FFB33D998DCBBD1F97C69655B +:10BC200022013BC07E810B812E3BB0727ED77029F2 +:10BC3000C8CD841E2B4DDB78250C7A4CB96097005B +:10BC4000DF5B0B95DB4D342DFF95BD88A7DFBB383F +:10BC5000871FF0D05548979CF6F3BBA79C2142F371 +:10BC60003B572E1F49827E8E9A25287FF2C3A64F0E +:10BC7000823D65FB603FFA8736D53F247CD32C5844 +:10BC80003FFB479413BBF91EA4FF5D05D36D7AF902 +:10BC90009EEA080E035EB4BCDD4BE5DB0CA4A7B73F +:10BCA00086293D99148E7C48E9D3E6DAE63D25C124 +:10BCB0007CE9778D3E7C917A11BE35E63D14D760E4 +:10BCC0006712726431D8919D206FD06E250A07EB00 +:10BCD00096C1CADF3FB06231D8A19D76AD7CE562E6 +:10BCE000599F57FE7006F3AADDEB4FF6EC82FA9EE1 +:10BCF0002CD2C4F01320AB74F64C41328FEBD6E754 +:10BD0000967FEFD6D9CD1A5D761530BA7CF9626789 +:10BD100035C8CD4E4A975609E87097C14FD6528D17 +:10BD20000E3B0B189DC5C3BBE57A0909EBEC408BB4 +:10BD3000A707E9D1E609A01D1D5D7F450AB363345D +:10BD4000FAB77909F2834D0A3E753FF287CB0FECC3 +:10BD5000672D68221CA5138BC8FCE189E6110F3EF4 +:10BD60008DFE3B0BF215A0D7F745E227E3D4B75C75 +:10BD70002FC5F96C71CB93927578F4E451BCC798D8 +:10BD8000CF5792D97C3A027581FB69BF72BDA4205E +:10BD9000DF7889BF1BF412257FB03BA9BDF9C9E448 +:10BDA000543D9E983DA2F5AF704D8316E0730F6D24 +:10BDB00047BFB6939714587A8B2764E0EF2FA604F9 +:10BDC00067EBFBE145E61F2E34BB4CE423E0673F05 +:10BDD000F5CBC293A99FD82262BAA7C58B69578BAE +:10BDE0008469778B4CC256EAFE90EBE7EF053BDBAC +:10BDF000E540F826A28B8E163FB66F6F99CDFAE11B +:10BE0000343A9FBA0BE8C261D2F8C4BF0BE83CC910 +:10BE1000AC959761BE8763E58F242F58AC14E37C03 +:10BE200050EE754D30AE395486EB77F3FDABF25BD7 +:10BE3000C5DFFE798F54E703FDBD6126FA38C618C9 +:10BE40007A09B3F16EB4FFAE6C13CAD3FDF3769EDC +:10BE5000F1D1BCE575DAFF78F4D8C3FA8FDB9F0621 +:10BE6000EFE02E84D74AD7DB4EFBB38A4CDEC7E324 +:10BE700087E8F9D294207F7808CAE9FD836BC9CBA3 +:10BE8000C09F7458BB087C1A9021DE25B4531CFB5C +:10BE900041DF06C2CF80BEB571E418CD0B2ADF505A +:10BEA000B5AFBC4CFB11641BE9A6ED06E7DD45A070 +:10BEB0005DE72B360A13A5D3947CB417EC85B5A4A3 +:10BEC0008DD6DB596D2766FA3D69FE1A02FDEDFC41 +:10BED000991DFBF79D9982FCBA4B647C34A11CF23E +:10BEE0009A4858AFC76D8E483E1FE4E57D24300D5B +:10BEF000F9FA693D5F533DD90BFC24902A8570A067 +:10BF0000871FF0333B4451E569E05832DA81016C18 +:10BF10001FB10B9B8808FC7ACE1CEA06BFC4DC80EC +:10BF200046DF22F361DB30F2B5BC3CA38C10170373 +:10BF300081ECF287492EE025C34C6D31204B818482 +:10BF4000A9DEE8A1FF007CFC85AB17C8AD84A4AFD7 +:10BF5000110CF3E02F382F996E05F8587D4D0FF135 +:10BF6000171A1BA13E4F74F5D19FA94B1ACF2F8CE6 +:10BF7000B6E30793557FD0497240EFB5B79C206F69 +:10BF80005B22FDF05171252DD5ECF9875358DC6209 +:10BF9000949E2446DF2F503F1DE8B1E31766D21B65 +:10BFA00083BEAF27FB0CF66E46D014991FFDF795A4 +:10BFB0008BD68A8306FA1C7FFDB3EA8DED739A1C3B +:10BFC000063CE635271BF23E25D3507F5257BEA1D3 +:10BFD000BCB067AAA17CF2A1E986FC94D0A70CF5BD +:10BFE0003FD15761C84FEB5F62A8FFC91335867C0C +:10BFF00049F86E43FD1967361ACA670E3D64289FDB +:10C00000757EAB213F67F8AF0CF5BD41F1E409E067 +:10C010004F4A8F668AAF5D19CA21D09FC36DD48EF7 +:10C020009BCFEC63D0B7249BA8F631554C694057A1 +:10C03000ECAF1DF400C8F93D8F85BF807AD2E407CC +:10C04000FEE50B16C91BA15DBB68225E9D1C911607 +:10C0500011F85EB1C78DDFE5D256E40F81AA0D7BE2 +:10C0600022E86DE37A10F376D20FF0BDC1E0E3452C +:10C0700025A67C12B28DF46F25F72405C6B1FB2CE2 +:10C0800092B1FECDD2BF2F45A5FF1C4AFFE689DB4A +:10C090006B74FF90499E9CC2FCC3AA731E83DF830E +:10C0A000781DF57B6CA41DD8A9BC6E24EB14ABAE37 +:10C0B000FA3756D3879FB871FF269ABF684A714EE8 +:10C0C000D7C9CBE4B566DF8FD587330CF65974DA60 +:10C0D00096F810CA3B2A17CB530C72315005F31354 +:10C0E0007819E5A2F6DDD73715E57297C8EC944EBE +:10C0F00089F2E538F88A96CB5F4E9698BF18473E8E +:10C100000B54CE82C2DDB9F2D35D8037791B41BDBD +:10C11000447510CAD9E8FEA95D7537C2E965F4A473 +:10C12000F9439ABF65A3F203FC2B9B44105F568A28 +:10C130002F27DA478FA27D49E721817D64F550FBE7 +:10C1400013F43DB53F99BDF9E7B52FF361DE7AFBF6 +:10C150004FD5972187DC94921ABFFF17E3EC479DD8 +:10C1600049D6FCEEFF9EF427A718F1A1D1A146679E +:10C1700056203A3ADEFB125B77DA2291D3F62F246F +:10C18000F84F10E9E5D4ECB34A25AC5BD0255BA9A8 +:10C190005EDD37BB06DB0993780272266178C33215 +:10C1A000D093A494C90985FE03F4E62836CA0D5B32 +:10C1B000941E15401F278ED5BB9A7CD0FCF389E4D2 +:10C1C000CBB752D438D92C324B2F5FE2F9E19A7CAD +:10C1D000D1F0B0E0831611ED8E0F68B9664FD07EB6 +:10C1E0002C397C00E2CC829FC84762F0DFCBAA5E8C +:10C1F000EE3B6997812E5D6B04F4B332FDE172C8AA +:10C200006736113FE067F670980469FF3FF4B0F5B8 +:10C21000C8F48738B0CF332F873880F3A085C58521 +:10C2200032B785387DDCE89AEAC7FDEEE2A37E5896 +:10C23000F78A3C17F2E9671713A48F21EFC69E72A5 +:10C24000D857984BFCC03F2E0F4F32217FDE1A4249 +:10C2500079E21F51A8AF4392E944614DAFB490E930 +:10C26000F751FFFDDD161BA6D75A444C2BF38A0766 +:10C2700017D07A5B7D0E8C1774E43B709CCE5C010A +:10C28000C7F98F9C87F2C02EF8758B17EB773DDED0 +:10C290005404F184CE93FF8971CD083D53AC7901EC +:10C2A0009E30EEF710BEC90BFBBE49F20CDC27ED49 +:10C2B000B404FF7103C413D70AFE6331F837E9E50C +:10C2C0001FA19F0CF8013CB4DB195EACCE26BF1B4E +:10C2D000E2FD93C8FA15B1F854C513A530B340E98F +:10C2E0003789910611E686DA1241AFFA493F059B7C +:10C2F000583A421CEC8790074509E245D9B6D02050 +:10C300009467D78BFE36AC4F705F415B278B9D04E3 +:10C310008EBBA05E98DB42BFBFE811D9FA0D8570D5 +:10C32000DFFD37176E1FCC21F1F97B4F4BF5D92A72 +:10C330005D3CD64562EF0BFFCB6D15160FEDF77622 +:10C34000806D26ACF7AC71F5E38DF67BBB8753E3CC +:10C350001393D3C15E6EE663DB996691AD0FC47F24 +:10C36000C08FDE5A28A5BB5DFA7E183ECC279FC73A +:10C37000F57116B3F9B77DEF8DCD8F513AF977DAB4 +:10C3800010E255AF5CFC0CFA8FEF254BFBC1EF526E +:10C390007E6C26B0CEEF7D7FD669589431F36E392E +:10C3A00093CCEBE249EF7DFBD5320BEDFFBDE75EB1 +:10C3B0002DE3510885101F5A79E387AF9541FC4A58 +:10C3C00068FE4DE6650AAF52418A9A204F0D68E635 +:10C3D000876E591A1E076F07D31ED802F1C2509BF1 +:10C3E0004BE4A8BDF625E71F05A0C766809FA60FF2 +:10C3F000DB4676727489B9F4779754D1FEB6728AA7 +:10C40000E2E2006F8A15FC0A72C1EA07BAD95AC87B +:10C41000F4E5D607C59002722CDCC4C8DDF65AE6F6 +:10C42000652A87ED3F0DC11900D2CE052A13207E63 +:10C43000378D20BDDF76AD290FF695DD44C8073A6C +:10C44000B498CCD8CFC84567A817E56FD32C9043D4 +:10C45000AD171F9D0CEBF57B55BE6871B73453D3F8 +:10C46000813A1FC4DDFC1877DBCDF7639C3EDE7C90 +:10C470009D5EB6AFC0571235DEF5DBEE7076841EDA +:10C4800034FE8A6EB7B785F861BC975A6C98BED0F7 +:10C4900022627AA2C58BE9F75B244C075A8A30EDF9 +:10C4A0006BF1FB0B2C00E76C4C3B2C647D40476729 +:10C4B0005FF0B0FDC87B92CABF0074FE24EDF73276 +:10C4C0006DF745DAFE32AD3FAF366C86B8CCBC11A5 +:10C4D0002A2F2528EFC2EFFB697F506F6CB9AD049E +:10C4E000CA4BABFBC380C7D262FA9D407F7D587FA9 +:10C4F0007FCB093F2B1FAAB450FC96FE96953BE7D5 +:10C50000D27E68DEA9F643C72F61F567637F745C4E +:10C51000CCC7E8B784C173A224163CD1F5A9956FA6 +:10C5200026548F88F0BFE0EF59240EF75138123EA1 +:10C5300006F2F882B51CF4E79E12926FA2FACD9231 +:10C540005AC041FEA966229A4BA8CACBA8D9554E1B +:10C55000A09D8CDF95557CE8980FF513F6ABE9A705 +:10C56000E4EA30EA9D243FC937BB69CAD381A753A7 +:10C5700054DF4722E70D503EB13CAE076D2756937E +:10C58000C8790332717DAA5FA2CA63D3DB474D210C +:10C590003EA63FF771701EB1835F4B7DFD7E924BCF +:10C5A000F3AA7DF645B5DEFE7965491B21BFF8810A +:10C5B000A7200EFE1BE2E5603F7EB47D943D77B878 +:10C5C000E54C5A55A1AA1440DE6F138FE8EDDC6CE0 +:10C5D00085D2AB8E0F7A9AF8EA5E8C2F04336A7498 +:10C5E000FAADC312CCA0CC4BAE3FF18F8B413E8055 +:10C5F000BE06393D7784E9F751BDFE5B261F357BCA +:10C600004250D76B9FBCB12D01F7D3A83E92C0AE6C +:10C6100008920ADA3EB17CEBCBF09D9418BF270854 +:10C620008C8F32BD210EF2999EC04F3CB0DF907CC2 +:10C63000487E86CEF7B7035609E8AFEFE4DA7A888A +:10C640001B3E4C12253BED27F3A54B02C0D1611ACE +:10C65000168008473CCD4B786A0775089A9CA486DB +:10C660000F5DFF8E34552E90DF7757D1FA074DC1FD +:10C67000AB54578ED63FE8086E813CFD936D54AFA6 +:10C68000EF1D8DA36FEB96294DEC55E3E6239ECF6E +:10C69000762BD990A7F5DD2CDF4EDBEF750F794DAA +:10C6A000349FC86DE93E930379ADFE966E85B6BFA3 +:10C6B000EA61E700882BE803B9379A17693E41978A +:10C6C000E7599ED858DA77F23F05D0431D6923A772 +:10C6D000B3009F3FE4FA41BE36BEFCF541C86FAEE1 +:10C6E0002712C4E7324F1CC175F8AAB97C04F0D6F2 +:10C6F000D7724644431DFEB475A176EA142FC17863 +:10C70000B210E242F960BF15F798D07EDB4E49B017 +:10C7100004F0DD9506EB5C91C6FC812921DA8F8E51 +:10C720007FA650BEB34E0775651919D6FB5BC46F63 +:10C73000027811E5F01FE57F2F01FDD4375B714CC6 +:10C74000A5E36DDAC0FB5B25D03FA15601D6FF04FF +:10C75000877AC2772663C73768FE5A7F4A2FF81B4D +:10C76000961D8C3E37F9FAD3A6D3B4C3CEE86293B4 +:10C770005BCDBB8DF976D59EF4BA157732FDBEF947 +:10C78000C4815C3000AF1E9B857EE4660D1E720086 +:10C79000E1B93A3827E9363ADFC69FB2B866E340D6 +:10C7A000C912987FE31E13013F6EF300A5271D7F7A +:10C7B000ECA37C284FA6F3907BA6F2943E02070BD5 +:10C7C00096DAE9FA7E3D5F16015FF569B7EEB6517C +:10C7D000E7E8EB823805E8A13EAD7437D0D3A6393F +:10C7E0006F213D26A596FEA49AE2EBE8DDD54B40ED +:10C7F000ACA599185F5282433967766F43FCFF6B93 +:10C800003919B1BA119DB8CF9907FF47E19B2CCADE +:10C8100015505F5C465D22A053217012EC10A5C23A +:10C820008671D20A711996E7AE21A66E0ACF112938 +:10C8300039B99536B517C826B053F2030E8C7F9AD6 +:10C8400013AA76803F7AEC1CCB47D6E912E2C55199 +:10C8500014EAB7D17E6E71F122F8226966D906EB2F +:10C86000467979E85829F00BB303942F1663BCE797 +:10C870006022A97F8EB63B6ADAD8FD235AEF68B2F0 +:10C8800087805DD9C171EB6BF07BC5D4AD743D8EF3 +:10C89000AAEB6776FB4558AFA36E637E2FB7F141D5 +:10C8A000C0DB23A92F2E81F9A559E59E140ADFE7E5 +:10C8B000525FECF666209EF36DB4FC737FFD42B7C9 +:10C8C0008DE2FD68AB9C29EAF293FF40A536CEE3EA +:10C8D00005E453DEFDC587808F69F98F6D54FF7EB7 +:10C8E0003D59B307587941BEC6D7D4AF9D4DE168D5 +:10C8F0001DCD2BB622D8F78AD4AFA27CFED5A7CD0A +:10C9000044EB1FEC09C79C7E9BC38CF3200EB067E1 +:10C91000A6F168CF38DC6C5D1D53F2D14E3A6A67E0 +:10C92000F81AC93161F922F3B322C407AC53781362 +:10C930009EE5214D01D0CF7C364F58BCF7B03C4529 +:10C9400082B029DB1FE47A56A07F682FD2ED071250 +:10C95000F0638DFB877C54BED03A9C61A27AD87379 +:10C960006105974BFBFB6CAAEA2F7A4806C4631F4C +:10C970004D6572E6D18072BB45021A1B66E75649C7 +:10C98000603AA4E9EB0AD2C73BBF32F65C4018ED2F +:10C99000B23D2E938AB749BBC305D45E763D27824C +:10C9A0001CA16A7EC761D06F1E1EE9A610F89FE623 +:10C9B000B7B9591CDED7B7E44BB3C13E7CB5D00440 +:10C9C000FCCF8B7E11CED99527942681DDC68FD2E0 +:10C9D000E9EB4BC240378373EE043F5000FEA59F46 +:10C9E0000FDBD9F9D0910CD20F7161DE2B13FD3E14 +:10C9F000A1C6BF3B5B6C98527FFE5DD01F5FEB22F0 +:10CA0000B84F2078039897DA09077CF1F2A7EEC6B1 +:10CA1000719FE10349EB40DE9E63763D900BC63982 +:10CA2000C24F7010E778DF16488279EF771BEDBFB1 +:10CA3000B23466C776A632F9D9D9C2E2A0C2F54FA0 +:10CA4000605CA7C3A2C923D7D2F05CB0E783788E1D +:10CA5000D61ADC2683BCB21145117571725BB631F2 +:10CA6000DE255CBF95C58752D938D1E70D5C9CD6D1 +:10CA70007FC1EEF1FC032D8D3E9FD04C02288FC864 +:10CA8000103BF7B06D57657AB2AE9F6D9C9C2E8EB1 +:10CA9000431F0F5F379390EE9CCAC3FC8800F37965 +:10CAA000F8BA80DF897738B115F66528C175C33AC1 +:10CAB0003EFF5DD44B0ED213860373568853E8CEE7 +:10CAC00085122F3F324AFFF911FEC07D752E067F79 +:10CAD00048C67CF47EFAA3E03BD37F77387F2DC035 +:10CAE0003CDFAB242360871232BC08F8B7B1D28197 +:10CAF00071EA87498FCD06062EDF23EAE3C58D0351 +:10CB000097123794E23E960476F0C32F951BE254B9 +:10CB1000DAF9302DBFF9C4068C1F3E7CF49A30B58B +:10CB200014C118B2507FACD1D673C69A1FA96FB783 +:10CB300004952CA0FF975AE52CFAE95B00279CABE3 +:10CB40006A9E340BFCBFDF8AF519802727AFEA8F76 +:10CB50003536D41FED76EAAF019D5E9C8CFA9416B3 +:10CB6000F3A09FB5F15778181D8EA8FE7C023533CF +:10CB700001BF1D8EC01566B41399A7F64E47B24685 +:10CB800037CDDDA0FF0E0A11B908933DE860F9E446 +:10CB9000B4E6EE76A687B1FEC893FC6EB0873AEC99 +:10CBA0006ADE43307F50E8413F41F9BE5502380FFD +:10CBB0003A027EF007951D5324D02755E92E9C8715 +:10CBC000E5EFACBD200F333DC1AB60B7100FB38FA5 +:10CBD000DE4BBD904B5C31FB19E16EA41FAFB11F62 +:10CBE000FB5C36FE7B9C39B0A334528FB60FE3B9A1 +:10CBF000807B6C18FFD1EA1FB618ED642D9D92C69C +:10CC0000E20C204F80AFB5EF42F03EE45F2B69426B +:10CC1000FEB57A8DFB451A3F0BD7A718E297DF4A7E +:10CC2000F5E1FA687240B85E8CE59D2A9DEE847D40 +:10CC3000F471C7498E33CE0C9413F1C72953E5081C +:10CC400051E3493C9E33D3F824BEBC30C671A3E502 +:10CC50009F966AF2EF884AC7FF600F2E4CA3FFFF32 +:10CC600050A87F91035B076F85F5F9A36AF716F566 +:10CC70001D3809E47745945B5353E13C957C1CD205 +:10CC80009BE59BFA3436DE5839C6E20FDB1E945022 +:10CC90003F3FC3FB1DFE1870D75F771AE4577EAA8B +:10CCA00084FDD5F30ACAB1FAEB8958FED1FBB793DC +:10CCB000D08CF1FA7761F968FFFDACFF973FF5E39F +:10CCC00083B3A1FFE3169355E7CF6D3BBE301DE262 +:10CCD00095DBEC542E1BF95606BEE57D64D40F029D +:10CCE0003EDFAFF945CAA2DD5573C16ED5F1F96CCF +:10CCF000B0BF22ED79BACEFB1D5AFB3B77833D34A2 +:10CD0000A6BE33AA7EBED6FF6AEC3F1A1E4D8E40E9 +:10CD10001EEC2DFE0F560D3E9443074C51FD8DCA5F +:10CD2000A520F6B7690EB33392FEBAFE270A0FF4B8 +:10CD3000172ACF023BEB4122C139E768BC27A9740F +:10CD4000587F7D92615D23F8BEC5F0FD9F5BBC24DA +:10CD5000A4E3B7CF04B72D027E4BD2D689283BB1CE +:10CD6000DDE12C12D2F1DDFFC0F151E1B82D0E1C36 +:10CD7000F3FFC270F80C7C1981A3C0F0FDA3C2615F +:10CD8000B65DCFBCACCB5B4492A5CF97846D599771 +:10CD90007576CB8C33A2213F73C86BA83FEBBC6484 +:10CDA000289F335C6428BFED8ADF909F3732DB50C9 +:10CDB0007FC175D9902F278B0DF52B6D2B0CF98525 +:10CDC000E25A43FD696A9CFC76EF0643BDC5D283F7 +:10CDD000867A4273CA77C07E59F0C1021BF8173BAE +:10CDE0005DA6EA10C5CF4E3E684B8E211FCBD47E88 +:10CDF00047F59D370DDB2F149BDA411E2EA4AE7034 +:10CE00001BB5D7D2EB02EDA0F7AB45229AD16F0E3E +:10CE1000B1F8C9072BABE0FB9D8B89D8ED8EE46F91 +:10CE2000FF2B42206FCD96F15C9BBDD884E7067640 +:10CE300017D78CBBFFB04FB5DFF744E9FB51FA3190 +:10CE4000B3F393D1DF8BD3195D1D58B08FC03E81F2 +:10CE5000CD15C27B3E8353767A21FFA505DFF6828E +:10CE60009FD135E5112FD04F67CE570DE7F21C0546 +:10CE70006C7F26BADFBF55FB2DB8FEA80DF4E7EE98 +:10CE80006C86CFE87ADAF9F4DD361637FFB8E6B902 +:10CE9000F8639AE7E5746667EDB68530FEDF5DF40A +:10CEA000F1C07FAF3ACE81058F1306EFE3780EB95C +:10CEB0002B4790F47A564BE1DE28CCA7D3B7D30B9F +:10CEC0007AB7CBF788C1FEB7C27C628C63F3323C81 +:10CED000ED163FDEF93CFE27CF6767CC7D775B9C84 +:10CEE00079156BF3F2AAF7283EA6793DF5179E5700 +:10CEF000581D2F359DD9A7BB25C64749E6C0CFF39E +:10CF00007DF1F92F69B6F19C5282DFE807E417043E +:10CF1000C63D7F745EC54F3C7E5D635152018ED726 +:10CF20005BD839DB7380479A9E0F4EAA80FB0AAF0D +:10CF3000C3792D0EDAEF48186F1DD606CD063827B7 +:10CF4000920F25E9F9888FD56B8CED56059CC6F3B9 +:10CF500052EA39038AA7FD105FD6F036669DFF4C72 +:10CF6000788A476F378AA7EEA29BC3D344F49D9A71 +:10CF70002E21BD4C84278D8EE2F5F3FF2A1D2DBE98 +:10CF800071FC20FD7CDCF8F9AF463FF7A64B37C4B7 +:10CF900067FFBFE2E7F11BC4CFE8796B81D4C73AE2 +:10CFA00007D2E915900E27734D6717839FBDD88C64 +:10CFB000F1B3D70E1734927C7D3DA6075E5B36A990 +:10CFC00011CF8F553BF1ACD65953EC7E5F53F1F145 +:10CFD00090D7AD9EA7F3A782DD7BB67AE5B8F322A2 +:10CFE000CBCCC6F38BC411999F99F64BA40A8C9FA6 +:10CFF00051BC1E1B67DDB5758B37DE8DAEDBD9EA04 +:10D00000B69B5A376D3C8AA798EDEEF6E6DF10DF47 +:10D01000C309768637761EA0EF7166B7F701BE6941 +:10D02000BFBF84A20CB0FF09C6FD56AF493F02F056 +:10D03000BEE665F1F001416AC47741562EDB0DE78B +:10D0400051CEAD727310D2D0E038A6AE67595D6C88 +:10D05000BBF339B53CD29E2393A5B1F58EA876CF0C +:10D06000AA3A0EED07C2CB39FA773FFE21AA3CBAA5 +:10D07000FD4BDE442C3F17E73CE6B7D4F6AB6BC75D +:10D080006F4FEA53F0DC1F21528EFE3EFA285DA955 +:10D090007CB0C21BFCBE97D67F9D0B7EF973104FF0 +:10D0A0009DE2C2F33D84273ED8F71FED8797F1BC80 +:10D0B000C6E54686F7E87E75FD85BDA9F1FB8B8741 +:10D0C0005F6D5EDA78A524807E1DA926E27E36BEDD +:10D0D00019CE39DC59499A707C5E427852DEA4FE42 +:10D0E0009C2F421F174CD23ABC48A3F633F0FBCA20 +:10D0F000A5D0CFC05993B8C3171FEE78F2E09F5464 +:10D10000FAF198833BE05C0159CFC53CB7F72BAFF0 +:10D110001DEBEDF78EEED7E338B73C19B448B4DF1A +:10D12000BBD4736784047356E8C6DFAFCE3BBA9DA9 +:10D13000C7CCF6C7C91B66C45F5FEF4339B1F8E7D8 +:10D1400035D55EDEEF2D32F8C7B5812D16B06B6B8D +:10D1500097ADB0482E289718DDA970F409C19C122C +:10D1600057044F71E58F8A9F81F3413CB7B1BE9957 +:10D17000C373C7C5DB19FDADDF3E686AA4E911952D +:10D180000F57C03E93AE3F77069B5F5FAF2317E01C +:10D19000EFD39FBFA0707CFA10C1B89D2DE3E93D8D +:10D1A00010B71BE6881AE7332D87FD8661755FACE3 +:10D1B0009096B702BC55A9C8E7EBB7AF403FFF96C2 +:10D1C0006AE6E70F0804CF01BD392F2104EF1D10D7 +:10D1D0009B3CF828CDBFF58724D2ED8FD0C71342F2 +:10D1E000781AD0476A5BE073B1E2D35206E3F3DF0B +:10D1F000BAD83E5E3CBC9C55E5A956AF86972CB18B +:10D20000EAAFAC36CA350DFE146BF83D12239E3ED4 +:10D210004A8FA1F1F5DD2F5439FD5A94BF547B3E5E +:10D22000B6DF3237433DA71BAAD884FA4AB14A7801 +:10D23000B65885C7A3AC467C7EB8948890BFD32AE5 +:10D240003D0DF0DD556B8E92C321EC67FD32A76179 +:10D250005E4FF4FE781ADC4BCA2F60F2F7FD2217FE +:10D260009E137F80340970FEAB8E28F3912F896462 +:10D2700001FA3EA7E24F83EF1C91136682BC683629 +:10D28000C7E4AFBB543A3A17A85C85E7DFDBCD783B +:10D290001EE1526DCA72887F2B018B1F8E375D6A2B +:10D2A0005F9970BF6E5D35BDA7D935E78395E3EA19 +:10D2B000AF5501E37AF5093DB8FFA75490A66394F2 +:10D2C000CE267FF9F2DE59347F36642A61E7DCD856 +:10D2D0007CCF86B2B473F1844FA3EBAE165D350DEF +:10D2E000637DE56FD8BCD6D58516C296D83D877AC2 +:10D2F000F6CDA2F9860CB7BAEF387F1EF0EBAF9AE5 +:10D30000C7B707A2E9E996271D867CD97922E07B79 +:10D3100014DB62EB87F7B29C6C5F87F7E7C23AAC2D +:10D32000DB1EBB9E3BDB85F5AEFED15C1FCBEF3E2B +:10D3300090C5D6637D3D17539E1FC84A60E50DB169 +:10D34000FB5F95E954E59D980BEBB23E0EBC2B328A +:10D3500013118EB73B56AF83FDFB2B51F655452677 +:10D360008343CA64E72BAFF6BED09106F4B09313A3 +:10D37000E11CD95B6EFF14A0BF0DED97D0CF4F57C6 +:10D38000EB3BD2034F66D0F4EEF3CF9D82FA0375E8 +:10D39000C4CF49F1F5C0E10C4D0F68F7A2357DD837 +:10D3A00063077D04FF0BFBAB1404252919D65D79B7 +:10D3B00008CFC5F43A44760FCA3F536F577F43A551 +:10D3C000E7AB476F6EBDEFA937DA4567C1FEF3449F +:10D3D000ECBFAB82B4B7948E7B95D25B2B9D0FF9DB +:10D3E000E0895BF5FA46E38778E3DEA81D78F5E887 +:10D3F000CDD98113CDF36719BE1BB203DFAF7E62B7 +:10D400005FA904F3ECB93596BCD5E4F22F55B918F1 +:10D410004D2F5AFA4B55CE5F098D0FD7670E19E184 +:10D4200059D7648447E38F2BA13607BCAB45479F90 +:10D4300006EBACD9A5A46AE60DBD17120FCE5FAB03 +:10D4400074F2AB66338F72EF2887F1E95F353F9155 +:10D45000182B6E153DFFAB264A0F401F4FF3287F58 +:10D460000AEB379C4C9322F4F87F543CFCA974A837 +:10D47000C9574D9F44B7FFAF4A779A3E9B88EE3C11 +:10D4800071E28F07326C88BF0DBC28C0FED1810CC1 +:10D4900089E589B8C80BF6EB6C76EE9D4AA85C78F6 +:10D4A00057E26AAF03EF8329DDD650215DC72BBD5C +:10D4B000B74DD1AFE3EC4CB61EEB1BDC3B61CBFAB6 +:10D4C0008AC9BF381DD6AF86BDEF71EE7CF2A2745B +:10D4D000DAFE892113BC9045D66DDB6086F9CDCC90 +:10D4E000647A64FDF657D1EEBB59BA5EDF64D4E7C7 +:10D4F0005FCE10553DC1ECF03BA95D00E708E3E1CC +:10D50000A13093E1E19EFAE3284FEFDDCEA13CBDCF +:10D510002593E1E35E3E847299B433FB99D8283EAB +:10D52000A85CBA0493007CFC35C7CE77F30141FFB9 +:10D53000FEC6FD7B562F043B309A3FBEA7E2E92B87 +:10D5400099EA3B84E9C13B33D13F0C70D0DF5B9F4C +:10D5500067F0AEDFBE05CF275FCC50ED6B953F2F58 +:10D56000C23ACD8CCC2F459DDF05C7C836D0179465 +:10D570006F4C78BEE47533C275F5ABDF6C827AE22E +:10D580005417DEF7423B96E6FB9627845A75F13A2C +:10D59000CDAEC9F7337EA8E565835DD890E933D871 +:10D5A000E9D1F6C6FFE80396F6A878FA4BE983C3FB +:10D5B000AA5DF0A7EA834754FE8FD60BA37CBC93E9 +:10D5C000F1F1A5F3FFBE10F2D17CFCADCC8FA69794 +:10D5D000A2F9F74AEFDD48D7CA1222161AFCA39C1B +:10D5E00010F8C1A3F41FF1933838DFF644EF4FA6CB +:10D5F000419CEBD2DED5EB628DFF4416B3B33626E9 +:10D600004A267C1FF2754667D17222BADD285FC4B4 +:10D61000892FD6D6CC41FFF05CCD6DB970EF2DDAF5 +:10D620003F18539F935357817FDCAAFAC7FBACF591 +:10D63000BD31E0F566317CE6178C9C027CBFDFC013 +:10D64000E17D62F8D3DBE9779FF7FF60581A0BEFB3 +:10D65000685EF34FB6B3F1A2C779575DB751FF4487 +:10D66000A1FE09C5F370AD3911CEB16AFEC9B0F2A1 +:10D67000E7F54FDE2423FF300BD6F9686CB81CEABF +:10D68000FCAF08C17D73281C579798FD0AF08B8961 +:10D69000B6D3F925D1EDFEA8CEE7CDED37298FCE53 +:10D6A0001BE3C9F1F86D14AE3F91DFFA84911CE0E1 +:10D6B000FB378F7C70F15198CF1107BE3F16DDCF3D +:10D6C000D7B2CCAA7FE0403ED0F4EF80D0B3F905CA +:10D6D000DAEECD3B32FD3B888E2F08E50BFAFDC21A +:10D6E0001F295FF851BE211FF7F53AEB63F9298333 +:10D6F000AA3F141DB7117BBFD1047EB14CFC167D2F +:10D70000DCE90D75DD7FA1CAA5A22CA63FEFAA5DBD +:10D710002140BCE8FED1781141E7429C9A7D04FC8F +:10D72000CBD7D47B02CAC68498F1DE992A5E278AB9 +:10D730001FACA933FAF577D51AE5C73BA1FC513DDB +:10D740005238CE7E9446BFF1C6BB51FDD117BAB94F +:10D75000FD8089E6F7D9AC1BD31FAB48D33C8C7353 +:10D76000D0F581B496344D7B81C2F3CEA19509608A +:10D7700047FD82906AB4E33FF8EC34BD5D1254F18A +:10D78000FC7EED67EF00727943689A164BFF44C741 +:10D79000697E118A7D2EE32E55AEBEA1DDA7B82B82 +:10D7A000763C7F8B3AEE1B75E3F34D74DCA67699DD +:10D7B00071DE4A16B387DEA86B7304995FCDC6FD90 +:10D7C0001B362EE82DBD5DAA64FD79F4E330C4EF6D +:10D7D000619CED84403CA54F50A6EACF5DA5643323 +:10D7E0003CE4178DBF0FA5EDA768F5A2EDAC9F67D0 +:10D7F0004A867BB3B5CB8C70B569F62D11310E72AC +:10D8000015F4A527A22FEFB4FA1F043A202E09CB56 +:10D810004FA878BFBBFEDF2C307F2A3F3BF01EDBDA +:10D82000599308F2B3EC7CC8A2C7CB851BF4AB2E8E +:10D83000A8F6C2447234BF6804E5DBFB2117DE8F13 +:10D8400078F30BBFB3C4EAB7F67A96E11CF1FA405D +:10D85000ECB88A98258C8B6731CB88BFF5D773F1EC +:10D860005C703CFBFF10C8AF99608F1EE9D0DBFFF6 +:10D870004F6549AAFDAFCA339ED9FDF1E2AF432AF5 +:10D880009D4D147FD5F4B3562F7AFDB5345A5F0EF3 +:10D89000ABFC1C5DEF52D68DD1DDA81D1387EEE2E7 +:10D8A0008DABF91F5ADC37BF98B68FB12F33661C8A +:10D8B000B55EF4386F46ADCF183F224EDC2E299B63 +:10D8C000E13718276E9794CDE2766709D38B4AC863 +:10D8D000897AECCAD17BF781B9F7C0E2CF9D06F512 +:10D8E000D6A8C66BEAEA5F3D057EAAE65744ECF18E +:10D8F000601BEC935DDDC1A1BD113D4EB45DDE0842 +:10D90000EF15822055E307456619E3D4E43176BE6E +:10D91000DFD3BC1AED4B2D3EDD27047624D0EFB7C4 +:10D920006CFFB76DA05F353FFE2D8BFF411667661C +:10D93000F6EE855E17DE73DD3AEAFFF931DE38CAAE +:10D94000FF6AFC71A2F518953771D6632279132FFF +:10D950002EA2A5A3FB2C8254F80A9C4BE512FDBD18 +:10D9600034AD11080F78A859CEA19F5923C84B3167 +:10D97000DEFCAAC90479DF72DF6E3807BFB2DA2293 +:10D98000DBA5C8FE4BE96B0D85AF807F41270C7E80 +:10D99000ECC02FA57F82FBC1AF2FB64BB03F727694 +:10D9A0009E34E8A1F9B3777022D83D558BEF374FFD +:10D9B00083F15671F80E8DB399A8E7B56F5D5E5986 +:10D9C00040C8370044DDBD8F1A6D9F4659BB0FEE2E +:10D9D000CD4E4D1D30B9284ABF7B78ED3E1B85AB3F +:10D9E000A335E085FB78F76597EC83FB786969F2EE +:10D9F000D0026A471DCC9EB11CF2037FA3F557BA33 +:10DA00000FEEDFBD680AFA385AFE83EC65CB79D891 +:10DA10008F98A48DBF1ECBEF5AF2E0B16DB4FFB763 +:10DA20000F6F590E67D7CBEAB4F11F595EC953FA8D +:10DA30009FABE51F4B84BCC74922FB4CB309B144E3 +:10DA4000EEF7E179F781D1FB7C2DCBE1FCF8EBE53A +:10DA50004D95708FB3ECCB1DFB8AA710326B59B973 +:10DA600028D3FCDC9C2F2F77C2FE31A1F448F3723F +:10DA7000CE57107E8FD9A4F61FDA2767033CCA540D +:10DA800028E79467F655BBE13EC2F06920CB879B3F +:10DA90007B6C69867B098A0CA68970A23C9C85E018 +:10DAA000A8FBDAD9E169ECBE9D9A2F62718AD1BCDC +:10DAB00097E50776C4BE7FF2610E935F038ED8E5CB +:10DAC0003D2ADF6BFBAF49E789FC6C0CFEFF3CC4D1 +:10DAD000FD6746F8E914C4433CF8E45C532BECC3FF +:10DAE000DA189CF1F671F7A9E314B426E13B45CBB3 +:10DAF0009A9CF8AECE243F9337948BF89520FFCDB7 +:10DB0000268433D5CCE17B26690E123C4ED3D41447 +:10DB1000F6BEC9328A6A787764E1A4C0513CDF9BC3 +:10DB20009E51D206E7EB5A7FCE831DA6B51F0BA7E9 +:10DB3000B805E04C35D7946C29D6E1AF98C14DD7E4 +:10DB40005D6D277F13DE7B19189A9A0F767565B67F +:10DB50006488CB940DD558E05CEAE51C554E48AC82 +:10DB60007D6A25932B235BD4F72A6CFE12435C5FFE +:10DB70009D7F65E7B22F41BD86210B817388DB8EC7 +:10DB800097E33BFDF1F8BF01CEBBEBF476031FC674 +:10DB900073E60D70DE7D06F4F75301CE37423FE0A9 +:10DBA0001FC0BD0EB09B52DB62AFB716576EB8EE0A +:10DBB00026CA0CFD7786AF48FF1E2C9F685E91FE3B +:10DBC0008CF7F8C6F6A7DEE7D3F0CEAB781762C3C2 +:10DBD000F9AA469714DF261D3DAD52E98B4A3F7CDA +:10DBE000D7F7C2F2E25EFD7B0584EC60E73A78BAD3 +:10DBF0008E604F0E39F07DE0329EC9C7B2A16451EC +:10DC0000E1C6D285B6AE03C94DF83ED1C80A2EE6AC +:10DC1000EF0F9CD7E052EDA7F4BAA079830E3E8DAA +:10DC2000FE23FD0F7D41E38F75C8B77B197C606FC4 +:10DC3000C03CFCE169FA73201AFCB753D981E7496B +:10DC4000DB54FCDFE10AF57211BC8DC57FD604EB15 +:10DC5000998BE5654327059867431C3EFD650E3BA0 +:10DC600027927E3E9C08E703966633FD35D03FC37E +:10DC70007E1BF0C53213E124366FB033CB34F94A42 +:10DC8000DEFB590595AFE9A3792A5F2558875179BD +:10DC90001BB6D922F57F9AF3DEF276AA3F3C567680 +:10DCA0001F8CDA8F36A2BB8768CD61F1DBD9C1D872 +:10DCB000FBD6C3390906B9F5547325799BCE6F6538 +:10DCC00036D3E7B387157C2749E3EB68B95498C38B +:10DCD000D6D197C3ECF18F5F2E7113C8A515AA5C3E +:10DCE00062E5C4136880F234937A2F4164EBBEF18D +:10DCF00047330A210EB7D56B96E09EC34ACE9FF3F9 +:10DD00002D3A4EAD4DEA489022F4514B6C920BF0F7 +:10DD10004D47807BAF35CBEC98873FB03BFEBD874E +:10DD200063F447A4A4DA71EC5A0D9EAD5E01C7DB23 +:10DD3000B8AB3029A887930F3C8BF13DA70AA72DDC +:10DD40004A5FF1C67C5A5AB8D164D695BB98FEEAB0 +:10DD5000F6CAE539605FAAE79BA2EDA27BB23983E0 +:10DD60001CD6ECA2DF79199F50FE45FF319DFA8F3A +:10DD700004EE7BF407F03C183C605488F775D9FB3F +:10DD8000C66F1D2773C14FD2FAB92BA7D8D06FDD4C +:10DD90006ABA489FA4CC69AB942FEBE4D919F57DFE +:10DDA0007A4A0F33815F57E710633B73201BEE9570 +:10DDB0009374AB1FE4CD29217018D757246E58DF18 +:10DDC00085E62D87912ECCC4DD86E7A48E60FBEA24 +:10DDD000BA9152B4533F308741EFFC3C3703E339EB +:10DDE000A94E46B7A7EC4DD88E275232CA1155EE30 +:10DDF000FD3C770ABE7FA1C9CFC87D16AD1F567EF8 +:10DE00008A5B910DEFC49E4A9D5CD2C619ED1DB090 +:10DE10007F22F6D2F3FB6EA7FC38ABBA3F4C61A66B +:10DE200052E5A5E58FD2FA5B7298FE3BE50B0CC07C +:10DE3000B8A7DC4404F8670F079F85FC62AF13DFC7 +:10DE400071D3D623CDC47E1F264DFDFD15E01348AA +:10DE5000C55CC66F8773D93ABEA3E6D31263FF9E33 +:10DE6000CC7FA8F57AE0FE1FADD75D1EFBDEE81E75 +:10DE7000958F1B6D3DD570955E77CF13EF2DF38495 +:10DE8000DA55B4CADE1CD60FD56788AFCACE3AFCC5 +:10DE90003DB1F78756E1BBAEA3BFF301EF54D17597 +:10DEA0000F9395FB01EFC22FCC787EB3C3C2E8522B +:10DEB000700745B88794E28CEDEF7E578527C5CC77 +:10DEC000DEEBD6EE2F58D4FBFCC7547B2CD15B8BFA +:10DED000721DDE58937CF02EDB08DECFD5D631FAEA +:10DEE0003CAE45BDC77FF3F643491CFBA1D4603F60 +:10DEF00068E346DB1117E13D6E5DBC7B9DF7DC42BC +:10DF0000A2ABFF6932DC01FD7D7A5B96212E11CF39 +:10DF1000FEF8912A6FC15E5062C22518BE5FA47ED2 +:10DF2000A0A21FFF0A1B3F32AE9328BA71F7E6C8C2 +:10DF30003FCEC1F8CD5C11DFB1B0133C0F5BA6BE84 +:10DF40005F47F513BE5748F55235C86FCD2F02BE57 +:10DF5000179380AFCBCFE6A4EAF4A4DA2E5A1EDDE5 +:10DF6000A1DA0177A8FA26E9BC66373A248E8BE855 +:10DF70009DB17A8B53EDE868F918AD178C7635A50D +:10DF80005B456F078CE11715AF374F1F93E2D0C782 +:10DF90002D7F11FBB26C6ED03C0DE4663547601FDF +:10DFA00064569551DF3B7299DFE1C8751ACEE1D610 +:10DFB000D419EB25423DE0AB5CE70DF9297A7DC42D +:10DFC0009941EEB1FE36ABF4E07BF7AC00EF372EB3 +:10DFD000C965F650499E9C9A4BD3237FA8EC83DFFA +:10DFE000A11869E549AF07DAC97DC31E98974D04AA +:10DFF0003FB57C6D55D1115A6EF9A905DF9D2427D7 +:10E0000062FBF7AE664EBE8FF273BE2AE71A3C6C17 +:10E010005E0D9EB05040E1C86C60F064F70F72BCBA +:10E020004EEE65D7B37AC5B91683FEF1439EC2772B +:10E030006BAE16BF0CB5C2EFA164D7CB3CE8BBCC2E +:10E040007E8EA8EF6EE27BA9997ED6BFCB1FE2EE53 +:10E050002D8ECCBBCBB4A218F445579AD30FFAE25D +:10E060007379C1329877C3857018D036EBC2100F20 +:10E0700076DFFE3C79167CD7E62799C54CD81F770A +:10E080005E60F0F544D13F21BBD575E965F0B9027A +:10E0900025004F5AA284EF10D1BF7CD0AB69C9AA2A +:10E0A000DE482341782F88D8683DB0831CB49EFE9B +:10E0B000DE260994C23E412875DA74D0730B1DFE2A +:10E0C0009336D0AFD37DD3E15DA1170EC78EA7D70E +:10E0D000AA7A87C27FA71EFE78FC31FADEBA5ACF31 +:10E0E00012C78FD6E8DE591DDB5EA59A00CBCBD7D1 +:10E0F0007AEE86F934B40BF81B5D1ADEF7E70536C5 +:10E10000E6A6C23A1DE1805F33FBCB91AE32159E8D +:10E11000805DD1EEC80DC13BB2EDC99F4A07FCC777 +:10E1200083BBA1D92CDFA7E7E77601D7E348D4F971 +:10E1300035CDCF782C97E9A3D37981AD30FEE613A6 +:10E1400007F09CE083472F09E3BDEB73A378E3EA74 +:10E1500099FFD2B086BD9751BE96473ADCD42EE0E7 +:10E16000BBEA0DCF1E0FE37EF17682FBA00DFDC74B +:10E170004FC33BAD590DF24CFDEF126435B077E360 +:10E18000D212467F1F5400BD9DD9BFA201E95A2477 +:10E1900022413A0AA2DD956D63F6A886DFD34238A4 +:10E1A00017E267A74DC4DF46CBAF59942289E6AF8B +:10E1B000F91C7E787FE1EF8FBF213D067886B81885 +:10E1C000BC7B9017FC12E0A3BB959D27EF5E48ED4A +:10E1D0001E5A6FA1936C85FCC2361701FEB8513CE4 +:10E1E000CC8AA28B59DB199FFC283751E55782EF67 +:10E1F000291DCF4D50EDA8601DDAAF741E9D731020 +:10E200002E9C87982B7F15E9564CC671331BC29CF8 +:10E21000FEFE899646E84A7E3637F566E0ECC77D15 +:10E22000C64DAA9C295F7B947B5B47072FE69A919A +:10E230006E329F3DC2817F48CB5B177AB03EC607E6 +:10E24000339F657ED3265A7EBF41AE6CC0F97439C8 +:10E2500098FD48E5CA4980EB94690BBEEF776A3AAE +:10E26000C17766EFB8103E8DE25985F794C0D6931A +:10E27000A77868A5F99FE54A38FE6921781FACFBAD +:10E28000E94C76BFBBCBB403DF3BD5F83E9A4F7F5A +:10E2900096CBFCC9CC3547398827789CCC9ED4E0F6 +:10E2A000D3EA95E4559C05FCCEAA1E423C34AEE16F +:10E2B000D97D0D159E8542A000FCB461B5BF93AB1E +:10E2C000BF6D3E44E16B2CE6909E9FFCBB57912EA8 +:10E2D0001B7B38F6BB413DAF0AAB74FED5C1EFBD29 +:10E2E0008A7A65E9008B1F340E1CE7EF7581BE3911 +:10E2F00089F4D948E9CF5E0AEBC6ECD86B96702E4C +:10E30000E8CB68FA745633B90831D742F60E1CEEE2 +:10E31000FF86D6DAD0EED7E4AFA8C209EF08827C38 +:10E32000FD8DCAEF5AFF117FD5EE07FAF6BD3BFD12 +:10E3300024BCEBD6E8E7FC701EF93F46F50993D7FD +:10E340005222FC7660A4FF68FCE5E631F91A438F9F +:10E350007C184B8F687AD6F77405BE97ACAD1FAFAB +:10E36000E27D54BFE7B1FB578979BC0A8FEC853851 +:10E37000B644F9B9BB14DEF50B144B809F54A71FAC +:10E38000E23B7FEF7E5DDAA0C3D76981F23BCD9F90 +:10E39000CE77203C942F92F274EBD750CC7E67EA74 +:10E3A000C9EFAE40BC36C0DA51BC3604EFBB0FF14A +:10E3B000EC25E231902F4126BF1AD6DCC5DE05D709 +:10E3C000F4DF731CE2BF4171E13BD74BFB57207D6B +:10E3D000128FDD5FC8A15CC375D6F84CCCD5F61D95 +:10E3E000D8BB43D4AF6F857889E6D727D605940488 +:10E3F000692C9FA6A87EFD4CD5AFB7CCB6FD59FDC4 +:10E40000FA4DCD3F41FFE721EF8F30D5F884FA8DEB +:10E41000067EBA2D8FD92D929A56E431BEDC54DA9D +:10E420008FF4BFE97213F28FAB9AC911D705A3FC21 +:10E43000D3E260D4836374E8EC5F04FB110BBFC2CA +:10E44000892007E2C1FD19AEE967705E851C67E7A8 +:10E4500028167CF0F344FD3BA435798CBEAFF599CA +:10E460004918F0CD3709E3D9BFF1FACB0957CDF9F7 +:10E4700027BA7EFFD29784E782AE3DBBF2F3905776 +:10E480008E26E139929C702DD2C535CF1C3FD081AC +:10E49000A78DE1E95A7F25D2CFBBE99209DE096B4E +:10E4A000ED7F623EFC5E74BD0AD7BBDF3537031ECD +:10E4B000767CED3BF3E15DC94D212E05EE9B5DEBD6 +:10E4C000FBCA1F41EFD51F7D18CF7DB57DF37FA11E +:10E4D000DD6D0A1D61DFFB9244A877F59903F30116 +:10E4E000BF6DFD6D58FEEE3347307FF26BDF311F9D +:10E4F0002A8DD0F1BBDF3DF2C3DF433E9088F77237 +:10E500001A824F3E0E79529BC8EE5D055F11F4BF33 +:10E51000DF75F0F820F2A146174BFB39F5DD30012D +:10E52000CF7968F4FB56457119F01DA550BF793EAF +:10E53000CD7727D4C78A23EE51E7DB00B408E3AEDA +:10E54000E142C0075D82D287F25CECCF0579EE2C08 +:10E550000E0BF02EE9EABAE3F3D9CF10B662F94A0E +:10E560001B3B2F368DF20BBC1F457B3BFA21C4F7BA +:10E57000BA1E5C07FD1D3613D19C118177B320A113 +:10E580007FB4B986F3530E231CD9762A15F6C79AA1 +:10E59000897AAE8BD5EBA2EEA52D19F510B1D3B4C7 +:10E5A0006C5BEC38E893792E953E19BF660EACC8CB +:10E5B00006F9413C567FA12FD25FCEF9A66E78DED8 +:10E5C0003FB37E6811CC6349D18619300F0FC4FB6D +:10E5D00040BF282EECBF11E293949FBEAACAC73455 +:10E5E0003180EF8CD8E4402AFC269B640DE0396E24 +:10E5F000697DC0D20A72861FC95D858AF09861FF65 +:10E60000F0A025983113FAEB52F5D351063F6D8FE8 +:10E61000FD4995B207DAD3FEB13F5B9DCCE36FBEF7 +:10E62000D9D83AFCEB0F6E3F668C9787C6F45FEA49 +:10E6300002FDA2ACC17593049CEFBB5015F1ADDC9B +:10E64000AA8F6347C77B409EC17EEFE9BCF2C1BC85 +:10E65000D448AAC581A2F1CC4BB49CF65321C998E9 +:10E6600092BE1BBB77A6C9EDCD7B54BDFBE22594C2 +:10E670003B9B833CD3BBC1CBA877FFA545266F53FB +:10E68000C3F2E0F39790BEEF3DC1F4EEE61325022E +:10E69000D0B3F61EF2E68A6BA87F153341BADE2CA2 +:10E6A000F49FF642FFDDC44D2D7BB279FEF02D20A4 +:10E6B000FF7EFDBC7D0DB43F653221BD9DEAFDC4EA +:10E6C00091364E0F1FF303B8FA10F2E366D52E28E9 +:10E6D0005F7BDF01F0C71AEBD9EF116C1E50F98B8D +:10E6E000FA6380DFCD275E45FAD1EC5EDFD3354893 +:10E6F0006F6E4A6FF8BB095543081FFDF317D2D45C +:10E700005DC5DEC55D52545206F47672F50F778210 +:10E71000DEDE5C4544E8FF608EFC3CBEFFFB3C87D0 +:10E72000EF511EB4F454C03DC9830B2511F8637337 +:10E73000B076543FE1F9EA60ED00F28F679D1FEC7F +:10E7400087EED620DAD5DD194EB40B0E3EDF8AFAFD +:10E7500073B3E4F0C3EF992C3DC16DC5F68A8B30DD +:10E76000F839B4F397866EC3735B1A3E96560DE77D +:10E770003279C1E0FEB565E8D330EF5F7FCF0A6F35 +:10E780007E8FD2DFFF05D640AE560080000000002D +:10E790001F8B080000000000000BDD7D0B7854D5B6 +:10E7A000B5F03A73CE3C1226939327E1E9C90308EA +:10E7B00098841308EF872704102BB583F2B2220E3A +:10E7C000C823424846C48AD77E37830331526F6FCD +:10E7D000AC2FEAA576A06AD12B106DAC51030DA821 +:10E7E00014ABB5D1528A16BDA3222F918CE083DEE3 +:10E7F000D2F2AFB5F639C9CC640262EDFFF9FFE998 +:10E800005737FBECF7DAEBBDD7DE9336D9BFF18E85 +:10E8100032802BD561BAAC03A42B6DBE3B3201D242 +:10E8200000F435986FB07B9D3A9647FE430A6DCE53 +:10E83000C5EFD3C0081501E4DF23192137408A262C +:10E840000164516A335307C008C0BF0691AA811200 +:10E850006F31C027B5067C3800F84FCB0658CEFF85 +:10E860000058B1A8D5A1617F554F89FE329D46E978 +:10E870002D989EA3BFCB305F013778B13C4B966E8D +:10E8800098C1A98D53ABDC4A8799F3C87D64E1BD7B +:10E890005370FEDFA9043D0987E85D88DF310F7EF4 +:10E8A000080DC0F9F7AEF4F6D5A83C73A92E633E67 +:10E8B0002B03BE4FE591350ED82C75ED7724AD6B4B +:10E8C00004D5F39649582FAB678A1EA4A1E4725B66 +:10E8D00012B52B95F4CD1AE5AF7E14084E59BD74D0 +:10E8E000EA072064C2C15B66C37A47B353F4F5F408 +:10E8F0003DF407E56A84C7244DB5CA4BA99DE601DE +:10E90000585FDAD96E4ABE97FB9BD233490FE23C7F +:10E91000A737044A204FC0C1EBEE8443684DF2DCB8 +:10E9200050143CC6131CB07D6830CC6D2C22F87B93 +:10E93000ABA89F6C9B9EB11E3715DC81926B526811 +:10E940009C20C36B00CD03D329B83E3FF59BEF5D00 +:10E95000C5F0C84AD113C163CF25021EBBE76C9333 +:10E960003760BDEA2229E4C4F9DDFFE28C525A6720 +:10E97000F54CB70E98AFF6290B695C08B8E031CCBE +:10E98000836FD1BD53305F5DE9D5D76BBCEE455485 +:10E99000DE3733495F8FE50F3E2F1994AF0EB84332 +:10E9A0004998BFB259E04375F3D3CA8D98F620BC9D +:10E9B0007353BB40C98CE2CEF900ACE1F9544F3A35 +:10E9C000D1FF656C1F9041972762DE111EA8E3FA04 +:10E9D000AB27860712BC4E3E9F3497DABF62B30561 +:10E9E000689C57365FBA292875EDE7A4DDDB44EB58 +:10E9F0003F89EB0F60F96F9FFF7388E8612DD28329 +:10EA00009C837BB4462BA7F2F55340A57DB1F66BF2 +:10EA10008F23504878B5272F99F183E6E945381FB1 +:10EA2000A77FF602B8F5126F8D8670AEB6B5D629FF +:10EA3000D46E4B06C018CCBF70F7409FBB2B9CB167 +:10EA40003DEF8B4B01C65F57A847281885572E17F7 +:10EA5000D2DA304E036E4C7BAC16F089EFE74ECD28 +:10EA6000CDFDAC7085F7E0CE41CDEA065736E29198 +:10EA70002F59E3EF49F680D107E7E3682E6FED8366 +:10EA8000E5D9E9F81FDAB7CD3D42B46FD9D9E07BBB +:10EA90002641BFAB4C3CB3F6A5211D182FB33DA2B8 +:10EAA000FECF4DBAF98949975BCC348A2E62F1DEEC +:10EAB000EDCB253E919D0CBEC604E359ED717E5C05 +:10EAC0006ECD0B5CD84F26B5D36C8CDF717417CA32 +:10EAD0002A1E4674372559DFED227A1A963B2C08F8 +:10EAE0009DE320247267A474C5035A07D10FAD8B30 +:10EAF000E8ACBB7A0DBB047F8AC7CB674C3AA9222E +:10EB00005CC7796F93901E13EEB3E8A7DE966B7B1C +:10EB100010E7FBA3FD32F3D9F87A56BAAB16A0750D +:10EB20001040DEC66B53BDC5DDD7DB66D6FB71ADCD +:10EB30008B53B7AEAD51B0FFA12D5AA90C349E3600 +:10EB400089C60BE078B4CF2913E15319E1E319DD4D +:10EB50005078672EE179E35C5AD750256C2B25BE9F +:10EB6000EBB5416BA1E0DFE7F0FF3DE72643ABAB40 +:10EB700033DFCB971E93EF53D93BA67E3F7F5E4C8E +:10EB8000F925AB87C494E70686C5E4F3EBC7C6D482 +:10EB90001FD03029263F68C37762EA0F0E5D1D93B0 +:10EBA000BF74CBF763EA17372E8C299FF48FFCDDF7 +:10EBB0003F253CA7F527E073561AD17279FF8636B8 +:10EBC000C7AE3F7574ECFA158800D1FBA4E4BFEA28 +:10EBD00089E8D94A5341F92C6CB5233EE0D26C0F39 +:10EBE000E23CCAFF2C87D627988785CF567E922293 +:10EBF000C78C6BF1890BE1579EEFFCF8F263C217EB +:10EC0000E779E6FD0F39215DAAB9820F28E0E5F525 +:10EC1000A74E9C7BDEF5DBE3D70F1AE3BD87D69FBB +:10EC200000EFE3D79F3A3A761FACF5E7F90637874E +:10EC3000B19FCFE74A2C5FF651D198AEFDBD1BB70F +:10EC4000CED9AB52599F01EF3509EB77CEE34E9EFB +:10EC5000C7F54EF02782C374130E95B982DE2F4498 +:10EC60009FEF9BF3F81FA24F4CDD6B73991E619FC2 +:10EC70001C1A805D2DAC9776F544BC48F7B9592F26 +:10EC80005BA8B44269949CBFDFA4EF074DFADE5045 +:10EC9000AB723F0FD7E670BAB156E3EF8FD416725E +:10ECA0001AAAD5F9FBE6DAD19C3E8AFA18A58FD7C5 +:10ECB0004EE3744BAD97EB3D593B97D3A76A7DFC70 +:10ECC000DDDA9FEBCDFD016F06CBB3F8F5CC5F9598 +:10ECD000182F412EE2F6F391CEE4F3F0B52EEDE5D8 +:10ECE00079A9E7C3A3D50773B7BF1C8507D7E5A6E6 +:10ECF000641EEE81FF1805A3CEC9176EFF65ADB681 +:10ED0000FD65FB85E9C2C21738FBE18044F5AEA77B +:10ED100031C722BFC9DDDC1070770F9F4E3C8AC31C +:10ED2000572FE22B7E2D21D9DE8BCAC3BDA3C7F995 +:10ED300093B9CF567EE64C81AFF1FDDE6FE2DF2C5A +:10ED4000C24F2C9F1D47AFA77385FC3C9D2BF4F44D +:10ED5000FDDDF08B7B726DA6FC14FB3E6B9FE04BE0 +:10ED600077F6983FC197605C294F8BA1CFD9336369 +:10ED7000F771BF5DF0B7FD7F92436B12ECFF85DA50 +:10ED80005BEB896FF72773BD9FFE7F466FFBAF4D2F +:10ED9000617D7EBFDDD72F2B6A7FF65FDB636EA2BE +:10EDA0007DFFDF5CBBD8AF421548BE433A18A407CD +:10EDB000E192020ED2E5A0403D4C7482C610D145CE +:10EDC000F778A9C0618B9E64826712EBE39FCF4CFA +:10EDD000E1FD079F6A4054FFA0A8AC976EFB2EEAA6 +:10EDE0000A349E82E3A11E0ABAAD73FFF2E8BFC9DE +:10EDF0009DFC5AEE9EDE2E8407161F994D7CE43C46 +:10EE0000F2BA6BBB8BE32387888F5CFACDF3118B4F +:10EE10008EE1EC8D03BC295DCB67111FE90DF0D3AA +:10EE2000DCB7998F7C6D3859746BEA13F1FCA4DB65 +:10EE300076CD9917907F263F57FCF561C48BDBE4B4 +:10EE40009486F5D8E42EC5FF73CA07020A3C86A94A +:10EE500073F5E9DE878673B7850AD71BC2F69D5323 +:10EE6000F1FF32CCF6A053A57A0FF5F8F7ED945FD9 +:10EE70008D1CD389E99749FD4380B640699EE03FE8 +:10EE8000B2EB4CEF4351F3B3ABD0273A5FDAEAEA87 +:10EE900073286ADF86EF5563F223DA7262EA8F3AEB +:10EEA000A0C5948F0917C6948F3BAAC7E427444690 +:10EEB000C7D4BFEC8C11932F872B62EA57B866C476 +:10EEC000E4A7A8D7C6D4BF3C67414CF915DA4DB1C9 +:10EED000FD157887E7E1BA173ADCF5522ADA69B905 +:10EEE0004619E59393ABFD0BC84E5AE3516122D509 +:10EEF0000E85086E750E97BA1EF9D40792D11F10B1 +:10EF00004FEFB3A1D59D8FF5E530507AD0A697523B +:10EF10009A676CF1119D6E2F4CD6681F920702B450 +:10EF2000919C52F424407EE2E811F95D01EDCB6F33 +:10EF30006CF01826DB5554F4A97E736688ECDFACC0 +:10EF400064DF15348FF5B606CF1ADA671B781FCB4E +:10EF500064BCFAC968CC1F7E41B1119E6D6FB1DDF2 +:10EF60003316F39F61F7329637B59DF8C995981F10 +:10EF7000DA66D7A9F65090D94E5CAEC03D4A7AF712 +:10EF800078F6F10F843D15FFFD677982DF6755083C +:10EF90003B33BEFC8E3C21DF3E76242E5F6EB6AF47 +:10EFA000B86BFA43C4D7EC6D7620BFC5AA2CA32753 +:10EFB0009C4F5F3D930FA1E15179C50BAA9BBE0FFA +:10EFC000E4EF1577CD83B05BF4437EAC5549464FF3 +:10EFD000F23B7C3C29F13C6E31E7613FD3A39B7E41 +:10EFE0003DFCFDE3BCF3AFD37E2609421989DABBB1 +:10EFF000F97B563071FB7BCCF13F4E4F5C5EDFD12D +:10F000007F2F086444B7137CA7739CBE5C6E3F934C +:10F01000068184EBC8E4EF9063E410DEEC423A270B +:10F020007E519E96ED0024F1F91079C540F8CF206D +:10F030009300F1145C7A29F12950EC91B04517281E +:10F040003F1680F201D90B3644C67338B51B56DB28 +:10F050003F0847D1D10C23360F543F4ADE7C427D16 +:10F06000E37A928714A612BE9F022D554D805F56FB +:10F070003ACF257B95A8F51CEC464F6A33E178B072 +:10F080005762383E6FF2B191F320A1BED696E711D8 +:10F090007659A1DEF37C7283E0EBCB88EE377E1FDE +:10F0A00032B9FCABC219F182E57AE4BBEE10FB2960 +:10F0B000BF71785BF8DD27062F3EC98F9F777F2EC3 +:10F0C0002FE8EB7D2B8FE58A3690E4629349BF4DA4 +:10F0D0008AD163989BF8185426827F9F7C534F8D6A +:10F0E0005B771318390BC8AFA1D875E267C932F83E +:10F0F0009F4E00FFF875A79AF3C6F6735BA93D789B +:10F1000074C1E7C0EBCA463D9FFE854B280FBC6922 +:10F11000A7FEE7F93DFA7A54813ECF13FAF40208CC +:10F12000DB890F77819F3BD34E7EDB78387A419B1A +:10F130002FE55F189EE905C6E7041F9B4BCDDE8ACD +:10F14000EB9C1FF000F9696E98079E629C8FEFBBE5 +:10F15000E96F185877E155434AD6527AE9F83A9957 +:10F160005B4F66BD4F0AF491CF5DFAD5F5BE3A8F7D +:10F17000AF90E8E390A42D61384808079237BD8F1F +:10F180000F5C1005C715FDCA7F9F9F45E7036064AC +:10F1900090BF788793FD56B001580FADD9397813D9 +:10F1A000C9852FF27DAF51BD51934DFFAD11197837 +:10F1B00075CAC5C30BFFEC44271782976CD2FB417D +:10F1C0004F62BC19972FF6EBABD24B66BE8043045F +:10F1D000E1B0B9EC9BA717845F0CFF782D5FF05F5F +:10F1E0002BB5E0366A5AAC7FF735731DAFE57B3837 +:10F1F000FD22DFCB706EEFF7E9E12492FF0E5C7F1A +:10F2000002BCF7764337DDADBF3B7AF9A6F8F2C111 +:10F21000E4C4F35CFC2D99E71B344FE2F32589E746 +:10F22000F96F17894FB83F4B5CF9DFFC3CBFC8371B +:10F23000DEC8A779A6279EE74F2F129EC8EC96B48A +:10F2400062BDD9C807A9DE373D5F082C984272E835 +:10F250001A9FF0FF1723C7253E845379F4DC70D240 +:10F260006FF5751B88EFACF4E80195F9C81BF982BE +:10F270000F8281F399394D627F52FB884F97288422 +:10F28000EFD9D09A46FC6AA793FDD9F1EB0F99EB21 +:10F29000473A799CE004D32303899F1C1C98984F1C +:10F2A0003C1E5FBF3EC2F2697D7962FD749B49AF2F +:10F2B0002B5C0DD3B26DD1E72BB84099B86CC0E888 +:10F2C00043F2B64C5D4BFCC4817289E0EAE833A49A +:10F2D00027ED07E6BD12F981735E3F207918DE271E +:10F2E0003AE097D739CEF1DABD6A81BD7B7EBE5C4C +:10F2F0007E66A43FC17AB66ABE5DF95176E3F22D0F +:10F30000AFAA05D1FE7108DB800547C4E6E5F341ED +:10F31000D36FD0132ECA6F509C29E865453F2FCB81 +:10F3200007921B643FD7BD30A6943617F50F20FB1C +:10F33000209292CCF222D87B6CA11605CF0FF32D30 +:10F34000FD53EE46AF74C47C7FB7D685266567FE55 +:10F35000FAA3FBA6903E3F1FC2EBA8FEFC553DE87A +:10F3600008B2639D1DFD9D9162F4DBCEFE15FE5E2D +:10F37000EE72B7CA433175FF2EE17E6CD58CA304C3 +:10F38000CFB5FD8C63B4CE78F805EE1A9FC67E0427 +:10F3900082DF655DF7BDBB7DFEAB669CA6FE5EE8C9 +:10F3A000A75A7E1D9DCFE392ADF361453DECEA8403 +:10F3B000F757DD9764D3BF88FAC4399AB701557EF1 +:10F3C0009ACF3C8BBEE3F41C2814FE803A4FDBBA84 +:10F3D0005D517478832D9225E476781D3999FE6706 +:10F3E0004712F38FF61DBFEDE7E3F3344BEFE8214F +:10F3F0009FEBF1D5E767F917ECC989F569EB1C6359 +:10F40000B7BDA880F5123AE71D8D79495B44F6AA8D +:10F41000A2821EC4F5955F8ED884FD4D92FBB68402 +:10F42000711D9FC3D9E40998FE2788F5AF7AF3A32D +:10F4300074F2634E52ECC7A3F953BC1F684041AC51 +:10F440003FF914CC4B6D25B88C4F67B86C6F99940D +:10F450004AFD943C3FB927A5BB6AEB55C5DEE90FD1 +:10F460008A9F7F793776E9B002A177BE9E6C0C2B1C +:10F47000C0B4BC9BF58F32EB85938D5105599DFD32 +:10F4800051FD44F1106D832C3FAE80EB358105AC0E +:10F490006FD95CC857897FA2FE2AABE4272CB03312 +:10F4A000BD1BA0A9D9EC3714FB8F7C5DC1FC0433D4 +:10F4B0002FD5BF1DA4761B6FF1F03938F83420F931 +:10F4C0008080E173813AC9CF7E0717C57D60BA5E3F +:10F4D000D237902E26DB2219822E4222AE017C0AE0 +:10F4E000E57F2B85831427B0D6F5EF3F273FB81172 +:10F4F00054206922E615603F63E0600A9FCBF1CC9F +:10F50000701E4E6B5E663EC5CCB7CF9A3A6D00A6B4 +:10F51000B7253FE2213C0D4BC847B19F2F93FFBD5C +:10F5200095E9C69FACDB7B937FE93DCE4B2B937572 +:10F530002987FC4F9E42D2535743B2EEC4710C77D9 +:10F540007180C67568C0FEF86468E475B8DD9F0414 +:10F5500008282AA812DB4FC9BE65056CAF009F932F +:10F560001F7E2F6533AD3F493DD57A077ECA0083A4 +:10F57000EB65C4C9C72CF72A89E337BC4A9C5CF405 +:10F580004904FF9E73E3BFC7CA4B171C54899F48A9 +:10F59000ADDE9C73C89FDA086E659D706B53845D09 +:10F5A00067C12D30C9FF4B826BE04EA71ACCECDE51 +:10F5B000DF86001A45FA789BBA642BD547C3096CDD +:10F5C000D45F8E585FA0D229F641F16DA5F6EFD831 +:10F5D0007354B27B2C3C7B68A0C9AFBBF1773C5025 +:10F5E00020F4A3EAF4C3D524E70007B5F50738995A +:10F5F000727424F10D9497F5242F93EC06C3DB92DB +:10F600009B2B9AD600D15575F30220BEF28EE41BD7 +:10F61000F032DB23C076D99C6981576C1AF9B26647 +:10F62000AE7363FA49411EE3D7FE57A6BEC26C48CB +:10F63000761753BBD2CBBC53B270DC6031E8776233 +:10F64000BD60926FEBB3B4AE3765FD318DE2212A18 +:10F65000E0C3E12632E1F74DB333D86F9A5911A9CF +:10F66000A37881C8DDA0527C4F17FA388BEB1B09B9 +:10F67000F00B1E0BFB59A4B612FEF4427C93D4CEC1 +:10F68000F247A93C5FE42FC37C8DD852C86F29FF95 +:10F69000DE0882479B0C141655D322D968FCFC99CE +:10F6A000C359AF29A0F2CCE8F2B4E54F61BE60EED9 +:10F6B000049DC849B3F97E762B95BF01BC0E30F985 +:10F6C000F7A838FA1DD749375C5EDA91F757D07C36 +:10F6D0005FB919D88EAD31E56D0CBDD162B1CC18D2 +:10F6E00049F8D7D10F503F15667E9CA2723F7DFD31 +:10F6F00060F205EFC607F89CC0A6937FB24E6A6021 +:10F70000F840C0CFFA1EC5CD10BDF49FB76BB79DB2 +:10F7100006CB1474A7EF157457065E99E03552BDF9 +:10F720003B48E3CF9997CB7C66CC5160B830E5611C +:10F730007E429AC4FB943F209FF165BC4BAF97116A +:10F740008F64B9343F09C79B3B4FE2F38959735D1E +:10F750002109FF390BE983E3A1145FEE6CC4F7398B +:10F760003E499CFB627E5E943F1EB5613E379BED39 +:10F7700004FFD309F0397F80C077AB7DCD5A478C29 +:10F780007FE792016EE1E71830F59302E6BF22AE03 +:10F79000252BD91B117CA381F9D4611BEADFA4FFBF +:10F7A00082C1FAF63526BD5BFC6296710BDBC1B3F4 +:10F7B000BCB17AF43BB4274407D74AACE7CE997B77 +:10F7C0007E3DFB5C8164C6DDF455599E99DF35D0E2 +:10F7D000D89EBE9AF49C12FC380DF59028FD7EDE72 +:10F7E0006D67D3B87ECFC7579CBB0451A152F09729 +:10F7F0001A8427F1CBF26B15A697EAB50E8EFFAAF5 +:10F80000695E63CF267CFE21E8025FDFAFEB83F306 +:10F81000EC53658C90B528BF4D554822BACE269E34 +:10F82000C3F08F38C82F37DBA157D1BA66A7831A28 +:10F830004843BCBCF68A8DD4FF5A17A832CADBDE17 +:10F840002D6F8608AF9095EB849388391CD7D657D7 +:10F85000EDC1E70BF5B6611CB755EF49D1A3E3A4A1 +:10F86000D6AFE9C43B8AD7D29C304C35F737919D4F +:10F87000346480E0570F4AC0F22270AD8BE19C9552 +:10F880002FE295B2527547308DF88D66D5E338BBBF +:10F8900007EDBE5EC3310DA15A29F647B48BA7FB15 +:10F8A000AC0CB39F1E9A1444629CD9525A6623B87A +:10F8B000B953748A4FB4FAAD4836ECC4B72A8648B7 +:10F8C00023820CCF4DCA22D24F9362F9BEDD2EF6B1 +:10F8D00005DE157C3F5E0EA21C60BE4F7EFB6019EC +:10F8E000CBAF8A01592C0FB89FD58A4B75EAD0450A +:10F8F0009E657A2185FC5CC31064A4AFB7E5786788 +:10F9000050FC5EE07585FD6A6573F5EB1647EDEB1F +:10F91000E60E391099CFF1503FD4FB503CD4DAF2C7 +:10F92000CE3CC53D56428383F0BD324E3E2E73BF62 +:10F93000CC7AE4B247ED9DF80B1427AAE713FFA891 +:10F940007AAA8B3F88F954273F8BB32F417D89D604 +:10F950003302F931F121A3204566FF32CC13721432 +:10F960001E97C82F267B56D793DC6B97521AE4B2AA +:10F970004E3E39C2DCAFBB14EF4B141F1B407DE978 +:10F980003115BACA01F0B3FE3211E526E9D152CBE6 +:10F990001C99C6DDB814FBA6F37C255C41F9DB9607 +:10F9A0008A735208DCCCE760E3024E95E8FFCBE4B3 +:10F9B000FE6BCD71FD7664D6C7D41F727F80FB428B +:10F9C0007A8B44FC10CB7B4FC3A64807E35A8E705A +:10F9D0007F1B33045DC4EB312FDBDC219B8DF86E84 +:10F9E00080E54E128472087E4681E0B36507049F6D +:10F9F0007D2E801AB44CAAACFF9AE9B9AC0772F913 +:10FA0000D80870FCCC0EF0559BFACE5D034650B47E +:10FA1000A85FF071535FB0F4B82971FB78B9FB7E31 +:10FA200085F8D6E5395DF64BA6FEA781C4FAE21546 +:10FA3000DAF9F99661F12588E54BB97096F70FEE82 +:10FA4000DE732BF90982717A50F022F5A05EB9BEFF +:10FA50005FD0FAE2F5A1EEE2299F1A7071F194A845 +:10FA600041CC27F935D6B2B3E2F0A77ACFF1F9F756 +:10FA70004027DE75E07360D375B40E94E72AD97D14 +:10FA8000D26F1E62BA5E8BF5E4F104CD83C1FFC272 +:10FA90007CAB0DFC14AF003EF534E1A92577911342 +:10FAA000319ED42D1678374A11F9BEA8C8125E06C9 +:10FAB00047C7EBEBBE5CF2471B65C51C1F6BC9E378 +:10FAC000E13683F16404E81954CFC2939161518EF9 +:10FAD000F8F11AF19371D3105FF228CE76541FD249 +:10FAE000BBCA4163FC288F936B15EE990AD17985C7 +:10FAF0002B7EFF0D3E779C6CE2C714F5EBE1C7252A +:10FB0000841F96DC423DF9AE38FBE2AE38FBE22BB7 +:10FB1000E0C7918BC18FC845E247BBFD87EF05CA9F +:10FB2000D89EF5CBFDBBE287D472DB927B88DE8367 +:10FB30002940FBFE74925AE1C679D6548AB8F3E1A3 +:10FB4000BF2F08523E7B452EEB854FA7E92F71B999 +:10FB50005F9497B519720AE6F3576139E69FCEF5BF +:10FB60005650BE66359663FD11FB7C41CA17FC50AA +:10FB70009497DEE97F2985E47C40B47FE1589DECD1 +:10FB8000C1F2509DD9BEBCA182F235F5A2FDC803D9 +:10FB9000A120E507DF23C6B7F4CECB4CFEF9B47441 +:10FBA000EAA5DBA93FE49F9B917F8E3B61946EC3E6 +:10FBB000FC22D56623BC5D1C09D8091F0EDBAA46B2 +:10FBC00012FEC0425F0EE19993EC56B9937FD9C8FB +:10FBD000A983ED262A76D6FB5E95FC0AD59B4624A2 +:10FBE000417276B4EE22FE4EF1C89B51DE1499F2BA +:10FBF000C88ADFA57B0433A2F6AB68A090F356BD9C +:10FC0000EC748117F0B0C00B2BBEB8F52190C8DFA3 +:10FC1000426B633F449778633FCBEF50BFE2618410 +:10FC2000B797539C31965F3E56C419979E3B3D351E +:10FC3000915D347CA0B0E78F9AF722ACEF95A15C80 +:10FC40001BD1CFD3843CBD099EDA1F495F7A9AC687 +:10FC50001ACB200DC068DA47912F7FBCEF7DF57D70 +:10FC60000196DAFC0AE111F497749AFF556DFEC90A +:10FC7000BC9E2A80EFF54AB00E53DE2F093A368B30 +:10FC80003811C17F6699FB764C9DF7CAED6C3F7BBE +:10FC9000743B8E3369FC00A6FB9973258BEEBF3352 +:10FCA00090F4603AC1607FB68FE3DD6F8290830687 +:10FCB000B9298EEE97BB3F7B8FE4D2F22DB174BD94 +:10FCC000025A1DC2DF1C79E46DECBF72438A4AF20E +:10FCD0006745636CBDCA0DBF3F209574E50395165B +:10FCE0001F08C5F2015438041F7868089F7FADCC07 +:10FCF00091B54319E4FFF0B3BC4F0221EFEF52F48A +:10FD000030D35F8B53D851A67E7E9B2CF4F32470A6 +:10FD100069EE42E2C336335E55E4ADF1212ECEE505 +:10FD200054C3CDCC6FAC78180420CBFB5381CBD51A +:10FD3000683F5B079F8FA3F7D2969EAD74DFC0F23A +:10FD4000B3A07EC0F6152C424E378EF910EF9BB44F +:10FD50000CFF3F86D6E5E0753DD4A33FF3F7D548C9 +:10FD600010CE52B28B95E256EA7388A02717D111B4 +:10FD7000F1F769B1F65612083D7E789BF0E38CE806 +:10FD800094FB75B4BF4ED05D42EE3700D157B7F645 +:10FD90008A7B55427B852514F63F7B9AE0EB17B2B0 +:10FDA00057BAB3473AF63309F5364C67FA92B6D3E9 +:10FDB000BA2F3B9B9A92289E6A66B9EC25BB6CA62B +:10FDC000DDC84A4FA0E73F60EAD91DF57D6EEE4FD2 +:10FDD000F1656CA7F825ECB795F87FDBEB8E8471A5 +:10FDE000C98AD9BF6237D444FD5F454EA9287FBB7D +:10FDF000E2CBE67EBF017DE579DA977879E4D81D1C +:10FE0000774E098181D171054F0F12FC6E4281F14D +:10FE10009B81744E94D49FF99D568AF6541FCE73DD +:10FE20007F076FBE9CE3243E03E38271126BA3FC49 +:10FE3000E707D3129F8BBC61F2D7148A7DC3F47697 +:10FE4000CDF8038D7FD421CE5D8E269BA9479C5B88 +:10FE5000BDD3515FF0C788C5276DA2FC687AEC79E5 +:10FE60008D55EF94D9EE50ADCBBB36CAFFAA3DE419 +:10FE7000F4939CCECA37EF71AC02B69FDB9F4FDB89 +:10FE800014BDAF670796A70CA2F8A27CC3D18BE084 +:10FE9000F8BC907FD54AD841FBFBF025BEA334EFD8 +:10FEA0006A0D8C67A81F2DECB8A698EC06111FD21E +:10FEB0006E1776607B9248AD799D1D382365109D45 +:10FEC000CBDE1C66BED8919F1166BE7776A097C721 +:10FED0006D9F65959BF9FF10790D549DE65BEE32A1 +:10FEE000ED8742752DFB5D51EF23BF4DFCF901C03D +:10FEF00078A11F9BF19E46DFBFF3395E777E7E9B24 +:10FF0000ABED95FFC2EFF34D7FB0AFF9D357EED015 +:10FF1000187F0ED3B80B4249C071DFFFA45FBFBD8D +:10FF20005F1BAF677D79A4FFC3651C2FC07EB5152D +:10FF30002DBF65BEBEC2A2FBA658BAEF65C2F14294 +:10FF4000E76AF1E72DDF009D0D1C9440EFFB35C9FA +:10FF50006BC4AF29F274E66BA79A24F68768D05673 +:10FF600047705E29897D59F9EA8D150ECA2F0695CD +:10FF7000F97C533C3FF305494F585E0F2CEF4A2163 +:10FF80003F95E05DB357261F02DFB7D1A2F824DD0D +:10FF9000B7D1A2EC62BA6F139DA7FB36D1F5E9BECB +:10FFA0004D7439DDB7892EA7FB36D179BA6F135D51 +:10FFB0009FEEDB44E7E9BE4D747DBA6F139DA7FB4E +:10FFC00036D1F58F80FFC1F112C175E206826BD385 +:10FFD0001AA74A70C5ED7AAB289BC519E31FDDCB84 +:10FFE00089EE67B967AA6305C2614F8E0CD268BA01 +:10FFF00077B32CA6DFE57215FB0950ED6039E2C737 +:020000021000EC +:10000000FF313CE522B6933F6F962003F175E986F8 +:1000100038FDA1E5DE3AD2B76F0AC57E5F0E517E8C +:10002000F7DCAEE7404B0699F1C0BDA137E1F31410 +:10003000D9ADD33E9FDA27EB4E305D00B4CF5B8560 +:100040003FB214063D349EF7D10E218D8E4744F900 +:10005000A98D722890DB793E746AEFAF0EFBB0DE9B +:10006000D25EB24A74E7CC89DDEF242D76BF7B14D3 +:10007000C6EE778A1EBBDFA9A363F73B1ECE694697 +:10008000ECFE833C9DE1BCBC0F9A77387EC6B45829 +:100090007CB0E03B1AFF27F05563F82E41F83E2C68 +:1000A000D1B9DA3D7BFA685DE15CDD7CAF83F4D7E2 +:1000B0008B85F37D7170FE1CC657B819B830D335E7 +:1000C000B2535F2ADBEBE72081636ADF0AF35EAF9E +:1000D00038DF31E18AFA0BDB0B51E750F5B2CCFA8D +:1000E000CC26A267233385F980BEA107EFD73097CE +:1000F000E86F31F8983F2D8ED36B96BAEF77905E0C +:1001000013BF4E9A0DF95D2A5B845E13BFDE2EFE8F +:10011000A842B5B58FE0DB8D0FEBB4CC168B4FFB4F +:10012000C88F91096D0ED263BAE38333728C5F93EB +:10013000DC402E06040F610AF05F427DB2A6A35890 +:10014000F8E79D7EE1E787401ACF6314887970A3B2 +:10015000287FFF2825C47E073429D8BF64D963F1DE +:10016000F084BED2DAB7B05FF92530E1A8CB92AD0A +:10017000D37F8F56A041FAF5C8CF84FE34DAD51864 +:1001800054B4AEF6F927F9E639B762C67F5EE01CD3 +:1001900092E64F7E8E6BCCF8BB092DA35EA17CC787 +:1001A000B9E4CE57FBD07E8DDFF9FB0C4ADF92B469 +:1001B000C7EEC0F1AF96045EC4DB95C11DE334DA2F +:1001C000FFCB242FFB2BA682BFAFB047423CAF89A9 +:1001D0002E1FEBB5369761E7F328D37F09109E4AAF +:1001E0007AFA32DDC1F358AB7E3095FC31CBC1F4E5 +:1001F000C734C7EE5F177B28CE0EAAC2FDA77EE3E9 +:10020000ED9E047814170F102BEF17145AF7CA45F8 +:10021000BC8A06E2FE77A5E947AA746DF4887338B4 +:1002200094737DA18BDDA410E0C7F07985BD90EDBE +:1002300062B407F8BC5F73248AD7033593CFD56FB8 +:1002400074CF64BE7C637D17BF0EE3F5E2860BAC12 +:10025000CBD413C6D3379CFFE1419A90FBC9D3F7A7 +:100260001A545CD6D63F5A9FAD7188FBB9E0CF884F +:10027000B9B730B8509C7B97997A53A5CB8453611A +:10028000A08EF4E30EBDA98BBDF8F5EEC958F12E92 +:1002900008AFA242C6E306CF9ACCCEF31D6B1D9FDA +:1002A0008C687BBC15E125A74C76117F5CD1CF37DC +:1002B0008CEAF73B103E4C74036E8DF5F593CDC779 +:1002C000F6CB799DEB423C7B701CADA35956C5BD66 +:1002D000F940DD38ECB7BD54E05DF7F6AF8027CECE +:1002E000EBB2C2ACAEF3B2E2ECA7C845A9E128BDBF +:1002F0003DC3845FFB10EF146A57F6C7BE1E9AAF6A +:100300003DAF714F6FD28B6F157A31EE2BFB41648D +:100310003B48A4974E91CFDE42F95339A092FD9904 +:10032000D923207B48CF5B00EC2702DDAF13AAC89E +:10033000FD8AD84ECEBE15ED27ECF7DD5537A6D198 +:10034000FDFEEC944569F96E8A6FC2A90EC0BC64CB +:10035000F38AFBD9CFBCF76F65543E8FFDD2D73BF4 +:10036000C53973EE0FFEB69CE900B474E7181ACFD6 +:10037000C7EF0B44D2649E5FF9B59F0D27FDAAF726 +:1003800059F730D2CF7AD1392F8274A8491F9755A7 +:100390004486FBDD9D70CACC4F6CBF649BF03898DF +:1003A0007C72369D8758F7301EEAF1069F879F348E +:1003B000CF4FF28C69A984E707075AE75AAD59E491 +:1003C000B2AA4E3252E7D03CDF94F97EC567AA91BB +:1003D0009A86E527C1CBFA63A0CDCEE744ABEEAE5B +:1003E000E899EEEE3E6E7F4DA1B06FAAE2E2A2AABE +:1003F0009456079D6755FD9371514D6871273A0FCB +:10040000B3D65F9DA68032145309BCE7ABF7E23F39 +:10041000E48470DC629677777FE3E7E6FAACFB1959 +:10042000D5743F033FAD7ABEBC279CC70EAD3E33AB +:100430002EE61E04D96BB4BEEA3313F97BC55D27E3 +:100440001C84DFD40F3D8560DDCFE80ECED985C298 +:10045000DEA8A67B0D19D1DF051D77F69FC9E54FF4 +:100460009A707B72AF6DDAE604F37CBD50D8DD4341 +:10047000B214F6175CDA0AC6A604E35AF5ACF70D17 +:10048000BA9B57D3A4F07C9A37C505271A6FA709E2 +:10049000476BBE4DE9E1255E71CE3A90DE2FE8C88C +:1004A000AB91FE5747F1D3B3A67FA0E93BE1FEFC39 +:1004B0005EC615C28EED6E9FE7F4F3A5137F18A9F3 +:1004C000B4DEFA4A269B5D407EB49EF35A6D242723 +:1004D0003BF84F37FBDD096739E61E4C57383BB810 +:1004E000BCE3FE19181E299BE410B03EF0D01F4B50 +:1004F0001C0E1CFF980D22C477A6C87DA7BE4079AC +:10050000B41F882E8FB1ECC07483CCF7998E3D9ABE +:10051000EF20BB6C49394464E45BC7DEEA5F477196 +:1005200097DA02D424C7A1BAB336F6FCB1128C3DD7 +:1005300029D8EEC603DED456CC2FBA27568E1D7BA3 +:10054000EBC70EB207A4856E3FC515E13CA7BE8080 +:10055000F9C5CD0EBE9FB5E4FEF8FE62F5E06C5322 +:10056000DEC6EBC39F179AFAF048184972E685DA9F +:1005700066F17E8E791F11F53F23119E587A7028FF +:1005800079D2DF99EF43A34C7C699C92B8FE92220A +:10059000B10F2B1F3BEDF068DDD3D971E42705388F +:1005A000FE895A95D3ACC1866B30F63F60B02F659B +:1005B00030B697B548FF4FD8CF29CE4111DF385F0D +:1005C00043F7D448DECE157A8253BEB992F5D13EB8 +:1005D000A006597FF1FBD99F6E43FD248DE2376E53 +:1005E000913DEC6F10EF078DF968511AAD37F3BFED +:1005F000E73C4D70A53B0E40EFB0941BA5C4DFD780 +:10060000CF70F379FF265B80FBA140ADBB109EA1AC +:1006100027C7EC26F77941E3BD93C8EE535B76B567 +:1006200092BD526FFB740FC525D44F043DC8D00E48 +:10063000F138352D339EA6F6FD67BA75BA5FBA3E1E +:10064000D72855A3FAD720F21EE99927AB6CEC37CF +:100650003DD5FC0B3EAF42FB2E42CAF7A9AA3CF6A1 +:100660009B59713F7CF697C06F7802E51B44DDE72C +:100670005ED1B4C946FAF8A5B451517155D6BCAA99 +:10068000EE6CCDBE8EE4EE130ACBD1CCDF5CC1F1B3 +:1006900003B98A26113CAF9354A18F9A7AF2B560C0 +:1006A000FD35BC42FAE942D293110F3F94421CAF90 +:1006B00069839667A9FDDC1CA10F82D63882FCD71E +:1006C000E12AF37DA2E5F634D26FAC7382EEF0A19D +:1006D0003B3F0FF6B4E41D1CF7A404EC6FAAB14530 +:1006E000FAD3FC8EDB13CBD779834D3E30D01F621B +:1006F000799E0EEA6334AF025F2ED165B54D5BC9BA +:100700007EAF7D5E8E0F6997D4F498775ED4865F56 +:1007100093DE5D6353857D73C028A5F398F6194574 +:10072000FCEECB497BB83FF311E47B149775EB13D8 +:100730004D3315845B756FD4BB30BFF9895D3315BC +:100740007A87272FBCC486F95707FF45940F091FE6 +:10075000A6FC1F9FF848940F0B2FA1FD39F9C4691F +:100760009127030C11EC6F4FFCEFCC00AEEBB8E916 +:10077000FF043D3C9FE659FDC2205BB47FF1C86099 +:10078000C1378F27897AC773E186AB49FF280CF3FD +:100790007D18ABDE6B83CDFB0426FEDFF462522BAB +:1007A000C5095BED202771FF41B3DD4DE67B59485C +:1007B0007FBFA27A2FE768E9BCCF479147115C9EC3 +:1007C0001FCCE73D370D4EE7FA049FF4A2AEE32DB0 +:1007D00023394F72C01E7BFFADC1DC2F2812FD579D +:1007E000F756D3683FB2D3859D811B927617BF63BE +:1007F000B0C9D4ABC4FE64CA6A695065B9339CEC15 +:10080000E697CFF62D65BBB9A29BFB9E83851CBBEB +:100810002928C689F4D2D4CD7CEF1C0C8A4779B93B +:10082000396973F47B29274DF81E199C26E0D7B14E +:100830000F3D251E2768C2A52FC2BBB8137FACF69B +:10084000175AF7F67FD1BABBEC5399989FB51E8023 +:100850007B051C707E69A8E71F5F63B61B6DCD43E7 +:10086000637AB8E9C5DB3708FEA7A5B3DD0E3F11F3 +:10087000707059E316F1F9E40A530F96036F38C804 +:10088000DE5851DFC6EFAFAD6814EF6D75D29DB184 +:100890002A9ACE32F3C53A33652333C8F488EB6322 +:1008A0007A34CC788358FCE980773C1D77E94F4B4C +:1008B0008FED4FE3FEBADB87B08917DFD83E041314 +:1008C000C3B383BFC4C1AF831E73CD76458867654C +:1008D0005DE9F18FDDD171EED71CCFBC77B2E27646 +:1008E000335E558BC5E3154DB9B685459DF5EF6E65 +:1008F000BCD71B1D4FEB6A5A1020F957D352CE714B +:10090000B52B9EDBFAEB00B65FB6FD010F05531F5A +:10091000531AB2492FAE7A6C9DC7A0731625E021F9 +:10092000BE792C244F4B747F75D41029461FABA67B +:100930007F62FFC79FFC5BDDBFE1FCBF9050BF4201 +:10094000785737FDB58EECB73D862B4272FBA81267 +:100950009E4A72F4A6056E3FBD2F58D31CAB4F2D97 +:10096000FBE503D91A077707FAD8589F6AED43EDDC +:10097000AA1FB5EB64BF57EF93751C066A20524758 +:10098000F38B6F5FD3F8A183E0AAA23ED8775CD740 +:1009900072E4248CF7354D3FFA54F6507AEC1D285A +:1009A000A1FEA2FC1108F7CA6EF4B2C221B1F7028F +:1009B0002CF840288BF59BE0130F95BC8FF33AF190 +:1009C000E86B1EA9285A5EDE29CEA91A6FFCF90B26 +:1009D0005AF772F524E907CEAE7A80D62C0925BBEA +:1009E00045A455F6560FF905AA36D9F5007EAEDABC +:1009F000FA8BC7E95C05DE76EA74F458B5F5B48382 +:100A0000DE3FAB928C88C47A1678A4919DFBB47CAF +:100A1000EB47C25FD54B86E9B84FCB7EF5B9A86FDF +:100A2000402409EB2F7FFA7DF66F55F9DC7E578263 +:100A30007DAA68DCE508BB13EC53E3FB53490F0ABE +:100A40003EF125EFC3B19D12F4CCEDDABE72D3476F +:100A50000EA29B13B8211969025E649FD634CA0B9B +:100A60001CA989F6ADF52AD2FFB09CFD2017DA3F0C +:100A7000D7101074F1DCD66D640F54BEE3D4A7D345 +:100A8000B8DB6EF100EEFF11C52FF0FD67EBB20D84 +:100A90001CB7D21EC8563915DF2B1FB995F170E966 +:100AA0009BB766B35E07462FDB685E6F2F5AE7E29F +:100AB0008DB3789D4BC0C77858F933E1CFF85C818E +:100AC0006989EE1B6F1F22E487136E2E21FAF81C32 +:100AD0007B223FCC11078878DEB7C43B644EB83A1E +:100AE00035FA9DB93B8708391080D07BF4FE640D40 +:100AF000DAC5C417E4373F9F4AFDACCA55FC4E9592 +:100B0000D71F30E1259D13F11C9A62C59DE6E17E59 +:100B1000BD39A527D9C14E38E5B8BE8CDF69D0C82C +:100B2000FF1BD58EE17664B33359423BFF4876E232 +:100B30007B84EF99EBC0BFB7200A9F6AB61C617C2B +:100B400002B4BB527344FE61A243B48B52116E9F38 +:100B5000EDFBD0D19BFC1D99361840F36DFB88F35B +:100B6000A0676954DFEABFA6D919F32E49CDA31FA8 +:100B7000C5D1B333EEBD133FC3B3065235D2378F61 +:100B80003822535FA471705C8AD75C72BF33E6BDB4 +:100B9000B04E7C71747ECFEDA44FCBBE5A6AD27F2B +:100BA000FCFAE3F9C19371FC0036667DA5F79FAAB4 +:100BB000ECA1C7093E5548AF01A657417FA8A347FE +:100BC00006203D7CFCD44BFBBF4F7EBA467BE674CF +:100BD0001E2D96CF563E83F44BFE348477924E7C86 +:100BE000F64B07E9BD39156807E3BC3F76EB74297E +:100BF000AD2BDDE2F78474EB063ED7FABFC55F97F5 +:100C000076C35FF7C5C1F373284AA53B0CC79F5C49 +:100C10007E09FB15E2E06BD9BBF17CB37A88C67024 +:100C20008EE79BF8B71FA2E0B8ECBF3F61BCFDA206 +:100C3000973807AB7EF4AF2CBF10AC1127E26D756F +:100C4000E853CEAF23F9C5F95D33E9BCBAEBBA631B +:100C5000E1195FBEC1E4471DF7DCEE8400C5DD4548 +:100C600076C8FC0E433BCEA58EF4F3A772F99C70B8 +:100C70009DA9EFB7AB110FE9E7EBD2AC3CDC40EF3D +:100C8000C1B4074AD400B54F32E30FBC114F5A9498 +:100C90009EF47E8BEC21BD2E1C826989DF050CF24F +:100CA0003CC2D05DF91A715F4B3EBB2D6CDAF54E3C +:100CB0001C2FBCE6CB6D746E7E4871F1B9E5A23590 +:100CC000733C7CFFAF25FF3F092F16BF8A70247A43 +:100CD0000A188E5E08E71B0508D0FC08F079B09C66 +:100CE00052B6E745ACB704014CE724F1FE9465E049 +:100CF0004D6DCDEDEA374139E820F9BF14E511FB20 +:100D0000BD37C6962F6BF998F16C591C9EF908CF28 +:100D10007A75C5B3DC4B4DFF4A29949AE7BA6CCF7C +:100D2000B7EF95F93CFF940B58DFA0735EDC3138C8 +:100D3000D522F3FE9C7A4A0A71BC61204BBCDF8A43 +:100D4000F84E7A968587F1F67D7C7AE2D97747D29C +:100D50003DB1AA5FFFA5E4BF303DF1EBB707BE4848 +:100D6000F9E7FEDCFF2FD0B57EC5CEBFB21DD3BEE6 +:100D7000D3C9FED0F69DBFED4F72B9FD05A74EF861 +:100D8000DB7EA753C435EC4CE177CCDAFB09BF5DC1 +:100D900070C7972561965B6B791FA75FEAE0FD3E00 +:100DA000D5F2379623A75A9C1AADA366670FF68F24 +:100DB000D5BC901422FF40FB8E2F4746BF77F5CF5E +:100DC000AEA7DABC4FD39E0273296EA63D4DC4591F +:100DD000D6BC38E6176BC81E69DAE520FF7FC56F01 +:100DE000FE5E427CA9FD995D0EE25B68973E02883B +:100DF0001F732EFDE903F65E745F0CD8DE3E7DE9BD +:100E00003BB3E87DACAE701170684738D0BA102E95 +:100E100095A49775078FEA6F2D3C3E657BA2AA6566 +:100E200014D351275C24437C4F09B9245AFFF31E85 +:100E3000F21BB5E7A1FCD769DD5F9690FE74A17542 +:100E4000FFC7A5E27DEEFFE7D76D838B5AF753DF2F +:100E5000DA750BFC1F76A926DEA78AA383AE78FE7F +:100E6000DC0F38BF2D45E7F97E45FA7FFD5BBBFE01 +:100E7000AFBCEF25E4B7BDD87DFFF85BBBEE0BED53 +:100E8000FBABE6BEA7A874BFAE7DC7DFFBF37ABF9E +:100E9000E2BA938BBEADFCEDFCEBEED08F64AF8B72 +:100EA0009ED8BA075ADB344CD775A3A78C2AB2FC5C +:100EB00010C21E914D7D631D0C3336915D857A06FF +:100EC000D901EB3245BE1EF50799EF0F72B00AD477 +:100ED000F7D5C5BBB68A1F54CCDBFF7C23C7B3ACA8 +:100EE000CBFE0EE495D17985F06304D7E8BE5DD8DA +:100EF0003E9866D3823A3D57B5D2B709CBD5DEB21C +:100F00004AF6CD3AED6A57F43B168ADB1163A7B86F +:100F1000E3EC8DE402478C5D9204BB55F2C327E9F4 +:100F20000AC7FF3921AA3DD6CF2A12EFF42743285A +:100F3000A0BA2F1E4E8BBE3E9C5C7CAF5235E104A6 +:100F40008641EB766A0AEB610AA0FD28D621EC4EB9 +:100F500084A316054730ED50C504B9A20D6338A22D +:100F600001A14D1A4D70F5331C83BD6495E1DAD9AA +:100F70001FAF3B7E1FD6699320CFD4C725FD9B872B +:100F8000F3D822111F100F672BCDF795AF21FD77F6 +:100F9000D51A71CEF5CCEFBEC3F9263BEAC374CFA8 +:100FA00030D5B7A288FC8E5E43223A5D3543BC2F14 +:100FB0005846F7C032C9D41771B899AEBEA0B0BFB9 +:100FC00012ED0CF657AA40F69F3C091AD91FE855B6 +:100FD000E2E27A558E7B0ADE2CE29EA01034F14EBE +:100FE0004B6CFC4F601214525CC314B9AA81E675B5 +:100FF0000A521A28EED2616FEDCFFEE17E008F918A +:10100000BFA5FC8B8D549E8B7A3DD07D32A5F53DDE +:101010008A6FB84D4E058EAB8AE0A728B85D76C6BC +:10102000054A149CCB212D267FA2DFE126B213F2C4 +:10103000024E9582C72A5CBD62DA9FE87586C70BAF +:101040003A5D2AD94753D4DC98F6B267EF7B64D770 +:10105000BC916E63BBE0F29CC131EDAFFAE0C4C657 +:101060000526CED23ABEF7AEB8A78AF6D623AF632E +:10107000BB37EF0720BFF1155A694CBB66D3BF12CF +:101080009962E7F766AE2C1C13336E737837C3A5ED +:101090002A0B243A0FAEB2214960BDEFEAE531F5E3 +:1010A000BE37FA8A987E67183362F255ABBF0025C7 +:1010B0000360DCEAB340EF0796B636C6B41FBEB78E +:1010C00039A6BEE7753485302DDDA705291D75507D +:1010D000DC231D8EFB41E71BCDE1853AC5EB14D324 +:1010E00005D0323A16F0565018F2C8A3FE9728BD24 +:1010F00050FC3298EFB2269BE7AFEB6DA1C605B965 +:1011000014FFD3F0E35D12C743EE263C1D1D69A812 +:1011100048C5EA63CF34BE446953DBF87A7AC7B373 +:101120000AA08DE5AFDBC6E70253E4961289ED9F76 +:101130001EC39D51E72EDDBDD7F9A3D2F27D4548F0 +:10114000476B738C865DC4F727BD3B5FCEEB5A0FB0 +:101150005425128DE73F2AF51EA6384D2B4E2AB98D +:101160004216BF4771B98893A9B3E94926F362FDD6 +:10117000409D6AE738FE65C582BF8D6CDBDCE82EDA +:1011800023BBD3A5D1BE2667C4DEF3BE71B4B8B706 +:10119000F7459179BEA2A859D7931FBC3845B4270B +:1011A0001F1F8D37DDC6FA94E780BEC78EF9FB0A94 +:1011B000F7A9C4CE9AA67F10E0F74D0FB44D903436 +:1011C000809EF794DAC80E87BD76FE7D99A6C2C9C7 +:1011D000A70BA87CFA5B1CC3B86BC22F0B49BEAD32 +:1011E0001C3CE4BCEF8C7ACE48A045C5412C2BD6E4 +:1011F000783E1E25CCEF1279CE285CEE99A7DBFA5B +:10120000478DB77282D0FF560E4EDE4A78EB3960BA +:1012100088B8A842B73680E9239CC37C4209E75CC2 +:101220009F22E2ABB4F3BCF37F7CCB88349263198A +:10123000E57A1AF94133B6CA1DF7CE683D3FA6FFDD +:10124000D0C13AACDF3F19E7B58562D744792BF2BC +:101250002458EFB0CA9125613E43B2CAD7CF9E5CF5 +:10126000C4EF31C6D41F9AD751DF70E574F6AF15BD +:10127000AFDFBFB688E037CA467125EB7F67E777F7 +:1012800006709DAC4FAC447A06E97CF0EC710178B5 +:101290007AB8FC90A4C5BD9FDB5A4CF982BEBE4112 +:1012A000C558FF92B3A9FC0EC067F5492CFF2E3933 +:1012B000FB3D7EAFB3C961F4BF9DFD37491C6F365E +:1012C000E3E68F37AC26BABEEA7821C52858EF5737 +:1012D000D6A85F303FB0E2EC3AE187F88B78FF6345 +:1012E0005B679EF883A7139E06BDCFB53E0ABEF48A +:1012F0009B2F334C78FA8A37CE5E8BFD6B8BA6E53D +:10130000105D9E0637C7F59D561F9F4DF33DBDC529 +:10131000CE41B44D26BF0C149AEF11648673E85E7B +:101320007EF19B368E473A88F860203EE4B7BE993E +:101330005E4CED3295748A6F383DFECFFC6EC2E98B +:101340001F0207172F0B3B185E4D998B2ACA19FFF6 +:10135000B574F23F58F06D34FB79B8D4B8B298FD4B +:101360005CE67D1163EC45BD3FB96BC2977C2EB046 +:101370003617F5FC340A393E5347EF4BAECCB5B3C4 +:101380005C5A99F6C5D44CC2F7725784DE81A859CD +:10139000FD19C317BBC98DBE07A69C91418B8ADF7F +:1013A000D2868AFD571483F75F39E3E0F2AAD5A706 +:1013B000996F5BED4F98E7ABF42E23DD17AAFA8700 +:1013C000CCF746911FD64BC328DDED5819C54FA069 +:1013D000F1D30E3E3F14F7EABEE96F25939F728664 +:1013E000A4CEA2F9B56C3B339BE2056624A9B328D1 +:1013F000DEA06EDBFBB329BE60463F7516C517DC69 +:10140000573C790E97F7521FB0A1FC7AB964BEC859 +:10141000E7AA7FA2FC535BEF98C3F553C4BEDFB6C7 +:1014200075CE9C00F36337D3C1A9FA1E21E779E892 +:1014300060E9EA1721FA3DDB2EE5E6EF49C15CC120 +:10144000F73EB9BB0FBFDB09056D1C2FB6BE58F8C0 +:10145000FB3BCF5741A5F3D5CC7C30C8DF9CF95C72 +:1014600092F85DA2436DFD097E4736DEF203F2A7D6 +:10147000AE9080DFD1AF026D24D1D5425BF83D4AFA +:101480005F1CEEBBB798F5A9368E775DBA7A27CF89 +:10149000EF53DD8C5B562345DEAFF54E04F69FF02F +:1014A0009D88D838E30F6CDA40EA5731E1B2506ECC +:1014B0009BEF10F37A94E6B5227D17C7392B6A5B50 +:1014C000B64FE851856C3FE524F37BD175BDDF292C +:1014D00049F43B088DB528EF91E49EA96DE674F5BB +:1014E00050607CEBA9841D3AF6537D40C89D916DF8 +:1014F0001F38A2E319779BF04D357FEF2A3E1E7708 +:1015000037C9A5A8B88315BD5BFB927E68ED6BE774 +:10151000BEB4F635F70568BE99192F3D45EF9D50CD +:101520009CEB0FE93CE3B9A456F25B778F27D63EDC +:10153000887937250BBE11793689F5A6F8751C34E4 +:10154000E76DAD2762CADFEED61131E5EBBF6A1D4C +:101550001193BFC7AFC7A26FEBBB45DF5DDB8BF954 +:101560005F3CDE897B6D17C23B8BFF5483AF50DC41 +:101570009716FCC682B7354F0B6E4DDDC4E32AAB20 +:101580009F8F598FD236898C1E482D11EF5F298D80 +:101590005700ED87B2BA85EB75B71E39E5333EC704 +:1015A00059A6819FF4DEF875554123B7EBBAAE0812 +:1015B000F3E3159AE0C75DE3F823CC9FABD13E235C +:1015C0007DDC5A77079FC6F5137D4F4086C37C9319 +:1015D000EE124A645FF862F4E372BA31117D6EE58F +:1015E000BA39263F45BD3DA6FEE5396B62CAAFD08C +:1015F000EE8E29BFB2F0DE98FC77F59FC6E9F79B27 +:10160000E2F4FB2762CAC787DB58FF7EA3761AC7BE +:10161000A74F3C1A613DBCB556E5FCEEDA1C4E5FA7 +:10162000AED598FEF7D41672BAB756E7EFBFAB1D2A +:10163000CDE9EBB506A76DB55E4EE3F946595BB84B +:101640008CFCFBA33353F93C6AE350DFF525140708 +:10165000B92F5244F837F640E34B240AF2439FBEB9 +:1016600047F54EAB0E8E475CBB6BCC1F6EC17CC684 +:10167000EB322469E7D38B6430A2F0C7333D0C749E +:10168000FEED01F13E567CFD8525424F9E0B61F13A +:101690009EC06A3E0187B92EF5152393C54684EC9A +:1016A000F6B9E0673DD4B65ABC5333177428237B90 +:1016B000D607FE7B381E29F67D01AF3163DDAFB062 +:1016C0007C36DD3BC5F6DF7737F2BDF267F6A64F15 +:1016D0002EC5EFD77A25FE9D8F033BEFBAD5C5F611 +:1016E000AF75FFF41DDBC5E8130B4B047DB54B7ADA +:1016F0001BCD379026DE2F8A6F37CA5CE755C108AD +:10170000EB1F11D43F28DECCA2CB19EA2173FD9A3E +:101710002D750CD1C71ABEDF50D5A6E94184F798C4 +:1017200043822E46205DD0BE8D3D2AE86024D20142 +:10173000CB41D33EB4E800EDA997A8FDA983A03B17 +:10174000B17DDDC41FC9647F8DF92C14A4F4B2B33C +:10175000915DE7B07C5C9BF8DDA40BD993965EDAD3 +:10176000523B97F16867AD8FD3D6DA4A133FFD9CA1 +:101770007FB97635E7F7D40638DD5B5B6FE2670348 +:1017800097BF5EBB81F36FD4864C3CDDC2DF3592E0 +:1017900067089FBB4B4C39ED2A37ED0A917A8D359E +:1017A00076BEE78F9F889FCCA5B9127E544A21E26E +:1017B000DF75E9013BE5EB92690F68D601AE7F9DCD +:1017C0001B5A490E54E5BC28F4B0383C29CFBC86DE +:1017D000F164A619C77A20BDEE5607E2C389C6FB9D +:1017E000ECB1EF8D5E1C5E2C73AFE57B7DF17CF17F +:1017F000267A8F42EECA0F0174BDAC4CDCEFA238E2 +:10180000BDAFCAEF555B9B795F4CDC7FA9EEEBE681 +:1018100038DB7F9D9C514D39030BA87E87FD9D7C55 +:10182000703EBD8FD7052E71F6F7E141627F2DFB2B +:101830001BF54CF64BB58764B6BF2A731B3C6C7F17 +:101840008F8E78683F6FDA2103EB8B8A38EF5D4A21 +:101850001D6914D7D3BA7F1CCB99557B882F2D33A4 +:10186000CF7BE3CF6DABE9BC574A04EF30C7D52F30 +:1018700037CF7BE3D75D3DFE089FF7565FE05EE91B +:101880007B25B1BFE7137F7FB73B7CA17882E8F768 +:101890005C4F9EAD653BEDC8B63B1E0AF4FDD7ED2F +:1018A000DFADA5DECF4A441C35DF9BB3F6B3CEFCDB +:1018B0005DCEBA492EBEC7D03E42E5F76FDA25F1BC +:1018C000FE4EFB5F415FA3D1FB3AEACB24172ED338 +:1018D0001DCC574787C57B01E3E95E6282F702268C +:1018E0001C0A0553A8DDC100FBA3C6ECF305E9DE25 +:1018F000EDA8D70D99C8ABF465AF4C7860C9274BFC +:101900005E75D295796F8E6232F2BF3AFD698B4671 +:10191000E7907ED761B7BAA7F23B45A75B81A349A1 +:101920002DBFD8F083864CF712461CF20549DED64F +:101930009976E6A813013915BF4FF8CCCF76D018A9 +:10194000B453E552718FDA8882AFE5D7B2F89CC5FF +:10195000D7AC7B7BAAC3B785FCCFF04212BFFF1286 +:101960003FEF41436DD67BD6838612DF33EFE94DDF +:1019700091CFEE3A4776419B8817B8E46CFBE3645D +:10198000F7AC7AB607DF53BB907D50A39E4EA89F5D +:101990005A698D4D9CA30CABD08693BD497A2BD947 +:1019A000A1965D1A5FBFAC74D2D8A15934AFF16D66 +:1019B00006E1B76A3B2F7ED7ACFEF4BC76A1357E3C +:1019C000CD8E11EAC228BFD5EAA19219C7F2F5DE81 +:1019D000A19E10991B23C7BEED7A1FD26119E11792 +:1019E000D98624A7BE4F3B80EBB80E5A595FB9DEAB +:1019F000FC1D8B1B001CD1F7646F0483F9C39F741B +:101A00005F0DE1CD6288CCA77C8D14A97A1141F8D5 +:101A1000C9C4716AAED6555E5FAC7C4E36EFC1C6A6 +:101A2000C3FD4E136F2DFEDFEDFEC4F1FFF65295A0 +:101A3000EF41B73F3BCE46E738EDBF97F9FD54ACD9 +:101A4000C87C25384CDC3B1D3ECF7C8704F9CA009E +:101A5000BD2B5F393D7ECE64F61FD1C106C59F2ADE +:101A60007AE1F551F7CD82E6EFBA6CC194E22553E5 +:101A7000E78595E8F3B39F9AF32FBF7632903D74D4 +:101A8000952AECCE292EC84C225E78F674D12C64AF +:101A90001057913E3B9CDF617F98E0DCF10E08F12E +:101AA000A34B70DFDE17E77C7093C4FED2E626916D +:101AB0002F5E9CC6EBFAAAFB883DF728C1F52F6E76 +:101AC0005286117D0F4D8FE4115D168F793B5DC2FB +:101AD000799598F7B170DAF510F5FB56EF9AEBF8B7 +:101AE0007CA8B18DE63734BD6DFD7DA45F3E6B03F0 +:101AF000F21B1E1973FB128892CB9ED249BFA27AA9 +:101B0000DB25F39DBA1DE2F70CB04576B47FEB4FB1 +:101B10007AC5F354AFD5F433C0AAE7F91EFF0C55CC +:101B2000EC014CCE327F4F32D23FD1EF0B59E75907 +:101B3000430996C2FFC8EF8A6D37FD936F0EFD60B3 +:101B40000EF917A1359247F3389224EE517B4A7D66 +:101B5000BF233E3394FCBCB48E9F09FFC091343F39 +:101B6000DF23791BF9339D1FFFA5D6C5E9BB681F8D +:101B700051FA3F681F51FA3EDA47947E88F611A564 +:101B80008BCF60A7B87F3374E36DE6AFDDACA37B8A +:101B9000FE1230F5FBC4BFD3F49609FF92A643773B +:101BA000F6203C6896393EBAF85985F5D3932DA3B3 +:101BB000627E9714E9F530ADAFA4F98F3FA17BD6D3 +:101BC000254D8A2A69742FFB7436C71FC6CD8FE056 +:101BD00040E70D911D0EF17B4AE67CB7A7B5ADA796 +:101BE000F6DB9FCDA319D2398EC0C31DCE84BF377B +:101BF0006CC5DB3D3154E85FDF7346CAA2CF1FE3FB +:101C0000E3D3D80F3C86F0B9E00F344E60AF0C033D +:101C1000182F63FD1BFD74710FC14A8B7738384E46 +:101C200079FB8EFD575F89FDFD1F8FB61B3100804C +:101C3000000000001F8B080000000000000BCD7D9D +:101C40000B7854D5B5F09A39F34A32934CC2000957 +:101C5000123809AF00018664121212E024048A8A45 +:101C60007482D482A28EB462541E23D29ADED23FF2 +:101C700027244012830605CA558401C1C7FDFCAE66 +:101C8000D102175BF44E50A9F6B73422E2A354C731 +:101C900047552C4A8A62EBAD2DFF5A6B9F939933BF +:101CA0004C0222FC97F0E9CE3E7B9FFD58EFC73EE9 +:101CB0003BB3265E5E24C900A7E9670A80CBDB1729 +:101CC000A008604CE9D70FDCEFC1F2599BDB0400A0 +:101CD000F360DB3437F6BBCED1F1A21BEBD7BBDF11 +:101CE0009B968EF51B334D07A8BC49CE999E812546 +:101CF0004088DFFF515EC5810CACCDF456DB024E4F +:101D0000800A9000F2807F4EE37F531D29008E6889 +:101D10007D9ABB8FA1FEBDCCCB0CFD2F978718DA27 +:101D2000AFCC1B6D68D7E79DE92D34F41B97D19597 +:101D30001B74D23EBEBAA71CF70326080FA37DED85 +:101D4000FEF2EDDBB19C35719E8FF67F0CDAAE1999 +:101D50008D1BFDA4A479E3FDF4B245B165F503B88C +:101D6000857EC7F6E3103E5286ED926BF9813BF11A +:101D7000BDDB322590BC00359BADEF4762D6B10488 +:101D8000FC6961EC77DB0EE37380882DEC03B83DD2 +:101D9000E00CB62000173D81ED0E433B8FBB78AFC2 +:101DA000CD4DED4BC0126DCF01A83D9AF3E40B3140 +:101DB000E38DCBE8BCEF7E1C6FDC9E39EE065CDF6A +:101DC00093A55F0F90719FE55E97E723040D4C800C +:101DD00009A711E42039CD80FD4EBD2485245CD7B0 +:101DE00034E99BD4483E3EAF423C67E17B26F90F85 +:101DF00065D8AEBE2CC14E1CE76F75F2932F5869A3 +:101E00007CB8D19F1FA50B80950C5FBD7CAB0E7F6E +:101E10001D01F0C73A07977FAA7373F96E5D269785 +:101E2000EFD5C95C7E5097C7E5AC431068C7F1FE9B +:101E3000FCF7F1007D681C15A06FB41C67F39A07CE +:101E4000E03ABA7E2F85B6E37EBF289F9006B4CED7 +:101E50006F70FE620D0F4802D5448CA5F8DF8FB776 +:101E6000BD98E5E3E7AA0BA75AF27709141C77B9E6 +:101E7000D724C65DD4F1629627DA0ECBDF33F48720 +:101E800015A603867A638EB1DE5A7120F67D1D0E8B +:101E9000F1E52D9BEFB0055C58AE372921E799EDB0 +:101EA000FA7AA6ED4F524C389E659F3D64C7FD2DD2 +:101EB000712BA0607F0B80D29E7FE67B00F50CE744 +:101EC000791204DB138C5B47E312BDEF4F02E93C50 +:101ED000C67D0B6983D6A3FE973DB413DF7B2B4DE4 +:101EE000017FCC3C2DDAF89FA5B7FDE22BECF7D9AA +:101EF00033404FB00E73693D63777D6C3663392E86 +:101F000059D0C95877C49C81E5899A7F6C3CE261BD +:101F100032F59B26637B6ED71107A2FCBEF6AB366B +:101F200039106F6F9BCD00034020BE04FBE31854B3 +:101F30007FD07BD5DC46FCFDCAFD4961F379ECE737 +:101F400041E445A6A34AC1EF3710DD88791440511A +:101F5000B37415E8F32A241F68FF547FADDDFFE654 +:101F60007AA233E8DA48F2E13840B885D7AFA4C6A0 +:101F7000F2FFD2677FC2FCB9280BF99E04E066C16C +:101F8000BF0EFC773A97F83534DD89EBBD358CFC14 +:101F90000F179FFF9FF13AA37C3E22219F1FBA1289 +:101FA000EB4B9F91BC766C3EB96F98E0278DEF7537 +:101FB0003ED7E1B87493C47CA9D73FDF27CD08256D +:101FC00080F7368D2E86285DB369BE65CF5AA00591 +:101FD000D7B76CD288FEB1E3C7BFB7B44902396640 +:101FE000FC279FB3D710BFC8D0D5AF1AF967DCB3B1 +:101FF000A7322AF24559CFF868D3E44DD720FF180D +:1020000094D726FF9F7E8EF301E27127C2A7327319 +:102010006E36CD3FDB094ACB7806CB1C07CA89ABAD +:102020000588E0EA92EBB201E1B919D12521DDCDB5 +:1020300051AA5FBF0EF1F80373E02A92F3C7BC43C5 +:1020400078FC6B5CCBAD606672CD36E17873E7D817 +:102050000B693FB31A045DBF9EDE759C9EBF3E298F +:10206000C5D480EFBD6E8246C888EEE375AB3F9B5A +:10207000E80D37EEFE08F163524649A7537A9617EA +:1020800044C91FE97894A2F26F9AE454699E936E52 +:1020900033D3BD25ABD546EBBA154207149C7789DF +:1020A000376C23F9773BB82D5462D1D54D1F447F4F +:1020B000E5FFE8388DEF2FE9944226ECDF5ED70E7E +:1020C00016C4EFD3757BB91CFCCDE0C6CB101ECB7C +:1020D000C7DBBC2DA4B734FA32AB26389D405F9DD8 +:1020E000499F96683BAEBBC2E10C4BA9F4D87A3C41 +:1020F000761D8DD94ACA78DC8FBAA63C9DE99368D3 +:102100006170749FE36C004E92F33B5358CE1F7B7B +:10211000AED84C783AF63B6BC844F52D23DEB8D3E5 +:10212000C7752079732CC36BB6517B466E48C5F6D4 +:102130005BCCA0925C86ED426E3D3FE9AE77488E67 +:102140002DDFE932D94D828E653401A447D7BEF325 +:10215000EF38CEADC8AC766F546F2C9AF2E8C62734 +:10216000900E1699DBEE29C767A7203CD68DF0FCB0 +:102170008BA97D38E9ED8F1FB287CDF4DEC323B77D +:102180004B38FECBA98191B41FC854FAE7E0F39A0B +:10219000437DA105DF9FFAE83F0F92DEBCF5C9BE83 +:1021A000CC5F3ADD4F233EC4F59C403EA4F59CDC59 +:1021B0003784F92E8A7F0187C5280FC8246ADEB1CB +:1021C000CE4FF80C24CBFCDC02AA7219E17BEF4D58 +:1021D00040765381645288CEBB9A115EA633E9499A +:1021E000196FE6F7169951BF121D06E44282C7091E +:1021F000935CA0F105D07ADE7F6EE4F6167C7FAEAC +:10220000D63F4A774797FC86E86EB3DD6BC7251C3F +:102210004F32EA7DBD9C393E9DF9E516C79760298E +:102220008C3E5F52FBB5B19E0F0AC98D8206B9F094 +:102230000E2CEFD4E07EC548FFF7C7E3FBB7B5AF80 +:10224000DBF38A4CF36EFEE9DB34EF4B4E9E175EF8 +:1022500011F03B6112FAA55BBF3AFECAE3A3E4E1C9 +:10226000F5EACF3F7EE88DB1011CFFE3DDA38703D4 +:10227000D2DD02A9F3A307115F9FBB3ADFF93996BC +:102280004FBF74A81FC12F7EBD8B6ABF004B8C1C33 +:102290003A6E32F17E17D13EF0F96F0AFD3733BE48 +:1022A0002DA827106E0B5AC66C2779304DCA4F23C4 +:1022B000BBE9C431E3FAE2D7A98FAFAF4F1F5FEF9D +:1022C000B78CE08F709838CE2DF4ABADF373C2EFBE +:1022D000677B469B9015A3CF333AC7A6E747F1E447 +:1022E00057EAADD4EF1A12F5888AB90E81D7B935FD +:1022F000A650430EF7E3F6EBF039E1BDC2D3C0F5CB +:10230000394ED467D87F51E66F785D24E81CA8D792 +:102310007E00FA4FF5AA5F61BF3797A5B25C987B44 +:102320004B9B95ECDC6E79A6BE6D3E3DFADBCB3364 +:10233000849EECEE07CCC3A43F013767C1FA24ADFD +:102340006E2AF963C3AF483EDF99EA95D064841AD8 +:1023500019C2C4D7272144F05E6D0AB2BDE7203D03 +:1023600080658BC99B69C1523277F5019E27C47085 +:102370009A06010BD57F6B8A3400BEB7CA539949C0 +:10238000F4FF2638FD6417FD207DF51892A395EE25 +:102390009973E9F96C35D5DD82FB6DB4CA77E793A3 +:1023A000FDF303C94B76AF0E175D7FCCB578AD0456 +:1023B000DF7E41D9AB22FD16BEA2384C0C7F874A86 +:1023C000E3BE6109F6A575BDE55C3FC664263B2DFD +:1023D000E41A839B7DFBD07F14FD1EDFFF2328932F +:1023E000C81E98F35B07CBF19B40667EFF11282C3B +:1023F000C76F8600D76F8188F54B7CEFDDD2FFD9A0 +:10240000B91FA2FB7A77E257BBC9AE9F2BB5F7CDB8 +:10241000C176B512F248CFFCDAF17FB646701D4A9C +:10242000830592D0BEFA35D129D9EF475DA19DD859 +:10243000EFAEE42DA91D588F9884FDA556069FA4E4 +:10244000FEAA19FC0D58F64D0E3C4F7CF8CB14310A +:102450004EADC5E126F94806168DF3D13B2EA67781 +:10246000D2BB3761BD0CB145F03AD157D09BFA577A +:1024700060B97BC2EAED5468DC53B27727BD3AD528 +:10248000CCEFC36999D75116A75F7CA3CDFC3EFC66 +:1024900043E6F72775590CFAC537CE1C7C1AF73777 +:1024A000E5EF965EF5CECD05827F7C7DCCC144F60E +:1024B000E0FF68FC851092683D0D7B4DA116264219 +:1024C000611F94E9F40891D5446FE50041A27BD8DF +:1024D0008B7A4C9F2797F7FFB9EA233AC476B60761 +:1024E000DB9F2739690F0A3EC1FA54DA8F23085E51 +:1024F000B2D750218305EB49F8A290BB6E203BB6C2 +:10250000A502DAA93E092212E17B0A417A08F9C341 +:1025100032D3ED5450B8AED3F1F740E5F272087102 +:1025200079258485BE07B9F1299CFFAA4F40EC6745 +:102530005498E91D1D19F747686FC0E5B798C9EEB3 +:10254000F0FD30B1BF30A840870B22C473EE709904 +:102550000E814C31BF80879D9EFBA2F070C4C123C9 +:1025600089E0E18DC203E710F03803BE023E931408 +:10257000840FCAA7C9D025D13C8A66DF548297CB85 +:102580002AF073D90B5C5EA8F79C09979248C01299 +:10259000C84F009FA989E96684069F3F1600CB2F8C +:1025A0005DFE5C5B20F3735D0E217F66923D1A2F0A +:1025B0009FF4E7BE94CA2F64A487AA82AC7916D48C +:1025C00067BEC2CA3B8760FDEAA7F344BDACF257C1 +:1025D000B958FF41C128511F5759684578D59B46C6 +:1025E000CFABC2FA90806923F1E5F27AB4AB715FA8 +:1025F00081A47B8244C7A60C709BB03D505FE42D44 +:10260000C07A00E912106E7629A79EE06CFF397837 +:102610001B7015196981C905B8DEFCF99DAB053E33 +:102620002BFBCFC5FEC73BAD6CB7ACB10583842790 +:102630006477777D69747FC79FFE790D3D7F7A004F +:10264000B849BF80472EF4BBCE5C8FD9015C5F8C4C +:102650007283E21F38DF4C9A2F80EA49A6753D2528 +:102660008508FECBEBA7B13F7024CFFFFD82BE31C2 +:10267000E3E33EA4F134AFD073E0C92924B8958CCC +:10268000F45F4BFD4EB850BEA651BBC0434F6563CF +:10269000813297E68D7F6E4EF9E6862538CF52A4BB +:1026A0001192D38B0B0237D2B84BCD914185F86C88 +:1026B00065CA3B36A60B05E993E403F12BEDB7069B +:1026C000E991E87ABFE057E40077B7FD8AF8F5F8BA +:1026D000BB6E58E813224EC2FF15CF0D3E8F6635F4 +:1026E0008D7F3BAD63A9D4B590E8F2F3F4D76C7F4E +:1026F00066BE1C28E84E935B4B9FFB9AF9E7593363 +:102700000425CD3F8618BE5BFA5C9285FCC3A59F6D +:10271000422805DF2FDBF77803F93BA5E8FF939FFD +:10272000BC78D753CC6FFB485F22E896FEF7B3CF57 +:102730003F487C7A6512C7A126BD767408D94153FB +:102740008E461A106D70E2D9372E13F4AFFB257F39 +:10275000339D8F1E9F26ADB887F0BD0CF16FC7F972 +:10276000969982A26E75B855967BC24FAED1F6F19E +:1027700019746E9CCF72453D504AFBC99480E56345 +:1027800048F81332FE23FEBFFD686835AD13A46F11 +:102790006C246F4EA15F4CFBBAFDB178BFA3EB4038 +:1027A00029F9DDE417E33E17B71BDB97C6EA870478 +:1027B0007EF296022D1E960DD9B4AF5FA33FF4C1F1 +:1027C000309A777E1AD9871329AE90405EEAFE715F +:1027D00028B9F29102B697DB25E287324BE2FE0B75 +:1027E000F3855FACDBFFCB1E92D88F5BF6509F5119 +:1027F000EC276BFC0A612FF3EF93A45788CE022FCE +:1028000003D1C12DDA9E60731FA6B95B9B4CECC748 +:10281000D8A53BBCA4F7C73DD2FFB67F63BA4975C4 +:102820004326D527CC7DCCC3F655908435FA556C1C +:10283000673E99DE954BF33F992E838AF3352475D5 +:10284000E5929C559F757849EFC6AFFBED02E10F0D +:102850000C098FDF14F1083C139FE7BC54BA89F0D0 +:102860007C12F99CF0B7CC35BC3F38C96E989C19E6 +:10287000C1B241B3D3731E1B95361BE1E2A3F5C66B +:10288000D8D51DAF5E9342F6F26E8B3FC58DFD4EDF +:102890001ECE35F841F16551189153D84BFB1B33CF +:1028A000870412C05D2F7D9B2C0C2F9D6E7F5DA732 +:1028B000C00756C247B9D8876A77DB7D447FA1A994 +:1028C000E44F2EBB19DC2DD87BD9CB0F3738A8DECF +:1028D0000C4CCD27E97FD4FF137388ECF15FA68CF5 +:1028E000BDB71CEBBB8E59849FA22A87F263EC58BC +:1028F0007BA6196403BD764A8B491E13DD23BD26D2 +:10290000C9C920C7D0634A5E86A1EEF20E30BC9FD3 +:1029100056926B684F574619DA8BA13612C0F514E0 +:10292000654AEE10AEB8CF8C0243BB1DE93A4CEBC2 +:10293000FC52D85125F84FE8DB20DB4365118007B6 +:10294000900E261E37DA59259136F637930E5B0C1A +:102950007100FB59E250C9851A7F0D8481C45F481C +:10296000FF5E9263270F8BB893ACC17359B6D0CF7B +:10297000CB5E96D80E5C76CCCC7AE22478BBF14361 +:10298000F251E7BB78B8F7F51BE1DC7FAE11AE5929 +:1029900001235C2FAB31C2353B6884EBE05A235CEA +:1029A0007354231C87344D34F41FD65669A88FD82E +:1029B0007485A1FFC8D06C437DF463D71AFA8F6980 +:1029C0005F60681FB7F736437B3C5D8D0F2F33B4D4 +:1029D000DB538F305D1D40BA32A13E287CE9DFE237 +:1029E000E8C2C2702F1AE8F48662F0AFE23FC27FFD +:1029F00099969798006A03F1E385C2FF1584FF94C6 +:102A000028FE75B9DA139FEAF81D42FA9AE565794E +:102A100084F07EB22485E9E5E04B270F2B40F84F88 +:102A20008502DCEFAC29228E22C9C126A2934E700A +:102A3000B591FDB9C61264FF4545B3702729E53845 +:102A40007FF3FB25E86FC6ACB35A49024BCC7EC777 +:102A500087DB0DF5C297F61AFA1775860DF5F18723 +:102A600041227D55F0A6F7792A8B3E5438FC55FC5F +:102A700049F0792A4BBF0CDE45FA37DECFBD5AAD9F +:102A800097D2C8AFFF7BFBF368D6A07F364825BF3F +:102A9000377247AAD73400E191FC4E03F9DF807604 +:102AA000B4159511B80FB23E98EF10EFFF2D69F2F3 +:102AB0002AEA6F42FF9CF08E70C9237BAF1692BD4D +:102AC0000417B25BC80F832B843DBFDAA4B23D9AD2 +:102AD00084F628D9230D157EB697A74370203DBFF5 +:102AE000069455C4779219ED577CFE3F23028D85DD +:102AF0004562B1443F777D21B3FF3D85FC6906A661 +:102B000002A4F74ED0EFB43E78691EC5E34F902E75 +:102B1000C3F5B7B5BC304F253BC303EE08AE3B2031 +:102B200040069B0B03F7D0B8EF9BDCAB0BF1DD83CA +:102B300013FF3288EC917585C2EEB34B0829A4814E +:102B4000FEF315A0E78DD9CA7D8545D1384B4FF4EA +:102B5000A3C733F5F8E6AEBA309716B75722BA8B4B +:102B60008F3B46CCEEAAF1A4FF9699D8EFFC0B2D33 +:102B7000AE94E7496539EF804E7B3A2F99FDFFEB24 +:102B800035BC991D9DAB7E8EEFDD1014F6D60293F9 +:102B900097FDF5DB338F731CC52E99C047FE505A45 +:102BA000FE76117FD1E3259749DFC6CE3ADB7E6FF3 +:102BB000CF3C668857C1137D12C6D7A3E3ABACFFE9 +:102BC00062F6B9659347E835F2F3DF6FCEAE84D491 +:102BD00044F37CCEF1ABEB83AF1AF8E2C6DAB70C64 +:102BE0007C7093FA9EA13DE2E9B252BC32B2276BEF +:102BF0003AC5D73FDB6D2F263C20FE0F16C6C4EB2F +:102C000022CDA3AB60ECB9ECF72FBC8EA3759D8CE5 +:102C1000577DBFEFD4BDC9F5485D84CBF8FDEAF11F +:102C200011BD4471D844F6CC5D12CA0BF277495EEF +:102C30007862E405401ED9FF7749A3BC44EFB6FD96 +:102C4000C147A9BDABDEEEDEEEE3F808C74D6A91E1 +:102C50002EC86E00A7787F81CDC176E81D3EE12F9A +:102C60001EADF8EA06B25F7320D58B32107FC27FAB +:102C7000A2B8C97C531AEBFFD55907B8FE61338857 +:102C8000BC514DF821F25797A6A60ABB58C1FE5871 +:102C90003F9161E6FAA11181AF981FF3C39CDF5801 +:102CA000DA5FC4F3C01319447CF833D9FFB5E05799 +:102CB0007780DA6B32D0DF46FAFDC4AC8E35116B0B +:102CC000ED1A70AD05F1FE49B2FA395934637CFD55 +:102CD000AE253FF3139BE0DF49BB4ECF53113E1FA0 +:102CE0009A24F6CFD5674C1CAF0167C4568D7ED8A9 +:102CF000038303561F8EDF66457BD2299ECF1E13AA +:102D00008DCB9EB0624971D024513A7DC2EE75F9E7 +:102D1000449E532F4710CCB09CE4D3E57CEB708AE3 +:102D2000BF9DDC6C07925B38BF42FE96FAAC88E32D +:102D3000F7CBF02F028117F71A5CAF6788FC05F11B +:102D40009F4742BF16F721FB720CF167726053B1C7 +:102D5000FDFD3DF66D84BFEEF51E16F1B0CF9A472E +:102D600073BC5BA713D9A7C5BD7F0C20DA2FDB4648 +:102D7000ED8B5F7EFF1D8ACFFDA63030D487ED0B33 +:102D8000CC7231C9C9C5A91D1CA72BF6C93C2FAEF1 +:102D900097F78B72AB117D7158EC88705CEF6CF11A +:102DA000FB9EF6FFD9CD9D1BF3395E2D8F25B9A271 +:102DB000CF8BEB28A675E8FBD4D7111DA777FED1E2 +:102DC000E3D07AFDE387D60CD7F20837FA13E8E5AB +:102DD000AB743AB6268EFBD768F88CC74FC18860B3 +:102DE00088E3796E703760FD5A0D4E9FCDC3FD703C +:102DF0003C44194FF85D3CDBE92538EBE3F7CB8029 +:102E0000C053BDCC73C548FF1CA2BFDB82224FA0BC +:102E1000B723FD893867730AD3EBE2E7DE7AE7E789 +:102E200038CBAD8F8E2924FDA1BF1F0F6784EF70B3 +:102E30005ACF0249E4CF10BE37D1F8F1F981F385BA +:102E4000EB89EC4ED60B27B6FD2C44EB3B91056E7F +:102E500013F2E3E27DBF7DD33496E8C41996B084C3 +:102E60005DC6F857BC9E7243E03A92237694236481 +:102E7000DFD8F5F7065A0CEF55672A77F9D81F55B2 +:102E8000EE2679645785BF362450C1F5E556E1AF8B +:102E9000EDEA34CBC4DFBB2C10223DBEFCD50C9533 +:102EA000ECC7E56877B0A79317E4F54232FA41E939 +:102EB00009EC069357E6785C5A600DC14BFAD1D401 +:102EC000079FC889FAA3BABE2CD2F4BD927F6303D0 +:102ED0008DEFD3E281686772BCB314029A1DA1C55D +:102EE000E19A0F701C4297DB3698EBA0F8CF9ABEA0 +:102EF0000B1CE41FCA382CC7D73CB3D3A0173B72B6 +:102F0000551D4ADA11D1BAB5073F5E3F1FC06BECC1 +:102F100047DB0512D6D07AD5814823FEDA3AEB7723 +:102F20005D2F60D932E691C84A6AFBE6B44476A4C4 +:102F300043B303B8E847EB14EFD906AEBEC384FA37 +:102F400033D96B81F763F4A00339FFFD3C6D5EB2AA +:102F50000732BBDBFF4078EB691F17AB24F8BC6F6F +:102F6000EDA5DDE6AD49240F12C28BC8C433FD18B0 +:102F7000D16332C4EC9BED9E98BA14072F89CAEE38 +:102F800076E57482FCE577DDD7AABAF0AB1F1AECC0 +:102F90008110AFDF6AF18317E9C9E6C176C3390C46 +:102FA00055CB7F220117C7ECEF1CF64576B955DBF0 +:102FB00097F522EF8BC6F5F7BBA4D7A75EE2EB0B24 +:102FC0005FE2F885EA4B1B7E4AF5A50D3FF5125FDF +:102FD0005FF812C72FCCBEB4D7A7CCBEB4F1AB5E9E +:102FE000E2EB0B5FE2F885AB2F6DF829575FDAF063 +:102FF000532FF1F5852F6DFCAA6C073ACB81CFCD0D +:10300000A6379A4374CE46AA0A73DE3857058E4710 +:10301000A73603E72BB67B851FA5C7E947D2103239 +:10302000FA2D567716D9D1DB1BEFABFC318E732A04 +:1030300013174FF9FCEC230A8DB36D1A70FEC2D939 +:10304000F8D1518A7FE540D81BCEA1B89A04E11887 +:10305000BBF4FA600A8463FC896AA58FA15ED43947 +:10306000C0D0FF964D430CED37B78D36B4FFA8A9FD +:10307000D050BF492D33F4B7434E4B1EE55D1B2D99 +:103080005ECA8359686FA567C20D76D8F83D05FF03 +:10309000911F9383167DF7B8B88F74D56618D7192A +:1030A000D77EB67C407C3E614EB1964FE8FE7E41B5 +:1030B000BC0F6E4FC2B8A79E4FD0F139DC92C4F856 +:1030C0005AA78A7CD39A69C28F9C1A729B286FA9CF +:1030D000E36FB44672FABEB7D519FDC9F446772539 +:1030E000FBA34DC0F9DCDC2A7348C9A138C1C04A32 +:1030F00007E239B443D04708047D841A81F385A1DF +:10310000AADC95D47E2A047C0A46A78FD1550B678A +:1031100052DCB53EBB5F16C51972AA043D2CDD6BAF +:10312000A4034AE7D256D30F4BBCFEF4FA8C02CA72 +:10313000E79D819727049CF5F3E7E97170CFDB6188 +:10314000C44B3CDEBE2D5ED614C77F57F2EDF06255 +:103150009B2177A4519C540599E2322F660F373397 +:103160001C9ABC8C9F19D88DF830A70938DF134FF3 +:103170008FAD7510AE8AE1DF1C6F5821FC4C93F2C5 +:103180002B99CFF0DDFEC0A744195FDB9A44FE16F1 +:10319000CB641A1FF6CA0328AE105267F3BAB737CA +:1031A000DB92E93CDF57F566A0F3F2DB73E40194B0 +:1031B00017DBFE8C696EECF920A40ABB3993F7612A +:1031C0003797706911A5A2956011ED6189EA835660 +:1031D00098E3F0A94AD49E3E2339EEB962A2FE5B81 +:1031E0008A73193E694A86015FD61223BF23180FDE +:1031F000E5A37C1C4CBFCB4457824E42AF4BA195FC +:103200001C5FE932D510DD68E72DD257CD06CA47DD +:10321000D567FF742ECBAF7A1BC31D5608BAD0F307 +:1032200082D6264187F1F4E3F21AE9C72A0D3489E0 +:10323000FC96E01F7D1DDB146DDE2C0954967BB6D9 +:1032400001C467D6B8F1EC243C49DE78045F3A61EA +:1032500036D07BCE123BE7B1413ACAF8B74E00E810 +:1032600013734E217EBD675DE777A4F30FBF239DE7 +:10327000EBF267AD57933F45E25CE429A46B8A1FEC +:103280004DADEA04FEFE0ADC26A247A4835959C5C7 +:103290007CF4817F76911CB213BCAAD3A8DDD5A99A +:1032A0004C25FA9D2EBDA2B8709CB587059DA37EC6 +:1032B0007989EAADCD16A0732628674C3FA2794BD9 +:1032C000EDEE952479A481E369DD853E943B1447B6 +:1032D0007CC5282F8A3A8D70CB8D97EB3DC0B127E6 +:1032E0003D110F47D7040D8EC508C721DF1E8E364E +:1032F000AFD0C3E92542CEBE98FD537ED57D589C04 +:10330000AB495780E1FA852AF4F274E97898E4CB66 +:103310003A05E50BB6CFD0DADD25429EE870CED572 +:10332000E0ACCB9375F32183F8DE4DF2C44970FD18 +:1033300088F5765B9180334084F39FA98AE09335CA +:1033400056F0529CB6ADD4E9A57861AEA2C1B7499A +:103350008397094C04DF78BA9421A68EEB4B8DAB92 +:103360007F5BF8964ED0F4643F283E1FF8AE4B4981 +:1033700015FC3654C0C7EA8CF0B9E6A61C8B77253D +:10338000F275470EC21BDB9B5E17F0FEA5D67FD5FC +:1033900018E07A53DFD5990CAF9C859944CF4DD670 +:1033A0003695F2584D3AFD69E7C25C9A9C9886FCC6 +:1033B000BD00DF5F8DF289F290A92501078DD794BA +:1033C0006F0189F7BFD99B68FF0E9FCD20072FABF8 +:1033D00031C235250E8E49DF91FF7F3CE1BBF1FF05 +:1033E00076FA15FBAD1906D0C979C89083E0642B35 +:1033F00099984C74D4D2BA9DEB32849A7271FF0FB3 +:103400003B85FDD5D23ABBD7F351214D2E6CA97324 +:1034100070795F9D9BCBB6BA4C2EEFA993D97E698C +:10342000ADCBE3B2A5CECB65535D0997ABEA14EE05 +:1034300027ADCDA860395C051CCF5E99F239E7DF76 +:10344000E3E7CB518D7A6C706DB201EE7D6618F5B5 +:1034500055BA62D457748E29B6DDE51D65684FC92B +:103460002B30D493E48986FE5326047E3981E48090 +:10347000A7324E0F223F8E899EB36B6915DF4BE951 +:10348000F0D3F59353E3F33556EF00CA3B395B05B0 +:103490009F366B765E13C111CB6405F8DC8CEDB002 +:1034A000E40D01F1FF6AA6F38771EEFE488B1DD98A +:1034B000D7286427B4C8C28EB78238F76BCBF4879D +:1034C0006BF07912EA2FCAEBDAE6A6B05C78D8E3A3 +:1034D000F4D239DB96D6656E5E8F579CA771E3BF39 +:1034E000447980F8F3358EA1C67339D6B39C6FFC4E +:1034F000754FF4DA9491508E9C2167BBF32FEF6BDC +:103500007429F22FF778043CED3DC8A3D6387BD957 +:10351000A9E55F60A02F61FFA83D25F20BAD717199 +:103520007BF4C312E66FDE9A2071FF3F4F9085BF98 +:10353000660903C96B9717DF8FF53B14F17DE8B976 +:10354000CE8F3F3E4F8C7C0A2407FE3C019F2B4FC1 +:10355000083B254916DFA1D84051583E81C887D085 +:10356000591FD237A95ABEA75BCE908888A13BE7E6 +:1035700019FEAEC88BD06716443F96E8FB17C4BF50 +:10358000FDB66523F9C3C37A69A7FC5002B9E02AE6 +:10359000D1BF1F832E4F3180EEBA23FC5C2589E119 +:1035A000172678359AD6CDC8C5E7A95E8B173100A6 +:1035B0001525F25E3A5FB14A4965FDBEAA446E2701 +:1035C000FEF942717A091FADF955ACAC93867DC8FE +:1035D000A2B7B1C4C676BA8E87246D5E444F679594 +:1035E0000E67ECEFCC9B11ADE37FCD6336725EAF1F +:1035F000E5AA4738DFD732EB3F38DFB73A6B7A1EA0 +:10360000C9BDA492E9C7F82097861F660DD2237919 +:10361000C6FCDEE9D3A2CE70A0F8849607048F31F1 +:10362000CF6791FD86F92F349E60A0D0436051F89A +:103630007B8333E95BF0B5DEAF673E50F5EF4E5765 +:10364000D2F9E0268F90A34DE07D3340F55724AFAB +:103650002AD3F38237E9BCE9EA8116C6CBEACCD992 +:103660004DC28E177E53936725E76DE3F5369DD7E0 +:103670008C95DB745E3356BE37C9B37BD5CB59010D +:10368000739CDE37BE9F1D34EA1FFDBDA4CC2B5FAB +:10369000AB8A392FD56CF13B485EACF2DC678AD53A +:1036A000730F2881052531E793AC99B3F83D7BB6BC +:1036B0002FE1BAAE50948544DFB8FF5EED81F59AF4 +:1036C0005CDCA8E997B3ED7393D6FF01ADFF66D23A +:1036D000EB23A2F8193EF4F26496CFEB441C8379F5 +:1036E00020665EA524B082D615C5AB390A17A4D3CF +:1036F000E1F957B0DDD1B06E7632E169E7FADED795 +:10370000A3E7D5F57E7A1E353EBF6EF3980DF0DF48 +:10371000A3C985175C0B2B1F40D0EC6C13F4D4B0FD +:103720004EE891E14F887D9C4987C6F5EE6CEBDD54 +:103730000E8AEF4F91C56E3AE17A465C7D405CFFA0 +:10374000DCB8F65171ED0571F58971FD2BE3EA578F +:10375000C4F59F1D57BF36AEFF82B8F6DBE2DA979D +:10376000C5D5FFCD884FDFB56989E0188F3FBDDF34 +:10377000B9E2EF5D5FC57EA2A3E13083E945A7B75B +:1037800073C543D4DEF5339DD94A46B17CDF81F65B +:1037900015D9433BDB2ADDE27C4760E56E8D3E4870 +:1037A0003F58368879D0CE4AE6F89CD36390236799 +:1037B000C3B709328CEDB17668EE85C7F7D9E93326 +:1037C000A4D917BDAF5BE7E32913FC27490E414895 +:1037D000F899BA5DBB4D15FCB34D5D50B99EE46DD3 +:1037E0009359C49FB5FB50E86E1D11270F684A38E6 +:1037F000C2F18426CD4F68D3E4C95A4D9EDCADF9A1 +:10380000094943839B28EE9B7C988FE740B3AFE048 +:10381000AF0B103FF797166FA3EFC7EE1E53F2F8EA +:10382000C35877FD5D827021DAE9635B14B259DA1F +:10383000948C243A4F946272B4939FB8AAB0CD3F4F +:1038400014FBADDD7FACFD79C4B39C69F3A2CE0758 +:10385000D9D265227A837C2F7F9786EB54C9C6B272 +:103860009677D5253A77BAF60AB7898CB0F419B2AB +:1038700099CE11F79910E85B8AF018DC046605EB25 +:10388000196A98CFE25C532A0BFFEA196428DE6FAD +:103890005716C1EBAB66DB7EAAF68C0F90B438DD11 +:1038A0007995FA38698234E887E38EB245ABAB8FFD +:1038B0006CA6F3D04E49D4A73CF3F8FC95F9D1FAA5 +:1038C00098671E1FB812DB5B0B0799489EA67B52B8 +:1038D00013DE137375A9909FDB9B170E4EE48FE9DF +:1038E000A53C13383021E76B25D1D4042C876AA579 +:1038F000AC3DCF14F52B35B8C9B55ABB4794177AF0 +:103900009EF8F1E794BA753B7B809F8D6CC877F683 +:1039100033D88B5797F6622FA279CCF1DAAD56796E +:10392000009D23DCDA6C03BAFF616B3688EF905799 +:10393000D9F8DC2858DC03AE7145D71D5AD56F1E67 +:10394000D14DC80486386EA6065FFB4493768EF28E +:103950009B307DC7B755CBF36C8588DB9D1F8BE70C +:103960005FCD27BCEA78DE57FAAFCD449F1DD90B57 +:103970002B37E27BEB1ACD1C3759D798CB744EE32B +:10398000907D746AC52133D9ADF9D06E263B7F1482 +:103990007D793D84AE400A70D9AEC9E7FFD4FCF80A +:1039A00061A0F0F341D0C5C0F9B438F01382CB1058 +:1039B000126D12F18FDBE4C07996EC4BAF48A4B7DF +:1039C000EB4AF5EF7AA1C652ACF91732C3B78EF8BD +:1039D000281EBE74429FE38E8ABF9EDA9D7B5F0DD8 +:1039E0005F86D5DD6F18E993F0363B46CF6CD4E0A7 +:1039F000E7F6FA15C2E1B5C581167A7FC9A6BF1EE2 +:103A0000207354565533BDFF14E11D9F2F0C07A79B +:103A1000D33063BCE14AEA3FBA76DB7E8AA7E5058C +:103A2000EFA8EC8FEB1BAE54577A888694C0FD3418 +:103A3000CED0CE48850BEBCE4DAF86B3783D6379C3 +:103A4000BC5C7D3D480FD54C476E11C7D7F04BF895 +:103A5000A773CB0B370BF8607B16EFCFE2CE8A5DF6 +:103A6000FFB669FDF8BB8578BA68D5E0F758148EC3 +:103A70006035FA358F2582A34EA73A3C6E78A26B4B +:103A800015E53AE7873A5F2439E8DFE49EC6F2B0ED +:103A900038F024BDEF6BF337701E7057275D47D4A5 +:103AA0000D1FA7D249D7BB603FE569C2FBD615EF12 +:103AB0005772BC782F88B8589C3ED44BAB129F6786 +:103AC00010F7E58CDB6BB493915E958D9E587A353B +:103AD00073BE33A4E9935013D22FCDB742D06F48B1 +:103AE0005DE64E44678F687A658746B7FAF3A13D75 +:103AF0009CBB3C54DAED27664A46781EEA8DEFD32C +:103B0000C0CBFC807C7084FA65101F607DF00A37A2 +:103B1000D3A7CE074BF6FEF500DD67E3F4C905B188 +:103B2000F7D745343C227DBE43EF2FD9D475807C36 +:103B3000C5C12B047D7E4C77871545E90CFDC7F781 +:103B4000A89F4E3FF1FB78571B4F2EF67F4C785CB9 +:103B5000B829C8E321FF1C2BE5713AC349CC724A4E +:103B600025ED676B1BB8693FF65F1474905C3855A0 +:103B70006B62B8DE981F5E65C6F2FAA160A5EB869F +:103B8000AA33916C72298F6BCCFF0D6B33E20FE976 +:103B9000E76F344F91276013C1EBA08DE5690F7477 +:103BA00011D57BAA0EFF157172D73CB1177A3ED79B +:103BB00071D7162B8E8945DF621DE7D84F8F379D51 +:103BC000193F1DC5FE434BD36CFD9CF00CBA8F67AB +:103BD0003BC54F11AEAB9A7AB7572F58FCB4F9A436 +:103BE000889FAE008E03AD4C196B4A44379740FC5A +:103BF00074CAC444F1D3C87B063B735593900B3A07 +:103C0000FC86578D4C16792948A57C891E1FD3F751 +:103C100075B7664F3669706B21B8313C05DCDA0840 +:103C20006E0C4F1D6E33843F425F8853BCD66316C3 +:103C300079B1910B3651BEE054A6C893D767DB44E7 +:103C40007B8EC82F9C411F9931F634F2C19A667160 +:103C50009F08BECF79B517B30F3886509E33D3CCAB +:103C600071DAED9EFB6AB6733D99F9CF0A6A5B1E65 +:103C7000CE3BFCC3B9EA027A5E62E773F27A3EA7F2 +:103C8000A5AFC8E7B8F2B47C4EDC7C76B8A9B28D9B +:103C9000E6CB137E4B8F74ECD3F2115A1E2823DF30 +:103CA00098AF70C4E52BE2F3956B9A17ECDF2EE228 +:103CB0002B2C9F87FF7824FB63F1F3B8671AFDB7BD +:103CC0003523753FEA1147A2EF1852AB8CF4D8A206 +:103CD000E1BBA1AFC8479C6D7C284F36F8552D79C4 +:103CE000E71647D0FB911FEA4ED03FDE0F3D1FFF86 +:103CF000D6CDE31BEF074CE0DF6E99C8F11441DF2E +:103D00006B9AC5FEBBE3699A5FA59F3FD2C7B16AB4 +:103D10007E1CD773A2724ACF870D75DB985E876AC7 +:103D2000F74535FC7B4A68650EE5D76675513E72EE +:103D3000E80E89F3EE439D7ECE43746C98CEF9F184 +:103D4000BEC981A727C6C49F76B87E9AC9F9022D3D +:103D5000DECFF7E6A0DE53D715762A64EF8E04BED9 +:103D60006727392E1F107F3F4E7C7D4E99D0C39917 +:103D7000D741C27B4F3E9F28DACFF4DFAF6038A136 +:103D8000BF9B2CE4ADA2D7FFBFE4A976B61DE2EF3E +:103D90007D4EF94093B3FF0997A29C3D5112389E86 +:103DA00050CE5ABA58CE8627289F919E5C4E177DDA +:103DB000101E6E4C7C3F8F5C76A9E2E16981877CA6 +:103DC0001D0FF75C92F942C4437659223CA05F452F +:103DD000F06AF32983A85D29510653D98D8F1F26D8 +:103DE000E68B5965C2EEBB58F858A7E1E35EC207FF +:103DF000C769642D4E93C7CF9B357CAC39031FEF49 +:103E00000B7C94E8F878EEBCF09151956168779757 +:103E10001BF191EACB35D49DF9467C240F2D308CD3 +:103E2000B7BC4C16F7240D9C68E877263E8CFEC084 +:103E30009DF45E2FF6E8C04067057D4B34606E7BD5 +:103E400007C9E64C7F5B0595FA3E37C7F9737AB927 +:103E50005CC35FE6D4C4F85DA0F15BC644E526030D +:103E60003D7C2F317FD668FD979728B794C5F2F334 +:103E70009589FB2FD1FADF3641591CDB1F7FD64BCA +:103E800031F6784FFB0E242BCBCB78FD224FB6A317 +:103E90003E95F3663B92E476CA57ABF54EC3BD75CB +:103EA00083E937AC67FEE89B0E95CED9D13D4168DA +:103EB000596DBBA35FEE1A6CDA96317C25C1B1A9AE +:103EC0006C88B8BF7591FF6DCAEF28EA09ED1CD266 +:103ED0007CBEEFC814EE63A27BB2C09D714EF92385 +:103EE0009467E25EB7C120BE238620EB41C90FE98B +:103EF000F4DDB205FC225F4EFDC5F785BCF9140860 +:103F000073DD0511AEA7697EDE0365393C6E3AC8E4 +:103F1000260124AF89E4A8CEA70E4F90E9DF53EB2A +:103F200036AD245FCE0250467EA073207FCF0B9526 +:103F3000A0523ECB040EB6334DEB0F7CCD793AFD4B +:103F4000FBC397FB88EF0FCF717FE7DAAF91EEE508 +:103F5000F344EFE56BD4EC01FD5E3EB532C8DF976C +:103F6000AB2BEDEE06CF99DF973F3A31B08BF0FDEA +:103F7000B7A4412191640E4E98EDBAA0E3872FF2C9 +:103F8000F8AF5CE4F1DFEC6DFCBBE9D752CAEBF9AA +:103F90008F123F37B88AD9EED4CB78BC5DA12811F7 +:103FA000EA27395E1BF0619FA83DE73C6A627FA863 +:103FB000C124CE9FA9EF99D8EE827C41074E19F219 +:103FC00072C645C7717A838345DC49C45FEAFF74D2 +:103FD000D708B2BF7F99322B9286E31D7C55D87FDC +:103FE00096A991CD74BF73FF349B773BF2DD3DDA28 +:103FF0007AEDA513EEBD137FBD798A90172E8BF74E +:10400000F2023EB7343342F6A3ABD82253AEC01906 +:1040100097D76CB5B42553BCB275C77D15A3B0FB5B +:1040200063752FB91B137CEFE9D4F29A23A5C472F0 +:10403000F09F939244DCCB67BC4FD85AAE9D2B497E +:104040008554B2232DFF52D2129D07D04B7DFE2204 +:104050004FA48ABEBF8ED0256E88E7A292EAA464E0 +:104060000F9F8BE824F8567AC30EB27F1F5F10BCF7 +:1040700035F6FBD3D61270911DEF9B22CEC36E5046 +:104080002417DDAFF160C4C2F78E3FB8E8E9E6144B +:10409000ACEF3D6A76133C5AFDEF3993B1FE388E92 +:1040A0004BF2EEE00E71CE529D0FA16108BF56F2A9 +:1040B0002AB1BE5B11E7B2D9212BD6AEEA43F8FF95 +:1040C00075725F016F0856D3BD9DEB5226F37D9646 +:1040D000D973443C78BA74B483DE7FB0C4CEF81B85 +:1040E000A29DD331A9D57C9F65DFF9C6733A0F2E07 +:1040F000EF5409BFEE52BB5BE5F3974ED7587CDF18 +:10410000F5A8192456715D3CF974C929D6E5157EC8 +:10411000EEE37258A5FB8EFBE27BF56EBE35D170E7 +:104120001E68F726E19FA68D777A91D271BD71E75F +:1041300085F475B5E1BAE8DE63D7508E4764CC31BB +:10414000AE2F2DCE6F70C6D5A79677DFE3339CF0E8 +:10415000FD85FFA785AF71AB574EE47FB6D64167AB +:1041600055CCB904670F71C09AC982AE6D592F380A +:10417000C84EF9C27FC4433878E59F073EBC97CA52 +:104180007FFD6ED75284CFEFBF7E73C793B4BFDA83 +:10419000BB0F11BDEAFE189FC1C4F5BC586D63B8D2 +:1041A000F96768E7397D1D2F587DDCCEF9A5B5FB91 +:1041B00093B87D64398492B07DA445C9BA99E8AEBC +:1041C00053F2D6CB3488388FA8E37FED0D7E138C65 +:1041D000213CFA25BA0F639A76BE76C3229009FF76 +:1041E000B645ED7C5EDDB75C9C57F729D5497CDE92 +:1041F000748E99CF87D4575F73F930ACEFBA5CDC1B +:104200004F3563B9328FE75704BDA475169B9713DA +:104210005D6689FB9AF4F3A645D0C5DF7F8CF4B6C2 +:1042200077D848DECC4700D3FA5A357C69718322AF +:104230005FA74AF6A4CB6BC463461CDEE2F1BA4228 +:10424000C7E34818497894A12D99F4E14300ED742F +:10425000AFC086E54FCFA3F36C5FA8690CAF9EF8A3 +:10426000F91DB4579511740F8B83CB4EB457A9DC4D +:1042700085F62A95AE60C575CB71DD7BDE38F8D248 +:104280000F71BA594AF5957444AB48CB7B81BA7427 +:104290005025AEFF06E25E51DF4289C4777D92A1D0 +:1042A000BED66389FE3D00FCD595A5FF7D80D35B1E +:1042B00094A108964C8B968F11F559E487C4B4EFFE +:1042C0009E69EC5FB63F66FC81B8DEC5366E0FEDC9 +:1042D0005BBA45B5C4B43F87F572805735FBF1FA38 +:1042E0009D66FFF604F2EDDD7261475AFE052AC9AC +:1042F000B52FD14E23FF5E322B2CDF21D72227BAD8 +:10430000570F00E561AC5F2E1BE5EBE51A5F58FC2B +:1043100015A0E5C7E01B3DFE803F7BFE388BEF63B9 +:104320005A35C4C2F70FA13EF0F696AFB3782C9F72 +:10433000C6DEDBF5AC2EBF87C1309AFF4B28FF43AA +:1043400005F341CCBD0DC4F76DCF5FB614E7F11D89 +:104350004DE638AAE45A9FC2F731D535B13C7F40CB +:1043600009FCB63CE67C4963FAC242922FFA3999BD +:10437000E8BD47D798BFCDBDF71DD50780F4C297DC +:10438000485AF65EE8B0B16EEF115AC7EABA762E17 +:104390009D6E85858DDD12E4B8CF154AE04FB43EA1 +:1043A0007B26B6C7F089D58DEF19FC0EE37D9CB254 +:1043B0003BE224B86F28F9C049F3B71E167CBDE173 +:1043C000F0EC24E2BB56EFA124E29B2FE8E2C7EF1A +:1043D000C0273EE5559661BBDF48BD9EE8674F4369 +:1043E0001ADB150797DF7F2DF1CF8DBFF801C3BB17 +:1043F0009B6FE0E14195CE18BE818799AEBBF9462F +:10440000ABF7CC377F67BEDADDCD37A2EECB074303 +:10441000FDE04C63FF6EBEA0F1912F1EAFB073BBE9 +:104420007DD2C35BD418BE3A49F558BEF909F24DA6 +:1044300002B93F7D9246DF17986F522E32DF0C9DF6 +:10444000A4C9CFEFCE3763275D14BED9633A1FBE30 +:10445000B9EC4CBEA99AD4F7DBF34DAB3BCCE7E902 +:104460005AE79813FE7D900F347939757EA0B28D8E +:10447000EC1A45DCDF374D9A99E5F3109F497487B4 +:1044800034EA4FA1CF0F5EDFFD7D06EB67FDFEF541 +:10449000F58450B293160BBAE9AC1371DF6952F987 +:1044A000B4C5A477E93B024A3553F694EC02D4FB39 +:1044B00032D985D05EE1C179365499A04DA62D0739 +:1044C000AB87F1F861B6CF8668717FA7942FBE677E +:1044D0009A29FEEE85FE5D4CB562BC5FB6FF59ECD5 +:1044E000265C770AF931EE12F17750164D8AD7BF64 +:1044F0006887E0FA3A07DA984E362857F71A273ACB +:10450000E35CB52F98302FF9D6249376CFBEF233E3 +:10451000A2B3DD6F6C49A673127B24E0F339F383F9 +:104520004FCD23BE73A942DEB4AEF833A52361D7C5 +:10453000B41F1AF5347C6AD4D3F0A9514F6BF51E21 +:10454000E58D7AC2A8A7B57AB79ED6EADD7A5AABCE +:1045500047E5CDA7063DBD61D2A70679F31ED5CFAD +:10456000414F1F9E7471F4F4A88B2C6F9EBE70F2A5 +:1045700066DFA4BE1743DE1C392F79937DA6BC39B4 +:10458000743EF2C6B5B943A5F4CCC21EF8A056C31A +:10459000FB5B65CADB343E949C5BBC269EBE3AAA9C +:1045A00017AEA6BF2BF3A557F87F3DBDEFAAFDD5EB +:1045B00091C6183FDC65E914DF23D4EEE1E7B76C60 +:1045C0007E95E3B1675D2F5D105A74A65E45BBC84A +:1045D000C1F4EB35732EFC7CD7D13A47F0DB95CF95 +:1045E000DEC1FC945C6E9C4FB77F3BAA6D669EAFAC +:1045F00044C8E99EECA19EE6FDA05C16F7FFC5CD80 +:104600001F4FBF489FE9938B981E2D742FF8179D5D +:10461000C07FA7EABF4E6EFCBF8A7C49E9C51193F3 +:10462000CF834EA76BF84CB06FEFC5DDF705E3CF36 +:10463000E993CFC38E3E4CFBEE9B70DFDF67385EA5 +:10464000B47D5F30FFE1E6F3C1F7BBE5DDFBE6EFEC +:104650005132B47D6FF8E735EF515C63C3BFAE7D77 +:104660008AE21AF77D9DB78DE21AFABD726910FDD4 +:1046700091F5EF8F102E2EBFF89E24634ECC774518 +:10468000C0FE7DF4BB13B2377CDDEDFF2BF7CA9182 +:104690007DD2DBBD72AD36635C4F2FAF2A17F64A71 +:1046A000AB691DC72336A05F558F78EB9823E211C5 +:1046B000AD68A7B0DC9953D0AB7DB4AB4EE1B85335 +:1046C0006B9D9FCB7BEB6670B9EBB5256524777D41 +:1046D000AF2D62BDE7F3FAAF7B1881E4AEF8D049A5 +:1046E000CFEFF5E8FE90B05FD2C87EC1FAC393D792 +:1046F0006F8D8D0B8CFAEFE15BD481D178555B66C1 +:104700008CDD23C7FA51A012B944FD28AC1BEC9AEA +:1047100011EC47ED26BB06EBED934718EC1A7D9E96 +:10472000B566A821BB66ED0EF38C4476CDACF2C421 +:104730007E14D6390FE27039F8FB7F49FBFB5F51DD +:104740007EE9DDAEC99D7271ED9ADF4FBE30F18713 +:104750006E3ED6EC990714E50D4DAE7C47F9B1D10C +:104760004CF1E36F2B3F4692FCC837C88FCFCE4742 +:104770007ECC2A771BE2A20765B5CF58B2D37798D3 +:10478000A15ED6F42FD63BD1AF31219C7E5221B110 +:104790009FB3C10BFCF7FDA64BF35F267AD8BDC8CB +:1047A000CCDFBB3FA88873220FCD11E7A91E5E5E48 +:1047B000309B3E235A9772C3DD4914D72E17F70456 +:1047C0004C97CA39CEFDE00C61E7643BDB2FA7FDB7 +:1047D0001FACB000D1D5D9E2DC146EE778B5E6475E +:1047E00081B499FD0ED70F2D6E3AAF1A1FBF769682 +:1047F0007CCCDFCD83F40A7FDF7DB6F8F5B78D5B27 +:104800000F98F29DE3D6CC8F35CF0DBF41759E49F1 +:104810009F4726CBE25C620F7A2C9E9F3BAAA7A7FC +:10482000457A3917E524FB29E61E59FD7BD659E563 +:10483000621E27D94F8551BAE8A82EEEF55EDA94AC +:10484000DA678EC4E685522CED3C5E4AED3E7EBEB4 +:104850009ECE2F90CCB27859AE3E5E89F239C178A7 +:10486000FBEA8287092EBFAEAB3D4C71EA49964EFA +:1048700089FE9EEBDE3A95EB7BEA9AB8DC55D7C60B +:10488000FDD6D76DE2F2BEBA103FBFB7EE31AEDF54 +:104890005DD7CEF5C773C53C132D211E6752178E09 +:1048A0001FC30F659FE03C31782E8DA886F6096FF7 +:1048B0003619DA8B3ADB0CF5BEFE4D86FE7D66843A +:1048C0000CED6F950502538AE85CC363867ECEFCCF +:1048D0007643FD5CFD850BDD6F654AAAE51FC8AF19 +:1048E0008302484F4867E9B5B2CA79F31AC197FD08 +:1048F0006BBD61AA6F71D998BF75BAE433CB26B18D +:104900007E53CC3DB51D2E717EB2A1AF88A734FC7D +:104910004CD4B76489F391C3AB447EA461A0B8972B +:1049200044CFC36F7169F793F8C43D1A83F223FC37 +:10493000DDED20EDEFC139CB45FECC0D6ECECF378E +:10494000D481F67D6284F31D1960F68AFBD5159932 +:10495000FF9E920542F5385F43BE5BBD85E44C3057 +:10496000D56BF6F29F960D99298F48E2899330ED29 +:104970009ADED1F2F2491F009F3BE886CFE7E27B47 +:1049800084DA2EBEB7A97F6D17E7E3B6FC42DC637D +:10499000130FD78E5F7CC5F72A6DFDD95759C4D444 +:1049A0005BBBCFED7425C57E8FB6A52695EF5BD892 +:1049B0005A9BCBE728B6D688EF8D6510FBDDB2C8D1 +:1049C000C6E730B6D69ACD24274F2DB2305CF4F529 +:1049D000C7CFAB7FBFB94E3BD773AF76AE67AD766F +:1049E000CEEA6EED5C4FB376CE6A8D763E76159D3F +:1049F000EBB1133CC5B99EADB50B14ED3CAB7E2FAE +:104A000003C35742F8F2772A56D86B1A07F4870C7B +:104A1000196EF1DFC7665425C79DE7319EB74AF589 +:104A20000D30D49DF9C6F356C9434719CFA90E34AA +:104A30009EEFB1798CE77A2CCE4AE3F9D058FA444C +:104A4000609A566CAC27FC77FF7D477AD88FFF7E43 +:104A50005C37FD86F47340129D4349637ACDAC12F6 +:104A6000F499A17D0FE3864E2E53915EA874529E59 +:104A70005DA273902AD351F4FB37A5577A3ADFBF72 +:104A80000720AD4CFCF700F473087FD1ECA8A553C8 +:104A9000944FA71445E7BB7F8A723CB6AE973DC9D9 +:104AA00085FFADF2FF01C18CE32B00800000000008 +:104AB0001F8B080000000000000BB555CF4B1B41B9 +:104AC00014FEB2BBD144A35934B6865A481A520DCB +:104AD000A4B06D37A225D2D5869283C8163C78E85B +:104AE00021879CFAE358E86D635B904A24A9422F22 +:104AF00052C8C11E0A821EFC03621B7A8E680B52CA +:104B000029C18AE7405B7A11D23793AC899BC47A7A +:104B1000E940F2F266E6FDF8BEF7E6E50D68798158 +:104B200090A2DD137D40245A2A3848065468B930D3 +:104B3000305324E9A2FDB5AA94359114C0A9095CAB +:104B40009ABA1E2F4912D9C9163BFDD4CECEEF8D8D +:104B500031BB0126252EAF1F39000FB015B3E51666 +:104B6000FDC0C20E9DABC0EF315B0E7E96DC49A549 +:104B700032CA4D01917D69BDDE4BC02CFB49F17AF3 +:104B8000C73D0309F29F3180FC30BBF3D0CD745791 +:104B9000343BE5A33C427B4548E42F5284DC078646 +:104BA000AFAC81F6E7AFDE17258AFB6109B84CFB95 +:104BB0000BF652EC11DDDB1AEF945F28CCCFB4FD7D +:104BC000299DCF5C1121325DB71F962855D860AB67 +:104BD0005C237EA25255A755A1CF0334E894F70C6D +:104BE000D347EABAFB243029535ECF0FFC1B8591D3 +:104BF000BA5D805261FBB7B51ECF71376D8410AAC4 +:104C000088751C15B6EE36CB3F866FA360673821DA +:104C100030BED43D21E7A738BD5F96BB183EB1A892 +:104C20008B25B2478C508F13CE3DDD8D73FC7D6795 +:104C3000FC7502078683CBA22173B9650C72796C6F +:104C4000F8B83C3246B83C34142E4BC61897408A0C +:104C5000D7B3D3061E2F63C47763C1F6F1645B59E3 +:104C60006775C78484F7ACCE432AB76BBA17253F64 +:104C70000D7C115DBC190A3D6F2799FDBB27028F82 +:104C8000B91ADDF4EAE166FBD56753E7E24E1B7320 +:104C9000BBAFECEDCF5D1D486CB6F0FBB2D6C740A4 +:104CA00096E711880B58A43CBC0EC529D3FDF4B679 +:104CB00093F7754871E49C0CDF9A0B3F4C1CD43F72 +:104CC000CB696A19829CD524997AEAD46F8F42F90C +:104CD00034F45560FAE320AB677A223FA8138ED5EF +:104CE0009B9FE786C92EB5232288E6BC5E6B369E65 +:104CF00097892B202982DC027F3B5C8F6BF618F2B0 +:104D0000F0B960E5DF7ADFAC3BADB4345A7BA2B4D6 +:104D1000125D898C4675D2D66D9C07A70FFC7D77F6 +:104D200040CB33BC17C80FB8433CE7238994AB9EF4 +:104D30004FBB3A997974D7FACF9B2C3B12846FF909 +:104D40001F7DD8672F3A58BD9692423CD7228FF5E7 +:104D5000DA9C5B526F39D97B44B8751EFD716B9F2D +:104D600056F35991C83F9B4F2AF96FC1F737C67761 +:104D7000B59FF745AA6B46137CAC9FFB891B8D4200 +:104D8000F547904B116FD9A8A0E4E9FC97DAA17020 +:104D9000F796F9D0145F6DE8A36BCD73675B73551D +:104DA000E74D1041366F7E0ECDBAF32DEA6B4A9374 +:104DB0004773EE34F358AEE24C567122DCFA3DD71D +:104DC000EB355F1BEA488867FBE6EB797DD38E7F86 +:104DD0006B1FAC2475779EFE1FF0691FBE1B8C8F66 +:104DE000B3EFAF1D6F569E8EFF334FD6F3A23957E8 +:104DF0002E88F3A2F74CFD2FDBA790A6F00700004A +:104E000000000000000000001F8B080000000000F0 +:104E1000000BFB51CFC0F0030977F3A0F2BFA3F161 +:104E2000D7F3A3F2CBB851F99E68FC2634FDE7D145 +:104E3000E4591820B4233BAA38B158988381410E15 +:104E400088353950C5F3A1E6D6002DE807E215AC48 +:104E500084CDFA2C05748F1C03C32920DD00C4D730 +:104E6000651918D8817C216906065F204E00E2CFC3 +:104E7000320C0CB380F43B20DE2A0DD1C707143B63 +:104E800027439EFBBB85C8D3378AA9831F28A1F27D +:104E900067683330DCD66160D0D683F0AF20C9BB01 +:104EA00003C5666A43D831AA0C0C877419184E28BA +:104EB00061373716287F18281FAB87DF7E572354AA +:104EC000FE2E6B54FE4F4354FE134F547E9F372AE1 +:104ED000BFD107420300BDE0D98DD8030000000018 +:104EE00000000000000000001F8B08000000000010 +:104EF000000BCD7D0D7C15D595F8998F376FDE674A +:104F000026C90B3C20C02404891AE8000182224EE5 +:104F100042B0C14DF181546997EA93B53622C81366 +:104F2000B1A6AE6D26DFE1AB8DE85656AD3E586DAD +:104F3000A9D51A2D6D6957DB04D0C52D8548A9B5B3 +:104F40002DFB6F50575B16D9E816755D5AFEF79C1E +:104F50003B93CC3C5E3EECC7CFC6ED0E77E67E9C25 +:104F60007BEE39E79EAF7B9F220640BF1CE01CFE14 +:104F7000B1E7452200CC197C462BA0542E07D8243B +:104F8000048D70117BFE415AD91566DFC08A2F9FB0 +:104F90003ED8EE5A10A8FEF3456DF13EF6BD63EA29 +:104FA00057E350C6EA4F14A8BE53CF79DE0812402B +:104FB000014049E76A35C1FAD934AE49C5FA1DFA4C +:104FC000F695C0C63B53A28084E315656FDFD6001B +:104FD000D03D0DE072D8AA16C758F998646C866C5B +:104FE000E314D1384ED91F17A1BB14E8EF1CFBDF27 +:104FF000A62F2621C1C66D9DFAD59508B7D27D335F +:10500000E811803BC6254167EF678248F3522A2C9E +:10501000305959D5ADB835FDFC713A102F65D86BB4 +:10502000677C7964F0FD32072F0C1F197801B804F2 +:10503000408359DD16960340ED33FB35EDF1B5F8AD +:10504000E8C63F7FFE7CFC19A0131E40ED8C272292 +:1050500083F06CF2F5774B0CDF5611188FB12A39BB +:105060006C9C4A573F99E30DCC53EEF4ACFF74842B +:10507000B380E621C8AEFE32E1996BD79BCB668E3A +:105080004F675E390BF83823F57F25A2B800EB7720 +:10509000C6AD888B1E65CB83F7A05D5F33BDF586FB +:1050A000C24F08F13307F163C5911E1D3A96C27ACB +:1050B000630D9B4F8105FD522E918D096300F2F126 +:1050C0005FAC89ACE99548AF634C56977D1F1BB325 +:1050D0001A25F67EDC82B420B367041ED2DE0801F6 +:1050E0004253728E1A599CEEBB6677F431BA3D0377 +:1050F00091CECDECD92CB37E116FC723E9C71848E8 +:105100008D97A51EE963E588254353398D4B7C783F +:10511000A77491B19991F4669BFE3B1A547AB63507 +:1051200068D0ED07686988D3F3FED097BE81FDD7BC +:105130005B7ECDCF9E72D7ED4F61B9192081E345DB +:1051400062BC7F9055ED310DCB6022DE2325FCF94A +:1051500012E285C1F9558649C4CB0F6D3CE9D04DAB +:10516000FCDA6C2CCF812CF8749EA1522F9F05F491 +:10517000206B3958F6C7F33C659F36DE531FA0906D +:10518000F04665262AEA042E8F22722F180827C3BC +:105190005756B960CB15499AD9DFCDE6179EA718A7 +:1051A000BB58D36D8297BFC6099C3ECA04959E31F9 +:1051B000E8DF7F0EF16288E9CD6CACE0CCE2AEEEC8 +:1051C000188EA91853D93A067D692D2F0B7F41B946 +:1051D0007CAACF81BBF8A3C78F24F5A41259C6FDC2 +:1051E000BDBD7E979F3DA222FFAB33C544BA0CE103 +:1051F000B5126CF2B05597459CF74707F7F0EB7581 +:10520000C2E6E73650A9BE8CEB553EB85E1D065B84 +:105210002FE49F72BE5E1DB2A58E66BD1E07F0E034 +:10522000253480972E8E97B28F182FCDFB5626B23D +:10523000CCA3CD5E4F190CA394F0A0E808E7D646A6 +:105240004EB716A3DB6CF277283C4839C7E3C9B2E6 +:10525000F3F17E8DC0C75964F38983A74D865893B7 +:105260000E239E3A6B506E6D2D1145944B1F159E6B +:105270001CB8360FC095E670957EB47049A1EE95C6 +:10528000D9F8B12D831FB720DC9CEE6A38DD891F69 +:1052900029DD397005901FF83A27F83ACB7F13EBD8 +:1052A000DC36B0CE49BECEF18F669D9DFD1C5463A9 +:1052B00025AE5B9DC6F890C1718B642937E0FE1A5C +:1052C00012E03183D101C23F8EE999E1A697751DA5 +:1052D000E03E21C0F50D69554ED2056F9DCC749608 +:1052E00059F87EEB05C961E601695F7F9F0327E3FB +:1052F000DFFAE38DED075C707E5188C408CE79300B +:105300000FE17C27BC3CA71B86EEEF6483DA28FB09 +:1053100000DE6BB0DA0FF8CEFF7E8B04A96CFAE5E5 +:1053200083B65C00B54BA1F9DFCD787026E2E1824F +:105330006A88B2F508378DC17940987D9CCFFAD93B +:105340001D68945DF81D6A3E037875DA3175C79F54 +:10535000777EFBA1DA7D20241F11187E5B63623506 +:10536000C2A596401AD7C0BF7B59F778181ADED667 +:10537000D85F06DE21D7CDAEF74EB8A90D58BB6673 +:105380009F71506774D252201A4D300887432FCE38 +:10539000BA38781CEDBAFC6680BEB65E01A467829E +:1053A0002ECDFCF3E9EA20D2D5C57F7DBA7AE36F32 +:1053B00097AE4E0A057FBB74A5D44BFAEBCCCE2832 +:1053C000924D2E27B5D516AD3F8ECDE492D439B38C +:1053D0001BE525C4997DC68701919515CDE47A2FEB +:1053E0001880FAAB5AE29593BE42AF9C8CAF34BBA7 +:1053F0009D7E37EB38AE42E3A27984E3CA61E80EC2 +:1054000044B1AC503F48CEE7A6303CC18335C5BC63 +:105410009D81ED869A8F8CEDD878A87E9C2BC276E4 +:105420007F9F93C862F70ECEDF3B4E7C452227114B +:10543000197D7D08CBFA1B2EBC0FDD4E86371CBCB8 +:1054400030FA2F453F49C120FECDDDB791FF220044 +:10545000A241765D619B855FDBF1FFCDC77D9FF348 +:10546000757BE12C0DF52D60FB0DBEB784CF039647 +:105470003F1074E25B673C299C00A21BBBDE48EB3B +:105480007F27F25316FE5E25727DE3BD2FA5FE1B1E +:10549000ED416BB3A03FC6F07AB8E17D788DF1E5C0 +:1054A000EAEE0B15F47B5C2F8EA17AAB1714298BD7 +:1054B0005CFDAC066E1702F4C9CB22EE711BB91E5F +:1054C000DA25EDC379BF5A21A571FF7BB5E27F488C +:1054D0003F7FD594D288E4573BAECE194EEE1C6E7A +:1054E000E0F6AC53EFB029D1FE7E58EE0B67D3E364 +:1054F00007C74FD3F8575548DE7D5AEE9371FDDF4D +:10550000FB22F8507F3EDCA00AAF4D65C62FCE933C +:10551000D1D1EA8A2205FD0E23CD6B89ED0773F008 +:10552000EBCCB3252CD23C5BC255E4B76AD1DE216B +:10553000FBF10C7B8FF26028781DBF558BB63C2B9E +:105540003E9408D7B7145F32BBBD69CFD72967FA3D +:10555000B31CF8DAC2DC2E6A0B73B8DA62621AF98D +:10556000BF2D9E7D5CE7D96CC3E7D46B8971BDB458 +:1055700085C993D1C02387BDF030B41D457FC94490 +:105580005BD6E4D7F6367E0EEDEC64D8940C7CD373 +:105590002B4C62E5097109366B6CDC9AAA8E6AC6DF +:1055A0000279AB122F3230602C7456A21F70F217A2 +:1055B00037F67C8DCD6BC27CBF86EDF26A523DCF53 +:1055C000B176E399989358BBB1C7D7AD4339FB4F38 +:1055D0006827A220B66E6A443F560B0E7109C0C3FD +:1055E000E2AA4AF4B3C9C0E502937ABA3C06FD3395 +:1055F00040CE99A1E403FB13CEF907DB0D85B788F4 +:105600002DAF68DE24AF960F2FAF36F2FE2DF61FBA +:10561000CA9B0983E351FB71758A078F6333BE1FF1 +:10562000B0E9D20FCBFEAAE38C87E501D44F222B41 +:10563000442D8DF5A12B17FD5063D6CAD08DDFCB3D +:105640003B1B99F81811EF4CEED570BF715258E61C +:1056500082F79722F7334DBAEB9820A0DFD7602A64 +:10566000FD4C2CD7CFCC46A7DB6DFA1C28D7AC1647 +:1056700092345E62C954946BB522D9BDFFB46256B0 +:10568000AEBBFDFBF63883EB0FBA3C17CB7CFDE5D8 +:1056900015A21998F1A7AFBFFC21D73F7FA3E2D98C +:1056A0004F3FECBAC8687B148CBCFE7FEE38CEBA94 +:1056B0009DCF1F5C3E4EBAAB3A80F2EFBEC4F07293 +:1056C000E5FC755B4EEB36660598E92C72252009E2 +:1056D0009E7DD579AA900283ADB3744C22F9268DB4 +:1056E0009DBB72270C3DAE145332EC37BB3FCBDC75 +:1056F0005FC2D6FF13E0FCF5CA28876A510EA15C91 +:105700002AF7BDEEF68F308C0F9619EEDFFAC2FE47 +:1057100003288F2C268FD07F9AF9BD16CB2E7AB80E +:1057200042E2FBEFBEEFFEE202818D73C4F0EB7E3E +:10573000F6EA90D0FB06F97D2B25DA8F113E752E07 +:10574000B607524E8E989259CDEAF7960BB48FFA5F +:10575000E1A5EBFE91DA8728DED1BBE0B52F5FCA69 +:10576000DA7FE2321F720EC704B68FB37FA25E7378 +:10577000B6EFCB97B2FA872ECB1F56DFAAC5F9BA80 +:10578000E8E4AA67BDE555486F08FF7FBC59FB20D8 +:105790001BEF08E424FCF8ACE0F01D41F890EEFBB0 +:1057A0007EF506EA85874D81FC51472A7E16437BAC +:1057B000BCD214485F5CBA4048FBB3CC73E982DBCF +:1057C000264F62FD258C901660DF0F55BEBDF55249 +:1057D00006EF553F90B6E1F3F45EA920593634BC8C +:1057E000CEFBAB4CEFFB01BD189216E21D341E97A9 +:1057F000F0C58CB89B5E07F418396166F3B7AD95B8 +:10580000B8FF51D00CD2EFE4B002388FA1EADF34F8 +:1058100004FDE6407FB7847038FAF7D9AB75B73C22 +:1058200074E050E44412C791340576A19E917B8DBB +:10583000EE9E7F83C4E34242DC2478148DC3A3C868 +:105840008699CDDF546FC3E3F403D069B7EF87BE09 +:10585000F0207CAD81C44AF45B58B9DC7FD812F1EA +:10586000FA03F7D8FD3CE6F4E783AC71158026EA2D +:10587000BF6A4C858AFD3757703D490783FCE32D8D +:10588000CC6E8461F4BAADB6BCD88CF10D3FC6398C +:10589000343BCE11E7FA53F819F2939D2913C9AEA0 +:1058A00019AA9F88E1D54742A55E3BC6D15F027A1F +:1058B0005E861FC8EBF7F18D914547EF437A1D09CE +:1058C000FE013DCFAED72EA7542D2B9ED2C3EA7337 +:1058D0007F3DFCF1F6215F97960DAEBF14DE1CBA3A +:1058E000CAEC5FC95752698ADB25E21E7DC09693D8 +:1058F0004ABE9AC27D01D4A1BE0779FB30FB8EF16E +:105900008C7042477F8A043C2EA4221FB8F0F3B665 +:10591000DDEED3B268EBF3298A830A7A8AFC766AD1 +:1059200021E31FE1FC76CEB3CF6EDFFE87DB5F2184 +:10593000FE2850893F049DF14F96719A24F394C438 +:105940009EB74AE65BF8F4FD514A66E393FFB2E581 +:105950008A5A9BD0D5628A2B923D92094740E6FD38 +:10596000DEE4C06FA5284E395AF8DF1F25FCCE387B +:105970000C7E592E20F87DF81C0A7EC986270FF46C +:105980004619E59ACEE52BC032DDAD97DC28737958 +:105990009167CB2780DBE26E7BEB7ABB9FD1CE2772 +:1059A0004F1EDD7C9C71D97C26C97C3D26CBC3ACC7 +:1059B000C7441B8E1B65BEDFA9D5093DCED6257712 +:1059C00008BA5A60C39192455BAFB8ED43D1D5C5D3 +:1059D000A39CC782C1759967AF4BC570F3986BCF15 +:1059E000A35382F9AFA35E3CC5F1F72CF7ACCB1DF6 +:1059F000367E3AFDCEBA6CF0ACCB2DF6BC463B9F62 +:105A0000C5767F23CDE78EC1755966CF67F970F3F0 +:105A100071D5BFD6AEBFD2AE4F76C71D726913DA4D +:105A2000194D5262955C30381EABF71977BDB79BA4 +:105A3000CF34DAF56EC0F7420DDFFF58BDD5EE7AF0 +:105A400060459BD03FD08AB602B3634A5A2EA9B2B2 +:105A5000DBD551BBDA81FE6FB6F983DA055A8426AD +:105A60002B4CF5D661BDC6457F74EADDEA85F76249 +:105A700007DE0D046FF5001CB7BBEB2D9027507FA0 +:105A8000E7C51D46E90FF2C5921D18E7CF834827E9 +:105A9000E679B4C9A947300FC0B264780CF309FCA9 +:105AA00086803EB66845EA1B582FD762F635AE5B56 +:105AB00055EA292C5B22249ACB299F80F205EA65BE +:105AC00055F31B987F61C00E56D662721AEDF356DD +:105AD0002169E1BEF85329F96599E4ABB6AA11FB37 +:105AE000CFD7B99E0E7DB46F3970DD13BA8EF21F19 +:105AF00072195CE88F6ACD80EBFED0A41EDC6FEFDC +:105B00002D50484F66065629CA973BA5A081FDF542 +:105B1000147C9EE0DDDEC8F31BB67FE2F304EF7D6C +:105B20000250DCF63E1FCF6FB8C7A76A4D1AF617B2 +:105B30001DF759CA87C8D1FCE5361C08DFDF1513ED +:105B40007CF9A055DE2890F8EA41FBB6B542217DEC +:105B5000797B6C5625F557A1929E7A5F625623E9B0 +:105B60001D1541F2D1E7870DB25BA3F314B0B01C51 +:105B7000331A51CF8CCC0D620E0CE417022617405D +:105B8000641AA4B1EC83CECE12F68C7630BB249F7F +:105B9000EC26B811EDDE0A8677B4232CF328DA253B +:105BA00061B0FFA44326CEDB374102F47B38EB1B08 +:105BB000ED1C683FACDD154D8FB25EF7E8EA453A63 +:105BC00098DD3F7B14F53A47592F3DCA7ADDBCDE9C +:105BD00088FE0E83DB7B2AFB0FEDB640A6DD1CF6AC +:105BE000DAC3BE8CEF99F1B8CC67663CE4A4EC8DC7 +:105BF000878CD4DE89838C345F744A0CC0298D5C19 +:105C0000DFD13787FAAE8CBF266EB2F6ADE33E1D0C +:105C100027B9366E157F4EB4DF4F5C69973F6D979D +:105C200057AD34B3C8F7B13E2E874BD11F329CDF3E +:105C300001B8FEF80683FD9C80C94BC3FB4F32F5CB +:105C4000DE4C79A7CA5615F2EBF604F76BFA9119F8 +:105C5000910F0B81FCB03E487596A09C0033BA783A +:105C6000CC20FFF8CC174CE4E7C3E324102A687D6E +:105C70000CF2A767D049265DF833FC397F2E9D7C56 +:105C8000CCE78DC7FEA5E844E99046C53F4AE72822 +:105C9000EBA54759AF7B74F5FC1DC2E8EA758EB2DF +:105CA0005E7A94F5BA79BDB6F90ADFCFE17B4D662D +:105CB0000983FB12D5536EBB24E8FD7E69D8536E71 +:105CC0009FA3D0FEEF94FD73554FB99DC979CFF7CF +:105CD00079612A6F6AEDAE625BD9A8F9E43FFF44AF +:105CE0003E295547F04B578819765B065FA97A0025 +:105CF000DBE7CB3A60FE547E8CEF53EC69A6B3E051 +:105D0000F7119BFF77C93C7F73BBAC07D07EFC5B70 +:105D10009F67A38FC3EBCC7724781DF9FBA664EBB8 +:105D20005B43E57D54F3BC4C1982949759526D56F0 +:105D3000994C2EC92FF2385866BFD729C9A77D2E96 +:105D40007B58D6923CBE67F7B7A44026BD44667226 +:105D50000DF51E05123545144714C9DF278747D8AE +:105D6000370A5D72AB7818B8ED3C56FAA40354FEBE +:105D7000968F1B3480E46B04FAC898CE41AD670A55 +:105D8000EA69BA00D4DE10B8FF7C8186FB5E2CF095 +:105D900097EE7715F52B98F7C0B9D087E857EE2323 +:105DA0007FE75FBCDF11E00D607EEFC5144288B96C +:105DB000F37B7DF114BD84B3E7CE49738137A1BF76 +:105DC00024C5D765D1207F288C8F925DD61ADBA0A1 +:105DD000BAD7F5FF7CC51EBF89A2B5DD2644D9B36D +:105DE00070ADD9370C9D9FC3600CFA470A6F34FB26 +:105DF00086D94F07E29918AFCFC2076D4A328DFAA4 +:105E0000BB3529CCED7939457EC676216FD6E67251 +:105E100017FD162ADD0857A4DCB4D0DE6BCF170DB2 +:105E2000D45365D8DA2BCC60EDA45A2399458F184A +:105E30006C2F9F74CF27A678F5A9E611E8BD7504ED +:105E4000BDC7A718C96CFED0690AB76B7DC1ECDF6E +:105E5000EF12AB4A9439E7E38DA9F9DCBECD850E8C +:105E6000E1639C7C28DFA1F08557100FAD0557C476 +:105E7000879B2F68DEBCCB9B4473A6323C1C73B25D +:105E8000C131DA7C10ADDA203A1CD097629CAE5159 +:105E90004F12C660BE07FFDB56BEAB1BF3407C371C +:105EA000F0B8AC64EE06F4533B7A9364064F88B4C2 +:105EB0009E0BB8FE54CAF52193FD87F3882E185E19 +:105EC000AF9632CACB14AF3ED4DCB017303EEFC031 +:105ED000EFF8F132E7758958756D767C8CCE1EBE71 +:105EE0008FD10B4CC378948A4881CE068DCA5F6EE1 +:105EF0008853796B834ECF9686527A6EC1A6F39102 +:105F0000CF531D450C6F1DF147E39F6555EE43D9F7 +:105F100041FBFE758B504FDE3C50666620837B3321 +:105F200006BC991E71BB72D522B4DF3707C0F62BB1 +:105F30002C5A647ACAD7345762D9F6336C6EBB9E3A +:105F4000EADF3711EC7310A6FA49D7BEF788E223CF +:105F5000FEC6BD85B7379BB1BF806C97E1B645DE05 +:105F60003298084F40E5E5FDCA06EA9F44001BEF62 +:105F700027CAED7CBCA9DC8F0F65CB47C023F7EBAC +:105F800083A273F9599647F92C8A61A0FB15EECBD1 +:105F9000B5E11E6D3F7292EF77C7B2EF97837C3306 +:105FA000C2BE66C331D2FA3374D87E88245838EE24 +:105FB000CF791CF1AF3DEE7DBE0F8717A5A2DFC2E2 +:105FC000F3230B94E4F791DE23665777112B476B8D +:105FD000BB2D62DF518E7BAFA2D9F34E12FF3B780F +:105FE00076F48EFFF279D7D11733290F2910E6FC0A +:105FF000375A78FB50BF9A33D80F3C51356E387DF5 +:10600000AD2021A21236202FF26B82688C0D947382 +:10601000CD3C4F39A762BCA77EC428F67CF7691730 +:1060200079BEFFA9EBF4F38C79FCBBAD373AE51FE1 +:1060300067CE7394FD3AE59EBE4562295B87976BF8 +:1060400025D2EF5EAE7DEDBED9584E4814BF3DB3AC +:10605000B2D9878C740CCCC81CF4872525DB9F6EC5 +:106060004E447CFE1CFFC9C67B09F73D269F8ED897 +:10607000E77F989C9888E79F8E5C366F22AEEB1185 +:106080001FE76FB03A493EFDCC071E79F0335BFE47 +:1060900018ED3B9AD10F794CE065A97DC7228BE2C0 +:1060A000835BDB3ECEF496AB390A6179AD90D51EA9 +:1060B00088F815C2C7074232E267F334ABF5D61849 +:1060C000E6BFE940FAAA1F12A497D5835529A2BEBC +:1060D000C3E88FE2DC727F6136BDE367F67EEE8750 +:1060E000AB49DF5F5E9BEB4363DE5F33D3877ED4D8 +:1060F000AB6B2A7D60EBCB9A0B3E3121D0F9A91511 +:10610000B5FE5D88D715B2E9CB16D7BA3AE1F7EC00 +:106110005333190E11FE63F6B90780FE4277BC694E +:10612000A69FDB3BF192E1ED05076EA7BCAC76E6DE +:10613000F38807866D3A8F026A7FE1751177BF2178 +:10614000272E1CC17E5F5EF90F7C7F6674817EC541 +:10615000174F7CCE4771D915F91EFE5B5E2D79E095 +:106160004F2C0879CAD7D45E9D33ACFE91F467C832 +:1061700033CB3E8729921CDE7C5C20F99033A93F0B +:106180008D799AF0B2045CFF73FCAF9790FF353ABB +:10619000A15F477D017E13D21E73C9CF169B2E8748 +:1061A0001AFF393FD76BE5BC1A8A6FBF7742D071AF +:1061B000BE425EFD349CAFAC984D386E4B9198C694 +:1061C000B8F79DC5DB555CEF4D251F4E0FF4C57824 +:1061D000BC5FB7B459C8FE43B54B9BFC1C41E6FB02 +:1061E000B57E1E6F69B5966B25B88C07B44A9C7F47 +:1061F000A010B29E3365F4BFD68F7EFB98053CBEDF +:106200009E20BDBA445D4D79B8F2F8E1E3B59978C6 +:1062100093ED386066BD276D7A2CA9D845FDBE7711 +:10622000E1F0FD3A7879DF10A1D7D627B0BE0A6C2D +:106230003E0CFF5B4A791E6E4BD9338467C9AC2490 +:106240007DD6A7A54CACB7A56C35D1652BAB93CF4C +:1062500086CEADEEA2739A5BFEC0E3134FB61F6805 +:1062600046FD614BCFCD807995C1781A507E6C99EF +:106270007E938A78D8B213A017E958EE22A75CC89B +:10628000F687873448334B0A426526A05CC8D3F8AA +:1062900099CA7DF12AC075DB520E06B2667E3AD5E8 +:1062A00088A19F2D711EFF0E969A354508F73891EB +:1062B000C4800EC90E2CB7D4CA348F368DE303EDDB +:1062C000AE734E7E17E6C19470BBAB04FDFBAC7F92 +:1062D000E58B7CDEFA8E12F2136DC97DD9447DD731 +:1062E000FA04185381EBB5A427C88C8EB0FF7A2D21 +:1062F000EBBA6F1593DFF2BBE2F7B2A60B48A79992 +:10630000F879CF0757E2BC5B668AB02B8BBEB1D75A +:10631000CFE3756963F955C559C679CEAF7BF204F1 +:10632000F4F715827BA8FA83F564F2EBA3E1B1845C +:10633000CDA3A086FB4B21E31C6B0C9264DF8E0582 +:10634000AB11F9D139BF3AA13AF1CB247B4A91156F +:10635000944F37D4795627CF7375852D9041BFF66A +:10636000D76CBE371FF401E2EDF2B38FBC80F95257 +:10637000BE0ABF46F955D0F902E66FDEC8D4312C0B +:10638000DF7C7CBA82F93F2F8F97303706F9278A56 +:1063900074F81688947FF6161C8DCE76D1F9297B79 +:1063A000DF41C98A72A43997CF4B0EB7F54A515CC9 +:1063B00077D9EA73F2F74861E279ED1066EF55CAD2 +:1063C0003E6A24F9D7C1F3859CFCC8CF767AF3875F +:1063D0003EB7C35BBE09968F41BEB989297469D6A1 +:1063E000EFCDEEBC2F36FE313FD70F3E07A936DC8E +:1063F0007FDAEDFC9875DF9FAE205DDF3C5B2BC242 +:106400007318CE3C7EEFE776E849C6A7BA8BFFD774 +:10641000C4D2949F9C39BFB7F62CEA4EB2F26BBA45 +:106420009CE276B6779EEDBEDEA598EF656DF3D95A +:106430007A8337CF71CDEE4A13F3C518F6F47C6F2B +:106440007B82FF1F3ABCF31D091F99F377F4C1A1AA +:10645000E6A3EC16B2E6FB85546FBE54B3CAE38DD7 +:1064600066B30C8185E79F8FB6AA5274BED96AF2D3 +:106470006BCD318A4F52FCAF9E110EC6F7CA559DA7 +:10648000FA792F30290D740E21350FF5A33FB7DFB0 +:10649000F92AE7C3BF74BF0B8780779DDAA7207FF7 +:1064A000AE973B6B84E2C1F301019F654E60F8F645 +:1064B000EF5DD63D013CF53A4659EF201E811E4561 +:1064C000BD1A7198FE4EDBFBD6BF3DF12F0AEEDF01 +:1064D0006F3D7E6229CAB95BFE550295D53BFD44EE +:1064E00004BA69DF492B2897D7EC9168FD41EE9EED +:1064F0007BB527DFBE99E67FCB5311DA1FD63CE38D +:106500004FD7B2F66BBEF7DA0C607C7BBAA9FF8579 +:106510000988BFC7059EC760F5CDB89ABD5F23C384 +:10652000F5D9F2106E50395F9DFA416825EEEFC241 +:10653000EE9EEBA8DFAE6B7D7E97FC5DA9727B9A29 +:10654000D533F1BBF54D213D55E0F065CBCB3BF5A7 +:106550004DEE4759B3D797C63CC535BB772A495648 +:106560006FFDEEB789BE173DF56414F1B07EAFF74D +:106570003CC22D4FFDA1ED92723AEFD45F8BF24FEA +:106580003A4BE533A6DACFF3E0B93FE656E2585688 +:10659000EF3B6F5EF16BF6FD645C82001329277B95 +:1065A000FF53F9572C27C32926CA58FFBE57DD7C55 +:1065B000B87EF76B74EE481399027B299E87C8F862 +:1065C0009E519FE9B90ACAC3F55D9BDE4679B97E43 +:1065D000CF5BBF42BA5B0FF2AB6E7E3E89FF18778E +:1065E0007E3C6B93EAF5D39D814373C901B03B3F79 +:1065F000ABBDE8C4B31CFEBEE5C9330FA31E71EAF0 +:1066000099FF7A18EF6758FBC7FF7918F35AE147EB +:10661000010DE5D6FAC77F1E0517FE1FB5E5C3E9D4 +:106620006F7EE3EB0F303C9CFEA59FB076FAB93746 +:1066300027E13D1DA79FFEDF31A87F6C7C6EF158DE +:10664000A4B38DDF5D3476B873A048B769BF7B7D96 +:10665000D3FC7E83BD026E8200CFDACF8C7581437E +:10666000FD0AEABDEF0AD0BF3997BDEFFA8382FA7F +:10667000CB0B26F4239EF6EF79ED85BB58F92DB6AA +:106680004EFE2CEBC4E63F41A4FD8DB10F7BDEBA7C +:10669000E7EAAB2E2BC7A7CFC0EED7433FED1BE7F2 +:1066A000ADEF31B6BEE583EB9BF9FD0C9C5510FFB9 +:1066B000EB9F60EB3903D795ADE78CF3D7F32DFC57 +:1066C000C7FCF3D773BFEAF5C79D81B58F3C801F28 +:1066D000F7E467B56F9DF55CF7DD4F0EAB973BF2C6 +:1066E00061243CD3F95E06D75754F3672AF2ED33A1 +:1066F000DFFAFA0331BECEB50C31A79F3C33090F48 +:106700006BFCD6D77F1DE2A1FF39BF867AD49AE70A +:106710007E417C77FABB2FD1B91EF61715D87E774C +:106720001A06FE8E022BDF2AF0C23ABDFF8A5FB145 +:106730007ED7B12E2C83D6EF8A5F95E3FAA9FDB4FC +:106740001EE965353ACADF7401CDFBD634E78F5BAD +:10675000D33D2BD09F9D89F748C0C9271C5C57F4B7 +:1067600097DEBAE7C415487F43ADA7337F0DE73FF7 +:106770008F7D7FD4CBBF43F2ABBDBEA777BEA7A0B2 +:106780007ED5FDAF8A26323BFFB4AF5F198FFBCDBC +:10679000D39286E78D33D77D10FF4D59CF1D673ECD +:1067A00033E9C31FC81EBF76F03412BF8F3CBF0F42 +:1067B00087BF33F63E9C89C75367B3EF075302DCAC +:1067C0009EBB153A6B50C5CCDCCF7C90B226140D25 +:1067D000C2DBD625919C3FB59BFB6932E5C5AD4335 +:1067E000D867339D71F6F6CC40B9766ADF0F6CBA84 +:1067F000E4747FEB132714CBDE1FD22EFCAE1FC236 +:10680000DF7DA9DDDFFA67B3F7B7FE89B7B3F677A7 +:106810005236AF45F84FF6FA282FE9649794D5CE53 +:106820009D1AF079F4AEB6C8DC5772583B291AA409 +:10683000BCABE626F317E827B58EFA6C3F80F15B18 +:10684000CCB76A8E04E99C7B73F426BA2FC9E9AFF2 +:1068500025034F723C41F6931C4B94F31858DA63AE +:10686000C7F81841B8E106D92A44BDFF70D19B3260 +:10687000F67B04F548975D7F4486D6FC723C172171 +:10688000188D90C5BF91D17F628104BADB4FD83D8E +:106890004EFC3D6BEF3F26A511B5F590EAA67301BE +:1068A00085D0F55896FE1E6AD0C97E2E4A5C4FFEF2 +:1068B0001F7F2A65A2BE56B8512B16F5A1C79D9819 +:1068C000F2C6AFC733CAFF3D8E73D047FA20EC7EC5 +:1068D000FCF1C7C7F02D05F5F217F0C9E4DFE57547 +:1068E0007A21961FB2E7CD7880CE314EB41232CAEB +:1068F0003921B64C46FD62712A21AF76ADE7E298A8 +:10690000301EF7D3F410F7407D3FC0F7CFC6C66BFB +:10691000288FFDC12F8A44D70F063E5E887C7620E3 +:10692000775E18FD6B3DEBE61E9AC6E09C10960064 +:106930004DCEFDE1E1CF6D3E6CFB1776D9F70F3DF3 +:106940006AE7977FDDC6DBEE86527A3EDE60D0F7DF +:10695000271A2AA8DCD55043CF671A12F43E7A577B +:106960003089F4B9A76125BD9F006F0BB8FEDF6BBE +:106970004852F9D1402EC13FF96E1093ECFD62C42C +:10698000477870DE0E3C69DBEEFE7EE0C72DC8174F +:106990000378CCC0F7E5D02BA8E8BF8A093AAE7BD4 +:1069A0007D40E779AE19F89DE4EF17302E577F3719 +:1069B000CF877858F09E77B8DF96FFDFB1F9F4DD26 +:1069C00068F2C9007BBE53B3A294F421D0CA906E82 +:1069D0001E1612478C22C2B3E7DCC9FABCE4770268 +:1069E0002EFFF0A40E6ED7EF08D8F26D2388486F03 +:1069F0001353A023BD39F3DE57A917A25CDC270887 +:106A0000B4DE486FA52E7A1BA0DF809D971CCFBEF9 +:106A10008F0FD22FE7FFF825A5F754235E3688E4C1 +:106A20000769C64FAE761FD874C4EC16D1427AAE51 +:106A300013C99F3BF9F8096112834FD7BE15C07B7C +:106A4000BBE293C0F637750590BE1EACE3FEC5AF42 +:106A50001DE7E798CE6C2C5E368DD55FCAF083C1FA +:106A6000A8BC25251EBFA5737EE16B6A22471BC605 +:106A7000BF9599F776FFE42FBD9FC3C699703CA4DC +:106A8000E379987B26FFA84761E5F17D02F993C67B +:106A90008753D3703D2BFFDF37C7F5B9D6E181753A +:106AA000A9C9A837B64DFEB6807C30FEEC8F05DC58 +:106AB000474AB4E49BB83E1364FB9CB09C9A87762B +:106AC000C1F57989DFE1FB4461FA53484F676A36C3 +:106AD000FE1BF6EFC421EBEBF5DC692EF990799EF5 +:106AE000E2A1D4F0FE4C67FE0FE1FC87A9E7CCDF02 +:106AF00059BF3335B1B5281733F199D96FDE9215E7 +:106B0000C38EFF907D8F189BBF3FE8926B85A93E97 +:106B100019DB39ED878ABB66CE77C04F34CA386D32 +:106B2000970FF2912E9EFEBF49DF3902483A0909BC +:106B3000FD53FB02C97108CF5C4851994947CA67A8 +:106B4000377239FF3E30E6EBE388EFE47411E57D00 +:106B50008C72BC5648242A719F334423DB3E303D5F +:106B6000C8E97E01A4C83F2A86EE1E3ECE5FE88DAE +:106B7000F36F059A0458DDAA1DFF0059437FD841E1 +:106B800098857EC8FC20E7F74A99DB97B30FEA3B6C +:106B900025EEB79296455CF8B3FD763EDE3583FB75 +:106BA0006ED0743CF735B34770F1EB7BA1E4C220A3 +:106BB000ABAFC4B93FD2174BD279CBC55258247F63 +:106BC0006E2797FFF590502FE47119C079EB1017DD +:106BD00071BF7F68233FDFAE6B2182FBA1984EE53A +:106BE0007A5B4FF9B14D473FB0E5FEF76D7AF92E6C +:106BF000CA7DA49B3EF3400E83EB3BB6FC7FDA9646 +:106C0000FF4FD9F27FCEB13EF86639C96303F39ED8 +:106C1000BFBC3DDE84D37CB2C1A47ABB1AEAE8B91A +:106C20003F77ACB897D57B74A3B80BF9F9516DECED +:106C30009578DF55DA140D81357EC8DABE28CAE0B2 +:106C4000DFA90A143F7BB82145ED76AA7A938AF131 +:106C500014662D5B4806F5BD14F6A8FC6DBF56C33F +:106C6000EA7DAD33EF4A8CC3DD5B23533B878FF462 +:106C7000391BB03944F3FC4164ABBC826E750ADA4F +:106C8000E91B45EAE72B81CFA88BD873E2C4A3EABE +:106C9000C7755C8C13668A7D5FC4908CF3A8E8EBA3 +:106CA000B3B05CF27A98F2B5E7BED2074FB3725137 +:106CB0005D84CA132D2F5F4CDFD367753238269E53 +:106CC000E2DFABF37E6775B1FA391BA2D45FD5EB77 +:106CD0007D02D2B3AFDC7BFE6A87EF97FB236CFCAF +:106CE000D8A1848078DB27688B3025C4FA143F7FD5 +:106CF00033F62054E1FB787409ADC3F66011D1CFAF +:106D0000D75A8EC66F463C6D8CB5A099B37FE3060B +:106D10003A9FE0DFB891EB4129EEFF9E78C701E191 +:106D2000732EF950D82267F5DB6D0FFA799C64E376 +:106D30008AC4340EDE8130EA7B25DC5F59D45AEDFB +:106D4000C96B72E2231F08C9ED41B29B789C44D6FF +:106D500052F4FE32097545F6FA4E91EB4989DE8010 +:106D6000DB0FA3DFC1EF67CB8463575026385AACE3 +:106D7000EA3A9417DBE6287200E19866DFCF62C733 +:106D80002107F63121B9CB2DD7648DC33591A132BE +:106D9000847077F77EAA8BF5F37ECAD9C7CC20E939 +:106DA00049F788C41F5BCBF939C0FDC63BDD78CFFE +:106DB00085C34FAD8648FCBB5D16D202EB677B797D +:106DC00071EE85483F31DCBD69BE2AE2B944F6F177 +:106DD0001C0E30F7A15FDC8F7E71B6DE25C743271E +:106DE00044F2FF79F3BF8B2CEFFA8BF5DE73771348 +:106DF00099D2E3CE57064634037446FB6BF5BEFFCB +:106E0000407E5819223A03CB8C568EC1F445FB4F75 +:106E1000AAA5F3CF2519E70C1EB0EDF787ED738413 +:106E200070F63640B9F5807DFEFA81B5625067781C +:106E300079DE3A4AFBE6C4FAEE4A0ACC687E4F7E17 +:106E4000B5FF6EAD09F7D7A294374FA832232FA80C +:106E5000E4CFCCB33E1EF4DAA9FB4E060DBC0F2FD7 +:106E60007D4C32509FFDF25DB349FE596BB8DE9206 +:106E7000AECB7B00CFBBE40B60E07BA75FC77E7D22 +:106E80002798477C939ECFBEE730B912E95A5287C4 +:106E9000EB05395A530CCF43DF09DFC6FEEBF8FA96 +:106EA000571602DDAF5318033AE7CC9E9B2F40FEE6 +:106EB000DF28624C1CCEA19C4739AEF6BE88EF732A +:106EC000AF14E9FE9CA216EB429CE7BE4BC68F476F +:106ED000FAD81AE6E75E9A851468086F01E7879D7D +:106EE000916ECA07DD562342135214C3A581FDAC2F +:106EF0000EEEA23C1684770ED11DE95D18A3407EEC +:106F0000B46E08F27DE7AC7521FA95A3A1BEAEFD83 +:106F1000AC9F70BB62EC62FDECACF4DE533735C461 +:106F2000F7BB404870E2FB81107B9A5B81F216D977 +:106F30005C88BF195F5940FB8246769513DF8FEE60 +:106F40005B22164DE7CF6217FFEEB2E56CDACE5B3F +:106F500078D8DE3F1C7DE301DB6ED86AEF1B45E687 +:106F6000554D0AD26D1DCC443C95ACED125667B31D +:106F7000EF3BBC7235935F2667F24BCA7B4E75427E +:106F80005DB1E77BC4B8C8F39D4231B8EE6CFF46F3 +:106F90003CB707CA24D4FB6643C274CB95A1F6FF65 +:106FA000FCA03923F421F49F68289142FD3353FF5C +:106FB000BED45E97EB0289F9B81ED14B56521ECF54 +:106FC000BA40E252EA5F4E0B284F1760BB58567822 +:106FD00029F96B14F0567F18784136E83CD79D921A +:106FE000739FADF73C1764DC5F9B793FEDC2FFBB3D +:106FF0009BEEA76D1598A287E51CFB7E5A3FBF9FAD +:10700000B635C2EDAE563B8FEA561B0FD787F87DDB +:10701000AF6B6D3A5D18CA7EFF91E3F74AA16CC071 +:107020007A63B3DF3B861A15F6B77042F6EFA91004 +:107030008F3B2E9C3CFC381B701CD6CFDCA0B92E9D +:10704000E4F2AFCC0E99EBDDE5DB43767E919C203C +:10705000BDD294F97E5814343786E6B8F06B3FF30E +:107060009694D379BE33F6793ED66E87407895B440 +:10707000D1E0DDD1FF5B05FD1E92833F677A5F960D +:10708000F5782F18B5C49CC17894A31FED0E717BC1 +:1070900092D1DB263E8F34E5418741BF07EF8198CF +:1070A00080F770EBE85738FEF0BFA0BCBDACB70668 +:1070B000F5A7753F94E87EBBF3F0B596D19D2B1FE5 +:1070C000C5793FFEFD0964074F9692F7875CF6F19C +:1070D000F8BA7E05E91DE1AFE6F0F3FC69217D21F8 +:1070E000B70780E238AD37C73DF98499F6481EDE10 +:1070F0007340724521BD2E132EC79E70CA99E711A9 +:107100000EDB74847FFA18BC271CB8322B9B12F25A +:10711000D71C48D2731EE8F464764B17CE83F19FD8 +:107120008E703685265D8AF3F82BE2ED47A1397F14 +:107130007B7873E8B82879F9001D67BBFFFAFE5029 +:1071400094E46DFDF108E9FDD17D5F20BA96185DEC +:10715000076283F932F560E7D187A10BF5DEA264FF +:10716000039D0B3DC3E818FB95347E8E55062D819B +:10717000711B29C6F9C327976AA2867159CB8F79EB +:1071800007563118286BD11FE986B73C9C7CD38DFC +:10719000C73B8FDF43F2F6BA40F224AEE79D259657 +:1071A0001F353B971C3EE596C3028475E4BF856797 +:1071B000F97E5999D465A487458CD311EF8B214969 +:1071C000E58F8345CF2590A6E7DFE19546A4C7D993 +:1071D000E716BAAF15DDE71606F2B9CB9D7C0E1E99 +:1071E000A72AB0E9106C3BF5F995CB1B17B3F1D981 +:1071F000E29B188FFAEA4A9ECFE39F27D3F9D58204 +:10720000BE1B6A314E042BB85EE6E441E4D57AF544 +:10721000B4F3EEB73AFEBBE3D82EF39C9CA3AF6564 +:10722000EE5BCE33535FCB0B673F3F39D4BE931930 +:1072300057A8C77F72FBD5B6AB1339EE7BE3339FFC +:10724000871BFA5B0EB8F2CC8FE0FD4659F7011EA2 +:10725000EF8DEEFB5DED8A72BA5FCEC094C9DE861B +:10726000EE85AF4F1DB483130B729F477F74A23A14 +:107270007796C4F0BE34FE6ECB817C806566CFC24B +:10728000D75DF3ECD518B459F48481F14CDF07EEE7 +:10729000FDF72D85CB97567BBC881D1F6B172D3FA7 +:1072A000F1ABED7FFB7D21B7D31DFB3EDB7C5B08A3 +:1072B0005F7D61A487A1E6FB0F61BE9F8E5969D0F7 +:1072C0007DF9CDF67DF9CD139DFC2D43437DF2A6CE +:1072D000702EBFAF205C42F1D5E69EF9E44F2E3808 +:1072E000E4237FFA981549C172ED8BF73670FFEBF6 +:1072F00057987E87F9205B985E87E57D957355B436 +:10730000176E8FCCA278EDE606C3932FE23CF13ED8 +:10731000BAA4CBBFD79CA8D230DEDB523B4B45BBD7 +:1073200043FA443995E50B677556317EFECCD61984 +:107330005714605CA28CDF47763D2B3796303B3A82 +:10734000CCF7D9C3C6EB61C453555877E887D6D17B +:10735000B72269FA502EC4B52ACC9571DE834D5FF1 +:10736000EC3DE9D76F29C99BC36CFE87ED7BB1DA91 +:107370009554E986323C17CF040EFA8955EE27441E +:107380003A68993D08F7061BBF97D8E33281243E3F +:10739000ED5A3F25CED7AF5D84BA6CEB737798EB8F +:1073A000372D9AA90D4B479AFC81E7FED0F218CFF2 +:1073B000CF8F313A72F1F3F9F4CEF9A93C9C680908 +:1073C00017A05C84D214CD3F4CF287DA4983F7587A +:1073D000C6C36607D63B9A6BEB2F853C0F9ABDDF81 +:1073E0009243F34B917C77F4C17699EB73A3D50765 +:1073F000F3966C247DF01DC65A649F7D6223C9ED0F +:107400008D3E95EEFFDBB740A67856740A5CEFB66A +:107410005BA4887DFF7F84FBE5F17712D2D3B8DED1 +:1074200083E73CA221A0732EFD13797E693BECAC6F +:107430009942F04DD5DCFB59E544EE67D85615ACC2 +:1074400073FB1B16E6F278D98BB995BFC3F9978504 +:10745000D355C89A176BD087F93450C5CF8F09859B +:10746000FC9C8D0F0C95F36BB586F7860A90A4F300 +:107470006743AE1F78EF177D5C4E3705116F31EE15 +:10748000D789EC1028694FEA32BBF1EC4E7BEEF263 +:107490001F223D32B967207FF7CC0D92BDF76E8F6A +:1074A00042F6E7BB37C3AFD19FF4AE2F072CB654DB +:1074B0003F12C55F3FC5E6DBCF987517E67F69FCD5 +:1074C000FBCCAD02F99B7EF4417002D2BB110511D9 +:1074D0007FCF6229D32778922084303E1B5D04DD64 +:1074E0009763FB9E30E1CF17FFC9C2D767D3FE1366 +:1074F000122BF0BC96F820CEFF9938E461FBD9FF3F +:107500005B25A1FFCAD187BEAA258F22DEE6815561 +:10751000D7C3DA6F53387F6DCB53D218A79C552051 +:10752000921E02BE507A2AFBBEF4E0EBD598DFB97A +:10753000B46226D6C4F169BD4BB4E4719C77B5B68C +:10754000AC3A97D52F3FA693FCBD227EDB012CCF12 +:107550003DCECB3E3FD7E3518F719F0F58FAFE24AB +:107560009AD79B61AECFB6C4CD5E531896AF32EEBC +:10757000E5F59E2F70E8806DEB3AE6A5D3BF75A2C6 +:107580008BA44F1CF43F4185619F3F71E8C1143EBD +:107590000C3DEC09F37DA11DF3CD6283F966EDB6D8 +:1075A000FE36DA7CB34C7ECA5B22D33ABCC3F42DE0 +:1075B000BCCFE37C3EB98DEEFFCCE42707CECDE512 +:1075C000793194C30EDF68F3EE26B9ECBF41A1FB1D +:1075D0004C1D3E72F8E7D29C013EBA0FE5C58AB059 +:1075E000BE98A76898E0E693AB47E0ABA5D07F20B4 +:1075F000C6CA4B65B07298083A3CFFB725935C7CCD +:107600009289CFA50B0478D5230779D9856F6DE0D2 +:107610001EE02C76F250EB7254E6E71E1C3EC5DFEE +:1076200063C1F3631DA201B81FB5E7AE36226CDD5E +:10763000E4DADCB5C80F5B84440AF92132EF54E880 +:107640002686F777C7302D12FD87FAEAA788DF5F15 +:1076500009915DB66DEE1A8A4BBD7B737232EE2FC7 +:107660009B18DE5FA5FD3C3D56A45CDBBEB13C6FC4 +:10767000428FF36732CEDF83FD3D6D974DBB5E1FBA +:10768000D563EBEB919B3F8D723EF86994EF539B72 +:10769000944E15E9A1BF48D5B2E52BA722BCFEE563 +:1076A0007E28C7FB18D968941FD0AA4A353BC95910 +:1076B000C2E5C4E5534A77B9CF5739EDEE6DE822FC +:1076C000BD6653C35E7AE6D7A601F3E882A5968E1F +:1076D000FA87FAC74502EEC770118FCBE3FB4697D6 +:1076E0005EF7695BBEAB785F101B4F6DB274F7FD40 +:1076F000B4AA2864BD47E84894FB89D526A0EFEAE0 +:10770000BE7FA6FC85FC1243F82C969B3AE9F765F0 +:1077100002DDFC7DACC4146E74F51BABEDF2ECA382 +:10772000AAD82793DD540F9A8546A0DC578DFEB961 +:107730008EE5C14ECC6BCEA437FC7BD54537EA1F16 +:10774000AF26FD098E72FDB5BA58253A6FAD577652 +:10775000A2FFEFF7B12ACA67EF88089EFC02E7890B +:10776000F177A611923FCDF2F338BC358DC7E1B168 +:107770008C71787C621C1E9F1887C7EF1887C7F230 +:10778000B71B4C2A633C1ECB188FC732C6E1B18CA5 +:10779000F1777CEE6DA8A3E70F1B52F4FDD9867A32 +:1077A0002A5F6ECB5728E5BF07D6F105C5C4FCA9F3 +:1077B0006E7B7DF69BCBEB7E86FE42881AB8AF07C8 +:1077C0000E35BDF2EF7699EEC98E17E7A3FF126270 +:1077D0002260DCA12DBE9DE9A283F30BC8F7824E87 +:1077E0007177AB0EF31EBFB1ADF70A99E91F25F112 +:1077F000DBAAF258F9C96D2FB7619EE9057AE3CA91 +:107800009DAEB21E99B5E6696DB03CB96CA71C641B +:10781000DF9F89FCB20DE54520C6F5C367B7FD9A29 +:10782000F4C3EE62A600A1BC2B52D248EF37E23A75 +:107830004DC579F07CEEBF83E638E6F94DD6955913 +:10784000C8A7AC7E37E78F51D6C760CD9CF3DB0D60 +:10785000574F2C1F553D3AA73B643DF65D18A69F38 +:107860005668D67A19EC5B7C7C1FB60AB89FB8C301 +:10787000C7E54347803FA7E438F90D55CDD102CC89 +:10788000FBE17CDC11E0F713F44F17E9777BA05E96 +:10789000F87BECE7F3E341C3FCC859D38BF3D14E3B +:1078A000F8854D0F532747F8FEFE8F2AEDEF1F9FF7 +:1078B000FC644B1E2B4FFD17C3C0FD7A0B1841947F +:1078C00027D6562E4FBE553E256F19AB7EF19CEF45 +:1078D000E6A17E3CCF964F69DB8E696CBD6932DADA +:1078E00011EFBEC4E5E31BB67CD9E9EB4DD17ACEEE +:1078F00009D3790B804ED25F1AE332E58989E3F828 +:1079000053F1699FA6FB335B15BAAF49F9C33C95A8 +:10791000FCAEEFFBEDFB8A7B49AF5102492D97BDD1 +:10792000EFB444F253346BC134DE9BB5253C8B7EFF +:10793000BFC12A93296EB6A58CC77F42916BE85EC2 +:10794000ACAFF404A87E6B58A57CE174D99E835536 +:10795000317C8A1AEA07697339DD636969A246795D +:10796000C7EC5FF47D6D8CFC4174FE18BFAFE5F190 +:107970000ADFD843546EFEA446FD839DDF4F2A9A4A +:1079800088BF2791E8F1DE4BDBFF938FA1BF640D29 +:107990003FBF32435BDEF31CFBDE62AA8962C60F87 +:1079A000ADDA3BFB42585E05144F0D4D7FBD298477 +:1079B000F56FD40C9EAFC5CF4B807D0F724BD98A2B +:1079C0009EFFC0FE578660AA81F5AB55E4576881DB +:1079D00017F0DEAA428288BDCF9D25A0DED65A4B85 +:1079E000D77332F8BCE70C5AF2AE54916EA4A57965 +:1079F000344E2B982AD6B76A65DA3F0BC36A37FA3A +:107A0000170A6DFF84230FF253AEF306EC7FE3D722 +:107A1000CA9EF308636FF4960B32EEE12DB7E927A7 +:107A2000136F99F3CC8F3D938BF0E4AFA59313E7DD +:107A3000C17F6F6CD6329CD7386D9FB0B39C4C1F02 +:107A40004DC77BC821D5E8CED7F873E19D51D6D27A +:107A50008BF4304397416778F918F43761FF5B6C1A +:107A6000FAEF28F2EEE3BFB0ED1FC6A76BA37330A9 +:107A7000EE2182E5EA1FE322960B9E291D799EF2F4 +:107A8000D4CEF19EFAD376147BBE5F98BEC8F3FDC8 +:107A9000E2DDB33CE5E95D9778EA7F6C6F95A73C42 +:107AA000B3FB4A4FFDD907977BCA737A3FEDA93FD5 +:107AB000EF95D59EEFF3FBD678BE5FFADB0D9EF215 +:107AC00065FD7779EA3BFA7FE6BE795394CBA30F45 +:107AD000ABF7E3EF03B9CF1D67DA15E7DDAFF3C707 +:107AE000661DE38410E5F7E9CAB8BFB3F2862F70CC +:107AF000FB4C5D68E8286F5645B97C5D9F67DE8E5C +:107B0000F2B532AAD23E2187793D397C05E923932B +:107B1000763039359BECB681EF18AFEE68B016962B +:107B2000B8FC5A01AD13304FAC325A43F70A3AED64 +:107B300065CD04CC9F5B15D5B91EC4AC5EBA2F4091 +:107B400067ED5DF36276225D31D1CFEC48D4FF075B +:107B5000EC443987E2C3CC4E243BD20872BB11CE31 +:107B60004AF4DDF88A40F7F8333B90ECC867C2CCA2 +:107B70008E9C89765BDF169443FD3F9529DEC8FE17 +:107B8000C84E2C6776E2E65CB7BFBCAF089F69D0F1 +:107B9000C6E3B347E916C71691DDF8CF48CF9FD9A2 +:107BA000F8521DF63BBD9CDFBFD731A6368EFA7466 +:107BB000475117F1497F91CCF7213951EAF6031E5D +:107BC000B0F7AB90FA2DB257D93A905C76D6618B6C +:107BD000D097C67B0EAD2F04C92F3EE937FEA3C850 +:107BE0006F6AB13A01F3048DFD8A89E3DD6BE3B975 +:107BF000589B59853F0759125FB60F9F17E84C1FD6 +:107C000061CFD2D27BF6E1F37B51327AE122E3E914 +:107C10002A9431EA42EEDF966728E92601FDD20C6C +:107C20008E2CF689F394A23BF8BD4025F21B487FC9 +:107C3000681D9C6353A8CC5329BE1C40BA10E84968 +:107C4000F4149043B4BF04F0B02A962B843486C455 +:107C5000507FC5BCD1CABC1D44078E5E8BFA6E92A4 +:107C6000DBD10790DE62B5DEF50FA9DF263CB5D883 +:107C7000E7A23B72F543556CDC8E82E23CF4EDA248 +:107C8000DF65994BFE1CB4F7DD477344474F20F97D +:107C9000B30073190A06F522C60F3BC429086F8288 +:107CA000E2F0814312D9FD81BB3BE97758039AA5E5 +:107CB00003E9FF968EFD5617AF243FE1FFC466919E +:107CC0001E1CA8FF5156BC05FA2430670F8DCFE863 +:107CD000050F903E0063823AEEB3F5B1A0B9338B45 +:107CE0007D5017B1ED9F498EDF3341E7625BD12FA5 +:107CF00017C6AD4D15319FE7F69F1678EC9ADB0B52 +:107D0000B81F73A8F103CC1E4DBAE0DBC4FA4539A5 +:107D1000DE7A76590DDDBB8ADB4C399E1B2DDB49A3 +:107D2000FEFCB3CD3AE67DD5D9784D61320FC3DF85 +:107D3000240516ED447992C7F42386D24ADBFFE28C +:107D4000F86926E6F0F8BF6181C4FD773E67DF126F +:107D5000CFE17D353AE8CA5CFB2A005281F9BEC604 +:107D6000FEAF07CF0F4EE970ED7380FB81B73C6D1E +:107D700087B77C61DA5B665AF4CBA807AC00E0FEFB +:107D80008FDDDEEF61307D186F19EFDCB39FE0E728 +:107D900009550601D2775957BAE76B6C7E09E73E61 +:107DA000CC8C7BF5A7EF4993FE7295FDBB1F99F72D +:107DB000BD8FC7DF019941F3F2ECA3B37C12F92523 +:107DC000D09F64B8FC49259AEEB1AB1CBF50A65CAD +:107DD0000F1EBF07D817B2EB937EBC37552B43FF5E +:107DE000435BE1977E73A27CD00FD326A7DE3C4194 +:107DF0007E4EA67FC5B89F04FDD7B7FFF48EFF3E29 +:107E0000E1F267BE1B4DCE46BFC7FD93797BE75EAF +:107E100055E7DCDF3B35F2F382CEE148BAE0B8B398 +:107E2000D4FA385757D2E3D08FE4F8611C7FC3F5FA +:107E30007926E9E75B8CA3A9FDACDFAA5FFA01FB19 +:107E4000592C1D3AD880F26EA24C7925DABCB58F38 +:107E500004D1EF89DF59B9AA481F4BFCF1A28FFC6E +:107E60000EED36DF3BE7571DBF4D2287F347AD6D63 +:107E70000FB09906ED731B41D4932FDECDD6D0B34E +:107E80001F72BFA1E31F9CDEE5FD7E111E0527FFCB +:107E9000E84ECA8332E6F33CA8312BD3FB709D3FFA +:107EA00066AF33C6B72AE70EC659C7AE4AEF433DA1 +:107EB00074869DCF54F6E2F3F493BF20154A485FD1 +:107EC00017611E136B671C903DE746C68040F94062 +:107ED000638E49469AF533E359EFF73270958B106C +:107EE0003E6F39337EC5D4ADB76F10F0F7535302F0 +:107EF000CAB3ADAB988DC0CAEB72EC3CA40BE002E8 +:107F0000A4DBC552D8C0FBF536FC5CA23C64FF89FB +:107F100069BFC0382ABCC4F32EB5293C2EABFD4442 +:107F2000329804042D0433678607E35D5F3D67E004 +:107F30005DFB037EB4C7D9BAE33EF404B3FB4B7CCC +:107F400068C76B54EE62763F969F61763F3EF7308E +:107F5000BB1FDF7F8FD9FD58DECBEC7E7CFE90D936 +:107F6000FDF8FE5966F763F9C5DCCA2D397330BEDA +:107F7000554AF4149CB987F21EDB559F86F4932969 +:107F8000CF2A2B6F575730FC6E0E2FA6784BD56239 +:107F90009E77BF256731D9D303FEBC0C7FE8A07F55 +:107FA000AF4F70FC7B78043A6EDBB3037ED2A44102 +:107FB000F71B8CDC8FE9F4437ED6F3FAB1FDAD6F8D +:107FC0007DE1575F6F669FD6CDD9DE112CC6733F1A +:107FD00029FEDDCE3FCCFCDDAD757B1A291F501983 +:107FE000772C85EBBAA73C4CFA06FE2E13CAED4C53 +:107FF0003BD1B10F33F571E799B91F66E6CB446CFD +:10800000BD64A4FC8D6DBE14C5B7AD46265F70BFC0 +:1080100068482F7CDD77BE7F77B29697714E99E7DF +:1080200067F90FF2BCBD0E486AEEF93BE723C8E6DC +:108030002BE67E46B77F375892A6FB1B826193F4EE +:108040004581E991A4576A498A17B60DF1FBDAA771 +:108050006C39D138EE1ADAEFDB5EF491BE556DE77C +:10806000C9358F53A9DC3C6E6E9CF22B2373D5BEB1 +:108070002CFD6C88140FBBBF4A6CFFD787D9FF2536 +:108080003F3F17D6BC6FBE8AE7A73AC2AB7BD16E23 +:10809000EF88C7284ED0336EAEE77E72295E41F777 +:1080A000594861AE674B7195F46C19E75F3658DF3C +:1080B000A9773087D30F6373F26306C29D54CF2F25 +:1080C000274CF4B7F8633C0FD9AFF1B862B0440461 +:1080D00035CB798D1EDB2FDE5196D4D0AFD31197DF +:1080E000E9DC47873E6BA8B82CBFEF42F3FA079B49 +:1080F0006DBF43739D427A61A23E57ABCEA7730B0F +:108100006790CF3BC24D2AC669FF3F82909C4F00CB +:10811000800000001F8B080000000000000BCD7DD8 +:108120000B7C14D5B9F8999DD9577637996437C91E +:10813000E6C90402060DB8818487C6380991A222D7 +:108140002E0235B4B42C0414E415D1B6ABD5B2214B +:10815000098F2025581F282DDD50B02FBD8D96DEAC +:1081600052ABFD6F04B9A8A8A97A15FDA146B43E8B +:10817000EECF6A04BDC547FFFCBFEF3B33C9CE64F9 +:108180003604B5F77FB1653833E7F19DEF7CEFF347 +:108190009DB38EBCCA60CCC758CB3FC5862E2F3C42 +:1081A0008B18EB8127934219AC9C318F2C3096CDE4 +:1081B000D869FC73317CEF76ABAC129ECB1C717727 +:1081C0000963E168454EFD44C6166685990CF51CA9 +:1081D000BEC5720CDADB1953B13FBD9DFE0C627F48 +:1081E000558C89F26F6BDEF20FFEAE3FC5F41D2C8D +:1081F0008270944A6FF7BA18B3294C386D8332F302 +:10820000CA6F9FC7E8CF6911FFEE09867DA9FBF110 +:10821000B9FEADE6AD8983DBAD2AEF75880A639BB5 +:10822000F7748419943F131482CBCE626A01CC6B2D +:10823000F5FEEB5904E6BF55EA71C900C7D62F8495 +:1082400085E1F2C1FD2FD3F003088B219CF0C776A6 +:10825000FA7CF85B618A63126305F866243EF9775D +:1082600018A5FB34F45F91807299060FFC7FE261E0 +:1082700063B9AAC7589E7CD458662C640F8F63ECF0 +:108280008575D0E9398CCD39F6DE3196CED8DC58FB +:10829000E8F147038CE5ABAE705C666C1E0B3DFEEF +:1082A0002A940B1A3C2C1182C16D6C19AE0B4CF345 +:1082B000A55280AF8111ACAC60591A63AE81FEBF8C +:1082C0002B67123E1A7A17CD64E319FBF1CD2D8C82 +:1082D000413FB13A21BE17E09F5DBF67F62878DEC7 +:1082E0005B692BBA0F1B45EC6FE1FC5CD0D9699838 +:1082F0006FA6EDFA1123A17E789A4768817A3FBE76 +:10830000E0DCCDA550EE993E3A8478077CBDD53FA0 +:108310001FC0FFBC306FAF8FFF6CE589B9A3E0B918 +:10832000B3F2A1D9F89C935C1FFA9B35A5B3D90190 +:10833000FD5DB9529980FD85EB8DED0BAA8D6580B1 +:108340009CD609E7EBCF1A0CEF99E0318FAFF777A6 +:10835000EF3A85F0CFBE007A007C86F113B40F4B64 +:108360007D5208F09C5F2DA871A09B0255503B2DBB +:10837000F8619B463F66FC8BB10C867C56374F8C70 +:10838000B743957C979DF09F3F53882B307EFEB27C +:10839000BEC469287FD3658F8BF03D2BB34BC0EFF4 +:1083A000F7AE64ACA384C04BAF4D5ADF7B5D6DF676 +:1083B00062F83E2F4F6436A003563D8AC6233846E6 +:1083C000123E8E737CB8081F052B438FFF0CC6BF6F +:1083D0007A8A5316A1FED50DFCBB0EDF5609E80CB8 +:1083E000BE6F053A8B119D49C793F133E7D8AA5563 +:1083F000488F734CEFC7CA8CE8EAEF538F8E29067B +:10840000B856091D333C008ADBDEC4182E346010D8 +:10841000E95AE7471D4FABF635133F26F199FD3476 +:10842000F233FE3B8750437CF698EBF732CA8DBFA0 +:1084300064F6EE6440C2BF9059ACBE9AB1FF93D6C9 +:10844000779E00E5DF74346CDA74117C77F7FD9663 +:108450005530E6DCF89D19338A06CA69EDCB67CC46 +:10846000B808FBE3E3C014627CBDFBC725FAE893C0 +:10847000397C5B54B65D84B26493B7874A06DA658B +:10848000613B61887661B65DB268E7D5DB019E36F7 +:10849000C0FAA569F34AD3BEDB347892C797106F50 +:1084A000B2E215603DA4E9928CF4F255E1C839D3EB +:1084B000BC236CBB7DD4E0760076B30EBFCD1AFE34 +:1084C000387E4F1EDF3E04FC5F373ECED49F43FB19 +:1084D0007ED6F041F5F539A9E78B70D9515F298A2D +:1084E000D796D4CFB6EE4F9F3A1F88579ACF426E99 +:1084F000E843B2AB7208E8BC5CBEC3859D4B99F5FE +:108500007204F86133945578BFB9ABC3A5C0FBF2D0 +:10851000D2DB3721D19727D218CA83714CCEBC1F2A +:10852000FA1D274B2C81AB76D1419B07CAEC0A166A +:108530001A0DFD6674A7913CC92CB9E017028C9BFB +:1085400099E952B1BD2773D22F18D10753A4247CC7 +:10855000786A5FA8F3205CB35908595112E2AC164F +:10856000996C2C637BA19C79C91E560FE5097FF796 +:108570002922F2B4C4F55D3BB6473DDDCA0EA17EAB +:10858000C9D3E4CF2687BC9DF4C7751243FDE1191A +:10859000778780F0DC0B5D89C097E5E559B3EBA1E7 +:1085A0005C7EC41652149C4F87508CF3098AA4B782 +:1085B000747CEA7264C24709CEF463597C2FC0DF31 +:1085C0006A8F27505EC5A65E2DEF0578F29724C905 +:1085D0006BFCAB0F7080F03E7DD5DEF612A46FE928 +:1085E000ADE4FE323E8A27509EB1DA8630B60FCC1B +:1085F000940CF23F4D936769263DD09A65273AD196 +:10860000F50153254586790BDABCD98FC2A40F9C9E +:108610002CE47290BDB280EC1081F50AA73D307F4A +:10862000AC887017F1790C6A3F89B767C1900BED80 +:108630001C675A5313D6878F59CD805CE1BA341525 +:10864000F5B3E060AEBC09306F1B8B74019D340B39 +:108650004CC2F2C0780986E3395D9E56B4BB1E73E6 +:10866000B5D8107F2D87417FC03C36DA19B7FFE4BB +:10867000902B0BDA4735FB6D6DC5C85C2C67E4E8C1 +:1086800076615846BA5C9B5D9A8BF661BABFF7DBA0 +:108690002867676EFFE30C17CAD53AA87301E89DF7 +:1086A000CC8736C540EE3A4F153025C9CE734A4DBA +:1086B0000CED29E7A962C3FBC43A98D1390365D50B +:1086C0006BABC771D6642A84D75A26B762BB5A40AF +:1086D0008692B42ECE53794C9968D57FA1E17D0264 +:1086E000EC24C5399CFE3D4C294BEE7F548AFEC7D5 +:1086F00098FA972DFB1FE8D76FE8B74D626447C71C +:10870000025E5A77B35DB031B3EEC64CB4479DAC50 +:10871000A9CBC2EEDC906923BADB186CEA51A17DCB +:108720001D03C6073AB9F88BE322237B06560AE8F5 +:1087300085154A7DFD743C12EB71FAB5C50486724D +:10874000E962C96EE0931A662C9BEDA27361AD11CC +:108750005F365F650FD2CFDAEC34C56901BFFEEC3E +:1087600059C76A4A47C37CD3C2CB18F0F1CFB71FB1 +:1087700076B505A19CCEE9E481EDAFCE88C1FC7A47 +:10878000044E7F6D011BE1255C97DB2926F51B76E6 +:10879000B0D12817C348DF5E0E0F8EDF935DB8BBE4 +:1087A000DD627C10BB06FB61B62AD49426CDAB47B4 +:1087B000B383FBC79B56D0897CD03F9E9355D1781D +:1087C00022E03F79BC9C2F37DE5F717EE503E3CD6D +:1087D0009E6E9CDF6C874CF39BADF1AF3EDE5F710C +:1087E0007E255F623C9C5FF278DF30CE6FB653A689 +:1087F000F9CD16397DF58F97F3E5C6EB59574676D7 +:10880000F04607C827A093B48A7DAE5130EE469754 +:108810005D16948176B5B537B8E6A2EEF54E9B9E0F +:108820000DE3D45D0295F3B19769D36B4B19DB2E41 +:1088300070BAE8CBFCAF4DE8479E9CB9B68CF48982 +:10884000665F5F8955411F5F29717867157AE3CDAF +:108850004978BC17E4880A70FC14F85D057EDC05D5 +:108860007C89E5F8BA203D7783BD8ECF3D002F7E11 +:10887000BF6F5D88CABF5A37859E7A3F6553B8DDA2 +:108880003EB6DADA6E3F2F8BDBEDDBF3E4F94B50CB +:10889000AFD5A685502FB229173235D9AE664D8F88 +:1088A000B9E1FBD66FB20AD48D637670B803F5399F +:1088B00064B7A7551CEC5907E58D925D41BDBC51CD +:1088C0006133ACFCE631A867603CA793B7671772C9 +:1088D0003F2C10EE3D887A6F0EDAE980D7ECB9BDF7 +:1088E00007D1FFBB0AEC72D2CBEC8D83AFC2F71776 +:1088F000C0FF6BC7B2E865329467CDC9A6F1E14FFE +:108900007A6D0EDAEFFCCF4F669E20BF22ECE67A3E +:1089100021C0663FDE8DF0861C4A9CFA6377869103 +:108920000F54BBD24EA2206C473D9D8D7A1ABED704 +:10893000BEE1643684EF1207C9B5B9738D7EC37684 +:10894000774246FB677B45803543FF57CD347E77C2 +:108950003A39BF854D7EC32C5319AC2DAE77C50572 +:108960001968EF6FC4575307E32D7AAC79E3C1243C +:108970003A55B27C81B73DB8106C0CCAB34F58F968 +:10898000B67AFC589845C68AB9FD3FD6C5361E044E +:10899000D4BF80720FE5AD83CB8DC1FCC1E1A9D1FD +:1089A000E4E3BDEB7A6ADE1A3D005FBE1417500F98 +:1089B000142C83F749F395027101FD1D26DE5F81BA +:1089C000FE8D791EF70AF7E7318BF1F4673E93DEEF +:1089D00046BCE052A23C37CFB766D07CAB9F2D653A +:1089E00056FCA46C477B6ED66131D4AC0CE0439F3F +:1089F000FFFF345FBDABE19BA90196007A7916E8D1 +:108A0000BD9DFB310CED549D5EA102D94F575E090F +:108A1000DF912E54B508F1F9ECC8BE3DD7603B900C +:108A20001D2DE8EFEA7650E2651BDA415FB6DF2BD9 +:108A3000AF7390BDC558BDFC76D9407FA9D607FB62 +:108A40007D3B497FF6DB89F8679226FA10C6E6502F +:108A500090EC819BC03E467F3F5AFF9E94CEBF1F45 +:108A60004FB253F1CFF1A4FE5ABA7F2D280057E739 +:108A7000BAAE9AB7EC03E3962C936D6D68CF35C709 +:108A8000058A4324A01ED803239729B656C0FF1297 +:108A9000EC07E9D324D747B6423FC9764AF55CF9DB +:108AA0007EA087D6F2BA8E103C37EFE0F132BD7E61 +:108AB0007FDC2C1023FFDCCE9A9800703ADC3FFA62 +:108AC000792FCC476D9198BB06CA766EEFB0577D73 +:108AD0002417446FD32FF17B3006720BE75DD7F478 +:108AE0003B2CC76C2CDC02CFBB3DBC7D5472C94E05 +:108AF00058BF76B975064E3F272F726F168CD796E2 +:108B0000934672D0F19A6F37CA2947E6846568F7B1 +:108B10002C88FE308CF148D9CF16862DE86B816603 +:108B20003FECD5E8EC983D519409704FCFABDB9BFF +:108B30005565513FFA23EAAF46B4B6C31ED5FAD9FC +:108B400069B3960BFF9EC5E39D57AF7AE8BDFB6006 +:108B50003E9E526F08C96DF3F96C9F601B5CBF3B72 +:108B60003BF287ACA478ABBB5496280ECABAA6A237 +:108B70003DB7F9F39F76FD0E509EF5B997E46C96DC +:108B8000E88B0B2586F68F26CF436FFF974F5F0C40 +:108B9000E2FAFCC5CD48BFB2D8D397AA18D7D4CB38 +:108BA000F046C072A65EFEEDA5E86F0E94AFB9B4B4 +:108BB00016CB48BB409435FEE866D4CF5B05A611C2 +:108BC000F14DBCBE9DD72FD4BED75CF6FE2FB6A10B +:108BD0003E98E4203F74AB6607E9F0A97E91F0A3CC +:108BE000FA87C6E36B1A9E5DC3C7E36B567838906D +:108BF000A7BE8EF875B32E01E9D8FDB9EB466C7FA0 +:108C0000CF3A165E02B0EF54F6FD7A9B42EDDFB626 +:108C10005A87F3F3D477B2088EE3BFD80670F8749E +:108C20003826B31B53C0F1E150EBF9A71C2EE7BE69 +:108C300015E0CF2CCDDE74387A82B3E12957DE758A +:108C4000830CF2664349578355FCF9333FF70332EF +:108C500053C4DB037E4E7FDDB9E1D30847ABFC9004 +:108C60000BC74F135818EB6F99D2CB84A47E4301E6 +:108C70008E6780DBE987766953998A74E663BE382C +:108C8000033AF35572F8B7045F600AB4F395C1D3A1 +:108C90008BEF7B89FFD1E5E0F400820ECA0E8D3E9A +:108CA00002FEAD97A29D9F25EAF457D48EF4E2B060 +:108CB00069F563459761B9338B9727DD51D41E2B36 +:108CC000043DE380362817F21D64EF98E75718E05B +:108CD000F3DB96ADE6FBB32DF0E9ECA575DA3ACE01 +:108CE000118AC1BAD6D87A1A1AF1DB655EB2D7E01A +:108CF0007D433C69FE976BF8BADCCFEDADAD9FBA12 +:108D00001AE216EB918A4E276AEDCF824E27FA2D92 +:108D1000E803E8B412F19F44A71F336B3ABDD06F4C +:108D200041E740A7D5F8DE8C0F735964EA8E450001 +:108D3000A0F4D9F45F6D436D7579F58EDFC1B3E6AC +:108D400073AFE4873AE2184676A2CDC5E5FB80DC36 +:108D50008F5C86704B7213BD17BD61DAAF792E2B15 +:108D600045BF9327ED40B9358C7EE721DCE67E4B8D +:108D7000FD8CD6A3E6326F246E81F77FFA256E1F35 +:108D80000778BD54FC322E60A3EF29F945A7FFDC1C +:108D9000F05284E34CFC523FC02FAB86C72FFB88B8 +:108DA0005F3CE59C5F3C29F80523D1289F3794F070 +:108DB000F28FFCB9C40FFDFCC3CAE87B3FFFB0B221 +:108DC000CBB0ACF3CF658132AA6F6E9F8EF3B6C085 +:108DD0004B9B5F9F47B815D7553D4F6E15C9DEE8D1 +:108DE0006528A73A595FB713F9B05A08ED85B7B3AC +:108DF000623DF52E05BFF7B0D9607F6CD5E87E17D0 +:108E0000C283FED0242D9E25F5B0AB7C83F9D857C4 +:108E100099288B24E17FA486C76F07C277E0F89D6D +:108E2000AC772CDAA5A9D6E91E6DBC9B82EA3D562B +:108E30007C7F26BDF328EA9D6C7CF27EB23E7735BE +:108E4000A11C30F379CDEA87DFBB6F887E1ED6F098 +:108E5000F6D0D9F3FD4329F8FEF726BEAF14465AE3 +:108E6000F2FDC329F8FECF567CFF15F8FC3FACF8A5 +:108E7000BCD33F3C3CBB035CBFBBB5F5FDB2787EC9 +:108E800047C3EFEBFEB3B6035EB7C213E0B9779802 +:108E9000787EC76A9D00CFEFFA69BD6D31DC17405F +:108EA0007E47FF7DD3E4581FEE875AC0D197DC8FF1 +:108EB0004BE1FD8069FFB100745EF3D9A650C48216 +:108EC0002FA1DD3F92E1D7DBDDE397B5B8B3723D6B +:108ED000DAD53B2FF7F2FD846CF5732B7EF80AEBA5 +:108EE000EF0C58C8E31A1B9743DFF6BF4576DE57F1 +:108EF000E8DF6FD5FF331A7D9D49FF8F49D2FFD838 +:108F00008F59DE75321E4FD9961D290910BE7A2F52 +:108F100045F9B4EBE62C01FDBA423521A0FD9FAF27 +:108F20008D77BB5F21FAD2DBED92128284F59B64D0 +:108F3000212618FA3B6FA8FECC70007CE30324DFE7 +:108F4000D4F3F1798FA6CFCED61EBA30A84E0E70CC +:108F5000393D15C757CF31CA697D1EB67017EB452D +:108F6000FD02EE77DC82AEF2357D09FDD4513F9AE9 +:108F7000BCBF20206BFE29EFEF6CF50DC07739F6F2 +:108F800007FD5E61059F192F6782F3960138AF0ECA +:108F900058E825737FBA7FADAF13E9D3A4B8CE12DA +:108FA0008D5E80AF1A113E579B2DC60203FCABEBC2 +:108FB0006B904C69D8FF4E078FA3EE5C797B2DE652 +:108FC0001B74DE2257204AF297713DA7AC2CA6B83D +:108FD000EA6AAD5F33FCFDED1D5D632796D3B86B88 +:108FE00071DC8BAB5902E54606DA09147F90258CBB +:108FF0002F64393B821897DD2C74342C463D7AA9B6 +:1090000097F42D0BCEB58C4FE94F3DFEA4CF9B05B9 +:109010002BCF50BF99EACB9E8E26B493865DDFD9C5 +:10902000616957FD44B3AB607E3F1E12AFC100C5FE +:10903000B774FC0E1E87AF5F6DB849407CA795C31F +:1090400090C09269E10EDA6CB595C6592FDA4F657A +:10905000402FD4DF0B9671BF81FE36E8707522FD7C +:109060007C55B8F47AA9C7E3F570FF8CE21D5E2E3B +:10907000B7E803944F1CF65BEE1FE8CF8DEB645509 +:1090800002FD73425632305EB851D383E09905AF8A +:10909000F2FDEBEB0DCC23CEE39DA6FA51C6E99E83 +:1090A000055D64DF61183E996E8E6A74B02D27FCF1 +:1090B0007480E4482884740DE567495EBAA0ECA387 +:1090C000F25FA92CF7979FA7FA415E9FC9F2B0F013 +:1090D0000CED5EA176527F3FC7A8ECED1FF7351A65 +:1090E00027D05FEEA5EF85BCFE70C7495A573EFFFB +:1090F0001E91E6FFB1A466E0FEE837A38D14279A1F +:109100001F5D4ECF4DEBE45A8CC73DB3AEAFB515E6 +:109110009EDF9CDF28A3DD3F7FE94F68FF5EEFFF06 +:109120004AF42B90DF156906D94525B6F01EEF00ED +:10913000BF0DC0D1AAE9FBDE7AA42397CAFADA2BC5 +:10914000A0FD948F5A5B0D794E1D943FE356A4CF3A +:1091500092E3EABA1CFCBB433D1D383B3A36CD973F +:10916000B18330FEC7DED2788CE8BA4EB6E2177D06 +:10917000DEA9FAD7E79D4ACEE8F8D3DF6F2E9D200F +:10918000F3FC9FB8012FEED1F594EF73A5A0C1E9D0 +:109190007369FCC6EBCD82711E2A27FA50907E6758 +:1091A000697E9C592FE8E3FEDD1119938DEDE0CD2A +:1091B0002D132CF03B4CBC1D5DB72C5C6F4779DC4C +:1091C000E5A6FD7B26539C5FAFD79062FE75D95C08 +:1091D0008F30A74AF3D9726B461CED8E2D8BFE2083 +:1091E0006370C533EEE32ACCD7F4087D9F2C46F993 +:1091F00072AB8FF2311A167D52D59CD4FFC2037F19 +:109200007261BCB761DCFA6C8CBB2C64D2C7C9F943 +:109210000EE6711BA2AB896E63CD428395BF752CA0 +:1092200087F3F5424C9111A9BFE3C9FBC88B9409A0 +:109230000E8C4F2C8A19F77340433A903E1A379997 +:10924000DF27EDE788D83FA379C770330FF55E9B22 +:109250008DE86D27E00DFDC0625097F83C9693A510 +:10926000F1410FE1F35F0DCFB11C6E0F395D2CE6BC +:10927000C91AA09BDC480743FDE4AB14687F33E0C8 +:10928000D3F323BA484FDDE1D5CBA0B700FFE1729D +:10929000CDCE29E5DF6D5846FFC7D373D0067CDC01 +:1092A0009EFDF865C1B1D05F79246893A9FCA44400 +:1092B000F6212F33F6F89307C99E95CF1542C0FFCC +:1092C00052F793878BC89FD7ECB1EE27C91EEB2FBF +:1092D000B30483F974A6F597555710CA23FBCB3115 +:1092E0002CEFD2ECF8F6ECEE275BC93E09B7652708 +:1092F000E9EF5AC6E3CB5FB77EEC0C2EE9C07CA247 +:1093000058A98DFCBD34133F3E98EDA07A637223BB +:109310007767C373D62D7D12C61B1C792F04500EA0 +:109320008C283DA18E04FA1F51CDD36458191FB764 +:10933000B3742DD90D9DDABAC0FFD6A3DE1B589F9A +:109340001ED3FAF0F50857F6D0FAF8CA7B68BD6C60 +:1093500058A6B81FDF8FBFA292DB1BB293EF2BFC86 +:10936000269BC75DFF942D6A4FEE976694DE4EF103 +:109370001DF70C1BD5CFD09E6639FEA76CC9A05730 +:109380000EE445FE909D64B7C2FB705925CAB740F4 +:1093900016EEB3D6964A37223DFF5CF34F619DEE41 +:1093A000A0752A09A445F8BA3D62B96E65C35BB7DA +:1093B00017D745485EA55AB76FCE17C35671B76722 +:1093C000353C7CD0F0B7BB902D57B9FA1CB80FB321 +:1093D000B974BB21AFDAB56F760273A1F5BCEAF5BB +:1093E0009EF46A94DBE6715FFCE23F0288DF999F9E +:1093F0003A2DE5E37F6BF2F185750DD40E16589189 +:1094000072480E309EF7D29F27269C76D2F45EC417 +:109410003CB4EF12EB333637FC06ED572F0E8A0CB7 +:10942000F7C71732635E198BEA79C13C0FF645091D +:109430005C5340E18B31210498628BA4D9BA5C3132 +:10944000E487CD9B3BFB10EEC3376AFBF0205F0C3B +:10945000DF979AF2C6AE6E5814AED7BE9FA4BFE394 +:1094600034AFB90AB71BE77ABDA45FE785E787EB9E +:1094700093F6E35EFAA76899875E97A3E3251CAE8F +:109480001F3D182F8BC3824356CE8C1F333E6A2557 +:109490008EAF451ABECCF831E3A171EE6C5A7FF362 +:1094A000FC5F7485093F2F027E305FD88C0FC62287 +:1094B0005720DDBE345F64681F4F1767DA314FA055 +:1094C00071B6C030BF68290BA5F3FC6075D625497D +:1094D000F09AF168C657E3A32C94807E1BEFF4D179 +:1094E000FA3DA7E1474C7C48F30AC3BCDAF9BC8ECD +:1094F000F3FC5599E675955AF17800BE475A41DA62 +:109500002A567A84CF6731CCA75D1EAC4F3E61D519 +:109510004D48274B4D790B66F8CCF0CF4439387560 +:10952000F03EFEE41C5F80CE2F8C67216D1F3F83D1 +:109530008E3584B287CC5B18E0734E5F0BA3B3FB10 +:10954000C7C37E0516E92FCB80DF994FF8B7CE83CE +:109550007FAF0D8A0AE609CE9E3FAA0DE71F66E19E +:109560008C4409DAFB7D76942357313063A1DDC545 +:109570003049D4B7E17A3795F57E4F747C64273D46 +:109580001E614D7B69FF5DC9983B2EB57C591B74EC +:10959000D078663B6566C5E80C9417667CE878FA77 +:1095A000568E96DF309E8D3F1BBCF4A0EC457F1697 +:1095B000E368B08E7DCB19DB5D31B07FCC0A556E90 +:1095C0004FE630DAFF5F9D93A9D91D4D147758A05F +:1095D000E9856376D6F0A097EF234F48928F0BF37F +:1095E0006A57E724C5FBF47D642FEB25FC7DD7E5A6 +:1095F0004D88E389EEDEEFA70F925F7ABE6684F2B4 +:1096000035C58C950AC5C53CE9E35906D8C58CCF4C +:109610001BFC989B7230AEE7298EA31130F3895F53 +:109620006C9AA70CACDBE6257B3B105CF7D2DFC75E +:10963000A87385E77378B475ABD5D6ADDF8E2E836E +:10964000F749F83DD1A1D961655A1C1FFF40F94483 +:10965000A91A1FCA7FD5D7D15D06FE87218FB08397 +:10966000F0A7AF2738117DC89791A04439C336E6DB +:1096700022FF387213CFC758C8945D981FB4306A60 +:109680003F91DC4F244F2238229BDD5ADC2444FDDD +:109690002CCEE3FDB032EEE7F5D37D0CDA27E53FC3 +:1096A000DA5C604A62FB4C1642FF09FACB417DCF7F +:1096B00036258D3372F0B8A9FA33B713B5FD5BD1F7 +:1096C000190A8592E4F46F72B89E3C11ACECB28D2D +:1096D0004C8DBFC52EBF2A25E5C51ECF733558C595 +:1096E000C5F4FE74FDDD6F27C6963F956C277A376B +:1096F000343E75F8A2243B31D6F814C515F5F2595D +:10970000DA89CFDFD5F8542BCCEF1FAF7E83F2C7B9 +:109710004F3481C0043CFAA3D3D89B7E940F32E926 +:10972000AFE206F0A830F95B52C622BDBBA305AA82 +:1097300094942F7B2C4721B8FDA52AED9741D32E79 +:1097400074C5FD524840BCDDAEC5CD8070C7CEF6B5 +:1097500025B7E37E883E9ED325131C0E7D3C166AFA +:10976000A6FCFA998CF4889E07A2F3B5DECFBB392C +:10977000C678DD30F8F9DD9CAAC1FC2C8A4DAFDF3C +:109780008A72E22991FCB0EF046FA2F7E678C089F3 +:109790001C6E1F8E102327502EF4343CFF9D1F405B +:1097A000BB35FB9C2154C3ABBEFFDE8FAB14C4138F +:1097B0005FFFF94B1BEFACC2798D9664DADF28E2CC +:1097C000711847B340FEABBBC411DE07CFB703B57A +:1097D000237293E07A3B504FE59133385C27A0CF5A +:1097E0007605DB6D6F207FD1C7F7BD4F280A9DEF4F +:1097F000133D8CEC09D1C99F99B9DC2ECDCCE5780D +:10980000766B4FD729811609E9BA09F72DA418E517 +:1098100041BB4E49F4DE210896F69ADE9FEB140810 +:1098200067C497C7DCDE41EF713ED85EF433837DB9 +:10983000938FEDABF0C9E9DD75CAC3E1F09BFB493D +:10984000E7EF35FE33C37163CEB462C4CBDB017581 +:10985000442E8F6F7339EC7DF2A8307E38F298E792 +:10986000EB5F9127B928AE77AB101F0DF2A9BDECC5 +:10987000441BC9AD1257139E934AB29F047EEE86D5 +:109880009FAB18B04FFB2E995389D16BA6DC1B1AE6 +:109890006C6FBD5EF9C9BC3958D0CE4F7C5797BDAF +:1098A0003128833DF79A565CA48CDC80A1FE2BAB5B +:1098B000B97DD688F65988E496C1EE32DB675ED072 +:1098C000F773802E96062519E9C26CA7B557CE23EB +:1098D000BBA61DEC1ACCD71E6CA77179735BD4C6DE +:1098E00054A8F74CB5487EC63365BD4F5C8CFA6210 +:1098F0008A5D217D51D677DB1CFA3E91C6F16AFE66 +:109900001DD4E7E71D429EF86878F76CF59BDEC62C +:10991000A4F57E66CA9B63D12FD89522BF428FD310 +:109920001CBC99E77FBD7E87107722DE6E116DD853 +:10993000EFC20A1FE5AD5E227A699CC6AD62DC49C2 +:109940003854D32FC919B01B99589DF33CE2619B41 +:109950009DE1F9C1A21B7B0D76EEC2A8D19E8B348E +:1099600081FDA39CBD1D68B6FFCC76CCDA5CCDAE84 +:109970009BC026A0FDF2CCBAFDECCDD10376CCACD9 +:1099800014FBDFBA1D7381ADEEE65C1E17A4FD83E8 +:109990005992F5FEFE559A7FCA42DC1FBC447C9F5B +:1099A000D6EB444852107FDE9B9EA4731DDE7F8A57 +:1099B00061ABF1B6E7727F7C978391BCDD35C14323 +:1099C00079D7DD379F9BDB4BEBA5DC5D8DEBFFA4EF +:1099D0009DE4602AFDE68E8AAC1426E68B0AF4D458 +:1099E000D77344D4CD92F5C38814790ABB73B9DC1C +:1099F000CEBE85D9D0CFCE8C31D5CA2FD5EB813F05 +:109A00003A1D63D4503F9109F0AD2EB551DC5FF79C +:109A10004BDD767EDED7FEC8F531F44F47007C087B +:109A20008702F0A11C2E897AA83C32EAA7E7A86831 +:109A3000263D4BA305F47D7474143DC7444BE8FDEB +:109A400039D1F3A85C169D48CFB1D10A7A9E1BBDCF +:109A5000909EE781DEC27AE5D15A7A8E8B5E4EEF18 +:109A6000C747E7D0F3FCE86C7A86A2DFA6EF15D1F2 +:109A7000467A4E882EA2F713A32BA85C19BD81CA83 +:109A800055D1EBE93929FA437A4E8EB6D0734AB4F0 +:109A900099EA4D8D6EA1F205D19FD0F3C2E8767A96 +:109AA000564777D2779D9F3D9A3DFD74708F4CF954 +:109AB000F62C518EF231151FBEA1E9856FE4AA4F35 +:109AC000A03CD5EB1DD1CE1D98EBBD9A3B74DECDED +:109AD000D15C4E9F1F848EDF85C769F575DB1C1C2A +:109AE0003A8EC0CA0367D8B7E2F33B9CCBDBEF9258 +:109AF0003AC8DED8D5C4281FCC57D923503E43508E +:109B00009A61454799417EBE6B4C6EE45D9CA737D8 +:109B1000EFAD83B81F7565AC27300DE92514489B60 +:109B200006FD8D68B5917BAD3059C0B252CFE404CB +:109B30001B88E7807D65D06BEEA04D8BFFF4CC9C3D +:109B400088F09C5B3A81EC576D3FF9C8CD2319FA38 +:109B50001DBB1C09414279B996B1643B7CD786C5CF +:109B6000F7259FD370071D9C8F36B1C7304E56D254 +:109B7000A1D4E179C2513BD4C730C573743C52972C +:109B800006E5737E157B0C9F63BBE2751E789EB75E +:109B90003FF118BA4FE312BD755E289F7F981DC034 +:109BA000F053458F32CD07E58947D503B84D52D5DF +:109BB0001B9996AE203CF196748067D76B60684124 +:109BC00079CAFB1D22B82503EB0F76DB8349EBE254 +:109BD0002EED5145F867E18D7205CAD95D52AF3B54 +:109BE000B37CF0FA74E2BC719EA057F66AFBE8728F +:109BF000D27A5405053D1E9817AC1A880776B63EF2 +:109C000047F1C0CE34B916435D7D973079B7827481 +:109C1000CCFD84B4B691A49F74BA03FC1AEC49B786 +:109C2000D6EFAE7E7BD31ABF55FFCBF07B50A3E7B8 +:109C300054F87D1AE79177663E9E1EE47615F07122 +:109C40005D303B75BD15412E4FCD78DE25C9E7123D +:109C5000BEBCCC16AB1858B76B34FA3E135E23FF6C +:109C6000CBF07A517068BCB24A3F8F336BF969A967 +:109C7000E4CD9114E744BEA7E13149CEF178A90CB7 +:109C8000726E546A39578B70650F21BF52E43BAC3A +:109C9000D7E8BB3B3B1C0B669F39AE7F9B4DAEC5E7 +:109CA0007C97D878467E02D897AD98BF3322A64CD1 +:109CB000A06D2C14CA88C709E7919F5E02F686340E +:109CC0008161AA63029F575466DA1697635E83C662 +:109CD0006FF2A26032BFE9FA7E801F75BAC8EAA4AB +:109CE000731640AF984FD8ADE169A01F1E8FD87092 +:109CF000537E677B921CEC0C155059AF9F8A7E5F98 +:109D0000D7E9B7F539DAEFBFA2DA3ADFE4CF41514C +:109D1000CB3BEA5391CE63354CA6F3CEADC7493E5B +:109D200065827C124A787808C72F8CA6DD8771DAA5 +:109D30008783399A3F2EA77DD3F7FF8F9EB781AFD8 +:109D40004E7E66B5DC8DE72A46801E52504E560385 +:109D5000EC95A8E71CB4EE0AE3EBA854B3784220D4 +:109D6000BC25D06F8ED9F8F98C238E2E95F48E23D6 +:109D700053C6FC93EEECC813C121F842F62815B87F +:109D8000A8AF0457CDF4E6615E8E9C86E597A07C73 +:109D9000DB14CC13EA655AF936EFD42F1F7F7865B0 +:109DA000C78A23B84F7561503D8AF0005DBF827449 +:109DB000AD9E234B141F1EE6FE93CE9F03FC24573B +:109DC000E8FCB4A89CE4E15BC1A4FDAC54F6CD2E44 +:109DD0004D7E7E121CDABED1E9FEACED1B0DDE37E6 +:109DE00035B9948AFF673EF1FC8E3D6C20FEE7CBCF +:109DF0007FB14752D0DE9EC6DE9C8871AF1E4EF703 +:109E00008CC7F9548CFF011DB82B5DA6B8AD30434B +:109E10008BBB0C19AFD5E3C97ABC4F8FEBA56B7424 +:109E2000851706A01E4F9F224B8BA9BF5E7615E6B5 +:109E300037E5D90C7C8D720BF7E75D6D59D2C8F20E +:109E4000817E196B2239D5D9C0E4F64CBEFF9A0148 +:109E5000F2A5633D233F2FF68C48FD9F546DEF61C3 +:109E6000CEF7C94A4020CA059529728E760E8188A0 +:109E70005C267A7532D685FE36FB51C8E5C038F7C8 +:109E800067025301EE239F89F49430C20D8DAE0812 +:109E90005584B0716D467508F703C537A10C70D6AF +:109EA00067546760F9C89189216611BFBB3AB2C88F +:109EB000105F32E3A9BFDE77DA285F61E719F63F6A +:109EC0002FCA73E876E7E43CDCFF5CD2D7EA5006A1 +:109ED000F63FF57DBDBCD2872EC57B76F25672FB70 +:109EE000339FC59B93EDA6A4FDC5DABC2ADC4FEFDA +:109EF000DF5FEC1993BCBFB826FF163CBA7F4FFF5B +:109F0000FE62A412EBABFEAE0AA44F3D1FF688839F +:109F1000EF03B0894F05140BFA5850F17836D1A3EE +:109F2000E64F0CFAAEC5CDCC7EF09C3C631CFF64C2 +:109F3000684E46023FA688E3EBF13CDD0FC6789DF4 +:109F40006CC97746FCEBE32F10B81FCBEC02C93B82 +:109F50005D6F823C598AF88666148F569D02E56BC8 +:109F60009D0C352AE417A5902FFDFB062C31DA6AEB +:109F70009F75819677627EFFA33CAE9716D8799C39 +:109F800052B87E6904C75D90E7129C4976D28A3C3C +:109F9000AEC7F5FD1747FEA92AC4B3C31151ACE6FD +:109FA0006DDE475981B66015C753C842EFA5C2D3CD +:109FB000517B07EDCB1D5D2AD279DD9391C974EFFA +:109FC000432AB9F00AD2CF68C6E6E5733D34B08EB5 +:109FD000D678D3F364CCFB55FDDF17B9E9FC8D3996 +:109FE0005FE6210D6F4F6978F957E7CB3CA5E1EFAC +:109FF000692D3EA3C7B3AE4821EF2FB0D53D90C722 +:10A00000E38C43C665CED3F37D34FCB00363E95ED5 +:10A010008E2D3DF6B85B40786CB47FD9F09F620816 +:10A02000ED2FBD9DD7242FF4FC1DBDEC3925B07854 +:10A03000D23E8247EAA238A9E79444EFCDFC775B91 +:10A040005EFFFE22F19FBE2EA9D6595F17F3FBFBE0 +:10A05000B47539BAE84F413CEFB2C5CD2CF38958FD +:10A06000BE31FE6ECE0348B5CFFD9AD6FFC9C8D427 +:10A070005C94CB0D8ED8E8E1F0BD8E9F17BFF8A39E +:10A080000BF96CCB29E70CABF57849D34FA04F37D0 +:10A0900025EF83FAE63FDF8ABD7A24E33EA8AE4F80 +:10A0A000F57D504FA5791FCD7A1F740BB3968FA9FC +:10A0B000F64107ED7F6AFAF6B3BC14FB9FE5439FB8 +:10A0C000673F90C78695F771B5839F9735BFEFD1EE +:10A0D000F8EE646473D15DC057372C7252965262A9 +:10A0E0009193F8B071919BE2B28D153CDEDB78A7BD +:10A0F000A0EDD719E3B04F83BC5809E33FABE99D0E +:10A1000037597812DAA3B32A05C33E79B8DA6D2835 +:10A11000CF5FFA93A7F1DE8467A6D8158A3F435F25 +:10A1200031B40BAA799E2253FA6EC338B71E7FD67C +:10A13000D7FF99EA37E91EB418D8F9A343187F1658 +:10A1400089BF9E796122BF974E18D80F57C04ED84D +:10A1500072C128CAF778B9FC5B14E7DD8271719887 +:10A16000E9962FFE3883E80894720CF9757C561C2A +:10A17000E563E3B80939489707C67FE6C3B8E8EB5B +:10A18000B79CCCC675EA5DD7447907E67537C799A1 +:10A19000CDF1E5B38D2757E71BE9E169533C5997AA +:10A1A0005766F991144FAECF1F463C59975BBA9C46 +:10A1B000D0E5D7CBE5EDAFEE867FBE1C71124CAF7C +:10A1C00068F3EEE74B8D2E5FD6F9F00B27D9230706 +:10A1D000C63F4CF9567ABDD6BC4CA2AF6F95C7EDC1 +:10A1E000B43F8B790A6503EB323FB2BCBF8CDD7E96 +:10A1F0007BD9F506FAE8975367946343CB29573E1A +:10A20000B7C352E56BF6A4D43FA3C94EF5FCD51EE7 +:10A2100077957C793DD4B0E80F0AB683E70E6A3FA4 +:10A22000DE11895BE827333C9E53228B4F4C7EAF77 +:10A23000F0F7FD7AC041DF6375CAFAF5016E4FB7DA +:10A24000107FC69CB8EE52B6DA8A749097ADB6E528 +:10A2500043BBDF06D40DF949F2B4C5CEF723451B45 +:10A260008B3C688197C7F235BCB07010FB6BAB3587 +:10A270009EE7D29FBFC997B4F3189382685FB7BCBB +:10A28000511144FE39E89B44F676AA75DBA6F31318 +:10A29000CAAFD103FEC4566DBD814555DCC76DB351 +:10A2A0008783C9F1C6ADF99CAED2A73ED48376733D +:10A2B0008B6CA33CC11699E75FB77AA5197BB4767E +:10A2C00001433B493F4745F765485E637EF5636858 +:10A2D000EF54A59EE763F9DC3FB4B3C41DD5C2803B +:10A2E0005EB11FAF75D1FD0F4C95797E53C8904F6D +:10A2F0006DD7F44B9D295F4394BF9CDF569C1DE9AD +:10A30000C6F534FB6D8702EA63F83E2AC59C481FF8 +:10A31000519735DF1FD6D6B5459BAFF95E55D17441 +:10A32000EF8368BAF72156D7F4CB5EA4B7F54EB9E0 +:10A330002540F73CD0BD0F51BC72099EFF70F37CE5 +:10A3400016F0FF26F3F306A15E94AF2CE8A2785432 +:10A3500047A1AA164259F4D976AF87FE5AD43A15C6 +:10A360008FAE74786D9DB8CF979317790DE731CD87 +:10A370002791DEE9B82C8DF4107C777339C26461C3 +:10A3800012F98374690AFAE078BECC1E74503CABB3 +:10A3900025C27A9DA3F8F97FA4F75A9638525D82B8 +:10A3A000F6B6AB12F17424343123622127F4A77975 +:10A3B000FFFFD5EFBD544CF9AA62E4A37CDAF76F36 +:10A3C000DC8AFBFA6BF68B21DC47F8CEF75F1EC305 +:10A3D000CF1B19F799EFF6D4F4A23E8B7A1D54AF38 +:10A3E000DB37A903F1D422F83AD0DF6D79E3FA9F85 +:10A3F000231E5B9A799CDB8CE783BEEFD3FD1A2783 +:10A400006139B1BEF97E0DD6713D5F27A78BF62D60 +:10A4100061BEF6822ABE8E141F3CE6A37BA04E1EB0 +:10A4200039E045F8BEC2BC65EC37F5BC0B65D257C8 +:10A430001AFD3029BC09E7F503D1D7D11EC07BD264 +:10A4400060BD11EE47ECE4EFDFED49A7758D027CAE +:10A45000B8AEA2AF5E4597ECC3FD22AD73546AA2BD +:10A4600079B198C4F6E2FB473EF9F18548076A16D0 +:10A47000ED6A89454D84970F012FEB2DF002F433DF +:10A48000A600FDE5476EA07E3A1C2E192D9B16DF17 +:10A49000243AAF3CDCFB452A0A847E7F4BBB5FA499 +:10A4A00002FB1D545FF3B3D0DFC6EFB532FB38CEED +:10A4B00006F09E2A7F452D30DACFC3C85F510B2CA2 +:10A4C000FCBBAFB0AE97170C49CFC6756D71FDDF01 +:10A4D000E96867A9627AC85D0C655C27C43FAE1362 +:10A4E000AE9716B72115A4201DC88902A4831BD2DC +:10A4F00043489F67921B12E3EB6E97809EC1AE7339 +:10A50000CA91A37476518BF7E8F2C4CC672D2EA3C1 +:10A51000BC6AD1EFE53B363C7905F4B202F16096B6 +:10A520005BC3A593EF0FA693EF0F45276979E12849 +:10A530007E473C154CA078C5CD583E7244DCE718E8 +:10A5400089E3F1B8595F1E937727E565E9F06CC69A +:10A55000CD6ED2CB3C6F4A6A600CF3E0FC652141C2 +:10A560002E1F161D6DFE9AE9E88EA1E48397F5D0A3 +:10A57000798D557A7ECEBEA1F373BEAAFE81F5BC5D +:10A580000FE169F17D9FE87383DD25F37BD4CE6E07 +:10A590005D1F2C10CCF70B3D988CB7C1EB1AD987F7 +:10A5A000EBA8164CA27B8CD8944564377567ABC773 +:10A5B000305F8C4921835C1CC43F9ADCFEC1390AA0 +:10A5C000E5ABFEA5599373CD4E19EDF1C70337FCEA +:10A5D0000EEBDFCE9430C6436B6C6B094F1FC2FC91 +:10A5E000768748AE96E1BE4F94A585343DFA1F08A4 +:10A5F000CF0CA559C882F781058A8DAE2155B63397 +:10A600005BF9F0F1F0DC603C3C37141E400EFEA715 +:10A6100046CF37223DEBE7ED53C9C137B4FECF42F9 +:10A620000EBE91CC5F5F03FDBE3FB47EFBDAE5CD8D +:10A63000A7389E59DE78357EFE6E8885305E3EDC1A +:10A640007C36B03715E4AFDA7417D14FCB8302E50F +:10A650004B811D1EA1B2CF45C2E6A0CFC1F37FF74B +:10A66000F1EF621DC7B3194F42213F9FB5AAEBFA24 +:10A67000B064C8938AF1F39AEA09B954C4FCFE6A3B +:10A68000A267BF66CFE879FDE99AFCEFD7F3336D97 +:10A69000349EBF88CB773FD83B681731A997A11F5D +:10A6A000FF83029EBF0FFC40F40DA384911F32A6CE +:10A6B00048A63C2DCE2FD912B77732034C205D83AC +:10A6C0007962F0FE13B027F07E824CD5D8EE076990 +:10A6D000DF15506FF52EF23609740E3EDCFD33287F +:10A6E0006761BE17F08D7F86B17E364B2A5BF8E737 +:10A6F000B13A5686798B15855ABCCDC182A41F35D7 +:10A700003F5DBF2F503C73DED7D4C261F8E9171705 +:10A71000EA79C2467DDCE56696F1B523855C1FD5F6 +:10A72000F7D6D6A15DBDD6C7C8AE5A8BBA13CB99A2 +:10A730000EBAD726D45DE9B2BAAF2253B519EEE707 +:10A74000F5CF4833DC7B9B1DCE3294731BF20DF5A5 +:10A75000F322230DDF0B969D6BF85ED434C1501E9F +:10A7600011BDC050BF04109C5C1EB5E93243FDD141 +:10A770001D5719CAE7ECF896A1FED8F862C3F7F3A3 +:10A780007E759DE1FBB8AEB586F2F9FB6F36D46FEE +:10A7900061D6F777766878057E2739D6ECAD6BA061 +:10A7A000DFD1901D8638FF755ABDEECC4965180F74 +:10A7B00069395E5146FE70FA0543FAC366B9984A94 +:10A7C0001E9BDF6F2EE4F2F383C7DE9EB412E91CFA +:10A7D000853CC8A50FBCAF6CC0396D2EE77909FA6E +:10A7E000EF6298EFE5EFDFA794549ACF822C07B37E +:10A7F0003A1F705DA162B9BFD02A845CB857940A31 +:10A800006F478689B7EDDA3CBE2ADE8E09C638105E +:10A81000EA93072DE07A42E32BD057BF453E047DF3 +:10A820005599461E06BFC7E16CF5890E07E8937F70 +:10A830002FCC1E9C1FFE41C3F3D7DCAD60FD6B78AF +:10A840007D5BA80CD725D5BED21385E67DA5AA656C +:10A8500028E716F8D284E4FB9AF76BF5F478764B88 +:10A86000FA67B4AFD4E208950D675F697F21E3F71B +:10A87000E0E2FA6627ADAB5D0DCA96FE9DD98E610A +:10A880004FE03D1831AF4479C366FF2EAAC96DDD94 +:10A890009F930ED692BFDFE21D49791F2DEA5AD24F +:10A8A000971D29FC5CD097BDB83ED37C371AFCB904 +:10A8B0008178804AE3415BB29B5A92FC7F6CA7DEB1 +:10A8C000CDEFD5FE1AFCE08F0ACFC2FF5718F783F1 +:10A8D0004F328EA793AA8DEC84936027A0FC6D93D2 +:10A8E00018ED7BC72A05C5CA2FEE58AFD987EB39BB +:10A8F000DECCFBDD663BE38AD0F584B736A0275774 +:10A9000025CE9FDBBF6D767EFFA6EC0F0751DFF6ED +:10A91000653BD86E80F660368FCFE978F9B2F228C1 +:10A92000A76890FF93533484FF738958DE85F7B688 +:10A930009E38C5E3220A1E450CE03DE47CFDD63E70 +:10A940003127B606F55489D484F9EB225332102FFF +:10A950006B0E8B2C2EA01C33E6E7DB59D35D188FD2 +:10A960006301FE3EC65CCD6827654C31EAB14CD52B +:10A97000A8C7FC33B24C7ACDA8C7721B8C7A2C2F97 +:10A9800062D46305CB2698F49A518F8D88D699F4BA +:10A990009A518F8DDA749549AF19F5D8393B8C7A75 +:10A9A0006C6CDCA8C7CEFBD55A935E33EAB1F3F7E3 +:10A9B000AF377CAF48B41BBE4F3C7CBBA15CD573AA +:10A9C000AFA1FEE4A3BB0DDFA7F6FEC6F01D10FD90 +:10A9D0001C9E67C07B6871112F7CF721E377A63A34 +:10A9E000301F7F059ECF8475BCA8EF61437FAC8389 +:10A9F0009F5B88C17FB85EEFB008DD030072EC504A +:10AA000001B45B1D17420986FAE9C1B771DF6679A7 +:10AA100050243F6E0D065B911EEEF7C5911EAEDD14 +:10AA2000613CFFB03C6E2CC7807E148C2B00FD2057 +:10AA30007DAD30FD6E04D883446F2B14A909ED4A17 +:10AA4000337DBDA3D3574C7D0ECF73E8F3D5E767B5 +:10AA5000D7CF9F6AF4A76AF4C7C44708EE1505224A +:10AA6000FDFE8E3E5F15FEE3DFDF77E03C3ED92F33 +:10AA7000303FC0710D8B1D2AB098CFEAFDDB1DC899 +:10AA80009FE67999E761B653DB8A8CFB489788DEAD +:10AA900010F1DD0B22E9239A02F2D903FCBCDEDAC5 +:10AAA00027443A17837C88FE82186B20BCAC01BC1B +:10AAB000E0BDE1BADD7A426B77E2A7229D6F3E13DB +:10AAC0003F2A1A3E9C41233FBA9534133D19F1EBBE +:10AAD0002933F2E78AD72E75A0FC3A04F816A6307F +:10AAE000E60B19F97585B892F6F9743C2BF01F8EB8 +:10AAF0002B81A98BF35E0DF34E2883F1BBEC91ED16 +:10AB00001B0A2CE8E64CF87DB0C8B8DFAEEFCFD515 +:10AB100002761C1679A53AFEBAB3D53FA27C4CE565 +:10AB20000F1F283A6B7FF840D1D7EB0F3F5334A467 +:10AB30003FDC370BFD29274B0FB55BC4FD242627CF +:10AB4000305E6B6FE271BF81F8DDD71EE7790BE1F4 +:10AB50009464AE27DD921EE7091D8DA07D92716E73 +:10AB600008F3A2861BE7F870B01EFB70283D06F6BE +:10AB7000C5313C4FA866E4D7DB9099A45019DDEFAE +:10AB80008C20F03CA4FF46F806E5EB966669F9C711 +:10AB9000CA90F9C75768FBBB1706D57F221CD0DFC8 +:10ABA00069ECAFFF3EB6CA6CEA27FD0CFDC4EAB8FB +:10ABB000BD16B3F93A5AB8BD46FB4C5F431CC35FA0 +:10ABC0008C712D2FC77F8B83C76DCF36CE565C3CE3 +:10ABD00028BE545C3C447CE91FAFE6F273AB21B065 +:10ABE0000E2A52D3B77E0E532F6FCE34FACB1B26CC +:10ABF00070B8CE2DE6EB1ED1CEE3D668653DEF12E0 +:10AC0000F316DD13A03C939F53D2CFB5EAFDD414C5 +:10AC1000FBA8FEA7C1BA1AC4C786127EFFCE864C17 +:10AC2000E33D3C278A6A6B705E53B4FE6B8A193F22 +:10AC30003731523BB7698A177CAED5FFBCA88E9ED0 +:10AC4000788E16FD1287285AE2735AB14DBBEF86F3 +:10AC5000D173BA7E7EEE4E7EBECE7CEF02F0C98B03 +:10AC6000F8FB506FDE66277F0FF4119D9F5B5AC083 +:10AC7000CF219AEF538894C98750BC7EC2CA2DEF6A +:10AC8000E51994E770EC26CABF7B662A9385BC332E +:10AC9000E73D7CBBB85F5F85BEE439BAC6E261E4DC +:10ACA0006B2DD1CED1F5A6713DD697E78AEFB6F0E0 +:10ACB000776FD5E8F236CDAFC5FD69DC27C7FBBDA0 +:10ACC000ADF6CB6F2DE6FBC3C33D577DBB231241D1 +:10ACD000BE359FAB4E759EBAD7D1DB968BF08E6595 +:10ACE00021B4DF7317C8DDB9502FAD5EA1F38F1B00 +:10ACF0004A58FA14FC5E610BE1B98ECCB9F2063BFE +:10AD000094334B599600E5DED81C1AFFB606268B05 +:10AD100000D77DC5FC3E8485B77C44E36557C3D42A +:10AD2000143A773E1DFDB35803A37B0BCDF3BC5BF8 +:10AD3000A35F571BBF2727A3D43A0FFFEE62DDBFE7 +:10AD40000EDF85F45B5BCAF6F1F3B3FC9C025E4B4D +:10AD50004FF99BA134DA17BC12D68DEF9FF7D0FACA +:10AD6000DD149CF6536CA7F39B43CB53309F27BF56 +:10AD7000AFF8ECCE93A72DB08637A1ADF735D9E16A +:10AD8000FB918ED2CA3AF8EF977E71FAB43849FB3C +:10AD9000694705DB4722A8FFDCA0FF047C2A329D1F +:10ADA000A3652E81CEC3BA9426A22BF794901F7F61 +:10ADB000178D2DB131BCC7659AD65E6D6002FE9EBF +:10ADC00004E502929C36FDBE841A6A6D86F697E011 +:10ADD000BE5908F3BE43CBB0BF7A6F9A8CF14D7762 +:10ADE00069532DAED7E30B791FB7A7382FA19FB3B7 +:10ADF0001FB87F6ACDB3867B051CCB9F35DC2BC08B +:10AE0000963FFB55EE1578AD78F9B3FF13F70AE8D6 +:10AE1000F20DD4901DEDFAA322BF47EFC347AFB6A2 +:10AE2000E33A6CA8655D88F7D8678067D7009EED28 +:10AE300075E1C777A25DB2363DC47F4F24F61D840D +:10AE4000F3350F93B1BD9E6F28B032D2D7731B0478 +:10AE5000B21F98D4B71ACBF31FF1C8E83F7CF8E8CB +:10AE60004B4531A0CF576F3DE9C3FCD4D7A53E1F5A +:10AE7000C2F5EE2DCFFBF0FEAE576F11290F85CE38 +:10AE80007D27E5890923387D2D1A113E85F4B5709B +:10AE9000DD3F2725DB672C9A4DFA7E791C204EB6C4 +:10AEA0007B7FE531FCAEE8AA2EBFA1ACEBF9554E95 +:10AEB000EB73F35347703E5C7E7FA7A340C1F12341 +:10AEC0006923A0FEBBDA39A077F7F9C88ED7E1591C +:10AED0007C7F8503EDE1D71F71B204C5057BECCC07 +:10AEE000CBF507E65D44F8D083E03CF4970207F227 +:10AEF000D95281F53989B9D921C4F7DF34FFCF3C64 +:10AF00008FA5AFCA0E5CDFA5B5AC0FCF9D2DBE518E +:10AF1000D8F003A8BF38E225BFDF3C4FB3BEB91657 +:10AF2000EFB311ACEE816B3AF467E86709F483F68E +:10AF3000E7D20EE3F713876F38B413C6DDB7DF41EE +:10AF4000F6E2B56788F78F1FA1E9A5496CF2E951D0 +:10AF5000A4FF32C629A9ED0E5D1FBDBB8E5192CA5A +:10AF60007FE1EFFBC2F3FD75323D4F152BB41E2B75 +:10AF7000F6771FA2DF16967A26A1BC9BF944A3E7B9 +:10AF80005B6C20AF685267CB819D5455CF574D50B5 +:10AF90007C6F8A76FFCBB5DAF98FAAA3E67CD5EE73 +:10AFA000C7FF8C761BCCFF6CEEED5930CC7B7B4E13 +:10AFB0001C9EE6413A993D42F37F26035EC4AF8E64 +:10AFC0009754ED56A5F8DD169D9F4E697A66C99E89 +:10AFD000D91BF261FC9647DF29C6F8718C71FAAE75 +:10AFE000FA29FFFD9F2A6F0ED19B0BE9330F9B9827 +:10AFF000EE7988B11759127D5FFB8887E82408F63F +:10B0000090730ABEE1F45A85F776227DBFC0DBBBA0 +:10B0100034FF36F2C8ADBCFE9F1DB233487C19B474 +:10B02000D13311B44DB1B867CB7CBF5887B1FC8127 +:10B03000BDB718E5CAB5263FF403C13A3FAD71C4A8 +:10B0400048C2C712459D8E79004B5978038FDFF2B5 +:10B050007B7BDE953A0EFD10F97D8FC06280A7558F +:10B060007F7CE0DF518E5DF7BB3BD3518EBD2775F2 +:10B07000E4E0782BF7B6A5A31E78578AA563FBF703 +:10B08000E25C9E0DD29723044D0EABE902C8E4D5D5 +:10B09000446AF0FF257D1B6E8671FE1BF08C7CBF21 +:10B0A0007ADFA7543EA4BAFA5810FBED9D8E702C9F +:10B0B0005FE46D6A0EA17F69E4CFEB7E79678E4213 +:10B0C000791EB1020D7F05D86EF51E3BE5F9A21F72 +:10B0D0008FC3AC617D343F73FB355D6F3A505ECBFF +:10B0E00036D65778E1E0EF60213990DFD6ECDBF21D +:10B0F00091988ECFF75EC1DF835A63B24F9769F2A2 +:10B10000DB4CFF5D26BA07FC507C210670F19F6383 +:10B11000E272BCE5D7778F7F03E07B7FCF53E9F8FE +:10B120007B133AFDEBF73C9FE86A5CE818E21EA14E +:10B130000F343EE9D70F9A7E52F60360B9507C84F3 +:10B140003F57DA13E917C27C5776DA4348F32B1FCF +:10B1500010552FDA552F3BC91E59F9C049A2DB956E +:10B1600082DA27909E63E928C7F5F55AF1C0DFA679 +:10B17000A39C5E9127B299C08AD7FDFE135E1FE89B +:10B18000DC0DF5573CF8C6F41F6219E489CB62BDAB +:10B19000A675753B7ABD16EBD5F5C6748CCFB7FC9A +:10B1A000FA1FB41EEFFD4560B92583DB2FEBFC1BB6 +:10B1B000C5C1DE8785F167727CA1BE59D3252E7289 +:10B1C0006458AD5F62D6C395F49DF2C2CFB48E1DB4 +:10B1D0002318D78F7F7CE0DF1E063896BDE20CCDAA +:10B1E000C471FFED86740674F08ED4C4E9FE676DF9 +:10B1F00039A8BF97D96339323DF9FB65BBBE47F427 +:10B2000078ED5FBF97A3ED37E4D9481EC4F2709E76 +:10B210004B7F3A8FE6790D8B103D2EFB19BF67F1FE +:10B2200013F0B3ADFC84A90AE71B27BB7EFCCD015C +:10B23000949B78670BC0E160FCBEAEE778FEBB93E1 +:10B240005D95916CE77A146ECFC558FC35B43BD749 +:10B25000805A46B9F6FF003503B31E008000000097 +:10B260001F8B080000000000000BE5BD0B7C54C5DF +:10B27000F5383E77EFBE425E4B5E8457B8791224B4 +:10B28000C485249040D485400C0AB8404494884B2F +:10B29000C010202101AD60A5CD860002C53628551D +:10B2A00014B40B8245451B31086AC08D2886EA1705 +:10B2B000438D165BA18B2008045810EAFA2DCAEFC3 +:10B2C0009C33F766EFDD243C5ABF9F4FFF9F7FFA08 +:10B2D000A9C3B93377EECC79CF9999B3E2814BF911 +:10B2E000BF8C62ECE1787DA5C9C25805D33B3D66B1 +:10B2F000867FC215814A493F189FC35F0263790761 +:10B300004675F3A4316662178CF767327611EA9FAF +:10B31000B36ADE6357E2193BB1D1D445B819CA18F4 +:10B32000565A07EDAFE0DF6DFEB25482CEA3A9F905 +:10B330005F18F43F97BE04FD6C3991BF0EFA65B1FA +:10B34000220B8FE5F073303E4B71486578367CAF49 +:10B35000E5A8B107D43BA3742C19C7DBFC0DC1CC05 +:10B360001A2D617BA5FF8A9D26E656C603FFAFD83E +:10B37000F48D91613F3AE6ED35AC7D3D6395E9880A +:10B38000870A162EAD84F284D19BFF2E7E07BEBBAA +:10B3900019BE53B206DAA7AAFAAB3FF937968EED7B +:10B3A0008DFEE7F1F8DFC58C65412116853B42181B +:10B3B0009B8938CC693FFF855F553FFE81AABF0C52 +:10B3C0002934EA7830FC63081B7245F4BFCFD603FA +:10B3D00092BAB77FFFFB2AE7E31F18F06D27E1B1B0 +:10B3E000CCE07A09F154F6A5C9EA043C96BD76C9C9 +:10B3F000A88B422A326F7257C64E6FDDF3C57D307F +:10B400009FD37586A831F4555B9810E3C77BE9B6E6 +:10B410006FF2D7417B03E03D08E839B7FE7BA30E0E +:10B42000DAC7E631AF09C67F3ACACED800C49BE17D +:10B430006B8F0A6F79F0DC1342E3E8A98BC5D2DD8C +:10B44000934139378A59DDF0FEDC16D12A21BE98A6 +:10B45000779925A4FDFB15754703E8A2AD67CC6B72 +:10B46000B4E377EB7F735E0C53E35DFFB5478577FD +:10B4700005CF81789D8A78EDEFC7EB2596160E9F54 +:10B4800061A75E99D3C791D61EBF0A5ECF563164BD +:10B4900072FFF33E12E159DA091FEA06750D72C90F +:10B4A000D8174C85C7D9AF9E21FEFD67779189C01B +:10B4B000377337FDB00CF90AD0EA3501FFCE759D20 +:10B4C0002778A9CDEC650437160AE91DCD5B8BCF33 +:10B4D000C0FA78446AB49FFE86C5CC190AFD7A7713 +:10B4E00089AE8D30B47392372C02E6B734883D6054 +:10B4F00087F29C4586BB2A307B601A8CF39C33DD37 +:10B50000E2C4F782D8E43AA0CF39BB37AC6B887F6E +:10B51000DE471AC43009DA7B5CACA02EA43D1F3292 +:10B520005643DFF7B0CEEAAB491E4689975FF7C0B6 +:10B53000F72E38F5CC04DFF3547FFFBA07CA637ADD +:10B54000B305F134A3FA9E30A683EF3724DE351914 +:10B55000DA3DB80FF047D3B319BB037EA7F3A9B305 +:10B560006F99F3E95C989F189AB9F75D78BF04105A +:10B570002B02BFCE58A5C5CF6C660F77C7A3DC1AC8 +:10B58000FC7C42FF7519DDF0DE4C4748E54AF86E59 +:10B59000E97A6DFDEC86D3C45FB303F8CB81FCD5AB +:10B5A000BD3D7FBDA2C8ED403610F96B9418A24393 +:10B5B0007E3ED724BA4CF0CE852506B60CE00B5B58 +:10B5C0000517837E2E3440238477729839A3896FC0 +:10B5D000153E57F0D68AFCD7B73D3EDBEAB71F1AB7 +:10B5E000FC1834297BEBEFE9EBA06C7DEBCB947777 +:10B5F00011DEF1D7B8BFB3F6EDF376FF3095C6B5DF +:10B60000DBC4705CE7767F14F718C2EF98ACC8B75C +:10B61000E7169B6C0CF5DDEE505732D6F7067E0030 +:10B62000BAD7ECFA3E1DF53D634B888E9F4B462AF8 +:10B630002F34FCEBB080F3683049388F8ADD80040A +:10B6400078BFE29D2017C3F7777D3FD811F2F3CD85 +:10B6500067AE9139883F43D9E46DC8BF5D990DE766 +:10B6600053F16ECE8BD5F0FDF2FA46E374A8CF7B92 +:10B67000EFC774D447E7B6351A515F9D35785E60E1 +:10B6800056E4DFFB6B0D80E7B3A1D0590FC61EDD7A +:10B69000F0BCDD19D2115E381ECE011E705E80979F +:10B6A00052575AE7F8F8FEBF161FE7A7E2F7CB1A82 +:10B6B0008630315E8D17C1C69F87BACC02CD9F3FC1 +:10B6C000DFFD7D3A0BB9F67CA3E38D24EFFF7F9974 +:10B6D0006F46FC7F2B7D39BFBF2B4934BE40BE6F08 +:10B6E000CFD73B1E21F8F5502B8DF73AE57DE27F51 +:10B6F000EDFCFF6FE83DEFBF76BED7A2F73E99DEC7 +:10B70000A11613EAAD5D3FC6B11B9877EDFF47E781 +:10B71000DDE6FFE8ACE64C18DFDF98EBEEE10279FE +:10B72000251DFA23BBE2B5EB8E71B25F51C3BE1E7D +:10B73000390DBEEB047F02FDFD9A90AFF52D003769 +:10B74000839F80FE0543E704F0D05C38D0B512ED4E +:10B75000B6BE925900367C319DE0C9C53FE833A1A1 +:10B76000FDDDE0E761FBFDD59E19D550BFBFAB4EB7 +:10B77000AA01F82EDBC4E47A802D3D440BAE636A47 +:10B780006C19664935BEBBB2B5EB91FB02D615F715 +:10B790004CD6D64F621BA3F5D0DFA4520373C194DD +:10B7A000EE0E68BF2EDE42F8BA87552EB584DC381F +:10B7B0009E4ECB78AA61839A24C48B4DB46E66EDFD +:10B7C000F1C6106F8897D80CB6D28A5FF1E85B009B +:10B7D00036C9FE15FC913CDE1D657E09F16462F3FD +:10B7E000D923D0DF25495F89ED4D0CD68D7CDCB4A3 +:10B7F000DE0CC41B93D79F26990477D91E628867F5 +:10B800007CDE2756F33ECD3B10CF378ED7C5C94FD0 +:10B81000235E0B43AD2EE40BDB8BD17AF85E0DE09B +:10B820005910FCF854F0148877F43969FD27E35B6C +:10B8300029D398772AFA9D612CCCBA12FA0F33F7E4 +:10B84000627A3E0FAFA93B161686EB357104AB5BEF +:10B8500009EB3596AD6F6D9B5702D5BB1F83F76A19 +:10B86000E6C1FB88D75E4CB213FF1759707D2330B9 +:10B8700007BB12ECF73F3FCD06FF339E4AE2DB4F9A +:10B8800037717FF352EE9BCB0682283198B3733029 +:10B89000FAB9F29FD35384EF894C67C5F52FB3D91A +:10B8A00024CB60EC97D1BA263C5BA759FF76B575DF +:10B8B000D1E02DB220420347DB7B68DA779B9CA066 +:10B8C000A9EFEEB84953DFB3749006EE5D3954D357 +:10B8D000BECFC2111A38DE7987A67DE2F2091A3886 +:10B8E000B9F63E4DFBBE6B8B35F5FD5CB335F5FD12 +:10B8F000B7CCD7C003EA7EA9697FF3CEC59AFA8197 +:10B90000EE959AFA8CA627357056F3739AF6430E85 +:10B910006ED4D4E7785ED1D40FFB769B06BEC5FB10 +:10B920008EA6FD6DBEF735F070F6B1A67D9EF9339B +:10B930000D3CCAF2774DFBDB638F06C43B2CCE87F0 +:10B9400032518D013F819C8D964E6BDA83C75C84AA +:10B950007C6390F9E1CED4EF34F563ADFFD2F467A8 +:10B960006495400464AB5A2ABBB03A2A43583395D5 +:10B97000BF1EE0B027A05CBCE05C864CB53FE7FB97 +:10B9800038B4239FE63EE444BEBB14CB2CE24018FF +:10B990000FF3EA91AF75C1977B395471A3309FC8FB +:10B9A000DC19C0873E814A8B2F98B923810F7D41D6 +:10B9B0005446F822E979A4AF2B9551BE9EF43CDAA7 +:10B9C000D79DCA185F2295DD7CF154C6FAFA53D987 +:10B9D000DDD78FCA1EBE0C7AAFA76F2095BD7CC382 +:10B9E000E8796F5F0E9571BE3C7ADEC7379C4AC915 +:10B9F000772795F1BED15426F82652BB44DF782A2A +:10BA0000937C53E879B2EF5E2A537CD3A9ECEB9B8D +:10BA10004665AA6F0E95FD7CB3A8BCC9F710BDD7CB +:10BA2000DF378FCA34DF63F47C80EF512AD37D3552 +:10BA300054DEECABA6D2EAFB0DB51BE85B41E5207A +:10BA4000DF53F43CC3B79ACA4CDF3A7A9EE57B9643 +:10BA5000CAC1BE17A91CE2DB4065B6EF552A737C4C +:10BA60002F5339D4F726BD37CCF70695B9BE77E901 +:10BA7000F92DBEB7A9BCD5B7879EDFE66BA4D2E689 +:10BA8000FB989E0FF7EDA37284EF337A9EE73B405D +:10BA9000E548DFDFE9F928DF9754E6FB8E5279BBF2 +:10BAA000EF089505BED3548EF69DA4F20EDF77F411 +:10BAB000DE9DBEF3548EF1FD8B9E8FF5FD40655BE0 +:10BAC0003C21D710A017DBF49FEE0AC67942223A38 +:10BAD0008CB7B5BD2FEBE3D5C12F308C7B8CAB146D +:10BAE000689DFE4CF0D90F484FE69824849762D3A6 +:10BAF000EEFC3B9618C6EEC77F488C35E69868FD8D +:10BB0000BEFF57FCBD65C38F7EF510DAC779268668 +:10BB1000F63150FF2ADFFD347B4F34FA61CB0679D2 +:10BB2000CA30FEF244BCA708CB860481ECC59B72E8 +:10BB3000F94E828ECA3503B8FD2E9A971C4E71AA13 +:10BB4000A8EB9BD7FFA2DD8FF6B77F2189F7C34211 +:10BB5000BC71642FAEB39FEB6DB7D4FCEB3F605C60 +:10BB6000C756A36741B702ACE7F6DEF955A86B33B9 +:10BB70004CC939A2F28F18E7712E36596AA210CF3C +:10BB8000BFFE13B65FC898DD04E51F121C9F254059 +:10BB90003FDF07C5B9C038C25FE59009A13F6BFF21 +:10BBA000FFF83FEEFF34EAB5CEFAFF87CC476312C9 +:10BBB000EDE7701C4C6F4B473A8C58DC5D8C82F77C +:10BBC000A7AD122CC847D3970CCC47FE18C46C14F1 +:10BBD00027BD3F923D60EFC02FEB96A893FD0BC9A8 +:10BBE000780F8CE70CB81CE84F144B8CF8B2B841B6 +:10BBF0007039290E6D0B1B0BF6BB54E6DBE2E5D565 +:10BC0000C605D0AEBC3B8F9731178F9799E17F283F +:10BC100047736A37ECA570A37899E26397D0EF0574 +:10BC2000D699B3A57D3C7601C699771A2D6837CA97 +:10BC3000EB02E2B90171B3C0789925518EC75A99C8 +:10BC400095C7B9434AFE8ADF63619218756DBC28B7 +:10BC5000F1598949DD108FA3C4B4705CC75C684A90 +:10BC60000E67584A52376CE7005A344329E81D439F +:10BC7000F039E0D38974F55607BB36C2B88E803DE3 +:10BC8000913270408E21468C47FEAD375B2910D52E +:10BC9000C80FABD824925FEF59FCAF6518C79E154B +:10BCA000AFA775C0348CB9E3F8DEEEEA720AD42F80 +:10BCB000E1DDFB9A407157279B1F8B71DDC07D141E +:10BCC000FBD2E871D948A7E55D079990564EDB177E +:10BCD00049312AFA2CA921BC16C74672FAEC3490D5 +:10BCE0005F0BF4A946FACC72198EA9F17C895D36F6 +:10BCF000E27E4CF1F2F344AFD97E7A69DA95D73619 +:10BD0000125D814E9AE71595279438FAB1ABD12B85 +:10BD10003F805E183FBF072B1745927E285AEC4E96 +:10BD2000AE54F169E0BE44D28CA1E1769087821EC8 +:10BD30009C1E4C6F8D417A7EB72A8BE81548A782EE +:10BD40009FA6133DD8DF42D96618CFFD89EC810943 +:10BD5000F0FC0139FE7A7FCDE8028C974F4DE4EB81 +:10BD6000934F61FD6983F5E7812A33B3816AFEACA5 +:10BD7000CA42F0E755B104FFB54AA2F2CBAA542A51 +:10BD80008F1959699D4ABE80018C38BE192857D138 +:10BD9000582AEBC3876331EE5EF0D367593A52A954 +:10BDA0006F8E1FD51BD7178004157E261706932F7D +:10BDB000ADC01E83253F16F5C70AC1BA19E96A1F2F +:10BDC000A669CF5233FC30DA2F3DE727E08B8DC8D0 +:10BDD0007FF78E89D4B49FB4BCA7065E9428D1F8AF +:10BDE000C617246A9EDF57D45F034FF3C17A1E3E05 +:10BDF000952415E89CD0FFC54F0CC4CF172B877432 +:10BE00005BC061E2BB40FC1F333A298EE0DC68B2C4 +:10BE1000A2FEFB3688F3F7B79F8BAE1A5AF73A2982 +:10BE2000EE72C96C91709DF2C874671CD63F120CFB +:10BE30002EF940C497C8307EC05E3191FE9CBE563C +:10BE4000604E94112FA3F5F2C32F9B689E33D68AC0 +:10BE5000CC91417C1287ED1F8E96A8BFFB13A53AAB +:10BE6000E467EF66937523D44EF7C8EF0B83681F22 +:10BE7000A47CFE5F0FEB511E529AD371AD5514EFA7 +:10BE80008E463DD8BAC940FB5EE5E286921020D1CD +:10BE90009C27DE0CCB9148FC08BFA70E446FC0F96D +:10BEA000FBE7EBA2B8C8377DEC1B13419F9E2A71BC +:10BEB000A5D33A79118FC7B7C70B233DE5D4854980 +:10BEC0009B71BED31D432C696A7BC8F7FDA61BACD2 +:10BED00031D634E4FECCEEA8078EAD321460DC051A +:10BEE000F4FE38C4D3B1DA48DD4A5A546D23FE2A31 +:10BEF000D64B46F5778B5789366A0FFA7D3CDAEBDD +:10BF0000D5A2830D41B896FA772E171CB8EF94C4CA +:10BF1000B2BB21DF3E346F48379CC7D44EF619CFF1 +:10BF200082CC3854FB58B3778976177E2FD3A32F52 +:10BF30001CA01E3F8F03253996F79A8F747A23C869 +:10BF4000BA5242BD9A188EEBD4932D6037E01BB3E2 +:10BF50006A1AD32560BDB28776101D4AC7D5A5B829 +:10BF6000E1F901B3E313C4E3B7DDEB9E1E8671A2D2 +:10BF70008617E39C680717F2FDB5D9AFCCEAA3F6A4 +:10BF8000E7DBFB132C56978D853B4600BC38249687 +:10BF90008FF89DC2EAE4F8858BC627A1D2057C58AC +:10BFA000CAF8FEDB749D75EA679988FE500BD2458E +:10BFB000E9EFA881C7B9FE21CBB362877B24713F2B +:10BFC0006BBA8ECB1DDB2D109F02C1BE4852D9CB60 +:10BFD0000AB68AEC656C4F91E1BEDDD9C408592FD1 +:10BFE00070FB3707ED1FEE0B5B04928FB22D269787 +:10BFF0000BF82B3589CBE76CE36B4F0FC2E6F1955D +:10C0000046FCCEAC7A813D074D4F195C25CDB82F4B +:10C0100065D9B02482DE33585DC8A7B27E3783422B +:10C0200040BD3013FF09F5E56B04979BF8C54E76CC +:10C030006806C64D70FD8F7A5EA547DAE9F700BD48 +:10C04000FE200BD8D7AFD5DA177B70A819C7397B7C +:10C050000DF76BFDE311D915C05589C3B5771C8D5C +:10C0600057A0B848E0F767E2F870BC303EB7F5C6B5 +:10C07000C75362E5725A562BB85C1D8C4FC16B7862 +:10C080002E93D03ECFD924B8901F4745CD23FCCE68 +:10C0900006FC46225E9DF6B07B002E014672517C66 +:10C0A00085E3BF623DC73FD0F92F6ABBFB4D94D7F4 +:10C0B0008878FD06ECA713F7032BBF27BAEF05FA24 +:10C0C000A2FCCE7AC365C48DC8D3AC362C04F97EED +:10C0D000ED81BDB82CF866CD9B31B87E2D8A7027D6 +:10C0E000EB406F45B2E8270B6EF1F35FA0BD6E67C2 +:10C0F0009703F0E36476B243EDF0645ED58CFBDE2B +:10C10000EDE827C7C51EC47F017E1EDC24DA82D27B +:10C1100035EDE4F3084EC25BA9D34B7E4229CCB384 +:10C12000C6824F9DF9889707AD8CF4EE8D8E3770DF +:10C130009C4C2C22FEC4B81EFA21FFEE7803FD8F22 +:10C14000494957F73F02F548A0FFF195C1A65B8C1E +:10C150007EDF01BE2F7E51EFEE8DF27B312AC10AC8 +:10C160002DFC7A347A5037D4F38A1E2D91ED96D275 +:10C17000EF8368AF003EBEF6CD30A4BB42FF9968A6 +:10C1800027D2FC76E291E9D03F7CEF911D41D4FFAC +:10C1900099B160A7A0CFA2E73F0A632AFDF7781FF5 +:10C1A000C7FC24D4278A5D1337C45980BF147D7916 +:10C1B000AD7557A7F30A099857A8765EC538AF0C36 +:10C1C0007F7FD3E5797DBD9CCFE7E82A3EBF19ED9F +:10C1D000E6C5EDFE232F9AAC4EF20BDCD12887DFAB +:10C1E000BE21B21AA22FF71B2E99819F0662FC6610 +:10C1F00015D9F593D14CC2B84EA7F67BB589FC8210 +:10C2000059DBF97EEB29617837DAF8FFC01DF62893 +:10C21000CAF53691A11DF28FA7CD6E3F9BA4B6DB68 +:10C22000D789378CB3A23D9B0BA843BE9FDBD08D33 +:10C23000E1399755C3599D48FBF01ED263C04214A3 +:10C240009F063F5C136F3031ABD98C74EA24FEFA41 +:10C25000CFE4F353E7133EBC29887FE5FB155DDC93 +:10C26000866EE8D7BC21905F53FEF0F0B0E10CBFC2 +:10C27000C3E3663B92B89D7A07F51CCC4BB0555290 +:10C280005C0C7C1ACBEF705CEB797C98BDCFEA102C +:10C29000BF0853FC58C7E7214816563488C7E5CD78 +:10C2A00068D7427464D702F17042FE4EB9A823FFEA +:10C2B000B7CCC8FDE073023FFFF1916C1F3F4AE22B +:10C2C000EBCC4F92783CE11CFA81D0EFB95B4CAEDD +:10C2D0006A01DD563DAD93F5B92617FA337A7388B6 +:10C2E0005B4C47F4EACFB6C933E06B2A6B36203D8E +:10C2F000C765CFDB82F339DC8359C4AE546DC77D8B +:10C300008429A41918DB6FF8EA438C473AA1AD08D9 +:10C310006B8529D9277A63FBF508C3FC0F07D57D08 +:10C32000887196C3F17A86FB02CE5D26B2FF861134 +:10C330009EDE14A7ECC258CD408CC7EC598A7CB461 +:10C34000373632D502ED1FD077B18A5CFF8C3C8F37 +:10C35000E32D15F8FECD124F16D2E766B6C472DC97 +:10C360004C5B0BF55722AFC63F7A765CE10318535E +:10C37000D908F8C750C6192B9BF0A98101AF045FFB +:10C38000DEF4C88435B9B869220D403A972578F5AE +:10C39000B89FE215987723E0E1EE6CAFDE86F4B249 +:10C3A000B1BABB807FDDFB9880DF4111C0EFDEE3D7 +:10C3B0004E18857860A9120B87FABBF412C1BD0A2A +:10C3C000588428EF1B601CEBE03081E8A0334B065B +:10C3D0009CB7BD401884FBA2658BAF6F9C61C9D52B +:10C3E00034CE329D8EAF671FE5EBD929CE23A3C88B +:10C3F0004FCA6502F26145449D81D6D1202F38FE97 +:10C4000081D08D1A7F53F41E3EBE52185F0ECA456E +:10C4100012F1F17D9502F99315C68EE31A3D9295BE +:10C42000759745C2F673E05FC8D7731A7624E3F7B1 +:10C4300056099C0FE6287CB6552B97B9C9ECAA7C07 +:10C440009D93CCF93A2799F37572DBF7EAC8EECEE3 +:10C4500069F8E820AE2B3BEBBFDCC4DC84975D269B +:10C460008A1F083A6F12D1051109749882FE24B808 +:10C4700088439223B89F2EF36709FA1F8958F2B8B0 +:10C48000880E9427DAC3D2DA178D88B4C0F347E058 +:10C49000F8D039A0D99B029FABE22AA246EF50DC2C +:10C4A00053307A67E078845B83ACA88FA718EB6879 +:10C4B0005D1ED8CE50CBFD2CC372EE67D1BE1AC024 +:10C4C000A655DCCF9CD2CB3B80919EB3E40BF1AC64 +:10C4D000CD2F2EE19F86E7651ABFD88471048C7B2F +:10C4E000ADE5FEA05EF65F8B5769FD85294B54FED6 +:10C4F0002275EB2DC7F11A160553DCC584FE84CADC +:10C500000FF8876EBC13F5B033414FE72F0D2CD0D9 +:10C510009FB0331ECFE4CFF5B29F383AD9A0D97F70 +:10C52000738E60A9888722D44389A86AECCB319E98 +:10C53000778185D662DC6C94B888E27F45D5FC5C57 +:10C540005A60FCEF42E587CF637BACC7E70BBAFCD0 +:10C550001487FB9BB02CB50BB782BFD1E5F0250744 +:10C56000CA07282AC3508C03EEFF06614117CE8408 +:10C570006CFCBEFB79ECDF69345B506F3D131C46ED +:10C58000FD2C5C28507C788985CBDBA1AF4237A29B +:10C590009E52E2BDCB8667ACC5734B359B1B27987B +:10C5A0007BA37A60746E8939F7FEC506F329BC0C4B +:10C5B0007243F047136CE1C0E71F7AA79A014FCF8F +:10C5C00026374DD0839C9CFBBDF705845F4D3EC054 +:10C5D000E127BC7141086FFE9CC3D54A7F9F4FC0C5 +:10C5E000FECE3DCBE1E550EF84EF17A17EC3790F7E +:10C5F0001568DDFF8AEC7F2BF19E22DDFBBC1CC1A0 +:10C60000DC683FAFD5AE3ED9FE0AFA3B62E8B150D6 +:10C61000F42FDEEE6B7B05EDF78E44FB53C948AF7C +:10C6200016574C34C6B174AC19E90276CCD6D1BEDB +:10C63000F42B493C4EF3568A9DDE57F005FDACFFC6 +:10C6400077FA1999C2C7A5EA67F3BFD34F78DF76A7 +:10C65000E3793D39FAC6FB9917D08FE2B781032CF5 +:10C66000A19EF2A6DAF6E1F8E6FCDA36A21EF5CFD4 +:10C670007E91F8F4BBCA1D2968F7BFDB6A8A44FBC8 +:10C6800037E7F5B7E34A308E20FB45A71BBF344A96 +:10C69000F0FE5C9FC86CA0A72B7C029573EB1B8DF2 +:10C6A000F96978AEB6D198A71A57993C4EE074FD57 +:10C6B00004951FB33F5927EBCDD554CE79FDA41E69 +:10C6C000E9394757771CCF1FB3A13CEE1538BF1D82 +:10C6D000B2DE3D8CE70D3A8803B4C8FAB9777FDB48 +:10C6E0006788B7B7509F030CE6CAD111BE7AA5F090 +:10C6F000711475E17A3EABC55AF219ADFBD27522C1 +:10C7000094830F561A8BE1F9C1C41187105FEDE3D2 +:10C71000905E1E876CE071C8A288E687C198B16EF2 +:10C720002F5D7CD20CEBB83B9F91E503450FF44B9A +:10C7300081499197E0892373799C0BE1FF4D363C49 +:10C7400085E7089BBA34FFE233B40F2B42D94690F9 +:10C75000B3FB8784C66D83714C77860B603BD970C1 +:10C760005368CA3468D79A30BC5B0AE92746FE6131 +:10C770006B82FD02CED7131FAC036784398C3C9EBD +:10C78000E5F8B348F12C477AB0C3D501BEBC323EC0 +:10C79000BBA5F0FD9D261D8C73108E839FEF85BF7A +:10C7A000B86D186F5ADC4740BE53BE3F2671788C77 +:10C7B000FAFB6312ED624AB4BA7D38C3F6D73B0E7A +:10C7C00096C2C71193C2E965CF05FE52E9FD092360 +:10C7D000833570E198486653AFEF0A7B6AE0C9453C +:10C7E000899AF6F7CDE8AFA91F6B6ACEACBC017F82 +:10C7F0005F0C4B0DA7F57F165F871C6AB8F4C51454 +:10C80000F46337895601E6356BD7E62F8651EF1270 +:10C81000C5B94E3589648FC0BD35AAF74FCEB06615 +:10C820003A77ACEFBA84ECDF9C587EBE7B964BBB6C +:10C83000FFA1C4E53BDA37417B5686E7623ADA3737 +:10C84000F1C7E3AFBA7F929D22AF8707B1417C3D2C +:10C85000DCBA1766CAF2763612BD6AF6895664D516 +:10C860009ADE0213609CB7D79B5C4130EE336F1F9A +:10C87000314AAAFD930A5F35062DE0BD23463C4FA1 +:10C8800075305922FACD6D386F64C017B737CC2395 +:10C89000B96E6E744445A3FD027F757B26F2575D29 +:10C8A00026DABF269DC58EFB6173968FA63873B8B6 +:10C8B0006F0A9565B5A3A9DF72DF4482E7FA8209A2 +:10C8C000FE546CAE3F80FD3C136E417B5EAE776ED6 +:10C8D00045BA944BC119B85F35B7FEC0C55FA21DFC +:10C8E000B5F07B1D63C5BF6462FDD83E165D4D5734 +:10C8F0001C6F10F5D33CE2EF9968970A705D00CF8A +:10C90000CBB6E53850EE87D7845A50EE453C4FD62B +:10C91000019FCE48E1FE9EC1C3C73BCA379EFA5372 +:10C92000EA67A72450BD021BA237E9517F28F330E4 +:10C9300080C1C7F20E5F7F2A2BEAC7EBF15CFC9F38 +:10C94000535F8C423C41FB102C93460E233DF35D1C +:10C95000E59070D681DE524A93AC87A7A01E86FE72 +:10C96000EE4DB555A11C8E5BE4D19B518F86982D61 +:10C97000B8FF312E7BA054A29A8FF8FEBDB892006A +:10C980005FC56B40BB3D054AB5DE7EA013FBB234EC +:10C9900045D1DBD54467C50EB12D4F325C874DE5DF +:10C9A00067B5DAE46ABE2CD7CAFBCD02F7079CDB79 +:10C9B000795C7F7EAA632DEA91E6E16CF236D2A71C +:10C9C000CD71E3437FBEF187E99B89CE611649872C +:10C9D000FB0A4AFDF36DF3E0F27DAD79AC94DB7FA9 +:10C9E0002AB285C8179FDE765BB30DFA6D7C2C23C7 +:10C9F0004354D9A9D753F8F94766F15E267DB13B78 +:10CA000058423D3016F71E32FD7E3F9E87C4B84621 +:10CA1000C56ED3463C0F561106EB7CF8FEF8FE8E31 +:10CA2000D7917E8DEFE55CC47B34365C98819CDBCE +:10CA30001A865CC473F63633681B2BFA41B63F91F5 +:10CA4000BEED64BCD7D2674923E744A13FF11D0C7A +:10CA500009ED2DD8FDCC160EDB115F8EE55CFE1CBA +:10CA6000B21C4E93F9B75896C3697A2E870FAC095A +:10CA7000B760BCB378913000CFCB3129D48A2AC0BB +:10CA8000807C9981FCC9F9B2CCD75596E778B91F5B +:10CA9000CEFF81F239D71749ED1439FD53AAE310BF +:10CAA000B72BCD990B615C77805CA3DE732CEE9E77 +:10CAB0008972E2E713A305F909F824B644C50735DE +:10CAC0008D3FE8914F0CB902F18909CA3C151FD975 +:10CAD000DBFC134B7E0CFA554BE2752B99BFFEEB3A +:10CAE00014659FFCFAF8FD53B97D7108F81114FF25 +:10CAF0000963185FBB1025519C74FE0A1824A060BE +:10CB0000BEC19D8C7198F9F382280E56D252B92C71 +:10CB1000546A4FAF7B7DE9B4BF3CD19744E5C14433 +:10CB20008717E5659A6F928CC7F4EBDA9FCBB2F169 +:10CB3000B89BC165B26E88C7B89B43A4FDB8DECC74 +:10CB4000F214D929653F8EC7DD309E87F1BDC0FD47 +:10CB5000358CC3E17ADA14A5D3EC13B68BC70DD7A5 +:10CB6000EEA79535FE65B00EEA4FC5DB282EF74DD2 +:10CB70001F47505F98C7EC09AED70DEA7D36198F75 +:10CB8000757A7732DAD1BA4A8E9FBA556201ED379B +:10CB900031163C5E755EF75A7C3CDB9748F851ECE9 +:10CBA0008BA2B77754D1A1CF36FD7D2DBB532EF389 +:10CBB0007B39F2BBB5BD9D51F835909F15FD6C8852 +:10CBC0006E213D7407BC82FE83A2AF0BF286E5A204 +:10CBD0009D1FF67262FD3B30FFD854470EE2E5B66A +:10CBE000577B67AE03F80EBD4B6F09B91E7DF88306 +:10CBF00081F4E1A2F18CF421946A7D68E8C40FBF4E +:10CC0000B5EF8DF1779ADC1EFC58EE1F82BE56F709 +:10CC1000373F75C4F8BED074525F6E277FAE717710 +:10CC2000A6C727F5BD313D9E278FFF5A7A7C565FF8 +:10CC3000AEC703F5366863D2DBE776F5A338D96172 +:10CC4000067A1EED5943B0B4395E75CEBD4BB84B74 +:10CC5000ADD77BF79F3E0BE97A1D7A7D36B6FB7721 +:10CC6000F57AFEF837C8AF823FFB5DB7C2FAE3370B +:10CC7000B0BE43F85358DFC5B79787403908E47B07 +:10CC8000588FD41F80F1353DDD87E20E2007C4F7B1 +:10CC9000E5C0F728078ABCCCAD1F188EFB06EC1345 +:10CCA00091A1FE0F948382BC57F518A7423D8EF8E0 +:10CCB000DA03328F7A26D04EFCD8D7F12CF28F22AD +:10CCC0000F8A1C5C9B8FDE36E0BAD450769EEB79DF +:10CCD00028D57ABE337FE6851BE4FF55D7C93F6F61 +:10CCE000FCFCFCF3C675F2CFB6FF847F9246BE4BC8 +:10CCF000FC83FA13D76F777E6C0D5FC0F987CE2562 +:10CD0000023F6462DCB969706F2BC669EEBCC2FD7C +:10CD10007AD0E9E4D707FAD55364FDF7801C2738A9 +:10CD2000986AFFBC2F9757F2DB8727060F447B7565 +:10CD3000BDFEDE94A84A6683E70F40A9D61326A459 +:10CD40005B07FEFADF6E90BE4DD749DFD37DFF63F0 +:10CD50003FEF52DFEBF0F3926CE68988CFEFDC7A9D +:10CD60008678BAD67AC0B096E3B9CD5F77EB15BBBB +:10CD700019897613F8E39FFF097F8CCDABBB68065A +:10CD8000BA466D3116EAA1FD243C6B41F10CD31A71 +:10CD90005B12EA1BA6EC0B50BCE35351869DE69652 +:10CDA00091308E3B9F62FE7D03A81F951BDE161FF0 +:10CDB0001198BF7DE41643CB2A8A3FF0F32ACCE1D9 +:10CDC000D1F37D3219CE043854056707C0EB79FBE7 +:10CDD00030BD87F1731FF27359FF8CB3F07D01FFF3 +:10CDE0007E9E37BF2BFA7FF58205F717EECB3D67A6 +:10CDF000C478CED83CCFDE9ED02E654B7861483FBC +:10CE0000785E2FD07807A7765BE34CA2235B363C95 +:10CE10006F5896CDF74D4C758DF9B60EF87070AA17 +:10CE2000D64EE19F3E86E263F467AA13983193F7EA +:10CE300093107F7DEF23FDE8FD047ADF6D8ABAFE53 +:10CE4000F7EFC9653657077C345269877161A57F52 +:10CE5000A0C9C43AC1D651DC664C2A9797669DAEEC +:10CE60009C019E0A53FBAFC1B8D728C6F96252EAAB +:10CE70004D854E1E4762B680F95E6DBC433B98AF50 +:10CE8000A47DDF7D357CD95215B957DE97E95FAABD +:10CE9000E59370BDFD83EF601CE1518205FDD4B9BF +:10CEA000F6A0552C1CE92EF335CB2AB4E5C2FC8242 +:10CEB00098268ED7C6D76C70E1C834F9DE3ED567A8 +:10CEC000AF41FADB756DED399F37086DEFA7EA19B1 +:10CED0007E82DEAF4C1DB206E37E400FAA2738E902 +:10CEE0002A7C5E1700E706C805E330C925EA65C05D +:10CEF0004F7207FBB74FC8F83D23F0F34DCD23B871 +:10CF00003FD79CC0CBADA9DC7F5B23E371BDDCBE0A +:10CF1000B98B0A0FBDFC74863F37AE0754F3263C2D +:10CF2000DD1BA5CC7B52E118985773041B20009F92 +:10CF3000BC943A61CD92DEFEF7B7A44E223EF1F7E3 +:10CF400057D88276FC5E194F5B53EF6EC17A3C7204 +:10CF500082F2569ECDF75F4DF5073A94B705EDF98D +:10CF6000C789F915CA8991F03DC166C8E4FD2474EA +:10CF7000809F5FB57FDF16F03E3344DDC8FB327D16 +:10CF8000C604D0AF20807E2303E0222DECF783A1DE +:10CF900067F09F8A77AE5E1A83F1B32D02DDB1028E +:10CFA000FD6C14E079E396070A43703D2A4A869E99 +:10CFB000D0F6C32DD35ACCA0BFC6A3FE227D5C4CB5 +:10CFC000FA7A22CA39C1D30B6D3723DF542E8D85EF +:10CFD000F61F6F99B106EFBDDEB764B50191FEE9AA +:10CFE0009692357AE8F7DECC3FEDC5FEF4D5A52D57 +:10CFF0006384ABF0696DC03CD607C0CE80F66BAEE3 +:10D00000A1CF9704BCBF28A07E5500BC36005EAE01 +:10D010007D7FDA0CBE7F390DE88788BB96BC7C9398 +:10D02000DAE617B4D92F01EDD9C75A7EBFB386C34C +:10D0300067531F295C1EA282B72C2854F3AF41B658 +:10D040001753A2ECB68EF8F75067FC931A68D79C7A +:10D050009A73898719D3D8DF3DA2166E1495F12EE5 +:10D060006D79384DB51FC89614E23E51E7FB158B1C +:10D070000B71BFE2CEDF29F58B0B6DAAF929EDF319 +:10D080007FBC22E2F7F42F57176EA2FD3F79FF2EE7 +:10D090008297B75DBE128674C9C7F3A358DFC59DDA +:10D0A0003C5F6DE7595D0ACEAFF1317EDFD05903A9 +:10D0B000F400392F6656DAFF6E0C0F5FF812B4DFFA +:10D0C000F398B810EDD7E1859174DEA8B01FF7C7CB +:10D0D000F684F7897910E0C6E0078C18576D7C7CE0 +:10D0E0001495EF8BB6655E407EFCCBB564C71B83A1 +:10D0F000C3092FBDFBAD2AC42D59A99F44787444A0 +:10D10000586276A21FBAD2C070FF8931EB0BC427D8 +:10D110004F98C84F9D56DD9FF67B8A7F3F3EBF3BB1 +:10D12000B42B5E6AA0F83FFCD17D0CC7CA5146AC57 +:10D130009FB1442E9DB753F9DE4F6F7E9C4EFB3A54 +:10D14000229DDBD9ED8B380E92CCBE760EA0FB0A69 +:10D1500047E5FC2A6FF773A4F583797CDD9A44F9DF +:10D160005298450A9B807EDB4DB601FDA2FDEDDEA7 +:10D17000FB49A4FDAA775B8B63906E43FA717ED95D +:10D18000ED2B8E2956D9F592337AC2F37B46E961AD +:10D19000D41BEF75E92D38496EEB2231CE3A43F6B8 +:10D1A0009B814F16BED9011F26F513A9DF63A68503 +:10D1B00078169635FE263A17C7A5BC97D5E2A8C1C2 +:10D1C0007C31865ED220B57F7C6BF2883C9C879F49 +:10D1D000BFFE48FA9CFC6380C7BDFCE21A27DABC9C +:10D1E0003DE0D7E338A26CF958AF9CC763B175290D +:10D1F000EAB882DF0F5D2CCB3F6F77080F07C3F7CC +:10D200000F6D0DA2735F879C7F0F55FBC78A7CCC87 +:10D210000CFBD5E1665A17874B421CF08DBEEAF82D +:10D22000A3F05EC9F306D29B25CF472FF2623DD013 +:10D2300013B70C03BFBBA51F3F0FD0B97CD407C8E1 +:10D2400047FD55E5A3F4E5370B378574241F5531A9 +:10D25000C847F9CF1BE87C755197CA4918472CD2AB +:10D26000DDCC6A607C239EFF450CEEB3CC7CDE44B3 +:10D2700074F584861EE7F3EA138FF36AB33FFDB8B3 +:10D28000BEF254E790BD1075E09D81FE16971968B7 +:10D290003D22C61849EF8961565EDF85C52F06BB62 +:10D2A000BC34345B42FA6E4679C8A27A09F92C2F55 +:10D2B0007CF21D78AEE5F0C244DA073B99C9F7C1AC +:10D2C000663DFA6218FA9F871EE6E7BB6763BE1DDC +:10D2D0005CE7FE9BFB5E1572BE9DFFAB7DAF67FA00 +:10D2E00005EE7BF173A07B16666472BC30C984784E +:10D2F0008A1B4878B9DDCCA420C08B18C15250FFDE +:10D3000028FB5EE22FB97E127502ADD38F55392905 +:10D310007F415E98993FFF25BFB7273E3D9ED13E96 +:10D32000585425ED8345C8789D26303BCACFD1207F +:10D330006BDCBC34E4BF20A2E7CC17667DF16C2621 +:10D34000D26D6C94269E80FC17ED7FFF44F52D3442 +:10D35000BE1302B3A0BDCFFB43DF91489F46D1F17E +:10D36000F4BDA4378369FF9C593C4F0C01786635A6 +:10D37000ACB319F24DF7B884347F3F33173F968230 +:10D38000F4CEFB43901BCFDFCC5812B416CF619480 +:10D3900035F07BDED3567C47E77159BCBE12E39C67 +:10D3A0005F2F09E2E7D4EB8710FF4CD3F1732E2CEB +:10D3B000CE48F1A5B21019EE954DB0EAFE9211E9F2 +:10D3C000A1DCBFF918F50A7CFFB4820FF41B51EF02 +:10D3D0002AE7E859A584F25FA4133A3CE7F5553FE4 +:10D3E000EE9F4E8BB3D279D1F2DF9AAC8BE3399DAD +:10D3F00045559EB9729D377F2DF6AB63D2760BAE45 +:10D400001F9A4B70BDCDEAFB521E820A3DD31B23EF +:10D41000E0B9C4F599329E0A69FCEDC44F7A7650A2 +:10D420001F81786CFEA219F96371A8847191F2AE24 +:10D430005607F51B6AB6703B217F17C79E887CE0B4 +:10D440003346201F7C21E84C3CFF804D07F5E71850 +:10D45000AF6FFBCE921569346FB34537A23BF2DD57 +:10D46000F9FCB5F0DEED4C4AE88EF7C456444E9A0E +:10D470008CF5AF89A49740987E9B8DFEDE6B62068B +:10D48000AE53A7ADD843F39BF3C640BC41C0A6BD85 +:10D49000FE19D9A739327F79E4736BC500BF01A5A6 +:10D4A000FE266E271C22ABAC2358D0EC572AF5E59C +:10D4B0002B0C448FF2A526A27379F55FA9DFF2D079 +:10D4C000E618A447F97603E5EF08BD49A2F6C5D5ED +:10D4D000BD730FC2B88B0DE116011E9539C71A1125 +:10D4E0002EAB150856BE57BEE2F3185D1AEF0F4B70 +:10D4F000938EEFB3FAFB8D8E437B767A6B64DC34CC +:10D5000015DD4F2FD91186FBCE4783DCC978CED7E6 +:10D510003B2FC88AE70A9578DAE925C9FC3E90A531 +:10D520003914F7AB673C9C188176EEB0C56DC4FA30 +:10D53000C375F178648ED92C965C846DFA9B093E94 +:10D540002D9F23A13FCC1F2870BE29DBBAC79800AE +:10D55000DF1B24E3E7CC6B47F70E457C001F5950D7 +:10D56000FFC435A7A01D2ED735A7F444FABC2290DE +:10D57000BF00EB531BE61F998B7C3508F4A1CC57F9 +:10D5800073EB772C40F92C7FEB643EE2F5CC5866C8 +:10D59000C4F858B93C7F583F7EA087F6E5DB36E4F7 +:10D5A00033FEFE07C8778ABD07788901E026238706 +:10D5B000336EE2FCD364F450DEBBA6498CD1FE99F5 +:10D5C0009E8DC47640797E0F4014E5FB6995B113BA +:10D5D00078DE3DA7FAFCDC5CAC4FF3D777C6378525 +:10D5E000325F14579BC82E15CA78F1ACD81E867CC2 +:10D5F00071E6B53D7B87A25C6C132C4C2D0F8A1C09 +:10D60000C679793DE0EF49C4DFB6F3F998876276D1 +:10D610006BA8843454F0A4C89B82970AC6F1A0E09A +:10D62000A5422FE349AEBF5BC64319F3527FAC75E9 +:10D6300080B419FB7FEB07DA6F3B338D09FC9C301C +:10D64000CF8BA6CCCF11A1DDDF5F26CF6FFA4DDCEB +:10D650006E9659B85D2C8B6252F540E2339B51C9EE +:10D660002F094DCEBC714433FEE7653968A337CE30 +:10D6700003C6E9D1F17B8281FAEB51197F47AAA752 +:10D68000B851AFCC76423F99280F96A9B8CFC95E62 +:10D690001765FD0D32A9FA6EDEAB47880F41774959 +:10D6A00011B066316C8171A0FFD5DA9BE28579DD1E +:10D6B0003C34EFCD632C4C07FAE488E009DD89F6B1 +:10D6C000E05191F494324E9BF363A287AD8ECB2749 +:10D6D000F20BC60715390D1CEF3279BC269DD58398 +:10D6E000E782D96281EEAF898BCF841EE4F68E2269 +:10D6F00089FEFE6FF900F7236D17C324816AAC7AA7 +:10D700006C37F7625802DAEF2372DCE1C8D21D6190 +:10D71000C52A3AACEBEC3BCB864848FFBC90838FE4 +:10D72000A11C3D759320F3BF75E442D40797C22432 +:10D730003C2FD514E14C433FAA49C796B308CE8786 +:10D74000FA183FFE405E087F502F3D65F1CBA532B1 +:10D750006EA09B1BE906ED6D5C8EACB48F31378AF1 +:10D76000EF8B5E5B9E323CA49FAA056963A6BF9DBA +:10D77000722FEF7179DE2423317E7B80FC89F6CE17 +:10D7800024E7310ACC837A7BAFAE7188BF8A10B3AD +:10D790000E977081F581B07F3D55A9473F9F2D8938 +:10D7A000DDABBE977634C849F7CFBCDD45B611E88E +:10D7B000513DEF237E9EB781DFDB52EC34FCAD6A36 +:10D7C000E33F78AF34F37C3EEAD73FE698E85E5318 +:10D7D0004C7F7EDEE514AB330E47FBFF6D737E9806 +:10D7E000E45F9FDC72D12D8693BF10AF591F94B5B3 +:10D7F0007E40F25CCE9AE93EF6B4159F8D1D82F410 +:10D800007ED940E70766D4C6939D3BB9697A06CEB8 +:10D8100077DAD26482676D7E90C32B78FEC3694B42 +:10D82000B35E42FFEB68902D1FF9D9BB5AB0E0FA06 +:10D830006AD8E6AC45F741FDB0D03E5D71DC873675 +:10D840001D1D8B743FB45024FD64DBF4D424ACB7AD +:10D85000ED14F1C618AC672C8B30AF29D3875BD0A1 +:10D860002F50CE17D618B8BE3D2FEB87936D25E706 +:10D87000D3BC9A9A14F497BC1BC01EE1BEB7D15B0F +:10D8800042E7BB058B7523F0CBB782936066B1246A +:10D8900054E7E07D96F5941FE75CB2C9827EF2FD05 +:10D8A000266645BFF6FEF77A0FC2A5824D5E578DFC +:10D8B0008DE4DF55F0A57CDF2BF33D135795D0BEEB +:10D8C00043A49480FAAD493E377E541EEFC9252FFC +:10D8D0004F42BFE0E496E408A6C2FB49394FD32C7F +:10D8E000D083DB3A58EFFD7893127770D1774AE511 +:10D8F00078E03E436D2FCCFB1978BFEBC486203314 +:10D90000E6E70DBCE775C2C0ED47BBFB5E3BB570FB +:10D91000609EDBC0F12865BBFBFFFD433AF4E315D5 +:10D92000390B7CBFDD7DF2A4EB3B5F8579C9F0BE8E +:10D9300077D34D8CC63932F8C737515F97D49A2CBC +:10D9400078FFFE589044EB2167169336A39D314B28 +:10D95000E1B89E3FB62F83CEFF957CC548AE4AEA1C +:10D960004517A62AFE6075DFDFE502FC60BDC18AAF +:10D97000EF9F5CB37A1217336D9E856CC6E57326F4 +:10D98000AC93DC16FFBA2870BD347BED1B748FF0AE +:10D99000E75A2F2971A4407CDFDA5FCE4FDAC9FD48 +:10D9A000B9F7806DB207B5C7776B9583D64567AB7E +:10D9B0004AA9CCA9DB90D753C2FB14477E3B0CE5A8 +:10D9C00026349CE221AD5595B489777667C665BC4F +:10D9D0001FFA6E48B805F5C5D9AA85F2E502994F38 +:10D9E00064BEBCA5BE51ECC9A87DC33068BF3B2452 +:10D9F0009CEEBA24D9B2C3D1CE2B740DBCDFACCC13 +:10DA0000EFD4A39CAECA784F6D991E867E67E3BAA9 +:10DA1000C8869C283C9E1B6E417F7BA67CFEE5F859 +:10DA20005AAE6FBE3587BF3406CFCFAC9F1883EB9D +:10DA3000BA070D5EA315FAB5EE1A1F8671BC6FF416 +:10DA40009E30BC6FFC0DB477A39DD0BB44D4734310 +:10DA50000B18EDE30D75EB99144F5BE6C41739AD68 +:10DA60007A17D2F5B4FBE29E2BC847AD3A8A77010C +:10DA700066F65C81F6D6D03E14277CF06DBEDE647F +:10DA80003F76E1F501F7169FE9CFFD9613EBDF1C1A +:10DA900047EBF34D060B8EF3ECA6CF63F01CCE6C78 +:10DAA000C6CFD77FBB45A079CC067E0C8A47FDC088 +:10DAB000E3A0B341EF9B85F67C98B7A59AF8703642 +:10DAC000F021E6F59E6DE3F99867633E6689B5CB74 +:10DAD000FFD155E6BB39C077787FF7E7CEFBF13B46 +:10DAE000850F03E45EA1BB821785FE7E3E649AFC2F +:10DAF0008211750387F7647E7DA0DCEF607ACF2A00 +:10DB0000BCA7B1400CADC57C55FBF5957FA0BC2DE5 +:10DB10004E3DDB4CF69CA562BEBC05E24D568C0723 +:10DB2000D6182BDBF2BA607D605E173184BF3F1ED2 +:10DB3000F313C37CBBA6C5D3F72658ACA310DD8670 +:10DB4000280FC505C43C9D8DEEE5D59868DD1CA861 +:10DB500087EA64FADE95C6F5D0FFF4E7E7B5957B72 +:10DB60007F4A099AB137F2FBF8E0884B1234D9D5D5 +:10DB7000FFD0DDB84F3B7E58C42F12E1FB7B5F3DE9 +:10DB8000CAE18C88ED090037F5FFFA6EBCC731FE9B +:10DB9000E6882C03FA01D5C7EE1E09F0F1FEB67730 +:10DBA000FBABBEA3F40BCF77E3F37FC439DEEF4FBB +:10DBB000CFBD2548EF734218CFF796E4A538A8F2F9 +:10DBC000DE01811D7E57F0C31E038BC3BC06FF839D +:10DBD000BA3BBAF3B27B9AED63FE7DED73A4D077C6 +:10DBE000B8CE94F77F7466C988FE9FDD6AB4F2FCF4 +:10DBF0008ACC6E06BFEA2E997F8BCD974792FDADFA +:10DC0000645613263059AEBD8FD5CF7F6F6FFD8D13 +:10DC1000DCDB634E9E87AF46CEC3D7D93D4AA1E138 +:10DC2000A31FD0BF0CBC3F95F149F35BC827E3802D +:10DC3000AFD05E643673F82E994FCA778CA57CCF2F +:10DC4000F30F185CE827CC92FDB12447172641BB9F +:10DC50004B20BFA8175AC7B953507F9CA862B5493B +:10DC6000A0B00ACC8E4BFD014F4DF11F515EB41395 +:10DC7000EB6BC2D0EF3903EB8931D04599ECDFB3C0 +:10DC8000CBA2FB36F483E3FB6D5CA9E2B79F643E55 +:10DC90006B8D77C7E1FAC6196FE2F91A2FEFA13C35 +:10DCA000CF0509A3B3308EB4BF6A273B9AEC7FAF90 +:10DCB000B3FB284375230C69AA7DC971FA8ECF691D +:10DCC0009C51F2696EE2F6DBA4AFA53C5A40CACA89 +:10DCD0006A82ED14578A451EC5F8B0F410C1CB66B0 +:10DCE000310BDD63F5EFD3D17D5085FE36EB959199 +:10DCF000D86E1CD01FF58DCEECD5236C2FE0E753EA +:10DD0000FA01E1509F28F41F252EFA2DD261BE7C26 +:10DD10008F6BBE50C9618399CEB906EA478C6B16EA +:10DD200091DE74EECD417F0CF424E55590F5A2040C +:10DD3000FFA3BC48D91B8CD4ECDA7991F6E6FC073A +:10DD4000FA31234D9B475CA193E25F754627454F0F +:10DD500002BD86A5455F3FBD943C65F39FE7F1CECC +:10DD6000F9CF4F8F1D44780389437F28ED4F44C47A +:10DD700099F21CD8FA48E263C308BB84FA76ECCE69 +:10DD80009E4C8247B3760A74BE75CCCE4882C37C63 +:10DD9000DD795E25D9DE8FFD63B711189F3CF9D27E +:10DDA000DF1FC6BCF7637EC3287EAC0B0EA17C13BD +:10DDB000E208398F8318F221DE63BD20F1DFA1B0C4 +:10DDC000B376F9037444FF267E4E1656794E4E27DD +:10DDD0007EEF6FFE3E6EE7E70FE7FB8217F00D6800 +:10DDE0007FA150A43C4DCF04A793FF5673B781EE9B +:10DDF0004730A7ED2FB8AE9A2CF383291616962A32 +:10DE00007A054920AF2AFA3C1EF4DB0F1DD0BF076C +:10DE1000D65D420FC682532334F57A67D037983FD8 +:10DE2000D6102B5A5C30FE506B0F4D7F76B1CC80F4 +:10DE3000F114E6E07EB4C25F4C6CD5D3BDF95C9EB4 +:10DE4000BFE2EEC9DA7B9286DCF323C9DEE46AFD29 +:10DE50006FFB35F236FD4AE1A77EAC9F9C979EECA6 +:10DE6000FF85167E3F4462F6B58ABCA0FE07EFE64A +:10DE700019C4CFA42603734984BFD7B0FE82D364EC +:10DE8000C178409B1F9E04EF45A19134139F635EB0 +:10DE900050F53C312FA81A2F9817540D635E50751A +:10DEA0007BCC0BAAAEC7BCA0EA7ACC0BAA86312FDA +:10DEB000A8BA3DE60555C3981754DD1EF382AA6142 +:10DEC000CC0BAA6E8F7941D5F59817545D8F7941A7 +:10DED000D530E60555B7C7BCA0EA7ACC0BAAAEC7C9 +:10DEE000BCA06A18F382AADB635E50753DE6055557 +:10DEF000D7635E50358C7941D5ED312FA81AC6BC59 +:10DF0000A0EAF69817540D635E50757BCC0BAAAE51 +:10DF1000C73CA0EA7ACCFBA98631EFA7BA7D335B78 +:10DF2000928C766C77BCE37FD268DFE95BE2E783B3 +:10DF3000F7033FA31C364DB450FEC21B5C277E9EE8 +:10DF400026EFF7C8FC7B89854CC573E89DBDAFF013 +:10DF5000E7EBB2BF01F66039F12F0BAD457FEE71F3 +:10DF6000BD8DEE4339EBF8FD44A6E77EC00251F6C5 +:10DF70007FE4BC100B4489FC00CC1DAC578DA7ABD3 +:10DF8000CDCCF42A3C4416583470B43D56D3BEDB95 +:10DF9000644953DFDD91AAA9EF596AD5C0BD2BB3FF +:10DFA00035EDFB2CB469E0786781A67DE272BB0693 +:10DFB0004EAE9DAC69DF77AD4353DFCF55AAA9EFD5 +:10DFC000BFA552030FA85BA8697FF34EA7A67EA04A +:10DFD0007BB9A63EA3A956036735AFD5B41F72D04F +:10DFE000A5A9CFF16CD1D40FFBB64E03DFE2DDA9BA +:10DFF000697F9BCFAD8187B37D9AF679E6031A7866 +:10E0000094E54B4DFBDB638F68EA474B2735F5659D +:10E01000A7B97FCF6A607D8071CA109E5F63AE9B97 +:10E02000D5A17F7167EA794D7B4314AC17807FCA15 +:10E03000411FA2DFF77D9738CAC7CC2AC3AC78EF5F +:10E04000DB39A2F20FEA7BDE63AD3F68BEFF4C70A6 +:10E05000983B88D61766B2B7230624907D6CCB27F1 +:10E06000A2DC67675E161B4521212FFA4702FEC21C +:10E0700012C061369E171AFC20F29F2CE017A1BF38 +:10E08000D9B62ED2C5C7A35D0EF6FBC5BDAEA8F2AC +:10E09000BC5CCB2FA66F67519EDE5103301E5EF72E +:10E0A000463EAEB36631E732DC4F54F22CEE0FD26F +:10E0B000C6B79472B419F0ABFADEBEA0DA5E83AED6 +:10E0C00022EFA3CDADD4BEAD5F39FE25C064E7AB72 +:10E0D000FAFF2DACFFF420D7B555207FE00F3D5956 +:10E0E0006521784D552CC14F574954AEAD4AA5F224 +:10E0F000B92A2BD5AFAFCA26F8852A1BC1AEAA0212 +:10E100002A3756D9E9F9A6AAC904BF54E5A0724B2B +:10E11000552995AF545552FDD6AA8504BF5EE5A496 +:10E12000B2AE6A393DDF56554B707DD55A82DFAAB3 +:10E130007251B9B36A0B95EF54D5517D03F86F084E +:10E14000EFAE7213ECAE6A22F8FDAA66823FA83ADF +:10E1500048F0DE2A0F954D55DF52F9E72A2FD57F7B +:10E1600052E523B855DE87583440D0DCC753603DB4 +:10E170003BC6FD3DCC5B817918B20D67AF961F376A +:10E18000900EA7E4FE0D23C05DC238728F948D35CA +:10E19000AA75C5F201DC5FACD6F1FC2DD53D98A582 +:10E1A00086FC761BE3E7B4B8DF3E13FF25C1D3A896 +:10E1B000AABDB8DE28A9E479CAB3901F53891F3FCE +:10E1C000B9A1759ABC2ED891687F6600AE43425CB7 +:10E1D0005FC467FAEFD11F4C743C877C7AA1F2C10F +:10E1E000BDD87AA6C59A821F196B724763FE2FEFBE +:10E1F0003ED1BA51EAFC7B15F2FD874EEB779FECDE +:10E2000085F6AAE02791E2FAFB0DA193719F7FABFF +:10E210008C8FAD03749AB228C9FE2A8EE74472E54A +:10E220004B0F09FEFBFB77E1121FE47B3C93280FA9 +:10E23000CE4466FB105DF0BBC11144F81EE6A4B2EB +:10E2400035C1518FEFDF0B0B10841D434D711DCD78 +:10E2500027703CBBE5F1EC96C7A1940B92ECBB1088 +:10E260006FC7926D9AF16C95F3338C63DE17705C17 +:10E27000FFDC75FEB890E8C7775B3C8555529E8CF5 +:10E2800022C6E3298F635E8C287F5E0C65FD50B447 +:10E290008FFFCE11FDA1FD5C104FEBDBC0BC19CB95 +:10E2A00086EFE17930603D86F77F8BE6FD82F42FC3 +:10E2B000FE1E14DEDB5DD0E530E599F1CC025EEDAB +:10E2C00049793578DE1B0720B027E5D5A07AE1260D +:10E2D000F87F771C9739554FE3EB42F94E9E09DEE4 +:10E2E0004F796930A660EA8A798F79BC66BFFD3CB8 +:10E2F000F7BBA3BC743F7547A2E3EB013C4EFE7431 +:10E3000006C689909FF03B16179D5F037E320A80F8 +:10E31000A29951C04F1DF81B0ADFCC95EFE128CF21 +:10E32000811F5B11DF67DF1E928A7C53B13B47423E +:10E330007CD7E8F87D3AE79FE57D41F9F710C4F016 +:10E34000B40D74EF009D71A46F4E28DD3B6814D9A5 +:10E35000C2373AD0AFA1E95CDEF7C7F27C92350153 +:10E36000FB93C6744E77633AE787B1EFEFA33C6443 +:10E37000739B78BC9A657AD2EC1D9CCBAA58F89B0B +:10E38000A79354F3A8D879849FE7629E34F539AEF9 +:10E3900064F9FB0AFF89C650C78610F5F878FC01BE +:10E3A000E420243D8BE4E038DEEB1E6792C2EF11DF +:10E3B000E8F7C1CE627E19C71F2C741E503917387A +:10E3C00083D9A99C099613F9DEEE5C4DF7E767B394 +:10E3D0003A7A3E377B7A1CC215CC3B3216D747CBF4 +:10E3E000AB3FC470D0C4DAD5A3BAC3BC26B8A67DEF +:10E3F00088E5F84DC271A74472D43B1DF7B785CAB2 +:10E40000A53DE07BF76D1DBE14E3D6E3444E07F651 +:10E4100031A74311F0B318D17E7E203749E95C6EF5 +:10E4200068FC8ADC142D66363C7FA0DC0F6993A360 +:10E43000EC39FFE8897B38E04F22BF56EC3645D0F7 +:10E44000FA14F3CCA0BE92E567A99EFB974E4C6DE3 +:10E450004AFA93FB1B069B9CCF8B717F648E93AF14 +:10E46000C74E19B8BC9D3A14EA42FE5ED0E5F538B5 +:10E47000920F83221F3F4DA5F33D0CFC8F5BDBFB0E +:10E480001F6D79667A31F237589C237650A2DF9E51 +:10E490009FD2B90687F1BCFCA3105F7B63F9FA79C0 +:10E4A0000EE6A1C1FAAE7609E3A5A7A2CD745F2856 +:10E4B00030CF1963569A9F419E1F8C6C32FAD32637 +:10E4C00039AE561330DFEF83E268BED27056C7D044 +:10E4D000B1D05B9CD351EE1FE2766241975F3BF077 +:10E4E000FB9E20661186D17C281EEBD4317B0D8FDC +:10E4F000CFD2FC16EACD163C97B36C9AE811C84E01 +:10E50000C038319E1765B6F2BCAA4AFEEDC0F1DAFA +:10E51000B4E333C7319C9F4D64DEA0617CBC383EC0 +:10E5200027D083E803F034D5F8A05F17E5FF0996FC +:10E530002CE88735FDF8108F2F5773FF11C6BF8564 +:10E54000E8D31DC6DFF3DAE337208BC2F817A4C780 +:10E5500013DFD5E00EA28876B62BE9DF0941F64736 +:10E56000900F931C2B7BCDC7B8468EC98AF13B76A2 +:10E57000B9A617EAA91026515EAD71369E570BBA9F +:10E580005B82FC301EF3D659C80F6855E761630102 +:10E59000F135200BC55727607C8DDF25FA00E3B3EA +:10E5A00013E5F3CDFDD8570AFE28BE26E2F8285E13 +:10E5B000EDA0719A90B25006619C87E8E0A27904C0 +:10E5C00033B71CCF6E26FF60B5CC87430F32B21332 +:10E5D0004343B89DD87D84B9F0DC57E30F93F242F2 +:10E5E000A17EF7793DE929C013E5037CE7736E57F7 +:10E5F000769F3CDE13F703AA7FD8DB13FDC4DD064C +:10E60000875881EFE7982C8BADFEB846C3C1101E2A +:10E61000D791E37CB7C8F36C60CD3515509FDD5DB5 +:10E62000641807CC6A7107A33C638EDA8EF61B73FD +:10E630002F1A35BF6B61B068E16CA682E3F1E85137 +:10E64000C0EF7FDEE03A775BBAF6F729DB7EF7B3FF +:10E6500035EABA7EF733539EC7AA74FBBBE964D789 +:10E66000268832DE05C417E88146C4F773E546FA0A +:10E670005D83C67263778F6A7CB5B3FE49F87DEF20 +:10E68000C77F92DD7A2F4BC98F531784CF8DCE5021 +:10E690008ABB3D77594771B775A55FD3FAA4369BFE +:10E6A000D1EF88D55E2E263FE05201C34D24567D22 +:10E6B000EBFF9622FCBB5BCCF4BDC0F1EF027FDE2A +:10E6C0000D847A17FC79775FC6DE067F1E61BCCFAA +:10E6D0008AE576F0E7B174813F8FE50BE0CF633BCD +:10E6E000F4E7B17C0EFC792CD7823F8FE5D3E0CFE5 +:10E6F00063BB35E0CF63F924F8F3F81CC69547E314 +:10E700003AC8E8DEFEE2E0B015E86748CE50F237DE +:10E710003EB50DEAE251D9D95B2FEA3474CE6DD5FE +:10E72000FEBECDD063119ADF3FC9FEAA87A67E70D8 +:10E730004B82A63EDEA9FD7D9B3E0BAFFEFB363D28 +:10E740004B4704FC3ECE1D01BF9FA3FD7D9B68FB94 +:10E750007D01BFBFA3FD7D9BDFC9F932153AA648F5 +:10E76000AF05215FAC2B9D10CE3AF02F94F2499962 +:10E770001E0AFCD4A3E2E48EE2C85137737BFFFE8D +:10E7800021D3BE4D80CFF758B81DE3EEEFD974A466 +:10E79000979E5B1B4271589367E849E49FF76C4C66 +:10E7A00042FE79EEF2882E389EE140467CDEB3943C +:10E7B000DBA73E374BC4CF3D4BBD22DE17BDEDB2CC +:10E7C000D78AFCF85418FF9D2DE8D7B518FA7B7F3F +:10E7D000ECE07E18C7792E04F819E5CDED0D4E0258 +:10E7E00038FC8A8EA17E045B4979FE9DCF86C8E7FE +:10E7F00051AFD07DB870D4E9A097DE2BE5DF4FF1A3 +:10E800005C0E56FB43BFFBE95A7861C4579DD6DFC7 +:10E81000313B01C7EBC73BA84628535829FB2DE2E3 +:10E82000A38CCB4F6DA98EE4E912C813E207664DA5 +:10E830007461CD5A797F12E5434D87B2841538CF84 +:10E84000E7D6E869B76C94B875DFCDF0CABA16910F +:10E85000B6D9258B37B823FF4E19F73A1B9F5F8433 +:10E8600095E9D0CE45003E5DB49F6DAD56FF9ED577 +:10E87000B3B27CFE5E96CF67647EC0F536C2A3C499 +:10E88000F5A353701CD95C5F033D05BC8F75690609 +:10E89000A3DF11FD7D6142978EF27CAF91C7F182BB +:10E8A0003CAFF5D82FC93397FB5162D170EC679D0F +:10E8B0009D911E5F67FBBA1AE376970A79BF7D16B2 +:10E8C0007904C46FAF4AAF80FDF77ED84DA54B1ECB +:10E8D000678FD266AA57FA93AC2ECEEF655FB32648 +:10E8E000982F1EB215C95EB4527ED4757A3D433B53 +:10E8F0008CFA0CE14B663D9E91603D661D63789FEE +:10E90000B936444FFB14EBE69E2278B585C361CE41 +:10E91000CA343C7FF1B63C9F30A7936057C07C520D +:10E92000A407C2D5BFE71A58EE90F1BC5DC6C7DB9D +:10E930000687EE028C63C85F45FAFD8ECEDE53EC8F +:10E940006CF657BA00FDD34523FFF81B7BB25DF888 +:10E95000F5CDB87E76DAC92E28EBB6ED63B87D5DCD +:10E960001D3CF5635CF717CA7CF44CF0B80FB1FEA0 +:10E97000B3D1FC77701A47DFDE5BAD2777CAE3DEE1 +:10E9800021E33DC7693BF430B41F6F37E1C8C08C49 +:10E99000D97AFF02FAB38F11AD6EA05B4B96220FAE +:10E9A000F66094BBF7C74C6707B1FF02BEEFB4BD7A +:10E9B00060223D9798FDCE01F0DE5F9AF5E4CFC06E +:10E9C000F3ABCAE37E19FF9FC8E3F8B38CFF269927 +:10E9D0004FF7A21DE98B7196542ADF97ED885BB63D +:10E9E00023BB653BD220DB91B7D18EF4C5794DA610 +:10E9F00072BB6C4732473F457ED225CC8B2BA01D86 +:10EA000099CB96C138F361FC6207F6EDAE6C31E04C +:10EA100077B2823574BA333552038F967A06FC4E3C +:10EA20005762C0EF78F5D7D4E79933027E076C9828 +:10EA3000A6FD6DBE1101BF23A6B523438F4DD0FAAD +:10EA4000335FDDA7A91FDC52ACA977E23F60BE5956 +:10EA5000C718CF2F1B9CFB04F24BD671BDF2FBCC29 +:10EA6000B48FA6F85B81FE4F166BDBC7D3D13E9EF9 +:10EA7000934978AE93B6961334F5E43FB518EC3D60 +:10EA8000F1FC61F578E03B3C87D8523286D13E3CC0 +:10EA9000F02FC85396FDC457946F542CCA203FE9F9 +:10EAA000A25EB39F9613B02F661FA9DD37CBBAC6FF +:10EAB000BED9B19B3BF91DF6D688EBF2C7409E4408 +:10EAC0001CF733C153F720DEDEFE92DBA9C62F1FF1 +:10EAD000E989CF3FC0A6D0CF8E6F1E21BF6B479B69 +:10EAE0007C3882D5FED6760FB7176FB524ECC47587 +:10EAF0004666B4407A30F3C8FC29C48F2D3AFA7DBB +:10EB0000CE94828A60C4CBF6838B83B5F7A754FA80 +:10EB10008108A5D20F22B232FFBDBEFF07E9D10F97 +:10EB200034008000000000001F8B0800000000007F +:10EB3000000BED7D0B7C14D5B9F8999D7D25BB812B +:10EB40000D09B08104260960AA3C36EF4D48C22465 +:10EB5000048C1AC8427804C1304978A48A9AAAB5AC +:10EB6000D86233211062A4121F55B08A2BADDAF699 +:10EB7000F6B65425A0A22CCFAA5058306844D4052C +:10EB800014ADA5F7A284D6F6CFFFE73DDF77CE24FC +:10EB90003BC32640DB7B5B7B6FF8E9E4CC3973E653 +:10EBA0009CEFFD3A134208F94AA4FF8B1F4E0269FD +:10EBB000047FBE4A81FFA7F4B6A19F5C4D02F6F028 +:10EBC0007686A19D6F185F62685F6F183FD3D0BED5 +:10EBD000D130BE56D7BF2D3473A0E2A4BFC3CFA49B +:10EBE0008BAF5B1A09095CD53B2EDBEC133D632F21 +:10EBF0001E97D369EA9D97FEB7F3FD25A6F3F1842E +:10EC000074748A7E5B32BD1E5F42D42C3A4FA7C912 +:10EC10004F04BC9A08EDDFD6C5DA36A23AC6D3FE59 +:10EC20002D9D664F9B44C80EFEDE31BE85037D31AF +:10EC3000844C329F8DF85EF982A9777F04E69B3978 +:10EC4000904418A75D77F179038D76BC6E6F74914F +:10EC500080ADB75F8CC9EEF4D17574844C1E7A9B7D +:10EC6000AEBF248ED07DEF762E76C0BC74BD840CF2 +:10EC700023E4DACD23AA9A461122D1759BE83EB649 +:10EC8000844CA48DEE33EB287B7F96458E734580B4 +:10EC90002B21263DFC2F9A8FFE009C9CA2BF8DC28B +:10ECA00065D7FB73E2C6D3F95FEA1409ACC7AAD4EF +:10ECB0003B7CE368BB8BAD4B9B77B25DD4C1A19825 +:10ECC0003874F8283C3B48D7CE3A41D7499FB74AD9 +:10ECD000157100DF4BAD939068031D0D32B487E9C9 +:10ECE000C68F9128DEC6F58D8797381EB6001EE8C0 +:10ECF000C65E8AF254F922C06BCB07D67A7FD8FD64 +:10ED0000660F054A365C4D78CD3A61F204287CCE18 +:10ED1000779A3C00BC3C57BBD810619EFC8FF4F442 +:10ED200099D319AD83171117F4CB07CB8F37ADD912 +:10ED30001336FEFB9E98F8D3D7D05F72492EEEFFB4 +:10ED400012CFFFA9515DB3C742E99892EC663A8EA3 +:10ED5000B82A0949E87B3C212B717F1A1C892B8E2C +:10ED60006EEE72F0D48ECF5D84AF3E9EEF9D472550 +:10ED700064308527052F8C5B3BDEF7B887B6496882 +:10ED80008608EF7FD0719B18A2EB7ECC71DB6EA062 +:10ED9000CF037FB64AC0D73BFFDC9108F7F7A76FD8 +:10EDA0004D04BADF4FDF1D84FD9929D668DBAADE4A +:10EDB000E400FA7AB3F308F28F4482374CC882B683 +:10EDC000C9D34687BD9A563990F403B7D7399DEC1D +:10EDD000E3FCBA87F3EBAE4637E76309AFAF35A67E +:10EDE000E1FDED8D1E6CBFDCE8C5F6B64619DB1DF6 +:10EDF0008D65783DDCE8C3FB871AABB0FDDB46854B +:10EE0000D161DA9DA5208FCE275200D07DAD744C04 +:10EE10003747C2E775929ECFAE75EBF96C0A8573E2 +:10EE2000787BB27DB8812F5375FD93BEBC5AD75FF6 +:10EE3000783643D79EF869BE6E7C5EA844D7CEED87 +:10EE4000BA5E377E6669A5AEDF57305FBF3ED189B7 +:10EE5000F265874B40B93C3DAB4ED7BF037E0139CD +:10EE60006C17FC6A32C0A5B25F791A00FCD8008E1C +:10EE70008C8F7FC3F1B317F06303BC30F8BF0AF087 +:10EE8000A7ED5700DEF49ADDADEC1E28811CA8C763 +:10EE9000B6356DA0D343E1FFAA5344F9BFB5B10124 +:10EEA0009FDB7FBEB65BC4F53A24C0CB0EBE9EFD91 +:10EEB00016A55B8C87B620AD142E5E5776979EDF25 +:10EEC000C7942D44B9B9A3F3A403E8EDB52F2F4F90 +:10EED000EF69E37E432A27037D1475525D957C69B3 +:10EEE000FDA7E9AD4BCDAF8D03BD1A495F18E7BD56 +:10EEF000FE4B4524741FAF76A90FC7403BF04D5120 +:10EF0000A2ED9C2E6532E06D4F9AE012051C375938 +:10EF100086755F387203DC7F2D6436C1BA0F5C18CA +:10EF200044601F3BA8DEB5D1716F92D4B51328BCE5 +:10EF3000035D5FEC07BE549D16CF6872F13A52D361 +:10EF400045942B5BC6DA4CC204D0776612180B7C52 +:10EF5000AE203C3BBE4C71C2754B9AC8EF0791DFA7 +:10EF6000C7A7BBF0B9572F64C443DB4482280F0204 +:10EF7000DDA6327F84FD8E87F750B9937DE143870C +:10EF80008B8EDFD75DEB00F9F25A179B3F7B45C8AC +:10EF90000170DAFFE52627DCDF919689F3EE1CB7D6 +:10EFA00014ED8B1DDD26A4EB1D63D73833B2709FA3 +:10EFB0001E80DD8EEEDAB5E940D75D666C4B4421EC +:10EFC00041A0B734A667B774D79223B4FFBC47F407 +:10EFD000039D6593F67D03E0FE90355692C2E06F87 +:10EFE0001E42C8ADEC6132D9A59703255D7A7D62DA +:10EFF0000D2D983503EC08A067DA9E668ED3F5EFE9 +:10F000007F7765FC4CC00B8537DC7BADFB8EFDE369 +:10F0100040FEF859FB0FC77F621D48AF4DE3D60C89 +:10F02000BF0DC66D71786C12F428E40BDACEED36A4 +:10F03000FBC1DEC876EAD7B1FF1B9508F72DDDCC02 +:10F04000BE3A9FC6F6B3C353471EA0CFBDCAEDAFAD +:10F05000C9274695C3FB0E50FB09EC8A573C2FC4C9 +:10F0600065823CF38A3A7AA3F0417A39DF49701E0F +:10F07000FA33601A8543011B42F9D0D77C3BEDDFA0 +:10F080009F6773ADA4A8DE7161D7EE3B683B374143 +:10F090002422DDC937FDFAF5E5FDD4A16BDFFAA91D +:10F0A000DE2EB11181EB7327CA81BEF867E259AB3E +:10F0B000EEB969669B6EDE5C12D68FF8B4F6F62761 +:10F0C0005FDA3ED9CAE59A669F6CB528F37D40D7D2 +:10F0D000C15997D0A32BB9FE6D4079B18D104F5B0C +:10F0E0003A95EBDF1065E0C3F3C7ED08C7DCC766F0 +:10F0F0004C24A8AF9589C00F488C61F680F7F8259D +:10F10000EC15974AE273F8AB085CCDA743747C2BEF +:10F1100055F35F810EE7FADC386F5F7AFF41C70075 +:10F1200094FB05A54C2F3CE638887ABEE37DAAE720 +:10F1300005F68E10C5FB6CF805F4FEFB561CFFCAE5 +:10F140007502CA11CD6EA824B285AA3832DDDB6DF6 +:10F15000FE01C59FCF5E3DEE567A7DE5DD8EE1C0B6 +:10F16000BFAF807D80F2A1C1C1EC8318358E2E71B6 +:10F170007B970DF970EB5913B183DFB0DD86744ACC +:10F18000F9F4FE71F43DDB83CC5EE838CBEDBDEDE8 +:10F190000EE4939D7F60EBE858E1607EC619AB0CEE +:10F1A000F6F8D6153108E731524CC00CF32D67F351 +:10F1B0007771BCBECDF1BA9FEBAB37B8BEFA0DD8B4 +:10F1C00013A8BF983DB11BEC097ADDC9ED891DA0DC +:10F1D000CFE8F5C5B3CFBF077C797E7B14DA9D639A +:10F1E00048DA6658D776A715D76984F33C45CF0728 +:10F1F00073ABF47643F958BDDD70FDA8E1BA7659DA +:10F2000062AAEEF9A9F1D7E8FA4B9D997A79649E42 +:10F21000A86BCB17F4764385F7063D3DC9617603AD +:10F22000CA3BBDDF383BDC6F4C063C313F676BD7D8 +:10F230001D88C7ADC753062A6176C2360EE7ADC733 +:10F2400099FEDC16FA22468960477CCAC77DC6F162 +:10F250007186E3E33F46C8BF4B1F0CFCF20593BF2A +:10F260007DD0B1F6BCF6DCA7FE5303C2F5FA4851D7 +:10F270004226D1DA7FE8786F0CF45F2E5F503A6D4A +:10F280000D513C7F478C696FA38FAC31373C056DC6 +:10F2900055359367B2101C6966ECBFDA03F2B839D2 +:10F2A000A6E139E8DFD264736D8A073EFAFEAFA0AB +:10F2B000BD9CB2828D5EFF1435C24F28AB39324CF3 +:10F2C00038FFB316DF700FE84DC137FF563A5EDDE9 +:10F2D00060F53C235DBC9ED80C4163F66DA087446D +:10F2E000CEF77F1194D80C7A5FFE8580723A4A225D +:10F2F000A8176CC41700FE21F5F27CE00F62A2FC97 +:10F3000043AF8D99CA50184F6422B9E83CC8DAF46B +:10F310007D4270DF9F05BA2E0B6950611E5B3D95E3 +:10F3200030949F1F4D5746E078F34C9CFFC569848D +:10F33000803CA3DBC176D6DDC4D5164B286B2BA64B +:10F340002F687B3EF5F7E1FD26C732D453EFFDCEA3 +:10F35000E41723D84B3D705E6639130A8B8F18E98A +:10F36000A783D3C5B6641FCA5FE3F3B900170AC702 +:10F37000AD1F4E1781BEB2EC0364B02BE806C51971 +:10F3800054BE6F3B79BDA326C273D767D5E4660C24 +:10F39000EE6D6705378B354EF4E745D8D716FA3B47 +:10F3A000ECEBE54E5300F07BDE694579D2D73EF2B7 +:10F3B00042FA38442ED80361FC46C80217F88B0283 +:10F3C0006917BEBA269CBEE4FBC3E9EBC58BE90B0B +:10F3D000E1FC9DB7D210AECD02A32F95D217F4ABAE +:10F3E000250D485FAA89F89AB390DEF0F9E566BB6F +:10F3F000CB4625E4B28C147C4F474CF97B0109DFE6 +:10F40000973A13FDB96AEECF55A39C7FE32893F397 +:10F41000C67DED3C3A677808EC89D17387039F7706 +:10F42000800218068BCA9B27EBDA248076E0140250 +:10F43000212B80C03CB03F3BAED3DA5ED62E66E3D4 +:10F440006F79FED10D2AB46FE2FDEA6CD6AFB549F3 +:10F45000FEBC62685B4CD83E09E3E9FB1EF3C8CBF7 +:10F46000006F8FA6CBB7025DE680D142AF9F4D9073 +:10F470006F87F6B20C82FBFDDE04F95B304E6B6FDA +:10F480001B2FDF19DEDED2E3A7B6733FF556B44B70 +:10F49000DFE89A89F6AC447C3780DE7923C8E251F4 +:10F4A0005B46F5EF071DE4F6FC01EEA7BE09F2E8A6 +:10F4B0002AD027CC4FDDCBFDD4DD5CAFECE47EEA77 +:10F4C0000EAE575EE57ED22BDC4F7A09FCD4ABC082 +:10F4D0000EA9E27112E6A7668D9E5C8A76844BF3D4 +:10F4E000534744F4532BBC7A7D33CDA3D73737A48D +:10F4F000C519F48B5EDF4C8DD7EB9B52E73506FDCB +:10F5000092A91B2F5FD0FBA945DD25BAF10567F451 +:10F510007E6AFE473375E39765488847EFF11B75B0 +:10F52000E3723A6B75E37AF1E6433C59D5279D6067 +:10F53000C76D1955C7F1C6EC050D6F1D97C0DB6F80 +:10F5400038DEF672BCEDE678DBC9F1B683DB03AFDB +:10F5500072BCBDC2ED819738DEB672BC6DE1F1853B +:10F56000831C6F0738DEDEE4FE6ED6E8DDE89F9D83 +:10F570003F4B38DE368A91F05696281AF0E030E09C +:10F58000418FB712F370031E520C78B85AD72E3839 +:10F590009361C043BEAEED3D5E6280FFF506BBA148 +:10F5A00052D7AFE16D9A67BE81BEEA74E32E9BDF4E +:10F5B0009CCCCEFB6BF96D1FB7E3F670BCED02BCC3 +:10F5C000619CC8C3E3115E1EF76576DCCB1C6FDB64 +:10F5D000785CA803F006F61DC75BF3A87368C79FA5 +:10F5E000BFA0E1ED6044BC5D29BF5DEBD6C785A639 +:10F5F000B8F471A1C9763DBF1513BD7D37E94B3D08 +:10F60000BF159ED5DB77133FD5F35B5E68A6AE4D85 +:10F61000ED8084CC6CD05337EA9ECB0ED6EAC6512F +:10F620003F89F92D1EAEF7FD95A88F5AA631FD48EA +:10F63000F910EDEF67BF4DED80F45E78BC68F09F88 +:10F640005EEC437F5F93C9F477C77BD508D76CD056 +:10F65000DF91F20B7C5C4EA60BAF363351A33370B7 +:10F66000997B86D1F5984731BBC71CB316820CF045 +:10F670001334E5F4DA49A2D347607E6A2FE5648645 +:10F68000E97DB3AB8180DD20DA1E5A00FB22A2C9DE +:10F69000837AD7601F917A977C07DCBF6380A78D40 +:10F6A000C2E296CC585C879B6CB6809DD198294F5E +:10F6B00002788A93193CB62451DF9DC2634B146BC8 +:10F6C000AB145ECFD0B6387001C2AF83C24B4C874B +:10F6D000F9E3C9DD745D55995606877984E953F5D8 +:10F6E00039A65F7BF421351868FBD968D6BEF18551 +:10F6F0009FCE53137BF56F5DE64BA84FC73887D578 +:10F7000091F174DEF5EA20B033C7D2F5817C34394B +:10F71000B62745B2BFFBB2C3568F97E7C17EBEC7BF +:10F72000F5EB180A117346DFCF3F1BEDBB05F09BCD +:10F7300005F0088B7BCDCC64766B15CC3318ED4B84 +:10F7400039DCBE24C14A6CB7A433FAFAF1DA99481D +:10F750006F4E0A2F3116D6CFE037FF2E465F57BACD +:10F760000F6DFDFDD0892FDC9E0EA393EF45A213F4 +:10F7700052EE71A3BFDE973DA7B2F53673FB51B3CE +:10F78000936D899ADDECC7F558287BE40FC22B995D +:10F7900042E13AC845305E53ED32F9FD14645160E0 +:10F7A000F083DC2915882B19669709C363B9142ED9 +:10F7B0007F8CF141EFF168837C1F64D0C3C374ED8B +:10F7C000A2EE14839F7875BF7ABED439D1A09F264C +:10F7D000EBC69725DE60F0632B0D7EAE5E4F9889F9 +:10F7E00059E5F83261DC421524730EDC27889FB09E +:10F7F0007EF43B7BE0FC845C85FCCAFD1A23BF36AB +:10F80000664A0867C1C5FC1A8D1FB4E735F859DD93 +:10F810000CAFEB7234FDE441BD630B7C93405C950F +:10F82000DAD0F2E6307ADBD4687FAF7434213F69F6 +:10F8300024EF9552E4F91B5D78DDD8E8C6EB138D13 +:10F84000125E1F6F4CC371EB1B3DD87EB4D18BD7BA +:10F85000471A65BCFF506319B6DB1B7DD85EDB58C9 +:10F8600085D7B64605EF8F322BAA9DEE6B542BF150 +:10F87000A8742BA3DBE9FBC2E096DA4AD71106F79E +:10F8800064D5A56B8F5CEED68D4F6A9074FDC3EB8B +:10F89000D374FD098A47D71E5AE5D58D1FEC9375A1 +:10F8A000EDB8B232DDF858D9A76BC778AA74E31D5A +:10F8B000698AAE7F5751FEC0503F7CFC506320C820 +:10F8C000E0120C3238BD1E64F0E9C2EBE75CFE0EBC +:10F8D0003207515E0CCA7251D2A1F8B2B3FC5A9CE5 +:10F8E000D923C486CD1F5746E74B0B5F2F9D4FE7AB +:10F8F0009FF9915E623C41DD7D475A97EEB929A29E +:10F90000B304F211870B448C7B1D2E888B01FBE521 +:10F910007E8B6B5A16A5C7434745CF26780E1E88A7 +:10F92000202F4F70BDE8186F47B950B14AD8242234 +:10F93000D1B2E76B3B5323C63D0FDD4BAA605F8E10 +:10F940005D2F494017150535715161FE5A45E0CFCD +:10F95000A56EB8BF2A3D278ACE56D19A6CAD1BDB67 +:10F96000BB2F6D5CED2ABD7DD94BF77E3BEC638CE4 +:10F970007AAF1DE45B5BE2266CB7A5F59F27F98C97 +:10F98000DB619F723BEC348FC37CC4EDB093DCEF42 +:10F9900009713BEC036E871DE7F6F3316E877571D5 +:10F9A000BFE76D6E3F7772FBF908B7C3DAD29E9F4F +:10F9B0008AF2F017021123F8A9DAF5969FEAEDB062 +:10F9C0006FFAF576D8D2F57A3B6C71BBDE0EAB6B75 +:10F9D000D5DB6135AADE0E5BB85C6F87DDD4A097FE +:10F9E00087F3EB27EBDAF3147D9C6D6E95DE7ED604 +:10F9F000F033DBA7978B95657AFBB9AFFDBE12B8E4 +:10FA00000EF33F80C453617AAF279F0B7A85D245AE +:10FA1000D605AA57300EEE6B86FCC9361842F56F34 +:10FA2000A129F816E47DC8DB2281B8D3AEF339E50D +:10FA30001511E82F47D5D3CD82E3FAF8C68D77E9C3 +:10FA4000E13A6399DE2FB196E9E12A27EAFD924A6D +:10FA5000A39EF1E9E1AA1285005D1AF58DC9B14CAA +:10FA600002F97DA57AC74AA85E616D9DDEB1C29D8F +:10FA7000145D3FEA9D1F64B17A831CBA0E30169A5A +:10FA8000A2720F7828DC76BD6BC63A11BAC023A3E8 +:10FA9000A8FE2982DF29FC5EB5286A03E4D9785ED6 +:10FAA00084886776DF4EC75B87B3BC08F9D2FC1148 +:10FAB000CCAFD07F80AF1C42DB617A2E3BC8FAC34B +:10FAC000D6ABEBF703CE06F7B71EF9C8A89CFFC963 +:10FAD000F5C4C49F06A137814CC07A83D0A0CB8ADD +:10FAE000AF1AEF6705981D9495C8EC206FD24C9122 +:10FAF000E79F08843CBC2662C778E608E27F06E2FE +:10FB00009CD1071CD369B319A64C003F49CFFFB362 +:10FB1000CAFBCFCF1BFDB0EBA45483DF768DC1AF02 +:10FB2000D3F3BF8D18EC971091C09E441C9874FDC0 +:10FB300008A777381D359D68990FFB7A2989E75703 +:10FB400038FD4CE4F82264F3EE1ADAEF758B04FC0E +:10FB50000D1B51E326407D51B04186BC43AED7E634 +:10FB600042BC892B3C68979E61F8F1D27F803F2F81 +:10FB700009C317E0EFB81E7F3643FFEF393D5DBC88 +:10FB80002E4647FFB87519E8CA39E8B2EA588CF72B +:10FB90008B83B21843D7B7D725601E756FB0215835 +:10FBA0004CDBE7DCAC6E684DE24C33AE97C803A685 +:10FBB000503C4CE5FBF5F2BC56472341BBE3C54640 +:10FBC0003B5E096910411EB5B8EF8803FDD831428C +:10FBD000190EF5691D836357417E7E8B25363152A0 +:10FBE0005DCB4E4B2EEAD38E9D0966893E5F6C76C7 +:10FBF00099E1B9E2C45A11FCBD6BBB08DA05C589AD +:10FC000004F3592F36060EB3F729588743F73119F5 +:10FC1000ECD35257CDE4987888CF52DB46023B377D +:10FC200016FDD73D836D88379B6B69E9B7E8FE0EFB +:10FC3000268844F052FC788827007A20D1E9F1C365 +:10FC4000746ECB4980733DFD0778D1F402E5F393E0 +:10FC5000E1F8C825616DCC2BE8DB23B3F5F891887A +:10FC60008275162D5DACBE8C8422E7593EE4768306 +:10FC700016DF3FCEED86633CEE7698DB0D2D86F8E1 +:10FC8000CD5BDC6ED8C3ED867DDC6E789DDB0D6FC1 +:10FC900072BBE100B71B7AFC05A236415E711EB152 +:10FCA00087C05F3858C3E0EC5E25F8CB201FAEB4A8 +:10FCB000FB4AE87DDB2A0BCACF91896A13C4C76D62 +:10FCC00055EA14D8877B417B135C9B8ADA12E0FEED +:10FCD0003CE5F471F0B3815EA6E5707EA7785867C5 +:10FCE00065705EBF38C6B312E85959528EE31219D7 +:10FCF000DCECF41FC03B61912A001DB8158B0EDEB1 +:10FD00003506F8CE837698FC88067AA4F09C9ECDC2 +:10FD1000EBCF32492683BB1A05708FAAE1704F8B57 +:10FD20008FC827EB39DC35B8EC2CBAD9A4D2A16F37 +:10FD300025B2BA89B70A6E361DA4EBEF9445CCBF45 +:10FD40007626F23A41FE5EE37CEF707B765D49FFFA +:10FD5000F1BA437C5C4FBB9548B68161F394DC6F8C +:10FD600091E8F35581FB92802FD60DD0F2C41EB4DA +:10FD7000AFA78805BF4DA6EB0CF23A484D5ECE21E9 +:10FD80001C3686F7BDC5F7D9D77ADE2AB9C122D18C +:10FD9000796705EE21F03E9BB9C11D5E5FDAC9D7D8 +:10FDA000B766C69D04F83238E26C3DFAF13E9B041A +:10FDB00076F7C844CF6AA00377A262F936BD3F9DAB +:10FDC000CA43C905CB6ADF190FE3E8338F13A09745 +:10FDD000AB37033DBC956447B9D3D77A2ED2237E87 +:10FDE00082F6485F7A84CA1FB4876CE59F1C07BF00 +:10FDF000B692347802F4B960966730F031A9B2A0B7 +:10FE00007E4EA3FFC2F36ADAB5D2A0BF1D5E4BBF20 +:10FE10007278E485C656F03BDE02FEC13C2889813B +:10FE2000FA9C60F99D76804F4552CA2EC00F29B6C4 +:10FE300087465338AC29587D13C06B4DF952970053 +:10FE40007455988AFDC162FB69A8C8E92A5E9324AB +:10FE500085C17BCD7DA448017827DDED5E42F79515 +:10FE600092F8C74685F24D9785F93DEF94FC3E31F7 +:10FE7000396C7C4676F1BF67435CC7CDE87C8C5516 +:10FE80004989541FACD179535134C6654ED6B07AE6 +:10FE9000057A7FF572FAA842F5559BA7978F1773DD +:10FEA0007A8A1ADD5D0FE395FB6C12FA67E282969F +:10FEB000E5B45D05F612D84F8F58902F357E4E6A07 +:10FEC000D0CB4DC5C0B75506BED6F8E9379AFCEC85 +:10FED000E5E318C06B540DE3276D7FC67DCDFB9223 +:10FEE000DA39718418FDBB7717A546333D1666DFF6 +:10FEF0004E40D92459E9FE66717A9AC5E98992E49F +:10FF00004E58CFA17B52A701BED426EA07C0DA56CD +:10FF1000587AEDDF14D82719E0A5FB9FB55C4C0794 +:10FF2000FF94DC65E9A5C714DDFBB05E604E781B6D +:10FF3000E85595DF013B02C299F0D23F9D38BCB72E +:10FF400099BEAF73581C69F2E07C1F31F928E17C3F +:10FF5000870AC4015EE8FFEEE87448E193707AA571 +:10FF6000F38754D65F7D4F6A069A9BBCFDE18AC138 +:10FF70005041467CE596DEF1F0BF5233E27FF60A4F +:10FF80006113C4FFC6889F9FDD4DC7CFAAB4799A7D +:10FF9000E9FCB31FACB580DD5FA92A7BEBE8B84A6A +:10FFA0004A177E17EE43C72747CCC402F31C9105BE +:10FFB000D24EDBB366E9F9A67A85BE6DB4478EC62C +:10FFC00028234CF4F94F041BD944AF3B372CDD08F0 +:10FFD000F37DFCA00DEB0A09BC2B07F400E1F1490D +:10FFE00079E33DB4BF76BD8D405E641EB7F7E37222 +:10FFF00092715E9363013E5FD316837EF1E90D43F8 +:020000022000DC +:10000000C703FE5B0735DC06F5D41FC72AD580D7AA +:10001000DA35D798203ED21ADD3E05C67F6222AE81 +:100020004DE9B42D3D6481F57451FB00E2ADDA3A3F +:100030006B5AC3F00FFBCA6171DCE926A26C8E60BB +:10004000D73C9A23703D4B545BD8FA37E448787F0D +:100050007ACAA09687E13D14FB2E0F870BEC7B0A32 +:100060008B8BB6267AAA07D3F6470271AD8C87AB85 +:10007000FC01F0A7FA031B7906D14F70BC75F8B0EC +:10008000A7DBC2FCFF4CFEDE53B1ACFFA43BDA0F92 +:10009000FB3C29B1B6EA76FA919ECD4ADA9C18B6B5 +:1000A0001F61089C8260EB3B1A235953101F447A4E +:1000B0009EAEABF691C710BF5B287C803FBB5C5205 +:1000C000CB4EBA8ED35459ABD0EF7E7C0AC0F3CE60 +:1000D0000C4AA80917C3A9316710AEE7F4FAE6186D +:1000E000AC337111C53AA4171E35ED5BBF238C47A5 +:1000F0003DAF32F9C1F84F2061F29DE2777ADE0F11 +:100100002DB5B0DF28D20E7831ED59658775CEABAD +:10011000B1607ECC497C65204F6B1E11B04D7FD6FF +:1001200082BEA8E5FCD52A0DDA07747C12EC71F4C6 +:10013000F79ED80BF501355C7E552DD2D3E962B719 +:1001400059C72F3396EBF987EE53D7DE98C3EA3AB7 +:10015000BBBC1FC7837E6EA5DB06B87CD222F837F6 +:10016000A17CF58D08AFAF1B9363D2E2F092250C12 +:10017000FEB594FE6A416FD8497B09D83579A3A7AB +:1001800002BD5B8F46E33A8DF0FD6787C3A924A9C2 +:100190007A305DCF294AC750FF73724333DA2FF0AC +:1001A00023EAF8DAD502F4BD84AEF27117D2A7754E +:1001B000C6B85E7AD1E053B33E791F8C73FF678C6B +:1001C000449D2752E3CE5F0AF6640F1D19E0037BBE +:1001D000366BEF49EDA533EC8F406765742CC38B0C +:1001E0008AFC5253DA93D71BD15FFD32E23B9FE288 +:1001F000B5237D3EE4A13439B7AEE84DA483732E18 +:10020000E217995FFB36C8FD18BE3695C881BA78EB +:10021000502654EFBAF01EFACB717CBFB1CB856388 +:10022000A599840C5A2E1E2BA537634B8301D0133E +:100230003637D7BBDB737F3566089C6E2018A7194D +:10024000105DEE09E06E5C09784EC1E24A00FBE702 +:100250004141A882B8FD00A2B7ABE20CF02059E6FC +:100260008FC2EDF2682EEF974E4915D0DF29D3FBF0 +:10027000A766835DF4AB1C93E65FE055825F291CA3 +:100280005BA8FF06726A50A0BD1DE8B39ADAAD7E86 +:10029000DCBF07F33AD652813C2EF4C6AFFE51F1D3 +:1002A0008B8BE2603C7ED1571C4C8B0754B25BD4E5 +:1002B000DF51DC90F7AB74533F6700D85937BBD19F +:1002C0006F729F46BBD4CAEDD2A8D18B5C2C7FC67F +:1002D000F8478B0718E9CA185732F29FD12EFDCF85 +:1002E0001C6E3F5D4DAEBE92F88016C75F93C6FC94 +:1002F0009E3569B52BA17EED3CF77B5CAA09F138F0 +:1003000067968078D4ECB539DEB3B380FFB4FA8356 +:100310004BF93D6D063F24DAFBB42C47D09F8E5C31 +:1003200046478E02D63FC74ECCF6B0FC813397E9E4 +:10033000DF39540FDAE916A7F3734415449F9F1A67 +:100340009ACBE4AC76A53FC18C1C5DBDE0D0DCB09F +:100350007CA88DE743EDBC5EB038BD7BF757705F7E +:100360006675C036B9E6C96F533844CF8AF19890A4 +:100370007E95677E087EF22C07CADBF83409EB5EB7 +:10038000AB12ED1EA47D557E1BFC32B43325D892F2 +:100390008CF2762EE5DF80AB1F7FC7DE7FDCCCA939 +:1003A000F93B058CAE7AE24B3E26BF4DF41FD0D30D +:1003B000EC2A3DBDCC55FAA79FDC5CFD39AE31A1DE +:1003C0000B3BBF42BA60FCBB6E04CB479F2FA763B9 +:1003D000207FDB873DAEF9B74E0BF58B285E82F2AE +:1003E0006EA4F7601AB184E3DB5720EAEA1B827936 +:1003F00024DA45FD9EA085243D48C70D90E75EEFB9 +:1004000002DFB7D81653837AC3AFB3EF0FD1794F5A +:1004100038FB5E8791CEEF1BBD04E3FF0F5C4741C5 +:1004200046D77F1F249CB15E6FCB7CF0DB1E8036ED +:10043000D6DFFDFBFC62684769ED6D3F92C3EA0DB4 +:10044000EEC90DFC482DA07E8D9DEA5B3A9F4322AC +:1004500098A7226433CA6711E281209FC786C1171B +:10046000FD063DBC8D76BC58C0E228A281EF8DEF21 +:10047000BD3D97F339C7535FFB363E477FAAAED6E3 +:10048000D3FF7772FBA997353EEF84FA89982BAF9B +:100490003BA08214F3D3223179C05F262504DF27E5 +:1004A000B8185D8184013D686918E041B8D17614BF +:1004B000E805BF438BABE2A2A300FF22E41303A82D +:1004C000CFE95242422A8CD7EA0F14F295E3F2E5C3 +:1004D0001E95C7388F54C6F2CBEFCA2404EF1BF326 +:1004E000F87A5F0EF8EB47A99E95408FDFAC42BCCF +:1004F000AC7B05C1FC80C3A5609BBE2AD4EC82B84E +:10050000156B575318815EB6B9F5F5AF3B8B1E2FAF +:10051000B6D2FE9652166F3DD418787715A5B596CB +:10052000827C9497AB6060D87A83BBA2AC10875171 +:10053000D46FD9C16EFE708568856B70658D0A9B1E +:100540007E3741DD2C4810775008F8F9D615CD5389 +:1005500080AFDEB5A89E414ECCAB629EB875A57A41 +:100560002BF83DB2545E964CF96853AB19CF199DE8 +:1005700028F97DA214C6879FE732BFE1E0CEA80725 +:10058000000E6B047B280AAE1665D37DF1F03EABFE +:10059000A7892EF1DDA68793E03D6B16AFF1EC82C3 +:1005A000FE261B9C40256B36D8AB60DE35494BDC04 +:1005B0004BC2E6B50FB736C0FDE0B016AC6B51CA02 +:1005C0003CD6A858D8D7E731909F6D5D911907B4F4 +:1005D000D892601D5107E396FCE9B7B98077C984CA +:1005E000795BABBBDD02FB1EE95654C88F9B72944E +:1005F0000340AFF3969F98827573A5B1ABE13AF2D1 +:10060000C2EDAD00FF77793C2694508BF9DA964520 +:100610007576586F4542CACAF0784C4BC162FB18D8 +:10062000FA5C8ADB54B374C0C5F4D102F19709B007 +:100630002EBA9F7130EE8F8D0A1D174AB256453A79 +:10064000A7F509D747F6E6A529101769D96087F4F9 +:100650000C691194F5901F50939D11EBD833BC0C8D +:10066000EED58A6B8A5542FC20BF7DBEF5D88FD46B +:1006700051605732FCD9CDC46E09D37F19D9C567F3 +:1006800072C3FCE88BDE9BD082FAA04560FC9BE144 +:10069000FDE247502FFC7CB6AF1BE0B7A655590FC3 +:1006A000F022AA9D0C28EA9B4F42F7911184CAE3DD +:1006B00096265B55A43AB4D022713AF009E5A0130E +:1006C000034684C9E5957529101F09355D85DCDD74 +:1006D000337E83FD03C04368435A2CE8C350526DF8 +:1006E0004A0AD02DA74BE3FC5BB81DF062A62FDAB7 +:1006F0000B76E55896F79C91EB73629BB4BBC1CE29 +:10070000FD1AD06D2AACF71F48B7A8E73ED9FA1FEB +:100710004857C47579F9481F0999319F5AF4178CC5 +:10072000F7B68DD3CE3FB1F8A066F7468DFE6815BB +:10073000F8ADBE3C2DDF55B017FCF5E95A3EB59C2F +:10074000C5075DF45FA4F8A0CF101F9C6E686BF620 +:10075000E60D5EBD7D9B28B5FB4A40EE1E103DE0D8 +:100760004F2411A65766940B7EB0B39B8AA2EDB8B6 +:10077000EE3C1EE7E4FED73CBEEE638D7602F92424 +:1007800093A36035AC7F7A3E5BBFA33E3D3B2081A7 +:100790007C67716E526F93306E02C84F203D7E9A17 +:1007A0000F26A1FB9957BF14EDFD5EF835B1F81087 +:1007B000D1FB133E62F01F16317B4CF3B7E61BEC06 +:1007C00003A3BD6F8C53F7E60536DB819EBAC7667F +:1007D0001C4A91B05B0D68F9003A6EA1B773752899 +:1007E0004CFE7472FD70A4513EB68AEE7FB5EFC721 +:1007F00076A0D336B3DF0EFAA4ADECCE18A0BFB608 +:10080000056219F07DB0B10CC71D6CF4E1759597C8 +:10081000C9BB60B6BCC21B1677AE2C2B3EB62ABC39 +:10082000EE41BEEED8AAB0F5577867E8DA1A9D55C2 +:1008300088A4617304F9F2BC97D9ED66AAF7B1CE2A +:1008400050FC85A7BFFA1BEAAF7687C3EF41AFDE46 +:100850009EBD7F6CC9C0FEEC166D7F1A5CB47D6BCB +:10086000FD7DADF37B7FE33A9FF5EAEDB94BADD368 +:10087000B83E6DDD7D8DAF0061350CD659BA00EA0A +:100880006283D94A07C8A3CA526135E44B8FF07816 +:10089000E29182183CE7BE378DF97BD1F58C6FA2CF +:1008A0004B6760DEEF4AF17BA397D995B30A04BF8B +:1008B0004C7F9DCACFDB1F4B63F9DCA6A29FFF16BE +:1008C000F2D0EF145A58BC97C8D3A785E5B1D659D2 +:1008D000FD01C8271DEBA9D358B6FA6EDA8ED6E40F +:1008E0004A953EEF306B963E7F5861C833441BE417 +:1008F000CA518D3E7228DC537BE1DE973FD1177DD4 +:1009000010F3D92CD04346F8DC66808FD17FA9D86C +:100910006EE087CBF46336B566ED85BC9A4AEDC9C7 +:10092000D1803FE8A2CF45CBBFC634C8803C468FBC +:10093000634267D6825EECA42A00F4CBBA9977AE04 +:1009400087F679AAF7012F7DBD47F3DF9ECF96BFCB +:10095000F446A81FE89123601F4C80BC6064FBA094 +:1009600073D1E46911ED83997529D9B0AE197AFB79 +:10097000A07343D99399701FEC03FAD39957A7B387 +:100980000F4859E625E0C3E46ED4E8AC88757AB325 +:10099000B395C17961FB71A43590F07AC6EE1C79EC +:1009A00008F4CFE07104ED7DD4FEDA638950BFA86E +:1009B000BD2FD7CBEAF049591CD30FFC7A293C6AEA +:1009C00075D4F75B64FCDE8B16F7D2C665E731FBA6 +:1009D000B03545AE877EE2CCB8C4BC4D5A9C232DC1 +:1009E0007D08AF1B96488F3FF41741C2FE08FE1EDC +:1009F00081BC6474E2D93D2E3AE433AF929F970DE7 +:100A0000E728FC2AE4436CE502DA4BB6448276CD53 +:100A1000E5FA57973BAE158A03C0DFAA65F1F2E20B +:100A20007433B6A3157113C8854917060A20377C9D +:100A30008AF834AC375AFEFCD31F83BEA67A1FE275 +:100A4000303ED280E7AC9D161FC627DACAE9CCE952 +:100A50001087596949C1787AF2AF63DCF0367F2B91 +:100A6000C4CB6D1E761EAACAABAE86EF6654148E3A +:100A70001608ED9FEE63F19B3910BF8179679DDD0C +:100A800009F19FD95E26BFC06F03BD39B7EE3BE3C6 +:100A90001E95FE9AB88DBF352E0BE34912C60B0C7E +:100AA000F1215BC1548C0F69752ABE0211CF779377 +:100AB00044277E87C218DF31C6738CF11E637CE742 +:100AC000EE3C5627ACD953DFCED3DB532BE00CC220 +:100AD00060B097A8A8A47CDD662149ED943E0F156F +:100AE0007F42EEA2EB70FED00435E0749C21CE78FC +:100AF00099722B48E5CA29D8C8EE372CE0DF2E9032 +:100B00006B30BE67A4FBC7B8FCBA2FCFA9ABEB080C +:100B1000362EE7CF47A980E705A3ACFEA8E4DE792F +:100B20002E973F9ECA911FCE637EC50F81CE894707 +:100B3000C1F30433725D3ABA250D83C9A9B0F88DAB +:100B4000F1BDDA7AB4F9AF741D0F71785F2E9FACE6 +:100B50002BCAB75BE9FBCF511C8BA82FA9411D16EF +:100B60009FD6E2E7DA73D59037C8043B52C0FC81C8 +:100B7000763F2C8E6D06BA8D4E54E448DF9B7A3B4F +:100B8000AF276E8A794CED3D4450502ED4F17C8DC8 +:100B9000369F99B89B900F80B6B5758911E2E6C46F +:100BA00063B75192A95D2B1288FF3889DC0EF1677B +:100BB0006BAB05DB44ADDA0776FA22CE17D682A9F5 +:100BC000FB20AEA6F185316F631513A7C2B475ED96 +:100BD000FAFC95313F65B4A7B5F8BA99BE04D6754D +:100BE0000EF0C1F6EB172F6FBF4FE37EBEA6FBD50D +:100BF000E8AA3CF31637D49FB44429EB6BE8BAD487 +:100C000027ED18AF70C0DA002601FA0FE4E493DE96 +:100C10001FE379F67CF65D9A1681D5A3EC49F8635B +:100C20007CF8F905533EA39B9FE549388EEACF0037 +:100C30009C972263E3912FB4FA934309CC0EAC281E +:100C40005C1CB893B6FF8DD74B5E53F88C96EF1FA4 +:100C5000509C43B0F403E0B2CECAEAD20E7DC38CFE +:100C6000F564443CB0EBCEF8DEBADD6B36EBFDCA82 +:100C70001BD2F4F6A0D1FEB31ADA43F38D75648A61 +:100C80001DEBC812781D195FBF914F7EDAC8F21AAA +:100C90003FE775FFBFE0E72F7FC9EBF736F3F39728 +:100CA000CFF373B31ADCEFB728188F3E711DB5E987 +:100CB000627BE380EB8ABEEBC6F3FBF9CCCF9A22D2 +:100CC0003A77819EEA3D67D1FF77C22ACBF479B3A8 +:100CD000D93E7DDE6C6E953E6FF6FF32E5ECFC6C26 +:100CE000388751BF12BE5330639588F9CA752DE716 +:100CF00050CF9E2F406BFBA2F71CE6E730B4731C6D +:100D0000DAFD6BF3D9F7911CBB122C508F3F635562 +:100D1000EC54889F1357C665D96F15107387FCCFA5 +:100D20004A9705BE0731239080F1D09AD62B9BE7D6 +:100D3000BED143304EDD13E757C7DE04F2F9B016DB +:100D4000E727D7DC0471FEC33CCE5FF3F2B827C1BE +:100D50003FFA599E3C17E0D1942757C1B586AF871B +:100D6000B66FCC1FDCDBA63FAFC7EABF3F5193DFB6 +:100D70004F3C5D9C2C3444AA17B939BF27CEB5141B +:100D8000E627F69E38D737613E626FC77376F7E67F +:100D900033F9D47C8CD4C33CCD2F93FAE723D8DD30 +:100DA00077E50BDA7CDFC2E7DD9A7EF3DDC9E6D7B3 +:100DB000CF27DA624780DF7F82D79719E7BB37DF1B +:100DC0008AE3E87CDFC3F9127BD6776FF8FA7ACF33 +:100DD000CFB86280691DD58AA98BD2136911B1EE93 +:100DE000C4D1E19A067549646A2AD6B11C2EADFCBD +:100DF000A7384F73B8F4857FC9F334DBF2932FEB38 +:100E00003C8D63265122C535029C2E7715640E0C4D +:100E1000F58327EBF2FD41B0337ADA668540DECF09 +:100E2000BAFC20DEBF3FCA551DD1BEE0F2ADA574AD +:100E3000910F52426B92A68AE1F6CBD92CE5CDFCFC +:100E400008E713CF8DEADE0DAA6966A96016E2D124 +:100E5000DEF608547E66AD9821BA2542BC0D0F4ED1 +:100E60001E4AFB672552FF2E6CDFF9F5BFDE4DD918 +:100E70009514941E6E8EA7E376E4286F03FD16B9D1 +:100E8000A53DD09EE54BC7BAF7FB6309DA79274643 +:100E90005BFD9B922F5EF7EF7AE5F24AF315C8E50A +:100EA00096467DFE7B4DD29895B0FE3125240412E6 +:100EB00036C57DB618F27F19D9CAEF605D296E225A +:100EC000DBC6E37D9984E56F8CF30E98C8F0342679 +:100ED00094F80388271FD2FCFDA22BF6F7FF180E0B +:100EE0006FE3F584E6EFAF8EECEF9F581417391FD0 +:100EF000D052570BF98013ABF5FEFE890DEE6A3820 +:100F0000E77782FBFB27A6507F7F6CDFF9006D9FA0 +:100F1000540E3927EAF201DC6EE771EDD9D9F2C03F +:100F200089D9E8CFBBE0DA9829C7E278D575139E56 +:100F3000472691CFC992275C32F839DAB9F65CAF0F +:100F4000320C9ED7CECB8E01D13608F2A2AEDB2278 +:100F5000D1F368BEBEBF3E4FDA93C734E139EACB66 +:100F60008CD35FEE38C9BB99D5E398599D61544243 +:100F7000891BF253E7C7DA51BFB7C2FFC2F46A6AEE +:100F8000BE3271E2E0F0790CDF57952EEFBD5A9D2D +:100F90003EE82BD02F9D849481BC7920B601E31EBE +:100FA000D771B819AFE513395E892B1EE0999AEF16 +:100FB000BB01F0415EDC2CE17760F9FDBEEAFB8D00 +:100FC000EB78D6EA7B1FCFD7978812ABCB23C81715 +:100FD00057A5B9504F6BF6D7D2894C6EDA48689452 +:100FE00095EEB359DEEDCCA4E33E7CC29C0E8F3D62 +:100FF00017432CB06E5F1A9573741F256E65647F5E +:10100000F211BE4864F2C2352098DC788D635755E2 +:1010100080FB17F1E313DD83C11E7FEE49969FBA73 +:10102000EAC945F6DAB0F99F98C8E566225B7FB554 +:101030002CF8A56458CF59CC43CD904C1E9940DE76 +:10104000F8FCD1B91027A4F6DB686C9FC376503248 +:1010500065425EFB43F7174761FC55F72E1E82F48D +:10106000CFE1B17045E6B368E7E728DF05FC070B81 +:10107000CEC5A48E453B7E3DD0FF4281F822D909E2 +:101080000F71BC5D2F37DC087476BD6C23706E2D3C +:10109000586C43B83F572848E0B75600CD433CE76B +:1010A0000933C69B293C9641FF018F03BF1B5D227C +:1010B000FFDA0CED3F8E13C8D07EF4F115C3B5E016 +:1010C000DC60E0C70F81FE22AC7F295FBFC64F14F2 +:1010D000EE25B82E99D58BF44557DD79F2934097DC +:1010E000AD294A3D7E17D135F3B2BE8B58F1533F3F +:1010F000D6EED97ED2308C44A8FF3AC4F9C478FF2A +:101100009713997D770BE78FAB9EEC3E701DF0F542 +:101110000A8B0BF0FAB33CDF66584F8FDFF57796FA +:101120002353C40588BF60395D3B7EC781C4407BC3 +:10113000FA2833E24F2DE1DFF9B89BB89A63F12921 +:101140006CDB5708C8670E677B1518CDE6BC86A315 +:10115000B3E1B96211CFF5879D73E9B78E2CC4CF87 +:101160009FB5C0F9336ACB075789DA77B7884065EE +:101170005BB0D4CCEDFBCF9E94E9AFCFF2FACC9329 +:10118000AF5A36421DCB51136BBFFDAA65C44AFA54 +:101190009ED008B68EB607054F9304D7A7D743FE57 +:1011A000B26EB9E029A3EDEAC03D5D10E25AF288C3 +:1011B0008D80ABF0F10F974E85FD9C7313FCBEEC58 +:1011C000DC04C6374A90F84DC9BDFEED0749C4AFEF +:1011D000E54BE11C9D97EB9987E01C1B5DF7B5EA99 +:1011E000B7D4EF40DE94FABD10571BE461F9CCE8A8 +:1011F000A0D9E327E0EFB2FAC8961F08E421984788 +:101200005CDB0CFEB98DD7EB46CB35E83F0EA2F484 +:101210002981060D9975E7D8EA8882F41B5746396B +:10122000231DAE7AFF38EB12E7D9E6DE343816F824 +:10123000E52F13F5E732FA8AAF6B57F8DE0DE0A71A +:1012400083E757B751BB1DF6FB32B5DBE1BA9DDA38 +:10125000ED701FBE530D5738CF06D75DD46E872B68 +:101260009C67832B9C67832B9C6783E7E03C1B5C1C +:10127000E13C1B9E3F2C540303013EC5D104F243C5 +:101280002D1646676A9215FD8D4021C1FC7D30C93F +:10129000BA6925C4EB0486273596F50763949BB19C +:1012A0009D3C96E577CD9E11708E7095305602FB71 +:1012B000A9D5AA60FDF289956602F5CBA169C2FBAA +:1012C00090772182C92352FB66C757B721FC17CB01 +:1012D000C40475E92BE1BBA1208F3F259B587C2ED0 +:1012E00028C2F7E59A6308A7C73ABF4C65F669417B +:1012F0006B1F52C09F9D043101A4DF030AF42F5ECF +:101300002EF076D02F8F82BA06DEAF1E7A0AFCD777 +:10131000558676A7497B3EE52998EF68CFFB465472 +:10132000CB40EF295A7FE242689F8AD29EFF7C2100 +:101330009EE7D2D6A37E8AF38592B4F1A9D5D01FB9 +:10134000EAA9935B82EB0D0D66E3FF6D57E7D3E0EF +:101350002FFFBDE76B56548CE3ABB3087926F662DA +:10136000FAFA7892A88F87CA822E1EAAC5DF4D8E00 +:101370000543F1FCD90336948BA79208FA217DC569 +:1013800045C3E2F51817FDD524AD9ED910FF240AF8 +:101390008179AB201EE8C1B72AE1E7D388D040A00D +:1013A0004EDD772646023BD29A1816BFE332A0BF25 +:1013B000786173038B0F06150B51937BEBFAAD0528 +:1013C000BCAE9FC70BB53A066BC1A3BABC81315EF8 +:1013D00048C465988FF62DD2C7032B942B8B172EFC +:1013E0002001CB50A07F59F080FFBEC0A57C300407 +:1013F000EDFDABD9F719A5D7316EAA9D1B833BF044 +:10140000DDA92ABEE7B65B4FBC3F848EF3AF8C925A +:10141000E030FEFC65C5F87C1EDD21C4B76A0AF128 +:10142000F02DC9FED4F3BA04F2D46DF23033CD7787 +:101430006F02D80B8B62316F72D35DE91FC03C8B9A +:1014400055073E47ED4A4EEF2F6D047A1221701971 +:10145000D6CE1AA1D15BD546E0AF49715A3BE629F9 +:10146000E08762ABF6BC17DBF3148DFFAE790AF4AC +:10147000C7D1128DBE0F54C3F3B3537BE643FA9E1C +:10148000E4D0DAD317427F6BCF7C4B36C27CEFC0FF +:10149000978DB03DF529E0E7E2195C5FA91F6D84E7 +:1014A000F95B1668F34FF0C3771EE79BB4E7A3FC24 +:1014B000B07E85686D2ACF68FB3DCEFFC70A5EA867 +:1014C000067EB9B1A7FF05DCEF02DE3E5E50F714E1 +:1014D000F4FFCBEFEF7FF87DC6F64D2438656856F4 +:1014E0002F5F18E5D56F8B981CF1D6FF1AC8952C85 +:1014F00068781ABFEF06F10096CF4A98E503796144 +:10150000173D943388CFEDC238A7719E9B0B595C71 +:10151000FD4C813E2FD662C88BF9787EAAAF798EBA +:1015200014B1795A4B22FBB119D9257F2A80FA01CF +:10153000725684F95C1460F07DB2964CE5FFC37D71 +:10154000CABAF8DD4D2AB23C709FFAC52AD899D3A1 +:101550002938210FDB54F438C6E9437916DDF7400A +:10156000B43CE73AAB8CF2F1635ED731BF449E7274 +:101570000FF0FF30916CC23A0F27E61BCCC3AD4F82 +:10158000A35CE7794FED7B1CD32F712EC2782EA57B +:101590009BC3FF5C419B05E4B34AD429A55928AFFE +:1015A00083506F6C72ACC53CB0ADC88279042DFF1E +:1015B000ACF0EF7F6B79DF49170632FD9EA6C5754B +:1015C000FBCFFF2ACB77FAD03E68178949B8381F7E +:1015D000BCD8A726413DCBF4D2183C2F5055FB0672 +:1015E000CE7F7804C1EF0447CF6AC0F341666A1F1B +:1015F000CA00179E2FD6EA63465EB81DCF8DD66906 +:10160000F5E662F941B0536D8F513F0BD997C14553 +:10161000CB17CF30C8FBC50595A86709B5E347C709 +:10162000C27BFA3FF7FCF0A458A49B8FDA593D7FA8 +:101630006121CF97F03CF0FD1616E76B4DD1D3D565 +:10164000CF27317F65FD244677BB8A7E5E85F633E2 +:101650003179202F469E60DF8583180B9EB7327E3E +:101660008F396D0EDA754F8CA45BA4B6B679F97B11 +:10167000185714D6B3E73E1D4F1AC06F319B599BC4 +:101680005E54C8FFE77A9599855097B5FC031CDF37 +:10169000ACB27AEFBEE237D5859ABE67F19BF9EE20 +:1016A0007D5D70AEEC6F8EE318CEBDFA24565FD22E +:1016B000562069F946FC2E21255C0BD88BA9F9BE72 +:1016C000FA428C6F6D96601D9ABCD957741BCA275D +:1016D0002247CE4B6B7CDF62C84BFBDCECF923AFBF +:1016E000DD530D7F17A2AF3CC4B3C53D7983E5F848 +:1016F000FE782D6F20DF03ED5E3D4A37E4D5E9D15A +:1017000085F5FF0BF4688FDDAE76A11DFB755B3FA1 +:10171000A5AB1710AF652C7EF6755BBF3C517E13F1 +:10172000F8F9BFFB3DE9137D5D00A7FB04B9CAC909 +:10173000927B1E419FE7FBA0B09F3CDFA5E20FFF1D +:10174000176FE83FDE602FD2E7E1FF59E20D0E3858 +:10175000433518F928B108F8A880F1D1BFBADCA345 +:10176000FBCD2F827CBAB0D91F9DFAF7F7F753F360 +:1017700095B222D4838A6917A59FFB8AEDCC9E0976 +:1017800030F8F6C633E8FABDBA78C653F5FF0DF166 +:101790000CBADF2AC46F297FFFD71F7F77207C65B3 +:1017A000664FFC0BD2E703B8BFCD6C7FFF80F76FAD +:1017B000447AF905A3975EF8303B290C3E0BEBFF0A +:1017C00031F0791EE1B38DADEF6B80CFD7119E1E46 +:1017D000B6DE4BF9D7270A044D2E1FC27D66313A7B +:1017E00038C5ED6BEA774F1E2AF5FADD4FE5C86F75 +:1017F00015313BF76891AEFE537E1BEEF7E3171FE2 +:1018000083FE087E7108EE7FDDFCE2D8429647EC4D +:10181000CDBBF8D9776F49D5F5DFA0EFF980C21BB2 +:10182000E26D6DCB45B42FCE2712FC1E80666F840F +:101830006259FDDEC5E7C14A099C47B4E5B1EF8CAA +:1018400068DF07308B0B0606A48BE17A7080628517 +:101850003AAF25727A0B9C6F9DBCF6733C77659509 +:101860006DF8773547BA3D96BBC08FA67EEEB510B2 +:101870004FAD77E1393AED5C9976FE634960DE3E23 +:101880003867DB46E92181BEA7A2D472327CFF46CD +:101890007BC36C681BFFAE69C2247DDE83C21FED73 +:1018A0009FF3EB597D5C9B99EC82FA8F3A55F437A4 +:1018B000D1F6336B05FC1EE7220A27F0F727B7277E +:1018C000633DB935917DEF4CFBBBA7940EDAF3C0B5 +:1018D000FE3B2A12FC3B76FC3C99F69DEFA869671B +:1018E000F17B5BA7E8FEE1FB3DDA772666703AD133 +:1018F000E019D5148770394FE142002EFCBCCDF4BD +:10190000E52C1FDCB2607110C8BBBAE0F35591EA58 +:1019100052E6B8F5DF4B37C6338CDF1B3713DF4099 +:101920003857575150AC82BD6AE3F59AD144C6EF9F +:101930005A9C5AFB63F65D8B528BEE3B22C6F746F0 +:101940001BE8D466883B18E9D4889772035E9E3101 +:10195000B3EF0CB6748A1E95DE6E7964512B9CCB66 +:10196000571F31B1BA7922E3779F5AA8C58BE7CFC9 +:10197000E962215E3F97C353C30B210D16E0B70503 +:10198000DA397453C36A384F3A8F9F43BF916CC69C +:10199000730637810541DFBB1042E4227C5746B213 +:1019A00032E7C045601D7555EC3B1926D803E409A4 +:1019B0001E3121BFB6B877E1DFFD0A0CB3C49E4EDD +:1019C00063FE44247BB627AE4021713A2C8EFF7F04 +:1019D000F1ABBF2D7E35B17010AB9B880AB8F29287 +:1019E000D9F726A09E6962A1C4CE2758941178DE4B +:1019F00061C3272AD08176DE81FEAC18A2FF6EC2B9 +:101A0000C649FDF87F258584D54727879240AE7D5E +:101A1000D0475DE5E1E29EBACAE72661FE9DDABFE6 +:101A20005920F798FD3B23D7F7B3496817B373CE16 +:101A30005A1CE933AFF24B185F087F3F270BCFE703 +:101A4000F8E1FC4E8553D82B48BDEF27C63AF6FF88 +:101A5000A579AB7BB8DF168C22F81DA46032A97A79 +:101A60003E023E9E29617644303D32BEB47E6A67B6 +:101A70001C9FC4FDA1018C28CE58F5F18193809F55 +:101A80003EFF0E1DC7E3E829F2478877DE7E385710 +:101A90002132D4F72ABEF701AFA7555102BD420249 +:101AA0000A7ECF6FFAF74557A4BFA7F8CF7EFD2F68 +:101AB000E87FAE8400800000000000001F8B08005B +:101AC00000000000000BED7D0D7854D5B5E83E73A5 +:101AD000CEFC24998409061C24E849001B6DC0E152 +:101AE000279000813393842490C0F0A741221E08E0 +:101AF000D0DC5EB44111634B9B0381102222BE8B6C +:101B0000AFBCFEE824185AEFB37DD4CB6745D48E22 +:101B1000012D5AD4E0851A2BA54110B1CF7E8F5EDE +:101B2000E5B5CFE7FB7C6BAD7DF6CC39930920C6DC +:101B30005EFADD3B7E7E877DF6DFDA6BAFFFBDF6BA +:101B4000492D8B3AAFCD628C6952A0131EB53EFD74 +:101B5000E4502CB39B59E74478A88723F224C65657 +:101B6000B2D84F7540B986FEC558DB5DA77E3F14DD +:101B7000DA4536A6A86C3A634B5607A97F11F332B3 +:101B8000199E6DD372181BC258C1B9C06115CABA6B +:101B9000DF11906898F0778741BFF08A4CB50DC689 +:101BA00059560CAF0A183BE984E714F8DF98B64C95 +:101BB000CB87FE58BE8E3A680CCA4B065BCAD9D09A +:101BC000F4186F5FA8FD35628C82F199D9DF6CFF44 +:101BD000AEC4DB9F0F66470C2F63B79BF550D6B1A1 +:101BE0002CFA33969E1354A07FBD24CAED9A629DB1 +:101BF000EFDA766D1A63679CF6F16BCDF16669AE2C +:101C0000761C2F1C9BDFD5AE41F97402FC77305E49 +:101C1000BE557350FB95B1F60E5AEF594994C7EA79 +:101C2000583EEE12FDF39769B0DEED39BC3E1C1A4A +:101C30001B31B2AF3E78BEEAF1BF303CD354A2AB09 +:101C4000C2FA5F945C0BFFAC6D6897752FD259F8A0 +:101C5000F70CE8D17844523BA14F21DB2B3399C0DC +:101C600076C94097533489B5C15CEB4212F50F7BBE +:101C70001D7C1EA328A2019D2D992EE8745904E70E +:101C8000ED8FEEFEF4D29AC70CEB3A8D354B6D70AA +:101C90001B636D702FEA82F6505E72F73FF811CE2B +:101CA00025B9627D2511A4BF964CD1EFC38BCE7BA5 +:101CB000EAA56AA2F725B179E653FB25A962BCDB48 +:101CC000A91CC7E79D767C1A372EC3F9045CA1D006 +:101CD0009D84CFB02FB219F93DEC670103F0797BF9 +:101CE000FD0659CFB7F09151A5121FF963E5889D04 +:101CF0008F0A888F061AAE9153C23FD440CEB0BC33 +:101D0000BD6A78CC57B16E9093B86E43A2750B3A0A +:101D1000AAF559E8DD03EB564539B0ACDE3B10F3CC +:101D20007697D1BC1F01BE599C9F98919BC03F974D +:101D3000375EB377B90BE15EA5495A04DA7F8EBFEF +:101D400019F1E7E9699CDE019F2F6BF0648580CF74 +:101D5000747CCF488EEF9B107E95F0ACEA8E2E807F +:101D6000CBA579581BE060DEE4F06FA83DDBE147CE +:101D7000FC0300D4BEE5285390CF80B7028EA95053 +:101D800076B29ABD49E6FD69C841F3363356B117BC +:101D9000E09BB8D1B72AEC8DD7E79671B8547CC2D6 +:101DA000B8C7D37BEF1802F3F732E6DB08E3371B43 +:101DB000C0BCF07CBF5E8A48B0E6F7B3C3738AA0AC +:101DC000DC9DE3086C84E9BB1F708F580BED7B72C0 +:101DD000BC0184AE277347BA0FC67F3F209BF8BA79 +:101DE000E73DE4EBE3E9317E3250BF749BF83DA759 +:101DF000853A908FDF5179F967A56BDF43FE6279F1 +:101E0000CCC786021EB007F0AA236D9AC70DF3BA9D +:101E1000668238C1BE3EA6BBA0DE8DF5B0C4798F08 +:101E2000EE7E74018E61D4BC32CAA2475D4C317A19 +:101E30003D34AFF2395790CC39293EAE6B67F3CBC6 +:101E4000CDA88FFD320B216FF9797B3FEBDDF0B927 +:101E500003C787721E43127CE97358BF6496F1F77B +:101E6000392CD1CBC2153908571E0BA0BE9DA73BFC +:101E7000CFC4EAF9639B32C98413E191D75714C1E7 +:101E800033B5DEDE6E761E943DF1F2AC9D7521C455 +:101E9000FB2C0DBA8D63ECC8CEBA681DC079A4D0F6 +:101EA000ED9300D3AE6CC5D67E36DBBB09F10E7662 +:101EB000C52119F0B2D49CAFD937EFF70CFAADCAEF +:101EC0008312ACFFF87782E90559C86F72C061B61A +:101ED00071087C306AE77470391D90A07DF37362DD +:101EE000DFB40EE403394DB295832E513FA903F9B7 +:101EF000E2784CAE8E598EE5452305DF0CED403D72 +:101F000039234D94072D47BEED559CA63CBBBE031F +:101F1000E559AB18CFD8457CFD3613F5691D484708 +:101F2000E198FC9BDB8EE55B7D263CC60F491E36A7 +:101F30006B5C9F4C7DE9D55EE30ADA037F16059161 +:101F40000FC35CDE25D64F391669CE30EDBAD16AA3 +:101F50005F7EDB1694898FC2DA9F65DCBFD206C034 +:101F600019EC5F498D74AC00E953612390EF5B9AE3 +:101F700080F74743F9608A4B4D47B9EE9BA925E1AD +:101F8000DF57830E1AAF2AE8CD3AFB75683F814DC3 +:101F900040BA6B696A14FD0DDC5F7D942B9292D37D +:101FA000FF38A74AB81CE8967C0BB97E9619EAE779 +:101FB000E02323BD452CDEEEC5122E0F5A26688B7A +:101FC00083F09C03E297C11E6E98FE837008E63989 +:101FD00053E40CB889CFB4B790CFE69B34F4B04B40 +:101FE000630FA0DC2872FB36A2EC96F39D8D505651 +:101FF0008603BF62B982D3B70EFF7D9E8BE32A7141 +:10200000FA0738E635DAF9416116FA86FAD5C1746D +:10201000BEFE9BD9CDB8FE079DBEA528C75A737DCD +:10202000775BE5D9FE122EC79E36D7DB35FD9F6B59 +:10203000103F1F334700E5C79ED430C9B353198CF6 +:1020400075A0CED798EA1B8A7CCDD721E5DDCAB032 +:10205000FD8F6E80250C03381ADFED2E9D00EF7783 +:10206000F17EE7C6B20686EF155E8687618CC37681 +:1020700027A9DDD6602ECDCF1E0B783C48FBD01CA7 +:10208000F7DBCBF63AF1E9487B7E849E647FC4930C +:10209000AD767E14C303F21268425CB7C474C7E71E +:1020A000B87E53FE039D6E273AADE17A64CAB9F358 +:1020B000367A2B0DAAD42E91EEA0DFA3D46FA1E81F +:1020C000C79CBAC55EDF168C443628A48F7E48EDC7 +:1020D000BCA08FB26CFAE8C7F43E411F4DAAD41ED3 +:1020E0000F16C4CBD07F3795FBF6EF0C26D167D007 +:1020F000FEA734AE47277CCD9BAC3D89E589D70B45 +:1021000079020D0B417E5C23CAE977D64FB3CA9F93 +:10211000C2C751DE2CD625B3FEEB8F237F1F0F09DC +:1021200079736429CA93983C62358FDBE4119B7301 +:1021300027D6C7E40F5BF5188E17933F6CE6E328AC +:102140003F82F3845E3BF3188EDF522BC6BF25120D +:1021500044BBC421FAA744900F7526CA763BF27798 +:10216000D3FE65A9D56F62EC5F1ED32C7EC689694C +:10217000758F931E3486B0D3820F72FBF2BB90032F +:10218000827E847D78EAE093BA01ED5654686F59F7 +:10219000F7256667F672BB276E5F9EE7F6F7C0DB32 +:1021A0008FA769FE7C4E6F5FC1F8FFCB3ABEB0A728 +:1021B000E0FDBF59DF5F6DFE1CC0E70A21BD4FE4A3 +:1021C000F05D41FF8C10AE2FC0F5D4DF00DE6C9ABD +:1021D000CFF403AE427C064243AE6AF84A09BE2AF7 +:1021E000BEDF2F6A313A2D4F4E07974DFF73695F5F +:1021F0004AF9BA2DE3CEA7F755822FD4A4FE3AB4FC +:10220000BBCDDE2ED6FF7682CB1CF722FDEFB4B716 +:102210008BF55F6EA5CF01E0F3D5D6FDFD0AE4484E +:10222000238D3F8A8FBF328EC7EF58DFFF67DCEC0C +:102230009274DE4EFBDEC0E9E932ECED9F60FBAD4F +:10224000D25E3D83E24486C0FB3F23DEE17DAF0BDF +:10225000DEBF65EEC79345E19FE17B2CFAC75BFCCF +:10226000136309AD2FEE9FC040F9567DAFB75BF504 +:10227000FDA1505D3BC22B97F0F6FBBBDE5C86EB0D +:102280004F2C835D7280D6930576C918B24B9EC7DA +:10229000F2A5C605F8BBA8DFB39C6E92D4BF42740A +:1022A000F514AF6F75713BF6EDDA8FC98ED3D6A8F2 +:1022B0000EB4E3845E3F1AE27E00D82315116F5FEF +:1022C000BBF1684812783B4AE3EEE5F83F1696D337 +:1022D000D1DE8CD92DEC55F283E276D55DEDB88F49 +:1022E00071BBAA81CAD3CD7D3E13BA779909EF0994 +:1022F0008E07733D976EFF1EC1E1E7ED93D49FA556 +:10230000F1B2399CCC7BF80CFAAD44AFFC37CA0172 +:10231000E5556621E85C549C05764BD74E4945321D +:1023200059B94BECF3FA769BDF68F2E162938E9534 +:1023300092E665185F58FC89E0FF437CFD313FB5AC +:1023400099E07FC78C4F3C8CED397C9F12FC2A872B +:10235000EF2B18DF55427619C74F0D339C689789CC +:10236000F382C4FDCD287188FD4D2F213B99C355C3 +:10237000A34B64BF87579C7222BD2F3DC6B464F443 +:1023800031A4C425E24F43A8BFD7F46F033C2E9479 +:10239000D87E78492C5E359CE0F4F1F936148547F7 +:1023A00060FF69FAD192A17C6B3C688F864BA5488F +:1023B0005B0EFA37DEB25228CF73B05EF2FB18DB49 +:1023C0008C715FF7F30A6B0B506B55B1C475804B82 +:1023D0007F8B7EE422739FE7B1587CC581F11A4B55 +:1023E000FC86FC4077C9FD793B558ABB50DCC6E5CD +:1023F00097C9AF083EB482E223A9856E9F1BE7917F +:10240000B3C9CF75FDD08C172DE4FEA503FE433B69 +:102410003AB59191FF36679B1451A1DEADD9E32FF8 +:1024200075EBCF37937FB782F934F01395427BBDBC +:102430002BC17F6D99A087104F6777D539101FC1C9 +:102440004AEE879DDD35D28BFC97E8479F453F9A42 +:10245000A4541F3FDA7800E36B163F7AED00FAD1FF +:102460008B4AC08F465964FAD1238BC2B7113D28DD +:102470001AC9B7AEE953E693BFBC4D666E687F7A62 +:10248000E7C4370AA16C6C5302186E78DFA92DC51A +:102490007A03FC69F97ADA2686F1ADB926FCA78BB6 +:1024A000CE9722FCDABDD70790DE4F3FE4263C9F53 +:1024B0005E99194983F132B6FD65530AF47F2532DE +:1024C0001C836C31FF3AD10F672C6220DD9C6623A0 +:1024D000581BEE83E26338AED290113002717F7BDD +:1024E0006E9ECFC0F1F4481AC37D8FBECAA4B379E3 +:1024F0008C8E1C908EE731D58985054C7322FE1792 +:10250000319DCAB701BF492371BE3C83E800F80E74 +:10251000E3774D13F4EF10BDFF88D307DBAEB4E3D0 +:1025200079C569E39174E4B33DA9F6788378B698E8 +:10253000FCE9413F7FCC80FAF90F5AE5C465C895A4 +:1025400047F87E727E7595301A07F4643DF279B7CC +:102550001907DE9EC9E3277BCC3849E213183E0BEE +:10256000FB7F513D01FAB29DE08DFBF11D08CF6567 +:10257000E8CB9F12DCFBF83A7721DC5CFEFCF7121B +:102580006E07A819144F01513C89EF2FFE3E95F4B8 +:102590005FE07CDA5312ED578ACA480EB95938CA3F +:1025A0008989E3117EEB87DAFB3D7BB17E6B827C10 +:1025B000FE3F16EA2FE0FCC5E78142A19DBB8AC71A +:1025C000C1E77AA5972535DEEE38C6A192ECF779FA +:1025D000538E42B3A803EC958733600FF2717F02EC +:1025E00083505EBFDDA49D441BEE7853053D7B9474 +:1025F00006921F3DBBE4C806E8FA4613EB2E1DDD2C +:1026000077DC9ADAE0C933167934B7EC090F08455C +:10261000D69CD77158C278BDE656DDD0BF3B3DBCD5 +:102620001DE3F5C651997502BCB72EAC3C79C622A4 +:102630001F12C785F998012CFB61894C701F0CBAD9 +:10264000A333308E60481194072B8C534E8C572E39 +:102650006D5CC674D82757E12905EDC29AA08FDAC0 +:10266000CF2D94996181EBF149DA7B8867A08B3398 +:10267000B4BF81981DF53E96834E2DC3971F8F439F +:102680008A7381174B9E22FBB83B93D1FC613F8B31 +:102690006C80F94BB465AE5E3C67F187296E7AB207 +:1026A00044A57957EE6C277852A7FD99E001DB39F4 +:1026B000EA18DC17DF820F8E9A786F31F1DE1F9EE9 +:1026C00095521ECF13E5B9654A3AE2F92D45A57337 +:1026D0008EFEF87B7EA97D7FDCFE0A5BB959BBD7F5 +:1026E00081F47476A71CC17D82E7EBB86F9FC0BEF2 +:1026F000B19CF838DDE9ACC6AA9FC5FECC29B5EF80 +:10270000CFD26D7C7F966E0B125E969656BA86F18E +:1027100073B5BD40DB4C2F5CC6102F2EED9482723A +:10272000ACBFFD027E1B568AFC6BDA8F57103FCF81 +:1027300029B5D8B55F757C1FE6BBA534899DFDB76B +:102740003A5F10F4740CE56A7E5CAEDE56CAE5684A +:10275000E253C8558B3D49714D0B1CCBEBAF000EBE +:10276000C127C8A728374A7648CEDE7CDC7FE0D771 +:1027700031689F7DB819F35156F919D14356A94ACA +:1027800074ED9A36CF85F278E5AE3F2BA8AF009F67 +:102790008B4B2D72B8A494093D544BEFEB395DFC83 +:1027A0007B9FEB003C77D3BED77238AFB673A7756B +:1027B000D5E18DA5740E0472C98BF1789FD04323A7 +:1027C00078DCFB8B9D6FBEBFF35E8676E0BC3FA5D9 +:1027D000AB6807DE5ED4A9E5A849CF3755C976BEF8 +:1027E000591762E45730161AC62E79BE99787EDAE8 +:1027F000F7BCD378B9392B6E77279E77269E6BB2BC +:102800007ECE3FFB9E771EAC2A02386705649FAAE6 +:10281000C6CF335DD3CE9E6063FB9E770E32F52E1E +:1028200043ED6D596FCF08756F14F3A38679021DC0 +:10283000BC399327C5F1087AC0E38679369501FC47 +:10284000682FE7743CBA80D9F0E8223C7C413CD246 +:10285000F936E265A714D988FD950603E5F94AE63D +:10286000537F1088EF676CBCBC751ACAE7EFD47948 +:102870009903F87F73D63D6C19B44F3D92C26468DA +:102880007F44BD87F6FBC847E92A9EF7BAFD967DCF +:102890003071A908F8E4BE7ED2DF601F3DC8727DAA +:1028A000F651ED28453D7BB9FBF76451F803E4632D +:1028B0000FE86B657CFC7DCF088ECFDE9B58A44370 +:1028C000EABB8F806F8DFCCE3CD6BE91EA1B18C64A +:1028D0000736498CE33B812E1C69EB0D3CD7762DE6 +:1028E000F7921FD5DCD040F83E0AF8367C9CBFF04A +:1028F0009CEA22FC25E88249432F9F2E12F7FDC84F +:10290000CE3AD67875EF6B3FFCB9BB14ED9ECBDDAC +:10291000D77953B59CB202EB3E6B23CB8658F9D6E0 +:10292000E07E0938C0E44F2E64AC33B3AF1D956F21 +:10293000E6A5C0785FC7F1C69431330EA88DC1F209 +:10294000821B5843B2BC976BCBB93F560B2622C5AE +:10295000558C54CABBACF5EDF83DE5611A37A9D6E4 +:102960003CCC3ABE0476FCE1F61EAC9F0B8B756442 +:10297000D12BCACB14F80995E5D0B845AB4FBDAE05 +:10298000527580C67781F0473FB5165F523E098B7E +:1029900074921CD0D97C90F777AC95289FB3C64829 +:1029A00063E8D7C6F32AF626E455F0F2DC6CB3DE12 +:1029B00078B1C37E8EF9DA72DB39A6D19BA0DFFE37 +:1029C00048FACF665F58F4D9072F7FB2DC50ACE7E6 +:1029D000989FD2F8276BC57CC1DDC17CEB39A66B13 +:1029E00037C223E2D4F0DB6D3DA704C8A92CE2C8AE +:1029F000A933B53A8C87ED9BA0AFC0FD914BA406DF +:102A0000B48F40C16812C56B7C1DE84F83FDBF12B7 +:102A1000EBFFDED70976485399E5FCE3EF0DFED3D3 +:102A200022BE6F1C5F8EF05DEDF002BE7F46F8AEF9 +:102A3000E0F8FE3B80F7605952FFE4AA81EF6D8217 +:102A40002F760EF1EF0ECF876596F38BAF7A3E6D42 +:102A5000AAF6BF71FD5FC13A1C33711D66FEC165E8 +:102A6000B4F7507BF3BC34B1BE69A6E93F98E7C424 +:102A7000EFC4CEF1AEADC3F17AE3E77A74EE153F61 +:102A800047CC1B89E78871F8F3687E718E189E79B0 +:102A9000731DE545F7738E391FEB4759FBDFB41BF8 +:102AA000F9AC2D613E9759BF6AE6448237BEDE0914 +:102AB000345F7742FB1A737D6B674EDD6D58F00112 +:102AC0009DA87D4C2E31AD0EE78B9F3B4EAFB39E44 +:102AD000DF7E6FA6B65B9CFFCF443A36CF69FFA37B +:102AE000E363C14C1EDF11E7E5820E474ED116228B +:102AF0009EAE367861FFEAADF4FF37986FDD4C0B80 +:102B00003F7DD1FE317E34F5BEC89F00FC1A88DFC0 +:102B1000A6723569BE84F013C3BD2C827ECB5416D9 +:102B200091F15C221CD019C641637C6D54125FBBCD +:102B300062F723E6ED46F917BF1FD1B61BED8BB840 +:102B4000FEFE559D3DCF616E9DF57CBEFD955F8976 +:102B5000753F6AE593811EFF7BE576BCC4CA267E7D +:102B600096DCFDDF46D8EF5F2CA679DE89DDBFA8B5 +:102B7000DB6DBFC7D0B0DB9EDFF15D3B5CACD50E3B +:102B8000176BB1ED574679EB6E03CA2E33EFCDB517 +:102B900042EAE77EC572920BE25C17CA36B940E59D +:102BA000EC8187EBB7828E4C3E8DC1D9273FEF9BDE +:102BB000BBEDF9790333BF452EBC8DFC30F078E7CF +:102BC000F73B04DEFBBBDFB15815E5C6BAFAFC2FB4 +:102BD0003F2FE6FF59E5C9975F07BF2FE24ABC2F99 +:102BE000C236D6D9E5CF65C3E72A4F2A7F2EAFFF7D +:102BF000A0F27EE58F0FC76DF63AE83E8AEE674990 +:102C0000EFA33495F373A9187F9AF751163C9CDC17 +:102C10009FFEAEE94F8B7877D0757E85F5BC6B74DF +:102C2000398F6FE796C7F25072697D8D1CBE00CA5E +:102C3000433CEF610AD380A7162E18918DF035FF23 +:102C40008E8FC7FCE027A7C7C7AB36E713F3BC34AA +:102C50002FBDC69AD730D69C27109F2F40F3ADE7E3 +:102C6000EB9007ADA67B5E31BFDAF831E1B5C5293F +:102C7000FCEC4EE2EF78DCB883E4CE22B7A0FF276D +:102C8000775BFD89DB7EFD14C9370C5FE0395EBCE4 +:102C90005F7BDDE5F42B2B37F5F12673BF8CD87EF7 +:102CA000CD44B82FD5DFE24747A5ACB81FBD6F8232 +:102CB0003607FB833F3DB7BCE0D2E3009E16119E72 +:102CC000D6DAFD114BFDE2725B5ED2F9D517CB4B24 +:102CD0005A61EE7B7F79492BCA6379242BCA2DE791 +:102CE0004AC17925E905182719E6487A8FE21E734B +:102CF0005FE3F95DBFA4F5B408BE33CBDB3379FDE8 +:102D0000B77EFD6C9DC9576BCA2DE717E2BC85E500 +:102D10001F8E629CC7925FA439AC719F92534EA4E0 +:102D200087A5DBA4A4F9337DF8A5D51C7F5B6C1FB8 +:102D30009BCA797C5FC7B8E36231EE3736D0B835CD +:102D40002BF8B8897CB3D5C4DFD6389EB6129EB4B2 +:102D500058BECD8358C69401F7F8F8F8E27E4FD0FC +:102D6000197E01CF755A0C4945F9AA372EA3734530 +:102D700056013C09FB141C96BB0D4587986F5C05FA +:102D80009F0FFE598AEDFCC042C630B06B2B96D126 +:102D9000B9F3248DE7AD4CAEDA200F5129AFE547EA +:102DA000B8AEA285EDCDB8BCDB6A7F2127CB67E941 +:102DB0008EE5B3B0B7460D05FE36E1C37B216B61EE +:102DC0009E7762F92C5565EBACF92CE12F97CF2259 +:102DD000E27F4B428057CBBE8D34D739B282E33588 +:102DE0007E0ECCE8FCF6465633EB268C2FE3BD2D49 +:102DF00078DD6DDE73BB90CD2278FEBF617A2AC587 +:102E0000F17A33199DABC28664544FC23C12FE4B1B +:102E1000195D4A715C37AC0BD781E7B2D1AFC1F015 +:102E200072EDA068127A7E234367012FC6FD8DCD17 +:102E30000CCFD5F447E87CEE86157FAEC77997EACC +:102E40006E15496071BDAF8CF2B856079CEB300E21 +:102E5000E9979986F1EC2AE77BFC9CC643789A5B5C +:102E6000CACB022F6EA6BC67C58B92506E3CB16177 +:102E7000CB214B7B5734251DCF05DF2E4FB7DD2BE4 +:102E800062B297E8E082DF11C173A86E85752900F0 +:102E9000479D2ED3F97BE7B635AFE3FDB1A57E257F +:102EA000E0807596344A94FFB5D8C7F1F49726634D +:102EB000CB21B0615386E5D239CC059F87A2F12D95 +:102EC000B59D14B7077AE95630AFE70199E1B9B774 +:102ED000C87F9A67D28BC063CAB28F092F17F03CA4 +:102EE0001CF1529849795073001FAA8FCEF93721EF +:102EF0009E525943F41A98F756BF83452D7168586E +:102F0000BF2D8F0CC6A6BC3385DED8EA093FA90FBA +:102F100094F07C34B92A8AFB7AA190EF2B94034871 +:102F2000EFAC94D3A9C07F6A029DBA13F2C312E931 +:102F3000B40FFE2BEC78EF5458208AF4764C26FB25 +:102F4000A277A7924179573B1D9477C55884EE31FB +:102F500075B2C18136949B5189CE096E33F126F04A +:102F6000CE58C3E6E518E76EC80860FC9F391A36EC +:102F7000637ED4E2481AE5DFDDCEF6521ED41DE8AA +:102F800021C3BC77329F0BCBCB59809E12CBA7FBC2 +:102F900025B7EA12F185CEA2D53701FEA2D7393383 +:102FA000AD7955FDE635C1CACF5ACE23465598F2C4 +:102FB000D2A3FB799EA76EDEFBD1283F28B3ACD409 +:102FC000A32791B7A545FAD72B0A2C7918BE064638 +:102FD000E7D345E1311543E2FD9F9AA08DC5F2E4A8 +:102FE00042ED166CBF07ED3CD0078B0E8F7D02F5CE +:102FF00059CB046D3CD627CAABD3FDE7DF451B8117 +:10300000EE7A505E511E613EF1E140E5DF9555F4E8 +:10301000C9BF2BA7F598F977279DFC5E19E5224FCC +:10302000657DEFA735DE46F5E27E5AE2BD34F62334 +:103030005E8605196DE3F0FE6E03AD5BE03D113F6A +:10304000CCBC97B6C4FF4A8F347600F2D67C60DCE5 +:103050000DBB187D18FCFE72F59A9E2CCA235428CD +:103060008FB02587DF5FDE844D30116814B7070706 +:10307000557239BE25B3C11F80FA2D4E9E0FC3F283 +:1030800074B6604C7CDC4195B238176A403A00BB9C +:103090008FEC2561AF8A76F7997AA1B14212F7CE0B +:1030A000EEC7F696FCEE46DA0F6F34E210E776FCD8 +:1030B00047E740C27E383EBC81F269DC5A727BA190 +:1030C000B922A6CF9B69FC9D429F6B9B70FC19D7D0 +:1030D000F816229FB94A64D6817A6CEE5D24779FF8 +:1030E000C1BC51B06926EB1B4A86C27E3F52619E2D +:1030F00037D56722BA58B7C6F349A3C50D7ED47732 +:103100005B8625BFF77DB282DBCF13AF3F2FE3B8DD +:103110005B9681A7320EF167501E9BB1086409943B +:10312000C1DD3F84E7321EB4038A502FF2F6BE7A27 +:103130006803FBD865E22B7823D00FDACFA3EDF933 +:1031400048E229DA25E65B81284FC77527E6B98969 +:103150007CAB1EC5480F24817F6ED95A0FE56B6585 +:103160002FF7A09E6CD14A68BCC4BCB72DD96C04A3 +:10317000C29598D726F2A644BE9418F7B90A4E27EE +:10318000226FCAEDE77A0B9E942713AD50CDFBBB9F +:10319000F6FC36915F83ED29BF269BF1FC1A7F0375 +:1031A000C37E6E2863FBB0997F9698570572E8201E +:1031B000D1411FFB88919DD15264E60D306DF332F1 +:1031C000B48FF0FC3690C4BE0281807AD005FA0933 +:1031D000EB15797505A6F27C593BAAB428DC83F07F +:1031E000B9FC3139FB3B82372E67DF35E5EC09ABA3 +:1031F0009C75BFBAF509B4BBB7489C0EB700DE9FFB +:103200004E421F1F98FCB6253339FD7C6ED26BCB26 +:1032100084F08738BE96C5EF777C513BB3256E6747 +:10322000723C0E909D09F8F8CC2AA7011FFF2F19B8 +:103230001EE0B709E58625CFD45959D07F9E696233 +:10324000FF2BBD277C0DC80DE43FF0077D95E40FF3 +:10325000723A16F2387EDFF6CAE4F53107C85180BB +:10326000076D026BFBDC4A2EE7C64DD5732B492F49 +:10327000F3FBBE5B83FCBE2F8B6AA4F78FA7EB35F5 +:10328000C8A72C6FFC25E6DB60E6D3EAF56192F374 +:10329000F32FD17EA339BFB9DEBCC1A43FB64ADA51 +:1032A000AE54395EBED4FAAEABD42623FCCD7A98A8 +:1032B000BE97B025CFA11AB0B47F9AAC17E3FB2D0F +:1032C000791B69FFDA80E024909B731CE71FCA9585 +:1032D000281FF85969103C3DE0B125A1EB59959C98 +:1032E000EEC18AA57A7642F35BE31C6B4DFD16CFE7 +:1032F0000778FA09EB3DA61595FB5618163D86F1A1 +:1033000092A793D0C5C24ACE3FB27B8D4D4F26B611 +:10331000BBB5D245ED56569AF10853EF2D72733F67 +:103320008A1D01F82C7A75DCD4D0EDB4AF063324B5 +:103330008B3E14FA8F6A2CEFDD7E7EFF841DB38FE7 +:1033400023D6799F49A7625EA0D755C81FA077BF33 +:1033500081F388FA4532E3F18E6E3BBE009ED59C28 +:10336000CED88A587E96051ECDC1C78DC1D1638740 +:10337000E33E733FC64DD5EEC371401FAFC3676BCD +:1033800008E82D095EC71784BE8DF50A335A73739A +:103390002E6AAF6EC076A26CB1579B2BEDF6EA2673 +:1033A0005C2FC8D1CDF87E4F6AF2797798F81AB0C1 +:1033B000EF065C269F3F88FF4CC22F6DBDFBD2C637 +:1033C000028BB9DDC6BDC497F9E32FC1579C8FEFBF +:1033D000BCBE81F4DB0BA6FDF1829329985703BC98 +:1033E000154896EF73B452D81B91E18897E7FAB16C +:1033F0003762EDFAC9ABFF1ADB9176257647DBB46D +:10340000E36964777CD29186FAFDB933A1A476C7CB +:103410000BD93B8627B33BF6F76377BC6ADAA7077D +:10342000DF77911D517C8EDB1DC5E776C8683FBCF8 +:1034300059A9D27A8ACE74CB3AC05D8C76078CB308 +:10344000DFB43BB03DD91D9FEC9011AEA273DDD42B +:10345000AF18CA687714F56377001432E2E1D9E255 +:10346000B67FC5FD4B5CEFBC897A8F956E0B7BBB3D +:1034700029BE23FAB5E56D4CD369BFEDF4535AA4C8 +:10348000DAF2E20B7B39BD27B6EB8FCECAE4AAD6BF +:103490005E58D75696BE83F2319586C7B16C180A2E +:1034A000FF3E1E7E5F039EF7CF051832B15DC34F0E +:1034B0007A51AF186E1F7ED7E02FA94BB99FB396F4 +:1034C000F99C53E37288960EA01921733C97C7D7D5 +:1034D0000C76D2F7D332088F8D3E11CFD951910B94 +:1034E000FDEFFFDA28BAF7137A040682F2D46332CA +:1034F000D58BF8CFEBC318E5E703FFCEA986F127FC +:103500009BE3839ED3EE85F68B4C3B6CA6ECA5F635 +:103510000FE6F1F6538DF3F5582EEA75A978BF8CB6 +:10352000C9EBE5BB316E8BF608B47FF0F9709907F3 +:10353000EA538F032438DE0917C52F447CA1E0D855 +:103540005EC267DA19972DAE910A122F6AB15B5CE1 +:10355000096526D70E4A269FC433310E71ED2CD350 +:103560001F1DCB6EF91CECAC0B6C7D2BAED13D3A24 +:10357000747037EBDB5FC419CE4FD446CC827D1C10 +:10358000E5D4C96FD95F01B8867DDABF73E7ECB1C6 +:1035900088F71D0AC5754F7E3B8DF6E9C0234A3B6F +:1035A000C6934E029FF2F8ADB112E9F5403A13E727 +:1035B00040518CCB1D88DD67CE5EA959CAE35E2BD6 +:1035C0007C1FF5E08121A2FD8F79BD281BFFB4127D +:1035D000F3360E0CE3E525AF3DD369101DF72AE461 +:1035E00057379EF626939F9366DBE9784EE11A4E95 +:1035F000C797E807F27EC6AC24FD52AAB97F75A032 +:1036000016401A8778D24B67015FEFEFB9A7750CA8 +:103610004C3571DAB7BB498E5ED3BB3699DC5F306F +:103620008BDB53D1E208F95BE0C3737F97298730C6 +:103630007F750E53C7A35FFFF0F4E77E3316E6797C +:10364000A368F47839095FDF3D2B97C689C37754A7 +:103650005E8E72E9A3F716269303DFAFD417DBD78C +:10366000C3CF479B772884FF0766FFDF2730EF2112 +:103670005ABC83E277FBFFE460E8AFEC1FC3ED7E4A +:10368000BCA187DFA51C00F8764E4E427700DF5DB7 +:10369000B30AFAC2377936E3F9A113B56F617D2217 +:1036A000BC2AC6B9015E30AF022847523EFC2FDD6E +:1036B00018CFDCDFEBA0A0CA85331D3292605B4FD0 +:1036C0006E299AAB33AA4EC94852C5BE4736E3D1DC +:1036D000AFBE5EB6F1DFE49E545BF98E866B6CE59F +:1036E00025F5C3E3FCC8F01ED0485BD9EDBFD95621 +:1036F0000EB209B6F2C2AAA9B6F1CA7C25B672B951 +:103700007FB6AD7DA5BAC0569E9DB7C4D6BE3A5011 +:1037100067AB0FE78F53F00A1FD0E5F771BFD38E69 +:1037200069C4E75B7AEEF1215D448BC3E44F1F4F20 +:10373000EFCEC678F5EBFD7C57EED42CAECFEEBCC9 +:103740001E4C239493A0CF3766C6DB07737B6DF1C5 +:10375000F8C3B3B87D7A7056623CBEBF7B705C3FE5 +:103760005FEEFDB7443D3CF7A67B482EB52D942374 +:10377000789FAA39EF2D2FDE1B7B7D218F23B46527 +:10378000C33ABD948F41FC7570D16D23F05C2D352B +:103790004FBF06E5BFD0DF257911761AEA537D11B8 +:1037A0003612EF9741B9CEBC675692CFDFDF68BEC5 +:1037B0005F854FD0DB332DF84AD4C741CFB897C1CE +:1037C0005D60D3FFEAA3EFF72DCCE7F19ED24F2245 +:1037D000A5789F7AB6F6D2217E6D9ACB9F378AFF65 +:1037E00098D58FDE7ED3CEAF47891FF69F997F5144 +:1037F000F9FF87261E5F7FA6C9C3A2B0BE134D3E48 +:103800007AFEAEC94FEF8F36A9F46C69CAA367B4CC +:103810002940F5FFDA5448CF434D1A3D5F69AAA00D +:10382000E7E1A630B57BADA9869E479A747AFFF191 +:103830002CCE97570B3C5A9E8827840F3A24C2EB14 +:10384000424CD59D724E93ADF21DF0FA6932BC5ECA +:10385000A91E8916EF1D1EE67A2A291F0D9D2DEE41 +:1038600085713B798E4E323F069F0BE37359F1F819 +:103870009C1B4D9AC104E7A0D9050307E701337EDD +:10388000732093D53CCDFDBA4D12E91BDF382ECF06 +:103890007F100E913C1F322EB93CCFE923CF979178 +:1038A000DE6287316E8A6945288CD7E1FCC9E32145 +:1038B000C6A09C8BE281CE2B051E2CFB15B8123CBA +:1038C00024AEBFB4489B8CE3E03D14E7E0BE7AE44D +:1038D000C6DECF348C493D9BCFE17DF8BDF983D066 +:1038E0005E7163308AEC1570F00A71BF99698FB40C +:1038F00077D667F71DE70FC57B49AF3F18B3739EB7 +:10390000203B26B11DFC0E111E506F59F090440E45 +:103910008493ADBF4C7EBE7723F43FD0CB285EA608 +:10392000A24D0DF03FA7F0EF341C38E7203C5FF0CC +:1039300048241FDD0FDCEBC1D8F6B3DFE5ED8C6A60 +:1039400089EE2FA475ED57D14E0DF6EAD7E0F7C6F4 +:103950000AA3954EFC3E6868DAB8408A850E428A12 +:103960005D4FA2A51AD33B140C1B9C50BE2EDE5EED +:10397000C6FDCF8D9773E8DEF53FCE063A9D7FBE3C +:1039800081A9F9667C35399E564B96789BC202AD6B +:103990009373C8EE3C741D9EDB8C661199E8CA20B7 +:1039A000FF5BC02B7BC3742F4FF8E99F4ADAFDB34E +:1039B00093D80FAC5EA37337E670D0B95BD304BD68 +:1039C00069369DCF279CCBF85EF93F12E8B45607C5 +:1039D0008BA27D6164B8087F89FB35B9B07213AEE4 +:1039E000CBFFA5FDFA1D92F53B0137AA33C89FBA5C +:1039F00000FE14DE436956F8FD28E3447AA4938060 +:103A0000647968B7DD2FDF1CC0FDFF7EDAF7C83FA1 +:103A10006A047F0BFDAF6DA61CBE3F35A383818278 +:103A2000DAE66CF81F58DF22B17007FA5B29D74736 +:103A300058461CAECED95C9FBBD91D8390CFBCBE6F +:103A40009927CF4C48E6EF71FFC419DBF76C1FF9DB +:103A50001B66D9EBD2FD98F7D8326EF52EBC8F6578 +:103A60000CF1F0F34E25ACCE03FC3C64DEAB653EBE +:103A7000836559EEEFCB4C398BF1D9563066F07C2B +:103A8000F79709F038AF101E174A18F447B35C11C6 +:103A9000CCAF51511E015CAD7E07F1CD2695F3FDF3 +:103AA00026AFE6F125D9B72D884777FFFB29E76CCC +:103AB000F2611C7B87D7417CD9AA2A5B73A0DCEA20 +:103AC00055F8F75A554745B27CAD8F6673BB099AD6 +:103AD000A4507E53703ED931FDCDD366EEA728A702 +:103AE000E6EB1AF18F1A08E37A9ABD5912C63745E8 +:103AF000FDAFCDF1459C78AB6917A5E6ED8D62BCB5 +:103B0000A665D8AA09882E0FD83967E1BD277F2F6F +:103B1000D9452D433C35C9CEBFCECFE671B6ADCE2B +:103B20004005E2736BBA831980BFAD39C9F5608F68 +:103B3000B97FCDEAF830D12DE063B4D4B7DD6F4C56 +:103B40007DB9D9B9C38FF7D0B68EBE95F2BCB68E0B +:103B5000E072B7F1C889CE0DF9C80FDF62FF86FCAD +:103B600090A5D0BEA92CE041FDD5E2537CE8EF4FF3 +:103B7000CC5AE7095AE497A0FFED6887C0D3396CA7 +:103B80007E0DD2E385C2D40022BD4C3E42DF0969DE +:103B900009803CCDC13CA4069FF5FE3FD8D37215E9 +:103BA000C0951E70D8ECED4185767F4165BA87E8F7 +:103BB0007318A7A3FEF62F111E2F4A9CF117699FB9 +:103BC000A9D724FB2EC9B82A8E574137CE4BD0CD6A +:103BD000A5E0B7E9BBECB8BECBA91AB10ACF2F1E3E +:103BE00062BC7EE491F39DE8AF2796BF2C7F362B15 +:103BF0003B481E378F72113D25F6DF9AC3E1F9600D +:103C0000F647341F861570DF323D3C8EB4BD7070B0 +:103C10004A32793B6BA25E5465B18B324BF7921EF0 +:103C20001D5CC5087F5E35EC1B05E3788FC940A39A +:103C3000806FC7677F3DA55E391E951D0D2CCCC7D3 +:103C4000233983BFCF40BE6598FA64CB0D6F30CC6B +:103C50009FD93E5209C89487702470313BDA5B6863 +:103C60008F137DD138504D95998F92C252781E5046 +:103C70005548A1FC1B07D79F1AFC3FD4BCC22E9904 +:103C8000FB3FD43C5A52F1158F7F65D5325A4F2CE9 +:103C90001F05BF2783E3E88CEC0CBC108BEDAE5BFB +:103CA000CDEDA86CD62BE1F9DE0D98952323BD73DD +:103CB000F97981653B281F07A6C17C12C97090BEA7 +:103CC000FBAF379C9482F0767BD1AA71B83F89EB29 +:103CD000585365C6B362EBB8381E049C034DA74227 +:103CE0002F377BB89ED54021A7A0119C10D72C93CD +:103CF000D7535CB3C570FB500F372BA077B3A877B1 +:103D000098E2A00971CDBFA4F0B8A7B48EF9A4229F +:103D10008A6BE6E13E35B2D400C61D0729BA07EB2F +:103D2000D346298CD355C3643C3F89FBDBAA97E774 +:103D3000BF35529EE0AF50AF41BBAECF2E2E8FF6B7 +:103D40005D42AFB51D1BE5A5B8B9A72E0DFDEC670B +:103D5000FCB947D06FB9E0E1F95BA25D57C2F74CFF +:103D60005A4C39D75365C6C753FE2263FF197E5597 +:103D7000C13CB990671CC9F76629F93940AF29DF02 +:103D80006E54DFE474B65A7C876C35C9FF77D34D27 +:103D9000FAADD79750BCD8B4E398A6A9BE4971FB39 +:103DA0004DE84BBFE233EEC271CCFCA93EEBECFA1E +:103DB0000786DF57617E4BDC3517E71F14CB9BC3AB +:103DC000F913EDB6FEF0D966FABDCDFE10E55D5CE7 +:103DD000409995E45C443CC1FEEC463955D06D9762 +:103DE0002F697976F9D2EA68A03C2EE366E6C33CF7 +:103DF0000F5615F05BED5FB0438F571133DBEDC904 +:103E0000FBAAB9BCEBCA54158CBF9478820CCF1BAB +:103E1000946C9DE17EB8FC818BEEC7CFABB8DE6FB2 +:103E2000C95B1E467FE5E1E9DF24BC4CACE079A527 +:103E3000A21DE8CB0FAA2C7E8BC83BB8ECEF23F970 +:103E40001C948F78B9F1A1B6692BF9F791FCCBE9F5 +:103E5000FB48CF78F8F791BAD2F534B4BFBEE8F793 +:103E600091EEAEE6F41AF27CE3E08C5C0B9E7A7481 +:103E7000CA0771F9CFD3B9CC0C337F24310EE47665 +:103E800037D0395AB4B86189350E2CF0F77393AE38 +:103E9000FF50AC539E4F7F7FDF41B4438CE1BADCCF +:103EA000669C734BF1B709FFF32B3229CEA49871AE +:103EB00026D7799DF27A3B27EAD7565BF49D3BDB08 +:103EC000207D97F63DC6EFAF7FCAEFAFA76D6421A7 +:103ED000BCAF1EFA6C3C9D3F85A229C467D33F0945 +:103EE000D0F7A7CBE4A75A73A1BEEB9842DF85EFCA +:103EF0009A9E9A857AEDE363DCBE4DEBBAE9C82D54 +:103F0000502E3E5687BE3EC81D806570DF754CFF43 +:103F1000C4F1A5FCC702F41F2DE72062DC5F361D4B +:103F200026FAD8D7D44DCFFD4D517AB635F5D0B35A +:103F300050D14A703D85DD7426C9A69C817A0B1C40 +:103F40008527A0BF851E864CD4B56AE2BF6E5BBBD9 +:103F5000B4BC1E5B3BF05F4BAB0B308F87E3D3856C +:103F6000DF0D83F1E7F6B0CD92FA1F4A5EADAA1ECF +:103F70001879F58FD505179357FC9C34D4637E27A9 +:103F80002C811F1DD52AF90D31BE34CF4B859E6E75 +:103F9000C57F823E6DCEF826976FB17C0C7EFF50B8 +:103FA0007C677EE3EB1FEDA1BCD277CC7A83FD4426 +:103FB000B3D433F6C92ABC0FF2123AAF60879E7BA6 +:103FC000BD6B15DE9BBEB52653D100BE123C58CD4D +:103FD0008CDF7F11798A8978FB9FD59CAF8FE7FAB8 +:103FE00028BEDE92CBFF5E4162BB37ABB9BC409AC4 +:103FF000B0FE1D8FD47EEEFDBC2AC635F1D6EAE2B6 +:10400000F907FDDDEF78ACFAE2F73BFE60D65FEA38 +:104010003EC72FCD795FC4790B282F720FD285F858 +:104020003B1B51F37DECEF6BF859D2717E6ECADD0C +:104030001BE7F8CCFDD414F33BD47B893ECCBF877F +:1040400020EAA79C8BD5EFA3F9627FF740A7F88FF2 +:10405000B85FF7F3EADFEED960F99E574BEC3B8986 +:104060003C6FE95313FEC4A7B85F12FB1E147B6BB1 +:104070008F66F91ED44FAADF396B7EAFEA10C16795 +:10408000DEAB79348E875FD3FB84EF0374BDFEDA39 +:104090001EF33ECE6FA8BE21F1BB5BEFEDB1DEEFAC +:1040A00079B4FAD42AB3FD515AA7F99DAE247461AC +:1040B000D2ED993D789FF032C67B97C633BFB3B53A +:1040C000D9E4A3FEE819DA9FA2F6B1EF0FD7795031 +:1040D000AFC4EFF1BFBBC7F6FDACFEF1F5475AB771 +:1040E0002EE665667E13E717911F26E8C23B87EF31 +:1040F000C776931FF0FE1FF55F316078F88CD69578 +:1041000070AFE852EBD837212CCF4138FCB1FC62BC +:1041100085CA5F121E711F2C913F86CF91445EF3BA +:10412000609A273BF61DCE6B06625E1877048D13EE +:10413000FFBEE7F57392CB9F2F342E532F2F6F4482 +:1041400094FF3F19A999BA607100000000000000B7 +:104150001F8B080000000000000BF3176060F8518F +:104160008FC09C687C5AE3BF4C0C0CFACC0C0C97AB +:10417000D818189C39191884F8C833E7229ABE7BDE +:1041800040B366F030302C636560D809C47A5CD8DF +:10419000F5D90822D847817E5F01C417E91C06A320 +:1041A00078F0E01A11068649A208BE9E18AA7CADD6 +:1041B0000882AD2345995D4E40FD008850BECB80FE +:1041C00003000000000000001F8B0800000000003A +:1041D000000BD57D0F7C54C5B5F0DCDDBB77FF2728 +:1041E00037C9029B10E24DF863D04037103058D4E5 +:1041F0004D041A90D7AE69ABB1A576A14A151156F8 +:104200006B9567D5DCFCDF841002A202455954107F +:10421000ADB6A9A2B59FE5BD0D508A7D7E9FE8533E +:10422000AB56FB62A5B45AA5F1594AFA7D086FCE88 +:1042300099B9D97B6FEE6E962A6DBFF86B87B9F38B +:10424000EFCCF93767CE9C99956C6E52760E21A70C +:10425000E1EF12421EF21242C6A4D2CAEF7DF986E5 +:1042600027AAE8BFBDCED04E9A54FE626E71B4222A +:10427000557F1611B05EED2F96FC91D07AFF4EEC73 +:104280008A937EDAE71FF486685E15EC04DA394912 +:104290004DC1BF0468F9902DD445F3C993361FA1D1 +:1042A000FD4C2776E8842844F645A6D1EFE29773C3 +:1042B00089AE7F737AF16691240B08D97F27112389 +:1042C000B45E9BFF8225033E425E6C4CFEE5C864F3 +:1042D00042C2C9A9A242FB39D07808F3FFD678F8C8 +:1042E0002F471C8444491E8E533BF72371296DB719 +:1042F000DF411AFA68BBDAB0E058AA1B2FCAE7B34D +:10430000DFCDCBE51AD1B2DC4FCBE9F7DAC0E596C9 +:10431000E5513A23AC97C7FB191AB0433D850C7A97 +:10432000719E27EB2DE7398EB7D3F255036CBEFB98 +:10433000DE3E7119D0214972234E484F96BD05F8D3 +:10434000EE77090A29A5F81D5884F84D027E6917F1 +:1043500027DE61F8DEFF892DD444F15DEB927D21EB +:104360009A2722A5072DAFF59130C225D294C271AC +:104370001987FB2A9ED6438A7451902EFD2E4A1728 +:10438000DFE8F05EB2594278B579F6C33CB368A76E +:10439000D1957EF545FCB41DB1E68391F8A1E3CD3E +:1043A0003C733835BC46E6F6FFE5888BE0DF69FAFA +:1043B000BFF9F2F37F39529ECA5F3274D890A71CBE +:1043C0004D5CB329BCF04F0552F1CF035A79292B2C +:1043D0008771E28DCA9F2751FEEB6D247F9E44F9C1 +:1043E000AFA7D185F9EE4619F35D8D41CCC745DA0B +:1043F00084D231DE4D122A6D9F17A6F575E3E5567E +:10440000D3763AF8FC21D990F796070DF5DD8A624C +:10441000288F2B37DB1294EE9D15B6845D0038A8EB +:104420008C9C0B70B830A5E0BE16A4F399C49A908A +:10443000750EE5576500CF4B76D24CF3394AD8B6A6 +:104440008CE64B82769208D1F1730609A1FDC5EF87 +:10445000246423EDAFBB72B66D19CD77CD71CA76EA +:10446000999004ED3FEEA4FD9C4A2A2DD0CF34292B +:1044700004FD905EF1B7802717FDEF741921131525 +:10448000E91D5B0E21A52AFDAE9F9F530D825CE7BF +:10449000561BBF4F5496DF4868FD8944F7BD34452D +:1044A0004F6D5C2D6F1ECF3CCE396B4CFD9BFA2DB2 +:1044B00051066AE48A54BFE790C126D9F7CFDC6F72 +:1044C000B856003A858892A83C7B70FBD67C9C77D6 +:1044D00064660ACFDD0EA607CDF236406CA83F8891 +:1044E000388684295C8A624B74D17EBA4A6DC83F93 +:1044F0004A1B4980DE5A37E1700CF25DA592D24C1E +:10450000F3A5E5071B84E984AC9D2023DF75ED75D9 +:1045100092E610832340F9B444E3D353033565C0D6 +:104520008702096DA4E5A5CAD126A82FBFE6511CB4 +:10453000D523E747D6B0F9639ECE7F10FE316B647A +:10454000BFBF9C258523C0B72A4938293C9D939A33 +:10455000EB543ACE03AA48407EBAEEEC7B1DF01C29 +:104560009FCCE035CFBB449196025F13FDF874BC3D +:10457000924957DC00F332C3A1E98BEF37CA288F89 +:104580005B1ACB317DA051EE033DB1E513BB257E17 +:104590002F13987EDEEA88D8003E758E2DB113F574 +:1045A0004F74EBF5347FFF77C7CE8075E0E6393680 +:1045B000D42F7FEE66F8BE5FE8BD8A607D49C1FA00 +:1045C00026F97F400C377F8BD6BF3F5840542ACF07 +:1045D000258EC30BCF85FED69455AAB4BFFB6FD9E9 +:1045E000F80EB42F993345B1D3F613AB8FBE4517F0 +:1045F00071B2E5D44030E2833C93EB923563FB2605 +:10460000513E19AFF4DE04E397544B4AA234C597E8 +:10461000C52484E39CD3E025497974FE2C5E9999E6 +:104620003FCF9E1EF8FBC85511C855410AEEADDCC0 +:104630003E31D37DB160437E1996AB6A26574F5EFB +:10464000C8E8ACC9D59609BDEFE5D27CCF37189F35 +:104650009AF9BCB4FA680DD0B59BCA4F7E909042CF +:10466000A7F2B140F33D4BB91C561F1596D3F67F08 +:104670007AD5A31090A725D6FA3A1D3FA752E3B8E2 +:104680000FDC62AB8DD07ABFBC76CA1F9D30DE12C4 +:10469000490139EB11CB717CE5BB92A2EAE859B232 +:1046A00084CA13E5AF925BB8FC98E46AB4F1E38D79 +:1046B00009F22E95A30D8D4112A6745BDFA8A07C94 +:1046C000ADE37206B62829A4792E67A47C06E6D34A +:1046D000D99F8434A1DCB994248952FA6CA07D93CB +:1046E00022F89E0C87E712920FBAEA42042769A3C8 +:1046F0006BFBFAE17212A64C4F7A049E57FFA88614 +:10470000E9787288E59F6BFAA3DA428570839BE5AE +:10471000F70AE535EA5C7DFB83D8BF569FE693B583 +:104720009374FD41FF157A786C35505FEBEF8DA6E1 +:10473000A21A958EBF9EE7A5E63C963FCBFD770B70 +:104740007D41CAF464ADA99F6E81E349FD8F70D8A5 +:10475000971AE73EE1BDB06A28FF4318F0A495FF21 +:10476000A0E93F5495D6FF8844B608940E33E64539 +:104770008B08A5BBB72E49C094DA60C2776A7E2F3A +:10478000E1FC7C152CFF60D32761C0B756FE8CE09E +:104790006F027C03DFF8C6121244212164F3CFBB01 +:1047A000AF7F01FE5D9E4FC81C3A8ED24B14DA8754 +:1047B0006D524C807D47708978D4200F9CEF287C07 +:1047C0004F08349D3137FA35580A2DE053F5F0691A +:1047D000E38F06AF06477AFE64E39BF9A87641F5BE +:1047E0008B73A97C790F3B424E05E6210BA0C7F3E2 +:1047F0000128AAD7F24EED473A11B12F0876B4B985 +:10480000DFFC794524A19BE7674DCF2D9067787B2E +:10481000454F579A7F4D8FC727A0DEAC917CA7CD1F +:10482000CF0DF3236007D3F955E9E7F75403CC2FF5 +:104830001DDECCF35BEFEE6D8858E8DF8B6D7CBF3F +:104840007B71F597A07F3A1E01FDE5560651FFCA20 +:10485000301EDD6AE69EDADF005BDB74E3C973E9D4 +:1048600078E5670F9FA3F1B18FEA2F85D6B3853224 +:10487000F3B1599EB5797B61DE02F011DB0F98E749 +:104880004D08E523FFFFBFF3FE5864F4BC85F6AF87 +:10489000B27931F9F807CDEBE3170A505E011E3B00 +:1048A000E3E7A0157FBD2B28867DAE99AFD3CDEB76 +:1048B0001FC5A723E79519CF675B0F65AB5F9B5FAC +:1048C000F3201E7BAE61FB849E43F3D1EFD0F3C295 +:1048D000A5E3008E9CF8F9244CEDDF29D03FEDAF25 +:1048E00047B32F36578DD23FB32FEE6B247DAD9358 +:1048F00009793A6700F7C3144E6CBF95DA9F09AA8D +:10490000E0AA5EBAC5BD948EB7F5BA8D6EF02BF5F0 +:10491000707BB1EAA587372CA0F81C776D7EA59D2A +:10492000B2428F5BFBBEE7F929F4FBE66BF877EE4A +:10493000BFA2DF5F82FA415E3F1D5C85D2403482B8 +:10494000F242E1D2E15F2B7FCAC6ECD227C1CE3A58 +:1049500017F633CCCE2AF4F42E05FAE66C959407BC +:104960008591FDFE6FAE4FEF033B8DCE77CBB5ED5E +:10497000456057EDDB317BBF0FE0BA86A03E3F3785 +:10498000B1ABDFA1C0F8AA00787ED241343B0BD78F +:10499000F9A26B34BAD60B974EC276DCCE62F9EF31 +:1049A0000FAFAB5F47BBA538CAF2CF347FB7A64580 +:1049B000D495ABDFAE0917A7CA5F6CBEB106D6DDD2 +:1049C00019AEE89B7329E96650BDD742E198212AC8 +:1049D000F618F0CBE680A5BDB8FB79574382E277A5 +:1049E000F78E2913AFB55847281591CE5A7EE62188 +:1049F000A39C3D09F873021E99DDDA4DD10BF583B6 +:104A000051A505F039F31009C17E349DBE4B47C74F +:104A1000E036A3BE9B211AE775B6E6F31191D97E65 +:104A20009BF74FD7F5976D6C3E7690A3992293FF35 +:104A30004F3B9F24E089D911BFB1EAFFEF35DF1961 +:104A40003E3A4EE0B31F27681A275DBF667DA5D6A4 +:104A50001241047F7C1109013C79F36204FCF87671 +:104A6000DFE1A04AED3D511EC0D411180CAA54EF4D +:104A70004A41A510526771A810BED3FD11978F8EC1 +:104A800026D4ABC3F9CE26D0A3EB218FF2B716CB39 +:104A9000370EE7D761FEEE094C3ECFB1DFD30F7A78 +:104AA000B80C940D856B5DFF1B0DE0072838E00BFB +:104AB00081A951E00B11D0C35A794FFF7B4117D820 +:104AC00071077CC44DF93D5F0E137DFBF5FD7F0D35 +:104AD000CAB4DCC7CB7D8188A17C63FFD4C22045EA +:104AE0009187977B82512CBFBB7F4EA10276CC0170 +:104AF0009F0CDFBDC5311CF7D25FACB4A13F76B1CE +:104B00002DE1D4E9ABF8E219A8DF9708D1A9764ADC +:104B10008F9A5F74BBC07E881FA81807DFD1E6415B +:104B20007F92F87F613F0AD9D36807F9E4A3E7735E +:104B30007AD953F4E886F30AF403B3738A383FA7AB +:104B4000506B9349185FCD6174A21C9DF23F63FBCB +:104B500043297F35E60F1BF27E3911867DB418A0FC +:104B6000FA81B6F786D530D05D2A6679BB2F9404DA +:104B7000FDB1F91B2404608B149F507FFD1C9A57D4 +:104B800080FE116CDF398BE5A56054857CBC92E515 +:104B90009DC5B124E4D74E65F9CD1A9DC9A3463E03 +:104BA000207F42BA770EE7DDCD501ED7F886789B7E +:104BB000A17CED454CCF168935FB00FF9BFB3B0BE1 +:104BC00097D3FE73811F68FFB94B42482F8D2EF794 +:104BD00029365C6F35BADCA7CCC07382CA5C8A09FF +:104BE0009C9082F4A83CE7669B0CE71DE7DB123B38 +:104BF00005389FEA760FD07A9BCB6760798968E7A2 +:104C0000FE01E60FDFC9FD0165D4BA00BB63275F73 +:104C1000AFF7DD332517DAEDDBFABF90DE17DBF3F4 +:104C2000B0DDDA72767EF32C5DA7C14FF74CA30B93 +:104C3000D31FD1FEA2545F3FD1E8C2F4078D32A644 +:104C40008F523D0E69372D4F82DF81962769BE6FE7 +:104C5000C05607F27F4F2335CD68FBBB1B5D1F8B12 +:104C600093C15F21637E7D6310F3DFB6D5AFB133AF +:104C70007F8AB782CEEBE99727A17F2FF4862D920A +:104C80008079CBA4607155EABB869F6FDB6AEF0425 +:104C90007EFDE18088E31071A0EB7CEB7ACD506F54 +:104CA000FA1B22EB2F30B0F1B28065BD0EA8F7F8E9 +:104CB00011063771253D69FAEB06782BDEE6F00523 +:104CC00093F969FADB00F51E3BC2E1F325BACEB3D6 +:104CD000AE772F8C7BDEDB1CBEE2C4C645D6E37EFE +:104CE0001FFA73E5337BE573E0CFA8C2756087A038 +:104CF00093E74D4B55C146E9EC2A188841BD6955EB +:104D000031A18C8E1FB83A26D8A6313BC346F36E2C +:104D1000E887A6E797D3725A6F1394FB75E5D09E88 +:104D2000A6532B5879E09BC6F261BDDD40343B357C +:104D300009CED6E0578CF92936A61F9FB3FFB606D9 +:104D4000F87D8AC4CAFF1BF260772D36D5F7B0FC18 +:104D50006FB5FA39ACBD4D6479573E9B77CE565747 +:104D600002ECAE0DF3DB83CB7CA9F9E62D889743EB +:104D70005E9BDF86055B83CB74F3C9FBC2B6F2652D +:104D800015E9D715B7622361DDBA3BA5B782840B5D +:104D9000FEF9F5CB5775EB06AC2BE3F8BA30AE9ABB +:104DA000AD2B146F2AB35719DED65F64C45BEEC512 +:104DB00046BCADBFD888B7DC4B32E3ED977CFC74C2 +:104DC000F8A3E387F5E36F5C681C3F7F9171FC8D6E +:104DD0008B8CE3E75FF6A9C74FEAF9A6B7C638BEE2 +:104DE0005C6B1CBFB7D638BE7CE9A71B5FA34F67BF +:104DF000FF16E3BA5E15217AFAC5FB3B8386753D43 +:104E0000C4D675AD7C6DFF4F83B0BEBB617D07FF1F +:104E10004C395BDF2BDFFD28087EFBF5171D0CC22C +:104E20003E633DAD7BB822B56EECBBE856DB63B4A8 +:104E3000DFEF4C65EB4CFF45CFB840FFAF2D67EB84 +:104E40004C9C9FE77635268FAF74A4E6E58FBB7147 +:104E5000BFA7E587ED25F2BB1AE0C378B98DDB4B20 +:104E600085CD616A8BBAA68A867C67052BBFBDB5E6 +:104E7000B059055F8AA816C23AE42D277FAEB0D894 +:104E80006F69E36BF0A41F9FED8B53E34F348D3FAD +:104E9000D130BE96774F63E5AA38A916E0D9CCF792 +:104EA000CDB788BF43FD72F6E09BD61C9EA4878FCA +:104EB000E553F0B1BC06DF5DE2F45A75D2DF13BEF4 +:104EC0000B4CF8BBC084BF0B0CF85B23569F11FE44 +:104ED000CCF5BA4DFC790309DF268E013922686FC3 +:104EE000C644999F07B1FEAA442E5F303EC4ED2C04 +:104EF0009512934B59793D5DD796887C1FC6EBD7A9 +:104F000099F29AFD0ACBD169F4C358DBAF12617AEA +:104F10009BDA1DA19DA8D743284FA97D07F363887D +:104F200062241CB1D007F78AEC7C5890430D00A78F +:104F3000E893D08F9AAE7EAF2870FB5A359CEFE491 +:104F400092C1A41DE008128C4F2227BFAC5C3E6DBD +:104F5000241C921889C2387659220FD2715AF3AEA6 +:104F600050F4714C8F6AF004C3088F2433782431D5 +:104F700014B6F2033F2832BF85D60F8590B71F24A1 +:104F800060276AF0B5B9230D4BC19ECF93104FAD8A +:104F90007EE379F96FF8BC5EE4696B9A733F02D1E6 +:104FA0001810BF34B61AEDD096EA5A17F0A542424F +:104FB0002EF0D7B7FAACE389B4D46C77C6A95D0AF2 +:104FC000F9766A9742DAEA7BB20ED69DE3C0C7163D +:104FD000E7DAC37A2E642349DDFED35BEE214983F1 +:104FE000FF348170BA957CC37767B0C8D0CE315694 +:104FF000447BBED5674B40A8D168F0B773F8B57A4B +:105000001D62CC2567B15F76068DF09E3DFCB1F642 +:105010005E479F6C05D76785378DAFCCFD4B05523A +:105020000CED623112D4F3BFDDC1F8542A70C5987B +:10503000BD9EAEDCC3DAFB6839D8C5BE8802E72F57 +:1050400054E4314ECC0572A0C3CF78DEAED5C1CFCB +:10505000A3490CFDB582126B003E72154B783E6081 +:105060006EA7A51EDEBEE393EFBC8EF231C685F2BD +:105070002128547E2CC6795C0C8F75D074B3181E11 +:1050800007A9E3943D6A2527631C4C8E5D9188E255 +:1050900062A12696F0CFE4FDF66AF0AB313CF7CA88 +:1050A00016FEB22CE19F99827FBA6316C2FF39487F +:1050B000D3C13F8DC3534042FDB06F0706857E09C3 +:1050C000B95CD19FCBF5F07E0B387C84DC8474D343 +:1050D000CA3B391EB29DCFDC2CE7D3939A4F1D9F5C +:1050E000CFC24CF3F9029F4F8F83AD57AEBA8812EF +:1050F000A47C959F862ECB79FF5B87E972D319F14B +:10510000D557B39CC7F2D43C9672BE5A96691E51CD +:105110000E4FAF9DCC3902F13313F97A43EA0D7487 +:10512000D9AEF19593AD1B84DC6CA0CB3DBC9F6CDC +:10513000E7B33ACBF96C4FCDE77B9C2E77649A8F1F +:10514000AE7E13AFDFCCE50AED96ED8EBDCD607F70 +:105150003C2E46DA1DB352E3D17A1DFA7AE3DBBA6C +:10516000B47A6BE1BBB078B85E371F9FDB450FE1C7 +:105170007EAC0D6C0C6ADF7CB1EDC55AB0C769BB63 +:105180008DD87F84AD9BB4DDDDFAFE67B6DDDBCC68 +:10519000EBDD07F59A2E3DA5F5BF59DFFF764752A7 +:1051A00083631BC25137DCDFFDFA7ACB1D7DCDEC6A +:1051B0009CB0583EEAD5D935C1ECCE7D1C81687CC7 +:1051C00000FC95C4DF0B7647BB18DB3E00FC408D2E +:1051D000BC9DF4FB6DCEB020D0F5530EC71E817A76 +:1051E000F9AA53B603DD6A633F82BC6A2311888B38 +:1051F000BCCF7BD776C8AF115DB23304F696824739 +:10520000433D0111E379DA84A80AEBE20931FAACF3 +:1052100003ED1EDA251DE7B60225D12580FF96088D +:10522000CCEE60706DF05E1D07389C142E880F6EFA +:1052300033C145C7C37D79E718166F4344522E42E8 +:105240007F764F08FAEB1F732BC21B6F72CAD03EDA +:105250003EF95684979645303ECF1143783B1C2E3D +:1052600019E2F1EEF3AEDA0CF1766BD45CAC8F7030 +:10527000C0FC279621FC6E124B2E2D05F5D51BB6D2 +:10528000013C8B258C4B8E0736E2FEB66B315DE41C +:10529000E8B85DE51B5568777CB107E3EBDCBE5EE3 +:1052A00002F15605974904E280DC815EB433F317BE +:1052B0007958BE98E038F99F67F1B20E322097D145 +:1052C000B420CEE28EBBCAEBD5A560C754B37854E8 +:1052D000A2865F86F8B63CC2FFECC5FDD0BF63BCBA +:1052E0009DD84329FA16F40EB7CF8D5AC8CB70BD9E +:1052F0004496F592D9D5CB8F8BD9D5EBCDB25E2222 +:10530000CB7A4956CF492ECFB58AF718E6FB7912EA +:10531000DA1F5A7C5B0EB5FC87ED935266B7EBED56 +:1053200015079152F60AF0997D494638D6BCD51436 +:1053300038A0B36F02923F80FB8D0BC8052897A35E +:10534000B43FD1A8060E38469F2F485852E7271F72 +:10535000ADFE5AB0F79CE9CBBDD3AF08A23E9BF699 +:10536000359E2E616925FD5E016903CF7F8DE7972C +:1053700034842DC6AB91981E2E27918C747073F8CF +:105380008FC2993F6D522ED2FA16E7E35AEAABB0BC +:1053900099EC46A3BE73896A2D9E7394B3F8412796 +:1053A0000823C84D88A07E7190A45C86E78BE19CA1 +:1053B000A56353F2E3088E45F9F93F85762254231D +:1053C0007D428047339F98F9C267E28B4FCB2757C6 +:1053D0009D253EF1C6ED59C98FB737CB7A892CEBA5 +:1053E00025B3ABE78B0BD9D5EBCDB25E22CB7A4997 +:1053F000566FEDBF48DCDF7A590BF861BC5F74195A +:10540000F26BBFE831967FC967C8772F34B6F72DA6 +:1054100032B6EF5E646CEFBB8CB57FAAFDAB9782B2 +:105420009F275B39F9DDDF2827E5AECCF5F3178F31 +:1054300022572E15F7936E5121C900AC5F749D124F +:10544000300D272CECBBE7B9FCBFE0607E9CB8A810 +:10545000E2BEF69F7D9E3F9098DF489BEF68F06A22 +:10546000FAF7F7766E6F99EDAF61BFCEC9D3A76734 +:10547000831E21102C4D64854E8DEA1B0FF1842074 +:1054800054C4539EC0F36973FF5D705EC7FC2EC1A8 +:105490007A1D1CCF3B995FE5E7A5ED413CAF9DBA76 +:1054A0002B08FBF4AE0982A59FE594C4CE05CBA2E0 +:1054B0005EB4333A1417EAC3AE09EC1E5397238146 +:1054C000FEE3AE52637B17B71F4E496CBCAE3B6325 +:1054D00004ECFFB6A9BB1A605C67F25F8942E1FE8B +:1054E000EE8418C68FB63BD93EC0195609AC0B2EB8 +:1054F00045C5F377333C712D6E882482F5BA79D790 +:105500003B19DFFC9CCE279B79BD2B49585F0E339E +:10551000FCA5C3D7DE33C4D7B54ED6AF127423BEB5 +:105520008E57135C4F8090F6D9048FC6D9DF20D1F7 +:10553000F387793D060A337E3B8D7945BC2A233FAC +:1055400099FD30CAB6AF65E4E70EBE9E3BC9D7B140 +:105550005FA7120B83BEF35624C832C42F0993B140 +:105560009CEF14F8BF56D546E5977241682B6575D8 +:10557000EF98CE50D2227E6998FE1592515ECE7081 +:105580003D9BE9A4EB9937B59E1D27DDE884EDB678 +:1055900091EBACF0AEAD674AE0AA8CF3EE6A647EA4 +:1055A0002B42EE207D309F57EC481F5B395137501E +:1055B0007A392B443CE7704E4A10A0B3AB9C24DDF3 +:1055C00039E9E7F51AE73B259879DC1E8EEF6E4E38 +:1055D000A774F5BAF9B9E76B1D0FB5C0FE2D6F1EA4 +:1055E000938361BE171306FE1C92985FA3CBAD3464 +:1055F000613C4B29F38F8C983787D32C57F134F7C4 +:105600006934B9FDABA4303DE44AA0DF41932F4596 +:10561000F957D4735D139A5DC0D471E541F4131F3B +:105620002F9708DC8331EB032DD5ECC84B48B70B23 +:10563000EE2BAD7DC51EEAB280D70D44D0F9F5CC76 +:10564000FA7A347D72DFA7D4273FD1E47EA43E41AD +:10565000FA5CDBD1BA1FE8D3E566FEEBFC3A952C89 +:10566000D5CDB79B8FBFC4C9D7856206479743AED8 +:10567000D1D3298F7EAFD1EBCD34F44947F72B211D +:105680001870560A0EF3FC763959BD7C18BF627447 +:105690003C8CA403C3438BD39A0F3EABF9343BB38A +:1056A000E3E36DBCDE368E576D5EA3C989D67F1FDE +:1056B000C757DE3C93DE175503FDED1ADEEA4CF5C5 +:1056C0005CC67A1A7E4427B357B47562B4FEDF967F +:1056D000187F98FB4F2787BF19964315FDB2DA381C +:1056E0004EF21CFA0F8E53BDDC5549F7A3BE418C18 +:1056F0002FA07B7D8C6F82F82FBDDE35EB2F4DFF09 +:10570000A7D347E67DCB68F5A58094D14ED2EC9A1D +:105710007C7E6FD2C5E381370AD6E73C435C8EA816 +:1057200062CF2AAE0FC244001F2442F8FDBF707F33 +:1057300013CD8F0D494A17F83FC4F9FD3B687ECC65 +:10574000CF9CA42B042E9779FDFD94DFD6865D11A6 +:10575000281FE72A1DBEA7D53B1BFC5ACCEE22F61C +:105760003B5E877BC063AF1409E0D549E6609CF6D9 +:10577000F13594769523E1192B12323E9FA6DC3F3A +:1057800080E787B0A5FC8A119F64B12E0F7E6097D9 +:1057900071DDCB76DE6678D2B51B159ED43EF4085B +:1057A0008CEF2499D7B5339DDFB05D9BE5BCB4FB8E +:1057B00068DAF7D2213B51E07EFB9080E939435E05 +:1057C0004C4B86DC984E182A200A255AF1501EA60A +:1057D000E387C6E3F7A2A1424C0B8726621A1C2A74 +:1057E000C5346FE87C4CE5A1A9986EE072983B3413 +:1057F00013F3DAFDB79CA14ACCFB873E8FA96F68F3 +:105800000E2BE7E7A91BEE8C12F0574BB00E51F9A7 +:10581000689BBF1CD725F3BC36B8D83ADCCEEF095D +:10582000B79BF4761F2F7FCCC5E47E03970B22C66F +:1058300088DE6F7E3FAFB7A12C8AF677BBB61E1607 +:105840002E37AC87E6FAED69EE273FA395737848CB +:1058500079FD28F461E7AFCE4014EF0D101245BD7D +:1058600044C4A841EFB66BF067798F70C3FC6790B2 +:105870008FDD549021B4D0FD856D0D0F83DE5970FE +:10588000EB7507A8DC7DE88CDEE68271BFB002997B +:10589000EEFBAB6E0F82DF77C3FC7BF17E1398DFEC +:1058A00010D7DCB1E08ED8C3C87551B4B369BBBBA7 +:1058B0005CBA73D0CEE5B737ECA2FD29AD36A2E8CD +:1058C000F8B5E40E0F51F4FAEB644121B42FBE2574 +:1058D000DFF0BD686591A19D764F22784D99A19E1C +:1058E0003CEF3C43BD9CB9338CEDF839B9AFEA428B +:1058F000433BA74FC32B3B47A4F437AC1F1D823556 +:105900001D632EA62FD3F1CD152EB6AEA5FACF4C22 +:10591000B774FD677B2F24C51F69E781E710B1F8D5 +:10592000E279604F39E528DE5339F3FA67771ED9FB +:10593000D633EBAB1CD05705A04F044C7DA0AF0A6B +:10594000408FB831D5EA9DE97DDB75A06F7C3A7D4B +:10595000338BCABD053FF8DC99F5CDF9BC7CB29B11 +:10596000E99B759CAFCC7C13E4F5D681BEA9185D8C +:10597000DF04DD99F54D251FEF1FAD6F3A67DC1B86 +:10598000FD16CDB92FD8D6F0104D3B2A6FC53CD5AA +:1059900017A29B9677CCBE23F6904E8F9093FFC9AB +:1059A000F892F3436EB5517F68FDFB43263DA2C9D3 +:1059B000C3DF28D7A738BFA6A3CF914F29D7A7CE3B +:1059C000925C9F7275CD83F3C56CE57A64FDB33B41 +:1059D0008F6CEBA9B5247909EC4BA678122DE0BFAA +:1059E000B4F586D8BDBC28C6ED743EEFE07E1EE659 +:1059F000FF9BE10A2F02FE99E18A2C76D3F63797B6 +:105A00002AE3609DA6F92FC2775D3E62CAD79BEA62 +:105A10007FC594BFC254BF415F1E57947170BE18BA +:105A20003FE4C0F3C1B862ABB3E2A7856EC62F876F +:105A30005C9128F4776EE2BC7140179A5F86FDB9DD +:105A4000597F347F8D29BF1CC74FE5AF3395AF30E9 +:105A500095AF34E557E9EB779E9A781FBEBFF14BBF +:105A600007D969E14F7A95EB898EC9B7479B995C55 +:105A7000DE06ED3BA6DC115B46902F08C06DF79962 +:105A8000F67F94CFF4FC7288F7F3F309B7E2BEA96E +:105A900083EE9F308E11FC7816F8F9B59BBFC3A535 +:105AA0005C8FF71FE28537A39FA3A3B819E3148E79 +:105AB0002B129ECFC64BADDB7736323F5347B1F545 +:105AC00039C2AF210857678F9049CCFF076270DA5F +:105AD00006EF0931FDDE56DA8EFA554A5ECFFC1B21 +:105AE0008551F46F3CC8E927F962E8577016C72C56 +:105AF000F7F51DC3F830FA35F769F8E0FB481D3EAD +:105B0000500E9B3B3F3C00EB6BDC6D2D673F7633CB +:105B1000397304B31B7FE4FCD9FAB01D2EB558ECE1 +:105B20006BE30E1627AF4E607E00918EA3F72B9885 +:105B3000C71B9EA7699FFD00C753DCCDE2ECB5FEF5 +:105B4000CCF03CC2EB3DE2667E056D5EA2CCC61990 +:105B5000ADFFE7E0B216F80164B31FC2A8E7EEE0BC +:105B6000F51D0163BD74F8B973183F2C1E4BE3DFBC +:105B7000D1F85D1BE710C085FB59EB7DB872B21AF6 +:105B8000E3378E137F6F17EC9B45F97588E3B88D6B +:105B90006E93C0CFDF22AAE85F501522EFC4F34F07 +:105BA00076FE709BFDBC10E83B178FAB20105711A1 +:105BB000D0C525829FF35C8CB37804CAD7A84E1950 +:105BC000DE3719724F6471AB27D7603C4527DDA9DA +:105BD000C3B827DC250978CFCA9EDB8DF6BCDD5E15 +:105BE00019B38A33153D8C6F2F39B91EF56CBBC2C2 +:105BF000EEDDB48B51577E05B8AA5594D74E257368 +:105C0000FCA2390ED2219BE30F8DF89AE661F48D48 +:105C1000F3F537EE0E35E8E393821E37960FB98D14 +:105C2000F075007C3E802B86F1A4F1629B0DF0762E +:105C3000B6E0D3C6954A6D11C04B8044315EC515A0 +:105C400014715C9B97E137DDB844113FD0BF1F73DF +:105C5000B6F039BCFE46193F89C483FCA4CC73D589 +:105C6000EE86FCF3CC2F6F1EE788277A8147E71773 +:105C700016E528FAB7B4FE168E6171DE6231C1FBFB +:105C80008A1289D495D2F9B714B3771645DF2871F3 +:105C900011C5667F45BA7339763E824554446BFE22 +:105CA000C0C6F5F078013F19C060D15C50E91321FE +:105CB0005E4011D83B102181C595CFC538F280FBDD +:105CC000B3EE7709F62B843790D3DE33E8571C40C8 +:105CD0003FD767DEEF28F0BAC936EC1742534F17AB +:105CE000A4FA05FD8B4EA593A74FC3B9999D687F74 +:105CF000CC0E176DEC5E1529CAC1B8C3B6C0CD2E47 +:105D00003D5D9B3C6586F55592DB6F1272E0DEE7E8 +:105D1000CAF04006BE6C0339023F62F135E181F200 +:105D2000F4F53438453A7D2B7F68BB144D3481BD82 +:105D300058E263F1AA620CCF473A84FC195D553AE8 +:105D4000FE2D96920097BF2AAC423C6347812D04FA +:105D5000715822E93E8CEF3BD9178732C9AB582CDA +:105D6000BEAF9FCF568F310EA465147E6FE3FA3A13 +:105D70005DB9430A45ADF4F0131EBE8E79ACCB3F3E +:105D8000F6D63EE6B15877F6723DD5914755E9E72C +:105D900018FB001F88C5075F073CB48D5990593F19 +:105DA000C946FDF45FDEF04F609C0C703C67050750 +:105DB00081C714B2B0FBE579188C988A070A30BE07 +:105DC000863820612C9CD2B2BF75550F26C1EE7665 +:105DD0002CF585817EF6F06E02EBA81617640F7B1A +:105DE000DEB1213DE7B2F8A072E6670DD3FF308E39 +:105DF0006C6EE6B831BB29FF2B339D1B9FC5F72284 +:105E000034F8B53875F3BC9EF2D6BEED9965858F32 +:105E1000ECF6419B28BF10CA2F1BE9FA4E91427A3B +:105E20001B65CCF7340631DFDDA860DADA588EE97D +:105E30005A683A07E23F62F152D88F041F0E5E4B58 +:105E4000AB6C029A605CCB8EF9B08FEC1ACE135516 +:105E5000807325B81F4FEDD0BF7A36CEE7E76C3C94 +:105E60006EB67D3E9EA30DE7B7B4815DD8C5E368ED +:105E7000E5B50FCE87FDE3A609DA3E39ECFAAACEE6 +:105E8000FE9AEC75B073A652AD7D4B1BF4E7167904 +:105E90009EEC996FCC9330C0E376B1FC42EFD3080F +:105EA0000FAA003ADEE5DE6730BF6932F73B54D413 +:105EB0008F8247E6C768F728CC0EAAC8473F8514EB +:105EC0000AC1F502B2298FC39D653FB0FFC1F5EE4F +:105ED00015EBF5322537A3AC6B1C8ED1E84FD18181 +:105EE000F605E86115C67DD58EF270B6C7DDE438DB +:105EF00033BC48D5832A5CFDDAE7895EE4A5EDFD75 +:105F0000E1BE6429CDE72C4EAA28BE598E5BE8E598 +:105F1000F7C9E87C41FE353C6B76C74D40C731A9D7 +:105F2000FE1C8130BE23E1E6EF09670BEF728F6C38 +:105F3000E8873C5E5B98E9DC654CC4064146C3FAE1 +:105F4000A2A0CEC38335583E2F9C6FC8E7561719C1 +:105F5000EAFB43658672877C9EA1FC6FA5D3D73D83 +:105F6000B281AF23A679CD379567DBAF7B8D5D819D +:105F7000F7204B45CD1EDD88F7928F038E413FF60B +:105F800056E23D5D3249BB8740C210AFE256C2C8FF +:105F90009F1E12C2755A2A36DAA962C068A7061B6C +:105FA000D4A4D62FC425B8D74838EEF03AE563F12B +:105FB00020DA3919EED72782AAFBDEA152D6CE32DB +:105FC0009E414B457E5E8677EF4B473F4F358F13A3 +:105FD000FC4AE63835737DE21395A33AF94BDF4E60 +:105FE000244775EF6AEC00DACF4AE13FBC7B29FA1F +:105FF0003D9C84DAD114CF2DC12B4894CEB31DAA79 +:1060000050FAC521A57CDE1E9C21631CBEC2E86A35 +:10601000733139F98E5731C473D87D4C4EB47AA39D +:10602000D1FF363B8959AD67AF7AD93EF9C45DB12E +:106030003FC1FE527D99E03BAE7D8D43F8CE655564 +:1060400072A11DFC26AF7BC7E27CAA0E84ED97EA05 +:10605000FAA922ECBD6FFA67D7FB5335FF3039E957 +:10606000C2B8E03D491617BC27F9DFFB4F43FE904D +:106070000DDF15DD7338B37DD5C7ED2BAD5EDF21A8 +:10608000B65FED1389373F939DC3EFBF55264D7122 +:106090008722B103FD4FDCA9D8C1DEE96B7409B0DA +:1060A000EECFE0F3AC4A86EDB09E8E36AF7D26FA99 +:1060B0006AF384FB8730CF561FBB0FD82AD3F9224F +:1060C0005FB3F7B2D3C13BBCEF97ADF121F9D9BBB8 +:1060D0001792232A5BCD7BB47B8A1A7CED009F004C +:1060E0002983AB3DC0E8D01ECC4C87160E9F56AF1F +:1060F00035C0E8D04AED836CE0117D4678A88D2745 +:10610000805DE823893A7CD34C252FC33E08558512 +:106110000278D897BC1FE0857B1760CFE75509D779 +:10612000C2BD8F28B30FFD55C9E4DE009A2711B810 +:10613000975130D09F7C9B961F6CF0E2634FF2B575 +:106140004792D08F280FA2FC74C160681F4D6C0766 +:106150007BA70DFE4955FAB8EEE002B03F44C2F409 +:10616000029538451CCBED130B79D79DEF0BA79DFE +:10617000A976E9F066B63B9DA43EB3BEE2E7FD2AF0 +:10618000FD0FF48D6CBA1F61B673CD71F017813EAF +:106190001F93C53D8C4F394E2E79D005EF21D8CBBA +:1061A0006D32BCC34C557A1EDCFFF1864502718D01 +:1061B000B9BE017C3A6B34BC53FD57C7E246FB883D +:1061C000FE1E69BD8FF98102F55582C0EE1128F0DF +:1061D000EE66A0FE50C88A4F35FE1CCEFB9E44FDE5 +:1061E000D8461271883B51EB6CB8AE759597E5E9CE +:1061F000F74737F904BE0FD5E84F1471768AFE745D +:106200007E61F7F4BF1FFDF3171BF17EA674B9D3AF +:10621000C7F4D268F4FFB4E368741B291F4D9C6E69 +:106220009B50FF754ECA4EAFA4E8F620CAABB79C90 +:10623000841316ED9A39BDCCF7F65D2446E0F728B5 +:10624000ECAF307BDA3E6E76C30E92812E23E2AC49 +:10625000583F761FF3A7AD133C21186A5D1AFFF271 +:1062600024BFC0F5FF008BE79B733008E7C7DDB3A1 +:106270008E06E19CA3E713EB73C8857E7E2E127E0B +:1062800003F7013DB3985F10FE40EFDCC6FE49CA3C +:10629000D4F736C33B66EBDEF21AECA1F6C6CCFEB1 +:1062A00006A9E8BA28D81927DE1114586F84A23538 +:1062B000E7025CFD7396E3BB23ED55FBF01CA63BA8 +:1062C00094992E5A9C6FBB29DE36DDB9E1092EAFB9 +:1062D00065EA0D685FF614BE8CE3ACABCA3C0EBC3D +:1062E0009795299ED7652351F4179BCE75DFE4E37C +:1062F000BDE9E3E7138EC8972696C2EF72A8E81FA0 +:106300001B5B1EE9B751BCD5FBA3AFF9285D7BE64B +:10631000DC5A0870C03B317ABA07A07F0BF8C6FA86 +:106320006D06BBE94459ECBFEEAC82DFA79882EF63 +:10633000D66BF5BAD3C4B19FA7D15971E3BEA71DDF +:10634000E2FE297CDD85D9E15FA3F325E405D7448E +:10635000680F71BE19F8D9BCDE8F8677331E7A1CA0 +:10636000031807D52358CF67A19FC95DCF9D4976F4 +:10637000AE36E7289EABF9926F60FCC477671DC606 +:1063800073B5123FA387DF378071A539D5EC3DC0C7 +:106390007472F400A79F281BEB1171C070EEB3DD7F +:1063A000C7CFCB0299FBD3E024AE0176DE33522E69 +:1063B00071FDD9D9FDF0417C378524F15CA1FD55F3 +:1063C0003BDC4D1DC6C308B98AB3DF85E9818DC7A3 +:1063D0008530CE5DEDE027E9D1CED92AD9BE49ACD2 +:1063E0004AE2399BCBAF18E3AF43DABB88D9CDD3B0 +:1063F000076B11F30F8BB0AE823F1EE06BADBC029A +:10640000FD69E9E8FA1D6F74A67F8CDEAFCFF65DFB +:10641000FF6C7C78C2A718EC43333F3AC937CE688B +:106420005F97CEBF7C82CB67002AEAF649DFF44B48 +:10643000D6F87DFBCAD1F0FB4D6BFC5EE501784FD1 +:10644000DC63FDFB445ABAC5A4EFB668F128F0231B +:106450002185D85FE9E516F3D6D6D5137EEDFD9EEE +:10646000A807D68D3275AE07C6DFD5BDCC03E3EEE7 +:10647000DA9C999EDAF8DBF9F96282DF77D1CA13E8 +:106480009C2F7798F4FC2B5CAEEFE7F2B5CB15F1BF +:10649000E0EF55ECBF6AD1548ABF32CA17E05254BC +:1064A0003A497EA6F14B55D3BEE40CEFB5F4F84D56 +:1064B000F1BD59DED3FCB478D901FC7321E0E1DFF2 +:1064C00051EEEDC95C94A7B2958C6FCAAE194CC25F +:1064D000BE76E2265B42C1389628E2A570A5A86088 +:1064E0004C1BBFF77A2E5FDF89FD0E5B0994C3BD9D +:1064F0007119DC2EF2D7301E669BF1F73F76B9C2D8 +:10650000CD12D8BF718C742465DDC6DFCB184F74F3 +:10651000BF5741C72D7CEB3DFCFD9442D3EF827CFD +:106520005ABCEFFD07E13D21128F5E1F2B028958F7 +:10653000E9FDFFE47CA9341D60EF18C47CE45DDD57 +:106540003907A55F3ED805DBD58D35804F354E42E6 +:10655000932DF4D86FFD5EED777C0EC03B0B8E6201 +:1065600076FFAC6DE915037BA9CADA7E472DB13AF7 +:106570005FA17AE1B77E5C9F985E48A8F52C3D69E3 +:10658000473E99DC4D12F03B28F336C5FA1D20EA50 +:106590002BD93BD48571559068BE8C9AAFB47B32B1 +:1065A000F13AC2EA2F218930F211792D3836F57B84 +:1065B00027250337F5C3BEF820DD17C3EFA868BF52 +:1065C00057A2F1CBF898913F26C78DF971267E31FD +:1065D000B72F53C822187F52B78DC0BE6E4C83AE02 +:1065E0003EF44706DF7B848E3FF9003CCC48D3DE87 +:1065F000CCFD8B24EAC8A1F87CFA2EDF2FCBE9046E +:106600001FEAAE2D00BCEC721176EF22E2C27717C2 +:1066100048C4FA3C6904DF6A767F9AFA297DC9EAA0 +:1066200069EB5EC75B027BE7A2447EA714FC9CAFCC +:10663000B1DFAD4BBD5B7121BE5B112431663F9272 +:1066400008A6AD9C3FE54B8B4BC11F1A7FDB2BC3CC +:10665000FD2CB9C0E84F13F3EBF03DB061BB3B9F9D +:10666000DADDB43C9E67D4A33539CC6E0DE5B07B42 +:10667000A1B297F5435C6AA15EEF6FCA118CE53E4B +:10668000B5F0CBBAF25ADE3ECEDF2DBF24675107FC +:10669000D833F2785ADF823FE7F171B57212081DE4 +:1066A00086F73F367FA37E967E3DDF94C3CE77E4A8 +:1066B00073F8B8C5D670C54BD9B877F37137E518FC +:1066C000DF8D23324BB5EFF7FA6F158E507C9F703C +:1066D000905A88576919634BC0BB69B78DD5E2C220 +:1066E00032EB098D0EC3F896593C52D175F20CBBB2 +:1066F000851C6BE9D63AE6A7327FBF9ACFA3F5BADD +:10670000DADE4914AEF0012677CE00B13C07A2F2E2 +:106710007D75CE2C8B75BFB50EF77127F232AFFBAE +:10672000E67DAEC8FD8BE67A4D9C4ECA2B417C8A35 +:10673000BB35C8FC895AFF270A995FD1DCAED3D498 +:10674000BF9BD48721CE18CE57E15C559A4412499D +:10675000DA8F27D02B972A101F705885FD91422879 +:106760001EC1CF162268D7B506D97E540CF6D6D8EE +:10677000209E84D4C97A3BAC88FFAEA29677F8A25B +:106780004D39680F8505C48BC8CEF34F38120B0105 +:106790009F2DA53662F54E7F770EB373B72AF52F7E +:1067A000965AD06F438E62B09F8B8698FD9DAE7EC9 +:1067B000AA1E836F981F832ADE3F200AE3C77A7FD1 +:1067C000F89E1CABF35B4DAF703FE4B26AAE7089CC +:1067D00072E5AFE93CAE3FE4C0D8F44B4E6E3F08E3 +:1067E000FAD74EF56F17FE8E5CEF41F0435E03F76C +:1067F0009F68FEFAB7A64925B4FCB5223B7F743EDC +:106800009203E37E486CE82FF990BC9C335347BF5A +:10681000A77224B6DEC41DA847357FDCB5BD0E8344 +:106820005EFDF666637E39A91F0B7E8AE59B1C24FC +:1068300041F17BBD49EF3E94C3CE89BE4D62EDB0C0 +:106840007EB6F1F3BF1B7F324D02B9B97EA65C6AFA +:10685000D7DDBB7A2E87D977EF533E527472B6C21A +:106860009790601FF7EE9E99577C9E403F89F622D5 +:10687000F0A7E559C7017E2B6E8473B47998E1D6F1 +:10688000CEF3D2C121EE162CFD42CFE708067F7C65 +:106890008B8BBD87146E1189FB6288C3A3020B70BA +:1068A000BFE5C7F7BBD5DA18C6D5A9CD4EB9258047 +:1068B0007176184FB786120CDE1F3ACAF94F8BABB0 +:1068C000A306C505B04FBBD13520815F79B518ABA4 +:1068D000839F4ED3CE659C8E68783C85DFF16C4DEE +:1068E000723C31D48B6759EF90509655BD3A5B8618 +:1068F000FE8E713DF98BC71F9260FDF9F0B177BE36 +:10690000087278C373760257F38E3DEE2749DC3F59 +:10691000242490F3157BEC96EF48508C61FF37FCF4 +:10692000C88F7A71C593CEC462DA7EC533EF4E2725 +:10693000549E8E350F1E1C0FF87B4C60E785EAC015 +:1069400074589F5688E49B56EF8EB97399BC7FF0BC +:10695000536F03D04FD8DD7F35F6DB77A543FF2E8D +:106960003EC965EB0FADC7E2261F1512932DF487C4 +:10697000B61FFAE0511657B2E2594702428257EC6D +:10698000DE2145291CAB777F84FC72E98F9EC8010C +:106990003CAC7ED66EB0236EF8D127ED17523ADFAD +:1069A0006027838B418EED27317F3CEC1AB4A35CCA +:1069B000B3F89455A80268BDA77EBFE0D7B4FCFD2C +:1069C000A09D4088EBFB877F273D07F9A88F5A6E73 +:1069D000D0BF91AF57EF7E57C2DF31B291C1E2CF46 +:1069E000C3F987D14E32D7276450023DB5BAAFF311 +:1069F000233BE5B7D57B3E7C13F86EB5493EDE8779 +:106A00007F148EB4CF2B734DF6F9EE82ACECA31B42 +:106A10009E38FE00F8233E78F28F0FC03DDA95A72E +:106A20003E7EE07B1017F66F6E19E47BF563AFE6F0 +:106A3000109DFEBF2C97AD9BC71E7D64D7563AFFB5 +:106A4000636F38115BC7F6FEBE04FC3FC77EFCD700 +:106A5000B1E00FBA65EF7CFCDD9A5B9EBE745CA66C +:106A60007511F835A1FF7D457E6EA43C2B80314920 +:106A7000C8CF786AA207E91D94605DFB8B4006BB16 +:106A8000F2E8F7BE4F24B0CF0E86C920E067FF9E24 +:106A9000770FDE4EF31F52FA382DE843E73FDE86CC +:106AA000FA998A0D4D57EDF9F2972EAA82D4817684 +:106AB000F86A32887A73045D5FA174AD4AD1D55CFF +:106AC0007E9C9C94E0DC60F5E3948ED3819E948E52 +:106AD000D347D2F143F8C79C91745C916B8C4B3ACD +:106AE0004E566EDF0A857B0A2CCF79B57DD68D4F49 +:106AF0007F35A3FDA4E985D1F07C9DC0E09A9D1B64 +:106B0000BE3D17E4EBC91FECDA1A60745E4C1173DA +:106B1000EC89E32584F2C91F1C8357031E06F73A4C +:106B20006558DF57ECFD15CADBB1A75F92148C6F77 +:106B30002139C26C9A27C37F2F139A5F25B0CC8D61 +:106B40000FFFBF056FD2F637C2431E32D20FF307D5 +:106B5000A9FC213D1297D729A077136370DEAB12F1 +:106B60004C2E5625FABF02717D66BC3F956BD3F45F +:106B7000FF305D216E6CD59E771600FFA5A3A7366A +:106B80007F19E67F012D7FD828B769E594D3F7D820 +:106B90008E1312D807C9E724D946EDE1638E410967 +:106BA000D7C71FDBE59DA191744FE19FC71F9DE1F2 +:106BB0003EFC876639E7F8194DCE479FD799E16DBE +:106BC0005BAEC2F65726FC7D70D25AFF3FCFF5C6AA +:106BD0002A12AB2B9A3872FD1249441D5F9A82F734 +:106BE00003881FA3F07EF0981DF787ED7DFB518F82 +:106BF0009BF5C5AA3476F49BB9CC1E58F56CFF748E +:106C0000D06B1FECFB29F2E5AAC7DF91C07F737040 +:106C1000F753D240454A0E607DD0FF0ECE073FECC1 +:106C20009F0EFA6B759A38C0DFF3F9ACFE99B1FF8D +:106C3000D58F7F64E8FF06B54F423FD928E3BC2FCC +:106C400086AF84F9BE7FD8012718E4FD3E7B9D9571 +:106C50009DF3025F1F353CB5FB67BF9E0BE75EF9F6 +:106C6000EC1DC6D6A6F0AFF0F77B5F72F0FD6DF8B5 +:106C700075B0675AF224BC8FD0EABF02FDF55A7F87 +:106C8000BD267CCA01B906F603F2BC48957E5FA515 +:106C9000C19F17B619E0BFC55F374EF1B1FD9942EC +:106CA000F71FFF03B64D466E008000000000000095 +:106CB0001F8B080000000000000BD57C0B7C54D516 +:106CC000B5F73A73CE3CC24C2627AFC9D37892F0C1 +:106CD00094804312DEB40E0491226A505AA9F5AB97 +:106CE00003F28821C9A4F8E25ABFCB8444F4029F7E +:106CF0008D95166A693B70A152217690A0B10DDC8A +:106D0000012C06056F105F78B18D5A152B24631482 +:106D1000B4575BEF5A6B9FC3CC9C4C84DEFBFBBE2D +:106D2000DFEF0BBF76BBCFD9679FB5D7FAAFD7DE02 +:106D3000EB0C28DEDCEA5400D93D6B366461AB5ABB +:106D4000D41409E02BFABB2AD6028400C603585D8E +:106D5000D5E07761AB5A407300FF7D45FFA7785BB4 +:106D60007BF0F97BE5D4D6B5348FB5F157D48726BF +:106D700005B657F2B0914A25DDBFC2BBB61860A375 +:106D8000F39F1FA7FB2B8376D58E6D73EA3DBFA5BE +:106D9000FE0609AA65EAD3F3383E6875A8DB55BC40 +:106DA0009E0E0BC265317AF25424321BA00CE9A06E +:106DB00016FFFC3001DF2B488266A8031C0129590D +:106DC000A120B5C6730FAAFE62757CAC2FBBBAC1F9 +:106DD0008FF35E2DBB2CB4FE07732D217B31B537AD +:106DE000A641D9403E18ED03ABAA213262F0FBADBB +:106DF000D98E855B80E90E5A681D9223B49D08F1F7 +:106E000081A67A8069030DFF873C74C4D18D037C11 +:106E1000B40E45BF6FC565D14D3B04B94D213960F6 +:106E2000EB84084029D2AD96B05C52A1479F240A5A +:106E3000D563006E4CF57F93D6993BB451A2EB1EFF +:106E4000A8E6B612FC12DDB738EBF2FC5FB33E5891 +:106E5000A09CE919A9CB175FB1C12AF8AF28A00CF3 +:106E600029273A36ABEF8FC679E87E268D0AB21C09 +:106E7000C6557D67740BC181888FE3F32333676444 +:106E8000126E8C71CD8EA29312F2DB27A7A8294532 +:106E9000D8579033C4A753A9CCA71F4DC399F1FE6F +:106EA0008F4FA56E95511E8F48024F41C213E10AC4 +:106EB0001A1F277CB8113F6BE9B9198DBF65BC5803 +:106EC000A0BAB952E7A487F827FE106F8CA7958A5D +:106ED00043B57B89B73E4DA1796C105A2B11BD7E0D +:106EE000E6A7035AB91D02616E5DD0CDED5DC4E722 +:106EF0006C928397FB69D0D33A149F9BA356D7AA71 +:106F000078FDC7B333245A9F0B549DBF8579D41F96 +:106F100094BF3391BF8E187FEDC44FE7407E3A4057 +:106F2000653EA47BC1BB761CCF0B115CC723D3216C +:106F30002433885450112F39FA3A33C127117D84F4 +:106F40001F5A5FF602B13EF3FB72A195C7E5439865 +:106F5000DB42E8E636C3A14A0AD3734A97EF3BF017 +:106F60009533468FD1DA09C138FFB9429CBF98B931 +:106F7000ED963CB47EE3AF9A71F887CA83BE2A1CB3 +:106F8000A7F85D3E3B2EE5FF54CE201082F572053A +:106F900048AEAE9E8573C18DC3BD36888CA4D9839F +:106FA0004C5FCA48D137EC8B1D051531E8C7E7ACFB +:106FB000A73E3C45CF59216E1CD121DF9A467C7FEC +:106FC000982E4C1EC8F795A79AB29E8B9B77AB9ACA +:106FD0009A45EB848930F12B39F63C4CCA40233377 +:106FE000F0F9CF5605B39EB3C6F8D0E2F867C6A550 +:106FF0000F019CF24DEC138EB36238465CB29D0BD0 +:10700000AEB6ABCD598C43C6E94A64901DDBCF5276 +:107010008A42BC7E689C7823DA618BC3274978BD9D +:107020004E7587883FF5AEF02CB61326BB317DBE7A +:107030001AC9C7717D8DE025BE6EDC73C369E26B32 +:107040009F07347BBAC0856F02D909C38E8026A3FF +:107050007CD748E31C12B6F5ED1FBFF47B1C9FD212 +:1070600029838CF7FB70CDDDB46EC5974E4274C298 +:10707000FA04FD6E7608FD31D669D6D77F749D2857 +:10708000799E9FE52093FD5DFF2FF47C3FA4B6D24F +:10709000F84D0ABE9AE6EFB286B6231F561C911928 +:1070A0006F2BDAA410909C152D8DFAF7BE2883C0A3 +:1070B0001FF0FD7B7F55CA789461F48FA6E1F381C0 +:1070C000CD562F5A4C48F725FAABCCD943408BC349 +:1070D00001047D2FE722BF16EBFCDAE87C780BD1A8 +:1070E000B3A949F8A7ECEA8C84F19FA55C6F5B8A91 +:1070F000F36B7948D714C24DE7F035D85F5E20AB0B +:10710000329A889C05F989FEB1D5FA0EE99F86FF6F +:1071100008DF86FD5A4AF68BEC907C3FFBBF73205C +:10712000FC9F02C2FF35A0BD8AE07CCB3689E78D8B +:10713000F96A3A1F595380ED1DA1C4EBCB4189F583 +:10714000D9CFBA47921D580943BC766920FE2DE974 +:10715000887F02890B5C420E2E2FD997FE5764AFB1 +:107160005DB082F595F84E7644EE19B1711ACE17DE +:10717000E8B24248237989FBFD9BE550B038A61F51 +:10718000FD5D7B981FCBF2901F884F7B6E22FF53D3 +:10719000B444FE3B47667CAD3C52BD267ECA739923 +:1071A000FFC86FA0F9D32695243EAFF37B24FE13CE +:1071B000FCF6319D4B3B24784C223EAF3F5CA00D4A +:1071C000E46B43C72336D2FF8BF1D5CCC7D1E9BAE4 +:1071D0001DD1F9780E3A0FE8A8AC7678D894F03A39 +:1071E00014B5753AE1B410F5967062D66B837FD60C +:1071F0002CD567C37197D1385C5FBE232C94D10B1B +:10720000CA09C2CB2261779B551FFB23C3DE3A2FED +:10721000D8ED77E12B6CB3E6553E4438BA534A6D4E +:10722000952B07EAEDBA31F7B0FD2A5C8DF698FD93 +:107230006A629C165EE5F02E467A9E5C05DEC5C34A +:10724000009E5AA5726B8EDF0C7DDF8CF19B5DF882 +:10725000679E5741FCAE55C9FE7855A2F3611BB03D +:107260009EF69541682BBE3F1CF9D4A391BD2E8F8D +:107270005E5F8DF145600954539CF1AF1922AE7BDE +:10728000466F6765D8B85D5B6D011FBEA7B7530E2B +:1072900049485FAFEA3B7215D99D4EABC6F1951ACE +:1072A0007DE97B7CBF425D8BFCCCB3B48EA3F7E25F +:1072B000F8D9219CB7AFF35DF7ED717EB9B7E3D193 +:1072C000511407FDCC0235E124F1D0F2740BC73123 +:1072D000BD23DFF1E0B2A1DE11B501E2E9C19EC636 +:1072E0006A8AA7EE746A4C97AD7D7AA480F1338FD9 +:1072F000E3E3E7960E61BCED3D0321D2BB59F2AD4D +:10730000D78EC1FEE45715AF9D95CA77FDC2093CE3 +:1073100084E5BEE1CB8A4DC4BF00F273355F6C3D9E +:1073200041F27AF6CF0A90DE55363EFDAE1FD77990 +:107330003817D1300960822F5C11C151333BD3A77C +:10734000937E074E01EBEBF86E2501B720D71D2A7F +:1073500020BBF286080F27BE61BA0F4199E2FFC930 +:107360003D89D7A75E04EFFF62D80D377808EF8F0D +:10737000ADEA8077C92FEAFE331F17988C9F06BEAF +:10738000F738673C922EE2769970EB55928F7F2703 +:1073900043C4F91BBE9425C2655F14BCAB915F7DED +:1073A0008BF379DD7D9F524086ED97F2EC709278F9 +:1073B000EBD7E93696DFCF6C02F73F5BEA0A35E19F +:1073C0007A0E2EADBDBC07DF77FE9FFC97AB5F1733 +:1073D00007A369B14C6279A511DFEF9CD722B11EDA +:1073E000426B1EF1CD3CDED013436F0C7DC95B3A7E +:1073F000C41F4AF29EE1B43EA46FC6D291928D7032 +:10740000BB5F029263EF6AA4EB6BE2C720AC2E2055 +:107410007A021D9FD8C85F3B3A255F28C9F8C3E9A7 +:107420006EE65FEFEA60D354E4D73D8BF059D20BA0 +:107430005B6B71B2F983B0A1008343684BD704EE54 +:107440001D701BE92528AD79E4B77B3BAABE4576C4 +:10745000FD31D4438A1B7E66F532DDC17A80EDC4EE +:10746000160A3CB15F783D6C591B974776A74F3F92 +:10747000958EF39D4A5779DE4CBF5722BABD7FFBEC +:10748000CC4DF3F77D6E67F9E5930EC7C56D9FA6EA +:107490000BFEACC9F0BDC678A9C96263EAF5BBBDF5 +:1074A0008B2B00AEEC407EC7E13226B720AF3BC34A +:1074B0001F647A32BA3171E2FCCBA751BC1CD08D6B +:1074C0003344245026C4EC73A5A3305220F28770B5 +:1074D0000EF237A3E6C76CAF53D00E53280EDD89EA +:1074E00079115B647C9E749FEC42B32AE2AC967483 +:1074F00061E75A1E5142CDF8DECD4A4FCA306C8B3F +:107500007DDA0C45237B5FC6F3E6DE05ACDF16476C +:1075100048223BE42CFD45FA85B86B2AC0EEBFC972 +:10752000CC7FB39C46EB7AB126C3FF05F1756C574F +:10753000F420856FDE14C824B9CE925DBCEEC96715 +:1075400085FD31DB1B39F2AB9F91BDE9D3F3A72455 +:10755000F6E676F2AF86BD01B9EC10E167EA8B7A08 +:107560009AA9DB19CC3E980F138FFA9B5D49ECCB9F +:1075700024A84E43165FD4BE98E588C1FE857E21BF +:1075800032A3A20BF528EE79B33D2AC8D0FDAF6E29 +:107590008FCEC1B49CABB5185ECA577A0FD9E3F051 +:1075A00061D8A1185E428C33F37B24705CE8ABA5F4 +:1075B000643F8ECA696477A6A3DC71FE2E5D4FD24C +:1075C0003F0D7D8BE4BFA1F39A14C2F5535D550EB8 +:1075D000529B15B9B2F6678C9F9503F383A0C385C0 +:1075E000EC9DF15E2B3834D748E28785F920ABD883 +:1075F0008F7B7F7FAB349BEC220A2D6DFE98C1ED13 +:10760000C18A5C1BBFE7A9AE9234C2910B30BF4563 +:10761000F955764A1C2798716DC67133BEC0C27980 +:107620006335C713B214D6F71D12F3D2E2E064F645 +:107630005377611E4E716B7F17FA2D6C9F423F4F3F +:10764000714AB36B16AFDB58AF41DF5DA93372A04F +:107650006CE0FA8D36F0B90CA1CCB8BE12B5118E23 +:10766000039FDB12AE1BFC1C8C0F063FA7103FA52F +:10767000FF3E3FA76608B99AF9FA3F5D7FE18A4964 +:10768000906C5FE0FF97F54F05FFEF7B44BEF55A26 +:10769000AE27664F0A57CC9697211F26503CEE8D99 +:1076A000D90707FE237C8DED68657B3309ED0DC599 +:1076B00099057561B62F137345BE64B61B5776C224 +:1076C0004D641F2747302EBD04FBF129FD471EEFF7 +:1076D000E3FC3203E91EF7FC82E5BBF0D2580D3221 +:1076E000E7E27BC6762B5EF27BD09D99745FC0EC9F +:1076F000378CB8D48847CDE38C78D4F0270D3A1F67 +:10770000FE3DC3FF64065D57D520E91BEA55F831FD +:107710002FC35EA378A13BBD7A37DF1F190E721EFF +:1077200050022AEDEBA0BE721C56E97045E4B1038D +:10773000F5D369D2C330F285F609822E4B689834AE +:10774000900E0CB78314F7E103FCFEA5BABF28C462 +:10775000312CB406E0F8BF702CF8C9EF1696638B95 +:10776000EB3CA6C7232F995AA4FB79E2AB5581A025 +:10777000BDFC1FA797482C2827FEF8FE40EB77CCCE +:10778000F631FD052A78298E2F50C29217DF9F51BE +:10779000A7491736910C3F8DF315CCD5D85F160C41 +:1077A000C53E8DA77827895C7A32ACBCCE7A47CFAC +:1077B000611BF22130B771B6DB128BD3ED56BFAF30 +:1077C00080F68F3A44BC0EB4DF379EED9244EB5105 +:1077D0006608FE0454915FB94065BB59A9CBB1D28C +:1077E0003197F777C827DA270F5CB7A4F97870FECE +:1077F0007CD082936376D5C87F701AA0F798ED6A23 +:10780000DFBED72F0BA23EBEF5BF3F4905BCFF2709 +:10781000259A4AFC387DFF89541FF2E3ADFB45FEF3 +:10782000F27D537CA4640AB92ECEACFE82F87ADBDA +:10783000AABF4D88B72FB0329BF5E28E904CC9F0AD +:1078400005FD59BEC3C97BCF46BF3E9C99D037F4D6 +:10785000A0DE0E8DC9E2EA6999222FBA63D7161B02 +:10786000E5D18B33FDA999D83FADC77FA7DB53790D +:107870003FC0A067D1AE7136E2F79F3AED106103C9 +:10788000D96D1572F65D2F4DA0CD7BF167A6F3F093 +:10789000FE021BED9F2F91202AF6B5E0F0CFB1FF3D +:1078A0005EAE0C6BBD03D7B1E42DD56641F92C99C2 +:1078B0000ED120EAD5A2BBA435F7E2F8457E1745E4 +:1078C0007003D6B9309898E72FD3E395DB1FB29AAF +:1078D000F2A4C6C3B45FB618E7A17C76496BE2FD9B +:1078E000FEAE3B0FFF9CFC40878DFDC0B28BE44F8A +:1078F000E332F57865024CFCAA94E295B21F9569D3 +:1079000083DB25235E39BD0A083CF097550E6ECF08 +:10791000AC52B9FD42B7D7CB3B0E1C665C2BDD13D6 +:10792000C8CF3ED5F5AEF3162DE637BEB9E5934385 +:107930003FC77E05ADB398EC65C44A78BC4AF71BD7 +:10794000CBF438A4E273B3DF38F087DF539E8DEBBE +:10795000DFCE19D7A5C523B782F2693C1F0C3F6261 +:10796000E6477F57A99370323F33713FF67FCA973E +:10797000C19EAB9711D749EC87A14F5F64087C2F5C +:10798000DE366F4D3EBEBF79DF07453DC22EBD06D8 +:107990009E185ED1D033DE960144D7223EFD9DFF76 +:1079A0007498F87498F03689FA97F1FDDC2AC42FA0 +:1079B000EAEDB2CE0FDF84B1AC5FB9965C6A23B951 +:1079C000945F9A7168C69F196FBDD69E22B20F66EA +:1079D0009CF54A89E76446BB34539C5F2CD67CB344 +:1079E00028DF45B7B646E5F508FB775A693DFC4305 +:1079F000D2DB6D12E787F5CFB43D4DF6A8F6B73F61 +:107A000071933DFA5069F5D0FBEAB63FE0F6915D1F +:107A100052826E7AFEC390B04BE6F775EA7C34CEA4 +:107A2000052EF8A587A26BEE437E9C477D26FD6D53 +:107A300068FFEB9AFB28CFF039A294779E567A66BE +:107A4000111D772C7435367929BF4D5C77EDE33FF6 +:107A5000F168BC7F1C2CD0F9C7F96AC336AB3782FA +:107A6000F336BC227BE9350188F2FACCCF07C2EFAE +:107A7000DAC87EAB1688164E1D781FC56823BD096F +:107A8000B4AFFB5876532BE415203EC79D33D4E8A2 +:107A900076D88CE35D99FABE888E5FE40FEFA70677 +:107AA000912EDA3F8290B0C7CDBFD938F66DA4EFE2 +:107AB000CCB617DD5259FCB9C26A96477FF8F65F1B +:107AC000392C83E3B757C77B2C6E09F1735A87248F +:107AD0000E833A455B678DB8296FABDB62F506F123 +:107AE000725D9B0C0EF25F27ED1C37D4B57DC2F89A +:107AF000AC937C51691C2FC32DC5C511CBDBDE9B1C +:107B000045F676799E0C7351A56AF79C13E37D10B8 +:107B10004DC1F1CB77BF3DEB87D447BC3B92C8AB9F +:107B20002A7CC026F4C624AFF0DBB3281E6EFECD3F +:107B3000672C8F0FF74B90533CF0F99A2DEFD9C873 +:107B40009F9C41C164A60B7E91DF0884E585B6B495 +:107B500064F28B5CFFBB4ABECFFB7F1793E37A3A9C +:107B60006B1BCF787FF2774847CD9B76EF5C7AEF3F +:107B70009377BA0171F081D22870FF8B073CE487BC +:107B80006BAC418FCAADB85EF3CBBB198FCB8EDF28 +:107B9000ED11F98D2F4FEC1705F3689D4B367F9B48 +:107BA000D7B914FC8CC79A5FC8D5B44F734E81D92E +:107BB000BB93E84D659688B7ECF083B1F789F30085 +:107BC000A0FCFC037DDF34F8B2CC719B1D6E4C9B96 +:107BD00017B7FF64CF12F62A08A13FD2B96A00DDB9 +:107BE0002B9F831C3F378BE6B9AB5869A473225C8B +:107BF0007F50E797F415EF0B80A6C4C55955C7AF62 +:107C0000CEA17D313BF4DBFE5725C7D51AC53D71AA +:107C1000CF31DF3ED86A1F225D89AD27F9BEE9ED7D +:107C20005986FEC3CB1087A7C08E0F184F80FE3B2E +:107C30002D57F41F237D5CE46A4C43BE7DFACABB1A +:107C4000363AD70AE27A8611BDDDEF711FBCD91A28 +:107C50008D37E60F74D863E781A4D7DBDE33E9758F +:107C6000E27DF4DFCCCF00A46994B77D608BCE2297 +:107C70007F1EC4F7527DC1D20DF684F3C6185E4C48 +:107C8000E78BBA7E1AFB9CCB4CF198D19AEDC2954A +:107C9000598976013667273D5F34E72175D6D0AF25 +:107CA000893F7527ED9CBFD4B509FDC3803A3A0CD6 +:107CB000F5E1A35D875EBB05D7F151D89A3597DF13 +:107CC00096686F6B9E42FDC5F132F23B85EDED6724 +:107CD0001C4F19FEE823175E1C93446FF17A52BDC6 +:107CE0007501DBB3FF577676D92076F6BB5903E2F0 +:107CF00084347C0DFCE589E597537C61E6AF615FD8 +:107D0000CD76F3934C2DA9DD04DDCF1B7CACDD7962 +:107D100096717B3E4F9C37356CFB2BFB31646BD4EB +:107D20008EB86D087DCCFD07C88F71FFC07C696C73 +:107D3000B27527F2D37CFF32922DE723D1EF139F48 +:107D4000658BDB2BF6E7543ECF6F26BF49765A533F +:107D500081E40833204C7187D4F9FC5FE97DE6BCEF +:107D60002238034636F2B92EAC8BAFCF092B7A3DC1 +:107D70004530797D4EB32D769E4BF7073BCF7D5F27 +:107D8000B7575E97CAE508D62C4D4E5657E2ADB2AE +:107D900024CD237E9225CE774AB3C5BA8F65097963 +:107DA000B4C8D5FA46A3C897680F95ED5FBA9BCFC4 +:107DB00083AD7A7D06CE9CCBE7074ECB27C812D881 +:107DC000BDA17A8E42FBC315963B4BB1DFB5E1F600 +:107DD000390AE2C73BD5B2A704FB2F6C582CFA57DF +:107DE0005A2AAC08FDC7834BE6CCA47D03CBDB3F0E +:107DF000A5F529AB15A0FA91D296F7B87F97559CB7 +:107E00005F353CBBB786DEDF20A12090FF2DEE70F2 +:107E100023D731E482BA9A368FB53D7EBABF260F9A +:107E2000F379944724CDFFDB2CF22B8E885B2BA1BA +:107E3000BCD2B7F17B785F79D94A3921AE53EC8354 +:107E40008FDE333597ECEEFF85F7FF5B56F6E0EFFC +:107E50003FF3D4B50B68FC68195419E72B57B42AC3 +:107E6000EADB31BFA6BCCD9043B922F85EE6B27121 +:107E70003ED792EECB253C1D239C665F7ADBACD7C8 +:107E80000FC94E810339CDD2B81BDB5774F9BFAA95 +:107E9000F383FE685FA06F5FCE56AE5B816811C949 +:107EA0005796B7B6113FA24D0A6CA5FDD77D8FB787 +:107EB000113E5FB73978FFE8E6B4F5D62B90E4724F +:107EC00047D19D04FE37A55D7753BB2FDBDF93259C +:107ED000E68DD0BCB77C5F16F3BA1A53C97F820F08 +:107EE000F54AECD370FC0E7ED42BA2F920EAD538EB +:107EF000320589754E663AE4B45D4CC7CD7641C70C +:107F0000825049730FD231CE1EBA8CF22B7C7F94F3 +:107F1000E4700B865B84E760217491DC5EBFEDCA80 +:107F20002D627D85ACAFACFF7CFE7EE6499A2F804A +:107F3000F3D3396A40EAE1FE1EC5A1065561DF1799 +:107F4000C6EDBB3D0BAD27CAC4FE7E33E51D53F520 +:107F5000BCD8D87F33EA0D2676F9AB5C64B0E54E29 +:107F600099ECCA398CD7C88E99F7DD269BECEFD4F3 +:107F70008E8FD82E5FEC3CD099ADDBE37CC8A77523 +:107F800084E93C90025EDD4F7AE93C3089FEC79D72 +:107F90000766660B397DED79E09DBABDD1A84E0E1E +:107FA000D7D18F1393DCFA8F2E82F24AAE476884C2 +:107FB000F4C1FD6ABBC9FE1B381FF38A7A3BD9B3F3 +:107FC00031AFC06DB4DEABF5F393FED3C0F580E303 +:107FD0007A1C5C1F68EDB28642525C3DCA490BD7E1 +:107FE000A3F48337C4F52B41BB1A647B3996EB4F5E +:107FF0005A4EEAE7BD7A3D438560D93F5C0F61AEDA +:108000007F98E29E242FACE4F31990260DAC7F9864 +:1080100022DF2A935D81A3429E17EA20E43299D69B +:10802000752E024029DA8457E2E48DFF9B9815945F +:10803000B9FCE954E2F529265C98E57F6DB61EDFB0 +:10804000E8F21FB48EE443B1AF360EC6721D89D577 +:108050005C47F286850B366375241521D2B7094D2E +:1080600062DFF862753CE63A1D731D4E9E3F914FEC +:1080700005355724DCBFACB13CA17FF9CA2909E31F +:108080008BD1A1C6F74B1F9A93307E58EB8D09FD1B +:10809000119B6E49183F2AB428E1FEE81DB549EB53 +:1080A0005E0C9C8C09AF48B8BFD1F9E4BB84AF9695 +:1080B0003C59A578FECA8EFB4C7531D31817538CEA +:1080C0007D785DFE465D1D9581119FC7A3FC1F2B2A +:1080D000A6B8E9FE2A491B88036F24C87EFC1FC589 +:1080E000C17A931D30F4FF62FB373FD6FD849C526A +:1080F00024519CE3C3B82A652AD5118B737B784B36 +:10810000D4AB7C96F2778E8B34C9ED856FD25B55FC +:1081100089E2A07BAB348E83EE1D527480F60F7A19 +:108120007EE0F64AF903EB42CD75A0190EDF64E05C +:10813000AD115107D982869EEC7F708683E38C87D0 +:108140002D96DBAAE3E87F225BD89F27B245BEF5D8 +:10815000735B7837D901C5016A539E789E8A1F8068 +:108160002A7B502EEE4C10F561F0C6DA9985E43F7B +:108170007B466AE9543F8BFD6FE06525C4FEE496BB +:108180006685F3BCD5CE27D99F942BC29F8C93854F +:10819000DF403FD241F6F14DE97EAB88B382569283 +:1081A0004F810382EE72F6AF7C4E9C0E59D28A321A +:1081B000AA4FBDE0B7B4AF104C876AA75A884FFDED +:1081C0008B653E0F7E8948427AFB6B46719D73FF3B +:1081D00085FA3F2D8DF2EBFEC58F9EBDBB32A69773 +:1081E000276DC9F3BC8BEDBBD56C793495CE514E60 +:1081F0008E8484FA8C37B3457EF866B62CEA0C423E +:10820000EF79884D7D4BBE184E4407A4EE352E1CE9 +:10821000F2E0A61F54935C6CEDF382B4AF69ECE31B +:108220005FC8033BA773FDB6912FDDFCBAD8D7BB5F +:10823000F98BC47DEB8FB2C5B9C047F43E6CCBBBA4 +:10824000FCE3496E379042F0BEB27F3CC507D52AA9 +:1082500068E4F717F817DE7D14FBF3D64B1CEFD359 +:108260007D1A7F23CA90EE9F00EFAB7B91BECFB308 +:10827000053DF3A1DA4A74BEF6FDFA54C2D3EBE928 +:10828000627C54026D6BDC7C37E8F3BDFEFDE57B60 +:10829000294FA7F7D1FB891E7AFF3C154AA8FF1A80 +:1082A000F8CFBE5A3CF0BD3781CFAAD77B59C94F12 +:1082B0009642A8ED69B2AB472CDEB5C06D2493FDA4 +:1082C000929DFD525F53F4C97B90CE3FD5FE75AFB2 +:1082D000847CFDE3C2E8AF9FC6EBDFDD248386B874 +:1082E000F838C32F7BE2EAB44F2EFE2495F889F1CB +:1082F000CAF69F92DEEDB47BA9AEE3CDDA9DC3E36F +:10830000E3FA54CF74073D07932EED3CADEA89C9DB +:108310008CBF15DB05FE56FC66440EE16C45EA0594 +:10832000DC89FEF6523E279D2041D2FC783FE24D8B +:108330001BC17535A021CEF67F2EEACAF71CCDA849 +:1083400020FA14F05F16BF9E3D2FDD329AEB79DFE5 +:10835000C8BA243A496783687F6F665389F181AE52 +:10836000270B3A332BF478729487E2B9DFFFE6ECFF +:108370007F105FF6EDDCFE43D6914BE3C3C03A5A63 +:108380007527DB27230FA3BA57CAD30E59D84F5EE0 +:108390002DDFCF7918D56970DE35A488C7A3C15108 +:1083A000ADC2BE89EF24300E6EF672BD27EBEB4AEC +:1083B00055C42D469E245BBCB98AF8C8E0C5A93CCB +:1083C0007F09D0FE989B122BC35E611CE1962DBAEB +:1083D000BD029F03F3D3D1BA3D9BE5F15EDB22CE14 +:1083E0006B12E24FEC57ED4A127756E33F8E3B3764 +:1083F000FB9B53D82F6D96CB28EEF03922E4C7CDE6 +:1084000071E75458CFFB0003E2CFE7FE7249F1E772 +:10841000F73CFF3DBFB3D4A3B1FD098F14762E1CEA +:1084200019C2790EFE55907E0DA5BD003A07CD13F9 +:10843000AD4DEA1DE940FDACF594AF7B681AC2650D +:10844000A8E00FF551A450AA7D72E82B8A03BB1552 +:10845000965FFF73577CED772495A887E4EC23871C +:10846000A770BD735F97D08FB60CEDDFA7529E81CA +:1084700071E656243145E9B1A52759CFD3647F5120 +:108480001FC21E9147393AC4B9A843F301D99714C2 +:10849000551D4789B9317EB147D8DDFAC36F16D96A +:1084A000503E672D47DD74BE52B7F729372E179A15 +:1084B00033FD0F90FE2C3FF9F20495EBDCB614511E +:1084C000FE1D8EBC3C83E3B3D9C8DA7183AF27B0FD +:1084D000A9823E4280864D99DC8EA27D15BC14880F +:1084E0008875F676346724DB1F08FCDB5B0769BD03 +:1084F0003B8FA570DCB233BB9BF520380F603BF29D +:10850000FB89CF47F37C0830A6E38A6A4D227FFFC0 +:108510000B7D3D3BF5FCB2F77399C719F38EE998D3 +:108520002EAB88ABB248EB41AEE3EAB46B24DF94E8 +:108530006D20F8D399C2756181FDD788BC335D9CED +:1085400047B70D89FE91DE13DD67D7A84E35456D1F +:10855000850C9CBFCD26FCEC2804FE53AED875E3F9 +:108560007D299D1BF92308C405D7E3A528ADF00D8F +:10857000573CFF5399DEFD1E11EFB40D89585CE4A2 +:10858000273057DACA74C5E8047EAF41E7288E8BDE +:10859000DB6CD1F769BF1DE9520917A340D0099DD3 +:1085A00023348A57525471AE9EA26ADEA03490AE34 +:1085B000C058086170000FAF860B7ACE7584436295 +:1085C0007D07EA425B891EC70417AF9B392DAE4F6A +:1085D000866C52ECF9139E65EB5A0A695DC20F2A4C +:1085E0004A98CFC7DD0B40A5F3EF14C5C77952CA2F +:1085F0007CD09A505E4E878FEF7B708EA6C9DC8F41 +:1086000010FD2ADDA77D9B34D53907E94EFB328D5D +:108610009F6BE8B672DD79DDDF6F4A2BC3F59DB144 +:108620001CBC6717B61F2D0C0FA773DA0969FEB7BC +:10863000C81E3F736AD1BA3138FE2F6D56EF5CB257 +:108640004B3DC11FD3B97DED13568DFCE2836FF412 +:1086500047BE22F93E2BB15DECB38AFBD8D79AF026 +:108660007E43E707363AD7BAA6E36D1BED7FAFCC62 +:10867000F1BF4F7A30A9A3A98AF836195A9B699F8E +:1086800013ED21D74B847385BDE87F65F8D6A638F6 +:108690003EBB72F47DEFA8FF72D29B4E5D3FF75355 +:1086A0007C84ED5E3D4EDB7BE0BBA55ADCF96910B6 +:1086B0000EF27EE06A788EEB3A8DEB7D216536E135 +:1086C00068F46B8EDB7C7138B3E5087DB7E9EFFBAE +:1086D000798EFF4BD6DB03EFD8DCB8FEC09FC345D5 +:1086E000E4AFC218CF7D5D1D69C0A42F17EA8E4E7E +:1086F00003DB919DAF7570FCBDF33E359DF41EE923 +:108700008734ECEFC5F882F4686FB1D0BBA657CFC1 +:108710008FA5FDE2F3FB965F4EFCEAF5580D7CCF8A +:1087200018427AB41BD88E197A58467A28D1F77B2A +:1087300062BFA78CF04D7A67EB9EC37AB7D702A4CD +:1087400077886FC63BE25BA538A44C45BCF3F323A6 +:10875000588FDBBA5FBE82EBD991BDC3C651DFC271 +:10876000F86A8BCC0949F87CA53572909EAFC4F7A6 +:10877000376931BDAC9412EB7A167B449DAC611F16 +:108780007FA0EB6778A496E6C5F14E594EC07F9C5A +:108790009F147DDD8FDEBBF127EB36A0BE94FA2A55 +:1087A0002C1328DE3926B31FD8AFC7C92BFE30E5FE +:1087B000865DE23AFBCF888E8B837ADCFCDCAA5C98 +:1087C000EE935FD0502EE3B1F55550BD7763156D34 +:1087D000C54D9ADD7A88DA29D5E12A3A2E9CB6A0D1 +:1087E000FB90F8C6CD379AF0D67EF05BA3B94EFA6F +:1087F000A41DE83BCEF6FF8CFEF1095CFF3DFB912A +:10880000DF90342E61BCA1C766FC0D86933EA9E7BC +:10881000FAA96897AFDBF8EB6B1574E80D04045CFC +:10882000FF9C8DDBD605D1079EC8F15D9783F8FBD1 +:1088300022D77F5D0EF2ADEFF87F7AC89FEC7DE521 +:108840001D37F9E1769B6F34E1AABD04F3882478E3 +:108850009C926365FF5A3948BD49638EC8B7860745 +:10886000611DE1A5A15D5643E4A77DDDD793DF78C7 +:108870001F5949FBDA4BA707DD942FD5EC3DC47592 +:10888000FA463EBD04F43FF9D659C4FF73B9223FFE +:108890005EBAC19A90DF8E80888DCE91037E576339 +:1088A000044552638A3BEEE8D8C2DF8DD46E4B7C20 +:1088B000AE8EE2148450DD45F2E3C61C7D9FA41405 +:1088C0004A294E41DCF03E49F455D9BB15B8BEAA41 +:1088D0008BEAAB765A049F9C0E6849CB88C52B2344 +:1088E000F27C4BC8DE2D31FC875EAF146D93F87BB4 +:1088F0008A513B44BE3CE5B4B685BF930AFAB84EF4 +:10890000AF860840BAA728415EFF94DC5208E2FA1D +:1089100027A179267D59DA2985989FFA772F0AFEB3 +:1089200013FB459B65FECE6FB30499C5346F94F974 +:1089300053ABEF1F2EDF91787E51B7E9F8610A95AE +:10894000EAC3A6F3209D3FE6F39DA7E83F929CEF84 +:10895000FC24478FE78AA028E1BBBCAE4BFB2EEF7F +:10896000238A075C74F8080971F91E1D470DFABACD +:10897000EB42B258378A82EAA36FD76112002FF315 +:10898000A91E71423880F542DE463D632D54DBA8B6 +:108990008EACBEBDE9309DBF2DD5E35A339E90A16C +:1089A000CCAF657ADD50CDE6C4FBB53A5F6A4D7C4D +:1089B00069F04B26FA44DC7DA9F4A1E5FA0EE1A0AA +:1089C000769795EBB9CFC1AD5C7F55DFBE85E95990 +:1089D000AACB6F20BD415ECF325C0FE9D3A5D26B2D +:1089E00096DF3103E757C01509F29B9D7949F22BB9 +:1089F000057539ADAFBF4BE4B5FD5D25BC2F61E01A +:108A0000C5FCFC2C3D8EBE66938837CF7654392941 +:108A10001EE83BAA7825C47DC5B14FDDF4FD4DF9B4 +:108A20003E19E89CB4AFB3625D10EDE59EAEA13790 +:108A300069E807CA8F29EC372A8E9587528AA95F81 +:108A4000EE2CE53A132D93F2009C87FD70DFD1A147 +:108A500027CA384E9F5949296AD3D17227C50B7B43 +:108A600040EC6F48C72A337BE2FCCA7B3962BF61A6 +:108A70004DEEBB0F939DBA66B795F783AFB1465FD6 +:108A8000A23C6C4F97E26DC27EDDB145AB5348DE30 +:108A9000BF91BC14761FEE5E9145E735F59D56D526 +:108AA000CEF4DE7D90EE077749DE61383EB0EFEA26 +:108AB000D16DB44FB4A5C24BEC35DE579EAE3D4AE6 +:108AC000F5AE90E7E4BCFD9ACBACEC5FCFE43BFFA6 +:108AD000752EAEABD6B76516D9E133BFDBC37515BE +:108AE0007D6D12E44AB48F7CE849AAF739F3F4713A +:108AF0001B9D0757B51FE7BA8DC1FCC1D910E28E87 +:108B0000F3F6561BE537F55B8C7E0F7F8F52ADC7B2 +:108B1000510DDBDEE67E2DE50184C7CD7248C3FF33 +:108B20003CB4EF193E1F6ED825EA3E2EDCDF26F15D +:108B30007D03EF8B74BBB51C34C6FB7203EF7A7DEB +:108B40009481F7733097EBB496EF7A84F1BD44C704 +:108B5000B7B96E0A2DB0AD2C4BE82BEDB799BFFF1E +:108B6000BB43C7F71D17C1F7A85C1DDFA36014E165 +:108B7000FBFC74514F77FEF81027CD7FFE08EFBE47 +:108B80007E1DCED9EF1ED5E382FE88C567BB323687 +:108B9000AEB7E313FE0E3170B4DF467527B33A3F2C +:108BA0006679CCED3C3093F87D1DF8EB887FD77566 +:108BB0003A558A83E7F6087B36A7D3CEE713D74129 +:108BC000B885E4DCB7FFF1960CC2CDAF056E0C3B67 +:108BD000B74CE7EBB5653F9845F97BADEE0FFBBBB6 +:108BE000EE9CC576671C1453BC3747FFCE7B4E58AE +:108BF000B7439B13F94EE7D424B7864E3BD79B5C13 +:108C00000B3D36F267D7EAFED3EC27FBF29C2CE74C +:108C100020FAAB6138BE6E97A98E52E9617AFA3BB1 +:108C20006C7CDED560F2BFD372AD09F51783E1D35A +:108C30002CAFDB72757FA2CB6B6E54D431CC7945EF +:108C4000F6D2F94357647519C50B06DFCCF2EAD2A8 +:108C50004AD3BEEEF7125ED2E37CA37F83FEFD5BB8 +:108C6000586D75C5E7EDCFE75AF473CED04F2B7032 +:108C70009D7749D04D38C4FCE6867229697EB332AF +:108C800017C73F5F78FBFA71F1F98D6FCB708AF7E8 +:108C90001E44BB5251C9F53BDD7C5EA8B4CEA57322 +:108CA000B0C02EAB97F29A4087CCF14060973D64FC +:108CB000C179AF211C215DD59DD2D58423CC1B5A0F +:108CC00072D13ECDA32D651C37AF03E3117C6EDE60 +:108CD000CC8F197F47868A75F72B5A4EB23CC2C893 +:108CE0001F1A3E17F1AA71BD01ED008D6FD0BF4B69 +:108CF0006B3FF8D7A2E2543AB7FDAC6821C5A9B9D9 +:108D0000227F31E2D528C6AB257ABC4275174B8548 +:108D1000E860E973F7D9C87E1DA61FB6A0FA49D549 +:108D2000BF86F261D50F8D3FA240436A613D6A2044 +:108D30009D221CEE95C4FECDB356AA0D81A6978741 +:108D4000705D60EF6BE21CCAACEFBD8BBAD95E9C64 +:108D50005FE86A24BC2D2FDBB206230C18BDFF751B +:108D6000B637A37F67532D6A6C5D4DF4DD1DE7694F +:108D70002D09F1726F47B38DF7A1E3BF1B2E1918B0 +:108D80001FD55F641FEB79935D41FA39DEED3B221D +:108D9000ABB42F847CFC657E3CBFF478A8FD600AF0 +:108DA000FBAFBEE3AE10C5FD7FD1F17846DF976F14 +:108DB0009A24333F2C93453B7AFF3325245F9287D7 +:108DC0001FEDFDCEFDCF5CE1E37DF490A823DE91A5 +:108DD00058875D1F4EACB336F81AD0F98A740DA7C8 +:108DE000EF950DBAF62A3D6E6F123D92A4832C2F9B +:108DF0008B9498E7069E95ABE3EB48713DB791DD08 +:108E00003B69E88B12F5901F7E2B5763DC34750AA3 +:108E1000F95AF68916DFFF1DB15F63E5F70FB83F1A +:108E2000235847F7CF173BB9BE013E0FCEA5FE3DF5 +:108E300025E2F703EE79B97644FC3E1D48221F0F68 +:108E400058A35CEF17386E61FA02C7FB3D435D64BF +:108E500017B7CCA43ADA6B757B71B8C45943380F95 +:108E6000D27B7362F32CC915E71B40EBCD8D7D5F80 +:108E700069AC7735DCC87C58ADE3EA3FF4BC1EF33F +:108E8000A8F3B949F2A8C1E2DF0B74EBF1D3F9E919 +:108E9000DA89EF210ECA8F2841CAD7F7BC91122276 +:108EA000FFDFB46FD99F281F0EBC69078A43EED934 +:108EB000BF6C04D7E1FBFD57923D39BFFF8E2BB944 +:108EC0008E5112DF970689BE5C8AA75EF5509C54CE +:108ED000BFEF55AE73ACDF3BFE518A9F305EBA9652 +:108EE000AE631CC3F82B3F56C9F8DB73B432B3949E +:108EF0000807AF93E6AD3FA270DD63FD91CA17E7A7 +:108F0000525C736C06C74F46BC5441F938C54F4795 +:108F10008626C44FA979827F7D075278FF4382124B +:108F2000811F189A809FBAF63F709C5187F62E1EBB +:108F300047C673C5790ACF332C4FC74F58F2313E1D +:108F4000768BB6AE630FAF6FB935CCF26EDA6515BE +:108F5000F7DB446BD44907212348FC78912EA11CF0 +:108F6000E6D84285946FBE502CF20DB33C9EC813D8 +:108F7000E7852F9C14DF19BF30DD3F22D9F7C641AA +:108F80009821F27049E777BB7576B2EF7977E4897B +:108F9000FD097726249C4B1AEDA379425FE6D8C4DD +:108FA0003E95F9BE3FCFF03FB08ECE634ECCB5AA12 +:108FB000C6EFB7E4A1DDBD1E8C3FEFABF3B3E89C79 +:108FC0004BE4D5003D33C91E7E9BF6F929FE9A2459 +:108FD000FCBAB1CF3F6F333C20F6F96FB5925D30EC +:108FE000EA4BE6F9CCF157F5D534CF8DE8DF699E31 +:108FF0009B6627DEFFF645E2AE0579BA1F1F0EC35A +:10900000455EE172923F38D76555655E476868B244 +:10901000EF0B0DFB737895383FEA42BB486DD3A840 +:10902000D779DFEA8503279F4C67BB9A0225C8E200 +:10903000ABBEFC9327D93C4D17F4757E02FE0C792C +:109040009DA53CA06CA0BCEECCB3E8DF259DB1F1A2 +:10905000F926343E649107FF2EA969D4672DA44FE9 +:1090600067F5EF5E90BE227B9CDD3F9BF731DFBF53 +:109070006706448378FFC0283BFBBFFA99129F1F05 +:10908000D447843FAC9F2FFCE1F0F6792C97EFA0FA +:109090005C7C5E3613AF515DAE21EFABBEEC9B69DD +:1090A000E493748ED34438673B9DC56D7DFBDB2D07 +:1090B0007C5E897E97E2C21B2625CA6D04F81FC814 +:1090C000C6FB37CF96BCE84106C8FDE65BE7B1DCDE +:1090D0006FD2BF8FB998DC7F9BE7FF691EE97D7770 +:1090E000FF77C6208B5E18F54111F9D7864170BD18 +:1090F00055E72F0C8D3E4DE765DE0BE7E97F7F3AA4 +:10910000FE3CBDC4E3DF924776D5F2A5FB0AA0F989 +:109110007A7EB942223901EBC5607AB5439F7F4719 +:109120009E2ADE9325CE8746E9FD17ACA142FE9E1E +:10913000A2ECD2CE019B9E7D7E2CD9B9DE0347C620 +:10914000DAE2E47A6605DA07F237FB0EF1F78731E7 +:10915000DC5974DC29DC4AD28DBA1F4DC4E119C236 +:1091600021D9E7DD87AEA7FCF16CFB4D599216E7DC +:1091700067F79E700F8B9BF7ACFEBB1898B70DFF7F +:10918000766A3C9D0F309D67C3623ED4FFE1378D08 +:1091900089BFDF6C7C67C7787E7064239FD31B78A0 +:1091A0005640E0D9F83D8C0BDF55DA80BF7B0CEEE2 +:1091B000B7737D459F355A941EA72F1F1A72449886 +:1091C0001566312BB9DE75226CA8E273024CDED72E +:1091D0004DA6CFEFC2B2A80F6DE4BAC5698DE025E8 +:1091E000DC4AB099FB13668BF3F229D02D135DDFB7 +:1091F0008428B73E50156A67508519B6931C61994B +:10920000C2ADB6F6834EC257C4A3A4BFEF10A5A744 +:10921000C9E4175BBF02EF1B78C5C1180425FD4EDA +:109220003F2B5FD87FAF53E863F4ACF8DD936F401A +:109230000FD33F55E9667A53352D83CE4B763FB732 +:1092400042A6FA97FDA04549CFBC998DBCFF169D5B +:109250000EE1ADE9B1F54EA2F5AAB1FE940560A10B +:10926000F54AB04BACBF1132E87C6C3244F83D5744 +:1092700011C1B8DEE9A029D4B7E517EB7C16F95B7C +:10928000959EBF591C41AEFB49CD17B8762A2139AE +:10929000AF92B7B6C38FD0F94CA958E744BCCEE71C +:1092A000388D82EE0BFE3A5FD8BB29106639430D2C +:1092B000A82FF28F2BCC54895F52C463A1DF13BB5C +:1092C00054BEF67980E977DF1EEDFD6165ECDCCBFD +:1092D000DB99C3F5D0EB254B5426BA1C85A21E3A68 +:1092E0000261FE2E3392F87B67C5F9375E9E4F7E92 +:1092F000CF2FBEC335D775EE086DE5BA9B05416427 +:109300000FCD530870DA13AB03B09684F8BE95CE38 +:10931000D955AE33ADA07C715FB6FFF2FC6CAE37B1 +:109320001DC69329A1F1D5A931BC2365FCFB3B4E99 +:10933000486D257BD4ACD7D30655B75ECF54C4EB6C +:10934000D0D0CEF38F4828A2AEFBDE2A517F7AEF31 +:1093500090FD5CE7DB23812A15D0F9FF7EAE03A6E2 +:109360001F86B3167CCDF97F96FEBB0F25FE3726F0 +:1093700096EA461E9F6B3E95CAF5AFCA0C9F46758E +:10938000BCE67AF1D296F10FF5705E6AD06BAA1343 +:1093900057BC7CFF5EDDBE363BC4EF0049ABEDAA97 +:1093A000348DBE7F5FC1BF63D54CA141257DF7BE23 +:1093B000829FA73A662A02ED4DF3DF44FC32FF2E6E +:1093C00015C2ABFF059A376D38EFF72593C73443C5 +:1093D0001E9681755228875B49BE46DDAD516F4BA5 +:1093E00080A0753B7DE277F054C409FFEE1F42C9AF +:1093F0004EB8F4997FCF43D4FFB6E8FC47BA7670F5 +:10940000DDA7437CA76D7CCF6BE69B81DFFF02B9B4 +:10941000D77EA250530000000000000000000000B2 +:109420001F8B080000000000000B9B25C3C0F0A3A9 +:109430001E8145A551F9E8F81C9A3C0B0303C34F64 +:10944000205ECC835F1F2E1CCB82607B893330185B +:109450008B32309800F12C209E0DC43F81D8508C67 +:1094600081C108888B81EC1220F6056247A0DA2FB3 +:109470001C0C0C13851918E600F1726154735F30EF +:109480004268252E060653206664C66E3FA73AD072 +:109490005E5D04FF23906D6F409E5F46F1D0C35523 +:1094A0004EA8FC7C6B54FE2C5B0606666704BFC0AE +:1094B0009A34F3ED817A1D9C71CB77BAA3F21B3DF0 +:1094C00051F97FDC50F935E1101A008D579524B819 +:1094D00003000000000000001F8B080000000000D7 +:1094E000000BED7D7D9C14D595E8A9AEEAEAEACFA4 +:1094F000A9197AA04706A8611A19E3A0050C30281B +:1095000048CDA0384693349890D1D5BC168821090F +:10951000CFD7F1ED2A1AC9F47CCFC0800DB2067DF9 +:10952000515B0C89262621899B3559B3698DC92346 +:10953000D96C168D9B47B2B86F243C379F9B79EE50 +:1095400043FABD90B0F79C7B6BA6ABA6BF00DDE4F1 +:109550008F37FCCCCDA9BA1FE79C7BEEB9E79C7B8B +:10956000EAB6EAF1437C1EC059FC5B03F0A6170083 +:10957000964D95E94E33076DACFC1C98FDECD1A5DA +:109580007AAE5362E5A2D0B84732002E8F66003C17 +:1095900000F1C38F8287D51B695461671380DFD8C0 +:1095A0005003A1A97EDD657F0F406E61E9F7F20BE4 +:1095B000A33123CCFA7B6A79B7C5FA19F9727BB764 +:1095C000D53AF5BE010765F8CD07864D3DC0E09C54 +:1095D00007C113051866632F64FF69F72521C1DAF7 +:1095E000A9B951301661BD5AAAAF3D73D4731B7B24 +:1095F0003EEC85EEC3ACD49E4DE7820CEFCB9ED300 +:1096000097C88C1EBF62797EC5607FCC934D231DA9 +:10961000B17DD4EF2946170EF576D1B314E9617404 +:10962000ACAA929E55A5E8792E9D467A2E7FD658F3 +:109630005C488FD6C8E9D11AFB689E4EC5183D4DCF +:109640001742CF3D44CFB0A067D845CFBB043D1BE8 +:109650006D7A1A86889EA1398C1EF6C8775F1A1219 +:10966000ACBE86F484B19E939E21A4A7B5083DDAD2 +:109670001F879E0F09794B213DCB2AD393427AEA6B +:10968000ABA02794019D3DF783641D6E9D8E975F6F +:10969000F071D13399589AF53BFA7B99E699ADC8A8 +:1096A000D8864553F5C6055EDF691A8A8DA37C2DE1 +:1096B000783006ACBFD13912D577F7FB10A8547FAC +:1096C00066A3D58BFDBFE34967FFA37338BE76FD64 +:1096D000DF8879FC0DC8D46E5628318AF0E882AF55 +:1096E0004112C7F166623AB66BE2ED06172CEF1E27 +:1096F0000F156BCFE919DD912679D672F710BFFEF1 +:10970000624E060C06FB9F4C02F25F8D717CECF6FC +:109710000C2F802B90ECBB2C8BE30770119BA7F4D4 +:109720005DB9341B2F9EB9434B307E8C36F46948AB +:10973000F788B1AF1BF5D6A9B80A7213E2559C0F92 +:10974000B65CAC81316D3E9BCFFE576473274CAF46 +:109750009746E1AA9F82959007722D407F6701E9A5 +:1097600049D2FC0F2E7890E85691AE4548570A0C26 +:10977000F6FC1B427E7CCFA401E54A33D2B1F4A2B1 +:10978000E9E38C20FF5BB1D74C6C4301FD3FB5E7AB +:1097900097CDAB6B7E892F0F81954B235FFCCE79E4 +:1097A000B3CBEF09BE5FDE9826FE561A7F3AFD7CEA +:1097B000FCBF0683FA012D134B84A7F019F58EF731 +:1097C000A15CB335691E62552E63E37414F0DB3D72 +:1097D000DE249D4AC621C75F137C1AF54FBC50D8C2 +:1097E0009F1B9F6F897ADF029D4A9BAECB9EE5E36C +:1097F00054EAFF47C8E27AACEF5A574ADAC1F77B1E +:1098000045FDCB9F73D62BC59F8F4FF2271D437904 +:10981000B4D723FE59330184C8D05F6839C025F816 +:109820007F5893DFDE367E172EADE3D1E4296CBF7F +:109830000D92F302CD6CBD78939FC5729D62BD49B8 +:10984000FD42487FFD52217732E9013E1EEB1E5852 +:10985000FF61D19F2275013079F6B543762743ED3C +:109860001AF9784E62FCDC0760CED20BF6F5137C59 +:109870005F5FA967D7E27E7EA5C20861E3D580EE6F +:10988000C712EBE758BDC8B290C946021FFC594D3C +:10989000A288DCF8DB20EDAF61E3B7AB8E75E1B7F2 +:1098A00092807A211C839C3F02A04BE128E1BF02F9 +:1098B0005670FC0D09FBAB538C5E858D23C73DE6CE +:1098C00041F6B46615ACDC54208786C4E5B737EEA4 +:1098D000F1205D434CFFFBD8928CCC61EB1DD7434C +:1098E0008CD91B45E47652BFE765C8CD60FDE625FF +:1098F000C82D657008562659BB8C0F569EA471C1A1 +:109900003C5844CE364A7C5EA5F8C4D9B3641740AF +:10991000F65AB20B32B48ED578C6C27D40B322A6B9 +:109920000FA7FDCCFD5CAF2960A19CD4C633B91A4A +:109930007C6F5CDC84F8CE8AA7E0B5565E9E28C0BA +:10994000570BA563643F355D2CF515EC63CF33F9F8 +:109950003951206F233BB81D30D83424F4CC8749CB +:109960007FDAEF3F20F8A48E3364902E43CDCE975C +:10997000A6CBF588545C4F6C16F4E2DFD5CB9DF294 +:10998000AACC14F2CA86F02940F235FC1464115FA7 +:10999000C6C9176E63F0A52F6AB093C9572B1CF583 +:1099A000A0FC5C0613549AA0CB582E0193CA3648EB +:1099B00050F9DB0E26F7ACDC6631799F4FF2FF3EA3 +:1099C000898DFF9B39C98511F6DC1F4F5F81FB0B29 +:1099D00093FF8DF89CC98984F2546741D1FDB2563A +:1099E000E2EB75AFA2FBB1DE5E0B483FEE97FAD318 +:1099F000B84F8C083B69C40F8E75BC47D03D22CA56 +:109A0000DA7812C6717ED9BCA05E7FBEE9765AC7ED +:109A10003E85C3436C5E48EE56F37DCC8D8786F35E +:109A2000B2E8FCE761E31F7F1E86A4FAA2F3308C44 +:109A3000F3B051E2FA53FD391FBF0C7DB44F6FEE06 +:109A40007D9CF8AF9E3CB7FA36FDCB5D7A7385D02E +:109A50007357C2C45C85E9913B7C39559108EF4747 +:109A600010EF377F72F403480F8C2717E23EC5F0E2 +:109A70007E54223D9982A36C7CE515398B7E8A2722 +:109A80007883962CE3A780CEF49926F4D97CFCDF6A +:109A900046FDF5E074FD7BF1E10F1D237B03B4E48B +:109AA0004ED44FAB531ACA457FE3060DE568B89113 +:109AB000C128373155932E676508BA50FE6CFB6399 +:109AC00028B669A4298A768FB91CBBB5C75F1B4B22 +:109AD0008244CF93337C4DCEE73FC3F5AF2763324B +:109AE000A34FCD5EAB219D83FA06ADD0EF5243C9A3 +:109AF00098CAE47018C7C3F1BDA9234D6DA83F6192 +:109B0000691FEA733D054B51BE639D84E7DAC68445 +:109B100086EF7DB125E03390C509B2AB86A24E7FBA +:109B20006EB8F14EB89DEAA7E0F5D074FBDA174A9B +:109B3000815AB04FE03872C13CFB94540EE99263F5 +:109B4000C5F5EE3F09F9F71809DA6F20F3494B63C1 +:109B500072EF1532E08DC14FA4CB0AE6295AB0EF5F +:109B6000B0791AF29BDDC5D625DB419CFD9A1268BF +:109B7000CBABEF776ABF15F39E5931324EF31ECE51 +:109B8000E0BCF733BD4FFBEAF170F61023A1777507 +:109B9000EA317CEF4D2BD017A56E5A709FBB5B7ED0 +:109BA0008789F2B707F9C6368EB11E8DCA9D3D3A38 +:109BB00095233D312A3F19FCC467C759BBED699F06 +:109BC000EE4339C8DCFD25EC8F79DD899DD86F9493 +:109BD000F58FFD2A9A7E484798EF3BDE382F6FF1CC +:109BE000703ED67802846F9B87DBE10658242F19DC +:109BF000BDBC9F5ED3EEB473C366606A3DB0FF82A6 +:109C00002D750ED86F5CE4A8EF5E2F2F79B8DEF0CB +:109C10002A09305BB12CAEC7CF4A32D593E5C513C4 +:109C2000687F28B354B20B0625A7DE7ED4C3F7BBEA +:109C3000273C1AD11983896F9F65FCF0EA1EB27B1D +:109C400022B5F30FE7903FF5AAB9801511EFB85E82 +:109C500057643C882ABF1E2F58E74F4956DCF3272C +:109C6000C0A769F4F7763AE47A9787EF7767C57A01 +:109C7000917D5637EA9918134320F9301E473E78F4 +:109C800082ABCC16C687C15AD5407F68A0D7537423 +:109C9000DF71F341AEB92586FAD1CDF76F09397A74 +:109CA0005AF07DCD99F7909ED8AD7BBAB221E4DB16 +:109CB000D12ED4F3036D1E0FCAF99F0CFF5C746C98 +:109CC0009FE4DF241DC4B78128B79BC774263FB823 +:109CD0009EA35C7E0CC875D17B93D1254DA7CBCDBF +:109CE000BFB79B3E9BEF35B59E44B615F19B481020 +:109CF0007EAB94A2F8FD47F1DDC62B3489578EE385 +:109D000065FE69E0F594943C88EB7B8F90D73DCA63 +:109D1000B8867A216ECB4D90AFA3E97A4972C83BE1 +:109D2000EBE7F3D8CFFDD80FAB7FBF32E1E8C7AE8A +:109D300017463EF07591E0EB42F9A3AE0B1BAF9DC9 +:109D4000026F03B25CAE5B8ACBF5DB8D97BD9FF6ED +:109D500005AF02D437B5A104D9DFB342891CF2ABF9 +:109D6000BF5E35D0FE618E12EDD7D4D428F093EAD1 +:109D700037C6B0FE607823D9E583DE04D9E947EA27 +:109D8000BF66DDC6E8EA3F53033E93F903C1AB8EDD +:109D900018A8178FC8E4AFF59F699E952A32CF4166 +:109DA0008C8F31FC03881FD9D5EAA4118EF8F68771 +:109DB00098E263FDBCD10A59D4A7DE901543BBBB22 +:109DC0007F9166F651AD04207FFB821F684FB64E2F +:109DD0006F1F0C0D7D4CBE6C6A1CF6279D45DB97F2 +:109DE000EDE1E8C7137D92E37D513C2AC1DE29589D +:109DF000A7FE196C68D8B5649D6D9EE23BA3A5458E +:109E0000C17D130226CE7F3CD1D5F73BE4D3F76466 +:109E1000D2836EFEFCB59C0CC8CBA6606F3449F3B0 +:109E200066F7775DBD427A546984AC4FC251135DC9 +:109E300068DFF6377A28BEA68436D494B5BB1BAB50 +:109E4000B3BB41C43D6C79E8F8391F376072FD1D22 +:109E50008671C0B84A0DF0B8462D1812507B534A8F +:109E600050B06415C553A2FEB7BADF5BA85FC9DA6C +:109E70000B6783E7D0AFC2FA6D7E1BFAAD80AF1FD0 +:109E80003E45FD32F5103D3B63AA5F6F2C450FE167 +:109E9000CCD9B3F272E04DE82F49F2AD784C5A9F1D +:109EA0007051C43CC48AC1E89D0E7FEABDF27C4774 +:109EB000DC54D5873E264558D9B8CD1A2FD00FEEA1 +:109EC000F9EDC681D0BF6CDC628D57A137D0EC2E86 +:109ED00016971A5293D95EDCBFE786288E084A8A05 +:109EE000E2C2C352DD12B49FED7A4AA39A43BCC2C8 +:109EF0006D561AF5C5F00C8F299BD8EFD851F40791 +:109F000040BEC14C96892F298DCA2F0BE9F9CF721B +:109F1000384A788A38577F05791FEA297F3EA1AAF7 +:109F200066B2983F9396B9FDA2068ABFBF5AEDDC90 +:109F3000212F9BCEB70CF28E3D1FAE652EF7E55C50 +:109F40007C500E94C6EF1E433E0C35AC8B95A31788 +:109F50007466E714F845A66AED94CBE3B1A7181E22 +:109F60001062C2B3B2CC38627EF5AB4D1EEF40A595 +:109F700088E771C23E637847A4995C4FE3DFEEB691 +:109F800083398CA3796F0B59387FB2F524C8ACFEA6 +:109F90000F1B6490DA110EBCE6A1F95C6592BE6AF3 +:109FA000E1FE9DC5FE211D9155AA63DF42FD39B931 +:109FB0006F35A1FC3BE1CFC9CE78667FCFB3F0B35C +:109FC0000553F8B34756B178B1A2761E2ECE8FBA9C +:109FD000AAF8B19FC90B3079D9C7FC46C614C8305E +:109FE000BF11E13DCC6F04F2270D2A077A5AA8DC95 +:109FF000854D57E2F9596AA4A909E3A59F8E7D9082 +:10A0000055D98FBA83CE55029D183FDF69C3EC89BD +:10A0100084B03867F941FFEF3A301EB3D3CF618087 +:10A02000890ECB01CB7D18EFDF19E6ED7F26873A4D +:10A03000F13C62BF384702C5D2DE57E0FFE7652F2B +:10A04000D18136106FFF9B5EECCFAF08383D87F0B3 +:10A050009984191F111FBFC6E1C681B9D43FA90059 +:10A06000365E7C601E1F6F01B7EFA17543053EF69B +:10A0700091FCDF84877048736B1D1E2A836A9A8067 +:10A08000DBCDFE5A817795FD8092E4FB9D882B9570 +:10A090005E3715F6358147A5F907F44B317EC1F4DB +:10A0A000701AC7FDC7E2FBF45B3DEE7EEFB9F145E8 +:10A0B0006D9F482B8CC57F29277585C161EB70AEDC +:10A0C00089C1911B72695ABE558EFB6B5917F1D02D +:10A0D00024AD7F9BCF8ACEED8EAB5DF3E88D5A74B5 +:10A0E0002EE90FF1F5572DBE2B719C827EE0E9CE53 +:10A0F0008644B874BBFA8467CADE62FFCDE80A4CB6 +:10A10000D96BECBF5AABCE01D7B45FE4A81F36E7DA +:10A110003BDE7BF57738DE9FEF3C5DE6A2A3D9E618 +:10A120009F80636E3AAB963BC510FB5C9ADB8F93C6 +:10A13000B0D88F2BC167163A61DEAF0F6EAEE1F675 +:10A140000DB763FE13883A6E3CCC02FD2B633D0EC7 +:10A150001B1E096CFB36D732BDFF7EED131487B38F +:10A16000FA15F05F353D4E97EE4C519C2DDDE7D34F +:10A17000FBA31477A338DB7666C8FB58B9CD9BDC0C +:10A180008AF27BDA3F370B11EC37B502E3D6FDAE2E +:10A1900078825B9EE29FBAA9E879995D8EF4F0F827 +:10A1A0009F0D6B8DC5F300EE55F879FD77BDC97B2A +:10A1B000110FD48D40715AA075E035F8FEF87CD3AC +:10A1C0003AF805F9FFFC7C4C85F4B166464F86F9F8 +:10A1D0006B3B0DA49BAF9391A6755A9C3DDF5BEB47 +:10A1E0001136DD04D94F998E990DB89E6A94093ABB +:10A1F000B7AB8917C7E77EC523E6EDD6B2F4B9E75A +:10A20000E3560CB4B2767BE7481EE2FF1C4FF61013 +:10A21000C6A31A3DB4AE775BEAE378D4BEBBADEE1D +:10A22000268AA75BAA47263A725AB1753828ECA647 +:10A230007E113FDDD3C8FDD6E73B5ED7F0BC668F0D +:10A24000D949F9004AE687D47E58F03BB3F804C5F3 +:10A25000C9874B9CBFF429DCCFEF0F07BAB345DFAA +:10A2600047E87DA6A9E38587900EA67F0F917F061C +:10A270000D5B181DBAA52F417EEF9D63797E81721B +:10A28000B5DA437216C1B89C8CE7A24EFF79EF6A2B +:10A290000F9DB366F49089F6FB29EB0DA08D48D194 +:10A2A0001BF07CB1E6F8953AED95CCDE6928B0F369 +:10A2B0006B56A556E07CD974F9607DD1F990E66EB5 +:10A2C0004F223FEF5E0206FA63BEB95DB94758BF41 +:10A2D000A757FA7454055787AFCE7D13E5896D2BC8 +:10A2E000E827FBA2560EED267F77100CF63E123BB8 +:10A2F0004C76941693C142BBEAFFCA345F4C671098 +:10A300005DCAFE9547D7B0F6EA6ACF2CB2CB5AF9B0 +:10A310007EA3B37FB8DF6871A75D257B73D4DFFDB3 +:10A32000E38FD3B9B2EAB2AB1428A88F76D7EA0D7F +:10A33000EF692EA20FEC521E8FD0B92EC8B794B57C +:10A34000B343C73FFC0F2F16F0FD84E2B2D385FD67 +:10A3500066F753CA7E3BDDB3F51F5E64B29CF4F230 +:10A3600038A8A25ABFC47579429C2FEE75E5DD244A +:10A37000BD7CBD9C16EB186716FD6DF48F915F03D5 +:10A38000D76CE47E16980E3F86ADF7D34A819F6D59 +:10A39000EF7719ABBC3F3195D712F2C7CBE4B5AC20 +:10A3A00057928AB74C5E8BBD5E47575B1063F33B99 +:10A3B000560BD93E9CDF35166C467995C0ECD379A7 +:10A3C000FD09FB1CA509E5F01AD882EBD7504C3CDF +:10A3D000871C6C7E3773144BE3AB449DF251691EAE +:10A3E000B7BBE671B6D769877B2151936BC23846FC +:10A3F000EC26C463775435713D7A3DB76CDD644C0F +:10A400009F4758C1F586379A8362E3DAFCBCC36B79 +:10A410002DF4629C5D358F2551FE3B55F27BDDF5B9 +:10A420006FF58A3C962650D03E4BE33AC1F5DB658A +:10A43000F1BC31494F3D6C12FA09C7B956FC4DCAFF +:10A4400067FB940CA919AB006EF436713DD3B19142 +:10A45000DB3DD78324D762FD24ED5F0D962EB1BE80 +:10A4600061D4B6CBF4DB62EB0BF4E48D423EA7DEA5 +:10A470002763EF73BCF7723CC3C26ED637C7D62FC3 +:10A480002AD2BEB6B89EBC5EC8F58D5E614FA437B9 +:10A49000535ED0A0714B02F93CB0C632B7A0D64291 +:10A4A00019C17C941038EC6326DF37223FEDF89118 +:10A4B000A227A8B4ED8152F3EFB603BC3167DE49A1 +:10A4C000B5E7B6F1FD37951DC7BD3FDBF96DA8F9BE +:10A4D0000AF9E4157C6815EB65CA5ECA88F56E5208 +:10A4E0003E90AC5A498C4BCA1238ECADBD425EE48A +:10A4F000007FEFC683F9CF77E13A952316F9D7109D +:10A500006AE3769B621AEB8BE06F9F733E21F278D1 +:10A51000E39977D3FE3756DB49FBDE805E5E7FD85A +:10A52000FBEA1AB841C3B8DD6069FD3156A83FD4D3 +:10A53000A8C7B98E857FCFE8378AF1D9E6534CC4D6 +:10A540004BFBC31B6365E382AEF31553B51E22BEFE +:10A5500094E6DB23E7C3B7319157B763F0E51744BF +:10A560001E82535F2F2EA9AFBFE0D0A7425FBF8DE1 +:10A57000FC7FEEADE07FB57118FF76D9383983A93D +:10A5800078254DF48C1AFBD2148FC1F58D7640A638 +:10A5900083F215200EA417B121EA3BBF6111DF023F +:10A5A00022CEA4363AF719391A70C0B1EE3460BE23 +:10A5B0001AF68B74FBB7AB34AECD6F66B3503E99D1 +:10A5C0006D5FE272427FA4547E9A5DDAF11B3CC655 +:10A5D000394BFBD4C78F207F4F8580F687D2F43B61 +:10A5E000C789BD37515E3FB9EA4348315E2F722EAD +:10A5F00038BD9D02AF17E8B5FFE3D227D693B775F4 +:10A60000931E058F89F1CBFED8464832BC8780EB7C +:10A6100093112C57623EC9121DFDDFEF7A0DDEDE6D +:10A62000E0FE9D4713717AA33A7FEF6EB60F15B324 +:10A630007F2E56B97D7CFA13A9DF625E427AA76449 +:10A64000E0FE76B2274FF6D3A6DC252AE6A55DA26A +:10A65000CEA47A9BF637A96B0BD6E726E0E7FE0C73 +:10A6600011B5508FDAEB4FCDF85E403A4F64785C0D +:10A67000E344E6DFE85CFFC401398B4C3D31726393 +:10A68000D9F57352E86DBBDEC903B285FDA547A4B9 +:10A69000EC02D6FEA462458AE60140969F070BF8BD +:10A6A0008319D92197A7772455D433277B34E967B9 +:10A6B0006C6E6E473A19FE9B324D2AFA6495E89A01 +:10A6C000A13AE7D3A67310F3159AA6F27706A36F03 +:10A6D00010BDA7D873B94C3C69A7D01383D1E2FA57 +:10A6E0002420CE5F03DE6CF1BC0717BDC116E7BAAC +:10A6F000B4F11B16F914C33AC76B38E6A179186E8A +:10A700002CAFC706C43CD8F50663FCBC755049683D +:10A71000D5E0E3D59DF8941A475B75B80BB7F91AE5 +:10A7200048767536117B5FC63802850E0DF49F9E04 +:10A73000923EC4D6CB0F6F0B59520C1F4EE4BEC9CC +:10A74000E898C5FC1DB44F752B2BCD6DC3BC4E19BD +:10A75000306EFCC89FBF917B15FD51E6FF205C6BFE +:10A76000A4D65F6B601E5C52C275B51B953F75FE2B +:10A77000AEFE8E56B1FE18FCD1A1CEB5188754207E +:10A7800021E2191E03F3F568E97B4AEB09D49E67C1 +:10A790007D53ED4AD2E9F28B7CB0A1BCFFBD95D7C9 +:10A7A0004FB37FA87766B9FCACDA6EA7DD5DE37ABC +:10A7B000BF57C86B29BFF2AD1A6726BCACE1B9AC74 +:10A7C000D6E6D1B3581F52B5B8DF466E5100EDF84A +:10A7D0009986DE8B21BE4A7CDF053CCF0DBF8828E1 +:10A7E0005C7F9F51B91DDB78E7A725DC9F4EA197C1 +:10A7F000BD18E1BC594C7EDD76DF887182E2894369 +:10A8000070B4AB19EDF92D1E3A4FDADDB6AFB6B024 +:10A81000FD77C43853F30F86B29C4E65C99F57DB52 +:10A820003C16EE5BE73BFF6E3FB9D2FC376C75DA46 +:10A83000C5E73A2F2F21E2CB2ACFFF858E63CFDBEE +:10A84000F4F5C1F566E39D2F521C67CC2CAF6FA6C3 +:10A85000CFDBCB346F9136B08AC5717E2CF6317761 +:10A860005E9F062930313FF115BEFFC8CDCB63078F +:10A87000CBE81F39EEF23F443FF90F021CC5FD56ED +:10A88000312A7C0F7778BFC2F6CDE0F62BF72B4B41 +:10A89000313FCBA23CAFD11E8B9E4FCEBFCF23F01A +:10A8A00095C0B35CE81583CE3FF72B646F78E02C3E +:10A8B000C6414007C3963BC07A5DFB158AC7182284 +:10A8C0008F80559D89ED80F4D2624CF6ACA7737AE7 +:10A8D000EA073BE271986E0EB386344F5ECB22BC22 +:10A8E000948C7627E3E72EBF800D01D70A581770A6 +:10A8F0009380611FC14195C11897F7667482030266 +:10A900006E12709D806B053C5FC0D23E8277A9BC01 +:10A91000BF9D4A96F71F10B021E03A01EB029E2F2F +:10A920006038C8C7F77118F7438283026E12F00CC3 +:10A9300001D70AB859C0D241824BCD5F206E117F3A +:10A94000A7E6BF8BF30D40F89B0917DC3D55BFC050 +:10A950001F1DEC31A4C2F3436F89F8D3121FD73304 +:10A96000131D09CA5362FE42FA44E1B963ACB8BC94 +:10A970005BA2DDE4B97994D52B1ABFEE2DBA2EAACD +:10A98000C56FDD79E2F7DEFF20FC6EF6D9EB9EFBAA +:10A99000E7131D26E1E9EECFDD0EED2D2838A70FD8 +:10A9A00028D934C66B988D44FE8E5773E6B3DEED1E +:10A9B000E3E79CBD3E9ECFDA2FF09BE8E0E70F83F4 +:10A9C0000B02D983D2F438E35FF8783CE1FB369E82 +:10A9D000DA61F27B8279B662C90FE27ED468BCB3D9 +:10A9E00042FEBAF2FF0AFD65771CE4DFF01D1B276B +:10A9F000102ACEA7BB27F5CD2DE913ACAEE667CF65 +:10AA0000D19FD1A3B1C6C2BC69F11E248F4CFAE517 +:10AA10000CAB67E78BC8D43F8F1737F278B12CEABD +:10AA2000D3384DFC3B066B09EE33EC798B18479A13 +:10AA3000DEAFBB5DCE57C7E74BE063E7A7C8F01CAE +:10AA4000F533898F92207EB99F631EB21EBAF0E75C +:10AA5000170A7B8D12E365F8F94BA5F69F15F232C4 +:10AA60004D3E4BCCEB7FF3D976CA610BF3816C3949 +:10AA7000B2E5EB7CE5E882E50437A4B6D2729286B3 +:10AA800014AD1B055DCEC5E72E2F45E4245758BFF6 +:10AA90005EAB15E7F926C90BC34721B9D5393EF599 +:10AAA0004BA2D49F846B7C21F62060E403A3F75271 +:10AAB000AD56F081C7290278CE58D09E1147F84A8A +:10AAC000B224F43EAFB746E3EB7C756723C71F445F +:10AAD000FF2E7C597F5A617F3234BAE49CE3FD7EBD +:10AAE0008DCF2FAB4FDFF94D1B5F91085F191269B6 +:10AAF0000F6BF75151DFADBFEC7287C06FD4035BB2 +:10AB0000F977920928FCAE32A879C4778F7C9DB979 +:10AB1000F59317E56AE9F9CB55B57ABD5E2BBEEF23 +:10AB2000303DDF82F1BE52FBCE316D723F6811F3D2 +:10AB3000764EF3FE6BD443CBA6E6B35A7C2F15E3D7 +:10AB40009E2BBE27A7E35B959CBD21F444B5F8ADD1 +:10AB5000394FFC5E76E1F756C9F519B11F558BFFE9 +:10AB6000FBCF531E7E309DBF55AD238F766EFCFD0F +:10AB7000E879E2F7CF6EFC4AAC5B55E3FC4A0397F9 +:10AB80000F459CBF548B5F4F65FC44BED8BA012B68 +:10AB90004EF61AF9E3BBB5750369650A3F0BB85E5B +:10ABA0003FD7F1EFAF7AFC770F58CAD4F88F68EF30 +:10ABB000768CAF2826095BB5E33E5AEDB8E9F73944 +:10ABC000E87E7AE47D8E71CF97EF5FAC7AFC5B1DF7 +:10ABD000743F3772AB93EE9049F9C4D58EFBCDF339 +:10ABE0005CEFBF14F80635DDB10F94B2DFCF08BBC0 +:10ABF000F6839AEE90E352F5DF10F6CABBAAAC7F5B +:10AC000052F4DF6CE353A1FE3D02FF7BAAACFF6B65 +:10AC100081CFCA2AF1F9BE5887A5F6CF80E07B1014 +:10AC20007564815F73A1794B5B7C49C98FE79CCFC9 +:10AC3000F4D077826F289A8EF14EE802B2C7FDC732 +:10AC4000C307795E495AF8FFC9B4C4F530C5B7BC2B +:10AC500051D3711E67FB5D8A92B08A9DB7D5FAB950 +:10AC6000FE9374B39BAF7715300FA954FDA0BF7846 +:10AC7000FCA5062628FF0462E21CE9CC8D46D173B0 +:10AC8000022541792DB2AEC24136CE40ED46A33009 +:10AC90006F396EE313B3081F55E7F8A88A6915CB1F +:10ACA000539EE3E7F36AF763FB87526C02F83D0EAD +:10ACB0001CBF417FA21BF3C4D3B52AF16920EC3C31 +:10ACC0001FBF49F4F34E41DF80B77C9E58E7CC7636 +:10ACD000CA57EA6FE7F94A069894DF39102A7FAF1E +:10ACE000C1580F8FFFEF14F94F23F8FD287E4F8CCA +:10ACF000DF8F2EC4F65FA1EFF04EB57ACADE8F1358 +:10AD0000369D71F6608BF37B1E3B2EEF379CDFF593 +:10AD1000F862CEEF7ABC3315CAEB1A08F1F3814A18 +:10AD2000F8DB79EF76BD6125A5E945F994759C0BB3 +:10AD3000F8624E7CDF3EFEF1F641EF61BD185E6FBA +:10AD400015DF4AC51B26E9AD515359AE371CF91919 +:10AD50003D42BE7C355A0AF532D3BB25DE0778FB6F +:10AD60005082F243B458C2A078B4D807345C0F05BF +:10AD70007CFAA4BD2E031E3BDF98F23A24C3A2F353 +:10AD8000470DD79134BDDDE4BCDA72FFFBB5315A13 +:10AD900027F51AAD13C998A0EFBADCE32CF45BFBDE +:10ADA000FC783EE6B71EC0D2FB0739596CBDECF506 +:10ADB000733DAADD9030B4F9E4AA92DDE3C6E34B1B +:10ADC00062FD856CFCD316E55F548BFFA355E26FE3 +:10ADD0008FC3F0FF1CEA5986FFE7B12C85FF534271 +:10ADE0001FD581D14B7BB6C1F52CC07AA330BE1ED6 +:10ADF00008F07EEB849E02E870E4F578055DD5D21C +:10AE0000F3ACADD72AD0638FCBE87951CCC777CAE2 +:10AE1000CDC7B7053D8100DFB7B40309832D4DB819 +:10AE2000B8C4BC9C1078CC0C88B852BAE39CE4EA55 +:10AE3000A52AE93831352FAF8A79F9E772741C17E2 +:10AE400072959161E549DC4F9BEDFC850D8E7999FA +:10AE50002DF893F1D9F3D2E99897DA739C975F555F +:10AE600049CFECA979392DE6255F4ECE0AEAFF5E7F +:10AE7000D4FF83A84F76E2ECC0EF06F0BC6CA13F94 +:10AE8000E109D44FED6FAC9E1C583655EF93A347A4 +:10AE9000EC7A3EAAD735594F0B14F407E9D706F0E0 +:10AEA000FC7B507CFFF1FDD1F035A25D84DADDC082 +:10AEB000E961ED6A0AFBFFD2E82B76FF33B05EEF63 +:10AEC000DA3FD8F5A285F56607FE60D78BE173E916 +:10AED000C0647F0D85789CF0FFEB00CFD771E57BD8 +:10AEE000E9D5E53B78A349BACFA10EC2199995439C +:10AEF0000ABF5F21CD8CEA43983FEB4BE6A00ABB2B +:10AF0000CBA3F1763E666FE1F9F10C1D9EF71BE8CD +:10AF100082987080BDDF1355C81FB8D39F6C0BD4C7 +:10AF2000733C290FE0556E8FF586DA441C85E3B536 +:10AF300037F88111EC4F677861FF9F0C469EC7FA86 +:10AF4000FBE6A894CFFBFC9CBBC84EDCDBAB00BE91 +:10AF5000DF7B9D4A76E203AF86691F1E54CC9B2897 +:10AF6000FFC1520DB41BEF0EFCE118E6298FF7D696 +:10AF7000E8D255440FE19FF640A29FFAE776E776C4 +:10AF8000863FE603D3D685FD76713F06449EF3DD0A +:10AF90006B0DCA9B3180DFDF34DCAE529ED2DEC641 +:10AFA000F91D38DE03ED1AD91D0FDC30BF97F2B959 +:10AFB000DB0394FB56173224CCEF89AC50013F04DD +:10AFC000A98B1ABD6877869707F0CE2FA86BE4E3AC +:10AFD000851702DDF3E7854C22CECAC8884AF738C8 +:10AFE0003D70C386DC66B46BDA79FE3223ECE5F89B +:10AFF0007280906025C83F00C4C73B9B9FE7DBF38E +:10B000001CC94CB62F7B8E18C956592F575DBDF001 +:10B010008842F9C915EB65AAAC97ADB25E8ED7AB85 +:10B02000787E2FF22935F60FE3707E773E76A8FC06 +:10B030007771E79AAFBB37E0CCBBAED4DECED3ADF1 +:10B04000442F1E664EE22957AE6FE7D9957AEF9DE1 +:10B0500079570CBF4B1BAEBF5794F7F1B2413C6F11 +:10B06000D81EA3FB221BC4FB86FBE8FE48773F7F6C +:10B070002BF4710B24CACE439DC0FF75863BC6B32B +:10B080005B940AF900EE7C3F97DED3947427ADDB26 +:10B090001B787ED1E4F7938DE2BB114825E214CFF3 +:10B0A000B2228B674EAD1FEFAAEFD2FAB1BF9B64FD +:10B0B000F3C3BF9774C9895B2E7CAEFC940B959348 +:10B0C0001FBF4D72E21D91AB5A3FDE4C95F5B25554 +:10B0D000D6CB55574F1D91AAD22B6AA6CA7AD92A28 +:10B0E000EBE578BDC195AAD8D7470731BEE5BD428B +:10B0F00073C08357049CEFAF0C39E0A165CEF6EA2C +:10B100007267FBA1E5CEF6EA0ADEDE0CEEBF261D75 +:10B11000AF7E9DFCAFF35C272D5AF9FAE1F60AEBFE +:10B120004AD3FDD8BE4E3100EF1762FB5556EC5B9B +:10B1300045E33FEB827CFD5F17D01DF7D3FDA9D31C +:10B14000D912E4F8DAF456C2D7D6BFFF220BBBAB54 +:10B1500044DE3D7E564079D830DE80FD3D7FCFCC49 +:10B1600006B4E7F6BEB682EEEFE87F979D376352EE +:10B170003EA472EC9764BFECDDCEEF977EB4D6ECC4 +:10B180008AA3BD12F600DACBCC8DA27B3DF6C63C7D +:10B19000648FF45F5DFEFE924FF5F03CA187D1EF26 +:10B1A00067FAFF80B877EB4171EFD6FD3D0695BB9E +:10B1B0007B5AA8DCD5635239DAD3CEF3197B2CF154 +:10B1C000DD5917955FEA49D0F32FF47453F9F99ECE +:10B1D000243D7FAA672B959FED49D1F3433DDBA921 +:10B1E0007CA2274DCF1FEF19A1F2B19E0C3D1FBAD3 +:10B1F0007A03DD9371EA3E0F7D1D520AFF392967FC +:10B20000DC61F65667DCA121E98C37CCEA76C61BF7 +:10B21000F455F31DEF236DEF70C0A1D6258EFA8192 +:10B22000F8150E586BEC74C04AE89D0ED87C6E83FE +:10B2300003BEEC999B1D70EBD39B1CF03B3EFD11B4 +:10B2400007DCF2A93B1DF0C5FBEF75E0171FEB73A0 +:10B25000C0EB83F3F97DE0033B1DCF8DFBF639E0B6 +:10B260008FCCB41E0B623C3413E1F6EC7189F6C14D +:10B270001973CDDBF03B29F8B14CF204519E0F3F1E +:10B28000637EEA72BCA70C94D48A1BC395EF91B677 +:10B29000E33D72A43D89F27AFA35C9407B578A6C46 +:10B2A0005F58E8CFD9E5D65329388C71499167A604 +:10B2B0005F0496C5DA05983EA1C34548E57650DCA3 +:10B2C000D243DF5165A424E59B309BD9FC2B1DF3B1 +:10B2D000E8DDFB6F90ECF253519ECFDED1A9350D26 +:10B2E000B0FABB17A926A6784DC3D775BFDDAF82CC +:10B2F000DC0FDEB583C72BF517FC4D1A6B1F32939D +:10B3000033D055B5DB8572DFA3EF944286B91CFDBF +:10B310009A503C039B43588F7FD7C7EA7F3558200C +:10B32000BFA164CE5259FDD89664B387D5DF2DFAFC +:10B33000DFBDECC7748F6038F713B898FC9DCFD091 +:10B34000F8E1B6A3707B18F5D338AC2BB28E77FF3B +:10B35000BEF8F748E34199DAEFEECD82C9DA05721B +:10B360005FA77B38ED7909B61E8524F6BB6A82BEDD +:10B37000A1DDBD43A27E764B2FC56282CE5E179DB6 +:10B380008817D2753BEB27D49D94D6B5F2E7CDE173 +:10B39000A97EF1FD667C7F4B4AC23CF76AF8A72282 +:10B3A0009F928C7FB8DEB664A4B2FC337216F25B57 +:10B3B0008B57E2DF839C7F8C6FB7B74EE7D764FD76 +:10B3C000F45158DE5AC06FD11EF9727B11BE4EF295 +:10B3D00089B54F52FB97606988B7433E8419DD9B5E +:10B3E0008BB5935E12E3649DE3303EDE4ECFD322F5 +:10B3F000BEC8EFF5B4F344ECFAF8D7B55CE42932F3 +:10B40000BABDE3B59BF1FBEB8ED624DD033C18F20D +:10B41000D0FD4283A1AFE4E89E7E1DE8FB5945B113 +:10B42000FA7E14E571E83EA9D83A75FA09F8654A3A +:10B43000E1F76403213B0FBF82BD24EE1596C5BD25 +:10B44000C2AA92E86AE2EBD9EC85A9F8EAF4F1F72E +:10B4500011DD72CCB9FF0E6C71EE7B71FD668A63F3 +:10B46000F747ABFB6EC897E7F6A52AF0F1E683FC39 +:10B47000BEE3BC9FF0B4F233A85C93AFA5F2AAFC84 +:10B480006C7ABF3ADF40F0AA7C33C157E69BA8BC78 +:10B49000227F293D5F99BF84E0F6FC522A57E417CA +:10B4A000D3F3E5F92B095E965F49705B7E2D954BD2 +:10B4B000F31D542EC95F4FEF17E7AF23D8CCDF48F9 +:10B4C000E525F9F554B6E4FF8CDE2FCCDF44F0C55A +:10B4D000F9CD042FC8DF46703CFF51829BF31FA6B5 +:10B4E000727EFEBF52D994FF18BD37F21F27785ED7 +:10B4F000FE1E82E7E6FB099E93EF25B831BF8BE085 +:10B50000D9F9512A2FCA3F4065437E2FBD9F957FB1 +:10B5100088CA99F927E8796DFE712AF5FCE7C57D9F +:10B52000D14F5119C97F95CA70FECBF43E94FF1BD1 +:10B530008283F9AF5319C87F9B4A2DFF3C9595E64E +:10B54000A9D2F74F6B6086432E56E72F72C0574E35 +:10B5500038F7EF953F77EEDF2BC69738E065C79C4D +:10B56000FBF7D2A39D8EF78B8FBCD3015F9273EE56 +:10B57000DF0BB3CEFD7BC1814D8EFACD998F38E0C4 +:10B58000A611E7FE3D2FEDDCBFE76CEF73DA2FA9C4 +:10B590009D0EB861AB73DF9E050FBBF2C90F3AEA8F +:10B5A000D7589F73D40FB77FC575BE92E5FADFFCFD +:10B5B00086D38E6979A1E8394C7CFF75F4DDFEA94C +:10B5C000468FB86748DCDB2AEE4773CF679DD00310 +:10B5D00033F2DC7F8A8A75578FEBAE20EF89D91959 +:10B5E000AFA17EB0ED8C19F38D2FBFC8E0D373559A +:10B5F000B397C1B69D61D7AFF8BB15AA399E6678DF +:10B600007A8FFBE8DE3929D26D615CEDEE1312DD35 +:10B610006F57371B449EC0755D3C3E01F67D3A7402 +:10B62000BFCFF01CFBFDE66B298ED1C4E123A11D29 +:10B63000EB308E3AECB5DF7FFE5A6AEFE7F0FF0899 +:10B640006D19C2F775358763681FED2A71BEF93F22 +:10B65000432AF1B33664FD30B46CEA9EE9E3D1E4E9 +:10B66000CB21F67C9B969C875776E33DF7788FF34A +:10B670003AC5FA11D65BAF58AF84685F70FA0FEF26 +:10B68000C7DCD765742FE04FF0BD1C7996F6A3BADE +:10B69000EBEFA3FBAA86C30C9F50697CFE3E244FB0 +:10B6A000EE3760EF37F3299E4AF6E05013D0BD190C +:10B6B000C3B58934DEE797FE8E06874CA43BC3935F +:10B6C00095447EE2F025862D178EFD092091C33822 +:10B6D0007E301932D05E0BC151CABF88C004953A82 +:10B6E000E892E3BE6D9BFE399C7EBCFF3F44E7F0D1 +:10B6F000D6B3E314674D81B8BFFA4D7CCEF8723AE9 +:10B70000B4AC345FAE91EF039D8DFF28B327918ECB +:10B710004781E33B86FEA98478A6F466EAD7798F51 +:10B720008472FCEB243776BC47915769CD488FB8BB +:10B73000C7A18BFD43FBB03E513EDEE3BEB7E15CEB +:10B74000E33DD1B03BDE13A2F3E453ADE5BF83B3D9 +:10B75000E33E63ADE5CF7B9F157EDFD7C479EF3342 +:10B76000E2BCF72BC2EF3B2CFCBE2FA2DFC79E3FF3 +:10B770002DFCBECFA1DFC7E027D1EF2BF8BEE4C977 +:10B7800012F7BF2CAC95849C6D27FB3E28EE2B62F4 +:10B7900023903D1F10F6FC98D93713FD8E602D6461 +:10B7A000D14FD87ADD41FA7E969162E2FD0077FCB6 +:10B7B000E2F599FF85C1F11838EE770AB4BAEE4B7D +:10B7C000A8348E92B5B0DF20F31B326669FE9C73FD +:10B7D000BF5A16FCE7D52FBFE7C7BEB78D71328DB4 +:10B7E000F21744BA7594ABBFA1714E897140FEC186 +:10B7F00011BACFF07205CAC9C1B471CE51FEB68478 +:10B800005DBF4FE1923FC0840D46EF3CF1BDA611F4 +:10B810004A37EF61EF9FB84F757C9FED96C7DED733 +:10B820007C14871D5CCCEFE579B17EDD45E80F7EA9 +:10B830007AEF9B4D889FFDDD52BFE98C5BCCBB0F3F +:10B84000A4C27C9603623FE8D7CBCBB97DAF78FF2B +:10B8500058F97A0F8A7A5F0C5A7D61D22B13741FC4 +:10B8600064FB89AE9B11DFC77668745EE36EF7C533 +:10B8700060726778D9743C0BDBA3BC9569BFAF5C81 +:10B88000FBE53FEDFA29946FFF70B8BE74FBB697E5 +:10B89000BB1EAE80FFC1E2E3A71FC376F3623CCEBE +:10B8A000D4DB3044F3BB6B07F79F5F5CB48EEE993B +:10B8B0001DA8E5F356A4DF2F54E04B7705BAFEAA86 +:10B8C000527BA93C5DDF2CC717C6D76315F8F29DE4 +:10B8D0000A7C3D5001FFBF2FC1D77988F73CFC7D22 +:10B8E00038D6AE770EE32BFA6FC85798BE1E8AF48F +:10B8F0007BAC1C5E55C8EBF805CAEBCF2BF0B592BC +:10B90000BC4E5CA0BCE64BC92BE27D01F22A47CAC3 +:10B91000F3B592BC06231726AF33CAB5AF425E67B4 +:10B9200097C3BF0A796D2E36BE0F8216DAD5A75A95 +:10B93000F939D9D60E7E3F99B785EFC3C1E39F256C +:10B940007B6980ED5733DA71DF3EF1E01D6D53FB0B +:10B95000B47B1F72F7E7DE47EFF8DF9FA17D342449 +:10B96000F67D1B1FBFE1EEA7FCFD16E73A6E007FD8 +:10B9700097A9E0F72E1A926FF578CE7D3E60F2F12E +:10B98000818DBF96CE159FA673C59AF60B1DB77C09 +:10B99000FD59DD1766177C28E2B40B666FFFEA637A +:10B9A000741F89E867B662D1EFF8297035BFFF646C +:10B9B0001BCF1F92B77FF9B1934B0BEE9982C35205 +:10B9C00061BE90BCEDF063270BF0CA63FC87C79B98 +:10B9D000298F31AE5F11A07BEBC6CA9F67FC40EC9C +:10B9E000E3DF17E71947C479C677855DFBA2B06B23 +:10B9F0005F10766D4ED8B57F2BECDAE7845DFB0DDA +:10BA0000719EF1A0388FC8F41C20784F4F56FC4E21 +:10BA1000C993E2774A0E8B7CC967F9B9454F8EDB33 +:10BA2000C78F7FAD19F93145873B8EC5E9B0EF4728 +:10BA300077D3F12ED379DFC6F52D41C7BC5D6738CA +:10BA4000E322D7C6663BEA5FA3373BDEAFD52E7550 +:10BA5000BCEF80A5CE384BFE0A679C65C21917B9AA +:10BA6000F2E7CE738D95E3CEB8C88A63373BE32CFB +:10BA7000479DE71A4B8F38E3228B73773AE0CB9FD1 +:10BA8000BDD7517FD161E7B9C6A54F3AE322B3BA1A +:10BA9000F739E05AEB61E777F5EDCEB848D874C6D0 +:10BAA00045822D5F71C0EF61FB3DEA4FBFE18C8B9A +:10BAB000F862CEB8C84F43FC1CD0F6B359BBBF8B5D +:10BAC00090BF19CA5DC9E4FD8928BFE7FD09485246 +:10BAD0009E2CC09F93DFA04CFA0D16AD7B59E81D3C +:10BAE000B5E1E48FD1AF517673BFE70E69454E2BB8 +:10BAF000F47BBCFF2215CA87ACBBFD870AFD7B4DDA +:10BB0000F277940A7EC9F47EB9BE9ABAE7BC2D8D4D +:10BB1000F954CAA45F72BDCB2FD996A1DFB39A5155 +:10BB2000DE2F9936CE39EA9FD391127E49CC43FC61 +:10BB30003314EE97EC32855F02FC7B29BB3F5BFF41 +:10BB4000A80DE5F5887D5F8BBA88FB0D4AA8F879CA +:10BB5000B67DDFA4BAB87C7FB65FF37711714F5C16 +:10BB60000D88B8FEFF978FB7523EAEAC29113779DA +:10BB70009BE5A354BD73950F057506E5837C70188E +:10BB8000F3417C2E581370CDFDDBD6E1F74DDB8100 +:10BB90009FEFC02BFCDED552FDDBF95DF155B7966A +:10BBA000CD83B0E3AC522D3FFF8CB7DF4AF993A7AA +:10BBB000D818E5EED576E75BC8D114FEE81E7ECF37 +:10BBC0005EF4DCE79FEA785C28DEFD81B2F68AFB52 +:10BBD00077C1E256F97B764705FEDF7E7516D9A957 +:10BBE000BBB6717DAC747FF37994C74FA33C9A14B4 +:10BBF00057D12E41BAB62974AF5AC8008A0FCE0D5C +:10BC000041B6B709F96AA6F13E2FF647E7CB93F2A2 +:10BC1000B9CD79BFC9EF74BE9EE389F27CADF8BBA4 +:10BC2000062B0F77D0774206A4F45A5A3FF07A9445 +:10BC3000F023391D6E37F9EFDF317C747D7A7B3765 +:10BC40005EEEF5A96CB98AE24AB3257B7D064DCC40 +:10BC5000D739150A95BDEF6D5ABFE7B81EBF306DD5 +:10BC60003DDED0F78F38EE9888236D677F05E79D1E +:10BC7000EEFEECF568C3DF7EF56EFABE6578EC4E3D +:10BC80007E6F71A3B81F6C8CEBC752781D1272B413 +:10BC90005BD88587F677F6217F07D8BA29D4470B7A +:10BCA000FEF2BD81243F5FACC3F23307F877DB17A8 +:10BCB0003FB4453CDF44CF1744F9FD470B983C6146 +:10BCC000CC3BBCEC158DBF7F59A7FAD1F1117C7F1D +:10BCD000B178BFA7BDCDC2DFAA8CD4CEEFC4521EAF +:10BCE0003B4A7A97CDB9B5C0C07115FA1D9DB923ED +:10BCF000F038D231772CB1E13AF40FD2C07FAF2DBA +:10BD00009ADC89F21AC900F597060E1BDB759ABFFB +:10BD1000F858721FD56FE5F5D97B82E7A6F8FBE0EE +:10BD200018C317C733D97B03DF73FC1BB7E814AF05 +:10BD30000B8D1D4DAC257FC46ECFE1865B787B6596 +:10BD40008CD183ED6376FBF10CBE9F15E5EDD5310B +:10BD5000BE3FEE69DF44F7EAB1F1E9DE29AF78FED4 +:10BD600084E07FBCFB5F336BA35379196966FFAE38 +:10BD70002FB29EED756FFF0E60BFF80E49D3663F80 +:10BD800072B2E05E06FB77430363CEFDF94C0D5FB4 +:10BD900097FF1DF5CCB2CAF7B3FD3B5950D3F30062 +:10BDA000800000001F8B080000000000000BC57D14 +:10BDB0000B7854D5B5F03E67CEBC3293E4E43D79C0 +:10BDC0004D4E2040944007081810DB495444458DDF +:10BDD00068DBE0B53A04E419202296A0D89C9004D0 +:10BDE000F20206EB2F111126281A2BE86041B15AF6 +:10BDF000EF80B9147B6D9B5A2FA2A28DA05114B86D +:10BE00002915C9DF5FAFFF5A6B9F43E64C2609EA4D +:10BE1000EDBDF93ED8D967BFD77BAFBDF60E6B102D +:10BE200059C8C6E8E79B61F09F1A63CC5725B2500A +:10BE30007E58BE32C3989F3BCC58FFF64B8D79D7C6 +:10BE400078633E798AA1FDF91B18EB744246F2D85B +:10BE500018A4D2D1DB6CA56318AB4D5E4EF9DEBBE6 +:10BE6000F4726F0CE6F3E418912533B6AD400C3450 +:10BE7000E532F644D5F2C3C320BF3659A43ED7BA43 +:10BE800066C6FBA0DE37F8F3A3FE69433563212BBA +:10BE900063DBABFD946EAB6EA5B43E79F0767BB5FB +:10BEA00076CF57DB58681463C16A99F2CF56BB2826 +:10BEB000BFAB5AA1F457D5F9F4BDBDDA43F927ABAE +:10BEC0008B287DA2DA4BDFDBAAA7537E6B7529E5B1 +:10BED000B7549751BEB5DA47E9C3D50B28F5575784 +:10BEE00052BAA1BA8AEAB554AB94365537D0F7C0E6 +:10BEF000B860596941FF79D6CA00871428BFDA9320 +:10BF0000510AEB79FC6A56168C5A4FA07A1B6500D1 +:10BF1000DA44C6DCCCCF1C85F07B2B633B15C6EC2A +:10BF20009D7ED50970BD74177CC37CC8AF3A209F35 +:10BF3000FF04CF6FD2C6A962CCCBB05D150BEC0469 +:10BF40007CD8143F9B0DE379B35576732C63376926 +:10BF5000E3E07784AF9AAB32C4EF098BB7544EC19C +:10BF60007EF8F8313E9F00CB63692B588D05D28453 +:10BF70008A2E668771E21F0A796D900E6BE864BEA7 +:10BF800002C4AF586282799CF38B011374AD4C6587 +:10BF9000A208E337BB383D44AED3DDBB8D852640D8 +:10BFA000BDE42E3B8EBBAE6A663C8B020F3D1DDDB1 +:10BFB0002EF6D127FCBB2410C60FF06F9D7FF0F644 +:10BFC0006965C6F609DE88F605D01EE0102806FC75 +:10BFD00045A1B7F82263FB584F447BD7E0E3C7F491 +:10BFE000DEC8424903D3F3294B790DC25DCF8FECF4 +:10BFF000FD21D57FD729131E12AF5FED4238C3CF85 +:10C00000550867298B059A04CC7AD902C89BE1B7F9 +:10C010002699E76D90374990F7403D55F1B2B198B8 +:10C020007ABC2C0E532FE50F997D1BE589982FE5DF +:10C03000DF651FD141E012E82203E58DD2E0CD8219 +:10C04000FC8FE1F7298CDD2C8F9EAE42FEBCD927F8 +:10C050005641FFCDD9626007E075A57B7C0CAEFB35 +:10C06000F196C1F9B416F974545FDEE4F43201FAC2 +:10C07000C9AC90C79BD8C0ED1EAA10A707A2F4BBFD +:10C080005BA3DFFA8A99F2085C7507CA30C6AC4E2A +:10C090001695DE60BDBB71BDE664BECE945B4B29D8 +:10C0A000CDDB35D9560AFC703E7670FC3546CCDFC8 +:10C0B0000E4306A3E1519B57DE1B2F91BC3C3F86EC +:10C0C000D3D540FD366BF2AB3720B24EC4AF544AE5 +:10C0D000F235E5561FCB83F5AC4B17034E58CFBA5C +:10C0E000AF6F69C8057E5237892407F4F9478E6B14 +:10C0F0002AE8124C50BEEEC042A6C0F8665729533B +:10C100000B30AFCBEB20C3FE1DCE90175390980C95 +:10C11000D7EFA8F2A998B7B854E2E775E917EADBB8 +:10C12000102ECD7E91E4FBDA2C31C0044A9913E63F +:10C13000736E35A37C4EFA838C24FD57309F49D013 +:10C140000FFE6E42783355C475E4325A471E3BCC1D +:10C150004CD0CE3686799AA04A7C1E3B80EDD6A57F +:10C160007F79C08AEBBB97794628D8D847F2080870 +:10C1700094A11C595B2953FDCCD6B1C417FABA7FE0 +:10C1800062F17D1ACE3716179767EBBE364595AF2D +:10C190008735F9183300FEE21378F97973F05A9471 +:10C1A0009FCD90DF11859EEC5ABD47E5997FCA5718 +:10C1B000FAF8532F7FD7A910DFEAF9CC5E0BCD3BFD +:10C1C000EFD69FC5E3BA06A287B51A9DF9E3B9FC7D +:10C1D000CD9B7A8517E17E0EE68AFC1E597F51BC05 +:10C1E00042F3D0F392D328A72E7E7E12C9E3BC532C +:10C1F000AB383F640F4EB7FA3CCF671BED04316F8D +:10C20000818A7C5DAF007E15B417D63091EC02E6D2 +:10C21000615C45B138C83FB15A935FF95DF64B2078 +:10C220006F7BCBC410BFDBAA4A4415E09E932B055D +:10C230004C00F7F82CBF97813DE2286002CE1FF03A +:10C240003D322105E96012C1337B754810A1D31E30 +:10C25000947D29B4EC3AD7243E0EFE077C3F26019C +:10C26000D6E9DD2570F9E0E2F2C10CD3B191FCAC66 +:10C27000624118CFF19689BE033F841E807C8C2CCE +:10C280007A509EB678D6A4221F3A1218E9B505D77F +:10C29000EE20B905F2D6B30556B4F46477EA32C895 +:10C2A000E7B9F87A74F8C414580CFA61C871A4801C +:10C2B00017FB7508CCE3F70CA247BE6DBFB600B301 +:10C2C0007FA77E4191A4129F683FEDAA80E3E0BA68 +:10C2D000A15F2B7B99C639A78DC34C6F1C467E8905 +:10C2E000F981C44C51F865C0714CB70FAA37AA8EBA +:10C2F0002DFC5347183DDF95109BDC3D1A7EB98C11 +:10C300005DF60D2A0E13103CCE03EC4E13AD9FAD1F +:10C31000413CE7C8DCEE509CEAF00D50FEF86A0B99 +:10C32000C90FBDDFF3D50BFED401486C29E072BF05 +:10C33000E6436B09F6533F4E0C58A15D47CAB48CD7 +:10C340002EF8FEC4A62F73717EBA7D5AEB31F245EA +:10C35000CE6A4E977ABE55E38B5A79707DB241EF23 +:10C36000AF65F07A0F6BF59E75786B918E81D20573 +:10C37000E4CFA2E3D36FC3F96E7FC0C64C51E4C2D1 +:10C38000B30E5F73C2C4FEF30C6F8FF43648FB5FCD +:10C390000ED67ED2BBD3DF6583B77F342165E0F64E +:10C3A000856F4EDF32C4FC1F8F3EBEBA1DDBE5B881 +:10C3B0002C0CF15B93BE96F0DBFC80C563057EEF31 +:10C3C0001833CD8578AB4BE0788BD2EFB383CD0BB0 +:10C3D000E05236C4BA5E18AABD30F8BA5E1D02AE8D +:10C3E000478780CBA1C1DA035C5B8798FF1FA3CF8F +:10C3F0005FCDC179E7645948CFD464035C518E2383 +:10C400005C597F7E88D2EF3B43C065287AFDF07B84 +:10C41000D2EBC9C1C6BF087AFDDBF7A4D7FF3B103A +:10C42000BDE2BCBF07BD4A89DF8F5E9D8983C375AE +:10C43000287A4D1EACFD45D06BD660F3BF087ACD8F +:10C440008B36BE9539BC2ADA45055C9F2F281649E4 +:10C45000BF9BF3B91E761C7BCA8BEBAA037D955458 +:10C46000847AFBF8C34B0BFBF474A41E8AEC2F52A6 +:10C470008F2EFDDB93A4479D9ADED7E7635722FBFF +:10C48000F99741EDBB6F3B6E8C8B85EC63FBDAA7B4 +:10C49000FBFEBBC733EAF9180F1F9FC1F85716A15F +:10C4A0007EDDE541BA8C2FFABEE30E5E3FADECFBBC +:10C4B000D9050B12C12E70F4D9059955BFDEFE5176 +:10C4C000525F3F999297C9403712BB8AEC3756C1E9 +:10C4D0003C3BB1B86ACFF68F26F4D903007F01FD4B +:10C4E00023FA38A68AE0F68FC2E6D53B9769FBB4FB +:10C4F0004ADA17E5C95362908ED7B50C6E2FBFA1EB +:10C50000E9F1DF6B7EAAC39A9FEA10FAA920ED40F9 +:10C510003F15A407D14F05E521F45341FE55CD4FFA +:10C52000F58AE6A7FA8DE6A77A58F393F9D14F4634 +:10C53000FEA880E68F6AD7FC51414A1BAAF753BA7E +:10C54000B63A44F5DADB5E188EF0E85B07B7DBF34A +:10C5500064DDBFC7D7C158298B86AF1B3C26C3FEFD +:10C56000E2FA7C87016FD72A4986FC35AE4C43FD41 +:10C57000ABE5E186F22B6DA30DE5C56C8221FFA32F +:10C58000DE2986FA57F49418F2977F7A9DA1FEE48B +:10C59000AE9986FC65476F33D49FD8596E289F703B +:10C5A0007891A17C5C68B921FF83FDF719EA8F09B6 +:10C5B000AE31948F6E6F3294A7953D18E167DA62C1 +:10C5C000A81F5FB423C28FF42B43B923FF7943FE26 +:10C5D00026D0F728FFECCA6F0CEDACAE8386FCBF0B +:10C5E000C531DAFFD89D41AF378A3DF9553CDFAF01 +:10C5F00082DD5E4CF632C8B1A671D8BAD28FFBF19B +:10C600004CF81DED63C0AEC08643EA31CA1D5385A8 +:10C61000C538FE10FC8C1E00ACEF861FE4C7AFF4DB +:10C62000FD6CBB5DFD218E9FC7E5B02AABE47F8822 +:10C630006CAFFB8BF2DA67C563799D5C2247930789 +:10C64000272CBE93E1FA2172FF9BE78D655E1CAF3C +:10C6500042F797717967E25558E6B16B0E0BE8FF28 +:10C660002A7B3501D7A3FB79D6697C5AAFF991AD06 +:10C67000EC72F2639CD3E43F334DF50C269F22E12C +:10C68000F56DE5999814B9CF9911FA18C7AF9002D2 +:10C69000D1F4A49EEA722CEFAD3B07C58F0E5F1D4F +:10C6A0008F2639E845BD6A532A59B9B33F9C4C5986 +:10C6B000400F71FFFC75E72619E5F839F64AB177A6 +:10C6C000D845ACB7EC0E5A878ECFC87AFA7EAB0548 +:10C6D000F14AF291CBDF5A0DBF6291770DC2370E4E +:10C6E000F6D1B8FF133D21D6F51DFCC08EFC4443A6 +:10C6F0005E726618EA9B3D952C88FE5B1887113D9B +:10C70000FA18FA73F11FFA4B4C3287F3C07C773971 +:10C71000F909CE45D82103F11F0EF1CDF0A1F9F5AD +:10C72000BBF277C7DC54EAFFBE78A6F95F549EAA35 +:10C73000EC4DA49FF2228D8098F2D3F760DE0B0FB0 +:10C740009B49CEFCE8ABED871E03BE341559E526A8 +:10C75000F20CF90FFD16CAE77A6DA5985F786C8C1C +:10C76000C50DE5473280085C585E1A8772E03413C5 +:10C77000A7A3DFEE347B336E42989CBB27C942F2FD +:10C780008535988F77D9707895CEB1EEF2F3BCBE2F +:10C79000AEF9ADC6FC3C3633558271E63D646601A8 +:10C7A00000D642261DEFD2E10074302789FBDFE777 +:10C7B000B3CAB5328C5B6FE6E7364B5E1C63413C17 +:10C7C0002C9C20E79AC6F5CDE3FE2491EA7F06F47F +:10C7D000A658FBBE2F72062C28974FEC9DF093CBEA +:10C7E00019F613589B81FECE04B04394FEF09DD3FE +:10C7F000609CE750EB889C37BA41069B87D42E7823 +:10C80000A3F9D51B9304031E6B6DBFD8DE05F3F4AB +:10C81000D64ACCFE43C84BFC5C493D161BD889F276 +:10C82000BBA4F2A92E8083BAC62AD742BAD9F18B0B +:10C83000E7B07E15200CFDB9CF2729348FF376772A +:10C8400000CF1940DF5C3633F6FBF7FBE23FA9DF90 +:10C8500057B0DF94FEFD2EB17559D09FB84CAA9CFD +:10C860002E88E857E4F5AC669F3713FD89FBC78532 +:10C87000321543BD868BAC7758187651F5A68B835D +:10C88000F47746936FBFDBF5B805E5D6E95F7D78B1 +:10C8900023EE8716BF6C6236A87766572C0B91BDC6 +:10C8A00017B0A0DDBA68AFC91BA07C68D22DB1E17A +:10C8B0007C5D4BFD2F7E2E96F6538B9EB706664011 +:10C8C000FB452F9C18CB401E9C59D3732813E1F7CE +:10C8D0002B81EC67A6768DBD05BE2F92D89DD1CE5B +:10C8E0003DFF9AC4ED8E532F39CA90DE84F603774C +:10C8F00050BFC19F9AAD617AEC489299F009F5C892 +:10C90000DFAD3E2D0446087C7E378F099F5F0DAF5B +:10C91000F734F7E72EDA6F0ED8717EED6D161FD45F +:10C920005BD6FE37A2EF2B9FDB1D877058B6DF6802 +:10C93000AF2E7EEEEBB55300CF8B4DAC6706E9F121 +:10C94000AF287FCE6BEB31911CF2C60920B79692CF +:10C95000C8827ABFFE64DA7B50FE99CBC4EC200A11 +:10C960003EEBFCD8F232E67DCE4AF4682FDB6FE472 +:10C97000C365ED272C382F59643D59C0E83FFC2290 +:10C980008C2F59FFFAB00FB6A09C5D166CFC9B096A +:10C99000E86DD9DED3EF22DD2D8BE0E7CFF097F401 +:10C9A000FEFAD29A1CA92FDF9884FE72D60E9B9FA6 +:10C9B000C903EB4B9DBF17EF3EB74D85F14F3DFFD0 +:10C9C000F93615505EF15F7FDF763FEE8F5EB5CBB7 +:10C9D000289796FDEA3FE25818FC872573F970E620 +:10C9E000E9A79EDC027038F38E95A076E6B79FB873 +:10C9F0001580FB993DFF3715CF9D56FCF6EA34A410 +:10CA0000B315FBAE4C1B6C5F84741BB086E33740E0 +:10CA1000F855F6C33869907D454B23F0726ACF799B +:10CA20000B9E0B7D29B01E94BF4B835F5BD03E3BBA +:10CA3000E4653D08A7D7F69E38741FE44F039EAC0B +:10CA400051F004EBCF1449AF843251BF2CDD7BCBC6 +:10CA50004D5714626AF6288827D643F2BE1F7EDF40 +:10CA600002FC16F6E137B2FC1CFBCA82F05FB60B83 +:10CA7000F03916F10AF81CDB1F9FA7F197C9FDF1E9 +:10CA8000599C6CB4FBCEB18AED5BB0706F12E17F44 +:10CA9000207C2ED9F7E341ED2C5D3E0C05E7050225 +:10CAA0009F576CB2F7E664E4DBE71DAA8BE33930ED +:10CAB00003CACEEC3EE76640279F9A7BEE4038F4EF +:10CAC000FCD62AEF80EF8B7EFB36F1DD997D7FB6B9 +:10CAD00020FEE1274E98047976E1E74D06F9A5DCC2 +:10CAE00006674B58CFB4770B31653DAA87F047F9FD +:10CAF00043C087848FC0CDD31594BF81145AF7D219 +:10CB000000E78FA58103B70A63FBC3BD3959D4F58C +:10CB1000D605BC0A4588CF0FA721FD0D844F7DFDAA +:10CB200032AEFF32287FC2C8BF91F59702BFE2FE46 +:10CB3000A81F7E0307FE88E99936AB24802D740672 +:10CB4000ED04677FBCF7C19FEBE76F6B1FD747F022 +:10CB5000BBDE5E87D350FC3ED4FABE2DFCEE4956B8 +:10CB60000C74A4C3F1D457D1F5411BCA8F8908C7EF +:10CB7000CAE919C3FBEB33132B553385BEF9AE0D50 +:10CB80009A48CE9F6A07BB5CE82F2F96E2396E94D5 +:10CB9000719ED3E4D4D2FD07C6A25C3B75F0258D0F +:10CBA0002E39DD2FDDF5A145D5F443205C3E0F7015 +:10CBB0002EFC9236EF65AF44EF6FD9AEBF45EDEF77 +:10CBC00033C9FB539CFF679D66A642179F054D51D5 +:10CBD000E3191E4FE6FAEFC2BA63271D8DC77D41E8 +:10CBE0005C8C82EBAE5DE37D1BCF45D537CD74FE0B +:10CBF000CF24CFA75628AF8D8D51D08F571B378F9D +:10CC000029617ABC2E024E92AB94CEEFA4E4D242BC +:10CC1000BEA70B18CE7FCD4010E1F306BD9B857AF1 +:10CC2000E983719F98719D7F8DB023FF2AB1B5690B +:10CC3000D0DF5F55C153A344DB1F18FBF7AD36317E +:10CC400025ACFFA5D69E0F703EEC5FED0CED32D308 +:10CC5000AB7601E5C9B26D66DA7F2D836D15C2ED45 +:10CC600093C7EC0115F29B7F5D7D07EAA5FFDC66AB +:10CC700065781EF1DABE95DDAB502E3D2A30F4A367 +:10CC8000FFE74BD55FA25E5EB8155607F264BEA300 +:10CC9000E7496C3FFFB94C560BED3F178293703359 +:10CCA000DB9D129A84FB90EEDDE91E95FA797129DD +:10CCB000F67BE63907F57BE65FDFA671CEFC6B2CD1 +:10CCC000E9357DFE606F2BE17A1CEC6DE5021F906B +:10CCD000BD1D96877116639ED717BED1641ECABF4D +:10CCE000C59802DD2FDE1FEF45FF4A583DEA6799E0 +:10CCF000B5E7E71EDA7FAB1922ED9D4219C88F8B8D +:10CD0000DB8DE37FA3C9BB65969E79BCBE3F83F3F1 +:10CD10006D27B573A668F4AA9547B6D7EBC7A40CE0 +:10CD20008BE887B75F6A6595D1F8204DEB7771FB8B +:10CD3000D7A38CFD71BAED3F0EFF7EAFC0E340D8A4 +:10CD40001E3BC5A35558422313816F5FB0B005C881 +:10CD5000BF1571A1910930DECB9ADCAC88813C7C97 +:10CD6000CFD0E681F531CF6C5D6710AF4B5EB4D3A9 +:10CD700079CA9217DEFE12F1790A610C183B95D23E +:10CD8000F9E5FD4007A71E333115ECB525D690FB1C +:10CD900051D4537BAC6C07F2F7ABAF93DE3AFDBCDA +:10CDA000551CEC9C7A4910A8C1D67F1D6A09CBAFEF +:10CDB00074621C8E576CC37DC36153A006C6AE92CD +:10CDC000BC6B9EC3F51D36D33EE3EC5C968FFBCA6D +:10CDD000B32CC3A312FE95B725285FF97BB3102DA2 +:10CDE0003EC9DC0B427D02F041EFF54C8154EA1D57 +:10CDF0004EE94A4BE52894BB26191657407E02B2ED +:10CE0000DBCDC91E361FD29589CC87F063CEEB2EC1 +:10CE1000F0D79F00A5CB1F51D2B0DD8F52CC34EF9D +:10CE200045A9DEEB53483F3A65B22F343A55F7F146 +:10CE3000799E17623C35189FD37BDF9D08DFE51F85 +:10CE40000A4A783C43643C6895A4BCAD14D27A4944 +:10CE50001EE5C9310CE17A563B773F3B57894F08B5 +:10CE600093CBCDD532C98FC66A17A5EBAAF39942E9 +:10CE7000FE350FE54DDAFAAD052AC507214FE38FE0 +:10CE8000D559EA453B0FE784714126A78FE8C8EAE8 +:10CE9000AA24DF94CDC9681F6B72AA6C3EA46627D2 +:10CEA000878FC9594AF0B16879A97506C113DAD3D9 +:10CEB000F7AB537D77233C6C59971AE4922579BCE4 +:10CEC00021DF0F5E3AFE77FF4FC18D119C1AAB6DCB +:10CED00094AEAB2E2278D5577B29FFBF00B7D694EE +:10CEE0008908B7294CB185C3ADC4901F106E8F005F +:10CEF000DF2487F30DC011F986C5787646597F6423 +:10CF00008AF11028A81FAC6EA554FF9E3880DE3E23 +:10CF10009F2268F1B0BE1A338E23737F0B4B565994 +:10CF2000D6A43EFF2673A94CC13CF22AE2E5680C68 +:10CF3000C16EF9FB76F21B9B64A93B5CAE2DBF4131 +:10CF40004943F965AA7A9C9D088B4733CD28B52BB8 +:10CF500004570F9D53D66A7AB3FE02FE8C7CD05CD8 +:10CF6000AD50BA5EE3878D1A3F6C423C631C8987E3 +:10CF70009F6BB64C67A417FF0FE4F93E3EC4C2E3B3 +:10CF800046123CC19019F04D3252A13444F1BF47D2 +:10CF9000AD8111B9143FE545FA4838BA8AFCC78C0F +:10CFA000055DE84F4BD0E0C65E1996302B9696672C +:10CFB000E67A879978EA37A33D1E09D75ACF411BF5 +:10CFC000EEAF079A4FF1070B051CEFFC2C42134BF9 +:10CFD000BE3D78B41CCF4F5B1CA457533D9539E838 +:10CFE000DF63C7AC449F4E8F4F981F86BFD401ECC0 +:10CFF000BA55A9D77E8C7CDB8DB20CE8F0C1D6E1A6 +:10D00000768473B339E84279D79CC0F587520650CD +:10D01000B8ACAFDD9F3439185768E4775DBECA53AA +:10D02000C71BE85797AB895719E95C97AB2FA570D9 +:10D030007B6D516AE9799C4F52EF56E2C348BACFF3 +:10D0400093A794F992510F304F13DA6B6833A21DF6 +:10D05000F7A110E0F4CEFD5367BB7277A09D03BB30 +:10D0600002922B2AF203E1A9E7B56F9231DE95CB4C +:10D070008735B699365C6F03D0111B85FE6C850031 +:10D08000BC01E887D179A047E38F224A75FA74A7DB +:10D09000E61AE2044D798744C4573DD811144F0C69 +:10D0A000FB3B278C271D986C437B4F327B0EA39C48 +:10D0B000EA891583A837EB9D336D5EF4DF241412E3 +:10D0C000DEBF8C2DCF192C6E09EC16F2DBCA4E0F89 +:10D0D0003B8EE330467E5B933C9EE13E71B7B333BB +:10D0E00006F72DB1A9A2615E8B527DC353C3F263D3 +:10D0F00070740D5FD8ED6EAD9FC8F17E90AAF92DCA +:10D10000B354E60D3BB7A8D2E95B51D95561FCBDDC +:10D1100066C434867117917C3DA0DCDAF9FDE456D3 +:10D120006D4E80F0658E9417C920C79D94AAA28C7D +:10D13000F3569AFF2581E8EA4A840373EEB86087C4 +:10D14000FC685814FA3A7A691AC56B5ED033B06B32 +:10D150002E203DB3B988DB239A9EE1FAE96C8B83DC +:10D16000F4D3D9B995144775B6254D41BA3BB0E112 +:10D17000F2B1088F79BD8D4C81F9CDEF9D4CE982DC +:10D18000D65F525ADEDA0644CE58CDFAF91B664114 +:10D19000BB138F98282EA83B30E14C15E4BB5BAC49 +:10D1A0000CE38EBBB7DE93837EF16E1807EDABEE1A +:10D1B000AD2388BEBA016E946F30D6C7786113E094 +:10D1C000A59C313D68D38BF5E7BD6E6A8B662795CC +:10D1D0006FB47AA39DEF5C286F8D6EB7D5E2AFE98F +:10D1E000F85FE5288457F107AB7270BD3AFFAF4C8A +:10D1F000047984F0FAC0CAA2F9E3AF4EBDBA227531 +:10D2000022A6DE159832676254FF5A1FFDF3714F54 +:10D210008860DF125E7C71371BFCACDC8F7942B317 +:10D220007F996D80F238ADBD1CBD7C49CBE7871E70 +:10D2300060787FA1B214895EDF4F9B18ECA705DCF4 +:10D24000FFDE4CF1D0FA7CC04E253A66800F942F59 +:10D2500073357F0FC0FD260B7C3FF1BA4940FAE8D9 +:10D26000A3275F1CDA2D42F30D6B7643F9DF0FF332 +:10D27000FDD9C2DE4D24EF84E6319B27C3F77B5EE8 +:10D2800037939CAF69BA7CE3ED80DF2FDE30517EAF +:10D2900041AF9DEA9D7CC0B3F976A8D7F30733D997 +:10D2A000E15F1CBE9AE21E4F9A8D7E82A9699C8F17 +:10D2B0005FD2F8795E6F33D91F7AF9BC863916854B +:10D2C000E874037D9F878736785F8195FD7B711EAB +:10D2D0009EE730BAAFF0D2C3B75EBF86F4DA78B259 +:10D2E000F7E7AFB77AA2C54FBF94AA18E4CFFCAE58 +:10D2F00016EA97815D949CAAF5172647E6F7261152 +:10D300001F30596518673C4F932717E6B7D56C90C7 +:10D310002727EDD1FD20AFA7F27DD4BCDECB89BF9E +:10D32000FAAFEF87F47D9E3E6E17E7C7BEF56C9EA1 +:10D330001C6D3D7DEB984AF54F26441FBF471BBF30 +:10D34000BB7A01F3825C2AB7423D278E7FCFDAA2F7 +:10D35000425C4742A210B6AEF9AD8B99376C5DF3D3 +:10D36000B7CEB69487F5DB8787E5FF5E2CF5E1A1A4 +:10D37000277509E161556AE931E49BF2E62BC62283 +:10D380003DCE6F6D24389F307BDC285F3F69BD2721 +:10D39000CE17759E8AC18F30BF55C30FD8BB85612C +:10D3A000F8D1F112D9BEFBFDF95F3E80F2E7116EB4 +:10D3B000DC0C04AF7E78CB8D0EB7188D3EBB41DF01 +:10D3C000FA086ECA0B4791AED73B3C48D703C36FF0 +:10D3D00034F30D06BF01EC57B0774C69785F017DDF +:10D3E000B4780ED9CAE96028B8F58DABD14171F493 +:10D3F000F514A5E97450C55460D8E396A1E8E07E21 +:10D40000A6DA0659C7053A78D84007459BD7131DB9 +:10D410007C8AF6CAA8FEF83F6E51E3A6E0B94F93A6 +:10D4200089CE958EC7A8A9B7F1FC3894C7C7E3FC8D +:10D4300037E2398D9E5FB87344DCECB0713F690010 +:10D440003844815F51DA00F493A7B28249FF3CFA75 +:10D4500039618E7EBFEFEAD4E2A969A83FFCD1FD15 +:10D46000B57AAACB6B53BCF3C23E13F5E771E7B0B4 +:10D470002F0350DA9CEA9B8E745197F0F33B511EB8 +:10D480001C3F2E90BEAD797FE528D46B917602ECDF +:10D490003F1BF0DC73A529D64F76A854B99DCE4129 +:10D4A0005589ED2CC47D4AE5968F46A0DFB08A529F +:10D4B000A6D9A12B4D977A9AC82F5BF9149E930297 +:10D4C00091C8585F6295746E0A82B014F39B1DFC7C +:10D4D000DCB54AB2C9D6B0B884E51ABFD45797FEB6 +:10D4E000F223F443DB5426A7627B2E3725C6EDAF2B +:10D4F0007FE03CC3F4BDC5EC933DB80F155829F24D +:10D500008559F2D1FD27B32B799C1A8687CA347EC0 +:10D51000DE6EEFE868C885F6F6BBFE20A31EB4C237 +:10D5200038E867B3654967C3FDD5E6E420DD6F627F +:10D530007961DFC1AE721640DEE00780F90E621736 +:10D54000BE2C785C5F223DD67078142188207D67E0 +:10D55000EEF03694CB45529D09E38E66DD3582F2BE +:10D560009BE77C33B22B0A3DCC7A655D27DA33B377 +:10D570005E499F83E707B39C233FC614B60BB618DA +:10D5800068FF9AC0824D905E657B9CE2195FD3FC78 +:10D59000631D980FD38B1D1ABD819D337D0FA4B3DE +:10D5A0006C7EF3DD057DFEB4C871376B7CDF610EE8 +:10D5B000A65C8A7400E3E03A7EF64AE0C7A0FAD996 +:10D5C000EDC1C00D63003F77B01E33C2D1C7643ACE +:10D5D000F7D0FDBAE5CCA3E519ED4FDFAB30EF4056 +:10D5E0003A89ECEFF610EFEF671DD01FA4771CEE21 +:10D5F000F93754CBBEA03CCDC1C2FADBEF39E460B1 +:10D60000FDFB8B84B347B299D430B8028AC470B89A +:10D61000F7836F7CD9756CECC07CD6076F3E8F4862 +:10D620007C7C8145C0A76D69DE5F23BFA969DEBD33 +:10D63000C8BF15B61EB70474732CD9B71FBF2F35DA +:10D64000F97252011EA7B37DA352102E9DD1CF5F58 +:10D6500023F93BAFECF463C83777D4480CF1BC76C0 +:10D66000DF278F215F9E36031FC17EE0B5559FC423 +:10D6700022DD2C01060C97271F548D20FBE9ECDEE0 +:10D680005183DE1FF940F397746A7CA2AFF34E64B6 +:10D690004018EFCEBD0EDACFDC5965BAB0CF427A72 +:10D6A000BFB38AC78730A973ECAD06BBB36EC07E2B +:10D6B000701F11D94F77B56F3BF1BDE49B8476F7AE +:10D6C00089EA05DB51BE44CE73A4CB77228DF4DB0F +:10D6D0006C43BCEDDC9685DBC3F950AF5F3B807CCF +:10D6E000F58CD2CE016D7C3CA6FCA0D83989EE6BBE +:10D6F000D28F3D64FB5008A387A1C6637957792F69 +:10D70000C805DC7FF944E64CEDDF5F643DBD7F5723 +:10D71000D595ECC4045C9FF7FFA5A50C3D7F8B8BD2 +:10D72000CFDFAEB5D3BFDB7D7E8676A1FDAB78B211 +:10D73000133CA3B8FFE11F9A5DC09CB05E6430FF4C +:10D7400066EFFFC67A61608A17B66FB5468D2BCA41 +:10D7500074491C2FC143C5B628F3EBD75F48621745 +:10D7600053CF338AAF1FDD64E4EF1A1943FB9AF2FB +:10D77000AA5ADA673782FC407D10399FE34D8F2A21 +:10D78000A807EC16BF827ED1C691A9B96BA01D482F +:10D7900035F2FBD863FC8A14FE5DF307D9D7F81580 +:10D7A000DCDF368EC8A0EF7A7F8D0297B33A5F3404 +:10D7B000C2BEEF79F28B795C3331AEF4ADC0F45870 +:10D7C00068B7632D0B99DC8C1D74678CC67DAEBF6A +:10D7D000DE42E77B8DF962FA5CC8C765DBC83FD6DD +:10D7E00096109A85F76B554122FDEA4F50AE8D4554 +:10D7F000FFEE9AB44E947F07EFB6D07A9B27F3FBE7 +:10D800006AD6291FF9AFC4FE57300FEAD51DBDBF38 +:10D810006EC57702D4A3B09F45BF21760AF268C7D0 +:10D82000F4B376DCCFB930AE0EF0B1D51CA4796D6F +:10D83000A9B152BF5BDA2C65D1F0F779BA44EB0A93 +:10D84000085D141F9CC4827684EB83D3676ECE83FD +:10D8500076B9794CC6FD7C73C1596DBFE935F1F3DA +:10D8600028DD8FC8ECDA79964D3BA7B285C7173E05 +:10D87000EADF4BFE43C78C204FA78BE47F8E9CC70B +:10D880000A17A77BC7D4CEE9A8271C852213D0BFCF +:10D8900099C7045C973C7D075DD2C8CD6703B43758 +:10D8A000517BD90BED0B797BF409C917D9BEC2C5E1 +:10D8B000E30CD7A31F0ACA03668F702DCC23708395 +:10D8C0002CA84A5FBD7A17D7AFDBA1FF10C9D100E2 +:10D8D000ADCB9D1F0C21BDB92B44C2D3FAA2E3747A +:10D8E0002EF060A1EE47F5D03CB6D61C3980F6D7B5 +:10D8F000D67B19D9495B518642BBAD37B0003F4F4B +:10D90000621928DFB62CB45C4FE7F905007F81D29D +:10D91000A8F39E9D6E237CBB573F18C2FBFB311EB4 +:10D9200020D45C4AA3D66F4CE770DA620EA4A37FC2 +:10D930006420BA287371BFAABB4AB3AB98DF85785D +:10D94000DDA0C187DD3A9EFB1724AF121EC7D5A705 +:10D950004FB81F03D64771AD497516D247E28CD038 +:10D960002C5C5762BE855D938BFCC5E1A68E117958 +:10D97000DC190BB4227FB65D924AF1A4EBC4800B94 +:10D98000FDCD6A8985CE930F1689B3F05D848D75C0 +:10D9900016F243409EF8C5EF1DD686FCE6985A5213 +:10D9A000B6A010DFB9B0C808DFDA02D98E745CEB1C +:10D9B000156501F21B4AF5FB118CDE37186732D969 +:10D9C000F3A17C7BBA883E5AB65D1088DFEBBD259B +:10D9D000FEE1F0BD5E4E16C2FD002FBBB8DD7B77C9 +:10D9E0004EE9CB2E4803DE07FDC3158E4B6912E3CB +:10D9F000572CE02796851660CC4D5BFD934771BD93 +:10DA0000EBC7D9E8FE6CF60A7F19CE37F6128B8287 +:10DA100078DDD19B349AD6576751909F3709816B37 +:10DA200091EFB7DE7D4845BFBAFD6327C60E336769 +:10DA3000D7DFAA317ECC59688938C76222CA717D86 +:10DA40005CE75B21A2A72EC1F79758F2FF1434E5DB +:10DA500027533CF32484E78629EFE6CF8B4217D087 +:10DA6000DE993A1EED653134692CCA29AEC7982477 +:10DA7000A787E3775376C63BE867DA560CF3C7F11E +:10DA8000AABA6FA779798FDC8F7695F3D8C9AFA33F +:10DA9000CFF34DD223B1C71C21712CA64B66907DCC +:10DAA000165E0FE4FEC61CEFC72EA09BDD355CEEB4 +:10DAB000B7DCC5E83D0AFCC90F836F4B014869FE1E +:10DAC000048D42F50A64F2A3AF13956008E139D6DC +:10DAD00046F494C67C24D722D7EB38D67837C61DB7 +:10DAE000393CC679F66AFC8D3F522A9D57A025CA5B +:10DAF0002CE973ED28FFF68C57D271BFFD6042749C +:10DB00003DFF5E3A6FBF5B886E9F9F4BB7737D0989 +:10DB1000B232348950C528AE0FF2622A9DDB909351 +:10DB2000DB2A72B9C0AE63A4F7E2C675D93D61E3E2 +:10DB3000ED49EF9B27C61FC46BED98DC13AA81F556 +:10DB4000B701D5E27DEEB86C0E47A7DA0747AC2FD8 +:10DB50006BEB023EA81955884094A93E2BB5D0B96D +:10DB6000084843F51BB10F0EB15AFD2D459280EFC9 +:10DB7000900C036008503F61BAC5708E22D71D51CA +:10DB8000B1FC7E1353128BFAC67F6C1C0BAC81F177 +:10DB9000E3BD4678C7AE786125DAE591748033B885 +:10DBA000D02F868ACF35B64BBDBD1F1F103C699E56 +:10DBB000009A96B7D80E0B00A5A55DD2E36349FE87 +:10DBC0004E3475AAE80FC580A47D30FF4B9F7ECBF5 +:10DBD000BB0BF22D3ECE67B1F92FAC44BA4CC8E076 +:10DBE000787A077DCB00E74799FC778CDB51AB4413 +:10DBF00005F1B12D348CF47823934A114F8D95475C +:10DC00004494EBCD7B99471090FEFFCB1A3EBFDBCF +:10DC1000D2F9390D9314927F929BDF1B6D2E101D4C +:10DC2000285F0FDEFD02E9BDC70E880CF9BFE4775F +:10DC3000C71EC1F7815ADEB152BEE5F54A921B3FBD +:10DC400087766A14FFF9507A39B27EDE921D029E01 +:10DC50004FE42C08BE3E12E5B35FF25C83F858D067 +:10DC600049EF872885FC9CCD392344EF8728A8D528 +:10DC7000C02655FC5ADAC2CBD9AD89B48F1A63EDF0 +:10DC80006AB80EE6F7E8D312437D69B206D3E743DC +:10DC9000BFA6179DA809FAED8F1E9D114A47391E90 +:10DCA000534961D0FDE677229DCB59F70CE5F72368 +:10DCB000A1DF84A91C96767FDA0194976833E3BDCF +:10DCC0000A87CAF5DC0629E0C538EF0D2B7C161C47 +:10DCD0009F69FB97C625E54F229C4F6A7A8F552E88 +:10DCE000A0774CDC1ABF38AA5871B47D56AB2B868E +:10DCF000C7B73C201E40FE707B19E90FB92A181ADD +:10DD0000A5E9659CB8BCFAF946D42FCE0A91D6B1E4 +:10DD100041EAACC1772536AC60728DD2BFBFEFDA75 +:10DD2000BE2ADD4AF36F451CA7F4AD835C7220DF89 +:10DD3000DC0BA2AFE3611C7762DF3A62F475E47733 +:10DD4000515E9FC7766FF0A2E6B1595BC7A6749982 +:10DD5000524701681A677F79BFC6F101BD2B1300D6 +:10DD60005BDD44F7D182D7615E794E64FCBE96914B +:10DD7000BFFBE535BA8AFCAEB0B0717291EE389E49 +:10DD800081EE34FB09F8CE86224054BE213F869FA7 +:10DD9000D61F498FFF74B9183E6FE83FB68109144A +:10DDA0001757C19492F4FE72916972D1C6D410CA09 +:10DDB000BFFF69B9087290E4620BAC3409762AB1EE +:10DDC0001D4D77A31ED7E5E144C4C914645FDB0D84 +:10DDD000254EDA1751FEB247FED082F191EB44EDA9 +:10DDE000BC4B830BBAA1102E5FBB14833E7D187F02 +:10DDF0008175ECE948BCBE00C6DB5C366C1CEE2FBE +:10DE0000ECFE17C93E7017F0F81577153F3F77E421 +:10DE1000CD7B32FC5E5C653AB7D32B75FAABF2BBB7 +:10DE2000709C0DD82FCAE73C0BE9CB475990EB43C8 +:10DE3000CD3EDDE6D2FC241A5D45F249A47C9AF081 +:10DE400087E41294EFE98255C6FD1CEAE783A946F0 +:10DE50007D8DF4A2EBEBD6CE3509E80FCBD5FCFDDA +:10DE6000B936639CC365195C9E99D3F93CD68995F4 +:10DE7000B4DF544B44DAC7E9F477418F47C031121D +:10DE80007E48A86B27517C0CE5E38A7B18F2EF36BD +:10DE900020597CE32D2E5DD1E2A6658273DBCFC4D1 +:10DEA000F1282FF77494DBD1BF2EB86DD7E2FE7046 +:10DEB000A3C04228373716BF4971254D55D0332CA2 +:10DEC000CA992FCEB68CED8F67E063DAAF3A546B08 +:10DED00027FAB582A11D14B7D01438348B713B9644 +:10DEE000615C4A53FE9A8C4528DFF34B0B11BF6DE2 +:10DEF000F5168A9B91F359543FC2E7B88F213AF93E +:10DF0000767ACCA1EF2F2BA2EF2B4B33F8FE3628DD +:10DF100081A882F964E58B1EE4FFAC3A4BD4795CAE +:10DF2000A9E1293383DF0F6BAB3F944EEF668995F0 +:10DF3000013618BE60FA6B52C3F03179007CB874B8 +:10DF40007C483A3E1266131F76758A5CDE925EDB71 +:10DF5000C0E4DB503FAA9516B2631BCD7C5FBEA325 +:10DF600040E30BD9D686C4F66DE93A6E8948F7705E +:10DF7000B28B44DA273A2A9EA7B8A64759CFEB2896 +:10DF8000EFD4027E7F3EB2FD1D19DC7F159414C1D3 +:10DF900043FB698E47C02BCD67EB88D4B6703E6DCE +:10DFA000D5ECE8561787E3D6FA87894F2F769EBAC5 +:10DFB000DCAED5ECE8855E9F05D5812A944E4B47B3 +:10DFC000FDF9047F878A999C64977F8A4DC2FCB2D1 +:10DFD000ABB27C951961E743B2B752C47A57E3BB41 +:10DFE00042D0FE9320BF0FFA49F0D7C5F40E978FA9 +:10DFF00011332F649D023139C8D09D907749412A51 +:10E00000772D80B924D0ED48CADB6CA0176142A7F8 +:10E01000ABF9FD8B6E7C5F92DE9FE4EF4B7EAEBD75 +:10E020002739A6755DC9A3389E22F950667C86EF14 +:10E030004BE2FDE7A277292EFA14C8DAA6048C87F2 +:10E04000E1F7B7E5FB982C4EC6FCFA128C7BBEE7D5 +:10E0500055AB764FB2730DDE7B795C8475439B665E +:10E0600009F4FD702C6A102AC3E878F7159D7178C1 +:10E07000CE773A78CBA0FE63BC3F48F3CDE078DAA8 +:10E08000E4584AF7CBE639436E6C7F60CF534F6E4E +:10E0900081F13EDF67A3F74C363B96BAB1FCF347FC +:10E0A000DE76A3BE38BDEF6D4BB4F3C92552701AAE +:10E0B000DE23AB50E3D91A987F7170B685E24F76B4 +:10E0C0001DA0FB694B649F05FBAF68DD43F9AB7690 +:10E0D000FDD98DE5EF67703D713ADDE746BF445EDF +:10E0E000AB352482FED93DCCBF28EA397B86A8CD4A +:10E0F000FB55EA7FB3E3D5438897D38F58C9EF76B2 +:10E10000E091DF51BFA7F6BD48F3FD7CF7DB77A0B8 +:10E110003D5DC19807E5F969BBE6D7B375C685EFE4 +:10E120006F5FD5E0A1E74FC76AFBE0AC21EA69E782 +:10E1300031CC09F0A7FB039D7178BFF073B3CF8298 +:10E14000F0588CF080B418E080727F7150A0792E66 +:10E150006E6DA3FB568BF772FFE0628017C1A5F5C9 +:10E1600000CDFF5806971BA7F6FDC54DEF52ECB545 +:10E17000D2FE595FF762A7CF8DF0D1D70B70E0EBDD +:10E18000DE7D71789AA7E3A9F5CF34AF8ABD7C5EB6 +:10E1900015BBF83CE6ED053C39114FB309FFA7F676 +:10E1A0003105EFC174EF79FB33B4674EEFB32968E3 +:10E1B00057E8F3CA02711B371EF988EB63B6572084 +:10E1C0007DCCA44E3ACF5922CB32BE4F70A13C60D9 +:10E1D000097079DA599209E5CF3C24D2FB964C0EAE +:10E1E0005E8AFED53319FAF946A71BFD62BBAFF074 +:10E1F000137D9E8CD5E02D75BA317E6673A6EF4CEB +:10E2000038BF9FFEF0C54B71DD2B4D95BFCBC6715E +:10E210009EE2F1A1E78755FEF5019AF770C3796395 +:10E22000640A708BC3F3EF7C91F9E85EF2DED7628B +:10E23000C2CFA14D99DCEFB6D9F101DD473C8DEF9E +:10E240003CD27C8214A735D25BEEC673BE93CCE978 +:10E25000C373D9CF9F788DE26DBAD375FF5327D59D +:10E260003BB5F7B5444CCBB5787816B885E418C003 +:10E27000B1C1363E9A7CD4EE1705F8BDB133020821 +:10E280004CD4138FE970AEB4CC349CEB70399AB592 +:10E2900035B783FC2D81E8F7CD22E56FDE4393E9A6 +:10E2A0005CF91C8B7EAECCB438B995A6188ABFD960 +:10E2B000ECF805DDBFAD52AD32DE5F39AEC9C58FBA +:10E2C000B4F716CEC7C4A922D0CD4B99BEE199139D +:10E2D000FBDFC32D6F5EE246F896E3B9076D6A7601 +:10E2E000DC807189140F3A85B46D88E067D6CB5B0A +:10E2F000797902CF4FC9DCB31EDFC344F8723BF516 +:10E30000495E9ECBCB7FA295CFCF281D9F49FA8532 +:10E31000D13B4560912574DBB80A8F068F3EB84823 +:10E32000AC5BB7ABA1F2C24CC6E336324AA7E27A85 +:10E33000A058E07CFFFDFA03BCABB6C4FF867E6C40 +:10E34000FF5DFD04492F893E7CE30ABE79B8FE7B60 +:10E35000BC84C94D09DFBFFFEFDA7EA5C92B9E44FF +:10E360003A8C1789EE75BEEE7E64D438DCFF5B1AFA +:10E37000EE0EA1DAEC8E2DB1A4C3F7730A3F3FB9BC +:10E38000EBA14D86F755F534F21D5BFD1CCF32DC59 +:10E39000783EDB92C9E5514B669FFF0DCFE546E223 +:10E3A0002F0ACFB7A452280CB7D359A588F187F903 +:10E3B0001D367AC7F712068202E63F9A8544D4DFFB +:10E3C000635817E57F802080FC38A698303F81F5A0 +:10E3D000B8A5E178FE1C5A8B76DAB1645F13D2D906 +:10E3E000978F747E2040F9CF337CBFE982EFEB3307 +:10E3F000F93EC8096621D2B38C29D0A1E898E18AF8 +:10E4000026F72FC053964E859FB7DD2C791F223AF1 +:10E41000665972B7A30FCEBA3C58A4BDBBA4B7FFD0 +:10E42000ECE9A786D17B437DEF850F7A1F785ED517 +:10E43000C2879E983048B9266777D7046E0BD7F706 +:10E44000ED1A9C9FC9D4F5805FD70764C7FDEA66C3 +:10E450006E3FEDBEC2BBE67194B7AD26DA4F9F6C3E +:10E46000FD0BBDFB78AE94915D37D0B82723F07ECD +:10E4700072E75319FCBC2360D0EF0B9F7CE9D2F00C +:10E48000784B00B3923C89BFC341783FE451AD263D +:10E49000A4D252F2C75858258F53C1F90EC777B886 +:10E4A00082943A5927A571AC875299C9E49F4E646A +:10E4B0001E4A935929A5A9AC52E0F69D9FD20C168D +:10E4C000A4340BED53F4F7B01E4A15BCF11916BF76 +:10E4D000310C4F4C87E37BBCA5FC7B447C9084785B +:10E4E0009C10459E47C40549ED5524CF312E684404 +:10E4F00072FFF71474F9BD39B3E43D94A72F657A20 +:10E500008F617AF8D9DFF3FB15EB05B2AF4FD8670F +:10E51000581440DD33895E7A07441559E94ED0EF2F +:10E520007375FF3FFEE871C208CC16F3A9F0F81D21 +:10E530006673E6E379F11CADEA1CED1C648EE60718 +:10E54000C1F7CDF83D3D0FDDB79FA39D3FCC89F0CE +:10E55000BF30BFD5E04751F11758C71CBF40E70691 +:10E56000736266BCDAC506A693B0FEE8DE5F798406 +:10E570001F6A487F56447E6E647B9BC06CA9F89DE1 +:10E58000D3D3333F54C8AED3FD5940700AB56BB0F6 +:10E590007E487E21FFD5DE70382565F17DABDD7FBD +:10E5A0004D5CB47797F4742ED867E6C4FEED6147EE +:10E5B00098807CAFCB619DCE7371638B7C946F0927 +:10E5C0000C1697AABF77DDF4809FE1BCEDA155F44E +:10E5D0004EF5BDD92AF96A6D0501BA1F10931F7057 +:10E5E000A951E6D784EF3A037F35C51ACF4D966718 +:10E5F00071FE5F9EC5CFB50F5D925A82E7D9EB14CD +:10E6000091EE0DAF53F8DF2D589735D43BE536C367 +:10E610003DF9B549DBE81D20FB57DB19DA93762974 +:10E62000FABD94DBB4F13769F537276D233F49C351 +:10E63000087EBE1F59FFC08887E9DDC7C65CD8EFDA +:10E6400062FA804AFDD78F78B80CDBDB428D86FBFF +:10E65000BCB3B3F8BEDAB697D3A329CF121886F4A9 +:10E6600020F929BE40AFD738C079D28D595C2E36FB +:10E670009903744FA649B3879667C56D407B675D64 +:10E68000D68EA3C8AFE7F2189D37DA434FD339824D +:10E690002DDFC2EC82F6770230BEA32048F8416736 +:10E6A00053C840B7317DEF6C98FAF75FF78DDF857F +:10E6B000EB6BCCF5D3F843ADF74A8D4E1B35FDDA45 +:10E6C00068379EA35568F0BE5E5B97ED1546F26411 +:10E6D00010B890BD77E3D61137A27FCAB67F48380D +:10E6E0001AEAE7B2B2F868FC1229FF9D0562C43B42 +:10E6F0004A02CDEBDC5E417B6F91BF63D1670704BB +:10E700002DD8EFBF6D2D3F782DCC6791CFE9C5F89F +:10E71000C9A7B6EEA07BFA8B5F34537CC2C8AED9D2 +:10E720005C0EB6F27712F5F78D2E69B51ADE9B5A9C +:10E73000C2C2DE5184F1161F3B798CD13D63E37771 +:10E74000FDDD8066FC10254E2DF2DD8187B222DFD3 +:10E7500023D3DE1D2888EEA7897C7760575024BD1F +:10E76000B11CE358691FB0AD04F73D55C704F21B57 +:10E77000F4E743E5B13C73585EF0103DAAB131DED9 +:10E780009D51F8E9BD6C4E2FBBF1508DECFEEA0DAA +:10E79000A12C4CEB189E37D5AE90643CD7AE0DC47F +:10E7A000D0FD925A590C60DC48766C890DFD8F2C97 +:10E7B0004194F11EDA34D354BAF764B9579A40EF52 +:10E7C000B3EE58D489F7EA6A5D12433ECE4EE0714B +:10E7D000042C5DA4F769EAE43713E6E03ECEC9EF06 +:10E7E000E9E5C82CA00868D779199E2FC366A53221 +:10E7F00004A657B6E00DE17B576CB255DEC9DF9930 +:10E80000B971DC24F203D3CF81B669A1DFE2385EAF +:10E810005B29E2FFAA7B93C91E0CB84C0CE3003FB6 +:10E82000CDE2E78296D892D0FB38BF590EF2ED06C2 +:10E83000543111F1F07ADBDA99D7C0777340A278BE +:10E8400087FCAF6B6FBB06DAF7B459E8BE850E27BD +:10E85000A54E32BCDFE05E6DCC5B22DEAB9058583B +:10E8600039E4DFC179905D55C642E171BCC95E7E75 +:10E87000E82E3B894EBA813FE9FC43CBBF8779A0A4 +:10E88000D776B39FF0DEFEBE40FED5836DF37248AF +:10E890005E3A966EC7BF635275949F630E249F9F26 +:10E8A000CE52F47712ECDA3B1576F47B45D2535D09 +:10E8B00035F3609CA12DD011331AF17BD8ECC1B097 +:10E8C000E67A4D3E4A4E2EC775BA894CEB23E8AF27 +:10E8D000DEECC9F743FDFAAF4DDABEF1F48D485FC7 +:10E8E00092ACD0BEDA9CC53C680E9B933B336498D7 +:10E8F000C7E8172D1EFC7B07D39E2B8847393FFAAC +:10E90000B55924DF104E882FA9CAE2413BD95A9548 +:10E91000EC9126603D27D1E559A785EC21A9CAE1F4 +:10E9200027FBAB6D924B09937B6BAB658F64C6BFC6 +:10E930008F63A374ED00F23E27412C45BFAB45B376 +:10E9400097D3B475A5653B284DCDE6F273BBA4CE35 +:10E95000A4F77B816E30EEE6C06A4EDFCBD36DA4A8 +:10E960003797BF3E3C6D30FFE093D52E4F1E0076AB +:10E97000DBEA72F2DB16AFFAA811E96E79AC4D460C +:10E980003A34C58DDC3C15E9FEF766BAE7591B3B06 +:10E99000499913D69F29AEC885F030896A06D2738B +:10E9A000C163C11BA5C94827EA16BCCF5F98DD7AB1 +:10E9B000A304F2A53D56CDC0F3B2A9D95B793E457B +:10E9C000DD22209F6407783E5BCD10213F23FB09A9 +:10E9D0009E1FA16EC1FCADD9ED3C3F86EBA3DBB31E +:10E9E00077DD88FAA8D6EC2943FFF4B330FF821113 +:10E9F000F87783787A870617BDFC79FC6EC6BF333B +:10EA0000C4D3C8F217B476FB0728FF8D56FECA00A0 +:10EA1000FDBFAAB50B0DD0FEA0D6AE6380F687B4BD +:10EA200076870728FFBD56FEC600FDFF516BD7391C +:10EA300040FB37B5766F0DD0FE88D6EEE800E5EFE7 +:10EA40006AE5C722FAFF40ABDFA57D77C736BC8BEE +:10EA5000F69A1BE415CA93FCD806F2776DAB2A240C +:10EA6000FAAF9DC8F5BF4EEF6EED5EC0916C7E6E45 +:10EA700073249BDB01551A9D17AFCADB3815E9F0EB +:10EA80000FFC9E22E88FA3780F575D25927F6FF9C8 +:10EA9000EBFC5D99E5AB243ADFB8A0F7B4F6FAFCDD +:10EAA00003DA3CEBB4B4329BBF9791ABBA3C33C2B0 +:10EAB000F4A35936E66DC04F18FF5F97CCF54CFEB6 +:10EAC000AA92063C37A9053D83EBAB775A42E8FF93 +:10EAD000AA97252AAF4B2EF1E379BF2A4BA487EAE8 +:10EAE000931343F84E735D5DA1E1BDCF3A59A2F790 +:10EAF00063A484AB6C739C283766C8283FEB989C52 +:10EB0000584CE76AB04F437D525522A3DCC94D48AB +:10EB10004E44B93C3787AFAB23B6DB8EF728A4074A +:10EB2000447A2B60A42C11BFE7D5890105E6D121D9 +:10EB30002F27FFEBCE16ED4C91F1F3445DCEB7FFDE +:10EB4000621AE9B15AD0630AE931163F2EB5EFFED9 +:10EB5000A6746CB405F5969C61626690CBBFCB4EF3 +:10EB6000A471773EC4F5D608D05BF8CEDAF642C67B +:10EB7000DF7973D9C8AF5B2E315752981FF377D91D +:10EB8000DC8E67A6191EDC678FC0F710C3E03BDC84 +:10EB90006FD45BB943E8AD9C2A909761F5AD2ED94F +:10EBA000900F666BEF2A799807ED9B69CF6D257DF5 +:10EBB0007216F50943FDF2C798D1A85F408F5859E6 +:10EBC0007F39A8CB63DD6ED1E574ADA6376A23F437 +:10EBD000C6D072F7EFAF8F22FA140DEFD00C247F5E +:10EBE000AB304E00E8DFEC1348AF30C947F7FB8786 +:10EBF000829BD95C2ACBCEA1E1674EF92201E5B414 +:10EC0000D927793E8A724F6A28F8EAF52CB6CCC724 +:10EC100050AF7D716C653EFABDD69A3B67EF42BA44 +:10EC200015E2E97E87A2F91DB655EF672746603CDD +:10EC3000FC7B5BEB26E0FD71AF4CFE92F41205DB32 +:10EC4000D9619F9E44761CDF6F32D9E75F84F6FC62 +:10EC50008B1605CF050E3FABBDDF90ED2478DEB3FC +:10EC60006705B5330B952E7EDECF08DEEB3212F949 +:10EC7000DF0969B76976E3998DDE3CE857EC1250FD +:10EC8000FFFC474EDB461BEA0F6D3FC058DB4DB81B +:10EC9000FF09062C5A7DBCE8CED81E51D0FDCF5EB0 +:10ECA000C9156E875A6EBA2A0BCF43E5D112F49775 +:10ECB000B1CDBED17C05968B7A7B2F5E1E42F1A52D +:10ECC000E725C0C3331D5AB99AB6F12A98CF1E8BD7 +:10ECD0003E3E18D445389EA8D193BC11FBDF5DA2FF +:10ECE000B7EFD9E89D4AF3B9DE047BB07C77E646FE +:10ECF000677ADF7C87E7E46EAC81B59F56BAE27035 +:10ED00001BB7A4EDA354D4DBEBCAF8FD616400F497 +:10ED10008FE8F7882FE06DEFCD2ABA62FFF3D03F7E +:10ED2000E20AA06899A9EB9003E0B6647FA5CD2C18 +:10ED3000E2FB5DA52ABEDFA5B75BB27736D939CB3A +:10ED40005E194769947687F1FECC776867B35CC437 +:10ED500078A7436F2EDDA5E0BD99CA06A789EA33DF +:10ED6000EEFF8ABE3EBDFDE95D6FFE04C73BA374A6 +:10ED7000A55E07B5D785002E51DAE9F5F5FBD55329 +:10ED80005CDECBDCC07FFF70733E6452A507EB07EF +:10ED90006D7EBAC76637FB4B519F002A0318A7A0A8 +:10EDA000A753DC79FC5DEC88EF91FC15B4B1A41994 +:10EDB000282F574874EE1EB4A98EB1906F817D4AFA +:10EDC0000D4C69CDB823E3315EA0659F93E47AEDE5 +:10EDD0008A0E5701F295C7C2D0EE6DB9A2331DDF7E +:10EDE000BFAFBBD752F604D26F68B9EBAE303B6C05 +:10EDF000780E8FABCF4EF097213FDA811F511F372E +:10EE00009A7D367C37454D1729AEDA0EE56F50797D +:10EE1000B656EE997E0DEDCB4419E7559F37777ABC +:10EE200009EA355722FFFB8423AE2A9B0FE501D95F +:10EE3000222379DD9D53EE43383D23792A91FF9EAD +:10EE4000713A658CC7025949FA401A914CF15956EA +:10EE5000EDBE53F638AEE7F57936B9B9FDD0E4B674 +:10EE6000101E5A623B6F2E867631F789B20AFD3743 +:10EE7000DEFB7029C6273E76EF913F637C6B53AA79 +:10EE800044EF0CECAE0979B15E8FC03A77801DB9C2 +:10EE9000BE6A6627EE47D73345417B7DB730D38FB7 +:10EEA000FAB92745623BA07E4C9E315ED559608CF5 +:10EEB00097CAAA30E637E6F8EEC7754DF8436131D8 +:10EEC0008E9322280A3E1D5CD8C9283E3F352F4F1D +:10EED000C6B8EEB8C28838D8A9C67E12AF32962717 +:10EEE000CF8888DBBAD558EEBADD98CF986BCC7F47 +:10EEF000AED3A38B9F3FE87FE7E1B17B9F64A8A7D8 +:10EF00001BBF8AA778568423DAED3123250F9E8B09 +:10EF1000645B3A67611C1CBB3486ECA583EE18A6C3 +:10EF200040DEBA94913CB526060FE07ED52ACAA5EC +:10EF30002A69A8E081F7A1DC01FB5594BF91F0CBD1 +:10EF4000CEE6FE416725FF7B7141294476847D55DD +:10EF5000BC5CE3C1AD63841FB6222CCFE3BD1F7739 +:10EF6000F3F338BA774F477284575819E26D320B72 +:10EF7000E03B94D9F77EA486601EEB95BC4AB4337F +:10EF8000D6895D348E5AEEF4E1BE3B05E3BC4D18E4 +:10EF9000EFAD521A898FE7DDDC4E52D85C3FE2D1EB +:10EFA000355BA4F891FA43317578F852AFBDD7A01C +:10EFB000C7B1E974F9B29BFBE7F67488A217FDE0CC +:10EFC000B7E7ED407CEBF9565F721BC5F58FABECF4 +:10EFD00042BA6437703B14F400DDCBD6E3C4F4B816 +:10EFE000C2EE1C1EBF763A47BC80BF901E47141667 +:10EFF000074E4777263CBAF0CB78DE933DAE5446B9 +:10F0000039F34BFDFE05E3FDE2F385746E3043F406 +:10F010005EA2F9D3D1AE4BD2C64B4A96BCF4BE3BEE +:10F02000CC4984FA0F315E3F296FEF4ABC77B507B0 +:10F030000907F9E72E0EE748BA4DEFF0978E4178B1 +:10F0400009A00FB3FAD3B1E06EA5F3C0FAFB58A242 +:10F05000755C7FBA9E68E2F64FCF4285E22C87A2AC +:10F06000F393EE04EEC74ED922A37D9B91F7500D8A +:10F07000DD83B98FC9A8EF323A3A6F46BF57243FB4 +:10F08000041C71E3799CDCB7F3C39B4C9C3F589AFA +:10F0900044788B8C2F8D8C271D9E93A0F929400FCF +:10F0A000C4E27D00F94A8C13EC59C5E89D809217A3 +:10F0B0005B6EFB77E8EFCB111619E575CE5BBEA74B +:10F0C0001C30AF2F5FF2E5A09CDE2675D913C2FC81 +:10F0D0009E92C8EF9F45CAEBE139A246AFA0375CCC +:10F0E000DF3DCD46FA06E20AE6A58E968108876FD7 +:10F0F000DFF4275BCAFFA0DDA2DAFCF8F746DD1DCE +:10F100007A3E8BECB09CB778BE685BD6465542B869 +:10F110005590BFE860F63CF21749EF727FD1189323 +:10F12000378079F69E9DE2EEDAF7DDBE00E3D5EAA0 +:10F1300053AF53503F176AFB9FF139425478491639 +:10F14000AF0FF926F27B81065FC64A3F9D0DF81B83 +:10F15000F3B885E2EEF2C5F2865CE4874613E1B3CC +:10F16000DCA42C6D0EDBA735A71697E44CA47D011B +:10F17000F3C18641E915980FDF614A3E5E8CF49A2F +:10F18000036C86F22547E506644E550CF385D1A93C +:10F19000D22B51FDE6546F498E26F7F0DCC7ACB197 +:10F1A000F43389A56C36EA65F8867AD7BC2B869F3E +:10F1B000F7241BEF479A4C3C5EE4266DDD663CD796 +:10F1C000198FEFBD8921EBD8FEF56FD5EA49366777 +:10F1D000C8148F7EB2378ED2BDCB887360DCDF520D +:10F1E0005C4E05233F28C285F2F7C8FCDDEE2A1EDF +:10F1F0000F50BB9A09781650ABDD5351EFE07F8F6B +:10F200009879BD0ABEAF425B4C05FF0B11FFBA6C8B +:10F210002C11EBA7B34E8A63641D4CE1F112C67347 +:10F22000A76D03BC03A5FB01A42A13ED5346BF66DB +:10F23000E77F17AA8AD13BE1F46613EE7F57B380CC +:10F2400024F4F9E18E642BD44E3F8FDDFDF50719D0 +:10F250002897F3C51DBE37C86E889577A07E8C3180 +:10F26000F2A17E7FAD56A3936DD532E15B2F77ABD4 +:10F27000C729DE3E87F5D4E03E2BA72AD180E70BD5 +:10F280007ED9DE4CE69B10DE6F80BFAB9B27D13B67 +:10F290005D4AAF9BCAB7552B43F43F6C80FED389C0 +:10F2A0009E06EE3F8BCAB787BE48B81140B1ADE7A6 +:10F2B000A38452A5CF6E8D84B37BB5517EFF607F52 +:10F2C000643C39878BDDEC4DBE19E0667F40F4B4B9 +:10F2D00031FC7B3CC67AD373CF25F0F372BD7E2818 +:10F2E000F916AC0FFBDE3605FFBE8FB17E69F1C7A4 +:10F2F00009FCDC5DAFCFE7F7A35E63BD48FC44CEFD +:10F3000017E695F2E3B0795D69B31ACACB66F79B4D +:10F3100057CA4FC3E6758DCB58DF57137D5ED7E7CD +:10F320005B079D975EEFA6A28BAB17B98E5BA65BC2 +:10F3300007803BAFFFD3B28BEBF75F160C5EEFCECF +:10F34000AAC871542E272CDE2328E7CA99B216DFEB +:10F350000967CE98A871C1259A1D7316FD14180F60 +:10F3600097E97D1FE55A4F368F4B39FCEC223F9EC3 +:10F37000C32CDF6751F0BC235BF35B83E0598CFC4B +:10F38000BBC72627603CA0CDAD68FBABCE5C8CE74D +:10F39000DBD37EE436927BCC68CFC07EAD18F535EA +:10F3A0008830BA97F126B64B098FA3F092FD572FFC +:10F3B0007AFE42FBAA9FF07D951EBF1F6E67B14982 +:10F3C0007D76961EBFBD491BE7BF7286D17CC0CE3D +:10F3D000A7BF7B9B9A27517CF32F6D9D9BF0FED19D +:10F3E0002F939313703F73589BB76E37EAF71AD277 +:10F3F00066E78D334581D7FF0791B1925A008000AF +:10F40000000000001F8B080000000000000BDD7DE5 +:10F410000B7C54D599F8B973EFBC9299C99D64F2ED +:10F42000E211EEE4C5044298608801AD4C12A0A838 +:10F430002C3BC147412D0E893C227921A8A1B2F570 +:10F44000864484F8206840A0A043148A56ED6011D9 +:10F4500001C11DA2A6764B6DECF661A94B47602950 +:10F4600002C2A8BB487F7F2D7BBEEFDC9B99B99978 +:10F470005150B6DDDF9FFEECCDB9E79ED777BEF7E2 +:10F48000F79D33172FD27F93087928892C0C1413FA +:10F49000FCC7951162CFCFEFE9741232BCD42B8E2A +:10F4A000A3EFDFC9D111329E9087E983D07AB9509A +:10F4B000F06FE3E8DF22212BCBE9F7D030979027DC +:10F4C000C57EBB40EB9F7408A2CC413B09DBED7CC1 +:10F4D0004BA7F3380879EA8EFC1EDE19296FF03944 +:10F4E000B64279B88EF80216E8445C44E8FB9D26E3 +:10F4F000D1DE594A8B42BFB3C64ACB3B7E7F1B67E6 +:10F500002364C40882FDD5B55693635711B2DB104E +:10F510007EF322CC673DE7DF46FB79ADBB74AA40A2 +:10F52000DBCF3B4988997E5AB7ECA6278FA71132CB +:10F53000E1B85809EFEB36DBDD3C7DDFD4DF321577 +:10F54000C6212DC45DE0262493AFE4ADB49FCC4723 +:10F55000DE73B7D329AFEB95F6846839BC9573F7A2 +:10F560004850BFB87431C0C7E2912C74BD7361AA12 +:10F57000F8DE3E550FED6E32B83B683F67F4641617 +:10F58000C0F1A20257F539F70EA982D0F9CF0D2CA0 +:10F590009B8BE38A1464D9B46C12711E26494C6D9E +:10F5A000A3E5CC2462328F23A47C85D8F7008C5F3E +:10F5B0006F157B288C6D1562DF8F605D2D3922EF12 +:10F5C00086C1FD0807B5FF791EAF81D07147EF30C6 +:10F5D000D0CED83E5EA4FF8D09C496C7EE892D9784 +:10F5E0000663CB57BD135B7E5562F09E681ABAE581 +:10F5F000388577EF012381F92E3A9DE4375278EF71 +:10F60000D31302EB975F32223E542FB278003F4E65 +:10F610009F4ADA6AA4E5838793F0FBBB7F6266DFCB +:10F62000EB022F43597E3999C0F78BD202E5A974BA +:10F63000DEAF7FC9DFE92D66CBD243FF2F176DED1B +:10F6400084FAAB02E5227DBF7B1421FD502FF84BDD +:10F65000609DBBFFC663BFE1E78DFE1EDAEFE9BD2B +:10F660003F7E19E075FAF9A1A91C9DF335BA9EAB4E +:10F670003AA1BECD2AF5D0F7134FBF98E78BDA97A2 +:10F68000453B8C31EB5C2C71B8CE56C1B3E259D8F6 +:10F690009F437AC4A725F3FC7541DA7E0997E39668 +:10F6A000A11F03C5D36228BB33ED145F27DA18DE30 +:10F6B0002E31D3729C7D579FB51B78E2BB2A523EF8 +:10F6C000BAFAC7381FD7C9F711AFF7E9655D12C09D +:10F6D0007135E7DE46E7BFCF6C2B2129F0CCF10373 +:10F6E000DEC81225BC745CD78F9A002F7EC5BB7B09 +:10F6F00048E2F15C597FDA3CF9AAAFA8A7E33A4B9C +:10F700000839F751D29D1E3A8F911B62F7BDC81F71 +:10F710005B5EA5C0A79644BD77C27C725766219DEB +:10F72000109C8FEBE407B739E97C8718490BC0457B +:10F730003BEE5A651D2FBC40FB716137FC459EF5C1 +:10F740002765D07D51E8EA758ED111FDB77428A5E3 +:10F75000B7451CE32FEAFB459A79A8FD4F94189F03 +:10F760007218DC6B42B8FF4611F6FFD483D39E3C7F +:10F77000AE1F3C9F130F7A3C93A3DECFDFB0B82FB0 +:10F780009BB66BD8993E8E8F826FC3F36F66DC4E4B +:10F79000DF9FD921B8810536CCDEFEF844F8EE793A +:10F7A0003E00F3857A0F5DEF99C0DB36F86EFE669A +:10F7B000FB385E8AB45FB0618A67B22B02CFCBA5FB +:10F7C000D3D72A189F5B14D0FB4D401781DF4D1D06 +:10F7D0000A78BA817317D071CA051F0F74672DF3A9 +:10F7E000E8E509844CFAE25FFB86D0FAE603E3CB56 +:10F7F0003B697DA7CE7BD33F01DD3DCDBBB7015D2E +:10F80000FFF69E0C5FD4FEBC03FB4BF7A5F3D606B8 +:10F81000EC47A6B85140997AAFABB61ACA138B0918 +:10F8200067A4FCD8769278FC16188FBCAF4B25E401 +:10F83000E4FE874A041DF2A3DB814E4E139B1BE8B6 +:10F840006E9FB5E5DF71BC97F438DEA4600A07FC53 +:10F8500077DF739CBB93003C62E9EFE4C915B64ABD +:10F8600046D7777A510EE88883F6B7F0D931C807C2 +:10F87000D4F7DAFDABF7C7F6A3C58B8F9475016A91 +:10F8800046E397F6BBB4E9B201E8B1A195CA8B286B +:10F89000BA6938DE652096C1E3103280BF04F09764 +:10F8A000E2259170BD66E41BF41F67A2787B0AFE17 +:10F8B000CA636542C7BF9BC3A59145A30285C0E744 +:10F8C0003841ACEAC88EF05752E1473E7F86FED9F8 +:10F8D000E906BE103802F40EB2741BC817317876F0 +:10F8E00013D4CB233CC08F860092D227F96932F221 +:10F8F000DF3352683BB67F718C5BA6AFCF01BD583A +:10F90000B09D2D358A3FB505DEB48568F9F4CEB4D7 +:10F910002ADE0678FB4B1BACF35420ADCA604BCCFF +:10F9200037B47C93CE0CE1FB21FC49F14E747A9202 +:10F930009D00EF0E2A74419EA5B594B6C4D937B583 +:10F940009DC3D0522A01FFF8BEC5DDC3E0463CB4DA +:10F95000FCE93B693DB0EFD7E8742817E672AC7F4D +:10F96000B57D913311BF9666071D117EFD84228FF0 +:10F97000557EFD8495C1E372F9B5F639ADB328051E +:10F98000E0F7299152403EA59AEA9E013D43AD7FA2 +:10F9900022811E50EA64FCE99D838529214BA4FD48 +:10F9A0009FF3BC6500B7ACAA7E0F4FE79F7503714C +:10F9B000B7D3651DE3DDF789147FEE2254BEC3B3D0 +:10F9C000CC67003E483AD211BE84B8A7C2FE2F9839 +:10F9D0004EF1A59495411ED77B0DEE4EAA37D40962 +:10F9E0000C3FEA7670FE760AB2BB1E8DDDBFF9DDF4 +:10F9F000C6081EC3FF6D8EAAA7E3D40BFE95206731 +:10FA000087514D29AD82E2EF73B1DF2F22419C5720 +:10FA1000C38B178DF1F0E2BF15BCF8739E6706AC7F +:10FA20008F9B69C2F92C7989437DC06108A0FE13C0 +:10FA30005E4CE5079D2FF92DC39BFFE4BDB8EEE6B4 +:10FA400065733D77D17D38D75AE7B98B56216B80E6 +:10FA5000FD0E307D6FD1E4401FF24122BE727B1655 +:10FA6000F4E74578501889DB101E028EF7DFBF657A +:10FA7000F8749BA2375EA39B89EB0AD713B187F278 +:10FA8000B9892F1EC432FDD772FB4478B07EE6B729 +:10FA90001011E0BA80C8064269ED01A713F7AF9EC6 +:10FAA000F41B185DFBDB3368BB26AA6F025F8BA3D8 +:10FAB0003F7C3F1A1F0F6BF0F1F015C3C709884F49 +:10FAC0009F1137E2D36D1A7C3C9C001FDB07F0B11D +:10FAD0001CF1596D4FF550624E1DFC3DE08B276ABD +:10FAE0009F176E8E2D93E7A2CAB98017B41C852F7D +:10FAF0004DBB2E1A3D71F064DD80BCF717D58C89A3 +:10FB0000E6136D38BF230A1EADBB657E36F0E935BE +:10FB100060700C513AA800F946FFC27D234113EDF5 +:10FB20003FE9AA8132D697AF6065FFD65F7B375C2D +:10FB30004BC87ABD2F5BA4F0AAE3BD7D3A902FF9A4 +:10FB4000BEE79C6057E83C3902EEABA7D03B0636D7 +:10FB500094E1E353E35A8A5AE2C04F9DFF7A2E1094 +:10FB6000D4019FDECBF4376B59581F2D5FDF703205 +:10FB70003994D21B427C0DBFCA11B02B36726BB3C5 +:10FB800001CF36664B5C3B5D53D9AEB64AC45FCA03 +:10FB9000EB0B28DE35EEFAB06F282D974DEB07F40E +:10FBA000A3EBF62E7E1BF8E5F824669724B76CD5F8 +:10FBB000D1FE32EF748D6BA7F8F6A653C27192AEE8 +:10FBC000EA3A08FD84174B620FED276B85ECBCA762 +:10FBD00018C66F6943BCAF21F83EFD7BCBDBE0BBB1 +:10FBE000478690541EBE236D1C7CB7329DC3FD58C2 +:10FBF0003997CC7AA518A84844BD7ED82C916B9B28 +:10FC000000E5964AA41749B4FF321BA9AC2385DA54 +:10FC10002DEB6C04F975BA8EBFB3863ED78D63E5C4 +:10FC2000D4E59CA70789772DCE2FD348A671A9ECE0 +:10FC3000BDBF18598E6727D6FB71BF33AB5B4A61D6 +:10FC40001E9979ECE930F874F974FC43EFE9FD2B67 +:10FC5000E83A0F29F8B2746B5566B45C3B74C6245D +:10FC6000E8A8DE7C284BB5178216B0179696566723 +:10FC700002F3C8CD9F9602FBEAC889AD3FA7F7A45F +:10FC80005C05F2FB3D9EC0FEFD97C59302F4798DA5 +:10FC900081CD5FBBEF9F29FBD97C8123FE28BA6C05 +:10FCA0009E751EEDB0E60B42CCFB330F9A08A810F0 +:10FCB000037AC5C2DEA9F05D23E95F0978D8184848 +:10FCC00026FE28BAB82629FEB82A3D345FE0891CF2 +:10FCD000775C43ECFB0B69444E8BF75D46EC7BBADB +:10FCE0008E98F29ECF07D601EF4945C8E6A576F873 +:10FCF00074D05368F99C5F27EBC7029B63FCEBACA5 +:10FD000018B201FFA2FA480BECCB592984FAC63984 +:10FD1000CA9AA01EE4780DECAF10B6CDB446C65119 +:10FD2000EBA17DF43E9E9D652041DC9F30CE03E03B +:10FD3000278F2464D3FE4F0C12E869FB0F22FC547A +:10FD40007C8986A31CC56F32DAFB833A4A5725B9F2 +:10FD5000196B8B8BE896F5AA7C216BAD87F2810C31 +:10FD60005E17C32792CB06F806B2A9753A5EE13357 +:10FD7000D96B275F1B5D66DF47DA0FA981FAB26294 +:10FD8000D6BE2277E87B2B40F6922E9C1F5D470E55 +:10FD9000C06FA06CD2942DB43C26AA2C6AEA1D9A9E +:10FDA000FA2C4D7918FBFE8C359803FE81EADC11A4 +:10FDB0003502A5D333D9C1391C2D3FDAEEAC994CAD +:10FDC000E9B4B18CE9174DFB39374722F06B723338 +:10FDD000BDDEE20E19EA8A010EFD7DC0571AF670EB +:10FDE0002247E9C112D819C432B493A2DA05386C9B +:10FDF000D710F810DB25ECDFA5433AEF741D65DF63 +:10FE000005FE827ACCC31D8BBDC0D8FAF48C6F512D +:10FE100029E7194A1B36EDA9213E4B84BF9ECDF63A +:10FE2000BC89FCF50027027D0EE029F46B89D085A2 +:10FE3000FAFD9FC6ECFF1DA849C94B3F6913E8F7BF +:10FE4000FFD1F897F1A077FF499123EB397F118C0F +:10FE5000BB89F88A408E7FBFB1E0A08E7E77441FB9 +:10FE6000DA02BCB73DF76A84DF116B683847F59258 +:10FE70008772AB6A040ABF23E9A12D00CFFFC8AD8A +:10FE800066E5E1A1E13A5A5EDDD3C4CA05A12D5071 +:10FE90007EA567362B8F090DE769FB3CF93684FF99 +:10FEA00036313E5D2FCB65FAAC3ABF87CA3C4B7307 +:10FEB000418F6E60F267CEDD876703BF9DA323226B +:10FEC000A17C7ADB99632F6DA3F0D8D69A4C7A186F +:10FED0003A7A056A6F6432D4A772A20BF97AD8C94C +:10FEE000F41BCAED42E0D74B1E6F923A9D917D51B3 +:10FEF000C7CF1CD5B213FACF9C538C72C4ECF41C40 +:10FF000081F1D5E7F451EC79245764FC9BD779F063 +:10FF1000FB07AC7EF87E8D99AD8BD20FEEB345D941 +:10FF20009735CABAD6E4323D63BA73CA91DCF1A000 +:10FF30009F28F6CEAA40FA283AAF6E8E04C06EA46F +:10FF40007A8A6C063E5C9F84F64C37CC1DEAD766F5 +:10FF5000FB653ACEED1CF1027F51F949B7DD939D67 +:10FF60001A65377697D2B225E227E8AEF1642739D1 +:10FF7000E099A1031B4AE54FDD4ED64E954F99ED12 +:10FF80006C9CCC35453DB09E6481A0BC9B37ABB02A +:10FF9000A70DF58399386FE2F16473B4BFE3F5B947 +:10FFA0003A80A3BA5FDBCB3C2FE0BA78E6F750F794 +:10FFB0004D85EF915CE6F7A8E3A97E41F1EEF17C77 +:10FFC0001FF647F58D1214EC8ABE710490767C04FE +:10FFD000CE44088D87F7FF1FC2AB1FF0E9DBC2AB31 +:10FFE000B195F211DD25F011058EEBB9A03E93F12C +:10FFF00011F44BC07B9047CF3B7DC773A3E861CE24 +:020000023000CC +:10000000038DA867AAF34ABEFFB569DF234087A71F +:1000100090EEE6FC2019FD085A3D50B503557D359C +:10002000911DF8A9420F6ED5EFADCC23B938F4D2AB +:1000300063145EA9C42A021F3D62088D71D3F6477E +:1000400074BE675F83790FE145CA4306F5F7421E28 +:100050008FE39B553C2161DB2847044F56533C31CD +:1000600041FB1A03DA25DD76FFC6F98027B70C734A +:10007000CB12CA61A467B93519EBAFD11D25E0C712 +:100080000F4F1045D033295E617DF7EC42BFCCFCA9 +:1000900031B219FDD349FE1EC0BB520A00E86FF60B +:1000A00028AC077F08FA91669BD87883F18AF92DEE +:1000B000461256EF54F0B63E17F136A39D303F90EE +:1000C000E029A989D217BE9FC7F022B92CF4EA1FF4 +:1000D00040FF7CD4EC2E20CC6405FF12E9CAC4FE9C +:1000E00028BE8CC81BCFE438F47BD7E3D6AD8CEFA9 +:1000F000B9CB01CE0F5BBBC832F40FEA71FE9BCDCA +:1001000041D4C37526C90E7EF8393C595F08FDB548 +:10011000EB45C0132DBC2BF312F91F42F746FB8BA6 +:10012000E71865630ED43F6846BB40B5FBE6A430D4 +:10013000BA52ED3ED5CFA11D47B5FBEED4D873031F +:10014000F59D7F2DA8A5FDFD59C13377EF8582B9B7 +:1001500016B66EF03FD5C25F74DCDAE5E60FC1CFAC +:100160005C2BEB83461BF091299E50949D4636B044 +:1001700075F87EA5F7039C5A05B27E3BEC8FCCD672 +:100180004FEDD8FAE8756D32B075C93FB0C6AC6BAB +:10019000938DC591BEFDBA3E1A1FBBAE93E3957514 +:1001A0001153066DA7C8B93B5BAD1F7225F409EB6F +:1001B000A24FB29CAECB1559D7B23CC64FE7287CB4 +:1001C0006C90DCCD637A7C1CBBFDFFC67ABB9EF2D3 +:1001D000C45BAF769D7FCEF3FC202F1DE9262896C9 +:1001E00045F0DAB791AEAB0CF635DDDF86FBCAF031 +:1001F00093109B1BF8D89279745DF06CCB447FE12F +:100200001CA3B407FCE6E44729CA3A09F281251B7E +:1002100087235D52BC6574FB14F3BF2C317BD17F07 +:10022000B364B1E8964558FF2B680787297F45BD21 +:10023000A43596AF7F3D1CCC39B5C5D17030E5CC27 +:100240002D8EB3EFB211F139D1BEFF990FDFCBE59F +:1002500025F69790E5B17E0AF0E70E94F9C165ADF9 +:10026000DF8390BF1963BF9713E051E8FBD1787427 +:1002700044AFE0D13233CA1F158F8E5815BF900698 +:100280008F08D5A2818ED5756BE13807E018C72F8E +:1002900044F1A900E07844B1CF283E15001C553A3E +:1002A000B8B395F1032DDCFE9498AF7DBB7568F073 +:1002B000F8DBAE43AD4FB40E55BFDDC02DDE08F800 +:1002C000B9219B88EDA80787C6809DE430F88B6034 +:1002D0005E9B0C947E91AF303FE1678762FDCEDA82 +:1002E000F95CB8647EC1FA4DC42712E1E5E5FAF97C +:1002F0006A35703BAAC06910BEE733B9A9F5F3357A +:10030000DBC24F83DED49CC4E4F7D90356A47392B6 +:100310001F9A03F6C2B97D4602F2A0890B15C27777 +:100320006739CF5CFCAE2D590239AEFA738FED669A +:10033000FE5C99507B9D961B7CCC1FDD2CFF7225AB +:10034000C0E5629ED002F672F39E587F20DD0F1B3F +:10035000ECCF591DE987EF9B787F3D98D8EB0D4C8A +:100360007F59AF23018067C48F70B410ED9A6C91F0 +:1003700080FFAA49F761E13D517E8726A5BE298706 +:10038000F9D3203F01E32E309473305C9A1E3DFD7B +:1003900025C4579B7669E93B96FE1B2265EE220732 +:1003A000FD45D53B23F48FFE03C08BC9C45FC081DC +:1003B0001F909593A7F5FB21CFA159F13FA7F78691 +:1003C000A6827E632D0B10E0FBCD2799DD3471FFF3 +:1003D000D637C13F689FD63F1C54A866251EA5B5D9 +:1003E000D726EC5FCB833F4BB5B7A2FC67453363A1 +:1003F000FCA72BB01DF8E360BC10BC82B881C0F430 +:10040000F2F58A5E4EF577E4F3F3BA46A2FE0EFAF1 +:1004100035E849AA3F0FF426D09F77E757CDC8A704 +:10042000EB9C5D50757DFE78361EFA29C04934215B +:1004300031DEAAF051BF03BFDE57C78514FD8FB070 +:1004400078D03DBF48FF4ABA5C949F307E7F7BB432 +:10045000FF7D9FC6FFBEEFCAC5833281AEEEE1A429 +:100460004CA0AB891AF9B62F811DB0247F201E94B1 +:100470000974ADB63FC1FB30FEA1C61DEA21CE8294 +:100480007226887189BB5B88BB13F3407C2BA1DC8F +:10049000B890889D14DF1B26FB58FCA38588374E37 +:1004A000607156298ADE208E195D263B6839460E1A +:1004B000F6631CA489F6B0C90D7E9AD8EF9B89BF5C +:1004C0005A003CDE73D118D34F37DBD73B15FCDE27 +:1004D0006866F18389CBB7F224CA8F9332CEE37C6E +:1004E00008E8F7177AF45FFFA7828F2A3CFE9C5733 +:1004F0007513E05512F8D5E0BB878CA8C71CD791BF +:100500008580DF6BECE4CE99F479F641E2C9D7033C +:100510001E8B39D1FE44F5D9B9CFBC10E8E219855C +:10052000EFA9EF2BA051BA120F40FD3F19F3472856 +:10053000FB2F01BA29CF55ED0E520271880F157E9F +:10054000DA74ABC507FD85748CAFBF98CFE4C08B60 +:10055000F906DC3FB53CE08F53E8828E83FD255DD4 +:100560004562E2D73F53F055F58713254EB7BE3E9F +:1005700089D92903F4A943FE9B5CEC35F890FF551B +:1005800021FF0D7F6491002ED34E37D4C33A3E9D98 +:10059000954420DFE62E254EFA6EBE1DFB55E38BFB +:1005A000FF40BA8889935E2A5DFC3E421731715242 +:1005B0000AD764900BFB74CCAEDD47110BFD8201B2 +:1005C00025EE2E100FC8AD7DBB46A21D3357F15747 +:1005D00053BE81F66B98CA37B6DFBE8DF3E0BB40E1 +:1005E00001E6237CA8F73FBF1DF49903CC4E53F7D7 +:1005F00063DFBEA17EE03B134F7F9103F0DF77F214 +:1006000085A190E7B14F89AB37188285E84F31302B +:10061000F9DE600B1602FC5E57F0A6218996E9FB15 +:10062000BC745F18F05ACD8B8176765C8F64037F43 +:10063000CE31C54E3F4AED769817A5967E88F7D302 +:10064000FDCE8672787526D3A7E9BC002F8E1D18C3 +:1006500083EB5BAF67782CEFE5D0FF73541F3ED17F +:100660004ABF3F9A7D156913413E5FD8DE07FD3FC3 +:10067000CD13A30879479F9FDF43BF3F378417C13E +:100680002F59A7F34ECD067EB19BF943B4FB00F280 +:100690003A3AAE7B968473D06FBA303700F87376EF +:1006A0007F11E6D3118748645A6EDECBEC476D7E2E +:1006B000C4717D2CFE6BFB857581FFB219FE067D32 +:1006C00024BA7D9CFEBEAE7C561F2A5C46E13145B5 +:1006D000F24905517E80E637B2518E1C7BEC73DC0B +:1006E0004FD2C5E2E8C7F59E39303FFBE4A0A13602 +:1006F0000A1FAF2E50FC5046A65F50FE6B88E637AF +:100700006A7D7915899B9F525EC0E8DCDACFE4F4FC +:10071000E07A86E7F7926779E0175743320FED6F7B +:10072000849267732FF9ECA011F4A94029E6F18CAB +:10073000581E443E40E78BF8797C630AF247F22862 +:10074000C3D7F93F3222FF984FE507F367B0BC42A9 +:10075000F228CB1F3AF19013F1B97C45B01CE9C1E6 +:100760004EDCA047BDD6F1A1CCD3FAB93BB852C8F4 +:100770009B9CDBE1443BF0EE5D4EDCDF890A5FAF22 +:10078000337A304F923CC3E29C773D518FE334265D +:10079000133B8FFAB5DF007AC4C21D1CC6C32706FF +:1007A00018FF6F108207414FD7E6FD107F6CBE0126 +:1007B000C82312A5C783FC211ABB2B76DFE54BD2D9 +:1007C00017B472667141427DE1EFA4C77F337D614A +:1007D0005981AAC7C7EA0B60FF17303C64726D27C6 +:1007E000C7F89CA22F3482BE00BAB022A75539BFE9 +:1007F0004091F32778A667CC37AEC5E79A0296E713 +:1008000070370929790E6103E87F89F0788D322FDE +:10081000158FBB008FC747F0B8E164B0CF887E0763 +:10082000F76EC8D368584E82566AB7CF175A509E93 +:100830000D118988F9AFD53E9C57E6126AAF51BCBD +:100840009C0FB1FC7197AFC70CD25B34FA8A3A6F38 +:1008500015AFB5FAF5C4E57E1EE28BBE9104DFABA1 +:100860004F91044A61BE352666DFD4982C411EFCA8 +:100870000F93F567A2EDCF1AC1F322E33BC3EC2738 +:1008800046234B23D0EF74A7E737A3D2237A7B729A +:100890005978E563B43F3D29D1015F57C7373B2BFA +:1008A0003F298638AFD08FF62BC962F92C478A19B9 +:1008B0005C93E93E6CA570D50B32C24F6F12ED6DA3 +:1008C00076D8FF7E8CD385D309FA6DD5FDDA622503 +:1008D00032E4151F2966787FA458C4276D8FF9006C +:1008E0007A176D4FFBAFDA67463E727EAFD50FFACF +:1008F00004959323ECB43EE34FD40EA4E5B3FBACD4 +:10090000A8579D55E49B43F5DF9395B8FFEF2A78F0 +:100910002393AAA160EF11EE86A174EE44B5431AA9 +:10092000ED89E2DA4ABDB3FF5686BF46D46FCEDB0F +:1009300043F74199CE0773E0FA14BC6ADE555DFABD +:1009400000C81BAFC5CDA0EE2B057DCDC82FBDD5F2 +:1009500044813D955F1E5E06783FDC221A6993C98B +:10096000233EF8FD6C5AFE68979E18017FB6DD9411 +:100970001284668227CB3B66F07CEAFDFAA3A128AD +:10098000BEB368476CB931105B6E26C2D15094BCBF +:100990006AFDA0FED76F45E1DBB902AB03F08048EA +:1009A000C47D91D2D3F107F7906320BBF93B52800D +:1009B0009FDF45D9563C7AFFFCC185BF7E8B7E27E1 +:1009C00018AA3E2F40FD5232007DD5523D279E9DF4 +:1009D000BF4DE16B4663CBC9AD143EC6D78DEE3635 +:1009E000DAAAB7C0470AD3C13E0EF7C1BE1A479C68 +:1009F0002981F846D5882F30BFE4FCBF1037C0E905 +:100A0000BCB912F1E9FC46B3047E80EE1C0BF3CBBB +:100A1000BFC1F9396617CE184FEDE9853815E0BB2F +:100A2000E1951B41AE4C308A2B445CAE4987FB4DAF +:100A3000AD63FAEC36C82BC1CFDE4D0DF43637D896 +:100A4000D1FD362086A98512CB9FE05F3498E89FC0 +:100A5000CE0E4F511BFD6E91378940DEACF0A5E004 +:100A6000053C7B18BA8AB22B8715323ED3680A1927 +:100A70002AE977CD5F2C9D96AE8BC47D8C7A9F67DB +:100A8000289DB77E4F6970287DB5A0B51AED672AFD +:100A90001F185F3CC0F8E2826595F89E9B390DD720 +:100AA0007B82AE17E0F2E64623AEF7C4700BFA3352 +:100AB0004E6CE1B0BC403460DE2DD5A7D22A1DF0CB +:100AC0005E2F1AC96078346F7878E5465AFF6E3623 +:100AD0004F388AFF7FD9FC738C4FFD85B0F1E55DFF +:100AE0003CEA697F11C3E54180A7D4628BB6D71772 +:100AF0006CE1BDC02F176CB9F7DD0900B799B79548 +:100B0000013C26D99766489648BDAA9F0AA915DBDD +:100B1000812E277D59DD3F09F4C42D946EE8BC0574 +:100B20001DF181BDF4D696EFA27DB0A026C90EEBD3 +:100B300093366F9B0AF2F82F354374B8AE9738227C +:100B4000023CECAD19F07E012778E3E1D5E1021E0D +:100B5000F1AA7284C50DF271C1EF78C4174A67B764 +:100B6000425CA9718B1EED8FB7661EFEFD6C47843B +:100B7000CEB8991B664C84EF7FACC7EF07F4BFCDAE +:100B80001F7F007E17F84735119043083F2DDD1970 +:100B9000472C2F847969E96FC18A964296EF717963 +:100BA000744836333AF41572C8A7BF011D2E2CBC09 +:100BB0000C3A24C35263F48EC17C4F46BC55E3E526 +:100BC0002637F16CB3607E9487A3FC7A6DA180F523 +:100BD0006B0B999D29FCF59E1DBFA2704A2BF4FD5D +:100BE000A010E42BF194827C96C26215B8E62D8A9F +:100BF0009E4B36B3F318600FC1FEAF4F27DB3BA30C +:100C0000FC5F8F417FE9C817DAA19FB37FFCA20F79 +:100C1000F6AB29E74C09D801CD17FE0BF36C2CFB82 +:100C2000597E96C51DC6BC35BDC38BF8A8F2FD66BE +:100C3000379343DA755D28D4333EED08633F635C38 +:100C40008C3ED5F8F4A6D6248C136E72F8CDCC8FDA +:100C500045F553DAFFF4321EF98CA9AC9D801C23B4 +:100C6000153CC6F7267DF16B02F1D077AFAD7683E8 +:100C70001E6C297B5348837556E895FA9FAECAA52A +:100C8000F5BFBE760ADA73F764F112E853D3CBF2FC +:100C900064949F1E96273FE98B14A4C319F5335023 +:100CA0000F56E7EB2526C942F1642625D6E8F30462 +:100CB00033AE354B9628FCFAB48B9BC6EC0029E585 +:100CC000E631CCEF162866F23C1A0EF7641970FC78 +:100CD000D905952F01BE4CBA8EEDC3A9978CFE1590 +:100CE00074DC53E6F8FADDFE42E647C815AE47BEAF +:100CF000B4F42523E66B9CE6E27F7FF72A1EF3CC53 +:100D0000EA5771C44FC73BF5FC6B39C0D73FDAF6E1 +:100D10005A4E6DD47C12B5FF6361227F76F0AE68C7 +:100D2000FFC074038B139171C6187FFF749B721EF2 +:100D3000E612E35FFF9430EEF38B6130DF5F0DC4AA +:100D40007DDE19161DFF1A8863BA59DC471BBFCC1C +:100D5000AFF83765BEECFC41ABA0CCD76D6471AC8D +:100D6000792C4F62C98134C4BBE986F0E318DF7C7B +:100D70008317953897C784EDB3587D8275118F27F7 +:100D8000DF518EFE319C0FB7870B5A6DDF627D8479 +:100D9000C5B5B4EBABDDCFC78DD336BB585E48725B +:100DA0007118EDC0A3EF3C0B991803F86EDEEFD479 +:100DB000459F5B19D06715FCBE09F09BAECFBC8A7E +:100DC0009513E175227EF5A822B755FC3EBA2A2F6D +:100DD00005F0ED215353A88FC2CFC3A710F3105ACB +:100DE00056F241E40FACC88778052E4491835B3EF0 +:100DF000B0A27DD6AE6F7906CED9C96D02D946DFD5 +:100E00003B929AFC6DB42CE9AD9847777FD28CADBC +:100E1000608786A882CBD1F2E74947B6829E404CD4 +:100E200029444FC791AB94F60693D84EF58BA79201 +:100E30006DC85F5AEF2228BF334990E32840DC2376 +:100E400073991F7CD16E0EF3E729C583DEE7CE8B45 +:100E5000AF8F168C64FCFB8F905045D7EBAE8EFFA6 +:100E60009D7BA4EAF7137CA128BBF461CE2D29F960 +:100E7000E404F265F5A47F36F265AAC7FF9ACA8337 +:100E8000A1FC2BE8FF3EF6A0EF9978E792D4E75D4E +:100E9000D5F1FD0A1394715D5D9C5F6F43FAD56DCA +:100EA0008DA15F25AE6BCD70530903F17C16B7CDD4 +:100EB00027EAF9940D10171952C1E668F38408E87F +:100EC00017595DD7135F1AD0D3C44C906F4BE6C54A +:100ED000DAB959B5ABB2D10F597BDF0C90DF1BF4F7 +:100EE00096555C0A3C63FD871B34FEC3AFE30B5988 +:100EF00009E9664216F8633644E2C1883FED73455E +:100F00003FCFE12A48749E4346BBD4E7033DA8D2B5 +:100F1000E4EE710FA61F52E1CE8275BDA8EE9B4292 +:100F2000CFCD0A6A72FB39B44B07F343059E8DC3DC +:100F3000109EE6AEFBD16E4A2E657EF7E4FA5A1F8C +:100F4000F09F64CA7FC08E33185A38DCFF89CC6E9C +:100F50005BC2B1F2924A5194E9F7069B923F7D033E +:100F6000ADB7039C7CBE68BFC335BA7B2AA3F3B47C +:100F70004542DB031F9EC5C69B6E5ACEF2C47D540C +:100F800047CA8EC0B14A81637E45123B6771AF0983 +:100F9000FD719BCD5D385F9DC4ECECDA4E33F2BB46 +:100FA000A1BC0BE352BD7A861FB2D584F4EAEE7D74 +:100FB0001FF305875E9D25F1CE28FC59CAEA55BC72 +:100FC000209A3C138341EA037F239D881BF2949669 +:100FD00070525F15AE4B0CCB6E58B7C2974B9298C0 +:100FE0001CA1E66616832B8B3B6AF68BE20D8B0306 +:100FF0008CB1303F17F149A87769D63B186FF6BA24 +:1010000080DFF60EE0CD1E573C7EBBC62EF5F544C4 +:10101000E30B9156821FF8111D0977C6C31F77ACE9 +:101020009DAFCD9BD4DAFB4DADD55EC5FE904DB8DE +:101030009F06B43F9A96557A99FDE16A037F59F36A +:10104000722AA9689BEAFD9C09FA6B9E6543FBBB6B +:1010500079CF4ECCA7689A46DC308D5AC59FADAE8D +:10106000F3A89EC549A9CC0A403E47B73DF4349C3D +:1010700083EDAE57F3BA589E93BC8753F2BAD43C73 +:10108000C0F011F0D7767312FA6D07CED3D2FD6798 +:10109000F95C979717682DF63AC112FF69C17FFC7A +:1010A0002629FD32F2AAE582755F9D579D742BD4E7 +:1010B0009B602F947A4003AA2FAB658F59827CAE38 +:1010C00048BD40ED4ED31E8EB597D7DC3245C07378 +:1010D000704AF9F327E1BCEB1A3389192F7A7E8223 +:1010E000A67F302D2D92FAFD1F664EC9C73C48657C +:1010F000FE154F7A86D1FEF4B1FD21CA28EDA1A0DC +:101100008EF7C2E863DD8F0E8BE8ED548FFF6CE441 +:10111000F888FEFEF0E1E95D63E958C9E26778EE20 +:1011200050D5C39B1D2CCF5A8BE77F53E414B58752 +:10113000A7826AFDF0ACC55EE877200F72FF5C0FF6 +:10114000D8C16A1E64F3722F9E3FA47ABFCE057980 +:10115000D57F3C73E220013BF314FA039A2F08CCAD +:101160004F4EED078EE28B69FF5AC41FB243EF0763 +:10117000D74EB75D26808FDD07B8F1805F84B4E479 +:10118000DC42617F9BCB9384FD25C83FC873313F10 +:1011900077B3AB6A6321C0FA398E803EDEE9FA1478 +:1011A000ED8AA6BD53C6479F97ADDFB38E9DBBDCCE +:1011B000A18FBBEE3C17CB776CDAFB2AC67B4EF9CE +:1011C00039A4B985827F35D89B0B17EAC0B2226556 +:1011D000FEB998374D661908CCDFACD821CD3B6EEF +:1011E00092E1FC6E33FD8F9200D9E49D8FFAF6A652 +:1011F00059260BE40934BB6A1723BF13933C60CA1A +:1012000069E739900FB92C09F3AA3AF7E8A7819D4D +:10121000544EE9E26716E0ABEF39B702FF4C1BC74B +:10122000B78B90771A5FFF2E1AC5E45007E795FF3A +:10123000B90CE338243ABF7DC41E667F4D74196231 +:10124000FD932E66175E2BF75703AEBD218492C126 +:101250001E6E269E4FC0EF45BC1609E3582480FE43 +:1012600040C78312DA4D2647E891B1507FAD8076B2 +:1012700093EA4738BB3713F5B1975DBEEFC23E9690 +:10128000F3A127FF19E0F688A0C4C3185FC9B9C944 +:10129000320EEC2BBD83E93366AACFC0B9A1EB5661 +:1012A0001FFF6535F0568717F50842851CDCEF50A7 +:1012B0006DE2583C48A33713D13D19DA4F55FCD2A3 +:1012C0000574B74E9810353B2EA6813FC32103BC51 +:1012D000DFA10B48A3F55388A783ED0BDBBFF50611 +:1012E000A6AFAFD799505F57F5E164473FDA898DD4 +:1012F000010EC76974BD82E7471629E71406CE0BB5 +:1013000008213C3F51EB4A56E2B01D0C3F493FFAE1 +:10131000C3C88B6C1FA8E689E72A54B8ABE70CD486 +:10132000FE0C4A7CB751F1E75280317A74A9F1DDA5 +:1013300015CA533D07C2C62582541EED775C5F4334 +:10134000483FCE4BB2C17C1FC9F0DEE7A2DF1FA52C +:10135000780C78767455B29F708047FD1E88D3C88C +:10136000A52CFEA2C5A7475C9C72CE2C3C15F3F0C1 +:10137000F6263867B627F69C19E50F8BDFA6E394AF +:10138000951D76037EAFB12BEDAF2778BE407BCEA7 +:10139000AC4BD987FF73E7CCDC9CA7873EB7BAEC90 +:1013A000B1E7CCDC6CBFD43C19EDF9B2B3D94181C3 +:1013B0009D07093DBD0DE5A511EDC2D73FEEEB0040 +:1013C0003FF3B952831BCED564DCF64E07E62B7192 +:1013D000420BC44FB5FAC0EF9CD53F01FA5977CB09 +:1013E0006E37E68F6BF481447E008CED46F9890EF2 +:1013F000B8AEAC1FC0DCF5B90DF0ED34177E1CF2B1 +:101400009AE5037CDCBCE60F5C89E2629E59D1FA66 +:1014100069879AFF674F8AC987ED4890FF9748EF21 +:101420001712E6FD5D8FFA5BC740DEDF34557F8B18 +:10143000CD6B1693BED25E56C79F1672C6E4117C62 +:1014400072C9EB54EC9804EB4B64B75D6E5E841686 +:101450000E1D09E4E85F5D03F13F4D5E8447843C67 +:10146000820EC823A04F812332FACF760EE44504C2 +:10147000D15FFCEA48F47B1913E645B0FC3EE1C0BD +:101480004809BE7B58EFF5803D23EFD42B72C0FF97 +:101490003CF84D3A0E64A39F8DB84225C01F05FB52 +:1014A000D42CD0AB3A14FC6CB8F4BC88B4A2387914 +:1014B000115BFDE31ECF65F6737F32D5CBB61226E6 +:1014C000A7E4FDCCAF49E78D7EBDF063C3515FE576 +:1014D000669A701DC7DE30F618510F77639E436D14 +:1014E000162F827CE9AE293F01F2EB18555C818E04 +:1014F000EBEE5E8EF66BA2FDA95B151B7756DF5FE8 +:10150000EA3E8D2B62FB7414EC7B14B432FA8B1719 +:10151000AEE20E62FEB626EE5D56441439119BC74C +:1015200070DE5C89F1D8FB9EA8C138EC7CD282CFFA +:1015300085A44B89CBB2788BB44A403921EDE0FCCD +:10154000929391890E6D7B5187F7F550F1B609445E +:10155000A24CA9E66AFA9AD371A0A74A1DB49C4985 +:10156000D7B55A90B3E8775BDF4F46FFEBC30E4920 +:101570003957C3EC2FF9510EF53FDA2FDACF720746 +:10158000C51BDACFCD452C2ED050C4FCC91445FC68 +:10159000381FE5D9A1E47DA8E3B5115D109E3A8E10 +:1015A0003D1F168569F1F43BB5BF0E7D8B09E22D19 +:1015B000E1E13A8C679E377866613C30B59080BD3A +:1015C000D8616D59358DD5230F3D6F0E7BB1FE3B34 +:1015D00002331488940AF3BD41D90FEDBECEEB8AD5 +:1015E0002D6BF313B4F77ED411DFC8ECBCC1F760E8 +:1015F000DC50C4E4E1F94EA7B22F6E8C9777E8A5D2 +:10160000DF38413EAE16500EB70D6370D30D67CF75 +:101610005CFBE4592887ED543FC5F9B2F9E77EC772 +:10162000C101FD75D8197E7DDB796BE7BBB4A810CD +:10163000F7AD038C063A5EC76ACECFE0C5E67DA95A +:10164000FEEA278AAEAC9C3AC6B9B70701CF2CFE9A +:101650001F81DFAFAECD28023F3BCD29F4BF9A47B3 +:101660007EB669612A968FAE2A403FD000DD9E5C2F +:10167000B918EE33B9D47C8AE714BC7857E387AB4A +:10168000ADE0DE837EB47007841254F9439B56DFCD +:10169000543C15F863938E4899A00FACD2E4B3681C +:1016A000E8798AE47BA508EC0F437F1FE353A1424E +:1016B00001F56FB31BE0B64E776CE7CF015F769A0A +:1016C000313FB26979783BF82B3325DF5E68776666 +:1016D000D9E1A99C84DDA19E74EEC048BC1FA7B6C9 +:1016E00043738FC7A3B1793464552ACBFBE88E7D51 +:1016F0000FF737C4B41B945FC3F4D6F5065F11D857 +:101700001793AE6379891FD7EB08E0C5C766863F9C +:10171000F2635645CEB80BA3F5DADF6BF1E3313354 +:10172000E2479D72EE4DBB1F8D801F74DF1A14FCC3 +:10173000F8F8D5AB0B013FCEECBCBA10F063BDBEE0 +:10174000CB03F4B53BDF7718E0717C8AB74FC7F85D +:1017500052E1E5E0ED4757186F2F55BF328D4A141F +:101760006F91EE888EB7F4EA999F4C36C79E1BEBBB +:10177000BD4CBF6A62FF58517EAC7FCC951F57BFEE +:101780003299BF52BFBAFC75103C37A8C6617AAD1A +:10179000E1C7B747C16B8999E5A32C291245B91454 +:1017A000D6579B87E710FF6872F77057749D317E9C +:1017B000C037BEC85BD905F3F030BFE51B82D477D4 +:1017C0000D1DF70DC2FC96DA75DFA8C46154BB5B32 +:1017D000B503B5E3978C627AE6A4519E52B00B260E +:1017E0007D7111FD0827E11E2C3AAEC9FF33B4E725 +:1017F000C87E4EC4738C128B8336ED9DF72CF85D3A +:10180000EBFD4AFC721787F67AFD739F60FDD93DA8 +:1018100075586FD9CF05210EDA3C4C87725BCD7FAE +:1018200050FD3FCDFB4BD1EFA3FA7FE83CC6805D76 +:1018300099EC081B906F817D49DB35092CBEDBE4F8 +:10184000206E1958ED9E58BF899A1FB5C96B407A12 +:10185000DFB49FF3833D9E61F03987213C87892760 +:1018600092237C63FA28CF4AC87352F3EEE0FE9FBE +:1018700051E3D10F9A83E710F4EA7D2FB1F7F324F7 +:10188000C2E70509E986CC89C6B790260E11BA626F +:1018900079CCB351DFFE6FE2457DDBA7C1B75002C3 +:1018A000F9D23C4ACD63BE15F57DB5FDE0FC7E3F27 +:1018B000CBEF1FC8CF6379FC0DD309E9B4B332DC99 +:1018C000EBD408F73AB999BC0F6AE47D7419F2E1D8 +:1018D00082517CBE41E8C77302EA3D4E901F17FD5E +:1018E0007D139CDBC963797231FD28FC3F93BF07F0 +:1018F000E35571E2C47744DB4B8754BBB0543D17CA +:101900001636803F6A499B230C718F4356E5BCBA5B +:1019100092AFBCC41C3E06FE9A25CF67E279A201B5 +:101920007BE425A3E2EF6774DAC0FE24CD0B8FA21F +:101930005FA219EEA5E022FB363DA11DF98B7C8844 +:101940001F1D1AB023DFC987F363AA5C687033FEDA +:10195000D6B08763E70803B1E7C85E1E7565E58406 +:10196000FA5DA2F6874625B24BBF0ECE0CDF0F25DF +:101970003A7FA7F075158E5ABCBF5CF8A9F503F045 +:10198000A37C08E583067E5ABF9FEABF231D22FA87 +:10199000F7A80E1580FC53D57F77A9F2FB43054EBF +:1019A0007F6FF94D4627E243DF6E7F12F1A3CBDD57 +:1019B0009741F21BF6A724B1FCCEAFF83765DEDA0B +:1019C000BC0965DE9ABC8943FAF00C760F0B858F53 +:1019D0007370DE4442FCFB9ABC896FB04E4DDEC48E +:1019E00057AF539B37F1CC81A76C105A84F38BE02F +:1019F00027E9DDA6C77C81A9BCC5C3F2D97896FFCB +:101A00004A3C785F6FB3C98CFE106DBE1FE5542B46 +:101A10005B401FAEA0760A9C97DAD28E7A4463367A +:101A20008FBE55C86F14A538F9A4424D4A501A9C70 +:101A3000D706E70BF05E8BCBCC6BBB66B4D581F2DF +:101A40005722CE6F985F5A3D1AFD0F5F9DD7F65C07 +:101A500001C3FF372D9FA545DFA75B552C13885386 +:101A6000253A0751339A1BC85BC6F38A824CA2E51C +:101A700071A276B34733FBEC4D43F8FD00E881B427 +:101A80001B88D36619A8F55F16B9AFE13697F7F64C +:101A9000D1E9A83FE1FE9EDDFB078C4F3C934D440E +:101AA0003897F08C5EC67D96D309E2B59A7FA18EF9 +:101AB000734E89A35D2AFF593CFAEF2B171EFFBF17 +:101AC000CE7706E569317AFC06FC06E96F809FE86F +:101AD00059FC4ABDAFE56BE5DC95E6339AFC9244D0 +:101AE000EB6A065AA4F8F3CA68EF8B8C8E3CE817B1 +:101AF000BD5CF9975C46F52180C72EA304A466520D +:101B0000EE65218F66AB7E5C769FE79AE1A82F7F1A +:101B10006C66F355EF9B51D7F3B6163FBFA5DDFDBD +:101B200078BEF7E7405FC72B3D780EFC612BD3DB17 +:101B3000C2CFB33C7DEDFD29946ED87D32CABDE0A5 +:101B4000DA7B20FE38FA1F23BF2F8CFEDFD1AFFED9 +:101B500051F2FBF2D7116B7F1FB2B23CC888FDFD7A +:101B6000BFB6AECB92D76A5E747955BF129FE008BC +:101B7000C427D4719AFBD9B9A2A1CA7916F5FD8DF3 +:101B80008A5E7867B167189C9F292B0B3E0DE76B27 +:101B90009A880D7FD7A02970FF8E5F39D8F9662CFF +:101BA000BB587C95782D785E3FADD057588CF41B90 +:101BB0005A09F439C241CA21CED1E99A49EA2C988E +:101BC00037310AEA472C0F3DFDAB32CC1B6B017A53 +:101BD00055F3A6CB2F7EB6725A19CE17FDD50E63DC +:101BE000ECBD333716337B507D4E53E64FB73D1B6C +:101BF000E67366213BEFDBECF088E0F756E3F4C9CF +:101C0000523FE63934ED62465139D88A50FFC03030 +:101C1000A4AFA65D95A510BF25017329DE07FE2799 +:101C2000760FFF996543D03FFAB2CB5709F3B696CA +:101C3000F9AF07BB7F041D07E2BC67765E5FEA8BE6 +:101C4000C33733F95419E2E0993C093C2946F816A8 +:101C5000B5F767A37F7B6518FD6EA5C5EC7DB383E3 +:101C6000C9F5E6FD35649E2552B63862CF8B4D1A14 +:101C700035A514E6515A2C2879A42C6FD549D530B6 +:101C8000F0736AF1C9A9E4ADD62879D9443645F292 +:101C9000B173BF3E6F559D9F5A56F356932F30BF79 +:101CA00043AE68C03C17EB2AC657C97282718E6B6F +:101CB000C3FDD529144EF9DDC16B014E290076BC58 +:101CC0006F39F4C858FADE91265C0BFE9BA75BC700 +:101CD000F582FE2BACEEFF0E6C89D42556814B3479 +:101CE000ADD0DB887824B4B8802F55FD4ECFCE55CB +:101CF000AD4E46BDB23BA701CF559D3D6C8C7B2FB1 +:101D000085FA94C98A2C8893E4AEFA77CC63B0EE56 +:101D1000E2E29EBF7BB7D8A29CBB5A91057117EB3C +:101D2000AA7EB982F69FFB184714333A9BCB027FF9 +:101D3000B6A003F95AB787DDCF58D765AF32A1BC3B +:101D400061FE2572AD03E588B0FA461DF009A18D4C +:101D50006AB1749D6F17B3787A41B7A80339F5AFAC +:101D60005FF271E35E4F1447CEE700B81A8DE1BE13 +:101D70002C67242F493D97A3FAA706E4CFAEB9E814 +:101D80009FBAFC3CF4F0ED98E7F86506C683A6DB45 +:101D9000983D420591723F516CFB41F713297A8BB4 +:101DA0006A176BE9409BD79D5F3104E982F2D1C08D +:101DB000263186EFC5CDEF6E1598DE4DD7615802FE +:101DC000F3A8CC72833FF152F3E9B5F6F4809EA3F9 +:101DD000E825EABCBF69FEB95ADF0079E771FC1F4C +:101DE000AA5ED3A19E33FF92DD1F3742B1278E76C4 +:101DF000FEBF12764FA79AE7E267E754F4947F227A +:101E0000FE84AE93010F76D9754DC5180F6BC27E57 +:101E100056B3DFFF18B12A6F4545193C45C25178CA +:101E20001FDDB76804C69B295D14C4A18BC5C5EC32 +:101E3000FE06617532E2B1B09660D6A660CF403C36 +:101E400016D6317C5DA4D0BD9A67A7C62DEF2CF6BF +:101E50001D2B4E8FBAA7A53589DDD3A2E4AB5B5B02 +:101E60000FBF04F79F3CADC4AD7BDF183D13E38982 +:101E7000AB050EECC3F3F6B923C07F7756E1DF560E +:101E8000A19F8896687AEDC5F38EB907D8392D41A0 +:101E9000C9AB15563BB6027E9A9D3E3CD7F99D8E46 +:101EA000208F795BE2F127A7496077840D906777EF +:101EB000AA4D08AFB0A3FE14E327D3FABD8810C023 +:101EC0003C22DD982BAB47A9DF256A2F8D49A83F1F +:101ED0007DABF322E46BFC53DF16AF13F9A72E7F23 +:101EE0001DDA7322CC3E216FB07CAC38EB8AF15FF7 +:101EF0005EF175A97E4B6D7EDD203A66FE0FD51E24 +:101F000052E325C423C7E4BFF7EAC520E83D904F5C +:101F1000FCAA1BF4EA1F9BA3F3DFAE1FA38BBDB784 +:101F200092F8CD701F429D723E9A08EE5510B7BDD3 +:101F30009FB776817DD70EE71240BF04F87251E754 +:101F4000333EB0629E46ABC0CE6F10999DFF5832B3 +:101F5000AFE5C7D07E495BA608F097AB5A7E8AE70B +:101F60003B74C4DB4E9F9F2BBF87A3CE473DAF90F2 +:101F7000487E0E3AAFF035E72DB2139CB758A0E07B +:101F8000BDEB2E82E72DC82ACF569857779B40206D +:101F90003E9D3A8D95470826FC7D2633E47DA7E1DA +:101FA000F958CCCF0E5378429EB919F2BED3E03C1B +:101FB0000CBBA7939B390DF12F95C207F482763D98 +:101FC000BB9753BEC582F8543D8DC55B53BD06E437 +:101FD0003FE7881BCF09C8707F9F03F06C05E2675D +:101FE000D89A81F1E2D47CA6479ABD069DC9897929 +:101FF000DD88AF614ECDEB667CAF7BAE84F9F60336 +:10200000F774CE23B83FAB0BA666C3EF920CB9C9E9 +:10201000C0417C499533550A7E746F55DA37B2F664 +:10202000708F27CC8F2C61ED07EEF1FC3EAB6F1566 +:102030004278AF14D561947B2459FD92D919483F59 +:10204000BC722E97DCA69C2BE0D83D644B660F61DA +:10205000F536C607C9DD498A3C57DADF9BEA57E205 +:1020600005EC7C40BD4EB9EFA08B44C79F553AD3D9 +:10207000FE3E4784CED8F9922722E704909EDBAF3C +:1020800017310F52BD87B4CA6260E7CE4CB17435C8 +:10209000694C2AC3FB0AB709C65DEBF4FC644C5CCF +:1020A0003F8D7F6E345F19A2F295BB0D1ABB2C9346 +:1020B000C1D5167E9A9D4F335E965D96380EFA7C9A +:1020C000766C1C744776741C54DDDFAA8506E42BFD +:1020D000DD76E92DC897DA44410BF73A6AD7BD6936 +:1020E000E07E76BF19F452AD3D7828415ED4E931E7 +:1020F0004C3F7427F0439C1E93C8CF9520AE5C6A7A +:10210000FC5F8A8F33FEDB9BE03CE200BC54BDC920 +:10211000A48D7BC897E5F7E935FD10F9A0A75D20F0 +:10212000E6EB6859737E8EF241E48BF20AA3D8EE97 +:10213000003EFA43E48BADD4723546F1456A8E5EBB +:102140000DFCB8F74117FEDED55B0FBAF179CECCA6 +:1021500005F8B1F00CCF018DE993970DDF83FBCD2E +:10216000CF59C33970BF794A207516DC577E2E3D92 +:102170007C04CAB69FDEC1CA05E1A7E1BEF3FC9F9D +:10218000FEF27B58061A1B42975B12FC9E5C0CF712 +:10219000EE8756F6837E5FA63977A0B97F19CEC742 +:1021A000C27A322D068C53672AE792C964C53F0470 +:1021B00099694077D9A598576821D2AE7EA81FC6E5 +:1021C000E42EAD6F83FB7DDB0B9C2C6E4E181F2025 +:1021D000C394BC131292C11FD5EEB463FB01FD6E14 +:1021E0009751C95B63E3BFF72ABB37493D6F4D8801 +:1021F000381CEC468B4462CAEA7DE6441087C3FD76 +:10220000C3ED6ABC5A291FC8F48D2A89B25FDE9BD0 +:10221000727F31ACF3E3DD0FE4833EF55DE577E2F9 +:10222000B478F5D7B14C8EAC48FEDB1CE0E3EFF39D +:102230003637F80F9666FACAA0BF798EB6F1768A5D +:102240003F93C54AFC3DAA89F26C0EF88AFD6636BA +:102250003FFB642F37AF38F23B55E93E01FDF4C434 +:10226000D7CD83BE9D7EDC2B027C1A4CE11C81F60F +:10227000F381C33709FA3D3FF7C3FB308F70C87B4A +:1022800047E05ED4F7F45DD536C027A7720F36114C +:10229000F01C50DFD0113DCAEF6DB1F340059C1228 +:1022A000870D4E06B9700361780B65A8BF51B987D9 +:1022B0006EAAC8EE8D9D5AE6C4DF4F9C41C202E073 +:1022C000C3D4F7BD3602F471B3AF2CDE3D1BEA93E5 +:1022D00064E9A568FAB95E8A2A13C8B7882DFF9306 +:1022E0003BB6FCCF155F8E8C2ED7089E3B60DDAFD2 +:1022F000734CFEC81398FC11496005C8C7175AC42F +:102300007118577770329447BF3604F3A84816CB3C +:10231000BF1865CBF53338E46D867585A99CEF71E0 +:10232000C0EFB0B1FBC532DE376C85FB2088246D71 +:10233000063ADCAD77619E6986A5F6676DA8CF5831 +:102340004901F2296933E2B5D524C1EF961CB4B234 +:10235000FC89F6B53A8C37713693CE43BFE37B04E4 +:1023600026FFAD0BABA19E2FA71B426575AF9DFD50 +:10237000AE5BFB78A25F510AFBE67E1FF522AB093C +:10238000CF274CB6B9EE807ADE66C0FB2B0E5ACB57 +:102390007DCA7804FA7FCEBA10DB038FD653FAEDEC +:1023A0003533FF3A4FEDE3156C7CFCFD46FE1EA273 +:1023B0008C6F220628D7123C6FD06B17D97CEFD5D3 +:1023C000613C04EAAFC3F999B05EBDCF3272BEB7CB +:1023D00052C0DF21E088121F6BC3F2530A1F6CD773 +:1023E0008B07014FE58F0881FD986CBB8074C0EBB3 +:1023F0006C6EBC1FC843F21D1984F92CE8F77C866B +:102400001884FC7BFE1E1BDACDA0F940FD50F813AA +:10241000E95AF09072C53583E3798E021E8FE08809 +:1024200017F6E354492EF2A36775EF6DC0FC0A8BD3 +:10243000D7E8A6E3186E23B8BFEEE4F8E77AF7967C +:10244000303A1DBC7FE55990C7C1D92A2478B65BC4 +:102450002B2438A7D46B776779A3CA71F6C50F7898 +:1024600013D91753505702FBE19640BFF8FAFE68A4 +:10247000BD05D623E1BCF8216E09ECD07C1BED87AD +:10248000F27D775AFC759C52D61150EE2DD4D6FFB2 +:10249000BE4477A5D7A9C1BF6FB9CE8CD8755EC130 +:1024A0007986B82B304F3E87CECF12991FFD13EFA0 +:1024B00051BBC1A243FCBA41BD1FCA157B4E447B30 +:1024C0002E8490E51B81CF7C57C977AD4AFE17F467 +:1024D000E35F4FF57C906B7DC93FCC877CD3A92906 +:1024E0006D1D8C385ACECC037E6CE290EFDC4882B6 +:1024F0002BE1FDB94ADF33F63CE4FB7F2B190FF7E4 +:10250000E9FA46A6D2F2C7FAAEFCC54EE48B1781B3 +:102510002F5A4818E9EE06F8BD46A0BBE9FE0E2882 +:10252000D3315AF09E304A8740B72A1D0E9E3FA5F0 +:102530004BFAFDD0161B9EDFDA428278002F8B7497 +:1025400071CCDFD282728B48C323EBA4443BD5D439 +:1025500082EBF8799B8CF2E1BBF6270528DF5CEA79 +:10256000738CA5F39A35F613FCBD0792357724D802 +:102570009D74BEE963FF81F31D7CAEFEABF3C8FE24 +:102580005EF6E884B1B1F6A823E96F9807277136A3 +:1025900037A1FAE3807DAA37615E42E41C72B80E6F +:1025A000CF3B73295E9067EA39642DDF9D741DE38C +:1025B000BB1F2FB6B957E03D923BD02E6DBED9A2BE +:1025C0009E5346FDAB79A14E39A7CCA15C6922266A +:1025D000BC2769E0F72CE93F2E23F2BB34FBE0BCBB +:1025E00072D9579D5796F03CB4BC9CC5E907ECBB2B +:1025F0004691D9AFEAEF9BDC9BABFE0E05D3531699 +:10260000934BB26FE39C6346BD91A4E814FB95E93C +:102610000BDD13245126185F657AF86C03D6AF4F93 +:10262000F2E3EF05D5F15D88240D63EDCAFD0F7E61 +:1026300033FEAE98C15D087C428DB3EECEF7358F88 +:10264000A5FB34AFD893C3D1A5D41958FC94D2C1FB +:10265000E67EDA6A1A69790E7E6FEE7AD2F25B5DF7 +:102660001ED2C1BDF0FDACD19FB0DFA18BD0C17D2A +:10267000400726C2FC01372871A2D73FDEDE01FBEE +:102680007E8E23EC3C9A4B7B1ECDFBC3B12C9EA5CA +:10269000FC9E542CDF899AC7713D9B8783E7711E8E +:1026A0002BE3CD63101D123F8E4FF7B705CFCB6BD9 +:1026B000F0483B1F6EFFFD789E6FF3ED44E42780EA +:1026C0001CEF37033C870146E4C13A7DEB609DD99E +:1026D0009062099354ECEA41F3E62DB8AFB7CE1EF1 +:1026E000C8D399915D0E712236EE53C94DEBC0EF00 +:1026F000D17CBB1EF97BCDFE31A8A7F5C94611924E +:1027000020C964965FE3A6FF8379CD229E2976DAFD +:10271000CF4D620DDE0B77F3746D5E8EFC500B6D4A +:102720007F8B92E773EBCDFAA3D1FAE639FDA37A5A +:1027300080835C6769E127427F42A4BD73305C06F9 +:10274000DD4BD5C1F813A17A0EF4DF5E1140FE9483 +:10275000884FED1D3B709FDCC86F98EF73702CE2C3 +:10276000ED57E7FB6C57EEB17A4B1FC6FB51DF4EBE +:102770005FB079315DE7C81F15E3EF1B4FC9A87F34 +:102780006E2D2DFF78D3282CBF9D71FBD2F7A0FEB4 +:10279000E9422C4FD67D3207E8C1553EFB06F85D75 +:1027A000E8B7CCAC9FAC245F770DFD2EAB24771C33 +:1027B0005C6033D910C6EF6E1CDB7815F8632627F2 +:1027C000B1F2A1D23F8CC372AE521EF7FA2828BFD5 +:1027D000C57D32271E5F1CEDE2824554DE4E4E65FC +:1027E000DF4F1FF7FC10B0E32757B1F26877E5EA37 +:1027F0003CA8D77D3A279EBE7456E1AB93BE38D72E +:1028000091E680B030FBBDE2D73C1FE2EFCB78A968 +:10281000BC85FB06BC152C0EE7F5940AF07B6655CB +:102820001E56AEB6B465031F9CE1339441DC55B42B +:10283000383B44DA2EA5A2723CEC7B3555B721CE4D +:1028400049E9EB53A4AFAB3FC9B1A15EAAD297A8A7 +:10285000477A4F7CAFE4E76CDF62E981F6F705CA9F +:10286000CF6B62E5E7207AD5E0E1FF008B7F42C5C0 +:1028700000800000000000001F8B08000000000026 +:10288000000BED7D0B785445D2769F3973CB7D429A +:102890004248088409F74BC01912205C1D02645994 +:1028A000050C171514E1041002B98DE0EEA2EB9AA5 +:1028B0000901441777E38ACA2AE88080A0C80E0A73 +:1028C000C86A644764237EBA1AAFEBED631345E52B +:1028D0004E0CA2B89FFFFAD75B7D0E99338405BFDB +:1028E000CBF3ECF7FC3F3E3E9D3ADDE77475557542 +:1028F00055757575CF55CE4EE15FE60921FC891EF1 +:10290000473E95BD6D271A7B0BFEF74357592A6941 +:10291000427410FABF9521457413A2930870B95EF2 +:10292000D42A421562B2558BF70C12C26E6970E35D +:102930007917C5D3D745CF45BEC759D41F2F764A7F +:10294000FEA29F4053F1C395429CB67D922D5285C5 +:1029500008D00375383DF489EEA9D48F82A66ED9CC +:102960009595E04CA35FA1B85C69E857D62B757FBD +:10297000E5F7D739E8FD0CEEBF93A73DF093F8AC2F +:1029800057FC5CBA84F6B8A0F155A40BD73D5EBCE9 +:10299000DCB8324CEFA5D388EFF110B8D73CDE9A03 +:1029A0007CCFA264F5427C2DCEE65961FACE3491FB +:1029B000E851E9FDF79616B5F712B2D709BF0DE356 +:1029C0007D282E31904CCF2BE724041DF47C670723 +:1029D0006D00E8A15A022F36127CB3F0D9D16EB245 +:1029E000D577059EC70BF9BD0AFADE3D289D448FB9 +:1029F0003C898723A30D7A44E1193DFE56BE346419 +:102A0000A0CC107E86D3856795DAC67884D57F778B +:102A100023BDFF0B35A1F61E2A1FB2FA2C1BA8FFFF +:102A2000C0EBB6E06685C72380CFD24F12363AB2EC +:102A3000A9B40A8685C7C1F54B6E26FCE9BD254AB7 +:102A4000962740CF6B12FC8FE17BCDD556B1311567 +:102A5000DFF76D00FC7A757781F1458F27BDF6A70A +:102A6000424BA17AC5FF04DA05AA1DAECDD4EEDB38 +:102A7000D87FCCDDC874482AB265111C3369432362 +:102A8000C18ADDE9528869E973D2595ED7DE427C9A +:102A900020FE050A42DDE603EF475551E38AA40311 +:102AA0006192DD2A9FEB3D44B4F69063831E0105DD +:102AB0007269B728B38BE28926F877656BB9DE6354 +:102AC0001182F8D43DBFA30FE35EE2151EC80FD1FB +:102AD0004101DDC55E45A703C913EA15973FE0BA7A +:102AE000904F4B1BB36F45FD7E0BE14B6501F12B06 +:102AF00005EFC7A9F27DC5D32199FA2F4812FE1020 +:102B0000954B62DCB746D275B8C532BB28477ECF3D +:102B100049F49BADCF0603CF396B55A1E50A31C609 +:102B200039F7B1C3B9C0775887A28488FA7BFAE431 +:102B3000CCA1F75FB689E9F8BE677FEF9CE21C1E67 +:102B4000872F94C37C5C1102FEA3D33D010FF06B71 +:102B50005EE1017EAA68DEEC011E014716F089C91C +:102B6000F40404F0AC15B7E545E01F43F803BF3BA0 +:102B7000C6F922C76DE07D313CA3E97D313C2139A6 +:102B8000CEC154AFCBCD1C675C933200A51A7690B2 +:102B9000888A55D4AF33525F45C9B90830DF272E34 +:102BA0001D537498E42DD54E8F20A7B725043712F6 +:102BB000FE136F1BCDCF9529E7589EDBD17C745057 +:102BC0003966BC5B69243CDAE5BD6515FD21A78447 +:102BD00017F0B1360E9A4CF43DD6557B12FAC6C0AA +:102BE000FF2F839EF06A547FC8224A4239178E6FA6 +:102BF000B72E4F2ED16887DC5538E3C3EA800BE54A +:102C0000E562F8BFD8A1E839E88D934AC36054560D +:102C1000F676F17321B46C7C2FD9953D3A197AE29E +:102C20007BEA6F30F414FDA379D0B7BBF627BC77ED +:102C3000BD281A67A5F1B61BAFD9341AD738359E0F +:102C4000E773CB7685F5D5585F8C0574A93C680B86 +:102C500006095EFCAACA745ABC5E0D62D2B608CFE1 +:102C60005ACCC39680C305B97C286EC06F4750F913 +:102C7000D97A9BC7817E03BEB77B53BFF3743EF501 +:102C80005A6B116E832FF47F9F60AC70F76E85FBDB +:102C90006D6D6782FB873A9ADA5FB1B7ABA9DE1B2D +:102CA000EE6BAACF3D38D0040F6A18666A3FE48302 +:102CB00002133CB4F12A53FBE147A698E091CD37CB +:102CC00098DA5F796E8EA9BE34B1B07E298DB73E99 +:102CD0005D150AD9C9D1A2D4D4BE542DB30B62B1AB +:102CE000A8B57D0A79F4D37FCC4F75A615743EBB89 +:102CF000571129A48F16AC95F5C67B2575F7AD84C1 +:102D00008D5B18343F2F15D65618FAF793856F1E32 +:102D100088E8AF576AB12599CABF7B1252212F624A +:102D20008818F283CA7CF540DFB4BCAB7A1C42370A +:102D3000A5042F7E5A09DE437CEC297A3C04BE119F +:102D40009F45D00DBECAFA96756A3040FD7C5B5532 +:102D5000F2E6011BC10773D7422F2F20BD0CBDE542 +:102D60004837F333C66DE6675C6F333F133C667ECE +:102D700026E59BF999EC33F33365BC999FED8BCC39 +:102D8000FCEC30DDCCCF0CCDCCCFCC12333F3BFBB9 +:102D9000CDFCECB2D4CCCFECC022537DB4FC765B3E +:102DA000B5D854FF50DCBE2F34A2436A47D5E5A006 +:102DB000A9D7A3F676D3F7843AC1BE82E8559AA97B +:102DC0000AD5D52A0701FA4FCE6B3FCFAFF92407BA +:102DD0000F131FCE8AD5F599EE0BE5A162EF7D7634 +:102DE000CCCF1F2B0FC3BD663920B94BD2DAB06BE5 +:102DF0004669F099FC91D15ED20FD3BCDA582FE925 +:102E000093E9BDBECAB292DE1045C5BD60472EC76C +:102E10004FB10EFE117ECAA410DBE38BFA29EECE71 +:102E2000ADFA8F9DBF80057AF9C3793696DF65715B +:102E300003B6432E3FA8917279064D860A71830826 +:102E4000B11FF661EC239DD15F01115C198ACADACA +:102E50009B80FF4CE04FF6EC26D168C3C7C98EDAE1 +:102E600051160B37977375FFEC66115E89C17C9222 +:102E7000AACD075D2A54AD4B1AE8D1A9218BFDD804 +:102E8000D75380F445E96AE8EB77F027B57BC45B5C +:102E90005481EF8C71BA6F7DC00D3F80EC03F1451A +:102EA0004C4861BC85B5A8FF94FE6D7D6719DB8B2E +:102EB00017144D03BD03194E0FECAD480F3DA3D0C1 +:102EC000F8FAB6730FBC27B9B5FDAFBC867D21C734 +:102ED00086DA3FB92B96E9D5AFC3867618D78FED42 +:102EE000F76EAF6F39F036DA5F6ABC76BB67D1CF69 +:102EF000A8DF6645F8371212EFEA7CC974483F3103 +:102F0000534DF4D4806F71B3EADB131D6EEDA0FD59 +:102F10000EDF9F7EFD4F570256F6A7B817137EA708 +:102F20008B1B07035FA2FF83A82F7312FD6968271D +:102F30003B6BBD9220144592FEF447FFA236F197F9 +:102F4000F81CD0E9FF6207ED31C8F57E4B439607C8 +:102F50007CB4360C663EBAE4B84EDA255D2E468760 +:102F600082B8CE3341FF790E8747257A1628F2BB07 +:102F7000879366CFAA24BC6FB614A5855513DE4F80 +:102F8000A3BFB2F8E22E19C0DBA6E3ED6CAFD3DD30 +:102F90009D13E99F45E35D83EFC31FFE15F997D9A4 +:102FA000781EDE06F839E1E2F58BC322ED7273B5C7 +:102FB00012DC48F56FEA745E6FA37698974ED1AE37 +:102FC0009AF0BB66E48A0D68F76BCDC9786F169EE0 +:102FD000BE6BB2C10FC1FA3EF32E2558930DBFCA86 +:102FE000C3723F4F1465EDA276AF79B57AE0FFB7B3 +:102FF000B87F0CCAB6F0341EF42E7D67CFB20E9E99 +:103000007B008DB83CF9EF4D9A03FD4F9928EDCE2A +:10301000CD3ADDA689229EA7C6BA8926FCC90A6ACE +:10302000379DFEE2F59870F7077E33007B5BE7F58E +:103030004CD1C0E52CE1E2F5D4DBD51D7E761BB585 +:10304000996269CEB2AB98A7346FB399FEFF0EB9FF +:10305000F966DC5B8714D0FD0ED263E0F79AF69731 +:1030600025C79315494F9AB79FEBF3360F53EBFCE7 +:10307000FC19DB5ECA9FD5D5E39FCD1F528C891901 +:10308000E4AFFF44AA42F1D09944914AE36CE8AA24 +:1030900006B19E1AA7DE61DD45E36C207FC2817117 +:1030A000FB8A3B9EA6FAF1646FEF91FA352140F05E +:1030B000249F2AEE6139685CBE909EBF9E4FF5D476 +:1030C000FE956A919047F02B5E9BA786E470DC39F1 +:1030D000ED4012959348EF87A9F555E9F78D857F67 +:1030E00030BE13D991083B715577334C13A113F8B7 +:1030F00074B54EEF093966BB330976C768DF86DDE4 +:1031000021FDAA82BE710375FBD357F485FD79B901 +:103110006AAFF88CEC8B6187C608B9DEB8981DB22F +:10312000DA0B5206B23FEBB6637ECCC1FA04F476FA +:10313000691D2747CC97D2210AF3C94D86C742E3C0 +:103140007FF3A01A047DACBEF070D06FF18B0ACB78 +:10315000E9D503B5AC81C48753B6C6F9909B8611F7 +:10316000B94982FAFFB48A10E945F3B7CA297C3419 +:1031700017BEA872317CA42A9DCB63556E2E4F5486 +:10318000F5E6FA53551E86CB0716F5027E73567D7B +:1031900065859FEF167EF68F96D07A17FC5A92B00F +:1031A00058C236A70B4AF8AECEF5963882EF0A2AF7 +:1031B0001ED8C585BB822BE308AFD23A9F3D9EE067 +:1031C000259DDB8D8947FB071496FAF907FDF51855 +:1031D000EEA9773FBD6EA2681D6FF93985D7C9EF9B +:1031E0000FF20D46FF5F56E5335E47AB7C8C97AF21 +:1031F000AEA93E85BE77BC6A3CC3770D2C1A81719F +:10320000FBC457EC474CDCDE64859F31CEA7F8C089 +:10321000E7513E110C12BDD6DAA45D594B76057A02 +:103220006074FF29EB6F15D0FB5A21DEBFB6DDDCE1 +:1032300071F05727E517B3FF7AFDF782FD5743FE7C +:103240002F358FDCA2E15426F5773220E9D3B2EB9B +:103250001D865BAC441F1AF1BE5DA5A582FC83965A +:10326000736FCBE7D48EFDD4DDB2DD629B6CB77893 +:10327000F7AFDBF9002BA25944ACB78E131F85239F +:10328000027EFA17E95A847C1D6F17FAE623E8C913 +:103290007FB77836B29C6A9F3D0F3DBADCC57AE6AF +:1032A000942DF4C5C3D0B39DC9AE72BD3F6E0AC99B +:1032B00059855D682C7742EB07F878ACE0F800FAA6 +:1032C00073F792CF218F3D773CD4F597EED6FEB6BB +:1032D0003CFDFB96E7DDA80FF2FCDFB6637DC74738 +:1032E000082ADBB92216787D76EF7399185F2F557F +:1032F000F8559A67737FF3C7CC3F52FF4F906E41EA +:103300001CE3059BE7D45EE0B39EF0A1EF3C716F38 +:10331000F940E8B779BF5BD817EF07065A98AE4F68 +:103320003DB793ED3FC998670CE9A9FE6B5E5A96CD +:1033300041EDAF58D764E948A577935283B274FB47 +:10334000CEB7ABA9BF5C97C50F7F74C54037BF3FF1 +:1033500030B461A302BDFEFDE31D31CF72D67C55B2 +:10336000D0515CDC6F782AEB8396621E572D8F6BF1 +:1033700077DDD4776E14F04BC82301BEC5760FDB22 +:10338000291AB60DFCDED56D03DEDF6309B0FD0939 +:10339000CC917ECBC9A2C0EF31FE726A1F20B8DC8F +:1033A000DBD0741BD597277715883B1C092E998194 +:1033B0007A9ADE2ED0A762D703851D093E3942785E +:1033C00014EABF64F79942B66F9DC9F7C6F776D580 +:1033D000A4DD00FB96533048A5FA2235C4FD894A86 +:1033E000D95F65DD4EA7E0F5BC68A792224CAE1B05 +:1033F000FD7266047F2C8DBFC9B6D2F7DA937D04C7 +:10340000BE6BB30319FEF8567BFA9AB7680BEB2331 +:10341000D7FDC5F8CEE78417FCADCBB57F768B7FA3 +:1034200021E3932E5C81A1ADDFED6C092FC43848F8 +:10343000DA5D01FACE6657C30C6E47F06FB95F6D67 +:103440000FE65FA64A544F95F6BA06FDBAA6668106 +:103450005F97DBFF4371FF60BFABD292E871E4B5C9 +:10346000FA2DD3536A5E6C247E6DE8A0EDC7F88C0C +:10347000B8A4B07ADCD0E3810EBE97F1BCCC49761B +:10348000D5C2F6F415C0861F7CDE0F735E9E3DDD4F +:10349000D9C1F717A6E365B677EB7186F37AF5EC39 +:1034A00040935EAD49B00B2F3DAF59E3E0B884388F +:1034B0006029ABA7F5C7487CC2D2FABD2509033BFA +:1034C00040DFD708D126BDF6D17CD688B661B203DD +:1034D0001ACDEB51E79A558DE77DC3CB4979D09F43 +:1034E000C297E0461CC022B4087B17FD1DE2D70935 +:1034F000F06BB488135A84DDF489643BE6AD886FC1 +:103500007799E30E3F6EB627FB1F8F1CF788960F47 +:10351000E2E052113D3AA0BCD8B85ED4C7F5278C82 +:103520008BCA79438AFE01FC467EEDB2627C23ADF4 +:1035300093B3BC5D196F6B2EF53BEA6B8B19EFEF04 +:10354000634DF0E5E2FF3385166A90E3AFEC1C179C +:10355000AC83EDA771D42DCC0962BEEFB18B801383 +:10356000EB982976F66BEB1202097D51AFB84288D1 +:1035700027BD606B9821D739C2B5D90BF97DE3110E +:10358000C8FF0D2D7605F1A98E0EF105FC25A126AB +:1035900089CDA911DF6FEFE2B885EACC5C8FB86204 +:1035A000DD50FDF90C3B3FAFB109B67B8119B18C01 +:1035B000D79A64FF6BFDA97E4DB58C677E2082ABE8 +:1035C000BAA2FE0E95EDC070CBC6CD0F621D333989 +:1035D0009DEDC69AE4706625DA2FECEB09903CEC81 +:1035E000F987CAF6608DD797D12E1E7A50C605D7B7 +:1035F0004CF665C4A6A24CB360BC1D49CFF3F36C76 +:103600006A47E54736D9EE439D6F44E90CE8DB870E +:10361000E7F510D03F57E7168CCC65FF47C63BAFA8 +:10362000952C10336E7E80E3AD0F6B6A50CD065D36 +:103630007E736F4F826F98A3BA1077BBB62486E370 +:10364000A1D76A7A3C749A390E7B75AE6F642EF1FD +:10365000BF3CD4A7DBE108399E71738F9F433F7C49 +:103660002A645CFAD769DA38B4137BBDDC6E2F3973 +:103670002B3FC04E38DD03D87F9E67AC1BC3734120 +:10368000DF7DCD4EF64B2F260F42789C7DE9FB0F58 +:103690005A4408F2DC05FC4961B90DC06F0B846225 +:1036A000580EC64F71727CBD25DEC2FB0C8F11BF58 +:1036B00060DF02BBE53E03294AE6DF83FB3AB35DE8 +:1036C0009AADEBB19AE9B1FC5ECD4E5BD0023E2BD8 +:1036D000C16D5BF0DE8B316C3FCBF4386FD9F3FDFD +:1036E000580EF6D87DD92BD0EF3E07F3B92CD19DDB +:1036F000C4F5FF962250FF821E772E8B0DF7443CB7 +:10370000BB5B7B6D3EE84172C771F932BB7C7E28A2 +:1037100058C0FB1A82FC95B851040B1FEF4F04C828 +:10372000AFD9EC91FC035E5A4DE78DC057233CC0E6 +:103730006771BB8C971FA2B98CF11DF27766BC94A0 +:1037400029E3336EA6FACF16C7711CF55051FD5907 +:10375000F80187D2559EF7A4A1EE1D42F564731BB4 +:10376000EE21B872E1A76F0CA1A715351F66ED75A4 +:10377000B7D27DE6B2F20982E460E6A23B2689C4B4 +:103780008BCFD799650EAC115BE7B7B063B12661FB +:10379000D2EB6B727D3590C350AEB612E3AFCC2145 +:1037A000FF99E4E894BDE151C4498EBAB5BB517F9D +:1037B000FA8F5F6EC173616DEEC9F2E16C2C449CAF +:1037C000A5CC22E344A3F3B4DFE6B29D4D64FE55DD +:1037D000861CCCBFB89C06A917EFB83C7B70AC6EBA +:1037E000F31E85FA298DADABE0520D0E80BD3AAEC9 +:1037F0008413956E4C5F0DF3EA842B9C08FE6816CB +:10380000E9BF956E8D1EA7DC4F2CC51FBCEE0CD9F1 +:1038100087135E8B48F53EECC2737B6BFBEC563E28 +:10382000D277988F22FE9359BF44FB6D7D06DE430D +:10383000742F4DDEFB9BE1D917D22F1A36C67321A8 +:103840003EFA3C290A27629E1C57E43C3921A4FE1B +:103850000A6C8DD1D7FF128F537FECC078A4E9F3A7 +:10386000E894A2B7DBE690ED48F6E0CF94FE41CABB +:10387000DD8336CF5AB9AF66657D599A22E152474A +:10388000BA0BFE5647356089855C56099E2F841B0E +:10389000CFCBE33B32F97D43AF892221A0D74A77D2 +:1038A000646C947E9DBE0EC600A8FDA2A7647F80B6 +:1038B000A1FF8F3D99A9F72FE753345FA3E9F07E6D +:1038C000AE8C5BD5240CEEF0CFE295BDD33F5E0706 +:1038D00015F4A04DCEEB4082B423E4B7A44FEE8F95 +:1038E000FD06BBE9BBA712ECB37DF1D877303F37BB +:1038F000BEF769AE5C477689E27B47B5F925F84BA0 +:10390000E271C17A221A8FA3788FF07DF2C9F37C1D +:103910005625DF49900CF97233FD840DFCF9D06E09 +:10392000F0F1D64CD2EBA5A055D7563AEEF16A99F4 +:10393000B023A7F47DA33DC904E7C0DF92F6C3809E +:103940000D7E44CBE9B20FE767629F2A2D4FAE0F81 +:103950006A6212078824945941E8816AA22BEAC955 +:103960000EF27EDCB1AAF1F71FB6B58EE78B2A9F67 +:103970008F4CD07978FE5AAF13F373C13AAF734EC0 +:10398000043F6AB6E61E7413DD4F6CB562274BD454 +:103990005883BF19968AE76A2820B8DE097A9F887B +:1039A000DFFF06DACD5F973C508DD04F0BD68EF3FC +:1039B000CD8BE043BFAD66BEF40F99E12BF69A6163 +:1039C000377832E8C7BFE70D9BE1DC8366F8B9FCC6 +:1039D00066F507D8A7784BD0A9A06C517F807E0FE1 +:1039E000AA41AC33BADC51347522C147D6CDF5803B +:1039F000CD0BDE5B3618FC3BB9FBAE3DE5F4DE914A +:103A000076160FD657C745E8FD89C48FF975F7D9E3 +:103A1000AD6E8CD72CE77B2CBADC3E29E37A0B8386 +:103A2000E6FA0BF543B51E4712BD23E52A9AFFD4EB +:103A3000EF753E42AC6CE9D4FBE1FF944C2081274A +:103A4000FC8686EEB38BF8CBE927C072634D14E198 +:103A500074C2AFE9AE048EA70C5B3A467C46DF2BFE +:103A6000B7BA0663BF7D8E5371617FDB889337EDF4 +:103A7000CCA8803DDDECB278904CE1CAF7D767E680 +:103A8000613D21422E0FE2F477AEC43ABEC49FC816 +:103A9000F45928821C679FB3DCD1AA1FE9FF79ABD8 +:103AA000A3F05913514FE32859676EBF68D30F8EA7 +:103AB00048D858970EABDBA062BC37EB78AB0199C6 +:103AC00037304C8F3F1C4653B2377FEB56549C87A0 +:103AD000F66B46CB7AAB53B7B33E5EE795C7DBDDFB +:103AE000ACCFAC6FADE4FD1A9A87B00F0713E6FFB9 +:103AF0001CFAEE8C53B81C9C47A231FC458A5C171B +:103B0000F23E04B53FB34E61BB5E9E22E1F2C79523 +:103B10002062BAE508C2027E42C65DCB747A404E8E +:103B20007C11E301BF2261516BC4BBC3BCFEADF08D +:103B30000B0FFC00417CF499F6BDC3F623B0B30132 +:103B400025F4B017FE9EF93B957B7F7044C2E7E3F6 +:103B5000C5C4BA6AFE7E90E9A8DA850F7A5CBD33E7 +:103B600096FD763200B1B0EF36DDBF16AB82ED6167 +:103B7000AFD6C05E51B942F7C303F7497BB526D92A +:103B8000D7D385FAFB323CA0C30D8ABEBE855F9FAA +:103B90000CFF7A3FF7DBACB85C1B93D15E0462523A +:103BA000D9BF96EB847FA86CEF9AC97FC7FEFC1A39 +:103BB0006F280C7CD63C90CDFEFA0B86DDBB3746D9 +:103BC000FAF317FADDEC5F89FBA5FFF891E0BEC5BB +:103BD0009EEEDA863C92F3B96A116F2ECD5BE6CB8E +:103BE000C077E74DB15BC00F517279FB1C9BF53C70 +:103BF00098661A2FE2EF8795A27A4B841FFC4C9EA1 +:103C0000B40F830B7C5BF4761EB49B67798BE93031 +:103C1000CF225C58CF6F3EA70A2BC19B6B1DC1659D +:103C2000F4CABCAEBE9E8B73F09E8C371DF24A7DEB +:103C30001F97277C41E87FFDBB2FE4594CA5182B2B +:103C4000E32C8763A41CCE1445851CEF770B53FE31 +:103C50008551BE9227EDDE3C7B83199F4F5E66BE89 +:103C600090CD732D837C8F957EC7E15B14B6E734CE +:103C70009E9E2E8207FF2E86E38587757B64D097F4 +:103C8000E487F3220CBD95ACCBCB9ABB83DB628877 +:103C9000DEF7D9486EC037921BE4F910DFD92F5CEC +:103CA00033238DF97E83CE57716F02F36DB8C52231 +:103CB000E97C6F06D399DA8BBFE3BD716EE9CF5F04 +:103CC000E63A8CF8FE37F03D7A3D66F05B58838328 +:103CD000FED97E4CF9734FEF0990FC2FFAC303898C +:103CE00082DA1DB5D6A679E8FDB2CD2B127D541E21 +:103CF000B106125DD4FFD1A03A3ED806BD3B0F52AB +:103D0000F4F5902F11797415BA1E3FF6E47FACBC20 +:103D10009DF0FC4611CDD08F15BBBE5B793B8DAFBE +:103D2000DEE76C863E3D626D2C84DE5D581CEFAF95 +:103D3000F660FE9AE3F28B9E7820CDCDF40E645AA5 +:103D4000D279FE67E2BD8A4D360FD67515EFAA1EF1 +:103D500037E6BD685E09FCA2DFAF0C7D6607FD5D3E +:103D600016D1DC69781BF5A291F57CE5AE5F7FA5E5 +:103D700026A23CFA11D6179551FB0125FA7E49F48B +:103D8000BE40C2A084D42F10F0D6F7A3893E9C97E2 +:103D90001020BC7AB0B8C83872CDB6870634C16F6F +:103DA000D8F45AA292D3BA1F60ECA3B484E63E863C +:103DB000B8EAC5E6E5A9A838B0A1C7DC7B1599B477 +:103DC0005827CB325B3811FE7ED9061BEB91B2A788 +:103DD0001FDFF230E4ED4387A7871BF0193BF44166 +:103DE00099E26B5658BF8B4465702BBF4A9FFEBC4F +:103DF000F011F8D719AA9840FC5AF4EC59D9DE27EB +:103E00009A63A87DE9CEA642AC0FCAB478BFB30DC1 +:103E10007E8D09BD646F8C6F835FA1A6428E536D4A +:103E2000FB96F971749F223A645FF87EC986CFEDE4 +:103E300042AE0F9A539225BD60EF2A436AB13DE925 +:103E4000C2F6F4FD49CFE771BD0BEB954BF1F124C0 +:103E500068C1F29E2090C758F291233801FCDDB171 +:103E60002411F94F5F5AFD52EED7AF48839F576236 +:103E70000BA4B9B894CF4B1EFD19CBE302C59FE646 +:103E8000E2BC2DD2AFF93CDE0C8CF3E675D7F238EC +:103E9000E70B8DE5B164BD5A14A4F2AC558CDFD9A3 +:103EA000C6BC796890D4770E71CB00CC93B3F4255F +:103EB000D8F12FF5757DE06DB99E7688294991FB83 +:103EC000432583A45E0C88E021D881CA061BC7293C +:103ED000D4B7CE16E23BB7665BFDC8DFA0F107742E +:103EE0007A293FC8F58B1B790C95F88BECE998B7CC +:103EF000C67568CCC1F75BEC3751BF5F639DE83195 +:103F0000BDC774FB72A32356B982CAB4B6F3BEEA26 +:103F1000CFCF7FF1B68890A7CAAD5FB23C89745508 +:103F200024A54B18FB11AE39F1FE24A2DBD7EF7E9E +:103F30006647FC3B906A113D806FC3E70C0B4F7BDB +:103F400037DA1BDFAFDCEB10E1C879BBE9F3A87906 +:103F50006DAE17C2CFF4AC14496ED8EF2FEDCD85FE +:103F60002FA01FEA7733F5339FFCAFB0C9BF6A2E8D +:103F70007C04FA64AFDDC5F107F23FC31172737EB2 +:103F8000BF53DFE75BA0EB83683A44EB87FBA2F407 +:103F900083F1BE58D7F6FE52AB5E08303DCB6C22A3 +:103FA000003FA3EC4307DB8FB2A7E57C14A44F7B53 +:103FB000D0FC38BEFDE5F76FC07A36644B9DC0BDBE +:103FC0009AF56FC9339FF3B8E612FD633CD0BFDFAB +:103FD000DAB1FE4D1F239A1D84FFF1D55E3BE4FE4E +:103FE00082794CCFDB9CC7AB15D66FFF55BD4BF428 +:103FF000E6FCC04BCDD70517D1BB7551743D2B7274 +:1040000092905E2D5CC55D78FF208ABE065DA3F5AB +:10401000E8B441EE36F528FD7B5F44D051884696E2 +:10402000E36F482F625FAD62D3776CD788ACCDC8A1 +:1040300027AF087EC5F00AD835865F9A8678E58571 +:10404000E336D333BAFE4EC818FD5FF4471BFB05B9 +:104050006575326F91DEE3754725E2F5DCBAB63E51 +:104060003335120E46C1A1A8F6BE28B828AABD163F +:1040700005FB4DEDCBF6BECCEB2CC2DBD4CEB1F4C0 +:104080006A5E875CE85704791C95BBBEB207201FA7 +:104090009D9AEDD08BB665229040EF37BFA8B2DF76 +:1040A0007BDADD9C083F65458CF4E34EBB7438D960 +:1040B00080C5EC62C2E37460800B7902CD3132DEE0 +:1040C00072BAA839313962DDDE54A726BAA97D63F8 +:1040D000508C6F3BCFA586E753A3B858BDF4E7C615 +:1040E000A9DFEF90F99F5681FCD8C6EA6F77209E32 +:1040F0007498D64FF05FE6555F9F88FD97D375DDC6 +:10410000AE998E75E0ABAA9069D63E3BF220E64AA6 +:10411000568A2322F0E0081A9F9A9057FF02D6573A +:104120002428D8FF9CB73ACABF11454961ACA7D72C +:1041300044E72B04EDF06F16909D853E2A5967AE3B +:104140005F54779CE7CBA2A8F9A2E971E3E8F9D222 +:1041500075B09EB7E0155E3D7F92F3F44E1F545943 +:10416000BE5A96DBC4CA5499278BFC92963A997F23 +:10417000D3B257C222A0E7F5E8F3D6A0DB09CCA75B +:104180005E17F75B4EECFEF7C1BF84FCECF97800DC +:10419000F6894FECF9B0E70B809FFB6BD6C7E2C204 +:1041A000F663F67D378BF1DAE710C0EBF4BE57B259 +:1041B000E06F9C7EDEC1F905A79739D85F0FEC4B05 +:1041C000E0B8C5E9CED21FAE79F1DB018D6C8F97D7 +:1041D000331F270EB64BBFAAEE3FD83EB6D439DC0C +:1041E0001847E5BE389E5795CFC7F0BEDAE917BF2E +:1041F0001D1C198FFBAF8EC7D8573F9D20A63F03CC +:10420000F9D5FDFFCA17863E5E8DF5F2AE97EC73C9 +:104210009127F2A7FF3300FAF5F4332FB1FE3D6585 +:104220006B7C14B1CDE97B321EB10D455C8F3ED65F +:104230005188AFF6CCB811F3E742BA483A9C263A17 +:10424000605C449712F8E517A347E5BF2C3DBE9A82 +:1042500025F5DC10817D9F56BA283EF93C81E35557 +:10426000347EF97CDFB703A0872E35DE7BFF1F1B72 +:10427000EF53186FFB7FC5F14A79CF1DEC66FCA2A6 +:10428000E5FE42B97EEEE70CEF48F030BE9739DF2D +:104290005FFB971DFFFF0CBF8FFECB8EF752FC7E9E +:1042A00055E777820BFBA0A75FFC3F59E2478CDB09 +:1042B00039E45F755EFFF3711BFE7C81EA39E8A586 +:1042C000F6AF89D0BB9E6CF64ADAF447060D518CE6 +:1042D000B838AFA7C6E02F37DA0F5C8E734C01F207 +:1042E00027B08EA9891F78E02D825F213F41E57DAF +:1042F00059194F7A25DD1B94F15DBF403CABE0AF0F +:1043000073197EDDFB9303C82B2954653CE6E56AEF +:10431000CFA6061AC7CBC91637CE958DED34F7F068 +:104320004EAA7775545D589FD574CA75BA23F01B91 +:104330001B6F5E675D1DB54EFAA9DB5C3F5E3C936B +:104340008AFDBAF1393681F33685681FB1AE4C1952 +:1043500022CFF7FC54D42E77C5FF783ACDD5E94467 +:1043600074E17D9B402755CF7333D34D806EA9A058 +:104370004B2EFBEF01E139F016C156DDBF12FAFEFC +:1043800063A133610BD6D10E51100E127CD66DE5B0 +:10439000F3935641EB61394E5E4747D34DE8EB6AE4 +:1043A000ABCE82B19DC68441673CEF926E7A9FC7C7 +:1043B0001D4DE71F4FD7FD9D9680AEE9099E20E475 +:1043C000A2D3B3A988B3D6109D15A5959E069DA22C +:1043D000E99E8FCDF541ADF4EE64F55A31CF46EA52 +:1043E000FEFC586BB2843B35A8F25C5E90DB8FF923 +:1043F000DA63853F323A3E99F343857E6E42D5F7C4 +:10440000C39161C778D0FA1479B693ADDA92219C42 +:104410005FEF120558B7168810E2B74ADD2BDF614F +:104420007D84F32245BCAF59FF01E05E382F86FC46 +:104430008E75D613A6F36E51E72526E5EF1C0D7E8B +:10444000CD594ACF10C772B9EB311F8BEF77B8C186 +:10445000BF4ED606AEA7B596AB7A2876AB430CC74F +:10446000CE234F3F03ED5E19CDED970897928C74E4 +:10447000BB109F778C77C97C355ABC7E03D8BE3C75 +:10448000C15D23E32602F2D41D65577C5FB64F1F42 +:104490004BDF43BE9BD0D85F8EEDCE9120D1552906 +:1044A000E2FDF72EDD645E44F30A07AF778AEFEA98 +:1044B000DC137A694281396EFDC510B9AF69945336 +:1044C000F3DD729FC2E249C777E62CEFC3EB2F35CD +:1044D000B6A87C37E8B8238EE5BC78E54D1307D144 +:1044E000F78B77A47880E6B1493B07CBF6337EF6AD +:1044F0001E3DD7B6C6F0F39FE76B8F0F419E81E25A +:104500009EB59B1ECCB9F6657B3A75A185269F4466 +:10451000DC715260E71BD8E79C344DE5F69384CC00 +:104520002B15CBE378DF7C62E02B6B3A7D6F222D7D +:104530006A50DF14E3CABA85F02FD6E3CD7FD0E707 +:10454000A11A2BB467E28157E79E5DE9F94421F394 +:104550009BA3E7ED71BD7D97311E772AE8A3C4B810 +:10456000701ED6688FEFE0BB5FE9F4785E2F0D9880 +:10457000E8CA71F179AB1C4DDD1251DAC2BDA8EC6D +:1045800033AC601FE46D425751B816DFBD4D151BAB +:1045900019DFE6628EB327F476830F9AD0CF77AE19 +:1045A000E9C1FB394DA305CB4FD37DD906BF393FB8 +:1045B000C958CF358DF6D4237FAB79B4D3B3D1832B +:1045C000FC9650187194436BE57E4D979A7077E88E +:1045D000D966AFDC07F97C69AE1B7272F303531323 +:1045E000A13FE7AE51C30EC8FB6A73DE9270793803 +:1045F0000F7C6EED683BD6AFF3E27D768CEB4CBE64 +:10460000F611F8659C73EC0B9C708EA7B6F875AC30 +:10461000FBD4449ACF987F567722D6D5D1794F953F +:104620007A7E9301FF3A4DFB0CDF9B93E4DE01F9A8 +:10463000F87469378EAB76CBD7CF575AC3DD419F1D +:1046400047692E607E3E3844CADF8476AE9EF12CE8 +:10465000BF3102E36AB2B97A429E9B56C45840A762 +:1046600009CBA41CDF6D95F32BE8735B02F4FEB35A +:10467000789FBE3BB3DA5AB481FAE9E414D6847663 +:10468000B4CE1DA63D0FFE4C0C541FC2FA7AAE6E7E +:10469000AFE6AE96E7C1BA8C917C15D686B129F407 +:1046A000FCC8E6EC81C87337E466FEB082BF0F89B0 +:1046B000E0FF84025F617BFACE048BBB057A78DE73 +:1046C00034E5A56E520E7E18C2EBF93A9EE72DA492 +:1046D000271CC93807D82061E4AB426FD43EE4738D +:1046E00046ACDBED6217D7DBE7C97CD42EF670351C +:1046F000E75FDD225CCB08DE427E84D526C4D62A65 +:1047000027974F5691BEEB21C4F6AA74867754B909 +:10471000B90C55F5E6E7CF547918DE5595CFF09EE4 +:104720002A1FC37BABC673F97C55113F8FD63F73ED +:10473000E3E7B33E71F5245E0FBD506E66B9092FF5 +:10474000E81FA770DD85F34742EABBE4DE52FF08AD +:104750005D1F75ED23EF03E8962FF9615B35DAC233 +:10476000E737AD8D1990BB71EA89A79F43BCA3249D +:104770009EF3B25A4423CF931661E173D9D03F0E12 +:1047800092BB2E778ECF8ECC3BBFB14411D608F9A9 +:10479000BAC91F23AC11F669F6D264133C73E93B26 +:1047A0007FEE40DFBFB1AB96974F781CBAF38BF525 +:1047B0007FA5E78FDD79AC873CA7FBFD86C8B84BAA +:1047C0008B6896B0D5C9FBF18FDD9E9196A2DFD3A1 +:1047D000007E19E7A4BBD89B8F3E8179B842F52CA7 +:1047E00023F823F087E8F989CE9FE215DD56FE0213 +:1047F000F3DAE7F428F49D43B7F72BCCA7F68FE95B +:10480000FB51179CAB4E97F6EB53D8AF6469CF0AB8 +:10481000A047C3D26E7DFAABB4C05DA8BF25D183DB +:10482000130DDAAA0E810504AFF6DA3D2AE27A7595 +:1048300082EF5D201A4BBF226033DBB1C64EC988C0 +:104840005B1AE79EE3F2824E3E77451D613F664E5E +:10485000EFFD22037AA9567161BF06E7349DEDA0F2 +:10486000DF14DE1F451ED034B29737E5AB3C3F7FE7 +:104870003FC4CAE559D873A26B8CF0707C66DE6ABF +:104880006A0FFD58EBB5CF8FD0BF73F4E7737B5B36 +:10489000B8349E97E17BD83F5CE59D0EF9E888FA35 +:1048A0001C9403A703BF8EF185562562FF777EBE59 +:1048B00055EF5FF67B169392E07B7A77B5DF9CC36A +:1048C000E7ADD86E19FDCCE93D706557D8EBD5A39F +:1048D000411D5163F3A4A752BBCAF3DF71497FC4E2 +:1048E00029F3B3CB2E62378C38DD11FC29CF3DF292 +:1048F0007817ED786A07CE3D2CFAD8C1F66BD11542 +:10490000D22E899CE0E0A91CD034C7C5C73E75B241 +:10491000FE2EC2E724CE2521DEBFEB333BF24369F6 +:10492000DAF8933200AB4DC8338D8ECF1ED8F171BB +:10493000629B71F15DEAE5C5C595EF1361178CF1D6 +:104940008C7BF16C1AFCAC4AE51CEF3355BEB822E7 +:10495000ADADFCB0E8B8F8F9F8B958FD15CED757A9 +:10496000DE71A4CDF879741CF0F1FCE8FD88F80242 +:10497000E889B307D520F6D35B823D92441BFD1B2B +:10498000F1F3CAB5F4520AE6A53B09FB61A72FE291 +:10499000971FC997F6FDA41E6F3FBD5DE5F5D2E9EF +:1049A000ED0941F8A715DBEFAFC73E65C52685DDEC +:1049B000F372D1C0F4223A0A67A41D43BE5B0A9C7D +:1049C0006B7712F495815FE953097EC8D5C290E2F6 +:1049D000DB4C78B438DD49ED23F03800B96A8F3C00 +:1049E000C0D060A6AB8EF7F3BA1E34DA2DACBB9FF5 +:1049F000E3D2D4EE14FB3B7F88139C27289ADF0078 +:104A00007EC7D7E57AB0AFB830B4B382F33BB6C750 +:104A1000B9108738A6E7391BDF69D0FB6BC897FE52 +:104A2000C9717DFFEEF80E79DE1C78623E1D53CC15 +:104A3000F982EFEBEFBD9F2FF7CFEEC05EE2A0D67D +:104A4000F60B434D89DDA9FD977BDFE1B2516FBFC6 +:104A500030BE6100ECEE97BBE2783FFECB5D8F1479 +:104A600022CE7C32343A15F26F7CFF54BE8DDB9F30 +:104A70005CA78E07BD4450E6D99483AEB99178A661 +:104A80006C086447CE33996F747CD7B389969C5673 +:104A90003E963BFD4E9CF7ACDC754B11E4B8DE2630 +:104AA000E969DF35398063CC95755E01F9E5799662 +:104AB000C1ED575922DA396C1EF68B6D7B8B7D6800 +:104AC0006FC4A117EFB6F179C15957B8AFBF11F351 +:104AD000F0351BF361711FF7F59C8FD4A072FEF2C5 +:104AE000E26C1186FFB1E4B6840DD80F33F09D95CA +:104AF0002BE77BD92A45F8685C6541790F4747E287 +:104B00007B00394AE98D83903FD9941DBCBB672A4D +:104B10009FDF0DE3FE1623CF94E6714F9C73EC30BC +:104B2000B41D8FFBC119856CEF0ED945007A21F0B9 +:104B30008CCCC329EB2AF3A31F86DCA3BF76E19EAE +:104B40002934DE133A5FCBA6847B222FA3EC990C89 +:104B5000CECB386197FBA5788EFDE2B281F47E3C26 +:104B6000DFCFA119EF2747C851D91C8F1BEDD47691 +:104B70001EB7371EF8BA4EB1DFBA3B41C06FB53C25 +:104B800097A0E757C5701EB9F15EBFA152EE8C7BAE +:104B90003FC40D321FF3419BCC577D707306DF7706 +:104BA00061B47FD0A6CD80FF8471C05F5F68AFED38 +:104BB000897D1703DF8589B58CE7095DCE17C6D6D9 +:104BC000CABC70FD1C31DA036ED2F3D89BB73938FA +:104BD0007FE55846C337C0F7D8B63EC88101BDE768 +:104BE000EFE57AF21F899F8B9E7484517F749B8CB2 +:104BF0005B1FB505BF811E3EBA3E85CF471D6D1FA9 +:104C00001CCCF9018ACB02FFECA8A2C33617FB9596 +:104C10005DEC0453FBD4586141FECEF8296B67214B +:104C2000BFA1659303E2298E6D79288DD735C29D8A +:104C3000C47936075501BE1D7BF23FFA44FA2F4670 +:104C4000B9689339EFAE295B98EEC9B97AA89C97F9 +:104C500057EBF4BD66A8B453E571A107BBF2F82485 +:104C6000BD893FBCBEA3199AC0F9134FF750A037B6 +:104C70001E16C19F7F9CC7AB6C37F2E6CB9ED9F660 +:104C800006F66B8F594403FC0FE5CEAD3FC77D1B85 +:104C9000A9BF49623B24C4261EDF51973CA74A1393 +:104CA00096C7BFB08384174DDDDA13703DD91C85DC +:104CB000E6D7228BC2FD2FDAD39FF3ED881F16DED5 +:104CC00027DBA9EAF8904F09FA6D91F9CA13DA05C2 +:104CD000B7C0DF6B5EDF4DE0FCFA3875DD00F0EF4A +:104CE000CCA6380BE4A9FCAEE149C341B737550166 +:104CF000FFE38CD5D321328E104DAFE83CF0E0506D +:104D0000A99FCA700F0ECDABD23DEBF9BE9052C831 +:104D100025E8F2A4C2FBD8A52B873FC472FA864DC2 +:104D2000F4A07E4F84EE4F8CE4CF3D43A55F70FE30 +:104D30003B760FB72FA5F6F2FDD71219CF2D36CE41 +:104D40006B89E6EB65BFFFA47A59EF9F1F7F88FC54 +:104D5000820117D2E18C68F8F9C7F4FDAFB7C7F04C +:104D60007A9056007C8EEDB82D341FE33EFE740C15 +:104D7000EBAFE3C9524F7C49FA34D00B785CFD5B52 +:104D800096D3B7A7F279BF0541F3778D7E7F3B5469 +:104D9000EAF1F2144F12D69DE56F4A7D48FCBA86BF +:104DA000DF7FD3C6EF478FA3427FEFFC3C7D3A8E77 +:104DB000E5E27847C98FE33B7AB17D6A4A76099686 +:104DC0009B6D36596F0B65C10F3EFE742F6F4DC43E +:104DD000778F2787B25C11CF9B6CC19543A43E6D42 +:104DE000C6BA588449D50E467E91603D6FBC57EADD +:104DF0005CDD003F05F9BD8307721976B4BB304F07 +:104E000077423BB99EFC529F779CB39AA6E793B337 +:104E1000DF13B2438F6BBA7F58B63D3ACF57D6D720 +:104E20001BEFD3BC4B35F28A2DC037644FE7788334 +:104E3000703F43F8962EBF6521F2C74BFDF7DD08A2 +:104E4000FFA9D42AC6DB09AF2645653C9A62C4ECAB +:104E500029F02323FB89F0DFDE6AED47E0DEB6327E +:104E6000FC41F3E0BDA16E293FB0A4F4BDB2E5CA98 +:104E70006A7CDFD02F1C284C6BA513F25A91DFD32C +:104E8000345AAFBFC8B89B6CB23E7ADC063E478747 +:104E9000CABCA0A66CF76F47802F7F51F97CD799C9 +:104EA000EF7393DAB5E1A7B5DA7B7B6B9E2DE1FF5B +:104EB0000D7C6BFACEF3BABE2B25FC8067CF75E66E +:104EC000BCF2DE9BCC70DFED66386797191E506729 +:104ED000863D07CCF021BD5FACB3710E19EB6C942D +:104EE0005867BB1D729D0D18EB6C945867E339D65B +:104EF000D980B1CE068C75366083DE586F03C67AD2 +:104F00001BF5BD86497D2E7CE134E46B5658649ECA +:104F10002FF1C3C7E79866D84DE7524EBF28CFA5FB +:104F2000903C487DBF309EE7C9C36831147649CEB6 +:104F3000A7D4E71DC165F4DE38B7963C0C7662ED68 +:104F400057F32177155D1B39EFB569C52B3DEFA7E9 +:104F5000768D4A82805F51B1F6AB59F0A33AB8B56D +:104F60000EC3089FCAD8869543386E1F66FDD15878 +:104F7000ED7EF34AC9478EBF14ABB8F982EA4BDA2B +:104F8000B5993F149D772E569BF3CC2F95771E2D08 +:104F900007861FF898AD39C3C5EBF4118F22CEBB3D +:104FA000584970619DFE598C5886FB8002AFCA3CFF +:104FB000B59683369937B05AD92822FC93413ABD29 +:104FC0000D78EEB95CF6C7CFC3AB158BB84288EE4F +:104FD0005A7313D6D7674A2CEC779F2929286C0F70 +:104FE000FF8FD6659813B86F2B125FDCB715293F7A +:104FF000B86FCB7C6EA2A3A93DEEDB329F9BE86B22 +:10500000AA9FBA3AD7543FAF68B8A9BEBB90F82D53 +:105010005928F19B47F6C197027819E72D2E01EF29 +:10502000C84FC952022B592F6F50F8DCB87BE9AA40 +:1050300042D0E5048933E20886DCCCD5ED8BB0069E +:10504000EC90BBB3A9B2FEA8D2F0C55DF4DE496F07 +:10505000ED165C8572D2B2EEC1116EE4D76FC872E4 +:10506000D13CBC5509A541F5140CD234C8D9616BAB +:10507000E364DE4FDCD9BE5D35FCCE8383DEC847FA +:105080007FDB55CE9B30E425CB26E3741B689D0166 +:10509000FF6A43ADCCE7DD509B12DB3D62FFC518D4 +:1050A000670BF820502E4B4BE5B89068C038C86F9E +:1050B0005F06BFEDCC41E9B71BE3E9BE3CDC690903 +:1050C000D5DFBA3386E973585F379CE8F3D20037EF +:1050D000CE6F54EDCD52E10F58B66FC13A22215533 +:1050E0005B0AB92FD9D0E3AFB8AF6BD17BAAC07937 +:1050F0009ACFD78C491C4ADF39F6B4CD3381E0BB57 +:105100006A1FB7639DBCC81AB4731EE6B60D76E479 +:1051100025FF64EB067E3E7F6B31E75D2E107E5EE1 +:10512000471ED1CF6519E32E2950D6B948BE3E1A85 +:1051300026F56349ACDCCF2379FE33C67566ABE256 +:1051400085FF38AD68A7BD989EDFA7B7734F9F3E18 +:105150000EF2D71292F76DB4BCAECA7BC4A6A932C8 +:105160002FE622F7F34C3D97CDF23DED5C3F5E67B5 +:105170005D1BEE23D7B139527FB4D4A9BC1FD7F23F +:10518000FACBA953F1BD3A1BEFDE95D81BE4F97FAA +:105190008BF0E31C817B7A8394AB6CE187FFB7E4EF +:1051A0002FEFD463DE2DC976BA311F8A46A826F9BF +:1051B000AC1C1B6792DFE9A29DE91CCD75482A89CA +:1051C00080A74DE8666A7FFDB47E51FA60606B3D52 +:1051D000EB836151E7000B4C70399577403F89AB09 +:1051E0004CEF958B29ADEDB01EDE24FDD6F25DC9E6 +:1051F0001BB12F5E6291EBA1E99A7C5EB1573E171D +:1052000022F6FCB9749CC7477CC0746E5BDFE74331 +:10521000BF1C0FECD6C0719DE60CD29744D1F2DED4 +:105220008D76C4D3C85D6E469CB43C4030FAF58997 +:10523000E61A9C1FB14AFAC67B5C5D9765B4CA4505 +:10524000C52E73BE55C5C177B89D91CF185D4F9ED1 +:10525000EFCA8EC07B82E2E57393DB9BEC88074D3F +:10526000D33AF1BD14D1F79F95859A18CF6BF7A665 +:10527000B9B06F5B1175EF59A7E16E699FF4F83F04 +:10528000EE0D927E42835DC66DE3F75B78FEC97BCF +:1052900076CECB658945DE1710459709DEF7B8BF96 +:1052A0008E19320F0D74B146D0255A8E40276B04EB +:1052B0009DE60B49A7F9A44D820477849C45D2E76B +:1052C00047D26B01FEA0FA057B9520F2DFA2E933FD +:1052D0005F6B64FACDD7E2FD41D785E3A9B8E383DC +:1052E0007AE8A71D19F29EC268FA2D100D2BB1EEB7 +:1052F0005D4076239CCC726177F23A4DF1C06EBB73 +:10530000F31BED36A9CF38CEDBF2FA3B3CEF5A3C2B +:1053100034AB211782EAA97DBCCFDDBCAC8D3CDF6C +:1053200029E764FCE4BA73562EA74D30CFBB6BCF90 +:10533000A5F1F31F4B970AD019728EB85E621BF766 +:10534000E621CE9778E1788DFD10430FB7FA75E628 +:10535000BCE58BF97FD171C2DEC3F538E12031C8DD +:1053600094B77C11BF233A6FD9B0E32DF1D24E8EA2 +:105370005373DEC4D9C6E257555EA7BBA78FB7F0FB +:10538000F9F157E57D77DA8AB34D904F2DC1C27A96 +:1053900070714257BED742D3E376463F59D529694B +:1053A00088FF15C7B8381FBFB85A2D82FD2AA676C8 +:1053B000EE88762B9777CB825DF8F4EE5E8F0668E9 +:1053C000BE7C7A5B6A1AE2FE9FADB0A592E63CDF36 +:1053D000EED315E3B2909FF1D97D8EE9C136E85343 +:1053E000345CDA81F23B3F60BB75D2F27AE2747AC8 +:1053F000BF6CC5EE4484EA4A57BC33D8452EC5E19C +:105400003CED9AE1BCBFBA610BDF07EDDAC0F709EA +:1054100068484A6E8F7D8815CCF7458ADCAFBE554B +:10542000097F7125B53B11735FE2F46CDC6E2A389D +:105430004FE3ECA604FD3C5A35E70D9D88257F809F +:10544000DA1F8991F43CB233C1C37762780259BC48 +:105450007E6B2FF7774A2D75D7019F6B52356DF80C +:1054600020E011DC92AE723B3EB7AE55F7486A2B96 +:10547000FE61945B743B0D7F1B25FC6DE4CBC0DFAC +:10548000060C7F1B25FC6D3CAF5C6BF6DF6ED7F71F +:10549000FB8C7870979A662FFCDD4081E8ED673BC6 +:1054A0003BA1E0F7B05BAF4A7F6189E259D5C8FE06 +:1054B00052422DD69D3556E967073E91E7A22082DC +:1054C000D04FBF50FB7AB09FFF50DC9D8FA1FD52A3 +:1054D000EC0FE5E11E53F2BD22E4F5CA734E1179DB +:1054E000EE7634396191F0186786A9FD3857B6A970 +:1054F000FE27E97D4CF53F757B4DF0D5BD879ADAE7 +:105500004FF48C36C1D7E4FFD4D47EB26FB2099E7B +:105510003A7E86A9FDB545C5A6FAEBA72F34D5CFAF +:10552000D06E31C13796DC666A7F93BFDA542F8420 +:10553000FF09D0C71790F7AAD561FDE4C0FD2F4E33 +:105540002EA9FE0FC8631E4D22CDF7AEFCE5677C89 +:105550008FF57EE435D38C1B31C6E26F2B8EFF07AF +:105560005DFE6347FAB60DE7756E03DF8B89D82DB4 +:10557000E46E1FECD4A0D6E79DAC46DCAA2143DE46 +:10558000876E6E7FB17623E2F69F7193C8F5AC3BD0 +:10559000739395F4D78821FB73BB21EF79C4E0594D +:1055A00056D2372386EF7FB62BC1FEBA3B6771FD1B +:1055B00015FBCFA0FE1F75C3243C55B06B72FB8852 +:1055C000BFDD84FC941157765DED91719136CFB7B4 +:1055D0001B25E88473E1A013CA30C93DCAFD24F736 +:1055E000280F90DCCF23BD564F728FF220AD33F1E0 +:1055F000FCDF689D89F2755A67A27C83D697281BC9 +:10560000687D89F2EDAAE95CBE5BA5F17BEF579559 +:1056100070F941959F9F7F54B594CB4FAA02FCFC33 +:10562000C3E1328E108F7B9313FEC9BDC97E17DF95 +:105630007F50A3DB2D51A7E7D5ECA7F52BE8D96860 +:105640004DFEC2D9BABF78F1F5BE557C11E1B74D18 +:10565000B6FA3E97FCEDE462BDAF3F2FF56AC7A0F6 +:105660004FDECB9EDA235785BDF3FF3989EADEB3DF +:10567000B47D9FE43E5D5E3E1EE13B8DEF8D741E6A +:10568000E2FD74770679ABC31956C07F65A08C5FC5 +:105690008EB436D4A0BEE63BE1C6BAF9A584F7794C +:1056A0001FBC86DC659C3F56CEC9F5CA287DFFBE6F +:1056B000E63BB97F3F0AB853FD4897ACAFB9992C88 +:1056C0009D17F521FEFE289C7696E7DB4C793B631F +:1056D000CF358CE1FA78BB1BF9A6A39C61F93DA7F5 +:1056E0007021BEFC52C21ED9FF38D9FFA6EFC2FC02 +:1056F0007DAC3E91973DD2D98ACF32C6AF41DE37DD +:105700009723DBD7E8ED4769D47F32F0F34BFC8A6F +:10571000A9BDC49FF5DC287C3319AB6D591F9B2EA6 +:10572000CF278F3DA7D77BE4783B58258C3325A81E +:10573000CF4CD1848FFACBCC141EC4DF46A536647F +:10574000707B3D9F21C12ABF97E491F77175FFBB24 +:1057500026F7038800C0DFC84B32E66DE776E10C20 +:10576000F8799D17DBF97B99EA4E2FF4F5A75EAD2A +:10577000EF08AAB73A2D3CBE1A9F3C2FFFD68BEEFE +:10578000CEB85F74B2EEAFFF13FE5F81F7473AF712 +:1057900049FEE392B7CC5658994FFF0F6D93FF9295 +:1057A0005E242F183FF19FF9017EEAFC570CFAE8BE +:1057B000FC3FCFAF6591F5BA7C5CC8FF90E4B72E93 +:1057C0004FA39C326F02EDC1FF9156290F35313244 +:1057D000DFE3A584C287714F16D1A608F1F991863F +:1057E000BCF8E5F9E1FFADFCCFB3CA7BE41C654E24 +:1057F000BEA7EE52F230BB5914E2DECD8D03B57D6B +:1058000098D7C5E7DCF580E78AD18570CF8DFAA7F8 +:105810002E52AF7DDD6C036C3C7F1BED06B5D65B75 +:105820009D6FC741EF19DF31DA7DA57FAFB5DD4050 +:10583000FE9D8D25E342EB60BFC6575B396E4D9EE2 +:1058400009C307C99EC97C4E5FA2372D32FFD373AF +:1058500060711EEE0B95E7B744BCF4ABDDF41FF4AA +:105860006AE1F745CBD19F50B75BB1EE388B7C5ADC +:10587000FA4E61AAD93F1F1FB5BF7E55CE97EC8F58 +:105880005F75897BAB7F3742F7A7B345F67FF2DEC2 +:10589000D08747B07EBEBC7B437B8B3A9683B1C535 +:1058A000329F8BC66F1988B88D4FF801170ABF1544 +:1058B00072305ED45AE5BAD277A2228F57ED4C9F50 +:1058C000AB45989F4F24830263720D890FE097E3E5 +:1058D00026CDC47DC06372C774C7F388FBF3FE0096 +:1058E000FC2A54ED6FAE88FBF3F68F95F36DF1B59E +:1058F00032DEB4DFD9AD4D3FF455B2B7DD7B802E3B +:1059000082CB3F933DEE4EE37E85EC31E0AB7A57A0 +:105910000BBC57E836E71D19EF5FED1A23AC2917CA +:10592000B777570FF86327D0F9B5E45E63C1AFD7F7 +:1059300092878C453CFEB5E40E16593AEC5CF67F36 +:10594000AE7B5BF819F3A3B5BF42EECFB8FF776C1F +:105950007B79FF6F345DAF1221137D27E8F4FD11D1 +:1059600074FD087A349AAEFBF475C57EE73B7B8CF8 +:10597000BC29C493BB2F6F60F8569B9C07E5CF4DA5 +:105980002C405EF4E2F7647EC751A002BBBB7438C2 +:10599000E33F6AE95061CDE5FDA800E85DE6947457 +:1059A0003C19786900EE29AF4FD18E83AF5FAE53BB +:1059B000F9BCFDC96762381E7724F86C22E869C813 +:1059C0007199EA5ECDBFA7F19A2AEF59FAFEE52C4C +:1059D000DC2B7A31B92679FE7AC4A036E4399EE40C +:1059E000B9FF85F22C36C97B0CCA9C856DF2D9585B +:1059F00077BE30D0C7FAC225C2B740FE2B845C1FE9 +:105A000055385F97F754128C73AFD17ED5E0586A42 +:105A10004FF576A7CC1736F89DE990F75866C6097A +:105A200017E22042CBED0B7CFB76F7C58DE4FCC280 +:105A30009CED91796BA3C2FD78DF79FC4195F3DD94 +:105A40005F8995F7B837123F14F24F7FD2CF1FDF2F +:105A500095F8983C444B1B8971A9DFABE8F7F51E1C +:105A60008A48E1F8796E3CAFB37FE47A3D6BA4AE2F +:105A70005F068801FFF4F711DACB7B8417BF9A1B0E +:105A800004DE8BABC9AAA5F2EF5CF03D7135589FDF +:105A900067B7EA9D51A227FFFEC598541BE799FFFF +:105AA0006FFB7D844CA1F1FCFBCFFE4EC278F9E880 +:105AB00082DF49C84C5C75404B6DFD9D8CE8DF4929 +:105AC000C8D4EFA7166E693F8CDF47B852F8382F5D +:105AD0007F5CBAD9AE8C718D3EE0E2D21CEFC9BCBE +:105AE000443ED74D23F5739D97E27BB9D0F92ECF75 +:105AF00075420EF4DF3B09423E8DDF3B31F86EFC10 +:105B0000EE494D7BF9BB27FF6ABF7312CD9FE8DFDB +:105B10003D89E64FF4EFA08CD262994E63CAE259F8 +:105B2000AE0D3E4DA7FFD81FC0B95CE5BF9F5FF724 +:105B300047CDD3B362F520DC537ABA58EAF58BD956 +:105B4000FF695EDFEFA16FB6E97ABFC629E321BE28 +:105B50001AAB881925703F21E7CBFEA246DE03551C +:105B60006395F18000F115F7E27D1BFB0F799F2310 +:105B7000F947B68E88CBF8F9FD80DDE9AAF144FC3F +:105B80000ED652791EF89045FE9ED4EC1CBF82FDC5 +:105B9000CB4E5DB5A7A0AFD245D1CEF91C97F70F7C +:105BA000817E9FF5274716EA677591F7478A1CF9AA +:105BB000BB4106FEB332655ED6B323753DEE9179E7 +:105BC000587B46CAFDC0048F8BCF3514E7083DBF14 +:105BD0005564CDEA0F39FE84FDF816B7F4AB1B6DA2 +:105BE000F21ECBC0AB329F679DFF6DF6FB37935F14 +:105BF000AB4AFF66EDBD1C674814D8C77D2CA6399B +:105C000019F8F75A2B4CFE429FA0D39497DC6FAB48 +:105C1000CB04F70FA59BDA5FB1D76DAAF7867B9B04 +:105C2000EA730F7A4CF0A0867C53FB211FF84CF0EE +:105C3000D0C6F1A6F6C38F1499E05323BB4A3A416C +:105C400026693CB396B882F25E7C1927E96297FE1A +:105C500054CD6D723D61E4AF6BFA3C88CE5FEF6C62 +:105C600095F9EB76BFB46B5ABC5CDFBADA0997CA18 +:105C7000E7621A18C6DD109C371E30E7997772CAA2 +:105C8000F59565AC5C7FD8F53CF3D8DEF2DC8B9102 +:105C9000574EEB0A1FE8DD5D34CEE0DF2FD0EF1367 +:105CA0008D96E7BF8FD4EF738AC2BB8B5D9EA7AB87 +:105CB000B9CDCEFBE75ABCBD4949BC109F6E7A7E78 +:105CC000E46667DBF73E39474939BB21AF488CA210 +:105CD000768F92D962FFEB82FE3C8DD07735BFB2D2 +:105CE00073DEF8A5FA9B75851CCF4C8B65F6E41C1A +:105CF0005E0FF23940A3DF74F44BEDFAF874398F7C +:105D0000EA6F565233DFBB2692EC6EC8AF16BF92D5 +:105D10006157AC4856DBA07BEBB90C99A77FD3EA5F +:105D2000D0BDBD08CF99F65A9BBC702068833C4C0F +:105D300028203FD28BF8EB43EBE3891F8FE207EC7F +:105D4000C8CFE8B2AFDDEC4077F899CD2C0F4844CE +:105D5000C17E22FC4F75602BDE6BAE9479DFBE51A5 +:105D6000C2B8FF80F16AD1E3232D2274FEFC44A067 +:105D70000D79D3E2EBF91C826BB194A7CE11E7AC9D +:105D8000B0FEFC9F3A2F21B0434AFDD86A853CE71C +:105D90007809FA19E754DCB7D88A36C6E3BC881804 +:105DA000AF44D0E1892BA55C2E061DDACB76D04717 +:105DB000176B477E5F12F6175A843BC97589B8FA8C +:105DC000FFC4F833AD32CE90E594E7453A5B35D663 +:105DD00017F6DEFA3D7717C8BBAE37F4385927AB54 +:105DE0009CF79D3C725E5FA8170EF0F7ED9ABC37EA +:105DF0002D9ABEFC2F22AE629C5F891D2BF588A1D7 +:105E000017CE9F43E921D7A1365D3F04BB5B38EF36 +:105E1000E0AE04F33C7E7C94A46FA13E8FC9CE27F4 +:105E20007A079BF484C0BE5ECD0A95F504E9C97A71 +:105E30008DF02CC6BD2CAED6DF7BBBF90169C74601 +:105E4000F98A1EC4BEC99C3536B181F715E4FDB090 +:105E50000BF438797120EA7E16DD1F3FBB5A71E1E1 +:105E60007720E6AE32D72F88FFE213AC1F6F8EBECD +:105E7000A7C6D8AFBB441CE0FE51BAFDF7088F9E01 +:105E80007FBF0CF89D0DCA7BAFCF9F57D2E33F2D4C +:105E9000C167257C87E07851B45F60C06EEC9345A4 +:105EA000DCC342F48DED0DFBBEDCDA667EA341DF80 +:105EB000F3791EFA3E1D95CB56F07A46E637903EB2 +:105EC000E07DB913540F3FF044E00CB73FB12B868F +:105ED000F34A4E7A1B0660FFD6D8A7EBAEC97DAC5D +:105EE000965D0932BF21DE22E1ADF21EFB457F0F38 +:105EF0000EC03AB631F0ACE99C83D668DEE78B2E53 +:105F0000B5EADDBCDE3C9CA7D58D427EBDD5E3F471 +:105F1000107C77FC7EBEA76B02AD1FA1D79097B215 +:105F20002255E2CFFA2B7046D2CF2FE9770D397A7E +:105F30009C9F27487B228E2968554B65717828F7EE +:105F4000FF63F7C1A69EF3CAFDDF73C3F97D6DD56C +:105F500050867B079B477F40FD5EA7C5BB1147BAB4 +:105F6000B6E617E362E9D38DBF8F5FC16567F3F9CA +:105F700001A3FC58B7238DB6B6EB27E8FA67E19585 +:105F800086BE96F2BEB85AE17DB5C59071C0F7CA1B +:105F9000FB390DF84CAD0E8F93F092151286698285 +:105FA0001F3C47FFDDB32D7AFC05E34789F1232E23 +:105FB000B05D8FCF60FC28317E3C87BE020C7D0532 +:105FC00018FA0A30F4154AE82B3CFF3C790CEF6BC9 +:105FD00063DF6E6CC47CC2BEDDD888F9817DBB48AE +:105FE00018FB7691EDB16F17598F7DBBC87AECDB4A +:105FF00045C2D8B78B6C8F7DBB4858E4FFB415867B +:106000005EF34D36C153693D3036623E63DF2EF29A +:10601000FBD8B7337D4FBBC5F4FE8D62A9E97DEC9B +:10602000DB45B69FBD5431EDEB09D1CC767DEEDA80 +:106030001496A3D7BC451957B6E7DFA9FA99AD2B3B +:10604000EB078E632C2E8FF5487ED78E97FCB7C852 +:10605000F3114A33FFBEC0993BEC121E67CEDF3608 +:106060004AEC7B8DB5C97D2F94D8F742897D2F945A +:10607000D8F71ADB43EE7BA1C4BE179E63DF0B2566 +:10608000F6BD5062DF0B25F6BD5062DF0B25F6BD75 +:10609000F01EF6BD5062DF0BCFB1EF8512FB5E78CC +:1060A0007E88F09817A1C7E0AF7737AD33490E4D22 +:1060B000EB4C970986BF1ED91EFE7A643DFCF5C8DD +:1060C0007AF8EB9130FCF5C8F6F0D723E11B46B91E +:1060D000799EC16F8F7C0F7E7B24DCBF36F067C456 +:1060E000D626AE3B7500656382F228CE1BDE70E5D6 +:1060F000B6D9D8BF6C8C51B29249A7DBAA77CC1E17 +:106100000B7BABE73F0E10CD16E81F0D8BC93C3E55 +:1061100067C879A5FDBFCBE0FADBF5FB11F81FF1ED +:10612000DDBB4BF0EFCE18FBEDC6FB1E32DB288D3E +:10613000F6AD70DBEDA2FB37DA716E55041E38D177 +:106140008CBC19EF1DF103B10ED9A2FF8EF096653C +:10615000322F3A5AAE7EABEBA72D969DFB710EA661 +:10616000B958F1E0DC47F75A8DCF99F59F292CAA51 +:10617000B7753CBD1E4BE4BCDA5F5C29ED9181BF75 +:10618000111F257DC1E7074734378C49A2F65A60B5 +:1061900034FF0ECE04BBD07F2FD83F0CEBC97E015D +:1061A000C5B73142CEABF5EF690189C7138F4D9268 +:1061B000EFC5CAF79E782C91FB9FB45CE13CB3110C +:1061C000DB850FE794EFD1F1EFB73DACA2BFE2E57D +:1061D000B23FE3BBC5EBB2EC38CF6DD0AB58348ED9 +:1061E000C57DD2224FC19DB2A2A75563BFB4C34C97 +:1061F00097057ED0E59E831A99973C0E7988A24E2A +:10620000F0BDA113F3DE328D97C93518BF6B2A7824 +:106210006DA8056EB1A0DF49448014C49309C67807 +:10622000344DF8B389BED74D2F667AF79E2914D026 +:10623000BBCFCC0D96547AAF9FF69205FE5AFFDA8B +:10624000462E8D71784624AB8027D85CE380FF848E +:10625000710AEB8FE83C1EF8070C2FB7B13D37FCF5 +:1062600087C509E7F37CFE8A3C9F33076D9CE77383 +:1062700066F959AE2FDE1DC3793DDA5A85F59AE1EC +:106280003718793B65B7BC3718F439961DDC92DCBA +:106290008DEDFC1FAF441E4BD79D89381A7762F9EC +:1062A000EEEBE0529E59BE5BFEFEACBEBF63FC8EC1 +:1062B000A9C8F1713E98E1070AB5CE1EB98F63FCFB +:1062C0001E1AE94F6E7766AFDDC5BF47A7FF7EA9EF +:1062D00011F729FE4B6E3DE85ABC5EFE9ED99C55D7 +:1062E000F7154E2778BECF19C6EFA147E7632D8C6F +:1062F000F2032FF5FBA5C267F6FF2EE6EFFCFFF2D7 +:10630000BFB7FCBF73A5703700800000000000001D +:106310001F8B080000000000000BED7D0B58556539 +:10632000BAF0B7F6DA37606F5C080AA8E002454DAC +:10633000C936225EBA2EB9282AE206C4B441DC204E +:106340002676AC21B3911ACA8D7B4348D6C04469E6 +:106350008ED5D6D433534DD1654A27EB6CB59A2EE2 +:106360009A263975A682ED25B53BE9F1D49CC799EB +:10637000CEFBBEDF5AB2D776836633E73FFFFFFC22 +:106380007B9E66F1ADEFFE7EEFFD7DBF25136D06B2 +:10639000369EB1337B459F98C258C5BE3DA52C8E15 +:1063A000B1533526C6A05C562F322CB367992F4DBA +:1063B000C0728E2102CA657F501C82CCD877ABAAEE +:1063C000F7BF064DF7AF823616C68ABF1FCC5826D8 +:1063D000631DAB642A977E3F86B158C60A0211F44A +:1063E0007EEEF789F4BCFEFBCBE87DB10DFAC1FC73 +:1063F000811DCCB71AE63BE5B650F9D44EE6C3F999 +:10640000F1173781B111F8070C99C1A43C368CB152 +:10641000D18AB007BAB359DF5F45E3CDFB3E83C6EF +:10642000BB667C45C300E80FBD1D69D07ED6F8F77A +:1064300072FAC17A5DEE295922948B8DFE39387E2D +:10644000B1C3C4DC29F8FE564302D417325613EB0D +:1064500080F650C6FDBA5CAC468861ECCE89D06946 +:10646000009459CDEB03100E5B98632BBC9AE7AAFE +:10647000C8C67663CA9820C2D4E551ACA61DF7629F +:106480000B64155DCED80FF8BB0EDEE322AFC4C59A +:1064900027BA14A82FEF077F0EA26D29CCCA983D0A +:1064A0009DD75FA924BABCC3E1EF96758A7520CE4B +:1064B000C77F43CDD00EE611EF34FB5603FC5D36AB +:1064C000EB61612C54B8F394C028DEE68754C6868D +:1064D0004D823FB2E05C0C86854E9867C18A0C7392 +:1064E000657ACF3ACCD9D9F3A6C03EF2F0BC61BCF4 +:1064F000E56B4C3E4B0A3ED3E299ADA75DE87311C4 +:10650000C0578EC575076E17003EF314A6E4C25C33 +:10651000F399B62FE667B08E1BD4B2D7AF049A6C4E +:10652000040F2ACFF18F70B9611D375B03530193BC +:10653000D8CFD36BF2130D8CBD61E270B5985CCAF5 +:10654000605887697B867FB08CFB90E83D330612EC +:106550009D76D8C7DAF6FB46C27BAF22F3FD995B86 +:106560004C0C07623E9313E0BC289D293E84BB91EE +:10657000E3D191352F3DDD2CF4ACFF8889CD6B0F35 +:10658000B3BF3AC540F36C03BC954732F6DB5556B2 +:106590007A3EB14A6232A0E053AB12A8FC34E0313B +:1065A0003EDB578DA2F7CFAD7250F9855593A8FC0D +:1065B000E22A85CADB57E5D3F38FAB9CF4BE60B407 +:1065C000EB1605D6FB9041397C0FEC6F90D8C210CA +:1065D0006FF1DCAD137ACE37A2E5BB0A3C8F2A9B64 +:1065E00059C6755701685CB08F4AC5EAA8075000C4 +:1065F0006C1B13A05C2EB2EE6647B873E7707C6C20 +:10660000FE7F2D3540BBC7EE8A24BAD5E057663EE3 +:10661000F0BA35A5077E1FD5FEDAC40C746C69325A +:10662000CC7B434D84A33905F1C3E9C1F546A53BB5 +:10663000CC2E80D7BC298CC6BD32D5D988EF6F5EF1 +:10664000BBEBD10FF0FC76A6985D709E15DB331A7C +:106650001364ECE7BA5781761536C98C78778B3797 +:10666000C62CE3F9C7033D206EB3EEE4627B0FDC7A +:10667000B728028D7B7D361FFF1B3C1F6AD7622A1D +:10668000D2B5E3E7733E3D1C9882F0F200FB581D43 +:1066900083F4F0E2143C77E94EA091C9B01EF63EB7 +:1066A000D59B1398E489391F5E83D90101EB13014F +:1066B00096EEC93DF06B1E55497CCE043428C604C5 +:1066C000C38F113D85E2CFFBB80F804BE50A6175A2 +:1066D00003CC5FD526FA0401E9ABE00DA2AF564129 +:1066E00026FA7A70983991E84D90907F15F497A723 +:1066F000C643FBEEFB0469B38CF40A738DEB19B748 +:106700006AFD64A2B72A1F3C337BA7CB9FB5EE4935 +:10671000DA21E3312A665C6795A498FB07D1FBA2D6 +:106720001681E822B4FC9A22723A626F9A106E6562 +:10673000C365C19381FBE1F8B160458AB9D286F5A2 +:10674000CC6F807515A4B237B05D772BAC3785CF91 +:10675000332E68DC4A1C37685E68BFD009E57715C0 +:106760003BC1B54292CD8928572489D657B9629743 +:1067700009E1B308E02C64203C1C661B8EBF14C6E4 +:1067800007F8DD20F9F3B0FE867499D5C339547A41 +:1067900033CCC89F5C6BF93CAEA618F3E550AE3025 +:1067A0004AE624289745323A37589F0FFB57013C59 +:1067B000FADB705CB610654B285C2AD4F556B5C47C +:1067C0009817EBDEB79AE474E26B4A387E214EE10B +:1067D000785BE92D4A5E87E7EDB64B44B746C5ECDA +:1067E000C075A9F09DDFB6CE9412D4FF5B158FC59E +:1067F000291CCF0A52FD6902EEF7D60807AE77BE14 +:10680000D46242789E83F3831C0E8B257F1A8EBF41 +:10681000D8CAE1700E3FDAF4E7DAB33E0EEFAAB65B +:106820000AA2BF1B8DCEE475D0FF4658A71B9EF36E +:10683000D7EF4A13F009F42E207F905CC9CE207A5E +:106840003BFEE0F5C9B47F583FC2DBEE90A722DFE4 +:1068500001BC21B9ABE14F7926A76BADDFE029463A +:106860009A77F0944BA3D7AAB5EF51FD22A0579485 +:10687000B766F68280F5666084E1E837094786F6F8 +:1068800036C01F77620FFDCE6781F9C85F17AD2D47 +:1068900062AE20FE03F2B6E6B930F09A87EBCD2265 +:1068A000B945E70D74F81AEBDF539FAD9E7759AAEF +:1068B0009EFE713C1CD7A1D567FBD36E4DEF69AF2F +:1068C000CD5BD69FF7437A403C74A8F0C1F6CBA9C4 +:1068D0003D2F833C5EDD80FCE13ED16711F0F9780D +:1068E000C3402C3F0BD216B6F6C5F297DE9D0BCFF8 +:1068F000CF1FDA548EFBD3D6B118F41DE41337AA98 +:10690000F2B9CA1F9E5FFC6292EBBA295941F8F3B3 +:10691000C0EF4720FFFEE2E977D210CE1FDB39BF80 +:10692000FBD9EF1F37B1D49EF55736BD67AAB00526 +:10693000C38BF3BBE65107E9FC168DE2FD1679BF68 +:1069400025F9C5407EA5A59C7FFE15DE6779FB5A1B +:1069500007B577D9FECCCF7F1093C4C40B9FB77611 +:10696000BEA1E7FEA8C9E94F407D34B54547FFA168 +:10697000FBAF50D75D3585F3B71B543CBEA1BA952C +:10698000FA5536553C8E7AEF7C8D7EABF4EFB5F33D +:1069900039B5D644E7736A6D5A23EA8BA7DAF9F959 +:1069A000FC8BD83E7625B4FB62D9D65B1253492FB7 +:1069B0004946BD04CF07F5D21B55FD74099C0FEA6B +:1069C000A761CEE736D4CBB4F292C7F8F92C7A7A25 +:1069D000DF277F9409FFF8FEEEB3F890FF56B63F2D +:1069E0007BE84A783FBFA9D59402ED3C5352083E5C +:1069F000E7F87C4D86C4A2617F4D9B4CC8073CDA0A +:106A0000BE43F05C832B33723EF328E8F0CD315C5B +:106A10001E09FD7BDACF674A3CF211E61EC2B6C6FC +:106A20009DBFFEA7553A2A48759849AE3544B1CD69 +:106A300012AEA3E27E36B677F9753482D305485D8F +:106A400005E9F3E8144732D285A6BF86B6DFAAD29D +:106A5000D7E0A8F6F9B8DEC1B120DF01C4BF895480 +:106A6000B251EFF9CD9556C9E3C0FE2E19EB2D5664 +:106A700026A17CDF6C90C7117E827E7F4F22C232BE +:106A800090857C6FF8B2C0B7B83E44A78871FC69A6 +:106A9000877DBFA3C20B55F181FCBD1F9F49C67600 +:106AA000E25391B51CFF42F50CAD5FA87E11AA57C9 +:106AB000F4B6BF3D17B9BFA3292E1FC98908266D9B +:106AC0008EA1FD2DC7F2B9FD8D628A01FA97FFF202 +:106AD000F24DA84F1EAD57769BA1FEE81D36EAFF8A +:106AE0008FDA6FE83EE75755E8F6798E6E5A44B272 +:106AF000334EB56426935D07360F83FAA3B7461865 +:106B000010FE4753B8BE0016A01DF5C46DAA1D891E +:106B1000FA383E511F6723B93E8EE5A755BB12F5E3 +:106B2000717C7F5CC5BFB248251AE57277BD5DDA1E +:106B30008CF0F073BAE9AC1D4670003D81F36355EB +:106B40002FE89402F6FE417C1AE4C77D28EF58ED49 +:106B50003086F65D67CB51BB211DF192AF4F6BBF05 +:106B6000C2D4C2EEC0760F0BBEAD306ED48AF7F23F +:106B7000E2514EB7A56408D06F41ED69E2870B6C16 +:106B800003658672DCE66A9C88F5EB53A4D5D02DAC +:106B9000AA2DA3B316FA2FF68E24FB798520937EB7 +:106BA000CFEA05B22B996A1F2CC1BFA0BCC4F6C6A0 +:106BB00070955F1A905F2EBAFF8EC644281F36B0BC +:106BC0006E11405360289A8AE5820D310E0FCA5B20 +:106BD0000FDF0FDB087CD4DAC3474F4F72B26CA4CF +:106BE000F7B3806F30FE68581BDA512B4CED0AAEBC +:106BF0009F81DEB195E17A9DA4C7AF52F1A2B3EDBA +:106C0000B05D56CF07F5F3E1AEEEC3F7E0B9DA0CAD +:106C10008E6619E5BBBC5F46B8BF2532D4678733A3 +:106C20005EBFDCCEEBE149FAF1F24DA28F917E5CC2 +:106C3000363080FAD77A91F8E2E24D250351DF58D9 +:106C40000C65945F1B702AC0A7C6B61CDEAE35EF7C +:106C50002137F0D3648139911F1D33068A101E2716 +:106C600037C5F7AF477DEF66CF0806F5559BEE4970 +:106C7000C6E7C94D11F3908FE74A45B931A8FF6CBB +:106C80008CC940BB5FA3B3F46C2E0F6EBA39271EBC +:106C9000E5DDB2BFEF795402B9BA187054423F48EB +:106CA0007B94CF0D4D96ADDA9E2C026AD9E35C231E +:106CB000116EFF62D8397732CA61C1B72D91DACB34 +:106CC000F1521F76F371B42B014F6FBEFB431AE7ED +:106CD0002BC3DEC2F9D07FD9CDCF47E338FFF260B6 +:106CE000C70409DE1F1BEFCAC4F13F17366D93D0EE +:106CF000AE5DBF692CCA8FF1AA7D54D0DF39773ED3 +:106D000087AF63B3DCFB7CD5DB0582A7565EE0EB87 +:106D10006766A897FA9959C2A7C4480F3E29B25A84 +:106D200094EF9A5EA2BD9F96CDF9CFC97E2DC9780A +:106D3000FE4BB7AD4B46F9F1999D975D5BFEB4F8FC +:106D40004E5887ABCD2031C03B979191DEBBC8CD6B +:106D5000F569560DCC24B167FEA2EC2882F3D2F57A +:106D6000993AB9878E197CFF9991E5E33A867ABA08 +:106D700033507FFAC8E85F8CE7FA11E8A7E8974933 +:106D8000CFE6F8F7518B3815DFBB57080CFD4F1FC6 +:106D9000B53C6F1FCEFD28E4C7602F9B7C5BA1BD77 +:106DA0007D7CBB1FF9DECD2FC48C4330E689E9F131 +:106DB000883FCB7798A60EE6FA145AD36C99D16F18 +:106DC0000E776E37A97AD4B9F20BCF9A11EF973DAF +:106DD000D54A7E0550537CA8DF2C6B7FF68D413061 +:106DE000DE2DDB2B32711EADFD2D2F703844B080AF +:106DF000B92448AFAE18D5BF7130F0C8E5D9F9AEA7 +:106E000007511FC273BA12D424655245BD119F1297 +:106E1000ED9319BB491F07FD8AECEB9BBD7CBC9B26 +:106E2000471D6C4CA57D15C5B2A0F3BF2DDB44E713 +:106E3000A5F5877D533F8FF5EEC702B05EC563644D +:106E400011D742D9C83EDE86F063D1D256DC879195 +:106E50001D7B039E2BC57EAC199E1B6B96FF2BB52D +:106E6000AFB748223C3D37D73D1380F964913919BB +:106E7000F47767D7D0786E33973FEBA29E7EF846C3 +:106E800028D7CEB13900BDA11C4DF0D9F90B03F1C3 +:106E9000F944D6BDC700CF78065404001A92EA6AB6 +:106EA00021BEC3383F5E799BEC437E0C1C5C403CAA +:106EB000FFE6951399B8EE6B87064E235E99EAA715 +:106EC00057E402FDAFCF56E1921EC8C4760376ABFD +:106ED0007CCD7880E4A32941EE8FFA8A1FC7C2F5E2 +:106EE000FDD54078B053F03F8EF36A70DAA7D2FB3D +:106EF0007319AE4DD9F05404D3ED7E683F5B8876AC +:106F0000E07E0FF417D3C60D433FC4C72938AE1B2C +:106F1000D0561CDCA3C766AB4B370F9AB41EE132C8 +:106F20000500CAAE065B26BD3F3342F95E66E8B691 +:106F3000C03AB2BBFFB2A91ECAD2AFFB3111449511 +:106F400027229965C3F8C26ED828EC6777FAEE4518 +:106F5000B8CE7BBBAD0CE1C4AC7A3DD76C48F4FF36 +:106F600012F1B926DAC112500EB567203F62B7D8C8 +:106F7000C83FB3E06C20EDE72897FEBA97F4F49F82 +:106F8000A5BA5E46B80E1295C32EA8BF57F20FFBE6 +:106F9000158E5F1BE5A8E7728405AF7FE71D7F8D27 +:106FA0008E857EDF748F303E03EDBE51AC0EF4E76C +:106FB00075DE39E6B5ABA07CB52A4F42D7F54D82D8 +:106FC0006C44BBE39B6EAB1FF5906F6C06F2736471 +:106FD000EFDCF321FA21B3AD36BF188DFD4C5F060F +:106FE000CB1B762029E6F8181231EC0780E74055D4 +:106FF0002E5DDB4F6F3F7666733BA853E53F46D966 +:1070000041703EE536B266C44306659CD768959AE2 +:10701000617DAFDAB62D40FFD5A9EF53FBA1DC3877 +:10702000B573583F96DE3B5FEC407D02F484884C9C +:10703000E5533C7F4DBE96AA708968B9DE84F0F0B6 +:10704000003CD0BF566A33F82DE85F9DA38703ABA1 +:10705000ED2E47BC61866807D20D9E2F9EBF2C186F +:10706000BAD955E79FF7756725FF2FA1BC00CE134E +:10707000E15A7EEAF8E5BF62746EDFE23AE01C1B7B +:10708000AE603DE7F7BFEDBC98D1D184E7B052B414 +:10709000B7E039788C5CDF73036E6D8DA16EDBF029 +:1070A0005C567A86D3390DF4009F403B0598DAE6AA +:1070B00038E42B07A9FD56CD9F36AA86F84CB9C7F0 +:1070C0002221FCBE8B8CA6FE0CCED534281C9FE161 +:1070D0007CA5B68A115F59985E23E0B927E00CB011 +:1070E0009F4E43C08EFB0C44801609CF6B725255E5 +:1070F000FD1B3882EA67C5FE8FDC61DF8CFC46B47D +:107100000E7EE4188822D6D41D3D1AD6D526B07638 +:10711000DA9749E51F4B6DA4CFB5C5F888BFB59583 +:107120000E71E05EBF616A7D7524F197AB0C062A93 +:1071300077CF1F48F6585B0CB0561C6FFE68D21B09 +:107140005EFC3B8F9774A7315E9FC146ACC7FAA225 +:107150005134DECB1ABFBACF4EE3B515298991540D +:107160003FD080FD5B535C137388AE793B503CA8E5 +:10717000DD860D4A229EE7866233B57B4870CE5F7E +:107180008CE35C6E23BD31303FF2E96DFC38FDE8E5 +:107190005FEAACE5FBD6E840F3AB0F751F7E18F94C +:1071A000873B1B4E04ED43EBD70B10AF1531DA01D3 +:1071B000287CDE397F770ECF59370097C545769208 +:1071C000BD2EA73104369C9FC4B2114FF6003CA1DE +:1071D000BDDB04E71CC7CF79751C9E73E1A6E07385 +:1071E00086F1DC2BE1BDB03CDA214CA2731E85E3B5 +:1071F000D7B24807DAD7E7CEEF555F063E4583237F +:10720000C102B0F83CD5353F27AB478E3CF209ECC4 +:107210000FE0526E0964B5A07E6E60D5ED61F8C0D6 +:10722000A21C6E1F48ACDB84F275A186FF7521F8A5 +:107230001F1812733C4AC57FE8F74ABC73319EC3DE +:107240005742C7047CB9F76FE2BC70E3DF9CC3F917 +:10725000D68138E7325CDF70E3EE21B7A1BE7187DB +:1072600085F45F7676CF109CF77729CE9FE378116F +:10727000C3BBC9BFDE99D86DC2FD75CEFF3C09F511 +:10728000AC85B57F22FABCD8F5AD8E1A6B42B91920 +:10729000939F610A40FFF8FC8CD7F15C0ECEB2C818 +:1072A00096307E905DB32626A13ED4317D6212F2E7 +:1072B000CB8E245833C953871DF9A869FBE5765C4A +:1072C00067477E26956526ABE5923EF9EB17C05FD2 +:1072D000FDA0087C06F61A3E4F80BDE6077EFB291E +:1072E000D86BF83C0AF61ABE3F0CF61A3EBB56396C +:1072F000E87D47FEB0ED8817675AB81F6591D11138 +:10730000562F5BF694C8FC1A7F83FF6EDA12A52B0A +:10731000576F8CD5956F6C030CB2F694ABD60ED329 +:107320009535FDB3D23B46F7DE5597A92BFF3F03BA +:10733000DF260E5FF497FF6F822FFED682BC2BC133 +:107340003F00BFF7654D233EDA21B09A5878C64812 +:107350009CFF199D02F9DDF0D70272BB18FF00BA3D +:1073600031DAE406ACF742FB5F435BB47DD1FE60EB +:10737000CC61AA80F7A5F91112CAF3B9AC86E86C02 +:107380001E6BA1E70DAC9D9E65EC003DCB19A7C31C +:107390006F2A0213F0F9719CEB53A4D36556D7639F +:1073A0007168B725B946C6223FB2F527BBB4B7739B +:1073B000420D9BA97AAE6D82BA2FF8CDC1B543BFFD +:1073C0008351636FBF5DEE99471B1FE63B8D7CE3E6 +:1073D0002B139F675FD6C424E40FCC3940674FF569 +:1073E000365FAB2A272BF2399CD0678BE563A50269 +:1073F000C58B77B55ACCE85F38B6C6A4EAEB77936D +:107400009D7BF810F7CB1C6B98968CF857DF3A32BF +:1074100019F1FC98496EA805F81F9B0CFCDB417E16 +:107420001C07CA8723F976EA0F92223A03CE6D91A0 +:10743000BABF23B2C37C07B42F4D1499DB81F1F49A +:1074400094685CBFB6EFD07557AEB5E8F060F6242F +:107450007DB994997BF02D05CFDBDC538F7A925860 +:10746000D6CFD587DD5DFBF1D2FDAF05E16B72AE06 +:107470003D0EF51A36914DFC41ECE9DF1B7CB57CE5 +:10748000060DBE1A5E7D9FE31C999B45AF29DE86E3 +:10749000717494C71DDB391C5BA3AEBDEF2A80431A +:1074A000F1FB22E3702E777F84F8BC83FBF543E782 +:1074B00009205D8F447AE5745DE17D8FECB78575B9 +:1074C00045265C5FB1AD3B09FD4EBBEE1A9984E7E2 +:1074D0007270D6C824E41B7BA68F7C64058CDB55B8 +:1074E000203A2C804FBB0A4EDF87E58E3A51C27995 +:1074F000BBB69F56F94BF7BE89B0BEAFF34D24879C +:10750000BAB6FF73F84CF10EE03330FF191FE733C2 +:107510004B8C4ED608F32E01B8A01DFFCFE63717CF +:10752000E233074DCE3CCCDBE8AA171CE87FAB9FCB +:107530006E21FDE120D08785E353C30AE49393C015 +:10754000FE9510DF9C596853766C1F3600E1C5DC50 +:10755000CAC151137AF07D51DD9202F4AFB3B5A6E2 +:1075600023A877A33304E57331331E0904E1A9EBA3 +:1075700005534F99F0DA78241084D7A1787A1BE26A +:1075800069540F9E9E616793CDA9BCFEC0C01EBE0C +:1075900087BF60FE728BE86FC478BF86B7FF39FD86 +:1075A000BD72541280AFDC9D0BF8FB8B7129AF04C8 +:1075B0008420BE72917CAC35EAEF24F7D645FD9D60 +:1075C000E4DEA1E95CEEED9A7EFDEEBF20DEDFC5D4 +:1075D000F1BEA37422E1658709E419C0EB605D6622 +:1075E00034968FAE2D213AD3E827749E2E15FFB521 +:1075F000760B8DDD264718FC74D589BAF34C7B6178 +:10760000413FE7E5BDAF5F1B576BA78DBB3024AE95 +:107610001B3AEE13B9DC0E4DDB52D6E7F86000F6EC +:10762000F4A33C94C81E7C15510FB89EB9013E5D71 +:10763000F91C3E5D05D7133D1ECAD7E8D2C5301EE2 +:107640007B708EE843FDB52BFF34D1E919A0531AA6 +:10765000A397794FAAF4795CA5CF632A7D6AF5E2F6 +:10766000D607E7DE80E3D689C4A70FCEC91C80F316 +:107670007DB6258DE685F550DED15BAF2DACAC1F18 +:107680004EFCC18EFCEB10C001ED8492D212B2A769 +:107690004B4C8E01E1F484D07D878EB76B9685F2DA +:1076A000C8603CE277C57795B046E40B0007C4CFCD +:1076B00043D81EEA8BB7723FF01E6C1F170CA791C0 +:1076C000A4AF1CFAADE040D161DAFE373B9EC35255 +:1076D0009F9E5F2C591FA53BB7C52DB1BA72F1749F +:1076E000BE8F4375C30684CB6BBAD0F969FD2FF604 +:1076F000FC6F52FBE39A7F203DA5BF6E3C04927E57 +:10770000BED490FAD121F5E374E50BE1E361152FC6 +:1077100034397238425E102EBED45568A90ECED3CD +:1077200088CEE3764B749E1AB7FF917235224FCF05 +:10773000AF2ED45FE34F9FE738A53C94A3FE12CA57 +:10774000DFBA587E14248713F270BD01C18CFD5B33 +:1077500055395BDDCEF16E5DD4FD947FF395AAA71C +:10776000035E12BFFF5AE5F75FFF412DFF5E20BCAD +:10777000DCB3636534EAED27B68F8C463BEC48BB3F +:10778000271AF9BECCDCD157023E7EE904F909D3B1 +:107790009D6CEF5B7E7EA6F29D13780E2437253A12 +:1077A0008FA3AAFC3C8CF293E4FD287A1E44F909CD +:1077B000F5739E55F5F4DF0A44FF4B8D2DE1FDD3A3 +:1077C0005BF4FCAA7A6354889CD4CBCDAAB58375AC +:1077D000E54AEF305DD955A7979B796219F1F5130A +:1077E0003E0EC792FC4C5DFB13B21C2D117C381C65 +:1077F000BE36C9D18867477CB1D1C1F4A2F1DF831D +:10780000217038867040FCF496F4892747D5FE5ADB +:1078100019EC4213CE5B6275BC1E877E84B5820371 +:10782000E35498EF3709CEF1C09C8CC79B83F48C4E +:10783000F7F344C297C3DE3DE5987775060C30F444 +:10784000F3FEA96E4F32FA572B9E8A22BD2974DEB1 +:10785000AA023D9FF9B2A128FB23E857F2BEE8B384 +:10786000223C0A62887FCD7956F48950EEAACB89F2 +:107870000EDEC709950E35B9B3C45813F61CAB37E5 +:10788000EACFB1A4A09EC6E978506817FAC173D7B1 +:107890006490A4E7F72B31F2FD2F794A24FFEE1212 +:1078A000EFB7FB30AEB804F4405413FED4E42944DF +:1078B000BC3EEC3419889FB6C716227CDC7344CAE0 +:1078C00083DDDB348CF0FC4853CE409CAF4985D33C +:1078D00089ED168370053C9D26E6277BD54FE7F999 +:1078E000A5B784E4C609840BEA414689E8E2813CF5 +:1078F000EE973F0CE360BD01E804F5E12E9F98EFA1 +:107900000B431F0FA8F31C3DFB2BC29F377C7BA2B0 +:1079100051AF38DCCEC73F5A2745637CEA1D6FA6BE +:107920009DD65700E3A2DEBBE37A929327BC1C1FCF +:10793000719D641F3671F9D1E15D74FF6480C75792 +:107940006B45D23BBF6A2A299C8CE7BDD644E59C97 +:10795000A2528A6F74F8B87C39E43B5A8EE777C23A +:107960000BA70FE5FA1D13F78D8FC37336113E5425 +:107970003DA53F97D2B57AFA825F74C604CACFA4F8 +:10798000B82CA81353D14EAA4C00F909947BB8A087 +:1079900084F22A8BDD7A7964614526C43BD42FB109 +:1079A0005DE52325597EA43FB740F272E10B3CEF21 +:1079B000DAB4E56A9277152D16DDBCC5757AFBA899 +:1079C00032C41E0AB5977EB4BC30D5948793171D78 +:1079D0009A5C60D25484FB1130AC9B33E0FD0B22E7 +:1079E000E5239FF14610FFAC5878EA1A552FBD16D3 +:1079F000F18039DC6C9266A707D159A5570CD1D319 +:107A0000F5F005FDF938EAC74DB1AA1C759790BF8E +:107A1000EEF31CE510F1FB8BB5BF2F5ABF2D57F5C8 +:107A2000DB72D26F3B4A2D94AF79109B04F5DF5582 +:107A30007A3DF9750ECDBA9EF4DC43E7FC3A4ED59B +:107A4000AF730D9DDBA102C067921B0EADDCA71EBC +:107A5000A1F18B4FD57338AAF2C9C32A9FEC52ED1E +:107A6000AD46555E78557971A840B5B7E218C90B97 +:107A7000A3516117C3676E6C8B0A910FB12176D445 +:107A8000E090F3D1CB8B6545AEC8A940F79684D181 +:107A9000BAF726699CAE9CB66527F98FCFC83C9F84 +:107AA000E81EC4098C9794F2FC2C666D27FF71A91F +:107AB00043A6FAC1182784F66852611E89869FDAA8 +:107AC0007B298EBFD7CAFD61D7F5D82EA59DCA9E4A +:107AD00052C6300F66B8360E80A31EF484C1E8C7C4 +:107AE000867912C040C3F61ABE0F99D34AEDB2ABE5 +:107AF000992440BBF4A929C4CF129842FC65E03216 +:107B0000A660BE0BF33D4FED1EBF1BF601781FF0C4 +:107B10005C47767989359AC7BB413EF68D67F53C5F +:107B20007E991F4B7ACB102347CD5EF1566D77219E +:107B3000BC0DD283264F25FA34903FA2356AAC099A +:107B4000F1B4D8E624BF01E0F582DBD15FF98A9970 +:107B5000FB094AB97FF2E0F4898FA0BD3BF6191BFF +:107B6000F9920F2E067C26FEDECDED84BA1237CABE +:107B7000BD3FE7733937E6992FE97E44D776E6C0F3 +:107B8000F29EBAE74FBD8DF43247203BA3A32E8768 +:107B9000F365C69C98BFD9919FB39ACA93C030CE63 +:107BA000407A50561B711D00D766AA5F745FD67865 +:107BB000BA6F42F89BA0E6194978AE893DE5384591 +:107BC0002DB3ED544E28E0F9817F54F58376F53CD2 +:107BD0007FA7DA41DB54BA6953E9E6D72ADDAC095D +:107BE000F5876EE47433C2E8B82F0ACA23DC7692B4 +:107BF00033FB0B8ED2BA81FE258CE7A64C179BC7B0 +:107C000003DCC65802C4A74B40ECAD86FD4C29A846 +:107C1000A7FCC51217A37845F19C7A5A5F00634B05 +:107C200057A1DE542F886A3DF2C731B17E6A5F6C7E +:107C30006512F62FC97F7617E6E196BA003450CE6A +:107C40009D532F107C2A603C68BFABEE011AEF50A9 +:107C5000355FC7413BEFDF51C1243794D358FEEE67 +:107C6000157C9D4E8C871EAA7B7E17C17B0E87F7E5 +:107C700055270D3A7ACCF047EAE87AF496FEBAFA3C +:107C800091EB07E9CA039CA9BAF6B1F97A7A8F1C7D +:107C90003E4E57DF915F6240397B668E96DFC3FDB3 +:107CA000629A5D37E5199B01E1317796A8F9710D6C +:107CB0006C205A5D8CFCBE4DAA9EC85A8631CCDF22 +:107CC00078FC4E03E507AC99E3B162DEC3997623F5 +:107CD0009D178C4B7CE4D04E238D6B4DF10AE8C789 +:107CE000BC17E02C06E97F4D9A7C53FDEAB81E6371 +:107CF000D07AFACB0C33C6CEB56F53F1E901751DBE +:107D0000C0B7A798705E27C793D802663041FF01BD +:107D100073B89C0EA5CB76B5FFEFD4FEDB547CEC9C +:107D2000CA7F7C7524C2651E237D244F5CB63A024F +:107D3000D751C0881EDBFDBB2383F5C73FF636CE87 +:107D40009CCC3C1AC7CDF9E8E8D9822702CF7563ED +:107D5000E0F377E1F9F2578DABA361BD4F08AC1D9D +:107D6000294AE39F9AFE7DD5D74D543F7A1C9868E7 +:107D700050FFF2D7CDBCFD0426A3BFEB8FAADC6970 +:107D800052E9276D4B3AF917CFAC3793DDB3AD709D +:107D9000C9E63658EFC899773DF102E24BE15D7FC5 +:107DA0007941EED1F34B0A133B317F7FC42A3B4329 +:107DB000FEA0CD9BB6E5CB6C5AB7646488A74F6E26 +:107DC0007DB112C7FBDDB6488302E33FB9D948FC59 +:107DD000E5B27B1FD9BC9E9DEF8F29C9D7DBF9BFC8 +:107DE0005BB3EE89EDF8BEF6F9C78E05E5E974CC14 +:107DF000BA2709FDA6075755B7E5A6F5CE3F4BCCE8 +:107E0000CC85F1BBFC97BF7CEE1D98FF03D765E3E3 +:107E100082ED80CFA7727DE7E0AADAB65CB0534767 +:107E20008BEAFD15A37B35C263F44B0365D4DF8079 +:107E3000148C2E8065FE8C088302FBFBC067DC443B +:107E40007C60C69A343CCFEC270B769FC4733EA46B +:107E5000E27B2FFAC841F59CCE954D32C1DDFD8AFB +:107E600095DB378A9C44F6B1434E2A0ED2E70EDEEC +:107E7000A5C5971C9F201F2F2E8BA2B8B216771175 +:107E8000F3BF6D403EBF70524D9644EBD7C7F1072C +:107E900021FC3231CECBE3F56EB791515E106C0D03 +:107EA000E964A5389AF24D3E5CFA0B8AD7BBEB2DFC +:107EB000525A1CC50D9EC1722DF01DCB788AE3FA73 +:107EC0005068274DE37E84D3F33C8F98E5DEE1EFE5 +:107ED000BDC0F998D4F3097D9F348D9F8B07CF25C2 +:107EE0004D772EBBF19ED479E7126D25FCD2CE459D +:107EF0008C6EA2736156DB28CCFB88E72885FBD902 +:107F00008772A8F310F7977D50765BFD4A289F3A59 +:107F1000DB8F215D687195F2049E7F4047027CCB28 +:107F2000A4F68F57F56EE463A87797AB7197CE05EB +:107F30008CE22EDA78676AFB497CBC5B486F2EAF17 +:107F400001FA475912F52AE9170DC3787E44B9ADF5 +:107F50007B01E5AB0A0607C6CDE343F47A37ABA154 +:107F6000F5C6BF2F923FDF10B596FAC70378F0FE33 +:107F70002166E8B260BF1218AD984F42570DE52058 +:107F80003D4BCDD78DAF7D89EB4739D03351379FEE +:107F9000F003ADDFF3A9887CA0D62223DFC3DC2C5D +:107FA000E4DB04BF14C4A375D45FBA8949788F8316 +:107FB000294CC67B9A823A5FE8FA613CAE17827E12 +:107FC00086FB15EAF8FC1B67F27B206C279383ED98 +:107FD0001616BC9E61BAB2EA27D3974D09669D9CDE +:107FE000FAE06C49BF9A3EFC35A1FD0DB2B36FBFFC +:107FF0006F7590DD95DAD35ECB13D3E03CA8D672D3 +:108000005888EEBDDFB222E5E7D3804E6DCC99FDF6 +:1080100036C0C3F5BE48F2CE10B597E01188E0F047 +:1080200039A7CFCEE3FA2E68E7F5946F0DF20ECFA5 +:108030000FF3B44700BE33B73E4F409B578B2F75AD +:10804000AAFC38901258E00C038F46A4DF2CE4E71A +:10805000DF50BCBB1CF55BC0E5C0EA2F74F73F4E98 +:10806000164D69C47587E621687AA976AFB4D3CD79 +:10807000E56CA73B93F8CE19666F21FD3F94DF189E +:1080800019E57DAC14231DCDE4B7BB9BF2466ADD38 +:1080900016C902CF590EBD3F66F624BD3C28526278 +:1080A00043E485DEDF55EAD4C78986B7DD41FCEBC2 +:1080B0000CEA4DC4EFF87A8C6A5E9909EF978868EC +:1080C000AFBBE9B957E5CFEFAA7A6604F257781F3C +:1080D0008589E5808F7616A0723F44F96198D22E8B +:1080E00053BE632C53A83C80B9A8ACE54126321F8F +:1080F0003DB5FC962416A0F250D487442429999EBD +:10810000C3D00E19867A9EE35CBC87F22673522890 +:108110005E50C4944FB05D41E65724F70AAE67EA5B +:108120003DDC138B14287796B29E7BB9986792C773 +:1081300054E4FC7411DE3FEE9CAE958FF3F214DE36 +:10814000FECD3F7DF138DED305FEA5D67FC6EBCF51 +:10815000954F2E9A82659381CAEF637B280FC8538F +:10816000DE9A06E7FFC9344678E4C955DE092E0FCA +:10817000CF55F621DE68E5095395FDC1E59539CA6D +:108180007BC1E5C773948EE0FE5D79CA215ECFF3B3 +:1081900097DE37294968EFC2EFB7C2048E87F87BB4 +:1081A000C3E4FA04DB294F09042F0BF0ED66E2DB90 +:1081B0004E86740A6463C53C22E033E6DBA19E8DE3 +:1081C0003353BE9F21CA96DC973F3294BE0226B637 +:1081D0001DFD744546D717440F217C4F70FFE9AF52 +:1081E00098C703F4908D7A7E408D8704EAB83F40AB +:1081F000A313ED7DE87C17C27BA604F979537BC6F7 +:10820000ED6DFDA1787C40D5F70EAAFADEFBAA5FE2 +:10821000FADC7E03C698E3D61EFAEE9D7F1AD9F1EA +:1082200020FE79FE7E8F2E3071F921A1BCE88C08EA +:108230007F0FBBB7F5EDCF991A974FF95E43248AAC +:1082400033308DEF737ED3897F021F1CD34FB35F12 +:108250001D5684431A4B98310AE66DCD67A4BF7A48 +:10826000727717D3F70DCA4082C1BA8EAE38861422 +:10827000C78467B83DD192C468BDF6142902F5A53C +:1082800006956F5A58CCF4E1B8FE214692B7A1EB9F +:108290006E88F60918571CE48FE0FE8D38E68B8057 +:1082A0007106E53BF2296FC52D4AF9582E6385A367 +:1082B000A05CD926CAF930CE9EB6125605E3564DBB +:1082C000023E4719E93C9FA2BF8AC7632C8CF22D5E +:1082D000D60DB051BCDABB66E4AEC5C837134596BF +:1082E00006EDD31BC6E5A3DFD363EBDF9F624EEA47 +:1082F0007A3C36C79B780FC32D19F83D1249B162FD +:108300001EFAA615C67CE4E749CF8E8F1683E07F60 +:10831000D47B2A02F3DB1F930C54FF585DB6F5465D +:108320001BDE23F42B9467201D516C30EF0668137D +:108330000FE3DD5F7DA46504EB1D1FA2F3CD3A3C86 +:108340008D729843FCA07ABFA529443F28C957F3F2 +:108350003426B00978CE573C71D6847AEE429B4CD5 +:108360007EF4EC2681F25302BB1CC9784E47EF1B0A +:10837000497E736F93A8FAAD1DE4B70E24B164BCB7 +:108380005F53D122905E2C7ABFADC77E4347C98927 +:1083900038CED0F1DD89C1FEB2C7EEFA4504F25104 +:1083A0006F9941F573331A4796156B0AECFF53AF7B +:1083B000C0F3274C9280F798ED0F8A11B8AE2E13B8 +:1083C000F75334033FC5FBB9CD538AFBA443D3F71E +:1083D000B0CE20BBA5212E3512E7EDC15F85FCEBA9 +:1083E000C75A32293EB2B9299BF24142C7B9771523 +:1083F0006B47FBA46195959EE7D5273B931DD0FF66 +:10840000D3D6298D20A4D8A7BB9626E0FDA0C52DE4 +:10841000161611068F8FB54EA4F916E33D669CB76C +:10842000A5C88C72645ADB1433C2EDDE55CAB3C1E1 +:10843000F31416BBD6205D46B53C4B7862637E379D +:10844000C2F3DFAE519251BF3896C6C2E6493E90A4 +:10845000CFED8477AE71D27D924F93C2B75B97CF49 +:10846000F335A3A7CBFCFEB891BDBB04E05C01F4DF +:10847000540FAF8E36654623DE9AD83262521F946F +:1084800095B8D19E3B8D7A3BF0F3C6BBE6AEAF828A +:10849000760D778FD88FECE30A33D79BD99F45A20F +:1084A0000BD00B2B903EFF638E55F204F15FD41F6F +:1084B000155D7E1A971BA626D16F067E6EDA79FCB3 +:1084C0006F68EF20DE2A41784CBF09AA5DA0E66BF9 +:1084D000244C206D9C7E0D33E6FAFC0CE32E8BAC15 +:1084E000789EA17AFA797872DE3A82C6473D37974C +:1084F000291141EB0096E0277FB98BCF7BAE9D5AC7 +:108500006F0406F34390FE1E5AAFED63E47A3DBD5F +:10851000BE93CFF542806F9FF1BACB7CFA7E9FE588 +:10852000333AB7D1A2B2FB38CAD97522E5558F5973 +:10853000C7E3FF678630F213F5369EC67FF1671CEE +:10854000A8C211E0DA18574CE7D95B3FB3EF80922D +:1085500032B6C73EBC2C41BF2EADDD67E7F6751BBA +:108560008BE4FA603BDA67161FF0BDB1F83CA0A0BF +:10857000FC1EB56985D4D7BE43F919FE6458EF6275 +:10858000F5C864C035E40F9FAE17543D84250C9F99 +:1085900040571749FE607F2588FF015FE1797B3EE8 +:1085A00081E0D3DC7A74F3BDE487B13B782B7E5E47 +:1085B00063992607791E90764F9061686A604F7CB8 +:1085C0004A83E3C9DFAE7EFA097875E2A9E55FE385 +:1085D000D332A0321AE1794FDC9C6B13A1DD58B382 +:1085E0002F01F9E9129FE53CBCB36AF89282F7F3D8 +:1085F000F4F59684A0F5C37FCD3B9E585F89726ADF +:1086000087D581A9E1885F6E1D7C02A9F85D9CAECB +:10861000BBFE95EEE7474AA716507E7B9D85EE751B +:1086200085C27789CA07987A5F43A3A78896910C79 +:10863000FD8B4754BBE9C85AB053A1DC586796F18B +:10864000BB065D8E222521CC78E63A33FF6E4EB014 +:108650009D98DAB34F6DFC2E37F74336C2F84218B7 +:108660007FDF85C6DB53A48C990EF8BFB7C879F9B4 +:10867000F42CCC6F5A44FBADDD5ED7F536B4B97738 +:10868000A02B03EB8FAC1D36414047A451A6FB7EC7 +:108690005EEF73244F5AF03B3E60CFB7B41B2350BC +:1086A000FF707B0D14BF6D698F8B1C8E72CA6608BC +:1086B0001B675D349DC3AB479E38A383F5A1E65C81 +:1086C000AE0F09CF94DD9F0AF0F21EE2798A9AFE7E +:1086D00021A97833C622117F96BC3CCFAD471FE25B +:1086E0007AF519D4AB515FCAAA9282E5534334FF9D +:1086F0000E4655AEC38DF730736C8CE4C750BCACDE +:10870000807E0B1BF34D4BC1EF643818E6E7F6078C +:10871000FD4706CC8E6FE3FA4EA4CDE650108F15C0 +:108720004E5756F81FC2337294C2701E63887E6122 +:108730000ED11FC490F282E97A7D42668E6884B3BE +:10874000FDBEBEF338347F2EE84D74CFCCCD00FE95 +:1087500088A756379D4F34181244CF8A22C70DEC94 +:10876000D1FBF13E1BF7AF48142F129446F2DB6F9A +:10877000CCE4FE8D44C6E35E83146ECF8F9DE4A6E9 +:1087800032D80F148762AFB248E4CBCB8A5CB723F0 +:108790007EA4001B40FBAF7F3A1388DC2F512F676C +:1087A000B5171757FACD6EEEFFF31A221D9BC3E0E3 +:1087B000FDAF0BB81F2E720FEC0DF5DBEBAD74BFE8 +:1087C000254F7CAA89F069BC81FCDA5E7640427E46 +:1087D000F2ABE95CDE1F2A72DE3F9DE2B2CE14846A +:1087E0007F82112C2A5076CDAA1F37E9F6D448D4BF +:1087F0008B3F4C7C91E0E106D8A5C17F9B6AE3FAF0 +:108800008F82F78FD6AE26B8CA03B89F4CBB771EAF +:108810002BF1FBFDCDCE536EBCDFBBA22095AFAFDD +:10882000C8382315CA43EB0202D2DD3D76651EEA45 +:10883000254DF273741E2919B201FD65838DEC4D2F +:10884000CB38C69E8EE1F5DAF7A31EB20FDC149C7E +:108850004F52ADEEFB2121BCBE725501DF67E70E22 +:1088600000643FB48F996A7FDB16933D7EAE0C7037 +:1088700043B8B8B9FDFCC274DB62F770B28B78BD47 +:10888000FB2ADE1EE3A5502FBDFD7E15DAE38FA681 +:10889000849FF74B75DE47DFEA7E04E358FF59CF2C +:1088A000E358BD9FB39F1980B76CB0B3647605F0F1 +:1088B000B9A5E679E1BE2373CD2CCE473A6DED0420 +:1088C0002F06F23CFA2ABA471FAAAF5A918E4E4B96 +:1088D0009BEB27CA9C8F644DA0ABFD1CF742C6BD25 +:1088E000B0DEEA4840FDD3B3B4BB01F98767D7D205 +:1088F0000FF15E7A799999F4D67263CDBFA31D64A6 +:10890000DCCBF35FF01B13880783801FE17DD36905 +:10891000D5FCFC164ADC5F2B3CF3B13307FDB18973 +:1089200046C24B4D8F1D6351DCE897DDA0E6B7339F +:1089300071483DDEF7320E16C9EF1B55077A2DEE52 +:108940002F97E7EB2AF03FE4439A9E6B4B37EAF20E +:108950007ACD2179BDC6903CE0AFA7AB79722A1FD2 +:10896000B2678DEF539F7A15EC605CE74EE043F8F9 +:10897000F4833D8CCFDD60AFE3F335B0D7D10FFE8C +:10898000C6AA51F47C739583DEBFBD6A123DAF4B1E +:108990000E98109FC91FCDBF33E717C8AFA7E19945 +:1089A00098966DC3EF76F0FA21331BFFD57D35D451 +:1089B000C7A9EDDDAEC5F49D3AADCCD62ECE4E277F +:1089C0003F38959B67342F46BFCFE652C53A03F038 +:1089D0006480C15981DF7960775A286E11BA9F0788 +:1089E0006768723CBC1DCFF013067A3FCEC0197D7C +:1089F000F8711E12F83AAEDAFBFE16A48F7E4546D9 +:108A000027E27172AA3E7EB07206D7F35E579FC905 +:108A10006FBB86F6755F5FA38FDEEA3D3B0005FA0C +:108A2000F55EEFB5B36BB1DE13139EAE06AA74D537 +:108A3000EBF8366E4FB219406F83B11C6A1F0628DF +:108A4000BFE4746D8E9FC8ED27D35B7712D25B575E +:108A50008CAF1EEDC4AE5D4BD7E3774244A4372400 +:108A60000BA4378C7F68F456CBCF6321D21BFC3923 +:108A7000ADEE3D670ED26302A72FE1999DCB291F72 +:108A8000E32E9E47A3D15B8C9A2F1F25B593BD483B +:108A90001FE6C07E407B1B04BCC773FC634AFE100C +:108AA0000B1CAE7074F723E9AD6CC64FA3B77FBB48 +:108AB0002640F9139D294A02EA335EF5FB813F9671 +:108AC0000ECFCC3073B970B92F11C7D9A08E336DCA +:108AD000C861F2FF15581D22CAB37C99C3356F7C5B +:108AE000267D6FC8A7F6DBED5456CC80E780B9270A +:108AF000C9CF3BC0C0E9F7C1B7CD8B11EF931A0EB8 +:108B0000164D437CB943247D3B745F1F14AA713317 +:108B100081CF0B9A5762701CF11E952EE53B3A38B7 +:108B20009F8F61521AAC27C12D15E7635CE86A0379 +:108B30007D4FA45FD1C11894CFDA78707009986F17 +:108B400082AAAF75DCF9F408BF76D3401D3DB7E0CB +:108B50003E7AA3E70BF10FFB0C41E31394EFEB52CA +:108B6000EF49FE58BF6DAF7EC4CBC3FB25AB66712A +:108B7000BEE131F1FC0F682DE177019A8A5C4FE28A +:108B80007ECED3FF764A7E17EE637934F995138C47 +:108B90005CDFC36F24F2EFE5B809CE5AFC4DD31762 +:108BA0006585E7172517BBFE80E36E62F22E94679A +:108BB00036079B47F13590678817CB8A9417675023 +:108BC000FCE5D2F4C02F8B9457895FF7824F03AE38 +:108BD0005776F7856F538AFE63CF0F48FF65DC5FDA +:108BE000BAB0AC8672B306819D84EB9DAAE6677825 +:108BF00086F07ACDBFEA1DA0C54F9542CC9F8C561A +:108C0000E135C6E26415D0BF0BE530DEDFDB1BF0DB +:108C1000E3BD600BDE2393D08FCAA87F4CADE093F9 +:108C2000B1BFF8E5EB182F32E5D0E744189BC4ED4F +:108C300001EDFE8D94FBE3FC8D87353E318E8D4733 +:108C4000F8241BE40726C3FBCC87F33AF078B21E66 +:108C5000591C8BE272E2A68612FCDED6D2AD9F6E64 +:108C6000427FE8E47FB7303C0FD01FFDC6B0F95C0F +:108C7000FF303942743570563CD71353C2E3E9E3F1 +:108C8000B354FD13F1344E87A76C66783C25FDE79D +:108C900027E069E44C3D9E1684E06914CD7BE978B9 +:108CA0001A3B13F0F4559083B8AF17E72A0366F622 +:108CB0008197DF952A897DD507C507C8EE1BC12698 +:108CC0005983BF7BA83D5B515EF6919FD07FCD114C +:108CD000CA8FF3D49EA63CE52EDB917D6807FD4745 +:108CE000AD450EF66781FEAED3D75B40AEB8C19EF0 +:108CF000DC304B247EB2E70E8BFF3AD46BEBF87D71 +:108D000084F2BA4D02E67B0FAAAE115CC0DFE21519 +:108D1000301DA17F8C62E8F19FC07F57980E903E76 +:108D2000BB0EE4B19BD817BF97A6C9FF31969AB77F +:108D3000D04EF5FCCDE8588DE7CCA45DC88FA603D6 +:108D40003D617CF39A6E906F41E3BDB56312F9D536 +:108D5000AEFB1EE45F901F670A8C185CCEB126EA5A +:108D6000FAE54929BAFA690997E9EA35BAEF8C5167 +:108D7000E32A595B72117FC40A9EA7305DCED0B53D +:108D80005F57964DDF03B86232BF7F3773D464DD1F +:108D9000F8A17AC1D5F03FA47731440F08D513422A +:108DA000F5828533F5F740D71803D9C49F18CFABA8 +:108DB0001B7AF6DF880ED6C91CCFBD65A7281FC356 +:108DC00003F63FFA9B0607E597225D8C3507C83FFF +:108DD000B761BE95CE63C38E27E8BB119AFF0BE83F +:108DE00086E8686CB64479AEE9F65F537FB694CBFB +:108DF000D950BA14EA5E22FD6FE36CD81B7E6F6D0A +:108E0000760A977B3B03E48760779A19CA4DAF6473 +:108E1000A0BCB1DF08FE086118D2AF42F28925304C +:108E2000C94BF992EFF1EF2932E6589388A6BF4279 +:108E3000798D80F6DD6FA979B488B711F9CCB17A54 +:108E4000327EEF97D377FFF1FC7C6C0E5E96AEE638 +:108E500065CDDE8E49602D98173B18C783B671B576 +:108E60004CF2905FC34FF543F2D9010FCDCFFBC752 +:108E70005731671394C51A45F537BBD4F87A37C50F +:108E8000BD53054724FA3786894E8A7B473389E2EA +:108E9000E283580D3DA3043F671E97C847AE00000C +:108EA000A0BC603799E9FB19D94FDA187DDF68A9B2 +:108EB0007933E5650564F223DE7388DFC3DB60FF89 +:108EC00005C5099AF6F1FB04F724B93FC478E6A07A +:108ED0003A81BE132E56F33882F8A6E89806F5625A +:108EE0005D2B7D072EBEDA407EAD2BCC35BBE81C5A +:108EF000EEB6D0F7E3BAA03FFAB9D6D90D8CE81593 +:108F000098C7397F2AFCBAAE7152DCA2EB6FFD48DC +:108F1000DEB1103FA7C7C5F56F4F9C99E397EDD41D +:108F200027C8B71BE322E97EDCBC6B6BF6211FD997 +:108F3000F09EE858ADFA9FD1FF3F14FFC0FC03B389 +:108F40003305F54E7375783FA59939F767A1BFF4DE +:108F5000AE25097DE951BDC6456C06BF39FAE2E38D +:108F6000220DE53C0EA2AD53DB67A36DB95029E39A +:108F70005F3F312E52D64B5C24502320BF1F8AF511 +:108F800063113EDC6F7DA971919AC24B8B8B68FB9C +:108F90009EA5FE5D0088ADE677505C80CECDD0B357 +:108FA000BE20386EC1F595E35F327F8F7186D96A36 +:108FB00079DF5307BF44BFFEDEDFEE7E0A9FD79DF9 +:108FC0007DAC6C39E045D1243BF97BF7FF32E641BB +:108FD0003E9C3E7E30CB61D1F9EFF187F849EB1032 +:108FE000F8BDFCE0FAA29075651BF5F1805C9BBEB4 +:108FF000FDD4387D7DFE107DD9CC6A084F43F7BB88 +:109000003AEA6ECA936BBC8D39788678D079881726 +:109010002E9B8798C3EE4BC337E64821BA5FF73ED5 +:10902000A77BE72B2BDE5A4976AC81EECF9F9ED7EC +:1090300070CF3B32E28799B9699C7C05F1E8BBDFD0 +:10904000A7BF4B311DC9E5BE11DA57E6F0EF459DCC +:10905000174F50FDF9436B77B5E706C57BEF1DE869 +:10906000721400DE0CB59D12500F195AFB1AD5CFA1 +:109070009D9FD5271EA5D5EE69CF0DFAAE5F9AD17B +:1090800069403F465AED1BF4BE37BDC720BB79FE91 +:109090005E9959267B4BCD534B53F126AD8CFB5B30 +:1090A000A5542E6F3698B87C7343B57815FC5F5B7A +:1090B00068BE1BE7EB6726F17B1D0CB810F22B6D29 +:1090C000BC5079A6C9019BC2F5C8B4B287B85CD1BF +:1090D000F205DB42F3E25C73113E427523B5DB9887 +:1090E000A3B6DBC9F5533683492897619F61F344E2 +:1090F00017A87EDADEF2D398663FCE79F343CCCF61 +:10910000FBD1F6632FE35E971C087BDFF636D56E46 +:10911000ED8C082439B81F38ACFE3EA374EAAD05C7 +:109120007DE8AF98578B30EDD55EB8C4BCDA8D6A58 +:10913000BC488B976AF9B5CCE81B87DFF91C65FB47 +:10914000F30D1407ED25AFF61EBB2380F7DCBD152C +:10915000118ECDECD2FDEB5BA7737E5A5DC0E81992 +:109160001A5F085DF78602DEFE5091F3E1823EE26F +:109170000A5AFB0F13C3FBE3BE2DE4FB3F775F29C5 +:109180009FEB7D8A4961E1F240B57CF7D0F7600F33 +:109190003D89EBD0CAAEFA34F2DB794C1C6FDD327C +:1091A000FF9EA0A63FDA507F243DAA85EAA3ABB973 +:1091B0003EA9E959921AD708A527A08F3FE23C8221 +:1091C0008DD3ADA6279EA38FB9401F409743188F1C +:1091D0002B19D4BCD121569E827EA97AD4F9F6D31C +:1091E000F7F64BB29FEAB74690FD54BDF92DD4ABCC +:1091F000D6D5723F61A7BDE62DFCFE81FB3D91F403 +:10920000A6DEFA6B76D447857A3B0AE38A888FF12B +:10921000369F205F8E7654C0E482F595A31D65C30A +:10922000BC555700E1166A4F75DDFD05E5BB82BDF3 +:1092300079B820EB1FC01F42FC4B8DD3393EEF1A8B +:109240007E8AFC26622DB7F7C45A1E0F3596F1B8F8 +:109250008551E17E1433C82374056A7E940D0EBDDA +:109260001FA52B89FB51E2736BFCA8079A26592492 +:1092700085E423F7AB6879ED632CBEB7F03E862713 +:10928000C3C8300F1D1455B2032D6A7C03FF410B78 +:1092900094579ADF24346FDA16E22709F5A358674A +:1092A000E9FD268F0AF2BD93619EE7D7E7BD83688B +:1092B000FB878D8BA3D06FF292AF61A6EA37791846 +:1092C000D7B3E343EE37E9DAC1ED22172A305785E9 +:1092D000C3BFF3E254E407B966DFE12AF483687E92 +:1092E000A8F86A151E6ADC07E18BF014F3393C63B9 +:1092F00042E0E91DA2C58554780EE0F02D2F709252 +:10930000DF4942784A3DF0D4FC54DEBDEDF47D6D7A +:10931000CB1D16D94DF0FC92EC5513C213E1FF138F +:10932000FD50E342E039EEE1CC07F03BC1E31F29F9 +:10933000E9C0E7844DB7C5DE00CF495B1F28C127D0 +:109340007B93C709FE7316E75798D91D4C8F636747 +:10935000C8BA3883064F0D0F7BFC778CFCB1E51241 +:10936000F7E797AB789886700BF6E739F470DBA0D7 +:10937000E64B1A736BDC68EF0E0D819B86871E84AB +:109380001BF2BB18B3EC26FF5D9D80F6506F78385A +:10939000B4EDC7E1E1FC59AA3DAFC2EDB9F599F7CB +:1093A00022BC5ED858F20E3E5FF4DD1685F0DABEC0 +:1093B000E58199BDC02D3198CFEF991E1E6E5B8B54 +:1093C0005DD5B3E0FD750E9F91F82CE01BDABD9BD7 +:1093D0009BC659F5F1198D3FE65BC3C98F0BFB970F +:1093E00096535EA1A76C39F1C7AE73FCB1DB8E79E1 +:1093F0008817CB1F2D85FCBE7D79ED77AF5F077099 +:10940000CDA93D4CF46704FAA373AB3B6C50F33128 +:109410005804C88BF832E6C7F8F12066F545099480 +:109420009F407CD38B79CEF881D2503F85F4C65FC4 +:1094300005220E261812808F63EED4152407EF9FA5 +:109440001586CFAE2B3390FF67B3EA1F944B9D2D4B +:10945000D84E8B6F2D2B525A67FD347FE1C3D85FF6 +:10946000F31776C6B073FE35FC3E784EED2601F359 +:109470005006D5DD4AF221BE4C61281FB266CAFCF7 +:109480007BB3B912EDF77C7F5B770EDA099D78A389 +:109490003D83F0E077384F67EDE38407572CE5FE16 +:1094A00091CEDAD3B1E1F1A036E2D2FC8C9B757299 +:1094B000D25BCBBF63D26957DE4CFB11783042C51B +:1094C000034D4EA2BC417C3296051E463FF620C09D +:1094D00087881494979C1F8BA0FF44C17EC45EFCB8 +:1094E0008F1A3D74C1DA2CFDF09E70683E400DADC0 +:1094F000FB7459B67F621FEBBBE83C00352EE95187 +:10950000E3920B6B79FE6AE71DDFE5E17A4F978105 +:109510007D0070D95CE660787ED340B10AD882E7DE +:10952000392F6F358074ACC521B578FED662E7114E +:109530003CD7EB00A712FA635EAF1AEF19A27E07C1 +:109540003A04FF01CF3FC77130DE837240F3A3338B +:10955000D41BED88DFCA17583FD65C9328117EBB19 +:10956000BA71FC753BEEA4FC851EFF20CF87FBC9BA +:10957000FEAD6833E5576AFE2DAF9DFBB72A5880D4 +:10958000FE9D3C8A2320DF6EB5D0F71AAA04D98C41 +:10959000EFF717BB8C85A4F738291FD635C72A915A +:1095A0001F6CE9B644E417E58D22C9EBDEEC92F3BB +:1095B000E9EC47F21995EE2E81CF0C2EBC383E9384 +:1095C00054A8E733C9853F217EB67E969EBFA0DEB4 +:1095D000590FF3E4A8F4746EDF6A1C1FE3571119E6 +:1095E00041FAA8BADF503A3A4F2FFDBF8FAE66223C +:1095F0009CC3D0D5ACC21F4757A58503FAA4ABB90D +:10960000857ABAFA1996FF17D2D5CF691F17A02B02 +:109610006321D3E749C7F2EF3C8F8935F03CCBFF9C +:10962000C379D25FCDE4FE8BD03C69C66AA85C00EA +:109630006743E7A3960BC73319E34C964DAFAD1DB7 +:109640002DF3F182FD9D2CC4CFC942FC9AA1FA5D95 +:10965000183FA8CEEFB9F789BFEC1D0D7F3EF9F496 +:109660007F915EBB6FAA40F7C90B477EB71375D0D9 +:10967000A23595EA3C7DFB3DFFD97E4EFC05FB55AE +:1096800043F7D51875B77A6FE0C7F93999E356FAF9 +:10969000BEF9BA1AE640B85FC8EFB9AE8EE74D6BB7 +:1096A00079CDCE57AA1E2C1DCFF3E9D0EF19EAEFE2 +:1096B000D4F2953DB64AD2F38F2856EE8F0DF1774E +:1096C00056C6CAB7D03DC6F3FD9DEF16FE03FC9DFE +:1096D000930A64FE5DC610BF677CBEF261611F7EA7 +:1096E000B3CE1807437E9763F30918AF656733C994 +:1096F000AF33C816A0EF6B95D74E213DF06491EBC8 +:10970000535CA731B7FBAB97C653BE8103870AE50D +:10971000CBA0671E2FFC27FA09FE597E3E5F01F79A +:10972000735DECFD791FC23BAB8F7BF472E0912837 +:1097300078FF68BD9DBEAFB552D5A33B4DDD492D29 +:1097400050BFFFAE13BBD13FE16B3330BCDF76B10E +:10975000FEA3860BE8C5E610FB68C339BDD8F7D673 +:10976000C420BDB86155FE8E6361C6D1F4E29B662C +:10977000EBF5E2721BD78BCB6DDD26B40FCAE3BECF +:109780007F1DF34E8DD5AC1DE5E220A586F4E17872 +:1097900089513EF1FF8FCBB37F685CBE78B63E2E19 +:1097A0003F56CD47411E8FDFFFE9D2FCA893B8DEBC +:1097B000B0C6C8ED15AF02EFC2C4D143E3F243CF48 +:1097C0003E4371F975DBAD748F6FC38E663EDE1458 +:1097D00026619E792253F5B502EE2F0DD53F1E3539 +:1097E00029D694F188EF06BA4F88F704C92FB2DD65 +:1097F000BA09FD4DE9769ECF6DDEFFF256B73148CE +:109800003F043D94F4E2B2007D97A95C7230E23BE4 +:109810007193FC141FAF1308BF46CCE6F4B330D7E6 +:1098200047FAE1A03249E0F7C4DCDC8E4FE671E78D +:1098300048C42F682A8EE2715FE980E8C0B8F37DE2 +:10984000D87432DE5F65FC7B15930DF4EF50AC13DA +:10985000BA13902FB70A4A223E4167A27B8F4FC7A7 +:109860002803F1DF93F22419E8DF93DA93D7988085 +:10987000EB6BAA6F4D40BD70CD6C1E4769CD3B4E62 +:10988000F90FA674D00753E819F6DF1D9DEB14D429 +:10989000BCC0F604FA1E026BF990F06A9499F17F4D +:1098A000E7C7E15F84F474CC46FAC2AF041FBF2758 +:1098B00064B7D27DBC96CBCC8955B09E66BB99B4BB +:1098C00009EF65530FA4C0FBE6015234C601BC2961 +:1098D000A912FA8FBC318D6FA21FA439259561BEE4 +:1098E0007F53D9048A9F379D0506033D3DA347EC6E +:1098F000CF82F76B84007D37C83DD9C0309FB0ED73 +:10990000B2A989C1F7324529544E3A482E88B2810E +:10991000EEF9896A3C5B3C2F9EAD8F4F7F3F9BEFFA +:109920005B662DF3E81E689C59C2FD965F56FC21CC +:10993000DD738B33535E50B989F1EF7E5CC6E85C12 +:1099400042E1E759A58F2B186DFAF5ADC1C034E59A +:10995000619F5D82F8D18030A53CEEAF96205F6AB2 +:1099600038577F92D747F0F2CED94797A01C941969 +:10997000FFF7491A46F1BCCBF201C5C487CB4D8134 +:10998000B0DFF9BDD07A64E653D4F1D8FFE4786B48 +:109990002E33CFF3A55F78BC9E7301F5F912C6D5BF +:1099A000DA858E1BDAEF7FAA7D6FFBFC68F6B9FBC8 +:1099B000719407412AA27A9F0DF564A3CA0F3DD97D +:1099C000137C7E19F9819BD3458C419767FBDFA6F9 +:1099D000F2D6B800800000001F8B080000000000D5 +:1099E000000BCD3B0D545CD599DF9BF7E6CD10669F +:1099F000E00D0CC910093E082831045F1288A04907 +:109A000079046240A94EF809B825E944A346DBB3BE +:109A10009DBAD6923DD932094320989009A9256E66 +:109A20006D8BA9D9B5B547A9DBEDAA47BB9398F5CE +:109A3000F81FDA5AAB7B3C16539BDDF6B83DF42792 +:109A4000969ED336FB7DDF7D0F6626432069F69C0C +:109A50009D1C72E7BE77EF77EFFDFE7FEE9C3B87A4 +:109A60009F5A8073562B6B2A9865C09F73607DD672 +:109A7000E0736AF93FD0FD0B0114FAE6C047DD4DF3 +:109A8000F1A24AF1BC25404370BE1B4003889F935E +:109A9000F0A9050F5FBD74AE182014C4877902AC1D +:109AA000B67006EE4FBB56C7EFF4039C4538B9C6F7 +:109AB0000C1CDE47113040B0C763FF5A35FCEE9DE9 +:109AC000B4EE35601CD367C62BD6BA571F51216E32 +:109AD000CFC7BFCF5AEBFEB4AB353BE499396F6AC1 +:109AE000BB6C3479DE8774065C27E283D163F83D72 +:109AF000FA6E4CE24D3C837FB8DFE84A6D74109FEC +:109B00003F688FF3E2B822315FC7FD66C0CC47598A +:109B1000C878B05E428903E7EFBBBAE2519AFFF022 +:109B2000E3C3DFFA363E3EF29D3DBFA4764149C510 +:109B30005035C2CB341C86403B044A900E4EFA8608 +:109B400078F47CEAC814A21FFBC978DA5B7E678CC4 +:109B5000C99748471C7FC77EC9D4703D97C77354C7 +:109B6000A6FDB92593F62B1F5EC4FB0F6C4FA6FB19 +:109B70008864BE1DC0F19103121CC37E8691B00E95 +:109B8000FEA905C9E39B09BF55D44B18871B3F2885 +:109B900041E7581A7C3F1874303D886E9184FD1F50 +:109BA00072EAB7105E0FED932182200FED74012C45 +:109BB00006F846F0DFEFDE5D02F0853E27E37D64C8 +:109BC0009D3A2AE1FB11AFB6B993FA4B1CC6511D61 +:109BD0000463E2B90EAEB88ACF65AF3778ABCEEB8F +:109BE000C5D6A9F9E0A1719381A097F9E88D2AE281 +:109BF000A3B765E6A3D4FDA7F2DD5C7C5618CCB113 +:109C0000F0300AC115C89EB279E20CEE0FAE763084 +:109C1000FF2CBFDAC1FB3B5B8003A4D9F9B0AF07CF +:109C200017B87A866F548BEE7BFD2DA708FC6CF37A +:109C3000D4D171B3A882D685F05839F27320797FD8 +:109C4000F6B8926979F83B5850C9723726E3595DE6 +:109C5000A371132AA81D37256CCB1EBD5FBB90BC1A +:109C6000B820017E11C1053E7FAAFC3A21C448DC20 +:109C70009359781B9DBF6FA30AB29406DF73F40F4C +:109C8000EDBCDB24FA473E0F4629EA096720992FED +:109C9000832F9430FFC80332B8A444FE6A34895E2F +:109CA0005FBAD539AD7FDCB61E23BA1B45E0C07D57 +:109CB0001D7E4B66BE391CDCFB0B99E4BB51D525E0 +:109CC000DC7F46ECEE87DAF1FDA1D765631087777C +:109CD0003FB3EB67AF627BBABA788D544C44322302 +:109CE000DB71FCE9F56E63D010F2378D97626E4C34 +:109CF000F79A99F50E5517F37A515C4FBA001F2861 +:109D00008DEA0744875478D3FABAFBF858C3EA04BB +:109D1000B95A187A2188E71BF2E0263CF4FE24BFEA +:109D2000874AE4CBFCD9D7418C325E7E465F71DC3A +:109D30005F5ACD9304A7A9B42A9249E7826C207C8C +:109D40007CE8356EF4E190F79D86DB289F99DF1B58 +:109D50007342BC9CF080EB62DB0C135B5A88EF4BC8 +:109D60009CAC3F64FF4A7EBEDD1B541CB8AFFF0CA9 +:109D700016F37AF6FC26F8B2721FBEBFD639DA4067 +:109D8000FC11DD0E5A04A76CF3C614EA6FA00DE2B5 +:109D9000C21BF53A7711C26D7C9E1602A8F50DFB29 +:109DA000C90E553C77A42044EB47CC1F95219E7DDE +:109DB0000255B0DC351EACC7F9BD6FC8C61E7EA209 +:109DC0001D0FE17C252003D1497A6A6D6002F7A35B +:109DD00078CEBC075900EB26011A12F8A976CA0DF5 +:109DE0000D097AAE0E2127F6EBDDF949E337684518 +:109DF00049EF65308D38D277636059D2386F55A5F9 +:109E000046FB6DD257263DBFB9AC26693E3428A724 +:109E100027B0BF16FF11DD65107D5BAE3CE5D84F66 +:109E200098AF40421FDFFF25E8F59FC9C4CE75708B +:109E30001DC94F33189D241F68BC8D63889785CF3B +:109E4000B92732C9909826DB75C9E2CFAA4D454C97 +:109E50001FC973C641F87F0461C8C81715DA848327 +:109E6000E804DA98C4CF516F0C22B2038AC9E3D058 +:109E7000C069511C77056A6F0DFBDE00C4A8BF04E2 +:109E8000623C1E3FB1C335C8166E313FAB058C83B3 +:109E9000F83EB33C2249D8CF69044346781E635C40 +:109EA000A27D6A385F5E492C19E77E41238CF73228 +:109EB0007C730FCDCFEF06AD2F9FF997DF8F7641E3 +:109EC00084F6F32818E092091FA890969216097359 +:109ED0007B25E839A487BE09C62AEA97C204EB2588 +:109EE00034EF12F517C19826947D9CF5374C28BEA7 +:109EF000336EA1FFD3C9CD8CFC2870C6A60B0EBE55 +:109F0000FF56B37C13EAC1CDB7555DD0DF50BA5FC1 +:109F10004C92DFBB37E98C77A57B23CB8BD2FD122C +:109F2000BF1FD814BC6E133E2755E05E75F1F8AF25 +:109F300050053EA31218E8CB40F4D99B02DBC85F62 +:109F400079D66D94B2C8233E892FAADD93AFD48809 +:109F5000F9440F3FD283F09D530E12E16009D10105 +:109F60009FAB48877D4CC718C32D0C83B1DB5A9734 +:109F7000FAF94807A2CB28680B08AF72F8E2E8C0EC +:109F80001F84B3E81937FB470AD165E965A1CBA760 +:109F9000098F174B97547AC0AE5C809AB9F5E95790 +:109FA000A57886B494C882F4C1F348481FC26700FC +:109FB000043DD0AE1B84A774F8A77E4625E87BB885 +:109FC0002FC6133D233533FC9F8DFC2FFA42BE7CF8 +:109FD0004807D11774F293BC603F101CE3F939DBDA +:109FE0002178209FE86132F26CBBEC8249F66B8BE2 +:109FF0002583E9B55446070DFB9952DC727E46D99C +:10A00000AE6781C6F4590C616EFDCEC9E3E7485FC7 +:10A010007B1CA391226A9FAEA3757A9B51C390CA01 +:10A02000F70ED7315FDE035A29F25DA16AB2FE2E28 +:10A03000BC4631227A22BEF608BF49378F90BD292F +:10A04000747861B07266DDA8D308C4905EA7BC675F +:10A050004E84F0F9827CB4EFC60C9E4F3BC5F908E4 +:10A06000A67C05C983908F4035EEC577BE7E0B2850 +:10A07000826F3D3B107F888FADF402F1240DFC1BF5 +:10A080003F7FA45EE8BBCF6E0A3D4EFC42FA89F1E9 +:10A09000678246FA493380F5A6438FB09F7076C039 +:10A0A000A5139F426CC424BF629BB5CEB601D707EF +:10A0B0005256C239A3AE243BEED083D9CCCF86040E +:10A0C000E41FCC77DEA5F23F74E7CDCB0FA87B6A07 +:10A0D0006DF644F9ECE354928FDCC479824EAA3FCA +:10A0E000C47E874A72923B371C678AFF62C371063F +:10A0F000820CC769FB2F64B7909E77A1DD1A447C60 +:10A100007FDA448788F972F23FC89EDF1ECE62BFB5 +:10A110008B5184E3EE8849A383C88F774258253E4C +:10A1200095A02442F4DB1A91D87F2BDEB73D8BFD3E +:10A130000568D0083F52FC06F9DCF28BC0A385A766 +:10A14000ADF15F3A752FE1D50B3F4F88B7ECF7BF04 +:10A15000EB5A7AAA4A27A5ED2923FA665AF445B59F +:10A160001D790DF7E9FC53360C6AE4177FE98D5A27 +:10A17000DC5FDF8F6583E2B34C10F1D50210763CD3 +:10A1800093E47429F1CB58FC33C46FDDD91A9DD701 +:10A190001E07D6B80884D83FCE443D40701D99FBB9 +:10A1A000993F33B354DDF6B721F11C6E89FD608F02 +:10A1B000A572F3D4789CE42B0FFDD8DDC9F02511EE +:10A1C000CF03C7437C0EE9FCF55758FE3ABEAA3BC5 +:10A1D000370FFF3ED57F87C47890C663DC194FC028 +:10A1E000EBB4BC587266EFDBE35193E525659E4DF9 +:10A1F0008F72A7E08FC5187FEDC6FD0E0C1CAD2336 +:10A200007D3392073A469AD0BFF59F248AB3D693FE +:10A210002E26FBD300A3144778401F2CC3BEB3C027 +:10A22000C3FCB3E8BF83F1CF209CBBAB5D9A8E38F3 +:10A2300059FC91A9D5E1FBBB0ADC8689F48D5AE370 +:10A24000230DE86789E5DF26BFF44E6BBF4C0B9406 +:10A2500043B3A588F95DF1B5ED7D8DE2DEC532C869 +:10A26000A4D7E42E83ECD39D1830E4A2EB0E5F76E6 +:10A27000B2DF87FE1D9FC7D590ECF7DDF58833A9C7 +:10A28000EF4CF1136B5B92FDC0A616E075693FB908 +:10A29000ABFE7AF8E0F1B3FE5CA18C3BB43476D52A +:10A2A000C6BFF49487F1FF421EE295F32441F37395 +:10A2B000D877211E895F11235955882793BEEAE478 +:10A2C000277FEF3E1AEF3A8BFC4BE3654FC3E788DD +:10A2D0000E57587802B12F13FFD1BE53FD61578A34 +:10A2E0003F9CBA6F9B0E77D8F859036B083FE89FE5 +:10A2F000B37F609F2BF53CCF637CDE80BCF4831E74 +:10A3000037B7F11E8DDB133D016E4FF6E8D0808E1E +:10A31000D54B3D65DCBEDC63F0F3577BAAB9B5F1E4 +:10A32000319BBEF1E639D85F38B4CBC17902A55C68 +:10A330007BE56AE2DBB764561F1AE819CA52B643D6 +:10A34000A0E0B82B1B955193CE62C53F8B2C3E5B92 +:10A35000EE9A3CEEC279B17C30F6D044B4DBDB2B14 +:10A3600067E29F75938E1939018A771624E50BEA07 +:10A370002037A95FEFBE2269FC066D69D27B9BBEC8 +:10A38000DFA81372B331B03C69FCA186F5F1BBC9FB +:10A39000AFAF7169946F68D25727BDBFB9EC8624FF +:10A3A0007820371BA4A773BA12E8C6E74FA6ABBA4A +:10A3B000E3C271904DE7D11439988DBEA97C6BE34F +:10A3C00035671AAF22AE8C525CA9D3B9CBA56D0804 +:10A3D0006A68DA2F3181F24BF6BA4A35C69715977B +:10A3E0003FBECCA2F8B2285D7CF921E76DE68C2F48 +:10A3F0001B93E3CBAC14BCCD155FBE7A89F8DC5A55 +:10A4000028F26E39AFCBEC07CA8D61B67FB9E3B2E3 +:10A41000B191424FCB1FF392CCE3B8AD552AFB97D5 +:10A420008760220022AF984FF630B7DCC8277DF353 +:10A43000A4CF5C781BC5F94D0EE3284E79B1EE2B05 +:10A4400001F23BF6ED7E34804609FEA7C5C1FA2E27 +:10A450005677660BC995A2A31F27716B8EA6F14F85 +:10A46000ECF176BEF1E016916F3C68E51B0F5AEBFC +:10A470002042D8DE8E54897CE3AF5B742BFF17E15A +:10A48000FCE2E12D6BAC7C23F657D07083EDF8A095 +:10A49000D730EF20FEF9850722F8E880A4654964EB +:10A4A0002FB63834CA1F8F34AE7A97F249FB3CAAD4 +:10A4B00041021FF5ADC927FE92B7A2DB83FDE1C6BD +:10A4C000E19769BE52EAE07E74CB559C171CC9D354 +:10A4D0009A8A29CEDB504C9806F9993FF5505E23B5 +:10A4E000EA3B13A0F9BDD78BF9B3D12735FF2F93E2 +:10A4F00026A6F8ADC41157118EFCFC993F13BCF38E +:10A50000F2F3297EC5A04FE5BC6DFE8FF77E2B527E +:10A5100042AADCE47CF308CA3CE169EB96966C8ABB +:10A52000A7B63A27F2D2D90B3BFF39ED6FFA93FD6C +:10A530008454F8FCB1F36B0ED1D5EDBC2D7EA2B7DF +:10A54000DC381A27BC41ACB198E25E8FB0CBB3E1E6 +:10A5500041F15CB80E22776798190978B0EB1DD7E6 +:10A56000B68A3CB8D1AADB79C6A47A89D2E8E07968 +:10A57000B67EB0F3E3A975127B1F35AD224F7BFD8C +:10A580000CBCA4BA89BC56B5E0191C17A7E6B3E702 +:10A59000AAA3CC95CF6EB6CE73B175937B5B81E7E2 +:10A5A000FD7FCD7FDFDBFA7F93FF3EBF5E34CAF2D3 +:10A5B00003CF4CFE9CE43BBA6CA13E28EA4349F52C +:10A5C0009CD43ACE60868033BC52F8A9C3563FB2C1 +:10A5D00042C04DADEF6458799548EB521187812107 +:10A5E00088AC9885C4171EE5BB110DF96181E71091 +:10A5F000F8B075F9B745A8AD2DD487AA715FC3CB64 +:10A600001C6CC786BDA147FB480F2DF3A4958F8313 +:10A61000AD422F0E10DF72FC04A683E44EB2850417 +:10A62000420EA4D708733EC0D1569FC86769B1EAED +:10A63000DB118F5F25BEC8E3F3F0FC54F85F3B1FCE +:10A64000FE63C4AF510B38C1D98670BED93A5D479D +:10A650008CD07BB7B59E5B8F5593BFF058AB26F47B +:10A66000B0B2D2A0F30FFBD2AFF798B59EE9084B7A +:10A67000346E5197980F6E31EFA034D9795AD09338 +:10A68000E589D6A7F79946B27E48859B5176E17A4F +:10A69000D9D3D3FB4F8E870E48E9F7F9634B0E6B86 +:10A6A0000B81ED11F1C59E347C912AEF2AE53F1113 +:10A6B000EE098B0EB6DEF128E3EB332BC9BE83D156 +:10A6C000CB883DCEE7DD93790BC7C97D378B3C87BF +:10A6D000AA08BD5DD089606AA8BED210E1BAE1FDCA +:10A6E000A0B97CE7E3E162E33DB2379184F93FB181 +:10A6F000F823B52E18A3BA20F9B15417A4FE4E576B +:10A70000673ABBFD6E8BD3B2BFE9EB3B47A8BE8374 +:10A71000F38F545BF59DA0A8EFD43DF508ECC4F78A +:10A72000BF331DECB74ED7771A8AD7480E9623A0B1 +:10A73000FAF47CEB3BB18679D67782175DDFF9635B +:10A740002BE2E79047D459A6EB3B6DFE79E5757493 +:10A7500088C5BB49AF7401E3C1DB340C3B299F10B2 +:10A760001071C6892A97E0AF9D92159F4103D87A50 +:10A770000A3FCD5DFAC3B9645FDE714129BE5FFF58 +:10A78000C4EB0AF587F31D6B287EBE569D78F05A00 +:10A790007ABFC6C9FAA30E29194FE28FB8CBC145BB +:10A7A000F0886AB5B268E312B5F5EECC247DBD4100 +:10A7B0004B8E3F86A64EC8D9C49F1A1812E279A8BC +:10A7C000CE30B349F71813BDF47C68836E0CEAE40D +:10A7D0000F27C729434DAAD0A745C2EE0C1FD71F8C +:10A7E00026FFAABF3B83FDCF03050E71EE1218258D +:10A7F0007E68D293E39AE1B1E27D2524673127E7B1 +:10A80000CBBF3326C66FDFBD7294E252CDF257B78D +:10A81000E7AF673F14FAC4B89BCB96A79C7F5C2335 +:10A82000BE88ED7402E1BFBFE0F601CA877E1075F5 +:10A83000AE2671196AD3997F6DBA6DEBBB93EB4469 +:10A840007D2A70DD74688BCAFC3F94F7C1913B4848 +:10A850004FE72D603C8F6C51F34309F270A2CDC5D8 +:10A86000F41ED922FC8B3C0784C6D2BC3FD126F40F +:10A87000D027EF013E4F16DA651D1FE94A38EE2258 +:10A880007C1400FC231D27F0E1437CFE460794E284 +:10A890001687FD5DECBFA5F2D9785B69525CEBAA27 +:10A8A0007624E1D1E90A8639CF7D33E8A4AF1A1ABC +:10A8B000B14FF17D970AC46FAEC0FD7CCE1CEC6732 +:10A8C00060DFDD188B28D87797845693DFFAE2CEC5 +:10A8D0008E01CAB3B8FC0E8DF8CDD57557B095C6AC +:10A8E000573A2103DFF7812E05689F1109485FEB76 +:10A8F000106A247F7D38E0D0286FD31C6DDF41EBD8 +:10A9000037FB1700D1796B9383D73B6BAA9CB4CAF2 +:10A91000234783F25F0B3D6C77DF77861FEEC0F134 +:10A92000EF23BD223073AE5D6DC54CA70C3D397E63 +:10A9300076438CEDF05A73BC8BD6595BAD52450310 +:10A940004ED49C3942FEFA4895CB70E1BE466A244B +:10A95000C6F7C755CE51BAE7F003755CA6757FF010 +:10A9600031F246513AF9BDB0DCA48E1FAA6E7113C4 +:10A970003FEC458A107E22530EB65FA9E3FE6CD1F0 +:10A980007F2FE285F01CC1FD96525C34897285D020 +:10A990007D53C1C7EFC076559BC2E3BE90EF885090 +:10A9A0005DA8BF496539E9F78606E8FE4F3FF23BEF +:10A9B000C743FE10F3F370BE9FE5D05E67B86673C1 +:10A9C00019F1CB1B5519ECB757B535DE4B7EFB7A29 +:10A9D000F9A37F798AE2A70295E9D9EF0CC65F2532 +:10A9E000BE6E12FEE2C9250FB0DCF575DD0E8437B0 +:10A9F0008884DFA1BA555F650DC3B7F30DC34B441F +:10AA00003EA9CF7F5F84F21BF16A915F30F38E72B3 +:10AA10003ECFCE2BD5597A6CB92BFC4A29CDBB47FA +:10AA2000117561B9204AFAC04579259AA724E7BB78 +:10AA3000D64D26C7C18B53E2E0D43C13B8C74B5A5E +:10AA4000D19E3ED986F1F17298CE2BD111588E2B22 +:10AA50005D1C2F8E548B3828E60CE76BE5E7CBF1B5 +:10AA60009B961F3CDEE3460E00F8518FC6FD2CF38B +:10AA700037BB7311D45B3D017E7EEBDA47A5C47909 +:10AA80004395ED6E9DF5C64480E0A6EA8B543E5892 +:10AA9000DBB6C0B20F26107D872681F1EBAD5915CC +:10AAA000273E3DFB7BE038F4130DE31E283E7F7EFE +:10AAB0009CF6E9A2FC97D8E749DAA78BF25F627FA0 +:10AAC0002FF7E8DCBEDA53C6ED827610797E5B1F85 +:10AAD0005C89FA00F1D65020FA24FF648773FCB732 +:10AAE0000789BF5C014523F97617C4E252823E18FC +:10AAF000F186DF25BBDC9FE761FE4BDDD7AFDA1CBB +:10AB0000D6B9C2B711DC21844B787F71E77F3DB4A1 +:10AB100094D6794B66BECAE9DABC83F50EEA850C99 +:10AB2000F637843E8CE57938EF30B2B354A2FB504F +:10AB30005B770B47774EB9C7754671DE09D4D7D41A +:10AB4000EF4739A7F3F4D77CF0195AE7E33F2EE03B +:10AB5000FB4D235BDE66B97F030390DCCB28F7B6A1 +:10AB60009CC5DE5AFC6D117F073B9E11E7673D389F +:10AB7000E21D8FD1F9FB7F22433ABC5D2A5DC19C67 +:10AB80009F1F32AA4C1E3FE74F53373445DDB07745 +:10AB9000EC7BDC8F34039462FFEB4ED34D7CF0F5FD +:10ABA000DD8E0BD60DBFBEFBC275C3D12F3BC0A53A +:10ABB000CDECE30A98E03C2B85F05407ECA357D882 +:10ABC00066B787AE6E673F52D415F51ACA39505F23 +:10ABD0005B40FEF3C026B38CDFFB73D8EE0794B165 +:10ABE00038D9F500D5CB75BABF10E1BA27E567E9CA +:10ABF000FE42EAF97B9D13EBF97C3884EA95A9F5CE +:10AC000049C9F37D51DF5F2AEA90767DB2429D38D3 +:10AC1000FA20E1E93637E3A1F7D9EBDFA1FA975D36 +:10AC2000C70F5875606D0768BBC539CC76F2FB9FBE +:10AC300017F550B81ECFB192169928DEB482EB9B5F +:10AC40001BE81C73ED7FBE75C3664BBF2173F33DDC +:10AC5000C89F59F8B4C7FD4DBB90C76B5591B786D7 +:10AC60002C95F5FCFA273C2093BFEC558F929C6CF9 +:10AC700083890D244FBD3EE1B7450F39D96FFB5491 +:10AC8000BBCE74CD534DBEBF90F7F719C66E0413FB +:10AC90003DAE65511EE92FADE6A7DA791FB1B616B4 +:10ACA000DAC780CCFAEEFDD20D7C8FA949CA66794D +:10ACB0005434B330515FEE6A4F7F1FA9B670B2852E +:10ACC000D7F73A80E2AD6886F1B24EF87E4161B8BE +:10ACD0004D20EE2BC1764D1AC073F67A4E337D6A45 +:10ACE0004B5D2B493FED6A17715BD49B3EAE7BA059 +:10ACF0005DC49F852DA12F101D6E82C97AD26F2849 +:10AD0000DA4684EFB588786D17E94B11EFEE72AC37 +:10AD100099C96BBDE40CEDA2F39ADF11FE842B20E0 +:10AD2000FC7A8CD4381F74ACC5FC0782DB4C7C5E8B +:10AD3000C98A0A8EAD3C7F1F519B2EED662FC13B09 +:10AD40006CE9E70ACDE4BA6B05388C5E7F425D5D45 +:10AD50009F5F5D5DD2BE2FEAE937083E86E723821A +:10AD60000FD78346F284FC7798D6B3EF97543CB75D +:10AD7000A388EB2E9758DF3ED5627E95E0BDB829BB +:10AD8000F8353AF7FB3B3B80E1CDF3BE466D6138C9 +:10AD900010443AF56708BFF9C93AA3339890FF7990 +:10ADA000D3A2D79B165D97233B8D8B7B6F6CC7AF70 +:10ADB000826A37D12B157E5F0F8C511D68B6F5D591 +:10ADC0007DF7B9294FDC5BB0DE4DF7D1A29EF5D9F6 +:10ADD000D4EF2F3003B47E5F4FE3B31F96121F09E9 +:10ADE000BE8F2C11F98818EAE748429EF4C576997F +:10ADF000F7555F0071CAA7BB3CC22F7261BCA8AFF8 +:10AE000020BFB99AED393E1FA3D4C16B963CC9A6A9 +:10AE10000126DD172C0089F0853A727A3E99BCFA3A +:10AE20008230D0BE66832337E07C8A470B34F643FA +:10AE30007EDDAE313E7DA663268E87F9E3EBD01C26 +:10AE4000F8CA99035FD37C6DC95D2A9ECE109E8897 +:10AE50004F7C0FF0B9E04FF52C672E547854CFFF9C +:10AE6000C8C68BC7849097C37F89F013A50B36E5BE +:10AE700033F8455F91F12B6B619EE72A3020B48255 +:10AE8000F0A149848FD4F3573CF77803E1ED956D39 +:10AE900042AFD62A96FE08E359903F6FB2D605CB53 +:10AEA0002E356508BBD30C3FF488BCB6E0D30A74DA +:10AEB000C7DD39E7EB57BB7D72967BD74F6ECE105F +:10AEC000FE903EC6FABDB751C0F77A851F7A74600E +:10AED00015FB0F37E6972E48D48F97BB4E985A171D +:10AEE0009CAB0E38C337A69BF6F93BEDBE085D95CB +:10AEF0009B8D3F1E24FE7192DCB8B93DEF7D613021 +:10AF000060905C2D31238074DBEB0B07887FFA8E19 +:10AF1000EF7C87EA24CAEBB241FEA6A20481C6DD1B +:10AF2000981766F9D8586002D5951EEC31BF9B087A +:10AF3000F7969650F966A45BA63666121C0FC423DA +:10AF4000648F6ECA35C3C13474A8DE2CF4C7B196C1 +:10AF5000E02A9A574BBA7315C0C39BCCD5D49FAF88 +:10AF6000BE3A5F9E1ADDA4F72F5D9E5ADC74BEFECA +:10AF70008220DFD3EAFFA14C1ED6F4B87E4B9EFAA6 +:10AF8000973C00A104B90A6E4ED13B7E4BEFF84DC1 +:10AF9000968BCD9B752B0F1C64F970923C9527E81E +:10AFA00019BFAD674C9647C56FCB93257F244F1EC5 +:10AFB000BA1F3C594F7E4A1F887B8CA9F2156E0937 +:10AFC0006DD94C762CEFB7AD45FACCFD4F5D17F23D +:10AFD000D45F60F1FB92A799FFCF22FFD365E15EBA +:10AFE0004F7112BFDBEDDA2919E2488A755312B7A7 +:10AFF0009F98CAE4B6762A835B732A97DBBA291F27 +:10B00000B7EBA7AEE0B67E2A9FDB8629E4FBD5C866 +:10B01000FF5345DCDE38B59CDB8D53CBB86D9C5AB5 +:10B02000CDE39AA656727BD3D40DDCDE3C5523D6F5 +:10B03000A19A504E5AFEA772D665E07F2342F5D101 +:10B04000BEE3F7BC43F8716A2AE751A2BE355CEF54 +:10B05000712A61E6FFA30542BF6FF408FAA4F2FF6C +:10B06000B196D0FE74FC0F4E716F4BA17B5B95ECDB +:10B07000E70C337F9FE7EFBEF447CA83A2FF7198C6 +:10B08000DF5FA2FD9FF62B1726FB95FD79C97E6534 +:10B09000DF12DBAF748D521D6CBBA4F33DB1532D99 +:10B0A000A17FE6F521B88DDE87DADC1AF95351DF8E +:10B0B0008D010FF6B7EE9581F27DE85F7C8BF80C81 +:10B0C000503F90DD98AFBC3EBCC9D2EFD6F80A38ED +:10B0D000ED085F847FF23E7DAD395FEE679B67CB05 +:10B0E000FD55509691CECEE638EB85DC6B42EEA353 +:10B0F00005C101CAB74453E4DEB6A3888724B93F2B +:10B1000065CBBD25C7397E71EF2387E41EF9EA2799 +:10B110009BC579D1DF4EB2A38A35DED928EA5BF52B +:10B120007EA1579546A12F142DD98E22DFBC4B74DA +:10B130004995F78822FCE3A6D27F9DB667645773D2 +:10B14000FC3E291B97D67E3F11A13CD6716529CBC9 +:10B1500077AA1C45B555CCE7C7957A4827FFF396E3 +:10B16000239F6D474CB623A9E36C79EA3BDEC47894 +:10B17000B1EDCA713CB799604F366A020F684F3E15 +:10B1800026FE4A95A7DA4233144CB34FB543F8A5CF +:10B19000AFAD0B0A7F11FD44F253A2CEF47E80DAEC +:10B1A00021FC9F9C46EBF7153A8473510F3636C647 +:10B1B000EBA98681F2AC7620BC75E6442FC960AF5E +:10B1C00067D84FFB47F97475FC15F2F9D126E117E2 +:10B1D00042772EFB2D763B17DFDBFE8ECDFFA9E3FA +:10B1E0009E2C323BD3E1E5F3165E8E0E3C9DC41FD0 +:10B1F00043CAD29B0C3DAD5E358DCBA257E7E757D6 +:10B200001C473BC77A7576BFE2BA8E347C309B5FB1 +:10B21000F1890E91CF45BF621DCDAB2D177EC5E7DD +:10B220003BE0F2FA0B35F731BE2ED55FD86CF1DF7B +:10B230006CFE425787AD37C2AC375C96DEB8587F9C +:10B24000218D7F703BF32F4CCA54FF43541B221FA8 +:10B2500022F408EA99BBE83DC6F1EC2F1CF5087E04 +:10B26000312D3D736D7B7007E175A85AF80B974B34 +:10B270000ED0EFBBAF236FFEF230DF71A58FAD1D97 +:10B2800098203F07BC31BA37DD4BF795287E7CCF3D +:10B290002BEE11009451DEFF8BF23506D9B991CC1B +:10B2A0002F7D83C6774714A07B83433D22FFF7C5DC +:10B2B000055947017967C8197E6AC2CFBF770D1E4D +:10B2C000C5F60F1985A39070EFF6B0256F2ED8C282 +:10B2D000F774B3B45B9EFD3037DDFEC4FD5CBABAD3 +:10B2E000728E7FD751A0F13D320B3F596A10227EFA +:10B2F000922307D747D0DB83EA84BC475F4D5727AB +:10B30000C7C1F922EF25837286F2EF03B49638178E +:10B310009FB37FB1FB513A970E218677D0EFE0BC07 +:10B320007BFF5A11EFF47BC26E2D8DDED8D7937C54 +:10B33000FF28B595973D16A33BC287038A4169CF85 +:10B34000C1B2CA26CA4F4635AE0083EA7304D3D5CC +:10B35000A7C72DF9D4C1607BAC7CB2253B9DBDB0A5 +:10B36000DB010BFF76DF5D326612DFA94566907F59 +:10B3700087E3F34B9184BCF11316FCBD9211AF45EA +:10B3800064EDF50AFDEFD66326FDDEB82FEF2EAE95 +:10B3900033BAF5089CA1E72531F839E9A77C77E7AE +:10B3A000689A7DBCD521E294BDCE10AFB7375FE17E +:10B3B000FAE3DEA2F4F9ACE73B441E49F5AD0F72A7 +:10B3C0005EDFA7709D3875DC53169FF4AB6640E3D3 +:10B3D000B8FA81323A577409708E72EC9D379FD853 +:10B3E0008DFDFD3D41CE7B0C51FE0385B5BFF05E6A +:10B3F000C6FBFE6B1C1A9D6383FC11DF47385C0D96 +:10B4000006E98FEC6A1C9710471E86D101BA0F77A8 +:10B41000782D70BED46B0493DEF723038E93FFA5C3 +:10B420004CB03E734237D7010EF855BEA73354795E +:10B430009AFD231DC6394F315429E865D793FC1670 +:10B440003FFAFD773527CAC1018B6E0F52DE9CEFA4 +:10B45000318D41A2FF75A0709CEDF38175E39D5481 +:10B4600017CCF2BB0D0A45F6D70481E474A8CA9143 +:10B47000F67ED450D569DE67EA7E9C277EC9FA2F16 +:10B480004B99E0FC4456D96FD9AE3C64ED63E35A66 +:10B49000E0CD66570B3D9BDD1606FA7D58DE5BF26C +:10B4A000A88EFDDD85BF8A38493E6E0358A4D37E41 +:10B4B0002778BF879B9F8EF3FEACFBBA203FCFF768 +:10B4C000712128E4D7BE77BDB04D4D8ADFB352EE6F +:10B4D0004565A6F441EEBAE07DB2EEF7EE3975327D +:10B4E00001DEA2CEE4FBD973CDFF43CF8E5327916B +:10B4F0005F0E575E58BE0E59758D584F35D3C9E64D +:10B50000339BEFB2E88839B3CF1FF28D75A6B3C372 +:10B510001D9D420E52F93195FF34D718DBF143EBF4 +:10B5200092E1DCD029E4F8060B4E4EA19E4FEFEDE0 +:10B530007B4C747FEAE934EB7EBA53E5F1337C6DE2 +:10B54000DBF9772ECDCE2F6B1176DEBF2A83EC3C54 +:10B55000E2F365BAC7F67B940F4890EB3E6FB29F5B +:10B5600069DBF9C73B457CF062DE5512D9E91CCF97 +:10B5700004FBBF59D5C97980543BAD3A431C37AA67 +:10B58000F9AAAD6FB89EF55AC7FB4F4410CEFEF82E +:10B590003EAE0F6522FF66484CA7483A3A4179F221 +:10B5A000BD9AF24E10BF63D3855EC85AAB70BD63BF +:10B5B000C8F15EF587D82AB130042DB883CCB7FB2B +:10B5C000C7F97E8EC5F773D1933E7F5A63FD2E85F2 +:10B5D000EA88F56F56A78B2BEC96EE4F25DF77BFE9 +:10B5E00038B9F8FB4EABBE9C0119422E9A1D7D6402 +:10B5F000EF9B1D7C2F85AEEF2A6BACD201D5F56990 +:10B6000067F8DE4FF77F24AB5EB474465EE0567198 +:10B61000AFE5EC0E714F867F47B8947EF739C1BF16 +:10B620000FBC926EB1CAEC07B3DC9C850207D583D0 +:10B6300023272469DA0FBA82AE341A0E9A570241D0 +:10B640006E53F77D1584F97919C4B8BD06C6B82DB7 +:10B6500087716E2B60925B9326E07E8D93A2AEB1D4 +:10B660000A0C999E574290DB3510E6B61A62DC7ED2 +:10B67000A5FE6F7F733B4EF9DA797811784D23DFA1 +:10B6800071043A7D7E1BCFAD9D3AF3C95CF4EEF3B5 +:10B690004DB01F5F5F3DCE7EA8D71364FE76FA05DE +:10B6A0007FDB709CB3E4836D3F49253F69751AFECB +:10B6B0009DC34F4AFD1DC9FF0229F7D0B3D04500F5 +:10B6C0000000000000000000000000180000000062 +:10B6D000000000000000004000000000000000002A +:10B6E0000000002800000000000000000000001022 +:10B6F000000000000000000000000020000000002A +:10B700000000000000000010000000000000000029 +:10B710000000000800000000000000000000000021 +:10B7200000000000000000000000003900000000E0 +:10B7300000000000000000380000000000000000D1 +:10B7400000000000000000000000000000000008F1 +:10B7500000000000000000000000000000000000E9 +:10B76000000000000000000C0000000000000000CD +:10B770000000000E000000000000000000000004B7 +:10B7800000000000000000000000001800000000A1 +:10B79000000000000000001C00000000000000008D +:10B7A0000000001C0000000000000000000000136A +:10B7B00000000000000000000000003A000000004F +:10B7C0000000000000000001000000000000000078 +:10B7D0000000000200000000000000000000000166 +:10B7E0000000000000000000000000100000000049 +:10B7F00000000000000000500000000000000000F9 +:10B800000000000000000000000000000000000335 +:10B810000000000000000000000000AB000000007D +:10B820000000000000000008000000000000000010 +:10B830000000C00000100000000000080000C00868 +:10B8400000100000000000020000C0000010000016 +:10B850000000001000009FB0000000000000000881 +:10B860000000C08000100000000000040000C0883C +:10B8700000100000000000020000C0800010000066 +:10B8800000000010000091200000000000000008EF +:10B8900000009340000100040000000100009348F4 +:10B8A00000000000000000020000935000000000B3 +:10B8B0000000000800009354000000000000000297 +:10B8C00000009418000000000000000800009358D9 +:10B8D000000800000000000800009AB000400000CE +:10B8E00000000040000093980008000000000008DD +:10B8F000000093D800080000000000080000942019 +:10B9000000C8000000000098000095B000980000FA +:10B9100000000028000095F00098000000000028BA +:10B920000000C480054000300000054000009D205C +:10B93000000800000000000100009D210008000038 +:10B9400000000001000020080010000000000010AE +:10B9500000002000000000000000000800009CD84B +:10B96000000800000000000200009D180000000018 +:10B9700000000001000000010000000000000000C5 +:10B9800000000009000000000000000000000002AC +:10B9900000000000000000000000CF2000000000B8 +:10B9A000000000200000CF46000000000000000161 +:10B9B0000000600000200000000000200000730074 +:10B9C000000800000000000800009FA00000000028 +:10B9D0000000000100009FA800000000000000011E +:10B9E00000009F60000000000000001000009F6346 +:10B9F000000000000000000100009F610000000046 +:10BA00000000000100009F6600000000000000012F +:10BA100000009F67000000000000000000009F6819 +:10BA2000000000000000000400009F6C0000000007 +:10BA300000000004000000520000000000000000B0 +:10BA400000000003000000000000000000000003F0 +:10BA500000000000000000000000000500000000E1 +:10BA600000000000000000020000000000000000D4 +:10BA700000060000000000000000002000009F7091 +:10BA8000000000000000000100009F900000000086 +:10BA9000000000080000005300000000000000004B +:10BAA00000009F98000000000000000200009F9C22 +:10BAB000000000000000000100009F9D0000000049 +:10BAC000000000010000000900000000000000006C +:10BAD0000000000100000000000000000000004421 +:10BAE0000000000000000000000000010000000055 +:10BAF00000000000000000500000000000000000F6 +:10BB0000000000890000000000000000000012C8D2 +:10BB10000080000000000080000000010000000024 +:10BB2000000000000000A000071000000000071047 +:10BB300000001AC800000000000000080000AEC0AD +:10BB400000080000000000080000AE4000080000EF +:10BB5000000000080000AE8000080000000000089F +:10BB6000000020080010000000000010000020006D +:10BB700000000000000000080000A01007100040B6 +:10BB80000000004000001BF8000800000000000159 +:10BB900000001BF9000800000000000100001AD09E +:10BBA000000000000000000100001AD800000000A2 +:10BBB0000000000200001ADA00000000000000028D +:10BBC0008000000000000000000000000000AF0046 +:10BBD000000000000000002000001B78002800008A +:10BBE000000000040000E000002000000000002031 +:10BBF0000000F300000800000000000800001AF038 +:10BC0000000000000000010800001B3700000000D9 +:10BC10000000000100001B0F0000000000000001F8 +:10BC200000001B70000000000000000400001B74F6 +:10BC300000000000000000040000005000000000B0 +:10BC400000000000000000030000000000000000F1 +:10BC500000000005000000000000000000000006D9 +:10BC600000000000000000000000000700000000CD +:10BC70000000000000001BC80000000000000001E0 +:10BC800000001BE800000000000000080000005158 +:10BC9000000000000000000000001BD000000000B9 +:10BCA0000000000400001BD400000000000000049D +:10BCB00000001BD8000000000000000400001BDC96 +:10BCC00000000000000000080000B00000180000A4 +:10BCD000000000180000C00000400000000000400C +:10BCE0000000C00000400002000000010000C00190 +:10BCF00000400002000000000000E2000020000000 +:10BD0000000000200000E204000200080020000201 +:10BD10008000000000000000000000000000E200C1 +:10BD200000080020000000040000F40000280000CB +:10BD3000000000280000F540001000000000001086 +:10BD40000000F5C000200000000000200000F5C049 +:10BD500000020020000000020000F30000200000AC +:10BD6000000000200000200800100000000000106B +:10BD70000000200000000000000000080000110882 +:10BD80000008000000000008000011680008000022 +:10BD900000000008000011A80008000000000008D2 +:10BDA00000001240000800000000000100001241E5 +:10BDB0000008000000000001000040000020000416 +:10BDC00000000010000059000030001800000010B2 +:10BDD0000000590800300018000000020000570061 +:10BDE00000080000000000010000570100080000EA +:10BDF00000000001000011E8000000000000000148 +:10BE0000000011F00000000000000001000011F827 +:10BE100000000000000000100000124400080000B4 +:10BE2000000000040000400000200000000000208E +:10BE30000000530000100000000000100000153842 +:10BE400000000000000000010000000300000000EE +:10BE500000000000000000000000000000000000E2 +:10BE600000000001000000000000000000000004CD +:10BE700000000000000000000000150800000000A5 +:10BE8000000000010000152800000000000000086C +:10BE900000000050000000000000000000008308C7 +:10BEA0000080000000000080000000010000000091 +:10BEB000000000000000200800100000000000103A +:10BEC00000002000000000000000000800008410B6 +:10BED0000008000000000008000084700008000056 +:10BEE0000000000800060000046000280000046054 +:10BEF00000008520000800000000000100008521EE +:10BF000000080000000000018000000000000000A8 +:10BF10000000000000008408000000000000000194 +:10BF2000000084F40008000000000002000084F615 +:10BF3000000800000000000200008504001000005E +:10BF400000000004000087600000000000000020E6 +:10BF500000006000002000000000002000007300CE +:10BF600000080000000000080000000300000000BE +:10BF700000000000000000050000000000000000BC +:10BF800000000006000000000000000000000007A4 +:10BF90000000000000000000000088080000000011 +:10BFA00000000001000088280000000000000008D8 +:10BFB0000000005000000000000000000000881099 +:10BFC00000000000000000040000881400000000D1 +:10BFD00000000004000088180000000000000004B9 +:10BFE0000000881C00000000000000080000300075 +:10BFF0000040000000000008000030080040000081 +:10C00000000000280000339001C00010000000086C +:10C010000000320000200000000000200000372057 +:10C02000000000000000000800001020062000387A +:10C03000000000080000A000000000000000200038 +:10C0400000003EA9000000000000000100003EC802 +:10C05000000000000000000280000000000000005E +:10C060000000000000006000002000000000000848 +:10C070000000400000080000000000010000400136 +:10C08000000800000000000100004040000800041B +:10C0900000000002000040600008000400000004EE +:10C0A0000000400000080000000000040000400400 +:10C0B00000080000000000040000404000000000F4 +:10C0C00000000008000040480000000000000008D8 +:10C0D0000000800000000000000000100000504040 +:10C0E00000010004000000010000500000000000FA +:10C0F00000000020000050080010000000000004B4 +:10C100000000500C0010000000000001000052C7A9 +:10C110000000000000000001000052C60000000006 +:10C120000000000100003000003000180000000492 +:10C130000000300400300018000000040000300847 +:10C1400000300018000000020000300A0030001823 +:10C15000000000020000300C003000180000000158 +:10C160000000300D00300018000000010000300E0B +:10C1700000300018000000010000301000300018EE +:10C18000000000040000301400300018000000041B +:10C19000000050000100008000080004000050046E +:10C1A00001000080000800040000000A00000000F8 +:10C1B0000000000000005068010000800000000145 +:10C1C0000000506901000080000000010000506C78 +:10C1D00001000080000000020000506E010000809D +:10C1E0000000000200005070010000800000000408 +:10C1F0000000507401000080000000040000506640 +:10C200000100008000000002000050640100008076 +:10C2100000000001000050600100008000000002EA +:10C220000000506201000080000000020000505039 +:10C230000100008000000004000050540100008054 +:10C2400000000004000050580100008000000004BD +:10C250000000505C01000080000000040000507CE1 +:10C2600001000080000000010000507D01000080FE +:10C270000000000100004018001000000000000451 +:10C2800000004090001000000000000400004098F2 +:10C290000010000000000004000041100000000039 +:10C2A0000000000200004112000000000000000237 +:10C2B00000004114000000000000000200004116D0 +:10C2C00000000000000000020000604000080000C4 +:10C2D00000000002000060420008000000000002B0 +:10C2E00000006044000800000000000400006080BE +:10C2F0000008000000000008000060C000400008C6 +:10C3000000000008000060000008000000000002BB +:10C31000000060020008000000000001000060044E +:10C320000008000000000002000063400008000058 +:10C330000000000800006380000800000000000406 +:10C34000000063840008000000000001000063C0DA +:10C350000008000000000002000063C400080000A4 +:10C36000000000020000640000080000000000045B +:10C3700000007000001000000000000400007004C5 +:10C380000010000000000004000070080010000011 +:10C3900000000004000090000008000000000002FF +:10C3A000000090020008000000000001000090045E +:10C3B000000800000000000200009040000800009B +:10C3C000000000020000904400080000000000028D +:10C3D000000090460008000000000002000096489F +:10C3E0000008000000000008000090800008000025 +:10C3F000000000020000908400080000000000021D +:10C40000000096880008000000000008000080403E +:10C41000000800000000000100008041000800004A +:10C420000000000100008042000800000000000140 +:10C4300000008043000800000000000100008000B0 +:10C440000008000000000002000080020008000058 +:10C45000000000010000800400080000000000024D +:10C46000000080C00008000000000002000080C240 +:10C470000008000000000002000080C40008000066 +:10C4800000000002000080800008000000000001A1 +:10C490000000808100080000000000010000808290 +:10C4A0000008000000000001000080830008000078 +:10C4B000000000010000808400080000000000016E +:10C4C0000000808500080000000000010000808658 +:10C4D00000080000000000010000600000080000EB +:10C4E00000000002000060020008000000000001DF +:10C4F000000060040008000000000002000060422C +:10C5000000C00018000000020000604000C00018D9 +:10C51000000000020000604C00C00018000000088D +:10C520000000604400C000180000000800006057D0 +:10C5300000C00018000000010000605400C0001896 +:10C54000000000020000605600C00018000000015A +:10C55000000066400008000000000008000066803F +:10C560000008000000000008000066C0000800008D +:10C57000000000080000DA4200180000000000027D +:10C580000000DE4000000000000000000000E000AD +:10C5900000000000000000040000D0C00000000007 +:10C5A000000000040000D0C40000000000000004EF +:10C5B0000000D0C800000000000000040000D0CC43 +:10C5C00000000000000000040000D0D000000000C7 +:10C5D000000000040000D0D40000000000000004AF +:10C5E0000000D0D800000000000000040000D0C00F +:10C5F00000000000000000200000DB000000000040 +:10C60000000000040000DB000000000000000068E3 +:10C610000000B94800000000000000000000D00049 +:10C6200000000000000000040000B0C00000000096 +:10C63000000000040000B0C400000000000000047E +:10C640000000B0C800000000000000040000B0C0FE +:10C6500000000000000000100000D6B00000000044 +:10C66000000000040000D6B4000000000000000438 +:10C670000000D6B800000000000000040000D6BC96 +:10C6800000000000000000040000D6B00000000020 +:10C69000000000100000D348000000000000000867 +:10C6A0000000D358000000000000008000000010CF +:10C6B00000000000000000000000D358000000004F +:10C6C0000000000800000000060209000000000051 +:00000001FF -- cgit v1.2.3-58-ga151 From 3b7f817e47bb66ae4d82ed73689a521af70a5410 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Thu, 31 Mar 2011 17:04:01 -0700 Subject: bnx2x: don't write dcb/llfc fields in STORM memory We could get hardware attention during DCB/FCoE traffic without this fix. Signed-off-by: Dmitry Kravkov Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_cmn.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index ef37b98d6146..775fef031ad8 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h @@ -1041,12 +1041,23 @@ static inline void storm_memset_cmng(struct bnx2x *bp, struct cmng_struct_per_port *cmng, u8 port) { - size_t size = sizeof(struct cmng_struct_per_port); + size_t size = + sizeof(struct rate_shaping_vars_per_port) + + sizeof(struct fairness_vars_per_port) + + sizeof(struct safc_struct_per_port) + + sizeof(struct pfc_struct_per_port); u32 addr = BAR_XSTRORM_INTMEM + XSTORM_CMNG_PER_PORT_VARS_OFFSET(port); __storm_memset_struct(bp, addr, size, (u32 *)cmng); + + addr += size + 4 /* SKIP DCB+LLFC */; + size = sizeof(struct cmng_struct_per_port) - + size /* written */ - 4 /*skipped*/; + + __storm_memset_struct(bp, addr, size, + (u32 *)(cmng->traffic_type_to_priority_cos)); } /* HW Lock for shared dual port PHYs */ -- cgit v1.2.3-58-ga151 From fab0dc89f0d98459c6ce7fa27422949ac15837fa Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Thu, 31 Mar 2011 17:04:22 -0700 Subject: bnx2x, cnic: Disable iSCSI if DCBX negotiation is successful With current bnx2x firmware 6.2.9, iSCSI is not supported in DCB network, so we need to disable it. Add cnic command to disconnect iSCSI connections and prevent future connections when DCBX negotiation succeeds. Signed-off-by: Dmitry Kravkov Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_dcb.c | 22 +++++++++++++++ drivers/net/bnx2x/bnx2x_dcb.h | 8 ++++-- drivers/net/bnx2x/bnx2x_main.c | 5 ++++ drivers/net/cnic.c | 64 +++++++++++++++++++++++++++++------------- drivers/net/cnic.h | 1 + drivers/net/cnic_if.h | 6 ++-- 6 files changed, 83 insertions(+), 23 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c index 9a24d79c71d9..1214907d00d9 100644 --- a/drivers/net/bnx2x/bnx2x_dcb.c +++ b/drivers/net/bnx2x/bnx2x_dcb.c @@ -571,6 +571,28 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state) { switch (state) { case BNX2X_DCBX_STATE_NEG_RECEIVED: +#ifdef BCM_CNIC + if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) { + struct cnic_ops *c_ops; + struct cnic_eth_dev *cp = &bp->cnic_eth_dev; + bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG; + cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI_OOO; + cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI; + + rcu_read_lock(); + c_ops = rcu_dereference(bp->cnic_ops); + if (c_ops) { + bnx2x_cnic_notify(bp, CNIC_CTL_STOP_ISCSI_CMD); + rcu_read_unlock(); + return; + } + rcu_read_unlock(); + } + + /* fall through if no CNIC initialized */ + case BNX2X_DCBX_STATE_ISCSI_STOPPED: +#endif + { DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_NEG_RECEIVED\n"); #ifdef BCM_DCBNL diff --git a/drivers/net/bnx2x/bnx2x_dcb.h b/drivers/net/bnx2x/bnx2x_dcb.h index 71b8eda43bd0..1e14775a18cb 100644 --- a/drivers/net/bnx2x/bnx2x_dcb.h +++ b/drivers/net/bnx2x/bnx2x_dcb.h @@ -183,9 +183,13 @@ void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled); enum { BNX2X_DCBX_STATE_NEG_RECEIVED = 0x1, - BNX2X_DCBX_STATE_TX_PAUSED = 0x2, - BNX2X_DCBX_STATE_TX_RELEASED = 0x4 +#ifdef BCM_CNIC + BNX2X_DCBX_STATE_ISCSI_STOPPED, +#endif + BNX2X_DCBX_STATE_TX_PAUSED, + BNX2X_DCBX_STATE_TX_RELEASED }; + void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state); /* DCB netlink */ diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 32e64cc85d2c..f3cf88918a9e 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -10342,6 +10342,11 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl) break; } + case DRV_CTL_ISCSI_STOPPED_CMD: { + bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_ISCSI_STOPPED); + break; + } + default: BNX2X_ERR("unknown command %x\n", ctl->cmd); rc = -EINVAL; diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 8cca60e43444..5dfbff06631c 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -2966,31 +2966,36 @@ static int cnic_service_bnx2x(void *data, void *status_blk) return 0; } -static void cnic_ulp_stop(struct cnic_dev *dev) +static void cnic_ulp_stop_one(struct cnic_local *cp, int if_type) { - struct cnic_local *cp = dev->cnic_priv; - int if_type; - - cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); + struct cnic_ulp_ops *ulp_ops; - for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) { - struct cnic_ulp_ops *ulp_ops; + if (if_type == CNIC_ULP_ISCSI) + cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); - mutex_lock(&cnic_lock); - ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type], - lockdep_is_held(&cnic_lock)); - if (!ulp_ops) { - mutex_unlock(&cnic_lock); - continue; - } - set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); + mutex_lock(&cnic_lock); + ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type], + lockdep_is_held(&cnic_lock)); + if (!ulp_ops) { mutex_unlock(&cnic_lock); + return; + } + set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); + mutex_unlock(&cnic_lock); - if (test_and_clear_bit(ULP_F_START, &cp->ulp_flags[if_type])) - ulp_ops->cnic_stop(cp->ulp_handle[if_type]); + if (test_and_clear_bit(ULP_F_START, &cp->ulp_flags[if_type])) + ulp_ops->cnic_stop(cp->ulp_handle[if_type]); - clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); - } + clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); +} + +static void cnic_ulp_stop(struct cnic_dev *dev) +{ + struct cnic_local *cp = dev->cnic_priv; + int if_type; + + for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) + cnic_ulp_stop_one(cp, if_type); } static void cnic_ulp_start(struct cnic_dev *dev) @@ -3039,6 +3044,12 @@ static int cnic_ctl(void *data, struct cnic_ctl_info *info) cnic_put(dev); break; + case CNIC_CTL_STOP_ISCSI_CMD: { + struct cnic_local *cp = dev->cnic_priv; + set_bit(CNIC_LCL_FL_STOP_ISCSI, &cp->cnic_local_flags); + queue_delayed_work(cnic_wq, &cp->delete_task, 0); + break; + } case CNIC_CTL_COMPLETION_CMD: { u32 cid = BNX2X_SW_CID(info->data.comp.cid); u32 l5_cid; @@ -3562,8 +3573,12 @@ static void cnic_init_csk_state(struct cnic_sock *csk) static int cnic_cm_connect(struct cnic_sock *csk, struct cnic_sockaddr *saddr) { + struct cnic_local *cp = csk->dev->cnic_priv; int err = 0; + if (cp->ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI) + return -EOPNOTSUPP; + if (!cnic_in_use(csk)) return -EINVAL; @@ -3965,6 +3980,17 @@ static void cnic_delete_task(struct work_struct *work) cp = container_of(work, struct cnic_local, delete_task.work); dev = cp->dev; + if (test_and_clear_bit(CNIC_LCL_FL_STOP_ISCSI, &cp->cnic_local_flags)) { + struct drv_ctl_info info; + + rtnl_lock(); + cnic_ulp_stop_one(cp, CNIC_ULP_ISCSI); + rtnl_unlock(); + + info.cmd = DRV_CTL_ISCSI_STOPPED_CMD; + cp->ethdev->drv_ctl(dev->netdev, &info); + } + for (i = 0; i < cp->max_cid_space; i++) { struct cnic_context *ctx = &cp->ctx_tbl[i]; diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h index 4456260c653c..3367a6d3a774 100644 --- a/drivers/net/cnic.h +++ b/drivers/net/cnic.h @@ -226,6 +226,7 @@ struct cnic_local { #define CNIC_LCL_FL_KWQ_INIT 0x0 #define CNIC_LCL_FL_L2_WAIT 0x1 #define CNIC_LCL_FL_RINGS_INITED 0x2 +#define CNIC_LCL_FL_STOP_ISCSI 0x4 struct cnic_dev *dev; diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h index e01b49ee3591..fdd8e46a9050 100644 --- a/drivers/net/cnic_if.h +++ b/drivers/net/cnic_if.h @@ -12,8 +12,8 @@ #ifndef CNIC_IF_H #define CNIC_IF_H -#define CNIC_MODULE_VERSION "2.2.13" -#define CNIC_MODULE_RELDATE "Jan 31, 2011" +#define CNIC_MODULE_VERSION "2.2.14" +#define CNIC_MODULE_RELDATE "Mar 30, 2011" #define CNIC_ULP_RDMA 0 #define CNIC_ULP_ISCSI 1 @@ -85,6 +85,7 @@ struct kcqe { #define CNIC_CTL_STOP_CMD 1 #define CNIC_CTL_START_CMD 2 #define CNIC_CTL_COMPLETION_CMD 3 +#define CNIC_CTL_STOP_ISCSI_CMD 4 #define DRV_CTL_IO_WR_CMD 0x101 #define DRV_CTL_IO_RD_CMD 0x102 @@ -94,6 +95,7 @@ struct kcqe { #define DRV_CTL_START_L2_CMD 0x106 #define DRV_CTL_STOP_L2_CMD 0x107 #define DRV_CTL_RET_L2_SPQ_CREDIT_CMD 0x10c +#define DRV_CTL_ISCSI_STOPPED_CMD 0x10d struct cnic_ctl_completion { u32 cid; -- cgit v1.2.3-58-ga151 From 9b12c75bf4d58dd85c987ee7b6a4356fdc7c1222 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 31 Mar 2011 18:03:35 -0700 Subject: net: Order ports in same order as addresses in flow objects. For consistency. Signed-off-by: David S. Miller --- include/net/flow.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/net/flow.h b/include/net/flow.h index 37e77d66f78c..c6d5fe5ec1bf 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -26,8 +26,8 @@ struct flowi_common { union flowi_uli { struct { - __be16 sport; __be16 dport; + __be16 sport; } ports; struct { @@ -36,8 +36,8 @@ union flowi_uli { } icmpt; struct { - __le16 sport; __le16 dport; + __le16 sport; } dnports; __be32 spi; @@ -86,8 +86,8 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif, fl4->flowi4_secid = 0; fl4->daddr = daddr; fl4->saddr = saddr; - fl4->fl4_sport = sport; fl4->fl4_dport = dport; + fl4->fl4_sport = sport; } -- cgit v1.2.3-58-ga151 From ab3cf6d0f3d2daeef2101a2a97b6c0beee6b70cf Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 1 Apr 2011 22:20:06 +0100 Subject: sfc: Move test of rx_checksum_enabled from nic.c to rx.c This is preparation for using the generic netdev features interface, and should have no effect in itself. Signed-off-by: Ben Hutchings --- drivers/net/sfc/nic.c | 6 ++---- drivers/net/sfc/rx.c | 3 +++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c index e8396614daf3..2594f39c3ba4 100644 --- a/drivers/net/sfc/nic.c +++ b/drivers/net/sfc/nic.c @@ -850,7 +850,6 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event) unsigned expected_ptr; bool rx_ev_pkt_ok, discard = false, checksummed; struct efx_rx_queue *rx_queue; - struct efx_nic *efx = channel->efx; /* Basic packet information */ rx_ev_byte_cnt = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_BYTE_CNT); @@ -873,9 +872,8 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event) * UDP/IP, then we can rely on the hardware checksum. */ checksummed = - likely(efx->rx_checksum_enabled) && - (rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP || - rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP); + rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP || + rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP; } else { efx_handle_rx_not_ok(rx_queue, event, &rx_ev_pkt_ok, &discard); checksummed = false; diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index c0fdb59030fb..fb402c52aaff 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c @@ -605,6 +605,9 @@ void __efx_rx_packet(struct efx_channel *channel, skb_record_rx_queue(skb, channel->channel); } + if (unlikely(!efx->rx_checksum_enabled)) + checksummed = false; + if (likely(checksummed || rx_buf->is_page)) { efx_rx_packet_gro(channel, rx_buf, eh, checksummed); return; -- cgit v1.2.3-58-ga151 From 98e778c9aa4f4f75550fa3a31358304e4ce67b96 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 31 Mar 2011 01:01:35 +0000 Subject: virtio_net: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 82dba5aaf423..0cb0b0632672 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -710,17 +710,6 @@ static int virtnet_close(struct net_device *dev) return 0; } -static int virtnet_set_tx_csum(struct net_device *dev, u32 data) -{ - struct virtnet_info *vi = netdev_priv(dev); - struct virtio_device *vdev = vi->vdev; - - if (data && !virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) - return -ENOSYS; - - return ethtool_op_set_tx_hw_csum(dev, data); -} - static void virtnet_set_rx_mode(struct net_device *dev) { struct virtnet_info *vi = netdev_priv(dev); @@ -822,10 +811,6 @@ static void virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) } static const struct ethtool_ops virtnet_ethtool_ops = { - .set_tx_csum = virtnet_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, - .set_ufo = ethtool_op_set_ufo, .get_link = ethtool_op_get_link, }; @@ -912,22 +897,29 @@ static int virtnet_probe(struct virtio_device *vdev) SET_NETDEV_DEV(dev, &vdev->dev); /* Do we support "hardware" checksums? */ - if (csum && virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) { + if (virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) { /* This opens up the world of extra features. */ - dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; - if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { - dev->features |= NETIF_F_TSO | NETIF_F_UFO + dev->hw_features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; + if (csum) + dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; + + if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { + dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO | NETIF_F_TSO_ECN | NETIF_F_TSO6; } /* Individual feature bits: what can host handle? */ - if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO4)) - dev->features |= NETIF_F_TSO; - if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO6)) - dev->features |= NETIF_F_TSO6; - if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN)) - dev->features |= NETIF_F_TSO_ECN; - if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO)) - dev->features |= NETIF_F_UFO; + if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO4)) + dev->hw_features |= NETIF_F_TSO; + if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO6)) + dev->hw_features |= NETIF_F_TSO6; + if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN)) + dev->hw_features |= NETIF_F_TSO_ECN; + if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO)) + dev->hw_features |= NETIF_F_UFO; + + if (gso) + dev->features |= dev->hw_features & (NETIF_F_ALL_TSO|NETIF_F_UFO); + /* (!csum && gso) case will be fixed by register_netdev() */ } /* Configuration may specify what MAC to use. Otherwise random. */ -- cgit v1.2.3-58-ga151 From 78e47fe4194ca7fac2cc29d25f1327db86922724 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 1 Apr 2011 20:56:23 -0700 Subject: net: convert SMSC USB net drivers to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's a race (not fixed here) in smsc75xx in setting RFE_CTL that's not properly handled via rfe_ctl_lock. Spinlock is not a good tool here, as this has to wait for URB completion (or maybe just submission) after issuing register write request. Otherwise, the rfe_ctl might be changed just after spin_unlock() and device left programmed with other value. smsc95xx has increased hard_header_len for the case of TX checksumming. smsc75xx is fixed to advertise IP+IPV6_CSUM instead of HW_CSUM as it does not use csum_start/csum_offset. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/usb/smsc75xx.c | 124 ++++++++++++++++----------------------------- drivers/net/usb/smsc95xx.c | 83 +++++++----------------------- 2 files changed, 63 insertions(+), 144 deletions(-) diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 753ee6eb7edd..860a20c938b4 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -65,7 +65,6 @@ struct smsc75xx_priv { struct usbnet *dev; u32 rfe_ctl; u32 multicast_hash_table[DP_SEL_VHF_HASH_LEN]; - bool use_rx_csum; struct mutex dataport_mutex; spinlock_t rfe_ctl_lock; struct work_struct set_multicast; @@ -548,28 +547,6 @@ static void smsc75xx_status(struct usbnet *dev, struct urb *urb) "unexpected interrupt, intdata=0x%08X", intdata); } -/* Enable or disable Rx checksum offload engine */ -static int smsc75xx_set_rx_csum_offload(struct usbnet *dev) -{ - struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); - unsigned long flags; - int ret; - - spin_lock_irqsave(&pdata->rfe_ctl_lock, flags); - - if (pdata->use_rx_csum) - pdata->rfe_ctl |= RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM; - else - pdata->rfe_ctl &= ~(RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM); - - spin_unlock_irqrestore(&pdata->rfe_ctl_lock, flags); - - ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl); - check_warn_return(ret, "Error writing RFE_CTL"); - - return 0; -} - static int smsc75xx_ethtool_get_eeprom_len(struct net_device *net) { return MAX_EEPROM_SIZE; @@ -599,34 +576,6 @@ static int smsc75xx_ethtool_set_eeprom(struct net_device *netdev, return smsc75xx_write_eeprom(dev, ee->offset, ee->len, data); } -static u32 smsc75xx_ethtool_get_rx_csum(struct net_device *netdev) -{ - struct usbnet *dev = netdev_priv(netdev); - struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); - - return pdata->use_rx_csum; -} - -static int smsc75xx_ethtool_set_rx_csum(struct net_device *netdev, u32 val) -{ - struct usbnet *dev = netdev_priv(netdev); - struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); - - pdata->use_rx_csum = !!val; - - return smsc75xx_set_rx_csum_offload(dev); -} - -static int smsc75xx_ethtool_set_tso(struct net_device *netdev, u32 data) -{ - if (data) - netdev->features |= NETIF_F_TSO | NETIF_F_TSO6; - else - netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); - - return 0; -} - static const struct ethtool_ops smsc75xx_ethtool_ops = { .get_link = usbnet_get_link, .nway_reset = usbnet_nway_reset, @@ -638,12 +587,6 @@ static const struct ethtool_ops smsc75xx_ethtool_ops = { .get_eeprom_len = smsc75xx_ethtool_get_eeprom_len, .get_eeprom = smsc75xx_ethtool_get_eeprom, .set_eeprom = smsc75xx_ethtool_set_eeprom, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_hw_csum, - .get_rx_csum = smsc75xx_ethtool_get_rx_csum, - .set_rx_csum = smsc75xx_ethtool_set_rx_csum, - .get_tso = ethtool_op_get_tso, - .set_tso = smsc75xx_ethtool_set_tso, }; static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) @@ -782,6 +725,30 @@ static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu) return usbnet_change_mtu(netdev, new_mtu); } +/* Enable or disable Rx checksum offload engine */ +static int smsc75xx_set_features(struct net_device *netdev, u32 features) +{ + struct usbnet *dev = netdev_priv(netdev); + struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); + unsigned long flags; + int ret; + + spin_lock_irqsave(&pdata->rfe_ctl_lock, flags); + + if (features & NETIF_F_RXCSUM) + pdata->rfe_ctl |= RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM; + else + pdata->rfe_ctl &= ~(RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM); + + spin_unlock_irqrestore(&pdata->rfe_ctl_lock, flags); + /* it's racing here! */ + + ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl); + check_warn_return(ret, "Error writing RFE_CTL"); + + return 0; +} + static int smsc75xx_reset(struct usbnet *dev) { struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); @@ -960,11 +927,7 @@ static int smsc75xx_reset(struct usbnet *dev) netif_dbg(dev, ifup, dev->net, "RFE_CTL set to 0x%08x", pdata->rfe_ctl); /* Enable or disable checksum offload engines */ - ethtool_op_set_tx_hw_csum(dev->net, DEFAULT_TX_CSUM_ENABLE); - ret = smsc75xx_set_rx_csum_offload(dev); - check_warn_return(ret, "Failed to set rx csum offload: %d", ret); - - smsc75xx_ethtool_set_tso(dev->net, DEFAULT_TSO_ENABLE); + smsc75xx_set_features(dev->net, dev->net->features); smsc75xx_set_multicast(dev->net); @@ -1037,6 +1000,7 @@ static const struct net_device_ops smsc75xx_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = smsc75xx_ioctl, .ndo_set_multicast_list = smsc75xx_set_multicast, + .ndo_set_features = smsc75xx_set_features, }; static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf) @@ -1065,10 +1029,17 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf) INIT_WORK(&pdata->set_multicast, smsc75xx_deferred_multicast_write); - pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE; + if (DEFAULT_TX_CSUM_ENABLE) { + dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + if (DEFAULT_TSO_ENABLE) + dev->net->features |= NETIF_F_SG | + NETIF_F_TSO | NETIF_F_TSO6; + } + if (DEFAULT_RX_CSUM_ENABLE) + dev->net->features |= NETIF_F_RXCSUM; - /* We have to advertise SG otherwise TSO cannot be enabled */ - dev->net->features |= NETIF_F_SG; + dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_RXCSUM; /* Init all registers */ ret = smsc75xx_reset(dev); @@ -1091,10 +1062,11 @@ static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf) } } -static void smsc75xx_rx_csum_offload(struct sk_buff *skb, u32 rx_cmd_a, - u32 rx_cmd_b) +static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb, + u32 rx_cmd_a, u32 rx_cmd_b) { - if (unlikely(rx_cmd_a & RX_CMD_A_LCSM)) { + if (!(dev->net->features & NETIF_F_RXCSUM) || + unlikely(rx_cmd_a & RX_CMD_A_LCSM)) { skb->ip_summed = CHECKSUM_NONE; } else { skb->csum = ntohs((u16)(rx_cmd_b >> RX_CMD_B_CSUM_SHIFT)); @@ -1104,8 +1076,6 @@ static void smsc75xx_rx_csum_offload(struct sk_buff *skb, u32 rx_cmd_a, static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { - struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); - while (skb->len > 0) { u32 rx_cmd_a, rx_cmd_b, align_count, size; struct sk_buff *ax_skb; @@ -1145,11 +1115,8 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) /* last frame in this batch */ if (skb->len == size) { - if (pdata->use_rx_csum) - smsc75xx_rx_csum_offload(skb, rx_cmd_a, - rx_cmd_b); - else - skb->ip_summed = CHECKSUM_NONE; + smsc75xx_rx_csum_offload(dev, skb, rx_cmd_a, + rx_cmd_b); skb_trim(skb, skb->len - 4); /* remove fcs */ skb->truesize = size + sizeof(struct sk_buff); @@ -1167,11 +1134,8 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) ax_skb->data = packet; skb_set_tail_pointer(ax_skb, size); - if (pdata->use_rx_csum) - smsc75xx_rx_csum_offload(ax_skb, rx_cmd_a, - rx_cmd_b); - else - ax_skb->ip_summed = CHECKSUM_NONE; + smsc75xx_rx_csum_offload(dev, ax_skb, rx_cmd_a, + rx_cmd_b); skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ ax_skb->truesize = size + sizeof(struct sk_buff); diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 727874d9deb6..708f2083898b 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -52,8 +52,6 @@ struct smsc95xx_priv { u32 hash_hi; u32 hash_lo; spinlock_t mac_cr_lock; - bool use_tx_csum; - bool use_rx_csum; }; struct usb_context { @@ -517,22 +515,24 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb) } /* Enable or disable Tx & Rx checksum offload engines */ -static int smsc95xx_set_csums(struct usbnet *dev) +static int smsc95xx_set_features(struct net_device *netdev, u32 features) { - struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); + struct usbnet *dev = netdev_priv(netdev); u32 read_buf; - int ret = smsc95xx_read_reg(dev, COE_CR, &read_buf); + int ret; + + ret = smsc95xx_read_reg(dev, COE_CR, &read_buf); if (ret < 0) { netdev_warn(dev->net, "Failed to read COE_CR: %d\n", ret); return ret; } - if (pdata->use_tx_csum) + if (features & NETIF_F_HW_CSUM) read_buf |= Tx_COE_EN_; else read_buf &= ~Tx_COE_EN_; - if (pdata->use_rx_csum) + if (features & NETIF_F_RXCSUM) read_buf |= Rx_COE_EN_; else read_buf &= ~Rx_COE_EN_; @@ -576,43 +576,6 @@ static int smsc95xx_ethtool_set_eeprom(struct net_device *netdev, return smsc95xx_write_eeprom(dev, ee->offset, ee->len, data); } -static u32 smsc95xx_ethtool_get_rx_csum(struct net_device *netdev) -{ - struct usbnet *dev = netdev_priv(netdev); - struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); - - return pdata->use_rx_csum; -} - -static int smsc95xx_ethtool_set_rx_csum(struct net_device *netdev, u32 val) -{ - struct usbnet *dev = netdev_priv(netdev); - struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); - - pdata->use_rx_csum = !!val; - - return smsc95xx_set_csums(dev); -} - -static u32 smsc95xx_ethtool_get_tx_csum(struct net_device *netdev) -{ - struct usbnet *dev = netdev_priv(netdev); - struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); - - return pdata->use_tx_csum; -} - -static int smsc95xx_ethtool_set_tx_csum(struct net_device *netdev, u32 val) -{ - struct usbnet *dev = netdev_priv(netdev); - struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); - - pdata->use_tx_csum = !!val; - - ethtool_op_set_tx_hw_csum(netdev, pdata->use_tx_csum); - return smsc95xx_set_csums(dev); -} - static const struct ethtool_ops smsc95xx_ethtool_ops = { .get_link = usbnet_get_link, .nway_reset = usbnet_nway_reset, @@ -624,10 +587,6 @@ static const struct ethtool_ops smsc95xx_ethtool_ops = { .get_eeprom_len = smsc95xx_ethtool_get_eeprom_len, .get_eeprom = smsc95xx_ethtool_get_eeprom, .set_eeprom = smsc95xx_ethtool_set_eeprom, - .get_tx_csum = smsc95xx_ethtool_get_tx_csum, - .set_tx_csum = smsc95xx_ethtool_set_tx_csum, - .get_rx_csum = smsc95xx_ethtool_get_rx_csum, - .set_rx_csum = smsc95xx_ethtool_set_rx_csum, }; static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) @@ -755,7 +714,6 @@ static int smsc95xx_phy_initialize(struct usbnet *dev) static int smsc95xx_reset(struct usbnet *dev) { struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); - struct net_device *netdev = dev->net; u32 read_buf, write_buf, burst_cap; int ret = 0, timeout; @@ -975,12 +933,7 @@ static int smsc95xx_reset(struct usbnet *dev) } /* Enable or disable checksum offload engines */ - ethtool_op_set_tx_hw_csum(netdev, pdata->use_tx_csum); - ret = smsc95xx_set_csums(dev); - if (ret < 0) { - netdev_warn(dev->net, "Failed to set csum offload: %d\n", ret); - return ret; - } + smsc95xx_set_features(dev->net, dev->net->features); smsc95xx_set_multicast(dev->net); @@ -1019,6 +972,7 @@ static const struct net_device_ops smsc95xx_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = smsc95xx_ioctl, .ndo_set_multicast_list = smsc95xx_set_multicast, + .ndo_set_features = smsc95xx_set_features, }; static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) @@ -1045,8 +999,12 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) spin_lock_init(&pdata->mac_cr_lock); - pdata->use_tx_csum = DEFAULT_TX_CSUM_ENABLE; - pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE; + if (DEFAULT_TX_CSUM_ENABLE) + dev->net->features |= NETIF_F_HW_CSUM; + if (DEFAULT_RX_CSUM_ENABLE) + dev->net->features |= NETIF_F_RXCSUM; + + dev->net->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM; smsc95xx_init_mac_address(dev); @@ -1056,7 +1014,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->netdev_ops = &smsc95xx_netdev_ops; dev->net->ethtool_ops = &smsc95xx_ethtool_ops; dev->net->flags |= IFF_MULTICAST; - dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD; + dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD_CSUM; return 0; } @@ -1080,8 +1038,6 @@ static void smsc95xx_rx_csum_offload(struct sk_buff *skb) static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { - struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); - while (skb->len > 0) { u32 header, align_count; struct sk_buff *ax_skb; @@ -1123,7 +1079,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) /* last frame in this batch */ if (skb->len == size) { - if (pdata->use_rx_csum) + if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(skb); skb_trim(skb, skb->len - 4); /* remove fcs */ skb->truesize = size + sizeof(struct sk_buff); @@ -1141,7 +1097,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) ax_skb->data = packet; skb_set_tail_pointer(ax_skb, size); - if (pdata->use_rx_csum) + if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(ax_skb); skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ ax_skb->truesize = size + sizeof(struct sk_buff); @@ -1174,8 +1130,7 @@ static u32 smsc95xx_calc_csum_preamble(struct sk_buff *skb) static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { - struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); - bool csum = pdata->use_tx_csum && (skb->ip_summed == CHECKSUM_PARTIAL); + bool csum = skb->ip_summed == CHECKSUM_PARTIAL; int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD; u32 tx_cmd_a, tx_cmd_b; -- cgit v1.2.3-58-ga151 From fb507934fd6faa00b3d833facb53b90c71ddc307 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 31 Mar 2011 01:01:35 +0000 Subject: net: convert xen-netfront to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not tested in any way. The original code for offload setting seems broken as it resets the features on every netback reconnect. This will set GSO_ROBUST at device creation time (earlier than connect time). RX checksum offload is forced on - so advertise as it is. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 57 +++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index c06f5a09b263..f6e7e2726f6b 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1148,6 +1148,8 @@ static const struct net_device_ops xennet_netdev_ops = { .ndo_change_mtu = xennet_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, + .ndo_fix_features = xennet_fix_features, + .ndo_set_features = xennet_set_features, }; static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev) @@ -1209,7 +1211,9 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev netdev->netdev_ops = &xennet_netdev_ops; netif_napi_add(netdev, &np->napi, xennet_poll, 64); - netdev->features = NETIF_F_IP_CSUM; + netdev->features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | + NETIF_F_GSO_ROBUST; + netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO; SET_ETHTOOL_OPS(netdev, &xennet_ethtool_ops); SET_NETDEV_DEV(netdev, &dev->dev); @@ -1509,52 +1513,40 @@ again: return err; } -static int xennet_set_sg(struct net_device *dev, u32 data) +static u32 xennet_fix_features(struct net_device *dev, u32 features) { - if (data) { - struct netfront_info *np = netdev_priv(dev); - int val; + struct netfront_info *np = netdev_priv(dev); + int val; + if (features & NETIF_F_SG) { if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-sg", "%d", &val) < 0) val = 0; - if (!val) - return -ENOSYS; - } else if (dev->mtu > ETH_DATA_LEN) - dev->mtu = ETH_DATA_LEN; - return ethtool_op_set_sg(dev, data); -} - -static int xennet_set_tso(struct net_device *dev, u32 data) -{ - if (data) { - struct netfront_info *np = netdev_priv(dev); - int val; + if (!val) + features &= ~NETIF_F_SG; + } + if (features & NETIF_F_TSO) { if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-gso-tcpv4", "%d", &val) < 0) val = 0; + if (!val) - return -ENOSYS; + features &= ~NETIF_F_TSO; } - return ethtool_op_set_tso(dev, data); + return features; } -static void xennet_set_features(struct net_device *dev) +static int xennet_set_features(struct net_device *dev, u32 features) { - /* Turn off all GSO bits except ROBUST. */ - dev->features &= ~NETIF_F_GSO_MASK; - dev->features |= NETIF_F_GSO_ROBUST; - xennet_set_sg(dev, 0); - - /* We need checksum offload to enable scatter/gather and TSO. */ - if (!(dev->features & NETIF_F_IP_CSUM)) - return; + if (!(features & NETIF_F_SG) && dev->mtu > ETH_DATA_LEN) { + netdev_info(dev, "Reducing MTU because no SG offload"); + dev->mtu = ETH_DATA_LEN; + } - if (!xennet_set_sg(dev, 1)) - xennet_set_tso(dev, 1); + return 0; } static int xennet_connect(struct net_device *dev) @@ -1581,7 +1573,7 @@ static int xennet_connect(struct net_device *dev) if (err) return err; - xennet_set_features(dev); + netdev_update_features(dev); spin_lock_bh(&np->rx_lock); spin_lock_irq(&np->tx_lock); @@ -1709,9 +1701,6 @@ static void xennet_get_strings(struct net_device *dev, u32 stringset, u8 * data) static const struct ethtool_ops xennet_ethtool_ops = { - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = xennet_set_sg, - .set_tso = xennet_set_tso, .get_link = ethtool_op_get_link, .get_sset_count = xennet_get_sset_count, -- cgit v1.2.3-58-ga151 From d7b576545648e487b2958c220542e111f5ac46f0 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 31 Mar 2011 01:01:35 +0000 Subject: jme: convert offload constraints to ndo_fix_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/jme.c | 77 ++++++++++++++----------------------------------------- drivers/net/jme.h | 2 -- 2 files changed, 19 insertions(+), 60 deletions(-) diff --git a/drivers/net/jme.c b/drivers/net/jme.c index 994c80939c7a..be4773f54a24 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -2230,17 +2230,9 @@ jme_change_mtu(struct net_device *netdev, int new_mtu) jme_restart_rx_engine(jme); } - if (new_mtu > 1900) { - netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_TSO | NETIF_F_TSO6); - } else { - if (test_bit(JME_FLAG_TXCSUM, &jme->flags)) - netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - if (test_bit(JME_FLAG_TSO, &jme->flags)) - netdev->features |= NETIF_F_TSO | NETIF_F_TSO6; - } - netdev->mtu = new_mtu; + netdev_update_features(netdev); + jme_reset_link(jme); return 0; @@ -2640,19 +2632,20 @@ jme_set_msglevel(struct net_device *netdev, u32 value) } static u32 -jme_get_rx_csum(struct net_device *netdev) +jme_fix_features(struct net_device *netdev, u32 features) { - struct jme_adapter *jme = netdev_priv(netdev); - return jme->reg_rxmcs & RXMCS_CHECKSUM; + if (netdev->mtu > 1900) + features &= ~(NETIF_F_ALL_TSO | NETIF_F_ALL_CSUM); + return features; } static int -jme_set_rx_csum(struct net_device *netdev, u32 on) +jme_set_features(struct net_device *netdev, u32 features) { struct jme_adapter *jme = netdev_priv(netdev); spin_lock_bh(&jme->rxmcs_lock); - if (on) + if (features & NETIF_F_RXCSUM) jme->reg_rxmcs |= RXMCS_CHECKSUM; else jme->reg_rxmcs &= ~RXMCS_CHECKSUM; @@ -2662,42 +2655,6 @@ jme_set_rx_csum(struct net_device *netdev, u32 on) return 0; } -static int -jme_set_tx_csum(struct net_device *netdev, u32 on) -{ - struct jme_adapter *jme = netdev_priv(netdev); - - if (on) { - set_bit(JME_FLAG_TXCSUM, &jme->flags); - if (netdev->mtu <= 1900) - netdev->features |= - NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - } else { - clear_bit(JME_FLAG_TXCSUM, &jme->flags); - netdev->features &= - ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - } - - return 0; -} - -static int -jme_set_tso(struct net_device *netdev, u32 on) -{ - struct jme_adapter *jme = netdev_priv(netdev); - - if (on) { - set_bit(JME_FLAG_TSO, &jme->flags); - if (netdev->mtu <= 1900) - netdev->features |= NETIF_F_TSO | NETIF_F_TSO6; - } else { - clear_bit(JME_FLAG_TSO, &jme->flags); - netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); - } - - return 0; -} - static int jme_nway_reset(struct net_device *netdev) { @@ -2839,11 +2796,6 @@ static const struct ethtool_ops jme_ethtool_ops = { .get_link = jme_get_link, .get_msglevel = jme_get_msglevel, .set_msglevel = jme_set_msglevel, - .get_rx_csum = jme_get_rx_csum, - .set_rx_csum = jme_set_rx_csum, - .set_tx_csum = jme_set_tx_csum, - .set_tso = jme_set_tso, - .set_sg = ethtool_op_set_sg, .nway_reset = jme_nway_reset, .get_eeprom_len = jme_get_eeprom_len, .get_eeprom = jme_get_eeprom, @@ -2903,6 +2855,8 @@ static const struct net_device_ops jme_netdev_ops = { .ndo_change_mtu = jme_change_mtu, .ndo_tx_timeout = jme_tx_timeout, .ndo_vlan_rx_register = jme_vlan_rx_register, + .ndo_fix_features = jme_fix_features, + .ndo_set_features = jme_set_features, }; static int __devinit @@ -2957,6 +2911,12 @@ jme_init_one(struct pci_dev *pdev, netdev->netdev_ops = &jme_netdev_ops; netdev->ethtool_ops = &jme_ethtool_ops; netdev->watchdog_timeo = TX_TIMEOUT; + netdev->hw_features = NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | + NETIF_F_SG | + NETIF_F_TSO | + NETIF_F_TSO6 | + NETIF_F_RXCSUM; netdev->features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG | @@ -3040,8 +3000,9 @@ jme_init_one(struct pci_dev *pdev, jme->reg_txpfc = 0; jme->reg_pmcs = PMCS_MFEN; jme->reg_gpreg1 = GPREG1_DEFAULT; - set_bit(JME_FLAG_TXCSUM, &jme->flags); - set_bit(JME_FLAG_TSO, &jme->flags); + + if (jme->reg_rxmcs & RXMCS_CHECKSUM) + netdev->features |= NETIF_F_RXCSUM; /* * Get Max Read Req Size from PCI Config Space diff --git a/drivers/net/jme.h b/drivers/net/jme.h index 8bf30451e821..e9aaeca96abc 100644 --- a/drivers/net/jme.h +++ b/drivers/net/jme.h @@ -468,8 +468,6 @@ struct jme_adapter { enum jme_flags_bits { JME_FLAG_MSI = 1, JME_FLAG_SSET = 2, - JME_FLAG_TXCSUM = 3, - JME_FLAG_TSO = 4, JME_FLAG_POLL = 5, JME_FLAG_SHUTDOWN = 6, }; -- cgit v1.2.3-58-ga151 From a2c725fa39b79fcc3f09151e847cc006ff0d4389 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 31 Mar 2011 01:01:35 +0000 Subject: veth: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should probably get TSO available as it's basically a loopback device. Offloads are left disabled by default - as before. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/veth.c | 45 +++++---------------------------------------- 1 file changed, 5 insertions(+), 40 deletions(-) diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 2de9b90c5f8f..654228849951 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -36,7 +36,6 @@ struct veth_net_stats { struct veth_priv { struct net_device *peer; struct veth_net_stats __percpu *stats; - unsigned ip_summed; }; /* @@ -99,47 +98,10 @@ static void veth_get_ethtool_stats(struct net_device *dev, data[0] = priv->peer->ifindex; } -static u32 veth_get_rx_csum(struct net_device *dev) -{ - struct veth_priv *priv; - - priv = netdev_priv(dev); - return priv->ip_summed == CHECKSUM_UNNECESSARY; -} - -static int veth_set_rx_csum(struct net_device *dev, u32 data) -{ - struct veth_priv *priv; - - priv = netdev_priv(dev); - priv->ip_summed = data ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE; - return 0; -} - -static u32 veth_get_tx_csum(struct net_device *dev) -{ - return (dev->features & NETIF_F_NO_CSUM) != 0; -} - -static int veth_set_tx_csum(struct net_device *dev, u32 data) -{ - if (data) - dev->features |= NETIF_F_NO_CSUM; - else - dev->features &= ~NETIF_F_NO_CSUM; - return 0; -} - static const struct ethtool_ops veth_ethtool_ops = { .get_settings = veth_get_settings, .get_drvinfo = veth_get_drvinfo, .get_link = ethtool_op_get_link, - .get_rx_csum = veth_get_rx_csum, - .set_rx_csum = veth_set_rx_csum, - .get_tx_csum = veth_get_tx_csum, - .set_tx_csum = veth_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, .get_strings = veth_get_strings, .get_sset_count = veth_get_sset_count, .get_ethtool_stats = veth_get_ethtool_stats, @@ -168,8 +130,9 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) /* don't change ip_summed == CHECKSUM_PARTIAL, as that will cause bad checksum on forwarded packets */ - if (skb->ip_summed == CHECKSUM_NONE) - skb->ip_summed = rcv_priv->ip_summed; + if (skb->ip_summed == CHECKSUM_NONE && + rcv->features & NETIF_F_RXCSUM) + skb->ip_summed = CHECKSUM_UNNECESSARY; length = skb->len; if (dev_forward_skb(rcv, skb) != NET_RX_SUCCESS) @@ -304,6 +267,8 @@ static void veth_setup(struct net_device *dev) dev->ethtool_ops = &veth_ethtool_ops; dev->features |= NETIF_F_LLTX; dev->destructor = veth_dev_free; + + dev->hw_features = NETIF_F_NO_CSUM | NETIF_F_SG | NETIF_F_RXCSUM; } /* -- cgit v1.2.3-58-ga151 From e9403c8437cf3721e7901c1a8fcb06bb642a7e55 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 1 Apr 2011 20:58:37 -0700 Subject: net: convert sunhme/sungem network drivers to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Side effects: - TX offloads (HW csum, scatter-gather) can be toggled now - RX checksum is reported correctly now (it's always active) Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/sungem.c | 3 ++- drivers/net/sunhme.c | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index c1a344829b54..a935426cbe63 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -3146,7 +3146,8 @@ static int __devinit gem_init_one(struct pci_dev *pdev, gp->phy_mii.def ? gp->phy_mii.def->name : "no"); /* GEM can do it all... */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_LLTX; + dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM; + dev->features |= dev->hw_features | NETIF_F_RXCSUM | NETIF_F_LLTX; if (pci_using_dac) dev->features |= NETIF_F_HIGHDMA; diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index eb4f59fb01e9..80e907df36b4 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2788,7 +2788,8 @@ static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int i dev->ethtool_ops = &hme_ethtool_ops; /* Happy Meal can do it all... */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; + dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM; + dev->features |= dev->hw_features | NETIF_F_RXCSUM; dev->irq = op->archdata.irqs[0]; @@ -3113,7 +3114,8 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, dev->dma = 0; /* Happy Meal can do it all... */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; + dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM; + dev->features |= dev->hw_features | NETIF_F_RXCSUM; #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) /* Hook up PCI register/descriptor accessors. */ -- cgit v1.2.3-58-ga151 From 6cb6a27c45cec9184302c2e350b3593c64bc7f6c Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sat, 2 Apr 2011 22:48:47 -0700 Subject: net: Call netdev_features_change() from netdev_update_features() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue FEAT_CHANGE notification when features are changed by netdev_update_features(). This will allow changes made by extra constraints on e.g. MTU change to be properly propagated like changes via ethtool. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- include/linux/netdevice.h | 1 + net/core/dev.c | 23 +++++++++++++++++------ net/core/ethtool.c | 6 +++--- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 5eeb2cd3631c..423a5447d2ed 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2550,6 +2550,7 @@ static inline u32 netdev_get_wanted_features(struct net_device *dev) } u32 netdev_increment_features(u32 all, u32 one, u32 mask); u32 netdev_fix_features(struct net_device *dev, u32 features); +int __netdev_update_features(struct net_device *dev); void netdev_update_features(struct net_device *dev); void netif_stacked_transfer_operstate(const struct net_device *rootdev, diff --git a/net/core/dev.c b/net/core/dev.c index 3da9fb06d47a..02f56376fe99 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5236,7 +5236,7 @@ u32 netdev_fix_features(struct net_device *dev, u32 features) } EXPORT_SYMBOL(netdev_fix_features); -void netdev_update_features(struct net_device *dev) +int __netdev_update_features(struct net_device *dev) { u32 features; int err = 0; @@ -5250,7 +5250,7 @@ void netdev_update_features(struct net_device *dev) features = netdev_fix_features(dev, features); if (dev->features == features) - return; + return 0; netdev_info(dev, "Features changed: 0x%08x -> 0x%08x\n", dev->features, features); @@ -5258,12 +5258,23 @@ void netdev_update_features(struct net_device *dev) if (dev->netdev_ops->ndo_set_features) err = dev->netdev_ops->ndo_set_features(dev, features); - if (!err) - dev->features = features; - else if (err < 0) + if (unlikely(err < 0)) { netdev_err(dev, "set_features() failed (%d); wanted 0x%08x, left 0x%08x\n", err, features, dev->features); + return -1; + } + + if (!err) + dev->features = features; + + return 1; +} + +void netdev_update_features(struct net_device *dev) +{ + if (__netdev_update_features(dev)) + netdev_features_change(dev); } EXPORT_SYMBOL(netdev_update_features); @@ -5430,7 +5441,7 @@ int register_netdevice(struct net_device *dev) goto err_uninit; dev->reg_state = NETREG_REGISTERED; - netdev_update_features(dev); + __netdev_update_features(dev); /* * Default initial state at registry is that the diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 74ead9eca126..439e4b0e1312 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -317,7 +317,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) dev->wanted_features &= ~features[0].valid; dev->wanted_features |= features[0].valid & features[0].requested; - netdev_update_features(dev); + __netdev_update_features(dev); if ((dev->wanted_features ^ dev->features) & features[0].valid) ret |= ETHTOOL_F_WISH; @@ -499,7 +499,7 @@ static int ethtool_set_one_feature(struct net_device *dev, else dev->wanted_features &= ~mask; - netdev_update_features(dev); + __netdev_update_features(dev); return 0; } @@ -551,7 +551,7 @@ int __ethtool_set_flags(struct net_device *dev, u32 data) dev->wanted_features = (dev->wanted_features & ~changed) | data; - netdev_update_features(dev); + __netdev_update_features(dev); return 0; } -- cgit v1.2.3-58-ga151 From 8a0427bb688eae86a8bb939b6a74e5aa00aa035a Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sat, 2 Apr 2011 22:49:12 -0700 Subject: vlan: convert VLAN devices to use ndo_fix_features() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note: get_flags was actually broken, because it should return the flags capped with vlan_features. This is now done implicitly by limiting netdev->hw_features. RX checksumming offload control is (and was) broken, as there was no way before to say whether it's done for tagged packets. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- net/8021q/vlan.c | 8 ++------ net/8021q/vlan_dev.c | 50 ++++++++++++++------------------------------------ 2 files changed, 16 insertions(+), 42 deletions(-) diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 7850412f52b7..e47600b4e2e3 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -327,10 +327,6 @@ static void vlan_sync_address(struct net_device *dev, static void vlan_transfer_features(struct net_device *dev, struct net_device *vlandev) { - u32 old_features = vlandev->features; - - vlandev->features &= ~dev->vlan_features; - vlandev->features |= dev->features & dev->vlan_features; vlandev->gso_max_size = dev->gso_max_size; if (dev->features & NETIF_F_HW_VLAN_TX) @@ -341,8 +337,8 @@ static void vlan_transfer_features(struct net_device *dev, #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid; #endif - if (old_features != vlandev->features) - netdev_features_change(vlandev); + + netdev_update_features(vlandev); } static void __vlan_device_event(struct net_device *dev, unsigned long event) diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index e34ea9e5e28b..b84a46b30c0c 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -704,8 +704,8 @@ static int vlan_dev_init(struct net_device *dev) (1<<__LINK_STATE_DORMANT))) | (1<<__LINK_STATE_PRESENT); - dev->features |= real_dev->features & real_dev->vlan_features; - dev->features |= NETIF_F_LLTX; + dev->hw_features = real_dev->vlan_features & NETIF_F_ALL_TX_OFFLOADS; + dev->features |= real_dev->vlan_features | NETIF_F_LLTX; dev->gso_max_size = real_dev->gso_max_size; /* ipv6 shared card related stuff */ @@ -759,6 +759,17 @@ static void vlan_dev_uninit(struct net_device *dev) } } +static u32 vlan_dev_fix_features(struct net_device *dev, u32 features) +{ + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; + + features &= (real_dev->features | NETIF_F_LLTX); + if (dev_ethtool_get_rx_csum(real_dev)) + features |= NETIF_F_RXCSUM; + + return features; +} + static int vlan_ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { @@ -774,18 +785,6 @@ static void vlan_ethtool_get_drvinfo(struct net_device *dev, strcpy(info->fw_version, "N/A"); } -static u32 vlan_ethtool_get_rx_csum(struct net_device *dev) -{ - const struct vlan_dev_info *vlan = vlan_dev_info(dev); - return dev_ethtool_get_rx_csum(vlan->real_dev); -} - -static u32 vlan_ethtool_get_flags(struct net_device *dev) -{ - const struct vlan_dev_info *vlan = vlan_dev_info(dev); - return dev_ethtool_get_flags(vlan->real_dev); -} - static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { @@ -823,32 +822,10 @@ static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, st return stats; } -static int vlan_ethtool_set_tso(struct net_device *dev, u32 data) -{ - if (data) { - struct net_device *real_dev = vlan_dev_info(dev)->real_dev; - - /* Underlying device must support TSO for VLAN-tagged packets - * and must have TSO enabled now. - */ - if (!(real_dev->vlan_features & NETIF_F_TSO)) - return -EOPNOTSUPP; - if (!(real_dev->features & NETIF_F_TSO)) - return -EINVAL; - dev->features |= NETIF_F_TSO; - } else { - dev->features &= ~NETIF_F_TSO; - } - return 0; -} - static const struct ethtool_ops vlan_ethtool_ops = { .get_settings = vlan_ethtool_get_settings, .get_drvinfo = vlan_ethtool_get_drvinfo, .get_link = ethtool_op_get_link, - .get_rx_csum = vlan_ethtool_get_rx_csum, - .get_flags = vlan_ethtool_get_flags, - .set_tso = vlan_ethtool_set_tso, }; static const struct net_device_ops vlan_netdev_ops = { @@ -874,6 +851,7 @@ static const struct net_device_ops vlan_netdev_ops = { .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, .ndo_fcoe_ddp_target = vlan_dev_fcoe_ddp_target, #endif + .ndo_fix_features = vlan_dev_fix_features, }; void vlan_setup(struct net_device *dev) -- cgit v1.2.3-58-ga151 From 8f7b01a178b8e6a7b663a1bbaa1710756d67b69b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 3 Apr 2011 17:21:00 -0700 Subject: xen: netfront: fix declaration order Must declare xennet_fix_features() and xennet_set_features() before using them. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 72 +++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index f6e7e2726f6b..0cfe4ccf92d2 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1140,6 +1140,42 @@ static void xennet_uninit(struct net_device *dev) gnttab_free_grant_references(np->gref_rx_head); } +static u32 xennet_fix_features(struct net_device *dev, u32 features) +{ + struct netfront_info *np = netdev_priv(dev); + int val; + + if (features & NETIF_F_SG) { + if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-sg", + "%d", &val) < 0) + val = 0; + + if (!val) + features &= ~NETIF_F_SG; + } + + if (features & NETIF_F_TSO) { + if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, + "feature-gso-tcpv4", "%d", &val) < 0) + val = 0; + + if (!val) + features &= ~NETIF_F_TSO; + } + + return features; +} + +static int xennet_set_features(struct net_device *dev, u32 features) +{ + if (!(features & NETIF_F_SG) && dev->mtu > ETH_DATA_LEN) { + netdev_info(dev, "Reducing MTU because no SG offload"); + dev->mtu = ETH_DATA_LEN; + } + + return 0; +} + static const struct net_device_ops xennet_netdev_ops = { .ndo_open = xennet_open, .ndo_uninit = xennet_uninit, @@ -1513,42 +1549,6 @@ again: return err; } -static u32 xennet_fix_features(struct net_device *dev, u32 features) -{ - struct netfront_info *np = netdev_priv(dev); - int val; - - if (features & NETIF_F_SG) { - if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-sg", - "%d", &val) < 0) - val = 0; - - if (!val) - features &= ~NETIF_F_SG; - } - - if (features & NETIF_F_TSO) { - if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, - "feature-gso-tcpv4", "%d", &val) < 0) - val = 0; - - if (!val) - features &= ~NETIF_F_TSO; - } - - return features; -} - -static int xennet_set_features(struct net_device *dev, u32 features) -{ - if (!(features & NETIF_F_SG) && dev->mtu > ETH_DATA_LEN) { - netdev_info(dev, "Reducing MTU because no SG offload"); - dev->mtu = ETH_DATA_LEN; - } - - return 0; -} - static int xennet_connect(struct net_device *dev) { struct netfront_info *np = netdev_priv(dev); -- cgit v1.2.3-58-ga151 From 95b8fbada76d978ce13a26785f8b85ff54478bb2 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 3 Apr 2011 13:31:06 +0000 Subject: mISDN: fix "persistant" typo Signed-off-by: Jan Engelhardt Signed-off-by: David S. Miller --- drivers/isdn/mISDN/layer2.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c index 4ae75053c9d2..9e1610f40e16 100644 --- a/drivers/isdn/mISDN/layer2.c +++ b/drivers/isdn/mISDN/layer2.c @@ -1640,7 +1640,7 @@ l2_tei_remove(struct FsmInst *fi, int event, void *arg) } static void -l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg) +l2_st14_persistent_da(struct FsmInst *fi, int event, void *arg) { struct layer2 *l2 = fi->userdata; struct sk_buff *skb = arg; @@ -1654,7 +1654,7 @@ l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg) } static void -l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg) +l2_st5_persistent_da(struct FsmInst *fi, int event, void *arg) { struct layer2 *l2 = fi->userdata; struct sk_buff *skb = arg; @@ -1671,7 +1671,7 @@ l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg) } static void -l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg) +l2_st6_persistent_da(struct FsmInst *fi, int event, void *arg) { struct layer2 *l2 = fi->userdata; struct sk_buff *skb = arg; @@ -1685,7 +1685,7 @@ l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg) } static void -l2_persistant_da(struct FsmInst *fi, int event, void *arg) +l2_persistent_da(struct FsmInst *fi, int event, void *arg) { struct layer2 *l2 = fi->userdata; struct sk_buff *skb = arg; @@ -1829,14 +1829,14 @@ static struct FsmNode L2FnList[] = {ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error}, {ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest}, {ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest}, - {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistant_da}, + {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistent_da}, {ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove}, {ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove}, - {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistant_da}, - {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da}, - {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da}, - {ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da}, - {ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da}, + {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistent_da}, + {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistent_da}, + {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistent_da}, + {ST_L2_7, EV_L1_DEACTIVATE, l2_persistent_da}, + {ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da}, }; static int -- cgit v1.2.3-58-ga151 From 7f5c6d4f665bb57a19a34ce1fb16cc708c04f219 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 4 Apr 2011 17:04:03 +0200 Subject: netfilter: get rid of atomic ops in fast path We currently use a percpu spinlock to 'protect' rule bytes/packets counters, after various attempts to use RCU instead. Lately we added a seqlock so that get_counters() can run without blocking BH or 'writers'. But we really only need the seqcount in it. Spinlock itself is only locked by the current/owner cpu, so we can remove it completely. This cleanups api, using correct 'writer' vs 'reader' semantic. At replace time, the get_counters() call makes sure all cpus are done using the old table. Signed-off-by: Eric Dumazet Cc: Jan Engelhardt Signed-off-by: Patrick McHardy --- include/linux/netfilter/x_tables.h | 96 +++++++++++++++++--------------------- net/ipv4/netfilter/arp_tables.c | 18 ++++--- net/ipv4/netfilter/ip_tables.c | 28 +++++------ net/ipv6/netfilter/ip6_tables.c | 19 +++++--- net/netfilter/x_tables.c | 9 ++-- 5 files changed, 80 insertions(+), 90 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 37219525ff6f..32cddf78b13e 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -456,72 +456,60 @@ extern void xt_proto_fini(struct net *net, u_int8_t af); extern struct xt_table_info *xt_alloc_table_info(unsigned int size); extern void xt_free_table_info(struct xt_table_info *info); -/* - * Per-CPU spinlock associated with per-cpu table entries, and - * with a counter for the "reading" side that allows a recursive - * reader to avoid taking the lock and deadlocking. - * - * "reading" is used by ip/arp/ip6 tables rule processing which runs per-cpu. - * It needs to ensure that the rules are not being changed while the packet - * is being processed. In some cases, the read lock will be acquired - * twice on the same CPU; this is okay because of the count. - * - * "writing" is used when reading counters. - * During replace any readers that are using the old tables have to complete - * before freeing the old table. This is handled by the write locking - * necessary for reading the counters. +/** + * xt_recseq - recursive seqcount for netfilter use + * + * Packet processing changes the seqcount only if no recursion happened + * get_counters() can use read_seqcount_begin()/read_seqcount_retry(), + * because we use the normal seqcount convention : + * Low order bit set to 1 if a writer is active. */ -struct xt_info_lock { - seqlock_t lock; - unsigned char readers; -}; -DECLARE_PER_CPU(struct xt_info_lock, xt_info_locks); +DECLARE_PER_CPU(seqcount_t, xt_recseq); -/* - * Note: we need to ensure that preemption is disabled before acquiring - * the per-cpu-variable, so we do it as a two step process rather than - * using "spin_lock_bh()". - * - * We _also_ need to disable bottom half processing before updating our - * nesting count, to make sure that the only kind of re-entrancy is this - * code being called by itself: since the count+lock is not an atomic - * operation, we can allow no races. +/** + * xt_write_recseq_begin - start of a write section * - * _Only_ that special combination of being per-cpu and never getting - * re-entered asynchronously means that the count is safe. + * Begin packet processing : all readers must wait the end + * 1) Must be called with preemption disabled + * 2) softirqs must be disabled too (or we should use irqsafe_cpu_add()) + * Returns : + * 1 if no recursion on this cpu + * 0 if recursion detected */ -static inline void xt_info_rdlock_bh(void) +static inline unsigned int xt_write_recseq_begin(void) { - struct xt_info_lock *lock; + unsigned int addend; - local_bh_disable(); - lock = &__get_cpu_var(xt_info_locks); - if (likely(!lock->readers++)) - write_seqlock(&lock->lock); -} + /* + * Low order bit of sequence is set if we already + * called xt_write_recseq_begin(). + */ + addend = (__this_cpu_read(xt_recseq.sequence) + 1) & 1; -static inline void xt_info_rdunlock_bh(void) -{ - struct xt_info_lock *lock = &__get_cpu_var(xt_info_locks); + /* + * This is kind of a write_seqcount_begin(), but addend is 0 or 1 + * We dont check addend value to avoid a test and conditional jump, + * since addend is most likely 1 + */ + __this_cpu_add(xt_recseq.sequence, addend); + smp_wmb(); - if (likely(!--lock->readers)) - write_sequnlock(&lock->lock); - local_bh_enable(); + return addend; } -/* - * The "writer" side needs to get exclusive access to the lock, - * regardless of readers. This must be called with bottom half - * processing (and thus also preemption) disabled. +/** + * xt_write_recseq_end - end of a write section + * @addend: return value from previous xt_write_recseq_begin() + * + * End packet processing : all readers can proceed + * 1) Must be called with preemption disabled + * 2) softirqs must be disabled too (or we should use irqsafe_cpu_add()) */ -static inline void xt_info_wrlock(unsigned int cpu) -{ - write_seqlock(&per_cpu(xt_info_locks, cpu).lock); -} - -static inline void xt_info_wrunlock(unsigned int cpu) +static inline void xt_write_recseq_end(unsigned int addend) { - write_sequnlock(&per_cpu(xt_info_locks, cpu).lock); + /* this is kind of a write_seqcount_end(), but addend is 0 or 1 */ + smp_wmb(); + __this_cpu_add(xt_recseq.sequence, addend); } /* diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 4b5d457c2d76..2ea743336836 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -260,6 +260,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, void *table_base; const struct xt_table_info *private; struct xt_action_param acpar; + unsigned int addend; if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) return NF_DROP; @@ -267,7 +268,8 @@ unsigned int arpt_do_table(struct sk_buff *skb, indev = in ? in->name : nulldevname; outdev = out ? out->name : nulldevname; - xt_info_rdlock_bh(); + local_bh_disable(); + addend = xt_write_recseq_begin(); private = table->private; table_base = private->entries[smp_processor_id()]; @@ -338,7 +340,8 @@ unsigned int arpt_do_table(struct sk_buff *skb, /* Verdict */ break; } while (!acpar.hotdrop); - xt_info_rdunlock_bh(); + xt_write_recseq_end(addend); + local_bh_enable(); if (acpar.hotdrop) return NF_DROP; @@ -712,7 +715,7 @@ static void get_counters(const struct xt_table_info *t, unsigned int i; for_each_possible_cpu(cpu) { - seqlock_t *lock = &per_cpu(xt_info_locks, cpu).lock; + seqcount_t *s = &per_cpu(xt_recseq, cpu); i = 0; xt_entry_foreach(iter, t->entries[cpu], t->size) { @@ -720,10 +723,10 @@ static void get_counters(const struct xt_table_info *t, unsigned int start; do { - start = read_seqbegin(lock); + start = read_seqcount_begin(s); bcnt = iter->counters.bcnt; pcnt = iter->counters.pcnt; - } while (read_seqretry(lock, start)); + } while (read_seqcount_retry(s, start)); ADD_COUNTER(counters[i], bcnt, pcnt); ++i; @@ -1115,6 +1118,7 @@ static int do_add_counters(struct net *net, const void __user *user, int ret = 0; void *loc_cpu_entry; struct arpt_entry *iter; + unsigned int addend; #ifdef CONFIG_COMPAT struct compat_xt_counters_info compat_tmp; @@ -1171,12 +1175,12 @@ static int do_add_counters(struct net *net, const void __user *user, /* Choose the copy that is on our node */ curcpu = smp_processor_id(); loc_cpu_entry = private->entries[curcpu]; - xt_info_wrlock(curcpu); + addend = xt_write_recseq_begin(); xt_entry_foreach(iter, loc_cpu_entry, private->size) { ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); ++i; } - xt_info_wrunlock(curcpu); + xt_write_recseq_end(addend); unlock_up_free: local_bh_enable(); xt_table_unlock(t); diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index ffcea0d1678e..2b6b700949eb 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -68,15 +68,6 @@ void *ipt_alloc_initial_table(const struct xt_table *info) } EXPORT_SYMBOL_GPL(ipt_alloc_initial_table); -/* - We keep a set of rules for each CPU, so we can avoid write-locking - them in the softirq when updating the counters and therefore - only need to read-lock in the softirq; doing a write_lock_bh() in user - context stops packets coming through and allows user context to read - the counters or update the rules. - - Hence the start of any table is given by get_table() below. */ - /* Returns whether matches rule or not. */ /* Performance critical - called for every packet */ static inline bool @@ -311,6 +302,7 @@ ipt_do_table(struct sk_buff *skb, unsigned int *stackptr, origptr, cpu; const struct xt_table_info *private; struct xt_action_param acpar; + unsigned int addend; /* Initialization */ ip = ip_hdr(skb); @@ -331,7 +323,8 @@ ipt_do_table(struct sk_buff *skb, acpar.hooknum = hook; IP_NF_ASSERT(table->valid_hooks & (1 << hook)); - xt_info_rdlock_bh(); + local_bh_disable(); + addend = xt_write_recseq_begin(); private = table->private; cpu = smp_processor_id(); table_base = private->entries[cpu]; @@ -430,7 +423,9 @@ ipt_do_table(struct sk_buff *skb, pr_debug("Exiting %s; resetting sp from %u to %u\n", __func__, *stackptr, origptr); *stackptr = origptr; - xt_info_rdunlock_bh(); + xt_write_recseq_end(addend); + local_bh_enable(); + #ifdef DEBUG_ALLOW_ALL return NF_ACCEPT; #else @@ -886,7 +881,7 @@ get_counters(const struct xt_table_info *t, unsigned int i; for_each_possible_cpu(cpu) { - seqlock_t *lock = &per_cpu(xt_info_locks, cpu).lock; + seqcount_t *s = &per_cpu(xt_recseq, cpu); i = 0; xt_entry_foreach(iter, t->entries[cpu], t->size) { @@ -894,10 +889,10 @@ get_counters(const struct xt_table_info *t, unsigned int start; do { - start = read_seqbegin(lock); + start = read_seqcount_begin(s); bcnt = iter->counters.bcnt; pcnt = iter->counters.pcnt; - } while (read_seqretry(lock, start)); + } while (read_seqcount_retry(s, start)); ADD_COUNTER(counters[i], bcnt, pcnt); ++i; /* macro does multi eval of i */ @@ -1312,6 +1307,7 @@ do_add_counters(struct net *net, const void __user *user, int ret = 0; void *loc_cpu_entry; struct ipt_entry *iter; + unsigned int addend; #ifdef CONFIG_COMPAT struct compat_xt_counters_info compat_tmp; @@ -1368,12 +1364,12 @@ do_add_counters(struct net *net, const void __user *user, /* Choose the copy that is on our node */ curcpu = smp_processor_id(); loc_cpu_entry = private->entries[curcpu]; - xt_info_wrlock(curcpu); + addend = xt_write_recseq_begin(); xt_entry_foreach(iter, loc_cpu_entry, private->size) { ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); ++i; } - xt_info_wrunlock(curcpu); + xt_write_recseq_end(addend); unlock_up_free: local_bh_enable(); xt_table_unlock(t); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 0b2af9b85cec..ec7cf579cdd4 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -340,6 +340,7 @@ ip6t_do_table(struct sk_buff *skb, unsigned int *stackptr, origptr, cpu; const struct xt_table_info *private; struct xt_action_param acpar; + unsigned int addend; /* Initialization */ indev = in ? in->name : nulldevname; @@ -358,7 +359,8 @@ ip6t_do_table(struct sk_buff *skb, IP_NF_ASSERT(table->valid_hooks & (1 << hook)); - xt_info_rdlock_bh(); + local_bh_disable(); + addend = xt_write_recseq_begin(); private = table->private; cpu = smp_processor_id(); table_base = private->entries[cpu]; @@ -442,7 +444,9 @@ ip6t_do_table(struct sk_buff *skb, } while (!acpar.hotdrop); *stackptr = origptr; - xt_info_rdunlock_bh(); + + xt_write_recseq_end(addend); + local_bh_enable(); #ifdef DEBUG_ALLOW_ALL return NF_ACCEPT; @@ -899,7 +903,7 @@ get_counters(const struct xt_table_info *t, unsigned int i; for_each_possible_cpu(cpu) { - seqlock_t *lock = &per_cpu(xt_info_locks, cpu).lock; + seqcount_t *s = &per_cpu(xt_recseq, cpu); i = 0; xt_entry_foreach(iter, t->entries[cpu], t->size) { @@ -907,10 +911,10 @@ get_counters(const struct xt_table_info *t, unsigned int start; do { - start = read_seqbegin(lock); + start = read_seqcount_begin(s); bcnt = iter->counters.bcnt; pcnt = iter->counters.pcnt; - } while (read_seqretry(lock, start)); + } while (read_seqcount_retry(s, start)); ADD_COUNTER(counters[i], bcnt, pcnt); ++i; @@ -1325,6 +1329,7 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, int ret = 0; const void *loc_cpu_entry; struct ip6t_entry *iter; + unsigned int addend; #ifdef CONFIG_COMPAT struct compat_xt_counters_info compat_tmp; @@ -1381,13 +1386,13 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, i = 0; /* Choose the copy that is on our node */ curcpu = smp_processor_id(); - xt_info_wrlock(curcpu); + addend = xt_write_recseq_begin(); loc_cpu_entry = private->entries[curcpu]; xt_entry_foreach(iter, loc_cpu_entry, private->size) { ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); ++i; } - xt_info_wrunlock(curcpu); + xt_write_recseq_end(addend); unlock_up_free: local_bh_enable(); diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index a9adf4c6b299..52959efca858 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -762,8 +762,8 @@ void xt_compat_unlock(u_int8_t af) EXPORT_SYMBOL_GPL(xt_compat_unlock); #endif -DEFINE_PER_CPU(struct xt_info_lock, xt_info_locks); -EXPORT_PER_CPU_SYMBOL_GPL(xt_info_locks); +DEFINE_PER_CPU(seqcount_t, xt_recseq); +EXPORT_PER_CPU_SYMBOL_GPL(xt_recseq); static int xt_jumpstack_alloc(struct xt_table_info *i) { @@ -1362,10 +1362,7 @@ static int __init xt_init(void) int rv; for_each_possible_cpu(i) { - struct xt_info_lock *lock = &per_cpu(xt_info_locks, i); - - seqlock_init(&lock->lock); - lock->readers = 0; + seqcount_init(&per_cpu(xt_recseq, i)); } xt = kmalloc(sizeof(struct xt_af) * NFPROTO_NUMPROTO, GFP_KERNEL); -- cgit v1.2.3-58-ga151 From fc3e5941248be00996150965a469d38c92913ac2 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 4 Apr 2011 11:07:57 -0700 Subject: xen: netfront: assume all hw features are available until backend connection setup We need to assume that all features will be available when registering the netdev otherwise they are ommitted from the initial set of dev->wanted_features. When we connect to the backed we reduce the set as necessary due to the call to netdev_update_features() in xennet_connect(). Signed-off-by: Ian Campbell Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 0cfe4ccf92d2..db9a763aaa7f 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1251,6 +1251,14 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev NETIF_F_GSO_ROBUST; netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO; + /* + * Assume that all hw features are available for now. This set + * will be adjusted by the call to netdev_update_features() in + * xennet_connect() which is the earliest point where we can + * negotiate with the backend regarding supported features. + */ + netdev->features |= netdev->hw_features; + SET_ETHTOOL_OPS(netdev, &xennet_ethtool_ops); SET_NETDEV_DEV(netdev, &dev->dev); -- cgit v1.2.3-58-ga151 From 0545a3037773512d3448557ba048cebb73b3e4af Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 05:30:58 +0000 Subject: pkt_sched: QFQ - quick fair queue scheduler This is an implementation of the Quick Fair Queue scheduler developed by Fabio Checconi. The same algorithm is already implemented in ipfw in FreeBSD. Fabio had an earlier version developed on Linux, I just cleaned it up. Thanks to Eric Dumazet for testing this under load. Signed-off-by: Stephen Hemminger Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/pkt_sched.h | 15 + net/sched/Kconfig | 11 + net/sched/Makefile | 1 + net/sched/sch_qfq.c | 1137 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1164 insertions(+) create mode 100644 net/sched/sch_qfq.c diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index b1032a3fafdc..8062e0a68dda 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -588,4 +588,19 @@ struct tc_sfb_xstats { #define SFB_MAX_PROB 0xFFFF +/* QFQ */ +enum { + TCA_QFQ_UNSPEC, + TCA_QFQ_WEIGHT, + TCA_QFQ_LMAX, + __TCA_QFQ_MAX +}; + +#define TCA_QFQ_MAX (__TCA_QFQ_MAX - 1) + +struct tc_qfq_stats { + __u32 weight; + __u32 lmax; +}; + #endif diff --git a/net/sched/Kconfig b/net/sched/Kconfig index a7a5583d4f68..aeaa2110b699 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -239,6 +239,17 @@ config NET_SCH_CHOKE To compile this code as a module, choose M here: the module will be called sch_choke. +config NET_SCH_QFQ + tristate "Quick Fair Queueing scheduler (QFQ)" + help + Say Y here if you want to use the Quick Fair Queueing Scheduler (QFQ) + packet scheduling algorithm. + + To compile this driver as a module, choose M here: the module + will be called sch_qfq. + + If unsure, say N. + config NET_SCH_INGRESS tristate "Ingress Qdisc" depends on NET_CLS_ACT diff --git a/net/sched/Makefile b/net/sched/Makefile index 2e77b8dba22e..dc5889c0a15a 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_NET_SCH_NETEM) += sch_netem.o obj-$(CONFIG_NET_SCH_DRR) += sch_drr.o obj-$(CONFIG_NET_SCH_MQPRIO) += sch_mqprio.o obj-$(CONFIG_NET_SCH_CHOKE) += sch_choke.o +obj-$(CONFIG_NET_SCH_QFQ) += sch_qfq.o obj-$(CONFIG_NET_CLS_U32) += cls_u32.o obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c new file mode 100644 index 000000000000..103343408593 --- /dev/null +++ b/net/sched/sch_qfq.c @@ -0,0 +1,1137 @@ +/* + * net/sched/sch_qfq.c Quick Fair Queueing Scheduler. + * + * Copyright (c) 2009 Fabio Checconi, Luigi Rizzo, and Paolo Valente. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Quick Fair Queueing + =================== + + Sources: + + Fabio Checconi, Luigi Rizzo, and Paolo Valente: "QFQ: Efficient + Packet Scheduling with Tight Bandwidth Distribution Guarantees." + + See also: + http://retis.sssup.it/~fabio/linux/qfq/ + */ + +/* + + Virtual time computations. + + S, F and V are all computed in fixed point arithmetic with + FRAC_BITS decimal bits. + + QFQ_MAX_INDEX is the maximum index allowed for a group. We need + one bit per index. + QFQ_MAX_WSHIFT is the maximum power of two supported as a weight. + + The layout of the bits is as below: + + [ MTU_SHIFT ][ FRAC_BITS ] + [ MAX_INDEX ][ MIN_SLOT_SHIFT ] + ^.__grp->index = 0 + *.__grp->slot_shift + + where MIN_SLOT_SHIFT is derived by difference from the others. + + The max group index corresponds to Lmax/w_min, where + Lmax=1<group mapping. We allow class weights that are + * in the range [1, 2^MAX_WSHIFT], and we try to map each class i to the + * group with the smallest index that can support the L_i / r_i configured + * for the class. + * + * grp->index is the index of the group; and grp->slot_shift + * is the shift for the corresponding (scaled) sigma_i. + */ +#define QFQ_MAX_INDEX 19 +#define QFQ_MAX_WSHIFT 16 + +#define QFQ_MAX_WEIGHT (1<clhash, classid); + if (clc == NULL) + return NULL; + return container_of(clc, struct qfq_class, common); +} + +static void qfq_purge_queue(struct qfq_class *cl) +{ + unsigned int len = cl->qdisc->q.qlen; + + qdisc_reset(cl->qdisc); + qdisc_tree_decrease_qlen(cl->qdisc, len); +} + +static const struct nla_policy qfq_policy[TCA_QFQ_MAX + 1] = { + [TCA_QFQ_WEIGHT] = { .type = NLA_U32 }, + [TCA_QFQ_LMAX] = { .type = NLA_U32 }, +}; + +/* + * Calculate a flow index, given its weight and maximum packet length. + * index = log_2(maxlen/weight) but we need to apply the scaling. + * This is used only once at flow creation. + */ +static int qfq_calc_index(u32 inv_w, unsigned int maxlen) +{ + u64 slot_size = (u64)maxlen * inv_w; + unsigned long size_map; + int index = 0; + + size_map = slot_size >> QFQ_MIN_SLOT_SHIFT; + if (!size_map) + goto out; + + index = __fls(size_map) + 1; /* basically a log_2 */ + index -= !(slot_size - (1ULL << (index + QFQ_MIN_SLOT_SHIFT - 1))); + + if (index < 0) + index = 0; +out: + pr_debug("qfq calc_index: W = %lu, L = %u, I = %d\n", + (unsigned long) ONE_FP/inv_w, maxlen, index); + + return index; +} + +static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, + struct nlattr **tca, unsigned long *arg) +{ + struct qfq_sched *q = qdisc_priv(sch); + struct qfq_class *cl = (struct qfq_class *)*arg; + struct nlattr *tb[TCA_QFQ_MAX + 1]; + u32 weight, lmax, inv_w; + int i, err; + + if (tca[TCA_OPTIONS] == NULL) { + pr_notice("qfq: no options\n"); + return -EINVAL; + } + + err = nla_parse_nested(tb, TCA_QFQ_MAX, tca[TCA_OPTIONS], qfq_policy); + if (err < 0) + return err; + + if (tb[TCA_QFQ_WEIGHT]) { + weight = nla_get_u32(tb[TCA_QFQ_WEIGHT]); + if (!weight || weight > (1UL << QFQ_MAX_WSHIFT)) { + pr_notice("qfq: invalid weight %u\n", weight); + return -EINVAL; + } + } else + weight = 1; + + inv_w = ONE_FP / weight; + weight = ONE_FP / inv_w; + if (q->wsum + weight > QFQ_MAX_WSUM) { + pr_notice("qfq: total weight out of range (%u + %u)\n", + weight, q->wsum); + return -EINVAL; + } + + if (tb[TCA_QFQ_LMAX]) { + lmax = nla_get_u32(tb[TCA_QFQ_LMAX]); + if (!lmax || lmax > (1UL << QFQ_MTU_SHIFT)) { + pr_notice("qfq: invalid max length %u\n", lmax); + return -EINVAL; + } + } else + lmax = 1UL << QFQ_MTU_SHIFT; + + if (cl != NULL) { + if (tca[TCA_RATE]) { + err = gen_replace_estimator(&cl->bstats, &cl->rate_est, + qdisc_root_sleeping_lock(sch), + tca[TCA_RATE]); + if (err) + return err; + } + + sch_tree_lock(sch); + if (tb[TCA_QFQ_WEIGHT]) { + q->wsum = weight - ONE_FP / cl->inv_w; + cl->inv_w = inv_w; + } + sch_tree_unlock(sch); + + return 0; + } + + cl = kzalloc(sizeof(struct qfq_class), GFP_KERNEL); + if (cl == NULL) + return -ENOBUFS; + + cl->refcnt = 1; + cl->common.classid = classid; + cl->lmax = lmax; + cl->inv_w = inv_w; + i = qfq_calc_index(cl->inv_w, cl->lmax); + + cl->grp = &q->groups[i]; + q->wsum += weight; + + cl->qdisc = qdisc_create_dflt(sch->dev_queue, + &pfifo_qdisc_ops, classid); + if (cl->qdisc == NULL) + cl->qdisc = &noop_qdisc; + + if (tca[TCA_RATE]) { + err = gen_new_estimator(&cl->bstats, &cl->rate_est, + qdisc_root_sleeping_lock(sch), + tca[TCA_RATE]); + if (err) { + qdisc_destroy(cl->qdisc); + kfree(cl); + return err; + } + } + + sch_tree_lock(sch); + qdisc_class_hash_insert(&q->clhash, &cl->common); + sch_tree_unlock(sch); + + qdisc_class_hash_grow(sch, &q->clhash); + + *arg = (unsigned long)cl; + return 0; +} + +static void qfq_destroy_class(struct Qdisc *sch, struct qfq_class *cl) +{ + struct qfq_sched *q = qdisc_priv(sch); + + if (cl->inv_w) { + q->wsum -= ONE_FP / cl->inv_w; + cl->inv_w = 0; + } + + gen_kill_estimator(&cl->bstats, &cl->rate_est); + qdisc_destroy(cl->qdisc); + kfree(cl); +} + +static int qfq_delete_class(struct Qdisc *sch, unsigned long arg) +{ + struct qfq_sched *q = qdisc_priv(sch); + struct qfq_class *cl = (struct qfq_class *)arg; + + if (cl->filter_cnt > 0) + return -EBUSY; + + sch_tree_lock(sch); + + qfq_purge_queue(cl); + qdisc_class_hash_remove(&q->clhash, &cl->common); + + BUG_ON(--cl->refcnt == 0); + /* + * This shouldn't happen: we "hold" one cops->get() when called + * from tc_ctl_tclass; the destroy method is done from cops->put(). + */ + + sch_tree_unlock(sch); + return 0; +} + +static unsigned long qfq_get_class(struct Qdisc *sch, u32 classid) +{ + struct qfq_class *cl = qfq_find_class(sch, classid); + + if (cl != NULL) + cl->refcnt++; + + return (unsigned long)cl; +} + +static void qfq_put_class(struct Qdisc *sch, unsigned long arg) +{ + struct qfq_class *cl = (struct qfq_class *)arg; + + if (--cl->refcnt == 0) + qfq_destroy_class(sch, cl); +} + +static struct tcf_proto **qfq_tcf_chain(struct Qdisc *sch, unsigned long cl) +{ + struct qfq_sched *q = qdisc_priv(sch); + + if (cl) + return NULL; + + return &q->filter_list; +} + +static unsigned long qfq_bind_tcf(struct Qdisc *sch, unsigned long parent, + u32 classid) +{ + struct qfq_class *cl = qfq_find_class(sch, classid); + + if (cl != NULL) + cl->filter_cnt++; + + return (unsigned long)cl; +} + +static void qfq_unbind_tcf(struct Qdisc *sch, unsigned long arg) +{ + struct qfq_class *cl = (struct qfq_class *)arg; + + cl->filter_cnt--; +} + +static int qfq_graft_class(struct Qdisc *sch, unsigned long arg, + struct Qdisc *new, struct Qdisc **old) +{ + struct qfq_class *cl = (struct qfq_class *)arg; + + if (new == NULL) { + new = qdisc_create_dflt(sch->dev_queue, + &pfifo_qdisc_ops, cl->common.classid); + if (new == NULL) + new = &noop_qdisc; + } + + sch_tree_lock(sch); + qfq_purge_queue(cl); + *old = cl->qdisc; + cl->qdisc = new; + sch_tree_unlock(sch); + return 0; +} + +static struct Qdisc *qfq_class_leaf(struct Qdisc *sch, unsigned long arg) +{ + struct qfq_class *cl = (struct qfq_class *)arg; + + return cl->qdisc; +} + +static int qfq_dump_class(struct Qdisc *sch, unsigned long arg, + struct sk_buff *skb, struct tcmsg *tcm) +{ + struct qfq_class *cl = (struct qfq_class *)arg; + struct nlattr *nest; + + tcm->tcm_parent = TC_H_ROOT; + tcm->tcm_handle = cl->common.classid; + tcm->tcm_info = cl->qdisc->handle; + + nest = nla_nest_start(skb, TCA_OPTIONS); + if (nest == NULL) + goto nla_put_failure; + NLA_PUT_U32(skb, TCA_QFQ_WEIGHT, ONE_FP/cl->inv_w); + NLA_PUT_U32(skb, TCA_QFQ_LMAX, cl->lmax); + return nla_nest_end(skb, nest); + +nla_put_failure: + nla_nest_cancel(skb, nest); + return -EMSGSIZE; +} + +static int qfq_dump_class_stats(struct Qdisc *sch, unsigned long arg, + struct gnet_dump *d) +{ + struct qfq_class *cl = (struct qfq_class *)arg; + struct tc_qfq_stats xstats; + + memset(&xstats, 0, sizeof(xstats)); + cl->qdisc->qstats.qlen = cl->qdisc->q.qlen; + + xstats.weight = ONE_FP/cl->inv_w; + xstats.lmax = cl->lmax; + + if (gnet_stats_copy_basic(d, &cl->bstats) < 0 || + gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 || + gnet_stats_copy_queue(d, &cl->qdisc->qstats) < 0) + return -1; + + return gnet_stats_copy_app(d, &xstats, sizeof(xstats)); +} + +static void qfq_walk(struct Qdisc *sch, struct qdisc_walker *arg) +{ + struct qfq_sched *q = qdisc_priv(sch); + struct qfq_class *cl; + struct hlist_node *n; + unsigned int i; + + if (arg->stop) + return; + + for (i = 0; i < q->clhash.hashsize; i++) { + hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) { + if (arg->count < arg->skip) { + arg->count++; + continue; + } + if (arg->fn(sch, (unsigned long)cl, arg) < 0) { + arg->stop = 1; + return; + } + arg->count++; + } + } +} + +static struct qfq_class *qfq_classify(struct sk_buff *skb, struct Qdisc *sch, + int *qerr) +{ + struct qfq_sched *q = qdisc_priv(sch); + struct qfq_class *cl; + struct tcf_result res; + int result; + + if (TC_H_MAJ(skb->priority ^ sch->handle) == 0) { + pr_debug("qfq_classify: found %d\n", skb->priority); + cl = qfq_find_class(sch, skb->priority); + if (cl != NULL) + return cl; + } + + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; + result = tc_classify(skb, q->filter_list, &res); + if (result >= 0) { +#ifdef CONFIG_NET_CLS_ACT + switch (result) { + case TC_ACT_QUEUED: + case TC_ACT_STOLEN: + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; + case TC_ACT_SHOT: + return NULL; + } +#endif + cl = (struct qfq_class *)res.class; + if (cl == NULL) + cl = qfq_find_class(sch, res.classid); + return cl; + } + + return NULL; +} + +/* Generic comparison function, handling wraparound. */ +static inline int qfq_gt(u64 a, u64 b) +{ + return (s64)(a - b) > 0; +} + +/* Round a precise timestamp to its slotted value. */ +static inline u64 qfq_round_down(u64 ts, unsigned int shift) +{ + return ts & ~((1ULL << shift) - 1); +} + +/* return the pointer to the group with lowest index in the bitmap */ +static inline struct qfq_group *qfq_ffs(struct qfq_sched *q, + unsigned long bitmap) +{ + int index = __ffs(bitmap); + return &q->groups[index]; +} +/* Calculate a mask to mimic what would be ffs_from(). */ +static inline unsigned long mask_from(unsigned long bitmap, int from) +{ + return bitmap & ~((1UL << from) - 1); +} + +/* + * The state computation relies on ER=0, IR=1, EB=2, IB=3 + * First compute eligibility comparing grp->S, q->V, + * then check if someone is blocking us and possibly add EB + */ +static int qfq_calc_state(struct qfq_sched *q, const struct qfq_group *grp) +{ + /* if S > V we are not eligible */ + unsigned int state = qfq_gt(grp->S, q->V); + unsigned long mask = mask_from(q->bitmaps[ER], grp->index); + struct qfq_group *next; + + if (mask) { + next = qfq_ffs(q, mask); + if (qfq_gt(grp->F, next->F)) + state |= EB; + } + + return state; +} + + +/* + * In principle + * q->bitmaps[dst] |= q->bitmaps[src] & mask; + * q->bitmaps[src] &= ~mask; + * but we should make sure that src != dst + */ +static inline void qfq_move_groups(struct qfq_sched *q, unsigned long mask, + int src, int dst) +{ + q->bitmaps[dst] |= q->bitmaps[src] & mask; + q->bitmaps[src] &= ~mask; +} + +static void qfq_unblock_groups(struct qfq_sched *q, int index, u64 old_F) +{ + unsigned long mask = mask_from(q->bitmaps[ER], index + 1); + struct qfq_group *next; + + if (mask) { + next = qfq_ffs(q, mask); + if (!qfq_gt(next->F, old_F)) + return; + } + + mask = (1UL << index) - 1; + qfq_move_groups(q, mask, EB, ER); + qfq_move_groups(q, mask, IB, IR); +} + +/* + * perhaps + * + old_V ^= q->V; + old_V >>= QFQ_MIN_SLOT_SHIFT; + if (old_V) { + ... + } + * + */ +static void qfq_make_eligible(struct qfq_sched *q, u64 old_V) +{ + unsigned long vslot = q->V >> QFQ_MIN_SLOT_SHIFT; + unsigned long old_vslot = old_V >> QFQ_MIN_SLOT_SHIFT; + + if (vslot != old_vslot) { + unsigned long mask = (1UL << fls(vslot ^ old_vslot)) - 1; + qfq_move_groups(q, mask, IR, ER); + qfq_move_groups(q, mask, IB, EB); + } +} + + +/* + * XXX we should make sure that slot becomes less than 32. + * This is guaranteed by the input values. + * roundedS is always cl->S rounded on grp->slot_shift bits. + */ +static void qfq_slot_insert(struct qfq_group *grp, struct qfq_class *cl, + u64 roundedS) +{ + u64 slot = (roundedS - grp->S) >> grp->slot_shift; + unsigned int i = (grp->front + slot) % QFQ_MAX_SLOTS; + + hlist_add_head(&cl->next, &grp->slots[i]); + __set_bit(slot, &grp->full_slots); +} + +/* Maybe introduce hlist_first_entry?? */ +static struct qfq_class *qfq_slot_head(struct qfq_group *grp) +{ + return hlist_entry(grp->slots[grp->front].first, + struct qfq_class, next); +} + +/* + * remove the entry from the slot + */ +static void qfq_front_slot_remove(struct qfq_group *grp) +{ + struct qfq_class *cl = qfq_slot_head(grp); + + BUG_ON(!cl); + hlist_del(&cl->next); + if (hlist_empty(&grp->slots[grp->front])) + __clear_bit(0, &grp->full_slots); +} + +/* + * Returns the first full queue in a group. As a side effect, + * adjust the bucket list so the first non-empty bucket is at + * position 0 in full_slots. + */ +static struct qfq_class *qfq_slot_scan(struct qfq_group *grp) +{ + unsigned int i; + + pr_debug("qfq slot_scan: grp %u full %#lx\n", + grp->index, grp->full_slots); + + if (grp->full_slots == 0) + return NULL; + + i = __ffs(grp->full_slots); /* zero based */ + if (i > 0) { + grp->front = (grp->front + i) % QFQ_MAX_SLOTS; + grp->full_slots >>= i; + } + + return qfq_slot_head(grp); +} + +/* + * adjust the bucket list. When the start time of a group decreases, + * we move the index down (modulo QFQ_MAX_SLOTS) so we don't need to + * move the objects. The mask of occupied slots must be shifted + * because we use ffs() to find the first non-empty slot. + * This covers decreases in the group's start time, but what about + * increases of the start time ? + * Here too we should make sure that i is less than 32 + */ +static void qfq_slot_rotate(struct qfq_group *grp, u64 roundedS) +{ + unsigned int i = (grp->S - roundedS) >> grp->slot_shift; + + grp->full_slots <<= i; + grp->front = (grp->front - i) % QFQ_MAX_SLOTS; +} + +static void qfq_update_eligible(struct qfq_sched *q, u64 old_V) +{ + struct qfq_group *grp; + unsigned long ineligible; + + ineligible = q->bitmaps[IR] | q->bitmaps[IB]; + if (ineligible) { + if (!q->bitmaps[ER]) { + grp = qfq_ffs(q, ineligible); + if (qfq_gt(grp->S, q->V)) + q->V = grp->S; + } + qfq_make_eligible(q, old_V); + } +} + +/* What is length of next packet in queue (0 if queue is empty) */ +static unsigned int qdisc_peek_len(struct Qdisc *sch) +{ + struct sk_buff *skb; + + skb = sch->ops->peek(sch); + return skb ? qdisc_pkt_len(skb) : 0; +} + +/* + * Updates the class, returns true if also the group needs to be updated. + */ +static bool qfq_update_class(struct qfq_group *grp, struct qfq_class *cl) +{ + unsigned int len = qdisc_peek_len(cl->qdisc); + + cl->S = cl->F; + if (!len) + qfq_front_slot_remove(grp); /* queue is empty */ + else { + u64 roundedS; + + cl->F = cl->S + (u64)len * cl->inv_w; + roundedS = qfq_round_down(cl->S, grp->slot_shift); + if (roundedS == grp->S) + return false; + + qfq_front_slot_remove(grp); + qfq_slot_insert(grp, cl, roundedS); + } + + return true; +} + +static struct sk_buff *qfq_dequeue(struct Qdisc *sch) +{ + struct qfq_sched *q = qdisc_priv(sch); + struct qfq_group *grp; + struct qfq_class *cl; + struct sk_buff *skb; + unsigned int len; + u64 old_V; + + if (!q->bitmaps[ER]) + return NULL; + + grp = qfq_ffs(q, q->bitmaps[ER]); + + cl = qfq_slot_head(grp); + skb = qdisc_dequeue_peeked(cl->qdisc); + if (!skb) { + WARN_ONCE(1, "qfq_dequeue: non-workconserving leaf\n"); + return NULL; + } + + sch->q.qlen--; + qdisc_bstats_update(sch, skb); + + old_V = q->V; + len = qdisc_pkt_len(skb); + q->V += (u64)len * IWSUM; + pr_debug("qfq dequeue: len %u F %lld now %lld\n", + len, (unsigned long long) cl->F, (unsigned long long) q->V); + + if (qfq_update_class(grp, cl)) { + u64 old_F = grp->F; + + cl = qfq_slot_scan(grp); + if (!cl) + __clear_bit(grp->index, &q->bitmaps[ER]); + else { + u64 roundedS = qfq_round_down(cl->S, grp->slot_shift); + unsigned int s; + + if (grp->S == roundedS) + goto skip_unblock; + grp->S = roundedS; + grp->F = roundedS + (2ULL << grp->slot_shift); + __clear_bit(grp->index, &q->bitmaps[ER]); + s = qfq_calc_state(q, grp); + __set_bit(grp->index, &q->bitmaps[s]); + } + + qfq_unblock_groups(q, grp->index, old_F); + } + +skip_unblock: + qfq_update_eligible(q, old_V); + + return skb; +} + +/* + * Assign a reasonable start time for a new flow k in group i. + * Admissible values for \hat(F) are multiples of \sigma_i + * no greater than V+\sigma_i . Larger values mean that + * we had a wraparound so we consider the timestamp to be stale. + * + * If F is not stale and F >= V then we set S = F. + * Otherwise we should assign S = V, but this may violate + * the ordering in ER. So, if we have groups in ER, set S to + * the F_j of the first group j which would be blocking us. + * We are guaranteed not to move S backward because + * otherwise our group i would still be blocked. + */ +static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl) +{ + unsigned long mask; + uint32_t limit, roundedF; + int slot_shift = cl->grp->slot_shift; + + roundedF = qfq_round_down(cl->F, slot_shift); + limit = qfq_round_down(q->V, slot_shift) + (1UL << slot_shift); + + if (!qfq_gt(cl->F, q->V) || qfq_gt(roundedF, limit)) { + /* timestamp was stale */ + mask = mask_from(q->bitmaps[ER], cl->grp->index); + if (mask) { + struct qfq_group *next = qfq_ffs(q, mask); + if (qfq_gt(roundedF, next->F)) { + cl->S = next->F; + return; + } + } + cl->S = q->V; + } else /* timestamp is not stale */ + cl->S = cl->F; +} + +static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) +{ + struct qfq_sched *q = qdisc_priv(sch); + struct qfq_group *grp; + struct qfq_class *cl; + int err; + u64 roundedS; + int s; + + cl = qfq_classify(skb, sch, &err); + if (cl == NULL) { + if (err & __NET_XMIT_BYPASS) + sch->qstats.drops++; + kfree_skb(skb); + return err; + } + pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid); + + err = qdisc_enqueue(skb, cl->qdisc); + if (unlikely(err != NET_XMIT_SUCCESS)) { + pr_debug("qfq_enqueue: enqueue failed %d\n", err); + if (net_xmit_drop_count(err)) { + cl->qstats.drops++; + sch->qstats.drops++; + } + return err; + } + + bstats_update(&cl->bstats, skb); + ++sch->q.qlen; + + /* If the new skb is not the head of queue, then done here. */ + if (cl->qdisc->q.qlen != 1) + return err; + + /* If reach this point, queue q was idle */ + grp = cl->grp; + qfq_update_start(q, cl); + + /* compute new finish time and rounded start. */ + cl->F = cl->S + (u64)qdisc_pkt_len(skb) * cl->inv_w; + roundedS = qfq_round_down(cl->S, grp->slot_shift); + + /* + * insert cl in the correct bucket. + * If cl->S >= grp->S we don't need to adjust the + * bucket list and simply go to the insertion phase. + * Otherwise grp->S is decreasing, we must make room + * in the bucket list, and also recompute the group state. + * Finally, if there were no flows in this group and nobody + * was in ER make sure to adjust V. + */ + if (grp->full_slots) { + if (!qfq_gt(grp->S, cl->S)) + goto skip_update; + + /* create a slot for this cl->S */ + qfq_slot_rotate(grp, roundedS); + /* group was surely ineligible, remove */ + __clear_bit(grp->index, &q->bitmaps[IR]); + __clear_bit(grp->index, &q->bitmaps[IB]); + } else if (!q->bitmaps[ER] && qfq_gt(roundedS, q->V)) + q->V = roundedS; + + grp->S = roundedS; + grp->F = roundedS + (2ULL << grp->slot_shift); + s = qfq_calc_state(q, grp); + __set_bit(grp->index, &q->bitmaps[s]); + + pr_debug("qfq enqueue: new state %d %#lx S %lld F %lld V %lld\n", + s, q->bitmaps[s], + (unsigned long long) cl->S, + (unsigned long long) cl->F, + (unsigned long long) q->V); + +skip_update: + qfq_slot_insert(grp, cl, roundedS); + + return err; +} + + +static void qfq_slot_remove(struct qfq_sched *q, struct qfq_group *grp, + struct qfq_class *cl) +{ + unsigned int i, offset; + u64 roundedS; + + roundedS = qfq_round_down(cl->S, grp->slot_shift); + offset = (roundedS - grp->S) >> grp->slot_shift; + i = (grp->front + offset) % QFQ_MAX_SLOTS; + + hlist_del(&cl->next); + if (hlist_empty(&grp->slots[i])) + __clear_bit(offset, &grp->full_slots); +} + +/* + * called to forcibly destroy a queue. + * If the queue is not in the front bucket, or if it has + * other queues in the front bucket, we can simply remove + * the queue with no other side effects. + * Otherwise we must propagate the event up. + */ +static void qfq_deactivate_class(struct qfq_sched *q, struct qfq_class *cl) +{ + struct qfq_group *grp = cl->grp; + unsigned long mask; + u64 roundedS; + int s; + + cl->F = cl->S; + qfq_slot_remove(q, grp, cl); + + if (!grp->full_slots) { + __clear_bit(grp->index, &q->bitmaps[IR]); + __clear_bit(grp->index, &q->bitmaps[EB]); + __clear_bit(grp->index, &q->bitmaps[IB]); + + if (test_bit(grp->index, &q->bitmaps[ER]) && + !(q->bitmaps[ER] & ~((1UL << grp->index) - 1))) { + mask = q->bitmaps[ER] & ((1UL << grp->index) - 1); + if (mask) + mask = ~((1UL << __fls(mask)) - 1); + else + mask = ~0UL; + qfq_move_groups(q, mask, EB, ER); + qfq_move_groups(q, mask, IB, IR); + } + __clear_bit(grp->index, &q->bitmaps[ER]); + } else if (hlist_empty(&grp->slots[grp->front])) { + cl = qfq_slot_scan(grp); + roundedS = qfq_round_down(cl->S, grp->slot_shift); + if (grp->S != roundedS) { + __clear_bit(grp->index, &q->bitmaps[ER]); + __clear_bit(grp->index, &q->bitmaps[IR]); + __clear_bit(grp->index, &q->bitmaps[EB]); + __clear_bit(grp->index, &q->bitmaps[IB]); + grp->S = roundedS; + grp->F = roundedS + (2ULL << grp->slot_shift); + s = qfq_calc_state(q, grp); + __set_bit(grp->index, &q->bitmaps[s]); + } + } + + qfq_update_eligible(q, q->V); +} + +static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg) +{ + struct qfq_sched *q = qdisc_priv(sch); + struct qfq_class *cl = (struct qfq_class *)arg; + + if (cl->qdisc->q.qlen == 0) + qfq_deactivate_class(q, cl); +} + +static unsigned int qfq_drop(struct Qdisc *sch) +{ + struct qfq_sched *q = qdisc_priv(sch); + struct qfq_group *grp; + unsigned int i, j, len; + + for (i = 0; i <= QFQ_MAX_INDEX; i++) { + grp = &q->groups[i]; + for (j = 0; j < QFQ_MAX_SLOTS; j++) { + struct qfq_class *cl; + struct hlist_node *n; + + hlist_for_each_entry(cl, n, &grp->slots[j], next) { + + if (!cl->qdisc->ops->drop) + continue; + + len = cl->qdisc->ops->drop(cl->qdisc); + if (len > 0) { + sch->q.qlen--; + if (!cl->qdisc->q.qlen) + qfq_deactivate_class(q, cl); + + return len; + } + } + } + } + + return 0; +} + +static int qfq_init_qdisc(struct Qdisc *sch, struct nlattr *opt) +{ + struct qfq_sched *q = qdisc_priv(sch); + struct qfq_group *grp; + int i, j, err; + + err = qdisc_class_hash_init(&q->clhash); + if (err < 0) + return err; + + for (i = 0; i <= QFQ_MAX_INDEX; i++) { + grp = &q->groups[i]; + grp->index = i; + grp->slot_shift = QFQ_MTU_SHIFT + FRAC_BITS + - (QFQ_MAX_INDEX - i); + for (j = 0; j < QFQ_MAX_SLOTS; j++) + INIT_HLIST_HEAD(&grp->slots[j]); + } + + return 0; +} + +static void qfq_reset_qdisc(struct Qdisc *sch) +{ + struct qfq_sched *q = qdisc_priv(sch); + struct qfq_group *grp; + struct qfq_class *cl; + struct hlist_node *n, *tmp; + unsigned int i, j; + + for (i = 0; i <= QFQ_MAX_INDEX; i++) { + grp = &q->groups[i]; + for (j = 0; j < QFQ_MAX_SLOTS; j++) { + hlist_for_each_entry_safe(cl, n, tmp, + &grp->slots[j], next) { + qfq_deactivate_class(q, cl); + } + } + } + + for (i = 0; i < q->clhash.hashsize; i++) { + hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) + qdisc_reset(cl->qdisc); + } + sch->q.qlen = 0; +} + +static void qfq_destroy_qdisc(struct Qdisc *sch) +{ + struct qfq_sched *q = qdisc_priv(sch); + struct qfq_class *cl; + struct hlist_node *n, *next; + unsigned int i; + + tcf_destroy_chain(&q->filter_list); + + for (i = 0; i < q->clhash.hashsize; i++) { + hlist_for_each_entry_safe(cl, n, next, &q->clhash.hash[i], + common.hnode) { + qfq_destroy_class(sch, cl); + } + } + qdisc_class_hash_destroy(&q->clhash); +} + +static const struct Qdisc_class_ops qfq_class_ops = { + .change = qfq_change_class, + .delete = qfq_delete_class, + .get = qfq_get_class, + .put = qfq_put_class, + .tcf_chain = qfq_tcf_chain, + .bind_tcf = qfq_bind_tcf, + .unbind_tcf = qfq_unbind_tcf, + .graft = qfq_graft_class, + .leaf = qfq_class_leaf, + .qlen_notify = qfq_qlen_notify, + .dump = qfq_dump_class, + .dump_stats = qfq_dump_class_stats, + .walk = qfq_walk, +}; + +static struct Qdisc_ops qfq_qdisc_ops __read_mostly = { + .cl_ops = &qfq_class_ops, + .id = "qfq", + .priv_size = sizeof(struct qfq_sched), + .enqueue = qfq_enqueue, + .dequeue = qfq_dequeue, + .peek = qdisc_peek_dequeued, + .drop = qfq_drop, + .init = qfq_init_qdisc, + .reset = qfq_reset_qdisc, + .destroy = qfq_destroy_qdisc, + .owner = THIS_MODULE, +}; + +static int __init qfq_init(void) +{ + return register_qdisc(&qfq_qdisc_ops); +} + +static void __exit qfq_exit(void) +{ + unregister_qdisc(&qfq_qdisc_ops); +} + +module_init(qfq_init); +module_exit(qfq_exit); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-58-ga151 From 1c0ce89c87b310e8022f50bb75c1b693ee9d7158 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 25 Mar 2011 17:59:39 +0100 Subject: iwlegacy: MAINTAINERS Add iwlegacy driver to MAINTAINERS. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- MAINTAINERS | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 09d3fc0fbbeb..5dd948b5bc6e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3355,14 +3355,10 @@ F: Documentation/wimax/README.i2400m F: drivers/net/wimax/i2400m/ F: include/linux/wimax/i2400m.h -INTEL PRO/WIRELESS 3945ABG/BG NETWORK CONNECTION SUPPORT +INTEL WIRELESS 3945ABG/BG, 4965AGN (iwlegacy) +M: Stanislaw Gruszka L: linux-wireless@vger.kernel.org -S: Orphan -F: drivers/net/wireless/iwlegacy/ - -INTEL WIRELESS WIFI 4965AGN NETWORK CONNECTION SUPPORT -L: linux-wireless@vger.kernel.org -S: Orphan +S: Supported F: drivers/net/wireless/iwlegacy/ INTEL WIRELESS WIFI LINK (iwlwifi) -- cgit v1.2.3-58-ga151 From 279daf64c01e391379060a6d30e9827cc0c56612 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Wed, 23 Mar 2011 14:04:31 -0700 Subject: wifi: Add hwflags to debugfs. Aids debugging wifi behaviour. Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- net/mac80211/debugfs.c | 89 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 13 deletions(-) diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 51f0d780dafa..0a602dbfdb2b 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -37,7 +37,7 @@ int mac80211_format_buffer(char __user *userbuf, size_t count, return simple_read_from_buffer(userbuf, count, ppos, buf, res); } -#define DEBUGFS_READONLY_FILE(name, fmt, value...) \ +#define DEBUGFS_READONLY_FILE_FN(name, fmt, value...) \ static ssize_t name## _read(struct file *file, char __user *userbuf, \ size_t count, loff_t *ppos) \ { \ @@ -45,14 +45,19 @@ static ssize_t name## _read(struct file *file, char __user *userbuf, \ \ return mac80211_format_buffer(userbuf, count, ppos, \ fmt "\n", ##value); \ -} \ - \ +} + +#define DEBUGFS_READONLY_FILE_OPS(name) \ static const struct file_operations name## _ops = { \ .read = name## _read, \ .open = mac80211_open_file_generic, \ .llseek = generic_file_llseek, \ }; +#define DEBUGFS_READONLY_FILE(name, fmt, value...) \ + DEBUGFS_READONLY_FILE_FN(name, fmt, value) \ + DEBUGFS_READONLY_FILE_OPS(name) + #define DEBUGFS_ADD(name) \ debugfs_create_file(#name, 0400, phyd, local, &name## _ops); @@ -291,11 +296,70 @@ static ssize_t channel_type_read(struct file *file, char __user *user_buf, return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); } -static const struct file_operations channel_type_ops = { - .read = channel_type_read, - .open = mac80211_open_file_generic, - .llseek = default_llseek, -}; +static ssize_t hwflags_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + int mxln = 500; + ssize_t rv; + char *buf = kzalloc(mxln, GFP_KERNEL); + int sf = 0; /* how many written so far */ + + sf += snprintf(buf, mxln - sf, "0x%x\n", local->hw.flags); + if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) + sf += snprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n"); + if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) + sf += snprintf(buf + sf, mxln - sf, "RX_INCLUDES_FCS\n"); + if (local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) + sf += snprintf(buf + sf, mxln - sf, + "HOST_BCAST_PS_BUFFERING\n"); + if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE) + sf += snprintf(buf + sf, mxln - sf, + "2GHZ_SHORT_SLOT_INCAPABLE\n"); + if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE) + sf += snprintf(buf + sf, mxln - sf, + "2GHZ_SHORT_PREAMBLE_INCAPABLE\n"); + if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) + sf += snprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n"); + if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) + sf += snprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n"); + if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) + sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_PERIOD\n"); + if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT) + sf += snprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n"); + if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) + sf += snprintf(buf + sf, mxln - sf, "AMPDU_AGGREGATION\n"); + if (local->hw.flags & IEEE80211_HW_SUPPORTS_PS) + sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PS\n"); + if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) + sf += snprintf(buf + sf, mxln - sf, "PS_NULLFUNC_STACK\n"); + if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) + sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); + if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE) + sf += snprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); + if (local->hw.flags & IEEE80211_HW_BEACON_FILTER) + sf += snprintf(buf + sf, mxln - sf, "BEACON_FILTER\n"); + if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) + sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n"); + if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) + sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_SMPS\n"); + if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) + sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n"); + if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) + sf += snprintf(buf + sf, mxln - sf, "REPORTS_TX_ACK_STATUS\n"); + if (local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) + sf += snprintf(buf + sf, mxln - sf, "CONNECTION_MONITOR\n"); + if (local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) + sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_CQM_RSSI\n"); + if (local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK) + sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); + if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) + sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); + + rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); + kfree(buf); + return rv; +} static ssize_t queues_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -315,11 +379,9 @@ static ssize_t queues_read(struct file *file, char __user *user_buf, return simple_read_from_buffer(user_buf, count, ppos, buf, res); } -static const struct file_operations queues_ops = { - .read = queues_read, - .open = mac80211_open_file_generic, - .llseek = default_llseek, -}; +DEBUGFS_READONLY_FILE_OPS(hwflags); +DEBUGFS_READONLY_FILE_OPS(channel_type); +DEBUGFS_READONLY_FILE_OPS(queues); /* statistics stuff */ @@ -395,6 +457,7 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(uapsd_queues); DEBUGFS_ADD(uapsd_max_sp_len); DEBUGFS_ADD(channel_type); + DEBUGFS_ADD(hwflags); DEBUGFS_ADD(user_power); DEBUGFS_ADD(power); -- cgit v1.2.3-58-ga151 From b64c6a3d1ab1bab9396e6efd2fd03479be4d0a63 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Thu, 24 Mar 2011 14:36:16 +0530 Subject: ath9k: cleanup few redundant macros Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 4 ---- drivers/net/wireless/ath/ath9k/common.c | 2 +- drivers/net/wireless/ath/ath9k/mac.c | 2 -- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 7c91ba4dce41..a43f05993687 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -120,13 +120,11 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, /* RX / TX */ /***********/ -#define ATH_MAX_ANTENNA 3 #define ATH_RXBUF 512 #define ATH_TXBUF 512 #define ATH_TXBUF_RESERVE 5 #define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE) #define ATH_TXMAXTRY 13 -#define ATH_MGT_TXMAXTRY 4 #define TID_TO_WME_AC(_tid) \ ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ @@ -688,8 +686,6 @@ void ath9k_ps_restore(struct ath_softc *sc); u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); -void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); - void ath_start_rfkill_poll(struct ath_softc *sc); extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); void ath9k_calculate_iter_data(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 615e68276e72..16ba8c67fbd5 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -116,7 +116,7 @@ void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, if (chan->band == IEEE80211_BAND_2GHZ) { ichan->chanmode = CHANNEL_G; - ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G; + ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; } else { ichan->chanmode = CHANNEL_A; ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 05efcfbeeadc..6f431cbff38a 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -713,7 +713,6 @@ EXPORT_SYMBOL(ath9k_hw_abortpcurecv); bool ath9k_hw_stopdmarecv(struct ath_hw *ah) { #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ -#define AH_RX_TIME_QUANTUM 100 /* usec */ struct ath_common *common = ath9k_hw_common(ah); int i; @@ -737,7 +736,6 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah) return true; } -#undef AH_RX_TIME_QUANTUM #undef AH_RX_STOP_DMA_TIMEOUT } EXPORT_SYMBOL(ath9k_hw_stopdmarecv); -- cgit v1.2.3-58-ga151 From 468b0d4482cadd174298e2fe9bde6a20044f90f5 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Thu, 24 Mar 2011 15:49:54 +0530 Subject: ath9k: remove set11n_virtualmorefrag This does not seems to be used anywhere so remove it. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_mac.c | 12 ------------ drivers/net/wireless/ath/ath9k/ar9003_mac.c | 12 ------------ drivers/net/wireless/ath/ath9k/hw-ops.h | 6 ------ drivers/net/wireless/ath/ath9k/hw.h | 2 -- 4 files changed, 32 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 399ab3bb299b..8dd8f6308502 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -415,17 +415,6 @@ static void ar9002_hw_set11n_burstduration(struct ath_hw *ah, void *ds, ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); } -static void ar9002_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, - u32 vmf) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - if (vmf) - ads->ds_ctl0 |= AR_VirtMoreFrag; - else - ads->ds_ctl0 &= ~AR_VirtMoreFrag; -} - void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, u32 size, u32 flags) { @@ -459,5 +448,4 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah) ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; ops->clr11n_aggr = ar9002_hw_clr11n_aggr; ops->set11n_burstduration = ar9002_hw_set11n_burstduration; - ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag; } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 038a0cbfc6e7..724ac2464ad5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -485,17 +485,6 @@ static void ar9003_hw_set11n_burstduration(struct ath_hw *ah, void *ds, } -static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, - u32 vmf) -{ - struct ar9003_txc *ads = (struct ar9003_txc *) ds; - - if (vmf) - ads->ctl11 |= AR_VirtMoreFrag; - else - ads->ctl11 &= ~AR_VirtMoreFrag; -} - void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) { struct ar9003_txc *ads = ds; @@ -521,7 +510,6 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; ops->clr11n_aggr = ar9003_hw_clr11n_aggr; ops->set11n_burstduration = ar9003_hw_set11n_burstduration; - ops->set11n_virtualmorefrag = ar9003_hw_set11n_virtualmorefrag; } void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index c8f254fe0f0b..22ee888b0baf 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -122,12 +122,6 @@ static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds, ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration); } -static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, - u32 vmf) -{ - ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); -} - /* Private hardware call ops */ /* PHY ops */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 4cc320bdf0aa..031b1bf0d370 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -628,8 +628,6 @@ struct ath_hw_ops { void (*clr11n_aggr)(struct ath_hw *ah, void *ds); void (*set11n_burstduration)(struct ath_hw *ah, void *ds, u32 burstDuration); - void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, - u32 vmf); }; struct ath_nf_limits { -- cgit v1.2.3-58-ga151 From 2638126a7c7cce87d51ae5d3bfaca9350503c0b4 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Thu, 24 Mar 2011 19:06:40 +0530 Subject: ath9k_hw: remove ath9k_get_channel_edges This function is nowhere used. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 25 ------------------------- drivers/net/wireless/ath/ath9k/hw.h | 3 --- 2 files changed, 28 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 298f4d6cbdbd..be7baf09eb00 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -156,25 +156,6 @@ u32 ath9k_hw_reverse_bits(u32 val, u32 n) return retval; } -bool ath9k_get_channel_edges(struct ath_hw *ah, - u16 flags, u16 *low, - u16 *high) -{ - struct ath9k_hw_capabilities *pCap = &ah->caps; - - if (flags & CHANNEL_5GHZ) { - *low = pCap->low_5ghz_chan; - *high = pCap->high_5ghz_chan; - return true; - } - if ((flags & CHANNEL_2GHZ)) { - *low = pCap->low_2ghz_chan; - *high = pCap->high_2ghz_chan; - return true; - } - return false; -} - u16 ath9k_hw_computetxtime(struct ath_hw *ah, u8 phy, int kbps, u32 frameLen, u16 rateix, @@ -1867,12 +1848,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if (AR_SREV_9300_20_OR_LATER(ah)) ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH; - pCap->low_2ghz_chan = 2312; - pCap->high_2ghz_chan = 2732; - - pCap->low_5ghz_chan = 4920; - pCap->high_5ghz_chan = 6100; - common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; if (ah->hw_version.devid != AR2427_DEVID_PCIE) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 031b1bf0d370..a778b66f4438 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -190,8 +190,6 @@ enum ath9k_hw_caps { struct ath9k_hw_capabilities { u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ - u16 low_5ghz_chan, high_5ghz_chan; - u16 low_2ghz_chan, high_2ghz_chan; u16 rts_aggr_limit; u8 tx_chainmask; u8 rx_chainmask; @@ -900,7 +898,6 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array, int column, unsigned int *writecnt); u32 ath9k_hw_reverse_bits(u32 val, u32 n); -bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); u16 ath9k_hw_computetxtime(struct ath_hw *ah, u8 phy, int kbps, u32 frameLen, u16 rateix, bool shortPreamble); -- cgit v1.2.3-58-ga151 From 1ed76487ce115110171480deabd3cd4656f9803e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 24 Mar 2011 19:46:18 +0100 Subject: mac80211: fix suppressing probe responses in ad-hoc mode The commit "mac80211: reply to directed probes in IBSS" changed ad-hoc specific code to respond to unicast probe requests, even if drv_tx_last_beacon returns false, however due to confusion over the meaning of the IEEE80211_RX_RA_MATCH flag, it also unconditionally enabled responding to multicast probe requests. Fix this by explicitly checking for a multicast destination address instead. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 3e81af1fce58..14883966374e 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -661,7 +661,6 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, struct sk_buff *req) { - struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(req); struct ieee80211_mgmt *mgmt = (void *)req->data; struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_local *local = sdata->local; @@ -685,7 +684,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, mgmt->bssid, tx_last_beacon); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - if (!tx_last_beacon && !(rx_status->rx_flags & IEEE80211_RX_RA_MATCH)) + if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da)) return; if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 && -- cgit v1.2.3-58-ga151 From 0022801c893e953ebff8e0ad00cc22716055babf Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Thu, 24 Mar 2011 20:49:38 -0700 Subject: mwifiex: remove helper functions for displaying 11n capabilities 'iw list' is sufficient to retrieve the information which was displayed by these functions. Signed-off-by: Yogesh Ashok Powar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n.c | 96 ----------------------------------- drivers/net/wireless/mwifiex/11n.h | 2 - drivers/net/wireless/mwifiex/cmdevt.c | 2 - drivers/net/wireless/mwifiex/fw.h | 16 ------ 4 files changed, 116 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 0e04a21be0a3..7b7b86d1ea3e 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -139,102 +139,6 @@ mwifiex_fill_cap_info(struct mwifiex_private *priv, ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap); } -/* - * Shows HT capability information fields. - * - * The following HT capability information fields are supported. - * - Maximum AMSDU length (3839 bytes or 7935 bytes) - * - Beam forming support - * - Greenfield preamble support - * - AMPDU support - * - MIMO Power Save support - * - Rx STBC support - * - Tx STBC support - * - Short GI for 20 MHz support - * - Short GI for 40 MHz support - * - LDPC coded packets receive support - * - Number of delayed BA streams - * - Number of immediate BA streams - * - 10 MHz channel width support - * - 20 MHz channel width support - * - 40 MHz channel width support - * - Presence of Tx antenna A/B/C/D - * - Presence of Rx antenna A/B/C/D - */ -void -mwifiex_show_dot_11n_dev_cap(struct mwifiex_adapter *adapter, u32 cap) -{ - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Max MSDU len = %s octets\n", - (ISSUPP_MAXAMSDU(cap) ? "7935" : "3839")); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Beam forming %s\n", - (ISSUPP_BEAMFORMING(cap) ? "supported" : "not supported")); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Greenfield preamble %s\n", - (ISSUPP_GREENFIELD(cap) ? "supported" : "not supported")); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: AMPDU %s\n", - (ISSUPP_AMPDU(cap) ? "supported" : "not supported")); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: MIMO Power Save %s\n", - (ISSUPP_MIMOPS(cap) ? "supported" : "not supported")); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Rx STBC %s\n", - (ISSUPP_RXSTBC(cap) ? "supported" : "not supported")); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Tx STBC %s\n", - (ISSUPP_TXSTBC(cap) ? "supported" : "not supported")); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Short GI for 40 Mhz %s\n", - (ISSUPP_SHORTGI40(cap) ? "supported" : "not supported")); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Short GI for 20 Mhz %s\n", - (ISSUPP_SHORTGI20(cap) ? "supported" : "not supported")); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: LDPC coded packet receive %s\n", - (ISSUPP_RXLDPC(cap) ? "supported" : "not supported")); - dev_dbg(adapter->dev, - "info: GET_HW_SPEC: Number of Delayed Block Ack streams = %d\n", - GET_DELAYEDBACK(cap)); - dev_dbg(adapter->dev, - "info: GET_HW_SPEC: Number of Immediate Block Ack streams = %d\n", - GET_IMMEDIATEBACK(cap)); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: 40 Mhz channel width %s\n", - (ISSUPP_CHANWIDTH40(cap) ? "supported" : "not supported")); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: 20 Mhz channel width %s\n", - (ISSUPP_CHANWIDTH20(cap) ? "supported" : "not supported")); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: 10 Mhz channel width %s\n", - (ISSUPP_CHANWIDTH10(cap) ? "supported" : "not supported")); - - if (ISSUPP_RXANTENNAA(cap)) - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Rx antennea A\n"); - - if (ISSUPP_RXANTENNAB(cap)) - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Rx antennea B\n"); - - if (ISSUPP_RXANTENNAC(cap)) - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Rx antennea C\n"); - - if (ISSUPP_RXANTENNAD(cap)) - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Rx antennea D\n"); - - if (ISSUPP_TXANTENNAA(cap)) - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Tx antennea A\n"); - - if (ISSUPP_TXANTENNAB(cap)) - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Tx antennea B\n"); - - if (ISSUPP_TXANTENNAC(cap)) - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Tx antennea C\n"); - - if (ISSUPP_TXANTENNAD(cap)) - dev_dbg(adapter->dev, "info: GET_HW_SPEC: Prescence of Tx antennea D\n"); - - return; -} - -/* - * Shows HT MCS support field. - */ -void -mwifiex_show_dev_mcs_support(struct mwifiex_adapter *adapter, u8 support) -{ - dev_dbg(adapter->dev, "info: GET_HW_SPEC: MCSs for %dx%d MIMO\n", - GET_RXMCSSUPP(support), GET_TXMCSSUPP(support)); - return; -} - /* * This function returns the pointer to an entry in BA Stream * table which matches the requested BA status. diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 769a27f2b2c3..71a853e61b61 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h @@ -24,8 +24,6 @@ #include "11n_rxreorder.h" #include "wmm.h" -void mwifiex_show_dot_11n_dev_cap(struct mwifiex_adapter *adapter, u32 cap); -void mwifiex_show_dev_mcs_support(struct mwifiex_adapter *adapter, u8 support); int mwifiex_ret_11n_delba(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 3a8fe1e122fb..24a3b6b69f64 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -1452,8 +1452,6 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, DEFAULT_11N_CAP_MASK; adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support; adapter->usr_dev_mcs_support = adapter->hw_dev_mcs_support; - mwifiex_show_dot_11n_dev_cap(adapter, adapter->hw_dot_11n_dev_cap); - mwifiex_show_dev_mcs_support(adapter, adapter->hw_dev_mcs_support); if (adapter->if_ops.update_mp_end_port) adapter->if_ops.update_mp_end_port(adapter, diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index e5dae45b11d2..d1a5a10c2a8e 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -196,30 +196,14 @@ enum MWIFIEX_802_11_WEP_STATUS { #define DEFAULT_11N_CAP_MASK (HWSPEC_SHORTGI20_SUPP | HWSPEC_RXSTBC_SUPP) #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) -#define ISSUPP_MAXAMSDU(Dot11nDevCap) (Dot11nDevCap & BIT(31)) -#define ISSUPP_BEAMFORMING(Dot11nDevCap) (Dot11nDevCap & BIT(30)) #define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) -#define ISSUPP_AMPDU(Dot11nDevCap) (Dot11nDevCap & BIT(28)) -#define ISSUPP_MIMOPS(Dot11nDevCap) (Dot11nDevCap & BIT(27)) #define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26)) #define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(25)) #define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & BIT(24)) #define ISSUPP_SHORTGI20(Dot11nDevCap) (Dot11nDevCap & BIT(23)) -#define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & BIT(22)) #define GET_DELAYEDBACK(Dot11nDevCap) (((Dot11nDevCap >> 20) & 0x03)) -#define GET_IMMEDIATEBACK(Dot11nDevCap) (((Dot11nDevCap >> 18) & 0x03)) #define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & BIT(17)) -#define ISSUPP_CHANWIDTH20(Dot11nDevCap) (Dot11nDevCap & BIT(16)) -#define ISSUPP_CHANWIDTH10(Dot11nDevCap) (Dot11nDevCap & BIT(15)) #define ISENABLED_40MHZ_INTOLARENT(Dot11nDevCap) (Dot11nDevCap & BIT(8)) -#define ISSUPP_RXANTENNAD(Dot11nDevCap) (Dot11nDevCap & BIT(7)) -#define ISSUPP_RXANTENNAC(Dot11nDevCap) (Dot11nDevCap & BIT(6)) -#define ISSUPP_RXANTENNAB(Dot11nDevCap) (Dot11nDevCap & BIT(5)) -#define ISSUPP_RXANTENNAA(Dot11nDevCap) (Dot11nDevCap & BIT(4)) -#define ISSUPP_TXANTENNAD(Dot11nDevCap) (Dot11nDevCap & BIT(3)) -#define ISSUPP_TXANTENNAC(Dot11nDevCap) (Dot11nDevCap & BIT(2)) -#define ISSUPP_TXANTENNAB(Dot11nDevCap) (Dot11nDevCap & BIT(1)) -#define ISSUPP_TXANTENNAA(Dot11nDevCap) (Dot11nDevCap & BIT(0)) #define SETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap |= BIT(17)) #define RESETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap &= ~BIT(17)) #define GET_TXMCSSUPP(DevMCSSupported) (DevMCSSupported >> 4) -- cgit v1.2.3-58-ga151 From 203afecaa320fa8c541ce130aed449ff53f5b4aa Mon Sep 17 00:00:00 2001 From: Marc Yang Date: Thu, 24 Mar 2011 20:49:39 -0700 Subject: mwifiex: remove unnecessary _set_auth functions mwifiex_set_encrypt_mode() mwifiex_set_auth_mode() mwifiex_set_auth() These functions are confusing and misleading. And they are really not needed at all. Some unused definitions are also removed. Signed-off-by: Marc Yang Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 17 ++++++------ drivers/net/wireless/mwifiex/ioctl.h | 2 -- drivers/net/wireless/mwifiex/join.c | 25 ++++++++---------- drivers/net/wireless/mwifiex/main.h | 8 ------ drivers/net/wireless/mwifiex/sta_ioctl.c | 44 -------------------------------- 5 files changed, 19 insertions(+), 77 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 80f367f27efc..84e33f1f0ffe 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1055,11 +1055,10 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, * scan. The cfg80211 does not give us the encryption * mode at this stage so just setting it to WEP here. */ - wpa_enabled = 0; - auth_type = MWIFIEX_AUTH_MODE_OPEN; - ret = mwifiex_set_auth(priv, - MWIFIEX_ENCRYPTION_MODE_WEP104, - auth_type, wpa_enabled); + priv->sec_info.encryption_mode = + MWIFIEX_ENCRYPTION_MODE_WEP104; + priv->sec_info.authentication_mode = + MWIFIEX_AUTH_MODE_OPEN; } goto done; @@ -1075,15 +1074,15 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, if (sme->crypto.n_ciphers_pairwise) { pairwise_encrypt_mode = mwifiex_get_mwifiex_cipher(sme->crypto. ciphers_pairwise[0], &wpa_enabled); - ret = mwifiex_set_auth(priv, pairwise_encrypt_mode, auth_type, - wpa_enabled); + priv->sec_info.encryption_mode = pairwise_encrypt_mode; + priv->sec_info.authentication_mode = auth_type; } if (sme->crypto.cipher_group) { group_encrypt_mode = mwifiex_get_mwifiex_cipher(sme->crypto. cipher_group, &wpa_enabled); - ret = mwifiex_set_auth(priv, group_encrypt_mode, auth_type, - wpa_enabled); + priv->sec_info.encryption_mode = group_encrypt_mode; + priv->sec_info.authentication_mode = auth_type; } if (sme->ie) ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len); diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index d6babfb1495c..b7e457110b4f 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -277,8 +277,6 @@ struct mwifiex_debug_info { enum { MWIFIEX_AUTH_MODE_OPEN = 0x00, MWIFIEX_AUTH_MODE_SHARED = 0x01, - MWIFIEX_AUTH_MODE_NETWORKEAP = 0x80, - MWIFIEX_AUTH_MODE_AUTO = 0xFF, }; enum { diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index d06f4c2d1d30..98d76d8c2656 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -441,20 +441,17 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: rates size = %d\n", rates_size); - /* Add the Authentication type to be used for Auth frames if needed */ - if (priv->sec_info.authentication_mode != MWIFIEX_AUTH_MODE_AUTO) { - auth_tlv = (struct mwifiex_ie_types_auth_type *) pos; - auth_tlv->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); - auth_tlv->header.len = cpu_to_le16(sizeof(auth_tlv->auth_type)); - if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED) - auth_tlv->auth_type = cpu_to_le16((u16) priv->sec_info. - authentication_mode); - else - auth_tlv->auth_type = - cpu_to_le16(MWIFIEX_AUTH_MODE_OPEN); - pos += sizeof(auth_tlv->header) + - le16_to_cpu(auth_tlv->header.len); - } + /* Add the Authentication type to be used for Auth frames */ + auth_tlv = (struct mwifiex_ie_types_auth_type *) pos; + auth_tlv->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); + auth_tlv->header.len = cpu_to_le16(sizeof(auth_tlv->auth_type)); + if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED) + auth_tlv->auth_type = cpu_to_le16( + (u16) priv->sec_info.authentication_mode); + else + auth_tlv->auth_type = cpu_to_le16(MWIFIEX_AUTH_MODE_OPEN); + + pos += sizeof(auth_tlv->header) + le16_to_cpu(auth_tlv->header.len); if (IS_SUPPORT_MULTI_BANDS(priv->adapter) && !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info) diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 2b0ad8e3d6e2..f6fe1054a65c 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -994,11 +994,6 @@ int mwifiex_get_channel_list(struct mwifiex_private *priv, int mwifiex_get_scan_table(struct mwifiex_private *priv, u8 wait_option, struct mwifiex_scan_resp *scanresp); -int mwifiex_get_auth_mode(struct mwifiex_private *priv, - u8 wait_option, u32 *auth_mode); -int mwifiex_get_encrypt_mode(struct mwifiex_private *priv, - u8 wait_option, - u32 *encrypt_mode); int mwifiex_enable_wep_key(struct mwifiex_private *priv, u8 wait_option); int mwifiex_find_best_bss(struct mwifiex_private *priv, u8 wait_option, struct mwifiex_ssid_bssid *ssid_bssid); @@ -1014,9 +1009,6 @@ int mwifiex_drv_get_mode(struct mwifiex_private *priv, u8 wait_option); int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel); -int mwifiex_set_auth(struct mwifiex_private *priv, int encrypt_mode, - int auth_mode, int wpa_enabled); - int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, int key_len, u8 key_index, int disable); diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 665a519b1403..362301f417a4 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -1690,20 +1690,6 @@ static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_adapter *adapter, return ret; } -/* - * IOCTL request handler to set/get authentication mode. - */ -static int mwifiex_set_auth_mode(struct mwifiex_private *priv, u32 auth_mode) -{ - int ret = 0; - - priv->sec_info.authentication_mode = auth_mode; - if (priv->sec_info.authentication_mode == MWIFIEX_AUTH_MODE_NETWORKEAP) - ret = mwifiex_set_wpa_ie_helper(priv, NULL, 0); - - return ret; -} - /* * IOCTL request handler to set WEP network key. * @@ -1998,36 +1984,6 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv, u8 wait_option, return status; } -/* - * Sends IOCTL request to set encryption mode. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -static int mwifiex_set_encrypt_mode(struct mwifiex_private *priv, - u8 wait_option, u32 encrypt_mode) -{ - priv->sec_info.encryption_mode = encrypt_mode; - return 0; -} - -/* - * This function set the authentication parameters. It sets both encryption - * mode and authentication mode, and also enables WPA if required. - */ -int -mwifiex_set_auth(struct mwifiex_private *priv, int encrypt_mode, - int auth_mode, int wpa_enabled) -{ - if (mwifiex_set_encrypt_mode(priv, MWIFIEX_IOCTL_WAIT, encrypt_mode)) - return -EFAULT; - - if (mwifiex_set_auth_mode(priv, auth_mode)) - return -EFAULT; - - return 0; -} - /* * Sends IOCTL request to set encoding parameters. * -- cgit v1.2.3-58-ga151 From 5f9f1812b68a2979bc97399cd4954f1c191986af Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 25 Mar 2011 21:39:19 +0100 Subject: mac80211: remove the dependency on crypto_blkcipher The only thing that using crypto_blkcipher with ecb does over just using arc4 directly is wrapping the encrypt/decrypt function into a for loop, looping over each individual character. To be able to do this, it pulls in around 40 kb worth of unnecessary kernel modules (at least on a MIPS embedded device). Using arc4 directly not only eliminates those dependencies, it also makes the code smaller. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/Kconfig | 1 - net/mac80211/ieee80211_i.h | 4 ++-- net/mac80211/tkip.c | 4 ++-- net/mac80211/tkip.h | 4 ++-- net/mac80211/wep.c | 34 +++++++++++++++------------------- net/mac80211/wep.h | 4 ++-- 6 files changed, 23 insertions(+), 28 deletions(-) diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 513f85cc2ae1..f5fdfcbf552a 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -2,7 +2,6 @@ config MAC80211 tristate "Generic IEEE 802.11 Networking Stack (mac80211)" depends on CFG80211 select CRYPTO - select CRYPTO_ECB select CRYPTO_ARC4 select CRYPTO_AES select CRC32 diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a40401701424..6eb2c8523eeb 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -809,8 +809,8 @@ struct ieee80211_local { struct rate_control_ref *rate_ctrl; - struct crypto_blkcipher *wep_tx_tfm; - struct crypto_blkcipher *wep_rx_tfm; + struct crypto_cipher *wep_tx_tfm; + struct crypto_cipher *wep_rx_tfm; u32 wep_iv; /* see iface.c */ diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index e840c9cd46db..757e4eb2baf7 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -202,7 +202,7 @@ EXPORT_SYMBOL(ieee80211_get_tkip_key); * @payload_len is the length of payload (_not_ including IV/ICV length). * @ta is the transmitter addresses. */ -int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, +int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, struct ieee80211_key *key, u8 *pos, size_t payload_len, u8 *ta) { @@ -223,7 +223,7 @@ int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, * beginning of the buffer containing IEEE 802.11 header payload, i.e., * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the * length of payload, including IV, Ext. IV, MIC, ICV. */ -int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, +int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, struct ieee80211_key *key, u8 *payload, size_t payload_len, u8 *ta, u8 *ra, int only_iv, int queue, diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h index 7e83dee976fa..1cab9c86978f 100644 --- a/net/mac80211/tkip.h +++ b/net/mac80211/tkip.h @@ -15,7 +15,7 @@ u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16); -int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, +int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, struct ieee80211_key *key, u8 *pos, size_t payload_len, u8 *ta); enum { @@ -24,7 +24,7 @@ enum { TKIP_DECRYPT_INVALID_KEYIDX = -2, TKIP_DECRYPT_REPLAY = -3, }; -int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, +int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, struct ieee80211_key *key, u8 *payload, size_t payload_len, u8 *ta, u8 *ra, int only_iv, int queue, diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 2ff6d1e3ed21..a1c6bfd55f0f 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -30,17 +30,15 @@ int ieee80211_wep_init(struct ieee80211_local *local) /* start WEP IV from a random value */ get_random_bytes(&local->wep_iv, WEP_IV_LEN); - local->wep_tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, - CRYPTO_ALG_ASYNC); + local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(local->wep_tx_tfm)) { local->wep_rx_tfm = ERR_PTR(-EINVAL); return PTR_ERR(local->wep_tx_tfm); } - local->wep_rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, - CRYPTO_ALG_ASYNC); + local->wep_rx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(local->wep_rx_tfm)) { - crypto_free_blkcipher(local->wep_tx_tfm); + crypto_free_cipher(local->wep_tx_tfm); local->wep_tx_tfm = ERR_PTR(-EINVAL); return PTR_ERR(local->wep_rx_tfm); } @@ -51,9 +49,9 @@ int ieee80211_wep_init(struct ieee80211_local *local) void ieee80211_wep_free(struct ieee80211_local *local) { if (!IS_ERR(local->wep_tx_tfm)) - crypto_free_blkcipher(local->wep_tx_tfm); + crypto_free_cipher(local->wep_tx_tfm); if (!IS_ERR(local->wep_rx_tfm)) - crypto_free_blkcipher(local->wep_rx_tfm); + crypto_free_cipher(local->wep_rx_tfm); } static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen) @@ -127,12 +125,11 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local, /* Perform WEP encryption using given key. data buffer must have tailroom * for 4-byte ICV. data_len must not include this ICV. Note: this function * does _not_ add IV. data = RC4(data | CRC32(data)) */ -int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, +int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, size_t klen, u8 *data, size_t data_len) { - struct blkcipher_desc desc = { .tfm = tfm }; - struct scatterlist sg; __le32 icv; + int i; if (IS_ERR(tfm)) return -1; @@ -140,9 +137,9 @@ int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, icv = cpu_to_le32(~crc32_le(~0, data, data_len)); put_unaligned(icv, (__le32 *)(data + data_len)); - crypto_blkcipher_setkey(tfm, rc4key, klen); - sg_init_one(&sg, data, data_len + WEP_ICV_LEN); - crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length); + crypto_cipher_setkey(tfm, rc4key, klen); + for (i = 0; i < data_len + WEP_ICV_LEN; i++) + crypto_cipher_encrypt_one(tfm, data + i, data + i); return 0; } @@ -186,19 +183,18 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, /* Perform WEP decryption using given key. data buffer includes encrypted * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV. * Return 0 on success and -1 on ICV mismatch. */ -int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, +int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, size_t klen, u8 *data, size_t data_len) { - struct blkcipher_desc desc = { .tfm = tfm }; - struct scatterlist sg; __le32 crc; + int i; if (IS_ERR(tfm)) return -1; - crypto_blkcipher_setkey(tfm, rc4key, klen); - sg_init_one(&sg, data, data_len + WEP_ICV_LEN); - crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length); + crypto_cipher_setkey(tfm, rc4key, klen); + for (i = 0; i < data_len + WEP_ICV_LEN; i++) + crypto_cipher_decrypt_one(tfm, data + i, data + i); crc = cpu_to_le32(~crc32_le(~0, data, data_len)); if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0) diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h index 58654ee33518..01e54840a628 100644 --- a/net/mac80211/wep.h +++ b/net/mac80211/wep.h @@ -18,12 +18,12 @@ int ieee80211_wep_init(struct ieee80211_local *local); void ieee80211_wep_free(struct ieee80211_local *local); -int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, +int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, size_t klen, u8 *data, size_t data_len); int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb, const u8 *key, int keylen, int keyidx); -int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, +int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, size_t klen, u8 *data, size_t data_len); bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); -- cgit v1.2.3-58-ga151 From b93f85f0fb019f527b68569aafb836c94b89a47e Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Fri, 25 Mar 2011 19:47:01 -0700 Subject: mwifiex: remove macro SHORT_SLOT_TIME_DISABLED and SHORT_SLOT_TIME_ENABLED. Use WLAN_CAPABILITY_SHORT_SLOT_TIME instead. Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/fw.h | 3 --- drivers/net/wireless/mwifiex/join.c | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index d1a5a10c2a8e..410be694e36b 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -57,9 +57,6 @@ struct tx_packet_hdr { #define GET_FW_DEFAULT_BANDS(adapter) \ ((adapter->fw_cap_info >> 8) & ALL_802_11_BANDS) -#define SHORT_SLOT_TIME_DISABLED(CapInfo) (CapInfo &= ~BIT(10)) -#define SHORT_SLOT_TIME_ENABLED(CapInfo) (CapInfo |= BIT(10)) - extern u8 supported_rates_b[B_SUPPORTED_RATES]; extern u8 supported_rates_g[G_SUPPORTED_RATES]; extern u8 supported_rates_bg[BG_SUPPORTED_RATES]; diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 98d76d8c2656..8ffb6a8d1036 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -517,7 +517,7 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, tmp_cap = bss_desc->cap_info_bitmap; if (priv->adapter->config_bands == BAND_B) - SHORT_SLOT_TIME_DISABLED(tmp_cap); + tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME; tmp_cap &= CAPINFO_MASK; dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", @@ -1015,9 +1015,9 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, + S_DS_GEN + cmd_append_size)); if (adapter->adhoc_start_band == BAND_B) - SHORT_SLOT_TIME_DISABLED(tmp_cap); + tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME; else - SHORT_SLOT_TIME_ENABLED(tmp_cap); + tmp_cap |= WLAN_CAPABILITY_SHORT_SLOT_TIME; adhoc_start->cap_info_bitmap = cpu_to_le16(tmp_cap); -- cgit v1.2.3-58-ga151 From 6d2bd916afe6950b50f750cd82bbb9c6ff58611f Mon Sep 17 00:00:00 2001 From: Marc Yang Date: Fri, 25 Mar 2011 19:47:02 -0700 Subject: mwifiex: use IEEE80211_HT_CAP_ macros for 11n cap_info The hw_dot_11n_dev_cap reported by firmware hw_spec has different format than the 11n capabilities. Hence a lot of SET_ and RESET_ bit operation macros were used to convert the dev_cap format to 11n capability format. However the locally defined 11n ht_cap macros are not necessary as we can use IEEE80211_HT_CAP_ macros directly. The 32-bit dev_cap bitmap is added as comment to explain the mapping between firmware and 11n spec. Some unused macros and unnecessary adapter variables are also removed. Signed-off-by: Marc Yang Signed-off-by: Yogesh Ashok Powar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n.c | 85 +++++++++++++-------------------- drivers/net/wireless/mwifiex/cfg80211.c | 3 +- drivers/net/wireless/mwifiex/cmdevt.c | 3 -- drivers/net/wireless/mwifiex/fw.h | 84 ++++++++------------------------ drivers/net/wireless/mwifiex/init.c | 2 - drivers/net/wireless/mwifiex/join.c | 13 ++--- drivers/net/wireless/mwifiex/main.h | 2 - 7 files changed, 63 insertions(+), 129 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 7b7b86d1ea3e..ce6421f3230b 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -61,59 +61,42 @@ mwifiex_fill_cap_info(struct mwifiex_private *priv, uint16_t ht_cap_info = le16_to_cpu(ht_cap->ht_cap.cap_info); uint16_t ht_ext_cap = le16_to_cpu(ht_cap->ht_cap.extended_ht_cap_info); - if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap) && - ISSUPP_CHANWIDTH40(adapter->usr_dot_11n_dev_cap)) - SETHT_SUPPCHANWIDTH(ht_cap_info); + /* Convert dev_cap to IEEE80211_HT_CAP */ + if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) + ht_cap_info |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; else - RESETHT_SUPPCHANWIDTH(ht_cap_info); + ht_cap_info &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap) && - ISSUPP_GREENFIELD(adapter->usr_dot_11n_dev_cap)) - SETHT_GREENFIELD(ht_cap_info); + if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap)) + ht_cap_info |= IEEE80211_HT_CAP_SGI_20; else - RESETHT_GREENFIELD(ht_cap_info); + ht_cap_info &= ~IEEE80211_HT_CAP_SGI_20; - if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap) && - ISSUPP_SHORTGI20(adapter->usr_dot_11n_dev_cap)) - SETHT_SHORTGI20(ht_cap_info); + if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap)) + ht_cap_info |= IEEE80211_HT_CAP_SGI_40; else - RESETHT_SHORTGI20(ht_cap_info); + ht_cap_info &= ~IEEE80211_HT_CAP_SGI_40; - if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap) && - ISSUPP_SHORTGI40(adapter->usr_dot_11n_dev_cap)) - SETHT_SHORTGI40(ht_cap_info); - else - RESETHT_SHORTGI40(ht_cap_info); - - /* No user config for RX STBC yet */ - if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap) - && ISSUPP_RXSTBC(adapter->usr_dot_11n_dev_cap)) - SETHT_RXSTBC(ht_cap_info, 1); - else - RESETHT_RXSTBC(ht_cap_info); - - /* No user config for TX STBC yet */ if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) - SETHT_TXSTBC(ht_cap_info); + ht_cap_info |= IEEE80211_HT_CAP_TX_STBC; else - RESETHT_TXSTBC(ht_cap_info); + ht_cap_info &= ~IEEE80211_HT_CAP_TX_STBC; - /* No user config for Delayed BACK yet */ - if (GET_DELAYEDBACK(adapter->hw_dot_11n_dev_cap)) - SETHT_DELAYEDBACK(ht_cap_info); + if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap)) + ht_cap_info |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; else - RESETHT_DELAYEDBACK(ht_cap_info); + ht_cap_info &= ~(3 << IEEE80211_HT_CAP_RX_STBC_SHIFT); - if (ISENABLED_40MHZ_INTOLARENT(adapter->usr_dot_11n_dev_cap)) - SETHT_40MHZ_INTOLARANT(ht_cap_info); + if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap)) + ht_cap_info |= IEEE80211_HT_CAP_GRN_FLD; else - RESETHT_40MHZ_INTOLARANT(ht_cap_info); + ht_cap_info &= ~IEEE80211_HT_CAP_GRN_FLD; - SETAMPDU_SIZE(ht_cap->ht_cap.ampdu_params_info, AMPDU_FACTOR_64K); - SETAMPDU_SPACING(ht_cap->ht_cap.ampdu_params_info, 0); + ht_cap_info &= ~IEEE80211_HT_CAP_MAX_AMSDU; + ht_cap_info |= IEEE80211_HT_CAP_SM_PS; - /* Need change to support 8k AMSDU receive */ - RESETHT_MAXAMSDU(ht_cap_info); + ht_cap->ht_cap.ampdu_params_info |= IEEE80211_HT_AMPDU_PARM_FACTOR; + ht_cap->ht_cap.ampdu_params_info &= ~IEEE80211_HT_AMPDU_PARM_DENSITY; rx_mcs_supp = GET_RXMCSSUPP(adapter->hw_dev_mcs_support); @@ -127,8 +110,7 @@ mwifiex_fill_cap_info(struct mwifiex_private *priv, sizeof(struct ieee80211_mcs_info) - rx_mcs_supp); if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA || - (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap) && - ISSUPP_CHANWIDTH40(adapter->usr_dot_11n_dev_cap))) + (ht_cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); @@ -452,10 +434,10 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, le16_to_cpu(ht_info->header.len)); if (!ISSUPP_CHANWIDTH40 - (priv->adapter->hw_dot_11n_dev_cap) - || !ISSUPP_CHANWIDTH40(priv->adapter-> - usr_dot_11n_dev_cap)) - RESET_CHANWIDTH40(ht_info->ht_info.ht_param); + (priv->adapter->hw_dot_11n_dev_cap)) + ht_info->ht_info.ht_param &= + ~(IEEE80211_HT_PARAM_CHAN_WIDTH_ANY | + IEEE80211_HT_PARAM_CHA_SEC_OFFSET); *buffer += sizeof(struct mwifiex_ie_types_htinfo); ret_len += sizeof(struct mwifiex_ie_types_htinfo); @@ -474,13 +456,13 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, chan_list->chan_scan_param[0].radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); - if ((ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) && - ISSUPP_CHANWIDTH40(priv->adapter->usr_dot_11n_dev_cap)) - && ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_info->ht_param)) + if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) + && (bss_desc->bcn_ht_info->ht_param & + IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. radio_type, - GET_SECONDARYCHAN(bss_desc-> - bcn_ht_info->ht_param)); + (bss_desc->bcn_ht_info->ht_param & + IEEE80211_HT_PARAM_CHA_SEC_OFFSET)); *buffer += sizeof(struct mwifiex_ie_types_chan_list_param_set); ret_len += sizeof(struct mwifiex_ie_types_chan_list_param_set); @@ -540,7 +522,8 @@ mwifiex_cfg_tx_buf(struct mwifiex_private *priv, u16 curr_tx_buf_size = 0; if (bss_desc->bcn_ht_cap) { - if (GETHT_MAXAMSDU(le16_to_cpu(bss_desc->bcn_ht_cap->cap_info))) + if (le16_to_cpu(bss_desc->bcn_ht_cap->cap_info) & + IEEE80211_HT_CAP_MAX_AMSDU) max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_8K; else max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_4K; diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 84e33f1f0ffe..de86ef879509 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1302,8 +1302,7 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, memset(&mcs[rx_mcs_supp], 0, sizeof(struct ieee80211_mcs_info) - rx_mcs_supp); if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA || - (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap) && - ISSUPP_CHANWIDTH40(adapter->usr_dot_11n_dev_cap))) + ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ SETHT_MCS32(mcs_set.rx_mask); diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 24a3b6b69f64..3865dd19e4f8 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -1448,10 +1448,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, } adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap); - adapter->usr_dot_11n_dev_cap = adapter->hw_dot_11n_dev_cap & - DEFAULT_11N_CAP_MASK; adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support; - adapter->usr_dev_mcs_support = adapter->hw_dev_mcs_support; if (adapter->if_ops.update_mp_end_port) adapter->if_ops.update_mp_end_port(adapter, diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 410be694e36b..6593e071dea8 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -182,76 +182,34 @@ enum MWIFIEX_802_11_WEP_STATUS { #define MWIFIEX_TX_DATA_BUF_SIZE_4K 4096 #define MWIFIEX_TX_DATA_BUF_SIZE_8K 8192 -#define MAX_RX_AMPDU_SIZE_64K 0x03 #define NON_GREENFIELD_STAS 0x04 -#define HWSPEC_GREENFIELD_SUPP BIT(29) -#define HWSPEC_RXSTBC_SUPP BIT(26) -#define HWSPEC_SHORTGI40_SUPP BIT(24) -#define HWSPEC_SHORTGI20_SUPP BIT(23) -#define HWSPEC_CHANBW40_SUPP BIT(17) - -#define DEFAULT_11N_CAP_MASK (HWSPEC_SHORTGI20_SUPP | HWSPEC_RXSTBC_SUPP) #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) -#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) -#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26)) -#define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(25)) -#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & BIT(24)) -#define ISSUPP_SHORTGI20(Dot11nDevCap) (Dot11nDevCap & BIT(23)) -#define GET_DELAYEDBACK(Dot11nDevCap) (((Dot11nDevCap >> 20) & 0x03)) + +/* dev_cap bitmap + * BIT + * 0-16 reserved + * 17 IEEE80211_HT_CAP_SUP_WIDTH_20_40 + * 18-22 reserved + * 23 IEEE80211_HT_CAP_SGI_20 + * 24 IEEE80211_HT_CAP_SGI_40 + * 25 IEEE80211_HT_CAP_TX_STBC + * 26 IEEE80211_HT_CAP_RX_STBC + * 27-28 reserved + * 29 IEEE80211_HT_CAP_GRN_FLD + * 30-31 reserved + */ #define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & BIT(17)) -#define ISENABLED_40MHZ_INTOLARENT(Dot11nDevCap) (Dot11nDevCap & BIT(8)) -#define SETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap |= BIT(17)) -#define RESETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap &= ~BIT(17)) -#define GET_TXMCSSUPP(DevMCSSupported) (DevMCSSupported >> 4) +#define ISSUPP_SHORTGI20(Dot11nDevCap) (Dot11nDevCap & BIT(23)) +#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & BIT(24)) +#define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(25)) +#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26)) +#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) + #define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f) -#define GETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo & BIT(1)) -#define GETHT_GREENFIELD(HTCapInfo) (HTCapInfo & BIT(4)) -#define GETHT_SHORTGI20(HTCapInfo) (HTCapInfo & BIT(5)) -#define GETHT_SHORTGI40(HTCapInfo) (HTCapInfo & BIT(6)) -#define GETHT_TXSTBC(HTCapInfo) (HTCapInfo & BIT(7)) -#define GETHT_RXSTBC(HTCapInfo) ((HTCapInfo >> 8) & 0x03) -#define GETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo & BIT(10)) -#define GETHT_MAXAMSDU(HTCapInfo) (HTCapInfo & BIT(11)) -#define SETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo |= BIT(1)) -#define SETHT_GREENFIELD(HTCapInfo) (HTCapInfo |= BIT(4)) -#define SETHT_SHORTGI20(HTCapInfo) (HTCapInfo |= BIT(5)) -#define SETHT_SHORTGI40(HTCapInfo) (HTCapInfo |= BIT(6)) -#define SETHT_TXSTBC(HTCapInfo) (HTCapInfo |= BIT(7)) -#define SETHT_RXSTBC(HTCapInfo, value) (HTCapInfo |= (value << 8)) -#define SETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo |= BIT(10)) -#define SETHT_MAXAMSDU(HTCapInfo) (HTCapInfo |= BIT(11)) -#define SETHT_DSSSCCK40(HTCapInfo) (HTCapInfo |= BIT(12)) -#define SETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo |= BIT(14)) -#define RESETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo &= ~BIT(1)) -#define RESETHT_GREENFIELD(HTCapInfo) (HTCapInfo &= ~BIT(4)) -#define RESETHT_SHORTGI20(HTCapInfo) (HTCapInfo &= ~BIT(5)) -#define RESETHT_SHORTGI40(HTCapInfo) (HTCapInfo &= ~BIT(6)) -#define RESETHT_TXSTBC(HTCapInfo) (HTCapInfo &= ~BIT(7)) -#define RESETHT_RXSTBC(HTCapInfo) (HTCapInfo &= ~(0x03 << 8)) -#define RESETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo &= ~BIT(10)) -#define RESETHT_MAXAMSDU(HTCapInfo) (HTCapInfo &= ~BIT(11)) -#define RESETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo &= ~BIT(14)) #define RESETHT_EXTCAP_RDG(HTExtCap) (HTExtCap &= ~BIT(11)) #define SETHT_MCS32(x) (x[4] |= 1) -#define SETHT_MCS_SET_DEFINED(x) (x[12] |= 1) -#define SETHT_RX_HIGHEST_DT_SUPP(x, y) ((*(u16 *) (x + 10)) = y) -#define AMPDU_FACTOR_64K 0x03 -#define SETAMPDU_SIZE(x, y) do { \ - x = x & ~0x03; \ - x |= y & 0x03; \ -} while (0) \ - -#define SETAMPDU_SPACING(x, y) do { \ - x = x & ~0x1c; \ - x |= (y & 0x07) << 2; \ -} while (0) \ - -#define ISSUPP_BANDA(FwCapInfo) (FwCapInfo & BIT(10)) -#define ISALLOWED_CHANWIDTH40(Field2) (Field2 & BIT(2)) -#define SET_CHANWIDTH40(Field2) (Field2 |= BIT(2)) -#define RESET_CHANWIDTH40(Field2) (Field2 &= ~(BIT(0) | BIT(1) | BIT(2))) -#define GET_SECONDARYCHAN(Field2) (Field2 & (BIT(0) | BIT(1))) + #define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4)) #define LLC_SNAP_LEN 8 diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 07ebc97e19c0..1c9315d31d9c 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -267,8 +267,6 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) memset(adapter->event_body, 0, sizeof(adapter->event_body)); adapter->hw_dot_11n_dev_cap = 0; adapter->hw_dev_mcs_support = 0; - adapter->usr_dot_11n_dev_cap = 0; - adapter->usr_dev_mcs_support = 0; adapter->chan_offset = 0; adapter->adhoc_11n_enabled = false; diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 8ffb6a8d1036..08fa721580cb 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -970,16 +970,16 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, cpu_to_le16(sizeof(struct ieee80211_ht_cap)); ht_cap_info = le16_to_cpu(ht_cap->ht_cap.cap_info); - SETHT_SHORTGI20(ht_cap_info); + ht_cap_info |= IEEE80211_HT_CAP_SGI_20; if (adapter->chan_offset) { - SETHT_SHORTGI40(ht_cap_info); - SETHT_DSSSCCK40(ht_cap_info); - SETHT_SUPPCHANWIDTH(ht_cap_info); + ht_cap_info |= IEEE80211_HT_CAP_SGI_40; + ht_cap_info |= IEEE80211_HT_CAP_DSSSCCK40; + ht_cap_info |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); } ht_cap->ht_cap.ampdu_params_info - = MAX_RX_AMPDU_SIZE_64K; + = IEEE80211_HT_MAX_AMPDU_64K; ht_cap->ht_cap.mcs.rx_mask[0] = 0xff; pos += sizeof(struct mwifiex_ie_types_htcap); cmd_append_size += @@ -999,7 +999,8 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, if (adapter->chan_offset) { ht_info->ht_info.ht_param = adapter->chan_offset; - SET_CHANWIDTH40(ht_info->ht_info.ht_param); + ht_info->ht_info.ht_param |= + IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; } ht_info->ht_info.operation_mode = cpu_to_le16(NON_GREENFIELD_STAS); diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index f6fe1054a65c..7bcb2e965aeb 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -687,8 +687,6 @@ struct mwifiex_adapter { u8 event_body[MAX_EVENT_SIZE]; u32 hw_dot_11n_dev_cap; u8 hw_dev_mcs_support; - u32 usr_dot_11n_dev_cap; - u8 usr_dev_mcs_support; u8 adhoc_11n_enabled; u8 chan_offset; struct mwifiex_dbg dbg; -- cgit v1.2.3-58-ga151 From 324732848c42bf79988479ee1b4359e15f08154b Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 27 Mar 2011 16:19:57 -0500 Subject: rtlwifi: Remove unused/unneeded variables Remove some unused variables and correct spelling errors. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/base.c | 5 +- drivers/net/wireless/rtlwifi/core.c | 8 +- drivers/net/wireless/rtlwifi/efuse.c | 106 ++++++++++------------ drivers/net/wireless/rtlwifi/pci.c | 53 ++++------- drivers/net/wireless/rtlwifi/pci.h | 4 +- drivers/net/wireless/rtlwifi/ps.c | 3 +- drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 38 +++----- drivers/net/wireless/rtlwifi/wifi.h | 18 ++-- 8 files changed, 98 insertions(+), 137 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index bb0c781f4a1b..dd5318ed7872 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -432,7 +432,7 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, } if (rtlpriv->dm.useramask) { - /* TODO we will differentiate adhoc and station futrue */ + /* TODO adhoc and station handled differently in the future */ tcb_desc->mac_id = 0; if ((mac->mode == WIRELESS_MODE_N_24G) || @@ -630,7 +630,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) const struct iphdr *ip; if (!ieee80211_is_data(fc)) - goto end; + return false; if (ieee80211_is_nullfunc(fc)) return true; @@ -686,7 +686,6 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) return true; } -end: return false; } diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index e4f4aee8f298..8fed3c687619 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -35,7 +35,7 @@ /*mutex for start & stop is must here. */ static int rtl_op_start(struct ieee80211_hw *hw) { - int err = 0; + int err; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -45,10 +45,8 @@ static int rtl_op_start(struct ieee80211_hw *hw) return 0; mutex_lock(&rtlpriv->locks.conf_mutex); err = rtlpriv->intf_ops->adapter_start(hw); - if (err) - goto out; - rtl_watch_dog_timer_callback((unsigned long)hw); -out: + if (!err) + rtl_watch_dog_timer_callback((unsigned long)hw); mutex_unlock(&rtlpriv->locks.conf_mutex); return err; } diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index f74a8701c67d..5d73c0f7012c 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c @@ -338,11 +338,11 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw) struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); u8 section_idx, i, Base; u16 words_need = 0, hdr_num = 0, totalbytes, efuse_used; - bool bwordchanged, bresult = true; + bool wordchanged, result = true; for (section_idx = 0; section_idx < 16; section_idx++) { Base = section_idx * 8; - bwordchanged = false; + wordchanged = false; for (i = 0; i < 8; i = i + 2) { if ((rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i] != @@ -351,11 +351,11 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw) rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i + 1])) { words_need++; - bwordchanged = true; + wordchanged = true; } } - if (bwordchanged == true) + if (wordchanged == true) hdr_num++; } @@ -364,14 +364,14 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw) if ((totalbytes + efuse_used) >= (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) - bresult = false; + result = false; RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("efuse_shadow_update_chk(): totalbytes(%#x), " "hdr_num(%#x), words_need(%#x), efuse_used(%d)\n", totalbytes, hdr_num, words_need, efuse_used)); - return bresult; + return result; } void efuse_shadow_read(struct ieee80211_hw *hw, u8 type, @@ -394,7 +394,7 @@ void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, u16 offset, else if (type == 2) efuse_shadow_write_2byte(hw, offset, (u16) value); else if (type == 4) - efuse_shadow_write_4byte(hw, offset, (u32) value); + efuse_shadow_write_4byte(hw, offset, value); } @@ -572,7 +572,7 @@ static int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, u8 *data) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 tmpidx = 0; - int bresult; + int result; rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, (u8) (addr & 0xff)); @@ -592,19 +592,18 @@ static int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, u8 *data) if (tmpidx < 100) { *data = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); - bresult = true; + result = true; } else { *data = 0xff; - bresult = false; + result = false; } - return bresult; + return result; } static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 tmpidx = 0; - bool bresult; RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("Addr = %x Data=%x\n", addr, data)); @@ -626,11 +625,9 @@ static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data) } if (tmpidx < 100) - bresult = true; - else - bresult = false; + return true; - return bresult; + return false; } static void efuse_read_all_map(struct ieee80211_hw *hw, u8 * efuse) @@ -681,11 +678,10 @@ static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) { u8 readstate = PG_STATE_HEADER; - bool bcontinual = true; + bool continual = true; u8 efuse_data, word_cnts = 0; u16 efuse_addr = 0; - u8 hworden; u8 tmpdata[8]; if (data == NULL) @@ -696,7 +692,7 @@ static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) memset(data, 0xff, PGPKT_DATA_SIZE * sizeof(u8)); memset(tmpdata, 0xff, PGPKT_DATA_SIZE * sizeof(u8)); - while (bcontinual && (efuse_addr < EFUSE_MAX_SIZE)) { + while (continual && (efuse_addr < EFUSE_MAX_SIZE)) { if (readstate & PG_STATE_HEADER) { if (efuse_one_byte_read(hw, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) @@ -705,9 +701,9 @@ static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) offset, tmpdata, &readstate); else - bcontinual = false; + continual = false; } else if (readstate & PG_STATE_DATA) { - efuse_word_enable_data_read(hworden, tmpdata, data); + efuse_word_enable_data_read(0, tmpdata, data); efuse_addr = efuse_addr + (word_cnts * 2) + 1; readstate = PG_STATE_HEADER; } @@ -725,13 +721,13 @@ static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) } static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, - u8 efuse_data, u8 offset, int *bcontinual, + u8 efuse_data, u8 offset, int *continual, u8 *write_state, struct pgpkt_struct *target_pkt, - int *repeat_times, int *bresult, u8 word_en) + int *repeat_times, int *result, u8 word_en) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct pgpkt_struct tmp_pkt; - int bdataempty = true; + bool dataempty = true; u8 originaldata[8 * sizeof(u8)]; u8 badworden = 0x0F; u8 match_word_en, tmp_word_en; @@ -751,10 +747,10 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, u16 address = *efuse_addr + 1 + tmpindex; if (efuse_one_byte_read(hw, address, &efuse_data) && (efuse_data != 0xFF)) - bdataempty = false; + dataempty = false; } - if (bdataempty == false) { + if (dataempty == false) { *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; *write_state = PG_STATE_HEADER; } else { @@ -811,12 +807,12 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, target_pkt->offset = offset; target_pkt->word_en = tmp_word_en; } else - *bcontinual = false; + *continual = false; *write_state = PG_STATE_HEADER; *repeat_times += 1; if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { - *bcontinual = false; - *bresult = false; + *continual = false; + *result = false; } } else { *efuse_addr += (2 * tmp_word_cnts) + 1; @@ -830,9 +826,9 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, } static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, - int *bcontinual, u8 *write_state, + int *continual, u8 *write_state, struct pgpkt_struct target_pkt, - int *repeat_times, int *bresult) + int *repeat_times, int *result) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct pgpkt_struct tmp_pkt; @@ -852,8 +848,8 @@ static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, *write_state = PG_STATE_HEADER; *repeat_times += 1; if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { - *bcontinual = false; - *bresult = false; + *continual = false; + *result = false; } } else { tmp_pkt.offset = (tmp_header >> 4) & 0x0F; @@ -884,8 +880,8 @@ static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, *write_state = PG_STATE_HEADER; *repeat_times += 1; if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { - *bcontinual = false; - *bresult = false; + *continual = false; + *result = false; } RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, @@ -899,7 +895,7 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct pgpkt_struct target_pkt; u8 write_state = PG_STATE_HEADER; - int bcontinual = true, bdataempty = true, bresult = true; + int continual = true, dataempty = true, result = true; u16 efuse_addr = 0; u8 efuse_data; u8 target_word_cnts = 0; @@ -923,11 +919,11 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, ("efuse Power ON\n")); - while (bcontinual && (efuse_addr < + while (continual && (efuse_addr < (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) { if (write_state == PG_STATE_HEADER) { - bdataempty = true; + dataempty = true; badworden = 0x0F; RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, ("efuse PG_STATE_HEADER\n")); @@ -936,32 +932,30 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, (efuse_data != 0xFF)) efuse_write_data_case1(hw, &efuse_addr, efuse_data, offset, - &bcontinual, + &continual, &write_state, &target_pkt, - &repeat_times, &bresult, + &repeat_times, &result, word_en); else efuse_write_data_case2(hw, &efuse_addr, - &bcontinual, + &continual, &write_state, target_pkt, &repeat_times, - &bresult); + &result); } else if (write_state == PG_STATE_DATA) { RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, ("efuse PG_STATE_DATA\n")); - badworden = 0x0f; badworden = efuse_word_enable_data_write(hw, efuse_addr + 1, target_pkt.word_en, target_pkt.data); if ((badworden & 0x0F) == 0x0F) { - bcontinual = false; + continual = false; } else { - efuse_addr = - efuse_addr + (2 * target_word_cnts) + 1; + efuse_addr += (2 * target_word_cnts) + 1; target_pkt.offset = offset; target_pkt.word_en = badworden; @@ -971,8 +965,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, write_state = PG_STATE_HEADER; repeat_times++; if (repeat_times > EFUSE_REPEAT_THRESHOLD_) { - bcontinual = false; - bresult = false; + continual = false; + result = false; } RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, ("efuse PG_STATE_HEADER-3\n")); @@ -1072,13 +1066,13 @@ static u8 efuse_word_enable_data_write(struct ieee80211_hw *hw, return badworden; } -static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate) +static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 tempval; u16 tmpV16; - if (pwrstate == true) { + if (pwrstate) { tmpV16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL]); if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { @@ -1106,8 +1100,8 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate) } } - if (pwrstate == true) { - if (bwrite == true) { + if (pwrstate) { + if (write) { tempval = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3); @@ -1119,7 +1113,7 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate) } } else { - if (bwrite == true) { + if (write) { tempval = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3); @@ -1134,12 +1128,12 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate) static u16 efuse_get_current_size(struct ieee80211_hw *hw) { - int bcontinual = true; + int continual = true; u16 efuse_addr = 0; u8 hoffset, hworden; u8 efuse_data, word_cnts; - while (bcontinual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) + while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) && (efuse_addr < EFUSE_MAX_SIZE)) { if (efuse_data != 0xFF) { hoffset = (efuse_data >> 4) & 0x0F; @@ -1147,7 +1141,7 @@ static u16 efuse_get_current_size(struct ieee80211_hw *hw) word_cnts = efuse_calculate_word_cnts(hworden); efuse_addr = efuse_addr + (word_cnts * 2) + 1; } else { - bcontinual = false; + continual = false; } } diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 9cd7703c2a30..efded435d596 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -113,32 +113,19 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) /*Set HW definition to determine if it supports ASPM. */ switch (rtlpci->const_support_pciaspm) { - case 0:{ - /*Not support ASPM. */ - bool support_aspm = false; - ppsc->support_aspm = support_aspm; - break; - } - case 1:{ - /*Support ASPM. */ - bool support_aspm = true; - bool support_backdoor = true; - ppsc->support_aspm = support_aspm; - - /*if(priv->oem_id == RT_CID_TOSHIBA && - !priv->ndis_adapter.amd_l1_patch) - support_backdoor = false; */ - - ppsc->support_backdoor = support_backdoor; - - break; - } + case 0: + /*Not support ASPM. */ + ppsc->support_aspm = false; + break; + case 1: + /*Support ASPM. */ + ppsc->support_aspm = true; + ppsc->support_backdoor = true; + break; case 2: /*ASPM value set by chipset. */ - if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) { - bool support_aspm = true; - ppsc->support_aspm = support_aspm; - } + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) + ppsc->support_aspm = true; break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, @@ -152,13 +139,11 @@ static bool _rtl_pci_platform_switch_device_pci_aspm( u8 value) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - bool bresult = false; value |= 0x40; - pci_write_config_byte(rtlpci->pdev, 0x80, value); - return bresult; + return false; } /*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/ @@ -166,14 +151,11 @@ static bool _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); u8 buffer; - bool bresult = false; buffer = value; - pci_write_config_byte(rtlpci->pdev, 0x81, value); - bresult = true; - return bresult; + return true; } /*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/ @@ -191,6 +173,7 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw) u16 pcibridge_linkctrlreg = pcipriv->ndis_adapter. pcibridge_linkctrlreg; u16 aspmlevel = 0; + u8 tmp_u1b = 0; if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, @@ -204,11 +187,8 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw) _rtl_pci_switch_clk_req(hw, 0x0); } - if (1) { - /*for promising device will in L0 state after an I/O. */ - u8 tmp_u1b; - pci_read_config_byte(rtlpci->pdev, 0x80, &tmp_u1b); - } + /*for promising device will in L0 state after an I/O. */ + pci_read_config_byte(rtlpci->pdev, 0x80, &tmp_u1b); /*Set corresponding value. */ aspmlevel |= BIT(0) | BIT(1); @@ -224,7 +204,6 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw) rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, pcibridge_linkctrlreg); udelay(50); - } /* diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h index 0caa81429726..12747b9c71e1 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/rtlwifi/pci.h @@ -192,8 +192,8 @@ struct rtl_pci { u8 const_devicepci_aspm_setting; /*If it supports ASPM, Offset[560h] = 0x40, otherwise Offset[560h] = 0x00. */ - bool b_support_aspm; - bool b_support_backdoor; + bool support_aspm; + bool support_backdoor; /*QOS & EDCA */ enum acm_method acm_method; diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 6b7e217b6b89..c8395fb0c050 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -63,7 +63,6 @@ EXPORT_SYMBOL(rtl_ps_enable_nic); bool rtl_ps_disable_nic(struct ieee80211_hw *hw) { - bool status = true; struct rtl_priv *rtlpriv = rtl_priv(hw); /*<1> Stop all timer */ @@ -75,7 +74,7 @@ bool rtl_ps_disable_nic(struct ieee80211_hw *hw) /*<3> Disable Adapter */ rtlpriv->cfg->ops->hw_disable(hw); - return status; + return true; } EXPORT_SYMBOL(rtl_ps_disable_nic); diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index 5ef91374b230..f107660f545d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c @@ -171,7 +171,6 @@ static void _rtl92c_write_fw(struct ieee80211_hw *hw, static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - int err = -EIO; u32 counter = 0; u32 value32; @@ -184,7 +183,7 @@ static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("chksum report faill ! REG_MCUFWDL:0x%08x .\n", value32)); - goto exit; + return -EIO; } RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, @@ -204,8 +203,7 @@ static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw) ("Polling FW ready success!!" " REG_MCUFWDL:0x%08x .\n", value32)); - err = 0; - goto exit; + return 0; } mdelay(FW_8192C_POLLING_DELAY); @@ -214,9 +212,7 @@ static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32)); - -exit: - return err; + return -EIO; } int rtl92c_download_fw(struct ieee80211_hw *hw) @@ -226,16 +222,14 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) struct rtl92c_firmware_header *pfwheader; u8 *pfwdata; u32 fwsize; - int err; enum version_8192c version = rtlhal->version; const struct firmware *firmware; - printk(KERN_INFO "rtl8192cu: Loading firmware file %s\n", + printk(KERN_INFO "rtl8192c: Loading firmware file %s\n", rtlpriv->cfg->fw_name); - err = request_firmware(&firmware, rtlpriv->cfg->fw_name, - rtlpriv->io.dev); - if (err) { - printk(KERN_ERR "rtl8192cu: Firmware loading failed\n"); + if (request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev)) { + printk(KERN_ERR "rtl8192c: Firmware loading failed\n"); return 1; } @@ -267,8 +261,7 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) _rtl92c_write_fw(hw, version, pfwdata, fwsize); _rtl92c_enable_fw_download(hw, false); - err = _rtl92c_fw_free_to_go(hw); - if (err) { + if (_rtl92c_fw_free_to_go(hw)) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Firmware is not ready to run!\n")); } else { @@ -303,7 +296,6 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, u16 box_reg, box_extreg; u8 u1b_tmp; bool isfw_read = false; - u8 buf_index; bool bwrite_sucess = false; u8 wait_h2c_limmit = 100; u8 wait_writeh2c_limmit = 100; @@ -414,7 +406,7 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, case 1: boxcontent[0] &= ~(BIT(7)); memcpy((u8 *) (boxcontent) + 1, - p_cmdbuffer + buf_index, 1); + p_cmdbuffer, 1); for (idx = 0; idx < 4; idx++) { rtl_write_byte(rtlpriv, box_reg + idx, @@ -424,7 +416,7 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, case 2: boxcontent[0] &= ~(BIT(7)); memcpy((u8 *) (boxcontent) + 1, - p_cmdbuffer + buf_index, 2); + p_cmdbuffer, 2); for (idx = 0; idx < 4; idx++) { rtl_write_byte(rtlpriv, box_reg + idx, @@ -434,7 +426,7 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, case 3: boxcontent[0] &= ~(BIT(7)); memcpy((u8 *) (boxcontent) + 1, - p_cmdbuffer + buf_index, 3); + p_cmdbuffer, 3); for (idx = 0; idx < 4; idx++) { rtl_write_byte(rtlpriv, box_reg + idx, @@ -444,9 +436,9 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, case 4: boxcontent[0] |= (BIT(7)); memcpy((u8 *) (boxextcontent), - p_cmdbuffer + buf_index, 2); + p_cmdbuffer, 2); memcpy((u8 *) (boxcontent) + 1, - p_cmdbuffer + buf_index + 2, 2); + p_cmdbuffer + 2, 2); for (idx = 0; idx < 2; idx++) { rtl_write_byte(rtlpriv, box_extreg + idx, @@ -461,9 +453,9 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, case 5: boxcontent[0] |= (BIT(7)); memcpy((u8 *) (boxextcontent), - p_cmdbuffer + buf_index, 2); + p_cmdbuffer, 2); memcpy((u8 *) (boxcontent) + 1, - p_cmdbuffer + buf_index + 2, 3); + p_cmdbuffer + 2, 3); for (idx = 0; idx < 2; idx++) { rtl_write_byte(rtlpriv, box_extreg + idx, diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 01226f8e70f9..4ce4853975f1 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -766,7 +766,7 @@ struct rtl_rfkill { #define IQK_MATRIX_REG_NUM 8 #define IQK_MATRIX_SETTINGS_NUM (1 + 24 + 21) struct iqk_matrix_regs { - bool b_iqk_done; + bool iqk_done; long value[1][IQK_MATRIX_REG_NUM]; }; @@ -1621,19 +1621,19 @@ struct bt_coexist_info { u32 bt_edca_ul; u32 bt_edca_dl; - bool b_init_set; - bool b_bt_busy_traffic; - bool b_bt_traffic_mode_set; - bool b_bt_non_traffic_mode_set; + bool init_set; + bool bt_busy_traffic; + bool bt_traffic_mode_set; + bool bt_non_traffic_mode_set; - bool b_fw_coexist_all_off; - bool b_sw_coexist_all_off; + bool fw_coexist_all_off; + bool sw_coexist_all_off; u32 current_state; u32 previous_state; u8 bt_pre_rssi_state; - u8 b_reg_bt_iso; - u8 b_reg_bt_sco; + u8 reg_bt_iso; + u8 reg_bt_sco; }; -- cgit v1.2.3-58-ga151 From 166389375d5a3894aa00a9c2e490ac4b9af2a891 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 28 Mar 2011 13:29:44 +0200 Subject: rt2x00: Limit rt2x00pci rxdone processing to 16 entries at once Instead of receiving an unlimited number of frames, stop after 16 entries and reschedule the rxdone tasklet. This allows other tasklets to be run inbetween. Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 6 ++++-- drivers/net/wireless/rt2x00/rt2500pci.c | 6 ++++-- drivers/net/wireless/rt2x00/rt2800pci.c | 6 ++++-- drivers/net/wireless/rt2x00/rt2x00pci.c | 7 +++++-- drivers/net/wireless/rt2x00/rt2x00pci.h | 5 ++++- drivers/net/wireless/rt2x00/rt61pci.c | 6 ++++-- 6 files changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 329f3283697b..137a24e520da 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1368,8 +1368,10 @@ static void rt2400pci_tbtt_tasklet(unsigned long data) static void rt2400pci_rxdone_tasklet(unsigned long data) { struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; - rt2x00pci_rxdone(rt2x00dev); - rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); + if (rt2x00pci_rxdone(rt2x00dev)) + tasklet_schedule(&rt2x00dev->rxdone_tasklet); + else + rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); } static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 58277878889e..198fc0a0d77c 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1500,8 +1500,10 @@ static void rt2500pci_tbtt_tasklet(unsigned long data) static void rt2500pci_rxdone_tasklet(unsigned long data) { struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; - rt2x00pci_rxdone(rt2x00dev); - rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); + if (rt2x00pci_rxdone(rt2x00dev)) + tasklet_schedule(&rt2x00dev->rxdone_tasklet); + else + rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); } static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 808073aa9dcc..4672dc99fe46 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -806,8 +806,10 @@ static void rt2800pci_tbtt_tasklet(unsigned long data) static void rt2800pci_rxdone_tasklet(unsigned long data) { struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; - rt2x00pci_rxdone(rt2x00dev); - rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); + if (rt2x00pci_rxdone(rt2x00dev)) + tasklet_schedule(&rt2x00dev->rxdone_tasklet); + else + rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); } static void rt2800pci_autowake_tasklet(unsigned long data) diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 4dd82b0b0520..9649bd0cd718 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -60,14 +60,15 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read); -void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) +bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue = rt2x00dev->rx; struct queue_entry *entry; struct queue_entry_priv_pci *entry_priv; struct skb_frame_desc *skbdesc; + int max_rx = 16; - while (1) { + while (--max_rx) { entry = rt2x00queue_get_entry(queue, Q_INDEX); entry_priv = entry->priv_data; @@ -93,6 +94,8 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) */ rt2x00lib_rxdone(entry); } + + return !max_rx; } EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 746ce8fe8cf4..07961b8b369a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -101,8 +101,11 @@ struct queue_entry_priv_pci { /** * rt2x00pci_rxdone - Handle RX done events * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * + * Returns true if there are still rx frames pending and false if all + * pending rx frames were processed. */ -void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); +bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); /* * Device initialization handlers. diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 77e8113b91e1..8ee1514a7943 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2313,8 +2313,10 @@ static void rt61pci_tbtt_tasklet(unsigned long data) static void rt61pci_rxdone_tasklet(unsigned long data) { struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; - rt2x00pci_rxdone(rt2x00dev); - rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE); + if (rt2x00pci_rxdone(rt2x00dev)) + rt2x00pci_rxdone(rt2x00dev); + else + rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE); } static void rt61pci_autowake_tasklet(unsigned long data) -- cgit v1.2.3-58-ga151 From 2e7798b7c12bdaab4a4aee76d6d1ab7c986234ac Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 28 Mar 2011 13:30:09 +0200 Subject: rt2x00: Limit rt2800pci txdone processing to 16 entries at once Instead of reporting an unlimited number of tx status reports to mac80211 stop after 16 frames and reschedule the tx status tasklet. This allows other tasklets to be run inbetween. Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 4672dc99fe46..d3055147ddfb 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -717,12 +717,13 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); } -static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) +static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; struct queue_entry *entry; u32 status; u8 qid; + int max_tx_done = 16; while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) { qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); @@ -759,7 +760,12 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); rt2800_txdone_entry(entry, status); + + if (--max_tx_done == 0) + break; } + + return !max_tx_done; } static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, @@ -780,7 +786,9 @@ static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, static void rt2800pci_txstatus_tasklet(unsigned long data) { - rt2800pci_txdone((struct rt2x00_dev *)data); + struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; + if (rt2800pci_txdone(rt2x00dev)) + tasklet_schedule(&rt2x00dev->txstatus_tasklet); /* * No need to enable the tx status interrupt here as we always -- cgit v1.2.3-58-ga151 From f78987cf8bb740b7a3636c08e003f1976f860cfc Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 28 Mar 2011 13:30:36 +0200 Subject: rt2x00: Calculate tx status fifo size instead of hardcoding it Instead of hardcoding the tx status fifo size as 512 calculate it based on the number of tx queues and the number of entries per queue. Also round the size up to a power of 2 as kfifo would otherwise round it down. On rt2800pci this will increase the kfifo size from 512 bytes to 1024 bytes which is then able to hold the tx status for all entries in all tx queues. Furthermore, if the number of tx queues or tx entries changes in the future (use of the MGMT queue for example) the kfifo size doesn't need to be updated. Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 9de9dbe94399..d63b582b6875 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "rt2x00.h" #include "rt2x00lib.h" @@ -811,13 +812,18 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) */ if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags)) { /* - * Allocate txstatus fifo and tasklet, we use a size of 512 - * for the kfifo which is big enough to store 512/4=128 tx - * status reports. In the worst case (tx status for all tx - * queues gets reported before we've got a chance to handle - * them) 24*4=384 tx status reports need to be cached. + * Allocate the txstatus fifo. In the worst case the tx + * status fifo has to hold the tx status of all entries + * in all tx queues. Hence, calculate the kfifo size as + * tx_queues * entry_num and round up to the nearest + * power of 2. */ - status = kfifo_alloc(&rt2x00dev->txstatus_fifo, 512, + int kfifo_size = + roundup_pow_of_two(rt2x00dev->ops->tx_queues * + rt2x00dev->ops->tx->entry_num * + sizeof(u32)); + + status = kfifo_alloc(&rt2x00dev->txstatus_fifo, kfifo_size, GFP_KERNEL); if (status) return status; -- cgit v1.2.3-58-ga151 From aca7305be5cd9e07f042e6bf6547e7c5635f0041 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 28 Mar 2011 13:30:59 +0200 Subject: rt2x00: Remove DRIVER_SUPPORT_WATCHDOG flag We can simply check if the driver registered the watchdog callback. There's no need to have an additional flag for that. Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 1 - drivers/net/wireless/rt2x00/rt2800usb.c | 1 - drivers/net/wireless/rt2x00/rt2x00.h | 1 - drivers/net/wireless/rt2x00/rt2x00link.c | 11 +++++------ drivers/net/wireless/rt2x00/rt73usb.c | 1 - 5 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 979fe6596a2d..d9e6cec56cb5 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1796,7 +1796,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); } - __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags); /* diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 4e368657a83c..1c99a4f449f5 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -564,7 +564,6 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (!modparam_nohwcrypt) __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); - __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index a3940d7300a4..60b1cb05a70d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -674,7 +674,6 @@ enum rt2x00_flags { DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, DRIVER_SUPPORT_LINK_TUNING, - DRIVER_SUPPORT_WATCHDOG, /* * Driver configuration diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index c975b0a12e95..fc8cee91b54e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -413,12 +413,11 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev) { struct link *link = &rt2x00dev->link; - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || - !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags)) - return; - - ieee80211_queue_delayed_work(rt2x00dev->hw, - &link->watchdog_work, WATCHDOG_INTERVAL); + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && + rt2x00dev->ops->lib->watchdog) + ieee80211_queue_delayed_work(rt2x00dev->hw, + &link->watchdog_work, + WATCHDOG_INTERVAL); } void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 02f1148c577e..149e4f928325 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2209,7 +2209,6 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (!modparam_nohwcrypt) __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); - __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags); /* * Set the rssi offset. -- cgit v1.2.3-58-ga151 From 75faae8b80171b447bfc4bac448308676fb8a663 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 28 Mar 2011 13:31:30 +0200 Subject: rt2x00: Restructure bw_comp calculation Move the HT40 check inside the calculation function to make it easier for a later cleanup. Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 2ee6cebb9b25..2f8af7a806ec 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1819,11 +1819,15 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, u16 eeprom; u8 comp_en; u8 comp_type; - int comp_value; + int comp_value = 0; rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom); - if (eeprom == 0xffff) + /* + * HT40 compensation not required. + */ + if (eeprom == 0xffff || + !test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) return 0; if (band == IEEE80211_BAND_2GHZ) { @@ -1865,13 +1869,12 @@ static u8 rt2800_compesate_txpower(struct rt2x00_dev *rt2x00dev, u8 eirp_txpower; u8 eirp_txpower_criterion; u8 reg_limit; - int bw_comp = 0; + int bw_comp; if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b)) return txpower; - if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) - bw_comp = rt2800_get_txpower_bw_comp(rt2x00dev, band); + bw_comp = rt2800_get_txpower_bw_comp(rt2x00dev, band); if (test_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags)) { /* -- cgit v1.2.3-58-ga151 From 2af242e19f06cfaade7ac8608c9df8af1e0fbb34 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 28 Mar 2011 13:32:01 +0200 Subject: rt2x00: Don't recalculate HT40 compensation for each rate Previously the HT40 tx power compensation value was calculated for each rate. However, the calculation is independent of the tx rate and as such can be precalculated and just passed in for each rate. Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 2f8af7a806ec..26ac8927a7c5 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1861,7 +1861,8 @@ static u8 rt2800_compesate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, enum ieee80211_band band, int power_level, - u8 txpower) + u8 txpower, + int delta) { u32 reg; u16 eeprom; @@ -1869,13 +1870,10 @@ static u8 rt2800_compesate_txpower(struct rt2x00_dev *rt2x00dev, u8 eirp_txpower; u8 eirp_txpower_criterion; u8 reg_limit; - int bw_comp; if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b)) return txpower; - bw_comp = rt2800_get_txpower_bw_comp(rt2x00dev, band); - if (test_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags)) { /* * Check if eirp txpower exceed txpower_limit. @@ -1898,14 +1896,14 @@ static u8 rt2800_compesate_txpower(struct rt2x00_dev *rt2x00dev, EEPROM_EIRP_MAX_TX_POWER_5GHZ); eirp_txpower = eirp_txpower_criterion + (txpower - criterion) + - (is_rate_b ? 4 : 0) + bw_comp; + (is_rate_b ? 4 : 0) + delta; reg_limit = (eirp_txpower > power_level) ? (eirp_txpower - power_level) : 0; } else reg_limit = 0; - return txpower + bw_comp - reg_limit; + return txpower + delta - reg_limit; } static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, @@ -1919,6 +1917,12 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, u32 offset; enum ieee80211_band band = conf->channel->band; int power_level = conf->power_level; + int delta; + + /* + * Calculate HT40 compensation delta + */ + delta = rt2800_get_txpower_bw_comp(rt2x00dev, band); /* * set to normal bbp tx power control mode: +/- 0dBm @@ -1948,7 +1952,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower); + power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE0, txpower); /* @@ -1959,7 +1963,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower); + power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE1, txpower); /* @@ -1970,7 +1974,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower); + power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE2, txpower); /* @@ -1981,7 +1985,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower); + power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE3, txpower); /* read the next four txpower values */ @@ -1997,7 +2001,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower); + power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE4, txpower); /* @@ -2008,7 +2012,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower); + power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE5, txpower); /* @@ -2019,7 +2023,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower); + power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE6, txpower); /* @@ -2030,7 +2034,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower); + power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE7, txpower); rt2800_register_write(rt2x00dev, offset, reg); -- cgit v1.2.3-58-ga151 From fa71a160272c0eec9c04102ab2a82befb7cb107f Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 28 Mar 2011 13:32:32 +0200 Subject: rt2x00: Indention cleanup in rt2800lib Fix the indention in rt2800_compesate_txpower and also fix a typo in the function name rt2800_compesate_txpower -> rt2800_compensate_txpower. Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 26ac8927a7c5..026513349370 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1857,12 +1857,9 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, return comp_value; } -static u8 rt2800_compesate_txpower(struct rt2x00_dev *rt2x00dev, - int is_rate_b, - enum ieee80211_band band, - int power_level, - u8 txpower, - int delta) +static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, + enum ieee80211_band band, int power_level, + u8 txpower, int delta) { u32 reg; u16 eeprom; @@ -1951,7 +1948,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); - txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE0, txpower); @@ -1962,7 +1959,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); - txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE1, txpower); @@ -1973,7 +1970,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); - txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE2, txpower); @@ -1984,7 +1981,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); - txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE3, txpower); @@ -2000,7 +1997,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); - txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE4, txpower); @@ -2011,7 +2008,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); - txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE5, txpower); @@ -2022,7 +2019,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); - txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE6, txpower); @@ -2033,7 +2030,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); - txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, power_level, txpower, delta); rt2x00_set_field32(®, TX_PWR_CFG_RATE7, txpower); -- cgit v1.2.3-58-ga151 From 2f2bb7e8bdc977c94cdaaf84328526555eba89b1 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 28 Mar 2011 13:33:04 +0200 Subject: rt2x00: Remove obsolete rt2x00queue_align_payload Since commit d1c3a37ceeb1a5ea02991a0476355f1a1d3b3e83 ("mac80211: clarify alignment docs, fix up alignment") removed the requirement for a 4-byte aligned payload rt2x00queue_align_payload is obsolete as mac80211 will align the payload when it passes the frame to the net stack. As a result we can remove the call to rt2x00queue_align_payload in the rx path and since that's the last user we can remove rt2x00queue_align_payload altogether. One advantage is that we save some alignment operations for frames that don't need to be aligned (for example beause they are not passed to the net stack). Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 -- drivers/net/wireless/rt2x00/rt2x00lib.h | 10 ---------- drivers/net/wireless/rt2x00/rt2x00queue.c | 13 ------------- 3 files changed, 25 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index d63b582b6875..55c1d0332b2a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -512,8 +512,6 @@ void rt2x00lib_rxdone(struct queue_entry *entry) (rxdesc.size > header_length) && (rxdesc.dev_flags & RXDONE_L2PAD)) rt2x00queue_remove_l2pad(entry->skb, header_length); - else - rt2x00queue_align_payload(entry->skb, header_length); /* Trim buffer to correct size */ skb_trim(entry->skb, rxdesc.size); diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 2d94cbaf5f4a..63c40d457244 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -118,16 +118,6 @@ void rt2x00queue_free_skb(struct queue_entry *entry); */ void rt2x00queue_align_frame(struct sk_buff *skb); -/** - * rt2x00queue_align_payload - Align 802.11 payload to 4-byte boundary - * @skb: The skb to align - * @header_length: Length of 802.11 header - * - * Align the 802.11 payload to a 4-byte boundary, this could - * mean the header is not aligned properly though. - */ -void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length); - /** * rt2x00queue_insert_l2pad - Align 802.11 header & payload to 4-byte boundary * @skb: The skb to align diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 4b3c70eeef1f..5d8925991ffb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -148,19 +148,6 @@ void rt2x00queue_align_frame(struct sk_buff *skb) skb_trim(skb, frame_length); } -void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length) -{ - unsigned int frame_length = skb->len; - unsigned int align = ALIGN_SIZE(skb, header_length); - - if (!align) - return; - - skb_push(skb, align); - memmove(skb->data, skb->data + align, frame_length); - skb_trim(skb, frame_length); -} - void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) { unsigned int payload_length = skb->len - header_length; -- cgit v1.2.3-58-ga151 From 9e33a3553821418b2c4f53d09311476c55176b13 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 28 Mar 2011 13:33:40 +0200 Subject: rt2x00: Implement tx power temperature compensation rt2800 devices should adjust their tx power in accordance with the eeproms temperature calibration values. Add a new driver callback gain_calibration that is called every 4 seconds. The rt2800 gain calibration routine simply runs the tx power configuration that takes care of calculating the temperature compensation delta. We don't need to synchronize the calls to rt2800_config_txpower as they should all happen from mac80211's single threaded workqueue. Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 106 ++++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2800lib.c | 133 +++++++++++++++++++++++++++++-- drivers/net/wireless/rt2x00/rt2800lib.h | 1 + drivers/net/wireless/rt2x00/rt2800pci.c | 1 + drivers/net/wireless/rt2x00/rt2800usb.c | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 6 ++ drivers/net/wireless/rt2x00/rt2x00dev.c | 2 + drivers/net/wireless/rt2x00/rt2x00lib.h | 13 +++ drivers/net/wireless/rt2x00/rt2x00link.c | 38 +++++++++ 9 files changed, 296 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 70b9abbdeb9e..3b3d851fe266 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2103,6 +2103,59 @@ struct mac_iveiv_entry { #define EEPROM_TXPOWER_BG_1 FIELD16(0x00ff) #define EEPROM_TXPOWER_BG_2 FIELD16(0xff00) +/* + * EEPROM temperature compensation boundaries 802.11BG + * MINUS4: If the actual TSSI is below this boundary, tx power needs to be + * reduced by (agc_step * -4) + * MINUS3: If the actual TSSI is below this boundary, tx power needs to be + * reduced by (agc_step * -3) + */ +#define EEPROM_TSSI_BOUND_BG1 0x0037 +#define EEPROM_TSSI_BOUND_BG1_MINUS4 FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_BG1_MINUS3 FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11BG + * MINUS2: If the actual TSSI is below this boundary, tx power needs to be + * reduced by (agc_step * -2) + * MINUS1: If the actual TSSI is below this boundary, tx power needs to be + * reduced by (agc_step * -1) + */ +#define EEPROM_TSSI_BOUND_BG2 0x0038 +#define EEPROM_TSSI_BOUND_BG2_MINUS2 FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_BG2_MINUS1 FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11BG + * REF: Reference TSSI value, no tx power changes needed + * PLUS1: If the actual TSSI is above this boundary, tx power needs to be + * increased by (agc_step * 1) + */ +#define EEPROM_TSSI_BOUND_BG3 0x0039 +#define EEPROM_TSSI_BOUND_BG3_REF FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_BG3_PLUS1 FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11BG + * PLUS2: If the actual TSSI is above this boundary, tx power needs to be + * increased by (agc_step * 2) + * PLUS3: If the actual TSSI is above this boundary, tx power needs to be + * increased by (agc_step * 3) + */ +#define EEPROM_TSSI_BOUND_BG4 0x003a +#define EEPROM_TSSI_BOUND_BG4_PLUS2 FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_BG4_PLUS3 FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11BG + * PLUS4: If the actual TSSI is above this boundary, tx power needs to be + * increased by (agc_step * 4) + * AGC_STEP: Temperature compensation step. + */ +#define EEPROM_TSSI_BOUND_BG5 0x003b +#define EEPROM_TSSI_BOUND_BG5_PLUS4 FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_BG5_AGC_STEP FIELD16(0xff00) + /* * EEPROM TXPOWER 802.11A */ @@ -2112,6 +2165,59 @@ struct mac_iveiv_entry { #define EEPROM_TXPOWER_A_1 FIELD16(0x00ff) #define EEPROM_TXPOWER_A_2 FIELD16(0xff00) +/* + * EEPROM temperature compensation boundaries 802.11A + * MINUS4: If the actual TSSI is below this boundary, tx power needs to be + * reduced by (agc_step * -4) + * MINUS3: If the actual TSSI is below this boundary, tx power needs to be + * reduced by (agc_step * -3) + */ +#define EEPROM_TSSI_BOUND_A1 0x006a +#define EEPROM_TSSI_BOUND_A1_MINUS4 FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_A1_MINUS3 FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11A + * MINUS2: If the actual TSSI is below this boundary, tx power needs to be + * reduced by (agc_step * -2) + * MINUS1: If the actual TSSI is below this boundary, tx power needs to be + * reduced by (agc_step * -1) + */ +#define EEPROM_TSSI_BOUND_A2 0x006b +#define EEPROM_TSSI_BOUND_A2_MINUS2 FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_A2_MINUS1 FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11A + * REF: Reference TSSI value, no tx power changes needed + * PLUS1: If the actual TSSI is above this boundary, tx power needs to be + * increased by (agc_step * 1) + */ +#define EEPROM_TSSI_BOUND_A3 0x006c +#define EEPROM_TSSI_BOUND_A3_REF FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_A3_PLUS1 FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11A + * PLUS2: If the actual TSSI is above this boundary, tx power needs to be + * increased by (agc_step * 2) + * PLUS3: If the actual TSSI is above this boundary, tx power needs to be + * increased by (agc_step * 3) + */ +#define EEPROM_TSSI_BOUND_A4 0x006d +#define EEPROM_TSSI_BOUND_A4_PLUS2 FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_A4_PLUS3 FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11A + * PLUS4: If the actual TSSI is above this boundary, tx power needs to be + * increased by (agc_step * 4) + * AGC_STEP: Temperature compensation step. + */ +#define EEPROM_TSSI_BOUND_A5 0x006e +#define EEPROM_TSSI_BOUND_A5_PLUS4 FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_A5_AGC_STEP FIELD16(0xff00) + /* * EEPROM TXPOWER by rate: tx power per tx rate for HT20 mode */ diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 026513349370..59302faec395 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1813,6 +1813,116 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, ®); } +static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) +{ + u8 tssi_bounds[9]; + u8 current_tssi; + u16 eeprom; + u8 step; + int i; + + /* + * Read TSSI boundaries for temperature compensation from + * the EEPROM. + * + * Array idx 0 1 2 3 4 5 6 7 8 + * Matching Delta value -4 -3 -2 -1 0 +1 +2 +3 +4 + * Example TSSI bounds 0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00 + */ + if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom); + tssi_bounds[0] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG1_MINUS4); + tssi_bounds[1] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG1_MINUS3); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom); + tssi_bounds[2] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG2_MINUS2); + tssi_bounds[3] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG2_MINUS1); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom); + tssi_bounds[4] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG3_REF); + tssi_bounds[5] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG3_PLUS1); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom); + tssi_bounds[6] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG4_PLUS2); + tssi_bounds[7] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG4_PLUS3); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom); + tssi_bounds[8] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG5_PLUS4); + + step = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_BG5_AGC_STEP); + } else { + rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom); + tssi_bounds[0] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A1_MINUS4); + tssi_bounds[1] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A1_MINUS3); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom); + tssi_bounds[2] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A2_MINUS2); + tssi_bounds[3] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A2_MINUS1); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom); + tssi_bounds[4] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A3_REF); + tssi_bounds[5] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A3_PLUS1); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom); + tssi_bounds[6] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A4_PLUS2); + tssi_bounds[7] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A4_PLUS3); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom); + tssi_bounds[8] = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A5_PLUS4); + + step = rt2x00_get_field16(eeprom, + EEPROM_TSSI_BOUND_A5_AGC_STEP); + } + + /* + * Check if temperature compensation is supported. + */ + if (tssi_bounds[4] == 0xff) + return 0; + + /* + * Read current TSSI (BBP 49). + */ + rt2800_bbp_read(rt2x00dev, 49, ¤t_tssi); + + /* + * Compare TSSI value (BBP49) with the compensation boundaries + * from the EEPROM and increase or decrease tx power. + */ + for (i = 0; i <= 3; i++) { + if (current_tssi > tssi_bounds[i]) + break; + } + + if (i == 4) { + for (i = 8; i >= 5; i--) { + if (current_tssi < tssi_bounds[i]) + break; + } + } + + return (i - 4) * step; +} + static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, enum ieee80211_band band) { @@ -1904,7 +2014,8 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, } static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf) + enum ieee80211_band band, + int power_level) { u8 txpower; u16 eeprom; @@ -1912,8 +2023,6 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, u32 reg; u8 r1; u32 offset; - enum ieee80211_band band = conf->channel->band; - int power_level = conf->power_level; int delta; /* @@ -1921,6 +2030,11 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ delta = rt2800_get_txpower_bw_comp(rt2x00dev, band); + /* + * calculate temperature compensation delta + */ + delta += rt2800_get_gain_calibration_delta(rt2x00dev); + /* * set to normal bbp tx power control mode: +/- 0dBm */ @@ -2041,6 +2155,13 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, } } +void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev) +{ + rt2800_config_txpower(rt2x00dev, rt2x00dev->curr_band, + rt2x00dev->tx_power); +} +EXPORT_SYMBOL_GPL(rt2800_gain_calibration); + static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf) { @@ -2094,10 +2215,12 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev, if (flags & IEEE80211_CONF_CHANGE_CHANNEL) { rt2800_config_channel(rt2x00dev, libconf->conf, &libconf->rf, &libconf->channel); - rt2800_config_txpower(rt2x00dev, libconf->conf); + rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band, + libconf->conf->power_level); } if (flags & IEEE80211_CONF_CHANGE_POWER) - rt2800_config_txpower(rt2x00dev, libconf->conf); + rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band, + libconf->conf->power_level); if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) rt2800_config_retry_limit(rt2x00dev, libconf); if (flags & IEEE80211_CONF_CHANGE_PS) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 0c92d86a36f4..f2d15941c71a 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -181,6 +181,7 @@ void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual); void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual); void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, const u32 count); +void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev); int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev); void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index d3055147ddfb..adc3534254df 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1053,6 +1053,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .link_stats = rt2800_link_stats, .reset_tuner = rt2800_reset_tuner, .link_tuner = rt2800_link_tuner, + .gain_calibration = rt2800_gain_calibration, .start_queue = rt2800pci_start_queue, .kick_queue = rt2800pci_kick_queue, .stop_queue = rt2800pci_stop_queue, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 1c99a4f449f5..8b3ab3f17eb3 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -629,6 +629,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .link_stats = rt2800_link_stats, .reset_tuner = rt2800_reset_tuner, .link_tuner = rt2800_link_tuner, + .gain_calibration = rt2800_gain_calibration, .watchdog = rt2800usb_watchdog, .start_queue = rt2800usb_start_queue, .kick_queue = rt2x00usb_kick_queue, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 60b1cb05a70d..dd0f66ade6e8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -348,6 +348,11 @@ struct link { * to bring the device/driver back into the desired state. */ struct delayed_work watchdog_work; + + /* + * Work structure for scheduling periodic AGC adjustments. + */ + struct delayed_work agc_work; }; enum rt2x00_delayed_flags { @@ -556,6 +561,7 @@ struct rt2x00lib_ops { struct link_qual *qual); void (*link_tuner) (struct rt2x00_dev *rt2x00dev, struct link_qual *qual, const u32 count); + void (*gain_calibration) (struct rt2x00_dev *rt2x00dev); /* * Data queue handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 55c1d0332b2a..a98c43485239 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -71,6 +71,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) */ rt2x00queue_start_queues(rt2x00dev); rt2x00link_start_tuner(rt2x00dev); + rt2x00link_start_agc(rt2x00dev); /* * Start watchdog monitoring. @@ -93,6 +94,7 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) /* * Stop all queues */ + rt2x00link_stop_agc(rt2x00dev); rt2x00link_stop_tuner(rt2x00dev); rt2x00queue_stop_queues(rt2x00dev); rt2x00queue_flush_queues(rt2x00dev, true); diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 63c40d457244..88f2f9275528 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -32,6 +32,7 @@ */ #define WATCHDOG_INTERVAL round_jiffies_relative(HZ) #define LINK_TUNE_INTERVAL round_jiffies_relative(HZ) +#define AGC_INTERVAL round_jiffies_relative(4 * HZ) /* * rt2x00_rate: Per rate device information @@ -270,6 +271,18 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev); */ void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev); +/** + * rt2x00link_start_agc - Start periodic gain calibration + * @rt2x00dev: Pointer to &struct rt2x00_dev. + */ +void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00link_stop_agc - Stop periodic gain calibration + * @rt2x00dev: Pointer to &struct rt2x00_dev. + */ +void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev); + /** * rt2x00link_register - Initialize link tuning & watchdog functionality * @rt2x00dev: Pointer to &struct rt2x00_dev. diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index fc8cee91b54e..128b3615c08c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -446,8 +446,46 @@ static void rt2x00link_watchdog(struct work_struct *work) WATCHDOG_INTERVAL); } +void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev) +{ + struct link *link = &rt2x00dev->link; + + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && + rt2x00dev->ops->lib->gain_calibration) + ieee80211_queue_delayed_work(rt2x00dev->hw, + &link->agc_work, + AGC_INTERVAL); +} + +void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev) +{ + cancel_delayed_work_sync(&rt2x00dev->link.agc_work); +} + +static void rt2x00link_agc(struct work_struct *work) +{ + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, link.agc_work.work); + struct link *link = &rt2x00dev->link; + + /* + * When the radio is shutting down we should + * immediately cease the watchdog monitoring. + */ + if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) + return; + + rt2x00dev->ops->lib->gain_calibration(rt2x00dev); + + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + ieee80211_queue_delayed_work(rt2x00dev->hw, + &link->agc_work, + AGC_INTERVAL); +} + void rt2x00link_register(struct rt2x00_dev *rt2x00dev) { + INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc); INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); } -- cgit v1.2.3-58-ga151 From 351151e8ace033fe3b1977516b32a6c76e9a3f6d Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 28 Mar 2011 13:34:15 +0200 Subject: rt2x00: Fix STBC transmissions to STAs with Rx STBC > 1 For STBC transmissions rt2x00 used the number of RxSTBC streams the destination STA indicates in its HT capabilities as STBC value in the TXWI. However, the legacy drivers and our own comment in rt2800.h suggest that the STBC field in the TXWI only allows a value of 0 or 1. The values 2 and 3 are reserved (probably for future devices). And indeed, STBC transmissions to STAs indicating more then 1 RxSTBC stream fail when the STBC field is set to something >1. Fix this by only setting the STBC field to 1 when STBC should be used. Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00ht.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c index ae1219dffaae..e8c0c3e92c2f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c @@ -43,8 +43,11 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */ - txdesc->u.ht.stbc = - (tx_info->flags & IEEE80211_TX_CTL_STBC) >> IEEE80211_TX_CTL_STBC_SHIFT; + /* + * Only one STBC stream is supported for now. + */ + if (tx_info->flags & IEEE80211_TX_CTL_STBC) + txdesc->u.ht.stbc = 1; /* * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the -- cgit v1.2.3-58-ga151 From b35e77cf84137bbb4b6888dc90616eb0b452ea36 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 28 Mar 2011 13:34:50 +0200 Subject: rt2x00: Add support for the ZyXEL NWD-211AN USB Add new USB ID Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 8b3ab3f17eb3..262bf669e1b1 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -877,6 +877,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zyxel */ { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0586, 0x3418), USB_DEVICE_DATA(&rt2800usb_ops) }, #ifdef CONFIG_RT2800USB_RT33XX /* Ralink */ { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, -- cgit v1.2.3-58-ga151 From f16d2db704b873d34cec54f992637f3579e10e08 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 28 Mar 2011 13:35:21 +0200 Subject: rt2x00: Fix tx aggregation problems with some clients Some clients seem to rely upon the reception of BlockAckReqs to flush their rx reorder buffer. In order to fix aggregation for these clients rt2x00 should send a BlockAckReq if the transmission of an AMPDU subframe fails. Introduce a new flag TXDONE_AMPDU to indicate that this is an AMPDU subframe and pass IEEE80211_TX_STAT_AMPDU_NO_BACK to mac80211 if an AMPDU subframe failed during transmission. This fixes aggregation problems with Intel 5100 Windows STAs (and maybe others as well). Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 3 +++ drivers/net/wireless/rt2x00/rt2x00dev.c | 6 +++++- drivers/net/wireless/rt2x00/rt2x00queue.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 59302faec395..769c05c0cbaa 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -687,6 +687,9 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status) mcs = real_mcs; } + if (aggr == 1 || ampdu == 1) + __set_bit(TXDONE_AMPDU, &txdesc.flags); + /* * Ralink has a retry mechanism using a global fallback * table. We setup this fallback table to try the immediate diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index a98c43485239..83252d94c2b7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -353,10 +353,14 @@ void rt2x00lib_txdone(struct queue_entry *entry, * which would allow the rc algorithm to better decide on * which rates are suitable. */ - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { + if (test_bit(TXDONE_AMPDU, &txdesc->flags) || + tx_info->flags & IEEE80211_TX_CTL_AMPDU) { tx_info->flags |= IEEE80211_TX_STAT_AMPDU; tx_info->status.ampdu_len = 1; tx_info->status.ampdu_ack_len = success ? 1 : 0; + + if (!success) + tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; } if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 0c8b0c699679..6ae820093997 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -217,6 +217,7 @@ enum txdone_entry_desc_flags { TXDONE_FALLBACK, TXDONE_FAILURE, TXDONE_EXCESSIVE_RETRY, + TXDONE_AMPDU, }; /** -- cgit v1.2.3-58-ga151 From 6a4c499e86f54ed9316a87e7ddc6b7d33adb4976 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 28 Mar 2011 13:35:51 +0200 Subject: rt2x00: Add an error message when trying to send on a full queue We already tell mac80211 to stop the queue when we hit a certain threshold. Hence, it shouldn't happen at all that a frame gets queued for tx on a full queue. Add an error message for this case. Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 5d8925991ffb..9fc4a1ec4b43 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -482,8 +482,11 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, struct skb_frame_desc *skbdesc; u8 rate_idx, rate_flags; - if (unlikely(rt2x00queue_full(queue))) + if (unlikely(rt2x00queue_full(queue))) { + ERROR(queue->rt2x00dev, + "Dropping frame due to full tx queue %d.\n", queue->qid); return -ENOBUFS; + } if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))) { -- cgit v1.2.3-58-ga151 From eecd8250e492ffc4e7b72953cda9c2f3ba0e6ccc Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Mon, 28 Mar 2011 17:55:41 -0700 Subject: mwifiex: remove MWIFIEX_BSS_MODE_ macros replace them with NL80211_IFTYPE_ macros Also remove redundant functions mwifiex_drv_get_mode() and mwifiex_bss_ioctl_mode(). Signed-off-by: Bing Zhao Signed-off-by: Amitkumar Karwar Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n.c | 4 +- drivers/net/wireless/mwifiex/cfg80211.c | 85 ++++++++++++++---------------- drivers/net/wireless/mwifiex/cfp.c | 3 +- drivers/net/wireless/mwifiex/init.c | 2 +- drivers/net/wireless/mwifiex/ioctl.h | 6 --- drivers/net/wireless/mwifiex/join.c | 12 ++--- drivers/net/wireless/mwifiex/main.h | 7 +-- drivers/net/wireless/mwifiex/scan.c | 29 +++++----- drivers/net/wireless/mwifiex/sta_cmd.c | 4 +- drivers/net/wireless/mwifiex/sta_cmdresp.c | 2 +- drivers/net/wireless/mwifiex/sta_event.c | 2 +- drivers/net/wireless/mwifiex/sta_ioctl.c | 83 +++-------------------------- 12 files changed, 74 insertions(+), 165 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index ce6421f3230b..73a6e62f5680 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -109,7 +109,7 @@ mwifiex_fill_cap_info(struct mwifiex_private *priv, memset(&mcs[rx_mcs_supp], 0, sizeof(struct ieee80211_mcs_info) - rx_mcs_supp); - if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA || + if (priv->bss_mode == NL80211_IFTYPE_STATION || (ht_cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); @@ -418,7 +418,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, } if (bss_desc->bcn_ht_info) { - if (priv->bss_mode == MWIFIEX_BSS_MODE_IBSS) { + if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { ht_info = (struct mwifiex_ie_types_htinfo *) *buffer; memset(ht_info, 0, sizeof(struct mwifiex_ie_types_htinfo)); diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index de86ef879509..701c17980f6d 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -398,13 +398,9 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, int ret = 0; int status = 0; struct mwifiex_ds_band_cfg band_cfg; - int mode; - u8 wait_option = MWIFIEX_IOCTL_WAIT; u32 config_bands = 0; struct wiphy *wiphy = priv->wdev->wiphy; - mode = mwifiex_drv_get_mode(priv, wait_option); - if (chan) { memset(&band_cfg, 0, sizeof(band_cfg)); /* Set appropriate bands */ @@ -412,10 +408,10 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, config_bands = BAND_B | BAND_G | BAND_GN; else config_bands = BAND_AN | BAND_A; - if (mode == MWIFIEX_BSS_MODE_INFRA - || mode == MWIFIEX_BSS_MODE_AUTO) { + if (priv->bss_mode == NL80211_IFTYPE_STATION + || priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED) { band_cfg.config_bands = config_bands; - } else if (mode == MWIFIEX_BSS_MODE_IBSS) { + } else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { band_cfg.config_bands = config_bands; band_cfg.adhoc_start_band = config_bands; } @@ -432,7 +428,8 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, } wiphy_dbg(wiphy, "info: setting band %d, channel offset %d and " - "mode %d\n", config_bands, band_cfg.sec_chan_offset, mode); + "mode %d\n", config_bands, band_cfg.sec_chan_offset, + priv->bss_mode); if (!chan) return ret; @@ -561,14 +558,6 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) /* * CFG802.11 operation handler to change interface type. - * - * This function creates an IOCTL request, populates it accordingly - * and issues an IOCTL. - * - * The function also maps the CFG802.11 mode type into driver mode type. - * NL80211_IFTYPE_ADHOC -> MWIFIEX_BSS_MODE_IBSS - * NL80211_IFTYPE_STATION -> MWIFIEX_BSS_MODE_INFRA - * NL80211_IFTYPE_UNSPECIFIED -> MWIFIEX_BSS_MODE_AUTO */ static int mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, @@ -578,41 +567,50 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, { int ret = 0; struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - int mode = -1; struct mwifiex_wait_queue *wait = NULL; - int status = 0; - wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); - if (!wait) - return -ENOMEM; + if (priv->bss_mode == type) { + wiphy_warn(wiphy, "already set to required type\n"); + return 0; + } + + priv->bss_mode = type; switch (type) { case NL80211_IFTYPE_ADHOC: - mode = MWIFIEX_BSS_MODE_IBSS; dev->ieee80211_ptr->iftype = NL80211_IFTYPE_ADHOC; wiphy_dbg(wiphy, "info: setting interface type to adhoc\n"); break; case NL80211_IFTYPE_STATION: - mode = MWIFIEX_BSS_MODE_INFRA; dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; - wiphy_dbg(wiphy, "info: Setting interface type to managed\n"); + wiphy_dbg(wiphy, "info: setting interface type to managed\n"); break; case NL80211_IFTYPE_UNSPECIFIED: - mode = MWIFIEX_BSS_MODE_AUTO; dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; wiphy_dbg(wiphy, "info: setting interface type to auto\n"); - break; + return 0; default: - ret = -EINVAL; + wiphy_err(wiphy, "unknown interface type: %d\n", type); + return -EINVAL; } - if (ret) - goto done; - status = mwifiex_bss_ioctl_mode(priv, wait, HostCmd_ACT_GEN_SET, &mode); - if (mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT)) + wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); + if (!wait) + return -ENOMEM; + + mwifiex_deauthenticate(priv, wait, NULL); + + priv->sec_info.authentication_mode = MWIFIEX_AUTH_MODE_OPEN; + + ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_SET_BSS_MODE, + HostCmd_ACT_GEN_SET, 0, wait, NULL); + if (!ret) + ret = -EINPROGRESS; + + ret = mwifiex_request_ioctl(priv, wait, ret, MWIFIEX_IOCTL_WAIT); + if (ret) ret = -EFAULT; -done: kfree(wait); return ret; } @@ -1046,7 +1044,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); /* Disable keys */ - if (mode == MWIFIEX_BSS_MODE_IBSS) { + if (mode == NL80211_IFTYPE_ADHOC) { /* "privacy" is set only for ad-hoc mode */ if (privacy) { /* @@ -1108,7 +1106,7 @@ done: memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid)); - if (mode != MWIFIEX_BSS_MODE_IBSS) { + if (mode != NL80211_IFTYPE_ADHOC) { if (mwifiex_find_best_bss(priv, MWIFIEX_IOCTL_WAIT, &ssid_bssid)) return -EFAULT; @@ -1129,7 +1127,7 @@ done: if (mwifiex_bss_start(priv, MWIFIEX_IOCTL_WAIT, &ssid_bssid)) return -EFAULT; - if (mode == MWIFIEX_BSS_MODE_IBSS) { + if (mode == NL80211_IFTYPE_ADHOC) { /* Inform the BSS information to kernel, otherwise * kernel will give a panic after successful assoc */ if (mwifiex_cfg80211_inform_ibss_bss(priv)) @@ -1152,14 +1150,11 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); int ret = 0; - int mode = 0; if (priv->assoc_request) return -EBUSY; - mode = mwifiex_drv_get_mode(priv, MWIFIEX_IOCTL_WAIT); - - if (mode == MWIFIEX_BSS_MODE_IBSS) { + if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { wiphy_err(wiphy, "received infra assoc request " "when station is in ibss mode\n"); goto done; @@ -1171,7 +1166,7 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, (char *) sme->ssid, sme->bssid); ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, - mode, sme->channel, sme, 0); + priv->bss_mode, sme->channel, sme, 0); done: priv->assoc_result = ret; @@ -1191,13 +1186,11 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, { struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); int ret = 0; - int mode = 0; if (priv->ibss_join_request) return -EBUSY; - mode = mwifiex_drv_get_mode(priv, MWIFIEX_IOCTL_WAIT); - if (mode != MWIFIEX_BSS_MODE_IBSS) { + if (priv->bss_mode != NL80211_IFTYPE_ADHOC) { wiphy_err(wiphy, "request to join ibss received " "when station is not in ibss mode\n"); goto done; @@ -1209,8 +1202,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, (char *) params->ssid, params->bssid); ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid, - params->bssid, mode, params->channel, NULL, - params->privacy); + params->bssid, priv->bss_mode, + params->channel, NULL, params->privacy); done: priv->ibss_join_result = ret; queue_work(priv->workqueue, &priv->cfg_workqueue); @@ -1301,7 +1294,7 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, /* Clear all the other values */ memset(&mcs[rx_mcs_supp], 0, sizeof(struct ieee80211_mcs_info) - rx_mcs_supp); - if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA || + if (priv->bss_mode == NL80211_IFTYPE_STATION || ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ SETHT_MCS32(mcs_set.rx_mask); diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c index 999ed81512fa..07187a405fee 100644 --- a/drivers/net/wireless/mwifiex/cfp.c +++ b/drivers/net/wireless/mwifiex/cfp.c @@ -288,8 +288,7 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates) { u32 k = 0; struct mwifiex_adapter *adapter = priv->adapter; - if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA) { - /* Infra. mode */ + if (priv->bss_mode == NL80211_IFTYPE_STATION) { switch (adapter->config_bands) { case BAND_B: dev_dbg(adapter->dev, "info: infra band=%d " diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 1c9315d31d9c..00e73eac1af4 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -78,7 +78,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) memset(priv->curr_addr, 0xff, ETH_ALEN); priv->pkt_tx_ctrl = 0; - priv->bss_mode = MWIFIEX_BSS_MODE_INFRA; + priv->bss_mode = NL80211_IFTYPE_STATION; priv->data_rate = 0; /* Initially indicate the rate as auto */ priv->is_data_rate_auto = true; priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index b7e457110b4f..7fb81dfdf8f2 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -66,12 +66,6 @@ struct mwifiex_scan_resp { u8 *scan_table; }; -enum { - MWIFIEX_BSS_MODE_INFRA = 1, - MWIFIEX_BSS_MODE_IBSS, - MWIFIEX_BSS_MODE_AUTO -}; - #define MWIFIEX_PROMISC_MODE 1 #define MWIFIEX_MULTICAST_MODE 2 #define MWIFIEX_ALL_MULTI_MODE 4 diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 08fa721580cb..d8c7c5f8464e 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -808,7 +808,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, /* Set the BSS mode */ adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS; - bss_desc->bss_mode = MWIFIEX_BSS_MODE_IBSS; + bss_desc->bss_mode = NL80211_IFTYPE_ADHOC; adhoc_start->beacon_period = cpu_to_le16(priv->beacon_period); bss_desc->beacon_period = priv->beacon_period; @@ -1289,8 +1289,8 @@ int mwifiex_associate(struct mwifiex_private *priv, u8 current_bssid[ETH_ALEN]; /* Return error if the adapter or table entry is not marked as infra */ - if ((priv->bss_mode != MWIFIEX_BSS_MODE_INFRA) || - (bss_desc->bss_mode != MWIFIEX_BSS_MODE_INFRA)) + if ((priv->bss_mode != NL80211_IFTYPE_STATION) || + (bss_desc->bss_mode != NL80211_IFTYPE_STATION)) return -1; memcpy(¤t_bssid, @@ -1358,7 +1358,7 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv, !mwifiex_ssid_cmp(&bss_desc->ssid, &priv->curr_bss_params.bss_descriptor.ssid) && (priv->curr_bss_params.bss_descriptor.bss_mode == - MWIFIEX_BSS_MODE_IBSS)) { + NL80211_IFTYPE_ADHOC)) { dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: new ad-hoc SSID" " is the same as current; not attempting to re-join\n"); return -1; @@ -1421,9 +1421,9 @@ int mwifiex_deauthenticate(struct mwifiex_private *priv, int ret = 0; if (priv->media_connected) { - if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA) { + if (priv->bss_mode == NL80211_IFTYPE_STATION) { ret = mwifiex_deauthenticate_infra(priv, wait, mac); - } else if (priv->bss_mode == MWIFIEX_BSS_MODE_IBSS) { + } else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_AD_HOC_STOP, HostCmd_ACT_GEN_SET, 0, wait, NULL); diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 7bcb2e965aeb..12b9a364d52b 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -877,7 +877,7 @@ mwifiex_queuing_ra_based(struct mwifiex_private *priv) * Currently we assume if we are in Infra, then DA=RA. This might not be * true in the future */ - if ((priv->bss_mode == MWIFIEX_BSS_MODE_INFRA) && + if ((priv->bss_mode == NL80211_IFTYPE_STATION) && (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)) return false; @@ -1003,8 +1003,6 @@ int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, int mwifiex_change_adhoc_chan(struct mwifiex_private *priv, int channel); int mwifiex_set_radio(struct mwifiex_private *priv, u8 option); -int mwifiex_drv_get_mode(struct mwifiex_private *priv, u8 wait_option); - int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel); int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, @@ -1043,9 +1041,6 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, int type, int dbm); int mwifiex_main_process(struct mwifiex_adapter *); -int mwifiex_bss_ioctl_mode(struct mwifiex_private *, - struct mwifiex_wait_queue *, - u16 action, int *mode); int mwifiex_bss_ioctl_channel(struct mwifiex_private *, u16 action, struct mwifiex_chan_freq_power *cfp); diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 1152beb930ab..69ea32fd1fbd 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -455,8 +455,8 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode) bss_desc->disable_11n = false; /* Don't check for compatibility if roaming */ - if (priv->media_connected && (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA) - && (bss_desc->bss_mode == MWIFIEX_BSS_MODE_INFRA)) + if (priv->media_connected && (priv->bss_mode == NL80211_IFTYPE_STATION) + && (bss_desc->bss_mode == NL80211_IFTYPE_STATION)) return index; if (priv->wps.session_enable) { @@ -573,8 +573,8 @@ mwifiex_find_best_network_in_list(struct mwifiex_private *priv) for (i = 0; i < adapter->num_in_scan_table; i++) { switch (mode) { - case MWIFIEX_BSS_MODE_INFRA: - case MWIFIEX_BSS_MODE_IBSS: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: if (mwifiex_is_network_compatible(priv, i, mode) >= 0) { if (SCAN_RSSI(adapter->scan_table[i].rssi) > best_rssi) { @@ -584,7 +584,7 @@ mwifiex_find_best_network_in_list(struct mwifiex_private *priv) } } break; - case MWIFIEX_BSS_MODE_AUTO: + case NL80211_IFTYPE_UNSPECIFIED: default: if (SCAN_RSSI(adapter->scan_table[i].rssi) > best_rssi) { @@ -1314,9 +1314,9 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter, } if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_IBSS) - bss_entry->bss_mode = MWIFIEX_BSS_MODE_IBSS; + bss_entry->bss_mode = NL80211_IFTYPE_ADHOC; else - bss_entry->bss_mode = MWIFIEX_BSS_MODE_INFRA; + bss_entry->bss_mode = NL80211_IFTYPE_STATION; /* Process variable IE */ @@ -2251,8 +2251,7 @@ mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv, searching the table for multiple entires for the SSID until no more are found */ while ((table_idx = mwifiex_find_ssid_in_list(priv, del_ssid, NULL, - MWIFIEX_BSS_MODE_AUTO)) >= - 0) { + NL80211_IFTYPE_UNSPECIFIED)) >= 0) { dev_dbg(priv->adapter->dev, "info: Scan: Delete SSID Entry: Found Idx = %d\n", table_idx); @@ -2746,8 +2745,8 @@ mwifiex_find_ssid_in_list(struct mwifiex_private *priv, (priv, (u8) adapter->scan_table[i].bss_band, (u16) adapter->scan_table[i].channel))) { switch (mode) { - case MWIFIEX_BSS_MODE_INFRA: - case MWIFIEX_BSS_MODE_IBSS: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: j = mwifiex_is_network_compatible(priv, i, mode); @@ -2765,7 +2764,7 @@ mwifiex_find_ssid_in_list(struct mwifiex_private *priv, net = j; } break; - case MWIFIEX_BSS_MODE_AUTO: + case NL80211_IFTYPE_UNSPECIFIED: default: /* * Do not check compatibility if the mode @@ -2829,8 +2828,8 @@ mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid, scan_table[i]. channel)) { switch (mode) { - case MWIFIEX_BSS_MODE_INFRA: - case MWIFIEX_BSS_MODE_IBSS: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: net = mwifiex_is_network_compatible(priv, i, mode); break; @@ -2881,7 +2880,7 @@ int mwifiex_find_best_network(struct mwifiex_private *priv, (u8 *) &req_bss->mac_address, ETH_ALEN); /* Make sure we are in the right mode */ - if (priv->bss_mode == MWIFIEX_BSS_MODE_AUTO) + if (priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED) priv->bss_mode = req_bss->bss_mode; } diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 795b1eae768d..6fff26153e26 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -1089,10 +1089,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, break; case HostCmd_CMD_SET_BSS_MODE: cmd_ptr->command = cpu_to_le16(cmd_no); - if (priv->bss_mode == MWIFIEX_BSS_MODE_IBSS) + if (priv->bss_mode == NL80211_IFTYPE_ADHOC) cmd_ptr->params.bss_mode.con_type = CONNECTION_TYPE_ADHOC; - else if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA) + else if (priv->bss_mode == NL80211_IFTYPE_STATION) cmd_ptr->params.bss_mode.con_type = CONNECTION_TYPE_INFRA; cmd_ptr->size = cpu_to_le16(sizeof(struct diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index ae960ddf2bd4..b220b8b62cfa 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -65,7 +65,7 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, if (le16_to_cpu(pm->action) == EN_AUTO_PS && (le16_to_cpu(pm->params.auto_ps.ps_bitmap) & BITMAP_STA_PS) - && priv->bss_mode == MWIFIEX_BSS_MODE_IBSS) + && priv->bss_mode == NL80211_IFTYPE_ADHOC) adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; } diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index d4a5c1fcefc2..0187185a1fc6 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -82,7 +82,7 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv) priv->is_data_rate_auto = true; priv->data_rate = 0; - if (priv->bss_mode == MWIFIEX_BSS_MODE_IBSS) { + if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { priv->adhoc_state = ADHOC_IDLE; priv->adhoc_is_link_sensed = false; } diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 362301f417a4..abad07e012f9 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -404,7 +404,7 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv, if (!ssid_bssid) return -1; - if (priv->bss_mode == MWIFIEX_BSS_MODE_INFRA) { + if (priv->bss_mode == NL80211_IFTYPE_STATION) { /* Infra mode */ ret = mwifiex_deauthenticate(priv, NULL, NULL); if (ret) @@ -413,11 +413,11 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv, /* Search for the requested SSID in the scan table */ if (ssid_bssid->ssid.ssid_len) i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, - NULL, MWIFIEX_BSS_MODE_INFRA); + NULL, NL80211_IFTYPE_STATION); else i = mwifiex_find_bssid_in_list(priv, (u8 *) &ssid_bssid->bssid, - MWIFIEX_BSS_MODE_INFRA); + NL80211_IFTYPE_STATION); if (i < 0) return -1; @@ -451,11 +451,11 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv, if (ssid_bssid->ssid.ssid_len) i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, NULL, - MWIFIEX_BSS_MODE_IBSS); + NL80211_IFTYPE_ADHOC); else i = mwifiex_find_bssid_in_list(priv, (u8 *)&ssid_bssid->bssid, - MWIFIEX_BSS_MODE_IBSS); + NL80211_IFTYPE_ADHOC); if (i >= 0) { dev_dbg(adapter->dev, "info: network found in scan" @@ -1020,50 +1020,6 @@ int mwifiex_bss_ioctl_channel(struct mwifiex_private *priv, u16 action, return 0; } -/* - * IOCTL request handler to set/get BSS mode. - * - * This function prepares the correct firmware command and - * issues it to set or get the BSS mode. - * - * In case the mode is changed, a deauthentication is performed - * first by the function automatically. - */ -int mwifiex_bss_ioctl_mode(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - u16 action, int *mode) -{ - int ret = 0; - - if (!mode) - return -1; - - if (action == HostCmd_ACT_GEN_GET) { - *mode = priv->bss_mode; - return 0; - } - - if ((priv->bss_mode == *mode) || (*mode == MWIFIEX_BSS_MODE_AUTO)) { - dev_dbg(priv->adapter->dev, - "info: Already set to required mode! No change!\n"); - priv->bss_mode = *mode; - return 0; - } - - ret = mwifiex_deauthenticate(priv, wait, NULL); - - priv->sec_info.authentication_mode = MWIFIEX_AUTH_MODE_OPEN; - priv->bss_mode = *mode; - if (priv->bss_mode != MWIFIEX_BSS_MODE_AUTO) { - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_SET_BSS_MODE, - HostCmd_ACT_GEN_SET, 0, wait, NULL); - if (!ret) - ret = -EINPROGRESS; - } - - return ret; -} - /* * IOCTL request handler to set/get Ad-Hoc channel. * @@ -1236,33 +1192,6 @@ done: return ret; } -/* - * IOCTL request handler to get current driver mode. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_drv_get_mode(struct mwifiex_private *priv, u8 wait_option) -{ - struct mwifiex_wait_queue *wait = NULL; - int status = 0; - int mode = -1; - - /* Allocate wait buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -1; - - status = mwifiex_bss_ioctl_mode(priv, wait, HostCmd_ACT_GEN_GET, &mode); - - status = mwifiex_request_ioctl(priv, wait, status, wait_option); - - if (wait && (status != -EINPROGRESS)) - kfree(wait); - return mode; -} - /* * IOCTL request handler to get rate. * @@ -1780,7 +1709,7 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter, return -1; } - if (priv->bss_mode == MWIFIEX_BSS_MODE_IBSS) { + if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { /* * IBSS/WPA-None uses only one key (Group) for both receiving * and sending unicast and multicast packets. -- cgit v1.2.3-58-ga151 From f986b6d538c9351c99108b51be9f77ac1b300b16 Mon Sep 17 00:00:00 2001 From: Marc Yang Date: Mon, 28 Mar 2011 17:55:42 -0700 Subject: mwifiex: remove MWIFIEX_AUTH_MODE_ macros replace them with NL80211_AUTHTYPE_ macros Signed-off-by: Marc Yang Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 8 ++++---- drivers/net/wireless/mwifiex/init.c | 2 +- drivers/net/wireless/mwifiex/ioctl.h | 5 ----- drivers/net/wireless/mwifiex/join.c | 2 +- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 701c17980f6d..2d9680044c12 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -600,7 +600,7 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, mwifiex_deauthenticate(priv, wait, NULL); - priv->sec_info.authentication_mode = MWIFIEX_AUTH_MODE_OPEN; + priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_SET_BSS_MODE, HostCmd_ACT_GEN_SET, 0, wait, NULL); @@ -1056,7 +1056,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, priv->sec_info.encryption_mode = MWIFIEX_ENCRYPTION_MODE_WEP104; priv->sec_info.authentication_mode = - MWIFIEX_AUTH_MODE_OPEN; + NL80211_AUTHTYPE_OPEN_SYSTEM; } goto done; @@ -1065,9 +1065,9 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, /* Now handle infra mode. "sme" is valid for infra mode only */ if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC || sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) - auth_type = MWIFIEX_AUTH_MODE_OPEN; + auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; else if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) - auth_type = MWIFIEX_AUTH_MODE_SHARED; + auth_type = NL80211_AUTHTYPE_SHARED_KEY; if (sme->crypto.n_ciphers_pairwise) { pairwise_encrypt_mode = mwifiex_get_mwifiex_cipher(sme->crypto. diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 00e73eac1af4..bad436d60590 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -85,7 +85,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR; priv->sec_info.wep_status = MWIFIEX_802_11_WEP_DISABLED; - priv->sec_info.authentication_mode = MWIFIEX_AUTH_MODE_OPEN; + priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; priv->sec_info.encryption_mode = MWIFIEX_ENCRYPTION_MODE_NONE; for (i = 0; i < ARRAY_SIZE(priv->wep_key); i++) memset(&priv->wep_key[i], 0, sizeof(struct mwifiex_wep_key)); diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 7fb81dfdf8f2..7e0d3160f610 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -268,11 +268,6 @@ struct mwifiex_debug_info { u8 event_received; }; -enum { - MWIFIEX_AUTH_MODE_OPEN = 0x00, - MWIFIEX_AUTH_MODE_SHARED = 0x01, -}; - enum { MWIFIEX_ENCRYPTION_MODE_NONE = 0, MWIFIEX_ENCRYPTION_MODE_WEP40 = 1, diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index d8c7c5f8464e..8a1eb2a9ab13 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -449,7 +449,7 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, auth_tlv->auth_type = cpu_to_le16( (u16) priv->sec_info.authentication_mode); else - auth_tlv->auth_type = cpu_to_le16(MWIFIEX_AUTH_MODE_OPEN); + auth_tlv->auth_type = cpu_to_le16(NL80211_AUTHTYPE_OPEN_SYSTEM); pos += sizeof(auth_tlv->header) + le16_to_cpu(auth_tlv->header.len); -- cgit v1.2.3-58-ga151 From fd2e401a35500c9af63dc7ffbc545d2e3c478702 Mon Sep 17 00:00:00 2001 From: Marc Yang Date: Mon, 28 Mar 2011 17:55:43 -0700 Subject: mwifiex: remove unused radio_on variable and macros The radio_on variable is defined but never used. Signed-off-by: Marc Yang Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/fw.h | 3 --- drivers/net/wireless/mwifiex/init.c | 1 - drivers/net/wireless/mwifiex/ioctl.h | 1 - drivers/net/wireless/mwifiex/main.h | 1 - drivers/net/wireless/mwifiex/sta_ioctl.c | 3 --- 5 files changed, 9 deletions(-) diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 6593e071dea8..2d9339145e08 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -875,9 +875,6 @@ struct host_cmd_ds_802_11_snmp_mib { u8 value[1]; } __packed; -#define RADIO_ON 0x01 -#define RADIO_OFF 0x00 - struct mwifiex_rate_scope { __le16 type; __le16 length; diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index bad436d60590..6fcdaa9b4294 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -234,7 +234,6 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) memset(adapter->bcn_buf, 0, sizeof(adapter->bcn_buf)); adapter->bcn_buf_end = adapter->bcn_buf; - adapter->radio_on = RADIO_ON; adapter->multiple_dtim = 1; adapter->local_listen_interval = 0; /* default value in firmware diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 7e0d3160f610..d01160aa1db8 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -193,7 +193,6 @@ struct mwifiex_bss_info { u32 bss_chan; u32 region_code; u32 media_connected; - u32 radio_on; u32 max_power_level; u32 min_power_level; u32 adhoc_state; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 12b9a364d52b..c26f70441f83 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -611,7 +611,6 @@ struct mwifiex_adapter { u16 curr_tx_buf_size; u32 ioport; enum MWIFIEX_HARDWARE_STATUS hw_status; - u16 radio_on; u16 number_of_antenna; u32 fw_cap_info; /* spin lock for interrupt handling */ diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index abad07e012f9..b163507b1fe0 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -790,9 +790,6 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv, /* Connection status */ info->media_connected = priv->media_connected; - /* Radio status */ - info->radio_on = adapter->radio_on; - /* Tx power information */ info->max_power_level = priv->max_tx_power_level; info->min_power_level = priv->min_tx_power_level; -- cgit v1.2.3-58-ga151 From 4f3f1ee9f373abfdc09bb3bed87969b7fe0fba06 Mon Sep 17 00:00:00 2001 From: Marc Yang Date: Mon, 28 Mar 2011 17:55:44 -0700 Subject: mwifiex: remove unused macros in fw.h These definitions are no longer used after previous cleanups. Signed-off-by: Marc Yang Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/fw.h | 42 --------------------------------------- 1 file changed, 42 deletions(-) diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 2d9339145e08..b4e4991e58e8 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -107,8 +107,6 @@ enum KEY_INFO_WAPI { #define FIRMWARE_READY 0xfedc -#define FIRMWARE_TRANSFER_NBLOCK 2 - enum MWIFIEX_802_11_PRIVACY_FILTER { MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL, MWIFIEX_802_11_PRIV_FILTER_8021X_WEP @@ -125,50 +123,22 @@ enum MWIFIEX_802_11_WEP_STATUS { #define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) #define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) #define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2) -#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 4) -#define TLV_TYPE_SNR_LOW (PROPRIETARY_TLV_BASE_ID + 5) -#define TLV_TYPE_FAILCOUNT (PROPRIETARY_TLV_BASE_ID + 6) -#define TLV_TYPE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 7) -#define TLV_TYPE_LEDBEHAVIOR (PROPRIETARY_TLV_BASE_ID + 9) #define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10) -#define TLV_TYPE_POWER_TBL_2_4GHZ (PROPRIETARY_TLV_BASE_ID + 12) -#define TLV_TYPE_POWER_TBL_5GHZ (PROPRIETARY_TLV_BASE_ID + 13) #define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16) #define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) -#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) -#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23) -#define TLV_TYPE_STARTBGSCANLATER (PROPRIETARY_TLV_BASE_ID + 30) #define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) -#define TLV_TYPE_LINK_QUALITY (PROPRIETARY_TLV_BASE_ID + 36) -#define TLV_TYPE_RSSI_LOW_DATA (PROPRIETARY_TLV_BASE_ID + 38) -#define TLV_TYPE_SNR_LOW_DATA (PROPRIETARY_TLV_BASE_ID + 39) -#define TLV_TYPE_RSSI_HIGH_DATA (PROPRIETARY_TLV_BASE_ID + 40) -#define TLV_TYPE_SNR_HIGH_DATA (PROPRIETARY_TLV_BASE_ID + 41) #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) -#define TLV_TYPE_BSSID (PROPRIETARY_TLV_BASE_ID + 35) #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 -#define TLV_TYPE_HT_CAP (PROPRIETARY_TLV_BASE_ID + 74) -#define TLV_TYPE_HT_INFO (PROPRIETARY_TLV_BASE_ID + 75) -#define TLV_SECONDARY_CHANNEL_OFFSET (PROPRIETARY_TLV_BASE_ID + 76) -#define TLV_TYPE_2040BSS_COEXISTENCE (PROPRIETARY_TLV_BASE_ID + 77) -#define TLV_TYPE_OVERLAP_BSS_SCAN_PARAM (PROPRIETARY_TLV_BASE_ID + 78) -#define TLV_TYPE_EXTCAP (PROPRIETARY_TLV_BASE_ID + 79) -#define TLV_TYPE_HT_OPERATIONAL_MCS_SET (PROPRIETARY_TLV_BASE_ID + 80) - -#define ADDBA_TID_MASK (BIT(2) | BIT(3) | BIT(4) | BIT(5)) -#define DELBA_TID_MASK (BIT(12) | BIT(13) | BIT(14) | BIT(15)) #define SSN_MASK 0xfff0 #define BA_RESULT_SUCCESS 0x0 -#define BA_RESULT_FAILURE 0x1 #define BA_RESULT_TIMEOUT 0x2 -#define BA_RESULT_DATA_INVALID 0x3 #define IS_BASTREAM_SETUP(ptr) (ptr->ba_status) @@ -214,7 +184,6 @@ enum MWIFIEX_802_11_WEP_STATUS { #define LLC_SNAP_LEN 8 -#define TLV_TYPE_RATE_DROP_PATTERN (PROPRIETARY_TLV_BASE_ID + 81) #define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) #define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) @@ -282,15 +251,7 @@ enum ENH_PS_MODES { #define HostCmd_RET_BIT 0x8000 #define HostCmd_ACT_GEN_GET 0x0000 #define HostCmd_ACT_GEN_SET 0x0001 -#define HostCmd_ACT_GEN_REMOVE 0x0004 -#define HostCmd_ACT_SET_BOTH 0x0003 -#define HostCmd_ACT_GET_BOTH 0x000c #define HostCmd_RESULT_OK 0x0000 -#define HostCmd_RESULT_ERROR 0x0001 -#define HostCmd_RESULT_NOT_SUPPORT 0x0002 -#define HostCmd_RESULT_PENDING 0x0003 -#define HostCmd_RESULT_BUSY 0x0004 -#define HostCmd_RESULT_PARTIAL_DATA 0x0005 #define HostCmd_ACT_MAC_RX_ON 0x0001 #define HostCmd_ACT_MAC_TX_ON 0x0002 @@ -298,11 +259,8 @@ enum ENH_PS_MODES { #define HostCmd_ACT_MAC_ETHERNETII_ENABLE 0x0010 #define HostCmd_ACT_MAC_PROMISCUOUS_ENABLE 0x0080 #define HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 -#define HostCmd_ACT_MAC_RTS_CTS_ENABLE 0x0200 -#define HostCmd_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400 #define HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON 0x2000 -#define HostCmd_BSS_MODE_BSS 0x0001 #define HostCmd_BSS_MODE_IBSS 0x0002 #define HostCmd_BSS_MODE_ANY 0x0003 -- cgit v1.2.3-58-ga151 From 4dd365fd55991b4e54a1d1c255081e6370b9da29 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Wed, 30 Mar 2011 18:01:15 -0700 Subject: ieee80211: add HT extended capabilities masks IEEE Std 802.11n, Oct. 29, 2009: 7.3.2.56.5 HT Extended Capabilities field Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 2d1c6117d92c..79690b710665 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -884,6 +884,15 @@ struct ieee80211_ht_cap { #define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 #define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 +/* 802.11n HT extended capabilities masks (for extended_ht_cap_info) */ +#define IEEE80211_HT_EXT_CAP_PCO 0x0001 +#define IEEE80211_HT_EXT_CAP_PCO_TIME 0x0006 +#define IEEE80211_HT_EXT_CAP_PCO_TIME_SHIFT 1 +#define IEEE80211_HT_EXT_CAP_MCS_FB 0x0300 +#define IEEE80211_HT_EXT_CAP_MCS_FB_SHIFT 8 +#define IEEE80211_HT_EXT_CAP_HTC_SUP 0x0400 +#define IEEE80211_HT_EXT_CAP_RD_RESPONDER 0x0800 + /* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ #define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 #define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C -- cgit v1.2.3-58-ga151 From 2b06bdbe073f8dff93eb476f07352df43dcdba44 Mon Sep 17 00:00:00 2001 From: Marc Yang Date: Wed, 30 Mar 2011 18:12:44 -0700 Subject: mwifiex: cleanup power save related struct and macros remove redundant structures and unused macros Signed-off-by: Marc Yang Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cmdevt.c | 37 ++++++++++++++------------- drivers/net/wireless/mwifiex/fw.h | 41 +++++------------------------- drivers/net/wireless/mwifiex/init.c | 2 +- drivers/net/wireless/mwifiex/sta_cmdresp.c | 23 ++++++++--------- 4 files changed, 37 insertions(+), 66 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 3865dd19e4f8..a9aeb31af455 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -275,14 +275,14 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) } if (GET_BSS_ROLE(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY)) == MWIFIEX_BSS_ROLE_STA) { - if (!sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl) + if (!sleep_cfm_buf->ps_cfm_sleep.resp_ctrl) /* Response is not needed for sleep confirm command */ adapter->ps_state = PS_STATE_SLEEP; else adapter->ps_state = PS_STATE_SLEEP_CFM; - if (!sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl + if (!sleep_cfm_buf->ps_cfm_sleep.resp_ctrl && (adapter->is_hs_configured && !adapter->sleep_period.period)) { adapter->pm_wakeup_card_req = true; @@ -1211,15 +1211,18 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv, if (cmd_action == DIS_AUTO_PS) { psmode_enh->action = cpu_to_le16(DIS_AUTO_PS); psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); - cmd->size = cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE); + cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + + sizeof(psmode_enh->params.ps_bitmap)); } else if (cmd_action == GET_PS) { psmode_enh->action = cpu_to_le16(GET_PS); psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); - cmd->size = cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE); + cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + + sizeof(psmode_enh->params.ps_bitmap)); } else if (cmd_action == EN_AUTO_PS) { psmode_enh->action = cpu_to_le16(EN_AUTO_PS); - psmode_enh->params.auto_ps.ps_bitmap = cpu_to_le16(ps_bitmap); - cmd_size = S_DS_GEN + AUTO_PS_FIX_SIZE; + psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); + cmd_size = S_DS_GEN + sizeof(psmode_enh->action) + + sizeof(psmode_enh->params.ps_bitmap); tlv = (u8 *) cmd + cmd_size; if (ps_bitmap & BITMAP_STA_PS) { struct mwifiex_adapter *adapter = priv->adapter; @@ -1249,24 +1252,23 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv, } if (ps_bitmap & BITMAP_AUTO_DS) { - struct mwifiex_ie_types_auto_ds_param *auto_ps_tlv = + struct mwifiex_ie_types_auto_ds_param *auto_ds_tlv = (struct mwifiex_ie_types_auto_ds_param *) tlv; - struct mwifiex_auto_ds_param *auto_ds = - &auto_ps_tlv->param; u16 idletime = 0; - auto_ps_tlv->header.type = + + auto_ds_tlv->header.type = cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM); - auto_ps_tlv->header.len = - cpu_to_le16(sizeof(*auto_ps_tlv) - + auto_ds_tlv->header.len = + cpu_to_le16(sizeof(*auto_ds_tlv) - sizeof(struct mwifiex_ie_types_header)); - cmd_size += sizeof(*auto_ps_tlv); - tlv += sizeof(*auto_ps_tlv); + cmd_size += sizeof(*auto_ds_tlv); + tlv += sizeof(*auto_ds_tlv); if (data_buf) idletime = ((struct mwifiex_ds_auto_ds *) data_buf)->idle_time; dev_dbg(priv->adapter->dev, "cmd: PS Command: Enter Auto Deep Sleep\n"); - auto_ds->deep_sleep_timeout = cpu_to_le16(idletime); + auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime); } cmd->size = cpu_to_le16(cmd_size); } @@ -1290,7 +1292,7 @@ int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv, uint16_t action = le16_to_cpu(ps_mode->action); uint16_t ps_bitmap = le16_to_cpu(ps_mode->params.ps_bitmap); uint16_t auto_ps_bitmap = - le16_to_cpu(ps_mode->params.auto_ps.ps_bitmap); + le16_to_cpu(ps_mode->params.ps_bitmap); dev_dbg(adapter->dev, "info: %s: PS_MODE cmd reply result=%#x action=%#X\n", __func__, resp->result, action); @@ -1318,8 +1320,7 @@ int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv, } } } else if (action == GET_PS) { - if (ps_bitmap & (BITMAP_STA_PS | BITMAP_UAP_INACT_PS - | BITMAP_UAP_DTIM_PS)) + if (ps_bitmap & BITMAP_STA_PS) adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; else adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index b4e4991e58e8..d981265eb943 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -127,11 +127,14 @@ enum MWIFIEX_802_11_WEP_STATUS { #define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16) #define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) - #define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) - #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) +#define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) +#define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) +#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) +#define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) +#define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 @@ -184,11 +187,6 @@ enum MWIFIEX_802_11_WEP_STATUS { #define LLC_SNAP_LEN 8 -#define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) -#define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) - -#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) - #define MOD_CLASS_HR_DSSS 0x03 #define MOD_CLASS_OFDM 0x07 #define MOD_CLASS_HT 0x08 @@ -553,34 +551,12 @@ struct mwifiex_ps_param { __le16 delay_to_ps; }; -struct mwifiex_auto_ds_param { - __le16 deep_sleep_timeout; -}; - -struct sleep_confirm_param { - __le16 resp_ctrl; -}; - #define BITMAP_AUTO_DS 0x01 #define BITMAP_STA_PS 0x10 -#define BITMAP_UAP_INACT_PS 0x100 -#define BITMAP_UAP_DTIM_PS 0x200 -struct auto_ps_param { - __le16 ps_bitmap; - /* auto deep sleep parameter, - * sta power save parameter - * uap inactivity parameter - * uap DTIM parameter */ -}; - -#define AUTO_PS_FIX_SIZE 4 - -#define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) -#define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) struct mwifiex_ie_types_auto_ds_param { struct mwifiex_ie_types_header header; - struct mwifiex_auto_ds_param param; + __le16 deep_sleep_timeout; } __packed; struct mwifiex_ie_types_ps_param { @@ -593,10 +569,7 @@ struct host_cmd_ds_802_11_ps_mode_enh { union { struct mwifiex_ps_param opt_ps; - struct mwifiex_auto_ds_param auto_ds; - struct sleep_confirm_param sleep_cfm; __le16 ps_bitmap; - struct auto_ps_param auto_ps; } params; } __packed; @@ -1260,7 +1233,7 @@ struct mwifiex_opt_sleep_confirm { __le16 seq_num; __le16 result; __le16 action; - struct sleep_confirm_param sleep_cfm; + __le16 resp_ctrl; } __packed; struct mwifiex_opt_sleep_confirm_buffer { diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 6fcdaa9b4294..43ea87d0f348 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -280,7 +280,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) cpu_to_le16(adapter->sleep_cfm->len); sleep_cfm_buf->ps_cfm_sleep.result = 0; sleep_cfm_buf->ps_cfm_sleep.action = cpu_to_le16(SLEEP_CONFIRM); - sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl = + sleep_cfm_buf->ps_cfm_sleep.resp_ctrl = cpu_to_le16(RESP_NEEDED); } memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params)); diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index b220b8b62cfa..74add45b99b6 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -46,6 +46,7 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, { struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; struct mwifiex_adapter *adapter = priv->adapter; + struct host_cmd_ds_802_11_ps_mode_enh *pm; unsigned long flags; dev_err(adapter->dev, "CMD_RESP: cmd %#x error, result=%#x\n", @@ -55,20 +56,16 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, switch (le16_to_cpu(resp->command)) { case HostCmd_CMD_802_11_PS_MODE_ENH: - { - struct host_cmd_ds_802_11_ps_mode_enh *pm = - &resp->params.psmode_enh; - dev_err(adapter->dev, "PS_MODE_ENH cmd failed: " - "result=0x%x action=0x%X\n", + pm = &resp->params.psmode_enh; + dev_err(adapter->dev, "PS_MODE_ENH cmd failed: " + "result=0x%x action=0x%X\n", resp->result, le16_to_cpu(pm->action)); - /* We do not re-try enter-ps command in ad-hoc mode. */ - if (le16_to_cpu(pm->action) == EN_AUTO_PS && - (le16_to_cpu(pm->params.auto_ps.ps_bitmap) & - BITMAP_STA_PS) - && priv->bss_mode == NL80211_IFTYPE_ADHOC) - adapter->ps_mode = - MWIFIEX_802_11_POWER_MODE_CAM; - } + /* We do not re-try enter-ps command in ad-hoc mode. */ + if (le16_to_cpu(pm->action) == EN_AUTO_PS && + (le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) && + priv->bss_mode == NL80211_IFTYPE_ADHOC) + adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; + break; case HostCmd_CMD_802_11_SCAN: /* Cancel all pending scan command */ -- cgit v1.2.3-58-ga151 From 7327890a1f42046c50030c8723bdbd9266d781bc Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Wed, 30 Mar 2011 18:12:45 -0700 Subject: mwifiex: remove struct mwifiex_802_11_fixed_ies struct mwifiex_802_11_fixed_ies is not necessary. struct mwifiex_event_wep_icv_err is not used any more. Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/fw.h | 14 -------------- drivers/net/wireless/mwifiex/scan.c | 16 ++++++++-------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index d981265eb943..2b938115b26a 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -343,20 +343,6 @@ enum ENH_PS_MODES { #define EVENT_GET_BSS_TYPE(event_cause) \ (((event_cause) >> 24) & 0x00ff) -struct mwifiex_event_wep_icv_err { - u16 reason_code; - u8 src_mac_addr[ETH_ALEN]; - u8 wep_key_index; - u8 wep_key_length; - u8 key[WLAN_KEY_LEN_WEP104]; -}; - -struct mwifiex_802_11_fixed_ies { - u8 time_stamp[8]; - __le16 beacon_interval; - __le16 capabilities; -}; - struct mwifiex_ie_types_header { __le16 type; __le16 len; diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 69ea32fd1fbd..64ed60a80977 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1210,7 +1210,8 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter, struct ieee_types_ds_param_set *ds_param_set; struct ieee_types_cf_param_set *cf_param_set; struct ieee_types_ibss_param_set *ibss_param_set; - struct mwifiex_802_11_fixed_ies fixed_ie; + __le16 beacon_interval; + __le16 capabilities; u8 *current_ptr; u8 *rate; u8 element_len; @@ -1283,22 +1284,21 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter, bss_entry->beacon_buf_size = bytes_left_for_current_beacon; /* Time stamp is 8 bytes long */ - memcpy(fixed_ie.time_stamp, current_ptr, 8); memcpy(bss_entry->time_stamp, current_ptr, 8); current_ptr += 8; bytes_left_for_current_beacon -= 8; /* Beacon interval is 2 bytes long */ - memcpy(&fixed_ie.beacon_interval, current_ptr, 2); - bss_entry->beacon_period = le16_to_cpu(fixed_ie.beacon_interval); + memcpy(&beacon_interval, current_ptr, 2); + bss_entry->beacon_period = le16_to_cpu(beacon_interval); current_ptr += 2; bytes_left_for_current_beacon -= 2; /* Capability information is 2 bytes long */ - memcpy(&fixed_ie.capabilities, current_ptr, 2); - dev_dbg(adapter->dev, "info: InterpretIE: fixed_ie.capabilities=0x%X\n", - fixed_ie.capabilities); - bss_entry->cap_info_bitmap = le16_to_cpu(fixed_ie.capabilities); + memcpy(&capabilities, current_ptr, 2); + dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n", + capabilities); + bss_entry->cap_info_bitmap = le16_to_cpu(capabilities); current_ptr += 2; bytes_left_for_current_beacon -= 2; -- cgit v1.2.3-58-ga151 From 8120347de30f98982b8c75243e3b17dd1ee75740 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Thu, 31 Mar 2011 19:50:14 -0700 Subject: mwifiex: remove unused macros in decl.h and main.h These macros are leftover of previous cleanup patches. Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/decl.h | 24 ------------------------ drivers/net/wireless/mwifiex/main.h | 7 ------- 2 files changed, 31 deletions(-) diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 4e1f115d3ec3..c3c15f9e757e 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h @@ -51,7 +51,6 @@ #define MWIFIEX_RATE_BITMAP_MCS127 159 #define MWIFIEX_RX_DATA_BUF_SIZE (4 * 1024) -#define MWIFIEX_RX_CMD_BUF_SIZE (2 * 1024) #define MWIFIEX_RTS_MIN_VALUE (0) #define MWIFIEX_RTS_MAX_VALUE (2347) @@ -141,13 +140,6 @@ struct mwifiex_bss_attr { u32 bss_num; }; -enum mwifiex_cmd_result_e { - MWIFIEX_CMD_RESULT_SUCCESS = 0, - MWIFIEX_CMD_RESULT_FAILURE = 1, - MWIFIEX_CMD_RESULT_TIMEOUT = 2, - MWIFIEX_CMD_RESULT_INVALID_DATA = 3 -} __packed; - enum mwifiex_wmm_ac_e { WMM_AC_BK, WMM_AC_BE, @@ -155,22 +147,6 @@ enum mwifiex_wmm_ac_e { WMM_AC_VO } __packed; -enum mwifiex_wmm_queue_config_action_e { - MWIFIEX_WMM_QUEUE_CONFIG_ACTION_GET = 0, - MWIFIEX_WMM_QUEUE_CONFIG_ACTION_SET = 1, - MWIFIEX_WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2, - MWIFIEX_WMM_QUEUE_CONFIG_ACTION_MAX -} __packed; - -enum mwifiex_wmm_queue_stats_action_e { - MWIFIEX_WMM_STATS_ACTION_START = 0, - MWIFIEX_WMM_STATS_ACTION_STOP = 1, - MWIFIEX_WMM_STATS_ACTION_GET_CLR = 2, - MWIFIEX_WMM_STATS_ACTION_SET_CFG = 3, /* Not currently used */ - MWIFIEX_WMM_STATS_ACTION_GET_CFG = 4, /* Not currently used */ - MWIFIEX_WMM_STATS_ACTION_MAX -} __packed; - struct mwifiex_device { struct mwifiex_bss_attr bss_attr[MWIFIEX_MAX_BSS_NUM]; }; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index c26f70441f83..43ff149de9db 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -50,8 +50,6 @@ enum { }; #define DRV_MODE_STA 0x1 -#define DRV_MODE_UAP 0x2 -#define DRV_MODE_UAP_STA 0x3 #define SD8787_W0 0x30 #define SD8787_W1 0x31 @@ -74,13 +72,8 @@ struct mwifiex_drv_mode { #define MWIFIEX_TIMER_10S 10000 #define MWIFIEX_TIMER_1S 1000 -#define NL_MAX_PAYLOAD 1024 -#define NL_MULTICAST_GROUP 1 - #define MAX_TX_PENDING 60 -#define HEADER_ALIGNMENT 8 - #define MWIFIEX_UPLD_SIZE (2312) #define MAX_EVENT_SIZE 1024 -- cgit v1.2.3-58-ga151 From 832fd35a545ecde11082d2dab74dd0aef8e0505e Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 1 Apr 2011 15:32:16 +0530 Subject: ath9k_hw: Use appropriate rx gain table for AR9485 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 3daf3df02481..aebaad97b190 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -66,8 +66,8 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) /* rx/tx gain */ INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9485_common_rx_gain_1_1, - ARRAY_SIZE(ar9485_common_rx_gain_1_1), 2); + ar9485Common_wo_xlna_rx_gain_1_1, + ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2); INIT_INI_ARRAY(&ah->iniModesTxGain, ar9485_modes_lowest_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), @@ -220,8 +220,8 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) default: if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9485_common_rx_gain_1_1, - ARRAY_SIZE(ar9485_common_rx_gain_1_1), + ar9485Common_wo_xlna_rx_gain_1_1, + ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2); else INIT_INI_ARRAY(&ah->iniModesRxGain, -- cgit v1.2.3-58-ga151 From ce57d9e694d98e421e329fbac5d6f5dc5e9e101e Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 1 Apr 2011 12:06:48 +0200 Subject: ssb: trivial: use u8 for chip_rev (it's mask is 0xF) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/scan.c | 2 +- include/linux/ssb/ssb.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index 29884c00c4d5..7dca719fbcfb 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c @@ -307,7 +307,7 @@ int ssb_bus_scan(struct ssb_bus *bus, } else { if (bus->bustype == SSB_BUSTYPE_PCI) { bus->chip_id = pcidev_to_chipid(bus->host_pci); - pci_read_config_word(bus->host_pci, PCI_REVISION_ID, + pci_read_config_byte(bus->host_pci, PCI_REVISION_ID, &bus->chip_rev); bus->chip_package = 0; } else { diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 9659eff52ca2..7e99b348834c 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -308,7 +308,7 @@ struct ssb_bus { /* ID information about the Chip. */ u16 chip_id; - u16 chip_rev; + u8 chip_rev; u16 sprom_offset; u16 sprom_size; /* number of words in sprom */ u8 chip_package; -- cgit v1.2.3-58-ga151 From 6c74608bd479bbe02ce330f83df43c3f535ed200 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 1 Apr 2011 12:07:32 +0200 Subject: ssb: pci: trivial: drop useless pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_pcicore.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 0e8d35224614..e0cf29e57919 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -417,11 +417,9 @@ static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) void ssb_pcicore_init(struct ssb_pcicore *pc) { struct ssb_device *dev = pc->dev; - struct ssb_bus *bus; if (!dev) return; - bus = dev->bus; if (!ssb_device_is_enabled(dev)) ssb_device_enable(dev, 0); -- cgit v1.2.3-58-ga151 From 1b1c7acd9709e545399d1b6b89888f025911c0a2 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 1 Apr 2011 12:07:33 +0200 Subject: ssb: pci: fix mdio writes on newer cores (rev 10+) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_pcicore.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index e0cf29e57919..08fa6fdfc101 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -444,11 +444,35 @@ static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data) pcicore_write32(pc, 0x134, data); } +static void ssb_pcie_mdio_set_phy(struct ssb_pcicore *pc, u8 phy) +{ + const u16 mdio_control = 0x128; + const u16 mdio_data = 0x12C; + u32 v; + int i; + + v = (1 << 30); /* Start of Transaction */ + v |= (1 << 28); /* Write Transaction */ + v |= (1 << 17); /* Turnaround */ + v |= (0x1F << 18); + v |= (phy << 4); + pcicore_write32(pc, mdio_data, v); + + udelay(10); + for (i = 0; i < 200; i++) { + v = pcicore_read32(pc, mdio_control); + if (v & 0x100 /* Trans complete */) + break; + msleep(1); + } +} + static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, u8 address, u16 data) { const u16 mdio_control = 0x128; const u16 mdio_data = 0x12C; + int max_retries = 10; u32 v; int i; @@ -456,16 +480,22 @@ static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, v |= 0x2; /* MDIO Clock Divisor */ pcicore_write32(pc, mdio_control, v); + if (pc->dev->id.revision >= 10) { + max_retries = 200; + ssb_pcie_mdio_set_phy(pc, device); + } + v = (1 << 30); /* Start of Transaction */ v |= (1 << 28); /* Write Transaction */ v |= (1 << 17); /* Turnaround */ - v |= (u32)device << 22; + if (pc->dev->id.revision < 10) + v |= (u32)device << 22; v |= (u32)address << 18; v |= data; pcicore_write32(pc, mdio_data, v); /* Wait for the device to complete the transaction */ udelay(10); - for (i = 0; i < 10; i++) { + for (i = 0; i < max_retries; i++) { v = pcicore_read32(pc, mdio_control); if (v & 0x100 /* Trans complete */) break; -- cgit v1.2.3-58-ga151 From ba91d1a1bcccd90247b5b9703c1a236cc2e95698 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 1 Apr 2011 12:07:34 +0200 Subject: ssb: pci: implement mdio reading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_pcicore.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 08fa6fdfc101..76cbf96001f1 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -467,6 +467,49 @@ static void ssb_pcie_mdio_set_phy(struct ssb_pcicore *pc, u8 phy) } } +#if 0 +//done but not used yet +static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address) +{ + const u16 mdio_control = 0x128; + const u16 mdio_data = 0x12C; + int max_retries = 10; + u16 ret = 0; + u32 v; + int i; + + v = 0x80; /* Enable Preamble Sequence */ + v |= 0x2; /* MDIO Clock Divisor */ + pcicore_write32(pc, mdio_control, v); + + if (pc->dev->id.revision >= 10) { + max_retries = 200; + ssb_pcie_mdio_set_phy(pc, device); + } + + v = (1 << 30); /* Start of Transaction */ + v |= (1 << 29); /* Read Transaction */ + v |= (1 << 17); /* Turnaround */ + if (pc->dev->id.revision < 10) + v |= (u32)device << 22; + v |= (u32)address << 18; + pcicore_write32(pc, mdio_data, v); + /* Wait for the device to complete the transaction */ + udelay(10); + for (i = 0; i < 200; i++) { + v = pcicore_read32(pc, mdio_control); + if (v & 0x100 /* Trans complete */) { + udelay(10); + ret = pcicore_read32(pc, mdio_data); + break; + } + msleep(1); + } + pcicore_write32(pc, mdio_control, 0); + return ret; +} +#endif + static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, u8 address, u16 data) { -- cgit v1.2.3-58-ga151 From ccc7c28af205888798b51b6cbc0b557ac1170a49 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 1 Apr 2011 13:26:52 +0200 Subject: ssb: pci: implement serdes workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_pcicore.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 76cbf96001f1..1ba9f0ee6f94 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -15,6 +15,11 @@ #include "ssb_private.h" +static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address); +static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data); +static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address); +static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, + u8 address, u16 data); static inline u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset) @@ -403,6 +408,27 @@ static int pcicore_is_in_hostmode(struct ssb_pcicore *pc) } #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ +/************************************************** + * Workarounds. + **************************************************/ + +static u8 ssb_pcicore_polarity_workaround(struct ssb_pcicore *pc) +{ + return (ssb_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80; +} + +static void ssb_pcicore_serdes_workaround(struct ssb_pcicore *pc) +{ + const u8 serdes_pll_device = 0x1D; + const u8 serdes_rx_device = 0x1F; + u16 tmp; + + ssb_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */, + ssb_pcicore_polarity_workaround(pc)); + tmp = ssb_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */); + if (tmp & 0x4000) + ssb_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000); +} /************************************************** * Generic and Clientmode operation code. @@ -430,6 +456,8 @@ void ssb_pcicore_init(struct ssb_pcicore *pc) #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ if (!pc->hostmode) ssb_pcicore_init_clientmode(pc); + + ssb_pcicore_serdes_workaround(pc); } static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) @@ -467,8 +495,6 @@ static void ssb_pcie_mdio_set_phy(struct ssb_pcicore *pc, u8 phy) } } -#if 0 -//done but not used yet static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address) { const u16 mdio_control = 0x128; @@ -508,7 +534,6 @@ static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address) pcicore_write32(pc, mdio_control, 0); return ret; } -#endif static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, u8 address, u16 data) -- cgit v1.2.3-58-ga151 From 26d59535aa08386b97ece58a27bb16fca4f066db Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 1 Apr 2011 13:52:48 +0200 Subject: mac80211: clean up station cleanup timer We currently run this timer exactly once when a new mac80211 device is registered, but that is completely pointless since it will have no work to do at all. Therefore, remove that and also simplify some code using the timer. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/main.c | 5 ----- net/mac80211/sta_info.c | 13 ++----------- net/mac80211/sta_info.h | 1 - net/mac80211/util.c | 2 +- 4 files changed, 3 insertions(+), 18 deletions(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 562d2984c482..dc50fc3153e5 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -879,10 +879,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) local->dynamic_ps_forced_timeout = -1; - result = sta_info_start(local); - if (result < 0) - goto fail_sta_info; - result = ieee80211_wep_init(local); if (result < 0) wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", @@ -945,7 +941,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) rtnl_unlock(); ieee80211_wep_free(local); sta_info_stop(local); - fail_sta_info: destroy_workqueue(local->workqueue); fail_workqueue: wiphy_unregister(local->hw.wiphy); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 5ec0a7c51b6d..999f8fbf0b4b 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -768,9 +768,8 @@ static void sta_info_cleanup(unsigned long data) if (!timer_needed) return; - local->sta_cleanup.expires = - round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); - add_timer(&local->sta_cleanup); + mod_timer(&local->sta_cleanup, + round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL)); } void sta_info_init(struct ieee80211_local *local) @@ -783,14 +782,6 @@ void sta_info_init(struct ieee80211_local *local) setup_timer(&local->sta_cleanup, sta_info_cleanup, (unsigned long)local); - local->sta_cleanup.expires = - round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); -} - -int sta_info_start(struct ieee80211_local *local) -{ - add_timer(&local->sta_cleanup); - return 0; } void sta_info_stop(struct ieee80211_local *local) diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 57681149e37f..43238e99cfb3 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -497,7 +497,6 @@ void sta_info_set_tim_bit(struct sta_info *sta); void sta_info_clear_tim_bit(struct sta_info *sta); void sta_info_init(struct ieee80211_local *local); -int sta_info_start(struct ieee80211_local *local); void sta_info_stop(struct ieee80211_local *local); int sta_info_flush(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 556647a910ac..ef0560a2346a 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1290,7 +1290,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) } } - add_timer(&local->sta_cleanup); + mod_timer(&local->sta_cleanup, jiffies + 1); mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) -- cgit v1.2.3-58-ga151 From 1e429f3842b5c9b5967a250f4daf78f92436268c Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 4 Apr 2011 18:25:14 -0300 Subject: Bluetooth: Remove gfp_mask param from hci_reassembly() It is unnecessary, once we are always in interrupt context. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_core.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index decd60198f31..a80bc1cdb35b 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1341,7 +1341,7 @@ int hci_recv_frame(struct sk_buff *skb) EXPORT_SYMBOL(hci_recv_frame); static int hci_reassembly(struct hci_dev *hdev, int type, void *data, - int count, __u8 index, gfp_t gfp_mask) + int count, __u8 index) { int len = 0; int hlen = 0; @@ -1371,7 +1371,7 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data, break; } - skb = bt_skb_alloc(len, gfp_mask); + skb = bt_skb_alloc(len, GFP_ATOMIC); if (!skb) return -ENOMEM; @@ -1457,8 +1457,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) return -EILSEQ; while (count) { - rem = hci_reassembly(hdev, type, data, count, - type - 1, GFP_ATOMIC); + rem = hci_reassembly(hdev, type, data, count, type - 1); if (rem < 0) return rem; @@ -1492,8 +1491,8 @@ int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count) } else type = bt_cb(skb)->pkt_type; - rem = hci_reassembly(hdev, type, data, - count, STREAM_REASSEMBLY, GFP_ATOMIC); + rem = hci_reassembly(hdev, type, data, count, + STREAM_REASSEMBLY); if (rem < 0) return rem; -- cgit v1.2.3-58-ga151 From e17acd40f6006d0a0e0b1b3f7359ba4d543011c6 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 30 Mar 2011 23:57:16 +0300 Subject: Bluetooth: Add mgmt_device_found event This patch adds a device_found event to the Management interface. For now the event only maps to BR/EDR inquiry result HCI events, but in the future the plan is to also use it for the LE device discovery process. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 2 ++ include/net/bluetooth/mgmt.h | 8 ++++++++ net/bluetooth/hci_event.c | 22 ++++++++++++++-------- net/bluetooth/mgmt.c | 17 +++++++++++++++++ 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3b2f09df279a..2a88fc82429b 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -787,6 +787,8 @@ int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status); int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, u8 status); +int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, + u8 *eir); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 1a6283f9fee8..864d0cbd2d57 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -267,3 +267,11 @@ struct mgmt_ev_auth_failed { struct mgmt_ev_local_name_changed { __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; + +#define MGMT_EV_DEVICE_FOUND 0x0012 +struct mgmt_ev_device_found { + bdaddr_t bdaddr; + __u8 dev_class[3]; + __s8 rssi; + __u8 eir[HCI_MAX_EIR_LENGTH]; +} __packed; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 833797e9654b..d04011c06be0 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1228,7 +1228,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff * hci_dev_lock(hdev); - for (; num_rsp; num_rsp--) { + for (; num_rsp; num_rsp--, info++) { bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; data.pscan_period_mode = info->pscan_period_mode; @@ -1237,8 +1237,9 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff * data.clock_offset = info->clock_offset; data.rssi = 0x00; data.ssp_mode = 0x00; - info++; hci_inquiry_cache_update(hdev, &data); + mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0, + NULL); } hci_dev_unlock(hdev); @@ -2158,7 +2159,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct struct inquiry_info_with_rssi_and_pscan_mode *info; info = (void *) (skb->data + 1); - for (; num_rsp; num_rsp--) { + for (; num_rsp; num_rsp--, info++) { bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; data.pscan_period_mode = info->pscan_period_mode; @@ -2167,13 +2168,15 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct data.clock_offset = info->clock_offset; data.rssi = info->rssi; data.ssp_mode = 0x00; - info++; hci_inquiry_cache_update(hdev, &data); + mgmt_device_found(hdev->id, &info->bdaddr, + info->dev_class, info->rssi, + NULL); } } else { struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); - for (; num_rsp; num_rsp--) { + for (; num_rsp; num_rsp--, info++) { bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; data.pscan_period_mode = info->pscan_period_mode; @@ -2182,8 +2185,10 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct data.clock_offset = info->clock_offset; data.rssi = info->rssi; data.ssp_mode = 0x00; - info++; hci_inquiry_cache_update(hdev, &data); + mgmt_device_found(hdev->id, &info->bdaddr, + info->dev_class, info->rssi, + NULL); } } @@ -2314,7 +2319,7 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct hci_dev_lock(hdev); - for (; num_rsp; num_rsp--) { + for (; num_rsp; num_rsp--, info++) { bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; data.pscan_period_mode = info->pscan_period_mode; @@ -2323,8 +2328,9 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct data.clock_offset = info->clock_offset; data.rssi = info->rssi; data.ssp_mode = 0x01; - info++; hci_inquiry_cache_update(hdev, &data); + mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, + info->rssi, info->data); } hci_dev_unlock(hdev); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f87691e04dca..86fb50215485 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2046,3 +2046,20 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, return err; } + +int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, + u8 *eir) +{ + struct mgmt_ev_device_found ev; + + memset(&ev, 0, sizeof(ev)); + + bacpy(&ev.bdaddr, bdaddr); + memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class)); + ev.rssi = rssi; + + if (eir) + memcpy(ev.eir, eir, sizeof(ev.eir)); + + return mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL); +} -- cgit v1.2.3-58-ga151 From a88a9652d25a63ce10b6a5fe680d0ad8f33b9c9b Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 30 Mar 2011 13:18:12 +0300 Subject: Bluetooth: Add mgmt_remote_name event This patch adds a new remote_name event to the Management interface which is sent every time the name of a remote device is resolved (over BR/EDR). Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 1 + include/net/bluetooth/mgmt.h | 6 ++++++ net/bluetooth/hci_event.c | 3 +++ net/bluetooth/mgmt.c | 12 ++++++++++++ 4 files changed, 22 insertions(+) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 2a88fc82429b..4093133c1283 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -789,6 +789,7 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, u8 status); int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, u8 *eir); +int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 864d0cbd2d57..6b6ff92ab499 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -275,3 +275,9 @@ struct mgmt_ev_device_found { __s8 rssi; __u8 eir[HCI_MAX_EIR_LENGTH]; } __packed; + +#define MGMT_EV_REMOTE_NAME 0x0013 +struct mgmt_ev_remote_name { + bdaddr_t bdaddr; + __u8 name[MGMT_MAX_NAME_LENGTH]; +} __packed; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d04011c06be0..7a3398d9cd65 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1497,6 +1497,9 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb hci_dev_lock(hdev); + if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags)) + mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name); + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); if (conn && hci_outgoing_auth_needed(hdev, conn)) { struct hci_cp_auth_requested cp; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 86fb50215485..9a61320c5f2e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2063,3 +2063,15 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, return mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL); } + +int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name) +{ + struct mgmt_ev_remote_name ev; + + memset(&ev, 0, sizeof(ev)); + + bacpy(&ev.bdaddr, bdaddr); + memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); + + return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL); +} -- cgit v1.2.3-58-ga151 From 03e9b64b89243ccc6f8f48f5955a5a78a8ca1431 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 14:03:27 +0000 Subject: bridge: change arguments to fdb_create Later patch provides ability to create non-local static entry. To make this easier move the updating of the flag values to after the code that creates entry. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_fdb.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 88485cc74dc3..70bd0bf04099 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -320,8 +320,7 @@ static inline struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head, static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, struct net_bridge_port *source, - const unsigned char *addr, - int is_local) + const unsigned char *addr) { struct net_bridge_fdb_entry *fdb; @@ -329,10 +328,9 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, if (fdb) { memcpy(fdb->addr.addr, addr, ETH_ALEN); fdb->dst = source; - fdb->is_local = is_local; - fdb->is_static = is_local; + fdb->is_local = 0; + fdb->is_static = 0; fdb->ageing_timer = jiffies; - hlist_add_head_rcu(&fdb->hlist, head); } return fdb; @@ -360,12 +358,15 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, fdb_delete(fdb); } - if (!fdb_create(head, source, addr, 1)) + fdb = fdb_create(head, source, addr); + if (!fdb) return -ENOMEM; + fdb->is_local = fdb->is_static = 1; return 0; } +/* Add entry for local address of interface */ int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr) { @@ -407,8 +408,9 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, } } else { spin_lock(&br->hash_lock); - if (!fdb_find(head, addr)) - fdb_create(head, source, addr, 0); + if (likely(!fdb_find(head, addr))) + fdb_create(head, source, addr); + /* else we lose race and someone else inserts * it first, don't bother updating */ -- cgit v1.2.3-58-ga151 From 7cd8861ab0d907430bbea0af93bc41aee0437efc Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 14:03:28 +0000 Subject: bridge: track last used time in forwarding table Adds tracking the last used time in forwarding table. Rename ageing_timer to updated to better describe it. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_fdb.c | 10 +++++----- net/bridge/br_input.c | 5 +++-- net/bridge/br_private.h | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 70bd0bf04099..b39135285f83 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -62,7 +62,7 @@ static inline int has_expired(const struct net_bridge *br, const struct net_bridge_fdb_entry *fdb) { return !fdb->is_static && - time_before_eq(fdb->ageing_timer + hold_time(br), jiffies); + time_before_eq(fdb->updated + hold_time(br), jiffies); } static inline int br_mac_hash(const unsigned char *mac) @@ -140,7 +140,7 @@ void br_fdb_cleanup(unsigned long _data) unsigned long this_timer; if (f->is_static) continue; - this_timer = f->ageing_timer + delay; + this_timer = f->updated + delay; if (time_before_eq(this_timer, jiffies)) fdb_delete(f); else if (time_before(this_timer, next_timer)) @@ -293,7 +293,7 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, fe->is_local = f->is_local; if (!f->is_static) - fe->ageing_timer_value = jiffies_to_clock_t(jiffies - f->ageing_timer); + fe->ageing_timer_value = jiffies_to_clock_t(jiffies - f->updated); ++fe; ++num; } @@ -330,7 +330,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, fdb->dst = source; fdb->is_local = 0; fdb->is_static = 0; - fdb->ageing_timer = jiffies; + fdb->updated = fdb->used = jiffies; hlist_add_head_rcu(&fdb->hlist, head); } return fdb; @@ -404,7 +404,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, } else { /* fastpath: update of existing entry */ fdb->dst = source; - fdb->ageing_timer = jiffies; + fdb->updated = jiffies; } } else { spin_lock(&br->hash_lock); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index e2160792e1bc..785932d7ad32 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -98,9 +98,10 @@ int br_handle_frame_finish(struct sk_buff *skb) } if (skb) { - if (dst) + if (dst) { + dst->used = jiffies; br_forward(dst->dst, skb, skb2); - else + } else br_flood_forward(br, skb, skb2); } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 387013d33745..a0e6b94c515b 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -64,7 +64,8 @@ struct net_bridge_fdb_entry struct net_bridge_port *dst; struct rcu_head rcu; - unsigned long ageing_timer; + unsigned long updated; + unsigned long used; mac_addr addr; unsigned char is_local; unsigned char is_static; -- cgit v1.2.3-58-ga151 From 664de48bb6c4e167fcdf92a4bddf880030fbfbb3 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 14:03:29 +0000 Subject: bridge: split rcu and no-rcu cases of fdb lookup In some cases, look up of forward database entry is done with RCU; and for others no RCU is needed because of locking. Split the two cases into two differnt loops (and take off inline). Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_fdb.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index b39135285f83..a839a5d9d2c7 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -305,8 +305,21 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, return num; } -static inline struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head, - const unsigned char *addr) +static struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head, + const unsigned char *addr) +{ + struct hlist_node *h; + struct net_bridge_fdb_entry *fdb; + + hlist_for_each_entry(fdb, h, head, hlist) { + if (!compare_ether_addr(fdb->addr.addr, addr)) + return fdb; + } + return NULL; +} + +static struct net_bridge_fdb_entry *fdb_find_rcu(struct hlist_head *head, + const unsigned char *addr) { struct hlist_node *h; struct net_bridge_fdb_entry *fdb; @@ -393,7 +406,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, source->state == BR_STATE_FORWARDING)) return; - fdb = fdb_find(head, addr); + fdb = fdb_find_rcu(head, addr); if (likely(fdb)) { /* attempt to update an entry for a local interface */ if (unlikely(fdb->is_local)) { -- cgit v1.2.3-58-ga151 From b078f0df676233fc7ebc1ab270bd11ef5824bb64 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 14:03:30 +0000 Subject: bridge: add netlink notification on forward entry changes This allows applications to query and monitor bridge forwarding table in the same method used for neighbor table. The forward table entries are returned in same structure format as used by the ioctl. If more information is desired in future, the netlink method is extensible. Example (using bridge extensions to iproute2) # br monitor Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_fdb.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++ net/bridge/br_netlink.c | 1 + net/bridge/br_private.h | 1 + 3 files changed, 127 insertions(+) diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index a839a5d9d2c7..5e19e61396c3 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -28,6 +28,7 @@ static struct kmem_cache *br_fdb_cache __read_mostly; static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr); +static void fdb_notify(const struct net_bridge_fdb_entry *, int); static u32 fdb_salt __read_mostly; @@ -81,6 +82,7 @@ static void fdb_rcu_free(struct rcu_head *head) static inline void fdb_delete(struct net_bridge_fdb_entry *f) { + fdb_notify(f, RTM_DELNEIGH); hlist_del_rcu(&f->hlist); call_rcu(&f->rcu, fdb_rcu_free); } @@ -345,6 +347,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, fdb->is_static = 0; fdb->updated = fdb->used = jiffies; hlist_add_head_rcu(&fdb->hlist, head); + fdb_notify(fdb, RTM_NEWNEIGH); } return fdb; } @@ -430,3 +433,125 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, spin_unlock(&br->hash_lock); } } + +static int fdb_to_nud(const struct net_bridge_fdb_entry *fdb) +{ + if (fdb->is_local) + return NUD_PERMANENT; + else if (fdb->is_static) + return NUD_NOARP; + else if (has_expired(fdb->dst->br, fdb)) + return NUD_STALE; + else + return NUD_REACHABLE; +} + +static int fdb_fill_info(struct sk_buff *skb, + const struct net_bridge_fdb_entry *fdb, + u32 pid, u32 seq, int type, unsigned int flags) +{ + unsigned long now = jiffies; + struct nda_cacheinfo ci; + struct nlmsghdr *nlh; + struct ndmsg *ndm; + + nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags); + if (nlh == NULL) + return -EMSGSIZE; + + + ndm = nlmsg_data(nlh); + ndm->ndm_family = AF_BRIDGE; + ndm->ndm_pad1 = 0; + ndm->ndm_pad2 = 0; + ndm->ndm_flags = 0; + ndm->ndm_type = 0; + ndm->ndm_ifindex = fdb->dst->dev->ifindex; + ndm->ndm_state = fdb_to_nud(fdb); + + NLA_PUT(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr); + + ci.ndm_used = jiffies_to_clock_t(now - fdb->used); + ci.ndm_confirmed = 0; + ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated); + ci.ndm_refcnt = 0; + NLA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci); + + return nlmsg_end(skb, nlh); + +nla_put_failure: + nlmsg_cancel(skb, nlh); + return -EMSGSIZE; +} + +static inline size_t fdb_nlmsg_size(void) +{ + return NLMSG_ALIGN(sizeof(struct ndmsg)) + + nla_total_size(ETH_ALEN) /* NDA_LLADDR */ + + nla_total_size(sizeof(struct nda_cacheinfo)); +} + +static void fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) +{ + struct net *net = dev_net(fdb->dst->dev); + struct sk_buff *skb; + int err = -ENOBUFS; + + skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC); + if (skb == NULL) + goto errout; + + err = fdb_fill_info(skb, fdb, 0, 0, type, 0); + if (err < 0) { + /* -EMSGSIZE implies BUG in fdb_nlmsg_size() */ + WARN_ON(err == -EMSGSIZE); + kfree_skb(skb); + goto errout; + } + rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); + return; +errout: + if (err < 0) + rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); +} + +/* Dump information about entries, in response to GETNEIGH */ +int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct net *net = sock_net(skb->sk); + struct net_device *dev; + int idx = 0; + + rcu_read_lock(); + for_each_netdev_rcu(net, dev) { + struct net_bridge *br = netdev_priv(dev); + int i; + + if (!(dev->priv_flags & IFF_EBRIDGE)) + continue; + + for (i = 0; i < BR_HASH_SIZE; i++) { + struct hlist_node *h; + struct net_bridge_fdb_entry *f; + + hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) { + if (idx < cb->args[0]) + goto skip; + + if (fdb_fill_info(skb, f, + NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, + RTM_NEWNEIGH, + NLM_F_MULTI) < 0) + break; +skip: + ++idx; + } + } + } + rcu_read_unlock(); + + cb->args[0] = idx; + + return skb->len; +} diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index f8bf4c7f842c..cedcafd115f3 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -196,6 +196,7 @@ int __init br_netlink_init(void) /* Only the first call to __rtnl_register can fail */ __rtnl_register(PF_BRIDGE, RTM_SETLINK, br_rtm_setlink, NULL); + __rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, br_fdb_dump); return 0; } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index a0e6b94c515b..884d245a205a 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -354,6 +354,7 @@ extern int br_fdb_insert(struct net_bridge *br, extern void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr); +extern int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb); /* br_forward.c */ extern void br_deliver(const struct net_bridge_port *to, -- cgit v1.2.3-58-ga151 From 36fd2b63e3b4336744cf3f6a6c9543ecbec334a7 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 14:03:31 +0000 Subject: bridge: allow creating/deleting fdb entries via netlink Use RTM_NEWNEIGH and RTM_DELNEIGH to allow updating of entries in bridge forwarding table. This allows manipulating static entries which is not possible with existing tools. Example (using bridge extensions to iproute2) # br fdb add 00:02:03:04:05:06 dev eth0 Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_fdb.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++ net/bridge/br_netlink.c | 3 ++ net/bridge/br_private.h | 2 + 3 files changed, 144 insertions(+) diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 5e19e61396c3..498f47c1c453 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -555,3 +555,142 @@ skip: return skb->len; } + +/* Create new static fdb entry */ +static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, + __u16 state) +{ + struct net_bridge *br = source->br; + struct hlist_head *head = &br->hash[br_mac_hash(addr)]; + struct net_bridge_fdb_entry *fdb; + + fdb = fdb_find(head, addr); + if (fdb) + return -EEXIST; + + fdb = fdb_create(head, source, addr); + if (!fdb) + return -ENOMEM; + + if (state & NUD_PERMANENT) + fdb->is_local = fdb->is_static = 1; + else if (state & NUD_NOARP) + fdb->is_static = 1; + return 0; +} + +/* Add new permanent fdb entry with RTM_NEWNEIGH */ +int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) +{ + struct net *net = sock_net(skb->sk); + struct ndmsg *ndm; + struct nlattr *tb[NDA_MAX+1]; + struct net_device *dev; + struct net_bridge_port *p; + const __u8 *addr; + int err; + + ASSERT_RTNL(); + err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); + if (err < 0) + return err; + + ndm = nlmsg_data(nlh); + if (ndm->ndm_ifindex == 0) { + pr_info("bridge: RTM_NEWNEIGH with invalid ifindex\n"); + return -EINVAL; + } + + dev = __dev_get_by_index(net, ndm->ndm_ifindex); + if (dev == NULL) { + pr_info("bridge: RTM_NEWNEIGH with unknown ifindex\n"); + return -ENODEV; + } + + if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) { + pr_info("bridge: RTM_NEWNEIGH with invalid address\n"); + return -EINVAL; + } + + addr = nla_data(tb[NDA_LLADDR]); + if (!is_valid_ether_addr(addr)) { + pr_info("bridge: RTM_NEWNEIGH with invalid ether address\n"); + return -EINVAL; + } + + p = br_port_get_rtnl(dev); + if (p == NULL) { + pr_info("bridge: RTM_NEWNEIGH %s not a bridge port\n", + dev->name); + return -EINVAL; + } + + spin_lock_bh(&p->br->hash_lock); + err = fdb_add_entry(p, addr, ndm->ndm_state); + spin_unlock_bh(&p->br->hash_lock); + + return err; +} + +static int fdb_delete_by_addr(struct net_bridge_port *p, const u8 *addr) +{ + struct net_bridge *br = p->br; + struct hlist_head *head = &br->hash[br_mac_hash(addr)]; + struct net_bridge_fdb_entry *fdb; + + fdb = fdb_find(head, addr); + if (!fdb) + return -ENOENT; + + fdb_delete(fdb); + return 0; +} + +/* Remove neighbor entry with RTM_DELNEIGH */ +int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) +{ + struct net *net = sock_net(skb->sk); + struct ndmsg *ndm; + struct net_bridge_port *p; + struct nlattr *llattr; + const __u8 *addr; + struct net_device *dev; + int err; + + ASSERT_RTNL(); + if (nlmsg_len(nlh) < sizeof(*ndm)) + return -EINVAL; + + ndm = nlmsg_data(nlh); + if (ndm->ndm_ifindex == 0) { + pr_info("bridge: RTM_DELNEIGH with invalid ifindex\n"); + return -EINVAL; + } + + dev = __dev_get_by_index(net, ndm->ndm_ifindex); + if (dev == NULL) { + pr_info("bridge: RTM_DELNEIGH with unknown ifindex\n"); + return -ENODEV; + } + + llattr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_LLADDR); + if (llattr == NULL || nla_len(llattr) != ETH_ALEN) { + pr_info("bridge: RTM_DELNEIGH with invalid address\n"); + return -EINVAL; + } + + addr = nla_data(llattr); + + p = br_port_get_rtnl(dev); + if (p == NULL) { + pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n", + dev->name); + return -EINVAL; + } + + spin_lock_bh(&p->br->hash_lock); + err = fdb_delete_by_addr(p, addr); + spin_unlock_bh(&p->br->hash_lock); + + return err; +} diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index cedcafd115f3..fb7d5a7478fe 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -196,6 +196,9 @@ int __init br_netlink_init(void) /* Only the first call to __rtnl_register can fail */ __rtnl_register(PF_BRIDGE, RTM_SETLINK, br_rtm_setlink, NULL); + + __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, br_fdb_add, NULL); + __rtnl_register(PF_BRIDGE, RTM_DELNEIGH, br_fdb_delete, NULL); __rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, br_fdb_dump); return 0; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 884d245a205a..4bbe0d14c9a2 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -355,6 +355,8 @@ extern void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr); extern int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb); +extern int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg); +extern int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg); /* br_forward.c */ extern void br_deliver(const struct net_bridge_port *to, -- cgit v1.2.3-58-ga151 From bb900b27a2f49b37bc38c08e656ea13048fee13b Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 14:03:32 +0000 Subject: bridge: allow creating bridge devices with netlink Add netlink device ops to allow creating bridge device via netlink. This works in a manner similar to vlan, macvlan and bonding. Example: # ip link add link dev br0 type bridge # ip link del dev br0 The change required rearranging initializtion code to deal with being called by create link. Most of the initialization happens in br_dev_setup, but allocation of stats is done in ndo_init callback to deal with allocation failure. Sysfs setup has to wait until after the network device kobject is registered. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br.c | 1 + net/bridge/br_device.c | 41 ++++++++++++++++++++++++ net/bridge/br_if.c | 83 +++---------------------------------------------- net/bridge/br_netlink.c | 57 +++++++++++++++++++++++++++------ net/bridge/br_notify.c | 6 ++++ 5 files changed, 101 insertions(+), 87 deletions(-) diff --git a/net/bridge/br.c b/net/bridge/br.c index 84bbb82599b2..f20c4fd915a8 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -104,3 +104,4 @@ module_init(br_init) module_exit(br_deinit) MODULE_LICENSE("GPL"); MODULE_VERSION(BR_VERSION); +MODULE_ALIAS_RTNL_LINK("bridge"); diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 21e5901186ea..45cfd54b06d3 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -74,6 +74,17 @@ out: return NETDEV_TX_OK; } +static int br_dev_init(struct net_device *dev) +{ + struct net_bridge *br = netdev_priv(dev); + + br->stats = alloc_percpu(struct br_cpu_netstats); + if (!br->stats) + return -ENOMEM; + + return 0; +} + static int br_dev_open(struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); @@ -334,6 +345,7 @@ static const struct ethtool_ops br_ethtool_ops = { static const struct net_device_ops br_netdev_ops = { .ndo_open = br_dev_open, .ndo_stop = br_dev_stop, + .ndo_init = br_dev_init, .ndo_start_xmit = br_dev_xmit, .ndo_get_stats64 = br_get_stats64, .ndo_set_mac_address = br_set_mac_address, @@ -357,18 +369,47 @@ static void br_dev_free(struct net_device *dev) free_netdev(dev); } +static struct device_type br_type = { + .name = "bridge", +}; + void br_dev_setup(struct net_device *dev) { + struct net_bridge *br = netdev_priv(dev); + random_ether_addr(dev->dev_addr); ether_setup(dev); dev->netdev_ops = &br_netdev_ops; dev->destructor = br_dev_free; SET_ETHTOOL_OPS(dev, &br_ethtool_ops); + SET_NETDEV_DEVTYPE(dev, &br_type); dev->tx_queue_len = 0; dev->priv_flags = IFF_EBRIDGE; dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX | NETIF_F_NETNS_LOCAL | NETIF_F_GSO | NETIF_F_HW_VLAN_TX; + + br->dev = dev; + spin_lock_init(&br->lock); + INIT_LIST_HEAD(&br->port_list); + spin_lock_init(&br->hash_lock); + + br->bridge_id.prio[0] = 0x80; + br->bridge_id.prio[1] = 0x00; + + memcpy(br->group_addr, br_group_address, ETH_ALEN); + + br->feature_mask = dev->features; + br->stp_enabled = BR_NO_STP; + br->designated_root = br->bridge_id; + br->bridge_max_age = br->max_age = 20 * HZ; + br->bridge_hello_time = br->hello_time = 2 * HZ; + br->bridge_forward_delay = br->forward_delay = 15 * HZ; + br->ageing_time = 300 * HZ; + + br_netfilter_rtable_init(br); + br_stp_timer_init(br); + br_multicast_init(br); } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 718b60366dfe..7f5379c593d9 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -175,56 +175,6 @@ static void del_br(struct net_bridge *br, struct list_head *head) unregister_netdevice_queue(br->dev, head); } -static struct net_device *new_bridge_dev(struct net *net, const char *name) -{ - struct net_bridge *br; - struct net_device *dev; - - dev = alloc_netdev(sizeof(struct net_bridge), name, - br_dev_setup); - - if (!dev) - return NULL; - dev_net_set(dev, net); - - br = netdev_priv(dev); - br->dev = dev; - - br->stats = alloc_percpu(struct br_cpu_netstats); - if (!br->stats) { - free_netdev(dev); - return NULL; - } - - spin_lock_init(&br->lock); - INIT_LIST_HEAD(&br->port_list); - spin_lock_init(&br->hash_lock); - - br->bridge_id.prio[0] = 0x80; - br->bridge_id.prio[1] = 0x00; - - memcpy(br->group_addr, br_group_address, ETH_ALEN); - - br->feature_mask = dev->features; - br->stp_enabled = BR_NO_STP; - br->designated_root = br->bridge_id; - br->root_path_cost = 0; - br->root_port = 0; - br->bridge_max_age = br->max_age = 20 * HZ; - br->bridge_hello_time = br->hello_time = 2 * HZ; - br->bridge_forward_delay = br->forward_delay = 15 * HZ; - br->topology_change = 0; - br->topology_change_detected = 0; - br->ageing_time = 300 * HZ; - - br_netfilter_rtable_init(br); - - br_stp_timer_init(br); - br_multicast_init(br); - - return dev; -} - /* find an available port number */ static int find_portno(struct net_bridge *br) { @@ -277,42 +227,19 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, return p; } -static struct device_type br_type = { - .name = "bridge", -}; - int br_add_bridge(struct net *net, const char *name) { struct net_device *dev; - int ret; - dev = new_bridge_dev(net, name); + dev = alloc_netdev(sizeof(struct net_bridge), name, + br_dev_setup); + if (!dev) return -ENOMEM; - rtnl_lock(); - if (strchr(dev->name, '%')) { - ret = dev_alloc_name(dev, dev->name); - if (ret < 0) - goto out_free; - } - - SET_NETDEV_DEVTYPE(dev, &br_type); - - ret = register_netdevice(dev); - if (ret) - goto out_free; - - ret = br_sysfs_addbr(dev); - if (ret) - unregister_netdevice(dev); - out: - rtnl_unlock(); - return ret; + dev_net_set(dev, net); -out_free: - free_netdev(dev); - goto out; + return register_netdev(dev); } int br_del_bridge(struct net *net, const char *name) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index fb7d5a7478fe..134a2ff6b98b 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -12,9 +12,11 @@ #include #include +#include #include #include #include + #include "br_private.h" static inline size_t br_nlmsg_size(void) @@ -188,24 +190,61 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) return 0; } +static int br_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + if (tb[IFLA_ADDRESS]) { + if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) + return -EINVAL; + if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) + return -EADDRNOTAVAIL; + } + + return 0; +} + +static struct rtnl_link_ops br_link_ops __read_mostly = { + .kind = "bridge", + .priv_size = sizeof(struct net_bridge), + .setup = br_dev_setup, + .validate = br_validate, +}; int __init br_netlink_init(void) { - if (__rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, br_dump_ifinfo)) - return -ENOBUFS; - - /* Only the first call to __rtnl_register can fail */ - __rtnl_register(PF_BRIDGE, RTM_SETLINK, br_rtm_setlink, NULL); + int err; - __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, br_fdb_add, NULL); - __rtnl_register(PF_BRIDGE, RTM_DELNEIGH, br_fdb_delete, NULL); - __rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, br_fdb_dump); + err = rtnl_link_register(&br_link_ops); + if (err < 0) + goto err1; + + err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, br_dump_ifinfo); + if (err) + goto err2; + err = __rtnl_register(PF_BRIDGE, RTM_SETLINK, br_rtm_setlink, NULL); + if (err) + goto err3; + err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, br_fdb_add, NULL); + if (err) + goto err3; + err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH, br_fdb_delete, NULL); + if (err) + goto err3; + err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, br_fdb_dump); + if (err) + goto err3; return 0; + +err3: + rtnl_unregister_all(PF_BRIDGE); +err2: + rtnl_link_unregister(&br_link_ops); +err1: + return err; } void __exit br_netlink_fini(void) { + rtnl_link_unregister(&br_link_ops); rtnl_unregister_all(PF_BRIDGE); } - diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 7d337c9b6082..7a03bb975375 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c @@ -36,6 +36,12 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v struct net_bridge *br; int err; + /* register of bridge completed, add sysfs entries */ + if ((dev->priv_flags && IFF_EBRIDGE) && event == NETDEV_REGISTER) { + br_sysfs_addbr(dev); + return NOTIFY_DONE; + } + /* not a port of a bridge */ p = br_port_get_rtnl(dev); if (!p) -- cgit v1.2.3-58-ga151 From 14f98f258f1936e0dba77474bd7eda63f61a9826 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 14:03:33 +0000 Subject: bridge: range check STP parameters Apply restrictions on STP parameters based 802.1D 1998 standard. * Fixes missing locking in set path cost ioctl * Uses common code for both ioctl and sysfs This is based on an earlier patch Sasikanth V but with overhaul. Note: 1. It does NOT enforce the restriction on the relationship max_age and forward delay or hello time because in existing implementation these are set as independant operations. 2. If STP is disabled, there is no restriction on forward delay 3. No restriction on holding time because users use Linux code to act as hub or be sticky. 4. Although standard allow 0-255, Linux only allows 0-63 for port priority because more bits are reserved for port number. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_ioctl.c | 40 +++++++++---------------------------- net/bridge/br_private.h | 13 ++++++++---- net/bridge/br_private_stp.h | 13 ++++++++++++ net/bridge/br_stp.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ net/bridge/br_stp_if.c | 21 ++++++++++++++++---- net/bridge/br_sysfs_br.c | 39 +++--------------------------------- net/bridge/br_sysfs_if.c | 26 ++++++++---------------- 7 files changed, 107 insertions(+), 93 deletions(-) diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index cb43312b846e..0459890dba41 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c @@ -181,40 +181,19 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (!capable(CAP_NET_ADMIN)) return -EPERM; - spin_lock_bh(&br->lock); - br->bridge_forward_delay = clock_t_to_jiffies(args[1]); - if (br_is_root_bridge(br)) - br->forward_delay = br->bridge_forward_delay; - spin_unlock_bh(&br->lock); - return 0; + return br_set_forward_delay(br, args[1]); case BRCTL_SET_BRIDGE_HELLO_TIME: - { - unsigned long t = clock_t_to_jiffies(args[1]); if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (t < HZ) - return -EINVAL; - - spin_lock_bh(&br->lock); - br->bridge_hello_time = t; - if (br_is_root_bridge(br)) - br->hello_time = br->bridge_hello_time; - spin_unlock_bh(&br->lock); - return 0; - } + return br_set_hello_time(br, args[1]); case BRCTL_SET_BRIDGE_MAX_AGE: if (!capable(CAP_NET_ADMIN)) return -EPERM; - spin_lock_bh(&br->lock); - br->bridge_max_age = clock_t_to_jiffies(args[1]); - if (br_is_root_bridge(br)) - br->max_age = br->bridge_max_age; - spin_unlock_bh(&br->lock); - return 0; + return br_set_max_age(br, args[1]); case BRCTL_SET_AGEING_TIME: if (!capable(CAP_NET_ADMIN)) @@ -275,19 +254,16 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) case BRCTL_SET_PORT_PRIORITY: { struct net_bridge_port *p; - int ret = 0; + int ret; if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (args[2] >= (1<<(16-BR_PORT_BITS))) - return -ERANGE; - spin_lock_bh(&br->lock); if ((p = br_get_port(br, args[1])) == NULL) ret = -EINVAL; else - br_stp_set_port_priority(p, args[2]); + ret = br_stp_set_port_priority(p, args[2]); spin_unlock_bh(&br->lock); return ret; } @@ -295,15 +271,17 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) case BRCTL_SET_PATH_COST: { struct net_bridge_port *p; - int ret = 0; + int ret; if (!capable(CAP_NET_ADMIN)) return -EPERM; + spin_lock_bh(&br->lock); if ((p = br_get_port(br, args[1])) == NULL) ret = -EINVAL; else - br_stp_set_path_cost(p, args[2]); + ret = br_stp_set_path_cost(p, args[2]); + spin_unlock_bh(&br->lock); return ret; } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 4bbe0d14c9a2..e2a40343aa09 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -495,6 +495,11 @@ extern struct net_bridge_port *br_get_port(struct net_bridge *br, extern void br_init_port(struct net_bridge_port *p); extern void br_become_designated_port(struct net_bridge_port *p); +extern int br_set_forward_delay(struct net_bridge *br, unsigned long x); +extern int br_set_hello_time(struct net_bridge *br, unsigned long x); +extern int br_set_max_age(struct net_bridge *br, unsigned long x); + + /* br_stp_if.c */ extern void br_stp_enable_bridge(struct net_bridge *br); extern void br_stp_disable_bridge(struct net_bridge *br); @@ -505,10 +510,10 @@ extern bool br_stp_recalculate_bridge_id(struct net_bridge *br); extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); extern void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio); -extern void br_stp_set_port_priority(struct net_bridge_port *p, - u8 newprio); -extern void br_stp_set_path_cost(struct net_bridge_port *p, - u32 path_cost); +extern int br_stp_set_port_priority(struct net_bridge_port *p, + unsigned long newprio); +extern int br_stp_set_path_cost(struct net_bridge_port *p, + unsigned long path_cost); extern ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id); /* br_stp_bpdu.c */ diff --git a/net/bridge/br_private_stp.h b/net/bridge/br_private_stp.h index 8b650f7fbfa0..642ef47a867e 100644 --- a/net/bridge/br_private_stp.h +++ b/net/bridge/br_private_stp.h @@ -16,6 +16,19 @@ #define BPDU_TYPE_CONFIG 0 #define BPDU_TYPE_TCN 0x80 +/* IEEE 802.1D-1998 timer values */ +#define BR_MIN_HELLO_TIME (1*HZ) +#define BR_MAX_HELLO_TIME (10*HZ) + +#define BR_MIN_FORWARD_DELAY (2*HZ) +#define BR_MAX_FORWARD_DELAY (30*HZ) + +#define BR_MIN_MAX_AGE (6*HZ) +#define BR_MAX_MAX_AGE (40*HZ) + +#define BR_MIN_PATH_COST 1 +#define BR_MAX_PATH_COST 65535 + struct br_config_bpdu { unsigned topology_change:1; diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index 7370d14f634d..bb4383e84de9 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -484,3 +484,51 @@ void br_received_tcn_bpdu(struct net_bridge_port *p) br_topology_change_acknowledge(p); } } + +/* Change bridge STP parameter */ +int br_set_hello_time(struct net_bridge *br, unsigned long val) +{ + unsigned long t = clock_t_to_jiffies(val); + + if (t < BR_MIN_HELLO_TIME || t > BR_MAX_HELLO_TIME) + return -ERANGE; + + spin_lock_bh(&br->lock); + br->bridge_hello_time = t; + if (br_is_root_bridge(br)) + br->hello_time = br->bridge_hello_time; + spin_unlock_bh(&br->lock); + return 0; +} + +int br_set_max_age(struct net_bridge *br, unsigned long val) +{ + unsigned long t = clock_t_to_jiffies(val); + + if (t < BR_MIN_MAX_AGE || t > BR_MAX_MAX_AGE) + return -ERANGE; + + spin_lock_bh(&br->lock); + br->bridge_max_age = t; + if (br_is_root_bridge(br)) + br->max_age = br->bridge_max_age; + spin_unlock_bh(&br->lock); + return 0; + +} + +int br_set_forward_delay(struct net_bridge *br, unsigned long val) +{ + unsigned long t = clock_t_to_jiffies(val); + + if (br->stp_enabled != BR_NO_STP && + (t < BR_MIN_FORWARD_DELAY || t > BR_MAX_FORWARD_DELAY)) + return -ERANGE; + + spin_lock_bh(&br->lock); + br->bridge_forward_delay = t; + if (br_is_root_bridge(br)) + br->forward_delay = br->bridge_forward_delay; + spin_unlock_bh(&br->lock); + return 0; +} diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 9b61d09de9b9..6f615b8192f4 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -20,7 +20,7 @@ /* Port id is composed of priority and port number. - * NB: least significant bits of priority are dropped to + * NB: some bits of priority are dropped to * make room for more ports. */ static inline port_id br_make_port_id(__u8 priority, __u16 port_no) @@ -29,6 +29,8 @@ static inline port_id br_make_port_id(__u8 priority, __u16 port_no) | (port_no & ((1<> BR_PORT_BITS) + /* called under bridge lock */ void br_init_port(struct net_bridge_port *p) { @@ -255,10 +257,14 @@ void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio) } /* called under bridge lock */ -void br_stp_set_port_priority(struct net_bridge_port *p, u8 newprio) +int br_stp_set_port_priority(struct net_bridge_port *p, unsigned long newprio) { - port_id new_port_id = br_make_port_id(newprio, p->port_no); + port_id new_port_id; + + if (newprio > BR_MAX_PORT_PRIORITY) + return -ERANGE; + new_port_id = br_make_port_id(newprio, p->port_no); if (br_is_designated_port(p)) p->designated_port = new_port_id; @@ -269,14 +275,21 @@ void br_stp_set_port_priority(struct net_bridge_port *p, u8 newprio) br_become_designated_port(p); br_port_state_selection(p->br); } + + return 0; } /* called under bridge lock */ -void br_stp_set_path_cost(struct net_bridge_port *p, u32 path_cost) +int br_stp_set_path_cost(struct net_bridge_port *p, unsigned long path_cost) { + if (path_cost < BR_MIN_PATH_COST || + path_cost > BR_MAX_PATH_COST) + return -ERANGE; + p->path_cost = path_cost; br_configuration_update(p->br); br_port_state_selection(p->br); + return 0; } ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id) diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 5c1e5559ebba..68b893ea8c3a 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -43,9 +43,7 @@ static ssize_t store_bridge_parm(struct device *d, if (endp == buf) return -EINVAL; - spin_lock_bh(&br->lock); err = (*set)(br, val); - spin_unlock_bh(&br->lock); return err ? err : len; } @@ -57,20 +55,11 @@ static ssize_t show_forward_delay(struct device *d, return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay)); } -static int set_forward_delay(struct net_bridge *br, unsigned long val) -{ - unsigned long delay = clock_t_to_jiffies(val); - br->forward_delay = delay; - if (br_is_root_bridge(br)) - br->bridge_forward_delay = delay; - return 0; -} - static ssize_t store_forward_delay(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, set_forward_delay); + return store_bridge_parm(d, buf, len, br_set_forward_delay); } static DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR, show_forward_delay, store_forward_delay); @@ -82,24 +71,11 @@ static ssize_t show_hello_time(struct device *d, struct device_attribute *attr, jiffies_to_clock_t(to_bridge(d)->hello_time)); } -static int set_hello_time(struct net_bridge *br, unsigned long val) -{ - unsigned long t = clock_t_to_jiffies(val); - - if (t < HZ) - return -EINVAL; - - br->hello_time = t; - if (br_is_root_bridge(br)) - br->bridge_hello_time = t; - return 0; -} - static ssize_t store_hello_time(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, set_hello_time); + return store_bridge_parm(d, buf, len, br_set_hello_time); } static DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time, store_hello_time); @@ -111,19 +87,10 @@ static ssize_t show_max_age(struct device *d, struct device_attribute *attr, jiffies_to_clock_t(to_bridge(d)->max_age)); } -static int set_max_age(struct net_bridge *br, unsigned long val) -{ - unsigned long t = clock_t_to_jiffies(val); - br->max_age = t; - if (br_is_root_bridge(br)) - br->bridge_max_age = t; - return 0; -} - static ssize_t store_max_age(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, set_max_age); + return store_bridge_parm(d, buf, len, br_set_max_age); } static DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, store_max_age); diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index fd5799c9bc8d..6229b62749e8 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -23,7 +23,7 @@ struct brport_attribute { struct attribute attr; ssize_t (*show)(struct net_bridge_port *, char *); - ssize_t (*store)(struct net_bridge_port *, unsigned long); + int (*store)(struct net_bridge_port *, unsigned long); }; #define BRPORT_ATTR(_name,_mode,_show,_store) \ @@ -38,27 +38,17 @@ static ssize_t show_path_cost(struct net_bridge_port *p, char *buf) { return sprintf(buf, "%d\n", p->path_cost); } -static ssize_t store_path_cost(struct net_bridge_port *p, unsigned long v) -{ - br_stp_set_path_cost(p, v); - return 0; -} + static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR, - show_path_cost, store_path_cost); + show_path_cost, br_stp_set_path_cost); static ssize_t show_priority(struct net_bridge_port *p, char *buf) { return sprintf(buf, "%d\n", p->priority); } -static ssize_t store_priority(struct net_bridge_port *p, unsigned long v) -{ - if (v >= (1<<(16-BR_PORT_BITS))) - return -ERANGE; - br_stp_set_port_priority(p, v); - return 0; -} + static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR, - show_priority, store_priority); + show_priority, br_stp_set_port_priority); static ssize_t show_designated_root(struct net_bridge_port *p, char *buf) { @@ -136,7 +126,7 @@ static ssize_t show_hold_timer(struct net_bridge_port *p, } static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL); -static ssize_t store_flush(struct net_bridge_port *p, unsigned long v) +static int store_flush(struct net_bridge_port *p, unsigned long v) { br_fdb_delete_by_port(p->br, p, 0); // Don't delete local entry return 0; @@ -148,7 +138,7 @@ static ssize_t show_hairpin_mode(struct net_bridge_port *p, char *buf) int hairpin_mode = (p->flags & BR_HAIRPIN_MODE) ? 1 : 0; return sprintf(buf, "%d\n", hairpin_mode); } -static ssize_t store_hairpin_mode(struct net_bridge_port *p, unsigned long v) +static int store_hairpin_mode(struct net_bridge_port *p, unsigned long v) { if (v) p->flags |= BR_HAIRPIN_MODE; @@ -165,7 +155,7 @@ static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) return sprintf(buf, "%d\n", p->multicast_router); } -static ssize_t store_multicast_router(struct net_bridge_port *p, +static int store_multicast_router(struct net_bridge_port *p, unsigned long v) { return br_multicast_set_port_router(p, v); -- cgit v1.2.3-58-ga151 From e3f6a652fd0e828de586a3a87b56c07f7a32259a Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 5 Apr 2011 11:25:03 +0900 Subject: IPVS: combine consecutive #ifdef CONFIG_PROC_FS blocks Signed-off-by: Simon Horman --- net/netfilter/ipvs/ip_vs_ctl.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 33733c8872e7..36f4495cfdbf 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1984,9 +1984,6 @@ static const struct file_operations ip_vs_info_fops = { .release = seq_release_private, }; -#endif - -#ifdef CONFIG_PROC_FS static int ip_vs_stats_show(struct seq_file *seq, void *v) { struct net *net = seq_file_single_net(seq); -- cgit v1.2.3-58-ga151 From c6e1a0d12ca7b4f22c58e55a16beacfb7d3d8462 Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Mon, 4 Apr 2011 22:30:30 -0700 Subject: net: Allow no-cache copy from user on transmit This patch uses __copy_from_user_nocache on transmit to bypass data cache for a performance improvement. skb_add_data_nocache and skb_copy_to_page_nocache can be called by sendmsg functions to use this feature, initial support is in tcp_sendmsg. This functionality is configurable per device using ethtool. Presumably, this feature would only be useful when the driver does not touch the data. The feature is turned on by default if a device indicates that it does some form of checksum offload; it is off by default for devices that do no checksum offload or indicate no checksum is necessary. For the former case copy-checksum is probably done anyway, in the latter case the device is likely loopback in which case the no cache copy is probably not beneficial. This patch was tested using 200 instances of netperf TCP_RR with 1400 byte request and one byte reply. Platform is 16 core AMD x86. No-cache copy disabled: 672703 tps, 97.13% utilization 50/90/99% latency:244.31 484.205 1028.41 No-cache copy enabled: 702113 tps, 96.16% utilization, 50/90/99% latency 238.56 467.56 956.955 Using 14000 byte request and response sizes demonstrate the effects more dramatically: No-cache copy disabled: 79571 tps, 34.34 %utlization 50/90/95% latency 1584.46 2319.59 5001.76 No-cache copy enabled: 83856 tps, 34.81% utilization 50/90/95% latency 2508.42 2622.62 2735.88 Note especially the effect on latency tail (95th percentile). This seems to provide a nice performance improvement and is consistent in the tests I ran. Presumably, this would provide the greatest benfits in the presence of an application workload stressing the cache and a lot of transmit data happening. Signed-off-by: Tom Herbert Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 2 +- include/linux/netdevice.h | 3 ++- include/net/sock.h | 53 +++++++++++++++++++++++++++++++++++++++++ net/core/dev.c | 12 ++++++++++ net/core/ethtool.c | 2 +- net/ipv4/tcp.c | 7 +++--- 6 files changed, 73 insertions(+), 6 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 16d6fe954695..b51e021354b5 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1407,7 +1407,7 @@ static int bond_compute_features(struct bonding *bond) int i; features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES); - features |= NETIF_F_GSO_MASK | NETIF_F_NO_CSUM; + features |= NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_NOCACHE_COPY; if (!bond->first_slave) goto done; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a4664cc68e2b..09d262415769 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1066,6 +1066,7 @@ struct net_device { #define NETIF_F_NTUPLE (1 << 27) /* N-tuple filters supported */ #define NETIF_F_RXHASH (1 << 28) /* Receive hashing offload */ #define NETIF_F_RXCSUM (1 << 29) /* Receive checksumming offload */ +#define NETIF_F_NOCACHE_COPY (1 << 30) /* Use no-cache copyfromuser */ /* Segmentation offload features */ #define NETIF_F_GSO_SHIFT 16 @@ -1081,7 +1082,7 @@ struct net_device { /* = all defined minus driver/device-class-related */ #define NETIF_F_NEVER_CHANGE (NETIF_F_HIGHDMA | NETIF_F_VLAN_CHALLENGED | \ NETIF_F_LLTX | NETIF_F_NETNS_LOCAL) -#define NETIF_F_ETHTOOL_BITS (0x3f3fffff & ~NETIF_F_NEVER_CHANGE) +#define NETIF_F_ETHTOOL_BITS (0x7f3fffff & ~NETIF_F_NEVER_CHANGE) /* List of features with software fallbacks. */ #define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | \ diff --git a/include/net/sock.h b/include/net/sock.h index da0534d3401c..43bd515e92fd 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -1389,6 +1390,58 @@ static inline void sk_nocaps_add(struct sock *sk, int flags) sk->sk_route_caps &= ~flags; } +static inline int skb_do_copy_data_nocache(struct sock *sk, struct sk_buff *skb, + char __user *from, char *to, + int copy) +{ + if (skb->ip_summed == CHECKSUM_NONE) { + int err = 0; + __wsum csum = csum_and_copy_from_user(from, to, copy, 0, &err); + if (err) + return err; + skb->csum = csum_block_add(skb->csum, csum, skb->len); + } else if (sk->sk_route_caps & NETIF_F_NOCACHE_COPY) { + if (!access_ok(VERIFY_READ, from, copy) || + __copy_from_user_nocache(to, from, copy)) + return -EFAULT; + } else if (copy_from_user(to, from, copy)) + return -EFAULT; + + return 0; +} + +static inline int skb_add_data_nocache(struct sock *sk, struct sk_buff *skb, + char __user *from, int copy) +{ + int err; + + err = skb_do_copy_data_nocache(sk, skb, from, skb_put(skb, copy), copy); + if (err) + __skb_trim(skb, skb->len); + + return err; +} + +static inline int skb_copy_to_page_nocache(struct sock *sk, char __user *from, + struct sk_buff *skb, + struct page *page, + int off, int copy) +{ + int err; + + err = skb_do_copy_data_nocache(sk, skb, from, + page_address(page) + off, copy); + if (err) + return err; + + skb->len += copy; + skb->data_len += copy; + skb->truesize += copy; + sk->sk_wmem_queued += copy; + sk_mem_charge(sk, copy); + return 0; +} + static inline int skb_copy_to_page(struct sock *sk, char __user *from, struct sk_buff *skb, struct page *page, int off, int copy) diff --git a/net/core/dev.c b/net/core/dev.c index 02f56376fe99..5d0b4f6f1a72 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5425,6 +5425,14 @@ int register_netdevice(struct net_device *dev) dev->features &= ~NETIF_F_GSO; } + /* Turn on no cache copy if HW is doing checksum */ + dev->hw_features |= NETIF_F_NOCACHE_COPY; + if ((dev->features & NETIF_F_ALL_CSUM) && + !(dev->features & NETIF_F_NO_CSUM)) { + dev->wanted_features |= NETIF_F_NOCACHE_COPY; + dev->features |= NETIF_F_NOCACHE_COPY; + } + /* Enable GRO and NETIF_F_HIGHDMA for vlans by default, * vlan_dev_init() will do the dev->features check, so these features * are enabled only if supported by underlying device. @@ -6182,6 +6190,10 @@ u32 netdev_increment_features(u32 all, u32 one, u32 mask) } } + /* If device can't no cache copy, don't do for all */ + if (!(one & NETIF_F_NOCACHE_COPY)) + all &= ~NETIF_F_NOCACHE_COPY; + one |= NETIF_F_ALL_CSUM; one |= all & NETIF_F_ONE_FOR_ALL; diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 439e4b0e1312..719670ae199c 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -359,7 +359,7 @@ static const char netdev_features_strings[ETHTOOL_DEV_FEATURE_WORDS * 32][ETH_GS /* NETIF_F_NTUPLE */ "rx-ntuple-filter", /* NETIF_F_RXHASH */ "rx-hashing", /* NETIF_F_RXCSUM */ "rx-checksum", - "", + /* NETIF_F_NOCACHE_COPY */ "tx-nocache-copy" "", }; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index b22d45010545..054a59d21eb0 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -999,7 +999,8 @@ new_segment: /* We have some space in skb head. Superb! */ if (copy > skb_tailroom(skb)) copy = skb_tailroom(skb); - if ((err = skb_add_data(skb, from, copy)) != 0) + err = skb_add_data_nocache(sk, skb, from, copy); + if (err) goto do_fault; } else { int merge = 0; @@ -1042,8 +1043,8 @@ new_segment: /* Time to copy data. We are close to * the end! */ - err = skb_copy_to_page(sk, from, skb, page, - off, copy); + err = skb_copy_to_page_nocache(sk, from, skb, + page, off, copy); if (err) { /* If this page was new, give it to the * socket so it does not get leaked. -- cgit v1.2.3-58-ga151 From f82d9a67fbcdfd8af6be7a7c9e381864ec9a271a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 5 Apr 2011 13:36:09 +0100 Subject: sfc: Enable all TSO features on VLANs The TSO code already supports IPv6 on VLAN, so enable it. Signed-off-by: Ben Hutchings --- drivers/net/sfc/efx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index d890679e4c4d..542f32d21acf 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -2457,7 +2457,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, net_dev->features |= NETIF_F_TSO6; /* Mask for features that also apply to VLAN devices */ net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG | - NETIF_F_HIGHDMA | NETIF_F_TSO); + NETIF_F_HIGHDMA | NETIF_F_ALL_TSO); efx = netdev_priv(net_dev); pci_set_drvdata(pci_dev, efx); SET_NETDEV_DEV(net_dev, &pci_dev->dev); -- cgit v1.2.3-58-ga151 From abfe903980161b11f3594e3dcbab8b5c5a67168b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 5 Apr 2011 15:00:02 +0100 Subject: sfc: Implement generic features interface Signed-off-by: Ben Hutchings --- drivers/net/sfc/efx.c | 20 ++++++++++-- drivers/net/sfc/ethtool.c | 78 -------------------------------------------- drivers/net/sfc/net_driver.h | 2 -- drivers/net/sfc/rx.c | 2 +- 4 files changed, 18 insertions(+), 84 deletions(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 542f32d21acf..db72a6e054e1 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1874,6 +1874,17 @@ static void efx_set_multicast_list(struct net_device *net_dev) /* Otherwise efx_start_port() will do this */ } +static int efx_set_features(struct net_device *net_dev, u32 data) +{ + struct efx_nic *efx = netdev_priv(net_dev); + + /* If disabling RX n-tuple filtering, clear existing filters */ + if (net_dev->features & ~data & NETIF_F_NTUPLE) + efx_filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL); + + return 0; +} + static const struct net_device_ops efx_netdev_ops = { .ndo_open = efx_net_open, .ndo_stop = efx_net_stop, @@ -1885,6 +1896,7 @@ static const struct net_device_ops efx_netdev_ops = { .ndo_change_mtu = efx_change_mtu, .ndo_set_mac_address = efx_set_mac_address, .ndo_set_multicast_list = efx_set_multicast_list, + .ndo_set_features = efx_set_features, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = efx_netpoll, #endif @@ -2269,7 +2281,6 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name)); efx->net_dev = net_dev; - efx->rx_checksum_enabled = true; spin_lock_init(&efx->stats_lock); mutex_init(&efx->mac_lock); efx->mac_op = type->default_mac_ops; @@ -2452,12 +2463,15 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, return -ENOMEM; net_dev->features |= (type->offload_features | NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_TSO | - NETIF_F_GRO); + NETIF_F_RXCSUM); if (type->offload_features & NETIF_F_V6_CSUM) net_dev->features |= NETIF_F_TSO6; /* Mask for features that also apply to VLAN devices */ net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG | - NETIF_F_HIGHDMA | NETIF_F_ALL_TSO); + NETIF_F_HIGHDMA | NETIF_F_ALL_TSO | + NETIF_F_RXCSUM); + /* All offloads can be toggled */ + net_dev->hw_features = net_dev->features & ~NETIF_F_HIGHDMA; efx = netdev_priv(net_dev); pci_set_drvdata(pci_dev, efx); SET_NETDEV_DEV(net_dev, &pci_dev->dev); diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 807178ef65ad..0d5543972574 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -518,72 +518,6 @@ static void efx_ethtool_get_stats(struct net_device *net_dev, } } -static int efx_ethtool_set_tso(struct net_device *net_dev, u32 enable) -{ - struct efx_nic *efx __attribute__ ((unused)) = netdev_priv(net_dev); - u32 features; - - features = NETIF_F_TSO; - if (efx->type->offload_features & NETIF_F_V6_CSUM) - features |= NETIF_F_TSO6; - - if (enable) - net_dev->features |= features; - else - net_dev->features &= ~features; - - return 0; -} - -static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable) -{ - struct efx_nic *efx = netdev_priv(net_dev); - u32 features = efx->type->offload_features & NETIF_F_ALL_CSUM; - - if (enable) - net_dev->features |= features; - else - net_dev->features &= ~features; - - return 0; -} - -static int efx_ethtool_set_rx_csum(struct net_device *net_dev, u32 enable) -{ - struct efx_nic *efx = netdev_priv(net_dev); - - /* No way to stop the hardware doing the checks; we just - * ignore the result. - */ - efx->rx_checksum_enabled = !!enable; - - return 0; -} - -static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev) -{ - struct efx_nic *efx = netdev_priv(net_dev); - - return efx->rx_checksum_enabled; -} - -static int efx_ethtool_set_flags(struct net_device *net_dev, u32 data) -{ - struct efx_nic *efx = netdev_priv(net_dev); - u32 supported = (efx->type->offload_features & - (ETH_FLAG_RXHASH | ETH_FLAG_NTUPLE)); - int rc; - - rc = ethtool_op_set_flags(net_dev, data, supported); - if (rc) - return rc; - - if (!(data & ETH_FLAG_NTUPLE)) - efx_filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL); - - return 0; -} - static void efx_ethtool_self_test(struct net_device *net_dev, struct ethtool_test *test, u64 *data) { @@ -1070,18 +1004,6 @@ const struct ethtool_ops efx_ethtool_ops = { .set_ringparam = efx_ethtool_set_ringparam, .get_pauseparam = efx_ethtool_get_pauseparam, .set_pauseparam = efx_ethtool_set_pauseparam, - .get_rx_csum = efx_ethtool_get_rx_csum, - .set_rx_csum = efx_ethtool_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - /* Need to enable/disable IPv6 too */ - .set_tx_csum = efx_ethtool_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - /* Need to enable/disable TSO-IPv6 too */ - .set_tso = efx_ethtool_set_tso, - .get_flags = ethtool_op_get_flags, - .set_flags = efx_ethtool_set_flags, .get_sset_count = efx_ethtool_get_sset_count, .self_test = efx_ethtool_self_test, .get_strings = efx_ethtool_get_strings, diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 215d5c51bfa0..f0f8ca535a4d 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -681,7 +681,6 @@ struct efx_filter_state; * @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock * @port_initialized: Port initialized? * @net_dev: Operating system network device. Consider holding the rtnl lock - * @rx_checksum_enabled: RX checksumming enabled * @stats_buffer: DMA buffer for statistics * @mac_op: MAC interface * @phy_type: PHY type @@ -771,7 +770,6 @@ struct efx_nic { bool port_initialized; struct net_device *net_dev; - bool rx_checksum_enabled; struct efx_buffer stats_buffer; diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index fb402c52aaff..b7dc891b4461 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c @@ -605,7 +605,7 @@ void __efx_rx_packet(struct efx_channel *channel, skb_record_rx_queue(skb, channel->channel); } - if (unlikely(!efx->rx_checksum_enabled)) + if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM))) checksummed = false; if (likely(checksummed || rx_buf->is_page)) { -- cgit v1.2.3-58-ga151 From e20b5b61a36bd5b80eea064c0f2e73285dbe0d3b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 1 Apr 2011 22:52:34 +0100 Subject: ethtool: Convert struct ethtool_ops comment to kernel-doc format Signed-off-by: Ben Hutchings --- include/linux/ethtool.h | 80 ++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 45 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index c8fcbdd2b0e7..ab12f84c17bd 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -683,63 +683,53 @@ void ethtool_ntuple_flush(struct net_device *dev); bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); /** - * ðtool_ops - Alter and report network device settings - * get_settings: Get device-specific settings - * set_settings: Set device-specific settings - * get_drvinfo: Report driver information - * get_regs: Get device registers - * get_wol: Report whether Wake-on-Lan is enabled - * set_wol: Turn Wake-on-Lan on or off - * get_msglevel: Report driver message level - * set_msglevel: Set driver message level - * nway_reset: Restart autonegotiation - * get_link: Get link status - * get_eeprom: Read data from the device EEPROM - * set_eeprom: Write data to the device EEPROM - * get_coalesce: Get interrupt coalescing parameters - * set_coalesce: Set interrupt coalescing parameters - * get_ringparam: Report ring sizes - * set_ringparam: Set ring sizes - * get_pauseparam: Report pause parameters - * set_pauseparam: Set pause parameters - * get_rx_csum: Report whether receive checksums are turned on or off - * set_rx_csum: Turn receive checksum on or off - * get_tx_csum: Report whether transmit checksums are turned on or off - * set_tx_csum: Turn transmit checksums on or off - * get_sg: Report whether scatter-gather is enabled - * set_sg: Turn scatter-gather on or off - * get_tso: Report whether TCP segmentation offload is enabled - * set_tso: Turn TCP segmentation offload on or off - * get_ufo: Report whether UDP fragmentation offload is enabled - * set_ufo: Turn UDP fragmentation offload on or off - * self_test: Run specified self-tests - * get_strings: Return a set of strings that describe the requested objects - * phys_id: Identify the device - * get_stats: Return statistics about the device - * get_flags: get 32-bit flags bitmap - * set_flags: set 32-bit flags bitmap - * - * Description: - * - * get_settings: + * struct ethtool_ops - Alter and report network device settings + * @get_settings: Get device-specific settings. * @get_settings is passed an ðtool_cmd to fill in. It returns * an negative errno or zero. - * - * set_settings: + * @set_settings: Set device-specific settings. * @set_settings is passed an ðtool_cmd and should attempt to set * all the settings this device supports. It may return an error value * if something goes wrong (otherwise 0). - * - * get_eeprom: + * @get_drvinfo: Report driver information + * @get_regs: Get device registers + * @get_wol: Report whether Wake-on-Lan is enabled + * @set_wol: Turn Wake-on-Lan on or off + * @get_msglevel: Report driver message level + * @set_msglevel: Set driver message level + * @nway_reset: Restart autonegotiation + * @get_link: Get link status + * @get_eeprom: Read data from the device EEPROM. * Should fill in the magic field. Don't need to check len for zero * or wraparound. Fill in the data argument with the eeprom values * from offset to offset + len. Update len to the amount read. * Returns an error or zero. - * - * set_eeprom: + * @set_eeprom: Write data to the device EEPROM. * Should validate the magic field. Don't need to check len for zero * or wraparound. Update len to the amount written. Returns an error * or zero. + * @get_coalesce: Get interrupt coalescing parameters + * @set_coalesce: Set interrupt coalescing parameters + * @get_ringparam: Report ring sizes + * @set_ringparam: Set ring sizes + * @get_pauseparam: Report pause parameters + * @set_pauseparam: Set pause parameters + * @get_rx_csum: Report whether receive checksums are turned on or off + * @set_rx_csum: Turn receive checksum on or off + * @get_tx_csum: Report whether transmit checksums are turned on or off + * @set_tx_csum: Turn transmit checksums on or off + * @get_sg: Report whether scatter-gather is enabled + * @set_sg: Turn scatter-gather on or off + * @get_tso: Report whether TCP segmentation offload is enabled + * @set_tso: Turn TCP segmentation offload on or off + * @get_ufo: Report whether UDP fragmentation offload is enabled + * @set_ufo: Turn UDP fragmentation offload on or off + * @self_test: Run specified self-tests + * @get_strings: Return a set of strings that describe the requested objects + * @phys_id: Identify the device + * @get_stats: Return statistics about the device + * @get_flags: get 32-bit flags bitmap + * @set_flags: set 32-bit flags bitmap */ struct ethtool_ops { int (*get_settings)(struct net_device *, struct ethtool_cmd *); -- cgit v1.2.3-58-ga151 From 8717d07b1143e0f150921f5bd7cfe7af579a995a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 1 Apr 2011 23:57:41 +0100 Subject: ethtool: Fill out and update comment for struct ethtool_ops Briefly document all operations (except get_rx_ntuple), including whether they may return an error code and whether they are deprecated. Also mention some things that should be handled by the ethtool core rather than by drivers. Briefly document general requirements for callers. Signed-off-by: Ben Hutchings --- include/linux/ethtool.h | 124 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 93 insertions(+), 31 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index ab12f84c17bd..ead7dcb1bf1e 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -683,22 +683,28 @@ void ethtool_ntuple_flush(struct net_device *dev); bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); /** - * struct ethtool_ops - Alter and report network device settings - * @get_settings: Get device-specific settings. - * @get_settings is passed an ðtool_cmd to fill in. It returns - * an negative errno or zero. - * @set_settings: Set device-specific settings. - * @set_settings is passed an ðtool_cmd and should attempt to set - * all the settings this device supports. It may return an error value - * if something goes wrong (otherwise 0). - * @get_drvinfo: Report driver information + * struct ethtool_ops - optional netdev operations + * @get_settings: Get various device settings including Ethernet link + * settings. Returns a negative error code or zero. + * @set_settings: Set various device settings including Ethernet link + * settings. Returns a negative error code or zero. + * @get_drvinfo: Report driver/device information. Should only set the + * @driver, @version, @fw_version and @bus_info fields. If not + * implemented, the @driver and @bus_info fields will be filled in + * according to the netdev's parent device. + * @get_regs_len: Get buffer length required for @get_regs * @get_regs: Get device registers * @get_wol: Report whether Wake-on-Lan is enabled - * @set_wol: Turn Wake-on-Lan on or off - * @get_msglevel: Report driver message level + * @set_wol: Turn Wake-on-Lan on or off. Returns a negative error code + * or zero. + * @get_msglevel: Report driver message level. This should be the value + * of the @msg_enable field used by netif logging functions. * @set_msglevel: Set driver message level - * @nway_reset: Restart autonegotiation - * @get_link: Get link status + * @nway_reset: Restart autonegotiation. Returns a negative error code + * or zero. + * @get_link: Report whether physical link is up. Will only be called if + * the netdev is up. Should usually be set to ethtool_op_get_link(), + * which uses netif_carrier_ok(). * @get_eeprom: Read data from the device EEPROM. * Should fill in the magic field. Don't need to check len for zero * or wraparound. Fill in the data argument with the eeprom values @@ -708,28 +714,84 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * Should validate the magic field. Don't need to check len for zero * or wraparound. Update len to the amount written. Returns an error * or zero. - * @get_coalesce: Get interrupt coalescing parameters - * @set_coalesce: Set interrupt coalescing parameters + * @get_coalesce: Get interrupt coalescing parameters. Returns a negative + * error code or zero. + * @set_coalesce: Set interrupt coalescing parameters. Returns a negative + * error code or zero. * @get_ringparam: Report ring sizes - * @set_ringparam: Set ring sizes + * @set_ringparam: Set ring sizes. Returns a negative error code or zero. * @get_pauseparam: Report pause parameters - * @set_pauseparam: Set pause parameters - * @get_rx_csum: Report whether receive checksums are turned on or off - * @set_rx_csum: Turn receive checksum on or off - * @get_tx_csum: Report whether transmit checksums are turned on or off - * @set_tx_csum: Turn transmit checksums on or off - * @get_sg: Report whether scatter-gather is enabled - * @set_sg: Turn scatter-gather on or off - * @get_tso: Report whether TCP segmentation offload is enabled - * @set_tso: Turn TCP segmentation offload on or off - * @get_ufo: Report whether UDP fragmentation offload is enabled - * @set_ufo: Turn UDP fragmentation offload on or off + * @set_pauseparam: Set pause parameters. Returns a negative error code + * or zero. + * @get_rx_csum: Deprecated in favour of the netdev feature %NETIF_F_RXCSUM. + * Report whether receive checksums are turned on or off. + * @set_rx_csum: Deprecated in favour of generic netdev features. Turn + * receive checksum on or off. Returns a negative error code or zero. + * @get_tx_csum: Deprecated as redundant. Report whether transmit checksums + * are turned on or off. + * @set_tx_csum: Deprecated in favour of generic netdev features. Turn + * transmit checksums on or off. Returns a egative error code or zero. + * @get_sg: Deprecated as redundant. Report whether scatter-gather is + * enabled. + * @set_sg: Deprecated in favour of generic netdev features. Turn + * scatter-gather on or off. Returns a negative error code or zero. + * @get_tso: Deprecated as redundant. Report whether TCP segmentation + * offload is enabled. + * @set_tso: Deprecated in favour of generic netdev features. Turn TCP + * segmentation offload on or off. Returns a negative error code or zero. * @self_test: Run specified self-tests * @get_strings: Return a set of strings that describe the requested objects - * @phys_id: Identify the device - * @get_stats: Return statistics about the device - * @get_flags: get 32-bit flags bitmap - * @set_flags: set 32-bit flags bitmap + * @phys_id: Identify the physical device, e.g. by flashing an LED + * attached to it until interrupted by a signal or the given time + * (in seconds) elapses. If the given time is zero, use a default + * time limit. Returns a negative error code or zero. Being + * interrupted by a signal is not an error. + * @get_ethtool_stats: Return extended statistics about the device. + * This is only useful if the device maintains statistics not + * included in &struct rtnl_link_stats64. + * @begin: Function to be called before any other operation. Returns a + * negative error code or zero. + * @complete: Function to be called after any other operation except + * @begin. Will be called even if the other operation failed. + * @get_ufo: Deprecated as redundant. Report whether UDP fragmentation + * offload is enabled. + * @set_ufo: Deprecated in favour of generic netdev features. Turn UDP + * fragmentation offload on or off. Returns a negative error code or zero. + * @get_flags: Deprecated as redundant. Report features included in + * &enum ethtool_flags that are enabled. + * @set_flags: Deprecated in favour of generic netdev features. Turn + * features included in &enum ethtool_flags on or off. Returns a + * negative error code or zero. + * @get_priv_flags: Report driver-specific feature flags. + * @set_priv_flags: Set driver-specific feature flags. Returns a negative + * error code or zero. + * @get_sset_count: Get number of strings that @get_strings will write. + * @get_rxnfc: Get RX flow classification rules. Returns a negative + * error code or zero. + * @set_rxnfc: Set RX flow classification rules. Returns a negative + * error code or zero. + * @flash_device: Write a firmware image to device's flash memory. + * Returns a negative error code or zero. + * @reset: Reset (part of) the device, as specified by a bitmask of + * flags from &enum ethtool_reset_flags. Returns a negative + * error code or zero. + * @set_rx_ntuple: Set an RX n-tuple rule. Returns a negative error code + * or zero. + * @get_rx_ntuple: Deprecated. + * @get_rxfh_indir: Get the contents of the RX flow hash indirection table. + * Returns a negative error code or zero. + * @set_rxfh_indir: Set the contents of the RX flow hash indirection table. + * Returns a negative error code or zero. + * + * All operations are optional (i.e. the function pointer may be set + * to %NULL) and callers must take this into account. Callers must + * hold the RTNL, except that for @get_drvinfo the caller may or may + * not hold the RTNL. + * + * See the structures used by these operations for further documentation. + * + * See &struct net_device and &struct net_device_ops for documentation + * of the generic netdev features interface. */ struct ethtool_ops { int (*get_settings)(struct net_device *, struct ethtool_cmd *); -- cgit v1.2.3-58-ga151 From 68f512f21a64c9b264df6c61a9333e7890faf74b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 2 Apr 2011 00:35:15 +0100 Subject: ethtool: Change ETHTOOL_PHYS_ID implementation to allow dropping RTNL The ethtool ETHTOOL_PHYS_ID command runs for an arbitrarily long period of time, holding the RTNL lock. This blocks routing updates, device enumeration, and various important operations that one might want to keep running while hunting for the flashing LED. We need to drop the RTNL lock during this operation, but currently the core implementation is a thin wrapper around a driver operation and drivers may well depend upon holding the lock. Define a new driver operation 'set_phys_id' with an argument that sets the ID indicator on/off/inactive/active (the last optional, for any driver or firmware that prefers to handle blinking asynchronously). When this is defined, the ethtool core drops the lock while waiting and only acquires it around calls to this operation. Deprecate the 'phys_id' operation in favour of this. It can be removed once all in-tree drivers are converted. Signed-off-by: Ben Hutchings --- include/linux/ethtool.h | 30 ++++++++++++++++++++++++++- net/core/ethtool.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 3 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index ead7dcb1bf1e..c04d1316d221 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -663,6 +663,22 @@ struct ethtool_rx_ntuple_list { unsigned int count; }; +/** + * enum ethtool_phys_id_state - indicator state for physical identification + * @ETHTOOL_ID_INACTIVE: Physical ID indicator should be deactivated + * @ETHTOOL_ID_ACTIVE: Physical ID indicator should be activated + * @ETHTOOL_ID_ON: LED should be turned on (used iff %ETHTOOL_ID_ACTIVE + * is not supported) + * @ETHTOOL_ID_OFF: LED should be turned off (used iff %ETHTOOL_ID_ACTIVE + * is not supported) + */ +enum ethtool_phys_id_state { + ETHTOOL_ID_INACTIVE, + ETHTOOL_ID_ACTIVE, + ETHTOOL_ID_ON, + ETHTOOL_ID_OFF +}; + struct net_device; /* Some generic methods drivers may use in their ethtool_ops */ @@ -741,7 +757,18 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * segmentation offload on or off. Returns a negative error code or zero. * @self_test: Run specified self-tests * @get_strings: Return a set of strings that describe the requested objects - * @phys_id: Identify the physical device, e.g. by flashing an LED + * @set_phys_id: Identify the physical devices, e.g. by flashing an LED + * attached to it. The implementation may update the indicator + * asynchronously or synchronously, but in either case it must return + * quickly. It is initially called with the argument %ETHTOOL_ID_ACTIVE, + * and must either activate asynchronous updates or return -%EINVAL. + * If it returns -%EINVAL then it will be called again at intervals with + * argument %ETHTOOL_ID_ON or %ETHTOOL_ID_OFF and should set the state of + * the indicator accordingly. Finally, it is called with the argument + * %ETHTOOL_ID_INACTIVE and must deactivate the indicator. Returns a + * negative error code or zero. + * @phys_id: Deprecated in favour of @set_phys_id. + * Identify the physical device, e.g. by flashing an LED * attached to it until interrupted by a signal or the given time * (in seconds) elapses. If the given time is zero, use a default * time limit. Returns a negative error code or zero. Being @@ -830,6 +857,7 @@ struct ethtool_ops { int (*set_tso)(struct net_device *, u32); void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); void (*get_strings)(struct net_device *, u32 stringset, u8 *); + int (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state); int (*phys_id)(struct net_device *, u32); void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *); diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 74ead9eca126..1c95f0fb8b3a 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include /* * Some useful ethtool_ops methods that're device independent. @@ -1618,14 +1620,63 @@ out: static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) { struct ethtool_value id; + static bool busy; + int rc; - if (!dev->ethtool_ops->phys_id) + if (!dev->ethtool_ops->set_phys_id && !dev->ethtool_ops->phys_id) return -EOPNOTSUPP; + if (busy) + return -EBUSY; + if (copy_from_user(&id, useraddr, sizeof(id))) return -EFAULT; - return dev->ethtool_ops->phys_id(dev, id.data); + if (!dev->ethtool_ops->set_phys_id) + /* Do it the old way */ + return dev->ethtool_ops->phys_id(dev, id.data); + + rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ACTIVE); + if (rc && rc != -EINVAL) + return rc; + + /* Drop the RTNL lock while waiting, but prevent reentry or + * removal of the device. + */ + busy = true; + dev_hold(dev); + rtnl_unlock(); + + if (rc == 0) { + /* Driver will handle this itself */ + schedule_timeout_interruptible( + id.data ? id.data : MAX_SCHEDULE_TIMEOUT); + } else { + /* Driver expects to be called periodically */ + do { + rtnl_lock(); + rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ON); + rtnl_unlock(); + if (rc) + break; + schedule_timeout_interruptible(HZ / 2); + + rtnl_lock(); + rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_OFF); + rtnl_unlock(); + if (rc) + break; + schedule_timeout_interruptible(HZ / 2); + } while (!signal_pending(current) && + (id.data == 0 || --id.data != 0)); + } + + rtnl_lock(); + dev_put(dev); + busy = false; + + (void)dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_INACTIVE); + return rc; } static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) -- cgit v1.2.3-58-ga151 From c5e129ac2fc72c119b85db79a629de66332f136d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 2 Apr 2011 00:43:46 +0100 Subject: sfc: Implement ethtool_ops::set_phys_id instead of ethtool_ops::phys_id Signed-off-by: Ben Hutchings --- drivers/net/sfc/ethtool.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 0d5543972574..644f7c1d6e7b 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -178,19 +178,27 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = { */ /* Identify device by flashing LEDs */ -static int efx_ethtool_phys_id(struct net_device *net_dev, u32 count) +static int efx_ethtool_phys_id(struct net_device *net_dev, + enum ethtool_phys_id_state state) { struct efx_nic *efx = netdev_priv(net_dev); + enum efx_led_mode mode; - do { - efx->type->set_id_led(efx, EFX_LED_ON); - schedule_timeout_interruptible(HZ / 2); - - efx->type->set_id_led(efx, EFX_LED_OFF); - schedule_timeout_interruptible(HZ / 2); - } while (!signal_pending(current) && --count != 0); + switch (state) { + case ETHTOOL_ID_ON: + mode = EFX_LED_ON; + break; + case ETHTOOL_ID_OFF: + mode = EFX_LED_OFF; + break; + case ETHTOOL_ID_INACTIVE: + mode = EFX_LED_DEFAULT; + break; + default: + return -EINVAL; + } - efx->type->set_id_led(efx, EFX_LED_DEFAULT); + efx->type->set_id_led(efx, mode); return 0; } @@ -1007,7 +1015,7 @@ const struct ethtool_ops efx_ethtool_ops = { .get_sset_count = efx_ethtool_get_sset_count, .self_test = efx_ethtool_self_test, .get_strings = efx_ethtool_get_strings, - .phys_id = efx_ethtool_phys_id, + .set_phys_id = efx_ethtool_phys_id, .get_ethtool_stats = efx_ethtool_get_stats, .get_wol = efx_ethtool_get_wol, .set_wol = efx_ethtool_set_wol, -- cgit v1.2.3-58-ga151 From aabf6f897e44bdf3e237ada04aa8f88d77d75cac Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 5 Apr 2011 15:37:45 +0200 Subject: Bluetooth: Use kthread API in hidp kernel_thread() is a low-level implementation detail and EXPORT_SYMBOL(kernel_thread) is scheduled for removal. Use the API instead. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hidp/core.c | 53 +++++++++++++++++++++-------------------------- net/bluetooth/hidp/hidp.h | 2 +- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index a1472b75d628..ae6ebc6c3481 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -463,8 +464,7 @@ static void hidp_idle_timeout(unsigned long arg) { struct hidp_session *session = (struct hidp_session *) arg; - atomic_inc(&session->terminate); - hidp_schedule(session); + kthread_stop(session->task); } static void hidp_set_timer(struct hidp_session *session) @@ -535,9 +535,7 @@ static void hidp_process_hid_control(struct hidp_session *session, skb_queue_purge(&session->ctrl_transmit); skb_queue_purge(&session->intr_transmit); - /* Kill session thread */ - atomic_inc(&session->terminate); - hidp_schedule(session); + kthread_stop(session->task); } } @@ -696,22 +694,10 @@ static int hidp_session(void *arg) struct sock *ctrl_sk = session->ctrl_sock->sk; struct sock *intr_sk = session->intr_sock->sk; struct sk_buff *skb; - int vendor = 0x0000, product = 0x0000; wait_queue_t ctrl_wait, intr_wait; BT_DBG("session %p", session); - if (session->input) { - vendor = session->input->id.vendor; - product = session->input->id.product; - } - - if (session->hid) { - vendor = session->hid->vendor; - product = session->hid->product; - } - - daemonize("khidpd_%04x%04x", vendor, product); set_user_nice(current, -15); init_waitqueue_entry(&ctrl_wait, current); @@ -720,7 +706,7 @@ static int hidp_session(void *arg) add_wait_queue(sk_sleep(intr_sk), &intr_wait); session->waiting_for_startup = 0; wake_up_interruptible(&session->startup_queue); - while (!atomic_read(&session->terminate)) { + while (!kthread_should_stop()) { set_current_state(TASK_INTERRUPTIBLE); if (ctrl_sk->sk_state != BT_CONNECTED || @@ -968,6 +954,7 @@ fault: int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock) { struct hidp_session *session, *s; + int vendor, product; int err; BT_DBG(""); @@ -1029,9 +1016,24 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, hidp_set_timer(session); - err = kernel_thread(hidp_session, session, CLONE_KERNEL); - if (err < 0) + if (session->hid) { + vendor = session->hid->vendor; + product = session->hid->product; + } else if (session->input) { + vendor = session->input->id.vendor; + product = session->input->id.product; + } else { + vendor = 0x0000; + product = 0x0000; + } + + session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x", + vendor, product); + if (IS_ERR(session->task)) { + err = PTR_ERR(session->task); goto unlink; + } + while (session->waiting_for_startup) { wait_event_interruptible(session->startup_queue, !session->waiting_for_startup); @@ -1056,8 +1058,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, err_add_device: hid_destroy_device(session->hid); session->hid = NULL; - atomic_inc(&session->terminate); - hidp_schedule(session); + kthread_stop(session->task); unlink: hidp_del_timer(session); @@ -1108,13 +1109,7 @@ int hidp_del_connection(struct hidp_conndel_req *req) skb_queue_purge(&session->ctrl_transmit); skb_queue_purge(&session->intr_transmit); - /* Wakeup user-space polling for socket errors */ - session->intr_sock->sk->sk_err = EUNATCH; - session->ctrl_sock->sk->sk_err = EUNATCH; - - /* Kill session thread */ - atomic_inc(&session->terminate); - hidp_schedule(session); + kthread_stop(session->task); } } else err = -ENOENT; diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index b412e7152eec..12822cde4b49 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h @@ -142,7 +142,7 @@ struct hidp_session { uint ctrl_mtu; uint intr_mtu; - atomic_t terminate; + struct task_struct *task; unsigned char keys[8]; unsigned char leds; -- cgit v1.2.3-58-ga151 From f4d7cd4a4c25cb4a5c30a675d4cc0052c93b925a Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 21 Mar 2011 14:20:00 +0100 Subject: Bluetooth: Use kthread API in bnep kernel_thread() is a low-level implementation detail and EXPORT_SYMBOL(kernel_thread) is scheduled for removal. Use the API instead. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/bnep/bnep.h | 2 +- net/bluetooth/bnep/core.c | 21 ++++++++------------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h index d768e0434ed8..8e6c06158f8e 100644 --- a/net/bluetooth/bnep/bnep.h +++ b/net/bluetooth/bnep/bnep.h @@ -155,7 +155,7 @@ struct bnep_session { unsigned int role; unsigned long state; unsigned long flags; - atomic_t killed; + struct task_struct *task; struct ethhdr eh; struct msghdr msg; diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 0a2e76bde542..ca39fcf010ce 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -479,12 +480,11 @@ static int bnep_session(void *arg) BT_DBG(""); - daemonize("kbnepd %s", dev->name); set_user_nice(current, -15); init_waitqueue_entry(&wait, current); add_wait_queue(sk_sleep(sk), &wait); - while (!atomic_read(&s->killed)) { + while (!kthread_should_stop()) { set_current_state(TASK_INTERRUPTIBLE); /* RX */ @@ -611,11 +611,12 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) __bnep_link_session(s); - err = kernel_thread(bnep_session, s, CLONE_KERNEL); - if (err < 0) { + s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name); + if (IS_ERR(s->task)) { /* Session thread start failed, gotta cleanup. */ unregister_netdev(dev); __bnep_unlink_session(s); + err = PTR_ERR(s->task); goto failed; } @@ -639,15 +640,9 @@ int bnep_del_connection(struct bnep_conndel_req *req) down_read(&bnep_session_sem); s = __bnep_get_session(req->dst); - if (s) { - /* Wakeup user-space which is polling for socket errors. - * This is temporary hack until we have shutdown in L2CAP */ - s->sock->sk->sk_err = EUNATCH; - - /* Kill session thread */ - atomic_inc(&s->killed); - wake_up_interruptible(sk_sleep(s->sock->sk)); - } else + if (s) + kthread_stop(s->task); + else err = -ENOENT; up_read(&bnep_session_sem); -- cgit v1.2.3-58-ga151 From fada4ac33992b1f953d95584e36f6ca7860aea40 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 21 Mar 2011 14:20:06 +0100 Subject: Bluetooth: Use kthread API in cmtp kernel_thread() is a low-level implementation detail and EXPORT_SYMBOL(kernel_thread) is scheduled for removal. Use the API instead. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/cmtp/capi.c | 6 +++--- net/bluetooth/cmtp/cmtp.h | 9 +-------- net/bluetooth/cmtp/core.c | 16 +++++++++------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c index 67cff810c77d..744233cba244 100644 --- a/net/bluetooth/cmtp/capi.c +++ b/net/bluetooth/cmtp/capi.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -143,7 +144,7 @@ static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb) skb_queue_tail(&session->transmit, skb); - cmtp_schedule(session); + wake_up_interruptible(sk_sleep(session->sock->sk)); } static void cmtp_send_interopmsg(struct cmtp_session *session, @@ -386,8 +387,7 @@ static void cmtp_reset_ctr(struct capi_ctr *ctrl) capi_ctr_down(ctrl); - atomic_inc(&session->terminate); - cmtp_schedule(session); + kthread_stop(session->task); } static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp) diff --git a/net/bluetooth/cmtp/cmtp.h b/net/bluetooth/cmtp/cmtp.h index c6f78f89415c..db43b54ac9af 100644 --- a/net/bluetooth/cmtp/cmtp.h +++ b/net/bluetooth/cmtp/cmtp.h @@ -81,7 +81,7 @@ struct cmtp_session { char name[BTNAMSIZ]; - atomic_t terminate; + struct task_struct *task; wait_queue_head_t wait; @@ -121,13 +121,6 @@ void cmtp_detach_device(struct cmtp_session *session); void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb); -static inline void cmtp_schedule(struct cmtp_session *session) -{ - struct sock *sk = session->sock->sk; - - wake_up_interruptible(sk_sleep(sk)); -} - /* CMTP init defines */ int cmtp_init_sockets(void); void cmtp_cleanup_sockets(void); diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 16aa6bd039ba..cce99b0919f5 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -287,12 +288,11 @@ static int cmtp_session(void *arg) BT_DBG("session %p", session); - daemonize("kcmtpd_ctr_%d", session->num); set_user_nice(current, -15); init_waitqueue_entry(&wait, current); add_wait_queue(sk_sleep(sk), &wait); - while (!atomic_read(&session->terminate)) { + while (!kthread_should_stop()) { set_current_state(TASK_INTERRUPTIBLE); if (sk->sk_state != BT_CONNECTED) @@ -370,9 +370,12 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) __cmtp_link_session(session); - err = kernel_thread(cmtp_session, session, CLONE_KERNEL); - if (err < 0) + session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d", + session->num); + if (IS_ERR(session->task)) { + err = PTR_ERR(session->task); goto unlink; + } if (!(session->flags & (1 << CMTP_LOOPBACK))) { err = cmtp_attach_device(session); @@ -409,9 +412,8 @@ int cmtp_del_connection(struct cmtp_conndel_req *req) /* Flush the transmit queue */ skb_queue_purge(&session->transmit); - /* Kill session thread */ - atomic_inc(&session->terminate); - cmtp_schedule(session); + /* Stop session thread */ + kthread_stop(session->task); } else err = -ENOENT; -- cgit v1.2.3-58-ga151 From 1322901da5094cecd9826ec3aaade83f6452cc45 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 4 Apr 2011 19:06:05 -0300 Subject: Bluetooth: Don't use spin_lock_bh in user context spin_lock() and spin_unlock() are more apropiated for user context. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/mgmt.c | 88 ++++++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 9a61320c5f2e..c32238163b72 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -179,7 +179,7 @@ static int read_controller_info(struct sock *sk, u16 index) hci_del_off_timer(hdev); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); set_bit(HCI_MGMT, &hdev->flags); @@ -208,7 +208,7 @@ static int read_controller_info(struct sock *sk, u16 index) memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name)); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp)); @@ -316,7 +316,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) if (!hdev) return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); up = test_bit(HCI_UP, &hdev->flags); if ((cp->val && up) || (!cp->val && !up)) { @@ -343,7 +343,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) err = 0; failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; } @@ -368,7 +368,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, if (!hdev) return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN); @@ -403,7 +403,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, mgmt_pending_remove(cmd); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -429,7 +429,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, if (!hdev) return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN); @@ -463,7 +463,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, mgmt_pending_remove(cmd); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -522,7 +522,7 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data, if (!hdev) return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (cp->val) set_bit(HCI_PAIRABLE, &hdev->flags); @@ -538,7 +538,7 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data, err = mgmt_event(MGMT_EV_PAIRABLE, index, &ev, sizeof(ev), sk); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -739,7 +739,7 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) if (!hdev) return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC); if (!uuid) { @@ -763,7 +763,7 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -788,7 +788,7 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) if (!hdev) return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) { err = hci_uuids_clear(hdev); @@ -823,7 +823,7 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0); unlock: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -847,7 +847,7 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data, if (!hdev) return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); hdev->major_class = cp->major; hdev->minor_class = cp->minor; @@ -857,7 +857,7 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data, if (err == 0) err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -879,7 +879,7 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, if (!hdev) return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); BT_DBG("hci%u enable %d", index, cp->enable); @@ -897,7 +897,7 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL, 0); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -931,7 +931,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys, key_count); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); hci_link_keys_clear(hdev); @@ -949,7 +949,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) key->pin_len); } - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return 0; @@ -971,7 +971,7 @@ static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len) if (!hdev) return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); err = hci_remove_link_key(hdev, &cp->bdaddr); if (err < 0) { @@ -994,7 +994,7 @@ static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len) } unlock: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1020,7 +1020,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) if (!hdev) return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN); @@ -1052,7 +1052,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) mgmt_pending_remove(cmd); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1073,7 +1073,7 @@ static int get_connections(struct sock *sk, u16 index) if (!hdev) return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); count = 0; list_for_each(p, &hdev->conn_hash.list) { @@ -1104,7 +1104,7 @@ static int get_connections(struct sock *sk, u16 index) unlock: kfree(rp); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; } @@ -1129,7 +1129,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, if (!hdev) return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN); @@ -1151,7 +1151,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, mgmt_pending_remove(cmd); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1178,7 +1178,7 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, @@ -1199,7 +1199,7 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data, mgmt_pending_remove(cmd); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1222,14 +1222,14 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data, if (!hdev) return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); hdev->io_capability = cp->io_capability; BT_DBG("%s IO capability set to 0x%02x", hdev->name, hdev->io_capability); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0); @@ -1315,7 +1315,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) if (!hdev) return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (cp->io_cap == 0x03) { sec_level = BT_SECURITY_MEDIUM; @@ -1357,7 +1357,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) err = 0; unlock: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1389,7 +1389,7 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, if (!hdev) return cmd_status(sk, index, mgmt_op, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, mgmt_op, ENETDOWN); @@ -1407,7 +1407,7 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, mgmt_pending_remove(cmd); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1431,7 +1431,7 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data, if (!hdev) return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len); if (!cmd) { @@ -1446,7 +1446,7 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data, mgmt_pending_remove(cmd); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1465,7 +1465,7 @@ static int read_local_oob_data(struct sock *sk, u16 index) return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, @@ -1495,7 +1495,7 @@ static int read_local_oob_data(struct sock *sk, u16 index) mgmt_pending_remove(cmd); unlock: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1519,7 +1519,7 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash, cp->randomizer); @@ -1529,7 +1529,7 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data, err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL, 0); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1553,7 +1553,7 @@ static int remove_remote_oob_data(struct sock *sk, u16 index, return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, ENODEV); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); err = hci_remove_remote_oob_data(hdev, &cp->bdaddr); if (err < 0) @@ -1563,7 +1563,7 @@ static int remove_remote_oob_data(struct sock *sk, u16 index, err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, NULL, 0); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; -- cgit v1.2.3-58-ga151 From e63a15ec0f25c0f97e8f6247b97ac9b30968b6b3 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 4 Apr 2011 18:56:53 -0300 Subject: Bluetooth: Use GFP_KERNEL in user context The allocation in mgmt_control() code are in user context and not locked by any spinlock, so it's not recommended the use of GFP_ATOMIC there. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index c32238163b72..c304688252b8 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1581,7 +1581,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) if (msglen < sizeof(*hdr)) return -EINVAL; - buf = kmalloc(msglen, GFP_ATOMIC); + buf = kmalloc(msglen, GFP_KERNEL); if (!buf) return -ENOMEM; -- cgit v1.2.3-58-ga151 From db940cb0db7c69a217661ecd49e1e6b0d680a6cc Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 2 Apr 2011 14:19:41 +0300 Subject: Bluetooth: convert net/bluetooth/ to kstrtox Convert from strict_strto*() interfaces to kstrto*() interfaces. Signed-off-by: Alexey Dobriyan Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_sysfs.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index e54421693eb8..8775933ea837 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -277,10 +277,12 @@ static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *at static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hci_dev *hdev = dev_get_drvdata(dev); - unsigned long val; + unsigned int val; + int rv; - if (strict_strtoul(buf, 0, &val) < 0) - return -EINVAL; + rv = kstrtouint(buf, 0, &val); + if (rv < 0) + return rv; if (val != 0 && (val < 500 || val > 3600000)) return -EINVAL; @@ -299,15 +301,14 @@ static ssize_t show_sniff_max_interval(struct device *dev, struct device_attribu static ssize_t store_sniff_max_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hci_dev *hdev = dev_get_drvdata(dev); - unsigned long val; - - if (strict_strtoul(buf, 0, &val) < 0) - return -EINVAL; + u16 val; + int rv; - if (val < 0x0002 || val > 0xFFFE || val % 2) - return -EINVAL; + rv = kstrtou16(buf, 0, &val); + if (rv < 0) + return rv; - if (val < hdev->sniff_min_interval) + if (val == 0 || val % 2 || val < hdev->sniff_min_interval) return -EINVAL; hdev->sniff_max_interval = val; @@ -324,15 +325,14 @@ static ssize_t show_sniff_min_interval(struct device *dev, struct device_attribu static ssize_t store_sniff_min_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hci_dev *hdev = dev_get_drvdata(dev); - unsigned long val; + u16 val; + int rv; - if (strict_strtoul(buf, 0, &val) < 0) - return -EINVAL; - - if (val < 0x0002 || val > 0xFFFE || val % 2) - return -EINVAL; + rv = kstrtou16(buf, 0, &val); + if (rv < 0) + return rv; - if (val > hdev->sniff_max_interval) + if (val == 0 || val % 2 || val > hdev->sniff_max_interval) return -EINVAL; hdev->sniff_min_interval = val; -- cgit v1.2.3-58-ga151 From de9f52300d03915846c2baab27332ec462f7f6b0 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 5 Apr 2011 14:22:43 +0000 Subject: tg3: Cleanup extended rx ring size code Hardcoded values are used in multiple places to describe the maximum rx ring sizes. This patch replaces those values with preprocessor constants. This patch also introduces a new TG3_FLG3_LRG_PROD_RING_CAP to determine if the device is capable of supporting larger ring sizes. Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/tg3.c | 37 +++++++++++++++++++------------------ drivers/net/tg3.h | 11 ++++++++--- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b7e03a6ebf25..8ffa5afd4141 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -97,14 +97,12 @@ * them in the NIC onboard memory. */ #define TG3_RX_STD_RING_SIZE(tp) \ - ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || \ - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) ? \ - RX_STD_MAX_SIZE_5717 : 512) + ((tp->tg3_flags3 & TG3_FLG3_LRG_PROD_RING_CAP) ? \ + TG3_RX_STD_MAX_SIZE_5717 : TG3_RX_STD_MAX_SIZE_5700) #define TG3_DEF_RX_RING_PENDING 200 #define TG3_RX_JMB_RING_SIZE(tp) \ - ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || \ - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) ? \ - 1024 : 256) + ((tp->tg3_flags3 & TG3_FLG3_LRG_PROD_RING_CAP) ? \ + TG3_RX_JMB_MAX_SIZE_5717 : TG3_RX_JMB_MAX_SIZE_5700) #define TG3_DEF_RX_JUMBO_RING_PENDING 100 #define TG3_RSS_INDIR_TBL_SIZE 128 @@ -8115,9 +8113,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) ((u64) tpr->rx_jmb_mapping >> 32)); tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, ((u64) tpr->rx_jmb_mapping & 0xffffffff)); + val = TG3_RX_JMB_RING_SIZE(tp) << + BDINFO_FLAGS_MAXLEN_SHIFT; tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, - (RX_JUMBO_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT) | - BDINFO_FLAGS_USE_EXT_RECV); + val | BDINFO_FLAGS_USE_EXT_RECV); if (!(tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR, @@ -8129,15 +8128,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) - val = RX_STD_MAX_SIZE_5705; + val = TG3_RX_STD_MAX_SIZE_5700; else - val = RX_STD_MAX_SIZE_5717; + val = TG3_RX_STD_MAX_SIZE_5717; val <<= BDINFO_FLAGS_MAXLEN_SHIFT; val |= (TG3_RX_STD_DMA_SZ << 2); } else val = TG3_RX_STD_DMA_SZ << BDINFO_FLAGS_MAXLEN_SHIFT; } else - val = RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT; + val = TG3_RX_STD_MAX_SIZE_5700 << BDINFO_FLAGS_MAXLEN_SHIFT; tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, val); @@ -8421,8 +8420,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE); tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB); val = RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + if (tp->tg3_flags3 & TG3_FLG3_LRG_PROD_RING_CAP) val |= RCVDBDI_MODE_LRG_RING_SZ; tw32(RCVDBDI_MODE, val); tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE); @@ -13125,14 +13123,13 @@ static inline void vlan_features_add(struct net_device *dev, unsigned long flags static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) - return 4096; + if (tp->tg3_flags3 & TG3_FLG3_LRG_PROD_RING_CAP) + return TG3_RX_RET_MAX_SIZE_5717; else if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) - return 1024; + return TG3_RX_RET_MAX_SIZE_5700; else - return 512; + return TG3_RX_RET_MAX_SIZE_5705; } static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = { @@ -13430,6 +13427,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags3 |= TG3_FLG3_40BIT_DMA_LIMIT_BUG; } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + tp->tg3_flags3 |= TG3_FLG3_LRG_PROD_RING_CAP; + if ((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719) tp->tg3_flags3 |= TG3_FLG3_USE_JUMBO_BDFLAG; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 73884b69b749..4c498ed66059 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -25,9 +25,13 @@ #define TG3_RX_INTERNAL_RING_SZ_5906 32 -#define RX_STD_MAX_SIZE_5705 512 -#define RX_STD_MAX_SIZE_5717 2048 -#define RX_JUMBO_MAX_SIZE 0xdeadbeef /* XXX */ +#define TG3_RX_STD_MAX_SIZE_5700 512 +#define TG3_RX_STD_MAX_SIZE_5717 2048 +#define TG3_RX_JMB_MAX_SIZE_5700 256 +#define TG3_RX_JMB_MAX_SIZE_5717 1024 +#define TG3_RX_RET_MAX_SIZE_5700 1024 +#define TG3_RX_RET_MAX_SIZE_5705 512 +#define TG3_RX_RET_MAX_SIZE_5717 4096 /* First 256 bytes are a mirror of PCI config space. */ #define TG3PCI_VENDOR 0x00000000 @@ -2897,6 +2901,7 @@ struct tg3 { #define TG3_FLG3_5701_DMA_BUG 0x00000008 #define TG3_FLG3_USE_PHYLIB 0x00000010 #define TG3_FLG3_MDIOBUS_INITED 0x00000020 +#define TG3_FLG3_LRG_PROD_RING_CAP 0x00000080 #define TG3_FLG3_RGMII_INBAND_DISABLE 0x00000100 #define TG3_FLG3_RGMII_EXT_IBND_RX_EN 0x00000200 #define TG3_FLG3_RGMII_EXT_IBND_TX_EN 0x00000400 -- cgit v1.2.3-58-ga151 From 1407deb1a99f7ec7ed5b09798b02abea5aa44128 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 5 Apr 2011 14:22:44 +0000 Subject: tg3: 5717_PLUS => 57765_PLUS The 57765 arrived before the 5717 and has a subset of the features supported by the 5717. This patch renames the 5717_PLUS flag so that it can be reintroduced to designate only 5717 and later devices. Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/tg3.c | 42 +++++++++++++++++++++--------------------- drivers/net/tg3.h | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 8ffa5afd4141..4f8976bd2b40 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7095,7 +7095,7 @@ static int tg3_chip_reset(struct tg3 *tp) if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { /* Force PCIe 1.0a mode */ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && - !(tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && + !(tp->tg3_flags3 & TG3_FLG3_57765_PLUS) && tr32(TG3_PCIE_PHY_TSTCTL) == (TG3_PCIE_PHY_TSTCTL_PCIE10 | TG3_PCIE_PHY_TSTCTL_PSCRAM)) tw32(TG3_PCIE_PHY_TSTCTL, TG3_PCIE_PHY_TSTCTL_PSCRAM); @@ -7248,7 +7248,7 @@ static int tg3_chip_reset(struct tg3 *tp) if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && - !(tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) { + !(tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) { val = tr32(0x7c00); tw32(0x7c00, val | (1 << 25)); @@ -7958,7 +7958,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (err) return err; - if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { + if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) { val = tr32(TG3PCI_DMA_RW_CTRL) & ~DMA_RWCTRL_DIS_CACHE_ALIGNMENT; if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) @@ -8126,7 +8126,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) BDINFO_FLAGS_DISABLED); } - if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { + if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) val = TG3_RX_STD_MAX_SIZE_5700; else @@ -8147,7 +8147,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->rx_jumbo_pending : 0; tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, tpr->rx_jmb_prod_idx); - if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { + if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) { tw32(STD_REPLENISH_LWM, 32); tw32(JMB_REPLENISH_LWM, 16); } @@ -8218,7 +8218,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || - (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) { + (tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) { val = tr32(TG3_RDMA_RSRVCTRL_REG); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) { val &= ~(TG3_RDMA_RSRVCTRL_TXMRGN_MASK | @@ -8866,7 +8866,7 @@ static int tg3_test_interrupt(struct tg3 *tp) * Turn off MSI one shot mode. Otherwise this test has no * observable way to know whether the interrupt was delivered. */ - if ((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && + if ((tp->tg3_flags3 & TG3_FLG3_57765_PLUS) && (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) { val = tr32(MSGINT_MODE) | MSGINT_MODE_ONE_SHOT_DISABLE; tw32(MSGINT_MODE, val); @@ -8909,7 +8909,7 @@ static int tg3_test_interrupt(struct tg3 *tp) if (intr_ok) { /* Reenable MSI one shot mode. */ - if ((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && + if ((tp->tg3_flags3 & TG3_FLG3_57765_PLUS) && (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) { val = tr32(MSGINT_MODE) & ~MSGINT_MODE_ONE_SHOT_DISABLE; tw32(MSGINT_MODE, val); @@ -9212,7 +9212,7 @@ static int tg3_open(struct net_device *dev) goto err_out2; } - if (!(tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && + if (!(tp->tg3_flags3 & TG3_FLG3_57765_PLUS) && (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) { u32 val = tr32(PCIE_TRANSACTION_CFG); @@ -12470,7 +12470,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) if (cfg2 & (1 << 18)) tp->phy_flags |= TG3_PHYFLG_SERDES_PREEMPHASIS; - if (((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) || + if (((tp->tg3_flags3 & TG3_FLG3_57765_PLUS) || ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX))) && (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN)) @@ -12478,7 +12478,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && - !(tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) { + !(tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) { u32 cfg3; tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &cfg3); @@ -13335,7 +13335,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) - tp->tg3_flags3 |= TG3_FLG3_5717_PLUS; + tp->tg3_flags3 |= TG3_FLG3_57765_PLUS; /* Intentionally exclude ASIC_REV_5906 */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || @@ -13344,7 +13344,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || - (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) + (tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) tp->tg3_flags3 |= TG3_FLG3_5755_PLUS; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || @@ -13376,7 +13376,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Determine TSO capabilities */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) ; /* Do nothing. HW bug. */ - else if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) + else if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) tp->tg3_flags2 |= TG3_FLG2_HW_TSO_3; else if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) @@ -13412,7 +13412,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; } - if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { + if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) { tp->tg3_flags |= TG3_FLAG_SUPPORT_MSIX; tp->irq_max = TG3_IRQ_MAX_VECS; } @@ -13431,7 +13431,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) tp->tg3_flags3 |= TG3_FLG3_LRG_PROD_RING_CAP; - if ((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && + if ((tp->tg3_flags3 & TG3_FLG3_57765_PLUS) && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719) tp->tg3_flags3 |= TG3_FLG3_USE_JUMBO_BDFLAG; @@ -13637,7 +13637,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || - (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) + (tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT; /* Set up tp->grc_local_ctrl before calling tg_power_up(). @@ -13716,7 +13716,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) !(tp->phy_flags & TG3_PHYFLG_IS_FET) && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780 && - !(tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) { + !(tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || @@ -14052,7 +14052,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) #endif #endif - if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { + if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) { val = goal ? 0 : DMA_RWCTRL_DIS_CACHE_ALIGNMENT; goto out; } @@ -14269,7 +14269,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp) tp->dma_rwctrl = tg3_calc_dma_bndry(tp, tp->dma_rwctrl); - if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) + if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) goto out; if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { @@ -14444,7 +14444,7 @@ out_nofree: static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) { - if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { + if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) { tp->bufmgr_config.mbuf_read_dma_low_water = DEFAULT_MB_RDMA_LOW_WATER_5705; tp->bufmgr_config.mbuf_mac_rx_low_water = diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 4c498ed66059..6f34db5d7e5e 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2915,7 +2915,7 @@ struct tg3 { #define TG3_FLG3_SHORT_DMA_BUG 0x00200000 #define TG3_FLG3_USE_JUMBO_BDFLAG 0x00400000 #define TG3_FLG3_L1PLLPD_EN 0x00800000 -#define TG3_FLG3_5717_PLUS 0x01000000 +#define TG3_FLG3_57765_PLUS 0x01000000 #define TG3_FLG3_APE_HAS_NCSI 0x02000000 struct timer_list timer; -- cgit v1.2.3-58-ga151 From 0a58d6689bb7c0d49addbf6992aa97234bcfc96c Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 5 Apr 2011 14:22:45 +0000 Subject: tg3: Reintroduce 5717_PLUS This patch reintroduces the TG3_FLG3_5717_PLUS to identify 5717 and later devices. Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/tg3.c | 40 ++++++++++++++++------------------------ drivers/net/tg3.h | 1 + 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 4f8976bd2b40..dc6b60b65c0b 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1042,8 +1042,7 @@ static int tg3_mdio_init(struct tg3 *tp) u32 reg; struct phy_device *phydev; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) { + if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { u32 is_serdes; tp->phy_addr = PCI_FUNC(tp->pdev->devfn) + 1; @@ -1621,8 +1620,7 @@ static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable) u32 reg; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || - ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) && + ((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && (tp->phy_flags & TG3_PHYFLG_MII_SERDES))) return; @@ -2045,8 +2043,7 @@ static int tg3_phy_reset(struct tg3 *tp) } } - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) && + if ((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && (tp->phy_flags & TG3_PHYFLG_MII_SERDES)) return 0; @@ -7671,8 +7668,7 @@ static void tg3_rings_reset(struct tg3 *tp) /* Disable all transmit rings but the first. */ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16; - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + else if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 4; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2; @@ -7686,8 +7682,7 @@ static void tg3_rings_reset(struct tg3 *tp) /* Disable all receive return rings but the first. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 17; else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16; @@ -8089,8 +8084,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) ((u64) tpr->rx_std_mapping >> 32)); tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, ((u64) tpr->rx_std_mapping & 0xffffffff)); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719) + if (!(tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_BUFFER_DESC); @@ -10848,8 +10842,7 @@ static int tg3_test_memory(struct tg3 *tp) int err = 0; int i; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) mem_tbl = mem_tbl_5717; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) mem_tbl = mem_tbl_57765; @@ -11930,8 +11923,7 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tg3_get_57780_nvram_info(tp); - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + else if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) tg3_get_5717_nvram_info(tp); else tg3_get_nvram_info(tp); @@ -13333,8 +13325,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pdev_peer = tg3_find_peer(tp); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + tp->tg3_flags3 |= TG3_FLG3_5717_PLUS; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 || + (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) tp->tg3_flags3 |= TG3_FLG3_57765_PLUS; /* Intentionally exclude ASIC_REV_5906 */ @@ -13427,8 +13422,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags3 |= TG3_FLG3_40BIT_DMA_LIMIT_BUG; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) tp->tg3_flags3 |= TG3_FLG3_LRG_PROD_RING_CAP; if ((tp->tg3_flags3 & TG3_FLG3_57765_PLUS) && @@ -13962,8 +13956,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) tw32_f(NVRAM_CMD, NVRAM_CMD_RESET); else tg3_nvram_unlock(tp); - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) { + } else if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { if (PCI_FUNC(tp->pdev->devfn) & 1) mac_offset = 0xcc; if (PCI_FUNC(tp->pdev->devfn) > 1) @@ -14760,8 +14753,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, } if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719) + !(tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) dev->netdev_ops = &tg3_netdev_ops; else dev->netdev_ops = &tg3_netdev_ops_dma_bug; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 6f34db5d7e5e..b8e6acc019b4 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2917,6 +2917,7 @@ struct tg3 { #define TG3_FLG3_L1PLLPD_EN 0x00800000 #define TG3_FLG3_57765_PLUS 0x01000000 #define TG3_FLG3_APE_HAS_NCSI 0x02000000 +#define TG3_FLG3_5717_PLUS 0x04000000 struct timer_list timer; u16 timer_counter; -- cgit v1.2.3-58-ga151 From d78b59f5d18bf064abae2fa5bc87f00545e2160a Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 5 Apr 2011 14:22:46 +0000 Subject: tg3: Add 5720 ASIC rev This patch adds support for the 5720 ASIC rev. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 30 ++++++++++++++++++++++-------- drivers/net/tg3.h | 5 +++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index dc6b60b65c0b..53a1209d4f9c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -2125,7 +2125,8 @@ static void tg3_frob_aux_power(struct tg3 *tp) if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) && + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) && tp->pdev_peer != tp->pdev) { struct net_device *dev_peer; @@ -7251,6 +7252,11 @@ static int tg3_chip_reset(struct tg3 *tp) tw32(0x7c00, val | (1 << 25)); } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { + val = tr32(TG3_CPMU_CLCK_ORIDE); + tw32(TG3_CPMU_CLCK_ORIDE, val & ~CPMU_CLCK_ORIDE_MAC_ORIDE_EN); + } + /* Reprobe ASF enable state. */ tp->tg3_flags &= ~TG3_FLAG_ENABLE_ASF; tp->tg3_flags2 &= ~TG3_FLG2_ASF_NEW_HANDSHAKE; @@ -8214,7 +8220,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || (tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) { val = tr32(TG3_RDMA_RSRVCTRL_REG); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { val &= ~(TG3_RDMA_RSRVCTRL_TXMRGN_MASK | TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK | TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK); @@ -8226,7 +8233,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) val | TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL); tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val | TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K | @@ -9050,7 +9058,9 @@ static bool tg3_enable_msix(struct tg3 *tp) if (tp->irq_cnt > 1) { tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) { + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { tp->tg3_flags3 |= TG3_FLG3_ENABLE_TSS; netif_set_real_num_tx_queues(tp->dev, tp->irq_cnt - 1); } @@ -13166,7 +13176,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719) + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720) pci_read_config_dword(tp->pdev, TG3PCI_GEN2_PRODID_ASICREV, &prod_id_asic_rev); @@ -13321,11 +13332,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) tp->pdev_peer = tg3_find_peer(tp); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) tp->tg3_flags3 |= TG3_FLG3_5717_PLUS; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 || @@ -13444,7 +13457,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; tp->pcie_readrq = 4096; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) tp->pcie_readrq = 2048; pcie_set_readrq(tp->pdev, tp->pcie_readrq); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index b8e6acc019b4..45605f2f7b54 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -58,6 +58,7 @@ #define TG3PCI_DEVICE_TIGON3_57791 0x16b2 #define TG3PCI_DEVICE_TIGON3_57795 0x16b6 #define TG3PCI_DEVICE_TIGON3_5719 0x1657 +#define TG3PCI_DEVICE_TIGON3_5720 0x165f /* 0x04 --> 0x2c unused */ #define TG3PCI_SUBVENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM #define TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6 0x1644 @@ -167,6 +168,7 @@ #define ASIC_REV_5717 0x5717 #define ASIC_REV_57765 0x57785 #define ASIC_REV_5719 0x5719 +#define ASIC_REV_5720 0x5720 #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 #define CHIPREV_5700_BX 0x71 @@ -1083,6 +1085,9 @@ #define CPMU_HST_ACC_MACCLK_6_25 0x00130000 /* 0x3620 --> 0x3630 unused */ +#define TG3_CPMU_CLCK_ORIDE 0x00003624 +#define CPMU_CLCK_ORIDE_MAC_ORIDE_EN 0x80000000 + #define TG3_CPMU_CLCK_STAT 0x00003630 #define CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001f0000 #define CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000 -- cgit v1.2.3-58-ga151 From 9b91b5f178605dd0d4debcbc184a3e97fcb4f591 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 5 Apr 2011 14:22:47 +0000 Subject: tg3: Add 5720 NVRAM decoding The 5720 implements its own NVRAM pin strapping scheme. This patch adds the required support. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++- drivers/net/tg3.h | 36 +++++++++++++++++ 2 files changed, 152 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 53a1209d4f9c..a079e745a071 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -11889,6 +11889,118 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp) tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS; } +static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp) +{ + u32 nvcfg1, nvmpinstrp; + + nvcfg1 = tr32(NVRAM_CFG1); + nvmpinstrp = nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK; + + switch (nvmpinstrp) { + case FLASH_5720_EEPROM_HD: + case FLASH_5720_EEPROM_LD: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + + nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; + tw32(NVRAM_CFG1, nvcfg1); + if (nvmpinstrp == FLASH_5720_EEPROM_HD) + tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; + else + tp->nvram_pagesize = ATMEL_AT24C02_CHIP_SIZE; + return; + case FLASH_5720VENDOR_M_ATMEL_DB011D: + case FLASH_5720VENDOR_A_ATMEL_DB011B: + case FLASH_5720VENDOR_A_ATMEL_DB011D: + case FLASH_5720VENDOR_M_ATMEL_DB021D: + case FLASH_5720VENDOR_A_ATMEL_DB021B: + case FLASH_5720VENDOR_A_ATMEL_DB021D: + case FLASH_5720VENDOR_M_ATMEL_DB041D: + case FLASH_5720VENDOR_A_ATMEL_DB041B: + case FLASH_5720VENDOR_A_ATMEL_DB041D: + case FLASH_5720VENDOR_M_ATMEL_DB081D: + case FLASH_5720VENDOR_A_ATMEL_DB081D: + case FLASH_5720VENDOR_ATMEL_45USPT: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + + switch (nvmpinstrp) { + case FLASH_5720VENDOR_M_ATMEL_DB021D: + case FLASH_5720VENDOR_A_ATMEL_DB021B: + case FLASH_5720VENDOR_A_ATMEL_DB021D: + tp->nvram_size = TG3_NVRAM_SIZE_256KB; + break; + case FLASH_5720VENDOR_M_ATMEL_DB041D: + case FLASH_5720VENDOR_A_ATMEL_DB041B: + case FLASH_5720VENDOR_A_ATMEL_DB041D: + tp->nvram_size = TG3_NVRAM_SIZE_512KB; + break; + case FLASH_5720VENDOR_M_ATMEL_DB081D: + case FLASH_5720VENDOR_A_ATMEL_DB081D: + tp->nvram_size = TG3_NVRAM_SIZE_1MB; + break; + default: + tp->nvram_size = TG3_NVRAM_SIZE_128KB; + break; + } + break; + case FLASH_5720VENDOR_M_ST_M25PE10: + case FLASH_5720VENDOR_M_ST_M45PE10: + case FLASH_5720VENDOR_A_ST_M25PE10: + case FLASH_5720VENDOR_A_ST_M45PE10: + case FLASH_5720VENDOR_M_ST_M25PE20: + case FLASH_5720VENDOR_M_ST_M45PE20: + case FLASH_5720VENDOR_A_ST_M25PE20: + case FLASH_5720VENDOR_A_ST_M45PE20: + case FLASH_5720VENDOR_M_ST_M25PE40: + case FLASH_5720VENDOR_M_ST_M45PE40: + case FLASH_5720VENDOR_A_ST_M25PE40: + case FLASH_5720VENDOR_A_ST_M45PE40: + case FLASH_5720VENDOR_M_ST_M25PE80: + case FLASH_5720VENDOR_M_ST_M45PE80: + case FLASH_5720VENDOR_A_ST_M25PE80: + case FLASH_5720VENDOR_A_ST_M45PE80: + case FLASH_5720VENDOR_ST_25USPT: + case FLASH_5720VENDOR_ST_45USPT: + tp->nvram_jedecnum = JEDEC_ST; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + + switch (nvmpinstrp) { + case FLASH_5720VENDOR_M_ST_M25PE20: + case FLASH_5720VENDOR_M_ST_M45PE20: + case FLASH_5720VENDOR_A_ST_M25PE20: + case FLASH_5720VENDOR_A_ST_M45PE20: + tp->nvram_size = TG3_NVRAM_SIZE_256KB; + break; + case FLASH_5720VENDOR_M_ST_M25PE40: + case FLASH_5720VENDOR_M_ST_M45PE40: + case FLASH_5720VENDOR_A_ST_M25PE40: + case FLASH_5720VENDOR_A_ST_M45PE40: + tp->nvram_size = TG3_NVRAM_SIZE_512KB; + break; + case FLASH_5720VENDOR_M_ST_M25PE80: + case FLASH_5720VENDOR_M_ST_M45PE80: + case FLASH_5720VENDOR_A_ST_M25PE80: + case FLASH_5720VENDOR_A_ST_M45PE80: + tp->nvram_size = TG3_NVRAM_SIZE_1MB; + break; + default: + tp->nvram_size = TG3_NVRAM_SIZE_128KB; + break; + } + break; + default: + tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM; + return; + } + + tg3_nvram_get_pagesize(tp, nvcfg1); + if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528) + tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS; +} + /* Chips other than 5700/5701 use the NVRAM for fetching info. */ static void __devinit tg3_nvram_init(struct tg3 *tp) { @@ -11933,8 +12045,11 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tg3_get_57780_nvram_info(tp); - else if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) tg3_get_5717_nvram_info(tp); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) + tg3_get_5720_nvram_info(tp); else tg3_get_nvram_info(tp); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 45605f2f7b54..169a6cebf9f1 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1827,6 +1827,38 @@ #define FLASH_5717VENDOR_ATMEL_45USPT 0x03400000 #define FLASH_5717VENDOR_ST_25USPT 0x03400002 #define FLASH_5717VENDOR_ST_45USPT 0x03400001 +#define FLASH_5720_EEPROM_HD 0x00000001 +#define FLASH_5720_EEPROM_LD 0x00000003 +#define FLASH_5720VENDOR_M_ATMEL_DB011D 0x01000000 +#define FLASH_5720VENDOR_M_ATMEL_DB021D 0x01000002 +#define FLASH_5720VENDOR_M_ATMEL_DB041D 0x01000001 +#define FLASH_5720VENDOR_M_ATMEL_DB081D 0x01000003 +#define FLASH_5720VENDOR_M_ST_M25PE10 0x02000000 +#define FLASH_5720VENDOR_M_ST_M25PE20 0x02000002 +#define FLASH_5720VENDOR_M_ST_M25PE40 0x02000001 +#define FLASH_5720VENDOR_M_ST_M25PE80 0x02000003 +#define FLASH_5720VENDOR_M_ST_M45PE10 0x03000000 +#define FLASH_5720VENDOR_M_ST_M45PE20 0x03000002 +#define FLASH_5720VENDOR_M_ST_M45PE40 0x03000001 +#define FLASH_5720VENDOR_M_ST_M45PE80 0x03000003 +#define FLASH_5720VENDOR_A_ATMEL_DB011B 0x01800000 +#define FLASH_5720VENDOR_A_ATMEL_DB021B 0x01800002 +#define FLASH_5720VENDOR_A_ATMEL_DB041B 0x01800001 +#define FLASH_5720VENDOR_A_ATMEL_DB011D 0x01c00000 +#define FLASH_5720VENDOR_A_ATMEL_DB021D 0x01c00002 +#define FLASH_5720VENDOR_A_ATMEL_DB041D 0x01c00001 +#define FLASH_5720VENDOR_A_ATMEL_DB081D 0x01c00003 +#define FLASH_5720VENDOR_A_ST_M25PE10 0x02800000 +#define FLASH_5720VENDOR_A_ST_M25PE20 0x02800002 +#define FLASH_5720VENDOR_A_ST_M25PE40 0x02800001 +#define FLASH_5720VENDOR_A_ST_M25PE80 0x02800003 +#define FLASH_5720VENDOR_A_ST_M45PE10 0x02c00000 +#define FLASH_5720VENDOR_A_ST_M45PE20 0x02c00002 +#define FLASH_5720VENDOR_A_ST_M45PE40 0x02c00001 +#define FLASH_5720VENDOR_A_ST_M45PE80 0x02c00003 +#define FLASH_5720VENDOR_ATMEL_45USPT 0x03c00000 +#define FLASH_5720VENDOR_ST_25USPT 0x03c00002 +#define FLASH_5720VENDOR_ST_45USPT 0x03c00001 #define NVRAM_CFG1_5752PAGE_SIZE_MASK 0x70000000 #define FLASH_5752PAGE_SIZE_256 0x00000000 #define FLASH_5752PAGE_SIZE_512 0x10000000 @@ -3060,6 +3092,7 @@ struct tg3 { int nvram_lock_cnt; u32 nvram_size; +#define TG3_NVRAM_SIZE_2KB 0x00000800 #define TG3_NVRAM_SIZE_64KB 0x00010000 #define TG3_NVRAM_SIZE_128KB 0x00020000 #define TG3_NVRAM_SIZE_256KB 0x00040000 @@ -3075,6 +3108,9 @@ struct tg3 { #define JEDEC_SAIFUN 0x4f #define JEDEC_SST 0xbf +#define ATMEL_AT24C02_CHIP_SIZE TG3_NVRAM_SIZE_2KB +#define ATMEL_AT24C02_PAGE_SIZE (8) + #define ATMEL_AT24C64_CHIP_SIZE TG3_NVRAM_SIZE_64KB #define ATMEL_AT24C64_PAGE_SIZE (32) -- cgit v1.2.3-58-ga151 From f2096f94b514d88593355995d5dd276961e88af1 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 5 Apr 2011 14:22:48 +0000 Subject: tg3: Add 5720 H2BMC support This patch adds support for the new Host to BMC feature. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 59 +++++++++++++++++++++++++++++++++++++++++-------------- drivers/net/tg3.h | 9 +++++++++ 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index a079e745a071..263f151ab528 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4390,6 +4390,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp) static int tg3_setup_phy(struct tg3 *tp, int force_reset) { + u32 val; int err; if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) @@ -4400,7 +4401,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) err = tg3_setup_copper_phy(tp, force_reset); if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) { - u32 val, scale; + u32 scale; val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK; if (val == CPMU_CLCK_STAT_MAC_CLCK_62_5) @@ -4415,17 +4416,20 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) tw32(GRC_MISC_CFG, val); } + val = (2 << TX_LENGTHS_IPG_CRS_SHIFT) | + (6 << TX_LENGTHS_IPG_SHIFT); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) + val |= tr32(MAC_TX_LENGTHS) & + (TX_LENGTHS_JMB_FRM_LEN_MSK | + TX_LENGTHS_CNT_DWN_VAL_MSK); + if (tp->link_config.active_speed == SPEED_1000 && tp->link_config.active_duplex == DUPLEX_HALF) - tw32(MAC_TX_LENGTHS, - ((2 << TX_LENGTHS_IPG_CRS_SHIFT) | - (6 << TX_LENGTHS_IPG_SHIFT) | - (0xff << TX_LENGTHS_SLOT_TIME_SHIFT))); + tw32(MAC_TX_LENGTHS, val | + (0xff << TX_LENGTHS_SLOT_TIME_SHIFT)); else - tw32(MAC_TX_LENGTHS, - ((2 << TX_LENGTHS_IPG_CRS_SHIFT) | - (6 << TX_LENGTHS_IPG_SHIFT) | - (32 << TX_LENGTHS_SLOT_TIME_SHIFT))); + tw32(MAC_TX_LENGTHS, val | + (32 << TX_LENGTHS_SLOT_TIME_SHIFT)); if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { if (netif_carrier_ok(tp->dev)) { @@ -4437,7 +4441,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) } if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND) { - u32 val = tr32(PCIE_PWR_MGMT_THRESH); + val = tr32(PCIE_PWR_MGMT_THRESH); if (!netif_carrier_ok(tp->dev)) val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) | tp->pwrmgmt_thresh; @@ -8164,10 +8168,16 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) /* The slot time is changed by tg3_setup_phy if we * run at gigabit with half duplex. */ - tw32(MAC_TX_LENGTHS, - (2 << TX_LENGTHS_IPG_CRS_SHIFT) | - (6 << TX_LENGTHS_IPG_SHIFT) | - (32 << TX_LENGTHS_SLOT_TIME_SHIFT)); + val = (2 << TX_LENGTHS_IPG_CRS_SHIFT) | + (6 << TX_LENGTHS_IPG_SHIFT) | + (32 << TX_LENGTHS_SLOT_TIME_SHIFT); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) + val |= tr32(MAC_TX_LENGTHS) & + (TX_LENGTHS_JMB_FRM_LEN_MSK | + TX_LENGTHS_CNT_DWN_VAL_MSK); + + tw32(MAC_TX_LENGTHS, val); /* Receive rules. */ tw32(MAC_RCV_RULE_CFG, RCV_RULE_CFG_DEFAULT_CLASS); @@ -8214,6 +8224,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) rdmac_mode |= RDMAC_MODE_IPV6_LSO_EN; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) + rdmac_mode |= tr32(RDMAC_MODE) & RDMAC_MODE_H2BNC_VLAN_DET; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || @@ -8447,9 +8460,17 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) } tp->tx_mode = TX_MODE_ENABLE; + if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tp->tx_mode |= TX_MODE_MBUF_LOCKUP_FIX; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { + val = TX_MODE_JMB_FRM_LEN | TX_MODE_CNT_DN_MODE; + tp->tx_mode &= ~val; + tp->tx_mode |= tr32(MAC_TX_MODE) & val; + } + tw32_f(MAC_TX_MODE, tp->tx_mode); udelay(100); @@ -13880,7 +13901,15 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Initialize data/descriptor byte/word swapping. */ val = tr32(GRC_MODE); - val &= GRC_MODE_HOST_STACKUP; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) + val &= (GRC_MODE_BYTE_SWAP_B2HRX_DATA | + GRC_MODE_WORD_SWAP_B2HRX_DATA | + GRC_MODE_B2HRX_ENABLE | + GRC_MODE_HTX2B_ENABLE | + GRC_MODE_HOST_STACKUP); + else + val &= GRC_MODE_HOST_STACKUP; + tw32(GRC_MODE, val | tp->grc_mode); tg3_switch_clocks(tp); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 169a6cebf9f1..a936727018f9 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -479,6 +479,8 @@ #define TX_MODE_BIG_BCKOFF_ENABLE 0x00000020 #define TX_MODE_LONG_PAUSE_ENABLE 0x00000040 #define TX_MODE_MBUF_LOCKUP_FIX 0x00000100 +#define TX_MODE_JMB_FRM_LEN 0x00400000 +#define TX_MODE_CNT_DN_MODE 0x00800000 #define MAC_TX_STATUS 0x00000460 #define TX_STATUS_XOFFED 0x00000001 #define TX_STATUS_SENT_XOFF 0x00000002 @@ -493,6 +495,8 @@ #define TX_LENGTHS_IPG_SHIFT 8 #define TX_LENGTHS_IPG_CRS_MASK 0x00003000 #define TX_LENGTHS_IPG_CRS_SHIFT 12 +#define TX_LENGTHS_JMB_FRM_LEN_MSK 0x00ff0000 +#define TX_LENGTHS_CNT_DWN_VAL_MSK 0xff000000 #define MAC_RX_MODE 0x00000468 #define RX_MODE_RESET 0x00000001 #define RX_MODE_ENABLE 0x00000002 @@ -1330,6 +1334,7 @@ #define RDMAC_MODE_MULT_DMA_RD_DIS 0x01000000 #define RDMAC_MODE_IPV4_LSO_EN 0x08000000 #define RDMAC_MODE_IPV6_LSO_EN 0x10000000 +#define RDMAC_MODE_H2BNC_VLAN_DET 0x20000000 #define RDMAC_STATUS 0x00004804 #define RDMAC_STATUS_TGTABORT 0x00000004 #define RDMAC_STATUS_MSTABORT 0x00000008 @@ -1622,6 +1627,8 @@ #define GRC_MODE_WSWAP_NONFRM_DATA 0x00000004 #define GRC_MODE_BSWAP_DATA 0x00000010 #define GRC_MODE_WSWAP_DATA 0x00000020 +#define GRC_MODE_BYTE_SWAP_B2HRX_DATA 0x00000040 +#define GRC_MODE_WORD_SWAP_B2HRX_DATA 0x00000080 #define GRC_MODE_SPLITHDR 0x00000100 #define GRC_MODE_NOFRM_CRACKING 0x00000200 #define GRC_MODE_INCL_CRC 0x00000400 @@ -1629,8 +1636,10 @@ #define GRC_MODE_NOIRQ_ON_SENDS 0x00002000 #define GRC_MODE_NOIRQ_ON_RCV 0x00004000 #define GRC_MODE_FORCE_PCI32BIT 0x00008000 +#define GRC_MODE_B2HRX_ENABLE 0x00008000 #define GRC_MODE_HOST_STACKUP 0x00010000 #define GRC_MODE_HOST_SENDBDS 0x00020000 +#define GRC_MODE_HTX2B_ENABLE 0x00040000 #define GRC_MODE_NO_TX_PHDR_CSUM 0x00100000 #define GRC_MODE_NVRAM_WR_ENABLE 0x00200000 #define GRC_MODE_PCIE_TL_SEL 0x00000000 -- cgit v1.2.3-58-ga151 From 6418f2c1b57f9a5d4e7380f698635e5a445c2a50 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 5 Apr 2011 14:22:49 +0000 Subject: tg3: Add 5720 PHY ID This patch adds the 5720 PHY ID. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 1 + drivers/net/tg3.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 263f151ab528..886174d75625 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -14673,6 +14673,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case TG3_PHY_ID_BCM5718S: return "5718S"; case TG3_PHY_ID_BCM57765: return "57765"; case TG3_PHY_ID_BCM5719C: return "5719C"; + case TG3_PHY_ID_BCM5720C: return "5720C"; case TG3_PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index a936727018f9..e7880d593aa8 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -3035,6 +3035,7 @@ struct tg3 { #define TG3_PHY_ID_BCM5718S 0xbc050ff0 #define TG3_PHY_ID_BCM57765 0x5c0d8a40 #define TG3_PHY_ID_BCM5719C 0x5c0d8a20 +#define TG3_PHY_ID_BCM5720C 0x5c0d8b60 #define TG3_PHY_ID_BCM5906 0xdc00ac40 #define TG3_PHY_ID_BCM8002 0x60010140 #define TG3_PHY_ID_INVALID 0xffffffff -- cgit v1.2.3-58-ga151 From ba1f3c76d7607a0af58834b79a055326619cbf2a Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 5 Apr 2011 14:22:50 +0000 Subject: tg3: Enable 5720 support This patch adds the 5720 device ID to the PCI table, thus enabling 5720 support. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 886174d75625..a065beb229f1 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -264,6 +264,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)}, -- cgit v1.2.3-58-ga151 From 66ee33bfda6237b009b6fb0e48690e31800ff334 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 5 Apr 2011 14:22:51 +0000 Subject: tg3: Support 4mb flash sizes for 5717 and 5719 If a 5717 or 5719 NVRAM part is manually strapped and is 2mb in size, the driver needs to look at the NVRAM size field rather than infer it from the strapping itself. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index a065beb229f1..f944c6b97dd6 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -11866,6 +11866,8 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp) switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { case FLASH_5717VENDOR_ATMEL_MDB021D: + /* Detect size with tg3_nvram_get_size() */ + break; case FLASH_5717VENDOR_ATMEL_ADB021B: case FLASH_5717VENDOR_ATMEL_ADB021D: tp->nvram_size = TG3_NVRAM_SIZE_256KB; @@ -11891,8 +11893,10 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp) switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { case FLASH_5717VENDOR_ST_M_M25PE20: - case FLASH_5717VENDOR_ST_A_M25PE20: case FLASH_5717VENDOR_ST_M_M45PE20: + /* Detect size with tg3_nvram_get_size() */ + break; + case FLASH_5717VENDOR_ST_A_M25PE20: case FLASH_5717VENDOR_ST_A_M45PE20: tp->nvram_size = TG3_NVRAM_SIZE_256KB; break; -- cgit v1.2.3-58-ga151 From 1ca050d909add6825224c015d8cec2425b3edf27 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 5 Apr 2011 08:01:16 +0000 Subject: can: convert protocol handling to RCU This patch removes spin_locks at CAN socket creation time by using RCU. Inspired by the discussion with Kurt van Dijck and Eric Dumazet the RCU code was partly derived from af_phonet.c Signed-off-by: Oliver Hartkopp Reviewed-by: Eric Dumazet Acked-by: Kurt Van Dijck Signed-off-by: David S. Miller --- net/can/af_can.c | 52 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/net/can/af_can.c b/net/can/af_can.c index 733d66f1b05a..a8dcaa49675a 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -85,7 +85,7 @@ static struct kmem_cache *rcv_cache __read_mostly; /* table of registered CAN protocols */ static struct can_proto *proto_tab[CAN_NPROTO] __read_mostly; -static DEFINE_SPINLOCK(proto_tab_lock); +static DEFINE_MUTEX(proto_tab_lock); struct timer_list can_stattimer; /* timer for statistics update */ struct s_stats can_stats; /* packet statistics */ @@ -115,6 +115,19 @@ static void can_sock_destruct(struct sock *sk) skb_queue_purge(&sk->sk_receive_queue); } +static struct can_proto *can_try_module_get(int protocol) +{ + struct can_proto *cp; + + rcu_read_lock(); + cp = rcu_dereference(proto_tab[protocol]); + if (cp && !try_module_get(cp->prot->owner)) + cp = NULL; + rcu_read_unlock(); + + return cp; +} + static int can_create(struct net *net, struct socket *sock, int protocol, int kern) { @@ -130,9 +143,12 @@ static int can_create(struct net *net, struct socket *sock, int protocol, if (!net_eq(net, &init_net)) return -EAFNOSUPPORT; + cp = can_try_module_get(protocol); + #ifdef CONFIG_MODULES - /* try to load protocol module kernel is modular */ - if (!proto_tab[protocol]) { + if (!cp) { + /* try to load protocol module if kernel is modular */ + err = request_module("can-proto-%d", protocol); /* @@ -143,22 +159,18 @@ static int can_create(struct net *net, struct socket *sock, int protocol, if (err && printk_ratelimit()) printk(KERN_ERR "can: request_module " "(can-proto-%d) failed.\n", protocol); + + cp = can_try_module_get(protocol); } #endif - spin_lock(&proto_tab_lock); - cp = proto_tab[protocol]; - if (cp && !try_module_get(cp->prot->owner)) - cp = NULL; - spin_unlock(&proto_tab_lock); - /* check for available protocol and correct usage */ if (!cp) return -EPROTONOSUPPORT; if (cp->type != sock->type) { - err = -EPROTONOSUPPORT; + err = -EPROTOTYPE; goto errout; } @@ -694,15 +706,16 @@ int can_proto_register(struct can_proto *cp) if (err < 0) return err; - spin_lock(&proto_tab_lock); + mutex_lock(&proto_tab_lock); + if (proto_tab[proto]) { printk(KERN_ERR "can: protocol %d already registered\n", proto); err = -EBUSY; } else - proto_tab[proto] = cp; + rcu_assign_pointer(proto_tab[proto], cp); - spin_unlock(&proto_tab_lock); + mutex_unlock(&proto_tab_lock); if (err < 0) proto_unregister(cp->prot); @@ -719,13 +732,12 @@ void can_proto_unregister(struct can_proto *cp) { int proto = cp->protocol; - spin_lock(&proto_tab_lock); - if (!proto_tab[proto]) { - printk(KERN_ERR "BUG: can: protocol %d is not registered\n", - proto); - } - proto_tab[proto] = NULL; - spin_unlock(&proto_tab_lock); + mutex_lock(&proto_tab_lock); + BUG_ON(proto_tab[proto] != cp); + rcu_assign_pointer(proto_tab[proto], NULL); + mutex_unlock(&proto_tab_lock); + + synchronize_rcu(); proto_unregister(cp->prot); } -- cgit v1.2.3-58-ga151 From 53478fef7490c90564dd328b395f238952d95c77 Mon Sep 17 00:00:00 2001 From: Sony Chacko Date: Fri, 1 Apr 2011 14:27:47 +0000 Subject: qlcnic: Make PCI info available in all modes Before this fix, PCI info was available only when multiple NIC functions are present on the same port. Signed-off-by: Sony Chacko Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index cd88c7e1bfa9..d230fdde28af 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -3954,14 +3954,14 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) dev_info(dev, "failed to create crb sysfs entry\n"); if (device_create_bin_file(dev, &bin_attr_mem)) dev_info(dev, "failed to create mem sysfs entry\n"); + if (device_create_bin_file(dev, &bin_attr_pci_config)) + dev_info(dev, "failed to create pci config sysfs entry"); if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) return; if (device_create_bin_file(dev, &bin_attr_esw_config)) dev_info(dev, "failed to create esw config sysfs entry"); if (adapter->op_mode != QLCNIC_MGMT_FUNC) return; - if (device_create_bin_file(dev, &bin_attr_pci_config)) - dev_info(dev, "failed to create pci config sysfs entry"); if (device_create_bin_file(dev, &bin_attr_npar_config)) dev_info(dev, "failed to create npar config sysfs entry"); if (device_create_bin_file(dev, &bin_attr_pm_config)) @@ -3982,12 +3982,12 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) device_remove_file(dev, &dev_attr_diag_mode); device_remove_bin_file(dev, &bin_attr_crb); device_remove_bin_file(dev, &bin_attr_mem); + device_remove_bin_file(dev, &bin_attr_pci_config); if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) return; device_remove_bin_file(dev, &bin_attr_esw_config); if (adapter->op_mode != QLCNIC_MGMT_FUNC) return; - device_remove_bin_file(dev, &bin_attr_pci_config); device_remove_bin_file(dev, &bin_attr_npar_config); device_remove_bin_file(dev, &bin_attr_pm_config); device_remove_bin_file(dev, &bin_attr_esw_stats); -- cgit v1.2.3-58-ga151 From f848d6dd10e8e27d5dd61a8ab7174a7dde3a3db5 Mon Sep 17 00:00:00 2001 From: Sony Chacko Date: Fri, 1 Apr 2011 14:27:59 +0000 Subject: qlcnic: Memory leak fix Fix a memory leak in error path of pci info. Signed-off-by: Sony Chacko Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index d230fdde28af..de6f86681a3c 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -464,8 +464,10 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter) for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { pfn = pci_info[i].id; - if (pfn > QLCNIC_MAX_PCI_FUNC) - return QL_STATUS_INVALID_PARAM; + if (pfn > QLCNIC_MAX_PCI_FUNC) { + ret = QL_STATUS_INVALID_PARAM; + goto err_eswitch; + } adapter->npars[pfn].active = (u8)pci_info[i].active; adapter->npars[pfn].type = (u8)pci_info[i].type; adapter->npars[pfn].phy_port = (u8)pci_info[i].default_port; -- cgit v1.2.3-58-ga151 From b1fc6d3cfaff6fefd838b84532cb356f8a80da7b Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Fri, 1 Apr 2011 14:28:05 +0000 Subject: qlcnic: Cleanup patch 1. Changed adapter structure to move away from embedding hardware and receive context structs and use pointers to those objects 2. Packed all the structs that interface with FW 3. Removed unused code and structs Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 126 +++++++++------------------- drivers/net/qlcnic/qlcnic_ctx.c | 135 +++++++++++++++--------------- drivers/net/qlcnic/qlcnic_ethtool.c | 40 ++++----- drivers/net/qlcnic/qlcnic_hw.c | 56 ++++++------- drivers/net/qlcnic/qlcnic_init.c | 26 +++--- drivers/net/qlcnic/qlcnic_main.c | 158 ++++++++++++++++++++++-------------- 6 files changed, 268 insertions(+), 273 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index dc44564ef6f9..15d950a4f46d 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -93,8 +93,6 @@ #define TX_IP_PKT 0x04 #define TX_TCP_LSO 0x05 #define TX_TCP_LSO6 0x06 -#define TX_IPSEC 0x07 -#define TX_IPSEC_CMD 0x0a #define TX_TCPV6_PKT 0x0b #define TX_UDPV6_PKT 0x0c @@ -200,7 +198,7 @@ struct rcv_desc { __le16 reserved; __le32 buffer_length; /* allocated buffer length (usually 2K) */ __le64 addr_buffer; -}; +} __packed; /* opcode field in status_desc */ #define QLCNIC_SYN_OFFLOAD 0x03 @@ -365,12 +363,6 @@ struct qlcnic_skb_frag { u64 length; }; -struct qlcnic_recv_crb { - u32 crb_rcv_producer[NUM_RCV_DESC_RINGS]; - u32 crb_sts_consumer[NUM_STS_DESC_RINGS]; - u32 sw_int_mask[NUM_STS_DESC_RINGS]; -}; - /* Following defines are for the state of the buffers */ #define QLCNIC_BUFFER_FREE 0 #define QLCNIC_BUFFER_BUSY 1 @@ -387,10 +379,10 @@ struct qlcnic_cmd_buffer { /* In rx_buffer, we do not need multiple fragments as is a single buffer */ struct qlcnic_rx_buffer { - struct list_head list; + u16 ref_handle; struct sk_buff *skb; + struct list_head list; u64 dma; - u16 ref_handle; }; /* Board types */ @@ -494,12 +486,12 @@ struct qlcnic_host_tx_ring { * present elsewhere. */ struct qlcnic_recv_context { + struct qlcnic_host_rds_ring *rds_rings; + struct qlcnic_host_sds_ring *sds_rings; u32 state; u16 context_id; u16 virt_port; - struct qlcnic_host_rds_ring *rds_rings; - struct qlcnic_host_sds_ring *sds_rings; }; /* HW context creation */ @@ -538,9 +530,6 @@ struct qlcnic_recv_context { #define QLCNIC_CDRP_CMD_DESTROY_RX_CTX 0x00000008 #define QLCNIC_CDRP_CMD_CREATE_TX_CTX 0x00000009 #define QLCNIC_CDRP_CMD_DESTROY_TX_CTX 0x0000000a -#define QLCNIC_CDRP_CMD_SETUP_STATISTICS 0x0000000e -#define QLCNIC_CDRP_CMD_GET_STATISTICS 0x0000000f -#define QLCNIC_CDRP_CMD_DELETE_STATISTICS 0x00000010 #define QLCNIC_CDRP_CMD_SET_MTU 0x00000012 #define QLCNIC_CDRP_CMD_READ_PHY 0x00000013 #define QLCNIC_CDRP_CMD_WRITE_PHY 0x00000014 @@ -549,17 +538,11 @@ struct qlcnic_recv_context { #define QLCNIC_CDRP_CMD_SET_FLOW_CTL 0x00000017 #define QLCNIC_CDRP_CMD_READ_MAX_MTU 0x00000018 #define QLCNIC_CDRP_CMD_READ_MAX_LRO 0x00000019 -#define QLCNIC_CDRP_CMD_CONFIGURE_TOE 0x0000001a -#define QLCNIC_CDRP_CMD_FUNC_ATTRIB 0x0000001b -#define QLCNIC_CDRP_CMD_READ_PEXQ_PARAMETERS 0x0000001c -#define QLCNIC_CDRP_CMD_GET_LIC_CAPABILITIES 0x0000001d -#define QLCNIC_CDRP_CMD_READ_MAX_LRO_PER_BOARD 0x0000001e #define QLCNIC_CDRP_CMD_MAC_ADDRESS 0x0000001f #define QLCNIC_CDRP_CMD_GET_PCI_INFO 0x00000020 #define QLCNIC_CDRP_CMD_GET_NIC_INFO 0x00000021 #define QLCNIC_CDRP_CMD_SET_NIC_INFO 0x00000022 -#define QLCNIC_CDRP_CMD_RESET_NPAR 0x00000023 #define QLCNIC_CDRP_CMD_GET_ESWITCH_CAPABILITY 0x00000024 #define QLCNIC_CDRP_CMD_TOGGLE_ESWITCH 0x00000025 #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026 @@ -597,14 +580,14 @@ struct qlcnic_hostrq_sds_ring { __le32 ring_size; /* Ring entries */ __le16 msi_index; __le16 rsvd; /* Padding */ -}; +} __packed; struct qlcnic_hostrq_rds_ring { __le64 host_phys_addr; /* Ring base addr */ __le64 buff_size; /* Packet buffer size */ __le32 ring_size; /* Ring entries */ __le32 ring_kind; /* Class of ring */ -}; +} __packed; struct qlcnic_hostrq_rx_ctx { __le64 host_rsp_dma_addr; /* Response dma'd here */ @@ -625,17 +608,17 @@ struct qlcnic_hostrq_rx_ctx { - N hostrq_rds_rings - N hostrq_sds_rings */ char data[0]; -}; +} __packed; struct qlcnic_cardrsp_rds_ring{ __le32 host_producer_crb; /* Crb to use */ __le32 rsvd1; /* Padding */ -}; +} __packed; struct qlcnic_cardrsp_sds_ring { __le32 host_consumer_crb; /* Crb to use */ __le32 interrupt_crb; /* Crb to use */ -}; +} __packed; struct qlcnic_cardrsp_rx_ctx { /* These ring offsets are relative to data[0] below */ @@ -654,7 +637,7 @@ struct qlcnic_cardrsp_rx_ctx { - N cardrsp_rds_rings - N cardrs_sds_rings */ char data[0]; -}; +} __packed; #define SIZEOF_HOSTRQ_RX(HOSTRQ_RX, rds_rings, sds_rings) \ (sizeof(HOSTRQ_RX) + \ @@ -674,7 +657,7 @@ struct qlcnic_hostrq_cds_ring { __le64 host_phys_addr; /* Ring base addr */ __le32 ring_size; /* Ring entries */ __le32 rsvd; /* Padding */ -}; +} __packed; struct qlcnic_hostrq_tx_ctx { __le64 host_rsp_dma_addr; /* Response dma'd here */ @@ -689,12 +672,12 @@ struct qlcnic_hostrq_tx_ctx { __le16 rsvd3; /* Padding */ struct qlcnic_hostrq_cds_ring cds_ring; /* Desc of cds ring */ u8 reserved[128]; /* future expansion */ -}; +} __packed; struct qlcnic_cardrsp_cds_ring { __le32 host_producer_crb; /* Crb to use */ __le32 interrupt_crb; /* Crb to use */ -}; +} __packed; struct qlcnic_cardrsp_tx_ctx { __le32 host_ctx_state; /* Starting state */ @@ -703,7 +686,7 @@ struct qlcnic_cardrsp_tx_ctx { u8 virt_port; /* Virtual/Logical id of port */ struct qlcnic_cardrsp_cds_ring cds_ring; /* Card cds settings */ u8 reserved[128]; /* future expansion */ -}; +} __packed; #define SIZEOF_HOSTRQ_TX(HOSTRQ_TX) (sizeof(HOSTRQ_TX)) #define SIZEOF_CARDRSP_TX(CARDRSP_TX) (sizeof(CARDRSP_TX)) @@ -782,50 +765,20 @@ struct qlcnic_nic_intr_coalesce { /* * Driver --> Firmware */ -#define QLCNIC_H2C_OPCODE_START 0 -#define QLCNIC_H2C_OPCODE_CONFIG_RSS 1 -#define QLCNIC_H2C_OPCODE_CONFIG_RSS_TBL 2 -#define QLCNIC_H2C_OPCODE_CONFIG_INTR_COALESCE 3 -#define QLCNIC_H2C_OPCODE_CONFIG_LED 4 -#define QLCNIC_H2C_OPCODE_CONFIG_PROMISCUOUS 5 -#define QLCNIC_H2C_OPCODE_CONFIG_L2_MAC 6 -#define QLCNIC_H2C_OPCODE_LRO_REQUEST 7 -#define QLCNIC_H2C_OPCODE_GET_SNMP_STATS 8 -#define QLCNIC_H2C_OPCODE_PROXY_START_REQUEST 9 -#define QLCNIC_H2C_OPCODE_PROXY_STOP_REQUEST 10 -#define QLCNIC_H2C_OPCODE_PROXY_SET_MTU 11 -#define QLCNIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE 12 -#define QLCNIC_H2C_OPCODE_GET_FINGER_PRINT_REQUEST 13 -#define QLCNIC_H2C_OPCODE_INSTALL_LICENSE_REQUEST 14 -#define QLCNIC_H2C_OPCODE_GET_LICENSE_CAPABILITY_REQUEST 15 -#define QLCNIC_H2C_OPCODE_GET_NET_STATS 16 -#define QLCNIC_H2C_OPCODE_PROXY_UPDATE_P2V 17 -#define QLCNIC_H2C_OPCODE_CONFIG_IPADDR 18 -#define QLCNIC_H2C_OPCODE_PROXY_STOP_DONE 20 -#define QLCNIC_H2C_OPCODE_GET_LINKEVENT 21 -#define QLCNIC_C2C_OPCODE 22 -#define QLCNIC_H2C_OPCODE_CONFIG_BRIDGING 23 -#define QLCNIC_H2C_OPCODE_CONFIG_HW_LRO 24 -#define QLCNIC_H2C_OPCODE_LAST 25 +#define QLCNIC_H2C_OPCODE_CONFIG_RSS 0x1 +#define QLCNIC_H2C_OPCODE_CONFIG_INTR_COALESCE 0x3 +#define QLCNIC_H2C_OPCODE_CONFIG_LED 0x4 +#define QLCNIC_H2C_OPCODE_LRO_REQUEST 0x7 +#define QLCNIC_H2C_OPCODE_SET_MAC_RECEIVE_MODE 0xc +#define QLCNIC_H2C_OPCODE_CONFIG_IPADDR 0x12 +#define QLCNIC_H2C_OPCODE_GET_LINKEVENT 0x15 +#define QLCNIC_H2C_OPCODE_CONFIG_BRIDGING 0x17 +#define QLCNIC_H2C_OPCODE_CONFIG_HW_LRO 0x18 /* * Firmware --> Driver */ -#define QLCNIC_C2H_OPCODE_START 128 -#define QLCNIC_C2H_OPCODE_CONFIG_RSS_RESPONSE 129 -#define QLCNIC_C2H_OPCODE_CONFIG_RSS_TBL_RESPONSE 130 -#define QLCNIC_C2H_OPCODE_CONFIG_MAC_RESPONSE 131 -#define QLCNIC_C2H_OPCODE_CONFIG_PROMISCUOUS_RESPONSE 132 -#define QLCNIC_C2H_OPCODE_CONFIG_L2_MAC_RESPONSE 133 -#define QLCNIC_C2H_OPCODE_LRO_DELETE_RESPONSE 134 -#define QLCNIC_C2H_OPCODE_LRO_ADD_FAILURE_RESPONSE 135 -#define QLCNIC_C2H_OPCODE_GET_SNMP_STATS 136 -#define QLCNIC_C2H_OPCODE_GET_FINGER_PRINT_REPLY 137 -#define QLCNIC_C2H_OPCODE_INSTALL_LICENSE_REPLY 138 -#define QLCNIC_C2H_OPCODE_GET_LICENSE_CAPABILITIES_REPLY 139 -#define QLCNIC_C2H_OPCODE_GET_NET_STATS_RESPONSE 140 #define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 141 -#define QLCNIC_C2H_OPCODE_LAST 142 #define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */ #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ @@ -894,7 +847,7 @@ struct qlcnic_nic_req { __le64 qhdr; __le64 req_hdr; __le64 words[6]; -}; +} __packed; struct qlcnic_mac_req { u8 op; @@ -905,7 +858,7 @@ struct qlcnic_mac_req { struct qlcnic_vlan_req { __le16 vlan_id; __le16 rsvd[3]; -}; +} __packed; struct qlcnic_ipaddr { __be32 ipv4; @@ -964,14 +917,14 @@ struct qlcnic_filter_hash { }; struct qlcnic_adapter { - struct qlcnic_hardware_context ahw; - + struct qlcnic_hardware_context *ahw; + struct qlcnic_recv_context *recv_ctx; + struct qlcnic_host_tx_ring *tx_ring; struct net_device *netdev; struct pci_dev *pdev; - struct list_head mac_list; - spinlock_t tx_clean_lock; - spinlock_t mac_learn_lock; + unsigned long state; + u32 flags; u16 num_txd; u16 num_rxd; @@ -989,7 +942,6 @@ struct qlcnic_adapter { u8 mc_enabled; u8 max_mc_count; - u8 rss_supported; u8 fw_wait_cnt; u8 fw_fail_cnt; u8 tx_timeo_cnt; @@ -1014,7 +966,6 @@ struct qlcnic_adapter { u32 fw_hal_version; u32 capabilities; - u32 flags; u32 irq; u32 temp; @@ -1039,9 +990,7 @@ struct qlcnic_adapter { struct qlcnic_nic_template *nic_ops; struct qlcnic_adapter_stats stats; - - struct qlcnic_recv_context recv_ctx; - struct qlcnic_host_tx_ring *tx_ring; + struct list_head mac_list; void __iomem *tgt_mask_reg; void __iomem *tgt_status_reg; @@ -1056,7 +1005,8 @@ struct qlcnic_adapter { struct qlcnic_filter_hash fhash; - unsigned long state; + spinlock_t tx_clean_lock; + spinlock_t mac_learn_lock; __le32 file_prd_off; /*File fw product offset*/ u32 fw_version; const struct firmware *fw; @@ -1078,7 +1028,7 @@ struct qlcnic_info { __le16 min_tx_bw; __le16 max_tx_bw; u8 reserved2[104]; -}; +} __packed; struct qlcnic_pci_info { __le16 id; /* pci function id */ @@ -1092,7 +1042,7 @@ struct qlcnic_pci_info { u8 mac[ETH_ALEN]; u8 reserved2[106]; -}; +} __packed; struct qlcnic_npar_info { u16 pvid; @@ -1209,7 +1159,7 @@ struct __qlcnic_esw_statistics { __le64 local_frames; __le64 numbytes; __le64 rsvd[3]; -}; +} __packed; struct qlcnic_esw_statistics { struct __qlcnic_esw_statistics rx; @@ -1293,7 +1243,7 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter); int qlcnic_check_fw_status(struct qlcnic_adapter *adapter); void qlcnic_watchdog_task(struct work_struct *work); -void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, u32 ringid, +void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, struct qlcnic_host_rds_ring *rds_ring); int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max); void qlcnic_set_multi(struct net_device *netdev); diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c index 27631f23b3fd..050fa5a99ff7 100644 --- a/drivers/net/qlcnic/qlcnic_ctx.c +++ b/drivers/net/qlcnic/qlcnic_ctx.c @@ -67,11 +67,11 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter, int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu) { - struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) { if (qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, recv_ctx->context_id, mtu, @@ -102,12 +102,12 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; u64 phys_addr; - int i, nrds_rings, nsds_rings; + u8 i, nrds_rings, nsds_rings; size_t rq_size, rsp_size; u32 cap, reg, val, reg2; int err; - struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; nrds_rings = adapter->max_rds_rings; nsds_rings = adapter->max_sds_rings; @@ -119,14 +119,14 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) SIZEOF_CARDRSP_RX(struct qlcnic_cardrsp_rx_ctx, nrds_rings, nsds_rings); - addr = pci_alloc_consistent(adapter->pdev, - rq_size, &hostrq_phys_addr); + addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size, + &hostrq_phys_addr, GFP_KERNEL); if (addr == NULL) return -ENOMEM; prq = (struct qlcnic_hostrq_rx_ctx *)addr; - addr = pci_alloc_consistent(adapter->pdev, - rsp_size, &cardrsp_phys_addr); + addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size, + &cardrsp_phys_addr, GFP_KERNEL); if (addr == NULL) { err = -ENOMEM; goto out_free_rq; @@ -151,7 +151,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) prq->num_rds_rings = cpu_to_le16(nrds_rings); prq->num_sds_rings = cpu_to_le16(nsds_rings); - prq->rds_ring_offset = cpu_to_le32(0); + prq->rds_ring_offset = 0; val = le32_to_cpu(prq->rds_ring_offset) + (sizeof(struct qlcnic_hostrq_rds_ring) * nrds_rings); @@ -187,7 +187,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) phys_addr = hostrq_phys_addr; err = qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, (u32)(phys_addr >> 32), (u32)(phys_addr & 0xffffffff), @@ -207,7 +207,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) rds_ring = &recv_ctx->rds_rings[i]; reg = le32_to_cpu(prsp_rds[i].host_producer_crb); - rds_ring->crb_rcv_producer = adapter->ahw.pci_base0 + reg; + rds_ring->crb_rcv_producer = adapter->ahw->pci_base0 + reg; } prsp_sds = ((struct qlcnic_cardrsp_sds_ring *) @@ -219,8 +219,8 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); reg2 = le32_to_cpu(prsp_sds[i].interrupt_crb); - sds_ring->crb_sts_consumer = adapter->ahw.pci_base0 + reg; - sds_ring->crb_intr_mask = adapter->ahw.pci_base0 + reg2; + sds_ring->crb_sts_consumer = adapter->ahw->pci_base0 + reg; + sds_ring->crb_intr_mask = adapter->ahw->pci_base0 + reg2; } recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); @@ -228,19 +228,20 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) recv_ctx->virt_port = prsp->virt_port; out_free_rsp: - pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr); + dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp, + cardrsp_phys_addr); out_free_rq: - pci_free_consistent(adapter->pdev, rq_size, prq, hostrq_phys_addr); + dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr); return err; } static void qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter) { - struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; if (qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, recv_ctx->context_id, QLCNIC_DESTROY_CTX_RESET, @@ -274,14 +275,14 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) *(tx_ring->hw_consumer) = 0; rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx); - rq_addr = pci_alloc_consistent(adapter->pdev, - rq_size, &rq_phys_addr); + rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size, + &rq_phys_addr, GFP_KERNEL); if (!rq_addr) return -ENOMEM; rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx); - rsp_addr = pci_alloc_consistent(adapter->pdev, - rsp_size, &rsp_phys_addr); + rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size, + &rsp_phys_addr, GFP_KERNEL); if (!rsp_addr) { err = -ENOMEM; goto out_free_rq; @@ -313,7 +314,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) phys_addr = rq_phys_addr; err = qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, (u32)(phys_addr >> 32), ((u32)phys_addr & 0xffffffff), @@ -322,7 +323,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) if (err == QLCNIC_RCODE_SUCCESS) { temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); - tx_ring->crb_cmd_producer = adapter->ahw.pci_base0 + temp; + tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp; adapter->tx_context_id = le16_to_cpu(prsp->context_id); @@ -332,10 +333,11 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) err = -EIO; } - pci_free_consistent(adapter->pdev, rsp_size, rsp_addr, rsp_phys_addr); + dma_free_coherent(&adapter->pdev->dev, rsp_size, rsp_addr, + rsp_phys_addr); out_free_rq: - pci_free_consistent(adapter->pdev, rq_size, rq_addr, rq_phys_addr); + dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr); return err; } @@ -344,7 +346,7 @@ static void qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter) { if (qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, adapter->tx_context_id, QLCNIC_DESTROY_CTX_RESET, @@ -361,7 +363,7 @@ qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val) { if (qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, reg, 0, @@ -378,7 +380,7 @@ int qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val) { return qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, reg, val, @@ -398,20 +400,19 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) struct pci_dev *pdev = adapter->pdev; - recv_ctx = &adapter->recv_ctx; + recv_ctx = adapter->recv_ctx; tx_ring = adapter->tx_ring; - tx_ring->hw_consumer = (__le32 *)pci_alloc_consistent(pdev, sizeof(u32), - &tx_ring->hw_cons_phys_addr); + tx_ring->hw_consumer = (__le32 *) dma_alloc_coherent(&pdev->dev, + sizeof(u32), &tx_ring->hw_cons_phys_addr, GFP_KERNEL); if (tx_ring->hw_consumer == NULL) { dev_err(&pdev->dev, "failed to allocate tx consumer\n"); return -ENOMEM; } - *(tx_ring->hw_consumer) = 0; /* cmd desc ring */ - addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring), - &tx_ring->phys_addr); + addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring), + &tx_ring->phys_addr, GFP_KERNEL); if (addr == NULL) { dev_err(&pdev->dev, "failed to allocate tx desc ring\n"); @@ -423,9 +424,9 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; - addr = pci_alloc_consistent(adapter->pdev, + addr = dma_alloc_coherent(&adapter->pdev->dev, RCV_DESC_RINGSIZE(rds_ring), - &rds_ring->phys_addr); + &rds_ring->phys_addr, GFP_KERNEL); if (addr == NULL) { dev_err(&pdev->dev, "failed to allocate rds ring [%d]\n", ring); @@ -439,9 +440,9 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; - addr = pci_alloc_consistent(adapter->pdev, + addr = dma_alloc_coherent(&adapter->pdev->dev, STATUS_DESC_RINGSIZE(sds_ring), - &sds_ring->phys_addr); + &sds_ring->phys_addr, GFP_KERNEL); if (addr == NULL) { dev_err(&pdev->dev, "failed to allocate sds ring [%d]\n", ring); @@ -501,11 +502,11 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) struct qlcnic_host_tx_ring *tx_ring; int ring; - recv_ctx = &adapter->recv_ctx; + recv_ctx = adapter->recv_ctx; tx_ring = adapter->tx_ring; if (tx_ring->hw_consumer != NULL) { - pci_free_consistent(adapter->pdev, + dma_free_coherent(&adapter->pdev->dev, sizeof(u32), tx_ring->hw_consumer, tx_ring->hw_cons_phys_addr); @@ -513,7 +514,7 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) } if (tx_ring->desc_head != NULL) { - pci_free_consistent(adapter->pdev, + dma_free_coherent(&adapter->pdev->dev, TX_DESC_RINGSIZE(tx_ring), tx_ring->desc_head, tx_ring->phys_addr); tx_ring->desc_head = NULL; @@ -523,7 +524,7 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) rds_ring = &recv_ctx->rds_rings[ring]; if (rds_ring->desc_head != NULL) { - pci_free_consistent(adapter->pdev, + dma_free_coherent(&adapter->pdev->dev, RCV_DESC_RINGSIZE(rds_ring), rds_ring->desc_head, rds_ring->phys_addr); @@ -535,7 +536,7 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) sds_ring = &recv_ctx->sds_rings[ring]; if (sds_ring->desc_head != NULL) { - pci_free_consistent(adapter->pdev, + dma_free_coherent(&adapter->pdev->dev, STATUS_DESC_RINGSIZE(sds_ring), sds_ring->desc_head, sds_ring->phys_addr); @@ -551,9 +552,9 @@ int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) int err; u32 arg1; - arg1 = adapter->ahw.pci_func | BIT_8; + arg1 = adapter->ahw->pci_func | BIT_8; err = qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, arg1, 0, @@ -582,15 +583,15 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter, void *nic_info_addr; size_t nic_size = sizeof(struct qlcnic_info); - nic_info_addr = pci_alloc_consistent(adapter->pdev, - nic_size, &nic_dma_t); + nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, + &nic_dma_t, GFP_KERNEL); if (!nic_info_addr) return -ENOMEM; memset(nic_info_addr, 0, nic_size); nic_info = (struct qlcnic_info *) nic_info_addr; err = qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, MSD(nic_dma_t), LSD(nic_dma_t), @@ -623,7 +624,8 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter, err = -EIO; } - pci_free_consistent(adapter->pdev, nic_size, nic_info_addr, nic_dma_t); + dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr, + nic_dma_t); return err; } @@ -639,8 +641,8 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) if (adapter->op_mode != QLCNIC_MGMT_FUNC) return err; - nic_info_addr = pci_alloc_consistent(adapter->pdev, nic_size, - &nic_dma_t); + nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, + &nic_dma_t, GFP_KERNEL); if (!nic_info_addr) return -ENOMEM; @@ -659,7 +661,7 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw); err = qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, MSD(nic_dma_t), LSD(nic_dma_t), @@ -672,7 +674,8 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) err = -EIO; } - pci_free_consistent(adapter->pdev, nic_size, nic_info_addr, nic_dma_t); + dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr, + nic_dma_t); return err; } @@ -687,15 +690,15 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, size_t npar_size = sizeof(struct qlcnic_pci_info); size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC; - pci_info_addr = pci_alloc_consistent(adapter->pdev, pci_size, - &pci_info_dma_t); + pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size, + &pci_info_dma_t, GFP_KERNEL); if (!pci_info_addr) return -ENOMEM; memset(pci_info_addr, 0, pci_size); npar = (struct qlcnic_pci_info *) pci_info_addr; err = qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, MSD(pci_info_dma_t), LSD(pci_info_dma_t), @@ -721,7 +724,7 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, err = -EIO; } - pci_free_consistent(adapter->pdev, pci_size, pci_info_addr, + dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr, pci_info_dma_t); return err; } @@ -741,7 +744,7 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, arg1 |= pci_func << 8; err = qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, arg1, 0, @@ -775,14 +778,14 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, return -ENOMEM; if (adapter->op_mode != QLCNIC_MGMT_FUNC && - func != adapter->ahw.pci_func) { + func != adapter->ahw->pci_func) { dev_err(&adapter->pdev->dev, "Not privilege to query stats for func=%d", func); return -EIO; } - stats_addr = pci_alloc_consistent(adapter->pdev, stats_size, - &stats_dma_t); + stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size, + &stats_dma_t, GFP_KERNEL); if (!stats_addr) { dev_err(&adapter->pdev->dev, "Unable to allocate memory\n"); return -ENOMEM; @@ -793,7 +796,7 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, arg1 |= rx_tx << 15 | stats_size << 16; err = qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, arg1, MSD(stats_dma_t), @@ -816,7 +819,7 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, esw_stats->numbytes = le64_to_cpu(stats->numbytes); } - pci_free_consistent(adapter->pdev, stats_size, stats_addr, + dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr, stats_dma_t); return err; } @@ -900,7 +903,7 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw, arg1 |= BIT_14 | rx_tx << 15; return qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, arg1, 0, @@ -921,7 +924,7 @@ __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, u8 pci_func; pci_func = (*arg1 >> 8); err = qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, *arg1, 0, @@ -999,7 +1002,7 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, } err = qlcnic_issue_cmd(adapter, - adapter->ahw.pci_func, + adapter->ahw->pci_func, adapter->fw_hal_version, arg1, arg2, diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 45b2755d6cba..7e53cad6be16 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -150,10 +150,10 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct qlcnic_adapter *adapter = netdev_priv(dev); int check_sfp_module = 0; - u16 pcifn = adapter->ahw.pci_func; + u16 pcifn = adapter->ahw->pci_func; /* read which mode */ - if (adapter->ahw.port_type == QLCNIC_GBE) { + if (adapter->ahw->port_type == QLCNIC_GBE) { ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | @@ -170,7 +170,7 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->duplex = adapter->link_duplex; ecmd->autoneg = adapter->link_autoneg; - } else if (adapter->ahw.port_type == QLCNIC_XGBE) { + } else if (adapter->ahw->port_type == QLCNIC_XGBE) { u32 val; val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR); @@ -201,7 +201,7 @@ skip: ecmd->phy_address = adapter->physical_port; ecmd->transceiver = XCVR_EXTERNAL; - switch (adapter->ahw.board_type) { + switch (adapter->ahw->board_type) { case QLCNIC_BRDTYPE_P3P_REF_QG: case QLCNIC_BRDTYPE_P3P_4_GB: case QLCNIC_BRDTYPE_P3P_4_GB_MM: @@ -238,7 +238,7 @@ skip: ecmd->autoneg = AUTONEG_DISABLE; break; case QLCNIC_BRDTYPE_P3P_10G_TP: - if (adapter->ahw.port_type == QLCNIC_XGBE) { + if (adapter->ahw->port_type == QLCNIC_XGBE) { ecmd->autoneg = AUTONEG_DISABLE; ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP); ecmd->advertising |= @@ -256,7 +256,7 @@ skip: break; default: dev_err(&adapter->pdev->dev, "Unsupported board model %d\n", - adapter->ahw.board_type); + adapter->ahw->board_type); return -EIO; } @@ -288,7 +288,7 @@ qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) __u32 status; /* read which mode */ - if (adapter->ahw.port_type == QLCNIC_GBE) { + if (adapter->ahw->port_type == QLCNIC_GBE) { /* autonegotiation */ if (qlcnic_fw_cmd_set_phy(adapter, QLCNIC_NIU_GB_MII_MGMT_ADDR_AUTONEG, @@ -340,14 +340,14 @@ static void qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) { struct qlcnic_adapter *adapter = netdev_priv(dev); - struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; struct qlcnic_host_sds_ring *sds_ring; u32 *regs_buff = p; int ring, i = 0, j = 0; memset(p, 0, qlcnic_get_regs_len(dev)); regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) | - (adapter->ahw.revision_id << 16) | (adapter->pdev)->device; + (adapter->ahw->revision_id << 16) | (adapter->pdev)->device; regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff)); regs_buff[1] = QLCNIC_MGMT_API_VERSION; @@ -382,7 +382,7 @@ static u32 qlcnic_test_link(struct net_device *dev) u32 val; val = QLCRD32(adapter, CRB_XG_STATE_P3P); - val = XG_LINK_STATE_P3P(adapter->ahw.pci_func, val); + val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val); return (val == XG_LINK_UP_P3P) ? 0 : 1; } @@ -482,7 +482,7 @@ qlcnic_get_pauseparam(struct net_device *netdev, int port = adapter->physical_port; __u32 val; - if (adapter->ahw.port_type == QLCNIC_GBE) { + if (adapter->ahw->port_type == QLCNIC_GBE) { if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS)) return; /* get flow control settings */ @@ -504,7 +504,7 @@ qlcnic_get_pauseparam(struct net_device *netdev, pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val)); break; } - } else if (adapter->ahw.port_type == QLCNIC_XGBE) { + } else if (adapter->ahw->port_type == QLCNIC_XGBE) { if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS)) return; pause->rx_pause = 1; @@ -515,7 +515,7 @@ qlcnic_get_pauseparam(struct net_device *netdev, pause->tx_pause = !(qlcnic_xg_get_xg1_mask(val)); } else { dev_err(&netdev->dev, "Unknown board type: %x\n", - adapter->ahw.port_type); + adapter->ahw->port_type); } } @@ -528,7 +528,7 @@ qlcnic_set_pauseparam(struct net_device *netdev, __u32 val; /* read mode */ - if (adapter->ahw.port_type == QLCNIC_GBE) { + if (adapter->ahw->port_type == QLCNIC_GBE) { if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS)) return -EIO; /* set flow control */ @@ -571,7 +571,7 @@ qlcnic_set_pauseparam(struct net_device *netdev, break; } QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val); - } else if (adapter->ahw.port_type == QLCNIC_XGBE) { + } else if (adapter->ahw->port_type == QLCNIC_XGBE) { if (!pause->rx_pause || pause->autoneg) return -EOPNOTSUPP; @@ -593,7 +593,7 @@ qlcnic_set_pauseparam(struct net_device *netdev, QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, val); } else { dev_err(&netdev->dev, "Unknown board type: %x\n", - adapter->ahw.port_type); + adapter->ahw->port_type); } return 0; } @@ -639,8 +639,8 @@ static int qlcnic_irq_test(struct net_device *netdev) goto clear_it; adapter->diag_cnt = 0; - ret = qlcnic_issue_cmd(adapter, adapter->ahw.pci_func, - adapter->fw_hal_version, adapter->portnum, + ret = qlcnic_issue_cmd(adapter, adapter->ahw->pci_func, + adapter->fw_hal_version, adapter->ahw->pci_func, 0, 0, 0x00000011); if (ret) goto done; @@ -749,14 +749,14 @@ qlcnic_get_ethtool_stats(struct net_device *dev, return; memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics)); - ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func, + ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func, QLCNIC_QUERY_RX_COUNTER, &port_stats.rx); if (ret) return; qlcnic_fill_device_stats(&index, data, &port_stats.rx); - ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func, + ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func, QLCNIC_QUERY_TX_COUNTER, &port_stats.tx); if (ret) return; diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 616940f0a8d0..7e3f52690e3f 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -457,7 +457,7 @@ int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); - word = QLCNIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE | + word = QLCNIC_H2C_OPCODE_SET_MAC_RECEIVE_MODE | ((u64)adapter->portnum << 16); req.req_hdr = cpu_to_le64(word); @@ -780,7 +780,7 @@ qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter, m = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)]; if (m->valid && (m->start_128M <= off) && (m->end_128M > off)) { - *addr = adapter->ahw.pci_base0 + m->start_2M + + *addr = adapter->ahw->pci_base0 + m->start_2M + (off - m->start_128M); return 0; } @@ -788,7 +788,7 @@ qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter, /* * Not in direct map, use crb window */ - *addr = adapter->ahw.pci_base0 + CRB_INDIRECT_2M + (off & MASK(16)); + *addr = adapter->ahw->pci_base0 + CRB_INDIRECT_2M + (off & MASK(16)); return 1; } @@ -801,7 +801,7 @@ static int qlcnic_pci_set_crbwindow_2M(struct qlcnic_adapter *adapter, ulong off) { u32 window; - void __iomem *addr = adapter->ahw.pci_base0 + CRB_WINDOW_2M; + void __iomem *addr = adapter->ahw->pci_base0 + CRB_WINDOW_2M; off -= QLCNIC_PCI_CRBSPACE; @@ -838,13 +838,13 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data) if (rv > 0) { /* indirect access */ - write_lock_irqsave(&adapter->ahw.crb_lock, flags); + write_lock_irqsave(&adapter->ahw->crb_lock, flags); crb_win_lock(adapter); rv = qlcnic_pci_set_crbwindow_2M(adapter, off); if (!rv) writel(data, addr); crb_win_unlock(adapter); - write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); + write_unlock_irqrestore(&adapter->ahw->crb_lock, flags); return rv; } @@ -869,12 +869,12 @@ qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off) if (rv > 0) { /* indirect access */ - write_lock_irqsave(&adapter->ahw.crb_lock, flags); + write_lock_irqsave(&adapter->ahw->crb_lock, flags); crb_win_lock(adapter); if (!qlcnic_pci_set_crbwindow_2M(adapter, off)) data = readl(addr); crb_win_unlock(adapter); - write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); + write_unlock_irqrestore(&adapter->ahw->crb_lock, flags); return data; } @@ -904,9 +904,9 @@ qlcnic_pci_set_window_2M(struct qlcnic_adapter *adapter, window = OCM_WIN_P3P(addr); - writel(window, adapter->ahw.ocm_win_crb); + writel(window, adapter->ahw->ocm_win_crb); /* read back to flush */ - readl(adapter->ahw.ocm_win_crb); + readl(adapter->ahw->ocm_win_crb); *start = QLCNIC_PCI_OCM0_2M + GET_MEM_OFFS_2M(addr); return 0; @@ -920,13 +920,13 @@ qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u64 off, int ret; u32 start; - mutex_lock(&adapter->ahw.mem_lock); + mutex_lock(&adapter->ahw->mem_lock); ret = qlcnic_pci_set_window_2M(adapter, off, &start); if (ret != 0) goto unlock; - addr = adapter->ahw.pci_base0 + start; + addr = adapter->ahw->pci_base0 + start; if (op == 0) /* read */ *data = readq(addr); @@ -934,7 +934,7 @@ qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u64 off, writeq(*data, addr); unlock: - mutex_unlock(&adapter->ahw.mem_lock); + mutex_unlock(&adapter->ahw->mem_lock); return ret; } @@ -942,23 +942,23 @@ unlock: void qlcnic_pci_camqm_read_2M(struct qlcnic_adapter *adapter, u64 off, u64 *data) { - void __iomem *addr = adapter->ahw.pci_base0 + + void __iomem *addr = adapter->ahw->pci_base0 + QLCNIC_PCI_CAMQM_2M_BASE + (off - QLCNIC_PCI_CAMQM); - mutex_lock(&adapter->ahw.mem_lock); + mutex_lock(&adapter->ahw->mem_lock); *data = readq(addr); - mutex_unlock(&adapter->ahw.mem_lock); + mutex_unlock(&adapter->ahw->mem_lock); } void qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *adapter, u64 off, u64 data) { - void __iomem *addr = adapter->ahw.pci_base0 + + void __iomem *addr = adapter->ahw->pci_base0 + QLCNIC_PCI_CAMQM_2M_BASE + (off - QLCNIC_PCI_CAMQM); - mutex_lock(&adapter->ahw.mem_lock); + mutex_lock(&adapter->ahw->mem_lock); writeq(data, addr); - mutex_unlock(&adapter->ahw.mem_lock); + mutex_unlock(&adapter->ahw->mem_lock); } #define MAX_CTL_CHECK 1000 @@ -997,7 +997,7 @@ qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter, correct: off8 = off & ~0xf; - mutex_lock(&adapter->ahw.mem_lock); + mutex_lock(&adapter->ahw->mem_lock); writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO)); writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI)); @@ -1049,7 +1049,7 @@ correct: ret = 0; done: - mutex_unlock(&adapter->ahw.mem_lock); + mutex_unlock(&adapter->ahw->mem_lock); return ret; } @@ -1091,7 +1091,7 @@ qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter, correct: off8 = off & ~0xf; - mutex_lock(&adapter->ahw.mem_lock); + mutex_lock(&adapter->ahw->mem_lock); writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO)); writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI)); @@ -1121,7 +1121,7 @@ correct: ret = 0; } - mutex_unlock(&adapter->ahw.mem_lock); + mutex_unlock(&adapter->ahw->mem_lock); return ret; } @@ -1145,7 +1145,7 @@ int qlcnic_get_board_info(struct qlcnic_adapter *adapter) if (qlcnic_rom_fast_read(adapter, offset, &board_type)) return -EIO; - adapter->ahw.board_type = board_type; + adapter->ahw->board_type = board_type; if (board_type == QLCNIC_BRDTYPE_P3P_4_GB_MM) { u32 gpio = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_PAD_GPIO_I); @@ -1164,20 +1164,20 @@ int qlcnic_get_board_info(struct qlcnic_adapter *adapter) case QLCNIC_BRDTYPE_P3P_10G_SFP_QT: case QLCNIC_BRDTYPE_P3P_10G_XFP: case QLCNIC_BRDTYPE_P3P_10000_BASE_T: - adapter->ahw.port_type = QLCNIC_XGBE; + adapter->ahw->port_type = QLCNIC_XGBE; break; case QLCNIC_BRDTYPE_P3P_REF_QG: case QLCNIC_BRDTYPE_P3P_4_GB: case QLCNIC_BRDTYPE_P3P_4_GB_MM: - adapter->ahw.port_type = QLCNIC_GBE; + adapter->ahw->port_type = QLCNIC_GBE; break; case QLCNIC_BRDTYPE_P3P_10G_TP: - adapter->ahw.port_type = (adapter->portnum < 2) ? + adapter->ahw->port_type = (adapter->portnum < 2) ? QLCNIC_XGBE : QLCNIC_GBE; break; default: dev_err(&pdev->dev, "unknown board type %x\n", board_type); - adapter->ahw.port_type = QLCNIC_XGBE; + adapter->ahw->port_type = QLCNIC_XGBE; break; } diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index a7f1d5b7e811..476ea14c0ff3 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -94,7 +94,7 @@ void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter) struct qlcnic_rx_buffer *rx_buf; int i, ring; - recv_ctx = &adapter->recv_ctx; + recv_ctx = adapter->recv_ctx; for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; for (i = 0; i < rds_ring->num_desc; ++i) { @@ -119,7 +119,7 @@ void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter) struct qlcnic_rx_buffer *rx_buf; int i, ring; - recv_ctx = &adapter->recv_ctx; + recv_ctx = adapter->recv_ctx; for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; @@ -173,7 +173,7 @@ void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter) struct qlcnic_host_tx_ring *tx_ring; int ring; - recv_ctx = &adapter->recv_ctx; + recv_ctx = adapter->recv_ctx; if (recv_ctx->rds_rings == NULL) goto skip_rds; @@ -226,7 +226,7 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) } tx_ring->cmd_buf_arr = cmd_buf_arr; - recv_ctx = &adapter->recv_ctx; + recv_ctx = adapter->recv_ctx; size = adapter->max_rds_rings * sizeof(struct qlcnic_host_rds_ring); rds_ring = kzalloc(size, GFP_KERNEL); @@ -864,7 +864,7 @@ nomn: for (i = 0; i < entries; i++) { __le32 flags, file_chiprev, offs; - u8 chiprev = adapter->ahw.revision_id; + u8 chiprev = adapter->ahw->revision_id; u32 flagbit; offs = cpu_to_le32(ptab_descr->findex) + @@ -1394,7 +1394,7 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, return skb; } -static int +static inline int qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb, u16 *vlan_tag) { @@ -1425,7 +1425,7 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter, int ring, u64 sts_data0) { struct net_device *netdev = adapter->netdev; - struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; struct qlcnic_rx_buffer *buffer; struct sk_buff *skb; struct qlcnic_host_rds_ring *rds_ring; @@ -1488,7 +1488,7 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, int ring, u64 sts_data0, u64 sts_data1) { struct net_device *netdev = adapter->netdev; - struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; struct qlcnic_rx_buffer *buffer; struct sk_buff *skb; struct qlcnic_host_rds_ring *rds_ring; @@ -1625,7 +1625,7 @@ skip: for (ring = 0; ring < adapter->max_rds_rings; ring++) { struct qlcnic_host_rds_ring *rds_ring = - &adapter->recv_ctx.rds_rings[ring]; + &adapter->recv_ctx->rds_rings[ring]; if (!list_empty(&sds_ring->free_list[ring])) { list_for_each(cur, &sds_ring->free_list[ring]) { @@ -1651,12 +1651,13 @@ skip: } void -qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, u32 ringid, +qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, struct qlcnic_host_rds_ring *rds_ring) { struct rcv_desc *pdesc; struct qlcnic_rx_buffer *buffer; - int producer, count = 0; + int count = 0; + u32 producer; struct list_head *head; producer = rds_ring->producer; @@ -1696,7 +1697,8 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, { struct rcv_desc *pdesc; struct qlcnic_rx_buffer *buffer; - int producer, count = 0; + int count = 0; + uint32_t producer; struct list_head *head; if (!spin_trylock(&rds_ring->lock)) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index de6f86681a3c..dde7e4403830 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -113,7 +113,7 @@ static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = { MODULE_DEVICE_TABLE(pci, qlcnic_pci_tbl); -void +inline void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter, struct qlcnic_host_tx_ring *tx_ring) { @@ -169,7 +169,7 @@ qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev) { int ring; struct qlcnic_host_sds_ring *sds_ring; - struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) return -ENOMEM; @@ -193,14 +193,14 @@ qlcnic_napi_del(struct qlcnic_adapter *adapter) { int ring; struct qlcnic_host_sds_ring *sds_ring; - struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; netif_napi_del(&sds_ring->napi); } - qlcnic_free_sds_rings(&adapter->recv_ctx); + qlcnic_free_sds_rings(adapter->recv_ctx); } static void @@ -208,7 +208,7 @@ qlcnic_napi_enable(struct qlcnic_adapter *adapter) { int ring; struct qlcnic_host_sds_ring *sds_ring; - struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) return; @@ -225,7 +225,7 @@ qlcnic_napi_disable(struct qlcnic_adapter *adapter) { int ring; struct qlcnic_host_sds_ring *sds_ring; - struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) return; @@ -359,7 +359,7 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter) struct pci_dev *pdev = adapter->pdev; int err, num_msix; - if (adapter->rss_supported) { + if (adapter->msix_supported) { num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ? MSIX_ENTRIES_PER_ADAPTER : 2; } else @@ -369,7 +369,7 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter) adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED); - legacy_intrp = &legacy_intr[adapter->ahw.pci_func]; + legacy_intrp = &legacy_intr[adapter->ahw->pci_func]; adapter->int_vec_bit = legacy_intrp->int_vec_bit; adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter, @@ -391,8 +391,7 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter) adapter->flags |= QLCNIC_MSIX_ENABLED; qlcnic_set_msix_bit(pdev, 1); - if (adapter->rss_supported) - adapter->max_sds_rings = num_msix; + adapter->max_sds_rings = num_msix; dev_info(&pdev->dev, "using msi-x interrupts\n"); return; @@ -407,7 +406,7 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter) if (use_msi && !pci_enable_msi(pdev)) { adapter->flags |= QLCNIC_MSI_ENABLED; adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter, - msi_tgt_status[adapter->ahw.pci_func]); + msi_tgt_status[adapter->ahw->pci_func]); dev_info(&pdev->dev, "using msi interrupts\n"); adapter->msix_entries[0].vector = pdev->irq; return; @@ -429,8 +428,8 @@ qlcnic_teardown_intr(struct qlcnic_adapter *adapter) static void qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter) { - if (adapter->ahw.pci_base0 != NULL) - iounmap(adapter->ahw.pci_base0); + if (adapter->ahw->pci_base0 != NULL) + iounmap(adapter->ahw->pci_base0); } static int @@ -500,7 +499,7 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter) u32 ref_count; int i, ret = 1; u32 data = QLCNIC_MGMT_FUNC; - void __iomem *priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE; + void __iomem *priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE; /* If other drivers are not in use set their privilege level */ ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE); @@ -512,16 +511,16 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter) for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { id = i; if (adapter->npars[i].type != QLCNIC_TYPE_NIC || - id == adapter->ahw.pci_func) + id == adapter->ahw->pci_func) continue; data |= (qlcnic_config_npars & QLC_DEV_SET_DRV(0xf, id)); } } else { data = readl(priv_op); - data = (data & ~QLC_DEV_SET_DRV(0xf, adapter->ahw.pci_func)) | + data = (data & ~QLC_DEV_SET_DRV(0xf, adapter->ahw->pci_func)) | (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, - adapter->ahw.pci_func)); + adapter->ahw->pci_func)); } writel(data, priv_op); qlcnic_api_unlock(adapter); @@ -539,22 +538,23 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter) u32 op_mode, priv_level; /* Determine FW API version */ - adapter->fw_hal_version = readl(adapter->ahw.pci_base0 + QLCNIC_FW_API); + adapter->fw_hal_version = readl(adapter->ahw->pci_base0 + + QLCNIC_FW_API); /* Find PCI function number */ pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func); - msix_base_addr = adapter->ahw.pci_base0 + QLCNIC_MSIX_BASE; + msix_base_addr = adapter->ahw->pci_base0 + QLCNIC_MSIX_BASE; msix_base = readl(msix_base_addr); func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE; - adapter->ahw.pci_func = func; + adapter->ahw->pci_func = func; /* Determine function privilege level */ - priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE; + priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE; op_mode = readl(priv_op); if (op_mode == QLC_DEV_DRV_DEFAULT) priv_level = QLCNIC_MGMT_FUNC; else - priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func); + priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func); if (priv_level == QLCNIC_NON_PRIV_FUNC) { adapter->op_mode = QLCNIC_NON_PRIV_FUNC; @@ -593,13 +593,14 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter) dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20)); - adapter->ahw.pci_base0 = mem_ptr0; - adapter->ahw.pci_len0 = pci_len0; + adapter->ahw->pci_base0 = mem_ptr0; + adapter->ahw->pci_len0 = pci_len0; qlcnic_check_vf(adapter); - adapter->ahw.ocm_win_crb = qlcnic_get_ioaddr(adapter, - QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(adapter->ahw.pci_func))); + adapter->ahw->ocm_win_crb = qlcnic_get_ioaddr(adapter, + QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG( + adapter->ahw->pci_func))); return 0; } @@ -641,7 +642,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) dev_info(&pdev->dev, "firmware v%d.%d.%d\n", fw_major, fw_minor, fw_build); - if (adapter->ahw.port_type == QLCNIC_XGBE) { + if (adapter->ahw->port_type == QLCNIC_XGBE) { if (adapter->flags & QLCNIC_ESWITCH_ENABLED) { adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_VF; adapter->max_rxd = MAX_RCV_DESCRIPTORS_VF; @@ -653,7 +654,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G; adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G; - } else if (adapter->ahw.port_type == QLCNIC_GBE) { + } else if (adapter->ahw->port_type == QLCNIC_GBE) { adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G; adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G; adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G; @@ -661,7 +662,6 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) } adapter->msix_supported = !!use_msi_x; - adapter->rss_supported = !!use_msi_x; adapter->num_txd = MAX_CMD_DESCRIPTORS; @@ -674,7 +674,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter) int err; struct qlcnic_info nic_info; - err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw.pci_func); + err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw->pci_func); if (err) return err; @@ -736,7 +736,7 @@ qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) return 0; - esw_cfg.pci_func = adapter->ahw.pci_func; + esw_cfg.pci_func = adapter->ahw->pci_func; if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg)) return -EIO; qlcnic_set_vlan_config(adapter, &esw_cfg); @@ -793,14 +793,14 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter) if (adapter->flags & QLCNIC_ADAPTER_INITIALIZED) return 0; - priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE; + priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE; op_mode = readl(priv_op); - priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func); + priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func); if (op_mode == QLC_DEV_DRV_DEFAULT) priv_level = QLCNIC_MGMT_FUNC; else - priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func); + priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func); if (adapter->flags & QLCNIC_ESWITCH_ENABLED) { if (priv_level == QLCNIC_MGMT_FUNC) { @@ -1040,7 +1040,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) unsigned long flags = 0; struct net_device *netdev = adapter->netdev; - struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) { handler = qlcnic_tmp_intr; @@ -1077,7 +1077,7 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter) int ring; struct qlcnic_host_sds_ring *sds_ring; - struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; @@ -1117,14 +1117,14 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) return -EIO; for (ring = 0; ring < adapter->max_rds_rings; ring++) { - rds_ring = &adapter->recv_ctx.rds_rings[ring]; - qlcnic_post_rx_buffers(adapter, ring, rds_ring); + rds_ring = &adapter->recv_ctx->rds_rings[ring]; + qlcnic_post_rx_buffers(adapter, rds_ring); } qlcnic_set_multi(netdev); qlcnic_fw_cmd_set_mtu(adapter, netdev->mtu); - adapter->ahw.linkup = 0; + adapter->ahw->linkup = 0; if (adapter->max_sds_rings > 1) qlcnic_config_rss(adapter, 1); @@ -1274,7 +1274,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings) clear_bit(__QLCNIC_DEV_UP, &adapter->state); if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) { for (ring = 0; ring < adapter->max_sds_rings; ring++) { - sds_ring = &adapter->recv_ctx.sds_rings[ring]; + sds_ring = &adapter->recv_ctx->sds_rings[ring]; qlcnic_disable_int(sds_ring); } } @@ -1295,6 +1295,39 @@ out: netif_device_attach(netdev); } +static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter) +{ + int err = 0; + adapter->ahw = kzalloc(sizeof(struct qlcnic_hardware_context), + GFP_KERNEL); + if (!adapter->ahw) { + dev_err(&adapter->pdev->dev, + "Failed to allocate recv ctx resources for adapter\n"); + err = -ENOMEM; + goto err_out; + } + adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context), + GFP_KERNEL); + if (!adapter->recv_ctx) { + dev_err(&adapter->pdev->dev, + "Failed to allocate recv ctx resources for adapter\n"); + kfree(adapter->ahw); + adapter->ahw = NULL; + err = -ENOMEM; + } +err_out: + return err; +} + +static void qlcnic_free_adapter_resources(struct qlcnic_adapter *adapter) +{ + kfree(adapter->recv_ctx); + adapter->recv_ctx = NULL; + + kfree(adapter->ahw); + adapter->ahw = NULL; +} + int qlcnic_diag_alloc_res(struct net_device *netdev, int test) { struct qlcnic_adapter *adapter = netdev_priv(netdev); @@ -1327,13 +1360,13 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) } for (ring = 0; ring < adapter->max_rds_rings; ring++) { - rds_ring = &adapter->recv_ctx.rds_rings[ring]; - qlcnic_post_rx_buffers(adapter, ring, rds_ring); + rds_ring = &adapter->recv_ctx->rds_rings[ring]; + qlcnic_post_rx_buffers(adapter, rds_ring); } if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) { for (ring = 0; ring < adapter->max_sds_rings; ring++) { - sds_ring = &adapter->recv_ctx.sds_rings[ring]; + sds_ring = &adapter->recv_ctx->sds_rings[ring]; qlcnic_enable_int(sds_ring); } } @@ -1503,23 +1536,26 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter = netdev_priv(netdev); adapter->netdev = netdev; adapter->pdev = pdev; - adapter->dev_rst_time = jiffies; + if (qlcnic_alloc_adapter_resources(adapter)) + goto err_out_free_netdev; + + adapter->dev_rst_time = jiffies; revision_id = pdev->revision; - adapter->ahw.revision_id = revision_id; + adapter->ahw->revision_id = revision_id; - rwlock_init(&adapter->ahw.crb_lock); - mutex_init(&adapter->ahw.mem_lock); + rwlock_init(&adapter->ahw->crb_lock); + mutex_init(&adapter->ahw->mem_lock); spin_lock_init(&adapter->tx_clean_lock); INIT_LIST_HEAD(&adapter->mac_list); err = qlcnic_setup_pci_map(adapter); if (err) - goto err_out_free_netdev; + goto err_out_free_hw; /* This will be reset for mezz cards */ - adapter->portnum = adapter->ahw.pci_func; + adapter->portnum = adapter->ahw->pci_func; err = qlcnic_get_board_info(adapter); if (err) { @@ -1547,7 +1583,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pr_info("%s: %s Board Chip rev 0x%x\n", module_name(THIS_MODULE), - brd_name, adapter->ahw.revision_id); + brd_name, adapter->ahw->revision_id); } qlcnic_clear_stats(adapter); @@ -1562,7 +1598,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); - switch (adapter->ahw.port_type) { + switch (adapter->ahw->port_type) { case QLCNIC_GBE: dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n", adapter->netdev->name); @@ -1587,6 +1623,9 @@ err_out_decr_ref: err_out_iounmap: qlcnic_cleanup_pci_map(adapter); +err_out_free_hw: + qlcnic_free_adapter_resources(adapter); + err_out_free_netdev: free_netdev(netdev); @@ -1640,6 +1679,7 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev) pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); + qlcnic_free_adapter_resources(adapter); free_netdev(netdev); } static int __qlcnic_shutdown(struct pci_dev *pdev) @@ -2248,16 +2288,16 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup) { struct net_device *netdev = adapter->netdev; - if (adapter->ahw.linkup && !linkup) { + if (adapter->ahw->linkup && !linkup) { netdev_info(netdev, "NIC Link is down\n"); - adapter->ahw.linkup = 0; + adapter->ahw->linkup = 0; if (netif_running(netdev)) { netif_carrier_off(netdev); netif_stop_queue(netdev); } - } else if (!adapter->ahw.linkup && linkup) { + } else if (!adapter->ahw->linkup && linkup) { netdev_info(netdev, "NIC Link is up\n"); - adapter->ahw.linkup = 1; + adapter->ahw->linkup = 1; if (netif_running(netdev)) { netif_carrier_on(netdev); netif_wake_queue(netdev); @@ -2493,7 +2533,7 @@ static void qlcnic_poll_controller(struct net_device *netdev) int ring; struct qlcnic_host_sds_ring *sds_ring; struct qlcnic_adapter *adapter = netdev_priv(netdev); - struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; disable_irq(adapter->irq); for (ring = 0; ring < adapter->max_sds_rings; ring++) { @@ -3503,7 +3543,7 @@ validate_esw_config(struct qlcnic_adapter *adapter, u8 pci_func; int i; - op_mode = readl(adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE); + op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE); for (i = 0; i < count; i++) { pci_func = esw_cfg[i].pci_func; @@ -3569,13 +3609,13 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) return QL_STATUS_INVALID_PARAM; - if (adapter->ahw.pci_func != esw_cfg[i].pci_func) + if (adapter->ahw->pci_func != esw_cfg[i].pci_func) continue; op_mode = esw_cfg[i].op_mode; qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]); esw_cfg[i].op_mode = op_mode; - esw_cfg[i].pci_func = adapter->ahw.pci_func; + esw_cfg[i].pci_func = adapter->ahw->pci_func; switch (esw_cfg[i].op_mode) { case QLCNIC_PORT_DEFAULTS: -- cgit v1.2.3-58-ga151 From 036d61f05189c9c02de22dd19a1c64a4fd74a914 Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Fri, 1 Apr 2011 14:28:11 +0000 Subject: qlcnic: Code optimization patch Optimized code resulted in achieving lower CPU utilization on transmit path and higher throughput for small packet sizes (64 bytes). Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 30 +++--- drivers/net/qlcnic/qlcnic_main.c | 210 +++++++++++++++++++-------------------- 2 files changed, 115 insertions(+), 125 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 15d950a4f46d..a5b28d1475b1 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -434,50 +434,49 @@ struct qlcnic_adapter_stats { * be one Rcv Descriptor for normal packets, one for jumbo and may be others. */ struct qlcnic_host_rds_ring { - u32 producer; + void __iomem *crb_rcv_producer; + struct rcv_desc *desc_head; + struct qlcnic_rx_buffer *rx_buf_arr; u32 num_desc; + u32 producer; u32 dma_size; u32 skb_size; u32 flags; - void __iomem *crb_rcv_producer; - struct rcv_desc *desc_head; - struct qlcnic_rx_buffer *rx_buf_arr; struct list_head free_list; spinlock_t lock; dma_addr_t phys_addr; -}; +} ____cacheline_internodealigned_in_smp; struct qlcnic_host_sds_ring { u32 consumer; u32 num_desc; void __iomem *crb_sts_consumer; - void __iomem *crb_intr_mask; struct status_desc *desc_head; struct qlcnic_adapter *adapter; struct napi_struct napi; struct list_head free_list[NUM_RCV_DESC_RINGS]; + void __iomem *crb_intr_mask; int irq; dma_addr_t phys_addr; char name[IFNAMSIZ+4]; -}; +} ____cacheline_internodealigned_in_smp; struct qlcnic_host_tx_ring { u32 producer; - __le32 *hw_consumer; u32 sw_consumer; - void __iomem *crb_cmd_producer; u32 num_desc; - - struct netdev_queue *txq; - - struct qlcnic_cmd_buffer *cmd_buf_arr; + void __iomem *crb_cmd_producer; struct cmd_desc_type0 *desc_head; + struct qlcnic_cmd_buffer *cmd_buf_arr; + __le32 *hw_consumer; + dma_addr_t phys_addr; dma_addr_t hw_cons_phys_addr; -}; + struct netdev_queue *txq; +} ____cacheline_internodealigned_in_smp; /* * Receive context. There is one such structure per instance of the @@ -1328,8 +1327,7 @@ static const struct qlcnic_brdinfo qlcnic_boards[] = { static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring) { - smp_mb(); - if (tx_ring->producer < tx_ring->sw_consumer) + if (likely(tx_ring->producer < tx_ring->sw_consumer)) return tx_ring->sw_consumer - tx_ring->producer; else return tx_ring->sw_consumer + tx_ring->num_desc - diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index dde7e4403830..3b740f55ca42 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -1861,6 +1861,7 @@ static void qlcnic_change_filter(struct qlcnic_adapter *adapter, vlan_req->vlan_id = vlan_id; tx_ring->producer = get_next_index(producer, tx_ring->num_desc); + smp_mb(); } #define QLCNIC_MAC_HASH(MAC)\ @@ -1921,58 +1922,122 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter, spin_unlock(&adapter->mac_learn_lock); } -static void -qlcnic_tso_check(struct net_device *netdev, - struct qlcnic_host_tx_ring *tx_ring, +static int +qlcnic_tx_pkt(struct qlcnic_adapter *adapter, struct cmd_desc_type0 *first_desc, struct sk_buff *skb) { - u8 opcode = TX_ETHER_PKT; - __be16 protocol = skb->protocol; - u16 flags = 0; - int copied, offset, copy_len, hdr_len = 0, tso = 0; + u8 opcode = 0, hdr_len = 0; + u16 flags = 0, vlan_tci = 0; + int copied, offset, copy_len; struct cmd_desc_type0 *hwdesc; struct vlan_ethhdr *vh; - struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; + u16 protocol = ntohs(skb->protocol); u32 producer = tx_ring->producer; - __le16 vlan_oob = first_desc->flags_opcode & - cpu_to_le16(FLAGS_VLAN_OOB); + + if (protocol == ETH_P_8021Q) { + vh = (struct vlan_ethhdr *)skb->data; + flags = FLAGS_VLAN_TAGGED; + vlan_tci = vh->h_vlan_TCI; + } else if (vlan_tx_tag_present(skb)) { + flags = FLAGS_VLAN_OOB; + vlan_tci = vlan_tx_tag_get(skb); + } + if (unlikely(adapter->pvid)) { + if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED)) + return -EIO; + if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED)) + goto set_flags; + + flags = FLAGS_VLAN_OOB; + vlan_tci = adapter->pvid; + } +set_flags: + qlcnic_set_tx_vlan_tci(first_desc, vlan_tci); + qlcnic_set_tx_flags_opcode(first_desc, flags, opcode); if (*(skb->data) & BIT_0) { flags |= BIT_0; memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN); } - - if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && + opcode = TX_ETHER_PKT; + if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && skb_shinfo(skb)->gso_size > 0) { hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); first_desc->total_hdr_length = hdr_len; - if (vlan_oob) { + + opcode = (protocol == ETH_P_IPV6) ? TX_TCP_LSO6 : TX_TCP_LSO; + + /* For LSO, we need to copy the MAC/IP/TCP headers into + * the descriptor ring */ + copied = 0; + offset = 2; + + if (flags & FLAGS_VLAN_OOB) { first_desc->total_hdr_length += VLAN_HLEN; first_desc->tcp_hdr_offset = VLAN_HLEN; first_desc->ip_hdr_offset = VLAN_HLEN; /* Only in case of TSO on vlan device */ flags |= FLAGS_VLAN_TAGGED; + + /* Create a TSO vlan header template for firmware */ + + hwdesc = &tx_ring->desc_head[producer]; + tx_ring->cmd_buf_arr[producer].skb = NULL; + + copy_len = min((int)sizeof(struct cmd_desc_type0) - + offset, hdr_len + VLAN_HLEN); + + vh = (struct vlan_ethhdr *)((char *) hwdesc + 2); + skb_copy_from_linear_data(skb, vh, 12); + vh->h_vlan_proto = htons(ETH_P_8021Q); + vh->h_vlan_TCI = htons(vlan_tci); + + skb_copy_from_linear_data_offset(skb, 12, + (char *)vh + 16, copy_len - 16); + + copied = copy_len - VLAN_HLEN; + offset = 0; + + producer = get_next_index(producer, tx_ring->num_desc); } - opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ? - TX_TCP_LSO6 : TX_TCP_LSO; - tso = 1; + while (copied < hdr_len) { + + copy_len = min((int)sizeof(struct cmd_desc_type0) - + offset, (hdr_len - copied)); + + hwdesc = &tx_ring->desc_head[producer]; + tx_ring->cmd_buf_arr[producer].skb = NULL; + + skb_copy_from_linear_data_offset(skb, copied, + (char *) hwdesc + offset, copy_len); + + copied += copy_len; + offset = 0; + + producer = get_next_index(producer, tx_ring->num_desc); + } + + tx_ring->producer = producer; + smp_mb(); + adapter->stats.lso_frames++; } else if (skb->ip_summed == CHECKSUM_PARTIAL) { u8 l4proto; - if (protocol == cpu_to_be16(ETH_P_IP)) { + if (protocol == ETH_P_IP) { l4proto = ip_hdr(skb)->protocol; if (l4proto == IPPROTO_TCP) opcode = TX_TCP_PKT; else if (l4proto == IPPROTO_UDP) opcode = TX_UDP_PKT; - } else if (protocol == cpu_to_be16(ETH_P_IPV6)) { + } else if (protocol == ETH_P_IPV6) { l4proto = ipv6_hdr(skb)->nexthdr; if (l4proto == IPPROTO_TCP) @@ -1981,63 +2046,11 @@ qlcnic_tso_check(struct net_device *netdev, opcode = TX_UDPV6_PKT; } } - first_desc->tcp_hdr_offset += skb_transport_offset(skb); first_desc->ip_hdr_offset += skb_network_offset(skb); qlcnic_set_tx_flags_opcode(first_desc, flags, opcode); - if (!tso) - return; - - /* For LSO, we need to copy the MAC/IP/TCP headers into - * the descriptor ring - */ - copied = 0; - offset = 2; - - if (vlan_oob) { - /* Create a TSO vlan header template for firmware */ - - hwdesc = &tx_ring->desc_head[producer]; - tx_ring->cmd_buf_arr[producer].skb = NULL; - - copy_len = min((int)sizeof(struct cmd_desc_type0) - offset, - hdr_len + VLAN_HLEN); - - vh = (struct vlan_ethhdr *)((char *)hwdesc + 2); - skb_copy_from_linear_data(skb, vh, 12); - vh->h_vlan_proto = htons(ETH_P_8021Q); - vh->h_vlan_TCI = (__be16)swab16((u16)first_desc->vlan_TCI); - - skb_copy_from_linear_data_offset(skb, 12, - (char *)vh + 16, copy_len - 16); - - copied = copy_len - VLAN_HLEN; - offset = 0; - - producer = get_next_index(producer, tx_ring->num_desc); - } - - while (copied < hdr_len) { - - copy_len = min((int)sizeof(struct cmd_desc_type0) - offset, - (hdr_len - copied)); - - hwdesc = &tx_ring->desc_head[producer]; - tx_ring->cmd_buf_arr[producer].skb = NULL; - - skb_copy_from_linear_data_offset(skb, copied, - (char *)hwdesc + offset, copy_len); - - copied += copy_len; - offset = 0; - - producer = get_next_index(producer, tx_ring->num_desc); - } - - tx_ring->producer = producer; - barrier(); - adapter->stats.lso_frames++; + return 0; } static int @@ -2088,39 +2101,21 @@ out_err: return -ENOMEM; } -static int -qlcnic_check_tx_tagging(struct qlcnic_adapter *adapter, - struct sk_buff *skb, - struct cmd_desc_type0 *first_desc) +static void +qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb, + struct qlcnic_cmd_buffer *pbuf) { - u8 opcode = 0; - u16 flags = 0; - __be16 protocol = skb->protocol; - struct vlan_ethhdr *vh; + struct qlcnic_skb_frag *nf = &pbuf->frag_array[0]; + int nr_frags = skb_shinfo(skb)->nr_frags; + int i; - if (protocol == cpu_to_be16(ETH_P_8021Q)) { - vh = (struct vlan_ethhdr *)skb->data; - protocol = vh->h_vlan_encapsulated_proto; - flags = FLAGS_VLAN_TAGGED; - qlcnic_set_tx_vlan_tci(first_desc, ntohs(vh->h_vlan_TCI)); - } else if (vlan_tx_tag_present(skb)) { - flags = FLAGS_VLAN_OOB; - qlcnic_set_tx_vlan_tci(first_desc, vlan_tx_tag_get(skb)); + for (i = 0; i < nr_frags; i++) { + nf = &pbuf->frag_array[i+1]; + pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); } - if (unlikely(adapter->pvid)) { - if (first_desc->vlan_TCI && - !(adapter->flags & QLCNIC_TAGGING_ENABLED)) - return -EIO; - if (first_desc->vlan_TCI && - (adapter->flags & QLCNIC_TAGGING_ENABLED)) - goto set_flags; - flags = FLAGS_VLAN_OOB; - qlcnic_set_tx_vlan_tci(first_desc, adapter->pvid); - } -set_flags: - qlcnic_set_tx_flags_opcode(first_desc, flags, opcode); - return 0; + nf = &pbuf->frag_array[0]; + pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); } static inline void @@ -2144,7 +2139,7 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) int i, k; u32 producer; - int frag_count, no_of_desc; + int frag_count; u32 num_txd = tx_ring->num_desc; if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { @@ -2161,12 +2156,8 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) frag_count = skb_shinfo(skb)->nr_frags + 1; - /* 4 fragments per cmd des */ - no_of_desc = (frag_count + 3) >> 2; - if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) { netif_stop_queue(netdev); - smp_mb(); if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) netif_start_queue(netdev); else { @@ -2183,9 +2174,6 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) first_desc = hwdesc = &tx_ring->desc_head[producer]; qlcnic_clear_cmddesc((u64 *)hwdesc); - if (qlcnic_check_tx_tagging(adapter, skb, first_desc)) - goto drop_packet; - if (qlcnic_map_tx_skb(pdev, skb, pbuf)) { adapter->stats.tx_dma_map_error++; goto drop_packet; @@ -2229,8 +2217,10 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } tx_ring->producer = get_next_index(producer, num_txd); + smp_mb(); - qlcnic_tso_check(netdev, tx_ring, first_desc, skb); + if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb))) + goto unwind_buff; if (qlcnic_mac_learn) qlcnic_send_filter(adapter, tx_ring, first_desc, skb); @@ -2242,6 +2232,8 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; +unwind_buff: + qlcnic_unmap_buffers(pdev, skb, pbuf); drop_packet: adapter->stats.txdropped++; dev_kfree_skb_any(skb); -- cgit v1.2.3-58-ga151 From b9796a14d9705c4be4a080a4fe39379a51681374 Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Fri, 1 Apr 2011 14:28:15 +0000 Subject: qlcnic: Changes to VLAN code Made changes to VLAN code comply with new VLAN infrastructure in kernel Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 4 +++- drivers/net/qlcnic/qlcnic_init.c | 15 +++++++------- drivers/net/qlcnic/qlcnic_main.c | 42 ++++++++++++++++++++++++---------------- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index a5b28d1475b1..be9c32944de5 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -29,6 +29,8 @@ #include #include +#include +#include #include "qlcnic_hdr.h" @@ -982,8 +984,8 @@ struct qlcnic_adapter { u8 mac_addr[ETH_ALEN]; u64 dev_rst_time; + unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)]; - struct vlan_group *vlgrp; struct qlcnic_npar_info *npars; struct qlcnic_eswitch *eswitch; struct qlcnic_nic_template *nic_ops; diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 476ea14c0ff3..74ec96da1762 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -1467,10 +1467,10 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter, skb->protocol = eth_type_trans(skb, netdev); - if ((vid != 0xffff) && adapter->vlgrp) - vlan_gro_receive(&sds_ring->napi, adapter->vlgrp, vid, skb); - else - napi_gro_receive(&sds_ring->napi, skb); + if (vid != 0xffff) + __vlan_hwaccel_put_tag(skb, vid); + + napi_gro_receive(&sds_ring->napi, skb); adapter->stats.rx_pkts++; adapter->stats.rxbytes += length; @@ -1552,10 +1552,9 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, length = skb->len; - if ((vid != 0xffff) && adapter->vlgrp) - vlan_hwaccel_receive_skb(skb, adapter->vlgrp, vid); - else - netif_receive_skb(skb); + if (vid != 0xffff) + __vlan_hwaccel_put_tag(skb, vid); + netif_receive_skb(skb); adapter->stats.lro_pkts++; adapter->stats.lrobytes += length; diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 3b740f55ca42..b75aef059adc 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -98,6 +97,9 @@ static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); static int qlcnicvf_start_firmware(struct qlcnic_adapter *); static void qlcnic_set_netdev_features(struct qlcnic_adapter *, struct qlcnic_esw_func_cfg *); +static void qlcnic_vlan_rx_add(struct net_device *, u16); +static void qlcnic_vlan_rx_del(struct net_device *, u16); + /* PCI Device ID Table */ #define ENTRY(device) \ {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \ @@ -317,13 +319,6 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p) return 0; } -static void qlcnic_vlan_rx_register(struct net_device *netdev, - struct vlan_group *grp) -{ - struct qlcnic_adapter *adapter = netdev_priv(netdev); - adapter->vlgrp = grp; -} - static const struct net_device_ops qlcnic_netdev_ops = { .ndo_open = qlcnic_open, .ndo_stop = qlcnic_close, @@ -334,7 +329,8 @@ static const struct net_device_ops qlcnic_netdev_ops = { .ndo_set_mac_address = qlcnic_set_mac, .ndo_change_mtu = qlcnic_change_mtu, .ndo_tx_timeout = qlcnic_tx_timeout, - .ndo_vlan_rx_register = qlcnic_vlan_rx_register, + .ndo_vlan_rx_add_vid = qlcnic_vlan_rx_add, + .ndo_vlan_rx_kill_vid = qlcnic_vlan_rx_del, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = qlcnic_poll_controller, #endif @@ -709,6 +705,22 @@ qlcnic_set_vlan_config(struct qlcnic_adapter *adapter, adapter->pvid = 0; } +static void +qlcnic_vlan_rx_add(struct net_device *netdev, u16 vid) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + set_bit(vid, adapter->vlans); +} + +static void +qlcnic_vlan_rx_del(struct net_device *netdev, u16 vid) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + + qlcnic_restore_indev_addr(netdev, NETDEV_DOWN); + clear_bit(vid, adapter->vlans); +} + static void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, struct qlcnic_esw_func_cfg *esw_cfg) @@ -755,7 +767,7 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter, features = (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_GRO); vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM); + NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_FILTER); if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) { features |= (NETIF_F_TSO | NETIF_F_TSO6); @@ -1448,7 +1460,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_GRO | NETIF_F_HW_VLAN_RX); netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM); + NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_FILTER); if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) { netdev->features |= (NETIF_F_TSO | NETIF_F_TSO6); @@ -4068,14 +4080,10 @@ qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event) qlcnic_config_indev_addr(adapter, netdev, event); - if (!adapter->vlgrp) - return; - - for (vid = 0; vid < VLAN_N_VID; vid++) { - dev = vlan_group_get_device(adapter->vlgrp, vid); + for_each_set_bit(vid, adapter->vlans, VLAN_N_VID) { + dev = vlan_find_dev(netdev, vid); if (!dev) continue; - qlcnic_config_indev_addr(adapter, dev, event); } } -- cgit v1.2.3-58-ga151 From 8816d0099b9c0f48452b69471c2f54037f7e0e3b Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Fri, 1 Apr 2011 14:28:21 +0000 Subject: qlcnic: Remove unused code Cleaned up unused codes for interrupt coalescence settings Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 56 ++++++++++++++----------------------- drivers/net/qlcnic/qlcnic_ethtool.c | 30 ++++++++------------ drivers/net/qlcnic/qlcnic_hw.c | 20 ++++++------- drivers/net/qlcnic/qlcnic_main.c | 21 ++++---------- 4 files changed, 46 insertions(+), 81 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index be9c32944de5..9d2e630c3895 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -391,6 +391,25 @@ struct qlcnic_rx_buffer { #define QLCNIC_GBE 0x01 #define QLCNIC_XGBE 0x02 +/* + * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is + * adjusted based on configured MTU. + */ +#define QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US 3 +#define QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS 256 + +#define QLCNIC_INTR_DEFAULT 0x04 +#define QLCNIC_CONFIG_INTR_COALESCE 3 + +struct qlcnic_nic_intr_coalesce { + u8 type; + u8 sts_ring_mask; + u16 rx_packets; + u16 rx_time_us; + u16 flag; + u32 timer_out; +}; + /* * One hardware_context{} per adapter * contains interrupt info as well shared hardware info. @@ -409,6 +428,8 @@ struct qlcnic_hardware_context { u8 linkup; u16 port_type; u16 board_type; + + struct qlcnic_nic_intr_coalesce coal; }; struct qlcnic_adapter_stats { @@ -721,40 +742,6 @@ struct qlcnic_mac_list_s { uint8_t mac_addr[ETH_ALEN+2]; }; -/* - * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is - * adjusted based on configured MTU. - */ -#define QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US 3 -#define QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS 256 -#define QLCNIC_DEFAULT_INTR_COALESCE_TX_PACKETS 64 -#define QLCNIC_DEFAULT_INTR_COALESCE_TX_TIME_US 4 - -#define QLCNIC_INTR_DEFAULT 0x04 - -union qlcnic_nic_intr_coalesce_data { - struct { - u16 rx_packets; - u16 rx_time_us; - u16 tx_packets; - u16 tx_time_us; - } data; - u64 word; -}; - -struct qlcnic_nic_intr_coalesce { - u16 stats_time_us; - u16 rate_sample_time; - u16 flags; - u16 rsvd_1; - u32 low_threshold; - u32 high_threshold; - union qlcnic_nic_intr_coalesce_data normal; - union qlcnic_nic_intr_coalesce_data low; - union qlcnic_nic_intr_coalesce_data high; - union qlcnic_nic_intr_coalesce_data irq; -}; - #define QLCNIC_HOST_REQUEST 0x13 #define QLCNIC_REQUEST 0x14 @@ -1002,7 +989,6 @@ struct qlcnic_adapter { struct delayed_work fw_work; - struct qlcnic_nic_intr_coalesce coal; struct qlcnic_filter_hash fhash; diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 7e53cad6be16..24a79a6fc73d 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -936,8 +936,8 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev, */ if (ethcoal->rx_coalesce_usecs > 0xffff || ethcoal->rx_max_coalesced_frames > 0xffff || - ethcoal->tx_coalesce_usecs > 0xffff || - ethcoal->tx_max_coalesced_frames > 0xffff || + ethcoal->tx_coalesce_usecs || + ethcoal->tx_max_coalesced_frames || ethcoal->rx_coalesce_usecs_irq || ethcoal->rx_max_coalesced_frames_irq || ethcoal->tx_coalesce_usecs_irq || @@ -959,21 +959,17 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev, if (!ethcoal->rx_coalesce_usecs || !ethcoal->rx_max_coalesced_frames) { - adapter->coal.flags = QLCNIC_INTR_DEFAULT; - adapter->coal.normal.data.rx_time_us = + adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT; + adapter->ahw->coal.rx_time_us = QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US; - adapter->coal.normal.data.rx_packets = + adapter->ahw->coal.rx_packets = QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS; } else { - adapter->coal.flags = 0; - adapter->coal.normal.data.rx_time_us = - ethcoal->rx_coalesce_usecs; - adapter->coal.normal.data.rx_packets = - ethcoal->rx_max_coalesced_frames; + adapter->ahw->coal.flag = 0; + adapter->ahw->coal.rx_time_us = ethcoal->rx_coalesce_usecs; + adapter->ahw->coal.rx_packets = + ethcoal->rx_max_coalesced_frames; } - adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs; - adapter->coal.normal.data.tx_packets = - ethcoal->tx_max_coalesced_frames; qlcnic_config_intr_coalesce(adapter); @@ -988,12 +984,8 @@ static int qlcnic_get_intr_coalesce(struct net_device *netdev, if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) return -EINVAL; - ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us; - ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us; - ethcoal->rx_max_coalesced_frames = - adapter->coal.normal.data.rx_packets; - ethcoal->tx_max_coalesced_frames = - adapter->coal.normal.data.tx_packets; + ethcoal->rx_coalesce_usecs = adapter->ahw->coal.rx_time_us; + ethcoal->rx_max_coalesced_frames = adapter->ahw->coal.rx_packets; return 0; } diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 7e3f52690e3f..3901be85dcac 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -532,33 +532,31 @@ void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter) } } -#define QLCNIC_CONFIG_INTR_COALESCE 3 - /* * Send the interrupt coalescing parameter set by ethtool to the card. */ int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter) { struct qlcnic_nic_req req; - u64 word[6]; - int rv, i; + int rv; memset(&req, 0, sizeof(struct qlcnic_nic_req)); req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); - word[0] = QLCNIC_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16); - req.req_hdr = cpu_to_le64(word[0]); - - memcpy(&word[0], &adapter->coal, sizeof(adapter->coal)); - for (i = 0; i < 6; i++) - req.words[i] = cpu_to_le64(word[i]); + req.req_hdr = cpu_to_le64(QLCNIC_CONFIG_INTR_COALESCE | + ((u64) adapter->portnum << 16)); + req.words[0] = cpu_to_le64(((u64) adapter->ahw->coal.flag) << 32); + req.words[2] = cpu_to_le64(adapter->ahw->coal.rx_packets | + ((u64) adapter->ahw->coal.rx_time_us) << 16); + req.words[5] = cpu_to_le64(adapter->ahw->coal.timer_out | + ((u64) adapter->ahw->coal.type) << 32 | + ((u64) adapter->ahw->coal.sts_ring_mask) << 40); rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); if (rv != 0) dev_err(&adapter->netdev->dev, "Could not send interrupt coalescing parameters\n"); - return rv; } diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index b75aef059adc..8bf9a968f7f2 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -1097,20 +1097,6 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter) } } -static void -qlcnic_init_coalesce_defaults(struct qlcnic_adapter *adapter) -{ - adapter->coal.flags = QLCNIC_INTR_DEFAULT; - adapter->coal.normal.data.rx_time_us = - QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US; - adapter->coal.normal.data.rx_packets = - QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS; - adapter->coal.normal.data.tx_time_us = - QLCNIC_DEFAULT_INTR_COALESCE_TX_TIME_US; - adapter->coal.normal.data.tx_packets = - QLCNIC_DEFAULT_INTR_COALESCE_TX_PACKETS; -} - static int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) { @@ -1244,8 +1230,6 @@ qlcnic_attach(struct qlcnic_adapter *adapter) goto err_out_free_hw; } - qlcnic_init_coalesce_defaults(adapter); - qlcnic_create_sysfs_entries(adapter); adapter->is_up = QLCNIC_ADAPTER_UP_MAGIC; @@ -1326,7 +1310,12 @@ static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter) kfree(adapter->ahw); adapter->ahw = NULL; err = -ENOMEM; + goto err_out; } + /* Initialize interrupt coalesce parameters */ + adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT; + adapter->ahw->coal.rx_time_us = QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US; + adapter->ahw->coal.rx_packets = QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS; err_out: return err; } -- cgit v1.2.3-58-ga151 From f8d54811cb125094769704722e4eda6610339b92 Mon Sep 17 00:00:00 2001 From: Sritej Velaga Date: Fri, 1 Apr 2011 14:28:26 +0000 Subject: qlcnic: Use flt method to determine flash fw region Use flash layout table to get flash fw starting address and its size. If that fails, use legacy method. Signed-off-by: Sritej Velaga Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 3 ++- drivers/net/qlcnic/qlcnic_init.c | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 9d2e630c3895..d9dd2c40c92f 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -292,6 +292,7 @@ struct uni_data_desc{ /* Flash Defines and Structures */ #define QLCNIC_FLT_LOCATION 0x3F1000 #define QLCNIC_FW_IMAGE_REGION 0x74 +#define QLCNIC_BOOTLD_REGION 0X72 struct qlcnic_flt_header { u16 version; u16 len; @@ -306,7 +307,7 @@ struct qlcnic_flt_entry { u8 reserved1; u32 size; u32 start_addr; - u32 end_add; + u32 end_addr; }; /* Magic number to let user know flash is programmed */ diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 74ec96da1762..4ec0eeb6bff9 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -1130,9 +1130,20 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter) } else { u64 data; u32 hi, lo; - - size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8; - flashaddr = QLCNIC_BOOTLD_START; + int ret; + struct qlcnic_flt_entry bootld_entry; + + ret = qlcnic_get_flt_entry(adapter, QLCNIC_BOOTLD_REGION, + &bootld_entry); + if (!ret) { + size = bootld_entry.size / 8; + flashaddr = bootld_entry.start_addr; + } else { + size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8; + flashaddr = QLCNIC_BOOTLD_START; + dev_info(&pdev->dev, + "using legacy method to get flash fw region"); + } for (i = 0; i < size; i++) { if (qlcnic_rom_fast_read(adapter, -- cgit v1.2.3-58-ga151 From b56421d0b7527f8ecea3de030cf508468fdc9ba1 Mon Sep 17 00:00:00 2001 From: Rajesh Borundia Date: Fri, 1 Apr 2011 14:28:31 +0000 Subject: qlcnic: Fix LRO disable o In dev->open LRO was enabled by default, enable it depending upon netdev->features , kernel may have disabled it. o Configure LRO when interface is up. Signed-off-by: Rajesh Borundia Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_ethtool.c | 26 ++++++++++++++++---------- drivers/net/qlcnic/qlcnic_hw.c | 6 ++++++ drivers/net/qlcnic/qlcnic_main.c | 3 ++- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 24a79a6fc73d..6be4d5a26c7c 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -998,22 +998,28 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data) if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO)) return -EINVAL; - if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)) - return -EINVAL; + if (data & ETH_FLAG_LRO) { - if (!adapter->rx_csum) { - dev_info(&adapter->pdev->dev, "rx csum is off, " - "cannot toggle lro\n"); - return -EINVAL; - } + if (netdev->features & NETIF_F_LRO) + return 0; - if ((data & ETH_FLAG_LRO) && (netdev->features & NETIF_F_LRO)) - return 0; + if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)) + return -EINVAL; + + if (!adapter->rx_csum) { + dev_info(&adapter->pdev->dev, "rx csum is off, " + "cannot toggle lro\n"); + return -EINVAL; + } - if (data & ETH_FLAG_LRO) { hw_lro = QLCNIC_LRO_ENABLED; netdev->features |= NETIF_F_LRO; + } else { + + if (!(netdev->features & NETIF_F_LRO)) + return 0; + hw_lro = 0; netdev->features &= ~NETIF_F_LRO; } diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 3901be85dcac..498cca92126a 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -566,6 +566,9 @@ int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable) u64 word; int rv; + if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) + return 0; + memset(&req, 0, sizeof(struct qlcnic_nic_req)); req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); @@ -711,6 +714,9 @@ int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter) u64 word; int rv; + if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) + return 0; + memset(&req, 0, sizeof(struct qlcnic_nic_req)); req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 8bf9a968f7f2..7f9edb2f1474 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -773,7 +773,8 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter, features |= (NETIF_F_TSO | NETIF_F_TSO6); vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6); } - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) + + if (netdev->features & NETIF_F_LRO) features |= NETIF_F_LRO; if (esw_cfg->offload_flags & BIT_0) { -- cgit v1.2.3-58-ga151 From 191350e7887aa6d843f1097fc1de06cb59eb6ac1 Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Fri, 1 Apr 2011 14:28:36 +0000 Subject: qlcnic: Update version number to 5.0.16 Bumped up version number to 5.0.16 Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index d9dd2c40c92f..dc6f7c69acac 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -36,8 +36,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 0 -#define _QLCNIC_LINUX_SUBVERSION 15 -#define QLCNIC_LINUX_VERSIONID "5.0.15" +#define _QLCNIC_LINUX_SUBVERSION 16 +#define QLCNIC_LINUX_VERSIONID "5.0.16" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) -- cgit v1.2.3-58-ga151 From 74e532ff3c634f20ee2eefe3f8f0083ea547c74c Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 08:43:41 +0000 Subject: sky2: support ethtool set_phys_id Use ethtool set_phys_id to control LED. Fixes issues with RTNL being held for extended periods. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 2a91868788f7..afc925a340d1 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3826,23 +3826,24 @@ static void sky2_led(struct sky2_port *sky2, enum led_mode mode) } /* blink LED's for finding board */ -static int sky2_phys_id(struct net_device *dev, u32 data) +static int sky2_set_phys_id(struct net_device *dev, + enum ethtool_phys_id_state state) { struct sky2_port *sky2 = netdev_priv(dev); - unsigned int i; - - if (data == 0) - data = UINT_MAX; - for (i = 0; i < data; i++) { + switch (state) { + case ETHTOOL_ID_ACTIVE: + return -EINVAL; + case ETHTOOL_ID_INACTIVE: + sky2_led(sky2, MO_LED_NORM); + break; + case ETHTOOL_ID_ON: sky2_led(sky2, MO_LED_ON); - if (msleep_interruptible(500)) - break; + break; + case ETHTOOL_ID_OFF: sky2_led(sky2, MO_LED_OFF); - if (msleep_interruptible(500)) - break; + break; } - sky2_led(sky2, MO_LED_NORM); return 0; } @@ -4269,7 +4270,7 @@ static const struct ethtool_ops sky2_ethtool_ops = { .set_ringparam = sky2_set_ringparam, .get_pauseparam = sky2_get_pauseparam, .set_pauseparam = sky2_set_pauseparam, - .phys_id = sky2_phys_id, + .set_phys_id = sky2_set_phys_id, .get_sset_count = sky2_get_sset_count, .get_ethtool_stats = sky2_get_ethtool_stats, .set_flags = sky2_set_flags, -- cgit v1.2.3-58-ga151 From a5b9f41c228f93d368ab0f292d890ea7143ca5aa Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 08:43:42 +0000 Subject: skge: implement set_phys_id Implement set_phys_id led control on SysKonnect board. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/skge.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 35b28f42d208..e579ff7579ad 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -786,28 +786,27 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) } /* blink LED's for finding board */ -static int skge_phys_id(struct net_device *dev, u32 data) +static int skge_set_phys_id(struct net_device *dev, + enum ethtool_phys_id_state state) { struct skge_port *skge = netdev_priv(dev); - unsigned long ms; - enum led_mode mode = LED_MODE_TST; - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT / HZ) * 1000; - else - ms = data * 1000; + switch (state) { + case ETHTOOL_ID_ACTIVE: + return -EINVAL; - while (ms > 0) { - skge_led(skge, mode); - mode ^= LED_MODE_TST; + case ETHTOOL_ID_ON: + skge_led(skge, LED_MODE_TST); + break; - if (msleep_interruptible(BLINK_MS)) - break; - ms -= BLINK_MS; - } + case ETHTOOL_ID_OFF: + skge_led(skge, LED_MODE_OFF); + break; - /* back to regular LED state */ - skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF); + case ETHTOOL_ID_INACTIVE: + /* back to regular LED state */ + skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF); + } return 0; } @@ -930,7 +929,7 @@ static const struct ethtool_ops skge_ethtool_ops = { .get_rx_csum = skge_get_rx_csum, .set_rx_csum = skge_set_rx_csum, .get_strings = skge_get_strings, - .phys_id = skge_phys_id, + .set_phys_id = skge_set_phys_id, .get_sset_count = skge_get_sset_count, .get_ethtool_stats = skge_get_ethtool_stats, }; -- cgit v1.2.3-58-ga151 From 81b8709c25e8c8f56224a24d860de7b77a772e83 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 08:43:50 +0000 Subject: tg3: implement ethtool set_phys_id Implement control of LED via set_phys_id. Note: since PHY is powered off if device is down, this board only allows blinking if device is up. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/tg3.c | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f944c6b97dd6..d37ae8747ad1 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10341,35 +10341,38 @@ static void tg3_get_strings(struct net_device *dev, u32 stringset, u8 *buf) } } -static int tg3_phys_id(struct net_device *dev, u32 data) +static int tg3_set_phys_id(struct net_device *dev, + enum ethtool_phys_id_state state) { struct tg3 *tp = netdev_priv(dev); - int i; if (!netif_running(tp->dev)) return -EAGAIN; - if (data == 0) - data = UINT_MAX / 2; + switch (state) { + case ETHTOOL_ID_ACTIVE: + return -EINVAL; - for (i = 0; i < (data * 2); i++) { - if ((i % 2) == 0) - tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE | - LED_CTRL_1000MBPS_ON | - LED_CTRL_100MBPS_ON | - LED_CTRL_10MBPS_ON | - LED_CTRL_TRAFFIC_OVERRIDE | - LED_CTRL_TRAFFIC_BLINK | - LED_CTRL_TRAFFIC_LED); + case ETHTOOL_ID_ON: + tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE | + LED_CTRL_1000MBPS_ON | + LED_CTRL_100MBPS_ON | + LED_CTRL_10MBPS_ON | + LED_CTRL_TRAFFIC_OVERRIDE | + LED_CTRL_TRAFFIC_BLINK | + LED_CTRL_TRAFFIC_LED); + break; - else - tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE | - LED_CTRL_TRAFFIC_OVERRIDE); + case ETHTOOL_ID_OFF: + tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE | + LED_CTRL_TRAFFIC_OVERRIDE); + break; - if (msleep_interruptible(500)) - break; + case ETHTOOL_ID_INACTIVE: + tw32(MAC_LED_CTRL, tp->led_ctrl); + break; } - tw32(MAC_LED_CTRL, tp->led_ctrl); + return 0; } @@ -11394,7 +11397,7 @@ static const struct ethtool_ops tg3_ethtool_ops = { .set_tso = tg3_set_tso, .self_test = tg3_self_test, .get_strings = tg3_get_strings, - .phys_id = tg3_phys_id, + .set_phys_id = tg3_set_phys_id, .get_ethtool_stats = tg3_get_ethtool_stats, .get_coalesce = tg3_get_coalesce, .set_coalesce = tg3_set_coalesce, -- cgit v1.2.3-58-ga151 From 12fcf941674fd781117a56f998d2bb28b4bc4cf1 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 08:43:51 +0000 Subject: cxgb3: implement set_phys_id Implement new ethtool set_phys_id on Chelsio cxgb3 board. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/cxgb3/cxgb3_main.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 910893143295..802c7a7c3b25 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1749,23 +1749,26 @@ static int restart_autoneg(struct net_device *dev) return 0; } -static int cxgb3_phys_id(struct net_device *dev, u32 data) +static int set_phys_id(struct net_device *dev, + enum ethtool_phys_id_state state) { struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; - int i; - if (data == 0) - data = 2; + switch (state) { + case ETHTOOL_ID_ACTIVE: + return -EINVAL; + + case ETHTOOL_ID_OFF: + t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, 0); + break; - for (i = 0; i < data * 2; i++) { + case ETHTOOL_ID_ON: + case ETHTOOL_ID_INACTIVE: t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, - (i & 1) ? F_GPIO0_OUT_VAL : 0); - if (msleep_interruptible(500)) - break; - } - t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, F_GPIO0_OUT_VAL); + } + return 0; } @@ -2107,7 +2110,7 @@ static const struct ethtool_ops cxgb_ethtool_ops = { .set_sg = ethtool_op_set_sg, .get_link = ethtool_op_get_link, .get_strings = get_strings, - .phys_id = cxgb3_phys_id, + .set_phys_id = set_phys_id, .nway_reset = restart_autoneg, .get_sset_count = get_sset_count, .get_ethtool_stats = get_stats, -- cgit v1.2.3-58-ga151 From 6d8a7e6f52b0bf646739f2d4bad4643c64977b2a Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 11:06:35 +0000 Subject: vxge: convert to set_phys_id Also fix up incorrect docbook comment Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/vxge/vxge-ethtool.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/net/vxge/vxge-ethtool.c b/drivers/net/vxge/vxge-ethtool.c index c5eb034107fd..43c458323f83 100644 --- a/drivers/net/vxge/vxge-ethtool.c +++ b/drivers/net/vxge/vxge-ethtool.c @@ -134,22 +134,29 @@ static void vxge_ethtool_gregs(struct net_device *dev, /** * vxge_ethtool_idnic - To physically identify the nic on the system. * @dev : device pointer. - * @id : pointer to the structure with identification parameters given by - * ethtool. + * @state : requested LED state * * Used to physically identify the NIC on the system. - * The Link LED will blink for a time specified by the user. - * Return value: * 0 on success */ -static int vxge_ethtool_idnic(struct net_device *dev, u32 data) +static int vxge_ethtool_idnic(struct net_device *dev, + enum ethtool_phys_id_state state) { struct vxgedev *vdev = netdev_priv(dev); struct __vxge_hw_device *hldev = vdev->devh; - vxge_hw_device_flick_link_led(hldev, VXGE_FLICKER_ON); - msleep_interruptible(data ? (data * HZ) : VXGE_MAX_FLICKER_TIME); - vxge_hw_device_flick_link_led(hldev, VXGE_FLICKER_OFF); + switch (state) { + case ETHTOOL_ID_ACTIVE: + vxge_hw_device_flick_link_led(hldev, VXGE_FLICKER_ON); + break; + + case ETHTOOL_ID_INACTIVE: + vxge_hw_device_flick_link_led(hldev, VXGE_FLICKER_OFF); + break; + + default: + return -EINVAL; + } return 0; } @@ -1183,7 +1190,7 @@ static const struct ethtool_ops vxge_ethtool_ops = { .get_tso = ethtool_op_get_tso, .set_tso = vxge_ethtool_op_set_tso, .get_strings = vxge_ethtool_get_strings, - .phys_id = vxge_ethtool_idnic, + .set_phys_id = vxge_ethtool_idnic, .get_sset_count = vxge_ethtool_get_sset_count, .get_ethtool_stats = vxge_get_ethtool_stats, .set_flags = vxge_set_flags, -- cgit v1.2.3-58-ga151 From 2e17e1aa80e914acd8a31a41b9bf1173186a976a Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 11:06:36 +0000 Subject: bnx2: convert to set_phys_id In this case, need to add element to device private to hold original led state. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 56 ++++++++++++++++++++++++++---------------------------- drivers/net/bnx2.h | 1 + 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 8e6d618b5305..05ddfb18d5bf 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7495,41 +7495,39 @@ bnx2_get_ethtool_stats(struct net_device *dev, } static int -bnx2_phys_id(struct net_device *dev, u32 data) +bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state) { struct bnx2 *bp = netdev_priv(dev); - int i; - u32 save; - bnx2_set_power_state(bp, PCI_D0); + switch (state) { + case ETHTOOL_ID_ACTIVE: + bnx2_set_power_state(bp, PCI_D0); - if (data == 0) - data = 2; + bp->leds_save = REG_RD(bp, BNX2_MISC_CFG); + REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC); + return -EINVAL; - save = REG_RD(bp, BNX2_MISC_CFG); - REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC); + case ETHTOOL_ID_ON: + REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE | + BNX2_EMAC_LED_1000MB_OVERRIDE | + BNX2_EMAC_LED_100MB_OVERRIDE | + BNX2_EMAC_LED_10MB_OVERRIDE | + BNX2_EMAC_LED_TRAFFIC_OVERRIDE | + BNX2_EMAC_LED_TRAFFIC); + break; - for (i = 0; i < (data * 2); i++) { - if ((i % 2) == 0) { - REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE); - } - else { - REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE | - BNX2_EMAC_LED_1000MB_OVERRIDE | - BNX2_EMAC_LED_100MB_OVERRIDE | - BNX2_EMAC_LED_10MB_OVERRIDE | - BNX2_EMAC_LED_TRAFFIC_OVERRIDE | - BNX2_EMAC_LED_TRAFFIC); - } - msleep_interruptible(500); - if (signal_pending(current)) - break; - } - REG_WR(bp, BNX2_EMAC_LED, 0); - REG_WR(bp, BNX2_MISC_CFG, save); + case ETHTOOL_ID_OFF: + REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE); + break; - if (!netif_running(dev)) - bnx2_set_power_state(bp, PCI_D3hot); + case ETHTOOL_ID_INACTIVE: + REG_WR(bp, BNX2_EMAC_LED, 0); + REG_WR(bp, BNX2_MISC_CFG, bp->leds_save); + + if (!netif_running(dev)) + bnx2_set_power_state(bp, PCI_D3hot); + break; + } return 0; } @@ -7602,7 +7600,7 @@ static const struct ethtool_ops bnx2_ethtool_ops = { .set_tso = bnx2_set_tso, .self_test = bnx2_self_test, .get_strings = bnx2_get_strings, - .phys_id = bnx2_phys_id, + .set_phys_id = bnx2_set_phys_id, .get_ethtool_stats = bnx2_get_ethtool_stats, .get_sset_count = bnx2_get_sset_count, .set_flags = bnx2_set_flags, diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 68020451dc4f..91e83562238e 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6922,6 +6922,7 @@ struct bnx2 { u8 num_tx_rings; u8 num_rx_rings; + u32 leds_save; u32 idle_chk_status_idx; #ifdef BCM_CNIC -- cgit v1.2.3-58-ga151 From 32d3613475d8c7d2170313b9105499dece6a3735 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 11:06:37 +0000 Subject: bnx2x: convert to set_phys_id Also cleanup error codes to no lie about things that driver doesn't support. If device is down report -EAGAIN (same as Broadcom), and if port doesn't blink then error as well. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_ethtool.c | 44 ++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index f5050155c6b5..147999459df5 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c @@ -2097,36 +2097,38 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev, } } -static int bnx2x_phys_id(struct net_device *dev, u32 data) +static int bnx2x_set_phys_id(struct net_device *dev, + enum ethtool_phys_id_state state) { struct bnx2x *bp = netdev_priv(dev); - int i; if (!netif_running(dev)) - return 0; + return -EAGAIN; if (!bp->port.pmf) - return 0; + return -EOPNOTSUPP; - if (data == 0) - data = 2; + switch (state) { + case ETHTOOL_ID_ACTIVE: + return -EINVAL; - for (i = 0; i < (data * 2); i++) { - if ((i % 2) == 0) - bnx2x_set_led(&bp->link_params, &bp->link_vars, - LED_MODE_OPER, SPEED_1000); - else - bnx2x_set_led(&bp->link_params, &bp->link_vars, - LED_MODE_OFF, 0); + case ETHTOOL_ID_ON: + bnx2x_set_led(&bp->link_params, &bp->link_vars, + LED_MODE_OPER, SPEED_1000); + break; - msleep_interruptible(500); - if (signal_pending(current)) - break; - } + case ETHTOOL_ID_OFF: + bnx2x_set_led(&bp->link_params, &bp->link_vars, + LED_MODE_OFF, 0); - if (bp->link_vars.link_up) - bnx2x_set_led(&bp->link_params, &bp->link_vars, LED_MODE_OPER, - bp->link_vars.line_speed); + break; + + case ETHTOOL_ID_INACTIVE: + if (bp->link_vars.link_up) + bnx2x_set_led(&bp->link_params, &bp->link_vars, + LED_MODE_OPER, + bp->link_vars.line_speed); + } return 0; } @@ -2218,7 +2220,7 @@ static const struct ethtool_ops bnx2x_ethtool_ops = { .self_test = bnx2x_self_test, .get_sset_count = bnx2x_get_sset_count, .get_strings = bnx2x_get_strings, - .phys_id = bnx2x_phys_id, + .set_phys_id = bnx2x_set_phys_id, .get_ethtool_stats = bnx2x_get_ethtool_stats, .get_rxnfc = bnx2x_get_rxnfc, .get_rxfh_indir = bnx2x_get_rxfh_indir, -- cgit v1.2.3-58-ga151 From 1a64246913849b0cef0be88c23381468ce169ab6 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 11:06:40 +0000 Subject: benet: convert to set_phys_id Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 1 + drivers/net/benet/be_ethtool.c | 38 +++++++++++++++++++++----------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 3937bca3d431..0899d9122278 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -313,6 +313,7 @@ struct be_adapter { char fw_ver[FW_VER_LEN]; u32 if_handle; /* Used to configure filtering */ u32 pmac_id; /* MAC addr handle used by BE card */ + u32 beacon_state; /* for set_phys_id */ bool eeh_err; bool link_up; diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 575ac659ceb4..a665697df824 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -526,29 +526,33 @@ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) } static int -be_phys_id(struct net_device *netdev, u32 data) +be_set_phys_id(struct net_device *netdev, + enum ethtool_phys_id_state state) { struct be_adapter *adapter = netdev_priv(netdev); - int status; - u32 cur; - - be_cmd_get_beacon_state(adapter, adapter->hba_port_num, &cur); - if (cur == BEACON_STATE_ENABLED) - return 0; + switch (state) { + case ETHTOOL_ID_ACTIVE: + be_cmd_get_beacon_state(adapter, adapter->hba_port_num, + &adapter->beacon_state); + return -EINVAL; - if (data < 2) - data = 2; + case ETHTOOL_ID_ON: + be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, + BEACON_STATE_ENABLED); + break; - status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, - BEACON_STATE_ENABLED); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(data*HZ); + case ETHTOOL_ID_OFF: + be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, + BEACON_STATE_DISABLED); + break; - status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, - BEACON_STATE_DISABLED); + case ETHTOOL_ID_INACTIVE: + be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, + adapter->beacon_state); + } - return status; + return 0; } static bool @@ -753,7 +757,7 @@ const struct ethtool_ops be_ethtool_ops = { .get_tso = ethtool_op_get_tso, .set_tso = ethtool_op_set_tso, .get_strings = be_get_stat_strings, - .phys_id = be_phys_id, + .set_phys_id = be_set_phys_id, .get_sset_count = be_get_sset_count, .get_ethtool_stats = be_get_ethtool_stats, .get_regs_len = be_get_reg_len, -- cgit v1.2.3-58-ga151 From 9871acf67c9af89c1e17aee907a3f36e88ccfb67 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 11:06:41 +0000 Subject: pcnet32: convert to set_phys_id Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/pcnet32.c | 74 +++++++++++++++++++-------------------------------- 1 file changed, 28 insertions(+), 46 deletions(-) diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index aee3bb0358bf..eb7ac4e48c71 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -295,12 +295,14 @@ struct pcnet32_private { struct net_device *next; struct mii_if_info mii_if; struct timer_list watchdog_timer; - struct timer_list blink_timer; u32 msg_enable; /* debug message level */ /* each bit indicates an available PHY */ u32 phymask; unsigned short chip_version; /* which variant this is */ + + /* saved registers during ethtool blink */ + u16 save_regs[4]; }; static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *); @@ -324,8 +326,6 @@ static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits); static void pcnet32_ethtool_test(struct net_device *dev, struct ethtool_test *eth_test, u64 * data); static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1); -static int pcnet32_phys_id(struct net_device *dev, u32 data); -static void pcnet32_led_blink_callback(struct net_device *dev); static int pcnet32_get_regs_len(struct net_device *dev); static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *ptr); @@ -1022,7 +1022,8 @@ clean_up: return rc; } /* end pcnet32_loopback_test */ -static void pcnet32_led_blink_callback(struct net_device *dev) +static int pcnet32_set_phys_id(struct net_device *dev, + enum ethtool_phys_id_state state) { struct pcnet32_private *lp = netdev_priv(dev); struct pcnet32_access *a = &lp->a; @@ -1030,50 +1031,31 @@ static void pcnet32_led_blink_callback(struct net_device *dev) unsigned long flags; int i; - spin_lock_irqsave(&lp->lock, flags); - for (i = 4; i < 8; i++) - a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000); - spin_unlock_irqrestore(&lp->lock, flags); - - mod_timer(&lp->blink_timer, PCNET32_BLINK_TIMEOUT); -} + switch (state) { + case ETHTOOL_ID_ACTIVE: + /* Save the current value of the bcrs */ + spin_lock_irqsave(&lp->lock, flags); + for (i = 4; i < 8; i++) + lp->save_regs[i - 4] = a->read_bcr(ioaddr, i); + spin_unlock_irqrestore(&lp->lock, flags); + return -EINVAL; -static int pcnet32_phys_id(struct net_device *dev, u32 data) -{ - struct pcnet32_private *lp = netdev_priv(dev); - struct pcnet32_access *a = &lp->a; - ulong ioaddr = dev->base_addr; - unsigned long flags; - int i, regs[4]; + case ETHTOOL_ID_ON: + case ETHTOOL_ID_OFF: + /* Blink the led */ + spin_lock_irqsave(&lp->lock, flags); + for (i = 4; i < 8; i++) + a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000); + spin_unlock_irqrestore(&lp->lock, flags); + break; - if (!lp->blink_timer.function) { - init_timer(&lp->blink_timer); - lp->blink_timer.function = (void *)pcnet32_led_blink_callback; - lp->blink_timer.data = (unsigned long)dev; + case ETHTOOL_ID_INACTIVE: + /* Restore the original value of the bcrs */ + spin_lock_irqsave(&lp->lock, flags); + for (i = 4; i < 8; i++) + a->write_bcr(ioaddr, i, lp->save_regs[i - 4]); + spin_unlock_irqrestore(&lp->lock, flags); } - - /* Save the current value of the bcrs */ - spin_lock_irqsave(&lp->lock, flags); - for (i = 4; i < 8; i++) - regs[i - 4] = a->read_bcr(ioaddr, i); - spin_unlock_irqrestore(&lp->lock, flags); - - mod_timer(&lp->blink_timer, jiffies); - set_current_state(TASK_INTERRUPTIBLE); - - /* AV: the limit here makes no sense whatsoever */ - if ((!data) || (data > (u32) (MAX_SCHEDULE_TIMEOUT / HZ))) - data = (u32) (MAX_SCHEDULE_TIMEOUT / HZ); - - msleep_interruptible(data * 1000); - del_timer_sync(&lp->blink_timer); - - /* Restore the original value of the bcrs */ - spin_lock_irqsave(&lp->lock, flags); - for (i = 4; i < 8; i++) - a->write_bcr(ioaddr, i, regs[i - 4]); - spin_unlock_irqrestore(&lp->lock, flags); - return 0; } @@ -1450,7 +1432,7 @@ static const struct ethtool_ops pcnet32_ethtool_ops = { .set_ringparam = pcnet32_set_ringparam, .get_strings = pcnet32_get_strings, .self_test = pcnet32_ethtool_test, - .phys_id = pcnet32_phys_id, + .set_phys_id = pcnet32_set_phys_id, .get_regs_len = pcnet32_get_regs_len, .get_regs = pcnet32_get_regs, .get_sset_count = pcnet32_get_sset_count, -- cgit v1.2.3-58-ga151 From 7bc93714042418cbc4ca89c51d3ab448ea3ef2fe Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 12:31:19 +0000 Subject: niu: convert to new ethtool set_phys_id Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/niu.c | 29 ++++++++++++++++------------- drivers/net/niu.h | 1 + 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 681a42ca5c51..ab4e7dd82d0b 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -7888,28 +7888,31 @@ static void niu_force_led(struct niu *np, int on) nw64_mac(reg, val); } -static int niu_phys_id(struct net_device *dev, u32 data) +static int niu_set_phys_id(struct net_device *dev, + enum ethtool_phys_id_state state) + { struct niu *np = netdev_priv(dev); - u64 orig_led_state; - int i; if (!netif_running(dev)) return -EAGAIN; - if (data == 0) - data = 2; + switch (state) { + case ETHTOOL_ID_ACTIVE: + np->orig_led_state = niu_led_state_save(np); + return -EINVAL; - orig_led_state = niu_led_state_save(np); - for (i = 0; i < (data * 2); i++) { - int on = ((i % 2) == 0); + case ETHTOOL_ID_ON: + niu_force_led(np, 1); + break; - niu_force_led(np, on); + case ETHTOOL_ID_OFF: + niu_force_led(np, 0); + break; - if (msleep_interruptible(500)) - break; + case ETHTOOL_ID_INACTIVE: + niu_led_state_restore(np, np->orig_led_state); } - niu_led_state_restore(np, orig_led_state); return 0; } @@ -7932,7 +7935,7 @@ static const struct ethtool_ops niu_ethtool_ops = { .get_strings = niu_get_strings, .get_sset_count = niu_get_sset_count, .get_ethtool_stats = niu_get_ethtool_stats, - .phys_id = niu_phys_id, + .set_phys_id = niu_set_phys_id, .get_rxnfc = niu_get_nfc, .set_rxnfc = niu_set_nfc, .set_flags = niu_set_flags, diff --git a/drivers/net/niu.h b/drivers/net/niu.h index a41fa8ebe05f..51e177e1860d 100644 --- a/drivers/net/niu.h +++ b/drivers/net/niu.h @@ -3279,6 +3279,7 @@ struct niu { unsigned long xpcs_off; struct timer_list timer; + u64 orig_led_state; const struct niu_phy_ops *phy_ops; int phy_addr; -- cgit v1.2.3-58-ga151 From 034e345081cfb442abeb0e00fa26edeedb5ba96a Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 4 Apr 2011 15:09:25 +0000 Subject: s2io: convert to set_phys_id (v2) Convert to new ethtool set physical id model. Remove no longer used timer, and fix docbook comment. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/s2io.c | 86 ++++++++++++++++++++++++++---------------------------- drivers/net/s2io.h | 3 -- 2 files changed, 41 insertions(+), 48 deletions(-) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 356e74d20b80..cae08edb833e 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -5484,83 +5484,79 @@ static void s2io_ethtool_gregs(struct net_device *dev, } } -/** - * s2io_phy_id - timer function that alternates adapter LED. - * @data : address of the private member of the device structure, which - * is a pointer to the s2io_nic structure, provided as an u32. - * Description: This is actually the timer function that alternates the - * adapter LED bit of the adapter control bit to set/reset every time on - * invocation. The timer is set for 1/2 a second, hence tha NIC blinks - * once every second. +/* + * s2io_set_led - control NIC led */ -static void s2io_phy_id(unsigned long data) +static void s2io_set_led(struct s2io_nic *sp, bool on) { - struct s2io_nic *sp = (struct s2io_nic *)data; struct XENA_dev_config __iomem *bar0 = sp->bar0; - u64 val64 = 0; - u16 subid; + u16 subid = sp->pdev->subsystem_device; + u64 val64; - subid = sp->pdev->subsystem_device; if ((sp->device_type == XFRAME_II_DEVICE) || ((subid & 0xFF) >= 0x07)) { val64 = readq(&bar0->gpio_control); - val64 ^= GPIO_CTRL_GPIO_0; + if (on) + val64 |= GPIO_CTRL_GPIO_0; + else + val64 &= ~GPIO_CTRL_GPIO_0; + writeq(val64, &bar0->gpio_control); } else { val64 = readq(&bar0->adapter_control); - val64 ^= ADAPTER_LED_ON; + if (on) + val64 |= ADAPTER_LED_ON; + else + val64 &= ~ADAPTER_LED_ON; + writeq(val64, &bar0->adapter_control); } - mod_timer(&sp->id_timer, jiffies + HZ / 2); } /** - * s2io_ethtool_idnic - To physically identify the nic on the system. - * @sp : private member of the device structure, which is a pointer to the - * s2io_nic structure. - * @id : pointer to the structure with identification parameters given by - * ethtool. + * s2io_ethtool_set_led - To physically identify the nic on the system. + * @dev : network device + * @state: led setting + * * Description: Used to physically identify the NIC on the system. * The Link LED will blink for a time specified by the user for * identification. * NOTE: The Link has to be Up to be able to blink the LED. Hence * identification is possible only if it's link is up. - * Return value: - * int , returns 0 on success */ -static int s2io_ethtool_idnic(struct net_device *dev, u32 data) +static int s2io_ethtool_set_led(struct net_device *dev, + enum ethtool_phys_id_state state) { - u64 val64 = 0, last_gpio_ctrl_val; struct s2io_nic *sp = netdev_priv(dev); struct XENA_dev_config __iomem *bar0 = sp->bar0; - u16 subid; + u16 subid = sp->pdev->subsystem_device; - subid = sp->pdev->subsystem_device; - last_gpio_ctrl_val = readq(&bar0->gpio_control); if ((sp->device_type == XFRAME_I_DEVICE) && ((subid & 0xFF) < 0x07)) { - val64 = readq(&bar0->adapter_control); + u64 val64 = readq(&bar0->adapter_control); if (!(val64 & ADAPTER_CNTL_EN)) { pr_err("Adapter Link down, cannot blink LED\n"); - return -EFAULT; + return -EAGAIN; } } - if (sp->id_timer.function == NULL) { - init_timer(&sp->id_timer); - sp->id_timer.function = s2io_phy_id; - sp->id_timer.data = (unsigned long)sp; - } - mod_timer(&sp->id_timer, jiffies); - if (data) - msleep_interruptible(data * HZ); - else - msleep_interruptible(MAX_FLICKER_TIME); - del_timer_sync(&sp->id_timer); - if (CARDS_WITH_FAULTY_LINK_INDICATORS(sp->device_type, subid)) { - writeq(last_gpio_ctrl_val, &bar0->gpio_control); - last_gpio_ctrl_val = readq(&bar0->gpio_control); + switch (state) { + case ETHTOOL_ID_ACTIVE: + sp->adapt_ctrl_org = readq(&bar0->gpio_control); + return -EINVAL; + + case ETHTOOL_ID_ON: + s2io_set_led(sp, true); + break; + + case ETHTOOL_ID_OFF: + s2io_set_led(sp, false); + break; + + case ETHTOOL_ID_INACTIVE: + if (CARDS_WITH_FAULTY_LINK_INDICATORS(sp->device_type, subid)) + writeq(sp->adapt_ctrl_org, &bar0->gpio_control); } return 0; @@ -6776,7 +6772,7 @@ static const struct ethtool_ops netdev_ethtool_ops = { .set_ufo = ethtool_op_set_ufo, .self_test = s2io_ethtool_test, .get_strings = s2io_ethtool_get_strings, - .phys_id = s2io_ethtool_idnic, + .set_phys_id = s2io_ethtool_set_led, .get_ethtool_stats = s2io_get_ethtool_stats, .get_sset_count = s2io_get_sset_count, }; diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 7d160306b651..6b5c0231225c 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -893,9 +893,6 @@ struct s2io_nic { u16 all_multi_pos; u16 promisc_flg; - /* Id timer, used to blink NIC to physically identify NIC. */ - struct timer_list id_timer; - /* Restart timer, used to restart NIC if the device is stuck and * a schedule task that will set the correct Link state once the * NIC's PHY has stabilized after a state change. -- cgit v1.2.3-58-ga151 From 17938a6983d634a909d9779143a8dc2922720de5 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Sun, 3 Apr 2011 22:26:24 +0000 Subject: Signed bit field; int have_hotplug_status_watch:1 Fixes error from sparse: CHECK drivers/net/xen-netback/xenbus.c drivers/net/xen-netback/xenbus.c:29:40: error: dubious one-bit signed bitfield int have_hotplug_status_watch:1; Reported-by: Dr. David Alan Gilbert Signed-off-by: Ian Campbell Signed-off-by: David S. Miller --- drivers/net/xen-netback/xenbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 22b8c3505991..1ce729d6af75 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -26,7 +26,7 @@ struct backend_info { struct xenvif *vif; enum xenbus_state frontend_state; struct xenbus_watch hotplug_status_watch; - int have_hotplug_status_watch:1; + u8 have_hotplug_status_watch:1; }; static int connect_rings(struct backend_info *); -- cgit v1.2.3-58-ga151 From 1f90d6657c1ce2eaa4c7fbd1fb36738542f2b650 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Wed, 6 Apr 2011 10:58:37 +0000 Subject: capi: Perform scheduled capifs removal udev fully replaces this special file system that only contains CAPI NCCI TTY device nodes. User space (pppdcapiplugin) works without noticing the difference. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- Documentation/feature-removal-schedule.txt | 10 -- drivers/isdn/capi/Kconfig | 15 -- drivers/isdn/capi/Makefile | 1 - drivers/isdn/capi/capi.c | 24 +-- drivers/isdn/capi/capifs.c | 239 ----------------------------- drivers/isdn/capi/capifs.h | 28 ---- 6 files changed, 4 insertions(+), 313 deletions(-) delete mode 100644 drivers/isdn/capi/capifs.c delete mode 100644 drivers/isdn/capi/capifs.h diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 274b32d12532..e38ccae81710 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -425,16 +425,6 @@ Who: anybody or Florian Mickler ---------------------------- -What: capifs -When: February 2011 -Files: drivers/isdn/capi/capifs.* -Why: udev fully replaces this special file system that only contains CAPI - NCCI TTY device nodes. User space (pppdcapiplugin) works without - noticing the difference. -Who: Jan Kiszka - ----------------------------- - What: KVM paravirt mmu host support When: January 2011 Why: The paravirt mmu host support is slower than non-paravirt mmu, both diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig index a168e8a891be..15c3ffd9d860 100644 --- a/drivers/isdn/capi/Kconfig +++ b/drivers/isdn/capi/Kconfig @@ -33,21 +33,6 @@ config ISDN_CAPI_CAPI20 standardized libcapi20 to access this functionality. You should say Y/M here. -config ISDN_CAPI_CAPIFS_BOOL - bool "CAPI2.0 filesystem support (DEPRECATED)" - depends on ISDN_CAPI_MIDDLEWARE && ISDN_CAPI_CAPI20 - help - This option provides a special file system, similar to /dev/pts with - device nodes for the special ttys established by using the - middleware extension above. - You no longer need this, udev fully replaces it. This feature is - scheduled for removal. - -config ISDN_CAPI_CAPIFS - tristate - depends on ISDN_CAPI_CAPIFS_BOOL - default ISDN_CAPI_CAPI20 - config ISDN_CAPI_CAPIDRV tristate "CAPI2.0 capidrv interface support" depends on ISDN_I4L diff --git a/drivers/isdn/capi/Makefile b/drivers/isdn/capi/Makefile index 57123e3e4978..4d5b4b71db1e 100644 --- a/drivers/isdn/capi/Makefile +++ b/drivers/isdn/capi/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_ISDN_CAPI) += kernelcapi.o obj-$(CONFIG_ISDN_CAPI_CAPI20) += capi.o obj-$(CONFIG_ISDN_CAPI_CAPIDRV) += capidrv.o -obj-$(CONFIG_ISDN_CAPI_CAPIFS) += capifs.o # Multipart objects. diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 0d7088367038..bea100983336 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -38,8 +38,6 @@ #include #include -#include "capifs.h" - MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); @@ -85,7 +83,6 @@ struct capiminor { struct kref kref; unsigned int minor; - struct dentry *capifs_dentry; struct capi20_appl *ap; u32 ncci; @@ -300,17 +297,8 @@ static void capiminor_free(struct capiminor *mp) static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { - struct capiminor *mp; - dev_t device; - - if (!(cdev->userflags & CAPIFLAG_HIGHJACKING)) - return; - - mp = np->minorp = capiminor_alloc(&cdev->ap, np->ncci); - if (mp) { - device = MKDEV(capinc_tty_driver->major, mp->minor); - mp->capifs_dentry = capifs_new_ncci(mp->minor, device); - } + if (cdev->userflags & CAPIFLAG_HIGHJACKING) + np->minorp = capiminor_alloc(&cdev->ap, np->ncci); } static void capincci_free_minor(struct capincci *np) @@ -319,8 +307,6 @@ static void capincci_free_minor(struct capincci *np) struct tty_struct *tty; if (mp) { - capifs_free_ncci(mp->capifs_dentry); - tty = tty_port_tty_get(&mp->port); if (tty) { tty_vhangup(tty); @@ -1514,10 +1500,8 @@ static int __init capi_init(void) proc_init(); -#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) - compileinfo = " (middleware+capifs)"; -#elif defined(CONFIG_ISDN_CAPI_MIDDLEWARE) - compileinfo = " (no capifs)"; +#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE + compileinfo = " (middleware)"; #else compileinfo = " (no middleware)"; #endif diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c deleted file mode 100644 index b4faed7fe0d3..000000000000 --- a/drivers/isdn/capi/capifs.c +++ /dev/null @@ -1,239 +0,0 @@ -/* $Id: capifs.c,v 1.1.2.3 2004/01/16 21:09:26 keil Exp $ - * - * Copyright 2000 by Carsten Paeth - * - * Heavily based on devpts filesystem from H. Peter Anvin - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include /* current */ - -#include "capifs.h" - -MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------------ */ - -#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') - -static struct vfsmount *capifs_mnt; -static int capifs_mnt_count; - -static struct { - int setuid; - int setgid; - uid_t uid; - gid_t gid; - umode_t mode; -} config = {.mode = 0600}; - -/* ------------------------------------------------------------------ */ - -static int capifs_remount(struct super_block *s, int *flags, char *data) -{ - int setuid = 0; - int setgid = 0; - uid_t uid = 0; - gid_t gid = 0; - umode_t mode = 0600; - char *this_char; - char *new_opt = kstrdup(data, GFP_KERNEL); - - this_char = NULL; - while ((this_char = strsep(&data, ",")) != NULL) { - int n; - char dummy; - if (!*this_char) - continue; - if (sscanf(this_char, "uid=%i%c", &n, &dummy) == 1) { - setuid = 1; - uid = n; - } else if (sscanf(this_char, "gid=%i%c", &n, &dummy) == 1) { - setgid = 1; - gid = n; - } else if (sscanf(this_char, "mode=%o%c", &n, &dummy) == 1) - mode = n & ~S_IFMT; - else { - kfree(new_opt); - printk("capifs: called with bogus options\n"); - return -EINVAL; - } - } - - mutex_lock(&s->s_root->d_inode->i_mutex); - - replace_mount_options(s, new_opt); - config.setuid = setuid; - config.setgid = setgid; - config.uid = uid; - config.gid = gid; - config.mode = mode; - - mutex_unlock(&s->s_root->d_inode->i_mutex); - - return 0; -} - -static const struct super_operations capifs_sops = -{ - .statfs = simple_statfs, - .remount_fs = capifs_remount, - .show_options = generic_show_options, -}; - - -static int -capifs_fill_super(struct super_block *s, void *data, int silent) -{ - struct inode * inode; - - s->s_blocksize = 1024; - s->s_blocksize_bits = 10; - s->s_magic = CAPIFS_SUPER_MAGIC; - s->s_op = &capifs_sops; - s->s_time_gran = 1; - - inode = new_inode(s); - if (!inode) - goto fail; - inode->i_ino = 1; - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; - inode->i_op = &simple_dir_inode_operations; - inode->i_fop = &simple_dir_operations; - inode->i_nlink = 2; - - s->s_root = d_alloc_root(inode); - if (s->s_root) - return 0; - - printk("capifs: get root dentry failed\n"); - iput(inode); -fail: - return -ENOMEM; -} - -static struct dentry *capifs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) -{ - return mount_single(fs_type, flags, data, capifs_fill_super); -} - -static struct file_system_type capifs_fs_type = { - .owner = THIS_MODULE, - .name = "capifs", - .mount = capifs_mount, - .kill_sb = kill_anon_super, -}; - -static struct dentry *new_ncci(unsigned int number, dev_t device) -{ - struct super_block *s = capifs_mnt->mnt_sb; - struct dentry *root = s->s_root; - struct dentry *dentry; - struct inode *inode; - char name[10]; - int namelen; - - mutex_lock(&root->d_inode->i_mutex); - - namelen = sprintf(name, "%d", number); - dentry = lookup_one_len(name, root, namelen); - if (IS_ERR(dentry)) { - dentry = NULL; - goto unlock_out; - } - - if (dentry->d_inode) { - dput(dentry); - dentry = NULL; - goto unlock_out; - } - - inode = new_inode(s); - if (!inode) { - dput(dentry); - dentry = NULL; - goto unlock_out; - } - - /* config contents is protected by root's i_mutex */ - inode->i_uid = config.setuid ? config.uid : current_fsuid(); - inode->i_gid = config.setgid ? config.gid : current_fsgid(); - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - inode->i_ino = number + 2; - init_special_inode(inode, S_IFCHR|config.mode, device); - - d_instantiate(dentry, inode); - dget(dentry); - -unlock_out: - mutex_unlock(&root->d_inode->i_mutex); - - return dentry; -} - -struct dentry *capifs_new_ncci(unsigned int number, dev_t device) -{ - struct dentry *dentry; - - if (simple_pin_fs(&capifs_fs_type, &capifs_mnt, &capifs_mnt_count) < 0) - return NULL; - - dentry = new_ncci(number, device); - if (!dentry) - simple_release_fs(&capifs_mnt, &capifs_mnt_count); - - return dentry; -} - -void capifs_free_ncci(struct dentry *dentry) -{ - struct dentry *root = capifs_mnt->mnt_sb->s_root; - struct inode *inode; - - if (!dentry) - return; - - mutex_lock(&root->d_inode->i_mutex); - - inode = dentry->d_inode; - if (inode) { - drop_nlink(inode); - d_delete(dentry); - dput(dentry); - } - dput(dentry); - - mutex_unlock(&root->d_inode->i_mutex); - - simple_release_fs(&capifs_mnt, &capifs_mnt_count); -} - -static int __init capifs_init(void) -{ - return register_filesystem(&capifs_fs_type); -} - -static void __exit capifs_exit(void) -{ - unregister_filesystem(&capifs_fs_type); -} - -EXPORT_SYMBOL(capifs_new_ncci); -EXPORT_SYMBOL(capifs_free_ncci); - -module_init(capifs_init); -module_exit(capifs_exit); diff --git a/drivers/isdn/capi/capifs.h b/drivers/isdn/capi/capifs.h deleted file mode 100644 index e193d1189531..000000000000 --- a/drivers/isdn/capi/capifs.h +++ /dev/null @@ -1,28 +0,0 @@ -/* $Id: capifs.h,v 1.1.2.2 2004/01/16 21:09:26 keil Exp $ - * - * Copyright 2000 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include - -#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) - -struct dentry *capifs_new_ncci(unsigned int num, dev_t device); -void capifs_free_ncci(struct dentry *dentry); - -#else - -static inline struct dentry *capifs_new_ncci(unsigned int num, dev_t device) -{ - return NULL; -} - -static inline void capifs_free_ncci(struct dentry *dentry) -{ -} - -#endif -- cgit v1.2.3-58-ga151 From 066413dac420c8225e3ef7f0f76c3255448782d3 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 5 Apr 2011 01:36:58 +0000 Subject: net: netxen: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather simple conversion to hw_features. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 2 +- drivers/net/netxen/netxen_nic_ethtool.c | 102 -------------------------------- drivers/net/netxen/netxen_nic_init.c | 3 +- drivers/net/netxen/netxen_nic_main.c | 53 +++++++++++++---- 4 files changed, 46 insertions(+), 114 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index d7299f1a4940..15595b3a54c6 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1177,7 +1177,7 @@ struct netxen_adapter { u8 max_sds_rings; u8 driver_mismatch; u8 msix_supported; - u8 rx_csum; + u8 __pad; u8 pci_using_dac; u8 portnum; u8 physical_port; diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 3bdcc803ec68..29f90baaa79b 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -676,62 +676,6 @@ netxen_nic_get_ethtool_stats(struct net_device *dev, } } -static u32 netxen_nic_get_tx_csum(struct net_device *dev) -{ - return dev->features & NETIF_F_IP_CSUM; -} - -static u32 netxen_nic_get_rx_csum(struct net_device *dev) -{ - struct netxen_adapter *adapter = netdev_priv(dev); - return adapter->rx_csum; -} - -static int netxen_nic_set_rx_csum(struct net_device *dev, u32 data) -{ - struct netxen_adapter *adapter = netdev_priv(dev); - - if (data) { - adapter->rx_csum = data; - return 0; - } - - if (dev->features & NETIF_F_LRO) { - if (netxen_config_hw_lro(adapter, NETXEN_NIC_LRO_DISABLED)) - return -EIO; - - dev->features &= ~NETIF_F_LRO; - netxen_send_lro_cleanup(adapter); - netdev_info(dev, "disabling LRO as rx_csum is off\n"); - } - adapter->rx_csum = data; - return 0; -} - -static u32 netxen_nic_get_tso(struct net_device *dev) -{ - struct netxen_adapter *adapter = netdev_priv(dev); - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0; - - return (dev->features & NETIF_F_TSO) != 0; -} - -static int netxen_nic_set_tso(struct net_device *dev, u32 data) -{ - if (data) { - struct netxen_adapter *adapter = netdev_priv(dev); - - dev->features |= NETIF_F_TSO; - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - dev->features |= NETIF_F_TSO6; - } else - dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); - - return 0; -} - static void netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { @@ -866,43 +810,6 @@ static int netxen_get_intr_coalesce(struct net_device *netdev, return 0; } -static int netxen_nic_set_flags(struct net_device *netdev, u32 data) -{ - struct netxen_adapter *adapter = netdev_priv(netdev); - int hw_lro; - - if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO)) - return -EINVAL; - - if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO)) - return -EINVAL; - - if (!adapter->rx_csum) { - netdev_info(netdev, "rx csum is off, cannot toggle LRO\n"); - return -EINVAL; - } - - if (!!(data & ETH_FLAG_LRO) == !!(netdev->features & NETIF_F_LRO)) - return 0; - - if (data & ETH_FLAG_LRO) { - hw_lro = NETXEN_NIC_LRO_ENABLED; - netdev->features |= NETIF_F_LRO; - } else { - hw_lro = NETXEN_NIC_LRO_DISABLED; - netdev->features &= ~NETIF_F_LRO; - } - - if (netxen_config_hw_lro(adapter, hw_lro)) - return -EIO; - - if ((hw_lro == 0) && netxen_send_lro_cleanup(adapter)) - return -EIO; - - - return 0; -} - const struct ethtool_ops netxen_nic_ethtool_ops = { .get_settings = netxen_nic_get_settings, .set_settings = netxen_nic_set_settings, @@ -916,21 +823,12 @@ const struct ethtool_ops netxen_nic_ethtool_ops = { .set_ringparam = netxen_nic_set_ringparam, .get_pauseparam = netxen_nic_get_pauseparam, .set_pauseparam = netxen_nic_set_pauseparam, - .get_tx_csum = netxen_nic_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .get_tso = netxen_nic_get_tso, - .set_tso = netxen_nic_set_tso, .get_wol = netxen_nic_get_wol, .set_wol = netxen_nic_set_wol, .self_test = netxen_nic_diag_test, .get_strings = netxen_nic_get_strings, .get_ethtool_stats = netxen_nic_get_ethtool_stats, .get_sset_count = netxen_get_sset_count, - .get_rx_csum = netxen_nic_get_rx_csum, - .set_rx_csum = netxen_nic_set_rx_csum, .get_coalesce = netxen_get_intr_coalesce, .set_coalesce = netxen_set_intr_coalesce, - .get_flags = ethtool_op_get_flags, - .set_flags = netxen_nic_set_flags, }; diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 731077d8d962..7f999671c7b2 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -1483,7 +1483,8 @@ static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter, if (!skb) goto no_skb; - if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) { + if (likely((adapter->netdev->features & NETIF_F_RXCSUM) + && cksum == STATUS_CKSUM_OK)) { adapter->stats.csummed++; skb->ip_summed = CHECKSUM_UNNECESSARY; } else diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 933671556c15..201b944bd463 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -485,6 +485,37 @@ static void netxen_set_multicast_list(struct net_device *dev) adapter->set_multi(dev); } +static u32 netxen_fix_features(struct net_device *dev, u32 features) +{ + if (!(features & NETIF_F_RXCSUM)) { + netdev_info(dev, "disabling LRO as RXCSUM is off\n"); + + features &= ~NETIF_F_LRO; + } + + return features; +} + +static int netxen_set_features(struct net_device *dev, u32 features) +{ + struct netxen_adapter *adapter = netdev_priv(dev); + int hw_lro; + + if (!((dev->features ^ features) & NETIF_F_LRO)) + return 0; + + hw_lro = (features & NETIF_F_LRO) ? NETXEN_NIC_LRO_ENABLED + : NETXEN_NIC_LRO_DISABLED; + + if (netxen_config_hw_lro(adapter, hw_lro)) + return -EIO; + + if (!(features & NETIF_F_LRO) && netxen_send_lro_cleanup(adapter)) + return -EIO; + + return 0; +} + static const struct net_device_ops netxen_netdev_ops = { .ndo_open = netxen_nic_open, .ndo_stop = netxen_nic_close, @@ -495,6 +526,8 @@ static const struct net_device_ops netxen_netdev_ops = { .ndo_set_mac_address = netxen_nic_set_mac, .ndo_change_mtu = netxen_nic_change_mtu, .ndo_tx_timeout = netxen_tx_timeout, + .ndo_fix_features = netxen_fix_features, + .ndo_set_features = netxen_set_features, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = netxen_nic_poll_controller, #endif @@ -1196,7 +1229,6 @@ netxen_setup_netdev(struct netxen_adapter *adapter, int err = 0; struct pci_dev *pdev = adapter->pdev; - adapter->rx_csum = 1; adapter->mc_enabled = 0; if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) adapter->max_mc_count = 38; @@ -1210,14 +1242,13 @@ netxen_setup_netdev(struct netxen_adapter *adapter, SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops); - netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); - netdev->features |= (NETIF_F_GRO); - netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_RXCSUM; - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); - netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); - } + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + netdev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; + + netdev->vlan_features |= netdev->hw_features; if (adapter->pci_using_dac) { netdev->features |= NETIF_F_HIGHDMA; @@ -1225,10 +1256,12 @@ netxen_setup_netdev(struct netxen_adapter *adapter, } if (adapter->capabilities & NX_FW_CAPABILITY_FVLANTX) - netdev->features |= (NETIF_F_HW_VLAN_TX); + netdev->hw_features |= NETIF_F_HW_VLAN_TX; if (adapter->capabilities & NX_FW_CAPABILITY_HW_LRO) - netdev->features |= NETIF_F_LRO; + netdev->hw_features |= NETIF_F_LRO; + + netdev->features |= netdev->hw_features; netdev->irq = adapter->msix_entries[0].vector; -- cgit v1.2.3-58-ga151 From 94469f75321d13a42056514e2883590b91d84cba Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 6 Apr 2011 11:47:23 +0000 Subject: qlcnic: convert to set_phys_id Convert driver to use new ethtool set_phys_id. Not completely sure that this is correct for all cases of device up/down and doing operation. Compile tested only. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 1 + drivers/net/qlcnic/qlcnic_ethtool.c | 53 ++++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index dc6f7c69acac..b6e0fc33585f 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -912,6 +912,7 @@ struct qlcnic_adapter { struct net_device *netdev; struct pci_dev *pdev; + bool blink_was_down; unsigned long state; u32 flags; diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 6be4d5a26c7c..3cd8a169694a 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -831,48 +831,51 @@ static int qlcnic_set_tso(struct net_device *dev, u32 data) return 0; } -static int qlcnic_blink_led(struct net_device *dev, u32 val) +static int qlcnic_set_led(struct net_device *dev, + enum ethtool_phys_id_state state) { struct qlcnic_adapter *adapter = netdev_priv(dev); int max_sds_rings = adapter->max_sds_rings; - int dev_down = 0; - int ret; - - if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { - dev_down = 1; - if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) - return -EIO; - ret = qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST); - if (ret) { - clear_bit(__QLCNIC_RESETTING, &adapter->state); - return ret; + switch (state) { + case ETHTOOL_ID_ACTIVE: + adapter->blink_was_down = false; + if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { + if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) + return -EIO; + + if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST)) { + clear_bit(__QLCNIC_RESETTING, &adapter->state); + return -EIO; + } + adapter->blink_was_down = true; } - } - ret = adapter->nic_ops->config_led(adapter, 1, 0xf); - if (ret) { + if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) + return 0; + dev_err(&adapter->pdev->dev, "Failed to set LED blink state.\n"); - goto done; - } + break; - msleep_interruptible(val * 1000); + case ETHTOOL_ID_INACTIVE: + if (adapter->nic_ops->config_led(adapter, 0, 0xf) == 0) + return 0; - ret = adapter->nic_ops->config_led(adapter, 0, 0xf); - if (ret) { dev_err(&adapter->pdev->dev, "Failed to reset LED blink state.\n"); - goto done; + break; + + default: + return -EINVAL; } -done: - if (dev_down) { + if (adapter->blink_was_down) { qlcnic_diag_free_res(dev, max_sds_rings); clear_bit(__QLCNIC_RESETTING, &adapter->state); } - return ret; + return -EIO; } static void @@ -1078,7 +1081,7 @@ const struct ethtool_ops qlcnic_ethtool_ops = { .set_coalesce = qlcnic_set_intr_coalesce, .get_flags = ethtool_op_get_flags, .set_flags = qlcnic_set_flags, - .phys_id = qlcnic_blink_led, + .set_phys_id = qlcnic_set_led, .set_msglevel = qlcnic_set_msglevel, .get_msglevel = qlcnic_get_msglevel, }; -- cgit v1.2.3-58-ga151 From 7b1b3afadf33627e707c5038af991ae2ce9b5ac5 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 6 Apr 2011 11:58:36 +0000 Subject: ewrk3: convert to set_phys_id Use ethtool infrastructure for blinking, which is now does locking at higher level. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ewrk3.c | 56 +++++++++++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index 380d0614a89a..c7ce4438e923 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -1604,55 +1604,47 @@ static u32 ewrk3_get_link(struct net_device *dev) return !(cmr & CMR_LINK); } -static int ewrk3_phys_id(struct net_device *dev, u32 data) +static int ewrk3_set_phys_id(struct net_device *dev, + enum ethtool_phys_id_state state) { struct ewrk3_private *lp = netdev_priv(dev); unsigned long iobase = dev->base_addr; - unsigned long flags; u8 cr; - int count; - - /* Toggle LED 4x per second */ - count = data << 2; - spin_lock_irqsave(&lp->hw_lock, flags); - - /* Bail if a PHYS_ID is already in progress */ - if (lp->led_mask == 0) { - spin_unlock_irqrestore(&lp->hw_lock, flags); - return -EBUSY; - } + spin_lock_irq(&lp->hw_lock); - /* Prevent ISR from twiddling the LED */ - lp->led_mask = 0; + switch (state) { + case ETHTOOL_ID_ACTIVE: + /* Prevent ISR from twiddling the LED */ + lp->led_mask = 0; + spin_unlock_irq(&lp->hw_lock); + return -EINVAL; - while (count--) { - /* Toggle the LED */ + case ETHTOOL_ID_ON: cr = inb(EWRK3_CR); - outb(cr ^ CR_LED, EWRK3_CR); + outb(cr | CR_LED, EWRK3_CR); + break; - /* Wait a little while */ - spin_unlock_irqrestore(&lp->hw_lock, flags); - msleep(250); - spin_lock_irqsave(&lp->hw_lock, flags); + case ETHTOOL_ID_OFF: + cr = inb(EWRK3_CR); + outb(cr & ~CR_LED, EWRK3_CR); + break; - /* Exit if we got a signal */ - if (signal_pending(current)) - break; + case ETHTOOL_ID_INACTIVE: + lp->led_mask = CR_LED; + cr = inb(EWRK3_CR); + outb(cr & ~CR_LED, EWRK3_CR); } + spin_unlock_irq(&lp->hw_lock); - lp->led_mask = CR_LED; - cr = inb(EWRK3_CR); - outb(cr & ~CR_LED, EWRK3_CR); - spin_unlock_irqrestore(&lp->hw_lock, flags); - return signal_pending(current) ? -ERESTARTSYS : 0; + return 0; } static const struct ethtool_ops ethtool_ops_203 = { .get_drvinfo = ewrk3_get_drvinfo, .get_settings = ewrk3_get_settings, .set_settings = ewrk3_set_settings, - .phys_id = ewrk3_phys_id, + .set_phys_id = ewrk3_set_phys_id, }; static const struct ethtool_ops ethtool_ops = { @@ -1660,7 +1652,7 @@ static const struct ethtool_ops ethtool_ops = { .get_settings = ewrk3_get_settings, .set_settings = ewrk3_set_settings, .get_link = ewrk3_get_link, - .phys_id = ewrk3_phys_id, + .set_phys_id = ewrk3_set_phys_id, }; /* -- cgit v1.2.3-58-ga151 From 912d398d28b4359c2fb1f3763f1ce4f86de8350e Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 6 Apr 2011 18:40:12 +0000 Subject: net: fix skb_add_data_nocache() to calc csum correctly commit c6e1a0d12ca7b4f22c58e55a16beacfb7d3d8462 broken the calc (net: Allow no-cache copy from user on transmit) of checksum, which may cause some tcp packets be dropped because incorrect checksum. ssh does not work under today's net-next-2.6 tree. Signed-off-by: Wei Yongjun Acked-by: Tom Herbert Signed-off-by: David S. Miller --- include/net/sock.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 43bd515e92fd..9cbf23c815f5 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1392,14 +1392,14 @@ static inline void sk_nocaps_add(struct sock *sk, int flags) static inline int skb_do_copy_data_nocache(struct sock *sk, struct sk_buff *skb, char __user *from, char *to, - int copy) + int copy, int offset) { if (skb->ip_summed == CHECKSUM_NONE) { int err = 0; __wsum csum = csum_and_copy_from_user(from, to, copy, 0, &err); if (err) return err; - skb->csum = csum_block_add(skb->csum, csum, skb->len); + skb->csum = csum_block_add(skb->csum, csum, offset); } else if (sk->sk_route_caps & NETIF_F_NOCACHE_COPY) { if (!access_ok(VERIFY_READ, from, copy) || __copy_from_user_nocache(to, from, copy)) @@ -1413,11 +1413,12 @@ static inline int skb_do_copy_data_nocache(struct sock *sk, struct sk_buff *skb, static inline int skb_add_data_nocache(struct sock *sk, struct sk_buff *skb, char __user *from, int copy) { - int err; + int err, offset = skb->len; - err = skb_do_copy_data_nocache(sk, skb, from, skb_put(skb, copy), copy); + err = skb_do_copy_data_nocache(sk, skb, from, skb_put(skb, copy), + copy, offset); if (err) - __skb_trim(skb, skb->len); + __skb_trim(skb, offset); return err; } @@ -1429,8 +1430,8 @@ static inline int skb_copy_to_page_nocache(struct sock *sk, char __user *from, { int err; - err = skb_do_copy_data_nocache(sk, skb, from, - page_address(page) + off, copy); + err = skb_do_copy_data_nocache(sk, skb, from, page_address(page) + off, + copy, skb->len); if (err) return err; -- cgit v1.2.3-58-ga151 From b0006e69615868f3dfdfe2bd64eb11973f1208fc Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 25 Mar 2011 20:21:55 +0100 Subject: ar9170usb: purge obsolete driver Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- Documentation/feature-removal-schedule.txt | 11 - MAINTAINERS | 7 - drivers/net/wireless/ath/Kconfig | 1 - drivers/net/wireless/ath/Makefile | 1 - drivers/net/wireless/ath/ar9170/Kconfig | 20 - drivers/net/wireless/ath/ar9170/Makefile | 3 - drivers/net/wireless/ath/ar9170/ar9170.h | 258 ---- drivers/net/wireless/ath/ar9170/cmd.c | 127 -- drivers/net/wireless/ath/ar9170/cmd.h | 92 -- drivers/net/wireless/ath/ar9170/eeprom.h | 179 --- drivers/net/wireless/ath/ar9170/hw.h | 430 ------ drivers/net/wireless/ath/ar9170/led.c | 181 --- drivers/net/wireless/ath/ar9170/mac.c | 519 ------- drivers/net/wireless/ath/ar9170/main.c | 2190 ---------------------------- drivers/net/wireless/ath/ar9170/phy.c | 1719 ---------------------- drivers/net/wireless/ath/ar9170/usb.c | 1008 ------------- drivers/net/wireless/ath/ar9170/usb.h | 82 -- 17 files changed, 6828 deletions(-) delete mode 100644 drivers/net/wireless/ath/ar9170/Kconfig delete mode 100644 drivers/net/wireless/ath/ar9170/Makefile delete mode 100644 drivers/net/wireless/ath/ar9170/ar9170.h delete mode 100644 drivers/net/wireless/ath/ar9170/cmd.c delete mode 100644 drivers/net/wireless/ath/ar9170/cmd.h delete mode 100644 drivers/net/wireless/ath/ar9170/eeprom.h delete mode 100644 drivers/net/wireless/ath/ar9170/hw.h delete mode 100644 drivers/net/wireless/ath/ar9170/led.c delete mode 100644 drivers/net/wireless/ath/ar9170/mac.c delete mode 100644 drivers/net/wireless/ath/ar9170/main.c delete mode 100644 drivers/net/wireless/ath/ar9170/phy.c delete mode 100644 drivers/net/wireless/ath/ar9170/usb.c delete mode 100644 drivers/net/wireless/ath/ar9170/usb.h diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 274b32d12532..05ed6f301d89 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -35,17 +35,6 @@ Who: Luis R. Rodriguez --------------------------- -What: AR9170USB -When: 2.6.40 - -Why: This driver is deprecated and the firmware is no longer - maintained. The replacement driver "carl9170" has been - around for a while, so the devices are still supported. - -Who: Christian Lamparter - ---------------------------- - What: IRQF_SAMPLE_RANDOM Check: IRQF_SAMPLE_RANDOM When: July 2009 diff --git a/MAINTAINERS b/MAINTAINERS index 5dd948b5bc6e..9f9104987a73 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1224,13 +1224,6 @@ W: http://wireless.kernel.org/en/users/Drivers/ath9k S: Supported F: drivers/net/wireless/ath/ath9k/ -ATHEROS AR9170 WIRELESS DRIVER -M: Christian Lamparter -L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org/en/users/Drivers/ar9170 -S: Obsolete -F: drivers/net/wireless/ath/ar9170/ - CARL9170 LINUX COMMUNITY WIRELESS DRIVER M: Christian Lamparter L: linux-wireless@vger.kernel.org diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 92c216263ee9..d1b23067619f 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig @@ -24,7 +24,6 @@ config ATH_DEBUG source "drivers/net/wireless/ath/ath5k/Kconfig" source "drivers/net/wireless/ath/ath9k/Kconfig" -source "drivers/net/wireless/ath/ar9170/Kconfig" source "drivers/net/wireless/ath/carl9170/Kconfig" endif diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index 6d711ec97ec2..0e8f528c81c0 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile @@ -1,6 +1,5 @@ obj-$(CONFIG_ATH5K) += ath5k/ obj-$(CONFIG_ATH9K_HW) += ath9k/ -obj-$(CONFIG_AR9170_USB) += ar9170/ obj-$(CONFIG_CARL9170) += carl9170/ obj-$(CONFIG_ATH_COMMON) += ath.o diff --git a/drivers/net/wireless/ath/ar9170/Kconfig b/drivers/net/wireless/ath/ar9170/Kconfig deleted file mode 100644 index 7b9672b0d090..000000000000 --- a/drivers/net/wireless/ath/ar9170/Kconfig +++ /dev/null @@ -1,20 +0,0 @@ -config AR9170_USB - tristate "Atheros AR9170 802.11n USB support (OBSOLETE)" - depends on USB && MAC80211 - select FW_LOADER - help - This driver is going to get replaced by carl9170. - - This is a driver for the Atheros "otus" 802.11n USB devices. - - These devices require additional firmware (2 files). - For now, these files can be downloaded from here: - - http://wireless.kernel.org/en/users/Drivers/ar9170 - - If you choose to build a module, it'll be called ar9170usb. - -config AR9170_LEDS - bool - depends on AR9170_USB && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = AR9170_USB) - default y diff --git a/drivers/net/wireless/ath/ar9170/Makefile b/drivers/net/wireless/ath/ar9170/Makefile deleted file mode 100644 index 8d91c7ee3215..000000000000 --- a/drivers/net/wireless/ath/ar9170/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -ar9170usb-objs := usb.o main.o cmd.o mac.o phy.o led.o - -obj-$(CONFIG_AR9170_USB) += ar9170usb.o diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h deleted file mode 100644 index 371e4ce49528..000000000000 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Atheros AR9170 driver - * - * Driver specific definitions - * - * Copyright 2008, Johannes Berg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef __AR9170_H -#define __AR9170_H - -#include -#include -#include -#include -#ifdef CONFIG_AR9170_LEDS -#include -#endif /* CONFIG_AR9170_LEDS */ -#include "eeprom.h" -#include "hw.h" - -#include "../regd.h" - -#define PAYLOAD_MAX (AR9170_MAX_CMD_LEN/4 - 1) - -enum ar9170_bw { - AR9170_BW_20, - AR9170_BW_40_BELOW, - AR9170_BW_40_ABOVE, - - __AR9170_NUM_BW, -}; - -static inline enum ar9170_bw nl80211_to_ar9170(enum nl80211_channel_type type) -{ - switch (type) { - case NL80211_CHAN_NO_HT: - case NL80211_CHAN_HT20: - return AR9170_BW_20; - case NL80211_CHAN_HT40MINUS: - return AR9170_BW_40_BELOW; - case NL80211_CHAN_HT40PLUS: - return AR9170_BW_40_ABOVE; - default: - BUG(); - } -} - -enum ar9170_rf_init_mode { - AR9170_RFI_NONE, - AR9170_RFI_WARM, - AR9170_RFI_COLD, -}; - -#define AR9170_MAX_RX_BUFFER_SIZE 8192 - -#ifdef CONFIG_AR9170_LEDS -struct ar9170; - -struct ar9170_led { - struct ar9170 *ar; - struct led_classdev l; - char name[32]; - unsigned int toggled; - bool last_state; - bool registered; -}; - -#endif /* CONFIG_AR9170_LEDS */ - -enum ar9170_device_state { - AR9170_UNKNOWN_STATE, - AR9170_STOPPED, - AR9170_IDLE, - AR9170_STARTED, -}; - -struct ar9170_rxstream_mpdu_merge { - struct ar9170_rx_head plcp; - bool has_plcp; -}; - -struct ar9170_tx_queue_stats { - unsigned int len; - unsigned int limit; - unsigned int count; -}; - -#define AR9170_QUEUE_TIMEOUT 64 -#define AR9170_TX_TIMEOUT 8 -#define AR9170_JANITOR_DELAY 128 -#define AR9170_TX_INVALID_RATE 0xffffffff - -#define AR9170_NUM_TX_LIMIT_HARD AR9170_TXQ_DEPTH -#define AR9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH - 10) - -struct ar9170 { - struct ieee80211_hw *hw; - struct ath_common common; - struct mutex mutex; - enum ar9170_device_state state; - bool registered; - unsigned long bad_hw_nagger; - - int (*open)(struct ar9170 *); - void (*stop)(struct ar9170 *); - int (*tx)(struct ar9170 *, struct sk_buff *); - int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 , - void *, u32 , void *); - void (*callback_cmd)(struct ar9170 *, u32 , void *); - int (*flush)(struct ar9170 *); - - /* interface mode settings */ - struct ieee80211_vif *vif; - - /* beaconing */ - struct sk_buff *beacon; - struct work_struct beacon_work; - bool enable_beacon; - - /* cryptographic engine */ - u64 usedkeys; - bool rx_software_decryption; - bool disable_offload; - - /* filter settings */ - u64 cur_mc_hash; - u32 cur_filter; - unsigned int filter_state; - bool sniffer_enabled; - - /* PHY */ - struct ieee80211_channel *channel; - int noise[4]; - - /* power calibration data */ - u8 power_5G_leg[4]; - u8 power_2G_cck[4]; - u8 power_2G_ofdm[4]; - u8 power_5G_ht20[8]; - u8 power_5G_ht40[8]; - u8 power_2G_ht20[8]; - u8 power_2G_ht40[8]; - - u8 phy_heavy_clip; - -#ifdef CONFIG_AR9170_LEDS - struct delayed_work led_work; - struct ar9170_led leds[AR9170_NUM_LEDS]; -#endif /* CONFIG_AR9170_LEDS */ - - /* qos queue settings */ - spinlock_t tx_stats_lock; - struct ar9170_tx_queue_stats tx_stats[5]; - struct ieee80211_tx_queue_params edcf[5]; - - spinlock_t cmdlock; - __le32 cmdbuf[PAYLOAD_MAX + 1]; - - /* MAC statistics */ - struct ieee80211_low_level_stats stats; - - /* EEPROM */ - struct ar9170_eeprom eeprom; - - /* tx queues - as seen by hw - */ - struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; - struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; - struct delayed_work tx_janitor; - - /* rxstream mpdu merge */ - struct ar9170_rxstream_mpdu_merge rx_mpdu; - struct sk_buff *rx_failover; - int rx_failover_missing; - - /* (cached) HW A-MPDU settings */ - u8 global_ampdu_density; - u8 global_ampdu_factor; -}; - -struct ar9170_tx_info { - unsigned long timeout; -}; - -#define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) -#define IS_ACCEPTING_CMD(a) (((struct ar9170 *)a)->state >= AR9170_IDLE) - -/* exported interface */ -void *ar9170_alloc(size_t priv_size); -int ar9170_register(struct ar9170 *ar, struct device *pdev); -void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb); -void ar9170_unregister(struct ar9170 *ar); -void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb); -void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len); -int ar9170_nag_limiter(struct ar9170 *ar); - -/* MAC */ -void ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); -int ar9170_init_mac(struct ar9170 *ar); -int ar9170_set_qos(struct ar9170 *ar); -int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hast); -int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter); -int ar9170_set_operating_mode(struct ar9170 *ar); -int ar9170_set_beacon_timers(struct ar9170 *ar); -int ar9170_set_dyn_sifs_ack(struct ar9170 *ar); -int ar9170_set_slot_time(struct ar9170 *ar); -int ar9170_set_basic_rates(struct ar9170 *ar); -int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry); -int ar9170_update_beacon(struct ar9170 *ar); -void ar9170_new_beacon(struct work_struct *work); -int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, - u8 keyidx, u8 *keydata, int keylen); -int ar9170_disable_key(struct ar9170 *ar, u8 id); - -/* LEDs */ -#ifdef CONFIG_AR9170_LEDS -int ar9170_register_leds(struct ar9170 *ar); -void ar9170_unregister_leds(struct ar9170 *ar); -#endif /* CONFIG_AR9170_LEDS */ -int ar9170_init_leds(struct ar9170 *ar); -int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state); - -/* PHY / RF */ -int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band); -int ar9170_init_rf(struct ar9170 *ar); -int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, - enum ar9170_rf_init_mode rfi, enum ar9170_bw bw); - -#endif /* __AR9170_H */ diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c deleted file mode 100644 index 6452c5055a63..000000000000 --- a/drivers/net/wireless/ath/ar9170/cmd.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Atheros AR9170 driver - * - * Basic HW register/memory/command access functions - * - * Copyright 2008, Johannes Berg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ar9170.h" -#include "cmd.h" - -int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len) -{ - int err; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return 0; - - err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL); - if (err) - wiphy_debug(ar->hw->wiphy, "writing memory failed\n"); - return err; -} - -int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) -{ - const __le32 buf[2] = { - cpu_to_le32(reg), - cpu_to_le32(val), - }; - int err; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return 0; - - err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf), - (u8 *) buf, 0, NULL); - if (err) - wiphy_debug(ar->hw->wiphy, "writing reg %#x (val %#x) failed\n", - reg, val); - return err; -} - -int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out) -{ - int i, err; - __le32 *offs, *res; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return 0; - - /* abuse "out" for the register offsets, must be same length */ - offs = (__le32 *)out; - for (i = 0; i < nregs; i++) - offs[i] = cpu_to_le32(regs[i]); - - /* also use the same buffer for the input */ - res = (__le32 *)out; - - err = ar->exec_cmd(ar, AR9170_CMD_RREG, - 4 * nregs, (u8 *)offs, - 4 * nregs, (u8 *)res); - if (err) - return err; - - /* convert result to cpu endian */ - for (i = 0; i < nregs; i++) - out[i] = le32_to_cpu(res[i]); - - return 0; -} - -int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val) -{ - return ar9170_read_mreg(ar, 1, ®, val); -} - -int ar9170_echo_test(struct ar9170 *ar, u32 v) -{ - __le32 echobuf = cpu_to_le32(v); - __le32 echores; - int err; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return -ENODEV; - - err = ar->exec_cmd(ar, AR9170_CMD_ECHO, - 4, (u8 *)&echobuf, - 4, (u8 *)&echores); - if (err) - return err; - - if (echobuf != echores) - return -EINVAL; - - return 0; -} diff --git a/drivers/net/wireless/ath/ar9170/cmd.h b/drivers/net/wireless/ath/ar9170/cmd.h deleted file mode 100644 index ec8134b4b949..000000000000 --- a/drivers/net/wireless/ath/ar9170/cmd.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Atheros AR9170 driver - * - * Basic HW register/memory/command access functions - * - * Copyright 2008, Johannes Berg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef __CMD_H -#define __CMD_H - -#include "ar9170.h" - -/* basic HW access */ -int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); -int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); -int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); -int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out); -int ar9170_echo_test(struct ar9170 *ar, u32 v); - -/* - * Macros to facilitate writing multiple registers in a single - * write-combining USB command. Note that when the first group - * fails the whole thing will fail without any others attempted, - * but you won't know which write in the group failed. - */ -#define ar9170_regwrite_begin(ar) \ -do { \ - int __nreg = 0, __err = 0; \ - struct ar9170 *__ar = ar; - -#define ar9170_regwrite(r, v) do { \ - __ar->cmdbuf[2 * __nreg + 1] = cpu_to_le32(r); \ - __ar->cmdbuf[2 * __nreg + 2] = cpu_to_le32(v); \ - __nreg++; \ - if ((__nreg >= PAYLOAD_MAX/2)) { \ - if (IS_ACCEPTING_CMD(__ar)) \ - __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ - 8 * __nreg, \ - (u8 *) &__ar->cmdbuf[1], \ - 0, NULL); \ - __nreg = 0; \ - if (__err) \ - goto __regwrite_out; \ - } \ -} while (0) - -#define ar9170_regwrite_finish() \ -__regwrite_out : \ - if (__nreg) { \ - if (IS_ACCEPTING_CMD(__ar)) \ - __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ - 8 * __nreg, \ - (u8 *) &__ar->cmdbuf[1], \ - 0, NULL); \ - __nreg = 0; \ - } - -#define ar9170_regwrite_result() \ - __err; \ -} while (0); - -#endif /* __CMD_H */ diff --git a/drivers/net/wireless/ath/ar9170/eeprom.h b/drivers/net/wireless/ath/ar9170/eeprom.h deleted file mode 100644 index 6c4663883423..000000000000 --- a/drivers/net/wireless/ath/ar9170/eeprom.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Atheros AR9170 driver - * - * EEPROM layout - * - * Copyright 2008, Johannes Berg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef __AR9170_EEPROM_H -#define __AR9170_EEPROM_H - -#define AR5416_MAX_CHAINS 2 -#define AR5416_MODAL_SPURS 5 - -struct ar9170_eeprom_modal { - __le32 antCtrlChain[AR5416_MAX_CHAINS]; - __le32 antCtrlCommon; - s8 antennaGainCh[AR5416_MAX_CHAINS]; - u8 switchSettling; - u8 txRxAttenCh[AR5416_MAX_CHAINS]; - u8 rxTxMarginCh[AR5416_MAX_CHAINS]; - s8 adcDesiredSize; - s8 pgaDesiredSize; - u8 xlnaGainCh[AR5416_MAX_CHAINS]; - u8 txEndToXpaOff; - u8 txEndToRxOn; - u8 txFrameToXpaOn; - u8 thresh62; - s8 noiseFloorThreshCh[AR5416_MAX_CHAINS]; - u8 xpdGain; - u8 xpd; - s8 iqCalICh[AR5416_MAX_CHAINS]; - s8 iqCalQCh[AR5416_MAX_CHAINS]; - u8 pdGainOverlap; - u8 ob; - u8 db; - u8 xpaBiasLvl; - u8 pwrDecreaseFor2Chain; - u8 pwrDecreaseFor3Chain; - u8 txFrameToDataStart; - u8 txFrameToPaOn; - u8 ht40PowerIncForPdadc; - u8 bswAtten[AR5416_MAX_CHAINS]; - u8 bswMargin[AR5416_MAX_CHAINS]; - u8 swSettleHt40; - u8 reserved[22]; - struct spur_channel { - __le16 spurChan; - u8 spurRangeLow; - u8 spurRangeHigh; - } __packed spur_channels[AR5416_MODAL_SPURS]; -} __packed; - -#define AR5416_NUM_PD_GAINS 4 -#define AR5416_PD_GAIN_ICEPTS 5 - -struct ar9170_calibration_data_per_freq { - u8 pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; - u8 vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; -} __packed; - -#define AR5416_NUM_5G_CAL_PIERS 8 -#define AR5416_NUM_2G_CAL_PIERS 4 - -#define AR5416_NUM_5G_TARGET_PWRS 8 -#define AR5416_NUM_2G_CCK_TARGET_PWRS 3 -#define AR5416_NUM_2G_OFDM_TARGET_PWRS 4 -#define AR5416_MAX_NUM_TGT_PWRS 8 - -struct ar9170_calibration_target_power_legacy { - u8 freq; - u8 power[4]; -} __packed; - -struct ar9170_calibration_target_power_ht { - u8 freq; - u8 power[8]; -} __packed; - -#define AR5416_NUM_CTLS 24 - -struct ar9170_calctl_edges { - u8 channel; -#define AR9170_CALCTL_EDGE_FLAGS 0xC0 - u8 power_flags; -} __packed; - -#define AR5416_NUM_BAND_EDGES 8 - -struct ar9170_calctl_data { - struct ar9170_calctl_edges - control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; -} __packed; - - -struct ar9170_eeprom { - __le16 length; - __le16 checksum; - __le16 version; - u8 operating_flags; -#define AR9170_OPFLAG_5GHZ 1 -#define AR9170_OPFLAG_2GHZ 2 - u8 misc; - __le16 reg_domain[2]; - u8 mac_address[6]; - u8 rx_mask; - u8 tx_mask; - __le16 rf_silent; - __le16 bluetooth_options; - __le16 device_capabilities; - __le32 build_number; - u8 deviceType; - u8 reserved[33]; - - u8 customer_data[64]; - - struct ar9170_eeprom_modal - modal_header[2]; - - u8 cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS]; - u8 cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS]; - - struct ar9170_calibration_data_per_freq - cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS], - cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; - - /* power calibration data */ - struct ar9170_calibration_target_power_legacy - cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS]; - struct ar9170_calibration_target_power_ht - cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS], - cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS]; - - struct ar9170_calibration_target_power_legacy - cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS], - cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS]; - struct ar9170_calibration_target_power_ht - cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS], - cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS]; - - /* conformance testing limits */ - u8 ctl_index[AR5416_NUM_CTLS]; - struct ar9170_calctl_data - ctl_data[AR5416_NUM_CTLS]; - - u8 pad; - __le16 subsystem_id; -} __packed; - -#endif /* __AR9170_EEPROM_H */ diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h deleted file mode 100644 index 06f1f3c951a4..000000000000 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Atheros AR9170 driver - * - * Hardware-specific definitions - * - * Copyright 2008, Johannes Berg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef __AR9170_HW_H -#define __AR9170_HW_H - -#define AR9170_MAX_CMD_LEN 64 - -enum ar9170_cmd { - AR9170_CMD_RREG = 0x00, - AR9170_CMD_WREG = 0x01, - AR9170_CMD_RMEM = 0x02, - AR9170_CMD_WMEM = 0x03, - AR9170_CMD_BITAND = 0x04, - AR9170_CMD_BITOR = 0x05, - AR9170_CMD_EKEY = 0x28, - AR9170_CMD_DKEY = 0x29, - AR9170_CMD_FREQUENCY = 0x30, - AR9170_CMD_RF_INIT = 0x31, - AR9170_CMD_SYNTH = 0x32, - AR9170_CMD_FREQ_START = 0x33, - AR9170_CMD_ECHO = 0x80, - AR9170_CMD_TALLY = 0x81, - AR9170_CMD_TALLY_APD = 0x82, - AR9170_CMD_CONFIG = 0x83, - AR9170_CMD_RESET = 0x90, - AR9170_CMD_DKRESET = 0x91, - AR9170_CMD_DKTX_STATUS = 0x92, - AR9170_CMD_FDC = 0xA0, - AR9170_CMD_WREEPROM = 0xB0, - AR9170_CMD_WFLASH = 0xB0, - AR9170_CMD_FLASH_ERASE = 0xB1, - AR9170_CMD_FLASH_PROG = 0xB2, - AR9170_CMD_FLASH_CHKSUM = 0xB3, - AR9170_CMD_FLASH_READ = 0xB4, - AR9170_CMD_FW_DL_INIT = 0xB5, - AR9170_CMD_MEM_WREEPROM = 0xBB, -}; - -/* endpoints */ -#define AR9170_EP_TX 1 -#define AR9170_EP_RX 2 -#define AR9170_EP_IRQ 3 -#define AR9170_EP_CMD 4 - -#define AR9170_EEPROM_START 0x1600 - -#define AR9170_GPIO_REG_BASE 0x1d0100 -#define AR9170_GPIO_REG_PORT_TYPE AR9170_GPIO_REG_BASE -#define AR9170_GPIO_REG_DATA (AR9170_GPIO_REG_BASE + 4) -#define AR9170_NUM_LEDS 2 - - -#define AR9170_USB_REG_BASE 0x1e1000 -#define AR9170_USB_REG_DMA_CTL (AR9170_USB_REG_BASE + 0x108) -#define AR9170_DMA_CTL_ENABLE_TO_DEVICE 0x1 -#define AR9170_DMA_CTL_ENABLE_FROM_DEVICE 0x2 -#define AR9170_DMA_CTL_HIGH_SPEED 0x4 -#define AR9170_DMA_CTL_PACKET_MODE 0x8 - -#define AR9170_USB_REG_MAX_AGG_UPLOAD (AR9170_USB_REG_BASE + 0x110) -#define AR9170_USB_REG_UPLOAD_TIME_CTL (AR9170_USB_REG_BASE + 0x114) - - - -#define AR9170_MAC_REG_BASE 0x1c3000 - -#define AR9170_MAC_REG_TSF_L (AR9170_MAC_REG_BASE + 0x514) -#define AR9170_MAC_REG_TSF_H (AR9170_MAC_REG_BASE + 0x518) - -#define AR9170_MAC_REG_ATIM_WINDOW (AR9170_MAC_REG_BASE + 0x51C) -#define AR9170_MAC_REG_BCN_PERIOD (AR9170_MAC_REG_BASE + 0x520) -#define AR9170_MAC_REG_PRETBTT (AR9170_MAC_REG_BASE + 0x524) - -#define AR9170_MAC_REG_MAC_ADDR_L (AR9170_MAC_REG_BASE + 0x610) -#define AR9170_MAC_REG_MAC_ADDR_H (AR9170_MAC_REG_BASE + 0x614) -#define AR9170_MAC_REG_BSSID_L (AR9170_MAC_REG_BASE + 0x618) -#define AR9170_MAC_REG_BSSID_H (AR9170_MAC_REG_BASE + 0x61c) - -#define AR9170_MAC_REG_GROUP_HASH_TBL_L (AR9170_MAC_REG_BASE + 0x624) -#define AR9170_MAC_REG_GROUP_HASH_TBL_H (AR9170_MAC_REG_BASE + 0x628) - -#define AR9170_MAC_REG_RX_TIMEOUT (AR9170_MAC_REG_BASE + 0x62C) - -#define AR9170_MAC_REG_BASIC_RATE (AR9170_MAC_REG_BASE + 0x630) -#define AR9170_MAC_REG_MANDATORY_RATE (AR9170_MAC_REG_BASE + 0x634) -#define AR9170_MAC_REG_RTS_CTS_RATE (AR9170_MAC_REG_BASE + 0x638) -#define AR9170_MAC_REG_BACKOFF_PROTECT (AR9170_MAC_REG_BASE + 0x63c) -#define AR9170_MAC_REG_RX_THRESHOLD (AR9170_MAC_REG_BASE + 0x640) -#define AR9170_MAC_REG_RX_PE_DELAY (AR9170_MAC_REG_BASE + 0x64C) - -#define AR9170_MAC_REG_DYNAMIC_SIFS_ACK (AR9170_MAC_REG_BASE + 0x658) -#define AR9170_MAC_REG_SNIFFER (AR9170_MAC_REG_BASE + 0x674) -#define AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC BIT(0) -#define AR9170_MAC_REG_SNIFFER_DEFAULTS 0x02000000 -#define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678) -#define AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE BIT(3) -#define AR9170_MAC_REG_ENCRYPTION_DEFAULTS 0x70 - -#define AR9170_MAC_REG_MISC_680 (AR9170_MAC_REG_BASE + 0x680) -#define AR9170_MAC_REG_TX_UNDERRUN (AR9170_MAC_REG_BASE + 0x688) - -#define AR9170_MAC_REG_FRAMETYPE_FILTER (AR9170_MAC_REG_BASE + 0x68c) -#define AR9170_MAC_REG_FTF_ASSOC_REQ BIT(0) -#define AR9170_MAC_REG_FTF_ASSOC_RESP BIT(1) -#define AR9170_MAC_REG_FTF_REASSOC_REQ BIT(2) -#define AR9170_MAC_REG_FTF_REASSOC_RESP BIT(3) -#define AR9170_MAC_REG_FTF_PRB_REQ BIT(4) -#define AR9170_MAC_REG_FTF_PRB_RESP BIT(5) -#define AR9170_MAC_REG_FTF_BIT6 BIT(6) -#define AR9170_MAC_REG_FTF_BIT7 BIT(7) -#define AR9170_MAC_REG_FTF_BEACON BIT(8) -#define AR9170_MAC_REG_FTF_ATIM BIT(9) -#define AR9170_MAC_REG_FTF_DEASSOC BIT(10) -#define AR9170_MAC_REG_FTF_AUTH BIT(11) -#define AR9170_MAC_REG_FTF_DEAUTH BIT(12) -#define AR9170_MAC_REG_FTF_BIT13 BIT(13) -#define AR9170_MAC_REG_FTF_BIT14 BIT(14) -#define AR9170_MAC_REG_FTF_BIT15 BIT(15) -#define AR9170_MAC_REG_FTF_BAR BIT(24) -#define AR9170_MAC_REG_FTF_BA BIT(25) -#define AR9170_MAC_REG_FTF_PSPOLL BIT(26) -#define AR9170_MAC_REG_FTF_RTS BIT(27) -#define AR9170_MAC_REG_FTF_CTS BIT(28) -#define AR9170_MAC_REG_FTF_ACK BIT(29) -#define AR9170_MAC_REG_FTF_CFE BIT(30) -#define AR9170_MAC_REG_FTF_CFE_ACK BIT(31) -#define AR9170_MAC_REG_FTF_DEFAULTS 0x0700ffff -#define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff - -#define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0) -#define AR9170_MAC_REG_RX_CRC32 (AR9170_MAC_REG_BASE + 0x6A4) -#define AR9170_MAC_REG_RX_CRC16 (AR9170_MAC_REG_BASE + 0x6A8) -#define AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI (AR9170_MAC_REG_BASE + 0x6AC) -#define AR9170_MAC_REG_RX_OVERRUN (AR9170_MAC_REG_BASE + 0x6B0) -#define AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL (AR9170_MAC_REG_BASE + 0x6BC) -#define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6CC) -#define AR9170_MAC_REG_TX_TOTAL (AR9170_MAC_REG_BASE + 0x6F4) - - -#define AR9170_MAC_REG_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0x690) -#define AR9170_MAC_REG_EIFS_AND_SIFS (AR9170_MAC_REG_BASE + 0x698) - -#define AR9170_MAC_REG_SLOT_TIME (AR9170_MAC_REG_BASE + 0x6F0) - -#define AR9170_MAC_REG_POWERMANAGEMENT (AR9170_MAC_REG_BASE + 0x700) -#define AR9170_MAC_REG_POWERMGT_IBSS 0xe0 -#define AR9170_MAC_REG_POWERMGT_AP 0xa1 -#define AR9170_MAC_REG_POWERMGT_STA 0x2 -#define AR9170_MAC_REG_POWERMGT_AP_WDS 0x3 -#define AR9170_MAC_REG_POWERMGT_DEFAULTS (0xf << 24) - -#define AR9170_MAC_REG_ROLL_CALL_TBL_L (AR9170_MAC_REG_BASE + 0x704) -#define AR9170_MAC_REG_ROLL_CALL_TBL_H (AR9170_MAC_REG_BASE + 0x708) - -#define AR9170_MAC_REG_AC0_CW (AR9170_MAC_REG_BASE + 0xB00) -#define AR9170_MAC_REG_AC1_CW (AR9170_MAC_REG_BASE + 0xB04) -#define AR9170_MAC_REG_AC2_CW (AR9170_MAC_REG_BASE + 0xB08) -#define AR9170_MAC_REG_AC3_CW (AR9170_MAC_REG_BASE + 0xB0C) -#define AR9170_MAC_REG_AC4_CW (AR9170_MAC_REG_BASE + 0xB10) -#define AR9170_MAC_REG_AC1_AC0_AIFS (AR9170_MAC_REG_BASE + 0xB14) -#define AR9170_MAC_REG_AC3_AC2_AIFS (AR9170_MAC_REG_BASE + 0xB18) - -#define AR9170_MAC_REG_RETRY_MAX (AR9170_MAC_REG_BASE + 0xB28) - -#define AR9170_MAC_REG_FCS_SELECT (AR9170_MAC_REG_BASE + 0xBB0) -#define AR9170_MAC_FCS_SWFCS 0x1 -#define AR9170_MAC_FCS_FIFO_PROT 0x4 - - -#define AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND (AR9170_MAC_REG_BASE + 0xB30) - -#define AR9170_MAC_REG_AC1_AC0_TXOP (AR9170_MAC_REG_BASE + 0xB44) -#define AR9170_MAC_REG_AC3_AC2_TXOP (AR9170_MAC_REG_BASE + 0xB48) - -#define AR9170_MAC_REG_AMPDU_FACTOR (AR9170_MAC_REG_BASE + 0xB9C) -#define AR9170_MAC_REG_AMPDU_DENSITY (AR9170_MAC_REG_BASE + 0xBA0) - -#define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xC00) -#define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xC50) - -#define AR9170_MAC_REG_TXRX_MPI (AR9170_MAC_REG_BASE + 0xD7C) -#define AR9170_MAC_TXRX_MPI_TX_MPI_MASK 0x0000000f -#define AR9170_MAC_TXRX_MPI_TX_TO_MASK 0x0000fff0 -#define AR9170_MAC_TXRX_MPI_RX_MPI_MASK 0x000f0000 -#define AR9170_MAC_TXRX_MPI_RX_TO_MASK 0xfff00000 - -#define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xD84) -#define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xD88) -#define AR9170_MAC_REG_BCN_PLCP (AR9170_MAC_REG_BASE + 0xD90) -#define AR9170_MAC_REG_BCN_CTRL (AR9170_MAC_REG_BASE + 0xD94) -#define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xDA0) -#define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xDA4) - - -#define AR9170_PWR_REG_BASE 0x1D4000 - -#define AR9170_PWR_REG_CLOCK_SEL (AR9170_PWR_REG_BASE + 0x008) -#define AR9170_PWR_CLK_AHB_40MHZ 0 -#define AR9170_PWR_CLK_AHB_20_22MHZ 1 -#define AR9170_PWR_CLK_AHB_40_44MHZ 2 -#define AR9170_PWR_CLK_AHB_80_88MHZ 3 -#define AR9170_PWR_CLK_DAC_160_INV_DLY 0x70 - - -/* put beacon here in memory */ -#define AR9170_BEACON_BUFFER_ADDRESS 0x117900 - - -struct ar9170_tx_control { - __le16 length; - __le16 mac_control; - __le32 phy_control; - u8 frame_data[0]; -} __packed; - -/* these are either-or */ -#define AR9170_TX_MAC_PROT_RTS 0x0001 -#define AR9170_TX_MAC_PROT_CTS 0x0002 - -#define AR9170_TX_MAC_NO_ACK 0x0004 -/* if unset, MAC will only do SIFS space before frame */ -#define AR9170_TX_MAC_BACKOFF 0x0008 -#define AR9170_TX_MAC_BURST 0x0010 -#define AR9170_TX_MAC_AGGR 0x0020 - -/* encryption is a two-bit field */ -#define AR9170_TX_MAC_ENCR_NONE 0x0000 -#define AR9170_TX_MAC_ENCR_RC4 0x0040 -#define AR9170_TX_MAC_ENCR_CENC 0x0080 -#define AR9170_TX_MAC_ENCR_AES 0x00c0 - -#define AR9170_TX_MAC_MMIC 0x0100 -#define AR9170_TX_MAC_HW_DURATION 0x0200 -#define AR9170_TX_MAC_QOS_SHIFT 10 -#define AR9170_TX_MAC_QOS_MASK (3 << AR9170_TX_MAC_QOS_SHIFT) -#define AR9170_TX_MAC_AGGR_QOS_BIT1 0x0400 -#define AR9170_TX_MAC_AGGR_QOS_BIT2 0x0800 -#define AR9170_TX_MAC_DISABLE_TXOP 0x1000 -#define AR9170_TX_MAC_TXOP_RIFS 0x2000 -#define AR9170_TX_MAC_IMM_AMPDU 0x4000 -#define AR9170_TX_MAC_RATE_PROBE 0x8000 - -/* either-or */ -#define AR9170_TX_PHY_MOD_MASK 0x00000003 -#define AR9170_TX_PHY_MOD_CCK 0x00000000 -#define AR9170_TX_PHY_MOD_OFDM 0x00000001 -#define AR9170_TX_PHY_MOD_HT 0x00000002 - -/* depends on modulation */ -#define AR9170_TX_PHY_SHORT_PREAMBLE 0x00000004 -#define AR9170_TX_PHY_GREENFIELD 0x00000004 - -#define AR9170_TX_PHY_BW_SHIFT 3 -#define AR9170_TX_PHY_BW_MASK (3 << AR9170_TX_PHY_BW_SHIFT) -#define AR9170_TX_PHY_BW_20MHZ 0 -#define AR9170_TX_PHY_BW_40MHZ 2 -#define AR9170_TX_PHY_BW_40MHZ_DUP 3 - -#define AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT 6 -#define AR9170_TX_PHY_TX_HEAVY_CLIP_MASK (7 << AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT) - -#define AR9170_TX_PHY_TX_PWR_SHIFT 9 -#define AR9170_TX_PHY_TX_PWR_MASK (0x3f << AR9170_TX_PHY_TX_PWR_SHIFT) - -/* not part of the hw-spec */ -#define AR9170_TX_PHY_QOS_SHIFT 25 -#define AR9170_TX_PHY_QOS_MASK (3 << AR9170_TX_PHY_QOS_SHIFT) - -#define AR9170_TX_PHY_TXCHAIN_SHIFT 15 -#define AR9170_TX_PHY_TXCHAIN_MASK (7 << AR9170_TX_PHY_TXCHAIN_SHIFT) -#define AR9170_TX_PHY_TXCHAIN_1 1 -/* use for cck, ofdm 6/9/12/18/24 and HT if capable */ -#define AR9170_TX_PHY_TXCHAIN_2 5 - -#define AR9170_TX_PHY_MCS_SHIFT 18 -#define AR9170_TX_PHY_MCS_MASK (0x7f << AR9170_TX_PHY_MCS_SHIFT) - -#define AR9170_TX_PHY_SHORT_GI 0x80000000 - -#define AR5416_MAX_RATE_POWER 63 - -struct ar9170_rx_head { - u8 plcp[12]; -} __packed; - -struct ar9170_rx_phystatus { - union { - struct { - u8 rssi_ant0, rssi_ant1, rssi_ant2, - rssi_ant0x, rssi_ant1x, rssi_ant2x, - rssi_combined; - } __packed; - u8 rssi[7]; - } __packed; - - u8 evm_stream0[6], evm_stream1[6]; - u8 phy_err; -} __packed; - -struct ar9170_rx_macstatus { - u8 SAidx, DAidx; - u8 error; - u8 status; -} __packed; - -#define AR9170_ENC_ALG_NONE 0x0 -#define AR9170_ENC_ALG_WEP64 0x1 -#define AR9170_ENC_ALG_TKIP 0x2 -#define AR9170_ENC_ALG_AESCCMP 0x4 -#define AR9170_ENC_ALG_WEP128 0x5 -#define AR9170_ENC_ALG_WEP256 0x6 -#define AR9170_ENC_ALG_CENC 0x7 - -#define AR9170_RX_ENC_SOFTWARE 0x8 - -static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t) -{ - return (t->SAidx & 0xc0) >> 4 | - (t->DAidx & 0xc0) >> 6; -} - -#define AR9170_RX_STATUS_MODULATION_MASK 0x03 -#define AR9170_RX_STATUS_MODULATION_CCK 0x00 -#define AR9170_RX_STATUS_MODULATION_OFDM 0x01 -#define AR9170_RX_STATUS_MODULATION_HT 0x02 -#define AR9170_RX_STATUS_MODULATION_DUPOFDM 0x03 - -/* depends on modulation */ -#define AR9170_RX_STATUS_SHORT_PREAMBLE 0x08 -#define AR9170_RX_STATUS_GREENFIELD 0x08 - -#define AR9170_RX_STATUS_MPDU_MASK 0x30 -#define AR9170_RX_STATUS_MPDU_SINGLE 0x00 -#define AR9170_RX_STATUS_MPDU_FIRST 0x20 -#define AR9170_RX_STATUS_MPDU_MIDDLE 0x30 -#define AR9170_RX_STATUS_MPDU_LAST 0x10 - -#define AR9170_RX_ERROR_RXTO 0x01 -#define AR9170_RX_ERROR_OVERRUN 0x02 -#define AR9170_RX_ERROR_DECRYPT 0x04 -#define AR9170_RX_ERROR_FCS 0x08 -#define AR9170_RX_ERROR_WRONG_RA 0x10 -#define AR9170_RX_ERROR_PLCP 0x20 -#define AR9170_RX_ERROR_MMIC 0x40 -#define AR9170_RX_ERROR_FATAL 0x80 - -struct ar9170_cmd_tx_status { - u8 dst[ETH_ALEN]; - __le32 rate; - __le16 status; -} __packed; - -#define AR9170_TX_STATUS_COMPLETE 0x00 -#define AR9170_TX_STATUS_RETRY 0x01 -#define AR9170_TX_STATUS_FAILED 0x02 - -struct ar9170_cmd_ba_failed_count { - __le16 failed; - __le16 rate; -} __packed; - -struct ar9170_cmd_response { - u8 flag; - u8 type; - __le16 padding; - - union { - struct ar9170_cmd_tx_status tx_status; - struct ar9170_cmd_ba_failed_count ba_fail_cnt; - u8 data[0]; - }; -} __packed; - -/* QoS */ - -/* mac80211 queue to HW/FW map */ -static const u8 ar9170_qos_hwmap[4] = { 3, 2, 0, 1 }; - -/* HW/FW queue to mac80211 map */ -static const u8 ar9170_qos_mac80211map[4] = { 2, 3, 1, 0 }; - -enum ar9170_txq { - AR9170_TXQ_BE, - AR9170_TXQ_BK, - AR9170_TXQ_VI, - AR9170_TXQ_VO, - - __AR9170_NUM_TXQ, -}; - -#define AR9170_TXQ_DEPTH 32 -#define AR9170_TX_MAX_PENDING 128 -#define AR9170_RX_STREAM_MAX_SIZE 65535 - -#endif /* __AR9170_HW_H */ diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c deleted file mode 100644 index 832d90087f8a..000000000000 --- a/drivers/net/wireless/ath/ar9170/led.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Atheros AR9170 driver - * - * LED handling - * - * Copyright 2008, Johannes Berg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ar9170.h" -#include "cmd.h" - -int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state) -{ - return ar9170_write_reg(ar, AR9170_GPIO_REG_DATA, led_state); -} - -int ar9170_init_leds(struct ar9170 *ar) -{ - int err; - - /* disable LEDs */ - /* GPIO [0/1 mode: output, 2/3: input] */ - err = ar9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3); - if (err) - goto out; - - /* GPIO 0/1 value: off */ - err = ar9170_set_leds_state(ar, 0); - -out: - return err; -} - -#ifdef CONFIG_AR9170_LEDS -static void ar9170_update_leds(struct work_struct *work) -{ - struct ar9170 *ar = container_of(work, struct ar9170, led_work.work); - int i, tmp, blink_delay = 1000; - u32 led_val = 0; - bool rerun = false; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return ; - - mutex_lock(&ar->mutex); - for (i = 0; i < AR9170_NUM_LEDS; i++) - if (ar->leds[i].registered && ar->leds[i].toggled) { - led_val |= 1 << i; - - tmp = 70 + 200 / (ar->leds[i].toggled); - if (tmp < blink_delay) - blink_delay = tmp; - - if (ar->leds[i].toggled > 1) - ar->leds[i].toggled = 0; - - rerun = true; - } - - ar9170_set_leds_state(ar, led_val); - mutex_unlock(&ar->mutex); - - if (!rerun) - return; - - ieee80211_queue_delayed_work(ar->hw, - &ar->led_work, - msecs_to_jiffies(blink_delay)); -} - -static void ar9170_led_brightness_set(struct led_classdev *led, - enum led_brightness brightness) -{ - struct ar9170_led *arl = container_of(led, struct ar9170_led, l); - struct ar9170 *ar = arl->ar; - - if (unlikely(!arl->registered)) - return ; - - if (arl->last_state != !!brightness) { - arl->toggled++; - arl->last_state = !!brightness; - } - - if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled)) - ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10); -} - -static int ar9170_register_led(struct ar9170 *ar, int i, char *name, - char *trigger) -{ - int err; - - snprintf(ar->leds[i].name, sizeof(ar->leds[i].name), - "ar9170-%s::%s", wiphy_name(ar->hw->wiphy), name); - - ar->leds[i].ar = ar; - ar->leds[i].l.name = ar->leds[i].name; - ar->leds[i].l.brightness_set = ar9170_led_brightness_set; - ar->leds[i].l.brightness = 0; - ar->leds[i].l.default_trigger = trigger; - - err = led_classdev_register(wiphy_dev(ar->hw->wiphy), - &ar->leds[i].l); - if (err) - wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n", - ar->leds[i].name, err); - else - ar->leds[i].registered = true; - - return err; -} - -void ar9170_unregister_leds(struct ar9170 *ar) -{ - int i; - - for (i = 0; i < AR9170_NUM_LEDS; i++) - if (ar->leds[i].registered) { - led_classdev_unregister(&ar->leds[i].l); - ar->leds[i].registered = false; - ar->leds[i].toggled = 0; - } - - cancel_delayed_work_sync(&ar->led_work); -} - -int ar9170_register_leds(struct ar9170 *ar) -{ - int err; - - INIT_DELAYED_WORK(&ar->led_work, ar9170_update_leds); - - err = ar9170_register_led(ar, 0, "tx", - ieee80211_get_tx_led_name(ar->hw)); - if (err) - goto fail; - - err = ar9170_register_led(ar, 1, "assoc", - ieee80211_get_assoc_led_name(ar->hw)); - if (err) - goto fail; - - return 0; - -fail: - ar9170_unregister_leds(ar); - return err; -} - -#endif /* CONFIG_AR9170_LEDS */ diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c deleted file mode 100644 index 857e86104295..000000000000 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - * Atheros AR9170 driver - * - * MAC programming - * - * Copyright 2008, Johannes Berg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include "ar9170.h" -#include "cmd.h" - -int ar9170_set_dyn_sifs_ack(struct ar9170 *ar) -{ - u32 val; - - if (conf_is_ht40(&ar->hw->conf)) - val = 0x010a; - else { - if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) - val = 0x105; - else - val = 0x104; - } - - return ar9170_write_reg(ar, AR9170_MAC_REG_DYNAMIC_SIFS_ACK, val); -} - -int ar9170_set_slot_time(struct ar9170 *ar) -{ - u32 slottime = 20; - - if (!ar->vif) - return 0; - - if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) || - ar->vif->bss_conf.use_short_slot) - slottime = 9; - - return ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, slottime << 10); -} - -int ar9170_set_basic_rates(struct ar9170 *ar) -{ - u8 cck, ofdm; - - if (!ar->vif) - return 0; - - ofdm = ar->vif->bss_conf.basic_rates >> 4; - - /* FIXME: is still necessary? */ - if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) - cck = 0; - else - cck = ar->vif->bss_conf.basic_rates & 0xf; - - return ar9170_write_reg(ar, AR9170_MAC_REG_BASIC_RATE, - ofdm << 8 | cck); -} - -int ar9170_set_qos(struct ar9170 *ar) -{ - ar9170_regwrite_begin(ar); - - ar9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min | - (ar->edcf[0].cw_max << 16)); - ar9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min | - (ar->edcf[1].cw_max << 16)); - ar9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min | - (ar->edcf[2].cw_max << 16)); - ar9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min | - (ar->edcf[3].cw_max << 16)); - ar9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min | - (ar->edcf[4].cw_max << 16)); - - ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_AIFS, - ((ar->edcf[0].aifs * 9 + 10)) | - ((ar->edcf[1].aifs * 9 + 10) << 12) | - ((ar->edcf[2].aifs * 9 + 10) << 24)); - ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_AIFS, - ((ar->edcf[2].aifs * 9 + 10) >> 8) | - ((ar->edcf[3].aifs * 9 + 10) << 4) | - ((ar->edcf[4].aifs * 9 + 10) << 16)); - - ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, - ar->edcf[0].txop | ar->edcf[1].txop << 16); - ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, - ar->edcf[2].txop | ar->edcf[3].txop << 16); - - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -static int ar9170_set_ampdu_density(struct ar9170 *ar, u8 mpdudensity) -{ - u32 val; - - /* don't allow AMPDU density > 8us */ - if (mpdudensity > 6) - return -EINVAL; - - /* Watch out! Otus uses slightly different density values. */ - val = 0x140a00 | (mpdudensity ? (mpdudensity + 1) : 0); - - ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, val); - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_init_mac(struct ar9170 *ar) -{ - ar9170_regwrite_begin(ar); - - ar9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40); - - ar9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0); - - /* enable MMIC */ - ar9170_regwrite(AR9170_MAC_REG_SNIFFER, - AR9170_MAC_REG_SNIFFER_DEFAULTS); - - ar9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80); - - ar9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70); - ar9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000); - ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10); - - /* CF-END mode */ - ar9170_regwrite(0x1c3b2c, 0x19000000); - - /* NAV protects ACK only (in TXOP) */ - ar9170_regwrite(0x1c3b38, 0x201); - - /* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */ - /* OTUS set AM to 0x1 */ - ar9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170); - - ar9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105); - - /* AGG test code*/ - /* Aggregation MAX number and timeout */ - ar9170_regwrite(0x1c3b9c, 0x10000a); - - ar9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, - AR9170_MAC_REG_FTF_DEFAULTS); - - /* Enable deaggregator, response in sniffer mode */ - ar9170_regwrite(0x1c3c40, 0x1 | 1<<30); - - /* rate sets */ - ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f); - ar9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f); - ar9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x10b01bb); - - /* MIMO response control */ - ar9170_regwrite(0x1c3694, 0x4003C1E);/* bit 26~28 otus-AM */ - - /* switch MAC to OTUS interface */ - ar9170_regwrite(0x1c3600, 0x3); - - ar9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff); - - /* set PHY register read timeout (??) */ - ar9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008); - - /* Disable Rx TimeOut, workaround for BB. */ - ar9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0); - - /* Set CPU clock frequency to 88/80MHz */ - ar9170_regwrite(AR9170_PWR_REG_CLOCK_SEL, - AR9170_PWR_CLK_AHB_80_88MHZ | - AR9170_PWR_CLK_DAC_160_INV_DLY); - - /* Set WLAN DMA interrupt mode: generate int per packet */ - ar9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011); - - ar9170_regwrite(AR9170_MAC_REG_FCS_SELECT, - AR9170_MAC_FCS_FIFO_PROT); - - /* Disables the CF_END frame, undocumented register */ - ar9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND, - 0x141E0F48); - - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac) -{ - static const u8 zero[ETH_ALEN] = { 0 }; - - if (!mac) - mac = zero; - - ar9170_regwrite_begin(ar); - - ar9170_regwrite(reg, get_unaligned_le32(mac)); - ar9170_regwrite(reg + 4, get_unaligned_le16(mac + 4)); - - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hash) -{ - int err; - - ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32); - ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash); - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - if (err) - return err; - - ar->cur_mc_hash = mc_hash; - return 0; -} - -int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter) -{ - int err; - - err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, filter); - if (err) - return err; - - ar->cur_filter = filter; - return 0; -} - -static int ar9170_set_promiscouous(struct ar9170 *ar) -{ - u32 encr_mode, sniffer; - int err; - - err = ar9170_read_reg(ar, AR9170_MAC_REG_SNIFFER, &sniffer); - if (err) - return err; - - err = ar9170_read_reg(ar, AR9170_MAC_REG_ENCRYPTION, &encr_mode); - if (err) - return err; - - if (ar->sniffer_enabled) { - sniffer |= AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; - - /* - * Rx decryption works in place. - * - * If we don't disable it, the hardware will render all - * encrypted frames which are encrypted with an unknown - * key useless. - */ - - encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; - ar->sniffer_enabled = true; - } else { - sniffer &= ~AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; - - if (ar->rx_software_decryption) - encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; - else - encr_mode &= ~AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; - } - - ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_ENCRYPTION, encr_mode); - ar9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer); - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_set_operating_mode(struct ar9170 *ar) -{ - struct ath_common *common = &ar->common; - u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS; - u8 *mac_addr, *bssid; - int err; - - if (ar->vif) { - mac_addr = common->macaddr; - bssid = common->curbssid; - - switch (ar->vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_ADHOC: - pm_mode |= AR9170_MAC_REG_POWERMGT_IBSS; - break; - case NL80211_IFTYPE_AP: - pm_mode |= AR9170_MAC_REG_POWERMGT_AP; - break; - case NL80211_IFTYPE_WDS: - pm_mode |= AR9170_MAC_REG_POWERMGT_AP_WDS; - break; - case NL80211_IFTYPE_MONITOR: - ar->sniffer_enabled = true; - ar->rx_software_decryption = true; - break; - default: - pm_mode |= AR9170_MAC_REG_POWERMGT_STA; - break; - } - } else { - mac_addr = NULL; - bssid = NULL; - } - - err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr); - if (err) - return err; - - err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid); - if (err) - return err; - - err = ar9170_set_promiscouous(ar); - if (err) - return err; - - /* set AMPDU density to 8us. */ - err = ar9170_set_ampdu_density(ar, 6); - if (err) - return err; - - ar9170_regwrite_begin(ar); - - ar9170_regwrite(AR9170_MAC_REG_POWERMANAGEMENT, pm_mode); - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_set_hwretry_limit(struct ar9170 *ar, unsigned int max_retry) -{ - u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111); - - return ar9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp); -} - -int ar9170_set_beacon_timers(struct ar9170 *ar) -{ - u32 v = 0; - u32 pretbtt = 0; - - if (ar->vif) { - v |= ar->vif->bss_conf.beacon_int; - - if (ar->enable_beacon) { - switch (ar->vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_ADHOC: - v |= BIT(25); - break; - case NL80211_IFTYPE_AP: - v |= BIT(24); - pretbtt = (ar->vif->bss_conf.beacon_int - 6) << - 16; - break; - default: - break; - } - } - - v |= ar->vif->bss_conf.dtim_period << 16; - } - - ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt); - ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v); - ar9170_regwrite_finish(); - return ar9170_regwrite_result(); -} - -int ar9170_update_beacon(struct ar9170 *ar) -{ - struct sk_buff *skb; - __le32 *data, *old = NULL; - u32 word; - int i; - - skb = ieee80211_beacon_get(ar->hw, ar->vif); - if (!skb) - return -ENOMEM; - - data = (__le32 *)skb->data; - if (ar->beacon) - old = (__le32 *)ar->beacon->data; - - ar9170_regwrite_begin(ar); - for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { - /* - * XXX: This accesses beyond skb data for up - * to the last 3 bytes!! - */ - - if (old && (data[i] == old[i])) - continue; - - word = le32_to_cpu(data[i]); - ar9170_regwrite(AR9170_BEACON_BUFFER_ADDRESS + 4 * i, word); - } - - /* XXX: use skb->cb info */ - if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) - ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, - ((skb->len + 4) << (3 + 16)) + 0x0400); - else - ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, - ((skb->len + 4) << 16) + 0x001b); - - ar9170_regwrite(AR9170_MAC_REG_BCN_LENGTH, skb->len + 4); - ar9170_regwrite(AR9170_MAC_REG_BCN_ADDR, AR9170_BEACON_BUFFER_ADDRESS); - ar9170_regwrite(AR9170_MAC_REG_BCN_CTRL, 1); - - ar9170_regwrite_finish(); - - dev_kfree_skb(ar->beacon); - ar->beacon = skb; - - return ar9170_regwrite_result(); -} - -void ar9170_new_beacon(struct work_struct *work) -{ - struct ar9170 *ar = container_of(work, struct ar9170, - beacon_work); - struct sk_buff *skb; - - if (unlikely(!IS_STARTED(ar))) - return ; - - mutex_lock(&ar->mutex); - - if (!ar->vif) - goto out; - - ar9170_update_beacon(ar); - - rcu_read_lock(); - while ((skb = ieee80211_get_buffered_bc(ar->hw, ar->vif))) - ar9170_op_tx(ar->hw, skb); - - rcu_read_unlock(); - - out: - mutex_unlock(&ar->mutex); -} - -int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, - u8 keyidx, u8 *keydata, int keylen) -{ - __le32 vals[7]; - static const u8 bcast[ETH_ALEN] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - u8 dummy; - - mac = mac ? : bcast; - - vals[0] = cpu_to_le32((keyidx << 16) + id); - vals[1] = cpu_to_le32(mac[1] << 24 | mac[0] << 16 | ktype); - vals[2] = cpu_to_le32(mac[5] << 24 | mac[4] << 16 | - mac[3] << 8 | mac[2]); - memset(&vals[3], 0, 16); - if (keydata) - memcpy(&vals[3], keydata, keylen); - - return ar->exec_cmd(ar, AR9170_CMD_EKEY, - sizeof(vals), (u8 *)vals, - 1, &dummy); -} - -int ar9170_disable_key(struct ar9170 *ar, u8 id) -{ - __le32 val = cpu_to_le32(id); - u8 dummy; - - return ar->exec_cmd(ar, AR9170_CMD_EKEY, - sizeof(val), (u8 *)&val, - 1, &dummy); -} diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c deleted file mode 100644 index b761fec0d721..000000000000 --- a/drivers/net/wireless/ath/ar9170/main.c +++ /dev/null @@ -1,2190 +0,0 @@ -/* - * Atheros AR9170 driver - * - * mac80211 interaction code - * - * Copyright 2008, Johannes Berg - * Copyright 2009, Christian Lamparter - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include "ar9170.h" -#include "hw.h" -#include "cmd.h" - -static int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); - -#define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ - .bitrate = (_bitrate), \ - .flags = (_flags), \ - .hw_value = (_hw_rate) | (_txpidx) << 4, \ -} - -static struct ieee80211_rate __ar9170_ratetable[] = { - RATE(10, 0, 0, 0), - RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE), - RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE), - RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE), - RATE(60, 0xb, 0, 0), - RATE(90, 0xf, 0, 0), - RATE(120, 0xa, 0, 0), - RATE(180, 0xe, 0, 0), - RATE(240, 0x9, 0, 0), - RATE(360, 0xd, 1, 0), - RATE(480, 0x8, 2, 0), - RATE(540, 0xc, 3, 0), -}; -#undef RATE - -#define ar9170_g_ratetable (__ar9170_ratetable + 0) -#define ar9170_g_ratetable_size 12 -#define ar9170_a_ratetable (__ar9170_ratetable + 4) -#define ar9170_a_ratetable_size 8 - -/* - * NB: The hw_value is used as an index into the ar9170_phy_freq_params - * array in phy.c so that we don't have to do frequency lookups! - */ -#define CHAN(_freq, _idx) { \ - .center_freq = (_freq), \ - .hw_value = (_idx), \ - .max_power = 18, /* XXX */ \ -} - -static struct ieee80211_channel ar9170_2ghz_chantable[] = { - CHAN(2412, 0), - CHAN(2417, 1), - CHAN(2422, 2), - CHAN(2427, 3), - CHAN(2432, 4), - CHAN(2437, 5), - CHAN(2442, 6), - CHAN(2447, 7), - CHAN(2452, 8), - CHAN(2457, 9), - CHAN(2462, 10), - CHAN(2467, 11), - CHAN(2472, 12), - CHAN(2484, 13), -}; - -static struct ieee80211_channel ar9170_5ghz_chantable[] = { - CHAN(4920, 14), - CHAN(4940, 15), - CHAN(4960, 16), - CHAN(4980, 17), - CHAN(5040, 18), - CHAN(5060, 19), - CHAN(5080, 20), - CHAN(5180, 21), - CHAN(5200, 22), - CHAN(5220, 23), - CHAN(5240, 24), - CHAN(5260, 25), - CHAN(5280, 26), - CHAN(5300, 27), - CHAN(5320, 28), - CHAN(5500, 29), - CHAN(5520, 30), - CHAN(5540, 31), - CHAN(5560, 32), - CHAN(5580, 33), - CHAN(5600, 34), - CHAN(5620, 35), - CHAN(5640, 36), - CHAN(5660, 37), - CHAN(5680, 38), - CHAN(5700, 39), - CHAN(5745, 40), - CHAN(5765, 41), - CHAN(5785, 42), - CHAN(5805, 43), - CHAN(5825, 44), - CHAN(5170, 45), - CHAN(5190, 46), - CHAN(5210, 47), - CHAN(5230, 48), -}; -#undef CHAN - -#define AR9170_HT_CAP \ -{ \ - .ht_supported = true, \ - .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ - IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ - IEEE80211_HT_CAP_SGI_40 | \ - IEEE80211_HT_CAP_GRN_FLD | \ - IEEE80211_HT_CAP_DSSSCCK40 | \ - IEEE80211_HT_CAP_SM_PS, \ - .ampdu_factor = 3, \ - .ampdu_density = 6, \ - .mcs = { \ - .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \ - .rx_highest = cpu_to_le16(300), \ - .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ - }, \ -} - -static struct ieee80211_supported_band ar9170_band_2GHz = { - .channels = ar9170_2ghz_chantable, - .n_channels = ARRAY_SIZE(ar9170_2ghz_chantable), - .bitrates = ar9170_g_ratetable, - .n_bitrates = ar9170_g_ratetable_size, - .ht_cap = AR9170_HT_CAP, -}; - -static struct ieee80211_supported_band ar9170_band_5GHz = { - .channels = ar9170_5ghz_chantable, - .n_channels = ARRAY_SIZE(ar9170_5ghz_chantable), - .bitrates = ar9170_a_ratetable, - .n_bitrates = ar9170_a_ratetable_size, - .ht_cap = AR9170_HT_CAP, -}; - -static void ar9170_tx(struct ar9170 *ar); - -static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr) -{ - return le16_to_cpu(hdr->seq_ctrl) >> 4; -} - -static inline u16 ar9170_get_seq(struct sk_buff *skb) -{ - struct ar9170_tx_control *txc = (void *) skb->data; - return ar9170_get_seq_h((void *) txc->frame_data); -} - -#ifdef AR9170_QUEUE_DEBUG -static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); - struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; - struct ieee80211_hdr *hdr = (void *) txc->frame_data; - - wiphy_debug(ar->hw->wiphy, - "=> FRAME [skb:%p, q:%d, DA:[%pM] s:%d " - "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", - skb, skb_get_queue_mapping(skb), - ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr), - le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), - jiffies_to_msecs(arinfo->timeout - jiffies)); -} - -static void __ar9170_dump_txqueue(struct ar9170 *ar, - struct sk_buff_head *queue) -{ - struct sk_buff *skb; - int i = 0; - - printk(KERN_DEBUG "---[ cut here ]---\n"); - wiphy_debug(ar->hw->wiphy, "%d entries in queue.\n", - skb_queue_len(queue)); - - skb_queue_walk(queue, skb) { - printk(KERN_DEBUG "index:%d =>\n", i++); - ar9170_print_txheader(ar, skb); - } - if (i != skb_queue_len(queue)) - printk(KERN_DEBUG "WARNING: queue frame counter " - "mismatch %d != %d\n", skb_queue_len(queue), i); - printk(KERN_DEBUG "---[ end ]---\n"); -} -#endif /* AR9170_QUEUE_DEBUG */ - -#ifdef AR9170_QUEUE_DEBUG -static void ar9170_dump_txqueue(struct ar9170 *ar, - struct sk_buff_head *queue) -{ - unsigned long flags; - - spin_lock_irqsave(&queue->lock, flags); - __ar9170_dump_txqueue(ar, queue); - spin_unlock_irqrestore(&queue->lock, flags); -} -#endif /* AR9170_QUEUE_DEBUG */ - -#ifdef AR9170_QUEUE_STOP_DEBUG -static void __ar9170_dump_txstats(struct ar9170 *ar) -{ - int i; - - wiphy_debug(ar->hw->wiphy, "QoS queue stats\n"); - - for (i = 0; i < __AR9170_NUM_TXQ; i++) - wiphy_debug(ar->hw->wiphy, - "queue:%d limit:%d len:%d waitack:%d stopped:%d\n", - i, ar->tx_stats[i].limit, ar->tx_stats[i].len, - skb_queue_len(&ar->tx_status[i]), - ieee80211_queue_stopped(ar->hw, i)); -} -#endif /* AR9170_QUEUE_STOP_DEBUG */ - -/* caller must guarantee exclusive access for _bin_ queue. */ -static void ar9170_recycle_expired(struct ar9170 *ar, - struct sk_buff_head *queue, - struct sk_buff_head *bin) -{ - struct sk_buff *skb, *old = NULL; - unsigned long flags; - - spin_lock_irqsave(&queue->lock, flags); - while ((skb = skb_peek(queue))) { - struct ieee80211_tx_info *txinfo; - struct ar9170_tx_info *arinfo; - - txinfo = IEEE80211_SKB_CB(skb); - arinfo = (void *) txinfo->rate_driver_data; - - if (time_is_before_jiffies(arinfo->timeout)) { -#ifdef AR9170_QUEUE_DEBUG - wiphy_debug(ar->hw->wiphy, - "[%ld > %ld] frame expired => recycle\n", - jiffies, arinfo->timeout); - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - __skb_unlink(skb, queue); - __skb_queue_tail(bin, skb); - } else { - break; - } - - if (unlikely(old == skb)) { - /* bail out - queue is shot. */ - - WARN_ON(1); - break; - } - old = skb; - } - spin_unlock_irqrestore(&queue->lock, flags); -} - -static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, - u16 tx_status) -{ - struct ieee80211_tx_info *txinfo; - unsigned int retries = 0; - - txinfo = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(txinfo); - - switch (tx_status) { - case AR9170_TX_STATUS_RETRY: - retries = 2; - case AR9170_TX_STATUS_COMPLETE: - txinfo->flags |= IEEE80211_TX_STAT_ACK; - break; - - case AR9170_TX_STATUS_FAILED: - retries = ar->hw->conf.long_frame_max_tx_count; - break; - - default: - wiphy_err(ar->hw->wiphy, - "invalid tx_status response (%x)\n", tx_status); - break; - } - - txinfo->status.rates[0].count = retries + 1; - skb_pull(skb, sizeof(struct ar9170_tx_control)); - ieee80211_tx_status_irqsafe(ar->hw, skb); -} - -void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ar9170_tx_info *arinfo = (void *) info->rate_driver_data; - unsigned int queue = skb_get_queue_mapping(skb); - unsigned long flags; - - spin_lock_irqsave(&ar->tx_stats_lock, flags); - ar->tx_stats[queue].len--; - - if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) { -#ifdef AR9170_QUEUE_STOP_DEBUG - wiphy_debug(ar->hw->wiphy, "wake queue %d\n", queue); - __ar9170_dump_txstats(ar); -#endif /* AR9170_QUEUE_STOP_DEBUG */ - ieee80211_wake_queue(ar->hw, queue); - } - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - - if (info->flags & IEEE80211_TX_CTL_NO_ACK) { - ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); - } else { - arinfo->timeout = jiffies + - msecs_to_jiffies(AR9170_TX_TIMEOUT); - - skb_queue_tail(&ar->tx_status[queue], skb); - } - - if (!ar->tx_stats[queue].len && - !skb_queue_empty(&ar->tx_pending[queue])) { - ar9170_tx(ar); - } -} - -static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, - const u8 *mac, - struct sk_buff_head *queue, - const u32 rate) -{ - unsigned long flags; - struct sk_buff *skb; - - /* - * Unfortunately, the firmware does not tell to which (queued) frame - * this transmission status report belongs to. - * - * So we have to make risky guesses - with the scarce information - * the firmware provided (-> destination MAC, and phy_control) - - * and hope that we picked the right one... - */ - - spin_lock_irqsave(&queue->lock, flags); - skb_queue_walk(queue, skb) { - struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *) txc->frame_data; - u32 r; - - if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) { -#ifdef AR9170_QUEUE_DEBUG - wiphy_debug(ar->hw->wiphy, - "skip frame => DA %pM != %pM\n", - mac, ieee80211_get_DA(hdr)); - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - continue; - } - - r = (le32_to_cpu(txc->phy_control) & AR9170_TX_PHY_MCS_MASK) >> - AR9170_TX_PHY_MCS_SHIFT; - - if ((rate != AR9170_TX_INVALID_RATE) && (r != rate)) { -#ifdef AR9170_QUEUE_DEBUG - wiphy_debug(ar->hw->wiphy, - "skip frame => rate %d != %d\n", rate, r); - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - continue; - } - - __skb_unlink(skb, queue); - spin_unlock_irqrestore(&queue->lock, flags); - return skb; - } - -#ifdef AR9170_QUEUE_DEBUG - wiphy_err(ar->hw->wiphy, - "ESS:[%pM] does not have any outstanding frames in queue.\n", - mac); - __ar9170_dump_txqueue(ar, queue); -#endif /* AR9170_QUEUE_DEBUG */ - spin_unlock_irqrestore(&queue->lock, flags); - - return NULL; -} - -/* - * This worker tries to keeps an maintain tx_status queues. - * So we can guarantee that incoming tx_status reports are - * actually for a pending frame. - */ - -static void ar9170_tx_janitor(struct work_struct *work) -{ - struct ar9170 *ar = container_of(work, struct ar9170, - tx_janitor.work); - struct sk_buff_head waste; - unsigned int i; - bool resched = false; - - if (unlikely(!IS_STARTED(ar))) - return ; - - skb_queue_head_init(&waste); - - for (i = 0; i < __AR9170_NUM_TXQ; i++) { -#ifdef AR9170_QUEUE_DEBUG - wiphy_debug(ar->hw->wiphy, "garbage collector scans queue:%d\n", - i); - ar9170_dump_txqueue(ar, &ar->tx_pending[i]); - ar9170_dump_txqueue(ar, &ar->tx_status[i]); -#endif /* AR9170_QUEUE_DEBUG */ - - ar9170_recycle_expired(ar, &ar->tx_status[i], &waste); - ar9170_recycle_expired(ar, &ar->tx_pending[i], &waste); - skb_queue_purge(&waste); - - if (!skb_queue_empty(&ar->tx_status[i]) || - !skb_queue_empty(&ar->tx_pending[i])) - resched = true; - } - - if (!resched) - return; - - ieee80211_queue_delayed_work(ar->hw, - &ar->tx_janitor, - msecs_to_jiffies(AR9170_JANITOR_DELAY)); -} - -void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) -{ - struct ar9170_cmd_response *cmd = (void *) buf; - - if ((cmd->type & 0xc0) != 0xc0) { - ar->callback_cmd(ar, len, buf); - return; - } - - /* hardware event handlers */ - switch (cmd->type) { - case 0xc1: { - /* - * TX status notification: - * bytes: 0c c1 XX YY M1 M2 M3 M4 M5 M6 R4 R3 R2 R1 S2 S1 - * - * XX always 81 - * YY always 00 - * M1-M6 is the MAC address - * R1-R4 is the transmit rate - * S1-S2 is the transmit status - */ - - struct sk_buff *skb; - u32 phy = le32_to_cpu(cmd->tx_status.rate); - u32 q = (phy & AR9170_TX_PHY_QOS_MASK) >> - AR9170_TX_PHY_QOS_SHIFT; -#ifdef AR9170_QUEUE_DEBUG - wiphy_debug(ar->hw->wiphy, - "recv tx_status for %pm, p:%08x, q:%d\n", - cmd->tx_status.dst, phy, q); -#endif /* AR9170_QUEUE_DEBUG */ - - skb = ar9170_get_queued_skb(ar, cmd->tx_status.dst, - &ar->tx_status[q], - AR9170_TX_INVALID_RATE); - if (unlikely(!skb)) - return ; - - ar9170_tx_status(ar, skb, le16_to_cpu(cmd->tx_status.status)); - break; - } - - case 0xc0: - /* - * pre-TBTT event - */ - if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP) - ieee80211_queue_work(ar->hw, &ar->beacon_work); - break; - - case 0xc2: - /* - * (IBSS) beacon send notification - * bytes: 04 c2 XX YY B4 B3 B2 B1 - * - * XX always 80 - * YY always 00 - * B1-B4 "should" be the number of send out beacons. - */ - break; - - case 0xc3: - /* End of Atim Window */ - break; - - case 0xc4: - /* BlockACK bitmap */ - break; - - case 0xc5: - /* BlockACK events */ - break; - - case 0xc6: - /* Watchdog Interrupt */ - break; - - case 0xc9: - /* retransmission issue / SIFS/EIFS collision ?! */ - break; - - /* firmware debug */ - case 0xca: - printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, - (char *)buf + 4); - break; - case 0xcb: - len -= 4; - - switch (len) { - case 1: - printk(KERN_DEBUG "ar9170 FW: u8: %#.2x\n", - *((char *)buf + 4)); - break; - case 2: - printk(KERN_DEBUG "ar9170 FW: u8: %#.4x\n", - le16_to_cpup((__le16 *)((char *)buf + 4))); - break; - case 4: - printk(KERN_DEBUG "ar9170 FW: u8: %#.8x\n", - le32_to_cpup((__le32 *)((char *)buf + 4))); - break; - case 8: - printk(KERN_DEBUG "ar9170 FW: u8: %#.16lx\n", - (unsigned long)le64_to_cpup( - (__le64 *)((char *)buf + 4))); - break; - } - break; - case 0xcc: - print_hex_dump_bytes("ar9170 FW:", DUMP_PREFIX_NONE, - (char *)buf + 4, len - 4); - break; - - default: - pr_info("received unhandled event %x\n", cmd->type); - print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len); - break; - } -} - -static void ar9170_rx_reset_rx_mpdu(struct ar9170 *ar) -{ - memset(&ar->rx_mpdu.plcp, 0, sizeof(struct ar9170_rx_head)); - ar->rx_mpdu.has_plcp = false; -} - -int ar9170_nag_limiter(struct ar9170 *ar) -{ - bool print_message; - - /* - * we expect all sorts of errors in promiscuous mode. - * don't bother with it, it's OK! - */ - if (ar->sniffer_enabled) - return false; - - /* - * only go for frequent errors! The hardware tends to - * do some stupid thing once in a while under load, in - * noisy environments or just for fun! - */ - if (time_before(jiffies, ar->bad_hw_nagger) && net_ratelimit()) - print_message = true; - else - print_message = false; - - /* reset threshold for "once in a while" */ - ar->bad_hw_nagger = jiffies + HZ / 4; - return print_message; -} - -static int ar9170_rx_mac_status(struct ar9170 *ar, - struct ar9170_rx_head *head, - struct ar9170_rx_macstatus *mac, - struct ieee80211_rx_status *status) -{ - u8 error, decrypt; - - BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12); - BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4); - - error = mac->error; - if (error & AR9170_RX_ERROR_MMIC) { - status->flag |= RX_FLAG_MMIC_ERROR; - error &= ~AR9170_RX_ERROR_MMIC; - } - - if (error & AR9170_RX_ERROR_PLCP) { - status->flag |= RX_FLAG_FAILED_PLCP_CRC; - error &= ~AR9170_RX_ERROR_PLCP; - - if (!(ar->filter_state & FIF_PLCPFAIL)) - return -EINVAL; - } - - if (error & AR9170_RX_ERROR_FCS) { - status->flag |= RX_FLAG_FAILED_FCS_CRC; - error &= ~AR9170_RX_ERROR_FCS; - - if (!(ar->filter_state & FIF_FCSFAIL)) - return -EINVAL; - } - - decrypt = ar9170_get_decrypt_type(mac); - if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && - decrypt != AR9170_ENC_ALG_NONE) - status->flag |= RX_FLAG_DECRYPTED; - - /* ignore wrong RA errors */ - error &= ~AR9170_RX_ERROR_WRONG_RA; - - if (error & AR9170_RX_ERROR_DECRYPT) { - error &= ~AR9170_RX_ERROR_DECRYPT; - /* - * Rx decryption is done in place, - * the original data is lost anyway. - */ - - return -EINVAL; - } - - /* drop any other error frames */ - if (unlikely(error)) { - /* TODO: update netdevice's RX dropped/errors statistics */ - - if (ar9170_nag_limiter(ar)) - wiphy_debug(ar->hw->wiphy, - "received frame with suspicious error code (%#x).\n", - error); - - return -EINVAL; - } - - status->band = ar->channel->band; - status->freq = ar->channel->center_freq; - - switch (mac->status & AR9170_RX_STATUS_MODULATION_MASK) { - case AR9170_RX_STATUS_MODULATION_CCK: - if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE) - status->flag |= RX_FLAG_SHORTPRE; - switch (head->plcp[0]) { - case 0x0a: - status->rate_idx = 0; - break; - case 0x14: - status->rate_idx = 1; - break; - case 0x37: - status->rate_idx = 2; - break; - case 0x6e: - status->rate_idx = 3; - break; - default: - if (ar9170_nag_limiter(ar)) - wiphy_err(ar->hw->wiphy, - "invalid plcp cck rate (%x).\n", - head->plcp[0]); - return -EINVAL; - } - break; - - case AR9170_RX_STATUS_MODULATION_DUPOFDM: - case AR9170_RX_STATUS_MODULATION_OFDM: - switch (head->plcp[0] & 0xf) { - case 0xb: - status->rate_idx = 0; - break; - case 0xf: - status->rate_idx = 1; - break; - case 0xa: - status->rate_idx = 2; - break; - case 0xe: - status->rate_idx = 3; - break; - case 0x9: - status->rate_idx = 4; - break; - case 0xd: - status->rate_idx = 5; - break; - case 0x8: - status->rate_idx = 6; - break; - case 0xc: - status->rate_idx = 7; - break; - default: - if (ar9170_nag_limiter(ar)) - wiphy_err(ar->hw->wiphy, - "invalid plcp ofdm rate (%x).\n", - head->plcp[0]); - return -EINVAL; - } - if (status->band == IEEE80211_BAND_2GHZ) - status->rate_idx += 4; - break; - - case AR9170_RX_STATUS_MODULATION_HT: - if (head->plcp[3] & 0x80) - status->flag |= RX_FLAG_40MHZ; - if (head->plcp[6] & 0x80) - status->flag |= RX_FLAG_SHORT_GI; - - status->rate_idx = clamp(0, 75, head->plcp[6] & 0x7f); - status->flag |= RX_FLAG_HT; - break; - - default: - if (ar9170_nag_limiter(ar)) - wiphy_err(ar->hw->wiphy, "invalid modulation\n"); - return -EINVAL; - } - - return 0; -} - -static void ar9170_rx_phy_status(struct ar9170 *ar, - struct ar9170_rx_phystatus *phy, - struct ieee80211_rx_status *status) -{ - int i; - - BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20); - - for (i = 0; i < 3; i++) - if (phy->rssi[i] != 0x80) - status->antenna |= BIT(i); - - /* post-process RSSI */ - for (i = 0; i < 7; i++) - if (phy->rssi[i] & 0x80) - phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f; - - /* TODO: we could do something with phy_errors */ - status->signal = ar->noise[0] + phy->rssi_combined; -} - -static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len) -{ - struct sk_buff *skb; - int reserved = 0; - struct ieee80211_hdr *hdr = (void *) buf; - - if (ieee80211_is_data_qos(hdr->frame_control)) { - u8 *qc = ieee80211_get_qos_ctl(hdr); - reserved += NET_IP_ALIGN; - - if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) - reserved += NET_IP_ALIGN; - } - - if (ieee80211_has_a4(hdr->frame_control)) - reserved += NET_IP_ALIGN; - - reserved = 32 + (reserved & NET_IP_ALIGN); - - skb = dev_alloc_skb(len + reserved); - if (likely(skb)) { - skb_reserve(skb, reserved); - memcpy(skb_put(skb, len), buf, len); - } - - return skb; -} - -/* - * If the frame alignment is right (or the kernel has - * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there - * is only a single MPDU in the USB frame, then we could - * submit to mac80211 the SKB directly. However, since - * there may be multiple packets in one SKB in stream - * mode, and we need to observe the proper ordering, - * this is non-trivial. - */ - -static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) -{ - struct ar9170_rx_head *head; - struct ar9170_rx_macstatus *mac; - struct ar9170_rx_phystatus *phy = NULL; - struct ieee80211_rx_status status; - struct sk_buff *skb; - int mpdu_len; - - if (unlikely(!IS_STARTED(ar) || len < (sizeof(*mac)))) - return ; - - /* Received MPDU */ - mpdu_len = len - sizeof(*mac); - - mac = (void *)(buf + mpdu_len); - if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) { - /* this frame is too damaged and can't be used - drop it */ - - return ; - } - - switch (mac->status & AR9170_RX_STATUS_MPDU_MASK) { - case AR9170_RX_STATUS_MPDU_FIRST: - /* first mpdu packet has the plcp header */ - if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) { - head = (void *) buf; - memcpy(&ar->rx_mpdu.plcp, (void *) buf, - sizeof(struct ar9170_rx_head)); - - mpdu_len -= sizeof(struct ar9170_rx_head); - buf += sizeof(struct ar9170_rx_head); - ar->rx_mpdu.has_plcp = true; - } else { - if (ar9170_nag_limiter(ar)) - wiphy_err(ar->hw->wiphy, - "plcp info is clipped.\n"); - return ; - } - break; - - case AR9170_RX_STATUS_MPDU_LAST: - /* last mpdu has a extra tail with phy status information */ - - if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) { - mpdu_len -= sizeof(struct ar9170_rx_phystatus); - phy = (void *)(buf + mpdu_len); - } else { - if (ar9170_nag_limiter(ar)) - wiphy_err(ar->hw->wiphy, - "frame tail is clipped.\n"); - return ; - } - - case AR9170_RX_STATUS_MPDU_MIDDLE: - /* middle mpdus are just data */ - if (unlikely(!ar->rx_mpdu.has_plcp)) { - if (!ar9170_nag_limiter(ar)) - return ; - - wiphy_err(ar->hw->wiphy, - "rx stream did not start with a first_mpdu frame tag.\n"); - - return ; - } - - head = &ar->rx_mpdu.plcp; - break; - - case AR9170_RX_STATUS_MPDU_SINGLE: - /* single mpdu - has plcp (head) and phy status (tail) */ - head = (void *) buf; - - mpdu_len -= sizeof(struct ar9170_rx_head); - mpdu_len -= sizeof(struct ar9170_rx_phystatus); - - buf += sizeof(struct ar9170_rx_head); - phy = (void *)(buf + mpdu_len); - break; - - default: - BUG_ON(1); - break; - } - - if (unlikely(mpdu_len < FCS_LEN)) - return ; - - memset(&status, 0, sizeof(status)); - if (unlikely(ar9170_rx_mac_status(ar, head, mac, &status))) - return ; - - if (phy) - ar9170_rx_phy_status(ar, phy, &status); - - skb = ar9170_rx_copy_data(buf, mpdu_len); - if (likely(skb)) { - memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - ieee80211_rx_irqsafe(ar->hw, skb); - } -} - -void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) -{ - unsigned int i, tlen, resplen, wlen = 0, clen = 0; - u8 *tbuf, *respbuf; - - tbuf = skb->data; - tlen = skb->len; - - while (tlen >= 4) { - clen = tbuf[1] << 8 | tbuf[0]; - wlen = ALIGN(clen, 4); - - /* check if this is stream has a valid tag.*/ - if (tbuf[2] != 0 || tbuf[3] != 0x4e) { - /* - * TODO: handle the highly unlikely event that the - * corrupted stream has the TAG at the right position. - */ - - /* check if the frame can be repaired. */ - if (!ar->rx_failover_missing) { - /* this is no "short read". */ - if (ar9170_nag_limiter(ar)) { - wiphy_err(ar->hw->wiphy, - "missing tag!\n"); - goto err_telluser; - } else - goto err_silent; - } - - if (ar->rx_failover_missing > tlen) { - if (ar9170_nag_limiter(ar)) { - wiphy_err(ar->hw->wiphy, - "possible multi stream corruption!\n"); - goto err_telluser; - } else - goto err_silent; - } - - memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); - ar->rx_failover_missing -= tlen; - - if (ar->rx_failover_missing <= 0) { - /* - * nested ar9170_rx call! - * termination is guranteed, even when the - * combined frame also have a element with - * a bad tag. - */ - - ar->rx_failover_missing = 0; - ar9170_rx(ar, ar->rx_failover); - - skb_reset_tail_pointer(ar->rx_failover); - skb_trim(ar->rx_failover, 0); - } - - return ; - } - - /* check if stream is clipped */ - if (wlen > tlen - 4) { - if (ar->rx_failover_missing) { - /* TODO: handle double stream corruption. */ - if (ar9170_nag_limiter(ar)) { - wiphy_err(ar->hw->wiphy, - "double rx stream corruption!\n"); - goto err_telluser; - } else - goto err_silent; - } - - /* - * save incomplete data set. - * the firmware will resend the missing bits when - * the rx - descriptor comes round again. - */ - - memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); - ar->rx_failover_missing = clen - tlen; - return ; - } - resplen = clen; - respbuf = tbuf + 4; - tbuf += wlen + 4; - tlen -= wlen + 4; - - i = 0; - - /* weird thing, but this is the same in the original driver */ - while (resplen > 2 && i < 12 && - respbuf[0] == 0xff && respbuf[1] == 0xff) { - i += 2; - resplen -= 2; - respbuf += 2; - } - - if (resplen < 4) - continue; - - /* found the 6 * 0xffff marker? */ - if (i == 12) - ar9170_handle_command_response(ar, respbuf, resplen); - else - ar9170_handle_mpdu(ar, respbuf, clen); - } - - if (tlen) { - if (net_ratelimit()) - wiphy_err(ar->hw->wiphy, - "%d bytes of unprocessed data left in rx stream!\n", - tlen); - - goto err_telluser; - } - - return ; - -err_telluser: - wiphy_err(ar->hw->wiphy, - "damaged RX stream data [want:%d, data:%d, rx:%d, pending:%d ]\n", - clen, wlen, tlen, ar->rx_failover_missing); - - if (ar->rx_failover_missing) - print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET, - ar->rx_failover->data, - ar->rx_failover->len); - - print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET, - skb->data, skb->len); - - wiphy_err(ar->hw->wiphy, - "If you see this message frequently, please check your hardware and cables.\n"); - -err_silent: - if (ar->rx_failover_missing) { - skb_reset_tail_pointer(ar->rx_failover); - skb_trim(ar->rx_failover, 0); - ar->rx_failover_missing = 0; - } -} - -#define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \ -do { \ - queue.aifs = ai_fs; \ - queue.cw_min = cwmin; \ - queue.cw_max = cwmax; \ - queue.txop = _txop; \ -} while (0) - -static int ar9170_op_start(struct ieee80211_hw *hw) -{ - struct ar9170 *ar = hw->priv; - int err, i; - - mutex_lock(&ar->mutex); - - /* reinitialize queues statistics */ - memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); - for (i = 0; i < __AR9170_NUM_TXQ; i++) - ar->tx_stats[i].limit = AR9170_TXQ_DEPTH; - - /* reset QoS defaults */ - AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT*/ - AR9170_FILL_QUEUE(ar->edcf[1], 7, 15, 1023, 0); /* BACKGROUND */ - AR9170_FILL_QUEUE(ar->edcf[2], 2, 7, 15, 94); /* VIDEO */ - AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ - AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ - - /* set sane AMPDU defaults */ - ar->global_ampdu_density = 6; - ar->global_ampdu_factor = 3; - - ar->bad_hw_nagger = jiffies; - - err = ar->open(ar); - if (err) - goto out; - - err = ar9170_init_mac(ar); - if (err) - goto out; - - err = ar9170_set_qos(ar); - if (err) - goto out; - - err = ar9170_init_phy(ar, IEEE80211_BAND_2GHZ); - if (err) - goto out; - - err = ar9170_init_rf(ar); - if (err) - goto out; - - /* start DMA */ - err = ar9170_write_reg(ar, 0x1c3d30, 0x100); - if (err) - goto out; - - ar->state = AR9170_STARTED; - -out: - mutex_unlock(&ar->mutex); - return err; -} - -static void ar9170_op_stop(struct ieee80211_hw *hw) -{ - struct ar9170 *ar = hw->priv; - unsigned int i; - - if (IS_STARTED(ar)) - ar->state = AR9170_IDLE; - - cancel_delayed_work_sync(&ar->tx_janitor); -#ifdef CONFIG_AR9170_LEDS - cancel_delayed_work_sync(&ar->led_work); -#endif - cancel_work_sync(&ar->beacon_work); - - mutex_lock(&ar->mutex); - - if (IS_ACCEPTING_CMD(ar)) { - ar9170_set_leds_state(ar, 0); - - /* stop DMA */ - ar9170_write_reg(ar, 0x1c3d30, 0); - ar->stop(ar); - } - - for (i = 0; i < __AR9170_NUM_TXQ; i++) { - skb_queue_purge(&ar->tx_pending[i]); - skb_queue_purge(&ar->tx_status[i]); - } - - mutex_unlock(&ar->mutex); -} - -static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - struct ar9170_tx_control *txc; - struct ieee80211_tx_info *info; - struct ieee80211_tx_rate *txrate; - struct ar9170_tx_info *arinfo; - unsigned int queue = skb_get_queue_mapping(skb); - u16 keytype = 0; - u16 len, icv = 0; - - BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); - - hdr = (void *)skb->data; - info = IEEE80211_SKB_CB(skb); - len = skb->len; - - txc = (void *)skb_push(skb, sizeof(*txc)); - - if (info->control.hw_key) { - icv = info->control.hw_key->icv_len; - - switch (info->control.hw_key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - case WLAN_CIPHER_SUITE_TKIP: - keytype = AR9170_TX_MAC_ENCR_RC4; - break; - case WLAN_CIPHER_SUITE_CCMP: - keytype = AR9170_TX_MAC_ENCR_AES; - break; - default: - WARN_ON(1); - goto err_out; - } - } - - /* Length */ - txc->length = cpu_to_le16(len + icv + 4); - - txc->mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | - AR9170_TX_MAC_BACKOFF); - txc->mac_control |= cpu_to_le16(ar9170_qos_hwmap[queue] << - AR9170_TX_MAC_QOS_SHIFT); - txc->mac_control |= cpu_to_le16(keytype); - txc->phy_control = cpu_to_le32(0); - - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); - - txrate = &info->control.rates[0]; - if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); - else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS) - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); - - arinfo = (void *)info->rate_driver_data; - arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_QUEUE_TIMEOUT); - - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && - (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { - /* - * WARNING: - * Putting the QoS queue bits into an unexplored territory is - * certainly not elegant. - * - * In my defense: This idea provides a reasonable way to - * smuggle valuable information to the tx_status callback. - * Also, the idea behind this bit-abuse came straight from - * the original driver code. - */ - - txc->phy_control |= - cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); - - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); - } - - return 0; - -err_out: - skb_pull(skb, sizeof(*txc)); - return -EINVAL; -} - -static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ar9170_tx_control *txc; - struct ieee80211_tx_info *info; - struct ieee80211_rate *rate = NULL; - struct ieee80211_tx_rate *txrate; - u32 power, chains; - - txc = (void *) skb->data; - info = IEEE80211_SKB_CB(skb); - txrate = &info->control.rates[0]; - - if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); - - if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE); - - if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ); - /* this works because 40 MHz is 2 and dup is 3 */ - if (txrate->flags & IEEE80211_TX_RC_DUP_DATA) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP); - - if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI); - - if (txrate->flags & IEEE80211_TX_RC_MCS) { - u32 r = txrate->idx; - u8 *txpower; - - /* heavy clip control */ - txc->phy_control |= cpu_to_le32((r & 0x7) << 7); - - r <<= AR9170_TX_PHY_MCS_SHIFT; - BUG_ON(r & ~AR9170_TX_PHY_MCS_MASK); - - txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK); - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT); - - if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { - if (info->band == IEEE80211_BAND_5GHZ) - txpower = ar->power_5G_ht40; - else - txpower = ar->power_2G_ht40; - } else { - if (info->band == IEEE80211_BAND_5GHZ) - txpower = ar->power_5G_ht20; - else - txpower = ar->power_2G_ht20; - } - - power = txpower[(txrate->idx) & 7]; - } else { - u8 *txpower; - u32 mod; - u32 phyrate; - u8 idx = txrate->idx; - - if (info->band != IEEE80211_BAND_2GHZ) { - idx += 4; - txpower = ar->power_5G_leg; - mod = AR9170_TX_PHY_MOD_OFDM; - } else { - if (idx < 4) { - txpower = ar->power_2G_cck; - mod = AR9170_TX_PHY_MOD_CCK; - } else { - mod = AR9170_TX_PHY_MOD_OFDM; - txpower = ar->power_2G_ofdm; - } - } - - rate = &__ar9170_ratetable[idx]; - - phyrate = rate->hw_value & 0xF; - power = txpower[(rate->hw_value & 0x30) >> 4]; - phyrate <<= AR9170_TX_PHY_MCS_SHIFT; - - txc->phy_control |= cpu_to_le32(mod); - txc->phy_control |= cpu_to_le32(phyrate); - } - - power <<= AR9170_TX_PHY_TX_PWR_SHIFT; - power &= AR9170_TX_PHY_TX_PWR_MASK; - txc->phy_control |= cpu_to_le32(power); - - /* set TX chains */ - if (ar->eeprom.tx_mask == 1) { - chains = AR9170_TX_PHY_TXCHAIN_1; - } else { - chains = AR9170_TX_PHY_TXCHAIN_2; - - /* >= 36M legacy OFDM - use only one chain */ - if (rate && rate->bitrate >= 360) - chains = AR9170_TX_PHY_TXCHAIN_1; - } - txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); -} - -static void ar9170_tx(struct ar9170 *ar) -{ - struct sk_buff *skb; - unsigned long flags; - struct ieee80211_tx_info *info; - struct ar9170_tx_info *arinfo; - unsigned int i, frames, frames_failed, remaining_space; - int err; - bool schedule_garbagecollector = false; - - BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); - - if (unlikely(!IS_STARTED(ar))) - return ; - - remaining_space = AR9170_TX_MAX_PENDING; - - for (i = 0; i < __AR9170_NUM_TXQ; i++) { - spin_lock_irqsave(&ar->tx_stats_lock, flags); - frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, - skb_queue_len(&ar->tx_pending[i])); - - if (remaining_space < frames) { -#ifdef AR9170_QUEUE_DEBUG - wiphy_debug(ar->hw->wiphy, - "tx quota reached queue:%d, " - "remaining slots:%d, needed:%d\n", - i, remaining_space, frames); -#endif /* AR9170_QUEUE_DEBUG */ - frames = remaining_space; - } - - ar->tx_stats[i].len += frames; - ar->tx_stats[i].count += frames; - if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { -#ifdef AR9170_QUEUE_DEBUG - wiphy_debug(ar->hw->wiphy, "queue %d full\n", i); - wiphy_debug(ar->hw->wiphy, "stuck frames: ===>\n"); - ar9170_dump_txqueue(ar, &ar->tx_pending[i]); - ar9170_dump_txqueue(ar, &ar->tx_status[i]); -#endif /* AR9170_QUEUE_DEBUG */ - -#ifdef AR9170_QUEUE_STOP_DEBUG - wiphy_debug(ar->hw->wiphy, "stop queue %d\n", i); - __ar9170_dump_txstats(ar); -#endif /* AR9170_QUEUE_STOP_DEBUG */ - ieee80211_stop_queue(ar->hw, i); - } - - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - - if (!frames) - continue; - - frames_failed = 0; - while (frames) { - skb = skb_dequeue(&ar->tx_pending[i]); - if (unlikely(!skb)) { - frames_failed += frames; - frames = 0; - break; - } - - info = IEEE80211_SKB_CB(skb); - arinfo = (void *) info->rate_driver_data; - - /* TODO: cancel stuck frames */ - arinfo->timeout = jiffies + - msecs_to_jiffies(AR9170_TX_TIMEOUT); - -#ifdef AR9170_QUEUE_DEBUG - wiphy_debug(ar->hw->wiphy, "send frame q:%d =>\n", i); - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - - err = ar->tx(ar, skb); - if (unlikely(err)) { - frames_failed++; - dev_kfree_skb_any(skb); - } else { - remaining_space--; - schedule_garbagecollector = true; - } - - frames--; - } - -#ifdef AR9170_QUEUE_DEBUG - wiphy_debug(ar->hw->wiphy, - "ar9170_tx report for queue %d\n", i); - - wiphy_debug(ar->hw->wiphy, - "unprocessed pending frames left:\n"); - ar9170_dump_txqueue(ar, &ar->tx_pending[i]); -#endif /* AR9170_QUEUE_DEBUG */ - - if (unlikely(frames_failed)) { -#ifdef AR9170_QUEUE_DEBUG - wiphy_debug(ar->hw->wiphy, - "frames failed %d =>\n", frames_failed); -#endif /* AR9170_QUEUE_DEBUG */ - - spin_lock_irqsave(&ar->tx_stats_lock, flags); - ar->tx_stats[i].len -= frames_failed; - ar->tx_stats[i].count -= frames_failed; -#ifdef AR9170_QUEUE_STOP_DEBUG - wiphy_debug(ar->hw->wiphy, "wake queue %d\n", i); - __ar9170_dump_txstats(ar); -#endif /* AR9170_QUEUE_STOP_DEBUG */ - ieee80211_wake_queue(ar->hw, i); - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - } - } - - if (!schedule_garbagecollector) - return; - - ieee80211_queue_delayed_work(ar->hw, - &ar->tx_janitor, - msecs_to_jiffies(AR9170_JANITOR_DELAY)); -} - -void ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ar9170 *ar = hw->priv; - struct ieee80211_tx_info *info; - unsigned int queue; - - if (unlikely(!IS_STARTED(ar))) - goto err_free; - - if (unlikely(ar9170_tx_prepare(ar, skb))) - goto err_free; - - queue = skb_get_queue_mapping(skb); - info = IEEE80211_SKB_CB(skb); - ar9170_tx_prepare_phy(ar, skb); - skb_queue_tail(&ar->tx_pending[queue], skb); - - ar9170_tx(ar); - return; - -err_free: - dev_kfree_skb_any(skb); -} - -static int ar9170_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct ar9170 *ar = hw->priv; - struct ath_common *common = &ar->common; - int err = 0; - - mutex_lock(&ar->mutex); - - if (ar->vif) { - err = -EBUSY; - goto unlock; - } - - ar->vif = vif; - memcpy(common->macaddr, vif->addr, ETH_ALEN); - - if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { - ar->rx_software_decryption = true; - ar->disable_offload = true; - } - - ar->cur_filter = 0; - err = ar9170_update_frame_filter(ar, AR9170_MAC_REG_FTF_DEFAULTS); - if (err) - goto unlock; - - err = ar9170_set_operating_mode(ar); - -unlock: - mutex_unlock(&ar->mutex); - return err; -} - -static void ar9170_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct ar9170 *ar = hw->priv; - - mutex_lock(&ar->mutex); - ar->vif = NULL; - ar9170_update_frame_filter(ar, 0); - ar9170_set_beacon_timers(ar); - dev_kfree_skb(ar->beacon); - ar->beacon = NULL; - ar->sniffer_enabled = false; - ar->rx_software_decryption = false; - ar9170_set_operating_mode(ar); - mutex_unlock(&ar->mutex); -} - -static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) -{ - struct ar9170 *ar = hw->priv; - int err = 0; - - mutex_lock(&ar->mutex); - - if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { - /* TODO */ - err = 0; - } - - if (changed & IEEE80211_CONF_CHANGE_PS) { - /* TODO */ - err = 0; - } - - if (changed & IEEE80211_CONF_CHANGE_POWER) { - /* TODO */ - err = 0; - } - - if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { - /* - * is it long_frame_max_tx_count or short_frame_max_tx_count? - */ - - err = ar9170_set_hwretry_limit(ar, - ar->hw->conf.long_frame_max_tx_count); - if (err) - goto out; - } - - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - - /* adjust slot time for 5 GHz */ - err = ar9170_set_slot_time(ar); - if (err) - goto out; - - err = ar9170_set_dyn_sifs_ack(ar); - if (err) - goto out; - - err = ar9170_set_channel(ar, hw->conf.channel, - AR9170_RFI_NONE, - nl80211_to_ar9170(hw->conf.channel_type)); - if (err) - goto out; - } - -out: - mutex_unlock(&ar->mutex); - return err; -} - -static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, - struct netdev_hw_addr_list *mc_list) -{ - u64 mchash; - struct netdev_hw_addr *ha; - - /* always get broadcast frames */ - mchash = 1ULL << (0xff >> 2); - - netdev_hw_addr_list_for_each(ha, mc_list) - mchash |= 1ULL << (ha->addr[5] >> 2); - - return mchash; -} - -static void ar9170_op_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *new_flags, - u64 multicast) -{ - struct ar9170 *ar = hw->priv; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return ; - - mutex_lock(&ar->mutex); - - /* mask supported flags */ - *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | - FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL; - ar->filter_state = *new_flags; - /* - * We can support more by setting the sniffer bit and - * then checking the error flags, later. - */ - - if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI) - multicast = ~0ULL; - - if (multicast != ar->cur_mc_hash) - ar9170_update_multicast(ar, multicast); - - if (changed_flags & FIF_CONTROL) { - u32 filter = AR9170_MAC_REG_FTF_PSPOLL | - AR9170_MAC_REG_FTF_RTS | - AR9170_MAC_REG_FTF_CTS | - AR9170_MAC_REG_FTF_ACK | - AR9170_MAC_REG_FTF_CFE | - AR9170_MAC_REG_FTF_CFE_ACK; - - if (*new_flags & FIF_CONTROL) - filter |= ar->cur_filter; - else - filter &= (~ar->cur_filter); - - ar9170_update_frame_filter(ar, filter); - } - - if (changed_flags & FIF_PROMISC_IN_BSS) { - ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0; - ar9170_set_operating_mode(ar); - } - - mutex_unlock(&ar->mutex); -} - - -static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changed) -{ - struct ar9170 *ar = hw->priv; - struct ath_common *common = &ar->common; - int err = 0; - - mutex_lock(&ar->mutex); - - if (changed & BSS_CHANGED_BSSID) { - memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); - err = ar9170_set_operating_mode(ar); - if (err) - goto out; - } - - if (changed & BSS_CHANGED_BEACON_ENABLED) - ar->enable_beacon = bss_conf->enable_beacon; - - if (changed & BSS_CHANGED_BEACON) { - err = ar9170_update_beacon(ar); - if (err) - goto out; - } - - if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON | - BSS_CHANGED_BEACON_INT)) { - err = ar9170_set_beacon_timers(ar); - if (err) - goto out; - } - - if (changed & BSS_CHANGED_ASSOC) { -#ifndef CONFIG_AR9170_LEDS - /* enable assoc LED. */ - err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0); -#endif /* CONFIG_AR9170_LEDS */ - } - - if (changed & BSS_CHANGED_HT) { - /* TODO */ - err = 0; - } - - if (changed & BSS_CHANGED_ERP_SLOT) { - err = ar9170_set_slot_time(ar); - if (err) - goto out; - } - - if (changed & BSS_CHANGED_BASIC_RATES) { - err = ar9170_set_basic_rates(ar); - if (err) - goto out; - } - -out: - mutex_unlock(&ar->mutex); -} - -static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw) -{ - struct ar9170 *ar = hw->priv; - int err; - u64 tsf; -#define NR 3 - static const u32 addr[NR] = { AR9170_MAC_REG_TSF_H, - AR9170_MAC_REG_TSF_L, - AR9170_MAC_REG_TSF_H }; - u32 val[NR]; - int loops = 0; - - mutex_lock(&ar->mutex); - - while (loops++ < 10) { - err = ar9170_read_mreg(ar, NR, addr, val); - if (err || val[0] == val[2]) - break; - } - - mutex_unlock(&ar->mutex); - - if (WARN_ON(err)) - return 0; - tsf = val[0]; - tsf = (tsf << 32) | val[1]; - return tsf; -#undef NR -} - -static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct ar9170 *ar = hw->priv; - int err = 0, i; - u8 ktype; - - if ((!ar->vif) || (ar->disable_offload)) - return -EOPNOTSUPP; - - switch (key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - ktype = AR9170_ENC_ALG_WEP64; - break; - case WLAN_CIPHER_SUITE_WEP104: - ktype = AR9170_ENC_ALG_WEP128; - break; - case WLAN_CIPHER_SUITE_TKIP: - ktype = AR9170_ENC_ALG_TKIP; - break; - case WLAN_CIPHER_SUITE_CCMP: - ktype = AR9170_ENC_ALG_AESCCMP; - break; - default: - return -EOPNOTSUPP; - } - - mutex_lock(&ar->mutex); - if (cmd == SET_KEY) { - if (unlikely(!IS_STARTED(ar))) { - err = -EOPNOTSUPP; - goto out; - } - - /* group keys need all-zeroes address */ - if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) - sta = NULL; - - if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { - for (i = 0; i < 64; i++) - if (!(ar->usedkeys & BIT(i))) - break; - if (i == 64) { - ar->rx_software_decryption = true; - ar9170_set_operating_mode(ar); - err = -ENOSPC; - goto out; - } - } else { - i = 64 + key->keyidx; - } - - key->hw_key_idx = i; - - err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 0, - key->key, min_t(u8, 16, key->keylen)); - if (err) - goto out; - - if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { - err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, - ktype, 1, key->key + 16, 16); - if (err) - goto out; - - /* - * hardware is not capable generating the MMIC - * for fragmented frames! - */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - } - - if (i < 64) - ar->usedkeys |= BIT(i); - - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - } else { - if (unlikely(!IS_STARTED(ar))) { - /* The device is gone... together with the key ;-) */ - err = 0; - goto out; - } - - err = ar9170_disable_key(ar, key->hw_key_idx); - if (err) - goto out; - - if (key->hw_key_idx < 64) { - ar->usedkeys &= ~BIT(key->hw_key_idx); - } else { - err = ar9170_upload_key(ar, key->hw_key_idx, NULL, - AR9170_ENC_ALG_NONE, 0, - NULL, 0); - if (err) - goto out; - - if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { - err = ar9170_upload_key(ar, key->hw_key_idx, - NULL, - AR9170_ENC_ALG_NONE, 1, - NULL, 0); - if (err) - goto out; - } - - } - } - - ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_L, ar->usedkeys); - ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_H, ar->usedkeys >> 32); - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - -out: - mutex_unlock(&ar->mutex); - - return err; -} - -static int ar9170_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct ar9170 *ar = hw->priv; - u32 val; - int err; - - mutex_lock(&ar->mutex); - err = ar9170_read_reg(ar, AR9170_MAC_REG_TX_RETRY, &val); - ar->stats.dot11ACKFailureCount += val; - - memcpy(stats, &ar->stats, sizeof(*stats)); - mutex_unlock(&ar->mutex); - - return 0; -} - -static int ar9170_get_survey(struct ieee80211_hw *hw, int idx, - struct survey_info *survey) -{ - struct ar9170 *ar = hw->priv; - struct ieee80211_conf *conf = &hw->conf; - - if (idx != 0) - return -ENOENT; - - /* TODO: update noise value, e.g. call ar9170_set_channel */ - - survey->channel = conf->channel; - survey->filled = SURVEY_INFO_NOISE_DBM; - survey->noise = ar->noise[0]; - - return 0; -} - -static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *param) -{ - struct ar9170 *ar = hw->priv; - int ret; - - mutex_lock(&ar->mutex); - if (queue < __AR9170_NUM_TXQ) { - memcpy(&ar->edcf[ar9170_qos_hwmap[queue]], - param, sizeof(*param)); - - ret = ar9170_set_qos(ar); - } else { - ret = -EINVAL; - } - - mutex_unlock(&ar->mutex); - return ret; -} - -static int ar9170_ampdu_action(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) -{ - switch (action) { - case IEEE80211_AMPDU_RX_START: - case IEEE80211_AMPDU_RX_STOP: - /* Handled by firmware */ - break; - - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static const struct ieee80211_ops ar9170_ops = { - .start = ar9170_op_start, - .stop = ar9170_op_stop, - .tx = ar9170_op_tx, - .add_interface = ar9170_op_add_interface, - .remove_interface = ar9170_op_remove_interface, - .config = ar9170_op_config, - .prepare_multicast = ar9170_op_prepare_multicast, - .configure_filter = ar9170_op_configure_filter, - .conf_tx = ar9170_conf_tx, - .bss_info_changed = ar9170_op_bss_info_changed, - .get_tsf = ar9170_op_get_tsf, - .set_key = ar9170_set_key, - .get_stats = ar9170_get_stats, - .get_survey = ar9170_get_survey, - .ampdu_action = ar9170_ampdu_action, -}; - -void *ar9170_alloc(size_t priv_size) -{ - struct ieee80211_hw *hw; - struct ar9170 *ar; - struct sk_buff *skb; - int i; - - /* - * this buffer is used for rx stream reconstruction. - * Under heavy load this device (or the transport layer?) - * tends to split the streams into separate rx descriptors. - */ - - skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL); - if (!skb) - goto err_nomem; - - hw = ieee80211_alloc_hw(priv_size, &ar9170_ops); - if (!hw) - goto err_nomem; - - ar = hw->priv; - ar->hw = hw; - ar->rx_failover = skb; - - mutex_init(&ar->mutex); - spin_lock_init(&ar->cmdlock); - spin_lock_init(&ar->tx_stats_lock); - for (i = 0; i < __AR9170_NUM_TXQ; i++) { - skb_queue_head_init(&ar->tx_status[i]); - skb_queue_head_init(&ar->tx_pending[i]); - } - ar9170_rx_reset_rx_mpdu(ar); - INIT_WORK(&ar->beacon_work, ar9170_new_beacon); - INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); - - /* all hw supports 2.4 GHz, so set channel to 1 by default */ - ar->channel = &ar9170_2ghz_chantable[0]; - - /* first part of wiphy init */ - ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_WDS) | - BIT(NL80211_IFTYPE_ADHOC); - ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM; - - ar->hw->queues = __AR9170_NUM_TXQ; - ar->hw->extra_tx_headroom = 8; - - ar->hw->max_rates = 1; - ar->hw->max_rate_tries = 3; - - for (i = 0; i < ARRAY_SIZE(ar->noise); i++) - ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ - - return ar; - -err_nomem: - kfree_skb(skb); - return ERR_PTR(-ENOMEM); -} - -static int ar9170_read_eeprom(struct ar9170 *ar) -{ -#define RW 8 /* number of words to read at once */ -#define RB (sizeof(u32) * RW) - struct ath_regulatory *regulatory = &ar->common.regulatory; - u8 *eeprom = (void *)&ar->eeprom; - u8 *addr = ar->eeprom.mac_address; - __le32 offsets[RW]; - unsigned int rx_streams, tx_streams, tx_params = 0; - int i, j, err, bands = 0; - - BUILD_BUG_ON(sizeof(ar->eeprom) & 3); - - BUILD_BUG_ON(RB > AR9170_MAX_CMD_LEN - 4); -#ifndef __CHECKER__ - /* don't want to handle trailing remains */ - BUILD_BUG_ON(sizeof(ar->eeprom) % RB); -#endif - - for (i = 0; i < sizeof(ar->eeprom)/RB; i++) { - for (j = 0; j < RW; j++) - offsets[j] = cpu_to_le32(AR9170_EEPROM_START + - RB * i + 4 * j); - - err = ar->exec_cmd(ar, AR9170_CMD_RREG, - RB, (u8 *) &offsets, - RB, eeprom + RB * i); - if (err) - return err; - } - -#undef RW -#undef RB - - if (ar->eeprom.length == cpu_to_le16(0xFFFF)) - return -ENODATA; - - if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { - ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar9170_band_2GHz; - bands++; - } - if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { - ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz; - bands++; - } - - rx_streams = hweight8(ar->eeprom.rx_mask); - tx_streams = hweight8(ar->eeprom.tx_mask); - - if (rx_streams != tx_streams) - tx_params = IEEE80211_HT_MCS_TX_RX_DIFF; - - if (tx_streams >= 1 && tx_streams <= IEEE80211_HT_MCS_TX_MAX_STREAMS) - tx_params = (tx_streams - 1) << - IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; - - ar9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params; - ar9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params; - - /* - * I measured this, a bandswitch takes roughly - * 135 ms and a frequency switch about 80. - * - * FIXME: measure these values again once EEPROM settings - * are used, that will influence them! - */ - if (bands == 2) - ar->hw->channel_change_time = 135 * 1000; - else - ar->hw->channel_change_time = 80 * 1000; - - regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); - regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); - - /* second part of wiphy init */ - SET_IEEE80211_PERM_ADDR(ar->hw, addr); - - return bands ? 0 : -EINVAL; -} - -static int ar9170_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ar9170 *ar = hw->priv; - - return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory); -} - -int ar9170_register(struct ar9170 *ar, struct device *pdev) -{ - struct ath_regulatory *regulatory = &ar->common.regulatory; - int err; - - /* try to read EEPROM, init MAC addr */ - err = ar9170_read_eeprom(ar); - if (err) - goto err_out; - - err = ath_regd_init(regulatory, ar->hw->wiphy, - ar9170_reg_notifier); - if (err) - goto err_out; - - err = ieee80211_register_hw(ar->hw); - if (err) - goto err_out; - - if (!ath_is_world_regd(regulatory)) - regulatory_hint(ar->hw->wiphy, regulatory->alpha2); - - err = ar9170_init_leds(ar); - if (err) - goto err_unreg; - -#ifdef CONFIG_AR9170_LEDS - err = ar9170_register_leds(ar); - if (err) - goto err_unreg; -#endif /* CONFIG_AR9170_LEDS */ - - dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", - wiphy_name(ar->hw->wiphy)); - - ar->registered = true; - return 0; - -err_unreg: - ieee80211_unregister_hw(ar->hw); - -err_out: - return err; -} - -void ar9170_unregister(struct ar9170 *ar) -{ - if (ar->registered) { -#ifdef CONFIG_AR9170_LEDS - ar9170_unregister_leds(ar); -#endif /* CONFIG_AR9170_LEDS */ - - ieee80211_unregister_hw(ar->hw); - } - - kfree_skb(ar->rx_failover); - mutex_destroy(&ar->mutex); -} diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c deleted file mode 100644 index 0dbfcf79ac96..000000000000 --- a/drivers/net/wireless/ath/ar9170/phy.c +++ /dev/null @@ -1,1719 +0,0 @@ -/* - * Atheros AR9170 driver - * - * PHY and RF code - * - * Copyright 2008, Johannes Berg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include "ar9170.h" -#include "cmd.h" - -static int ar9170_init_power_cal(struct ar9170 *ar) -{ - ar9170_regwrite_begin(ar); - - ar9170_regwrite(0x1bc000 + 0x993c, 0x7f); - ar9170_regwrite(0x1bc000 + 0x9934, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0x9938, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa234, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa238, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa38c, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa390, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa3cc, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa3d0, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa3d4, 0x3f3f3f3f); - - ar9170_regwrite_finish(); - return ar9170_regwrite_result(); -} - -struct ar9170_phy_init { - u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20; -}; - -static struct ar9170_phy_init ar5416_phy_init[] = { - { 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, - { 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, }, - { 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, }, - { 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, }, - { 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, }, - { 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, }, - { 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, }, - { 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, - { 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, }, - { 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, - { 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, - { 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, - { 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, }, - { 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, }, - { 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, }, - { 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, }, - { 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, }, - { 0x1c5850, 0x6c48b4e4, 0x6c48b4e4, 0x6c48b0e4, 0x6c48b0e4, }, - { 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, }, - { 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, }, - { 0x1c585c, 0x31395c5e, 0x31395c5e, 0x31395c5e, 0x31395c5e, }, - { 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, }, - { 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, }, - { 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, }, - { 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, }, - { 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, }, - { 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, }, - { 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, }, - { 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, }, - { 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, - { 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, - { 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, }, - { 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, }, - { 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, }, - { 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, }, - { 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, }, - { 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, }, - { 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, - { 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, }, - { 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, }, - { 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, - { 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, - { 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, }, - { 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, }, - { 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, }, - { 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, }, - { 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, }, - { 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, }, - { 0x1c59c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, }, - { 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, }, - { 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, }, - { 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, }, - { 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, }, - { 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, }, - { 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, }, - { 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, }, - { 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, }, - { 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, }, - { 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, }, - { 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, }, - { 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, }, - { 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, }, - { 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, }, - { 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, }, - { 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, }, - { 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, - { 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, }, - { 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, }, - { 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, }, - { 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, }, - { 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, }, - { 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, }, - { 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, }, - { 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, }, - { 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, }, - { 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, }, - { 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, }, - { 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, }, - { 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, }, - { 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, }, - { 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, }, - { 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, }, - { 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, }, - { 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, }, - { 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, }, - { 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, }, - { 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, }, - { 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, }, - { 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, }, - { 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, }, - { 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, }, - { 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, }, - { 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, }, - { 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, }, - { 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, }, - { 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, - { 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, }, - { 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, }, - { 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, - { 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, }, - { 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, }, - { 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, }, - { 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, }, - { 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, }, - { 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, }, - { 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, }, - { 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, - { 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, }, - { 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, }, - { 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, }, - { 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, }, - { 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, }, - { 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, }, - { 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, }, - { 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, - { 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, }, - { 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, }, - { 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, }, - { 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, }, - { 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, }, - { 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, }, - { 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, }, - { 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, }, - { 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, }, - { 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, - { 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, }, - { 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, }, - { 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, }, - { 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, }, - { 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, }, - { 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, }, - { 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, }, - { 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, }, - { 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, }, - { 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, }, - { 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, - { 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, - { 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, }, - { 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, }, - { 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, }, - { 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, - { 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, }, - { 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, }, - { 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, }, - { 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, }, - { 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, }, - { 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, }, - { 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, }, - { 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, }, - { 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, }, - { 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, }, - { 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, }, - { 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, }, - { 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, - { 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, - { 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, }, - { 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, }, - { 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, }, - { 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, }, - { 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, - { 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, }, - { 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, - { 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, }, - { 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, }, - { 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, }, - { 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, }, - { 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, }, - { 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, }, - { 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, }, - { 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, }, - { 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, }, - { 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, }, - { 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, }, - { 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, }, - { 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, - { 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, - { 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, - { 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, }, - { 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, }, - { 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, }, - { 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, - { 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, }, - { 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, - { 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, - { 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, }, - { 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, - { 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, - { 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, - { 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, - { 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, - { 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, - { 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, - { 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, - { 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, - { 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, -/* { 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */ - { 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, }, - { 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, }, - { 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, }, - { 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, }, - { 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, }, - { 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, }, - { 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, }, - { 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, }, - { 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, }, - { 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, }, - { 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, }, - { 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, }, - { 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, }, - { 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, }, - { 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, }, - { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, } -}; - -/* - * look up a certain register in ar5416_phy_init[] and return the init. value - * for the band and bandwidth given. Return 0 if register address not found. - */ -static u32 ar9170_get_default_phy_reg_val(u32 reg, bool is_2ghz, bool is_40mhz) -{ - unsigned int i; - for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { - if (ar5416_phy_init[i].reg != reg) - continue; - - if (is_2ghz) { - if (is_40mhz) - return ar5416_phy_init[i]._2ghz_40; - else - return ar5416_phy_init[i]._2ghz_20; - } else { - if (is_40mhz) - return ar5416_phy_init[i]._5ghz_40; - else - return ar5416_phy_init[i]._5ghz_20; - } - } - return 0; -} - -/* - * initialize some phy regs from eeprom values in modal_header[] - * acc. to band and bandwith - */ -static int ar9170_init_phy_from_eeprom(struct ar9170 *ar, - bool is_2ghz, bool is_40mhz) -{ - static const u8 xpd2pd[16] = { - 0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2, - 0x2, 0x3, 0x7, 0x2, 0xB, 0x2, 0x2, 0x2 - }; - u32 defval, newval; - /* pointer to the modal_header acc. to band */ - struct ar9170_eeprom_modal *m = &ar->eeprom.modal_header[is_2ghz]; - - ar9170_regwrite_begin(ar); - - /* ant common control (index 0) */ - newval = le32_to_cpu(m->antCtrlCommon); - ar9170_regwrite(0x1c5964, newval); - - /* ant control chain 0 (index 1) */ - newval = le32_to_cpu(m->antCtrlChain[0]); - ar9170_regwrite(0x1c5960, newval); - - /* ant control chain 2 (index 2) */ - newval = le32_to_cpu(m->antCtrlChain[1]); - ar9170_regwrite(0x1c7960, newval); - - /* SwSettle (index 3) */ - if (!is_40mhz) { - defval = ar9170_get_default_phy_reg_val(0x1c5844, - is_2ghz, is_40mhz); - newval = (defval & ~0x3f80) | - ((m->switchSettling & 0x7f) << 7); - ar9170_regwrite(0x1c5844, newval); - } - - /* adcDesired, pdaDesired (index 4) */ - defval = ar9170_get_default_phy_reg_val(0x1c5850, is_2ghz, is_40mhz); - newval = (defval & ~0xffff) | ((u8)m->pgaDesiredSize << 8) | - ((u8)m->adcDesiredSize); - ar9170_regwrite(0x1c5850, newval); - - /* TxEndToXpaOff, TxFrameToXpaOn (index 5) */ - defval = ar9170_get_default_phy_reg_val(0x1c5834, is_2ghz, is_40mhz); - newval = (m->txEndToXpaOff << 24) | (m->txEndToXpaOff << 16) | - (m->txFrameToXpaOn << 8) | m->txFrameToXpaOn; - ar9170_regwrite(0x1c5834, newval); - - /* TxEndToRxOn (index 6) */ - defval = ar9170_get_default_phy_reg_val(0x1c5828, is_2ghz, is_40mhz); - newval = (defval & ~0xff0000) | (m->txEndToRxOn << 16); - ar9170_regwrite(0x1c5828, newval); - - /* thresh62 (index 7) */ - defval = ar9170_get_default_phy_reg_val(0x1c8864, is_2ghz, is_40mhz); - newval = (defval & ~0x7f000) | (m->thresh62 << 12); - ar9170_regwrite(0x1c8864, newval); - - /* tx/rx attenuation chain 0 (index 8) */ - defval = ar9170_get_default_phy_reg_val(0x1c5848, is_2ghz, is_40mhz); - newval = (defval & ~0x3f000) | ((m->txRxAttenCh[0] & 0x3f) << 12); - ar9170_regwrite(0x1c5848, newval); - - /* tx/rx attenuation chain 2 (index 9) */ - defval = ar9170_get_default_phy_reg_val(0x1c7848, is_2ghz, is_40mhz); - newval = (defval & ~0x3f000) | ((m->txRxAttenCh[1] & 0x3f) << 12); - ar9170_regwrite(0x1c7848, newval); - - /* tx/rx margin chain 0 (index 10) */ - defval = ar9170_get_default_phy_reg_val(0x1c620c, is_2ghz, is_40mhz); - newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[0] & 0x3f) << 18); - /* bsw margin chain 0 for 5GHz only */ - if (!is_2ghz) - newval = (newval & ~0x3c00) | ((m->bswMargin[0] & 0xf) << 10); - ar9170_regwrite(0x1c620c, newval); - - /* tx/rx margin chain 2 (index 11) */ - defval = ar9170_get_default_phy_reg_val(0x1c820c, is_2ghz, is_40mhz); - newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[1] & 0x3f) << 18); - ar9170_regwrite(0x1c820c, newval); - - /* iqCall, iqCallq chain 0 (index 12) */ - defval = ar9170_get_default_phy_reg_val(0x1c5920, is_2ghz, is_40mhz); - newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[0] & 0x3f) << 5) | - ((u8)m->iqCalQCh[0] & 0x1f); - ar9170_regwrite(0x1c5920, newval); - - /* iqCall, iqCallq chain 2 (index 13) */ - defval = ar9170_get_default_phy_reg_val(0x1c7920, is_2ghz, is_40mhz); - newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[1] & 0x3f) << 5) | - ((u8)m->iqCalQCh[1] & 0x1f); - ar9170_regwrite(0x1c7920, newval); - - /* xpd gain mask (index 14) */ - defval = ar9170_get_default_phy_reg_val(0x1c6258, is_2ghz, is_40mhz); - newval = (defval & ~0xf0000) | (xpd2pd[m->xpdGain & 0xf] << 16); - ar9170_regwrite(0x1c6258, newval); - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) -{ - int i, err; - u32 val; - bool is_2ghz = band == IEEE80211_BAND_2GHZ; - bool is_40mhz = conf_is_ht40(&ar->hw->conf); - - ar9170_regwrite_begin(ar); - - for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { - if (is_40mhz) { - if (is_2ghz) - val = ar5416_phy_init[i]._2ghz_40; - else - val = ar5416_phy_init[i]._5ghz_40; - } else { - if (is_2ghz) - val = ar5416_phy_init[i]._2ghz_20; - else - val = ar5416_phy_init[i]._5ghz_20; - } - - ar9170_regwrite(ar5416_phy_init[i].reg, val); - } - - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - if (err) - return err; - - err = ar9170_init_phy_from_eeprom(ar, is_2ghz, is_40mhz); - if (err) - return err; - - err = ar9170_init_power_cal(ar); - if (err) - return err; - - /* XXX: remove magic! */ - if (is_2ghz) - err = ar9170_write_reg(ar, 0x1d4014, 0x5163); - else - err = ar9170_write_reg(ar, 0x1d4014, 0x5143); - - return err; -} - -struct ar9170_rf_init { - u32 reg, _5ghz, _2ghz; -}; - -static struct ar9170_rf_init ar9170_rf_init[] = { - /* bank 0 */ - { 0x1c58b0, 0x1e5795e5, 0x1e5795e5}, - { 0x1c58e0, 0x02008020, 0x02008020}, - /* bank 1 */ - { 0x1c58b0, 0x02108421, 0x02108421}, - { 0x1c58ec, 0x00000008, 0x00000008}, - /* bank 2 */ - { 0x1c58b0, 0x0e73ff17, 0x0e73ff17}, - { 0x1c58e0, 0x00000420, 0x00000420}, - /* bank 3 */ - { 0x1c58f0, 0x01400018, 0x01c00018}, - /* bank 4 */ - { 0x1c58b0, 0x000001a1, 0x000001a1}, - { 0x1c58e8, 0x00000001, 0x00000001}, - /* bank 5 */ - { 0x1c58b0, 0x00000013, 0x00000013}, - { 0x1c58e4, 0x00000002, 0x00000002}, - /* bank 6 */ - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00004000, 0x00004000}, - { 0x1c58b0, 0x00006c00, 0x00006c00}, - { 0x1c58b0, 0x00002c00, 0x00002c00}, - { 0x1c58b0, 0x00004800, 0x00004800}, - { 0x1c58b0, 0x00004000, 0x00004000}, - { 0x1c58b0, 0x00006000, 0x00006000}, - { 0x1c58b0, 0x00001000, 0x00001000}, - { 0x1c58b0, 0x00004000, 0x00004000}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00087c00, 0x00087c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00005400, 0x00005400}, - { 0x1c58b0, 0x00000c00, 0x00000c00}, - { 0x1c58b0, 0x00001800, 0x00001800}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00006c00, 0x00006c00}, - { 0x1c58b0, 0x00006c00, 0x00006c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00002c00, 0x00002c00}, - { 0x1c58b0, 0x00003c00, 0x00003c00}, - { 0x1c58b0, 0x00003800, 0x00003800}, - { 0x1c58b0, 0x00001c00, 0x00001c00}, - { 0x1c58b0, 0x00000800, 0x00000800}, - { 0x1c58b0, 0x00000408, 0x00000408}, - { 0x1c58b0, 0x00004c15, 0x00004c15}, - { 0x1c58b0, 0x00004188, 0x00004188}, - { 0x1c58b0, 0x0000201e, 0x0000201e}, - { 0x1c58b0, 0x00010408, 0x00010408}, - { 0x1c58b0, 0x00000801, 0x00000801}, - { 0x1c58b0, 0x00000c08, 0x00000c08}, - { 0x1c58b0, 0x0000181e, 0x0000181e}, - { 0x1c58b0, 0x00001016, 0x00001016}, - { 0x1c58b0, 0x00002800, 0x00002800}, - { 0x1c58b0, 0x00004010, 0x00004010}, - { 0x1c58b0, 0x0000081c, 0x0000081c}, - { 0x1c58b0, 0x00000115, 0x00000115}, - { 0x1c58b0, 0x00000015, 0x00000015}, - { 0x1c58b0, 0x00000066, 0x00000066}, - { 0x1c58b0, 0x0000001c, 0x0000001c}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000004, 0x00000004}, - { 0x1c58b0, 0x00000015, 0x00000015}, - { 0x1c58b0, 0x0000001f, 0x0000001f}, - { 0x1c58e0, 0x00000000, 0x00000400}, - /* bank 7 */ - { 0x1c58b0, 0x000000a0, 0x000000a0}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000040, 0x00000040}, - { 0x1c58f0, 0x0000001c, 0x0000001c}, -}; - -static int ar9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz) -{ - int err, i; - - ar9170_regwrite_begin(ar); - - for (i = 0; i < ARRAY_SIZE(ar9170_rf_init); i++) - ar9170_regwrite(ar9170_rf_init[i].reg, - band5ghz ? ar9170_rf_init[i]._5ghz - : ar9170_rf_init[i]._2ghz); - - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - if (err) - wiphy_err(ar->hw->wiphy, "rf init failed\n"); - return err; -} - -static int ar9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, - u32 freq, enum ar9170_bw bw) -{ - int err; - u32 d0, d1, td0, td1, fd0, fd1; - u8 chansel; - u8 refsel0 = 1, refsel1 = 0; - u8 lf_synth = 0; - - switch (bw) { - case AR9170_BW_40_ABOVE: - freq += 10; - break; - case AR9170_BW_40_BELOW: - freq -= 10; - break; - case AR9170_BW_20: - break; - case __AR9170_NUM_BW: - BUG(); - } - - if (band5ghz) { - if (freq % 10) { - chansel = (freq - 4800) / 5; - } else { - chansel = ((freq - 4800) / 10) * 2; - refsel0 = 0; - refsel1 = 1; - } - chansel = byte_rev_table[chansel]; - } else { - if (freq == 2484) { - chansel = 10 + (freq - 2274) / 5; - lf_synth = 1; - } else - chansel = 16 + (freq - 2272) / 5; - chansel *= 4; - chansel = byte_rev_table[chansel]; - } - - d1 = chansel; - d0 = 0x21 | - refsel0 << 3 | - refsel1 << 2 | - lf_synth << 1; - td0 = d0 & 0x1f; - td1 = d1 & 0x1f; - fd0 = td1 << 5 | td0; - - td0 = (d0 >> 5) & 0x7; - td1 = (d1 >> 5) & 0x7; - fd1 = td1 << 5 | td0; - - ar9170_regwrite_begin(ar); - - ar9170_regwrite(0x1c58b0, fd0); - ar9170_regwrite(0x1c58e8, fd1); - - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - if (err) - return err; - - msleep(10); - - return 0; -} - -struct ar9170_phy_freq_params { - u8 coeff_exp; - u16 coeff_man; - u8 coeff_exp_shgi; - u16 coeff_man_shgi; -}; - -struct ar9170_phy_freq_entry { - u16 freq; - struct ar9170_phy_freq_params params[__AR9170_NUM_BW]; -}; - -/* NB: must be in sync with channel tables in main! */ -static const struct ar9170_phy_freq_entry ar9170_phy_freq_params[] = { -/* - * freq, - * 20MHz, - * 40MHz (below), - * 40Mhz (above), - */ - { 2412, { - { 3, 21737, 3, 19563, }, - { 3, 21827, 3, 19644, }, - { 3, 21647, 3, 19482, }, - } }, - { 2417, { - { 3, 21692, 3, 19523, }, - { 3, 21782, 3, 19604, }, - { 3, 21602, 3, 19442, }, - } }, - { 2422, { - { 3, 21647, 3, 19482, }, - { 3, 21737, 3, 19563, }, - { 3, 21558, 3, 19402, }, - } }, - { 2427, { - { 3, 21602, 3, 19442, }, - { 3, 21692, 3, 19523, }, - { 3, 21514, 3, 19362, }, - } }, - { 2432, { - { 3, 21558, 3, 19402, }, - { 3, 21647, 3, 19482, }, - { 3, 21470, 3, 19323, }, - } }, - { 2437, { - { 3, 21514, 3, 19362, }, - { 3, 21602, 3, 19442, }, - { 3, 21426, 3, 19283, }, - } }, - { 2442, { - { 3, 21470, 3, 19323, }, - { 3, 21558, 3, 19402, }, - { 3, 21382, 3, 19244, }, - } }, - { 2447, { - { 3, 21426, 3, 19283, }, - { 3, 21514, 3, 19362, }, - { 3, 21339, 3, 19205, }, - } }, - { 2452, { - { 3, 21382, 3, 19244, }, - { 3, 21470, 3, 19323, }, - { 3, 21295, 3, 19166, }, - } }, - { 2457, { - { 3, 21339, 3, 19205, }, - { 3, 21426, 3, 19283, }, - { 3, 21252, 3, 19127, }, - } }, - { 2462, { - { 3, 21295, 3, 19166, }, - { 3, 21382, 3, 19244, }, - { 3, 21209, 3, 19088, }, - } }, - { 2467, { - { 3, 21252, 3, 19127, }, - { 3, 21339, 3, 19205, }, - { 3, 21166, 3, 19050, }, - } }, - { 2472, { - { 3, 21209, 3, 19088, }, - { 3, 21295, 3, 19166, }, - { 3, 21124, 3, 19011, }, - } }, - { 2484, { - { 3, 21107, 3, 18996, }, - { 3, 21192, 3, 19073, }, - { 3, 21022, 3, 18920, }, - } }, - { 4920, { - { 4, 21313, 4, 19181, }, - { 4, 21356, 4, 19220, }, - { 4, 21269, 4, 19142, }, - } }, - { 4940, { - { 4, 21226, 4, 19104, }, - { 4, 21269, 4, 19142, }, - { 4, 21183, 4, 19065, }, - } }, - { 4960, { - { 4, 21141, 4, 19027, }, - { 4, 21183, 4, 19065, }, - { 4, 21098, 4, 18988, }, - } }, - { 4980, { - { 4, 21056, 4, 18950, }, - { 4, 21098, 4, 18988, }, - { 4, 21014, 4, 18912, }, - } }, - { 5040, { - { 4, 20805, 4, 18725, }, - { 4, 20846, 4, 18762, }, - { 4, 20764, 4, 18687, }, - } }, - { 5060, { - { 4, 20723, 4, 18651, }, - { 4, 20764, 4, 18687, }, - { 4, 20682, 4, 18614, }, - } }, - { 5080, { - { 4, 20641, 4, 18577, }, - { 4, 20682, 4, 18614, }, - { 4, 20601, 4, 18541, }, - } }, - { 5180, { - { 4, 20243, 4, 18219, }, - { 4, 20282, 4, 18254, }, - { 4, 20204, 4, 18183, }, - } }, - { 5200, { - { 4, 20165, 4, 18148, }, - { 4, 20204, 4, 18183, }, - { 4, 20126, 4, 18114, }, - } }, - { 5220, { - { 4, 20088, 4, 18079, }, - { 4, 20126, 4, 18114, }, - { 4, 20049, 4, 18044, }, - } }, - { 5240, { - { 4, 20011, 4, 18010, }, - { 4, 20049, 4, 18044, }, - { 4, 19973, 4, 17976, }, - } }, - { 5260, { - { 4, 19935, 4, 17941, }, - { 4, 19973, 4, 17976, }, - { 4, 19897, 4, 17907, }, - } }, - { 5280, { - { 4, 19859, 4, 17873, }, - { 4, 19897, 4, 17907, }, - { 4, 19822, 4, 17840, }, - } }, - { 5300, { - { 4, 19784, 4, 17806, }, - { 4, 19822, 4, 17840, }, - { 4, 19747, 4, 17772, }, - } }, - { 5320, { - { 4, 19710, 4, 17739, }, - { 4, 19747, 4, 17772, }, - { 4, 19673, 4, 17706, }, - } }, - { 5500, { - { 4, 19065, 4, 17159, }, - { 4, 19100, 4, 17190, }, - { 4, 19030, 4, 17127, }, - } }, - { 5520, { - { 4, 18996, 4, 17096, }, - { 4, 19030, 4, 17127, }, - { 4, 18962, 4, 17065, }, - } }, - { 5540, { - { 4, 18927, 4, 17035, }, - { 4, 18962, 4, 17065, }, - { 4, 18893, 4, 17004, }, - } }, - { 5560, { - { 4, 18859, 4, 16973, }, - { 4, 18893, 4, 17004, }, - { 4, 18825, 4, 16943, }, - } }, - { 5580, { - { 4, 18792, 4, 16913, }, - { 4, 18825, 4, 16943, }, - { 4, 18758, 4, 16882, }, - } }, - { 5600, { - { 4, 18725, 4, 16852, }, - { 4, 18758, 4, 16882, }, - { 4, 18691, 4, 16822, }, - } }, - { 5620, { - { 4, 18658, 4, 16792, }, - { 4, 18691, 4, 16822, }, - { 4, 18625, 4, 16762, }, - } }, - { 5640, { - { 4, 18592, 4, 16733, }, - { 4, 18625, 4, 16762, }, - { 4, 18559, 4, 16703, }, - } }, - { 5660, { - { 4, 18526, 4, 16673, }, - { 4, 18559, 4, 16703, }, - { 4, 18493, 4, 16644, }, - } }, - { 5680, { - { 4, 18461, 4, 16615, }, - { 4, 18493, 4, 16644, }, - { 4, 18428, 4, 16586, }, - } }, - { 5700, { - { 4, 18396, 4, 16556, }, - { 4, 18428, 4, 16586, }, - { 4, 18364, 4, 16527, }, - } }, - { 5745, { - { 4, 18252, 4, 16427, }, - { 4, 18284, 4, 16455, }, - { 4, 18220, 4, 16398, }, - } }, - { 5765, { - { 4, 18189, 5, 32740, }, - { 4, 18220, 4, 16398, }, - { 4, 18157, 5, 32683, }, - } }, - { 5785, { - { 4, 18126, 5, 32626, }, - { 4, 18157, 5, 32683, }, - { 4, 18094, 5, 32570, }, - } }, - { 5805, { - { 4, 18063, 5, 32514, }, - { 4, 18094, 5, 32570, }, - { 4, 18032, 5, 32458, }, - } }, - { 5825, { - { 4, 18001, 5, 32402, }, - { 4, 18032, 5, 32458, }, - { 4, 17970, 5, 32347, }, - } }, - { 5170, { - { 4, 20282, 4, 18254, }, - { 4, 20321, 4, 18289, }, - { 4, 20243, 4, 18219, }, - } }, - { 5190, { - { 4, 20204, 4, 18183, }, - { 4, 20243, 4, 18219, }, - { 4, 20165, 4, 18148, }, - } }, - { 5210, { - { 4, 20126, 4, 18114, }, - { 4, 20165, 4, 18148, }, - { 4, 20088, 4, 18079, }, - } }, - { 5230, { - { 4, 20049, 4, 18044, }, - { 4, 20088, 4, 18079, }, - { 4, 20011, 4, 18010, }, - } }, -}; - -static const struct ar9170_phy_freq_params * -ar9170_get_hw_dyn_params(struct ieee80211_channel *channel, - enum ar9170_bw bw) -{ - unsigned int chanidx = 0; - u16 freq = 2412; - - if (channel) { - chanidx = channel->hw_value; - freq = channel->center_freq; - } - - BUG_ON(chanidx >= ARRAY_SIZE(ar9170_phy_freq_params)); - - BUILD_BUG_ON(__AR9170_NUM_BW != 3); - - WARN_ON(ar9170_phy_freq_params[chanidx].freq != freq); - - return &ar9170_phy_freq_params[chanidx].params[bw]; -} - - -int ar9170_init_rf(struct ar9170 *ar) -{ - const struct ar9170_phy_freq_params *freqpar; - __le32 cmd[7]; - int err; - - err = ar9170_init_rf_banks_0_7(ar, false); - if (err) - return err; - - err = ar9170_init_rf_bank4_pwr(ar, false, 2412, AR9170_BW_20); - if (err) - return err; - - freqpar = ar9170_get_hw_dyn_params(NULL, AR9170_BW_20); - - cmd[0] = cpu_to_le32(2412 * 1000); - cmd[1] = cpu_to_le32(0); - cmd[2] = cpu_to_le32(1); - cmd[3] = cpu_to_le32(freqpar->coeff_exp); - cmd[4] = cpu_to_le32(freqpar->coeff_man); - cmd[5] = cpu_to_le32(freqpar->coeff_exp_shgi); - cmd[6] = cpu_to_le32(freqpar->coeff_man_shgi); - - /* RF_INIT echoes the command back to us */ - err = ar->exec_cmd(ar, AR9170_CMD_RF_INIT, - sizeof(cmd), (u8 *)cmd, - sizeof(cmd), (u8 *)cmd); - if (err) - return err; - - msleep(1000); - - return ar9170_echo_test(ar, 0xaabbccdd); -} - -static int ar9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f) -{ - int idx = nfreqs - 2; - - while (idx >= 0) { - if (f >= freqs[idx]) - return idx; - idx--; - } - - return 0; -} - -static s32 ar9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) -{ - /* nothing to interpolate, it's horizontal */ - if (y2 == y1) - return y1; - - /* check if we hit one of the edges */ - if (x == x1) - return y1; - if (x == x2) - return y2; - - /* x1 == x2 is bad, hopefully == x */ - if (x2 == x1) - return y1; - - return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1)); -} - -static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2) -{ -#define SHIFT 8 - s32 y; - - y = ar9170_interpolate_s32(x << SHIFT, - x1 << SHIFT, y1 << SHIFT, - x2 << SHIFT, y2 << SHIFT); - - /* - * XXX: unwrap this expression - * Isn't it just DIV_ROUND_UP(y, 1<> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1)); -#undef SHIFT -} - -static u8 ar9170_interpolate_val(u8 x, u8 *x_array, u8 *y_array) -{ - int i; - - for (i = 0; i < 3; i++) - if (x <= x_array[i + 1]) - break; - - return ar9170_interpolate_u8(x, - x_array[i], - y_array[i], - x_array[i + 1], - y_array[i + 1]); -} - -static int ar9170_set_freq_cal_data(struct ar9170 *ar, - struct ieee80211_channel *channel) -{ - u8 *cal_freq_pier; - u8 vpds[2][AR5416_PD_GAIN_ICEPTS]; - u8 pwrs[2][AR5416_PD_GAIN_ICEPTS]; - int chain, idx, i; - u32 phy_data = 0; - u8 f, tmp; - - switch (channel->band) { - case IEEE80211_BAND_2GHZ: - f = channel->center_freq - 2300; - cal_freq_pier = ar->eeprom.cal_freq_pier_2G; - i = AR5416_NUM_2G_CAL_PIERS - 1; - break; - - case IEEE80211_BAND_5GHZ: - f = (channel->center_freq - 4800) / 5; - cal_freq_pier = ar->eeprom.cal_freq_pier_5G; - i = AR5416_NUM_5G_CAL_PIERS - 1; - break; - - default: - return -EINVAL; - break; - } - - for (; i >= 0; i--) { - if (cal_freq_pier[i] != 0xff) - break; - } - if (i < 0) - return -EINVAL; - - idx = ar9170_find_freq_idx(i, cal_freq_pier, f); - - ar9170_regwrite_begin(ar); - - for (chain = 0; chain < AR5416_MAX_CHAINS; chain++) { - for (i = 0; i < AR5416_PD_GAIN_ICEPTS; i++) { - struct ar9170_calibration_data_per_freq *cal_pier_data; - int j; - - switch (channel->band) { - case IEEE80211_BAND_2GHZ: - cal_pier_data = &ar->eeprom. - cal_pier_data_2G[chain][idx]; - break; - - case IEEE80211_BAND_5GHZ: - cal_pier_data = &ar->eeprom. - cal_pier_data_5G[chain][idx]; - break; - - default: - return -EINVAL; - } - - for (j = 0; j < 2; j++) { - vpds[j][i] = ar9170_interpolate_u8(f, - cal_freq_pier[idx], - cal_pier_data->vpd_pdg[j][i], - cal_freq_pier[idx + 1], - cal_pier_data[1].vpd_pdg[j][i]); - - pwrs[j][i] = ar9170_interpolate_u8(f, - cal_freq_pier[idx], - cal_pier_data->pwr_pdg[j][i], - cal_freq_pier[idx + 1], - cal_pier_data[1].pwr_pdg[j][i]) / 2; - } - } - - for (i = 0; i < 76; i++) { - if (i < 25) { - tmp = ar9170_interpolate_val(i, &pwrs[0][0], - &vpds[0][0]); - } else { - tmp = ar9170_interpolate_val(i - 12, - &pwrs[1][0], - &vpds[1][0]); - } - - phy_data |= tmp << ((i & 3) << 3); - if ((i & 3) == 3) { - ar9170_regwrite(0x1c6280 + chain * 0x1000 + - (i & ~3), phy_data); - phy_data = 0; - } - } - - for (i = 19; i < 32; i++) - ar9170_regwrite(0x1c6280 + chain * 0x1000 + (i << 2), - 0x0); - } - - ar9170_regwrite_finish(); - return ar9170_regwrite_result(); -} - -static u8 ar9170_get_max_edge_power(struct ar9170 *ar, - struct ar9170_calctl_edges edges[], - u32 freq) -{ - int i; - u8 rc = AR5416_MAX_RATE_POWER; - u8 f; - if (freq < 3000) - f = freq - 2300; - else - f = (freq - 4800) / 5; - - for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { - if (edges[i].channel == 0xff) - break; - if (f == edges[i].channel) { - /* exact freq match */ - rc = edges[i].power_flags & ~AR9170_CALCTL_EDGE_FLAGS; - break; - } - if (i > 0 && f < edges[i].channel) { - if (f > edges[i - 1].channel && - edges[i - 1].power_flags & - AR9170_CALCTL_EDGE_FLAGS) { - /* lower channel has the inband flag set */ - rc = edges[i - 1].power_flags & - ~AR9170_CALCTL_EDGE_FLAGS; - } - break; - } - } - - if (i == AR5416_NUM_BAND_EDGES) { - if (f > edges[i - 1].channel && - edges[i - 1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { - /* lower channel has the inband flag set */ - rc = edges[i - 1].power_flags & - ~AR9170_CALCTL_EDGE_FLAGS; - } - } - return rc; -} - -static u8 ar9170_get_heavy_clip(struct ar9170 *ar, - struct ar9170_calctl_edges edges[], - u32 freq, enum ar9170_bw bw) -{ - u8 f; - int i; - u8 rc = 0; - - if (freq < 3000) - f = freq - 2300; - else - f = (freq - 4800) / 5; - - if (bw == AR9170_BW_40_BELOW || bw == AR9170_BW_40_ABOVE) - rc |= 0xf0; - - for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { - if (edges[i].channel == 0xff) - break; - if (f == edges[i].channel) { - if (!(edges[i].power_flags & AR9170_CALCTL_EDGE_FLAGS)) - rc |= 0x0f; - break; - } - } - - return rc; -} - -/* - * calculate the conformance test limits and the heavy clip parameter - * and apply them to ar->power* (derived from otus hal/hpmain.c, line 3706) - */ -static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) -{ - u8 ctl_grp; /* CTL group */ - u8 ctl_idx; /* CTL index */ - int i, j; - struct ctl_modes { - u8 ctl_mode; - u8 max_power; - u8 *pwr_cal_data; - int pwr_cal_len; - } *modes; - - /* - * order is relevant in the mode_list_*: we fall back to the - * lower indices if any mode is missed in the EEPROM. - */ - struct ctl_modes mode_list_2ghz[] = { - { CTL_11B, 0, ar->power_2G_cck, 4 }, - { CTL_11G, 0, ar->power_2G_ofdm, 4 }, - { CTL_2GHT20, 0, ar->power_2G_ht20, 8 }, - { CTL_2GHT40, 0, ar->power_2G_ht40, 8 }, - }; - struct ctl_modes mode_list_5ghz[] = { - { CTL_11A, 0, ar->power_5G_leg, 4 }, - { CTL_5GHT20, 0, ar->power_5G_ht20, 8 }, - { CTL_5GHT40, 0, ar->power_5G_ht40, 8 }, - }; - int nr_modes; - -#define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n]) - - ar->phy_heavy_clip = 0; - - /* - * TODO: investigate the differences between OTUS' - * hpreg.c::zfHpGetRegulatoryDomain() and - * ath/regd.c::ath_regd_get_band_ctl() - - * e.g. for FCC3_WORLD the OTUS procedure - * always returns CTL_FCC, while the one in ath/ delivers - * CTL_ETSI for 2GHz and CTL_FCC for 5GHz. - */ - ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory, - ar->hw->conf.channel->band); - - /* ctl group not found - either invalid band (NO_CTL) or ww roaming */ - if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL) - ctl_grp = CTL_FCC; - - if (ctl_grp != CTL_FCC) - /* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */ - return; - - if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { - modes = mode_list_2ghz; - nr_modes = ARRAY_SIZE(mode_list_2ghz); - } else { - modes = mode_list_5ghz; - nr_modes = ARRAY_SIZE(mode_list_5ghz); - } - - for (i = 0; i < nr_modes; i++) { - u8 c = ctl_grp | modes[i].ctl_mode; - for (ctl_idx = 0; ctl_idx < AR5416_NUM_CTLS; ctl_idx++) - if (c == ar->eeprom.ctl_index[ctl_idx]) - break; - if (ctl_idx < AR5416_NUM_CTLS) { - int f_off = 0; - - /* determine heav clip parameter from - the 11G edges array */ - if (modes[i].ctl_mode == CTL_11G) { - ar->phy_heavy_clip = - ar9170_get_heavy_clip(ar, - EDGES(ctl_idx, 1), - freq, bw); - } - - /* adjust freq for 40MHz */ - if (modes[i].ctl_mode == CTL_2GHT40 || - modes[i].ctl_mode == CTL_5GHT40) { - if (bw == AR9170_BW_40_BELOW) - f_off = -10; - else - f_off = 10; - } - - modes[i].max_power = - ar9170_get_max_edge_power(ar, EDGES(ctl_idx, 1), - freq+f_off); - - /* - * TODO: check if the regulatory max. power is - * controlled by cfg80211 for DFS - * (hpmain applies it to max_power itself for DFS freq) - */ - - } else { - /* - * Workaround in otus driver, hpmain.c, line 3906: - * if no data for 5GHT20 are found, take the - * legacy 5G value. - * We extend this here to fallback from any other *HT or - * 11G, too. - */ - int k = i; - - modes[i].max_power = AR5416_MAX_RATE_POWER; - while (k-- > 0) { - if (modes[k].max_power != - AR5416_MAX_RATE_POWER) { - modes[i].max_power = modes[k].max_power; - break; - } - } - } - - /* apply max power to pwr_cal_data (ar->power_*) */ - for (j = 0; j < modes[i].pwr_cal_len; j++) { - modes[i].pwr_cal_data[j] = min(modes[i].pwr_cal_data[j], - modes[i].max_power); - } - } - - if (ar->phy_heavy_clip & 0xf0) { - ar->power_2G_ht40[0]--; - ar->power_2G_ht40[1]--; - ar->power_2G_ht40[2]--; - } - if (ar->phy_heavy_clip & 0xf) { - ar->power_2G_ht20[0]++; - ar->power_2G_ht20[1]++; - ar->power_2G_ht20[2]++; - } - - -#undef EDGES -} - -static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) -{ - struct ar9170_calibration_target_power_legacy *ctpl; - struct ar9170_calibration_target_power_ht *ctph; - u8 *ctpres; - int ntargets; - int idx, i, n; - u8 ackpower, ackchains, f; - u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS]; - - if (freq < 3000) - f = freq - 2300; - else - f = (freq - 4800)/5; - - /* - * cycle through the various modes - * - * legacy modes first: 5G, 2G CCK, 2G OFDM - */ - for (i = 0; i < 3; i++) { - switch (i) { - case 0: /* 5 GHz legacy */ - ctpl = &ar->eeprom.cal_tgt_pwr_5G[0]; - ntargets = AR5416_NUM_5G_TARGET_PWRS; - ctpres = ar->power_5G_leg; - break; - case 1: /* 2.4 GHz CCK */ - ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0]; - ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS; - ctpres = ar->power_2G_cck; - break; - case 2: /* 2.4 GHz OFDM */ - ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0]; - ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; - ctpres = ar->power_2G_ofdm; - break; - default: - BUG(); - } - - for (n = 0; n < ntargets; n++) { - if (ctpl[n].freq == 0xff) - break; - pwr_freqs[n] = ctpl[n].freq; - } - ntargets = n; - idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); - for (n = 0; n < 4; n++) - ctpres[n] = ar9170_interpolate_u8( - f, - ctpl[idx + 0].freq, - ctpl[idx + 0].power[n], - ctpl[idx + 1].freq, - ctpl[idx + 1].power[n]); - } - - /* - * HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40 - */ - for (i = 0; i < 4; i++) { - switch (i) { - case 0: /* 5 GHz HT 20 */ - ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0]; - ntargets = AR5416_NUM_5G_TARGET_PWRS; - ctpres = ar->power_5G_ht20; - break; - case 1: /* 5 GHz HT 40 */ - ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0]; - ntargets = AR5416_NUM_5G_TARGET_PWRS; - ctpres = ar->power_5G_ht40; - break; - case 2: /* 2.4 GHz HT 20 */ - ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0]; - ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; - ctpres = ar->power_2G_ht20; - break; - case 3: /* 2.4 GHz HT 40 */ - ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0]; - ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; - ctpres = ar->power_2G_ht40; - break; - default: - BUG(); - } - - for (n = 0; n < ntargets; n++) { - if (ctph[n].freq == 0xff) - break; - pwr_freqs[n] = ctph[n].freq; - } - ntargets = n; - idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); - for (n = 0; n < 8; n++) - ctpres[n] = ar9170_interpolate_u8( - f, - ctph[idx + 0].freq, - ctph[idx + 0].power[n], - ctph[idx + 1].freq, - ctph[idx + 1].power[n]); - } - - - /* calc. conformance test limits and apply to ar->power*[] */ - ar9170_calc_ctl(ar, freq, bw); - - /* set ACK/CTS TX power */ - ar9170_regwrite_begin(ar); - - if (ar->eeprom.tx_mask != 1) - ackchains = AR9170_TX_PHY_TXCHAIN_2; - else - ackchains = AR9170_TX_PHY_TXCHAIN_1; - - if (freq < 3000) - ackpower = ar->power_2G_ofdm[0] & 0x3f; - else - ackpower = ar->power_5G_leg[0] & 0x3f; - - ar9170_regwrite(0x1c3694, ackpower << 20 | ackchains << 26); - ar9170_regwrite(0x1c3bb4, ackpower << 5 | ackchains << 11 | - ackpower << 21 | ackchains << 27); - - ar9170_regwrite_finish(); - return ar9170_regwrite_result(); -} - -static int ar9170_calc_noise_dbm(u32 raw_noise) -{ - if (raw_noise & 0x100) - return ~((raw_noise & 0x0ff) >> 1); - else - return (raw_noise & 0xff) >> 1; -} - -int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, - enum ar9170_rf_init_mode rfi, enum ar9170_bw bw) -{ - const struct ar9170_phy_freq_params *freqpar; - u32 cmd, tmp, offs; - __le32 vals[8]; - int i, err; - bool bandswitch; - - /* clear BB heavy clip enable */ - err = ar9170_write_reg(ar, 0x1c59e0, 0x200); - if (err) - return err; - - /* may be NULL at first setup */ - if (ar->channel) - bandswitch = ar->channel->band != channel->band; - else - bandswitch = true; - - /* HW workaround */ - if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] && - channel->center_freq <= 2417) - bandswitch = true; - - err = ar->exec_cmd(ar, AR9170_CMD_FREQ_START, 0, NULL, 0, NULL); - if (err) - return err; - - if (rfi != AR9170_RFI_NONE || bandswitch) { - u32 val = 0x400; - - if (rfi == AR9170_RFI_COLD) - val = 0x800; - - /* warm/cold reset BB/ADDA */ - err = ar9170_write_reg(ar, 0x1d4004, val); - if (err) - return err; - - err = ar9170_write_reg(ar, 0x1d4004, 0x0); - if (err) - return err; - - err = ar9170_init_phy(ar, channel->band); - if (err) - return err; - - err = ar9170_init_rf_banks_0_7(ar, - channel->band == IEEE80211_BAND_5GHZ); - if (err) - return err; - - cmd = AR9170_CMD_RF_INIT; - } else { - cmd = AR9170_CMD_FREQUENCY; - } - - err = ar9170_init_rf_bank4_pwr(ar, - channel->band == IEEE80211_BAND_5GHZ, - channel->center_freq, bw); - if (err) - return err; - - switch (bw) { - case AR9170_BW_20: - tmp = 0x240; - offs = 0; - break; - case AR9170_BW_40_BELOW: - tmp = 0x2c4; - offs = 3; - break; - case AR9170_BW_40_ABOVE: - tmp = 0x2d4; - offs = 1; - break; - default: - BUG(); - return -ENOSYS; - } - - if (ar->eeprom.tx_mask != 1) - tmp |= 0x100; - - err = ar9170_write_reg(ar, 0x1c5804, tmp); - if (err) - return err; - - err = ar9170_set_freq_cal_data(ar, channel); - if (err) - return err; - - err = ar9170_set_power_cal(ar, channel->center_freq, bw); - if (err) - return err; - - freqpar = ar9170_get_hw_dyn_params(channel, bw); - - vals[0] = cpu_to_le32(channel->center_freq * 1000); - vals[1] = cpu_to_le32(conf_is_ht40(&ar->hw->conf)); - vals[2] = cpu_to_le32(offs << 2 | 1); - vals[3] = cpu_to_le32(freqpar->coeff_exp); - vals[4] = cpu_to_le32(freqpar->coeff_man); - vals[5] = cpu_to_le32(freqpar->coeff_exp_shgi); - vals[6] = cpu_to_le32(freqpar->coeff_man_shgi); - vals[7] = cpu_to_le32(1000); - - err = ar->exec_cmd(ar, cmd, sizeof(vals), (u8 *)vals, - sizeof(vals), (u8 *)vals); - if (err) - return err; - - if (ar->phy_heavy_clip) { - err = ar9170_write_reg(ar, 0x1c59e0, - 0x200 | ar->phy_heavy_clip); - if (err) { - if (ar9170_nag_limiter(ar)) - wiphy_err(ar->hw->wiphy, - "failed to set heavy clip\n"); - } - } - - for (i = 0; i < 2; i++) { - ar->noise[i] = ar9170_calc_noise_dbm( - (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff); - - ar->noise[i + 2] = ar9170_calc_noise_dbm( - (le32_to_cpu(vals[5 + i]) >> 23) & 0x1ff); - } - - ar->channel = channel; - return 0; -} diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c deleted file mode 100644 index d3be6f9816b5..000000000000 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ /dev/null @@ -1,1008 +0,0 @@ -/* - * Atheros AR9170 driver - * - * USB - frontend - * - * Copyright 2008, Johannes Berg - * Copyright 2009, Christian Lamparter - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "ar9170.h" -#include "cmd.h" -#include "hw.h" -#include "usb.h" - -MODULE_AUTHOR("Johannes Berg "); -MODULE_AUTHOR("Christian Lamparter "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); -MODULE_FIRMWARE("ar9170.fw"); - -enum ar9170_requirements { - AR9170_REQ_FW1_ONLY = 1, -}; - -static struct usb_device_id ar9170_usb_ids[] = { - /* Atheros 9170 */ - { USB_DEVICE(0x0cf3, 0x9170) }, - /* Atheros TG121N */ - { USB_DEVICE(0x0cf3, 0x1001) }, - /* TP-Link TL-WN821N v2 */ - { USB_DEVICE(0x0cf3, 0x1002) }, - /* 3Com Dual Band 802.11n USB Adapter */ - { USB_DEVICE(0x0cf3, 0x1010) }, - /* H3C Dual Band 802.11n USB Adapter */ - { USB_DEVICE(0x0cf3, 0x1011) }, - /* Cace Airpcap NX */ - { USB_DEVICE(0xcace, 0x0300) }, - /* D-Link DWA 160 A1 */ - { USB_DEVICE(0x07d1, 0x3c10) }, - /* D-Link DWA 160 A2 */ - { USB_DEVICE(0x07d1, 0x3a09) }, - /* Netgear WNA1000 */ - { USB_DEVICE(0x0846, 0x9040) }, - /* Netgear WNDA3100 */ - { USB_DEVICE(0x0846, 0x9010) }, - /* Netgear WN111 v2 */ - { USB_DEVICE(0x0846, 0x9001) }, - /* Zydas ZD1221 */ - { USB_DEVICE(0x0ace, 0x1221) }, - /* Proxim ORiNOCO 802.11n USB */ - { USB_DEVICE(0x1435, 0x0804) }, - /* WNC Generic 11n USB Dongle */ - { USB_DEVICE(0x1435, 0x0326) }, - /* ZyXEL NWD271N */ - { USB_DEVICE(0x0586, 0x3417) }, - /* Z-Com UB81 BG */ - { USB_DEVICE(0x0cde, 0x0023) }, - /* Z-Com UB82 ABG */ - { USB_DEVICE(0x0cde, 0x0026) }, - /* Sphairon Homelink 1202 */ - { USB_DEVICE(0x0cde, 0x0027) }, - /* Arcadyan WN7512 */ - { USB_DEVICE(0x083a, 0xf522) }, - /* Planex GWUS300 */ - { USB_DEVICE(0x2019, 0x5304) }, - /* IO-Data WNGDNUS2 */ - { USB_DEVICE(0x04bb, 0x093f) }, - /* AVM FRITZ!WLAN USB Stick N */ - { USB_DEVICE(0x057C, 0x8401) }, - /* NEC WL300NU-G */ - { USB_DEVICE(0x0409, 0x0249) }, - /* AVM FRITZ!WLAN USB Stick N 2.4 */ - { USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY }, - /* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */ - { USB_DEVICE(0x1668, 0x1200) }, - - /* terminate */ - {} -}; -MODULE_DEVICE_TABLE(usb, ar9170_usb_ids); - -static void ar9170_usb_submit_urb(struct ar9170_usb *aru) -{ - struct urb *urb; - unsigned long flags; - int err; - - if (unlikely(!IS_STARTED(&aru->common))) - return ; - - spin_lock_irqsave(&aru->tx_urb_lock, flags); - if (atomic_read(&aru->tx_submitted_urbs) >= AR9170_NUM_TX_URBS) { - spin_unlock_irqrestore(&aru->tx_urb_lock, flags); - return ; - } - atomic_inc(&aru->tx_submitted_urbs); - - urb = usb_get_from_anchor(&aru->tx_pending); - if (!urb) { - atomic_dec(&aru->tx_submitted_urbs); - spin_unlock_irqrestore(&aru->tx_urb_lock, flags); - - return ; - } - spin_unlock_irqrestore(&aru->tx_urb_lock, flags); - - aru->tx_pending_urbs--; - usb_anchor_urb(urb, &aru->tx_submitted); - - err = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(err)) { - if (ar9170_nag_limiter(&aru->common)) - dev_err(&aru->udev->dev, "submit_urb failed (%d).\n", - err); - - usb_unanchor_urb(urb); - atomic_dec(&aru->tx_submitted_urbs); - ar9170_tx_callback(&aru->common, urb->context); - } - - usb_free_urb(urb); -} - -static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) -{ - struct sk_buff *skb = urb->context; - struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); - - if (unlikely(!aru)) { - dev_kfree_skb_irq(skb); - return ; - } - - atomic_dec(&aru->tx_submitted_urbs); - - ar9170_tx_callback(&aru->common, skb); - - ar9170_usb_submit_urb(aru); -} - -static void ar9170_usb_tx_urb_complete(struct urb *urb) -{ -} - -static void ar9170_usb_irq_completed(struct urb *urb) -{ - struct ar9170_usb *aru = urb->context; - - switch (urb->status) { - /* everything is fine */ - case 0: - break; - - /* disconnect */ - case -ENOENT: - case -ECONNRESET: - case -ENODEV: - case -ESHUTDOWN: - goto free; - - default: - goto resubmit; - } - - ar9170_handle_command_response(&aru->common, urb->transfer_buffer, - urb->actual_length); - -resubmit: - usb_anchor_urb(urb, &aru->rx_submitted); - if (usb_submit_urb(urb, GFP_ATOMIC)) { - usb_unanchor_urb(urb); - goto free; - } - - return; - -free: - usb_free_coherent(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma); -} - -static void ar9170_usb_rx_completed(struct urb *urb) -{ - struct sk_buff *skb = urb->context; - struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); - int err; - - if (!aru) - goto free; - - switch (urb->status) { - /* everything is fine */ - case 0: - break; - - /* disconnect */ - case -ENOENT: - case -ECONNRESET: - case -ENODEV: - case -ESHUTDOWN: - goto free; - - default: - goto resubmit; - } - - skb_put(skb, urb->actual_length); - ar9170_rx(&aru->common, skb); - -resubmit: - skb_reset_tail_pointer(skb); - skb_trim(skb, 0); - - usb_anchor_urb(urb, &aru->rx_submitted); - err = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(err)) { - usb_unanchor_urb(urb); - goto free; - } - - return ; - -free: - dev_kfree_skb_irq(skb); -} - -static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru, - struct urb *urb, gfp_t gfp) -{ - struct sk_buff *skb; - - skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE + 32, gfp); - if (!skb) - return -ENOMEM; - - /* reserve some space for mac80211's radiotap */ - skb_reserve(skb, 32); - - usb_fill_bulk_urb(urb, aru->udev, - usb_rcvbulkpipe(aru->udev, AR9170_EP_RX), - skb->data, min(skb_tailroom(skb), - AR9170_MAX_RX_BUFFER_SIZE), - ar9170_usb_rx_completed, skb); - - return 0; -} - -static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru) -{ - struct urb *urb = NULL; - void *ibuf; - int err = -ENOMEM; - - /* initialize interrupt endpoint */ - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto out; - - ibuf = usb_alloc_coherent(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma); - if (!ibuf) - goto out; - - usb_fill_int_urb(urb, aru->udev, - usb_rcvintpipe(aru->udev, AR9170_EP_IRQ), ibuf, - 64, ar9170_usb_irq_completed, aru, 1); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - usb_anchor_urb(urb, &aru->rx_submitted); - err = usb_submit_urb(urb, GFP_KERNEL); - if (err) { - usb_unanchor_urb(urb); - usb_free_coherent(aru->udev, 64, urb->transfer_buffer, - urb->transfer_dma); - } - -out: - usb_free_urb(urb); - return err; -} - -static int ar9170_usb_alloc_rx_bulk_urbs(struct ar9170_usb *aru) -{ - struct urb *urb; - int i; - int err = -EINVAL; - - for (i = 0; i < AR9170_NUM_RX_URBS; i++) { - err = -ENOMEM; - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto err_out; - - err = ar9170_usb_prep_rx_urb(aru, urb, GFP_KERNEL); - if (err) { - usb_free_urb(urb); - goto err_out; - } - - usb_anchor_urb(urb, &aru->rx_submitted); - err = usb_submit_urb(urb, GFP_KERNEL); - if (err) { - usb_unanchor_urb(urb); - dev_kfree_skb_any((void *) urb->transfer_buffer); - usb_free_urb(urb); - goto err_out; - } - usb_free_urb(urb); - } - - /* the device now waiting for a firmware. */ - aru->common.state = AR9170_IDLE; - return 0; - -err_out: - - usb_kill_anchored_urbs(&aru->rx_submitted); - return err; -} - -static int ar9170_usb_flush(struct ar9170 *ar) -{ - struct ar9170_usb *aru = (void *) ar; - struct urb *urb; - int ret, err = 0; - - if (IS_STARTED(ar)) - aru->common.state = AR9170_IDLE; - - usb_wait_anchor_empty_timeout(&aru->tx_pending, - msecs_to_jiffies(800)); - while ((urb = usb_get_from_anchor(&aru->tx_pending))) { - ar9170_tx_callback(&aru->common, (void *) urb->context); - usb_free_urb(urb); - } - - /* lets wait a while until the tx - queues are dried out */ - ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, - msecs_to_jiffies(100)); - if (ret == 0) - err = -ETIMEDOUT; - - usb_kill_anchored_urbs(&aru->tx_submitted); - - if (IS_ACCEPTING_CMD(ar)) - aru->common.state = AR9170_STARTED; - - return err; -} - -static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru) -{ - int err; - - aru->common.state = AR9170_UNKNOWN_STATE; - - err = ar9170_usb_flush(&aru->common); - if (err) - dev_err(&aru->udev->dev, "stuck tx urbs!\n"); - - usb_poison_anchored_urbs(&aru->tx_submitted); - usb_poison_anchored_urbs(&aru->rx_submitted); -} - -static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, - unsigned int plen, void *payload, - unsigned int outlen, void *out) -{ - struct ar9170_usb *aru = (void *) ar; - struct urb *urb = NULL; - unsigned long flags; - int err = -ENOMEM; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return -EPERM; - - if (WARN_ON(plen > AR9170_MAX_CMD_LEN - 4)) - return -EINVAL; - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (unlikely(!urb)) - goto err_free; - - ar->cmdbuf[0] = cpu_to_le32(plen); - ar->cmdbuf[0] |= cpu_to_le32(cmd << 8); - /* writing multiple regs fills this buffer already */ - if (plen && payload != (u8 *)(&ar->cmdbuf[1])) - memcpy(&ar->cmdbuf[1], payload, plen); - - spin_lock_irqsave(&aru->common.cmdlock, flags); - aru->readbuf = (u8 *)out; - aru->readlen = outlen; - spin_unlock_irqrestore(&aru->common.cmdlock, flags); - - usb_fill_int_urb(urb, aru->udev, - usb_sndintpipe(aru->udev, AR9170_EP_CMD), - aru->common.cmdbuf, plen + 4, - ar9170_usb_tx_urb_complete, NULL, 1); - - usb_anchor_urb(urb, &aru->tx_submitted); - err = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(err)) { - usb_unanchor_urb(urb); - usb_free_urb(urb); - goto err_unbuf; - } - usb_free_urb(urb); - - err = wait_for_completion_timeout(&aru->cmd_wait, HZ); - if (err == 0) { - err = -ETIMEDOUT; - goto err_unbuf; - } - - if (aru->readlen != outlen) { - err = -EMSGSIZE; - goto err_unbuf; - } - - return 0; - -err_unbuf: - /* Maybe the device was removed in the second we were waiting? */ - if (IS_STARTED(ar)) { - dev_err(&aru->udev->dev, "no command feedback " - "received (%d).\n", err); - - /* provide some maybe useful debug information */ - print_hex_dump_bytes("ar9170 cmd: ", DUMP_PREFIX_NONE, - aru->common.cmdbuf, plen + 4); - dump_stack(); - } - - /* invalidate to avoid completing the next prematurely */ - spin_lock_irqsave(&aru->common.cmdlock, flags); - aru->readbuf = NULL; - aru->readlen = 0; - spin_unlock_irqrestore(&aru->common.cmdlock, flags); - -err_free: - - return err; -} - -static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ar9170_usb *aru = (struct ar9170_usb *) ar; - struct urb *urb; - - if (unlikely(!IS_STARTED(ar))) { - /* Seriously, what were you drink... err... thinking!? */ - return -EPERM; - } - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (unlikely(!urb)) - return -ENOMEM; - - usb_fill_bulk_urb(urb, aru->udev, - usb_sndbulkpipe(aru->udev, AR9170_EP_TX), - skb->data, skb->len, - ar9170_usb_tx_urb_complete_frame, skb); - urb->transfer_flags |= URB_ZERO_PACKET; - - usb_anchor_urb(urb, &aru->tx_pending); - aru->tx_pending_urbs++; - - usb_free_urb(urb); - - ar9170_usb_submit_urb(aru); - return 0; -} - -static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer) -{ - struct ar9170_usb *aru = (void *) ar; - unsigned long flags; - u32 in, out; - - if (unlikely(!buffer)) - return ; - - in = le32_to_cpup((__le32 *)buffer); - out = le32_to_cpu(ar->cmdbuf[0]); - - /* mask off length byte */ - out &= ~0xFF; - - if (aru->readlen >= 0) { - /* add expected length */ - out |= aru->readlen; - } else { - /* add obtained length */ - out |= in & 0xFF; - } - - /* - * Some commands (e.g: AR9170_CMD_FREQUENCY) have a variable response - * length and we cannot predict the correct length in advance. - * So we only check if we provided enough space for the data. - */ - if (unlikely(out < in)) { - dev_warn(&aru->udev->dev, "received invalid command response " - "got %d bytes, instead of %d bytes " - "and the resp length is %d bytes\n", - in, out, len); - print_hex_dump_bytes("ar9170 invalid resp: ", - DUMP_PREFIX_OFFSET, buffer, len); - /* - * Do not complete, then the command times out, - * and we get a stack trace from there. - */ - return ; - } - - spin_lock_irqsave(&aru->common.cmdlock, flags); - if (aru->readbuf && len > 0) { - memcpy(aru->readbuf, buffer + 4, len - 4); - aru->readbuf = NULL; - } - complete(&aru->cmd_wait); - spin_unlock_irqrestore(&aru->common.cmdlock, flags); -} - -static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, - size_t len, u32 addr, bool complete) -{ - int transfer, err; - u8 *buf = kmalloc(4096, GFP_KERNEL); - - if (!buf) - return -ENOMEM; - - while (len) { - transfer = min_t(int, len, 4096); - memcpy(buf, data, transfer); - - err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), - 0x30 /* FW DL */, 0x40 | USB_DIR_OUT, - addr >> 8, 0, buf, transfer, 1000); - - if (err < 0) { - kfree(buf); - return err; - } - - len -= transfer; - data += transfer; - addr += transfer; - } - kfree(buf); - - if (complete) { - err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), - 0x31 /* FW DL COMPLETE */, - 0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 5000); - } - - return 0; -} - -static int ar9170_usb_reset(struct ar9170_usb *aru) -{ - int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); - - if (lock) { - ret = usb_lock_device_for_reset(aru->udev, aru->intf); - if (ret < 0) { - dev_err(&aru->udev->dev, "unable to lock device " - "for reset (%d).\n", ret); - return ret; - } - } - - ret = usb_reset_device(aru->udev); - if (lock) - usb_unlock_device(aru->udev); - - /* let it rest - for a second - */ - msleep(1000); - - return ret; -} - -static int ar9170_usb_upload_firmware(struct ar9170_usb *aru) -{ - int err; - - if (!aru->init_values) - goto upload_fw_start; - - /* First, upload initial values to device RAM */ - err = ar9170_usb_upload(aru, aru->init_values->data, - aru->init_values->size, 0x102800, false); - if (err) { - dev_err(&aru->udev->dev, "firmware part 1 " - "upload failed (%d).\n", err); - return err; - } - -upload_fw_start: - - /* Then, upload the firmware itself and start it */ - return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size, - 0x200000, true); -} - -static int ar9170_usb_init_transport(struct ar9170_usb *aru) -{ - struct ar9170 *ar = (void *) &aru->common; - int err; - - ar9170_regwrite_begin(ar); - - /* Set USB Rx stream mode MAX packet number to 2 */ - ar9170_regwrite(AR9170_USB_REG_MAX_AGG_UPLOAD, 0x4); - - /* Set USB Rx stream mode timeout to 10us */ - ar9170_regwrite(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80); - - ar9170_regwrite_finish(); - - err = ar9170_regwrite_result(); - if (err) - dev_err(&aru->udev->dev, "USB setup failed (%d).\n", err); - - return err; -} - -static void ar9170_usb_stop(struct ar9170 *ar) -{ - struct ar9170_usb *aru = (void *) ar; - int ret; - - if (IS_ACCEPTING_CMD(ar)) - aru->common.state = AR9170_STOPPED; - - ret = ar9170_usb_flush(ar); - if (ret) - dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); - - usb_poison_anchored_urbs(&aru->tx_submitted); - - /* - * Note: - * So far we freed all tx urbs, but we won't dare to touch any rx urbs. - * Else we would end up with a unresponsive device... - */ -} - -static int ar9170_usb_open(struct ar9170 *ar) -{ - struct ar9170_usb *aru = (void *) ar; - int err; - - usb_unpoison_anchored_urbs(&aru->tx_submitted); - err = ar9170_usb_init_transport(aru); - if (err) { - usb_poison_anchored_urbs(&aru->tx_submitted); - return err; - } - - aru->common.state = AR9170_IDLE; - return 0; -} - -static int ar9170_usb_init_device(struct ar9170_usb *aru) -{ - int err; - - err = ar9170_usb_alloc_rx_irq_urb(aru); - if (err) - goto err_out; - - err = ar9170_usb_alloc_rx_bulk_urbs(aru); - if (err) - goto err_unrx; - - err = ar9170_usb_upload_firmware(aru); - if (err) { - err = ar9170_echo_test(&aru->common, 0x60d43110); - if (err) { - /* force user invention, by disabling the device */ - err = usb_driver_set_configuration(aru->udev, -1); - dev_err(&aru->udev->dev, "device is in a bad state. " - "please reconnect it!\n"); - goto err_unrx; - } - } - - return 0; - -err_unrx: - ar9170_usb_cancel_urbs(aru); - -err_out: - return err; -} - -static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) -{ - struct device *parent = aru->udev->dev.parent; - struct usb_device *udev; - - /* - * Store a copy of the usb_device pointer locally. - * This is because device_release_driver initiates - * ar9170_usb_disconnect, which in turn frees our - * driver context (aru). - */ - udev = aru->udev; - - complete(&aru->firmware_loading_complete); - - /* unbind anything failed */ - if (parent) - device_lock(parent); - - device_release_driver(&udev->dev); - if (parent) - device_unlock(parent); - - usb_put_dev(udev); -} - -static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) -{ - struct ar9170_usb *aru = context; - int err; - - aru->firmware = fw; - - if (!fw) { - dev_err(&aru->udev->dev, "firmware file not found.\n"); - goto err_freefw; - } - - err = ar9170_usb_init_device(aru); - if (err) - goto err_freefw; - - err = ar9170_usb_open(&aru->common); - if (err) - goto err_unrx; - - err = ar9170_register(&aru->common, &aru->udev->dev); - - ar9170_usb_stop(&aru->common); - if (err) - goto err_unrx; - - complete(&aru->firmware_loading_complete); - usb_put_dev(aru->udev); - return; - - err_unrx: - ar9170_usb_cancel_urbs(aru); - - err_freefw: - ar9170_usb_firmware_failed(aru); -} - -static void ar9170_usb_firmware_inits(const struct firmware *fw, - void *context) -{ - struct ar9170_usb *aru = context; - int err; - - if (!fw) { - dev_err(&aru->udev->dev, "file with init values not found.\n"); - ar9170_usb_firmware_failed(aru); - return; - } - - aru->init_values = fw; - - /* ok so we have the init values -- get code for two-stage */ - - err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-2.fw", - &aru->udev->dev, GFP_KERNEL, aru, - ar9170_usb_firmware_finish); - if (err) - ar9170_usb_firmware_failed(aru); -} - -static void ar9170_usb_firmware_step2(const struct firmware *fw, void *context) -{ - struct ar9170_usb *aru = context; - int err; - - if (fw) { - ar9170_usb_firmware_finish(fw, context); - return; - } - - if (aru->req_one_stage_fw) { - dev_err(&aru->udev->dev, "ar9170.fw firmware file " - "not found and is required for this device\n"); - ar9170_usb_firmware_failed(aru); - return; - } - - dev_err(&aru->udev->dev, "ar9170.fw firmware file " - "not found, trying old firmware...\n"); - - err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-1.fw", - &aru->udev->dev, GFP_KERNEL, aru, - ar9170_usb_firmware_inits); - if (err) - ar9170_usb_firmware_failed(aru); -} - -static bool ar9170_requires_one_stage(const struct usb_device_id *id) -{ - if (!id->driver_info) - return false; - if (id->driver_info == AR9170_REQ_FW1_ONLY) - return true; - return false; -} - -static int ar9170_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct ar9170_usb *aru; - struct ar9170 *ar; - struct usb_device *udev; - int err; - - aru = ar9170_alloc(sizeof(*aru)); - if (IS_ERR(aru)) { - err = PTR_ERR(aru); - goto out; - } - - udev = interface_to_usbdev(intf); - usb_get_dev(udev); - aru->udev = udev; - aru->intf = intf; - ar = &aru->common; - - aru->req_one_stage_fw = ar9170_requires_one_stage(id); - - usb_set_intfdata(intf, aru); - SET_IEEE80211_DEV(ar->hw, &intf->dev); - - init_usb_anchor(&aru->rx_submitted); - init_usb_anchor(&aru->tx_pending); - init_usb_anchor(&aru->tx_submitted); - init_completion(&aru->cmd_wait); - init_completion(&aru->firmware_loading_complete); - spin_lock_init(&aru->tx_urb_lock); - - aru->tx_pending_urbs = 0; - atomic_set(&aru->tx_submitted_urbs, 0); - - aru->common.stop = ar9170_usb_stop; - aru->common.flush = ar9170_usb_flush; - aru->common.open = ar9170_usb_open; - aru->common.tx = ar9170_usb_tx; - aru->common.exec_cmd = ar9170_usb_exec_cmd; - aru->common.callback_cmd = ar9170_usb_callback_cmd; - -#ifdef CONFIG_PM - udev->reset_resume = 1; -#endif /* CONFIG_PM */ - err = ar9170_usb_reset(aru); - if (err) - goto err_freehw; - - usb_get_dev(aru->udev); - return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", - &aru->udev->dev, GFP_KERNEL, aru, - ar9170_usb_firmware_step2); -err_freehw: - usb_set_intfdata(intf, NULL); - usb_put_dev(udev); - ieee80211_free_hw(ar->hw); -out: - return err; -} - -static void ar9170_usb_disconnect(struct usb_interface *intf) -{ - struct ar9170_usb *aru = usb_get_intfdata(intf); - - if (!aru) - return; - - aru->common.state = AR9170_IDLE; - - wait_for_completion(&aru->firmware_loading_complete); - - ar9170_unregister(&aru->common); - ar9170_usb_cancel_urbs(aru); - - usb_put_dev(aru->udev); - usb_set_intfdata(intf, NULL); - ieee80211_free_hw(aru->common.hw); - - release_firmware(aru->init_values); - release_firmware(aru->firmware); -} - -#ifdef CONFIG_PM -static int ar9170_suspend(struct usb_interface *intf, - pm_message_t message) -{ - struct ar9170_usb *aru = usb_get_intfdata(intf); - - if (!aru) - return -ENODEV; - - aru->common.state = AR9170_IDLE; - ar9170_usb_cancel_urbs(aru); - - return 0; -} - -static int ar9170_resume(struct usb_interface *intf) -{ - struct ar9170_usb *aru = usb_get_intfdata(intf); - int err; - - if (!aru) - return -ENODEV; - - usb_unpoison_anchored_urbs(&aru->rx_submitted); - usb_unpoison_anchored_urbs(&aru->tx_submitted); - - err = ar9170_usb_init_device(aru); - if (err) - goto err_unrx; - - err = ar9170_usb_open(&aru->common); - if (err) - goto err_unrx; - - return 0; - -err_unrx: - aru->common.state = AR9170_IDLE; - ar9170_usb_cancel_urbs(aru); - - return err; -} -#endif /* CONFIG_PM */ - -static struct usb_driver ar9170_driver = { - .name = "ar9170usb", - .probe = ar9170_usb_probe, - .disconnect = ar9170_usb_disconnect, - .id_table = ar9170_usb_ids, - .soft_unbind = 1, -#ifdef CONFIG_PM - .suspend = ar9170_suspend, - .resume = ar9170_resume, - .reset_resume = ar9170_resume, -#endif /* CONFIG_PM */ -}; - -static int __init ar9170_init(void) -{ - return usb_register(&ar9170_driver); -} - -static void __exit ar9170_exit(void) -{ - usb_deregister(&ar9170_driver); -} - -module_init(ar9170_init); -module_exit(ar9170_exit); diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h deleted file mode 100644 index 919b06046eb3..000000000000 --- a/drivers/net/wireless/ath/ar9170/usb.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Atheros AR9170 USB driver - * - * Driver specific definitions - * - * Copyright 2008, Johannes Berg - * Copyright 2009, Christian Lamparter - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef __USB_H -#define __USB_H - -#include -#include -#include -#include -#include -#include -#include -#include "eeprom.h" -#include "hw.h" -#include "ar9170.h" - -#define AR9170_NUM_RX_URBS 16 -#define AR9170_NUM_TX_URBS 8 - -struct firmware; - -struct ar9170_usb { - struct ar9170 common; - struct usb_device *udev; - struct usb_interface *intf; - - struct usb_anchor rx_submitted; - struct usb_anchor tx_pending; - struct usb_anchor tx_submitted; - - bool req_one_stage_fw; - - spinlock_t tx_urb_lock; - atomic_t tx_submitted_urbs; - unsigned int tx_pending_urbs; - - struct completion cmd_wait; - struct completion firmware_loading_complete; - int readlen; - u8 *readbuf; - - const struct firmware *init_values; - const struct firmware *firmware; -}; - -#endif /* __USB_H */ -- cgit v1.2.3-58-ga151 From 08b8099c128d601fd675b212ef8b10397706b633 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Sun, 27 Mar 2011 01:15:53 +0100 Subject: wireless: rt2x00: rt{2500,73}usb.c fix duplicate ids based on the Ralink drivers: W = Windows_ralink_driver L = Linux_ralink_driver USB_IDs W_73 W_2500 L_73 L_2500 ============= ==== ====== ==== ====== 0x050d,0x7050 - - - YES 0x050d,0x705a - - YES - 0x1371,0x9022 - YES YES - 0x148f,0x2573 YES - YES - Signed-off-by: Xose Vazquez Perez Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 4 ---- drivers/net/wireless/rt2x00/rt73usb.c | 1 - 2 files changed, 5 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index d9e6cec56cb5..eac788160f55 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1909,13 +1909,10 @@ static struct usb_device_id rt2500usb_device_table[] = { /* Belkin */ { USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x050d, 0x7051), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Cisco Systems */ { USB_DEVICE(0x13b1, 0x000d), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x13b1, 0x0011), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x13b1, 0x001a), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* CNet */ - { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Conceptronic */ { USB_DEVICE(0x14b2, 0x3c02), USB_DEVICE_DATA(&rt2500usb_ops) }, /* D-LINK */ @@ -1938,7 +1935,6 @@ static struct usb_device_id rt2500usb_device_table[] = { /* Ralink */ { USB_DEVICE(0x148f, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x148f, 0x2570), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x148f, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Sagem */ { USB_DEVICE(0x079b, 0x004b), USB_DEVICE_DATA(&rt2500usb_ops) }, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 149e4f928325..6593059f9c7e 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2406,7 +2406,6 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x0b05, 0x1723), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0b05, 0x1724), USB_DEVICE_DATA(&rt73usb_ops) }, /* Belkin */ - { USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x050d, 0x905b), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) }, -- cgit v1.2.3-58-ga151 From 3598e1774c94e55c71b585340e7dc4538f310e3f Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 31 Mar 2011 17:36:26 +0200 Subject: iwlwifi: fix enqueue hcmd race conditions We mark command as huge by using meta->flags from other (non huge) command, but flags can be possibly overridden, when non huge command is enqueued, what can lead to: WARNING: at lib/dma-debug.c:696 dma_debug_device_change+0x1a3/0x1f0() DMA-API: device driver has pending DMA allocations while released from device [count=1] To fix introduce additional CMD_MAPPED to mark command as mapped and serialize iwl_enqueue_hcmd() with iwl_tx_cmd_complete() using hcmd_lock. Serialization will also fix possible race conditions, because q->read_ptr, q->write_ptr are modified/used in parallel. On the way fix whitespace. Signed-off-by: Stanislaw Gruszka Acked-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + drivers/net/wireless/iwlwifi/iwl-tx.c | 62 ++++++++++++++++++---------------- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index a5d438d91821..746587546a4f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -309,6 +309,7 @@ enum { CMD_SIZE_HUGE = (1 << 0), CMD_ASYNC = (1 << 1), CMD_WANT_SKB = (1 << 2), + CMD_MAPPED = (1 << 3), }; #define DEF_CMD_PAYLOAD_SIZE 320 diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 277c9175dcf6..39a4180ee854 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -149,32 +149,31 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv) struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; struct iwl_queue *q = &txq->q; int i; - bool huge = false; if (q->n_bd == 0) return; while (q->read_ptr != q->write_ptr) { - /* we have no way to tell if it is a huge cmd ATM */ i = get_cmd_index(q, q->read_ptr, 0); - if (txq->meta[i].flags & CMD_SIZE_HUGE) - huge = true; - else + if (txq->meta[i].flags & CMD_MAPPED) { pci_unmap_single(priv->pci_dev, dma_unmap_addr(&txq->meta[i], mapping), dma_unmap_len(&txq->meta[i], len), PCI_DMA_BIDIRECTIONAL); + txq->meta[i].flags = 0; + } - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } - if (huge) { - i = q->n_window; + i = q->n_window; + if (txq->meta[i].flags & CMD_MAPPED) { pci_unmap_single(priv->pci_dev, dma_unmap_addr(&txq->meta[i], mapping), dma_unmap_len(&txq->meta[i], len), PCI_DMA_BIDIRECTIONAL); + txq->meta[i].flags = 0; } } @@ -463,7 +462,11 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) return -EIO; } + spin_lock_irqsave(&priv->hcmd_lock, flags); + if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { + spin_unlock_irqrestore(&priv->hcmd_lock, flags); + IWL_ERR(priv, "No space in command queue\n"); if (priv->cfg->ops->lib->tt_ops.ct_kill_check) { is_ct_kill = @@ -476,22 +479,17 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) return -ENOSPC; } - spin_lock_irqsave(&priv->hcmd_lock, flags); - - /* If this is a huge cmd, mark the huge flag also on the meta.flags - * of the _original_ cmd. This is used for DMA mapping clean up. - */ - if (cmd->flags & CMD_SIZE_HUGE) { - idx = get_cmd_index(q, q->write_ptr, 0); - txq->meta[idx].flags = CMD_SIZE_HUGE; - } - idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); out_cmd = txq->cmd[idx]; out_meta = &txq->meta[idx]; + if (WARN_ON(out_meta->flags & CMD_MAPPED)) { + spin_unlock_irqrestore(&priv->hcmd_lock, flags); + return -ENOSPC; + } + memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ - out_meta->flags = cmd->flags; + out_meta->flags = cmd->flags | CMD_MAPPED; if (cmd->flags & CMD_WANT_SKB) out_meta->source = cmd; if (cmd->flags & CMD_ASYNC) @@ -609,6 +607,10 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; + unsigned long flags; + void (*callback) (struct iwl_priv *priv, struct iwl_device_cmd *cmd, + struct iwl_rx_packet *pkt); + /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced @@ -622,14 +624,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) return; } - /* If this is a huge cmd, clear the huge flag on the meta.flags - * of the _original_ cmd. So that iwl_cmd_queue_free won't unmap - * the DMA buffer for the scan (huge) command. - */ - if (huge) { - cmd_index = get_cmd_index(&txq->q, index, 0); - txq->meta[cmd_index].flags = 0; - } + spin_lock_irqsave(&priv->hcmd_lock, flags); + cmd_index = get_cmd_index(&txq->q, index, huge); cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; @@ -639,12 +635,13 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) dma_unmap_len(meta, len), PCI_DMA_BIDIRECTIONAL); + callback = NULL; /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { meta->source->reply_page = (unsigned long)rxb_addr(rxb); rxb->page = NULL; - } else if (meta->callback) - meta->callback(priv, cmd, pkt); + } else + callback = meta->callback; iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); @@ -654,5 +651,12 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) get_cmd_string(cmd->hdr.cmd)); wake_up_interruptible(&priv->wait_command_queue); } + + /* Mark as unmapped */ meta->flags = 0; + + spin_unlock_irqrestore(&priv->hcmd_lock, flags); + + if (callback) + callback(priv, cmd, pkt); } -- cgit v1.2.3-58-ga151 From dc1a4068fce2657991c5c3b1f6849f7fc466c69f Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 31 Mar 2011 17:36:27 +0200 Subject: iwlwifi: more priv->mutex serialization Check status bits with mutex taken, because when we wait for mutex unlock, status can change. Patch should also make remaining sync commands be send with priv->mutex taken. That will prevent execute these commands when we are currently reset firmware, what could possibly cause troubles. Signed-off-by: Stanislaw Gruszka Acked-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 28ac0d44555e..70428e9b9f76 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -483,12 +483,14 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) container_of(work, struct iwl_priv, bt_full_concurrency); struct iwl_rxon_context *ctx; + mutex_lock(&priv->mutex); + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; + goto out; /* dont send host command if rf-kill is on */ if (!iwl_is_ready_rf(priv)) - return; + goto out; IWL_DEBUG_INFO(priv, "BT coex in %s mode\n", priv->bt_full_concurrent ? @@ -498,15 +500,15 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) * LQ & RXON updated cmds must be sent before BT Config cmd * to avoid 3-wire collisions */ - mutex_lock(&priv->mutex); for_each_context(priv, ctx) { if (priv->cfg->ops->hcmd->set_rxon_chain) priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); iwlcore_commit_rxon(priv, ctx); } - mutex_unlock(&priv->mutex); priv->cfg->ops->hcmd->send_bt_config(priv); +out: + mutex_unlock(&priv->mutex); } /** @@ -2620,10 +2622,13 @@ static void iwl_bg_init_alive_start(struct work_struct *data) struct iwl_priv *priv = container_of(data, struct iwl_priv, init_alive_start.work); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + mutex_lock(&priv->mutex); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { + mutex_unlock(&priv->mutex); return; + } - mutex_lock(&priv->mutex); priv->cfg->ops->lib->init_alive_start(priv); mutex_unlock(&priv->mutex); } @@ -2633,15 +2638,16 @@ static void iwl_bg_alive_start(struct work_struct *data) struct iwl_priv *priv = container_of(data, struct iwl_priv, alive_start.work); + mutex_lock(&priv->mutex); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; + goto unlock; /* enable dram interrupt */ if (priv->cfg->ops->lib->isr_ops.reset) priv->cfg->ops->lib->isr_ops.reset(priv); - mutex_lock(&priv->mutex); iwl_alive_start(priv); +unlock: mutex_unlock(&priv->mutex); } @@ -3267,21 +3273,22 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); + mutex_lock(&priv->mutex); + if (iwl_is_rfkill(priv)) - goto out_exit; + goto out; if (test_bit(STATUS_EXIT_PENDING, &priv->status) || test_bit(STATUS_SCANNING, &priv->status)) - goto out_exit; + goto out; if (!iwl_is_associated_ctx(ctx)) - goto out_exit; + goto out; /* channel switch in progress */ if (priv->switch_rxon.switch_in_progress == true) - goto out_exit; + goto out; - mutex_lock(&priv->mutex); if (priv->cfg->ops->lib->set_channel_switch) { ch = channel->hw_value; @@ -3337,7 +3344,6 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, } out: mutex_unlock(&priv->mutex); -out_exit: if (!priv->switch_rxon.switch_in_progress) ieee80211_chswitch_done(ctx->vif, false); IWL_DEBUG_MAC80211(priv, "leave\n"); -- cgit v1.2.3-58-ga151 From 8447c163afeaa7e9f6f015088177b1c8511e0877 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 31 Mar 2011 17:36:28 +0200 Subject: iwlwifi: remove sync_cmd_mutex We now use priv->mutex to serialize sync command, remove old priv->sync_cmd_mutex and add assertion that priv->mutex must be locked. Signed-off-by: Stanislaw Gruszka Acked-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-hcmd.c | 13 +++++-------- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 70428e9b9f76..42fad62baf76 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2371,9 +2371,6 @@ static void __iwl_down(struct iwl_priv *priv) priv->bt_full_concurrent = false; priv->bt_ci_compliance = 0; - /* Unblock any waiting calls */ - wake_up_interruptible_all(&priv->wait_command_queue); - /* Wipe out the EXIT_PENDING status bit if we are not actually * exiting the module */ if (!exit_pending) @@ -3620,7 +3617,6 @@ static int iwl_init_drv(struct iwl_priv *priv) INIT_LIST_HEAD(&priv->free_frames); mutex_init(&priv->mutex); - mutex_init(&priv->sync_cmd_mutex); priv->ieee_channels = NULL; priv->ieee_rates = NULL; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 746587546a4f..1c9d2dd37cca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1307,7 +1307,6 @@ struct iwl_priv { spinlock_t hcmd_lock; /* protect hcmd */ spinlock_t reg_lock; /* protect hw register access */ struct mutex mutex; - struct mutex sync_cmd_mutex; /* enable serialization of sync commands */ /* basic pci-network driver stuff */ struct pci_dev *pci_dev; diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 02499f684683..c71c0a45fa0b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -171,14 +171,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) int cmd_idx; int ret; - BUG_ON(cmd->flags & CMD_ASYNC); + lockdep_assert_held(&priv->mutex); /* A synchronous command can not have a callback set. */ - BUG_ON(cmd->callback); + BUG_ON((cmd->flags & CMD_ASYNC) || cmd->callback); IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", get_cmd_string(cmd->id)); - mutex_lock(&priv->sync_cmd_mutex); set_bit(STATUS_HCMD_ACTIVE, &priv->status); IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", @@ -189,7 +188,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) ret = cmd_idx; IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); - goto out; + return ret; } ret = wait_event_interruptible_timeout(priv->wait_command_queue, @@ -229,8 +228,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) goto cancel; } - ret = 0; - goto out; + return 0; cancel: if (cmd->flags & CMD_WANT_SKB) { @@ -248,8 +246,7 @@ fail: iwl_free_pages(priv, cmd->reply_page); cmd->reply_page = 0; } -out: - mutex_unlock(&priv->sync_cmd_mutex); + return ret; } -- cgit v1.2.3-58-ga151 From f4263c9857e6411ef2388868cc6c79a1602a654e Mon Sep 17 00:00:00 2001 From: Paul Stewart Date: Thu, 31 Mar 2011 09:25:41 -0700 Subject: nl80211: Add BSS parameters to station This allows user-space monitoring of BSS parameters for the associated station. This is useful for debugging and verifying that the paramaters are as expected. [Exactly the same as before but bundled into a single message] Signed-off-by: Paul Stewart Cc: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 35 ++++++++++++++++++++++++++++++++++- include/net/cfg80211.h | 34 ++++++++++++++++++++++++++++++++++ net/mac80211/cfg.c | 13 ++++++++++++- net/wireless/nl80211.c | 21 ++++++++++++++++++++- 4 files changed, 100 insertions(+), 3 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 30022189104d..16eea7229e99 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1221,6 +1221,36 @@ enum nl80211_rate_info { NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1 }; +/** + * enum nl80211_sta_bss_param - BSS information collected by STA + * + * These attribute types are used with %NL80211_STA_INFO_BSS_PARAM + * when getting information about the bitrate of a station. + * + * @__NL80211_STA_BSS_PARAM_INVALID: attribute number 0 is reserved + * @NL80211_STA_BSS_PARAM_CTS_PROT: whether CTS protection is enabled (flag) + * @NL80211_STA_BSS_PARAM_SHORT_PREAMBLE: whether short preamble is enabled + * (flag) + * @NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME: whether short slot time is enabled + * (flag) + * @NL80211_STA_BSS_PARAM_DTIM_PERIOD: DTIM period for beaconing (u8) + * @NL80211_STA_BSS_PARAM_BEACON_INTERVAL: Beacon interval (u16) + * @NL80211_STA_BSS_PARAM_MAX: highest sta_bss_param number currently defined + * @__NL80211_STA_BSS_PARAM_AFTER_LAST: internal use + */ +enum nl80211_sta_bss_param { + __NL80211_STA_BSS_PARAM_INVALID, + NL80211_STA_BSS_PARAM_CTS_PROT, + NL80211_STA_BSS_PARAM_SHORT_PREAMBLE, + NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME, + NL80211_STA_BSS_PARAM_DTIM_PERIOD, + NL80211_STA_BSS_PARAM_BEACON_INTERVAL, + + /* keep last */ + __NL80211_STA_BSS_PARAM_AFTER_LAST, + NL80211_STA_BSS_PARAM_MAX = __NL80211_STA_BSS_PARAM_AFTER_LAST - 1 +}; + /** * enum nl80211_sta_info - station information * @@ -1233,7 +1263,7 @@ enum nl80211_rate_info { * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute - * containing info as possible, see &enum nl80211_sta_info_txrate. + * containing info as possible, see &enum nl80211_rate_info * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station) * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this * station) @@ -1245,6 +1275,8 @@ enum nl80211_rate_info { * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station * @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested * attribute, like NL80211_STA_INFO_TX_BITRATE. + * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute + * containing info as possible, see &enum nl80211_sta_bss_param * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -1264,6 +1296,7 @@ enum nl80211_sta_info { NL80211_STA_INFO_TX_FAILED, NL80211_STA_INFO_SIGNAL_AVG, NL80211_STA_INFO_RX_BITRATE, + NL80211_STA_INFO_BSS_PARAM, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 2c4530451721..ba7384acf4e0 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -422,6 +422,7 @@ struct station_parameters { * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled * @STATION_INFO_SIGNAL_AVG: @signal_avg filled * @STATION_INFO_RX_BITRATE: @rxrate fields are filled + * @STATION_INFO_BSS_PARAM: @bss_param filled */ enum station_info_flags { STATION_INFO_INACTIVE_TIME = 1<<0, @@ -439,6 +440,7 @@ enum station_info_flags { STATION_INFO_RX_DROP_MISC = 1<<12, STATION_INFO_SIGNAL_AVG = 1<<13, STATION_INFO_RX_BITRATE = 1<<14, + STATION_INFO_BSS_PARAM = 1<<15, }; /** @@ -472,6 +474,37 @@ struct rate_info { u16 legacy; }; +/** + * enum station_info_rate_flags - bitrate info flags + * + * Used by the driver to indicate the specific rate transmission + * type for 802.11n transmissions. + * + * @BSS_PARAM_FLAGS_CTS_PROT: whether CTS protection is enabled + * @BSS_PARAM_FLAGS_SHORT_PREAMBLE: whether short preamble is enabled + * @BSS_PARAM_FLAGS_SHORT_SLOT_TIME: whether short slot time is enabled + */ +enum bss_param_flags { + BSS_PARAM_FLAGS_CTS_PROT = 1<<0, + BSS_PARAM_FLAGS_SHORT_PREAMBLE = 1<<1, + BSS_PARAM_FLAGS_SHORT_SLOT_TIME = 1<<2, +}; + +/** + * struct sta_bss_parameters - BSS parameters for the attached station + * + * Information about the currently associated BSS + * + * @flags: bitflag of flags from &enum bss_param_flags + * @dtim_period: DTIM period for the BSS + * @beacon_interval: beacon interval + */ +struct sta_bss_parameters { + u8 flags; + u8 dtim_period; + u16 beacon_interval; +}; + /** * struct station_info - station information * @@ -515,6 +548,7 @@ struct station_info { u32 tx_retries; u32 tx_failed; u32 rx_dropped_misc; + struct sta_bss_parameters bss_param; int generation; }; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 334213571ad0..bf5d28da46e6 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -342,7 +342,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) STATION_INFO_TX_FAILED | STATION_INFO_TX_BITRATE | STATION_INFO_RX_BITRATE | - STATION_INFO_RX_DROP_MISC; + STATION_INFO_RX_DROP_MISC | + STATION_INFO_BSS_PARAM; sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); sinfo->rx_bytes = sta->rx_bytes; @@ -389,6 +390,16 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->plink_state = sta->plink_state; #endif } + + sinfo->bss_param.flags = 0; + if (sdata->vif.bss_conf.use_cts_prot) + sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT; + if (sdata->vif.bss_conf.use_short_preamble) + sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; + if (sdata->vif.bss_conf.use_short_slot) + sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; + sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period; + sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 40c90fb461c4..297d7ce4117b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2002,7 +2002,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, const u8 *mac_addr, struct station_info *sinfo) { void *hdr; - struct nlattr *sinfoattr; + struct nlattr *sinfoattr, *bss_param; hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); if (!hdr) @@ -2062,6 +2062,25 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, if (sinfo->filled & STATION_INFO_TX_FAILED) NLA_PUT_U32(msg, NL80211_STA_INFO_TX_FAILED, sinfo->tx_failed); + if (sinfo->filled & STATION_INFO_BSS_PARAM) { + bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); + if (!bss_param) + goto nla_put_failure; + + if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) + NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_CTS_PROT); + if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) + NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE); + if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) + NLA_PUT_FLAG(msg, + NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME); + NLA_PUT_U8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD, + sinfo->bss_param.dtim_period); + NLA_PUT_U16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL, + sinfo->bss_param.beacon_interval); + + nla_nest_end(msg, bss_param); + } nla_nest_end(msg, sinfoattr); return genlmsg_end(msg, hdr); -- cgit v1.2.3-58-ga151 From 2d3d0a88bd136f8e6f39bc53242712852e5d0bb2 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 1 Apr 2011 18:36:46 -0700 Subject: mwifiex: return success in set_default_key for WPA/WPA2 When testing wpa_supplicant with 'nl80211' driver to connect to an AP with WPA/WPA2 security, we notice the followings: 1) add_key is called firstly with the key from cfg80211 2) set_defaut_key is called next set_default_key() is specific to WEP keys and should not be called in case of WPA/WPA2 security. The set_default_key() won't be called if wpa_supplicant uses "-Dwext" option, but it's been called if "-Dnl80211" option is specified. We can fix this issue by adding a check to return from set_default_key() if WEP key is not configured. Signed-off-by: Amitkumar Karwar Signed-off-by: Yogesh Ashok Powar Signed-off-by: Marc Yang Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 2d9680044c12..4ac4f5a0ce61 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -228,6 +228,10 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); int ret; + /* Return if WEP key not configured */ + if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED) + return 0; + ret = mwifiex_set_encode(priv, NULL, 0, key_index, 0); wiphy_dbg(wiphy, "info: set default Tx key index\n"); -- cgit v1.2.3-58-ga151 From 2be50b8df53f2f329b7ddcc8be286ef6a7469fd2 Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Fri, 1 Apr 2011 18:36:47 -0700 Subject: mwifiex: remove redundant encryption_mode mapping remove MWIFIEX_ENCRYPTION_MODE_ and use WLAN_CIPHER_SUITE_ macros directly Signed-off-by: Yogesh Ashok Powar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 76 +++++--------------------------- drivers/net/wireless/mwifiex/init.c | 2 +- drivers/net/wireless/mwifiex/ioctl.h | 8 ---- drivers/net/wireless/mwifiex/join.c | 2 +- drivers/net/wireless/mwifiex/scan.c | 12 ++--- drivers/net/wireless/mwifiex/sta_event.c | 2 +- 6 files changed, 19 insertions(+), 83 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 4ac4f5a0ce61..ec0895f4e8d3 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -90,8 +90,8 @@ mwifiex_is_alg_wep(u32 cipher) int alg = 0; switch (cipher) { - case MWIFIEX_ENCRYPTION_MODE_WEP40: - case MWIFIEX_ENCRYPTION_MODE_WEP104: + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: alg = 1; break; default: @@ -101,55 +101,6 @@ mwifiex_is_alg_wep(u32 cipher) return alg; } -/* - * This function maps the given cipher type into driver specific type. - * - * It also sets a flag to indicate whether WPA is enabled or not. - * - * The mapping table is - - * Input cipher Driver cipher type WPA enabled? - * ------------ ------------------ ------------ - * IW_AUTH_CIPHER_NONE MWIFIEX_ENCRYPTION_MODE_NONE No - * WLAN_CIPHER_SUITE_WEP40 MWIFIEX_ENCRYPTION_MODE_WEP40 No - * WLAN_CIPHER_SUITE_WEP104 MWIFIEX_ENCRYPTION_MODE_WEP104 No - * WLAN_CIPHER_SUITE_TKIP MWIFIEX_ENCRYPTION_MODE_TKIP Yes - * WLAN_CIPHER_SUITE_CCMP MWIFIEX_ENCRYPTION_MODE_CCMP Yes - * Others -1 No - */ -static int -mwifiex_get_mwifiex_cipher(u32 cipher, int *wpa_enabled) -{ - int encrypt_mode; - - if (wpa_enabled) - *wpa_enabled = 0; - switch (cipher) { - case IW_AUTH_CIPHER_NONE: - encrypt_mode = MWIFIEX_ENCRYPTION_MODE_NONE; - break; - case WLAN_CIPHER_SUITE_WEP40: - encrypt_mode = MWIFIEX_ENCRYPTION_MODE_WEP40; - break; - case WLAN_CIPHER_SUITE_WEP104: - encrypt_mode = MWIFIEX_ENCRYPTION_MODE_WEP104; - break; - case WLAN_CIPHER_SUITE_TKIP: - encrypt_mode = MWIFIEX_ENCRYPTION_MODE_TKIP; - if (wpa_enabled) - *wpa_enabled = 1; - break; - case WLAN_CIPHER_SUITE_CCMP: - encrypt_mode = MWIFIEX_ENCRYPTION_MODE_CCMP; - if (wpa_enabled) - *wpa_enabled = 1; - break; - default: - encrypt_mode = -1; - } - - return encrypt_mode; -} - /* * This function retrieves the private structure from kernel wiphy structure. */ @@ -252,13 +203,9 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, { struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); int ret = 0; - int encrypt_mode; - - encrypt_mode = mwifiex_get_mwifiex_cipher(params->cipher, NULL); - if (encrypt_mode != -1) - ret = mwifiex_set_encode(priv, params->key, params->key_len, - key_index, 0); + ret = mwifiex_set_encode(priv, params->key, params->key_len, + key_index, 0); wiphy_dbg(wiphy, "info: crypto keys added\n"); @@ -1019,7 +966,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, struct mwifiex_802_11_ssid req_ssid; struct mwifiex_ssid_bssid ssid_bssid; int ret = 0; - int auth_type = 0, pairwise_encrypt_mode = 0, wpa_enabled = 0; + int auth_type = 0, pairwise_encrypt_mode = 0; int group_encrypt_mode = 0; int alg_is_wep = 0; @@ -1052,13 +999,13 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, /* "privacy" is set only for ad-hoc mode */ if (privacy) { /* - * Keep MWIFIEX_ENCRYPTION_MODE_WEP104 for now so that + * Keep WLAN_CIPHER_SUITE_WEP104 for now so that * the firmware can find a matching network from the * scan. The cfg80211 does not give us the encryption * mode at this stage so just setting it to WEP here. */ priv->sec_info.encryption_mode = - MWIFIEX_ENCRYPTION_MODE_WEP104; + WLAN_CIPHER_SUITE_WEP104; priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; } @@ -1074,16 +1021,13 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, auth_type = NL80211_AUTHTYPE_SHARED_KEY; if (sme->crypto.n_ciphers_pairwise) { - pairwise_encrypt_mode = mwifiex_get_mwifiex_cipher(sme->crypto. - ciphers_pairwise[0], &wpa_enabled); - priv->sec_info.encryption_mode = pairwise_encrypt_mode; + priv->sec_info.encryption_mode = + sme->crypto.ciphers_pairwise[0]; priv->sec_info.authentication_mode = auth_type; } if (sme->crypto.cipher_group) { - group_encrypt_mode = mwifiex_get_mwifiex_cipher(sme->crypto. - cipher_group, &wpa_enabled); - priv->sec_info.encryption_mode = group_encrypt_mode; + priv->sec_info.encryption_mode = sme->crypto.cipher_group; priv->sec_info.authentication_mode = auth_type; } if (sme->ie) diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 43ea87d0f348..8189862da1f9 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -86,7 +86,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) priv->sec_info.wep_status = MWIFIEX_802_11_WEP_DISABLED; priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; - priv->sec_info.encryption_mode = MWIFIEX_ENCRYPTION_MODE_NONE; + priv->sec_info.encryption_mode = 0; for (i = 0; i < ARRAY_SIZE(priv->wep_key); i++) memset(&priv->wep_key[i], 0, sizeof(struct mwifiex_wep_key)); priv->wep_key_curr_index = 0; diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index d01160aa1db8..703a6d12ebf3 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -267,14 +267,6 @@ struct mwifiex_debug_info { u8 event_received; }; -enum { - MWIFIEX_ENCRYPTION_MODE_NONE = 0, - MWIFIEX_ENCRYPTION_MODE_WEP40 = 1, - MWIFIEX_ENCRYPTION_MODE_TKIP = 2, - MWIFIEX_ENCRYPTION_MODE_CCMP = 3, - MWIFIEX_ENCRYPTION_MODE_WEP104 = 4, -}; - #define MWIFIEX_KEY_INDEX_UNICAST 0x40000000 #define MWIFIEX_MAX_KEY_LENGTH 32 #define WAPI_RXPN_LEN 16 diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 8a1eb2a9ab13..7a9e0b5962ed 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -869,7 +869,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, tmp_cap |= WLAN_CAPABILITY_IBSS; /* Set up privacy in bss_desc */ - if (priv->sec_info.encryption_mode != MWIFIEX_ENCRYPTION_MODE_NONE) { + if (priv->sec_info.encryption_mode) { /* Ad-Hoc capability privacy on */ dev_dbg(adapter->dev, "info: ADHOC_S_CMD: wep_status set privacy to WEP\n"); diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 64ed60a80977..6bb52d0e6cfa 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -273,8 +273,8 @@ mwifiex_is_network_compatible_for_no_sec(struct mwifiex_private *priv, && ((!bss_desc->bcn_rsn_ie) || ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) - && priv->sec_info.encryption_mode == - MWIFIEX_ENCRYPTION_MODE_NONE && !bss_desc->privacy) { + && !priv->sec_info.encryption_mode + && !bss_desc->privacy) { return true; } return false; @@ -386,8 +386,8 @@ mwifiex_is_network_compatible_for_adhoc_aes(struct mwifiex_private *priv, element_id != WLAN_EID_WPA)) && ((!bss_desc->bcn_rsn_ie) || ((*(bss_desc->bcn_rsn_ie)).ieee_hdr. element_id != WLAN_EID_RSN)) - && priv->sec_info.encryption_mode == - MWIFIEX_ENCRYPTION_MODE_NONE && bss_desc->privacy) { + && !priv->sec_info.encryption_mode + && bss_desc->privacy) { return true; } return false; @@ -408,8 +408,8 @@ mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv, element_id != WLAN_EID_WPA)) && ((!bss_desc->bcn_rsn_ie) || ((*(bss_desc->bcn_rsn_ie)).ieee_hdr. element_id != WLAN_EID_RSN)) - && priv->sec_info.encryption_mode != - MWIFIEX_ENCRYPTION_MODE_NONE && bss_desc->privacy) { + && priv->sec_info.encryption_mode + && bss_desc->privacy) { dev_dbg(priv->adapter->dev, "info: %s: dynamic " "WEP: index=%d wpa_ie=%#x wpa2_ie=%#x " "EncMode=%#x privacy=%#x\n", diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 0187185a1fc6..936d7c175e75 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -76,7 +76,7 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv) priv->wapi_ie_len = 0; priv->sec_info.wapi_key_on = false; - priv->sec_info.encryption_mode = MWIFIEX_ENCRYPTION_MODE_NONE; + priv->sec_info.encryption_mode = 0; /* Enable auto data rate */ priv->is_data_rate_auto = true; -- cgit v1.2.3-58-ga151 From 5e65968a10bb628b87024161c9adc8dbd886b47a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 2 Apr 2011 03:39:47 +0200 Subject: ath9k: fix beacon slot processing in ad-hoc mode The recent cleanups in the beacon code fixed SWBA backoff calculation, however it did not remove a line of code that worked around the issues from the earlier version of the code. After the cleanup, the initial TSF based slot calculation now always returns 0 instead of ATH_BCBUF-1, so the previous hack that reversed the slot order needs to be removed, as ad-hoc mode does not use staggered beacons. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 74f33bc193fe..24861b247b44 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -392,14 +392,6 @@ void ath_beacon_tasklet(unsigned long data) tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); slot = (tsftu % (intval * ATH_BCBUF)) / intval; - /* - * Reverse the slot order to get slot 0 on the TBTT offset that does - * not require TSF adjustment and other slots adding - * slot/ATH_BCBUF * beacon_int to timestamp. For example, with - * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 .. - * and slot 0 is at correct offset to TBTT. - */ - slot = ATH_BCBUF - slot - 1; vif = sc->beacon.bslot[slot]; ath_dbg(common, ATH_DBG_BEACON, -- cgit v1.2.3-58-ga151 From 26cd322bacd3d65fffef6f8418c2fdad5b42e4b5 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 2 Apr 2011 03:39:48 +0200 Subject: ath9k: use the hw opmode to select the beacon timer mode Since the beacon timers are global, the individual vif type should not be used to determine the beacon timer configuration mode, use the global opmode instead. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 24861b247b44..f6885278398a 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -700,7 +700,7 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) if (cur_conf->dtim_period == 0) cur_conf->dtim_period = 1; - switch (iftype) { + switch (sc->sc_ah->opmode) { case NL80211_IFTYPE_AP: ath_beacon_config_ap(sc, cur_conf); break; -- cgit v1.2.3-58-ga151 From fbd5d17b8e2b418b495599c554f9c4754b7f93c9 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Sat, 2 Apr 2011 11:25:54 +0300 Subject: zd1211rw: rename CR* macros to ZD_CR* With compat-wireless CR* macros in zd_usb.h conflict with CR macros in include/asm-generic/termbits.h. So rename CR* macros to ZD_CR*. Conversion was done with using sed and then 'over 80 character line' checkpatch.pl warnings and comment indents were fixed. Reported-by: Walter Goldens Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_chip.c | 262 ++++++------- drivers/net/wireless/zd1211rw/zd_chip.h | 533 +++++++++++++------------- drivers/net/wireless/zd1211rw/zd_rf.h | 2 +- drivers/net/wireless/zd1211rw/zd_rf_al2230.c | 198 +++++----- drivers/net/wireless/zd1211rw/zd_rf_al7230b.c | 240 ++++++------ drivers/net/wireless/zd1211rw/zd_rf_rf2959.c | 78 ++-- drivers/net/wireless/zd1211rw/zd_rf_uw2453.c | 86 +++-- drivers/net/wireless/zd1211rw/zd_usb.c | 4 +- drivers/net/wireless/zd1211rw/zd_usb.h | 2 +- 9 files changed, 710 insertions(+), 695 deletions(-) diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index a73a305d3cba..ff306d763e37 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -557,7 +557,7 @@ int zd_chip_unlock_phy_regs(struct zd_chip *chip) return r; } -/* CR157 can be optionally patched by the EEPROM for original ZD1211 */ +/* ZD_CR157 can be optionally patched by the EEPROM for original ZD1211 */ static int patch_cr157(struct zd_chip *chip) { int r; @@ -571,7 +571,7 @@ static int patch_cr157(struct zd_chip *chip) return r; dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value >> 8); - return zd_iowrite32_locked(chip, value >> 8, CR157); + return zd_iowrite32_locked(chip, value >> 8, ZD_CR157); } /* @@ -593,8 +593,8 @@ static int patch_6m_band_edge(struct zd_chip *chip, u8 channel) int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel) { struct zd_ioreq16 ioreqs[] = { - { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, - { CR47, 0x1e }, + { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, + { ZD_CR47, 0x1e }, }; /* FIXME: Channel 11 is not the edge for all regulatory domains. */ @@ -608,69 +608,69 @@ int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel) static int zd1211_hw_reset_phy(struct zd_chip *chip) { static const struct zd_ioreq16 ioreqs[] = { - { CR0, 0x0a }, { CR1, 0x06 }, { CR2, 0x26 }, - { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xa0 }, - { CR10, 0x81 }, { CR11, 0x00 }, { CR12, 0x7f }, - { CR13, 0x8c }, { CR14, 0x80 }, { CR15, 0x3d }, - { CR16, 0x20 }, { CR17, 0x1e }, { CR18, 0x0a }, - { CR19, 0x48 }, { CR20, 0x0c }, { CR21, 0x0c }, - { CR22, 0x23 }, { CR23, 0x90 }, { CR24, 0x14 }, - { CR25, 0x40 }, { CR26, 0x10 }, { CR27, 0x19 }, - { CR28, 0x7f }, { CR29, 0x80 }, { CR30, 0x4b }, - { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, - { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, - { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, - { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, - { CR43, 0x10 }, { CR44, 0x12 }, { CR46, 0xff }, - { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, - { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, - { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, - { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, - { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, - { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, - { CR79, 0x68 }, { CR80, 0x64 }, { CR81, 0x64 }, - { CR82, 0x00 }, { CR83, 0x00 }, { CR84, 0x00 }, - { CR85, 0x02 }, { CR86, 0x00 }, { CR87, 0x00 }, - { CR88, 0xff }, { CR89, 0xfc }, { CR90, 0x00 }, - { CR91, 0x00 }, { CR92, 0x00 }, { CR93, 0x08 }, - { CR94, 0x00 }, { CR95, 0x00 }, { CR96, 0xff }, - { CR97, 0xe7 }, { CR98, 0x00 }, { CR99, 0x00 }, - { CR100, 0x00 }, { CR101, 0xae }, { CR102, 0x02 }, - { CR103, 0x00 }, { CR104, 0x03 }, { CR105, 0x65 }, - { CR106, 0x04 }, { CR107, 0x00 }, { CR108, 0x0a }, - { CR109, 0xaa }, { CR110, 0xaa }, { CR111, 0x25 }, - { CR112, 0x25 }, { CR113, 0x00 }, { CR119, 0x1e }, - { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, + { ZD_CR0, 0x0a }, { ZD_CR1, 0x06 }, { ZD_CR2, 0x26 }, + { ZD_CR3, 0x38 }, { ZD_CR4, 0x80 }, { ZD_CR9, 0xa0 }, + { ZD_CR10, 0x81 }, { ZD_CR11, 0x00 }, { ZD_CR12, 0x7f }, + { ZD_CR13, 0x8c }, { ZD_CR14, 0x80 }, { ZD_CR15, 0x3d }, + { ZD_CR16, 0x20 }, { ZD_CR17, 0x1e }, { ZD_CR18, 0x0a }, + { ZD_CR19, 0x48 }, { ZD_CR20, 0x0c }, { ZD_CR21, 0x0c }, + { ZD_CR22, 0x23 }, { ZD_CR23, 0x90 }, { ZD_CR24, 0x14 }, + { ZD_CR25, 0x40 }, { ZD_CR26, 0x10 }, { ZD_CR27, 0x19 }, + { ZD_CR28, 0x7f }, { ZD_CR29, 0x80 }, { ZD_CR30, 0x4b }, + { ZD_CR31, 0x60 }, { ZD_CR32, 0x43 }, { ZD_CR33, 0x08 }, + { ZD_CR34, 0x06 }, { ZD_CR35, 0x0a }, { ZD_CR36, 0x00 }, + { ZD_CR37, 0x00 }, { ZD_CR38, 0x38 }, { ZD_CR39, 0x0c }, + { ZD_CR40, 0x84 }, { ZD_CR41, 0x2a }, { ZD_CR42, 0x80 }, + { ZD_CR43, 0x10 }, { ZD_CR44, 0x12 }, { ZD_CR46, 0xff }, + { ZD_CR47, 0x1E }, { ZD_CR48, 0x26 }, { ZD_CR49, 0x5b }, + { ZD_CR64, 0xd0 }, { ZD_CR65, 0x04 }, { ZD_CR66, 0x58 }, + { ZD_CR67, 0xc9 }, { ZD_CR68, 0x88 }, { ZD_CR69, 0x41 }, + { ZD_CR70, 0x23 }, { ZD_CR71, 0x10 }, { ZD_CR72, 0xff }, + { ZD_CR73, 0x32 }, { ZD_CR74, 0x30 }, { ZD_CR75, 0x65 }, + { ZD_CR76, 0x41 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x30 }, + { ZD_CR79, 0x68 }, { ZD_CR80, 0x64 }, { ZD_CR81, 0x64 }, + { ZD_CR82, 0x00 }, { ZD_CR83, 0x00 }, { ZD_CR84, 0x00 }, + { ZD_CR85, 0x02 }, { ZD_CR86, 0x00 }, { ZD_CR87, 0x00 }, + { ZD_CR88, 0xff }, { ZD_CR89, 0xfc }, { ZD_CR90, 0x00 }, + { ZD_CR91, 0x00 }, { ZD_CR92, 0x00 }, { ZD_CR93, 0x08 }, + { ZD_CR94, 0x00 }, { ZD_CR95, 0x00 }, { ZD_CR96, 0xff }, + { ZD_CR97, 0xe7 }, { ZD_CR98, 0x00 }, { ZD_CR99, 0x00 }, + { ZD_CR100, 0x00 }, { ZD_CR101, 0xae }, { ZD_CR102, 0x02 }, + { ZD_CR103, 0x00 }, { ZD_CR104, 0x03 }, { ZD_CR105, 0x65 }, + { ZD_CR106, 0x04 }, { ZD_CR107, 0x00 }, { ZD_CR108, 0x0a }, + { ZD_CR109, 0xaa }, { ZD_CR110, 0xaa }, { ZD_CR111, 0x25 }, + { ZD_CR112, 0x25 }, { ZD_CR113, 0x00 }, { ZD_CR119, 0x1e }, + { ZD_CR125, 0x90 }, { ZD_CR126, 0x00 }, { ZD_CR127, 0x00 }, { }, - { CR5, 0x00 }, { CR6, 0x00 }, { CR7, 0x00 }, - { CR8, 0x00 }, { CR9, 0x20 }, { CR12, 0xf0 }, - { CR20, 0x0e }, { CR21, 0x0e }, { CR27, 0x10 }, - { CR44, 0x33 }, { CR47, 0x1E }, { CR83, 0x24 }, - { CR84, 0x04 }, { CR85, 0x00 }, { CR86, 0x0C }, - { CR87, 0x12 }, { CR88, 0x0C }, { CR89, 0x00 }, - { CR90, 0x10 }, { CR91, 0x08 }, { CR93, 0x00 }, - { CR94, 0x01 }, { CR95, 0x00 }, { CR96, 0x50 }, - { CR97, 0x37 }, { CR98, 0x35 }, { CR101, 0x13 }, - { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, - { CR105, 0x12 }, { CR109, 0x27 }, { CR110, 0x27 }, - { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, - { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, - { CR117, 0xfc }, { CR118, 0xfa }, { CR120, 0x4f }, - { CR125, 0xaa }, { CR127, 0x03 }, { CR128, 0x14 }, - { CR129, 0x12 }, { CR130, 0x10 }, { CR131, 0x0C }, - { CR136, 0xdf }, { CR137, 0x40 }, { CR138, 0xa0 }, - { CR139, 0xb0 }, { CR140, 0x99 }, { CR141, 0x82 }, - { CR142, 0x54 }, { CR143, 0x1c }, { CR144, 0x6c }, - { CR147, 0x07 }, { CR148, 0x4c }, { CR149, 0x50 }, - { CR150, 0x0e }, { CR151, 0x18 }, { CR160, 0xfe }, - { CR161, 0xee }, { CR162, 0xaa }, { CR163, 0xfa }, - { CR164, 0xfa }, { CR165, 0xea }, { CR166, 0xbe }, - { CR167, 0xbe }, { CR168, 0x6a }, { CR169, 0xba }, - { CR170, 0xba }, { CR171, 0xba }, - /* Note: CR204 must lead the CR203 */ - { CR204, 0x7d }, + { ZD_CR5, 0x00 }, { ZD_CR6, 0x00 }, { ZD_CR7, 0x00 }, + { ZD_CR8, 0x00 }, { ZD_CR9, 0x20 }, { ZD_CR12, 0xf0 }, + { ZD_CR20, 0x0e }, { ZD_CR21, 0x0e }, { ZD_CR27, 0x10 }, + { ZD_CR44, 0x33 }, { ZD_CR47, 0x1E }, { ZD_CR83, 0x24 }, + { ZD_CR84, 0x04 }, { ZD_CR85, 0x00 }, { ZD_CR86, 0x0C }, + { ZD_CR87, 0x12 }, { ZD_CR88, 0x0C }, { ZD_CR89, 0x00 }, + { ZD_CR90, 0x10 }, { ZD_CR91, 0x08 }, { ZD_CR93, 0x00 }, + { ZD_CR94, 0x01 }, { ZD_CR95, 0x00 }, { ZD_CR96, 0x50 }, + { ZD_CR97, 0x37 }, { ZD_CR98, 0x35 }, { ZD_CR101, 0x13 }, + { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 }, { ZD_CR104, 0x18 }, + { ZD_CR105, 0x12 }, { ZD_CR109, 0x27 }, { ZD_CR110, 0x27 }, + { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 }, { ZD_CR113, 0x27 }, + { ZD_CR114, 0x27 }, { ZD_CR115, 0x26 }, { ZD_CR116, 0x24 }, + { ZD_CR117, 0xfc }, { ZD_CR118, 0xfa }, { ZD_CR120, 0x4f }, + { ZD_CR125, 0xaa }, { ZD_CR127, 0x03 }, { ZD_CR128, 0x14 }, + { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, { ZD_CR131, 0x0C }, + { ZD_CR136, 0xdf }, { ZD_CR137, 0x40 }, { ZD_CR138, 0xa0 }, + { ZD_CR139, 0xb0 }, { ZD_CR140, 0x99 }, { ZD_CR141, 0x82 }, + { ZD_CR142, 0x54 }, { ZD_CR143, 0x1c }, { ZD_CR144, 0x6c }, + { ZD_CR147, 0x07 }, { ZD_CR148, 0x4c }, { ZD_CR149, 0x50 }, + { ZD_CR150, 0x0e }, { ZD_CR151, 0x18 }, { ZD_CR160, 0xfe }, + { ZD_CR161, 0xee }, { ZD_CR162, 0xaa }, { ZD_CR163, 0xfa }, + { ZD_CR164, 0xfa }, { ZD_CR165, 0xea }, { ZD_CR166, 0xbe }, + { ZD_CR167, 0xbe }, { ZD_CR168, 0x6a }, { ZD_CR169, 0xba }, + { ZD_CR170, 0xba }, { ZD_CR171, 0xba }, + /* Note: ZD_CR204 must lead the ZD_CR203 */ + { ZD_CR204, 0x7d }, { }, - { CR203, 0x30 }, + { ZD_CR203, 0x30 }, }; int r, t; @@ -697,62 +697,62 @@ out: static int zd1211b_hw_reset_phy(struct zd_chip *chip) { static const struct zd_ioreq16 ioreqs[] = { - { CR0, 0x14 }, { CR1, 0x06 }, { CR2, 0x26 }, - { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xe0 }, - { CR10, 0x81 }, - /* power control { { CR11, 1 << 6 }, */ - { CR11, 0x00 }, - { CR12, 0xf0 }, { CR13, 0x8c }, { CR14, 0x80 }, - { CR15, 0x3d }, { CR16, 0x20 }, { CR17, 0x1e }, - { CR18, 0x0a }, { CR19, 0x48 }, - { CR20, 0x10 }, /* Org:0x0E, ComTrend:RalLink AP */ - { CR21, 0x0e }, { CR22, 0x23 }, { CR23, 0x90 }, - { CR24, 0x14 }, { CR25, 0x40 }, { CR26, 0x10 }, - { CR27, 0x10 }, { CR28, 0x7f }, { CR29, 0x80 }, - { CR30, 0x4b }, /* ASIC/FWT, no jointly decoder */ - { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, - { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, - { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, - { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, - { CR43, 0x10 }, { CR44, 0x33 }, { CR46, 0xff }, - { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, - { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, - { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, - { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, - { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, - { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, - { CR79, 0xf0 }, { CR80, 0x64 }, { CR81, 0x64 }, - { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, - { CR85, 0x00 }, { CR86, 0x0c }, { CR87, 0x12 }, - { CR88, 0x0c }, { CR89, 0x00 }, { CR90, 0x58 }, - { CR91, 0x04 }, { CR92, 0x00 }, { CR93, 0x00 }, - { CR94, 0x01 }, - { CR95, 0x20 }, /* ZD1211B */ - { CR96, 0x50 }, { CR97, 0x37 }, { CR98, 0x35 }, - { CR99, 0x00 }, { CR100, 0x01 }, { CR101, 0x13 }, - { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, - { CR105, 0x12 }, { CR106, 0x04 }, { CR107, 0x00 }, - { CR108, 0x0a }, { CR109, 0x27 }, { CR110, 0x27 }, - { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, - { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, - { CR117, 0xfc }, { CR118, 0xfa }, { CR119, 0x1e }, - { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, - { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, - { CR131, 0x0c }, { CR136, 0xdf }, { CR137, 0xa0 }, - { CR138, 0xa8 }, { CR139, 0xb4 }, { CR140, 0x98 }, - { CR141, 0x82 }, { CR142, 0x53 }, { CR143, 0x1c }, - { CR144, 0x6c }, { CR147, 0x07 }, { CR148, 0x40 }, - { CR149, 0x40 }, /* Org:0x50 ComTrend:RalLink AP */ - { CR150, 0x14 }, /* Org:0x0E ComTrend:RalLink AP */ - { CR151, 0x18 }, { CR159, 0x70 }, { CR160, 0xfe }, - { CR161, 0xee }, { CR162, 0xaa }, { CR163, 0xfa }, - { CR164, 0xfa }, { CR165, 0xea }, { CR166, 0xbe }, - { CR167, 0xbe }, { CR168, 0x6a }, { CR169, 0xba }, - { CR170, 0xba }, { CR171, 0xba }, - /* Note: CR204 must lead the CR203 */ - { CR204, 0x7d }, + { ZD_CR0, 0x14 }, { ZD_CR1, 0x06 }, { ZD_CR2, 0x26 }, + { ZD_CR3, 0x38 }, { ZD_CR4, 0x80 }, { ZD_CR9, 0xe0 }, + { ZD_CR10, 0x81 }, + /* power control { { ZD_CR11, 1 << 6 }, */ + { ZD_CR11, 0x00 }, + { ZD_CR12, 0xf0 }, { ZD_CR13, 0x8c }, { ZD_CR14, 0x80 }, + { ZD_CR15, 0x3d }, { ZD_CR16, 0x20 }, { ZD_CR17, 0x1e }, + { ZD_CR18, 0x0a }, { ZD_CR19, 0x48 }, + { ZD_CR20, 0x10 }, /* Org:0x0E, ComTrend:RalLink AP */ + { ZD_CR21, 0x0e }, { ZD_CR22, 0x23 }, { ZD_CR23, 0x90 }, + { ZD_CR24, 0x14 }, { ZD_CR25, 0x40 }, { ZD_CR26, 0x10 }, + { ZD_CR27, 0x10 }, { ZD_CR28, 0x7f }, { ZD_CR29, 0x80 }, + { ZD_CR30, 0x4b }, /* ASIC/FWT, no jointly decoder */ + { ZD_CR31, 0x60 }, { ZD_CR32, 0x43 }, { ZD_CR33, 0x08 }, + { ZD_CR34, 0x06 }, { ZD_CR35, 0x0a }, { ZD_CR36, 0x00 }, + { ZD_CR37, 0x00 }, { ZD_CR38, 0x38 }, { ZD_CR39, 0x0c }, + { ZD_CR40, 0x84 }, { ZD_CR41, 0x2a }, { ZD_CR42, 0x80 }, + { ZD_CR43, 0x10 }, { ZD_CR44, 0x33 }, { ZD_CR46, 0xff }, + { ZD_CR47, 0x1E }, { ZD_CR48, 0x26 }, { ZD_CR49, 0x5b }, + { ZD_CR64, 0xd0 }, { ZD_CR65, 0x04 }, { ZD_CR66, 0x58 }, + { ZD_CR67, 0xc9 }, { ZD_CR68, 0x88 }, { ZD_CR69, 0x41 }, + { ZD_CR70, 0x23 }, { ZD_CR71, 0x10 }, { ZD_CR72, 0xff }, + { ZD_CR73, 0x32 }, { ZD_CR74, 0x30 }, { ZD_CR75, 0x65 }, + { ZD_CR76, 0x41 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x30 }, + { ZD_CR79, 0xf0 }, { ZD_CR80, 0x64 }, { ZD_CR81, 0x64 }, + { ZD_CR82, 0x00 }, { ZD_CR83, 0x24 }, { ZD_CR84, 0x04 }, + { ZD_CR85, 0x00 }, { ZD_CR86, 0x0c }, { ZD_CR87, 0x12 }, + { ZD_CR88, 0x0c }, { ZD_CR89, 0x00 }, { ZD_CR90, 0x58 }, + { ZD_CR91, 0x04 }, { ZD_CR92, 0x00 }, { ZD_CR93, 0x00 }, + { ZD_CR94, 0x01 }, + { ZD_CR95, 0x20 }, /* ZD1211B */ + { ZD_CR96, 0x50 }, { ZD_CR97, 0x37 }, { ZD_CR98, 0x35 }, + { ZD_CR99, 0x00 }, { ZD_CR100, 0x01 }, { ZD_CR101, 0x13 }, + { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 }, { ZD_CR104, 0x18 }, + { ZD_CR105, 0x12 }, { ZD_CR106, 0x04 }, { ZD_CR107, 0x00 }, + { ZD_CR108, 0x0a }, { ZD_CR109, 0x27 }, { ZD_CR110, 0x27 }, + { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 }, { ZD_CR113, 0x27 }, + { ZD_CR114, 0x27 }, { ZD_CR115, 0x26 }, { ZD_CR116, 0x24 }, + { ZD_CR117, 0xfc }, { ZD_CR118, 0xfa }, { ZD_CR119, 0x1e }, + { ZD_CR125, 0x90 }, { ZD_CR126, 0x00 }, { ZD_CR127, 0x00 }, + { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, + { ZD_CR131, 0x0c }, { ZD_CR136, 0xdf }, { ZD_CR137, 0xa0 }, + { ZD_CR138, 0xa8 }, { ZD_CR139, 0xb4 }, { ZD_CR140, 0x98 }, + { ZD_CR141, 0x82 }, { ZD_CR142, 0x53 }, { ZD_CR143, 0x1c }, + { ZD_CR144, 0x6c }, { ZD_CR147, 0x07 }, { ZD_CR148, 0x40 }, + { ZD_CR149, 0x40 }, /* Org:0x50 ComTrend:RalLink AP */ + { ZD_CR150, 0x14 }, /* Org:0x0E ComTrend:RalLink AP */ + { ZD_CR151, 0x18 }, { ZD_CR159, 0x70 }, { ZD_CR160, 0xfe }, + { ZD_CR161, 0xee }, { ZD_CR162, 0xaa }, { ZD_CR163, 0xfa }, + { ZD_CR164, 0xfa }, { ZD_CR165, 0xea }, { ZD_CR166, 0xbe }, + { ZD_CR167, 0xbe }, { ZD_CR168, 0x6a }, { ZD_CR169, 0xba }, + { ZD_CR170, 0xba }, { ZD_CR171, 0xba }, + /* Note: ZD_CR204 must lead the ZD_CR203 */ + { ZD_CR204, 0x7d }, {}, - { CR203, 0x30 }, + { ZD_CR203, 0x30 }, }; int r, t; @@ -1200,24 +1200,24 @@ out: static int update_pwr_int(struct zd_chip *chip, u8 channel) { u8 value = chip->pwr_int_values[channel - 1]; - return zd_iowrite16_locked(chip, value, CR31); + return zd_iowrite16_locked(chip, value, ZD_CR31); } static int update_pwr_cal(struct zd_chip *chip, u8 channel) { u8 value = chip->pwr_cal_values[channel-1]; - return zd_iowrite16_locked(chip, value, CR68); + return zd_iowrite16_locked(chip, value, ZD_CR68); } static int update_ofdm_cal(struct zd_chip *chip, u8 channel) { struct zd_ioreq16 ioreqs[3]; - ioreqs[0].addr = CR67; + ioreqs[0].addr = ZD_CR67; ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1]; - ioreqs[1].addr = CR66; + ioreqs[1].addr = ZD_CR66; ioreqs[1].value = chip->ofdm_cal_values[OFDM_48M_INDEX][channel-1]; - ioreqs[2].addr = CR65; + ioreqs[2].addr = ZD_CR65; ioreqs[2].value = chip->ofdm_cal_values[OFDM_54M_INDEX][channel-1]; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -1236,9 +1236,9 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip, return r; if (zd_chip_is_zd1211b(chip)) { static const struct zd_ioreq16 ioreqs[] = { - { CR69, 0x28 }, + { ZD_CR69, 0x28 }, {}, - { CR69, 0x2a }, + { ZD_CR69, 0x2a }, }; r = update_ofdm_cal(chip, channel); @@ -1269,7 +1269,7 @@ static int patch_cck_gain(struct zd_chip *chip) if (r) return r; dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff); - return zd_iowrite16_locked(chip, value & 0xff, CR47); + return zd_iowrite16_locked(chip, value & 0xff, ZD_CR47); } int zd_chip_set_channel(struct zd_chip *chip, u8 channel) @@ -1505,9 +1505,9 @@ int zd_rfwritev_locked(struct zd_chip *chip, int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value) { const struct zd_ioreq16 ioreqs[] = { - { CR244, (value >> 16) & 0xff }, - { CR243, (value >> 8) & 0xff }, - { CR242, value & 0xff }, + { ZD_CR244, (value >> 16) & 0xff }, + { ZD_CR243, (value >> 8) & 0xff }, + { ZD_CR242, value & 0xff }, }; ZD_ASSERT(mutex_is_locked(&chip->mutex)); return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 14e4402a6111..4be7c3b5b265 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -61,277 +61,288 @@ enum { #define FWRAW_DATA(offset) ((zd_addr_t)(FW_START + (offset))) /* 8-bit hardware registers */ -#define CR0 CTL_REG(0x0000) -#define CR1 CTL_REG(0x0004) -#define CR2 CTL_REG(0x0008) -#define CR3 CTL_REG(0x000C) +#define ZD_CR0 CTL_REG(0x0000) +#define ZD_CR1 CTL_REG(0x0004) +#define ZD_CR2 CTL_REG(0x0008) +#define ZD_CR3 CTL_REG(0x000C) -#define CR5 CTL_REG(0x0010) +#define ZD_CR5 CTL_REG(0x0010) /* bit 5: if set short preamble used * bit 6: filter band - Japan channel 14 on, else off */ -#define CR6 CTL_REG(0x0014) -#define CR7 CTL_REG(0x0018) -#define CR8 CTL_REG(0x001C) +#define ZD_CR6 CTL_REG(0x0014) +#define ZD_CR7 CTL_REG(0x0018) +#define ZD_CR8 CTL_REG(0x001C) -#define CR4 CTL_REG(0x0020) +#define ZD_CR4 CTL_REG(0x0020) -#define CR9 CTL_REG(0x0024) -/* bit 2: antenna switch (together with CR10) */ -#define CR10 CTL_REG(0x0028) -/* bit 1: antenna switch (together with CR9) - * RF2959 controls with CR11 radion on and off +#define ZD_CR9 CTL_REG(0x0024) +/* bit 2: antenna switch (together with ZD_CR10) */ +#define ZD_CR10 CTL_REG(0x0028) +/* bit 1: antenna switch (together with ZD_CR9) + * RF2959 controls with ZD_CR11 radion on and off */ -#define CR11 CTL_REG(0x002C) +#define ZD_CR11 CTL_REG(0x002C) /* bit 6: TX power control for OFDM - * RF2959 controls with CR10 radio on and off + * RF2959 controls with ZD_CR10 radio on and off */ -#define CR12 CTL_REG(0x0030) -#define CR13 CTL_REG(0x0034) -#define CR14 CTL_REG(0x0038) -#define CR15 CTL_REG(0x003C) -#define CR16 CTL_REG(0x0040) -#define CR17 CTL_REG(0x0044) -#define CR18 CTL_REG(0x0048) -#define CR19 CTL_REG(0x004C) -#define CR20 CTL_REG(0x0050) -#define CR21 CTL_REG(0x0054) -#define CR22 CTL_REG(0x0058) -#define CR23 CTL_REG(0x005C) -#define CR24 CTL_REG(0x0060) /* CCA threshold */ -#define CR25 CTL_REG(0x0064) -#define CR26 CTL_REG(0x0068) -#define CR27 CTL_REG(0x006C) -#define CR28 CTL_REG(0x0070) -#define CR29 CTL_REG(0x0074) -#define CR30 CTL_REG(0x0078) -#define CR31 CTL_REG(0x007C) /* TX power control for RF in CCK mode */ -#define CR32 CTL_REG(0x0080) -#define CR33 CTL_REG(0x0084) -#define CR34 CTL_REG(0x0088) -#define CR35 CTL_REG(0x008C) -#define CR36 CTL_REG(0x0090) -#define CR37 CTL_REG(0x0094) -#define CR38 CTL_REG(0x0098) -#define CR39 CTL_REG(0x009C) -#define CR40 CTL_REG(0x00A0) -#define CR41 CTL_REG(0x00A4) -#define CR42 CTL_REG(0x00A8) -#define CR43 CTL_REG(0x00AC) -#define CR44 CTL_REG(0x00B0) -#define CR45 CTL_REG(0x00B4) -#define CR46 CTL_REG(0x00B8) -#define CR47 CTL_REG(0x00BC) /* CCK baseband gain - * (patch value might be in EEPROM) - */ -#define CR48 CTL_REG(0x00C0) -#define CR49 CTL_REG(0x00C4) -#define CR50 CTL_REG(0x00C8) -#define CR51 CTL_REG(0x00CC) /* TX power control for RF in 6-36M modes */ -#define CR52 CTL_REG(0x00D0) /* TX power control for RF in 48M mode */ -#define CR53 CTL_REG(0x00D4) /* TX power control for RF in 54M mode */ -#define CR54 CTL_REG(0x00D8) -#define CR55 CTL_REG(0x00DC) -#define CR56 CTL_REG(0x00E0) -#define CR57 CTL_REG(0x00E4) -#define CR58 CTL_REG(0x00E8) -#define CR59 CTL_REG(0x00EC) -#define CR60 CTL_REG(0x00F0) -#define CR61 CTL_REG(0x00F4) -#define CR62 CTL_REG(0x00F8) -#define CR63 CTL_REG(0x00FC) -#define CR64 CTL_REG(0x0100) -#define CR65 CTL_REG(0x0104) /* OFDM 54M calibration */ -#define CR66 CTL_REG(0x0108) /* OFDM 48M calibration */ -#define CR67 CTL_REG(0x010C) /* OFDM 36M calibration */ -#define CR68 CTL_REG(0x0110) /* CCK calibration */ -#define CR69 CTL_REG(0x0114) -#define CR70 CTL_REG(0x0118) -#define CR71 CTL_REG(0x011C) -#define CR72 CTL_REG(0x0120) -#define CR73 CTL_REG(0x0124) -#define CR74 CTL_REG(0x0128) -#define CR75 CTL_REG(0x012C) -#define CR76 CTL_REG(0x0130) -#define CR77 CTL_REG(0x0134) -#define CR78 CTL_REG(0x0138) -#define CR79 CTL_REG(0x013C) -#define CR80 CTL_REG(0x0140) -#define CR81 CTL_REG(0x0144) -#define CR82 CTL_REG(0x0148) -#define CR83 CTL_REG(0x014C) -#define CR84 CTL_REG(0x0150) -#define CR85 CTL_REG(0x0154) -#define CR86 CTL_REG(0x0158) -#define CR87 CTL_REG(0x015C) -#define CR88 CTL_REG(0x0160) -#define CR89 CTL_REG(0x0164) -#define CR90 CTL_REG(0x0168) -#define CR91 CTL_REG(0x016C) -#define CR92 CTL_REG(0x0170) -#define CR93 CTL_REG(0x0174) -#define CR94 CTL_REG(0x0178) -#define CR95 CTL_REG(0x017C) -#define CR96 CTL_REG(0x0180) -#define CR97 CTL_REG(0x0184) -#define CR98 CTL_REG(0x0188) -#define CR99 CTL_REG(0x018C) -#define CR100 CTL_REG(0x0190) -#define CR101 CTL_REG(0x0194) -#define CR102 CTL_REG(0x0198) -#define CR103 CTL_REG(0x019C) -#define CR104 CTL_REG(0x01A0) -#define CR105 CTL_REG(0x01A4) -#define CR106 CTL_REG(0x01A8) -#define CR107 CTL_REG(0x01AC) -#define CR108 CTL_REG(0x01B0) -#define CR109 CTL_REG(0x01B4) -#define CR110 CTL_REG(0x01B8) -#define CR111 CTL_REG(0x01BC) -#define CR112 CTL_REG(0x01C0) -#define CR113 CTL_REG(0x01C4) -#define CR114 CTL_REG(0x01C8) -#define CR115 CTL_REG(0x01CC) -#define CR116 CTL_REG(0x01D0) -#define CR117 CTL_REG(0x01D4) -#define CR118 CTL_REG(0x01D8) -#define CR119 CTL_REG(0x01DC) -#define CR120 CTL_REG(0x01E0) -#define CR121 CTL_REG(0x01E4) -#define CR122 CTL_REG(0x01E8) -#define CR123 CTL_REG(0x01EC) -#define CR124 CTL_REG(0x01F0) -#define CR125 CTL_REG(0x01F4) -#define CR126 CTL_REG(0x01F8) -#define CR127 CTL_REG(0x01FC) -#define CR128 CTL_REG(0x0200) -#define CR129 CTL_REG(0x0204) -#define CR130 CTL_REG(0x0208) -#define CR131 CTL_REG(0x020C) -#define CR132 CTL_REG(0x0210) -#define CR133 CTL_REG(0x0214) -#define CR134 CTL_REG(0x0218) -#define CR135 CTL_REG(0x021C) -#define CR136 CTL_REG(0x0220) -#define CR137 CTL_REG(0x0224) -#define CR138 CTL_REG(0x0228) -#define CR139 CTL_REG(0x022C) -#define CR140 CTL_REG(0x0230) -#define CR141 CTL_REG(0x0234) -#define CR142 CTL_REG(0x0238) -#define CR143 CTL_REG(0x023C) -#define CR144 CTL_REG(0x0240) -#define CR145 CTL_REG(0x0244) -#define CR146 CTL_REG(0x0248) -#define CR147 CTL_REG(0x024C) -#define CR148 CTL_REG(0x0250) -#define CR149 CTL_REG(0x0254) -#define CR150 CTL_REG(0x0258) -#define CR151 CTL_REG(0x025C) -#define CR152 CTL_REG(0x0260) -#define CR153 CTL_REG(0x0264) -#define CR154 CTL_REG(0x0268) -#define CR155 CTL_REG(0x026C) -#define CR156 CTL_REG(0x0270) -#define CR157 CTL_REG(0x0274) -#define CR158 CTL_REG(0x0278) -#define CR159 CTL_REG(0x027C) -#define CR160 CTL_REG(0x0280) -#define CR161 CTL_REG(0x0284) -#define CR162 CTL_REG(0x0288) -#define CR163 CTL_REG(0x028C) -#define CR164 CTL_REG(0x0290) -#define CR165 CTL_REG(0x0294) -#define CR166 CTL_REG(0x0298) -#define CR167 CTL_REG(0x029C) -#define CR168 CTL_REG(0x02A0) -#define CR169 CTL_REG(0x02A4) -#define CR170 CTL_REG(0x02A8) -#define CR171 CTL_REG(0x02AC) -#define CR172 CTL_REG(0x02B0) -#define CR173 CTL_REG(0x02B4) -#define CR174 CTL_REG(0x02B8) -#define CR175 CTL_REG(0x02BC) -#define CR176 CTL_REG(0x02C0) -#define CR177 CTL_REG(0x02C4) -#define CR178 CTL_REG(0x02C8) -#define CR179 CTL_REG(0x02CC) -#define CR180 CTL_REG(0x02D0) -#define CR181 CTL_REG(0x02D4) -#define CR182 CTL_REG(0x02D8) -#define CR183 CTL_REG(0x02DC) -#define CR184 CTL_REG(0x02E0) -#define CR185 CTL_REG(0x02E4) -#define CR186 CTL_REG(0x02E8) -#define CR187 CTL_REG(0x02EC) -#define CR188 CTL_REG(0x02F0) -#define CR189 CTL_REG(0x02F4) -#define CR190 CTL_REG(0x02F8) -#define CR191 CTL_REG(0x02FC) -#define CR192 CTL_REG(0x0300) -#define CR193 CTL_REG(0x0304) -#define CR194 CTL_REG(0x0308) -#define CR195 CTL_REG(0x030C) -#define CR196 CTL_REG(0x0310) -#define CR197 CTL_REG(0x0314) -#define CR198 CTL_REG(0x0318) -#define CR199 CTL_REG(0x031C) -#define CR200 CTL_REG(0x0320) -#define CR201 CTL_REG(0x0324) -#define CR202 CTL_REG(0x0328) -#define CR203 CTL_REG(0x032C) /* I2C bus template value & flash control */ -#define CR204 CTL_REG(0x0330) -#define CR205 CTL_REG(0x0334) -#define CR206 CTL_REG(0x0338) -#define CR207 CTL_REG(0x033C) -#define CR208 CTL_REG(0x0340) -#define CR209 CTL_REG(0x0344) -#define CR210 CTL_REG(0x0348) -#define CR211 CTL_REG(0x034C) -#define CR212 CTL_REG(0x0350) -#define CR213 CTL_REG(0x0354) -#define CR214 CTL_REG(0x0358) -#define CR215 CTL_REG(0x035C) -#define CR216 CTL_REG(0x0360) -#define CR217 CTL_REG(0x0364) -#define CR218 CTL_REG(0x0368) -#define CR219 CTL_REG(0x036C) -#define CR220 CTL_REG(0x0370) -#define CR221 CTL_REG(0x0374) -#define CR222 CTL_REG(0x0378) -#define CR223 CTL_REG(0x037C) -#define CR224 CTL_REG(0x0380) -#define CR225 CTL_REG(0x0384) -#define CR226 CTL_REG(0x0388) -#define CR227 CTL_REG(0x038C) -#define CR228 CTL_REG(0x0390) -#define CR229 CTL_REG(0x0394) -#define CR230 CTL_REG(0x0398) -#define CR231 CTL_REG(0x039C) -#define CR232 CTL_REG(0x03A0) -#define CR233 CTL_REG(0x03A4) -#define CR234 CTL_REG(0x03A8) -#define CR235 CTL_REG(0x03AC) -#define CR236 CTL_REG(0x03B0) - -#define CR240 CTL_REG(0x03C0) -/* bit 7: host-controlled RF register writes - * CR241-CR245: for hardware controlled writing of RF bits, not needed for - * USB +#define ZD_CR12 CTL_REG(0x0030) +#define ZD_CR13 CTL_REG(0x0034) +#define ZD_CR14 CTL_REG(0x0038) +#define ZD_CR15 CTL_REG(0x003C) +#define ZD_CR16 CTL_REG(0x0040) +#define ZD_CR17 CTL_REG(0x0044) +#define ZD_CR18 CTL_REG(0x0048) +#define ZD_CR19 CTL_REG(0x004C) +#define ZD_CR20 CTL_REG(0x0050) +#define ZD_CR21 CTL_REG(0x0054) +#define ZD_CR22 CTL_REG(0x0058) +#define ZD_CR23 CTL_REG(0x005C) +#define ZD_CR24 CTL_REG(0x0060) /* CCA threshold */ +#define ZD_CR25 CTL_REG(0x0064) +#define ZD_CR26 CTL_REG(0x0068) +#define ZD_CR27 CTL_REG(0x006C) +#define ZD_CR28 CTL_REG(0x0070) +#define ZD_CR29 CTL_REG(0x0074) +#define ZD_CR30 CTL_REG(0x0078) +#define ZD_CR31 CTL_REG(0x007C) /* TX power control for RF in + * CCK mode + */ +#define ZD_CR32 CTL_REG(0x0080) +#define ZD_CR33 CTL_REG(0x0084) +#define ZD_CR34 CTL_REG(0x0088) +#define ZD_CR35 CTL_REG(0x008C) +#define ZD_CR36 CTL_REG(0x0090) +#define ZD_CR37 CTL_REG(0x0094) +#define ZD_CR38 CTL_REG(0x0098) +#define ZD_CR39 CTL_REG(0x009C) +#define ZD_CR40 CTL_REG(0x00A0) +#define ZD_CR41 CTL_REG(0x00A4) +#define ZD_CR42 CTL_REG(0x00A8) +#define ZD_CR43 CTL_REG(0x00AC) +#define ZD_CR44 CTL_REG(0x00B0) +#define ZD_CR45 CTL_REG(0x00B4) +#define ZD_CR46 CTL_REG(0x00B8) +#define ZD_CR47 CTL_REG(0x00BC) /* CCK baseband gain + * (patch value might be in EEPROM) + */ +#define ZD_CR48 CTL_REG(0x00C0) +#define ZD_CR49 CTL_REG(0x00C4) +#define ZD_CR50 CTL_REG(0x00C8) +#define ZD_CR51 CTL_REG(0x00CC) /* TX power control for RF in + * 6-36M modes + */ +#define ZD_CR52 CTL_REG(0x00D0) /* TX power control for RF in + * 48M mode + */ +#define ZD_CR53 CTL_REG(0x00D4) /* TX power control for RF in + * 54M mode + */ +#define ZD_CR54 CTL_REG(0x00D8) +#define ZD_CR55 CTL_REG(0x00DC) +#define ZD_CR56 CTL_REG(0x00E0) +#define ZD_CR57 CTL_REG(0x00E4) +#define ZD_CR58 CTL_REG(0x00E8) +#define ZD_CR59 CTL_REG(0x00EC) +#define ZD_CR60 CTL_REG(0x00F0) +#define ZD_CR61 CTL_REG(0x00F4) +#define ZD_CR62 CTL_REG(0x00F8) +#define ZD_CR63 CTL_REG(0x00FC) +#define ZD_CR64 CTL_REG(0x0100) +#define ZD_CR65 CTL_REG(0x0104) /* OFDM 54M calibration */ +#define ZD_CR66 CTL_REG(0x0108) /* OFDM 48M calibration */ +#define ZD_CR67 CTL_REG(0x010C) /* OFDM 36M calibration */ +#define ZD_CR68 CTL_REG(0x0110) /* CCK calibration */ +#define ZD_CR69 CTL_REG(0x0114) +#define ZD_CR70 CTL_REG(0x0118) +#define ZD_CR71 CTL_REG(0x011C) +#define ZD_CR72 CTL_REG(0x0120) +#define ZD_CR73 CTL_REG(0x0124) +#define ZD_CR74 CTL_REG(0x0128) +#define ZD_CR75 CTL_REG(0x012C) +#define ZD_CR76 CTL_REG(0x0130) +#define ZD_CR77 CTL_REG(0x0134) +#define ZD_CR78 CTL_REG(0x0138) +#define ZD_CR79 CTL_REG(0x013C) +#define ZD_CR80 CTL_REG(0x0140) +#define ZD_CR81 CTL_REG(0x0144) +#define ZD_CR82 CTL_REG(0x0148) +#define ZD_CR83 CTL_REG(0x014C) +#define ZD_CR84 CTL_REG(0x0150) +#define ZD_CR85 CTL_REG(0x0154) +#define ZD_CR86 CTL_REG(0x0158) +#define ZD_CR87 CTL_REG(0x015C) +#define ZD_CR88 CTL_REG(0x0160) +#define ZD_CR89 CTL_REG(0x0164) +#define ZD_CR90 CTL_REG(0x0168) +#define ZD_CR91 CTL_REG(0x016C) +#define ZD_CR92 CTL_REG(0x0170) +#define ZD_CR93 CTL_REG(0x0174) +#define ZD_CR94 CTL_REG(0x0178) +#define ZD_CR95 CTL_REG(0x017C) +#define ZD_CR96 CTL_REG(0x0180) +#define ZD_CR97 CTL_REG(0x0184) +#define ZD_CR98 CTL_REG(0x0188) +#define ZD_CR99 CTL_REG(0x018C) +#define ZD_CR100 CTL_REG(0x0190) +#define ZD_CR101 CTL_REG(0x0194) +#define ZD_CR102 CTL_REG(0x0198) +#define ZD_CR103 CTL_REG(0x019C) +#define ZD_CR104 CTL_REG(0x01A0) +#define ZD_CR105 CTL_REG(0x01A4) +#define ZD_CR106 CTL_REG(0x01A8) +#define ZD_CR107 CTL_REG(0x01AC) +#define ZD_CR108 CTL_REG(0x01B0) +#define ZD_CR109 CTL_REG(0x01B4) +#define ZD_CR110 CTL_REG(0x01B8) +#define ZD_CR111 CTL_REG(0x01BC) +#define ZD_CR112 CTL_REG(0x01C0) +#define ZD_CR113 CTL_REG(0x01C4) +#define ZD_CR114 CTL_REG(0x01C8) +#define ZD_CR115 CTL_REG(0x01CC) +#define ZD_CR116 CTL_REG(0x01D0) +#define ZD_CR117 CTL_REG(0x01D4) +#define ZD_CR118 CTL_REG(0x01D8) +#define ZD_CR119 CTL_REG(0x01DC) +#define ZD_CR120 CTL_REG(0x01E0) +#define ZD_CR121 CTL_REG(0x01E4) +#define ZD_CR122 CTL_REG(0x01E8) +#define ZD_CR123 CTL_REG(0x01EC) +#define ZD_CR124 CTL_REG(0x01F0) +#define ZD_CR125 CTL_REG(0x01F4) +#define ZD_CR126 CTL_REG(0x01F8) +#define ZD_CR127 CTL_REG(0x01FC) +#define ZD_CR128 CTL_REG(0x0200) +#define ZD_CR129 CTL_REG(0x0204) +#define ZD_CR130 CTL_REG(0x0208) +#define ZD_CR131 CTL_REG(0x020C) +#define ZD_CR132 CTL_REG(0x0210) +#define ZD_CR133 CTL_REG(0x0214) +#define ZD_CR134 CTL_REG(0x0218) +#define ZD_CR135 CTL_REG(0x021C) +#define ZD_CR136 CTL_REG(0x0220) +#define ZD_CR137 CTL_REG(0x0224) +#define ZD_CR138 CTL_REG(0x0228) +#define ZD_CR139 CTL_REG(0x022C) +#define ZD_CR140 CTL_REG(0x0230) +#define ZD_CR141 CTL_REG(0x0234) +#define ZD_CR142 CTL_REG(0x0238) +#define ZD_CR143 CTL_REG(0x023C) +#define ZD_CR144 CTL_REG(0x0240) +#define ZD_CR145 CTL_REG(0x0244) +#define ZD_CR146 CTL_REG(0x0248) +#define ZD_CR147 CTL_REG(0x024C) +#define ZD_CR148 CTL_REG(0x0250) +#define ZD_CR149 CTL_REG(0x0254) +#define ZD_CR150 CTL_REG(0x0258) +#define ZD_CR151 CTL_REG(0x025C) +#define ZD_CR152 CTL_REG(0x0260) +#define ZD_CR153 CTL_REG(0x0264) +#define ZD_CR154 CTL_REG(0x0268) +#define ZD_CR155 CTL_REG(0x026C) +#define ZD_CR156 CTL_REG(0x0270) +#define ZD_CR157 CTL_REG(0x0274) +#define ZD_CR158 CTL_REG(0x0278) +#define ZD_CR159 CTL_REG(0x027C) +#define ZD_CR160 CTL_REG(0x0280) +#define ZD_CR161 CTL_REG(0x0284) +#define ZD_CR162 CTL_REG(0x0288) +#define ZD_CR163 CTL_REG(0x028C) +#define ZD_CR164 CTL_REG(0x0290) +#define ZD_CR165 CTL_REG(0x0294) +#define ZD_CR166 CTL_REG(0x0298) +#define ZD_CR167 CTL_REG(0x029C) +#define ZD_CR168 CTL_REG(0x02A0) +#define ZD_CR169 CTL_REG(0x02A4) +#define ZD_CR170 CTL_REG(0x02A8) +#define ZD_CR171 CTL_REG(0x02AC) +#define ZD_CR172 CTL_REG(0x02B0) +#define ZD_CR173 CTL_REG(0x02B4) +#define ZD_CR174 CTL_REG(0x02B8) +#define ZD_CR175 CTL_REG(0x02BC) +#define ZD_CR176 CTL_REG(0x02C0) +#define ZD_CR177 CTL_REG(0x02C4) +#define ZD_CR178 CTL_REG(0x02C8) +#define ZD_CR179 CTL_REG(0x02CC) +#define ZD_CR180 CTL_REG(0x02D0) +#define ZD_CR181 CTL_REG(0x02D4) +#define ZD_CR182 CTL_REG(0x02D8) +#define ZD_CR183 CTL_REG(0x02DC) +#define ZD_CR184 CTL_REG(0x02E0) +#define ZD_CR185 CTL_REG(0x02E4) +#define ZD_CR186 CTL_REG(0x02E8) +#define ZD_CR187 CTL_REG(0x02EC) +#define ZD_CR188 CTL_REG(0x02F0) +#define ZD_CR189 CTL_REG(0x02F4) +#define ZD_CR190 CTL_REG(0x02F8) +#define ZD_CR191 CTL_REG(0x02FC) +#define ZD_CR192 CTL_REG(0x0300) +#define ZD_CR193 CTL_REG(0x0304) +#define ZD_CR194 CTL_REG(0x0308) +#define ZD_CR195 CTL_REG(0x030C) +#define ZD_CR196 CTL_REG(0x0310) +#define ZD_CR197 CTL_REG(0x0314) +#define ZD_CR198 CTL_REG(0x0318) +#define ZD_CR199 CTL_REG(0x031C) +#define ZD_CR200 CTL_REG(0x0320) +#define ZD_CR201 CTL_REG(0x0324) +#define ZD_CR202 CTL_REG(0x0328) +#define ZD_CR203 CTL_REG(0x032C) /* I2C bus template value & flash + * control + */ +#define ZD_CR204 CTL_REG(0x0330) +#define ZD_CR205 CTL_REG(0x0334) +#define ZD_CR206 CTL_REG(0x0338) +#define ZD_CR207 CTL_REG(0x033C) +#define ZD_CR208 CTL_REG(0x0340) +#define ZD_CR209 CTL_REG(0x0344) +#define ZD_CR210 CTL_REG(0x0348) +#define ZD_CR211 CTL_REG(0x034C) +#define ZD_CR212 CTL_REG(0x0350) +#define ZD_CR213 CTL_REG(0x0354) +#define ZD_CR214 CTL_REG(0x0358) +#define ZD_CR215 CTL_REG(0x035C) +#define ZD_CR216 CTL_REG(0x0360) +#define ZD_CR217 CTL_REG(0x0364) +#define ZD_CR218 CTL_REG(0x0368) +#define ZD_CR219 CTL_REG(0x036C) +#define ZD_CR220 CTL_REG(0x0370) +#define ZD_CR221 CTL_REG(0x0374) +#define ZD_CR222 CTL_REG(0x0378) +#define ZD_CR223 CTL_REG(0x037C) +#define ZD_CR224 CTL_REG(0x0380) +#define ZD_CR225 CTL_REG(0x0384) +#define ZD_CR226 CTL_REG(0x0388) +#define ZD_CR227 CTL_REG(0x038C) +#define ZD_CR228 CTL_REG(0x0390) +#define ZD_CR229 CTL_REG(0x0394) +#define ZD_CR230 CTL_REG(0x0398) +#define ZD_CR231 CTL_REG(0x039C) +#define ZD_CR232 CTL_REG(0x03A0) +#define ZD_CR233 CTL_REG(0x03A4) +#define ZD_CR234 CTL_REG(0x03A8) +#define ZD_CR235 CTL_REG(0x03AC) +#define ZD_CR236 CTL_REG(0x03B0) + +#define ZD_CR240 CTL_REG(0x03C0) +/* bit 7: host-controlled RF register writes + * ZD_CR241-ZD_CR245: for hardware controlled writing of RF bits, not needed for + * USB */ -#define CR241 CTL_REG(0x03C4) -#define CR242 CTL_REG(0x03C8) -#define CR243 CTL_REG(0x03CC) -#define CR244 CTL_REG(0x03D0) -#define CR245 CTL_REG(0x03D4) - -#define CR251 CTL_REG(0x03EC) /* only used for activation and deactivation of - * Airoha RFs AL2230 and AL7230B - */ -#define CR252 CTL_REG(0x03F0) -#define CR253 CTL_REG(0x03F4) -#define CR254 CTL_REG(0x03F8) -#define CR255 CTL_REG(0x03FC) +#define ZD_CR241 CTL_REG(0x03C4) +#define ZD_CR242 CTL_REG(0x03C8) +#define ZD_CR243 CTL_REG(0x03CC) +#define ZD_CR244 CTL_REG(0x03D0) +#define ZD_CR245 CTL_REG(0x03D4) + +#define ZD_CR251 CTL_REG(0x03EC) /* only used for activation and + * deactivation of Airoha RFs AL2230 + * and AL7230B + */ +#define ZD_CR252 CTL_REG(0x03F0) +#define ZD_CR253 CTL_REG(0x03F4) +#define ZD_CR254 CTL_REG(0x03F8) +#define ZD_CR255 CTL_REG(0x03FC) #define CR_MAX_PHY_REG 255 diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h index 79dc1035592d..725b7c99b23d 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf.h +++ b/drivers/net/wireless/zd1211rw/zd_rf.h @@ -55,7 +55,7 @@ struct zd_rf { * defaults to 1 (yes) */ u8 update_channel_int:1; - /* whether CR47 should be patched from the EEPROM, if the appropriate + /* whether ZD_CR47 should be patched from the EEPROM, if the appropriate * flag is set in the POD. The vendor driver suggests that this should * be done for all RF's, but a bug in their code prevents but their * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */ diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c index 74a8f7a55591..12babcb633c3 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c @@ -61,31 +61,31 @@ static const u32 zd1211b_al2230_table[][3] = { }; static const struct zd_ioreq16 zd1211b_ioreqs_shared_1[] = { - { CR240, 0x57 }, { CR9, 0xe0 }, + { ZD_CR240, 0x57 }, { ZD_CR9, 0xe0 }, }; static const struct zd_ioreq16 ioreqs_init_al2230s[] = { - { CR47, 0x1e }, /* MARK_002 */ - { CR106, 0x22 }, - { CR107, 0x2a }, /* MARK_002 */ - { CR109, 0x13 }, /* MARK_002 */ - { CR118, 0xf8 }, /* MARK_002 */ - { CR119, 0x12 }, { CR122, 0xe0 }, - { CR128, 0x10 }, /* MARK_001 from 0xe->0x10 */ - { CR129, 0x0e }, /* MARK_001 from 0xd->0x0e */ - { CR130, 0x10 }, /* MARK_001 from 0xb->0x0d */ + { ZD_CR47, 0x1e }, /* MARK_002 */ + { ZD_CR106, 0x22 }, + { ZD_CR107, 0x2a }, /* MARK_002 */ + { ZD_CR109, 0x13 }, /* MARK_002 */ + { ZD_CR118, 0xf8 }, /* MARK_002 */ + { ZD_CR119, 0x12 }, { ZD_CR122, 0xe0 }, + { ZD_CR128, 0x10 }, /* MARK_001 from 0xe->0x10 */ + { ZD_CR129, 0x0e }, /* MARK_001 from 0xd->0x0e */ + { ZD_CR130, 0x10 }, /* MARK_001 from 0xb->0x0d */ }; static int zd1211b_al2230_finalize_rf(struct zd_chip *chip) { int r; static const struct zd_ioreq16 ioreqs[] = { - { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, - { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, - { CR203, 0x06 }, + { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, { ZD_CR79, 0x58 }, + { ZD_CR12, 0xf0 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x58 }, + { ZD_CR203, 0x06 }, { }, - { CR240, 0x80 }, + { ZD_CR240, 0x80 }, }; r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -94,12 +94,12 @@ static int zd1211b_al2230_finalize_rf(struct zd_chip *chip) /* related to antenna selection? */ if (chip->new_phy_layout) { - r = zd_iowrite16_locked(chip, 0xe1, CR9); + r = zd_iowrite16_locked(chip, 0xe1, ZD_CR9); if (r) return r; } - return zd_iowrite16_locked(chip, 0x06, CR203); + return zd_iowrite16_locked(chip, 0x06, ZD_CR203); } static int zd1211_al2230_init_hw(struct zd_rf *rf) @@ -108,40 +108,40 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf) struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs_init[] = { - { CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 }, - { CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 }, - { CR44, 0x33 }, { CR106, 0x2a }, { CR107, 0x1a }, - { CR109, 0x09 }, { CR110, 0x27 }, { CR111, 0x2b }, - { CR112, 0x2b }, { CR119, 0x0a }, { CR10, 0x89 }, + { ZD_CR15, 0x20 }, { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 }, + { ZD_CR26, 0x11 }, { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, + { ZD_CR44, 0x33 }, { ZD_CR106, 0x2a }, { ZD_CR107, 0x1a }, + { ZD_CR109, 0x09 }, { ZD_CR110, 0x27 }, { ZD_CR111, 0x2b }, + { ZD_CR112, 0x2b }, { ZD_CR119, 0x0a }, { ZD_CR10, 0x89 }, /* for newest (3rd cut) AL2300 */ - { CR17, 0x28 }, - { CR26, 0x93 }, { CR34, 0x30 }, + { ZD_CR17, 0x28 }, + { ZD_CR26, 0x93 }, { ZD_CR34, 0x30 }, /* for newest (3rd cut) AL2300 */ - { CR35, 0x3e }, - { CR41, 0x24 }, { CR44, 0x32 }, + { ZD_CR35, 0x3e }, + { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, /* for newest (3rd cut) AL2300 */ - { CR46, 0x96 }, - { CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 }, - { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, - { CR92, 0x0a }, { CR99, 0x28 }, { CR100, 0x00 }, - { CR101, 0x13 }, { CR102, 0x27 }, { CR106, 0x24 }, - { CR107, 0x2a }, { CR109, 0x09 }, { CR110, 0x13 }, - { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, - { CR114, 0x27 }, + { ZD_CR46, 0x96 }, + { ZD_CR47, 0x1e }, { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, + { ZD_CR81, 0x30 }, { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 }, + { ZD_CR92, 0x0a }, { ZD_CR99, 0x28 }, { ZD_CR100, 0x00 }, + { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, { ZD_CR106, 0x24 }, + { ZD_CR107, 0x2a }, { ZD_CR109, 0x09 }, { ZD_CR110, 0x13 }, + { ZD_CR111, 0x1f }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 }, + { ZD_CR114, 0x27 }, /* for newest (3rd cut) AL2300 */ - { CR115, 0x24 }, - { CR116, 0x24 }, { CR117, 0xf4 }, { CR118, 0xfc }, - { CR119, 0x10 }, { CR120, 0x4f }, { CR121, 0x77 }, - { CR122, 0xe0 }, { CR137, 0x88 }, { CR252, 0xff }, - { CR253, 0xff }, + { ZD_CR115, 0x24 }, + { ZD_CR116, 0x24 }, { ZD_CR117, 0xf4 }, { ZD_CR118, 0xfc }, + { ZD_CR119, 0x10 }, { ZD_CR120, 0x4f }, { ZD_CR121, 0x77 }, + { ZD_CR122, 0xe0 }, { ZD_CR137, 0x88 }, { ZD_CR252, 0xff }, + { ZD_CR253, 0xff }, }; static const struct zd_ioreq16 ioreqs_pll[] = { /* shdnb(PLL_ON)=0 */ - { CR251, 0x2f }, + { ZD_CR251, 0x2f }, /* shdnb(PLL_ON)=1 */ - { CR251, 0x3f }, - { CR138, 0x28 }, { CR203, 0x06 }, + { ZD_CR251, 0x3f }, + { ZD_CR138, 0x28 }, { ZD_CR203, 0x06 }, }; static const u32 rv1[] = { @@ -161,7 +161,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf) 0x0805b6, 0x011687, 0x000688, - 0x0403b9, /* external control TX power (CR31) */ + 0x0403b9, /* external control TX power (ZD_CR31) */ 0x00dbba, 0x00099b, 0x0bdffc, @@ -221,52 +221,54 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs1[] = { - { CR10, 0x89 }, { CR15, 0x20 }, - { CR17, 0x2B }, /* for newest(3rd cut) AL2230 */ - { CR23, 0x40 }, { CR24, 0x20 }, { CR26, 0x93 }, - { CR28, 0x3e }, { CR29, 0x00 }, - { CR33, 0x28 }, /* 5621 */ - { CR34, 0x30 }, - { CR35, 0x3e }, /* for newest(3rd cut) AL2230 */ - { CR41, 0x24 }, { CR44, 0x32 }, - { CR46, 0x99 }, /* for newest(3rd cut) AL2230 */ - { CR47, 0x1e }, + { ZD_CR10, 0x89 }, { ZD_CR15, 0x20 }, + { ZD_CR17, 0x2B }, /* for newest(3rd cut) AL2230 */ + { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 }, { ZD_CR26, 0x93 }, + { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, + { ZD_CR33, 0x28 }, /* 5621 */ + { ZD_CR34, 0x30 }, + { ZD_CR35, 0x3e }, /* for newest(3rd cut) AL2230 */ + { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, + { ZD_CR46, 0x99 }, /* for newest(3rd cut) AL2230 */ + { ZD_CR47, 0x1e }, /* ZD1211B 05.06.10 */ - { CR48, 0x06 }, { CR49, 0xf9 }, { CR51, 0x01 }, - { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, - { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, - { CR69, 0x28 }, - - { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, - { CR87, 0x0a }, { CR89, 0x04 }, - { CR91, 0x00 }, /* 5621 */ - { CR92, 0x0a }, - { CR98, 0x8d }, /* 4804, for 1212 new algorithm */ - { CR99, 0x00 }, /* 5621 */ - { CR101, 0x13 }, { CR102, 0x27 }, - { CR106, 0x24 }, /* for newest(3rd cut) AL2230 */ - { CR107, 0x2a }, - { CR109, 0x13 }, /* 4804, for 1212 new algorithm */ - { CR110, 0x1f }, /* 4804, for 1212 new algorithm */ - { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, - { CR114, 0x27 }, - { CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut) AL2230 */ - { CR116, 0x24 }, - { CR117, 0xfa }, /* for 1211b */ - { CR118, 0xfa }, /* for 1211b */ - { CR119, 0x10 }, - { CR120, 0x4f }, - { CR121, 0x6c }, /* for 1211b */ - { CR122, 0xfc }, /* E0->FC at 4902 */ - { CR123, 0x57 }, /* 5623 */ - { CR125, 0xad }, /* 4804, for 1212 new algorithm */ - { CR126, 0x6c }, /* 5614 */ - { CR127, 0x03 }, /* 4804, for 1212 new algorithm */ - { CR137, 0x50 }, /* 5614 */ - { CR138, 0xa8 }, - { CR144, 0xac }, /* 5621 */ - { CR150, 0x0d }, { CR252, 0x34 }, { CR253, 0x34 }, + { ZD_CR48, 0x06 }, { ZD_CR49, 0xf9 }, { ZD_CR51, 0x01 }, + { ZD_CR52, 0x80 }, { ZD_CR53, 0x7e }, { ZD_CR65, 0x00 }, + { ZD_CR66, 0x00 }, { ZD_CR67, 0x00 }, { ZD_CR68, 0x00 }, + { ZD_CR69, 0x28 }, + + { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, + { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 }, + { ZD_CR91, 0x00 }, /* 5621 */ + { ZD_CR92, 0x0a }, + { ZD_CR98, 0x8d }, /* 4804, for 1212 new algorithm */ + { ZD_CR99, 0x00 }, /* 5621 */ + { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, + { ZD_CR106, 0x24 }, /* for newest(3rd cut) AL2230 */ + { ZD_CR107, 0x2a }, + { ZD_CR109, 0x13 }, /* 4804, for 1212 new algorithm */ + { ZD_CR110, 0x1f }, /* 4804, for 1212 new algorithm */ + { ZD_CR111, 0x1f }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 }, + { ZD_CR114, 0x27 }, + { ZD_CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut) + * AL2230 + */ + { ZD_CR116, 0x24 }, + { ZD_CR117, 0xfa }, /* for 1211b */ + { ZD_CR118, 0xfa }, /* for 1211b */ + { ZD_CR119, 0x10 }, + { ZD_CR120, 0x4f }, + { ZD_CR121, 0x6c }, /* for 1211b */ + { ZD_CR122, 0xfc }, /* E0->FC at 4902 */ + { ZD_CR123, 0x57 }, /* 5623 */ + { ZD_CR125, 0xad }, /* 4804, for 1212 new algorithm */ + { ZD_CR126, 0x6c }, /* 5614 */ + { ZD_CR127, 0x03 }, /* 4804, for 1212 new algorithm */ + { ZD_CR137, 0x50 }, /* 5614 */ + { ZD_CR138, 0xa8 }, + { ZD_CR144, 0xac }, /* 5621 */ + { ZD_CR150, 0x0d }, { ZD_CR252, 0x34 }, { ZD_CR253, 0x34 }, }; static const u32 rv1[] = { @@ -284,7 +286,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) 0x6da010, /* Reg6 update for MP versio */ 0xe36280, /* Modified by jxiao for Bor-Chin on 2004/08/02 */ 0x116000, - 0x9dc020, /* External control TX power (CR31) */ + 0x9dc020, /* External control TX power (ZD_CR31) */ 0x5ddb00, /* RegA update for MP version */ 0xd99000, /* RegB update for MP version */ 0x3ffbd0, /* RegC update for MP version */ @@ -295,8 +297,8 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) }; static const struct zd_ioreq16 ioreqs2[] = { - { CR251, 0x2f }, /* shdnb(PLL_ON)=0 */ - { CR251, 0x7f }, /* shdnb(PLL_ON)=1 */ + { ZD_CR251, 0x2f }, /* shdnb(PLL_ON)=0 */ + { ZD_CR251, 0x7f }, /* shdnb(PLL_ON)=1 */ }; static const u32 rv3[] = { @@ -308,7 +310,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) static const struct zd_ioreq16 ioreqs3[] = { /* related to 6M band edge patching, happens unconditionally */ - { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, + { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, }; r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1, @@ -361,8 +363,8 @@ static int zd1211_al2230_set_channel(struct zd_rf *rf, u8 channel) const u32 *rv = zd1211_al2230_table[channel-1]; struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { CR138, 0x28 }, - { CR203, 0x06 }, + { ZD_CR138, 0x28 }, + { ZD_CR203, 0x06 }, }; r = zd_rfwritev_locked(chip, rv, 3, RF_RV_BITS); @@ -393,8 +395,8 @@ static int zd1211_al2230_switch_radio_on(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x00 }, - { CR251, 0x3f }, + { ZD_CR11, 0x00 }, + { ZD_CR251, 0x3f }, }; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -404,8 +406,8 @@ static int zd1211b_al2230_switch_radio_on(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x00 }, - { CR251, 0x7f }, + { ZD_CR11, 0x00 }, + { ZD_CR251, 0x7f }, }; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -415,8 +417,8 @@ static int al2230_switch_radio_off(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x04 }, - { CR251, 0x2f }, + { ZD_CR11, 0x04 }, + { ZD_CR251, 0x2f }, }; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c index 65095d661e6b..385c670d1293 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c @@ -68,19 +68,19 @@ static const u32 rv_init2[] = { }; static const struct zd_ioreq16 ioreqs_sw[] = { - { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, - { CR38, 0x38 }, { CR136, 0xdf }, + { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, + { ZD_CR38, 0x38 }, { ZD_CR136, 0xdf }, }; static int zd1211b_al7230b_finalize(struct zd_chip *chip) { int r; static const struct zd_ioreq16 ioreqs[] = { - { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, - { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, - { CR203, 0x04 }, + { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, { ZD_CR79, 0x58 }, + { ZD_CR12, 0xf0 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x58 }, + { ZD_CR203, 0x04 }, { }, - { CR240, 0x80 }, + { ZD_CR240, 0x80 }, }; r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -89,12 +89,12 @@ static int zd1211b_al7230b_finalize(struct zd_chip *chip) if (chip->new_phy_layout) { /* antenna selection? */ - r = zd_iowrite16_locked(chip, 0xe5, CR9); + r = zd_iowrite16_locked(chip, 0xe5, ZD_CR9); if (r) return r; } - return zd_iowrite16_locked(chip, 0x04, CR203); + return zd_iowrite16_locked(chip, 0x04, ZD_CR203); } static int zd1211_al7230b_init_hw(struct zd_rf *rf) @@ -106,66 +106,66 @@ static int zd1211_al7230b_init_hw(struct zd_rf *rf) * specified */ static const struct zd_ioreq16 ioreqs_1[] = { /* This one is 7230-specific, and happens before the rest */ - { CR240, 0x57 }, + { ZD_CR240, 0x57 }, { }, - { CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 }, - { CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 }, - { CR44, 0x33 }, + { ZD_CR15, 0x20 }, { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 }, + { ZD_CR26, 0x11 }, { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, + { ZD_CR44, 0x33 }, /* This value is different for 7230 (was: 0x2a) */ - { CR106, 0x22 }, - { CR107, 0x1a }, { CR109, 0x09 }, { CR110, 0x27 }, - { CR111, 0x2b }, { CR112, 0x2b }, { CR119, 0x0a }, + { ZD_CR106, 0x22 }, + { ZD_CR107, 0x1a }, { ZD_CR109, 0x09 }, { ZD_CR110, 0x27 }, + { ZD_CR111, 0x2b }, { ZD_CR112, 0x2b }, { ZD_CR119, 0x0a }, /* This happened further down in AL2230, * and the value changed (was: 0xe0) */ - { CR122, 0xfc }, - { CR10, 0x89 }, + { ZD_CR122, 0xfc }, + { ZD_CR10, 0x89 }, /* for newest (3rd cut) AL2300 */ - { CR17, 0x28 }, - { CR26, 0x93 }, { CR34, 0x30 }, + { ZD_CR17, 0x28 }, + { ZD_CR26, 0x93 }, { ZD_CR34, 0x30 }, /* for newest (3rd cut) AL2300 */ - { CR35, 0x3e }, - { CR41, 0x24 }, { CR44, 0x32 }, + { ZD_CR35, 0x3e }, + { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, /* for newest (3rd cut) AL2300 */ - { CR46, 0x96 }, - { CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 }, - { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, - { CR92, 0x0a }, { CR99, 0x28 }, + { ZD_CR46, 0x96 }, + { ZD_CR47, 0x1e }, { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, + { ZD_CR81, 0x30 }, { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 }, + { ZD_CR92, 0x0a }, { ZD_CR99, 0x28 }, /* This value is different for 7230 (was: 0x00) */ - { CR100, 0x02 }, - { CR101, 0x13 }, { CR102, 0x27 }, + { ZD_CR100, 0x02 }, + { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, /* This value is different for 7230 (was: 0x24) */ - { CR106, 0x22 }, + { ZD_CR106, 0x22 }, /* This value is different for 7230 (was: 0x2a) */ - { CR107, 0x3f }, - { CR109, 0x09 }, + { ZD_CR107, 0x3f }, + { ZD_CR109, 0x09 }, /* This value is different for 7230 (was: 0x13) */ - { CR110, 0x1f }, - { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, - { CR114, 0x27 }, + { ZD_CR110, 0x1f }, + { ZD_CR111, 0x1f }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 }, + { ZD_CR114, 0x27 }, /* for newest (3rd cut) AL2300 */ - { CR115, 0x24 }, + { ZD_CR115, 0x24 }, /* This value is different for 7230 (was: 0x24) */ - { CR116, 0x3f }, + { ZD_CR116, 0x3f }, /* This value is different for 7230 (was: 0xf4) */ - { CR117, 0xfa }, - { CR118, 0xfc }, { CR119, 0x10 }, { CR120, 0x4f }, - { CR121, 0x77 }, { CR137, 0x88 }, + { ZD_CR117, 0xfa }, + { ZD_CR118, 0xfc }, { ZD_CR119, 0x10 }, { ZD_CR120, 0x4f }, + { ZD_CR121, 0x77 }, { ZD_CR137, 0x88 }, /* This one is 7230-specific */ - { CR138, 0xa8 }, + { ZD_CR138, 0xa8 }, /* This value is different for 7230 (was: 0xff) */ - { CR252, 0x34 }, + { ZD_CR252, 0x34 }, /* This value is different for 7230 (was: 0xff) */ - { CR253, 0x34 }, + { ZD_CR253, 0x34 }, /* PLL_OFF */ - { CR251, 0x2f }, + { ZD_CR251, 0x2f }, }; static const struct zd_ioreq16 ioreqs_2[] = { - { CR251, 0x3f }, /* PLL_ON */ - { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, - { CR38, 0x38 }, { CR136, 0xdf }, + { ZD_CR251, 0x3f }, /* PLL_ON */ + { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, + { ZD_CR38, 0x38 }, { ZD_CR136, 0xdf }, }; r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1)); @@ -192,10 +192,10 @@ static int zd1211_al7230b_init_hw(struct zd_rf *rf) if (r) return r; - r = zd_iowrite16_locked(chip, 0x06, CR203); + r = zd_iowrite16_locked(chip, 0x06, ZD_CR203); if (r) return r; - r = zd_iowrite16_locked(chip, 0x80, CR240); + r = zd_iowrite16_locked(chip, 0x80, ZD_CR240); if (r) return r; @@ -208,79 +208,79 @@ static int zd1211b_al7230b_init_hw(struct zd_rf *rf) struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs_1[] = { - { CR240, 0x57 }, { CR9, 0x9 }, + { ZD_CR240, 0x57 }, { ZD_CR9, 0x9 }, { }, - { CR10, 0x8b }, { CR15, 0x20 }, - { CR17, 0x2B }, /* for newest (3rd cut) AL2230 */ - { CR20, 0x10 }, /* 4N25->Stone Request */ - { CR23, 0x40 }, { CR24, 0x20 }, { CR26, 0x93 }, - { CR28, 0x3e }, { CR29, 0x00 }, - { CR33, 0x28 }, /* 5613 */ - { CR34, 0x30 }, - { CR35, 0x3e }, /* for newest (3rd cut) AL2230 */ - { CR41, 0x24 }, { CR44, 0x32 }, - { CR46, 0x99 }, /* for newest (3rd cut) AL2230 */ - { CR47, 0x1e }, + { ZD_CR10, 0x8b }, { ZD_CR15, 0x20 }, + { ZD_CR17, 0x2B }, /* for newest (3rd cut) AL2230 */ + { ZD_CR20, 0x10 }, /* 4N25->Stone Request */ + { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 }, { ZD_CR26, 0x93 }, + { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, + { ZD_CR33, 0x28 }, /* 5613 */ + { ZD_CR34, 0x30 }, + { ZD_CR35, 0x3e }, /* for newest (3rd cut) AL2230 */ + { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, + { ZD_CR46, 0x99 }, /* for newest (3rd cut) AL2230 */ + { ZD_CR47, 0x1e }, /* ZD1215 5610 */ - { CR48, 0x00 }, { CR49, 0x00 }, { CR51, 0x01 }, - { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, - { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, - { CR69, 0x28 }, - - { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, - { CR87, 0x0A }, { CR89, 0x04 }, - { CR90, 0x58 }, /* 5112 */ - { CR91, 0x00 }, /* 5613 */ - { CR92, 0x0a }, - { CR98, 0x8d }, /* 4804, for 1212 new algorithm */ - { CR99, 0x00 }, { CR100, 0x02 }, { CR101, 0x13 }, - { CR102, 0x27 }, - { CR106, 0x20 }, /* change to 0x24 for AL7230B */ - { CR109, 0x13 }, /* 4804, for 1212 new algorithm */ - { CR112, 0x1f }, + { ZD_CR48, 0x00 }, { ZD_CR49, 0x00 }, { ZD_CR51, 0x01 }, + { ZD_CR52, 0x80 }, { ZD_CR53, 0x7e }, { ZD_CR65, 0x00 }, + { ZD_CR66, 0x00 }, { ZD_CR67, 0x00 }, { ZD_CR68, 0x00 }, + { ZD_CR69, 0x28 }, + + { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, + { ZD_CR87, 0x0A }, { ZD_CR89, 0x04 }, + { ZD_CR90, 0x58 }, /* 5112 */ + { ZD_CR91, 0x00 }, /* 5613 */ + { ZD_CR92, 0x0a }, + { ZD_CR98, 0x8d }, /* 4804, for 1212 new algorithm */ + { ZD_CR99, 0x00 }, { ZD_CR100, 0x02 }, { ZD_CR101, 0x13 }, + { ZD_CR102, 0x27 }, + { ZD_CR106, 0x20 }, /* change to 0x24 for AL7230B */ + { ZD_CR109, 0x13 }, /* 4804, for 1212 new algorithm */ + { ZD_CR112, 0x1f }, }; static const struct zd_ioreq16 ioreqs_new_phy[] = { - { CR107, 0x28 }, - { CR110, 0x1f }, /* 5127, 0x13->0x1f */ - { CR111, 0x1f }, /* 0x13 to 0x1f for AL7230B */ - { CR116, 0x2a }, { CR118, 0xfa }, { CR119, 0x12 }, - { CR121, 0x6c }, /* 5613 */ + { ZD_CR107, 0x28 }, + { ZD_CR110, 0x1f }, /* 5127, 0x13->0x1f */ + { ZD_CR111, 0x1f }, /* 0x13 to 0x1f for AL7230B */ + { ZD_CR116, 0x2a }, { ZD_CR118, 0xfa }, { ZD_CR119, 0x12 }, + { ZD_CR121, 0x6c }, /* 5613 */ }; static const struct zd_ioreq16 ioreqs_old_phy[] = { - { CR107, 0x24 }, - { CR110, 0x13 }, /* 5127, 0x13->0x1f */ - { CR111, 0x13 }, /* 0x13 to 0x1f for AL7230B */ - { CR116, 0x24 }, { CR118, 0xfc }, { CR119, 0x11 }, - { CR121, 0x6a }, /* 5613 */ + { ZD_CR107, 0x24 }, + { ZD_CR110, 0x13 }, /* 5127, 0x13->0x1f */ + { ZD_CR111, 0x13 }, /* 0x13 to 0x1f for AL7230B */ + { ZD_CR116, 0x24 }, { ZD_CR118, 0xfc }, { ZD_CR119, 0x11 }, + { ZD_CR121, 0x6a }, /* 5613 */ }; static const struct zd_ioreq16 ioreqs_2[] = { - { CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x24 }, - { CR117, 0xfa }, { CR120, 0x4f }, - { CR122, 0xfc }, /* E0->FCh at 4901 */ - { CR123, 0x57 }, /* 5613 */ - { CR125, 0xad }, /* 4804, for 1212 new algorithm */ - { CR126, 0x6c }, /* 5613 */ - { CR127, 0x03 }, /* 4804, for 1212 new algorithm */ - { CR130, 0x10 }, - { CR131, 0x00 }, /* 5112 */ - { CR137, 0x50 }, /* 5613 */ - { CR138, 0xa8 }, /* 5112 */ - { CR144, 0xac }, /* 5613 */ - { CR148, 0x40 }, /* 5112 */ - { CR149, 0x40 }, /* 4O07, 50->40 */ - { CR150, 0x1a }, /* 5112, 0C->1A */ - { CR252, 0x34 }, { CR253, 0x34 }, - { CR251, 0x2f }, /* PLL_OFF */ + { ZD_CR113, 0x27 }, { ZD_CR114, 0x27 }, { ZD_CR115, 0x24 }, + { ZD_CR117, 0xfa }, { ZD_CR120, 0x4f }, + { ZD_CR122, 0xfc }, /* E0->FCh at 4901 */ + { ZD_CR123, 0x57 }, /* 5613 */ + { ZD_CR125, 0xad }, /* 4804, for 1212 new algorithm */ + { ZD_CR126, 0x6c }, /* 5613 */ + { ZD_CR127, 0x03 }, /* 4804, for 1212 new algorithm */ + { ZD_CR130, 0x10 }, + { ZD_CR131, 0x00 }, /* 5112 */ + { ZD_CR137, 0x50 }, /* 5613 */ + { ZD_CR138, 0xa8 }, /* 5112 */ + { ZD_CR144, 0xac }, /* 5613 */ + { ZD_CR148, 0x40 }, /* 5112 */ + { ZD_CR149, 0x40 }, /* 4O07, 50->40 */ + { ZD_CR150, 0x1a }, /* 5112, 0C->1A */ + { ZD_CR252, 0x34 }, { ZD_CR253, 0x34 }, + { ZD_CR251, 0x2f }, /* PLL_OFF */ }; static const struct zd_ioreq16 ioreqs_3[] = { - { CR251, 0x7f }, /* PLL_ON */ - { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, - { CR38, 0x38 }, { CR136, 0xdf }, + { ZD_CR251, 0x7f }, /* PLL_ON */ + { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, + { ZD_CR38, 0x38 }, { ZD_CR136, 0xdf }, }; r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1)); @@ -331,16 +331,16 @@ static int zd1211_al7230b_set_channel(struct zd_rf *rf, u8 channel) static const struct zd_ioreq16 ioreqs[] = { /* PLL_ON */ - { CR251, 0x3f }, - { CR203, 0x06 }, { CR240, 0x08 }, + { ZD_CR251, 0x3f }, + { ZD_CR203, 0x06 }, { ZD_CR240, 0x08 }, }; - r = zd_iowrite16_locked(chip, 0x57, CR240); + r = zd_iowrite16_locked(chip, 0x57, ZD_CR240); if (r) return r; /* PLL_OFF */ - r = zd_iowrite16_locked(chip, 0x2f, CR251); + r = zd_iowrite16_locked(chip, 0x2f, ZD_CR251); if (r) return r; @@ -376,15 +376,15 @@ static int zd1211b_al7230b_set_channel(struct zd_rf *rf, u8 channel) const u32 *rv = chan_rv[channel-1]; struct zd_chip *chip = zd_rf_to_chip(rf); - r = zd_iowrite16_locked(chip, 0x57, CR240); + r = zd_iowrite16_locked(chip, 0x57, ZD_CR240); if (r) return r; - r = zd_iowrite16_locked(chip, 0xe4, CR9); + r = zd_iowrite16_locked(chip, 0xe4, ZD_CR9); if (r) return r; /* PLL_OFF */ - r = zd_iowrite16_locked(chip, 0x2f, CR251); + r = zd_iowrite16_locked(chip, 0x2f, ZD_CR251); if (r) return r; r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv)); @@ -410,7 +410,7 @@ static int zd1211b_al7230b_set_channel(struct zd_rf *rf, u8 channel) if (r) return r; - r = zd_iowrite16_locked(chip, 0x7f, CR251); + r = zd_iowrite16_locked(chip, 0x7f, ZD_CR251); if (r) return r; @@ -421,8 +421,8 @@ static int zd1211_al7230b_switch_radio_on(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x00 }, - { CR251, 0x3f }, + { ZD_CR11, 0x00 }, + { ZD_CR251, 0x3f }, }; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -432,8 +432,8 @@ static int zd1211b_al7230b_switch_radio_on(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x00 }, - { CR251, 0x7f }, + { ZD_CR11, 0x00 }, + { ZD_CR251, 0x7f }, }; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -443,8 +443,8 @@ static int al7230b_switch_radio_off(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x04 }, - { CR251, 0x2f }, + { ZD_CR11, 0x04 }, + { ZD_CR251, 0x2f }, }; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -456,7 +456,7 @@ static int zd1211b_al7230b_patch_6m(struct zd_rf *rf, u8 channel) { struct zd_chip *chip = zd_rf_to_chip(rf); struct zd_ioreq16 ioreqs[] = { - { CR128, 0x14 }, { CR129, 0x12 }, + { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, }; /* FIXME: Channel 11 is not the edge for all regulatory domains. */ diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c index 0597d862fbd2..032542614259 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c @@ -152,44 +152,44 @@ static int rf2959_init_hw(struct zd_rf *rf) struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { CR2, 0x1E }, { CR9, 0x20 }, { CR10, 0x89 }, - { CR11, 0x00 }, { CR15, 0xD0 }, { CR17, 0x68 }, - { CR19, 0x4a }, { CR20, 0x0c }, { CR21, 0x0E }, - { CR23, 0x48 }, + { ZD_CR2, 0x1E }, { ZD_CR9, 0x20 }, { ZD_CR10, 0x89 }, + { ZD_CR11, 0x00 }, { ZD_CR15, 0xD0 }, { ZD_CR17, 0x68 }, + { ZD_CR19, 0x4a }, { ZD_CR20, 0x0c }, { ZD_CR21, 0x0E }, + { ZD_CR23, 0x48 }, /* normal size for cca threshold */ - { CR24, 0x14 }, - /* { CR24, 0x20 }, */ - { CR26, 0x90 }, { CR27, 0x30 }, { CR29, 0x20 }, - { CR31, 0xb2 }, { CR32, 0x43 }, { CR33, 0x28 }, - { CR38, 0x30 }, { CR34, 0x0f }, { CR35, 0xF0 }, - { CR41, 0x2a }, { CR46, 0x7F }, { CR47, 0x1E }, - { CR51, 0xc5 }, { CR52, 0xc5 }, { CR53, 0xc5 }, - { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, - { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, - { CR85, 0x00 }, { CR86, 0x10 }, { CR87, 0x2A }, - { CR88, 0x10 }, { CR89, 0x24 }, { CR90, 0x18 }, - /* { CR91, 0x18 }, */ + { ZD_CR24, 0x14 }, + /* { ZD_CR24, 0x20 }, */ + { ZD_CR26, 0x90 }, { ZD_CR27, 0x30 }, { ZD_CR29, 0x20 }, + { ZD_CR31, 0xb2 }, { ZD_CR32, 0x43 }, { ZD_CR33, 0x28 }, + { ZD_CR38, 0x30 }, { ZD_CR34, 0x0f }, { ZD_CR35, 0xF0 }, + { ZD_CR41, 0x2a }, { ZD_CR46, 0x7F }, { ZD_CR47, 0x1E }, + { ZD_CR51, 0xc5 }, { ZD_CR52, 0xc5 }, { ZD_CR53, 0xc5 }, + { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, + { ZD_CR82, 0x00 }, { ZD_CR83, 0x24 }, { ZD_CR84, 0x04 }, + { ZD_CR85, 0x00 }, { ZD_CR86, 0x10 }, { ZD_CR87, 0x2A }, + { ZD_CR88, 0x10 }, { ZD_CR89, 0x24 }, { ZD_CR90, 0x18 }, + /* { ZD_CR91, 0x18 }, */ /* should solve continous CTS frame problems */ - { CR91, 0x00 }, - { CR92, 0x0a }, { CR93, 0x00 }, { CR94, 0x01 }, - { CR95, 0x00 }, { CR96, 0x40 }, { CR97, 0x37 }, - { CR98, 0x05 }, { CR99, 0x28 }, { CR100, 0x00 }, - { CR101, 0x13 }, { CR102, 0x27 }, { CR103, 0x27 }, - { CR104, 0x18 }, { CR105, 0x12 }, + { ZD_CR91, 0x00 }, + { ZD_CR92, 0x0a }, { ZD_CR93, 0x00 }, { ZD_CR94, 0x01 }, + { ZD_CR95, 0x00 }, { ZD_CR96, 0x40 }, { ZD_CR97, 0x37 }, + { ZD_CR98, 0x05 }, { ZD_CR99, 0x28 }, { ZD_CR100, 0x00 }, + { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 }, + { ZD_CR104, 0x18 }, { ZD_CR105, 0x12 }, /* normal size */ - { CR106, 0x1a }, - /* { CR106, 0x22 }, */ - { CR107, 0x24 }, { CR108, 0x0a }, { CR109, 0x13 }, - { CR110, 0x2F }, { CR111, 0x27 }, { CR112, 0x27 }, - { CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x40 }, - { CR116, 0x40 }, { CR117, 0xF0 }, { CR118, 0xF0 }, - { CR119, 0x16 }, + { ZD_CR106, 0x1a }, + /* { ZD_CR106, 0x22 }, */ + { ZD_CR107, 0x24 }, { ZD_CR108, 0x0a }, { ZD_CR109, 0x13 }, + { ZD_CR110, 0x2F }, { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 }, + { ZD_CR113, 0x27 }, { ZD_CR114, 0x27 }, { ZD_CR115, 0x40 }, + { ZD_CR116, 0x40 }, { ZD_CR117, 0xF0 }, { ZD_CR118, 0xF0 }, + { ZD_CR119, 0x16 }, /* no TX continuation */ - { CR122, 0x00 }, - /* { CR122, 0xff }, */ - { CR127, 0x03 }, { CR131, 0x08 }, { CR138, 0x28 }, - { CR148, 0x44 }, { CR150, 0x10 }, { CR169, 0xBB }, - { CR170, 0xBB }, + { ZD_CR122, 0x00 }, + /* { ZD_CR122, 0xff }, */ + { ZD_CR127, 0x03 }, { ZD_CR131, 0x08 }, { ZD_CR138, 0x28 }, + { ZD_CR148, 0x44 }, { ZD_CR150, 0x10 }, { ZD_CR169, 0xBB }, + { ZD_CR170, 0xBB }, }; static const u32 rv[] = { @@ -210,7 +210,7 @@ static int rf2959_init_hw(struct zd_rf *rf) */ 0x294128, /* internal power */ /* 0x28252c, */ /* External control TX power */ - /* CR31_CCK, CR51_6-36M, CR52_48M, CR53_54M */ + /* ZD_CR31_CCK, ZD_CR51_6-36M, ZD_CR52_48M, ZD_CR53_54M */ 0x2c0000, 0x300000, 0x340000, /* REG13(0xD) */ @@ -245,8 +245,8 @@ static int rf2959_set_channel(struct zd_rf *rf, u8 channel) static int rf2959_switch_radio_on(struct zd_rf *rf) { static const struct zd_ioreq16 ioreqs[] = { - { CR10, 0x89 }, - { CR11, 0x00 }, + { ZD_CR10, 0x89 }, + { ZD_CR11, 0x00 }, }; struct zd_chip *chip = zd_rf_to_chip(rf); @@ -256,8 +256,8 @@ static int rf2959_switch_radio_on(struct zd_rf *rf) static int rf2959_switch_radio_off(struct zd_rf *rf) { static const struct zd_ioreq16 ioreqs[] = { - { CR10, 0x15 }, - { CR11, 0x81 }, + { ZD_CR10, 0x15 }, + { ZD_CR11, 0x81 }, }; struct zd_chip *chip = zd_rf_to_chip(rf); diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c index 9e74eb1b67d5..860b0af7dc3e 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c @@ -314,42 +314,44 @@ static int uw2453_init_hw(struct zd_rf *rf) struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { CR10, 0x89 }, { CR15, 0x20 }, - { CR17, 0x28 }, /* 6112 no change */ - { CR23, 0x38 }, { CR24, 0x20 }, { CR26, 0x93 }, - { CR27, 0x15 }, { CR28, 0x3e }, { CR29, 0x00 }, - { CR33, 0x28 }, { CR34, 0x30 }, - { CR35, 0x43 }, /* 6112 3e->43 */ - { CR41, 0x24 }, { CR44, 0x32 }, - { CR46, 0x92 }, /* 6112 96->92 */ - { CR47, 0x1e }, - { CR48, 0x04 }, /* 5602 Roger */ - { CR49, 0xfa }, { CR79, 0x58 }, { CR80, 0x30 }, - { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, - { CR91, 0x00 }, { CR92, 0x0a }, { CR98, 0x8d }, - { CR99, 0x28 }, { CR100, 0x02 }, - { CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */ - { CR102, 0x27 }, - { CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */ - { CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */ - { CR109, 0x13 }, - { CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */ - { CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 }, - { CR114, 0x23 }, /* 6221 27->23 */ - { CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */ - { CR116, 0x24 }, /* 6220 1c->24 */ - { CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */ - { CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */ - { CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */ - { CR120, 0x4f }, - { CR121, 0x1f }, /* 6220 4f->1f */ - { CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad }, - { CR126, 0x6c }, { CR127, 0x03 }, - { CR128, 0x14 }, /* 6302 12->11 */ - { CR129, 0x12 }, /* 6301 10->0f */ - { CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 }, - { CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff }, - { CR253, 0xff }, + { ZD_CR10, 0x89 }, { ZD_CR15, 0x20 }, + { ZD_CR17, 0x28 }, /* 6112 no change */ + { ZD_CR23, 0x38 }, { ZD_CR24, 0x20 }, { ZD_CR26, 0x93 }, + { ZD_CR27, 0x15 }, { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, + { ZD_CR33, 0x28 }, { ZD_CR34, 0x30 }, + { ZD_CR35, 0x43 }, /* 6112 3e->43 */ + { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, + { ZD_CR46, 0x92 }, /* 6112 96->92 */ + { ZD_CR47, 0x1e }, + { ZD_CR48, 0x04 }, /* 5602 Roger */ + { ZD_CR49, 0xfa }, { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, + { ZD_CR81, 0x30 }, { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 }, + { ZD_CR91, 0x00 }, { ZD_CR92, 0x0a }, { ZD_CR98, 0x8d }, + { ZD_CR99, 0x28 }, { ZD_CR100, 0x02 }, + { ZD_CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */ + { ZD_CR102, 0x27 }, + { ZD_CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f + * 6221 1f->1c + */ + { ZD_CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */ + { ZD_CR109, 0x13 }, + { ZD_CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */ + { ZD_CR111, 0x13 }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 }, + { ZD_CR114, 0x23 }, /* 6221 27->23 */ + { ZD_CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */ + { ZD_CR116, 0x24 }, /* 6220 1c->24 */ + { ZD_CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */ + { ZD_CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */ + { ZD_CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */ + { ZD_CR120, 0x4f }, + { ZD_CR121, 0x1f }, /* 6220 4f->1f */ + { ZD_CR122, 0xf0 }, { ZD_CR123, 0x57 }, { ZD_CR125, 0xad }, + { ZD_CR126, 0x6c }, { ZD_CR127, 0x03 }, + { ZD_CR128, 0x14 }, /* 6302 12->11 */ + { ZD_CR129, 0x12 }, /* 6301 10->0f */ + { ZD_CR130, 0x10 }, { ZD_CR137, 0x50 }, { ZD_CR138, 0xa8 }, + { ZD_CR144, 0xac }, { ZD_CR146, 0x20 }, { ZD_CR252, 0xff }, + { ZD_CR253, 0xff }, }; static const u32 rv[] = { @@ -433,7 +435,7 @@ static int uw2453_init_hw(struct zd_rf *rf) * the one that produced a lock. */ UW2453_PRIV(rf)->config = found_config + 1; - return zd_iowrite16_locked(chip, 0x06, CR203); + return zd_iowrite16_locked(chip, 0x06, ZD_CR203); } static int uw2453_set_channel(struct zd_rf *rf, u8 channel) @@ -445,8 +447,8 @@ static int uw2453_set_channel(struct zd_rf *rf, u8 channel) struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, - { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, + { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, { ZD_CR79, 0x58 }, + { ZD_CR12, 0xf0 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x58 }, }; r = uw2453_synth_set_channel(chip, channel, autocal); @@ -474,7 +476,7 @@ static int uw2453_set_channel(struct zd_rf *rf, u8 channel) if (r) return r; - return zd_iowrite16_locked(chip, 0x06, CR203); + return zd_iowrite16_locked(chip, 0x06, ZD_CR203); } static int uw2453_switch_radio_on(struct zd_rf *rf) @@ -482,7 +484,7 @@ static int uw2453_switch_radio_on(struct zd_rf *rf) int r; struct zd_chip *chip = zd_rf_to_chip(rf); struct zd_ioreq16 ioreqs[] = { - { CR11, 0x00 }, { CR251, 0x3f }, + { ZD_CR11, 0x00 }, { ZD_CR251, 0x3f }, }; /* enter RXTX mode */ @@ -501,7 +503,7 @@ static int uw2453_switch_radio_off(struct zd_rf *rf) int r; struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x04 }, { CR251, 0x2f }, + { ZD_CR11, 0x04 }, { ZD_CR251, 0x2f }, }; /* enter IDLE mode */ diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 58236e6d0921..c9c1362e9499 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -1877,10 +1877,10 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) dev_dbg_f(zd_usb_dev(usb), "value %#09x bits %d\n", value, bits); - r = zd_usb_ioread16(usb, &bit_value_template, CR203); + r = zd_usb_ioread16(usb, &bit_value_template, ZD_CR203); if (r) { dev_dbg_f(zd_usb_dev(usb), - "error %d: Couldn't read CR203\n", r); + "error %d: Couldn't read ZD_CR203\n", r); return r; } bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA); diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h index b3df2c8116cc..3924258ce177 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.h +++ b/drivers/net/wireless/zd1211rw/zd_usb.h @@ -109,7 +109,7 @@ struct usb_req_rfwrite { __le16 bits; /* RF2595: 24 */ __le16 bit_values[0]; - /* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ + /* (ZD_CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ } __packed; /* USB interrupt */ -- cgit v1.2.3-58-ga151 From ffbd308dce898a857de76d17cc05748505cf4ece Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Sun, 3 Apr 2011 19:05:28 +0530 Subject: mac80211: remove few obsolete flags Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 64d92d5a7f40..865fed4cc18b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -90,20 +90,11 @@ enum rx_mgmt_action { /* no action required */ RX_MGMT_NONE, - /* caller must call cfg80211_send_rx_auth() */ - RX_MGMT_CFG80211_AUTH, - - /* caller must call cfg80211_send_rx_assoc() */ - RX_MGMT_CFG80211_ASSOC, - /* caller must call cfg80211_send_deauth() */ RX_MGMT_CFG80211_DEAUTH, /* caller must call cfg80211_send_disassoc() */ RX_MGMT_CFG80211_DISASSOC, - - /* caller must tell cfg80211 about internal error */ - RX_MGMT_CFG80211_ASSOC_ERROR, }; /* utils */ -- cgit v1.2.3-58-ga151 From a0bbb58bcb70295ff05f870c93d34f9fbe614204 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 4 Apr 2011 11:04:57 +0300 Subject: wl1251: Prepare for idle mode support RFC for WL1251 idle mode support brought a few issues that are worth to update before adding the idle mode support. Since the idle mode can reuse the code that is now used in Power Save Mode (PSM), the flag psm in struct wl1251 is changed to variable station_mode to be able to distinguish between PSM and idle modes. As the station mode is different than the power power save mode command that is sent to chip, the enum wl1251_cmd_ps_mod values are used only when communicating with the chip and new enum wl1251_station_mode values are used inside the driver. Confusing comment about psm and elp relation is removed since the PSM is actually activated by putting the chip into Entreme Low Power (ELP) mode. Signed-off-by: Jarkko Nikula Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl1251/cmd.h | 4 ++-- drivers/net/wireless/wl1251/event.c | 6 ++++-- drivers/net/wireless/wl1251/main.c | 6 +++--- drivers/net/wireless/wl1251/ps.c | 14 ++++++-------- drivers/net/wireless/wl1251/ps.h | 2 +- drivers/net/wireless/wl1251/wl1251.h | 8 ++++++-- 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/wl1251/cmd.h b/drivers/net/wireless/wl1251/cmd.h index e5c74c631374..79ca5273c9e9 100644 --- a/drivers/net/wireless/wl1251/cmd.h +++ b/drivers/net/wireless/wl1251/cmd.h @@ -313,8 +313,8 @@ struct wl1251_cmd_vbm_update { } __packed; enum wl1251_cmd_ps_mode { - STATION_ACTIVE_MODE, - STATION_POWER_SAVE_MODE + CHIP_ACTIVE_MODE, + CHIP_POWER_SAVE_MODE }; struct wl1251_cmd_ps_params { diff --git a/drivers/net/wireless/wl1251/event.c b/drivers/net/wireless/wl1251/event.c index dfc4579acb06..9f15ccaf8f05 100644 --- a/drivers/net/wireless/wl1251/event.c +++ b/drivers/net/wireless/wl1251/event.c @@ -68,14 +68,16 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) if (vector & BSS_LOSE_EVENT_ID) { wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); - if (wl->psm_requested && wl->psm) { + if (wl->psm_requested && + wl->station_mode != STATION_ACTIVE_MODE) { ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); if (ret < 0) return ret; } } - if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && wl->psm) { + if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && + wl->station_mode != STATION_ACTIVE_MODE) { wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT"); /* indicate to the stack, that beacons have been lost */ diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c index 12c9e635a6d6..04a054915dbe 100644 --- a/drivers/net/wireless/wl1251/main.c +++ b/drivers/net/wireless/wl1251/main.c @@ -497,7 +497,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) wl->rx_last_id = 0; wl->next_tx_complete = 0; wl->elp = false; - wl->psm = 0; + wl->station_mode = STATION_ACTIVE_MODE; wl->tx_queue_stopped = false; wl->power_level = WL1251_DEFAULT_POWER_LEVEL; wl->rssi_thold = 0; @@ -632,7 +632,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) wl->psm_requested = false; - if (wl->psm) { + if (wl->station_mode != STATION_ACTIVE_MODE) { ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); if (ret < 0) goto out_sleep; @@ -1384,7 +1384,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void) wl->rx_config = WL1251_DEFAULT_RX_CONFIG; wl->rx_filter = WL1251_DEFAULT_RX_FILTER; wl->elp = false; - wl->psm = 0; + wl->station_mode = STATION_ACTIVE_MODE; wl->psm_requested = false; wl->tx_queue_stopped = false; wl->power_level = WL1251_DEFAULT_POWER_LEVEL; diff --git a/drivers/net/wireless/wl1251/ps.c b/drivers/net/wireless/wl1251/ps.c index 9cc514703d2a..97a5b8c82f01 100644 --- a/drivers/net/wireless/wl1251/ps.c +++ b/drivers/net/wireless/wl1251/ps.c @@ -39,7 +39,7 @@ void wl1251_elp_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (wl->elp || !wl->psm) + if (wl->elp || wl->station_mode == STATION_ACTIVE_MODE) goto out; wl1251_debug(DEBUG_PSM, "chip to elp"); @@ -57,7 +57,7 @@ void wl1251_ps_elp_sleep(struct wl1251 *wl) { unsigned long delay; - if (wl->psm) { + if (wl->station_mode != STATION_ACTIVE_MODE) { delay = msecs_to_jiffies(ELP_ENTRY_DELAY); ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay); } @@ -104,7 +104,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) return 0; } -int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode) +int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode) { int ret; @@ -128,15 +128,13 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode) if (ret < 0) return ret; - ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); + ret = wl1251_cmd_ps_mode(wl, CHIP_POWER_SAVE_MODE); if (ret < 0) return ret; ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP); if (ret < 0) return ret; - - wl->psm = 1; break; case STATION_ACTIVE_MODE: default: @@ -163,13 +161,13 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode) if (ret < 0) return ret; - ret = wl1251_cmd_ps_mode(wl, STATION_ACTIVE_MODE); + ret = wl1251_cmd_ps_mode(wl, CHIP_ACTIVE_MODE); if (ret < 0) return ret; - wl->psm = 0; break; } + wl->station_mode = mode; return ret; } diff --git a/drivers/net/wireless/wl1251/ps.h b/drivers/net/wireless/wl1251/ps.h index 55c3dda75e69..75efad246d67 100644 --- a/drivers/net/wireless/wl1251/ps.h +++ b/drivers/net/wireless/wl1251/ps.h @@ -26,7 +26,7 @@ #include "wl1251.h" #include "acx.h" -int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode); +int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode); void wl1251_ps_elp_sleep(struct wl1251 *wl); int wl1251_ps_elp_wakeup(struct wl1251 *wl); void wl1251_elp_work(struct work_struct *work); diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h index bb23cd522b22..bf245a87e80e 100644 --- a/drivers/net/wireless/wl1251/wl1251.h +++ b/drivers/net/wireless/wl1251/wl1251.h @@ -129,6 +129,11 @@ enum wl1251_partition_type { PART_TABLE_LEN }; +enum wl1251_station_mode { + STATION_ACTIVE_MODE, + STATION_POWER_SAVE_MODE, +}; + struct wl1251_partition { u32 size; u32 start; @@ -358,8 +363,7 @@ struct wl1251 { struct delayed_work elp_work; - /* we can be in psm, but not in elp, we have to differentiate */ - bool psm; + enum wl1251_station_mode station_mode; /* PSM mode requested */ bool psm_requested; -- cgit v1.2.3-58-ga151 From 1e5f52de216a32986a5c3cbc358dbb2620a03047 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 4 Apr 2011 11:04:58 +0300 Subject: wl1251: Add support for idle mode On Nokia N900 the wl1251 consumes the most power when the interface is up but not associated to access point (that supports PSM). In terms of battery current consumption, the consumption is ~180 mA higher when the interface is up but not associated and only ~5 mA higher when associated compared to interface down and driver not loaded cases. This patch adds support for the mac80211 idle notifications. Chip is put into idle very much the same way when entering into PSM by utilizing the Extreme Low Power (ELP) mode. I.e. idle is entered by setting necessary conditions in wl1251_ps_set_mode followed by a call to wl1251_ps_elp_sleep. It seems it is just enough the authorize ELP mode followed by CMD_DISCONNECT (thanks to Kalle Valo about the idea to use it). Without disconnect command the chip remains somewhat active and stays consuming ~20 mA. Idle mode is left by same way than PSM. The wl1251_join call is used to revert the CMD_DISCONNECT. Without it association to AP doesn't work when trying second time. With this patch the interface up but not associated case the battery current consumption is less than 1 mA higher compared to interface down case. Signed-off-by: Jarkko Nikula Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl1251/main.c | 16 ++++++++++++++++ drivers/net/wireless/wl1251/ps.c | 11 +++++++++++ drivers/net/wireless/wl1251/wl1251.h | 1 + 3 files changed, 28 insertions(+) diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c index 04a054915dbe..a14a48c99cdc 100644 --- a/drivers/net/wireless/wl1251/main.c +++ b/drivers/net/wireless/wl1251/main.c @@ -639,6 +639,22 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) } } + if (changed & IEEE80211_CONF_CHANGE_IDLE) { + if (conf->flags & IEEE80211_CONF_IDLE) { + ret = wl1251_ps_set_mode(wl, STATION_IDLE); + if (ret < 0) + goto out_sleep; + } else { + ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); + if (ret < 0) + goto out_sleep; + ret = wl1251_join(wl, wl->bss_type, wl->channel, + wl->beacon_int, wl->dtim_period); + if (ret < 0) + goto out_sleep; + } + } + if (conf->power_level != wl->power_level) { ret = wl1251_acx_tx_power(wl, conf->power_level); if (ret < 0) diff --git a/drivers/net/wireless/wl1251/ps.c b/drivers/net/wireless/wl1251/ps.c index 97a5b8c82f01..db719f7d2692 100644 --- a/drivers/net/wireless/wl1251/ps.c +++ b/drivers/net/wireless/wl1251/ps.c @@ -136,6 +136,17 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode) if (ret < 0) return ret; break; + case STATION_IDLE: + wl1251_debug(DEBUG_PSM, "entering idle"); + + ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP); + if (ret < 0) + return ret; + + ret = wl1251_cmd_template_set(wl, CMD_DISCONNECT, NULL, 0); + if (ret < 0) + return ret; + break; case STATION_ACTIVE_MODE: default: wl1251_debug(DEBUG_PSM, "leaving psm"); diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h index bf245a87e80e..a77f1bbbed0a 100644 --- a/drivers/net/wireless/wl1251/wl1251.h +++ b/drivers/net/wireless/wl1251/wl1251.h @@ -132,6 +132,7 @@ enum wl1251_partition_type { enum wl1251_station_mode { STATION_ACTIVE_MODE, STATION_POWER_SAVE_MODE, + STATION_IDLE, }; struct wl1251_partition { -- cgit v1.2.3-58-ga151 From 59575d1c717815d62f1b5aeac74e5e60a1b27428 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 4 Apr 2011 22:56:16 +0530 Subject: ath9k: deny new interface addtion on IBSS mode The present check denies the IBSS interface addtion if we already have any other vifs. But it fails to deny interface addition if IBSS was already present. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3c5de73dcb4b..88073f4c2b6a 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1479,8 +1479,9 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, } } - if ((vif->type == NL80211_IFTYPE_ADHOC) && - sc->nvifs > 0) { + if ((ah->opmode == NL80211_IFTYPE_ADHOC) || + ((vif->type == NL80211_IFTYPE_ADHOC) && + sc->nvifs > 0)) { ath_err(common, "Cannot create ADHOC interface when other" " interfaces already exist.\n"); ret = -EINVAL; -- cgit v1.2.3-58-ga151 From 66da424177db4f4f2fa7a462db5912655aad966f Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 4 Apr 2011 22:56:17 +0530 Subject: ath9k: Cleanup ath_vif struct Remove unused bssid from ath_vif and set av_bslot on beacon alloc/return. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 -- drivers/net/wireless/ath/ath9k/beacon.c | 1 + drivers/net/wireless/ath/ath9k/main.c | 6 ------ 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index a43f05993687..f3a753096d7d 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -346,9 +346,7 @@ struct ath_vif { int av_bslot; bool is_bslot_active; __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ - enum nl80211_iftype av_opmode; struct ath_buf *av_bcbuf; - u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */ }; /*******************/ diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index f6885278398a..dfd1b98a086b 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -323,6 +323,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) if (avp->av_bslot != -1) { sc->beacon.bslot[avp->av_bslot] = NULL; sc->nbcnvifs--; + avp->av_bslot = -1; } bf = avp->av_bcbuf; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 88073f4c2b6a..6f300d7df88e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1450,7 +1450,6 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); - struct ath_vif *avp = (void *)vif->drv_priv; int ret = 0; mutex_lock(&sc->mutex); @@ -1491,10 +1490,6 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ath_dbg(common, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", vif->type); - /* Set the VIF opmode */ - avp->av_opmode = vif->type; - avp->av_bslot = -1; - sc->nvifs++; ath9k_do_vif_add_setup(hw, vif); @@ -1910,7 +1905,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BSSID) { /* Set BSSID */ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); - memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); common->curaid = 0; ath9k_hw_write_associd(ah); -- cgit v1.2.3-58-ga151 From 4f5ef75b155955bf92adc772c6660787151fc78c Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 4 Apr 2011 22:56:18 +0530 Subject: ath9k: Handle BSSID/AID for multiple interfaces As of now bssid/aid is overridden with recently changed vif's bss config. This may cause improper beacon updation due to bssid/aid mismatch. On station mode, select an associated sta vif as primary vif and configure that vif's bss into hw. Update the primary vif on interface change and bss info change. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 3 +- drivers/net/wireless/ath/ath9k/main.c | 70 +++++++++++++++++++++++++++++----- 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index f3a753096d7d..a972396049e5 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -344,7 +344,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid struct ath_vif { int av_bslot; - bool is_bslot_active; + bool is_bslot_active, primary_sta_vif; __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ struct ath_buf *av_bcbuf; }; @@ -546,6 +546,7 @@ struct ath_ant_comb { #define SC_OP_BT_SCAN BIT(13) #define SC_OP_ANI_RUN BIT(14) #define SC_OP_ENABLE_APM BIT(15) +#define SC_OP_PRIM_STA_VIF BIT(16) /* Powersave flags */ #define PS_WAIT_FOR_BEACON BIT(0) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6f300d7df88e..3181211ae248 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -841,10 +841,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, "Bss Info ASSOC %d, bssid: %pM\n", bss_conf->aid, common->curbssid); - /* New association, store aid */ - common->curaid = bss_conf->aid; - ath9k_hw_write_associd(ah); - /* * Request a re-configuration of Beacon related timers * on the receipt of the first Beacon frame (i.e., @@ -863,7 +859,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, ath_start_ani(common); } else { ath_dbg(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); - common->curaid = 0; /* Stop ANI */ sc->sc_flags &= ~SC_OP_ANI_RUN; del_timer_sync(&common->ani.timer); @@ -1886,6 +1881,66 @@ static int ath9k_set_key(struct ieee80211_hw *hw, return ret; } +static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +{ + struct ath_softc *sc = data; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct ath_vif *avp = (void *)vif->drv_priv; + + switch (sc->sc_ah->opmode) { + case NL80211_IFTYPE_ADHOC: + /* There can be only one vif available */ + memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); + common->curaid = bss_conf->aid; + ath9k_hw_write_associd(sc->sc_ah); + break; + case NL80211_IFTYPE_STATION: + /* + * Skip iteration if primary station vif's bss info + * was not changed + */ + if (sc->sc_flags & SC_OP_PRIM_STA_VIF) + break; + + if (bss_conf->assoc) { + sc->sc_flags |= SC_OP_PRIM_STA_VIF; + avp->primary_sta_vif = true; + memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); + common->curaid = bss_conf->aid; + ath9k_hw_write_associd(sc->sc_ah); + } + break; + default: + break; + } +} + +static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct ath_vif *avp = (void *)vif->drv_priv; + + /* Reconfigure bss info */ + if (avp->primary_sta_vif && !bss_conf->assoc) { + sc->sc_flags &= ~SC_OP_PRIM_STA_VIF; + avp->primary_sta_vif = false; + memset(common->curbssid, 0, ETH_ALEN); + common->curaid = 0; + } + + ieee80211_iterate_active_interfaces_atomic( + sc->hw, ath9k_bss_iter, sc); + + /* + * None of station vifs are associated. + * Clear bssid & aid + */ + if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && + !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) + ath9k_hw_write_associd(sc->sc_ah); +} static void ath9k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -1903,10 +1958,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&sc->mutex); if (changed & BSS_CHANGED_BSSID) { - /* Set BSSID */ - memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); - common->curaid = 0; - ath9k_hw_write_associd(ah); + ath9k_config_bss(sc, vif); /* Set aggregation protection mode parameters */ sc->config.ath_aggr_prot = 0; -- cgit v1.2.3-58-ga151 From 99e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 4 Apr 2011 22:56:19 +0530 Subject: ath9k: configure beacons based on hw opmode Current ath9k code does not handle beacon timers on opmode specific. One such example is that a STA beacon config overwrites already configured AP vif's beacon timers during scan. On multi station vif case, configure beacon timers beased on primary vif selected. This also helps while moving back to single STA vif from multi STA vifs, where the power save is enabled and hw has to be reconfigured with proper beacon and bssid/aid. Otherwise connection poll will be triggered so frequently due to beacon loss. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/beacon.c | 99 +++++++++++++++++++++++++-------- drivers/net/wireless/ath/ath9k/main.c | 84 +++++++++------------------- drivers/net/wireless/ath/ath9k/recv.c | 2 +- 4 files changed, 103 insertions(+), 83 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index a972396049e5..38835bc324b2 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -397,6 +397,7 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif); void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); int ath_beaconq_config(struct ath_softc *sc); +void ath_set_beacon(struct ath_softc *sc); void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); /*******/ diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index dfd1b98a086b..eccb0ec87adb 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -663,22 +663,63 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, ath9k_hw_set_interrupts(ah, ah->imask); } -void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) +static bool ath9k_allow_beacon_config(struct ath_softc *sc, + struct ieee80211_vif *vif) { struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; struct ath_common *common = ath9k_hw_common(sc->sc_ah); - enum nl80211_iftype iftype; + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct ath_vif *avp = (void *)vif->drv_priv; - /* Setup the beacon configuration parameters */ - if (vif) { - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - iftype = vif->type; - cur_conf->beacon_interval = bss_conf->beacon_int; - cur_conf->dtim_period = bss_conf->dtim_period; - } else { - iftype = sc->sc_ah->opmode; + /* + * Can not have different beacon interval on multiple + * AP interface case + */ + if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) && + (sc->nbcnvifs > 1) && + (vif->type == NL80211_IFTYPE_AP) && + (cur_conf->beacon_interval != bss_conf->beacon_int)) { + ath_dbg(common, ATH_DBG_CONFIG, + "Changing beacon interval of multiple \ + AP interfaces !\n"); + return false; + } + /* + * Can not configure station vif's beacon config + * while on AP opmode + */ + if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) && + (vif->type != NL80211_IFTYPE_AP)) { + ath_dbg(common, ATH_DBG_CONFIG, + "STA vif's beacon not allowed on AP mode\n"); + return false; + } + /* + * Do not allow beacon config if HW was already configured + * with another STA vif + */ + if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && + (vif->type == NL80211_IFTYPE_STATION) && + (sc->sc_flags & SC_OP_BEACONS) && + !avp->primary_sta_vif) { + ath_dbg(common, ATH_DBG_CONFIG, + "Beacon already configured for a station interface\n"); + return false; } + return true; +} + +void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) +{ + struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + if (!ath9k_allow_beacon_config(sc, vif)) + return; + + /* Setup the beacon configuration parameters */ + cur_conf->beacon_interval = bss_conf->beacon_int; + cur_conf->dtim_period = bss_conf->dtim_period; cur_conf->listen_interval = 1; cur_conf->dtim_count = 1; cur_conf->bmiss_timeout = @@ -701,6 +742,15 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) if (cur_conf->dtim_period == 0) cur_conf->dtim_period = 1; + ath_set_beacon(sc); + sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; +} + +void ath_set_beacon(struct ath_softc *sc) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; + switch (sc->sc_ah->opmode) { case NL80211_IFTYPE_AP: ath_beacon_config_ap(sc, cur_conf); @@ -728,22 +778,23 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status) int slot; bool found = false; - ath9k_ps_wakeup(sc); - if (status) { - for (slot = 0; slot < ATH_BCBUF; slot++) { - if (sc->beacon.bslot[slot]) { - avp = (void *)sc->beacon.bslot[slot]->drv_priv; - if (avp->is_bslot_active) { - found = true; - break; - } + for (slot = 0; slot < ATH_BCBUF; slot++) { + if (sc->beacon.bslot[slot]) { + avp = (void *)sc->beacon.bslot[slot]->drv_priv; + if (avp->is_bslot_active) { + found = true; + break; } } - if (found) { - /* Re-enable beaconing */ - ah->imask |= ATH9K_INT_SWBA; - ath9k_hw_set_interrupts(ah, ah->imask); - } + } + if (!found) + return; + + ath9k_ps_wakeup(sc); + if (status) { + /* Re-enable beaconing */ + ah->imask |= ATH9K_INT_SWBA; + ath9k_hw_set_interrupts(ah, ah->imask); } else { /* Disable SWBA interrupt */ ah->imask &= ~ATH9K_INT_SWBA; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3181211ae248..ddd5413c8da8 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -299,7 +299,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { if (sc->sc_flags & SC_OP_BEACONS) - ath_beacon_config(sc, NULL); + ath_set_beacon(sc); ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); ath_start_ani(common); @@ -828,43 +828,6 @@ chip_reset: #undef SCHED_INTR } -static void ath9k_bss_assoc_info(struct ath_softc *sc, - struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - - if (bss_conf->assoc) { - ath_dbg(common, ATH_DBG_CONFIG, - "Bss Info ASSOC %d, bssid: %pM\n", - bss_conf->aid, common->curbssid); - - /* - * Request a re-configuration of Beacon related timers - * on the receipt of the first Beacon frame (i.e., - * after time sync with the AP). - */ - sc->ps_flags |= PS_BEACON_SYNC; - - /* Configure the beacon */ - ath_beacon_config(sc, vif); - - /* Reset rssi stats */ - sc->last_rssi = ATH_RSSI_DUMMY_MARKER; - sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; - - sc->sc_flags |= SC_OP_ANI_RUN; - ath_start_ani(common); - } else { - ath_dbg(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); - /* Stop ANI */ - sc->sc_flags &= ~SC_OP_ANI_RUN; - del_timer_sync(&common->ani.timer); - } -} - void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) { struct ath_hw *ah = sc->sc_ah; @@ -894,7 +857,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) goto out; } if (sc->sc_flags & SC_OP_BEACONS) - ath_beacon_config(sc, NULL); /* restart beacons */ + ath_set_beacon(sc); /* restart beacons */ /* Re-Enable interrupts */ ath9k_hw_set_interrupts(ah, ah->imask); @@ -1001,7 +964,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) sc->config.txpowlimit, &sc->curtxpow); if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL))) - ath_beacon_config(sc, NULL); /* restart beacons */ + ath_set_beacon(sc); /* restart beacons */ ath9k_hw_set_interrupts(ah, ah->imask); @@ -1408,9 +1371,6 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, if ((iter_data.naps + iter_data.nadhocs) > 0) { sc->sc_flags |= SC_OP_ANI_RUN; ath_start_ani(common); - } else { - sc->sc_flags &= ~SC_OP_ANI_RUN; - del_timer_sync(&common->ani.timer); } } @@ -1894,6 +1854,9 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); common->curaid = bss_conf->aid; ath9k_hw_write_associd(sc->sc_ah); + /* configure beacon */ + if (bss_conf->enable_beacon) + ath_beacon_config(sc, vif); break; case NL80211_IFTYPE_STATION: /* @@ -1909,6 +1872,16 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); common->curaid = bss_conf->aid; ath9k_hw_write_associd(sc->sc_ah); + ath_dbg(common, ATH_DBG_CONFIG, + "Bss Info ASSOC %d, bssid: %pM\n", + bss_conf->aid, common->curbssid); + ath_beacon_config(sc, vif); + /* Reset rssi stats */ + sc->last_rssi = ATH_RSSI_DUMMY_MARKER; + sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; + + sc->sc_flags |= SC_OP_ANI_RUN; + ath_start_ani(common); } break; default: @@ -1924,7 +1897,10 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) /* Reconfigure bss info */ if (avp->primary_sta_vif && !bss_conf->assoc) { - sc->sc_flags &= ~SC_OP_PRIM_STA_VIF; + ath_dbg(common, ATH_DBG_CONFIG, + "Bss Info DISASSOC %d, bssid %pM\n", + common->curaid, common->curbssid); + sc->sc_flags &= ~(SC_OP_PRIM_STA_VIF | SC_OP_BEACONS); avp->primary_sta_vif = false; memset(common->curbssid, 0, ETH_ALEN); common->curaid = 0; @@ -1938,8 +1914,12 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) * Clear bssid & aid */ if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && - !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) + !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) { ath9k_hw_write_associd(sc->sc_ah); + /* Stop ANI */ + sc->sc_flags &= ~SC_OP_ANI_RUN; + del_timer_sync(&common->ani.timer); + } } static void ath9k_bss_info_changed(struct ieee80211_hw *hw, @@ -1948,7 +1928,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, u32 changed) { struct ath_softc *sc = hw->priv; - struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ath_vif *avp = (void *)vif->drv_priv; @@ -1965,9 +1944,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n", common->curbssid, common->curaid); - - /* need to reconfigure the beacon */ - sc->sc_flags &= ~SC_OP_BEACONS ; } /* Enable transmission of beacons (AP, IBSS, MESH) */ @@ -2008,7 +1984,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_BEACON_INT) { - cur_conf->beacon_interval = bss_conf->beacon_int; /* * In case of AP mode, the HW TSF has to be reset * when the beacon interval changes. @@ -2020,9 +1995,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, if (!error) ath_beacon_config(sc, vif); ath9k_set_beaconing_status(sc, true); - } else { + } else ath_beacon_config(sc, vif); - } } if (changed & BSS_CHANGED_ERP_PREAMBLE) { @@ -2044,12 +2018,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; } - if (changed & BSS_CHANGED_ASSOC) { - ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", - bss_conf->assoc); - ath9k_bss_assoc_info(sc, hw, vif, bss_conf); - } - mutex_unlock(&sc->mutex); } diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index a9c3f4672aa0..3842b7518661 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -574,7 +574,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) sc->ps_flags &= ~PS_BEACON_SYNC; ath_dbg(common, ATH_DBG_PS, "Reconfigure Beacon timers based on timestamp from the AP\n"); - ath_beacon_config(sc, NULL); + ath_set_beacon(sc); } if (ath_beacon_dtim_pending_cab(skb)) { -- cgit v1.2.3-58-ga151 From 0321708748d8f2ecfffa4a9feafb332312e4e57f Mon Sep 17 00:00:00 2001 From: Nishant Sarmukadam Date: Tue, 5 Apr 2011 14:18:09 +0530 Subject: mwl8k: Do not configure tx power unconditionally Instead of configuring tx power unconditionally, check for IEEE80211_CONF_CHANGE_POWER and configure it only when stack sets this flag Signed-off-by: Nishant Sarmukadam Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index ae56d2f32b2e..d5e047970345 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -4463,9 +4463,12 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) conf->power_level = 18; if (priv->ap_fw) { - rc = mwl8k_cmd_tx_power(hw, conf, conf->power_level); - if (rc) - goto out; + + if (conf->flags & IEEE80211_CONF_CHANGE_POWER) { + rc = mwl8k_cmd_tx_power(hw, conf, conf->power_level); + if (rc) + goto out; + } rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x3); if (rc) -- cgit v1.2.3-58-ga151 From cebb28ba1ebb00edee4606547d81acf8db0f0532 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 5 Apr 2011 16:59:06 +0200 Subject: rt2x00: Drop __TIME__ usage The kernel already prints its build timestamp during boot, no need to repeat it in random drivers and produce different object files each time. Signed-off-by: Michal Marek Acked-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Cc: linux-wireless@vger.kernel.org Cc: netdev@vger.kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00debug.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index c92db3264741..66166ef037f5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -568,7 +568,6 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name, blob->data = data; data += sprintf(data, "driver:\t%s\n", intf->rt2x00dev->ops->name); data += sprintf(data, "version:\t%s\n", DRV_VERSION); - data += sprintf(data, "compiled:\t%s %s\n", __DATE__, __TIME__); blob->size = strlen(blob->data); return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob); -- cgit v1.2.3-58-ga151 From 68e022dfeb548b48635888d1392f983977293573 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:41:48 -0700 Subject: iwlagn: remove unused variable Some code was removed, but a variable it used and that is now unused stayed around, kill it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sta.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index b0dcca07ff45..6ded0174a609 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -233,7 +233,6 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_station_entry *station; int i; u8 sta_id = IWL_INVALID_STATION; - u16 rate; if (is_ap) sta_id = ctx->ap_sta_id; -- cgit v1.2.3-58-ga151 From 3240cab3ddfb2637cfca3a078078cdeda44d0a99 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:41:49 -0700 Subject: iwlagn: clean up some 3945/4965 remnants When the driver was split, a bunch of definitions for the 3945 and 4965 devices stayed around, but they're now useless so remove (some of) them. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 28 -- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 2 - drivers/net/wireless/iwlwifi/iwl-commands.h | 591 +--------------------------- drivers/net/wireless/iwlwifi/iwl-core.c | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 235 +++-------- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 185 --------- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 2 - drivers/net/wireless/iwlwifi/iwl-prph.h | 11 - 9 files changed, 63 insertions(+), 994 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 184828c72b31..b356a39a824f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -41,20 +41,6 @@ struct iwl_rate_info { u8 next_rs_tgg; /* next rate used in TGG rs algo */ }; -struct iwl3945_rate_info { - u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ - u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */ - u8 prev_ieee; /* previous rate in IEEE speeds */ - u8 next_ieee; /* next rate in IEEE speeds */ - u8 prev_rs; /* previous rate used in rs algo */ - u8 next_rs; /* next rate used in rs algo */ - u8 prev_rs_tgg; /* previous rate used in TGG rs algo */ - u8 next_rs_tgg; /* next rate used in TGG rs algo */ - u8 table_rs_index; /* index in rate scale table cmd */ - u8 prev_table_rs; /* prev in rate table cmd */ -}; - - /* * These serve as indexes into * struct iwl_rate_info iwl_rates[IWL_RATE_COUNT]; @@ -75,7 +61,6 @@ enum { IWL_RATE_60M_INDEX, IWL_RATE_COUNT, /*FIXME:RS:change to IWL_RATE_INDEX_COUNT,*/ IWL_RATE_COUNT_LEGACY = IWL_RATE_COUNT - 1, /* Excluding 60M */ - IWL_RATE_COUNT_3945 = IWL_RATE_COUNT - 1, IWL_RATE_INVM_INDEX = IWL_RATE_COUNT, IWL_RATE_INVALID = IWL_RATE_COUNT, }; @@ -213,7 +198,6 @@ enum { IWL_CCK_BASIC_RATES_MASK) #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) -#define IWL_RATES_MASK_3945 ((1 << IWL_RATE_COUNT_3945) - 1) #define IWL_INVALID_VALUE -1 @@ -453,19 +437,9 @@ static inline u8 first_antenna(u8 mask) } -/** - * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info - * - * The specific throughput table used is based on the type of network - * the associated with, including A, B, G, and G w/ TGG protection - */ -extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); - /* Initialize station's rate scaling information after adding station */ extern void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id); -extern void iwl3945_rs_rate_init(struct iwl_priv *priv, - struct ieee80211_sta *sta, u8 sta_id); /** * iwl_rate_control_register - Register the rate control algorithm callbacks @@ -478,7 +452,6 @@ extern void iwl3945_rs_rate_init(struct iwl_priv *priv, * */ extern int iwlagn_rate_control_register(void); -extern int iwl3945_rate_control_register(void); /** * iwl_rate_control_unregister - Unregister the rate control callbacks @@ -487,6 +460,5 @@ extern int iwl3945_rate_control_register(void); * the driver is unloaded. */ extern void iwlagn_rate_control_unregister(void); -extern void iwl3945_rate_control_unregister(void); #endif /* __iwl_agn__rs__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 35f085ac336b..3782fe8194fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -474,7 +474,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key)); memset(&priv->stations[sta_id].sta.key, 0, - sizeof(struct iwl4965_keyinfo)); + sizeof(struct iwl_keyinfo)); priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 39313acb9cc7..80de8a1edacf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -66,7 +66,6 @@ #include "iwl-dev.h" /* configuration for the _agn devices */ -extern struct iwl_cfg iwl4965_agn_cfg; extern struct iwl_cfg iwl5300_agn_cfg; extern struct iwl_cfg iwl5100_agn_cfg; extern struct iwl_cfg iwl5350_agn_cfg; @@ -114,7 +113,6 @@ extern struct iwl_hcmd_ops iwlagn_bt_hcmd; extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; extern struct ieee80211_ops iwlagn_hw_ops; -extern struct ieee80211_ops iwl4965_hw_ops; int iwl_reset_ict(struct iwl_priv *priv); void iwl_disable_ict(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index cc2151482f31..e6058436aeb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -103,9 +103,7 @@ enum { REPLY_WEPKEY = 0x20, /* RX, TX, LEDs */ - REPLY_3945_RX = 0x1b, /* 3945 only */ REPLY_TX = 0x1c, - REPLY_RATE_SCALE = 0x47, /* 3945 only */ REPLY_LEDS_CMD = 0x48, REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* for 4965 and up */ @@ -229,7 +227,7 @@ struct iwl_cmd_header { * There is one exception: uCode sets bit 15 when it originates * the response/notification, i.e. when the response/notification * is not a direct response to a command sent by the driver. For - * example, uCode issues REPLY_3945_RX when it sends a received frame + * example, uCode issues REPLY_RX when it sends a received frame * to the driver; it is not a direct response to any driver command. * * The Linux driver uses the following format: @@ -248,36 +246,6 @@ struct iwl_cmd_header { } __packed; -/** - * struct iwl3945_tx_power - * - * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_SCAN_CMD, REPLY_CHANNEL_SWITCH - * - * Each entry contains two values: - * 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained - * linear value that multiplies the output of the digital signal processor, - * before being sent to the analog radio. - * 2) Radio gain. This sets the analog gain of the radio Tx path. - * It is a coarser setting, and behaves in a logarithmic (dB) fashion. - * - * Driver obtains values from struct iwl3945_tx_power power_gain_table[][]. - */ -struct iwl3945_tx_power { - u8 tx_gain; /* gain for analog radio */ - u8 dsp_atten; /* gain for DSP */ -} __packed; - -/** - * struct iwl3945_power_per_rate - * - * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH - */ -struct iwl3945_power_per_rate { - u8 rate; /* plcp */ - struct iwl3945_tx_power tpc; - u8 reserved; -} __packed; - /** * iwlagn rate_n_flags bit fields * @@ -376,30 +344,6 @@ struct iwl3945_power_per_rate { #define IWL_PWR_NUM_HT_OFDM_ENTRIES 24 #define IWL_PWR_CCK_ENTRIES 2 -/** - * union iwl4965_tx_power_dual_stream - * - * Host format used for REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH - * Use __le32 version (struct tx_power_dual_stream) when building command. - * - * Driver provides radio gain and DSP attenuation settings to device in pairs, - * one value for each transmitter chain. The first value is for transmitter A, - * second for transmitter B. - * - * For SISO bit rates, both values in a pair should be identical. - * For MIMO rates, one value may be different from the other, - * in order to balance the Tx output between the two transmitters. - * - * See more details in doc for TXPOWER in iwl-4965-hw.h. - */ -union iwl4965_tx_power_dual_stream { - struct { - u8 radio_tx_gain[2]; - u8 dsp_predis_atten[2]; - } s; - u32 dw; -}; - /** * struct tx_power_dual_stream * @@ -411,15 +355,6 @@ struct tx_power_dual_stream { __le32 dw; } __packed; -/** - * struct iwl4965_tx_power_db - * - * Entire table within REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH - */ -struct iwl4965_tx_power_db { - struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES]; -} __packed; - /** * Command REPLY_TX_POWER_DBM_CMD = 0x98 * struct iwlagn_tx_power_dbm_cmd @@ -724,46 +659,6 @@ enum { * regardless of whether RXON_FILTER_ASSOC_MSK is set. */ -struct iwl3945_rxon_cmd { - u8 node_addr[6]; - __le16 reserved1; - u8 bssid_addr[6]; - __le16 reserved2; - u8 wlap_bssid_addr[6]; - __le16 reserved3; - u8 dev_type; - u8 air_propagation; - __le16 reserved4; - u8 ofdm_basic_rates; - u8 cck_basic_rates; - __le16 assoc_id; - __le32 flags; - __le32 filter_flags; - __le16 channel; - __le16 reserved5; -} __packed; - -struct iwl4965_rxon_cmd { - u8 node_addr[6]; - __le16 reserved1; - u8 bssid_addr[6]; - __le16 reserved2; - u8 wlap_bssid_addr[6]; - __le16 reserved3; - u8 dev_type; - u8 air_propagation; - __le16 rx_chain; - u8 ofdm_basic_rates; - u8 cck_basic_rates; - __le16 assoc_id; - __le32 flags; - __le32 filter_flags; - __le16 channel; - u8 ofdm_ht_single_stream_basic_rates; - u8 ofdm_ht_dual_stream_basic_rates; -} __packed; - -/* 5000 HW just extend this command */ struct iwl_rxon_cmd { u8 node_addr[6]; __le16 reserved1; @@ -791,25 +686,6 @@ struct iwl_rxon_cmd { /* * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response) */ -struct iwl3945_rxon_assoc_cmd { - __le32 flags; - __le32 filter_flags; - u8 ofdm_basic_rates; - u8 cck_basic_rates; - __le16 reserved; -} __packed; - -struct iwl4965_rxon_assoc_cmd { - __le32 flags; - __le32 filter_flags; - u8 ofdm_basic_rates; - u8 cck_basic_rates; - u8 ofdm_ht_single_stream_basic_rates; - u8 ofdm_ht_dual_stream_basic_rates; - __le16 rx_chain_select_flags; - __le16 reserved; -} __packed; - struct iwl5000_rxon_assoc_cmd { __le32 flags; __le32 filter_flags; @@ -845,26 +721,6 @@ struct iwl_rxon_time_cmd { /* * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response) */ -struct iwl3945_channel_switch_cmd { - u8 band; - u8 expect_beacon; - __le16 channel; - __le32 rxon_flags; - __le32 rxon_filter_flags; - __le32 switch_time; - struct iwl3945_power_per_rate power[IWL_MAX_RATES]; -} __packed; - -struct iwl4965_channel_switch_cmd { - u8 band; - u8 expect_beacon; - __le16 channel; - __le32 rxon_flags; - __le32 rxon_filter_flags; - __le32 switch_time; - struct iwl4965_tx_power_db tx_power; -} __packed; - /** * struct iwl5000_channel_switch_cmd * @band: 0- 5.2GHz, 1- 2.4GHz @@ -978,15 +834,10 @@ struct iwl_qosparam_cmd { #define IWL_AP_ID 0 #define IWL_AP_ID_PAN 1 #define IWL_STA_ID 2 -#define IWL3945_BROADCAST_ID 24 -#define IWL3945_STATION_COUNT 25 -#define IWL4965_BROADCAST_ID 31 -#define IWL4965_STATION_COUNT 32 #define IWLAGN_PAN_BCAST_ID 14 #define IWLAGN_BROADCAST_ID 15 #define IWLAGN_STATION_COUNT 16 -#define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/ #define IWL_INVALID_STATION 255 #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) @@ -1034,16 +885,6 @@ struct iwl_qosparam_cmd { * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ #define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) -struct iwl4965_keyinfo { - __le16 key_flags; - u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */ - u8 reserved1; - __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */ - u8 key_offset; - u8 reserved2; - u8 key[16]; /* 16-byte unicast decryption key */ -} __packed; - /* agn */ struct iwl_keyinfo { __le16 key_flags; @@ -1085,7 +926,6 @@ struct sta_id_modify { * with info on security keys, aggregation parameters, and Tx rates for * initial Tx attempt and any retries (agn devices uses * REPLY_TX_LINK_QUALITY_CMD, - * 3945 uses REPLY_RATE_SCALE to set up rate tables). * * REPLY_ADD_STA sets up the table entry for one station, either creating * a new entry, or modifying a pre-existing one. @@ -1105,72 +945,6 @@ struct sta_id_modify { * entries for all STAs in network, starting with index IWL_STA_ID. */ -struct iwl3945_addsta_cmd { - u8 mode; /* 1: modify existing, 0: add new station */ - u8 reserved[3]; - struct sta_id_modify sta; - struct iwl4965_keyinfo key; - __le32 station_flags; /* STA_FLG_* */ - __le32 station_flags_msk; /* STA_FLG_* */ - - /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID) - * corresponding to bit (e.g. bit 5 controls TID 5). - * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ - __le16 tid_disable_tx; - - __le16 rate_n_flags; - - /* TID for which to add block-ack support. - * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ - u8 add_immediate_ba_tid; - - /* TID for which to remove block-ack support. - * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */ - u8 remove_immediate_ba_tid; - - /* Starting Sequence Number for added block-ack support. - * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ - __le16 add_immediate_ba_ssn; -} __packed; - -struct iwl4965_addsta_cmd { - u8 mode; /* 1: modify existing, 0: add new station */ - u8 reserved[3]; - struct sta_id_modify sta; - struct iwl4965_keyinfo key; - __le32 station_flags; /* STA_FLG_* */ - __le32 station_flags_msk; /* STA_FLG_* */ - - /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID) - * corresponding to bit (e.g. bit 5 controls TID 5). - * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ - __le16 tid_disable_tx; - - __le16 reserved1; - - /* TID for which to add block-ack support. - * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ - u8 add_immediate_ba_tid; - - /* TID for which to remove block-ack support. - * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */ - u8 remove_immediate_ba_tid; - - /* Starting Sequence Number for added block-ack support. - * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ - __le16 add_immediate_ba_ssn; - - /* - * Number of packets OK to transmit to station even though - * it is asleep -- used to synchronise PS-poll and u-APSD - * responses while ucode keeps track of STA sleep state. - */ - __le16 sleep_tx_count; - - __le16 reserved2; -} __packed; - -/* agn */ struct iwl_addsta_cmd { u8 mode; /* 1: modify existing, 0: add new station */ u8 reserved[3]; @@ -1339,62 +1113,6 @@ struct iwl_wep_cmd { #define RX_MPDU_RES_STATUS_DEC_DONE_MSK (0x800) -struct iwl3945_rx_frame_stats { - u8 phy_count; - u8 id; - u8 rssi; - u8 agc; - __le16 sig_avg; - __le16 noise_diff; - u8 payload[0]; -} __packed; - -struct iwl3945_rx_frame_hdr { - __le16 channel; - __le16 phy_flags; - u8 reserved1; - u8 rate; - __le16 len; - u8 payload[0]; -} __packed; - -struct iwl3945_rx_frame_end { - __le32 status; - __le64 timestamp; - __le32 beacon_timestamp; -} __packed; - -/* - * REPLY_3945_RX = 0x1b (response only, not a command) - * - * NOTE: DO NOT dereference from casts to this structure - * It is provided only for calculating minimum data set size. - * The actual offsets of the hdr and end are dynamic based on - * stats.phy_count - */ -struct iwl3945_rx_frame { - struct iwl3945_rx_frame_stats stats; - struct iwl3945_rx_frame_hdr hdr; - struct iwl3945_rx_frame_end end; -} __packed; - -#define IWL39_RX_FRAME_SIZE (4 + sizeof(struct iwl3945_rx_frame)) - -/* Fixed (non-configurable) rx data from phy */ - -#define IWL49_RX_RES_PHY_CNT 14 -#define IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET (4) -#define IWL49_RX_PHY_FLAGS_ANTENNAE_MASK (0x70) -#define IWL49_AGC_DB_MASK (0x3f80) /* MASK(7,13) */ -#define IWL49_AGC_DB_POS (7) -struct iwl4965_rx_non_cfg_phy { - __le16 ant_selection; /* ant A bit 4, ant B bit 5, ant C bit 6 */ - __le16 agc_info; /* agc code 0:6, agc dB 7:13, reserved 14:15 */ - u8 rssi_info[6]; /* we use even entries, 0/2/4 for A/B/C rssi */ - u8 pad[0]; -} __packed; - - #define IWLAGN_RX_RES_PHY_CNT 8 #define IWLAGN_RX_RES_AGC_IDX 1 #define IWLAGN_RX_RES_RSSI_AB_IDX 2 @@ -1578,80 +1296,6 @@ struct iwl_rx_mpdu_res_start { * REPLY_TX = 0x1c (command) */ -struct iwl3945_tx_cmd { - /* - * MPDU byte count: - * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size, - * + 8 byte IV for CCM or TKIP (not used for WEP) - * + Data payload - * + 8-byte MIC (not used for CCM/WEP) - * NOTE: Does not include Tx command bytes, post-MAC pad bytes, - * MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i - * Range: 14-2342 bytes. - */ - __le16 len; - - /* - * MPDU or MSDU byte count for next frame. - * Used for fragmentation and bursting, but not 11n aggregation. - * Same as "len", but for next frame. Set to 0 if not applicable. - */ - __le16 next_frame_len; - - __le32 tx_flags; /* TX_CMD_FLG_* */ - - u8 rate; - - /* Index of recipient station in uCode's station table */ - u8 sta_id; - u8 tid_tspec; - u8 sec_ctl; - u8 key[16]; - union { - u8 byte[8]; - __le16 word[4]; - __le32 dw[2]; - } tkip_mic; - __le32 next_frame_info; - union { - __le32 life_time; - __le32 attempt; - } stop_time; - u8 supp_rates[2]; - u8 rts_retry_limit; /*byte 50 */ - u8 data_retry_limit; /*byte 51 */ - union { - __le16 pm_frame_timeout; - __le16 attempt_duration; - } timeout; - - /* - * Duration of EDCA burst Tx Opportunity, in 32-usec units. - * Set this if txop time is not specified by HCCA protocol (e.g. by AP). - */ - __le16 driver_txop; - - /* - * MAC header goes here, followed by 2 bytes padding if MAC header - * length is 26 or 30 bytes, followed by payload data - */ - u8 payload[0]; - struct ieee80211_hdr hdr[0]; -} __packed; - -/* - * REPLY_TX = 0x1c (response) - */ -struct iwl3945_tx_resp { - u8 failure_rts; - u8 failure_frame; - u8 bt_kill_count; - u8 rate; - __le32 wireless_media_time; - __le32 status; /* TX status */ -} __packed; - - /* * 4965 uCode updates these Tx attempt count values in host DRAM. * Used for managing Tx retries when expecting block-acks. @@ -1742,54 +1386,6 @@ struct iwl_tx_cmd { struct ieee80211_hdr hdr[0]; } __packed; -/* TX command response is sent after *3945* transmission attempts. - * - * NOTES: - * - * TX_STATUS_FAIL_NEXT_FRAG - * - * If the fragment flag in the MAC header for the frame being transmitted - * is set and there is insufficient time to transmit the next frame, the - * TX status will be returned with 'TX_STATUS_FAIL_NEXT_FRAG'. - * - * TX_STATUS_FIFO_UNDERRUN - * - * Indicates the host did not provide bytes to the FIFO fast enough while - * a TX was in progress. - * - * TX_STATUS_FAIL_MGMNT_ABORT - * - * This status is only possible if the ABORT ON MGMT RX parameter was - * set to true with the TX command. - * - * If the MSB of the status parameter is set then an abort sequence is - * required. This sequence consists of the host activating the TX Abort - * control line, and then waiting for the TX Abort command response. This - * indicates that a the device is no longer in a transmit state, and that the - * command FIFO has been cleared. The host must then deactivate the TX Abort - * control line. Receiving is still allowed in this case. - */ -enum { - TX_3945_STATUS_SUCCESS = 0x01, - TX_3945_STATUS_DIRECT_DONE = 0x02, - TX_3945_STATUS_FAIL_SHORT_LIMIT = 0x82, - TX_3945_STATUS_FAIL_LONG_LIMIT = 0x83, - TX_3945_STATUS_FAIL_FIFO_UNDERRUN = 0x84, - TX_3945_STATUS_FAIL_MGMNT_ABORT = 0x85, - TX_3945_STATUS_FAIL_NEXT_FRAG = 0x86, - TX_3945_STATUS_FAIL_LIFE_EXPIRE = 0x87, - TX_3945_STATUS_FAIL_DEST_PS = 0x88, - TX_3945_STATUS_FAIL_ABORTED = 0x89, - TX_3945_STATUS_FAIL_BT_RETRY = 0x8a, - TX_3945_STATUS_FAIL_STA_INVALID = 0x8b, - TX_3945_STATUS_FAIL_FRAG_DROPPED = 0x8c, - TX_3945_STATUS_FAIL_TID_DISABLE = 0x8d, - TX_3945_STATUS_FAIL_FRAME_FLUSHED = 0x8e, - TX_3945_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, - TX_3945_STATUS_FAIL_TX_LOCKED = 0x90, - TX_3945_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, -}; - /* * TX command response is sent after *agn* transmission attempts. * @@ -1907,43 +1503,6 @@ struct agg_tx_status { __le16 sequence; } __packed; -struct iwl4965_tx_resp { - u8 frame_count; /* 1 no aggregation, >1 aggregation */ - u8 bt_kill_count; /* # blocked by bluetooth (unused for agg) */ - u8 failure_rts; /* # failures due to unsuccessful RTS */ - u8 failure_frame; /* # failures due to no ACK (unused for agg) */ - - /* For non-agg: Rate at which frame was successful. - * For agg: Rate at which all frames were transmitted. */ - __le32 rate_n_flags; /* RATE_MCS_* */ - - /* For non-agg: RTS + CTS + frame tx attempts time + ACK. - * For agg: RTS + CTS + aggregation tx time + block-ack time. */ - __le16 wireless_media_time; /* uSecs */ - - __le16 reserved; - __le32 pa_power1; /* RF power amplifier measurement (not used) */ - __le32 pa_power2; - - /* - * For non-agg: frame status TX_STATUS_* - * For agg: status of 1st frame, AGG_TX_STATE_*; other frame status - * fields follow this one, up to frame_count. - * Bit fields: - * 11- 0: AGG_TX_STATE_* status code - * 15-12: Retry count for 1st frame in aggregation (retries - * occur if tx failed for this frame when it was a - * member of a previous aggregation block). If rate - * scaling is used, retry count indicates the rate - * table entry used for all frames in the new agg. - * 31-16: Sequence # for this frame's Tx cmd (not SSN!) - */ - union { - __le32 status; - struct agg_tx_status agg_status[0]; /* for each agg frame */ - } u; -} __packed; - /* * definitions for initial rate index field * bits [3:0] initial rate index @@ -2032,52 +1591,8 @@ struct iwl_compressed_ba_resp { /* * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response) * - * See details under "TXPOWER" in iwl-4965-hw.h. */ -struct iwl3945_txpowertable_cmd { - u8 band; /* 0: 5 GHz, 1: 2.4 GHz */ - u8 reserved; - __le16 channel; - struct iwl3945_power_per_rate power[IWL_MAX_RATES]; -} __packed; - -struct iwl4965_txpowertable_cmd { - u8 band; /* 0: 5 GHz, 1: 2.4 GHz */ - u8 reserved; - __le16 channel; - struct iwl4965_tx_power_db tx_power; -} __packed; - - -/** - * struct iwl3945_rate_scaling_cmd - Rate Scaling Command & Response - * - * REPLY_RATE_SCALE = 0x47 (command, has simple generic response) - * - * NOTE: The table of rates passed to the uCode via the - * RATE_SCALE command sets up the corresponding order of - * rates used for all related commands, including rate - * masks, etc. - * - * For example, if you set 9MB (PLCP 0x0f) as the first - * rate in the rate table, the bit mask for that rate - * when passed through ofdm_basic_rates on the REPLY_RXON - * command would be bit 0 (1 << 0) - */ -struct iwl3945_rate_scaling_info { - __le16 rate_n_flags; - u8 try_cnt; - u8 next_rate_index; -} __packed; - -struct iwl3945_rate_scaling_cmd { - u8 table_id; - u8 reserved[3]; - struct iwl3945_rate_scaling_info table[IWL_MAX_RATES]; -} __packed; - - /*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */ #define LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK (1 << 0) @@ -2698,14 +2213,6 @@ struct iwl_spectrum_notification { #define IWL_POWER_BT_SCO_ENA cpu_to_le16(BIT(8)) #define IWL_POWER_ADVANCE_PM_ENA_MSK cpu_to_le16(BIT(9)) -struct iwl3945_powertable_cmd { - __le16 flags; - u8 reserved[2]; - __le32 rx_data_timeout; - __le32 tx_data_timeout; - __le32 sleep_interval[IWL_POWER_VEC_SIZE]; -} __packed; - struct iwl_powertable_cmd { __le16 flags; u8 keep_alive_seconds; /* 3945 reserved */ @@ -2808,25 +2315,6 @@ struct iwl_ct_kill_throttling_config { * active_dwell < max_out_time */ -/* FIXME: rename to AP1, remove tpc */ -struct iwl3945_scan_channel { - /* - * type is defined as: - * 0:0 1 = active, 0 = passive - * 1:4 SSID direct bit map; if a bit is set, then corresponding - * SSID IE is transmitted in probe request. - * 5:7 reserved - */ - u8 type; - u8 channel; /* band is selected by iwl3945_scan_cmd "flags" field */ - struct iwl3945_tx_power tpc; - __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ - __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */ -} __packed; - -/* set number of direct probes u8 type */ -#define IWL39_SCAN_PROBE_MASK(n) ((BIT(n) | (BIT(n) - BIT(1)))) - struct iwl_scan_channel { /* * type is defined as: @@ -2922,50 +2410,6 @@ struct iwl_ssid_ie { * struct iwl_scan_channel. */ -struct iwl3945_scan_cmd { - __le16 len; - u8 reserved0; - u8 channel_count; /* # channels in channel list */ - __le16 quiet_time; /* dwell only this # millisecs on quiet channel - * (only for active scan) */ - __le16 quiet_plcp_th; /* quiet chnl is < this # pkts (typ. 1) */ - __le16 good_CRC_th; /* passive -> active promotion threshold */ - __le16 reserved1; - __le32 max_out_time; /* max usec to be away from associated (service) - * channel */ - __le32 suspend_time; /* pause scan this long (in "extended beacon - * format") when returning to service channel: - * 3945; 31:24 # beacons, 19:0 additional usec, - * 4965; 31:22 # beacons, 21:0 additional usec. - */ - __le32 flags; /* RXON_FLG_* */ - __le32 filter_flags; /* RXON_FILTER_* */ - - /* For active scans (set to all-0s for passive scans). - * Does not include payload. Must specify Tx rate; no rate scaling. */ - struct iwl3945_tx_cmd tx_cmd; - - /* For directed active scans (set to all-0s otherwise) */ - struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_3945]; - - /* - * Probe request frame, followed by channel list. - * - * Size of probe request frame is specified by byte count in tx_cmd. - * Channel list follows immediately after probe request frame. - * Number of channels in list is specified by channel_count. - * Each channel in list is of type: - * - * struct iwl3945_scan_channel channels[0]; - * - * NOTE: Only one band of channels can be scanned per pass. You - * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait - * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION) - * before requesting another scan. - */ - u8 data[0]; -} __packed; - enum iwl_scan_flags { /* BIT(0) currently unused */ IWL_SCAN_FLAGS_ACTION_FRAME_TX = BIT(1), @@ -3092,20 +2536,6 @@ enum iwl_ibss_manager { * BEACON_NOTIFICATION = 0x90 (notification only, not a command) */ -struct iwl3945_beacon_notif { - struct iwl3945_tx_resp beacon_notify_hdr; - __le32 low_tsf; - __le32 high_tsf; - __le32 ibss_mgr_status; -} __packed; - -struct iwl4965_beacon_notif { - struct iwl4965_tx_resp beacon_notify_hdr; - __le32 low_tsf; - __le32 high_tsf; - __le32 ibss_mgr_status; -} __packed; - struct iwlagn_beacon_notif { struct iwlagn_tx_resp beacon_notify_hdr; __le32 low_tsf; @@ -3117,14 +2547,6 @@ struct iwlagn_beacon_notif { * REPLY_TX_BEACON = 0x91 (command, has simple generic response) */ -struct iwl3945_tx_beacon_cmd { - struct iwl3945_tx_cmd tx; - __le16 tim_idx; - u8 tim_size; - u8 reserved1; - struct ieee80211_hdr frame[0]; /* beacon frame */ -} __packed; - struct iwl_tx_beacon_cmd { struct iwl_tx_cmd tx; __le16 tim_idx; @@ -3473,13 +2895,6 @@ struct iwl_statistics_cmd { #define STATISTICS_REPLY_FLG_BAND_24G_MSK cpu_to_le32(0x2) #define STATISTICS_REPLY_FLG_HT40_MODE_MSK cpu_to_le32(0x8) -struct iwl3945_notif_statistics { - __le32 flag; - struct iwl39_statistics_rx rx; - struct iwl39_statistics_tx tx; - struct iwl39_statistics_general general; -} __packed; - struct iwl_notif_statistics { __le32 flag; struct statistics_rx rx; @@ -4453,10 +3868,6 @@ struct iwl_rx_packet { __le32 len_n_flags; struct iwl_cmd_header hdr; union { - struct iwl3945_rx_frame rx_frame; - struct iwl3945_tx_resp tx_resp; - struct iwl3945_beacon_notif beacon_status; - struct iwl_alive_resp alive_frame; struct iwl_spectrum_notification spectrum_notif; struct iwl_csa_notification csa_notif; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 6c30fa652e27..d778f52132cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1430,7 +1430,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, iwl_teardown_interface(priv, vif, false); - memset(priv->bssid, 0, ETH_ALEN); mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 1c9d2dd37cca..8dc209a341aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -26,7 +26,6 @@ /* * Please use this file (iwl-dev.h) for driver implementation definitions. * Please use iwl-commands.h for uCode API definitions. - * Please use iwl-4965-hw.h for hardware-related definitions. */ #ifndef __iwl_dev_h__ @@ -179,53 +178,12 @@ struct iwl_tx_queue { #define IWL_NUM_SCAN_RATES (2) -struct iwl4965_channel_tgd_info { - u8 type; - s8 max_power; -}; - -struct iwl4965_channel_tgh_info { - s64 last_radar_time; -}; - -#define IWL4965_MAX_RATE (33) - -struct iwl3945_clip_group { - /* maximum power level to prevent clipping for each rate, derived by - * us from this band's saturation power in EEPROM */ - const s8 clip_powers[IWL_MAX_RATES]; -}; - -/* current Tx power values to use, one for each rate for each channel. - * requested power is limited by: - * -- regulatory EEPROM limits for this channel - * -- hardware capabilities (clip-powers) - * -- spectrum management - * -- user preference (e.g. iwconfig) - * when requested power is set, base power index must also be set. */ -struct iwl3945_channel_power_info { - struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */ - s8 power_table_index; /* actual (compenst'd) index into gain table */ - s8 base_power_index; /* gain index for power at factory temp. */ - s8 requested_power; /* power (dBm) requested for this chnl/rate */ -}; - -/* current scan Tx power values to use, one for each scan rate for each - * channel. */ -struct iwl3945_scan_power_info { - struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */ - s8 power_table_index; /* actual (compenst'd) index into gain table */ - s8 requested_power; /* scan pwr (dBm) requested for chnl/rate */ -}; - /* * One for each channel, holds all channel setup data * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant * with one another! */ struct iwl_channel_info { - struct iwl4965_channel_tgd_info tgd; - struct iwl4965_channel_tgh_info tgh; struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */ struct iwl_eeprom_channel ht40_eeprom; /* EEPROM regulatory limit for * HT40 channel */ @@ -245,14 +203,6 @@ struct iwl_channel_info { s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ u8 ht40_flags; /* flags copied from EEPROM */ u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ - - /* Radio/DSP gain settings for each "normal" data Tx rate. - * These include, in addition to RF and DSP gain, a few fields for - * remembering/modifying gain settings (indexes). */ - struct iwl3945_channel_power_info power_info[IWL4965_MAX_RATE]; - - /* Radio/DSP gain settings for each scan rate, for directed scans. */ - struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; }; #define IWL_TX_FIFO_BK 0 /* shared */ @@ -501,9 +451,6 @@ struct iwl_station_priv_common { * When mac80211 creates a station it reserves some space (hw->sta_data_size) * in the structure for use by driver. This structure is places in that * space. - * - * The common struct MUST be first because it is shared between - * 3945 and agn! */ struct iwl_station_priv { struct iwl_station_priv_common common; @@ -621,14 +568,6 @@ struct iwl_tlv_ucode_header { u8 data[0]; }; -struct iwl4965_ibss_seq { - u8 mac[ETH_ALEN]; - u16 seq_num; - u16 frag_num; - unsigned long packet_time; - struct list_head list; -}; - struct iwl_sensitivity_ranges { u16 min_nrg_cck; u16 max_nrg_cck; @@ -724,8 +663,6 @@ struct iwl_hw_params { * Naming convention -- * iwl_ <-- Is part of iwlwifi * iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX) - * iwl4965_bg_ <-- Called from work queue context - * iwl4965_mac_ <-- mac80211 callback * ****************************************************************************/ extern void iwl_update_chain_flags(struct iwl_priv *priv); @@ -774,7 +711,6 @@ struct iwl_dma_ptr { /* Sensitivity and chain noise calibration */ #define INITIALIZATION_VALUE 0xFFFF -#define IWL4965_CAL_NUM_BEACONS 20 #define IWL_CAL_NUM_BEACONS 16 #define MAXIMUM_ALLOWED_PATHLOSS 15 @@ -808,24 +744,19 @@ struct iwl_dma_ptr { #define NRG_NUM_PREV_STAT_L 20 #define NUM_RX_CHAINS 3 -enum iwl4965_false_alarm_state { +enum iwlagn_false_alarm_state { IWL_FA_TOO_MANY = 0, IWL_FA_TOO_FEW = 1, IWL_FA_GOOD_RANGE = 2, }; -enum iwl4965_chain_noise_state { +enum iwlagn_chain_noise_state { IWL_CHAIN_NOISE_ALIVE = 0, /* must be 0 */ IWL_CHAIN_NOISE_ACCUMULATE, IWL_CHAIN_NOISE_CALIBRATED, IWL_CHAIN_NOISE_DONE, }; -enum iwl4965_calib_enabled_state { - IWL_CALIB_DISABLED = 0, /* must be 0 */ - IWL_CALIB_ENABLED = 1, -}; - /* * enum iwl_calib @@ -1132,12 +1063,6 @@ struct iwl_force_reset { }; /* extend beacon time format bit shifting */ -/* - * for _3945 devices - * bits 31:24 - extended - * bits 23:0 - interval - */ -#define IWL3945_EXT_BEACON_TIME_POS 24 /* * for _agn devices * bits 31:22 - extended @@ -1391,15 +1316,12 @@ struct iwl_priv { struct iwl_power_mgr power_data; struct iwl_tt_mgmt thermal_throttle; - /* context information */ - u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */ - /* station table variables */ /* Note: if lock and sta_lock are needed, lock must be acquired first */ spinlock_t sta_lock; int num_stations; - struct iwl_station_entry stations[IWL_STATION_COUNT]; + struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; unsigned long ucode_key_table; /* queue refcounts */ @@ -1423,101 +1345,66 @@ struct iwl_priv { /* Last Rx'd beacon timestamp */ u64 timestamp; - union { -#if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE) - struct { - void *shared_virt; - dma_addr_t shared_phys; - - struct delayed_work thermal_periodic; - struct delayed_work rfkill_poll; - - struct iwl3945_notif_statistics statistics; -#ifdef CONFIG_IWLWIFI_DEBUGFS - struct iwl3945_notif_statistics accum_statistics; - struct iwl3945_notif_statistics delta_statistics; - struct iwl3945_notif_statistics max_delta; -#endif - - u32 sta_supp_rates; - int last_rx_rssi; /* From Rx packet statistics */ - - /* Rx'd packet timing information */ - u32 last_beacon_time; - u64 last_tsf; - - /* - * each calibration channel group in the - * EEPROM has a derived clip setting for - * each rate. - */ - const struct iwl3945_clip_group clip_groups[5]; - - } _3945; -#endif -#if defined(CONFIG_IWLAGN) || defined(CONFIG_IWLAGN_MODULE) - struct { - /* INT ICT Table */ - __le32 *ict_tbl; - void *ict_tbl_vir; - dma_addr_t ict_tbl_dma; - dma_addr_t aligned_ict_tbl_dma; - int ict_index; - u32 inta; - bool use_ict; - /* - * reporting the number of tids has AGG on. 0 means - * no AGGREGATION - */ - u8 agg_tids_count; - - struct iwl_rx_phy_res last_phy_res; - bool last_phy_res_valid; - - struct completion firmware_loading_complete; - - u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; - u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; - - /* - * chain noise reset and gain commands are the - * two extra calibration commands follows the standard - * phy calibration commands - */ - u8 phy_calib_chain_noise_reset_cmd; - u8 phy_calib_chain_noise_gain_cmd; - - struct iwl_notif_statistics statistics; - struct iwl_bt_notif_statistics statistics_bt; - /* counts reply_tx error */ - struct reply_tx_error_statistics reply_tx_stats; - struct reply_agg_tx_error_statistics reply_agg_tx_stats; + struct { + /* INT ICT Table */ + __le32 *ict_tbl; + void *ict_tbl_vir; + dma_addr_t ict_tbl_dma; + dma_addr_t aligned_ict_tbl_dma; + int ict_index; + u32 inta; + bool use_ict; + /* + * reporting the number of tids has AGG on. 0 means + * no AGGREGATION + */ + u8 agg_tids_count; + + struct iwl_rx_phy_res last_phy_res; + bool last_phy_res_valid; + + struct completion firmware_loading_complete; + + u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; + u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; + + /* + * chain noise reset and gain commands are the + * two extra calibration commands follows the standard + * phy calibration commands + */ + u8 phy_calib_chain_noise_reset_cmd; + u8 phy_calib_chain_noise_gain_cmd; + + struct iwl_notif_statistics statistics; + struct iwl_bt_notif_statistics statistics_bt; + /* counts reply_tx error */ + struct reply_tx_error_statistics reply_tx_stats; + struct reply_agg_tx_error_statistics reply_agg_tx_stats; #ifdef CONFIG_IWLWIFI_DEBUGFS - struct iwl_notif_statistics accum_statistics; - struct iwl_notif_statistics delta_statistics; - struct iwl_notif_statistics max_delta; - struct iwl_bt_notif_statistics accum_statistics_bt; - struct iwl_bt_notif_statistics delta_statistics_bt; - struct iwl_bt_notif_statistics max_delta_bt; -#endif - - /* notification wait support */ - struct list_head notif_waits; - spinlock_t notif_wait_lock; - wait_queue_head_t notif_waitq; - - /* remain-on-channel offload support */ - struct ieee80211_channel *hw_roc_channel; - struct delayed_work hw_roc_work; - enum nl80211_channel_type hw_roc_chantype; - int hw_roc_duration; - - struct sk_buff *offchan_tx_skb; - int offchan_tx_timeout; - struct ieee80211_channel *offchan_tx_chan; - } _agn; + struct iwl_notif_statistics accum_statistics; + struct iwl_notif_statistics delta_statistics; + struct iwl_notif_statistics max_delta; + struct iwl_bt_notif_statistics accum_statistics_bt; + struct iwl_bt_notif_statistics delta_statistics_bt; + struct iwl_bt_notif_statistics max_delta_bt; #endif - }; + /* notification wait support */ + struct list_head notif_waits; + spinlock_t notif_wait_lock; + wait_queue_head_t notif_waitq; + + /* remain-on-channel offload support */ + struct ieee80211_channel *hw_roc_channel; + struct delayed_work hw_roc_work; + enum nl80211_channel_type hw_roc_chantype; + int hw_roc_duration; + bool hw_roc_setup; + + struct sk_buff *offchan_tx_skb; + int offchan_tx_timeout; + struct ieee80211_channel *offchan_tx_chan; + } _agn; /* bt coex */ u8 bt_enable_flag; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 98aa8af01192..d0f858af30e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -110,10 +110,6 @@ enum { }; /* SKU Capabilities */ -/* 3945 only */ -#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0) -#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) - /* 5000 and up */ #define EEPROM_SKU_CAP_BAND_POS (4) #define EEPROM_SKU_CAP_BAND_SELECTION \ @@ -168,28 +164,6 @@ struct iwl_eeprom_enhanced_txpwr { s8 mimo3_max; } __packed; -/* 3945 Specific */ -#define EEPROM_3945_EEPROM_VERSION (0x2f) - -/* 4965 has two radio transmitters (and 3 radio receivers) */ -#define EEPROM_TX_POWER_TX_CHAINS (2) - -/* 4965 has room for up to 8 sets of txpower calibration data */ -#define EEPROM_TX_POWER_BANDS (8) - -/* 4965 factory calibration measures txpower gain settings for - * each of 3 target output levels */ -#define EEPROM_TX_POWER_MEASUREMENTS (3) - -/* 4965 Specific */ -/* 4965 driver does not work with txpower calibration version < 5 */ -#define EEPROM_4965_TX_POWER_VERSION (5) -#define EEPROM_4965_EEPROM_VERSION (0x2f) -#define EEPROM_4965_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */ -#define EEPROM_4965_CALIB_TXPOWER_OFFSET (2*0xE8) /* 48 bytes */ -#define EEPROM_4965_BOARD_REVISION (2*0x4F) /* 2 bytes */ -#define EEPROM_4965_BOARD_PBA (2*0x56+1) /* 9 bytes */ - /* 5000 Specific */ #define EEPROM_5000_TX_POWER_VERSION (4) #define EEPROM_5000_EEPROM_VERSION (0x11A) @@ -282,90 +256,6 @@ struct iwl_eeprom_enhanced_txpwr { /* 2.4 GHz */ extern const u8 iwl_eeprom_band_1[14]; -/* - * factory calibration data for one txpower level, on one channel, - * measured on one of the 2 tx chains (radio transmitter and associated - * antenna). EEPROM contains: - * - * 1) Temperature (degrees Celsius) of device when measurement was made. - * - * 2) Gain table index used to achieve the target measurement power. - * This refers to the "well-known" gain tables (see iwl-4965-hw.h). - * - * 3) Actual measured output power, in half-dBm ("34" = 17 dBm). - * - * 4) RF power amplifier detector level measurement (not used). - */ -struct iwl_eeprom_calib_measure { - u8 temperature; /* Device temperature (Celsius) */ - u8 gain_idx; /* Index into gain table */ - u8 actual_pow; /* Measured RF output power, half-dBm */ - s8 pa_det; /* Power amp detector level (not used) */ -} __packed; - - -/* - * measurement set for one channel. EEPROM contains: - * - * 1) Channel number measured - * - * 2) Measurements for each of 3 power levels for each of 2 radio transmitters - * (a.k.a. "tx chains") (6 measurements altogether) - */ -struct iwl_eeprom_calib_ch_info { - u8 ch_num; - struct iwl_eeprom_calib_measure - measurements[EEPROM_TX_POWER_TX_CHAINS] - [EEPROM_TX_POWER_MEASUREMENTS]; -} __packed; - -/* - * txpower subband info. - * - * For each frequency subband, EEPROM contains the following: - * - * 1) First and last channels within range of the subband. "0" values - * indicate that this sample set is not being used. - * - * 2) Sample measurement sets for 2 channels close to the range endpoints. - */ -struct iwl_eeprom_calib_subband_info { - u8 ch_from; /* channel number of lowest channel in subband */ - u8 ch_to; /* channel number of highest channel in subband */ - struct iwl_eeprom_calib_ch_info ch1; - struct iwl_eeprom_calib_ch_info ch2; -} __packed; - - -/* - * txpower calibration info. EEPROM contains: - * - * 1) Factory-measured saturation power levels (maximum levels at which - * tx power amplifier can output a signal without too much distortion). - * There is one level for 2.4 GHz band and one for 5 GHz band. These - * values apply to all channels within each of the bands. - * - * 2) Factory-measured power supply voltage level. This is assumed to be - * constant (i.e. same value applies to all channels/bands) while the - * factory measurements are being made. - * - * 3) Up to 8 sets of factory-measured txpower calibration values. - * These are for different frequency ranges, since txpower gain - * characteristics of the analog radio circuitry vary with frequency. - * - * Not all sets need to be filled with data; - * struct iwl_eeprom_calib_subband_info contains range of channels - * (0 if unused) for each set of data. - */ -struct iwl_eeprom_calib_info { - u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */ - u8 saturation_power52; /* half-dBm */ - __le16 voltage; /* signed */ - struct iwl_eeprom_calib_subband_info - band_info[EEPROM_TX_POWER_BANDS]; -} __packed; - - #define ADDRESS_MSK 0x0000FFFF #define INDIRECT_TYPE_MSK 0x000F0000 #define INDIRECT_HOST 0x00010000 @@ -398,83 +288,8 @@ struct iwl_eeprom_calib_info { #define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ #define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ -#define EEPROM_3945_RF_CFG_TYPE_MAX 0x0 -#define EEPROM_4965_RF_CFG_TYPE_MAX 0x1 - -/* Radio Config for 5000 and up */ -#define EEPROM_RF_CONFIG_TYPE_R3x3 0x0 -#define EEPROM_RF_CONFIG_TYPE_R2x2 0x1 -#define EEPROM_RF_CONFIG_TYPE_R1x2 0x2 #define EEPROM_RF_CONFIG_TYPE_MAX 0x3 -/* - * Per-channel regulatory data. - * - * Each channel that *might* be supported by iwl has a fixed location - * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory - * txpower (MSB). - * - * Entries immediately below are for 20 MHz channel width. HT40 (40 MHz) - * channels (only for 4965, not supported by 3945) appear later in the EEPROM. - * - * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 - */ -#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */ -#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */ -#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */ - -/* - * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196, - * 5.0 GHz channels 7, 8, 11, 12, 16 - * (4915-5080MHz) (none of these is ever supported) - */ -#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */ -#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */ - -/* - * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 - * (5170-5320MHz) - */ -#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */ -#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */ - -/* - * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 - * (5500-5700MHz) - */ -#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */ -#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */ - -/* - * 5.7 GHz channels 145, 149, 153, 157, 161, 165 - * (5725-5825MHz) - */ -#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */ -#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */ - -/* - * 2.4 GHz HT40 channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11) - * - * The channel listed is the center of the lower 20 MHz half of the channel. - * The overall center frequency is actually 2 channels (10 MHz) above that, - * and the upper half of each HT40 channel is centered 4 channels (20 MHz) away - * from the lower half; e.g. the upper half of HT40 channel 1 is channel 5, - * and the overall HT40 channel width centers on channel 3. - * - * NOTE: The RXON command uses 20 MHz channel numbers to specify the - * control channel to which to tune. RXON also specifies whether the - * control channel is the upper or lower half of a HT40 channel. - * - * NOTE: 4965 does not support HT40 channels on 2.4 GHz. - */ -#define EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS (2*0xA0) /* 14 bytes */ - -/* - * 5.2 GHz HT40 channels 36 (40), 44 (48), 52 (56), 60 (64), - * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161) - */ -#define EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS (2*0xA8) /* 22 bytes */ - #define EEPROM_REGULATORY_BAND_NO_HT40 (0) struct iwl_eeprom_ops { diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index c71c0a45fa0b..165e7567d8ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -51,9 +51,7 @@ const char *get_cmd_string(u8 cmd) IWL_CMD(REPLY_REMOVE_ALL_STA); IWL_CMD(REPLY_TXFIFO_FLUSH); IWL_CMD(REPLY_WEPKEY); - IWL_CMD(REPLY_3945_RX); IWL_CMD(REPLY_TX); - IWL_CMD(REPLY_RATE_SCALE); IWL_CMD(REPLY_LEDS_CMD); IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); IWL_CMD(COEX_PRIORITY_TABLE_CMD); diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 86f5123bccda..81c464747f59 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -91,7 +91,6 @@ #define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000) #define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000) #define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000) -#define APMG_PS_CTRL_VAL_PWR_SRC_MAX (0x01000000) /* 3945 only */ #define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000) #define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */ #define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060) @@ -234,16 +233,6 @@ #define BSM_SRAM_SIZE (1024) /* bytes */ -/* 3945 Tx scheduler registers */ -#define ALM_SCD_BASE (PRPH_BASE + 0x2E00) -#define ALM_SCD_MODE_REG (ALM_SCD_BASE + 0x000) -#define ALM_SCD_ARASTAT_REG (ALM_SCD_BASE + 0x004) -#define ALM_SCD_TXFACT_REG (ALM_SCD_BASE + 0x010) -#define ALM_SCD_TXF4MF_REG (ALM_SCD_BASE + 0x014) -#define ALM_SCD_TXF5MF_REG (ALM_SCD_BASE + 0x020) -#define ALM_SCD_SBYP_MODE_1_REG (ALM_SCD_BASE + 0x02C) -#define ALM_SCD_SBYP_MODE_2_REG (ALM_SCD_BASE + 0x030) - /** * Tx Scheduler * -- cgit v1.2.3-58-ga151 From 2dedbf58b2edbe940d370845dbf4210f1ddd2b31 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:41:50 -0700 Subject: iwlagn: make mac80211 handlers static Now that these handlers are no longer shared between 4965 and agn, they can be static. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 53 +++++++++++++++++----------------- drivers/net/wireless/iwlwifi/iwl-agn.h | 28 ------------------ 2 files changed, 27 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 42fad62baf76..b701a03e9ebf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2921,7 +2921,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, } -int iwlagn_mac_start(struct ieee80211_hw *hw) +static int iwlagn_mac_start(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; int ret; @@ -2962,7 +2962,7 @@ out: return 0; } -void iwlagn_mac_stop(struct ieee80211_hw *hw) +static void iwlagn_mac_stop(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; @@ -2985,7 +2985,7 @@ void iwlagn_mac_stop(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211(priv, "leave\n"); } -void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct iwl_priv *priv = hw->priv; @@ -3000,11 +3000,11 @@ void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) IWL_DEBUG_MACDUMP(priv, "leave\n"); } -void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_key_conf *keyconf, - struct ieee80211_sta *sta, - u32 iv32, u16 *phase1key) +static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, + u32 iv32, u16 *phase1key) { struct iwl_priv *priv = hw->priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; @@ -3017,9 +3017,10 @@ void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "leave\n"); } -int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) +static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; @@ -3094,11 +3095,11 @@ int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } -int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) +static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size) { struct iwl_priv *priv = hw->priv; int ret = -EINVAL; @@ -3205,9 +3206,9 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, return ret; } -int iwlagn_mac_sta_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct iwl_priv *priv = hw->priv; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; @@ -3248,8 +3249,8 @@ int iwlagn_mac_sta_add(struct ieee80211_hw *hw, return 0; } -void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, - struct ieee80211_channel_switch *ch_switch) +static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_channel_switch *ch_switch) { struct iwl_priv *priv = hw->priv; const struct iwl_channel_info *ch_info; @@ -3346,10 +3347,10 @@ out: IWL_DEBUG_MAC80211(priv, "leave\n"); } -void iwlagn_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) +static void iwlagn_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) { struct iwl_priv *priv = hw->priv; __le32 filter_or = 0, filter_nand = 0; @@ -3396,7 +3397,7 @@ void iwlagn_configure_filter(struct ieee80211_hw *hw, FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; } -void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) +static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) { struct iwl_priv *priv = hw->priv; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 80de8a1edacf..4a0a46e6be3f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -337,32 +337,4 @@ void __releases(wait_entry) iwlagn_remove_notification(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry); -/* mac80211 handlers (for 4965) */ -void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); -int iwlagn_mac_start(struct ieee80211_hw *hw); -void iwlagn_mac_stop(struct ieee80211_hw *hw); -void iwlagn_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast); -int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key); -void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_key_conf *keyconf, - struct ieee80211_sta *sta, - u32 iv32, u16 *phase1key); -int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size); -int iwlagn_mac_sta_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, - struct ieee80211_channel_switch *ch_switch); -void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop); - #endif /* __iwl_agn_h__ */ -- cgit v1.2.3-58-ga151 From 7102762ef0ef330ab0601b6c3bc92bf9be5b1317 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:41:51 -0700 Subject: iwlagn: clean up ucode loading All agn devices behave the same, so there's no need to go through function pointers for any of the ucode loading functionality. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 3 --- drivers/net/wireless/iwlwifi/iwl-2000.c | 3 --- drivers/net/wireless/iwlwifi/iwl-5000.c | 6 ------ drivers/net/wireless/iwlwifi/iwl-6000.c | 6 ------ drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-core.h | 7 +------ 7 files changed, 5 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 2601b552c6fa..ad500631a407 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -185,13 +185,10 @@ static struct iwl_lib_ops iwl1000_lib = { .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, - .load_ucode = iwlagn_load_ucode, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, .dump_fh = iwl_dump_fh, - .init_alive_start = iwlagn_init_alive_start, - .alive_notify = iwlagn_alive_notify, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .apm_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 55274a14af01..5e375d8089c4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -266,13 +266,10 @@ static struct iwl_lib_ops iwl2000_lib = { .setup_deferred_work = iwlagn_bt_setup_deferred_work, .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, - .load_ucode = iwlagn_load_ucode, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, .dump_fh = iwl_dump_fh, - .init_alive_start = iwlagn_init_alive_start, - .alive_notify = iwlagn_alive_notify, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl2030_hw_channel_switch, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 8cab3571047d..0e1f0b50f8e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -358,9 +358,6 @@ static struct iwl_lib_ops iwl5000_lib = { .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, .dump_fh = iwl_dump_fh, - .load_ucode = iwlagn_load_ucode, - .init_alive_start = iwlagn_init_alive_start, - .alive_notify = iwlagn_alive_notify, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl5000_hw_channel_switch, @@ -423,9 +420,6 @@ static struct iwl_lib_ops iwl5150_lib = { .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, - .load_ucode = iwlagn_load_ucode, - .init_alive_start = iwlagn_init_alive_start, - .alive_notify = iwlagn_alive_notify, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl5000_hw_channel_switch, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 7ecfbbc9457a..4d545e62e5c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -294,13 +294,10 @@ static struct iwl_lib_ops iwl6000_lib = { .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, - .load_ucode = iwlagn_load_ucode, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, .dump_fh = iwl_dump_fh, - .init_alive_start = iwlagn_init_alive_start, - .alive_notify = iwlagn_alive_notify, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl6000_hw_channel_switch, @@ -362,13 +359,10 @@ static struct iwl_lib_ops iwl6030_lib = { .setup_deferred_work = iwlagn_bt_setup_deferred_work, .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, - .load_ucode = iwlagn_load_ucode, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, .dump_fh = iwl_dump_fh, - .init_alive_start = iwlagn_init_alive_start, - .alive_notify = iwlagn_alive_notify, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl6000_hw_channel_switch, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index d807e5e2b718..5d35e3504516 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -318,7 +318,7 @@ void iwlagn_init_alive_start(struct iwl_priv *priv) goto restart; } - ret = priv->cfg->ops->lib->alive_notify(priv); + ret = iwlagn_alive_notify(priv); if (ret) { IWL_WARN(priv, "Could not complete ALIVE transition: %d\n", ret); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b701a03e9ebf..c8cd33387a59 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2248,7 +2248,7 @@ static void iwl_alive_start(struct iwl_priv *priv) goto restart; } - ret = priv->cfg->ops->lib->alive_notify(priv); + ret = iwlagn_alive_notify(priv); if (ret) { IWL_WARN(priv, "Could not complete ALIVE transition [ntf]: %d\n", ret); @@ -2581,7 +2581,7 @@ static int __iwl_up(struct iwl_priv *priv) /* load bootstrap state machine, * load bootstrap program into processor's memory, * prepare to load the "initialize" uCode */ - ret = priv->cfg->ops->lib->load_ucode(priv); + ret = iwlagn_load_ucode(priv); if (ret) { IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n", @@ -2626,7 +2626,7 @@ static void iwl_bg_init_alive_start(struct work_struct *data) return; } - priv->cfg->ops->lib->init_alive_start(priv); + iwlagn_init_alive_start(priv); mutex_unlock(&priv->mutex); } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 967b4c008bc0..46c90b3cc30a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -177,14 +177,9 @@ struct iwl_lib_ops { void (*setup_deferred_work)(struct iwl_priv *priv); /* cancel deferred work */ void (*cancel_deferred_work)(struct iwl_priv *priv); - /* alive notification after init uCode load */ - void (*init_alive_start)(struct iwl_priv *priv); - /* alive notification */ - int (*alive_notify)(struct iwl_priv *priv); /* check validity of rtc data address */ int (*is_valid_rtc_data_addr)(u32 addr); - /* 1st ucode load */ - int (*load_ucode)(struct iwl_priv *priv); + int (*dump_nic_event_log)(struct iwl_priv *priv, bool full_log, char **buf, bool display); void (*dump_nic_error_log)(struct iwl_priv *priv); -- cgit v1.2.3-58-ga151 From 4de10b188070b1b96743b1b912843af729ebe50f Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 5 Apr 2011 09:41:52 -0700 Subject: iwlagn: remove more 3945/4965 related defines After driver split, remove unused #defines Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-prph.h | 327 -------------------------------- 1 file changed, 327 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 81c464747f59..448b0eab54ac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -97,142 +97,6 @@ #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) -/** - * BSM (Bootstrap State Machine) - * - * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program - * in special SRAM that does not power down when the embedded control - * processor is sleeping (e.g. for periodic power-saving shutdowns of radio). - * - * When powering back up after sleeps (or during initial uCode load), the BSM - * internally loads the short bootstrap program from the special SRAM into the - * embedded processor's instruction SRAM, and starts the processor so it runs - * the bootstrap program. - * - * This bootstrap program loads (via PCI busmaster DMA) instructions and data - * images for a uCode program from host DRAM locations. The host driver - * indicates DRAM locations and sizes for instruction and data images via the - * four BSM_DRAM_* registers. Once the bootstrap program loads the new program, - * the new program starts automatically. - * - * The uCode used for open-source drivers includes two programs: - * - * 1) Initialization -- performs hardware calibration and sets up some - * internal data, then notifies host via "initialize alive" notification - * (struct iwl_init_alive_resp) that it has completed all of its work. - * After signal from host, it then loads and starts the runtime program. - * The initialization program must be used when initially setting up the - * NIC after loading the driver. - * - * 2) Runtime/Protocol -- performs all normal runtime operations. This - * notifies host via "alive" notification (struct iwl_alive_resp) that it - * is ready to be used. - * - * When initializing the NIC, the host driver does the following procedure: - * - * 1) Load bootstrap program (instructions only, no data image for bootstrap) - * into bootstrap memory. Use dword writes starting at BSM_SRAM_LOWER_BOUND - * - * 2) Point (via BSM_DRAM_*) to the "initialize" uCode data and instruction - * images in host DRAM. - * - * 3) Set up BSM to copy from BSM SRAM into uCode instruction SRAM when asked: - * BSM_WR_MEM_SRC_REG = 0 - * BSM_WR_MEM_DST_REG = RTC_INST_LOWER_BOUND - * BSM_WR_MEM_DWCOUNT_REG = # dwords in bootstrap instruction image - * - * 4) Load bootstrap into instruction SRAM: - * BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START - * - * 5) Wait for load completion: - * Poll BSM_WR_CTRL_REG for BSM_WR_CTRL_REG_BIT_START = 0 - * - * 6) Enable future boot loads whenever NIC's power management triggers it: - * BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START_EN - * - * 7) Start the NIC by removing all reset bits: - * CSR_RESET = 0 - * - * The bootstrap uCode (already in instruction SRAM) loads initialization - * uCode. Initialization uCode performs data initialization, sends - * "initialize alive" notification to host, and waits for a signal from - * host to load runtime code. - * - * 4) Point (via BSM_DRAM_*) to the "runtime" uCode data and instruction - * images in host DRAM. The last register loaded must be the instruction - * byte count register ("1" in MSbit tells initialization uCode to load - * the runtime uCode): - * BSM_DRAM_INST_BYTECOUNT_REG = byte count | BSM_DRAM_INST_LOAD - * - * 5) Wait for "alive" notification, then issue normal runtime commands. - * - * Data caching during power-downs: - * - * Just before the embedded controller powers down (e.g for automatic - * power-saving modes, or for RFKILL), uCode stores (via PCI busmaster DMA) - * a current snapshot of the embedded processor's data SRAM into host DRAM. - * This caches the data while the embedded processor's memory is powered down. - * Location and size are controlled by BSM_DRAM_DATA_* registers. - * - * NOTE: Instruction SRAM does not need to be saved, since that doesn't - * change during operation; the original image (from uCode distribution - * file) can be used for reload. - * - * When powering back up, the BSM loads the bootstrap program. Bootstrap looks - * at the BSM_DRAM_* registers, which now point to the runtime instruction - * image and the cached (modified) runtime data (*not* the initialization - * uCode). Bootstrap reloads these runtime images into SRAM, and restarts the - * uCode from where it left off before the power-down. - * - * NOTE: Initialization uCode does *not* run as part of the save/restore - * procedure. - * - * This save/restore method is mostly for autonomous power management during - * normal operation (result of POWER_TABLE_CMD). Platform suspend/resume and - * RFKILL should use complete restarts (with total re-initialization) of uCode, - * allowing total shutdown (including BSM memory). - * - * Note that, during normal operation, the host DRAM that held the initial - * startup data for the runtime code is now being used as a backup data cache - * for modified data! If you need to completely re-initialize the NIC, make - * sure that you use the runtime data image from the uCode distribution file, - * not the modified/saved runtime data. You may want to store a separate - * "clean" runtime data image in DRAM to avoid disk reads of distribution file. - */ - -/* BSM bit fields */ -#define BSM_WR_CTRL_REG_BIT_START (0x80000000) /* start boot load now */ -#define BSM_WR_CTRL_REG_BIT_START_EN (0x40000000) /* enable boot after pwrup*/ -#define BSM_DRAM_INST_LOAD (0x80000000) /* start program load now */ - -/* BSM addresses */ -#define BSM_BASE (PRPH_BASE + 0x3400) -#define BSM_END (PRPH_BASE + 0x3800) - -#define BSM_WR_CTRL_REG (BSM_BASE + 0x000) /* ctl and status */ -#define BSM_WR_MEM_SRC_REG (BSM_BASE + 0x004) /* source in BSM mem */ -#define BSM_WR_MEM_DST_REG (BSM_BASE + 0x008) /* dest in SRAM mem */ -#define BSM_WR_DWCOUNT_REG (BSM_BASE + 0x00C) /* bytes */ -#define BSM_WR_STATUS_REG (BSM_BASE + 0x010) /* bit 0: 1 == done */ - -/* - * Pointers and size regs for bootstrap load and data SRAM save/restore. - * NOTE: 3945 pointers use bits 31:0 of DRAM address. - * 4965 pointers use bits 35:4 of DRAM address. - */ -#define BSM_DRAM_INST_PTR_REG (BSM_BASE + 0x090) -#define BSM_DRAM_INST_BYTECOUNT_REG (BSM_BASE + 0x094) -#define BSM_DRAM_DATA_PTR_REG (BSM_BASE + 0x098) -#define BSM_DRAM_DATA_BYTECOUNT_REG (BSM_BASE + 0x09C) - -/* - * BSM special memory, stays powered on during power-save sleeps. - * Read/write, address range from LOWER_BOUND to (LOWER_BOUND + SIZE -1) - */ -#define BSM_SRAM_LOWER_BOUND (PRPH_BASE + 0x3800) -#define BSM_SRAM_SIZE (1024) /* bytes */ - - /** * Tx Scheduler * @@ -319,201 +183,10 @@ * Max Tx window size is the max number of contiguous TFDs that the scheduler * can keep track of at one time when creating block-ack chains of frames. * Note that "64" matches the number of ack bits in a block-ack packet. - * Driver should use SCD_WIN_SIZE and SCD_FRAME_LIMIT values to initialize - * IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) values. */ #define SCD_WIN_SIZE 64 #define SCD_FRAME_LIMIT 64 -/* SCD registers are internal, must be accessed via HBUS_TARG_PRPH regs */ -#define IWL49_SCD_START_OFFSET 0xa02c00 - -/* - * 4965 tells driver SRAM address for internal scheduler structs via this reg. - * Value is valid only after "Alive" response from uCode. - */ -#define IWL49_SCD_SRAM_BASE_ADDR (IWL49_SCD_START_OFFSET + 0x0) - -/* - * Driver may need to update queue-empty bits after changing queue's - * write and read pointers (indexes) during (re-)initialization (i.e. when - * scheduler is not tracking what's happening). - * Bit fields: - * 31-16: Write mask -- 1: update empty bit, 0: don't change empty bit - * 15-00: Empty state, one for each queue -- 1: empty, 0: non-empty - * NOTE: This register is not used by Linux driver. - */ -#define IWL49_SCD_EMPTY_BITS (IWL49_SCD_START_OFFSET + 0x4) - -/* - * Physical base address of array of byte count (BC) circular buffers (CBs). - * Each Tx queue has a BC CB in host DRAM to support Scheduler-ACK mode. - * This register points to BC CB for queue 0, must be on 1024-byte boundary. - * Others are spaced by 1024 bytes. - * Each BC CB is 2 bytes * (256 + 64) = 740 bytes, followed by 384 bytes pad. - * (Index into a queue's BC CB) = (index into queue's TFD CB) = (SSN & 0xff). - * Bit fields: - * 25-00: Byte Count CB physical address [35:10], must be 1024-byte aligned. - */ -#define IWL49_SCD_DRAM_BASE_ADDR (IWL49_SCD_START_OFFSET + 0x10) - -/* - * Enables any/all Tx DMA/FIFO channels. - * Scheduler generates requests for only the active channels. - * Set this to 0xff to enable all 8 channels (normal usage). - * Bit fields: - * 7- 0: Enable (1), disable (0), one bit for each channel 0-7 - */ -#define IWL49_SCD_TXFACT (IWL49_SCD_START_OFFSET + 0x1c) -/* - * Queue (x) Write Pointers (indexes, really!), one for each Tx queue. - * Initialized and updated by driver as new TFDs are added to queue. - * NOTE: If using Block Ack, index must correspond to frame's - * Start Sequence Number; index = (SSN & 0xff) - * NOTE: Alternative to HBUS_TARG_WRPTR, which is what Linux driver uses? - */ -#define IWL49_SCD_QUEUE_WRPTR(x) (IWL49_SCD_START_OFFSET + 0x24 + (x) * 4) - -/* - * Queue (x) Read Pointers (indexes, really!), one for each Tx queue. - * For FIFO mode, index indicates next frame to transmit. - * For Scheduler-ACK mode, index indicates first frame in Tx window. - * Initialized by driver, updated by scheduler. - */ -#define IWL49_SCD_QUEUE_RDPTR(x) (IWL49_SCD_START_OFFSET + 0x64 + (x) * 4) - -/* - * Select which queues work in chain mode (1) vs. not (0). - * Use chain mode to build chains of aggregated frames. - * Bit fields: - * 31-16: Reserved - * 15-00: Mode, one bit for each queue -- 1: Chain mode, 0: one-at-a-time - * NOTE: If driver sets up queue for chain mode, it should be also set up - * Scheduler-ACK mode as well, via SCD_QUEUE_STATUS_BITS(x). - */ -#define IWL49_SCD_QUEUECHAIN_SEL (IWL49_SCD_START_OFFSET + 0xd0) - -/* - * Select which queues interrupt driver when scheduler increments - * a queue's read pointer (index). - * Bit fields: - * 31-16: Reserved - * 15-00: Interrupt enable, one bit for each queue -- 1: enabled, 0: disabled - * NOTE: This functionality is apparently a no-op; driver relies on interrupts - * from Rx queue to read Tx command responses and update Tx queues. - */ -#define IWL49_SCD_INTERRUPT_MASK (IWL49_SCD_START_OFFSET + 0xe4) - -/* - * Queue search status registers. One for each queue. - * Sets up queue mode and assigns queue to Tx DMA channel. - * Bit fields: - * 19-10: Write mask/enable bits for bits 0-9 - * 9: Driver should init to "0" - * 8: Scheduler-ACK mode (1), non-Scheduler-ACK (i.e. FIFO) mode (0). - * Driver should init to "1" for aggregation mode, or "0" otherwise. - * 7-6: Driver should init to "0" - * 5: Window Size Left; indicates whether scheduler can request - * another TFD, based on window size, etc. Driver should init - * this bit to "1" for aggregation mode, or "0" for non-agg. - * 4-1: Tx FIFO to use (range 0-7). - * 0: Queue is active (1), not active (0). - * Other bits should be written as "0" - * - * NOTE: If enabling Scheduler-ACK mode, chain mode should also be enabled - * via SCD_QUEUECHAIN_SEL. - */ -#define IWL49_SCD_QUEUE_STATUS_BITS(x)\ - (IWL49_SCD_START_OFFSET + 0x104 + (x) * 4) - -/* Bit field positions */ -#define IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE (0) -#define IWL49_SCD_QUEUE_STTS_REG_POS_TXF (1) -#define IWL49_SCD_QUEUE_STTS_REG_POS_WSL (5) -#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK (8) - -/* Write masks */ -#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (10) -#define IWL49_SCD_QUEUE_STTS_REG_MSK (0x0007FC00) - -/** - * 4965 internal SRAM structures for scheduler, shared with driver ... - * - * Driver should clear and initialize the following areas after receiving - * "Alive" response from 4965 uCode, i.e. after initial - * uCode load, or after a uCode load done for error recovery: - * - * SCD_CONTEXT_DATA_OFFSET (size 128 bytes) - * SCD_TX_STTS_BITMAP_OFFSET (size 256 bytes) - * SCD_TRANSLATE_TBL_OFFSET (size 32 bytes) - * - * Driver accesses SRAM via HBUS_TARG_MEM_* registers. - * Driver reads base address of this scheduler area from SCD_SRAM_BASE_ADDR. - * All OFFSET values must be added to this base address. - */ - -/* - * Queue context. One 8-byte entry for each of 16 queues. - * - * Driver should clear this entire area (size 0x80) to 0 after receiving - * "Alive" notification from uCode. Additionally, driver should init - * each queue's entry as follows: - * - * LS Dword bit fields: - * 0-06: Max Tx window size for Scheduler-ACK. Driver should init to 64. - * - * MS Dword bit fields: - * 16-22: Frame limit. Driver should init to 10 (0xa). - * - * Driver should init all other bits to 0. - * - * Init must be done after driver receives "Alive" response from 4965 uCode, - * and when setting up queue for aggregation. - */ -#define IWL49_SCD_CONTEXT_DATA_OFFSET 0x380 -#define IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) \ - (IWL49_SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) - -#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS (0) -#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK (0x0000007F) -#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) -#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) - -/* - * Tx Status Bitmap - * - * Driver should clear this entire area (size 0x100) to 0 after receiving - * "Alive" notification from uCode. Area is used only by device itself; - * no other support (besides clearing) is required from driver. - */ -#define IWL49_SCD_TX_STTS_BITMAP_OFFSET 0x400 - -/* - * RAxTID to queue translation mapping. - * - * When queue is in Scheduler-ACK mode, frames placed in a that queue must be - * for only one combination of receiver address (RA) and traffic ID (TID), i.e. - * one QOS priority level destined for one station (for this wireless link, - * not final destination). The SCD_TRANSLATE_TABLE area provides 16 16-bit - * mappings, one for each of the 16 queues. If queue is not in Scheduler-ACK - * mode, the device ignores the mapping value. - * - * Bit fields, for each 16-bit map: - * 15-9: Reserved, set to 0 - * 8-4: Index into device's station table for recipient station - * 3-0: Traffic ID (tid), range 0-15 - * - * Driver should clear this entire area (size 32 bytes) to 0 after receiving - * "Alive" notification from uCode. To update a 16-bit map value, driver - * must read a dword-aligned value from device SRAM, replace the 16-bit map - * value of interest, and write the dword value back into device SRAM. - */ -#define IWL49_SCD_TRANSLATE_TBL_OFFSET 0x500 - -/* Find translation table dword to read/write for given queue */ -#define IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ - ((IWL49_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffffffc) - #define IWL_SCD_TXFIFO_POS_TID (0) #define IWL_SCD_TXFIFO_POS_RA (4) #define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF) -- cgit v1.2.3-58-ga151 From 08960dea6c736280a03cb947f445fdb94fdaa2ee Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:41:53 -0700 Subject: iwlagn: remove pointless return variables A number of places just use a variable to return it right away, which is useless, so let's remove the variables there. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 9 ++------- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 4 +--- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 7 ++----- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index e394e49228ba..97abc10f4f22 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2771,16 +2771,13 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, gfp_t gfp) { - struct iwl_lq_sta *lq_sta; struct iwl_station_priv *sta_priv = (struct iwl_station_priv *) sta->drv_priv; struct iwl_priv *priv; priv = (struct iwl_priv *)priv_rate; IWL_DEBUG_RATE(priv, "create station rate scale window\n"); - lq_sta = &sta_priv->lq_sta; - - return lq_sta; + return &sta_priv->lq_sta; } /* @@ -3259,7 +3256,6 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, { char buff[120]; int desc = 0; - ssize_t ret; struct iwl_lq_sta *lq_sta = file->private_data; struct iwl_priv *priv; @@ -3276,8 +3272,7 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, "Bit Rate= %d Mb/s\n", iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); - ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); - return ret; + return simple_read_from_buffer(user_buf, count, ppos, buff, desc); } static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 5d35e3504516..bb262a60e816 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -653,7 +653,5 @@ int iwl_verify_ucode(struct iwl_priv *priv) * Selection of bootstrap image (vs. other images) is arbitrary. */ image = (__le32 *)priv->ucode_boot.v_addr; len = priv->ucode_boot.len; - ret = iwl_verify_inst_full(priv, image, len); - - return ret; + return iwl_verify_inst_full(priv, image, len); } diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 8842411f1cf3..90f2b6464bc1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1572,12 +1572,10 @@ static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, int pos = 0; char buf[200]; const size_t bufsz = sizeof(buf); - ssize_t ret; if (!priv->bt_enable_flag) { pos += scnprintf(buf + pos, bufsz - pos, "BT coex disabled\n"); - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } pos += scnprintf(buf + pos, bufsz - pos, "BT enable flag: 0x%x\n", priv->bt_enable_flag); @@ -1608,8 +1606,7 @@ static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, break; } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } static ssize_t iwl_dbgfs_protection_mode_read(struct file *file, -- cgit v1.2.3-58-ga151 From 36127db02ec17828c1582bb6bc1f12160fd35d64 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 5 Apr 2011 09:41:54 -0700 Subject: iwlagn: return send calibration result In alive notification call, return the status from iwl_send_calib_results() Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index bb262a60e816..127c842fea55 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -530,9 +530,7 @@ int iwlagn_alive_notify(struct iwl_priv *priv) iwlagn_send_wimax_coex(priv); iwlagn_set_Xtal_calib(priv); - iwl_send_calib_results(priv); - - return 0; + return iwl_send_calib_results(priv); } -- cgit v1.2.3-58-ga151 From fb66216f9ebb146ad457829fcb62ae8f4348cda2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:41:55 -0700 Subject: iwlagn: simplify ucode check code The code in iwlcore_verify_inst_sparse really doesn't need to keep track of the number of errors it encountered since a single one is fatal. Also, the code in iwl_verify_inst_full is just used to print out some things, so rename it to iwl_print_inst and don't give it a return code and just make it print out the values. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 51 ++++++++++------------------ 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 127c842fea55..2205b6035207 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -542,8 +542,6 @@ int iwlagn_alive_notify(struct iwl_priv *priv) static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) { u32 val; - int ret = 0; - u32 errcnt = 0; u32 i; IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); @@ -555,56 +553,39 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, i + IWLAGN_RTC_INST_LOWER_BOUND); val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); - if (val != le32_to_cpu(*image)) { - ret = -EIO; - errcnt++; - if (errcnt >= 3) - break; - } + if (val != le32_to_cpu(*image)) + return -EIO; } - return ret; + return 0; } -/** - * iwlcore_verify_inst_full - verify runtime uCode image in card vs. host, - * looking at all data. - */ -static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, - u32 len) +static void iwl_print_mismatch_inst(struct iwl_priv *priv, + __le32 *image, u32 len) { u32 val; - u32 save_len = len; - int ret = 0; - u32 errcnt; + u32 offs; + int errors = 0; IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, IWLAGN_RTC_INST_LOWER_BOUND); - errcnt = 0; - for (; len > 0; len -= sizeof(u32), image++) { + for (offs = 0; + offs < len && errors < 20; + offs += sizeof(u32), image++) { /* read data comes through single port, auto-incr addr */ /* NOTE: Use the debugless read so we don't flood kernel log * if IWL_DL_IO is set */ val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { - IWL_ERR(priv, "uCode INST section is invalid at " - "offset 0x%x, is 0x%x, s/b 0x%x\n", - save_len - len, val, le32_to_cpu(*image)); - ret = -EIO; - errcnt++; - if (errcnt >= 20) - break; + IWL_ERR(priv, "uCode INST section at " + "offset 0x%x, is 0x%x, s/b 0x%x\n", + offs, val, le32_to_cpu(*image)); + errors++; } } - - if (!errcnt) - IWL_DEBUG_INFO(priv, - "ucode image in INSTRUCTION memory is good\n"); - - return ret; } /** @@ -651,5 +632,7 @@ int iwl_verify_ucode(struct iwl_priv *priv) * Selection of bootstrap image (vs. other images) is arbitrary. */ image = (__le32 *)priv->ucode_boot.v_addr; len = priv->ucode_boot.len; - return iwl_verify_inst_full(priv, image, len); + iwl_print_mismatch_inst(priv, image, len); + + return -EIO; } -- cgit v1.2.3-58-ga151 From 35b1d92dfb361d24664381a0e4ae8ed47c771a66 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:41:56 -0700 Subject: iwlagn: verify specific ucode When we loaded a ucode, there's no point in checking any one that is present, we know which one is supposed to be present so also verify that it is exactly the right one. That also simplifies the code and makes it faster since it doesn't have to check all. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 51 +++++++--------------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 2 +- 3 files changed, 14 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 2205b6035207..c7b9b8377efe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -311,7 +311,7 @@ void iwlagn_init_alive_start(struct iwl_priv *priv) /* initialize uCode was loaded... verify inst image. * This is a paranoid check, because we would not have gotten the * "initialize" alive if code weren't properly loaded. */ - if (iwl_verify_ucode(priv)) { + if (iwl_verify_ucode(priv, &priv->ucode_init)) { /* Runtime instruction load was bad; * take it all the way back down so we can try again */ IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); @@ -539,8 +539,11 @@ int iwlagn_alive_notify(struct iwl_priv *priv) * using sample data 100 bytes apart. If these sample points are good, * it's a pretty good bet that everything between them is good, too. */ -static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) +static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, + struct fw_desc *fw_desc) { + __le32 *image = (__le32 *)fw_desc->v_addr; + u32 len = fw_desc->len; u32 val; u32 i; @@ -561,8 +564,10 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 } static void iwl_print_mismatch_inst(struct iwl_priv *priv, - __le32 *image, u32 len) + struct fw_desc *fw_desc) { + __le32 *image = (__le32 *)fw_desc->v_addr; + u32 len = fw_desc->len; u32 val; u32 offs; int errors = 0; @@ -592,47 +597,15 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, * iwl_verify_ucode - determine which instruction image is in SRAM, * and verify its contents */ -int iwl_verify_ucode(struct iwl_priv *priv) +int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc) { - __le32 *image; - u32 len; - int ret; - - /* Try bootstrap */ - image = (__le32 *)priv->ucode_boot.v_addr; - len = priv->ucode_boot.len; - ret = iwlcore_verify_inst_sparse(priv, image, len); - if (!ret) { + if (!iwlcore_verify_inst_sparse(priv, fw_desc)) { IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); return 0; } - /* Try initialize */ - image = (__le32 *)priv->ucode_init.v_addr; - len = priv->ucode_init.len; - ret = iwlcore_verify_inst_sparse(priv, image, len); - if (!ret) { - IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); - return 0; - } - - /* Try runtime/protocol */ - image = (__le32 *)priv->ucode_code.v_addr; - len = priv->ucode_code.len; - ret = iwlcore_verify_inst_sparse(priv, image, len); - if (!ret) { - IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); - return 0; - } - - IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); - - /* Since nothing seems to match, show first several data entries in - * instruction SRAM, so maybe visual inspection will give a clue. - * Selection of bootstrap image (vs. other images) is arbitrary. */ - image = (__le32 *)priv->ucode_boot.v_addr; - len = priv->ucode_boot.len; - iwl_print_mismatch_inst(priv, image, len); + IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); + iwl_print_mismatch_inst(priv, fw_desc); return -EIO; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c8cd33387a59..c66fcea4737b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2241,7 +2241,7 @@ static void iwl_alive_start(struct iwl_priv *priv) /* Initialize uCode has loaded Runtime uCode ... verify inst image. * This is a paranoid check, because we would not have gotten the * "runtime" alive if code weren't properly loaded. */ - if (iwl_verify_ucode(priv)) { + if (iwl_verify_ucode(priv, &priv->ucode_code)) { /* Runtime instruction load was bad; * take it all the way back down so we can try again */ IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 4a0a46e6be3f..d2953bc7beee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -152,7 +152,7 @@ void iwlagn_rx_calib_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwlagn_init_alive_start(struct iwl_priv *priv); int iwlagn_alive_notify(struct iwl_priv *priv); -int iwl_verify_ucode(struct iwl_priv *priv); +int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc); void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); void iwlagn_send_prio_tbl(struct iwl_priv *priv); -- cgit v1.2.3-58-ga151 From 1fc352765fb461e4afafff4d650624df8ab6b6d6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:41:57 -0700 Subject: iwlagn: remove bootstrap code Only 4965 had a bootstrap microcode image, so the agn driver can completely ignore that and we can remove some code from it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 - drivers/net/wireless/iwlwifi/iwl-2000.c | 1 - drivers/net/wireless/iwlwifi/iwl-5000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-6000.c | 1 - drivers/net/wireless/iwlwifi/iwl-agn.c | 36 ++++----------------------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 -- 6 files changed, 4 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index ad500631a407..53a6702f4063 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -141,7 +141,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; - priv->hw_params.max_bsm_size = 0; priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 5e375d8089c4..9f973895ce86 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -147,7 +147,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; - priv->hw_params.max_bsm_size = 0; priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 0e1f0b50f8e8..653bb8ef2950 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -185,7 +185,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; - priv->hw_params.max_bsm_size = 0; priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; @@ -231,7 +230,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; - priv->hw_params.max_bsm_size = 0; priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 4d545e62e5c7..1e55f811431c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -176,7 +176,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; - priv->hw_params.max_bsm_size = 0; priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c66fcea4737b..5e74eb0fd6ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1181,7 +1181,6 @@ static void iwl_dealloc_ucode_pci(struct iwl_priv *priv) iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup); iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init); iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot); } static void iwl_nic_start(struct iwl_priv *priv) @@ -1239,8 +1238,8 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) } struct iwlagn_firmware_pieces { - const void *inst, *data, *init, *init_data, *boot; - size_t inst_size, data_size, init_size, init_data_size, boot_size; + const void *inst, *data, *init, *init_data; + size_t inst_size, data_size, init_size, init_data_size; u32 build; @@ -1271,7 +1270,6 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); - pieces->boot_size = le32_to_cpu(ucode->u.v2.boot_size); src = ucode->u.v2.data; break; case 0: @@ -1287,7 +1285,6 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, pieces->data_size = le32_to_cpu(ucode->u.v1.data_size); pieces->init_size = le32_to_cpu(ucode->u.v1.init_size); pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size); - pieces->boot_size = le32_to_cpu(ucode->u.v1.boot_size); src = ucode->u.v1.data; break; } @@ -1295,7 +1292,7 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, /* Verify size of file vs. image size info in file's header */ if (ucode_raw->size != hdr_size + pieces->inst_size + pieces->data_size + pieces->init_size + - pieces->init_data_size + pieces->boot_size) { + pieces->init_data_size) { IWL_ERR(priv, "uCode file size %d does not match expected size\n", @@ -1311,8 +1308,6 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, src += pieces->init_size; pieces->init_data = src; src += pieces->init_data_size; - pieces->boot = src; - src += pieces->boot_size; return 0; } @@ -1413,8 +1408,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, pieces->init_data_size = tlv_len; break; case IWL_UCODE_TLV_BOOT: - pieces->boot = tlv_data; - pieces->boot_size = tlv_len; + IWL_ERR(priv, "Found unexpected BOOT ucode\n"); break; case IWL_UCODE_TLV_PROBE_MAX_LEN: if (tlv_len != sizeof(u32)) @@ -1614,8 +1608,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) pieces.init_size); IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n", pieces.init_data_size); - IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %Zd\n", - pieces.boot_size); /* Verify that uCode images will fit in card's SRAM */ if (pieces.inst_size > priv->hw_params.max_inst_size) { @@ -1642,12 +1634,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) goto try_again; } - if (pieces.boot_size > priv->hw_params.max_bsm_size) { - IWL_ERR(priv, "uCode boot instr len %Zd too large to fit in\n", - pieces.boot_size); - goto try_again; - } - /* Allocate ucode buffers for card's bus-master loading ... */ /* Runtime instructions and 2 copies of data: @@ -1678,15 +1664,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) goto err_pci_alloc; } - /* Bootstrap (instructions only, no data) */ - if (pieces.boot_size) { - priv->ucode_boot.len = pieces.boot_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); - - if (!priv->ucode_boot.v_addr) - goto err_pci_alloc; - } - /* Now that we can no longer fail, copy information */ /* @@ -1749,11 +1726,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) pieces.init_data_size); } - /* Bootstrap instructions */ - IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", - pieces.boot_size); - memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size); - /* * figure out the offset of chain noise reset and gain commands * base on the size of standard phy calibration commands table size diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 8dc209a341aa..b3af2e8afc0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -641,7 +641,6 @@ struct iwl_hw_params { u8 max_beacon_itrvl; /* in 1024 ms */ u32 max_inst_size; u32 max_data_size; - u32 max_bsm_size; u32 ct_kill_threshold; /* value in hw-dependent units */ u32 ct_kill_exit_threshold; /* value in hw-dependent units */ /* for 1000, 6000 series and up */ @@ -1263,7 +1262,6 @@ struct iwl_priv { struct fw_desc ucode_data_backup; /* runtime data save/restore */ struct fw_desc ucode_init; /* initialization inst */ struct fw_desc ucode_init_data; /* initialization data */ - struct fw_desc ucode_boot; /* bootstrap inst */ enum ucode_type ucode_type; u8 ucode_write_complete; /* the image write is complete */ char firmware_name[25]; -- cgit v1.2.3-58-ga151 From e649437fd6e2bae6f7b8a36a302a1ec4faa5d906 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:41:58 -0700 Subject: iwlagn: centralize and fix ucode restart The ucode restart has to take into account a number of things, like clearing the HCMD_ACTIVE and other status bits, and waking up the wait_command_queue. Currently, however, there are a number of places that neither do that, nor actually set the FW error bit that leads to proper restart handling, which means that in those cases things will probably just hang completely. To clean this up, make all ucode restart go through a single function, except for the cases where it's called during firmware loading. Also fix a bug in wimax coexist restart avoidance, it needs to first clear the status bits (and it has to clear the HCMD_ACTIVE one as well) and then wake up anything waiting on wait_command_queue. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 99 +++++++++++++++++---------------- drivers/net/wireless/iwlwifi/iwl-core.h | 3 + drivers/net/wireless/iwlwifi/iwl-tx.c | 4 +- 3 files changed, 56 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d778f52132cb..64b28b01ad86 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -890,10 +890,8 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv, IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); } #endif -/** - * iwl_irq_handle_error - called for HW or SW error interrupt from card - */ -void iwl_irq_handle_error(struct iwl_priv *priv) + +void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) { unsigned int reload_msec; unsigned long reload_jiffies; @@ -904,18 +902,62 @@ void iwl_irq_handle_error(struct iwl_priv *priv) /* Cancel currently queued command. */ clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + /* Keep the restart process from trying to send host + * commands by clearing the ready bit */ + clear_bit(STATUS_READY, &priv->status); + + wake_up_interruptible(&priv->wait_command_queue); + + if (!ondemand) { + /* + * If firmware keep reloading, then it indicate something + * serious wrong and firmware having problem to recover + * from it. Instead of keep trying which will fill the syslog + * and hang the system, let's just stop it + */ + reload_jiffies = jiffies; + reload_msec = jiffies_to_msecs((long) reload_jiffies - + (long) priv->reload_jiffies); + priv->reload_jiffies = reload_jiffies; + if (reload_msec <= IWL_MIN_RELOAD_DURATION) { + priv->reload_count++; + if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) { + IWL_ERR(priv, "BUG_ON, Stop restarting\n"); + return; + } + } else + priv->reload_count = 0; + } + + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { + if (priv->cfg->mod_params->restart_fw) { + IWL_DEBUG(priv, IWL_DL_FW_ERRORS, + "Restarting adapter due to uCode error.\n"); + queue_work(priv->workqueue, &priv->restart); + } else + IWL_DEBUG(priv, IWL_DL_FW_ERRORS, + "Detected FW error, but not restarting\n"); + } +} + +/** + * iwl_irq_handle_error - called for HW or SW error interrupt from card + */ +void iwl_irq_handle_error(struct iwl_priv *priv) +{ /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ if (priv->cfg->internal_wimax_coex && (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) & APMS_CLK_VAL_MRB_FUNC_MODE) || (iwl_read_prph(priv, APMG_PS_CTRL_REG) & APMG_PS_CTRL_VAL_RESET_REQ))) { - wake_up_interruptible(&priv->wait_command_queue); /* - *Keep the restart process from trying to send host - * commands by clearing the INIT status bit + * Keep the restart process from trying to send host + * commands by clearing the ready bit. */ clear_bit(STATUS_READY, &priv->status); + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + wake_up_interruptible(&priv->wait_command_queue); IWL_ERR(priv, "RF is used by WiMAX\n"); return; } @@ -935,38 +977,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv) &priv->contexts[IWL_RXON_CTX_BSS]); #endif - wake_up_interruptible(&priv->wait_command_queue); - - /* Keep the restart process from trying to send host - * commands by clearing the INIT status bit */ - clear_bit(STATUS_READY, &priv->status); - - /* - * If firmware keep reloading, then it indicate something - * serious wrong and firmware having problem to recover - * from it. Instead of keep trying which will fill the syslog - * and hang the system, let's just stop it - */ - reload_jiffies = jiffies; - reload_msec = jiffies_to_msecs((long) reload_jiffies - - (long) priv->reload_jiffies); - priv->reload_jiffies = reload_jiffies; - if (reload_msec <= IWL_MIN_RELOAD_DURATION) { - priv->reload_count++; - if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) { - IWL_ERR(priv, "BUG_ON, Stop restarting\n"); - return; - } - } else - priv->reload_count = 0; - - if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_DEBUG(priv, IWL_DL_FW_ERRORS, - "Restarting adapter due to uCode error.\n"); - - if (priv->cfg->mod_params->restart_fw) - queue_work(priv->workqueue, &priv->restart); - } + iwlagn_fw_error(priv, false); } static int iwl_apm_stop_master(struct iwl_priv *priv) @@ -1755,15 +1766,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) break; } IWL_ERR(priv, "On demand firmware reload\n"); - /* Set the FW error flag -- cleared on iwl_down */ - set_bit(STATUS_FW_ERROR, &priv->status); - wake_up_interruptible(&priv->wait_command_queue); - /* - * Keep the restart process from trying to send host - * commands by clearing the INIT status bit - */ - clear_bit(STATUS_READY, &priv->status); - queue_work(priv->workqueue, &priv->restart); + iwlagn_fw_error(priv, true); break; } return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 46c90b3cc30a..8bc23468d82c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -729,4 +729,7 @@ static inline bool iwl_bt_statistics(struct iwl_priv *priv) extern bool bt_coex_active; extern bool bt_siso_mode; + +void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand); + #endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 39a4180ee854..fa81df22a103 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -474,7 +474,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) } if (!is_ct_kill) { IWL_ERR(priv, "Restarting adapter due to queue full\n"); - queue_work(priv->workqueue, &priv->restart); + iwlagn_fw_error(priv, false); } return -ENOSPC; } @@ -582,7 +582,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, if (nfreed++ > 0) { IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx, q->write_ptr, q->read_ptr); - queue_work(priv->workqueue, &priv->restart); + iwlagn_fw_error(priv, false); } } -- cgit v1.2.3-58-ga151 From 6009c39c6fc1cb988bdc90a395d9cce273afc7d5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:41:59 -0700 Subject: iwlagn: remove ucode_data_backup This was used only on 4965 in conjunction with the bootstrap ucode. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 19 +------------------ drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5e74eb0fd6ee..e3095afc9554 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1178,7 +1178,6 @@ static void iwl_dealloc_ucode_pci(struct iwl_priv *priv) { iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code); iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup); iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init); iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data); } @@ -1645,11 +1644,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) priv->ucode_data.len = pieces.data_size; iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); - priv->ucode_data_backup.len = pieces.data_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); - - if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || - !priv->ucode_data_backup.v_addr) + if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr) goto err_pci_alloc; /* Initialization instructions and data */ @@ -1709,7 +1704,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", pieces.data_size); memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size); - memcpy(priv->ucode_data_backup.v_addr, pieces.data, pieces.data_size); /* Initialization instructions */ if (pieces.init_size) { @@ -2481,11 +2475,6 @@ static int __iwl_up(struct iwl_priv *priv) return -EIO; } - if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) { - IWL_ERR(priv, "ucode not available for device bringup\n"); - return -EIO; - } - for_each_context(priv, ctx) { ret = iwlagn_alloc_bcast_station(priv, ctx); if (ret) { @@ -2542,12 +2531,6 @@ static int __iwl_up(struct iwl_priv *priv) iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - /* Copy original ucode data image from disk into backup cache. - * This will be used to initialize the on-board processor's - * data SRAM for a clean start when the runtime program first loads. */ - memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr, - priv->ucode_data.len); - for (i = 0; i < MAX_HW_RESTARTS; i++) { /* load bootstrap state machine, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b3af2e8afc0a..7619cee648f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1259,7 +1259,6 @@ struct iwl_priv { iwl_ucode.ver */ struct fw_desc ucode_code; /* runtime inst */ struct fw_desc ucode_data; /* runtime data original */ - struct fw_desc ucode_data_backup; /* runtime data save/restore */ struct fw_desc ucode_init; /* initialization inst */ struct fw_desc ucode_init_data; /* initialization data */ enum ucode_type ucode_type; -- cgit v1.2.3-58-ga151 From 901069c71415a76d731857ccda814e18ded062f7 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 5 Apr 2011 09:42:00 -0700 Subject: iwlagn: change Copyright to 2011 Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-2000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000-hw.h | 4 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-6000-hw.h | 4 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 4 +- drivers/net/wireless/iwlwifi/iwl-agn-calib.h | 4 +- drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c | 52 +++++++++++++------------- drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c | 4 +- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-hw.h | 4 +- drivers/net/wireless/iwlwifi/iwl-agn-ict.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-led.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tt.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 4 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 4 +- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 6 +-- drivers/net/wireless/iwlwifi/iwl-csr.h | 4 +- drivers/net/wireless/iwlwifi/iwl-debug.h | 2 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-devtrace.c | 2 +- drivers/net/wireless/iwlwifi/iwl-devtrace.h | 2 +- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 4 +- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 4 +- drivers/net/wireless/iwlwifi/iwl-fh.h | 4 +- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 2 +- drivers/net/wireless/iwlwifi/iwl-helpers.h | 2 +- drivers/net/wireless/iwlwifi/iwl-io.h | 2 +- drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-led.h | 2 +- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-power.h | 2 +- drivers/net/wireless/iwlwifi/iwl-prph.h | 4 +- drivers/net/wireless/iwlwifi/iwl-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 +- drivers/net/wireless/iwlwifi/iwl-spectrum.h | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.h | 2 +- drivers/net/wireless/iwlwifi/iwl-tx.c | 2 +- 53 files changed, 93 insertions(+), 93 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 53a6702f4063..5c3bb47de3a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 9f973895ce86..f87adbf11349 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 3975e45e7500..05ad47628b63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 653bb8ef2950..d2f4eb3f4b38 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h index 47891e16a758..b27986e57c92 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 1e55f811431c..c1f8d1d2b721 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 9006293e740c..7b761de77b0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h index e37ae7261630..ef4d5079a7ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index b500aaae53ec..d1834aa7edf0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c @@ -1,30 +1,30 @@ /****************************************************************************** -* -* GPL LICENSE SUMMARY -* -* Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of version 2 of the GNU General Public License as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, but -* WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, -* USA -* -* The full GNU General Public License is included in this distribution -* in the file called LICENSE.GPL. -* -* Contact Information: -* Intel Linux Wireless -* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*****************************************************************************/ + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ #include "iwl-agn.h" #include "iwl-agn-debugfs.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h index f2573b5486cd..9a3f329e508f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c index 27b5a3eec9dc..c6dd9b755a05 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 41543ad4cb84..861cc93957a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index a52b82c8e7a6..7bd19f4e66de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c index 47e1fa4bacfd..34d77d22a360 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.c b/drivers/net/wireless/iwlwifi/iwl-agn-led.c index c1190d965614..4bb877e600c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.h b/drivers/net/wireless/iwlwifi/iwl-agn-led.h index 96f323dc5dd6..c0b7611b72c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 3a02bea46328..9a3d69d9b8a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 97abc10f4f22..dbe6295bbf23 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index b356a39a824f..69a29932babc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index dfdbea6e8f99..c335ee6883ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 3782fe8194fd..079275f2c64d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index e3a8216a033c..348f74f1c8e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h index d55060427cac..d118ed29bf3f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index cb8eacd5fdb5..2816b432c62f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index c7b9b8377efe..a7c913119f2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e3095afc9554..2f4fe16d1eea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index d2953bc7beee..016b79e4421e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index e6058436aeb3..a2348ee61fd9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 64b28b01ad86..6e9829fd6c03 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 8bc23468d82c..696b056b070c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -73,7 +73,7 @@ struct iwl_cmd; #define IWLWIFI_VERSION "in-tree:" -#define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" #define DRV_AUTHOR "" #define IWL_PCI_DEVICE(dev, subdev, cfg) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 1123319f2e2b..5ab90ba7a024 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index ebdea3be3ef9..8489431ceb8b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 90f2b6464bc1..92f6efd2c73f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 7619cee648f4..0696e7ff0f37 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index 4a487639d932..a635a7e75447 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2009 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 4cf864c664ee..f00172cb8a6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2009 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index c831a0f24613..f70d87162e59 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index d0f858af30e8..35bf54b38515 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 55b8370bc6d4..da06d136a357 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 165e7567d8ee..9177b553fe57 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 8821f088ba7f..5da5761c74b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 0203a3bbf872..3ddb2fbe12f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index d7f2a0bb32c9..c2862d4e00e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 101eef12b3bb..05b8e8f7dd4a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 576795e2c75b..c43c8e66de73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index fe012032c28c..59635d784e27 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 448b0eab54ac..c960195df989 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 6f9a2fa04763..984a42cfffe9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 3a4d9e6b0421..c517f6d8a15f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/drivers/net/wireless/iwlwifi/iwl-spectrum.h index c4ca0b5d77da..cb80bb4ce45e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.h +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ieee80211 subsystem header files. * diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 6ded0174a609..c21515640077 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 206f1e1a0caf..ff64027ff4cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index fa81df22a103..565980fbb591 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. -- cgit v1.2.3-58-ga151 From 7415952ff789b1c1878119662d4dc011ac9d261e Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 5 Apr 2011 09:42:01 -0700 Subject: iwlagn: check more error return code In alive notify, we should check return code instead of assume everything ok Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index a7c913119f2a..9c5abff6f04a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -432,6 +432,7 @@ int iwlagn_alive_notify(struct iwl_priv *priv) unsigned long flags; int i, chan; u32 reg_val; + int ret; spin_lock_irqsave(&priv->lock, flags); @@ -527,9 +528,14 @@ int iwlagn_alive_notify(struct iwl_priv *priv) iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - iwlagn_send_wimax_coex(priv); + ret = iwlagn_send_wimax_coex(priv); + if (ret) + return ret; + + ret = iwlagn_set_Xtal_calib(priv); + if (ret) + return ret; - iwlagn_set_Xtal_calib(priv); return iwl_send_calib_results(priv); } -- cgit v1.2.3-58-ga151 From 3997ff39faa184a2ff670a6792cdb89ff51cf78f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:42:02 -0700 Subject: iwlagn: add feature flags Some new devices and microcode files will a greater variety of features, so the TLV-per-feature approach we took before will quickly make things harder to manage and increase the file size. Add a new TLV that has feature flags. Currently, it will contain: 1) a PAN feature flag, which moves from a separate TLV 2) a new BT stats bit that indicates whether the microcode image uses bluetooth statistics 3) a new MFP flag for management frame protection which can be enabled once the device/microcode supports it Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 29 ++++++++++++++++++++++++++--- drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 17 +++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 2f4fe16d1eea..30b8b9e1bc2e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1191,7 +1191,7 @@ static void iwl_nic_start(struct iwl_priv *priv) struct iwlagn_ucode_capabilities { u32 max_probe_length; u32 standard_phy_calibration_size; - bool pan; + u32 flags; }; static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); @@ -1418,7 +1418,23 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, case IWL_UCODE_TLV_PAN: if (tlv_len) goto invalid_tlv_len; - capa->pan = true; + capa->flags |= IWL_UCODE_TLV_FLAGS_PAN; + break; + case IWL_UCODE_TLV_FLAGS: + /* must be at least one u32 */ + if (tlv_len < sizeof(u32)) + goto invalid_tlv_len; + /* and a proper number of u32s */ + if (tlv_len % sizeof(u32)) + goto invalid_tlv_len; + /* + * This driver only reads the first u32 as + * right now no more features are defined, + * if that changes then either the driver + * will not work with the new firmware, or + * it'll not take advantage of new features. + */ + capa->flags = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_INIT_EVTLOG_PTR: if (tlv_len != sizeof(u32)) @@ -1681,12 +1697,16 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) priv->cfg->base_params->max_event_log_size; priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; - if (ucode_capa.pan) { + if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN); priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; } else priv->sta_key_max_num = STA_KEY_MAX_NUM; + if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BTSTATS || + (priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics)) + priv->bt_statistics = true; + /* Copy images into buffers for card's bus-master reads ... */ /* Runtime instructions (first block of data in file) */ @@ -2827,6 +2847,9 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | IEEE80211_HW_SUPPORTS_STATIC_SMPS; + if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP) + hw->flags |= IEEE80211_HW_MFP_CAPABLE; + hw->sta_data_size = sizeof(struct iwl_station_priv); hw->vif_data_size = sizeof(struct iwl_vif_priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 696b056b070c..7b9f64ea9662 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -723,7 +723,7 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv) static inline bool iwl_bt_statistics(struct iwl_priv *priv) { - return priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics; + return priv->bt_statistics; } extern bool bt_coex_active; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 0696e7ff0f37..2f7458d3be9c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -535,6 +535,22 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, + /* 16 and 17 reserved for future use */ + IWL_UCODE_TLV_FLAGS = 18, +}; + +/** + * enum iwl_ucode_tlv_flag - ucode API flags + * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously + * was a separate TLV but moved here to save space. + * @IWL_UCODE_TLV_FLAGS_BTSTATS: This uCode image uses BT statistics, which + * may be true even if the device doesn't have BT. + * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). + */ +enum iwl_ucode_tlv_flag { + IWL_UCODE_TLV_FLAGS_PAN = BIT(0), + IWL_UCODE_TLV_FLAGS_BTSTATS = BIT(1), + IWL_UCODE_TLV_FLAGS_MFP = BIT(2), }; struct iwl_ucode_tlv { @@ -1410,6 +1426,7 @@ struct iwl_priv { bool bt_ch_announce; bool bt_full_concurrent; bool bt_ant_couple_ok; + bool bt_statistics; __le32 kill_ack_mask; __le32 kill_cts_mask; __le16 bt_valid; -- cgit v1.2.3-58-ga151 From 3d09cdff233b5a37ce9993c533e8da1403e2da30 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:42:03 -0700 Subject: iwlagn: fix ucode verify message My previous patch left a message talking about bootstrap, but that's clearly bogus. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 9c5abff6f04a..5187a2c20644 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -606,7 +606,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc) { if (!iwlcore_verify_inst_sparse(priv, fw_desc)) { - IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); + IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n"); return 0; } -- cgit v1.2.3-58-ga151 From d7d5783c6668b54111cc77005755799e94261497 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:42:04 -0700 Subject: iwlagn: clean up alive handling Devices newer than 4965 don't actually send two different versions of the ALIVE command, so we always had a bug here since before this patch we copy more data than we got. Remove the iwl_init_alive_resp struct and don't use it. Since we also really don't need to track all the data received in ALIVE as we only use the error and log event tables later, we can also save space by just keeping those and not more data around in memory. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 16 +++------- drivers/net/wireless/iwlwifi/iwl-commands.h | 48 ----------------------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 8 ++--- drivers/net/wireless/iwlwifi/iwl-rx.c | 10 +++--- 4 files changed, 13 insertions(+), 69 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 30b8b9e1bc2e..b3b1e84c9311 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -590,10 +590,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv) u32 num_wraps; /* # times uCode wrapped to top of log */ u32 next_entry; /* index of next entry to be written by uCode */ - if (priv->ucode_type == UCODE_INIT) - base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); - else - base = le32_to_cpu(priv->card_alive.log_event_table_ptr); + base = priv->device_pointers.error_event_table; if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { capacity = iwl_read_targ_mem(priv, base); num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); @@ -1871,12 +1868,11 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) u32 blink1, blink2, ilink1, ilink2; u32 pc, hcmd; + base = priv->device_pointers.error_event_table; if (priv->ucode_type == UCODE_INIT) { - base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); if (!base) base = priv->_agn.init_errlog_ptr; } else { - base = le32_to_cpu(priv->card_alive.error_event_table_ptr); if (!base) base = priv->_agn.inst_errlog_ptr; } @@ -1941,12 +1937,11 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, if (num_events == 0) return pos; + base = priv->device_pointers.log_event_table; if (priv->ucode_type == UCODE_INIT) { - base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); if (!base) base = priv->_agn.init_evtlog_ptr; } else { - base = le32_to_cpu(priv->card_alive.log_event_table_ptr); if (!base) base = priv->_agn.inst_evtlog_ptr; } @@ -2055,13 +2050,12 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, int pos = 0; size_t bufsz = 0; + base = priv->device_pointers.log_event_table; if (priv->ucode_type == UCODE_INIT) { - base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); logsize = priv->_agn.init_evtlog_size; if (!base) base = priv->_agn.init_evtlog_ptr; } else { - base = le32_to_cpu(priv->card_alive.log_event_table_ptr); logsize = priv->_agn.inst_evtlog_size; if (!base) base = priv->_agn.inst_evtlog_ptr; @@ -2415,8 +2409,6 @@ static void __iwl_down(struct iwl_priv *priv) iwl_apm_stop(priv); exit: - memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); - dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = NULL; diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index a2348ee61fd9..a1a5c1b23096 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -388,54 +388,6 @@ struct iwl_tx_ant_config_cmd { #define UCODE_VALID_OK cpu_to_le32(0x1) #define INITIALIZE_SUBTYPE (9) -/* - * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command) - * - * uCode issues this "initialize alive" notification once the initialization - * uCode image has completed its work, and is ready to load the runtime image. - * This is the *first* "alive" notification that the driver will receive after - * rebooting uCode; the "initialize" alive is indicated by subtype field == 9. - * - * See comments documenting "BSM" (bootstrap state machine). - * - * For 4965, this notification contains important calibration data for - * calculating txpower settings: - * - * 1) Power supply voltage indication. The voltage sensor outputs higher - * values for lower voltage, and vice verse. - * - * 2) Temperature measurement parameters, for each of two channel widths - * (20 MHz and 40 MHz) supported by the radios. Temperature sensing - * is done via one of the receiver chains, and channel width influences - * the results. - * - * 3) Tx gain compensation to balance 4965's 2 Tx chains for MIMO operation, - * for each of 5 frequency ranges. - */ -struct iwl_init_alive_resp { - u8 ucode_minor; - u8 ucode_major; - __le16 reserved1; - u8 sw_rev[8]; - u8 ver_type; - u8 ver_subtype; /* "9" for initialize alive */ - __le16 reserved2; - __le32 log_event_table_ptr; - __le32 error_event_table_ptr; - __le32 timestamp; - __le32 is_valid; - - /* calibration values from "initialize" uCode */ - __le32 voltage; /* signed, higher value is lower voltage */ - __le32 therm_r1[2]; /* signed, 1st for normal, 2nd for HT40 */ - __le32 therm_r2[2]; /* signed */ - __le32 therm_r3[2]; /* signed */ - __le32 therm_r4[2]; /* signed */ - __le32 tx_atten[5][2]; /* signed MIMO gain comp, 5 freq groups, - * 2 Tx chains */ -} __packed; - - /** * REPLY_ALIVE = 0x1 (response only, not a command) * diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2f7458d3be9c..b4bfcab233ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1285,10 +1285,10 @@ struct iwl_priv { struct iwl_switch_rxon switch_rxon; - /* 1st responses from initialize and runtime uCode images. - * _agn's initialize alive response contains some calibration data. */ - struct iwl_init_alive_resp card_alive_init; - struct iwl_alive_resp card_alive; + struct { + u32 error_event_table; + u32 log_event_table; + } device_pointers; u16 active_rate; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 984a42cfffe9..b5124de99624 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -239,16 +239,16 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv, palive->is_valid, palive->ver_type, palive->ver_subtype); + priv->device_pointers.log_event_table = + le32_to_cpu(palive->log_event_table_ptr); + priv->device_pointers.error_event_table = + le32_to_cpu(palive->error_event_table_ptr); + if (palive->ver_subtype == INITIALIZE_SUBTYPE) { IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); - memcpy(&priv->card_alive_init, - &pkt->u.alive_frame, - sizeof(struct iwl_init_alive_resp)); pwork = &priv->init_alive_start; } else { IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); - memcpy(&priv->card_alive, &pkt->u.alive_frame, - sizeof(struct iwl_alive_resp)); pwork = &priv->alive_start; } -- cgit v1.2.3-58-ga151 From 17445b8c443bb1aaf7f85bcf60676d04be1c467c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:42:05 -0700 Subject: iwlagn: init cmd_queue earlier We know after loading the ucode whether it will support PAN or not, so we can also initialise the cmd_queue variable much earlier. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b3b1e84c9311..d700860434a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1700,6 +1700,11 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) } else priv->sta_key_max_num = STA_KEY_MAX_NUM; + if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) + priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; + else + priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BTSTATS || (priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics)) priv->bt_statistics = true; @@ -2518,12 +2523,6 @@ static int __iwl_up(struct iwl_priv *priv) iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - /* must be initialised before iwl_hw_nic_init */ - if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) - priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; - else - priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; - ret = iwlagn_hw_nic_init(priv); if (ret) { IWL_ERR(priv, "Unable to init nic\n"); -- cgit v1.2.3-58-ga151 From 917b6777b45ac49c436570e36eb09d9b8b84c434 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:42:06 -0700 Subject: iwlagn: remove BSM clock setting Again, a 4965 specific code path that we no longer need in iwlagn. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 - drivers/net/wireless/iwlwifi/iwl-2000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-5000.c | 1 - drivers/net/wireless/iwlwifi/iwl-6000.c | 3 --- drivers/net/wireless/iwlwifi/iwl-core.c | 12 ++---------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - 6 files changed, 2 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 5c3bb47de3a7..de5b287920b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -249,7 +249,6 @@ static struct iwl_base_params iwl1000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, .set_l0s = true, - .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_1000, .shadow_ram_support = false, .led_compensation = 51, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index f87adbf11349..d22e0069801c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -356,7 +356,6 @@ static struct iwl_base_params iwl2000_base_params = { .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, .set_l0s = true, - .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_2x00, .shadow_ram_support = true, .led_compensation = 51, @@ -380,7 +379,6 @@ static struct iwl_base_params iwl2030_base_params = { .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, .set_l0s = true, - .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_2x00, .shadow_ram_support = true, .led_compensation = 57, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index d2f4eb3f4b38..de0e86a5d2f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -488,7 +488,6 @@ static struct iwl_base_params iwl5000_base_params = { .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, .set_l0s = true, - .use_bsm = false, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index c1f8d1d2b721..be2dbf7bd808 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -459,7 +459,6 @@ static struct iwl_base_params iwl6000_base_params = { .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, .set_l0s = true, - .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, .led_compensation = 51, @@ -482,7 +481,6 @@ static struct iwl_base_params iwl6050_base_params = { .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, .set_l0s = true, - .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_6x50, .shadow_ram_support = true, .led_compensation = 51, @@ -504,7 +502,6 @@ static struct iwl_base_params iwl6000_g2_base_params = { .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, .set_l0s = true, - .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, .led_compensation = 57, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 6e9829fd6c03..c46be36b9e2e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1105,21 +1105,13 @@ int iwl_apm_init(struct iwl_priv *priv) } /* - * Enable DMA and BSM (if used) clocks, wait for them to stabilize. - * BSM (Boostrap State Machine) is only in 3945 and 4965; - * later devices (i.e. 5000 and later) have non-volatile SRAM, - * and don't need BSM to restore data after power-saving sleep. + * Enable DMA clock and wait for it to stabilize. * * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits * do not disable clocks. This preserves any hardware bits already * set by default in "CLK_CTRL_REG" after reset. */ - if (priv->cfg->base_params->use_bsm) - iwl_write_prph(priv, APMG_CLK_EN_REG, - APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); - else - iwl_write_prph(priv, APMG_CLK_EN_REG, - APMG_CLK_VAL_DMA_CLK_RQT); + iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); udelay(20); /* Disable L1-Active */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7b9f64ea9662..ada76af124a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -283,7 +283,6 @@ struct iwl_base_params { /* for iwl_apm_init() */ u32 pll_cfg_val; bool set_l0s; - bool use_bsm; const u16 max_ll_items; const bool shadow_ram_support; -- cgit v1.2.3-58-ga151 From bc255930639122d788d1b6ce10d3c01cc2946398 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:42:07 -0700 Subject: iwlagn: remove hw_wa_rev The variable is never used. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d700860434a5..55a1d65c4baf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3688,7 +3688,6 @@ struct ieee80211_ops iwlagn_hw_ops = { static void iwl_hw_detect(struct iwl_priv *priv) { priv->hw_rev = _iwl_read32(priv, CSR_HW_REV); - priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG); priv->rev_id = priv->pci_dev->revision; IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id); } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b4bfcab233ab..2c2d5b00a345 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1254,7 +1254,6 @@ struct iwl_priv { /* pci hardware address support */ void __iomem *hw_base; u32 hw_rev; - u32 hw_wa_rev; u8 rev_id; /* microcode/device supports multiple contexts */ -- cgit v1.2.3-58-ga151 From e98a130259ed6f88bc2833fa525b10453c92c047 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:42:08 -0700 Subject: iwlagn: remove hw_rev The hw_rev variable is used only during init, so there's no need to keep it around. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 11 ++++++----- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-eeprom.c | 8 ++++---- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 55a1d65c4baf..c3306bae0f1e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3685,11 +3685,11 @@ struct ieee80211_ops iwlagn_hw_ops = { .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait, }; -static void iwl_hw_detect(struct iwl_priv *priv) +static u32 iwl_hw_detect(struct iwl_priv *priv) { - priv->hw_rev = _iwl_read32(priv, CSR_HW_REV); priv->rev_id = priv->pci_dev->revision; IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id); + return _iwl_read32(priv, CSR_HW_REV); } static int iwl_set_hw_params(struct iwl_priv *priv) @@ -3740,6 +3740,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); unsigned long flags; u16 pci_cmd, num_mac; + u32 hw_rev; /************************ * 1. Allocating HW data @@ -3885,9 +3886,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); - iwl_hw_detect(priv); + hw_rev = iwl_hw_detect(priv); IWL_INFO(priv, "Detected %s, REV=0x%X\n", - priv->cfg->name, priv->hw_rev); + priv->cfg->name, hw_rev); /* We disable the RETRY_TIMEOUT register (0x41) to keep * PCI Tx retries from interfering with C3 CPU state */ @@ -3903,7 +3904,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * 4. Read EEPROM *****************/ /* Read the EEPROM */ - err = iwl_eeprom_init(priv); + err = iwl_eeprom_init(priv, hw_rev); if (err) { IWL_ERR(priv, "Unable to init EEPROM\n"); goto out_iounmap; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2c2d5b00a345..1779d603e3e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1253,7 +1253,6 @@ struct iwl_priv { /* pci hardware address support */ void __iomem *hw_base; - u32 hw_rev; u8 rev_id; /* microcode/device supports multiple contexts */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index f70d87162e59..4f8c13e9850b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -188,13 +188,13 @@ static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) CSR_OTP_GP_REG_OTP_ACCESS_MODE); } -static int iwlcore_get_nvm_type(struct iwl_priv *priv) +static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) { u32 otpgp; int nvm_type; /* OTP only valid for CP/PP and after */ - switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { + switch (hw_rev & CSR_HW_REV_TYPE_MSK) { case CSR_HW_REV_TYPE_NONE: IWL_ERR(priv, "Unknown hardware type\n"); return -ENOENT; @@ -394,7 +394,7 @@ u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) * * NOTE: This routine uses the non-debug IO access functions. */ -int iwl_eeprom_init(struct iwl_priv *priv) +int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) { __le16 *e; u32 gp = iwl_read32(priv, CSR_EEPROM_GP); @@ -404,7 +404,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) u16 validblockaddr = 0; u16 cache_addr = 0; - priv->nvm_device_type = iwlcore_get_nvm_type(priv); + priv->nvm_device_type = iwlcore_get_nvm_type(priv, hw_rev); if (priv->nvm_device_type == -ENOENT) return -ENOENT; /* allocate eeprom */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 35bf54b38515..6b4343bd4bd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -302,7 +302,7 @@ struct iwl_eeprom_ops { }; -int iwl_eeprom_init(struct iwl_priv *priv); +int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev); void iwl_eeprom_free(struct iwl_priv *priv); int iwl_eeprom_check_version(struct iwl_priv *priv); int iwl_eeprom_check_sku(struct iwl_priv *priv); -- cgit v1.2.3-58-ga151 From c2974a1d18832a9fffb2eb389c3878f5c4ed92f1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:42:09 -0700 Subject: iwlagn: remove rev_id The rev_id variable is only printed, we don't need to store it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ++++-- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c3306bae0f1e..08bad17ca0ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3687,8 +3687,10 @@ struct ieee80211_ops iwlagn_hw_ops = { static u32 iwl_hw_detect(struct iwl_priv *priv) { - priv->rev_id = priv->pci_dev->revision; - IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id); + u8 rev_id; + + pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); + IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); return _iwl_read32(priv, CSR_HW_REV); } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 1779d603e3e6..54b20d8ac93f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1253,7 +1253,6 @@ struct iwl_priv { /* pci hardware address support */ void __iomem *hw_base; - u8 rev_id; /* microcode/device supports multiple contexts */ u8 valid_contexts; -- cgit v1.2.3-58-ga151 From 0e5884458eeadbb48ab3eb1d5f63b4a53a044a95 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:42:10 -0700 Subject: iwlagn: remove rxb page bookkeeping We never use the value in alloc_rxb_page, so there's no point in keeping it either. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 3 --- drivers/net/wireless/iwlwifi/iwl-rx.c | 1 - 3 files changed, 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 9a3d69d9b8a4..9e47be6a7393 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -912,7 +912,6 @@ void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; - priv->alloc_rxb_page++; spin_unlock_irqrestore(&rxq->lock, flags); } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 54b20d8ac93f..72133368c1f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1191,7 +1191,6 @@ struct iwl_priv { int frames_count; enum ieee80211_band band; - int alloc_rxb_page; void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); @@ -1609,12 +1608,10 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch) static inline void __iwl_free_pages(struct iwl_priv *priv, struct page *page) { __free_pages(page, priv->hw_params.rx_page_order); - priv->alloc_rxb_page--; } static inline void iwl_free_pages(struct iwl_priv *priv, unsigned long page) { free_pages(page, priv->hw_params.rx_page_order); - priv->alloc_rxb_page--; } #endif /* __iwl_dev_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index b5124de99624..c421f566982f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -898,7 +898,6 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); ieee80211_rx(priv->hw, skb); - priv->alloc_rxb_page--; rxb->page = NULL; } -- cgit v1.2.3-58-ga151 From 519d8abd358afad825a1b919a2421d76779f23cd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:42:11 -0700 Subject: iwlagn: remove ISR ops The ISR (interrupt service routine) ops are now no longer necessary since they are the same for all devices this driver now handles. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 7 ------- drivers/net/wireless/iwlwifi/iwl-2000.c | 7 ------- drivers/net/wireless/iwlwifi/iwl-5000.c | 14 -------------- drivers/net/wireless/iwlwifi/iwl-6000.c | 14 -------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 17 ++++++----------- drivers/net/wireless/iwlwifi/iwl-core.h | 11 ----------- 6 files changed, 6 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index de5b287920b4..1b2799291834 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -209,13 +209,6 @@ static struct iwl_lib_ops iwl1000_lib = { .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, - .isr_ops = { - .isr = iwl_isr_ict, - .free = iwl_free_isr_ict, - .alloc = iwl_alloc_isr_ict, - .reset = iwl_reset_ict, - .disable = iwl_disable_ict, - }, .temp_ops = { .temperature = iwlagn_temperature, }, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index d22e0069801c..f602af4b9408 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -292,13 +292,6 @@ static struct iwl_lib_ops iwl2000_lib = { .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, - .isr_ops = { - .isr = iwl_isr_ict, - .free = iwl_free_isr_ict, - .alloc = iwl_alloc_isr_ict, - .reset = iwl_reset_ict, - .disable = iwl_disable_ict, - }, .temp_ops = { .temperature = iwlagn_temperature, }, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index de0e86a5d2f7..fb00464cead5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -378,13 +378,6 @@ static struct iwl_lib_ops iwl5000_lib = { .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, - .isr_ops = { - .isr = iwl_isr_ict, - .free = iwl_free_isr_ict, - .alloc = iwl_alloc_isr_ict, - .reset = iwl_reset_ict, - .disable = iwl_disable_ict, - }, .temp_ops = { .temperature = iwlagn_temperature, }, @@ -440,13 +433,6 @@ static struct iwl_lib_ops iwl5150_lib = { .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, - .isr_ops = { - .isr = iwl_isr_ict, - .free = iwl_free_isr_ict, - .alloc = iwl_alloc_isr_ict, - .reset = iwl_reset_ict, - .disable = iwl_disable_ict, - }, .temp_ops = { .temperature = iwl5150_temperature, }, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index be2dbf7bd808..24d105b29aec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -320,13 +320,6 @@ static struct iwl_lib_ops iwl6000_lib = { .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, - .isr_ops = { - .isr = iwl_isr_ict, - .free = iwl_free_isr_ict, - .alloc = iwl_alloc_isr_ict, - .reset = iwl_reset_ict, - .disable = iwl_disable_ict, - }, .temp_ops = { .temperature = iwlagn_temperature, }, @@ -385,13 +378,6 @@ static struct iwl_lib_ops iwl6030_lib = { .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, - .isr_ops = { - .isr = iwl_isr_ict, - .free = iwl_free_isr_ict, - .alloc = iwl_alloc_isr_ict, - .reset = iwl_reset_ict, - .disable = iwl_disable_ict, - }, .temp_ops = { .temperature = iwlagn_temperature, }, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 08bad17ca0ed..fd3aed8ed960 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2397,8 +2397,7 @@ static void __iwl_down(struct iwl_priv *priv) STATUS_EXIT_PENDING; /* device going down, Stop using ICT table */ - if (priv->cfg->ops->lib->isr_ops.disable) - priv->cfg->ops->lib->isr_ops.disable(priv); + iwl_disable_ict(priv); iwlagn_txq_ctx_stop(priv); iwlagn_rxq_stop(priv); @@ -2606,8 +2605,7 @@ static void iwl_bg_alive_start(struct work_struct *data) goto unlock; /* enable dram interrupt */ - if (priv->cfg->ops->lib->isr_ops.reset) - priv->cfg->ops->lib->isr_ops.reset(priv); + iwl_reset_ict(priv); iwl_alive_start(priv); unlock: @@ -3958,10 +3956,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_enable_msi(priv->pci_dev); - if (priv->cfg->ops->lib->isr_ops.alloc) - priv->cfg->ops->lib->isr_ops.alloc(priv); + iwl_alloc_isr_ict(priv); - err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr, + err = request_irq(priv->pci_dev->irq, iwl_isr_ict, IRQF_SHARED, DRV_NAME, priv); if (err) { IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); @@ -4008,8 +4005,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) destroy_workqueue(priv->workqueue); priv->workqueue = NULL; free_irq(priv->pci_dev->irq, priv); - if (priv->cfg->ops->lib->isr_ops.free) - priv->cfg->ops->lib->isr_ops.free(priv); + iwl_free_isr_ict(priv); out_disable_msi: pci_disable_msi(priv->pci_dev); iwl_uninit_drv(priv); @@ -4107,8 +4103,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) iwl_uninit_drv(priv); - if (priv->cfg->ops->lib->isr_ops.free) - priv->cfg->ops->lib->isr_ops.free(priv); + iwl_free_isr_ict(priv); dev_kfree_skb(priv->beacon_skb); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index ada76af124a4..82939f851eb9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -122,14 +122,6 @@ struct iwl_apm_ops { void (*config)(struct iwl_priv *priv); }; -struct iwl_isr_ops { - irqreturn_t (*isr) (int irq, void *data); - void (*free)(struct iwl_priv *priv); - int (*alloc)(struct iwl_priv *priv); - int (*reset)(struct iwl_priv *priv); - void (*disable)(struct iwl_priv *priv); -}; - struct iwl_debugfs_ops { ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); @@ -194,9 +186,6 @@ struct iwl_lib_ops { int (*send_tx_power) (struct iwl_priv *priv); void (*update_chain_flags)(struct iwl_priv *priv); - /* isr */ - struct iwl_isr_ops isr_ops; - /* eeprom operations (as defined in iwl-eeprom.h) */ struct iwl_eeprom_ops eeprom_ops; -- cgit v1.2.3-58-ga151 From 02a7fa00a6d145037d549c779ad7692deb504acc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2011 09:42:12 -0700 Subject: iwlagn: move IO functions out of line This generates a massive reduction in module size: with debug: text data bss dec hex filename 670300 13136 420 683856 a6f50 iwlagn.ko (before) 388347 13136 408 401891 621e3 iwlagn.ko (after) without debug: text data bss dec hex filename 528575 13072 420 542067 84573 iwlagn.ko (before) 294192 13072 408 307672 4b1d8 iwlagn.ko (after) This also removes all the IO debug functionality since it can easily be replaced by tracing, and makes the code unnecessarily complex. I haven't done any CPU utilisation measurements, but given that the hotpaths don't use much IO it is not likely to have a negative impact; in fact, the size reduction will reduce cache pressure which possibly improves performance. Finally, an unused function or two were removed. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 6 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 18 +- drivers/net/wireless/iwlwifi/iwl-debug.h | 2 - drivers/net/wireless/iwlwifi/iwl-eeprom.c | 36 +- drivers/net/wireless/iwlwifi/iwl-io.c | 274 +++++++++++++++ drivers/net/wireless/iwlwifi/iwl-io.h | 489 ++------------------------ 8 files changed, 326 insertions(+), 503 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-io.c diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 9d6ee836426c..3652931753e0 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_IWLAGN) += iwlagn.o iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o -iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o +iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c index c6dd9b755a05..3bcaa10f9929 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -103,7 +103,7 @@ int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv) CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, EEPROM_SEM_TIMEOUT); if (ret >= 0) { - IWL_DEBUG_IO(priv, + IWL_DEBUG_EEPROM(priv, "Acquired semaphore after %d tries.\n", count+1); return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 5187a2c20644..01a6d2fc795c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -561,7 +561,7 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, * if IWL_DL_IO is set */ iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, i + IWLAGN_RTC_INST_LOWER_BOUND); - val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) return -EIO; } @@ -587,9 +587,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, offs < len && errors < 20; offs += sizeof(u32), image++) { /* read data comes through single port, auto-incr addr */ - /* NOTE: Use the debugless read so we don't flood kernel log - * if IWL_DL_IO is set */ - val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { IWL_ERR(priv, "uCode INST section at " "offset 0x%x, is 0x%x, s/b 0x%x\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index fd3aed8ed960..60bfde75ce87 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -558,7 +558,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, } /* Set starting address; reads will auto-increment */ - _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); + iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); rmb(); /* @@ -566,13 +566,13 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); - time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); if (mode == 0) { trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev); } else { - data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); trace_iwlwifi_dev_ucode_cont_event(priv, time, data, ev); } @@ -1963,14 +1963,14 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, iwl_grab_nic_access(priv); /* Set starting address; reads will auto-increment */ - _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); + iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); rmb(); /* "time" is actually "data" for mode 0 (no timestamp). * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); - time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); if (mode == 0) { /* data, ev */ if (bufsz) { @@ -1984,7 +1984,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, time, ev); } } else { - data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); if (bufsz) { pos += scnprintf(*buf + pos, bufsz - pos, "EVT_LOGT:%010u:0x%08x:%04u\n", @@ -3689,7 +3689,7 @@ static u32 iwl_hw_detect(struct iwl_priv *priv) pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); - return _iwl_read32(priv, CSR_HW_REV); + return iwl_read32(priv, CSR_HW_REV); } static int iwl_set_hw_params(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 8489431ceb8b..2824ccbcc1fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -146,7 +146,6 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DL_RX (1 << 24) #define IWL_DL_ISR (1 << 25) #define IWL_DL_HT (1 << 26) -#define IWL_DL_IO (1 << 27) /* 0xF0000000 - 0x10000000 */ #define IWL_DL_11H (1 << 28) #define IWL_DL_STATS (1 << 29) @@ -174,7 +173,6 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a) #define IWL_DEBUG_AP(p, f, a...) IWL_DEBUG(p, IWL_DL_AP, f, ## a) #define IWL_DEBUG_TXPOWER(p, f, a...) IWL_DEBUG(p, IWL_DL_TXPOWER, f, ## a) -#define IWL_DEBUG_IO(p, f, a...) IWL_DEBUG(p, IWL_DL_IO, f, ## a) #define IWL_DEBUG_RATE(p, f, a...) IWL_DEBUG(p, IWL_DL_RATE, f, ## a) #define IWL_DEBUG_RATE_LIMIT(p, f, a...) \ IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a) diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 4f8c13e9850b..859b94a12297 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -226,15 +226,15 @@ static int iwl_init_otp_access(struct iwl_priv *priv) int ret; /* Enable 40MHz radio clock */ - _iwl_write32(priv, CSR_GP_CNTRL, - _iwl_read32(priv, CSR_GP_CNTRL) | - CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_write32(priv, CSR_GP_CNTRL, + iwl_read32(priv, CSR_GP_CNTRL) | + CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* wait for clock to be ready */ ret = iwl_poll_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, - 25000); + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, + 25000); if (ret < 0) IWL_ERR(priv, "Time out access OTP\n"); else { @@ -261,17 +261,17 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat u32 r; u32 otpgp; - _iwl_write32(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); + iwl_write32(priv, CSR_EEPROM_REG, + CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); ret = iwl_poll_bit(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_READ_VALID_MSK, - CSR_EEPROM_REG_READ_VALID_MSK, - IWL_EEPROM_ACCESS_TIMEOUT); + CSR_EEPROM_REG_READ_VALID_MSK, + CSR_EEPROM_REG_READ_VALID_MSK, + IWL_EEPROM_ACCESS_TIMEOUT); if (ret < 0) { IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); return ret; } - r = _iwl_read_direct32(priv, CSR_EEPROM_REG); + r = iwl_read32(priv, CSR_EEPROM_REG); /* check for ECC errors: */ otpgp = iwl_read32(priv, CSR_OTP_GP_REG); if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { @@ -442,9 +442,9 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) ret = -ENOENT; goto done; } - _iwl_write32(priv, CSR_EEPROM_GP, - iwl_read32(priv, CSR_EEPROM_GP) & - ~CSR_EEPROM_GP_IF_OWNER_MSK); + iwl_write32(priv, CSR_EEPROM_GP, + iwl_read32(priv, CSR_EEPROM_GP) & + ~CSR_EEPROM_GP_IF_OWNER_MSK); iwl_set_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | @@ -471,8 +471,8 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) for (addr = 0; addr < sz; addr += sizeof(u16)) { u32 r; - _iwl_write32(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); + iwl_write32(priv, CSR_EEPROM_REG, + CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); ret = iwl_poll_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, @@ -482,7 +482,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); goto done; } - r = _iwl_read_direct32(priv, CSR_EEPROM_REG); + r = iwl_read32(priv, CSR_EEPROM_REG); e[addr / 2] = cpu_to_le16(r >> 16); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c new file mode 100644 index 000000000000..51337416e4ca --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -0,0 +1,274 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * + * Portions of this file are derived from the ipw3945 project. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#include "iwl-io.h" + +#define IWL_POLL_INTERVAL 10 /* microseconds */ + +static inline void __iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) +{ + iwl_write32(priv, reg, iwl_read32(priv, reg) | mask); +} + +static inline void __iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) +{ + iwl_write32(priv, reg, iwl_read32(priv, reg) & ~mask); +} + +void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->reg_lock, flags); + __iwl_set_bit(priv, reg, mask); + spin_unlock_irqrestore(&priv->reg_lock, flags); +} + +void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->reg_lock, flags); + __iwl_clear_bit(priv, reg, mask); + spin_unlock_irqrestore(&priv->reg_lock, flags); +} + +int iwl_poll_bit(struct iwl_priv *priv, u32 addr, + u32 bits, u32 mask, int timeout) +{ + int t = 0; + + do { + if ((iwl_read32(priv, addr) & mask) == (bits & mask)) + return t; + udelay(IWL_POLL_INTERVAL); + t += IWL_POLL_INTERVAL; + } while (t < timeout); + + return -ETIMEDOUT; +} + +int iwl_grab_nic_access(struct iwl_priv *priv) +{ + int ret; + u32 val; + + lockdep_assert_held(&priv->reg_lock); + + /* this bit wakes up the NIC */ + __iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + + /* + * These bits say the device is running, and should keep running for + * at least a short while (at least as long as MAC_ACCESS_REQ stays 1), + * but they do not indicate that embedded SRAM is restored yet; + * 3945 and 4965 have volatile SRAM, and must save/restore contents + * to/from host DRAM when sleeping/waking for power-saving. + * Each direction takes approximately 1/4 millisecond; with this + * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a + * series of register accesses are expected (e.g. reading Event Log), + * to keep device from sleeping. + * + * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that + * SRAM is okay/restored. We don't check that here because this call + * is just for hardware register access; but GP1 MAC_SLEEP check is a + * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log). + * + * 5000 series and later (including 1000 series) have non-volatile SRAM, + * and do not save/restore SRAM when power cycling. + */ + ret = iwl_poll_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, + (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | + CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); + if (ret < 0) { + val = iwl_read32(priv, CSR_GP_CNTRL); + IWL_ERR(priv, + "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); + return -EIO; + } + + return 0; +} + +void iwl_release_nic_access(struct iwl_priv *priv) +{ + lockdep_assert_held(&priv->reg_lock); + __iwl_clear_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); +} + +u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) +{ + u32 value; + unsigned long flags; + + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + value = iwl_read32(priv, reg); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); + + return value; +} + +void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->reg_lock, flags); + if (!iwl_grab_nic_access(priv)) { + iwl_write32(priv, reg, value); + iwl_release_nic_access(priv); + } + spin_unlock_irqrestore(&priv->reg_lock, flags); +} + +int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, + int timeout) +{ + int t = 0; + + do { + if ((iwl_read_direct32(priv, addr) & mask) == mask) + return t; + udelay(IWL_POLL_INTERVAL); + t += IWL_POLL_INTERVAL; + } while (t < timeout); + + return -ETIMEDOUT; +} + +static inline u32 __iwl_read_prph(struct iwl_priv *priv, u32 reg) +{ + iwl_write32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); + rmb(); + return iwl_read32(priv, HBUS_TARG_PRPH_RDAT); +} + +static inline void __iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) +{ + iwl_write32(priv, HBUS_TARG_PRPH_WADDR, + ((addr & 0x0000FFFF) | (3 << 24))); + wmb(); + iwl_write32(priv, HBUS_TARG_PRPH_WDAT, val); +} + +u32 iwl_read_prph(struct iwl_priv *priv, u32 reg) +{ + unsigned long flags; + u32 val; + + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + val = __iwl_read_prph(priv, reg); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); + return val; +} + +void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->reg_lock, flags); + if (!iwl_grab_nic_access(priv)) { + __iwl_write_prph(priv, addr, val); + iwl_release_nic_access(priv); + } + spin_unlock_irqrestore(&priv->reg_lock, flags); +} + +void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + __iwl_write_prph(priv, reg, __iwl_read_prph(priv, reg) | mask); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); +} + +void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, + u32 bits, u32 mask) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + __iwl_write_prph(priv, reg, + (__iwl_read_prph(priv, reg) & mask) | bits); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); +} + +void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) +{ + unsigned long flags; + u32 val; + + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + val = __iwl_read_prph(priv, reg); + __iwl_write_prph(priv, reg, (val & ~mask)); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); +} + +u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) +{ + unsigned long flags; + u32 value; + + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + + iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr); + rmb(); + value = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); + return value; +} + +void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->reg_lock, flags); + if (!iwl_grab_nic_access(priv)) { + iwl_write32(priv, HBUS_TARG_MEM_WADDR, addr); + wmb(); + iwl_write32(priv, HBUS_TARG_MEM_WDAT, val); + iwl_release_nic_access(priv); + } + spin_unlock_irqrestore(&priv->reg_lock, flags); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 3ddb2fbe12f9..ab632baf49d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -35,494 +35,47 @@ #include "iwl-debug.h" #include "iwl-devtrace.h" -/* - * IO, register, and NIC memory access functions - * - * NOTE on naming convention and macro usage for these - * - * A single _ prefix before a an access function means that no state - * check or debug information is printed when that function is called. - * - * A double __ prefix before an access function means that state is checked - * and the current line number and caller function name are printed in addition - * to any other debug output. - * - * The non-prefixed name is the #define that maps the caller into a - * #define that provides the caller's name and __LINE__ to the double - * prefix version. - * - * If you wish to call the function without any debug or state checking, - * you should use the single _ prefix version (as is used by dependent IO - * routines, for example _iwl_read_direct32 calls the non-check version of - * _iwl_read32.) - * - * These declarations are *extremely* useful in quickly isolating code deltas - * which result in misconfiguration of the hardware I/O. In combination with - * git-bisect and the IO debug level you can quickly determine the specific - * commit which breaks the IO sequence to the hardware. - * - */ - -static inline void _iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) +static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) { trace_iwlwifi_dev_iowrite8(priv, ofs, val); iowrite8(val, priv->hw_base + ofs); } -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_write8(const char *f, u32 l, struct iwl_priv *priv, - u32 ofs, u8 val) -{ - IWL_DEBUG_IO(priv, "write8(0x%08X, 0x%02X) - %s %d\n", ofs, val, f, l); - _iwl_write8(priv, ofs, val); -} -#define iwl_write8(priv, ofs, val) \ - __iwl_write8(__FILE__, __LINE__, priv, ofs, val) -#else -#define iwl_write8(priv, ofs, val) _iwl_write8(priv, ofs, val) -#endif - - -static inline void _iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) +static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) { trace_iwlwifi_dev_iowrite32(priv, ofs, val); iowrite32(val, priv->hw_base + ofs); } -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, - u32 ofs, u32 val) -{ - IWL_DEBUG_IO(priv, "write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); - _iwl_write32(priv, ofs, val); -} -#define iwl_write32(priv, ofs, val) \ - __iwl_write32(__FILE__, __LINE__, priv, ofs, val) -#else -#define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val) -#endif - -static inline u32 _iwl_read32(struct iwl_priv *priv, u32 ofs) +static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs) { u32 val = ioread32(priv->hw_base + ofs); trace_iwlwifi_dev_ioread32(priv, ofs, val); return val; } -#ifdef CONFIG_IWLWIFI_DEBUG -static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) -{ - IWL_DEBUG_IO(priv, "read_direct32(0x%08X) - %s %d\n", ofs, f, l); - return _iwl_read32(priv, ofs); -} -#define iwl_read32(priv, ofs) __iwl_read32(__FILE__, __LINE__, priv, ofs) -#else -#define iwl_read32(p, o) _iwl_read32(p, o) -#endif - -#define IWL_POLL_INTERVAL 10 /* microseconds */ -static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr, - u32 bits, u32 mask, int timeout) -{ - int t = 0; - - do { - if ((_iwl_read32(priv, addr) & mask) == (bits & mask)) - return t; - udelay(IWL_POLL_INTERVAL); - t += IWL_POLL_INTERVAL; - } while (t < timeout); - - return -ETIMEDOUT; -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline int __iwl_poll_bit(const char *f, u32 l, - struct iwl_priv *priv, u32 addr, - u32 bits, u32 mask, int timeout) -{ - int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout); - IWL_DEBUG_IO(priv, "poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", - addr, bits, mask, - unlikely(ret == -ETIMEDOUT) ? "timeout" : "", f, l); - return ret; -} -#define iwl_poll_bit(priv, addr, bits, mask, timeout) \ - __iwl_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout) -#else -#define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t) -#endif - -static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) -{ - _iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_set_bit(const char *f, u32 l, - struct iwl_priv *priv, u32 reg, u32 mask) -{ - u32 val = _iwl_read32(priv, reg) | mask; - IWL_DEBUG_IO(priv, "set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); - _iwl_write32(priv, reg, val); -} -static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&p->reg_lock, reg_flags); - __iwl_set_bit(__FILE__, __LINE__, p, r, m); - spin_unlock_irqrestore(&p->reg_lock, reg_flags); -} -#else -static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&p->reg_lock, reg_flags); - _iwl_set_bit(p, r, m); - spin_unlock_irqrestore(&p->reg_lock, reg_flags); -} -#endif - -static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) -{ - _iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_clear_bit(const char *f, u32 l, - struct iwl_priv *priv, u32 reg, u32 mask) -{ - u32 val = _iwl_read32(priv, reg) & ~mask; - IWL_DEBUG_IO(priv, "clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); - _iwl_write32(priv, reg, val); -} -static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&p->reg_lock, reg_flags); - __iwl_clear_bit(__FILE__, __LINE__, p, r, m); - spin_unlock_irqrestore(&p->reg_lock, reg_flags); -} -#else -static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&p->reg_lock, reg_flags); - _iwl_clear_bit(p, r, m); - spin_unlock_irqrestore(&p->reg_lock, reg_flags); -} -#endif - -static inline int _iwl_grab_nic_access(struct iwl_priv *priv) -{ - int ret; - u32 val; - - /* this bit wakes up the NIC */ - _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - - /* - * These bits say the device is running, and should keep running for - * at least a short while (at least as long as MAC_ACCESS_REQ stays 1), - * but they do not indicate that embedded SRAM is restored yet; - * 3945 and 4965 have volatile SRAM, and must save/restore contents - * to/from host DRAM when sleeping/waking for power-saving. - * Each direction takes approximately 1/4 millisecond; with this - * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a - * series of register accesses are expected (e.g. reading Event Log), - * to keep device from sleeping. - * - * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that - * SRAM is okay/restored. We don't check that here because this call - * is just for hardware register access; but GP1 MAC_SLEEP check is a - * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log). - * - * 5000 series and later (including 1000 series) have non-volatile SRAM, - * and do not save/restore SRAM when power cycling. - */ - ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, - (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | - CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); - if (ret < 0) { - val = _iwl_read32(priv, CSR_GP_CNTRL); - IWL_ERR(priv, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); - _iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); - return -EIO; - } - - return 0; -} - -#ifdef CONFIG_IWLWIFI_DEBUG -static inline int __iwl_grab_nic_access(const char *f, u32 l, - struct iwl_priv *priv) -{ - IWL_DEBUG_IO(priv, "grabbing nic access - %s %d\n", f, l); - return _iwl_grab_nic_access(priv); -} -#define iwl_grab_nic_access(priv) \ - __iwl_grab_nic_access(__FILE__, __LINE__, priv) -#else -#define iwl_grab_nic_access(priv) \ - _iwl_grab_nic_access(priv) -#endif - -static inline void _iwl_release_nic_access(struct iwl_priv *priv) -{ - _iwl_clear_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_release_nic_access(const char *f, u32 l, - struct iwl_priv *priv) -{ - - IWL_DEBUG_IO(priv, "releasing nic access - %s %d\n", f, l); - _iwl_release_nic_access(priv); -} -#define iwl_release_nic_access(priv) \ - __iwl_release_nic_access(__FILE__, __LINE__, priv) -#else -#define iwl_release_nic_access(priv) \ - _iwl_release_nic_access(priv) -#endif - -static inline u32 _iwl_read_direct32(struct iwl_priv *priv, u32 reg) -{ - return _iwl_read32(priv, reg); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline u32 __iwl_read_direct32(const char *f, u32 l, - struct iwl_priv *priv, u32 reg) -{ - u32 value = _iwl_read_direct32(priv, reg); - IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d\n", reg, value, - f, l); - return value; -} -static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) -{ - u32 value; - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - value = __iwl_read_direct32(__FILE__, __LINE__, priv, reg); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); - return value; -} - -#else -static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) -{ - u32 value; - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - value = _iwl_read_direct32(priv, reg); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); - return value; - -} -#endif - -static inline void _iwl_write_direct32(struct iwl_priv *priv, - u32 reg, u32 value) -{ - _iwl_write32(priv, reg, value); -} -static inline void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - if (!iwl_grab_nic_access(priv)) { - _iwl_write_direct32(priv, reg, value); - iwl_release_nic_access(priv); - } - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} - -static inline void iwl_write_reg_buf(struct iwl_priv *priv, - u32 reg, u32 len, u32 *values) -{ - u32 count = sizeof(u32); - - if ((priv != NULL) && (values != NULL)) { - for (; 0 < len; len -= count, reg += count, values++) - iwl_write_direct32(priv, reg, *values); - } -} - -static inline int _iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, - u32 mask, int timeout) -{ - int t = 0; - - do { - if ((iwl_read_direct32(priv, addr) & mask) == mask) - return t; - udelay(IWL_POLL_INTERVAL); - t += IWL_POLL_INTERVAL; - } while (t < timeout); - - return -ETIMEDOUT; -} - -#ifdef CONFIG_IWLWIFI_DEBUG -static inline int __iwl_poll_direct_bit(const char *f, u32 l, - struct iwl_priv *priv, - u32 addr, u32 mask, int timeout) -{ - int ret = _iwl_poll_direct_bit(priv, addr, mask, timeout); - - if (unlikely(ret == -ETIMEDOUT)) - IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) - " - "timedout - %s %d\n", addr, mask, f, l); - else - IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) = 0x%08X " - "- %s %d\n", addr, mask, ret, f, l); - return ret; -} -#define iwl_poll_direct_bit(priv, addr, mask, timeout) \ - __iwl_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout) -#else -#define iwl_poll_direct_bit _iwl_poll_direct_bit -#endif - -static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg) -{ - _iwl_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); - rmb(); - return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT); -} -static inline u32 iwl_read_prph(struct iwl_priv *priv, u32 reg) -{ - unsigned long reg_flags; - u32 val; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - val = _iwl_read_prph(priv, reg); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); - return val; -} - -static inline void _iwl_write_prph(struct iwl_priv *priv, - u32 addr, u32 val) -{ - _iwl_write_direct32(priv, HBUS_TARG_PRPH_WADDR, - ((addr & 0x0000FFFF) | (3 << 24))); - wmb(); - _iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); -} - -static inline void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) -{ - unsigned long reg_flags; +void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask); +void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask); - spin_lock_irqsave(&priv->reg_lock, reg_flags); - if (!iwl_grab_nic_access(priv)) { - _iwl_write_prph(priv, addr, val); - iwl_release_nic_access(priv); - } - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} +int iwl_poll_bit(struct iwl_priv *priv, u32 addr, + u32 bits, u32 mask, int timeout); +int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, + int timeout); -#define _iwl_set_bits_prph(priv, reg, mask) \ - _iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask)) +int iwl_grab_nic_access(struct iwl_priv *priv); +void iwl_release_nic_access(struct iwl_priv *priv); -static inline void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) -{ - unsigned long reg_flags; +u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg); +void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value); - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - _iwl_set_bits_prph(priv, reg, mask); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} -#define _iwl_set_bits_mask_prph(priv, reg, bits, mask) \ - _iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits)) +u32 iwl_read_prph(struct iwl_priv *priv, u32 reg); +void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val); +void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); +void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, + u32 bits, u32 mask); +void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); -static inline void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, - u32 bits, u32 mask) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - _iwl_set_bits_mask_prph(priv, reg, bits, mask); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} - -static inline void iwl_clear_bits_prph(struct iwl_priv - *priv, u32 reg, u32 mask) -{ - unsigned long reg_flags; - u32 val; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - val = _iwl_read_prph(priv, reg); - _iwl_write_prph(priv, reg, (val & ~mask)); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} - -static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) -{ - unsigned long reg_flags; - u32 value; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - - _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr); - rmb(); - value = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); - - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); - return value; -} - -static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - if (!iwl_grab_nic_access(priv)) { - _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); - wmb(); - _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val); - iwl_release_nic_access(priv); - } - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} - -static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr, - u32 len, u32 *values) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - if (!iwl_grab_nic_access(priv)) { - _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); - wmb(); - for (; 0 < len; len -= sizeof(u32), values++) - _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values); - - iwl_release_nic_access(priv); - } - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} +u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr); +void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val); #endif -- cgit v1.2.3-58-ga151 From 146095557b01cf5ff5d66554d96cbb8133d94eb9 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 5 Apr 2011 10:49:03 -0700 Subject: cfg80211: fix regulatory restore upon user hints When we restore regulatory settings its possible CRDA will not reply because of a bogus user entry. In this case the bogus entry will prevent any further processing on cfg80211 for regulatory domains even if we restore regulatory settings. To prevent this we suck out all pending requests when restoring regulatory settings and add them back into the queue after we have queued up the reset work. The impact of not having this applied is that a user with privileges can issue a userspace regulatory hint while we are disasocciating and this would prevent any further processing of regulatory domains. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 3332d5bce317..7b1a89b20ebf 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1744,6 +1744,8 @@ static void restore_regulatory_settings(bool reset_user) { char alpha2[2]; struct reg_beacon *reg_beacon, *btmp; + struct regulatory_request *reg_request, *tmp; + LIST_HEAD(tmp_reg_req_list); mutex_lock(&cfg80211_mutex); mutex_lock(®_mutex); @@ -1751,6 +1753,25 @@ static void restore_regulatory_settings(bool reset_user) reset_regdomains(); restore_alpha2(alpha2, reset_user); + /* + * If there's any pending requests we simply + * stash them to a temporary pending queue and + * add then after we've restored regulatory + * settings. + */ + spin_lock(®_requests_lock); + if (!list_empty(®_requests_list)) { + list_for_each_entry_safe(reg_request, tmp, + ®_requests_list, list) { + if (reg_request->initiator != + NL80211_REGDOM_SET_BY_USER) + continue; + list_del(®_request->list); + list_add_tail(®_request->list, &tmp_reg_req_list); + } + } + spin_unlock(®_requests_lock); + /* Clear beacon hints */ spin_lock_bh(®_pending_beacons_lock); if (!list_empty(®_pending_beacons)) { @@ -1785,8 +1806,31 @@ static void restore_regulatory_settings(bool reset_user) */ if (is_an_alpha2(alpha2)) regulatory_hint_user(user_alpha2); -} + if (list_empty(&tmp_reg_req_list)) + return; + + mutex_lock(&cfg80211_mutex); + mutex_lock(®_mutex); + + spin_lock(®_requests_lock); + list_for_each_entry_safe(reg_request, tmp, &tmp_reg_req_list, list) { + REG_DBG_PRINT("Adding request for country %c%c back " + "into the queue\n", + reg_request->alpha2[0], + reg_request->alpha2[1]); + list_del(®_request->list); + list_add_tail(®_request->list, ®_requests_list); + } + spin_unlock(®_requests_lock); + + mutex_unlock(®_mutex); + mutex_unlock(&cfg80211_mutex); + + REG_DBG_PRINT("Kicking the queue\n"); + + schedule_work(®_work); +} void regulatory_hint_disconnect(void) { -- cgit v1.2.3-58-ga151 From a90c7a313a1c5b4fc99f987a2ae8f92ab0ae35c7 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 5 Apr 2011 10:49:04 -0700 Subject: cfg80211: add a timer for invalid user reg hints We have no other option but to inform userspace that we have queued up their regulatory hint request when we are given one given that nl80211 operates atomically on user requests. The best we can do is accept the request, and add a delayed work item for processing failure and cancel it if we succeeed. Upon failure we restore the regulatory settings and ignore the user input. This fixes this reported bug: https://bugzilla.kernel.org/show_bug.cgi?id=28112 Reported-by: gregoryx.alagnou@intel.com Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 7b1a89b20ebf..2714379ce2d6 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -106,6 +106,9 @@ struct reg_beacon { static void reg_todo(struct work_struct *work); static DECLARE_WORK(reg_work, reg_todo); +static void reg_timeout_work(struct work_struct *work); +static DECLARE_DELAYED_WORK(reg_timeout, reg_timeout_work); + /* We keep a static world regulatory domain in case of the absence of CRDA */ static const struct ieee80211_regdomain world_regdom = { .n_reg_rules = 5, @@ -1330,6 +1333,9 @@ static void reg_set_request_processed(void) need_more_processing = true; spin_unlock(®_requests_lock); + if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) + cancel_delayed_work_sync(®_timeout); + if (need_more_processing) schedule_work(®_work); } @@ -1440,8 +1446,17 @@ static void reg_process_hint(struct regulatory_request *reg_request) r = __regulatory_hint(wiphy, reg_request); /* This is required so that the orig_* parameters are saved */ if (r == -EALREADY && wiphy && - wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) + wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { wiphy_update_regulatory(wiphy, initiator); + return; + } + + /* + * We only time out user hints, given that they should be the only + * source of bogus requests. + */ + if (reg_request->initiator == NL80211_REGDOM_SET_BY_USER) + schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); } /* @@ -2169,6 +2184,13 @@ out: mutex_unlock(®_mutex); } +static void reg_timeout_work(struct work_struct *work) +{ + REG_DBG_PRINT("Timeout while waiting for CRDA to reply, " + "restoring regulatory settings"); + restore_regulatory_settings(true); +} + int __init regulatory_init(void) { int err = 0; @@ -2222,6 +2244,7 @@ void /* __init_or_exit */ regulatory_exit(void) struct reg_beacon *reg_beacon, *btmp; cancel_work_sync(®_work); + cancel_delayed_work_sync(®_timeout); mutex_lock(&cfg80211_mutex); mutex_lock(®_mutex); -- cgit v1.2.3-58-ga151 From 48454079c2d4b9ee65c570a22c5fdfe1827996a4 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 00:22:30 -0300 Subject: Bluetooth: Create struct l2cap_chan struct l2cap_chan cames to create a clear separation between what properties and data belongs to the L2CAP channel and what belongs to the socket. By now we just fold the struct sock * in struct l2cap_chan as all the channel info is struct l2cap_pinfo today. In the next commits we will see a move of channel stuff to struct l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 18 ++- net/bluetooth/l2cap_core.c | 247 +++++++++++++++++++++++++++--------------- net/bluetooth/l2cap_sock.c | 6 +- 3 files changed, 175 insertions(+), 96 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 2b9ca0d5c4a0..6378bcc94e2b 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -276,9 +276,16 @@ struct l2cap_conn_param_update_rsp { #define L2CAP_CONN_PARAM_ACCEPTED 0x0000 #define L2CAP_CONN_PARAM_REJECTED 0x0001 -/* ----- L2CAP connections ----- */ +/* ----- L2CAP channels and connections ----- */ + +struct l2cap_chan { + struct sock *sk; + struct l2cap_chan *next_c; + struct l2cap_chan *prev_c; +}; + struct l2cap_chan_list { - struct sock *head; + struct l2cap_chan *head; rwlock_t lock; }; @@ -317,7 +324,7 @@ struct sock_del_list { #define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04 #define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08 -/* ----- L2CAP channel and socket info ----- */ +/* ----- L2CAP socket info ----- */ #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) #define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) #define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue) @@ -389,8 +396,7 @@ struct l2cap_pinfo { struct work_struct busy_work; struct srej_list srej_l; struct l2cap_conn *conn; - struct sock *next_c; - struct sock *prev_c; + struct l2cap_chan *chan; }; #define L2CAP_CONF_REQ_SENT 0x01 @@ -471,7 +477,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent); struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err); -void l2cap_chan_del(struct sock *sk, int err); +void l2cap_chan_del(struct l2cap_chan *chan, int err); int l2cap_do_connect(struct sock *sk); #endif /* __L2CAP_H */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c3cebed205cc..e49d8f7b80a5 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -74,58 +74,58 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); /* ---- L2CAP channels ---- */ -static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) +static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) { - struct sock *s; - for (s = l->head; s; s = l2cap_pi(s)->next_c) { - if (l2cap_pi(s)->dcid == cid) + struct l2cap_chan *c; + for (c = l->head; c; c = c->next_c) { + if (l2cap_pi(c->sk)->dcid == cid) break; } - return s; + return c; } -static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) +static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) { - struct sock *s; - for (s = l->head; s; s = l2cap_pi(s)->next_c) { - if (l2cap_pi(s)->scid == cid) + struct l2cap_chan *c; + for (c = l->head; c; c = c->next_c) { + if (l2cap_pi(c->sk)->scid == cid) break; } - return s; + return c; } /* Find channel with given SCID. * Returns locked socket */ -static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) +static inline struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) { - struct sock *s; + struct l2cap_chan *c; read_lock(&l->lock); - s = __l2cap_get_chan_by_scid(l, cid); - if (s) - bh_lock_sock(s); + c = __l2cap_get_chan_by_scid(l, cid); + if (c) + bh_lock_sock(c->sk); read_unlock(&l->lock); - return s; + return c; } -static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) +static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) { - struct sock *s; - for (s = l->head; s; s = l2cap_pi(s)->next_c) { - if (l2cap_pi(s)->ident == ident) + struct l2cap_chan *c; + for (c = l->head; c; c = c->next_c) { + if (l2cap_pi(c->sk)->ident == ident) break; } - return s; + return c; } -static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) +static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) { - struct sock *s; + struct l2cap_chan *c; read_lock(&l->lock); - s = __l2cap_get_chan_by_ident(l, ident); - if (s) - bh_lock_sock(s); + c = __l2cap_get_chan_by_ident(l, ident); + if (c) + bh_lock_sock(c->sk); read_unlock(&l->lock); - return s; + return c; } static u16 l2cap_alloc_cid(struct l2cap_chan_list *l) @@ -140,38 +140,52 @@ static u16 l2cap_alloc_cid(struct l2cap_chan_list *l) return 0; } -static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk) +static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) +{ + struct l2cap_chan *chan; + + chan = kzalloc(sizeof(*chan), GFP_ATOMIC); + if (!chan) + return NULL; + + chan->sk = sk; + + return chan; +} + +static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct l2cap_chan *chan) { - sock_hold(sk); + sock_hold(chan->sk); if (l->head) - l2cap_pi(l->head)->prev_c = sk; + l->head->prev_c = chan; - l2cap_pi(sk)->next_c = l->head; - l2cap_pi(sk)->prev_c = NULL; - l->head = sk; + chan->next_c = l->head; + chan->prev_c = NULL; + l->head = chan; } -static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk) +static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct l2cap_chan *chan) { - struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c; + struct l2cap_chan *next = chan->next_c, *prev = chan->prev_c; write_lock_bh(&l->lock); - if (sk == l->head) + if (chan == l->head) l->head = next; if (next) - l2cap_pi(next)->prev_c = prev; + next->prev_c = prev; if (prev) - l2cap_pi(prev)->next_c = next; + prev->next_c = next; write_unlock_bh(&l->lock); - __sock_put(sk); + __sock_put(chan->sk); } -static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) +static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) { struct l2cap_chan_list *l = &conn->chan_list; + struct sock *sk = chan->sk; BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid); @@ -203,13 +217,14 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; } - __l2cap_chan_link(l, sk); + __l2cap_chan_link(l, chan); } /* Delete channel. * Must be called on the locked socket. */ -void l2cap_chan_del(struct sock *sk, int err) +void l2cap_chan_del(struct l2cap_chan *chan, int err) { + struct sock *sk = chan->sk; struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct sock *parent = bt_sk(sk)->parent; @@ -219,7 +234,7 @@ void l2cap_chan_del(struct sock *sk, int err) if (conn) { /* Unlink from channel list */ - l2cap_chan_unlink(&conn->chan_list, sk); + l2cap_chan_unlink(&conn->chan_list, chan); l2cap_pi(sk)->conn = NULL; hci_conn_put(conn->hcon); } @@ -253,6 +268,8 @@ void l2cap_chan_del(struct sock *sk, int err) kfree(l); } } + + kfree(chan); } static inline u8 l2cap_get_auth_type(struct sock *sk) @@ -487,7 +504,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) { struct l2cap_chan_list *l = &conn->chan_list; struct sock_del_list del, *tmp1, *tmp2; - struct sock *sk; + struct l2cap_chan *chan; BT_DBG("conn %p", conn); @@ -495,7 +512,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) read_lock(&l->lock); - for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + for (chan = l->head; chan; chan = chan->next_c) { + struct sock *sk = chan->sk; bh_lock_sock(sk); if (sk->sk_type != SOCK_SEQPACKET && @@ -622,6 +640,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) { struct l2cap_chan_list *list = &conn->chan_list; struct sock *parent, *uninitialized_var(sk); + struct l2cap_chan *chan; BT_DBG(""); @@ -641,6 +660,12 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) if (!sk) goto clean; + chan = l2cap_chan_alloc(sk); + if (!chan) { + l2cap_sock_kill(sk); + goto clean; + } + write_lock_bh(&list->lock); hci_conn_hold(conn->hcon); @@ -651,7 +676,9 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) bt_accept_enqueue(parent, sk); - __l2cap_chan_add(conn, sk); + __l2cap_chan_add(conn, chan); + + l2cap_pi(sk)->chan = chan; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); @@ -667,7 +694,7 @@ clean: static void l2cap_conn_ready(struct l2cap_conn *conn) { struct l2cap_chan_list *l = &conn->chan_list; - struct sock *sk; + struct l2cap_chan *chan; BT_DBG("conn %p", conn); @@ -676,7 +703,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) read_lock(&l->lock); - for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + for (chan = l->head; chan; chan = chan->next_c) { + struct sock *sk = chan->sk; bh_lock_sock(sk); if (conn->hcon->type == LE_LINK) { @@ -703,13 +731,14 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) { struct l2cap_chan_list *l = &conn->chan_list; - struct sock *sk; + struct l2cap_chan *chan; BT_DBG("conn %p", conn); read_lock(&l->lock); - for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + for (chan = l->head; chan; chan = chan->next_c) { + struct sock *sk = chan->sk; if (l2cap_pi(sk)->force_reliable) sk->sk_err = err; } @@ -768,6 +797,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) static void l2cap_conn_del(struct hci_conn *hcon, int err) { struct l2cap_conn *conn = hcon->l2cap_data; + struct l2cap_chan *chan; struct sock *sk; if (!conn) @@ -778,9 +808,10 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) kfree_skb(conn->rx_skb); /* Kill channels */ - while ((sk = conn->chan_list.head)) { + while ((chan = conn->chan_list.head)) { + sk = chan->sk; bh_lock_sock(sk); - l2cap_chan_del(sk, err); + l2cap_chan_del(chan, err); bh_unlock_sock(sk); l2cap_sock_kill(sk); } @@ -792,11 +823,11 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) kfree(conn); } -static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) +static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) { struct l2cap_chan_list *l = &conn->chan_list; write_lock_bh(&l->lock); - __l2cap_chan_add(conn, sk); + __l2cap_chan_add(conn, chan); write_unlock_bh(&l->lock); } @@ -837,6 +868,7 @@ int l2cap_do_connect(struct sock *sk) bdaddr_t *src = &bt_sk(sk)->src; bdaddr_t *dst = &bt_sk(sk)->dst; struct l2cap_conn *conn; + struct l2cap_chan *chan; struct hci_conn *hcon; struct hci_dev *hdev; __u8 auth_type; @@ -872,10 +904,19 @@ int l2cap_do_connect(struct sock *sk) goto done; } + chan = l2cap_chan_alloc(sk); + if (!chan) { + hci_conn_put(hcon); + err = -ENOMEM; + goto done; + } + /* Update source addr of the socket */ bacpy(src, conn->src); - l2cap_chan_add(conn, sk); + l2cap_chan_add(conn, chan); + + l2cap_pi(sk)->chan = chan; sk->sk_state = BT_CONNECT; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); @@ -1387,12 +1428,13 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) { struct l2cap_chan_list *l = &conn->chan_list; struct sk_buff *nskb; - struct sock *sk; + struct l2cap_chan *chan; BT_DBG("conn %p", conn); read_lock(&l->lock); - for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + for (chan = l->head; chan; chan = chan->next_c) { + struct sock *sk = chan->sk; if (sk->sk_type != SOCK_RAW) continue; @@ -1976,6 +2018,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd struct l2cap_chan_list *list = &conn->chan_list; struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; struct l2cap_conn_rsp rsp; + struct l2cap_chan *chan; struct sock *parent, *sk = NULL; int result, status = L2CAP_CS_NO_INFO; @@ -2013,6 +2056,12 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd if (!sk) goto response; + chan = l2cap_chan_alloc(sk); + if (!chan) { + l2cap_sock_kill(sk); + goto response; + } + write_lock_bh(&list->lock); /* Check if we already have channel with that dcid */ @@ -2033,7 +2082,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd bt_accept_enqueue(parent, sk); - __l2cap_chan_add(conn, sk); + __l2cap_chan_add(conn, chan); + + l2cap_pi(sk)->chan = chan; + dcid = l2cap_pi(sk)->scid; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); @@ -2105,6 +2157,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd { struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; u16 scid, dcid, result, status; + struct l2cap_chan *chan; struct sock *sk; u8 req[128]; @@ -2116,15 +2169,17 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status); if (scid) { - sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); - if (!sk) + chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); + if (!chan) return -EFAULT; } else { - sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident); - if (!sk) + chan = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident); + if (!chan) return -EFAULT; } + sk = chan->sk; + switch (result) { case L2CAP_CR_SUCCESS: sk->sk_state = BT_CONFIG; @@ -2155,7 +2210,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd break; } - l2cap_chan_del(sk, ECONNREFUSED); + l2cap_chan_del(chan, ECONNREFUSED); break; } @@ -2179,6 +2234,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; u16 dcid, flags; u8 rsp[64]; + struct l2cap_chan *chan; struct sock *sk; int len; @@ -2187,10 +2243,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); - sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid); - if (!sk) + chan = l2cap_get_chan_by_scid(&conn->chan_list, dcid); + if (!chan) return -ENOENT; + sk = chan->sk; + if (sk->sk_state != BT_CONFIG) { struct l2cap_cmd_rej rej; @@ -2269,6 +2327,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr { struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; u16 scid, flags, result; + struct l2cap_chan *chan; struct sock *sk; int len = cmd->len - sizeof(*rsp); @@ -2279,10 +2338,12 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", scid, flags, result); - sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); - if (!sk) + chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); + if (!chan) return 0; + sk = chan->sk; + switch (result) { case L2CAP_CONF_SUCCESS: l2cap_conf_rfc_get(sk, rsp->data, len); @@ -2349,6 +2410,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; struct l2cap_disconn_rsp rsp; u16 dcid, scid; + struct l2cap_chan *chan; struct sock *sk; scid = __le16_to_cpu(req->scid); @@ -2356,10 +2418,12 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); - sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid); - if (!sk) + chan = l2cap_get_chan_by_scid(&conn->chan_list, dcid); + if (!chan) return 0; + sk = chan->sk; + rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); @@ -2375,7 +2439,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd return 0; } - l2cap_chan_del(sk, ECONNRESET); + l2cap_chan_del(chan, ECONNRESET); bh_unlock_sock(sk); l2cap_sock_kill(sk); @@ -2386,6 +2450,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd { struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; u16 dcid, scid; + struct l2cap_chan *chan; struct sock *sk; scid = __le16_to_cpu(rsp->scid); @@ -2393,10 +2458,12 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); - sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); - if (!sk) + chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); + if (!chan) return 0; + sk = chan->sk; + /* don't delete l2cap channel if sk is owned by user */ if (sock_owned_by_user(sk)) { sk->sk_state = BT_DISCONN; @@ -2406,7 +2473,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd return 0; } - l2cap_chan_del(sk, 0); + l2cap_chan_del(chan, 0); bh_unlock_sock(sk); l2cap_sock_kill(sk); @@ -3538,18 +3605,20 @@ drop: static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) { + struct l2cap_chan *chan; struct sock *sk; struct l2cap_pinfo *pi; u16 control; u8 tx_seq; int len; - sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); - if (!sk) { + chan = l2cap_get_chan_by_scid(&conn->chan_list, cid); + if (!chan) { BT_DBG("unknown cid 0x%4.4x", cid); goto drop; } + sk = chan->sk; pi = l2cap_pi(sk); BT_DBG("sk %p, len %d", sk, skb->len); @@ -3788,7 +3857,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) { struct l2cap_chan_list *l; struct l2cap_conn *conn = hcon->l2cap_data; - struct sock *sk; + struct l2cap_chan *chan; if (!conn) return 0; @@ -3799,7 +3868,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) read_lock(&l->lock); - for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + for (chan = l->head; chan; chan = chan->next_c) { + struct sock *sk = chan->sk; bh_lock_sock(sk); if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) { @@ -3872,7 +3942,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl if (!(flags & ACL_CONT)) { struct l2cap_hdr *hdr; - struct sock *sk; + struct l2cap_chan *chan; u16 cid; int len; @@ -3910,18 +3980,21 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl goto drop; } - sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); + chan = l2cap_get_chan_by_scid(&conn->chan_list, cid); - if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) { - BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)", - len, l2cap_pi(sk)->imtu); - bh_unlock_sock(sk); - l2cap_conn_unreliable(conn, ECOMM); - goto drop; - } + if (chan && chan->sk) { + struct sock *sk = chan->sk; - if (sk) + if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) { + BT_ERR("Frame exceeding recv MTU (len %d, " + "MTU %d)", len, + l2cap_pi(sk)->imtu); + bh_unlock_sock(sk); + l2cap_conn_unreliable(conn, ECOMM); + goto drop; + } bh_unlock_sock(sk); + } /* Allocate skb for the complete frame (with header) */ conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index f77308e63e58..7df81181a119 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -902,7 +902,7 @@ void __l2cap_sock_close(struct sock *sk, int reason) l2cap_sock_set_timer(sk, sk->sk_sndtimeo); l2cap_send_disconn_req(conn, sk, reason); } else - l2cap_chan_del(sk, reason); + l2cap_chan_del(l2cap_pi(sk)->chan, reason); break; case BT_CONNECT2: @@ -925,12 +925,12 @@ void __l2cap_sock_close(struct sock *sk, int reason) L2CAP_CONN_RSP, sizeof(rsp), &rsp); } - l2cap_chan_del(sk, reason); + l2cap_chan_del(l2cap_pi(sk)->chan, reason); break; case BT_CONNECT: case BT_DISCONN: - l2cap_chan_del(sk, reason); + l2cap_chan_del(l2cap_pi(sk)->chan, reason); break; default: -- cgit v1.2.3-58-ga151 From baa7e1fa6d2870462bd744df1c6ddbd497fe86d6 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Thu, 31 Mar 2011 16:17:41 -0300 Subject: Bluetooth: Use struct list_head for L2CAP channels list Use a well known Kernel API is always a good idea than implement your own list. In the future we might use RCU on this list. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 12 +-- net/bluetooth/l2cap_core.c | 188 +++++++++++++++++++----------------------- 2 files changed, 88 insertions(+), 112 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 6378bcc94e2b..ddf4bc56a5b5 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -277,16 +277,9 @@ struct l2cap_conn_param_update_rsp { #define L2CAP_CONN_PARAM_REJECTED 0x0001 /* ----- L2CAP channels and connections ----- */ - struct l2cap_chan { struct sock *sk; - struct l2cap_chan *next_c; - struct l2cap_chan *prev_c; -}; - -struct l2cap_chan_list { - struct l2cap_chan *head; - rwlock_t lock; + struct list_head list; }; struct l2cap_conn { @@ -312,7 +305,8 @@ struct l2cap_conn { __u8 disc_reason; - struct l2cap_chan_list chan_list; + struct list_head chan_l; + rwlock_t chan_lock; }; struct sock_del_list { diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index e49d8f7b80a5..0dbbaf394c13 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -74,66 +74,75 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); /* ---- L2CAP channels ---- */ -static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) +static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) { struct l2cap_chan *c; - for (c = l->head; c; c = c->next_c) { - if (l2cap_pi(c->sk)->dcid == cid) - break; + + list_for_each_entry(c, &conn->chan_l, list) { + struct sock *s = c->sk; + if (l2cap_pi(s)->dcid == cid) + return c; } - return c; + return NULL; + } -static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) +static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) { struct l2cap_chan *c; - for (c = l->head; c; c = c->next_c) { - if (l2cap_pi(c->sk)->scid == cid) - break; + + list_for_each_entry(c, &conn->chan_l, list) { + struct sock *s = c->sk; + if (l2cap_pi(s)->scid == cid) + return c; } - return c; + return NULL; } /* Find channel with given SCID. * Returns locked socket */ -static inline struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) +static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) { struct l2cap_chan *c; - read_lock(&l->lock); - c = __l2cap_get_chan_by_scid(l, cid); + + read_lock(&conn->chan_lock); + c = __l2cap_get_chan_by_scid(conn, cid); if (c) bh_lock_sock(c->sk); - read_unlock(&l->lock); + read_unlock(&conn->chan_lock); return c; } -static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) +static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) { struct l2cap_chan *c; - for (c = l->head; c; c = c->next_c) { - if (l2cap_pi(c->sk)->ident == ident) - break; + + list_for_each_entry(c, &conn->chan_l, list) { + struct sock *s = c->sk; + if (l2cap_pi(s)->ident == ident) + return c; } - return c; + return NULL; } -static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) +static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) { struct l2cap_chan *c; - read_lock(&l->lock); - c = __l2cap_get_chan_by_ident(l, ident); + + read_lock(&conn->chan_lock); + c = __l2cap_get_chan_by_ident(conn, ident); if (c) bh_lock_sock(c->sk); - read_unlock(&l->lock); + read_unlock(&conn->chan_lock); return c; } -static u16 l2cap_alloc_cid(struct l2cap_chan_list *l) +static u16 l2cap_alloc_cid(struct l2cap_conn *conn) { u16 cid = L2CAP_CID_DYN_START; for (; cid < L2CAP_CID_DYN_END; cid++) { - if (!__l2cap_get_chan_by_scid(l, cid)) + if (!__l2cap_get_chan_by_scid(conn, cid)) return cid; } @@ -153,38 +162,8 @@ static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) return chan; } -static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct l2cap_chan *chan) -{ - sock_hold(chan->sk); - - if (l->head) - l->head->prev_c = chan; - - chan->next_c = l->head; - chan->prev_c = NULL; - l->head = chan; -} - -static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct l2cap_chan *chan) -{ - struct l2cap_chan *next = chan->next_c, *prev = chan->prev_c; - - write_lock_bh(&l->lock); - if (chan == l->head) - l->head = next; - - if (next) - next->prev_c = prev; - if (prev) - prev->next_c = next; - write_unlock_bh(&l->lock); - - __sock_put(chan->sk); -} - static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) { - struct l2cap_chan_list *l = &conn->chan_list; struct sock *sk = chan->sk; BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, @@ -202,7 +181,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA; } else { /* Alloc CID for connection-oriented socket */ - l2cap_pi(sk)->scid = l2cap_alloc_cid(l); + l2cap_pi(sk)->scid = l2cap_alloc_cid(conn); l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; } } else if (sk->sk_type == SOCK_DGRAM) { @@ -217,7 +196,9 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; } - __l2cap_chan_link(l, chan); + sock_hold(sk); + + list_add(&chan->list, &conn->chan_l); } /* Delete channel. @@ -233,8 +214,12 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) BT_DBG("sk %p, conn %p, err %d", sk, conn, err); if (conn) { - /* Unlink from channel list */ - l2cap_chan_unlink(&conn->chan_list, chan); + /* Delete from channel list */ + write_lock_bh(&conn->chan_lock); + list_del(&chan->list); + write_unlock_bh(&conn->chan_lock); + __sock_put(sk); + l2cap_pi(sk)->conn = NULL; hci_conn_put(conn->hcon); } @@ -502,7 +487,6 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err) /* ---- L2CAP connections ---- */ static void l2cap_conn_start(struct l2cap_conn *conn) { - struct l2cap_chan_list *l = &conn->chan_list; struct sock_del_list del, *tmp1, *tmp2; struct l2cap_chan *chan; @@ -510,10 +494,11 @@ static void l2cap_conn_start(struct l2cap_conn *conn) INIT_LIST_HEAD(&del.list); - read_lock(&l->lock); + read_lock(&conn->chan_lock); - for (chan = l->head; chan; chan = chan->next_c) { + list_for_each_entry(chan, &conn->chan_l, list) { struct sock *sk = chan->sk; + bh_lock_sock(sk); if (sk->sk_type != SOCK_SEQPACKET && @@ -593,7 +578,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) bh_unlock_sock(sk); } - read_unlock(&l->lock); + read_unlock(&conn->chan_lock); list_for_each_entry_safe(tmp1, tmp2, &del.list, list) { bh_lock_sock(tmp1->sk); @@ -638,7 +623,6 @@ static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src) static void l2cap_le_conn_ready(struct l2cap_conn *conn) { - struct l2cap_chan_list *list = &conn->chan_list; struct sock *parent, *uninitialized_var(sk); struct l2cap_chan *chan; @@ -666,11 +650,12 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) goto clean; } - write_lock_bh(&list->lock); + write_lock_bh(&conn->chan_lock); hci_conn_hold(conn->hcon); l2cap_sock_init(sk, parent); + bacpy(&bt_sk(sk)->src, conn->src); bacpy(&bt_sk(sk)->dst, conn->dst); @@ -685,7 +670,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) sk->sk_state = BT_CONNECTED; parent->sk_data_ready(parent, 0); - write_unlock_bh(&list->lock); + write_unlock_bh(&conn->chan_lock); clean: bh_unlock_sock(parent); @@ -693,7 +678,6 @@ clean: static void l2cap_conn_ready(struct l2cap_conn *conn) { - struct l2cap_chan_list *l = &conn->chan_list; struct l2cap_chan *chan; BT_DBG("conn %p", conn); @@ -701,10 +685,11 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) if (!conn->hcon->out && conn->hcon->type == LE_LINK) l2cap_le_conn_ready(conn); - read_lock(&l->lock); + read_lock(&conn->chan_lock); - for (chan = l->head; chan; chan = chan->next_c) { + list_for_each_entry(chan, &conn->chan_l, list) { struct sock *sk = chan->sk; + bh_lock_sock(sk); if (conn->hcon->type == LE_LINK) { @@ -724,26 +709,26 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) bh_unlock_sock(sk); } - read_unlock(&l->lock); + read_unlock(&conn->chan_lock); } /* Notify sockets that we cannot guaranty reliability anymore */ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) { - struct l2cap_chan_list *l = &conn->chan_list; struct l2cap_chan *chan; BT_DBG("conn %p", conn); - read_lock(&l->lock); + read_lock(&conn->chan_lock); - for (chan = l->head; chan; chan = chan->next_c) { + list_for_each_entry(chan, &conn->chan_l, list) { struct sock *sk = chan->sk; + if (l2cap_pi(sk)->force_reliable) sk->sk_err = err; } - read_unlock(&l->lock); + read_unlock(&conn->chan_lock); } static void l2cap_info_timeout(unsigned long arg) @@ -783,7 +768,9 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) conn->feat_mask = 0; spin_lock_init(&conn->lock); - rwlock_init(&conn->chan_list.lock); + rwlock_init(&conn->chan_lock); + + INIT_LIST_HEAD(&conn->chan_l); if (hcon->type != LE_LINK) setup_timer(&conn->info_timer, l2cap_info_timeout, @@ -797,7 +784,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) static void l2cap_conn_del(struct hci_conn *hcon, int err) { struct l2cap_conn *conn = hcon->l2cap_data; - struct l2cap_chan *chan; + struct l2cap_chan *chan, *l; struct sock *sk; if (!conn) @@ -808,7 +795,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) kfree_skb(conn->rx_skb); /* Kill channels */ - while ((chan = conn->chan_list.head)) { + list_for_each_entry_safe(chan, l, &conn->chan_l, list) { sk = chan->sk; bh_lock_sock(sk); l2cap_chan_del(chan, err); @@ -825,10 +812,9 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) { - struct l2cap_chan_list *l = &conn->chan_list; - write_lock_bh(&l->lock); + write_lock_bh(&conn->chan_lock); __l2cap_chan_add(conn, chan); - write_unlock_bh(&l->lock); + write_unlock_bh(&conn->chan_lock); } /* ---- Socket interface ---- */ @@ -1426,14 +1412,13 @@ static void l2cap_chan_ready(struct sock *sk) /* Copy frame to all raw sockets on that connection */ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) { - struct l2cap_chan_list *l = &conn->chan_list; struct sk_buff *nskb; struct l2cap_chan *chan; BT_DBG("conn %p", conn); - read_lock(&l->lock); - for (chan = l->head; chan; chan = chan->next_c) { + read_lock(&conn->chan_lock); + list_for_each_entry(chan, &conn->chan_l, list) { struct sock *sk = chan->sk; if (sk->sk_type != SOCK_RAW) continue; @@ -1448,7 +1433,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) if (sock_queue_rcv_skb(sk, nskb)) kfree_skb(nskb); } - read_unlock(&l->lock); + read_unlock(&conn->chan_lock); } /* ---- L2CAP signalling commands ---- */ @@ -2015,7 +2000,6 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) { - struct l2cap_chan_list *list = &conn->chan_list; struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; struct l2cap_conn_rsp rsp; struct l2cap_chan *chan; @@ -2062,11 +2046,11 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd goto response; } - write_lock_bh(&list->lock); + write_lock_bh(&conn->chan_lock); /* Check if we already have channel with that dcid */ - if (__l2cap_get_chan_by_dcid(list, scid)) { - write_unlock_bh(&list->lock); + if (__l2cap_get_chan_by_dcid(conn, scid)) { + write_unlock_bh(&conn->chan_lock); sock_set_flag(sk, SOCK_ZAPPED); l2cap_sock_kill(sk); goto response; @@ -2115,7 +2099,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd status = L2CAP_CS_NO_INFO; } - write_unlock_bh(&list->lock); + write_unlock_bh(&conn->chan_lock); response: bh_unlock_sock(parent); @@ -2169,11 +2153,11 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status); if (scid) { - chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); + chan = l2cap_get_chan_by_scid(conn, scid); if (!chan) return -EFAULT; } else { - chan = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident); + chan = l2cap_get_chan_by_ident(conn, cmd->ident); if (!chan) return -EFAULT; } @@ -2243,7 +2227,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); - chan = l2cap_get_chan_by_scid(&conn->chan_list, dcid); + chan = l2cap_get_chan_by_scid(conn, dcid); if (!chan) return -ENOENT; @@ -2338,7 +2322,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", scid, flags, result); - chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); + chan = l2cap_get_chan_by_scid(conn, scid); if (!chan) return 0; @@ -2418,7 +2402,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); - chan = l2cap_get_chan_by_scid(&conn->chan_list, dcid); + chan = l2cap_get_chan_by_scid(conn, dcid); if (!chan) return 0; @@ -2458,7 +2442,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); - chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); + chan = l2cap_get_chan_by_scid(conn, scid); if (!chan) return 0; @@ -3612,7 +3596,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk u8 tx_seq; int len; - chan = l2cap_get_chan_by_scid(&conn->chan_list, cid); + chan = l2cap_get_chan_by_scid(conn, cid); if (!chan) { BT_DBG("unknown cid 0x%4.4x", cid); goto drop; @@ -3855,21 +3839,19 @@ static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt) static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) { - struct l2cap_chan_list *l; struct l2cap_conn *conn = hcon->l2cap_data; struct l2cap_chan *chan; if (!conn) return 0; - l = &conn->chan_list; - BT_DBG("conn %p", conn); - read_lock(&l->lock); + read_lock(&conn->chan_lock); - for (chan = l->head; chan; chan = chan->next_c) { + list_for_each_entry(chan, &conn->chan_l, list) { struct sock *sk = chan->sk; + bh_lock_sock(sk); if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) { @@ -3923,7 +3905,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) bh_unlock_sock(sk); } - read_unlock(&l->lock); + read_unlock(&conn->chan_lock); return 0; } @@ -3980,7 +3962,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl goto drop; } - chan = l2cap_get_chan_by_scid(&conn->chan_list, cid); + chan = l2cap_get_chan_by_scid(conn, cid); if (chan && chan->sk) { struct sock *sk = chan->sk; -- cgit v1.2.3-58-ga151 From 820ffdb3d25f74fbd553453f461709d52dfa72a2 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 1 Apr 2011 00:35:21 -0300 Subject: Bluetooth: Remove struct del_list As we use struct list_head to keep L2CAP channels list the workaround with del_list is not needed anymore. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 5 ----- net/bluetooth/l2cap_core.c | 24 +++++++----------------- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index ddf4bc56a5b5..d24b51c3ff8c 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -309,11 +309,6 @@ struct l2cap_conn { rwlock_t chan_lock; }; -struct sock_del_list { - struct sock *sk; - struct list_head list; -}; - #define L2CAP_INFO_CL_MTU_REQ_SENT 0x01 #define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04 #define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08 diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 0dbbaf394c13..b0aaaa9cf00e 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -487,16 +487,13 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err) /* ---- L2CAP connections ---- */ static void l2cap_conn_start(struct l2cap_conn *conn) { - struct sock_del_list del, *tmp1, *tmp2; - struct l2cap_chan *chan; + struct l2cap_chan *chan, *tmp; BT_DBG("conn %p", conn); - INIT_LIST_HEAD(&del.list); - read_lock(&conn->chan_lock); - list_for_each_entry(chan, &conn->chan_l, list) { + list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { struct sock *sk = chan->sk; bh_lock_sock(sk); @@ -520,10 +517,11 @@ static void l2cap_conn_start(struct l2cap_conn *conn) conn->feat_mask) && l2cap_pi(sk)->conf_state & L2CAP_CONF_STATE2_DEVICE) { - tmp1 = kzalloc(sizeof(struct sock_del_list), - GFP_ATOMIC); - tmp1->sk = sk; - list_add_tail(&tmp1->list, &del.list); + /* __l2cap_sock_close() calls list_del(chan) + * so release the lock */ + read_unlock_bh(&conn->chan_lock); + __l2cap_sock_close(sk, ECONNRESET); + read_lock_bh(&conn->chan_lock); bh_unlock_sock(sk); continue; } @@ -579,14 +577,6 @@ static void l2cap_conn_start(struct l2cap_conn *conn) } read_unlock(&conn->chan_lock); - - list_for_each_entry_safe(tmp1, tmp2, &del.list, list) { - bh_lock_sock(tmp1->sk); - __l2cap_sock_close(tmp1->sk, ECONNRESET); - bh_unlock_sock(tmp1->sk); - list_del(&tmp1->list); - kfree(tmp1); - } } /* Find socket with cid and source bdaddr. -- cgit v1.2.3-58-ga151 From fc7f8a7ed4543853a99852ca405ea71fabe78946 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 13:59:37 -0300 Subject: Bluetooth: Move ident to struct l2cap_chan ident is chan property, no need to reside on socket. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 4 ++-- net/bluetooth/l2cap_core.c | 38 +++++++++++++++++++------------------- net/bluetooth/l2cap_sock.c | 4 ++-- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index d24b51c3ff8c..81829e5c407d 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -279,6 +279,8 @@ struct l2cap_conn_param_update_rsp { /* ----- L2CAP channels and connections ----- */ struct l2cap_chan { struct sock *sk; + __u8 ident; + struct list_head list; }; @@ -363,8 +365,6 @@ struct l2cap_pinfo { __u16 partial_sdu_len; struct sk_buff *sdu; - __u8 ident; - __u8 tx_win; __u8 max_tx; __u8 remote_tx_win; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b0aaaa9cf00e..6020e1e2f500 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -118,8 +118,7 @@ static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 struct l2cap_chan *c; list_for_each_entry(c, &conn->chan_l, list) { - struct sock *s = c->sk; - if (l2cap_pi(s)->ident == ident) + if (c->ident == ident) return c; } return NULL; @@ -410,8 +409,9 @@ static inline int __l2cap_no_conn_pending(struct sock *sk) return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND); } -static void l2cap_do_start(struct sock *sk) +static void l2cap_do_start(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; struct l2cap_conn *conn = l2cap_pi(sk)->conn; if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { @@ -423,11 +423,11 @@ static void l2cap_do_start(struct sock *sk) req.scid = cpu_to_le16(l2cap_pi(sk)->scid); req.psm = l2cap_pi(sk)->psm; - l2cap_pi(sk)->ident = l2cap_get_ident(conn); + chan->ident = l2cap_get_ident(conn); l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; - l2cap_send_cmd(conn, l2cap_pi(sk)->ident, - L2CAP_CONN_REQ, sizeof(req), &req); + l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, + sizeof(req), &req); } } else { struct l2cap_info_req req; @@ -529,11 +529,11 @@ static void l2cap_conn_start(struct l2cap_conn *conn) req.scid = cpu_to_le16(l2cap_pi(sk)->scid); req.psm = l2cap_pi(sk)->psm; - l2cap_pi(sk)->ident = l2cap_get_ident(conn); + chan->ident = l2cap_get_ident(conn); l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; - l2cap_send_cmd(conn, l2cap_pi(sk)->ident, - L2CAP_CONN_REQ, sizeof(req), &req); + l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, + sizeof(req), &req); } else if (sk->sk_state == BT_CONNECT2) { struct l2cap_conn_rsp rsp; @@ -558,8 +558,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); } - l2cap_send_cmd(conn, l2cap_pi(sk)->ident, - L2CAP_CONN_RSP, sizeof(rsp), &rsp); + l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, + sizeof(rsp), &rsp); if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT || rsp.result != L2CAP_CR_SUCCESS) { @@ -694,7 +694,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) sk->sk_state = BT_CONNECTED; sk->sk_state_change(sk); } else if (sk->sk_state == BT_CONNECT) - l2cap_do_start(sk); + l2cap_do_start(chan); bh_unlock_sock(sk); } @@ -904,7 +904,7 @@ int l2cap_do_connect(struct sock *sk) if (l2cap_check_security(sk)) sk->sk_state = BT_CONNECTED; } else - l2cap_do_start(sk); + l2cap_do_start(chan); } err = 0; @@ -2064,7 +2064,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd l2cap_sock_set_timer(sk, sk->sk_sndtimeo); - l2cap_pi(sk)->ident = cmd->ident; + chan->ident = cmd->ident; if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { if (l2cap_check_security(sk)) { @@ -2157,7 +2157,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd switch (result) { case L2CAP_CR_SUCCESS: sk->sk_state = BT_CONFIG; - l2cap_pi(sk)->ident = 0; + chan->ident = 0; l2cap_pi(sk)->dcid = dcid; l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND; @@ -3862,10 +3862,10 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) req.scid = cpu_to_le16(l2cap_pi(sk)->scid); req.psm = l2cap_pi(sk)->psm; - l2cap_pi(sk)->ident = l2cap_get_ident(conn); + chan->ident = l2cap_get_ident(conn); l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; - l2cap_send_cmd(conn, l2cap_pi(sk)->ident, + l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); } else { l2cap_sock_clear_timer(sk); @@ -3888,8 +3888,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.result = cpu_to_le16(result); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); - l2cap_send_cmd(conn, l2cap_pi(sk)->ident, - L2CAP_CONN_RSP, sizeof(rsp), &rsp); + l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, + sizeof(rsp), &rsp); } bh_unlock_sock(sk); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 7df81181a119..cad4bc7d36b2 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -818,7 +818,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); - l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident, + l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) { @@ -921,7 +921,7 @@ void __l2cap_sock_close(struct sock *sk, int reason) rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.result = cpu_to_le16(result); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); - l2cap_send_cmd(conn, l2cap_pi(sk)->ident, + l2cap_send_cmd(conn, l2cap_pi(sk)->chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); } -- cgit v1.2.3-58-ga151 From 73ffa904b78287f6acf8797e040150aa26a4af4a Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 14:16:54 -0300 Subject: Bluetooth: Move conf_{req,rsp} stuff to struct l2cap_chan They are also l2cap_chan specific. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 11 +++++---- net/bluetooth/l2cap_core.c | 55 ++++++++++++++++++++++--------------------- net/bluetooth/l2cap_sock.c | 8 +++---- 3 files changed, 38 insertions(+), 36 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 81829e5c407d..bf918283712a 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -281,6 +281,11 @@ struct l2cap_chan { struct sock *sk; __u8 ident; + __u8 conf_req[64]; + __u8 conf_len; + __u8 num_conf_req; + __u8 num_conf_rsp; + struct list_head list; }; @@ -337,8 +342,6 @@ struct l2cap_pinfo { __u16 omtu; __u16 flush_to; __u8 mode; - __u8 num_conf_req; - __u8 num_conf_rsp; __u8 fcs; __u8 sec_level; @@ -346,8 +349,6 @@ struct l2cap_pinfo { __u8 force_reliable; __u8 flushable; - __u8 conf_req[64]; - __u8 conf_len; __u8 conf_state; __u16 conn_state; @@ -447,7 +448,7 @@ void l2cap_cleanup_sockets(void); u8 l2cap_get_ident(struct l2cap_conn *conn); void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data); -int l2cap_build_conf_req(struct sock *sk, void *data); +int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); int __l2cap_wait_ack(struct sock *sk); struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 6020e1e2f500..cb849b51632f 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -569,8 +569,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(sk, buf), buf); - l2cap_pi(sk)->num_conf_req++; + l2cap_build_conf_req(chan, buf), buf); + chan->num_conf_req++; } bh_unlock_sock(sk); @@ -1598,8 +1598,9 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) } } -int l2cap_build_conf_req(struct sock *sk, void *data) +int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); struct l2cap_conf_req *req = data; struct l2cap_conf_rfc rfc = { .mode = pi->mode }; @@ -1607,7 +1608,7 @@ int l2cap_build_conf_req(struct sock *sk, void *data) BT_DBG("sk %p", sk); - if (pi->num_conf_req || pi->num_conf_rsp) + if (chan->num_conf_req || chan->num_conf_rsp) goto done; switch (pi->mode) { @@ -1696,20 +1697,20 @@ done: return ptr - data; } -static int l2cap_parse_conf_req(struct sock *sk, void *data) +static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct l2cap_conf_rsp *rsp = data; void *ptr = rsp->data; - void *req = pi->conf_req; - int len = pi->conf_len; + void *req = chan->conf_req; + int len = chan->conf_len; int type, hint, olen; unsigned long val; struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; u16 mtu = L2CAP_DEFAULT_MTU; u16 result = L2CAP_CONF_SUCCESS; - BT_DBG("sk %p", sk); + BT_DBG("chan %p", chan); while (len >= L2CAP_CONF_OPT_SIZE) { len -= l2cap_get_conf_opt(&req, &type, &olen, &val); @@ -1750,7 +1751,7 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data) } } - if (pi->num_conf_rsp || pi->num_conf_req > 1) + if (chan->num_conf_rsp || chan->num_conf_req > 1) goto done; switch (pi->mode) { @@ -1773,7 +1774,7 @@ done: result = L2CAP_CONF_UNACCEPT; rfc.mode = pi->mode; - if (pi->num_conf_rsp == 1) + if (chan->num_conf_rsp == 1) return -ECONNREFUSED; l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, @@ -1992,7 +1993,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd { struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; struct l2cap_conn_rsp rsp; - struct l2cap_chan *chan; + struct l2cap_chan *chan = NULL; struct sock *parent, *sk = NULL; int result, status = L2CAP_CS_NO_INFO; @@ -2115,13 +2116,13 @@ sendresp: L2CAP_INFO_REQ, sizeof(info), &info); } - if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) && + if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) && result == L2CAP_CR_SUCCESS) { u8 buf[128]; l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(sk, buf), buf); - l2cap_pi(sk)->num_conf_req++; + l2cap_build_conf_req(chan, buf), buf); + chan->num_conf_req++; } return 0; @@ -2167,8 +2168,8 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(sk, req), req); - l2cap_pi(sk)->num_conf_req++; + l2cap_build_conf_req(chan, req), req); + chan->num_conf_req++; break; case L2CAP_CR_PEND: @@ -2234,7 +2235,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr /* Reject if config buffer is too small. */ len = cmd_len - sizeof(*req); - if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) { + if (chan->conf_len + len > sizeof(chan->conf_req)) { l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, l2cap_build_conf_rsp(sk, rsp, L2CAP_CONF_REJECT, flags), rsp); @@ -2242,8 +2243,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr } /* Store config. */ - memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len); - l2cap_pi(sk)->conf_len += len; + memcpy(chan->conf_req + chan->conf_len, req->data, len); + chan->conf_len += len; if (flags & 0x0001) { /* Incomplete config. Send empty response. */ @@ -2254,17 +2255,17 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr } /* Complete config. */ - len = l2cap_parse_conf_req(sk, rsp); + len = l2cap_parse_conf_req(chan, rsp); if (len < 0) { l2cap_send_disconn_req(conn, sk, ECONNRESET); goto unlock; } l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); - l2cap_pi(sk)->num_conf_rsp++; + chan->num_conf_rsp++; /* Reset config buffer. */ - l2cap_pi(sk)->conf_len = 0; + chan->conf_len = 0; if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE)) goto unlock; @@ -2288,8 +2289,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr u8 buf[64]; l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(sk, buf), buf); - l2cap_pi(sk)->num_conf_req++; + l2cap_build_conf_req(chan, buf), buf); + chan->num_conf_req++; } unlock: @@ -2324,7 +2325,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr break; case L2CAP_CONF_UNACCEPT: - if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { + if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { char req[64]; if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { @@ -2343,7 +2344,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, len, req); - l2cap_pi(sk)->num_conf_req++; + chan->num_conf_req++; if (result != L2CAP_CONF_SUCCESS) goto done; break; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index cad4bc7d36b2..244475ea045c 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -810,6 +810,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) { struct l2cap_conn_rsp rsp; struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; u8 buf[128]; sk->sk_state = BT_CONFIG; @@ -818,7 +819,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); - l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->chan->ident, + l2cap_send_cmd(l2cap_pi(sk)->conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) { @@ -828,8 +829,8 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(sk, buf), buf); - l2cap_pi(sk)->num_conf_req++; + l2cap_build_conf_req(chan, buf), buf); + chan->num_conf_req++; release_sock(sk); return 0; @@ -1035,7 +1036,6 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) } /* Default config options */ - pi->conf_len = 0; pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; skb_queue_head_init(TX_QUEUE(sk)); skb_queue_head_init(SREJ_QUEUE(sk)); -- cgit v1.2.3-58-ga151 From 710f9b0a423cad155144742f6497efe5163ed750 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 14:30:37 -0300 Subject: Bluetooth: clean up l2cap_sock_recvmsg() Move some channel specific stuff to l2cap_core.c, this will make things more clear. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 3 +-- net/bluetooth/l2cap_core.c | 28 +++++++++++++++++++++++++++- net/bluetooth/l2cap_sock.c | 25 +------------------------ 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index bf918283712a..469241353d78 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -446,9 +446,8 @@ extern struct bt_sock_list l2cap_sk_list; int l2cap_init_sockets(void); void l2cap_cleanup_sockets(void); -u8 l2cap_get_ident(struct l2cap_conn *conn); void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data); -int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); +void __l2cap_connect_rsp_defer(struct sock *sk); int __l2cap_wait_ack(struct sock *sk); struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index cb849b51632f..b41e21f46231 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -70,6 +70,7 @@ static void l2cap_busy_work(struct work_struct *work); static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, u8 ident, u16 dlen, void *data); +static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); @@ -1598,7 +1599,7 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) } } -int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) +static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) { struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); @@ -1934,6 +1935,31 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 fla return ptr - data; } +void __l2cap_connect_rsp_defer(struct sock *sk) +{ + struct l2cap_conn_rsp rsp; + struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + u8 buf[128]; + + sk->sk_state = BT_CONFIG; + + rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); + rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); + rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); + rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); + l2cap_send_cmd(conn, chan->ident, + L2CAP_CONN_RSP, sizeof(rsp), &rsp); + + if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) + return; + + l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; + l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, + l2cap_build_conf_req(chan, buf), buf); + chan->num_conf_req++; +} + static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len) { struct l2cap_pinfo *pi = l2cap_pi(sk); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 244475ea045c..450f57b106b9 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -808,30 +808,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms lock_sock(sk); if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) { - struct l2cap_conn_rsp rsp; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; - struct l2cap_chan *chan = l2cap_pi(sk)->chan; - u8 buf[128]; - - sk->sk_state = BT_CONFIG; - - rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); - rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); - rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); - rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); - l2cap_send_cmd(l2cap_pi(sk)->conn, chan->ident, - L2CAP_CONN_RSP, sizeof(rsp), &rsp); - - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) { - release_sock(sk); - return 0; - } - - l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; - l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(chan, buf), buf); - chan->num_conf_req++; - + __l2cap_connect_rsp_defer(sk); release_sock(sk); return 0; } -- cgit v1.2.3-58-ga151 From 525cd1851b9faaadf5ea33e05192b8d22f42487e Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 19:43:39 -0300 Subject: Bluetooth: Move conn_state to struct l2cap_chan This is part of "moving things to l2cap_chan". As one the first move it triggered a big number of changes in the funcions parameters, basically changing the struct sock param to struct l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 5 +- net/bluetooth/l2cap_core.c | 391 ++++++++++++++++++++++-------------------- net/bluetooth/l2cap_sock.c | 16 +- 3 files changed, 217 insertions(+), 195 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 469241353d78..82d5b81a779b 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -286,6 +286,8 @@ struct l2cap_chan { __u8 num_conf_req; __u8 num_conf_rsp; + __u16 conn_state; + struct list_head list; }; @@ -350,7 +352,6 @@ struct l2cap_pinfo { __u8 flushable; __u8 conf_state; - __u16 conn_state; __u8 next_tx_seq; __u8 expected_ack_seq; @@ -456,7 +457,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len); void l2cap_do_send(struct sock *sk, struct sk_buff *skb); void l2cap_streaming_send(struct sock *sk); -int l2cap_ertm_send(struct sock *sk); +int l2cap_ertm_send(struct l2cap_chan *chan); void l2cap_sock_set_timer(struct sock *sk, long timeout); void l2cap_sock_clear_timer(struct sock *sk); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b41e21f46231..b5435cd74f99 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -340,10 +340,11 @@ void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *d hci_send_acl(conn->hcon, skb, flags); } -static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) +static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) { struct sk_buff *skb; struct l2cap_hdr *lh; + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct l2cap_conn *conn = pi->conn; struct sock *sk = (struct sock *)pi; int count, hlen = L2CAP_HDR_SIZE + 2; @@ -360,14 +361,14 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) count = min_t(unsigned int, conn->mtu, hlen); control |= L2CAP_CTRL_FRAME_TYPE; - if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { + if (chan->conn_state & L2CAP_CONN_SEND_FBIT) { control |= L2CAP_CTRL_FINAL; - pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; + chan->conn_state &= ~L2CAP_CONN_SEND_FBIT; } - if (pi->conn_state & L2CAP_CONN_SEND_PBIT) { + if (chan->conn_state & L2CAP_CONN_SEND_PBIT) { control |= L2CAP_CTRL_POLL; - pi->conn_state &= ~L2CAP_CONN_SEND_PBIT; + chan->conn_state &= ~L2CAP_CONN_SEND_PBIT; } skb = bt_skb_alloc(count, GFP_ATOMIC); @@ -392,17 +393,19 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) hci_send_acl(pi->conn->hcon, skb, flags); } -static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) +static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control) { - if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); + + if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; - pi->conn_state |= L2CAP_CONN_RNR_SENT; + chan->conn_state |= L2CAP_CONN_RNR_SENT; } else control |= L2CAP_SUPER_RCV_READY; control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; - l2cap_send_sframe(pi, control); + l2cap_send_sframe(chan, control); } static inline int __l2cap_no_conn_pending(struct sock *sk) @@ -949,9 +952,10 @@ int __l2cap_wait_ack(struct sock *sk) static void l2cap_monitor_timeout(unsigned long arg) { - struct sock *sk = (void *) arg; + struct l2cap_chan *chan = (void *) arg; + struct sock *sk = chan->sk; - BT_DBG("sk %p", sk); + BT_DBG("chan %p", chan); bh_lock_sock(sk); if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) { @@ -963,13 +967,14 @@ static void l2cap_monitor_timeout(unsigned long arg) l2cap_pi(sk)->retry_count++; __mod_monitor_timer(); - l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL); + l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); bh_unlock_sock(sk); } static void l2cap_retrans_timeout(unsigned long arg) { - struct sock *sk = (void *) arg; + struct l2cap_chan *chan = (void *) arg; + struct sock *sk = chan->sk; BT_DBG("sk %p", sk); @@ -977,9 +982,9 @@ static void l2cap_retrans_timeout(unsigned long arg) l2cap_pi(sk)->retry_count = 1; __mod_monitor_timer(); - l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F; + chan->conn_state |= L2CAP_CONN_WAIT_F; - l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL); + l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); bh_unlock_sock(sk); } @@ -1040,8 +1045,9 @@ void l2cap_streaming_send(struct sock *sk) } } -static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq) +static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *skb, *tx_skb; u16 control, fcs; @@ -1069,9 +1075,9 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq) bt_cb(skb)->retries++; control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); - if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { + if (chan->conn_state & L2CAP_CONN_SEND_FBIT) { control |= L2CAP_CTRL_FINAL; - pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; + chan->conn_state &= ~L2CAP_CONN_SEND_FBIT; } control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) @@ -1087,9 +1093,10 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq) l2cap_do_send(sk, tx_skb); } -int l2cap_ertm_send(struct sock *sk) +int l2cap_ertm_send(struct l2cap_chan *chan) { struct sk_buff *skb, *tx_skb; + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; int nsent = 0; @@ -1112,9 +1119,9 @@ int l2cap_ertm_send(struct sock *sk) control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); control &= L2CAP_CTRL_SAR; - if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { + if (chan->conn_state & L2CAP_CONN_SEND_FBIT) { control |= L2CAP_CTRL_FINAL; - pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; + chan->conn_state &= ~L2CAP_CONN_SEND_FBIT; } control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); @@ -1149,8 +1156,9 @@ int l2cap_ertm_send(struct sock *sk) return nsent; } -static int l2cap_retransmit_frames(struct sock *sk) +static int l2cap_retransmit_frames(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); int ret; @@ -1158,32 +1166,32 @@ static int l2cap_retransmit_frames(struct sock *sk) sk->sk_send_head = TX_QUEUE(sk)->next; pi->next_tx_seq = pi->expected_ack_seq; - ret = l2cap_ertm_send(sk); + ret = l2cap_ertm_send(chan); return ret; } -static void l2cap_send_ack(struct l2cap_pinfo *pi) +static void l2cap_send_ack(struct l2cap_chan *chan) { - struct sock *sk = (struct sock *)pi; + struct sock *sk = chan->sk; u16 control = 0; - control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control |= l2cap_pi(sk)->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; - if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; - pi->conn_state |= L2CAP_CONN_RNR_SENT; - l2cap_send_sframe(pi, control); + chan->conn_state |= L2CAP_CONN_RNR_SENT; + l2cap_send_sframe(chan, control); return; } - if (l2cap_ertm_send(sk) > 0) + if (l2cap_ertm_send(chan) > 0) return; control |= L2CAP_SUPER_RCV_READY; - l2cap_send_sframe(pi, control); + l2cap_send_sframe(chan, control); } -static void l2cap_send_srejtail(struct sock *sk) +static void l2cap_send_srejtail(struct l2cap_chan *chan) { struct srej_list *tail; u16 control; @@ -1191,10 +1199,10 @@ static void l2cap_send_srejtail(struct sock *sk) control = L2CAP_SUPER_SELECT_REJECT; control |= L2CAP_CTRL_FINAL; - tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list); + tail = list_entry(SREJ_LIST(chan->sk)->prev, struct srej_list, list); control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; - l2cap_send_sframe(l2cap_pi(sk), control); + l2cap_send_sframe(chan, control); } static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb) @@ -1556,15 +1564,17 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) static void l2cap_ack_timeout(unsigned long arg) { - struct sock *sk = (void *) arg; + struct l2cap_chan *chan = (void *) arg; - bh_lock_sock(sk); - l2cap_send_ack(l2cap_pi(sk)); - bh_unlock_sock(sk); + bh_lock_sock(chan->sk); + l2cap_send_ack(chan); + bh_unlock_sock(chan->sk); } -static inline void l2cap_ertm_init(struct sock *sk) +static inline void l2cap_ertm_init(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; + l2cap_pi(sk)->expected_ack_seq = 0; l2cap_pi(sk)->unacked_frames = 0; l2cap_pi(sk)->buffer_seq = 0; @@ -1572,11 +1582,11 @@ static inline void l2cap_ertm_init(struct sock *sk) l2cap_pi(sk)->frames_sent = 0; setup_timer(&l2cap_pi(sk)->retrans_timer, - l2cap_retrans_timeout, (unsigned long) sk); + l2cap_retrans_timeout, (unsigned long) chan); setup_timer(&l2cap_pi(sk)->monitor_timer, - l2cap_monitor_timeout, (unsigned long) sk); + l2cap_monitor_timeout, (unsigned long) chan); setup_timer(&l2cap_pi(sk)->ack_timer, - l2cap_ack_timeout, (unsigned long) sk); + l2cap_ack_timeout, (unsigned long) chan); __skb_queue_head_init(SREJ_QUEUE(sk)); __skb_queue_head_init(BUSY_QUEUE(sk)); @@ -2305,7 +2315,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr l2cap_pi(sk)->expected_tx_seq = 0; __skb_queue_head_init(TX_QUEUE(sk)); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) - l2cap_ertm_init(sk); + l2cap_ertm_init(chan); l2cap_chan_ready(sk); goto unlock; @@ -2396,7 +2406,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr l2cap_pi(sk)->expected_tx_seq = 0; __skb_queue_head_init(TX_QUEUE(sk)); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) - l2cap_ertm_init(sk); + l2cap_ertm_init(chan); l2cap_chan_ready(sk); } @@ -2777,30 +2787,30 @@ static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb) return 0; } -static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk) +static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u16 control = 0; pi->frames_sent = 0; control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; - if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; - l2cap_send_sframe(pi, control); - pi->conn_state |= L2CAP_CONN_RNR_SENT; + l2cap_send_sframe(chan, control); + chan->conn_state |= L2CAP_CONN_RNR_SENT; } - if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY) - l2cap_retransmit_frames(sk); + if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY) + l2cap_retransmit_frames(chan); - l2cap_ertm_send(sk); + l2cap_ertm_send(chan); - if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) && + if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) && pi->frames_sent == 0) { control |= L2CAP_SUPER_RCV_READY; - l2cap_send_sframe(pi, control); + l2cap_send_sframe(chan, control); } } @@ -2847,25 +2857,25 @@ static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_s return 0; } -static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) +static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct sk_buff *_skb; int err; switch (control & L2CAP_CTRL_SAR) { case L2CAP_SDU_UNSEGMENTED: - if (pi->conn_state & L2CAP_CONN_SAR_SDU) + if (chan->conn_state & L2CAP_CONN_SAR_SDU) goto drop; - err = sock_queue_rcv_skb(sk, skb); + err = sock_queue_rcv_skb(chan->sk, skb); if (!err) return err; break; case L2CAP_SDU_START: - if (pi->conn_state & L2CAP_CONN_SAR_SDU) + if (chan->conn_state & L2CAP_CONN_SAR_SDU) goto drop; pi->sdu_len = get_unaligned_le16(skb->data); @@ -2884,12 +2894,12 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); - pi->conn_state |= L2CAP_CONN_SAR_SDU; + chan->conn_state |= L2CAP_CONN_SAR_SDU; pi->partial_sdu_len = skb->len; break; case L2CAP_SDU_CONTINUE: - if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) + if (!(chan->conn_state & L2CAP_CONN_SAR_SDU)) goto disconnect; if (!pi->sdu) @@ -2904,13 +2914,13 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c break; case L2CAP_SDU_END: - if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) + if (!(chan->conn_state & L2CAP_CONN_SAR_SDU)) goto disconnect; if (!pi->sdu) goto disconnect; - if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) { + if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) { pi->partial_sdu_len += skb->len; if (pi->partial_sdu_len > pi->imtu) @@ -2924,19 +2934,19 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c _skb = skb_clone(pi->sdu, GFP_ATOMIC); if (!_skb) { - pi->conn_state |= L2CAP_CONN_SAR_RETRY; + chan->conn_state |= L2CAP_CONN_SAR_RETRY; return -ENOMEM; } - err = sock_queue_rcv_skb(sk, _skb); + err = sock_queue_rcv_skb(chan->sk, _skb); if (err < 0) { kfree_skb(_skb); - pi->conn_state |= L2CAP_CONN_SAR_RETRY; + chan->conn_state |= L2CAP_CONN_SAR_RETRY; return err; } - pi->conn_state &= ~L2CAP_CONN_SAR_RETRY; - pi->conn_state &= ~L2CAP_CONN_SAR_SDU; + chan->conn_state &= ~L2CAP_CONN_SAR_RETRY; + chan->conn_state &= ~L2CAP_CONN_SAR_SDU; kfree_skb(pi->sdu); break; @@ -2950,13 +2960,14 @@ drop: pi->sdu = NULL; disconnect: - l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan->sk, ECONNRESET); kfree_skb(skb); return 0; } -static int l2cap_try_push_rx_skb(struct sock *sk) +static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *skb; u16 control; @@ -2964,7 +2975,7 @@ static int l2cap_try_push_rx_skb(struct sock *sk) while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) { control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; - err = l2cap_ertm_reassembly_sdu(sk, skb, control); + err = l2cap_ertm_reassembly_sdu(chan, skb, control); if (err < 0) { skb_queue_head(BUSY_QUEUE(sk), skb); return -EBUSY; @@ -2973,22 +2984,22 @@ static int l2cap_try_push_rx_skb(struct sock *sk) pi->buffer_seq = (pi->buffer_seq + 1) % 64; } - if (!(pi->conn_state & L2CAP_CONN_RNR_SENT)) + if (!(chan->conn_state & L2CAP_CONN_RNR_SENT)) goto done; control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL; - l2cap_send_sframe(pi, control); + l2cap_send_sframe(chan, control); l2cap_pi(sk)->retry_count = 1; del_timer(&pi->retrans_timer); __mod_monitor_timer(); - l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F; + chan->conn_state |= L2CAP_CONN_WAIT_F; done: - pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY; - pi->conn_state &= ~L2CAP_CONN_RNR_SENT; + chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY; + chan->conn_state &= ~L2CAP_CONN_RNR_SENT; BT_DBG("sk %p, Exit local busy", sk); @@ -3032,7 +3043,7 @@ static void l2cap_busy_work(struct work_struct *work) if (err) break; - if (l2cap_try_push_rx_skb(sk) == 0) + if (l2cap_try_push_rx_skb(l2cap_pi(sk)->chan) == 0) break; } @@ -3042,20 +3053,21 @@ static void l2cap_busy_work(struct work_struct *work) release_sock(sk); } -static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control) +static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); int sctrl, err; - if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; __skb_queue_tail(BUSY_QUEUE(sk), skb); - return l2cap_try_push_rx_skb(sk); + return l2cap_try_push_rx_skb(chan); } - err = l2cap_ertm_reassembly_sdu(sk, skb, control); + err = l2cap_ertm_reassembly_sdu(chan, skb, control); if (err >= 0) { pi->buffer_seq = (pi->buffer_seq + 1) % 64; return err; @@ -3064,15 +3076,15 @@ static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control) /* Busy Condition */ BT_DBG("sk %p, Enter local busy", sk); - pi->conn_state |= L2CAP_CONN_LOCAL_BUSY; + chan->conn_state |= L2CAP_CONN_LOCAL_BUSY; bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; __skb_queue_tail(BUSY_QUEUE(sk), skb); sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; sctrl |= L2CAP_SUPER_RCV_NOT_READY; - l2cap_send_sframe(pi, sctrl); + l2cap_send_sframe(chan, sctrl); - pi->conn_state |= L2CAP_CONN_RNR_SENT; + chan->conn_state |= L2CAP_CONN_RNR_SENT; del_timer(&pi->ack_timer); @@ -3081,9 +3093,9 @@ static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control) return err; } -static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) +static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct sk_buff *_skb; int err = -EINVAL; @@ -3094,19 +3106,19 @@ static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, switch (control & L2CAP_CTRL_SAR) { case L2CAP_SDU_UNSEGMENTED: - if (pi->conn_state & L2CAP_CONN_SAR_SDU) { + if (chan->conn_state & L2CAP_CONN_SAR_SDU) { kfree_skb(pi->sdu); break; } - err = sock_queue_rcv_skb(sk, skb); + err = sock_queue_rcv_skb(chan->sk, skb); if (!err) return 0; break; case L2CAP_SDU_START: - if (pi->conn_state & L2CAP_CONN_SAR_SDU) { + if (chan->conn_state & L2CAP_CONN_SAR_SDU) { kfree_skb(pi->sdu); break; } @@ -3127,13 +3139,13 @@ static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); - pi->conn_state |= L2CAP_CONN_SAR_SDU; + chan->conn_state |= L2CAP_CONN_SAR_SDU; pi->partial_sdu_len = skb->len; err = 0; break; case L2CAP_SDU_CONTINUE: - if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) + if (!(chan->conn_state & L2CAP_CONN_SAR_SDU)) break; memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); @@ -3147,12 +3159,12 @@ static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, break; case L2CAP_SDU_END: - if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) + if (!(chan->conn_state & L2CAP_CONN_SAR_SDU)) break; memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); - pi->conn_state &= ~L2CAP_CONN_SAR_SDU; + chan->conn_state &= ~L2CAP_CONN_SAR_SDU; pi->partial_sdu_len += skb->len; if (pi->partial_sdu_len > pi->imtu) @@ -3160,7 +3172,7 @@ static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, if (pi->partial_sdu_len == pi->sdu_len) { _skb = skb_clone(pi->sdu, GFP_ATOMIC); - err = sock_queue_rcv_skb(sk, _skb); + err = sock_queue_rcv_skb(chan->sk, _skb); if (err < 0) kfree_skb(_skb); } @@ -3175,8 +3187,9 @@ drop: return err; } -static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq) +static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq) { + struct sock *sk = chan->sk; struct sk_buff *skb; u16 control; @@ -3186,16 +3199,16 @@ static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq) skb = skb_dequeue(SREJ_QUEUE(sk)); control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; - l2cap_ertm_reassembly_sdu(sk, skb, control); + l2cap_ertm_reassembly_sdu(chan, skb, control); l2cap_pi(sk)->buffer_seq_srej = (l2cap_pi(sk)->buffer_seq_srej + 1) % 64; tx_seq = (tx_seq + 1) % 64; } } -static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq) +static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct sock *sk = chan->sk; struct srej_list *l, *tmp; u16 control; @@ -3207,14 +3220,15 @@ static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq) } control = L2CAP_SUPER_SELECT_REJECT; control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; - l2cap_send_sframe(pi, control); + l2cap_send_sframe(chan, control); list_del(&l->list); list_add_tail(&l->list, SREJ_LIST(sk)); } } -static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq) +static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); struct srej_list *new; u16 control; @@ -3222,7 +3236,7 @@ static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq) while (tx_seq != pi->expected_tx_seq) { control = L2CAP_SUPER_SELECT_REJECT; control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; - l2cap_send_sframe(pi, control); + l2cap_send_sframe(chan, control); new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); new->tx_seq = pi->expected_tx_seq; @@ -3232,8 +3246,9 @@ static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq) pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; } -static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) +static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); u8 tx_seq = __get_txseq(rx_control); u8 req_seq = __get_reqseq(rx_control); @@ -3242,15 +3257,15 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str int num_to_ack = (pi->tx_win/6) + 1; int err = 0; - BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq, - rx_control); + BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len, + tx_seq, rx_control); if (L2CAP_CTRL_FINAL & rx_control && - l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) { + chan->conn_state & L2CAP_CONN_WAIT_F) { del_timer(&pi->monitor_timer); if (pi->unacked_frames > 0) __mod_retrans_timer(); - pi->conn_state &= ~L2CAP_CONN_WAIT_F; + chan->conn_state &= ~L2CAP_CONN_WAIT_F; } pi->expected_ack_seq = req_seq; @@ -3269,25 +3284,25 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str goto drop; } - if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY) + if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY) goto drop; - if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { + if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { struct srej_list *first; first = list_first_entry(SREJ_LIST(sk), struct srej_list, list); if (tx_seq == first->tx_seq) { l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); - l2cap_check_srej_gap(sk, tx_seq); + l2cap_check_srej_gap(chan, tx_seq); list_del(&first->list); kfree(first); if (list_empty(SREJ_LIST(sk))) { pi->buffer_seq = pi->buffer_seq_srej; - pi->conn_state &= ~L2CAP_CONN_SREJ_SENT; - l2cap_send_ack(pi); + chan->conn_state &= ~L2CAP_CONN_SREJ_SENT; + l2cap_send_ack(chan); BT_DBG("sk %p, Exit SREJ_SENT", sk); } } else { @@ -3299,11 +3314,11 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str list_for_each_entry(l, SREJ_LIST(sk), list) { if (l->tx_seq == tx_seq) { - l2cap_resend_srejframe(sk, tx_seq); + l2cap_resend_srejframe(chan, tx_seq); return 0; } } - l2cap_send_srejframe(sk, tx_seq); + l2cap_send_srejframe(chan, tx_seq); } } else { expected_tx_seq_offset = @@ -3315,7 +3330,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str if (tx_seq_offset < expected_tx_seq_offset) goto drop; - pi->conn_state |= L2CAP_CONN_SREJ_SENT; + chan->conn_state |= L2CAP_CONN_SREJ_SENT; BT_DBG("sk %p, Enter SREJ", sk); @@ -3326,9 +3341,9 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str __skb_queue_head_init(BUSY_QUEUE(sk)); l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); - pi->conn_state |= L2CAP_CONN_SEND_PBIT; + chan->conn_state |= L2CAP_CONN_SEND_PBIT; - l2cap_send_srejframe(sk, tx_seq); + l2cap_send_srejframe(chan, tx_seq); del_timer(&pi->ack_timer); } @@ -3337,29 +3352,29 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str expected: pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; - if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { + if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { bt_cb(skb)->tx_seq = tx_seq; bt_cb(skb)->sar = sar; __skb_queue_tail(SREJ_QUEUE(sk), skb); return 0; } - err = l2cap_push_rx_skb(sk, skb, rx_control); + err = l2cap_push_rx_skb(chan, skb, rx_control); if (err < 0) return 0; if (rx_control & L2CAP_CTRL_FINAL) { - if (pi->conn_state & L2CAP_CONN_REJ_ACT) - pi->conn_state &= ~L2CAP_CONN_REJ_ACT; + if (chan->conn_state & L2CAP_CONN_REJ_ACT) + chan->conn_state &= ~L2CAP_CONN_REJ_ACT; else - l2cap_retransmit_frames(sk); + l2cap_retransmit_frames(chan); } __mod_ack_timer(); pi->num_acked = (pi->num_acked + 1) % num_to_ack; if (pi->num_acked == num_to_ack - 1) - l2cap_send_ack(pi); + l2cap_send_ack(chan); return 0; @@ -3368,8 +3383,9 @@ drop: return 0; } -static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) +static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control), @@ -3379,154 +3395,156 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) l2cap_drop_acked_frames(sk); if (rx_control & L2CAP_CTRL_POLL) { - pi->conn_state |= L2CAP_CONN_SEND_FBIT; - if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { - if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && + chan->conn_state |= L2CAP_CONN_SEND_FBIT; + if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { + if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && (pi->unacked_frames > 0)) __mod_retrans_timer(); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - l2cap_send_srejtail(sk); + chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + l2cap_send_srejtail(chan); } else { - l2cap_send_i_or_rr_or_rnr(sk); + l2cap_send_i_or_rr_or_rnr(chan); } } else if (rx_control & L2CAP_CTRL_FINAL) { - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - if (pi->conn_state & L2CAP_CONN_REJ_ACT) - pi->conn_state &= ~L2CAP_CONN_REJ_ACT; + if (chan->conn_state & L2CAP_CONN_REJ_ACT) + chan->conn_state &= ~L2CAP_CONN_REJ_ACT; else - l2cap_retransmit_frames(sk); + l2cap_retransmit_frames(chan); } else { - if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && + if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && (pi->unacked_frames > 0)) __mod_retrans_timer(); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - if (pi->conn_state & L2CAP_CONN_SREJ_SENT) - l2cap_send_ack(pi); + chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + if (chan->conn_state & L2CAP_CONN_SREJ_SENT) + l2cap_send_ack(chan); else - l2cap_ertm_send(sk); + l2cap_ertm_send(chan); } } -static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control) +static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_reqseq(rx_control); - BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control); + BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); + l2cap_drop_acked_frames(chan->sk); if (rx_control & L2CAP_CTRL_FINAL) { - if (pi->conn_state & L2CAP_CONN_REJ_ACT) - pi->conn_state &= ~L2CAP_CONN_REJ_ACT; + if (chan->conn_state & L2CAP_CONN_REJ_ACT) + chan->conn_state &= ~L2CAP_CONN_REJ_ACT; else - l2cap_retransmit_frames(sk); + l2cap_retransmit_frames(chan); } else { - l2cap_retransmit_frames(sk); + l2cap_retransmit_frames(chan); - if (pi->conn_state & L2CAP_CONN_WAIT_F) - pi->conn_state |= L2CAP_CONN_REJ_ACT; + if (chan->conn_state & L2CAP_CONN_WAIT_F) + chan->conn_state |= L2CAP_CONN_REJ_ACT; } } -static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control) +static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_reqseq(rx_control); - BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control); + BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; if (rx_control & L2CAP_CTRL_POLL) { pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); + l2cap_drop_acked_frames(chan->sk); - pi->conn_state |= L2CAP_CONN_SEND_FBIT; - l2cap_retransmit_one_frame(sk, tx_seq); + chan->conn_state |= L2CAP_CONN_SEND_FBIT; + l2cap_retransmit_one_frame(chan, tx_seq); - l2cap_ertm_send(sk); + l2cap_ertm_send(chan); - if (pi->conn_state & L2CAP_CONN_WAIT_F) { + if (chan->conn_state & L2CAP_CONN_WAIT_F) { pi->srej_save_reqseq = tx_seq; - pi->conn_state |= L2CAP_CONN_SREJ_ACT; + chan->conn_state |= L2CAP_CONN_SREJ_ACT; } } else if (rx_control & L2CAP_CTRL_FINAL) { - if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) && + if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) && pi->srej_save_reqseq == tx_seq) - pi->conn_state &= ~L2CAP_CONN_SREJ_ACT; + chan->conn_state &= ~L2CAP_CONN_SREJ_ACT; else - l2cap_retransmit_one_frame(sk, tx_seq); + l2cap_retransmit_one_frame(chan, tx_seq); } else { - l2cap_retransmit_one_frame(sk, tx_seq); - if (pi->conn_state & L2CAP_CONN_WAIT_F) { + l2cap_retransmit_one_frame(chan, tx_seq); + if (chan->conn_state & L2CAP_CONN_WAIT_F) { pi->srej_save_reqseq = tx_seq; - pi->conn_state |= L2CAP_CONN_SREJ_ACT; + chan->conn_state |= L2CAP_CONN_SREJ_ACT; } } } -static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control) +static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_reqseq(rx_control); - BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control); + BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); - pi->conn_state |= L2CAP_CONN_REMOTE_BUSY; + chan->conn_state |= L2CAP_CONN_REMOTE_BUSY; pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); + l2cap_drop_acked_frames(chan->sk); if (rx_control & L2CAP_CTRL_POLL) - pi->conn_state |= L2CAP_CONN_SEND_FBIT; + chan->conn_state |= L2CAP_CONN_SEND_FBIT; - if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) { + if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) { del_timer(&pi->retrans_timer); if (rx_control & L2CAP_CTRL_POLL) - l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL); + l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL); return; } if (rx_control & L2CAP_CTRL_POLL) - l2cap_send_srejtail(sk); + l2cap_send_srejtail(chan); else - l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY); + l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY); } -static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) +static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb) { - BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); + struct sock *sk = chan->sk; + + BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len); if (L2CAP_CTRL_FINAL & rx_control && - l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) { + chan->conn_state & L2CAP_CONN_WAIT_F) { del_timer(&l2cap_pi(sk)->monitor_timer); if (l2cap_pi(sk)->unacked_frames > 0) __mod_retrans_timer(); - l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F; + chan->conn_state &= ~L2CAP_CONN_WAIT_F; } switch (rx_control & L2CAP_CTRL_SUPERVISE) { case L2CAP_SUPER_RCV_READY: - l2cap_data_channel_rrframe(sk, rx_control); + l2cap_data_channel_rrframe(chan, rx_control); break; case L2CAP_SUPER_REJECT: - l2cap_data_channel_rejframe(sk, rx_control); + l2cap_data_channel_rejframe(chan, rx_control); break; case L2CAP_SUPER_SELECT_REJECT: - l2cap_data_channel_srejframe(sk, rx_control); + l2cap_data_channel_srejframe(chan, rx_control); break; case L2CAP_SUPER_RCV_NOT_READY: - l2cap_data_channel_rnrframe(sk, rx_control); + l2cap_data_channel_rnrframe(chan, rx_control); break; } @@ -3536,6 +3554,7 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control; u8 req_seq; @@ -3586,7 +3605,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) goto drop; } - l2cap_data_channel_iframe(sk, control, skb); + l2cap_data_channel_iframe(chan, control, skb); } else { if (len != 0) { BT_ERR("%d", len); @@ -3594,7 +3613,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) goto drop; } - l2cap_data_channel_sframe(sk, control, skb); + l2cap_data_channel_sframe(chan, control, skb); } return 0; @@ -3675,7 +3694,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk else pi->expected_tx_seq = (tx_seq + 1) % 64; - l2cap_streaming_reassembly_sdu(sk, skb, control); + l2cap_streaming_reassembly_sdu(chan, skb, control); goto done; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 450f57b106b9..66ec966ffc18 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -778,14 +778,16 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms if (pi->mode == L2CAP_MODE_STREAMING) { l2cap_streaming_send(sk); - } else { - if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && - (pi->conn_state & L2CAP_CONN_WAIT_F)) { - err = len; - break; - } - err = l2cap_ertm_send(sk); + err = len; + break; + } + + if ((pi->chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && + (pi->chan->conn_state & L2CAP_CONN_WAIT_F)) { + err = len; + break; } + err = l2cap_ertm_send(pi->chan); if (err >= 0) err = len; -- cgit v1.2.3-58-ga151 From 42e5c8027bad6f1591032941f0ebf4fc079405c8 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 19:58:34 -0300 Subject: Bluetooth: Move of ERTM *_seq vars to struct l2cap_chan As part of the moving channel to stuff to struct l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 20 +++---- net/bluetooth/l2cap_core.c | 128 ++++++++++++++++++++---------------------- net/bluetooth/l2cap_sock.c | 2 +- 3 files changed, 73 insertions(+), 77 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 82d5b81a779b..9b43874ca6e4 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -288,6 +288,12 @@ struct l2cap_chan { __u16 conn_state; + __u8 next_tx_seq; + __u8 expected_ack_seq; + __u8 expected_tx_seq; + __u8 buffer_seq; + __u8 buffer_seq_srej; + struct list_head list; }; @@ -353,11 +359,6 @@ struct l2cap_pinfo { __u8 conf_state; - __u8 next_tx_seq; - __u8 expected_ack_seq; - __u8 expected_tx_seq; - __u8 buffer_seq; - __u8 buffer_seq_srej; __u8 srej_save_reqseq; __u8 frames_sent; __u8 unacked_frames; @@ -421,17 +422,16 @@ struct l2cap_pinfo { #define __mod_ack_timer() mod_timer(&l2cap_pi(sk)->ack_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); -static inline int l2cap_tx_window_full(struct sock *sk) +static inline int l2cap_tx_window_full(struct l2cap_chan *ch) { - struct l2cap_pinfo *pi = l2cap_pi(sk); int sub; - sub = (pi->next_tx_seq - pi->expected_ack_seq) % 64; + sub = (ch->next_tx_seq - ch->expected_ack_seq) % 64; if (sub < 0) sub += 64; - return sub == pi->remote_tx_win; + return sub == l2cap_pi(ch->sk)->remote_tx_win; } #define __get_txseq(ctrl) (((ctrl) & L2CAP_CTRL_TXSEQ) >> 1) @@ -456,7 +456,7 @@ struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen); int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len); void l2cap_do_send(struct sock *sk, struct sk_buff *skb); -void l2cap_streaming_send(struct sock *sk); +void l2cap_streaming_send(struct l2cap_chan *chan); int l2cap_ertm_send(struct l2cap_chan *chan); void l2cap_sock_set_timer(struct sock *sk, long timeout); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b5435cd74f99..d975092904c1 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -395,15 +395,13 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); - if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; chan->conn_state |= L2CAP_CONN_RNR_SENT; } else control |= L2CAP_SUPER_RCV_READY; - control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; l2cap_send_sframe(chan, control); } @@ -988,13 +986,14 @@ static void l2cap_retrans_timeout(unsigned long arg) bh_unlock_sock(sk); } -static void l2cap_drop_acked_frames(struct sock *sk) +static void l2cap_drop_acked_frames(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; struct sk_buff *skb; while ((skb = skb_peek(TX_QUEUE(sk))) && l2cap_pi(sk)->unacked_frames) { - if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq) + if (bt_cb(skb)->tx_seq == chan->expected_ack_seq) break; skb = skb_dequeue(TX_QUEUE(sk)); @@ -1023,15 +1022,16 @@ void l2cap_do_send(struct sock *sk, struct sk_buff *skb) hci_send_acl(hcon, skb, flags); } -void l2cap_streaming_send(struct sock *sk) +void l2cap_streaming_send(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; struct sk_buff *skb; struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; while ((skb = skb_dequeue(TX_QUEUE(sk)))) { control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE); - control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; + control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE); if (pi->fcs == L2CAP_FCS_CRC16) { @@ -1041,7 +1041,7 @@ void l2cap_streaming_send(struct sock *sk) l2cap_do_send(sk, skb); - pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; + chan->next_tx_seq = (chan->next_tx_seq + 1) % 64; } } @@ -1080,7 +1080,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) chan->conn_state &= ~L2CAP_CONN_SEND_FBIT; } - control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) + control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); @@ -1104,7 +1104,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan) if (sk->sk_state != BT_CONNECTED) return -ENOTCONN; - while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) { + while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(chan))) { if (pi->remote_max_tx && bt_cb(skb)->retries == pi->remote_max_tx) { @@ -1123,8 +1123,8 @@ int l2cap_ertm_send(struct l2cap_chan *chan) control |= L2CAP_CTRL_FINAL; chan->conn_state &= ~L2CAP_CONN_SEND_FBIT; } - control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) - | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); + control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) + | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); @@ -1137,8 +1137,8 @@ int l2cap_ertm_send(struct l2cap_chan *chan) __mod_retrans_timer(); - bt_cb(skb)->tx_seq = pi->next_tx_seq; - pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; + bt_cb(skb)->tx_seq = chan->next_tx_seq; + chan->next_tx_seq = (chan->next_tx_seq + 1) % 64; if (bt_cb(skb)->retries == 1) pi->unacked_frames++; @@ -1159,23 +1159,21 @@ int l2cap_ertm_send(struct l2cap_chan *chan) static int l2cap_retransmit_frames(struct l2cap_chan *chan) { struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); int ret; if (!skb_queue_empty(TX_QUEUE(sk))) sk->sk_send_head = TX_QUEUE(sk)->next; - pi->next_tx_seq = pi->expected_ack_seq; + chan->next_tx_seq = chan->expected_ack_seq; ret = l2cap_ertm_send(chan); return ret; } static void l2cap_send_ack(struct l2cap_chan *chan) { - struct sock *sk = chan->sk; u16 control = 0; - control |= l2cap_pi(sk)->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; @@ -1575,9 +1573,9 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan) { struct sock *sk = chan->sk; - l2cap_pi(sk)->expected_ack_seq = 0; + chan->expected_ack_seq = 0; l2cap_pi(sk)->unacked_frames = 0; - l2cap_pi(sk)->buffer_seq = 0; + chan->buffer_seq = 0; l2cap_pi(sk)->num_acked = 0; l2cap_pi(sk)->frames_sent = 0; @@ -2311,8 +2309,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr sk->sk_state = BT_CONNECTED; - l2cap_pi(sk)->next_tx_seq = 0; - l2cap_pi(sk)->expected_tx_seq = 0; + chan->next_tx_seq = 0; + chan->expected_tx_seq = 0; __skb_queue_head_init(TX_QUEUE(sk)); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) l2cap_ertm_init(chan); @@ -2402,8 +2400,8 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr set_default_fcs(l2cap_pi(sk)); sk->sk_state = BT_CONNECTED; - l2cap_pi(sk)->next_tx_seq = 0; - l2cap_pi(sk)->expected_tx_seq = 0; + chan->next_tx_seq = 0; + chan->expected_tx_seq = 0; __skb_queue_head_init(TX_QUEUE(sk)); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) l2cap_ertm_init(chan); @@ -2794,7 +2792,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) pi->frames_sent = 0; - control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; @@ -2814,10 +2812,10 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) } } -static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar) +static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar) { + struct sock *sk = chan->sk; struct sk_buff *next_skb; - struct l2cap_pinfo *pi = l2cap_pi(sk); int tx_seq_offset, next_tx_seq_offset; bt_cb(skb)->tx_seq = tx_seq; @@ -2829,7 +2827,7 @@ static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_s return 0; } - tx_seq_offset = (tx_seq - pi->buffer_seq) % 64; + tx_seq_offset = (tx_seq - chan->buffer_seq) % 64; if (tx_seq_offset < 0) tx_seq_offset += 64; @@ -2838,7 +2836,7 @@ static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_s return -EINVAL; next_tx_seq_offset = (bt_cb(next_skb)->tx_seq - - pi->buffer_seq) % 64; + chan->buffer_seq) % 64; if (next_tx_seq_offset < 0) next_tx_seq_offset += 64; @@ -2981,13 +2979,13 @@ static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) return -EBUSY; } - pi->buffer_seq = (pi->buffer_seq + 1) % 64; + chan->buffer_seq = (chan->buffer_seq + 1) % 64; } if (!(chan->conn_state & L2CAP_CONN_RNR_SENT)) goto done; - control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL; l2cap_send_sframe(chan, control); l2cap_pi(sk)->retry_count = 1; @@ -3069,7 +3067,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c err = l2cap_ertm_reassembly_sdu(chan, skb, control); if (err >= 0) { - pi->buffer_seq = (pi->buffer_seq + 1) % 64; + chan->buffer_seq = (chan->buffer_seq + 1) % 64; return err; } @@ -3080,7 +3078,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; __skb_queue_tail(BUSY_QUEUE(sk), skb); - sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; sctrl |= L2CAP_SUPER_RCV_NOT_READY; l2cap_send_sframe(chan, sctrl); @@ -3200,8 +3198,8 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq) skb = skb_dequeue(SREJ_QUEUE(sk)); control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; l2cap_ertm_reassembly_sdu(chan, skb, control); - l2cap_pi(sk)->buffer_seq_srej = - (l2cap_pi(sk)->buffer_seq_srej + 1) % 64; + chan->buffer_seq_srej = + (chan->buffer_seq_srej + 1) % 64; tx_seq = (tx_seq + 1) % 64; } } @@ -3229,21 +3227,20 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq) static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) { struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); struct srej_list *new; u16 control; - while (tx_seq != pi->expected_tx_seq) { + while (tx_seq != chan->expected_tx_seq) { control = L2CAP_SUPER_SELECT_REJECT; - control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; l2cap_send_sframe(chan, control); new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); - new->tx_seq = pi->expected_tx_seq; - pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; + new->tx_seq = chan->expected_tx_seq; + chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; list_add_tail(&new->list, SREJ_LIST(sk)); } - pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; + chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; } static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb) @@ -3268,13 +3265,13 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont chan->conn_state &= ~L2CAP_CONN_WAIT_F; } - pi->expected_ack_seq = req_seq; - l2cap_drop_acked_frames(sk); + chan->expected_ack_seq = req_seq; + l2cap_drop_acked_frames(chan); - if (tx_seq == pi->expected_tx_seq) + if (tx_seq == chan->expected_tx_seq) goto expected; - tx_seq_offset = (tx_seq - pi->buffer_seq) % 64; + tx_seq_offset = (tx_seq - chan->buffer_seq) % 64; if (tx_seq_offset < 0) tx_seq_offset += 64; @@ -3293,14 +3290,14 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont first = list_first_entry(SREJ_LIST(sk), struct srej_list, list); if (tx_seq == first->tx_seq) { - l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); + l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); l2cap_check_srej_gap(chan, tx_seq); list_del(&first->list); kfree(first); if (list_empty(SREJ_LIST(sk))) { - pi->buffer_seq = pi->buffer_seq_srej; + chan->buffer_seq = chan->buffer_seq_srej; chan->conn_state &= ~L2CAP_CONN_SREJ_SENT; l2cap_send_ack(chan); BT_DBG("sk %p, Exit SREJ_SENT", sk); @@ -3309,7 +3306,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont struct srej_list *l; /* duplicated tx_seq */ - if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0) + if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0) goto drop; list_for_each_entry(l, SREJ_LIST(sk), list) { @@ -3322,7 +3319,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont } } else { expected_tx_seq_offset = - (pi->expected_tx_seq - pi->buffer_seq) % 64; + (chan->expected_tx_seq - chan->buffer_seq) % 64; if (expected_tx_seq_offset < 0) expected_tx_seq_offset += 64; @@ -3335,11 +3332,11 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont BT_DBG("sk %p, Enter SREJ", sk); INIT_LIST_HEAD(SREJ_LIST(sk)); - pi->buffer_seq_srej = pi->buffer_seq; + chan->buffer_seq_srej = chan->buffer_seq; __skb_queue_head_init(SREJ_QUEUE(sk)); __skb_queue_head_init(BUSY_QUEUE(sk)); - l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); + l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); chan->conn_state |= L2CAP_CONN_SEND_PBIT; @@ -3350,7 +3347,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont return 0; expected: - pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; + chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { bt_cb(skb)->tx_seq = tx_seq; @@ -3391,8 +3388,8 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control), rx_control); - pi->expected_ack_seq = __get_reqseq(rx_control); - l2cap_drop_acked_frames(sk); + chan->expected_ack_seq = __get_reqseq(rx_control); + l2cap_drop_acked_frames(chan); if (rx_control & L2CAP_CTRL_POLL) { chan->conn_state |= L2CAP_CONN_SEND_FBIT; @@ -3430,15 +3427,14 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_reqseq(rx_control); BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(chan->sk); + chan->expected_ack_seq = tx_seq; + l2cap_drop_acked_frames(chan); if (rx_control & L2CAP_CTRL_FINAL) { if (chan->conn_state & L2CAP_CONN_REJ_ACT) @@ -3462,8 +3458,8 @@ static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_ chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; if (rx_control & L2CAP_CTRL_POLL) { - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(chan->sk); + chan->expected_ack_seq = tx_seq; + l2cap_drop_acked_frames(chan); chan->conn_state |= L2CAP_CONN_SEND_FBIT; l2cap_retransmit_one_frame(chan, tx_seq); @@ -3497,8 +3493,8 @@ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_c BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); chan->conn_state |= L2CAP_CONN_REMOTE_BUSY; - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(chan->sk); + chan->expected_ack_seq = tx_seq; + l2cap_drop_acked_frames(chan); if (rx_control & L2CAP_CTRL_POLL) chan->conn_state |= L2CAP_CONN_SEND_FBIT; @@ -3584,12 +3580,12 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) } req_seq = __get_reqseq(control); - req_seq_offset = (req_seq - pi->expected_ack_seq) % 64; + req_seq_offset = (req_seq - chan->expected_ack_seq) % 64; if (req_seq_offset < 0) req_seq_offset += 64; next_tx_seq_offset = - (pi->next_tx_seq - pi->expected_ack_seq) % 64; + (chan->next_tx_seq - chan->expected_ack_seq) % 64; if (next_tx_seq_offset < 0) next_tx_seq_offset += 64; @@ -3689,10 +3685,10 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk tx_seq = __get_txseq(control); - if (pi->expected_tx_seq == tx_seq) - pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; + if (chan->expected_tx_seq == tx_seq) + chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; else - pi->expected_tx_seq = (tx_seq + 1) % 64; + chan->expected_tx_seq = (tx_seq + 1) % 64; l2cap_streaming_reassembly_sdu(chan, skb, control); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 66ec966ffc18..19574e43226a 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -777,7 +777,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms } if (pi->mode == L2CAP_MODE_STREAMING) { - l2cap_streaming_send(sk); + l2cap_streaming_send(pi->chan); err = len; break; } -- cgit v1.2.3-58-ga151 From 6a026610eee2c53ff59598905fcbaa979aec68d1 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 1 Apr 2011 00:38:50 -0300 Subject: Bluetooth: Move more ERTM stuff to struct l2cap_chan As part of the moving channel stuff to l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 10 ++++----- net/bluetooth/l2cap_core.c | 51 ++++++++++++++++++++----------------------- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 9b43874ca6e4..041213b4175a 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -293,6 +293,11 @@ struct l2cap_chan { __u8 expected_tx_seq; __u8 buffer_seq; __u8 buffer_seq_srej; + __u8 srej_save_reqseq; + __u8 frames_sent; + __u8 unacked_frames; + __u8 retry_count; + __u8 num_acked; struct list_head list; }; @@ -359,11 +364,6 @@ struct l2cap_pinfo { __u8 conf_state; - __u8 srej_save_reqseq; - __u8 frames_sent; - __u8 unacked_frames; - __u8 retry_count; - __u8 num_acked; __u16 sdu_len; __u16 partial_sdu_len; struct sk_buff *sdu; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index d975092904c1..3f601d1c164a 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -924,7 +924,7 @@ int __l2cap_wait_ack(struct sock *sk) int timeo = HZ/5; add_wait_queue(sk_sleep(sk), &wait); - while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) { + while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) { set_current_state(TASK_INTERRUPTIBLE); if (!timeo) @@ -956,13 +956,13 @@ static void l2cap_monitor_timeout(unsigned long arg) BT_DBG("chan %p", chan); bh_lock_sock(sk); - if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) { + if (chan->retry_count >= l2cap_pi(sk)->remote_max_tx) { l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED); bh_unlock_sock(sk); return; } - l2cap_pi(sk)->retry_count++; + chan->retry_count++; __mod_monitor_timer(); l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); @@ -977,7 +977,7 @@ static void l2cap_retrans_timeout(unsigned long arg) BT_DBG("sk %p", sk); bh_lock_sock(sk); - l2cap_pi(sk)->retry_count = 1; + chan->retry_count = 1; __mod_monitor_timer(); chan->conn_state |= L2CAP_CONN_WAIT_F; @@ -992,17 +992,17 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan) struct sk_buff *skb; while ((skb = skb_peek(TX_QUEUE(sk))) && - l2cap_pi(sk)->unacked_frames) { + chan->unacked_frames) { if (bt_cb(skb)->tx_seq == chan->expected_ack_seq) break; skb = skb_dequeue(TX_QUEUE(sk)); kfree_skb(skb); - l2cap_pi(sk)->unacked_frames--; + chan->unacked_frames--; } - if (!l2cap_pi(sk)->unacked_frames) + if (!chan->unacked_frames) del_timer(&l2cap_pi(sk)->retrans_timer); } @@ -1141,9 +1141,9 @@ int l2cap_ertm_send(struct l2cap_chan *chan) chan->next_tx_seq = (chan->next_tx_seq + 1) % 64; if (bt_cb(skb)->retries == 1) - pi->unacked_frames++; + chan->unacked_frames++; - pi->frames_sent++; + chan->frames_sent++; if (skb_queue_is_last(TX_QUEUE(sk), skb)) sk->sk_send_head = NULL; @@ -1574,10 +1574,10 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan) struct sock *sk = chan->sk; chan->expected_ack_seq = 0; - l2cap_pi(sk)->unacked_frames = 0; + chan->unacked_frames = 0; chan->buffer_seq = 0; - l2cap_pi(sk)->num_acked = 0; - l2cap_pi(sk)->frames_sent = 0; + chan->num_acked = 0; + chan->frames_sent = 0; setup_timer(&l2cap_pi(sk)->retrans_timer, l2cap_retrans_timeout, (unsigned long) chan); @@ -2787,10 +2787,9 @@ static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb) static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u16 control = 0; - pi->frames_sent = 0; + chan->frames_sent = 0; control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; @@ -2806,7 +2805,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) l2cap_ertm_send(chan); if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) && - pi->frames_sent == 0) { + chan->frames_sent == 0) { control |= L2CAP_SUPER_RCV_READY; l2cap_send_sframe(chan, control); } @@ -2988,7 +2987,7 @@ static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL; l2cap_send_sframe(chan, control); - l2cap_pi(sk)->retry_count = 1; + chan->retry_count = 1; del_timer(&pi->retrans_timer); __mod_monitor_timer(); @@ -3260,7 +3259,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont if (L2CAP_CTRL_FINAL & rx_control && chan->conn_state & L2CAP_CONN_WAIT_F) { del_timer(&pi->monitor_timer); - if (pi->unacked_frames > 0) + if (chan->unacked_frames > 0) __mod_retrans_timer(); chan->conn_state &= ~L2CAP_CONN_WAIT_F; } @@ -3369,8 +3368,8 @@ expected: __mod_ack_timer(); - pi->num_acked = (pi->num_acked + 1) % num_to_ack; - if (pi->num_acked == num_to_ack - 1) + chan->num_acked = (chan->num_acked + 1) % num_to_ack; + if (chan->num_acked == num_to_ack - 1) l2cap_send_ack(chan); return 0; @@ -3383,7 +3382,6 @@ drop: static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control) { struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control), rx_control); @@ -3395,7 +3393,7 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co chan->conn_state |= L2CAP_CONN_SEND_FBIT; if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && - (pi->unacked_frames > 0)) + (chan->unacked_frames > 0)) __mod_retrans_timer(); chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; @@ -3414,7 +3412,7 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co } else { if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && - (pi->unacked_frames > 0)) + (chan->unacked_frames > 0)) __mod_retrans_timer(); chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; @@ -3450,7 +3448,6 @@ static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_c } static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_reqseq(rx_control); BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); @@ -3467,19 +3464,19 @@ static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_ l2cap_ertm_send(chan); if (chan->conn_state & L2CAP_CONN_WAIT_F) { - pi->srej_save_reqseq = tx_seq; + chan->srej_save_reqseq = tx_seq; chan->conn_state |= L2CAP_CONN_SREJ_ACT; } } else if (rx_control & L2CAP_CTRL_FINAL) { if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) && - pi->srej_save_reqseq == tx_seq) + chan->srej_save_reqseq == tx_seq) chan->conn_state &= ~L2CAP_CONN_SREJ_ACT; else l2cap_retransmit_one_frame(chan, tx_seq); } else { l2cap_retransmit_one_frame(chan, tx_seq); if (chan->conn_state & L2CAP_CONN_WAIT_F) { - pi->srej_save_reqseq = tx_seq; + chan->srej_save_reqseq = tx_seq; chan->conn_state |= L2CAP_CONN_SREJ_ACT; } } @@ -3521,7 +3518,7 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_cont if (L2CAP_CTRL_FINAL & rx_control && chan->conn_state & L2CAP_CONN_WAIT_F) { del_timer(&l2cap_pi(sk)->monitor_timer); - if (l2cap_pi(sk)->unacked_frames > 0) + if (chan->unacked_frames > 0) __mod_retrans_timer(); chan->conn_state &= ~L2CAP_CONN_WAIT_F; } -- cgit v1.2.3-58-ga151 From 6f61fd475907bf0a1470cb969ee993a31d305513 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 20:09:37 -0300 Subject: Bluetooth: Move SDU related vars to struct l2cap_chan As part of the moving channel stuff to l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 8 ++--- net/bluetooth/l2cap_core.c | 74 +++++++++++++++++++++---------------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 041213b4175a..19d613bbcf00 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -298,6 +298,10 @@ struct l2cap_chan { __u8 unacked_frames; __u8 retry_count; __u8 num_acked; + __u16 sdu_len; + __u16 partial_sdu_len; + struct sk_buff *sdu; + struct list_head list; }; @@ -364,10 +368,6 @@ struct l2cap_pinfo { __u8 conf_state; - __u16 sdu_len; - __u16 partial_sdu_len; - struct sk_buff *sdu; - __u8 tx_win; __u8 max_tx; __u8 remote_tx_win; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 3f601d1c164a..8ccfcdf3e083 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -2875,13 +2875,13 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk if (chan->conn_state & L2CAP_CONN_SAR_SDU) goto drop; - pi->sdu_len = get_unaligned_le16(skb->data); + chan->sdu_len = get_unaligned_le16(skb->data); - if (pi->sdu_len > pi->imtu) + if (chan->sdu_len > pi->imtu) goto disconnect; - pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC); - if (!pi->sdu) + chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC); + if (!chan->sdu) return -ENOMEM; /* pull sdu_len bytes only after alloc, because of Local Busy @@ -2889,24 +2889,24 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk * only once, i.e., when alloc does not fail */ skb_pull(skb, 2); - memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); chan->conn_state |= L2CAP_CONN_SAR_SDU; - pi->partial_sdu_len = skb->len; + chan->partial_sdu_len = skb->len; break; case L2CAP_SDU_CONTINUE: if (!(chan->conn_state & L2CAP_CONN_SAR_SDU)) goto disconnect; - if (!pi->sdu) + if (!chan->sdu) goto disconnect; - pi->partial_sdu_len += skb->len; - if (pi->partial_sdu_len > pi->sdu_len) + chan->partial_sdu_len += skb->len; + if (chan->partial_sdu_len > chan->sdu_len) goto drop; - memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); break; @@ -2914,22 +2914,22 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk if (!(chan->conn_state & L2CAP_CONN_SAR_SDU)) goto disconnect; - if (!pi->sdu) + if (!chan->sdu) goto disconnect; if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) { - pi->partial_sdu_len += skb->len; + chan->partial_sdu_len += skb->len; - if (pi->partial_sdu_len > pi->imtu) + if (chan->partial_sdu_len > pi->imtu) goto drop; - if (pi->partial_sdu_len != pi->sdu_len) + if (chan->partial_sdu_len != chan->sdu_len) goto drop; - memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); } - _skb = skb_clone(pi->sdu, GFP_ATOMIC); + _skb = skb_clone(chan->sdu, GFP_ATOMIC); if (!_skb) { chan->conn_state |= L2CAP_CONN_SAR_RETRY; return -ENOMEM; @@ -2945,7 +2945,7 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk chan->conn_state &= ~L2CAP_CONN_SAR_RETRY; chan->conn_state &= ~L2CAP_CONN_SAR_SDU; - kfree_skb(pi->sdu); + kfree_skb(chan->sdu); break; } @@ -2953,8 +2953,8 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk return 0; drop: - kfree_skb(pi->sdu); - pi->sdu = NULL; + kfree_skb(chan->sdu); + chan->sdu = NULL; disconnect: l2cap_send_disconn_req(pi->conn, chan->sk, ECONNRESET); @@ -3104,7 +3104,7 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf switch (control & L2CAP_CTRL_SAR) { case L2CAP_SDU_UNSEGMENTED: if (chan->conn_state & L2CAP_CONN_SAR_SDU) { - kfree_skb(pi->sdu); + kfree_skb(chan->sdu); break; } @@ -3116,28 +3116,28 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf case L2CAP_SDU_START: if (chan->conn_state & L2CAP_CONN_SAR_SDU) { - kfree_skb(pi->sdu); + kfree_skb(chan->sdu); break; } - pi->sdu_len = get_unaligned_le16(skb->data); + chan->sdu_len = get_unaligned_le16(skb->data); skb_pull(skb, 2); - if (pi->sdu_len > pi->imtu) { + if (chan->sdu_len > pi->imtu) { err = -EMSGSIZE; break; } - pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC); - if (!pi->sdu) { + chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC); + if (!chan->sdu) { err = -ENOMEM; break; } - memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); chan->conn_state |= L2CAP_CONN_SAR_SDU; - pi->partial_sdu_len = skb->len; + chan->partial_sdu_len = skb->len; err = 0; break; @@ -3145,11 +3145,11 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf if (!(chan->conn_state & L2CAP_CONN_SAR_SDU)) break; - memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); - pi->partial_sdu_len += skb->len; - if (pi->partial_sdu_len > pi->sdu_len) - kfree_skb(pi->sdu); + chan->partial_sdu_len += skb->len; + if (chan->partial_sdu_len > chan->sdu_len) + kfree_skb(chan->sdu); else err = 0; @@ -3159,16 +3159,16 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf if (!(chan->conn_state & L2CAP_CONN_SAR_SDU)) break; - memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); chan->conn_state &= ~L2CAP_CONN_SAR_SDU; - pi->partial_sdu_len += skb->len; + chan->partial_sdu_len += skb->len; - if (pi->partial_sdu_len > pi->imtu) + if (chan->partial_sdu_len > pi->imtu) goto drop; - if (pi->partial_sdu_len == pi->sdu_len) { - _skb = skb_clone(pi->sdu, GFP_ATOMIC); + if (chan->partial_sdu_len == chan->sdu_len) { + _skb = skb_clone(chan->sdu, GFP_ATOMIC); err = sock_queue_rcv_skb(chan->sk, _skb); if (err < 0) kfree_skb(_skb); @@ -3176,7 +3176,7 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf err = 0; drop: - kfree_skb(pi->sdu); + kfree_skb(chan->sdu); break; } -- cgit v1.2.3-58-ga151 From 2c03a7a49e0831646bd35d0877ec7d051d8f174b Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 20:15:28 -0300 Subject: Bluetooth: Move remote info to struct l2cap_chan As part of the moving channel stuff to l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 10 +++++----- net/bluetooth/l2cap_core.c | 32 ++++++++++++++++---------------- net/bluetooth/l2cap_sock.c | 4 ++-- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 19d613bbcf00..11c53cb4a116 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -302,6 +302,9 @@ struct l2cap_chan { __u16 partial_sdu_len; struct sk_buff *sdu; + __u8 remote_tx_win; + __u8 remote_max_tx; + __u16 remote_mps; struct list_head list; }; @@ -370,11 +373,8 @@ struct l2cap_pinfo { __u8 tx_win; __u8 max_tx; - __u8 remote_tx_win; - __u8 remote_max_tx; __u16 retrans_timeout; __u16 monitor_timeout; - __u16 remote_mps; __u16 mps; __le16 sport; @@ -431,7 +431,7 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch) if (sub < 0) sub += 64; - return sub == l2cap_pi(ch->sk)->remote_tx_win; + return sub == ch->remote_tx_win; } #define __get_txseq(ctrl) (((ctrl) & L2CAP_CTRL_TXSEQ) >> 1) @@ -454,7 +454,7 @@ int __l2cap_wait_ack(struct sock *sk); struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len); struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len); struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen); -int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len); +int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); void l2cap_do_send(struct sock *sk, struct sk_buff *skb); void l2cap_streaming_send(struct l2cap_chan *chan); int l2cap_ertm_send(struct l2cap_chan *chan); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8ccfcdf3e083..2176a003087e 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -956,7 +956,7 @@ static void l2cap_monitor_timeout(unsigned long arg) BT_DBG("chan %p", chan); bh_lock_sock(sk); - if (chan->retry_count >= l2cap_pi(sk)->remote_max_tx) { + if (chan->retry_count >= chan->remote_max_tx) { l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED); bh_unlock_sock(sk); return; @@ -1065,8 +1065,8 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) } while ((skb = skb_queue_next(TX_QUEUE(sk), skb))); - if (pi->remote_max_tx && - bt_cb(skb)->retries == pi->remote_max_tx) { + if (chan->remote_max_tx && + bt_cb(skb)->retries == chan->remote_max_tx) { l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED); return; } @@ -1106,8 +1106,8 @@ int l2cap_ertm_send(struct l2cap_chan *chan) while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(chan))) { - if (pi->remote_max_tx && - bt_cb(skb)->retries == pi->remote_max_tx) { + if (chan->remote_max_tx && + bt_cb(skb)->retries == chan->remote_max_tx) { l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED); break; } @@ -1337,9 +1337,9 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz return skb; } -int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len) +int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct sock *sk = chan->sk; struct sk_buff *skb; struct sk_buff_head sar_queue; u16 control; @@ -1347,20 +1347,20 @@ int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len) skb_queue_head_init(&sar_queue); control = L2CAP_SDU_START; - skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len); + skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len); if (IS_ERR(skb)) return PTR_ERR(skb); __skb_queue_tail(&sar_queue, skb); - len -= pi->remote_mps; - size += pi->remote_mps; + len -= chan->remote_mps; + size += chan->remote_mps; while (len > 0) { size_t buflen; - if (len > pi->remote_mps) { + if (len > chan->remote_mps) { control = L2CAP_SDU_CONTINUE; - buflen = pi->remote_mps; + buflen = chan->remote_mps; } else { control = L2CAP_SDU_END; buflen = len; @@ -1810,13 +1810,13 @@ done: break; case L2CAP_MODE_ERTM: - pi->remote_tx_win = rfc.txwin_size; - pi->remote_max_tx = rfc.max_transmit; + chan->remote_tx_win = rfc.txwin_size; + chan->remote_max_tx = rfc.max_transmit; if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10) rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); - pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); + chan->remote_mps = le16_to_cpu(rfc.max_pdu_size); rfc.retrans_timeout = le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO); @@ -1834,7 +1834,7 @@ done: if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10) rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); - pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); + chan->remote_mps = le16_to_cpu(rfc.max_pdu_size); pi->conf_state |= L2CAP_CONF_MODE_DONE; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 19574e43226a..f90ca2586eaf 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -757,7 +757,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms case L2CAP_MODE_ERTM: case L2CAP_MODE_STREAMING: /* Entire SDU fits into one PDU */ - if (len <= pi->remote_mps) { + if (len <= pi->chan->remote_mps) { control = L2CAP_SDU_UNSEGMENTED; skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0); if (IS_ERR(skb)) { @@ -771,7 +771,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms } else { /* Segment SDU into multiples PDUs */ - err = l2cap_sar_segment_sdu(sk, msg, len); + err = l2cap_sar_segment_sdu(pi->chan, msg, len); if (err < 0) goto done; } -- cgit v1.2.3-58-ga151 From e92c8e70faf5e3cc22979daba2a895359aa1eab2 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 1 Apr 2011 00:53:45 -0300 Subject: Bluetooth: Move ERTM timers to struct l2cap_chan This also triggered a change in l2cap_send_disconn_req() parameters. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 15 +++++---- net/bluetooth/l2cap_core.c | 74 +++++++++++++++++++++---------------------- net/bluetooth/l2cap_sock.c | 13 ++++---- 3 files changed, 51 insertions(+), 51 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 11c53cb4a116..5f4abea313a2 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -306,6 +306,10 @@ struct l2cap_chan { __u8 remote_max_tx; __u16 remote_mps; + struct timer_list retrans_timer; + struct timer_list monitor_timer; + struct timer_list ack_timer; + struct list_head list; }; @@ -379,9 +383,6 @@ struct l2cap_pinfo { __le16 sport; - struct timer_list retrans_timer; - struct timer_list monitor_timer; - struct timer_list ack_timer; struct sk_buff_head tx_queue; struct sk_buff_head srej_queue; struct sk_buff_head busy_queue; @@ -415,11 +416,11 @@ struct l2cap_pinfo { #define L2CAP_CONN_RNR_SENT 0x0200 #define L2CAP_CONN_SAR_RETRY 0x0400 -#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ +#define __mod_retrans_timer() mod_timer(&chan->retrans_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); -#define __mod_monitor_timer() mod_timer(&l2cap_pi(sk)->monitor_timer, \ +#define __mod_monitor_timer() mod_timer(&chan->monitor_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO)); -#define __mod_ack_timer() mod_timer(&l2cap_pi(sk)->ack_timer, \ +#define __mod_ack_timer() mod_timer(&chan->ack_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); static inline int l2cap_tx_window_full(struct l2cap_chan *ch) @@ -466,7 +467,7 @@ void l2cap_sock_kill(struct sock *sk); void l2cap_sock_init(struct sock *sk, struct sock *parent); struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); -void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err); +void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); void l2cap_chan_del(struct l2cap_chan *chan, int err); int l2cap_do_connect(struct sock *sk); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 2176a003087e..eaac13cb7932 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -241,9 +241,9 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { struct srej_list *l, *tmp; - del_timer(&l2cap_pi(sk)->retrans_timer); - del_timer(&l2cap_pi(sk)->monitor_timer); - del_timer(&l2cap_pi(sk)->ack_timer); + del_timer(&chan->retrans_timer); + del_timer(&chan->monitor_timer); + del_timer(&chan->ack_timer); skb_queue_purge(SREJ_QUEUE(sk)); skb_queue_purge(BUSY_QUEUE(sk)); @@ -462,19 +462,22 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) } } -void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err) +void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) { + struct sock *sk; struct l2cap_disconn_req req; if (!conn) return; + sk = chan->sk; + skb_queue_purge(TX_QUEUE(sk)); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { - del_timer(&l2cap_pi(sk)->retrans_timer); - del_timer(&l2cap_pi(sk)->monitor_timer); - del_timer(&l2cap_pi(sk)->ack_timer); + del_timer(&chan->retrans_timer); + del_timer(&chan->monitor_timer); + del_timer(&chan->ack_timer); } req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid); @@ -957,7 +960,7 @@ static void l2cap_monitor_timeout(unsigned long arg) bh_lock_sock(sk); if (chan->retry_count >= chan->remote_max_tx) { - l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED); + l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED); bh_unlock_sock(sk); return; } @@ -1003,7 +1006,7 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan) } if (!chan->unacked_frames) - del_timer(&l2cap_pi(sk)->retrans_timer); + del_timer(&chan->retrans_timer); } void l2cap_do_send(struct sock *sk, struct sk_buff *skb) @@ -1067,7 +1070,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) if (chan->remote_max_tx && bt_cb(skb)->retries == chan->remote_max_tx) { - l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED); + l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED); return; } @@ -1108,7 +1111,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan) if (chan->remote_max_tx && bt_cb(skb)->retries == chan->remote_max_tx) { - l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED); + l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED); break; } @@ -1579,12 +1582,11 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan) chan->num_acked = 0; chan->frames_sent = 0; - setup_timer(&l2cap_pi(sk)->retrans_timer, - l2cap_retrans_timeout, (unsigned long) chan); - setup_timer(&l2cap_pi(sk)->monitor_timer, - l2cap_monitor_timeout, (unsigned long) chan); - setup_timer(&l2cap_pi(sk)->ack_timer, - l2cap_ack_timeout, (unsigned long) chan); + setup_timer(&chan->retrans_timer, l2cap_retrans_timeout, + (unsigned long) chan); + setup_timer(&chan->monitor_timer, l2cap_monitor_timeout, + (unsigned long) chan); + setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan); __skb_queue_head_init(SREJ_QUEUE(sk)); __skb_queue_head_init(BUSY_QUEUE(sk)); @@ -2291,7 +2293,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr /* Complete config. */ len = l2cap_parse_conf_req(chan, rsp); if (len < 0) { - l2cap_send_disconn_req(conn, sk, ECONNRESET); + l2cap_send_disconn_req(conn, chan, ECONNRESET); goto unlock; } @@ -2363,7 +2365,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr char req[64]; if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { - l2cap_send_disconn_req(conn, sk, ECONNRESET); + l2cap_send_disconn_req(conn, chan, ECONNRESET); goto done; } @@ -2372,7 +2374,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr len = l2cap_parse_conf_rsp(sk, rsp->data, len, req, &result); if (len < 0) { - l2cap_send_disconn_req(conn, sk, ECONNRESET); + l2cap_send_disconn_req(conn, chan, ECONNRESET); goto done; } @@ -2387,7 +2389,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr default: sk->sk_err = ECONNRESET; l2cap_sock_set_timer(sk, HZ * 5); - l2cap_send_disconn_req(conn, sk, ECONNRESET); + l2cap_send_disconn_req(conn, chan, ECONNRESET); goto done; } @@ -2957,7 +2959,7 @@ drop: chan->sdu = NULL; disconnect: - l2cap_send_disconn_req(pi->conn, chan->sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); kfree_skb(skb); return 0; } @@ -2965,7 +2967,6 @@ disconnect: static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) { struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *skb; u16 control; int err; @@ -2989,7 +2990,7 @@ static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) l2cap_send_sframe(chan, control); chan->retry_count = 1; - del_timer(&pi->retrans_timer); + del_timer(&chan->retrans_timer); __mod_monitor_timer(); chan->conn_state |= L2CAP_CONN_WAIT_F; @@ -3020,7 +3021,7 @@ static void l2cap_busy_work(struct work_struct *work) if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) { err = -EBUSY; - l2cap_send_disconn_req(pi->conn, sk, EBUSY); + l2cap_send_disconn_req(pi->conn, pi->chan, EBUSY); break; } @@ -3083,7 +3084,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c chan->conn_state |= L2CAP_CONN_RNR_SENT; - del_timer(&pi->ack_timer); + del_timer(&chan->ack_timer); queue_work(_busy_wq, &pi->busy_work); @@ -3258,7 +3259,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont if (L2CAP_CTRL_FINAL & rx_control && chan->conn_state & L2CAP_CONN_WAIT_F) { - del_timer(&pi->monitor_timer); + del_timer(&chan->monitor_timer); if (chan->unacked_frames > 0) __mod_retrans_timer(); chan->conn_state &= ~L2CAP_CONN_WAIT_F; @@ -3276,7 +3277,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont /* invalid tx_seq */ if (tx_seq_offset >= pi->tx_win) { - l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } @@ -3341,7 +3342,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont l2cap_send_srejframe(chan, tx_seq); - del_timer(&pi->ack_timer); + del_timer(&chan->ack_timer); } return 0; @@ -3484,7 +3485,6 @@ static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_reqseq(rx_control); BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); @@ -3497,7 +3497,7 @@ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_c chan->conn_state |= L2CAP_CONN_SEND_FBIT; if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) { - del_timer(&pi->retrans_timer); + del_timer(&chan->retrans_timer); if (rx_control & L2CAP_CTRL_POLL) l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL); return; @@ -3511,13 +3511,11 @@ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_c static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb) { - struct sock *sk = chan->sk; - BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len); if (L2CAP_CTRL_FINAL & rx_control && chan->conn_state & L2CAP_CONN_WAIT_F) { - del_timer(&l2cap_pi(sk)->monitor_timer); + del_timer(&chan->monitor_timer); if (chan->unacked_frames > 0) __mod_retrans_timer(); chan->conn_state &= ~L2CAP_CONN_WAIT_F; @@ -3572,7 +3570,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) len -= 2; if (len > pi->mps) { - l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } @@ -3588,13 +3586,13 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) /* check for invalid req-seq */ if (req_seq_offset > next_tx_seq_offset) { - l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } if (__is_iframe(control)) { if (len < 0) { - l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } @@ -3602,7 +3600,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) } else { if (len != 0) { BT_ERR("%d", len); - l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index f90ca2586eaf..d66886f7eccb 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -866,6 +866,7 @@ static void l2cap_sock_cleanup_listen(struct sock *parent) void __l2cap_sock_close(struct sock *sk, int reason) { struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket); @@ -880,9 +881,9 @@ void __l2cap_sock_close(struct sock *sk, int reason) sk->sk_type == SOCK_STREAM) && conn->hcon->type == ACL_LINK) { l2cap_sock_set_timer(sk, sk->sk_sndtimeo); - l2cap_send_disconn_req(conn, sk, reason); + l2cap_send_disconn_req(conn, chan, reason); } else - l2cap_chan_del(l2cap_pi(sk)->chan, reason); + l2cap_chan_del(chan, reason); break; case BT_CONNECT2: @@ -901,16 +902,16 @@ void __l2cap_sock_close(struct sock *sk, int reason) rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.result = cpu_to_le16(result); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); - l2cap_send_cmd(conn, l2cap_pi(sk)->chan->ident, - L2CAP_CONN_RSP, sizeof(rsp), &rsp); + l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, + sizeof(rsp), &rsp); } - l2cap_chan_del(l2cap_pi(sk)->chan, reason); + l2cap_chan_del(chan, reason); break; case BT_CONNECT: case BT_DISCONN: - l2cap_chan_del(l2cap_pi(sk)->chan, reason); + l2cap_chan_del(chan, reason); break; default: -- cgit v1.2.3-58-ga151 From f1c6775be6fc944e32e0150305d9753b9a846519 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 20:36:10 -0300 Subject: Bluetooth: Move srej and busy queues to struct l2cap_chan As part of the moving channel stuff to l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 6 ++---- net/bluetooth/l2cap_core.c | 42 ++++++++++++++++++++---------------------- net/bluetooth/l2cap_sock.c | 2 -- 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 5f4abea313a2..09f4a2fc2e20 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -309,6 +309,8 @@ struct l2cap_chan { struct timer_list retrans_timer; struct timer_list monitor_timer; struct timer_list ack_timer; + struct sk_buff_head srej_q; + struct sk_buff_head busy_q; struct list_head list; }; @@ -347,8 +349,6 @@ struct l2cap_conn { /* ----- L2CAP socket info ----- */ #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) #define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) -#define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue) -#define BUSY_QUEUE(sk) (&l2cap_pi(sk)->busy_queue) #define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list) struct srej_list { @@ -384,8 +384,6 @@ struct l2cap_pinfo { __le16 sport; struct sk_buff_head tx_queue; - struct sk_buff_head srej_queue; - struct sk_buff_head busy_queue; struct work_struct busy_work; struct srej_list srej_l; struct l2cap_conn *conn; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index eaac13cb7932..06c505b1476d 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -245,8 +245,8 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) del_timer(&chan->monitor_timer); del_timer(&chan->ack_timer); - skb_queue_purge(SREJ_QUEUE(sk)); - skb_queue_purge(BUSY_QUEUE(sk)); + skb_queue_purge(&chan->srej_q); + skb_queue_purge(&chan->busy_q); list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { list_del(&l->list); @@ -1588,8 +1588,8 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan) (unsigned long) chan); setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan); - __skb_queue_head_init(SREJ_QUEUE(sk)); - __skb_queue_head_init(BUSY_QUEUE(sk)); + skb_queue_head_init(&chan->srej_q); + skb_queue_head_init(&chan->busy_q); INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work); @@ -2815,16 +2815,15 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar) { - struct sock *sk = chan->sk; struct sk_buff *next_skb; int tx_seq_offset, next_tx_seq_offset; bt_cb(skb)->tx_seq = tx_seq; bt_cb(skb)->sar = sar; - next_skb = skb_peek(SREJ_QUEUE(sk)); + next_skb = skb_peek(&chan->srej_q); if (!next_skb) { - __skb_queue_tail(SREJ_QUEUE(sk), skb); + __skb_queue_tail(&chan->srej_q, skb); return 0; } @@ -2842,16 +2841,16 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, next_tx_seq_offset += 64; if (next_tx_seq_offset > tx_seq_offset) { - __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb); + __skb_queue_before(&chan->srej_q, next_skb, skb); return 0; } - if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb)) + if (skb_queue_is_last(&chan->srej_q, next_skb)) break; - } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb))); + } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb))); - __skb_queue_tail(SREJ_QUEUE(sk), skb); + __skb_queue_tail(&chan->srej_q, skb); return 0; } @@ -2971,11 +2970,11 @@ static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) u16 control; int err; - while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) { + while ((skb = skb_dequeue(&chan->busy_q))) { control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; err = l2cap_ertm_reassembly_sdu(chan, skb, control); if (err < 0) { - skb_queue_head(BUSY_QUEUE(sk), skb); + skb_queue_head(&chan->busy_q, skb); return -EBUSY; } @@ -3016,7 +3015,7 @@ static void l2cap_busy_work(struct work_struct *work) lock_sock(sk); add_wait_queue(sk_sleep(sk), &wait); - while ((skb = skb_peek(BUSY_QUEUE(sk)))) { + while ((skb = skb_peek(&pi->chan->busy_q))) { set_current_state(TASK_INTERRUPTIBLE); if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) { @@ -3059,7 +3058,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; - __skb_queue_tail(BUSY_QUEUE(sk), skb); + __skb_queue_tail(&chan->busy_q, skb); return l2cap_try_push_rx_skb(chan); @@ -3076,7 +3075,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c chan->conn_state |= L2CAP_CONN_LOCAL_BUSY; bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; - __skb_queue_tail(BUSY_QUEUE(sk), skb); + __skb_queue_tail(&chan->busy_q, skb); sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; sctrl |= L2CAP_SUPER_RCV_NOT_READY; @@ -3187,15 +3186,14 @@ drop: static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq) { - struct sock *sk = chan->sk; struct sk_buff *skb; u16 control; - while ((skb = skb_peek(SREJ_QUEUE(sk)))) { + while ((skb = skb_peek(&chan->srej_q))) { if (bt_cb(skb)->tx_seq != tx_seq) break; - skb = skb_dequeue(SREJ_QUEUE(sk)); + skb = skb_dequeue(&chan->srej_q); control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; l2cap_ertm_reassembly_sdu(chan, skb, control); chan->buffer_seq_srej = @@ -3334,8 +3332,8 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont INIT_LIST_HEAD(SREJ_LIST(sk)); chan->buffer_seq_srej = chan->buffer_seq; - __skb_queue_head_init(SREJ_QUEUE(sk)); - __skb_queue_head_init(BUSY_QUEUE(sk)); + __skb_queue_head_init(&chan->srej_q); + __skb_queue_head_init(&chan->busy_q); l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); chan->conn_state |= L2CAP_CONN_SEND_PBIT; @@ -3352,7 +3350,7 @@ expected: if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { bt_cb(skb)->tx_seq = tx_seq; bt_cb(skb)->sar = sar; - __skb_queue_tail(SREJ_QUEUE(sk), skb); + __skb_queue_tail(&chan->srej_q, skb); return 0; } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index d66886f7eccb..55dee999af94 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1018,8 +1018,6 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) /* Default config options */ pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; skb_queue_head_init(TX_QUEUE(sk)); - skb_queue_head_init(SREJ_QUEUE(sk)); - skb_queue_head_init(BUSY_QUEUE(sk)); INIT_LIST_HEAD(SREJ_LIST(sk)); } -- cgit v1.2.3-58-ga151 From 311bb895e325e5f4d708c1ed2206da8a3885c83a Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 20:41:00 -0300 Subject: Bluetooth: Move busy workqueue to struct l2cap_chan As part of the moving channel stuff to l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 2 +- net/bluetooth/l2cap_core.c | 20 +++++++++----------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 09f4a2fc2e20..d05d91f2fd32 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -311,6 +311,7 @@ struct l2cap_chan { struct timer_list ack_timer; struct sk_buff_head srej_q; struct sk_buff_head busy_q; + struct work_struct busy_work; struct list_head list; }; @@ -384,7 +385,6 @@ struct l2cap_pinfo { __le16 sport; struct sk_buff_head tx_queue; - struct work_struct busy_work; struct srej_list srej_l; struct l2cap_conn *conn; struct l2cap_chan *chan; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 06c505b1476d..d3b5d6489a80 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1591,7 +1591,7 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan) skb_queue_head_init(&chan->srej_q); skb_queue_head_init(&chan->busy_q); - INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work); + INIT_WORK(&chan->busy_work, l2cap_busy_work); sk->sk_backlog_rcv = l2cap_ertm_data_rcv; } @@ -3006,21 +3006,21 @@ done: static void l2cap_busy_work(struct work_struct *work) { DECLARE_WAITQUEUE(wait, current); - struct l2cap_pinfo *pi = - container_of(work, struct l2cap_pinfo, busy_work); - struct sock *sk = (struct sock *)pi; + struct l2cap_chan *chan = + container_of(work, struct l2cap_chan, busy_work); + struct sock *sk = chan->sk; int n_tries = 0, timeo = HZ/5, err; struct sk_buff *skb; lock_sock(sk); add_wait_queue(sk_sleep(sk), &wait); - while ((skb = skb_peek(&pi->chan->busy_q))) { + while ((skb = skb_peek(&chan->busy_q))) { set_current_state(TASK_INTERRUPTIBLE); if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) { err = -EBUSY; - l2cap_send_disconn_req(pi->conn, pi->chan, EBUSY); + l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY); break; } @@ -3040,7 +3040,7 @@ static void l2cap_busy_work(struct work_struct *work) if (err) break; - if (l2cap_try_push_rx_skb(l2cap_pi(sk)->chan) == 0) + if (l2cap_try_push_rx_skb(chan) == 0) break; } @@ -3052,8 +3052,6 @@ static void l2cap_busy_work(struct work_struct *work) static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) { - struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); int sctrl, err; if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { @@ -3071,7 +3069,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c } /* Busy Condition */ - BT_DBG("sk %p, Enter local busy", sk); + BT_DBG("chan %p, Enter local busy", chan); chan->conn_state |= L2CAP_CONN_LOCAL_BUSY; bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; @@ -3085,7 +3083,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c del_timer(&chan->ack_timer); - queue_work(_busy_wq, &pi->busy_work); + queue_work(_busy_wq, &chan->busy_work); return err; } -- cgit v1.2.3-58-ga151 From 2ead70b8390d199ca04cd35311b51f5f3676079e Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 1 Apr 2011 15:13:36 -0300 Subject: Bluetooth: Fix lockdep warning with skb list lock This is a regression acctually, caused by the first patch series for creating a formal strcut l2cap_chan. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index d3b5d6489a80..7264119b64a6 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -236,6 +236,10 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) } else sk->sk_state_change(sk); + if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE && + l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE)) + goto free; + skb_queue_purge(TX_QUEUE(sk)); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { @@ -254,6 +258,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) } } +free: kfree(chan); } -- cgit v1.2.3-58-ga151 From 4b97291429bf59c09a969184a7d2ebde7287e7eb Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Wed, 6 Apr 2011 18:07:43 +0000 Subject: be2net: add rxhash support Add rxhash support, Based on initial work by Eric Dumazet. Cc: Eric Dumazet Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 5 +++++ drivers/net/benet/be_ethtool.c | 13 +++++++++++++ drivers/net/benet/be_main.c | 17 ++++++++++++----- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index ea1ea824d7c7..ab5be0545e38 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -485,6 +485,11 @@ static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac) memcpy(mac, adapter->netdev->dev_addr, 3); } +static inline bool be_multi_rxq(const struct be_adapter *adapter) +{ + return adapter->num_rx_qs > 1; +} + extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped); extern void be_link_status_update(struct be_adapter *adapter, bool link_up); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index a665697df824..1565c81ff96c 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -735,6 +735,18 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, return status; } +static int be_set_flags(struct net_device *netdev, u32 data) +{ + struct be_adapter *adapter = netdev_priv(netdev); + int rc = -1; + + if (be_multi_rxq(adapter)) + rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_RXHASH | + ETH_FLAG_TXVLAN | ETH_FLAG_RXVLAN); + + return rc; +} + const struct ethtool_ops be_ethtool_ops = { .get_settings = be_get_settings, .get_drvinfo = be_get_drvinfo, @@ -764,4 +776,5 @@ const struct ethtool_ops be_ethtool_ops = { .get_regs = be_get_regs, .flash_device = be_do_flash, .self_test = be_self_test, + .set_flags = be_set_flags, }; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 2c3685389485..d762c2a3dd9b 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -116,11 +116,6 @@ static char *ue_status_hi_desc[] = { "Unknown" }; -static inline bool be_multi_rxq(struct be_adapter *adapter) -{ - return (adapter->num_rx_qs > 1); -} - static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q) { struct be_dma_mem *mem = &q->dma_mem; @@ -1012,6 +1007,9 @@ static void be_rx_compl_process(struct be_adapter *adapter, skb->truesize = skb->len + sizeof(struct sk_buff); skb->protocol = eth_type_trans(skb, adapter->netdev); + if (adapter->netdev->features & NETIF_F_RXHASH) + skb->rxhash = rxcp->rss_hash; + if (unlikely(rxcp->vlanf)) { if (!adapter->vlan_grp || adapter->vlans_added == 0) { @@ -1072,6 +1070,8 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, skb->data_len = rxcp->pkt_size; skb->truesize += rxcp->pkt_size; skb->ip_summed = CHECKSUM_UNNECESSARY; + if (adapter->netdev->features & NETIF_F_RXHASH) + skb->rxhash = rxcp->rss_hash; if (likely(!rxcp->vlanf)) napi_gro_frags(&eq_obj->napi); @@ -1101,6 +1101,8 @@ static void be_parse_rx_compl_v1(struct be_adapter *adapter, AMAP_GET_BITS(struct amap_eth_rx_compl_v1, numfrags, compl); rxcp->pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, cast_enc, compl); + rxcp->rss_hash = + AMAP_GET_BITS(struct amap_eth_rx_compl_v1, rsshash, rxcp); if (rxcp->vlanf) { rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm, compl); @@ -1131,6 +1133,8 @@ static void be_parse_rx_compl_v0(struct be_adapter *adapter, AMAP_GET_BITS(struct amap_eth_rx_compl_v0, numfrags, compl); rxcp->pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, cast_enc, compl); + rxcp->rss_hash = + AMAP_GET_BITS(struct amap_eth_rx_compl_v0, rsshash, rxcp); if (rxcp->vlanf) { rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm, compl); @@ -2615,6 +2619,9 @@ static void be_netdev_init(struct net_device *netdev) NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_GRO | NETIF_F_TSO6; + if (be_multi_rxq(adapter)) + netdev->features |= NETIF_F_RXHASH; + netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; -- cgit v1.2.3-58-ga151 From b0060586d23968d66325d775651d92ee830c032f Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Wed, 6 Apr 2011 18:08:01 +0000 Subject: be2net: use common method to check for sriov function type Lancer and BE can both use SLI_INTF_REG to check a VF or a PF. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index ab5be0545e38..7e2040084654 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -458,18 +458,10 @@ static inline u8 is_udp_pkt(struct sk_buff *skb) static inline void be_check_sriov_fn_type(struct be_adapter *adapter) { - u8 data; u32 sli_intf; - if (lancer_chip(adapter)) { - pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, - &sli_intf); - adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; - } else { - pci_write_config_byte(adapter->pdev, 0xFE, 0xAA); - pci_read_config_byte(adapter->pdev, 0xFE, &data); - adapter->is_virtfn = (data != 0xAA); - } + pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); + adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; } static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac) -- cgit v1.2.3-58-ga151 From 81be8f0ab47db1171dac0eb8b062291603b57dd4 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Wed, 6 Apr 2011 18:08:17 +0000 Subject: be2net: fix to get max VFs supported from adapter The user supplied num_vfs value need not be compared against a static BE_MAX_VF, but can be checked against the actual VFs that the device can support. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index d762c2a3dd9b..bc110782da88 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1947,7 +1947,20 @@ static void be_sriov_enable(struct be_adapter *adapter) be_check_sriov_fn_type(adapter); #ifdef CONFIG_PCI_IOV if (be_physfn(adapter) && num_vfs) { - int status; + int status, pos; + u16 nvfs; + + pos = pci_find_ext_capability(adapter->pdev, + PCI_EXT_CAP_ID_SRIOV); + pci_read_config_word(adapter->pdev, + pos + PCI_SRIOV_TOTAL_VF, &nvfs); + + if (num_vfs > nvfs) { + dev_info(&adapter->pdev->dev, + "Device supports %d VFs and not %d\n", + nvfs, num_vfs); + num_vfs = nvfs; + } status = pci_enable_sriov(adapter->pdev, num_vfs); adapter->sriov_enabled = status ? false : true; @@ -3284,13 +3297,6 @@ static int __init be_init_module(void) rx_frag_size = 2048; } - if (num_vfs > 32) { - printk(KERN_WARNING DRV_NAME - " : Module param num_vfs must not be greater than 32." - "Using 32\n"); - num_vfs = 32; - } - return pci_register_driver(&be_driver); } module_init(be_init_module); -- cgit v1.2.3-58-ga151 From 48f5a19168c228e6533401c563d9fcbc152bc33f Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Wed, 6 Apr 2011 18:08:30 +0000 Subject: be2net: dynamically allocate adapter->vf_cfg Instead of a fixed sized array for vf_cfg, allocate the size dynamically depending on number of VFs the device supports. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 4 +--- drivers/net/benet/be_main.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 7e2040084654..d2c42f5d5e9e 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -92,8 +92,6 @@ static inline char *nic_name(struct pci_dev *pdev) #define FW_VER_LEN 32 -#define BE_MAX_VF 32 - struct be_dma_mem { void *va; dma_addr_t dma; @@ -336,7 +334,7 @@ struct be_adapter { bool be3_native; bool sriov_enabled; - struct be_vf_cfg vf_cfg[BE_MAX_VF]; + struct be_vf_cfg *vf_cfg; u8 is_virtfn; u32 sli_family; u8 hba_port_num; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index bc110782da88..6e7df0dd418b 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2838,6 +2838,7 @@ static void __devexit be_remove(struct pci_dev *pdev) be_ctrl_cleanup(adapter); + kfree(adapter->vf_cfg); be_sriov_disable(adapter); be_msix_disable(adapter); @@ -3022,16 +3023,23 @@ static int __devinit be_probe(struct pci_dev *pdev, } be_sriov_enable(adapter); + if (adapter->sriov_enabled) { + adapter->vf_cfg = kcalloc(num_vfs, + sizeof(struct be_vf_cfg), GFP_KERNEL); + + if (!adapter->vf_cfg) + goto free_netdev; + } status = be_ctrl_init(adapter); if (status) - goto free_netdev; + goto free_vf_cfg; if (lancer_chip(adapter)) { status = lancer_test_and_set_rdy_state(adapter); if (status) { dev_err(&pdev->dev, "Adapter in non recoverable error\n"); - goto free_netdev; + goto ctrl_clean; } } @@ -3093,6 +3101,8 @@ stats_clean: be_stats_cleanup(adapter); ctrl_clean: be_ctrl_cleanup(adapter); +free_vf_cfg: + kfree(adapter->vf_cfg); free_netdev: be_sriov_disable(adapter); free_netdev(netdev); -- cgit v1.2.3-58-ga151 From 57841869197831542f25c739beaeab4465977878 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Wed, 6 Apr 2011 18:08:43 +0000 Subject: be2net: call FLR after setup wol in be_shutdown Calling setup_wol after a reset is inconsequential. The WOL setting should be programmed before FLR. And yes, FLR does not erase wol information. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 6e7df0dd418b..b8831403400c 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -3191,11 +3191,11 @@ static void be_shutdown(struct pci_dev *pdev) netif_device_detach(adapter->netdev); - be_cmd_reset_function(adapter); - if (adapter->wol) be_setup_wol(adapter, true); + be_cmd_reset_function(adapter); + pci_disable_device(pdev); } -- cgit v1.2.3-58-ga151 From e92702b1046a418a562878b22f92433517760921 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 31 Mar 2011 01:01:35 +0000 Subject: skge: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit just IP_CSUM. This needs testing and so is not changed here. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/skge.c | 53 +++++------------------------------------------------ drivers/net/skge.h | 1 - 2 files changed, 5 insertions(+), 49 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index e579ff7579ad..310dcbce2519 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -537,46 +537,6 @@ static int skge_nway_reset(struct net_device *dev) return 0; } -static int skge_set_sg(struct net_device *dev, u32 data) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - - if (hw->chip_id == CHIP_ID_GENESIS && data) - return -EOPNOTSUPP; - return ethtool_op_set_sg(dev, data); -} - -static int skge_set_tx_csum(struct net_device *dev, u32 data) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - - if (hw->chip_id == CHIP_ID_GENESIS && data) - return -EOPNOTSUPP; - - return ethtool_op_set_tx_csum(dev, data); -} - -static u32 skge_get_rx_csum(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - - return skge->rx_csum; -} - -/* Only Yukon supports checksum offload. */ -static int skge_set_rx_csum(struct net_device *dev, u32 data) -{ - struct skge_port *skge = netdev_priv(dev); - - if (skge->hw->chip_id == CHIP_ID_GENESIS && data) - return -EOPNOTSUPP; - - skge->rx_csum = data; - return 0; -} - static void skge_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *ecmd) { @@ -924,10 +884,6 @@ static const struct ethtool_ops skge_ethtool_ops = { .set_pauseparam = skge_set_pauseparam, .get_coalesce = skge_get_coalesce, .set_coalesce = skge_set_coalesce, - .set_sg = skge_set_sg, - .set_tx_csum = skge_set_tx_csum, - .get_rx_csum = skge_get_rx_csum, - .set_rx_csum = skge_set_rx_csum, .get_strings = skge_get_strings, .set_phys_id = skge_set_phys_id, .get_sset_count = skge_get_sset_count, @@ -3084,7 +3040,8 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, } skb_put(skb, len); - if (skge->rx_csum) { + + if (dev->features & NETIF_F_RXCSUM) { skb->csum = csum; skb->ip_summed = CHECKSUM_COMPLETE; } @@ -3846,10 +3803,10 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge); if (hw->chip_id != CHIP_ID_GENESIS) { - dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; - skge->rx_csum = 1; + dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | + NETIF_F_RXCSUM; + dev->features |= dev->hw_features; } - dev->features |= NETIF_F_GRO; /* read the mac address */ memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN); diff --git a/drivers/net/skge.h b/drivers/net/skge.h index 507addcaffa3..f055c47de47e 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -2460,7 +2460,6 @@ struct skge_port { struct timer_list link_timer; enum pause_control flow_control; enum pause_status flow_status; - u8 rx_csum; u8 blink_on; u8 wol; u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */ -- cgit v1.2.3-58-ga151 From 6332c8d3a5e352fae854cbcac764622e083461e5 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 7 Apr 2011 02:43:48 +0000 Subject: net: benet: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simple conversion. This also fixes a bug in TX checksum toggling --- driver was changing NETIF_F_HW_CSUM instead of NETIF_F_IP_CSUM+NETIF_F_IPV6_CSUM. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 1 - drivers/net/benet/be_ethtool.c | 27 --------------------------- drivers/net/benet/be_main.c | 19 ++++++++++--------- 3 files changed, 10 insertions(+), 37 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index d2c42f5d5e9e..a0b4743d7224 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -307,7 +307,6 @@ struct be_adapter { u16 work_counter; /* Ethtool knobs and info */ - bool rx_csum; /* BE card must perform rx-checksumming */ char fw_ver[FW_VER_LEN]; u32 if_handle; /* Used to configure filtering */ u32 pmac_id; /* MAC addr handle used by BE card */ diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 1565c81ff96c..96f5502e0ef7 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -261,25 +261,6 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) return 0; } -static u32 be_get_rx_csum(struct net_device *netdev) -{ - struct be_adapter *adapter = netdev_priv(netdev); - - return adapter->rx_csum; -} - -static int be_set_rx_csum(struct net_device *netdev, uint32_t data) -{ - struct be_adapter *adapter = netdev_priv(netdev); - - if (data) - adapter->rx_csum = true; - else - adapter->rx_csum = false; - - return 0; -} - static void be_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, uint64_t *data) @@ -760,14 +741,6 @@ const struct ethtool_ops be_ethtool_ops = { .get_ringparam = be_get_ringparam, .get_pauseparam = be_get_pauseparam, .set_pauseparam = be_set_pauseparam, - .get_rx_csum = be_get_rx_csum, - .set_rx_csum = be_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_hw_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, .get_strings = be_get_stat_strings, .set_phys_id = be_set_phys_id, .get_sset_count = be_get_sset_count, diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index b8831403400c..58a652f81862 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -988,9 +988,10 @@ static void be_rx_compl_process(struct be_adapter *adapter, struct be_rx_obj *rxo, struct be_rx_compl_info *rxcp) { + struct net_device *netdev = adapter->netdev; struct sk_buff *skb; - skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN); + skb = netdev_alloc_skb_ip_align(netdev, BE_HDR_LEN); if (unlikely(!skb)) { if (net_ratelimit()) dev_warn(&adapter->pdev->dev, "skb alloc failed\n"); @@ -1000,13 +1001,13 @@ static void be_rx_compl_process(struct be_adapter *adapter, skb_fill_rx_data(adapter, rxo, skb, rxcp); - if (likely(adapter->rx_csum && csum_passed(rxcp))) + if (likely((netdev->features & NETIF_F_RXCSUM) && csum_passed(rxcp))) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb_checksum_none_assert(skb); skb->truesize = skb->len + sizeof(struct sk_buff); - skb->protocol = eth_type_trans(skb, adapter->netdev); + skb->protocol = eth_type_trans(skb, netdev); if (adapter->netdev->features & NETIF_F_RXHASH) skb->rxhash = rxcp->rss_hash; @@ -2627,10 +2628,12 @@ static void be_netdev_init(struct net_device *netdev) struct be_rx_obj *rxo; int i; - netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | - NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | - NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_GRO | NETIF_F_TSO6; + netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; + + netdev->features |= netdev->hw_features | + NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_FILTER; if (be_multi_rxq(adapter)) netdev->features |= NETIF_F_RXHASH; @@ -2643,8 +2646,6 @@ static void be_netdev_init(struct net_device *netdev) netdev->flags |= IFF_MULTICAST; - adapter->rx_csum = true; - /* Default settings for Rx and Tx flow control */ adapter->rx_fc = true; adapter->tx_fc = true; -- cgit v1.2.3-58-ga151 From 5ec8f9b8e6d87faa9d3a4b079b83e3c0d9c39921 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 7 Apr 2011 02:43:48 +0000 Subject: net: enic: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As the driver uses GRO and not LRO, LRO settings are ignored anyway and are removed here to avoid confusion. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/enic/enic.h | 1 - drivers/net/enic/enic_main.c | 74 +++++--------------------------------------- drivers/net/enic/enic_res.c | 4 +-- 3 files changed, 10 insertions(+), 69 deletions(-) diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index 178b94d7f89b..38b351c7b979 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -84,7 +84,6 @@ struct enic { unsigned int flags; unsigned int mc_count; unsigned int uc_count; - int csum_rx_enabled; u32 port_mtu; u32 rx_coalesce_usecs; u32 tx_coalesce_usecs; diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 9a3a0277bf21..b2245511c51a 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -251,56 +251,6 @@ static void enic_get_ethtool_stats(struct net_device *netdev, *(data++) = ((u64 *)&vstats->rx)[enic_rx_stats[i].offset]; } -static u32 enic_get_rx_csum(struct net_device *netdev) -{ - struct enic *enic = netdev_priv(netdev); - return enic->csum_rx_enabled; -} - -static int enic_set_rx_csum(struct net_device *netdev, u32 data) -{ - struct enic *enic = netdev_priv(netdev); - - if (data && !ENIC_SETTING(enic, RXCSUM)) - return -EINVAL; - - enic->csum_rx_enabled = !!data; - - return 0; -} - -static int enic_set_tx_csum(struct net_device *netdev, u32 data) -{ - struct enic *enic = netdev_priv(netdev); - - if (data && !ENIC_SETTING(enic, TXCSUM)) - return -EINVAL; - - if (data) - netdev->features |= NETIF_F_HW_CSUM; - else - netdev->features &= ~NETIF_F_HW_CSUM; - - return 0; -} - -static int enic_set_tso(struct net_device *netdev, u32 data) -{ - struct enic *enic = netdev_priv(netdev); - - if (data && !ENIC_SETTING(enic, TSO)) - return -EINVAL; - - if (data) - netdev->features |= - NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN; - else - netdev->features &= - ~(NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN); - - return 0; -} - static u32 enic_get_msglevel(struct net_device *netdev) { struct enic *enic = netdev_priv(netdev); @@ -388,17 +338,8 @@ static const struct ethtool_ops enic_ethtool_ops = { .get_strings = enic_get_strings, .get_sset_count = enic_get_sset_count, .get_ethtool_stats = enic_get_ethtool_stats, - .get_rx_csum = enic_get_rx_csum, - .set_rx_csum = enic_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = enic_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = enic_set_tso, .get_coalesce = enic_get_coalesce, .set_coalesce = enic_set_coalesce, - .get_flags = ethtool_op_get_flags, }; static void enic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf) @@ -1309,7 +1250,7 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, skb_put(skb, bytes_written); skb->protocol = eth_type_trans(skb, netdev); - if (enic->csum_rx_enabled && !csum_not_calc) { + if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc) { skb->csum = htons(checksum); skb->ip_summed = CHECKSUM_COMPLETE; } @@ -2438,17 +2379,18 @@ static int __devinit enic_probe(struct pci_dev *pdev, dev_info(dev, "loopback tag=0x%04x\n", enic->loop_tag); } if (ENIC_SETTING(enic, TXCSUM)) - netdev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; + netdev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM; if (ENIC_SETTING(enic, TSO)) - netdev->features |= NETIF_F_TSO | + netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN; - if (ENIC_SETTING(enic, LRO)) - netdev->features |= NETIF_F_GRO; + if (ENIC_SETTING(enic, RXCSUM)) + netdev->hw_features |= NETIF_F_RXCSUM; + + netdev->features |= netdev->hw_features; + if (using_dac) netdev->features |= NETIF_F_HIGHDMA; - enic->csum_rx_enabled = ENIC_SETTING(enic, RXCSUM); - err = register_netdev(netdev); if (err) { dev_err(dev, "Cannot register net device, aborting\n"); diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c index f111a37419ce..6e5c6356e7df 100644 --- a/drivers/net/enic/enic_res.c +++ b/drivers/net/enic/enic_res.c @@ -98,9 +98,9 @@ int enic_get_vnic_config(struct enic *enic) "vNIC MAC addr %pM wq/rq %d/%d mtu %d\n", enic->mac_addr, c->wq_desc_count, c->rq_desc_count, c->mtu); dev_info(enic_get_dev(enic), "vNIC csum tx/rx %d/%d " - "tso/lro %d/%d intr timer %d usec rss %d\n", + "tso %d intr timer %d usec rss %d\n", ENIC_SETTING(enic, TXCSUM), ENIC_SETTING(enic, RXCSUM), - ENIC_SETTING(enic, TSO), ENIC_SETTING(enic, LRO), + ENIC_SETTING(enic, TSO), c->intr_timer_usec, ENIC_SETTING(enic, RSS)); return 0; -- cgit v1.2.3-58-ga151 From dc668910f4eaa233c241d43d96ed6b0b9258cc43 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 7 Apr 2011 03:35:07 +0000 Subject: net: tg3: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup hint: Some features are calculated in tg3_get_invariants() and the rest in its caller --- tg3_init_one(). This is not changed here. Signed-off-by: Michał Mirosław Acked-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/tg3.c | 135 +++++++++++++----------------------------------------- drivers/net/tg3.h | 2 - 2 files changed, 32 insertions(+), 105 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index d37ae8747ad1..38962afdce61 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4816,7 +4816,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) skb = copy_skb; } - if ((tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) && + if ((tp->dev->features & NETIF_F_RXCSUM) && (desc->type_flags & RXD_FLAG_TCPUDP_CSUM) && (((desc->ip_tcp_csum & RXD_TCPCSUM_MASK) >> RXD_TCPCSUM_SHIFT) == 0xffff)) @@ -6127,6 +6127,16 @@ dma_error: return NETDEV_TX_OK; } +static u32 tg3_fix_features(struct net_device *dev, u32 features) +{ + struct tg3 *tp = netdev_priv(dev); + + if (dev->mtu > ETH_DATA_LEN && (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) + features &= ~NETIF_F_ALL_TSO; + + return features; +} + static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, int new_mtu) { @@ -6134,14 +6144,16 @@ static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, if (new_mtu > ETH_DATA_LEN) { if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { + netdev_update_features(dev); tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; - ethtool_op_set_tso(dev, 0); } else { tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE; } } else { - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) + if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; + netdev_update_features(dev); + } tp->tg3_flags &= ~TG3_FLAG_JUMBO_RING_ENABLE; } } @@ -10021,33 +10033,6 @@ static void tg3_set_msglevel(struct net_device *dev, u32 value) tp->msg_enable = value; } -static int tg3_set_tso(struct net_device *dev, u32 value) -{ - struct tg3 *tp = netdev_priv(dev); - - if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { - if (value) - return -EINVAL; - return 0; - } - if ((dev->features & NETIF_F_IPV6_CSUM) && - ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) || - (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3))) { - if (value) { - dev->features |= NETIF_F_TSO6; - if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && - GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) - dev->features |= NETIF_F_TSO_ECN; - } else - dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN); - } - return ethtool_op_set_tso(dev, value); -} - static int tg3_nway_reset(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); @@ -10270,50 +10255,6 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam return err; } -static u32 tg3_get_rx_csum(struct net_device *dev) -{ - struct tg3 *tp = netdev_priv(dev); - return (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0; -} - -static int tg3_set_rx_csum(struct net_device *dev, u32 data) -{ - struct tg3 *tp = netdev_priv(dev); - - if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) { - if (data != 0) - return -EINVAL; - return 0; - } - - spin_lock_bh(&tp->lock); - if (data) - tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; - else - tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; - spin_unlock_bh(&tp->lock); - - return 0; -} - -static int tg3_set_tx_csum(struct net_device *dev, u32 data) -{ - struct tg3 *tp = netdev_priv(dev); - - if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) { - if (data != 0) - return -EINVAL; - return 0; - } - - if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) - ethtool_op_set_tx_ipv6_csum(dev, data); - else - ethtool_op_set_tx_csum(dev, data); - - return 0; -} - static int tg3_get_sset_count(struct net_device *dev, int sset) { switch (sset) { @@ -11390,11 +11331,6 @@ static const struct ethtool_ops tg3_ethtool_ops = { .set_ringparam = tg3_set_ringparam, .get_pauseparam = tg3_get_pauseparam, .set_pauseparam = tg3_set_pauseparam, - .get_rx_csum = tg3_get_rx_csum, - .set_rx_csum = tg3_set_rx_csum, - .set_tx_csum = tg3_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = tg3_set_tso, .self_test = tg3_self_test, .get_strings = tg3_get_strings, .set_phys_id = tg3_set_phys_id, @@ -13262,11 +13198,6 @@ done: static struct pci_dev * __devinit tg3_find_peer(struct tg3 *); -static inline void vlan_features_add(struct net_device *dev, unsigned long flags) -{ - dev->vlan_features |= flags; -} - static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp) { if (tp->tg3_flags3 & TG3_FLG3_LRG_PROD_RING_CAP) @@ -13513,16 +13444,14 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* 5700 B0 chips do not support checksumming correctly due * to hardware bugs. */ - if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0) - tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS; - else { - unsigned long features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_GRO; + if (tp->pci_chip_rev_id != CHIPREV_ID_5700_B0) { + u32 features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM; - tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) features |= NETIF_F_IPV6_CSUM; tp->dev->features |= features; - vlan_features_add(tp->dev, features); + tp->dev->hw_features |= features; + tp->dev->vlan_features |= features; } /* Determine TSO capabilities */ @@ -14794,6 +14723,7 @@ static const struct net_device_ops tg3_netdev_ops = { .ndo_do_ioctl = tg3_ioctl, .ndo_tx_timeout = tg3_tx_timeout, .ndo_change_mtu = tg3_change_mtu, + .ndo_fix_features = tg3_fix_features, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = tg3_poll_controller, #endif @@ -14824,6 +14754,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, u32 sndmbx, rcvmbx, intmbx; char str[40]; u64 dma_mask, persist_dma_mask; + u32 hw_features = 0; printk_once(KERN_INFO "%s\n", version); @@ -14984,27 +14915,25 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * is off by default, but can be enabled using ethtool. */ if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) && - (dev->features & NETIF_F_IP_CSUM)) { - dev->features |= NETIF_F_TSO; - vlan_features_add(dev, NETIF_F_TSO); - } + (dev->features & NETIF_F_IP_CSUM)) + hw_features |= NETIF_F_TSO; if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) || (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3)) { - if (dev->features & NETIF_F_IPV6_CSUM) { - dev->features |= NETIF_F_TSO6; - vlan_features_add(dev, NETIF_F_TSO6); - } + if (dev->features & NETIF_F_IPV6_CSUM) + hw_features |= NETIF_F_TSO6; if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) { - dev->features |= NETIF_F_TSO_ECN; - vlan_features_add(dev, NETIF_F_TSO_ECN); - } + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + hw_features |= NETIF_F_TSO_ECN; } + dev->hw_features |= hw_features; + dev->features |= hw_features; + dev->vlan_features |= hw_features; + if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 && !(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) && !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) { @@ -15133,7 +15062,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, } netdev_info(dev, "RXcsums[%d] LinkChgREG[%d] MIirq[%d] ASF[%d] TSOcap[%d]\n", - (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0, + (dev->features & NETIF_F_RXCSUM) != 0, (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0, (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT) != 0, (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0, diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index e7880d593aa8..73dda2787103 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2883,7 +2883,6 @@ struct tg3 { u32 tg3_flags; #define TG3_FLAG_TAGGED_STATUS 0x00000001 #define TG3_FLAG_TXD_MBOX_HWBUG 0x00000002 -#define TG3_FLAG_RX_CHECKSUMS 0x00000004 #define TG3_FLAG_USE_LINKCHG_REG 0x00000008 #define TG3_FLAG_ENABLE_ASF 0x00000020 #define TG3_FLAG_ASPM_WORKAROUND 0x00000040 @@ -2909,7 +2908,6 @@ struct tg3 { #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 #define TG3_FLAG_CPMU_PRESENT 0x04000000 #define TG3_FLAG_40BIT_DMA_BUG 0x08000000 -#define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 #define TG3_FLAG_JUMBO_CAPABLE 0x20000000 #define TG3_FLAG_CHIP_RESETTING 0x40000000 #define TG3_FLAG_INIT_COMPLETE 0x80000000 -- cgit v1.2.3-58-ga151 From 782d640afd15af7a1faf01cfe566ca4ac511319d Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 7 Apr 2011 07:32:18 +0000 Subject: net: atl*: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Things left as they were: - atl1: is RX checksum really enabled? - atl2: copy-paste from atl1, with-errors-on-modify I presume - atl1c: there's a bug: MTU can't be changed if device is not up Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/atl1c/atl1c_ethtool.c | 8 -------- drivers/net/atl1c/atl1c_main.c | 23 ++++++++++++++--------- drivers/net/atl1e/atl1e_ethtool.c | 3 --- drivers/net/atl1e/atl1e_main.c | 12 ++++-------- drivers/net/atlx/atl1.c | 15 +++++---------- drivers/net/atlx/atl2.c | 14 +------------- 6 files changed, 24 insertions(+), 51 deletions(-) diff --git a/drivers/net/atl1c/atl1c_ethtool.c b/drivers/net/atl1c/atl1c_ethtool.c index 7c521508313c..3af5a336a5af 100644 --- a/drivers/net/atl1c/atl1c_ethtool.c +++ b/drivers/net/atl1c/atl1c_ethtool.c @@ -113,11 +113,6 @@ static int atl1c_set_settings(struct net_device *netdev, return 0; } -static u32 atl1c_get_tx_csum(struct net_device *netdev) -{ - return (netdev->features & NETIF_F_HW_CSUM) != 0; -} - static u32 atl1c_get_msglevel(struct net_device *netdev) { struct atl1c_adapter *adapter = netdev_priv(netdev); @@ -307,9 +302,6 @@ static const struct ethtool_ops atl1c_ethtool_ops = { .get_link = ethtool_op_get_link, .get_eeprom_len = atl1c_get_eeprom_len, .get_eeprom = atl1c_get_eeprom, - .get_tx_csum = atl1c_get_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, }; void atl1c_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 7d9d5067a65c..894d485bf5bc 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -484,6 +484,15 @@ static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter, adapter->rx_buffer_len = mtu > AT_RX_BUF_SIZE ? roundup(mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN, 8) : AT_RX_BUF_SIZE; } + +static u32 atl1c_fix_features(struct net_device *netdev, u32 features) +{ + if (netdev->mtu > MAX_TSO_FRAME_SIZE) + features &= ~(NETIF_F_TSO | NETIF_F_TSO6); + + return features; +} + /* * atl1c_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure @@ -510,14 +519,8 @@ static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) netdev->mtu = new_mtu; adapter->hw.max_frame_size = new_mtu; atl1c_set_rxbufsize(adapter, netdev); - if (new_mtu > MAX_TSO_FRAME_SIZE) { - adapter->netdev->features &= ~NETIF_F_TSO; - adapter->netdev->features &= ~NETIF_F_TSO6; - } else { - adapter->netdev->features |= NETIF_F_TSO; - adapter->netdev->features |= NETIF_F_TSO6; - } atl1c_down(adapter); + netdev_update_features(netdev); atl1c_up(adapter); clear_bit(__AT_RESETTING, &adapter->flags); if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) { @@ -2585,6 +2588,7 @@ static const struct net_device_ops atl1c_netdev_ops = { .ndo_set_mac_address = atl1c_set_mac_addr, .ndo_set_multicast_list = atl1c_set_multi, .ndo_change_mtu = atl1c_change_mtu, + .ndo_fix_features = atl1c_fix_features, .ndo_do_ioctl = atl1c_ioctl, .ndo_tx_timeout = atl1c_tx_timeout, .ndo_get_stats = atl1c_get_stats, @@ -2605,12 +2609,13 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev) atl1c_set_ethtool_ops(netdev); /* TODO: add when ready */ - netdev->features = NETIF_F_SG | + netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX | - NETIF_F_HW_VLAN_RX | NETIF_F_TSO | NETIF_F_TSO6; + netdev->features = netdev->hw_features | + NETIF_F_HW_VLAN_RX; return 0; } diff --git a/drivers/net/atl1e/atl1e_ethtool.c b/drivers/net/atl1e/atl1e_ethtool.c index 1209297433b8..47783749d9fa 100644 --- a/drivers/net/atl1e/atl1e_ethtool.c +++ b/drivers/net/atl1e/atl1e_ethtool.c @@ -382,9 +382,6 @@ static const struct ethtool_ops atl1e_ethtool_ops = { .get_eeprom_len = atl1e_get_eeprom_len, .get_eeprom = atl1e_get_eeprom, .set_eeprom = atl1e_set_eeprom, - .set_tx_csum = ethtool_op_set_tx_hw_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, }; void atl1e_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 1ff001a8270c..c05b2e7c93d0 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -1927,11 +1927,7 @@ void atl1e_down(struct atl1e_adapter *adapter) * reschedule our watchdog timer */ set_bit(__AT_DOWN, &adapter->flags); -#ifdef NETIF_F_LLTX netif_stop_queue(netdev); -#else - netif_tx_disable(netdev); -#endif /* reset MAC to disable all RX/TX */ atl1e_reset_hw(&adapter->hw); @@ -2223,10 +2219,10 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev) netdev->watchdog_timeo = AT_TX_WATCHDOG; atl1e_set_ethtool_ops(netdev); - netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - netdev->features |= NETIF_F_LLTX; - netdev->features |= NETIF_F_TSO; + netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO | + NETIF_F_HW_VLAN_TX; + netdev->features = netdev->hw_features | + NETIF_F_HW_VLAN_RX | NETIF_F_LLTX; return 0; } diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index e973d056dc8f..98334a1f0c5c 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -2986,6 +2986,11 @@ static int __devinit atl1_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_SG; netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX); + netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_TSO; + + /* is this valid? see atl1_setup_mac_ctrl() */ + netdev->features |= NETIF_F_RXCSUM; + /* * patch for some L1 of old version, * the final version of L1 may not need these @@ -3595,12 +3600,6 @@ static int atl1_set_pauseparam(struct net_device *netdev, return 0; } -/* FIXME: is this right? -- CHS */ -static u32 atl1_get_rx_csum(struct net_device *netdev) -{ - return 1; -} - static void atl1_get_strings(struct net_device *netdev, u32 stringset, u8 *data) { @@ -3668,13 +3667,9 @@ static const struct ethtool_ops atl1_ethtool_ops = { .set_ringparam = atl1_set_ringparam, .get_pauseparam = atl1_get_pauseparam, .set_pauseparam = atl1_set_pauseparam, - .get_rx_csum = atl1_get_rx_csum, - .set_tx_csum = ethtool_op_set_tx_hw_csum, .get_link = ethtool_op_get_link, - .set_sg = ethtool_op_set_sg, .get_strings = atl1_get_strings, .nway_reset = atl1_nway_reset, .get_ethtool_stats = atl1_get_ethtool_stats, .get_sset_count = atl1_get_sset_count, - .set_tso = ethtool_op_set_tso, }; diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index 937ef1afa5db..02761dd23fb8 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c @@ -1411,9 +1411,8 @@ static int __devinit atl2_probe(struct pci_dev *pdev, err = -EIO; -#ifdef NETIF_F_HW_VLAN_TX + netdev->hw_features = NETIF_F_SG; netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX); -#endif /* Init PHY as early as possible due to power saving issue */ atl2_phy_init(&adapter->hw); @@ -1840,11 +1839,6 @@ static int atl2_set_settings(struct net_device *netdev, return 0; } -static u32 atl2_get_tx_csum(struct net_device *netdev) -{ - return (netdev->features & NETIF_F_HW_CSUM) != 0; -} - static u32 atl2_get_msglevel(struct net_device *netdev) { return 0; @@ -2112,12 +2106,6 @@ static const struct ethtool_ops atl2_ethtool_ops = { .get_eeprom_len = atl2_get_eeprom_len, .get_eeprom = atl2_get_eeprom, .set_eeprom = atl2_set_eeprom, - .get_tx_csum = atl2_get_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, -#ifdef NETIF_F_TSO - .get_tso = ethtool_op_get_tso, -#endif }; static void atl2_set_ethtool_ops(struct net_device *netdev) -- cgit v1.2.3-58-ga151 From 1d5cc5559aaf5273cc1f9aac9b428e3a99d41de6 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 28 Mar 2011 16:12:43 -0700 Subject: iwlwifi: remove extranious macro from firmware define define of firmware filenames use extra macro to build the files name. Signed-off-by: Jay Sternberg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 6 ++---- drivers/net/wireless/iwlwifi/iwl-2000.c | 9 +++------ drivers/net/wireless/iwlwifi/iwl-5000.c | 6 ++---- drivers/net/wireless/iwlwifi/iwl-6000.c | 12 ++++-------- 4 files changed, 11 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 1b2799291834..4323d27cc9f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -57,12 +57,10 @@ #define IWL100_UCODE_API_MIN 5 #define IWL1000_FW_PRE "iwlwifi-1000-" -#define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode" -#define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api) +#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode" #define IWL100_FW_PRE "iwlwifi-100-" -#define _IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode" -#define IWL100_MODULE_FIRMWARE(api) _IWL100_MODULE_FIRMWARE(api) +#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode" /* diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index f602af4b9408..564477d09153 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -60,16 +60,13 @@ #define IWL200_UCODE_API_MIN 5 #define IWL2030_FW_PRE "iwlwifi-2030-" -#define _IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode" -#define IWL2030_MODULE_FIRMWARE(api) _IWL2030_MODULE_FIRMWARE(api) +#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode" #define IWL2000_FW_PRE "iwlwifi-2000-" -#define _IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode" -#define IWL2000_MODULE_FIRMWARE(api) _IWL2000_MODULE_FIRMWARE(api) +#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode" #define IWL200_FW_PRE "iwlwifi-200-" -#define _IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE #api ".ucode" -#define IWL200_MODULE_FIRMWARE(api) _IWL200_MODULE_FIRMWARE(api) +#define IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE #api ".ucode" static void iwl2000_set_ct_threshold(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 66f5fe8fe1ac..4dafc58800d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -59,12 +59,10 @@ #define IWL5150_UCODE_API_MIN 1 #define IWL5000_FW_PRE "iwlwifi-5000-" -#define _IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode" -#define IWL5000_MODULE_FIRMWARE(api) _IWL5000_MODULE_FIRMWARE(api) +#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode" #define IWL5150_FW_PRE "iwlwifi-5150-" -#define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" -#define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) +#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" /* NIC configuration for 5000 series */ static void iwl5000_nic_config(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 24d105b29aec..9fb2a42e5ea0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -60,20 +60,16 @@ #define IWL6000G2_UCODE_API_MIN 4 #define IWL6000_FW_PRE "iwlwifi-6000-" -#define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" -#define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api) +#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" #define IWL6050_FW_PRE "iwlwifi-6050-" -#define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" -#define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) +#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" #define IWL6005_FW_PRE "iwlwifi-6000g2a-" -#define _IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode" -#define IWL6005_MODULE_FIRMWARE(api) _IWL6005_MODULE_FIRMWARE(api) +#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode" #define IWL6030_FW_PRE "iwlwifi-6000g2b-" -#define _IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode" -#define IWL6030_MODULE_FIRMWARE(api) _IWL6030_MODULE_FIRMWARE(api) +#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode" static void iwl6000_set_ct_threshold(struct iwl_priv *priv) { -- cgit v1.2.3-58-ga151 From 3ecccbcd3c67374aeee447c08fcb9e39a99f7ee5 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 29 Mar 2011 17:53:15 -0700 Subject: iwlagn: remove un-necessary function pointer After driver split, no need to use function pointer for those event and register dump function. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-2000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-5000.c | 7 ------- drivers/net/wireless/iwlwifi/iwl-6000.c | 8 -------- drivers/net/wireless/iwlwifi/iwl-agn.h | 2 -- drivers/net/wireless/iwlwifi/iwl-core.c | 10 ++++------ drivers/net/wireless/iwlwifi/iwl-core.h | 8 ++------ drivers/net/wireless/iwlwifi/iwl-debugfs.c | 21 ++++++++------------- 8 files changed, 14 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 4323d27cc9f6..cb2f87101f9d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -182,10 +182,6 @@ static struct iwl_lib_ops iwl1000_lib = { .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, - .dump_nic_event_log = iwl_dump_nic_event_log, - .dump_nic_error_log = iwl_dump_nic_error_log, - .dump_csr = iwl_dump_csr, - .dump_fh = iwl_dump_fh, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .apm_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 564477d09153..e73ac80a721e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -262,10 +262,6 @@ static struct iwl_lib_ops iwl2000_lib = { .setup_deferred_work = iwlagn_bt_setup_deferred_work, .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, - .dump_nic_event_log = iwl_dump_nic_event_log, - .dump_nic_error_log = iwl_dump_nic_error_log, - .dump_csr = iwl_dump_csr, - .dump_fh = iwl_dump_fh, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl2030_hw_channel_switch, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 4dafc58800d9..4c8f72a77a72 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -350,10 +350,6 @@ static struct iwl_lib_ops iwl5000_lib = { .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, - .dump_nic_event_log = iwl_dump_nic_event_log, - .dump_nic_error_log = iwl_dump_nic_error_log, - .dump_csr = iwl_dump_csr, - .dump_fh = iwl_dump_fh, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl5000_hw_channel_switch, @@ -406,9 +402,6 @@ static struct iwl_lib_ops iwl5150_lib = { .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, - .dump_nic_event_log = iwl_dump_nic_event_log, - .dump_nic_error_log = iwl_dump_nic_error_log, - .dump_csr = iwl_dump_csr, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl5000_hw_channel_switch, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 9fb2a42e5ea0..80a335fc78cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -289,10 +289,6 @@ static struct iwl_lib_ops iwl6000_lib = { .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, - .dump_nic_event_log = iwl_dump_nic_event_log, - .dump_nic_error_log = iwl_dump_nic_error_log, - .dump_csr = iwl_dump_csr, - .dump_fh = iwl_dump_fh, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl6000_hw_channel_switch, @@ -347,10 +343,6 @@ static struct iwl_lib_ops iwl6030_lib = { .setup_deferred_work = iwlagn_bt_setup_deferred_work, .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, - .dump_nic_event_log = iwl_dump_nic_event_log, - .dump_nic_error_log = iwl_dump_nic_error_log, - .dump_csr = iwl_dump_csr, - .dump_fh = iwl_dump_fh, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl6000_hw_channel_switch, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 016b79e4421e..290a20814692 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -173,8 +173,6 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv); int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); -void iwl_dump_csr(struct iwl_priv *priv); -int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); /* rx */ void iwlagn_rx_queue_restock(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c46be36b9e2e..5e7281c22c0b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -965,12 +965,10 @@ void iwl_irq_handle_error(struct iwl_priv *priv) IWL_ERR(priv, "Loaded firmware version: %s\n", priv->hw->wiphy->fw_version); - priv->cfg->ops->lib->dump_nic_error_log(priv); - if (priv->cfg->ops->lib->dump_csr) - priv->cfg->ops->lib->dump_csr(priv); - if (priv->cfg->ops->lib->dump_fh) - priv->cfg->ops->lib->dump_fh(priv, NULL, false); - priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); + iwl_dump_nic_error_log(priv); + iwl_dump_csr(priv); + iwl_dump_fh(priv, NULL, false); + iwl_dump_nic_event_log(priv, false, NULL, false); #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) iwl_print_rx_config_cmd(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 82939f851eb9..43d4c92268e7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -171,12 +171,6 @@ struct iwl_lib_ops { void (*cancel_deferred_work)(struct iwl_priv *priv); /* check validity of rtc data address */ int (*is_valid_rtc_data_addr)(u32 addr); - - int (*dump_nic_event_log)(struct iwl_priv *priv, - bool full_log, char **buf, bool display); - void (*dump_nic_error_log)(struct iwl_priv *priv); - void (*dump_csr)(struct iwl_priv *priv); - int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display); int (*set_channel_switch)(struct iwl_priv *priv, struct ieee80211_channel_switch *ch_switch); /* power management */ @@ -598,6 +592,8 @@ extern const struct dev_pm_ops iwl_pm_ops; void iwl_dump_nic_error_log(struct iwl_priv *priv); int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, char **buf, bool display); +void iwl_dump_csr(struct iwl_priv *priv); +int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); #ifdef CONFIG_IWLWIFI_DEBUG void iwl_print_rx_config_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 92f6efd2c73f..93a86998a3b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -437,8 +437,7 @@ static ssize_t iwl_dbgfs_log_event_read(struct file *file, int pos = 0; ssize_t ret = -ENOMEM; - ret = pos = priv->cfg->ops->lib->dump_nic_event_log( - priv, true, &buf, true); + ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true); if (buf) { ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); @@ -462,8 +461,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, if (sscanf(buf, "%d", &event_log_flag) != 1) return -EFAULT; if (event_log_flag == 1) - priv->cfg->ops->lib->dump_nic_event_log(priv, true, - NULL, false); + iwl_dump_nic_event_log(priv, true, NULL, false); return count; } @@ -1268,8 +1266,7 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file, if (sscanf(buf, "%d", &csr) != 1) return -EFAULT; - if (priv->cfg->ops->lib->dump_csr) - priv->cfg->ops->lib->dump_csr(priv); + iwl_dump_csr(priv); return count; } @@ -1359,13 +1356,11 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, int pos = 0; ssize_t ret = -EFAULT; - if (priv->cfg->ops->lib->dump_fh) { - ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true); - if (buf) { - ret = simple_read_from_buffer(user_buf, - count, ppos, buf, pos); - kfree(buf); - } + ret = pos = iwl_dump_fh(priv, &buf, true); + if (buf) { + ret = simple_read_from_buffer(user_buf, + count, ppos, buf, pos); + kfree(buf); } return ret; -- cgit v1.2.3-58-ga151 From 68b993118f715cc631b62b6a50574e4701fe9ace Mon Sep 17 00:00:00 2001 From: Garen Tamrazian Date: Wed, 30 Mar 2011 02:29:32 -0700 Subject: iwlagn: fix radar frame rejection The microcode may sometimes reject TX frames when on a radar channel even after we associated as it clears information during association and needs to receive a new beacon before allowing that channel again. This manifests itself as a TX status value of TX_STATUS_FAIL_PASSIVE_NO_RX. So in this case, stop the corresponding queue and give the frame back to mac80211 for retransmission. We start the queue again when a beacon from the AP is received which will make the regulatory enforcement in the device allow transmitting again. Signed-off-by: Garen Tamrazian Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 29 ++++++++++++++++++++-------- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 13 +++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 3 +++ drivers/net/wireless/iwlwifi/iwl-agn.h | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-helpers.h | 13 +++++++++++++ drivers/net/wireless/iwlwifi/iwl-rx.c | 21 ++++++++++++++++++++ 7 files changed, 74 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 9e47be6a7393..cccf7471c003 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -172,6 +172,7 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) static void iwlagn_set_tx_status(struct iwl_priv *priv, struct ieee80211_tx_info *info, + struct iwl_rxon_context *ctx, struct iwlagn_tx_resp *tx_resp, int txq_id, bool is_agg) { @@ -186,6 +187,13 @@ static void iwlagn_set_tx_status(struct iwl_priv *priv, if (!iwl_is_tx_success(status)) iwlagn_count_tx_err_status(priv, status); + if (status == TX_STATUS_FAIL_PASSIVE_NO_RX && + iwl_is_associated_ctx(ctx) && ctx->vif && + ctx->vif->type == NL80211_IFTYPE_STATION) { + ctx->last_tx_rejected = true; + iwl_stop_queue(priv, &priv->txq[txq_id]); + } + IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " "0x%x retries %d\n", txq_id, @@ -242,15 +250,16 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, /* # frames attempted by Tx command */ if (agg->frame_count == 1) { + struct iwl_tx_info *txb; + /* Only one frame was attempted; no block-ack will arrive */ idx = start_idx; IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", agg->frame_count, agg->start_idx, idx); - iwlagn_set_tx_status(priv, - IEEE80211_SKB_CB( - priv->txq[txq_id].txb[idx].skb), - tx_resp, txq_id, true); + txb = &priv->txq[txq_id].txb[idx]; + iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(txb->skb), + txb->ctx, tx_resp, txq_id, true); agg->wait_for_ba = 0; } else { /* Two or more frames were attempted; expect block-ack */ @@ -391,7 +400,8 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct ieee80211_tx_info *info; struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - u32 status = le16_to_cpu(tx_resp->status.status); + struct iwl_tx_info *txb; + u32 status = le16_to_cpu(tx_resp->status.status); int tid; int sta_id; int freed; @@ -406,7 +416,8 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, } txq->time_stamp = jiffies; - info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); + txb = &txq->txb[txq->q.read_ptr]; + info = IEEE80211_SKB_CB(txb->skb); memset(&info->status, 0, sizeof(info->status)); tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> @@ -450,12 +461,14 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, iwl_wake_queue(priv, txq); } } else { - iwlagn_set_tx_status(priv, info, tx_resp, txq_id, false); + iwlagn_set_tx_status(priv, info, txb->ctx, tx_resp, + txq_id, false); freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); iwl_free_tfds_in_queue(priv, sta_id, tid, freed); if (priv->mac80211_registered && - (iwl_queue_space(&txq->q) > txq->q.low_mark)) + iwl_queue_space(&txq->q) > txq->q.low_mark && + status != TX_STATUS_FAIL_PASSIVE_NO_RX) iwl_wake_queue(priv, txq); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index c335ee6883ee..56f46ee3bacd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -29,6 +29,7 @@ #include "iwl-sta.h" #include "iwl-core.h" #include "iwl-agn-calib.h" +#include "iwl-helpers.h" static int iwlagn_disable_bss(struct iwl_priv *priv, struct iwl_rxon_context *ctx, @@ -600,6 +601,18 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, priv->timestamp = bss_conf->timestamp; ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; } else { + /* + * If we disassociate while there are pending + * frames, just wake up the queues and let the + * frames "escape" ... This shouldn't really + * be happening to start with, but we should + * not get stuck in this case either since it + * can happen if userspace gets confused. + */ + if (ctx->last_tx_rejected) { + ctx->last_tx_rejected = false; + iwl_wake_any_queue(priv, ctx); + } ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; } } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 01a6d2fc795c..5c30f6b19a7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -428,6 +428,7 @@ void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) int iwlagn_alive_notify(struct iwl_priv *priv) { const struct queue_to_fifo_ac *queue_to_fifo; + struct iwl_rxon_context *ctx; u32 a; unsigned long flags; int i, chan; @@ -501,6 +502,8 @@ int iwlagn_alive_notify(struct iwl_priv *priv) memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); for (i = 0; i < 4; i++) atomic_set(&priv->queue_stop_count[i], 0); + for_each_context(priv, ctx) + ctx->last_tx_rejected = false; /* reset to 0 to enable all the queue first */ priv->txq_ctx_active_msk = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 290a20814692..078a23e5d99d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -220,6 +220,7 @@ static inline u32 iwl_tx_status_to_mac80211(u32 status) case TX_STATUS_DIRECT_DONE: return IEEE80211_TX_STAT_ACK; case TX_STATUS_FAIL_DEST_PS: + case TX_STATUS_FAIL_PASSIVE_NO_RX: return IEEE80211_TX_STAT_TX_FILTERED; default: return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 72133368c1f5..14f7d8fb6886 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1170,6 +1170,8 @@ struct iwl_rxon_context { bool enabled, is_40mhz; u8 extension_chan_offset; } ht; + + bool last_tx_rejected; }; enum iwl_scan_type { diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 5da5761c74b1..9309ff2df4c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -131,6 +131,19 @@ static inline void iwl_stop_queue(struct iwl_priv *priv, ieee80211_stop_queue(priv->hw, ac); } +static inline void iwl_wake_any_queue(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) +{ + u8 ac; + + for (ac = 0; ac < AC_NUM; ac++) { + IWL_DEBUG_INFO(priv, "Queue Status: Q[%d] %s\n", + ac, (atomic_read(&priv->queue_stop_count[ac]) > 0) + ? "stopped" : "awake"); + iwl_wake_queue(priv, &priv->txq[ctx->ac_to_queue[ac]]); + } +} + #define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index c421f566982f..4472761fc591 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -873,6 +873,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, { struct sk_buff *skb; __le16 fc = hdr->frame_control; + struct iwl_rxon_context *ctx; /* We only process data packets if the interface is open */ if (unlikely(!priv->is_open)) { @@ -895,6 +896,26 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); iwl_update_stats(priv, false, fc, len); + + /* + * Wake any queues that were stopped due to a passive channel tx + * failure. This can happen because the regulatory enforcement in + * the device waits for a beacon before allowing transmission, + * sometimes even after already having transmitted frames for the + * association because the new RXON may reset the information. + */ + if (unlikely(ieee80211_is_beacon(fc))) { + for_each_context(priv, ctx) { + if (!ctx->last_tx_rejected) + continue; + if (compare_ether_addr(hdr->addr3, + ctx->active.bssid_addr)) + continue; + ctx->last_tx_rejected = false; + iwl_wake_any_queue(priv, ctx); + } + } + memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); ieee80211_rx(priv->hw, skb); -- cgit v1.2.3-58-ga151 From a2b76b3b31568da9d281a393845f17689594ccdf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 29 Mar 2011 06:29:37 -0700 Subject: iwlwifi: fix bugs in change_interface If change_interface gets invoked during a firmware restart, it may crash; prevent that from happening by checking if ctx->vif is assigned. Additionally, in my initial commit I forgot to set the vif->p2p variable correctly, so fix that too. Cc: stable@kernel.org [2.6.38+] Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5e7281c22c0b..b5a06549b2a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1775,6 +1775,15 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mutex_lock(&priv->mutex); + if (!ctx->vif || !iwl_is_ready_rf(priv)) { + /* + * Huh? But wait ... this can maybe happen when + * we're in the middle of a firmware restart! + */ + err = -EBUSY; + goto out; + } + interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes; if (!(interface_modes & BIT(newtype))) { @@ -1802,6 +1811,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /* success */ iwl_teardown_interface(priv, vif, true); vif->type = newtype; + vif->p2p = newp2p; err = iwl_setup_interface(priv, ctx); WARN_ON(err); /* -- cgit v1.2.3-58-ga151 From dcf6640f0f58affa93f158d8573b6868136e3d62 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 1 Apr 2011 13:20:44 -0700 Subject: iwlagn: PAPD read for 2000 series devices For 2000 series NICs, disable OTP refresh in order to read correct PAPD table from high OTP block Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-2000.c | 5 ++++- drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index e73ac80a721e..86d7ffd6e38b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -98,6 +98,8 @@ static void iwl2000_nic_config(struct iwl_priv *priv) iwl_set_bit(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); + if (priv->cfg->disable_otp_refresh) + iwl_write_prph(priv, APMG_ANALOG_SVR_REG, 0x80000010); } static struct iwl_sensitivity_ranges iwl2000_sensitivity = { @@ -409,7 +411,8 @@ static struct iwl_bt_params iwl2030_bt_params = { .need_dc_calib = true, \ .need_temp_offset_calib = true, \ .led_mode = IWL_LED_RF_STATE, \ - .iq_invert = true \ + .iq_invert = true, \ + .disable_otp_refresh = true \ struct iwl_cfg iwl2000_2bgn_cfg = { .name = "2000 Series 2x2 BGN", diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 43d4c92268e7..10a6f856356a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -331,6 +331,7 @@ struct iwl_ht_params { * @rx_with_siso_diversity: 1x1 device with rx antenna diversity * @internal_wimax_coex: internal wifi/wimax combo device * @iq_invert: I/Q inversion + * @disable_otp_refresh: disable OTP refresh current limit * * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the @@ -381,6 +382,7 @@ struct iwl_cfg { const bool rx_with_siso_diversity; const bool internal_wimax_coex; const bool iq_invert; + const bool disable_otp_refresh; }; /*************************** -- cgit v1.2.3-58-ga151 From ece3cd2e8fb119a4394dcdc6ef921e85cdd4cc69 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 1 Apr 2011 16:29:47 -0700 Subject: iwlagn: no 3945 define needed Remove 3945 define Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 69a29932babc..bdae82e7fa90 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -83,7 +83,6 @@ enum { enum { IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX, - IWL39_LAST_OFDM_RATE = IWL_RATE_54M_INDEX, IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX, IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX, IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX, -- cgit v1.2.3-58-ga151 From ab4bf5ef5afce9d31cf5cf05ac80b3b01cbb24a3 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 1 Apr 2011 16:35:09 -0700 Subject: iwlagn: remove unused 3945 define 3945 no longer apply Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-fh.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index da06d136a357..0f1052f80a53 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -424,7 +424,6 @@ #define RX_LOW_WATERMARK 8 /* Size of one Rx buffer in host DRAM */ -#define IWL_RX_BUF_SIZE_3K (3 * 1000) /* 3945 only */ #define IWL_RX_BUF_SIZE_4K (4 * 1024) #define IWL_RX_BUF_SIZE_8K (8 * 1024) @@ -443,7 +442,7 @@ struct iwl_rb_status { __le16 closed_fr_num; __le16 finished_rb_num; __le16 finished_fr_nam; - __le32 __unused; /* 3945 only */ + __le32 __unused; } __packed; -- cgit v1.2.3-58-ga151 From ee3cd7e04ca08ff0ec1ebb96be7e64aef928f511 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 1 Apr 2011 16:35:10 -0700 Subject: iwlagn: cleanup to remove the reference for 3945 More clean up after driver split Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b5a06549b2a5..4c7649960983 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1049,7 +1049,6 @@ int iwl_apm_init(struct iwl_priv *priv) /* * Enable HAP INTA (interrupt from management bus) to * wake device's PCI Express link L1a -> L0s - * NOTE: This is no-op for 3945 (non-existant bit) */ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); -- cgit v1.2.3-58-ga151 From 6bb64697ed58909985487e885c269dafd09583f1 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 1 Apr 2011 16:29:50 -0700 Subject: iwlagn: remove more reference to legacy devices Remove the reference to both 3945 and 4965 in LED code Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-led.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index c2862d4e00e3..0d90004e8b1b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -63,8 +63,8 @@ static const struct ieee80211_tpt_blink iwl_blink[] = { /* * Adjust led blink rate to compensate on a MAC Clock difference on every HW - * Led blink rate analysis showed an average deviation of 0% on 3945, - * 5% on 4965 HW and 20% on 5000 series and up. + * Led blink rate analysis showed an average deviation of 20% on 5000 series + * and up. * Need to compensate on the led on/off time per HW according to the deviation * to achieve the desired led frequency * The calculation is: (100-averageDeviation)/100 * blinkTime -- cgit v1.2.3-58-ga151 From 15ade3ca647d95611814333cfe0885fd0184481e Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 1 Apr 2011 16:29:51 -0700 Subject: iwlagn: remove un-needed configuration After driver split, set_l0s config is no longer needed, remove it Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 - drivers/net/wireless/iwlwifi/iwl-2000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-5000.c | 1 - drivers/net/wireless/iwlwifi/iwl-6000.c | 3 --- drivers/net/wireless/iwlwifi/iwl-core.c | 26 ++++++++++++-------------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - 6 files changed, 12 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index cb2f87101f9d..5a7281047a13 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -235,7 +235,6 @@ static struct iwl_base_params iwl1000_base_params = { .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .eeprom_size = OTP_LOW_IMAGE_SIZE, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, - .set_l0s = true, .max_ll_items = OTP_MAX_LL_ITEMS_1000, .shadow_ram_support = false, .led_compensation = 51, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 86d7ffd6e38b..9daf888b733c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -343,7 +343,6 @@ static struct iwl_base_params iwl2000_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, - .set_l0s = true, .max_ll_items = OTP_MAX_LL_ITEMS_2x00, .shadow_ram_support = true, .led_compensation = 51, @@ -366,7 +365,6 @@ static struct iwl_base_params iwl2030_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, - .set_l0s = true, .max_ll_items = OTP_MAX_LL_ITEMS_2x00, .shadow_ram_support = true, .led_compensation = 57, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 4c8f72a77a72..8106423a2c84 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -464,7 +464,6 @@ static struct iwl_base_params iwl5000_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, - .set_l0s = true, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 80a335fc78cb..7f0715eb0593 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -432,7 +432,6 @@ static struct iwl_base_params iwl6000_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, - .set_l0s = true, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, .led_compensation = 51, @@ -454,7 +453,6 @@ static struct iwl_base_params iwl6050_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, - .set_l0s = true, .max_ll_items = OTP_MAX_LL_ITEMS_6x50, .shadow_ram_support = true, .led_compensation = 51, @@ -475,7 +473,6 @@ static struct iwl_base_params iwl6000_g2_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, - .set_l0s = true, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, .led_compensation = 57, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4c7649960983..0e98a8703e55 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1061,20 +1061,18 @@ int iwl_apm_init(struct iwl_priv *priv) * If not (unlikely), enable L0S, so there is at least some * power savings, even without L1. */ - if (priv->cfg->base_params->set_l0s) { - lctl = iwl_pcie_link_ctl(priv); - if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == - PCI_CFG_LINK_CTRL_VAL_L1_EN) { - /* L1-ASPM enabled; disable(!) L0S */ - iwl_set_bit(priv, CSR_GIO_REG, - CSR_GIO_REG_VAL_L0S_ENABLED); - IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n"); - } else { - /* L1-ASPM disabled; enable(!) L0S */ - iwl_clear_bit(priv, CSR_GIO_REG, - CSR_GIO_REG_VAL_L0S_ENABLED); - IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n"); - } + lctl = iwl_pcie_link_ctl(priv); + if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == + PCI_CFG_LINK_CTRL_VAL_L1_EN) { + /* L1-ASPM enabled; disable(!) L0S */ + iwl_set_bit(priv, CSR_GIO_REG, + CSR_GIO_REG_VAL_L0S_ENABLED); + IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n"); + } else { + /* L1-ASPM disabled; enable(!) L0S */ + iwl_clear_bit(priv, CSR_GIO_REG, + CSR_GIO_REG_VAL_L0S_ENABLED); + IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n"); } /* Configure analog phase-lock-loop before activating to D0A */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 10a6f856356a..7d303acc837c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -265,7 +265,6 @@ struct iwl_base_params { int num_of_ampdu_queues;/* def: HW dependent */ /* for iwl_apm_init() */ u32 pll_cfg_val; - bool set_l0s; const u16 max_ll_items; const bool shadow_ram_support; -- cgit v1.2.3-58-ga151 From 8ff84a2c99bc7f5f22d9d2b5365d821ce4f7a8f9 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 1 Apr 2011 16:29:52 -0700 Subject: iwlagn: more cleanup to remove unused reference More cleanup code, no functional changes Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-fh.h | 35 ++++++++++++++++----------------- drivers/net/wireless/iwlwifi/iwl-prph.h | 16 +++------------ drivers/net/wireless/iwlwifi/iwl-tx.c | 1 - 3 files changed, 20 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 0f1052f80a53..b90924e890a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -77,14 +77,14 @@ /** * Keep-Warm (KW) buffer base address. * - * Driver must allocate a 4KByte buffer that is used by 4965 for keeping the + * Driver must allocate a 4KByte buffer that is for keeping the * host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency - * DRAM access when 4965 is Txing or Rxing. The dummy accesses prevent host + * DRAM access when doing Txing or Rxing. The dummy accesses prevent host * from going into a power-savings mode that would cause higher DRAM latency, * and possible data over/under-runs, before all Tx/Rx is complete. * * Driver loads FH_KW_MEM_ADDR_REG with the physical address (bits 35:4) - * of the buffer, which must be 4K aligned. Once this is set up, the 4965 + * of the buffer, which must be 4K aligned. Once this is set up, the device * automatically invokes keep-warm accesses when normal accesses might not * be sufficient to maintain fast DRAM response. * @@ -97,7 +97,7 @@ /** * TFD Circular Buffers Base (CBBC) addresses * - * 4965 has 16 base pointer registers, one for each of 16 host-DRAM-resident + * Device has 16 base pointer registers, one for each of 16 host-DRAM-resident * circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs) * (see struct iwl_tfd_frame). These 16 pointer registers are offset by 0x04 * bytes from one another. Each TFD circular buffer in DRAM must be 256-byte @@ -116,16 +116,16 @@ /** * Rx SRAM Control and Status Registers (RSCSR) * - * These registers provide handshake between driver and 4965 for the Rx queue + * These registers provide handshake between driver and device for the Rx queue * (this queue handles *all* command responses, notifications, Rx data, etc. - * sent from 4965 uCode to host driver). Unlike Tx, there is only one Rx + * sent from uCode to host driver). Unlike Tx, there is only one Rx * queue, and only one Rx DMA/FIFO channel. Also unlike Tx, which can * concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer * Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1 * mapping between RBDs and RBs. * * Driver must allocate host DRAM memory for the following, and set the - * physical address of each into 4965 registers: + * physical address of each into device registers: * * 1) Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256 * entries (although any power of 2, up to 4096, is selectable by driver). @@ -140,20 +140,20 @@ * Driver sets physical address [35:8] of base of RBD circular buffer * into FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0]. * - * 2) Rx status buffer, 8 bytes, in which 4965 indicates which Rx Buffers + * 2) Rx status buffer, 8 bytes, in which uCode indicates which Rx Buffers * (RBs) have been filled, via a "write pointer", actually the index of * the RB's corresponding RBD within the circular buffer. Driver sets * physical address [35:4] into FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0]. * * Bit fields in lower dword of Rx status buffer (upper dword not used - * by driver; see struct iwl4965_shared, val0): + * by driver: * 31-12: Not used by driver * 11- 0: Index of last filled Rx buffer descriptor - * (4965 writes, driver reads this value) + * (device writes, driver reads this value) * - * As the driver prepares Receive Buffers (RBs) for 4965 to fill, driver must + * As the driver prepares Receive Buffers (RBs) for device to fill, driver must * enter pointers to these RBs into contiguous RBD circular buffer entries, - * and update the 4965's "write" index register, + * and update the device's "write" index register, * FH_RSCSR_CHNL0_RBDCB_WPTR_REG. * * This "write" index corresponds to the *next* RBD that the driver will make @@ -162,12 +162,12 @@ * RBs), should be 8 after preparing the first 8 RBs (for example), and must * wrap back to 0 at the end of the circular buffer (but don't wrap before * "read" index has advanced past 1! See below). - * NOTE: 4965 EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8. + * NOTE: DEVICE EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8. * - * As the 4965 fills RBs (referenced from contiguous RBDs within the circular + * As the device fills RBs (referenced from contiguous RBDs within the circular * buffer), it updates the Rx status buffer in host DRAM, 2) described above, * to tell the driver the index of the latest filled RBD. The driver must - * read this "read" index from DRAM after receiving an Rx interrupt from 4965. + * read this "read" index from DRAM after receiving an Rx interrupt from device * * The driver must also internally keep track of a third index, which is the * next RBD to process. When receiving an Rx interrupt, driver should process @@ -176,7 +176,7 @@ * driver may process the RB pointed to by RBD 0. Depending on volume of * traffic, there may be many RBs to process. * - * If read index == write index, 4965 thinks there is no room to put new data. + * If read index == write index, device thinks there is no room to put new data. * Due to this, the maximum number of filled RBs is 255, instead of 256. To * be safe, make sure that there is a gap of at least 2 RBDs between "write" * and "read" indexes; that is, make sure that there are no more than 254 @@ -303,7 +303,7 @@ /** * Transmit DMA Channel Control/Status Registers (TCSR) * - * 4965 has one configuration register for each of 8 Tx DMA/FIFO channels + * Device has one configuration register for each of 8 Tx DMA/FIFO channels * supported in hardware (don't confuse these with the 16 Tx queues in DRAM, * which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes. * @@ -326,7 +326,6 @@ #define FH_TCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xE60) /* Find Control/Status reg for given Tx DMA/FIFO channel */ -#define FH49_TCSR_CHNL_NUM (7) #define FH50_TCSR_CHNL_NUM (8) /* TCSR: tx_config register values */ diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index c960195df989..f00d188b2cfc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -107,17 +107,7 @@ * device. A queue maps to only one (selectable by driver) Tx DMA channel, * but one DMA channel may take input from several queues. * - * Tx DMA FIFOs have dedicated purposes. For 4965, they are used as follows - * (cf. default_queue_to_tx_fifo in iwl-4965.c): - * - * 0 -- EDCA BK (background) frames, lowest priority - * 1 -- EDCA BE (best effort) frames, normal priority - * 2 -- EDCA VI (video) frames, higher priority - * 3 -- EDCA VO (voice) and management frames, highest priority - * 4 -- Commands (e.g. RXON, etc.) - * 5 -- unused (HCCA) - * 6 -- unused (HCCA) - * 7 -- not used by driver (device-internal only) + * Tx DMA FIFOs have dedicated purposes. * * For 5000 series and up, they are used differently * (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c): @@ -151,7 +141,7 @@ * Tx completion may end up being out-of-order). * * The driver must maintain the queue's Byte Count table in host DRAM - * (struct iwl4965_sched_queue_byte_cnt_tbl) for this mode. + * for this mode. * This mode does not support fragmentation. * * 2) FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order. @@ -164,7 +154,7 @@ * * Driver controls scheduler operation via 3 means: * 1) Scheduler registers - * 2) Shared scheduler data base in internal 4956 SRAM + * 2) Shared scheduler data base in internal SRAM * 3) Shared data in host DRAM * * Initialization: diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 565980fbb591..3732380c4ffe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -232,7 +232,6 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) * reclaiming packets (on 'tx done IRQ), if free space become > high mark, * Tx queue resumed. * - * See more detailed info in iwl-4965-hw.h. ***************************************************/ int iwl_queue_space(const struct iwl_queue *q) -- cgit v1.2.3-58-ga151 From 23c0fcc66b4345ea97ae588c2e01f10c994652ba Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 1 Apr 2011 16:29:53 -0700 Subject: iwlagn: all _agn devices support power save mode Remove broken_power_save checking Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 5 ++--- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - drivers/net/wireless/iwlwifi/iwl-debugfs.c | 7 ++----- drivers/net/wireless/iwlwifi/iwl-power.c | 4 +--- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 60bfde75ce87..23b89c2e71da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2828,9 +2828,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; - if (!priv->cfg->base_params->broken_powersave) - hw->flags |= IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_SUPPORTS_DYNAMIC_PS; + hw->flags |= IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_SUPPORTS_DYNAMIC_PS; if (priv->cfg->sku & IWL_SKU_N) hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7d303acc837c..a0530d03b301 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -269,7 +269,6 @@ struct iwl_base_params { const u16 max_ll_items; const bool shadow_ram_support; u16 led_compensation; - const bool broken_powersave; int chain_noise_num_beacons; bool adv_thermal_throttle; bool support_ct_kill_exit; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 93a86998a3b1..2c58980f2d06 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1723,11 +1723,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); - if (!priv->cfg->base_params->broken_powersave) { - DEBUGFS_ADD_FILE(sleep_level_override, dir_data, - S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); - } + DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index c43c8e66de73..ae176d8da9e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -354,9 +354,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, dtimper = priv->hw->conf.ps_dtim_period ?: 1; - if (priv->cfg->base_params->broken_powersave) - iwl_power_sleep_cam_cmd(priv, cmd); - else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) + if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && priv->cfg->ops->lib->tt_ops.tt_power_mode && -- cgit v1.2.3-58-ga151 From ae89726a02049e8f61bb3c8bf5dbf1fc06527a07 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 1 Apr 2011 16:29:54 -0700 Subject: iwlagn: tx power calib always done in firmware Remove the config flag for tx power calib Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 6 ++++-- drivers/net/wireless/iwlwifi/iwl-core.h | 3 --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 3 --- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index cccf7471c003..bc5dfe2978f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -495,8 +495,10 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv) void iwlagn_setup_deferred_work(struct iwl_priv *priv) { - /* in agn, the tx power calibration is done in uCode */ - priv->disable_tx_power_cal = 1; + /* + * nothing need to be done here anymore + * still keep for future use if needed + */ } int iwlagn_hw_valid_rtc_data_addr(u32 addr) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a0530d03b301..98dc544f112c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -250,8 +250,6 @@ struct iwl_mod_params { * @wd_timeout: TX queues watchdog timeout * @temperature_kelvin: temperature report by uCode in kelvin * @max_event_log_size: size of event log buffer size for ucode event logging - * @tx_power_by_driver: tx power calibration performed by driver - * instead of uCode * @ucode_tracing: support ucode continuous tracing * @sensitivity_calib_by_driver: driver has the capability to perform * sensitivity calibration operation @@ -278,7 +276,6 @@ struct iwl_base_params { unsigned int wd_timeout; bool temperature_kelvin; u32 max_event_log_size; - const bool tx_power_by_driver; const bool ucode_tracing; const bool sensitivity_calib_by_driver; const bool chain_noise_calib_by_driver; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 2c58980f2d06..9b1f9621b630 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1767,9 +1767,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) if (priv->cfg->base_params->chain_noise_calib_by_driver) DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, &priv->disable_chain_noise_cal); - if (priv->cfg->base_params->tx_power_by_driver) - DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, - &priv->disable_tx_power_cal); return 0; err: diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 14f7d8fb6886..7fe68f8dd210 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1489,7 +1489,6 @@ struct iwl_priv { struct work_struct txpower_work; u32 disable_sens_cal; u32 disable_chain_noise_cal; - u32 disable_tx_power_cal; struct work_struct run_time_calib_work; struct timer_list statistics_periodic; struct timer_list ucode_trace; -- cgit v1.2.3-58-ga151 From 703bc583cb98a24eeedd297ee59dfa12852897d1 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sun, 3 Apr 2011 08:14:41 -0700 Subject: iwlagn: sensitivity and chain noise done by driver _agn driver should perform both sensitivity and chain noise calib. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-2000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-6000.c | 6 ------ drivers/net/wireless/iwlwifi/iwl-core.h | 6 ------ drivers/net/wireless/iwlwifi/iwl-debugfs.c | 16 ++++++---------- 6 files changed, 6 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 5a7281047a13..d1d7852f0ee4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -245,8 +245,6 @@ static struct iwl_base_params iwl1000_base_params = { .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 128, .ucode_tracing = true, - .sensitivity_calib_by_driver = true, - .chain_noise_calib_by_driver = true, }; static struct iwl_ht_params iwl1000_ht_params = { .ht_greenfield_support = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 9daf888b733c..805b0394850e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -354,8 +354,6 @@ static struct iwl_base_params iwl2000_base_params = { .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 512, .ucode_tracing = true, - .sensitivity_calib_by_driver = true, - .chain_noise_calib_by_driver = true, .shadow_reg_enable = true, }; @@ -376,8 +374,6 @@ static struct iwl_base_params iwl2030_base_params = { .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .ucode_tracing = true, - .sensitivity_calib_by_driver = true, - .chain_noise_calib_by_driver = true, .shadow_reg_enable = true, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 8106423a2c84..357137f08632 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -471,8 +471,6 @@ static struct iwl_base_params iwl5000_base_params = { .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .ucode_tracing = true, - .sensitivity_calib_by_driver = true, - .chain_noise_calib_by_driver = true, }; static struct iwl_ht_params iwl5000_ht_params = { .ht_greenfield_support = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 7f0715eb0593..8847b2113978 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -443,8 +443,6 @@ static struct iwl_base_params iwl6000_base_params = { .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 512, .ucode_tracing = true, - .sensitivity_calib_by_driver = true, - .chain_noise_calib_by_driver = true, .shadow_reg_enable = true, }; @@ -464,8 +462,6 @@ static struct iwl_base_params iwl6050_base_params = { .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 1024, .ucode_tracing = true, - .sensitivity_calib_by_driver = true, - .chain_noise_calib_by_driver = true, .shadow_reg_enable = true, }; static struct iwl_base_params iwl6000_g2_base_params = { @@ -484,8 +480,6 @@ static struct iwl_base_params iwl6000_g2_base_params = { .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .ucode_tracing = true, - .sensitivity_calib_by_driver = true, - .chain_noise_calib_by_driver = true, .shadow_reg_enable = true, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 98dc544f112c..57763c013ca9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -251,10 +251,6 @@ struct iwl_mod_params { * @temperature_kelvin: temperature report by uCode in kelvin * @max_event_log_size: size of event log buffer size for ucode event logging * @ucode_tracing: support ucode continuous tracing - * @sensitivity_calib_by_driver: driver has the capability to perform - * sensitivity calibration operation - * @chain_noise_calib_by_driver: driver has the capability to perform - * chain noise calibration operation * @shadow_reg_enable: HW shadhow register bit */ struct iwl_base_params { @@ -277,8 +273,6 @@ struct iwl_base_params { bool temperature_kelvin; u32 max_event_log_size; const bool ucode_tracing; - const bool sensitivity_calib_by_driver; - const bool chain_noise_calib_by_driver; const bool shadow_reg_enable; }; /* diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 9b1f9621b630..c02f06901f8c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1747,10 +1747,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR); - if (priv->cfg->base_params->sensitivity_calib_by_driver) - DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); - if (priv->cfg->base_params->chain_noise_calib_by_driver) - DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); if (priv->cfg->base_params->ucode_tracing) DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); if (iwl_bt_statistics(priv)) @@ -1761,12 +1759,10 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); if (iwl_advanced_bt_coexist(priv)) DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); - if (priv->cfg->base_params->sensitivity_calib_by_driver) - DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, - &priv->disable_sens_cal); - if (priv->cfg->base_params->chain_noise_calib_by_driver) - DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, - &priv->disable_chain_noise_cal); + DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, + &priv->disable_sens_cal); + DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, + &priv->disable_chain_noise_cal); return 0; err: -- cgit v1.2.3-58-ga151 From 0da0e5bf1522d75d446f5124e17016628d0a149e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 8 Apr 2011 08:14:56 -0700 Subject: iwlagn: clean up & autodetect statistics There's no need to keep both normal and BT statistics versions around all the time in memory when we only use a subset of both. So keep only the subsets that we need in memory, depending on the debug config). Also, in doing so, we can remove all the calls to iwl_bt_statistics() in the driver as we'll just access the copied statistics now. Finally, also remove this call from the one place where it might still be needed and automatically detect what kind of statistics the device is sending based on their size. This way, we don't need to keep track of which devices do what any more, which is good since this is subject to change based on the ucode version (as some ucode even for non-BT devices will in fact use BT statistics). Warn upon encountering a statistics command from the ucode that isn't known, so we will find such issues earlier in the future. Signed-off-by: Johannes Berg Tested-by: Don Fry Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-2000.c | 1 - drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 1 - drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 43 +--- drivers/net/wireless/iwlwifi/iwl-agn-calib.h | 4 +- drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c | 134 ++++------- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 4 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 17 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 64 ------ drivers/net/wireless/iwlwifi/iwl-core.h | 7 - drivers/net/wireless/iwlwifi/iwl-debugfs.c | 3 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 41 ++-- drivers/net/wireless/iwlwifi/iwl-rx.c | 298 +++++++++++++------------ 13 files changed, 243 insertions(+), 376 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 805b0394850e..a31314fdb053 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -383,7 +383,6 @@ static struct iwl_ht_params iwl2000_ht_params = { }; static struct iwl_bt_params iwl2030_bt_params = { - .bt_statistics = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .advanced_bt_coexist = true, .agg_time_limit = BT_AGG_THRESHOLD_DEF, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 357137f08632..7c286662d26a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -259,7 +259,7 @@ static void iwl5150_temperature(struct iwl_priv *priv) u32 vt = 0; s32 offset = iwl_temp_calib_to_offset(priv); - vt = le32_to_cpu(priv->_agn.statistics.general.common.temperature); + vt = le32_to_cpu(priv->statistics.common.temperature); vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; /* now vt hold the temperature in Kelvin */ priv->temperature = KELVIN_TO_CELSIUS(vt); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 8847b2113978..064981345c84 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -489,7 +489,6 @@ static struct iwl_ht_params iwl6000_ht_params = { }; static struct iwl_bt_params iwl6000_bt_params = { - .bt_statistics = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .advanced_bt_coexist = true, .agg_time_limit = BT_AGG_THRESHOLD_DEF, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 7b761de77b0a..0f6bb9b2e642 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -605,7 +605,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) IWL_DEBUG_CALIB(priv, "<lock, flags); - if (iwl_bt_statistics(priv)) { - rx_info = &(((struct iwl_bt_notif_statistics *)resp)-> - rx.general.common); - ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm); - cck = &(((struct iwl_bt_notif_statistics *)resp)->rx.cck); - } else { - rx_info = &(((struct iwl_notif_statistics *)resp)->rx.general); - ofdm = &(((struct iwl_notif_statistics *)resp)->rx.ofdm); - cck = &(((struct iwl_notif_statistics *)resp)->rx.cck); - } + rx_info = &priv->statistics.rx_non_phy; + ofdm = &priv->statistics.rx_ofdm; + cck = &priv->statistics.rx_cck; if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); spin_unlock_irqrestore(&priv->lock, flags); @@ -851,7 +844,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, * 1) Which antennas are connected. * 2) Differential rx gain settings to balance the 3 receivers. */ -void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) +void iwl_chain_noise_calibration(struct iwl_priv *priv) { struct iwl_chain_noise_data *data = NULL; @@ -896,13 +889,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) } spin_lock_irqsave(&priv->lock, flags); - if (iwl_bt_statistics(priv)) { - rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)-> - rx.general.common); - } else { - rx_info = &(((struct iwl_notif_statistics *)stat_resp)-> - rx.general); - } + + rx_info = &priv->statistics.rx_non_phy; + if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); spin_unlock_irqrestore(&priv->lock, flags); @@ -911,19 +900,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK); rxon_chnum = le16_to_cpu(ctx->staging.channel); - if (iwl_bt_statistics(priv)) { - stat_band24 = !!(((struct iwl_bt_notif_statistics *) - stat_resp)->flag & - STATISTICS_REPLY_FLG_BAND_24G_MSK); - stat_chnum = le32_to_cpu(((struct iwl_bt_notif_statistics *) - stat_resp)->flag) >> 16; - } else { - stat_band24 = !!(((struct iwl_notif_statistics *) - stat_resp)->flag & - STATISTICS_REPLY_FLG_BAND_24G_MSK); - stat_chnum = le32_to_cpu(((struct iwl_notif_statistics *) - stat_resp)->flag) >> 16; - } + stat_band24 = + !!(priv->statistics.flag & STATISTICS_REPLY_FLG_BAND_24G_MSK); + stat_chnum = le32_to_cpu(priv->statistics.flag) >> 16; /* Make sure we accumulate data for just the associated channel * (even if scanning). */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h index ef4d5079a7ed..4ef4dd934254 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h @@ -66,8 +66,8 @@ #include "iwl-core.h" #include "iwl-commands.h" -void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp); -void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp); +void iwl_chain_noise_calibration(struct iwl_priv *priv); +void iwl_sensitivity_calibration(struct iwl_priv *priv); void iwl_init_sensitivity(struct iwl_priv *priv); void iwl_reset_run_time_calib(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index d1834aa7edf0..71a5f31cd7cc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c @@ -39,10 +39,7 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) int p = 0; u32 flag; - if (iwl_bt_statistics(priv)) - flag = le32_to_cpu(priv->_agn.statistics_bt.flag); - else - flag = le32_to_cpu(priv->_agn.statistics.flag); + flag = le32_to_cpu(priv->statistics.flag); p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag); if (flag & UCODE_STATISTICS_CLEAR_MSK) @@ -88,43 +85,22 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, * the last statistics notification from uCode * might not reflect the current uCode activity */ - if (iwl_bt_statistics(priv)) { - ofdm = &priv->_agn.statistics_bt.rx.ofdm; - cck = &priv->_agn.statistics_bt.rx.cck; - general = &priv->_agn.statistics_bt.rx.general.common; - ht = &priv->_agn.statistics_bt.rx.ofdm_ht; - accum_ofdm = &priv->_agn.accum_statistics_bt.rx.ofdm; - accum_cck = &priv->_agn.accum_statistics_bt.rx.cck; - accum_general = - &priv->_agn.accum_statistics_bt.rx.general.common; - accum_ht = &priv->_agn.accum_statistics_bt.rx.ofdm_ht; - delta_ofdm = &priv->_agn.delta_statistics_bt.rx.ofdm; - delta_cck = &priv->_agn.delta_statistics_bt.rx.cck; - delta_general = - &priv->_agn.delta_statistics_bt.rx.general.common; - delta_ht = &priv->_agn.delta_statistics_bt.rx.ofdm_ht; - max_ofdm = &priv->_agn.max_delta_bt.rx.ofdm; - max_cck = &priv->_agn.max_delta_bt.rx.cck; - max_general = &priv->_agn.max_delta_bt.rx.general.common; - max_ht = &priv->_agn.max_delta_bt.rx.ofdm_ht; - } else { - ofdm = &priv->_agn.statistics.rx.ofdm; - cck = &priv->_agn.statistics.rx.cck; - general = &priv->_agn.statistics.rx.general; - ht = &priv->_agn.statistics.rx.ofdm_ht; - accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm; - accum_cck = &priv->_agn.accum_statistics.rx.cck; - accum_general = &priv->_agn.accum_statistics.rx.general; - accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht; - delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm; - delta_cck = &priv->_agn.delta_statistics.rx.cck; - delta_general = &priv->_agn.delta_statistics.rx.general; - delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht; - max_ofdm = &priv->_agn.max_delta.rx.ofdm; - max_cck = &priv->_agn.max_delta.rx.cck; - max_general = &priv->_agn.max_delta.rx.general; - max_ht = &priv->_agn.max_delta.rx.ofdm_ht; - } + ofdm = &priv->statistics.rx_ofdm; + cck = &priv->statistics.rx_cck; + general = &priv->statistics.rx_non_phy; + ht = &priv->statistics.rx_ofdm_ht; + accum_ofdm = &priv->accum_stats.rx_ofdm; + accum_cck = &priv->accum_stats.rx_cck; + accum_general = &priv->accum_stats.rx_non_phy; + accum_ht = &priv->accum_stats.rx_ofdm_ht; + delta_ofdm = &priv->delta_stats.rx_ofdm; + delta_cck = &priv->delta_stats.rx_cck; + delta_general = &priv->delta_stats.rx_non_phy; + delta_ht = &priv->delta_stats.rx_ofdm_ht; + max_ofdm = &priv->max_delta_stats.rx_ofdm; + max_cck = &priv->max_delta_stats.rx_cck; + max_general = &priv->max_delta_stats.rx_non_phy; + max_ht = &priv->max_delta_stats.rx_ofdm_ht; pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, @@ -531,20 +507,13 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, } /* the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - if (iwl_bt_statistics(priv)) { - tx = &priv->_agn.statistics_bt.tx; - accum_tx = &priv->_agn.accum_statistics_bt.tx; - delta_tx = &priv->_agn.delta_statistics_bt.tx; - max_tx = &priv->_agn.max_delta_bt.tx; - } else { - tx = &priv->_agn.statistics.tx; - accum_tx = &priv->_agn.accum_statistics.tx; - delta_tx = &priv->_agn.delta_statistics.tx; - max_tx = &priv->_agn.max_delta.tx; - } + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + tx = &priv->statistics.tx; + accum_tx = &priv->accum_stats.tx; + delta_tx = &priv->delta_stats.tx; + max_tx = &priv->max_delta_stats.tx; pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, @@ -731,36 +700,21 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, } /* the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - if (iwl_bt_statistics(priv)) { - general = &priv->_agn.statistics_bt.general.common; - dbg = &priv->_agn.statistics_bt.general.common.dbg; - div = &priv->_agn.statistics_bt.general.common.div; - accum_general = &priv->_agn.accum_statistics_bt.general.common; - accum_dbg = &priv->_agn.accum_statistics_bt.general.common.dbg; - accum_div = &priv->_agn.accum_statistics_bt.general.common.div; - delta_general = &priv->_agn.delta_statistics_bt.general.common; - max_general = &priv->_agn.max_delta_bt.general.common; - delta_dbg = &priv->_agn.delta_statistics_bt.general.common.dbg; - max_dbg = &priv->_agn.max_delta_bt.general.common.dbg; - delta_div = &priv->_agn.delta_statistics_bt.general.common.div; - max_div = &priv->_agn.max_delta_bt.general.common.div; - } else { - general = &priv->_agn.statistics.general.common; - dbg = &priv->_agn.statistics.general.common.dbg; - div = &priv->_agn.statistics.general.common.div; - accum_general = &priv->_agn.accum_statistics.general.common; - accum_dbg = &priv->_agn.accum_statistics.general.common.dbg; - accum_div = &priv->_agn.accum_statistics.general.common.div; - delta_general = &priv->_agn.delta_statistics.general.common; - max_general = &priv->_agn.max_delta.general.common; - delta_dbg = &priv->_agn.delta_statistics.general.common.dbg; - max_dbg = &priv->_agn.max_delta.general.common.dbg; - delta_div = &priv->_agn.delta_statistics.general.common.div; - max_div = &priv->_agn.max_delta.general.common.div; - } + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + general = &priv->statistics.common; + dbg = &priv->statistics.common.dbg; + div = &priv->statistics.common.div; + accum_general = &priv->accum_stats.common; + accum_dbg = &priv->accum_stats.common.dbg; + accum_div = &priv->accum_stats.common.div; + delta_general = &priv->delta_stats.common; + max_general = &priv->max_delta_stats.common; + delta_dbg = &priv->delta_stats.common.dbg; + max_dbg = &priv->max_delta_stats.common.dbg; + delta_div = &priv->delta_stats.common.div; + max_div = &priv->max_delta_stats.common.div; pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, @@ -876,8 +830,8 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file, * the last statistics notification from uCode * might not reflect the current uCode activity */ - bt = &priv->_agn.statistics_bt.general.activity; - accum_bt = &priv->_agn.accum_statistics_bt.general.activity; + bt = &priv->statistics.bt_activity; + accum_bt = &priv->accum_stats.bt_activity; pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n"); @@ -918,10 +872,8 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file, pos += scnprintf(buf + pos, bufsz - pos, "(rx)num_bt_kills:\t\t%u\t\t\t%u\n", - le32_to_cpu(priv->_agn.statistics_bt.rx. - general.num_bt_kills), - priv->_agn.accum_statistics_bt.rx. - general.num_bt_kills); + le32_to_cpu(priv->statistics.num_bt_kills), + priv->statistics.accum_num_bt_kills); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index bc5dfe2978f0..e741128842bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -549,9 +549,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) void iwlagn_temperature(struct iwl_priv *priv) { /* store temperature from correct statistics (in Celsius) */ - priv->temperature = le32_to_cpu((iwl_bt_statistics(priv)) ? - priv->_agn.statistics_bt.general.common.temperature : - priv->_agn.statistics.general.common.temperature); + priv->temperature = le32_to_cpu(priv->statistics.common.temperature); iwl_tt_handler(priv); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 23b89c2e71da..20499b764430 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1705,10 +1705,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) else priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; - if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BTSTATS || - (priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics)) - priv->bt_statistics = true; - /* Copy images into buffers for card's bus-master reads ... */ /* Runtime instructions (first block of data in file) */ @@ -2626,17 +2622,8 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) } if (priv->start_calib) { - if (iwl_bt_statistics(priv)) { - iwl_chain_noise_calibration(priv, - (void *)&priv->_agn.statistics_bt); - iwl_sensitivity_calibration(priv, - (void *)&priv->_agn.statistics_bt); - } else { - iwl_chain_noise_calibration(priv, - (void *)&priv->_agn.statistics); - iwl_sensitivity_calibration(priv, - (void *)&priv->_agn.statistics); - } + iwl_chain_noise_calibration(priv); + iwl_sensitivity_calibration(priv); } mutex_unlock(&priv->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index a1a5c1b23096..0edba8a6419b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2535,53 +2535,6 @@ struct rate_histogram { /* statistics command response */ -struct iwl39_statistics_rx_phy { - __le32 ina_cnt; - __le32 fina_cnt; - __le32 plcp_err; - __le32 crc32_err; - __le32 overrun_err; - __le32 early_overrun_err; - __le32 crc32_good; - __le32 false_alarm_cnt; - __le32 fina_sync_err_cnt; - __le32 sfd_timeout; - __le32 fina_timeout; - __le32 unresponded_rts; - __le32 rxe_frame_limit_overrun; - __le32 sent_ack_cnt; - __le32 sent_cts_cnt; -} __packed; - -struct iwl39_statistics_rx_non_phy { - __le32 bogus_cts; /* CTS received when not expecting CTS */ - __le32 bogus_ack; /* ACK received when not expecting ACK */ - __le32 non_bssid_frames; /* number of frames with BSSID that - * doesn't belong to the STA BSSID */ - __le32 filtered_frames; /* count frames that were dumped in the - * filtering process */ - __le32 non_channel_beacons; /* beacons with our bss id but not on - * our serving channel */ -} __packed; - -struct iwl39_statistics_rx { - struct iwl39_statistics_rx_phy ofdm; - struct iwl39_statistics_rx_phy cck; - struct iwl39_statistics_rx_non_phy general; -} __packed; - -struct iwl39_statistics_tx { - __le32 preamble_cnt; - __le32 rx_detected_cnt; - __le32 bt_prio_defer_cnt; - __le32 bt_prio_kill_cnt; - __le32 few_bytes_cnt; - __le32 cts_timeout; - __le32 ack_timeout; - __le32 expected_ack_cnt; - __le32 actual_ack_cnt; -} __packed; - struct statistics_dbg { __le32 burst_check; __le32 burst_count; @@ -2589,23 +2542,6 @@ struct statistics_dbg { __le32 reserved[3]; } __packed; -struct iwl39_statistics_div { - __le32 tx_on_a; - __le32 tx_on_b; - __le32 exec_time; - __le32 probe_time; -} __packed; - -struct iwl39_statistics_general { - __le32 temperature; - struct statistics_dbg dbg; - __le32 sleep_time; - __le32 slots_out; - __le32 slots_idle; - __le32 ttl_timestamp; - struct iwl39_statistics_div div; -} __packed; - struct statistics_rx_phy { __le32 ina_cnt; __le32 fina_cnt; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 57763c013ca9..6988335328e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -279,7 +279,6 @@ struct iwl_base_params { * @advanced_bt_coexist: support advanced bt coexist * @bt_init_traffic_load: specify initial bt traffic load * @bt_prio_boost: default bt priority boost value - * @bt_statistics: use BT version of statistics notification * @agg_time_limit: maximum number of uSec in aggregation * @ampdu_factor: Maximum A-MPDU length factor * @ampdu_density: Minimum A-MPDU spacing @@ -289,7 +288,6 @@ struct iwl_bt_params { bool advanced_bt_coexist; u8 bt_init_traffic_load; u8 bt_prio_boost; - const bool bt_statistics; u16 agg_time_limit; u8 ampdu_factor; u8 ampdu_density; @@ -696,11 +694,6 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv) priv->cfg->bt_params->advanced_bt_coexist; } -static inline bool iwl_bt_statistics(struct iwl_priv *priv) -{ - return priv->bt_statistics; -} - extern bool bt_coex_active; extern bool bt_siso_mode; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index c02f06901f8c..897efacb96eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1751,8 +1751,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); if (priv->cfg->base_params->ucode_tracing) DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); - if (iwl_bt_statistics(priv)) - DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 7fe68f8dd210..e84534c4d956 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -543,13 +543,12 @@ enum iwl_ucode_tlv_type { * enum iwl_ucode_tlv_flag - ucode API flags * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously * was a separate TLV but moved here to save space. - * @IWL_UCODE_TLV_FLAGS_BTSTATS: This uCode image uses BT statistics, which - * may be true even if the device doesn't have BT. + * @IWL_UCODE_TLV_FLAGS_RESERVED_1: reserved * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). */ enum iwl_ucode_tlv_flag { IWL_UCODE_TLV_FLAGS_PAN = BIT(0), - IWL_UCODE_TLV_FLAGS_BTSTATS = BIT(1), + IWL_UCODE_TLV_FLAGS_RESERVED_1 = BIT(1), IWL_UCODE_TLV_FLAGS_MFP = BIT(2), }; @@ -1356,6 +1355,31 @@ struct iwl_priv { /* Last Rx'd beacon timestamp */ u64 timestamp; + struct { + __le32 flag; + struct statistics_general_common common; + struct statistics_rx_non_phy rx_non_phy; + struct statistics_rx_phy rx_ofdm; + struct statistics_rx_ht_phy rx_ofdm_ht; + struct statistics_rx_phy rx_cck; + struct statistics_tx tx; +#ifdef CONFIG_IWLWIFI_DEBUGFS + struct statistics_bt_activity bt_activity; + __le32 num_bt_kills, accum_num_bt_kills; +#endif + } statistics; +#ifdef CONFIG_IWLWIFI_DEBUGFS + struct { + struct statistics_general_common common; + struct statistics_rx_non_phy rx_non_phy; + struct statistics_rx_phy rx_ofdm; + struct statistics_rx_ht_phy rx_ofdm_ht; + struct statistics_rx_phy rx_cck; + struct statistics_tx tx; + struct statistics_bt_activity bt_activity; + } accum_stats, delta_stats, max_delta_stats; +#endif + struct { /* INT ICT Table */ __le32 *ict_tbl; @@ -1387,19 +1411,9 @@ struct iwl_priv { u8 phy_calib_chain_noise_reset_cmd; u8 phy_calib_chain_noise_gain_cmd; - struct iwl_notif_statistics statistics; - struct iwl_bt_notif_statistics statistics_bt; /* counts reply_tx error */ struct reply_tx_error_statistics reply_tx_stats; struct reply_agg_tx_error_statistics reply_agg_tx_stats; -#ifdef CONFIG_IWLWIFI_DEBUGFS - struct iwl_notif_statistics accum_statistics; - struct iwl_notif_statistics delta_statistics; - struct iwl_notif_statistics max_delta; - struct iwl_bt_notif_statistics accum_statistics_bt; - struct iwl_bt_notif_statistics delta_statistics_bt; - struct iwl_bt_notif_statistics max_delta_bt; -#endif /* notification wait support */ struct list_head notif_waits; spinlock_t notif_wait_lock; @@ -1424,7 +1438,6 @@ struct iwl_priv { bool bt_ch_announce; bool bt_full_concurrent; bool bt_ant_couple_ok; - bool bt_statistics; __le32 kill_ack_mask; __le32 kill_cts_mask; __le16 bt_valid; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 4472761fc591..b49819ca2cd6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -390,21 +390,16 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal * operation state. */ -static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt) +static bool iwl_good_ack_health(struct iwl_priv *priv, + struct statistics_tx *cur) { int actual_delta, expected_delta, ba_timeout_delta; - struct statistics_tx *cur, *old; + struct statistics_tx *old; if (priv->_agn.agg_tids_count) return true; - if (iwl_bt_statistics(priv)) { - cur = &pkt->u.stats_bt.tx; - old = &priv->_agn.statistics_bt.tx; - } else { - cur = &pkt->u.stats.tx; - old = &priv->_agn.statistics.tx; - } + old = &priv->statistics.tx; actual_delta = le32_to_cpu(cur->actual_ack_cnt) - le32_to_cpu(old->actual_ack_cnt); @@ -430,10 +425,10 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt * DEBUG is not, these will just compile out. */ IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta %d\n", - priv->_agn.delta_statistics.tx.rx_detected_cnt); + priv->delta_stats.tx.rx_detected_cnt); IWL_DEBUG_RADIO(priv, "ack_or_ba_timeout_collision delta %d\n", - priv->_agn.delta_statistics.tx.ack_or_ba_timeout_collision); + priv->delta_stats.tx.ack_or_ba_timeout_collision); #endif if (ba_timeout_delta >= BA_TIMEOUT_MAX) @@ -450,7 +445,9 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt * to improve the throughput. */ static bool iwl_good_plcp_health(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, unsigned int msecs) + struct statistics_rx_phy *cur_ofdm, + struct statistics_rx_ht_phy *cur_ofdm_ht, + unsigned int msecs) { int delta; int threshold = priv->cfg->base_params->plcp_delta_threshold; @@ -460,29 +457,12 @@ static bool iwl_good_plcp_health(struct iwl_priv *priv, return true; } - if (iwl_bt_statistics(priv)) { - struct statistics_rx_bt *cur, *old; - - cur = &pkt->u.stats_bt.rx; - old = &priv->_agn.statistics_bt.rx; - - delta = le32_to_cpu(cur->ofdm.plcp_err) - - le32_to_cpu(old->ofdm.plcp_err) + - le32_to_cpu(cur->ofdm_ht.plcp_err) - - le32_to_cpu(old->ofdm_ht.plcp_err); - } else { - struct statistics_rx *cur, *old; - - cur = &pkt->u.stats.rx; - old = &priv->_agn.statistics.rx; - - delta = le32_to_cpu(cur->ofdm.plcp_err) - - le32_to_cpu(old->ofdm.plcp_err) + - le32_to_cpu(cur->ofdm_ht.plcp_err) - - le32_to_cpu(old->ofdm_ht.plcp_err); - } + delta = le32_to_cpu(cur_ofdm->plcp_err) - + le32_to_cpu(priv->statistics.rx_ofdm.plcp_err) + + le32_to_cpu(cur_ofdm_ht->plcp_err) - + le32_to_cpu(priv->statistics.rx_ofdm_ht.plcp_err); - /* Can be negative if firmware reseted statistics */ + /* Can be negative if firmware reset statistics */ if (delta <= 0) return true; @@ -497,44 +477,36 @@ static bool iwl_good_plcp_health(struct iwl_priv *priv, } static void iwl_recover_from_statistics(struct iwl_priv *priv, - struct iwl_rx_packet *pkt) + struct statistics_rx_phy *cur_ofdm, + struct statistics_rx_ht_phy *cur_ofdm_ht, + struct statistics_tx *tx, + unsigned long stamp) { const struct iwl_mod_params *mod_params = priv->cfg->mod_params; unsigned int msecs; - unsigned long stamp; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - stamp = jiffies; msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies); /* Only gather statistics and update time stamp when not associated */ if (!iwl_is_any_associated(priv)) - goto out; + return; /* Do not check/recover when do not have enough statistics data */ if (msecs < 99) return; - if (mod_params->ack_check && !iwl_good_ack_health(priv, pkt)) { + if (mod_params->ack_check && !iwl_good_ack_health(priv, tx)) { IWL_ERR(priv, "low ack count detected, restart firmware\n"); if (!iwl_force_reset(priv, IWL_FW_RESET, false)) return; } - if (mod_params->plcp_check && !iwl_good_plcp_health(priv, pkt, msecs)) + if (mod_params->plcp_check && + !iwl_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs)) iwl_force_reset(priv, IWL_RF_RESET, false); - -out: - if (iwl_bt_statistics(priv)) - memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt, - sizeof(priv->_agn.statistics_bt)); - else - memcpy(&priv->_agn.statistics, &pkt->u.stats, - sizeof(priv->_agn.statistics)); - - priv->rx_statistics_jiffies = stamp; } /* Calculate noise level, based on measurements during network silence just @@ -548,10 +520,8 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) int bcn_silence_a, bcn_silence_b, bcn_silence_c; int last_rx_noise; - if (iwl_bt_statistics(priv)) - rx_info = &(priv->_agn.statistics_bt.rx.general.common); - else - rx_info = &(priv->_agn.statistics.rx.general); + rx_info = &priv->statistics.rx_non_phy; + bcn_silence_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER; bcn_silence_b = @@ -583,105 +553,153 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) last_rx_noise); } +#ifdef CONFIG_IWLWIFI_DEBUGFS /* * based on the assumption of all statistics counter are in DWORD * FIXME: This function is for debugging, do not deal with * the case of counters roll-over. */ -static void iwl_accumulative_statistics(struct iwl_priv *priv, - __le32 *stats) +static void accum_stats(__le32 *prev, __le32 *cur, __le32 *delta, + __le32 *max_delta, __le32 *accum, int size) { -#ifdef CONFIG_IWLWIFI_DEBUGFS - int i, size; - __le32 *prev_stats; - u32 *accum_stats; - u32 *delta, *max_delta; - struct statistics_general_common *general, *accum_general; - struct statistics_tx *tx, *accum_tx; - - if (iwl_bt_statistics(priv)) { - prev_stats = (__le32 *)&priv->_agn.statistics_bt; - accum_stats = (u32 *)&priv->_agn.accum_statistics_bt; - size = sizeof(struct iwl_bt_notif_statistics); - general = &priv->_agn.statistics_bt.general.common; - accum_general = &priv->_agn.accum_statistics_bt.general.common; - tx = &priv->_agn.statistics_bt.tx; - accum_tx = &priv->_agn.accum_statistics_bt.tx; - delta = (u32 *)&priv->_agn.delta_statistics_bt; - max_delta = (u32 *)&priv->_agn.max_delta_bt; - } else { - prev_stats = (__le32 *)&priv->_agn.statistics; - accum_stats = (u32 *)&priv->_agn.accum_statistics; - size = sizeof(struct iwl_notif_statistics); - general = &priv->_agn.statistics.general.common; - accum_general = &priv->_agn.accum_statistics.general.common; - tx = &priv->_agn.statistics.tx; - accum_tx = &priv->_agn.accum_statistics.tx; - delta = (u32 *)&priv->_agn.delta_statistics; - max_delta = (u32 *)&priv->_agn.max_delta; - } - for (i = sizeof(__le32); i < size; - i += sizeof(__le32), stats++, prev_stats++, delta++, - max_delta++, accum_stats++) { - if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { - *delta = (le32_to_cpu(*stats) - - le32_to_cpu(*prev_stats)); - *accum_stats += *delta; - if (*delta > *max_delta) + int i; + + for (i = 0; + i < size / sizeof(__le32); + i++, prev++, cur++, delta++, max_delta++, accum++) { + if (le32_to_cpu(*cur) > le32_to_cpu(*prev)) { + *delta = cpu_to_le32( + le32_to_cpu(*cur) - le32_to_cpu(*prev)); + le32_add_cpu(accum, le32_to_cpu(*delta)); + if (le32_to_cpu(*delta) > le32_to_cpu(*max_delta)) *max_delta = *delta; } } +} - /* reset accumulative statistics for "no-counter" type statistics */ - accum_general->temperature = general->temperature; - accum_general->temperature_m = general->temperature_m; - accum_general->ttl_timestamp = general->ttl_timestamp; - accum_tx->tx_power.ant_a = tx->tx_power.ant_a; - accum_tx->tx_power.ant_b = tx->tx_power.ant_b; - accum_tx->tx_power.ant_c = tx->tx_power.ant_c; -#endif +static void +iwl_accumulative_statistics(struct iwl_priv *priv, + struct statistics_general_common *common, + struct statistics_rx_non_phy *rx_non_phy, + struct statistics_rx_phy *rx_ofdm, + struct statistics_rx_ht_phy *rx_ofdm_ht, + struct statistics_rx_phy *rx_cck, + struct statistics_tx *tx, + struct statistics_bt_activity *bt_activity) +{ +#define ACCUM(_name) \ + accum_stats((__le32 *)&priv->statistics._name, \ + (__le32 *)_name, \ + (__le32 *)&priv->delta_stats._name, \ + (__le32 *)&priv->max_delta_stats._name, \ + (__le32 *)&priv->accum_stats._name, \ + sizeof(*_name)); + + ACCUM(common); + ACCUM(rx_non_phy); + ACCUM(rx_ofdm); + ACCUM(rx_ofdm_ht); + ACCUM(rx_cck); + ACCUM(tx); + if (bt_activity) + ACCUM(bt_activity); +#undef ACCUM } +#else +static inline void +iwl_accumulative_statistics(struct iwl_priv *priv, + struct statistics_general_common *common, + struct statistics_rx_non_phy *rx_non_phy, + struct statistics_rx_phy *rx_ofdm, + struct statistics_rx_ht_phy *rx_ofdm_ht, + struct statistics_rx_phy *rx_cck, + struct statistics_tx *tx, + struct statistics_bt_activity *bt_activity) +{ +} +#endif static void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { + unsigned long stamp = jiffies; const int reg_recalib_period = 60; int change; struct iwl_rx_packet *pkt = rxb_addr(rxb); + u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; + __le32 *flag; + struct statistics_general_common *common; + struct statistics_rx_non_phy *rx_non_phy; + struct statistics_rx_phy *rx_ofdm; + struct statistics_rx_ht_phy *rx_ofdm_ht; + struct statistics_rx_phy *rx_cck; + struct statistics_tx *tx; + struct statistics_bt_activity *bt_activity; + + len -= sizeof(struct iwl_cmd_header); /* skip header */ + + IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n", + len); + + if (len == sizeof(struct iwl_bt_notif_statistics)) { + struct iwl_bt_notif_statistics *stats; + stats = &pkt->u.stats_bt; + flag = &stats->flag; + common = &stats->general.common; + rx_non_phy = &stats->rx.general.common; + rx_ofdm = &stats->rx.ofdm; + rx_ofdm_ht = &stats->rx.ofdm_ht; + rx_cck = &stats->rx.cck; + tx = &stats->tx; + bt_activity = &stats->general.activity; - if (iwl_bt_statistics(priv)) { - IWL_DEBUG_RX(priv, - "Statistics notification received (%d vs %d).\n", - (int)sizeof(struct iwl_bt_notif_statistics), - le32_to_cpu(pkt->len_n_flags) & - FH_RSCSR_FRAME_SIZE_MSK); - - change = ((priv->_agn.statistics_bt.general.common.temperature != - pkt->u.stats_bt.general.common.temperature) || - ((priv->_agn.statistics_bt.flag & - STATISTICS_REPLY_FLG_HT40_MODE_MSK) != - (pkt->u.stats_bt.flag & - STATISTICS_REPLY_FLG_HT40_MODE_MSK))); - - iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt); +#ifdef CONFIG_IWLWIFI_DEBUGFS + /* handle this exception directly */ + priv->statistics.num_bt_kills = stats->rx.general.num_bt_kills; + le32_add_cpu(&priv->statistics.accum_num_bt_kills, + le32_to_cpu(stats->rx.general.num_bt_kills)); +#endif + } else if (len == sizeof(struct iwl_notif_statistics)) { + struct iwl_notif_statistics *stats; + stats = &pkt->u.stats; + flag = &stats->flag; + common = &stats->general.common; + rx_non_phy = &stats->rx.general; + rx_ofdm = &stats->rx.ofdm; + rx_ofdm_ht = &stats->rx.ofdm_ht; + rx_cck = &stats->rx.cck; + tx = &stats->tx; + bt_activity = NULL; } else { - IWL_DEBUG_RX(priv, - "Statistics notification received (%d vs %d).\n", - (int)sizeof(struct iwl_notif_statistics), - le32_to_cpu(pkt->len_n_flags) & - FH_RSCSR_FRAME_SIZE_MSK); - - change = ((priv->_agn.statistics.general.common.temperature != - pkt->u.stats.general.common.temperature) || - ((priv->_agn.statistics.flag & - STATISTICS_REPLY_FLG_HT40_MODE_MSK) != - (pkt->u.stats.flag & - STATISTICS_REPLY_FLG_HT40_MODE_MSK))); - - iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); + WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n", + len, sizeof(struct iwl_bt_notif_statistics), + sizeof(struct iwl_notif_statistics)); + return; } - iwl_recover_from_statistics(priv, pkt); + change = common->temperature != priv->statistics.common.temperature || + (*flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK) != + (priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK); + + iwl_accumulative_statistics(priv, common, rx_non_phy, rx_ofdm, + rx_ofdm_ht, rx_cck, tx, bt_activity); + + iwl_recover_from_statistics(priv, rx_ofdm, rx_ofdm_ht, tx, stamp); + + priv->statistics.flag = *flag; + memcpy(&priv->statistics.common, common, sizeof(*common)); + memcpy(&priv->statistics.rx_non_phy, rx_non_phy, sizeof(*rx_non_phy)); + memcpy(&priv->statistics.rx_ofdm, rx_ofdm, sizeof(*rx_ofdm)); + memcpy(&priv->statistics.rx_ofdm_ht, rx_ofdm_ht, sizeof(*rx_ofdm_ht)); + memcpy(&priv->statistics.rx_cck, rx_cck, sizeof(*rx_cck)); + memcpy(&priv->statistics.tx, tx, sizeof(*tx)); +#ifdef CONFIG_IWLWIFI_DEBUGFS + if (bt_activity) + memcpy(&priv->statistics.bt_activity, bt_activity, + sizeof(*bt_activity)); +#endif + + priv->rx_statistics_jiffies = stamp; set_bit(STATUS_STATISTICS, &priv->status); @@ -708,18 +726,12 @@ static void iwl_rx_reply_statistics(struct iwl_priv *priv, if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { #ifdef CONFIG_IWLWIFI_DEBUGFS - memset(&priv->_agn.accum_statistics, 0, - sizeof(struct iwl_notif_statistics)); - memset(&priv->_agn.delta_statistics, 0, - sizeof(struct iwl_notif_statistics)); - memset(&priv->_agn.max_delta, 0, - sizeof(struct iwl_notif_statistics)); - memset(&priv->_agn.accum_statistics_bt, 0, - sizeof(struct iwl_bt_notif_statistics)); - memset(&priv->_agn.delta_statistics_bt, 0, - sizeof(struct iwl_bt_notif_statistics)); - memset(&priv->_agn.max_delta_bt, 0, - sizeof(struct iwl_bt_notif_statistics)); + memset(&priv->accum_stats, 0, + sizeof(priv->accum_stats)); + memset(&priv->delta_stats, 0, + sizeof(priv->delta_stats)); + memset(&priv->max_delta_stats, 0, + sizeof(priv->max_delta_stats)); #endif IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); } -- cgit v1.2.3-58-ga151 From 6fc3ba999994b675c4e6af77ac4e1a6bfd8e6128 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 4 Apr 2011 06:16:29 -0700 Subject: iwlagn: downgrade warning on unknown TLV If we maintain API properly, then there isn't really a reason to warn about this since we'll just be adding things that are safe to ignore, so downgrade the warning to debug info level. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 20499b764430..47a4cda9eb72 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1481,7 +1481,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, le32_to_cpup((__le32 *)tlv_data); break; default: - IWL_WARN(priv, "unknown TLV: %d\n", tlv_type); + IWL_DEBUG_INFO(priv, "unknown TLV: %d\n", tlv_type); break; } } -- cgit v1.2.3-58-ga151 From 93ae653491f0a413d5f4d9aa4df45d09ecb55d62 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 8 Apr 2011 13:03:02 -0700 Subject: cnic: Fix rtnl deadlock When cnic_stop_hw() -> cnic_cm_stop_bnx2x_hw() is called under rtnl_lock() from NETDEV_DOWN event, it waits for cnic_delete_task() to complete. It will deadlock when cnic_delete_task() takes rtnl_lock() before calling cnic_ulp_stop_one(). We fix it by removing the rtnl_lock() in cnic_delete_task(). cnic_ulp_stop_one() has mutex and atomic bit ops to prevent important operations from being done more than once, so it is not necessary to take rtnl_lock(). Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/cnic.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 5dfbff06631c..cde59b4e5ef8 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -3983,9 +3983,7 @@ static void cnic_delete_task(struct work_struct *work) if (test_and_clear_bit(CNIC_LCL_FL_STOP_ISCSI, &cp->cnic_local_flags)) { struct drv_ctl_info info; - rtnl_lock(); cnic_ulp_stop_one(cp, CNIC_ULP_ISCSI); - rtnl_unlock(); info.cmd = DRV_CTL_ISCSI_STOPPED_CMD; cp->ethdev->drv_ctl(dev->netdev, &info); -- cgit v1.2.3-58-ga151 From c5e06360317d9c7a91de983749d136c4089e5379 Mon Sep 17 00:00:00 2001 From: Dimitris Michailidis Date: Fri, 8 Apr 2011 13:06:25 -0700 Subject: cxgb4: drop phys_id interface and implement the newer set_phys_id Signed-off-by: Dimitris Michailidis Signed-off-by: David S. Miller --- drivers/net/cxgb4/cxgb4_main.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c index 5352c8a23f4d..0af9c9f0ca78 100644 --- a/drivers/net/cxgb4/cxgb4_main.c +++ b/drivers/net/cxgb4/cxgb4_main.c @@ -1336,15 +1336,20 @@ static int restart_autoneg(struct net_device *dev) return 0; } -static int identify_port(struct net_device *dev, u32 data) +static int identify_port(struct net_device *dev, + enum ethtool_phys_id_state state) { + unsigned int val; struct adapter *adap = netdev2adap(dev); - if (data == 0) - data = 2; /* default to 2 seconds */ + if (state == ETHTOOL_ID_ACTIVE) + val = 0xffff; + else if (state == ETHTOOL_ID_INACTIVE) + val = 0; + else + return -EINVAL; - return t4_identify_port(adap, adap->fn, netdev2pinfo(dev)->viid, - data * 5); + return t4_identify_port(adap, adap->fn, netdev2pinfo(dev)->viid, val); } static unsigned int from_fw_linkcaps(unsigned int type, unsigned int caps) @@ -2011,7 +2016,7 @@ static struct ethtool_ops cxgb_ethtool_ops = { .set_sg = ethtool_op_set_sg, .get_link = ethtool_op_get_link, .get_strings = get_strings, - .phys_id = identify_port, + .set_phys_id = identify_port, .nway_reset = restart_autoneg, .get_sset_count = get_sset_count, .get_ethtool_stats = get_stats, -- cgit v1.2.3-58-ga151 From 857a3d0fb648b450de4a87cc2df9055774cafd2d Mon Sep 17 00:00:00 2001 From: Dimitris Michailidis Date: Fri, 8 Apr 2011 13:07:08 -0700 Subject: cxgb4vf: drop phys_id interface and implement the newer set_phys_id Signed-off-by: Dimitris Michailidis Signed-off-by: David S. Miller --- drivers/net/cxgb4vf/cxgb4vf_main.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c index 6aad64df4dcb..b0d037ea367d 100644 --- a/drivers/net/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/cxgb4vf/cxgb4vf_main.c @@ -1352,11 +1352,20 @@ static int cxgb4vf_set_rx_csum(struct net_device *dev, u32 csum) /* * Identify the port by blinking the port's LED. */ -static int cxgb4vf_phys_id(struct net_device *dev, u32 id) +static int cxgb4vf_phys_id(struct net_device *dev, + enum ethtool_phys_id_state state) { + unsigned int val; struct port_info *pi = netdev_priv(dev); - return t4vf_identify_port(pi->adapter, pi->viid, 5); + if (state == ETHTOOL_ID_ACTIVE) + val = 0xffff; + else if (state == ETHTOOL_ID_INACTIVE) + val = 0; + else + return -EINVAL; + + return t4vf_identify_port(pi->adapter, pi->viid, val); } /* @@ -1588,7 +1597,7 @@ static struct ethtool_ops cxgb4vf_ethtool_ops = { .set_sg = ethtool_op_set_sg, .get_link = ethtool_op_get_link, .get_strings = cxgb4vf_get_strings, - .phys_id = cxgb4vf_phys_id, + .set_phys_id = cxgb4vf_phys_id, .get_sset_count = cxgb4vf_get_sset_count, .get_ethtool_stats = cxgb4vf_get_ethtool_stats, .get_regs_len = cxgb4vf_get_regs_len, -- cgit v1.2.3-58-ga151 From 6e4d2d9eb22dc9e9f0abfb1a464405b97a461cde Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 6 Apr 2011 21:40:13 +0000 Subject: usb: plusb: Whitespace This patch cleans up a couple of instances of incorrect whitespace Signed-off-by: Simon Wood Signed-off-by: David S. Miller --- drivers/net/usb/plusb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c index 823c53751307..2fe1bb5d7ba5 100644 --- a/drivers/net/usb/plusb.c +++ b/drivers/net/usb/plusb.c @@ -134,13 +134,13 @@ static struct usb_driver plusb_driver = { static int __init plusb_init(void) { - return usb_register(&plusb_driver); + return usb_register(&plusb_driver); } module_init(plusb_init); static void __exit plusb_exit(void) { - usb_deregister(&plusb_driver); + usb_deregister(&plusb_driver); } module_exit(plusb_exit); -- cgit v1.2.3-58-ga151 From 647da406e5e6cef87d17ee4d3c65c7b496883a3f Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 6 Apr 2011 21:40:14 +0000 Subject: usb: plusb: Add support for PL-25A1 This patch adds support for the PL-25A1 by adding the appropriate USB ID's. This chip is used in the Belkin 'Windows Easy Transfer' Cables. Signed-off-by: Simon Wood Signed-off-by: David S. Miller --- drivers/net/usb/Kconfig | 2 +- drivers/net/usb/plusb.c | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 3ec22c307797..9d4f9117260f 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -258,7 +258,7 @@ config USB_NET_NET1080 optionally with LEDs that indicate traffic config USB_NET_PLUSB - tristate "Prolific PL-2301/2302 based cables" + tristate "Prolific PL-2301/2302/25A1 based cables" # if the handshake/init/reset problems, from original 'plusb', # are ever resolved ... then remove "experimental" depends on USB_USBNET && EXPERIMENTAL diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c index 2fe1bb5d7ba5..f46aa07bfa69 100644 --- a/drivers/net/usb/plusb.c +++ b/drivers/net/usb/plusb.c @@ -45,6 +45,14 @@ * seems to get wedged under load. Prolific docs are weak, and * don't identify differences between PL2301 and PL2302, much less * anything to explain the different PL2302 versions observed. + * + * NOTE: pl2501 has several modes, including pl2301 and pl2302 + * compatibility. Some docs suggest the difference between 2301 + * and 2302 is only to make MS-Windows use a different driver... + * + * pl25a1 glue based on patch from Tony Gibbs. Prolific "docs" on + * this chip are as usual incomplete about what control messages + * are supported. */ /* @@ -95,7 +103,7 @@ static int pl_reset(struct usbnet *dev) } static const struct driver_info prolific_info = { - .description = "Prolific PL-2301/PL-2302", + .description = "Prolific PL-2301/PL-2302/PL-25A1", .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT, /* some PL-2302 versions seem to fail usb_set_interface() */ .reset = pl_reset, @@ -111,6 +119,7 @@ static const struct driver_info prolific_info = { static const struct usb_device_id products [] = { +/* full speed cables */ { USB_DEVICE(0x067b, 0x0000), // PL-2301 .driver_info = (unsigned long) &prolific_info, @@ -119,6 +128,15 @@ static const struct usb_device_id products [] = { .driver_info = (unsigned long) &prolific_info, }, +/* high speed cables */ +{ + USB_DEVICE(0x067b, 0x25a1), /* PL-25A1, no eeprom */ + .driver_info = (unsigned long) &prolific_info, +}, { + USB_DEVICE(0x050d, 0x258a), /* Belkin F5U258/F5U279 (PL-25A1) */ + .driver_info = (unsigned long) &prolific_info, +}, + { }, // END }; MODULE_DEVICE_TABLE(usb, products); @@ -145,5 +163,5 @@ static void __exit plusb_exit(void) module_exit(plusb_exit); MODULE_AUTHOR("David Brownell"); -MODULE_DESCRIPTION("Prolific PL-2301/2302 USB Host to Host Link Driver"); +MODULE_DESCRIPTION("Prolific PL-2301/2302/25A1 USB Host to Host Link Driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3-58-ga151 From 5325e92f33eef5fb54e2e63185d965b4be59a4b3 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 6 Apr 2011 21:40:15 +0000 Subject: usb: plusb: Add debug to reset function This patch adds some debug to the reset function to print out the reason why it fails. Signed-off-by: Simon Wood Signed-off-by: David S. Miller --- drivers/net/usb/plusb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c index f46aa07bfa69..217aec8a768f 100644 --- a/drivers/net/usb/plusb.c +++ b/drivers/net/usb/plusb.c @@ -94,11 +94,15 @@ pl_set_QuickLink_features(struct usbnet *dev, int val) static int pl_reset(struct usbnet *dev) { + int status; + /* some units seem to need this reset, others reject it utterly. * FIXME be more like "naplink" or windows drivers. */ - (void) pl_set_QuickLink_features(dev, + status = pl_set_QuickLink_features(dev, PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E); + if (status != 0 && netif_msg_probe(dev)) + netif_dbg(dev, link, dev->net, "pl_reset --> %d\n", status); return 0; } -- cgit v1.2.3-58-ga151 From 5c04c819a20af40adb7d282199f4e34e14fa05c5 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Thu, 7 Apr 2011 04:51:50 +0000 Subject: fib_validate_source(): pass sk_buff instead of mark This makes sk_buff available for other use in fib_validate_source(). Signed-off-by: Michael Smith Signed-off-by: David S. Miller --- include/net/ip_fib.h | 6 +++--- net/ipv4/fib_frontend.c | 10 ++++------ net/ipv4/route.c | 16 ++++++++-------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index e5d66ec88cf6..514627f56339 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -227,9 +227,9 @@ extern struct fib_table *fib_get_table(struct net *net, u32 id); /* Exported by fib_frontend.c */ extern const struct nla_policy rtm_ipv4_policy[]; extern void ip_fib_init(void); -extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, - struct net_device *dev, __be32 *spec_dst, - u32 *itag, u32 mark); +extern int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, + u8 tos, int oif, struct net_device *dev, + __be32 *spec_dst, u32 *itag); extern void fib_select_default(struct fib_result *res); /* Exported by fib_semantics.c */ diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 451088330bbb..f162f84b8d6d 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -188,9 +188,9 @@ EXPORT_SYMBOL(inet_dev_addr_type); * - check, that packet arrived from expected physical interface. * called with rcu_read_lock() */ -int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, - struct net_device *dev, __be32 *spec_dst, - u32 *itag, u32 mark) +int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, u8 tos, + int oif, struct net_device *dev, __be32 *spec_dst, + u32 *itag) { struct in_device *in_dev; struct flowi4 fl4; @@ -202,7 +202,6 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, fl4.flowi4_oif = 0; fl4.flowi4_iif = oif; - fl4.flowi4_mark = mark; fl4.daddr = src; fl4.saddr = dst; fl4.flowi4_tos = tos; @@ -214,8 +213,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, no_addr = in_dev->ifa_list == NULL; rpf = IN_DEV_RPFILTER(in_dev); accept_local = IN_DEV_ACCEPT_LOCAL(in_dev); - if (mark && !IN_DEV_SRC_VMARK(in_dev)) - fl4.flowi4_mark = 0; + fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0; } if (in_dev == NULL) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 1628be530314..052c9123e576 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1871,8 +1871,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, goto e_inval; spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); } else { - err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, - &itag, 0); + err = fib_validate_source(skb, saddr, 0, tos, 0, dev, &spec_dst, + &itag); if (err < 0) goto e_err; } @@ -1981,8 +1981,8 @@ static int __mkroute_input(struct sk_buff *skb, } - err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res), - in_dev->dev, &spec_dst, &itag, skb->mark); + err = fib_validate_source(skb, saddr, daddr, tos, FIB_RES_OIF(*res), + in_dev->dev, &spec_dst, &itag); if (err < 0) { ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, saddr); @@ -2150,9 +2150,9 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, goto brd_input; if (res.type == RTN_LOCAL) { - err = fib_validate_source(saddr, daddr, tos, + err = fib_validate_source(skb, saddr, daddr, tos, net->loopback_dev->ifindex, - dev, &spec_dst, &itag, skb->mark); + dev, &spec_dst, &itag); if (err < 0) goto martian_source_keep_err; if (err) @@ -2176,8 +2176,8 @@ brd_input: if (ipv4_is_zeronet(saddr)) spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); else { - err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, - &itag, skb->mark); + err = fib_validate_source(skb, saddr, 0, tos, 0, dev, &spec_dst, + &itag); if (err < 0) goto martian_source_keep_err; if (err) -- cgit v1.2.3-58-ga151 From 990078afbf90e0175e71da2df04595b99153514c Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Thu, 7 Apr 2011 04:51:51 +0000 Subject: Disable rp_filter for IPsec packets The reverse path filter interferes with IPsec subnet-to-subnet tunnels, especially when the link to the IPsec peer is on an interface other than the one hosting the default route. With dynamic routing, where the peer might be reachable through eth0 today and eth1 tomorrow, it's difficult to keep rp_filter enabled unless fake routes to the remote subnets are configured on the interface currently used to reach the peer. IPsec provides a much stronger anti-spoofing policy than rp_filter, so this patch disables the rp_filter for packets with a security path. Signed-off-by: Michael Smith Signed-off-by: David S. Miller --- include/net/xfrm.h | 9 +++++++++ net/ipv4/fib_frontend.c | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 6ae4bc5ce8a7..65ea31348631 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -957,6 +957,15 @@ struct sec_path { struct xfrm_state *xvec[XFRM_MAX_DEPTH]; }; +static inline int secpath_exists(struct sk_buff *skb) +{ +#ifdef CONFIG_XFRM + return skb->sp != NULL; +#else + return 0; +#endif +} + static inline struct sec_path * secpath_get(struct sec_path *sp) { diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index f162f84b8d6d..22524716fe70 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -44,6 +44,7 @@ #include #include #include +#include #ifndef CONFIG_IP_MULTIPLE_TABLES @@ -211,7 +212,10 @@ int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, u8 tos, in_dev = __in_dev_get_rcu(dev); if (in_dev) { no_addr = in_dev->ifa_list == NULL; - rpf = IN_DEV_RPFILTER(in_dev); + + /* Ignore rp_filter for packets protected by IPsec. */ + rpf = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(in_dev); + accept_local = IN_DEV_ACCEPT_LOCAL(in_dev); fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0; } -- cgit v1.2.3-58-ga151 From 4e01d2d1cac683477b539b40b7b4662d6a9c436f Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 8 Apr 2011 02:38:46 +0000 Subject: net: Remove invalid offloads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove offload changing ethtool ops which drivers don't really support: - fs_enet - ucc_geth Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/fs_enet/fs_enet-main.c | 2 -- drivers/net/ucc_geth_ethtool.c | 1 - 2 files changed, 3 deletions(-) diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 24cb953900dd..a9388944f1d3 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -956,8 +956,6 @@ static const struct ethtool_ops fs_ethtool_ops = { .get_link = ethtool_op_get_link, .get_msglevel = fs_get_msglevel, .set_msglevel = fs_set_msglevel, - .set_tx_csum = ethtool_op_set_tx_csum, /* local! */ - .set_sg = ethtool_op_set_sg, .get_regs = fs_get_regs, }; diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c index 6f92e48f02d3..537fbc0a4401 100644 --- a/drivers/net/ucc_geth_ethtool.c +++ b/drivers/net/ucc_geth_ethtool.c @@ -410,7 +410,6 @@ static const struct ethtool_ops uec_ethtool_ops = { .set_ringparam = uec_set_ringparam, .get_pauseparam = uec_get_pauseparam, .set_pauseparam = uec_set_pauseparam, - .set_sg = ethtool_op_set_sg, .get_sset_count = uec_get_sset_count, .get_strings = uec_get_strings, .get_ethtool_stats = uec_get_ethtool_stats, -- cgit v1.2.3-58-ga151 From 8b8ddc68df13032a5666438b48dfb7a86de3a610 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 8 Apr 2011 02:38:47 +0000 Subject: net: benet: convert to hw_features - fixup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix up after merge with NETIF_F_RXHASH implementation. This allows to toggle NETIF_F_RXHASH and NETIF_F_HW_VLAN_TX. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 58a652f81862..289c73aa6875 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2629,14 +2629,13 @@ static void be_netdev_init(struct net_device *netdev) int i; netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | - NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | + NETIF_F_HW_VLAN_TX; + if (be_multi_rxq(adapter)) + netdev->hw_features |= NETIF_F_RXHASH; netdev->features |= netdev->hw_features | - NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX | - NETIF_F_HW_VLAN_FILTER; - - if (be_multi_rxq(adapter)) - netdev->features |= NETIF_F_RXHASH; + NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; -- cgit v1.2.3-58-ga151 From 350fb32ae45ec74ea9cc117c728c48b8e840f0f9 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 8 Apr 2011 06:35:56 +0000 Subject: net: r8169: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simple conversion with a bit of needed cleanup. This also fixes: - confusion around vlan_features in rtl8169_vlan_mode(), - problem with broken TSO for too big MTU (the limit is set at 0xFFF --- max MSS field value). SG+IP_CSUM+TSO is left disabled by default, based on suggestion by David Dillow. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/r8169.c | 95 +++++++++++++++++++---------------------------------- 1 file changed, 33 insertions(+), 62 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index caa99cdb5818..058524f3eb49 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1286,14 +1286,15 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) return ret; } -static u32 rtl8169_get_rx_csum(struct net_device *dev) +static u32 rtl8169_fix_features(struct net_device *dev, u32 features) { - struct rtl8169_private *tp = netdev_priv(dev); + if (dev->mtu > MSSMask) + features &= ~NETIF_F_ALL_TSO; - return tp->cp_cmd & RxChkSum; + return features; } -static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) +static int rtl8169_set_features(struct net_device *dev, u32 features) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; @@ -1301,11 +1302,16 @@ static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) spin_lock_irqsave(&tp->lock, flags); - if (data) + if (features & NETIF_F_RXCSUM) tp->cp_cmd |= RxChkSum; else tp->cp_cmd &= ~RxChkSum; + if (dev->features & NETIF_F_HW_VLAN_RX) + tp->cp_cmd |= RxVlan; + else + tp->cp_cmd &= ~RxVlan; + RTL_W16(CPlusCmd, tp->cp_cmd); RTL_R16(CPlusCmd); @@ -1321,27 +1327,6 @@ static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; } -#define NETIF_F_HW_VLAN_TX_RX (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX) - -static void rtl8169_vlan_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (dev->features & NETIF_F_HW_VLAN_RX) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(CPlusCmd, tp->cp_cmd); - /* PCI commit */ - RTL_R16(CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); - - dev->vlan_features = dev->features &~ NETIF_F_HW_VLAN_TX_RX; -} - static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb) { u32 opts2 = le32_to_cpu(desc->opts2); @@ -1522,28 +1507,6 @@ static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) } } -static int rtl8169_set_flags(struct net_device *dev, u32 data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long old_feat = dev->features; - int rc; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_05) && - !(data & ETH_FLAG_RXVLAN)) { - netif_info(tp, drv, dev, "8110SCd requires hardware Rx VLAN\n"); - return -EINVAL; - } - - rc = ethtool_op_set_flags(dev, data, ETH_FLAG_TXVLAN | ETH_FLAG_RXVLAN); - if (rc) - return rc; - - if ((old_feat ^ dev->features) & NETIF_F_HW_VLAN_RX) - rtl8169_vlan_mode(dev); - - return 0; -} - static const struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, .get_regs_len = rtl8169_get_regs_len, @@ -1552,19 +1515,12 @@ static const struct ethtool_ops rtl8169_ethtool_ops = { .set_settings = rtl8169_set_settings, .get_msglevel = rtl8169_get_msglevel, .set_msglevel = rtl8169_set_msglevel, - .get_rx_csum = rtl8169_get_rx_csum, - .set_rx_csum = rtl8169_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, .get_regs = rtl8169_get_regs, .get_wol = rtl8169_get_wol, .set_wol = rtl8169_set_wol, .get_strings = rtl8169_get_strings, .get_sset_count = rtl8169_get_sset_count, .get_ethtool_stats = rtl8169_get_ethtool_stats, - .set_flags = rtl8169_set_flags, - .get_flags = ethtool_op_get_flags, }; static void rtl8169_get_mac_version(struct rtl8169_private *tp, @@ -2979,6 +2935,8 @@ static const struct net_device_ops rtl8169_netdev_ops = { .ndo_tx_timeout = rtl8169_tx_timeout, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = rtl8169_change_mtu, + .ndo_fix_features = rtl8169_fix_features, + .ndo_set_features = rtl8169_set_features, .ndo_set_mac_address = rtl_set_mac_address, .ndo_do_ioctl = rtl8169_ioctl, .ndo_set_multicast_list = rtl_set_rx_mode, @@ -3425,7 +3383,19 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - dev->features |= NETIF_F_HW_VLAN_TX_RX | NETIF_F_GRO; + /* don't enable SG, IP_CSUM and TSO by default - it might not work + * properly for all devices */ + dev->features |= NETIF_F_RXCSUM | + NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_HIGHDMA; + + if (tp->mac_version == RTL_GIGA_MAC_VER_05) + /* 8110SCd requires hardware Rx VLAN - disallow toggling */ + dev->hw_features &= ~NETIF_F_HW_VLAN_RX; tp->intr_mask = 0xffff; tp->hw_start = cfg->hw_start; @@ -3545,7 +3515,7 @@ static int rtl8169_open(struct net_device *dev) rtl8169_init_phy(dev, tp); - rtl8169_vlan_mode(dev); + rtl8169_set_features(dev, dev->features); rtl_pll_power_up(tp); @@ -4318,6 +4288,8 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) return -EINVAL; dev->mtu = new_mtu; + netdev_update_features(dev); + return 0; } @@ -4642,12 +4614,11 @@ err_out: static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) { - if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->gso_size; + u32 mss = skb_shinfo(skb)->gso_size; + + if (mss) + return LargeSend | ((mss & MSSMask) << MSSShift); - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - } if (skb->ip_summed == CHECKSUM_PARTIAL) { const struct iphdr *ip = ip_hdr(skb); -- cgit v1.2.3-58-ga151 From 044a890c5a0fb7ac60c70bbb4e1b79e59272e504 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sat, 9 Apr 2011 00:58:18 +0000 Subject: net: 8139cp: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/8139cp.c | 46 +++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index dd16e83933a2..10c45051caea 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -758,8 +758,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, entry = cp->tx_head; eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; - if (dev->features & NETIF_F_TSO) - mss = skb_shinfo(skb)->gso_size; + mss = skb_shinfo(skb)->gso_size; if (skb_shinfo(skb)->nr_frags == 0) { struct cp_desc *txd = &cp->tx_ring[entry]; @@ -1416,32 +1415,23 @@ static void cp_set_msglevel(struct net_device *dev, u32 value) cp->msg_enable = value; } -static u32 cp_get_rx_csum(struct net_device *dev) +static int cp_set_features(struct net_device *dev, u32 features) { struct cp_private *cp = netdev_priv(dev); - return (cpr16(CpCmd) & RxChkSum) ? 1 : 0; -} + unsigned long flags; -static int cp_set_rx_csum(struct net_device *dev, u32 data) -{ - struct cp_private *cp = netdev_priv(dev); - u16 cmd = cp->cpcmd, newcmd; + if (!((dev->features ^ features) & NETIF_F_RXCSUM)) + return 0; - newcmd = cmd; + spin_lock_irqsave(&cp->lock, flags); - if (data) - newcmd |= RxChkSum; + if (features & NETIF_F_RXCSUM) + cp->cpcmd |= RxChkSum; else - newcmd &= ~RxChkSum; - - if (newcmd != cmd) { - unsigned long flags; + cp->cpcmd &= ~RxChkSum; - spin_lock_irqsave(&cp->lock, flags); - cp->cpcmd = newcmd; - cpw16_f(CpCmd, newcmd); - spin_unlock_irqrestore(&cp->lock, flags); - } + cpw16_f(CpCmd, cp->cpcmd); + spin_unlock_irqrestore(&cp->lock, flags); return 0; } @@ -1554,11 +1544,6 @@ static const struct ethtool_ops cp_ethtool_ops = { .get_link = ethtool_op_get_link, .get_msglevel = cp_get_msglevel, .set_msglevel = cp_set_msglevel, - .get_rx_csum = cp_get_rx_csum, - .set_rx_csum = cp_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, /* local! */ - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, .get_regs = cp_get_regs, .get_wol = cp_get_wol, .set_wol = cp_set_wol, @@ -1831,6 +1816,7 @@ static const struct net_device_ops cp_netdev_ops = { .ndo_do_ioctl = cp_ioctl, .ndo_start_xmit = cp_start_xmit, .ndo_tx_timeout = cp_tx_timeout, + .ndo_set_features = cp_set_features, #if CP_VLAN_TAG_USED .ndo_vlan_rx_register = cp_vlan_rx_register, #endif @@ -1934,6 +1920,9 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) cp->cpcmd = (pci_using_dac ? PCIDAC : 0) | PCIMulRW | RxChkSum | CpRxOn | CpTxOn; + dev->features |= NETIF_F_RXCSUM; + dev->hw_features |= NETIF_F_RXCSUM; + regs = ioremap(pciaddr, CP_REGS_SIZE); if (!regs) { rc = -EIO; @@ -1966,9 +1955,8 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_using_dac) dev->features |= NETIF_F_HIGHDMA; -#if 0 /* disabled by default until verified */ - dev->features |= NETIF_F_TSO; -#endif + /* disabled by default until verified */ + dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; dev->irq = pdev->irq; -- cgit v1.2.3-58-ga151 From 5e982f3bfdd5d063f8806a26c87843496a35d26b Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sat, 9 Apr 2011 02:46:55 +0000 Subject: net: stmmac: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also removes TSO as it's made fully in software --- better to leave this to networking core. If the MAC features can be detected at probe time and not at open, then stmmac_fix_features could be simplified by limiting hw_features. That's also better for users as they don't see offloads being togglable but never turned on. Redundant fallbacks for TX csum are removed as it's already handled by network core. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/stmmac/stmmac_ethtool.c | 14 ------- drivers/net/stmmac/stmmac_main.c | 83 ++++++++++--------------------------- 2 files changed, 23 insertions(+), 74 deletions(-) diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c index fd719edc7f7c..156a805c6c23 100644 --- a/drivers/net/stmmac/stmmac_ethtool.c +++ b/drivers/net/stmmac/stmmac_ethtool.c @@ -197,13 +197,6 @@ static void stmmac_ethtool_gregs(struct net_device *dev, } } -static u32 stmmac_ethtool_get_rx_csum(struct net_device *dev) -{ - struct stmmac_priv *priv = netdev_priv(dev); - - return priv->rx_coe; -} - static void stmmac_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) @@ -358,11 +351,6 @@ static struct ethtool_ops stmmac_ethtool_ops = { .get_regs = stmmac_ethtool_gregs, .get_regs_len = stmmac_ethtool_get_regs_len, .get_link = ethtool_op_get_link, - .get_rx_csum = stmmac_ethtool_get_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_ipv6_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, .get_pauseparam = stmmac_get_pauseparam, .set_pauseparam = stmmac_set_pauseparam, .get_ethtool_stats = stmmac_get_ethtool_stats, @@ -370,8 +358,6 @@ static struct ethtool_ops stmmac_ethtool_ops = { .get_wol = stmmac_get_wol, .set_wol = stmmac_set_wol, .get_sset_count = stmmac_get_sset_count, - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, }; void stmmac_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 0e5f03135b50..62fa51ed93ff 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -139,7 +139,6 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFDOWN | NETIF_MSG_TIMER); static irqreturn_t stmmac_interrupt(int irq, void *dev_id); -static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev); /** * stmmac_verify_args - verify the driver parameters. @@ -843,6 +842,7 @@ static int stmmac_open(struct net_device *dev) pr_info("stmmac: Rx Checksum Offload Engine supported\n"); if (priv->plat->tx_coe) pr_info("\tTX Checksum insertion supported\n"); + netdev_update_features(dev); /* Initialise the MMC (if present) to disable all interrupts. */ writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK); @@ -927,46 +927,6 @@ static int stmmac_release(struct net_device *dev) return 0; } -/* - * To perform emulated hardware segmentation on skb. - */ -static int stmmac_sw_tso(struct stmmac_priv *priv, struct sk_buff *skb) -{ - struct sk_buff *segs, *curr_skb; - int gso_segs = skb_shinfo(skb)->gso_segs; - - /* Estimate the number of fragments in the worst case */ - if (unlikely(stmmac_tx_avail(priv) < gso_segs)) { - netif_stop_queue(priv->dev); - TX_DBG(KERN_ERR "%s: TSO BUG! Tx Ring full when queue awake\n", - __func__); - if (stmmac_tx_avail(priv) < gso_segs) - return NETDEV_TX_BUSY; - - netif_wake_queue(priv->dev); - } - TX_DBG("\tstmmac_sw_tso: segmenting: skb %p (len %d)\n", - skb, skb->len); - - segs = skb_gso_segment(skb, priv->dev->features & ~NETIF_F_TSO); - if (IS_ERR(segs)) - goto sw_tso_end; - - do { - curr_skb = segs; - segs = segs->next; - TX_DBG("\t\tcurrent skb->len: %d, *curr %p," - "*next %p\n", curr_skb->len, curr_skb, segs); - curr_skb->next = NULL; - stmmac_xmit(curr_skb, priv->dev); - } while (segs); - -sw_tso_end: - dev_kfree_skb(skb); - - return NETDEV_TX_OK; -} - static unsigned int stmmac_handle_jumbo_frames(struct sk_buff *skb, struct net_device *dev, int csum_insertion) @@ -1044,16 +1004,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) !skb_is_gso(skb) ? "isn't" : "is"); #endif - if (unlikely(skb_is_gso(skb))) - return stmmac_sw_tso(priv, skb); - - if (likely((skb->ip_summed == CHECKSUM_PARTIAL))) { - if (unlikely((!priv->plat->tx_coe) || - (priv->no_csum_insertion))) - skb_checksum_help(skb); - else - csum_insertion = 1; - } + csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL); desc = priv->dma_tx + entry; first = desc; @@ -1373,18 +1324,29 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu) return -EINVAL; } + dev->mtu = new_mtu; + netdev_update_features(dev); + + return 0; +} + +static u32 stmmac_fix_features(struct net_device *dev, u32 features) +{ + struct stmmac_priv *priv = netdev_priv(dev); + + if (!priv->rx_coe) + features &= ~NETIF_F_RXCSUM; + if (!priv->plat->tx_coe) + features &= ~NETIF_F_ALL_CSUM; + /* Some GMAC devices have a bugged Jumbo frame support that * needs to have the Tx COE disabled for oversized frames * (due to limited buffer sizes). In this case we disable * the TX csum insertionin the TDES and not use SF. */ - if ((priv->plat->bugged_jumbo) && (priv->dev->mtu > ETH_DATA_LEN)) - priv->no_csum_insertion = 1; - else - priv->no_csum_insertion = 0; + if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN)) + features &= ~NETIF_F_ALL_CSUM; - dev->mtu = new_mtu; - - return 0; + return features; } static irqreturn_t stmmac_interrupt(int irq, void *dev_id) @@ -1464,6 +1426,7 @@ static const struct net_device_ops stmmac_netdev_ops = { .ndo_start_xmit = stmmac_xmit, .ndo_stop = stmmac_release, .ndo_change_mtu = stmmac_change_mtu, + .ndo_fix_features = stmmac_fix_features, .ndo_set_multicast_list = stmmac_multicast_list, .ndo_tx_timeout = stmmac_tx_timeout, .ndo_do_ioctl = stmmac_ioctl, @@ -1494,8 +1457,8 @@ static int stmmac_probe(struct net_device *dev) dev->netdev_ops = &stmmac_netdev_ops; stmmac_set_ethtool_ops(dev); - dev->features |= NETIF_F_SG | NETIF_F_HIGHDMA | - NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + dev->features |= dev->hw_features | NETIF_F_HIGHDMA; dev->watchdog_timeo = msecs_to_jiffies(watchdog); #ifdef STMMAC_VLAN_TAG_USED /* Both mac100 and gmac support receive VLAN tag detection */ -- cgit v1.2.3-58-ga151 From e6a46416d4233c99a041ca35c1f692ecae9f942d Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 10 Apr 2011 03:13:21 +0000 Subject: net: ksz884x: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also fixes possible race when changing receive checksum state and removes IPV6_CSUM_GEN_HACK as it's always set. BTW, The claim about fake IPV6 checksum looks dubious. If that were true, then there's a problem in networking core and should be fixed there and not in random drivers. BTW#2, there's no MAINTAINERS entry for this driver. I assume this driver is supported by Micrel? Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/ksz884x.c | 73 +++++++++++++++------------------------------------ 1 file changed, 21 insertions(+), 52 deletions(-) diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c index 7f7d5708a658..2c37a3804303 100644 --- a/drivers/net/ksz884x.c +++ b/drivers/net/ksz884x.c @@ -1221,7 +1221,6 @@ struct ksz_port_info { #define LINK_INT_WORKING (1 << 0) #define SMALL_PACKET_TX_BUG (1 << 1) #define HALF_DUPLEX_SIGNAL_BUG (1 << 2) -#define IPV6_CSUM_GEN_HACK (1 << 3) #define RX_HUGE_FRAME (1 << 4) #define STP_SUPPORT (1 << 8) @@ -3748,7 +3747,6 @@ static int hw_init(struct ksz_hw *hw) if (1 == rc) hw->features |= HALF_DUPLEX_SIGNAL_BUG; } - hw->features |= IPV6_CSUM_GEN_HACK; return rc; } @@ -4887,8 +4885,7 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev) left = hw_alloc_pkt(hw, skb->len, num); if (left) { if (left < num || - ((hw->features & IPV6_CSUM_GEN_HACK) && - (CHECKSUM_PARTIAL == skb->ip_summed) && + ((CHECKSUM_PARTIAL == skb->ip_summed) && (ETH_P_IPV6 == htons(skb->protocol)))) { struct sk_buff *org_skb = skb; @@ -6583,57 +6580,33 @@ static void netdev_get_ethtool_stats(struct net_device *dev, } /** - * netdev_get_rx_csum - get receive checksum support + * netdev_set_features - set receive checksum support * @dev: Network device. - * - * This function gets receive checksum support setting. - * - * Return true if receive checksum is enabled; false otherwise. - */ -static u32 netdev_get_rx_csum(struct net_device *dev) -{ - struct dev_priv *priv = netdev_priv(dev); - struct dev_info *hw_priv = priv->adapter; - struct ksz_hw *hw = &hw_priv->hw; - - return hw->rx_cfg & - (DMA_RX_CSUM_UDP | - DMA_RX_CSUM_TCP | - DMA_RX_CSUM_IP); -} - -/** - * netdev_set_rx_csum - set receive checksum support - * @dev: Network device. - * @data: Zero to disable receive checksum support. + * @features: New device features (offloads). * * This function sets receive checksum support setting. * * Return 0 if successful; otherwise an error code. */ -static int netdev_set_rx_csum(struct net_device *dev, u32 data) +static int netdev_set_features(struct net_device *dev, u32 features) { struct dev_priv *priv = netdev_priv(dev); struct dev_info *hw_priv = priv->adapter; struct ksz_hw *hw = &hw_priv->hw; - u32 new_setting = hw->rx_cfg; - if (data) - new_setting |= - (DMA_RX_CSUM_UDP | DMA_RX_CSUM_TCP | - DMA_RX_CSUM_IP); - else - new_setting &= - ~(DMA_RX_CSUM_UDP | DMA_RX_CSUM_TCP | - DMA_RX_CSUM_IP); - new_setting &= ~DMA_RX_CSUM_UDP; mutex_lock(&hw_priv->lock); - if (new_setting != hw->rx_cfg) { - hw->rx_cfg = new_setting; - if (hw->enabled) - writel(hw->rx_cfg, hw->io + KS_DMA_RX_CTRL); - } + + /* see note in hw_setup() */ + if (features & NETIF_F_RXCSUM) + hw->rx_cfg |= DMA_RX_CSUM_TCP | DMA_RX_CSUM_IP; + else + hw->rx_cfg &= ~(DMA_RX_CSUM_TCP | DMA_RX_CSUM_IP); + + if (hw->enabled) + writel(hw->rx_cfg, hw->io + KS_DMA_RX_CTRL); + mutex_unlock(&hw_priv->lock); + return 0; } @@ -6658,12 +6631,6 @@ static struct ethtool_ops netdev_ethtool_ops = { .get_strings = netdev_get_strings, .get_sset_count = netdev_get_sset_count, .get_ethtool_stats = netdev_get_ethtool_stats, - .get_rx_csum = netdev_get_rx_csum, - .set_rx_csum = netdev_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, }; /* @@ -6828,14 +6795,15 @@ static int __init netdev_init(struct net_device *dev) /* 500 ms timeout */ dev->watchdog_timeo = HZ / 2; - dev->features |= NETIF_F_IP_CSUM; + dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_RXCSUM; /* * Hardware does not really support IPv6 checksum generation, but - * driver actually runs faster with this on. Refer IPV6_CSUM_GEN_HACK. + * driver actually runs faster with this on. */ - dev->features |= NETIF_F_IPV6_CSUM; - dev->features |= NETIF_F_SG; + dev->hw_features |= NETIF_F_IPV6_CSUM; + + dev->features |= dev->hw_features; sema_init(&priv->proc_sem, 1); @@ -6860,6 +6828,7 @@ static const struct net_device_ops netdev_ops = { .ndo_start_xmit = netdev_tx, .ndo_tx_timeout = netdev_tx_timeout, .ndo_change_mtu = netdev_change_mtu, + .ndo_set_features = netdev_set_features, .ndo_set_mac_address = netdev_set_mac_address, .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = netdev_ioctl, -- cgit v1.2.3-58-ga151 From f593fe363268e7354b3a7f3907170de1ac4de7e7 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 10 Apr 2011 03:13:21 +0000 Subject: net: via-velocity: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trivial conversion. This also enables toggling TX VLAN offload and fixes TX checksumming race with offload changes. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/via-velocity.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 0d6fec6b7d93..77315ad1e7e2 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -2600,8 +2600,7 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb, /* * Handle hardware checksum */ - if ((dev->features & NETIF_F_IP_CSUM) && - (skb->ip_summed == CHECKSUM_PARTIAL)) { + if (skb->ip_summed == CHECKSUM_PARTIAL) { const struct iphdr *ip = ip_hdr(skb); if (ip->protocol == IPPROTO_TCP) td_ptr->tdesc1.TCR |= TCR0_TCPCK; @@ -2841,6 +2840,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi dev->ethtool_ops = &velocity_ethtool_ops; netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT); + dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_HW_VLAN_TX; dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM; @@ -3457,13 +3457,10 @@ static const struct ethtool_ops velocity_ethtool_ops = { .get_settings = velocity_get_settings, .set_settings = velocity_set_settings, .get_drvinfo = velocity_get_drvinfo, - .set_tx_csum = ethtool_op_set_tx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, .get_wol = velocity_ethtool_get_wol, .set_wol = velocity_ethtool_set_wol, .get_msglevel = velocity_get_msglevel, .set_msglevel = velocity_set_msglevel, - .set_sg = ethtool_op_set_sg, .get_link = velocity_get_link, .get_coalesce = velocity_get_coalesce, .set_coalesce = velocity_set_coalesce, -- cgit v1.2.3-58-ga151 From 8d7dfc2b57bb2cad0731dedd58ec1d70bcca1ccf Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 10 Apr 2011 04:47:46 +0000 Subject: net: bnx2: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 109 ++++++++++++++--------------------------------------- drivers/net/bnx2.h | 2 - 2 files changed, 28 insertions(+), 83 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 05ddfb18d5bf..0a52079bafef 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3174,7 +3174,7 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) } skb_checksum_none_assert(skb); - if (bp->rx_csum && + if ((bp->dev->features & NETIF_F_RXCSUM) && (status & (L2_FHDR_STATUS_TCP_SEGMENT | L2_FHDR_STATUS_UDP_DATAGRAM))) { @@ -7189,38 +7189,6 @@ bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) return 0; } -static u32 -bnx2_get_rx_csum(struct net_device *dev) -{ - struct bnx2 *bp = netdev_priv(dev); - - return bp->rx_csum; -} - -static int -bnx2_set_rx_csum(struct net_device *dev, u32 data) -{ - struct bnx2 *bp = netdev_priv(dev); - - bp->rx_csum = data; - return 0; -} - -static int -bnx2_set_tso(struct net_device *dev, u32 data) -{ - struct bnx2 *bp = netdev_priv(dev); - - if (data) { - dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN; - if (CHIP_NUM(bp) == CHIP_NUM_5709) - dev->features |= NETIF_F_TSO6; - } else - dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6 | - NETIF_F_TSO_ECN); - return 0; -} - static struct { char string[ETH_GSTRING_LEN]; } bnx2_stats_str_arr[] = { @@ -7532,43 +7500,37 @@ bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state) return 0; } -static int -bnx2_set_tx_csum(struct net_device *dev, u32 data) +static u32 +bnx2_fix_features(struct net_device *dev, u32 features) { struct bnx2 *bp = netdev_priv(dev); - if (CHIP_NUM(bp) == CHIP_NUM_5709) - return ethtool_op_set_tx_ipv6_csum(dev, data); - else - return ethtool_op_set_tx_csum(dev, data); + if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)) + features |= NETIF_F_HW_VLAN_RX; + + return features; } static int -bnx2_set_flags(struct net_device *dev, u32 data) +bnx2_set_features(struct net_device *dev, u32 features) { struct bnx2 *bp = netdev_priv(dev); - int rc; - - if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN) && - !(data & ETH_FLAG_RXVLAN)) - return -EINVAL; /* TSO with VLAN tag won't work with current firmware */ - if (!(data & ETH_FLAG_TXVLAN)) - return -EINVAL; - - rc = ethtool_op_set_flags(dev, data, ETH_FLAG_RXHASH | ETH_FLAG_RXVLAN | - ETH_FLAG_TXVLAN); - if (rc) - return rc; + if (features & NETIF_F_HW_VLAN_TX) + dev->vlan_features |= (dev->hw_features & NETIF_F_ALL_TSO); + else + dev->vlan_features &= ~NETIF_F_ALL_TSO; - if ((!!(data & ETH_FLAG_RXVLAN) != + if ((!!(features & NETIF_F_HW_VLAN_RX) != !!(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) && netif_running(dev)) { bnx2_netif_stop(bp, false); + dev->features = features; bnx2_set_rx_mode(dev); bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1); bnx2_netif_start(bp, false); + return 1; } return 0; @@ -7593,18 +7555,11 @@ static const struct ethtool_ops bnx2_ethtool_ops = { .set_ringparam = bnx2_set_ringparam, .get_pauseparam = bnx2_get_pauseparam, .set_pauseparam = bnx2_set_pauseparam, - .get_rx_csum = bnx2_get_rx_csum, - .set_rx_csum = bnx2_set_rx_csum, - .set_tx_csum = bnx2_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = bnx2_set_tso, .self_test = bnx2_self_test, .get_strings = bnx2_get_strings, .set_phys_id = bnx2_set_phys_id, .get_ethtool_stats = bnx2_get_ethtool_stats, .get_sset_count = bnx2_get_sset_count, - .set_flags = bnx2_set_flags, - .get_flags = ethtool_op_get_flags, }; /* Called with rtnl_lock */ @@ -8116,8 +8071,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->tx_ring_size = MAX_TX_DESC_CNT; bnx2_set_rx_ring_size(bp, 255); - bp->rx_csum = 1; - bp->tx_quick_cons_trip_int = 2; bp->tx_quick_cons_trip = 20; bp->tx_ticks_int = 18; @@ -8309,17 +8262,14 @@ static const struct net_device_ops bnx2_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = bnx2_change_mac_addr, .ndo_change_mtu = bnx2_change_mtu, + .ndo_fix_features = bnx2_fix_features, + .ndo_set_features = bnx2_set_features, .ndo_tx_timeout = bnx2_tx_timeout, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = poll_bnx2, #endif }; -static inline void vlan_features_add(struct net_device *dev, u32 flags) -{ - dev->vlan_features |= flags; -} - static int __devinit bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -8359,20 +8309,17 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) memcpy(dev->dev_addr, bp->mac_addr, 6); memcpy(dev->perm_addr, bp->mac_addr, 6); - dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_GRO | - NETIF_F_RXHASH; - vlan_features_add(dev, NETIF_F_IP_CSUM | NETIF_F_SG); - if (CHIP_NUM(bp) == CHIP_NUM_5709) { - dev->features |= NETIF_F_IPV6_CSUM; - vlan_features_add(dev, NETIF_F_IPV6_CSUM); - } - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN; - vlan_features_add(dev, NETIF_F_TSO | NETIF_F_TSO_ECN); - if (CHIP_NUM(bp) == CHIP_NUM_5709) { - dev->features |= NETIF_F_TSO6; - vlan_features_add(dev, NETIF_F_TSO6); - } + dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | + NETIF_F_TSO | NETIF_F_TSO_ECN | + NETIF_F_RXHASH | NETIF_F_RXCSUM; + + if (CHIP_NUM(bp) == CHIP_NUM_5709) + dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; + + dev->vlan_features = dev->hw_features; + dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->features |= dev->hw_features; + if ((rc = register_netdev(dev))) { dev_err(&pdev->dev, "Cannot register net device\n"); goto error; diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 91e83562238e..bf371f6fe154 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6754,8 +6754,6 @@ struct bnx2 { u32 rx_max_ring_idx; u32 rx_max_pg_ring_idx; - u32 rx_csum; - /* TX constants */ int tx_ring_size; u32 tx_wake_thresh; -- cgit v1.2.3-58-ga151 From 5d9f11cf5038587cc53975deb8beaa1a876a7a7b Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 8 Apr 2011 12:07:22 +0000 Subject: ethtool: prevent null pointer dereference with NTUPLE set but no set_rx_ntuple This change is meant to prevent a possible null pointer dereference if NETIF_F_NTUPLE is defined but the set_rx_ntuple function pointer is not. The main motivation behind this patch is to eventually replace the ntuple interfaces entirely with the network flow classifier interfaces. This allows the device drivers to maintain the ntuple check internally while using the network flow classifier interface for setting up and displaying rules. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/core/ethtool.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 1b7fa984de7d..704e176ad3a9 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -910,6 +910,9 @@ static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev, struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL; int ret; + if (!ops->set_rx_ntuple) + return -EOPNOTSUPP; + if (!(dev->features & NETIF_F_NTUPLE)) return -EINVAL; -- cgit v1.2.3-58-ga151 From 127fe533ae56d7f4e7b5011869870982eba25723 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 8 Apr 2011 18:01:59 +0000 Subject: v3 ethtool: add ntuple flow specifier data to network flow classifier This change is meant to add an ntuple data extensions to the rx network flow classification specifiers. The idea is to allow ntuple to be displayed via the network flow classification interface. The first patch had some left over stuff from the original flow extension flags I had added. That bit is removed in this patch. The second had some left over comments that stated we ignored bits in the masks when we actually match them. This work is based on input from Ben Hutchings. Signed-off-by: Alexander Duyck Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- include/linux/ethtool.h | 53 +++++++++++++++++++++++++++++-------------------- net/socket.c | 14 ++++++------- 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index c04d1316d221..c7eff13d2f34 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -380,27 +380,42 @@ struct ethtool_usrip4_spec { __u8 proto; }; +union ethtool_flow_union { + struct ethtool_tcpip4_spec tcp_ip4_spec; + struct ethtool_tcpip4_spec udp_ip4_spec; + struct ethtool_tcpip4_spec sctp_ip4_spec; + struct ethtool_ah_espip4_spec ah_ip4_spec; + struct ethtool_ah_espip4_spec esp_ip4_spec; + struct ethtool_usrip4_spec usr_ip4_spec; + struct ethhdr ether_spec; + __u8 hdata[60]; +}; + +struct ethtool_flow_ext { + __be16 vlan_etype; + __be16 vlan_tci; + __be32 data[2]; +}; + /** * struct ethtool_rx_flow_spec - specification for RX flow filter * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW * @h_u: Flow fields to match (dependent on @flow_type) - * @m_u: Masks for flow field bits to be ignored + * @h_ext: Additional fields to match + * @m_u: Masks for flow field bits to be matched + * @m_ext: Masks for additional field bits to be matched + * Note, all additional fields must be ignored unless @flow_type + * includes the %FLOW_EXT flag. * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC * if packets should be discarded * @location: Index of filter in hardware table */ struct ethtool_rx_flow_spec { __u32 flow_type; - union { - struct ethtool_tcpip4_spec tcp_ip4_spec; - struct ethtool_tcpip4_spec udp_ip4_spec; - struct ethtool_tcpip4_spec sctp_ip4_spec; - struct ethtool_ah_espip4_spec ah_ip4_spec; - struct ethtool_ah_espip4_spec esp_ip4_spec; - struct ethtool_usrip4_spec usr_ip4_spec; - struct ethhdr ether_spec; - __u8 hdata[72]; - } h_u, m_u; + union ethtool_flow_union h_u; + struct ethtool_flow_ext h_ext; + union ethtool_flow_union m_u; + struct ethtool_flow_ext m_ext; __u64 ring_cookie; __u32 location; }; @@ -458,16 +473,10 @@ struct ethtool_rxnfc { struct compat_ethtool_rx_flow_spec { u32 flow_type; - union { - struct ethtool_tcpip4_spec tcp_ip4_spec; - struct ethtool_tcpip4_spec udp_ip4_spec; - struct ethtool_tcpip4_spec sctp_ip4_spec; - struct ethtool_ah_espip4_spec ah_ip4_spec; - struct ethtool_ah_espip4_spec esp_ip4_spec; - struct ethtool_usrip4_spec usr_ip4_spec; - struct ethhdr ether_spec; - u8 hdata[72]; - } h_u, m_u; + union ethtool_flow_union h_u; + struct ethtool_flow_ext h_ext; + union ethtool_flow_union m_u; + struct ethtool_flow_ext m_ext; compat_u64 ring_cookie; u32 location; }; @@ -1072,6 +1081,8 @@ struct ethtool_ops { #define IPV4_FLOW 0x10 /* hash only */ #define IPV6_FLOW 0x11 /* hash only */ #define ETHER_FLOW 0x12 /* spec only (ether_spec) */ +/* Flag to enable additional fields in struct ethtool_rx_flow_spec */ +#define FLOW_EXT 0x80000000 /* L3-L4 network traffic flow hash options */ #define RXH_L2DA (1 << 1) diff --git a/net/socket.c b/net/socket.c index 5212447c86e7..575c84f2af19 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2643,13 +2643,13 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) return -EFAULT; if (convert_in) { - /* We expect there to be holes between fs.m_u and + /* We expect there to be holes between fs.m_ext and * fs.ring_cookie and at the end of fs, but nowhere else. */ - BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_u) + - sizeof(compat_rxnfc->fs.m_u) != - offsetof(struct ethtool_rxnfc, fs.m_u) + - sizeof(rxnfc->fs.m_u)); + BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) + + sizeof(compat_rxnfc->fs.m_ext) != + offsetof(struct ethtool_rxnfc, fs.m_ext) + + sizeof(rxnfc->fs.m_ext)); BUILD_BUG_ON( offsetof(struct compat_ethtool_rxnfc, fs.location) - offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != @@ -2657,7 +2657,7 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) offsetof(struct ethtool_rxnfc, fs.ring_cookie)); if (copy_in_user(rxnfc, compat_rxnfc, - (void *)(&rxnfc->fs.m_u + 1) - + (void *)(&rxnfc->fs.m_ext + 1) - (void *)rxnfc) || copy_in_user(&rxnfc->fs.ring_cookie, &compat_rxnfc->fs.ring_cookie, @@ -2674,7 +2674,7 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) if (convert_out) { if (copy_in_user(compat_rxnfc, rxnfc, - (const void *)(&rxnfc->fs.m_u + 1) - + (const void *)(&rxnfc->fs.m_ext + 1) - (const void *)rxnfc) || copy_in_user(&compat_rxnfc->fs.ring_cookie, &rxnfc->fs.ring_cookie, -- cgit v1.2.3-58-ga151 From 1b3291241a658fb4d4bbdb41483e1f53c26445ec Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 6 Apr 2011 13:47:50 +0000 Subject: qlge: use ethtool set_phys_id This is a stab at replacing old ethtool phys_id with set_phys_id on the Qlogic 10Gb driver. Compile tested only. Not sure if set_led_cfg will flash continuously, or needs to be replaced by ETHTOOL_ID_ON/ETHTOOL_ID_OFF Signed-off-by: Stephen Hemminger Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_ethtool.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index 8149cc9de4ca..687754da2a9f 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c @@ -412,31 +412,31 @@ static int ql_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) return 0; } -static int ql_phys_id(struct net_device *ndev, u32 data) +static int ql_set_phys_id(struct net_device *ndev, + enum ethtool_phys_id_state state) + { struct ql_adapter *qdev = netdev_priv(ndev); - u32 led_reg, i; - int status; - /* Save the current LED settings */ - status = ql_mb_get_led_cfg(qdev); - if (status) - return status; - led_reg = qdev->led_config; + switch (state) { + case ETHTOOL_ID_ACTIVE: + /* Save the current LED settings */ + if (ql_mb_get_led_cfg(qdev)) + return -EIO; - /* Start blinking the led */ - if (!data || data > 300) - data = 300; - - for (i = 0; i < (data * 10); i++) + /* Start blinking */ ql_mb_set_led_cfg(qdev, QL_LED_BLINK); + return 0; - /* Restore LED settings */ - status = ql_mb_set_led_cfg(qdev, led_reg); - if (status) - return status; + case ETHTOOL_ID_INACTIVE: + /* Restore LED settings */ + if (ql_mb_set_led_cfg(qdev, qdev->led_config)) + return -EIO; + return 0; - return 0; + default: + return -EINVAL; + } } static int ql_start_loopback(struct ql_adapter *qdev) @@ -703,7 +703,7 @@ const struct ethtool_ops qlge_ethtool_ops = { .get_msglevel = ql_get_msglevel, .set_msglevel = ql_set_msglevel, .get_link = ethtool_op_get_link, - .phys_id = ql_phys_id, + .set_phys_id = ql_set_phys_id, .self_test = ql_self_test, .get_pauseparam = ql_get_pauseparam, .set_pauseparam = ql_set_pauseparam, -- cgit v1.2.3-58-ga151 From bde3528f17aebb9c74d6b0ef81860868c91af049 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 8 Apr 2011 13:45:11 +0000 Subject: gianfar: Clean up implementation of RX network flow classification This code was cribbed from niu, so gfar_set_hash_opts() begins by converting the ethtool flow class code into a class code for Sun Neptune hardware, then does the same thing again for the hardware it's really dealing with. It may also return -1 (-EPERM) for some unhandled ethtool flow class codes. Remove the useless code and definitions, and fix the error code. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/gianfar.h | 17 -------------- drivers/net/gianfar_ethtool.c | 52 +------------------------------------------ 2 files changed, 1 insertion(+), 68 deletions(-) diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index ec5d595ce2e2..57ee3b009d75 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -382,23 +382,6 @@ extern const char gfar_driver_version[]; #define BD_LFLAG(flags) ((flags) << 16) #define BD_LENGTH_MASK 0x0000ffff -#define CLASS_CODE_UNRECOG 0x00 -#define CLASS_CODE_DUMMY1 0x01 -#define CLASS_CODE_ETHERTYPE1 0x02 -#define CLASS_CODE_ETHERTYPE2 0x03 -#define CLASS_CODE_USER_PROG1 0x04 -#define CLASS_CODE_USER_PROG2 0x05 -#define CLASS_CODE_USER_PROG3 0x06 -#define CLASS_CODE_USER_PROG4 0x07 -#define CLASS_CODE_TCP_IPV4 0x08 -#define CLASS_CODE_UDP_IPV4 0x09 -#define CLASS_CODE_AH_ESP_IPV4 0x0a -#define CLASS_CODE_SCTP_IPV4 0x0b -#define CLASS_CODE_TCP_IPV6 0x0c -#define CLASS_CODE_UDP_IPV6 0x0d -#define CLASS_CODE_AH_ESP_IPV6 0x0e -#define CLASS_CODE_SCTP_IPV6 0x0f - #define FPR_FILER_MASK 0xFFFFFFFF #define MAX_FILER_IDX 0xFF diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 3bc8e276ba4d..0840590958dd 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -645,42 +645,6 @@ static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) } #endif -static int gfar_ethflow_to_class(int flow_type, u64 *class) -{ - switch (flow_type) { - case TCP_V4_FLOW: - *class = CLASS_CODE_TCP_IPV4; - break; - case UDP_V4_FLOW: - *class = CLASS_CODE_UDP_IPV4; - break; - case AH_V4_FLOW: - case ESP_V4_FLOW: - *class = CLASS_CODE_AH_ESP_IPV4; - break; - case SCTP_V4_FLOW: - *class = CLASS_CODE_SCTP_IPV4; - break; - case TCP_V6_FLOW: - *class = CLASS_CODE_TCP_IPV6; - break; - case UDP_V6_FLOW: - *class = CLASS_CODE_UDP_IPV6; - break; - case AH_V6_FLOW: - case ESP_V6_FLOW: - *class = CLASS_CODE_AH_ESP_IPV6; - break; - case SCTP_V6_FLOW: - *class = CLASS_CODE_SCTP_IPV6; - break; - default: - return 0; - } - - return 1; -} - static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) { u32 fcr = 0x0, fpr = FPR_FILER_MASK; @@ -778,11 +742,6 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u case UDP_V6_FLOW: cmp_rqfpr = RQFPR_IPV6 |RQFPR_UDP; break; - case IPV4_FLOW: - cmp_rqfpr = RQFPR_IPV4; - case IPV6_FLOW: - cmp_rqfpr = RQFPR_IPV6; - break; default: printk(KERN_ERR "Right now this class is not supported\n"); return 0; @@ -848,18 +807,9 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u static int gfar_set_hash_opts(struct gfar_private *priv, struct ethtool_rxnfc *cmd) { - u64 class; - - if (!gfar_ethflow_to_class(cmd->flow_type, &class)) - return -EINVAL; - - if (class < CLASS_CODE_USER_PROG1 || - class > CLASS_CODE_SCTP_IPV6) - return -EINVAL; - /* write the filer rules here */ if (!gfar_ethflow_to_filer_table(priv, cmd->data, cmd->flow_type)) - return -1; + return -EINVAL; return 0; } -- cgit v1.2.3-58-ga151 From c44d79950b2daa1025e62eede73e4e4a274d1ef3 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 8 Apr 2011 13:49:15 +0000 Subject: niu: Recognise original ethtool class code for AH/ESP flow hashing When the RX network flow classification interface was originally defined for reporting and controlling of flow hashing, AH and ESP were not given distinct flow class codes (apparently because the Sun Neptune hardware treats them very similarly). For flow steering, they must be distinguished, so new and separate flow class codes were added for AH and ESP. But for backward- compatibility, flow hash operations should continue to support the original class codes. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/niu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index ab4e7dd82d0b..9e6330bc0531 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -7022,6 +7022,7 @@ static int niu_ethflow_to_class(int flow_type, u64 *class) case UDP_V4_FLOW: *class = CLASS_CODE_UDP_IPV4; break; + case AH_ESP_V4_FLOW: case AH_V4_FLOW: case ESP_V4_FLOW: *class = CLASS_CODE_AH_ESP_IPV4; @@ -7035,6 +7036,7 @@ static int niu_ethflow_to_class(int flow_type, u64 *class) case UDP_V6_FLOW: *class = CLASS_CODE_UDP_IPV6; break; + case AH_ESP_V6_FLOW: case AH_V6_FLOW: case ESP_V6_FLOW: *class = CLASS_CODE_AH_ESP_IPV6; -- cgit v1.2.3-58-ga151 From 73d6ac633c6c0ca703f90db0b808d9593e46aef6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 11 Apr 2011 10:43:50 +0000 Subject: caif: code cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup of new CAIF code. * make local functions static * remove code that is never used * expand get_caif_conf() since wrapper is no longer needed * make args to comparison functions const * rename connect_req_to_link_param to keep exported names consistent Compile tested only. Signed-off-by: Stephen Hemminger Acked-by: Sjur Brændeland Signed-off-by: David S. Miller --- include/net/caif/caif_dev.h | 27 ++----- include/net/caif/cfctrl.h | 12 +-- include/net/caif/cfmuxl.h | 2 - include/net/caif/cfpkt.h | 75 ------------------- include/net/caif/cfsrvl.h | 3 +- net/caif/caif_config_util.c | 6 +- net/caif/caif_dev.c | 24 ++---- net/caif/cfcnfg.c | 2 +- net/caif/cfctrl.c | 75 ++----------------- net/caif/cfmuxl.c | 35 --------- net/caif/cfpkt_skbuff.c | 178 ++------------------------------------------ net/caif/cfsrvl.c | 7 +- 12 files changed, 30 insertions(+), 416 deletions(-) diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h index 8eff83b95366..7e3f7a6d2ba3 100644 --- a/include/net/caif/caif_dev.h +++ b/include/net/caif/caif_dev.h @@ -74,19 +74,8 @@ int caif_connect_client(struct caif_connect_request *conn_req, int caif_disconnect_client(struct cflayer *client_layer); /** - * caif_release_client - Release adaptation layer reference to client. - * - * @client_layer: Client layer. - * - * Releases a client/adaptation layer use of the caif stack. - * This function must be used after caif_disconnect_client to - * decrease the reference count of the service layer. - */ -void caif_release_client(struct cflayer *client_layer); - -/** - * connect_req_to_link_param - Translate configuration parameters - * from socket format to internal format. + * caif_connect_req_to_link_param - Translate configuration parameters + * from socket format to internal format. * @cnfg: Pointer to configuration handler * @con_req: Configuration parameters supplied in function * caif_connect_client @@ -94,14 +83,8 @@ void caif_release_client(struct cflayer *client_layer); * setting up channels. * */ -int connect_req_to_link_param(struct cfcnfg *cnfg, - struct caif_connect_request *con_req, - struct cfctrl_link_param *channel_setup_param); - -/** - * get_caif_conf() - Get the configuration handler. - */ -struct cfcnfg *get_caif_conf(void); - +int caif_connect_req_to_link_param(struct cfcnfg *cnfg, + struct caif_connect_request *con_req, + struct cfctrl_link_param *setup_param); #endif /* CAIF_DEV_H_ */ diff --git a/include/net/caif/cfctrl.h b/include/net/caif/cfctrl.h index e54f6396fa4c..d84416fa175a 100644 --- a/include/net/caif/cfctrl.h +++ b/include/net/caif/cfctrl.h @@ -121,19 +121,9 @@ int cfctrl_linkup_request(struct cflayer *cfctrl, struct cflayer *user_layer); int cfctrl_linkdown_req(struct cflayer *cfctrl, u8 linkid, struct cflayer *client); -void cfctrl_sleep_req(struct cflayer *cfctrl); -void cfctrl_wake_req(struct cflayer *cfctrl); -void cfctrl_getstartreason_req(struct cflayer *cfctrl); + struct cflayer *cfctrl_create(void); -void cfctrl_set_dnlayer(struct cflayer *this, struct cflayer *dn); -void cfctrl_set_uplayer(struct cflayer *this, struct cflayer *up); struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer); -bool cfctrl_req_eq(struct cfctrl_request_info *r1, - struct cfctrl_request_info *r2); -void cfctrl_insert_req(struct cfctrl *ctrl, - struct cfctrl_request_info *req); -struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, - struct cfctrl_request_info *req); void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer); #endif /* CFCTRL_H_ */ diff --git a/include/net/caif/cfmuxl.h b/include/net/caif/cfmuxl.h index 4e1b4f33423e..5847a196b8ad 100644 --- a/include/net/caif/cfmuxl.h +++ b/include/net/caif/cfmuxl.h @@ -16,7 +16,5 @@ int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid); struct cflayer *cfmuxl_remove_dnlayer(struct cflayer *layr, u8 phyid); int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *up, u8 phyid); struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 linkid); -bool cfmuxl_is_phy_inuse(struct cflayer *layr, u8 phyid); -u8 cfmuxl_get_phyid(struct cflayer *layr, u8 channel_id); #endif /* CFMUXL_H_ */ diff --git a/include/net/caif/cfpkt.h b/include/net/caif/cfpkt.h index fbc681beff52..8b550f8950d7 100644 --- a/include/net/caif/cfpkt.h +++ b/include/net/caif/cfpkt.h @@ -16,12 +16,6 @@ struct cfpkt; */ struct cfpkt *cfpkt_create(u16 len); -/* Create a CAIF packet. - * data Data to copy. - * len Length of packet to be created - * @return New packet. - */ -struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len); /* * Destroy a CAIF Packet. * pkt Packet to be destoyed. @@ -181,22 +175,6 @@ u16 cfpkt_iterate(struct cfpkt *pkt, u16 (*iter_func)(u16 chks, void *buf, u16 len), u16 data); -/* Append by giving user access to packet buffer - * cfpkt Packet to append to - * buf Buffer inside pkt that user shall copy data into - * buflen Length of buffer and number of bytes added to packet - * @return 0 on error, 1 on success - */ -int cfpkt_raw_append(struct cfpkt *cfpkt, void **buf, unsigned int buflen); - -/* Extract by giving user access to packet buffer - * cfpkt Packet to extract from - * buf Buffer inside pkt that user shall copy data from - * buflen Length of buffer and number of bytes removed from packet - * @return 0 on error, 1 on success - */ -int cfpkt_raw_extract(struct cfpkt *cfpkt, void **buf, unsigned int buflen); - /* Map from a "native" packet (e.g. Linux Socket Buffer) to a CAIF packet. * dir - Direction indicating whether this packet is to be sent or received. * nativepkt - The native packet to be transformed to a CAIF packet @@ -210,59 +188,6 @@ struct cfpkt *cfpkt_fromnative(enum caif_direction dir, void *nativepkt); */ void *cfpkt_tonative(struct cfpkt *pkt); -/* - * Insert a packet in the packet queue. - * pktq Packet queue to insert into - * pkt Packet to be inserted in queue - * prio Priority of packet - */ -void cfpkt_queue(struct cfpktq *pktq, struct cfpkt *pkt, - unsigned short prio); - -/* - * Remove a packet from the packet queue. - * pktq Packet queue to fetch packets from. - * @return Dequeued packet. - */ -struct cfpkt *cfpkt_dequeue(struct cfpktq *pktq); - -/* - * Peek into a packet from the packet queue. - * pktq Packet queue to fetch packets from. - * @return Peeked packet. - */ -struct cfpkt *cfpkt_qpeek(struct cfpktq *pktq); - -/* - * Initiates the packet queue. - * @return Pointer to new packet queue. - */ -struct cfpktq *cfpktq_create(void); - -/* - * Get the number of packets in the queue. - * pktq Packet queue to fetch count from. - * @return Number of packets in queue. - */ -int cfpkt_qcount(struct cfpktq *pktq); - -/* - * Put content of packet into buffer for debuging purposes. - * pkt Packet to copy data from - * buf Buffer to copy data into - * buflen Length of data to copy - * @return Pointer to copied data - */ -char *cfpkt_log_pkt(struct cfpkt *pkt, char *buf, int buflen); - -/* - * Clones a packet and releases the original packet. - * This is used for taking ownership of a packet e.g queueing. - * pkt Packet to clone and release. - * @return Cloned packet. - */ -struct cfpkt *cfpkt_clone_release(struct cfpkt *pkt); - /* * Returns packet information for a packet. diff --git a/include/net/caif/cfsrvl.h b/include/net/caif/cfsrvl.h index b1fa87ee0992..6c8279c1ae9a 100644 --- a/include/net/caif/cfsrvl.h +++ b/include/net/caif/cfsrvl.h @@ -22,7 +22,6 @@ struct cfsrvl { struct kref ref; }; -void cfsrvl_release(struct kref *kref); struct cflayer *cfvei_create(u8 linkid, struct dev_info *dev_info); struct cflayer *cfdgml_create(u8 linkid, struct dev_info *dev_info); struct cflayer *cfutill_create(u8 linkid, struct dev_info *dev_info); @@ -31,7 +30,7 @@ struct cflayer *cfrfml_create(u8 linkid, struct dev_info *dev_info, int mtu_size); struct cflayer *cfdbgl_create(u8 linkid, struct dev_info *dev_info); bool cfsrvl_phyid_match(struct cflayer *layer, int phyid); -void cfservl_destroy(struct cflayer *layer); + void cfsrvl_init(struct cfsrvl *service, u8 channel_id, struct dev_info *dev_info, diff --git a/net/caif/caif_config_util.c b/net/caif/caif_config_util.c index d522d8c1703e..9b63e4e3910e 100644 --- a/net/caif/caif_config_util.c +++ b/net/caif/caif_config_util.c @@ -10,9 +10,9 @@ #include #include -int connect_req_to_link_param(struct cfcnfg *cnfg, - struct caif_connect_request *s, - struct cfctrl_link_param *l) +int caif_connect_req_to_link_param(struct cfcnfg *cnfg, + struct caif_connect_request *s, + struct cfctrl_link_param *l) { struct dev_info *dev_info; enum cfcnfg_phy_preference pref; diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index a42a408306e4..b533bb09a002 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -257,7 +257,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, break; } dev_hold(dev); - cfcnfg_add_phy_layer(get_caif_conf(), + cfcnfg_add_phy_layer(cfg, phy_type, dev, &caifd->layer, @@ -300,7 +300,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, if (atomic_read(&caifd->in_use)) netdev_warn(dev, "Unregistering an active CAIF device\n"); - cfcnfg_del_phy_layer(get_caif_conf(), &caifd->layer); + cfcnfg_del_phy_layer(cfg, &caifd->layer); dev_put(dev); atomic_set(&caifd->state, what); break; @@ -322,24 +322,18 @@ static struct notifier_block caif_device_notifier = { .priority = 0, }; - -struct cfcnfg *get_caif_conf(void) -{ - return cfg; -} -EXPORT_SYMBOL(get_caif_conf); - int caif_connect_client(struct caif_connect_request *conn_req, struct cflayer *client_layer, int *ifindex, int *headroom, int *tailroom) { struct cfctrl_link_param param; int ret; - ret = connect_req_to_link_param(get_caif_conf(), conn_req, ¶m); + + ret = caif_connect_req_to_link_param(cfg, conn_req, ¶m); if (ret) return ret; /* Hook up the adaptation layer. */ - return cfcnfg_add_adaptation_layer(get_caif_conf(), ¶m, + return cfcnfg_add_adaptation_layer(cfg, ¶m, client_layer, ifindex, headroom, tailroom); } @@ -347,16 +341,10 @@ EXPORT_SYMBOL(caif_connect_client); int caif_disconnect_client(struct cflayer *adap_layer) { - return cfcnfg_disconn_adapt_layer(get_caif_conf(), adap_layer); + return cfcnfg_disconn_adapt_layer(cfg, adap_layer); } EXPORT_SYMBOL(caif_disconnect_client); -void caif_release_client(struct cflayer *adap_layer) -{ - cfcnfg_release_adap_layer(adap_layer); -} -EXPORT_SYMBOL(caif_release_client); - /* Per-namespace Caif devices handling */ static int caif_init_net(struct net *net) { diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index f1f98d967d8a..25c0b198e285 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c @@ -253,7 +253,7 @@ static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id) { } -int protohead[CFCTRL_SRV_MASK] = { +static const int protohead[CFCTRL_SRV_MASK] = { [CFCTRL_SRV_VEI] = 4, [CFCTRL_SRV_DATAGRAM] = 7, [CFCTRL_SRV_UTIL] = 4, diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c index 3cd8f978e309..397a2c099e2c 100644 --- a/net/caif/cfctrl.c +++ b/net/caif/cfctrl.c @@ -58,7 +58,8 @@ struct cflayer *cfctrl_create(void) return &this->serv.layer; } -static bool param_eq(struct cfctrl_link_param *p1, struct cfctrl_link_param *p2) +static bool param_eq(const struct cfctrl_link_param *p1, + const struct cfctrl_link_param *p2) { bool eq = p1->linktype == p2->linktype && @@ -100,8 +101,8 @@ static bool param_eq(struct cfctrl_link_param *p1, struct cfctrl_link_param *p2) return false; } -bool cfctrl_req_eq(struct cfctrl_request_info *r1, - struct cfctrl_request_info *r2) +static bool cfctrl_req_eq(const struct cfctrl_request_info *r1, + const struct cfctrl_request_info *r2) { if (r1->cmd != r2->cmd) return false; @@ -112,7 +113,7 @@ bool cfctrl_req_eq(struct cfctrl_request_info *r1, } /* Insert request at the end */ -void cfctrl_insert_req(struct cfctrl *ctrl, +static void cfctrl_insert_req(struct cfctrl *ctrl, struct cfctrl_request_info *req) { spin_lock(&ctrl->info_list_lock); @@ -123,8 +124,8 @@ void cfctrl_insert_req(struct cfctrl *ctrl, } /* Compare and remove request */ -struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, - struct cfctrl_request_info *req) +static struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, + struct cfctrl_request_info *req) { struct cfctrl_request_info *p, *tmp, *first; @@ -154,16 +155,6 @@ struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer) return &this->res; } -void cfctrl_set_dnlayer(struct cflayer *this, struct cflayer *dn) -{ - this->dn = dn; -} - -void cfctrl_set_uplayer(struct cflayer *this, struct cflayer *up) -{ - this->up = up; -} - static void init_info(struct caif_payload_info *info, struct cfctrl *cfctrl) { info->hdr_len = 0; @@ -304,58 +295,6 @@ int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, return ret; } -void cfctrl_sleep_req(struct cflayer *layer) -{ - int ret; - struct cfctrl *cfctrl = container_obj(layer); - struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); - if (!pkt) { - pr_warn("Out of memory\n"); - return; - } - cfpkt_addbdy(pkt, CFCTRL_CMD_SLEEP); - init_info(cfpkt_info(pkt), cfctrl); - ret = - cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); - if (ret < 0) - cfpkt_destroy(pkt); -} - -void cfctrl_wake_req(struct cflayer *layer) -{ - int ret; - struct cfctrl *cfctrl = container_obj(layer); - struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); - if (!pkt) { - pr_warn("Out of memory\n"); - return; - } - cfpkt_addbdy(pkt, CFCTRL_CMD_WAKE); - init_info(cfpkt_info(pkt), cfctrl); - ret = - cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); - if (ret < 0) - cfpkt_destroy(pkt); -} - -void cfctrl_getstartreason_req(struct cflayer *layer) -{ - int ret; - struct cfctrl *cfctrl = container_obj(layer); - struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); - if (!pkt) { - pr_warn("Out of memory\n"); - return; - } - cfpkt_addbdy(pkt, CFCTRL_CMD_START_REASON); - init_info(cfpkt_info(pkt), cfctrl); - ret = - cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); - if (ret < 0) - cfpkt_destroy(pkt); -} - - void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer) { struct cfctrl_request_info *p, *tmp; diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c index 24f1ffa74b06..f8ce0f3d9210 100644 --- a/net/caif/cfmuxl.c +++ b/net/caif/cfmuxl.c @@ -71,41 +71,6 @@ int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid) return 0; } -bool cfmuxl_is_phy_inuse(struct cflayer *layr, u8 phyid) -{ - struct list_head *node; - struct cflayer *layer; - struct cfmuxl *muxl = container_obj(layr); - bool match = false; - spin_lock(&muxl->receive_lock); - - list_for_each(node, &muxl->srvl_list) { - layer = list_entry(node, struct cflayer, node); - if (cfsrvl_phyid_match(layer, phyid)) { - match = true; - break; - } - - } - spin_unlock(&muxl->receive_lock); - return match; -} - -u8 cfmuxl_get_phyid(struct cflayer *layr, u8 channel_id) -{ - struct cflayer *up; - int phyid; - struct cfmuxl *muxl = container_obj(layr); - spin_lock(&muxl->receive_lock); - up = get_up(muxl, channel_id); - if (up != NULL) - phyid = cfsrvl_getphyid(up); - else - phyid = 0; - spin_unlock(&muxl->receive_lock); - return phyid; -} - int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *dn, u8 phyid) { struct cfmuxl *muxl = (struct cfmuxl *) layr; diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c index d7e865e2ff65..20c6cb3522e0 100644 --- a/net/caif/cfpkt_skbuff.c +++ b/net/caif/cfpkt_skbuff.c @@ -42,22 +42,22 @@ struct cfpkt_priv_data { bool erronous; }; -inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt) +static inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt) { return (struct cfpkt_priv_data *) pkt->skb.cb; } -inline bool is_erronous(struct cfpkt *pkt) +static inline bool is_erronous(struct cfpkt *pkt) { return cfpkt_priv(pkt)->erronous; } -inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt) +static inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt) { return &pkt->skb; } -inline struct cfpkt *skb_to_pkt(struct sk_buff *skb) +static inline struct cfpkt *skb_to_pkt(struct sk_buff *skb) { return (struct cfpkt *) skb; } @@ -317,17 +317,6 @@ int cfpkt_setlen(struct cfpkt *pkt, u16 len) } EXPORT_SYMBOL(cfpkt_setlen); -struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len) -{ - struct cfpkt *pkt = cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); - if (!pkt) - return NULL; - if (unlikely(data != NULL)) - cfpkt_add_body(pkt, data, len); - return pkt; -} -EXPORT_SYMBOL(cfpkt_create_uplink); - struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, struct cfpkt *addpkt, u16 expectlen) @@ -408,169 +397,12 @@ struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) } EXPORT_SYMBOL(cfpkt_split); -char *cfpkt_log_pkt(struct cfpkt *pkt, char *buf, int buflen) -{ - struct sk_buff *skb = pkt_to_skb(pkt); - char *p = buf; - int i; - - /* - * Sanity check buffer length, it needs to be at least as large as - * the header info: ~=50+ bytes - */ - if (buflen < 50) - return NULL; - - snprintf(buf, buflen, "%s: pkt:%p len:%ld(%ld+%ld) {%ld,%ld} data: [", - is_erronous(pkt) ? "ERRONOUS-SKB" : - (skb->data_len != 0 ? "COMPLEX-SKB" : "SKB"), - skb, - (long) skb->len, - (long) (skb_tail_pointer(skb) - skb->data), - (long) skb->data_len, - (long) (skb->data - skb->head), - (long) (skb_tail_pointer(skb) - skb->head)); - p = buf + strlen(buf); - - for (i = 0; i < skb_tail_pointer(skb) - skb->data && i < 300; i++) { - if (p > buf + buflen - 10) { - sprintf(p, "..."); - p = buf + strlen(buf); - break; - } - sprintf(p, "%02x,", skb->data[i]); - p = buf + strlen(buf); - } - sprintf(p, "]\n"); - return buf; -} -EXPORT_SYMBOL(cfpkt_log_pkt); - -int cfpkt_raw_append(struct cfpkt *pkt, void **buf, unsigned int buflen) -{ - struct sk_buff *skb = pkt_to_skb(pkt); - struct sk_buff *lastskb; - - caif_assert(buf != NULL); - if (unlikely(is_erronous(pkt))) - return -EPROTO; - /* Make sure SKB is writable */ - if (unlikely(skb_cow_data(skb, 0, &lastskb) < 0)) { - PKT_ERROR(pkt, "skb_cow_data failed\n"); - return -EPROTO; - } - - if (unlikely(skb_linearize(skb) != 0)) { - PKT_ERROR(pkt, "linearize failed\n"); - return -EPROTO; - } - - if (unlikely(skb_tailroom(skb) < buflen)) { - PKT_ERROR(pkt, "buffer too short - failed\n"); - return -EPROTO; - } - - *buf = skb_put(skb, buflen); - return 1; -} -EXPORT_SYMBOL(cfpkt_raw_append); - -int cfpkt_raw_extract(struct cfpkt *pkt, void **buf, unsigned int buflen) -{ - struct sk_buff *skb = pkt_to_skb(pkt); - - caif_assert(buf != NULL); - if (unlikely(is_erronous(pkt))) - return -EPROTO; - - if (unlikely(buflen > skb->len)) { - PKT_ERROR(pkt, "buflen too large - failed\n"); - return -EPROTO; - } - - if (unlikely(buflen > skb_headlen(skb))) { - if (unlikely(skb_linearize(skb) != 0)) { - PKT_ERROR(pkt, "linearize failed\n"); - return -EPROTO; - } - } - - *buf = skb->data; - skb_pull(skb, buflen); - - return 1; -} -EXPORT_SYMBOL(cfpkt_raw_extract); - -inline bool cfpkt_erroneous(struct cfpkt *pkt) +bool cfpkt_erroneous(struct cfpkt *pkt) { return cfpkt_priv(pkt)->erronous; } EXPORT_SYMBOL(cfpkt_erroneous); -struct cfpktq *cfpktq_create(void) -{ - struct cfpktq *q = kmalloc(sizeof(struct cfpktq), GFP_ATOMIC); - if (!q) - return NULL; - skb_queue_head_init(&q->head); - atomic_set(&q->count, 0); - spin_lock_init(&q->lock); - return q; -} -EXPORT_SYMBOL(cfpktq_create); - -void cfpkt_queue(struct cfpktq *pktq, struct cfpkt *pkt, unsigned short prio) -{ - atomic_inc(&pktq->count); - spin_lock(&pktq->lock); - skb_queue_tail(&pktq->head, pkt_to_skb(pkt)); - spin_unlock(&pktq->lock); - -} -EXPORT_SYMBOL(cfpkt_queue); - -struct cfpkt *cfpkt_qpeek(struct cfpktq *pktq) -{ - struct cfpkt *tmp; - spin_lock(&pktq->lock); - tmp = skb_to_pkt(skb_peek(&pktq->head)); - spin_unlock(&pktq->lock); - return tmp; -} -EXPORT_SYMBOL(cfpkt_qpeek); - -struct cfpkt *cfpkt_dequeue(struct cfpktq *pktq) -{ - struct cfpkt *pkt; - spin_lock(&pktq->lock); - pkt = skb_to_pkt(skb_dequeue(&pktq->head)); - if (pkt) { - atomic_dec(&pktq->count); - caif_assert(atomic_read(&pktq->count) >= 0); - } - spin_unlock(&pktq->lock); - return pkt; -} -EXPORT_SYMBOL(cfpkt_dequeue); - -int cfpkt_qcount(struct cfpktq *pktq) -{ - return atomic_read(&pktq->count); -} -EXPORT_SYMBOL(cfpkt_qcount); - -struct cfpkt *cfpkt_clone_release(struct cfpkt *pkt) -{ - struct cfpkt *clone; - clone = skb_to_pkt(skb_clone(pkt_to_skb(pkt), GFP_ATOMIC)); - /* Free original packet. */ - cfpkt_destroy(pkt); - if (!clone) - return NULL; - return clone; -} -EXPORT_SYMBOL(cfpkt_clone_release); struct caif_payload_info *cfpkt_info(struct cfpkt *pkt) { diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index ab5e542526bf..24ba392f203b 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c @@ -151,12 +151,7 @@ static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) return -EINVAL; } -void cfservl_destroy(struct cflayer *layer) -{ - kfree(layer); -} - -void cfsrvl_release(struct kref *kref) +static void cfsrvl_release(struct kref *kref) { struct cfsrvl *service = container_of(kref, struct cfsrvl, ref); kfree(service); -- cgit v1.2.3-58-ga151 From 4dd820c088d201e526840c9dbc2f0b87a0a41868 Mon Sep 17 00:00:00 2001 From: Sjur Brændeland Date: Mon, 11 Apr 2011 10:43:51 +0000 Subject: caif: Don't resend if dev_queue_xmit fails. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CAIF Link Layer returns an error, we no longer try to re-build the CAIF packet and resend it. Instead, we simply return any transmission errors to the socket client. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- net/caif/caif_dev.c | 21 ++++----------------- net/caif/caif_socket.c | 35 +++-------------------------------- net/caif/cfdgml.c | 7 +------ net/caif/cffrml.c | 8 +------- net/caif/cfmuxl.c | 7 +------ net/caif/cfserl.c | 7 +------ net/caif/cfutill.c | 7 +------ net/caif/cfveil.c | 5 +---- net/caif/cfvidl.c | 5 +---- 9 files changed, 14 insertions(+), 88 deletions(-) diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index b533bb09a002..a518fdd4da0a 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -120,25 +120,12 @@ static int transmit(struct cflayer *layer, struct cfpkt *pkt) { struct caif_device_entry *caifd = container_of(layer, struct caif_device_entry, layer); - struct sk_buff *skb, *skb2; - int ret = -EINVAL; + struct sk_buff *skb; + skb = cfpkt_tonative(pkt); skb->dev = caifd->netdev; - /* - * Don't allow SKB to be destroyed upon error, but signal resend - * notification to clients. We can't rely on the return value as - * congestion (NET_XMIT_CN) sometimes drops the packet, sometimes don't. - */ - if (netif_queue_stopped(caifd->netdev)) - return -EAGAIN; - skb2 = skb_get(skb); - - ret = dev_queue_xmit(skb2); - - if (!ret) - kfree_skb(skb); - else - return -EAGAIN; + + dev_queue_xmit(skb); return 0; } diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 37a4034dfc29..20212424e2e8 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -519,43 +519,14 @@ static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk, int noblock, long timeo) { struct cfpkt *pkt; - int ret, loopcnt = 0; pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb); memset(cfpkt_info(pkt), 0, sizeof(struct caif_payload_info)); - do { - - ret = -ETIMEDOUT; - /* Slight paranoia, probably not needed. */ - if (unlikely(loopcnt++ > 1000)) { - pr_warn("transmit retries failed, error = %d\n", ret); - break; - } + if (cf_sk->layer.dn == NULL) + return -EINVAL; - if (cf_sk->layer.dn != NULL) - ret = cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt); - if (likely(ret >= 0)) - break; - /* if transmit return -EAGAIN, then retry */ - if (noblock && ret == -EAGAIN) - break; - timeo = caif_wait_for_flow_on(cf_sk, 0, timeo, &ret); - if (signal_pending(current)) { - ret = sock_intr_errno(timeo); - break; - } - if (ret) - break; - if (cf_sk->sk.sk_state != CAIF_CONNECTED || - sock_flag(&cf_sk->sk, SOCK_DEAD) || - (cf_sk->sk.sk_shutdown & RCV_SHUTDOWN)) { - ret = -EPIPE; - cf_sk->sk.sk_err = EPIPE; - break; - } - } while (ret == -EAGAIN); - return ret; + return cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt); } /* Copied from af_unix:unix_dgram_sendmsg, and adapted to CAIF */ diff --git a/net/caif/cfdgml.c b/net/caif/cfdgml.c index 054fdb5aeb88..0382dec84fdc 100644 --- a/net/caif/cfdgml.c +++ b/net/caif/cfdgml.c @@ -108,10 +108,5 @@ static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt) */ info->hdr_len = 4; info->dev_info = &service->dev_info; - ret = layr->dn->transmit(layr->dn, pkt); - if (ret < 0) { - u32 tmp32; - cfpkt_extr_head(pkt, &tmp32, 4); - } - return ret; + return layr->dn->transmit(layr->dn, pkt); } diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c index a445043931ae..2423fed8e26c 100644 --- a/net/caif/cffrml.c +++ b/net/caif/cffrml.c @@ -120,7 +120,6 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt) int tmp; u16 chks; u16 len; - int ret; struct cffrml *this = container_obj(layr); if (this->dofcs) { chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff); @@ -137,12 +136,7 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt) pr_err("Packet is erroneous!\n"); return -EPROTO; } - ret = layr->dn->transmit(layr->dn, pkt); - if (ret < 0) { - /* Remove header on faulty packet. */ - cfpkt_extr_head(pkt, &tmp, 2); - } - return ret; + return layr->dn->transmit(layr->dn, pkt); } static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c index f8ce0f3d9210..ebfda2c9290b 100644 --- a/net/caif/cfmuxl.c +++ b/net/caif/cfmuxl.c @@ -184,7 +184,6 @@ static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt) static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt) { - int ret; struct cfmuxl *muxl = container_obj(layr); u8 linkid; struct cflayer *dn; @@ -198,11 +197,7 @@ static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt) info->hdr_len += 1; linkid = info->channel_id; cfpkt_add_head(pkt, &linkid, 1); - ret = dn->transmit(dn, pkt); - /* Remove MUX protocol header upon error. */ - if (ret < 0) - cfpkt_extr_head(pkt, &linkid, 1); - return ret; + return dn->transmit(dn, pkt); } static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c index 8303fe3ebf89..2715c84cfa87 100644 --- a/net/caif/cfserl.c +++ b/net/caif/cfserl.c @@ -179,15 +179,10 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt) static int cfserl_transmit(struct cflayer *layer, struct cfpkt *newpkt) { struct cfserl *layr = container_obj(layer); - int ret; u8 tmp8 = CFSERL_STX; if (layr->usestx) cfpkt_add_head(newpkt, &tmp8, 1); - ret = layer->dn->transmit(layer->dn, newpkt); - if (ret < 0) - cfpkt_extr_head(newpkt, &tmp8, 1); - - return ret; + return layer->dn->transmit(layer->dn, newpkt); } static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, diff --git a/net/caif/cfutill.c b/net/caif/cfutill.c index 315c0d601368..98e027db18ed 100644 --- a/net/caif/cfutill.c +++ b/net/caif/cfutill.c @@ -100,10 +100,5 @@ static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt) */ info->hdr_len = 1; info->dev_info = &service->dev_info; - ret = layr->dn->transmit(layr->dn, pkt); - if (ret < 0) { - u32 tmp32; - cfpkt_extr_head(pkt, &tmp32, 4); - } - return ret; + return layr->dn->transmit(layr->dn, pkt); } diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c index c3b1dec4acf6..1a588cd818ea 100644 --- a/net/caif/cfveil.c +++ b/net/caif/cfveil.c @@ -96,8 +96,5 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt) info->channel_id = service->layer.id; info->hdr_len = 1; info->dev_info = &service->dev_info; - ret = layr->dn->transmit(layr->dn, pkt); - if (ret < 0) - cfpkt_extr_head(pkt, &tmp, 1); - return ret; + return layr->dn->transmit(layr->dn, pkt); } diff --git a/net/caif/cfvidl.c b/net/caif/cfvidl.c index bf6fef2a0eff..b2f5989ad455 100644 --- a/net/caif/cfvidl.c +++ b/net/caif/cfvidl.c @@ -60,8 +60,5 @@ static int cfvidl_transmit(struct cflayer *layr, struct cfpkt *pkt) info = cfpkt_info(pkt); info->channel_id = service->layer.id; info->dev_info = &service->dev_info; - ret = layr->dn->transmit(layr->dn, pkt); - if (ret < 0) - cfpkt_extr_head(pkt, &videoheader, 4); - return ret; + return layr->dn->transmit(layr->dn, pkt); } -- cgit v1.2.3-58-ga151 From 39b9afbb4c0750742eb61b7a015e12f483e0b4a3 Mon Sep 17 00:00:00 2001 From: Sjur Brændeland Date: Mon, 11 Apr 2011 10:43:52 +0000 Subject: caif: Add BUG_ON if dev_info is missing in packet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- net/caif/cfmuxl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c index ebfda2c9290b..fc2497468571 100644 --- a/net/caif/cfmuxl.c +++ b/net/caif/cfmuxl.c @@ -188,7 +188,8 @@ static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt) u8 linkid; struct cflayer *dn; struct caif_payload_info *info = cfpkt_info(pkt); - dn = get_dn(muxl, cfpkt_info(pkt)->dev_info); + BUG_ON(!info); + dn = get_dn(muxl, info->dev_info); if (dn == NULL) { pr_warn("Send data on unknown phy ID = %d (0x%x)\n", info->dev_info->id, info->dev_info->id); -- cgit v1.2.3-58-ga151 From f344c25dbab1a392ef7a7afc8ca061b3b7285423 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 11 Apr 2011 15:49:26 -0700 Subject: niu: Fix warnings due to -Wunused-but-set-variable Most of these were legitimate, and once case was a real bug (not propagating errors from ->xcvr_init() methods). Signed-off-by: David S. Miller --- drivers/net/niu.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 9e6330bc0531..3fa1e9cdb4a8 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -1233,7 +1233,7 @@ static int link_status_1g_rgmii(struct niu *np, int *link_up_p) bmsr = err; if (bmsr & BMSR_LSTATUS) { - u16 adv, lpa, common, estat; + u16 adv, lpa; err = mii_read(np, np->phy_addr, MII_ADVERTISE); if (err < 0) @@ -1245,12 +1245,9 @@ static int link_status_1g_rgmii(struct niu *np, int *link_up_p) goto out; lpa = err; - common = adv & lpa; - err = mii_read(np, np->phy_addr, MII_ESTATUS); if (err < 0) goto out; - estat = err; link_up = 1; current_speed = SPEED_1000; current_duplex = DUPLEX_FULL; @@ -1650,7 +1647,7 @@ static int xcvr_init_10g(struct niu *np) break; } - return 0; + return err; } static int mii_reset(struct niu *np) @@ -2381,17 +2378,14 @@ static int serdes_init_10g_serdes(struct niu *np) struct niu_link_config *lp = &np->link_config; unsigned long ctrl_reg, test_cfg_reg, pll_cfg, i; u64 ctrl_val, test_cfg_val, sig, mask, val; - u64 reset_val; switch (np->port) { case 0: - reset_val = ENET_SERDES_RESET_0; ctrl_reg = ENET_SERDES_0_CTRL_CFG; test_cfg_reg = ENET_SERDES_0_TEST_CFG; pll_cfg = ENET_SERDES_0_PLL_CFG; break; case 1: - reset_val = ENET_SERDES_RESET_1; ctrl_reg = ENET_SERDES_1_CTRL_CFG; test_cfg_reg = ENET_SERDES_1_TEST_CFG; pll_cfg = ENET_SERDES_1_PLL_CFG; @@ -8135,7 +8129,7 @@ static int __devinit niu_pci_vpd_scan_props(struct niu *np, netif_printk(np, probe, KERN_DEBUG, np->dev, "VPD_SCAN: start[%x] end[%x]\n", start, end); while (start < end) { - int len, err, instance, type, prop_len; + int len, err, prop_len; char namebuf[64]; u8 *prop_buf; int max_len; @@ -8151,8 +8145,6 @@ static int __devinit niu_pci_vpd_scan_props(struct niu *np, len = err; start += 3; - instance = niu_pci_eeprom_read(np, start); - type = niu_pci_eeprom_read(np, start + 3); prop_len = niu_pci_eeprom_read(np, start + 4); err = niu_pci_vpd_get_propname(np, start + 5, namebuf, 64); if (err < 0) -- cgit v1.2.3-58-ga151 From d83d282bcbf24ec8ddd4f0eb57f7ad302c431b8a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 11 Apr 2011 16:00:00 -0700 Subject: s2io: Fix warnings due to -Wunused-but-set-variable. Most of these are cases where we are trying to read back a register after a write to ensure completion. Simply pre-fixing the readl() or readq() with "(void)" is sufficient because these are volatile operations and the compiler cannot eliminate them just because no real assignment takes place. The case of free_rxd_blk()'s assignments to "struct buffAdd *ba" is a real spurious assignment as this variable is completely otherwise unused. Signed-off-by: David S. Miller Acked-by: Jon Mason --- drivers/net/s2io.c | 5 +---- drivers/net/s2io.h | 10 ++++------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index ca8e75e9a7ee..2d5cc6142c04 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -2244,13 +2244,12 @@ static int verify_xena_quiescence(struct s2io_nic *sp) static void fix_mac_address(struct s2io_nic *sp) { struct XENA_dev_config __iomem *bar0 = sp->bar0; - u64 val64; int i = 0; while (fix_mac[i] != END_SIGN) { writeq(fix_mac[i++], &bar0->gpio_control); udelay(10); - val64 = readq(&bar0->gpio_control); + (void) readq(&bar0->gpio_control); } } @@ -2727,7 +2726,6 @@ static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk) int j; struct sk_buff *skb; struct RxD_t *rxdp; - struct buffAdd *ba; struct RxD1 *rxdp1; struct RxD3 *rxdp3; struct mac_info *mac_control = &sp->mac_control; @@ -2751,7 +2749,6 @@ static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk) memset(rxdp, 0, sizeof(struct RxD1)); } else if (sp->rxd_mode == RXD_MODE_3B) { rxdp3 = (struct RxD3 *)rxdp; - ba = &mac_control->rings[ring_no].ba[blk][j]; pci_unmap_single(sp->pdev, (dma_addr_t)rxdp3->Buffer0_ptr, BUF0_LEN, diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 628fd278866a..800b3a44e653 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -1002,18 +1002,16 @@ static inline void writeq(u64 val, void __iomem *addr) #define LF 2 static inline void SPECIAL_REG_WRITE(u64 val, void __iomem *addr, int order) { - u32 ret; - if (order == LF) { writel((u32) (val), addr); - ret = readl(addr); + (void) readl(addr); writel((u32) (val >> 32), (addr + 4)); - ret = readl(addr + 4); + (void) readl(addr + 4); } else { writel((u32) (val >> 32), (addr + 4)); - ret = readl(addr + 4); + (void) readl(addr + 4); writel((u32) (val), addr); - ret = readl(addr); + (void) readl(addr); } } -- cgit v1.2.3-58-ga151 From cd883a791b55c3c52ce402cd551585fed092d240 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Fri, 8 Apr 2011 11:11:21 +0000 Subject: vxge: always enable hardware time stamp Hardware time stamp calculation can only be enabled by the privileged function. Enable it always by default and simply use the ethtool interface to set a flag to indicate whether or not the respective function driver should indicate the timestamp along with the received packet. Also, make certain fields in vxge_hw_device_config bit-fields to reduce the size of the struct. Signed-off-by: Jon Mason Signed-off-by: David S. Miller --- drivers/net/vxge/vxge-config.h | 70 ++++++++++++++++++++++------------------- drivers/net/vxge/vxge-main.c | 43 +++++++++++++++---------- drivers/net/vxge/vxge-traffic.h | 2 +- 3 files changed, 64 insertions(+), 51 deletions(-) diff --git a/drivers/net/vxge/vxge-config.h b/drivers/net/vxge/vxge-config.h index 3c53aa732c9d..359b9b9f8041 100644 --- a/drivers/net/vxge/vxge-config.h +++ b/drivers/net/vxge/vxge-config.h @@ -412,44 +412,48 @@ struct vxge_hw_vp_config { * See also: struct vxge_hw_tim_intr_config{}. */ struct vxge_hw_device_config { - u32 dma_blockpool_initial; - u32 dma_blockpool_max; -#define VXGE_HW_MIN_DMA_BLOCK_POOL_SIZE 0 -#define VXGE_HW_INITIAL_DMA_BLOCK_POOL_SIZE 0 -#define VXGE_HW_INCR_DMA_BLOCK_POOL_SIZE 4 -#define VXGE_HW_MAX_DMA_BLOCK_POOL_SIZE 4096 - -#define VXGE_HW_MAX_PAYLOAD_SIZE_512 2 - - u32 intr_mode; -#define VXGE_HW_INTR_MODE_IRQLINE 0 -#define VXGE_HW_INTR_MODE_MSIX 1 -#define VXGE_HW_INTR_MODE_MSIX_ONE_SHOT 2 - -#define VXGE_HW_INTR_MODE_DEF 0 - - u32 rth_en; -#define VXGE_HW_RTH_DISABLE 0 -#define VXGE_HW_RTH_ENABLE 1 -#define VXGE_HW_RTH_DEFAULT 0 - - u32 rth_it_type; -#define VXGE_HW_RTH_IT_TYPE_SOLO_IT 0 -#define VXGE_HW_RTH_IT_TYPE_MULTI_IT 1 -#define VXGE_HW_RTH_IT_TYPE_DEFAULT 0 - - u32 rts_mac_en; + u32 device_poll_millis; +#define VXGE_HW_MIN_DEVICE_POLL_MILLIS 1 +#define VXGE_HW_MAX_DEVICE_POLL_MILLIS 100000 +#define VXGE_HW_DEF_DEVICE_POLL_MILLIS 1000 + + u32 dma_blockpool_initial; + u32 dma_blockpool_max; +#define VXGE_HW_MIN_DMA_BLOCK_POOL_SIZE 0 +#define VXGE_HW_INITIAL_DMA_BLOCK_POOL_SIZE 0 +#define VXGE_HW_INCR_DMA_BLOCK_POOL_SIZE 4 +#define VXGE_HW_MAX_DMA_BLOCK_POOL_SIZE 4096 + +#define VXGE_HW_MAX_PAYLOAD_SIZE_512 2 + + u32 intr_mode:2, +#define VXGE_HW_INTR_MODE_IRQLINE 0 +#define VXGE_HW_INTR_MODE_MSIX 1 +#define VXGE_HW_INTR_MODE_MSIX_ONE_SHOT 2 + +#define VXGE_HW_INTR_MODE_DEF 0 + + rth_en:1, +#define VXGE_HW_RTH_DISABLE 0 +#define VXGE_HW_RTH_ENABLE 1 +#define VXGE_HW_RTH_DEFAULT 0 + + rth_it_type:1, +#define VXGE_HW_RTH_IT_TYPE_SOLO_IT 0 +#define VXGE_HW_RTH_IT_TYPE_MULTI_IT 1 +#define VXGE_HW_RTH_IT_TYPE_DEFAULT 0 + + rts_mac_en:1, #define VXGE_HW_RTS_MAC_DISABLE 0 #define VXGE_HW_RTS_MAC_ENABLE 1 #define VXGE_HW_RTS_MAC_DEFAULT 0 - struct vxge_hw_vp_config vp_config[VXGE_HW_MAX_VIRTUAL_PATHS]; - - u32 device_poll_millis; -#define VXGE_HW_MIN_DEVICE_POLL_MILLIS 1 -#define VXGE_HW_MAX_DEVICE_POLL_MILLIS 100000 -#define VXGE_HW_DEF_DEVICE_POLL_MILLIS 1000 + hwts_en:1; +#define VXGE_HW_HWTS_DISABLE 0 +#define VXGE_HW_HWTS_ENABLE 1 +#define VXGE_HW_HWTS_DEFAULT 1 + struct vxge_hw_vp_config vp_config[VXGE_HW_MAX_VIRTUAL_PATHS]; }; /** diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index aff68c1118d4..d192dad8ff21 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -3112,8 +3112,7 @@ vxge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats) return net_stats; } -static enum vxge_hw_status vxge_timestamp_config(struct vxgedev *vdev, - int enable) +static enum vxge_hw_status vxge_timestamp_config(struct __vxge_hw_device *devh) { enum vxge_hw_status status; u64 val64; @@ -3123,27 +3122,24 @@ static enum vxge_hw_status vxge_timestamp_config(struct vxgedev *vdev, * required for the driver to load (due to a hardware bug), * there is no need to do anything special here. */ - if (enable) - val64 = VXGE_HW_XMAC_TIMESTAMP_EN | - VXGE_HW_XMAC_TIMESTAMP_USE_LINK_ID(0) | - VXGE_HW_XMAC_TIMESTAMP_INTERVAL(0); - else - val64 = 0; + val64 = VXGE_HW_XMAC_TIMESTAMP_EN | + VXGE_HW_XMAC_TIMESTAMP_USE_LINK_ID(0) | + VXGE_HW_XMAC_TIMESTAMP_INTERVAL(0); - status = vxge_hw_mgmt_reg_write(vdev->devh, + status = vxge_hw_mgmt_reg_write(devh, vxge_hw_mgmt_reg_type_mrpcim, 0, offsetof(struct vxge_hw_mrpcim_reg, xmac_timestamp), val64); - vxge_hw_device_flush_io(vdev->devh); + vxge_hw_device_flush_io(devh); + devh->config.hwts_en = VXGE_HW_HWTS_ENABLE; return status; } static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data) { struct hwtstamp_config config; - enum vxge_hw_status status; int i; if (copy_from_user(&config, data, sizeof(config))) @@ -3164,10 +3160,6 @@ static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data) switch (config.rx_filter) { case HWTSTAMP_FILTER_NONE: - status = vxge_timestamp_config(vdev, 0); - if (status != VXGE_HW_OK) - return -EFAULT; - vdev->rx_hwts = 0; config.rx_filter = HWTSTAMP_FILTER_NONE; break; @@ -3186,8 +3178,7 @@ static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data) case HWTSTAMP_FILTER_PTP_V2_EVENT: case HWTSTAMP_FILTER_PTP_V2_SYNC: case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - status = vxge_timestamp_config(vdev, 1); - if (status != VXGE_HW_OK) + if (vdev->devh->config.hwts_en != VXGE_HW_HWTS_ENABLE) return -EFAULT; vdev->rx_hwts = 1; @@ -4575,6 +4566,24 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) goto _exit4; } + /* Always enable HWTS. This will always cause the FCS to be invalid, + * due to the fact that HWTS is using the FCS as the location of the + * timestamp. The HW FCS checking will still correctly determine if + * there is a valid checksum, and the FCS is being removed by the driver + * anyway. So no fucntionality is being lost. Since it is always + * enabled, we now simply use the ioctl call to set whether or not the + * driver should be paying attention to the HWTS. + */ + if (is_privileged == VXGE_HW_OK) { + status = vxge_timestamp_config(hldev); + if (status != VXGE_HW_OK) { + vxge_debug_init(VXGE_ERR, "%s: HWTS enable failed", + VXGE_DRIVER_NAME); + ret = -EFAULT; + goto _exit4; + } + } + vxge_hw_device_debug_set(hldev, VXGE_ERR, VXGE_COMPONENT_LL); /* set private device info */ diff --git a/drivers/net/vxge/vxge-traffic.h b/drivers/net/vxge/vxge-traffic.h index 6c2fc0b72af5..4a518a3b131c 100644 --- a/drivers/net/vxge/vxge-traffic.h +++ b/drivers/net/vxge/vxge-traffic.h @@ -240,7 +240,7 @@ struct vxge_hw_tim_intr_config { u32 btimer_val; #define VXGE_HW_MIN_TIM_BTIMER_VAL 0 #define VXGE_HW_MAX_TIM_BTIMER_VAL 67108864 -#define VXGE_HW_USE_FLASH_DEFAULT 0xffffffff +#define VXGE_HW_USE_FLASH_DEFAULT (~0) u32 timer_ac_en; #define VXGE_HW_TIM_TIMER_AC_ENABLE 1 -- cgit v1.2.3-58-ga151 From 9f9b16458134ba9f06ef6f15369513aa9eebc81c Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Fri, 8 Apr 2011 11:11:22 +0000 Subject: vxge: spin-lock issue In vxge_hw_vpath_close, __vxge_hw_vp_terminate memsets the vpath which clobbers the spin lock state, then the driver attempts to acquire the spin lock. Resolve this by not zeroing the lock part of vpath struct, clean-up vpath locking in init, close, and fix locking hole in fw_api call. Issue found by Bob Picco Signed-off-by: Jon Mason Signed-off-by: David S. Miller --- drivers/net/vxge/vxge-config.c | 48 ++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c index 401bebf59502..32763b2dd73f 100644 --- a/drivers/net/vxge/vxge-config.c +++ b/drivers/net/vxge/vxge-config.c @@ -159,16 +159,15 @@ vxge_hw_vpath_fw_api(struct __vxge_hw_virtualpath *vpath, u32 action, u32 fw_memo, u32 offset, u64 *data0, u64 *data1, u64 *steer_ctrl) { - struct vxge_hw_vpath_reg __iomem *vp_reg; + struct vxge_hw_vpath_reg __iomem *vp_reg = vpath->vp_reg; enum vxge_hw_status status; u64 val64; - u32 retry = 0, max_retry = 100; - - vp_reg = vpath->vp_reg; + u32 retry = 0, max_retry = 3; - if (vpath->vp_open) { - max_retry = 3; - spin_lock(&vpath->lock); + spin_lock(&vpath->lock); + if (!vpath->vp_open) { + spin_unlock(&vpath->lock); + max_retry = 100; } writeq(*data0, &vp_reg->rts_access_steer_data0); @@ -1000,7 +999,7 @@ exit: /** * vxge_hw_device_hw_info_get - Get the hw information * Returns the vpath mask that has the bits set for each vpath allocated - * for the driver, FW version information and the first mac addresse for + * for the driver, FW version information, and the first mac address for * each vpath */ enum vxge_hw_status __devinit @@ -1064,9 +1063,10 @@ vxge_hw_device_hw_info_get(void __iomem *bar0, val64 = readq(&toc->toc_vpath_pointer[i]); + spin_lock_init(&vpath.lock); vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *) (bar0 + val64); - vpath.vp_open = 0; + vpath.vp_open = VXGE_HW_VP_NOT_OPEN; status = __vxge_hw_vpath_pci_func_mode_get(&vpath, hw_info); if (status != VXGE_HW_OK) @@ -1090,7 +1090,7 @@ vxge_hw_device_hw_info_get(void __iomem *bar0, val64 = readq(&toc->toc_vpath_pointer[i]); vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *) (bar0 + val64); - vpath.vp_open = 0; + vpath.vp_open = VXGE_HW_VP_NOT_OPEN; status = __vxge_hw_vpath_addr_get(&vpath, hw_info->mac_addrs[i], @@ -4646,7 +4646,27 @@ static void __vxge_hw_vp_terminate(struct __vxge_hw_device *hldev, u32 vp_id) vpath->hldev->tim_int_mask1, vpath->vp_id); hldev->stats.hw_dev_info_stats.vpath_info[vpath->vp_id] = NULL; - memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath)); + /* If the whole struct __vxge_hw_virtualpath is zeroed, nothing will + * work after the interface is brought down. + */ + spin_lock(&vpath->lock); + vpath->vp_open = VXGE_HW_VP_NOT_OPEN; + spin_unlock(&vpath->lock); + + vpath->vpmgmt_reg = NULL; + vpath->nofl_db = NULL; + vpath->max_mtu = 0; + vpath->vsport_number = 0; + vpath->max_kdfc_db = 0; + vpath->max_nofl_db = 0; + vpath->ringh = NULL; + vpath->fifoh = NULL; + memset(&vpath->vpath_handles, 0, sizeof(struct list_head)); + vpath->stats_block = 0; + vpath->hw_stats = NULL; + vpath->hw_stats_sav = NULL; + vpath->sw_stats = NULL; + exit: return; } @@ -4670,7 +4690,7 @@ __vxge_hw_vp_initialize(struct __vxge_hw_device *hldev, u32 vp_id, vpath = &hldev->virtual_paths[vp_id]; - spin_lock_init(&hldev->virtual_paths[vp_id].lock); + spin_lock_init(&vpath->lock); vpath->vp_id = vp_id; vpath->vp_open = VXGE_HW_VP_OPEN; vpath->hldev = hldev; @@ -5019,10 +5039,6 @@ enum vxge_hw_status vxge_hw_vpath_close(struct __vxge_hw_vpath_handle *vp) __vxge_hw_vp_terminate(devh, vp_id); - spin_lock(&vpath->lock); - vpath->vp_open = VXGE_HW_VP_NOT_OPEN; - spin_unlock(&vpath->lock); - vpath_close_exit: return status; } -- cgit v1.2.3-58-ga151 From 6ba1037c3d871ab70e342631516dbf841c35b086 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Fri, 8 Apr 2011 11:11:23 +0000 Subject: vxge: update driver version Update vxge driver version to 2.5.3 Signed-off-by: Jon Mason Signed-off-by: David S. Miller --- drivers/net/vxge/vxge-version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/vxge/vxge-version.h b/drivers/net/vxge/vxge-version.h index 581e21525e85..b9efa28bab3e 100644 --- a/drivers/net/vxge/vxge-version.h +++ b/drivers/net/vxge/vxge-version.h @@ -16,8 +16,8 @@ #define VXGE_VERSION_MAJOR "2" #define VXGE_VERSION_MINOR "5" -#define VXGE_VERSION_FIX "2" -#define VXGE_VERSION_BUILD "22259" +#define VXGE_VERSION_FIX "3" +#define VXGE_VERSION_BUILD "22640" #define VXGE_VERSION_FOR "k" #define VXGE_FW_VER(maj, min, bld) (((maj) << 16) + ((min) << 8) + (bld)) -- cgit v1.2.3-58-ga151 From 143780c6562080c1117cd9197ee1b33c0d838376 Mon Sep 17 00:00:00 2001 From: "Allan, Bruce W" Date: Mon, 11 Apr 2011 13:01:59 +0000 Subject: ethtool: time to blink provided in seconds not jiffies When blinking for a duration set by the user, the value specified is in seconds but it is used as the number of jiffies in the timeout after which the Physical ID indicator is deactivated. Fix by converting the timeout to seconds. Signed-off-by: Bruce Allan Acked-by: Ben Hutchings Signed-off-by: David S. Miller --- net/core/ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 704e176ad3a9..43ef09fedd6e 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1653,7 +1653,7 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) if (rc == 0) { /* Driver will handle this itself */ schedule_timeout_interruptible( - id.data ? id.data : MAX_SCHEDULE_TIMEOUT); + id.data ? (id.data * HZ) : MAX_SCHEDULE_TIMEOUT); } else { /* Driver expects to be called periodically */ do { -- cgit v1.2.3-58-ga151 From e8306f989483e4b97a8b37dd268de6c8c6f35e75 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Wed, 6 Apr 2011 11:41:10 +0530 Subject: mac80211: Check for queued frames before entering power save. In a highly noisy environment, the tx rate of the driver drops and the application slows down since it has not yet received ACKs for the frames already queued in the hardware. Since this ACK may take more than 100ms, stopping the dev queues for entering PS at this stage breaks applications, WMM test cases in my testing. If there are frames already pending in the tx queue, postponing the PS logic helps to avoid redundant queue stops. When power save is enabled by default and in a noisy environment, this API certainly helps in improving the average throughput. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- include/net/mac80211.h | 4 ++++ net/mac80211/driver-ops.h | 13 +++++++++++++ net/mac80211/driver-trace.h | 20 ++++++++++++++++++++ net/mac80211/mlme.c | 17 +++++++++-------- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 965f1b16e53a..361bc5d85b1a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1819,6 +1819,9 @@ enum ieee80211_ampdu_mlme_action { * @set_ringparam: Set tx and rx ring sizes. * * @get_ringparam: Get tx and rx ring current and maximum sizes. + * + * @tx_frames_pending: Check if there is any pending frame in the hardware + * queues before entering power save. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); @@ -1906,6 +1909,7 @@ struct ieee80211_ops { int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx); void (*get_ringparam)(struct ieee80211_hw *hw, u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); + bool (*tx_frames_pending)(struct ieee80211_hw *hw); }; /** diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 9c0d62bb0ea3..00a0685f2403 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -552,4 +552,17 @@ static inline void drv_get_ringparam(struct ieee80211_local *local, trace_drv_return_void(local); } +static inline bool drv_tx_frames_pending(struct ieee80211_local *local) +{ + bool ret = false; + + might_sleep(); + + trace_drv_tx_frames_pending(local); + if (local->ops->tx_frames_pending) + ret = local->ops->tx_frames_pending(&local->hw); + trace_drv_return_bool(local, ret); + + return ret; +} #endif /* __MAC80211_DRIVER_OPS */ diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 45aab80738e2..c8c934d48b7a 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -74,6 +74,21 @@ TRACE_EVENT(drv_return_int, TP_printk(LOCAL_PR_FMT " - %d", LOCAL_PR_ARG, __entry->ret) ); +TRACE_EVENT(drv_return_bool, + TP_PROTO(struct ieee80211_local *local, bool ret), + TP_ARGS(local, ret), + TP_STRUCT__entry( + LOCAL_ENTRY + __field(bool, ret) + ), + TP_fast_assign( + LOCAL_ASSIGN; + __entry->ret = ret; + ), + TP_printk(LOCAL_PR_FMT " - %s", LOCAL_PR_ARG, (__entry->ret) ? + "true" : "false") +); + TRACE_EVENT(drv_return_u64, TP_PROTO(struct ieee80211_local *local, u64 ret), TP_ARGS(local, ret), @@ -964,6 +979,11 @@ TRACE_EVENT(drv_get_ringparam, ) ); +DEFINE_EVENT(local_only_evt, drv_tx_frames_pending, + TP_PROTO(struct ieee80211_local *local), + TP_ARGS(local) +); + DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait, TP_PROTO(struct ieee80211_local *local), TP_ARGS(local) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 865fed4cc18b..a41f234bd486 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -761,15 +761,16 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { netif_tx_stop_all_queues(sdata->dev); - /* - * Flush all the frames queued in the driver before - * going to power save - */ - drv_flush(local, false); - ieee80211_send_nullfunc(local, sdata, 1); - /* Flush once again to get the tx status of nullfunc frame */ - drv_flush(local, false); + if (drv_tx_frames_pending(local)) + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies( + local->hw.conf.dynamic_ps_timeout)); + else { + ieee80211_send_nullfunc(local, sdata, 1); + /* Flush to get the tx status of nullfunc frame */ + drv_flush(local, false); + } } if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) && -- cgit v1.2.3-58-ga151 From 15b91e830dbf300d653b3fe70f6ef71b568164a3 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Wed, 6 Apr 2011 11:41:11 +0530 Subject: ath9k: Implement dev_tx_frames_pending callback. This function returns true if there is atleast one frame in any one of the tx queues. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index ba1c9a684eff..93b9fa2cbaf8 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2201,6 +2201,21 @@ out: ath9k_ps_restore(sc); } +static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) +{ + struct ath_softc *sc = hw->priv; + int i; + + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { + if (!ATH_TXQ_SETUP(sc, i)) + continue; + + if (ath9k_has_pending_frames(sc, &sc->tx.txq[i])) + return true; + } + return false; +} + struct ieee80211_ops ath9k_ops = { .tx = ath9k_tx, .start = ath9k_start, @@ -2223,4 +2238,5 @@ struct ieee80211_ops ath9k_ops = { .rfkill_poll = ath9k_rfkill_poll_state, .set_coverage_class = ath9k_set_coverage_class, .flush = ath9k_flush, + .tx_frames_pending = ath9k_tx_frames_pending, }; -- cgit v1.2.3-58-ga151 From d88525e8fdc00c0078d38353caffc29e5a9c70cc Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Wed, 6 Apr 2011 21:42:52 +0530 Subject: ath9k_hw: Fix instable target power control b/w CCK/OFDM The problem is that when the attenuation is increased, the rate will start to drop from MCS7 -> MCS6, and finally will see MCS1 -> CCK_11Mbps. When the rate is changed b/w CCK and OFDM, it will use register desired_scale to calculate how much tx gain need to change. The output power with the same tx gain for CCK and OFDM modulated signals are different. This difference is constant for AR9280 but not AR9285/AR9271. It has different PA architecture a constant. So it should be calibrated against this PA characteristic. The driver has to read the calibrated values from EEPROM and set the tx power registers accordingly. Signed-off-by: Rajkumar Manoharan Acked-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_phy.h | 6 ++++++ drivers/net/wireless/ath/ath9k/eeprom.h | 6 +++++- drivers/net/wireless/ath/ath9k/eeprom_4k.c | 26 ++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index 37663dbbcf57..47780ef1c892 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h @@ -483,7 +483,11 @@ #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 +#define AR_PHY_TX_PWRCTRL8 0xa278 + #define AR_PHY_TX_PWRCTRL9 0xa27C + +#define AR_PHY_TX_PWRCTRL10 0xa394 #define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 #define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 @@ -495,6 +499,8 @@ #define AR_PHY_CH0_TX_PWRCTRL11 0xa398 #define AR_PHY_CH1_TX_PWRCTRL11 0xb398 +#define AR_PHY_CH0_TX_PWRCTRL12 0xa3dc +#define AR_PHY_CH0_TX_PWRCTRL13 0xa3e0 #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00 #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index bd82447f5b78..3e316133f114 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -436,7 +436,11 @@ struct modal_eep_4k_header { u8 db2_2:4, db2_3:4; u8 db2_4:4, reserved:4; #endif - u8 futureModal[4]; + u8 tx_diversity; + u8 flc_pwr_thresh; + u8 bb_scale_smrt_antenna; +#define EEP_4K_BB_DESIRED_SCALE_MASK 0x1f + u8 futureModal[1]; struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS]; } __packed; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index bc77a308c901..6f714dd72365 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -781,6 +781,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, { struct modal_eep_4k_header *pModal; struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; + struct base_eep_header_4k *pBase = &eep->baseEepHeader; u8 txRxAttenLocal; u8 ob[5], db1[5], db2[5]; u8 ant_div_control1, ant_div_control2; @@ -1003,6 +1004,31 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); } + if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) { + u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna & + EEP_4K_BB_DESIRED_SCALE_MASK); + if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) { + u32 pwrctrl, mask, clr; + + mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25); + pwrctrl = mask * bb_desired_scale; + clr = mask * 0x1f; + REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); + REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); + REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); + + mask = BIT(0)|BIT(5)|BIT(15); + pwrctrl = mask * bb_desired_scale; + clr = mask * 0x1f; + REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr); + + mask = BIT(0)|BIT(5); + pwrctrl = mask * bb_desired_scale; + clr = mask * 0x1f; + REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); + REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); + } + } } static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) -- cgit v1.2.3-58-ga151 From 18bf965702058f5f8039e6a46bb5ebaa18d38ebd Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Wed, 6 Apr 2011 16:46:55 -0700 Subject: mwifiex: fix cmd_skb headroom decreasing issue Before calling host_to_card() to send the cmd to firmware, we use skb_push() to add 4 bytes SDIO interface header at the start of the data buffer. Since cmd_skb data structure will be re-used at a later time, we need to restore its headroom by removing the 4 bytes header. Signed-off-by: Bing Zhao Signed-off-by: Marc Yang Signed-off-by: Yogesh Ashok Powar Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cmdevt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index a9aeb31af455..8676480ead94 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -206,6 +206,8 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, cmd_node->cmd_skb->data, cmd_node->cmd_skb->len, NULL); + skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN); + if (ret == -1) { dev_err(adapter->dev, "DNLD_CMD: host to card failed\n"); if (wait_queue) -- cgit v1.2.3-58-ga151 From 6a35a0ac5771fa962c45926678d1f194cbc98c4e Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Wed, 6 Apr 2011 16:46:56 -0700 Subject: mwifiex: use common keyinfo bitmap for different key types Instead of having separate key information definitions for each type of key, a common key information bitmap is used. Signed-off-by: Yogesh Ashok Powar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/fw.h | 27 +++------------------------ drivers/net/wireless/mwifiex/sta_cmd.c | 27 +++++++++++++-------------- drivers/net/wireless/mwifiex/sta_cmdresp.c | 3 +-- drivers/net/wireless/mwifiex/sta_ioctl.c | 3 +-- 4 files changed, 18 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 2b938115b26a..f8c008f8f476 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -72,33 +72,12 @@ enum KEY_TYPE_ID { KEY_TYPE_ID_AES, KEY_TYPE_ID_WAPI, }; - -enum KEY_INFO_WEP { - KEY_INFO_WEP_MCAST = 0x01, - KEY_INFO_WEP_UNICAST = 0x02, - KEY_INFO_WEP_ENABLED = 0x04 -}; - -enum KEY_INFO_TKIP { - KEY_INFO_TKIP_MCAST = 0x01, - KEY_INFO_TKIP_UNICAST = 0x02, - KEY_INFO_TKIP_ENABLED = 0x04 -}; - -enum KEY_INFO_AES { - KEY_INFO_AES_MCAST = 0x01, - KEY_INFO_AES_UNICAST = 0x02, - KEY_INFO_AES_ENABLED = 0x04 -}; +#define KEY_MCAST BIT(0) +#define KEY_UNICAST BIT(1) +#define KEY_ENABLED BIT(2) #define WAPI_KEY_LEN 50 -enum KEY_INFO_WAPI { - KEY_INFO_WAPI_MCAST = 0x01, - KEY_INFO_WAPI_UNICAST = 0x02, - KEY_INFO_WAPI_ENABLED = 0x04 -}; - #define MAX_POLL_TRIES 100 #define MAX_MULTI_INTERFACE_POLL_TRIES 1000 diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 6fff26153e26..19de6524d428 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -500,9 +500,8 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv, key_param_set->key_type_id = cpu_to_le16(KEY_TYPE_ID_WEP); key_param_set->key_info = - cpu_to_le16(KEY_INFO_WEP_ENABLED | - KEY_INFO_WEP_UNICAST | - KEY_INFO_WEP_MCAST); + cpu_to_le16(KEY_ENABLED | KEY_UNICAST | + KEY_MCAST); key_param_set->key_len = cpu_to_le16(priv->wep_key[i].key_length); /* Set WEP key index */ @@ -589,10 +588,10 @@ static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, cpu_to_le16(KEY_TYPE_ID_WAPI); if (cmd_oid == KEY_INFO_ENABLED) key_material->key_param_set.key_info = - cpu_to_le16(KEY_INFO_WAPI_ENABLED); + cpu_to_le16(KEY_ENABLED); else key_material->key_param_set.key_info = - cpu_to_le16(!KEY_INFO_WAPI_ENABLED); + cpu_to_le16(!KEY_ENABLED); key_material->key_param_set.key[0] = enc_key->key_index; if (!priv->sec_info.wapi_key_on) @@ -604,10 +603,10 @@ static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, if (0 != memcmp(enc_key->mac_addr, bc_mac, sizeof(bc_mac))) { /* WAPI pairwise key: unicast */ key_material->key_param_set.key_info |= - cpu_to_le16(KEY_INFO_WAPI_UNICAST); + cpu_to_le16(KEY_UNICAST); } else { /* WAPI group key: multicast */ key_material->key_param_set.key_info |= - cpu_to_le16(KEY_INFO_WAPI_MCAST); + cpu_to_le16(KEY_MCAST); priv->sec_info.wapi_key_on = true; } @@ -634,32 +633,32 @@ static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, cpu_to_le16(KEY_TYPE_ID_AES); if (cmd_oid == KEY_INFO_ENABLED) key_material->key_param_set.key_info = - cpu_to_le16(KEY_INFO_AES_ENABLED); + cpu_to_le16(KEY_ENABLED); else key_material->key_param_set.key_info = - cpu_to_le16(!KEY_INFO_AES_ENABLED); + cpu_to_le16(!KEY_ENABLED); if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) /* AES pairwise key: unicast */ key_material->key_param_set.key_info |= - cpu_to_le16(KEY_INFO_AES_UNICAST); + cpu_to_le16(KEY_UNICAST); else /* AES group key: multicast */ key_material->key_param_set.key_info |= - cpu_to_le16(KEY_INFO_AES_MCAST); + cpu_to_le16(KEY_MCAST); } else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) { dev_dbg(priv->adapter->dev, "cmd: WPA_TKIP\n"); key_material->key_param_set.key_type_id = cpu_to_le16(KEY_TYPE_ID_TKIP); key_material->key_param_set.key_info = - cpu_to_le16(KEY_INFO_TKIP_ENABLED); + cpu_to_le16(KEY_ENABLED); if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) /* TKIP pairwise key: unicast */ key_material->key_param_set.key_info |= - cpu_to_le16(KEY_INFO_TKIP_UNICAST); + cpu_to_le16(KEY_UNICAST); else /* TKIP group key: multicast */ key_material->key_param_set.key_info |= - cpu_to_le16(KEY_INFO_TKIP_MCAST); + cpu_to_le16(KEY_MCAST); } if (key_material->key_param_set.key_type_id) { diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 74add45b99b6..648df690f5d1 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -574,8 +574,7 @@ static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv, &resp->params.key_material; if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) { - if ((le16_to_cpu(key->key_param_set.key_info) & - KEY_INFO_TKIP_MCAST)) { + if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) { dev_dbg(priv->adapter->dev, "info: key: GTK is set\n"); priv->wpa_is_gtk_set = true; priv->scan_block = false; diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index b163507b1fe0..2fcdbc224e08 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -1729,8 +1729,7 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter, sizeof(ibss_key->key_param_set.key_len)); ibss_key->key_param_set.key_type_id = cpu_to_le16(KEY_TYPE_ID_TKIP); - ibss_key->key_param_set.key_info - = cpu_to_le16(KEY_INFO_TKIP_ENABLED); + ibss_key->key_param_set.key_info = cpu_to_le16(KEY_ENABLED); /* Send the key as GTK to firmware */ encrypt_key->key_index = ~MWIFIEX_KEY_INDEX_UNICAST; -- cgit v1.2.3-58-ga151 From 264bbec811024e39fe8f9e7a45743f81f373529e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 7 Apr 2011 19:24:23 +0200 Subject: ath9k: fix PS-Poll reception on AR9160 and earlier I can't find any valid reason for not setting the ATH9K_RX_FILTER_PSPOLL flag on older hardware and neither the documentation nor the reference code mention any reason for excluding older hardware here. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 3842b7518661..ef198ae71eb7 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -426,9 +426,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) else rfilt |= ATH9K_RX_FILTER_BEACON; - if ((AR_SREV_9280_20_OR_LATER(sc->sc_ah) || - AR_SREV_9285_12_OR_LATER(sc->sc_ah)) && - (sc->sc_ah->opmode == NL80211_IFTYPE_AP) && + if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || (sc->rx.rxfilter & FIF_PSPOLL)) rfilt |= ATH9K_RX_FILTER_PSPOLL; -- cgit v1.2.3-58-ga151 From 952949738aba19f84dae9def18e0baa58f0ce0b8 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 7 Apr 2011 19:30:32 +0200 Subject: ath9k: fix too early enabling of rx during ath_startrecv() rx should only be enabled after enough rx buffers have been given to the hardware, however ath_rx_buf_link was calling ath9k_hw_rxena after every single added buffer. Fix this by calling ath9k_hw_rxena directly from the rx tasklet after completion instead. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ef198ae71eb7..b81bfc4d66ef 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -75,7 +75,6 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) *sc->rx.rxlink = bf->bf_daddr; sc->rx.rxlink = &ds->ds_link; - ath9k_hw_rxena(ah); } static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) @@ -1765,6 +1764,7 @@ requeue: } else { list_move_tail(&bf->list, &sc->rx.rxbuf); ath_rx_buf_link(sc, bf); + ath9k_hw_rxena(ah); } } while (1); -- cgit v1.2.3-58-ga151 From a22e93f5d819f11d2a2d6332e20ff5b462e5c208 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Thu, 7 Apr 2011 20:40:32 +0200 Subject: iwl4965: drop a lone pr_err() iwl4965_rate_control_register() prints a message at KERN_ERR level. It looks like it's just a debugging message, so pr_err() seems to be overdone. But none of the similar functions in drivers/net/wireless print a message, so let's just drop it. Signed-off-by: Paul Bolle Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-4965-rs.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c index 31ac672b64e1..89509392ef5d 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c @@ -2860,7 +2860,6 @@ static struct rate_control_ops rs_4965_ops = { int iwl4965_rate_control_register(void) { - pr_err("Registering 4965 rate control operations\n"); return ieee80211_rate_control_register(&rs_4965_ops); } -- cgit v1.2.3-58-ga151 From 581a8b0feeed8877aab3a8ca4c972419790cd07f Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Thu, 7 Apr 2011 15:08:27 -0700 Subject: nl80211: rename NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE To NL80211_MESH_SETUP_IE. This reflects our ability to insert any ie into a mesh beacon, not simply path selection ies. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- include/linux/nl80211.h | 9 +++++---- include/net/cfg80211.h | 8 ++++---- net/mac80211/cfg.c | 15 +++++++-------- net/mac80211/ieee80211_i.h | 4 ++-- net/mac80211/mesh.c | 6 +++--- net/mac80211/mesh_plink.c | 2 +- net/mac80211/tx.c | 2 +- net/wireless/mesh.c | 4 ++-- net/wireless/nl80211.c | 11 ++++++----- 9 files changed, 31 insertions(+), 30 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 16eea7229e99..ecf6b68a96da 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -545,6 +545,7 @@ enum nl80211_commands { /* source-level API compatibility */ #define NL80211_CMD_GET_MESH_PARAMS NL80211_CMD_GET_MESH_CONFIG #define NL80211_CMD_SET_MESH_PARAMS NL80211_CMD_SET_MESH_CONFIG +#define NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE NL80211_MESH_SETUP_IE /** * enum nl80211_attrs - nl80211 netlink attributes @@ -1719,9 +1720,9 @@ enum nl80211_meshconf_params { * vendor specific path metric or disable it to use the default Airtime * metric. * - * @NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE: A vendor specific information - * element that vendors will use to identify the path selection methods and - * metrics in use. + * @NL80211_MESH_SETUP_IE: Information elements for this mesh, for instance, a + * robust security network ie, or a vendor specific information element that + * vendors will use to identify the path selection methods and metrics in use. * * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use @@ -1730,7 +1731,7 @@ enum nl80211_mesh_setup_params { __NL80211_MESH_SETUP_INVALID, NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL, NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC, - NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE, + NL80211_MESH_SETUP_IE, /* keep last */ __NL80211_MESH_SETUP_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index ba7384acf4e0..1d02ddf5a8a3 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -689,8 +689,8 @@ struct mesh_config { * @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes * @path_sel_proto: which path selection protocol to use * @path_metric: which metric to use - * @vendor_ie: vendor information elements (optional) - * @vendor_ie_len: length of vendor information elements + * @ie: vendor information elements (optional) + * @ie_len: length of vendor information elements * * These parameters are fixed when the mesh is created. */ @@ -699,8 +699,8 @@ struct mesh_setup { u8 mesh_id_len; u8 path_sel_proto; u8 path_metric; - const u8 *vendor_ie; - u8 vendor_ie_len; + const u8 *ie; + u8 ie_len; }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index bf5d28da46e6..d9428afd8bf6 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1034,26 +1034,25 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, u8 *new_ie; const u8 *old_ie; - /* first allocate the new vendor information element */ + /* allocate information elements */ new_ie = NULL; - old_ie = ifmsh->vendor_ie; + old_ie = ifmsh->ie; - ifmsh->vendor_ie_len = setup->vendor_ie_len; - if (setup->vendor_ie_len) { - new_ie = kmemdup(setup->vendor_ie, setup->vendor_ie_len, + if (setup->ie_len) { + new_ie = kmemdup(setup->ie, setup->ie_len, GFP_KERNEL); if (!new_ie) return -ENOMEM; } + ifmsh->ie_len = setup->ie_len; + ifmsh->ie = new_ie; + kfree(old_ie); /* now copy the rest of the setup parameters */ ifmsh->mesh_id_len = setup->mesh_id_len; memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); ifmsh->mesh_pp_id = setup->path_sel_proto; ifmsh->mesh_pm_id = setup->path_metric; - ifmsh->vendor_ie = new_ie; - - kfree(old_ie); return 0; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6eb2c8523eeb..6450100594ba 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -488,8 +488,8 @@ struct ieee80211_if_mesh { struct mesh_config mshcfg; u32 mesh_seqnum; bool accepting_plinks; - const u8 *vendor_ie; - u8 vendor_ie_len; + const u8 *ie; + u8 ie_len; }; #ifdef CONFIG_MAC80211_MESH diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 2a57cc02c618..1c244c0c7664 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -279,9 +279,9 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; *pos++ = 0x00; - if (sdata->u.mesh.vendor_ie) { - int len = sdata->u.mesh.vendor_ie_len; - const u8 *data = sdata->u.mesh.vendor_ie; + if (sdata->u.mesh.ie) { + int len = sdata->u.mesh.ie_len; + const u8 *data = sdata->u.mesh.ie; if (skb_tailroom(skb) > len) memcpy(skb_put(skb, len), data, len); } diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 44b53931ba5e..c705b20e1acb 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -161,7 +161,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, __le16 reason) { struct ieee80211_local *local = sdata->local; struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + - sdata->u.mesh.vendor_ie_len); + sdata->u.mesh.ie_len); struct ieee80211_mgmt *mgmt; bool include_plid = false; static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ce4596ed1268..17b10be31f55 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2262,7 +2262,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, /* headroom, head length, tail length and maximum TIM length */ skb = dev_alloc_skb(local->tx_headroom + 400 + - sdata->u.mesh.vendor_ie_len); + sdata->u.mesh.ie_len); if (!skb) goto out; diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 73e39c171ffb..0d4b2260f96f 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -53,8 +53,8 @@ const struct mesh_config default_mesh_config = { const struct mesh_setup default_mesh_setup = { .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, .path_metric = IEEE80211_PATH_METRIC_AIRTIME, - .vendor_ie = NULL, - .vendor_ie_len = 0, + .ie = NULL, + .ie_len = 0, }; int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 297d7ce4117b..ccd825a5857e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2823,7 +2823,7 @@ static const struct nla_policy nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = { [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, - [NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE] = { .type = NLA_BINARY, + [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, }; @@ -2925,13 +2925,14 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, IEEE80211_PATH_METRIC_VENDOR : IEEE80211_PATH_METRIC_AIRTIME; - if (tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]) { + + if (tb[NL80211_MESH_SETUP_IE]) { struct nlattr *ieattr = - tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]; + tb[NL80211_MESH_SETUP_IE]; if (!is_valid_ie_attr(ieattr)) return -EINVAL; - setup->vendor_ie = nla_data(ieattr); - setup->vendor_ie_len = nla_len(ieattr); + setup->ie = nla_data(ieattr); + setup->ie_len = nla_len(ieattr); } return 0; -- cgit v1.2.3-58-ga151 From 15d5dda623139bbf6165030fc251bbd5798f4130 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Thu, 7 Apr 2011 15:08:28 -0700 Subject: cfg80211/nl80211: Add userspace authentication flag to mesh setup During mesh setup, use NL80211_MESH_SETUP_USERSPACE_AUTH flag to create a secure mesh and route management frames to userspace. Also, NL80211_CMD_GET_WIPHY now returns a flag NL80211_SUPPORT_MESH_AUTH if the wiphy's mesh implementation supports routing of mesh auth frames to userspace. This is useful for forward compatibility between old kernels and new userspace tools. Signed-off-by: Javier Cardona Signed-off-by: Thomas Pedersen Signed-off-by: John W. Linville --- include/linux/nl80211.h | 9 +++++++++ include/net/cfg80211.h | 5 +++++ net/wireless/mesh.c | 4 ++++ net/wireless/nl80211.c | 5 +++++ 4 files changed, 23 insertions(+) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index ecf6b68a96da..0e652d860819 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -887,6 +887,9 @@ enum nl80211_commands { * changed once the mesh is active. * @NL80211_ATTR_MESH_CONFIG: Mesh configuration parameters, a nested attribute * containing attributes from &enum nl80211_meshconf_params. + * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver + * allows auth frames in a mesh to be passed to userspace for processing via + * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -1075,6 +1078,8 @@ enum nl80211_attrs { NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, + NL80211_ATTR_SUPPORT_MESH_AUTH, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1724,6 +1729,9 @@ enum nl80211_meshconf_params { * robust security network ie, or a vendor specific information element that * vendors will use to identify the path selection methods and metrics in use. * + * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication + * daemon will be authenticating mesh candidates. + * * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use */ @@ -1732,6 +1740,7 @@ enum nl80211_mesh_setup_params { NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL, NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC, NL80211_MESH_SETUP_IE, + NL80211_MESH_SETUP_USERSPACE_AUTH, /* keep last */ __NL80211_MESH_SETUP_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 1d02ddf5a8a3..e77603bd1630 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -691,6 +691,7 @@ struct mesh_config { * @path_metric: which metric to use * @ie: vendor information elements (optional) * @ie_len: length of vendor information elements + * @is_secure: or not * * These parameters are fixed when the mesh is created. */ @@ -701,6 +702,7 @@ struct mesh_setup { u8 path_metric; const u8 *ie; u8 ie_len; + bool is_secure; }; /** @@ -1451,6 +1453,8 @@ struct cfg80211_ops { * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN. * @WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS: The device supports separate * unicast and multicast TX keys. + * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing + * auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH. */ enum wiphy_flags { WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), @@ -1463,6 +1467,7 @@ enum wiphy_flags { WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), WIPHY_FLAG_IBSS_RSN = BIT(8), WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS= BIT(9), + WIPHY_FLAG_MESH_AUTH = BIT(10), }; struct mac_address { diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 0d4b2260f96f..0e5c122ce324 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -72,6 +72,10 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) return -EOPNOTSUPP; + if (!(rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && + setup->is_secure) + return -EOPNOTSUPP; + if (wdev->mesh_id_len) return -EALREADY; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index ccd825a5857e..cbedfc2a42a2 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -124,6 +124,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 }, [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED }, + [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG }, [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, .len = NL80211_HT_CAPABILITY_LEN }, @@ -594,6 +595,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN); + if (dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) + NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_MESH_AUTH); NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, sizeof(u32) * dev->wiphy.n_cipher_suites, @@ -2823,6 +2826,7 @@ static const struct nla_policy nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = { [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, + [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, }; @@ -2934,6 +2938,7 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, setup->ie = nla_data(ieattr); setup->ie_len = nla_len(ieattr); } + setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]); return 0; } -- cgit v1.2.3-58-ga151 From 5cff5e01e818029a5d2c3c31b7ae5e5e7ee70452 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Thu, 7 Apr 2011 15:08:29 -0700 Subject: mac80211: ignore peers if security is enabled for this mesh Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 1 + net/mac80211/ieee80211_i.h | 1 + net/mac80211/mesh.c | 4 ++++ net/mac80211/mesh_plink.c | 4 ++++ net/wireless/mesh.c | 1 + 5 files changed, 11 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d9428afd8bf6..dc623d884d02 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1053,6 +1053,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); ifmsh->mesh_pp_id = setup->path_sel_proto; ifmsh->mesh_pm_id = setup->path_metric; + ifmsh->is_secure = setup->is_secure; return 0; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6450100594ba..8d6d6e3d95da 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -490,6 +490,7 @@ struct ieee80211_if_mesh { bool accepting_plinks; const u8 *ie; u8 ie_len; + bool is_secure; }; #ifdef CONFIG_MAC80211_MESH diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 1c244c0c7664..47a26c0f6993 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -573,6 +573,10 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, &elems); + /* ignore beacons from secure mesh peers if our security is off */ + if (elems.rsn_len && !sdata->u.mesh.is_secure) + return; + if (elems.ds_params && elems.ds_params_len == 1) freq = ieee80211_channel_to_frequency(elems.ds_params[0], band); else diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index c705b20e1acb..bafe25594e09 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -449,6 +449,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m mpl_dbg("Mesh plink: missing necessary peer link ie\n"); return; } + if (elems.rsn_len && !sdata->u.mesh.is_secure) { + mpl_dbg("Mesh plink: can't establish link with secure peer\n"); + return; + } ftype = mgmt->u.action.u.plink_action.action_code; ie_len = elems.peer_link_len; diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 0e5c122ce324..e0226e8265a3 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -55,6 +55,7 @@ const struct mesh_setup default_mesh_setup = { .path_metric = IEEE80211_PATH_METRIC_AIRTIME, .ie = NULL, .ie_len = 0, + .is_secure = false, }; int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, -- cgit v1.2.3-58-ga151 From b39c48fac1fc915a5dcd024bf6e9aabc855ed591 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Thu, 7 Apr 2011 15:08:30 -0700 Subject: nl80211/mac80211: let userspace authenticate stations Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- include/linux/nl80211.h | 2 ++ net/mac80211/cfg.c | 6 ++++++ net/wireless/nl80211.c | 5 ++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 0e652d860819..5ec4ac3a0ef4 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1174,6 +1174,7 @@ enum nl80211_iftype { * with short barker preamble * @NL80211_STA_FLAG_WME: station is WME/QoS capable * @NL80211_STA_FLAG_MFP: station uses management frame protection + * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated * @NL80211_STA_FLAG_MAX: highest station flag number currently defined * @__NL80211_STA_FLAG_AFTER_LAST: internal use */ @@ -1183,6 +1184,7 @@ enum nl80211_sta_flags { NL80211_STA_FLAG_SHORT_PREAMBLE, NL80211_STA_FLAG_WME, NL80211_STA_FLAG_MFP, + NL80211_STA_FLAG_AUTHENTICATED, /* keep last */ __NL80211_STA_FLAG_AFTER_LAST, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index dc623d884d02..1c25723eacda 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -686,6 +686,12 @@ static void sta_apply_parameters(struct ieee80211_local *local, if (set & BIT(NL80211_STA_FLAG_MFP)) sta->flags |= WLAN_STA_MFP; } + + if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { + sta->flags &= ~WLAN_STA_AUTH; + if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) + sta->flags |= WLAN_STA_AUTH; + } spin_unlock_irqrestore(&sta->flaglock, flags); /* diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index cbedfc2a42a2..ce29a0d0e88e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1925,6 +1925,7 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG }, [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG }, + [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG }, }; static int parse_station_flags(struct genl_info *info, @@ -2284,7 +2285,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) err = -EINVAL; if (params.supported_rates) err = -EINVAL; - if (params.sta_flags_mask) + if (params.sta_flags_mask & + ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | + BIT(NL80211_STA_FLAG_AUTHORIZED))) err = -EINVAL; break; default: -- cgit v1.2.3-58-ga151 From 71839121a0f35f9968d2e204a76eb22683156fd8 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Thu, 7 Apr 2011 15:08:31 -0700 Subject: mac80211: Let user space receive and send mesh auth/deauth frames Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/mac80211/main.c | 4 +++- net/mac80211/rx.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index dc50fc3153e5..e2db3dc23953 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -545,7 +545,9 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { }, [NL80211_IFTYPE_MESH_POINT] = { .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4), }, }; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fc2ff78582ca..359fc394a3b0 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -502,7 +502,8 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) if (ieee80211_is_probe_req(hdr->frame_control) || ieee80211_is_probe_resp(hdr->frame_control) || - ieee80211_is_beacon(hdr->frame_control)) + ieee80211_is_beacon(hdr->frame_control) || + ieee80211_is_auth(hdr->frame_control)) return RX_CONTINUE; return RX_DROP_MONITOR; -- cgit v1.2.3-58-ga151 From 53e805111b69d55834f4e1ed0a31a97ea0b9e425 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Thu, 7 Apr 2011 15:08:32 -0700 Subject: mac80211: ignore peer link requests from unauthenticated stations. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/mac80211/mesh_plink.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index bafe25594e09..5d0dd9217e5f 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -372,6 +372,9 @@ int mesh_plink_open(struct sta_info *sta) __le16 llid; struct ieee80211_sub_if_data *sdata = sta->sdata; + if (!test_sta_flags(sta, WLAN_STA_AUTH)) + return -EPERM; + spin_lock_bh(&sta->lock); get_random_bytes(&llid, 2); sta->llid = llid; @@ -484,6 +487,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m return; } + if (sta && !test_sta_flags(sta, WLAN_STA_AUTH)) { + mpl_dbg("Mesh plink: Action frame from non-authed peer\n"); + rcu_read_unlock(); + return; + } + if (sta && sta->plink_state == PLINK_BLOCKED) { rcu_read_unlock(); return; -- cgit v1.2.3-58-ga151 From 96b78dff0321d881ef27d858a462c476e0444619 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Thu, 7 Apr 2011 15:08:33 -0700 Subject: nl80211/mac80211: Perform PLINK_ACTION on new station Modify the NEW_STATION command to accept PLINK_ACTIONS, in case userspace wants to create stations and initiate a peer link right away (for authenticated stations) or create a blocked station (for debugging). Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/mac80211/mesh_plink.c | 2 +- net/wireless/nl80211.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 5d0dd9217e5f..b327e0e6c730 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -105,7 +105,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, if (!sta) return NULL; - sta->flags = WLAN_STA_AUTHORIZED; + sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH; sta->sta.supp_rates[local->hw.conf.channel->band] = rates; rate_control_rate_init(sta); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index ce29a0d0e88e..f4cb8efe2e5f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2349,11 +2349,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); + if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) + params.plink_action = + nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); + if (parse_station_flags(info, ¶ms)) return -EINVAL; if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) return -EINVAL; -- cgit v1.2.3-58-ga151 From c93b5e717ec47b57abfe0229360bc11e77520984 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Thu, 7 Apr 2011 15:08:34 -0700 Subject: nl80211: New notification to discover mesh peer candidates. Notify userspace when a beacon/presp is received from a suitable mesh peer candidate for whom no sta information exists. Userspace can then decide to create a sta info for the candidate. If userspace is not ready to authenticate the peer right away, it can create the sta info with the authenticated flag unset and set it later. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- include/linux/nl80211.h | 12 ++++++++++++ include/net/cfg80211.h | 16 ++++++++++++++++ net/wireless/mesh.c | 14 ++++++++++++++ net/wireless/nl80211.c | 38 ++++++++++++++++++++++++++++++++++++++ net/wireless/nl80211.h | 4 ++++ 5 files changed, 84 insertions(+) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 5ec4ac3a0ef4..b87481866dde 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -410,6 +410,16 @@ * notification. This event is used to indicate that an unprotected * disassociation frame was dropped when MFP is in use. * + * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a + * beacon or probe response from a compatible mesh peer. This is only + * sent while no station information (sta_info) exists for the new peer + * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set. On + * reception of this notification, userspace may decide to create a new + * station (@NL80211_CMD_NEW_STATION). To stop this notification from + * reoccurring, the userspace authentication daemon may want to create the + * new station with the AUTHENTICATED flag unset and maybe change it later + * depending on the authentication result. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -522,6 +532,8 @@ enum nl80211_commands { NL80211_CMD_UNPROT_DEAUTHENTICATE, NL80211_CMD_UNPROT_DISASSOCIATE, + NL80211_CMD_NEW_PEER_CANDIDATE, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index e77603bd1630..f40cd30847de 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2488,6 +2488,22 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, */ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp); +/** + * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate + * + * @dev: network device + * @macaddr: the MAC address of the new candidate + * @ie: information elements advertised by the peer candidate + * @ie_len: lenght of the information elements buffer + * @gfp: allocation flags + * + * This function notifies cfg80211 that the mesh peer candidate has been + * detected, most likely via a beacon or, less likely, via a probe response. + * cfg80211 then sends a notification to userspace. + */ +void cfg80211_notify_new_peer_candidate(struct net_device *dev, + const u8 *macaddr, const u8 *ie, u8 ie_len, gfp_t gfp); + /** * DOC: RFkill integration * diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index e0226e8265a3..5c116083eeca 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -1,5 +1,6 @@ #include #include +#include "nl80211.h" #include "core.h" /* Default values, timeouts in ms */ @@ -110,6 +111,19 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, return err; } +void cfg80211_notify_new_peer_candidate(struct net_device *dev, + const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) + return; + + nl80211_send_new_peer_candidate(wiphy_to_dev(wdev->wiphy), dev, + macaddr, ie, ie_len, gfp); +} +EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate); + static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, struct net_device *dev) { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f4cb8efe2e5f..58f501a35022 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5818,6 +5818,44 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, nlmsg_free(msg); } +void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *macaddr, const u8* ie, u8 ie_len, + gfp_t gfp) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE); + if (!hdr) { + nlmsg_free(msg); + return; + } + + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, macaddr); + if (ie_len && ie) + NLA_PUT(msg, NL80211_ATTR_IE, ie_len , ie); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, + nl80211_mlme_mcgrp.id, gfp); + return; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *addr, enum nl80211_key_type key_type, int key_id, diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index dcac5cd6f017..f2af6955a665 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -50,6 +50,10 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, struct net_device *netdev, u16 reason, const u8 *ie, size_t ie_len, bool from_ap); +void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *macaddr, const u8* ie, u8 ie_len, + gfp_t gfp); void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *addr, -- cgit v1.2.3-58-ga151 From 1570ca59279a74db73b8ff840abdfaf64a9ee2ff Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Thu, 7 Apr 2011 15:08:35 -0700 Subject: mac80211: send notification on new peer candidate for our secure mesh Also, advertise support for mesh authentication. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/mac80211/main.c | 5 +++++ net/mac80211/mesh.c | 4 +--- net/mac80211/mesh.h | 3 ++- net/mac80211/mesh_plink.c | 18 +++++++++++++----- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index e2db3dc23953..0ab2a8df312d 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -762,6 +762,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT); #endif + /* if the underlying driver supports mesh, mac80211 will (at least) + * provide routing of mesh authentication frames to userspace */ + if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT)) + local->hw.wiphy->flags |= WIPHY_FLAG_MESH_AUTH; + /* mac80211 supports control port protocol changing */ local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 47a26c0f6993..11207979e2e2 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -590,9 +590,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, if (elems.mesh_id && elems.mesh_config && mesh_matches_local(&elems, sdata)) { supp_rates = ieee80211_sta_get_rates(local, &elems, band); - - mesh_neighbour_update(mgmt->sa, supp_rates, sdata, - mesh_peer_accepts_plinks(&elems)); + mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems); } } diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index b99e230fe31c..10acf1cc8082 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -226,7 +226,8 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); /* Mesh plinks */ void mesh_neighbour_update(u8 *hw_addr, u32 rates, - struct ieee80211_sub_if_data *sdata, bool add); + struct ieee80211_sub_if_data *sdata, + struct ieee802_11_elems *ie); bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); void mesh_plink_broken(struct sta_info *sta); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index b327e0e6c730..84e5b056af02 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -237,8 +237,9 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, return 0; } -void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata, - bool peer_accepting_plinks) +void mesh_neighbour_update(u8 *hw_addr, u32 rates, + struct ieee80211_sub_if_data *sdata, + struct ieee802_11_elems *elems) { struct ieee80211_local *local = sdata->local; struct sta_info *sta; @@ -248,8 +249,14 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data sta = sta_info_get(sdata, hw_addr); if (!sta) { rcu_read_unlock(); - - sta = mesh_plink_alloc(sdata, hw_addr, rates); + /* Userspace handles peer allocation when security is enabled + * */ + if (sdata->u.mesh.is_secure) + cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr, + elems->ie_start, elems->total_len, + GFP_KERNEL); + else + sta = mesh_plink_alloc(sdata, hw_addr, rates); if (!sta) return; if (sta_info_insert_rcu(sta)) { @@ -260,7 +267,8 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data sta->last_rx = jiffies; sta->sta.supp_rates[local->hw.conf.channel->band] = rates; - if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && + if (mesh_peer_accepts_plinks(elems) && + sta->plink_state == PLINK_LISTEN && sdata->u.mesh.accepting_plinks && sdata->u.mesh.mshcfg.auto_open_plinks) mesh_plink_open(sta); -- cgit v1.2.3-58-ga151 From 7d75541499319dff375af252345ae1999540b4a9 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Fri, 8 Apr 2011 15:30:34 +0530 Subject: ath9k: Add RSSI information from control and extension chains Export RSSI information from all the control and extension channel chains to debugfs. Also add rx antenna information to debugfs. This will be useful for debugging purpose. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 40 +++++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/debug.h | 7 ++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index a762cadb3ab7..34f191ec8e8c 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -845,7 +845,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, struct ath_softc *sc = file->private_data; char *buf; - unsigned int len = 0, size = 1152; + unsigned int len = 0, size = 1400; ssize_t retval = 0; buf = kzalloc(size, GFP_KERNEL); @@ -874,6 +874,34 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, "%18s : %10u\n", "DECRYPT BUSY ERR", sc->debug.stats.rxstats.decrypt_busy_err); + len += snprintf(buf + len, size - len, + "%18s : %10d\n", "RSSI-CTL0", + sc->debug.stats.rxstats.rs_rssi_ctl0); + + len += snprintf(buf + len, size - len, + "%18s : %10d\n", "RSSI-CTL1", + sc->debug.stats.rxstats.rs_rssi_ctl1); + + len += snprintf(buf + len, size - len, + "%18s : %10d\n", "RSSI-CTL2", + sc->debug.stats.rxstats.rs_rssi_ctl2); + + len += snprintf(buf + len, size - len, + "%18s : %10d\n", "RSSI-EXT0", + sc->debug.stats.rxstats.rs_rssi_ext0); + + len += snprintf(buf + len, size - len, + "%18s : %10d\n", "RSSI-EXT1", + sc->debug.stats.rxstats.rs_rssi_ext1); + + len += snprintf(buf + len, size - len, + "%18s : %10d\n", "RSSI-EXT2", + sc->debug.stats.rxstats.rs_rssi_ext2); + + len += snprintf(buf + len, size - len, + "%18s : %10d\n", "Rx Antenna", + sc->debug.stats.rxstats.rs_antenna); + PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); @@ -948,6 +976,16 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) RX_PHY_ERR_INC(phyerr); } + sc->debug.stats.rxstats.rs_rssi_ctl0 = rs->rs_rssi_ctl0; + sc->debug.stats.rxstats.rs_rssi_ctl1 = rs->rs_rssi_ctl1; + sc->debug.stats.rxstats.rs_rssi_ctl2 = rs->rs_rssi_ctl2; + + sc->debug.stats.rxstats.rs_rssi_ext0 = rs->rs_rssi_ext0; + sc->debug.stats.rxstats.rs_rssi_ext1 = rs->rs_rssi_ext1; + sc->debug.stats.rxstats.rs_rssi_ext2 = rs->rs_rssi_ext2; + + sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna; + #undef RX_STAT_INC #undef RX_PHY_ERR_INC } diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 59338de0ce19..1f9f8eada465 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -157,6 +157,13 @@ struct ath_rx_stats { u32 post_delim_crc_err; u32 decrypt_busy_err; u32 phy_err_stats[ATH9K_PHYERR_MAX]; + int8_t rs_rssi_ctl0; + int8_t rs_rssi_ctl1; + int8_t rs_rssi_ctl2; + int8_t rs_rssi_ext0; + int8_t rs_rssi_ext1; + int8_t rs_rssi_ext2; + u8 rs_antenna; }; struct ath_stats { -- cgit v1.2.3-58-ga151 From d0ef824b9a712b866e38212089ade3a7114225a4 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Fri, 8 Apr 2011 15:30:35 +0530 Subject: ath9k: Update gain table for AR9485 Update Tx gain 23 for all tx gain table. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9485_initvals.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index f91f73e50d00..fbdde29f0ab8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h @@ -396,7 +396,7 @@ static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = { {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, @@ -469,7 +469,7 @@ static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = { {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, @@ -635,7 +635,7 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = { {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, @@ -728,7 +728,7 @@ static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = { {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, @@ -827,7 +827,7 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = { {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, -- cgit v1.2.3-58-ga151 From f60c49b67dd6db2ccb740a6a671414f9dab00c4f Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 8 Apr 2011 17:06:25 +0530 Subject: ath9k: Fix kernel panic on module unload The commit "ath9k: configure beacons based on hw opmode" introduced a regression which leads to kernel panic. Failed to stop ani timer during the driver unload while any of the beaconing vif is running. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 1 + drivers/net/wireless/ath/ath9k/main.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index eccb0ec87adb..b56f69e7677b 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -320,6 +320,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) if (avp->av_bcbuf != NULL) { struct ath_buf *bf; + avp->is_bslot_active = false; if (avp->av_bslot != -1) { sc->beacon.bslot[avp->av_bslot] = NULL; sc->nbcnvifs--; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 93b9fa2cbaf8..a55a8929810b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1375,6 +1375,9 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, if ((iter_data.naps + iter_data.nadhocs) > 0) { sc->sc_flags |= SC_OP_ANI_RUN; ath_start_ani(common); + } else { + sc->sc_flags &= ~SC_OP_ANI_RUN; + del_timer_sync(&common->ani.timer); } } -- cgit v1.2.3-58-ga151 From ebe27c91af8b7f4810ae906fbd3eeb2d87850026 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 8 Apr 2011 21:24:24 +0530 Subject: {mac|nl}80211: Add station connected time Add station connected time in debugfs. This will be helpful to get a measure of stability of the connection and for debugging stress issues Cc: Senthilkumar Balasubramanian Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- include/linux/nl80211.h | 2 ++ include/net/cfg80211.h | 4 ++++ net/mac80211/cfg.c | 7 ++++++- net/mac80211/debugfs_sta.c | 26 ++++++++++++++++++++++++++ net/mac80211/sta_info.c | 3 +++ net/mac80211/sta_info.h | 2 ++ net/wireless/nl80211.c | 3 +++ 7 files changed, 46 insertions(+), 1 deletion(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index b87481866dde..be8df57b789d 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1297,6 +1297,7 @@ enum nl80211_sta_bss_param { * attribute, like NL80211_STA_INFO_TX_BITRATE. * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute * containing info as possible, see &enum nl80211_sta_bss_param + * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -1317,6 +1318,7 @@ enum nl80211_sta_info { NL80211_STA_INFO_SIGNAL_AVG, NL80211_STA_INFO_RX_BITRATE, NL80211_STA_INFO_BSS_PARAM, + NL80211_STA_INFO_CONNECTED_TIME, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f40cd30847de..d30eada7c6cd 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -423,6 +423,7 @@ struct station_parameters { * @STATION_INFO_SIGNAL_AVG: @signal_avg filled * @STATION_INFO_RX_BITRATE: @rxrate fields are filled * @STATION_INFO_BSS_PARAM: @bss_param filled + * @STATION_INFO_CONNECTED_TIME: @connected_time filled */ enum station_info_flags { STATION_INFO_INACTIVE_TIME = 1<<0, @@ -441,6 +442,7 @@ enum station_info_flags { STATION_INFO_SIGNAL_AVG = 1<<13, STATION_INFO_RX_BITRATE = 1<<14, STATION_INFO_BSS_PARAM = 1<<15, + STATION_INFO_CONNECTED_TIME = 1<<16 }; /** @@ -511,6 +513,7 @@ struct sta_bss_parameters { * Station information filled by driver for get_station() and dump_station. * * @filled: bitflag of flags from &enum station_info_flags + * @connected_time: time(in secs) since a station is last connected * @inactive_time: time since last station activity (tx/rx) in milliseconds * @rx_bytes: bytes received from this station * @tx_bytes: bytes transmitted to this station @@ -533,6 +536,7 @@ struct sta_bss_parameters { */ struct station_info { u32 filled; + u32 connected_time; u32 inactive_time; u32 rx_bytes; u32 tx_bytes; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 1c25723eacda..a6d191f2a0fe 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -330,6 +330,7 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) { struct ieee80211_sub_if_data *sdata = sta->sdata; + struct timespec uptime; sinfo->generation = sdata->local->sta_generation; @@ -343,7 +344,11 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) STATION_INFO_TX_BITRATE | STATION_INFO_RX_BITRATE | STATION_INFO_RX_DROP_MISC | - STATION_INFO_BSS_PARAM; + STATION_INFO_BSS_PARAM | + STATION_INFO_CONNECTED_TIME; + + do_posix_clock_monotonic_gettime(&uptime); + sinfo->connected_time = uptime.tv_sec - sta->last_connected; sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); sinfo->rx_bytes = sta->rx_bytes; diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index c04a1396cf8d..c008232731eb 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -92,6 +92,31 @@ static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf, } STA_OPS(inactive_ms); + +static ssize_t sta_connected_time_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct sta_info *sta = file->private_data; + struct timespec uptime; + struct tm result; + long connected_time_secs; + char buf[100]; + int res; + do_posix_clock_monotonic_gettime(&uptime); + connected_time_secs = uptime.tv_sec - sta->last_connected; + time_to_tm(connected_time_secs, 0, &result); + result.tm_year -= 70; + result.tm_mday -= 1; + res = scnprintf(buf, sizeof(buf), + "years - %d\nmonths - %d\ndays - %d\nclock - %d:%d:%d\n\n", + result.tm_year, result.tm_mon, result.tm_mday, + result.tm_hour, result.tm_min, result.tm_sec); + return simple_read_from_buffer(userbuf, count, ppos, buf, res); +} +STA_OPS(connected_time); + + + static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -324,6 +349,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) DEBUGFS_ADD(flags); DEBUGFS_ADD(num_ps_buf_frames); DEBUGFS_ADD(inactive_ms); + DEBUGFS_ADD(connected_time); DEBUGFS_ADD(last_seq_ctrl); DEBUGFS_ADD(agg_status); DEBUGFS_ADD(dev); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 999f8fbf0b4b..8a9068ac0673 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -228,6 +228,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; struct sta_info *sta; + struct timespec uptime; int i; sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); @@ -245,6 +246,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, sta->sdata = sdata; sta->last_rx = jiffies; + do_posix_clock_monotonic_gettime(&uptime); + sta->last_connected = uptime.tv_sec; ewma_init(&sta->avg_signal, 1024, 8); if (sta_prepare_rate_control(local, sta, gfp)) { diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 43238e99cfb3..984a03db3553 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -226,6 +226,7 @@ enum plink_state { * @rx_bytes: Number of bytes received from this STA * @wep_weak_iv_count: number of weak WEP IVs received from this station * @last_rx: time (in jiffies) when last frame was received from this STA + * @last_connected: time (in seconds) when a station got connected * @num_duplicates: number of duplicate frames received from this STA * @rx_fragments: number of received MPDUs * @rx_dropped: number of dropped MPDUs from this STA @@ -295,6 +296,7 @@ struct sta_info { unsigned long rx_packets, rx_bytes; unsigned long wep_weak_iv_count; unsigned long last_rx; + long last_connected; unsigned long num_duplicates; unsigned long rx_fragments; unsigned long rx_dropped; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 58f501a35022..0efa7fd01150 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2020,6 +2020,9 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO); if (!sinfoattr) goto nla_put_failure; + if (sinfo->filled & STATION_INFO_CONNECTED_TIME) + NLA_PUT_U32(msg, NL80211_STA_INFO_CONNECTED_TIME, + sinfo->connected_time); if (sinfo->filled & STATION_INFO_INACTIVE_TIME) NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME, sinfo->inactive_time); -- cgit v1.2.3-58-ga151 From 1296433bf39a8dea852aafad1f29b775f993bca1 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 8 Apr 2011 20:49:16 +0200 Subject: ath9k_hw: remove unnecessary parts of the AR9380 SREV check Older versions have not been sold and the driver does not explicitly check for them anyway, so we can simply ignore the macRev here. Reduces ath9k_hw size on mips by more than 2 KB. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/reg.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 693d543937b5..2fbbe8842bb9 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -858,9 +858,7 @@ #define AR_SREV_9300(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300)) #define AR_SREV_9300_20_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9300) || \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9300_20))) + ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300) #define AR_SREV_9485(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) -- cgit v1.2.3-58-ga151 From ba30c4a58ceb10e81dbf6bd80aeb6a4db42db8fe Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Sat, 9 Apr 2011 00:25:37 +0530 Subject: mwl8k: Fix checkpatch.pl and sparse warnings and errors Fix checkpatch errors and warnings comprising of indent errors, spaces and __packed warnings. Also fix 'make C = 2' warnings. Signed-off-by: Yogesh Ashok Powar Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 8913180a7bd3..fb472f4924d0 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -701,7 +701,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) "helper image\n", pci_name(priv->pdev)); return rc; } - msleep(5); + msleep(20); rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); } else { @@ -823,8 +823,8 @@ static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb) /* * Make sure the packet header is in the DMA header format (4-address * without QoS), the necessary crypto padding between the header and the - * payload has already been provided by mac80211, but it doesn't add tail - * padding when HW crypto is enabled. + * payload has already been provided by mac80211, but it doesn't add + * tail padding when HW crypto is enabled. * * We have the following trailer padding requirements: * - WEP: 4 trailer bytes (ICV) @@ -1487,9 +1487,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) if (timeout) { WARN_ON(priv->pending_tx_pkts); - if (retry) { + if (retry) wiphy_notice(hw->wiphy, "tx rings drained\n"); - } break; } @@ -1649,8 +1648,8 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) /* Rate control is happening in the firmware. * Ensure no tx rate is being reported. */ - info->status.rates[0].idx = -1; - info->status.rates[0].count = 1; + info->status.rates[0].idx = -1; + info->status.rates[0].count = 1; if (MWL8K_TXD_SUCCESS(status)) info->flags |= IEEE80211_TX_STAT_ACK; @@ -1688,7 +1687,7 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index) } /* caller must hold priv->stream_lock when calling the stream functions */ -struct mwl8k_ampdu_stream * +static struct mwl8k_ampdu_stream * mwl8k_add_stream(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 tid) { struct mwl8k_ampdu_stream *stream; @@ -2657,7 +2656,7 @@ struct mwl8k_cmd_tx_power { __le16 bw; __le16 sub_ch; __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; -} __attribute__((packed)); +} __packed; static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw, struct ieee80211_conf *conf, @@ -3520,13 +3519,13 @@ static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw, #define BASTREAM_FLAG_DIRECTION_UPSTREAM 0x00 #define BASTREAM_FLAG_IMMEDIATE_TYPE 0x01 -enum { +enum ba_stream_action_type { MWL8K_BA_CREATE, MWL8K_BA_UPDATE, MWL8K_BA_DESTROY, MWL8K_BA_FLUSH, MWL8K_BA_CHECK, -} ba_stream_action_type; +}; struct mwl8k_create_ba_stream { @@ -3780,7 +3779,7 @@ struct mwl8k_cmd_update_encryption { __u8 mac_addr[6]; __u8 encr_type; -} __attribute__((packed)); +} __packed; struct mwl8k_cmd_set_key { struct mwl8k_cmd_pkt header; @@ -3800,7 +3799,7 @@ struct mwl8k_cmd_set_key { __le16 tkip_tsc_low; __le32 tkip_tsc_high; __u8 mac_addr[6]; -} __attribute__((packed)); +} __packed; enum { MWL8K_ENCR_ENABLE, @@ -4502,7 +4501,7 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u32 changed) { struct mwl8k_priv *priv = hw->priv; - u32 ap_legacy_rates; + u32 ap_legacy_rates = 0; u8 ap_mcs_rates[16]; int rc; -- cgit v1.2.3-58-ga151 From a065784620a2b78a2bbd00e066c004644d227ea8 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 8 Apr 2011 15:33:12 -0400 Subject: 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 Signed-off-by: John W. Linville Reviewed-by: Bob Copeland --- drivers/net/wireless/ath/ath5k/eeprom.c | 129 +++++++++++++++++--------------- 1 file changed, 70 insertions(+), 59 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index b6561f785c6e..fb12027e0346 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -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; } +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 * used by interpolation code */ static int @@ -684,7 +731,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, GFP_KERNEL); if (!chinfo[pier].pd_curves) - return -ENOMEM; + goto err_out; /* Only one curve for RF5111 * 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, sizeof(u8), GFP_KERNEL); if (!pd->pd_step) - return -ENOMEM; + goto err_out; pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, sizeof(s16), GFP_KERNEL); if (!pd->pd_pwr) - return -ENOMEM; + goto err_out; /* Fill raw dataset * (convert power to 0.25dB units @@ -734,6 +781,10 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, } return 0; + +err_out: + ath5k_eeprom_free_pcal_info(ah, mode); + return -ENOMEM; } /* Parse EEPROM data */ @@ -867,7 +918,7 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, GFP_KERNEL); if (!chinfo[pier].pd_curves) - return -ENOMEM; + goto err_out; /* Fill pd_curves */ 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); if (!pd->pd_step) - return -ENOMEM; + goto err_out; pd->pd_pwr = kcalloc(pd->pd_points, sizeof(s16), GFP_KERNEL); if (!pd->pd_pwr) - return -ENOMEM; - + goto err_out; /* Fill raw dataset * (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); if (!pd->pd_step) - return -ENOMEM; + goto err_out; pd->pd_pwr = kcalloc(pd->pd_points, sizeof(s16), GFP_KERNEL); if (!pd->pd_pwr) - return -ENOMEM; + goto err_out; /* Fill raw dataset * (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; + +err_out: + ath5k_eeprom_free_pcal_info(ah, mode); + return -ENOMEM; } /* Parse EEPROM data */ @@ -1156,7 +1210,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, GFP_KERNEL); if (!chinfo[pier].pd_curves) - return -ENOMEM; + goto err_out; /* Fill pd_curves */ 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); if (!pd->pd_step) - return -ENOMEM; + goto err_out; pd->pd_pwr = kcalloc(pd->pd_points, sizeof(s16), GFP_KERNEL); if (!pd->pd_pwr) - return -ENOMEM; + goto err_out; /* Fill raw dataset * convert all pwr levels to @@ -1213,6 +1267,10 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, } return 0; + +err_out: + ath5k_eeprom_free_pcal_info(ah, mode); + return -ENOMEM; } /* Parse EEPROM data */ @@ -1534,53 +1592,6 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) 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 */ static int ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) -- cgit v1.2.3-58-ga151 From 6d7b97b23e114c8fbb825e6721164d228c1af3fc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 9 Apr 2011 21:37:14 +0200 Subject: ath5k: fix tx status reporting issues During normal operation, minstrel was showing suspicious EWMA probabilities exceeding 100%. It looks like the tx status reporting in ath5k was not properly clearing the rate index for rates which were never attempted. This is caused by uninitialized stale data in the on-stack tx status information, which is reused when more frames are received. To fix this, rely on ts->ts_final_idx to select the last attempted rate, instead of checking whether ts->ts_rate is set. Additionally, the conversion from the driver rate index back to the mac80211 rate index can be dropped, as the mac80211 tx status will still have the original rate index which was used to set up the descriptor. Additionally, one more inaccuracy was fixed - the final rate attempt count only needs to be increased by one if the transmission attempt was successful. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 4d7f21ee111c..753662f98f75 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1580,21 +1580,14 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, info = IEEE80211_SKB_CB(skb); ieee80211_tx_info_clear_status(info); - for (i = 0; i < 4; i++) { + for (i = 0; i <= ts->ts_final_idx; i++) { struct ieee80211_tx_rate *r = &info->status.rates[i]; - if (ts->ts_rate[i]) { - r->idx = ath5k_hw_to_driver_rix(sc, ts->ts_rate[i]); - r->count = ts->ts_retry[i]; - } else { - r->idx = -1; - r->count = 0; - } + r->count = ts->ts_retry[i]; } - /* count the successful attempt as well */ - info->status.rates[ts->ts_final_idx].count++; + info->status.rates[ts->ts_final_idx + 1].idx = -1; if (unlikely(ts->ts_status)) { sc->stats.ack_fail++; @@ -1609,6 +1602,9 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, } else { info->flags |= IEEE80211_TX_STAT_ACK; info->status.ack_signal = ts->ts_rssi; + + /* count the successful attempt as well */ + info->status.rates[ts->ts_final_idx].count++; } /* -- cgit v1.2.3-58-ga151 From a27049e2c926bcf68360532a5ae66e408296ae85 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 9 Apr 2011 23:10:19 +0200 Subject: ath5k: fix short preamble rate duration value Subtract the difference in preamble duration (in usec) from the value returned by ieee80211_generic_frame_duration. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 2 +- drivers/net/wireless/ath/ath5k/pcu.c | 31 ++++++++++++------------------- drivers/net/wireless/ath/ath5k/qcu.c | 2 +- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 8a06dbd39629..996d8afafdb7 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1233,7 +1233,7 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); /* Protocol Control Unit Functions */ /* Helpers */ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, - int len, struct ieee80211_rate *rate); + int len, struct ieee80211_rate *rate, bool shortpre); unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah); unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah); extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index a702817daf72..e342e470fb05 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -75,7 +75,7 @@ static const unsigned int ack_rates_high[] = * bwmodes. */ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, - int len, struct ieee80211_rate *rate) + int len, struct ieee80211_rate *rate, bool shortpre) { struct ath5k_softc *sc = ah->ah_sc; int sifs, preamble, plcp_bits, sym_time; @@ -84,9 +84,15 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, /* Fallback */ if (!ah->ah_bwmode) { - dur = ieee80211_generic_frame_duration(sc->hw, - NULL, len, rate); - return le16_to_cpu(dur); + __le16 raw_dur = ieee80211_generic_frame_duration(sc->hw, + NULL, len, rate); + + /* subtract difference between long and short preamble */ + dur = le16_to_cpu(raw_dur); + if (shortpre) + dur -= 96; + + return dur; } bitrate = rate->bitrate; @@ -263,27 +269,14 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) * actual rate for this rate. See mac80211 tx.c * ieee80211_duration() for a brief description of * what rate we should choose to TX ACKs. */ - tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); + tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); ath5k_hw_reg_write(ah, tx_time, reg); if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) continue; - /* - * We're not distinguishing short preamble here, - * This is true, all we'll get is a longer value here - * which is not necessarilly bad. We could use - * export ieee80211_frame_duration() but that needs to be - * fixed first to be properly used by mac802111 drivers: - * - * - remove erp stuff and let the routine figure ofdm - * erp rates - * - remove passing argument ieee80211_local as - * drivers don't have access to it - * - move drivers using ieee80211_generic_frame_duration() - * to this - */ + tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, true); ath5k_hw_reg_write(ah, tx_time, reg + (AR5K_SET_SHORT_PREAMBLE << 2)); } diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 3343fb9e4940..93abcfacd990 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -550,7 +550,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) else rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; - ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); + ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); /* ack_tx_time includes an SIFS already */ eifs = ack_tx_time + sifs + 2 * slot_time; -- cgit v1.2.3-58-ga151 From 488a50176c169eb36544b4f970c8bba68ede30a1 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 9 Apr 2011 23:10:20 +0200 Subject: ath5k: fix SIFS time handling ath5k uses 8 usec as a sifs time, extracted from the initvals, whereas the standard requires a sifs time of 10. The difference originates from the fact that the SIFS register has an offset of 2 usec. Fix the SIFS time definition to use the standard value of 10 usec and subtract 2 usecs when writing the SIFS register. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 3 +-- drivers/net/wireless/ath/ath5k/qcu.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 996d8afafdb7..a49aeac378cd 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -224,8 +224,7 @@ /* SIFS */ #define AR5K_INIT_SIFS_TURBO 6 -/* XXX: 8 from initvals 10 from standard */ -#define AR5K_INIT_SIFS_DEFAULT_BG 8 +#define AR5K_INIT_SIFS_DEFAULT_BG 10 #define AR5K_INIT_SIFS_DEFAULT_A 16 #define AR5K_INIT_SIFS_HALF_RATE 32 #define AR5K_INIT_SIFS_QUARTER_RATE 64 diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 93abcfacd990..b18c5021aac3 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -519,7 +519,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) return -EINVAL; sifs = ath5k_hw_get_default_sifs(ah); - sifs_clock = ath5k_hw_htoclock(ah, sifs); + sifs_clock = ath5k_hw_htoclock(ah, sifs - 2); /* EIFS * Txtime of ack at lowest rate + SIFS + DIFS -- cgit v1.2.3-58-ga151 From b1ad1b6febb7772583c98d9a879fbbdb82a726a7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 9 Apr 2011 23:10:21 +0200 Subject: ath5k: fix slot time handling Set the slot time based on the mac80211 short slot vs long slot setting instead of just forcing long slot for all CCK-enabled channels. This slightly improves 802.11g mode performance in in my tests. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 1 + drivers/net/wireless/ath/ath5k/mac80211-ops.c | 9 +++++++++ drivers/net/wireless/ath/ath5k/pcu.c | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index a49aeac378cd..4bb381cae08d 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1057,6 +1057,7 @@ struct ath5k_hw { u8 ah_coverage_class; bool ah_ack_bitrate_high; u8 ah_bwmode; + bool ah_short_slot; /* Antenna Control */ u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 9be29b728b1c..807bd6440169 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -282,6 +282,15 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (changes & BSS_CHANGED_BEACON_INT) sc->bintval = bss_conf->beacon_int; + if (changes & BSS_CHANGED_ERP_SLOT) { + int slot_time; + + ah->ah_short_slot = bss_conf->use_short_slot; + slot_time = ath5k_hw_get_default_slottime(ah) + + 3 * ah->ah_coverage_class; + ath5k_hw_set_ifs_intervals(ah, slot_time); + } + if (changes & BSS_CHANGED_ASSOC) { avf->assoc = bss_conf->assoc; if (bss_conf->assoc) diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index e342e470fb05..71b60b7c617e 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -151,9 +151,9 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE; break; case AR5K_BWMODE_DEFAULT: - slot_time = AR5K_INIT_SLOT_TIME_DEFAULT; default: - if (channel->hw_value & CHANNEL_CCK) + slot_time = AR5K_INIT_SLOT_TIME_DEFAULT; + if ((channel->hw_value & CHANNEL_CCK) && !ah->ah_short_slot) slot_time = AR5K_INIT_SLOT_TIME_B; break; } -- cgit v1.2.3-58-ga151 From c5e0a88aa2e0f42cdb4c79c977c52f6bc38ec160 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 10 Apr 2011 18:32:13 +0200 Subject: ath5k: optimize tx descriptor setup Use local variables to reduce the number of load/store operations on uncached memory. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/desc.c | 38 ++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 16b44ff7dd3e..0a8a9efaf8b4 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -184,6 +184,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, { struct ath5k_hw_4w_tx_ctl *tx_ctl; unsigned int frame_len; + u32 txctl0 = 0, txctl1 = 0, txctl2 = 0, txctl3 = 0; tx_ctl = &desc->ud.ds_tx5212.tx_ctl; @@ -209,7 +210,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, tx_power = AR5K_TUNE_MAX_TXPOWER; /* Clear descriptor */ - memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); + memset(&desc->ud.ds_tx5212.tx_stat, 0, + sizeof(desc->ud.ds_tx5212.tx_stat)); /* Setup control descriptor */ @@ -221,7 +223,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) return -EINVAL; - tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; + txctl0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; /* Verify and set buffer length */ @@ -232,21 +234,17 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) return -EINVAL; - tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; + txctl1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; - tx_ctl->tx_control_0 |= - AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | - AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); - tx_ctl->tx_control_1 |= AR5K_REG_SM(type, - AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); - tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0, - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); - tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; + txctl0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | + AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); + txctl1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); + txctl2 = AR5K_REG_SM(tx_tries0, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); + txctl3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; #define _TX_FLAGS(_c, _flag) \ if (flags & AR5K_TXDESC_##_flag) { \ - tx_ctl->tx_control_##_c |= \ - AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ + txctl##_c |= AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ } _TX_FLAGS(0, CLRDMASK); @@ -262,8 +260,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, * WEP crap */ if (key_index != AR5K_TXKEYIX_INVALID) { - tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; - tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, + txctl0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; + txctl1 |= AR5K_REG_SM(key_index, AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX); } @@ -274,12 +272,16 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, if ((flags & AR5K_TXDESC_RTSENA) && (flags & AR5K_TXDESC_CTSENA)) return -EINVAL; - tx_ctl->tx_control_2 |= rtscts_duration & - AR5K_4W_TX_DESC_CTL2_RTS_DURATION; - tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate, + txctl2 |= rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION; + txctl3 |= AR5K_REG_SM(rtscts_rate, AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); } + tx_ctl->tx_control_0 = txctl0; + tx_ctl->tx_control_1 = txctl1; + tx_ctl->tx_control_2 = txctl2; + tx_ctl->tx_control_3 = txctl3; + return 0; } -- cgit v1.2.3-58-ga151 From fe12081cb664cd5d412dc56de0585a80484b1331 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 10 Apr 2011 18:32:14 +0200 Subject: ath5k: remove ts_rate from ath5k_tx_status It is no longer necessary for preparing mac80211 tx status Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 1 - drivers/net/wireless/ath/ath5k/desc.c | 13 ------------- 2 files changed, 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 4bb381cae08d..aa588a0521c1 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -452,7 +452,6 @@ struct ath5k_tx_status { u16 ts_seqnum; u16 ts_tstamp; u8 ts_status; - u8 ts_rate[4]; u8 ts_retry[4]; u8 ts_final_idx; s8 ts_rssi; diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 0a8a9efaf8b4..990a3b421443 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -375,8 +375,6 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); ts->ts_antenna = 1; ts->ts_status = 0; - ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0, - AR5K_2W_TX_DESC_CTL0_XMIT_RATE); ts->ts_retry[0] = ts->ts_longretry; ts->ts_final_idx = 0; @@ -439,32 +437,21 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; switch (ts->ts_final_idx) { case 3: - ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3, - AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); - ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); ts->ts_longretry += ts->ts_retry[2]; /* fall through */ case 2: - ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3, - AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); - ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); ts->ts_longretry += ts->ts_retry[1]; /* fall through */ case 1: - ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3, - AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); - ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); ts->ts_longretry += ts->ts_retry[0]; /* fall through */ case 0: - ts->ts_rate[0] = tx_ctl->tx_control_3 & - AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; break; } -- cgit v1.2.3-58-ga151 From b161b89fb97b30233526d31c5f94397ed94ffea6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 10 Apr 2011 18:32:15 +0200 Subject: ath5k: optimize tx status processing Use ACCESS_ONCE to reduce the number of variable reloads on uncached memory Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/desc.c | 37 ++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 990a3b421443..3758b967029a 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -401,32 +401,38 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, { struct ath5k_hw_4w_tx_ctl *tx_ctl; struct ath5k_hw_tx_status *tx_status; + u32 txstat0, txstat1, txctl2; tx_ctl = &desc->ud.ds_tx5212.tx_ctl; tx_status = &desc->ud.ds_tx5212.tx_stat; + txstat1 = ACCESS_ONCE(tx_status->tx_status_1); + /* No frame has been send or error */ - if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))) + if (unlikely(!(txstat1 & AR5K_DESC_TX_STATUS1_DONE))) return -EINPROGRESS; + txstat0 = ACCESS_ONCE(tx_status->tx_status_0); + txctl2 = ACCESS_ONCE(tx_ctl->tx_control_2); + /* * Get descriptor status */ - ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, + ts->ts_tstamp = AR5K_REG_MS(txstat0, AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); - ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, + ts->ts_shortretry = AR5K_REG_MS(txstat0, AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); - ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, + ts->ts_longretry = AR5K_REG_MS(txstat0, AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); - ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, + ts->ts_seqnum = AR5K_REG_MS(txstat1, AR5K_DESC_TX_STATUS1_SEQ_NUM); - ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, + ts->ts_rssi = AR5K_REG_MS(txstat1, AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); - ts->ts_antenna = (tx_status->tx_status_1 & + ts->ts_antenna = (txstat1 & AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1; ts->ts_status = 0; - ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, + ts->ts_final_idx = AR5K_REG_MS(txstat1, AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212); /* The longretry counter has the number of un-acked retries @@ -437,17 +443,17 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; switch (ts->ts_final_idx) { case 3: - ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2, + ts->ts_retry[2] = AR5K_REG_MS(txctl2, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); ts->ts_longretry += ts->ts_retry[2]; /* fall through */ case 2: - ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2, + ts->ts_retry[1] = AR5K_REG_MS(txctl2, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); ts->ts_longretry += ts->ts_retry[1]; /* fall through */ case 1: - ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2, + ts->ts_retry[0] = AR5K_REG_MS(txctl2, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); ts->ts_longretry += ts->ts_retry[0]; /* fall through */ @@ -456,15 +462,14 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, } /* TX error */ - if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { - if (tx_status->tx_status_0 & - AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) + if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { + if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) ts->ts_status |= AR5K_TXERR_XRETRY; - if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) + if (txstat0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) ts->ts_status |= AR5K_TXERR_FIFO; - if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) + if (txstat0 & AR5K_DESC_TX_STATUS0_FILTERED) ts->ts_status |= AR5K_TXERR_FILT; } -- cgit v1.2.3-58-ga151 From b2fd97d0190a400b49a2f910109a4a492bfea319 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 10 Apr 2011 18:32:16 +0200 Subject: ath5k: optimize rx status processing Use ACCESS_ONCE to reduce the number of redundant loads on uncached memory Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/desc.c | 41 +++++++++++++++-------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 3758b967029a..e366d30ef039 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -603,37 +603,37 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, struct ath5k_rx_status *rs) { struct ath5k_hw_rx_status *rx_status; + u32 rxstat0, rxstat1; rx_status = &desc->ud.ds_rx.rx_stat; + rxstat1 = ACCESS_ONCE(rx_status->rx_status_1); /* No frame received / not ready */ - if (unlikely(!(rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_DONE))) + if (unlikely(!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_DONE))) return -EINPROGRESS; memset(rs, 0, sizeof(struct ath5k_rx_status)); + rxstat0 = ACCESS_ONCE(rx_status->rx_status_0); /* * Frame receive status */ - rs->rs_datalen = rx_status->rx_status_0 & - AR5K_5212_RX_DESC_STATUS0_DATA_LEN; - rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, + rs->rs_datalen = rxstat0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN; + rs->rs_rssi = AR5K_REG_MS(rxstat0, AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); - rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, + rs->rs_rate = AR5K_REG_MS(rxstat0, AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); - rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, + rs->rs_antenna = AR5K_REG_MS(rxstat0, AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA); - rs->rs_more = !!(rx_status->rx_status_0 & - AR5K_5212_RX_DESC_STATUS0_MORE); - rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, + rs->rs_more = !!(rxstat0 & AR5K_5212_RX_DESC_STATUS0_MORE); + rs->rs_tstamp = AR5K_REG_MS(rxstat1, AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); /* * Key table status */ - if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) - rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, + if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) + rs->rs_keyix = AR5K_REG_MS(rxstat1, AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); else rs->rs_keyix = AR5K_RXKEYIX_INVALID; @@ -641,27 +641,22 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, /* * Receive/descriptor errors */ - if (!(rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { - if (rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) + if (!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { + if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) rs->rs_status |= AR5K_RXERR_CRC; - if (rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { + if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { rs->rs_status |= AR5K_RXERR_PHY; - rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, + rs->rs_phyerr = AR5K_REG_MS(rxstat1, AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE); if (!ah->ah_capabilities.cap_has_phyerr_counters) ath5k_ani_phy_error_report(ah, rs->rs_phyerr); } - if (rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) + if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) rs->rs_status |= AR5K_RXERR_DECRYPT; - if (rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) + if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) rs->rs_status |= AR5K_RXERR_MIC; } return 0; -- cgit v1.2.3-58-ga151 From ed8950857f728303a1463ac9267e72c278738bf6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 10 Apr 2011 18:32:17 +0200 Subject: ath5k: remove ts_retry from ath5k_tx_status Reusing the configured retry counts from the skb cb is more efficient than reloading the data from uncached memory. Replace ts_longretry (unused) with ts_final_retry which contains the retry count for the final rate only Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 3 +-- drivers/net/wireless/ath/ath5k/base.c | 11 +++++++++-- drivers/net/wireless/ath/ath5k/desc.c | 34 +++------------------------------- 3 files changed, 13 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index aa588a0521c1..fcaf4ed84ca5 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -452,11 +452,10 @@ struct ath5k_tx_status { u16 ts_seqnum; u16 ts_tstamp; u8 ts_status; - u8 ts_retry[4]; u8 ts_final_idx; + u8 ts_final_retry; s8 ts_rssi; u8 ts_shortretry; - u8 ts_longretry; u8 ts_virtcol; u8 ts_antenna; }; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 753662f98f75..1a561b89221e 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1573,20 +1573,27 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, struct ath5k_txq *txq, struct ath5k_tx_status *ts) { struct ieee80211_tx_info *info; + u8 tries[3]; int i; sc->stats.tx_all_count++; sc->stats.tx_bytes_count += skb->len; info = IEEE80211_SKB_CB(skb); + tries[0] = info->status.rates[0].count; + tries[1] = info->status.rates[1].count; + tries[2] = info->status.rates[2].count; + ieee80211_tx_info_clear_status(info); - for (i = 0; i <= ts->ts_final_idx; i++) { + + for (i = 0; i < ts->ts_final_idx; i++) { struct ieee80211_tx_rate *r = &info->status.rates[i]; - r->count = ts->ts_retry[i]; + r->count = tries[i]; } + info->status.rates[ts->ts_final_idx].count = ts->ts_final_retry; info->status.rates[ts->ts_final_idx + 1].idx = -1; if (unlikely(ts->ts_status)) { diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index e366d30ef039..0391813befd1 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -366,7 +366,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); - ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, + ts->ts_final_retry = AR5K_REG_MS(tx_status->tx_status_0, AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); /*TODO: ts->ts_virtcol + test*/ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, @@ -375,7 +375,6 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); ts->ts_antenna = 1; ts->ts_status = 0; - ts->ts_retry[0] = ts->ts_longretry; ts->ts_final_idx = 0; if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { @@ -401,7 +400,7 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, { struct ath5k_hw_4w_tx_ctl *tx_ctl; struct ath5k_hw_tx_status *tx_status; - u32 txstat0, txstat1, txctl2; + u32 txstat0, txstat1; tx_ctl = &desc->ud.ds_tx5212.tx_ctl; tx_status = &desc->ud.ds_tx5212.tx_stat; @@ -413,7 +412,6 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, return -EINPROGRESS; txstat0 = ACCESS_ONCE(tx_status->tx_status_0); - txctl2 = ACCESS_ONCE(tx_ctl->tx_control_2); /* * Get descriptor status @@ -422,7 +420,7 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); ts->ts_shortretry = AR5K_REG_MS(txstat0, AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); - ts->ts_longretry = AR5K_REG_MS(txstat0, + ts->ts_final_retry = AR5K_REG_MS(txstat0, AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); ts->ts_seqnum = AR5K_REG_MS(txstat1, AR5K_DESC_TX_STATUS1_SEQ_NUM); @@ -435,32 +433,6 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, ts->ts_final_idx = AR5K_REG_MS(txstat1, AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212); - /* The longretry counter has the number of un-acked retries - * for the final rate. To get the total number of retries - * we have to add the retry counters for the other rates - * as well - */ - ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; - switch (ts->ts_final_idx) { - case 3: - ts->ts_retry[2] = AR5K_REG_MS(txctl2, - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); - ts->ts_longretry += ts->ts_retry[2]; - /* fall through */ - case 2: - ts->ts_retry[1] = AR5K_REG_MS(txctl2, - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); - ts->ts_longretry += ts->ts_retry[1]; - /* fall through */ - case 1: - ts->ts_retry[0] = AR5K_REG_MS(txctl2, - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); - ts->ts_longretry += ts->ts_retry[0]; - /* fall through */ - case 0: - break; - } - /* TX error */ if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) -- cgit v1.2.3-58-ga151 From 5b7916ad8c29da9f30fbf03a8b61862acdba00ce Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 10 Apr 2011 18:32:18 +0200 Subject: ath5k: clean up debugfs code The pointers to the debugfs entries do not need to be saved, because they will be recursively removed when the wiphy is unregistered. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 1 - drivers/net/wireless/ath/ath5k/debug.c | 65 ++++++++++------------------------ drivers/net/wireless/ath/ath5k/debug.h | 17 --------- 3 files changed, 19 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 1a561b89221e..a799d04e0c8c 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2901,7 +2901,6 @@ ath5k_deinit_softc(struct ath5k_softc *sc) * XXX: ??? detach ath5k_hw ??? * Other than that, it's straightforward... */ - ath5k_debug_finish_device(sc); ieee80211_unregister_hw(hw); ath5k_desc_free(sc); ath5k_txq_release(sc); diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 0230f30e9e9a..0bf7313b8a17 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -888,65 +888,38 @@ static const struct file_operations fops_queue = { void ath5k_debug_init_device(struct ath5k_softc *sc) { - sc->debug.level = ath5k_debug; + struct dentry *phydir; - sc->debug.debugfs_phydir = debugfs_create_dir("ath5k", - sc->hw->wiphy->debugfsdir); + sc->debug.level = ath5k_debug; - sc->debug.debugfs_debug = debugfs_create_file("debug", - S_IWUSR | S_IRUSR, - sc->debug.debugfs_phydir, sc, &fops_debug); + phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir); + if (!phydir) + return; - sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR, - sc->debug.debugfs_phydir, sc, &fops_registers); + debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc, + &fops_debug); - sc->debug.debugfs_beacon = debugfs_create_file("beacon", - S_IWUSR | S_IRUSR, - sc->debug.debugfs_phydir, sc, &fops_beacon); + debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers); - sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, - sc->debug.debugfs_phydir, sc, &fops_reset); + debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc, + &fops_beacon); - sc->debug.debugfs_antenna = debugfs_create_file("antenna", - S_IWUSR | S_IRUSR, - sc->debug.debugfs_phydir, sc, &fops_antenna); + debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset); - sc->debug.debugfs_misc = debugfs_create_file("misc", - S_IRUSR, - sc->debug.debugfs_phydir, sc, &fops_misc); + debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc, + &fops_antenna); - sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors", - S_IWUSR | S_IRUSR, - sc->debug.debugfs_phydir, sc, - &fops_frameerrors); + debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc); - sc->debug.debugfs_ani = debugfs_create_file("ani", - S_IWUSR | S_IRUSR, - sc->debug.debugfs_phydir, sc, - &fops_ani); + debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc, + &fops_frameerrors); - sc->debug.debugfs_queue = debugfs_create_file("queue", - S_IWUSR | S_IRUSR, - sc->debug.debugfs_phydir, sc, - &fops_queue); -} + debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani); -void -ath5k_debug_finish_device(struct ath5k_softc *sc) -{ - debugfs_remove(sc->debug.debugfs_debug); - debugfs_remove(sc->debug.debugfs_registers); - debugfs_remove(sc->debug.debugfs_beacon); - debugfs_remove(sc->debug.debugfs_reset); - debugfs_remove(sc->debug.debugfs_antenna); - debugfs_remove(sc->debug.debugfs_misc); - debugfs_remove(sc->debug.debugfs_frameerrors); - debugfs_remove(sc->debug.debugfs_ani); - debugfs_remove(sc->debug.debugfs_queue); - debugfs_remove(sc->debug.debugfs_phydir); + debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc, + &fops_queue); } - /* functions used in other places */ void diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index b0355aef68d3..193dd2d4ea3c 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h @@ -68,17 +68,6 @@ struct ath5k_buf; struct ath5k_dbg_info { unsigned int level; /* debug level */ - /* debugfs entries */ - struct dentry *debugfs_phydir; - struct dentry *debugfs_debug; - struct dentry *debugfs_registers; - struct dentry *debugfs_beacon; - struct dentry *debugfs_reset; - struct dentry *debugfs_antenna; - struct dentry *debugfs_misc; - struct dentry *debugfs_frameerrors; - struct dentry *debugfs_ani; - struct dentry *debugfs_queue; }; /** @@ -140,9 +129,6 @@ enum ath5k_debug_level { void ath5k_debug_init_device(struct ath5k_softc *sc); -void -ath5k_debug_finish_device(struct ath5k_softc *sc); - void ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah); @@ -166,9 +152,6 @@ ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) static inline void ath5k_debug_init_device(struct ath5k_softc *sc) {} -static inline void -ath5k_debug_finish_device(struct ath5k_softc *sc) {} - static inline void ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {} -- cgit v1.2.3-58-ga151 From c266c71a9cbdccb40fb6f4c05d4ddaa6226e5eba Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 10 Apr 2011 18:32:19 +0200 Subject: ath5k: reduce interrupt load caused by rx/tx interrupts While the rx/tx tasklet is pending, new unnecessary interrupts may arrive. Decrease the load by temporarily disabling the interrupts until the tasklet has completed. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 13 ++++++++++ drivers/net/wireless/ath/ath5k/base.c | 45 +++++++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath5k/base.h | 4 +++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index fcaf4ed84ca5..e303db7ee6f6 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -872,6 +872,19 @@ enum ath5k_int { AR5K_INT_QTRIG = 0x40000000, /* Non common */ AR5K_INT_GLOBAL = 0x80000000, + AR5K_INT_TX_ALL = AR5K_INT_TXOK + | AR5K_INT_TXDESC + | AR5K_INT_TXERR + | AR5K_INT_TXEOL + | AR5K_INT_TXURN, + + AR5K_INT_RX_ALL = AR5K_INT_RXOK + | AR5K_INT_RXDESC + | AR5K_INT_RXERR + | AR5K_INT_RXNOFRM + | AR5K_INT_RXEOL + | AR5K_INT_RXORN, + AR5K_INT_COMMON = AR5K_INT_RXOK | AR5K_INT_RXDESC | AR5K_INT_RXERR diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index a799d04e0c8c..c7da00454397 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1443,6 +1443,21 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) return true; } +static void +ath5k_set_current_imask(struct ath5k_softc *sc) +{ + enum ath5k_int imask = sc->imask; + unsigned long flags; + + spin_lock_irqsave(&sc->irqlock, flags); + if (sc->rx_pending) + imask &= ~AR5K_INT_RX_ALL; + if (sc->tx_pending) + imask &= ~AR5K_INT_TX_ALL; + ath5k_hw_set_imr(sc->ah, imask); + spin_unlock_irqrestore(&sc->irqlock, flags); +} + static void ath5k_tasklet_rx(unsigned long data) { @@ -1506,6 +1521,8 @@ next: } while (ath5k_rxbuf_setup(sc, bf) == 0); unlock: spin_unlock(&sc->rxbuflock); + sc->rx_pending = false; + ath5k_set_current_imask(sc); } @@ -1693,6 +1710,9 @@ ath5k_tasklet_tx(unsigned long data) for (i=0; i < AR5K_NUM_TX_QUEUES; i++) if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) ath5k_tx_processq(sc, &sc->txqs[i]); + + sc->tx_pending = false; + ath5k_set_current_imask(sc); } @@ -2122,6 +2142,20 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah) * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ } +static void +ath5k_schedule_rx(struct ath5k_softc *sc) +{ + sc->rx_pending = true; + tasklet_schedule(&sc->rxtq); +} + +static void +ath5k_schedule_tx(struct ath5k_softc *sc) +{ + sc->tx_pending = true; + tasklet_schedule(&sc->txtq); +} + irqreturn_t ath5k_intr(int irq, void *dev_id) { @@ -2164,7 +2198,7 @@ ath5k_intr(int irq, void *dev_id) ieee80211_queue_work(sc->hw, &sc->reset_work); } else - tasklet_schedule(&sc->rxtq); + ath5k_schedule_rx(sc); } else { if (status & AR5K_INT_SWBA) { tasklet_hi_schedule(&sc->beacontq); @@ -2182,10 +2216,10 @@ ath5k_intr(int irq, void *dev_id) ath5k_hw_update_tx_triglevel(ah, true); } if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) - tasklet_schedule(&sc->rxtq); + ath5k_schedule_rx(sc); if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC | AR5K_INT_TXERR | AR5K_INT_TXEOL)) - tasklet_schedule(&sc->txtq); + ath5k_schedule_tx(sc); if (status & AR5K_INT_BMISS) { /* TODO */ } @@ -2204,6 +2238,9 @@ ath5k_intr(int irq, void *dev_id) } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); + if (sc->rx_pending || sc->tx_pending) + ath5k_set_current_imask(sc); + if (unlikely(!counter)) ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); @@ -2575,6 +2612,8 @@ done: static void stop_tasklets(struct ath5k_softc *sc) { + sc->rx_pending = false; + sc->tx_pending = false; tasklet_kill(&sc->rxtq); tasklet_kill(&sc->txtq); tasklet_kill(&sc->calib); diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 978f1f4ac2f3..4c4e36064a3b 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -207,6 +207,10 @@ struct ath5k_softc { enum ath5k_int imask; /* interrupt mask copy */ + spinlock_t irqlock; + bool rx_pending; /* rx tasklet pending */ + bool tx_pending; /* tx tasklet pending */ + u8 lladdr[ETH_ALEN]; u8 bssidmask[ETH_ALEN]; -- cgit v1.2.3-58-ga151 From 0f8e94d2ae4f7966d09c8105ccabb3b3d8238a4d Mon Sep 17 00:00:00 2001 From: roel Date: Sun, 10 Apr 2011 21:09:50 +0200 Subject: ath9k_hw: index out of bounds Check whether index is within bounds before testing the element Both spurChans arrays in modalHeader5G and modalHeader2G have 5 elements, AR_EEPROM_MODAL_SPURS is defined 5. So unless a break occurs, in the last iteration (i=5) we tried to access spurChansPtr[5] before testing whether i was within bounds. Fix this. Signed-off-by: Roel Kluin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index eb250d6b8038..93398de0bf67 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -401,7 +401,7 @@ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah, ar9003_hw_spur_ofdm_clear(ah); - for (i = 0; spurChansPtr[i] && i < 5; i++) { + for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) { freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq; if (abs(freq_offset) < range) { ar9003_hw_spur_ofdm_work(ah, chan, freq_offset); -- cgit v1.2.3-58-ga151 From f0bce44f5f2eb37dba58aa992d0c58da92ded201 Mon Sep 17 00:00:00 2001 From: roel Date: Sun, 10 Apr 2011 21:09:55 +0200 Subject: ath9k: index out of bounds Check whether index is within bounds before testing the element Signed-off-by: Roel Kluin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index a3241cd089b1..2a40532126f3 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1092,8 +1092,7 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, if (!(rate->flags & IEEE80211_TX_RC_MCS)) return rate->idx; - while (rate->idx > mcs_rix_off[i] && - i < ARRAY_SIZE(mcs_rix_off)) { + while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) { rix++; i++; } -- cgit v1.2.3-58-ga151 From 228bdfca9a09c1263c24509b4bc23a67be168e1a Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Sun, 10 Apr 2011 18:30:23 -0500 Subject: rtlwifi: rtl8192ce: Fix LED initialization Driver rtl8192ce does not initialize the LED correctly. Signed-off-by: Chaoming Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/base.c | 12 +++++++----- drivers/net/wireless/rtlwifi/pci.c | 3 ++- drivers/net/wireless/rtlwifi/rtl8192ce/led.c | 14 +++++++++++--- drivers/net/wireless/rtlwifi/rtl8192ce/led.h | 1 - drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 1 - 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index dd5318ed7872..9477785f1168 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -251,14 +251,16 @@ void rtl_init_rfkill(struct ieee80211_hw *hw) bool blocked; u8 valid = 0; - radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); + /*set init state to on */ + rtlpriv->rfkill.rfkill_state = 1; + wiphy_rfkill_set_hw_state(hw->wiphy, 0); - /*set init state to that of switch */ - rtlpriv->rfkill.rfkill_state = radio_state; - printk(KERN_INFO "rtlwifi: wireless switch is %s\n", - rtlpriv->rfkill.rfkill_state ? "on" : "off"); + radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); if (valid) { + printk(KERN_INFO "rtlwifi: wireless switch is %s\n", + rtlpriv->rfkill.rfkill_state ? "on" : "off"); + rtlpriv->rfkill.rfkill_state = radio_state; blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1; diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index efded435d596..59a150ce3064 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1785,7 +1785,8 @@ void rtl_pci_disconnect(struct pci_dev *pdev) rtl_pci_deinit(hw); rtl_deinit_core(hw); - rtlpriv->cfg->ops->deinit_sw_leds(hw); + if (rtlpriv->cfg->ops->deinit_sw_leds) + rtlpriv->cfg->ops->deinit_sw_leds(hw); _rtl_pci_io_handler_release(hw); rtlpriv->cfg->ops->deinit_sw_vars(hw); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c index 7b1da8d7508f..d21b934b5c33 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c @@ -32,6 +32,14 @@ #include "reg.h" #include "led.h" +static void _rtl92ce_init_led(struct ieee80211_hw *hw, + struct rtl_led *pled, enum rtl_led_pin ledpin) +{ + pled->hw = hw; + pled->ledpin = ledpin; + pled->ledon = false; +} + void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) { u8 ledcfg; @@ -97,10 +105,10 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) void rtl92ce_init_sw_leds(struct ieee80211_hw *hw) { -} + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); -void rtl92ce_deinit_sw_leds(struct ieee80211_hw *hw) -{ + _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); + _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); } void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/rtlwifi/rtl8192ce/led.h index 10da3018f4b7..94332b3af5b1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.h @@ -31,7 +31,6 @@ #define __RTL92CE_LED_H__ void rtl92ce_init_sw_leds(struct ieee80211_hw *hw); -void rtl92ce_deinit_sw_leds(struct ieee80211_hw *hw); void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); void rtl92ce_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index b1cc4d44f534..f4e2f3dcccae 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -131,7 +131,6 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { .enable_hw_sec = rtl92ce_enable_hw_security_config, .set_key = rtl92ce_set_key, .init_sw_leds = rtl92ce_init_sw_leds, - .deinit_sw_leds = rtl92ce_deinit_sw_leds, .get_bbreg = rtl92c_phy_query_bb_reg, .set_bbreg = rtl92c_phy_set_bb_reg, .get_rfreg = rtl92ce_phy_query_rf_reg, -- cgit v1.2.3-58-ga151 From 3dfd7f606645279c788f48cfdfdf9565ec72c4f0 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Mon, 11 Apr 2011 16:39:40 +0530 Subject: ath9k: Implement integer mode for AR9485 This fixes random disconnect. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 15 ++++++++-- drivers/net/wireless/ath/ath9k/hw.c | 45 +++++++++++++++++++---------- drivers/net/wireless/ath/ath9k/phy.h | 1 - drivers/net/wireless/ath/ath9k/reg.h | 31 ++++++++++++++++---- 4 files changed, 67 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 93398de0bf67..1bc33f51e466 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -75,9 +75,18 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) freq = centers.synth_center; if (freq < 4800) { /* 2 GHz, fractional mode */ - if (AR_SREV_9485(ah)) - channelSel = CHANSEL_2G_9485(freq); - else + if (AR_SREV_9485(ah)) { + u32 chan_frac; + + /* + * freq_ref = 40 / (refdiva >> amoderefsel); where refdiva=1 and amoderefsel=0 + * ndiv = ((chan_mhz * 4) / 3) / freq_ref; + * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 + */ + channelSel = (freq * 4) / 120; + chan_frac = (((freq * 4) % 120) * 0x20000) / 120; + channelSel = (channelSel << 17) | chan_frac; + } else channelSel = CHANSEL_2G(freq); /* Set to 2G mode */ bMode = 1; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 1b5bd13b0a6c..3a8c41c782e9 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -676,42 +676,55 @@ unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) } EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); -#define DPLL2_KD_VAL 0x3D -#define DPLL2_KI_VAL 0x06 -#define DPLL3_PHASE_SHIFT_VAL 0x1 - +#define DPLL3_PHASE_SHIFT_VAL 0x1 static void ath9k_hw_init_pll(struct ath_hw *ah, struct ath9k_channel *chan) { u32 pll; if (AR_SREV_9485(ah)) { - REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); - REG_WRITE(ah, AR_CH0_DDR_DPLL2, 0x19e82f01); - - REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3, - AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); - REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); - udelay(1000); + /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */ + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_BB_DPLL2_PLL_PWD, 0x1); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_DPLL2_KD, 0x40); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_DPLL2_KI, 0x4); - REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, + AR_CH0_BB_DPLL1_REFDIV, 0x5); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, + AR_CH0_BB_DPLL1_NINI, 0x58); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, + AR_CH0_BB_DPLL1_NFRAC, 0x0); REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, - AR_CH0_DPLL2_KD, DPLL2_KD_VAL); + AR_CH0_BB_DPLL2_OUTDIV, 0x1); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_BB_DPLL2_LOCAL_PLL, 0x1); REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, - AR_CH0_DPLL2_KI, DPLL2_KI_VAL); + AR_CH0_BB_DPLL2_EN_NEGTRIG, 0x1); + /* program BB PLL phase_shift to 0x6 */ REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, - AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); - REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c); + AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x6); + + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_BB_DPLL2_PLL_PWD, 0x0); udelay(1000); + + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, + AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); } pll = ath9k_hw_compute_pll_control(ah, chan); REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); + if (AR_SREV_9485(ah)) + udelay(1000); + /* Switch the core clock for ar9271 to 117Mhz */ if (AR_SREV_9271(ah)) { udelay(500); diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index f50e2c29f71e..8e5fe9d7f174 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -19,7 +19,6 @@ #define CHANSEL_DIV 15 #define CHANSEL_2G(_freq) (((_freq) * 0x10000) / CHANSEL_DIV) -#define CHANSEL_2G_9485(_freq) ((((_freq) * 0x10000) - 215) / CHANSEL_DIV) #define CHANSEL_5G(_freq) (((_freq) * 0x8000) / CHANSEL_DIV) #define AR_PHY_BASE 0x9800 diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 2fbbe8842bb9..6acbf0e2240b 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1086,14 +1086,35 @@ enum { #define AR_ENT_OTP 0x40d8 #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 #define AR_ENT_OTP_MPSD 0x00800000 -#define AR_CH0_BB_DPLL2 0x16184 + +#define AR_CH0_BB_DPLL1 0x16180 +#define AR_CH0_BB_DPLL1_REFDIV 0xF8000000 +#define AR_CH0_BB_DPLL1_REFDIV_S 27 +#define AR_CH0_BB_DPLL1_NINI 0x07FC0000 +#define AR_CH0_BB_DPLL1_NINI_S 18 +#define AR_CH0_BB_DPLL1_NFRAC 0x0003FFFF +#define AR_CH0_BB_DPLL1_NFRAC_S 0 + +#define AR_CH0_BB_DPLL2 0x16184 +#define AR_CH0_BB_DPLL2_LOCAL_PLL 0x40000000 +#define AR_CH0_BB_DPLL2_LOCAL_PLL_S 30 +#define AR_CH0_DPLL2_KI 0x3C000000 +#define AR_CH0_DPLL2_KI_S 26 +#define AR_CH0_DPLL2_KD 0x03F80000 +#define AR_CH0_DPLL2_KD_S 19 +#define AR_CH0_BB_DPLL2_EN_NEGTRIG 0x00040000 +#define AR_CH0_BB_DPLL2_EN_NEGTRIG_S 18 +#define AR_CH0_BB_DPLL2_PLL_PWD 0x00010000 +#define AR_CH0_BB_DPLL2_PLL_PWD_S 16 +#define AR_CH0_BB_DPLL2_OUTDIV 0x0000E000 +#define AR_CH0_BB_DPLL2_OUTDIV_S 13 + #define AR_CH0_BB_DPLL3 0x16188 +#define AR_CH0_BB_DPLL3_PHASE_SHIFT 0x3F800000 +#define AR_CH0_BB_DPLL3_PHASE_SHIFT_S 23 + #define AR_CH0_DDR_DPLL2 0x16244 #define AR_CH0_DDR_DPLL3 0x16248 -#define AR_CH0_DPLL2_KD 0x03F80000 -#define AR_CH0_DPLL2_KD_S 19 -#define AR_CH0_DPLL2_KI 0x3C000000 -#define AR_CH0_DPLL2_KI_S 26 #define AR_CH0_DPLL3_PHASE_SHIFT 0x3F800000 #define AR_CH0_DPLL3_PHASE_SHIFT_S 23 #define AR_PHY_CCA_NOM_VAL_2GHZ -118 -- cgit v1.2.3-58-ga151 From 2d05a0c2b4ac614cb5e0eba75d39a37205d129e8 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 11 Apr 2011 20:22:28 +0530 Subject: ath9k_hw: Remove unused code in AR9287 eeprom Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom_9287.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 2f0712ea49a6..13579752a300 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -858,35 +858,12 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, { struct ar9287_eeprom *eep = &ah->eeprom.map9287; struct modal_eep_ar9287_header *pModal = &eep->modalHeader; - u16 antWrites[AR9287_ANT_16S]; u32 regChainOffset, regval; u8 txRxAttenLocal; - int i, j, offset_num; + int i; pModal = &eep->modalHeader; - antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF); - antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF); - antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF); - antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF); - antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF); - antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF); - antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF); - antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF); - - offset_num = 8; - - for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) { - antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf); - antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3); - antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3); - antWrites[j++] = 0; - antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3); - antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3); - antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3); - antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3); - } - REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); for (i = 0; i < AR9287_MAX_CHAINS; i++) { -- cgit v1.2.3-58-ga151 From 5fb32faf821586312dc0b51a64bfa17ad0633daf Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 11 Apr 2011 20:22:29 +0530 Subject: ath9k_hw: update Ar9003 intervals to fix carrier leak Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 96 +++++++++++----------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 9ecca93392e8..7f30bc686438 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -34,10 +34,10 @@ static const u32 ar9300_2p2_radio_postamble[][5] = { static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, - {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, - {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, @@ -119,14 +119,14 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, - {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, - {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000c2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, - {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, - {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, @@ -835,10 +835,10 @@ static const u32 ar9300_2p2_baseband_core[][2] = { static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, - {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, - {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, @@ -920,14 +920,14 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, - {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, - {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, - {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, - {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, @@ -941,10 +941,10 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800}, - {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000}, - {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, @@ -1026,14 +1026,14 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800}, - {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000}, - {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000c2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800}, - {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000}, - {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, @@ -1307,10 +1307,10 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = { static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, - {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, - {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, @@ -1392,14 +1392,14 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, - {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, - {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, - {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, - {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, -- cgit v1.2.3-58-ga151 From 901c1113da1efc98881233a8a67f98286a0b766a Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 11 Apr 2011 20:22:30 +0530 Subject: ath9k_hw: update AR9003 low_ob_db_tx_gain to improve spur performance Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 100 ++++++++++----------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 7f30bc686438..f915a3dbfcad 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -1307,9 +1307,9 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = { static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, @@ -1329,21 +1329,21 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, @@ -1361,44 +1361,44 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, - {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, - {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, - {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, - {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, + {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, + {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, -- cgit v1.2.3-58-ga151 From b3ba44c6d1633692b45910ee77064e635e2c3143 Mon Sep 17 00:00:00 2001 From: Mark Davis Date: Tue, 12 Apr 2011 00:19:10 -0400 Subject: rt2800usb: Add seven new USB IDs Adds USB IDs for seven previously missing devices. Additionally, all instances of 'Conceptronic' have been replaced by the OEM name. Devices added are.. 0411:01a2 - Buffalo WLI-UC-GNM, RT3070V 0586:341e - ZyXEL NWD2105, RT3070 13b1:002f - Linksys AE1000, RT3572 13b1:0031 - Cisco / Linksys AM10, RT3072 14b2:3c2c - Keebox W150NU / Alpha Networks WUS-N12, RT3070 157e:3013 - TRENDnet TEW-645UB, RT2770+RT2720 15a9:0012 - Airlink AWLL7025 / Gemtek WUBR-208N, RT2870+RT2850 Signed-off-by: Mark Davis Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 35 +++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6ba31a0e8f78..d2f5c87305a4 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -710,6 +710,16 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Alpha Networks */ + { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c2c), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Amit */ { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Askey */ @@ -736,15 +746,7 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Buffalo */ { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0411, 0x016f), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Conceptronic */ - { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0411, 0x01a2), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Corega */ { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -776,6 +778,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Gemtek */ + { USB_DEVICE(0x15a9, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gigabyte */ { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -792,6 +796,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Linksys */ + { USB_DEVICE(0x13b1, 0x0031), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Logitec */ @@ -870,8 +875,9 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sweex */ { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* U-Media*/ + /* U-Media */ { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x157e, 0x3013), USB_DEVICE_DATA(&rt2800usb_ops) }, /* ZCOM */ { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -883,6 +889,7 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Zyxel */ { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0586, 0x3418), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0586, 0x341e), USB_DEVICE_DATA(&rt2800usb_ops) }, #ifdef CONFIG_RT2800USB_RT33XX /* Ralink */ { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -901,6 +908,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, /* I-O DATA */ { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Linksys */ + { USB_DEVICE(0x13b1, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ralink */ { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ @@ -915,6 +924,9 @@ static struct usb_device_id rt2800usb_device_table[] = { * Unclear what kind of devices these are (they aren't supported by the * vendor linux driver). */ + /* Alpha Networks */ + { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Amigo */ { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -933,9 +945,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Conceptronic */ - { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Corega */ { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, -- cgit v1.2.3-58-ga151 From 6f11c819d5fb24b637f2db605e5d3c270c979627 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 12 Apr 2011 12:42:22 +0530 Subject: ath9k: Register id table for platform device Currently the device id in the platform driver is hardcoded to an id which is specific to AR9130/AR9132 SOCs as it supports only wmac (wireless mac) of these SOCs. But this needs to be dynamic when we want to support different wmac of SOCs. So add id_table to driver to make it extendable to more SOCs. Signed-off-by: Vasanthakumar Thiagarajan Acked-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ahb.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 9cb0efa9b4c0..5193ed58a17b 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -21,6 +21,14 @@ #include #include "ath9k.h" +const struct platform_device_id ath9k_platform_id_table[] = { + { + .name = "ath9k", + .driver_data = AR5416_AR9100_DEVID, + }, + {}, +}; + /* return bus cachesize in 4B word units */ static void ath_ahb_read_cachesize(struct ath_common *common, int *csz) { @@ -57,6 +65,7 @@ static int ath_ahb_probe(struct platform_device *pdev) struct ath_softc *sc; struct ieee80211_hw *hw; struct resource *res; + const struct platform_device_id *id = platform_get_device_id(pdev); int irq; int ret = 0; struct ath_hw *ah; @@ -116,7 +125,7 @@ static int ath_ahb_probe(struct platform_device *pdev) goto err_free_hw; } - ret = ath9k_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops); + ret = ath9k_init_device(id->driver_data, sc, 0x0, &ath_ahb_bus_ops); if (ret) { dev_err(&pdev->dev, "failed to initialize device\n"); goto err_irq; @@ -165,8 +174,11 @@ static struct platform_driver ath_ahb_driver = { .name = "ath9k", .owner = THIS_MODULE, }, + .id_table = ath9k_platform_id_table, }; +MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table); + int ath_ahb_init(void) { return platform_driver_register(&ath_ahb_driver); -- cgit v1.2.3-58-ga151 From bcc6d47903612c3861201cc3a866fb604f26b8b2 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 7 Apr 2011 19:48:33 +0000 Subject: net: vlan: make non-hw-accel rx path similar to hw-accel Now there are 2 paths for rx vlan frames. When rx-vlan-hw-accel is enabled, skb is untagged by NIC, vlan_tci is set and the skb gets into vlan code in __netif_receive_skb - vlan_hwaccel_do_receive. For non-rx-vlan-hw-accel however, tagged skb goes thru whole __netif_receive_skb, it's untagged in ptype_base hander and reinjected This incosistency is fixed by this patch. Vlan untagging happens early in __netif_receive_skb so the rest of code (ptype_all handlers, rx_handlers) see the skb like it was untagged by hw. Signed-off-by: Jiri Pirko v1->v2: remove "inline" from vlan_core.c functions Signed-off-by: David S. Miller --- include/linux/if_vlan.h | 10 ++- net/8021q/vlan.c | 8 --- net/8021q/vlan.h | 2 - net/8021q/vlan_core.c | 85 +++++++++++++++++++++++- net/8021q/vlan_dev.c | 173 ------------------------------------------------ net/core/dev.c | 8 ++- 6 files changed, 99 insertions(+), 187 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 635e1faec412..998b29930b80 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -132,7 +132,8 @@ extern u16 vlan_dev_vlan_id(const struct net_device *dev); extern int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci, int polling); -extern bool vlan_hwaccel_do_receive(struct sk_buff **skb); +extern bool vlan_do_receive(struct sk_buff **skb); +extern struct sk_buff *vlan_untag(struct sk_buff *skb); extern gro_result_t vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct sk_buff *skb); @@ -166,13 +167,18 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, return NET_XMIT_SUCCESS; } -static inline bool vlan_hwaccel_do_receive(struct sk_buff **skb) +static inline bool vlan_do_receive(struct sk_buff **skb) { if ((*skb)->vlan_tci & VLAN_VID_MASK) (*skb)->pkt_type = PACKET_OTHERHOST; return false; } +inline struct sk_buff *vlan_untag(struct sk_buff *skb) +{ + return skb; +} + static inline gro_result_t vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct sk_buff *skb) diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index e47600b4e2e3..14ef5efbc653 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -49,11 +49,6 @@ const char vlan_version[] = DRV_VERSION; static const char vlan_copyright[] = "Ben Greear "; static const char vlan_buggyright[] = "David S. Miller "; -static struct packet_type vlan_packet_type __read_mostly = { - .type = cpu_to_be16(ETH_P_8021Q), - .func = vlan_skb_recv, /* VLAN receive method */ -}; - /* End of global variables definitions. */ static void vlan_group_free(struct vlan_group *grp) @@ -684,7 +679,6 @@ static int __init vlan_proto_init(void) if (err < 0) goto err4; - dev_add_pack(&vlan_packet_type); vlan_ioctl_set(vlan_ioctl_handler); return 0; @@ -705,8 +699,6 @@ static void __exit vlan_cleanup_module(void) unregister_netdevice_notifier(&vlan_notifier_block); - dev_remove_pack(&vlan_packet_type); - unregister_pernet_subsys(&vlan_net_ops); rcu_barrier(); /* Wait for completion of call_rcu()'s */ diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 5687c9b95f33..c3408def8a19 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h @@ -75,8 +75,6 @@ static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev) } /* found in vlan_dev.c */ -int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *ptype, struct net_device *orig_dev); void vlan_dev_set_ingress_priority(const struct net_device *dev, u32 skb_prio, u16 vlan_prio); int vlan_dev_set_egress_priority(const struct net_device *dev, diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index ce8e3ab3e7a5..41495dc2a4c9 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -4,7 +4,7 @@ #include #include "vlan.h" -bool vlan_hwaccel_do_receive(struct sk_buff **skbp) +bool vlan_do_receive(struct sk_buff **skbp) { struct sk_buff *skb = *skbp; u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK; @@ -88,3 +88,86 @@ gro_result_t vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, return napi_gro_frags(napi); } EXPORT_SYMBOL(vlan_gro_frags); + +static struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) +{ + if (vlan_dev_info(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) { + if (skb_cow(skb, skb_headroom(skb)) < 0) + skb = NULL; + if (skb) { + /* Lifted from Gleb's VLAN code... */ + memmove(skb->data - ETH_HLEN, + skb->data - VLAN_ETH_HLEN, 12); + skb->mac_header += VLAN_HLEN; + } + } + return skb; +} + +static void vlan_set_encap_proto(struct sk_buff *skb, struct vlan_hdr *vhdr) +{ + __be16 proto; + unsigned char *rawp; + + /* + * Was a VLAN packet, grab the encapsulated protocol, which the layer + * three protocols care about. + */ + + proto = vhdr->h_vlan_encapsulated_proto; + if (ntohs(proto) >= 1536) { + skb->protocol = proto; + return; + } + + rawp = skb->data; + if (*(unsigned short *) rawp == 0xFFFF) + /* + * This is a magic hack to spot IPX packets. Older Novell + * breaks the protocol design and runs IPX over 802.3 without + * an 802.2 LLC layer. We look for FFFF which isn't a used + * 802.2 SSAP/DSAP. This won't work for fault tolerant netware + * but does for the rest. + */ + skb->protocol = htons(ETH_P_802_3); + else + /* + * Real 802.2 LLC + */ + skb->protocol = htons(ETH_P_802_2); +} + +struct sk_buff *vlan_untag(struct sk_buff *skb) +{ + struct vlan_hdr *vhdr; + u16 vlan_tci; + + if (unlikely(vlan_tx_tag_present(skb))) { + /* vlan_tci is already set-up so leave this for another time */ + return skb; + } + + skb = skb_share_check(skb, GFP_ATOMIC); + if (unlikely(!skb)) + goto err_free; + + if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) + goto err_free; + + vhdr = (struct vlan_hdr *) skb->data; + vlan_tci = ntohs(vhdr->h_vlan_TCI); + __vlan_hwaccel_put_tag(skb, vlan_tci); + + skb_pull_rcsum(skb, VLAN_HLEN); + vlan_set_encap_proto(skb, vhdr); + + skb = vlan_check_reorder_header(skb); + if (unlikely(!skb)) + goto err_free; + + return skb; + +err_free: + kfree_skb(skb); + return NULL; +} diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index b84a46b30c0c..d174c312b7f1 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -65,179 +65,6 @@ static int vlan_dev_rebuild_header(struct sk_buff *skb) return 0; } -static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) -{ - if (vlan_dev_info(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) { - if (skb_cow(skb, skb_headroom(skb)) < 0) - skb = NULL; - if (skb) { - /* Lifted from Gleb's VLAN code... */ - memmove(skb->data - ETH_HLEN, - skb->data - VLAN_ETH_HLEN, 12); - skb->mac_header += VLAN_HLEN; - } - } - - return skb; -} - -static inline void vlan_set_encap_proto(struct sk_buff *skb, - struct vlan_hdr *vhdr) -{ - __be16 proto; - unsigned char *rawp; - - /* - * Was a VLAN packet, grab the encapsulated protocol, which the layer - * three protocols care about. - */ - - proto = vhdr->h_vlan_encapsulated_proto; - if (ntohs(proto) >= 1536) { - skb->protocol = proto; - return; - } - - rawp = skb->data; - if (*(unsigned short *)rawp == 0xFFFF) - /* - * This is a magic hack to spot IPX packets. Older Novell - * breaks the protocol design and runs IPX over 802.3 without - * an 802.2 LLC layer. We look for FFFF which isn't a used - * 802.2 SSAP/DSAP. This won't work for fault tolerant netware - * but does for the rest. - */ - skb->protocol = htons(ETH_P_802_3); - else - /* - * Real 802.2 LLC - */ - skb->protocol = htons(ETH_P_802_2); -} - -/* - * Determine the packet's protocol ID. The rule here is that we - * assume 802.3 if the type field is short enough to be a length. - * This is normal practice and works for any 'now in use' protocol. - * - * Also, at this point we assume that we ARE dealing exclusively with - * VLAN packets, or packets that should be made into VLAN packets based - * on a default VLAN ID. - * - * NOTE: Should be similar to ethernet/eth.c. - * - * SANITY NOTE: This method is called when a packet is moving up the stack - * towards userland. To get here, it would have already passed - * through the ethernet/eth.c eth_type_trans() method. - * SANITY NOTE 2: We are referencing to the VLAN_HDR frields, which MAY be - * stored UNALIGNED in the memory. RISC systems don't like - * such cases very much... - * SANITY NOTE 2a: According to Dave Miller & Alexey, it will always be - * aligned, so there doesn't need to be any of the unaligned - * stuff. It has been commented out now... --Ben - * - */ -int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *ptype, struct net_device *orig_dev) -{ - struct vlan_hdr *vhdr; - struct vlan_pcpu_stats *rx_stats; - struct net_device *vlan_dev; - u16 vlan_id; - u16 vlan_tci; - - skb = skb_share_check(skb, GFP_ATOMIC); - if (skb == NULL) - goto err_free; - - if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) - goto err_free; - - vhdr = (struct vlan_hdr *)skb->data; - vlan_tci = ntohs(vhdr->h_vlan_TCI); - vlan_id = vlan_tci & VLAN_VID_MASK; - - rcu_read_lock(); - vlan_dev = vlan_find_dev(dev, vlan_id); - - /* If the VLAN device is defined, we use it. - * If not, and the VID is 0, it is a 802.1p packet (not - * really a VLAN), so we will just netif_rx it later to the - * original interface, but with the skb->proto set to the - * wrapped proto: we do nothing here. - */ - - if (!vlan_dev) { - if (vlan_id) { - pr_debug("%s: ERROR: No net_device for VID: %u on dev: %s\n", - __func__, vlan_id, dev->name); - goto err_unlock; - } - rx_stats = NULL; - } else { - skb->dev = vlan_dev; - - rx_stats = this_cpu_ptr(vlan_dev_info(skb->dev)->vlan_pcpu_stats); - - u64_stats_update_begin(&rx_stats->syncp); - rx_stats->rx_packets++; - rx_stats->rx_bytes += skb->len; - - skb->priority = vlan_get_ingress_priority(skb->dev, vlan_tci); - - pr_debug("%s: priority: %u for TCI: %hu\n", - __func__, skb->priority, vlan_tci); - - switch (skb->pkt_type) { - case PACKET_BROADCAST: - /* Yeah, stats collect these together.. */ - /* stats->broadcast ++; // no such counter :-( */ - break; - - case PACKET_MULTICAST: - rx_stats->rx_multicast++; - break; - - case PACKET_OTHERHOST: - /* Our lower layer thinks this is not local, let's make - * sure. - * This allows the VLAN to have a different MAC than the - * underlying device, and still route correctly. - */ - if (!compare_ether_addr(eth_hdr(skb)->h_dest, - skb->dev->dev_addr)) - skb->pkt_type = PACKET_HOST; - break; - default: - break; - } - u64_stats_update_end(&rx_stats->syncp); - } - - skb_pull_rcsum(skb, VLAN_HLEN); - vlan_set_encap_proto(skb, vhdr); - - if (vlan_dev) { - skb = vlan_check_reorder_header(skb); - if (!skb) { - rx_stats->rx_errors++; - goto err_unlock; - } - } - - netif_rx(skb); - - rcu_read_unlock(); - return NET_RX_SUCCESS; - -err_unlock: - rcu_read_unlock(); -err_free: - atomic_long_inc(&dev->rx_dropped); - kfree_skb(skb); - return NET_RX_DROP; -} - static inline u16 vlan_dev_get_egress_qos_mask(struct net_device *dev, struct sk_buff *skb) { diff --git a/net/core/dev.c b/net/core/dev.c index 95897ff3a76f..d1aebf7c6494 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3130,6 +3130,12 @@ another_round: __this_cpu_inc(softnet_data.processed); + if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { + skb = vlan_untag(skb); + if (unlikely(!skb)) + goto out; + } + #ifdef CONFIG_NET_CLS_ACT if (skb->tc_verd & TC_NCLS) { skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); @@ -3177,7 +3183,7 @@ ncls: ret = deliver_skb(skb, pt_prev, orig_dev); pt_prev = NULL; } - if (vlan_hwaccel_do_receive(&skb)) { + if (vlan_do_receive(&skb)) { ret = __netif_receive_skb(skb); goto out; } else if (unlikely(!skb)) -- cgit v1.2.3-58-ga151 From 872674858fe236b746317741013c830bb70775c2 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 12 Apr 2011 09:56:38 +0000 Subject: net: add RTNL_ASSERT in __netdev_update_features() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- net/core/dev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index d1aebf7c6494..f523eee3141c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5247,6 +5247,8 @@ int __netdev_update_features(struct net_device *dev) u32 features; int err = 0; + ASSERT_RTNL(); + features = netdev_get_wanted_features(dev); if (dev->netdev_ops->ndo_fix_features) -- cgit v1.2.3-58-ga151 From f5d640371dacda100a32a30e8013f957aff26ce1 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 10 Apr 2011 03:13:21 +0000 Subject: net: sky2: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Caveats: - driver modifies vlan_features on HW VLAN TX changes - broken RX checksum will be reenabled on features change Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/sky2.c | 161 ++++++++++++++++++++--------------------------------- drivers/net/sky2.h | 1 - 2 files changed, 59 insertions(+), 103 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 336c762515b2..a4b8fe564eb0 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1198,12 +1198,12 @@ static void rx_set_checksum(struct sky2_port *sky2) sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), - (sky2->flags & SKY2_FLAG_RX_CHECKSUM) + (sky2->netdev->features & NETIF_F_RXCSUM) ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); } /* Enable/disable receive hash calculation (RSS) */ -static void rx_set_rss(struct net_device *dev) +static void rx_set_rss(struct net_device *dev, u32 features) { struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; @@ -1216,7 +1216,7 @@ static void rx_set_rss(struct net_device *dev) } /* Program RSS initial values */ - if (dev->features & NETIF_F_RXHASH) { + if (features & NETIF_F_RXHASH) { u32 key[nkeys]; get_random_bytes(key, nkeys * sizeof(u32)); @@ -1322,32 +1322,32 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return err; } -#define NETIF_F_ALL_VLAN (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX) +#define SKY2_VLAN_OFFLOADS (NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO) -static void sky2_vlan_mode(struct net_device *dev) +static void sky2_vlan_mode(struct net_device *dev, u32 features) { struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; u16 port = sky2->port; - if (dev->features & NETIF_F_HW_VLAN_RX) + if (features & NETIF_F_HW_VLAN_RX) sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON); else sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF); - dev->vlan_features = dev->features &~ NETIF_F_ALL_VLAN; - if (dev->features & NETIF_F_HW_VLAN_TX) + if (features & NETIF_F_HW_VLAN_TX) { sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_ON); - else { + + dev->vlan_features |= SKY2_VLAN_OFFLOADS; + } else { sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF); /* Can't do transmit offload of vlan without hw vlan */ - dev->vlan_features &= ~(NETIF_F_TSO | NETIF_F_SG - | NETIF_F_ALL_CSUM); + dev->vlan_features &= ~SKY2_VLAN_OFFLOADS; } } @@ -1463,7 +1463,7 @@ static void sky2_rx_start(struct sky2_port *sky2) rx_set_checksum(sky2); if (!(hw->flags & SKY2_HW_RSS_BROKEN)) - rx_set_rss(sky2->netdev); + rx_set_rss(sky2->netdev, sky2->netdev->features); /* submit Rx ring */ for (i = 0; i < sky2->rx_pending; i++) { @@ -1626,7 +1626,8 @@ static void sky2_hw_up(struct sky2_port *sky2) sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, sky2->tx_ring_size - 1); - sky2_vlan_mode(sky2->netdev); + sky2_vlan_mode(sky2->netdev, sky2->netdev->features); + netdev_update_features(sky2->netdev); sky2_rx_start(sky2); } @@ -2261,12 +2262,9 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) hw->chip_id == CHIP_ID_YUKON_FE_P)) return -EINVAL; - /* TSO, etc on Yukon Ultra and MTU > 1500 not supported */ - if (new_mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U) - dev->features &= ~(NETIF_F_TSO|NETIF_F_SG|NETIF_F_ALL_CSUM); - if (!netif_running(dev)) { dev->mtu = new_mtu; + netdev_update_features(dev); return 0; } @@ -2288,6 +2286,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) sky2_rx_clean(sky2); dev->mtu = new_mtu; + netdev_update_features(dev); mode = DATA_BLIND_VAL(DATA_BLIND_DEF) | GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF); @@ -2535,8 +2534,11 @@ static void sky2_rx_checksum(struct sky2_port *sky2, u32 status) "%s: receive checksum problem (status = %#x)\n", sky2->netdev->name, status); - /* Disable checksum offload */ - sky2->flags &= ~SKY2_FLAG_RX_CHECKSUM; + /* Disable checksum offload + * It will be reenabled on next ndo_set_features, but if it's + * really broken, will get disabled again + */ + sky2->netdev->features &= ~NETIF_F_RXCSUM; sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), BMU_DIS_RX_CHKSUM); } @@ -2591,7 +2593,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) /* This chip reports checksum status differently */ if (hw->flags & SKY2_HW_NEW_LE) { - if ((sky2->flags & SKY2_FLAG_RX_CHECKSUM) && + if ((dev->features & NETIF_F_RXCSUM) && (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) && (le->css & CSS_TCPUDPCSOK)) skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -2616,7 +2618,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) sky2->rx_tag = length; /* fall through */ case OP_RXCHKS: - if (likely(sky2->flags & SKY2_FLAG_RX_CHECKSUM)) + if (likely(dev->features & NETIF_F_RXCSUM)) sky2_rx_checksum(sky2, status); break; @@ -3552,28 +3554,6 @@ static const struct sky2_stat { { "tx_fifo_underrun", GM_TXE_FIFO_UR }, }; -static u32 sky2_get_rx_csum(struct net_device *dev) -{ - struct sky2_port *sky2 = netdev_priv(dev); - - return !!(sky2->flags & SKY2_FLAG_RX_CHECKSUM); -} - -static int sky2_set_rx_csum(struct net_device *dev, u32 data) -{ - struct sky2_port *sky2 = netdev_priv(dev); - - if (data) - sky2->flags |= SKY2_FLAG_RX_CHECKSUM; - else - sky2->flags &= ~SKY2_FLAG_RX_CHECKSUM; - - sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), - data ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); - - return 0; -} - static u32 sky2_get_msglevel(struct net_device *netdev) { struct sky2_port *sky2 = netdev_priv(netdev); @@ -4084,34 +4064,6 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs, } } -/* In order to do Jumbo packets on these chips, need to turn off the - * transmit store/forward. Therefore checksum offload won't work. - */ -static int no_tx_offload(struct net_device *dev) -{ - const struct sky2_port *sky2 = netdev_priv(dev); - const struct sky2_hw *hw = sky2->hw; - - return dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U; -} - -static int sky2_set_tx_csum(struct net_device *dev, u32 data) -{ - if (data && no_tx_offload(dev)) - return -EINVAL; - - return ethtool_op_set_tx_csum(dev, data); -} - - -static int sky2_set_tso(struct net_device *dev, u32 data) -{ - if (data && no_tx_offload(dev)) - return -EINVAL; - - return ethtool_op_set_tso(dev, data); -} - static int sky2_get_eeprom_len(struct net_device *dev) { struct sky2_port *sky2 = netdev_priv(dev); @@ -4214,31 +4166,36 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom return sky2_vpd_write(sky2->hw, cap, data, eeprom->offset, eeprom->len); } -static int sky2_set_flags(struct net_device *dev, u32 data) +static u32 sky2_fix_features(struct net_device *dev, u32 features) { - struct sky2_port *sky2 = netdev_priv(dev); - unsigned long old_feat = dev->features; - u32 supported = 0; - int rc; + const struct sky2_port *sky2 = netdev_priv(dev); + const struct sky2_hw *hw = sky2->hw; - if (!(sky2->hw->flags & SKY2_HW_RSS_BROKEN)) - supported |= ETH_FLAG_RXHASH; + /* In order to do Jumbo packets on these chips, need to turn off the + * transmit store/forward. Therefore checksum offload won't work. + */ + if (dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U) + features &= ~(NETIF_F_TSO|NETIF_F_SG|NETIF_F_ALL_CSUM); - if (!(sky2->hw->flags & SKY2_HW_VLAN_BROKEN)) - supported |= ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN; + return features; +} - printk(KERN_DEBUG "sky2 set_flags: supported %x data %x\n", - supported, data); +static int sky2_set_features(struct net_device *dev, u32 features) +{ + struct sky2_port *sky2 = netdev_priv(dev); + u32 changed = dev->features ^ features; - rc = ethtool_op_set_flags(dev, data, supported); - if (rc) - return rc; + if (changed & NETIF_F_RXCSUM) { + u32 on = features & NETIF_F_RXCSUM; + sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), + on ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); + } - if ((old_feat ^ dev->features) & NETIF_F_RXHASH) - rx_set_rss(dev); + if (changed & NETIF_F_RXHASH) + rx_set_rss(dev, features); - if ((old_feat ^ dev->features) & NETIF_F_ALL_VLAN) - sky2_vlan_mode(dev); + if (changed & (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX)) + sky2_vlan_mode(dev, features); return 0; } @@ -4258,11 +4215,6 @@ static const struct ethtool_ops sky2_ethtool_ops = { .get_eeprom_len = sky2_get_eeprom_len, .get_eeprom = sky2_get_eeprom, .set_eeprom = sky2_set_eeprom, - .set_sg = ethtool_op_set_sg, - .set_tx_csum = sky2_set_tx_csum, - .set_tso = sky2_set_tso, - .get_rx_csum = sky2_get_rx_csum, - .set_rx_csum = sky2_set_rx_csum, .get_strings = sky2_get_strings, .get_coalesce = sky2_get_coalesce, .set_coalesce = sky2_set_coalesce, @@ -4273,8 +4225,6 @@ static const struct ethtool_ops sky2_ethtool_ops = { .set_phys_id = sky2_set_phys_id, .get_sset_count = sky2_get_sset_count, .get_ethtool_stats = sky2_get_ethtool_stats, - .set_flags = sky2_set_flags, - .get_flags = ethtool_op_get_flags, }; #ifdef CONFIG_SKY2_DEBUG @@ -4554,6 +4504,8 @@ static const struct net_device_ops sky2_netdev_ops[2] = { .ndo_set_mac_address = sky2_set_mac_address, .ndo_set_multicast_list = sky2_set_multicast, .ndo_change_mtu = sky2_change_mtu, + .ndo_fix_features = sky2_fix_features, + .ndo_set_features = sky2_set_features, .ndo_tx_timeout = sky2_tx_timeout, .ndo_get_stats64 = sky2_get_stats, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -4569,6 +4521,8 @@ static const struct net_device_ops sky2_netdev_ops[2] = { .ndo_set_mac_address = sky2_set_mac_address, .ndo_set_multicast_list = sky2_set_multicast, .ndo_change_mtu = sky2_change_mtu, + .ndo_fix_features = sky2_fix_features, + .ndo_set_features = sky2_set_features, .ndo_tx_timeout = sky2_tx_timeout, .ndo_get_stats64 = sky2_get_stats, }, @@ -4601,7 +4555,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, /* Auto speed and flow control */ sky2->flags = SKY2_FLAG_AUTO_SPEED | SKY2_FLAG_AUTO_PAUSE; if (hw->chip_id != CHIP_ID_YUKON_XL) - sky2->flags |= SKY2_FLAG_RX_CHECKSUM; + dev->hw_features |= NETIF_F_RXCSUM; sky2->flow_mode = FC_BOTH; @@ -4620,18 +4574,21 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, sky2->port = port; - dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG - | NETIF_F_TSO | NETIF_F_GRO; + dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO; if (highmem) dev->features |= NETIF_F_HIGHDMA; /* Enable receive hashing unless hardware is known broken */ if (!(hw->flags & SKY2_HW_RSS_BROKEN)) - dev->features |= NETIF_F_RXHASH; + dev->hw_features |= NETIF_F_RXHASH; + + if (!(hw->flags & SKY2_HW_VLAN_BROKEN)) { + dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->vlan_features |= SKY2_VLAN_OFFLOADS; + } - if (!(hw->flags & SKY2_HW_VLAN_BROKEN)) - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->features |= dev->hw_features; /* read the mac address */ memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN); diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 0c6d10c5f053..318c9ae7bf91 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -2254,7 +2254,6 @@ struct sky2_port { u8 wol; /* WAKE_ bits */ u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */ u16 flags; -#define SKY2_FLAG_RX_CHECKSUM 0x0001 #define SKY2_FLAG_AUTO_SPEED 0x0002 #define SKY2_FLAG_AUTO_PAUSE 0x0004 -- cgit v1.2.3-58-ga151 From d1423c7ab847e72a63e0e3512a1a7f3bce55ae01 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 10 Apr 2011 04:49:55 +0000 Subject: net: ps3_gelic: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/ps3_gelic_net.c | 26 +++++--------------------- drivers/net/ps3_gelic_net.h | 3 --- drivers/net/ps3_gelic_wireless.c | 4 ---- 3 files changed, 5 insertions(+), 28 deletions(-) diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index ffdf7349ef7a..4383ed21813e 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c @@ -951,7 +951,7 @@ static void gelic_net_pass_skb_up(struct gelic_descr *descr, skb->protocol = eth_type_trans(skb, netdev); /* checksum offload */ - if (card->rx_csum) { + if (netdev->features & NETIF_F_RXCSUM) { if ((data_status & GELIC_DESCR_DATA_STATUS_CHK_MASK) && (!(data_error & GELIC_DESCR_DATA_ERROR_CHK_MASK))) skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -1312,21 +1312,6 @@ static int gelic_ether_set_settings(struct net_device *netdev, return 0; } -u32 gelic_net_get_rx_csum(struct net_device *netdev) -{ - struct gelic_card *card = netdev_card(netdev); - - return card->rx_csum; -} - -int gelic_net_set_rx_csum(struct net_device *netdev, u32 data) -{ - struct gelic_card *card = netdev_card(netdev); - - card->rx_csum = data; - return 0; -} - static void gelic_net_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { @@ -1411,10 +1396,6 @@ static const struct ethtool_ops gelic_ether_ethtool_ops = { .get_settings = gelic_ether_get_settings, .set_settings = gelic_ether_set_settings, .get_link = ethtool_op_get_link, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .get_rx_csum = gelic_net_get_rx_csum, - .set_rx_csum = gelic_net_set_rx_csum, .get_wol = gelic_net_get_wol, .set_wol = gelic_net_set_wol, }; @@ -1512,7 +1493,11 @@ int __devinit gelic_net_setup_netdev(struct net_device *netdev, int status; u64 v1, v2; + netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM; + netdev->features = NETIF_F_IP_CSUM; + if (GELIC_CARD_RX_CSUM_DEFAULT) + netdev->features |= NETIF_F_RXCSUM; status = lv1_net_control(bus_id(card), dev_id(card), GELIC_LV1_GET_MAC_ADDRESS, @@ -1756,7 +1741,6 @@ static int __devinit ps3_gelic_driver_probe(struct ps3_system_bus_device *dev) /* setup card structure */ card->irq_mask = GELIC_CARD_RXINT | GELIC_CARD_TXINT | GELIC_CARD_PORT_STATUS_CHANGED; - card->rx_csum = GELIC_CARD_RX_CSUM_DEFAULT; if (gelic_card_init_chain(card, &card->tx_chain, diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h index fadadf9097a3..d9a55b93898b 100644 --- a/drivers/net/ps3_gelic_net.h +++ b/drivers/net/ps3_gelic_net.h @@ -290,7 +290,6 @@ struct gelic_card { struct gelic_descr_chain tx_chain; struct gelic_descr_chain rx_chain; int rx_dma_restart_required; - int rx_csum; /* * tx_lock guards tx descriptor list and * tx_dma_progress. @@ -377,8 +376,6 @@ extern int gelic_net_setup_netdev(struct net_device *netdev, /* shared ethtool ops */ extern void gelic_net_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info); -extern u32 gelic_net_get_rx_csum(struct net_device *netdev); -extern int gelic_net_set_rx_csum(struct net_device *netdev, u32 data); extern void gelic_net_poll_controller(struct net_device *netdev); #endif /* _GELIC_NET_H */ diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index b5ae29d20f2e..2e62938c0f82 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c @@ -2581,10 +2581,6 @@ static const struct net_device_ops gelic_wl_netdevice_ops = { static const struct ethtool_ops gelic_wl_ethtool_ops = { .get_drvinfo = gelic_net_get_drvinfo, .get_link = gelic_wl_get_link, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .get_rx_csum = gelic_net_get_rx_csum, - .set_rx_csum = gelic_net_set_rx_csum, }; static void __devinit gelic_wl_setup_netdev_ops(struct net_device *netdev) -- cgit v1.2.3-58-ga151 From e5ee20e70f078d584572709962f5d90f876912c3 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 12 Apr 2011 09:38:23 +0000 Subject: net: bna: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note: looks like bnad->conf_mutex is duplicating rtnl_lock. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/bna/bnad.c | 22 ++++++--------- drivers/net/bna/bnad.h | 2 -- drivers/net/bna/bnad_ethtool.c | 63 ------------------------------------------ 3 files changed, 9 insertions(+), 78 deletions(-) diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c index 9f356d5d0f33..b9f253470da2 100644 --- a/drivers/net/bna/bnad.c +++ b/drivers/net/bna/bnad.c @@ -501,7 +501,7 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget) skb_put(skb, ntohs(cmpl->length)); if (likely - (bnad->rx_csum && + ((bnad->netdev->features & NETIF_F_RXCSUM) && (((flags & BNA_CQ_EF_IPV4) && (flags & BNA_CQ_EF_L3_CKSUM_OK)) || (flags & BNA_CQ_EF_IPV6)) && @@ -2903,23 +2903,20 @@ bnad_netdev_init(struct bnad *bnad, bool using_dac) { struct net_device *netdev = bnad->netdev; - netdev->features |= NETIF_F_IPV6_CSUM; - netdev->features |= NETIF_F_TSO; - netdev->features |= NETIF_F_TSO6; + netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_VLAN_TX; - netdev->features |= NETIF_F_GRO; - pr_warn("bna: GRO enabled, using kernel stack GRO\n"); + netdev->vlan_features = NETIF_F_SG | NETIF_F_HIGHDMA | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_TSO | NETIF_F_TSO6; - netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + netdev->features |= netdev->hw_features | + NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; if (using_dac) netdev->features |= NETIF_F_HIGHDMA; - netdev->features |= - NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | - NETIF_F_HW_VLAN_FILTER; - - netdev->vlan_features = netdev->features; netdev->mem_start = bnad->mmio_start; netdev->mem_end = bnad->mmio_start + bnad->mmio_len - 1; @@ -2970,7 +2967,6 @@ bnad_init(struct bnad *bnad, bnad->txq_depth = BNAD_TXQ_DEPTH; bnad->rxq_depth = BNAD_RXQ_DEPTH; - bnad->rx_csum = true; bnad->tx_coalescing_timeo = BFI_TX_COALESCING_TIMEO; bnad->rx_coalescing_timeo = BFI_RX_COALESCING_TIMEO; diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h index a89117fa4970..ccdabad0a40c 100644 --- a/drivers/net/bna/bnad.h +++ b/drivers/net/bna/bnad.h @@ -237,8 +237,6 @@ struct bnad { struct bna_rx_config rx_config[BNAD_MAX_RXS]; struct bna_tx_config tx_config[BNAD_MAX_TXS]; - u32 rx_csum; - void __iomem *bar0; /* BAR0 address */ struct bna bna; diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c index 142d6047da27..c51e078e8f0d 100644 --- a/drivers/net/bna/bnad_ethtool.c +++ b/drivers/net/bna/bnad_ethtool.c @@ -806,61 +806,6 @@ bnad_set_pauseparam(struct net_device *netdev, return 0; } -static u32 -bnad_get_rx_csum(struct net_device *netdev) -{ - u32 rx_csum; - struct bnad *bnad = netdev_priv(netdev); - - rx_csum = bnad->rx_csum; - return rx_csum; -} - -static int -bnad_set_rx_csum(struct net_device *netdev, u32 rx_csum) -{ - struct bnad *bnad = netdev_priv(netdev); - - mutex_lock(&bnad->conf_mutex); - bnad->rx_csum = rx_csum; - mutex_unlock(&bnad->conf_mutex); - return 0; -} - -static int -bnad_set_tx_csum(struct net_device *netdev, u32 tx_csum) -{ - struct bnad *bnad = netdev_priv(netdev); - - mutex_lock(&bnad->conf_mutex); - if (tx_csum) { - netdev->features |= NETIF_F_IP_CSUM; - netdev->features |= NETIF_F_IPV6_CSUM; - } else { - netdev->features &= ~NETIF_F_IP_CSUM; - netdev->features &= ~NETIF_F_IPV6_CSUM; - } - mutex_unlock(&bnad->conf_mutex); - return 0; -} - -static int -bnad_set_tso(struct net_device *netdev, u32 tso) -{ - struct bnad *bnad = netdev_priv(netdev); - - mutex_lock(&bnad->conf_mutex); - if (tso) { - netdev->features |= NETIF_F_TSO; - netdev->features |= NETIF_F_TSO6; - } else { - netdev->features &= ~NETIF_F_TSO; - netdev->features &= ~NETIF_F_TSO6; - } - mutex_unlock(&bnad->conf_mutex); - return 0; -} - static void bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string) { @@ -1256,14 +1201,6 @@ static struct ethtool_ops bnad_ethtool_ops = { .set_ringparam = bnad_set_ringparam, .get_pauseparam = bnad_get_pauseparam, .set_pauseparam = bnad_set_pauseparam, - .get_rx_csum = bnad_get_rx_csum, - .set_rx_csum = bnad_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = bnad_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = bnad_set_tso, .get_strings = bnad_get_strings, .get_ethtool_stats = bnad_get_ethtool_stats, .get_sset_count = bnad_get_sset_count -- cgit v1.2.3-58-ga151 From 66371c44136b566f39f70c72cb4d117558bee3fa Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 12 Apr 2011 09:38:23 +0000 Subject: net: bnx2x: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since ndo_fix_features callback is postponing features change when bp->recovery_state != BNX2X_RECOVERY_DONE, netdev_update_features() has to be called again when this condition changes. Previously, ethtool_ops->set_flags callback returned -EBUSY in that case (it's not possible in the new model). Signed-off-by: Michał Mirosław v5: - don't delay set_features, as it's rtnl_locked - same as recovery process v4: - complete bp->rx_csum -> NETIF_F_RXCSUM conversion - add check for failed ndo_set_features in ndo_open callback v3: - include NETIF_F_LRO in hw_features - don't call netdev_update_features() if bnx2x_nic_load() failed v2: - comment in ndo_fix_features callback Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x.h | 1 - drivers/net/bnx2x/bnx2x_cmn.c | 49 +++++++++++++++++--- drivers/net/bnx2x/bnx2x_cmn.h | 3 ++ drivers/net/bnx2x/bnx2x_ethtool.c | 95 --------------------------------------- drivers/net/bnx2x/bnx2x_main.c | 27 +++++------ 5 files changed, 57 insertions(+), 118 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index e0fca701d2f3..9e87417f6ec7 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -918,7 +918,6 @@ struct bnx2x { int tx_ring_size; - u32 rx_csum; /* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */ #define ETH_OVREHEAD (ETH_HLEN + 8 + 8) #define ETH_MIN_PACKET_SIZE 60 diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index e83ac6dd6fc0..bec33a87bcdc 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -640,7 +640,7 @@ reuse_rx: skb_checksum_none_assert(skb); - if (bp->rx_csum) { + if (bp->dev->features & NETIF_F_RXCSUM) { if (likely(BNX2X_RX_CSUM_OK(cqe))) skb->ip_summed = CHECKSUM_UNNECESSARY; else @@ -2443,11 +2443,21 @@ alloc_err: } +static int bnx2x_reload_if_running(struct net_device *dev) +{ + struct bnx2x *bp = netdev_priv(dev); + + if (unlikely(!netif_running(dev))) + return 0; + + bnx2x_nic_unload(bp, UNLOAD_NORMAL); + return bnx2x_nic_load(bp, LOAD_NORMAL); +} + /* called with rtnl_lock */ int bnx2x_change_mtu(struct net_device *dev, int new_mtu) { struct bnx2x *bp = netdev_priv(dev); - int rc = 0; if (bp->recovery_state != BNX2X_RECOVERY_DONE) { printk(KERN_ERR "Handling parity error recovery. Try again later\n"); @@ -2464,12 +2474,39 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu) */ dev->mtu = new_mtu; - if (netif_running(dev)) { - bnx2x_nic_unload(bp, UNLOAD_NORMAL); - rc = bnx2x_nic_load(bp, LOAD_NORMAL); + return bnx2x_reload_if_running(dev); +} + +u32 bnx2x_fix_features(struct net_device *dev, u32 features) +{ + struct bnx2x *bp = netdev_priv(dev); + + /* TPA requires Rx CSUM offloading */ + if (!(features & NETIF_F_RXCSUM) || bp->disable_tpa) + features &= ~NETIF_F_LRO; + + return features; +} + +int bnx2x_set_features(struct net_device *dev, u32 features) +{ + struct bnx2x *bp = netdev_priv(dev); + u32 flags = bp->flags; + + if (features & NETIF_F_LRO) + flags |= TPA_ENABLE_FLAG; + else + flags &= ~TPA_ENABLE_FLAG; + + if (flags ^ bp->flags) { + bp->flags = flags; + + if (bp->recovery_state == BNX2X_RECOVERY_DONE) + return bnx2x_reload_if_running(dev); + /* else: bnx2x_nic_load() will be called at end of recovery */ } - return rc; + return 0; } void bnx2x_tx_timeout(struct net_device *dev) diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index 775fef031ad8..1cdab69b2a51 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h @@ -431,6 +431,9 @@ void bnx2x_free_mem_bp(struct bnx2x *bp); */ int bnx2x_change_mtu(struct net_device *dev, int new_mtu); +u32 bnx2x_fix_features(struct net_device *dev, u32 features); +int bnx2x_set_features(struct net_device *dev, u32 features); + /** * tx timeout netdev callback * diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index 147999459df5..ad7d91e499f4 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c @@ -1299,91 +1299,6 @@ static int bnx2x_set_pauseparam(struct net_device *dev, return 0; } -static int bnx2x_set_flags(struct net_device *dev, u32 data) -{ - struct bnx2x *bp = netdev_priv(dev); - int changed = 0; - int rc = 0; - - if (bp->recovery_state != BNX2X_RECOVERY_DONE) { - printk(KERN_ERR "Handling parity error recovery. Try again later\n"); - return -EAGAIN; - } - - if (!(data & ETH_FLAG_RXVLAN)) - return -EINVAL; - - if ((data & ETH_FLAG_LRO) && bp->rx_csum && bp->disable_tpa) - return -EINVAL; - - rc = ethtool_op_set_flags(dev, data, ETH_FLAG_LRO | ETH_FLAG_RXVLAN | - ETH_FLAG_TXVLAN | ETH_FLAG_RXHASH); - if (rc) - return rc; - - /* TPA requires Rx CSUM offloading */ - if ((data & ETH_FLAG_LRO) && bp->rx_csum) { - if (!(bp->flags & TPA_ENABLE_FLAG)) { - bp->flags |= TPA_ENABLE_FLAG; - changed = 1; - } - } else if (bp->flags & TPA_ENABLE_FLAG) { - dev->features &= ~NETIF_F_LRO; - bp->flags &= ~TPA_ENABLE_FLAG; - changed = 1; - } - - if (changed && netif_running(dev)) { - bnx2x_nic_unload(bp, UNLOAD_NORMAL); - rc = bnx2x_nic_load(bp, LOAD_NORMAL); - } - - return rc; -} - -static u32 bnx2x_get_rx_csum(struct net_device *dev) -{ - struct bnx2x *bp = netdev_priv(dev); - - return bp->rx_csum; -} - -static int bnx2x_set_rx_csum(struct net_device *dev, u32 data) -{ - struct bnx2x *bp = netdev_priv(dev); - int rc = 0; - - if (bp->recovery_state != BNX2X_RECOVERY_DONE) { - printk(KERN_ERR "Handling parity error recovery. Try again later\n"); - return -EAGAIN; - } - - bp->rx_csum = data; - - /* Disable TPA, when Rx CSUM is disabled. Otherwise all - TPA'ed packets will be discarded due to wrong TCP CSUM */ - if (!data) { - u32 flags = ethtool_op_get_flags(dev); - - rc = bnx2x_set_flags(dev, (flags & ~ETH_FLAG_LRO)); - } - - return rc; -} - -static int bnx2x_set_tso(struct net_device *dev, u32 data) -{ - if (data) { - dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); - dev->features |= NETIF_F_TSO6; - } else { - dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO_ECN); - dev->features &= ~NETIF_F_TSO6; - } - - return 0; -} - static const struct { char string[ETH_GSTRING_LEN]; } bnx2x_tests_str_arr[BNX2X_NUM_TESTS] = { @@ -2207,16 +2122,6 @@ static const struct ethtool_ops bnx2x_ethtool_ops = { .set_ringparam = bnx2x_set_ringparam, .get_pauseparam = bnx2x_get_pauseparam, .set_pauseparam = bnx2x_set_pauseparam, - .get_rx_csum = bnx2x_get_rx_csum, - .set_rx_csum = bnx2x_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_hw_csum, - .set_flags = bnx2x_set_flags, - .get_flags = ethtool_op_get_flags, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = bnx2x_set_tso, .self_test = bnx2x_self_test, .get_sset_count = bnx2x_get_sset_count, .get_strings = bnx2x_get_strings, diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index a6915aafa695..696e84afdc53 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -8904,8 +8904,6 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) bp->multi_mode = multi_mode; bp->int_mode = int_mode; - bp->dev->features |= NETIF_F_GRO; - /* Set TPA flags */ if (disable_tpa) { bp->flags &= ~TPA_ENABLE_FLAG; @@ -8925,8 +8923,6 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) bp->tx_ring_size = MAX_TX_AVAIL; - bp->rx_csum = 1; - /* make sure that the numbers are in the right granularity */ bp->tx_ticks = (50 / BNX2X_BTR) * BNX2X_BTR; bp->rx_ticks = (25 / BNX2X_BTR) * BNX2X_BTR; @@ -9304,6 +9300,8 @@ static const struct net_device_ops bnx2x_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = bnx2x_ioctl, .ndo_change_mtu = bnx2x_change_mtu, + .ndo_fix_features = bnx2x_fix_features, + .ndo_set_features = bnx2x_set_features, .ndo_tx_timeout = bnx2x_tx_timeout, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = poll_bnx2x, @@ -9430,20 +9428,17 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, dev->netdev_ops = &bnx2x_netdev_ops; bnx2x_set_ethtool_ops(dev); - dev->features |= NETIF_F_SG; - dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - if (bp->flags & USING_DAC_FLAG) - dev->features |= NETIF_F_HIGHDMA; - dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); - dev->features |= NETIF_F_TSO6; - dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX); - dev->vlan_features |= NETIF_F_SG; - dev->vlan_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | + NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_HW_VLAN_TX; + + dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA; + + dev->features |= dev->hw_features | NETIF_F_HW_VLAN_RX; if (bp->flags & USING_DAC_FLAG) - dev->vlan_features |= NETIF_F_HIGHDMA; - dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); - dev->vlan_features |= NETIF_F_TSO6; + dev->features |= NETIF_F_HIGHDMA; #ifdef BCM_DCBNL dev->dcbnl_ops = &bnx2x_dcbnl_ops; -- cgit v1.2.3-58-ga151 From 6d95ff974a4b51121777973ffba7547c648da974 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 12 Apr 2011 09:48:17 +0000 Subject: net: ioc3: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/ioc3-eth.c | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index c8ee8d28767b..96c95617195f 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -90,8 +90,6 @@ struct ioc3_private { u32 emcr, ehar_h, ehar_l; spinlock_t ioc3_lock; struct mii_if_info mii; - unsigned long flags; -#define IOC3_FLAG_RX_CHECKSUMS 1 struct pci_dev *pdev; @@ -609,7 +607,7 @@ static inline void ioc3_rx(struct net_device *dev) goto next; } - if (likely(ip->flags & IOC3_FLAG_RX_CHECKSUMS)) + if (likely(dev->features & NETIF_F_RXCSUM)) ioc3_tcpudp_checksum(skb, w0 & ERXBUF_IPCKSUM_MASK, len); @@ -1328,6 +1326,7 @@ static int __devinit ioc3_probe(struct pci_dev *pdev, dev->watchdog_timeo = 5 * HZ; dev->netdev_ops = &ioc3_netdev_ops; dev->ethtool_ops = &ioc3_ethtool_ops; + dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM; dev->features = NETIF_F_IP_CSUM; sw_physid1 = ioc3_mdio_read(dev, ip->mii.phy_id, MII_PHYSID1); @@ -1618,37 +1617,12 @@ static u32 ioc3_get_link(struct net_device *dev) return rc; } -static u32 ioc3_get_rx_csum(struct net_device *dev) -{ - struct ioc3_private *ip = netdev_priv(dev); - - return ip->flags & IOC3_FLAG_RX_CHECKSUMS; -} - -static int ioc3_set_rx_csum(struct net_device *dev, u32 data) -{ - struct ioc3_private *ip = netdev_priv(dev); - - spin_lock_bh(&ip->ioc3_lock); - if (data) - ip->flags |= IOC3_FLAG_RX_CHECKSUMS; - else - ip->flags &= ~IOC3_FLAG_RX_CHECKSUMS; - spin_unlock_bh(&ip->ioc3_lock); - - return 0; -} - static const struct ethtool_ops ioc3_ethtool_ops = { .get_drvinfo = ioc3_get_drvinfo, .get_settings = ioc3_get_settings, .set_settings = ioc3_set_settings, .nway_reset = ioc3_nway_reset, .get_link = ioc3_get_link, - .get_rx_csum = ioc3_get_rx_csum, - .set_rx_csum = ioc3_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum }; static int ioc3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -- cgit v1.2.3-58-ga151 From 1aac62671686e6234c91b5f6fc4caaa850419d5d Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 12 Apr 2011 04:07:39 +0000 Subject: net: vlan_features comment clarification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 09d262415769..cb8178ab3c52 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1035,7 +1035,7 @@ struct net_device { u32 hw_features; /* user-requested features */ u32 wanted_features; - /* VLAN feature mask */ + /* mask of features inheritable by VLAN devices */ u32 vlan_features; /* Net device feature bits; if you change something, -- cgit v1.2.3-58-ga151 From 095d3da610d4022d341c517c59dd5a5d656d966f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 12 Apr 2011 15:58:41 -0700 Subject: 9p: Kill set but unused variable in 9p_client_{read,write}() and p9_client_readdir() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following warnings: net/9p/client.c:1305:18: warning: variable ‘total’ set but not used [-Wunused-but-set-variable] net/9p/client.c:1370:18: warning: variable ‘total’ set but not used [-Wunused-but-set-variable] net/9p/client.c:1769:18: warning: variable ‘total’ set but not used [-Wunused-but-set-variable] Signed-off-by: David S. Miller --- net/9p/client.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/net/9p/client.c b/net/9p/client.c index 48b8e084e710..0ce959218607 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1302,7 +1302,7 @@ int p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, u32 count) { - int err, rsize, total; + int err, rsize; struct p9_client *clnt; struct p9_req_t *req; char *dataptr; @@ -1311,7 +1311,6 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, (long long unsigned) offset, count); err = 0; clnt = fid->clnt; - total = 0; rsize = fid->iounit; if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) @@ -1367,7 +1366,7 @@ int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, u64 offset, u32 count) { - int err, rsize, total; + int err, rsize; struct p9_client *clnt; struct p9_req_t *req; @@ -1375,7 +1374,6 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, fid->fid, (long long unsigned) offset, count); err = 0; clnt = fid->clnt; - total = 0; rsize = fid->iounit; if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) @@ -1766,7 +1764,7 @@ EXPORT_SYMBOL_GPL(p9_client_xattrcreate); int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) { - int err, rsize, total; + int err, rsize; struct p9_client *clnt; struct p9_req_t *req; char *dataptr; @@ -1776,7 +1774,6 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) err = 0; clnt = fid->clnt; - total = 0; rsize = fid->iounit; if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ) -- cgit v1.2.3-58-ga151 From 24743537d3f784a8b3014e934fad0a9c45e4e789 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 12 Apr 2011 16:14:21 -0700 Subject: atm: iphase: Fix set-but-not-used warnings. The "iavcc" and "iadev" cases are obvious. The intr_status and frmr_intr cases are reading a register to clear the chip status. This driver is pretty old and creaky, and uses volatile pointer dereferences to do register I/O when it should be using readl() and friends. However that it outside of the scope of these changes. Signed-off-by: David S. Miller --- drivers/atm/iphase.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 1c674a91f146..dee4f01a64d8 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -613,7 +613,6 @@ static int ia_que_tx (IADEV *iadev) { struct sk_buff *skb; int num_desc; struct atm_vcc *vcc; - struct ia_vcc *iavcc; num_desc = ia_avail_descs(iadev); while (num_desc && (skb = skb_dequeue(&iadev->tx_backlog))) { @@ -627,7 +626,6 @@ static int ia_que_tx (IADEV *iadev) { printk("Free the SKB on closed vci %d \n", vcc->vci); break; } - iavcc = INPH_IA_VCC(vcc); if (ia_pkt_tx (vcc, skb)) { skb_queue_head(&iadev->tx_backlog, skb); } @@ -823,8 +821,6 @@ static void IaFrontEndIntr(IADEV *iadev) { volatile IA_SUNI *suni; volatile ia_mb25_t *mb25; volatile suni_pm7345_t *suni_pm7345; - u32 intr_status; - u_int frmr_intr; if(iadev->phy_type & FE_25MBIT_PHY) { mb25 = (ia_mb25_t*)iadev->phy; @@ -832,18 +828,18 @@ static void IaFrontEndIntr(IADEV *iadev) { } else if (iadev->phy_type & FE_DS3_PHY) { suni_pm7345 = (suni_pm7345_t *)iadev->phy; /* clear FRMR interrupts */ - frmr_intr = suni_pm7345->suni_ds3_frm_intr_stat; + (void) suni_pm7345->suni_ds3_frm_intr_stat; iadev->carrier_detect = Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV)); } else if (iadev->phy_type & FE_E3_PHY ) { suni_pm7345 = (suni_pm7345_t *)iadev->phy; - frmr_intr = suni_pm7345->suni_e3_frm_maint_intr_ind; + (void) suni_pm7345->suni_e3_frm_maint_intr_ind; iadev->carrier_detect = Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat&SUNI_E3_LOS)); } else { suni = (IA_SUNI *)iadev->phy; - intr_status = suni->suni_rsop_status & 0xff; + (void) suni->suni_rsop_status; iadev->carrier_detect = Boolean(!(suni->suni_rsop_status & SUNI_LOSV)); } if (iadev->carrier_detect) @@ -2660,7 +2656,6 @@ static void ia_close(struct atm_vcc *vcc) static int ia_open(struct atm_vcc *vcc) { - IADEV *iadev; struct ia_vcc *ia_vcc; int error; if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) @@ -2668,7 +2663,6 @@ static int ia_open(struct atm_vcc *vcc) IF_EVENT(printk("ia: not partially allocated resources\n");) vcc->dev_data = NULL; } - iadev = INPH_IA_DEV(vcc->dev); if (vcc->vci != ATM_VPI_UNSPEC && vcc->vpi != ATM_VCI_UNSPEC) { IF_EVENT(printk("iphase open: unspec part\n");) @@ -3052,11 +3046,9 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { static int ia_send(struct atm_vcc *vcc, struct sk_buff *skb) { IADEV *iadev; - struct ia_vcc *iavcc; unsigned long flags; iadev = INPH_IA_DEV(vcc->dev); - iavcc = INPH_IA_VCC(vcc); if ((!skb)||(skb->len>(iadev->tx_buf_sz-sizeof(struct cpcs_trailer)))) { if (!skb) -- cgit v1.2.3-58-ga151 From 6139e75f4a413bdc8f366fc11e437347be8abc59 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 12 Apr 2011 19:27:51 -0700 Subject: net: Missing 'inline' in vlan-disabled vlan_untag() Reported-by: Stephen Rothwell Signed-off-by: David S. Miller --- include/linux/if_vlan.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 998b29930b80..546d9d35fbd4 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -174,7 +174,7 @@ static inline bool vlan_do_receive(struct sk_buff **skb) return false; } -inline struct sk_buff *vlan_untag(struct sk_buff *skb) +static inline struct sk_buff *vlan_untag(struct sk_buff *skb) { return skb; } -- cgit v1.2.3-58-ga151 From 91eb7c08c6cb3b8eeba1c61f5753c56dcb77f018 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Wed, 13 Apr 2011 13:51:38 +0200 Subject: netfilter: ipset: SCTP, UDPLITE support added SCTP and UDPLITE port support added to the hash:*port* set types. Signed-off-by: Jozsef Kadlecsik Signed-off-by: Patrick McHardy --- include/linux/netfilter/ipset/ip_set_getport.h | 2 ++ net/netfilter/ipset/ip_set_getport.c | 16 +++++++++++++++- net/netfilter/ipset/ip_set_hash_ipport.c | 2 +- net/netfilter/ipset/ip_set_hash_ipportip.c | 2 +- net/netfilter/ipset/ip_set_hash_ipportnet.c | 2 +- net/netfilter/ipset/ip_set_hash_netport.c | 2 +- 6 files changed, 21 insertions(+), 5 deletions(-) diff --git a/include/linux/netfilter/ipset/ip_set_getport.h b/include/linux/netfilter/ipset/ip_set_getport.h index 5aebd170f899..90d09300e954 100644 --- a/include/linux/netfilter/ipset/ip_set_getport.h +++ b/include/linux/netfilter/ipset/ip_set_getport.h @@ -22,7 +22,9 @@ static inline bool ip_set_proto_with_ports(u8 proto) { switch (proto) { case IPPROTO_TCP: + case IPPROTO_SCTP: case IPPROTO_UDP: + case IPPROTO_UDPLITE: return true; } return false; diff --git a/net/netfilter/ipset/ip_set_getport.c b/net/netfilter/ipset/ip_set_getport.c index 8d5227212686..757143b2240a 100644 --- a/net/netfilter/ipset/ip_set_getport.c +++ b/net/netfilter/ipset/ip_set_getport.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,20 @@ get_port(const struct sk_buff *skb, int protocol, unsigned int protooff, *port = src ? th->source : th->dest; break; } - case IPPROTO_UDP: { + case IPPROTO_SCTP: { + sctp_sctphdr_t _sh; + const sctp_sctphdr_t *sh; + + sh = skb_header_pointer(skb, protooff, sizeof(_sh), &_sh); + if (sh == NULL) + /* No choice either */ + return false; + + *port = src ? sh->source : sh->dest; + break; + } + case IPPROTO_UDP: + case IPPROTO_UDPLITE: { struct udphdr _udph; const struct udphdr *uh; diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c index b9214145d357..14281b6b8074 100644 --- a/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/net/netfilter/ipset/ip_set_hash_ipport.c @@ -491,7 +491,7 @@ static struct ip_set_type hash_ipport_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, .dimension = IPSET_DIM_TWO, .family = AF_UNSPEC, - .revision = 0, + .revision = 1, .create = hash_ipport_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c index 4642872df6e1..401c8a2531db 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/net/netfilter/ipset/ip_set_hash_ipportip.c @@ -509,7 +509,7 @@ static struct ip_set_type hash_ipportip_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, .dimension = IPSET_DIM_THREE, .family = AF_UNSPEC, - .revision = 0, + .revision = 1, .create = hash_ipportip_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index 2cb84a54b7ad..4743e5402522 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c @@ -574,7 +574,7 @@ static struct ip_set_type hash_ipportnet_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, .dimension = IPSET_DIM_THREE, .family = AF_UNSPEC, - .revision = 0, + .revision = 1, .create = hash_ipportnet_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c index 8598676f2a05..d2a40362dd3a 100644 --- a/net/netfilter/ipset/ip_set_hash_netport.c +++ b/net/netfilter/ipset/ip_set_hash_netport.c @@ -526,7 +526,7 @@ static struct ip_set_type hash_netport_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, .dimension = IPSET_DIM_TWO, .family = AF_UNSPEC, - .revision = 0, + .revision = 1, .create = hash_netport_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, -- cgit v1.2.3-58-ga151 From 8962d87129ec0a820d17ac44cbf3f51010ad8db8 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 13 Apr 2011 08:47:32 -0400 Subject: ath5k: improve comments for optimized tx descriptor setup Comment the use of local variables to reduce the number of load/store operations on uncached memory, in hopes of not losing this optimization accidentally in the future. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/desc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 0391813befd1..dd7cd95c364a 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -184,6 +184,11 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, { struct ath5k_hw_4w_tx_ctl *tx_ctl; unsigned int frame_len; + + /* + * Use local variables for these to reduce load/store access on + * uncached memory + */ u32 txctl0 = 0, txctl1 = 0, txctl2 = 0, txctl3 = 0; tx_ctl = &desc->ud.ds_tx5212.tx_ctl; @@ -209,7 +214,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, if (tx_power > AR5K_TUNE_MAX_TXPOWER) tx_power = AR5K_TUNE_MAX_TXPOWER; - /* Clear descriptor */ + /* Clear descriptor status area */ memset(&desc->ud.ds_tx5212.tx_stat, 0, sizeof(desc->ud.ds_tx5212.tx_stat)); -- cgit v1.2.3-58-ga151 From 39d5a3ee355fa903ef4609402c79f570eb9fc4d2 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 4 Apr 2011 15:40:12 -0300 Subject: Bluetooth: Move SREJ list to struct l2cap_chan As part of moving all the Channel related operation to struct l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 13 ++++++------- net/bluetooth/l2cap_core.c | 22 +++++++++++----------- net/bluetooth/l2cap_sock.c | 1 - 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index d05d91f2fd32..ec56d8861a4e 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -277,6 +277,11 @@ struct l2cap_conn_param_update_rsp { #define L2CAP_CONN_PARAM_REJECTED 0x0001 /* ----- L2CAP channels and connections ----- */ +struct srej_list { + __u8 tx_seq; + struct list_head list; +}; + struct l2cap_chan { struct sock *sk; __u8 ident; @@ -312,6 +317,7 @@ struct l2cap_chan { struct sk_buff_head srej_q; struct sk_buff_head busy_q; struct work_struct busy_work; + struct list_head srej_l; struct list_head list; }; @@ -350,12 +356,6 @@ struct l2cap_conn { /* ----- L2CAP socket info ----- */ #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) #define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) -#define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list) - -struct srej_list { - __u8 tx_seq; - struct list_head list; -}; struct l2cap_pinfo { struct bt_sock bt; @@ -385,7 +385,6 @@ struct l2cap_pinfo { __le16 sport; struct sk_buff_head tx_queue; - struct srej_list srej_l; struct l2cap_conn *conn; struct l2cap_chan *chan; }; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 7264119b64a6..9580d6cd55da 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -252,7 +252,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) skb_queue_purge(&chan->srej_q); skb_queue_purge(&chan->busy_q); - list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { + list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { list_del(&l->list); kfree(l); } @@ -1205,7 +1205,7 @@ static void l2cap_send_srejtail(struct l2cap_chan *chan) control = L2CAP_SUPER_SELECT_REJECT; control |= L2CAP_CTRL_FINAL; - tail = list_entry(SREJ_LIST(chan->sk)->prev, struct srej_list, list); + tail = list_entry((&chan->srej_l)->prev, struct srej_list, list); control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; l2cap_send_sframe(chan, control); @@ -1596,6 +1596,8 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan) skb_queue_head_init(&chan->srej_q); skb_queue_head_init(&chan->busy_q); + INIT_LIST_HEAD(&chan->srej_l); + INIT_WORK(&chan->busy_work, l2cap_busy_work); sk->sk_backlog_rcv = l2cap_ertm_data_rcv; @@ -3207,11 +3209,10 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq) static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq) { - struct sock *sk = chan->sk; struct srej_list *l, *tmp; u16 control; - list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { + list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { if (l->tx_seq == tx_seq) { list_del(&l->list); kfree(l); @@ -3221,13 +3222,12 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq) control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; l2cap_send_sframe(chan, control); list_del(&l->list); - list_add_tail(&l->list, SREJ_LIST(sk)); + list_add_tail(&l->list, &chan->srej_l); } } static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) { - struct sock *sk = chan->sk; struct srej_list *new; u16 control; @@ -3239,7 +3239,7 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); new->tx_seq = chan->expected_tx_seq; chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; - list_add_tail(&new->list, SREJ_LIST(sk)); + list_add_tail(&new->list, &chan->srej_l); } chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; } @@ -3288,7 +3288,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { struct srej_list *first; - first = list_first_entry(SREJ_LIST(sk), + first = list_first_entry(&chan->srej_l, struct srej_list, list); if (tx_seq == first->tx_seq) { l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); @@ -3297,7 +3297,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont list_del(&first->list); kfree(first); - if (list_empty(SREJ_LIST(sk))) { + if (list_empty(&chan->srej_l)) { chan->buffer_seq = chan->buffer_seq_srej; chan->conn_state &= ~L2CAP_CONN_SREJ_SENT; l2cap_send_ack(chan); @@ -3310,7 +3310,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0) goto drop; - list_for_each_entry(l, SREJ_LIST(sk), list) { + list_for_each_entry(l, &chan->srej_l, list) { if (l->tx_seq == tx_seq) { l2cap_resend_srejframe(chan, tx_seq); return 0; @@ -3332,7 +3332,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont BT_DBG("sk %p, Enter SREJ", sk); - INIT_LIST_HEAD(SREJ_LIST(sk)); + INIT_LIST_HEAD(&chan->srej_l); chan->buffer_seq_srej = chan->buffer_seq; __skb_queue_head_init(&chan->srej_q); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 55dee999af94..16a223bfa8f5 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1018,7 +1018,6 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) /* Default config options */ pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; skb_queue_head_init(TX_QUEUE(sk)); - INIT_LIST_HEAD(SREJ_LIST(sk)); } static struct proto l2cap_proto = { -- cgit v1.2.3-58-ga151 From 49208c9c7b483098401683fef5cfbd66931ca643 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 4 Apr 2011 15:59:54 -0300 Subject: Bluetooth: Remove some sk references from l2cap_core.c Change some BT_DBG messages and consequently remove some struct sock declarations. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9580d6cd55da..0edfa658090a 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -211,7 +211,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) l2cap_sock_clear_timer(sk); - BT_DBG("sk %p, conn %p, err %d", sk, conn, err); + BT_DBG("chan %p, conn %p, err %d", chan, conn, err); if (conn) { /* Delete from channel list */ @@ -361,7 +361,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) if (pi->fcs == L2CAP_FCS_CRC16) hlen += 2; - BT_DBG("pi %p, control 0x%2.2x", pi, control); + BT_DBG("chan %p, control 0x%2.2x", chan, control); count = min_t(unsigned int, conn->mtu, hlen); control |= L2CAP_CTRL_FRAME_TYPE; @@ -982,7 +982,7 @@ static void l2cap_retrans_timeout(unsigned long arg) struct l2cap_chan *chan = (void *) arg; struct sock *sk = chan->sk; - BT_DBG("sk %p", sk); + BT_DBG("chan %p", chan); bh_lock_sock(sk); chan->retry_count = 1; @@ -1618,13 +1618,12 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) { - struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct l2cap_conf_req *req = data; struct l2cap_conf_rfc rfc = { .mode = pi->mode }; void *ptr = req->data; - BT_DBG("sk %p", sk); + BT_DBG("chan %p", chan); if (chan->num_conf_req || chan->num_conf_rsp) goto done; @@ -2972,7 +2971,6 @@ disconnect: static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) { - struct sock *sk = chan->sk; struct sk_buff *skb; u16 control; int err; @@ -3005,7 +3003,7 @@ done: chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY; chan->conn_state &= ~L2CAP_CONN_RNR_SENT; - BT_DBG("sk %p, Exit local busy", sk); + BT_DBG("chan %p, Exit local busy", chan); return 0; } @@ -3246,8 +3244,7 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb) { - struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_txseq(rx_control); u8 req_seq = __get_reqseq(rx_control); u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; @@ -3301,7 +3298,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont chan->buffer_seq = chan->buffer_seq_srej; chan->conn_state &= ~L2CAP_CONN_SREJ_SENT; l2cap_send_ack(chan); - BT_DBG("sk %p, Exit SREJ_SENT", sk); + BT_DBG("chan %p, Exit SREJ_SENT", chan); } } else { struct srej_list *l; @@ -3330,7 +3327,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont chan->conn_state |= L2CAP_CONN_SREJ_SENT; - BT_DBG("sk %p, Enter SREJ", sk); + BT_DBG("chan %p, Enter SREJ", chan); INIT_LIST_HEAD(&chan->srej_l); chan->buffer_seq_srej = chan->buffer_seq; @@ -3383,9 +3380,7 @@ drop: static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control) { - struct sock *sk = chan->sk; - - BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control), + BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control), rx_control); chan->expected_ack_seq = __get_reqseq(rx_control); @@ -3633,7 +3628,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk sk = chan->sk; pi = l2cap_pi(sk); - BT_DBG("sk %p, len %d", sk, skb->len); + BT_DBG("chan %p, len %d", chan, skb->len); if (sk->sk_state != BT_CONNECTED) goto drop; @@ -3691,7 +3686,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk goto done; default: - BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode); + BT_DBG("chan %p: bad mode 0x%2.2x", chan, pi->mode); break; } -- cgit v1.2.3-58-ga151 From c916fbe45c1f30417fa28e62cbbfae295a3f315c Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 4 Apr 2011 16:00:55 -0300 Subject: Bluetooth: Remove unneeded uninitialized_vars() That was unnecessary use of it. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 0edfa658090a..5fc852a9ae59 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -623,7 +623,7 @@ static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src) static void l2cap_le_conn_ready(struct l2cap_conn *conn) { - struct sock *parent, *uninitialized_var(sk); + struct sock *parent, *sk; struct l2cap_chan *chan; BT_DBG(""); -- cgit v1.2.3-58-ga151 From 58d35f87effa0235181a24d55576aaa756ef7312 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 4 Apr 2011 16:16:44 -0300 Subject: Bluetooth: Move tx queue to struct l2cap_chan tx_q is the queue used by ERTM mode. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 4 ++-- net/bluetooth/l2cap_core.c | 40 +++++++++++++++++++--------------------- net/bluetooth/l2cap_sock.c | 7 +++---- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index ec56d8861a4e..7a215a7f9e39 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -314,6 +314,8 @@ struct l2cap_chan { struct timer_list retrans_timer; struct timer_list monitor_timer; struct timer_list ack_timer; + struct sk_buff *tx_send_head; + struct sk_buff_head tx_q; struct sk_buff_head srej_q; struct sk_buff_head busy_q; struct work_struct busy_work; @@ -355,7 +357,6 @@ struct l2cap_conn { /* ----- L2CAP socket info ----- */ #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) -#define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) struct l2cap_pinfo { struct bt_sock bt; @@ -384,7 +385,6 @@ struct l2cap_pinfo { __le16 sport; - struct sk_buff_head tx_queue; struct l2cap_conn *conn; struct l2cap_chan *chan; }; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 5fc852a9ae59..97827506dc94 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -240,7 +240,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE)) goto free; - skb_queue_purge(TX_QUEUE(sk)); + skb_queue_purge(&chan->tx_q); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { struct srej_list *l, *tmp; @@ -477,7 +477,7 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in sk = chan->sk; - skb_queue_purge(TX_QUEUE(sk)); + skb_queue_purge(&chan->tx_q); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { del_timer(&chan->retrans_timer); @@ -996,15 +996,14 @@ static void l2cap_retrans_timeout(unsigned long arg) static void l2cap_drop_acked_frames(struct l2cap_chan *chan) { - struct sock *sk = chan->sk; struct sk_buff *skb; - while ((skb = skb_peek(TX_QUEUE(sk))) && + while ((skb = skb_peek(&chan->tx_q)) && chan->unacked_frames) { if (bt_cb(skb)->tx_seq == chan->expected_ack_seq) break; - skb = skb_dequeue(TX_QUEUE(sk)); + skb = skb_dequeue(&chan->tx_q); kfree_skb(skb); chan->unacked_frames--; @@ -1037,7 +1036,7 @@ void l2cap_streaming_send(struct l2cap_chan *chan) struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; - while ((skb = skb_dequeue(TX_QUEUE(sk)))) { + while ((skb = skb_dequeue(&chan->tx_q))) { control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE); control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE); @@ -1060,7 +1059,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) struct sk_buff *skb, *tx_skb; u16 control, fcs; - skb = skb_peek(TX_QUEUE(sk)); + skb = skb_peek(&chan->tx_q); if (!skb) return; @@ -1068,10 +1067,10 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) if (bt_cb(skb)->tx_seq == tx_seq) break; - if (skb_queue_is_last(TX_QUEUE(sk), skb)) + if (skb_queue_is_last(&chan->tx_q, skb)) return; - } while ((skb = skb_queue_next(TX_QUEUE(sk), skb))); + } while ((skb = skb_queue_next(&chan->tx_q, skb))); if (chan->remote_max_tx && bt_cb(skb)->retries == chan->remote_max_tx) { @@ -1112,7 +1111,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan) if (sk->sk_state != BT_CONNECTED) return -ENOTCONN; - while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(chan))) { + while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) { if (chan->remote_max_tx && bt_cb(skb)->retries == chan->remote_max_tx) { @@ -1153,10 +1152,10 @@ int l2cap_ertm_send(struct l2cap_chan *chan) chan->frames_sent++; - if (skb_queue_is_last(TX_QUEUE(sk), skb)) - sk->sk_send_head = NULL; + if (skb_queue_is_last(&chan->tx_q, skb)) + chan->tx_send_head = NULL; else - sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb); + chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); nsent++; } @@ -1166,11 +1165,10 @@ int l2cap_ertm_send(struct l2cap_chan *chan) static int l2cap_retransmit_frames(struct l2cap_chan *chan) { - struct sock *sk = chan->sk; int ret; - if (!skb_queue_empty(TX_QUEUE(sk))) - sk->sk_send_head = TX_QUEUE(sk)->next; + if (!skb_queue_empty(&chan->tx_q)) + chan->tx_send_head = chan->tx_q.next; chan->next_tx_seq = chan->expected_ack_seq; ret = l2cap_ertm_send(chan); @@ -1384,9 +1382,9 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le len -= buflen; size += buflen; } - skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk)); - if (sk->sk_send_head == NULL) - sk->sk_send_head = sar_queue.next; + skb_queue_splice_tail(&sar_queue, &chan->tx_q); + if (chan->tx_send_head == NULL) + chan->tx_send_head = sar_queue.next; return size; } @@ -2319,7 +2317,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr chan->next_tx_seq = 0; chan->expected_tx_seq = 0; - __skb_queue_head_init(TX_QUEUE(sk)); + skb_queue_head_init(&chan->tx_q); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) l2cap_ertm_init(chan); @@ -2410,7 +2408,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr sk->sk_state = BT_CONNECTED; chan->next_tx_seq = 0; chan->expected_tx_seq = 0; - __skb_queue_head_init(TX_QUEUE(sk)); + skb_queue_head_init(&chan->tx_q); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) l2cap_ertm_init(chan); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 16a223bfa8f5..b2bfa1e0d74e 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -764,10 +764,10 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms err = PTR_ERR(skb); goto done; } - __skb_queue_tail(TX_QUEUE(sk), skb); + __skb_queue_tail(&pi->chan->tx_q, skb); - if (sk->sk_send_head == NULL) - sk->sk_send_head = skb; + if (pi->chan->tx_send_head == NULL) + pi->chan->tx_send_head = skb; } else { /* Segment SDU into multiples PDUs */ @@ -1017,7 +1017,6 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) /* Default config options */ pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; - skb_queue_head_init(TX_QUEUE(sk)); } static struct proto l2cap_proto = { -- cgit v1.2.3-58-ga151 From cd69a03af1106c486033df600c7945957ea5abeb Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 5 Apr 2011 15:24:40 -0300 Subject: Bluetooth: Fix wrong comparison in listen() We should check for the pi->scid there. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index b2bfa1e0d74e..473e5973d8fe 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -269,7 +269,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) goto done; } - if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->dcid) { + if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->scid) { bdaddr_t *src = &bt_sk(sk)->src; u16 psm; -- cgit v1.2.3-58-ga151 From 0733119c0bed37eda4bb832d049939a0dc53a233 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 5 Apr 2011 22:29:31 -0300 Subject: Bluetooth: Clean up ath3k_load_firmware() Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/ath3k.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 5577ed656e2f..695d4414bd4c 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -138,9 +138,6 @@ static int ath3k_load_firmware(struct usb_device *udev, count -= size; } - kfree(send_buf); - return 0; - error: kfree(send_buf); return err; -- cgit v1.2.3-58-ga151 From 9f69bda6aa8b365169b4a6fd35432ee40574d661 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Thu, 7 Apr 2011 16:40:25 -0300 Subject: Bluetooth: Add proper handling of received LE data Despite it works, handling through l2cap_data_channel() is wrongs. That function should handle only connection oriented data. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 97827506dc94..c9c1f9257a91 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -3728,6 +3728,36 @@ done: return 0; } +static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb) +{ + struct sock *sk; + + sk = l2cap_get_sock_by_scid(0, cid, conn->src); + if (!sk) + goto drop; + + bh_lock_sock(sk); + + BT_DBG("sk %p, len %d", sk, skb->len); + + if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) + goto drop; + + if (l2cap_pi(sk)->imtu < skb->len) + goto drop; + + if (!sock_queue_rcv_skb(sk, skb)) + goto done; + +drop: + kfree_skb(skb); + +done: + if (sk) + bh_unlock_sock(sk); + return 0; +} + static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) { struct l2cap_hdr *lh = (void *) skb->data; @@ -3757,6 +3787,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) l2cap_conless_channel(conn, psm, skb); break; + case L2CAP_CID_LE_DATA: + l2cap_att_channel(conn, cid, skb); + break; + default: l2cap_data_channel(conn, cid, skb); break; -- cgit v1.2.3-58-ga151 From e1ba1f15469903b6f443fbf00f069d169e3fba6d Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 6 Apr 2011 13:01:59 +0200 Subject: Bluetooth: Fix Out Of Band pairing when mgmt interface is disabled Use kernel stored remote Out Of Band data only if management interface is enabled. Otherwise HCI_OP_REMOTE_OOB_DATA_NEG_REPLY was sent to controller even if remote Out Of Band data was present in bluetoothd. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 7a3398d9cd65..c7eb073fe633 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2497,6 +2497,9 @@ static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, hci_dev_lock(hdev); + if (!test_bit(HCI_MGMT, &hdev->flags)) + goto unlock; + data = hci_find_remote_oob_data(hdev, &ev->bdaddr); if (data) { struct hci_cp_remote_oob_data_reply cp; @@ -2515,6 +2518,7 @@ static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, &cp); } +unlock: hci_dev_unlock(hdev); } -- cgit v1.2.3-58-ga151 From 78b4a56c28c096a1eb02f1d864eb450eb910e43d Mon Sep 17 00:00:00 2001 From: Jiejing Zhang Date: Thu, 7 Apr 2011 20:37:06 +0800 Subject: Bluetooth: hci_uart: check the return value of recv() Check the return value of hu->proto->recv() in hci_uart_tty_receive() the recv() may return error, check it, not add this to statistics. Signed-off-by: Jiejing Zhang Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/hci_ath.c | 7 ++++++- drivers/bluetooth/hci_ldisc.c | 6 ++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c index bd34406faaae..4093935ddf42 100644 --- a/drivers/bluetooth/hci_ath.c +++ b/drivers/bluetooth/hci_ath.c @@ -201,8 +201,13 @@ static struct sk_buff *ath_dequeue(struct hci_uart *hu) /* Recv data */ static int ath_recv(struct hci_uart *hu, void *data, int count) { - if (hci_recv_stream_fragment(hu->hdev, data, count) < 0) + int ret; + + ret = hci_recv_stream_fragment(hu->hdev, data, count); + if (ret < 0) { BT_ERR("Frame Reassembly Failed"); + return ret; + } return count; } diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 48ad2a7ab080..320f71803a2b 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -359,6 +359,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty) */ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count) { + int ret; struct hci_uart *hu = (void *)tty->disc_data; if (!hu || tty != hu->tty) @@ -368,8 +369,9 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f return; spin_lock(&hu->rx_lock); - hu->proto->recv(hu, (void *) data, count); - hu->hdev->stat.byte_rx += count; + ret = hu->proto->recv(hu, (void *) data, count); + if (ret > 0) + hu->hdev->stat.byte_rx += count; spin_unlock(&hu->rx_lock); tty_unthrottle(tty); -- cgit v1.2.3-58-ga151 From b86ed368f1f0b19de1918c57e4b056e73d5613a0 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Thu, 7 Apr 2011 18:53:45 -0300 Subject: Bluetooth: Check return value of hci_recv_stream_fragment() It may return error and in this case we do add to the stats. Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/hci_h4.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index 7b8ad93e2c36..2fcd8b387d69 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c @@ -151,8 +151,13 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len) /* Recv data */ static int h4_recv(struct hci_uart *hu, void *data, int count) { - if (hci_recv_stream_fragment(hu->hdev, data, count) < 0) + int ret; + + ret = hci_recv_stream_fragment(hu->hdev, data, count); + if (ret < 0) { BT_ERR("Frame Reassembly Failed"); + return ret; + } return count; } -- cgit v1.2.3-58-ga151 From 9f72c1d977e47a7d182d49ea131067cba0a96ab8 Mon Sep 17 00:00:00 2001 From: Kevin Gan Date: Fri, 8 Apr 2011 18:19:33 -0700 Subject: Bluetooth: btmrvl: support Marvell Bluetooth device SD8787 The SD8787 firmware image is shared with mwifiex driver. Whoever gets loaded first will be responsible for firmware downloading. Signed-off-by: Kevin Gan Signed-off-by: Tristan Xu Signed-off-by: Bing Zhao Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/Kconfig | 4 +- drivers/bluetooth/btmrvl_sdio.c | 124 ++++++++++++++++++++++++++++++---------- drivers/bluetooth/btmrvl_sdio.h | 68 +++++++++++----------- 3 files changed, 132 insertions(+), 64 deletions(-) diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 8e0de9a05867..11b41fd40c27 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -188,7 +188,7 @@ config BT_MRVL The core driver to support Marvell Bluetooth devices. This driver is required if you want to support - Marvell Bluetooth devices, such as 8688. + Marvell Bluetooth devices, such as 8688/8787. Say Y here to compile Marvell Bluetooth driver into the kernel or say M to compile it as module. @@ -201,7 +201,7 @@ config BT_MRVL_SDIO The driver for Marvell Bluetooth chipsets with SDIO interface. This driver is required if you want to use Marvell Bluetooth - devices with SDIO interface. Currently only SD8688 chipset is + devices with SDIO interface. Currently SD8688/SD8787 chipsets are supported. Say Y here to compile support for Marvell BT-over-SDIO driver diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index dcc2a6ec23f0..7f521d4ac657 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -49,15 +49,59 @@ static u8 user_rmmod; static u8 sdio_ireg; +static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = { + .cfg = 0x03, + .host_int_mask = 0x04, + .host_intstatus = 0x05, + .card_status = 0x20, + .sq_read_base_addr_a0 = 0x10, + .sq_read_base_addr_a1 = 0x11, + .card_fw_status0 = 0x40, + .card_fw_status1 = 0x41, + .card_rx_len = 0x42, + .card_rx_unit = 0x43, + .io_port_0 = 0x00, + .io_port_1 = 0x01, + .io_port_2 = 0x02, +}; +static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = { + .cfg = 0x00, + .host_int_mask = 0x02, + .host_intstatus = 0x03, + .card_status = 0x30, + .sq_read_base_addr_a0 = 0x40, + .sq_read_base_addr_a1 = 0x41, + .card_revision = 0x5c, + .card_fw_status0 = 0x60, + .card_fw_status1 = 0x61, + .card_rx_len = 0x62, + .card_rx_unit = 0x63, + .io_port_0 = 0x78, + .io_port_1 = 0x79, + .io_port_2 = 0x7a, +}; + static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = { .helper = "sd8688_helper.bin", .firmware = "sd8688.bin", + .reg = &btmrvl_reg_8688, + .sd_blksz_fw_dl = 64, +}; + +static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { + .helper = NULL, + .firmware = "mrvl/sd8787_uapsta.bin", + .reg = &btmrvl_reg_8787, + .sd_blksz_fw_dl = 256, }; static const struct sdio_device_id btmrvl_sdio_ids[] = { /* Marvell SD8688 Bluetooth device */ { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105), .driver_data = (unsigned long) &btmrvl_sdio_sd6888 }, + /* Marvell SD8787 Bluetooth device */ + { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), + .driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, { } /* Terminating entry */ }; @@ -69,7 +113,7 @@ static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card) u8 reg; int ret; - reg = sdio_readb(card->func, CARD_RX_UNIT_REG, &ret); + reg = sdio_readb(card->func, card->reg->card_rx_unit, &ret); if (!ret) card->rx_unit = reg; @@ -83,11 +127,11 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat) *dat = 0; - fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret); + fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret); if (ret) return -EIO; - fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret); + fws1 = sdio_readb(card->func, card->reg->card_fw_status1, &ret); if (ret) return -EIO; @@ -101,7 +145,7 @@ static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat) u8 reg; int ret; - reg = sdio_readb(card->func, CARD_RX_LEN_REG, &ret); + reg = sdio_readb(card->func, card->reg->card_rx_len, &ret); if (!ret) *dat = (u16) reg << card->rx_unit; @@ -113,7 +157,7 @@ static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card, { int ret; - sdio_writeb(card->func, mask, HOST_INT_MASK_REG, &ret); + sdio_writeb(card->func, mask, card->reg->host_int_mask, &ret); if (ret) { BT_ERR("Unable to enable the host interrupt!"); ret = -EIO; @@ -128,13 +172,13 @@ static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card, u8 host_int_mask; int ret; - host_int_mask = sdio_readb(card->func, HOST_INT_MASK_REG, &ret); + host_int_mask = sdio_readb(card->func, card->reg->host_int_mask, &ret); if (ret) return -EIO; host_int_mask &= ~mask; - sdio_writeb(card->func, host_int_mask, HOST_INT_MASK_REG, &ret); + sdio_writeb(card->func, host_int_mask, card->reg->host_int_mask, &ret); if (ret < 0) { BT_ERR("Unable to disable the host interrupt!"); return -EIO; @@ -150,7 +194,7 @@ static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits) int ret; for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) { - status = sdio_readb(card->func, CARD_STATUS_REG, &ret); + status = sdio_readb(card->func, card->reg->card_status, &ret); if (ret) goto failed; if ((status & bits) == bits) @@ -299,7 +343,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card) u8 base0, base1; void *tmpfwbuf = NULL; u8 *fwbuf; - u16 len; + u16 len, blksz_dl = card->sd_blksz_fw_dl; int txlen = 0, tx_blocks = 0, count = 0; ret = request_firmware(&fw_firmware, card->firmware, @@ -345,7 +389,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card) for (tries = 0; tries < MAX_POLL_TRIES; tries++) { base0 = sdio_readb(card->func, - SQ_READ_BASE_ADDRESS_A0_REG, &ret); + card->reg->sq_read_base_addr_a0, &ret); if (ret) { BT_ERR("BASE0 register read failed:" " base0 = 0x%04X(%d)." @@ -355,7 +399,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card) goto done; } base1 = sdio_readb(card->func, - SQ_READ_BASE_ADDRESS_A1_REG, &ret); + card->reg->sq_read_base_addr_a1, &ret); if (ret) { BT_ERR("BASE1 register read failed:" " base1 = 0x%04X(%d)." @@ -403,20 +447,19 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card) if (firmwarelen - offset < txlen) txlen = firmwarelen - offset; - tx_blocks = - (txlen + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE; + tx_blocks = (txlen + blksz_dl - 1) / blksz_dl; memcpy(fwbuf, &firmware[offset], txlen); } ret = sdio_writesb(card->func, card->ioport, fwbuf, - tx_blocks * SDIO_BLOCK_SIZE); + tx_blocks * blksz_dl); if (ret < 0) { BT_ERR("FW download, writesb(%d) failed @%d", count, offset); - sdio_writeb(card->func, HOST_CMD53_FIN, CONFIG_REG, - &ret); + sdio_writeb(card->func, HOST_CMD53_FIN, + card->reg->cfg, &ret); if (ret) BT_ERR("writeb failed (CFG)"); } @@ -597,7 +640,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func) priv = card->priv; - ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret); + ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret); if (ret) { BT_ERR("sdio_readb: read int status register failed"); return; @@ -613,7 +656,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func) sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS), - HOST_INTSTATUS_REG, &ret); + card->reg->host_intstatus, &ret); if (ret) { BT_ERR("sdio_writeb: clear int status register failed"); return; @@ -664,7 +707,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card) goto release_irq; } - reg = sdio_readb(func, IO_PORT_0_REG, &ret); + reg = sdio_readb(func, card->reg->io_port_0, &ret); if (ret < 0) { ret = -EIO; goto release_irq; @@ -672,7 +715,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card) card->ioport = reg; - reg = sdio_readb(func, IO_PORT_1_REG, &ret); + reg = sdio_readb(func, card->reg->io_port_1, &ret); if (ret < 0) { ret = -EIO; goto release_irq; @@ -680,7 +723,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card) card->ioport |= (reg << 8); - reg = sdio_readb(func, IO_PORT_2_REG, &ret); + reg = sdio_readb(func, card->reg->io_port_2, &ret); if (ret < 0) { ret = -EIO; goto release_irq; @@ -815,6 +858,8 @@ exit: static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card) { int ret = 0; + u8 fws0; + int pollnum = MAX_POLL_TRIES; if (!card || !card->func) { BT_ERR("card or function is NULL!"); @@ -827,20 +872,36 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card) goto done; } - ret = btmrvl_sdio_download_helper(card); + /* Check if other function driver is downloading the firmware */ + fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret); if (ret) { - BT_ERR("Failed to download helper!"); + BT_ERR("Failed to read FW downloading status!"); ret = -EIO; goto done; } + if (fws0) { + BT_DBG("BT not the winner (%#x). Skip FW downloading", fws0); + + /* Give other function more time to download the firmware */ + pollnum *= 10; + } else { + if (card->helper) { + ret = btmrvl_sdio_download_helper(card); + if (ret) { + BT_ERR("Failed to download helper!"); + ret = -EIO; + goto done; + } + } - if (btmrvl_sdio_download_fw_w_helper(card)) { - BT_ERR("Failed to download firmware!"); - ret = -EIO; - goto done; + if (btmrvl_sdio_download_fw_w_helper(card)) { + BT_ERR("Failed to download firmware!"); + ret = -EIO; + goto done; + } } - if (btmrvl_sdio_verify_fw_download(card, MAX_POLL_TRIES)) { + if (btmrvl_sdio_verify_fw_download(card, pollnum)) { BT_ERR("FW failed to be active in time!"); ret = -ETIMEDOUT; goto done; @@ -864,7 +925,7 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv) sdio_claim_host(card->func); - sdio_writeb(card->func, HOST_POWER_UP, CONFIG_REG, &ret); + sdio_writeb(card->func, HOST_POWER_UP, card->reg->cfg, &ret); sdio_release_host(card->func); @@ -893,8 +954,10 @@ static int btmrvl_sdio_probe(struct sdio_func *func, if (id->driver_data) { struct btmrvl_sdio_device *data = (void *) id->driver_data; - card->helper = data->helper; + card->helper = data->helper; card->firmware = data->firmware; + card->reg = data->reg; + card->sd_blksz_fw_dl = data->sd_blksz_fw_dl; } if (btmrvl_sdio_register_dev(card) < 0) { @@ -1011,3 +1074,4 @@ MODULE_VERSION(VERSION); MODULE_LICENSE("GPL v2"); MODULE_FIRMWARE("sd8688_helper.bin"); MODULE_FIRMWARE("sd8688.bin"); +MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h index 27329f107e5a..43d35a609ca9 100644 --- a/drivers/bluetooth/btmrvl_sdio.h +++ b/drivers/bluetooth/btmrvl_sdio.h @@ -47,44 +47,46 @@ /* Max retry number of CMD53 write */ #define MAX_WRITE_IOMEM_RETRY 2 -/* Host Control Registers */ -#define IO_PORT_0_REG 0x00 -#define IO_PORT_1_REG 0x01 -#define IO_PORT_2_REG 0x02 - -#define CONFIG_REG 0x03 -#define HOST_POWER_UP BIT(1) -#define HOST_CMD53_FIN BIT(2) - -#define HOST_INT_MASK_REG 0x04 -#define HIM_DISABLE 0xff -#define HIM_ENABLE (BIT(0) | BIT(1)) - -#define HOST_INTSTATUS_REG 0x05 -#define UP_LD_HOST_INT_STATUS BIT(0) -#define DN_LD_HOST_INT_STATUS BIT(1) - -/* Card Control Registers */ -#define SQ_READ_BASE_ADDRESS_A0_REG 0x10 -#define SQ_READ_BASE_ADDRESS_A1_REG 0x11 - -#define CARD_STATUS_REG 0x20 -#define DN_LD_CARD_RDY BIT(0) -#define CARD_IO_READY BIT(3) - -#define CARD_FW_STATUS0_REG 0x40 -#define CARD_FW_STATUS1_REG 0x41 -#define FIRMWARE_READY 0xfedc - -#define CARD_RX_LEN_REG 0x42 -#define CARD_RX_UNIT_REG 0x43 - +/* register bitmasks */ +#define HOST_POWER_UP BIT(1) +#define HOST_CMD53_FIN BIT(2) + +#define HIM_DISABLE 0xff +#define HIM_ENABLE (BIT(0) | BIT(1)) + +#define UP_LD_HOST_INT_STATUS BIT(0) +#define DN_LD_HOST_INT_STATUS BIT(1) + +#define DN_LD_CARD_RDY BIT(0) +#define CARD_IO_READY BIT(3) + +#define FIRMWARE_READY 0xfedc + + +struct btmrvl_sdio_card_reg { + u8 cfg; + u8 host_int_mask; + u8 host_intstatus; + u8 card_status; + u8 sq_read_base_addr_a0; + u8 sq_read_base_addr_a1; + u8 card_revision; + u8 card_fw_status0; + u8 card_fw_status1; + u8 card_rx_len; + u8 card_rx_unit; + u8 io_port_0; + u8 io_port_1; + u8 io_port_2; +}; struct btmrvl_sdio_card { struct sdio_func *func; u32 ioport; const char *helper; const char *firmware; + const struct btmrvl_sdio_card_reg *reg; + u16 sd_blksz_fw_dl; u8 rx_unit; struct btmrvl_private *priv; }; @@ -92,6 +94,8 @@ struct btmrvl_sdio_card { struct btmrvl_sdio_device { const char *helper; const char *firmware; + const struct btmrvl_sdio_card_reg *reg; + u16 sd_blksz_fw_dl; }; -- cgit v1.2.3-58-ga151 From 8b5933c380fc66a6311739f9b36a812383f82141 Mon Sep 17 00:00:00 2001 From: amit salecha Date: Thu, 7 Apr 2011 01:58:42 +0000 Subject: net: ethtool support to configure number of channels Ethtool support to configure RX, TX and other channels. combined field in struct ethtool_channels to reflect set of channel (RX, TX or other). Other channel can be link interrupts, SR-IOV coordination etc. ETHTOOL_GCHANNELS will report max and current number of RX channels, max and current number of TX channels, max and current number of other channel or max and current number of combined channel. Number of channel can be modify upto max number of channel through ETHTOOL_SCHANNELS command. Ben Hutchings: o define 'combined' and 'other' types. Most multiqueue drivers pair up RX and TX queues so that most channels combine RX and TX work. o Please could you use a kernel-doc comment to describe the structure. Signed-off-by: Amit Kumar Salecha Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- include/linux/ethtool.h | 36 ++++++++++++++++++++++++++++++++++++ net/core/ethtool.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 12cfbd0be2ee..ad22a68c2e5d 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -229,6 +229,34 @@ struct ethtool_ringparam { __u32 tx_pending; }; +/** + * struct ethtool_channels - configuring number of network channel + * @cmd: ETHTOOL_{G,S}CHANNELS + * @max_rx: Read only. Maximum number of receive channel the driver support. + * @max_tx: Read only. Maximum number of transmit channel the driver support. + * @max_other: Read only. Maximum number of other channel the driver support. + * @max_combined: Read only. Maximum number of combined channel the driver + * support. Set of queues RX, TX or other. + * @rx_count: Valid values are in the range 1 to the max_rx. + * @tx_count: Valid values are in the range 1 to the max_tx. + * @other_count: Valid values are in the range 1 to the max_other. + * @combined_count: Valid values are in the range 1 to the max_combined. + * + * This can be used to configure RX, TX and other channels. + */ + +struct ethtool_channels { + __u32 cmd; + __u32 max_rx; + __u32 max_tx; + __u32 max_other; + __u32 max_combined; + __u32 rx_count; + __u32 tx_count; + __u32 other_count; + __u32 combined_count; +}; + /* for configuring link flow control parameters */ struct ethtool_pauseparam { __u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ @@ -818,6 +846,9 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * Returns a negative error code or zero. * @set_rxfh_indir: Set the contents of the RX flow hash indirection table. * Returns a negative error code or zero. + * @get_channels: Get number of channels. + * @set_channels: Set number of channels. Returns a negative error code or + * zero. * * All operations are optional (i.e. the function pointer may be set * to %NULL) and callers must take this into account. Callers must @@ -891,6 +922,9 @@ struct ethtool_ops { struct ethtool_rxfh_indir *); int (*set_rxfh_indir)(struct net_device *, const struct ethtool_rxfh_indir *); + void (*get_channels)(struct net_device *, struct ethtool_channels *); + int (*set_channels)(struct net_device *, struct ethtool_channels *); + }; #endif /* __KERNEL__ */ @@ -959,6 +993,8 @@ struct ethtool_ops { #define ETHTOOL_GFEATURES 0x0000003a /* Get device offload settings */ #define ETHTOOL_SFEATURES 0x0000003b /* Change device offload settings */ +#define ETHTOOL_GCHANNELS 0x0000003c /* Get no of channels */ +#define ETHTOOL_SCHANNELS 0x0000003d /* Set no of channels */ /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 43ef09fedd6e..41dee2de13ad 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1446,6 +1446,35 @@ static int ethtool_set_ringparam(struct net_device *dev, void __user *useraddr) return dev->ethtool_ops->set_ringparam(dev, &ringparam); } +static noinline_for_stack int ethtool_get_channels(struct net_device *dev, + void __user *useraddr) +{ + struct ethtool_channels channels = { .cmd = ETHTOOL_GCHANNELS }; + + if (!dev->ethtool_ops->get_channels) + return -EOPNOTSUPP; + + dev->ethtool_ops->get_channels(dev, &channels); + + if (copy_to_user(useraddr, &channels, sizeof(channels))) + return -EFAULT; + return 0; +} + +static noinline_for_stack int ethtool_set_channels(struct net_device *dev, + void __user *useraddr) +{ + struct ethtool_channels channels; + + if (!dev->ethtool_ops->set_channels) + return -EOPNOTSUPP; + + if (copy_from_user(&channels, useraddr, sizeof(channels))) + return -EFAULT; + + return dev->ethtool_ops->set_channels(dev, &channels); +} + static int ethtool_get_pauseparam(struct net_device *dev, void __user *useraddr) { struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; @@ -2007,6 +2036,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) case ETHTOOL_SGRO: rc = ethtool_set_one_feature(dev, useraddr, ethcmd); break; + case ETHTOOL_GCHANNELS: + rc = ethtool_get_channels(dev, useraddr); + break; + case ETHTOOL_SCHANNELS: + rc = ethtool_set_channels(dev, useraddr); + break; default: rc = -EOPNOTSUPP; } -- cgit v1.2.3-58-ga151 From b19f7f71b6fa5e0c49f65082044b8a2ff1009f00 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 13 Apr 2011 05:03:24 +0000 Subject: macb: Add rx overrun counter Signed-off-by: Alexander Stein Signed-off-by: David S. Miller --- drivers/net/macb.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 2cb4e792f871..629bd2649c0c 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -576,6 +576,11 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) * add that if/when we get our hands on a full-blown MII PHY. */ + if (status & MACB_BIT(ISR_ROVR)) { + /* We missed at least one packet */ + bp->hw_stats.rx_overruns++; + } + if (status & MACB_BIT(HRESP)) { /* * TODO: Reset the hardware, and maybe move the printk @@ -1024,7 +1029,8 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev) hwstat->rx_jabbers + hwstat->rx_undersize_pkts + hwstat->rx_length_mismatch); - nstat->rx_over_errors = hwstat->rx_resource_errors; + nstat->rx_over_errors = hwstat->rx_resource_errors + + hwstat->rx_overruns; nstat->rx_crc_errors = hwstat->rx_fcs_errors; nstat->rx_frame_errors = hwstat->rx_align_errors; nstat->rx_fifo_errors = hwstat->rx_overruns; -- cgit v1.2.3-58-ga151 From 74ae2fd7d326750d973920c30d5269596724ca71 Mon Sep 17 00:00:00 2001 From: Giuseppe Cavallaro Date: Wed, 13 Apr 2011 11:51:43 -0700 Subject: stmmac: review Wol and enable the Unicast support Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/dwmac1000_core.c | 5 +++-- drivers/net/stmmac/stmmac_ethtool.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c index 6ae4c3f4c63c..f20455cbfbbc 100644 --- a/drivers/net/stmmac/dwmac1000_core.c +++ b/drivers/net/stmmac/dwmac1000_core.c @@ -178,10 +178,11 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode) { unsigned int pmt = 0; - if (mode == WAKE_MAGIC) { + if (mode & WAKE_MAGIC) { CHIP_DBG(KERN_DEBUG "GMAC: WOL Magic frame\n"); pmt |= power_down | magic_pkt_en; - } else if (mode == WAKE_UCAST) { + } + if (mode & WAKE_UCAST) { CHIP_DBG(KERN_DEBUG "GMAC: WOL on global unicast\n"); pmt |= global_unicast; } diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c index 156a805c6c23..0e61ac8707cb 100644 --- a/drivers/net/stmmac/stmmac_ethtool.c +++ b/drivers/net/stmmac/stmmac_ethtool.c @@ -308,7 +308,7 @@ static void stmmac_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) spin_lock_irq(&priv->lock); if (device_can_wakeup(priv->device)) { - wol->supported = WAKE_MAGIC; + wol->supported = WAKE_MAGIC | WAKE_UCAST; wol->wolopts = priv->wolopts; } spin_unlock_irq(&priv->lock); @@ -317,7 +317,7 @@ static void stmmac_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct stmmac_priv *priv = netdev_priv(dev); - u32 support = WAKE_MAGIC; + u32 support = WAKE_MAGIC | WAKE_UCAST; if (!device_can_wakeup(priv->device)) return -EINVAL; -- cgit v1.2.3-58-ga151 From 12488e01fb2b06bb3f6ee137efc88e29d827817e Mon Sep 17 00:00:00 2001 From: Nishant Sarmukadam Date: Fri, 8 Apr 2011 14:38:27 +0530 Subject: mwl8k: interrupt handling changes We do not need to enable all the interrupts in mwl8k_probe_hw. We need to enable only MWL8K_A2H_INT_OPC_DONE interrupt for sending commands to the firmware. Keep the other interrupts masked in mwl8k_probe_hw. Also, in mwl8k_start, where we expect other interrupts, enable only those interrupts we are interested in. Signed-off-by: Nishant Sarmukadam Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index fb472f4924d0..d2416709ba52 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -4284,6 +4284,8 @@ static int mwl8k_start(struct ieee80211_hw *hw) /* Enable interrupts */ iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); + iowrite32(MWL8K_A2H_EVENTS, + priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); rc = mwl8k_fw_lock(hw); if (!rc) { @@ -5282,7 +5284,8 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) iowrite32(MWL8K_A2H_INT_TX_DONE|MWL8K_A2H_INT_RX_READY| MWL8K_A2H_INT_BA_WATCHDOG, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); - iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); + iowrite32(MWL8K_A2H_INT_OPC_DONE, + priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); rc = request_irq(priv->pdev->irq, mwl8k_interrupt, IRQF_SHARED, MWL8K_NAME, hw); -- cgit v1.2.3-58-ga151 From 8e26a0303614e766f993b1ac4a5bfbf80436d9dd Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 12 Apr 2011 18:23:16 +0200 Subject: ath9k: introduce ATH9K_{PCI,AHB} config options Currently ath9k only available in menuconfig if PCI bus support is enabled. However the driver is required for the built-in wireless MACs of the Atheros AR9130/AR9132 SoCs. These SoCs have no PCI controller, the wireless MAC is connected to the AHB bus on them. Introduce separated config options for the supported buses, in order to allow building of ath9h without PCI bus support. As a bonus, this patch removes the cross-reference of the ATHEROS_AR71XX option which is not present in the kernel. Cc: Luis R. Rodriguez Cc: Vasanthakumar Thiagarajan Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Kconfig | 21 ++++++++++++++++++++- drivers/net/wireless/ath/ath9k/Makefile | 4 ++-- drivers/net/wireless/ath/ath9k/ath9k.h | 4 ++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index ad57a6d23110..d9ff8413ab9a 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -5,7 +5,7 @@ config ATH9K_COMMON config ATH9K tristate "Atheros 802.11n wireless cards support" - depends on PCI && MAC80211 + depends on MAC80211 select ATH9K_HW select MAC80211_LEDS select LEDS_CLASS @@ -23,6 +23,25 @@ config ATH9K If you choose to build a module, it'll be called ath9k. +config ATH9K_PCI + bool "Atheros ath9k PCI/PCIe bus support" + depends on ATH9K && PCI + default PCI + ---help--- + This option enables the PCI bus support in ath9k. + + Say Y, if you have a compatible PCI/PCIe wireless card. + +config ATH9K_AHB + bool "Atheros ath9k AHB bus support" + depends on ATH9K + default n + ---help--- + This option enables the AHB bus support in ath9k. + + Say Y, if you have a SoC with a compatible built-in + wireless MAC. Say N if unsure. + config ATH9K_DEBUGFS bool "Atheros ath9k debugging" depends on ATH9K && DEBUG_FS diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 4d66ca8042eb..ca4c436e0f65 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -6,8 +6,8 @@ ath9k-y += beacon.o \ xmit.o \ ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o -ath9k-$(CONFIG_PCI) += pci.o -ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o +ath9k-$(CONFIG_ATH9K_PCI) += pci.o +ath9k-$(CONFIG_ATH9K_AHB) += ahb.o ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o obj-$(CONFIG_ATH9K) += ath9k.o diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 38835bc324b2..77ad407e9fa3 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -665,7 +665,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode); bool ath9k_uses_beacons(int type); -#ifdef CONFIG_PCI +#ifdef CONFIG_ATH9K_PCI int ath_pci_init(void); void ath_pci_exit(void); #else @@ -673,7 +673,7 @@ static inline int ath_pci_init(void) { return 0; }; static inline void ath_pci_exit(void) {}; #endif -#ifdef CONFIG_ATHEROS_AR71XX +#ifdef CONFIG_ATH9K_AHB int ath_ahb_init(void); void ath_ahb_exit(void); #else -- cgit v1.2.3-58-ga151 From 4114fa21465ec7ee9526173676d3122a98bbbbd8 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 12 Apr 2011 19:15:22 +0200 Subject: mac80211: receive EAP frames from a station in an AP VLAN on the main AP This makes it easier to handle moving stations to VLAN interfaces that are part of a different bridge. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/rx.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 359fc394a3b0..54858a68abd7 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1586,7 +1586,7 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) } static int -__ieee80211_data_to_8023(struct ieee80211_rx_data *rx) +__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control) { struct ieee80211_sub_if_data *sdata = rx->sdata; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; @@ -1594,6 +1594,7 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) struct ethhdr *ehdr; int ret; + *port_control = false; if (ieee80211_has_a4(hdr->frame_control) && sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta) return -1; @@ -1612,11 +1613,13 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) return -1; ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); - if (ret < 0 || !check_port_control) + if (ret < 0) return ret; ehdr = (struct ethhdr *) rx->skb->data; - if (ehdr->h_proto != rx->sdata->control_port_protocol) + if (ehdr->h_proto == rx->sdata->control_port_protocol) + *port_control = true; + else if (check_port_control) return -1; return 0; @@ -1917,6 +1920,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) struct net_device *dev = sdata->dev; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; __le16 fc = hdr->frame_control; + bool port_control; int err; if (unlikely(!ieee80211_is_data(hdr->frame_control))) @@ -1933,13 +1937,21 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) sdata->vif.type == NL80211_IFTYPE_AP) return RX_DROP_MONITOR; - err = __ieee80211_data_to_8023(rx); + err = __ieee80211_data_to_8023(rx, &port_control); if (unlikely(err)) return RX_DROP_UNUSABLE; if (!ieee80211_frame_allowed(rx, fc)) return RX_DROP_MONITOR; + if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && + unlikely(port_control) && sdata->bss) { + sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, + u.ap); + dev = sdata->dev; + rx->sdata = sdata; + } + rx->skb->dev = dev; dev->stats.rx_packets++; -- cgit v1.2.3-58-ga151 From d0805c1c5758f8fd16c88bf1efa8fb4be4408ce1 Mon Sep 17 00:00:00 2001 From: Brian Cavagnolo Date: Tue, 12 Apr 2011 11:06:28 -0700 Subject: mwl8k: use traffic threshold to decide when to start ampdu Currently, ampdu stream is created on the first qos packet to an HT sta. The overhead of setting up the BA session may not be justified if the outgoing packet rate is minimal (e.g., ping). So we only allow ampdu streams after seeing a critical number of packets in an arbitrary one-second interval. Based on work by Nishant Sarmukadam Signed-off-by: Brian Cavagnolo Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 45 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index d2416709ba52..28ebaec80be6 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -289,10 +289,17 @@ struct mwl8k_vif { #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) #define IEEE80211_KEY_CONF(_u8) ((struct ieee80211_key_conf *)(_u8)) +struct tx_traffic_info { + u32 start_time; + u32 pkts; +}; + +#define MWL8K_MAX_TID 8 struct mwl8k_sta { /* Index into station database. Returned by UPDATE_STADB. */ u8 peer_id; u8 is_ampdu_allowed; + struct tx_traffic_info tx_stats[MWL8K_MAX_TID]; }; #define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv)) @@ -1754,6 +1761,41 @@ mwl8k_lookup_stream(struct ieee80211_hw *hw, u8 *addr, u8 tid) return NULL; } +#define MWL8K_AMPDU_PACKET_THRESHOLD 64 +static inline bool mwl8k_ampdu_allowed(struct ieee80211_sta *sta, u8 tid) +{ + struct mwl8k_sta *sta_info = MWL8K_STA(sta); + struct tx_traffic_info *tx_stats; + + BUG_ON(tid >= MWL8K_MAX_TID); + tx_stats = &sta_info->tx_stats[tid]; + + return sta_info->is_ampdu_allowed && + tx_stats->pkts > MWL8K_AMPDU_PACKET_THRESHOLD; +} + +static inline void mwl8k_tx_count_packet(struct ieee80211_sta *sta, u8 tid) +{ + struct mwl8k_sta *sta_info = MWL8K_STA(sta); + struct tx_traffic_info *tx_stats; + + BUG_ON(tid >= MWL8K_MAX_TID); + tx_stats = &sta_info->tx_stats[tid]; + + if (tx_stats->start_time == 0) + tx_stats->start_time = jiffies; + + /* reset the packet count after each second elapses. If the number of + * packets ever exceeds the ampdu_min_traffic threshold, we will allow + * an ampdu stream to be started. + */ + if (jiffies - tx_stats->start_time > HZ) { + tx_stats->pkts = 0; + tx_stats->start_time = 0; + } else + tx_stats->pkts++; +} + static void mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) { @@ -1840,6 +1882,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) skb->protocol != cpu_to_be16(ETH_P_PAE) && sta->ht_cap.ht_supported && priv->ap_fw) { tid = qos & 0xf; + mwl8k_tx_count_packet(sta, tid); spin_lock(&priv->stream_lock); stream = mwl8k_lookup_stream(hw, sta->addr, tid); if (stream != NULL) { @@ -1880,7 +1923,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) * prevents sequence number mismatch at the recepient * as described above. */ - if (MWL8K_STA(sta)->is_ampdu_allowed) { + if (mwl8k_ampdu_allowed(sta, tid)) { stream = mwl8k_add_stream(hw, sta, tid); if (stream != NULL) start_ba_session = true; -- cgit v1.2.3-58-ga151 From 9efabad2b228ef820f5ce969baa62860cf65b9ea Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:22:33 +0530 Subject: ath9k_htc: Remove AR7010 v1.0 support All the AR7010 devices supoprted by ath9k_htc are based on version v1.1, so remove support for v1.0. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index f1b8af64569c..3d53d9899628 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -17,11 +17,9 @@ #include "htc.h" /* identify firmware images */ -#define FIRMWARE_AR7010 "ar7010.fw" #define FIRMWARE_AR7010_1_1 "ar7010_1_1.fw" #define FIRMWARE_AR9271 "ar9271.fw" -MODULE_FIRMWARE(FIRMWARE_AR7010); MODULE_FIRMWARE(FIRMWARE_AR7010_1_1); MODULE_FIRMWARE(FIRMWARE_AR9271); @@ -1026,10 +1024,7 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, /* Find out which firmware to load */ if (IS_AR7010_DEVICE(id->driver_info)) - if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202) - hif_dev->fw_name = FIRMWARE_AR7010_1_1; - else - hif_dev->fw_name = FIRMWARE_AR7010; + hif_dev->fw_name = FIRMWARE_AR7010_1_1; else hif_dev->fw_name = FIRMWARE_AR9271; -- cgit v1.2.3-58-ga151 From ce18f391aa872a910e7798c340b6cf22d02c77a2 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:22:42 +0530 Subject: ath9k_htc: Rename firmware Since the new FW requires backward incompatible host driver changes, rename the FW to allow older driver versions to work with the older FW. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 3d53d9899628..23094b70d6eb 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -17,8 +17,8 @@ #include "htc.h" /* identify firmware images */ -#define FIRMWARE_AR7010_1_1 "ar7010_1_1.fw" -#define FIRMWARE_AR9271 "ar9271.fw" +#define FIRMWARE_AR7010_1_1 "htc_7010.fw" +#define FIRMWARE_AR9271 "htc_9271.fw" MODULE_FIRMWARE(FIRMWARE_AR7010_1_1); MODULE_FIRMWARE(FIRMWARE_AR9271); -- cgit v1.2.3-58-ga151 From 29bbfb2491316f9a3888e74b0de7fccdbde67aaa Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:22:51 +0530 Subject: ath9k_htc: Add a WMI command to get the firmware version Also, update the wiphy information and use the correct device pointer when registering. This would fix ethtool. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 3 +++ drivers/net/wireless/ath/ath9k/htc_drv_init.c | 32 +++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/wmi.c | 2 ++ drivers/net/wireless/ath/ath9k/wmi.h | 6 +++++ 4 files changed, 43 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index ec47be94b74f..9544cd7fd440 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -388,6 +388,9 @@ struct ath9k_htc_priv { struct htc_target *htc; struct wmi *wmi; + u16 fw_version_major; + u16 fw_version_minor; + enum htc_endpoint_id wmi_cmd_ep; enum htc_endpoint_id beacon_ep; enum htc_endpoint_id cab_ep; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 8303b34bdc90..6bbfca58deda 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -782,6 +782,32 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, SET_IEEE80211_PERM_ADDR(hw, common->macaddr); } +static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv) +{ + struct ieee80211_hw *hw = priv->hw; + struct wmi_fw_version cmd_rsp; + int ret; + + memset(&cmd_rsp, 0, sizeof(cmd_rsp)); + + WMI_CMD(WMI_GET_FW_VERSION); + if (ret) + return -EINVAL; + + priv->fw_version_major = be16_to_cpu(cmd_rsp.major); + priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor); + + snprintf(hw->wiphy->fw_version, ETHTOOL_BUSINFO_LEN, "%d.%d", + priv->fw_version_major, + priv->fw_version_minor); + + dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n", + priv->fw_version_major, + priv->fw_version_minor); + + return 0; +} + static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid, char *product, u32 drv_info) { @@ -801,6 +827,10 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, common = ath9k_hw_common(ah); ath9k_set_hw_capab(priv, hw); + error = ath9k_init_firmware_version(priv); + if (error != 0) + goto err_fw; + /* Initialize regulatory */ error = ath_regd_init(&common->regulatory, priv->hw->wiphy, ath9k_reg_notifier); @@ -861,6 +891,8 @@ err_rx: err_tx: /* Nothing */ err_regd: + /* Nothing */ +err_fw: ath9k_deinit_priv(priv); err_init: return error; diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index d3d24904f62f..267a98fcf5f2 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -23,6 +23,8 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_ECHO_CMDID"; case WMI_ACCESS_MEMORY_CMDID: return "WMI_ACCESS_MEMORY_CMDID"; + case WMI_GET_FW_VERSION: + return "WMI_GET_FW_VERSION"; case WMI_DISABLE_INTR_CMDID: return "WMI_DISABLE_INTR_CMDID"; case WMI_ENABLE_INTR_CMDID: diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 42084277522d..6a36572b6fb8 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -31,11 +31,17 @@ struct wmi_cmd_hdr { __be16 seq_no; } __packed; +struct wmi_fw_version { + __be16 major; + __be16 minor; + +} __packed; enum wmi_cmd_id { WMI_ECHO_CMDID = 0x0001, WMI_ACCESS_MEMORY_CMDID, /* Commands to Target */ + WMI_GET_FW_VERSION, WMI_DISABLE_INTR_CMDID, WMI_ENABLE_INTR_CMDID, WMI_RX_LINK_CMDID, -- cgit v1.2.3-58-ga151 From 1c165c972b040f9ce199b8d8d3cc4f619872cba5 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:22:59 +0530 Subject: ath9k_htc: Fix WMI and beacon header Match the beacon header with that of the firmware. Also, the firmware reports the TSF for an SWBA, so store it. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 2 +- drivers/net/wireless/ath/ath9k/wmi.c | 7 ++++++- drivers/net/wireless/ath/ath9k/wmi.h | 6 ++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 9544cd7fd440..cf7909ec0769 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -96,8 +96,8 @@ struct tx_mgmt_hdr { } __packed; struct tx_beacon_header { - u8 len_changed; u8 vif_index; + u8 len_changed; u16 rev; } __packed; diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 267a98fcf5f2..96171a2c6873 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -156,6 +156,7 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, struct wmi_cmd_hdr *hdr; u16 cmd_id; void *wmi_event; + struct wmi_event_swba *swba; #ifdef CONFIG_ATH9K_HTC_DEBUGFS __be32 txrate; #endif @@ -170,7 +171,11 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); switch (cmd_id) { case WMI_SWBA_EVENTID: - wmi->beacon_pending = *(u8 *)wmi_event; + swba = (struct wmi_event_swba *) wmi_event; + + wmi->tsf = be64_to_cpu(swba->tsf); + wmi->beacon_pending = swba->beacon_pending; + tasklet_schedule(&wmi->drv_priv->swba_tasklet); break; case WMI_FATAL_EVENTID: diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 6a36572b6fb8..2fa91a941a72 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -36,6 +36,11 @@ struct wmi_fw_version { __be16 minor; } __packed; + +struct wmi_event_swba { + __be64 tsf; + u8 beacon_pending; +}; enum wmi_cmd_id { WMI_ECHO_CMDID = 0x0001, WMI_ACCESS_MEMORY_CMDID, @@ -106,6 +111,7 @@ struct wmi { u32 cmd_rsp_len; bool stopped; + u64 tsf; u8 beacon_pending; spinlock_t wmi_lock; -- cgit v1.2.3-58-ga151 From 832f6a18fc2aead14954c081ece03b7a5b425f81 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:23:08 +0530 Subject: ath9k_htc: Add beacon slots Beacon transmission is now handled through a slot mechanism. This allows multiple beaconing interfaces to be be present. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 13 ++- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 123 +++++++++++++++++++++--- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 5 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 12 ++- drivers/net/wireless/ath/ath9k/wmi.c | 4 +- 5 files changed, 138 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index cf7909ec0769..31c649605d79 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -244,6 +244,7 @@ struct ath9k_htc_vif { u8 index; u16 seq_no; bool beacon_configured; + int bslot; }; struct ath9k_vif_iter_data { @@ -351,10 +352,14 @@ struct ath_led { int brightness; }; +#define BSTUCK_THRESHOLD 10 + struct htc_beacon_config { + struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF]; u16 beacon_interval; u16 dtim_period; u16 bmiss_timeout; + u32 bmiss_cnt; }; struct ath_btcoex { @@ -414,7 +419,6 @@ struct ath9k_htc_priv { u16 txpowlimit; u16 nvifs; u16 nstations; - u32 bmiss_cnt; bool rearm_ani; bool reconfig_beacon; @@ -425,7 +429,6 @@ struct ath9k_htc_priv { bool tx_queues_stop; spinlock_t tx_lock; - struct ieee80211_vif *vif; struct htc_beacon_config cur_beacon_conf; unsigned int rxfilter; struct tasklet_struct swba_tasklet; @@ -473,11 +476,15 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) void ath9k_htc_reset(struct ath9k_htc_priv *priv); +void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif); +void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif); void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif); void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv); -void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); +void ath9k_htc_swba(struct ath9k_htc_priv *priv); void ath9k_htc_rxep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 8f56158e5887..b561f703e467 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -172,12 +172,13 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, imask |= ATH9K_INT_SWBA; ath_dbg(common, ATH_DBG_CONFIG, - "AP Beacon config, intval: %d, nexttbtt: %u imask: 0x%x\n", + "AP Beacon config, intval: %d, nexttbtt: %u " + "imask: 0x%x\n", bss_conf->beacon_interval, nexttbtt, imask); WMI_CMD(WMI_DISABLE_INTR_CMDID); ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); - priv->bmiss_cnt = 0; + priv->cur_beacon_conf.bmiss_cnt = 0; htc_imask = cpu_to_be32(imask); WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); } @@ -214,7 +215,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, WMI_CMD(WMI_DISABLE_INTR_CMDID); ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); - priv->bmiss_cnt = 0; + priv->cur_beacon_conf.bmiss_cnt = 0; htc_imask = cpu_to_be32(imask); WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); } @@ -225,9 +226,11 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, dev_kfree_skb_any(skb); } -void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) +static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, + int slot) { - struct ath9k_htc_vif *avp = (void *)priv->vif->drv_priv; + struct ieee80211_vif *vif; + struct ath9k_htc_vif *avp; struct tx_beacon_header beacon_hdr; struct ath9k_htc_tx_ctl tx_ctl; struct ieee80211_tx_info *info; @@ -237,21 +240,18 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); - /* FIXME: Handle BMISS */ - if (beacon_pending != 0) { - priv->bmiss_cnt++; - return; - } - spin_lock_bh(&priv->beacon_lock); + vif = priv->cur_beacon_conf.bslot[slot]; + avp = (struct ath9k_htc_vif *)vif->drv_priv; + if (unlikely(priv->op_flags & OP_SCANNING)) { spin_unlock_bh(&priv->beacon_lock); return; } /* Get a new beacon */ - beacon = ieee80211_beacon_get(priv->hw, priv->vif); + beacon = ieee80211_beacon_get(priv->hw, vif); if (!beacon) { spin_unlock_bh(&priv->beacon_lock); return; @@ -276,6 +276,69 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) spin_unlock_bh(&priv->beacon_lock); } +static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + unsigned long flags; + u64 tsf; + u32 tsftu; + u16 intval; + int slot; + + intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD; + + spin_lock_irqsave(&priv->wmi->wmi_lock, flags); + tsf = priv->wmi->tsf; + spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); + + tsftu = TSF_TO_TU(tsf >> 32, tsf); + slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval; + slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1; + + ath_dbg(common, ATH_DBG_BEACON, + "Choose slot: %d, tsf: %llu, tsftu: %u, intval: %u\n", + slot, tsf, tsftu, intval); + + return slot; +} + +void ath9k_htc_swba(struct ath9k_htc_priv *priv) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + unsigned long flags; + int slot; + + spin_lock_irqsave(&priv->wmi->wmi_lock, flags); + if (priv->wmi->beacon_pending != 0) { + spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); + priv->cur_beacon_conf.bmiss_cnt++; + if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) { + ath_dbg(common, ATH_DBG_BEACON, + "Beacon stuck, HW reset\n"); + ath9k_htc_reset(priv); + } + return; + } + spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); + + if (priv->cur_beacon_conf.bmiss_cnt) { + ath_dbg(common, ATH_DBG_BEACON, + "Resuming beacon xmit after %u misses\n", + priv->cur_beacon_conf.bmiss_cnt); + priv->cur_beacon_conf.bmiss_cnt = 0; + } + + slot = ath9k_htc_choose_bslot(priv); + spin_lock_bh(&priv->beacon_lock); + if (priv->cur_beacon_conf.bslot[slot] == NULL) { + spin_unlock_bh(&priv->beacon_lock); + return; + } + spin_unlock_bh(&priv->beacon_lock); + + ath9k_htc_send_beacon(priv, slot); +} + /* Currently, only for IBSS */ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) { @@ -307,6 +370,42 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) } } +void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; + int i = 0; + + spin_lock_bh(&priv->beacon_lock); + for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) { + if (priv->cur_beacon_conf.bslot[i] == NULL) { + avp->bslot = i; + break; + } + } + + priv->cur_beacon_conf.bslot[avp->bslot] = vif; + spin_unlock_bh(&priv->beacon_lock); + + ath_dbg(common, ATH_DBG_CONFIG, + "Added interface at beacon slot: %d\n", avp->bslot); +} + +void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; + + spin_lock_bh(&priv->beacon_lock); + priv->cur_beacon_conf.bslot[avp->bslot] = NULL; + spin_unlock_bh(&priv->beacon_lock); + + ath_dbg(common, ATH_DBG_CONFIG, + "Removed interface at beacon slot: %d\n", avp->bslot); +} + static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { bool *beacon_configured = (bool *)data; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 6bbfca58deda..9405e0ad7032 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -643,7 +643,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, { struct ath_hw *ah = NULL; struct ath_common *common; - int ret = 0, csz = 0; + int i, ret = 0, csz = 0; priv->op_flags |= OP_INVALID; @@ -711,6 +711,9 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, if (ret) goto err_queues; + for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) + priv->cur_beacon_conf.bslot[i] = NULL; + ath9k_init_crypto(priv); ath9k_init_channels_rates(priv); ath9k_init_misc(priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index db8c0c044e9e..293a9b38e22e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1281,9 +1281,13 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, priv->vif_slot |= (1 << avp->index); priv->nvifs++; - priv->vif = vif; INC_VIF(priv, vif->type); + + if ((vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_ADHOC)) + ath9k_htc_assign_bslot(priv, vif); + ath9k_htc_set_opmode(priv); if ((priv->ah->opmode == NL80211_IFTYPE_AP) && @@ -1321,9 +1325,13 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, priv->vif_slot &= ~(1 << avp->index); ath9k_htc_remove_station(priv, vif, NULL); - priv->vif = NULL; DEC_VIF(priv, vif->type); + + if ((vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_ADHOC)) + ath9k_htc_remove_bslot(priv, vif); + ath9k_htc_set_opmode(priv); /* diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 96171a2c6873..a39552b3077b 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -126,7 +126,7 @@ void ath9k_swba_tasklet(unsigned long data) { struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; - ath9k_htc_swba(priv, priv->wmi->beacon_pending); + ath9k_htc_swba(priv); } void ath9k_fatal_work(struct work_struct *work) @@ -173,8 +173,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, case WMI_SWBA_EVENTID: swba = (struct wmi_event_swba *) wmi_event; + spin_lock(&wmi->wmi_lock); wmi->tsf = be64_to_cpu(swba->tsf); wmi->beacon_pending = swba->beacon_pending; + spin_unlock(&wmi->wmi_lock); tasklet_schedule(&wmi->drv_priv->swba_tasklet); break; -- cgit v1.2.3-58-ga151 From 9b674a0207c9b75ddcdcdb07e46843fac8267507 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:23:17 +0530 Subject: ath9k_htc: Add TSF adjust capability In multi-interface mode, beacons/probe responses that are sent out must have their timestamp field updated. Calculate the TSF adjustment value for each beaconing interface and set it in the frame properly. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 3 +++ drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 36 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/htc_drv_main.c | 5 +++- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 12 ++++++++- 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 31c649605d79..87e4ca911a58 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -245,6 +245,7 @@ struct ath9k_htc_vif { u16 seq_no; bool beacon_configured; int bslot; + __le64 tsfadjust; }; struct ath9k_vif_iter_data { @@ -480,6 +481,8 @@ void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif); void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif); +void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif); void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index b561f703e467..2fad613add51 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -234,6 +234,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, struct tx_beacon_header beacon_hdr; struct ath9k_htc_tx_ctl tx_ctl; struct ieee80211_tx_info *info; + struct ieee80211_mgmt *mgmt; struct sk_buff *beacon; u8 *tx_fhdr; @@ -257,6 +258,13 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, return; } + /* + * Update the TSF adjust value here, the HW will + * add this value for every beacon. + */ + mgmt = (struct ieee80211_mgmt *)beacon->data; + mgmt->u.beacon.timestamp = avp->tsfadjust; + info = IEEE80211_SKB_CB(beacon); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { struct ieee80211_hdr *hdr = @@ -406,6 +414,34 @@ void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, "Removed interface at beacon slot: %d\n", avp->bslot); } +/* + * Calculate the TSF adjustment value for all slots + * other than zero. + */ +void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; + struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; + u64 tsfadjust; + + if (avp->bslot == 0) + return; + + /* + * The beacon interval cannot be different for multi-AP mode, + * and we reach here only for VIF slots greater than zero, + * so beacon_interval is guaranteed to be set in cur_conf. + */ + tsfadjust = cur_conf->beacon_interval * avp->bslot / ATH9K_HTC_MAX_BCN_VIF; + avp->tsfadjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); + + ath_dbg(common, ATH_DBG_CONFIG, + "tsfadjust is: %llu for bslot: %d\n", + (unsigned long long)tsfadjust, avp->bslot); +} + static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { bool *beacon_configured = (bool *)data; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 293a9b38e22e..6926ac0d5e5c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1291,8 +1291,10 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, ath9k_htc_set_opmode(priv); if ((priv->ah->opmode == NL80211_IFTYPE_AP) && - !(priv->op_flags & OP_ANI_RUNNING)) + !(priv->op_flags & OP_ANI_RUNNING)) { + ath9k_hw_set_tsfadjust(priv->ah, 1); ath9k_htc_start_ani(priv); + } ath_dbg(common, ATH_DBG_CONFIG, "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index); @@ -1652,6 +1654,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) { ath_dbg(common, ATH_DBG_CONFIG, "Beacon enabled for BSS: %pM\n", bss_conf->bssid); + ath9k_htc_set_tsfadjust(priv, vif); priv->op_flags |= OP_ENABLE_BEACON; ath9k_htc_beacon_config(priv, vif); } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 4a4f27ba96af..b3f94850821e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -82,11 +82,12 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) { struct ieee80211_hdr *hdr; + struct ieee80211_mgmt *mgmt; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_sta *sta = tx_info->control.sta; struct ieee80211_vif *vif = tx_info->control.vif; struct ath9k_htc_sta *ista; - struct ath9k_htc_vif *avp; + struct ath9k_htc_vif *avp = NULL; struct ath9k_htc_tx_ctl tx_ctl; enum htc_endpoint_id epid; u16 qnum; @@ -195,6 +196,15 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); + /* + * Set the TSF adjust value for probe response + * frame also. + */ + if (avp && unlikely(ieee80211_is_probe_resp(fc))) { + mgmt = (struct ieee80211_mgmt *)skb->data; + mgmt->u.probe_resp.timestamp = avp->tsfadjust; + } + tx_ctl.type = ATH9K_HTC_NORMAL; mgmt_hdr.node_idx = sta_idx; -- cgit v1.2.3-58-ga151 From 2493a547ee81e6daca812d5dd7cf9357aebc379b Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:23:26 +0530 Subject: ath9k_htc: Configure the beacon queue Set operating parameters (cwmin, cwmax) for the beacon queue in AP mode. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 77 +++++++++++++++---------- 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 2fad613add51..7aafd2179398 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -18,6 +18,50 @@ #define FUDGE 2 +void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) +{ + struct ath_hw *ah = priv->ah; + struct ath9k_tx_queue_info qi, qi_be; + + memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); + memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); + + ath9k_hw_get_txq_props(ah, priv->beaconq, &qi); + + if (priv->ah->opmode == NL80211_IFTYPE_AP) { + qi.tqi_aifs = 1; + qi.tqi_cwmin = 0; + qi.tqi_cwmax = 0; + } else if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { + int qnum = priv->hwq_map[WME_AC_BE]; + + ath9k_hw_get_txq_props(ah, qnum, &qi_be); + + qi.tqi_aifs = qi_be.tqi_aifs; + + /* + * For WIFI Beacon Distribution + * Long slot time : 2x cwmin + * Short slot time : 4x cwmin + */ + if (ah->slottime == ATH9K_SLOT_TIME_20) + qi.tqi_cwmin = 2*qi_be.tqi_cwmin; + else + qi.tqi_cwmin = 4*qi_be.tqi_cwmin; + + qi.tqi_cwmax = qi_be.tqi_cwmax; + + } + + if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { + ath_err(ath9k_hw_common(ah), + "Unable to update beacon queue %u!\n", priv->beaconq); + } else { + ath9k_hw_resettxqueue(ah, priv->beaconq); + } +} + + static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, struct htc_beacon_config *bss_conf) { @@ -176,6 +220,8 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, "imask: 0x%x\n", bss_conf->beacon_interval, nexttbtt, imask); + ath9k_htc_beaconq_config(priv); + WMI_CMD(WMI_DISABLE_INTR_CMDID); ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); priv->cur_beacon_conf.bmiss_cnt = 0; @@ -347,37 +393,6 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv) ath9k_htc_send_beacon(priv, slot); } -/* Currently, only for IBSS */ -void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) -{ - struct ath_hw *ah = priv->ah; - struct ath9k_tx_queue_info qi, qi_be; - int qnum = priv->hwq_map[WME_AC_BE]; - - memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); - memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); - - ath9k_hw_get_txq_props(ah, qnum, &qi_be); - - qi.tqi_aifs = qi_be.tqi_aifs; - /* For WIFI Beacon Distribution - * Long slot time : 2x cwmin - * Short slot time : 4x cwmin - */ - if (ah->slottime == ATH9K_SLOT_TIME_20) - qi.tqi_cwmin = 2*qi_be.tqi_cwmin; - else - qi.tqi_cwmin = 4*qi_be.tqi_cwmin; - qi.tqi_cwmax = qi_be.tqi_cwmax; - - if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { - ath_err(ath9k_hw_common(ah), - "Unable to update beacon queue %u!\n", qnum); - } else { - ath9k_hw_resettxqueue(ah, priv->beaconq); - } -} - void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif) { -- cgit v1.2.3-58-ga151 From 7d547eb4bb664c5a6b7c8790c2ecb0aec5d15385 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:23:34 +0530 Subject: ath9k_htc: Handle buffered frames in AP mode Use the CAB endpoint to send buffered multicast or broadcast frames after each SWBA event. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 6 +++- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 43 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/htc_drv_init.c | 3 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 5 ++- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 14 ++++++-- 5 files changed, 65 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 87e4ca911a58..a072a9eb3f3e 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -292,6 +292,7 @@ struct ath9k_htc_tx_ctl { #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) +#define CAB_STAT_INC priv->debug.tx_stats.cab_queued++ #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) @@ -301,6 +302,7 @@ struct ath_tx_stats { u32 skb_queued; u32 skb_completed; u32 skb_dropped; + u32 cab_queued; u32 queue_stats[WME_NUM_AC]; }; @@ -324,6 +326,7 @@ struct ath9k_debug { #define TX_STAT_INC(c) do { } while (0) #define RX_STAT_INC(c) do { } while (0) +#define CAB_STAT_INC do { } while (0) #define TX_QSTAT_INC(c) do { } while (0) @@ -505,7 +508,8 @@ void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv); int ath9k_tx_init(struct ath9k_htc_priv *priv); void ath9k_tx_tasklet(unsigned long data); -int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb); +int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, + struct sk_buff *skb, bool is_cab); void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype); int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 7aafd2179398..c96779c24296 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -272,6 +272,48 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, dev_kfree_skb_any(skb); } +static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, + int slot) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ieee80211_vif *vif; + struct sk_buff *skb; + struct ieee80211_hdr *hdr; + int padpos, padsize, ret; + + spin_lock_bh(&priv->beacon_lock); + + vif = priv->cur_beacon_conf.bslot[slot]; + + skb = ieee80211_get_buffered_bc(priv->hw, vif); + + while(skb) { + hdr = (struct ieee80211_hdr *) skb->data; + + padpos = ath9k_cmn_padpos(hdr->frame_control); + padsize = padpos & 3; + if (padsize && skb->len > padpos) { + if (skb_headroom(skb) < padsize) { + dev_kfree_skb_any(skb); + goto next; + } + skb_push(skb, padsize); + memmove(skb->data, skb->data + padsize, padpos); + } + + ret = ath9k_htc_tx_start(priv, skb, true); + if (ret != 0) { + ath_dbg(common, ATH_DBG_FATAL, + "Failed to send CAB frame\n"); + dev_kfree_skb_any(skb); + } + next: + skb = ieee80211_get_buffered_bc(priv->hw, vif); + } + + spin_unlock_bh(&priv->beacon_lock); +} + static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, int slot) { @@ -390,6 +432,7 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv) } spin_unlock_bh(&priv->beacon_lock); + ath9k_htc_send_buffered(priv, slot); ath9k_htc_send_beacon(priv, slot); } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 9405e0ad7032..b1c68bff72a6 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -748,7 +748,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, IEEE80211_HW_HAS_RATE_CONTROL | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK; + IEEE80211_HW_PS_NULLFUNC_STACK | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 6926ac0d5e5c..8f38075d1240 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -797,6 +797,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "SKBs dropped", priv->debug.tx_stats.skb_dropped); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "CAB queued", + priv->debug.tx_stats.cab_queued); len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "BE queued", @@ -1054,7 +1057,7 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) memmove(skb->data, skb->data + padsize, padpos); } - ret = ath9k_htc_tx_start(priv, skb); + ret = ath9k_htc_tx_start(priv, skb, false); if (ret != 0) { if (ret == -ENOMEM) { ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index b3f94850821e..0e2855893669 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -79,7 +79,8 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, return error; } -int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) +int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, + struct sk_buff *skb, bool is_cab) { struct ieee80211_hdr *hdr; struct ieee80211_mgmt *mgmt; @@ -170,6 +171,12 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) tx_fhdr = skb_push(skb, sizeof(tx_hdr)); memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); + if (is_cab) { + CAB_STAT_INC; + epid = priv->cab_ep; + goto send; + } + qnum = skb_get_queue_mapping(skb); switch (qnum) { @@ -222,7 +229,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); epid = priv->mgmt_ep; } - +send: return htc_send(priv->htc, skb, epid, &tx_ctl); } @@ -326,7 +333,8 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, } else if ((ep_id == priv->data_bk_ep) || (ep_id == priv->data_be_ep) || (ep_id == priv->data_vi_ep) || - (ep_id == priv->data_vo_ep)) { + (ep_id == priv->data_vo_ep) || + (ep_id == priv->cab_ep)) { skb_pull(skb, sizeof(struct tx_frame_hdr)); } else { ath_err(common, "Unsupported TX EPID: %d\n", ep_id); -- cgit v1.2.3-58-ga151 From b0a6ba983e3663bf256ca2e79d17bb846878cd9e Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:23:44 +0530 Subject: ath9k_htc: Fix beacon miss under heavy load Transmission of beacons becomes erratic when TX load is high, since the latency involved in the generation of a SWBA interrupt on the target to the actual sending of a beacon is quite high for USB devices. Fix this by adjusting the beacon response time. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 7 +++++ drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 39 +++++++++++++++++++++---- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index a072a9eb3f3e..133fc6dc3929 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -358,6 +358,13 @@ struct ath_led { #define BSTUCK_THRESHOLD 10 +/* + * Adjust these when the max. no of beaconing interfaces is + * increased. + */ +#define DEFAULT_SWBA_RESPONSE 40 /* in TUs */ +#define MIN_SWBA_RESPONSE 10 /* in TUs */ + struct htc_beacon_config { struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF]; u16 beacon_interval; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index c96779c24296..48bc28823f6f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -198,6 +198,15 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, intval /= ATH9K_HTC_MAX_BCN_VIF; nexttbtt = intval; + /* + * To reduce beacon misses under heavy TX load, + * set the beacon response time to a larger value. + */ + if (intval > DEFAULT_SWBA_RESPONSE) + priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; + else + priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; + if (priv->op_flags & OP_TSF_RESET) { ath9k_hw_reset_tsf(priv->ah); priv->op_flags &= ~OP_TSF_RESET; @@ -216,9 +225,10 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, imask |= ATH9K_INT_SWBA; ath_dbg(common, ATH_DBG_CONFIG, - "AP Beacon config, intval: %d, nexttbtt: %u " + "AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d " "imask: 0x%x\n", - bss_conf->beacon_interval, nexttbtt, imask); + bss_conf->beacon_interval, nexttbtt, + priv->ah->config.sw_beacon_response_time, imask); ath9k_htc_beaconq_config(priv); @@ -252,12 +262,22 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, nexttbtt += intval; } while (nexttbtt < tsftu); + /* + * Only one IBSS interfce is allowed. + */ + if (intval > DEFAULT_SWBA_RESPONSE) + priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; + else + priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; + if (priv->op_flags & OP_ENABLE_BEACON) imask |= ATH9K_INT_SWBA; ath_dbg(common, ATH_DBG_CONFIG, - "IBSS Beacon config, intval: %d, nexttbtt: %u, imask: 0x%x\n", - bss_conf->beacon_interval, nexttbtt, imask); + "IBSS Beacon config, intval: %d, nexttbtt: %u, " + "resp_time: %d, imask: 0x%x\n", + bss_conf->beacon_interval, nexttbtt, + priv->ah->config.sw_beacon_response_time, imask); WMI_CMD(WMI_DISABLE_INTR_CMDID); ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); @@ -317,6 +337,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, int slot) { + struct ath_common *common = ath9k_hw_common(priv->ah); struct ieee80211_vif *vif; struct ath9k_htc_vif *avp; struct tx_beacon_header beacon_hdr; @@ -325,6 +346,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, struct ieee80211_mgmt *mgmt; struct sk_buff *beacon; u8 *tx_fhdr; + int ret; memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); @@ -367,7 +389,14 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); - htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl); + ret = htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl); + if (ret != 0) { + if (ret == -ENOMEM) { + ath_dbg(common, ATH_DBG_BSTUCK, + "Failed to send beacon, no free TX buffer\n"); + } + dev_kfree_skb_any(beacon); + } spin_unlock_bh(&priv->beacon_lock); } -- cgit v1.2.3-58-ga151 From f4c88991f51e097b6541f998fd23d477999e5886 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:23:52 +0530 Subject: ath9k_htc: Queue WMI events Use a queue to handle WMI events and schedule a tasklet to process the events. This fixes the race between the WMI event ISR and the SWBA tasklet when the arrival of WMI events in quick succession could overwrite the SWBA data before the tasklet from a previous iteration could have been scheduled. Also, drain the WMI queue properly. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 3 +- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 27 +++---- drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 3 + drivers/net/wireless/ath/ath9k/htc_drv_init.c | 2 - drivers/net/wireless/ath/ath9k/htc_drv_main.c | 7 +- drivers/net/wireless/ath/ath9k/wmi.c | 97 ++++++++++++++++--------- drivers/net/wireless/ath/ath9k/wmi.h | 7 +- 7 files changed, 89 insertions(+), 57 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 133fc6dc3929..20511af33f5f 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -497,7 +497,8 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif); void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv); -void ath9k_htc_swba(struct ath9k_htc_priv *priv); +void ath9k_htc_swba(struct ath9k_htc_priv *priv, + struct wmi_event_swba *swba); void ath9k_htc_rxep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 48bc28823f6f..2180a9da3801 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -401,10 +401,10 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, spin_unlock_bh(&priv->beacon_lock); } -static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv) +static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv, + struct wmi_event_swba *swba) { struct ath_common *common = ath9k_hw_common(priv->ah); - unsigned long flags; u64 tsf; u32 tsftu; u16 intval; @@ -412,10 +412,7 @@ static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv) intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD; - spin_lock_irqsave(&priv->wmi->wmi_lock, flags); - tsf = priv->wmi->tsf; - spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); - + tsf = be64_to_cpu(swba->tsf); tsftu = TSF_TO_TU(tsf >> 32, tsf); slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval; slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1; @@ -427,33 +424,31 @@ static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv) return slot; } -void ath9k_htc_swba(struct ath9k_htc_priv *priv) +void ath9k_htc_swba(struct ath9k_htc_priv *priv, + struct wmi_event_swba *swba) { struct ath_common *common = ath9k_hw_common(priv->ah); - unsigned long flags; int slot; - spin_lock_irqsave(&priv->wmi->wmi_lock, flags); - if (priv->wmi->beacon_pending != 0) { - spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); + if (swba->beacon_pending != 0) { priv->cur_beacon_conf.bmiss_cnt++; if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) { - ath_dbg(common, ATH_DBG_BEACON, + ath_dbg(common, ATH_DBG_BSTUCK, "Beacon stuck, HW reset\n"); - ath9k_htc_reset(priv); + ieee80211_queue_work(priv->hw, + &priv->fatal_work); } return; } - spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); if (priv->cur_beacon_conf.bmiss_cnt) { - ath_dbg(common, ATH_DBG_BEACON, + ath_dbg(common, ATH_DBG_BSTUCK, "Resuming beacon xmit after %u misses\n", priv->cur_beacon_conf.bmiss_cnt); priv->cur_beacon_conf.bmiss_cnt = 0; } - slot = ath9k_htc_choose_bslot(priv); + slot = ath9k_htc_choose_bslot(priv, swba); spin_lock_bh(&priv->beacon_lock); if (priv->cur_beacon_conf.bslot[slot] == NULL) { spin_unlock_bh(&priv->beacon_lock); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 7e630a81b453..459ba0d36f4c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -436,6 +436,9 @@ void ath9k_htc_radio_disable(struct ieee80211_hw *hw) /* Stop RX */ WMI_CMD(WMI_STOP_RECV_CMDID); + /* Clear the WMI event queue */ + ath9k_wmi_event_drain(priv); + /* * The MIB counters have to be disabled here, * since the target doesn't do it. diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index b1c68bff72a6..921d76f32016 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -676,8 +676,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, spin_lock_init(&priv->tx_lock); mutex_init(&priv->mutex); mutex_init(&priv->htc_pm_lock); - tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet, - (unsigned long)priv); tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, (unsigned long)priv); tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 8f38075d1240..81dfe0782f74 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -202,6 +202,8 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); + ath9k_wmi_event_drain(priv); + caldata = &priv->caldata; ret = ath9k_hw_reset(ah, ah->curchan, caldata, false); if (ret) { @@ -255,6 +257,8 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); + ath9k_wmi_event_drain(priv); + ath_dbg(common, ATH_DBG_CONFIG, "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", priv->ah->curchan->channel, @@ -1172,12 +1176,13 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); - tasklet_kill(&priv->swba_tasklet); tasklet_kill(&priv->rx_tasklet); tasklet_kill(&priv->tx_tasklet); skb_queue_purge(&priv->tx_queue); + ath9k_wmi_event_drain(priv); + mutex_unlock(&priv->mutex); /* Cancel all the running timers/work .. */ diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index a39552b3077b..45784754dbc2 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -104,9 +104,12 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv) wmi->drv_priv = priv; wmi->stopped = false; + skb_queue_head_init(&wmi->wmi_event_queue); mutex_init(&wmi->op_mutex); mutex_init(&wmi->multi_write_mutex); init_completion(&wmi->cmd_wait); + tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet, + (unsigned long)wmi); return wmi; } @@ -122,11 +125,64 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv) kfree(priv->wmi); } -void ath9k_swba_tasklet(unsigned long data) +void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv) { - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; + unsigned long flags; - ath9k_htc_swba(priv); + tasklet_kill(&priv->wmi->wmi_event_tasklet); + spin_lock_irqsave(&priv->wmi->wmi_lock, flags); + __skb_queue_purge(&priv->wmi->wmi_event_queue); + spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); +} + +void ath9k_wmi_event_tasklet(unsigned long data) +{ + struct wmi *wmi = (struct wmi *)data; + struct ath9k_htc_priv *priv = wmi->drv_priv; + struct wmi_cmd_hdr *hdr; + void *wmi_event; + struct wmi_event_swba *swba; + struct sk_buff *skb = NULL; + unsigned long flags; + u16 cmd_id; +#ifdef CONFIG_ATH9K_HTC_DEBUGFS + __be32 txrate; +#endif + + do { + spin_lock_irqsave(&wmi->wmi_lock, flags); + skb = __skb_dequeue(&wmi->wmi_event_queue); + if (!skb) { + spin_unlock_irqrestore(&wmi->wmi_lock, flags); + return; + } + spin_unlock_irqrestore(&wmi->wmi_lock, flags); + + hdr = (struct wmi_cmd_hdr *) skb->data; + cmd_id = be16_to_cpu(hdr->command_id); + wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); + + switch (cmd_id) { + case WMI_SWBA_EVENTID: + swba = (struct wmi_event_swba *) wmi_event; + ath9k_htc_swba(priv, swba); + break; + case WMI_FATAL_EVENTID: + ieee80211_queue_work(wmi->drv_priv->hw, + &wmi->drv_priv->fatal_work); + break; + case WMI_TXRATE_EVENTID: +#ifdef CONFIG_ATH9K_HTC_DEBUGFS + txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; + wmi->drv_priv->debug.txrate = be32_to_cpu(txrate); +#endif + break; + default: + break; + } + + kfree_skb(skb); + } while (1); } void ath9k_fatal_work(struct work_struct *work) @@ -155,11 +211,6 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, struct wmi *wmi = (struct wmi *) priv; struct wmi_cmd_hdr *hdr; u16 cmd_id; - void *wmi_event; - struct wmi_event_swba *swba; -#ifdef CONFIG_ATH9K_HTC_DEBUGFS - __be32 txrate; -#endif if (unlikely(wmi->stopped)) goto free_skb; @@ -168,32 +219,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, cmd_id = be16_to_cpu(hdr->command_id); if (cmd_id & 0x1000) { - wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); - switch (cmd_id) { - case WMI_SWBA_EVENTID: - swba = (struct wmi_event_swba *) wmi_event; - - spin_lock(&wmi->wmi_lock); - wmi->tsf = be64_to_cpu(swba->tsf); - wmi->beacon_pending = swba->beacon_pending; - spin_unlock(&wmi->wmi_lock); - - tasklet_schedule(&wmi->drv_priv->swba_tasklet); - break; - case WMI_FATAL_EVENTID: - ieee80211_queue_work(wmi->drv_priv->hw, - &wmi->drv_priv->fatal_work); - break; - case WMI_TXRATE_EVENTID: -#ifdef CONFIG_ATH9K_HTC_DEBUGFS - txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; - wmi->drv_priv->debug.txrate = be32_to_cpu(txrate); -#endif - break; - default: - break; - } - kfree_skb(skb); + spin_lock(&wmi->wmi_lock); + __skb_queue_tail(&wmi->wmi_event_queue, skb); + spin_unlock(&wmi->wmi_lock); + tasklet_schedule(&wmi->wmi_event_tasklet); return; } diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 2fa91a941a72..ff5ba2b30ecc 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -106,13 +106,13 @@ struct wmi { struct mutex op_mutex; struct completion cmd_wait; enum wmi_cmd_id last_cmd_id; + struct sk_buff_head wmi_event_queue; + struct tasklet_struct wmi_event_tasklet; u16 tx_seq_id; u8 *cmd_rsp_buf; u32 cmd_rsp_len; bool stopped; - u64 tsf; - u8 beacon_pending; spinlock_t wmi_lock; atomic_t mwrite_cnt; @@ -129,8 +129,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, u8 *cmd_buf, u32 cmd_len, u8 *rsp_buf, u32 rsp_len, u32 timeout); -void ath9k_swba_tasklet(unsigned long data); +void ath9k_wmi_event_tasklet(unsigned long data); void ath9k_fatal_work(struct work_struct *work); +void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv); #define WMI_CMD(_wmi_cmd) \ do { \ -- cgit v1.2.3-58-ga151 From 8e42e4ba98f986be64016df79eacbb671dbd3d18 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:24:00 +0530 Subject: ath9k_htc: Move debug code to a separate file Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 2 + drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 219 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/htc_drv_main.c | 212 ------------------------ 3 files changed, 221 insertions(+), 212 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/htc_drv_debug.c diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index ca4c436e0f65..05a6fade7b1c 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -48,4 +48,6 @@ ath9k_htc-y += htc_hst.o \ htc_drv_init.o \ htc_drv_gpio.o +ath9k_htc-$(CONFIG_ATH9K_HTC_DEBUGFS) += htc_drv_debug.o + obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c new file mode 100644 index 000000000000..8b679aab338a --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2010-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "htc.h" + +static struct dentry *ath9k_debugfs_root; + +static int ath9k_debugfs_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + struct ath9k_htc_target_stats cmd_rsp; + char buf[512]; + unsigned int len = 0; + int ret = 0; + + memset(&cmd_rsp, 0, sizeof(cmd_rsp)); + + WMI_CMD(WMI_TGT_STATS_CMDID); + if (ret) + return -EINVAL; + + + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Short Retries", + be32_to_cpu(cmd_rsp.tx_shortretry)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Long Retries", + be32_to_cpu(cmd_rsp.tx_longretry)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Xretries", + be32_to_cpu(cmd_rsp.tx_xretries)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Unaggr. Xretries", + be32_to_cpu(cmd_rsp.ht_txunaggr_xretry)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Xretries (HT)", + be32_to_cpu(cmd_rsp.ht_tx_xretries)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Rate", priv->debug.txrate); + + if (len > sizeof(buf)) + len = sizeof(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_tgt_stats = { + .read = read_file_tgt_stats, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static ssize_t read_file_xmit(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + char buf[512]; + unsigned int len = 0; + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "Buffers queued", + priv->debug.tx_stats.buf_queued); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "Buffers completed", + priv->debug.tx_stats.buf_completed); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs queued", + priv->debug.tx_stats.skb_queued); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs completed", + priv->debug.tx_stats.skb_completed); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs dropped", + priv->debug.tx_stats.skb_dropped); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "CAB queued", + priv->debug.tx_stats.cab_queued); + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "BE queued", + priv->debug.tx_stats.queue_stats[WME_AC_BE]); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "BK queued", + priv->debug.tx_stats.queue_stats[WME_AC_BK]); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "VI queued", + priv->debug.tx_stats.queue_stats[WME_AC_VI]); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "VO queued", + priv->debug.tx_stats.queue_stats[WME_AC_VO]); + + if (len > sizeof(buf)) + len = sizeof(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_xmit = { + .read = read_file_xmit, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static ssize_t read_file_recv(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + char buf[512]; + unsigned int len = 0; + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs allocated", + priv->debug.rx_stats.skb_allocated); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs completed", + priv->debug.rx_stats.skb_completed); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs Dropped", + priv->debug.rx_stats.skb_dropped); + + if (len > sizeof(buf)) + len = sizeof(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_recv = { + .read = read_file_recv, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +int ath9k_htc_init_debug(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + + if (!ath9k_debugfs_root) + return -ENOENT; + + priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy), + ath9k_debugfs_root); + if (!priv->debug.debugfs_phy) + goto err; + + priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_tgt_stats); + if (!priv->debug.debugfs_tgt_stats) + goto err; + + + priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_xmit); + if (!priv->debug.debugfs_xmit) + goto err; + + priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_recv); + if (!priv->debug.debugfs_recv) + goto err; + + return 0; + +err: + ath9k_htc_exit_debug(ah); + return -ENOMEM; +} + +void ath9k_htc_exit_debug(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + + debugfs_remove(priv->debug.debugfs_recv); + debugfs_remove(priv->debug.debugfs_xmit); + debugfs_remove(priv->debug.debugfs_tgt_stats); + debugfs_remove(priv->debug.debugfs_phy); +} + +int ath9k_htc_debug_create_root(void) +{ + ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); + if (!ath9k_debugfs_root) + return -ENOENT; + + return 0; +} + +void ath9k_htc_debug_remove_root(void) +{ + debugfs_remove(ath9k_debugfs_root); + ath9k_debugfs_root = NULL; +} diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 81dfe0782f74..59710e75f051 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -16,10 +16,6 @@ #include "htc.h" -#ifdef CONFIG_ATH9K_HTC_DEBUGFS -static struct dentry *ath9k_debugfs_root; -#endif - /*************/ /* Utilities */ /*************/ @@ -720,214 +716,6 @@ static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, return ret; } -/*********/ -/* DEBUG */ -/*********/ - -#ifdef CONFIG_ATH9K_HTC_DEBUGFS - -static int ath9k_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = file->private_data; - struct ath9k_htc_target_stats cmd_rsp; - char buf[512]; - unsigned int len = 0; - int ret = 0; - - memset(&cmd_rsp, 0, sizeof(cmd_rsp)); - - WMI_CMD(WMI_TGT_STATS_CMDID); - if (ret) - return -EINVAL; - - - len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Short Retries", - be32_to_cpu(cmd_rsp.tx_shortretry)); - len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Long Retries", - be32_to_cpu(cmd_rsp.tx_longretry)); - len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Xretries", - be32_to_cpu(cmd_rsp.tx_xretries)); - len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Unaggr. Xretries", - be32_to_cpu(cmd_rsp.ht_txunaggr_xretry)); - len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Xretries (HT)", - be32_to_cpu(cmd_rsp.ht_tx_xretries)); - len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Rate", priv->debug.txrate); - - if (len > sizeof(buf)) - len = sizeof(buf); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_tgt_stats = { - .read = read_file_tgt_stats, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static ssize_t read_file_xmit(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = file->private_data; - char buf[512]; - unsigned int len = 0; - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "Buffers queued", - priv->debug.tx_stats.buf_queued); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "Buffers completed", - priv->debug.tx_stats.buf_completed); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs queued", - priv->debug.tx_stats.skb_queued); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs completed", - priv->debug.tx_stats.skb_completed); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs dropped", - priv->debug.tx_stats.skb_dropped); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "CAB queued", - priv->debug.tx_stats.cab_queued); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "BE queued", - priv->debug.tx_stats.queue_stats[WME_AC_BE]); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "BK queued", - priv->debug.tx_stats.queue_stats[WME_AC_BK]); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "VI queued", - priv->debug.tx_stats.queue_stats[WME_AC_VI]); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "VO queued", - priv->debug.tx_stats.queue_stats[WME_AC_VO]); - - if (len > sizeof(buf)) - len = sizeof(buf); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_xmit = { - .read = read_file_xmit, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static ssize_t read_file_recv(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = file->private_data; - char buf[512]; - unsigned int len = 0; - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs allocated", - priv->debug.rx_stats.skb_allocated); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs completed", - priv->debug.rx_stats.skb_completed); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs Dropped", - priv->debug.rx_stats.skb_dropped); - - if (len > sizeof(buf)) - len = sizeof(buf); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_recv = { - .read = read_file_recv, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -int ath9k_htc_init_debug(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - - if (!ath9k_debugfs_root) - return -ENOENT; - - priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy), - ath9k_debugfs_root); - if (!priv->debug.debugfs_phy) - goto err; - - priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_tgt_stats); - if (!priv->debug.debugfs_tgt_stats) - goto err; - - - priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_xmit); - if (!priv->debug.debugfs_xmit) - goto err; - - priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_recv); - if (!priv->debug.debugfs_recv) - goto err; - - return 0; - -err: - ath9k_htc_exit_debug(ah); - return -ENOMEM; -} - -void ath9k_htc_exit_debug(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - - debugfs_remove(priv->debug.debugfs_recv); - debugfs_remove(priv->debug.debugfs_xmit); - debugfs_remove(priv->debug.debugfs_tgt_stats); - debugfs_remove(priv->debug.debugfs_phy); -} - -int ath9k_htc_debug_create_root(void) -{ - ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (!ath9k_debugfs_root) - return -ENOENT; - - return 0; -} - -void ath9k_htc_debug_remove_root(void) -{ - debugfs_remove(ath9k_debugfs_root); - ath9k_debugfs_root = NULL; -} - -#endif /* CONFIG_ATH9K_HTC_DEBUGFS */ - /*******/ /* ANI */ /*******/ -- cgit v1.2.3-58-ga151 From 719c4cf6b1b113e9caf377c6607ae45758a85871 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:24:10 +0530 Subject: ath9k_htc: Add RX error statistics Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 16 ++++ drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 109 +++++++++++++++++++++++-- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 2 + 3 files changed, 118 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 20511af33f5f..0e48fa0efa77 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -296,6 +296,9 @@ struct ath9k_htc_tx_ctl { #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) +void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, + struct ath_htc_rx_status *rxs); + struct ath_tx_stats { u32 buf_queued; u32 buf_completed; @@ -310,6 +313,14 @@ struct ath_rx_stats { u32 skb_allocated; u32 skb_completed; u32 skb_dropped; + u32 err_crc; + u32 err_decrypt_crc; + u32 err_mic; + u32 err_pre_delim; + u32 err_post_delim; + u32 err_decrypt_busy; + u32 err_phy; + u32 err_phy_stats[ATH9K_PHYERR_MAX]; }; struct ath9k_debug { @@ -330,6 +341,11 @@ struct ath9k_debug { #define TX_QSTAT_INC(c) do { } while (0) +static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, + struct ath_htc_rx_status *rxs) +{ +} + #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ #define ATH_LED_PIN_DEF 1 diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 8b679aab338a..6fc6cb749362 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -123,27 +123,118 @@ static const struct file_operations fops_xmit = { .llseek = default_llseek, }; +void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, + struct ath_htc_rx_status *rxs) +{ +#define RX_PHY_ERR_INC(c) priv->debug.rx_stats.err_phy_stats[c]++ + + if (rxs->rs_status & ATH9K_RXERR_CRC) + priv->debug.rx_stats.err_crc++; + if (rxs->rs_status & ATH9K_RXERR_DECRYPT) + priv->debug.rx_stats.err_decrypt_crc++; + if (rxs->rs_status & ATH9K_RXERR_MIC) + priv->debug.rx_stats.err_mic++; + if (rxs->rs_status & ATH9K_RX_DELIM_CRC_PRE) + priv->debug.rx_stats.err_pre_delim++; + if (rxs->rs_status & ATH9K_RX_DELIM_CRC_POST) + priv->debug.rx_stats.err_post_delim++; + if (rxs->rs_status & ATH9K_RX_DECRYPT_BUSY) + priv->debug.rx_stats.err_decrypt_busy++; + + if (rxs->rs_status & ATH9K_RXERR_PHY) { + priv->debug.rx_stats.err_phy++; + if (rxs->rs_phyerr < ATH9K_PHYERR_MAX) + RX_PHY_ERR_INC(rxs->rs_phyerr); + } + +#undef RX_PHY_ERR_INC +} + static ssize_t read_file_recv(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { +#define PHY_ERR(s, p) \ + len += snprintf(buf + len, size - len, "%20s : %10u\n", s, \ + priv->debug.rx_stats.err_phy_stats[p]); + struct ath9k_htc_priv *priv = file->private_data; - char buf[512]; - unsigned int len = 0; + char *buf; + unsigned int len = 0, size = 1500; + ssize_t retval = 0; - len += snprintf(buf + len, sizeof(buf) - len, + buf = kzalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + len += snprintf(buf + len, size - len, "%20s : %10u\n", "SKBs allocated", priv->debug.rx_stats.skb_allocated); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, size - len, "%20s : %10u\n", "SKBs completed", priv->debug.rx_stats.skb_completed); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, size - len, "%20s : %10u\n", "SKBs Dropped", priv->debug.rx_stats.skb_dropped); - if (len > sizeof(buf)) - len = sizeof(buf); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); + len += snprintf(buf + len, size - len, + "%20s : %10u\n", "CRC ERR", + priv->debug.rx_stats.err_crc); + len += snprintf(buf + len, size - len, + "%20s : %10u\n", "DECRYPT CRC ERR", + priv->debug.rx_stats.err_decrypt_crc); + len += snprintf(buf + len, size - len, + "%20s : %10u\n", "MIC ERR", + priv->debug.rx_stats.err_mic); + len += snprintf(buf + len, size - len, + "%20s : %10u\n", "PRE-DELIM CRC ERR", + priv->debug.rx_stats.err_pre_delim); + len += snprintf(buf + len, size - len, + "%20s : %10u\n", "POST-DELIM CRC ERR", + priv->debug.rx_stats.err_post_delim); + len += snprintf(buf + len, size - len, + "%20s : %10u\n", "DECRYPT BUSY ERR", + priv->debug.rx_stats.err_decrypt_busy); + len += snprintf(buf + len, size - len, + "%20s : %10u\n", "TOTAL PHY ERR", + priv->debug.rx_stats.err_phy); + + + PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); + PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); + PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); + PHY_ERR("RATE", ATH9K_PHYERR_RATE); + PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH); + PHY_ERR("RADAR", ATH9K_PHYERR_RADAR); + PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE); + PHY_ERR("TOR", ATH9K_PHYERR_TOR); + PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING); + PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); + PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); + PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); + PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP); + PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE); + PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART); + PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT); + PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING); + PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC); + PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL); + PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE); + PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART); + PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); + PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP); + PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR); + PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); + PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); + + if (len > size) + len = size; + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + + return retval; + +#undef PHY_ERR } static const struct file_operations fops_recv = { diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 0e2855893669..a62495d1330a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -540,6 +540,8 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, goto rx_next; } + ath9k_htc_err_stat_rx(priv, rxstatus); + /* Get the RX status information */ memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); -- cgit v1.2.3-58-ga151 From b1563a4c3d721cb0496b8e1fb874f08a8f2b62cc Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:24:19 +0530 Subject: ath9k_htc: Fix RX length check The length of the received SKB could be equal to HTC_RX_FRAME_HEADER_SIZE in case of packets with phy/crc errors, in which case they are dropped without being processed. Fix this check so that the error counters are updated correctly. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index a62495d1330a..7cd3e4e66aa6 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -525,8 +525,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, int last_rssi = ATH_RSSI_DUMMY_MARKER; __le16 fc; - if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) { - ath_err(common, "Corrupted RX frame, dropping\n"); + if (skb->len < HTC_RX_FRAME_HEADER_SIZE) { + ath_err(common, "Corrupted RX frame, dropping (len: %d)\n", + skb->len); goto rx_next; } -- cgit v1.2.3-58-ga151 From e723f3900c3b23feb427672c6ccfe5d4243d2c2d Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:24:25 +0530 Subject: ath9k_htc: Remove unused WMI commands WMI_TGT_TXQ_ENABLE_CMDID WMI_HOST_ATTACH WMI_DEBUG_INFO_CMDID WMI_BEACON_UPDATE_CMDID WMI_RESET_CMDID WMI_RX_LINK_CMDID WMI_STOP_DMA_RECV_CMDID Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/wmi.c | 14 -------------- drivers/net/wireless/ath/ath9k/wmi.h | 7 ------- 2 files changed, 21 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 45784754dbc2..3b8f25fbecfd 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -29,16 +29,12 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_DISABLE_INTR_CMDID"; case WMI_ENABLE_INTR_CMDID: return "WMI_ENABLE_INTR_CMDID"; - case WMI_RX_LINK_CMDID: - return "WMI_RX_LINK_CMDID"; case WMI_ATH_INIT_CMDID: return "WMI_ATH_INIT_CMDID"; case WMI_ABORT_TXQ_CMDID: return "WMI_ABORT_TXQ_CMDID"; case WMI_STOP_TX_DMA_CMDID: return "WMI_STOP_TX_DMA_CMDID"; - case WMI_STOP_DMA_RECV_CMDID: - return "WMI_STOP_DMA_RECV_CMDID"; case WMI_ABORT_TX_DMA_CMDID: return "WMI_ABORT_TX_DMA_CMDID"; case WMI_DRAIN_TXQ_CMDID: @@ -53,8 +49,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_FLUSH_RECV_CMDID"; case WMI_SET_MODE_CMDID: return "WMI_SET_MODE_CMDID"; - case WMI_RESET_CMDID: - return "WMI_RESET_CMDID"; case WMI_NODE_CREATE_CMDID: return "WMI_NODE_CREATE_CMDID"; case WMI_NODE_REMOVE_CMDID: @@ -63,8 +57,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_VAP_REMOVE_CMDID"; case WMI_VAP_CREATE_CMDID: return "WMI_VAP_CREATE_CMDID"; - case WMI_BEACON_UPDATE_CMDID: - return "WMI_BEACON_UPDATE_CMDID"; case WMI_REG_READ_CMDID: return "WMI_REG_READ_CMDID"; case WMI_REG_WRITE_CMDID: @@ -73,10 +65,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_RC_STATE_CHANGE_CMDID"; case WMI_RC_RATE_UPDATE_CMDID: return "WMI_RC_RATE_UPDATE_CMDID"; - case WMI_DEBUG_INFO_CMDID: - return "WMI_DEBUG_INFO_CMDID"; - case WMI_HOST_ATTACH: - return "WMI_HOST_ATTACH"; case WMI_TARGET_IC_UPDATE_CMDID: return "WMI_TARGET_IC_UPDATE_CMDID"; case WMI_TGT_STATS_CMDID: @@ -85,8 +73,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_TX_AGGR_ENABLE_CMDID"; case WMI_TGT_DETACH_CMDID: return "WMI_TGT_DETACH_CMDID"; - case WMI_TGT_TXQ_ENABLE_CMDID: - return "WMI_TGT_TXQ_ENABLE_CMDID"; case WMI_AGGR_LIMIT_CMD: return "WMI_AGGR_LIMIT_CMD"; } diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index ff5ba2b30ecc..3ab9604fd6bd 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -49,11 +49,9 @@ enum wmi_cmd_id { WMI_GET_FW_VERSION, WMI_DISABLE_INTR_CMDID, WMI_ENABLE_INTR_CMDID, - WMI_RX_LINK_CMDID, WMI_ATH_INIT_CMDID, WMI_ABORT_TXQ_CMDID, WMI_STOP_TX_DMA_CMDID, - WMI_STOP_DMA_RECV_CMDID, WMI_ABORT_TX_DMA_CMDID, WMI_DRAIN_TXQ_CMDID, WMI_DRAIN_TXQ_ALL_CMDID, @@ -61,23 +59,18 @@ enum wmi_cmd_id { WMI_STOP_RECV_CMDID, WMI_FLUSH_RECV_CMDID, WMI_SET_MODE_CMDID, - WMI_RESET_CMDID, WMI_NODE_CREATE_CMDID, WMI_NODE_REMOVE_CMDID, WMI_VAP_REMOVE_CMDID, WMI_VAP_CREATE_CMDID, - WMI_BEACON_UPDATE_CMDID, WMI_REG_READ_CMDID, WMI_REG_WRITE_CMDID, WMI_RC_STATE_CHANGE_CMDID, WMI_RC_RATE_UPDATE_CMDID, - WMI_DEBUG_INFO_CMDID, - WMI_HOST_ATTACH, WMI_TARGET_IC_UPDATE_CMDID, WMI_TGT_STATS_CMDID, WMI_TX_AGGR_ENABLE_CMDID, WMI_TGT_DETACH_CMDID, - WMI_TGT_TXQ_ENABLE_CMDID, WMI_AGGR_LIMIT_CMD = 0x0026, }; -- cgit v1.2.3-58-ga151 From 40dc9e4b86963b77918f1b8fa02b98c1e420a7e1 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:24:31 +0530 Subject: ath9k_htc: Use SKB's private area for TX parameters For all packets sent through the USB_WLAN_TX_PIPE endpoint, the private area of the SKB's tx_info can be used to store driver-specific information. For packets sent through USB_REG_OUT_PIPE, this will not make a difference since they are routed through a separate routine that doesn't access the private region. This would help in situations where TX information is required in the URB callback. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 17 +++++++++-------- drivers/net/wireless/ath/ath9k/htc.h | 14 +++++++++++++- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 11 +++++++---- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 15 ++++++++------- drivers/net/wireless/ath/ath9k/htc_hst.c | 18 +++++++++--------- drivers/net/wireless/ath/ath9k/htc_hst.h | 5 ++--- drivers/net/wireless/ath/ath9k/wmi.c | 2 +- 7 files changed, 49 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 23094b70d6eb..e252576760d1 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -284,9 +284,9 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) return ret; } -static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb, - struct ath9k_htc_tx_ctl *tx_ctl) +static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb) { + struct ath9k_htc_tx_ctl *tx_ctl; unsigned long flags; spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); @@ -305,12 +305,14 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb, __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); hif_dev->tx.tx_skb_cnt++; - /* Send normal frames immediately */ - if (!tx_ctl || (tx_ctl && (tx_ctl->type == ATH9K_HTC_NORMAL))) + tx_ctl = HTC_SKB_CB(skb); + + /* Send normal/mgmt/beacon frames immediately */ + if (tx_ctl->type != ATH9K_HTC_AMPDU) __hif_usb_tx(hif_dev); /* Check if AMPDUs have to be sent immediately */ - if (tx_ctl && (tx_ctl->type == ATH9K_HTC_AMPDU) && + if ((tx_ctl->type == ATH9K_HTC_AMPDU) && (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && (hif_dev->tx.tx_skb_cnt < 2)) { __hif_usb_tx(hif_dev); @@ -352,15 +354,14 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id) } } -static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb, - struct ath9k_htc_tx_ctl *tx_ctl) +static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb) { struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; int ret = 0; switch (pipe_id) { case USB_WLAN_TX_PIPE: - ret = hif_usb_send_tx(hif_dev, skb, tx_ctl); + ret = hif_usb_send_tx(hif_dev, skb); break; case USB_REG_OUT_PIPE: ret = hif_usb_send_regout(hif_dev, skb); diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 0e48fa0efa77..2eabfe4ad268 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -67,8 +67,11 @@ enum htc_opmode { }; #define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr) -#define ATH9K_HTC_AMPDU 1 + +#define ATH9K_HTC_AMPDU 1 #define ATH9K_HTC_NORMAL 2 +#define ATH9K_HTC_BEACON 3 +#define ATH9K_HTC_MGMT 4 #define ATH9K_HTC_TX_CTSONLY 0x1 #define ATH9K_HTC_TX_RTSCTS 0x2 @@ -288,6 +291,15 @@ struct ath9k_htc_tx_ctl { u8 type; /* ATH9K_HTC_* */ }; +static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + + BUILD_BUG_ON(sizeof(struct ath9k_htc_tx_ctl) > + IEEE80211_TX_INFO_DRIVER_DATA_SIZE); + return (struct ath9k_htc_tx_ctl *) &tx_info->driver_data; +} + #ifdef CONFIG_ATH9K_HTC_DEBUGFS #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 2180a9da3801..713def184519 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -341,7 +341,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif; struct ath9k_htc_vif *avp; struct tx_beacon_header beacon_hdr; - struct ath9k_htc_tx_ctl tx_ctl; + struct ath9k_htc_tx_ctl *tx_ctl; struct ieee80211_tx_info *info; struct ieee80211_mgmt *mgmt; struct sk_buff *beacon; @@ -349,7 +349,6 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, int ret; memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); - memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); spin_lock_bh(&priv->beacon_lock); @@ -384,12 +383,16 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); } - tx_ctl.type = ATH9K_HTC_NORMAL; + tx_ctl = HTC_SKB_CB(beacon); + memset(tx_ctl, 0, sizeof(*tx_ctl)); + + tx_ctl->type = ATH9K_HTC_BEACON; + beacon_hdr.vif_index = avp->index; tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); - ret = htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl); + ret = htc_send(priv->htc, beacon, priv->beacon_ep); if (ret != 0) { if (ret == -ENOMEM) { ath_dbg(common, ATH_DBG_BSTUCK, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 7cd3e4e66aa6..ab55dff4721f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -89,13 +89,16 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif = tx_info->control.vif; struct ath9k_htc_sta *ista; struct ath9k_htc_vif *avp = NULL; - struct ath9k_htc_tx_ctl tx_ctl; + struct ath9k_htc_tx_ctl *tx_ctl; enum htc_endpoint_id epid; u16 qnum; __le16 fc; u8 *tx_fhdr; u8 sta_idx, vif_idx; + tx_ctl = HTC_SKB_CB(skb); + memset(tx_ctl, 0, sizeof(*tx_ctl)); + hdr = (struct ieee80211_hdr *) skb->data; fc = hdr->frame_control; @@ -126,8 +129,6 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, sta_idx = priv->vif_sta_pos[vif_idx]; } - memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); - if (ieee80211_is_data(fc)) { struct tx_frame_hdr tx_hdr; u32 flags = 0; @@ -139,10 +140,10 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, tx_hdr.vif_idx = vif_idx; if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { - tx_ctl.type = ATH9K_HTC_AMPDU; + tx_ctl->type = ATH9K_HTC_AMPDU; tx_hdr.data_type = ATH9K_HTC_AMPDU; } else { - tx_ctl.type = ATH9K_HTC_NORMAL; + tx_ctl->type = ATH9K_HTC_NORMAL; tx_hdr.data_type = ATH9K_HTC_NORMAL; } @@ -212,7 +213,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, mgmt->u.probe_resp.timestamp = avp->tsfadjust; } - tx_ctl.type = ATH9K_HTC_NORMAL; + tx_ctl->type = ATH9K_HTC_MGMT; mgmt_hdr.node_idx = sta_idx; mgmt_hdr.vif_idx = vif_idx; @@ -230,7 +231,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, epid = priv->mgmt_ep; } send: - return htc_send(priv->htc, skb, epid, &tx_ctl); + return htc_send(priv->htc, skb, epid); } static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index c41ab8c30161..6ee53de45c6a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -17,8 +17,8 @@ #include "htc.h" static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, - u16 len, u8 flags, u8 epid, - struct ath9k_htc_tx_ctl *tx_ctl) + u16 len, u8 flags, u8 epid) + { struct htc_frame_hdr *hdr; struct htc_endpoint *endpoint = &target->endpoint[epid]; @@ -30,8 +30,8 @@ static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, hdr->flags = flags; hdr->payload_len = cpu_to_be16(len); - status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb, - tx_ctl); + status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb); + return status; } @@ -162,7 +162,7 @@ static int htc_config_pipe_credits(struct htc_target *target) target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; - ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); + ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); if (ret) goto err; @@ -197,7 +197,7 @@ static int htc_setup_complete(struct htc_target *target) target->htc_flags |= HTC_OP_START_WAIT; - ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); + ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); if (ret) goto err; @@ -268,7 +268,7 @@ int htc_connect_service(struct htc_target *target, conn_msg->dl_pipeid = endpoint->dl_pipeid; conn_msg->ul_pipeid = endpoint->ul_pipeid; - ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); + ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); if (ret) goto err; @@ -287,9 +287,9 @@ err: } int htc_send(struct htc_target *target, struct sk_buff *skb, - enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl) + enum htc_endpoint_id epid) { - return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl); + return htc_issue_send(target, skb, skb->len, 0, epid); } void htc_stop(struct htc_target *target) diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index ecd018798c47..3531552672e0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -35,8 +35,7 @@ struct ath9k_htc_hif { void (*start) (void *hif_handle, u8 pipe); void (*stop) (void *hif_handle, u8 pipe); - int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf, - struct ath9k_htc_tx_ctl *tx_ctl); + int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf); }; enum htc_endpoint_id { @@ -206,7 +205,7 @@ int htc_connect_service(struct htc_target *target, struct htc_service_connreq *service_connreq, enum htc_endpoint_id *conn_rsp_eid); int htc_send(struct htc_target *target, struct sk_buff *skb, - enum htc_endpoint_id eid, struct ath9k_htc_tx_ctl *tx_ctl); + enum htc_endpoint_id eid); void htc_stop(struct htc_target *target); void htc_start(struct htc_target *target); diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 3b8f25fbecfd..83d1e0e5dd8c 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -267,7 +267,7 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi, hdr->command_id = cpu_to_be16(cmd); hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); - return htc_send(wmi->htc, skb, wmi->ctrl_epid, NULL); + return htc_send(wmi->htc, skb, wmi->ctrl_epid); } int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, -- cgit v1.2.3-58-ga151 From b97c57ff3f568b33ed91915f48431feae2dab288 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:24:37 +0530 Subject: ath9k_htc: Sync struct ath9k_htc_target_sta with FW Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 30 ++++----------------------- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 6 ++---- 2 files changed, 6 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 2eabfe4ad268..e096624d9073 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -104,17 +104,6 @@ struct tx_beacon_header { u16 rev; } __packed; -struct ath9k_htc_target_hw { - u32 flags; - u32 flags_ext; - u32 ampdu_limit; - u8 ampdu_subframes; - u8 tx_chainmask; - u8 tx_chainmask_legacy; - u8 rtscts_ratecode; - u8 protmode; -} __packed; - struct ath9k_htc_cap_target { u32 flags; u32 flags_ext; @@ -146,27 +135,16 @@ struct ath9k_htc_target_vif { #define ATH_HTC_STA_ERP 0x0004 #define ATH_HTC_STA_HT 0x0008 -/* FIXME: UAPSD variables */ struct ath9k_htc_target_sta { - u16 associd; - u16 txpower; - u32 ucastkey; u8 macaddr[ETH_ALEN]; u8 bssid[ETH_ALEN]; u8 sta_index; u8 vif_index; - u8 vif_sta; - __be16 flags; /* ATH_HTC_STA_* */ - u16 htcap; - u8 valid; - u16 capinfo; - struct ath9k_htc_target_hw *hw; - struct ath9k_htc_target_vif *vif; - u16 txseqmgmt; u8 is_vif_sta; - u16 maxampdu; - u16 iv16; - u32 iv32; + __be16 flags; /* ATH_HTC_STA_* */ + __be16 htcap; + __be16 maxampdu; + u8 pad; } __packed; struct ath9k_htc_target_aggr { diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 59710e75f051..9bb20f33638c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -382,7 +382,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) tsta.is_vif_sta = 1; tsta.sta_index = sta_idx; tsta.vif_index = hvif.index; - tsta.maxampdu = 0xffff; + tsta.maxampdu = cpu_to_be16(0xffff); WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); if (ret) { @@ -463,9 +463,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, ista = (struct ath9k_htc_sta *) sta->drv_priv; memcpy(&tsta.macaddr, sta->addr, ETH_ALEN); memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); - tsta.associd = common->curaid; tsta.is_vif_sta = 0; - tsta.valid = true; ista->index = sta_idx; } else { memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); @@ -474,7 +472,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, tsta.sta_index = sta_idx; tsta.vif_index = avp->index; - tsta.maxampdu = 0xffff; + tsta.maxampdu = cpu_to_be16(0xffff); if (sta && sta->ht_cap.ht_supported) tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); -- cgit v1.2.3-58-ga151 From e4c62506fcfa7c1fa7c586ab518a172c3a65db0f Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:24:43 +0530 Subject: ath9k_htc: Sync struct ath9k_htc_target_vif with FW Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 12 +++--------- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 8 ++++---- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index e096624d9073..f74f45f238af 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -117,17 +117,11 @@ struct ath9k_htc_cap_target { struct ath9k_htc_target_vif { u8 index; - u8 des_bssid[ETH_ALEN]; - __be32 opmode; + u8 opmode; u8 myaddr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - u32 flags; - u32 flags_ext; - u16 ps_sta; - __be16 rtsthreshold; u8 ath_cap; - u8 node; - s8 mcast_rate; + __be16 rtsthreshold; + u8 pad; } __packed; #define ATH_HTC_STA_AUTH 0x0001 diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 9bb20f33638c..400226702e0a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -349,7 +349,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); - hvif.opmode = cpu_to_be32(HTC_M_MONITOR); + hvif.opmode = HTC_M_MONITOR; hvif.index = ffz(priv->vif_slot); WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); @@ -1039,13 +1039,13 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, switch (vif->type) { case NL80211_IFTYPE_STATION: - hvif.opmode = cpu_to_be32(HTC_M_STA); + hvif.opmode = HTC_M_STA; break; case NL80211_IFTYPE_ADHOC: - hvif.opmode = cpu_to_be32(HTC_M_IBSS); + hvif.opmode = HTC_M_IBSS; break; case NL80211_IFTYPE_AP: - hvif.opmode = cpu_to_be32(HTC_M_HOSTAP); + hvif.opmode = HTC_M_HOSTAP; break; default: ath_err(common, -- cgit v1.2.3-58-ga151 From 0a8579f6b7c3f4332ad9eb6615c7631ef9cd4ed6 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:24:49 +0530 Subject: ath9k_htc: Sync struct ath9k_htc_cap_target with FW Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index f74f45f238af..1568c3692da4 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -113,6 +113,7 @@ struct ath9k_htc_cap_target { u8 tx_chainmask_legacy; u8 rtscts_ratecode; u8 protmode; + u8 pad; } __packed; struct ath9k_htc_target_vif { -- cgit v1.2.3-58-ga151 From ee3fa1bdadd998652083a7814af745f765a06a25 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:24:55 +0530 Subject: ath9k_htc: Remove unused WMI_WLAN_TXCOMP_EVENTID Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/wmi.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 3ab9604fd6bd..a81d554edb8e 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -80,7 +80,6 @@ enum wmi_event_id { WMI_FATAL_EVENTID, WMI_TXTO_EVENTID, WMI_BMISS_EVENTID, - WMI_WLAN_TXCOMP_EVENTID, WMI_DELBA_EVENTID, WMI_TXRATE_EVENTID, }; -- cgit v1.2.3-58-ga151 From 658ef04fd42a587b17a379ad9208023473442ddd Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:25:00 +0530 Subject: ath9k_htc: Move TX specific stuff to a separate structure Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 19 ++++++++++++------- drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 8 ++++---- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 22 +++++++++++----------- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 24 ++++++++++++------------ 5 files changed, 40 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 1568c3692da4..3af8a58d400f 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -260,6 +260,13 @@ struct ath9k_htc_rx { spinlock_t rxbuflock; }; +struct ath9k_htc_tx { + bool tx_queues_stop; + spinlock_t tx_lock; + + struct sk_buff_head tx_queue; +}; + struct ath9k_htc_tx_ctl { u8 type; /* ATH9K_HTC_* */ }; @@ -433,22 +440,20 @@ struct ath9k_htc_priv { u16 nstations; bool rearm_ani; bool reconfig_beacon; + unsigned int rxfilter; struct ath9k_hw_cal_data caldata; + struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; spinlock_t beacon_lock; + struct htc_beacon_config cur_beacon_conf; - bool tx_queues_stop; - spinlock_t tx_lock; + struct ath9k_htc_rx rx; + struct ath9k_htc_tx tx; - struct htc_beacon_config cur_beacon_conf; - unsigned int rxfilter; struct tasklet_struct swba_tasklet; struct tasklet_struct rx_tasklet; - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; - struct ath9k_htc_rx rx; struct tasklet_struct tx_tasklet; - struct sk_buff_head tx_queue; struct delayed_work ani_work; struct work_struct ps_work; struct work_struct fatal_work; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 459ba0d36f4c..1f6df4a1d224 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -398,9 +398,9 @@ void ath9k_htc_radio_enable(struct ieee80211_hw *hw) /* Start TX */ htc_start(priv->htc); - spin_lock_bh(&priv->tx_lock); - priv->tx_queues_stop = false; - spin_unlock_bh(&priv->tx_lock); + spin_lock_bh(&priv->tx.tx_lock); + priv->tx.tx_queues_stop = false; + spin_unlock_bh(&priv->tx.tx_lock); ieee80211_wake_queues(hw); WMI_CMD(WMI_ENABLE_INTR_CMDID); @@ -431,7 +431,7 @@ void ath9k_htc_radio_disable(struct ieee80211_hw *hw) ieee80211_stop_queues(hw); htc_stop(priv->htc); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); - skb_queue_purge(&priv->tx_queue); + skb_queue_purge(&priv->tx.tx_queue); /* Stop RX */ WMI_CMD(WMI_STOP_RECV_CMDID); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 921d76f32016..c270da7be10f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -673,7 +673,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, spin_lock_init(&priv->wmi->wmi_lock); spin_lock_init(&priv->beacon_lock); - spin_lock_init(&priv->tx_lock); + spin_lock_init(&priv->tx.tx_lock); mutex_init(&priv->mutex); mutex_init(&priv->htc_pm_lock); tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 400226702e0a..ff3a49577a02 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -707,9 +707,9 @@ static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, (aggr.aggr_enable) ? "Starting" : "Stopping", sta->addr, tid); - spin_lock_bh(&priv->tx_lock); + spin_lock_bh(&priv->tx.tx_lock); ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; - spin_unlock_bh(&priv->tx_lock); + spin_unlock_bh(&priv->tx.tx_lock); return ret; } @@ -853,9 +853,9 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, "Stopping TX queues\n"); ieee80211_stop_queues(hw); - spin_lock_bh(&priv->tx_lock); - priv->tx_queues_stop = true; - spin_unlock_bh(&priv->tx_lock); + spin_lock_bh(&priv->tx.tx_lock); + priv->tx.tx_queues_stop = true; + spin_unlock_bh(&priv->tx.tx_lock); } else { ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, "Tx failed\n"); @@ -923,9 +923,9 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) priv->op_flags &= ~OP_INVALID; htc_start(priv->htc); - spin_lock_bh(&priv->tx_lock); - priv->tx_queues_stop = false; - spin_unlock_bh(&priv->tx_lock); + spin_lock_bh(&priv->tx.tx_lock); + priv->tx.tx_queues_stop = false; + spin_unlock_bh(&priv->tx.tx_lock); ieee80211_wake_queues(hw); @@ -965,7 +965,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) tasklet_kill(&priv->rx_tasklet); tasklet_kill(&priv->tx_tasklet); - skb_queue_purge(&priv->tx_queue); + skb_queue_purge(&priv->tx.tx_queue); ath9k_wmi_event_drain(priv); @@ -1563,9 +1563,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, break; case IEEE80211_AMPDU_TX_OPERATIONAL: ista = (struct ath9k_htc_sta *) sta->drv_priv; - spin_lock_bh(&priv->tx_lock); + spin_lock_bh(&priv->tx.tx_lock); ista->tid_state[tid] = AGGR_OPERATIONAL; - spin_unlock_bh(&priv->tx_lock); + spin_unlock_bh(&priv->tx.tx_lock); break; default: ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index ab55dff4721f..6f7987d7b6b0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -239,10 +239,10 @@ static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, { bool ret = false; - spin_lock_bh(&priv->tx_lock); + spin_lock_bh(&priv->tx.tx_lock); if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP)) ret = true; - spin_unlock_bh(&priv->tx_lock); + spin_unlock_bh(&priv->tx.tx_lock); return ret; } @@ -257,7 +257,7 @@ void ath9k_tx_tasklet(unsigned long data) struct sk_buff *skb = NULL; __le16 fc; - while ((skb = skb_dequeue(&priv->tx_queue)) != NULL) { + while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { hdr = (struct ieee80211_hdr *) skb->data; fc = hdr->frame_control; @@ -292,9 +292,9 @@ void ath9k_tx_tasklet(unsigned long data) if (ath9k_htc_check_tx_aggr(priv, ista, tid)) { ieee80211_start_tx_ba_session(sta, tid, 0); - spin_lock_bh(&priv->tx_lock); + spin_lock_bh(&priv->tx.tx_lock); ista->tid_state[tid] = AGGR_PROGRESS; - spin_unlock_bh(&priv->tx_lock); + spin_unlock_bh(&priv->tx.tx_lock); } } } @@ -307,16 +307,16 @@ void ath9k_tx_tasklet(unsigned long data) } /* Wake TX queues if needed */ - spin_lock_bh(&priv->tx_lock); - if (priv->tx_queues_stop) { - priv->tx_queues_stop = false; - spin_unlock_bh(&priv->tx_lock); + spin_lock_bh(&priv->tx.tx_lock); + if (priv->tx.tx_queues_stop) { + priv->tx.tx_queues_stop = false; + spin_unlock_bh(&priv->tx.tx_lock); ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, "Waking up TX queues\n"); ieee80211_wake_queues(priv->hw); return; } - spin_unlock_bh(&priv->tx_lock); + spin_unlock_bh(&priv->tx.tx_lock); } void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, @@ -348,13 +348,13 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, if (txok) tx_info->flags |= IEEE80211_TX_STAT_ACK; - skb_queue_tail(&priv->tx_queue, skb); + skb_queue_tail(&priv->tx.tx_queue, skb); tasklet_schedule(&priv->tx_tasklet); } int ath9k_tx_init(struct ath9k_htc_priv *priv) { - skb_queue_head_init(&priv->tx_queue); + skb_queue_head_init(&priv->tx.tx_queue); return 0; } -- cgit v1.2.3-58-ga151 From 15f6d6d52fe0d9fcf8c09788caff5d1684e5f12c Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:25:06 +0530 Subject: ath9k_htc: Reduce TX queue size The current max queue length of 1024 is quite large and unnecessary. 256 suffices well enough even for high throughput situations. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 7b9d863d4035..f82b32bbf4e2 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -31,7 +31,7 @@ /* FIXME: Verify these numbers (with Windows) */ #define MAX_TX_URB_NUM 8 -#define MAX_TX_BUF_NUM 1024 +#define MAX_TX_BUF_NUM 256 #define MAX_TX_BUF_SIZE 32768 #define MAX_TX_AGGR_NUM 20 -- cgit v1.2.3-58-ga151 From e8e3860765641d5e9d1607ec50191cb33c28371d Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:25:12 +0530 Subject: ath9k_htc: Sync MGMT/DATA packet headers with firmware Add a new cookie field that would be filled by the host. This can be used to match the TX status WMI event with the appropriate packet. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 3af8a58d400f..3185fe7568cb 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -85,7 +85,8 @@ struct tx_frame_hdr { __be32 flags; /* ATH9K_HTC_TX_* */ u8 key_type; u8 keyix; - u8 reserved[26]; + u8 cookie; + u8 pad; } __packed; struct tx_mgmt_hdr { @@ -95,7 +96,8 @@ struct tx_mgmt_hdr { u8 flags; u8 key_type; u8 keyix; - u16 reserved; + u8 cookie; + u8 pad; } __packed; struct tx_beacon_header { -- cgit v1.2.3-58-ga151 From 16c56ae87509d9bbcd8c711dc4f99b38c234d6c5 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:25:18 +0530 Subject: ath9k_htc: Add a new WMI event WMI_TXSTATUS_EVENTID This event will be generated by the target for packet completions. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/wmi.h | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index a81d554edb8e..8c877dc2e2e0 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -41,6 +41,44 @@ struct wmi_event_swba { __be64 tsf; u8 beacon_pending; }; + +/* + * 64 - HTC header - WMI header - 1 / txstatus + * And some other hdr. space is also accounted for. + * 13 seems to be the magic number. + */ +#define HTC_MAX_TX_STATUS 13 + +#define ATH9K_HTC_TXSTAT_ACK BIT(0) +#define ATH9K_HTC_TXSTAT_FILT BIT(1) +#define ATH9K_HTC_TXSTAT_RTC_CTS BIT(2) +#define ATH9K_HTC_TXSTAT_MCS BIT(3) +#define ATH9K_HTC_TXSTAT_CW40 BIT(4) +#define ATH9K_HTC_TXSTAT_SGI BIT(5) + +/* + * Legacy rates are indicated as indices. + * HT rates are indicated as dot11 numbers. + * This allows us to resrict the rate field + * to 4 bits. + */ +#define ATH9K_HTC_TXSTAT_RATE 0x0f +#define ATH9K_HTC_TXSTAT_RATE_S 0 + +#define ATH9K_HTC_TXSTAT_EPID 0xf0 +#define ATH9K_HTC_TXSTAT_EPID_S 4 + +struct __wmi_event_txstatus { + u8 cookie; + u8 ts_rate; /* Also holds EP ID */ + u8 ts_flags; +}; + +struct wmi_event_txstatus { + u8 cnt; + struct __wmi_event_txstatus txstatus[HTC_MAX_TX_STATUS]; +} __packed; + enum wmi_cmd_id { WMI_ECHO_CMDID = 0x0001, WMI_ACCESS_MEMORY_CMDID, @@ -82,6 +120,7 @@ enum wmi_event_id { WMI_BMISS_EVENTID, WMI_DELBA_EVENTID, WMI_TXRATE_EVENTID, + WMI_TXSTATUS_EVENTID, }; #define MAX_CMD_NUMBER 62 -- cgit v1.2.3-58-ga151 From 3deff76095c4ac4252e27c537db3041f619c23a2 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:25:23 +0530 Subject: ath9k_htc: Increase URB count for REG_IN pipe Using a single URB for receiving WMI events is insufficient, increase it to 64 to not lose WMI events in high throughput situations. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 99 +++++++++++++++++++------------- drivers/net/wireless/ath/ath9k/hif_usb.h | 4 +- 2 files changed, 61 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index e252576760d1..0b63a48462c7 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -566,6 +566,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) case -ESHUTDOWN: goto free; default: + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); + goto resubmit; } @@ -590,23 +593,15 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) USB_REG_IN_PIPE), nskb->data, MAX_REG_IN_BUF_SIZE, ath9k_hif_usb_reg_in_cb, nskb); - - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) { - kfree_skb(nskb); - urb->context = NULL; - } - - return; } resubmit: - skb_reset_tail_pointer(skb); - skb_trim(skb, 0); - + usb_anchor_urb(urb, &hif_dev->reg_in_submitted); ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) + if (ret) { + usb_unanchor_urb(urb); goto free; + } return; free: @@ -747,43 +742,67 @@ err_urb: return ret; } -static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev) +static void ath9k_hif_usb_dealloc_reg_in_urbs(struct hif_device_usb *hif_dev) { - if (hif_dev->reg_in_urb) { - usb_kill_urb(hif_dev->reg_in_urb); - if (hif_dev->reg_in_urb->context) - kfree_skb((void *)hif_dev->reg_in_urb->context); - usb_free_urb(hif_dev->reg_in_urb); - hif_dev->reg_in_urb = NULL; - } + usb_kill_anchored_urbs(&hif_dev->reg_in_submitted); } -static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) +static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev) { - struct sk_buff *skb; + struct urb *urb = NULL; + struct sk_buff *skb = NULL; + int i, ret; - hif_dev->reg_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (hif_dev->reg_in_urb == NULL) - return -ENOMEM; + init_usb_anchor(&hif_dev->reg_in_submitted); - skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); - if (!skb) - goto err; + for (i = 0; i < MAX_REG_IN_URB_NUM; i++) { - usb_fill_bulk_urb(hif_dev->reg_in_urb, hif_dev->udev, - usb_rcvbulkpipe(hif_dev->udev, - USB_REG_IN_PIPE), - skb->data, MAX_REG_IN_BUF_SIZE, - ath9k_hif_usb_reg_in_cb, skb); + /* Allocate URB */ + urb = usb_alloc_urb(0, GFP_KERNEL); + if (urb == NULL) { + ret = -ENOMEM; + goto err_urb; + } - if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0) - goto err; + /* Allocate buffer */ + skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); + if (!skb) { + ret = -ENOMEM; + goto err_skb; + } + + usb_fill_bulk_urb(urb, hif_dev->udev, + usb_rcvbulkpipe(hif_dev->udev, + USB_REG_IN_PIPE), + skb->data, MAX_REG_IN_BUF_SIZE, + ath9k_hif_usb_reg_in_cb, skb); + + /* Anchor URB */ + usb_anchor_urb(urb, &hif_dev->reg_in_submitted); + + /* Submit URB */ + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + usb_unanchor_urb(urb); + goto err_submit; + } + + /* + * Drop reference count. + * This ensures that the URB is freed when killing them. + */ + usb_free_urb(urb); + } return 0; -err: - ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); - return -ENOMEM; +err_submit: + kfree_skb(skb); +err_skb: + usb_free_urb(urb); +err_urb: + ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev); + return ret; } static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) @@ -800,7 +819,7 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) goto err_rx; /* Register Read */ - if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0) + if (ath9k_hif_usb_alloc_reg_in_urbs(hif_dev) < 0) goto err_reg; return 0; @@ -815,7 +834,7 @@ err: static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) { usb_kill_anchored_urbs(&hif_dev->regout_submitted); - ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); + ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev); ath9k_hif_usb_dealloc_tx_urbs(hif_dev); ath9k_hif_usb_dealloc_rx_urbs(hif_dev); } diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index f82b32bbf4e2..8b98d646e91a 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -40,7 +40,7 @@ #define MAX_PKT_NUM_IN_TRANSFER 10 #define MAX_REG_OUT_URB_NUM 1 -#define MAX_REG_OUT_BUF_NUM 8 +#define MAX_REG_IN_URB_NUM 64 #define MAX_REG_IN_BUF_SIZE 64 @@ -90,9 +90,9 @@ struct hif_device_usb { const struct firmware *firmware; struct htc_target *htc_handle; struct hif_usb_tx tx; - struct urb *reg_in_urb; struct usb_anchor regout_submitted; struct usb_anchor rx_submitted; + struct usb_anchor reg_in_submitted; struct sk_buff *remain_skb; const char *fw_name; int rx_remain_len; -- cgit v1.2.3-58-ga151 From 8e86a54715c4102a8ed697939de9ebd9715dc59c Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:25:29 +0530 Subject: ath9k_htc: Fix TX queue management Handle queue start/stop properly by maintaining a counter to check if the pending frame count has exceeded the threshold. Otherwise, packets would be dropped needlessly. While at it, use a simple flag to track queue status and use helper functions too. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 13 +++++++-- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 4 +++ drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 21 +++++-------- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 39 ++++++++++++++++++------- 5 files changed, 52 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 3185fe7568cb..fc4c466e7563 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -262,11 +262,16 @@ struct ath9k_htc_rx { spinlock_t rxbuflock; }; -struct ath9k_htc_tx { - bool tx_queues_stop; - spinlock_t tx_lock; +#define ATH9K_HTC_TX_RESERVE 10 +#define ATH9K_HTC_TX_THRESHOLD (MAX_TX_BUF_NUM - ATH9K_HTC_TX_RESERVE) + +#define ATH9K_HTC_OP_TX_QUEUES_STOP BIT(0) +struct ath9k_htc_tx { + u8 flags; + int queued_cnt; struct sk_buff_head tx_queue; + spinlock_t tx_lock; }; struct ath9k_htc_tx_ctl { @@ -532,6 +537,8 @@ int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv); int get_hw_qnum(u16 queue, int *hwq_map); int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, struct ath9k_tx_queue_info *qinfo); +void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv); +void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv); int ath9k_rx_init(struct ath9k_htc_priv *priv); void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 713def184519..de37d46bb0d0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -326,6 +326,10 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, ath_dbg(common, ATH_DBG_FATAL, "Failed to send CAB frame\n"); dev_kfree_skb_any(skb); + } else { + spin_lock_bh(&priv->tx.tx_lock); + priv->tx.queued_cnt++; + spin_unlock_bh(&priv->tx.tx_lock); } next: skb = ieee80211_get_buffered_bc(priv->hw, vif); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 1f6df4a1d224..92e4b312a98b 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -399,7 +399,7 @@ void ath9k_htc_radio_enable(struct ieee80211_hw *hw) /* Start TX */ htc_start(priv->htc); spin_lock_bh(&priv->tx.tx_lock); - priv->tx.tx_queues_stop = false; + priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; spin_unlock_bh(&priv->tx.tx_lock); ieee80211_wake_queues(hw); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index ff3a49577a02..690113673d25 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -833,6 +833,7 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct ieee80211_hdr *hdr; struct ath9k_htc_priv *priv = hw->priv; + struct ath_common *common = ath9k_hw_common(priv->ah); int padpos, padsize, ret; hdr = (struct ieee80211_hdr *) skb->data; @@ -841,28 +842,22 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) padpos = ath9k_cmn_padpos(hdr->frame_control); padsize = padpos & 3; if (padsize && skb->len > padpos) { - if (skb_headroom(skb) < padsize) + if (skb_headroom(skb) < padsize) { + ath_dbg(common, ATH_DBG_XMIT, "No room for padding\n"); goto fail_tx; + } skb_push(skb, padsize); memmove(skb->data, skb->data + padsize, padpos); } ret = ath9k_htc_tx_start(priv, skb, false); if (ret != 0) { - if (ret == -ENOMEM) { - ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, - "Stopping TX queues\n"); - ieee80211_stop_queues(hw); - spin_lock_bh(&priv->tx.tx_lock); - priv->tx.tx_queues_stop = true; - spin_unlock_bh(&priv->tx.tx_lock); - } else { - ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, - "Tx failed\n"); - } + ath_dbg(common, ATH_DBG_XMIT, "Tx failed\n"); goto fail_tx; } + ath9k_htc_check_stop_queues(priv); + return; fail_tx: @@ -924,7 +919,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) htc_start(priv->htc); spin_lock_bh(&priv->tx.tx_lock); - priv->tx.tx_queues_stop = false; + priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; spin_unlock_bh(&priv->tx.tx_lock); ieee80211_wake_queues(hw); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 6f7987d7b6b0..1cbe194179ab 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -53,6 +53,29 @@ int get_hw_qnum(u16 queue, int *hwq_map) } } +void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv) +{ + spin_lock_bh(&priv->tx.tx_lock); + priv->tx.queued_cnt++; + if ((priv->tx.queued_cnt >= ATH9K_HTC_TX_THRESHOLD) && + !(priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) { + priv->tx.flags |= ATH9K_HTC_OP_TX_QUEUES_STOP; + ieee80211_stop_queues(priv->hw); + } + spin_unlock_bh(&priv->tx.tx_lock); +} + +void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv) +{ + spin_lock_bh(&priv->tx.tx_lock); + if ((priv->tx.queued_cnt < ATH9K_HTC_TX_THRESHOLD) && + (priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) { + priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; + ieee80211_wake_queues(priv->hw); + } + spin_unlock_bh(&priv->tx.tx_lock); +} + int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, struct ath9k_tx_queue_info *qinfo) { @@ -302,21 +325,17 @@ void ath9k_tx_tasklet(unsigned long data) rcu_read_unlock(); send_mac80211: + spin_lock_bh(&priv->tx.tx_lock); + if (WARN_ON(--priv->tx.queued_cnt < 0)) + priv->tx.queued_cnt = 0; + spin_unlock_bh(&priv->tx.tx_lock); + /* Send status to mac80211 */ ieee80211_tx_status(priv->hw, skb); } /* Wake TX queues if needed */ - spin_lock_bh(&priv->tx.tx_lock); - if (priv->tx.tx_queues_stop) { - priv->tx.tx_queues_stop = false; - spin_unlock_bh(&priv->tx.tx_lock); - ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, - "Waking up TX queues\n"); - ieee80211_wake_queues(priv->hw); - return; - } - spin_unlock_bh(&priv->tx.tx_lock); + ath9k_htc_check_wake_queues(priv); } void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, -- cgit v1.2.3-58-ga151 From d67ee5339363608adce786ec8fd62a0fb2b66116 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:25:35 +0530 Subject: ath9k_htc: Introduce new HTC API A new routine that takes an endpoint explicitly is introduced. The normal htc_send() now retrieves the endpoint from the packet's private data. This would be useful in TX completion when the endpoint ID would be required. While at it, use a helper function to map the queue to endpoint. Data/mgmt/beacon packets use htc_send(), while WMI comamnds pass the endpoint to HTC. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 3 +- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 56 ++++++++++++++----------- drivers/net/wireless/ath/ath9k/htc_hst.c | 12 +++++- drivers/net/wireless/ath/ath9k/htc_hst.h | 5 ++- drivers/net/wireless/ath/ath9k/wmi.c | 2 +- 6 files changed, 49 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index fc4c466e7563..356f49c180b3 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -276,6 +276,7 @@ struct ath9k_htc_tx { struct ath9k_htc_tx_ctl { u8 type; /* ATH9K_HTC_* */ + u8 epid; }; static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index de37d46bb0d0..97b116fb4e11 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -391,12 +391,13 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, memset(tx_ctl, 0, sizeof(*tx_ctl)); tx_ctl->type = ATH9K_HTC_BEACON; + tx_ctl->epid = priv->beacon_ep; beacon_hdr.vif_index = avp->index; tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); - ret = htc_send(priv->htc, beacon, priv->beacon_ep); + ret = htc_send(priv->htc, beacon); if (ret != 0) { if (ret == -ENOMEM) { ath_dbg(common, ATH_DBG_BSTUCK, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 1cbe194179ab..d17662fa604a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -76,6 +76,34 @@ void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv) spin_unlock_bh(&priv->tx.tx_lock); } +static enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, + u16 qnum) +{ + enum htc_endpoint_id epid; + + switch (qnum) { + case 0: + TX_QSTAT_INC(WME_AC_VO); + epid = priv->data_vo_ep; + break; + case 1: + TX_QSTAT_INC(WME_AC_VI); + epid = priv->data_vi_ep; + break; + case 2: + TX_QSTAT_INC(WME_AC_BE); + epid = priv->data_be_ep; + break; + case 3: + default: + TX_QSTAT_INC(WME_AC_BK); + epid = priv->data_bk_ep; + break; + } + + return epid; +} + int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, struct ath9k_tx_queue_info *qinfo) { @@ -113,7 +141,6 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct ath9k_htc_sta *ista; struct ath9k_htc_vif *avp = NULL; struct ath9k_htc_tx_ctl *tx_ctl; - enum htc_endpoint_id epid; u16 qnum; __le16 fc; u8 *tx_fhdr; @@ -197,31 +224,12 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, if (is_cab) { CAB_STAT_INC; - epid = priv->cab_ep; + tx_ctl->epid = priv->cab_ep; goto send; } qnum = skb_get_queue_mapping(skb); - - switch (qnum) { - case 0: - TX_QSTAT_INC(WME_AC_VO); - epid = priv->data_vo_ep; - break; - case 1: - TX_QSTAT_INC(WME_AC_VI); - epid = priv->data_vi_ep; - break; - case 2: - TX_QSTAT_INC(WME_AC_BE); - epid = priv->data_be_ep; - break; - case 3: - default: - TX_QSTAT_INC(WME_AC_BK); - epid = priv->data_bk_ep; - break; - } + tx_ctl->epid = get_htc_epid(priv, qnum); } else { struct tx_mgmt_hdr mgmt_hdr; @@ -251,10 +259,10 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); - epid = priv->mgmt_ep; + tx_ctl->epid = priv->mgmt_ep; } send: - return htc_send(priv->htc, skb, epid); + return htc_send(priv->htc, skb); } static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 6ee53de45c6a..be87f4757bf5 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -286,8 +286,16 @@ err: return ret; } -int htc_send(struct htc_target *target, struct sk_buff *skb, - enum htc_endpoint_id epid) +int htc_send(struct htc_target *target, struct sk_buff *skb) +{ + struct ath9k_htc_tx_ctl *tx_ctl; + + tx_ctl = HTC_SKB_CB(skb); + return htc_issue_send(target, skb, skb->len, 0, tx_ctl->epid); +} + +int htc_send_epid(struct htc_target *target, struct sk_buff *skb, + enum htc_endpoint_id epid) { return htc_issue_send(target, skb, skb->len, 0, epid); } diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index 3531552672e0..064a324b5228 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -204,8 +204,9 @@ int htc_init(struct htc_target *target); int htc_connect_service(struct htc_target *target, struct htc_service_connreq *service_connreq, enum htc_endpoint_id *conn_rsp_eid); -int htc_send(struct htc_target *target, struct sk_buff *skb, - enum htc_endpoint_id eid); +int htc_send(struct htc_target *target, struct sk_buff *skb); +int htc_send_epid(struct htc_target *target, struct sk_buff *skb, + enum htc_endpoint_id epid); void htc_stop(struct htc_target *target); void htc_start(struct htc_target *target); diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 83d1e0e5dd8c..e66f6c333028 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -267,7 +267,7 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi, hdr->command_id = cpu_to_be16(cmd); hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); - return htc_send(wmi->htc, skb, wmi->ctrl_epid); + return htc_send_epid(wmi->htc, skb, wmi->ctrl_epid); } int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, -- cgit v1.2.3-58-ga151 From 729bd3ab460d3bb8236cc8f6fd0289201124112d Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:25:41 +0530 Subject: ath9k_htc: Move endpoint header parsing to TX tasklet There is no need to do endpoint header removal in the ISR. Also, this is needed when TX slot management is added later on. Use a helper function to strip the driver header. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 68 ++++++++++++++++++--------- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 356f49c180b3..0831ca3de95c 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -277,6 +277,7 @@ struct ath9k_htc_tx { struct ath9k_htc_tx_ctl { u8 type; /* ATH9K_HTC_* */ u8 epid; + u8 txok; }; static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index d17662fa604a..7b218dad55d9 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -104,6 +104,30 @@ static enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, return epid; } +static inline int strip_drv_header(struct ath9k_htc_priv *priv, + struct sk_buff *skb) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_tx_ctl *tx_ctl; + + tx_ctl = HTC_SKB_CB(skb); + + if (tx_ctl->epid == priv->mgmt_ep) { + skb_pull(skb, sizeof(struct tx_mgmt_hdr)); + } else if ((tx_ctl->epid == priv->data_bk_ep) || + (tx_ctl->epid == priv->data_be_ep) || + (tx_ctl->epid == priv->data_vi_ep) || + (tx_ctl->epid == priv->data_vo_ep) || + (tx_ctl->epid == priv->cab_ep)) { + skb_pull(skb, sizeof(struct tx_frame_hdr)); + } else { + ath_err(common, "Unsupported EPID: %d\n", tx_ctl->epid); + return -EINVAL; + } + + return 0; +} + int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, struct ath9k_tx_queue_info *qinfo) { @@ -281,22 +305,40 @@ static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, void ath9k_tx_tasklet(unsigned long data) { struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; + struct ath9k_htc_tx_ctl *tx_ctl; struct ieee80211_vif *vif; struct ieee80211_sta *sta; struct ieee80211_hdr *hdr; struct ieee80211_tx_info *tx_info; struct sk_buff *skb = NULL; __le16 fc; + bool txok; while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { + if (strip_drv_header(priv, skb) < 0) { + dev_kfree_skb_any(skb); + continue; + } + + tx_ctl = HTC_SKB_CB(skb); hdr = (struct ieee80211_hdr *) skb->data; fc = hdr->frame_control; tx_info = IEEE80211_SKB_CB(skb); vif = tx_info->control.vif; + txok = tx_ctl->txok; memset(&tx_info->status, 0, sizeof(tx_info->status)); + /* + * URB submission failed for this frame, it never reached + * the target. + */ + if (!txok) + goto send_mac80211; + + tx_info->flags |= IEEE80211_TX_STAT_ACK; + if (!vif) goto send_mac80211; @@ -350,30 +392,10 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, bool txok) { struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ieee80211_tx_info *tx_info; - - if (!skb) - return; - - if (ep_id == priv->mgmt_ep) { - skb_pull(skb, sizeof(struct tx_mgmt_hdr)); - } else if ((ep_id == priv->data_bk_ep) || - (ep_id == priv->data_be_ep) || - (ep_id == priv->data_vi_ep) || - (ep_id == priv->data_vo_ep) || - (ep_id == priv->cab_ep)) { - skb_pull(skb, sizeof(struct tx_frame_hdr)); - } else { - ath_err(common, "Unsupported TX EPID: %d\n", ep_id); - dev_kfree_skb_any(skb); - return; - } - - tx_info = IEEE80211_SKB_CB(skb); + struct ath9k_htc_tx_ctl *tx_ctl; - if (txok) - tx_info->flags |= IEEE80211_TX_STAT_ACK; + tx_ctl = HTC_SKB_CB(skb); + tx_ctl->txok = txok; skb_queue_tail(&priv->tx.tx_queue, skb); tasklet_schedule(&priv->tx_tasklet); -- cgit v1.2.3-58-ga151 From 2c5d57f004673a9c8658e20b1fa3f992b5a10f70 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:25:47 +0530 Subject: ath9k_htc: Add TX slots Maintain a bitmap of slots for transmission and update the cookie field for every packet with the slot value. This value would be used for matching packets when TX completion processing is added. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 5 ++- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 17 +++++++-- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 14 +++++-- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 51 ++++++++++++++++++++++--- 4 files changed, 73 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 0831ca3de95c..45cf75579438 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -271,6 +271,7 @@ struct ath9k_htc_tx { u8 flags; int queued_cnt; struct sk_buff_head tx_queue; + DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM); spinlock_t tx_lock; }; @@ -532,7 +533,7 @@ void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv); int ath9k_tx_init(struct ath9k_htc_priv *priv); void ath9k_tx_tasklet(unsigned long data); int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, - struct sk_buff *skb, bool is_cab); + struct sk_buff *skb, u8 slot, bool is_cab); void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype); int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv); @@ -541,6 +542,8 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, struct ath9k_tx_queue_info *qinfo); void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv); void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv); +int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv); +void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot); int ath9k_rx_init(struct ath9k_htc_priv *priv); void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 97b116fb4e11..bf7ef1b7eb3f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -299,7 +299,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif; struct sk_buff *skb; struct ieee80211_hdr *hdr; - int padpos, padsize, ret; + int padpos, padsize, ret, tx_slot; spin_lock_bh(&priv->beacon_lock); @@ -321,11 +321,20 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, memmove(skb->data, skb->data + padsize, padpos); } - ret = ath9k_htc_tx_start(priv, skb, true); + tx_slot = ath9k_htc_tx_get_slot(priv); + if (tx_slot != 0) { + ath_dbg(common, ATH_DBG_XMIT, "No free CAB slot\n"); + dev_kfree_skb_any(skb); + goto next; + } + + ret = ath9k_htc_tx_start(priv, skb, tx_slot, true); if (ret != 0) { - ath_dbg(common, ATH_DBG_FATAL, - "Failed to send CAB frame\n"); + ath9k_htc_tx_clear_slot(priv, tx_slot); dev_kfree_skb_any(skb); + + ath_dbg(common, ATH_DBG_XMIT, + "Failed to send CAB frame\n"); } else { spin_lock_bh(&priv->tx.tx_lock); priv->tx.queued_cnt++; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 690113673d25..c7e056b40e1d 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -834,7 +834,7 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) struct ieee80211_hdr *hdr; struct ath9k_htc_priv *priv = hw->priv; struct ath_common *common = ath9k_hw_common(priv->ah); - int padpos, padsize, ret; + int padpos, padsize, ret, slot; hdr = (struct ieee80211_hdr *) skb->data; @@ -850,16 +850,24 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) memmove(skb->data, skb->data + padsize, padpos); } - ret = ath9k_htc_tx_start(priv, skb, false); + slot = ath9k_htc_tx_get_slot(priv); + if (slot < 0) { + ath_dbg(common, ATH_DBG_XMIT, "No free TX slot\n"); + goto fail_tx; + } + + ret = ath9k_htc_tx_start(priv, skb, slot, false); if (ret != 0) { ath_dbg(common, ATH_DBG_XMIT, "Tx failed\n"); - goto fail_tx; + goto clear_slot; } ath9k_htc_check_stop_queues(priv); return; +clear_slot: + ath9k_htc_tx_clear_slot(priv, slot); fail_tx: dev_kfree_skb_any(skb); } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 7b218dad55d9..ee5b3e281cd3 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -76,6 +76,29 @@ void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv) spin_unlock_bh(&priv->tx.tx_lock); } +int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv) +{ + int slot; + + spin_lock_bh(&priv->tx.tx_lock); + slot = find_first_zero_bit(priv->tx.tx_slot, MAX_TX_BUF_NUM); + if (slot >= MAX_TX_BUF_NUM) { + spin_unlock_bh(&priv->tx.tx_lock); + return -ENOBUFS; + } + __set_bit(slot, priv->tx.tx_slot); + spin_unlock_bh(&priv->tx.tx_lock); + + return slot; +} + +void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot) +{ + spin_lock_bh(&priv->tx.tx_lock); + __clear_bit(slot, priv->tx.tx_slot); + spin_unlock_bh(&priv->tx.tx_lock); +} + static enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, u16 qnum) { @@ -104,28 +127,38 @@ static enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, return epid; } +/* + * Removes the driver header and returns the TX slot number + */ static inline int strip_drv_header(struct ath9k_htc_priv *priv, struct sk_buff *skb) { struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_htc_tx_ctl *tx_ctl; + int slot; tx_ctl = HTC_SKB_CB(skb); if (tx_ctl->epid == priv->mgmt_ep) { + struct tx_mgmt_hdr *tx_mhdr = + (struct tx_mgmt_hdr *)skb->data; + slot = tx_mhdr->cookie; skb_pull(skb, sizeof(struct tx_mgmt_hdr)); } else if ((tx_ctl->epid == priv->data_bk_ep) || (tx_ctl->epid == priv->data_be_ep) || (tx_ctl->epid == priv->data_vi_ep) || (tx_ctl->epid == priv->data_vo_ep) || (tx_ctl->epid == priv->cab_ep)) { + struct tx_frame_hdr *tx_fhdr = + (struct tx_frame_hdr *)skb->data; + slot = tx_fhdr->cookie; skb_pull(skb, sizeof(struct tx_frame_hdr)); } else { ath_err(common, "Unsupported EPID: %d\n", tx_ctl->epid); - return -EINVAL; + slot = -EINVAL; } - return 0; + return slot; } int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, @@ -155,7 +188,8 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, } int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, - struct sk_buff *skb, bool is_cab) + struct sk_buff *skb, + u8 slot, bool is_cab) { struct ieee80211_hdr *hdr; struct ieee80211_mgmt *mgmt; @@ -212,6 +246,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, tx_hdr.node_idx = sta_idx; tx_hdr.vif_idx = vif_idx; + tx_hdr.cookie = slot; if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { tx_ctl->type = ATH9K_HTC_AMPDU; @@ -274,6 +309,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, mgmt_hdr.vif_idx = vif_idx; mgmt_hdr.tidno = 0; mgmt_hdr.flags = 0; + mgmt_hdr.cookie = slot; mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) @@ -313,10 +349,12 @@ void ath9k_tx_tasklet(unsigned long data) struct sk_buff *skb = NULL; __le16 fc; bool txok; + int slot; while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { - if (strip_drv_header(priv, skb) < 0) { + slot = strip_drv_header(priv, skb); + if (slot < 0) { dev_kfree_skb_any(skb); continue; } @@ -347,8 +385,7 @@ void ath9k_tx_tasklet(unsigned long data) sta = ieee80211_find_sta(vif, hdr->addr1); if (!sta) { rcu_read_unlock(); - ieee80211_tx_status(priv->hw, skb); - continue; + goto send_mac80211; } /* Check if we need to start aggregation */ @@ -380,6 +417,8 @@ void ath9k_tx_tasklet(unsigned long data) priv->tx.queued_cnt = 0; spin_unlock_bh(&priv->tx.tx_lock); + ath9k_htc_tx_clear_slot(priv, slot); + /* Send status to mac80211 */ ieee80211_tx_status(priv->hw, skb); } -- cgit v1.2.3-58-ga151 From f2820f4583b233827f10d91adea70225e196d852 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:25:54 +0530 Subject: ath9k_htc: Use helper functions for TX processing Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 137 ++++++++++++++------------ 1 file changed, 73 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index ee5b3e281cd3..944440c84c49 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -325,8 +325,8 @@ send: return htc_send(priv->htc, skb); } -static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, - struct ath9k_htc_sta *ista, u8 tid) +static inline bool __ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, + struct ath9k_htc_sta *ista, u8 tid) { bool ret = false; @@ -338,89 +338,98 @@ static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, return ret; } -void ath9k_tx_tasklet(unsigned long data) +static void ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif, + struct sk_buff *skb) { - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; - struct ath9k_htc_tx_ctl *tx_ctl; - struct ieee80211_vif *vif; struct ieee80211_sta *sta; struct ieee80211_hdr *hdr; - struct ieee80211_tx_info *tx_info; - struct sk_buff *skb = NULL; __le16 fc; - bool txok; - int slot; - while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { + hdr = (struct ieee80211_hdr *) skb->data; + fc = hdr->frame_control; - slot = strip_drv_header(priv, skb); - if (slot < 0) { - dev_kfree_skb_any(skb); - continue; - } + rcu_read_lock(); - tx_ctl = HTC_SKB_CB(skb); - hdr = (struct ieee80211_hdr *) skb->data; - fc = hdr->frame_control; - tx_info = IEEE80211_SKB_CB(skb); - vif = tx_info->control.vif; - txok = tx_ctl->txok; + sta = ieee80211_find_sta(vif, hdr->addr1); + if (!sta) { + rcu_read_unlock(); + return; + } - memset(&tx_info->status, 0, sizeof(tx_info->status)); + if (sta && conf_is_ht(&priv->hw->conf) && + !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { + if (ieee80211_is_data_qos(fc)) { + u8 *qc, tid; + struct ath9k_htc_sta *ista; - /* - * URB submission failed for this frame, it never reached - * the target. - */ - if (!txok) - goto send_mac80211; + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & 0xf; + ista = (struct ath9k_htc_sta *)sta->drv_priv; + if (__ath9k_htc_check_tx_aggr(priv, ista, tid)) { + ieee80211_start_tx_ba_session(sta, tid, 0); + spin_lock_bh(&priv->tx.tx_lock); + ista->tid_state[tid] = AGGR_PROGRESS; + spin_unlock_bh(&priv->tx.tx_lock); + } + } + } - tx_info->flags |= IEEE80211_TX_STAT_ACK; + rcu_read_unlock(); +} - if (!vif) - goto send_mac80211; +static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, + struct sk_buff *skb) +{ + struct ieee80211_vif *vif; + struct ath9k_htc_tx_ctl *tx_ctl; + struct ieee80211_tx_info *tx_info; + bool txok; + int slot; - rcu_read_lock(); + slot = strip_drv_header(priv, skb); + if (slot < 0) { + dev_kfree_skb_any(skb); + return; + } - sta = ieee80211_find_sta(vif, hdr->addr1); - if (!sta) { - rcu_read_unlock(); - goto send_mac80211; - } + tx_ctl = HTC_SKB_CB(skb); + txok = tx_ctl->txok; + tx_info = IEEE80211_SKB_CB(skb); + vif = tx_info->control.vif; - /* Check if we need to start aggregation */ + memset(&tx_info->status, 0, sizeof(tx_info->status)); - if (sta && conf_is_ht(&priv->hw->conf) && - !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { - if (ieee80211_is_data_qos(fc)) { - u8 *qc, tid; - struct ath9k_htc_sta *ista; + /* + * URB submission failed for this frame, it never reached + * the target. + */ + if (!txok || !vif) + goto send_mac80211; - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; - ista = (struct ath9k_htc_sta *)sta->drv_priv; + tx_info->flags |= IEEE80211_TX_STAT_ACK; - if (ath9k_htc_check_tx_aggr(priv, ista, tid)) { - ieee80211_start_tx_ba_session(sta, tid, 0); - spin_lock_bh(&priv->tx.tx_lock); - ista->tid_state[tid] = AGGR_PROGRESS; - spin_unlock_bh(&priv->tx.tx_lock); - } - } - } + ath9k_htc_check_tx_aggr(priv, vif, skb); - rcu_read_unlock(); +send_mac80211: + spin_lock_bh(&priv->tx.tx_lock); + if (WARN_ON(--priv->tx.queued_cnt < 0)) + priv->tx.queued_cnt = 0; + spin_unlock_bh(&priv->tx.tx_lock); - send_mac80211: - spin_lock_bh(&priv->tx.tx_lock); - if (WARN_ON(--priv->tx.queued_cnt < 0)) - priv->tx.queued_cnt = 0; - spin_unlock_bh(&priv->tx.tx_lock); + ath9k_htc_tx_clear_slot(priv, slot); + + /* Send status to mac80211 */ + ieee80211_tx_status(priv->hw, skb); +} - ath9k_htc_tx_clear_slot(priv, slot); +void ath9k_tx_tasklet(unsigned long data) +{ + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; + struct sk_buff *skb = NULL; - /* Send status to mac80211 */ - ieee80211_tx_status(priv->hw, skb); + while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { + ath9k_htc_tx_process(priv, skb); } /* Wake TX queues if needed */ -- cgit v1.2.3-58-ga151 From b587fc81a80b9656f64e89fe0a106ffa4b35abca Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:25:59 +0530 Subject: ath9k_htc: Drain pending TX frames properly When doing a channel set or a reset operation the pending frames queued up for transmission have to be flushed and sent to mac80211. Fixing this has to be done in two separate steps: * Flush queued frames and kill the URB TX completion handler. * Complete all the frames that in the TX pending queue. This patch adds proper support for draining and all the callsites namely, channel change/reset/idle/stop are fixed. A separate queue is used for handling failed frames. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 55 ++++++++++---------------- drivers/net/wireless/ath/ath9k/htc.h | 6 ++- drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 8 ++-- drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 3 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 15 ++++--- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 31 ++++++++++++++- 6 files changed, 69 insertions(+), 49 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 0b63a48462c7..db07e7b93204 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -131,7 +131,19 @@ static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, while ((skb = __skb_dequeue(list)) != NULL) { dev_kfree_skb_any(skb); - TX_STAT_INC(skb_dropped); + } +} + +static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev, + struct sk_buff_head *queue, + bool txok) +{ + struct sk_buff *skb; + + while ((skb = __skb_dequeue(queue)) != NULL) { + ath9k_htc_txcompletion_cb(hif_dev->htc_handle, + skb, txok); + (txok) ? TX_STAT_INC(skb_success) : TX_STAT_INC(skb_failed); } } @@ -139,7 +151,7 @@ static void hif_usb_tx_cb(struct urb *urb) { struct tx_buf *tx_buf = (struct tx_buf *) urb->context; struct hif_device_usb *hif_dev; - struct sk_buff *skb; + bool txok = true; if (!tx_buf || !tx_buf->hif_dev) return; @@ -153,10 +165,7 @@ static void hif_usb_tx_cb(struct urb *urb) case -ECONNRESET: case -ENODEV: case -ESHUTDOWN: - /* - * The URB has been killed, free the SKBs. - */ - ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); + txok = false; /* * If the URBs are being flushed, no need to add this @@ -165,41 +174,19 @@ static void hif_usb_tx_cb(struct urb *urb) spin_lock(&hif_dev->tx.tx_lock); if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { spin_unlock(&hif_dev->tx.tx_lock); + ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); return; } spin_unlock(&hif_dev->tx.tx_lock); - /* - * In the stop() case, this URB has to be added to - * the free list. - */ - goto add_free; + break; default: + txok = false; break; } - /* - * Check if TX has been stopped, this is needed because - * this CB could have been invoked just after the TX lock - * was released in hif_stop() and kill_urb() hasn't been - * called yet. - */ - spin_lock(&hif_dev->tx.tx_lock); - if (hif_dev->tx.flags & HIF_USB_TX_STOP) { - spin_unlock(&hif_dev->tx.tx_lock); - ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); - goto add_free; - } - spin_unlock(&hif_dev->tx.tx_lock); - - /* Complete the queued SKBs. */ - while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { - ath9k_htc_txcompletion_cb(hif_dev->htc_handle, - skb, 1); - TX_STAT_INC(skb_completed); - } + ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, txok); -add_free: /* Re-initialize the SKB queue */ tx_buf->len = tx_buf->offset = 0; __skb_queue_head_init(&tx_buf->skb_queue); @@ -272,7 +259,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); if (ret) { tx_buf->len = tx_buf->offset = 0; - ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); + ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, false); __skb_queue_head_init(&tx_buf->skb_queue); list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); hif_dev->tx.tx_buf_cnt++; @@ -342,7 +329,7 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id) unsigned long flags; spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - ath9k_skb_queue_purge(hif_dev, &hif_dev->tx.tx_skb_queue); + ath9k_skb_queue_complete(hif_dev, &hif_dev->tx.tx_skb_queue, false); hif_dev->tx.tx_skb_cnt = 0; hif_dev->tx.flags |= HIF_USB_TX_STOP; spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 45cf75579438..0d2e2b10358d 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -271,6 +271,7 @@ struct ath9k_htc_tx { u8 flags; int queued_cnt; struct sk_buff_head tx_queue; + struct sk_buff_head tx_failed; DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM); spinlock_t tx_lock; }; @@ -305,8 +306,8 @@ struct ath_tx_stats { u32 buf_queued; u32 buf_completed; u32 skb_queued; - u32 skb_completed; - u32 skb_dropped; + u32 skb_success; + u32 skb_failed; u32 cab_queued; u32 queue_stats[WME_NUM_AC]; }; @@ -544,6 +545,7 @@ void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv); void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv); int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv); void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot); +void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv); int ath9k_rx_init(struct ath9k_htc_priv *priv); void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 6fc6cb749362..91a486cca32a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -88,11 +88,11 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, "%20s : %10u\n", "SKBs queued", priv->debug.tx_stats.skb_queued); len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs completed", - priv->debug.tx_stats.skb_completed); + "%20s : %10u\n", "SKBs success", + priv->debug.tx_stats.skb_success); len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs dropped", - priv->debug.tx_stats.skb_dropped); + "%20s : %10u\n", "SKBs failed", + priv->debug.tx_stats.skb_failed); len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "CAB queued", priv->debug.tx_stats.cab_queued); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 92e4b312a98b..dc0b33d01210 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -429,9 +429,8 @@ void ath9k_htc_radio_disable(struct ieee80211_hw *hw) /* Stop TX */ ieee80211_stop_queues(hw); - htc_stop(priv->htc); + ath9k_htc_tx_drain(priv); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); - skb_queue_purge(&priv->tx.tx_queue); /* Stop RX */ WMI_CMD(WMI_STOP_RECV_CMDID); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index c7e056b40e1d..fb9ff1188a0a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -193,7 +193,9 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) ath9k_htc_stop_ani(priv); ieee80211_stop_queues(priv->hw); - htc_stop(priv->htc); + + ath9k_htc_tx_drain(priv); + WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); @@ -248,7 +250,9 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); ath9k_htc_ps_wakeup(priv); - htc_stop(priv->htc); + + ath9k_htc_tx_drain(priv); + WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); @@ -263,6 +267,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, if (!fastcc) caldata = &priv->caldata; + ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); if (ret) { ath_err(common, @@ -960,16 +965,14 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) } ath9k_htc_ps_wakeup(priv); - htc_stop(priv->htc); + WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); tasklet_kill(&priv->rx_tasklet); - tasklet_kill(&priv->tx_tasklet); - - skb_queue_purge(&priv->tx.tx_queue); + ath9k_htc_tx_drain(priv); ath9k_wmi_event_drain(priv); mutex_unlock(&priv->mutex); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 944440c84c49..9e0c34b0a794 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -423,6 +423,26 @@ send_mac80211: ieee80211_tx_status(priv->hw, skb); } +void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv) +{ + struct sk_buff *skb = NULL; + + /* + * Ensure that all pending TX frames are flushed, + * and that the TX completion tasklet is killed. + */ + htc_stop(priv->htc); + tasklet_kill(&priv->tx_tasklet); + + while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { + ath9k_htc_tx_process(priv, skb); + } + + while ((skb = skb_dequeue(&priv->tx.tx_failed)) != NULL) { + ath9k_htc_tx_process(priv, skb); + } +} + void ath9k_tx_tasklet(unsigned long data) { struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; @@ -432,6 +452,10 @@ void ath9k_tx_tasklet(unsigned long data) ath9k_htc_tx_process(priv, skb); } + while ((skb = skb_dequeue(&priv->tx.tx_failed)) != NULL) { + ath9k_htc_tx_process(priv, skb); + } + /* Wake TX queues if needed */ ath9k_htc_check_wake_queues(priv); } @@ -445,13 +469,18 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, tx_ctl = HTC_SKB_CB(skb); tx_ctl->txok = txok; - skb_queue_tail(&priv->tx.tx_queue, skb); + if (txok) + skb_queue_tail(&priv->tx.tx_queue, skb); + else + skb_queue_tail(&priv->tx.tx_failed, skb); + tasklet_schedule(&priv->tx_tasklet); } int ath9k_tx_init(struct ath9k_htc_priv *priv) { skb_queue_head_init(&priv->tx.tx_queue); + skb_queue_head_init(&priv->tx.tx_failed); return 0; } -- cgit v1.2.3-58-ga151 From e1fe7c38d39f8f6ebdffc3a55e2ec6e2ec0d1872 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:26:06 +0530 Subject: ath9k_htc: Optimize HTC start/stop API There is no point in looping over all the endpoints, since the HIF layer uses the start/stop APIs only for the TX pipe. Simplify the API accordingly. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 4 ++-- drivers/net/wireless/ath/ath9k/htc_hst.c | 19 ++----------------- drivers/net/wireless/ath/ath9k/htc_hst.h | 4 ++-- 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index db07e7b93204..b3f23c2be738 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -310,7 +310,7 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb) return 0; } -static void hif_usb_start(void *hif_handle, u8 pipe_id) +static void hif_usb_start(void *hif_handle) { struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; unsigned long flags; @@ -322,7 +322,7 @@ static void hif_usb_start(void *hif_handle, u8 pipe_id) spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); } -static void hif_usb_stop(void *hif_handle, u8 pipe_id) +static void hif_usb_stop(void *hif_handle) { struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index be87f4757bf5..7ced8ab1ae4c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -302,27 +302,12 @@ int htc_send_epid(struct htc_target *target, struct sk_buff *skb, void htc_stop(struct htc_target *target) { - enum htc_endpoint_id epid; - struct htc_endpoint *endpoint; - - for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { - endpoint = &target->endpoint[epid]; - if (endpoint->service_id != 0) - target->hif->stop(target->hif_dev, endpoint->ul_pipeid); - } + target->hif->stop(target->hif_dev); } void htc_start(struct htc_target *target) { - enum htc_endpoint_id epid; - struct htc_endpoint *endpoint; - - for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { - endpoint = &target->endpoint[epid]; - if (endpoint->service_id != 0) - target->hif->start(target->hif_dev, - endpoint->ul_pipeid); - } + target->hif->start(target->hif_dev); } void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index 064a324b5228..191e3c0837a6 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -33,8 +33,8 @@ struct ath9k_htc_hif { u8 control_dl_pipe; u8 control_ul_pipe; - void (*start) (void *hif_handle, u8 pipe); - void (*stop) (void *hif_handle, u8 pipe); + void (*start) (void *hif_handle); + void (*stop) (void *hif_handle); int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf); }; -- cgit v1.2.3-58-ga151 From 84c9e164468bd707e52b440e1c34bc3c85299332 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:26:11 +0530 Subject: ath9k_htc: Drain packets on station removal When a station entry is removed, there could still be pending packets destined for that station in the HIF layer. Sending these to the target is not necessary, so drain them in the driver itself. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 35 +++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/htc.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_main.c | 3 +++ drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8 ++++++ drivers/net/wireless/ath/ath9k/htc_hst.c | 5 ++++ drivers/net/wireless/ath/ath9k/htc_hst.h | 2 ++ 6 files changed, 54 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index b3f23c2be738..7fae79d16665 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -363,6 +363,40 @@ static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb) return ret; } +static inline bool check_index(struct sk_buff *skb, u8 idx) +{ + struct ath9k_htc_tx_ctl *tx_ctl; + + tx_ctl = HTC_SKB_CB(skb); + + if ((tx_ctl->type == ATH9K_HTC_AMPDU) && + (tx_ctl->sta_idx == idx)) + return true; + + return false; +} + +static void hif_usb_sta_drain(void *hif_handle, u8 idx) +{ + struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; + struct sk_buff *skb, *tmp; + unsigned long flags; + + spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + + skb_queue_walk_safe(&hif_dev->tx.tx_skb_queue, skb, tmp) { + if (check_index(skb, idx)) { + __skb_unlink(skb, &hif_dev->tx.tx_skb_queue); + ath9k_htc_txcompletion_cb(hif_dev->htc_handle, + skb, false); + hif_dev->tx.tx_skb_cnt--; + TX_STAT_INC(skb_failed); + } + } + + spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); +} + static struct ath9k_htc_hif hif_usb = { .transport = ATH9K_HIF_USB, .name = "ath9k_hif_usb", @@ -372,6 +406,7 @@ static struct ath9k_htc_hif hif_usb = { .start = hif_usb_start, .stop = hif_usb_stop, + .sta_drain = hif_usb_sta_drain, .send = hif_usb_send, }; diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 0d2e2b10358d..41823fd6d9ad 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -280,6 +280,7 @@ struct ath9k_htc_tx_ctl { u8 type; /* ATH9K_HTC_* */ u8 epid; u8 txok; + u8 sta_idx; }; static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index fb9ff1188a0a..ae85cc4373f0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1303,10 +1303,13 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct ath9k_htc_priv *priv = hw->priv; + struct ath9k_htc_sta *ista; int ret; mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); + ista = (struct ath9k_htc_sta *) sta->drv_priv; + htc_sta_drain(priv->htc, ista->index); ret = ath9k_htc_remove_station(priv, vif, sta); ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 9e0c34b0a794..0790070a7f63 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -248,6 +248,14 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, tx_hdr.vif_idx = vif_idx; tx_hdr.cookie = slot; + /* + * This is a bit redundant but it helps to get + * the per-packet index quickly when draining the + * TX queue in the HIF layer. Otherwise we would + * have to parse the packet contents ... + */ + tx_ctl->sta_idx = sta_idx; + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { tx_ctl->type = ATH9K_HTC_AMPDU; tx_hdr.data_type = ATH9K_HTC_AMPDU; diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 7ced8ab1ae4c..5c76352b1319 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -310,6 +310,11 @@ void htc_start(struct htc_target *target) target->hif->start(target->hif_dev); } +void htc_sta_drain(struct htc_target *target, u8 idx) +{ + target->hif->sta_drain(target->hif_dev, idx); +} + void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, struct sk_buff *skb, bool txok) { diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index 191e3c0837a6..cb9174ade53e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -35,6 +35,7 @@ struct ath9k_htc_hif { void (*start) (void *hif_handle); void (*stop) (void *hif_handle); + void (*sta_drain) (void *hif_handle, u8 idx); int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf); }; @@ -209,6 +210,7 @@ int htc_send_epid(struct htc_target *target, struct sk_buff *skb, enum htc_endpoint_id epid); void htc_stop(struct htc_target *target); void htc_start(struct htc_target *target); +void htc_sta_drain(struct htc_target *target, u8 idx); void ath9k_htc_rx_msg(struct htc_target *htc_handle, struct sk_buff *skb, u32 len, u8 pipe_id); -- cgit v1.2.3-58-ga151 From 27876a29de221186c9d5883e5fe5f6da18ef9a45 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:26:18 +0530 Subject: ath9k_htc: Add support for TX completion Now that the infrastructure is in place, process WMI TX status events and complete packets. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 14 +- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 208 ++++++++++++++++++++++---- drivers/net/wireless/ath/ath9k/wmi.c | 10 ++ drivers/net/wireless/ath/ath9k/wmi.h | 4 +- 5 files changed, 207 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 41823fd6d9ad..6c103edf890a 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -266,11 +266,17 @@ struct ath9k_htc_rx { #define ATH9K_HTC_TX_THRESHOLD (MAX_TX_BUF_NUM - ATH9K_HTC_TX_RESERVE) #define ATH9K_HTC_OP_TX_QUEUES_STOP BIT(0) +#define ATH9K_HTC_OP_TX_DRAIN BIT(1) struct ath9k_htc_tx { u8 flags; int queued_cnt; - struct sk_buff_head tx_queue; + struct sk_buff_head mgmt_ep_queue; + struct sk_buff_head cab_ep_queue; + struct sk_buff_head data_be_queue; + struct sk_buff_head data_bk_queue; + struct sk_buff_head data_vi_queue; + struct sk_buff_head data_vo_queue; struct sk_buff_head tx_failed; DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM); spinlock_t tx_lock; @@ -465,8 +471,8 @@ struct ath9k_htc_priv { struct tasklet_struct swba_tasklet; struct tasklet_struct rx_tasklet; - struct tasklet_struct tx_tasklet; struct delayed_work ani_work; + struct tasklet_struct tx_failed_tasklet; struct work_struct ps_work; struct work_struct fatal_work; @@ -533,7 +539,6 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv); void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv); int ath9k_tx_init(struct ath9k_htc_priv *priv); -void ath9k_tx_tasklet(unsigned long data); int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb, u8 slot, bool is_cab); void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); @@ -547,6 +552,9 @@ void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv); int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv); void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot); void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv); +void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event); +void ath9k_htc_tx_failed(struct ath9k_htc_priv *priv); +void ath9k_tx_failed_tasklet(unsigned long data); int ath9k_rx_init(struct ath9k_htc_priv *priv); void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index c270da7be10f..afceeaa6b916 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -678,7 +678,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, mutex_init(&priv->htc_pm_lock); tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, (unsigned long)priv); - tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, + tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet, (unsigned long)priv); INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work); INIT_WORK(&priv->ps_work, ath9k_ps_work); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 0790070a7f63..a9b6bb1ef287 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -99,8 +99,8 @@ void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot) spin_unlock_bh(&priv->tx.tx_lock); } -static enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, - u16 qnum) +static inline enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, + u16 qnum) { enum htc_endpoint_id epid; @@ -127,6 +127,30 @@ static enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, return epid; } +static inline struct sk_buff_head* +get_htc_epid_queue(struct ath9k_htc_priv *priv, u8 epid) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct sk_buff_head *epid_queue = NULL; + + if (epid == priv->mgmt_ep) + epid_queue = &priv->tx.mgmt_ep_queue; + else if (epid == priv->cab_ep) + epid_queue = &priv->tx.cab_ep_queue; + else if (epid == priv->data_be_ep) + epid_queue = &priv->tx.data_be_queue; + else if (epid == priv->data_bk_ep) + epid_queue = &priv->tx.data_bk_queue; + else if (epid == priv->data_vi_ep) + epid_queue = &priv->tx.data_vi_queue; + else if (epid == priv->data_vo_ep) + epid_queue = &priv->tx.data_vo_queue; + else + ath_err(common, "Invalid EPID: %d\n", epid); + + return epid_queue; +} + /* * Removes the driver header and returns the TX slot number */ @@ -387,11 +411,15 @@ static void ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, } static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, - struct sk_buff *skb) + struct sk_buff *skb, + struct __wmi_event_txstatus *txs) { struct ieee80211_vif *vif; struct ath9k_htc_tx_ctl *tx_ctl; struct ieee80211_tx_info *tx_info; + struct ieee80211_tx_rate *rate; + struct ieee80211_conf *cur_conf = &priv->hw->conf; + struct ieee80211_supported_band *sband; bool txok; int slot; @@ -405,6 +433,8 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, txok = tx_ctl->txok; tx_info = IEEE80211_SKB_CB(skb); vif = tx_info->control.vif; + rate = &tx_info->status.rates[0]; + sband = priv->hw->wiphy->bands[cur_conf->channel->band]; memset(&tx_info->status, 0, sizeof(tx_info->status)); @@ -412,10 +442,32 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, * URB submission failed for this frame, it never reached * the target. */ - if (!txok || !vif) + if (!txok || !vif || !txs) goto send_mac80211; - tx_info->flags |= IEEE80211_TX_STAT_ACK; + if (txs->ts_flags & ATH9K_HTC_TXSTAT_ACK) + tx_info->flags |= IEEE80211_TX_STAT_ACK; + + if (txs->ts_flags & ATH9K_HTC_TXSTAT_FILT) + tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; + + if (txs->ts_flags & ATH9K_HTC_TXSTAT_RTC_CTS) + rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; + + rate->count = 1; + rate->idx = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_RATE); + + if (txs->ts_flags & ATH9K_HTC_TXSTAT_MCS) { + rate->flags |= IEEE80211_TX_RC_MCS; + + if (txs->ts_flags & ATH9K_HTC_TXSTAT_CW40) + rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + if (txs->ts_flags & ATH9K_HTC_TXSTAT_SGI) + rate->flags |= IEEE80211_TX_RC_SHORT_GI; + } else { + if (cur_conf->channel->band == IEEE80211_BAND_5GHZ) + rate->idx += 4; /* No CCK rates */ + } ath9k_htc_check_tx_aggr(priv, vif, skb); @@ -431,37 +483,130 @@ send_mac80211: ieee80211_tx_status(priv->hw, skb); } +static inline void ath9k_htc_tx_drainq(struct ath9k_htc_priv *priv, + struct sk_buff_head *queue) +{ + struct sk_buff *skb; + + while ((skb = skb_dequeue(queue)) != NULL) { + ath9k_htc_tx_process(priv, skb, NULL); + } +} + void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv) { - struct sk_buff *skb = NULL; + spin_lock_bh(&priv->tx.tx_lock); + priv->tx.flags |= ATH9K_HTC_OP_TX_DRAIN; + spin_unlock_bh(&priv->tx.tx_lock); /* * Ensure that all pending TX frames are flushed, - * and that the TX completion tasklet is killed. + * and that the TX completion/failed tasklets is killed. */ htc_stop(priv->htc); - tasklet_kill(&priv->tx_tasklet); + tasklet_kill(&priv->wmi->wmi_event_tasklet); + tasklet_kill(&priv->tx_failed_tasklet); - while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { - ath9k_htc_tx_process(priv, skb); - } + ath9k_htc_tx_drainq(priv, &priv->tx.mgmt_ep_queue); + ath9k_htc_tx_drainq(priv, &priv->tx.cab_ep_queue); + ath9k_htc_tx_drainq(priv, &priv->tx.data_be_queue); + ath9k_htc_tx_drainq(priv, &priv->tx.data_bk_queue); + ath9k_htc_tx_drainq(priv, &priv->tx.data_vi_queue); + ath9k_htc_tx_drainq(priv, &priv->tx.data_vo_queue); + ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed); - while ((skb = skb_dequeue(&priv->tx.tx_failed)) != NULL) { - ath9k_htc_tx_process(priv, skb); - } + spin_lock_bh(&priv->tx.tx_lock); + priv->tx.flags &= ~ATH9K_HTC_OP_TX_DRAIN; + spin_unlock_bh(&priv->tx.tx_lock); } -void ath9k_tx_tasklet(unsigned long data) +void ath9k_tx_failed_tasklet(unsigned long data) { struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; - struct sk_buff *skb = NULL; - while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { - ath9k_htc_tx_process(priv, skb); + spin_lock_bh(&priv->tx.tx_lock); + if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { + spin_unlock_bh(&priv->tx.tx_lock); + return; } + spin_unlock_bh(&priv->tx.tx_lock); - while ((skb = skb_dequeue(&priv->tx.tx_failed)) != NULL) { - ath9k_htc_tx_process(priv, skb); + ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed); +} + +static inline bool check_cookie(struct ath9k_htc_priv *priv, + struct sk_buff *skb, + u8 cookie, u8 epid) +{ + u8 fcookie = 0; + + if (epid == priv->mgmt_ep) { + struct tx_mgmt_hdr *hdr; + hdr = (struct tx_mgmt_hdr *) skb->data; + fcookie = hdr->cookie; + } else if ((epid == priv->data_bk_ep) || + (epid == priv->data_be_ep) || + (epid == priv->data_vi_ep) || + (epid == priv->data_vo_ep) || + (epid == priv->cab_ep)) { + struct tx_frame_hdr *hdr; + hdr = (struct tx_frame_hdr *) skb->data; + fcookie = hdr->cookie; + } + + if (fcookie == cookie) + return true; + + return false; +} + +static struct sk_buff* ath9k_htc_tx_get_packet(struct ath9k_htc_priv *priv, + struct __wmi_event_txstatus *txs) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct sk_buff_head *epid_queue; + struct sk_buff *skb, *tmp; + unsigned long flags; + u8 epid = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_EPID); + + epid_queue = get_htc_epid_queue(priv, epid); + if (!epid_queue) + return NULL; + + spin_lock_irqsave(&epid_queue->lock, flags); + skb_queue_walk_safe(epid_queue, skb, tmp) { + if (check_cookie(priv, skb, txs->cookie, epid)) { + __skb_unlink(skb, epid_queue); + spin_unlock_irqrestore(&epid_queue->lock, flags); + return skb; + } + } + spin_unlock_irqrestore(&epid_queue->lock, flags); + + ath_dbg(common, ATH_DBG_XMIT, + "No matching packet for cookie: %d, epid: %d\n", + txs->cookie, epid); + + return NULL; +} + +void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event) +{ + struct wmi_event_txstatus *txs = (struct wmi_event_txstatus *)wmi_event; + struct __wmi_event_txstatus *__txs; + struct sk_buff *skb; + int i; + + for (i = 0; i < txs->cnt; i++) { + WARN_ON(txs->cnt > HTC_MAX_TX_STATUS); + + __txs = &txs->txstatus[i]; + + skb = ath9k_htc_tx_get_packet(priv, __txs); + if (!skb) + continue; + + ath9k_htc_tx_process(priv, skb, __txs); } /* Wake TX queues if needed */ @@ -473,21 +618,34 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, { struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; struct ath9k_htc_tx_ctl *tx_ctl; + struct sk_buff_head *epid_queue; tx_ctl = HTC_SKB_CB(skb); tx_ctl->txok = txok; - if (txok) - skb_queue_tail(&priv->tx.tx_queue, skb); - else + if (!txok) { skb_queue_tail(&priv->tx.tx_failed, skb); + tasklet_schedule(&priv->tx_failed_tasklet); + return; + } + + epid_queue = get_htc_epid_queue(priv, ep_id); + if (!epid_queue) { + dev_kfree_skb_any(skb); + return; + } - tasklet_schedule(&priv->tx_tasklet); + skb_queue_tail(epid_queue, skb); } int ath9k_tx_init(struct ath9k_htc_priv *priv) { - skb_queue_head_init(&priv->tx.tx_queue); + skb_queue_head_init(&priv->tx.mgmt_ep_queue); + skb_queue_head_init(&priv->tx.cab_ep_queue); + skb_queue_head_init(&priv->tx.data_be_queue); + skb_queue_head_init(&priv->tx.data_bk_queue); + skb_queue_head_init(&priv->tx.data_vi_queue); + skb_queue_head_init(&priv->tx.data_vo_queue); skb_queue_head_init(&priv->tx.tx_failed); return 0; } diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index e66f6c333028..3f5a4d1fe077 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -163,6 +163,16 @@ void ath9k_wmi_event_tasklet(unsigned long data) wmi->drv_priv->debug.txrate = be32_to_cpu(txrate); #endif break; + case WMI_TXSTATUS_EVENTID: + spin_lock_bh(&priv->tx.tx_lock); + if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { + spin_unlock_bh(&priv->tx.tx_lock); + break; + } + spin_unlock_bh(&priv->tx.tx_lock); + + ath9k_htc_txstatus(priv, wmi_event); + break; default: break; } diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 8c877dc2e2e0..44b17385374f 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -45,9 +45,9 @@ struct wmi_event_swba { /* * 64 - HTC header - WMI header - 1 / txstatus * And some other hdr. space is also accounted for. - * 13 seems to be the magic number. + * 12 seems to be the magic number. */ -#define HTC_MAX_TX_STATUS 13 +#define HTC_MAX_TX_STATUS 12 #define ATH9K_HTC_TXSTAT_ACK BIT(0) #define ATH9K_HTC_TXSTAT_FILT BIT(1) -- cgit v1.2.3-58-ga151 From 01f684de7cc0641a9ee968f2d2c45c3a67241252 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:26:26 +0530 Subject: ath9k_htc: Add a debugfs file to dump TX slot information Location: ath9k_htc/phy#/slot Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 42 ++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 6c103edf890a..b9c7bec9dd45 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -338,6 +338,7 @@ struct ath9k_debug { struct dentry *debugfs_tgt_stats; struct dentry *debugfs_xmit; struct dentry *debugfs_recv; + struct dentry *debugfs_slot; struct ath_tx_stats tx_stats; struct ath_rx_stats rx_stats; u32 txrate; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 91a486cca32a..119cc544cea0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -244,6 +244,41 @@ static const struct file_operations fops_recv = { .llseek = default_llseek, }; +static ssize_t read_file_slot(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + char buf[512]; + unsigned int len = 0; + + spin_lock_bh(&priv->tx.tx_lock); + + len += snprintf(buf + len, sizeof(buf) - len, "TX slot bitmap : "); + + len += bitmap_scnprintf(buf + len, sizeof(buf) - len, + priv->tx.tx_slot, MAX_TX_BUF_NUM); + + len += snprintf(buf + len, sizeof(buf) - len, "\n"); + + len += snprintf(buf + len, sizeof(buf) - len, + "Used slots : %d\n", + bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM)); + + spin_unlock_bh(&priv->tx.tx_lock); + + if (len > sizeof(buf)) + len = sizeof(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_slot = { + .read = read_file_slot, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + int ath9k_htc_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -276,6 +311,12 @@ int ath9k_htc_init_debug(struct ath_hw *ah) if (!priv->debug.debugfs_recv) goto err; + priv->debug.debugfs_slot = debugfs_create_file("slot", S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_slot); + if (!priv->debug.debugfs_slot) + goto err; + return 0; err: @@ -288,6 +329,7 @@ void ath9k_htc_exit_debug(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + debugfs_remove(priv->debug.debugfs_slot); debugfs_remove(priv->debug.debugfs_recv); debugfs_remove(priv->debug.debugfs_xmit); debugfs_remove(priv->debug.debugfs_tgt_stats); -- cgit v1.2.3-58-ga151 From c4d04186c7023d54445b695da226b3e98e0a55f9 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:26:31 +0530 Subject: ath9k_htc: Add a debugfs file showing endpoint status Location: ath9k_htc/phy#/queue Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 54 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index b9c7bec9dd45..b40753ca6706 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -339,6 +339,7 @@ struct ath9k_debug { struct dentry *debugfs_xmit; struct dentry *debugfs_recv; struct dentry *debugfs_slot; + struct dentry *debugfs_queue; struct ath_tx_stats tx_stats; struct ath_rx_stats rx_stats; u32 txrate; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 119cc544cea0..961bec20d140 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -279,6 +279,53 @@ static const struct file_operations fops_slot = { .llseek = default_llseek, }; +static ssize_t read_file_queue(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + char buf[512]; + unsigned int len = 0; + + len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + "Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue)); + + len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + "Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue)); + + len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + "Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue)); + + len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + "Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue)); + + len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + "Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue)); + + len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + "Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue)); + + len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + "Failed queue", skb_queue_len(&priv->tx.tx_failed)); + + spin_lock_bh(&priv->tx.tx_lock); + len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + "Queued count", priv->tx.queued_cnt); + spin_unlock_bh(&priv->tx.tx_lock); + + if (len > sizeof(buf)) + len = sizeof(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); + +} + +static const struct file_operations fops_queue = { + .read = read_file_queue, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + int ath9k_htc_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -317,6 +364,12 @@ int ath9k_htc_init_debug(struct ath_hw *ah) if (!priv->debug.debugfs_slot) goto err; + priv->debug.debugfs_queue = debugfs_create_file("queue", S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_queue); + if (!priv->debug.debugfs_queue) + goto err; + return 0; err: @@ -329,6 +382,7 @@ void ath9k_htc_exit_debug(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + debugfs_remove(priv->debug.debugfs_queue); debugfs_remove(priv->debug.debugfs_slot); debugfs_remove(priv->debug.debugfs_recv); debugfs_remove(priv->debug.debugfs_xmit); -- cgit v1.2.3-58-ga151 From 859c3ca1e4608615788dc6cbc199210fe4b5efa2 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:26:39 +0530 Subject: ath9k_htc: Add a timer to cleanup WMI events Occasionally, a WMI event would arrive ahead of the TX URB completion handler. Discarding these events would exhaust the available TX slots, so handle them by running a timer cleaning up such events. Also, timeout packets for which TX completion events have not arrived. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 8 +- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 3 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 12 +++ drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 127 +++++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/wmi.c | 3 + drivers/net/wireless/ath/ath9k/wmi.h | 9 ++ 6 files changed, 159 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index b40753ca6706..b413b46119b0 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -262,7 +262,10 @@ struct ath9k_htc_rx { spinlock_t rxbuflock; }; -#define ATH9K_HTC_TX_RESERVE 10 +#define ATH9K_HTC_TX_CLEANUP_INTERVAL 50 /* ms */ +#define ATH9K_HTC_TX_TIMEOUT_INTERVAL 2500 /* ms */ +#define ATH9K_HTC_TX_RESERVE 10 +#define ATH9K_HTC_TX_TIMEOUT_COUNT 20 #define ATH9K_HTC_TX_THRESHOLD (MAX_TX_BUF_NUM - ATH9K_HTC_TX_RESERVE) #define ATH9K_HTC_OP_TX_QUEUES_STOP BIT(0) @@ -279,6 +282,7 @@ struct ath9k_htc_tx { struct sk_buff_head data_vo_queue; struct sk_buff_head tx_failed; DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM); + struct timer_list cleanup_timer; spinlock_t tx_lock; }; @@ -287,6 +291,7 @@ struct ath9k_htc_tx_ctl { u8 epid; u8 txok; u8 sta_idx; + unsigned long timestamp; }; static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) @@ -557,6 +562,7 @@ void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv); void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event); void ath9k_htc_tx_failed(struct ath9k_htc_priv *priv); void ath9k_tx_failed_tasklet(unsigned long data); +void ath9k_htc_tx_cleanup_timer(unsigned long data); int ath9k_rx_init(struct ath9k_htc_priv *priv); void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index afceeaa6b916..0aec25920c0a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -671,7 +671,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, common->priv = priv; common->debug_mask = ath9k_debug; - spin_lock_init(&priv->wmi->wmi_lock); spin_lock_init(&priv->beacon_lock); spin_lock_init(&priv->tx.tx_lock); mutex_init(&priv->mutex); @@ -683,6 +682,8 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work); INIT_WORK(&priv->ps_work, ath9k_ps_work); INIT_WORK(&priv->fatal_work, ath9k_fatal_work); + setup_timer(&priv->tx.cleanup_timer, ath9k_htc_tx_cleanup_timer, + (unsigned long)priv); /* * Cache line size is used to size and align various diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index ae85cc4373f0..4de38643cb53 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -194,6 +194,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) ath9k_htc_stop_ani(priv); ieee80211_stop_queues(priv->hw); + del_timer_sync(&priv->tx.cleanup_timer); ath9k_htc_tx_drain(priv); WMI_CMD(WMI_DISABLE_INTR_CMDID); @@ -225,6 +226,9 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) ath9k_htc_vif_reconfig(priv); ieee80211_wake_queues(priv->hw); + mod_timer(&priv->tx.cleanup_timer, + jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); } @@ -251,6 +255,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, ath9k_htc_ps_wakeup(priv); + del_timer_sync(&priv->tx.cleanup_timer); ath9k_htc_tx_drain(priv); WMI_CMD(WMI_DISABLE_INTR_CMDID); @@ -301,6 +306,9 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) ath9k_htc_vif_reconfig(priv); + mod_timer(&priv->tx.cleanup_timer, + jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); + err: ath9k_htc_ps_restore(priv); return ret; @@ -937,6 +945,9 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) ieee80211_wake_queues(hw); + mod_timer(&priv->tx.cleanup_timer, + jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); + if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) { ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, AR_STOMP_LOW_WLAN_WGHT); @@ -972,6 +983,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) tasklet_kill(&priv->rx_tasklet); + del_timer_sync(&priv->tx.cleanup_timer); ath9k_htc_tx_drain(priv); ath9k_wmi_event_drain(priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index a9b6bb1ef287..86f5ce9b6e0e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -495,6 +495,8 @@ static inline void ath9k_htc_tx_drainq(struct ath9k_htc_priv *priv, void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv) { + struct ath9k_htc_tx_event *event, *tmp; + spin_lock_bh(&priv->tx.tx_lock); priv->tx.flags |= ATH9K_HTC_OP_TX_DRAIN; spin_unlock_bh(&priv->tx.tx_lock); @@ -515,6 +517,16 @@ void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv) ath9k_htc_tx_drainq(priv, &priv->tx.data_vo_queue); ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed); + /* + * The TX cleanup timer has already been killed. + */ + spin_lock_bh(&priv->wmi->event_lock); + list_for_each_entry_safe(event, tmp, &priv->wmi->pending_tx_events, list) { + list_del(&event->list); + kfree(event); + } + spin_unlock_bh(&priv->wmi->event_lock); + spin_lock_bh(&priv->tx.tx_lock); priv->tx.flags &= ~ATH9K_HTC_OP_TX_DRAIN; spin_unlock_bh(&priv->tx.tx_lock); @@ -595,6 +607,7 @@ void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event) struct wmi_event_txstatus *txs = (struct wmi_event_txstatus *)wmi_event; struct __wmi_event_txstatus *__txs; struct sk_buff *skb; + struct ath9k_htc_tx_event *tx_pend; int i; for (i = 0; i < txs->cnt; i++) { @@ -603,8 +616,26 @@ void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event) __txs = &txs->txstatus[i]; skb = ath9k_htc_tx_get_packet(priv, __txs); - if (!skb) + if (!skb) { + /* + * Store this event, so that the TX cleanup + * routine can check later for the needed packet. + */ + tx_pend = kzalloc(sizeof(struct ath9k_htc_tx_event), + GFP_ATOMIC); + if (!tx_pend) + continue; + + memcpy(&tx_pend->txs, __txs, + sizeof(struct __wmi_event_txstatus)); + + spin_lock(&priv->wmi->event_lock); + list_add_tail(&tx_pend->list, + &priv->wmi->pending_tx_events); + spin_unlock(&priv->wmi->event_lock); + continue; + } ath9k_htc_tx_process(priv, skb, __txs); } @@ -622,6 +653,7 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, tx_ctl = HTC_SKB_CB(skb); tx_ctl->txok = txok; + tx_ctl->timestamp = jiffies; if (!txok) { skb_queue_tail(&priv->tx.tx_failed, skb); @@ -638,6 +670,99 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, skb_queue_tail(epid_queue, skb); } +static inline bool check_packet(struct ath9k_htc_priv *priv, struct sk_buff *skb) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_tx_ctl *tx_ctl; + + tx_ctl = HTC_SKB_CB(skb); + + if (time_after(jiffies, + tx_ctl->timestamp + + msecs_to_jiffies(ATH9K_HTC_TX_TIMEOUT_INTERVAL))) { + ath_dbg(common, ATH_DBG_XMIT, + "Dropping a packet due to TX timeout\n"); + return true; + } + + return false; +} + +static void ath9k_htc_tx_cleanup_queue(struct ath9k_htc_priv *priv, + struct sk_buff_head *epid_queue) +{ + bool process = false; + unsigned long flags; + struct sk_buff *skb, *tmp; + struct sk_buff_head queue; + + skb_queue_head_init(&queue); + + spin_lock_irqsave(&epid_queue->lock, flags); + skb_queue_walk_safe(epid_queue, skb, tmp) { + if (check_packet(priv, skb)) { + __skb_unlink(skb, epid_queue); + __skb_queue_tail(&queue, skb); + process = true; + } + } + spin_unlock_irqrestore(&epid_queue->lock, flags); + + if (process) { + skb_queue_walk_safe(&queue, skb, tmp) { + __skb_unlink(skb, &queue); + ath9k_htc_tx_process(priv, skb, NULL); + } + } +} + +void ath9k_htc_tx_cleanup_timer(unsigned long data) +{ + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) data; + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_tx_event *event, *tmp; + struct sk_buff *skb; + + spin_lock(&priv->wmi->event_lock); + list_for_each_entry_safe(event, tmp, &priv->wmi->pending_tx_events, list) { + + skb = ath9k_htc_tx_get_packet(priv, &event->txs); + if (skb) { + ath_dbg(common, ATH_DBG_XMIT, + "Found packet for cookie: %d, epid: %d\n", + event->txs.cookie, + MS(event->txs.ts_rate, ATH9K_HTC_TXSTAT_EPID)); + + ath9k_htc_tx_process(priv, skb, &event->txs); + list_del(&event->list); + kfree(event); + continue; + } + + if (++event->count >= ATH9K_HTC_TX_TIMEOUT_COUNT) { + list_del(&event->list); + kfree(event); + } + } + spin_unlock(&priv->wmi->event_lock); + + /* + * Check if status-pending packets have to be cleaned up. + */ + ath9k_htc_tx_cleanup_queue(priv, &priv->tx.mgmt_ep_queue); + ath9k_htc_tx_cleanup_queue(priv, &priv->tx.cab_ep_queue); + ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_be_queue); + ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_bk_queue); + ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_vi_queue); + ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_vo_queue); + + /* Wake TX queues if needed */ + ath9k_htc_check_wake_queues(priv); + + mod_timer(&priv->tx.cleanup_timer, + jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); +} + int ath9k_tx_init(struct ath9k_htc_priv *priv) { skb_queue_head_init(&priv->tx.mgmt_ep_queue); diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 3f5a4d1fe077..697e5af842c1 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -91,9 +91,12 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv) wmi->drv_priv = priv; wmi->stopped = false; skb_queue_head_init(&wmi->wmi_event_queue); + spin_lock_init(&wmi->wmi_lock); + spin_lock_init(&wmi->event_lock); mutex_init(&wmi->op_mutex); mutex_init(&wmi->multi_write_mutex); init_completion(&wmi->cmd_wait); + INIT_LIST_HEAD(&wmi->pending_tx_events); tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet, (unsigned long)wmi); diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 44b17385374f..310d94eaed19 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -130,6 +130,12 @@ struct register_write { __be32 val; }; +struct ath9k_htc_tx_event { + int count; + struct __wmi_event_txstatus txs; + struct list_head list; +}; + struct wmi { struct ath9k_htc_priv *drv_priv; struct htc_target *htc; @@ -144,6 +150,9 @@ struct wmi { u32 cmd_rsp_len; bool stopped; + struct list_head pending_tx_events; + spinlock_t event_lock; + spinlock_t wmi_lock; atomic_t mwrite_cnt; -- cgit v1.2.3-58-ga151 From 2f80194c90caea3668d0e3739518bf100449a813 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:26:46 +0530 Subject: ath9k_htc: Use separate URB pool for management frames Beacon transmission needs to involve as little latency as possible after receiving a SWBA event from the target. Since packets are buffered to use TX stream mode, beacon frames sometimes gets queued up and are not sent out immediately. Fix this by decoupling management frame transmission from the normal data path and send them out immediately. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 116 ++++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath9k/hif_usb.h | 1 + 2 files changed, 108 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 7fae79d16665..3b0efab65131 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -78,7 +78,7 @@ static void hif_usb_regout_cb(struct urb *urb) if (cmd) { ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, - cmd->skb, 1); + cmd->skb, true); kfree(cmd); } @@ -124,6 +124,90 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, return ret; } +static void hif_usb_mgmt_cb(struct urb *urb) +{ + struct cmd_buf *cmd = (struct cmd_buf *)urb->context; + struct hif_device_usb *hif_dev = cmd->hif_dev; + bool txok = true; + + if (!cmd || !cmd->skb || !cmd->hif_dev) + return; + + switch (urb->status) { + case 0: + break; + case -ENOENT: + case -ECONNRESET: + case -ENODEV: + case -ESHUTDOWN: + txok = false; + + /* + * If the URBs are being flushed, no need to complete + * this packet. + */ + spin_lock(&hif_dev->tx.tx_lock); + if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { + spin_unlock(&hif_dev->tx.tx_lock); + dev_kfree_skb_any(cmd->skb); + kfree(cmd); + return; + } + spin_unlock(&hif_dev->tx.tx_lock); + + break; + default: + txok = false; + break; + } + + skb_pull(cmd->skb, 4); + ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, + cmd->skb, txok); + kfree(cmd); +} + +static int hif_usb_send_mgmt(struct hif_device_usb *hif_dev, + struct sk_buff *skb) +{ + struct urb *urb; + struct cmd_buf *cmd; + int ret = 0; + __le16 *hdr; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (urb == NULL) + return -ENOMEM; + + cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); + if (cmd == NULL) { + usb_free_urb(urb); + return -ENOMEM; + } + + cmd->skb = skb; + cmd->hif_dev = hif_dev; + + hdr = (__le16 *) skb_push(skb, 4); + *hdr++ = cpu_to_le16(skb->len - 4); + *hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG); + + usb_fill_bulk_urb(urb, hif_dev->udev, + usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE), + skb->data, skb->len, + hif_usb_mgmt_cb, cmd); + + usb_anchor_urb(urb, &hif_dev->mgmt_submitted); + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) { + usb_unanchor_urb(urb); + kfree(cmd); + } + usb_free_urb(urb); + + return ret; +} + static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, struct sk_buff_head *list) { @@ -275,6 +359,7 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb) { struct ath9k_htc_tx_ctl *tx_ctl; unsigned long flags; + int ret = 0; spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); @@ -289,25 +374,33 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb) return -ENOMEM; } - __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); - hif_dev->tx.tx_skb_cnt++; + spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); tx_ctl = HTC_SKB_CB(skb); - /* Send normal/mgmt/beacon frames immediately */ - if (tx_ctl->type != ATH9K_HTC_AMPDU) - __hif_usb_tx(hif_dev); + /* Mgmt/Beacon frames don't use the TX buffer pool */ + if ((tx_ctl->type == ATH9K_HTC_MGMT) || + (tx_ctl->type == ATH9K_HTC_BEACON)) { + ret = hif_usb_send_mgmt(hif_dev, skb); + } + + spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + + if ((tx_ctl->type == ATH9K_HTC_NORMAL) || + (tx_ctl->type == ATH9K_HTC_AMPDU)) { + __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); + hif_dev->tx.tx_skb_cnt++; + } /* Check if AMPDUs have to be sent immediately */ - if ((tx_ctl->type == ATH9K_HTC_AMPDU) && - (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && + if ((hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && (hif_dev->tx.tx_skb_cnt < 2)) { __hif_usb_tx(hif_dev); } spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); - return 0; + return ret; } static void hif_usb_start(void *hif_handle) @@ -339,6 +432,8 @@ static void hif_usb_stop(void *hif_handle) &hif_dev->tx.tx_pending, list) { usb_kill_urb(tx_buf->urb); } + + usb_kill_anchored_urbs(&hif_dev->mgmt_submitted); } static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb) @@ -657,6 +752,8 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) kfree(tx_buf->buf); kfree(tx_buf); } + + usb_kill_anchored_urbs(&hif_dev->mgmt_submitted); } static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) @@ -668,6 +765,7 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) INIT_LIST_HEAD(&hif_dev->tx.tx_pending); spin_lock_init(&hif_dev->tx.tx_lock); __skb_queue_head_init(&hif_dev->tx.tx_skb_queue); + init_usb_anchor(&hif_dev->mgmt_submitted); for (i = 0; i < MAX_TX_URB_NUM; i++) { tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 8b98d646e91a..f59df48a86e2 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -93,6 +93,7 @@ struct hif_device_usb { struct usb_anchor regout_submitted; struct usb_anchor rx_submitted; struct usb_anchor reg_in_submitted; + struct usb_anchor mgmt_submitted; struct sk_buff *remain_skb; const char *fw_name; int rx_remain_len; -- cgit v1.2.3-58-ga151 From 821f9414c0546fbc99a999e9dc613d1756e1de8a Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:26:52 +0530 Subject: ath9k_htc: Use helper routines for transmission Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 227 ++++++++++++++------------ 1 file changed, 127 insertions(+), 100 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 86f5ce9b6e0e..723a3a9c5cd9 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -211,28 +211,140 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, return error; } +static void ath9k_htc_tx_mgmt(struct ath9k_htc_priv *priv, + struct ath9k_htc_vif *avp, + struct sk_buff *skb, + u8 sta_idx, u8 vif_idx, u8 slot) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_mgmt *mgmt; + struct ieee80211_hdr *hdr; + struct tx_mgmt_hdr mgmt_hdr; + struct ath9k_htc_tx_ctl *tx_ctl; + u8 *tx_fhdr; + + tx_ctl = HTC_SKB_CB(skb); + hdr = (struct ieee80211_hdr *) skb->data; + + memset(tx_ctl, 0, sizeof(*tx_ctl)); + memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); + + /* + * Set the TSF adjust value for probe response + * frame also. + */ + if (avp && unlikely(ieee80211_is_probe_resp(hdr->frame_control))) { + mgmt = (struct ieee80211_mgmt *)skb->data; + mgmt->u.probe_resp.timestamp = avp->tsfadjust; + } + + tx_ctl->type = ATH9K_HTC_MGMT; + + mgmt_hdr.node_idx = sta_idx; + mgmt_hdr.vif_idx = vif_idx; + mgmt_hdr.tidno = 0; + mgmt_hdr.flags = 0; + mgmt_hdr.cookie = slot; + + mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); + if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) + mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; + else + mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; + + tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); + memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); + tx_ctl->epid = priv->mgmt_ep; +} + +static void ath9k_htc_tx_data(struct ath9k_htc_priv *priv, + struct ieee80211_vif *vif, + struct sk_buff *skb, + u8 sta_idx, u8 vif_idx, u8 slot, + bool is_cab) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr; + struct ath9k_htc_tx_ctl *tx_ctl; + struct tx_frame_hdr tx_hdr; + u32 flags = 0; + u8 *qc, *tx_fhdr; + u16 qnum; + + tx_ctl = HTC_SKB_CB(skb); + hdr = (struct ieee80211_hdr *) skb->data; + + memset(tx_ctl, 0, sizeof(*tx_ctl)); + memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); + + tx_hdr.node_idx = sta_idx; + tx_hdr.vif_idx = vif_idx; + tx_hdr.cookie = slot; + + /* + * This is a bit redundant but it helps to get + * the per-packet index quickly when draining the + * TX queue in the HIF layer. Otherwise we would + * have to parse the packet contents ... + */ + tx_ctl->sta_idx = sta_idx; + + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { + tx_ctl->type = ATH9K_HTC_AMPDU; + tx_hdr.data_type = ATH9K_HTC_AMPDU; + } else { + tx_ctl->type = ATH9K_HTC_NORMAL; + tx_hdr.data_type = ATH9K_HTC_NORMAL; + } + + if (ieee80211_is_data_qos(hdr->frame_control)) { + qc = ieee80211_get_qos_ctl(hdr); + tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + } + + /* Check for RTS protection */ + if (priv->hw->wiphy->rts_threshold != (u32) -1) + if (skb->len > priv->hw->wiphy->rts_threshold) + flags |= ATH9K_HTC_TX_RTSCTS; + + /* CTS-to-self */ + if (!(flags & ATH9K_HTC_TX_RTSCTS) && + (vif && vif->bss_conf.use_cts_prot)) + flags |= ATH9K_HTC_TX_CTSONLY; + + tx_hdr.flags = cpu_to_be32(flags); + tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); + if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) + tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; + else + tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; + + tx_fhdr = skb_push(skb, sizeof(tx_hdr)); + memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); + + if (is_cab) { + CAB_STAT_INC; + tx_ctl->epid = priv->cab_ep; + return; + } + + qnum = skb_get_queue_mapping(skb); + tx_ctl->epid = get_htc_epid(priv, qnum); +} + int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb, u8 slot, bool is_cab) { struct ieee80211_hdr *hdr; - struct ieee80211_mgmt *mgmt; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_sta *sta = tx_info->control.sta; struct ieee80211_vif *vif = tx_info->control.vif; struct ath9k_htc_sta *ista; struct ath9k_htc_vif *avp = NULL; - struct ath9k_htc_tx_ctl *tx_ctl; - u16 qnum; - __le16 fc; - u8 *tx_fhdr; u8 sta_idx, vif_idx; - tx_ctl = HTC_SKB_CB(skb); - memset(tx_ctl, 0, sizeof(*tx_ctl)); - hdr = (struct ieee80211_hdr *) skb->data; - fc = hdr->frame_control; /* * Find out on which interface this packet has to be @@ -261,99 +373,14 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, sta_idx = priv->vif_sta_pos[vif_idx]; } - if (ieee80211_is_data(fc)) { - struct tx_frame_hdr tx_hdr; - u32 flags = 0; - u8 *qc; - - memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); - - tx_hdr.node_idx = sta_idx; - tx_hdr.vif_idx = vif_idx; - tx_hdr.cookie = slot; - - /* - * This is a bit redundant but it helps to get - * the per-packet index quickly when draining the - * TX queue in the HIF layer. Otherwise we would - * have to parse the packet contents ... - */ - tx_ctl->sta_idx = sta_idx; - - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { - tx_ctl->type = ATH9K_HTC_AMPDU; - tx_hdr.data_type = ATH9K_HTC_AMPDU; - } else { - tx_ctl->type = ATH9K_HTC_NORMAL; - tx_hdr.data_type = ATH9K_HTC_NORMAL; - } - - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - } - - /* Check for RTS protection */ - if (priv->hw->wiphy->rts_threshold != (u32) -1) - if (skb->len > priv->hw->wiphy->rts_threshold) - flags |= ATH9K_HTC_TX_RTSCTS; - - /* CTS-to-self */ - if (!(flags & ATH9K_HTC_TX_RTSCTS) && - (vif && vif->bss_conf.use_cts_prot)) - flags |= ATH9K_HTC_TX_CTSONLY; - - tx_hdr.flags = cpu_to_be32(flags); - tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); - if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) - tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; - else - tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; - - tx_fhdr = skb_push(skb, sizeof(tx_hdr)); - memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); - - if (is_cab) { - CAB_STAT_INC; - tx_ctl->epid = priv->cab_ep; - goto send; - } - - qnum = skb_get_queue_mapping(skb); - tx_ctl->epid = get_htc_epid(priv, qnum); - } else { - struct tx_mgmt_hdr mgmt_hdr; - - memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); - - /* - * Set the TSF adjust value for probe response - * frame also. - */ - if (avp && unlikely(ieee80211_is_probe_resp(fc))) { - mgmt = (struct ieee80211_mgmt *)skb->data; - mgmt->u.probe_resp.timestamp = avp->tsfadjust; - } - - tx_ctl->type = ATH9K_HTC_MGMT; - - mgmt_hdr.node_idx = sta_idx; - mgmt_hdr.vif_idx = vif_idx; - mgmt_hdr.tidno = 0; - mgmt_hdr.flags = 0; - mgmt_hdr.cookie = slot; + if (ieee80211_is_data(hdr->frame_control)) + ath9k_htc_tx_data(priv, vif, skb, + sta_idx, vif_idx, slot, is_cab); + else + ath9k_htc_tx_mgmt(priv, avp, skb, + sta_idx, vif_idx, slot); - mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); - if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) - mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; - else - mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; - tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); - memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); - tx_ctl->epid = priv->mgmt_ep; - } -send: return htc_send(priv->htc, skb); } -- cgit v1.2.3-58-ga151 From fbc29d6c3da58bc51416f65a50bdb419d4ea85b8 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:26:58 +0530 Subject: ath9k_htc: Add detailed firmware statistics New debugfs files: /ath9k_htc//tgt_int_stats /ath9k_htc//tgt_tx_stats /ath9k_htc//tgt_rx_stats Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 36 +++-- drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 185 +++++++++++++++++++++---- drivers/net/wireless/ath/ath9k/wmi.c | 19 ++- drivers/net/wireless/ath/ath9k/wmi.h | 7 +- 4 files changed, 195 insertions(+), 52 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index b413b46119b0..cc5d0a4b9da2 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -175,12 +175,31 @@ struct ath9k_htc_target_rate { struct ath9k_htc_rate rates; }; -struct ath9k_htc_target_stats { - __be32 tx_shortretry; - __be32 tx_longretry; - __be32 tx_xretries; - __be32 ht_txunaggr_xretry; - __be32 ht_tx_xretries; +struct ath9k_htc_target_int_stats { + __be32 rx; + __be32 rxorn; + __be32 rxeol; + __be32 txurn; + __be32 txto; + __be32 cst; +} __packed; + +struct ath9k_htc_target_tx_stats { + __be32 xretries; + __be32 fifoerr; + __be32 filtered; + __be32 timer_exp; + __be32 shortretries; + __be32 longretries; + __be32 qnull; + __be32 encap_fail; + __be32 nobuf; +} __packed; + +struct ath9k_htc_target_rx_stats { + __be32 nobuf; + __be32 host_send; + __be32 host_done; } __packed; #define ATH9K_HTC_MAX_VIF 2 @@ -340,14 +359,15 @@ struct ath_rx_stats { struct ath9k_debug { struct dentry *debugfs_phy; - struct dentry *debugfs_tgt_stats; + struct dentry *debugfs_tgt_int_stats; + struct dentry *debugfs_tgt_tx_stats; + struct dentry *debugfs_tgt_rx_stats; struct dentry *debugfs_xmit; struct dentry *debugfs_recv; struct dentry *debugfs_slot; struct dentry *debugfs_queue; struct ath_tx_stats tx_stats; struct ath_rx_stats rx_stats; - u32 txrate; }; #else diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 961bec20d140..8d0de60e0c27 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -24,39 +24,108 @@ static int ath9k_debugfs_open(struct inode *inode, struct file *file) return 0; } -static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) +static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) { struct ath9k_htc_priv *priv = file->private_data; - struct ath9k_htc_target_stats cmd_rsp; + struct ath9k_htc_target_int_stats cmd_rsp; char buf[512]; unsigned int len = 0; int ret = 0; memset(&cmd_rsp, 0, sizeof(cmd_rsp)); - WMI_CMD(WMI_TGT_STATS_CMDID); + WMI_CMD(WMI_INT_STATS_CMDID); if (ret) return -EINVAL; + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "RX", + be32_to_cpu(cmd_rsp.rx)); + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "RXORN", + be32_to_cpu(cmd_rsp.rxorn)); + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "RXEOL", + be32_to_cpu(cmd_rsp.rxeol)); + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "TXURN", + be32_to_cpu(cmd_rsp.txurn)); + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "TXTO", + be32_to_cpu(cmd_rsp.txto)); + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "CST", + be32_to_cpu(cmd_rsp.cst)); + + if (len > sizeof(buf)) + len = sizeof(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_tgt_int_stats = { + .read = read_file_tgt_int_stats, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + struct ath9k_htc_target_tx_stats cmd_rsp; + char buf[512]; + unsigned int len = 0; + int ret = 0; + + memset(&cmd_rsp, 0, sizeof(cmd_rsp)); + + WMI_CMD(WMI_TX_STATS_CMDID); + if (ret) + return -EINVAL; + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "Xretries", + be32_to_cpu(cmd_rsp.xretries)); + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "FifoErr", + be32_to_cpu(cmd_rsp.fifoerr)); + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "Filtered", + be32_to_cpu(cmd_rsp.filtered)); len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Short Retries", - be32_to_cpu(cmd_rsp.tx_shortretry)); + "%20s : %10u\n", "TimerExp", + be32_to_cpu(cmd_rsp.timer_exp)); + len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Long Retries", - be32_to_cpu(cmd_rsp.tx_longretry)); + "%20s : %10u\n", "ShortRetries", + be32_to_cpu(cmd_rsp.shortretries)); + len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Xretries", - be32_to_cpu(cmd_rsp.tx_xretries)); + "%20s : %10u\n", "LongRetries", + be32_to_cpu(cmd_rsp.longretries)); + len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Unaggr. Xretries", - be32_to_cpu(cmd_rsp.ht_txunaggr_xretry)); + "%20s : %10u\n", "QueueNull", + be32_to_cpu(cmd_rsp.qnull)); + len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Xretries (HT)", - be32_to_cpu(cmd_rsp.ht_tx_xretries)); + "%20s : %10u\n", "EncapFail", + be32_to_cpu(cmd_rsp.encap_fail)); + len += snprintf(buf + len, sizeof(buf) - len, - "%19s : %10u\n", "TX Rate", priv->debug.txrate); + "%20s : %10u\n", "NoBuf", + be32_to_cpu(cmd_rsp.nobuf)); if (len > sizeof(buf)) len = sizeof(buf); @@ -64,8 +133,48 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, return simple_read_from_buffer(user_buf, count, ppos, buf, len); } -static const struct file_operations fops_tgt_stats = { - .read = read_file_tgt_stats, +static const struct file_operations fops_tgt_tx_stats = { + .read = read_file_tgt_tx_stats, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + struct ath9k_htc_target_rx_stats cmd_rsp; + char buf[512]; + unsigned int len = 0; + int ret = 0; + + memset(&cmd_rsp, 0, sizeof(cmd_rsp)); + + WMI_CMD(WMI_RX_STATS_CMDID); + if (ret) + return -EINVAL; + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "NoBuf", + be32_to_cpu(cmd_rsp.nobuf)); + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "HostSend", + be32_to_cpu(cmd_rsp.host_send)); + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "HostDone", + be32_to_cpu(cmd_rsp.host_done)); + + if (len > sizeof(buf)) + len = sizeof(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_tgt_rx_stats = { + .read = read_file_tgt_rx_stats, .open = ath9k_debugfs_open, .owner = THIS_MODULE, .llseek = default_llseek, @@ -286,29 +395,29 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf, char buf[512]; unsigned int len = 0; - len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue)); - len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue)); - len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue)); - len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue)); - len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue)); - len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue)); - len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "Failed queue", skb_queue_len(&priv->tx.tx_failed)); spin_lock_bh(&priv->tx.tx_lock); - len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n", + len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "Queued count", priv->tx.queued_cnt); spin_unlock_bh(&priv->tx.tx_lock); @@ -339,12 +448,26 @@ int ath9k_htc_init_debug(struct ath_hw *ah) if (!priv->debug.debugfs_phy) goto err; - priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_tgt_stats); - if (!priv->debug.debugfs_tgt_stats) + priv->debug.debugfs_tgt_int_stats = debugfs_create_file("tgt_int_stats", + S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_tgt_int_stats); + if (!priv->debug.debugfs_tgt_int_stats) goto err; + priv->debug.debugfs_tgt_tx_stats = debugfs_create_file("tgt_tx_stats", + S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_tgt_tx_stats); + if (!priv->debug.debugfs_tgt_tx_stats) + goto err; + + priv->debug.debugfs_tgt_rx_stats = debugfs_create_file("tgt_rx_stats", + S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_tgt_rx_stats); + if (!priv->debug.debugfs_tgt_rx_stats) + goto err; priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy, @@ -386,7 +509,9 @@ void ath9k_htc_exit_debug(struct ath_hw *ah) debugfs_remove(priv->debug.debugfs_slot); debugfs_remove(priv->debug.debugfs_recv); debugfs_remove(priv->debug.debugfs_xmit); - debugfs_remove(priv->debug.debugfs_tgt_stats); + debugfs_remove(priv->debug.debugfs_tgt_int_stats); + debugfs_remove(priv->debug.debugfs_tgt_tx_stats); + debugfs_remove(priv->debug.debugfs_tgt_rx_stats); debugfs_remove(priv->debug.debugfs_phy); } diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 697e5af842c1..8f095ad0a3db 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -67,12 +67,18 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_RC_RATE_UPDATE_CMDID"; case WMI_TARGET_IC_UPDATE_CMDID: return "WMI_TARGET_IC_UPDATE_CMDID"; - case WMI_TGT_STATS_CMDID: - return "WMI_TGT_STATS_CMDID"; case WMI_TX_AGGR_ENABLE_CMDID: return "WMI_TX_AGGR_ENABLE_CMDID"; case WMI_TGT_DETACH_CMDID: return "WMI_TGT_DETACH_CMDID"; + case WMI_NODE_UPDATE_CMDID: + return "WMI_NODE_UPDATE_CMDID"; + case WMI_INT_STATS_CMDID: + return "WMI_INT_STATS_CMDID"; + case WMI_TX_STATS_CMDID: + return "WMI_TX_STATS_CMDID"; + case WMI_RX_STATS_CMDID: + return "WMI_RX_STATS_CMDID"; case WMI_AGGR_LIMIT_CMD: return "WMI_AGGR_LIMIT_CMD"; } @@ -134,9 +140,6 @@ void ath9k_wmi_event_tasklet(unsigned long data) struct sk_buff *skb = NULL; unsigned long flags; u16 cmd_id; -#ifdef CONFIG_ATH9K_HTC_DEBUGFS - __be32 txrate; -#endif do { spin_lock_irqsave(&wmi->wmi_lock, flags); @@ -160,12 +163,6 @@ void ath9k_wmi_event_tasklet(unsigned long data) ieee80211_queue_work(wmi->drv_priv->hw, &wmi->drv_priv->fatal_work); break; - case WMI_TXRATE_EVENTID: -#ifdef CONFIG_ATH9K_HTC_DEBUGFS - txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; - wmi->drv_priv->debug.txrate = be32_to_cpu(txrate); -#endif - break; case WMI_TXSTATUS_EVENTID: spin_lock_bh(&priv->tx.tx_lock); if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 310d94eaed19..02ecb9f06db0 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -17,7 +17,6 @@ #ifndef WMI_H #define WMI_H - struct wmi_event_txrate { __be32 txrate; struct { @@ -106,9 +105,12 @@ enum wmi_cmd_id { WMI_RC_STATE_CHANGE_CMDID, WMI_RC_RATE_UPDATE_CMDID, WMI_TARGET_IC_UPDATE_CMDID, - WMI_TGT_STATS_CMDID, WMI_TX_AGGR_ENABLE_CMDID, WMI_TGT_DETACH_CMDID, + WMI_NODE_UPDATE_CMDID, + WMI_INT_STATS_CMDID, + WMI_TX_STATS_CMDID, + WMI_RX_STATS_CMDID, WMI_AGGR_LIMIT_CMD = 0x0026, }; @@ -119,7 +121,6 @@ enum wmi_event_id { WMI_TXTO_EVENTID, WMI_BMISS_EVENTID, WMI_DELBA_EVENTID, - WMI_TXRATE_EVENTID, WMI_TXSTATUS_EVENTID, }; -- cgit v1.2.3-58-ga151 From 09d5b94d2cbc6c3ebb70a9a318f6390d0b4cf010 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 13 Apr 2011 11:27:06 +0530 Subject: ath9k_htc: Enable AP and P2P modes Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 0aec25920c0a..22736eb901cf 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -752,7 +752,10 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC); + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_P2P_CLIENT); hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; -- cgit v1.2.3-58-ga151 From a3e6b12c0232748658a602eda39f12fddb254ba8 Mon Sep 17 00:00:00 2001 From: cozybit Inc Date: Wed, 13 Apr 2011 11:10:28 -0700 Subject: mac80211: Allocate new mesh path and portal tables before taking locks It is unnecessary to hold the path table resize lock while allocating a new table. Allocate first and take lock later. This resolves a soft-lockup: [ 293.385799] BUG: soft lockup - CPU#0 stuck for 61s! [kworker/u:3:744] (...) [ 293.386049] Call Trace: [ 293.386049] [] do_raw_read_lock+0x26/0x29 [ 293.386049] [] _raw_read_lock+0x8/0xa [ 293.386049] [] mesh_path_add+0xb7/0x24e [ 293.386049] [] ? mesh_path_lookup+0x1b/0xa6 [ 293.386049] [] hwmp_route_info_get+0x276/0x2fd [ 293.386049] [] mesh_rx_path_sel_frame+0x5a/0x5d9 [ 293.386049] [] ? update_curr+0x1cf/0x1d7 [ 293.386049] [] ieee80211_mesh_rx_queued_mgmt+0x60/0x67 [ 293.386049] [] ieee80211_iface_work+0x1f0/0x258 (...) Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/mac80211/mesh_pathtbl.c | 49 +++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 8d65b47d9837..7776ae5a8f15 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -65,42 +65,37 @@ void mesh_table_free(struct mesh_table *tbl, bool free_leafs) __mesh_table_free(tbl); } -static struct mesh_table *mesh_table_grow(struct mesh_table *tbl) +static int mesh_table_grow(struct mesh_table *oldtbl, + struct mesh_table *newtbl) { - struct mesh_table *newtbl; struct hlist_head *oldhash; struct hlist_node *p, *q; int i; - if (atomic_read(&tbl->entries) - < tbl->mean_chain_len * (tbl->hash_mask + 1)) - goto endgrow; + if (atomic_read(&oldtbl->entries) + < oldtbl->mean_chain_len * (oldtbl->hash_mask + 1)) + return -EAGAIN; - newtbl = mesh_table_alloc(tbl->size_order + 1); - if (!newtbl) - goto endgrow; - newtbl->free_node = tbl->free_node; - newtbl->mean_chain_len = tbl->mean_chain_len; - newtbl->copy_node = tbl->copy_node; - atomic_set(&newtbl->entries, atomic_read(&tbl->entries)); + newtbl->free_node = oldtbl->free_node; + newtbl->mean_chain_len = oldtbl->mean_chain_len; + newtbl->copy_node = oldtbl->copy_node; + atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries)); - oldhash = tbl->hash_buckets; - for (i = 0; i <= tbl->hash_mask; i++) + oldhash = oldtbl->hash_buckets; + for (i = 0; i <= oldtbl->hash_mask; i++) hlist_for_each(p, &oldhash[i]) - if (tbl->copy_node(p, newtbl) < 0) + if (oldtbl->copy_node(p, newtbl) < 0) goto errcopy; - return newtbl; + return 0; errcopy: for (i = 0; i <= newtbl->hash_mask; i++) { hlist_for_each_safe(p, q, &newtbl->hash_buckets[i]) - tbl->free_node(p, 0); + oldtbl->free_node(p, 0); } - __mesh_table_free(newtbl); -endgrow: - return NULL; + return -ENOMEM; } @@ -334,10 +329,13 @@ void mesh_mpath_table_grow(void) { struct mesh_table *oldtbl, *newtbl; + newtbl = mesh_table_alloc(mesh_paths->size_order + 1); + if (!newtbl) + return; write_lock(&pathtbl_resize_lock); oldtbl = mesh_paths; - newtbl = mesh_table_grow(mesh_paths); - if (!newtbl) { + if (mesh_table_grow(mesh_paths, newtbl) < 0) { + __mesh_table_free(newtbl); write_unlock(&pathtbl_resize_lock); return; } @@ -352,10 +350,13 @@ void mesh_mpp_table_grow(void) { struct mesh_table *oldtbl, *newtbl; + newtbl = mesh_table_alloc(mpp_paths->size_order + 1); + if (!newtbl) + return; write_lock(&pathtbl_resize_lock); oldtbl = mpp_paths; - newtbl = mesh_table_grow(mpp_paths); - if (!newtbl) { + if (mesh_table_grow(mpp_paths, newtbl) < 0) { + __mesh_table_free(newtbl); write_unlock(&pathtbl_resize_lock); return; } -- cgit v1.2.3-58-ga151 From 4d42d417be75d750b82798922b6e775915e11bce Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 13 Apr 2011 14:48:55 -0700 Subject: rndis_host: Poll status before control channel where necessary Some RNDIS devices don't respond on the control channel until polled on the status channel. In particular, this was reported to be the case for the 2Wire HomePortal 1000SW and for some Windows Mobile devices. This is roughly based on a patch by John Carr which is currently applied by Mandriva. Reported-by: Mark Glassberg Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/usb/rndis_host.c | 39 ++++++++++++++++++++++++++++++++------- include/linux/usb/rndis_host.h | 2 ++ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 5994a25c56ac..6d6c1da68a36 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -104,8 +104,10 @@ static void rndis_msg_indicate(struct usbnet *dev, struct rndis_indicate *msg, int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen) { struct cdc_state *info = (void *) &dev->data; + struct usb_cdc_notification notification; int master_ifnum; int retval; + int partial; unsigned count; __le32 rsp; u32 xid = 0, msg_len, request_id; @@ -133,13 +135,20 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen) if (unlikely(retval < 0 || xid == 0)) return retval; - // FIXME Seems like some devices discard responses when - // we time out and cancel our "get response" requests... - // so, this is fragile. Probably need to poll for status. + /* Some devices don't respond on the control channel until + * polled on the status channel, so do that first. */ + if (dev->driver_info->data & RNDIS_DRIVER_DATA_POLL_STATUS) { + retval = usb_interrupt_msg( + dev->udev, + usb_rcvintpipe(dev->udev, + dev->status->desc.bEndpointAddress), + ¬ification, sizeof(notification), &partial, + RNDIS_CONTROL_TIMEOUT_MS); + if (unlikely(retval < 0)) + return retval; + } - /* ignore status endpoint, just poll the control channel; - * the request probably completed immediately - */ + /* Poll the control channel; the request probably completed immediately */ rsp = buf->msg_type | RNDIS_MSG_COMPLETION; for (count = 0; count < 10; count++) { memset(buf, 0, CONTROL_BUFFER_SIZE); @@ -581,17 +590,33 @@ static const struct driver_info rndis_info = { .tx_fixup = rndis_tx_fixup, }; +static const struct driver_info rndis_poll_status_info = { + .description = "RNDIS device (poll status before control)", + .flags = FLAG_ETHER | FLAG_FRAMING_RN | FLAG_NO_SETINT, + .data = RNDIS_DRIVER_DATA_POLL_STATUS, + .bind = rndis_bind, + .unbind = rndis_unbind, + .status = rndis_status, + .rx_fixup = rndis_rx_fixup, + .tx_fixup = rndis_tx_fixup, +}; + /*-------------------------------------------------------------------------*/ static const struct usb_device_id products [] = { { + /* 2Wire HomePortal 1000SW */ + USB_DEVICE_AND_INTERFACE_INFO(0x1630, 0x0042, + USB_CLASS_COMM, 2 /* ACM */, 0x0ff), + .driver_info = (unsigned long) &rndis_poll_status_info, +}, { /* RNDIS is MSFT's un-official variant of CDC ACM */ USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff), .driver_info = (unsigned long) &rndis_info, }, { /* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */ USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1), - .driver_info = (unsigned long) &rndis_info, + .driver_info = (unsigned long) &rndis_poll_status_info, }, { /* RNDIS for tethering */ USB_INTERFACE_INFO(USB_CLASS_WIRELESS_CONTROLLER, 1, 3), diff --git a/include/linux/usb/rndis_host.h b/include/linux/usb/rndis_host.h index 05ef52861988..88fceb718c77 100644 --- a/include/linux/usb/rndis_host.h +++ b/include/linux/usb/rndis_host.h @@ -256,6 +256,8 @@ struct rndis_keepalive_c { /* IN (optionally OUT) */ #define FLAG_RNDIS_PHYM_NOT_WIRELESS 0x0001 #define FLAG_RNDIS_PHYM_WIRELESS 0x0002 +/* Flags for driver_info::data */ +#define RNDIS_DRIVER_DATA_POLL_STATUS 1 /* poll status before control */ extern void rndis_status(struct usbnet *dev, struct urb *urb); extern int -- cgit v1.2.3-58-ga151 From 280f294f7bd0c14d9f802a551c95dc930e31d723 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 13 Apr 2011 19:01:22 -0300 Subject: Bluetooth: Don't lock sock inside l2cap_get_sock_by_scid() Fix an locking issue with the new l2cap_att_channel(). l2cap_att_channel() was trying to lock a locked socket. Reported-by: Anderson Lizardo Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c9c1f9257a91..d5db5a38df6a 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -594,7 +594,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) */ static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src) { - struct sock *s, *sk = NULL, *sk1 = NULL; + struct sock *sk = NULL, *sk1 = NULL; struct hlist_node *node; read_lock(&l2cap_sk_list.lock); @@ -613,12 +613,10 @@ static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src) sk1 = sk; } } - s = node ? sk : sk1; - if (s) - bh_lock_sock(s); + read_unlock(&l2cap_sk_list.lock); - return s; + return node ? sk : sk1; } static void l2cap_le_conn_ready(struct l2cap_conn *conn) -- cgit v1.2.3-58-ga151 From 97bd8e491d1786f0020372a5a470bb8b3184856f Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 13 Apr 2011 11:05:04 +0000 Subject: tg3: Provide full regdump on tx timeout The current amount of information provided in the output of a tx timeout is insufficient to determine a root cause. This patch replaces the terse, four-register status output with a more complete body of information. For PCIe devices, the full register space is dumped. For other devices, select registers are dumped instead. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 189 ++++++++++++++++++++++++++++++++++-------------------- drivers/net/tg3.h | 2 + 2 files changed, 123 insertions(+), 68 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 9d7defc2628d..72744353b1cb 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4459,6 +4459,123 @@ static inline int tg3_irq_sync(struct tg3 *tp) return tp->irq_sync; } +static inline void tg3_rd32_loop(struct tg3 *tp, u32 *dst, u32 off, u32 len) +{ + int i; + + dst = (u32 *)((u8 *)dst + off); + for (i = 0; i < len; i += sizeof(u32)) + *dst++ = tr32(off + i); +} + +static void tg3_dump_legacy_regs(struct tg3 *tp, u32 *regs) +{ + tg3_rd32_loop(tp, regs, TG3PCI_VENDOR, 0xb0); + tg3_rd32_loop(tp, regs, MAILBOX_INTERRUPT_0, 0x200); + tg3_rd32_loop(tp, regs, MAC_MODE, 0x4f0); + tg3_rd32_loop(tp, regs, SNDDATAI_MODE, 0xe0); + tg3_rd32_loop(tp, regs, SNDDATAC_MODE, 0x04); + tg3_rd32_loop(tp, regs, SNDBDS_MODE, 0x80); + tg3_rd32_loop(tp, regs, SNDBDI_MODE, 0x48); + tg3_rd32_loop(tp, regs, SNDBDC_MODE, 0x04); + tg3_rd32_loop(tp, regs, RCVLPC_MODE, 0x20); + tg3_rd32_loop(tp, regs, RCVLPC_SELLST_BASE, 0x15c); + tg3_rd32_loop(tp, regs, RCVDBDI_MODE, 0x0c); + tg3_rd32_loop(tp, regs, RCVDBDI_JUMBO_BD, 0x3c); + tg3_rd32_loop(tp, regs, RCVDBDI_BD_PROD_IDX_0, 0x44); + tg3_rd32_loop(tp, regs, RCVDCC_MODE, 0x04); + tg3_rd32_loop(tp, regs, RCVBDI_MODE, 0x20); + tg3_rd32_loop(tp, regs, RCVCC_MODE, 0x14); + tg3_rd32_loop(tp, regs, RCVLSC_MODE, 0x08); + tg3_rd32_loop(tp, regs, MBFREE_MODE, 0x08); + tg3_rd32_loop(tp, regs, HOSTCC_MODE, 0x100); + + if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) + tg3_rd32_loop(tp, regs, HOSTCC_RXCOL_TICKS_VEC1, 0x180); + + tg3_rd32_loop(tp, regs, MEMARB_MODE, 0x10); + tg3_rd32_loop(tp, regs, BUFMGR_MODE, 0x58); + tg3_rd32_loop(tp, regs, RDMAC_MODE, 0x08); + tg3_rd32_loop(tp, regs, WDMAC_MODE, 0x08); + tg3_rd32_loop(tp, regs, RX_CPU_MODE, 0x04); + tg3_rd32_loop(tp, regs, RX_CPU_STATE, 0x04); + tg3_rd32_loop(tp, regs, RX_CPU_PGMCTR, 0x04); + tg3_rd32_loop(tp, regs, RX_CPU_HWBKPT, 0x04); + + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + tg3_rd32_loop(tp, regs, TX_CPU_MODE, 0x04); + tg3_rd32_loop(tp, regs, TX_CPU_STATE, 0x04); + tg3_rd32_loop(tp, regs, TX_CPU_PGMCTR, 0x04); + } + + tg3_rd32_loop(tp, regs, GRCMBOX_INTERRUPT_0, 0x110); + tg3_rd32_loop(tp, regs, FTQ_RESET, 0x120); + tg3_rd32_loop(tp, regs, MSGINT_MODE, 0x0c); + tg3_rd32_loop(tp, regs, DMAC_MODE, 0x04); + tg3_rd32_loop(tp, regs, GRC_MODE, 0x4c); + + if (tp->tg3_flags & TG3_FLAG_NVRAM) + tg3_rd32_loop(tp, regs, NVRAM_CMD, 0x24); +} + +static void tg3_dump_state(struct tg3 *tp) +{ + int i; + u32 *regs; + + regs = kzalloc(TG3_REG_BLK_SIZE, GFP_ATOMIC); + if (!regs) { + netdev_err(tp->dev, "Failed allocating register dump buffer\n"); + return; + } + + if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { + /* Read up to but not including private PCI registers */ + for (i = 0; i < TG3_PCIE_TLDLPL_PORT; i += sizeof(u32)) + regs[i / sizeof(u32)] = tr32(i); + } else + tg3_dump_legacy_regs(tp, regs); + + for (i = 0; i < TG3_REG_BLK_SIZE / sizeof(u32); i += 4) { + if (!regs[i + 0] && !regs[i + 1] && + !regs[i + 2] && !regs[i + 3]) + continue; + + netdev_err(tp->dev, "0x%08x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", + i * 4, + regs[i + 0], regs[i + 1], regs[i + 2], regs[i + 3]); + } + + kfree(regs); + + for (i = 0; i < tp->irq_cnt; i++) { + struct tg3_napi *tnapi = &tp->napi[i]; + + /* SW status block */ + netdev_err(tp->dev, + "%d: Host status block [%08x:%08x:(%04x:%04x:%04x):(%04x:%04x)]\n", + i, + tnapi->hw_status->status, + tnapi->hw_status->status_tag, + tnapi->hw_status->rx_jumbo_consumer, + tnapi->hw_status->rx_consumer, + tnapi->hw_status->rx_mini_consumer, + tnapi->hw_status->idx[0].rx_producer, + tnapi->hw_status->idx[0].tx_consumer); + + netdev_err(tp->dev, + "%d: NAPI info [%08x:%08x:(%04x:%04x:%04x):%04x:(%04x:%04x:%04x:%04x)]\n", + i, + tnapi->last_tag, tnapi->last_irq_tag, + tnapi->tx_prod, tnapi->tx_cons, tnapi->tx_pending, + tnapi->rx_rcb_ptr, + tnapi->prodring.rx_std_prod_idx, + tnapi->prodring.rx_std_cons_idx, + tnapi->prodring.rx_jmb_prod_idx, + tnapi->prodring.rx_jmb_cons_idx); + } +} + /* This is called whenever we suspect that the system chipset is re- * ordering the sequence of MMIO to the tx send mailbox. The symptom * is bogus tx completions. We try to recover by setting the @@ -5516,21 +5633,13 @@ out: tg3_phy_start(tp); } -static void tg3_dump_short_state(struct tg3 *tp) -{ - netdev_err(tp->dev, "DEBUG: MAC_TX_STATUS[%08x] MAC_RX_STATUS[%08x]\n", - tr32(MAC_TX_STATUS), tr32(MAC_RX_STATUS)); - netdev_err(tp->dev, "DEBUG: RDMAC_STATUS[%08x] WDMAC_STATUS[%08x]\n", - tr32(RDMAC_STATUS), tr32(WDMAC_STATUS)); -} - static void tg3_tx_timeout(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); if (netif_msg_tx_err(tp)) { netdev_err(dev, "transmit timed out, resetting\n"); - tg3_dump_short_state(tp); + tg3_dump_state(tp); } schedule_work(&tp->reset_task); @@ -9624,82 +9733,26 @@ static void tg3_set_rx_mode(struct net_device *dev) tg3_full_unlock(tp); } -#define TG3_REGDUMP_LEN (32 * 1024) - static int tg3_get_regs_len(struct net_device *dev) { - return TG3_REGDUMP_LEN; + return TG3_REG_BLK_SIZE; } static void tg3_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p) { - u32 *p = _p; struct tg3 *tp = netdev_priv(dev); - u8 *orig_p = _p; - int i; regs->version = 0; - memset(p, 0, TG3_REGDUMP_LEN); + memset(_p, 0, TG3_REG_BLK_SIZE); if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) return; tg3_full_lock(tp, 0); -#define __GET_REG32(reg) (*(p)++ = tr32(reg)) -#define GET_REG32_LOOP(base, len) \ -do { p = (u32 *)(orig_p + (base)); \ - for (i = 0; i < len; i += 4) \ - __GET_REG32((base) + i); \ -} while (0) -#define GET_REG32_1(reg) \ -do { p = (u32 *)(orig_p + (reg)); \ - __GET_REG32((reg)); \ -} while (0) - - GET_REG32_LOOP(TG3PCI_VENDOR, 0xb0); - GET_REG32_LOOP(MAILBOX_INTERRUPT_0, 0x200); - GET_REG32_LOOP(MAC_MODE, 0x4f0); - GET_REG32_LOOP(SNDDATAI_MODE, 0xe0); - GET_REG32_1(SNDDATAC_MODE); - GET_REG32_LOOP(SNDBDS_MODE, 0x80); - GET_REG32_LOOP(SNDBDI_MODE, 0x48); - GET_REG32_1(SNDBDC_MODE); - GET_REG32_LOOP(RCVLPC_MODE, 0x20); - GET_REG32_LOOP(RCVLPC_SELLST_BASE, 0x15c); - GET_REG32_LOOP(RCVDBDI_MODE, 0x0c); - GET_REG32_LOOP(RCVDBDI_JUMBO_BD, 0x3c); - GET_REG32_LOOP(RCVDBDI_BD_PROD_IDX_0, 0x44); - GET_REG32_1(RCVDCC_MODE); - GET_REG32_LOOP(RCVBDI_MODE, 0x20); - GET_REG32_LOOP(RCVCC_MODE, 0x14); - GET_REG32_LOOP(RCVLSC_MODE, 0x08); - GET_REG32_1(MBFREE_MODE); - GET_REG32_LOOP(HOSTCC_MODE, 0x100); - GET_REG32_LOOP(MEMARB_MODE, 0x10); - GET_REG32_LOOP(BUFMGR_MODE, 0x58); - GET_REG32_LOOP(RDMAC_MODE, 0x08); - GET_REG32_LOOP(WDMAC_MODE, 0x08); - GET_REG32_1(RX_CPU_MODE); - GET_REG32_1(RX_CPU_STATE); - GET_REG32_1(RX_CPU_PGMCTR); - GET_REG32_1(RX_CPU_HWBKPT); - GET_REG32_1(TX_CPU_MODE); - GET_REG32_1(TX_CPU_STATE); - GET_REG32_1(TX_CPU_PGMCTR); - GET_REG32_LOOP(GRCMBOX_INTERRUPT_0, 0x110); - GET_REG32_LOOP(FTQ_RESET, 0x120); - GET_REG32_LOOP(MSGINT_MODE, 0x0c); - GET_REG32_1(DMAC_MODE); - GET_REG32_LOOP(GRC_MODE, 0x4c); - if (tp->tg3_flags & TG3_FLAG_NVRAM) - GET_REG32_LOOP(NVRAM_CMD, 0x24); - -#undef __GET_REG32 -#undef GET_REG32_LOOP -#undef GET_REG32_1 + tg3_dump_legacy_regs(tp, (u32 *)_p); tg3_full_unlock(tp); } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 829a84ad80f2..99120100bf6a 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1954,6 +1954,8 @@ #define TG3_PCIE_PL_LO_PHYCTL5 0x00000014 #define TG3_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ 0x80000000 +#define TG3_REG_BLK_SIZE 0x00008000 + /* OTP bit definitions */ #define TG3_OTP_AGCTGT_MASK 0x000000e0 #define TG3_OTP_AGCTGT_SHIFT 1 -- cgit v1.2.3-58-ga151 From e64de4e6c660dae6d6370b3acb59d5d5cc9ecf20 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 13 Apr 2011 11:05:05 +0000 Subject: tg3: Dump registers when status block shows errors This patch monitors the error bit of the status word within the status block. If it is set, the driver will dump the driver state after validating the error and then reset the chip. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 40 +++++++++++++++++++++++++++++++++++++++- drivers/net/tg3.h | 3 +++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 72744353b1cb..b61b52f0a9fb 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -5259,6 +5259,40 @@ tx_recovery: return work_done; } +static void tg3_process_error(struct tg3 *tp) +{ + u32 val; + bool real_error = false; + + if (tp->tg3_flags & TG3_FLAG_ERROR_PROCESSED) + return; + + /* Check Flow Attention register */ + val = tr32(HOSTCC_FLOW_ATTN); + if (val & ~HOSTCC_FLOW_ATTN_MBUF_LWM) { + netdev_err(tp->dev, "FLOW Attention error. Resetting chip.\n"); + real_error = true; + } + + if (tr32(MSGINT_STATUS) & ~MSGINT_STATUS_MSI_REQ) { + netdev_err(tp->dev, "MSI Status error. Resetting chip.\n"); + real_error = true; + } + + if (tr32(RDMAC_STATUS) || tr32(WDMAC_STATUS)) { + netdev_err(tp->dev, "DMA Status error. Resetting chip.\n"); + real_error = true; + } + + if (!real_error) + return; + + tg3_dump_state(tp); + + tp->tg3_flags |= TG3_FLAG_ERROR_PROCESSED; + schedule_work(&tp->reset_task); +} + static int tg3_poll(struct napi_struct *napi, int budget) { struct tg3_napi *tnapi = container_of(napi, struct tg3_napi, napi); @@ -5267,6 +5301,9 @@ static int tg3_poll(struct napi_struct *napi, int budget) struct tg3_hw_status *sblk = tnapi->hw_status; while (1) { + if (sblk->status & SD_STATUS_ERROR) + tg3_process_error(tp); + tg3_poll_link(tp); work_done = tg3_poll_work(tnapi, work_done, budget); @@ -7316,7 +7353,8 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_restore_pci_state(tp); - tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING; + tp->tg3_flags &= ~(TG3_FLAG_CHIP_RESETTING | + TG3_FLAG_ERROR_PROCESSED); val = 0; if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 99120100bf6a..b3ccfcc9ffea 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1201,6 +1201,7 @@ #define HOSTCC_STATS_BLK_NIC_ADDR 0x00003c40 #define HOSTCC_STATUS_BLK_NIC_ADDR 0x00003c44 #define HOSTCC_FLOW_ATTN 0x00003c48 +#define HOSTCC_FLOW_ATTN_MBUF_LWM 0x00000040 /* 0x3c4c --> 0x3c50 unused */ #define HOSTCC_JUMBO_CON_IDX 0x00003c50 #define HOSTCC_STD_CON_IDX 0x00003c54 @@ -1611,6 +1612,7 @@ #define MSGINT_MODE_ONE_SHOT_DISABLE 0x00000020 #define MSGINT_MODE_MULTIVEC_EN 0x00000080 #define MSGINT_STATUS 0x00006004 +#define MSGINT_STATUS_MSI_REQ 0x00000001 #define MSGINT_FIFO 0x00006008 /* 0x600c --> 0x6400 unused */ @@ -2886,6 +2888,7 @@ struct tg3 { #define TG3_FLAG_TAGGED_STATUS 0x00000001 #define TG3_FLAG_TXD_MBOX_HWBUG 0x00000002 #define TG3_FLAG_USE_LINKCHG_REG 0x00000008 +#define TG3_FLAG_ERROR_PROCESSED 0x00000010 #define TG3_FLAG_ENABLE_ASF 0x00000020 #define TG3_FLAG_ASPM_WORKAROUND 0x00000040 #define TG3_FLAG_POLL_SERDES 0x00000080 -- cgit v1.2.3-58-ga151 From 48fa55a0a5e20b9e2a28a72c66c7027678cae6bb Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 13 Apr 2011 11:05:06 +0000 Subject: tg3: Automatically size stat/test string arrays This patch reimplements the size preprocessor constants of the stats and ethtool test string arrays. The size is calculated at compile time rather than using static constants. Signed-off-by: Matt Carlson Signed-off-by: Benjamin Li Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b61b52f0a9fb..9975cdb38831 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -165,11 +165,6 @@ #define TG3_RAW_IP_ALIGN 2 -/* number of ETHTOOL_GSTATS u64's */ -#define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64)) - -#define TG3_NUM_TEST 6 - #define TG3_FW_UPDATE_TIMEOUT_SEC 5 #define FIRMWARE_TG3 "tigon/tg3.bin" @@ -279,7 +274,7 @@ MODULE_DEVICE_TABLE(pci, tg3_pci_tbl); static const struct { const char string[ETH_GSTRING_LEN]; -} ethtool_stats_keys[TG3_NUM_STATS] = { +} ethtool_stats_keys[] = { { "rx_octets" }, { "rx_fragments" }, { "rx_ucast_packets" }, @@ -358,9 +353,12 @@ static const struct { { "nic_tx_threshold_hit" } }; +#define TG3_NUM_STATS ARRAY_SIZE(ethtool_stats_keys) + + static const struct { const char string[ETH_GSTRING_LEN]; -} ethtool_test_keys[TG3_NUM_TEST] = { +} ethtool_test_keys[] = { { "nvram test (online) " }, { "link test (online) " }, { "register test (offline)" }, @@ -369,6 +367,9 @@ static const struct { { "interrupt test (offline)" }, }; +#define TG3_NUM_TEST ARRAY_SIZE(ethtool_test_keys) + + static void tg3_write32(struct tg3 *tp, u32 off, u32 val) { writel(val, tp->regs + off); -- cgit v1.2.3-58-ga151 From 4852a8614f63999e38539ad16615054dcd20a05d Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 13 Apr 2011 11:05:07 +0000 Subject: tg3: Add jumbo frame loopback tests to selftest This patch adds jumbo frame loopback test support to the ethtool selftest. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 9975cdb38831..52dd516ba786 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10935,7 +10935,7 @@ static int tg3_test_memory(struct tg3 *tp) #define TG3_MAC_LOOPBACK 0 #define TG3_PHY_LOOPBACK 1 -static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) +static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) { u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key; u32 desc_idx, coal_now; @@ -11033,7 +11033,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) err = -EIO; - tx_len = 1514; + tx_len = pktsz; skb = netdev_alloc_skb(tp->dev, tx_len); if (!skb) return -ENOMEM; @@ -11042,7 +11042,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) memcpy(tx_data, tp->dev->dev_addr, 6); memset(tx_data + 6, 0x0, 8); - tw32(MAC_RX_MTU_SIZE, tx_len + 4); + tw32(MAC_RX_MTU_SIZE, tx_len + ETH_FCS_LEN); for (i = 14; i < tx_len; i++) tx_data[i] = (u8) (i & 0xff); @@ -11098,8 +11098,6 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) desc = &rnapi->rx_rcb[rx_start_idx]; desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; - if (opaque_key != RXD_OPAQUE_RING_STD) - goto out; if ((desc->err_vlan & RXD_ERR_MASK) != 0 && (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) @@ -11109,9 +11107,20 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) if (rx_len != tx_len) goto out; - rx_skb = tpr->rx_std_buffers[desc_idx].skb; + if (pktsz <= TG3_RX_STD_DMA_SZ - ETH_FCS_LEN) { + if (opaque_key != RXD_OPAQUE_RING_STD) + goto out; + + rx_skb = tpr->rx_std_buffers[desc_idx].skb; + map = dma_unmap_addr(&tpr->rx_std_buffers[desc_idx], mapping); + } else { + if (opaque_key != RXD_OPAQUE_RING_JUMBO) + goto out; + + rx_skb = tpr->rx_jmb_buffers[desc_idx].skb; + map = dma_unmap_addr(&tpr->rx_jmb_buffers[desc_idx], mapping); + } - map = dma_unmap_addr(&tpr->rx_std_buffers[desc_idx], mapping); pci_dma_sync_single_for_cpu(tp->pdev, map, rx_len, PCI_DMA_FROMDEVICE); for (i = 14; i < tx_len; i++) { @@ -11177,9 +11186,13 @@ static int tg3_test_loopback(struct tg3 *tp) CPMU_CTRL_LINK_AWARE_MODE)); } - if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK)) + if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_MAC_LOOPBACK)) err |= TG3_MAC_LOOPBACK_FAILED; + if ((tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) && + tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_MAC_LOOPBACK)) + err |= (TG3_MAC_LOOPBACK_FAILED << 2); + if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) { tw32(TG3_CPMU_CTRL, cpmuctrl); @@ -11189,8 +11202,11 @@ static int tg3_test_loopback(struct tg3 *tp) if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) && !(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { - if (tg3_run_loopback(tp, TG3_PHY_LOOPBACK)) + if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_PHY_LOOPBACK)) err |= TG3_PHY_LOOPBACK_FAILED; + if ((tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) && + tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_PHY_LOOPBACK)) + err |= (TG3_PHY_LOOPBACK_FAILED << 2); } /* Re-enable gphy autopowerdown. */ -- cgit v1.2.3-58-ga151 From c3e945006ab2295e9a3f4327aa74a502ad123fe6 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 13 Apr 2011 11:05:08 +0000 Subject: tg3: Add support for extended VPD blocks In some devices, the VPD block is relocated to a different area in NVRAM. The original location can still contain old, but still valid VPD data. This patch changes the code to look for an extended VPD block in NVRAM. If one is found, that block is used for all VPD operations instead. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 125 +++++++++++++++++++++++++++++++++++------------------- drivers/net/tg3.h | 2 + 2 files changed, 83 insertions(+), 44 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 52dd516ba786..10fa476fede3 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10416,6 +10416,81 @@ static void tg3_get_ethtool_stats(struct net_device *dev, memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats)); } +static __be32 * tg3_vpd_readblock(struct tg3 *tp) +{ + int i; + __be32 *buf; + u32 offset = 0, len = 0; + u32 magic, val; + + if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || + tg3_nvram_read(tp, 0, &magic)) + return NULL; + + if (magic == TG3_EEPROM_MAGIC) { + for (offset = TG3_NVM_DIR_START; + offset < TG3_NVM_DIR_END; + offset += TG3_NVM_DIRENT_SIZE) { + if (tg3_nvram_read(tp, offset, &val)) + return NULL; + + if ((val >> TG3_NVM_DIRTYPE_SHIFT) == + TG3_NVM_DIRTYPE_EXTVPD) + break; + } + + if (offset != TG3_NVM_DIR_END) { + len = (val & TG3_NVM_DIRTYPE_LENMSK) * 4; + if (tg3_nvram_read(tp, offset + 4, &offset)) + return NULL; + + offset = tg3_nvram_logical_addr(tp, offset); + } + } + + if (!offset || !len) { + offset = TG3_NVM_VPD_OFF; + len = TG3_NVM_VPD_LEN; + } + + buf = kmalloc(len, GFP_KERNEL); + if (buf == NULL) + return NULL; + + if (magic == TG3_EEPROM_MAGIC) { + for (i = 0; i < len; i += 4) { + /* The data is in little-endian format in NVRAM. + * Use the big-endian read routines to preserve + * the byte order as it exists in NVRAM. + */ + if (tg3_nvram_read_be32(tp, offset + i, &buf[i/4])) + goto error; + } + } else { + u8 *ptr; + ssize_t cnt; + unsigned int pos = 0; + + ptr = (u8 *)&buf[0]; + for (i = 0; pos < len && i < 3; i++, pos += cnt, ptr += cnt) { + cnt = pci_read_vpd(tp->pdev, pos, + len - pos, ptr); + if (cnt == -ETIMEDOUT || cnt == -EINTR) + cnt = 0; + else if (cnt < 0) + goto error; + } + if (pos != len) + goto error; + } + + return buf; + +error: + kfree(buf); + return NULL; +} + #define NVRAM_TEST_SIZE 0x100 #define NVRAM_SELFBOOT_FORMAT1_0_SIZE 0x14 #define NVRAM_SELFBOOT_FORMAT1_2_SIZE 0x18 @@ -10555,14 +10630,11 @@ static int tg3_test_nvram(struct tg3 *tp) if (csum != le32_to_cpu(buf[0xfc/4])) goto out; - for (i = 0; i < TG3_NVM_VPD_LEN; i += 4) { - /* The data is in little-endian format in NVRAM. - * Use the big-endian read routines to preserve - * the byte order as it exists in NVRAM. - */ - if (tg3_nvram_read_be32(tp, TG3_NVM_VPD_OFF + i, &buf[i/4])) - goto out; - } + kfree(buf); + + buf = tg3_vpd_readblock(tp); + if (!buf) + return -ENOMEM; i = pci_vpd_find_tag((u8 *)buf, 0, TG3_NVM_VPD_LEN, PCI_VPD_LRDT_RO_DATA); @@ -12905,46 +12977,11 @@ static void __devinit tg3_read_vpd(struct tg3 *tp) u8 *vpd_data; unsigned int block_end, rosize, len; int j, i = 0; - u32 magic; - - if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || - tg3_nvram_read(tp, 0x0, &magic)) - goto out_no_vpd; - vpd_data = kmalloc(TG3_NVM_VPD_LEN, GFP_KERNEL); + vpd_data = (u8 *)tg3_vpd_readblock(tp); if (!vpd_data) goto out_no_vpd; - if (magic == TG3_EEPROM_MAGIC) { - for (i = 0; i < TG3_NVM_VPD_LEN; i += 4) { - u32 tmp; - - /* The data is in little-endian format in NVRAM. - * Use the big-endian read routines to preserve - * the byte order as it exists in NVRAM. - */ - if (tg3_nvram_read_be32(tp, TG3_NVM_VPD_OFF + i, &tmp)) - goto out_not_found; - - memcpy(&vpd_data[i], &tmp, sizeof(tmp)); - } - } else { - ssize_t cnt; - unsigned int pos = 0; - - for (; pos < TG3_NVM_VPD_LEN && i < 3; i++, pos += cnt) { - cnt = pci_read_vpd(tp->pdev, pos, - TG3_NVM_VPD_LEN - pos, - &vpd_data[pos]); - if (cnt == -ETIMEDOUT || cnt == -EINTR) - cnt = 0; - else if (cnt < 0) - goto out_not_found; - } - if (pos != TG3_NVM_VPD_LEN) - goto out_not_found; - } - i = pci_vpd_find_tag(vpd_data, 0, TG3_NVM_VPD_LEN, PCI_VPD_LRDT_RO_DATA); if (i < 0) diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index b3ccfcc9ffea..224c3e0ec695 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2009,7 +2009,9 @@ #define TG3_NVM_DIR_END 0x78 #define TG3_NVM_DIRENT_SIZE 0xc #define TG3_NVM_DIRTYPE_SHIFT 24 +#define TG3_NVM_DIRTYPE_LENMSK 0x003fffff #define TG3_NVM_DIRTYPE_ASFINI 1 +#define TG3_NVM_DIRTYPE_EXTVPD 20 #define TG3_NVM_PTREV_BCVER 0x94 #define TG3_NVM_BCVER_MAJMSK 0x0000ff00 #define TG3_NVM_BCVER_MAJSFT 8 -- cgit v1.2.3-58-ga151 From c326de88b8ac7ed1cd1027017ba6079dbe91be49 Mon Sep 17 00:00:00 2001 From: "Mathieu J. Poirier" Date: Wed, 13 Apr 2011 17:13:00 -0700 Subject: net: allow shifted access in smsc911x V2 This is a revised patch that permits a shifted access to the LAN9221 registers. More specifically: It adds a shift parameter in the platform_data. It introduces an ops in smsc911x_data. A choice of access function to use at run-time. Four new shifted access function. Signed-off-by: Mathieu Poirier Signed-off-by: Alessandro Rubini Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 156 ++++++++++++++++++++++++++++++++++++++++++++--- include/linux/smsc911x.h | 1 + 2 files changed, 150 insertions(+), 7 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index b8faab7780da..c6d47d10590c 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -71,6 +71,17 @@ static int debug = 3; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); +struct smsc911x_data; + +struct smsc911x_ops { + u32 (*reg_read)(struct smsc911x_data *pdata, u32 reg); + void (*reg_write)(struct smsc911x_data *pdata, u32 reg, u32 val); + void (*rx_readfifo)(struct smsc911x_data *pdata, + unsigned int *buf, unsigned int wordcount); + void (*tx_writefifo)(struct smsc911x_data *pdata, + unsigned int *buf, unsigned int wordcount); +}; + struct smsc911x_data { void __iomem *ioaddr; @@ -118,8 +129,14 @@ struct smsc911x_data { unsigned int clear_bits_mask; unsigned int hashhi; unsigned int hashlo; + + /* register access functions */ + const struct smsc911x_ops *ops; }; +/* Easy access to information */ +#define __smsc_shift(pdata, reg) ((reg) << ((pdata)->config.shift)) + static inline u32 __smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg) { if (pdata->config.flags & SMSC911X_USE_32BIT) @@ -133,13 +150,29 @@ static inline u32 __smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg) return 0; } +static inline u32 +__smsc911x_reg_read_shift(struct smsc911x_data *pdata, u32 reg) +{ + if (pdata->config.flags & SMSC911X_USE_32BIT) + return readl(pdata->ioaddr + __smsc_shift(pdata, reg)); + + if (pdata->config.flags & SMSC911X_USE_16BIT) + return (readw(pdata->ioaddr + + __smsc_shift(pdata, reg)) & 0xFFFF) | + ((readw(pdata->ioaddr + + __smsc_shift(pdata, reg + 2)) & 0xFFFF) << 16); + + BUG(); + return 0; +} + static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg) { u32 data; unsigned long flags; spin_lock_irqsave(&pdata->dev_lock, flags); - data = __smsc911x_reg_read(pdata, reg); + data = pdata->ops->reg_read(pdata, reg); spin_unlock_irqrestore(&pdata->dev_lock, flags); return data; @@ -162,13 +195,32 @@ static inline void __smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg, BUG(); } +static inline void +__smsc911x_reg_write_shift(struct smsc911x_data *pdata, u32 reg, u32 val) +{ + if (pdata->config.flags & SMSC911X_USE_32BIT) { + writel(val, pdata->ioaddr + __smsc_shift(pdata, reg)); + return; + } + + if (pdata->config.flags & SMSC911X_USE_16BIT) { + writew(val & 0xFFFF, + pdata->ioaddr + __smsc_shift(pdata, reg)); + writew((val >> 16) & 0xFFFF, + pdata->ioaddr + __smsc_shift(pdata, reg + 2)); + return; + } + + BUG(); +} + static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg, u32 val) { unsigned long flags; spin_lock_irqsave(&pdata->dev_lock, flags); - __smsc911x_reg_write(pdata, reg, val); + pdata->ops->reg_write(pdata, reg, val); spin_unlock_irqrestore(&pdata->dev_lock, flags); } @@ -204,6 +256,40 @@ out: spin_unlock_irqrestore(&pdata->dev_lock, flags); } +/* Writes a packet to the TX_DATA_FIFO - shifted version */ +static inline void +smsc911x_tx_writefifo_shift(struct smsc911x_data *pdata, unsigned int *buf, + unsigned int wordcount) +{ + unsigned long flags; + + spin_lock_irqsave(&pdata->dev_lock, flags); + + if (pdata->config.flags & SMSC911X_SWAP_FIFO) { + while (wordcount--) + __smsc911x_reg_write_shift(pdata, TX_DATA_FIFO, + swab32(*buf++)); + goto out; + } + + if (pdata->config.flags & SMSC911X_USE_32BIT) { + writesl(pdata->ioaddr + __smsc_shift(pdata, + TX_DATA_FIFO), buf, wordcount); + goto out; + } + + if (pdata->config.flags & SMSC911X_USE_16BIT) { + while (wordcount--) + __smsc911x_reg_write_shift(pdata, + TX_DATA_FIFO, *buf++); + goto out; + } + + BUG(); +out: + spin_unlock_irqrestore(&pdata->dev_lock, flags); +} + /* Reads a packet out of the RX_DATA_FIFO */ static inline void smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf, @@ -236,6 +322,40 @@ out: spin_unlock_irqrestore(&pdata->dev_lock, flags); } +/* Reads a packet out of the RX_DATA_FIFO - shifted version */ +static inline void +smsc911x_rx_readfifo_shift(struct smsc911x_data *pdata, unsigned int *buf, + unsigned int wordcount) +{ + unsigned long flags; + + spin_lock_irqsave(&pdata->dev_lock, flags); + + if (pdata->config.flags & SMSC911X_SWAP_FIFO) { + while (wordcount--) + *buf++ = swab32(__smsc911x_reg_read_shift(pdata, + RX_DATA_FIFO)); + goto out; + } + + if (pdata->config.flags & SMSC911X_USE_32BIT) { + readsl(pdata->ioaddr + __smsc_shift(pdata, + RX_DATA_FIFO), buf, wordcount); + goto out; + } + + if (pdata->config.flags & SMSC911X_USE_16BIT) { + while (wordcount--) + *buf++ = __smsc911x_reg_read_shift(pdata, + RX_DATA_FIFO); + goto out; + } + + BUG(); +out: + spin_unlock_irqrestore(&pdata->dev_lock, flags); +} + /* waits for MAC not busy, with timeout. Only called by smsc911x_mac_read * and smsc911x_mac_write, so assumes mac_lock is held */ static int smsc911x_mac_complete(struct smsc911x_data *pdata) @@ -500,7 +620,7 @@ static int smsc911x_phy_check_loopbackpkt(struct smsc911x_data *pdata) wrsz += (u32)((ulong)pdata->loopback_tx_pkt & 0x3); wrsz >>= 2; - smsc911x_tx_writefifo(pdata, (unsigned int *)bufp, wrsz); + pdata->ops->tx_writefifo(pdata, (unsigned int *)bufp, wrsz); /* Wait till transmit is done */ i = 60; @@ -544,7 +664,7 @@ static int smsc911x_phy_check_loopbackpkt(struct smsc911x_data *pdata) rdsz += (u32)((ulong)pdata->loopback_rx_pkt & 0x3); rdsz >>= 2; - smsc911x_rx_readfifo(pdata, (unsigned int *)bufp, rdsz); + pdata->ops->rx_readfifo(pdata, (unsigned int *)bufp, rdsz); if (pktlength != (MIN_PACKET_SIZE + 4)) { SMSC_WARN(pdata, hw, "Unexpected packet size " @@ -1046,8 +1166,8 @@ static int smsc911x_poll(struct napi_struct *napi, int budget) /* Align IP on 16B boundary */ skb_reserve(skb, NET_IP_ALIGN); skb_put(skb, pktlength - 4); - smsc911x_rx_readfifo(pdata, (unsigned int *)skb->head, - pktwords); + pdata->ops->rx_readfifo(pdata, + (unsigned int *)skb->head, pktwords); skb->protocol = eth_type_trans(skb, dev); skb_checksum_none_assert(skb); netif_receive_skb(skb); @@ -1351,7 +1471,7 @@ static int smsc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) wrsz += (u32)((ulong)skb->data & 0x3); wrsz >>= 2; - smsc911x_tx_writefifo(pdata, (unsigned int *)bufp, wrsz); + pdata->ops->tx_writefifo(pdata, (unsigned int *)bufp, wrsz); freespace -= (skb->len + 32); dev_kfree_skb(skb); @@ -1957,6 +2077,22 @@ static int __devexit smsc911x_drv_remove(struct platform_device *pdev) return 0; } +/* standard register acces */ +static const struct smsc911x_ops standard_smsc911x_ops = { + .reg_read = __smsc911x_reg_read, + .reg_write = __smsc911x_reg_write, + .rx_readfifo = smsc911x_rx_readfifo, + .tx_writefifo = smsc911x_tx_writefifo, +}; + +/* shifted register access */ +static const struct smsc911x_ops shifted_smsc911x_ops = { + .reg_read = __smsc911x_reg_read_shift, + .reg_write = __smsc911x_reg_write_shift, + .rx_readfifo = smsc911x_rx_readfifo_shift, + .tx_writefifo = smsc911x_tx_writefifo_shift, +}; + static int __devinit smsc911x_drv_probe(struct platform_device *pdev) { struct net_device *dev; @@ -2026,6 +2162,12 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) goto out_free_netdev_2; } + /* assume standard, non-shifted, access to HW registers */ + pdata->ops = &standard_smsc911x_ops; + /* apply the right access if shifting is needed */ + if (config->shift) + pdata->ops = &shifted_smsc911x_ops; + retval = smsc911x_init(dev); if (retval < 0) goto out_unmap_io_3; diff --git a/include/linux/smsc911x.h b/include/linux/smsc911x.h index 7144e8aa1e41..4dde70e74822 100644 --- a/include/linux/smsc911x.h +++ b/include/linux/smsc911x.h @@ -29,6 +29,7 @@ struct smsc911x_platform_config { unsigned int irq_polarity; unsigned int irq_type; unsigned int flags; + unsigned int shift; phy_interface_t phy_interface; unsigned char mac[6]; }; -- cgit v1.2.3-58-ga151 From 7c158399c21e4eabb33965a5fc689ebbd2ded4f6 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 12 Mar 2011 11:56:02 +0000 Subject: igb: Add anti-spoofing feature documentation Add the documentation for the anti-spoofing feature in the HW. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher --- Documentation/networking/igb.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Documentation/networking/igb.txt b/Documentation/networking/igb.txt index 98953c0d5342..9a2a037194a5 100644 --- a/Documentation/networking/igb.txt +++ b/Documentation/networking/igb.txt @@ -93,6 +93,19 @@ Additional Configurations REQUIREMENTS: MSI-X support is required for Multiqueue. If MSI-X is not found, the system will fallback to MSI or to Legacy interrupts. + MAC and VLAN anti-spoofing feature + ---------------------------------- + When a malicious driver attempts to send a spoofed packet, it is dropped by + the hardware and not transmitted. An interrupt is sent to the PF driver + notifying it of the spoof attempt. + + When a spoofed packet is detected the PF driver will send the following + message to the system log (displayed by the "dmesg" command): + + Spoof event(s) detected on VF(n) + + Where n=the VF that attempted to do the spoofing. + Support ======= -- cgit v1.2.3-58-ga151 From 34a0326e3aaf1d67fe3de55e77e92961c6a9a847 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Tue, 5 Apr 2011 04:27:05 +0000 Subject: igb: fix typo in igb_validate_nvm_checksum_82580 Comment spelling fix. Signed-off-by: Stefan Assmann Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_82575.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 6b256c275e10..0cd41c49bc17 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -1877,7 +1877,7 @@ static s32 igb_validate_nvm_checksum_82580(struct e1000_hw *hw) } if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) { - /* if chekcsums compatibility bit is set validate checksums + /* if checksums compatibility bit is set validate checksums * for all 4 ports. */ eeprom_regions_count = 4; } @@ -1988,6 +1988,7 @@ static s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw) out: return ret_val; } + /** * igb_set_eee_i350 - Enable/disable EEE support * @hw: pointer to the HW structure -- cgit v1.2.3-58-ga151 From 563988dcfe706457ec7049d59e18d6147179bb0a Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Tue, 5 Apr 2011 04:27:15 +0000 Subject: igb: introduce igb_thermal_sensor_event for sensor checking The code for thermal sensor checking should be wrapped into a function. Signed-off-by: Stefan Assmann Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/igb_main.c | 67 +++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 0dfd1b93829e..cdfd57271051 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3532,6 +3532,25 @@ bool igb_has_link(struct igb_adapter *adapter) return link_active; } +static bool igb_thermal_sensor_event(struct e1000_hw *hw, u32 event) +{ + bool ret = false; + u32 ctrl_ext, thstat; + + /* check for thermal sensor event on i350, copper only */ + if (hw->mac.type == e1000_i350) { + thstat = rd32(E1000_THSTAT); + ctrl_ext = rd32(E1000_CTRL_EXT); + + if ((hw->phy.media_type == e1000_media_type_copper) && + !(ctrl_ext & E1000_CTRL_EXT_LINK_MODE_SGMII)) { + ret = !!(thstat & event); + } + } + + return ret; +} + /** * igb_watchdog - Timer Call-back * @data: pointer to adapter cast into an unsigned long @@ -3550,7 +3569,7 @@ static void igb_watchdog_task(struct work_struct *work) watchdog_task); struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; - u32 link, ctrl_ext, thstat; + u32 link; int i; link = igb_has_link(adapter); @@ -3574,25 +3593,14 @@ static void igb_watchdog_task(struct work_struct *work) ((ctrl & E1000_CTRL_RFCE) ? "RX" : ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None"))); - /* check for thermal sensor event on i350, - * copper only */ - if (hw->mac.type == e1000_i350) { - thstat = rd32(E1000_THSTAT); - ctrl_ext = rd32(E1000_CTRL_EXT); - if ((hw->phy.media_type == - e1000_media_type_copper) && !(ctrl_ext & - E1000_CTRL_EXT_LINK_MODE_SGMII)) { - if (thstat & - E1000_THSTAT_LINK_THROTTLE) { - printk(KERN_INFO "igb: %s The " - "network adapter link " - "speed was downshifted " - "because it " - "overheated.\n", - netdev->name); - } - } + /* check for thermal sensor event */ + if (igb_thermal_sensor_event(hw, E1000_THSTAT_LINK_THROTTLE)) { + printk(KERN_INFO "igb: %s The network adapter " + "link speed was downshifted " + "because it overheated.\n", + netdev->name); } + /* adjust timeout factor according to speed/duplex */ adapter->tx_timeout_factor = 1; switch (adapter->link_speed) { @@ -3618,22 +3626,15 @@ static void igb_watchdog_task(struct work_struct *work) if (netif_carrier_ok(netdev)) { adapter->link_speed = 0; adapter->link_duplex = 0; - /* check for thermal sensor event on i350 - * copper only*/ - if (hw->mac.type == e1000_i350) { - thstat = rd32(E1000_THSTAT); - ctrl_ext = rd32(E1000_CTRL_EXT); - if ((hw->phy.media_type == - e1000_media_type_copper) && !(ctrl_ext & - E1000_CTRL_EXT_LINK_MODE_SGMII)) { - if (thstat & E1000_THSTAT_PWR_DOWN) { - printk(KERN_ERR "igb: %s The " - "network adapter was stopped " - "because it overheated.\n", + + /* check for thermal sensor event */ + if (igb_thermal_sensor_event(hw, E1000_THSTAT_PWR_DOWN)) { + printk(KERN_ERR "igb: %s The network adapter " + "was stopped because it " + "overheated.\n", netdev->name); - } - } } + /* Links status message must follow this format */ printk(KERN_INFO "igb: %s NIC Link is Down\n", netdev->name); -- cgit v1.2.3-58-ga151 From 1bba4386ab4f67a53c9649268dd9c83bc6110a9b Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Sat, 19 Mar 2011 00:27:20 +0000 Subject: e1000e: convert short duration msleep() to usleep_range() With durations less than 20ms, the jiffies or legacy timer backed msleep() may sleep ~20ms which might not be what the caller expects. Instead, it is recommended to use the hrtimers backed usleep_range(). For more, see Documentation/timers/timers-howto.txt. Issues reported by checkpatch. In addition, remove unnecessary sleep in e1000e_write_nvm_spi(). Signed-off-by: Bruce Allan Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/e1000e/82571.c | 10 +++++----- drivers/net/e1000e/es2lan.c | 4 ++-- drivers/net/e1000e/ethtool.c | 20 ++++++++++---------- drivers/net/e1000e/ich8lan.c | 12 ++++++------ drivers/net/e1000e/lib.c | 10 ++++------ drivers/net/e1000e/netdev.c | 8 ++++---- drivers/net/e1000e/phy.c | 4 ++-- 7 files changed, 33 insertions(+), 35 deletions(-) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 89a69035e538..9fedbca66dfd 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -594,7 +594,7 @@ static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw) extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; - msleep(2); + usleep_range(2000, 4000); i++; } while (i < MDIO_OWNERSHIP_TIMEOUT); @@ -816,7 +816,7 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw) /* Check for pending operations. */ for (i = 0; i < E1000_FLASH_UPDATES; i++) { - msleep(1); + usleep_range(1000, 2000); if ((er32(EECD) & E1000_EECD_FLUPD) == 0) break; } @@ -840,7 +840,7 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw) ew32(EECD, eecd); for (i = 0; i < E1000_FLASH_UPDATES; i++) { - msleep(1); + usleep_range(1000, 2000); if ((er32(EECD) & E1000_EECD_FLUPD) == 0) break; } @@ -930,7 +930,7 @@ static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw) if (er32(EEMNGCTL) & E1000_NVM_CFG_DONE_PORT_0) break; - msleep(1); + usleep_range(1000, 2000); timeout--; } if (!timeout) { @@ -1037,7 +1037,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) ew32(TCTL, E1000_TCTL_PSP); e1e_flush(); - msleep(10); + usleep_range(10000, 20000); /* * Must acquire the MDIO ownership before MAC reset. diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c index 2fefa820302b..0279695b6942 100644 --- a/drivers/net/e1000e/es2lan.c +++ b/drivers/net/e1000e/es2lan.c @@ -612,7 +612,7 @@ static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw) while (timeout) { if (er32(EEMNGCTL) & mask) break; - msleep(1); + usleep_range(1000, 2000); timeout--; } if (!timeout) { @@ -802,7 +802,7 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) ew32(TCTL, E1000_TCTL_PSP); e1e_flush(); - msleep(10); + usleep_range(10000, 20000); ctrl = er32(CTRL); diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 07f09e96e453..5b4cf9076bac 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -253,7 +253,7 @@ static int e1000_set_settings(struct net_device *netdev, } while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - msleep(1); + usleep_range(1000, 2000); if (ecmd->autoneg == AUTONEG_ENABLE) { hw->mac.autoneg = 1; @@ -317,7 +317,7 @@ static int e1000_set_pauseparam(struct net_device *netdev, adapter->fc_autoneg = pause->autoneg; while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - msleep(1); + usleep_range(1000, 2000); if (adapter->fc_autoneg == AUTONEG_ENABLE) { hw->fc.requested_mode = e1000_fc_default; @@ -673,7 +673,7 @@ static int e1000_set_ringparam(struct net_device *netdev, return -EINVAL; while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - msleep(1); + usleep_range(1000, 2000); if (netif_running(adapter->netdev)) e1000e_down(adapter); @@ -952,7 +952,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) /* Disable all the interrupts */ ew32(IMC, 0xFFFFFFFF); - msleep(10); + usleep_range(10000, 20000); /* Test each interrupt */ for (i = 0; i < 10; i++) { @@ -984,7 +984,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) adapter->test_icr = 0; ew32(IMC, mask); ew32(ICS, mask); - msleep(10); + usleep_range(10000, 20000); if (adapter->test_icr & mask) { *data = 3; @@ -1002,7 +1002,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) adapter->test_icr = 0; ew32(IMS, mask); ew32(ICS, mask); - msleep(10); + usleep_range(10000, 20000); if (!(adapter->test_icr & mask)) { *data = 4; @@ -1020,7 +1020,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) adapter->test_icr = 0; ew32(IMC, ~mask & 0x00007FFF); ew32(ICS, ~mask & 0x00007FFF); - msleep(10); + usleep_range(10000, 20000); if (adapter->test_icr) { *data = 5; @@ -1031,7 +1031,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) /* Disable all the interrupts */ ew32(IMC, 0xFFFFFFFF); - msleep(10); + usleep_range(10000, 20000); /* Unhook test interrupt handler */ free_irq(irq, netdev); @@ -1406,7 +1406,7 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter) */ #define E1000_SERDES_LB_ON 0x410 ew32(SCTL, E1000_SERDES_LB_ON); - msleep(10); + usleep_range(10000, 20000); return 0; } @@ -1501,7 +1501,7 @@ static void e1000_loopback_cleanup(struct e1000_adapter *adapter) hw->phy.media_type == e1000_media_type_internal_serdes) { #define E1000_SERDES_LB_OFF 0x400 ew32(SCTL, E1000_SERDES_LB_OFF); - msleep(10); + usleep_range(10000, 20000); break; } /* Fall Through */ diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index ce1dbfdca112..06ff884bc2c7 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -338,7 +338,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) /* Ungate automatic PHY configuration on non-managed 82579 */ if ((hw->mac.type == e1000_pch2lan) && !(fwsm & E1000_ICH_FWSM_FW_VALID)) { - msleep(10); + usleep_range(10000, 20000); e1000_gate_hw_phy_config_ich8lan(hw, false); } @@ -427,7 +427,7 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) phy->id = 0; while ((e1000_phy_unknown == e1000e_get_phy_type_from_id(phy->id)) && (i++ < 100)) { - msleep(1); + usleep_range(1000, 2000); ret_val = e1000e_get_phy_id(hw); if (ret_val) return ret_val; @@ -1704,7 +1704,7 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) goto out; /* Allow time for h/w to get to quiescent state after reset */ - msleep(10); + usleep_range(10000, 20000); /* Perform any necessary post-reset workarounds */ switch (hw->mac.type) { @@ -1737,7 +1737,7 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) if (hw->mac.type == e1000_pch2lan) { /* Ungate automatic PHY configuration on non-managed 82579 */ if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { - msleep(10); + usleep_range(10000, 20000); e1000_gate_hw_phy_config_ich8lan(hw, false); } @@ -2532,7 +2532,7 @@ release: */ if (!ret_val) { e1000e_reload_nvm(hw); - msleep(10); + usleep_range(10000, 20000); } out: @@ -3009,7 +3009,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ew32(TCTL, E1000_TCTL_PSP); e1e_flush(); - msleep(10); + usleep_range(10000, 20000); /* Workaround for ICH8 bit corruption issue in FIFO memory */ if (hw->mac.type == e1000_ich8lan) { diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index 96921de5df2e..30ef8fa4968c 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -868,7 +868,7 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) * milliseconds even if the other end is doing it in SW). */ for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { - msleep(10); + usleep_range(10000, 20000); status = er32(STATUS); if (status & E1000_STATUS_LU) break; @@ -930,7 +930,7 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw) ew32(CTRL, ctrl); e1e_flush(); - msleep(1); + usleep_range(1000, 2000); /* * For these adapters, the SW definable pin 1 is set when the optics @@ -1385,7 +1385,7 @@ s32 e1000e_get_auto_rd_done(struct e1000_hw *hw) while (i < AUTO_READ_DONE_TIMEOUT) { if (er32(EECD) & E1000_EECD_AUTO_RD) break; - msleep(1); + usleep_range(1000, 2000); i++; } @@ -2087,8 +2087,6 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) if (ret_val) return ret_val; - msleep(10); - while (widx < words) { u8 write_opcode = NVM_WRITE_OPCODE_SPI; @@ -2132,7 +2130,7 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) } } - msleep(10); + usleep_range(10000, 20000); nvm->ops.release(hw); return 0; } diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 506a0a0043b3..909c8de58c15 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2902,7 +2902,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) rctl = er32(RCTL); ew32(RCTL, rctl & ~E1000_RCTL_EN); e1e_flush(); - msleep(10); + usleep_range(10000, 20000); if (adapter->flags2 & FLAG2_DMA_BURST) { /* @@ -3383,7 +3383,7 @@ void e1000e_down(struct e1000_adapter *adapter) ew32(TCTL, tctl); /* flush both disables and wait for them to finish */ e1e_flush(); - msleep(10); + usleep_range(10000, 20000); napi_disable(&adapter->napi); e1000_irq_disable(adapter); @@ -3418,7 +3418,7 @@ void e1000e_reinit_locked(struct e1000_adapter *adapter) { might_sleep(); while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - msleep(1); + usleep_range(1000, 2000); e1000e_down(adapter); e1000e_up(adapter); clear_bit(__E1000_RESETTING, &adapter->state); @@ -5028,7 +5028,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) } while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - msleep(1); + usleep_range(1000, 2000); /* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */ adapter->max_frame_size = max_frame; e_info("changing MTU from %d to %d\n", netdev->mtu, new_mtu); diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 6ae31fcfb629..484774c13c21 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -2372,7 +2372,7 @@ s32 e1000e_determine_phy_address(struct e1000_hw *hw) ret_val = 0; goto out; } - msleep(1); + usleep_range(1000, 2000); i++; } while (i < 10); } @@ -2740,7 +2740,7 @@ void e1000_power_down_phy_copper(struct e1000_hw *hw) e1e_rphy(hw, PHY_CONTROL, &mii_reg); mii_reg |= MII_CR_POWER_DOWN; e1e_wphy(hw, PHY_CONTROL, mii_reg); - msleep(1); + usleep_range(1000, 2000); } /** -- cgit v1.2.3-58-ga151 From a5cc764206a3d01dce8ebc17b4e1534afb53c495 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Sat, 19 Mar 2011 00:31:23 +0000 Subject: e1000e: PCIe link speed in GT/s, not GB/s Correct the log message when driver loads. Signed-off-by: Bruce Allan Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/e1000e/netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 909c8de58c15..99c8c7c0b1fb 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -5714,7 +5714,7 @@ static void e1000_print_device_info(struct e1000_adapter *adapter) u8 pba_str[E1000_PBANUM_LENGTH]; /* print bus type/speed/width info */ - e_info("(PCI Express:2.5GB/s:%s) %pM\n", + e_info("(PCI Express:2.5GT/s:%s) %pM\n", /* bus width */ ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" : "Width x1"), -- cgit v1.2.3-58-ga151 From 86d70e532c352bd309dab5f1d18d113f441cb3ae Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 25 Mar 2011 16:01:01 +0000 Subject: e1000e: convert to new VLAN model This switches the e1000e driver to use the new VLAN interfaces. CC: Jesse Gross Signed-off-by: Jeff Kirsher Tested-by: Jeff Pieper --- drivers/net/e1000e/e1000.h | 4 +- drivers/net/e1000e/ethtool.c | 26 +++++++ drivers/net/e1000e/netdev.c | 170 +++++++++++++++++++++++-------------------- 3 files changed, 119 insertions(+), 81 deletions(-) diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 00bf595ebd67..500896e42206 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -31,6 +31,7 @@ #ifndef _E1000_H_ #define _E1000_H_ +#include #include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include "hw.h" @@ -280,7 +282,7 @@ struct e1000_adapter { const struct e1000_info *ei; - struct vlan_group *vlgrp; + unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; u32 bd_number; u32 rx_buffer_len; u16 mng_vlan_id; diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 5b4cf9076bac..a31d280ffb6d 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -2020,6 +2020,31 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset, } } +static int e1000e_set_flags(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + bool need_reset = false; + int rc; + + need_reset = (data & ETH_FLAG_RXVLAN) != + (netdev->features & NETIF_F_HW_VLAN_RX); + + rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_RXVLAN | + ETH_FLAG_TXVLAN); + + if (rc) + return rc; + + if (need_reset) { + if (netif_running(netdev)) + e1000e_reinit_locked(adapter); + else + e1000e_reset(adapter); + } + + return 0; +} + static const struct ethtool_ops e1000_ethtool_ops = { .get_settings = e1000_get_settings, .set_settings = e1000_set_settings, @@ -2055,6 +2080,7 @@ static const struct ethtool_ops e1000_ethtool_ops = { .get_coalesce = e1000_get_coalesce, .set_coalesce = e1000_set_coalesce, .get_flags = ethtool_op_get_flags, + .set_flags = e1000e_set_flags, }; void e1000e_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 99c8c7c0b1fb..8812eb28e099 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -459,13 +459,13 @@ static void e1000_receive_skb(struct e1000_adapter *adapter, struct net_device *netdev, struct sk_buff *skb, u8 status, __le16 vlan) { + u16 tag = le16_to_cpu(vlan); skb->protocol = eth_type_trans(skb, netdev); - if (adapter->vlgrp && (status & E1000_RXD_STAT_VP)) - vlan_gro_receive(&adapter->napi, adapter->vlgrp, - le16_to_cpu(vlan), skb); - else - napi_gro_receive(&adapter->napi, skb); + if (status & E1000_RXD_STAT_VP) + __vlan_hwaccel_put_tag(skb, tag); + + napi_gro_receive(&adapter->napi, skb); } /** @@ -2433,6 +2433,8 @@ static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid) vfta |= (1 << (vid & 0x1F)); hw->mac.ops.write_vfta(hw, index, vfta); } + + set_bit(vid, adapter->active_vlans); } static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) @@ -2441,13 +2443,6 @@ static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) struct e1000_hw *hw = &adapter->hw; u32 vfta, index; - if (!test_bit(__E1000_DOWN, &adapter->state)) - e1000_irq_disable(adapter); - vlan_group_set_device(adapter->vlgrp, vid, NULL); - - if (!test_bit(__E1000_DOWN, &adapter->state)) - e1000_irq_enable(adapter); - if ((adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && (vid == adapter->mng_vlan_id)) { @@ -2463,93 +2458,105 @@ static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) vfta &= ~(1 << (vid & 0x1F)); hw->mac.ops.write_vfta(hw, index, vfta); } + + clear_bit(vid, adapter->active_vlans); } -static void e1000_update_mng_vlan(struct e1000_adapter *adapter) +/** + * e1000e_vlan_filter_disable - helper to disable hw VLAN filtering + * @adapter: board private structure to initialize + **/ +static void e1000e_vlan_filter_disable(struct e1000_adapter *adapter) { struct net_device *netdev = adapter->netdev; - u16 vid = adapter->hw.mng_cookie.vlan_id; - u16 old_vid = adapter->mng_vlan_id; - - if (!adapter->vlgrp) - return; + struct e1000_hw *hw = &adapter->hw; + u32 rctl; - if (!vlan_group_get_device(adapter->vlgrp, vid)) { - adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; - if (adapter->hw.mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN) { - e1000_vlan_rx_add_vid(netdev, vid); - adapter->mng_vlan_id = vid; + if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { + /* disable VLAN receive filtering */ + rctl = er32(RCTL); + rctl &= ~(E1000_RCTL_VFE | E1000_RCTL_CFIEN); + ew32(RCTL, rctl); + + if (adapter->mng_vlan_id != (u16)E1000_MNG_VLAN_NONE) { + e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); + adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; } - - if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && - (vid != old_vid) && - !vlan_group_get_device(adapter->vlgrp, old_vid)) - e1000_vlan_rx_kill_vid(netdev, old_vid); - } else { - adapter->mng_vlan_id = vid; } } +/** + * e1000e_vlan_filter_enable - helper to enable HW VLAN filtering + * @adapter: board private structure to initialize + **/ +static void e1000e_vlan_filter_enable(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 rctl; + + if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { + /* enable VLAN receive filtering */ + rctl = er32(RCTL); + rctl |= E1000_RCTL_VFE; + rctl &= ~E1000_RCTL_CFIEN; + ew32(RCTL, rctl); + } +} -static void e1000_vlan_rx_register(struct net_device *netdev, - struct vlan_group *grp) +/** + * e1000e_vlan_strip_enable - helper to disable HW VLAN stripping + * @adapter: board private structure to initialize + **/ +static void e1000e_vlan_strip_disable(struct e1000_adapter *adapter) { - struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - u32 ctrl, rctl; + u32 ctrl; - if (!test_bit(__E1000_DOWN, &adapter->state)) - e1000_irq_disable(adapter); - adapter->vlgrp = grp; + /* disable VLAN tag insert/strip */ + ctrl = er32(CTRL); + ctrl &= ~E1000_CTRL_VME; + ew32(CTRL, ctrl); +} - if (grp) { - /* enable VLAN tag insert/strip */ - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_VME; - ew32(CTRL, ctrl); +/** + * e1000e_vlan_strip_enable - helper to enable HW VLAN stripping + * @adapter: board private structure to initialize + **/ +static void e1000e_vlan_strip_enable(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 ctrl; - if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { - /* enable VLAN receive filtering */ - rctl = er32(RCTL); - rctl &= ~E1000_RCTL_CFIEN; - ew32(RCTL, rctl); - e1000_update_mng_vlan(adapter); - } - } else { - /* disable VLAN tag insert/strip */ - ctrl = er32(CTRL); - ctrl &= ~E1000_CTRL_VME; - ew32(CTRL, ctrl); + /* enable VLAN tag insert/strip */ + ctrl = er32(CTRL); + ctrl |= E1000_CTRL_VME; + ew32(CTRL, ctrl); +} - if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { - if (adapter->mng_vlan_id != - (u16)E1000_MNG_VLAN_NONE) { - e1000_vlan_rx_kill_vid(netdev, - adapter->mng_vlan_id); - adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; - } - } +static void e1000_update_mng_vlan(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + u16 vid = adapter->hw.mng_cookie.vlan_id; + u16 old_vid = adapter->mng_vlan_id; + + if (adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN) { + e1000_vlan_rx_add_vid(netdev, vid); + adapter->mng_vlan_id = vid; } - if (!test_bit(__E1000_DOWN, &adapter->state)) - e1000_irq_enable(adapter); + if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && (vid != old_vid)) + e1000_vlan_rx_kill_vid(netdev, old_vid); } static void e1000_restore_vlan(struct e1000_adapter *adapter) { u16 vid; - e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp); - - if (!adapter->vlgrp) - return; + e1000_vlan_rx_add_vid(adapter->netdev, 0); - for (vid = 0; vid < VLAN_N_VID; vid++) { - if (!vlan_group_get_device(adapter->vlgrp, vid)) - continue; + for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) e1000_vlan_rx_add_vid(adapter->netdev, vid); - } } static void e1000_init_manageability_pt(struct e1000_adapter *adapter) @@ -3039,6 +3046,8 @@ static void e1000_set_multi(struct net_device *netdev) if (netdev->flags & IFF_PROMISC) { rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); rctl &= ~E1000_RCTL_VFE; + /* Do not hardware filter VLANs in promisc mode */ + e1000e_vlan_filter_disable(adapter); } else { if (netdev->flags & IFF_ALLMULTI) { rctl |= E1000_RCTL_MPE; @@ -3046,8 +3055,7 @@ static void e1000_set_multi(struct net_device *netdev) } else { rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); } - if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) - rctl |= E1000_RCTL_VFE; + e1000e_vlan_filter_enable(adapter); } ew32(RCTL, rctl); @@ -3072,6 +3080,11 @@ static void e1000_set_multi(struct net_device *netdev) */ e1000_update_mc_addr_list(hw, NULL, 0); } + + if (netdev->features & NETIF_F_HW_VLAN_RX) + e1000e_vlan_strip_enable(adapter); + else + e1000e_vlan_strip_disable(adapter); } /** @@ -3721,10 +3734,8 @@ static int e1000_close(struct net_device *netdev) * kill manageability vlan ID if supported, but not if a vlan with * the same ID is registered on the host OS (let 8021q kill it) */ - if ((adapter->hw.mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && - !(adapter->vlgrp && - vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) + if (adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN) e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); /* @@ -5759,7 +5770,6 @@ static const struct net_device_ops e1000e_netdev_ops = { .ndo_tx_timeout = e1000_tx_timeout, .ndo_validate_addr = eth_validate_addr, - .ndo_vlan_rx_register = e1000_vlan_rx_register, .ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = e1000_vlan_rx_kill_vid, #ifdef CONFIG_NET_POLL_CONTROLLER -- cgit v1.2.3-58-ga151 From 2084b114e3fb0d84e5882f5ee6c7039be52da715 Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Tue, 5 Apr 2011 04:27:43 +0000 Subject: e1000e: fix stats locking in e1000_watchdog_task Just move the unlock down a bit because it unlocks too early leaving a chance for get_stats64() run in parallel while it is still accessing the stats. Signed-off-by: Flavio Leitner Acked-by: Bruce Allan Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/e1000e/netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 8812eb28e099..8a3145e9aa3e 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -4339,7 +4339,6 @@ static void e1000_watchdog_task(struct work_struct *work) link_up: spin_lock(&adapter->stats64_lock); e1000e_update_stats(adapter); - spin_unlock(&adapter->stats64_lock); mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; adapter->tpt_old = adapter->stats.tpt; @@ -4350,6 +4349,7 @@ link_up: adapter->gorc_old = adapter->stats.gorc; adapter->gotc = adapter->stats.gotc - adapter->gotc_old; adapter->gotc_old = adapter->stats.gotc; + spin_unlock(&adapter->stats64_lock); e1000e_update_adaptive(&adapter->hw); -- cgit v1.2.3-58-ga151 From 78cd29d5a92ae5067377ad42089f2c8781312f4a Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Thu, 24 Mar 2011 03:09:03 +0000 Subject: e1000e: If ASPM L0s needs to be disabled, do it prior to enabling device Based on a patch from Naga Chumbalkar : If ASPM L0s needs to be disabled due to HW errata, do it prior to "enabling" the device. This way if the kernel ever defaults its aspm_policy to POLICY_POWERSAVE, then the e1000e driver will get a chance to disable ASPM on the misbehaving device *prior* to calling pci_enable_device_mem(). This will be useful in situations where the BIOS indicates ASPM support on the server by clearing the ACPI FADT "ASPM Controls" bit. Note: The kernel (2.6.38) currently uses the BIOS "default" as its aspm_policy. However, Linux distros can diverge from that and set the default to "powersave". v2: o cleanup namespace pollution of e1000e_disable_aspm(), o fix type and initialization of the new aspm_disable_flag in a few functions, and o redefine FLAG2_DISABLE_ASPM_L0S to the first unused bit in adapter->flags2. Signed-off-by: Bruce Allan Cc: Naga Chumbalkar Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/e1000e/82571.c | 10 +++++----- drivers/net/e1000e/e1000.h | 2 +- drivers/net/e1000e/netdev.c | 29 ++++++++++++++++++++++++----- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 9fedbca66dfd..ae07d37903ba 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -431,9 +431,6 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter) case e1000_82573: case e1000_82574: case e1000_82583: - /* Disable ASPM L0s due to hardware errata */ - e1000e_disable_aspm(adapter->pdev, PCIE_LINK_STATE_L0S); - if (pdev->device == E1000_DEV_ID_82573L) { adapter->flags |= FLAG_HAS_JUMBO_FRAMES; adapter->max_hw_frame_size = DEFAULT_JUMBO; @@ -2066,7 +2063,8 @@ struct e1000_info e1000_82573_info = { | FLAG_HAS_SMART_POWER_DOWN | FLAG_HAS_AMT | FLAG_HAS_SWSM_ON_LOAD, - .flags2 = FLAG2_DISABLE_ASPM_L1, + .flags2 = FLAG2_DISABLE_ASPM_L1 + | FLAG2_DISABLE_ASPM_L0S, .pba = 20, .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, .get_variants = e1000_get_variants_82571, @@ -2086,7 +2084,8 @@ struct e1000_info e1000_82574_info = { | FLAG_HAS_SMART_POWER_DOWN | FLAG_HAS_AMT | FLAG_HAS_CTRLEXT_ON_LOAD, - .flags2 = FLAG2_CHECK_PHY_HANG, + .flags2 = FLAG2_CHECK_PHY_HANG + | FLAG2_DISABLE_ASPM_L0S, .pba = 32, .max_hw_frame_size = DEFAULT_JUMBO, .get_variants = e1000_get_variants_82571, @@ -2104,6 +2103,7 @@ struct e1000_info e1000_82583_info = { | FLAG_HAS_SMART_POWER_DOWN | FLAG_HAS_AMT | FLAG_HAS_CTRLEXT_ON_LOAD, + .flags2 = FLAG2_DISABLE_ASPM_L0S, .pba = 32, .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, .get_variants = e1000_get_variants_82571, diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 500896e42206..3be5478dfdf1 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -458,6 +458,7 @@ struct e1000_info { #define FLAG2_HAS_PHY_STATS (1 << 4) #define FLAG2_HAS_EEE (1 << 5) #define FLAG2_DMA_BURST (1 << 6) +#define FLAG2_DISABLE_ASPM_L0S (1 << 7) #define FLAG2_DISABLE_AIM (1 << 8) #define FLAG2_CHECK_PHY_HANG (1 << 9) @@ -504,7 +505,6 @@ extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); extern void e1000e_get_hw_control(struct e1000_adapter *adapter); extern void e1000e_release_hw_control(struct e1000_adapter *adapter); -extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state); extern unsigned int copybreak; diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 8a3145e9aa3e..4deb67d98e36 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -58,6 +58,8 @@ char e1000e_driver_name[] = "e1000e"; const char e1000e_driver_version[] = DRV_VERSION; +static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state); + static const struct e1000_info *e1000_info_tbl[] = { [board_82571] = &e1000_82571_info, [board_82572] = &e1000_82572_info, @@ -5384,7 +5386,7 @@ static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16); } #endif -void e1000e_disable_aspm(struct pci_dev *pdev, u16 state) +static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state) { dev_info(&pdev->dev, "Disabling ASPM %s %s\n", (state & PCIE_LINK_STATE_L0S) ? "L0s" : "", @@ -5404,13 +5406,19 @@ static int __e1000_resume(struct pci_dev *pdev) struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; + u16 aspm_disable_flag = 0; u32 err; + if (adapter->flags2 & FLAG2_DISABLE_ASPM_L0S) + aspm_disable_flag = PCIE_LINK_STATE_L0S; + if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) + aspm_disable_flag |= PCIE_LINK_STATE_L1; + if (aspm_disable_flag) + e1000e_disable_aspm(pdev, aspm_disable_flag); + pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); pci_save_state(pdev); - if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) - e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1); e1000e_set_interrupt_capability(adapter); if (netif_running(netdev)) { @@ -5654,11 +5662,17 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; + u16 aspm_disable_flag = 0; int err; pci_ers_result_t result; + if (adapter->flags2 & FLAG2_DISABLE_ASPM_L0S) + aspm_disable_flag = PCIE_LINK_STATE_L0S; if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) - e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1); + aspm_disable_flag |= PCIE_LINK_STATE_L1; + if (aspm_disable_flag) + e1000e_disable_aspm(pdev, aspm_disable_flag); + err = pci_enable_device_mem(pdev); if (err) { dev_err(&pdev->dev, @@ -5799,12 +5813,17 @@ static int __devinit e1000_probe(struct pci_dev *pdev, resource_size_t flash_start, flash_len; static int cards_found; + u16 aspm_disable_flag = 0; int i, err, pci_using_dac; u16 eeprom_data = 0; u16 eeprom_apme_mask = E1000_EEPROM_APME; + if (ei->flags2 & FLAG2_DISABLE_ASPM_L0S) + aspm_disable_flag = PCIE_LINK_STATE_L0S; if (ei->flags2 & FLAG2_DISABLE_ASPM_L1) - e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1); + aspm_disable_flag |= PCIE_LINK_STATE_L1; + if (aspm_disable_flag) + e1000e_disable_aspm(pdev, aspm_disable_flag); err = pci_enable_device_mem(pdev); if (err) -- cgit v1.2.3-58-ga151 From c8ca76ebc6e50752c5311b92bb9aef7edb324577 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Sat, 12 Mar 2011 03:50:53 +0000 Subject: ixgbe: DCB, further cleanups to app configuration With the app data on the kernel dcb_app list we no longer need to specifically handle them in ixgbe for the CEE case. So now we can remove app handling logic and check when the hw is configured if the app data matches the hardware configuration in set_hw_all(). If it does not match then we can reconfigure. Signed-off-by: John Fastabend Tested-by: Ross Brattain Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_dcb_nl.c | 107 +++++++++------------------------------ 1 file changed, 24 insertions(+), 83 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index 327c8614198c..7b59f64a13d4 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -347,18 +347,28 @@ static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority, static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct dcb_app app = { + .selector = DCB_APP_IDTYPE_ETHTYPE, + .protocol = ETH_P_FCOE, + }; + u8 up = dcb_getapp(netdev, &app); int ret; - if (!adapter->dcb_set_bitmap || - !(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) - return DCB_NO_HW_CHG; - ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg, MAX_TRAFFIC_CLASS); - if (ret) return DCB_NO_HW_CHG; + /* In IEEE mode app data must be parsed into DCBX format for + * hardware routines. + */ + if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) + up = (1 << up); + +#ifdef IXGBE_FCOE + if (up && (up != (1 << adapter->fcoe.up))) + adapter->dcb_set_bitmap |= BIT_APP_UPCHG; + /* * Only take down the adapter if an app change occurred. FCoE * may shuffle tx rings in this case and this can not be done @@ -368,10 +378,13 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) msleep(1); + ixgbe_fcoe_setapp(adapter, up); + if (netif_running(netdev)) netdev->netdev_ops->ndo_stop(netdev); ixgbe_clear_interrupt_scheme(adapter); } +#endif if (adapter->dcb_cfg.pfc_mode_enable) { switch (adapter->hw.mac.type) { @@ -399,12 +412,14 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) } } +#ifdef IXGBE_FCOE if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { ixgbe_init_interrupt_scheme(adapter); if (netif_running(netdev)) netdev->netdev_ops->ndo_open(netdev); ret = DCB_HW_CHG_RST; } +#endif if (adapter->dcb_set_bitmap & BIT_PFC) { u8 pfc_en; @@ -558,68 +573,6 @@ static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id) return dcb_getapp(netdev, &app); } -/** - * ixgbe_dcbnl_setapp - set the DCBX application user priority - * @netdev : the corresponding netdev - * @idtype : identifies the id as ether type or TCP/UDP port number - * @id: id is either ether type or TCP/UDP port number - * @up: the 802.1p user priority bitmap - * - * Returns : 0 on success or 1 on error - */ -static u8 ixgbe_dcbnl_setapp(struct net_device *netdev, - u8 idtype, u16 id, u8 up) -{ - struct ixgbe_adapter *adapter = netdev_priv(netdev); - u8 rval = 1; - struct dcb_app app = { - .selector = idtype, - .protocol = id, - .priority = up - }; - - if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) - return rval; - - rval = dcb_setapp(netdev, &app); - - switch (idtype) { - case DCB_APP_IDTYPE_ETHTYPE: -#ifdef IXGBE_FCOE - if (id == ETH_P_FCOE) { - u8 old_tc; - - /* Get current programmed tc */ - old_tc = adapter->fcoe.tc; - rval = ixgbe_fcoe_setapp(adapter, up); - - if (rval || - !(adapter->flags & IXGBE_FLAG_DCB_ENABLED) || - !(adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) - break; - - /* The FCoE application priority may be changed multiple - * times in quick succession with switches that build up - * TLVs. To avoid creating uneeded device resets this - * checks the actual HW configuration and clears - * BIT_APP_UPCHG if a HW configuration change is not - * need - */ - if (old_tc == adapter->fcoe.tc) - adapter->dcb_set_bitmap &= ~BIT_APP_UPCHG; - else - adapter->dcb_set_bitmap |= BIT_APP_UPCHG; - } -#endif - break; - case DCB_APP_IDTYPE_PORTNUM: - break; - default: - break; - } - return rval; -} - static int ixgbe_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets) { @@ -745,25 +698,14 @@ static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev, if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) return -EINVAL; -#ifdef IXGBE_FCOE - if (app->selector == 1 && app->protocol == ETH_P_FCOE) { - if (adapter->fcoe.tc == app->priority) - goto setapp; - /* In IEEE mode map up to tc 1:1 */ - adapter->fcoe.tc = app->priority; - adapter->fcoe.up = app->priority; + dcb_setapp(dev, app); - /* Force hardware reset required to push FCoE - * setup on {tx|rx}_rings - */ - adapter->dcb_set_bitmap |= BIT_APP_UPCHG; +#ifdef IXGBE_FCOE + if (app->selector == 1 && app->protocol == ETH_P_FCOE && + adapter->fcoe.tc == app->priority) ixgbe_dcbnl_set_all(dev); - } - -setapp: #endif - dcb_setapp(dev, app); return 0; } @@ -838,7 +780,6 @@ const struct dcbnl_rtnl_ops dcbnl_ops = { .getpfcstate = ixgbe_dcbnl_getpfcstate, .setpfcstate = ixgbe_dcbnl_setpfcstate, .getapp = ixgbe_dcbnl_getapp, - .setapp = ixgbe_dcbnl_setapp, .getdcbx = ixgbe_dcbnl_getdcbx, .setdcbx = ixgbe_dcbnl_setdcbx, }; -- cgit v1.2.3-58-ga151 From 2ea5ea5fc4f4f1daa74708c2a14e364d8474812d Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Sat, 12 Mar 2011 08:56:38 +0000 Subject: ixgbe: fix return value checks The value of status was incorrectly tested. Also whitespace cleanup. Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_x540.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c index d9323c08f5c7..7ce3f45cad71 100644 --- a/drivers/net/ixgbe/ixgbe_x540.c +++ b/drivers/net/ixgbe/ixgbe_x540.c @@ -452,7 +452,7 @@ static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_EEC, flup); status = ixgbe_poll_flash_update_done_X540(hw); - if (status) + if (status == 0) hw_dbg(hw, "Flash update complete\n"); else hw_dbg(hw, "Flash update time out\n"); @@ -466,11 +466,10 @@ static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw) } status = ixgbe_poll_flash_update_done_X540(hw); - if (status) + if (status == 0) hw_dbg(hw, "Flash update complete\n"); else hw_dbg(hw, "Flash update time out\n"); - } out: return status; -- cgit v1.2.3-58-ga151 From c9130180a8dc48943f2a072acec4a53616a1f0ab Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Wed, 16 Mar 2011 01:55:55 +0000 Subject: ixgbe: correct function number for some 82598 parts Some 82598 parts have LAN0 disabled and LAN1 enabled and the LAN ID bits in Device Status register report the NIC as having only LAN1 as enabled. This causes ixgbe_set_lan_id_multi_port_pcie() to set bus->func = 1 which is incorrect. Force bus->func to 0 when LAN0 is disabled in the EEPROM. Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82598.c | 34 +++++++++++++++++++++++++++++++++- drivers/net/ixgbe/ixgbe_type.h | 5 +++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 845c679c8b87..c9b6574cdd72 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -1188,6 +1188,38 @@ out: return physical_layer; } +/** + * ixgbe_set_lan_id_multi_port_pcie_82598 - Set LAN id for PCIe multiple + * port devices. + * @hw: pointer to the HW structure + * + * Calls common function and corrects issue with some single port devices + * that enable LAN1 but not LAN0. + **/ +static void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw) +{ + struct ixgbe_bus_info *bus = &hw->bus; + u16 pci_gen = 0; + u16 pci_ctrl2 = 0; + + ixgbe_set_lan_id_multi_port_pcie(hw); + + /* check if LAN0 is disabled */ + hw->eeprom.ops.read(hw, IXGBE_PCIE_GENERAL_PTR, &pci_gen); + if ((pci_gen != 0) && (pci_gen != 0xFFFF)) { + + hw->eeprom.ops.read(hw, pci_gen + IXGBE_PCIE_CTRL2, &pci_ctrl2); + + /* if LAN0 is completely disabled force function to 0 */ + if ((pci_ctrl2 & IXGBE_PCIE_CTRL2_LAN_DISABLE) && + !(pci_ctrl2 & IXGBE_PCIE_CTRL2_DISABLE_SELECT) && + !(pci_ctrl2 & IXGBE_PCIE_CTRL2_DUMMY_ENABLE)) { + + bus->func = 0; + } + } +} + static struct ixgbe_mac_operations mac_ops_82598 = { .init_hw = &ixgbe_init_hw_generic, .reset_hw = &ixgbe_reset_hw_82598, @@ -1199,7 +1231,7 @@ static struct ixgbe_mac_operations mac_ops_82598 = { .get_mac_addr = &ixgbe_get_mac_addr_generic, .stop_adapter = &ixgbe_stop_adapter_generic, .get_bus_info = &ixgbe_get_bus_info_generic, - .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, + .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie_82598, .read_analog_reg8 = &ixgbe_read_analog_reg8_82598, .write_analog_reg8 = &ixgbe_write_analog_reg8_82598, .setup_link = &ixgbe_setup_mac_link_82598, diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 25c1fb7eda06..cd1c2b62ec49 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1616,6 +1616,11 @@ #define IXGBE_FLUDONE_ATTEMPTS 20000 #endif +#define IXGBE_PCIE_CTRL2 0x5 /* PCIe Control 2 Offset */ +#define IXGBE_PCIE_CTRL2_DUMMY_ENABLE 0x8 /* Dummy Function Enable */ +#define IXGBE_PCIE_CTRL2_LAN_DISABLE 0x2 /* LAN PCI Disable */ +#define IXGBE_PCIE_CTRL2_DISABLE_SELECT 0x1 /* LAN Disable Select */ + #define IXGBE_SAN_MAC_ADDR_PORT0_OFFSET 0x0 #define IXGBE_SAN_MAC_ADDR_PORT1_OFFSET 0x3 #define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP 0x1 -- cgit v1.2.3-58-ga151 From d6cd8e0e75b66896bd4e14c8883d62322831cb8f Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Wed, 16 Mar 2011 01:58:20 +0000 Subject: ixgbe: fix namespacecheck issue Set ixgbe_identify_82599() as static Signed-off-by: Emil Tantilov Tested-by: Stephen Ko Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82599.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 00aeba385a2f..32ad4119ff77 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -1775,7 +1775,7 @@ static s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw) * If PHY already detected, maintains current PHY type in hw struct, * otherwise executes the PHY detection routine. **/ -s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw) +static s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_PHY_ADDR_INVALID; -- cgit v1.2.3-58-ga151 From 75e3d3c6812ef2387f8dcfd86437cff00f64b68b Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 17 Mar 2011 18:11:38 +0000 Subject: ixgbe: update version string for Dell CEM use Signed-off-by: Jeff Kirsher Acked-by: Don Skidmore Tested-by: Stephen Ko --- drivers/net/ixgbe/ixgbe_main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 6f8adc7f5d7c..3dbe6896b2c3 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -51,8 +51,12 @@ char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = "Intel(R) 10 Gigabit PCI Express Network Driver"; - -#define DRV_VERSION "3.2.9-k2" +#define MAJ 3 +#define MIN 2 +#define BUILD 9 +#define KFIX 2 +#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ + __stringify(BUILD) "-k" __stringify(KFIX) const char ixgbe_driver_version[] = DRV_VERSION; static const char ixgbe_copyright[] = "Copyright (c) 1999-2011 Intel Corporation."; -- cgit v1.2.3-58-ga151 From 7184b7cf555f5bc08e34994147c341abb07d1dbb Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Fri, 18 Mar 2011 08:18:22 +0000 Subject: ixgbe: refactor common start_hw code for 82599 and x540 Factored out the common start_hw code into a new function ixgbe_start_hw_gen2() so that it can be used by x540 and 82599. Signed-off-by: Emil Tantilov Acked-by: Don Skidmore Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82599.c | 22 ++++++++++------------ drivers/net/ixgbe/ixgbe_common.c | 24 ++++++++++++++++++++++++ drivers/net/ixgbe/ixgbe_common.h | 1 + drivers/net/ixgbe/ixgbe_x540.c | 24 +++++++++++++++++++++++- 4 files changed, 58 insertions(+), 13 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 32ad4119ff77..09934a82eb30 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -1740,30 +1740,28 @@ static s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val) * ixgbe_start_hw_82599 - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * - * Starts the hardware using the generic start_hw function. - * Then performs device-specific: - * Clears the rate limiter registers. + * Starts the hardware using the generic start_hw function + * and the generation start_hw function. + * Then performs revision-specific operations, if any. **/ static s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw) { - u32 q_num; - s32 ret_val; + s32 ret_val = 0; ret_val = ixgbe_start_hw_generic(hw); + if (ret_val != 0) + goto out; - /* Clear the rate limiters */ - for (q_num = 0; q_num < hw->mac.max_tx_queues; q_num++) { - IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, q_num); - IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0); - } - IXGBE_WRITE_FLUSH(hw); + ret_val = ixgbe_start_hw_gen2(hw); + if (ret_val != 0) + goto out; /* We need to run link autotry after the driver loads */ hw->mac.autotry_restart = true; if (ret_val == 0) ret_val = ixgbe_verify_fw_version_82599(hw); - +out: return ret_val; } diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index bcd952916eb2..c66fd957578c 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -95,6 +95,30 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) return 0; } +/** + * ixgbe_start_hw_gen2 - Init sequence for common device family + * @hw: pointer to hw structure + * + * Performs the init sequence common to the second generation + * of 10 GbE devices. + * Devices in the second generation: + * 82599 + * X540 + **/ +s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw) +{ + u32 i; + + /* Clear the rate limiters */ + for (i = 0; i < hw->mac.max_tx_queues; i++) { + IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i); + IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0); + } + IXGBE_WRITE_FLUSH(hw); + + return 0; +} + /** * ixgbe_init_hw_generic - Generic hardware initialization * @hw: pointer to hardware structure diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index 508f635fc2ca..2585bf38391d 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -35,6 +35,7 @@ u32 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw); s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw); s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw); s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw); +s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw); s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw); s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, u32 pba_num_size); diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c index 7ce3f45cad71..295c17003d6d 100644 --- a/drivers/net/ixgbe/ixgbe_x540.c +++ b/drivers/net/ixgbe/ixgbe_x540.c @@ -225,6 +225,28 @@ mac_reset_top: return status; } +/** + * ixgbe_start_hw_X540 - Prepare hardware for Tx/Rx + * @hw: pointer to hardware structure + * + * Starts the hardware using the generic start_hw function + * and the generation start_hw function. + * Then performs revision-specific operations, if any. + **/ +static s32 ixgbe_start_hw_X540(struct ixgbe_hw *hw) +{ + s32 ret_val = 0; + + ret_val = ixgbe_start_hw_generic(hw); + if (ret_val != 0) + goto out; + + ret_val = ixgbe_start_hw_gen2(hw); + +out: + return ret_val; +} + /** * ixgbe_get_supported_physical_layer_X540 - Returns physical layer type * @hw: pointer to hardware structure @@ -660,7 +682,7 @@ static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw) static struct ixgbe_mac_operations mac_ops_X540 = { .init_hw = &ixgbe_init_hw_generic, .reset_hw = &ixgbe_reset_hw_X540, - .start_hw = &ixgbe_start_hw_generic, + .start_hw = &ixgbe_start_hw_X540, .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, .get_media_type = &ixgbe_get_media_type_X540, .get_supported_physical_layer = -- cgit v1.2.3-58-ga151 From 3d5c520727ce3dbf418eec38e431856708f946f8 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Sat, 19 Mar 2011 01:32:46 +0000 Subject: ixgbe: move disabling of relaxed ordering in start_hw() Relaxed ordering can lead to issues with some chipsets. This patch makes sure that it is disabled by default and not only when DCA is on. Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82598.c | 21 ++++++++++++++++++++- drivers/net/ixgbe/ixgbe_common.c | 15 +++++++++++++++ drivers/net/ixgbe/ixgbe_main.c | 4 ---- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index c9b6574cdd72..a93275fd260f 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -197,14 +197,33 @@ out: * @hw: pointer to hardware structure * * Starts the hardware using the generic start_hw function. - * Then set pcie completion timeout + * Disables relaxed ordering Then set pcie completion timeout + * **/ static s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw) { + u32 regval; + u32 i; s32 ret_val = 0; ret_val = ixgbe_start_hw_generic(hw); + /* Disable relaxed ordering */ + for (i = 0; ((i < hw->mac.max_tx_queues) && + (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { + regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i)); + regval &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), regval); + } + + for (i = 0; ((i < hw->mac.max_rx_queues) && + (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { + regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); + regval &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN | + IXGBE_DCA_RXCTRL_DESC_HSRO_EN); + IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); + } + /* set the completion timeout for interface */ if (ret_val == 0) ixgbe_set_pcie_completion_timeout(hw); diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index c66fd957578c..1b8b3cd1664f 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -108,6 +108,7 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw) { u32 i; + u32 regval; /* Clear the rate limiters */ for (i = 0; i < hw->mac.max_tx_queues; i++) { @@ -116,6 +117,20 @@ s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw) } IXGBE_WRITE_FLUSH(hw); + /* Disable relaxed ordering */ + for (i = 0; i < hw->mac.max_tx_queues; i++) { + regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); + regval &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); + } + + for (i = 0; i < hw->mac.max_rx_queues; i++) { + regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); + regval &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN | + IXGBE_DCA_RXCTRL_DESC_HSRO_EN); + IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); + } + return 0; } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 3dbe6896b2c3..3148e2182e92 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -947,8 +947,6 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter, rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN; rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN; rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_RRO_EN); - rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN | - IXGBE_DCA_RXCTRL_DESC_HSRO_EN); IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(reg_idx), rxctrl); } @@ -966,7 +964,6 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter, txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK; txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; - txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(reg_idx), txctrl); break; case ixgbe_mac_82599EB: @@ -976,7 +973,6 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter, txctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) << IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599); txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; - txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(reg_idx), txctrl); break; default: -- cgit v1.2.3-58-ga151 From 0fa6d83258252695203d24c8818092644df10fd7 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Fri, 18 Mar 2011 08:18:32 +0000 Subject: ixgbe: fix 82599 KR downshift coexistence with LESM FW module Disable KR to KX4/KX downshift on 82599 backplane devices when LESM (Link Establishment State Machine) is enabled in FW. Those features cannot co-exist as they both manipulate the same registers. Signed-off-by: Emil Tantilov Acked-by: Don Skidmore Tested-by: Phillip Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82599.c | 46 ++++++++++++++++++++++++++++++++++++++++- drivers/net/ixgbe/ixgbe_type.h | 3 +++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 09934a82eb30..d195278c62e3 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -61,6 +61,7 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, bool autoneg, bool autoneg_wait_to_complete); static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw); +static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw); static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) { @@ -86,7 +87,8 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) if ((mac->ops.get_media_type(hw) == ixgbe_media_type_backplane) && (hw->phy.smart_speed == ixgbe_smart_speed_auto || - hw->phy.smart_speed == ixgbe_smart_speed_on)) + hw->phy.smart_speed == ixgbe_smart_speed_on) && + !ixgbe_verify_lesm_fw_enabled_82599(hw)) mac->ops.setup_link = &ixgbe_setup_mac_link_smartspeed; else mac->ops.setup_link = &ixgbe_setup_mac_link_82599; @@ -2028,6 +2030,48 @@ fw_version_out: return status; } +/** + * ixgbe_verify_lesm_fw_enabled_82599 - Checks LESM FW module state. + * @hw: pointer to hardware structure + * + * Returns true if the LESM FW module is present and enabled. Otherwise + * returns false. Smart Speed must be disabled if LESM FW module is enabled. + **/ +static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw) +{ + bool lesm_enabled = false; + u16 fw_offset, fw_lesm_param_offset, fw_lesm_state; + s32 status; + + /* get the offset to the Firmware Module block */ + status = hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset); + + if ((status != 0) || + (fw_offset == 0) || (fw_offset == 0xFFFF)) + goto out; + + /* get the offset to the LESM Parameters block */ + status = hw->eeprom.ops.read(hw, (fw_offset + + IXGBE_FW_LESM_PARAMETERS_PTR), + &fw_lesm_param_offset); + + if ((status != 0) || + (fw_lesm_param_offset == 0) || (fw_lesm_param_offset == 0xFFFF)) + goto out; + + /* get the lesm state word */ + status = hw->eeprom.ops.read(hw, (fw_lesm_param_offset + + IXGBE_FW_LESM_STATE_1), + &fw_lesm_state); + + if ((status == 0) && + (fw_lesm_state & IXGBE_FW_LESM_STATE_ENABLED)) + lesm_enabled = true; + +out: + return lesm_enabled; +} + static struct ixgbe_mac_operations mac_ops_82599 = { .init_hw = &ixgbe_init_hw_generic, .reset_hw = &ixgbe_reset_hw_82599, diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index cd1c2b62ec49..e00356a25ee1 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1625,6 +1625,9 @@ #define IXGBE_SAN_MAC_ADDR_PORT1_OFFSET 0x3 #define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP 0x1 #define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS 0x2 +#define IXGBE_FW_LESM_PARAMETERS_PTR 0x2 +#define IXGBE_FW_LESM_STATE_1 0x1 +#define IXGBE_FW_LESM_STATE_ENABLED 0x8000 /* LESM Enable bit */ #define IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR 0x4 #define IXGBE_FW_PATCH_VERSION_4 0x7 -- cgit v1.2.3-58-ga151 From 032b4325b61b03f87f0346d0e92e39f785e24105 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Fri, 18 Mar 2011 09:32:53 +0000 Subject: ixgbe: cleanup short msleep's (<20ms) to use usleep_range Since msleep might not sleep for the desired amount when less than 20ms use usleep_range. Signed-off-by: Don Skidmore Tested-by: Stephen Ko Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82598.c | 2 +- drivers/net/ixgbe/ixgbe_82599.c | 14 +++++++++----- drivers/net/ixgbe/ixgbe_common.c | 14 +++++++++----- drivers/net/ixgbe/ixgbe_dcb_nl.c | 2 +- drivers/net/ixgbe/ixgbe_ethtool.c | 14 +++++++------- drivers/net/ixgbe/ixgbe_main.c | 8 ++++---- drivers/net/ixgbe/ixgbe_phy.c | 4 ++-- drivers/net/ixgbe/ixgbe_x540.c | 6 +++--- 8 files changed, 36 insertions(+), 28 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index a93275fd260f..af4054a1a133 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -1083,7 +1083,7 @@ static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK; if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS) break; - msleep(10); + usleep_range(10000, 20000); } if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_PASS) { diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index d195278c62e3..e39380ca996c 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -130,8 +130,12 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) /* Release the semaphore */ ixgbe_release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); - /* Delay obtaining semaphore again to allow FW access */ - msleep(hw->eeprom.semaphore_delay); + /* + * Delay obtaining semaphore again to allow FW access, + * semaphore_delay is in ms usleep_range needs us. + */ + usleep_range(hw->eeprom.semaphore_delay * 1000, + hw->eeprom.semaphore_delay * 2000); /* Now restart DSP by setting Restart_AN and clearing LMS */ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, ((IXGBE_READ_REG(hw, @@ -140,7 +144,7 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) /* Wait for AN to leave state 0 */ for (i = 0; i < 10; i++) { - msleep(4); + usleep_range(4000, 8000); reg_anlp1 = IXGBE_READ_REG(hw, IXGBE_ANLP1); if (reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK) break; @@ -1178,7 +1182,7 @@ s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc) if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & IXGBE_FDIRCTRL_INIT_DONE) break; - msleep(1); + usleep_range(1000, 2000); } if (i >= IXGBE_FDIR_INIT_DONE_POLL) hw_dbg(hw, "Flow Director Signature poll time exceeded!\n"); @@ -1273,7 +1277,7 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc) if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & IXGBE_FDIRCTRL_INIT_DONE) break; - msleep(1); + usleep_range(1000, 2000); } if (i >= IXGBE_FDIR_INIT_DONE_POLL) hw_dbg(hw, "Flow Director Perfect poll time exceeded!\n"); diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 1b8b3cd1664f..a67cba5149d1 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -503,7 +503,7 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) reg_val &= ~(IXGBE_RXCTRL_RXEN); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val); IXGBE_WRITE_FLUSH(hw); - msleep(2); + usleep_range(2000, 4000); /* Clear interrupt mask to stop from interrupts being generated */ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); @@ -1151,8 +1151,12 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw) hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); - /* Delay before attempt to obtain semaphore again to allow FW access */ - msleep(hw->eeprom.semaphore_delay); + /* + * Delay before attempt to obtain semaphore again to allow FW + * access. semaphore_delay is in ms we need us for usleep_range + */ + usleep_range(hw->eeprom.semaphore_delay * 1000, + hw->eeprom.semaphore_delay * 2000); } /** @@ -2228,7 +2232,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) * thread currently using resource (swmask) */ ixgbe_release_eeprom_semaphore(hw); - msleep(5); + usleep_range(5000, 10000); timeout--; } @@ -2302,7 +2306,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) autoc_reg |= IXGBE_AUTOC_AN_RESTART; autoc_reg |= IXGBE_AUTOC_FLU; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); - msleep(10); + usleep_range(10000, 20000); } led_reg &= ~IXGBE_LED_MODE_MASK(index); diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index 7b59f64a13d4..5e7ed225851a 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -376,7 +376,7 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) */ if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) - msleep(1); + usleep_range(1000, 2000); ixgbe_fcoe_setapp(adapter, up); diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 76380a2b35aa..5005a36f8593 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -931,7 +931,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev, } while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) - msleep(1); + usleep_range(1000, 2000); if (!netif_running(adapter->netdev)) { for (i = 0; i < adapter->num_tx_queues; i++) @@ -1417,7 +1417,7 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data) /* Disable all the interrupts */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF); - msleep(10); + usleep_range(10000, 20000); /* Test each interrupt */ for (; i < 10; i++) { @@ -1437,7 +1437,7 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data) ~mask & 0x00007FFF); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, ~mask & 0x00007FFF); - msleep(10); + usleep_range(10000, 20000); if (adapter->test_icr & mask) { *data = 3; @@ -1454,7 +1454,7 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data) adapter->test_icr = 0; IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask); - msleep(10); + usleep_range(10000, 20000); if (!(adapter->test_icr &mask)) { *data = 4; @@ -1474,7 +1474,7 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data) ~mask & 0x00007FFF); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, ~mask & 0x00007FFF); - msleep(10); + usleep_range(10000, 20000); if (adapter->test_icr) { *data = 5; @@ -1485,7 +1485,7 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data) /* Disable all the interrupts */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF); - msleep(10); + usleep_range(10000, 20000); /* Unhook test interrupt handler */ free_irq(irq, netdev); @@ -1613,7 +1613,7 @@ static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter) reg_data |= IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU; IXGBE_WRITE_REG(&adapter->hw, IXGBE_AUTOC, reg_data); IXGBE_WRITE_FLUSH(&adapter->hw); - msleep(10); + usleep_range(10000, 20000); /* Disable Atlas Tx lanes; re-enabled in reset path */ if (hw->mac.type == ixgbe_mac_82598EB) { diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 3148e2182e92..5cd2cd3dd353 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2731,7 +2731,7 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter, /* poll to verify queue is enabled */ do { - msleep(1); + usleep_range(1000, 2000); txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx)); } while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE)); if (!wait_loop) @@ -3023,7 +3023,7 @@ static void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter, return; do { - msleep(1); + usleep_range(1000, 2000); rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx)); } while (--wait_loop && !(rxdctl & IXGBE_RXDCTL_ENABLE)); @@ -3945,7 +3945,7 @@ void ixgbe_reinit_locked(struct ixgbe_adapter *adapter) { WARN_ON(in_interrupt()); while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) - msleep(1); + usleep_range(1000, 2000); ixgbe_down(adapter); /* * If SR-IOV enabled then wait a bit before bringing the adapter @@ -4150,7 +4150,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) /* this call also flushes the previous write */ ixgbe_disable_rx_queue(adapter, adapter->rx_ring[i]); - msleep(10); + usleep_range(10000, 20000); netif_tx_stop_all_queues(netdev); diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index df5b8aa4795d..31cc29ed137c 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -753,7 +753,7 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw) &phy_data); if ((phy_data & MDIO_CTRL1_RESET) == 0) break; - msleep(10); + usleep_range(10000, 20000); } if ((phy_data & MDIO_CTRL1_RESET) != 0) { @@ -782,7 +782,7 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw) case IXGBE_DELAY_NL: data_offset++; hw_dbg(hw, "DELAY: %d MS\n", edata); - msleep(edata); + usleep_range(edata * 1000, edata * 2000); break; case IXGBE_DATA_NL: hw_dbg(hw, "DATA:\n"); diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c index 295c17003d6d..8aa1dc1155a9 100644 --- a/drivers/net/ixgbe/ixgbe_x540.c +++ b/drivers/net/ixgbe/ixgbe_x540.c @@ -563,7 +563,7 @@ static s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask) * resource (swmask) */ ixgbe_release_swfw_sync_semaphore(hw); - msleep(5); + usleep_range(5000, 10000); } } @@ -585,7 +585,7 @@ static s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask) } } - msleep(5); + usleep_range(5000, 10000); return 0; } @@ -609,7 +609,7 @@ static void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask) IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync); ixgbe_release_swfw_sync_semaphore(hw); - msleep(5); + usleep_range(5000, 10000); } /** -- cgit v1.2.3-58-ga151 From eb9c3e3ea2981e56c71e8f5477c51783856090b1 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 24 Mar 2011 00:57:50 +0000 Subject: ixgbe: fix semaphores in eeprom routines for x540 HW can upload EEPROM content from flash while in a middle of checksum calculation. Take NVM ownership for the whole process of checksum update. Call ixgbe_read_eerd_generic() and ixgbe_write_eewr_generic() directly to avoid double take of semaphores which leads to long loading times. Signed-off-by: Emil Tantilov Tested-by: Stephen Ko Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_common.c | 44 ++++++++++- drivers/net/ixgbe/ixgbe_common.h | 2 +- drivers/net/ixgbe/ixgbe_x540.c | 154 +++++++++++++++++++++++++++------------ 3 files changed, 153 insertions(+), 47 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index a67cba5149d1..fc31e0256c18 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -54,6 +54,7 @@ static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw); static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm); static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num); +static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg); /** * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx @@ -777,6 +778,47 @@ out: return status; } +/** + * ixgbe_write_eewr_generic - Write EEPROM word using EEWR + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to write + * @data: word write to the EEPROM + * + * Write a 16 bit word to the EEPROM using the EEWR register. + **/ +s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data) +{ + u32 eewr; + s32 status; + + hw->eeprom.ops.init_params(hw); + + if (offset >= hw->eeprom.word_size) { + status = IXGBE_ERR_EEPROM; + goto out; + } + + eewr = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) | + (data << IXGBE_EEPROM_RW_REG_DATA) | IXGBE_EEPROM_RW_REG_START; + + status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); + if (status != 0) { + hw_dbg(hw, "Eeprom write EEWR timed out\n"); + goto out; + } + + IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); + + status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); + if (status != 0) { + hw_dbg(hw, "Eeprom write EEWR timed out\n"); + goto out; + } + +out: + return status; +} + /** * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status * @hw: pointer to hardware structure @@ -785,7 +827,7 @@ out: * Polls the status bit (bit 1) of the EERD or EEWR to determine when the * read or write is done respectively. **/ -s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) +static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) { u32 i; u32 reg; diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index 2585bf38391d..e18dc136ad34 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -50,13 +50,13 @@ s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw); s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data); s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); +s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data); s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw); s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, u16 *checksum_val); s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw); -s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg); s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c index 8aa1dc1155a9..5433f15c1e1b 100644 --- a/drivers/net/ixgbe/ixgbe_x540.c +++ b/drivers/net/ixgbe/ixgbe_x540.c @@ -322,55 +322,33 @@ static s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data) } /** - * ixgbe_write_eewr_X540 - Write EEPROM word using EEWR - * @hw: pointer to hardware structure - * @offset: offset of word in the EEPROM to write - * @data: word write to the EEPROM + * ixgbe_write_eewr_X540 - Write EEPROM word using EEWR + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to write + * @data: word write to the EEPROM * - * Write a 16 bit word to the EEPROM using the EEWR register. + * Write a 16 bit word to the EEPROM using the EEWR register. **/ static s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data) { - u32 eewr; - s32 status; - - hw->eeprom.ops.init_params(hw); - - if (offset >= hw->eeprom.word_size) { - status = IXGBE_ERR_EEPROM; - goto out; - } - - eewr = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) | - (data << IXGBE_EEPROM_RW_REG_DATA) | - IXGBE_EEPROM_RW_REG_START; - - if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { - status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); - if (status != 0) { - hw_dbg(hw, "Eeprom write EEWR timed out\n"); - goto out; - } - - IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); + s32 status = 0; - status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); - if (status != 0) { - hw_dbg(hw, "Eeprom write EEWR timed out\n"); - goto out; - } - } else { + if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) + status = ixgbe_write_eewr_generic(hw, offset, data); + else status = IXGBE_ERR_SWFW_SYNC; - } -out: - ixgbe_release_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM); + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); return status; } /** - * ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum - * @hw: pointer to hardware structure + * ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum + * + * This function does not use synchronization for EERD and EEWR. It can + * be used internally by function which utilize ixgbe_acquire_swfw_sync_X540. + * + * @hw: pointer to hardware structure **/ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) { @@ -381,9 +359,15 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) u16 pointer = 0; u16 word = 0; + /* + * Do not use hw->eeprom.ops.read because we do not want to take + * the synchronization semaphores here. Instead use + * ixgbe_read_eerd_generic + */ + /* Include 0x0-0x3F in the checksum */ for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { - if (hw->eeprom.ops.read(hw, i, &word) != 0) { + if (ixgbe_read_eerd_generic(hw, i, &word) != 0) { hw_dbg(hw, "EEPROM read failed\n"); break; } @@ -398,7 +382,7 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) continue; - if (hw->eeprom.ops.read(hw, i, &pointer) != 0) { + if (ixgbe_read_eerd_generic(hw, i, &pointer) != 0) { hw_dbg(hw, "EEPROM read failed\n"); break; } @@ -408,7 +392,7 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) pointer >= hw->eeprom.word_size) continue; - if (hw->eeprom.ops.read(hw, pointer, &length) != 0) { + if (ixgbe_read_eerd_generic(hw, pointer, &length) != 0) { hw_dbg(hw, "EEPROM read failed\n"); break; } @@ -419,7 +403,7 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) continue; for (j = pointer+1; j <= pointer+length; j++) { - if (hw->eeprom.ops.read(hw, j, &word) != 0) { + if (ixgbe_read_eerd_generic(hw, j, &word) != 0) { hw_dbg(hw, "EEPROM read failed\n"); break; } @@ -432,6 +416,62 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) return checksum; } +/** + * ixgbe_validate_eeprom_checksum_X540 - Validate EEPROM checksum + * @hw: pointer to hardware structure + * @checksum_val: calculated checksum + * + * Performs checksum calculation and validates the EEPROM checksum. If the + * caller does not need checksum_val, the value can be NULL. + **/ +static s32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw, + u16 *checksum_val) +{ + s32 status; + u16 checksum; + u16 read_checksum = 0; + + /* + * Read the first word from the EEPROM. If this times out or fails, do + * not continue or we could be in for a very long wait while every + * EEPROM read fails + */ + status = hw->eeprom.ops.read(hw, 0, &checksum); + + if (status != 0) { + hw_dbg(hw, "EEPROM read failed\n"); + goto out; + } + + if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { + checksum = hw->eeprom.ops.calc_checksum(hw); + + /* + * Do not use hw->eeprom.ops.read because we do not want to take + * the synchronization semaphores twice here. + */ + ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM, + &read_checksum); + + /* + * Verify read checksum from EEPROM is the same as + * calculated checksum + */ + if (read_checksum != checksum) + status = IXGBE_ERR_EEPROM_CHECKSUM; + + /* If the user cares, return the calculated checksum */ + if (checksum_val) + *checksum_val = checksum; + } else { + status = IXGBE_ERR_SWFW_SYNC; + } + + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); +out: + return status; +} + /** * ixgbe_update_eeprom_checksum_X540 - Updates the EEPROM checksum and flash * @hw: pointer to hardware structure @@ -443,11 +483,35 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) static s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw) { s32 status; + u16 checksum; - status = ixgbe_update_eeprom_checksum_generic(hw); + /* + * Read the first word from the EEPROM. If this times out or fails, do + * not continue or we could be in for a very long wait while every + * EEPROM read fails + */ + status = hw->eeprom.ops.read(hw, 0, &checksum); + + if (status != 0) + hw_dbg(hw, "EEPROM read failed\n"); + + if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { + checksum = hw->eeprom.ops.calc_checksum(hw); - if (status) + /* + * Do not use hw->eeprom.ops.write because we do not want to + * take the synchronization semaphores twice here. + */ + status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM, + checksum); + + if (status == 0) status = ixgbe_update_flash_X540(hw); + else + status = IXGBE_ERR_SWFW_SYNC; + } + + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); return status; } @@ -728,7 +792,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_X540 = { .read = &ixgbe_read_eerd_X540, .write = &ixgbe_write_eewr_X540, .calc_checksum = &ixgbe_calc_eeprom_checksum_X540, - .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, + .validate_checksum = &ixgbe_validate_eeprom_checksum_X540, .update_checksum = &ixgbe_update_eeprom_checksum_X540, }; -- cgit v1.2.3-58-ga151 From 4c40ef0291acebf32435e5a4921178ee53bd8933 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 24 Mar 2011 07:06:02 +0000 Subject: ixgbe: add support for new HW Add new device ID supported by ixgbe. Signed-off-by: Emil Tantilov Tested-by: Stephen Ko Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82599.c | 1 + drivers/net/ixgbe/ixgbe_main.c | 2 ++ drivers/net/ixgbe/ixgbe_type.h | 1 + 3 files changed, 4 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index e39380ca996c..63b4da6b5b77 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -359,6 +359,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82599_SFP: case IXGBE_DEV_ID_82599_SFP_FCOE: case IXGBE_DEV_ID_82599_SFP_EM: + case IXGBE_DEV_ID_82599_SFP_SF2: media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_82599_CX4: diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 5cd2cd3dd353..200ae7e60ba0 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -124,6 +124,8 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = { board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T), board_X540 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF2), + board_82599 }, /* required last entry */ {0, } diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index e00356a25ee1..15580d687aee 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -58,6 +58,7 @@ #define IXGBE_DEV_ID_82599_SFP_FCOE 0x1529 #define IXGBE_SUBDEV_ID_82599_SFP 0x11A9 #define IXGBE_DEV_ID_82599_SFP_EM 0x1507 +#define IXGBE_DEV_ID_82599_SFP_SF2 0x154D #define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC #define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8 #define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ 0x000C -- cgit v1.2.3-58-ga151 From a59e8a1a72806057084adc2d321fc2a7cbce9579 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 31 Mar 2011 09:36:12 +0000 Subject: ixgbe: explicitly disable 100H for x540 100H is not supported on this HW, but the bit is set on the PHY. This can result in link at 100F when advertising only 1000F. Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_phy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 31cc29ed137c..fd381ea17e99 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -449,7 +449,8 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) MDIO_MMD_AN, &autoneg_reg); - autoneg_reg &= ~ADVERTISE_100FULL; + autoneg_reg &= ~(ADVERTISE_100FULL | + ADVERTISE_100HALF); if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) autoneg_reg |= ADVERTISE_100FULL; -- cgit v1.2.3-58-ga151 From b776d1043510c60f59220eb5e58b524f5a7f0e52 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 31 Mar 2011 09:36:18 +0000 Subject: ixgbe: make device_caps() generic x540 has the same device capability word in the EEPROM as 82599. This patch renames ixgbe_get_device_caps_82599 to ixgbe_get_device_caps_generic, moves it to ixgbe_common.h and sets up the function pointer for x540. Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82599.c | 17 +---------------- drivers/net/ixgbe/ixgbe_common.c | 15 +++++++++++++++ drivers/net/ixgbe/ixgbe_common.h | 1 + drivers/net/ixgbe/ixgbe_x540.c | 2 +- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 63b4da6b5b77..e4323055347b 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -1972,21 +1972,6 @@ static s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval) return 0; } -/** - * ixgbe_get_device_caps_82599 - Get additional device capabilities - * @hw: pointer to hardware structure - * @device_caps: the EEPROM word with the extra device capabilities - * - * This function will read the EEPROM location for the device capabilities, - * and return the word through device_caps. - **/ -static s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps) -{ - hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); - - return 0; -} - /** * ixgbe_verify_fw_version_82599 - verify fw version for 82599 * @hw: pointer to hardware structure @@ -2087,7 +2072,7 @@ static struct ixgbe_mac_operations mac_ops_82599 = { .enable_rx_dma = &ixgbe_enable_rx_dma_82599, .get_mac_addr = &ixgbe_get_mac_addr_generic, .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, - .get_device_caps = &ixgbe_get_device_caps_82599, + .get_device_caps = &ixgbe_get_device_caps_generic, .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, .stop_adapter = &ixgbe_stop_adapter_generic, .get_bus_info = &ixgbe_get_bus_info_generic, diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index fc31e0256c18..cb2e8e18dd39 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -2968,3 +2968,18 @@ void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) pfvfspoof &= ~(1 << vf_target_shift); IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); } + +/** + * ixgbe_get_device_caps_generic - Get additional device capabilities + * @hw: pointer to hardware structure + * @device_caps: the EEPROM word with the extra device capabilities + * + * This function will read the EEPROM location for the device capabilities, + * and return the word through device_caps. + **/ +s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps) +{ + hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); + + return 0; +} diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index e18dc136ad34..e850adbb32a1 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -90,6 +90,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index); void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf); void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf); +s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps); #define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg))) diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c index 5433f15c1e1b..05f8e9cddef4 100644 --- a/drivers/net/ixgbe/ixgbe_x540.c +++ b/drivers/net/ixgbe/ixgbe_x540.c @@ -754,7 +754,7 @@ static struct ixgbe_mac_operations mac_ops_X540 = { .enable_rx_dma = &ixgbe_enable_rx_dma_generic, .get_mac_addr = &ixgbe_get_mac_addr_generic, .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, - .get_device_caps = NULL, + .get_device_caps = &ixgbe_get_device_caps_generic, .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, .stop_adapter = &ixgbe_stop_adapter_generic, .get_bus_info = &ixgbe_get_bus_info_generic, -- cgit v1.2.3-58-ga151 From e09ad236fc85b1d6e010138f59aba76f6c9a295b Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Mon, 4 Apr 2011 04:29:41 +0000 Subject: ixgbe: DCB, misallocated packet buffer size with X540 device The X540 device has a smaller packet buffer but the DCB configuration never took this into account. Under stress this can result in the DMA engine hanging and TX Unit hang occurring to reset the device. This patch reworks the packet buffer allocation routine used for DCB on 82599 and X540 devices to account for RX packet buffer sizes. This fixes the immediate hang. We should consolidate the various hardware specific routines for configuring features into a single routine. This will make it much harder to miss feature cases like this. Signed-off-by: John Fastabend Tested-by: Ross Brattain Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82598.c | 3 ++ drivers/net/ixgbe/ixgbe_82599.c | 2 ++ drivers/net/ixgbe/ixgbe_dcb_82599.c | 68 +++++++++++++++++++++++-------------- drivers/net/ixgbe/ixgbe_dcb_82599.h | 2 ++ drivers/net/ixgbe/ixgbe_type.h | 1 + drivers/net/ixgbe/ixgbe_x540.c | 3 +- 6 files changed, 52 insertions(+), 27 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index af4054a1a133..7a64f50435cf 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -37,6 +37,7 @@ #define IXGBE_82598_RAR_ENTRIES 16 #define IXGBE_82598_MC_TBL_SIZE 128 #define IXGBE_82598_VFT_TBL_SIZE 128 +#define IXGBE_82598_RX_PB_SIZE 512 static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, @@ -224,6 +225,8 @@ static s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); } + hw->mac.rx_pb_size = IXGBE_82598_RX_PB_SIZE; + /* set the completion timeout for interface */ if (ret_val == 0) ixgbe_set_pcie_completion_timeout(hw); diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index e4323055347b..b341ed8ef84f 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -38,6 +38,7 @@ #define IXGBE_82599_RAR_ENTRIES 128 #define IXGBE_82599_MC_TBL_SIZE 128 #define IXGBE_82599_VFT_TBL_SIZE 128 +#define IXGBE_82599_RX_PB_SIZE 512 static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); @@ -1765,6 +1766,7 @@ static s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw) /* We need to run link autotry after the driver loads */ hw->mac.autotry_restart = true; + hw->mac.rx_pb_size = IXGBE_82599_RX_PB_SIZE; if (ret_val == 0) ret_val = ixgbe_verify_fw_version_82599(hw); diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c index 025af8c53ddb..865ddd82b268 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82599.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c @@ -39,36 +39,52 @@ */ static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw, u8 rx_pba) { - s32 ret_val = 0; - u32 value = IXGBE_RXPBSIZE_64KB; + int num_tcs = IXGBE_MAX_PACKET_BUFFERS; + u32 rx_pb_size = hw->mac.rx_pb_size << IXGBE_RXPBSIZE_SHIFT; + u32 rxpktsize; + u32 txpktsize; + u32 txpbthresh; u8 i = 0; - /* Setup Rx packet buffer sizes */ - switch (rx_pba) { - case pba_80_48: - /* Setup the first four at 80KB */ - value = IXGBE_RXPBSIZE_80KB; - for (; i < 4; i++) - IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value); - /* Setup the last four at 48KB...don't re-init i */ - value = IXGBE_RXPBSIZE_48KB; - /* Fall Through */ - case pba_equal: - default: - for (; i < IXGBE_MAX_PACKET_BUFFERS; i++) - IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value); - - /* Setup Tx packet buffer sizes */ - for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) { - IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), - IXGBE_TXPBSIZE_20KB); - IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), - IXGBE_TXPBTHRESH_DCB); - } - break; + /* + * This really means configure the first half of the TCs + * (Traffic Classes) to use 5/8 of the Rx packet buffer + * space. To determine the size of the buffer for each TC, + * we are multiplying the average size by 5/4 and applying + * it to half of the traffic classes. + */ + if (rx_pba == pba_80_48) { + rxpktsize = (rx_pb_size * 5) / (num_tcs * 4); + rx_pb_size -= rxpktsize * (num_tcs / 2); + for (; i < (num_tcs / 2); i++) + IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); + } + + /* Divide the remaining Rx packet buffer evenly among the TCs */ + rxpktsize = rx_pb_size / (num_tcs - i); + for (; i < num_tcs; i++) + IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); + + /* + * Setup Tx packet buffer and threshold equally for all TCs + * TXPBTHRESH register is set in K so divide by 1024 and subtract + * 10 since the largest packet we support is just over 9K. + */ + txpktsize = IXGBE_TXPBSIZE_MAX / num_tcs; + txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX; + for (i = 0; i < num_tcs; i++) { + IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize); + IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh); } - return ret_val; + /* Clear unused TCs, if any, to zero buffer size*/ + for (; i < MAX_TRAFFIC_CLASS; i++) { + IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); + IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0); + IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0); + } + + return 0; } /** diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ixgbe/ixgbe_dcb_82599.h index 148fd8b477a9..2de71a503153 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82599.h +++ b/drivers/net/ixgbe/ixgbe_dcb_82599.h @@ -92,8 +92,10 @@ #define IXGBE_RXPBSIZE_64KB 0x00010000 /* 64KB Packet Buffer */ #define IXGBE_RXPBSIZE_80KB 0x00014000 /* 80KB Packet Buffer */ #define IXGBE_RXPBSIZE_128KB 0x00020000 /* 128KB Packet Buffer */ +#define IXGBE_TXPBSIZE_MAX 0x00028000 /* 160KB Packet Buffer*/ #define IXGBE_TXPBTHRESH_DCB 0xA /* THRESH value for DCB mode */ +#define IXGBE_TXPKT_SIZE_MAX 0xA /* Max Tx Packet size */ /* SECTXMINIFG DCB */ #define IXGBE_SECTX_DCB 0x00001F00 /* DCB TX Buffer IFG */ diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 15580d687aee..7d0b37d2ab7b 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -2606,6 +2606,7 @@ struct ixgbe_mac_info { u32 vft_size; u32 num_rar_entries; u32 rar_highwater; + u32 rx_pb_size; u32 max_tx_queues; u32 max_rx_queues; u32 max_msix_vectors; diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c index 05f8e9cddef4..932394fce439 100644 --- a/drivers/net/ixgbe/ixgbe_x540.c +++ b/drivers/net/ixgbe/ixgbe_x540.c @@ -37,6 +37,7 @@ #define IXGBE_X540_RAR_ENTRIES 128 #define IXGBE_X540_MC_TBL_SIZE 128 #define IXGBE_X540_VFT_TBL_SIZE 128 +#define IXGBE_X540_RX_PB_SIZE 384 static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw); static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw); @@ -242,7 +243,7 @@ static s32 ixgbe_start_hw_X540(struct ixgbe_hw *hw) goto out; ret_val = ixgbe_start_hw_gen2(hw); - + hw->mac.rx_pb_size = IXGBE_X540_RX_PB_SIZE; out: return ret_val; } -- cgit v1.2.3-58-ga151 From 45a5f720fe37d21059da3c333c373c845ccbd82b Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Mon, 4 Apr 2011 04:29:46 +0000 Subject: ixgbe: DCB, X540 devices do not respond to pause frames DCB enabled X540 devices are not responding to pause frames due to a missing register set that was added for these devices that did not exist in other devices. Signed-off-by: John Fastabend Tested-by: Ross Brattain Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_dcb_82599.c | 9 +++++++-- drivers/net/ixgbe/ixgbe_type.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c index 865ddd82b268..d50cf78c234d 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82599.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c @@ -301,12 +301,17 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en) IXGBE_WRITE_REG(hw, IXGBE_FCCFG, reg); /* * Enable Receive PFC - * We will always honor XOFF frames we receive when - * we are in PFC mode. + * 82599 will always honor XOFF frames we receive when + * we are in PFC mode however X540 only honors enabled + * traffic classes. */ reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); reg &= ~IXGBE_MFLCN_RFCE; reg |= IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_DPF; + + if (hw->mac.type == ixgbe_mac_X540) + reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT; + IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg); } else { diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 7d0b37d2ab7b..f5bec9754c00 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1728,6 +1728,8 @@ #define IXGBE_MFLCN_RPFCE 0x00000004 /* Receive Priority FC Enable */ #define IXGBE_MFLCN_RFCE 0x00000008 /* Receive FC Enable */ +#define IXGBE_MFLCN_RPFCE_SHIFT 4 + /* Multiple Receive Queue Control */ #define IXGBE_MRQC_RSSEN 0x00000001 /* RSS Enable */ #define IXGBE_MRQC_MRQE_MASK 0xF /* Bits 3:0 */ -- cgit v1.2.3-58-ga151 From 8849b720e9632acef139a349f9ec62e63ce7e497 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 14 Apr 2011 00:20:07 -0700 Subject: NET: AX.25, NETROM, ROSE: Remove SOCK_DEBUG calls Nobody alive seems to recall when they last were useful. Signed-off-by: Ralf Baechle Signed-off-by: David S. Miller --- net/ax25/af_ax25.c | 16 +--------------- net/netrom/af_netrom.c | 12 +----------- net/rose/af_rose.c | 16 ++-------------- 3 files changed, 4 insertions(+), 40 deletions(-) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 6da5daeebab7..e7c69f4619ec 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1538,8 +1538,6 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, } /* Build a packet */ - SOCK_DEBUG(sk, "AX.25: sendto: Addresses built. Building packet.\n"); - /* Assume the worst case */ size = len + ax25->ax25_dev->dev->hard_header_len; @@ -1549,8 +1547,6 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, skb_reserve(skb, size - len); - SOCK_DEBUG(sk, "AX.25: Appending user data\n"); - /* User data follows immediately after the AX.25 data */ if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { err = -EFAULT; @@ -1564,8 +1560,6 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, if (!ax25->pidincl) *skb_push(skb, 1) = sk->sk_protocol; - SOCK_DEBUG(sk, "AX.25: Transmitting buffer\n"); - if (sk->sk_type == SOCK_SEQPACKET) { /* Connected mode sockets go via the LAPB machine */ if (sk->sk_state != TCP_ESTABLISHED) { @@ -1583,22 +1577,14 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, skb_push(skb, 1 + ax25_addr_size(dp)); - SOCK_DEBUG(sk, "Building AX.25 Header (dp=%p).\n", dp); - - if (dp != NULL) - SOCK_DEBUG(sk, "Num digipeaters=%d\n", dp->ndigi); + /* Building AX.25 Header */ /* Build an AX.25 header */ lv = ax25_addr_build(skb->data, &ax25->source_addr, &sax.sax25_call, dp, AX25_COMMAND, AX25_MODULUS); - SOCK_DEBUG(sk, "Built header (%d bytes)\n",lv); - skb_set_transport_header(skb, lv); - SOCK_DEBUG(sk, "base=%p pos=%p\n", - skb->data, skb_transport_header(skb)); - *skb_transport_header(skb) = AX25_UI; /* Datagram frames go straight out of the door as UI */ diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 06cb02796a0e..732152f718e0 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -591,7 +591,6 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return -EINVAL; } if ((dev = nr_dev_get(&addr->fsa_ax25.sax25_call)) == NULL) { - SOCK_DEBUG(sk, "NET/ROM: bind failed: invalid node callsign\n"); release_sock(sk); return -EADDRNOTAVAIL; } @@ -632,7 +631,7 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) sock_reset_flag(sk, SOCK_ZAPPED); dev_put(dev); release_sock(sk); - SOCK_DEBUG(sk, "NET/ROM: socket is bound\n"); + return 0; } @@ -1082,8 +1081,6 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, sax.sax25_call = nr->dest_addr; } - SOCK_DEBUG(sk, "NET/ROM: sendto: Addresses built.\n"); - /* Build a packet - the conventional user limit is 236 bytes. We can do ludicrously large NetROM frames but must not overflow */ if (len > 65536) { @@ -1091,7 +1088,6 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, goto out; } - SOCK_DEBUG(sk, "NET/ROM: sendto: building packet.\n"); size = len + NR_NETWORK_LEN + NR_TRANSPORT_LEN; if ((skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) @@ -1105,7 +1101,6 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, */ asmptr = skb_push(skb, NR_TRANSPORT_LEN); - SOCK_DEBUG(sk, "Building NET/ROM Header.\n"); /* Build a NET/ROM Transport header */ @@ -1114,15 +1109,12 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, *asmptr++ = 0; /* To be filled in later */ *asmptr++ = 0; /* Ditto */ *asmptr++ = NR_INFO; - SOCK_DEBUG(sk, "Built header.\n"); /* * Put the data on the end */ skb_put(skb, len); - SOCK_DEBUG(sk, "NET/ROM: Appending user data\n"); - /* User data follows immediately after the NET/ROM transport header */ if (memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len)) { kfree_skb(skb); @@ -1130,8 +1122,6 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, goto out; } - SOCK_DEBUG(sk, "NET/ROM: Transmitting buffer\n"); - if (sk->sk_state != TCP_ESTABLISHED) { kfree_skb(skb); err = -ENOTCONN; diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index a80aef6e3d1f..f9ea925ad9cb 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -682,10 +682,8 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS) return -EINVAL; - if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) { - SOCK_DEBUG(sk, "ROSE: bind failed: invalid address\n"); + if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) return -EADDRNOTAVAIL; - } source = &addr->srose_call; @@ -716,7 +714,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) rose_insert_socket(sk); sock_reset_flag(sk, SOCK_ZAPPED); - SOCK_DEBUG(sk, "ROSE: socket is bound\n"); + return 0; } @@ -1109,10 +1107,7 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, srose.srose_digis[n] = rose->dest_digis[n]; } - SOCK_DEBUG(sk, "ROSE: sendto: Addresses built.\n"); - /* Build a packet */ - SOCK_DEBUG(sk, "ROSE: sendto: building packet.\n"); /* Sanity check the packet size */ if (len > 65535) return -EMSGSIZE; @@ -1127,7 +1122,6 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, /* * Put the data on the end */ - SOCK_DEBUG(sk, "ROSE: Appending user data\n"); skb_reset_transport_header(skb); skb_put(skb, len); @@ -1152,8 +1146,6 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, */ asmptr = skb_push(skb, ROSE_MIN_LEN); - SOCK_DEBUG(sk, "ROSE: Building Network Header.\n"); - /* Build a ROSE Network header */ asmptr[0] = ((rose->lci >> 8) & 0x0F) | ROSE_GFI; asmptr[1] = (rose->lci >> 0) & 0xFF; @@ -1162,10 +1154,6 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, if (qbit) asmptr[0] |= ROSE_Q_BIT; - SOCK_DEBUG(sk, "ROSE: Built header.\n"); - - SOCK_DEBUG(sk, "ROSE: Transmitting buffer\n"); - if (sk->sk_state != TCP_ESTABLISHED) { kfree_skb(skb); return -ENOTCONN; -- cgit v1.2.3-58-ga151 From dfa8fc69d92f8418e1296d762f3b1624df59f0ac Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 14 Apr 2011 10:38:22 -0400 Subject: ath9k: avoid using trinary operator w/ TX_STAT_INC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise, you get this: CC [M] drivers/net/wireless/ath/ath9k/hif_usb.o drivers/net/wireless/ath/ath9k/hif_usb.c: In function ‘ath9k_skb_queue_complete’: drivers/net/wireless/ath/ath9k/hif_usb.c:230:12: error: expected expression before ‘do’ make[2]: *** [drivers/net/wireless/ath/ath9k/hif_usb.o] Error 1 make[1]: *** [drivers/net/wireless/ath/ath9k] Error 2 make: *** [drivers/net/wireless/ath/] Error 2 The TX_STAT_INC macro should probably be changed to accomodate such usage, although using a trinary operator in place of an if-else seems questionable to me anyway. Signed-off-by: John W. Linville Acked-by: Sujith Manoharan --- drivers/net/wireless/ath/ath9k/hif_usb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 3b0efab65131..48bcc1a21076 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -227,7 +227,10 @@ static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev, while ((skb = __skb_dequeue(queue)) != NULL) { ath9k_htc_txcompletion_cb(hif_dev->htc_handle, skb, txok); - (txok) ? TX_STAT_INC(skb_success) : TX_STAT_INC(skb_failed); + if (txok) + TX_STAT_INC(skb_success); + else + TX_STAT_INC(skb_failed); } } -- cgit v1.2.3-58-ga151 From 10add41f2b7a7bc1a74ba7bb535a6745cac318a2 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 12 Apr 2011 17:29:29 +0530 Subject: ath9k: Fix improper beacon slot selection in IBSS Request a re-configuration of Beacon related timers on the receipt of the first Beacon frame has to be set only for station mode. Setting beacon sync for IBSS is causing wrong beacon slot selection on beacon generation. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index b56f69e7677b..9193a385ceb2 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -744,7 +744,6 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) cur_conf->dtim_period = 1; ath_set_beacon(sc); - sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; } void ath_set_beacon(struct ath_softc *sc) @@ -762,6 +761,12 @@ void ath_set_beacon(struct ath_softc *sc) break; case NL80211_IFTYPE_STATION: ath_beacon_config_sta(sc, cur_conf); + /* + * Request a re-configuration of Beacon related timers + * on the receipt of the first Beacon frame (i.e., + * after time sync with the AP). + */ + sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; break; default: ath_dbg(common, ATH_DBG_CONFIG, -- cgit v1.2.3-58-ga151 From 7f94f05b24b47f6b70f2322b26876d0636329dfe Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 13 Apr 2011 21:56:42 +0200 Subject: ath5k: disable 5 GHz support if a 2.4 GHz radio is detected On a dual-radio dual-band AR5312 device, the calibration data is shared between the 5 GHz and the 2.4 GHz radio/MAC. Signed-off-by: Felix Fietkau Tested-by: Sedat Dilek Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/caps.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index f77e8a703c5c..7dd88e1c3ff8 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c @@ -94,6 +94,9 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) } } + if ((ah->ah_radio_5ghz_revision & 0xf0) == AR5K_SREV_RAD_2112) + __clear_bit(AR5K_MODE_11A, caps->cap_mode); + /* Set number of supported TX queues */ if (ah->ah_version == AR5K_AR5210) caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU; -- cgit v1.2.3-58-ga151 From 0cb9e06b6359bfa82f46c38a0b43e72d90b84081 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 13 Apr 2011 21:56:43 +0200 Subject: ath: unshare struct ath_bus_ops between ath5k and ath9k This struct is not used in any common code, and moving it out of the ath header makes it easier to add more driver specific ops. Signed-off-by: Felix Fietkau Tested-by: Sedat Dilek Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath.h | 9 +-------- drivers/net/wireless/ath/ath5k/ath5k.h | 6 ++++++ drivers/net/wireless/ath/ath9k/hw.h | 8 ++++++++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 6d7105b7e8f1..7cf4317a2a84 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -123,14 +123,7 @@ struct ath_ops { }; struct ath_common; - -struct ath_bus_ops { - enum ath_bus_type ath_bus_type; - void (*read_cachesize)(struct ath_common *common, int *csz); - bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); - void (*bt_coex_prep)(struct ath_common *common); - void (*extn_synch_en)(struct ath_common *common); -}; +struct ath_bus_ops; struct ath_common { void *ah; diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index e303db7ee6f6..266e548acf78 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1155,6 +1155,12 @@ struct ath5k_hw { struct ath5k_rx_status *); }; +struct ath_bus_ops { + enum ath_bus_type ath_bus_type; + void (*read_cachesize)(struct ath_common *common, int *csz); + bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); +}; + /* * Prototypes */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index a778b66f4438..073bc9e1c792 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -846,6 +846,14 @@ struct ath_hw { u32 ent_mode; }; +struct ath_bus_ops { + enum ath_bus_type ath_bus_type; + void (*read_cachesize)(struct ath_common *common, int *csz); + bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); + void (*bt_coex_prep)(struct ath_common *common); + void (*extn_synch_en)(struct ath_common *common); +}; + static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) { return &ah->common; -- cgit v1.2.3-58-ga151 From fa9bfd61e03e8dbcf110a93b373234d17a732233 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 13 Apr 2011 21:56:44 +0200 Subject: ath5k: add a new bus op for reading the mac address On AHB, the calibration data usually does not contain a valid MAC address, the correct MAC address is stored in the board config. Signed-off-by: Felix Fietkau Tested-by: Sedat Dilek Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ahb.c | 18 ++++++++++++++++++ drivers/net/wireless/ath/ath5k/ath5k.h | 2 +- drivers/net/wireless/ath/ath5k/base.c | 2 +- drivers/net/wireless/ath/ath5k/eeprom.c | 29 ----------------------------- drivers/net/wireless/ath/ath5k/pci.c | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 52 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index 82324e98efef..1374e647f4e6 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c @@ -18,6 +18,7 @@ #include #include +#include #include #include "ath5k.h" #include "debug.h" @@ -62,10 +63,27 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah) return 0; } +static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) +{ + struct ath5k_softc *sc = ah->ah_sc; + struct platform_device *pdev = to_platform_device(sc->dev); + struct ar231x_board_config *bcfg = pdev->dev.platform_data; + u8 *cfg_mac; + + if (to_platform_device(sc->dev)->id == 0) + cfg_mac = bcfg->config->wlan0_mac; + else + cfg_mac = bcfg->config->wlan1_mac; + + memcpy(mac, cfg_mac, ETH_ALEN); + return 0; +} + static const struct ath_bus_ops ath_ahb_bus_ops = { .ath_bus_type = ATH_AHB, .read_cachesize = ath5k_ahb_read_cachesize, .eeprom_read = ath5k_ahb_eeprom_read, + .eeprom_read_mac = ath5k_ahb_eeprom_read_mac, }; /*Initialization*/ diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 266e548acf78..bb50700436fe 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1159,6 +1159,7 @@ struct ath_bus_ops { enum ath_bus_type ath_bus_type; void (*read_cachesize)(struct ath_common *common, int *csz); bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); + int (*eeprom_read_mac)(struct ath5k_hw *ah, u8 *mac); }; /* @@ -1244,7 +1245,6 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah); /* EEPROM access functions */ int ath5k_eeprom_init(struct ath5k_hw *ah); void ath5k_eeprom_detach(struct ath5k_hw *ah); -int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); /* Protocol Control Unit Functions */ diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index c7da00454397..7583841fc29a 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2880,7 +2880,7 @@ ath5k_init(struct ieee80211_hw *hw) INIT_WORK(&sc->reset_work, ath5k_reset_work); INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work); - ret = ath5k_eeprom_read_mac(ah, mac); + ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac); if (ret) { ATH5K_ERR(sc, "unable to read address from EEPROM\n"); goto err_queues; diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index fb12027e0346..e9263e4c7f3e 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -1732,35 +1732,6 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah) return ret; } -/* - * Read the MAC address from eeprom - */ -int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) -{ - u8 mac_d[ETH_ALEN] = {}; - u32 total, offset; - u16 data; - int octet; - - AR5K_EEPROM_READ(0x20, data); - - for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { - AR5K_EEPROM_READ(offset, data); - - total += data; - mac_d[octet + 1] = data & 0xff; - mac_d[octet] = data >> 8; - octet += 2; - } - - if (!total || total == 3 * 0xffff) - return -EINVAL; - - memcpy(mac, mac_d, ETH_ALEN); - - return 0; -} - /***********************\ * Init/Detach functions * diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c index 66598a0d1df0..5cc4a2fe47b6 100644 --- a/drivers/net/wireless/ath/ath5k/pci.c +++ b/drivers/net/wireless/ath/ath5k/pci.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "../ath.h" #include "ath5k.h" #include "debug.h" @@ -108,11 +109,42 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah) return 0; } +/* + * Read the MAC address from eeprom or platform_data + */ +static int ath5k_pci_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) +{ + u8 mac_d[ETH_ALEN] = {}; + u32 total, offset; + u16 data; + int octet; + + AR5K_EEPROM_READ(0x20, data); + + for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { + AR5K_EEPROM_READ(offset, data); + + total += data; + mac_d[octet + 1] = data & 0xff; + mac_d[octet] = data >> 8; + octet += 2; + } + + if (!total || total == 3 * 0xffff) + return -EINVAL; + + memcpy(mac, mac_d, ETH_ALEN); + + return 0; +} + + /* Common ath_bus_opts structure */ static const struct ath_bus_ops ath_pci_bus_ops = { .ath_bus_type = ATH_PCI, .read_cachesize = ath5k_pci_read_cachesize, .eeprom_read = ath5k_pci_eeprom_read, + .eeprom_read_mac = ath5k_pci_eeprom_read_mac, }; /********************\ -- cgit v1.2.3-58-ga151 From 32377b6cf75247cbdd0640efb43bef992efe3b68 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 13 Apr 2011 21:56:45 +0200 Subject: ath5k: fix the EEPROM check for hw AES crypto support EEPROM version 5.0 adds a new field for disabling AES support, having an older version means that AES is present. This patch fixes hw AES crypto support on AR5312 boards, which have an older EEPROM version. Signed-off-by: Felix Fietkau Tested-by: Sedat Dilek Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/attach.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index bc8240560488..326d7c84c912 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -318,7 +318,7 @@ int ath5k_hw_init(struct ath5k_softc *sc) AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211); if (srev >= AR5K_SREV_AR5212_V4 && - (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && + (ee->ee_version < AR5K_EEPROM_VERSION_5_0 || !AR5K_EEPROM_AES_DIS(ee->ee_misc5))) common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; -- cgit v1.2.3-58-ga151 From 3a9dddea89eb2132ba919fe04cb3b44a3b1e6db7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 13 Apr 2011 21:56:46 +0200 Subject: ath5k: disable 5 GHz support for the dualband PHY chip on dual-radio AR5312 There are two variants of AR5312 dual-band devices, one single-radio and the other one dual-radio. On the dual-radio board, the first MAC only supports 5 GHz, even though it has a dual-band PHY. The 2.4 GHz part of this phy is used in pass-through mode, connecting the second MAC with the second PHY. Disable 2.4 GHz for the first MAC on an AR5312, but only if the board configuration indicates a dual-radio device. Signed-off-by: Felix Fietkau Tested-by: Sedat Dilek Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ahb.c | 10 ++++++++++ drivers/net/wireless/ath/ath5k/attach.c | 5 +++++ drivers/net/wireless/ath/ath5k/base.h | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index 1374e647f4e6..ea9982781559 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c @@ -160,6 +160,16 @@ static int ath_ahb_probe(struct platform_device *pdev) else reg |= AR5K_AR5312_ENABLE_WLAN1; __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); + + /* + * On a dual-band AR5312, the multiband radio is only + * used as pass-through. Disable 2 GHz support in the + * driver for it + */ + if (to_platform_device(sc->dev)->id == 0 && + (bcfg->config->flags & (BD_WLAN0|BD_WLAN1)) == + (BD_WLAN1|BD_WLAN0)) + __set_bit(ATH_STAT_2G_DISABLED, sc->status); } ret = ath5k_init_softc(sc, &ath_ahb_bus_ops); diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 326d7c84c912..1588401de3c4 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -313,6 +313,11 @@ int ath5k_hw_init(struct ath5k_softc *sc) goto err; } + if (test_bit(ATH_STAT_2G_DISABLED, sc->status)) { + __clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode); + __clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode); + } + /* Crypto settings */ common->keymax = (sc->ah->ah_version == AR5K_AR5210 ? AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211); diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 4c4e36064a3b..b294f3305011 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -193,12 +193,13 @@ struct ath5k_softc { dma_addr_t desc_daddr; /* DMA (physical) address */ size_t desc_len; /* size of TX/RX descriptors */ - DECLARE_BITMAP(status, 5); + DECLARE_BITMAP(status, 6); #define ATH_STAT_INVALID 0 /* disable hardware accesses */ #define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ #define ATH_STAT_PROMISC 2 #define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ #define ATH_STAT_STARTED 4 /* opened & irqs enabled */ +#define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */ unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ struct ieee80211_channel *curchan; /* current h/w channel */ -- cgit v1.2.3-58-ga151 From 600f5d909a54a8dccf8c8c23898fc2e91bc0953e Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 13 Apr 2011 17:27:06 -0700 Subject: mwifiex: cleanup ioctl wait queue and abstraction layer 1) remove mwifiex_alloc_fill_wait_queue() and mwifiex_request_ioctl() 2) avoid dynamic allocation of wait queue 3) remove unnecessary mwifiex_error_code macros that were used mainly by the wait queue status code 4) remove some abstraction functions 5) split mwifiex_prepare_cmd() to mwifiex_send_cmd_async() and mwifiex_send_sync() to handle asynchronous and synchronous commands respectively Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n.c | 13 +- drivers/net/wireless/mwifiex/11n_rxreorder.c | 2 +- drivers/net/wireless/mwifiex/README | 2 +- drivers/net/wireless/mwifiex/cfg80211.c | 113 ++- drivers/net/wireless/mwifiex/cmdevt.c | 179 ++--- drivers/net/wireless/mwifiex/debugfs.c | 4 +- drivers/net/wireless/mwifiex/decl.h | 24 +- drivers/net/wireless/mwifiex/init.c | 3 +- drivers/net/wireless/mwifiex/join.c | 90 +-- drivers/net/wireless/mwifiex/main.c | 71 +- drivers/net/wireless/mwifiex/main.h | 123 +--- drivers/net/wireless/mwifiex/scan.c | 126 +--- drivers/net/wireless/mwifiex/sdio.c | 11 +- drivers/net/wireless/mwifiex/sta_cmd.c | 60 +- drivers/net/wireless/mwifiex/sta_cmdresp.c | 29 +- drivers/net/wireless/mwifiex/sta_event.c | 25 +- drivers/net/wireless/mwifiex/sta_ioctl.c | 1008 ++++---------------------- drivers/net/wireless/mwifiex/sta_tx.c | 2 +- drivers/net/wireless/mwifiex/util.c | 51 +- 19 files changed, 502 insertions(+), 1434 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 73a6e62f5680..edf4c274fa9b 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -541,9 +541,8 @@ mwifiex_cfg_tx_buf(struct mwifiex_private *priv, else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_8K) curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_8K; if (curr_tx_buf_size != tx_buf) - mwifiex_prepare_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, - HostCmd_ACT_GEN_SET, 0, - NULL, &tx_buf); + mwifiex_send_cmd_async(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, + HostCmd_ACT_GEN_SET, 0, &tx_buf); return; } @@ -694,8 +693,8 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN); /* We don't wait for the response of this command */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_ADDBA_REQ, - 0, 0, NULL, &add_ba_req); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_REQ, + 0, 0, &add_ba_req); return ret; } @@ -722,8 +721,8 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN); /* We don't wait for the response of this command */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, - HostCmd_ACT_GEN_SET, 0, NULL, &delba); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_DELBA, + HostCmd_ACT_GEN_SET, 0, &delba); return ret; } diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index 8e94e620e6f4..ef46d0a8a6d0 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -609,7 +609,7 @@ void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv, delba.del_ba_param_set |= cpu_to_le16( (u16) event->origninator << DELBA_INITIATOR_POS); delba.reason_code = cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); - mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, NULL, &delba); + mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_DELBA, 0, 0, &delba); return; } diff --git a/drivers/net/wireless/mwifiex/README b/drivers/net/wireless/mwifiex/README index 338377f7093b..b55badef4660 100644 --- a/drivers/net/wireless/mwifiex/README +++ b/drivers/net/wireless/mwifiex/README @@ -157,7 +157,7 @@ info mp_wr_bitmap = cmd_resp_received = <0/1, no cmd response to process/response received and yet to process> event_received = <0/1, no event to process/event received and yet to process> - ioctl_pending = + cmd_pending = tx_pending = rx_pending = diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index ec0895f4e8d3..a1ff490da836 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -139,8 +139,16 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, { int ret = 0; struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + struct mwifiex_power_cfg power_cfg; - ret = mwifiex_set_tx_power(priv, type, dbm); + if (type == NL80211_TX_POWER_FIXED) { + power_cfg.is_power_auto = 0; + power_cfg.power_level = dbm; + } else { + power_cfg.is_power_auto = 1; + } + + ret = mwifiex_set_tx_power(priv, &power_cfg); return ret; } @@ -157,13 +165,15 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy, { int ret = 0; struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + u32 ps_mode; if (timeout) wiphy_dbg(wiphy, "info: ignoring the timeout value" " for IEEE power save\n"); - ret = mwifiex_drv_set_power(priv, enabled); + ps_mode = enabled; + ret = mwifiex_drv_set_power(priv, &ps_mode); return ret; } @@ -291,8 +301,8 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) domain_info->no_of_triplet = no_of_triplet; /* Send cmd to FW to set domain info */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, - HostCmd_ACT_GEN_SET, 0, NULL, NULL); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, + HostCmd_ACT_GEN_SET, 0, NULL); if (ret) wiphy_err(wiphy, "11D: setting domain info in FW\n"); @@ -347,7 +357,6 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, { struct mwifiex_chan_freq_power cfp; int ret = 0; - int status = 0; struct mwifiex_ds_band_cfg band_cfg; u32 config_bands = 0; struct wiphy *wiphy = priv->wdev->wiphy; @@ -370,10 +379,9 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, band_cfg.sec_chan_offset = mwifiex_cfg80211_channel_type_to_mwifiex_channels (channel_type); - status = mwifiex_radio_ioctl_band_cfg(priv, HostCmd_ACT_GEN_SET, - &band_cfg); + ret = mwifiex_set_radio_band_cfg(priv, &band_cfg); - if (status) + if (ret) return -EFAULT; mwifiex_send_domain_info_cmd_fw(wiphy); } @@ -389,8 +397,8 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, /* Convert frequency to channel */ cfp.channel = ieee80211_frequency_to_channel(chan->center_freq); - status = mwifiex_bss_ioctl_channel(priv, HostCmd_ACT_GEN_SET, &cfp); - if (status) + ret = mwifiex_bss_set_channel(priv, &cfp); + if (ret) return -EFAULT; ret = mwifiex_drv_change_adhoc_chan(priv, cfp.channel); @@ -422,66 +430,45 @@ mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, /* * This function sets the fragmentation threshold. * - * This function creates an IOCTL request, populates it accordingly - * and issues an IOCTL. - * - * The fragmentation threshold value must lies between MWIFIEX_FRAG_MIN_VALUE + * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE * and MWIFIEX_FRAG_MAX_VALUE. */ static int mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) { int ret = 0; - int status = 0; - struct mwifiex_wait_queue *wait = NULL; - u8 wait_option = MWIFIEX_IOCTL_WAIT; if (frag_thr < MWIFIEX_FRAG_MIN_VALUE || frag_thr > MWIFIEX_FRAG_MAX_VALUE) return -EINVAL; - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; + /* Send request to firmware */ + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_SET, FRAG_THRESH_I, + &frag_thr); - status = mwifiex_snmp_mib_ioctl(priv, wait, FRAG_THRESH_I, - HostCmd_ACT_GEN_SET, &frag_thr); - - if (mwifiex_request_ioctl(priv, wait, status, wait_option)) - ret = -EFAULT; - - kfree(wait); return ret; } /* * This function sets the RTS threshold. - * - * This function creates an IOCTL request, populates it accordingly - * and issues an IOCTL. + + * The rts value must lie between MWIFIEX_RTS_MIN_VALUE + * and MWIFIEX_RTS_MAX_VALUE. */ static int mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr) { int ret = 0; - struct mwifiex_wait_queue *wait = NULL; - int status = 0; - u8 wait_option = MWIFIEX_IOCTL_WAIT; if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE) rts_thr = MWIFIEX_RTS_MAX_VALUE; - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; - - status = mwifiex_snmp_mib_ioctl(priv, wait, RTS_THRESH_I, - HostCmd_ACT_GEN_SET, &rts_thr); - - if (mwifiex_request_ioctl(priv, wait, status, wait_option)) - ret = -EFAULT; + /* Send request to firmware */ + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_SET, RTS_THRESH_I, + &rts_thr); - kfree(wait); return ret; } @@ -518,7 +505,6 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, { int ret = 0; struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct mwifiex_wait_queue *wait = NULL; if (priv->bss_mode == type) { wiphy_warn(wiphy, "already set to required type\n"); @@ -545,24 +531,13 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, return -EINVAL; } - wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); - if (!wait) - return -ENOMEM; - - mwifiex_deauthenticate(priv, wait, NULL); + mwifiex_deauthenticate(priv, NULL); priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_SET_BSS_MODE, - HostCmd_ACT_GEN_SET, 0, wait, NULL); - if (!ret) - ret = -EINPROGRESS; + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE, + HostCmd_ACT_GEN_SET, 0, NULL); - ret = mwifiex_request_ioctl(priv, wait, ret, MWIFIEX_IOCTL_WAIT); - if (ret) - ret = -EFAULT; - - kfree(wait); return ret; } @@ -592,7 +567,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, /* Get signal information from the firmware */ memset(&signal, 0, sizeof(struct mwifiex_ds_get_signal)); - if (mwifiex_get_signal_info(priv, MWIFIEX_IOCTL_WAIT, &signal)) { + if (mwifiex_get_signal_info(priv, &signal)) { dev_err(priv->adapter->dev, "getting signal information\n"); ret = -EFAULT; } @@ -750,7 +725,7 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, return -EBUSY; priv->disconnect = 1; - if (mwifiex_disconnect(priv, MWIFIEX_IOCTL_WAIT, NULL)) + if (mwifiex_deauthenticate(priv, NULL)) return -EFAULT; wiphy_dbg(wiphy, "info: successfully disconnected from %pM:" @@ -838,8 +813,8 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, u8 element_id, element_len; memset(&scan_resp, 0, sizeof(scan_resp)); - if (mwifiex_get_scan_table(priv, MWIFIEX_IOCTL_WAIT, &scan_resp)) - return -EFAULT; + scan_resp.scan_table = (u8 *) priv->adapter->scan_table; + scan_resp.num_in_scan_table = priv->adapter->num_in_scan_table; #define MAX_IE_BUF 2048 ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL); @@ -986,7 +961,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, } /* disconnect before try to associate */ - mwifiex_disconnect(priv, MWIFIEX_IOCTL_WAIT, NULL); + mwifiex_deauthenticate(priv, NULL); if (channel) ret = mwifiex_set_rf_channel(priv, channel, @@ -1046,7 +1021,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, } done: /* Do specific SSID scanning */ - if (mwifiex_request_scan(priv, MWIFIEX_IOCTL_WAIT, &req_ssid)) { + if (mwifiex_request_scan(priv, &req_ssid)) { dev_err(priv->adapter->dev, "scan error\n"); return -EFAULT; } @@ -1055,8 +1030,7 @@ done: memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid)); if (mode != NL80211_IFTYPE_ADHOC) { - if (mwifiex_find_best_bss(priv, MWIFIEX_IOCTL_WAIT, - &ssid_bssid)) + if (mwifiex_find_best_bss(priv, &ssid_bssid)) return -EFAULT; /* Inform the BSS information to kernel, otherwise * kernel will give a panic after successful assoc */ @@ -1072,7 +1046,10 @@ done: /* Connect to BSS by ESSID */ memset(&ssid_bssid.bssid, 0, ETH_ALEN); - if (mwifiex_bss_start(priv, MWIFIEX_IOCTL_WAIT, &ssid_bssid)) + if (!netif_queue_stopped(priv->netdev)) + netif_stop_queue(priv->netdev); + + if (mwifiex_bss_start(priv, &ssid_bssid)) return -EFAULT; if (mode == NL80211_IFTYPE_ADHOC) { @@ -1176,7 +1153,7 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n", priv->cfg_bssid); - if (mwifiex_disconnect(priv, MWIFIEX_IOCTL_WAIT, NULL)) + if (mwifiex_deauthenticate(priv, NULL)) return -EFAULT; queue_work(priv->workqueue, &priv->cfg_workqueue); diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 8676480ead94..bb6fecd77619 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -36,11 +36,12 @@ static void mwifiex_init_cmd_node(struct mwifiex_private *priv, struct cmd_ctrl_node *cmd_node, - u32 cmd_oid, void *wait_queue, void *data_buf) + u32 cmd_oid, void *data_buf) { cmd_node->priv = priv; cmd_node->cmd_oid = cmd_oid; - cmd_node->wq_buf = wait_queue; + cmd_node->wait_q_enabled = priv->adapter->cmd_wait_q_required; + priv->adapter->cmd_wait_q_required = false; cmd_node->data_buf = data_buf; cmd_node->cmd_skb = cmd_node->skb; } @@ -86,8 +87,8 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, { cmd_node->cmd_oid = 0; cmd_node->cmd_flag = 0; - cmd_node->wq_buf = NULL; cmd_node->data_buf = NULL; + cmd_node->wait_q_enabled = false; if (cmd_node->resp_skb) { mwifiex_recv_complete(adapter, cmd_node->resp_skb, 0); @@ -97,30 +98,6 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, return; } -/* - * This function returns a command node from the pending queue which - * matches the given IOCTL request. - */ -static struct cmd_ctrl_node * -mwifiex_get_pending_ioctl_cmd(struct mwifiex_adapter *adapter, - struct mwifiex_wait_queue *wait_queue) -{ - unsigned long flags; - struct cmd_ctrl_node *cmd_node; - - spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); - list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) { - if (cmd_node->wq_buf == wait_queue) { - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, - flags); - return cmd_node; - } - } - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - - return NULL; -} - /* * This function sends a host command to the firmware. * @@ -155,7 +132,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, struct mwifiex_adapter *adapter = priv->adapter; int ret = 0; struct host_cmd_ds_command *host_cmd; - struct mwifiex_wait_queue *wait_queue = NULL; uint16_t cmd_code; uint16_t cmd_size; struct timeval tstamp; @@ -165,15 +141,13 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, return -1; host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); - if (cmd_node->wq_buf) - wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf; /* Sanity test */ if (host_cmd == NULL || host_cmd->size == 0) { dev_err(adapter->dev, "DNLD_CMD: host_cmd is null" " or cmd size is 0, not sending\n"); - if (wait_queue) - wait_queue->status = MWIFIEX_ERROR_CMD_DNLD_FAIL; + if (cmd_node->wait_q_enabled) + adapter->cmd_wait_q.status = -1; mwifiex_insert_cmd_to_free_q(adapter, cmd_node); return -1; } @@ -210,8 +184,8 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, if (ret == -1) { dev_err(adapter->dev, "DNLD_CMD: host to card failed\n"); - if (wait_queue) - wait_queue->status = MWIFIEX_ERROR_CMD_DNLD_FAIL; + if (cmd_node->wait_q_enabled) + adapter->cmd_wait_q.status = -1; mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); @@ -437,7 +411,31 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) } /* - * This function prepares a command before sending it to the firmware. + * This function is used to send synchronous command to the firmware. + * + * it allocates a wait queue for the command and wait for the command + * response. + */ +int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, + u16 cmd_action, u32 cmd_oid, void *data_buf) +{ + int ret = 0; + struct mwifiex_adapter *adapter = priv->adapter; + + adapter->cmd_wait_q_required = true; + adapter->cmd_wait_q.condition = false; + + ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid, + data_buf); + if (!ret) + ret = mwifiex_wait_queue_complete(adapter); + + return ret; +} + + +/* + * This function prepares a command and asynchronously send it to the firmware. * * Preparation includes - * - Sanity tests to make sure the card is still present or the FW @@ -447,9 +445,8 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) * - Fill up the non-default parameters and buffer pointers * - Add the command to pending queue */ -int mwifiex_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, - u16 cmd_action, u32 cmd_oid, - void *wait_queue, void *data_buf) +int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, + u16 cmd_action, u32 cmd_oid, void *data_buf) { int ret = 0; struct mwifiex_adapter *adapter = priv->adapter; @@ -487,7 +484,7 @@ int mwifiex_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, } /* Initialize the command node */ - mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, wait_queue, data_buf); + mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf); if (!cmd_node->cmd_skb) { dev_err(adapter->dev, "PREP_CMD: no free cmd buf\n"); @@ -537,18 +534,13 @@ void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, struct cmd_ctrl_node *cmd_node) { - struct mwifiex_wait_queue *wait_queue = NULL; unsigned long flags; if (cmd_node == NULL) return; - if (cmd_node->wq_buf) { - wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf; - if (wait_queue->status != MWIFIEX_ERROR_NO_ERROR) - mwifiex_ioctl_complete(adapter, wait_queue, -1); - else - mwifiex_ioctl_complete(adapter, wait_queue, 0); - } + + if (cmd_node->wait_q_enabled) + mwifiex_complete_cmd(adapter); /* Clean the node */ mwifiex_clean_cmd_node(adapter, cmd_node); @@ -694,7 +686,6 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) uint16_t orig_cmdresp_no; uint16_t cmdresp_no; uint16_t cmdresp_result; - struct mwifiex_wait_queue *wait_queue = NULL; struct timeval tstamp; unsigned long flags; @@ -708,10 +699,6 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) return -1; } - if (adapter->curr_cmd->wq_buf) - wait_queue = (struct mwifiex_wait_queue *) - adapter->curr_cmd->wq_buf; - adapter->num_cmd_timeout = 0; resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data; @@ -766,8 +753,8 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) if (!(orig_cmdresp_no & HostCmd_RET_BIT)) { dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n"); - if (wait_queue) - wait_queue->status = MWIFIEX_ERROR_FW_CMDRESP; + if (adapter->curr_cmd->wait_q_enabled) + adapter->cmd_wait_q.status = -1; mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); @@ -783,8 +770,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) ret = mwifiex_ret_802_11_hs_cfg(priv, resp); } else { /* handle response */ - ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp, - wait_queue); + ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp); } /* Check init command response */ @@ -799,10 +785,10 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) } if (adapter->curr_cmd) { - if (wait_queue && (!ret)) - wait_queue->status = MWIFIEX_ERROR_NO_ERROR; - else if (wait_queue && (ret == -1)) - wait_queue->status = MWIFIEX_ERROR_CMD_RESP_FAIL; + if (adapter->curr_cmd->wait_q_enabled && (!ret)) + adapter->cmd_wait_q.status = 0; + else if (adapter->curr_cmd->wait_q_enabled && (ret == -1)) + adapter->cmd_wait_q.status = -1; /* Clean up and put current command back to cmd_free_q */ mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); @@ -826,7 +812,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context) struct mwifiex_adapter *adapter = (struct mwifiex_adapter *) function_context; struct cmd_ctrl_node *cmd_node = NULL; - struct mwifiex_wait_queue *wait_queue = NULL; struct timeval tstamp; adapter->num_cmd_timeout++; @@ -836,10 +821,8 @@ mwifiex_cmd_timeout_func(unsigned long function_context) return; } cmd_node = adapter->curr_cmd; - if (cmd_node->wq_buf) { - wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf; - wait_queue->status = MWIFIEX_ERROR_CMD_TIMEOUT; - } + if (cmd_node->wait_q_enabled) + adapter->cmd_wait_q.status = -ETIMEDOUT; if (cmd_node) { adapter->dbg.timeout_cmd_id = @@ -903,18 +886,15 @@ void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) { struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; - struct mwifiex_wait_queue *wait_queue = NULL; unsigned long flags; /* Cancel current cmd */ - if ((adapter->curr_cmd) && (adapter->curr_cmd->wq_buf)) { - wait_queue = - (struct mwifiex_wait_queue *) adapter->curr_cmd->wq_buf; + if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd->wq_buf = NULL; + adapter->curr_cmd->wait_q_enabled = false; spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL; - mwifiex_ioctl_complete(adapter, wait_queue, -1); + adapter->cmd_wait_q.status = -1; + mwifiex_complete_cmd(adapter); } /* Cancel all pending command */ spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); @@ -923,12 +903,10 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) list_del(&cmd_node->list); spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - if (cmd_node->wq_buf) { - wait_queue = - (struct mwifiex_wait_queue *) cmd_node->wq_buf; - wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL; - mwifiex_ioctl_complete(adapter, wait_queue, -1); - cmd_node->wq_buf = NULL; + if (cmd_node->wait_q_enabled) { + adapter->cmd_wait_q.status = -1; + mwifiex_complete_cmd(adapter); + cmd_node->wait_q_enabled = false; } mwifiex_insert_cmd_to_free_q(adapter, cmd_node); spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); @@ -942,7 +920,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) list_del(&cmd_node->list); spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - cmd_node->wq_buf = NULL; + cmd_node->wait_q_enabled = false; mwifiex_insert_cmd_to_free_q(adapter, cmd_node); spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); } @@ -964,8 +942,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) * are cancelled. */ void -mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter, - struct mwifiex_wait_queue *wait_queue) +mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) { struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; unsigned long cmd_flags; @@ -974,45 +951,33 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter, uint16_t cancel_scan_cmd = false; if ((adapter->curr_cmd) && - (adapter->curr_cmd->wq_buf == wait_queue)) { + (adapter->curr_cmd->wait_q_enabled)) { spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); cmd_node = adapter->curr_cmd; - cmd_node->wq_buf = NULL; + cmd_node->wait_q_enabled = false; cmd_node->cmd_flag |= CMD_F_CANCELED; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - } - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); - while (1) { - cmd_node = mwifiex_get_pending_ioctl_cmd(adapter, wait_queue); - if (!cmd_node) - break; - spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags); list_del(&cmd_node->list); spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_pending_q_flags); - - cmd_node->wq_buf = NULL; mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); } - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); + /* Cancel all pending scan command */ spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_pending_q_flags); list_for_each_entry_safe(cmd_node, tmp_node, &adapter->scan_pending_q, list) { - if (cmd_node->wq_buf == wait_queue) { - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - scan_pending_q_flags); - cmd_node->wq_buf = NULL; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - spin_lock_irqsave(&adapter->scan_pending_q_lock, - scan_pending_q_flags); - cancel_scan_cmd = true; - } + list_del(&cmd_node->list); + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, + scan_pending_q_flags); + cmd_node->wait_q_enabled = false; + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + spin_lock_irqsave(&adapter->scan_pending_q_lock, + scan_pending_q_flags); + cancel_scan_cmd = true; } spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_pending_q_flags); @@ -1022,8 +987,8 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter, adapter->scan_processing = false; spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); } - wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL; - mwifiex_ioctl_complete(adapter, wait_queue, -1); + adapter->cmd_wait_q.status = -1; + mwifiex_complete_cmd(adapter); return; } diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index 63b09692f27d..77d7c777ea66 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c @@ -129,8 +129,8 @@ static struct mwifiex_debug_data items[] = { item_addr(event_received), 1}, /* variables defined in struct mwifiex_adapter */ - {"ioctl_pending", adapter_item_size(ioctl_pending), - adapter_item_addr(ioctl_pending), 1}, + {"cmd_pending", adapter_item_size(cmd_pending), + adapter_item_addr(cmd_pending), 1}, {"tx_pending", adapter_item_size(tx_pending), adapter_item_addr(tx_pending), 1}, {"rx_pending", adapter_item_size(rx_pending), diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index c3c15f9e757e..8364b62c3298 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h @@ -61,23 +61,6 @@ #define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0) -enum mwifiex_error_code { - MWIFIEX_ERROR_NO_ERROR = 0, - MWIFIEX_ERROR_FW_NOT_READY = 0x00000001, - MWIFIEX_ERROR_FW_BUSY, - MWIFIEX_ERROR_FW_CMDRESP, - MWIFIEX_ERROR_PKT_SIZE_INVALID = 0x80000001, - MWIFIEX_ERROR_PKT_TIMEOUT, - MWIFIEX_ERROR_CMD_INVALID, - MWIFIEX_ERROR_CMD_TIMEOUT, - MWIFIEX_ERROR_CMD_DNLD_FAIL, - MWIFIEX_ERROR_CMD_CANCEL, - MWIFIEX_ERROR_CMD_RESP_FAIL, - MWIFIEX_ERROR_ASSOC_FAIL, - MWIFIEX_ERROR_EVENT_UNKNOWN, - MWIFIEX_ERROR_INVALID_PARAMETER, -}; - enum mwifiex_bss_type { MWIFIEX_BSS_TYPE_STA = 0, MWIFIEX_BSS_TYPE_UAP = 1, @@ -112,12 +95,9 @@ struct mwifiex_802_11_ssid { }; struct mwifiex_wait_queue { - u32 bss_index; - wait_queue_head_t *wait; - u16 *condition; - u32 start_time; + wait_queue_head_t wait; + u16 condition; int status; - u32 enabled; }; struct mwifiex_rxinfo { diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 8189862da1f9..26931d5f950f 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -35,7 +35,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) { struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_bss_prio_node *bss_prio; - int status = 0; unsigned long flags; bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL); @@ -59,7 +58,7 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) spin_unlock_irqrestore(&adapter->bss_prio_tbl[priv->bss_priority] .bss_prio_lock, flags); - return status; + return 0; } /* diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 7a9e0b5962ed..60d25c690c07 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -590,11 +590,10 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, * an association success (0) or failure (non-zero). */ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, void *wq_buf) + struct host_cmd_ds_command *resp) { + struct mwifiex_adapter *adapter = priv->adapter; int ret = 0; - struct mwifiex_wait_queue *wait_queue = - (struct mwifiex_wait_queue *) wq_buf; struct ieee_types_assoc_rsp *assoc_rsp; struct mwifiex_bssdescriptor *bss_desc; u8 enable_data = true; @@ -718,16 +717,11 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, done: /* Need to indicate IOCTL complete */ - if (wait_queue) { - if (ret) { - if (assoc_rsp->status_code) - wait_queue->status = - le16_to_cpu(assoc_rsp->status_code); - else - wait_queue->status = MWIFIEX_ERROR_ASSOC_FAIL; - } else { - wait_queue->status = MWIFIEX_ERROR_NO_ERROR; - } + if (adapter->curr_cmd->wait_q_enabled) { + if (ret) + adapter->cmd_wait_q.status = -1; + else + adapter->cmd_wait_q.status = 0; } return ret; @@ -885,9 +879,9 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, mwifiex_get_active_data_rates(priv, adhoc_start->DataRate); if ((adapter->adhoc_start_band & BAND_G) && (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) { - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, - 0, NULL, &priv->curr_pkt_filter); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, + HostCmd_ACT_GEN_SET, 0, + &priv->curr_pkt_filter); if (ret) { dev_err(adapter->dev, @@ -1066,9 +1060,9 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, priv-> curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, NULL, - &curr_pkt_filter); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, + HostCmd_ACT_GEN_SET, 0, + &curr_pkt_filter); if (ret) { dev_err(priv->adapter->dev, "ADHOC_J_CMD: G Protection config failed\n"); @@ -1192,11 +1186,10 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, * saves the beacon buffer. */ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, void *wq_buf) + struct host_cmd_ds_command *resp) { int ret = 0; - struct mwifiex_wait_queue *wait_queue = - (struct mwifiex_wait_queue *) wq_buf; + struct mwifiex_adapter *adapter = priv->adapter; struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result; struct mwifiex_bssdescriptor *bss_desc; u16 command = le16_to_cpu(resp->command); @@ -1264,11 +1257,11 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, done: /* Need to indicate IOCTL complete */ - if (wait_queue) { + if (adapter->curr_cmd->wait_q_enabled) { if (ret) - wait_queue->status = MWIFIEX_ERROR_ASSOC_FAIL; + adapter->cmd_wait_q.status = -1; else - wait_queue->status = MWIFIEX_ERROR_NO_ERROR; + adapter->cmd_wait_q.status = 0; } @@ -1283,7 +1276,7 @@ done: * command to firmware. */ int mwifiex_associate(struct mwifiex_private *priv, - void *wait_queue, struct mwifiex_bssdescriptor *bss_desc) + struct mwifiex_bssdescriptor *bss_desc) { int ret = 0; u8 current_bssid[ETH_ALEN]; @@ -1301,9 +1294,8 @@ int mwifiex_associate(struct mwifiex_private *priv, retrieval */ priv->assoc_rsp_size = 0; - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_ASSOCIATE, - HostCmd_ACT_GEN_SET, 0, wait_queue, - bss_desc); + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_ASSOCIATE, + HostCmd_ACT_GEN_SET, 0, bss_desc); return ret; } @@ -1315,7 +1307,7 @@ int mwifiex_associate(struct mwifiex_private *priv, */ int mwifiex_adhoc_start(struct mwifiex_private *priv, - void *wait_queue, struct mwifiex_802_11_ssid *adhoc_ssid) + struct mwifiex_802_11_ssid *adhoc_ssid) { int ret = 0; @@ -1326,9 +1318,8 @@ mwifiex_adhoc_start(struct mwifiex_private *priv, dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n", priv->curr_bss_params.band); - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_AD_HOC_START, - HostCmd_ACT_GEN_SET, 0, wait_queue, - adhoc_ssid); + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START, + HostCmd_ACT_GEN_SET, 0, adhoc_ssid); return ret; } @@ -1340,7 +1331,7 @@ mwifiex_adhoc_start(struct mwifiex_private *priv, * if already not connected to the requested SSID. */ int mwifiex_adhoc_join(struct mwifiex_private *priv, - void *wait_queue, struct mwifiex_bssdescriptor *bss_desc) + struct mwifiex_bssdescriptor *bss_desc) { int ret = 0; @@ -1369,9 +1360,8 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv, dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n", priv->curr_bss_params.band); - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, - HostCmd_ACT_GEN_SET, 0, wait_queue, - bss_desc); + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, + HostCmd_ACT_GEN_SET, 0, bss_desc); return ret; } @@ -1380,9 +1370,7 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv, * This function deauthenticates/disconnects from infra network by sending * deauthentication request. */ -static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - u8 *mac) +static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac) { u8 mac_address[ETH_ALEN]; int ret = 0; @@ -1400,11 +1388,8 @@ static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, bss_descriptor.mac_address, ETH_ALEN); } - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, - HostCmd_ACT_GEN_SET, 0, wait, &mac_address); - - if (!ret && wait) - ret = -EINPROGRESS; + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, + HostCmd_ACT_GEN_SET, 0, &mac_address); return ret; } @@ -1415,26 +1400,23 @@ static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, * In case of infra made, it sends deauthentication request, and * in case of ad-hoc mode, a stop network request is sent to the firmware. */ -int mwifiex_deauthenticate(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, u8 *mac) +int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) { int ret = 0; if (priv->media_connected) { if (priv->bss_mode == NL80211_IFTYPE_STATION) { - ret = mwifiex_deauthenticate_infra(priv, wait, mac); + ret = mwifiex_deauthenticate_infra(priv, mac); } else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { - ret = mwifiex_prepare_cmd(priv, - HostCmd_CMD_802_11_AD_HOC_STOP, - HostCmd_ACT_GEN_SET, 0, wait, NULL); - - if (!ret && wait) - ret = -EINPROGRESS; + ret = mwifiex_send_cmd_sync(priv, + HostCmd_CMD_802_11_AD_HOC_STOP, + HostCmd_ACT_GEN_SET, 0, NULL); } } return ret; } +EXPORT_SYMBOL_GPL(mwifiex_deauthenticate); /* * This function converts band to radio type used in channel TLV. diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index ed89ca41a902..df665db8c433 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -597,16 +597,23 @@ mwifiex_set_mac_address(struct net_device *dev, void *addr) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); struct sockaddr *hw_addr = (struct sockaddr *) addr; + int ret = 0; memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN); - if (mwifiex_request_set_mac_address(priv)) { - dev_err(priv->adapter->dev, "set MAC address failed\n"); - return -EFAULT; - } + /* Send request to firmware */ + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_MAC_ADDRESS, + HostCmd_ACT_GEN_SET, 0, NULL); + + if (!ret) + memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN); + else + dev_err(priv->adapter->dev, "set mac address failed: ret=%d" + "\n", ret); + memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); - return 0; + return ret; } /* @@ -615,7 +622,20 @@ mwifiex_set_mac_address(struct net_device *dev, void *addr) static void mwifiex_set_multicast_list(struct net_device *dev) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - mwifiex_request_set_multicast_list(priv, dev); + struct mwifiex_multicast_list mcast_list; + + if (dev->flags & IFF_PROMISC) { + mcast_list.mode = MWIFIEX_PROMISC_MODE; + } else if (dev->flags & IFF_ALLMULTI || + netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) { + mcast_list.mode = MWIFIEX_ALL_MULTI_MODE; + } else { + mcast_list.mode = MWIFIEX_MULTICAST_MODE; + if (netdev_mc_count(dev)) + mcast_list.num_multicast_addr = + mwifiex_copy_mcast_addr(&mcast_list, dev); + } + mwifiex_request_set_multicast_list(priv, &mcast_list); } /* @@ -677,9 +697,6 @@ mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev) { dev->netdev_ops = &mwifiex_netdev_ops; /* Initialize private structure */ - init_waitqueue_head(&priv->ioctl_wait_q); - init_waitqueue_head(&priv->cmd_wait_q); - init_waitqueue_head(&priv->w_stats_wait_q); priv->current_key_index = 0; priv->media_connected = false; memset(&priv->nick_name, 0, sizeof(priv->nick_name)); @@ -807,32 +824,6 @@ mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index) return; } -/* - * Sends IOCTL request to shutdown firmware. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_shutdown_fw(struct mwifiex_private *priv, u8 wait_option) -{ - struct mwifiex_wait_queue *wait = NULL; - int status = 0; - - /* Allocate an IOCTL request buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; - - status = mwifiex_misc_ioctl_init_shutdown(priv->adapter, wait, - MWIFIEX_FUNC_SHUTDOWN); - - status = mwifiex_request_ioctl(priv, wait, status, wait_option); - - kfree(wait); - return status; -} -EXPORT_SYMBOL_GPL(mwifiex_shutdown_fw); - /* * This function check if command is pending. */ @@ -927,6 +918,10 @@ mwifiex_add_card(void *card, struct semaphore *sem, adapter->is_suspended = false; adapter->hs_activated = false; init_waitqueue_head(&adapter->hs_activate_wait_q); + adapter->cmd_wait_q_required = false; + init_waitqueue_head(&adapter->cmd_wait_q.wait); + adapter->cmd_wait_q.condition = false; + adapter->cmd_wait_q.status = 0; /* Create workqueue */ adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE"); @@ -1038,12 +1033,12 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n"); if (atomic_read(&adapter->rx_pending) || atomic_read(&adapter->tx_pending) || - atomic_read(&adapter->ioctl_pending)) { + atomic_read(&adapter->cmd_pending)) { dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, " - "ioctl_pending=%d\n", + "cmd_pending=%d\n", atomic_read(&adapter->rx_pending), atomic_read(&adapter->tx_pending), - atomic_read(&adapter->ioctl_pending)); + atomic_read(&adapter->cmd_pending)); } /* Remove interface */ diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 43ff149de9db..7ead15e1967e 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -42,11 +42,8 @@ extern const char driver_version[]; extern struct mwifiex_adapter *g_adapter; enum { - MWIFIEX_NO_WAIT, - MWIFIEX_IOCTL_WAIT, - MWIFIEX_CMD_WAIT, - MWIFIEX_PROC_WAIT, - MWIFIEX_WSTATS_WAIT + MWIFIEX_ASYNC_CMD, + MWIFIEX_SYNC_CMD }; #define DRV_MODE_STA 0x1 @@ -468,10 +465,6 @@ struct mwifiex_private { u32 curr_bcn_size; /* spin lock for beacon buffer */ spinlock_t curr_bcn_buf_lock; - u16 ioctl_wait_q_woken; - wait_queue_head_t ioctl_wait_q; - u16 cmd_wait_q_woken; - wait_queue_head_t cmd_wait_q; struct wireless_dev *wdev; struct mwifiex_chan_freq_power cfp; char version_str[128]; @@ -480,8 +473,6 @@ struct mwifiex_private { #endif u8 nick_name[16]; struct iw_statistics w_stats; - u16 w_stats_wait_q_woken; - wait_queue_head_t w_stats_wait_q; u16 current_key_index; struct semaphore async_sem; u8 scan_pending_on_block; @@ -552,7 +543,7 @@ struct cmd_ctrl_node { struct sk_buff *cmd_skb; struct sk_buff *resp_skb; void *data_buf; - void *wq_buf; + u32 wait_q_enabled; struct sk_buff *skb; }; @@ -590,7 +581,7 @@ struct mwifiex_adapter { struct mwifiex_if_ops if_ops; atomic_t rx_pending; atomic_t tx_pending; - atomic_t ioctl_pending; + atomic_t cmd_pending; struct workqueue_struct *workqueue; struct work_struct main_work; struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM]; @@ -684,6 +675,8 @@ struct mwifiex_adapter { struct mwifiex_dbg dbg; u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE]; u32 arp_filter_size; + u16 cmd_wait_q_required; + struct mwifiex_wait_queue cmd_wait_q; }; int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); @@ -707,29 +700,23 @@ int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb); int mwifiex_process_event(struct mwifiex_adapter *adapter); -int mwifiex_ioctl_complete(struct mwifiex_adapter *adapter, - struct mwifiex_wait_queue *ioctl_wq, - int status); +int mwifiex_complete_cmd(struct mwifiex_adapter *adapter); -int mwifiex_prepare_cmd(struct mwifiex_private *priv, - uint16_t cmd_no, - u16 cmd_action, - u32 cmd_oid, - void *wait_queue, void *data_buf); +int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, + u16 cmd_action, u32 cmd_oid, void *data_buf); + +int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, + u16 cmd_action, u32 cmd_oid, void *data_buf); void mwifiex_cmd_timeout_func(unsigned long function_context); -int mwifiex_misc_ioctl_init_shutdown(struct mwifiex_adapter *adapter, - struct mwifiex_wait_queue *wait_queue, - u32 func_init_shutdown); int mwifiex_get_debug_info(struct mwifiex_private *, struct mwifiex_debug_info *); int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter); int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter); void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter); -void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter, - struct mwifiex_wait_queue *ioctl_wq); +void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter); void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, struct cmd_ctrl_node *cmd_node); @@ -772,24 +759,21 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no, u16 cmd_action, u32 cmd_oid, void *data_buf, void *cmd_buf); int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, - void *cmd_buf, void *ioctl); + void *cmd_buf); int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *, struct sk_buff *skb); int mwifiex_process_sta_event(struct mwifiex_private *); void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta); -int mwifiex_scan_networks(struct mwifiex_private *priv, void *wait_queue, - u16 action, - const struct mwifiex_user_scan_cfg - *user_scan_in, struct mwifiex_scan_resp *); +int mwifiex_scan_networks(struct mwifiex_private *priv, + const struct mwifiex_user_scan_cfg *user_scan_in); int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, void *data_buf); void mwifiex_queue_scan_cmd(struct mwifiex_private *priv, struct cmd_ctrl_node *cmd_node); int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *wait_queue); + struct host_cmd_ds_command *resp); s32 mwifiex_find_ssid_in_list(struct mwifiex_private *priv, struct mwifiex_802_11_ssid *ssid, u8 *bssid, u32 mode); @@ -799,23 +783,20 @@ int mwifiex_find_best_network(struct mwifiex_private *priv, struct mwifiex_ssid_bssid *req_ssid_bssid); s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1, struct mwifiex_802_11_ssid *ssid2); -int mwifiex_associate(struct mwifiex_private *priv, void *wait_queue, +int mwifiex_associate(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc); int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, void *data_buf); int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *wait_queue); + struct host_cmd_ds_command *resp); void mwifiex_reset_connect_state(struct mwifiex_private *priv); void mwifiex_2040_coex_event(struct mwifiex_private *priv); u8 mwifiex_band_to_radio_type(u8 band); -int mwifiex_deauthenticate(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait_queue, - u8 *mac); -int mwifiex_adhoc_start(struct mwifiex_private *priv, void *wait_queue, +int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac); +int mwifiex_adhoc_start(struct mwifiex_private *priv, struct mwifiex_802_11_ssid *adhoc_ssid); -int mwifiex_adhoc_join(struct mwifiex_private *priv, void *wait_queue, +int mwifiex_adhoc_join(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc); int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, @@ -824,8 +805,7 @@ int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, void *data_buf); int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *wait_queue); + struct host_cmd_ds_command *resp); int mwifiex_cmd_802_11_bg_scan_query(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, void *data_buf); @@ -943,52 +923,34 @@ mwifiex_netdev_get_priv(struct net_device *dev) return (struct mwifiex_private *) (*(unsigned long *) netdev_priv(dev)); } -struct mwifiex_wait_queue *mwifiex_alloc_fill_wait_queue( - struct mwifiex_private *, - u8 wait_option); struct mwifiex_private *mwifiex_bss_index_to_priv(struct mwifiex_adapter *adapter, u8 bss_index); -int mwifiex_shutdown_fw(struct mwifiex_private *, u8); - +int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, + u32 func_init_shutdown); int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *); int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *); void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version, int maxlen); -int mwifiex_request_set_mac_address(struct mwifiex_private *priv); -void mwifiex_request_set_multicast_list(struct mwifiex_private *priv, - struct net_device *dev); -int mwifiex_request_ioctl(struct mwifiex_private *priv, - struct mwifiex_wait_queue *req, - int, u8 wait_option); -int mwifiex_disconnect(struct mwifiex_private *, u8, u8 *); +int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, + struct mwifiex_multicast_list *mcast_list); +int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, + struct net_device *dev); +int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter); int mwifiex_bss_start(struct mwifiex_private *priv, - u8 wait_option, struct mwifiex_ssid_bssid *ssid_bssid); int mwifiex_set_hs_params(struct mwifiex_private *priv, - u16 action, u8 wait_option, + u16 action, int cmd_type, struct mwifiex_ds_hs_cfg *hscfg); -int mwifiex_cancel_hs(struct mwifiex_private *priv, u8 wait_option); +int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); int mwifiex_enable_hs(struct mwifiex_adapter *adapter); -void mwifiex_process_ioctl_resp(struct mwifiex_private *priv, - struct mwifiex_wait_queue *req); -u32 mwifiex_get_mode(struct mwifiex_private *priv, u8 wait_option); int mwifiex_get_signal_info(struct mwifiex_private *priv, - u8 wait_option, struct mwifiex_ds_get_signal *signal); int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, struct mwifiex_rate_cfg *rate); -int mwifiex_get_channel_list(struct mwifiex_private *priv, - u8 wait_option, - struct mwifiex_chan_list *chanlist); -int mwifiex_get_scan_table(struct mwifiex_private *priv, - u8 wait_option, - struct mwifiex_scan_resp *scanresp); -int mwifiex_enable_wep_key(struct mwifiex_private *priv, u8 wait_option); -int mwifiex_find_best_bss(struct mwifiex_private *priv, u8 wait_option, +int mwifiex_find_best_bss(struct mwifiex_private *priv, struct mwifiex_ssid_bssid *ssid_bssid); int mwifiex_request_scan(struct mwifiex_private *priv, - u8 wait_option, struct mwifiex_802_11_ssid *req_ssid); int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, struct mwifiex_user_scan_cfg *scan_req); @@ -1024,27 +986,22 @@ int mwifiex_set_tx_rate_cfg(struct mwifiex_private *priv, int tx_rate_index); int mwifiex_get_tx_rate_cfg(struct mwifiex_private *priv, int *tx_rate_index); -int mwifiex_drv_set_power(struct mwifiex_private *priv, bool power_on); +int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode); int mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, int max_len); -int mwifiex_set_tx_power(struct mwifiex_private *priv, int type, int dbm); +int mwifiex_set_tx_power(struct mwifiex_private *priv, + struct mwifiex_power_cfg *power_cfg); int mwifiex_main_process(struct mwifiex_adapter *); -int mwifiex_bss_ioctl_channel(struct mwifiex_private *, - u16 action, - struct mwifiex_chan_freq_power *cfp); +int mwifiex_bss_set_channel(struct mwifiex_private *, + struct mwifiex_chan_freq_power *cfp); int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *, - struct mwifiex_wait_queue *, struct mwifiex_ssid_bssid *); -int mwifiex_radio_ioctl_band_cfg(struct mwifiex_private *, - u16 action, - struct mwifiex_ds_band_cfg *); -int mwifiex_snmp_mib_ioctl(struct mwifiex_private *, - struct mwifiex_wait_queue *, - u32 cmd_oid, u16 action, u32 *value); +int mwifiex_set_radio_band_cfg(struct mwifiex_private *, + struct mwifiex_ds_band_cfg *); int mwifiex_get_bss_info(struct mwifiex_private *, struct mwifiex_bss_info *); diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 6bb52d0e6cfa..12fe021536d1 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -178,9 +178,8 @@ mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1, * with requisite parameters and calls the IOCTL handler. */ int mwifiex_find_best_bss(struct mwifiex_private *priv, - u8 wait_option, struct mwifiex_ssid_bssid *ssid_bssid) + struct mwifiex_ssid_bssid *ssid_bssid) { - struct mwifiex_wait_queue *wait = NULL; struct mwifiex_ssid_bssid tmp_ssid_bssid; int ret = 0; u8 *mac = NULL; @@ -188,14 +187,9 @@ int mwifiex_find_best_bss(struct mwifiex_private *priv, if (!ssid_bssid) return -1; - /* Allocate wait request buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; - memcpy(&tmp_ssid_bssid, ssid_bssid, sizeof(struct mwifiex_ssid_bssid)); - ret = mwifiex_bss_ioctl_find_bss(priv, wait, &tmp_ssid_bssid); + ret = mwifiex_bss_ioctl_find_bss(priv, &tmp_ssid_bssid); if (!ret) { memcpy(ssid_bssid, &tmp_ssid_bssid, @@ -205,7 +199,6 @@ int mwifiex_find_best_bss(struct mwifiex_private *priv, " %pM\n", ssid_bssid->ssid.ssid, mac); } - kfree(wait); return ret; } @@ -221,22 +214,14 @@ int mwifiex_find_best_bss(struct mwifiex_private *priv, int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, struct mwifiex_user_scan_cfg *scan_req) { - struct mwifiex_wait_queue *wait = NULL; int status = 0; - u8 wait_option = MWIFIEX_IOCTL_WAIT; - - /* Allocate an IOCTL request buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; - status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_SET, - scan_req, NULL); + priv->adapter->cmd_wait_q.condition = false; - status = mwifiex_request_ioctl(priv, wait, status, wait_option); + status = mwifiex_scan_networks(priv, scan_req); + if (!status) + status = mwifiex_wait_queue_complete(priv->adapter); - if (wait && (status != -EINPROGRESS)) - kfree(wait); return status; } @@ -674,7 +659,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, * along with the other TLVs, to the firmware. */ static int -mwifiex_scan_channel_list(struct mwifiex_private *priv, void *wait_buf, +mwifiex_scan_channel_list(struct mwifiex_private *priv, u32 max_chan_per_scan, u8 filtered_scan, struct mwifiex_scan_cmd_config *scan_cfg_out, struct mwifiex_ie_types_chan_list_param_set @@ -808,9 +793,9 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, void *wait_buf, /* Send the scan command to the firmware with the specified cfg */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_SCAN, - HostCmd_ACT_GEN_SET, - 0, wait_buf, scan_cfg_out); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SCAN, + HostCmd_ACT_GEN_SET, 0, + scan_cfg_out); if (ret) break; } @@ -2271,9 +2256,7 @@ mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv, * update the internal driver scan table. */ int mwifiex_scan_networks(struct mwifiex_private *priv, - void *wait_buf, u16 action, - const struct mwifiex_user_scan_cfg *user_scan_in, - struct mwifiex_scan_resp *scan_resp) + const struct mwifiex_user_scan_cfg *user_scan_in) { int ret = 0; struct mwifiex_adapter *adapter = priv->adapter; @@ -2288,18 +2271,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, u8 max_chan_per_scan; unsigned long flags; - if (action == HostCmd_ACT_GEN_GET) { - if (scan_resp) { - scan_resp->scan_table = (u8 *) adapter->scan_table; - scan_resp->num_in_scan_table = - adapter->num_in_scan_table; - } else { - ret = -1; - } - return ret; - } - - if (adapter->scan_processing && action == HostCmd_ACT_GEN_SET) { + if (adapter->scan_processing) { dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); return ret; } @@ -2308,7 +2280,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, adapter->scan_processing = true; spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - if (priv->scan_block && action == HostCmd_ACT_GEN_SET) { + if (priv->scan_block) { dev_dbg(adapter->dev, "cmd: Scan is blocked during association...\n"); return ret; @@ -2348,9 +2320,9 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, adapter->bcn_buf_end = adapter->bcn_buf; } - ret = mwifiex_scan_channel_list(priv, wait_buf, max_chan_per_scan, - filtered_scan, &scan_cfg_out->config, - chan_list_out, scan_chan_list); + ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan, + &scan_cfg_out->config, chan_list_out, + scan_chan_list); /* Get scan command from scan_pending_q and put to cmd_pending_q */ if (!ret) { @@ -2367,7 +2339,6 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); } - ret = -EINPROGRESS; } else { spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); adapter->scan_processing = true; @@ -2437,11 +2408,10 @@ int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv, * .-------------------------------------------------------------. */ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, void *wq_buf) + struct host_cmd_ds_command *resp) { int ret = 0; struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_wait_queue *wait_queue = NULL; struct cmd_ctrl_node *cmd_node = NULL; struct host_cmd_ds_802_11_scan_rsp *scan_rsp = NULL; struct mwifiex_bssdescriptor *bss_new_entry = NULL; @@ -2653,13 +2623,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, mwifiex_process_scan_results(priv); /* Need to indicate IOCTL complete */ - wait_queue = (struct mwifiex_wait_queue *) wq_buf; - if (wait_queue) { - wait_queue->status = MWIFIEX_ERROR_NO_ERROR; - - /* Indicate ioctl complete */ - mwifiex_ioctl_complete(adapter, - (struct mwifiex_wait_queue *) wait_queue, 0); + if (adapter->curr_cmd->wait_q_enabled) { + adapter->cmd_wait_q.status = 0; + mwifiex_complete_cmd(adapter); } if (priv->report_scan_result) priv->report_scan_result = false; @@ -2853,6 +2819,7 @@ mwifiex_queue_scan_cmd(struct mwifiex_private *priv, struct mwifiex_adapter *adapter = priv->adapter; unsigned long flags; + cmd_node->wait_q_enabled = true; spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); list_add_tail(&cmd_node->list, &adapter->scan_pending_q); spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); @@ -2899,9 +2866,7 @@ int mwifiex_find_best_network(struct mwifiex_private *priv, * firmware, filtered on a specific SSID. */ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, - void *wait_buf, u16 action, - struct mwifiex_802_11_ssid *req_ssid, - struct mwifiex_scan_resp *scan_resp) + struct mwifiex_802_11_ssid *req_ssid) { struct mwifiex_adapter *adapter = priv->adapter; int ret = 0; @@ -2910,24 +2875,12 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, if (!req_ssid) return -1; - if (action == HostCmd_ACT_GEN_GET) { - if (scan_resp) { - scan_resp->scan_table = - (u8 *) &priv->curr_bss_params.bss_descriptor; - scan_resp->num_in_scan_table = - adapter->num_in_scan_table; - } else { - ret = -1; - } - return ret; - } - - if (adapter->scan_processing && action == HostCmd_ACT_GEN_SET) { + if (adapter->scan_processing) { dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); return ret; } - if (priv->scan_block && action == HostCmd_ACT_GEN_SET) { + if (priv->scan_block) { dev_dbg(adapter->dev, "cmd: Scan is blocked during association...\n"); return ret; @@ -2945,7 +2898,7 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, req_ssid->ssid_len); scan_cfg->keep_previous_scan = true; - ret = mwifiex_scan_networks(priv, wait_buf, action, scan_cfg, NULL); + ret = mwifiex_scan_networks(priv, scan_cfg); kfree(scan_cfg); return ret; @@ -2960,12 +2913,10 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, * Scan command can be issued for both normal scan and specific SSID * scan, depending upon whether an SSID is provided or not. */ -int mwifiex_request_scan(struct mwifiex_private *priv, u8 wait_option, +int mwifiex_request_scan(struct mwifiex_private *priv, struct mwifiex_802_11_ssid *req_ssid) { int ret = 0; - struct mwifiex_wait_queue *wait = NULL; - int status = 0; if (down_interruptible(&priv->async_sem)) { dev_err(priv->adapter->dev, "%s: acquire semaphore\n", @@ -2974,32 +2925,23 @@ int mwifiex_request_scan(struct mwifiex_private *priv, u8 wait_option, } priv->scan_pending_on_block = true; - /* Allocate wait request buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) { - ret = -1; - goto done; - } + priv->adapter->cmd_wait_q.condition = false; if (req_ssid && req_ssid->ssid_len != 0) /* Specific SSID scan */ - status = mwifiex_scan_specific_ssid(priv, wait, - HostCmd_ACT_GEN_SET, - req_ssid, NULL); + ret = mwifiex_scan_specific_ssid(priv, req_ssid); else /* Normal scan */ - status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_SET, - NULL, NULL); - status = mwifiex_request_ioctl(priv, wait, status, wait_option); - if (status == -1) - ret = -1; -done: - if ((wait) && (status != -EINPROGRESS)) - kfree(wait); + ret = mwifiex_scan_networks(priv, NULL); + + if (!ret) + ret = mwifiex_wait_queue_complete(priv->adapter); + if (ret == -1) { priv->scan_pending_on_block = false; up(&priv->async_sem); } + return ret; } diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index f21e5cd19839..f207756cbb79 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -208,7 +208,7 @@ static int mwifiex_sdio_resume(struct device *dev) /* Disable Host Sleep */ mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), - MWIFIEX_NO_WAIT); + MWIFIEX_ASYNC_CMD); return 0; } @@ -1745,13 +1745,12 @@ mwifiex_sdio_cleanup_module(void) for (i = 0; i < adapter->priv_num; i++) if ((GET_BSS_ROLE(adapter->priv[i]) == MWIFIEX_BSS_ROLE_STA) && adapter->priv[i]->media_connected) - mwifiex_disconnect(adapter->priv[i], MWIFIEX_CMD_WAIT, - NULL); + mwifiex_deauthenticate(adapter->priv[i], NULL); if (!adapter->surprise_removed) - mwifiex_shutdown_fw(mwifiex_get_priv - (adapter, MWIFIEX_BSS_ROLE_ANY), - MWIFIEX_CMD_WAIT); + mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, + MWIFIEX_BSS_ROLE_ANY), + MWIFIEX_FUNC_SHUTDOWN); exit: up(&add_remove_card_sem); diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 19de6524d428..dec496369b95 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -1135,65 +1135,66 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) if (first_sta) { - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_FUNC_INIT, - HostCmd_ACT_GEN_SET, 0, NULL, NULL); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_FUNC_INIT, + HostCmd_ACT_GEN_SET, 0, NULL); if (ret) return -1; /* Read MAC address from HW */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_GET_HW_SPEC, - HostCmd_ACT_GEN_GET, 0, NULL, NULL); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_GET_HW_SPEC, + HostCmd_ACT_GEN_GET, 0, NULL); if (ret) return -1; /* Reconfigure tx buf size */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, - HostCmd_ACT_GEN_SET, 0, NULL, - &priv->adapter->tx_buf_size); + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_RECONFIGURE_TX_BUFF, + HostCmd_ACT_GEN_SET, 0, + &priv->adapter->tx_buf_size); if (ret) return -1; /* Enable IEEE PS by default */ priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, - EN_AUTO_PS, BITMAP_STA_PS, NULL, - NULL); + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_802_11_PS_MODE_ENH, + EN_AUTO_PS, BITMAP_STA_PS, NULL); if (ret) return -1; } /* get tx rate */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TX_RATE_CFG, - HostCmd_ACT_GEN_GET, 0, NULL, NULL); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_TX_RATE_CFG, + HostCmd_ACT_GEN_GET, 0, NULL); if (ret) return -1; priv->data_rate = 0; /* get tx power */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TXPWR_CFG, - HostCmd_ACT_GEN_GET, 0, NULL, NULL); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_TXPWR_CFG, + HostCmd_ACT_GEN_GET, 0, NULL); if (ret) return -1; /* set ibss coalescing_status */ - ret = mwifiex_prepare_cmd(priv, - HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, - HostCmd_ACT_GEN_SET, 0, NULL, &enable); + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, + HostCmd_ACT_GEN_SET, 0, &enable); if (ret) return -1; memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); amsdu_aggr_ctrl.enable = true; /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, - HostCmd_ACT_GEN_SET, 0, NULL, - (void *) &amsdu_aggr_ctrl); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, + HostCmd_ACT_GEN_SET, 0, + (void *) &amsdu_aggr_ctrl); if (ret) return -1; /* MAC Control must be the last command in init_fw */ /* set MAC Control */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, NULL, - &priv->curr_pkt_filter); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, + HostCmd_ACT_GEN_SET, 0, + &priv->curr_pkt_filter); if (ret) return -1; @@ -1201,19 +1202,18 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) /* Enable auto deep sleep */ auto_ds.auto_ds = DEEP_SLEEP_ON; auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; - ret = mwifiex_prepare_cmd(priv, - HostCmd_CMD_802_11_PS_MODE_ENH, - EN_AUTO_PS, BITMAP_AUTO_DS, NULL, - &auto_ds); + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_802_11_PS_MODE_ENH, + EN_AUTO_PS, BITMAP_AUTO_DS, + &auto_ds); if (ret) return -1; } /* Send cmd to FW to enable/disable 11D function */ state_11d = ENABLE_11D; - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, DOT11D_I, - NULL, &state_11d); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_SET, DOT11D_I, &state_11d); if (ret) dev_err(priv->adapter->dev, "11D: failed to enable 11D\n"); diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 648df690f5d1..8743c116bee5 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -41,8 +41,7 @@ */ static void mwifiex_process_cmdresp_error(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - struct mwifiex_wait_queue *wq_buf) + struct host_cmd_ds_command *resp) { struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; struct mwifiex_adapter *adapter = priv->adapter; @@ -51,8 +50,9 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, dev_err(adapter->dev, "CMD_RESP: cmd %#x error, result=%#x\n", resp->command, resp->result); - if (wq_buf) - wq_buf->status = MWIFIEX_ERROR_FW_CMDRESP; + + if (adapter->curr_cmd->wait_q_enabled) + adapter->cmd_wait_q.status = -1; switch (le16_to_cpu(resp->command)) { case HostCmd_CMD_802_11_PS_MODE_ENH: @@ -328,9 +328,9 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, if (priv->is_data_rate_auto) priv->data_rate = 0; else - ret = mwifiex_prepare_cmd(priv, + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, - HostCmd_ACT_GEN_GET, 0, NULL, NULL); + HostCmd_ACT_GEN_GET, 0, NULL); if (data_buf) { ds_rate = (struct mwifiex_rate_cfg *) data_buf; @@ -833,19 +833,17 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv, * response handlers based on the command ID. */ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, - u16 cmdresp_no, void *cmd_buf, void *wq_buf) + u16 cmdresp_no, void *cmd_buf) { int ret = 0; struct mwifiex_adapter *adapter = priv->adapter; struct host_cmd_ds_command *resp = (struct host_cmd_ds_command *) cmd_buf; - struct mwifiex_wait_queue *wait_queue = - (struct mwifiex_wait_queue *) wq_buf; void *data_buf = adapter->curr_cmd->data_buf; /* If the command is not successful, cleanup and return failure */ if (resp->result != HostCmd_RESULT_OK) { - mwifiex_process_cmdresp_error(priv, resp, wait_queue); + mwifiex_process_cmdresp_error(priv, resp); return -1; } /* Command successful, handle response */ @@ -865,12 +863,11 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, ret = mwifiex_ret_tx_rate_cfg(priv, resp, data_buf); break; case HostCmd_CMD_802_11_SCAN: - ret = mwifiex_ret_802_11_scan(priv, resp, wait_queue); - wait_queue = NULL; - adapter->curr_cmd->wq_buf = NULL; + ret = mwifiex_ret_802_11_scan(priv, resp); + adapter->curr_cmd->wait_q_enabled = false; break; case HostCmd_CMD_802_11_BG_SCAN_QUERY: - ret = mwifiex_ret_802_11_scan(priv, resp, wait_queue); + ret = mwifiex_ret_802_11_scan(priv, resp); dev_dbg(adapter->dev, "info: CMD_RESP: BG_SCAN result is ready!\n"); break; @@ -884,14 +881,14 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, ret = mwifiex_ret_802_11_hs_cfg(priv, resp); break; case HostCmd_CMD_802_11_ASSOCIATE: - ret = mwifiex_ret_802_11_associate(priv, resp, wait_queue); + ret = mwifiex_ret_802_11_associate(priv, resp); break; case HostCmd_CMD_802_11_DEAUTHENTICATE: ret = mwifiex_ret_802_11_deauthenticate(priv, resp); break; case HostCmd_CMD_802_11_AD_HOC_START: case HostCmd_CMD_802_11_AD_HOC_JOIN: - ret = mwifiex_ret_802_11_ad_hoc(priv, resp, wait_queue); + ret = mwifiex_ret_802_11_ad_hoc(priv, resp); break; case HostCmd_CMD_802_11_AD_HOC_STOP: ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp); diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 936d7c175e75..fc265cab0907 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -271,8 +271,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) case EVENT_HS_ACT_REQ: dev_dbg(adapter->dev, "event: HS_ACT_REQ\n"); - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH, - 0, 0, NULL, NULL); + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_802_11_HS_CFG_ENH, + 0, 0, NULL); break; case EVENT_MIC_ERR_UNICAST: @@ -303,9 +304,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP); adapter->num_in_scan_table = 0; adapter->bcn_buf_end = adapter->bcn_buf; - ret = mwifiex_prepare_cmd(priv, - HostCmd_CMD_802_11_BG_SCAN_QUERY, - HostCmd_ACT_GEN_GET, 0, NULL, NULL); + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_802_11_BG_SCAN_QUERY, + HostCmd_ACT_GEN_GET, 0, NULL); break; case EVENT_PORT_RELEASE: @@ -314,8 +315,8 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) case EVENT_WMM_STATUS_CHANGE: dev_dbg(adapter->dev, "event: WMM status changed\n"); - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_WMM_GET_STATUS, - 0, 0, NULL, NULL); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_WMM_GET_STATUS, + 0, 0, NULL); break; case EVENT_RSSI_LOW: @@ -353,15 +354,15 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) break; case EVENT_IBSS_COALESCED: dev_dbg(adapter->dev, "event: IBSS_COALESCED\n"); - ret = mwifiex_prepare_cmd(priv, + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, - HostCmd_ACT_GEN_GET, 0, NULL, NULL); + HostCmd_ACT_GEN_GET, 0, NULL); break; case EVENT_ADDBA: dev_dbg(adapter->dev, "event: ADDBA Request\n"); - mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP, - HostCmd_ACT_GEN_SET, 0, NULL, - adapter->event_body); + mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_RSP, + HostCmd_ACT_GEN_SET, 0, + adapter->event_body); break; case EVENT_DELBA: dev_dbg(adapter->dev, "event: DELBA Request\n"); diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 2fcdbc224e08..5f2ce9459d26 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -33,9 +33,8 @@ * size, and the calling function must ensure enough memory is * available. */ -static int -mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, - struct net_device *dev) +int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, + struct net_device *dev) { int i = 0; struct netdev_hw_addr *ha; @@ -46,217 +45,52 @@ mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, return i; } -/* - * Allocate and fills a wait queue with proper parameters. - * - * This function needs to be called before an IOCTL request can be made. - * It can handle the following wait options: - * MWIFIEX_NO_WAIT - Waiting is disabled - * MWIFIEX_IOCTL_WAIT - Waiting is done on IOCTL wait queue - * MWIFIEX_CMD_WAIT - Waiting is done on command wait queue - * MWIFIEX_WSTATS_WAIT - Waiting is done on stats wait queue - */ -struct mwifiex_wait_queue * -mwifiex_alloc_fill_wait_queue(struct mwifiex_private *priv, - u8 wait_option) -{ - struct mwifiex_wait_queue *wait = NULL; - - wait = (struct mwifiex_wait_queue *) - kzalloc(sizeof(struct mwifiex_wait_queue), GFP_ATOMIC); - if (!wait) { - dev_err(priv->adapter->dev, "%s: fail to alloc buffer\n", - __func__); - return wait; - } - - wait->bss_index = priv->bss_index; - - switch (wait_option) { - case MWIFIEX_NO_WAIT: - wait->enabled = 0; - break; - case MWIFIEX_IOCTL_WAIT: - priv->ioctl_wait_q_woken = false; - wait->start_time = jiffies; - wait->wait = &priv->ioctl_wait_q; - wait->condition = &priv->ioctl_wait_q_woken; - wait->enabled = 1; - break; - case MWIFIEX_CMD_WAIT: - priv->cmd_wait_q_woken = false; - wait->start_time = jiffies; - wait->wait = &priv->cmd_wait_q; - wait->condition = &priv->cmd_wait_q_woken; - wait->enabled = 1; - break; - case MWIFIEX_WSTATS_WAIT: - priv->w_stats_wait_q_woken = false; - wait->start_time = jiffies; - wait->wait = &priv->w_stats_wait_q; - wait->condition = &priv->w_stats_wait_q_woken; - wait->enabled = 1; - break; - } - - return wait; -} - /* * Wait queue completion handler. * - * This function waits on a particular wait queue. - * For NO_WAIT option, it returns immediately. It also cancels the - * pending IOCTL request after waking up, in case of errors. + * This function waits on a cmd wait queue. It also cancels the pending + * request after waking up, in case of errors. */ -static void -mwifiex_wait_ioctl_complete(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - u8 wait_option) +int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) { bool cancel_flag = false; + int status = adapter->cmd_wait_q.status; - switch (wait_option) { - case MWIFIEX_NO_WAIT: - break; - case MWIFIEX_IOCTL_WAIT: - wait_event_interruptible(priv->ioctl_wait_q, - priv->ioctl_wait_q_woken); - if (!priv->ioctl_wait_q_woken) - cancel_flag = true; - break; - case MWIFIEX_CMD_WAIT: - wait_event_interruptible(priv->cmd_wait_q, - priv->cmd_wait_q_woken); - if (!priv->cmd_wait_q_woken) - cancel_flag = true; - break; - case MWIFIEX_WSTATS_WAIT: - wait_event_interruptible(priv->w_stats_wait_q, - priv->w_stats_wait_q_woken); - if (!priv->w_stats_wait_q_woken) - cancel_flag = true; - break; - } - if (cancel_flag) { - mwifiex_cancel_pending_ioctl(priv->adapter, wait); - dev_dbg(priv->adapter->dev, "cmd: IOCTL cancel: wait=%p, wait_option=%d\n", - wait, wait_option); - } + dev_dbg(adapter->dev, "cmd pending\n"); + atomic_inc(&adapter->cmd_pending); - return; -} + /* Status pending, wake up main process */ + queue_work(adapter->workqueue, &adapter->main_work); -/* - * The function waits for the request to complete and issues the - * completion handler, if required. - */ -int mwifiex_request_ioctl(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - int status, u8 wait_option) -{ - switch (status) { - case -EINPROGRESS: - dev_dbg(priv->adapter->dev, "cmd: IOCTL pending: wait=%p, wait_option=%d\n", - wait, wait_option); - atomic_inc(&priv->adapter->ioctl_pending); - /* Status pending, wake up main process */ - queue_work(priv->adapter->workqueue, &priv->adapter->main_work); - - /* Wait for completion */ - if (wait_option) { - mwifiex_wait_ioctl_complete(priv, wait, wait_option); - status = wait->status; - } - break; - case 0: - case -1: - case -EBUSY: - default: - break; - } - return status; -} -EXPORT_SYMBOL_GPL(mwifiex_request_ioctl); + /* Wait for completion */ + wait_event_interruptible(adapter->cmd_wait_q.wait, + adapter->cmd_wait_q.condition); + if (!adapter->cmd_wait_q.condition) + cancel_flag = true; -/* - * IOCTL request handler to set/get MAC address. - * - * This function prepares the correct firmware command and - * issues it to get the extended version information. - */ -static int mwifiex_bss_ioctl_mac_address(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - u8 action, u8 *mac) -{ - int ret = 0; - - if ((action == HostCmd_ACT_GEN_GET) && mac) { - memcpy(mac, priv->curr_addr, ETH_ALEN); - return 0; + if (cancel_flag) { + mwifiex_cancel_pending_ioctl(adapter); + dev_dbg(adapter->dev, "cmd cancel\n"); } + adapter->cmd_wait_q.status = 0; - /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_MAC_ADDRESS, - action, 0, wait, mac); - if (!ret) - ret = -EINPROGRESS; - - return ret; -} - -/* - * Sends IOCTL request to set MAC address. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_request_set_mac_address(struct mwifiex_private *priv) -{ - struct mwifiex_wait_queue *wait = NULL; - int status = 0; - u8 wait_option = MWIFIEX_CMD_WAIT; - - /* Allocate wait buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; - - status = mwifiex_bss_ioctl_mac_address(priv, wait, HostCmd_ACT_GEN_SET, - NULL); - - status = mwifiex_request_ioctl(priv, wait, status, wait_option); - if (!status) - memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN); - else - dev_err(priv->adapter->dev, "set mac address failed: status=%d" - " error_code=%#x\n", status, wait->status); - - kfree(wait); return status; } /* - * IOCTL request handler to set multicast list. - * * This function prepares the correct firmware command and * issues it to set the multicast list. * * This function can be used to enable promiscuous mode, or enable all * multicast packets, or to enable selective multicast. */ -static int -mwifiex_bss_ioctl_multicast_list(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - u16 action, - struct mwifiex_multicast_list *mcast_list) +int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, + struct mwifiex_multicast_list *mcast_list) { int ret = 0; u16 old_pkt_filter; old_pkt_filter = priv->curr_pkt_filter; - if (action == HostCmd_ACT_GEN_GET) - return -1; if (mcast_list->mode == MWIFIEX_PROMISC_MODE) { dev_dbg(priv->adapter->dev, "info: Enable Promiscuous mode\n"); @@ -281,16 +115,15 @@ mwifiex_bss_ioctl_multicast_list(struct mwifiex_private *priv, /* Set multicast addresses to firmware */ if (old_pkt_filter == priv->curr_pkt_filter) { /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_MULTICAST_ADR, - action, 0, wait, mcast_list); - if (!ret) - ret = -EINPROGRESS; + HostCmd_ACT_GEN_SET, 0, + mcast_list); } else { /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_MULTICAST_ADR, - action, 0, NULL, + HostCmd_ACT_GEN_SET, 0, mcast_list); } } @@ -300,101 +133,21 @@ mwifiex_bss_ioctl_multicast_list(struct mwifiex_private *priv, "info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n", old_pkt_filter, priv->curr_pkt_filter); if (old_pkt_filter != priv->curr_pkt_filter) { - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, action, - 0, wait, &priv->curr_pkt_filter); - if (!ret) - ret = -EINPROGRESS; + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, + HostCmd_ACT_GEN_SET, + 0, &priv->curr_pkt_filter); } return ret; } /* - * Sends IOCTL request to set multicast list. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -void -mwifiex_request_set_multicast_list(struct mwifiex_private *priv, - struct net_device *dev) -{ - struct mwifiex_wait_queue *wait = NULL; - struct mwifiex_multicast_list mcast_list; - u8 wait_option = MWIFIEX_NO_WAIT; - int status = 0; - - /* Allocate wait buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return; - - if (dev->flags & IFF_PROMISC) { - mcast_list.mode = MWIFIEX_PROMISC_MODE; - } else if (dev->flags & IFF_ALLMULTI || - netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) { - mcast_list.mode = MWIFIEX_ALL_MULTI_MODE; - } else { - mcast_list.mode = MWIFIEX_MULTICAST_MODE; - if (netdev_mc_count(dev)) - mcast_list.num_multicast_addr = - mwifiex_copy_mcast_addr(&mcast_list, dev); - } - status = mwifiex_bss_ioctl_multicast_list(priv, wait, - HostCmd_ACT_GEN_SET, - &mcast_list); - - status = mwifiex_request_ioctl(priv, wait, status, wait_option); - if (wait && status != -EINPROGRESS) - kfree(wait); - - return; -} - -/* - * IOCTL request handler to disconnect from a BSS/IBSS. - */ -static int mwifiex_bss_ioctl_stop(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, u8 *mac) -{ - return mwifiex_deauthenticate(priv, wait, mac); -} - -/* - * Sends IOCTL request to disconnect from a BSS. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_disconnect(struct mwifiex_private *priv, u8 wait_option, u8 *mac) -{ - struct mwifiex_wait_queue *wait = NULL; - int status = 0; - - /* Allocate wait buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; - - status = mwifiex_bss_ioctl_stop(priv, wait, mac); - - status = mwifiex_request_ioctl(priv, wait, status, wait_option); - - kfree(wait); - return status; -} -EXPORT_SYMBOL_GPL(mwifiex_disconnect); - -/* - * IOCTL request handler to join a BSS/IBSS. - * * In Ad-Hoc mode, the IBSS is created if not found in scan list. * In both Ad-Hoc and infra mode, an deauthentication is performed * first. */ -static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - struct mwifiex_ssid_bssid *ssid_bssid) +int mwifiex_bss_start(struct mwifiex_private *priv, + struct mwifiex_ssid_bssid *ssid_bssid) { int ret = 0; struct mwifiex_adapter *adapter = priv->adapter; @@ -406,7 +159,7 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv, if (priv->bss_mode == NL80211_IFTYPE_STATION) { /* Infra mode */ - ret = mwifiex_deauthenticate(priv, NULL, NULL); + ret = mwifiex_deauthenticate(priv, NULL); if (ret) return ret; @@ -427,7 +180,7 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv, /* Clear any past association response stored for * application retrieval */ priv->assoc_rsp_size = 0; - ret = mwifiex_associate(priv, wait, &adapter->scan_table[i]); + ret = mwifiex_associate(priv, &adapter->scan_table[i]); if (ret) return ret; } else { @@ -441,7 +194,7 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv, /* Exit Adhoc mode first */ dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n"); - ret = mwifiex_deauthenticate(priv, NULL, NULL); + ret = mwifiex_deauthenticate(priv, NULL); if (ret) return ret; @@ -460,75 +213,39 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv, if (i >= 0) { dev_dbg(adapter->dev, "info: network found in scan" " list. Joining...\n"); - ret = mwifiex_adhoc_join(priv, wait, - &adapter->scan_table[i]); + ret = mwifiex_adhoc_join(priv, &adapter->scan_table[i]); if (ret) return ret; } else { /* i >= 0 */ dev_dbg(adapter->dev, "info: Network not found in " "the list, creating adhoc with ssid = %s\n", ssid_bssid->ssid.ssid); - ret = mwifiex_adhoc_start(priv, wait, - &ssid_bssid->ssid); + ret = mwifiex_adhoc_start(priv, &ssid_bssid->ssid); if (ret) return ret; } } - if (!ret) - ret = -EINPROGRESS; - return ret; } -/* - * Sends IOCTL request to connect with a BSS. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_bss_start(struct mwifiex_private *priv, u8 wait_option, - struct mwifiex_ssid_bssid *ssid_bssid) -{ - struct mwifiex_wait_queue *wait = NULL; - struct mwifiex_ssid_bssid tmp_ssid_bssid; - int status = 0; - - /* Stop the O.S. TX queue if needed */ - if (!netif_queue_stopped(priv->netdev)) - netif_stop_queue(priv->netdev); - - /* Allocate wait buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; - - if (ssid_bssid) - memcpy(&tmp_ssid_bssid, ssid_bssid, - sizeof(struct mwifiex_ssid_bssid)); - status = mwifiex_bss_ioctl_start(priv, wait, &tmp_ssid_bssid); - - status = mwifiex_request_ioctl(priv, wait, status, wait_option); - - kfree(wait); - return status; -} - /* * IOCTL request handler to set host sleep configuration. * * This function prepares the correct firmware command and * issues it. */ -static int -mwifiex_pm_ioctl_hs_cfg(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - u16 action, struct mwifiex_ds_hs_cfg *hs_cfg) +int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, + int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg) + { struct mwifiex_adapter *adapter = priv->adapter; int status = 0; u32 prev_cond = 0; + if (!hs_cfg) + return -ENOMEM; + switch (action) { case HostCmd_ACT_GEN_SET: if (adapter->pps_uapsd_mode) { @@ -561,12 +278,16 @@ mwifiex_pm_ioctl_hs_cfg(struct mwifiex_private *priv, status = -1; break; } - status = mwifiex_prepare_cmd(priv, - HostCmd_CMD_802_11_HS_CFG_ENH, - HostCmd_ACT_GEN_SET, - 0, wait, &adapter->hs_cfg); - if (!status) - status = -EINPROGRESS; + if (cmd_type == MWIFIEX_SYNC_CMD) + status = mwifiex_send_cmd_sync(priv, + HostCmd_CMD_802_11_HS_CFG_ENH, + HostCmd_ACT_GEN_SET, 0, + &adapter->hs_cfg); + else + status = mwifiex_send_cmd_async(priv, + HostCmd_CMD_802_11_HS_CFG_ENH, + HostCmd_ACT_GEN_SET, 0, + &adapter->hs_cfg); if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) /* Restore previous condition */ adapter->hs_cfg.conditions = @@ -591,43 +312,13 @@ mwifiex_pm_ioctl_hs_cfg(struct mwifiex_private *priv, return status; } -/* - * Sends IOCTL request to set Host Sleep parameters. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, - u8 wait_option, - struct mwifiex_ds_hs_cfg *hscfg) -{ - int ret = 0; - struct mwifiex_wait_queue *wait = NULL; - - if (!hscfg) - return -ENOMEM; - - /* Allocate wait buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; - - ret = mwifiex_pm_ioctl_hs_cfg(priv, wait, action, hscfg); - - ret = mwifiex_request_ioctl(priv, wait, ret, wait_option); - - if (wait && (ret != -EINPROGRESS)) - kfree(wait); - return ret; -} - /* * Sends IOCTL request to cancel the existing Host Sleep configuration. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler. */ -int mwifiex_cancel_hs(struct mwifiex_private *priv, u8 wait_option) +int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type) { int ret = 0; struct mwifiex_ds_hs_cfg hscfg; @@ -636,7 +327,7 @@ int mwifiex_cancel_hs(struct mwifiex_private *priv, u8 wait_option) hscfg.conditions = HOST_SLEEP_CFG_CANCEL; hscfg.is_invoke_hostcmd = true; ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, - wait_option, &hscfg); + cmd_type, &hscfg); return ret; } @@ -665,8 +356,8 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) if (mwifiex_set_hs_params(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), - HostCmd_ACT_GEN_SET, - MWIFIEX_IOCTL_WAIT, &hscfg)) { + HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD, + &hscfg)) { dev_err(adapter->dev, "IOCTL request HS enable failed\n"); return false; } @@ -678,69 +369,6 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) } EXPORT_SYMBOL_GPL(mwifiex_enable_hs); -/* - * IOCTL request handler to get signal information. - * - * This function prepares the correct firmware command and - * issues it to get the signal (RSSI) information. - * - * This only works in the connected mode. - */ -static int mwifiex_get_info_signal(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - struct mwifiex_ds_get_signal *signal) -{ - int ret = 0; - - if (!wait) { - dev_err(priv->adapter->dev, "WAIT information is not present\n"); - return -1; - } - - /* Signal info can be obtained only if connected */ - if (!priv->media_connected) { - dev_dbg(priv->adapter->dev, - "info: Can not get signal in disconnected state\n"); - return -1; - } - - /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_RSSI_INFO, - HostCmd_ACT_GEN_GET, 0, wait, signal); - - if (!ret) - ret = -EINPROGRESS; - - return ret; -} - -/* - * IOCTL request handler to get statistics. - * - * This function prepares the correct firmware command and - * issues it to get the statistics (RSSI) information. - */ -static int mwifiex_get_info_stats(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - struct mwifiex_ds_get_stats *log) -{ - int ret = 0; - - if (!wait) { - dev_err(priv->adapter->dev, "MWIFIEX IOCTL information is not present\n"); - return -1; - } - - /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_GET_LOG, - HostCmd_ACT_GEN_GET, 0, wait, log); - - if (!ret) - ret = -EINPROGRESS; - - return ret; -} - /* * IOCTL request handler to get BSS information. * @@ -813,90 +441,20 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv, } /* - * IOCTL request handler to get extended version information. - * - * This function prepares the correct firmware command and - * issues it to get the extended version information. - */ -static int mwifiex_get_info_ver_ext(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - struct mwifiex_ver_ext *ver_ext) -{ - int ret = 0; - - /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_VERSION_EXT, - HostCmd_ACT_GEN_GET, 0, wait, ver_ext); - if (!ret) - ret = -EINPROGRESS; - - return ret; -} - -/* - * IOCTL request handler to set/get SNMP MIB parameters. - * - * This function prepares the correct firmware command and - * issues it. + * The function sets band configurations. * - * Currently the following parameters are supported - - * Set/get RTS Threshold - * Set/get fragmentation threshold - * Set/get retry count - */ -int mwifiex_snmp_mib_ioctl(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - u32 cmd_oid, u16 action, u32 *value) -{ - int ret = 0; - - if (!value) - return -1; - - /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, - action, cmd_oid, wait, value); - - if (!ret) - ret = -EINPROGRESS; - - return ret; -} - -/* - * IOCTL request handler to set/get band configurations. - * - * For SET operation, it performs extra checks to make sure the Ad-Hoc + * it performs extra checks to make sure the Ad-Hoc * band and channel are compatible. Otherwise it returns an error. * - * For GET operation, this function retrieves the following information - - * - Infra bands - * - Ad-hoc band - * - Ad-hoc channel - * - Secondary channel offset */ -int mwifiex_radio_ioctl_band_cfg(struct mwifiex_private *priv, - u16 action, - struct mwifiex_ds_band_cfg *radio_cfg) +int mwifiex_set_radio_band_cfg(struct mwifiex_private *priv, + struct mwifiex_ds_band_cfg *radio_cfg) { struct mwifiex_adapter *adapter = priv->adapter; u8 infra_band = 0; u8 adhoc_band = 0; u32 adhoc_channel = 0; - if (action == HostCmd_ACT_GEN_GET) { - /* Infra Bands */ - radio_cfg->config_bands = adapter->config_bands; - /* Adhoc Band */ - radio_cfg->adhoc_start_band = adapter->adhoc_start_band; - /* Adhoc channel */ - radio_cfg->adhoc_channel = priv->adhoc_channel; - /* Secondary channel offset */ - radio_cfg->sec_chan_offset = adapter->chan_offset; - return 0; - } - - /* For action = SET */ infra_band = (u8) radio_cfg->config_bands; adhoc_band = (u8) radio_cfg->adhoc_start_band; adhoc_channel = radio_cfg->adhoc_channel; @@ -950,8 +508,8 @@ int mwifiex_radio_ioctl_band_cfg(struct mwifiex_private *priv, * This function performs validity checking on channel/frequency * compatibility and returns failure if not valid. */ -int mwifiex_bss_ioctl_channel(struct mwifiex_private *priv, u16 action, - struct mwifiex_chan_freq_power *chan) +int mwifiex_bss_set_channel(struct mwifiex_private *priv, + struct mwifiex_chan_freq_power *chan) { struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_chan_freq_power *cfp = NULL; @@ -959,16 +517,6 @@ int mwifiex_bss_ioctl_channel(struct mwifiex_private *priv, u16 action, if (!chan) return -1; - if (action == HostCmd_ACT_GEN_GET) { - cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv, - priv->curr_bss_params.band, - (u16) priv->curr_bss_params.bss_descriptor. - channel); - chan->channel = cfp->channel; - chan->freq = cfp->freq; - - return 0; - } if (!chan->channel && !chan->freq) return -1; if (adapter->adhoc_start_band & BAND_AN) @@ -1024,7 +572,6 @@ int mwifiex_bss_ioctl_channel(struct mwifiex_private *priv, u16 action, * issues it to set or get the ad-hoc channel. */ static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, u16 action, u16 *channel) { int ret = 0; @@ -1039,10 +586,8 @@ static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv, } /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_RF_CHANNEL, - action, 0, wait, channel); - if (!ret) - ret = -EINPROGRESS; + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_RF_CHANNEL, + action, 0, channel); return ret; } @@ -1054,7 +599,6 @@ static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv, * these are provided, just the best BSS (best RSSI) is returned. */ int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, struct mwifiex_ssid_bssid *ssid_bssid) { struct mwifiex_adapter *adapter = priv->adapter; @@ -1114,10 +658,7 @@ int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) { int ret = 0; - int status = 0; struct mwifiex_bss_info bss_info; - struct mwifiex_wait_queue *wait = NULL; - u8 wait_option = MWIFIEX_IOCTL_WAIT; struct mwifiex_ssid_bssid ssid_bssid; u16 curr_chan = 0; @@ -1127,19 +668,10 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) if (mwifiex_get_bss_info(priv, &bss_info)) return -1; - /* Allocate wait buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; - /* Get current channel */ - status = mwifiex_bss_ioctl_ibss_channel(priv, wait, HostCmd_ACT_GEN_GET, - &curr_chan); + ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_GET, + &curr_chan); - if (mwifiex_request_ioctl(priv, wait, status, wait_option)) { - ret = -1; - goto done; - } if (curr_chan == channel) { ret = 0; goto done; @@ -1154,23 +686,13 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) /* Do disonnect */ memset(&ssid_bssid, 0, ETH_ALEN); - status = mwifiex_bss_ioctl_stop(priv, wait, ssid_bssid.bssid); + ret = mwifiex_deauthenticate(priv, ssid_bssid.bssid); - if (mwifiex_request_ioctl(priv, wait, status, wait_option)) { - ret = -1; - goto done; - } - - status = mwifiex_bss_ioctl_ibss_channel(priv, wait, HostCmd_ACT_GEN_SET, - (u16 *) &channel); - - if (mwifiex_request_ioctl(priv, wait, status, wait_option)) { - ret = -1; - goto done; - } + ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_SET, + (u16 *) &channel); /* Do specific SSID scanning */ - if (mwifiex_request_scan(priv, wait_option, &bss_info.ssid)) { + if (mwifiex_request_scan(priv, &bss_info.ssid)) { ret = -1; goto done; } @@ -1179,13 +701,8 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) memcpy(&ssid_bssid.ssid, &bss_info.ssid, sizeof(struct mwifiex_802_11_ssid)); - status = mwifiex_bss_ioctl_start(priv, wait, &ssid_bssid); - - if (mwifiex_request_ioctl(priv, wait, status, wait_option)) - ret = -1; - + ret = mwifiex_bss_start(priv, &ssid_bssid); done: - kfree(wait); return ret; } @@ -1198,7 +715,6 @@ done: * for the band. */ static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, struct mwifiex_rate_cfg *rate_cfg) { struct mwifiex_adapter *adapter = priv->adapter; @@ -1242,11 +758,9 @@ static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv, } } else { /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, - HostCmd_CMD_802_11_TX_RATE_QUERY, - HostCmd_ACT_GEN_GET, 0, wait, NULL); - if (!ret) - ret = -EINPROGRESS; + ret = mwifiex_send_cmd_sync(priv, + HostCmd_CMD_802_11_TX_RATE_QUERY, + HostCmd_ACT_GEN_GET, 0, NULL); } return ret; @@ -1261,7 +775,6 @@ static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv, * The function also performs validation checking on the supplied value. */ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, struct mwifiex_rate_cfg *rate_cfg) { u8 rates[MWIFIEX_SUPPORTED_RATES]; @@ -1316,10 +829,8 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv, } /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TX_RATE_CFG, - HostCmd_ACT_GEN_SET, 0, wait, bitmap_rates); - if (!ret) - ret = -EINPROGRESS; + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, + HostCmd_ACT_GEN_SET, 0, bitmap_rates); return ret; } @@ -1331,7 +842,6 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv, * rate index. */ static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, struct mwifiex_rate_cfg *rate_cfg) { int status = 0; @@ -1340,11 +850,9 @@ static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv, return -1; if (rate_cfg->action == HostCmd_ACT_GEN_GET) - status = mwifiex_rate_ioctl_get_rate_value( - priv, wait, rate_cfg); + status = mwifiex_rate_ioctl_get_rate_value(priv, rate_cfg); else - status = mwifiex_rate_ioctl_set_rate_value( - priv, wait, rate_cfg); + status = mwifiex_rate_ioctl_set_rate_value(priv, rate_cfg); return status; } @@ -1359,19 +867,11 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, struct mwifiex_rate_cfg *rate) { int ret = 0; - struct mwifiex_wait_queue *wait = NULL; - u8 wait_option = MWIFIEX_IOCTL_WAIT; - - /* Allocate wait buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; memset(rate, 0, sizeof(struct mwifiex_rate_cfg)); rate->action = HostCmd_ACT_GEN_GET; - ret = mwifiex_rate_ioctl_cfg(priv, wait, rate); + ret = mwifiex_rate_ioctl_cfg(priv, rate); - ret = mwifiex_request_ioctl(priv, wait, ret, wait_option); if (!ret) { if (rate && rate->is_rate_auto) rate->rate = mwifiex_index_to_data_rate(priv->adapter, @@ -1382,7 +882,6 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, ret = -1; } - kfree(wait); return ret; } @@ -1398,9 +897,8 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, * - Modulation class HTBW20 * - Modulation class HTBW40 */ -static int mwifiex_power_ioctl_set_power(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - struct mwifiex_power_cfg *power_cfg) +int mwifiex_set_tx_power(struct mwifiex_private *priv, + struct mwifiex_power_cfg *power_cfg) { int ret = 0; struct host_cmd_ds_txpwr_cfg *txp_cfg = NULL; @@ -1473,12 +971,10 @@ static int mwifiex_power_ioctl_set_power(struct mwifiex_private *priv, pg->ht_bandwidth = HT_BW_40; } /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TXPWR_CFG, - HostCmd_ACT_GEN_SET, 0, wait, buf); - if (!ret) - ret = -EINPROGRESS; - kfree(buf); + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TXPWR_CFG, + HostCmd_ACT_GEN_SET, 0, buf); + kfree(buf); return ret; } @@ -1488,33 +984,23 @@ static int mwifiex_power_ioctl_set_power(struct mwifiex_private *priv, * This function prepares the correct firmware command and * issues it. */ -static int mwifiex_pm_ioctl_ps_mode(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - u32 *ps_mode, u16 action) +int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode) { int ret = 0; struct mwifiex_adapter *adapter = priv->adapter; u16 sub_cmd; - if (action == HostCmd_ACT_GEN_SET) { - if (*ps_mode) - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; - else - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; - sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS; - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, - sub_cmd, BITMAP_STA_PS, wait, NULL); - if ((!ret) && (sub_cmd == DIS_AUTO_PS)) - ret = mwifiex_prepare_cmd(priv, - HostCmd_CMD_802_11_PS_MODE_ENH, GET_PS, - 0, NULL, NULL); - } else { - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, - GET_PS, 0, wait, NULL); - } - - if (!ret) - ret = -EINPROGRESS; + if (*ps_mode) + adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; + else + adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; + sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS; + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_PS_MODE_ENH, + sub_cmd, BITMAP_STA_PS, NULL); + if ((!ret) && (sub_cmd == DIS_AUTO_PS)) + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_802_11_PS_MODE_ENH, GET_PS, + 0, NULL); return ret; } @@ -1600,18 +1086,14 @@ static int mwifiex_set_wapi_ie(struct mwifiex_private *priv, * This function prepares the correct firmware command and * issues it. */ -static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_adapter *adapter, - struct mwifiex_wait_queue *wait, +static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv, struct mwifiex_ds_encrypt_key *encrypt_key) { int ret = 0; - struct mwifiex_private *priv = adapter->priv[wait->bss_index]; - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, - wait, encrypt_key); - if (!ret) - ret = -EINPROGRESS; + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, + encrypt_key); return ret; } @@ -1622,12 +1104,10 @@ static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_adapter *adapter, * This function prepares the correct firmware command and * issues it, after validation checks. */ -static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter, - struct mwifiex_wait_queue *wait, +static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, struct mwifiex_ds_encrypt_key *encrypt_key) { int ret = 0; - struct mwifiex_private *priv = adapter->priv[wait->bss_index]; struct mwifiex_wep_key *wep_key = NULL; int index; @@ -1641,7 +1121,7 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter, /* Copy the required key as the current key */ wep_key = &priv->wep_key[index]; if (!wep_key->key_length) { - dev_err(adapter->dev, + dev_err(priv->adapter->dev, "key not set, so cannot enable it\n"); return -1; } @@ -1661,8 +1141,9 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter, } if (wep_key->key_length) { /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, 0, NULL, NULL); + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, 0, NULL); if (ret) return ret; } @@ -1672,11 +1153,9 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter, priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, wait, - &priv->curr_pkt_filter); - if (!ret) - ret = -EINPROGRESS; + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL, + HostCmd_ACT_GEN_SET, 0, + &priv->curr_pkt_filter); return ret; } @@ -1691,18 +1170,16 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter, * * This function can also be used to disable a currently set key. */ -static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter, - struct mwifiex_wait_queue *wait, +static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, struct mwifiex_ds_encrypt_key *encrypt_key) { int ret = 0; - struct mwifiex_private *priv = adapter->priv[wait->bss_index]; u8 remove_key = false; struct host_cmd_ds_802_11_key_material *ibss_key; /* Current driver only supports key length of up to 32 bytes */ if (encrypt_key->key_len > MWIFIEX_MAX_KEY_LENGTH) { - dev_err(adapter->dev, "key length too long\n"); + dev_err(priv->adapter->dev, "key length too long\n"); return -1; } @@ -1713,9 +1190,10 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter, */ /* Send the key as PTK to firmware */ encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, - NULL, encrypt_key); + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, + encrypt_key); if (ret) return ret; @@ -1740,18 +1218,16 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter, if (remove_key) /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, - !(KEY_INFO_ENABLED), - wait, encrypt_key); + ret = mwifiex_send_cmd_sync(priv, + HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, !(KEY_INFO_ENABLED), + encrypt_key); else /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, - wait, encrypt_key); - - if (!ret) - ret = -EINPROGRESS; + ret = mwifiex_send_cmd_sync(priv, + HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, + encrypt_key); return ret; } @@ -1764,21 +1240,16 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter, */ static int mwifiex_sec_ioctl_encrypt_key(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, struct mwifiex_ds_encrypt_key *encrypt_key) { int status = 0; - struct mwifiex_adapter *adapter = priv->adapter; if (encrypt_key->is_wapi_key) - status = mwifiex_sec_ioctl_set_wapi_key(adapter, wait, - encrypt_key); + status = mwifiex_sec_ioctl_set_wapi_key(priv, encrypt_key); else if (encrypt_key->key_len > WLAN_KEY_LEN_WEP104) - status = mwifiex_sec_ioctl_set_wpa_key(adapter, wait, - encrypt_key); + status = mwifiex_sec_ioctl_set_wpa_key(priv, encrypt_key); else - status = mwifiex_sec_ioctl_set_wep_key(adapter, wait, - encrypt_key); + status = mwifiex_sec_ioctl_set_wep_key(priv, encrypt_key); return status; } @@ -1805,95 +1276,32 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, return 0; } -/* - * Sends IOCTL request to set Tx power. It can be set to either auto - * or a fixed value. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_set_tx_power(struct mwifiex_private *priv, int type, int dbm) -{ - struct mwifiex_power_cfg power_cfg; - struct mwifiex_wait_queue *wait = NULL; - int status = 0; - int ret = 0; - - wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); - if (!wait) - return -ENOMEM; - - if (type == NL80211_TX_POWER_FIXED) { - power_cfg.is_power_auto = 0; - power_cfg.power_level = dbm; - } else { - power_cfg.is_power_auto = 1; - } - status = mwifiex_power_ioctl_set_power(priv, wait, &power_cfg); - - ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); - - kfree(wait); - return ret; -} - -/* - * Sends IOCTL request to get scan table. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_get_scan_table(struct mwifiex_private *priv, u8 wait_option, - struct mwifiex_scan_resp *scan_resp) -{ - struct mwifiex_wait_queue *wait = NULL; - struct mwifiex_scan_resp scan; - int status = 0; - - /* Allocate wait buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; - - status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_GET, - NULL, &scan); - - status = mwifiex_request_ioctl(priv, wait, status, wait_option); - if (!status) { - if (scan_resp) - memcpy(scan_resp, &scan, - sizeof(struct mwifiex_scan_resp)); - } - - if (wait && (status != -EINPROGRESS)) - kfree(wait); - return status; -} - /* * Sends IOCTL request to get signal information. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler. */ -int mwifiex_get_signal_info(struct mwifiex_private *priv, u8 wait_option, +int mwifiex_get_signal_info(struct mwifiex_private *priv, struct mwifiex_ds_get_signal *signal) { struct mwifiex_ds_get_signal info; - struct mwifiex_wait_queue *wait = NULL; int status = 0; - /* Allocate wait buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; - + memset(&info, 0, sizeof(struct mwifiex_ds_get_signal)); info.selector = ALL_RSSI_INFO_MASK; - status = mwifiex_get_info_signal(priv, wait, &info); + /* Signal info can be obtained only if connected */ + if (!priv->media_connected) { + dev_dbg(priv->adapter->dev, + "info: Can not get signal in disconnected state\n"); + return -1; + } + + /* Send request to firmware */ + status = mwifiex_send_cmd_sync(priv, HostCmd_CMD_RSSI_INFO, + HostCmd_ACT_GEN_GET, 0, signal); - status = mwifiex_request_ioctl(priv, wait, status, wait_option); if (!status) { if (signal) memcpy(signal, &info, @@ -1904,8 +1312,6 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv, u8 wait_option, priv->w_stats.qual.noise = info.bcn_nf_avg; } - if (wait && (status != -EINPROGRESS)) - kfree(wait); return status; } @@ -1918,15 +1324,9 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv, u8 wait_option, int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, int key_len, u8 key_index, int disable) { - struct mwifiex_wait_queue *wait = NULL; struct mwifiex_ds_encrypt_key encrypt_key; - int status = 0; int ret = 0; - wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); - if (!wait) - return -ENOMEM; - memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key)); encrypt_key.key_len = key_len; if (!disable) { @@ -1937,40 +1337,8 @@ int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, encrypt_key.key_disable = true; } - status = mwifiex_sec_ioctl_encrypt_key(priv, wait, &encrypt_key); - - if (mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT)) - ret = -EFAULT; - - kfree(wait); - return ret; -} - -/* - * Sends IOCTL request to set power management parameters. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_drv_set_power(struct mwifiex_private *priv, bool power_on) -{ - int ret = 0; - int status = 0; - struct mwifiex_wait_queue *wait = NULL; - u32 ps_mode; - - wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); - if (!wait) - return -ENOMEM; - - ps_mode = power_on; - status = mwifiex_pm_ioctl_ps_mode(priv, wait, &ps_mode, - HostCmd_ACT_GEN_SET); + ret = mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key); - ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); - - kfree(wait); return ret; } @@ -1984,26 +1352,17 @@ int mwifiex_get_ver_ext(struct mwifiex_private *priv) { struct mwifiex_ver_ext ver_ext; - struct mwifiex_wait_queue *wait = NULL; - int status = 0; int ret = 0; - u8 wait_option = MWIFIEX_IOCTL_WAIT; - - /* Allocate wait buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; /* get fw version */ memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext)); - status = mwifiex_get_info_ver_ext(priv, wait, &ver_ext); - - ret = mwifiex_request_ioctl(priv, wait, status, wait_option); + /* Send request to firmware */ + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_VERSION_EXT, + HostCmd_ACT_GEN_GET, 0, &ver_ext); if (ret) ret = -1; - kfree(wait); return ret; } @@ -2018,21 +1377,13 @@ mwifiex_get_stats_info(struct mwifiex_private *priv, struct mwifiex_ds_get_stats *log) { int ret = 0; - int status = 0; - struct mwifiex_wait_queue *wait = NULL; struct mwifiex_ds_get_stats get_log; - u8 wait_option = MWIFIEX_IOCTL_WAIT; - - /* Allocate wait buffer */ - wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); - if (!wait) - return -ENOMEM; memset(&get_log, 0, sizeof(struct mwifiex_ds_get_stats)); - status = mwifiex_get_info_stats(priv, wait, &get_log); + /* Send request to firmware */ + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG, + HostCmd_ACT_GEN_GET, 0, &get_log); - /* Send IOCTL request to MWIFIEX */ - ret = mwifiex_request_ioctl(priv, wait, status, wait_option); if (!ret) { if (log) memcpy(log, &get_log, sizeof(struct @@ -2042,7 +1393,6 @@ mwifiex_get_stats_info(struct mwifiex_private *priv, priv->w_stats.discard.misc = get_log.ack_failure; } - kfree(wait); return ret; } @@ -2060,7 +1410,6 @@ mwifiex_get_stats_info(struct mwifiex_private *priv, * - CAU */ static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, struct mwifiex_ds_reg_rw *reg_rw, u16 action) { @@ -2088,10 +1437,7 @@ static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv, } /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, cmd_no, action, 0, wait, reg_rw); - - if (!ret) - ret = -EINPROGRESS; + ret = mwifiex_send_cmd_sync(priv, cmd_no, action, 0, reg_rw); return ret; } @@ -2107,23 +1453,13 @@ mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type, u32 reg_offset, u32 reg_value) { int ret = 0; - int status = 0; - struct mwifiex_wait_queue *wait = NULL; struct mwifiex_ds_reg_rw reg_rw; - wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); - if (!wait) - return -ENOMEM; - reg_rw.type = cpu_to_le32(reg_type); reg_rw.offset = cpu_to_le32(reg_offset); reg_rw.value = cpu_to_le32(reg_value); - status = mwifiex_reg_mem_ioctl_reg_rw(priv, wait, ®_rw, - HostCmd_ACT_GEN_SET); + ret = mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_SET); - ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); - - kfree(wait); return ret; } @@ -2138,50 +1474,18 @@ mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type, u32 reg_offset, u32 *value) { int ret = 0; - int status = 0; - struct mwifiex_wait_queue *wait = NULL; struct mwifiex_ds_reg_rw reg_rw; - wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); - if (!wait) - return -ENOMEM; - reg_rw.type = cpu_to_le32(reg_type); reg_rw.offset = cpu_to_le32(reg_offset); - status = mwifiex_reg_mem_ioctl_reg_rw(priv, wait, ®_rw, - HostCmd_ACT_GEN_GET); + ret = mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_GET); - ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); if (ret) goto done; *value = le32_to_cpu(reg_rw.value); done: - kfree(wait); - return ret; -} - -/* - * IOCTL request handler to read EEPROM. - * - * This function prepares the correct firmware command and - * issues it. - */ -static int -mwifiex_reg_mem_ioctl_read_eeprom(struct mwifiex_private *priv, - struct mwifiex_wait_queue *wait, - struct mwifiex_ds_read_eeprom *rd_eeprom) -{ - int ret = 0; - - /* Send request to firmware */ - ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_EEPROM_ACCESS, - HostCmd_ACT_GEN_GET, 0, wait, rd_eeprom); - - if (!ret) - ret = -EINPROGRESS; - return ret; } @@ -2196,25 +1500,17 @@ mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, u8 *value) { int ret = 0; - int status = 0; - struct mwifiex_wait_queue *wait = NULL; struct mwifiex_ds_read_eeprom rd_eeprom; - wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); - if (!wait) - return -ENOMEM; - rd_eeprom.offset = cpu_to_le16((u16) offset); rd_eeprom.byte_count = cpu_to_le16((u16) bytes); - status = mwifiex_reg_mem_ioctl_read_eeprom(priv, wait, &rd_eeprom); - ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); - if (ret) - goto done; + /* Send request to firmware */ + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_EEPROM_ACCESS, + HostCmd_ACT_GEN_GET, 0, &rd_eeprom); - memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA); -done: - kfree(wait); + if (!ret) + memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA); return ret; } diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index e8db6bd021c6..b261d812c4d3 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c @@ -51,7 +51,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, if (!skb->len) { dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len); - tx_info->status_code = MWIFIEX_ERROR_PKT_SIZE_INVALID; + tx_info->status_code = -1; return skb->data; } diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 205022aa52f5..9f65587622fd 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c @@ -55,17 +55,12 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter) } /* - * IOCTL request handler to send function init/shutdown command + * This function sends init/shutdown command * to firmware. - * - * This function prepares the correct firmware command and - * issues it. */ -int mwifiex_misc_ioctl_init_shutdown(struct mwifiex_adapter *adapter, - struct mwifiex_wait_queue *wait, - u32 func_init_shutdown) +int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, + u32 func_init_shutdown) { - struct mwifiex_private *priv = adapter->priv[wait->bss_index]; int ret; u16 cmd; @@ -74,19 +69,16 @@ int mwifiex_misc_ioctl_init_shutdown(struct mwifiex_adapter *adapter, } else if (func_init_shutdown == MWIFIEX_FUNC_SHUTDOWN) { cmd = HostCmd_CMD_FUNC_SHUTDOWN; } else { - dev_err(adapter->dev, "unsupported parameter\n"); + dev_err(priv->adapter->dev, "unsupported parameter\n"); return -1; } /* Send command to firmware */ - ret = mwifiex_prepare_cmd(priv, cmd, HostCmd_ACT_GEN_SET, - 0, wait, NULL); - - if (!ret) - ret = -EINPROGRESS; + ret = mwifiex_send_cmd_sync(priv, cmd, HostCmd_ACT_GEN_SET, 0, NULL); return ret; } +EXPORT_SYMBOL_GPL(mwifiex_init_shutdown_fw); /* * IOCTL request handler to set/get debug information. @@ -222,31 +214,18 @@ int mwifiex_recv_complete(struct mwifiex_adapter *adapter, * corresponding waiting function. Otherwise, it processes the * IOCTL response and frees the response buffer. */ -int mwifiex_ioctl_complete(struct mwifiex_adapter *adapter, - struct mwifiex_wait_queue *wait_queue, - int status) +int mwifiex_complete_cmd(struct mwifiex_adapter *adapter) { - enum mwifiex_error_code status_code = - (enum mwifiex_error_code) wait_queue->status; - - atomic_dec(&adapter->ioctl_pending); + atomic_dec(&adapter->cmd_pending); + dev_dbg(adapter->dev, "cmd completed: status=%d\n", + adapter->cmd_wait_q.status); - dev_dbg(adapter->dev, "cmd: IOCTL completed: status=%d," - " status_code=%#x\n", status, status_code); + adapter->cmd_wait_q.condition = true; - if (wait_queue->enabled) { - *wait_queue->condition = true; - wait_queue->status = status; - if (status && (status_code == MWIFIEX_ERROR_CMD_TIMEOUT)) - dev_err(adapter->dev, "cmd timeout\n"); - else - wake_up_interruptible(wait_queue->wait); - } else { - if (status) - dev_err(adapter->dev, "cmd failed: status_code=%#x\n", - status_code); - kfree(wait_queue); - } + if (adapter->cmd_wait_q.status == -ETIMEDOUT) + dev_err(adapter->dev, "cmd timeout\n"); + else + wake_up_interruptible(&adapter->cmd_wait_q.wait); return 0; } -- cgit v1.2.3-58-ga151 From 19a898601ad192d8c59c3a8f1a4501919f53b94d Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Wed, 13 Apr 2011 17:27:07 -0700 Subject: mwifiex: remove redundant "return" at end of void function The return statement at the last line of a void function is not necessary. Signed-off-by: Yogesh Ashok Powar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n.c | 6 ------ drivers/net/wireless/mwifiex/11n_rxreorder.c | 4 ---- drivers/net/wireless/mwifiex/cfg80211.c | 2 -- drivers/net/wireless/mwifiex/cmdevt.c | 13 +------------ drivers/net/wireless/mwifiex/debugfs.c | 3 --- drivers/net/wireless/mwifiex/init.c | 6 ------ drivers/net/wireless/mwifiex/main.c | 3 --- drivers/net/wireless/mwifiex/sdio.c | 4 ---- drivers/net/wireless/mwifiex/sta_cmdresp.c | 2 -- drivers/net/wireless/mwifiex/wmm.c | 2 -- 10 files changed, 1 insertion(+), 44 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index edf4c274fa9b..c57107a860d1 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -543,8 +543,6 @@ mwifiex_cfg_tx_buf(struct mwifiex_private *priv, if (curr_tx_buf_size != tx_buf) mwifiex_send_cmd_async(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, HostCmd_ACT_GEN_SET, 0, &tx_buf); - - return; } /* @@ -582,8 +580,6 @@ void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv, list_del(&tx_ba_tsr_tbl->list); kfree(tx_ba_tsr_tbl); - - return; } /* @@ -662,8 +658,6 @@ void mwifiex_11n_create_tx_ba_stream_tbl(struct mwifiex_private *priv, list_add_tail(&new_node->list, &priv->tx_ba_stream_tbl_ptr); spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); } - - return; } /* diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index ef46d0a8a6d0..6736fc604844 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -309,8 +309,6 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); list_add_tail(&new_node->list, &priv->rx_reorder_tbl_ptr); spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - - return; } /* @@ -610,8 +608,6 @@ void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv, (u16) event->origninator << DELBA_INITIATOR_POS); delba.reason_code = cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_DELBA, 0, 0, &delba); - - return; } /* diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index a1ff490da836..74b6cf20da04 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1428,6 +1428,4 @@ done: memset(priv->cfg_bssid, 0, ETH_ALEN); priv->disconnect = 0; } - - return; } diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index bb6fecd77619..776146a104ec 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -94,8 +94,6 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, mwifiex_recv_complete(adapter, cmd_node->resp_skb, 0); cmd_node->resp_skb = NULL; } - - return; } /* @@ -536,7 +534,7 @@ mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, { unsigned long flags; - if (cmd_node == NULL) + if (!cmd_node) return; if (cmd_node->wait_q_enabled) @@ -548,8 +546,6 @@ mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, spin_lock_irqsave(&adapter->cmd_free_q_lock, flags); list_add_tail(&cmd_node->list, &adapter->cmd_free_q); spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); - - return; } /* @@ -594,8 +590,6 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x is queued\n", command); - - return; } /* @@ -871,8 +865,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context) } if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) mwifiex_init_fw_complete(adapter); - - return; } /* @@ -989,8 +981,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) } adapter->cmd_wait_q.status = -1; mwifiex_complete_cmd(adapter); - - return; } /* @@ -1094,7 +1084,6 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter) adapter->is_hs_configured = false; mwifiex_hs_activated_event(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY), false); - return; } /* diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index 77d7c777ea66..7ddcb062f103 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c @@ -735,8 +735,6 @@ mwifiex_dev_debugfs_init(struct mwifiex_private *priv) MWIFIEX_DFS_ADD_FILE(getlog); MWIFIEX_DFS_ADD_FILE(regrdwr); MWIFIEX_DFS_ADD_FILE(rdeeprom); - - return; } /* @@ -749,7 +747,6 @@ mwifiex_dev_debugfs_remove(struct mwifiex_private *priv) return; debugfs_remove_recursive(priv->dfs_dev_dir); - return; } /* diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 26931d5f950f..1b79a5ac9214 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -299,8 +299,6 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) adapter->adhoc_awake_period = 0; memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); adapter->arp_filter_size = 0; - - return; } /* @@ -339,8 +337,6 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter) adapter->if_ops.cleanup_if(adapter); dev_kfree_skb_any(adapter->sleep_cfm); - - return; } /* @@ -428,8 +424,6 @@ void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) list_del(&priv->rx_reorder_tbl_ptr); } } - - return; } /* diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index df665db8c433..77abfc3d6c32 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -505,7 +505,6 @@ mwifiex_fill_buffer(struct sk_buff *skb) */ do_gettimeofday(&tv); skb->tstamp = timeval_to_ktime(tv); - return; } /* @@ -820,8 +819,6 @@ mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index) wiphy_unregister(priv->wdev->wiphy); wiphy_free(priv->wdev->wiphy); kfree(priv->wdev); - - return; } /* diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index f207756cbb79..fa46df509757 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -859,8 +859,6 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) adapter->int_status |= sdio_ireg; spin_unlock_irqrestore(&adapter->int_lock, flags); } - - return; } /* @@ -891,8 +889,6 @@ mwifiex_sdio_interrupt(struct sdio_func *func) mwifiex_interrupt_status(adapter); queue_work(adapter->workqueue, &adapter->main_work); - - return; } /* diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 8743c116bee5..20ce8cb39186 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -103,8 +103,6 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); adapter->curr_cmd = NULL; spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - - return; } /* diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 1cfbc6bed692..6ce6f94e222b 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -1232,6 +1232,4 @@ mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) if (mwifiex_dequeue_tx_packet(adapter)) break; } while (true); - - return; } -- cgit v1.2.3-58-ga151 From 572e8f3ead47ad223fb428a4f1db986317e8e0ec Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 13 Apr 2011 17:27:08 -0700 Subject: mwifiex: remove unused function parameters Some function parameters become useless after previous cleanup changes. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n.c | 13 +++----- drivers/net/wireless/mwifiex/11n.h | 50 ++++++++++------------------ drivers/net/wireless/mwifiex/11n_aggr.c | 5 ++- drivers/net/wireless/mwifiex/11n_rxreorder.c | 6 ++-- drivers/net/wireless/mwifiex/11n_rxreorder.h | 6 ++-- drivers/net/wireless/mwifiex/cfp.c | 9 ++--- drivers/net/wireless/mwifiex/main.h | 17 +++------- drivers/net/wireless/mwifiex/scan.c | 7 ++-- drivers/net/wireless/mwifiex/sdio.c | 18 +++++----- drivers/net/wireless/mwifiex/sta_cmd.c | 40 ++++++++++------------ drivers/net/wireless/mwifiex/sta_cmdresp.c | 13 +++----- drivers/net/wireless/mwifiex/sta_ioctl.c | 7 ++-- drivers/net/wireless/mwifiex/wmm.c | 17 +++++----- drivers/net/wireless/mwifiex/wmm.h | 8 ++--- 14 files changed, 80 insertions(+), 136 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index c57107a860d1..d64065ff235c 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -242,9 +242,7 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, * * Handling includes changing the header fields into CPU format. */ -int mwifiex_ret_11n_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *data_buf) +int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf) { struct mwifiex_ds_11n_tx_cfg *tx_cfg = NULL; struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg; @@ -298,8 +296,7 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv, * - Setting AMSDU control parameters (for SET only) * - Ensuring correct endian-ness */ -int mwifiex_cmd_amsdu_aggr_ctrl(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, +int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, int cmd_action, void *data_buf) { struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl = @@ -331,8 +328,7 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct mwifiex_private *priv, * * Handling includes changing the header fields into CPU format. */ -int mwifiex_ret_amsdu_aggr_ctrl(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, +int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp, void *data_buf) { struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl = NULL; @@ -357,8 +353,7 @@ int mwifiex_ret_amsdu_aggr_ctrl(struct mwifiex_private *priv, * - Setting HT Tx capability and HT Tx information fields * - Ensuring correct endian-ness */ -int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, +int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, void *data_buf) { struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg; diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 71a853e61b61..9128d2c9638b 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h @@ -28,15 +28,9 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); -int mwifiex_ret_11n_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, +int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf); -int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf); - -int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, +int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, void *data_buf); int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, @@ -67,24 +61,19 @@ int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv, struct mwifiex_ds_rx_reorder_tbl *buf); int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, struct mwifiex_ds_tx_ba_stream_tbl *buf); -int mwifiex_ret_amsdu_aggr_ctrl(struct mwifiex_private *priv, - struct host_cmd_ds_command - *resp, +int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp, void *data_buf); int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, int cmd_action, void *data_buf); -int mwifiex_cmd_amsdu_aggr_ctrl(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - int cmd_action, - void *data_buf); +int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, + int cmd_action, void *data_buf); /* * This function checks whether AMPDU is allowed or not for a particular TID. */ static inline u8 -mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int tid) +mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, int tid) { return ((priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED) ? true : false); @@ -94,8 +83,7 @@ mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, * This function checks whether AMSDU is allowed or not for a particular TID. */ static inline u8 -mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int tid) +mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, int tid) { return (((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED) && ((priv->is_data_rate_auto) @@ -106,21 +94,18 @@ mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, /* * This function checks whether a BA stream is available or not. */ -static inline u8 -mwifiex_is_ba_stream_avail(struct mwifiex_private *priv) +static inline u8 mwifiex_is_ba_stream_avail(struct mwifiex_adapter *adapter) { - struct mwifiex_private *pmpriv = NULL; - u8 i = 0; + struct mwifiex_private *priv; + u8 i; u32 ba_stream_num = 0; - for (i = 0; i < priv->adapter->priv_num; i++) { - pmpriv = priv->adapter->priv[i]; - if (pmpriv) - ba_stream_num += - mwifiex_wmm_list_len(priv->adapter, - (struct list_head - *) &pmpriv-> - tx_ba_stream_tbl_ptr); + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + if (priv) + ba_stream_num += mwifiex_wmm_list_len( + (struct list_head *) + &priv->tx_ba_stream_tbl_ptr); } return ((ba_stream_num < @@ -133,8 +118,7 @@ mwifiex_is_ba_stream_avail(struct mwifiex_private *priv) * Upon successfully locating, both the TID and the RA are returned. */ static inline u8 -mwifiex_find_stream_to_delete(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int ptr_tid, +mwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid, int *ptid, u8 *ra) { int tid; diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index c2abced66957..c9fb0627de43 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -44,8 +44,7 @@ * MSDU => |DA|SA|Length|SNAP|...... ..| */ static int -mwifiex_11n_form_amsdu_pkt(struct mwifiex_adapter *adapter, - struct sk_buff *skb_aggr, +mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr, struct sk_buff *skb_src, int *pad) { @@ -324,7 +323,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); - mwifiex_11n_form_amsdu_pkt(adapter, skb_aggr, skb_src, &pad); + mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); mwifiex_write_data_complete(adapter, skb_src, 0); diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index 6736fc604844..755e5d533c03 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -319,8 +319,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, * - Setting add BA request buffer * - Ensuring correct endian-ness */ -int mwifiex_cmd_11n_addba_req(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, void *data_buf) +int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf) { struct host_cmd_ds_11n_addba_req *add_ba_req = (struct host_cmd_ds_11n_addba_req *) @@ -391,8 +390,7 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, * - Setting del BA request buffer * - Ensuring correct endian-ness */ -int mwifiex_cmd_11n_delba(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, void *data_buf) +int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd, void *data_buf) { struct host_cmd_ds_11n_delba *del_ba = (struct host_cmd_ds_11n_delba *) &cmd->params.del_ba; diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h index 42f569035745..f3ca8c8c18f9 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h @@ -49,14 +49,12 @@ void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv, int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); -int mwifiex_cmd_11n_delba(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, +int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd, void *data_buf); int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, void *data_buf); -int mwifiex_cmd_11n_addba_req(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, +int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf); void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv); struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c index 07187a405fee..bb73cfe14aeb 100644 --- a/drivers/net/wireless/mwifiex/cfp.c +++ b/drivers/net/wireless/mwifiex/cfp.c @@ -75,8 +75,7 @@ u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 }; * This function maps an index in supported rates table into * the corresponding data rate. */ -u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index, - u8 ht_info) +u32 mwifiex_index_to_data_rate(u8 index, u8 ht_info) { u16 mcs_rate[4][8] = { {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e} @@ -126,7 +125,7 @@ u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index, * This function maps a data rate value into corresponding index in supported * rates table. */ -u8 mwifiex_data_rate_to_index(struct mwifiex_adapter *adapter, u32 rate) +u8 mwifiex_data_rate_to_index(u32 rate) { u16 *ptr; @@ -265,9 +264,7 @@ mwifiex_is_rate_auto(struct mwifiex_private *priv) /* * This function converts rate bitmap into rate index. */ -int -mwifiex_get_rate_index(struct mwifiex_adapter *adapter, u16 *rate_bitmap, - int size) +int mwifiex_get_rate_index(u16 *rate_bitmap, int size) { int i; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 7ead15e1967e..2d296dcc210e 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -767,8 +767,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta); int mwifiex_scan_networks(struct mwifiex_private *priv, const struct mwifiex_user_scan_cfg *user_scan_in); -int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, +int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, void *data_buf); void mwifiex_queue_scan_cmd(struct mwifiex_private *priv, struct cmd_ctrl_node *cmd_node); @@ -806,9 +805,7 @@ int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, void *data_buf); int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); -int mwifiex_cmd_802_11_bg_scan_query(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - void *data_buf); +int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd); struct mwifiex_chan_freq_power * mwifiex_get_cfp_by_band_and_channel_from_cfg80211( struct mwifiex_private *priv, @@ -816,20 +813,16 @@ struct mwifiex_chan_freq_power * struct mwifiex_chan_freq_power *mwifiex_get_cfp_by_band_and_freq_from_cfg80211( struct mwifiex_private *priv, u8 band, u32 freq); -u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index, - u8 ht_info); +u32 mwifiex_index_to_data_rate(u8 index, u8 ht_info); u32 mwifiex_find_freq_from_band_chan(u8, u8); int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask, u8 **buffer); -u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index, - u8 ht_info); u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, u8 *rates); u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates); -u8 mwifiex_data_rate_to_index(struct mwifiex_adapter *adapter, u32 rate); +u8 mwifiex_data_rate_to_index(u32 rate); u8 mwifiex_is_rate_auto(struct mwifiex_private *priv); -int mwifiex_get_rate_index(struct mwifiex_adapter *adapter, - u16 *rateBitmap, int size); +int mwifiex_get_rate_index(u16 *rateBitmap, int size); extern u16 region_code_index[MWIFIEX_MAX_REGION_CODE]; void mwifiex_save_curr_bcn(struct mwifiex_private *priv); void mwifiex_free_curr_bcn(struct mwifiex_private *priv); diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 12fe021536d1..84742715893f 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -2364,8 +2364,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, * - Setting command ID, and proper size * - Ensuring correct endian-ness */ -int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, void *data_buf) +int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, void *data_buf) { struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan; struct mwifiex_scan_cmd_config *scan_cfg; @@ -2658,9 +2657,7 @@ done: * - Setting background scan flush parameter * - Ensuring correct endian-ness */ -int mwifiex_cmd_802_11_bg_scan_query(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - void *data_buf) +int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd) { struct host_cmd_ds_802_11_bg_scan_query *bg_query = &cmd->params.bg_scan_query; diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index fa46df509757..41c087d3f0f5 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -282,7 +282,7 @@ mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u32 *data) */ static int mwifiex_write_data_sync(struct mwifiex_adapter *adapter, - u8 *buffer, u32 pkt_len, u32 port, u32 timeout) + u8 *buffer, u32 pkt_len, u32 port) { struct sdio_mmc_card *card = adapter->card; int ret = -1; @@ -314,9 +314,8 @@ mwifiex_write_data_sync(struct mwifiex_adapter *adapter, /* * This function reads multiple data from SDIO card memory. */ -static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, - u8 *buffer, u32 len, - u32 port, u32 timeout, u8 claim) +static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer, + u32 len, u32 port, u8 claim) { struct sdio_mmc_card *card = adapter->card; int ret = -1; @@ -430,8 +429,7 @@ static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter, int ret = 0; do { - ret = mwifiex_write_data_sync(adapter, payload, pkt_len, - port, 0); + ret = mwifiex_write_data_sync(adapter, payload, pkt_len, port); if (ret) { i++; dev_err(adapter->dev, "host_to_card, write iomem" @@ -630,7 +628,7 @@ static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter, return -1; } - ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 0, 1); + ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 1); if (ret) { dev_err(adapter->dev, "%s: read iomem failed: %d\n", __func__, @@ -769,7 +767,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, ret = mwifiex_write_data_sync(adapter, fwbuf, tx_blocks * MWIFIEX_SDIO_BLOCK_SIZE, - adapter->ioport, 0); + adapter->ioport); if (ret) { dev_err(adapter->dev, "FW download, write iomem (%d)" " failed @ %d\n", i, offset); @@ -842,7 +840,7 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) unsigned long flags; if (mwifiex_read_data_sync(adapter, card->mp_regs, MAX_MP_REGS, - REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0, + REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0)) { dev_err(adapter->dev, "read mp_regs failed\n"); return; @@ -1050,7 +1048,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, card->mpa_rx.buf_len, (adapter->ioport | 0x1000 | (card->mpa_rx.ports << 4)) + - card->mpa_rx.start_port, 0, 1)) + card->mpa_rx.start_port, 1)) return -1; curr_ptr = card->mpa_rx.buf; diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index dec496369b95..33c8ba1f5e33 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -190,8 +190,7 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv, * - Ensuring correct endian-ness */ static int -mwifiex_cmd_802_11_get_log(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd) +mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command *cmd) { cmd->command = cpu_to_le16(HostCmd_CMD_802_11_GET_LOG); cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log) + @@ -272,8 +271,7 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, * (as required) * - Ensuring correct endian-ness */ -static int mwifiex_cmd_tx_power_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, +static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, void *data_buf) { struct mwifiex_types_power_group *pg_tlv = NULL; @@ -407,8 +405,7 @@ static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv, * - Setting MAC multicast address * - Ensuring correct endian-ness */ -static int mwifiex_cmd_mac_multicast_adr(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, +static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd, u16 cmd_action, void *data_buf) { struct mwifiex_multicast_list *mcast_list = @@ -463,8 +460,7 @@ static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv, * - Setting command ID and proper size * - Ensuring correct endian-ness */ -static int mwifiex_cmd_802_11_ad_hoc_stop(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd) +static int mwifiex_cmd_802_11_ad_hoc_stop(struct host_cmd_ds_command *cmd) { cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP); cmd->size = cpu_to_le16(S_DS_GEN); @@ -777,8 +773,7 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv, * - Setting status to enable or disable (for SET only) * - Ensuring correct endian-ness */ -static int mwifiex_cmd_ibss_coalescing_status(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, +static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd, u16 cmd_action, void *data_buf) { struct host_cmd_ds_802_11_ibss_status *ibss_coal = @@ -946,7 +941,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, cmd_action); break; case HostCmd_CMD_MAC_MULTICAST_ADR: - ret = mwifiex_cmd_mac_multicast_adr(priv, cmd_ptr, cmd_action, + ret = mwifiex_cmd_mac_multicast_adr(cmd_ptr, cmd_action, data_buf); break; case HostCmd_CMD_TX_RATE_CFG: @@ -954,7 +949,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, data_buf); break; case HostCmd_CMD_TXPWR_CFG: - ret = mwifiex_cmd_tx_power_cfg(priv, cmd_ptr, cmd_action, + ret = mwifiex_cmd_tx_power_cfg(cmd_ptr, cmd_action, data_buf); break; case HostCmd_CMD_802_11_PS_MODE_ENH: @@ -966,11 +961,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, (struct mwifiex_hs_config_param *) data_buf); break; case HostCmd_CMD_802_11_SCAN: - ret = mwifiex_cmd_802_11_scan(priv, cmd_ptr, data_buf); + ret = mwifiex_cmd_802_11_scan(cmd_ptr, data_buf); break; case HostCmd_CMD_802_11_BG_SCAN_QUERY: - ret = mwifiex_cmd_802_11_bg_scan_query(priv, cmd_ptr, - data_buf); + ret = mwifiex_cmd_802_11_bg_scan_query(cmd_ptr); break; case HostCmd_CMD_802_11_ASSOCIATE: ret = mwifiex_cmd_802_11_associate(priv, cmd_ptr, data_buf); @@ -984,14 +978,14 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, data_buf); break; case HostCmd_CMD_802_11_GET_LOG: - ret = mwifiex_cmd_802_11_get_log(priv, cmd_ptr); + ret = mwifiex_cmd_802_11_get_log(cmd_ptr); break; case HostCmd_CMD_802_11_AD_HOC_JOIN: ret = mwifiex_cmd_802_11_ad_hoc_join(priv, cmd_ptr, data_buf); break; case HostCmd_CMD_802_11_AD_HOC_STOP: - ret = mwifiex_cmd_802_11_ad_hoc_stop(priv, cmd_ptr); + ret = mwifiex_cmd_802_11_ad_hoc_stop(cmd_ptr); break; case HostCmd_CMD_RSSI_INFO: ret = mwifiex_cmd_802_11_rssi_info(priv, cmd_ptr, cmd_action); @@ -1036,10 +1030,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, cmd_ptr->size = cpu_to_le16(S_DS_GEN); break; case HostCmd_CMD_11N_ADDBA_REQ: - ret = mwifiex_cmd_11n_addba_req(priv, cmd_ptr, data_buf); + ret = mwifiex_cmd_11n_addba_req(cmd_ptr, data_buf); break; case HostCmd_CMD_11N_DELBA: - ret = mwifiex_cmd_11n_delba(priv, cmd_ptr, data_buf); + ret = mwifiex_cmd_11n_delba(cmd_ptr, data_buf); break; case HostCmd_CMD_11N_ADDBA_RSP: ret = mwifiex_cmd_11n_addba_rsp_gen(priv, cmd_ptr, data_buf); @@ -1058,11 +1052,11 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, data_buf); break; case HostCmd_CMD_AMSDU_AGGR_CTRL: - ret = mwifiex_cmd_amsdu_aggr_ctrl(priv, cmd_ptr, cmd_action, + ret = mwifiex_cmd_amsdu_aggr_ctrl(cmd_ptr, cmd_action, data_buf); break; case HostCmd_CMD_11N_CFG: - ret = mwifiex_cmd_11n_cfg(priv, cmd_ptr, cmd_action, + ret = mwifiex_cmd_11n_cfg(cmd_ptr, cmd_action, data_buf); break; case HostCmd_CMD_WMM_GET_STATUS: @@ -1075,8 +1069,8 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, ret = 0; break; case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: - ret = mwifiex_cmd_ibss_coalescing_status(priv, cmd_ptr, - cmd_action, data_buf); + ret = mwifiex_cmd_ibss_coalescing_status(cmd_ptr, cmd_action, + data_buf); break; case HostCmd_CMD_MAC_REG_ACCESS: case HostCmd_CMD_BBP_REG_ACCESS: diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 20ce8cb39186..7f4f10b752fb 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -280,7 +280,6 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, struct host_cmd_ds_command *resp, void *data_buf) { - struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_rate_cfg *ds_rate = NULL; struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg; struct mwifiex_rate_scope *rate_scope; @@ -336,9 +335,7 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, if (priv->is_data_rate_auto) { ds_rate->is_rate_auto = 1; } else { - ds_rate->rate = - mwifiex_get_rate_index(adapter, - priv-> + ds_rate->rate = mwifiex_get_rate_index(priv-> bitmap_rates, sizeof(priv-> bitmap_rates)); @@ -514,13 +511,11 @@ static int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv, static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv, struct host_cmd_ds_command *resp) { - struct mwifiex_adapter *adapter = priv->adapter; - priv->tx_rate = resp->params.tx_rate.tx_rate; priv->tx_htinfo = resp->params.tx_rate.ht_info; if (!priv->is_data_rate_auto) priv->data_rate = - mwifiex_index_to_data_rate(adapter, priv->tx_rate, + mwifiex_index_to_data_rate(priv->tx_rate, priv->tx_htinfo); return 0; @@ -946,7 +941,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, mp_end_port)); break; case HostCmd_CMD_AMSDU_AGGR_CTRL: - ret = mwifiex_ret_amsdu_aggr_ctrl(priv, resp, data_buf); + ret = mwifiex_ret_amsdu_aggr_ctrl(resp, data_buf); break; case HostCmd_CMD_WMM_GET_STATUS: ret = mwifiex_ret_wmm_get_status(priv, resp); @@ -965,7 +960,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, case HostCmd_CMD_SET_BSS_MODE: break; case HostCmd_CMD_11N_CFG: - ret = mwifiex_ret_11n_cfg(priv, resp, data_buf); + ret = mwifiex_ret_11n_cfg(resp, data_buf); break; default: dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 5f2ce9459d26..6489f264ef5f 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -812,8 +812,7 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv, } memset(bitmap_rates, 0, sizeof(bitmap_rates)); - rate_index = - mwifiex_data_rate_to_index(adapter, rate_cfg->rate); + rate_index = mwifiex_data_rate_to_index(rate_cfg->rate); /* Only allow b/g rates to be set */ if (rate_index >= MWIFIEX_RATE_INDEX_HRDSSS0 && @@ -874,8 +873,8 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, if (!ret) { if (rate && rate->is_rate_auto) - rate->rate = mwifiex_index_to_data_rate(priv->adapter, - priv->tx_rate, priv->tx_htinfo); + rate->rate = mwifiex_index_to_data_rate(priv->tx_rate, + priv->tx_htinfo); else if (rate) rate->rate = priv->data_rate; } else { diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 6ce6f94e222b..57b98c59235d 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -177,8 +177,7 @@ static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv) * This function map ACs to TIDs. */ static void -mwifiex_wmm_queue_priorities_tid(struct mwifiex_private *priv, - u8 queue_priority[]) +mwifiex_wmm_queue_priorities_tid(u8 queue_priority[]) { int i; @@ -247,7 +246,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, } } - mwifiex_wmm_queue_priorities_tid(priv, priv->wmm.queue_priority); + mwifiex_wmm_queue_priorities_tid(priv->wmm.queue_priority); } /* @@ -416,7 +415,7 @@ mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) priv = adapter->priv[j]; if (priv) { for (i = 0; i < MAX_NUM_TID; i++) - if (!mwifiex_wmm_is_ra_list_empty(adapter, + if (!mwifiex_wmm_is_ra_list_empty( &priv->wmm.tid_tbl_ptr[i].ra_list)) return false; } @@ -1161,7 +1160,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) if (!ptr) return -1; - tid = mwifiex_get_tid(priv->adapter, ptr); + tid = mwifiex_get_tid(ptr); dev_dbg(adapter->dev, "data: tid=%d\n", tid); @@ -1186,14 +1185,14 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) /* ra_list_spinlock has been freed in mwifiex_send_single_packet() */ } else { - if (mwifiex_is_ampdu_allowed(priv, ptr, tid)) { - if (mwifiex_is_ba_stream_avail(priv)) { + if (mwifiex_is_ampdu_allowed(priv, tid)) { + if (mwifiex_is_ba_stream_avail(adapter)) { mwifiex_11n_create_tx_ba_stream_tbl(priv, ptr->ra, tid, BA_STREAM_SETUP_INPROGRESS); mwifiex_send_addba(priv, tid, ptr->ra); } else if (mwifiex_find_stream_to_delete - (priv, ptr, tid, &tid_del, ra)) { + (priv, tid, &tid_del, ra)) { mwifiex_11n_create_tx_ba_stream_tbl(priv, ptr->ra, tid, BA_STREAM_SETUP_INPROGRESS); @@ -1202,7 +1201,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) } /* Minimum number of AMSDU */ #define MIN_NUM_AMSDU 2 - if (mwifiex_is_amsdu_allowed(priv, ptr, tid) && + if (mwifiex_is_amsdu_allowed(priv, tid) && (mwifiex_num_pkts_in_txq(priv, ptr, adapter->tx_buf_size) >= MIN_NUM_AMSDU)) mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN, diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h index 241f1b0b77f9..fcea1f68792f 100644 --- a/drivers/net/wireless/mwifiex/wmm.h +++ b/drivers/net/wireless/mwifiex/wmm.h @@ -35,8 +35,7 @@ enum ieee_types_wmm_ecw_bitmasks { * This function retrieves the TID of the given RA list. */ static inline int -mwifiex_get_tid(struct mwifiex_adapter *adapter, - struct mwifiex_ra_list_tbl *ptr) +mwifiex_get_tid(struct mwifiex_ra_list_tbl *ptr) { struct sk_buff *skb; @@ -52,7 +51,7 @@ mwifiex_get_tid(struct mwifiex_adapter *adapter, * This function gets the length of a list. */ static inline int -mwifiex_wmm_list_len(struct mwifiex_adapter *adapter, struct list_head *head) +mwifiex_wmm_list_len(struct list_head *head) { struct list_head *pos; int count = 0; @@ -67,8 +66,7 @@ mwifiex_wmm_list_len(struct mwifiex_adapter *adapter, struct list_head *head) * This function checks if a RA list is empty or not. */ static inline u8 -mwifiex_wmm_is_ra_list_empty(struct mwifiex_adapter *adapter, - struct list_head *ra_list_hhead) +mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead) { struct mwifiex_ra_list_tbl *ra_list; int is_list_empty; -- cgit v1.2.3-58-ga151 From 53d7938e6a2ac6569476fc59b404e70c0537b42b Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Wed, 13 Apr 2011 17:27:09 -0700 Subject: mwifiex: rename function mwifiex_is_ba_stream_avail The old function name sounds like checking for existing BA stream. The function actually checks if we have room for creating new BA stream or not. Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n.h | 5 +++-- drivers/net/wireless/mwifiex/wmm.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 9128d2c9638b..02602ff30cbf 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h @@ -92,9 +92,10 @@ mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, int tid) } /* - * This function checks whether a BA stream is available or not. + * This function checks whether a space is available for new BA stream or not. */ -static inline u8 mwifiex_is_ba_stream_avail(struct mwifiex_adapter *adapter) +static inline u8 mwifiex_space_avail_for_new_ba_stream( + struct mwifiex_adapter *adapter) { struct mwifiex_private *priv; u8 i; diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 57b98c59235d..99e8431c1e93 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -1186,7 +1186,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) mwifiex_send_single_packet() */ } else { if (mwifiex_is_ampdu_allowed(priv, tid)) { - if (mwifiex_is_ba_stream_avail(adapter)) { + if (mwifiex_space_avail_for_new_ba_stream(adapter)) { mwifiex_11n_create_tx_ba_stream_tbl(priv, ptr->ra, tid, BA_STREAM_SETUP_INPROGRESS); -- cgit v1.2.3-58-ga151 From 9f219bd248d417c2144eedafdf2c683ba8baee84 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 13 Apr 2011 21:00:02 -0500 Subject: rtlwifi: Fix unitialized variable warnings In http://lkml.indiana.edu/hypermail/linux/kernel/1104.1/01955.html, Geerti Uytterhoeven reports the following warnings for the rtlwifi drivers. src/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c: warning: 'cck_index' may be used uninitialized in this function: => 637 src/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c: warning: 'cck_index_old' may be used uninitialized in this function: => 637 src/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c: warning: 'box_extreg' may be used uninitialized in this function: => 303 src/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c: warning: 'box_reg' may be used uninitialized in this function: => 303 src/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c: warning: 'chnlgroup' may be used uninitialized in this function: => 205 src/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c: warning: 'u4_regvalue' may be used uninitialized in this function: => 450 src/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c: warning: 'hq_sele' may be used uninitialized in this function: => 924 Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192ce/rf.c | 4 ++-- drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index bb023274414c..c228b9ee3711 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -634,7 +634,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw u8 thermalvalue, delta, delta_lck, delta_iqk; long ele_a, ele_d, temp_cck, val_x, value32; long val_y, ele_c; - u8 ofdm_index[2], cck_index, ofdm_index_old[2], cck_index_old; + u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0; int i; bool is2t = IS_92C_SERIAL(rtlhal->version); u8 txpwr_level[2] = {0, 0}; diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index f107660f545d..bc9d24134ac4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c @@ -293,7 +293,7 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u8 boxnum; - u16 box_reg, box_extreg; + u16 box_reg = 0, box_extreg = 0; u8 u1b_tmp; bool isfw_read = false; bool bwrite_sucess = false; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c index 669b1168dbec..e301b12e281a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c @@ -202,7 +202,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 i, chnlgroup, pwr_diff_limit[4]; + u8 i, chnlgroup = 0, pwr_diff_limit[4]; u32 writeVal, customer_limit, rf; for (rf = 0; rf < 2; rf++) { @@ -447,7 +447,7 @@ static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 u4_regvalue; + u32 u4_regvalue = 0; u8 rfpath; bool rtstatus; struct bb_reg_def *pphyreg; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 9444e76838cf..e43be2547827 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -921,7 +921,7 @@ static void _rtl92cu_init_chipT_queue_priority(struct ieee80211_hw *hw, u8 out_ep_num, u8 queue_sel) { - u8 hq_sele; + u8 hq_sele = 0; struct rtl_priv *rtlpriv = rtl_priv(hw); switch (out_ep_num) { -- cgit v1.2.3-58-ga151 From 34a0a2025c8bddc6505b56a58ef2e7333a4e4165 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Thu, 14 Apr 2011 16:41:30 +0530 Subject: ath: Add a missing world regulatory domain 0x6C Some customers use 0x6C world regulatory domain and this patch adds the support. Cc: Luis R. Rodriguez Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 7 ++++--- drivers/net/wireless/ath/regd_common.h | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index f828f294ba89..7e3b29015dda 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -97,8 +97,8 @@ static const struct ieee80211_regdomain ath_world_regdom_66_69 = { } }; -/* Can be used by 0x67, 0x6A and 0x68 */ -static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = { +/* Can be used by 0x67, 0x68, 0x6A and 0x6C */ +static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = { .n_reg_rules = 4, .alpha2 = "99", .reg_rules = { @@ -151,7 +151,8 @@ ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg) case 0x67: case 0x68: case 0x6A: - return &ath_world_regdom_67_68_6A; + case 0x6C: + return &ath_world_regdom_67_68_6A_6C; default: WARN_ON(1); return ath_default_world_regdomain(); diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h index 5c2cfe694152..24b53839fc3a 100644 --- a/drivers/net/wireless/ath/regd_common.h +++ b/drivers/net/wireless/ath/regd_common.h @@ -86,6 +86,7 @@ enum EnumRd { WOR9_WORLD = 0x69, WORA_WORLD = 0x6A, WORB_WORLD = 0x6B, + WORC_WORLD = 0x6C, MKK3_MKKB = 0x80, MKK3_MKKA2 = 0x81, @@ -282,6 +283,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { {WOR9_WORLD, NO_CTL, NO_CTL}, {WORA_WORLD, NO_CTL, NO_CTL}, {WORB_WORLD, NO_CTL, NO_CTL}, + {WORC_WORLD, NO_CTL, NO_CTL}, }; static struct country_code_to_enum_rd allCountries[] = { -- cgit v1.2.3-58-ga151 From 62f3a2cfb1891c070631e496eeea852e949ea8bb Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Thu, 14 Apr 2011 18:34:34 -0300 Subject: Bluetooth: Fix another locking unbalance l2cap_get_sock_by_scid was changed to not lock the socket anymore, but I forgot to change all the users of this function. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index d5db5a38df6a..bc84ed1b3320 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -632,6 +632,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) if (!parent) return; + bh_lock_sock(parent); + /* Check for backlog size */ if (sk_acceptq_is_full(parent)) { BT_DBG("backlog full %d", parent->sk_ack_backlog); -- cgit v1.2.3-58-ga151 From 26954c7f26068b6ced108806fdd39aee5cd54e6f Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Thu, 14 Apr 2011 17:57:26 -0300 Subject: Bluetooth: Fix lockdep warning in L2CAP Fix a regression from the L2CAP "rewrite" patches. Purge the tx_q already happens on l2cap_chan_del() so we don't need it at l2cap_disconnect_req(). Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index bc84ed1b3320..d47de2b04b2e 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -477,8 +477,6 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in sk = chan->sk; - skb_queue_purge(&chan->tx_q); - if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { del_timer(&chan->retrans_timer); del_timer(&chan->monitor_timer); -- cgit v1.2.3-58-ga151 From 21d8c49e01a0c1c6eb6c750cd04110db4a539284 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 14 Apr 2011 14:49:37 -0700 Subject: ipv4: Call fib_select_default() only when actually necessary. fib_select_default() is a complete NOP, and completely pointless to invoke, when we have no more than 1 default route installed. And this is far and away the common case. So remember how many prefixlen==0 routes we have in the routing table, and elide the call when we have no more than one of those. This cuts output route creation time by 157 cycles on Niagara2+. In order to add the new int to fib_table, we have to correct the type of ->tb_data[] to unsigned long, otherwise the private area will be unaligned on 64-bit systems. Signed-off-by: David S. Miller Reviewed-by: Eric Dumazet --- include/net/ip_fib.h | 3 ++- net/ipv4/fib_trie.c | 7 +++++++ net/ipv4/route.c | 4 +++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 514627f56339..10422ef14e28 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -160,7 +160,8 @@ struct fib_table { struct hlist_node tb_hlist; u32 tb_id; int tb_default; - unsigned char tb_data[0]; + int tb_num_default; + unsigned long tb_data[0]; }; extern int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index bde80c450b52..9ac481a10d37 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -1332,6 +1332,9 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) } } + if (!plen) + tb->tb_num_default++; + list_add_tail_rcu(&new_fa->fa_list, (fa ? &fa->fa_list : fa_head)); @@ -1697,6 +1700,9 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) list_del_rcu(&fa->fa_list); + if (!plen) + tb->tb_num_default--; + if (list_empty(fa_head)) { hlist_del_rcu(&li->hlist); free_leaf_info(li); @@ -1987,6 +1993,7 @@ struct fib_table *fib_trie_table(u32 id) tb->tb_id = id; tb->tb_default = -1; + tb->tb_num_default = 0; t = (struct trie *) tb->tb_data; memset(t, 0, sizeof(*t)); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 0e7430c327a7..e9aee81de3e3 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2615,7 +2615,9 @@ static struct rtable *ip_route_output_slow(struct net *net, fib_select_multipath(&res); else #endif - if (!res.prefixlen && res.type == RTN_UNICAST && !fl4.flowi4_oif) + if (!res.prefixlen && + res.table->tb_num_default > 1 && + res.type == RTN_UNICAST && !fl4.flowi4_oif) fib_select_default(&res); if (!fl4.saddr) -- cgit v1.2.3-58-ga151 From fce55922f5299a04c0a56b170a141fab34f13465 Mon Sep 17 00:00:00 2001 From: "Allan, Bruce W" Date: Wed, 13 Apr 2011 13:09:10 +0000 Subject: ethtool: allow custom interval for physical identification When physical identification of an adapter is done by toggling the mechanism on and off through software utilizing the set_phys_id operation, it is done with a fixed duration for both on and off states. Some drivers may want to set a custom duration for the on/off intervals. This patch changes the API so the return code from the driver's entry point when it is called with ETHTOOL_ID_ACTIVE can specify the frequency at which to cycle the on/off states, and updates the drivers that have already been converted to use the new set_phys_id and use the synchronous method for identifying an adapter. The physical identification frequency set in the updated drivers is based on how it was done prior to the introduction of set_phys_id. Compile tested only. Also fixes a compiler warning in sfc. v2: drivers do not return -EINVAL for ETHOOL_ID_ACTIVE v3: fold patchset into single patch and cleanup per Ben's feedback Signed-off-by: Bruce Allan Cc: Ben Hutchings Cc: Sathya Perla Cc: Subbu Seetharaman Cc: Ajit Khaparde Cc: Michael Chan Cc: Eilon Greenstein Cc: Divy Le Ray Cc: Don Fry Cc: Jon Mason Cc: Solarflare linux maintainers Cc: Steve Hodgson Cc: Stephen Hemminger Cc: Matt Carlson Acked-by: Jon Mason Acked-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/benet/be_ethtool.c | 2 +- drivers/net/bnx2.c | 2 +- drivers/net/bnx2x/bnx2x_ethtool.c | 2 +- drivers/net/cxgb3/cxgb3_main.c | 2 +- drivers/net/ewrk3.c | 2 +- drivers/net/niu.c | 2 +- drivers/net/pcnet32.c | 2 +- drivers/net/s2io.c | 2 +- drivers/net/sfc/ethtool.c | 6 +++--- drivers/net/skge.c | 2 +- drivers/net/sky2.c | 2 +- drivers/net/tg3.c | 2 +- include/linux/ethtool.h | 6 ++++-- net/core/ethtool.c | 31 ++++++++++++++++--------------- 14 files changed, 34 insertions(+), 31 deletions(-) diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 96f5502e0ef7..80226e4801f3 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -516,7 +516,7 @@ be_set_phys_id(struct net_device *netdev, case ETHTOOL_ID_ACTIVE: be_cmd_get_beacon_state(adapter, adapter->hba_port_num, &adapter->beacon_state); - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 0a52079bafef..bf729ee6acbd 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7473,7 +7473,7 @@ bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state) bp->leds_save = REG_RD(bp, BNX2_MISC_CFG); REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC); - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE | diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index ad7d91e499f4..0a5e88d6ba2c 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c @@ -2025,7 +2025,7 @@ static int bnx2x_set_phys_id(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: bnx2x_set_led(&bp->link_params, &bp->link_vars, diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 802c7a7c3b25..a087e0691dce 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1757,7 +1757,7 @@ static int set_phys_id(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_OFF: t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, 0); diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index c7ce4438e923..17b6027d8be8 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -1618,7 +1618,7 @@ static int ewrk3_set_phys_id(struct net_device *dev, /* Prevent ISR from twiddling the LED */ lp->led_mask = 0; spin_unlock_irq(&lp->hw_lock); - return -EINVAL; + return 2; /* cycle on/off twice per second */ case ETHTOOL_ID_ON: cr = inb(EWRK3_CR); diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 3fa1e9cdb4a8..ea2272f0f37e 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -7896,7 +7896,7 @@ static int niu_set_phys_id(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: np->orig_led_state = niu_led_state_save(np); - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: niu_force_led(np, 1); diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index e89afb929740..0a1efbae1bc0 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1038,7 +1038,7 @@ static int pcnet32_set_phys_id(struct net_device *dev, for (i = 4; i < 8; i++) lp->save_regs[i - 4] = a->read_bcr(ioaddr, i); spin_unlock_irqrestore(&lp->lock, flags); - return -EINVAL; + return 2; /* cycle on/off twice per second */ case ETHTOOL_ID_ON: case ETHTOOL_ID_OFF: diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 2d5cc6142c04..2302d9743744 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -5541,7 +5541,7 @@ static int s2io_ethtool_set_led(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: sp->adapt_ctrl_org = readq(&bar0->gpio_control); - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: s2io_set_led(sp, true); diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 644f7c1d6e7b..5d8468fc5804 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -182,7 +182,7 @@ static int efx_ethtool_phys_id(struct net_device *net_dev, enum ethtool_phys_id_state state) { struct efx_nic *efx = netdev_priv(net_dev); - enum efx_led_mode mode; + enum efx_led_mode mode = EFX_LED_DEFAULT; switch (state) { case ETHTOOL_ID_ON: @@ -194,8 +194,8 @@ static int efx_ethtool_phys_id(struct net_device *net_dev, case ETHTOOL_ID_INACTIVE: mode = EFX_LED_DEFAULT; break; - default: - return -EINVAL; + case ETHTOOL_ID_ACTIVE: + return 1; /* cycle on/off once per second */ } efx->type->set_id_led(efx, mode); diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 310dcbce2519..176d784cbb54 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -753,7 +753,7 @@ static int skge_set_phys_id(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: - return -EINVAL; + return 2; /* cycle on/off twice per second */ case ETHTOOL_ID_ON: skge_led(skge, LED_MODE_TST); diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index a4b8fe564eb0..c8d045114c66 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3813,7 +3813,7 @@ static int sky2_set_phys_id(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_INACTIVE: sky2_led(sky2, MO_LED_NORM); break; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 10fa476fede3..9915734ac3e9 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10384,7 +10384,7 @@ static int tg3_set_phys_id(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE | diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index ad22a68c2e5d..9de31274341d 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -798,8 +798,10 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * attached to it. The implementation may update the indicator * asynchronously or synchronously, but in either case it must return * quickly. It is initially called with the argument %ETHTOOL_ID_ACTIVE, - * and must either activate asynchronous updates or return -%EINVAL. - * If it returns -%EINVAL then it will be called again at intervals with + * and must either activate asynchronous updates and return zero, return + * a negative error or return a positive frequency for synchronous + * indication (e.g. 1 for one on/off cycle per second). If it returns + * a frequency then it will be called again at intervals with the * argument %ETHTOOL_ID_ON or %ETHTOOL_ID_OFF and should set the state of * the indicator accordingly. Finally, it is called with the argument * %ETHTOOL_ID_INACTIVE and must deactivate the indicator. Returns a diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 41dee2de13ad..13d79f5a86e5 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1669,7 +1669,7 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) return dev->ethtool_ops->phys_id(dev, id.data); rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ACTIVE); - if (rc && rc != -EINVAL) + if (rc < 0) return rc; /* Drop the RTNL lock while waiting, but prevent reentry or @@ -1684,21 +1684,22 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) schedule_timeout_interruptible( id.data ? (id.data * HZ) : MAX_SCHEDULE_TIMEOUT); } else { - /* Driver expects to be called periodically */ + /* Driver expects to be called at twice the frequency in rc */ + int n = rc * 2, i, interval = HZ / n; + + /* Count down seconds */ do { - rtnl_lock(); - rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ON); - rtnl_unlock(); - if (rc) - break; - schedule_timeout_interruptible(HZ / 2); - - rtnl_lock(); - rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_OFF); - rtnl_unlock(); - if (rc) - break; - schedule_timeout_interruptible(HZ / 2); + /* Count down iterations per second */ + i = n; + do { + rtnl_lock(); + rc = dev->ethtool_ops->set_phys_id(dev, + (i & 1) ? ETHTOOL_ID_OFF : ETHTOOL_ID_ON); + rtnl_unlock(); + if (rc) + break; + schedule_timeout_interruptible(interval); + } while (!signal_pending(current) && --i != 0); } while (!signal_pending(current) && (id.data == 0 || --id.data != 0)); } -- cgit v1.2.3-58-ga151 From 44f4d5a27ee63ec80d498e0d0673605d5ce1427d Mon Sep 17 00:00:00 2001 From: Rémi Denis-Courmont Date: Tue, 12 Apr 2011 23:27:36 +0000 Subject: Phonet: convert bound sockets hash list to RCU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This gets rid of the last spinlock in the Phonet stack proper. Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- net/phonet/socket.c | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/net/phonet/socket.c b/net/phonet/socket.c index b1adafab377c..8c5bfcef92cb 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -52,7 +52,7 @@ static int pn_socket_release(struct socket *sock) static struct { struct hlist_head hlist[PN_HASHSIZE]; - spinlock_t lock; + struct mutex lock; } pnsocks; void __init pn_sock_init(void) @@ -61,7 +61,7 @@ void __init pn_sock_init(void) for (i = 0; i < PN_HASHSIZE; i++) INIT_HLIST_HEAD(pnsocks.hlist + i); - spin_lock_init(&pnsocks.lock); + mutex_init(&pnsocks.lock); } static struct hlist_head *pn_hash_list(u16 obj) @@ -82,9 +82,8 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn) u8 res = spn->spn_resource; struct hlist_head *hlist = pn_hash_list(obj); - spin_lock_bh(&pnsocks.lock); - - sk_for_each(sknode, node, hlist) { + rcu_read_lock(); + sk_for_each_rcu(sknode, node, hlist) { struct pn_sock *pn = pn_sk(sknode); BUG_ON(!pn->sobject); /* unbound socket */ @@ -107,8 +106,7 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn) sock_hold(sknode); break; } - - spin_unlock_bh(&pnsocks.lock); + rcu_read_unlock(); return rval; } @@ -119,7 +117,7 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb) struct hlist_head *hlist = pnsocks.hlist; unsigned h; - spin_lock(&pnsocks.lock); + rcu_read_lock(); for (h = 0; h < PN_HASHSIZE; h++) { struct hlist_node *node; struct sock *sknode; @@ -140,25 +138,26 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb) } hlist++; } - spin_unlock(&pnsocks.lock); + rcu_read_unlock(); } void pn_sock_hash(struct sock *sk) { struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject); - spin_lock_bh(&pnsocks.lock); - sk_add_node(sk, hlist); - spin_unlock_bh(&pnsocks.lock); + mutex_lock(&pnsocks.lock); + sk_add_node_rcu(sk, hlist); + mutex_unlock(&pnsocks.lock); } EXPORT_SYMBOL(pn_sock_hash); void pn_sock_unhash(struct sock *sk) { - spin_lock_bh(&pnsocks.lock); - sk_del_node_init(sk); - spin_unlock_bh(&pnsocks.lock); + mutex_lock(&pnsocks.lock); + sk_del_node_init_rcu(sk); + mutex_unlock(&pnsocks.lock); pn_sock_unbind_all_res(sk); + synchronize_rcu(); } EXPORT_SYMBOL(pn_sock_unhash); @@ -548,7 +547,7 @@ static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos) unsigned h; for (h = 0; h < PN_HASHSIZE; h++) { - sk_for_each(sknode, node, hlist) { + sk_for_each_rcu(sknode, node, hlist) { if (!net_eq(net, sock_net(sknode))) continue; if (!pos) @@ -572,9 +571,9 @@ static struct sock *pn_sock_get_next(struct seq_file *seq, struct sock *sk) } static void *pn_sock_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(pnsocks.lock) + __acquires(rcu) { - spin_lock_bh(&pnsocks.lock); + rcu_read_lock(); return *pos ? pn_sock_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } @@ -591,9 +590,9 @@ static void *pn_sock_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void pn_sock_seq_stop(struct seq_file *seq, void *v) - __releases(pnsocks.lock) + __releases(rcu) { - spin_unlock_bh(&pnsocks.lock); + rcu_read_unlock(); } static int pn_sock_seq_show(struct seq_file *seq, void *v) @@ -721,13 +720,11 @@ void pn_sock_unbind_all_res(struct sock *sk) } mutex_unlock(&resource_mutex); - if (match == 0) - return; - synchronize_rcu(); while (match > 0) { - sock_put(sk); + __sock_put(sk); match--; } + /* Caller is responsible for RCU sync before final sock_put() */ } #ifdef CONFIG_PROC_FS -- cgit v1.2.3-58-ga151 From 6c8c2513c86c589a819c161c9abbdea2a3d56f5e Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Thu, 14 Apr 2011 05:50:12 +0000 Subject: sfc: make function tables const The phy, mac, and board information structures should be const. Since tables contain function pointer this improves security (at least theoretically). Compile tested only. Signed-off-by: Stephen Hemminger Acked-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/efx.c | 6 +++--- drivers/net/sfc/falcon.c | 4 ++-- drivers/net/sfc/falcon_xmac.c | 2 +- drivers/net/sfc/mac.h | 4 ++-- drivers/net/sfc/mcdi_mac.c | 2 +- drivers/net/sfc/mcdi_phy.c | 2 +- drivers/net/sfc/net_driver.h | 6 +++--- drivers/net/sfc/nic.h | 6 +++--- drivers/net/sfc/phy.h | 8 ++++---- drivers/net/sfc/qt202x_phy.c | 2 +- drivers/net/sfc/siena.c | 2 +- drivers/net/sfc/tenxpress.c | 2 +- drivers/net/sfc/txc43128_phy.c | 2 +- 13 files changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index db72a6e054e1..c8871b2db38c 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -2245,7 +2245,7 @@ static bool efx_port_dummy_op_poll(struct efx_nic *efx) return false; } -static struct efx_phy_operations efx_dummy_phy_operations = { +static const struct efx_phy_operations efx_dummy_phy_operations = { .init = efx_port_dummy_op_int, .reconfigure = efx_port_dummy_op_int, .poll = efx_port_dummy_op_poll, @@ -2261,7 +2261,7 @@ static struct efx_phy_operations efx_dummy_phy_operations = { /* This zeroes out and then fills in the invariants in a struct * efx_nic (including all sub-structures). */ -static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, +static int efx_init_struct(struct efx_nic *efx, const struct efx_nic_type *type, struct pci_dev *pci_dev, struct net_device *net_dev) { int i; @@ -2451,7 +2451,7 @@ static int efx_pci_probe_main(struct efx_nic *efx) static int __devinit efx_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *entry) { - struct efx_nic_type *type = (struct efx_nic_type *) entry->driver_data; + const struct efx_nic_type *type = (const struct efx_nic_type *) entry->driver_data; struct net_device *net_dev; struct efx_nic *efx; int i, rc; diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index d96b23769bd1..60176e873d62 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1703,7 +1703,7 @@ static int falcon_set_wol(struct efx_nic *efx, u32 type) ************************************************************************** */ -struct efx_nic_type falcon_a1_nic_type = { +const struct efx_nic_type falcon_a1_nic_type = { .probe = falcon_probe_nic, .remove = falcon_remove_nic, .init = falcon_init_nic, @@ -1744,7 +1744,7 @@ struct efx_nic_type falcon_a1_nic_type = { .reset_world_flags = ETH_RESET_IRQ, }; -struct efx_nic_type falcon_b0_nic_type = { +const struct efx_nic_type falcon_b0_nic_type = { .probe = falcon_probe_nic, .remove = falcon_remove_nic, .init = falcon_init_nic, diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index 2c9ee5db3bf7..9516452c079c 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c @@ -362,7 +362,7 @@ void falcon_poll_xmac(struct efx_nic *efx) falcon_ack_status_intr(efx); } -struct efx_mac_operations falcon_xmac_operations = { +const struct efx_mac_operations falcon_xmac_operations = { .reconfigure = falcon_reconfigure_xmac, .update_stats = falcon_update_stats_xmac, .check_fault = falcon_xmac_check_fault, diff --git a/drivers/net/sfc/mac.h b/drivers/net/sfc/mac.h index 6886cdf87c12..d6a255d0856b 100644 --- a/drivers/net/sfc/mac.h +++ b/drivers/net/sfc/mac.h @@ -13,8 +13,8 @@ #include "net_driver.h" -extern struct efx_mac_operations falcon_xmac_operations; -extern struct efx_mac_operations efx_mcdi_mac_operations; +extern const struct efx_mac_operations falcon_xmac_operations; +extern const struct efx_mac_operations efx_mcdi_mac_operations; extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, u32 dma_len, int enable, int clear); diff --git a/drivers/net/sfc/mcdi_mac.c b/drivers/net/sfc/mcdi_mac.c index 33f7294edb47..50c20777a564 100644 --- a/drivers/net/sfc/mcdi_mac.c +++ b/drivers/net/sfc/mcdi_mac.c @@ -138,7 +138,7 @@ static bool efx_mcdi_mac_check_fault(struct efx_nic *efx) } -struct efx_mac_operations efx_mcdi_mac_operations = { +const struct efx_mac_operations efx_mcdi_mac_operations = { .reconfigure = efx_mcdi_mac_reconfigure, .update_stats = efx_port_dummy_op_void, .check_fault = efx_mcdi_mac_check_fault, diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c index 7e3c65b0c99f..1fcda2d82399 100644 --- a/drivers/net/sfc/mcdi_phy.c +++ b/drivers/net/sfc/mcdi_phy.c @@ -739,7 +739,7 @@ static const char *efx_mcdi_phy_test_name(struct efx_nic *efx, return NULL; } -struct efx_phy_operations efx_mcdi_phy_ops = { +const struct efx_phy_operations efx_mcdi_phy_ops = { .probe = efx_mcdi_phy_probe, .init = efx_port_dummy_op_int, .reconfigure = efx_mcdi_phy_reconfigure, diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 92a9067e8e77..ab4d05b84eb7 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -773,10 +773,10 @@ struct efx_nic { struct efx_buffer stats_buffer; - struct efx_mac_operations *mac_op; + const struct efx_mac_operations *mac_op; unsigned int phy_type; - struct efx_phy_operations *phy_op; + const struct efx_phy_operations *phy_op; void *phy_data; struct mdio_if_info mdio; unsigned int mdio_bus; @@ -897,7 +897,7 @@ struct efx_nic_type { void (*resume_wol)(struct efx_nic *efx); int (*test_registers)(struct efx_nic *efx); int (*test_nvram)(struct efx_nic *efx); - struct efx_mac_operations *default_mac_ops; + const struct efx_mac_operations *default_mac_ops; int revision; unsigned int mem_map_size; diff --git a/drivers/net/sfc/nic.h b/drivers/net/sfc/nic.h index d9de1b647d41..f7ec03cc002d 100644 --- a/drivers/net/sfc/nic.h +++ b/drivers/net/sfc/nic.h @@ -150,9 +150,9 @@ struct siena_nic_data { int wol_filter_id; }; -extern struct efx_nic_type falcon_a1_nic_type; -extern struct efx_nic_type falcon_b0_nic_type; -extern struct efx_nic_type siena_a0_nic_type; +extern const struct efx_nic_type falcon_a1_nic_type; +extern const struct efx_nic_type falcon_b0_nic_type; +extern const struct efx_nic_type siena_a0_nic_type; /************************************************************************** * diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h index b3b79472421e..11d148cd8441 100644 --- a/drivers/net/sfc/phy.h +++ b/drivers/net/sfc/phy.h @@ -13,14 +13,14 @@ /**************************************************************************** * 10Xpress (SFX7101) PHY */ -extern struct efx_phy_operations falcon_sfx7101_phy_ops; +extern const struct efx_phy_operations falcon_sfx7101_phy_ops; extern void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode); /**************************************************************************** * AMCC/Quake QT202x PHYs */ -extern struct efx_phy_operations falcon_qt202x_phy_ops; +extern const struct efx_phy_operations falcon_qt202x_phy_ops; /* These PHYs provide various H/W control states for LEDs */ #define QUAKE_LED_LINK_INVAL (0) @@ -39,7 +39,7 @@ extern void falcon_qt202x_set_led(struct efx_nic *p, int led, int state); /**************************************************************************** * Transwitch CX4 retimer */ -extern struct efx_phy_operations falcon_txc_phy_ops; +extern const struct efx_phy_operations falcon_txc_phy_ops; #define TXC_GPIO_DIR_INPUT 0 #define TXC_GPIO_DIR_OUTPUT 1 @@ -50,7 +50,7 @@ extern void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int val); /**************************************************************************** * Siena managed PHYs */ -extern struct efx_phy_operations efx_mcdi_phy_ops; +extern const struct efx_phy_operations efx_mcdi_phy_ops; extern int efx_mcdi_mdio_read(struct efx_nic *efx, unsigned int bus, unsigned int prtad, unsigned int devad, diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c index 55f90924247e..7ad97e397406 100644 --- a/drivers/net/sfc/qt202x_phy.c +++ b/drivers/net/sfc/qt202x_phy.c @@ -449,7 +449,7 @@ static void qt202x_phy_remove(struct efx_nic *efx) efx->phy_data = NULL; } -struct efx_phy_operations falcon_qt202x_phy_ops = { +const struct efx_phy_operations falcon_qt202x_phy_ops = { .probe = qt202x_phy_probe, .init = qt202x_phy_init, .reconfigure = qt202x_phy_reconfigure, diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index e4dd8986b1fe..ceac1c9907f0 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c @@ -581,7 +581,7 @@ static void siena_init_wol(struct efx_nic *efx) ************************************************************************** */ -struct efx_nic_type siena_a0_nic_type = { +const struct efx_nic_type siena_a0_nic_type = { .probe = siena_probe_nic, .remove = siena_remove_nic, .init = siena_init_nic, diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index efdceb35aaae..204ecdaac9ab 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -478,7 +478,7 @@ static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising) advertising & ADVERTISED_10000baseT_Full); } -struct efx_phy_operations falcon_sfx7101_phy_ops = { +const struct efx_phy_operations falcon_sfx7101_phy_ops = { .probe = tenxpress_phy_probe, .init = tenxpress_phy_init, .reconfigure = tenxpress_phy_reconfigure, diff --git a/drivers/net/sfc/txc43128_phy.c b/drivers/net/sfc/txc43128_phy.c index d9886addcc99..7c21b334a75b 100644 --- a/drivers/net/sfc/txc43128_phy.c +++ b/drivers/net/sfc/txc43128_phy.c @@ -545,7 +545,7 @@ static void txc43128_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) mdio45_ethtool_gset(&efx->mdio, ecmd); } -struct efx_phy_operations falcon_txc_phy_ops = { +const struct efx_phy_operations falcon_txc_phy_ops = { .probe = txc43128_phy_probe, .init = txc43128_phy_init, .reconfigure = txc43128_phy_reconfigure, -- cgit v1.2.3-58-ga151 From ef9c7ab4a97d53d9cb4912d13e142f52a30ecd54 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Thu, 14 Apr 2011 05:51:52 +0000 Subject: qlge: make nic_operations struct const The struct nic_operations is just function pointers and should be declared const for added security. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 2 +- drivers/net/qlge/qlge_main.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 4757c59a07a2..d32850715f5c 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -2134,7 +2134,7 @@ struct ql_adapter { struct delayed_work mpi_idc_work; struct delayed_work mpi_core_to_log; struct completion ide_completion; - struct nic_operations *nic_ops; + const struct nic_operations *nic_ops; u16 device_id; struct timer_list timer; atomic_t lb_count; diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 5bb311945436..f61e717adac4 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -4412,12 +4412,12 @@ error: rtnl_unlock(); } -static struct nic_operations qla8012_nic_ops = { +static const struct nic_operations qla8012_nic_ops = { .get_flash = ql_get_8012_flash_params, .port_initialize = ql_8012_port_initialize, }; -static struct nic_operations qla8000_nic_ops = { +static const struct nic_operations qla8000_nic_ops = { .get_flash = ql_get_8000_flash_params, .port_initialize = ql_8000_port_initialize, }; -- cgit v1.2.3-58-ga151 From d30ee670f25ea8f265a2804e2a0a53804cac5185 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 13 Apr 2011 15:22:29 +0000 Subject: net-bonding: Fix minor sparse complaints This gets rid of minor sparse complaints: drivers/net/bonding/bond_main.c:4361:4: warning: do-while statement is not a compound statement drivers/net/bonding/bond_main.c:243:12: warning: symbol 'bond_mode_name' was not declared. Should it be static? Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 4 ++-- drivers/net/bonding/bond_procfs.c | 2 -- drivers/net/bonding/bonding.h | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b51e021354b5..94a371c12d70 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4357,9 +4357,9 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) u16 txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0; if (unlikely(txq >= dev->real_num_tx_queues)) { - do + do { txq -= dev->real_num_tx_queues; - while (txq >= dev->real_num_tx_queues); + } while (txq >= dev->real_num_tx_queues); } return txq; } diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c index c32ff55a34c1..c97307ddd1c9 100644 --- a/drivers/net/bonding/bond_procfs.c +++ b/drivers/net/bonding/bond_procfs.c @@ -4,8 +4,6 @@ #include "bonding.h" -extern const char *bond_mode_name(int mode); - static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos) __acquires(RCU) __acquires(&bond->lock) diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 90736cb4d975..3ca503e50718 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -416,6 +416,7 @@ void bond_destroy_debugfs(void); void bond_debug_register(struct bonding *bond); void bond_debug_unregister(struct bonding *bond); void bond_debug_reregister(struct bonding *bond); +const char *bond_mode_name(int mode); struct bond_net { struct net * net; /* Associated network namespace */ -- cgit v1.2.3-58-ga151 From 65cce19c07756c2b2b51595c967dda93b0727027 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 13 Apr 2011 15:22:30 +0000 Subject: net-bonding: Fix minor/cosmetic type inconsistencies The __get_link_speed() function returns a u16 value which was stored in a u32 local variable. This patch uses the return value directly, thus fixing that minor type consistency. The 'duplex' field in struct slave being encoded on 8 bits, to be more consistent we use a u8 integer (instead of u16) whenever we copy it to local variables. Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 4 +--- drivers/net/bonding/bond_main.c | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 494bf960442d..123dd602261f 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -716,11 +716,9 @@ static void __set_agg_ports_ready(struct aggregator *aggregator, int val) static u32 __get_agg_bandwidth(struct aggregator *aggregator) { u32 bandwidth = 0; - u32 basic_speed; if (aggregator->num_of_ports) { - basic_speed = __get_link_speed(aggregator->lag_ports); - switch (basic_speed) { + switch (__get_link_speed(aggregator->lag_ports)) { case AD_LINK_SPEED_BITMASK_1MBPS: bandwidth = aggregator->num_of_ports; break; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 94a371c12d70..4df674bc6f12 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3340,7 +3340,7 @@ static int bond_slave_netdev_event(unsigned long event, slave = bond_get_slave_by_dev(bond, slave_dev); if (slave) { u16 old_speed = slave->speed; - u16 old_duplex = slave->duplex; + u8 old_duplex = slave->duplex; bond_update_speed_duplex(slave); -- cgit v1.2.3-58-ga151 From 5d30530efbb811f875786d788ae1c5d79547c3a4 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 13 Apr 2011 15:22:31 +0000 Subject: net-bonding: Adding support for throughputs larger than 65536 Mbps This updates the bonding driver to support v2.6.27-rc3 enhancements (b11f8d8c aka. "ethtool: Expand ethtool_cmd.speed to 32 bits") which allow to encode the Mbps link speed on 32-bits (Max 4 Pbps) instead of 16 (Max 65536 Mbps). This patch also attempts to compact struct slave by reordering its fields. Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 12 +++++++----- drivers/net/bonding/bonding.h | 6 +++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 4df674bc6f12..ca902ae3f2e5 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -631,7 +631,8 @@ down: static int bond_update_speed_duplex(struct slave *slave) { struct net_device *slave_dev = slave->dev; - struct ethtool_cmd etool; + struct ethtool_cmd etool = { .cmd = ETHTOOL_GSET }; + u32 slave_speed; int res; /* Fake speed and duplex */ @@ -645,7 +646,8 @@ static int bond_update_speed_duplex(struct slave *slave) if (res < 0) return -1; - switch (etool.speed) { + slave_speed = ethtool_cmd_speed(&etool); + switch (slave_speed) { case SPEED_10: case SPEED_100: case SPEED_1000: @@ -663,7 +665,7 @@ static int bond_update_speed_duplex(struct slave *slave) return -1; } - slave->speed = etool.speed; + slave->speed = slave_speed; slave->duplex = etool.duplex; return 0; @@ -2493,7 +2495,7 @@ static void bond_miimon_commit(struct bonding *bond) bond_update_speed_duplex(slave); - pr_info("%s: link status definitely up for interface %s, %d Mbps %s duplex.\n", + pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n", bond->dev->name, slave->dev->name, slave->speed, slave->duplex ? "full" : "half"); @@ -3339,7 +3341,7 @@ static int bond_slave_netdev_event(unsigned long event, slave = bond_get_slave_by_dev(bond, slave_dev); if (slave) { - u16 old_speed = slave->speed; + u32 old_speed = slave->speed; u8 old_duplex = slave->duplex; bond_update_speed_duplex(slave); diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 3ca503e50718..553c764f7407 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -196,12 +196,12 @@ struct slave { u8 backup:1, /* indicates backup slave. Value corresponds with BOND_STATE_ACTIVE and BOND_STATE_BACKUP */ inactive:1; /* indicates inactive slave */ + u8 duplex; u32 original_mtu; u32 link_failure_count; - u8 perm_hwaddr[ETH_ALEN]; - u16 speed; - u8 duplex; + u32 speed; u16 queue_id; + u8 perm_hwaddr[ETH_ALEN]; struct ad_slave_info ad_info; /* HUGE - better to dynamically alloc */ struct tlb_slave_info tlb_info; #ifdef CONFIG_NET_POLL_CONTROLLER -- cgit v1.2.3-58-ga151 From eb8aa72d4e8756bde74d5f22bdd968ee6131069a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 14 Apr 2011 23:23:45 -0700 Subject: rndis_host: Quirky devices are still 'point-to-point' My changes in commit 4d42d417be75d750b82798922b6e775915e11bce were written some time before the introduction of FLAG_POINTTOPOINT, so didn't include that flag in the new driver_info. Change the new driver_info to be consistent. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/usb/rndis_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 6d6c1da68a36..255d6a424a6b 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -592,7 +592,7 @@ static const struct driver_info rndis_info = { static const struct driver_info rndis_poll_status_info = { .description = "RNDIS device (poll status before control)", - .flags = FLAG_ETHER | FLAG_FRAMING_RN | FLAG_NO_SETINT, + .flags = FLAG_ETHER | FLAG_POINTTOPOINT | FLAG_FRAMING_RN | FLAG_NO_SETINT, .data = RNDIS_DRIVER_DATA_POLL_STATUS, .bind = rndis_bind, .unbind = rndis_unbind, -- cgit v1.2.3-58-ga151 From bd015928bb1713691068c4d0d159afccbaf0f8c0 Mon Sep 17 00:00:00 2001 From: Daniel Walter Date: Wed, 13 Apr 2011 21:09:25 +0000 Subject: ipv6: ignore looped-back NA while dad is running [ipv6] Ignore looped-back NAs while in Duplicate Address Detection If we send an unsolicited NA shortly after bringing up an IPv6 address, the duplicate address detection algorithm fails and the ip stays in tentative mode forever. This is due a missing check if the NA is looped-back to us. Signed-off-by: Daniel Walter Signed-off-by: David S. Miller --- net/ipv6/ndisc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 92f952d093db..f057ff312840 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -945,9 +945,10 @@ static void ndisc_recv_na(struct sk_buff *skb) } ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1); if (ifp) { - if (ifp->flags & IFA_F_TENTATIVE) { - addrconf_dad_failure(ifp); - return; + if (skb->pkt_type != PACKET_LOOPBACK + && (ifp->flags & IFA_F_TENTATIVE)) { + addrconf_dad_failure(ifp); + return; } /* What should we make now? The advertisement is invalid, but ndisc specs say nothing -- cgit v1.2.3-58-ga151 From c3968a857a6b6c3d2ef4ead35776b055fb664d74 Mon Sep 17 00:00:00 2001 From: Daniel Walter Date: Wed, 13 Apr 2011 21:10:57 +0000 Subject: ipv6: RTA_PREFSRC support for ipv6 route source address selection [ipv6] Add support for RTA_PREFSRC This patch allows a user to select the preferred source address for a specific IPv6-Route. It can be set via a netlink message setting RTA_PREFSRC to a valid IPv6 address which must be up on the device the route will be bound to. Signed-off-by: Daniel Walter Signed-off-by: David S. Miller --- include/net/ip6_fib.h | 2 ++ include/net/ip6_route.h | 7 +++++ net/ipv6/addrconf.c | 2 ++ net/ipv6/ip6_output.c | 8 +++--- net/ipv6/route.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 84 insertions(+), 7 deletions(-) diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index bc3cde0a810c..98348d53b2b6 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -42,6 +42,7 @@ struct fib6_config { struct in6_addr fc_dst; struct in6_addr fc_src; + struct in6_addr fc_prefsrc; struct in6_addr fc_gateway; unsigned long fc_expires; @@ -107,6 +108,7 @@ struct rt6_info { struct rt6key rt6i_dst ____cacheline_aligned_in_smp; u32 rt6i_flags; struct rt6key rt6i_src; + struct rt6key rt6i_prefsrc; u32 rt6i_metric; u32 rt6i_peer_genid; diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index c850e5fb967c..86b1cb486903 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -84,6 +84,12 @@ extern int ip6_route_add(struct fib6_config *cfg); extern int ip6_ins_rt(struct rt6_info *); extern int ip6_del_rt(struct rt6_info *); +extern int ip6_route_get_saddr(struct net *net, + struct rt6_info *rt, + struct in6_addr *daddr, + unsigned int prefs, + struct in6_addr *saddr); + extern struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, const struct in6_addr *saddr, @@ -141,6 +147,7 @@ struct rt6_rtnl_dump_arg { extern int rt6_dump_route(struct rt6_info *rt, void *p_arg); extern void rt6_ifdown(struct net *net, struct net_device *dev); extern void rt6_mtu_change(struct net_device *dev, unsigned mtu); +extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp); /* diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 1493534116df..129d7e1f311c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -825,6 +825,8 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) dst_release(&rt->dst); } + /* clean up prefsrc entries */ + rt6_remove_prefsrc(ifp); out: in6_ifa_put(ifp); } diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 46cf7bea6769..c614d02bf429 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -930,10 +930,10 @@ static int ip6_dst_lookup_tail(struct sock *sk, goto out_err_release; if (ipv6_addr_any(&fl6->saddr)) { - err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev, - &fl6->daddr, - sk ? inet6_sk(sk)->srcprefs : 0, - &fl6->saddr); + struct rt6_info *rt = (struct rt6_info *) *dst; + err = ip6_route_get_saddr(net, rt, &fl6->daddr, + sk ? inet6_sk(sk)->srcprefs : 0, + &fl6->saddr); if (err) goto out_err_release; } diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 843406f14d7b..af26cc1073cb 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1325,6 +1325,16 @@ int ip6_route_add(struct fib6_config *cfg) if (dev == NULL) goto out; + if (!ipv6_addr_any(&cfg->fc_prefsrc)) { + if (!ipv6_chk_addr(net, &cfg->fc_prefsrc, dev, 0)) { + err = -EINVAL; + goto out; + } + ipv6_addr_copy(&rt->rt6i_prefsrc.addr, &cfg->fc_prefsrc); + rt->rt6i_prefsrc.plen = 128; + } else + rt->rt6i_prefsrc.plen = 0; + if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev); if (IS_ERR(rt->rt6i_nexthop)) { @@ -2037,6 +2047,55 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, return rt; } +int ip6_route_get_saddr(struct net *net, + struct rt6_info *rt, + struct in6_addr *daddr, + unsigned int prefs, + struct in6_addr *saddr) +{ + struct inet6_dev *idev = ip6_dst_idev((struct dst_entry*)rt); + int err = 0; + if (rt->rt6i_prefsrc.plen) + ipv6_addr_copy(saddr, &rt->rt6i_prefsrc.addr); + else + err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, + daddr, prefs, saddr); + return err; +} + +/* remove deleted ip from prefsrc entries */ +struct arg_dev_net_ip { + struct net_device *dev; + struct net *net; + struct in6_addr *addr; +}; + +static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg) +{ + struct net_device *dev = ((struct arg_dev_net_ip *)arg)->dev; + struct net *net = ((struct arg_dev_net_ip *)arg)->net; + struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr; + + if (((void *)rt->rt6i_dev == dev || dev == NULL) && + rt != net->ipv6.ip6_null_entry && + ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) { + /* remove prefsrc entry */ + rt->rt6i_prefsrc.plen = 0; + } + return 0; +} + +void rt6_remove_prefsrc(struct inet6_ifaddr *ifp) +{ + struct net *net = dev_net(ifp->idev->dev); + struct arg_dev_net_ip adni = { + .dev = ifp->idev->dev, + .net = net, + .addr = &ifp->addr, + }; + fib6_clean_all(net, fib6_remove_prefsrc, 0, &adni); +} + struct arg_dev_net { struct net_device *dev; struct net *net; @@ -2183,6 +2242,9 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen); } + if (tb[RTA_PREFSRC]) + nla_memcpy(&cfg->fc_prefsrc, tb[RTA_PREFSRC], 16); + if (tb[RTA_OIF]) cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]); @@ -2325,13 +2387,17 @@ static int rt6_fill_node(struct net *net, #endif NLA_PUT_U32(skb, RTA_IIF, iif); } else if (dst) { - struct inet6_dev *idev = ip6_dst_idev(&rt->dst); struct in6_addr saddr_buf; - if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, - dst, 0, &saddr_buf) == 0) + if (ip6_route_get_saddr(net, rt, dst, 0, &saddr_buf) == 0) NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); } + if (rt->rt6i_prefsrc.plen) { + struct in6_addr saddr_buf; + ipv6_addr_copy(&saddr_buf, &rt->rt6i_prefsrc.addr); + NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); + } + if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) goto nla_put_failure; -- cgit v1.2.3-58-ga151 From 911cb193f3eb0370f20fbba712211e55ffede4de Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 15 Apr 2011 02:26:25 +0000 Subject: net: minor cleanup to net_namespace.c. Inline a small static function that's only ever called from one place. Signed-off-by: Rob Landley Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- net/core/net_namespace.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 3f860261c5ee..1abb50841046 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -216,11 +216,14 @@ static void net_free(struct net *net) kmem_cache_free(net_cachep, net); } -static struct net *net_create(void) +struct net *copy_net_ns(unsigned long flags, struct net *old_net) { struct net *net; int rv; + if (!(flags & CLONE_NEWNET)) + return get_net(old_net); + net = net_alloc(); if (!net) return ERR_PTR(-ENOMEM); @@ -239,13 +242,6 @@ static struct net *net_create(void) return net; } -struct net *copy_net_ns(unsigned long flags, struct net *old_net) -{ - if (!(flags & CLONE_NEWNET)) - return get_net(old_net); - return net_create(); -} - static DEFINE_SPINLOCK(cleanup_list_lock); static LIST_HEAD(cleanup_list); /* Must hold cleanup_list_lock to touch */ -- cgit v1.2.3-58-ga151 From 6de240b7f714d63ca2a53d52c7eefb37e7eb3f1b Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 15 Apr 2011 04:50:49 +0000 Subject: net: spider_net: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/spider_net.c | 15 +++++++-------- drivers/net/spider_net.h | 7 ------- drivers/net/spider_net_ethtool.c | 21 --------------------- 3 files changed, 7 insertions(+), 36 deletions(-) diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index cb6bcca9d541..949f124e1278 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -994,15 +994,13 @@ spider_net_pass_skb_up(struct spider_net_descr *descr, skb->protocol = eth_type_trans(skb, netdev); /* checksum offload */ - if (card->options.rx_csum) { + skb_checksum_none_assert(skb); + if (netdev->features & NETIF_F_RXCSUM) { if ( ( (data_status & SPIDER_NET_DATA_STATUS_CKSUM_MASK) == SPIDER_NET_DATA_STATUS_CKSUM_MASK) && !(data_error & SPIDER_NET_DATA_ERR_CKSUM_MASK)) skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb_checksum_none_assert(skb); - } else - skb_checksum_none_assert(skb); + } if (data_status & SPIDER_NET_VLAN_PACKET) { /* further enhancements: HW-accel VLAN @@ -2322,14 +2320,15 @@ spider_net_setup_netdev(struct spider_net_card *card) card->aneg_timer.function = spider_net_link_phy; card->aneg_timer.data = (unsigned long) card; - card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT; - netif_napi_add(netdev, &card->napi, spider_net_poll, SPIDER_NET_NAPI_WEIGHT); spider_net_setup_netdev_ops(netdev); - netdev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX; + netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM; + if (SPIDER_NET_RX_CSUM_DEFAULT) + netdev->features |= NETIF_F_RXCSUM; + netdev->features |= NETIF_F_IP_CSUM | NETIF_F_LLTX; /* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | * NETIF_F_HW_VLAN_FILTER */ diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h index 05f74cbdd617..020f64a8fcf7 100644 --- a/drivers/net/spider_net.h +++ b/drivers/net/spider_net.h @@ -429,12 +429,6 @@ struct spider_net_descr_chain { * 701b8000 would be correct, but every packets gets that flag */ #define SPIDER_NET_DESTROY_RX_FLAGS 0x700b8000 -/* this will be bigger some time */ -struct spider_net_options { - int rx_csum; /* for rx: if 0 ip_summed=NONE, - if 1 and hw has verified, ip_summed=UNNECESSARY */ -}; - #define SPIDER_NET_DEFAULT_MSG ( NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ NETIF_MSG_LINK | \ @@ -487,7 +481,6 @@ struct spider_net_card { /* for ethtool */ int msg_enable; struct spider_net_extra_stats spider_stats; - struct spider_net_options options; /* Must be last item in struct */ struct spider_net_descr darray[0]; diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c index 5bae728c3820..d723fca872ce 100644 --- a/drivers/net/spider_net_ethtool.c +++ b/drivers/net/spider_net_ethtool.c @@ -115,24 +115,6 @@ spider_net_ethtool_nway_reset(struct net_device *netdev) return 0; } -static u32 -spider_net_ethtool_get_rx_csum(struct net_device *netdev) -{ - struct spider_net_card *card = netdev_priv(netdev); - - return card->options.rx_csum; -} - -static int -spider_net_ethtool_set_rx_csum(struct net_device *netdev, u32 n) -{ - struct spider_net_card *card = netdev_priv(netdev); - - card->options.rx_csum = n; - return 0; -} - - static void spider_net_ethtool_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ering) @@ -189,9 +171,6 @@ const struct ethtool_ops spider_net_ethtool_ops = { .set_msglevel = spider_net_ethtool_set_msglevel, .get_link = ethtool_op_get_link, .nway_reset = spider_net_ethtool_nway_reset, - .get_rx_csum = spider_net_ethtool_get_rx_csum, - .set_rx_csum = spider_net_ethtool_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, .get_ringparam = spider_net_ethtool_get_ringparam, .get_strings = spider_net_get_strings, .get_sset_count = spider_net_get_sset_count, -- cgit v1.2.3-58-ga151 From c88fcb3d8265cf473c73bc147a2aa21ae03abf67 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 15 Apr 2011 04:50:49 +0000 Subject: net: dm9000: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/dm9000.c | 57 ++++++++++++---------------------------------------- 1 file changed, 13 insertions(+), 44 deletions(-) diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index b7af5bab9937..f7bdebbcb908 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -131,8 +131,6 @@ typedef struct board_info { u32 msg_enable; u32 wake_state; - int rx_csum; - int can_csum; int ip_summed; } board_info_t; @@ -470,47 +468,20 @@ static int dm9000_nway_reset(struct net_device *dev) return mii_nway_restart(&dm->mii); } -static uint32_t dm9000_get_rx_csum(struct net_device *dev) +static int dm9000_set_features(struct net_device *dev, u32 features) { board_info_t *dm = to_dm9000_board(dev); - return dm->rx_csum; -} - -static int dm9000_set_rx_csum_unlocked(struct net_device *dev, uint32_t data) -{ - board_info_t *dm = to_dm9000_board(dev); - - if (dm->can_csum) { - dm->rx_csum = data; - iow(dm, DM9000_RCSR, dm->rx_csum ? RCSR_CSUM : 0); + u32 changed = dev->features ^ features; + unsigned long flags; + if (!(changed & NETIF_F_RXCSUM)) return 0; - } - - return -EOPNOTSUPP; -} - -static int dm9000_set_rx_csum(struct net_device *dev, uint32_t data) -{ - board_info_t *dm = to_dm9000_board(dev); - unsigned long flags; - int ret; spin_lock_irqsave(&dm->lock, flags); - ret = dm9000_set_rx_csum_unlocked(dev, data); + iow(dm, DM9000_RCSR, (features & NETIF_F_RXCSUM) ? RCSR_CSUM : 0); spin_unlock_irqrestore(&dm->lock, flags); - return ret; -} - -static int dm9000_set_tx_csum(struct net_device *dev, uint32_t data) -{ - board_info_t *dm = to_dm9000_board(dev); - int ret = -EOPNOTSUPP; - - if (dm->can_csum) - ret = ethtool_op_set_tx_csum(dev, data); - return ret; + return 0; } static u32 dm9000_get_link(struct net_device *dev) @@ -643,10 +614,6 @@ static const struct ethtool_ops dm9000_ethtool_ops = { .get_eeprom_len = dm9000_get_eeprom_len, .get_eeprom = dm9000_get_eeprom, .set_eeprom = dm9000_set_eeprom, - .get_rx_csum = dm9000_get_rx_csum, - .set_rx_csum = dm9000_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = dm9000_set_tx_csum, }; static void dm9000_show_carrier(board_info_t *db, @@ -800,7 +767,9 @@ dm9000_init_dm9000(struct net_device *dev) db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ /* Checksum mode */ - dm9000_set_rx_csum_unlocked(dev, db->rx_csum); + if (dev->hw_features & NETIF_F_RXCSUM) + iow(dm, DM9000_RCSR, + (dev->features & NETIF_F_RXCSUM) ? RCSR_CSUM : 0); iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ @@ -1049,7 +1018,7 @@ dm9000_rx(struct net_device *dev) /* Pass to upper layer */ skb->protocol = eth_type_trans(skb, dev); - if (db->rx_csum) { + if (dev->features & NETIF_F_RXCSUM) { if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0) skb->ip_summed = CHECKSUM_UNNECESSARY; else @@ -1358,6 +1327,7 @@ static const struct net_device_ops dm9000_netdev_ops = { .ndo_set_multicast_list = dm9000_hash_table, .ndo_do_ioctl = dm9000_ioctl, .ndo_change_mtu = eth_change_mtu, + .ndo_set_features = dm9000_set_features, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -1551,9 +1521,8 @@ dm9000_probe(struct platform_device *pdev) /* dm9000a/b are capable of hardware checksum offload */ if (db->type == TYPE_DM9000A || db->type == TYPE_DM9000B) { - db->can_csum = 1; - db->rx_csum = 1; - ndev->features |= NETIF_F_IP_CSUM; + ndev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM; + ndev->features |= ndev->hw_features; } /* from this point we assume that we have found a DM9000 */ -- cgit v1.2.3-58-ga151 From 569e146396cb3b378d2957b94671bf30cd777c67 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 15 Apr 2011 04:50:49 +0000 Subject: net: forcedeth: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also fixes a race around np->txrxctl_bits while changing RXCSUM offload. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 78 +++++++++++++++++-------------------------------- 1 file changed, 26 insertions(+), 52 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index d5ab4dad5051..ec9a32d01e61 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -774,7 +774,6 @@ struct fe_priv { u32 driver_data; u32 device_id; u32 register_size; - int rx_csum; u32 mac_in_use; int mgmt_version; int mgmt_sema; @@ -4480,58 +4479,36 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam* return 0; } -static u32 nv_get_rx_csum(struct net_device *dev) +static u32 nv_fix_features(struct net_device *dev, u32 features) { - struct fe_priv *np = netdev_priv(dev); - return np->rx_csum != 0; + /* vlan is dependent on rx checksum offload */ + if (features & (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX)) + features |= NETIF_F_RXCSUM; + + return features; } -static int nv_set_rx_csum(struct net_device *dev, u32 data) +static int nv_set_features(struct net_device *dev, u32 features) { struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - int retcode = 0; + u32 changed = dev->features ^ features; - if (np->driver_data & DEV_HAS_CHECKSUM) { - if (data) { - np->rx_csum = 1; - np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK; - } else { - np->rx_csum = 0; - /* vlan is dependent on rx checksum offload */ - if (!(np->vlanctl_bits & NVREG_VLANCONTROL_ENABLE)) - np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK; - } - if (netif_running(dev)) { - spin_lock_irq(&np->lock); - writel(np->txrxctl_bits, base + NvRegTxRxControl); - spin_unlock_irq(&np->lock); - } - } else { - return -EINVAL; - } - - return retcode; -} + if (changed & NETIF_F_RXCSUM) { + spin_lock_irq(&np->lock); -static int nv_set_tx_csum(struct net_device *dev, u32 data) -{ - struct fe_priv *np = netdev_priv(dev); + if (features & NETIF_F_RXCSUM) + np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK; + else + np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK; - if (np->driver_data & DEV_HAS_CHECKSUM) - return ethtool_op_set_tx_csum(dev, data); - else - return -EOPNOTSUPP; -} + if (netif_running(dev)) + writel(np->txrxctl_bits, base + NvRegTxRxControl); -static int nv_set_sg(struct net_device *dev, u32 data) -{ - struct fe_priv *np = netdev_priv(dev); + spin_unlock_irq(&np->lock); + } - if (np->driver_data & DEV_HAS_CHECKSUM) - return ethtool_op_set_sg(dev, data); - else - return -EOPNOTSUPP; + return 0; } static int nv_get_sset_count(struct net_device *dev, int sset) @@ -4896,15 +4873,10 @@ static const struct ethtool_ops ops = { .get_regs_len = nv_get_regs_len, .get_regs = nv_get_regs, .nway_reset = nv_nway_reset, - .set_tso = nv_set_tso, .get_ringparam = nv_get_ringparam, .set_ringparam = nv_set_ringparam, .get_pauseparam = nv_get_pauseparam, .set_pauseparam = nv_set_pauseparam, - .get_rx_csum = nv_get_rx_csum, - .set_rx_csum = nv_set_rx_csum, - .set_tx_csum = nv_set_tx_csum, - .set_sg = nv_set_sg, .get_strings = nv_get_strings, .get_ethtool_stats = nv_get_ethtool_stats, .get_sset_count = nv_get_sset_count, @@ -5235,6 +5207,8 @@ static const struct net_device_ops nv_netdev_ops = { .ndo_start_xmit = nv_start_xmit, .ndo_tx_timeout = nv_tx_timeout, .ndo_change_mtu = nv_change_mtu, + .ndo_fix_features = nv_fix_features, + .ndo_set_features = nv_set_features, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = nv_set_mac_address, .ndo_set_multicast_list = nv_set_multicast, @@ -5251,6 +5225,8 @@ static const struct net_device_ops nv_netdev_ops_optimized = { .ndo_start_xmit = nv_start_xmit_optimized, .ndo_tx_timeout = nv_tx_timeout, .ndo_change_mtu = nv_change_mtu, + .ndo_fix_features = nv_fix_features, + .ndo_set_features = nv_set_features, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = nv_set_mac_address, .ndo_set_multicast_list = nv_set_multicast, @@ -5364,11 +5340,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->pkt_limit = NV_PKTLIMIT_2; if (id->driver_data & DEV_HAS_CHECKSUM) { - np->rx_csum = 1; np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK; - dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; - dev->features |= NETIF_F_TSO; - dev->features |= NETIF_F_GRO; + dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_SG | + NETIF_F_TSO | NETIF_F_RXCSUM; + dev->features |= dev->hw_features; } np->vlanctl_bits = 0; @@ -5384,7 +5359,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->pause_flags |= NV_PAUSEFRAME_TX_CAPABLE | NV_PAUSEFRAME_TX_REQ; } - err = -ENOMEM; np->base = ioremap(addr, np->register_size); if (!np->base) -- cgit v1.2.3-58-ga151 From c8c64cff2c88b17fdd7402dd06288d7415896430 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 15 Apr 2011 04:50:49 +0000 Subject: net: mlx4: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/mlx4/en_ethtool.c | 42 ------------------------------------------ drivers/net/mlx4/en_netdev.c | 26 ++++++++++---------------- drivers/net/mlx4/en_rx.c | 2 +- drivers/net/mlx4/mlx4_en.h | 1 - 4 files changed, 11 insertions(+), 60 deletions(-) diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c index d54b7abf0225..da1b64d68607 100644 --- a/drivers/net/mlx4/en_ethtool.c +++ b/drivers/net/mlx4/en_ethtool.c @@ -57,37 +57,6 @@ mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) drvinfo->eedump_len = 0; } -static u32 mlx4_en_get_tso(struct net_device *dev) -{ - return (dev->features & NETIF_F_TSO) != 0; -} - -static int mlx4_en_set_tso(struct net_device *dev, u32 data) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - - if (data) { - if (!priv->mdev->LSO_support) - return -EPERM; - dev->features |= (NETIF_F_TSO | NETIF_F_TSO6); - } else - dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); - return 0; -} - -static u32 mlx4_en_get_rx_csum(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - return priv->rx_csum; -} - -static int mlx4_en_set_rx_csum(struct net_device *dev, u32 data) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - priv->rx_csum = (data != 0); - return 0; -} - static const char main_strings[][ETH_GSTRING_LEN] = { "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", @@ -483,17 +452,7 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { .get_drvinfo = mlx4_en_get_drvinfo, .get_settings = mlx4_en_get_settings, .set_settings = mlx4_en_set_settings, -#ifdef NETIF_F_TSO - .get_tso = mlx4_en_get_tso, - .set_tso = mlx4_en_set_tso, -#endif - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, .get_link = ethtool_op_get_link, - .get_rx_csum = mlx4_en_get_rx_csum, - .set_rx_csum = mlx4_en_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_ipv6_csum, .get_strings = mlx4_en_get_strings, .get_sset_count = mlx4_en_get_sset_count, .get_ethtool_stats = mlx4_en_get_ethtool_stats, @@ -508,7 +467,6 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { .set_pauseparam = mlx4_en_set_pauseparam, .get_ringparam = mlx4_en_get_ringparam, .set_ringparam = mlx4_en_set_ringparam, - .get_flags = ethtool_op_get_flags, }; diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 77063f91c564..61850adae6f7 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -1083,7 +1083,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv->prof = prof; priv->port = port; priv->port_up = false; - priv->rx_csum = 1; priv->flags = prof->flags; priv->tx_ring_num = prof->tx_ring_num; priv->rx_ring_num = prof->rx_ring_num; @@ -1141,21 +1140,16 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, /* * Set driver features */ - dev->features |= NETIF_F_SG; - dev->vlan_features |= NETIF_F_SG; - dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - dev->vlan_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - dev->features |= NETIF_F_HIGHDMA; - dev->features |= NETIF_F_HW_VLAN_TX | - NETIF_F_HW_VLAN_RX | - NETIF_F_HW_VLAN_FILTER; - dev->features |= NETIF_F_GRO; - if (mdev->LSO_support) { - dev->features |= NETIF_F_TSO; - dev->features |= NETIF_F_TSO6; - dev->vlan_features |= NETIF_F_TSO; - dev->vlan_features |= NETIF_F_TSO6; - } + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + if (mdev->LSO_support) + dev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; + + dev->vlan_features = dev->hw_features; + + dev->hw_features |= NETIF_F_RXCSUM; + dev->features = dev->hw_features | NETIF_F_HIGHDMA | + NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | + NETIF_F_HW_VLAN_FILTER; mdev->pndev[port] = dev; diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index 62dd21b06df4..277215fb9d72 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -584,7 +584,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud ring->bytes += length; ring->packets++; - if (likely(priv->rx_csum)) { + if (likely(dev->features & NETIF_F_RXCSUM)) { if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) && (cqe->checksum == cpu_to_be16(0xffff))) { priv->port_stats.rx_chksum_good++; diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index e30f6099c0de..0b5150df0585 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -451,7 +451,6 @@ struct mlx4_en_priv { int registered; int allocated; int stride; - int rx_csum; u64 mac; int mac_index; unsigned max_mtu; -- cgit v1.2.3-58-ga151 From 8b3afe95e363dbd32bd9ddc6c2d562944f5350c5 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 15 Apr 2011 04:50:50 +0000 Subject: net: gianfar: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note: I bet that gfar_set_features() don't really need a full reset. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 16 ++++++------ drivers/net/gianfar.h | 3 ++- drivers/net/gianfar_ethtool.c | 58 ++++--------------------------------------- 3 files changed, 16 insertions(+), 61 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 2a0ad9a501bb..ff60b23a5b74 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -365,7 +365,7 @@ static void gfar_init_mac(struct net_device *ndev) gfar_write(®s->rir0, DEFAULT_RIR0); } - if (priv->rx_csum_enable) + if (ndev->features & NETIF_F_RXCSUM) rctrl |= RCTRL_CHECKSUMMING; if (priv->extended_hash) { @@ -463,6 +463,7 @@ static const struct net_device_ops gfar_netdev_ops = { .ndo_start_xmit = gfar_start_xmit, .ndo_stop = gfar_close, .ndo_change_mtu = gfar_change_mtu, + .ndo_set_features = gfar_set_features, .ndo_set_multicast_list = gfar_set_multi, .ndo_tx_timeout = gfar_timeout, .ndo_do_ioctl = gfar_ioctl, @@ -513,7 +514,7 @@ void unlock_tx_qs(struct gfar_private *priv) /* Returns 1 if incoming frames use an FCB */ static inline int gfar_uses_fcb(struct gfar_private *priv) { - return priv->vlgrp || priv->rx_csum_enable || + return priv->vlgrp || (priv->ndev->features & NETIF_F_RXCSUM) || (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER); } @@ -1030,10 +1031,11 @@ static int gfar_probe(struct platform_device *ofdev) netif_napi_add(dev, &priv->gfargrp[i].napi, gfar_poll, GFAR_DEV_WEIGHT); if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { - priv->rx_csum_enable = 1; - dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA; - } else - priv->rx_csum_enable = 0; + dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | + NETIF_F_RXCSUM; + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG | + NETIF_F_RXCSUM | NETIF_F_HIGHDMA; + } priv->vlgrp = NULL; @@ -2697,7 +2699,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, if (priv->padding) skb_pull(skb, priv->padding); - if (priv->rx_csum_enable) + if (dev->features & NETIF_F_RXCSUM) gfar_rx_checksum(skb, fcb); /* Tell the skb what kind of packet this is */ diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 0438d3551d5c..fc86f5195445 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -1083,7 +1083,7 @@ struct gfar_private { struct device_node *phy_node; struct device_node *tbi_node; u32 device_flags; - unsigned char rx_csum_enable:1, + unsigned char extended_hash:1, bd_stash_en:1, rx_filer_enable:1, @@ -1153,6 +1153,7 @@ extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, extern void gfar_configure_coalescing(struct gfar_private *priv, unsigned long tx_mask, unsigned long rx_mask); void gfar_init_sysfs(struct net_device *dev); +int gfar_set_features(struct net_device *dev, u32 features); extern const struct ethtool_ops gfar_ethtool_ops; diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 0840590958dd..493d743839d9 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -517,15 +517,15 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva return err; } -static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) +int gfar_set_features(struct net_device *dev, u32 features) { struct gfar_private *priv = netdev_priv(dev); unsigned long flags; int err = 0, i = 0; + u32 changed = dev->features ^ features; - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) - return -EOPNOTSUPP; - + if (!(changed & NETIF_F_RXCSUM)) + return 0; if (dev->flags & IFF_UP) { /* Halt TX and RX, and process the frames which @@ -546,58 +546,15 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) /* Now we take down the rings to rebuild them */ stop_gfar(dev); - } - spin_lock_irqsave(&priv->bflock, flags); - priv->rx_csum_enable = data; - spin_unlock_irqrestore(&priv->bflock, flags); + dev->features = features; - if (dev->flags & IFF_UP) { err = startup_gfar(dev); netif_tx_wake_all_queues(dev); } return err; } -static uint32_t gfar_get_rx_csum(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) - return 0; - - return priv->rx_csum_enable; -} - -static int gfar_set_tx_csum(struct net_device *dev, uint32_t data) -{ - struct gfar_private *priv = netdev_priv(dev); - - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) - return -EOPNOTSUPP; - - netif_tx_lock_bh(dev); - - if (data) - dev->features |= NETIF_F_IP_CSUM; - else - dev->features &= ~NETIF_F_IP_CSUM; - - netif_tx_unlock_bh(dev); - - return 0; -} - -static uint32_t gfar_get_tx_csum(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) - return 0; - - return (dev->features & NETIF_F_IP_CSUM) != 0; -} - static uint32_t gfar_get_msglevel(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); @@ -844,11 +801,6 @@ const struct ethtool_ops gfar_ethtool_ops = { .get_strings = gfar_gstrings, .get_sset_count = gfar_sset_count, .get_ethtool_stats = gfar_fill_stats, - .get_rx_csum = gfar_get_rx_csum, - .get_tx_csum = gfar_get_tx_csum, - .set_rx_csum = gfar_set_rx_csum, - .set_tx_csum = gfar_set_tx_csum, - .set_sg = ethtool_op_set_sg, .get_msglevel = gfar_get_msglevel, .set_msglevel = gfar_set_msglevel, #ifdef CONFIG_PM -- cgit v1.2.3-58-ga151 From dd182574d86e22faaaed37db79e3d54e773f29f7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 00:03:38 -0700 Subject: atm: eni: Kill set-but-unused variables. The variable eni_dev is initialized but never subsequently used in these two functions. Signed-off-by: David S. Miller --- drivers/atm/eni.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index c495fae74200..3230ea0df83c 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -1469,10 +1469,7 @@ if (eni_boards) printk(KERN_INFO "loss: %ld\n",ENI_DEV(eni_boards)->lost); static void bug_int(struct atm_dev *dev,unsigned long reason) { - struct eni_dev *eni_dev; - DPRINTK(">bug_int\n"); - eni_dev = ENI_DEV(dev); if (reason & MID_DMA_ERR_ACK) printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA " "error\n",dev->number); @@ -1900,7 +1897,6 @@ static void eni_close(struct atm_vcc *vcc) static int eni_open(struct atm_vcc *vcc) { - struct eni_dev *eni_dev; struct eni_vcc *eni_vcc; int error; short vpi = vcc->vpi; @@ -1910,7 +1906,6 @@ static int eni_open(struct atm_vcc *vcc) EVENT("eni_open\n",0,0); if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) vcc->dev_data = NULL; - eni_dev = ENI_DEV(vcc->dev); if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC) set_bit(ATM_VF_ADDR,&vcc->flags); if (vcc->qos.aal != ATM_AAL0 && vcc->qos.aal != ATM_AAL5) -- cgit v1.2.3-58-ga151 From e60c5e14fbfcaa54f430aad80b38763a403b2158 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 00:07:55 -0700 Subject: atm: he: Fix undefined sequence points. GCC complains in these queue index operations because we perform operations of the form: x = some_operation(++x); which is undefined. Replace with: x = some_operation(x + 1); which is well defined and provides the intended operation. Signed-off-by: David S. Miller --- drivers/atm/he.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/atm/he.c b/drivers/atm/he.c index 6cf59bf281dc..9a51df4f5b74 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -1801,7 +1801,7 @@ return_host_buffers: next_rbrq_entry: he_dev->rbrq_head = (struct he_rbrq *) ((unsigned long) he_dev->rbrq_base | - RBRQ_MASK(++he_dev->rbrq_head)); + RBRQ_MASK(he_dev->rbrq_head + 1)); } read_unlock(&vcc_sklist_lock); @@ -1884,7 +1884,7 @@ next_tbrq_entry: pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status)); he_dev->tbrq_head = (struct he_tbrq *) ((unsigned long) he_dev->tbrq_base | - TBRQ_MASK(++he_dev->tbrq_head)); + TBRQ_MASK(he_dev->tbrq_head + 1)); } if (updated) { -- cgit v1.2.3-58-ga151 From edb4dcb717d71f63c5147d7bef3014f96d192842 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 00:10:17 -0700 Subject: atm: idt77252: Fix set-but-unused variables. Two cases here: 1) idt77252_rx_raw() really does not make any use of the extracted PTI field of the atm header. 2) idt77252_collect_stat() only uses the register values in code which has been compiled out by a "NOTDEF" cpp test for more than 10 years. Just kill this NOTDEF code entirely, but keep the register reads in case they have side effects. Signed-off-by: David S. Miller --- drivers/atm/idt77252.c | 52 ++++---------------------------------------------- 1 file changed, 4 insertions(+), 48 deletions(-) diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 048f99fe6f83..1f8d724a18bf 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -1261,14 +1261,13 @@ idt77252_rx_raw(struct idt77252_dev *card) PCI_DMA_FROMDEVICE); while (head != tail) { - unsigned int vpi, vci, pti; + unsigned int vpi, vci; u32 header; header = le32_to_cpu(*(u32 *) &queue->data[0]); vpi = (header & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT; vci = (header & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT; - pti = (header & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT; #ifdef CONFIG_ATM_IDT77252_DEBUG if (debug & DBG_RAW_CELL) { @@ -2709,53 +2708,10 @@ idt77252_proc_read(struct atm_dev *dev, loff_t * pos, char *page) static void idt77252_collect_stat(struct idt77252_dev *card) { - u32 cdc, vpec, icc; + (void) readl(SAR_REG_CDC); + (void) readl(SAR_REG_VPEC); + (void) readl(SAR_REG_ICC); - cdc = readl(SAR_REG_CDC); - vpec = readl(SAR_REG_VPEC); - icc = readl(SAR_REG_ICC); - -#ifdef NOTDEF - printk("%s:", card->name); - - if (cdc & 0x7f0000) { - char *s = ""; - - printk(" ["); - if (cdc & (1 << 22)) { - printk("%sRM ID", s); - s = " | "; - } - if (cdc & (1 << 21)) { - printk("%sCON TAB", s); - s = " | "; - } - if (cdc & (1 << 20)) { - printk("%sNO FB", s); - s = " | "; - } - if (cdc & (1 << 19)) { - printk("%sOAM CRC", s); - s = " | "; - } - if (cdc & (1 << 18)) { - printk("%sRM CRC", s); - s = " | "; - } - if (cdc & (1 << 17)) { - printk("%sRM FIFO", s); - s = " | "; - } - if (cdc & (1 << 16)) { - printk("%sRX FIFO", s); - s = " | "; - } - printk("]"); - } - - printk(" CDC %04x, VPEC %04x, ICC: %04x\n", - cdc & 0xffff, vpec & 0xffff, icc & 0xffff); -#endif } static irqreturn_t -- cgit v1.2.3-58-ga151 From 06091ed6b8ec726e6cbc7e40ee6b5aa2332cf381 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 00:11:25 -0700 Subject: atm: solos-pci: Fix set-but-unused variable. This is just a readback to entire completion of a register write, keep the readback but kill the unused variable. Signed-off-by: David S. Miller --- drivers/atm/solos-pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index cd0ff66469b2..5d1d07645132 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -527,7 +527,6 @@ static int flash_upgrade(struct solos_card *card, int chip) { const struct firmware *fw; const char *fw_name; - uint32_t data32 = 0; int blocksize = 0; int numblocks = 0; int offset; @@ -576,7 +575,7 @@ static int flash_upgrade(struct solos_card *card, int chip) dev_info(&card->dev->dev, "Changing FPGA to Update mode\n"); iowrite32(1, card->config_regs + FPGA_MODE); - data32 = ioread32(card->config_regs + FPGA_MODE); + (void) ioread32(card->config_regs + FPGA_MODE); /* Set mode to Chip Erase */ if(chip == 0 || chip == 2) -- cgit v1.2.3-58-ga151 From 21f825e61878db94c7093c8407602fc89fc38ad9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 00:13:16 -0700 Subject: pktgen: Fix set-but-unused variable. "iph" in pktgen_output_ipsec() is set but never actually used. Kill it off. Signed-off-by: David S. Miller --- net/core/pktgen.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index aeeece72b72f..2fa6fee1b46f 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2514,7 +2514,6 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev) { struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; int err = 0; - struct iphdr *iph; if (!x) return 0; @@ -2524,7 +2523,6 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev) return 0; spin_lock(&x->lock); - iph = ip_hdr(skb); err = x->outer_mode->output(x, skb); if (err) -- cgit v1.2.3-58-ga151 From 9bf9055eb716f85372c41b3fbc51f90bc7653740 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 00:14:09 -0700 Subject: decnet: Fix set-but-unused variable. "next" in dn_rebuild_zone() is set but not actually used, kill it off. Signed-off-by: David S. Miller --- net/decnet/dn_table.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index 99d8d3a40998..d8ea583076cf 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c @@ -124,11 +124,10 @@ static inline void dn_rebuild_zone(struct dn_zone *dz, int old_divisor) { int i; - struct dn_fib_node *f, **fp, *next; + struct dn_fib_node *f, **fp; for(i = 0; i < old_divisor; i++) { for(f = old_ht[i]; f; f = f->fn_next) { - next = f->fn_next; for(fp = dn_chain_p(f->fn_key, dz); *fp && dn_key_leq((*fp)->fn_key, f->fn_key); fp = &(*fp)->fn_next) -- cgit v1.2.3-58-ga151 From b3b8dc51c16cdaca0d191a340022093fb5c9f003 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 00:15:22 -0700 Subject: econet: Fix set-but-unused variable. #if 0'd out code for IP handling in aun_data_available() has been commented out since the beginning, which makes the variable "ip" set but not used. Kill it off as well as the stub code. Signed-off-by: David S. Miller --- net/econet/af_econet.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 116d3fd3d669..a1d9f3787dd5 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -935,7 +935,6 @@ static void aun_data_available(struct sock *sk, int slen) struct sk_buff *skb; unsigned char *data; struct aunhdr *ah; - struct iphdr *ip; size_t len; while ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) { @@ -949,7 +948,6 @@ static void aun_data_available(struct sock *sk, int slen) data = skb_transport_header(skb) + sizeof(struct udphdr); ah = (struct aunhdr *)data; len = skb->len - sizeof(struct udphdr); - ip = ip_hdr(skb); switch (ah->code) { @@ -962,12 +960,6 @@ static void aun_data_available(struct sock *sk, int slen) case 4: aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_NOT_LISTENING); break; -#if 0 - /* This isn't quite right yet. */ - case 5: - aun_send_response(ip->saddr, ah->handle, 6, ah->cb); - break; -#endif default: printk(KERN_DEBUG "unknown AUN packet (type %d)\n", data[0]); } -- cgit v1.2.3-58-ga151 From d8f969e603b85931f25a1d50f3a7a01e2712c17a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 00:46:45 -0700 Subject: ax25: Fix set-but-unused variable. The variable 's' is set but unused in ax25_protocol_release(). Just kill it off. Signed-off-by: David S. Miller --- net/ax25/ax25_iface.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c index 5a0dda8df492..60b545e2822a 100644 --- a/net/ax25/ax25_iface.c +++ b/net/ax25/ax25_iface.c @@ -58,7 +58,7 @@ EXPORT_SYMBOL_GPL(ax25_register_pid); void ax25_protocol_release(unsigned int pid) { - struct ax25_protocol *s, *protocol; + struct ax25_protocol *protocol; write_lock_bh(&protocol_list_lock); protocol = protocol_list; @@ -72,7 +72,6 @@ void ax25_protocol_release(unsigned int pid) while (protocol != NULL && protocol->next != NULL) { if (protocol->next->pid == pid) { - s = protocol->next; protocol->next = protocol->next->next; goto out; } -- cgit v1.2.3-58-ga151 From 9e5ebaf852b96aaf4d7f63b920d8016b6784f088 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 00:48:01 -0700 Subject: atm: lec: Fix set-but-unused variables. The variable 'eth' is set but unused in lec_handle_bridge(). Also, the variable 'priv' is set but unused in lane_module_cleanup(). Just kill them off. Signed-off-by: David S. Miller --- net/atm/lec.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/atm/lec.c b/net/atm/lec.c index 38754fdb88ba..25073b6ef474 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -129,7 +129,6 @@ static struct net_device *dev_lec[MAX_LEC_ITF]; #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) { - struct ethhdr *eth; char *buff; struct lec_priv *priv; @@ -138,7 +137,6 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit * as the Config BPDU has */ - eth = (struct ethhdr *)skb->data; buff = skb->data + skb->dev->hard_header_len; if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) { struct sock *sk; @@ -1180,7 +1178,6 @@ static int __init lane_module_init(void) static void __exit lane_module_cleanup(void) { int i; - struct lec_priv *priv; remove_proc_entry("lec", atm_proc_root); @@ -1188,7 +1185,6 @@ static void __exit lane_module_cleanup(void) for (i = 0; i < MAX_LEC_ITF; i++) { if (dev_lec[i] != NULL) { - priv = netdev_priv(dev_lec[i]); unregister_netdev(dev_lec[i]); free_netdev(dev_lec[i]); dev_lec[i] = NULL; -- cgit v1.2.3-58-ga151 From 7d038eb6dc0e256dbcac88d52972c4ac55a78fc5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 00:50:58 -0700 Subject: bonding: Fix set-but-unused variable. The variable 'vlan_dev' is set but unused in bond_send_gratuitous_arp(). Just kill it off. Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index ca902ae3f2e5..fdf9215ada7d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2763,7 +2763,6 @@ static void bond_send_gratuitous_arp(struct bonding *bond) { struct slave *slave = bond->curr_active_slave; struct vlan_entry *vlan; - struct net_device *vlan_dev; pr_debug("bond_send_grat_arp: bond %s slave %s\n", bond->dev->name, slave ? slave->dev->name : "NULL"); @@ -2783,7 +2782,6 @@ static void bond_send_gratuitous_arp(struct bonding *bond) return; list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { - vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id); if (vlan->vlan_ip) { bond_arp_send(slave->dev, ARPOP_REPLY, vlan->vlan_ip, vlan->vlan_ip, vlan->vlan_id); -- cgit v1.2.3-58-ga151 From f8dfc4528b93ba9c9a191151f8888b4da1d1a45b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 00:51:40 -0700 Subject: atlx: Fix set-but-unused variable. The variable 'tpc' is set but unused in atl1_intr_tx(). Just kill it off. Signed-off-by: David S. Miller --- drivers/net/atlx/atl1.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 98334a1f0c5c..dffa6919a419 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -2074,9 +2074,6 @@ static void atl1_intr_tx(struct atl1_adapter *adapter) cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx); while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) { - struct tx_packet_desc *tpd; - - tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean); buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean]; if (buffer_info->dma) { pci_unmap_page(adapter->pdev, buffer_info->dma, -- cgit v1.2.3-58-ga151 From c96922c7beeb6246f36b89a1e8b61d99a435a780 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 00:54:51 -0700 Subject: atl1e: Fix set-but-unused variable. The variable 'tx_ring' is set but unused in atl1e_init_ring_resources(). Just kill it off. Signed-off-by: David S. Miller --- drivers/net/atl1e/atl1e_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 9900ca1d8eda..86a912283134 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -691,10 +691,8 @@ static void atl1e_cal_ring_size(struct atl1e_adapter *adapter, u32 *ring_size) static void atl1e_init_ring_resources(struct atl1e_adapter *adapter) { - struct atl1e_tx_ring *tx_ring = NULL; struct atl1e_rx_ring *rx_ring = NULL; - tx_ring = &adapter->tx_ring; rx_ring = &adapter->rx_ring; rx_ring->real_page_size = adapter->rx_ring.page_size -- cgit v1.2.3-58-ga151 From 0c78641d7f677c8f420f1c302b4848135b207eb8 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 00:55:20 -0700 Subject: atl1c: Fix set-but-unused variable. The variable 'extra_size' is set but unused in atl1c_configure_tx(). Just kill it off. Signed-off-by: David S. Miller --- drivers/net/atl1c/atl1c_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 894d485bf5bc..5c64a5d91544 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -1095,10 +1095,8 @@ static void atl1c_configure_tx(struct atl1c_adapter *adapter) u32 max_pay_load; u16 tx_offload_thresh; u32 txq_ctrl_data; - u32 extra_size = 0; /* Jumbo frame threshold in QWORD unit */ u32 max_pay_load_data; - extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN; tx_offload_thresh = MAX_TX_OFFLOAD_THRESH; AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH, (tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK); -- cgit v1.2.3-58-ga151 From 551586292b39da6e4fbfbb5b96b57b68decfdab9 Mon Sep 17 00:00:00 2001 From: Linus Lüssing Date: Mon, 14 Mar 2011 22:43:27 +0000 Subject: batman-adv: Move bonding / iface alternating router search to own functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This decreases the size of find_router() by outsourcing the router search for the bonding and interface alternating modes to their own sub functions. This shall make it easier to keep track of the correct refcounting later. Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/routing.c | 180 +++++++++++++++++++++++++++-------------------- 1 file changed, 105 insertions(+), 75 deletions(-) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index c172f5d0e05a..f212abe745bc 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1092,6 +1092,106 @@ out: return ret; } +/* In the bonding case, send the packets in a round + * robin fashion over the remaining interfaces. + * + * This method rotates the bonding list and increases the + * returned router's refcount. */ +static struct neigh_node *find_bond_router(struct orig_node *primary_orig, + struct hard_iface *recv_if) +{ + struct neigh_node *tmp_neigh_node; + struct neigh_node *router = NULL, *first_candidate = NULL; + + rcu_read_lock(); + list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, + bonding_list) { + if (!first_candidate) + first_candidate = tmp_neigh_node; + + /* recv_if == NULL on the first node. */ + if (tmp_neigh_node->if_incoming == recv_if) + continue; + + if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + continue; + + router = tmp_neigh_node; + break; + } + + /* use the first candidate if nothing was found. */ + if (!router && first_candidate && + atomic_inc_not_zero(&first_candidate->refcount)) + router = first_candidate; + + if (!router) + goto out; + + /* selected should point to the next element + * after the current router */ + spin_lock_bh(&primary_orig->neigh_list_lock); + /* this is a list_move(), which unfortunately + * does not exist as rcu version */ + list_del_rcu(&primary_orig->bond_list); + list_add_rcu(&primary_orig->bond_list, + &router->bonding_list); + spin_unlock_bh(&primary_orig->neigh_list_lock); + +out: + rcu_read_unlock(); + return router; +} + +/* Interface Alternating: Use the best of the + * remaining candidates which are not using + * this interface. + * + * Increases the returned router's refcount */ +static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig, + struct hard_iface *recv_if) +{ + struct neigh_node *tmp_neigh_node; + struct neigh_node *router = NULL, *first_candidate = NULL; + + rcu_read_lock(); + list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, + bonding_list) { + if (!first_candidate) + first_candidate = tmp_neigh_node; + + /* recv_if == NULL on the first node. */ + if (tmp_neigh_node->if_incoming == recv_if) + continue; + + if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + continue; + + /* if we don't have a router yet + * or this one is better, choose it. */ + if ((!router) || + (tmp_neigh_node->tq_avg > router->tq_avg)) { + /* decrement refcount of + * previously selected router */ + if (router) + neigh_node_free_ref(router); + + router = tmp_neigh_node; + atomic_inc_not_zero(&router->refcount); + } + + neigh_node_free_ref(tmp_neigh_node); + } + + /* use the first candidate if nothing was found. */ + if (!router && first_candidate && + atomic_inc_not_zero(&first_candidate->refcount)) + router = first_candidate; + + rcu_read_unlock(); + return router; +} + /* find a suitable router for this originator, and use * bonding if possible. increases the found neighbors * refcount.*/ @@ -1101,7 +1201,7 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, { struct orig_node *primary_orig_node; struct orig_node *router_orig; - struct neigh_node *router, *first_candidate, *tmp_neigh_node; + struct neigh_node *router; static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; int bonding_enabled; @@ -1157,82 +1257,12 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, * in. */ neigh_node_free_ref(router); - first_candidate = NULL; - router = NULL; - - if (bonding_enabled) { - /* in the bonding case, send the packets in a round - * robin fashion over the remaining interfaces. */ - - list_for_each_entry_rcu(tmp_neigh_node, - &primary_orig_node->bond_list, bonding_list) { - if (!first_candidate) - first_candidate = tmp_neigh_node; - /* recv_if == NULL on the first node. */ - if (tmp_neigh_node->if_incoming != recv_if && - atomic_inc_not_zero(&tmp_neigh_node->refcount)) { - router = tmp_neigh_node; - break; - } - } - - /* use the first candidate if nothing was found. */ - if (!router && first_candidate && - atomic_inc_not_zero(&first_candidate->refcount)) - router = first_candidate; - if (!router) { - rcu_read_unlock(); - return NULL; - } - - /* selected should point to the next element - * after the current router */ - spin_lock_bh(&primary_orig_node->neigh_list_lock); - /* this is a list_move(), which unfortunately - * does not exist as rcu version */ - list_del_rcu(&primary_orig_node->bond_list); - list_add_rcu(&primary_orig_node->bond_list, - &router->bonding_list); - spin_unlock_bh(&primary_orig_node->neigh_list_lock); - - } else { - /* if bonding is disabled, use the best of the - * remaining candidates which are not using - * this interface. */ - list_for_each_entry_rcu(tmp_neigh_node, - &primary_orig_node->bond_list, bonding_list) { - if (!first_candidate) - first_candidate = tmp_neigh_node; - - /* recv_if == NULL on the first node. */ - if (tmp_neigh_node->if_incoming == recv_if) - continue; - - if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) - continue; - - /* if we don't have a router yet - * or this one is better, choose it. */ - if ((!router) || - (tmp_neigh_node->tq_avg > router->tq_avg)) { - /* decrement refcount of - * previously selected router */ - if (router) - neigh_node_free_ref(router); - - router = tmp_neigh_node; - atomic_inc_not_zero(&router->refcount); - } - - neigh_node_free_ref(tmp_neigh_node); - } + if (bonding_enabled) + router = find_bond_router(primary_orig_node, recv_if); + else + router = find_ifalter_router(primary_orig_node, recv_if); - /* use the first candidate if nothing was found. */ - if (!router && first_candidate && - atomic_inc_not_zero(&first_candidate->refcount)) - router = first_candidate; - } return_router: rcu_read_unlock(); return router; -- cgit v1.2.3-58-ga151 From 4c804850572f70a2350e4d1e79d6659392b07733 Mon Sep 17 00:00:00 2001 From: Linus Lüssing Date: Mon, 14 Mar 2011 22:43:30 +0000 Subject: batman-adv: Make gateway_get_selected type safe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the return value explicit instead of (void *). Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/gateway_client.c | 2 +- net/batman-adv/gateway_client.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 3cc43558cf9c..27b87add044b 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -42,7 +42,7 @@ static void gw_node_free_ref(struct gw_node *gw_node) call_rcu(&gw_node->rcu, gw_node_free_rcu); } -void *gw_get_selected(struct bat_priv *bat_priv) +struct orig_node *gw_get_selected(struct bat_priv *bat_priv) { struct gw_node *curr_gateway_tmp; struct orig_node *orig_node = NULL; diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h index 2aa439124ee3..97c31d178163 100644 --- a/net/batman-adv/gateway_client.h +++ b/net/batman-adv/gateway_client.h @@ -24,7 +24,7 @@ void gw_deselect(struct bat_priv *bat_priv); void gw_election(struct bat_priv *bat_priv); -void *gw_get_selected(struct bat_priv *bat_priv); +struct orig_node *gw_get_selected(struct bat_priv *bat_priv); void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node); void gw_node_update(struct bat_priv *bat_priv, struct orig_node *orig_node, uint8_t new_gwflags); -- cgit v1.2.3-58-ga151 From 57f0c07c4d0da8bcc23e21c330fe9c7c5cf776b5 Mon Sep 17 00:00:00 2001 From: Linus Lüssing Date: Mon, 14 Mar 2011 22:43:33 +0000 Subject: batman-adv: Simplify gw_check_election(), use gw_get_selected() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gw_get_selected() can get us the desired orig_node directly, therefore reusing that function in gw_check_election(). Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/gateway_client.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 27b87add044b..879ac1594869 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -23,6 +23,7 @@ #include "gateway_client.h" #include "gateway_common.h" #include "hard-interface.h" +#include "originator.h" #include #include #include @@ -203,28 +204,25 @@ void gw_election(struct bat_priv *bat_priv) void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) { - struct gw_node *curr_gateway_tmp; + struct orig_node *curr_gw_orig; uint8_t gw_tq_avg, orig_tq_avg; - rcu_read_lock(); - curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw); - if (!curr_gateway_tmp) - goto out_rcu; + curr_gw_orig = gw_get_selected(bat_priv); + if (!curr_gw_orig) + goto deselect; - if (!curr_gateway_tmp->orig_node) - goto deselect_rcu; - - if (!curr_gateway_tmp->orig_node->router) + rcu_read_lock(); + if (!curr_gw_orig->router) goto deselect_rcu; /* this node already is the gateway */ - if (curr_gateway_tmp->orig_node == orig_node) + if (curr_gw_orig == orig_node) goto out_rcu; if (!orig_node->router) goto out_rcu; - gw_tq_avg = curr_gateway_tmp->orig_node->router->tq_avg; + gw_tq_avg = curr_gw_orig->router->tq_avg; rcu_read_unlock(); orig_tq_avg = orig_node->router->tq_avg; @@ -255,6 +253,9 @@ deselect_rcu: deselect: gw_deselect(bat_priv); out: + if (curr_gw_orig) + orig_node_free_ref(curr_gw_orig); + return; } -- cgit v1.2.3-58-ga151 From e1a5382f978b67b5cc36eec65e6046730ce07714 Mon Sep 17 00:00:00 2001 From: Linus Lüssing Date: Mon, 14 Mar 2011 22:43:37 +0000 Subject: batman-adv: Make orig_node->router an rcu protected pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rcu protected macros rcu_dereference() and rcu_assign_pointer() for the orig_node->router need to be used, as well as spin/rcu locking. Otherwise we might end up using a router pointer pointing to already freed memory. Therefore this commit introduces the safe getter method orig_node_get_router(). Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/gateway_client.c | 80 ++++++++++------- net/batman-adv/icmp_socket.c | 18 +--- net/batman-adv/originator.c | 37 ++++++-- net/batman-adv/originator.h | 1 + net/batman-adv/routing.c | 194 +++++++++++++++++++--------------------- net/batman-adv/send.c | 19 ++-- net/batman-adv/types.h | 4 +- net/batman-adv/vis.c | 91 ++++++++++--------- 8 files changed, 232 insertions(+), 212 deletions(-) diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 879ac1594869..42a8a7ba06e6 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -98,6 +98,7 @@ void gw_election(struct bat_priv *bat_priv) { struct hlist_node *node; struct gw_node *gw_node, *curr_gw, *curr_gw_tmp = NULL; + struct neigh_node *router; uint8_t max_tq = 0; uint32_t max_gw_factor = 0, tmp_gw_factor = 0; int down, up; @@ -133,10 +134,11 @@ void gw_election(struct bat_priv *bat_priv) } hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { - if (!gw_node->orig_node->router) + if (gw_node->deleted) continue; - if (gw_node->deleted) + router = orig_node_get_router(gw_node->orig_node); + if (!router) continue; switch (atomic_read(&bat_priv->gw_sel_class)) { @@ -144,15 +146,14 @@ void gw_election(struct bat_priv *bat_priv) gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up); - tmp_gw_factor = (gw_node->orig_node->router->tq_avg * - gw_node->orig_node->router->tq_avg * + tmp_gw_factor = (router->tq_avg * router->tq_avg * down * 100 * 100) / (TQ_LOCAL_WINDOW_SIZE * TQ_LOCAL_WINDOW_SIZE * 64); if ((tmp_gw_factor > max_gw_factor) || ((tmp_gw_factor == max_gw_factor) && - (gw_node->orig_node->router->tq_avg > max_tq))) + (router->tq_avg > max_tq))) curr_gw_tmp = gw_node; break; @@ -164,19 +165,25 @@ void gw_election(struct bat_priv *bat_priv) * soon as a better gateway appears which has * $routing_class more tq points) **/ - if (gw_node->orig_node->router->tq_avg > max_tq) + if (router->tq_avg > max_tq) curr_gw_tmp = gw_node; break; } - if (gw_node->orig_node->router->tq_avg > max_tq) - max_tq = gw_node->orig_node->router->tq_avg; + if (router->tq_avg > max_tq) + max_tq = router->tq_avg; if (tmp_gw_factor > max_gw_factor) max_gw_factor = tmp_gw_factor; + + neigh_node_free_ref(router); } if (curr_gw != curr_gw_tmp) { + router = orig_node_get_router(curr_gw_tmp->orig_node); + if (!router) + goto out; + if ((curr_gw) && (!curr_gw_tmp)) bat_dbg(DBG_BATMAN, bat_priv, "Removing selected gateway - " @@ -187,45 +194,47 @@ void gw_election(struct bat_priv *bat_priv) "(gw_flags: %i, tq: %i)\n", curr_gw_tmp->orig_node->orig, curr_gw_tmp->orig_node->gw_flags, - curr_gw_tmp->orig_node->router->tq_avg); + router->tq_avg); else bat_dbg(DBG_BATMAN, bat_priv, "Changing route to gateway %pM " "(gw_flags: %i, tq: %i)\n", curr_gw_tmp->orig_node->orig, curr_gw_tmp->orig_node->gw_flags, - curr_gw_tmp->orig_node->router->tq_avg); + router->tq_avg); + neigh_node_free_ref(router); gw_select(bat_priv, curr_gw_tmp); } +out: rcu_read_unlock(); } void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) { struct orig_node *curr_gw_orig; + struct neigh_node *router_gw = NULL, *router_orig = NULL; uint8_t gw_tq_avg, orig_tq_avg; curr_gw_orig = gw_get_selected(bat_priv); if (!curr_gw_orig) goto deselect; - rcu_read_lock(); - if (!curr_gw_orig->router) - goto deselect_rcu; + router_gw = orig_node_get_router(curr_gw_orig); + if (!router_gw) + goto deselect; /* this node already is the gateway */ if (curr_gw_orig == orig_node) - goto out_rcu; - - if (!orig_node->router) - goto out_rcu; + goto out; - gw_tq_avg = curr_gw_orig->router->tq_avg; - rcu_read_unlock(); + router_orig = orig_node_get_router(orig_node); + if (!router_orig) + goto out; - orig_tq_avg = orig_node->router->tq_avg; + gw_tq_avg = router_gw->tq_avg; + orig_tq_avg = router_orig->tq_avg; /* the TQ value has to be better */ if (orig_tq_avg < gw_tq_avg) @@ -243,18 +252,16 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) "Restarting gateway selection: better gateway found (tq curr: " "%i, tq new: %i)\n", gw_tq_avg, orig_tq_avg); - goto deselect; -out_rcu: - rcu_read_unlock(); - goto out; -deselect_rcu: - rcu_read_unlock(); deselect: gw_deselect(bat_priv); out: if (curr_gw_orig) orig_node_free_ref(curr_gw_orig); + if (router_gw) + neigh_node_free_ref(router_gw); + if (router_orig) + neigh_node_free_ref(router_orig); return; } @@ -362,23 +369,30 @@ void gw_node_purge(struct bat_priv *bat_priv) spin_unlock_bh(&bat_priv->gw_list_lock); } +/** + * fails if orig_node has no router + */ static int _write_buffer_text(struct bat_priv *bat_priv, struct seq_file *seq, struct gw_node *gw_node) { struct gw_node *curr_gw; - int down, up, ret; + struct neigh_node *router; + int down, up, ret = -1; gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up); + router = orig_node_get_router(gw_node->orig_node); + if (!router) + goto out; + rcu_read_lock(); curr_gw = rcu_dereference(bat_priv->curr_gw); ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", (curr_gw == gw_node ? "=>" : " "), gw_node->orig_node->orig, - gw_node->orig_node->router->tq_avg, - gw_node->orig_node->router->addr, - gw_node->orig_node->router->if_incoming->net_dev->name, + router->tq_avg, router->addr, + router->if_incoming->net_dev->name, gw_node->orig_node->gw_flags, (down > 2048 ? down / 1024 : down), (down > 2048 ? "MBit" : "KBit"), @@ -386,6 +400,8 @@ static int _write_buffer_text(struct bat_priv *bat_priv, (up > 2048 ? "MBit" : "KBit")); rcu_read_unlock(); + neigh_node_free_ref(router); +out: return ret; } @@ -423,10 +439,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) if (gw_node->deleted) continue; - if (!gw_node->orig_node->router) + /* fails if orig_node has no router */ + if (_write_buffer_text(bat_priv, seq, gw_node) < 0) continue; - _write_buffer_text(bat_priv, seq, gw_node); gw_count++; } rcu_read_unlock(); diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index 34ce56c358e5..49079c254476 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c @@ -218,23 +218,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) goto dst_unreach; - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, icmp_packet->dst); - if (!orig_node) - goto unlock; - - neigh_node = orig_node->router; + goto dst_unreach; + neigh_node = orig_node_get_router(orig_node); if (!neigh_node) - goto unlock; - - if (!atomic_inc_not_zero(&neigh_node->refcount)) { - neigh_node = NULL; - goto unlock; - } - - rcu_read_unlock(); + goto dst_unreach; if (!neigh_node->if_incoming) goto dst_unreach; @@ -252,8 +242,6 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); goto out; -unlock: - rcu_read_unlock(); dst_unreach: icmp_packet->msg_type = DESTINATION_UNREACHABLE; bat_socket_add_packet(socket_client, icmp_packet, packet_len); diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 0b9133022d2d..b4cfe3686155 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -70,6 +70,21 @@ void neigh_node_free_ref(struct neigh_node *neigh_node) call_rcu(&neigh_node->rcu, neigh_node_free_rcu); } +/* increases the refcounter of a found router */ +struct neigh_node *orig_node_get_router(struct orig_node *orig_node) +{ + struct neigh_node *router; + + rcu_read_lock(); + router = rcu_dereference(orig_node->router); + + if (router && !atomic_inc_not_zero(&router->refcount)) + router = NULL; + + rcu_read_unlock(); + return router; +} + struct neigh_node *create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, @@ -390,7 +405,7 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) struct hlist_node *node, *node_tmp; struct hlist_head *head; struct orig_node *orig_node; - struct neigh_node *neigh_node; + struct neigh_node *neigh_node, *neigh_node_tmp; int batman_count = 0; int last_seen_secs; int last_seen_msecs; @@ -421,37 +436,41 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) rcu_read_lock(); hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { - if (!orig_node->router) + neigh_node = orig_node_get_router(orig_node); + if (!neigh_node) continue; - if (orig_node->router->tq_avg == 0) - continue; + if (neigh_node->tq_avg == 0) + goto next; last_seen_secs = jiffies_to_msecs(jiffies - orig_node->last_valid) / 1000; last_seen_msecs = jiffies_to_msecs(jiffies - orig_node->last_valid) % 1000; - neigh_node = orig_node->router; seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", orig_node->orig, last_seen_secs, last_seen_msecs, neigh_node->tq_avg, neigh_node->addr, neigh_node->if_incoming->net_dev->name); - hlist_for_each_entry_rcu(neigh_node, node_tmp, + hlist_for_each_entry_rcu(neigh_node_tmp, node_tmp, &orig_node->neigh_list, list) { - seq_printf(seq, " %pM (%3i)", neigh_node->addr, - neigh_node->tq_avg); + seq_printf(seq, " %pM (%3i)", + neigh_node_tmp->addr, + neigh_node_tmp->tq_avg); } seq_printf(seq, "\n"); batman_count++; + +next: + neigh_node_free_ref(neigh_node); } rcu_read_unlock(); } - if ((batman_count == 0)) + if (batman_count == 0) seq_printf(seq, "No batman nodes in range ...\n"); return 0; diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 5cc011057da1..e1d641f27aa9 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h @@ -34,6 +34,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node, uint8_t *neigh, struct hard_iface *if_incoming); void neigh_node_free_ref(struct neigh_node *neigh_node); +struct neigh_node *orig_node_get_router(struct orig_node *orig_node); int orig_seq_print_text(struct seq_file *seq, void *offset); int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num); int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num); diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index f212abe745bc..b7d43caaa9c8 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -87,18 +87,20 @@ static void update_route(struct bat_priv *bat_priv, struct neigh_node *neigh_node, unsigned char *hna_buff, int hna_buff_len) { - struct neigh_node *neigh_node_tmp; + struct neigh_node *curr_router; + + curr_router = orig_node_get_router(orig_node); /* route deleted */ - if ((orig_node->router) && (!neigh_node)) { + if ((curr_router) && (!neigh_node)) { bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", orig_node->orig); hna_global_del_orig(bat_priv, orig_node, "originator timed out"); - /* route added */ - } else if ((!orig_node->router) && (neigh_node)) { + /* route added */ + } else if ((!curr_router) && (neigh_node)) { bat_dbg(DBG_ROUTES, bat_priv, "Adding route towards: %pM (via %pM)\n", @@ -106,21 +108,29 @@ static void update_route(struct bat_priv *bat_priv, hna_global_add_orig(bat_priv, orig_node, hna_buff, hna_buff_len); - /* route changed */ + /* route changed */ } else { bat_dbg(DBG_ROUTES, bat_priv, "Changing route towards: %pM " "(now via %pM - was via %pM)\n", orig_node->orig, neigh_node->addr, - orig_node->router->addr); + curr_router->addr); } + if (curr_router) + neigh_node_free_ref(curr_router); + + /* increase refcount of new best neighbor */ if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) neigh_node = NULL; - neigh_node_tmp = orig_node->router; - orig_node->router = neigh_node; - if (neigh_node_tmp) - neigh_node_free_ref(neigh_node_tmp); + + spin_lock_bh(&orig_node->neigh_list_lock); + rcu_assign_pointer(orig_node->router, neigh_node); + spin_unlock_bh(&orig_node->neigh_list_lock); + + /* decrease refcount of previous best neighbor */ + if (curr_router) + neigh_node_free_ref(curr_router); } @@ -128,16 +138,23 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, struct neigh_node *neigh_node, unsigned char *hna_buff, int hna_buff_len) { + struct neigh_node *router = NULL; if (!orig_node) - return; + goto out; + + router = orig_node_get_router(orig_node); - if (orig_node->router != neigh_node) + if (router != neigh_node) update_route(bat_priv, orig_node, neigh_node, hna_buff, hna_buff_len); /* may be just HNA changed */ else update_HNA(bat_priv, orig_node, hna_buff, hna_buff_len); + +out: + if (router) + neigh_node_free_ref(router); } static int is_bidirectional_neigh(struct orig_node *orig_node, @@ -288,8 +305,8 @@ static void bonding_candidate_add(struct orig_node *orig_node, struct neigh_node *neigh_node) { struct hlist_node *node; - struct neigh_node *tmp_neigh_node; - uint8_t best_tq, interference_candidate = 0; + struct neigh_node *tmp_neigh_node, *router = NULL; + uint8_t interference_candidate = 0; spin_lock_bh(&orig_node->neigh_list_lock); @@ -298,13 +315,12 @@ static void bonding_candidate_add(struct orig_node *orig_node, neigh_node->orig_node->primary_addr)) goto candidate_del; - if (!orig_node->router) + router = orig_node_get_router(orig_node); + if (!router) goto candidate_del; - best_tq = orig_node->router->tq_avg; - /* ... and is good enough to be considered */ - if (neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD) + if (neigh_node->tq_avg < router->tq_avg - BONDING_TQ_THRESHOLD) goto candidate_del; /** @@ -350,7 +366,9 @@ candidate_del: out: spin_unlock_bh(&orig_node->neigh_list_lock); - return; + + if (router) + neigh_node_free_ref(router); } /* copy primary address for bonding */ @@ -373,6 +391,7 @@ static void update_orig(struct bat_priv *bat_priv, char is_duplicate) { struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; + struct neigh_node *router = NULL; struct orig_node *orig_node_tmp; struct hlist_node *node; int tmp_hna_buff_len; @@ -441,19 +460,18 @@ static void update_orig(struct bat_priv *bat_priv, /* if this neighbor already is our next hop there is nothing * to change */ - if (orig_node->router == neigh_node) + router = orig_node_get_router(orig_node); + if (router == neigh_node) goto update_hna; /* if this neighbor does not offer a better TQ we won't consider it */ - if ((orig_node->router) && - (orig_node->router->tq_avg > neigh_node->tq_avg)) + if (router && (router->tq_avg > neigh_node->tq_avg)) goto update_hna; /* if the TQ is the same and the link not more symetric we * won't consider it either */ - if ((orig_node->router) && - (neigh_node->tq_avg == orig_node->router->tq_avg)) { - orig_node_tmp = orig_node->router->orig_node; + if (router && (neigh_node->tq_avg == router->tq_avg)) { + orig_node_tmp = router->orig_node; spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); bcast_own_sum_orig = orig_node_tmp->bcast_own_sum[if_incoming->if_num]; @@ -474,7 +492,7 @@ static void update_orig(struct bat_priv *bat_priv, goto update_gw; update_hna: - update_routes(bat_priv, orig_node, orig_node->router, + update_routes(bat_priv, orig_node, router, hna_buff, tmp_hna_buff_len); update_gw: @@ -496,6 +514,8 @@ unlock: out: if (neigh_node) neigh_node_free_ref(neigh_node); + if (router) + neigh_node_free_ref(router); } /* checks whether the host restarted and is in the protection time. @@ -603,6 +623,8 @@ void receive_bat_packet(struct ethhdr *ethhdr, struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); struct hard_iface *hard_iface; struct orig_node *orig_neigh_node, *orig_node; + struct neigh_node *router = NULL, *router_router = NULL; + struct neigh_node *orig_neigh_router = NULL; char has_directlink_flag; char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; @@ -747,14 +769,15 @@ void receive_bat_packet(struct ethhdr *ethhdr, goto out; } + router = orig_node_get_router(orig_node); + if (router) + router_router = orig_node_get_router(router->orig_node); + /* avoid temporary routing loops */ - if ((orig_node->router) && - (orig_node->router->orig_node->router) && - (compare_eth(orig_node->router->addr, - batman_packet->prev_sender)) && + if (router && router_router && + (compare_eth(router->addr, batman_packet->prev_sender)) && !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) && - (compare_eth(orig_node->router->addr, - orig_node->router->orig_node->router->addr))) { + (compare_eth(router->addr, router_router->addr))) { bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: ignoring all rebroadcast packets that " "may make me loop (sender: %pM)\n", ethhdr->h_source); @@ -769,9 +792,11 @@ void receive_bat_packet(struct ethhdr *ethhdr, if (!orig_neigh_node) goto out; + orig_neigh_router = orig_node_get_router(orig_neigh_node); + /* drop packet if sender is not a direct neighbor and if we * don't route towards it */ - if (!is_single_hop_neigh && (!orig_neigh_node->router)) { + if (!is_single_hop_neigh && (!orig_neigh_router)) { bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: OGM via unknown neighbor!\n"); goto out_neigh; @@ -825,6 +850,13 @@ out_neigh: if ((orig_neigh_node) && (!is_single_hop_neigh)) orig_node_free_ref(orig_neigh_node); out: + if (router) + neigh_node_free_ref(router); + if (router_router) + neigh_node_free_ref(router_router); + if (orig_neigh_router) + neigh_node_free_ref(orig_neigh_router); + orig_node_free_ref(orig_node); } @@ -869,7 +901,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, struct sk_buff *skb, size_t icmp_len) { struct orig_node *orig_node = NULL; - struct neigh_node *neigh_node = NULL; + struct neigh_node *router = NULL; struct icmp_packet_rr *icmp_packet; int ret = NET_RX_DROP; @@ -886,23 +918,13 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, /* answer echo request (ping) */ /* get routing information */ - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, icmp_packet->orig); - if (!orig_node) - goto unlock; - - neigh_node = orig_node->router; - - if (!neigh_node) - goto unlock; - - if (!atomic_inc_not_zero(&neigh_node->refcount)) { - neigh_node = NULL; - goto unlock; - } + goto out; - rcu_read_unlock(); + router = orig_node_get_router(orig_node); + if (!router) + goto out; /* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) @@ -916,15 +938,12 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, icmp_packet->msg_type = ECHO_REPLY; icmp_packet->ttl = TTL; - send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); + send_skb_packet(skb, router->if_incoming, router->addr); ret = NET_RX_SUCCESS; - goto out; -unlock: - rcu_read_unlock(); out: - if (neigh_node) - neigh_node_free_ref(neigh_node); + if (router) + neigh_node_free_ref(router); if (orig_node) orig_node_free_ref(orig_node); return ret; @@ -934,7 +953,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, struct sk_buff *skb) { struct orig_node *orig_node = NULL; - struct neigh_node *neigh_node = NULL; + struct neigh_node *router = NULL; struct icmp_packet *icmp_packet; int ret = NET_RX_DROP; @@ -952,23 +971,13 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, goto out; /* get routing information */ - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, icmp_packet->orig); - if (!orig_node) - goto unlock; - - neigh_node = orig_node->router; - - if (!neigh_node) - goto unlock; - - if (!atomic_inc_not_zero(&neigh_node->refcount)) { - neigh_node = NULL; - goto unlock; - } + goto out; - rcu_read_unlock(); + router = orig_node_get_router(orig_node); + if (!router) + goto out; /* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) @@ -982,15 +991,12 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, icmp_packet->msg_type = TTL_EXCEEDED; icmp_packet->ttl = TTL; - send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); + send_skb_packet(skb, router->if_incoming, router->addr); ret = NET_RX_SUCCESS; - goto out; -unlock: - rcu_read_unlock(); out: - if (neigh_node) - neigh_node_free_ref(neigh_node); + if (router) + neigh_node_free_ref(router); if (orig_node) orig_node_free_ref(orig_node); return ret; @@ -1003,7 +1009,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) struct icmp_packet_rr *icmp_packet; struct ethhdr *ethhdr; struct orig_node *orig_node = NULL; - struct neigh_node *neigh_node = NULL; + struct neigh_node *router = NULL; int hdr_size = sizeof(struct icmp_packet); int ret = NET_RX_DROP; @@ -1050,23 +1056,13 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) return recv_icmp_ttl_exceeded(bat_priv, skb); /* get routing information */ - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, icmp_packet->dst); - if (!orig_node) - goto unlock; - - neigh_node = orig_node->router; - - if (!neigh_node) - goto unlock; - - if (!atomic_inc_not_zero(&neigh_node->refcount)) { - neigh_node = NULL; - goto unlock; - } + goto out; - rcu_read_unlock(); + router = orig_node_get_router(orig_node); + if (!router) + goto out; /* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) @@ -1078,15 +1074,12 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) icmp_packet->ttl--; /* route it */ - send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); + send_skb_packet(skb, router->if_incoming, router->addr); ret = NET_RX_SUCCESS; - goto out; -unlock: - rcu_read_unlock(); out: - if (neigh_node) - neigh_node_free_ref(neigh_node); + if (router) + neigh_node_free_ref(router); if (orig_node) orig_node_free_ref(orig_node); return ret; @@ -1208,7 +1201,8 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, if (!orig_node) return NULL; - if (!orig_node->router) + router = orig_node_get_router(orig_node); + if (!router) return NULL; /* without bonding, the first node should @@ -1217,9 +1211,8 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, rcu_read_lock(); /* select default router to output */ - router = orig_node->router; - router_orig = orig_node->router->orig_node; - if (!router_orig || !atomic_inc_not_zero(&router->refcount)) { + router_orig = router->orig_node; + if (!router_orig) { rcu_read_unlock(); return NULL; } @@ -1251,7 +1244,6 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, if (atomic_read(&primary_orig_node->bond_candidates) < 2) goto return_router; - /* all nodes between should choose a candidate which * is is not on the interface where the packet came * in. */ diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index d49e54d932af..e78670c3c4b7 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -308,6 +308,7 @@ void schedule_forward_packet(struct orig_node *orig_node, struct hard_iface *if_incoming) { struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); + struct neigh_node *router; unsigned char in_tq, in_ttl, tq_avg = 0; unsigned long send_time; @@ -316,6 +317,8 @@ void schedule_forward_packet(struct orig_node *orig_node, return; } + router = orig_node_get_router(orig_node); + in_tq = batman_packet->tq; in_ttl = batman_packet->ttl; @@ -324,20 +327,22 @@ void schedule_forward_packet(struct orig_node *orig_node, /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast * of our best tq value */ - if ((orig_node->router) && (orig_node->router->tq_avg != 0)) { + if (router && router->tq_avg != 0) { /* rebroadcast ogm of best ranking neighbor as is */ - if (!compare_eth(orig_node->router->addr, ethhdr->h_source)) { - batman_packet->tq = orig_node->router->tq_avg; + if (!compare_eth(router->addr, ethhdr->h_source)) { + batman_packet->tq = router->tq_avg; - if (orig_node->router->last_ttl) - batman_packet->ttl = orig_node->router->last_ttl - - 1; + if (router->last_ttl) + batman_packet->ttl = router->last_ttl - 1; } - tq_avg = orig_node->router->tq_avg; + tq_avg = router->tq_avg; } + if (router) + neigh_node_free_ref(router); + /* apply hop penalty */ batman_packet->tq = hop_penalty(batman_packet->tq, bat_priv); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 83445cf0cc9f..1854cbb4c1b6 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -67,7 +67,7 @@ struct hard_iface { struct orig_node { uint8_t orig[ETH_ALEN]; uint8_t primary_addr[ETH_ALEN]; - struct neigh_node *router; + struct neigh_node __rcu *router; /* rcu protected pointer */ unsigned long *bcast_own; uint8_t *bcast_own_sum; unsigned long last_valid; @@ -83,7 +83,7 @@ struct orig_node { uint32_t last_bcast_seqno; struct hlist_head neigh_list; struct list_head frag_list; - spinlock_t neigh_list_lock; /* protects neighbor list */ + spinlock_t neigh_list_lock; /* protects neigh_list and router */ atomic_t refcount; struct rcu_head rcu; struct hlist_node hash_entry; diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index f90212f42082..d4cc4f5399f4 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c @@ -558,6 +558,7 @@ static int find_best_vis_server(struct bat_priv *bat_priv, struct vis_info *info) { struct hashtable_t *hash = bat_priv->orig_hash; + struct neigh_node *router; struct hlist_node *node; struct hlist_head *head; struct orig_node *orig_node; @@ -571,13 +572,17 @@ static int find_best_vis_server(struct bat_priv *bat_priv, rcu_read_lock(); hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { - if ((orig_node) && (orig_node->router) && - (orig_node->flags & VIS_SERVER) && - (orig_node->router->tq_avg > best_tq)) { - best_tq = orig_node->router->tq_avg; + router = orig_node_get_router(orig_node); + if (!router) + continue; + + if ((orig_node->flags & VIS_SERVER) && + (router->tq_avg > best_tq)) { + best_tq = router->tq_avg; memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); } + neigh_node_free_ref(router); } rcu_read_unlock(); } @@ -605,7 +610,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv) struct hlist_node *node; struct hlist_head *head; struct orig_node *orig_node; - struct neigh_node *neigh_node; + struct neigh_node *router; struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; struct vis_info_entry *entry; @@ -633,30 +638,32 @@ static int generate_vis_packet(struct bat_priv *bat_priv) rcu_read_lock(); hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { - neigh_node = orig_node->router; - - if (!neigh_node) + router = orig_node_get_router(orig_node); + if (!router) continue; - if (!compare_eth(neigh_node->addr, orig_node->orig)) - continue; + if (!compare_eth(router->addr, orig_node->orig)) + goto next; - if (neigh_node->if_incoming->if_status != IF_ACTIVE) - continue; + if (router->if_incoming->if_status != IF_ACTIVE) + goto next; - if (neigh_node->tq_avg < 1) - continue; + if (router->tq_avg < 1) + goto next; /* fill one entry into buffer. */ entry = (struct vis_info_entry *) skb_put(info->skb_packet, sizeof(*entry)); memcpy(entry->src, - neigh_node->if_incoming->net_dev->dev_addr, + router->if_incoming->net_dev->dev_addr, ETH_ALEN); memcpy(entry->dest, orig_node->orig, ETH_ALEN); - entry->quality = neigh_node->tq_avg; + entry->quality = router->tq_avg; packet->entries++; +next: + neigh_node_free_ref(router); + if (vis_packet_full(info)) goto unlock; } @@ -725,6 +732,7 @@ static void purge_vis_packets(struct bat_priv *bat_priv) static void broadcast_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) { + struct neigh_node *router; struct hashtable_t *hash = bat_priv->orig_hash; struct hlist_node *node; struct hlist_head *head; @@ -745,19 +753,26 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv, rcu_read_lock(); hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { /* if it's a vis server and reachable, send it. */ - if ((!orig_node) || (!orig_node->router)) - continue; if (!(orig_node->flags & VIS_SERVER)) continue; + + router = orig_node_get_router(orig_node); + if (!router) + continue; + /* don't send it if we already received the packet from - * this node. */ + * this node. */ if (recv_list_is_in(bat_priv, &info->recv_list, - orig_node->orig)) + orig_node->orig)) { + neigh_node_free_ref(router); continue; + } memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); - hard_iface = orig_node->router->if_incoming; - memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); + hard_iface = router->if_incoming; + memcpy(dstaddr, router->addr, ETH_ALEN); + + neigh_node_free_ref(router); skb = skb_clone(info->skb_packet, GFP_ATOMIC); if (skb) @@ -772,45 +787,29 @@ static void unicast_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) { struct orig_node *orig_node; - struct neigh_node *neigh_node = NULL; + struct neigh_node *router = NULL; struct sk_buff *skb; struct vis_packet *packet; packet = (struct vis_packet *)info->skb_packet->data; - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, packet->target_orig); - if (!orig_node) - goto unlock; + goto out; - neigh_node = orig_node->router; - - if (!neigh_node) - goto unlock; - - if (!atomic_inc_not_zero(&neigh_node->refcount)) { - neigh_node = NULL; - goto unlock; - } - - rcu_read_unlock(); + router = orig_node_get_router(orig_node); + if (!router) + goto out; skb = skb_clone(info->skb_packet, GFP_ATOMIC); if (skb) - send_skb_packet(skb, neigh_node->if_incoming, - neigh_node->addr); - - goto out; + send_skb_packet(skb, router->if_incoming, router->addr); -unlock: - rcu_read_unlock(); out: - if (neigh_node) - neigh_node_free_ref(neigh_node); + if (router) + neigh_node_free_ref(router); if (orig_node) orig_node_free_ref(orig_node); - return; } /* only send one vis packet. called from send_vis_packets() */ -- cgit v1.2.3-58-ga151 From 68003903e4eeec5288f074ff0751a381750ceb34 Mon Sep 17 00:00:00 2001 From: Linus Lüssing Date: Mon, 14 Mar 2011 22:43:40 +0000 Subject: batman-adv: Protect global TQ window with a spinlock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/originator.c | 1 + net/batman-adv/routing.c | 4 ++++ net/batman-adv/types.h | 1 + 3 files changed, 6 insertions(+) diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index b4cfe3686155..5b8fe32043da 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -102,6 +102,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node, INIT_HLIST_NODE(&neigh_node->list); INIT_LIST_HEAD(&neigh_node->bonding_list); + spin_lock_init(&neigh_node->tq_lock); memcpy(neigh_node->addr, neigh, ETH_ALEN); neigh_node->orig_node = orig_neigh_node; diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index b7d43caaa9c8..f6c642246972 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -415,10 +415,12 @@ static void update_orig(struct bat_priv *bat_priv, if (is_duplicate) continue; + spin_lock_bh(&tmp_neigh_node->tq_lock); ring_buffer_set(tmp_neigh_node->tq_recv, &tmp_neigh_node->tq_index, 0); tmp_neigh_node->tq_avg = ring_buffer_avg(tmp_neigh_node->tq_recv); + spin_unlock_bh(&tmp_neigh_node->tq_lock); } if (!neigh_node) { @@ -443,10 +445,12 @@ static void update_orig(struct bat_priv *bat_priv, orig_node->flags = batman_packet->flags; neigh_node->last_valid = jiffies; + spin_lock_bh(&neigh_node->tq_lock); ring_buffer_set(neigh_node->tq_recv, &neigh_node->tq_index, batman_packet->tq); neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv); + spin_unlock_bh(&neigh_node->tq_lock); if (!is_duplicate) { orig_node->last_ttl = batman_packet->ttl; diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 1854cbb4c1b6..091476df4f0e 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -125,6 +125,7 @@ struct neigh_node { struct rcu_head rcu; struct orig_node *orig_node; struct hard_iface *if_incoming; + spinlock_t tq_lock; /* protects: tq_recv, tq_index */ }; -- cgit v1.2.3-58-ga151 From c4aac1ab9b973798163b34939b522f01e4d28ac9 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Wed, 23 Mar 2011 11:24:34 +0100 Subject: batman-adv: concentrate all curr_gw related rcu operations in select/deselect functions Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/gateway_client.c | 170 +++++++++++++++++++++++----------------- net/batman-adv/gateway_client.h | 2 +- net/batman-adv/unicast.c | 2 +- 3 files changed, 100 insertions(+), 74 deletions(-) diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 42a8a7ba06e6..2acd7a666bda 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -43,61 +43,75 @@ static void gw_node_free_ref(struct gw_node *gw_node) call_rcu(&gw_node->rcu, gw_node_free_rcu); } -struct orig_node *gw_get_selected(struct bat_priv *bat_priv) +static struct gw_node *gw_get_selected_gw_node(struct bat_priv *bat_priv) { - struct gw_node *curr_gateway_tmp; - struct orig_node *orig_node = NULL; + struct gw_node *gw_node; rcu_read_lock(); - curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw); - if (!curr_gateway_tmp) - goto out; - - orig_node = curr_gateway_tmp->orig_node; - if (!orig_node) + gw_node = rcu_dereference(bat_priv->curr_gw); + if (!gw_node) goto out; - if (!atomic_inc_not_zero(&orig_node->refcount)) - orig_node = NULL; + if (!atomic_inc_not_zero(&gw_node->refcount)) + gw_node = NULL; out: rcu_read_unlock(); - return orig_node; + return gw_node; } -void gw_deselect(struct bat_priv *bat_priv) +struct orig_node *gw_get_selected_orig(struct bat_priv *bat_priv) { struct gw_node *gw_node; + struct orig_node *orig_node = NULL; - spin_lock_bh(&bat_priv->gw_list_lock); - gw_node = rcu_dereference(bat_priv->curr_gw); - rcu_assign_pointer(bat_priv->curr_gw, NULL); - spin_unlock_bh(&bat_priv->gw_list_lock); + gw_node = gw_get_selected_gw_node(bat_priv); + if (!gw_node) + goto out; + + rcu_read_lock(); + orig_node = gw_node->orig_node; + if (!orig_node) + goto unlock; + + if (!atomic_inc_not_zero(&orig_node->refcount)) + orig_node = NULL; +unlock: + rcu_read_unlock(); +out: if (gw_node) gw_node_free_ref(gw_node); + return orig_node; } static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node) { struct gw_node *curr_gw_node; + spin_lock_bh(&bat_priv->gw_list_lock); + if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount)) new_gw_node = NULL; - spin_lock_bh(&bat_priv->gw_list_lock); - curr_gw_node = rcu_dereference(bat_priv->curr_gw); + curr_gw_node = bat_priv->curr_gw; rcu_assign_pointer(bat_priv->curr_gw, new_gw_node); - spin_unlock_bh(&bat_priv->gw_list_lock); if (curr_gw_node) gw_node_free_ref(curr_gw_node); + + spin_unlock_bh(&bat_priv->gw_list_lock); +} + +void gw_deselect(struct bat_priv *bat_priv) +{ + gw_select(bat_priv, NULL); } void gw_election(struct bat_priv *bat_priv) { struct hlist_node *node; - struct gw_node *gw_node, *curr_gw, *curr_gw_tmp = NULL; + struct gw_node *gw_node, *curr_gw = NULL, *curr_gw_tmp = NULL; struct neigh_node *router; uint8_t max_tq = 0; uint32_t max_gw_factor = 0, tmp_gw_factor = 0; @@ -112,25 +126,17 @@ void gw_election(struct bat_priv *bat_priv) if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT) return; - rcu_read_lock(); - curr_gw = rcu_dereference(bat_priv->curr_gw); - if (curr_gw) { - rcu_read_unlock(); - return; - } + curr_gw = gw_get_selected_gw_node(bat_priv); + if (!curr_gw) + goto out; + rcu_read_lock(); if (hlist_empty(&bat_priv->gw_list)) { - - if (curr_gw) { - rcu_read_unlock(); - bat_dbg(DBG_BATMAN, bat_priv, - "Removing selected gateway - " - "no gateway in range\n"); - gw_deselect(bat_priv); - } else - rcu_read_unlock(); - - return; + bat_dbg(DBG_BATMAN, bat_priv, + "Removing selected gateway - " + "no gateway in range\n"); + gw_deselect(bat_priv); + goto unlock; } hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { @@ -182,7 +188,7 @@ void gw_election(struct bat_priv *bat_priv) if (curr_gw != curr_gw_tmp) { router = orig_node_get_router(curr_gw_tmp->orig_node); if (!router) - goto out; + goto unlock; if ((curr_gw) && (!curr_gw_tmp)) bat_dbg(DBG_BATMAN, bat_priv, @@ -207,8 +213,11 @@ void gw_election(struct bat_priv *bat_priv) gw_select(bat_priv, curr_gw_tmp); } -out: +unlock: rcu_read_unlock(); +out: + if (curr_gw) + gw_node_free_ref(curr_gw); } void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) @@ -217,7 +226,7 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) struct neigh_node *router_gw = NULL, *router_orig = NULL; uint8_t gw_tq_avg, orig_tq_avg; - curr_gw_orig = gw_get_selected(bat_priv); + curr_gw_orig = gw_get_selected_orig(bat_priv); if (!curr_gw_orig) goto deselect; @@ -299,7 +308,11 @@ void gw_node_update(struct bat_priv *bat_priv, struct orig_node *orig_node, uint8_t new_gwflags) { struct hlist_node *node; - struct gw_node *gw_node; + struct gw_node *gw_node, *curr_gw; + + curr_gw = gw_get_selected_gw_node(bat_priv); + if (!curr_gw) + goto out; rcu_read_lock(); hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { @@ -320,22 +333,26 @@ void gw_node_update(struct bat_priv *bat_priv, "Gateway %pM removed from gateway list\n", orig_node->orig); - if (gw_node == rcu_dereference(bat_priv->curr_gw)) { - rcu_read_unlock(); - gw_deselect(bat_priv); - return; - } + if (gw_node == curr_gw) + goto deselect; } - rcu_read_unlock(); - return; + goto unlock; } - rcu_read_unlock(); if (new_gwflags == 0) - return; + goto unlock; gw_node_add(bat_priv, orig_node, new_gwflags); + goto unlock; + +deselect: + gw_deselect(bat_priv); +unlock: + rcu_read_unlock(); +out: + if (curr_gw) + gw_node_free_ref(curr_gw); } void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node) @@ -345,9 +362,12 @@ void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node) void gw_node_purge(struct bat_priv *bat_priv) { - struct gw_node *gw_node; + struct gw_node *gw_node, *curr_gw; struct hlist_node *node, *node_tmp; unsigned long timeout = 2 * PURGE_TIMEOUT * HZ; + char do_deselect = 0; + + curr_gw = gw_get_selected_gw_node(bat_priv); spin_lock_bh(&bat_priv->gw_list_lock); @@ -358,15 +378,21 @@ void gw_node_purge(struct bat_priv *bat_priv) atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) continue; - if (rcu_dereference(bat_priv->curr_gw) == gw_node) - gw_deselect(bat_priv); + if (curr_gw == gw_node) + do_deselect = 1; hlist_del_rcu(&gw_node->list); gw_node_free_ref(gw_node); } - spin_unlock_bh(&bat_priv->gw_list_lock); + + /* gw_deselect() needs to acquire the gw_list_lock */ + if (do_deselect) + gw_deselect(bat_priv); + + if (curr_gw) + gw_node_free_ref(curr_gw); } /** @@ -385,22 +411,22 @@ static int _write_buffer_text(struct bat_priv *bat_priv, if (!router) goto out; - rcu_read_lock(); - curr_gw = rcu_dereference(bat_priv->curr_gw); + curr_gw = gw_get_selected_gw_node(bat_priv); ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", - (curr_gw == gw_node ? "=>" : " "), - gw_node->orig_node->orig, - router->tq_avg, router->addr, - router->if_incoming->net_dev->name, - gw_node->orig_node->gw_flags, - (down > 2048 ? down / 1024 : down), - (down > 2048 ? "MBit" : "KBit"), - (up > 2048 ? up / 1024 : up), - (up > 2048 ? "MBit" : "KBit")); + (curr_gw == gw_node ? "=>" : " "), + gw_node->orig_node->orig, + router->tq_avg, router->addr, + router->if_incoming->net_dev->name, + gw_node->orig_node->gw_flags, + (down > 2048 ? down / 1024 : down), + (down > 2048 ? "MBit" : "KBit"), + (up > 2048 ? up / 1024 : up), + (up > 2048 ? "MBit" : "KBit")); - rcu_read_unlock(); neigh_node_free_ref(router); + if (curr_gw) + gw_node_free_ref(curr_gw); out: return ret; } @@ -459,6 +485,7 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) struct iphdr *iphdr; struct ipv6hdr *ipv6hdr; struct udphdr *udphdr; + struct gw_node *curr_gw; unsigned int header_len = 0; if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF) @@ -523,12 +550,11 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER) return -1; - rcu_read_lock(); - if (!rcu_dereference(bat_priv->curr_gw)) { - rcu_read_unlock(); + curr_gw = gw_get_selected_gw_node(bat_priv); + if (!curr_gw) return 0; - } - rcu_read_unlock(); + if (curr_gw) + gw_node_free_ref(curr_gw); return 1; } diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h index 97c31d178163..1ce8c6066da1 100644 --- a/net/batman-adv/gateway_client.h +++ b/net/batman-adv/gateway_client.h @@ -24,7 +24,7 @@ void gw_deselect(struct bat_priv *bat_priv); void gw_election(struct bat_priv *bat_priv); -struct orig_node *gw_get_selected(struct bat_priv *bat_priv); +struct orig_node *gw_get_selected_orig(struct bat_priv *bat_priv); void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node); void gw_node_update(struct bat_priv *bat_priv, struct orig_node *orig_node, uint8_t new_gwflags); diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index 19f84bd443af..d46acc815138 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c @@ -289,7 +289,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) /* get routing information */ if (is_multicast_ether_addr(ethhdr->h_dest)) { - orig_node = (struct orig_node *)gw_get_selected(bat_priv); + orig_node = (struct orig_node *)gw_get_selected_orig(bat_priv); if (orig_node) goto find_router; } -- cgit v1.2.3-58-ga151 From ba85fac28005a59e6e03fdb13918fc6f6e69a3ca Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Sun, 17 Apr 2011 20:34:27 +0200 Subject: batman-adv: protect softif_neigh by rcu Add get/set wrapper functions for softif_neigh and use rcu functions to manipulate the pointers. Signed-off-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/soft-interface.c | 114 ++++++++++++++++++++++++++++++---------- net/batman-adv/types.h | 2 +- 2 files changed, 88 insertions(+), 28 deletions(-) diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 9ed26140a269..ad6da4c7ddb5 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -90,10 +90,51 @@ static void softif_neigh_free_ref(struct softif_neigh *softif_neigh) call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu); } +static struct softif_neigh *softif_neigh_get_selected(struct bat_priv *bat_priv) +{ + struct softif_neigh *neigh; + + rcu_read_lock(); + neigh = rcu_dereference(bat_priv->softif_neigh); + + if (neigh && !atomic_inc_not_zero(&neigh->refcount)) + neigh = NULL; + + rcu_read_unlock(); + return neigh; +} + +static void softif_neigh_select(struct bat_priv *bat_priv, + struct softif_neigh *new_neigh) +{ + struct softif_neigh *curr_neigh; + + spin_lock_bh(&bat_priv->softif_neigh_lock); + + if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount)) + new_neigh = NULL; + + curr_neigh = bat_priv->softif_neigh; + rcu_assign_pointer(bat_priv->softif_neigh, new_neigh); + + if (curr_neigh) + softif_neigh_free_ref(curr_neigh); + + spin_unlock_bh(&bat_priv->softif_neigh_lock); +} + +static void softif_neigh_deselect(struct bat_priv *bat_priv) +{ + softif_neigh_select(bat_priv, NULL); +} + void softif_neigh_purge(struct bat_priv *bat_priv) { - struct softif_neigh *softif_neigh, *softif_neigh_tmp; + struct softif_neigh *softif_neigh, *curr_softif_neigh; struct hlist_node *node, *node_tmp; + char do_deselect = 0; + + curr_softif_neigh = softif_neigh_get_selected(bat_priv); spin_lock_bh(&bat_priv->softif_neigh_lock); @@ -105,22 +146,26 @@ void softif_neigh_purge(struct bat_priv *bat_priv) (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) continue; - hlist_del_rcu(&softif_neigh->list); - - if (bat_priv->softif_neigh == softif_neigh) { + if (curr_softif_neigh == softif_neigh) { bat_dbg(DBG_ROUTES, bat_priv, "Current mesh exit point '%pM' vanished " "(vid: %d).\n", softif_neigh->addr, softif_neigh->vid); - softif_neigh_tmp = bat_priv->softif_neigh; - bat_priv->softif_neigh = NULL; - softif_neigh_free_ref(softif_neigh_tmp); + do_deselect = 1; } + hlist_del_rcu(&softif_neigh->list); softif_neigh_free_ref(softif_neigh); } spin_unlock_bh(&bat_priv->softif_neigh_lock); + + /* soft_neigh_deselect() needs to acquire the softif_neigh_lock */ + if (do_deselect) + softif_neigh_deselect(bat_priv); + + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); } static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv, @@ -171,6 +216,7 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) struct bat_priv *bat_priv = netdev_priv(net_dev); struct softif_neigh *softif_neigh; struct hlist_node *node; + struct softif_neigh *curr_softif_neigh; if (!bat_priv->primary_if) { return seq_printf(seq, "BATMAN mesh %s disabled - " @@ -180,14 +226,17 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); + curr_softif_neigh = softif_neigh_get_selected(bat_priv); rcu_read_lock(); hlist_for_each_entry_rcu(softif_neigh, node, &bat_priv->softif_neigh_list, list) seq_printf(seq, "%s %pM (vid: %d)\n", - bat_priv->softif_neigh == softif_neigh + curr_softif_neigh == softif_neigh ? "=>" : " ", softif_neigh->addr, softif_neigh->vid); rcu_read_unlock(); + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); return 0; } @@ -198,7 +247,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, struct bat_priv *bat_priv = netdev_priv(dev); struct ethhdr *ethhdr = (struct ethhdr *)skb->data; struct batman_packet *batman_packet; - struct softif_neigh *softif_neigh, *softif_neigh_tmp; + struct softif_neigh *softif_neigh; + struct softif_neigh *curr_softif_neigh = NULL; if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) batman_packet = (struct batman_packet *) @@ -223,7 +273,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, if (!softif_neigh) goto err; - if (bat_priv->softif_neigh == softif_neigh) + curr_softif_neigh = softif_neigh_get_selected(bat_priv); + if (curr_softif_neigh == softif_neigh) goto out; /* we got a neighbor but its mac is 'bigger' than ours */ @@ -232,38 +283,39 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, goto out; /* switch to new 'smallest neighbor' */ - if ((bat_priv->softif_neigh) && - (memcmp(softif_neigh->addr, bat_priv->softif_neigh->addr, + if ((curr_softif_neigh) && + (memcmp(softif_neigh->addr, curr_softif_neigh->addr, ETH_ALEN) < 0)) { bat_dbg(DBG_ROUTES, bat_priv, "Changing mesh exit point from %pM (vid: %d) " "to %pM (vid: %d).\n", - bat_priv->softif_neigh->addr, - bat_priv->softif_neigh->vid, + curr_softif_neigh->addr, + curr_softif_neigh->vid, softif_neigh->addr, softif_neigh->vid); - softif_neigh_tmp = bat_priv->softif_neigh; - bat_priv->softif_neigh = softif_neigh; - softif_neigh_free_ref(softif_neigh_tmp); - /* we need to hold the additional reference */ - goto err; + + softif_neigh_select(bat_priv, softif_neigh); + goto out; } /* close own batX device and use softif_neigh as exit node */ - if ((!bat_priv->softif_neigh) && + if ((!curr_softif_neigh) && (memcmp(softif_neigh->addr, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) { bat_dbg(DBG_ROUTES, bat_priv, "Setting mesh exit point to %pM (vid: %d).\n", softif_neigh->addr, softif_neigh->vid); - bat_priv->softif_neigh = softif_neigh; - /* we need to hold the additional reference */ - goto err; + + softif_neigh_select(bat_priv, softif_neigh); + goto out; } out: softif_neigh_free_ref(softif_neigh); err: kfree_skb(skb); + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); + return; } @@ -321,6 +373,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) struct bat_priv *bat_priv = netdev_priv(soft_iface); struct bcast_packet *bcast_packet; struct vlan_ethhdr *vhdr; + struct softif_neigh *curr_softif_neigh = NULL; int data_len = skb->len, ret; short vid = -1; bool do_bcast = false; @@ -348,7 +401,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) * if we have a another chosen mesh exit node in range * it will transport the packets to the mesh */ - if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) + curr_softif_neigh = softif_neigh_get_selected(bat_priv); + if ((curr_softif_neigh) && (curr_softif_neigh->vid == vid)) goto dropped; /* TODO: check this for locks */ @@ -410,6 +464,8 @@ dropped: dropped_freed: bat_priv->stats.tx_dropped++; end: + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); return NETDEV_TX_OK; } @@ -421,6 +477,7 @@ void interface_rx(struct net_device *soft_iface, struct unicast_packet *unicast_packet; struct ethhdr *ethhdr; struct vlan_ethhdr *vhdr; + struct softif_neigh *curr_softif_neigh = NULL; short vid = -1; int ret; @@ -450,7 +507,8 @@ void interface_rx(struct net_device *soft_iface, * if we have a another chosen mesh exit node in range * it will transport the packets to the non-mesh network */ - if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) { + curr_softif_neigh = softif_neigh_get_selected(bat_priv); + if (curr_softif_neigh && (curr_softif_neigh->vid == vid)) { skb_push(skb, hdr_size); unicast_packet = (struct unicast_packet *)skb->data; @@ -461,7 +519,7 @@ void interface_rx(struct net_device *soft_iface, skb_reset_mac_header(skb); memcpy(unicast_packet->dest, - bat_priv->softif_neigh->addr, ETH_ALEN); + curr_softif_neigh->addr, ETH_ALEN); ret = route_unicast_packet(skb, recv_if); if (ret == NET_RX_DROP) goto dropped; @@ -486,11 +544,13 @@ void interface_rx(struct net_device *soft_iface, soft_iface->last_rx = jiffies; netif_rx(skb); - return; + goto out; dropped: kfree_skb(skb); out: + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); return; } diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 091476df4f0e..75123b1ae0de 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -147,7 +147,7 @@ struct bat_priv { atomic_t batman_queue_left; char num_ifaces; struct hlist_head softif_neigh_list; - struct softif_neigh *softif_neigh; + struct softif_neigh __rcu *softif_neigh; struct debug_log *debug_log; struct hard_iface *primary_if; struct kobject *mesh_obj; -- cgit v1.2.3-58-ga151 From af20b710479ae662829cf739b521390daa7fcbcb Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 17 Apr 2011 20:39:07 +0200 Subject: batman-adv: Set the txqueuelen to zero when creating soft interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Like other virtual interfaces, e.g. br0, we don't need a transmit queue. Packets should only be queued on real interfaces which are underneath. In practice this patch makes little difference since the virtual interfaces can accept packets as fast as they come, but the patch will avoid bufferbloat questions to the mailling lists in the future. Signed-off-by: Andrew Lunn Tested-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/soft-interface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index ad6da4c7ddb5..58ce4400d581 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -584,6 +584,7 @@ static void interface_setup(struct net_device *dev) dev->hard_start_xmit = interface_tx; #endif dev->destructor = free_netdev; + dev->tx_queue_len = 0; /** * can't call min_mtu, because the needed variables -- cgit v1.2.3-58-ga151 From a713c3bbb5a6736e673940eb97d9bf2c27aec4c5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:22:33 -0700 Subject: isdn: gigaset: Fix set-but-unused variable. The variable 'offset' is set but unused in write_iso_tasklet(). Just kill it off. Signed-off-by: David S. Miller --- drivers/isdn/gigaset/bas-gigaset.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 8a3c5cfc4fea..3913f47ef86d 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -1157,7 +1157,6 @@ static void write_iso_tasklet(unsigned long data) struct urb *urb; int status; struct usb_iso_packet_descriptor *ifd; - int offset; unsigned long flags; int i; struct sk_buff *skb; @@ -1225,7 +1224,6 @@ static void write_iso_tasklet(unsigned long data) * successfully sent * - all following frames are not sent at all */ - offset = done->limit; /* default (no error) */ for (i = 0; i < BAS_NUMFRAMES; i++) { ifd = &urb->iso_frame_desc[i]; if (ifd->status || @@ -1235,9 +1233,6 @@ static void write_iso_tasklet(unsigned long data) i, ifd->actual_length, ifd->length, get_usb_statmsg(ifd->status)); - offset = (ifd->offset + - ifd->actual_length) - % BAS_OUTBUFSIZE; break; } } -- cgit v1.2.3-58-ga151 From 2d09d567127e85dddd027d049196093640025c36 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:23:22 -0700 Subject: isdn: eicon: Fix set-but-unused variables. The variable 'best_id' is set but unused in diva_mnt_add_xdi_adapter(). Just kill it off. Similarly for the variable 'CIP' in connect_req(), 'Number' in sig_ind(), 'Info' in dtmf_confirmation() mixer_command() fax_connect_ack_command() fax_edata_ack_command() rtp_connect_b3_res_command() and rtp_connect_b3_res_command(), and 'a' in mixer_indication_coefs_set(), Signed-off-by: David S. Miller --- drivers/isdn/hardware/eicon/debug.c | 3 +-- drivers/isdn/hardware/eicon/message.c | 23 ++--------------------- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c index 362640120886..7a9894cb4557 100644 --- a/drivers/isdn/hardware/eicon/debug.c +++ b/drivers/isdn/hardware/eicon/debug.c @@ -861,7 +861,7 @@ static int diva_get_idi_adapter_info (IDI_CALL request, dword* serial, dword* lo void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { diva_os_spin_lock_magic_t old_irql, old_irql1; dword sec, usec, logical, serial, org_mask; - int id, best_id = 0, free_id = -1; + int id, free_id = -1; char tmp[128]; diva_dbg_entry_head_t* pmsg = NULL; int len; @@ -906,7 +906,6 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { and slot is still free - reuse it */ free_id = id; - best_id = 1; break; } } diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c index 8c5c563c4f12..a3395986df3d 100644 --- a/drivers/isdn/hardware/eicon/message.c +++ b/drivers/isdn/hardware/eicon/message.c @@ -1198,7 +1198,6 @@ static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, word ch; word i; word Info; - word CIP; byte LinkLayer; API_PARSE * ai; API_PARSE * bp; @@ -1340,7 +1339,6 @@ static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, add_s(plci,BC,&parms[6]); add_s(plci,LLC,&parms[7]); add_s(plci,HLC,&parms[8]); - CIP = GET_WORD(parms[0].info); if (a->Info_Mask[appl->Id-1] & 0x200) { /* early B3 connect (CIP mask bit 9) no release after a disc */ @@ -4830,7 +4828,6 @@ static void sig_ind(PLCI *plci) dword x_Id; dword Id; dword rId; - word Number = 0; word i; word cip; dword cip_mask; @@ -5106,7 +5103,7 @@ static void sig_ind(PLCI *plci) } } - if(plci->appl) Number = plci->appl->Number++; + if(plci->appl) plci->appl->Number++; switch(plci->Sig.Ind) { /* Response to Get_Supported_Services request */ @@ -5894,7 +5891,6 @@ static void sig_ind(PLCI *plci) break; case TEL_CTRL: - Number = 0; ie = multi_fac_parms[0]; /* inspect the facility hook indications */ if(plci->State==ADVANCED_VOICE_SIG && ie[0]){ switch (ie[1]&0x91) { @@ -10119,14 +10115,12 @@ static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI static void dtmf_confirmation (dword Id, PLCI *plci) { - word Info; word i; byte result[4]; dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation", UnMapId (Id), (char *)(FILE_), __LINE__)); - Info = GOOD; result[0] = 2; PUT_WORD (&result[1], DTMF_SUCCESS); if (plci->dtmf_send_requests != 0) @@ -11520,13 +11514,12 @@ static word mixer_restore_config (dword Id, PLCI *plci, byte Rc) static void mixer_command (dword Id, PLCI *plci, byte Rc) { DIVA_CAPI_ADAPTER *a; - word i, internal_command, Info; + word i, internal_command; dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x", UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command, plci->li_cmd)); - Info = GOOD; a = plci->adapter; internal_command = plci->internal_command; plci->internal_command = 0; @@ -11550,7 +11543,6 @@ static void mixer_command (dword Id, PLCI *plci, byte Rc) { dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed", UnMapId (Id), (char *)(FILE_), __LINE__)); - Info = _FACILITY_NOT_SUPPORTED; break; } if (plci->internal_command) @@ -11592,7 +11584,6 @@ static void mixer_command (dword Id, PLCI *plci, byte Rc) } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos) && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG)); } - Info = _FACILITY_NOT_SUPPORTED; break; } if (plci->internal_command) @@ -11610,7 +11601,6 @@ static void mixer_command (dword Id, PLCI *plci, byte Rc) { dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed", UnMapId (Id), (char *)(FILE_), __LINE__)); - Info = _FACILITY_NOT_SUPPORTED; break; } if (plci->internal_command) @@ -12448,13 +12438,11 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI static void mixer_indication_coefs_set (dword Id, PLCI *plci) { dword d; - DIVA_CAPI_ADAPTER *a; byte result[12]; dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set", UnMapId (Id), (char *)(FILE_), __LINE__)); - a = plci->adapter; if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos) { do @@ -14111,13 +14099,11 @@ static void select_b_command (dword Id, PLCI *plci, byte Rc) static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc) { - word Info; word internal_command; dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x", UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); - Info = GOOD; internal_command = plci->internal_command; plci->internal_command = 0; switch (internal_command) @@ -14160,13 +14146,11 @@ static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc) static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc) { - word Info; word internal_command; dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x", UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); - Info = GOOD; internal_command = plci->internal_command; plci->internal_command = 0; switch (internal_command) @@ -14395,13 +14379,11 @@ static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc) static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc) { - word Info; word internal_command; dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x", UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); - Info = GOOD; internal_command = plci->internal_command; plci->internal_command = 0; switch (internal_command) @@ -14423,7 +14405,6 @@ static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc) { dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x", UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); - Info = _WRONG_STATE; break; } if (plci_nl_busy (plci)) -- cgit v1.2.3-58-ga151 From a719e0a81f8ab1e96301aada203be1c43788aec7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:34:50 -0700 Subject: isdn: hfcpci: Fix set-but-unused variables. The variable 'total' is set but unused in hfcpci_empty_bfifo(). Just kill it off. Similarly for the variable 'val' in ph_state_nt(). Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/hfcpci.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 4343abac0b13..b01a7be1300f 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -405,7 +405,7 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz, u_char *bdata, int count) { u_char *ptr, *ptr1, new_f2; - int total, maxlen, new_z2; + int maxlen, new_z2; struct zt *zp; if ((bch->debug & DEBUG_HW_BCHANNEL) && !(bch->debug & DEBUG_HW_BFIFO)) @@ -431,7 +431,6 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz, printk(KERN_WARNING "HFCPCI: receive out of memory\n"); return; } - total = count; count -= 3; ptr = skb_put(bch->rx_skb, count); @@ -968,7 +967,6 @@ static void ph_state_nt(struct dchannel *dch) { struct hfc_pci *hc = dch->hw; - u_char val; if (dch->debug) printk(KERN_DEBUG "%s: NT newstate %x\n", @@ -982,7 +980,7 @@ ph_state_nt(struct dchannel *dch) hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER; Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1); /* Clear already pending ints */ - val = Read_hfc(hc, HFCPCI_INT_S1); + (void) Read_hfc(hc, HFCPCI_INT_S1); Write_hfc(hc, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE); udelay(10); Write_hfc(hc, HFCPCI_STATES, 4); -- cgit v1.2.3-58-ga151 From 3c76c58fca03c1162ab8592f71c996e933af3a9e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:35:27 -0700 Subject: isdn: hfcsusb: Fix set-but-unused variables. The variable 'buf' is set but unused in ctrl_complete(). Just kill it off. Similarly for the variable 'err' in setup_hfcsusb(). Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/hfcsusb.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index 8700474747e8..3ccbff13eaf2 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c @@ -118,14 +118,12 @@ static void ctrl_complete(struct urb *urb) { struct hfcsusb *hw = (struct hfcsusb *) urb->context; - struct ctrl_buf *buf; if (debug & DBG_HFC_CALL_TRACE) printk(KERN_DEBUG "%s: %s\n", hw->name, __func__); urb->dev = hw->dev; if (hw->ctrl_cnt) { - buf = &hw->ctrl_buff[hw->ctrl_out_idx]; hw->ctrl_cnt--; /* decrement actual count */ if (++hw->ctrl_out_idx >= HFC_CTRL_BUFSIZE) hw->ctrl_out_idx = 0; /* pointer wrap */ @@ -1726,7 +1724,6 @@ hfcsusb_stop_endpoint(struct hfcsusb *hw, int channel) static int setup_hfcsusb(struct hfcsusb *hw) { - int err; u_char b; if (debug & DBG_HFC_CALL_TRACE) @@ -1745,7 +1742,7 @@ setup_hfcsusb(struct hfcsusb *hw) } /* first set the needed config, interface and alternate */ - err = usb_set_interface(hw->dev, hw->if_used, hw->alt_used); + (void) usb_set_interface(hw->dev, hw->if_used, hw->alt_used); hw->led_state = 0; -- cgit v1.2.3-58-ga151 From 011bc1ef447dd6aa969d9c83a90fe3df360b5d6e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:36:28 -0700 Subject: isdn: arcofi: Fix set-but-unused variables. The variable 'val' is set but unused in send_arcofi(). Just kill it off. Signed-off-by: David S. Miller --- drivers/isdn/hisax/arcofi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c index 85a8fd8dd0b7..21cbbe1d5563 100644 --- a/drivers/isdn/hisax/arcofi.c +++ b/drivers/isdn/hisax/arcofi.c @@ -30,8 +30,6 @@ add_arcofi_timer(struct IsdnCardState *cs) { static void send_arcofi(struct IsdnCardState *cs) { - u_char val; - add_arcofi_timer(cs); cs->dc.isac.mon_txp = 0; cs->dc.isac.mon_txc = cs->dc.isac.arcofi_list->len; @@ -45,7 +43,7 @@ send_arcofi(struct IsdnCardState *cs) { cs->dc.isac.mocr &= 0x0f; cs->dc.isac.mocr |= 0xa0; cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); - val = cs->readisac(cs, ISAC_MOSR); + (void) cs->readisac(cs, ISAC_MOSR); cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); cs->dc.isac.mocr |= 0x10; cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); -- cgit v1.2.3-58-ga151 From 94dbe1ae44df1d22a391980eb6bd502f937b1af8 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:37:11 -0700 Subject: isdn: elsa_cs: Fix set-but-unused variables. The variable 'dev' is set but unused in elsa_cs_config(). Just kill it off. Signed-off-by: David S. Miller --- drivers/isdn/hisax/elsa_cs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index 496d477af0f8..9e5e87be756b 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -129,12 +129,10 @@ static int elsa_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data) static int __devinit elsa_cs_config(struct pcmcia_device *link) { - local_info_t *dev; int i; IsdnCard_t icard; dev_dbg(&link->dev, "elsa_config(0x%p)\n", link); - dev = link->priv; link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; -- cgit v1.2.3-58-ga151 From db47367451cbee4e8a3fd9389cc341f4acc43b1e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:38:33 -0700 Subject: isdn: elsa_ser: Fix set-but-unused variables. The variable 'bits' is set but unused in change_speed(). Just kill it off. Signed-off-by: David S. Miller --- drivers/isdn/hisax/elsa_ser.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c index cbda3790a10d..3fa9f6171095 100644 --- a/drivers/isdn/hisax/elsa_ser.c +++ b/drivers/isdn/hisax/elsa_ser.c @@ -109,11 +109,10 @@ static void change_speed(struct IsdnCardState *cs, int baud) { int quot = 0, baud_base; unsigned cval, fcr = 0; - int bits; /* byte size and parity */ - cval = 0x03; bits = 10; + cval = 0x03; /* Determine divisor based on baud rate */ baud_base = BASE_BAUD; quot = baud_base / baud; -- cgit v1.2.3-58-ga151 From a1e6216d1b5035db1d4c018cf841d3267f949281 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:39:18 -0700 Subject: isdn: hfc_usb: Fix set-but-unused variables. The variable 'buf' is set but unused in ctrl_complete(). Just kill it off. Similarly for 'err' in hfc_usb_init(). Signed-off-by: David S. Miller --- drivers/isdn/hisax/hfc_usb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c index ed9527aa5f2c..f407de0e006d 100644 --- a/drivers/isdn/hisax/hfc_usb.c +++ b/drivers/isdn/hisax/hfc_usb.c @@ -258,11 +258,9 @@ static void ctrl_complete(struct urb *urb) { hfcusb_data *hfc = (hfcusb_data *) urb->context; - ctrl_buft *buf; urb->dev = hfc->dev; if (hfc->ctrl_cnt) { - buf = &hfc->ctrl_buff[hfc->ctrl_out_idx]; hfc->ctrl_cnt--; /* decrement actual count */ if (++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE) hfc->ctrl_out_idx = 0; /* pointer wrap */ @@ -1097,7 +1095,7 @@ static int hfc_usb_init(hfcusb_data * hfc) { usb_fifo *fifo; - int i, err; + int i; u_char b; struct hisax_b_if *p_b_if[2]; @@ -1112,7 +1110,7 @@ hfc_usb_init(hfcusb_data * hfc) } /* first set the needed config, interface and alternate */ - err = usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used); + usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used); /* do Chip reset */ write_usb(hfc, HFCUSB_CIRM, 8); -- cgit v1.2.3-58-ga151 From d462003ddbb28926109396b9038299fc740c2efc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:40:30 -0700 Subject: isdn: ipacx: Fix set-but-unused variables. The variable 'cda2_cr' is set but unused in ctrl_complete(). Just kill it off. Keep the cs->readisac() call just in case the register read has side effects. Signed-off-by: David S. Miller --- drivers/isdn/hisax/ipacx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c index 332104103e18..690840444184 100644 --- a/drivers/isdn/hisax/ipacx.c +++ b/drivers/isdn/hisax/ipacx.c @@ -96,7 +96,7 @@ dch_l2l1(struct PStack *st, int pr, void *arg) { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; - u_char cda1_cr, cda2_cr; + u_char cda1_cr; switch (pr) { case (PH_DATA |REQUEST): @@ -163,7 +163,7 @@ dch_l2l1(struct PStack *st, int pr, void *arg) cs->writeisac(cs, IPACX_CDA_TSDP10, 0x80); // Timeslot 0 is B1 cs->writeisac(cs, IPACX_CDA_TSDP11, 0x81); // Timeslot 0 is B1 cda1_cr = cs->readisac(cs, IPACX_CDA1_CR); - cda2_cr = cs->readisac(cs, IPACX_CDA2_CR); + (void) cs->readisac(cs, IPACX_CDA2_CR); if ((long)arg &1) { // loop B1 cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x0a); } -- cgit v1.2.3-58-ga151 From f6f0e4a7a343f85dd773f6f18e553933c4367e96 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:41:29 -0700 Subject: isdn: jade: Fix set-but-unused variables. The variable 'i' is set but unused in JadeVersion(). Just kill it off. Signed-off-by: David S. Miller --- drivers/isdn/hisax/jade.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c index ea8f840871d0..a06cea09158b 100644 --- a/drivers/isdn/hisax/jade.c +++ b/drivers/isdn/hisax/jade.c @@ -23,10 +23,9 @@ int JadeVersion(struct IsdnCardState *cs, char *s) { - int ver,i; + int ver; int to = 50; cs->BC_Write_Reg(cs, -1, 0x50, 0x19); - i=0; while (to) { udelay(1); ver = cs->BC_Read_Reg(cs, -1, 0x60); -- cgit v1.2.3-58-ga151 From cf117eafa0dc17c6f973d078d4e0bf2069f45ce7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:42:15 -0700 Subject: isdn: l3dss1: Fix set-but-unused variables. The variable 'cause' is set but unused in dss1up(). Just kill it off. Signed-off-by: David S. Miller --- drivers/isdn/hisax/l3dss1.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c index 8e2fd02ecce0..b0d9ab1f21c0 100644 --- a/drivers/isdn/hisax/l3dss1.c +++ b/drivers/isdn/hisax/l3dss1.c @@ -2943,7 +2943,7 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb) static void dss1up(struct PStack *st, int pr, void *arg) { - int i, mt, cr, cause, callState; + int i, mt, cr, callState; char *ptr; u_char *p; struct sk_buff *skb = arg; @@ -3034,12 +3034,10 @@ dss1up(struct PStack *st, int pr, void *arg) return; } } else if (mt == MT_STATUS) { - cause = 0; if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) { ptr++; if (*ptr++ == 2) ptr++; - cause = *ptr & 0x7f; } callState = 0; if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) { -- cgit v1.2.3-58-ga151 From 1397c5df2547f3296ad37a0c77daff3b124b98c8 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:43:20 -0700 Subject: isdn: l3ni1: Fix set-but-unused variables. The variable 'cause' is set but unused in ni1up(). Just kill it off. Signed-off-by: David S. Miller --- drivers/isdn/hisax/l3ni1.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c index 7b229c0ce115..092dcbb39d94 100644 --- a/drivers/isdn/hisax/l3ni1.c +++ b/drivers/isdn/hisax/l3ni1.c @@ -2883,7 +2883,7 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb) static void ni1up(struct PStack *st, int pr, void *arg) { - int i, mt, cr, cause, callState; + int i, mt, cr, callState; char *ptr; u_char *p; struct sk_buff *skb = arg; @@ -2986,12 +2986,10 @@ ni1up(struct PStack *st, int pr, void *arg) return; } } else if (mt == MT_STATUS) { - cause = 0; if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) { ptr++; if (*ptr++ == 2) ptr++; - cause = *ptr & 0x7f; } callState = 0; if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) { -- cgit v1.2.3-58-ga151 From 8c85290d84eaa7b3ba605090987d2136a3302ca9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:44:12 -0700 Subject: isdn: teles_cs: Fix set-but-unused variables. The variable 'dev' is set but unused in teles_cs_config(). Just kill it off. Signed-off-by: David S. Miller --- drivers/isdn/hisax/teles_cs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index aa25e183bf79..360f9ec7c802 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -111,12 +111,10 @@ static int teles_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data) static int __devinit teles_cs_config(struct pcmcia_device *link) { - local_info_t *dev; int i; IsdnCard_t icard; dev_dbg(&link->dev, "teles_config(0x%p)\n", link); - dev = link->priv; i = pcmcia_loop_config(link, teles_cs_configcheck, NULL); if (i != 0) -- cgit v1.2.3-58-ga151 From 50a7c114c2673f3fcbb0ba5d659049156e1ccd50 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:45:51 -0700 Subject: isdn: i4l: isdn_common: Fix set-but-unused variables. The variable 'ch' is set but unused in isdn_capi_rec_hl_msg(). Just kill it off. Similarly for 'chidx' in isdn_ioctl() and 'di' in isdn_capi_rec_hl_msg(). Signed-off-by: David S. Miller --- drivers/isdn/i4l/isdn_common.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 15632bd2f643..6ed82add6ffa 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -399,13 +399,8 @@ isdn_all_eaz(int di, int ch) #include static int -isdn_capi_rec_hl_msg(capi_msg *cm) { - - int di; - int ch; - - di = (cm->adr.Controller & 0x7f) -1; - ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f); +isdn_capi_rec_hl_msg(capi_msg *cm) +{ switch(cm->Command) { case CAPI_FACILITY: /* in the moment only handled in tty */ @@ -1278,7 +1273,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) uint minor = iminor(file->f_path.dentry->d_inode); isdn_ctrl c; int drvidx; - int chidx; int ret; int i; char __user *p; @@ -1340,7 +1334,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) drvidx = isdn_minor2drv(minor); if (drvidx < 0) return -ENODEV; - chidx = isdn_minor2chan(minor); if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) return -ENODEV; return 0; -- cgit v1.2.3-58-ga151 From 07f46f80f4ca4ddb700ff40a19876ba1b3242917 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:46:50 -0700 Subject: isdn: i4l: isdn_net: Fix set-but-unused variables. The variable 'unused' is set but unused in isdn_net_ciscohdlck_slarp_in(). Just kill it off. Signed-off-by: David S. Miller --- drivers/isdn/i4l/isdn_net.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 2a7d17c19489..97988111e45a 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -1678,7 +1678,6 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb) u32 your_seq; __be32 local; __be32 *addr, *mask; - u16 unused; if (skb->len < 14) return; @@ -1722,7 +1721,6 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb) lp->cisco_last_slarp_in = jiffies; my_seq = be32_to_cpup((__be32 *)(p + 0)); your_seq = be32_to_cpup((__be32 *)(p + 4)); - unused = be16_to_cpup((__be16 *)(p + 8)); p += 10; lp->cisco_yourseq = my_seq; lp->cisco_mineseen = your_seq; -- cgit v1.2.3-58-ga151 From 81b424d9e2ef815b2035d4c2be0bc41dddbebc06 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:48:53 -0700 Subject: isdn: mISDN: socket: Fix set-but-unused variables. The variable 'len' is set but unused in data_sock_getsockopt(). The code should use 'len' to validate that the user's socket option is indeed the right size. Signed-off-by: David S. Miller --- drivers/isdn/mISDN/socket.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index 7446d8b4282d..8e325227b4c0 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c @@ -457,6 +457,9 @@ static int data_sock_getsockopt(struct socket *sock, int level, int optname, if (get_user(len, optlen)) return -EFAULT; + if (len != sizeof(char)) + return -EINVAL; + switch (optname) { case MISDN_TIME_STAMP: if (_pms(sk)->cmask & MISDN_TIME_STAMP) -- cgit v1.2.3-58-ga151 From 585985429080a449e0ecf66dd485899a8765c26c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:51:36 -0700 Subject: bna: Fix set-but-unused variables. The variable 'pgoff' is set but unused in bfa_nw_ioc_fwver_get() and bfa_ioc_download_fw(). Similarly for 'cmd_h' in bna_mbox_flush_q and the entirety of bna_rit_mod_uninit() is unused since variables are purely set but no action is made using them. Same for 'bna' in bna_rit_create() and 'ret' in bna_rx_create(). Just kill them off. Signed-off-by: David S. Miller --- drivers/net/bna/bfa_ioc.c | 6 ++---- drivers/net/bna/bna_ctrl.c | 21 --------------------- drivers/net/bna/bna_txrx.c | 7 ++----- 3 files changed, 4 insertions(+), 30 deletions(-) diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c index e3de0b8625cd..c1c9e70eec2f 100644 --- a/drivers/net/bna/bfa_ioc.c +++ b/drivers/net/bna/bfa_ioc.c @@ -1272,13 +1272,12 @@ bfa_ioc_lpu_stop(struct bfa_ioc *ioc) void bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) { - u32 pgnum, pgoff; + u32 pgnum; u32 loff = 0; int i; u32 *fwsig = (u32 *) fwhdr; pgnum = bfa_ioc_smem_pgnum(ioc, loff); - pgoff = bfa_ioc_smem_pgoff(ioc, loff); writel(pgnum, ioc->ioc_regs.host_page_num_fn); for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr) / sizeof(u32)); @@ -1509,7 +1508,7 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param) { u32 *fwimg; - u32 pgnum, pgoff; + u32 pgnum; u32 loff = 0; u32 chunkno = 0; u32 i; @@ -1522,7 +1521,6 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type, fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno); pgnum = bfa_ioc_smem_pgnum(ioc, loff); - pgoff = bfa_ioc_smem_pgoff(ioc, loff); writel(pgnum, ioc->ioc_regs.host_page_num_fn); diff --git a/drivers/net/bna/bna_ctrl.c b/drivers/net/bna/bna_ctrl.c index e1527472b961..53b14169e363 100644 --- a/drivers/net/bna/bna_ctrl.c +++ b/drivers/net/bna/bna_ctrl.c @@ -246,7 +246,6 @@ static void bna_mbox_flush_q(struct bna *bna, struct list_head *q) { struct bna_mbox_qe *mb_qe = NULL; - struct bfi_mhdr *cmd_h; struct list_head *mb_q; void (*cbfn)(void *arg, int status); void *cbarg; @@ -260,7 +259,6 @@ bna_mbox_flush_q(struct bna *bna, struct list_head *q) bfa_q_qe_init(mb_qe); bna->mbox_mod.msg_pending--; - cmd_h = (struct bfi_mhdr *)(&mb_qe->cmd.msg[0]); if (cbfn) cbfn(cbarg, BNA_CB_NOT_EXEC); } @@ -2774,23 +2772,6 @@ bna_rit_mod_init(struct bna_rit_mod *rit_mod, } } -static void -bna_rit_mod_uninit(struct bna_rit_mod *rit_mod) -{ - struct bna_rit_segment *rit_segment; - struct list_head *qe; - int i; - int j; - - for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) { - j = 0; - list_for_each(qe, &rit_mod->rit_seg_pool[i]) { - rit_segment = (struct bna_rit_segment *)qe; - j++; - } - } -} - /* * Public functions */ @@ -2977,8 +2958,6 @@ bna_uninit(struct bna *bna) bna_ucam_mod_uninit(&bna->ucam_mod); - bna_rit_mod_uninit(&bna->rit_mod); - bna_ib_mod_uninit(&bna->ib_mod); bna_rx_mod_uninit(&bna->rx_mod); diff --git a/drivers/net/bna/bna_txrx.c b/drivers/net/bna/bna_txrx.c index 58c7664040dc..380085cc3088 100644 --- a/drivers/net/bna/bna_txrx.c +++ b/drivers/net/bna/bna_txrx.c @@ -2229,14 +2229,11 @@ void bna_rit_create(struct bna_rx *rx) { struct list_head *qe_rxp; - struct bna *bna; struct bna_rxp *rxp; struct bna_rxq *q0 = NULL; struct bna_rxq *q1 = NULL; int offset; - bna = rx->bna; - offset = 0; list_for_each(qe_rxp, &rx->rxp_q) { rxp = (struct bna_rxp *)qe_rxp; @@ -2830,7 +2827,7 @@ bna_rx_create(struct bna *bna, struct bnad *bnad, struct bna_mem_descr *dsqpt_mem; /* s/w qpt for data */ struct bna_mem_descr *hpage_mem; /* hdr page mem */ struct bna_mem_descr *dpage_mem; /* data page mem */ - int i, cpage_idx = 0, dpage_idx = 0, hpage_idx = 0, ret; + int i, cpage_idx = 0, dpage_idx = 0, hpage_idx = 0; int dpage_count, hpage_count, rcb_idx; struct bna_ib_config ibcfg; /* Fail if we don't have enough RXPs, RXQs */ @@ -2924,7 +2921,7 @@ bna_rx_create(struct bna *bna, struct bnad *bnad, ibcfg.interpkt_timeo = BFI_RX_INTERPKT_TIMEO; ibcfg.ctrl_flags = BFI_IB_CF_INT_ENABLE; - ret = bna_ib_config(rxp->cq.ib, &ibcfg); + bna_ib_config(rxp->cq.ib, &ibcfg); /* Link rxqs to rxp */ _rxp_add_rxqs(rxp, q0, q1); -- cgit v1.2.3-58-ga151 From b8ee8328bac0d8420d2b9ef4838d0df25df100ab Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:56:12 -0700 Subject: bnx2x: Fix set-but-unused variables. The variable 'rc' is set but unused in bnx2x_timer(). Similarly for 'hc_index_p' in bnx2x_init_sb(), and 'port' in bnx2x_get_hwinfo(). Just kill them off. Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_main.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 696e84afdc53..bfd7ac98248b 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -3904,10 +3904,9 @@ static void bnx2x_timer(unsigned long data) if (poll) { struct bnx2x_fastpath *fp = &bp->fp[0]; - int rc; bnx2x_tx_int(fp); - rc = bnx2x_rx_int(fp, 1000); + bnx2x_rx_int(fp, 1000); } if (!BP_NOMCP(bp)) { @@ -4062,7 +4061,6 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, struct hc_status_block_data_e2 sb_data_e2; struct hc_status_block_data_e1x sb_data_e1x; struct hc_status_block_sm *hc_sm_p; - struct hc_index_data *hc_index_p; int data_size; u32 *sb_data_p; @@ -4083,7 +4081,6 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, sb_data_e2.common.host_sb_addr.hi = U64_HI(mapping); sb_data_e2.common.host_sb_addr.lo = U64_LO(mapping); hc_sm_p = sb_data_e2.common.state_machine; - hc_index_p = sb_data_e2.index_data; sb_data_p = (u32 *)&sb_data_e2; data_size = sizeof(struct hc_status_block_data_e2)/sizeof(u32); } else { @@ -4097,7 +4094,6 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, sb_data_e1x.common.host_sb_addr.hi = U64_HI(mapping); sb_data_e1x.common.host_sb_addr.lo = U64_LO(mapping); hc_sm_p = sb_data_e1x.common.state_machine; - hc_index_p = sb_data_e1x.index_data; sb_data_p = (u32 *)&sb_data_e1x; data_size = sizeof(struct hc_status_block_data_e1x)/sizeof(u32); } @@ -8635,7 +8631,7 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) { int /*abs*/func = BP_ABS_FUNC(bp); - int vn, port; + int vn; u32 val = 0; int rc = 0; @@ -8670,7 +8666,6 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) bp->mf_ov = 0; bp->mf_mode = 0; vn = BP_E1HVN(bp); - port = BP_PORT(bp); if (!CHIP_IS_E1(bp) && !BP_NOMCP(bp)) { DP(NETIF_MSG_PROBE, -- cgit v1.2.3-58-ga151 From 056693a38e56c520e208409d221cbc077282c19d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:57:55 -0700 Subject: caif: Fix set-but-unused variables. The variable 'caifdef' is set but unused in modemcmd(). Similarly for 'net' in receive(), and 'res' in caif_device_notify() and caif_exit_net(). Just kill them off. Signed-off-by: David S. Miller --- net/caif/caif_dev.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index a518fdd4da0a..75e00d59eb49 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -133,9 +133,7 @@ static int transmit(struct cflayer *layer, struct cfpkt *pkt) static int modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) { struct caif_device_entry *caifd; - struct caif_dev_common *caifdev; caifd = container_of(layr, struct caif_device_entry, layer); - caifdev = netdev_priv(caifd->netdev); if (ctrl == _CAIF_MODEMCMD_PHYIF_USEFULL) { atomic_set(&caifd->in_use, 1); wake_up_interruptible(&caifd->event); @@ -154,10 +152,8 @@ static int modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) static int receive(struct sk_buff *skb, struct net_device *dev, struct packet_type *pkttype, struct net_device *orig_dev) { - struct net *net; struct cfpkt *pkt; struct caif_device_entry *caifd; - net = dev_net(dev); pkt = cfpkt_fromnative(CAIF_DIR_IN, skb); caifd = caif_get(dev); if (!caifd || !caifd->layer.up || !caifd->layer.up->receive) @@ -195,7 +191,6 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, struct caif_device_entry *caifd = NULL; struct caif_dev_common *caifdev; enum cfcnfg_phy_preference pref; - int res = -EINVAL; enum cfcnfg_phy_type phy_type; if (dev->type != ARPHRD_CAIF) @@ -210,7 +205,6 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, caifdev = netdev_priv(dev); caifdev->flowctrl = dev_flowctrl; atomic_set(&caifd->state, what); - res = 0; break; case NETDEV_UP: @@ -274,7 +268,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, _CAIF_CTRLCMD_PHYIF_DOWN_IND, caifd->layer.id); might_sleep(); - res = wait_event_interruptible_timeout(caifd->event, + wait_event_interruptible_timeout(caifd->event, atomic_read(&caifd->in_use) == 0, TIMEOUT); break; @@ -344,12 +338,11 @@ static int caif_init_net(struct net *net) static void caif_exit_net(struct net *net) { struct net_device *dev; - int res; rtnl_lock(); for_each_netdev(net, dev) { if (dev->type != ARPHRD_CAIF) continue; - res = dev_close(dev); + dev_close(dev); caif_device_destroy(dev); } rtnl_unlock(); -- cgit v1.2.3-58-ga151 From 1627ea35cb10af2f71d38a82de6f6dfb910771ed Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:59:09 -0700 Subject: irda: irlap_event: Fix set-but-unused variables. The variable 'ret' is set but unused in irlap_state_sclose(). Just kill it off. Signed-off-by: David S. Miller --- net/irda/irlap_event.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c index bb47021c9a55..ccd214f9d196 100644 --- a/net/irda/irlap_event.c +++ b/net/irda/irlap_event.c @@ -2227,8 +2227,6 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event, static int irlap_state_sclose(struct irlap_cb *self, IRLAP_EVENT event, struct sk_buff *skb, struct irlap_info *info) { - int ret = 0; - IRDA_DEBUG(1, "%s()\n", __func__); IRDA_ASSERT(self != NULL, return -ENODEV;); @@ -2289,7 +2287,6 @@ static int irlap_state_sclose(struct irlap_cb *self, IRLAP_EVENT event, IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __func__, event, irlap_event[event]); - ret = -EINVAL; break; } -- cgit v1.2.3-58-ga151 From 6385969b3297287e6259a012671be09c78c20620 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 16:59:50 -0700 Subject: irda: irproc: Fix set-but-unused variables. The variable 'd' is set but unused in irda_proc_register(). Just kill it off. Signed-off-by: David S. Miller --- net/irda/irproc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/irda/irproc.c b/net/irda/irproc.c index 318766e5dbdf..b9ac598e2116 100644 --- a/net/irda/irproc.c +++ b/net/irda/irproc.c @@ -65,15 +65,14 @@ static const struct irda_entry irda_dirs[] = { void __init irda_proc_register(void) { int i; - struct proc_dir_entry *d; proc_irda = proc_mkdir("irda", init_net.proc_net); if (proc_irda == NULL) return; for (i = 0; i < ARRAY_SIZE(irda_dirs); i++) - d = proc_create(irda_dirs[i].name, 0, proc_irda, - irda_dirs[i].fops); + (void) proc_create(irda_dirs[i].name, 0, proc_irda, + irda_dirs[i].fops); } /* -- cgit v1.2.3-58-ga151 From 8cb490144708ef295421d0601b0866623651a37e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 17:01:05 -0700 Subject: l2tp: Fix set-but-unused variables. The variable 'ret' is set but unused in l2tp_nl_register_ops(). This was obviously meant to maintain error codes which are returned to the caller, make it so. Signed-off-by: David S. Miller --- net/l2tp/l2tp_netlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 4c1e540732d7..93a41a09458b 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -795,11 +795,12 @@ int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops goto out; l2tp_nl_cmd_ops[pw_type] = ops; + ret = 0; out: genl_unlock(); err: - return 0; + return ret; } EXPORT_SYMBOL_GPL(l2tp_nl_register_ops); -- cgit v1.2.3-58-ga151 From dab51d0e0718e7beef26075a9353f09ea2652a4f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 17:01:49 -0700 Subject: netlabel: Fix set-but-unused variables. The variable 'type_str' is set but unused in netlbl_cipsov4_add(). Just kill it off. Signed-off-by: David S. Miller --- net/netlabel/netlabel_cipso_v4.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index 5f14c8462e30..bae5756b1626 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -422,7 +422,6 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) { int ret_val = -EINVAL; - const char *type_str = "(unknown)"; struct netlbl_audit audit_info; if (!info->attrs[NLBL_CIPSOV4_A_DOI] || @@ -432,15 +431,12 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) netlbl_netlink_auditinfo(skb, &audit_info); switch (nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE])) { case CIPSO_V4_MAP_TRANS: - type_str = "trans"; ret_val = netlbl_cipsov4_add_std(info, &audit_info); break; case CIPSO_V4_MAP_PASS: - type_str = "pass"; ret_val = netlbl_cipsov4_add_pass(info, &audit_info); break; case CIPSO_V4_MAP_LOCAL: - type_str = "local"; ret_val = netlbl_cipsov4_add_local(info, &audit_info); break; } -- cgit v1.2.3-58-ga151 From d87d7fb381c153f71b7cdfd37f3513edc6d0eb8f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 17:02:29 -0700 Subject: netfilter: nfnetlink_log: Fix set-but-unused variables. The variable 'tmp_uint' is set but unused in __build_packet_message(). Just kill it off. Signed-off-by: David S. Miller --- net/netfilter/nfnetlink_log.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 985e9b76c916..e0ee010935e7 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -381,7 +381,6 @@ __build_packet_message(struct nfulnl_instance *inst, struct nfulnl_msg_packet_hdr pmsg; struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; - __be32 tmp_uint; sk_buff_data_t old_tail = inst->skb->tail; nlh = NLMSG_PUT(inst->skb, 0, 0, @@ -428,7 +427,6 @@ __build_packet_message(struct nfulnl_instance *inst, } if (outdev) { - tmp_uint = htonl(outdev->ifindex); #ifndef CONFIG_BRIDGE_NETFILTER NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, htonl(outdev->ifindex)); -- cgit v1.2.3-58-ga151 From d88d7de09875e643e225a5d0883d18152ce5a89b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 17:03:33 -0700 Subject: netfilter: nf_conntrack_standalone: Fix set-but-unused variables. The variable 'ret' is set but unused in ct_seq_show(). This was obviously meant to be used to propagate error codes to the caller, so make it so. Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_standalone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 0ae142825881..05e9feb101c3 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -245,7 +245,7 @@ static int ct_seq_show(struct seq_file *s, void *v) ret = 0; release: nf_ct_put(ct); - return 0; + return ret; } static const struct seq_operations ct_seq_ops = { -- cgit v1.2.3-58-ga151 From f3c85dd560f26ceae1351e6f83e83f1322761ead Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 17:04:48 -0700 Subject: netfilter: ip6_tables: Fix set-but-unused variables. The variable 'target' is set but unused in compat_copy_entry_from_user(). Just kill it off. Signed-off-by: David S. Miller --- net/ipv6/netfilter/ip6_tables.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 5a1c6f27ffaf..4c1492ff473c 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1578,7 +1578,6 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, struct xt_table_info *newinfo, unsigned char *base) { struct xt_entry_target *t; - struct xt_target *target; struct ip6t_entry *de; unsigned int origsize; int ret, h; @@ -1600,7 +1599,6 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, } de->target_offset = e->target_offset - (origsize - *size); t = compat_ip6t_get_target(e); - target = t->u.kernel.target; xt_compat_target_from_user(t, dstptr, size); de->next_offset = e->next_offset - (origsize - *size); -- cgit v1.2.3-58-ga151 From b169f6db40605d0907458d1ff78ceac2b194a44f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 17:06:15 -0700 Subject: netfilter: ip6table_mangle: Fix set-but-unused variables. The variable 'flowlabel' is set but unused in ip6t_mangle_out(). The intention here was to compare this key to the header value after mangling, and trigger a route lookup on mismatch. Make it so. Signed-off-by: David S. Miller --- net/ipv6/netfilter/ip6table_mangle.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 679a0a3b7b3c..00d19173db7e 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -64,7 +64,8 @@ ip6t_mangle_out(struct sk_buff *skb, const struct net_device *out) (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) || memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) || skb->mark != mark || - ipv6_hdr(skb)->hop_limit != hop_limit)) + ipv6_hdr(skb)->hop_limit != hop_limit || + flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP; return ret; -- cgit v1.2.3-58-ga151 From 9365f11a5321bcff5579799a071a70c5cacb5e65 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 17:07:57 -0700 Subject: isdn: i4l: isdn_tty: Fix unused-but-set variables. The variable 'fcr' is set but not used in isdn_tty_change_speed(). Just kill it off. Signed-off-by: David S. Miller --- drivers/isdn/i4l/isdn_tty.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 607d846ae063..d8504279e502 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -998,7 +998,6 @@ isdn_tty_change_speed(modem_info * info) { uint cflag, cval, - fcr, quot; int i; @@ -1037,7 +1036,6 @@ isdn_tty_change_speed(modem_info * info) cval |= UART_LCR_PARITY; if (!(cflag & PARODD)) cval |= UART_LCR_EPAR; - fcr = 0; /* CTS flow control flag and modem status interrupts */ if (cflag & CRTSCTS) { -- cgit v1.2.3-58-ga151 From 03746b0a02d25866a29cd8d7306d221c238d6397 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 17:08:41 -0700 Subject: be2net: Fix unused-but-set variables. The variables 'tx_min' and 'tx_max' are set but not used in be_set_coalesce(). Similarly for 'region' in be_do_flash(). Just kill them off. Signed-off-by: David S. Miller --- drivers/net/benet/be_ethtool.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 80226e4801f3..0f645a92bebe 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -205,9 +205,9 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) struct be_rx_obj *rxo; struct be_eq_obj *rx_eq; struct be_eq_obj *tx_eq = &adapter->tx_eq; - u32 tx_max, tx_min, tx_cur; u32 rx_max, rx_min, rx_cur; int status = 0, i; + u32 tx_cur; if (coalesce->use_adaptive_tx_coalesce == 1) return -EINVAL; @@ -246,8 +246,6 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) } } - tx_max = coalesce->tx_coalesce_usecs_high; - tx_min = coalesce->tx_coalesce_usecs_low; tx_cur = coalesce->tx_coalesce_usecs; if (tx_cur > BE_MAX_EQD) @@ -664,11 +662,9 @@ be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) { struct be_adapter *adapter = netdev_priv(netdev); char file_name[ETHTOOL_FLASH_MAX_FILENAME]; - u32 region; file_name[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0; strcpy(file_name, efl->data); - region = efl->region; return be_load_fw(adapter, file_name); } -- cgit v1.2.3-58-ga151 From 391876466670988196786150fc9d9da2f3c7cecb Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 17 Apr 2011 00:15:46 +0000 Subject: net: macvlan: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not much of a conversion anyway - macvlan has no way to change the offload settings independently to its base device. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 78e34e9e4f00..3ad5425b82dd 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -415,7 +415,7 @@ static struct lock_class_key macvlan_netdev_addr_lock_key; #define MACVLAN_FEATURES \ (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \ - NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO) + NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM) #define MACVLAN_STATE_MASK \ ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT)) @@ -517,12 +517,6 @@ static void macvlan_ethtool_get_drvinfo(struct net_device *dev, snprintf(drvinfo->version, 32, "0.1"); } -static u32 macvlan_ethtool_get_rx_csum(struct net_device *dev) -{ - const struct macvlan_dev *vlan = netdev_priv(dev); - return dev_ethtool_get_rx_csum(vlan->lowerdev); -} - static int macvlan_ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { @@ -530,18 +524,10 @@ static int macvlan_ethtool_get_settings(struct net_device *dev, return dev_ethtool_get_settings(vlan->lowerdev, cmd); } -static u32 macvlan_ethtool_get_flags(struct net_device *dev) -{ - const struct macvlan_dev *vlan = netdev_priv(dev); - return dev_ethtool_get_flags(vlan->lowerdev); -} - static const struct ethtool_ops macvlan_ethtool_ops = { .get_link = ethtool_op_get_link, .get_settings = macvlan_ethtool_get_settings, - .get_rx_csum = macvlan_ethtool_get_rx_csum, .get_drvinfo = macvlan_ethtool_get_drvinfo, - .get_flags = macvlan_ethtool_get_flags, }; static const struct net_device_ops macvlan_netdev_ops = { -- cgit v1.2.3-58-ga151 From d2fe2755342b30bc1ee7797b9975f8626d65e485 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 17 Apr 2011 00:15:46 +0000 Subject: net: cxgb3: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes some of the remnants of LRO -> GRO conversion. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/cxgb3/adapter.h | 7 ---- drivers/net/cxgb3/common.h | 1 - drivers/net/cxgb3/cxgb3_main.c | 78 +++++++----------------------------------- drivers/net/cxgb3/sge.c | 7 ++-- 4 files changed, 17 insertions(+), 76 deletions(-) diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index ef67be59680f..7300de5a1426 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -50,11 +50,6 @@ struct adapter; struct sge_qset; struct port_info; -enum { /* rx_offload flags */ - T3_RX_CSUM = 1 << 0, - T3_LRO = 1 << 1, -}; - enum mac_idx_types { LAN_MAC_IDX = 0, SAN_MAC_IDX, @@ -74,7 +69,6 @@ struct port_info { struct vlan_group *vlan_grp; struct sge_qset *qs; u8 port_id; - u8 rx_offload; u8 nqsets; u8 first_qset; struct cphy phy; @@ -212,7 +206,6 @@ struct sge_qset { /* an SGE queue set */ struct sge_fl fl[SGE_RXQ_PER_SET]; struct sge_txq txq[SGE_TXQ_PER_SET]; int nomem; - int lro_enabled; void *lro_va; struct net_device *netdev; struct netdev_queue *tx_q; /* associated netdev TX queue */ diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index 5ccb77d078aa..056ee8c831f1 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -317,7 +317,6 @@ struct tp_params { struct qset_params { /* SGE queue set parameters */ unsigned int polling; /* polling/interrupt service for rspq */ - unsigned int lro; /* large receive offload */ unsigned int coalesce_usecs; /* irq coalescing timer */ unsigned int rspq_size; /* # of entries in response queue */ unsigned int fl_size; /* # of entries in regular free list */ diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index a087e0691dce..040491804efb 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -643,26 +643,6 @@ static void enable_all_napi(struct adapter *adap) napi_enable(&adap->sge.qs[i].napi); } -/** - * set_qset_lro - Turn a queue set's LRO capability on and off - * @dev: the device the qset is attached to - * @qset_idx: the queue set index - * @val: the LRO switch - * - * Sets LRO on or off for a particular queue set. - * the device's features flag is updated to reflect the LRO - * capability when all queues belonging to the device are - * in the same state. - */ -static void set_qset_lro(struct net_device *dev, int qset_idx, int val) -{ - struct port_info *pi = netdev_priv(dev); - struct adapter *adapter = pi->adapter; - - adapter->params.sge.qset[qset_idx].lro = !!val; - adapter->sge.qs[qset_idx].lro_enabled = !!val; -} - /** * setup_sge_qsets - configure SGE Tx/Rx/response queues * @adap: the adapter @@ -685,7 +665,6 @@ static int setup_sge_qsets(struct adapter *adap) pi->qs = &adap->sge.qs[pi->first_qset]; for (j = 0; j < pi->nqsets; ++j, ++qset_idx) { - set_qset_lro(dev, qset_idx, pi->rx_offload & T3_LRO); err = t3_sge_alloc_qset(adap, qset_idx, 1, (adap->flags & USING_MSIX) ? qset_idx + 1 : irq_idx, @@ -1910,29 +1889,6 @@ static int set_pauseparam(struct net_device *dev, return 0; } -static u32 get_rx_csum(struct net_device *dev) -{ - struct port_info *p = netdev_priv(dev); - - return p->rx_offload & T3_RX_CSUM; -} - -static int set_rx_csum(struct net_device *dev, u32 data) -{ - struct port_info *p = netdev_priv(dev); - - if (data) { - p->rx_offload |= T3_RX_CSUM; - } else { - int i; - - p->rx_offload &= ~(T3_RX_CSUM | T3_LRO); - for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) - set_qset_lro(dev, i, 0); - } - return 0; -} - static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e) { struct port_info *pi = netdev_priv(dev); @@ -2104,10 +2060,6 @@ static const struct ethtool_ops cxgb_ethtool_ops = { .set_eeprom = set_eeprom, .get_pauseparam = get_pauseparam, .set_pauseparam = set_pauseparam, - .get_rx_csum = get_rx_csum, - .set_rx_csum = set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, .get_link = ethtool_op_get_link, .get_strings = get_strings, .set_phys_id = set_phys_id, @@ -2117,7 +2069,6 @@ static const struct ethtool_ops cxgb_ethtool_ops = { .get_regs_len = get_regs_len, .get_regs = get_regs, .get_wol = get_wol, - .set_tso = ethtool_op_set_tso, }; static int in_range(int val, int lo, int hi) @@ -2165,15 +2116,6 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) MAX_RSPQ_ENTRIES)) return -EINVAL; - if ((adapter->flags & FULL_INIT_DONE) && t.lro > 0) - for_each_port(adapter, i) { - pi = adap2pinfo(adapter, i); - if (t.qset_idx >= pi->first_qset && - t.qset_idx < pi->first_qset + pi->nqsets && - !(pi->rx_offload & T3_RX_CSUM)) - return -EINVAL; - } - if ((adapter->flags & FULL_INIT_DONE) && (t.rspq_size >= 0 || t.fl_size[0] >= 0 || t.fl_size[1] >= 0 || t.txq_size[0] >= 0 || @@ -2234,8 +2176,14 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) } } } - if (t.lro >= 0) - set_qset_lro(dev, t.qset_idx, t.lro); + + if (t.lro >= 0) { + if (t.lro) + dev->wanted_features |= NETIF_F_GRO; + else + dev->wanted_features &= ~NETIF_F_GRO; + netdev_update_features(dev); + } break; } @@ -2269,7 +2217,7 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) t.fl_size[0] = q->fl_size; t.fl_size[1] = q->jumbo_size; t.polling = q->polling; - t.lro = q->lro; + t.lro = !!(dev->features & NETIF_F_GRO); t.intr_lat = q->coalesce_usecs; t.cong_thres = q->cong_thres; t.qnum = q1; @@ -3307,18 +3255,18 @@ static int __devinit init_one(struct pci_dev *pdev, adapter->port[i] = netdev; pi = netdev_priv(netdev); pi->adapter = adapter; - pi->rx_offload = T3_RX_CSUM | T3_LRO; pi->port_id = i; netif_carrier_off(netdev); netdev->irq = pdev->irq; netdev->mem_start = mmio_start; netdev->mem_end = mmio_start + mmio_len - 1; - netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; - netdev->features |= NETIF_F_GRO; + netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_TSO | NETIF_F_RXCSUM; + netdev->features |= netdev->hw_features | + NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; - netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; netdev->netdev_ops = &cxgb_netdev_ops; SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops); } diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index bfa2d56af1ee..cba1401377ab 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -2019,7 +2019,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq, skb_pull(skb, sizeof(*p) + pad); skb->protocol = eth_type_trans(skb, adap->port[p->iff]); pi = netdev_priv(skb->dev); - if ((pi->rx_offload & T3_RX_CSUM) && p->csum_valid && + if ((skb->dev->features & NETIF_F_RXCSUM) && p->csum_valid && p->csum == htons(0xffff) && !p->fragment) { qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++; skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -2120,7 +2120,7 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, offset = 2 + sizeof(struct cpl_rx_pkt); cpl = qs->lro_va = sd->pg_chunk.va + 2; - if ((pi->rx_offload & T3_RX_CSUM) && + if ((qs->netdev->features & NETIF_F_RXCSUM) && cpl->csum_valid && cpl->csum == htons(0xffff)) { skb->ip_summed = CHECKSUM_UNNECESSARY; qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++; @@ -2285,7 +2285,8 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs, q->next_holdoff = q->holdoff_tmr; while (likely(budget_left && is_new_response(r, q))) { - int packet_complete, eth, ethpad = 2, lro = qs->lro_enabled; + int packet_complete, eth, ethpad = 2; + int lro = !!(qs->netdev->features & NETIF_F_GRO); struct sk_buff *skb = NULL; u32 len, flags; __be32 rss_hi, rss_lo; -- cgit v1.2.3-58-ga151 From eea3250b43fd0b4fe565409bbf2fb06514213386 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 17 Apr 2011 00:15:46 +0000 Subject: net: tehuti: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As a side effect, make TX offloads changeable. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/tehuti.c | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 8564ec5cfb7f..8be71de725e5 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -2017,9 +2017,11 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ndev->irq = pdev->irq; ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | - NETIF_F_HW_VLAN_FILTER + NETIF_F_HW_VLAN_FILTER | NETIF_F_RXCSUM /*| NETIF_F_FRAGLIST */ ; + ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | + NETIF_F_TSO | NETIF_F_HW_VLAN_TX; if (pci_using_dac) ndev->features |= NETIF_F_HIGHDMA; @@ -2187,24 +2189,6 @@ bdx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) drvinfo->eedump_len = 0; } -/* - * bdx_get_rx_csum - report whether receive checksums are turned on or off - * @netdev - */ -static u32 bdx_get_rx_csum(struct net_device *netdev) -{ - return 1; /* always on */ -} - -/* - * bdx_get_tx_csum - report whether transmit checksums are turned on or off - * @netdev - */ -static u32 bdx_get_tx_csum(struct net_device *netdev) -{ - return (netdev->features & NETIF_F_IP_CSUM) != 0; -} - /* * bdx_get_coalesce - get interrupt coalescing parameters * @netdev @@ -2424,10 +2408,6 @@ static void bdx_set_ethtool_ops(struct net_device *netdev) .set_coalesce = bdx_set_coalesce, .get_ringparam = bdx_get_ringparam, .set_ringparam = bdx_set_ringparam, - .get_rx_csum = bdx_get_rx_csum, - .get_tx_csum = bdx_get_tx_csum, - .get_sg = ethtool_op_get_sg, - .get_tso = ethtool_op_get_tso, .get_strings = bdx_get_strings, .get_sset_count = bdx_get_sset_count, .get_ethtool_stats = bdx_get_ethtool_stats, -- cgit v1.2.3-58-ga151 From aad59c431b77be5cbfa01f2066a036b95981fed9 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 17 Apr 2011 00:15:46 +0000 Subject: net: mv643xx: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Side effect: don't reenable RXCSUM on every ifdown/ifup. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 34425b94452f..29605a34d4c1 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1575,18 +1575,12 @@ mv643xx_eth_set_ringparam(struct net_device *dev, struct ethtool_ringparam *er) return 0; } -static u32 -mv643xx_eth_get_rx_csum(struct net_device *dev) -{ - struct mv643xx_eth_private *mp = netdev_priv(dev); - - return !!(rdlp(mp, PORT_CONFIG) & 0x02000000); -} static int -mv643xx_eth_set_rx_csum(struct net_device *dev, u32 rx_csum) +mv643xx_eth_set_features(struct net_device *dev, u32 features) { struct mv643xx_eth_private *mp = netdev_priv(dev); + u32 rx_csum = features & NETIF_F_RXCSUM; wrlp(mp, PORT_CONFIG, rx_csum ? 0x02000000 : 0x00000000); @@ -1634,11 +1628,6 @@ static void mv643xx_eth_get_ethtool_stats(struct net_device *dev, } } -static int mv643xx_eth_set_flags(struct net_device *dev, u32 data) -{ - return ethtool_op_set_flags(dev, data, ETH_FLAG_LRO); -} - static int mv643xx_eth_get_sset_count(struct net_device *dev, int sset) { if (sset == ETH_SS_STATS) @@ -1657,14 +1646,8 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops = { .set_coalesce = mv643xx_eth_set_coalesce, .get_ringparam = mv643xx_eth_get_ringparam, .set_ringparam = mv643xx_eth_set_ringparam, - .get_rx_csum = mv643xx_eth_get_rx_csum, - .set_rx_csum = mv643xx_eth_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, .get_strings = mv643xx_eth_get_strings, .get_ethtool_stats = mv643xx_eth_get_ethtool_stats, - .get_flags = ethtool_op_get_flags, - .set_flags = mv643xx_eth_set_flags, .get_sset_count = mv643xx_eth_get_sset_count, }; @@ -2264,7 +2247,7 @@ static void port_start(struct mv643xx_eth_private *mp) * frames to RX queue #0, and include the pseudo-header when * calculating receive checksums. */ - wrlp(mp, PORT_CONFIG, 0x02000000); + mv643xx_eth_set_features(dev, dev->features); /* * Treat BPDUs as normal multicasts, and disable partition mode. @@ -2848,6 +2831,7 @@ static const struct net_device_ops mv643xx_eth_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = mv643xx_eth_ioctl, .ndo_change_mtu = mv643xx_eth_change_mtu, + .ndo_set_features = mv643xx_eth_set_features, .ndo_tx_timeout = mv643xx_eth_tx_timeout, .ndo_get_stats = mv643xx_eth_get_stats, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -2930,7 +2914,9 @@ static int mv643xx_eth_probe(struct platform_device *pdev) dev->watchdog_timeo = 2 * HZ; dev->base_addr = 0; - dev->features = NETIF_F_SG | NETIF_F_IP_CSUM; + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_RXCSUM | NETIF_F_LRO; + dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM; dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM; SET_NETDEV_DEV(dev, &pdev->dev); -- cgit v1.2.3-58-ga151 From 86688a8f132a7630f8610c13a349c711fe683b44 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 17 Apr 2011 00:15:47 +0000 Subject: net: typhoon: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/typhoon.c | 39 ++++++++------------------------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 82653cb07857..119c394f71ce 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -1144,28 +1144,6 @@ typhoon_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) return 0; } -static u32 -typhoon_get_rx_csum(struct net_device *dev) -{ - /* For now, we don't allow turning off RX checksums. - */ - return 1; -} - -static int -typhoon_set_flags(struct net_device *dev, u32 data) -{ - /* There's no way to turn off the RX VLAN offloading and stripping - * on the current 3XP firmware -- it does not respect the offload - * settings -- so we only allow the user to toggle the TX processing. - */ - if (!(data & ETH_FLAG_RXVLAN)) - return -EINVAL; - - return ethtool_op_set_flags(dev, data, - ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN); -} - static void typhoon_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { @@ -1187,13 +1165,7 @@ static const struct ethtool_ops typhoon_ethtool_ops = { .get_wol = typhoon_get_wol, .set_wol = typhoon_set_wol, .get_link = ethtool_op_get_link, - .get_rx_csum = typhoon_get_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = ethtool_op_set_tso, .get_ringparam = typhoon_get_ringparam, - .set_flags = typhoon_set_flags, - .get_flags = ethtool_op_get_flags, }; static int @@ -2482,10 +2454,15 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* We can handle scatter gather, up to 16 entries, and * we can do IP checksumming (only version 4, doh...) + * + * There's no way to turn off the RX VLAN offloading and stripping + * on the current 3XP firmware -- it does not respect the offload + * settings -- so we only allow the user to toggle the TX processing. */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->features |= NETIF_F_TSO; + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_HW_VLAN_TX; + dev->features = dev->hw_features | + NETIF_F_HW_VLAN_RX | NETIF_F_RXCSUM; if(register_netdev(dev) < 0) { err_msg = "unable to register netdev"; -- cgit v1.2.3-58-ga151 From 66a1c5413260a8c302b4024555c489cc6731b463 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 17 Apr 2011 00:15:47 +0000 Subject: net: benet: convert to hw_features - fixup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove be_set_flags() as it's already covered by hw_features. Signed-off-by: Michał Mirosław Acked-by: Ajit Khaparde ajit.khaparde@emulex.com Signed-off-by: David S. Miller --- drivers/net/benet/be_ethtool.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 0f645a92bebe..28716a6061bc 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -712,18 +712,6 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, return status; } -static int be_set_flags(struct net_device *netdev, u32 data) -{ - struct be_adapter *adapter = netdev_priv(netdev); - int rc = -1; - - if (be_multi_rxq(adapter)) - rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_RXHASH | - ETH_FLAG_TXVLAN | ETH_FLAG_RXVLAN); - - return rc; -} - const struct ethtool_ops be_ethtool_ops = { .get_settings = be_get_settings, .get_drvinfo = be_get_drvinfo, @@ -745,5 +733,4 @@ const struct ethtool_ops be_ethtool_ops = { .get_regs = be_get_regs, .flash_device = be_do_flash, .self_test = be_self_test, - .set_flags = be_set_flags, }; -- cgit v1.2.3-58-ga151 From f4786a96252b97f6f05cd42ea7fe6e967048bfa3 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 17 Apr 2011 00:15:47 +0000 Subject: net: ehea: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/ehea/ehea_ethtool.c | 23 ----------------------- drivers/net/ehea/ehea_main.c | 4 +++- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/drivers/net/ehea/ehea_ethtool.c b/drivers/net/ehea/ehea_ethtool.c index 3e2e734fecb7..5f13491cf2a9 100644 --- a/drivers/net/ehea/ehea_ethtool.c +++ b/drivers/net/ehea/ehea_ethtool.c @@ -162,11 +162,6 @@ static void ehea_set_msglevel(struct net_device *dev, u32 value) port->msg_enable = value; } -static u32 ehea_get_rx_csum(struct net_device *dev) -{ - return 1; -} - static char ehea_ethtool_stats_keys[][ETH_GSTRING_LEN] = { {"sig_comp_iv"}, {"swqe_refill_th"}, @@ -263,34 +258,16 @@ static void ehea_get_ethtool_stats(struct net_device *dev, } -static int ehea_set_flags(struct net_device *dev, u32 data) -{ - /* Avoid changing the VLAN flags */ - if ((data & (ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN)) != - (ethtool_op_get_flags(dev) & (ETH_FLAG_RXVLAN | - ETH_FLAG_TXVLAN))){ - return -EINVAL; - } - - return ethtool_op_set_flags(dev, data, ETH_FLAG_LRO - | ETH_FLAG_TXVLAN - | ETH_FLAG_RXVLAN); -} - const struct ethtool_ops ehea_ethtool_ops = { .get_settings = ehea_get_settings, .get_drvinfo = ehea_get_drvinfo, .get_msglevel = ehea_get_msglevel, .set_msglevel = ehea_set_msglevel, .get_link = ethtool_op_get_link, - .set_tso = ethtool_op_set_tso, .get_strings = ehea_get_strings, .get_sset_count = ehea_get_sset_count, .get_ethtool_stats = ehea_get_ethtool_stats, - .get_rx_csum = ehea_get_rx_csum, .set_settings = ehea_set_settings, - .get_flags = ethtool_op_get_flags, - .set_flags = ehea_set_flags, .nway_reset = ehea_nway_reset, /* Restart autonegotiation */ }; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index f75d3144b8a5..ce2f0ca61d9a 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -3262,10 +3262,12 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, dev->netdev_ops = &ehea_netdev_ops; ehea_set_ethtool_ops(dev); + dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO + | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_LRO; dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER - | NETIF_F_LLTX; + | NETIF_F_LLTX | NETIF_F_RXCSUM; dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT; if (use_lro) -- cgit v1.2.3-58-ga151 From 3cd8ef4b6071834fd432bbccbec0611591908643 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 17 Apr 2011 00:15:47 +0000 Subject: net: niu: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Side effect: allow toggling of TX offloads. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/niu.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index ea2272f0f37e..a7072174ffa7 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -7913,11 +7913,6 @@ static int niu_set_phys_id(struct net_device *dev, return 0; } -static int niu_set_flags(struct net_device *dev, u32 data) -{ - return ethtool_op_set_flags(dev, data, ETH_FLAG_RXHASH); -} - static const struct ethtool_ops niu_ethtool_ops = { .get_drvinfo = niu_get_drvinfo, .get_link = ethtool_op_get_link, @@ -7934,8 +7929,6 @@ static const struct ethtool_ops niu_ethtool_ops = { .set_phys_id = niu_set_phys_id, .get_rxnfc = niu_get_nfc, .set_rxnfc = niu_set_nfc, - .set_flags = niu_set_flags, - .get_flags = ethtool_op_get_flags, }; static int niu_ldg_assign_ldn(struct niu *np, struct niu_parent *parent, @@ -9764,8 +9757,8 @@ static void __devinit niu_device_announce(struct niu *np) static void __devinit niu_set_basic_features(struct net_device *dev) { - dev->features |= (NETIF_F_SG | NETIF_F_HW_CSUM | - NETIF_F_GRO | NETIF_F_RXHASH); + dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXHASH; + dev->features |= dev->hw_features | NETIF_F_RXCSUM; } static int __devinit niu_pci_init_one(struct pci_dev *pdev, -- cgit v1.2.3-58-ga151 From 131ae329702755d897c6072c7839086b0702fb10 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 17 Apr 2011 00:15:47 +0000 Subject: net: greth: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note: Driver modifies its struct net_device_ops. This will break if used for multiple devices that are not all the same (if that HW config is possible). Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/greth.c | 46 ++++------------------------------------------ drivers/net/greth.h | 4 ---- 2 files changed, 4 insertions(+), 46 deletions(-) diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 396ff7d785d1..f181304a7ab6 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -901,7 +901,7 @@ static int greth_rx_gbit(struct net_device *dev, int limit) skb_put(skb, pkt_len); - if (greth->flags & GRETH_FLAG_RX_CSUM && hw_checksummed(status)) + if (dev->features & NETIF_F_RXCSUM && hw_checksummed(status)) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb_checksum_none_assert(skb); @@ -1142,41 +1142,6 @@ static void greth_get_regs(struct net_device *dev, struct ethtool_regs *regs, vo buff[i] = greth_read_bd(&greth_regs[i]); } -static u32 greth_get_rx_csum(struct net_device *dev) -{ - struct greth_private *greth = netdev_priv(dev); - return (greth->flags & GRETH_FLAG_RX_CSUM) != 0; -} - -static int greth_set_rx_csum(struct net_device *dev, u32 data) -{ - struct greth_private *greth = netdev_priv(dev); - - spin_lock_bh(&greth->devlock); - - if (data) - greth->flags |= GRETH_FLAG_RX_CSUM; - else - greth->flags &= ~GRETH_FLAG_RX_CSUM; - - spin_unlock_bh(&greth->devlock); - - return 0; -} - -static u32 greth_get_tx_csum(struct net_device *dev) -{ - return (dev->features & NETIF_F_IP_CSUM) != 0; -} - -static int greth_set_tx_csum(struct net_device *dev, u32 data) -{ - netif_tx_lock_bh(dev); - ethtool_op_set_tx_csum(dev, data); - netif_tx_unlock_bh(dev); - return 0; -} - static const struct ethtool_ops greth_ethtool_ops = { .get_msglevel = greth_get_msglevel, .set_msglevel = greth_set_msglevel, @@ -1185,10 +1150,6 @@ static const struct ethtool_ops greth_ethtool_ops = { .get_drvinfo = greth_get_drvinfo, .get_regs_len = greth_get_regs_len, .get_regs = greth_get_regs, - .get_rx_csum = greth_get_rx_csum, - .set_rx_csum = greth_set_rx_csum, - .get_tx_csum = greth_get_tx_csum, - .set_tx_csum = greth_set_tx_csum, .get_link = ethtool_op_get_link, }; @@ -1570,9 +1531,10 @@ static int __devinit greth_of_probe(struct platform_device *ofdev) GRETH_REGSAVE(regs->status, 0xFF); if (greth->gbit_mac) { - dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HIGHDMA; + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_RXCSUM; + dev->features = dev->hw_features | NETIF_F_HIGHDMA; greth_netdev_ops.ndo_start_xmit = greth_start_xmit_gbit; - greth->flags = GRETH_FLAG_RX_CSUM; } if (greth->multicast) { diff --git a/drivers/net/greth.h b/drivers/net/greth.h index be0f2062bd14..9a0040dee4da 100644 --- a/drivers/net/greth.h +++ b/drivers/net/greth.h @@ -77,9 +77,6 @@ */ #define MAX_FRAME_SIZE 1520 -/* Flags */ -#define GRETH_FLAG_RX_CSUM 0x1 - /* GRETH APB registers */ struct greth_regs { u32 control; @@ -133,7 +130,6 @@ struct greth_private { unsigned int duplex; u32 msg_enable; - u32 flags; u8 phyaddr; u8 multicast; -- cgit v1.2.3-58-ga151 From 5e4011e2b8032cd132d9482f016558f1b27569cd Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 17 Apr 2011 00:15:47 +0000 Subject: net: ibm_newemac: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Side effect: allow toggling of TX offloads. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/ibm_newemac/core.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 3bb990b6651a..079450fe5e96 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -2053,13 +2053,6 @@ static void emac_ethtool_get_pauseparam(struct net_device *ndev, mutex_unlock(&dev->link_lock); } -static u32 emac_ethtool_get_rx_csum(struct net_device *ndev) -{ - struct emac_instance *dev = netdev_priv(ndev); - - return dev->tah_dev != NULL; -} - static int emac_get_regs_len(struct emac_instance *dev) { if (emac_has_feature(dev, EMAC_FTR_EMAC4)) @@ -2203,15 +2196,11 @@ static const struct ethtool_ops emac_ethtool_ops = { .get_ringparam = emac_ethtool_get_ringparam, .get_pauseparam = emac_ethtool_get_pauseparam, - .get_rx_csum = emac_ethtool_get_rx_csum, - .get_strings = emac_ethtool_get_strings, .get_sset_count = emac_ethtool_get_sset_count, .get_ethtool_stats = emac_ethtool_get_ethtool_stats, .get_link = ethtool_op_get_link, - .get_tx_csum = ethtool_op_get_tx_csum, - .get_sg = ethtool_op_get_sg, }; static int emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) @@ -2859,8 +2848,10 @@ static int __devinit emac_probe(struct platform_device *ofdev) if (err != 0) goto err_detach_tah; - if (dev->tah_dev) - ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; + if (dev->tah_dev) { + ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG; + ndev->features |= ndev->hw_features | NETIF_F_RXCSUM; + } ndev->watchdog_timeo = 5 * HZ; if (emac_phy_supports_gige(dev->phy_mode)) { ndev->netdev_ops = &emac_gige_netdev_ops; -- cgit v1.2.3-58-ga151 From c582a950b1d7488750831cb4499de071781c7f45 Mon Sep 17 00:00:00 2001 From: Thiago Farina Date: Sun, 17 Apr 2011 17:49:21 -0700 Subject: drivers/net/usb/usbnet.c: Use FIELD_SIZEOF macro in usbnet_init() function. Signed-off-by: Thiago Farina Signed-off-by: David S. Miller --- drivers/net/usb/usbnet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 069c1cf0fdf7..7bc9852bd57c 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1529,9 +1529,9 @@ EXPORT_SYMBOL_GPL(usbnet_resume); static int __init usbnet_init(void) { - /* compiler should optimize this out */ - BUILD_BUG_ON (sizeof (((struct sk_buff *)0)->cb) - < sizeof (struct skb_data)); + /* Compiler should optimize this out. */ + BUILD_BUG_ON( + FIELD_SIZEOF(struct sk_buff, cb) < sizeof(struct skb_data)); random_ether_addr(node_id); return 0; -- cgit v1.2.3-58-ga151 From 2ed28baa7076083b56c1e70ccd927b7870117c59 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sat, 16 Apr 2011 13:05:08 +0000 Subject: net: cxgb4{,vf}: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Acked-by: Dimitris Michailidis Signed-off-by: David S. Miller --- drivers/net/cxgb4/cxgb4.h | 6 ---- drivers/net/cxgb4/cxgb4_main.c | 72 +++++++++----------------------------- drivers/net/cxgb4/sge.c | 4 +-- drivers/net/cxgb4vf/adapter.h | 6 ---- drivers/net/cxgb4vf/cxgb4vf_main.c | 57 +++++------------------------- drivers/net/cxgb4vf/sge.c | 4 +-- 6 files changed, 28 insertions(+), 121 deletions(-) diff --git a/drivers/net/cxgb4/cxgb4.h b/drivers/net/cxgb4/cxgb4.h index 01d49eaa44d2..bc9982a4c1f4 100644 --- a/drivers/net/cxgb4/cxgb4.h +++ b/drivers/net/cxgb4/cxgb4.h @@ -290,7 +290,6 @@ struct port_info { u8 port_id; u8 tx_chan; u8 lport; /* associated offload logical port */ - u8 rx_offload; /* CSO, etc */ u8 nqsets; /* # of qsets */ u8 first_qset; /* index of first qset */ u8 rss_mode; @@ -298,11 +297,6 @@ struct port_info { u16 *rss; }; -/* port_info.rx_offload flags */ -enum { - RX_CSO = 1 << 0, -}; - struct dentry; struct work_struct; diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c index 0af9c9f0ca78..bdc868ca47ec 100644 --- a/drivers/net/cxgb4/cxgb4_main.c +++ b/drivers/net/cxgb4/cxgb4_main.c @@ -1531,24 +1531,6 @@ static int set_pauseparam(struct net_device *dev, return 0; } -static u32 get_rx_csum(struct net_device *dev) -{ - struct port_info *p = netdev_priv(dev); - - return p->rx_offload & RX_CSO; -} - -static int set_rx_csum(struct net_device *dev, u32 data) -{ - struct port_info *p = netdev_priv(dev); - - if (data) - p->rx_offload |= RX_CSO; - else - p->rx_offload &= ~RX_CSO; - return 0; -} - static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e) { const struct port_info *pi = netdev_priv(dev); @@ -1870,36 +1852,20 @@ static int set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) return err; } -#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN) - -static int set_tso(struct net_device *dev, u32 value) -{ - if (value) - dev->features |= TSO_FLAGS; - else - dev->features &= ~TSO_FLAGS; - return 0; -} - -static int set_flags(struct net_device *dev, u32 flags) +static int cxgb_set_features(struct net_device *dev, u32 features) { + const struct port_info *pi = netdev_priv(dev); + u32 changed = dev->features ^ features; int err; - unsigned long old_feat = dev->features; - - err = ethtool_op_set_flags(dev, flags, ETH_FLAG_RXHASH | - ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN); - if (err) - return err; - if ((old_feat ^ dev->features) & NETIF_F_HW_VLAN_RX) { - const struct port_info *pi = netdev_priv(dev); + if (!(changed & NETIF_F_HW_VLAN_RX)) + return 0; - err = t4_set_rxmode(pi->adapter, pi->adapter->fn, pi->viid, -1, - -1, -1, -1, !!(flags & ETH_FLAG_RXVLAN), - true); - if (err) - dev->features = old_feat; - } + err = t4_set_rxmode(pi->adapter, pi->adapter->fn, pi->viid, -1, + -1, -1, -1, + !!(features & NETIF_F_HW_VLAN_RX), true); + if (unlikely(err)) + dev->features = features ^ NETIF_F_HW_VLAN_RX; return err; } @@ -2010,10 +1976,6 @@ static struct ethtool_ops cxgb_ethtool_ops = { .set_eeprom = set_eeprom, .get_pauseparam = get_pauseparam, .set_pauseparam = set_pauseparam, - .get_rx_csum = get_rx_csum, - .set_rx_csum = set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_ipv6_csum, - .set_sg = ethtool_op_set_sg, .get_link = ethtool_op_get_link, .get_strings = get_strings, .set_phys_id = identify_port, @@ -2024,8 +1986,6 @@ static struct ethtool_ops cxgb_ethtool_ops = { .get_regs = get_regs, .get_wol = get_wol, .set_wol = set_wol, - .set_tso = set_tso, - .set_flags = set_flags, .get_rxnfc = get_rxnfc, .get_rxfh_indir = get_rss_table, .set_rxfh_indir = set_rss_table, @@ -2882,6 +2842,7 @@ static const struct net_device_ops cxgb4_netdev_ops = { .ndo_get_stats64 = cxgb_get_stats, .ndo_set_rx_mode = cxgb_set_rxmode, .ndo_set_mac_address = cxgb_set_mac_addr, + .ndo_set_features = cxgb_set_features, .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = cxgb_ioctl, .ndo_change_mtu = cxgb_change_mtu, @@ -3564,6 +3525,7 @@ static void free_some_resources(struct adapter *adapter) t4_fw_bye(adapter, adapter->fn); } +#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN) #define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \ NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA) @@ -3665,14 +3627,14 @@ static int __devinit init_one(struct pci_dev *pdev, pi = netdev_priv(netdev); pi->adapter = adapter; pi->xact_addr_filt = -1; - pi->rx_offload = RX_CSO; pi->port_id = i; netdev->irq = pdev->irq; - netdev->features |= NETIF_F_SG | TSO_FLAGS; - netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - netdev->features |= NETIF_F_GRO | NETIF_F_RXHASH | highdma; - netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + netdev->hw_features = NETIF_F_SG | TSO_FLAGS | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM | NETIF_F_RXHASH | + NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + netdev->features |= netdev->hw_features | highdma; netdev->vlan_features = netdev->features & VLAN_FEAT; netdev->netdev_ops = &cxgb4_netdev_ops; diff --git a/drivers/net/cxgb4/sge.c b/drivers/net/cxgb4/sge.c index 311471b439a8..75a4b0fa19ee 100644 --- a/drivers/net/cxgb4/sge.c +++ b/drivers/net/cxgb4/sge.c @@ -1556,7 +1556,6 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp, { bool csum_ok; struct sk_buff *skb; - struct port_info *pi; const struct cpl_rx_pkt *pkt; struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq); @@ -1584,10 +1583,9 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp, if (skb->dev->features & NETIF_F_RXHASH) skb->rxhash = (__force u32)pkt->rsshdr.hash_val; - pi = netdev_priv(skb->dev); rxq->stats.pkts++; - if (csum_ok && (pi->rx_offload & RX_CSO) && + if (csum_ok && (q->netdev->features & NETIF_F_RXCSUM) && (pkt->l2info & htonl(RXF_UDP | RXF_TCP))) { if (!pkt->ip_frag) { skb->ip_summed = CHECKSUM_UNNECESSARY; diff --git a/drivers/net/cxgb4vf/adapter.h b/drivers/net/cxgb4vf/adapter.h index 4766b4116b41..4fd821aadc8a 100644 --- a/drivers/net/cxgb4vf/adapter.h +++ b/drivers/net/cxgb4vf/adapter.h @@ -97,17 +97,11 @@ struct port_info { u16 rss_size; /* size of VI's RSS table slice */ u8 pidx; /* index into adapter port[] */ u8 port_id; /* physical port ID */ - u8 rx_offload; /* CSO, etc. */ u8 nqsets; /* # of "Queue Sets" */ u8 first_qset; /* index of first "Queue Set" */ struct link_config link_cfg; /* physical port configuration */ }; -/* port_info.rx_offload flags */ -enum { - RX_CSO = 1 << 0, -}; - /* * Scatter Gather Engine resources for the "adapter". Our ingress and egress * queues are organized into "Queue Sets" with one ingress and one egress diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c index c662679de4fa..8cf9890cafaf 100644 --- a/drivers/net/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/cxgb4vf/cxgb4vf_main.c @@ -1325,30 +1325,6 @@ static void cxgb4vf_get_pauseparam(struct net_device *dev, pauseparam->tx_pause = (pi->link_cfg.fc & PAUSE_TX) != 0; } -/* - * Return whether RX Checksum Offloading is currently enabled for the device. - */ -static u32 cxgb4vf_get_rx_csum(struct net_device *dev) -{ - struct port_info *pi = netdev_priv(dev); - - return (pi->rx_offload & RX_CSO) != 0; -} - -/* - * Turn RX Checksum Offloading on or off for the device. - */ -static int cxgb4vf_set_rx_csum(struct net_device *dev, u32 csum) -{ - struct port_info *pi = netdev_priv(dev); - - if (csum) - pi->rx_offload |= RX_CSO; - else - pi->rx_offload &= ~RX_CSO; - return 0; -} - /* * Identify the port by blinking the port's LED. */ @@ -1569,18 +1545,6 @@ static void cxgb4vf_get_wol(struct net_device *dev, */ #define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN) -/* - * Set TCP Segmentation Offloading feature capabilities. - */ -static int cxgb4vf_set_tso(struct net_device *dev, u32 tso) -{ - if (tso) - dev->features |= TSO_FLAGS; - else - dev->features &= ~TSO_FLAGS; - return 0; -} - static struct ethtool_ops cxgb4vf_ethtool_ops = { .get_settings = cxgb4vf_get_settings, .get_drvinfo = cxgb4vf_get_drvinfo, @@ -1591,10 +1555,6 @@ static struct ethtool_ops cxgb4vf_ethtool_ops = { .get_coalesce = cxgb4vf_get_coalesce, .set_coalesce = cxgb4vf_set_coalesce, .get_pauseparam = cxgb4vf_get_pauseparam, - .get_rx_csum = cxgb4vf_get_rx_csum, - .set_rx_csum = cxgb4vf_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_ipv6_csum, - .set_sg = ethtool_op_set_sg, .get_link = ethtool_op_get_link, .get_strings = cxgb4vf_get_strings, .set_phys_id = cxgb4vf_phys_id, @@ -1603,7 +1563,6 @@ static struct ethtool_ops cxgb4vf_ethtool_ops = { .get_regs_len = cxgb4vf_get_regs_len, .get_regs = cxgb4vf_get_regs, .get_wol = cxgb4vf_get_wol, - .set_tso = cxgb4vf_set_tso, }; /* @@ -2638,19 +2597,19 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev, * it. */ pi->xact_addr_filt = -1; - pi->rx_offload = RX_CSO; netif_carrier_off(netdev); netdev->irq = pdev->irq; - netdev->features = (NETIF_F_SG | TSO_FLAGS | - NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | - NETIF_F_GRO); + netdev->hw_features = NETIF_F_SG | TSO_FLAGS | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM; + netdev->vlan_features = NETIF_F_SG | TSO_FLAGS | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_HIGHDMA; + netdev->features = netdev->hw_features | + NETIF_F_HW_VLAN_RX; if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; - netdev->vlan_features = - (netdev->features & - ~(NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX)); #ifdef HAVE_NET_DEVICE_OPS netdev->netdev_ops = &cxgb4vf_netdev_ops; diff --git a/drivers/net/cxgb4vf/sge.c b/drivers/net/cxgb4vf/sge.c index bb65121f581c..5182960e29fd 100644 --- a/drivers/net/cxgb4vf/sge.c +++ b/drivers/net/cxgb4vf/sge.c @@ -1555,8 +1555,8 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp, pi = netdev_priv(skb->dev); rxq->stats.pkts++; - if (csum_ok && (pi->rx_offload & RX_CSO) && !pkt->err_vec && - (be32_to_cpu(pkt->l2info) & (RXF_UDP|RXF_TCP))) { + if (csum_ok && (rspq->netdev->features & NETIF_F_RXCSUM) && + !pkt->err_vec && (be32_to_cpu(pkt->l2info) & (RXF_UDP|RXF_TCP))) { if (!pkt->ip_frag) skb->ip_summed = CHECKSUM_UNNECESSARY; else { -- cgit v1.2.3-58-ga151 From 28674b97cfb907b0b3de7b7fea89efda1e65f34e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 17 Apr 2011 17:52:51 -0700 Subject: bridge: fix accidental creation of sysfs directory Commit bb900b27a2f49b37bc38c08e656ea13048fee13b ("bridge: allow creating bridge devices with netlink") introduced a bug in net-next because of a typo in notifier. Every device would have the sysfs bridge directory (and files). Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 7a03bb975375..606b323e8a0c 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c @@ -37,7 +37,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v int err; /* register of bridge completed, add sysfs entries */ - if ((dev->priv_flags && IFF_EBRIDGE) && event == NETDEV_REGISTER) { + if ((dev->priv_flags & IFF_EBRIDGE) && event == NETDEV_REGISTER) { br_sysfs_addbr(dev); return NOTIFY_DONE; } -- cgit v1.2.3-58-ga151 From df4511feb76173db872c8845b63179dd15f2b7da Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 16 Apr 2011 14:15:25 +0000 Subject: via_rhine: Use netdev_ and pr_ Use the more current logging styles. Add #define DEBUG to make netdev_dbg always active. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/via-rhine.c | 230 +++++++++++++++++++++++------------------------- 1 file changed, 108 insertions(+), 122 deletions(-) diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 0422a79acfd7..40f394ce113b 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -29,6 +29,8 @@ */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRV_NAME "via-rhine" #define DRV_VERSION "1.5.0" #define DRV_RELDATE "2010-10-09" @@ -37,6 +39,7 @@ /* A few user-configurable values. These may be modified when a driver module is loaded. */ +#define DEBUG static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ static int max_interrupt_work = 20; @@ -111,8 +114,7 @@ static const int multicast_filter_limit = 32; /* These identify the driver base version and may not be removed. */ static const char version[] __devinitconst = - KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VERSION " " DRV_RELDATE - " Written by Donald Becker\n"; + "v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker"; /* This driver was written to use PCI memory space. Some early versions of the Rhine may only work correctly with I/O space accesses. */ @@ -495,14 +497,15 @@ static void rhine_set_vlan_cam_mask(void __iomem *ioaddr, u32 mask); static void rhine_init_cam_filter(struct net_device *dev); static void rhine_update_vcam(struct net_device *dev); -#define RHINE_WAIT_FOR(condition) do { \ - int i=1024; \ - while (!(condition) && --i) \ - ; \ - if (debug > 1 && i < 512) \ - printk(KERN_INFO "%s: %4d cycles used @ %s:%d\n", \ - DRV_NAME, 1024-i, __func__, __LINE__); \ -} while(0) +#define RHINE_WAIT_FOR(condition) \ +do { \ + int i = 1024; \ + while (!(condition) && --i) \ + ; \ + if (debug > 1 && i < 512) \ + pr_info("%4d cycles used @ %s:%d\n", \ + 1024 - i, __func__, __LINE__); \ +} while (0) static inline u32 get_intr_status(struct net_device *dev) { @@ -571,8 +574,8 @@ static void rhine_power_init(struct net_device *dev) default: reason = "Unknown"; } - printk(KERN_INFO "%s: Woke system up. Reason: %s.\n", - DRV_NAME, reason); + netdev_info(dev, "Woke system up. Reason: %s\n", + reason); } } } @@ -586,8 +589,7 @@ static void rhine_chip_reset(struct net_device *dev) IOSYNC; if (ioread8(ioaddr + ChipCmd1) & Cmd1Reset) { - printk(KERN_INFO "%s: Reset not complete yet. " - "Trying harder.\n", DRV_NAME); + netdev_info(dev, "Reset not complete yet. Trying harder.\n"); /* Force reset */ if (rp->quirks & rqForceReset) @@ -598,9 +600,9 @@ static void rhine_chip_reset(struct net_device *dev) } if (debug > 1) - printk(KERN_INFO "%s: Reset %s.\n", dev->name, - (ioread8(ioaddr + ChipCmd1) & Cmd1Reset) ? - "failed" : "succeeded"); + netdev_info(dev, "Reset %s\n", + (ioread8(ioaddr + ChipCmd1) & Cmd1Reset) ? + "failed" : "succeeded"); } #ifdef USE_MMIO @@ -728,9 +730,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, /* when built into the kernel, we only print version if device is found */ #ifndef MODULE - static int printed_version; - if (!printed_version++) - printk(version); + pr_info_once("%s\n", version); #endif io_size = 256; @@ -765,8 +765,8 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, /* this should always be supported */ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (rc) { - printk(KERN_ERR "32-bit PCI DMA addresses not supported by " - "the card!?\n"); + dev_err(&pdev->dev, + "32-bit PCI DMA addresses not supported by the card!?\n"); goto err_out; } @@ -774,7 +774,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, if ((pci_resource_len(pdev, 0) < io_size) || (pci_resource_len(pdev, 1) < io_size)) { rc = -EIO; - printk(KERN_ERR "Insufficient PCI resources, aborting\n"); + dev_err(&pdev->dev, "Insufficient PCI resources, aborting\n"); goto err_out; } @@ -786,7 +786,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, dev = alloc_etherdev(sizeof(struct rhine_private)); if (!dev) { rc = -ENOMEM; - printk(KERN_ERR "alloc_etherdev failed\n"); + dev_err(&pdev->dev, "alloc_etherdev failed\n"); goto err_out; } SET_NETDEV_DEV(dev, &pdev->dev); @@ -804,8 +804,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, ioaddr = pci_iomap(pdev, bar, io_size); if (!ioaddr) { rc = -EIO; - printk(KERN_ERR "ioremap failed for device %s, region 0x%X " - "@ 0x%lX\n", pci_name(pdev), io_size, memaddr); + dev_err(&pdev->dev, + "ioremap failed for device %s, region 0x%X @ 0x%lX\n", + pci_name(pdev), io_size, memaddr); goto err_out_free_res; } @@ -820,8 +821,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, unsigned char b = readb(ioaddr+reg); if (a != b) { rc = -EIO; - printk(KERN_ERR "MMIO do not match PIO [%02x] " - "(%02x != %02x)\n", reg, a, b); + dev_err(&pdev->dev, + "MMIO do not match PIO [%02x] (%02x != %02x)\n", + reg, a, b); goto err_out_unmap; } } @@ -840,7 +842,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, if (!is_valid_ether_addr(dev->perm_addr)) { rc = -EIO; - printk(KERN_ERR "Invalid MAC address\n"); + dev_err(&pdev->dev, "Invalid MAC address\n"); goto err_out_unmap; } @@ -878,14 +880,14 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, if (rc) goto err_out_unmap; - printk(KERN_INFO "%s: VIA %s at 0x%lx, %pM, IRQ %d.\n", - dev->name, name, + netdev_info(dev, "VIA %s at 0x%lx, %pM, IRQ %d\n", + name, #ifdef USE_MMIO - memaddr, + memaddr, #else - (long)ioaddr, + (long)ioaddr, #endif - dev->dev_addr, pdev->irq); + dev->dev_addr, pdev->irq); pci_set_drvdata(pdev, dev); @@ -896,11 +898,11 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, mdio_write(dev, phy_id, MII_BMCR, mii_cmd); if (mii_status != 0xffff && mii_status != 0x0000) { rp->mii_if.advertising = mdio_read(dev, phy_id, 4); - printk(KERN_INFO "%s: MII PHY found at address " - "%d, status 0x%4.4x advertising %4.4x " - "Link %4.4x.\n", dev->name, phy_id, - mii_status, rp->mii_if.advertising, - mdio_read(dev, phy_id, 5)); + netdev_info(dev, + "MII PHY found at address %d, status 0x%04x advertising %04x Link %04x\n", + phy_id, + mii_status, rp->mii_if.advertising, + mdio_read(dev, phy_id, 5)); /* set IFF_RUNNING */ if (mii_status & BMSR_LSTATUS) @@ -912,8 +914,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, } rp->mii_if.phy_id = phy_id; if (debug > 1 && avoid_D3) - printk(KERN_INFO "%s: No D3 power state at shutdown.\n", - dev->name); + netdev_info(dev, "No D3 power state at shutdown\n"); return 0; @@ -938,7 +939,7 @@ static int alloc_ring(struct net_device* dev) TX_RING_SIZE * sizeof(struct tx_desc), &ring_dma); if (!ring) { - printk(KERN_ERR "Could not allocate DMA memory.\n"); + netdev_err(dev, "Could not allocate DMA memory\n"); return -ENOMEM; } if (rp->quirks & rqRhineI) { @@ -1098,8 +1099,8 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media) iowrite8(ioread8(ioaddr + ChipCmd1) & ~Cmd1FDuplex, ioaddr + ChipCmd1); if (debug > 1) - printk(KERN_INFO "%s: force_media %d, carrier %d\n", dev->name, - rp->mii_if.force_media, netif_carrier_ok(dev)); + netdev_info(dev, "force_media %d, carrier %d\n", + rp->mii_if.force_media, netif_carrier_ok(dev)); } /* Called after status of force_media possibly changed */ @@ -1113,9 +1114,8 @@ static void rhine_set_carrier(struct mii_if_info *mii) else /* Let MMI library update carrier status */ rhine_check_media(mii->dev, 0); if (debug > 1) - printk(KERN_INFO "%s: force_media %d, carrier %d\n", - mii->dev->name, mii->force_media, - netif_carrier_ok(mii->dev)); + netdev_info(mii->dev, "force_media %d, carrier %d\n", + mii->force_media, netif_carrier_ok(mii->dev)); } /** @@ -1402,8 +1402,7 @@ static int rhine_open(struct net_device *dev) return rc; if (debug > 1) - printk(KERN_DEBUG "%s: rhine_open() irq %d.\n", - dev->name, rp->pdev->irq); + netdev_dbg(dev, "%s() irq %d\n", __func__, rp->pdev->irq); rc = alloc_ring(dev); if (rc) { @@ -1415,10 +1414,9 @@ static int rhine_open(struct net_device *dev) rhine_chip_reset(dev); init_registers(dev); if (debug > 2) - printk(KERN_DEBUG "%s: Done rhine_open(), status %4.4x " - "MII status: %4.4x.\n", - dev->name, ioread16(ioaddr + ChipCmd), - mdio_read(dev, rp->mii_if.phy_id, MII_BMSR)); + netdev_dbg(dev, "%s() Done - status %04x MII status: %04x\n", + __func__, ioread16(ioaddr + ChipCmd), + mdio_read(dev, rp->mii_if.phy_id, MII_BMSR)); netif_start_queue(dev); @@ -1461,10 +1459,9 @@ static void rhine_tx_timeout(struct net_device *dev) struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; - printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status " - "%4.4x, resetting...\n", - dev->name, ioread16(ioaddr + IntrStatus), - mdio_read(dev, rp->mii_if.phy_id, MII_BMSR)); + netdev_warn(dev, "Transmit timed out, status %04x, PHY status %04x, resetting...\n", + ioread16(ioaddr + IntrStatus), + mdio_read(dev, rp->mii_if.phy_id, MII_BMSR)); schedule_work(&rp->reset_task); } @@ -1551,8 +1548,8 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb, spin_unlock_irqrestore(&rp->lock, flags); if (debug > 4) { - printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n", - dev->name, rp->cur_tx-1, entry); + netdev_dbg(dev, "Transmit frame #%d queued in slot %d\n", + rp->cur_tx-1, entry); } return NETDEV_TX_OK; } @@ -1578,8 +1575,8 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance) IOSYNC; if (debug > 4) - printk(KERN_DEBUG "%s: Interrupt, status %8.8x.\n", - dev->name, intr_status); + netdev_dbg(dev, "Interrupt, status %08x\n", + intr_status); if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped | IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) { @@ -1597,9 +1594,9 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance) RHINE_WAIT_FOR(!(ioread8(ioaddr+ChipCmd) & CmdTxOn)); if (debug > 2 && ioread8(ioaddr+ChipCmd) & CmdTxOn) - printk(KERN_WARNING "%s: " - "rhine_interrupt() Tx engine " - "still on.\n", dev->name); + netdev_warn(dev, + "%s: Tx engine still on\n", + __func__); } rhine_tx(dev); } @@ -1611,16 +1608,15 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance) rhine_error(dev, intr_status); if (--boguscnt < 0) { - printk(KERN_WARNING "%s: Too much work at interrupt, " - "status=%#8.8x.\n", - dev->name, intr_status); + netdev_warn(dev, "Too much work at interrupt, status=%#08x\n", + intr_status); break; } } if (debug > 3) - printk(KERN_DEBUG "%s: exiting interrupt, status=%8.8x.\n", - dev->name, ioread16(ioaddr + IntrStatus)); + netdev_dbg(dev, "exiting interrupt, status=%08x\n", + ioread16(ioaddr + IntrStatus)); return IRQ_RETVAL(handled); } @@ -1637,15 +1633,14 @@ static void rhine_tx(struct net_device *dev) while (rp->dirty_tx != rp->cur_tx) { txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status); if (debug > 6) - printk(KERN_DEBUG "Tx scavenge %d status %8.8x.\n", - entry, txstatus); + netdev_dbg(dev, "Tx scavenge %d status %08x\n", + entry, txstatus); if (txstatus & DescOwn) break; if (txstatus & 0x8000) { if (debug > 1) - printk(KERN_DEBUG "%s: Transmit error, " - "Tx status %8.8x.\n", - dev->name, txstatus); + netdev_dbg(dev, "Transmit error, Tx status %08x\n", + txstatus); dev->stats.tx_errors++; if (txstatus & 0x0400) dev->stats.tx_carrier_errors++; @@ -1668,9 +1663,9 @@ static void rhine_tx(struct net_device *dev) else dev->stats.collisions += txstatus & 0x0F; if (debug > 6) - printk(KERN_DEBUG "collisions: %1.1x:%1.1x\n", - (txstatus >> 3) & 0xF, - txstatus & 0xF); + netdev_dbg(dev, "collisions: %1.1x:%1.1x\n", + (txstatus >> 3) & 0xF, + txstatus & 0xF); dev->stats.tx_bytes += rp->tx_skbuff[entry]->len; dev->stats.tx_packets++; } @@ -1714,9 +1709,9 @@ static int rhine_rx(struct net_device *dev, int limit) int entry = rp->cur_rx % RX_RING_SIZE; if (debug > 4) { - printk(KERN_DEBUG "%s: rhine_rx(), entry %d status %8.8x.\n", - dev->name, entry, - le32_to_cpu(rp->rx_head_desc->rx_status)); + netdev_dbg(dev, "%s(), entry %d status %08x\n", + __func__, entry, + le32_to_cpu(rp->rx_head_desc->rx_status)); } /* If EOP is set on the next entry, it's a new packet. Send it up. */ @@ -1730,26 +1725,26 @@ static int rhine_rx(struct net_device *dev, int limit) break; if (debug > 4) - printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n", - desc_status); + netdev_dbg(dev, "%s() status is %08x\n", + __func__, desc_status); if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) { if ((desc_status & RxWholePkt) != RxWholePkt) { - printk(KERN_WARNING "%s: Oversized Ethernet " - "frame spanned multiple buffers, entry " - "%#x length %d status %8.8x!\n", - dev->name, entry, data_size, - desc_status); - printk(KERN_WARNING "%s: Oversized Ethernet " - "frame %p vs %p.\n", dev->name, - rp->rx_head_desc, &rp->rx_ring[entry]); + netdev_warn(dev, + "Oversized Ethernet frame spanned multiple buffers, " + "entry %#x length %d status %08x!\n", + entry, data_size, + desc_status); + netdev_warn(dev, + "Oversized Ethernet frame %p vs %p\n", + rp->rx_head_desc, + &rp->rx_ring[entry]); dev->stats.rx_length_errors++; } else if (desc_status & RxErr) { /* There was a error. */ if (debug > 2) - printk(KERN_DEBUG "rhine_rx() Rx " - "error was %8.8x.\n", - desc_status); + netdev_dbg(dev, "%s() Rx error was %08x\n", + __func__, desc_status); dev->stats.rx_errors++; if (desc_status & 0x0030) dev->stats.rx_length_errors++; @@ -1791,9 +1786,7 @@ static int rhine_rx(struct net_device *dev, int limit) } else { skb = rp->rx_skbuff[entry]; if (skb == NULL) { - printk(KERN_ERR "%s: Inconsistent Rx " - "descriptor chain.\n", - dev->name); + netdev_err(dev, "Inconsistent Rx descriptor chain\n"); break; } rp->rx_skbuff[entry] = NULL; @@ -1886,9 +1879,8 @@ static void rhine_restart_tx(struct net_device *dev) { else { /* This should never happen */ if (debug > 1) - printk(KERN_WARNING "%s: rhine_restart_tx() " - "Another error occurred %8.8x.\n", - dev->name, intr_status); + netdev_warn(dev, "%s() Another error occurred %08x\n", + __func__, intr_status); } } @@ -1909,21 +1901,19 @@ static void rhine_error(struct net_device *dev, int intr_status) } if (intr_status & IntrTxAborted) { if (debug > 1) - printk(KERN_INFO "%s: Abort %8.8x, frame dropped.\n", - dev->name, intr_status); + netdev_info(dev, "Abort %08x, frame dropped\n", + intr_status); } if (intr_status & IntrTxUnderrun) { if (rp->tx_thresh < 0xE0) BYTE_REG_BITS_SET((rp->tx_thresh += 0x20), 0x80, ioaddr + TxConfig); if (debug > 1) - printk(KERN_INFO "%s: Transmitter underrun, Tx " - "threshold now %2.2x.\n", - dev->name, rp->tx_thresh); + netdev_info(dev, "Transmitter underrun, Tx threshold now %02x\n", + rp->tx_thresh); } if (intr_status & IntrTxDescRace) { if (debug > 2) - printk(KERN_INFO "%s: Tx descriptor write-back race.\n", - dev->name); + netdev_info(dev, "Tx descriptor write-back race\n"); } if ((intr_status & IntrTxError) && (intr_status & (IntrTxAborted | @@ -1932,9 +1922,8 @@ static void rhine_error(struct net_device *dev, int intr_status) BYTE_REG_BITS_SET((rp->tx_thresh += 0x20), 0x80, ioaddr + TxConfig); } if (debug > 1) - printk(KERN_INFO "%s: Unspecified error. Tx " - "threshold now %2.2x.\n", - dev->name, rp->tx_thresh); + netdev_info(dev, "Unspecified error. Tx threshold now %02x\n", + rp->tx_thresh); } if (intr_status & (IntrTxAborted | IntrTxUnderrun | IntrTxDescRace | IntrTxError)) @@ -1944,8 +1933,8 @@ static void rhine_error(struct net_device *dev, int intr_status) IntrTxError | IntrTxAborted | IntrNormalSummary | IntrTxDescRace)) { if (debug > 1) - printk(KERN_ERR "%s: Something Wicked happened! " - "%8.8x.\n", dev->name, intr_status); + netdev_err(dev, "Something Wicked happened! %08x\n", + intr_status); } spin_unlock(&rp->lock); @@ -2145,9 +2134,8 @@ static int rhine_close(struct net_device *dev) spin_lock_irq(&rp->lock); if (debug > 1) - printk(KERN_DEBUG "%s: Shutting down ethercard, " - "status was %4.4x.\n", - dev->name, ioread16(ioaddr + ChipCmd)); + netdev_dbg(dev, "Shutting down ethercard, status was %04x\n", + ioread16(ioaddr + ChipCmd)); /* Switch to loopback mode to avoid hardware races. */ iowrite8(rp->tx_thresh | 0x02, ioaddr + TxConfig); @@ -2265,12 +2253,12 @@ static int rhine_resume(struct pci_dev *pdev) return 0; if (request_irq(dev->irq, rhine_interrupt, IRQF_SHARED, dev->name, dev)) - printk(KERN_ERR "via-rhine %s: request_irq failed\n", dev->name); + netdev_err(dev, "request_irq failed\n"); ret = pci_set_power_state(pdev, PCI_D0); if (debug > 1) - printk(KERN_INFO "%s: Entering power state D0 %s (%d).\n", - dev->name, ret ? "failed" : "succeeded", ret); + netdev_info(dev, "Entering power state D0 %s (%d)\n", + ret ? "failed" : "succeeded", ret); pci_restore_state(pdev); @@ -2326,17 +2314,15 @@ static int __init rhine_init(void) { /* when a module, this is printed whether or not devices are found in probe */ #ifdef MODULE - printk(version); + pr_info("%s\n", version); #endif if (dmi_check_system(rhine_dmi_table)) { /* these BIOSes fail at PXE boot if chip is in D3 */ avoid_D3 = 1; - printk(KERN_WARNING "%s: Broken BIOS detected, avoid_D3 " - "enabled.\n", - DRV_NAME); + pr_warn("Broken BIOS detected, avoid_D3 enabled\n"); } else if (avoid_D3) - printk(KERN_INFO "%s: avoid_D3 set.\n", DRV_NAME); + pr_info("avoid_D3 set\n"); return pci_register_driver(&rhine_driver); } -- cgit v1.2.3-58-ga151 From 482e3febc2e7df78411005dcdd7621c16b98b088 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 16 Apr 2011 14:15:26 +0000 Subject: via-rhine: Assign random MAC address if necessary Roger Luethi has had several reports of Rhine NICs providing an invalid MAC address. If so, assign a random MAC address so the hardware can still be used. Tested as a standalone interface, as carrier for ppp, and as a bonding slave. Original-patch-by: Alexandru Gagniuc Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/via-rhine.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 40f394ce113b..7f23ab913fd9 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -838,13 +838,15 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, for (i = 0; i < 6; i++) dev->dev_addr[i] = ioread8(ioaddr + StationAddr + i); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - if (!is_valid_ether_addr(dev->perm_addr)) { - rc = -EIO; - dev_err(&pdev->dev, "Invalid MAC address\n"); - goto err_out_unmap; + if (!is_valid_ether_addr(dev->dev_addr)) { + /* Report it and use a random ethernet address instead */ + netdev_err(dev, "Invalid MAC address: %pM\n", dev->dev_addr); + random_ether_addr(dev->dev_addr); + netdev_info(dev, "Using random MAC address: %pM\n", + dev->dev_addr); } + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); /* For Rhine-I/II, phy_id is loaded from EEPROM */ if (!phy_id) -- cgit v1.2.3-58-ga151 From a01c1335a308ee660518e33db03fb5f5e1dfc166 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 17 Apr 2011 20:47:07 -0700 Subject: decnet: Don't leak entries when rebuilding zone. As noticed by Ben Hutchings, when we move entries from one table to another we leak all except the first entry. Put back the "next" variable removed by commit 9bf9055eb716f85372c41b3fbc51f90bc7653740 ("decnet: Fix set-but-unused variable.") and use it properly. Reported-by: Ben Hutchings Signed-off-by: David S. Miller --- net/decnet/dn_table.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index d8ea583076cf..bd0a52dd1d40 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c @@ -123,11 +123,12 @@ static inline void dn_rebuild_zone(struct dn_zone *dz, struct dn_fib_node **old_ht, int old_divisor) { + struct dn_fib_node *f, **fp, *next; int i; - struct dn_fib_node *f, **fp; for(i = 0; i < old_divisor; i++) { - for(f = old_ht[i]; f; f = f->fn_next) { + for(f = old_ht[i]; f; f = next) { + next = f->fn_next; for(fp = dn_chain_p(f->fn_key, dz); *fp && dn_key_leq((*fp)->fn_key, f->fn_key); fp = &(*fp)->fn_next) -- cgit v1.2.3-58-ga151 From b3337e4cea15beb167e8d3a70ca1023e39abb4e5 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Thu, 14 Apr 2011 16:11:34 +0000 Subject: bnx2x: cosmetics: Using ethtool_cmd_speed() API This updates bnx2x to use the ethtool_cmd_speed() family of functions (see b11f8d8c in 2.6.27-rc3 aka. "ethtool: Expand ethtool_cmd.speed to 32 bits") to get and set the link speed via ethtool. This allows to avoid manually accessing ethtool_cmd's speed_hi field. Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_ethtool.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index 0a5e88d6ba2c..e711a2292446 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c @@ -167,6 +167,7 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct bnx2x *bp = netdev_priv(dev); int cfg_idx = bnx2x_get_link_cfg_idx(bp); + /* Dual Media boards present all available port types */ cmd->supported = bp->port.supported[cfg_idx] | (bp->port.supported[cfg_idx ^ 1] & @@ -176,16 +177,16 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) if ((bp->state == BNX2X_STATE_OPEN) && !(bp->flags & MF_FUNC_DIS) && (bp->link_vars.link_up)) { - cmd->speed = bp->link_vars.line_speed; + ethtool_cmd_speed_set(cmd, bp->link_vars.line_speed); cmd->duplex = bp->link_vars.duplex; } else { - - cmd->speed = bp->link_params.req_line_speed[cfg_idx]; + ethtool_cmd_speed_set( + cmd, bp->link_params.req_line_speed[cfg_idx]); cmd->duplex = bp->link_params.req_duplex[cfg_idx]; } if (IS_MF(bp)) - cmd->speed = bnx2x_get_mf_speed(bp); + ethtool_cmd_speed_set(cmd, bnx2x_get_mf_speed(bp)); if (bp->port.supported[cfg_idx] & SUPPORTED_TP) cmd->port = PORT_TP; @@ -206,10 +207,11 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->maxrxpkt = 0; DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n" - DP_LEVEL " supported 0x%x advertising 0x%x speed %d\n" + DP_LEVEL " supported 0x%x advertising 0x%x speed %u\n" DP_LEVEL " duplex %d port %d phy_address %d transceiver %d\n" DP_LEVEL " autoneg %d maxtxpkt %d maxrxpkt %d\n", - cmd->cmd, cmd->supported, cmd->advertising, cmd->speed, + cmd->cmd, cmd->supported, cmd->advertising, + ethtool_cmd_speed(cmd), cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver, cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt); @@ -226,16 +228,15 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) return 0; DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n" - " supported 0x%x advertising 0x%x speed %d speed_hi %d\n" + " supported 0x%x advertising 0x%x speed %u\n" " duplex %d port %d phy_address %d transceiver %d\n" " autoneg %d maxtxpkt %d maxrxpkt %d\n", - cmd->cmd, cmd->supported, cmd->advertising, cmd->speed, - cmd->speed_hi, + cmd->cmd, cmd->supported, cmd->advertising, + ethtool_cmd_speed(cmd), cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver, cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt); - speed = cmd->speed; - speed |= (cmd->speed_hi << 16); + speed = ethtool_cmd_speed(cmd); if (IS_MF_SI(bp)) { u32 part; @@ -439,7 +440,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) break; default: - DP(NETIF_MSG_LINK, "Unsupported speed %d\n", speed); + DP(NETIF_MSG_LINK, "Unsupported speed %u\n", speed); return -EINVAL; } -- cgit v1.2.3-58-ga151 From f47b94646f30529624c82ab0f9cd5bd3f25ef9d2 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 15 Apr 2011 13:46:02 +0000 Subject: ipv6: Send unsolicited neighbour advertismements when notified The NETDEV_NOTIFY_PEERS notifier is a request to send such advertisements following migration to a different physical link, e.g. virtual machine migration. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- net/ipv6/ndisc.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index f057ff312840..62cbd15b4cde 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -611,6 +611,29 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, inc_opt ? ND_OPT_TARGET_LL_ADDR : 0); } +static void ndisc_send_unsol_na(struct net_device *dev) +{ + struct inet6_dev *idev; + struct inet6_ifaddr *ifa; + struct in6_addr mcaddr; + + idev = in6_dev_get(dev); + if (!idev) + return; + + read_lock_bh(&idev->lock); + list_for_each_entry(ifa, &idev->addr_list, if_list) { + addrconf_addr_solict_mult(&ifa->addr, &mcaddr); + ndisc_send_na(dev, NULL, &mcaddr, &ifa->addr, + /*router=*/ !!idev->cnf.forwarding, + /*solicited=*/ false, /*override=*/ true, + /*inc_opt=*/ true); + } + read_unlock_bh(&idev->lock); + + in6_dev_put(idev); +} + void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, const struct in6_addr *solicit, const struct in6_addr *daddr, const struct in6_addr *saddr) @@ -1723,6 +1746,9 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, neigh_ifdown(&nd_tbl, dev); fib6_run_gc(~0UL, net); break; + case NETDEV_NOTIFY_PEERS: + ndisc_send_unsol_na(dev); + break; default: break; } -- cgit v1.2.3-58-ga151 From 99606477a5888b0ead0284fecb13417b1da8e3af Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 15 Apr 2011 13:46:49 +0000 Subject: vlan: Propagate NETDEV_NOTIFY_PEERS notifier The NETDEV_NOTIFY_PEERS notifier indicates that a device moved to a different physical link; this also applies to any VLAN devices on top of it. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- net/8021q/vlan.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 14ef5efbc653..b2ff70fcf8ea 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -499,6 +499,17 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, case NETDEV_PRE_TYPE_CHANGE: /* Forbid underlaying device to change its type. */ return NOTIFY_BAD; + + case NETDEV_NOTIFY_PEERS: + /* Propagate to vlan devices */ + for (i = 0; i < VLAN_N_VID; i++) { + vlandev = vlan_group_get_device(grp, i); + if (!vlandev) + continue; + + call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, vlandev); + } + break; } out: -- cgit v1.2.3-58-ga151 From 7c89943236750537d26421d9bbb6f6575e2d1e1b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 15 Apr 2011 13:47:51 +0000 Subject: bonding, ipv4, ipv6, vlan: Handle NETDEV_BONDING_FAILOVER like NETDEV_NOTIFY_PEERS It is undesirable for the bonding driver to be poking into higher level protocols, and notifiers provide a way to avoid that. This does mean removing the ability to configure reptitition of gratuitous ARPs and unsolicited NAs. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/bonding/Makefile | 3 -- drivers/net/bonding/bond_main.c | 94 ---------------------------------------- drivers/net/bonding/bond_sysfs.c | 80 ---------------------------------- drivers/net/bonding/bonding.h | 29 ------------- net/8021q/vlan.c | 3 +- net/ipv4/devinet.c | 1 + net/ipv6/ndisc.c | 1 + 7 files changed, 4 insertions(+), 207 deletions(-) diff --git a/drivers/net/bonding/Makefile b/drivers/net/bonding/Makefile index 3c5c014e82b2..4c21bf6b8b2f 100644 --- a/drivers/net/bonding/Makefile +++ b/drivers/net/bonding/Makefile @@ -9,6 +9,3 @@ bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o bond_debugfs.o proc-$(CONFIG_PROC_FS) += bond_procfs.o bonding-objs += $(proc-y) -ipv6-$(subst m,y,$(CONFIG_IPV6)) += bond_ipv6.o -bonding-objs += $(ipv6-y) - diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index fdf9215ada7d..4ce14bdf96dd 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -89,8 +89,6 @@ static int max_bonds = BOND_DEFAULT_MAX_BONDS; static int tx_queues = BOND_DEFAULT_TX_QUEUES; -static int num_grat_arp = 1; -static int num_unsol_na = 1; static int miimon = BOND_LINK_MON_INTERV; static int updelay; static int downdelay; @@ -113,10 +111,6 @@ module_param(max_bonds, int, 0); MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); module_param(tx_queues, int, 0); MODULE_PARM_DESC(tx_queues, "Max number of transmit queues (default = 16)"); -module_param(num_grat_arp, int, 0644); -MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event"); -module_param(num_unsol_na, int, 0644); -MODULE_PARM_DESC(num_unsol_na, "Number of unsolicited IPv6 Neighbor Advertisements packets to send on failover event"); module_param(miimon, int, 0); MODULE_PARM_DESC(miimon, "Link check interval in milliseconds"); module_param(updelay, int, 0); @@ -234,7 +228,6 @@ struct bond_parm_tbl ad_select_tbl[] = { /*-------------------------- Forward declarations ---------------------------*/ -static void bond_send_gratuitous_arp(struct bonding *bond); static int bond_init(struct net_device *bond_dev); static void bond_uninit(struct net_device *bond_dev); @@ -1162,14 +1155,6 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) bond_do_fail_over_mac(bond, new_active, old_active); - if (netif_running(bond->dev)) { - bond->send_grat_arp = bond->params.num_grat_arp; - bond_send_gratuitous_arp(bond); - - bond->send_unsol_na = bond->params.num_unsol_na; - bond_send_unsolicited_na(bond); - } - write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); @@ -2580,18 +2565,6 @@ void bond_mii_monitor(struct work_struct *work) if (bond->slave_cnt == 0) goto re_arm; - if (bond->send_grat_arp) { - read_lock(&bond->curr_slave_lock); - bond_send_gratuitous_arp(bond); - read_unlock(&bond->curr_slave_lock); - } - - if (bond->send_unsol_na) { - read_lock(&bond->curr_slave_lock); - bond_send_unsolicited_na(bond); - read_unlock(&bond->curr_slave_lock); - } - if (bond_miimon_inspect(bond)) { read_unlock(&bond->lock); rtnl_lock(); @@ -2753,42 +2726,6 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) } } -/* - * Kick out a gratuitous ARP for an IP on the bonding master plus one - * for each VLAN above us. - * - * Caller must hold curr_slave_lock for read or better - */ -static void bond_send_gratuitous_arp(struct bonding *bond) -{ - struct slave *slave = bond->curr_active_slave; - struct vlan_entry *vlan; - - pr_debug("bond_send_grat_arp: bond %s slave %s\n", - bond->dev->name, slave ? slave->dev->name : "NULL"); - - if (!slave || !bond->send_grat_arp || - test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state)) - return; - - bond->send_grat_arp--; - - if (bond->master_ip) { - bond_arp_send(slave->dev, ARPOP_REPLY, bond->master_ip, - bond->master_ip, 0); - } - - if (!bond->vlgrp) - return; - - list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { - if (vlan->vlan_ip) { - bond_arp_send(slave->dev, ARPOP_REPLY, vlan->vlan_ip, - vlan->vlan_ip, vlan->vlan_id); - } - } -} - static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 sip, __be32 tip) { int i; @@ -3255,18 +3192,6 @@ void bond_activebackup_arp_mon(struct work_struct *work) if (bond->slave_cnt == 0) goto re_arm; - if (bond->send_grat_arp) { - read_lock(&bond->curr_slave_lock); - bond_send_gratuitous_arp(bond); - read_unlock(&bond->curr_slave_lock); - } - - if (bond->send_unsol_na) { - read_lock(&bond->curr_slave_lock); - bond_send_unsolicited_na(bond); - read_unlock(&bond->curr_slave_lock); - } - if (bond_ab_arp_inspect(bond, delta_in_ticks)) { read_unlock(&bond->lock); rtnl_lock(); @@ -3645,9 +3570,6 @@ static int bond_close(struct net_device *bond_dev) write_lock_bh(&bond->lock); - bond->send_grat_arp = 0; - bond->send_unsol_na = 0; - /* signal timers not to re-arm */ bond->kill_timers = 1; @@ -4724,18 +4646,6 @@ static int bond_check_params(struct bond_params *params) use_carrier = 1; } - if (num_grat_arp < 0 || num_grat_arp > 255) { - pr_warning("Warning: num_grat_arp (%d) not in range 0-255 so it was reset to 1\n", - num_grat_arp); - num_grat_arp = 1; - } - - if (num_unsol_na < 0 || num_unsol_na > 255) { - pr_warning("Warning: num_unsol_na (%d) not in range 0-255 so it was reset to 1\n", - num_unsol_na); - num_unsol_na = 1; - } - /* reset values for 802.3ad */ if (bond_mode == BOND_MODE_8023AD) { if (!miimon) { @@ -4925,8 +4835,6 @@ static int bond_check_params(struct bond_params *params) params->mode = bond_mode; params->xmit_policy = xmit_hashtype; params->miimon = miimon; - params->num_grat_arp = num_grat_arp; - params->num_unsol_na = num_unsol_na; params->arp_interval = arp_interval; params->arp_validate = arp_validate_value; params->updelay = updelay; @@ -5121,7 +5029,6 @@ static int __init bonding_init(void) register_netdevice_notifier(&bond_netdev_notifier); register_inetaddr_notifier(&bond_inetaddr_notifier); - bond_register_ipv6_notifier(); out: return res; err: @@ -5136,7 +5043,6 @@ static void __exit bonding_exit(void) { unregister_netdevice_notifier(&bond_netdev_notifier); unregister_inetaddr_notifier(&bond_inetaddr_notifier); - bond_unregister_ipv6_notifier(); bond_destroy_sysfs(); bond_destroy_debugfs(); diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index de87aea6d01a..259ff32cd573 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -873,84 +873,6 @@ out: static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR, bonding_show_ad_select, bonding_store_ad_select); -/* - * Show and set the number of grat ARP to send after a failover event. - */ -static ssize_t bonding_show_n_grat_arp(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct bonding *bond = to_bond(d); - - return sprintf(buf, "%d\n", bond->params.num_grat_arp); -} - -static ssize_t bonding_store_n_grat_arp(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int new_value, ret = count; - struct bonding *bond = to_bond(d); - - if (sscanf(buf, "%d", &new_value) != 1) { - pr_err("%s: no num_grat_arp value specified.\n", - bond->dev->name); - ret = -EINVAL; - goto out; - } - if (new_value < 0 || new_value > 255) { - pr_err("%s: Invalid num_grat_arp value %d not in range 0-255; rejected.\n", - bond->dev->name, new_value); - ret = -EINVAL; - goto out; - } else { - bond->params.num_grat_arp = new_value; - } -out: - return ret; -} -static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, - bonding_show_n_grat_arp, bonding_store_n_grat_arp); - -/* - * Show and set the number of unsolicited NA's to send after a failover event. - */ -static ssize_t bonding_show_n_unsol_na(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct bonding *bond = to_bond(d); - - return sprintf(buf, "%d\n", bond->params.num_unsol_na); -} - -static ssize_t bonding_store_n_unsol_na(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int new_value, ret = count; - struct bonding *bond = to_bond(d); - - if (sscanf(buf, "%d", &new_value) != 1) { - pr_err("%s: no num_unsol_na value specified.\n", - bond->dev->name); - ret = -EINVAL; - goto out; - } - - if (new_value < 0 || new_value > 255) { - pr_err("%s: Invalid num_unsol_na value %d not in range 0-255; rejected.\n", - bond->dev->name, new_value); - ret = -EINVAL; - goto out; - } else - bond->params.num_unsol_na = new_value; -out: - return ret; -} -static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR, - bonding_show_n_unsol_na, bonding_store_n_unsol_na); - /* * Show and set the MII monitor interval. There are two tricky bits * here. First, if MII monitoring is activated, then we must disable @@ -1650,8 +1572,6 @@ static struct attribute *per_bond_attrs[] = { &dev_attr_lacp_rate.attr, &dev_attr_ad_select.attr, &dev_attr_xmit_hash_policy.attr, - &dev_attr_num_grat_arp.attr, - &dev_attr_num_unsol_na.attr, &dev_attr_miimon.attr, &dev_attr_primary.attr, &dev_attr_primary_reselect.attr, diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 553c764f7407..6126c6a13a74 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -149,8 +149,6 @@ struct bond_params { int mode; int xmit_policy; int miimon; - int num_grat_arp; - int num_unsol_na; int arp_interval; int arp_validate; int use_carrier; @@ -178,9 +176,6 @@ struct vlan_entry { struct list_head vlan_list; __be32 vlan_ip; unsigned short vlan_id; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - struct in6_addr vlan_ipv6; -#endif }; struct slave { @@ -234,8 +229,6 @@ struct bonding { rwlock_t lock; rwlock_t curr_slave_lock; s8 kill_timers; - s8 send_grat_arp; - s8 send_unsol_na; s8 setup_by_slave; s8 igmp_retrans; #ifdef CONFIG_PROC_FS @@ -260,9 +253,6 @@ struct bonding { struct delayed_work alb_work; struct delayed_work ad_work; struct delayed_work mcast_work; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - struct in6_addr master_ipv6; -#endif #ifdef CONFIG_DEBUG_FS /* debugging suport via debugfs */ struct dentry *debug_dir; @@ -460,23 +450,4 @@ extern const struct bond_parm_tbl fail_over_mac_tbl[]; extern const struct bond_parm_tbl pri_reselect_tbl[]; extern struct bond_parm_tbl ad_select_tbl[]; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -void bond_send_unsolicited_na(struct bonding *bond); -void bond_register_ipv6_notifier(void); -void bond_unregister_ipv6_notifier(void); -#else -static inline void bond_send_unsolicited_na(struct bonding *bond) -{ - return; -} -static inline void bond_register_ipv6_notifier(void) -{ - return; -} -static inline void bond_unregister_ipv6_notifier(void) -{ - return; -} -#endif - #endif /* _LINUX_BONDING_H */ diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index b2ff70fcf8ea..969e7004cf86 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -501,13 +501,14 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, return NOTIFY_BAD; case NETDEV_NOTIFY_PEERS: + case NETDEV_BONDING_FAILOVER: /* Propagate to vlan devices */ for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; - call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, vlandev); + call_netdevice_notifiers(event, vlandev); } break; } diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 5345b0bee6df..acf553f95b5b 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1203,6 +1203,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, break; /* fall through */ case NETDEV_NOTIFY_PEERS: + case NETDEV_BONDING_FAILOVER: /* Send gratuitous ARP to notify of link change */ inetdev_send_gratuitous_arp(dev, in_dev); break; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 62cbd15b4cde..01a0ffc7b402 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1747,6 +1747,7 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, fib6_run_gc(~0UL, net); break; case NETDEV_NOTIFY_PEERS: + case NETDEV_BONDING_FAILOVER: ndisc_send_unsol_na(dev); break; default: -- cgit v1.2.3-58-ga151 From e79b1ca75bb48111e8d93fc576f50e24671f5f9d Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 5 Apr 2011 08:30:43 -0700 Subject: iwlagn: use direct call for led functions After driver split, no need to call led functions through callback Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/Makefile | 2 +- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 - drivers/net/wireless/iwlwifi/iwl-2000.c | 5 -- drivers/net/wireless/iwlwifi/iwl-5000.c | 3 -- drivers/net/wireless/iwlwifi/iwl-6000.c | 5 -- drivers/net/wireless/iwlwifi/iwl-agn-led.c | 73 ------------------------------ drivers/net/wireless/iwlwifi/iwl-agn-led.h | 33 -------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl-core.h | 1 - drivers/net/wireless/iwlwifi/iwl-led.c | 26 ++++++++++- drivers/net/wireless/iwlwifi/iwl-led.h | 1 + 11 files changed, 27 insertions(+), 125 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-led.c delete mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-led.h diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 3652931753e0..bb6a737de61f 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -1,6 +1,6 @@ # AGN obj-$(CONFIG_IWLAGN) += iwlagn.o -iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o +iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index d1d7852f0ee4..809117d74196 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -45,7 +45,6 @@ #include "iwl-agn.h" #include "iwl-helpers.h" #include "iwl-agn-hw.h" -#include "iwl-agn-led.h" #include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ @@ -226,7 +225,6 @@ static const struct iwl_ops iwl1000_ops = { .lib = &iwl1000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .led = &iwlagn_led_ops, .ieee80211_ops = &iwlagn_hw_ops, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index a31314fdb053..0a330d16ce7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -46,7 +46,6 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" -#include "iwl-agn-led.h" #include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ @@ -310,7 +309,6 @@ static const struct iwl_ops iwl2000_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .led = &iwlagn_led_ops, .ieee80211_ops = &iwlagn_hw_ops, }; @@ -318,7 +316,6 @@ static const struct iwl_ops iwl2030_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_bt_hcmd, .utils = &iwlagn_hcmd_utils, - .led = &iwlagn_led_ops, .ieee80211_ops = &iwlagn_hw_ops, }; @@ -326,7 +323,6 @@ static const struct iwl_ops iwl200_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .led = &iwlagn_led_ops, .ieee80211_ops = &iwlagn_hw_ops, }; @@ -334,7 +330,6 @@ static const struct iwl_ops iwl230_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_bt_hcmd, .utils = &iwlagn_hcmd_utils, - .led = &iwlagn_led_ops, .ieee80211_ops = &iwlagn_hw_ops, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 7c286662d26a..79dd45c3aefc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -45,7 +45,6 @@ #include "iwl-sta.h" #include "iwl-helpers.h" #include "iwl-agn.h" -#include "iwl-agn-led.h" #include "iwl-agn-hw.h" #include "iwl-5000-hw.h" #include "iwl-agn-debugfs.h" @@ -447,7 +446,6 @@ static const struct iwl_ops iwl5000_ops = { .lib = &iwl5000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .led = &iwlagn_led_ops, .ieee80211_ops = &iwlagn_hw_ops, }; @@ -455,7 +453,6 @@ static const struct iwl_ops iwl5150_ops = { .lib = &iwl5150_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .led = &iwlagn_led_ops, .ieee80211_ops = &iwlagn_hw_ops, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 064981345c84..a35338e20b10 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -46,7 +46,6 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" -#include "iwl-agn-led.h" #include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ @@ -397,7 +396,6 @@ static const struct iwl_ops iwl6000_ops = { .lib = &iwl6000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .led = &iwlagn_led_ops, .ieee80211_ops = &iwlagn_hw_ops, }; @@ -405,7 +403,6 @@ static const struct iwl_ops iwl6050_ops = { .lib = &iwl6000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .led = &iwlagn_led_ops, .nic = &iwl6050_nic_ops, .ieee80211_ops = &iwlagn_hw_ops, }; @@ -414,7 +411,6 @@ static const struct iwl_ops iwl6150_ops = { .lib = &iwl6000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .led = &iwlagn_led_ops, .nic = &iwl6150_nic_ops, .ieee80211_ops = &iwlagn_hw_ops, }; @@ -423,7 +419,6 @@ static const struct iwl_ops iwl6030_ops = { .lib = &iwl6030_lib, .hcmd = &iwlagn_bt_hcmd, .utils = &iwlagn_hcmd_utils, - .led = &iwlagn_led_ops, .ieee80211_ops = &iwlagn_hw_ops, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.c b/drivers/net/wireless/iwlwifi/iwl-agn-led.c deleted file mode 100644 index 4bb877e600c7..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn-led.c +++ /dev/null @@ -1,73 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iwl-commands.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-agn-led.h" - -/* Send led command */ -static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) -{ - struct iwl_host_cmd cmd = { - .id = REPLY_LEDS_CMD, - .len = sizeof(struct iwl_led_cmd), - .data = led_cmd, - .flags = CMD_ASYNC, - .callback = NULL, - }; - u32 reg; - - reg = iwl_read32(priv, CSR_LED_REG); - if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) - iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); - - return iwl_send_cmd(priv, &cmd); -} - -/* Set led register off */ -void iwlagn_led_enable(struct iwl_priv *priv) -{ - iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); -} - -const struct iwl_led_ops iwlagn_led_ops = { - .cmd = iwl_send_led_cmd, -}; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.h b/drivers/net/wireless/iwlwifi/iwl-agn-led.h deleted file mode 100644 index c0b7611b72c3..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn-led.h +++ /dev/null @@ -1,33 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl_agn_led_h__ -#define __iwl_agn_led_h__ - -extern const struct iwl_led_ops iwlagn_led_ops; -void iwlagn_led_enable(struct iwl_priv *priv); - -#endif /* __iwl_agn_led_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 47a4cda9eb72..b4f7510f51ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -59,7 +59,6 @@ #include "iwl-sta.h" #include "iwl-agn-calib.h" #include "iwl-agn.h" -#include "iwl-agn-led.h" /****************************************************************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 6988335328e8..240abdf4347c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -217,7 +217,6 @@ struct iwl_ops { const struct iwl_lib_ops *lib; const struct iwl_hcmd_ops *hcmd; const struct iwl_hcmd_utils_ops *utils; - const struct iwl_led_ops *led; const struct iwl_nic_ops *nic; const struct iwl_legacy_ops *legacy; const struct ieee80211_ops *ieee80211_ops; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 0d90004e8b1b..d798c2a152d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -61,6 +61,12 @@ static const struct ieee80211_tpt_blink iwl_blink[] = { { .throughput = 300 * 1024 - 1, .blink_time = 50 }, }; +/* Set led register off */ +void iwlagn_led_enable(struct iwl_priv *priv) +{ + iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); +} + /* * Adjust led blink rate to compensate on a MAC Clock difference on every HW * Led blink rate analysis showed an average deviation of 20% on 5000 series @@ -84,6 +90,24 @@ static inline u8 iwl_blink_compensation(struct iwl_priv *priv, return (u8)((time * compensation) >> 6); } +static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) +{ + struct iwl_host_cmd cmd = { + .id = REPLY_LEDS_CMD, + .len = sizeof(struct iwl_led_cmd), + .data = led_cmd, + .flags = CMD_ASYNC, + .callback = NULL, + }; + u32 reg; + + reg = iwl_read32(priv, CSR_LED_REG); + if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) + iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); + + return iwl_send_cmd(priv, &cmd); +} + /* Set led pattern command */ static int iwl_led_cmd(struct iwl_priv *priv, unsigned long on, @@ -108,7 +132,7 @@ static int iwl_led_cmd(struct iwl_priv *priv, led_cmd.off = iwl_blink_compensation(priv, off, priv->cfg->base_params->led_compensation); - ret = priv->cfg->ops->led->cmd(priv, &led_cmd); + ret = iwl_send_led_cmd(priv, &led_cmd); if (!ret) { priv->blink_on = on; priv->blink_off = off; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 05b8e8f7dd4a..1c93dfef6933 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -50,6 +50,7 @@ enum iwl_led_mode { IWL_LED_BLINK, }; +void iwlagn_led_enable(struct iwl_priv *priv); void iwl_leds_init(struct iwl_priv *priv); void iwl_leds_exit(struct iwl_priv *priv); -- cgit v1.2.3-58-ga151 From 3e41ace5deef7af16dd277d9d17f9d36dca0a10e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 18 Apr 2011 09:12:37 -0700 Subject: iwlagn: remove most BUG_ON instances There are a number of things in the driver that may result in a BUG(), which is suboptimal since it's hard to get debugging information out of the driver in that case and the user experience is also not good :-) Almost all BUG_ON instances can be converted to WARN_ON with a few lines of appropriate error handling, so do that instead. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 9 +++++++-- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 6 ------ drivers/net/wireless/iwlwifi/iwl-eeprom.h | 1 - drivers/net/wireless/iwlwifi/iwl-hcmd.c | 12 ++++++++---- drivers/net/wireless/iwlwifi/iwl-power.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-sta.c | 9 ++++++--- drivers/net/wireless/iwlwifi/iwl-tx.c | 25 +++++++++++++++++-------- 7 files changed, 42 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b4f7510f51ec..0daededb0ff2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -394,7 +394,9 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, return -EINVAL; } - BUG_ON(addr & ~DMA_BIT_MASK(36)); + if (WARN_ON(addr & ~DMA_BIT_MASK(36))) + return -EINVAL; + if (unlikely(addr & ~IWL_TX_DMA_MASK)) IWL_ERR(priv, "Unaligned address = %llx\n", (unsigned long long)addr); @@ -718,7 +720,10 @@ static void iwl_rx_handle(struct iwl_priv *priv) /* If an RXB doesn't have a Rx queue slot associated with it, * then a bug has been introduced in the queue refilling * routines -- catch it here */ - BUG_ON(rxb == NULL); + if (WARN_ON(rxb == NULL)) { + i = (i + 1) & RX_QUEUE_MASK; + continue; + } rxq->queue[i] = NULL; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 859b94a12297..402733638f50 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -215,12 +215,6 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) return nvm_type; } -const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) -{ - BUG_ON(offset >= priv->cfg->base_params->eeprom_size); - return &priv->eeprom[offset]; -} - static int iwl_init_otp_access(struct iwl_priv *priv) { int ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 0e9d9703636a..9ce052573c6a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -309,7 +309,6 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv); const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); int iwlcore_eeprom_verify_signature(struct iwl_priv *priv); u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); -const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); int iwl_init_channel_map(struct iwl_priv *priv); void iwl_free_channel_map(struct iwl_priv *priv); const struct iwl_channel_info *iwl_get_channel_info( diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 9177b553fe57..8f0beb992ccf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -143,10 +143,12 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { int ret; - BUG_ON(!(cmd->flags & CMD_ASYNC)); + if (WARN_ON(!(cmd->flags & CMD_ASYNC))) + return -EINVAL; /* An asynchronous command can not expect an SKB to be set. */ - BUG_ON(cmd->flags & CMD_WANT_SKB); + if (WARN_ON(cmd->flags & CMD_WANT_SKB)) + return -EINVAL; /* Assign a generic callback if one is not provided */ if (!cmd->callback) @@ -169,10 +171,12 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) int cmd_idx; int ret; - lockdep_assert_held(&priv->mutex); + if (WARN_ON(cmd->flags & CMD_ASYNC)) + return -EINVAL; /* A synchronous command can not have a callback set. */ - BUG_ON((cmd->flags & CMD_ASYNC) || cmd->callback); + if (WARN_ON(cmd->callback)) + return -EINVAL; IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", get_cmd_string(cmd->id)); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index ae176d8da9e8..b7cd95820ff8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -188,9 +188,10 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, table = range_0; } - BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM); - - *cmd = table[lvl].cmd; + if (WARN_ON(lvl < 0 || lvl >= IWL_POWER_NUM)) + memset(cmd, 0, sizeof(*cmd)); + else + *cmd = table[lvl].cmd; if (period == 0) { skip = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index c21515640077..3c8cebde16cc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -494,7 +494,8 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, priv->num_stations--; - BUG_ON(priv->num_stations < 0); + if (WARN_ON(priv->num_stations < 0)) + priv->num_stations = 0; spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -679,7 +680,8 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv) priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; priv->num_stations--; - BUG_ON(priv->num_stations < 0); + if (WARN_ON(priv->num_stations < 0)) + priv->num_stations = 0; kfree(priv->stations[i].lq); priv->stations[i].lq = NULL; } @@ -775,7 +777,8 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, spin_unlock_irqrestore(&priv->sta_lock, flags_spin); iwl_dump_lq_cmd(priv, lq); - BUG_ON(init && (cmd.flags & CMD_ASYNC)); + if (WARN_ON(init && (cmd.flags & CMD_ASYNC))) + return -EINVAL; if (is_lq_table_valid(priv, ctx, lq)) ret = iwl_send_cmd(priv, &cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 3732380c4ffe..e7faba57b6e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -263,11 +263,13 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, /* count must be power-of-two size, otherwise iwl_queue_inc_wrap * and iwl_queue_dec_wrap are broken. */ - BUG_ON(!is_power_of_2(count)); + if (WARN_ON(!is_power_of_2(count))) + return -EINVAL; /* slots_num must be power-of-two size, otherwise * get_cmd_index is broken. */ - BUG_ON(!is_power_of_2(slots_num)); + if (WARN_ON(!is_power_of_2(slots_num))) + return -EINVAL; q->low_mark = q->n_window / 4; if (q->low_mark < 4) @@ -384,7 +386,9 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); /* Initialize queue's high/low-water marks, and head/tail indexes */ - iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); + ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); + if (ret) + return ret; /* Tell device where to find queue */ priv->cfg->ops->lib->txq_init(priv, txq); @@ -446,14 +450,19 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); - /* If any of the command structures end up being larger than + /* + * If any of the command structures end up being larger than * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then * we will need to increase the size of the TFD entries * Also, check to see if command buffer should not exceed the size - * of device_cmd and max_cmd_size. */ - BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && - !(cmd->flags & CMD_SIZE_HUGE)); - BUG_ON(fix_size > IWL_MAX_CMD_SIZE); + * of device_cmd and max_cmd_size. + */ + if (WARN_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && + !(cmd->flags & CMD_SIZE_HUGE))) + return -EINVAL; + + if (WARN_ON(fix_size > IWL_MAX_CMD_SIZE)) + return -EINVAL; if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { IWL_WARN(priv, "Not sending command - %s KILL\n", -- cgit v1.2.3-58-ga151 From 7b21f00ee6073909c01adeba317af3d78c3b9d0a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 18 Apr 2011 09:22:10 -0700 Subject: iwlagn: verify that huge commands are synchronous Since huge commands all share a single buffer, there can only be a single one in flight at a time since otherwise they'd overwrite each other. This is true in the driver now, but it seems like a possible source of bugs, so add a test to verify that huge commands are always sent synchronously. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-tx.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index e7faba57b6e3..1b69507db5fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -470,6 +470,14 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) return -EIO; } + /* + * As we only have a single huge buffer, check that the command + * is synchronous (otherwise buffers could end up being reused). + */ + + if (WARN_ON((cmd->flags & CMD_ASYNC) && (cmd->flags & CMD_SIZE_HUGE))) + return -EINVAL; + spin_lock_irqsave(&priv->hcmd_lock, flags); if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { -- cgit v1.2.3-58-ga151 From b4ebd28f23e3ae00af886aff1c00f800dee3b080 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 6 Apr 2011 12:28:56 -0700 Subject: iwlagn: use huge command for beacon When testing some new P2P code, Angie found that the driver might crash because the beacon command ended up being bigger than a regular command. This is quite obvious -- a normal command is limited to roughly 360 bytes but a beacon may be much larger of course. To fix this, use the huge command buffer. Reported-by: Angie Chinchilla Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0daededb0ff2..3cfd7ebb3448 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -253,6 +253,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) struct iwl_frame *frame; unsigned int frame_size; int rc; + struct iwl_host_cmd cmd = { + .id = REPLY_TX_BEACON, + .flags = CMD_SIZE_HUGE, + }; frame = iwl_get_free_frame(priv); if (!frame) { @@ -268,8 +272,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) return -EINVAL; } - rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, - &frame->u.cmd[0]); + cmd.len = frame_size; + cmd.data = &frame->u.cmd[0]; + + rc = iwl_send_cmd_sync(priv, &cmd); iwl_free_frame(priv, frame); -- cgit v1.2.3-58-ga151 From b7af6a99690503a48c63ce5e587b4e4555f31cdb Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 6 Apr 2011 15:55:25 -0700 Subject: iwlagn: always support uCode trace All _agn devices support continuous uCode trace, remove checking Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 - drivers/net/wireless/iwlwifi/iwl-2000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-5000.c | 1 - drivers/net/wireless/iwlwifi/iwl-6000.c | 3 --- drivers/net/wireless/iwlwifi/iwl-core.h | 2 -- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 3 +-- 6 files changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 809117d74196..e7844565ef55 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -242,7 +242,6 @@ static struct iwl_base_params iwl1000_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 128, - .ucode_tracing = true, }; static struct iwl_ht_params iwl1000_ht_params = { .ht_greenfield_support = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 0a330d16ce7e..dcd660818d21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -348,7 +348,6 @@ static struct iwl_base_params iwl2000_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 512, - .ucode_tracing = true, .shadow_reg_enable = true, }; @@ -368,7 +367,6 @@ static struct iwl_base_params iwl2030_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, - .ucode_tracing = true, .shadow_reg_enable = true, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 79dd45c3aefc..14b75f1de186 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -467,7 +467,6 @@ static struct iwl_base_params iwl5000_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, - .ucode_tracing = true, }; static struct iwl_ht_params iwl5000_ht_params = { .ht_greenfield_support = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index a35338e20b10..81881aad8751 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -437,7 +437,6 @@ static struct iwl_base_params iwl6000_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 512, - .ucode_tracing = true, .shadow_reg_enable = true, }; @@ -456,7 +455,6 @@ static struct iwl_base_params iwl6050_base_params = { .chain_noise_scale = 1500, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 1024, - .ucode_tracing = true, .shadow_reg_enable = true, }; static struct iwl_base_params iwl6000_g2_base_params = { @@ -474,7 +472,6 @@ static struct iwl_base_params iwl6000_g2_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, - .ucode_tracing = true, .shadow_reg_enable = true, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 240abdf4347c..2e8c936e556d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -249,7 +249,6 @@ struct iwl_mod_params { * @wd_timeout: TX queues watchdog timeout * @temperature_kelvin: temperature report by uCode in kelvin * @max_event_log_size: size of event log buffer size for ucode event logging - * @ucode_tracing: support ucode continuous tracing * @shadow_reg_enable: HW shadhow register bit */ struct iwl_base_params { @@ -271,7 +270,6 @@ struct iwl_base_params { unsigned int wd_timeout; bool temperature_kelvin; u32 max_event_log_size; - const bool ucode_tracing; const bool shadow_reg_enable; }; /* diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 897efacb96eb..c272204fccff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1749,8 +1749,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); - if (priv->cfg->base_params->ucode_tracing) - DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); -- cgit v1.2.3-58-ga151 From f42e7662815647c1a6f73e160abcdf812d3057d2 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 18 Apr 2011 09:30:09 -0700 Subject: iwlagn: temperature should be measure for all _agn devices Thermal throttling functions are available for all _agn devices, call the functions directly. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 5 ----- drivers/net/wireless/iwlwifi/iwl-2000.c | 5 ----- drivers/net/wireless/iwlwifi/iwl-5000.c | 10 ---------- drivers/net/wireless/iwlwifi/iwl-6000.c | 10 ---------- drivers/net/wireless/iwlwifi/iwl-core.h | 9 --------- drivers/net/wireless/iwlwifi/iwl-power.c | 6 ++---- drivers/net/wireless/iwlwifi/iwl-tx.c | 5 +---- 7 files changed, 3 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index e7844565ef55..946c7dca440a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -214,11 +214,6 @@ static struct iwl_lib_ops iwl1000_lib = { }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, - .tt_ops = { - .lower_power_detection = iwl_tt_is_low_power_state, - .tt_power_mode = iwl_tt_current_power_mode, - .ct_kill_check = iwl_check_for_ct_kill, - } }; static const struct iwl_ops iwl1000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index dcd660818d21..c8bb4a4930df 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -298,11 +298,6 @@ static struct iwl_lib_ops iwl2000_lib = { }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, - .tt_ops = { - .lower_power_detection = iwl_tt_is_low_power_state, - .tt_power_mode = iwl_tt_current_power_mode, - .ct_kill_check = iwl_check_for_ct_kill, - } }; static const struct iwl_ops iwl2000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 14b75f1de186..ced89f662bd1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -383,11 +383,6 @@ static struct iwl_lib_ops iwl5000_lib = { }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, - .tt_ops = { - .lower_power_detection = iwl_tt_is_low_power_state, - .tt_power_mode = iwl_tt_current_power_mode, - .ct_kill_check = iwl_check_for_ct_kill, - } }; static struct iwl_lib_ops iwl5150_lib = { @@ -435,11 +430,6 @@ static struct iwl_lib_ops iwl5150_lib = { }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, - .tt_ops = { - .lower_power_detection = iwl_tt_is_low_power_state, - .tt_power_mode = iwl_tt_current_power_mode, - .ct_kill_check = iwl_check_for_ct_kill, - } }; static const struct iwl_ops iwl5000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 81881aad8751..ed6a0ed0f501 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -323,11 +323,6 @@ static struct iwl_lib_ops iwl6000_lib = { }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, - .tt_ops = { - .lower_power_detection = iwl_tt_is_low_power_state, - .tt_power_mode = iwl_tt_current_power_mode, - .ct_kill_check = iwl_check_for_ct_kill, - } }; static struct iwl_lib_ops iwl6030_lib = { @@ -377,11 +372,6 @@ static struct iwl_lib_ops iwl6030_lib = { }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, - .tt_ops = { - .lower_power_detection = iwl_tt_is_low_power_state, - .tt_power_mode = iwl_tt_current_power_mode, - .ct_kill_check = iwl_check_for_ct_kill, - } }; static struct iwl_nic_ops iwl6050_nic_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 2e8c936e556d..abee5074d30e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -139,12 +139,6 @@ struct iwl_temp_ops { void (*temperature)(struct iwl_priv *priv); }; -struct iwl_tt_ops { - bool (*lower_power_detection)(struct iwl_priv *priv); - u8 (*tt_power_mode)(struct iwl_priv *priv); - bool (*ct_kill_check)(struct iwl_priv *priv); -}; - struct iwl_lib_ops { /* set hw dependent parameters */ int (*set_hw_params)(struct iwl_priv *priv); @@ -190,9 +184,6 @@ struct iwl_lib_ops { void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control); struct iwl_debugfs_ops debugfs_ops; - - /* thermal throttling */ - struct iwl_tt_ops tt_ops; }; struct iwl_led_ops { diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index b7cd95820ff8..595c930b28ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -357,12 +357,10 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); - else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && - priv->cfg->ops->lib->tt_ops.tt_power_mode && - priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) { + else if (iwl_tt_is_low_power_state(priv)) { /* in thermal throttling low power state */ iwl_static_sleep_cmd(priv, cmd, - priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper); + iwl_tt_current_power_mode(priv), dtimper); } else if (!enabled) iwl_power_sleep_cam_cmd(priv, cmd); else if (priv->power_data.debug_sleep_level_override >= 0) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 1b69507db5fc..80c3565a66ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -484,10 +484,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) spin_unlock_irqrestore(&priv->hcmd_lock, flags); IWL_ERR(priv, "No space in command queue\n"); - if (priv->cfg->ops->lib->tt_ops.ct_kill_check) { - is_ct_kill = - priv->cfg->ops->lib->tt_ops.ct_kill_check(priv); - } + is_ct_kill = iwl_check_for_ct_kill(priv); if (!is_ct_kill) { IWL_ERR(priv, "Restarting adapter due to queue full\n"); iwlagn_fw_error(priv, false); -- cgit v1.2.3-58-ga151 From 5cab35e7f4feda1a0bfd4f48b7686391004be9de Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 6 Apr 2011 15:55:27 -0700 Subject: iwlagn: no 5.2GHz/HT40 support for bgn devices For bgn devices, there were no HT40 channels value in EEPROM Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-2000.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 946c7dca440a..a01871801e53 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -195,7 +195,7 @@ static struct iwl_lib_ops iwl1000_lib = { EEPROM_REG_BAND_4_CHANNELS, EEPROM_REG_BAND_5_CHANNELS, EEPROM_REG_BAND_24_HT40_CHANNELS, - EEPROM_REG_BAND_52_HT40_CHANNELS + EEPROM_REGULATORY_BAND_NO_HT40, }, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index c8bb4a4930df..0bd9b146bb94 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -278,7 +278,7 @@ static struct iwl_lib_ops iwl2000_lib = { EEPROM_REG_BAND_4_CHANNELS, EEPROM_REG_BAND_5_CHANNELS, EEPROM_6000_REG_BAND_24_HT40_CHANNELS, - EEPROM_REG_BAND_52_HT40_CHANNELS + EEPROM_REGULATORY_BAND_NO_HT40, }, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, -- cgit v1.2.3-58-ga151 From 119ea186cad7643ea82b7290374ebb8e780c35b6 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 18 Apr 2011 09:34:06 -0700 Subject: iwlagn: remove un-necessary ieee80211_ops After driver split, no need to use ieee80211_ops, remove it Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 - drivers/net/wireless/iwlwifi/iwl-2000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-6000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-agn.c | 22 ++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.c | 24 ------------------------ drivers/net/wireless/iwlwifi/iwl-core.h | 2 -- 7 files changed, 22 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index a01871801e53..baf80111efaf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -220,7 +220,6 @@ static const struct iwl_ops iwl1000_ops = { .lib = &iwl1000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl1000_base_params = { diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 0bd9b146bb94..e76e02c28928 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -304,28 +304,24 @@ static const struct iwl_ops iwl2000_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl2030_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_bt_hcmd, .utils = &iwlagn_hcmd_utils, - .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl200_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl230_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_bt_hcmd, .utils = &iwlagn_hcmd_utils, - .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl2000_base_params = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index ced89f662bd1..655afc19f68f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -436,14 +436,12 @@ static const struct iwl_ops iwl5000_ops = { .lib = &iwl5000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl5150_ops = { .lib = &iwl5150_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl5000_base_params = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index ed6a0ed0f501..905eb57f7cab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -386,7 +386,6 @@ static const struct iwl_ops iwl6000_ops = { .lib = &iwl6000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, - .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl6050_ops = { @@ -394,7 +393,6 @@ static const struct iwl_ops iwl6050_ops = { .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, .nic = &iwl6050_nic_ops, - .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl6150_ops = { @@ -402,14 +400,12 @@ static const struct iwl_ops iwl6150_ops = { .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, .nic = &iwl6150_nic_ops, - .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl6030_ops = { .lib = &iwl6030_lib, .hcmd = &iwlagn_bt_hcmd, .utils = &iwlagn_hcmd_utils, - .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl6000_base_params = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3cfd7ebb3448..cdeb09eee739 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3728,6 +3728,28 @@ static const u8 iwlagn_pan_ac_to_queue[] = { 7, 6, 5, 4, }; +/* This function both allocates and initializes hw and priv. */ +static struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg) +{ + struct iwl_priv *priv; + /* mac80211 allocates memory for this device instance, including + * space for this driver's private structure */ + struct ieee80211_hw *hw; + + hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwlagn_hw_ops); + if (hw == NULL) { + pr_err("%s: Can not allocate network device\n", + cfg->name); + goto out; + } + + priv = hw->priv; + priv->hw = hw; + +out: + return hw; +} + static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int err = 0, i; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 0e98a8703e55..885167f8168d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -67,30 +67,6 @@ u32 iwl_debug_level; const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - -/* This function both allocates and initializes hw and priv. */ -struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg) -{ - struct iwl_priv *priv; - /* mac80211 allocates memory for this device instance, including - * space for this driver's private structure */ - struct ieee80211_hw *hw; - - hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), - cfg->ops->ieee80211_ops); - if (hw == NULL) { - pr_err("%s: Can not allocate network device\n", - cfg->name); - goto out; - } - - priv = hw->priv; - priv->hw = hw; - -out: - return hw; -} - #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index abee5074d30e..0049790eab7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -210,7 +210,6 @@ struct iwl_ops { const struct iwl_hcmd_utils_ops *utils; const struct iwl_nic_ops *nic; const struct iwl_legacy_ops *legacy; - const struct ieee80211_ops *ieee80211_ops; }; struct iwl_mod_params { @@ -364,7 +363,6 @@ struct iwl_cfg { * L i b * ***************************/ -struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg); int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); -- cgit v1.2.3-58-ga151 From e339807d97bcb4e214c9137bb5bbb2f685054624 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 8 Apr 2011 10:21:52 -0700 Subject: iwlagn: remove legacy ops No longer used by _agn devices, remove it Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 0049790eab7f..99a91bddd9ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -195,21 +195,11 @@ struct iwl_nic_ops { void (*additional_nic_config)(struct iwl_priv *priv); }; -struct iwl_legacy_ops { - void (*post_associate)(struct iwl_priv *priv); - void (*config_ap)(struct iwl_priv *priv); - /* station management */ - int (*update_bcast_stations)(struct iwl_priv *priv); - int (*manage_ibss_station)(struct iwl_priv *priv, - struct ieee80211_vif *vif, bool add); -}; - struct iwl_ops { const struct iwl_lib_ops *lib; const struct iwl_hcmd_ops *hcmd; const struct iwl_hcmd_utils_ops *utils; const struct iwl_nic_ops *nic; - const struct iwl_legacy_ops *legacy; }; struct iwl_mod_params { -- cgit v1.2.3-58-ga151 From f212b43c4e4a8f6378c50ce18f3d271983b575a7 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 18 Apr 2011 09:36:30 -0700 Subject: iwlagn: remove led_ops No longer use, remove it Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 99a91bddd9ee..32a990ff09ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -186,10 +186,6 @@ struct iwl_lib_ops { struct iwl_debugfs_ops debugfs_ops; }; -struct iwl_led_ops { - int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd); -}; - /* NIC specific ops */ struct iwl_nic_ops { void (*additional_nic_config)(struct iwl_priv *priv); -- cgit v1.2.3-58-ga151 From 56d37f17165084e10f425e66f0bd964f06e8bd23 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 18 Apr 2011 01:04:37 +0000 Subject: net: dm9000: Fix build Commit c88fcb (net: dm9000: convert to hw_features) broke the build of the dm9000 driver since it merged functions which use different names for the board info structure used for I/O operations without updating all the references to use the same name. Fix that. Signed-off-by: Mark Brown Signed-off-by: David S. Miller --- drivers/net/dm9000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index f7bdebbcb908..fbaff3584bd4 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -768,7 +768,7 @@ dm9000_init_dm9000(struct net_device *dev) /* Checksum mode */ if (dev->hw_features & NETIF_F_RXCSUM) - iow(dm, DM9000_RCSR, + iow(db, DM9000_RCSR, (dev->features & NETIF_F_RXCSUM) ? RCSR_CSUM : 0); iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ -- cgit v1.2.3-58-ga151 From 47c2cdf5513e86e43c799da8d5406cc9a2bf3626 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 15 Apr 2011 04:50:50 +0000 Subject: net: myri10ge: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Acked-by: Jon Mason Signed-off-by: David S. Miller --- drivers/net/myri10ge/myri10ge.c | 66 ++++++++--------------------------------- 1 file changed, 12 insertions(+), 54 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 1446de59ae53..e7f801643c12 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -205,7 +205,6 @@ struct myri10ge_priv { int tx_boundary; /* boundary transmits cannot cross */ int num_slices; int running; /* running? */ - int csum_flag; /* rx_csums? */ int small_bytes; int big_bytes; int max_intr_slots; @@ -1386,7 +1385,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum, skb->protocol = eth_type_trans(skb, dev); skb_record_rx_queue(skb, ss - &mgp->ss[0]); - if (mgp->csum_flag) { + if (dev->features & NETIF_F_RXCSUM) { if ((skb->protocol == htons(ETH_P_IP)) || (skb->protocol == htons(ETH_P_IPV6))) { skb->csum = csum; @@ -1757,43 +1756,6 @@ myri10ge_get_ringparam(struct net_device *netdev, ring->tx_pending = ring->tx_max_pending; } -static u32 myri10ge_get_rx_csum(struct net_device *netdev) -{ - struct myri10ge_priv *mgp = netdev_priv(netdev); - - if (mgp->csum_flag) - return 1; - else - return 0; -} - -static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled) -{ - struct myri10ge_priv *mgp = netdev_priv(netdev); - int err = 0; - - if (csum_enabled) - mgp->csum_flag = MXGEFW_FLAGS_CKSUM; - else { - netdev->features &= ~NETIF_F_LRO; - mgp->csum_flag = 0; - - } - return err; -} - -static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled) -{ - struct myri10ge_priv *mgp = netdev_priv(netdev); - u32 flags = mgp->features & (NETIF_F_TSO6 | NETIF_F_TSO); - - if (tso_enabled) - netdev->features |= flags; - else - netdev->features &= ~flags; - return 0; -} - static const char myri10ge_gstrings_main_stats[][ETH_GSTRING_LEN] = { "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", @@ -1944,11 +1906,6 @@ static u32 myri10ge_get_msglevel(struct net_device *netdev) return mgp->msg_enable; } -static int myri10ge_set_flags(struct net_device *netdev, u32 value) -{ - return ethtool_op_set_flags(netdev, value, ETH_FLAG_LRO); -} - static const struct ethtool_ops myri10ge_ethtool_ops = { .get_settings = myri10ge_get_settings, .get_drvinfo = myri10ge_get_drvinfo, @@ -1957,19 +1914,12 @@ static const struct ethtool_ops myri10ge_ethtool_ops = { .get_pauseparam = myri10ge_get_pauseparam, .set_pauseparam = myri10ge_set_pauseparam, .get_ringparam = myri10ge_get_ringparam, - .get_rx_csum = myri10ge_get_rx_csum, - .set_rx_csum = myri10ge_set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_hw_csum, - .set_sg = ethtool_op_set_sg, - .set_tso = myri10ge_set_tso, .get_link = ethtool_op_get_link, .get_strings = myri10ge_get_strings, .get_sset_count = myri10ge_get_sset_count, .get_ethtool_stats = myri10ge_get_ethtool_stats, .set_msglevel = myri10ge_set_msglevel, .get_msglevel = myri10ge_get_msglevel, - .get_flags = ethtool_op_get_flags, - .set_flags = myri10ge_set_flags }; static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss) @@ -3136,6 +3086,14 @@ static int myri10ge_set_mac_address(struct net_device *dev, void *addr) return 0; } +static u32 myri10ge_fix_features(struct net_device *dev, u32 features) +{ + if (!(features & NETIF_F_RXCSUM)) + features &= ~NETIF_F_LRO; + + return features; +} + static int myri10ge_change_mtu(struct net_device *dev, int new_mtu) { struct myri10ge_priv *mgp = netdev_priv(dev); @@ -3834,6 +3792,7 @@ static const struct net_device_ops myri10ge_netdev_ops = { .ndo_get_stats = myri10ge_get_stats, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = myri10ge_change_mtu, + .ndo_fix_features = myri10ge_fix_features, .ndo_set_multicast_list = myri10ge_set_multicast_list, .ndo_set_mac_address = myri10ge_set_mac_address, }; @@ -3860,7 +3819,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) mgp = netdev_priv(netdev); mgp->dev = netdev; mgp->pdev = pdev; - mgp->csum_flag = MXGEFW_FLAGS_CKSUM; mgp->pause = myri10ge_flow_control; mgp->intr_coal_delay = myri10ge_intr_coal_delay; mgp->msg_enable = netif_msg_init(myri10ge_debug, MYRI10GE_MSG_DEFAULT); @@ -3976,11 +3934,11 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->netdev_ops = &myri10ge_netdev_ops; netdev->mtu = myri10ge_initial_mtu; netdev->base_addr = mgp->iomem_base; - netdev->features = mgp->features; + netdev->hw_features = mgp->features | NETIF_F_LRO | NETIF_F_RXCSUM; + netdev->features = netdev->hw_features; if (dac_enabled) netdev->features |= NETIF_F_HIGHDMA; - netdev->features |= NETIF_F_LRO; netdev->vlan_features |= mgp->features; if (mgp->fw_ver_tiny < 37) -- cgit v1.2.3-58-ga151 From 2b7b431858c284b62c18baaf2cea571be2797d5a Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Mon, 18 Apr 2011 22:53:24 -0700 Subject: r8169: TSO fixes. - the MSS value is actually contained in a 11 bits wide (0x7ff) field. The extra bit in the former MSSMask did encompass the TSO command bit ("LargeSend") as well (0xfff). Oops. - the Tx descriptor layout is not the same through the whole chipset family. The 8169 documentation, the 8168c documentation and Realtek's drivers (8.020.00, 1.019.00, 6.014.00) highlight two layouts: 1. 8169, 8168 up to 8168b (included) and 8101 2. {8102e, 8168c} and beyond - notwithstanding the "first descriptor" and "last descriptor" bits, the same Tx descriptor content is enforced when a packet consists of several descriptors. The chipsets are documented to require it. Credits go to David Dillow for the original patch. Signed-off-by: Francois Romieu Cc: Realtek Signed-off-by: David S. Miller --- drivers/net/r8169.c | 209 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 137 insertions(+), 72 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 058524f3eb49..fb03e6ff3716 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -134,47 +134,52 @@ enum mac_version { RTL_GIGA_MAC_VER_33 = 0x21, // 8168E }; -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } +enum rtl_tx_desc_version { + RTL_TD_0 = 0, + RTL_TD_1 = 1, +}; + +#define _R(NAME,MAC,TD) \ + { .name = NAME, .mac_version = MAC, .txd_version = TD } static const struct { const char *name; u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ + enum rtl_tx_desc_version txd_version; } rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_28, 0xff7e1880), // PCI-E - _R("RTL8105e", RTL_GIGA_MAC_VER_29, 0xff7e1880), // PCI-E - _R("RTL8105e", RTL_GIGA_MAC_VER_30, 0xff7e1880), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_31, 0xff7e1880), // PCI-E - _R("RTL8168e/8111e", RTL_GIGA_MAC_VER_32, 0xff7e1880), // PCI-E - _R("RTL8168e/8111e", RTL_GIGA_MAC_VER_33, 0xff7e1880) // PCI-E + _R("RTL8169", RTL_GIGA_MAC_VER_01, RTL_TD_0), // 8169 + _R("RTL8169s", RTL_GIGA_MAC_VER_02, RTL_TD_0), // 8169S + _R("RTL8110s", RTL_GIGA_MAC_VER_03, RTL_TD_0), // 8110S + _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, RTL_TD_0), // 8169SB + _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, RTL_TD_0), // 8110SCd + _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, RTL_TD_0), // 8110SCe + _R("RTL8102e", RTL_GIGA_MAC_VER_07, RTL_TD_1), // PCI-E + _R("RTL8102e", RTL_GIGA_MAC_VER_08, RTL_TD_1), // PCI-E + _R("RTL8102e", RTL_GIGA_MAC_VER_09, RTL_TD_1), // PCI-E + _R("RTL8101e", RTL_GIGA_MAC_VER_10, RTL_TD_0), // PCI-E + _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, RTL_TD_0), // PCI-E + _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, RTL_TD_0), // PCI-E + _R("RTL8101e", RTL_GIGA_MAC_VER_13, RTL_TD_0), // PCI-E 8139 + _R("RTL8100e", RTL_GIGA_MAC_VER_14, RTL_TD_0), // PCI-E 8139 + _R("RTL8100e", RTL_GIGA_MAC_VER_15, RTL_TD_0), // PCI-E 8139 + _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, RTL_TD_0), // PCI-E + _R("RTL8101e", RTL_GIGA_MAC_VER_16, RTL_TD_0), // PCI-E + _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, RTL_TD_1), // PCI-E + _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, RTL_TD_1), // PCI-E + _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, RTL_TD_1), // PCI-E + _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, RTL_TD_1), // PCI-E + _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, RTL_TD_1), // PCI-E + _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, RTL_TD_1), // PCI-E + _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, RTL_TD_1), // PCI-E + _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, RTL_TD_1), // PCI-E + _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, RTL_TD_1), // PCI-E + _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, RTL_TD_1), // PCI-E + _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_28, RTL_TD_1), // PCI-E + _R("RTL8105e", RTL_GIGA_MAC_VER_29, RTL_TD_1), // PCI-E + _R("RTL8105e", RTL_GIGA_MAC_VER_30, RTL_TD_1), // PCI-E + _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_31, RTL_TD_1), // PCI-E + _R("RTL8168e/8111e", RTL_GIGA_MAC_VER_32, RTL_TD_1), // PCI-E + _R("RTL8168e/8111e", RTL_GIGA_MAC_VER_33, RTL_TD_1) // PCI-E }; #undef _R @@ -230,6 +235,9 @@ enum rtl_registers { IntrStatus = 0x3e, TxConfig = 0x40, RxConfig = 0x44, + +#define RTL_RX_CONFIG_MASK 0xff7e1880u + RxMissed = 0x4c, Cfg9346 = 0x50, Config0 = 0x51, @@ -452,21 +460,69 @@ enum rtl_register_content { CounterDump = 0x8, }; -enum desc_status_bit { +enum rtl_desc_bit { + /* First doubleword. */ DescOwn = (1 << 31), /* Descriptor is owned by NIC */ RingEnd = (1 << 30), /* End of descriptor ring */ FirstFrag = (1 << 29), /* First segment of a packet */ LastFrag = (1 << 28), /* Final segment of a packet */ +}; + +/* Generic case. */ +enum rtl_tx_desc_bit { + /* First doubleword. */ + TD_LSO = (1 << 27), /* Large Send Offload */ +#define TD_MSS_MAX 0x07ffu /* MSS value */ - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ + /* Second doubleword. */ + TxVlanTag = (1 << 17), /* Add VLAN tag */ +}; + +/* 8169, 8168b and 810x except 8102e. */ +enum rtl_tx_desc_bit_0 { + /* First doubleword. */ +#define TD0_MSS_SHIFT 16 /* MSS position (11 bits) */ + TD0_TCP_CS = (1 << 16), /* Calculate TCP/IP checksum */ + TD0_UDP_CS = (1 << 17), /* Calculate UDP/IP checksum */ + TD0_IP_CS = (1 << 18), /* Calculate IP checksum */ +}; + +/* 8102e, 8168c and beyond. */ +enum rtl_tx_desc_bit_1 { + /* Second doubleword. */ +#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */ + TD1_IP_CS = (1 << 29), /* Calculate IP checksum */ + TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */ + TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */ +}; +static const struct rtl_tx_desc_info { + struct { + u32 udp; + u32 tcp; + } checksum; + u16 mss_shift; + u16 opts_offset; +} tx_desc_info [] = { + [RTL_TD_0] = { + .checksum = { + .udp = TD0_IP_CS | TD0_UDP_CS, + .tcp = TD0_IP_CS | TD0_TCP_CS + }, + .mss_shift = TD0_MSS_SHIFT, + .opts_offset = 0 + }, + [RTL_TD_1] = { + .checksum = { + .udp = TD1_IP_CS | TD1_UDP_CS, + .tcp = TD1_IP_CS | TD1_TCP_CS + }, + .mss_shift = TD1_MSS_SHIFT, + .opts_offset = 1 + } +}; + +enum rtl_rx_desc_bit { /* Rx private */ PID1 = (1 << 18), /* Protocol ID bit 1/2 */ PID0 = (1 << 17), /* Protocol ID bit 2/2 */ @@ -531,8 +587,8 @@ struct rtl8169_private { struct napi_struct napi; spinlock_t lock; /* spin lock flag */ u32 msg_enable; - int chipset; - int mac_version; + u16 txd_version; + u16 mac_version; u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ u32 dirty_rx; @@ -1288,7 +1344,7 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) static u32 rtl8169_fix_features(struct net_device *dev, u32 features) { - if (dev->mtu > MSSMask) + if (dev->mtu > TD_MSS_MAX) features &= ~NETIF_F_ALL_TSO; return features; @@ -3194,7 +3250,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) struct mii_if_info *mii; struct net_device *dev; void __iomem *ioaddr; - unsigned int i; + int chipset, i; int rc; if (netif_msg_drv(&debug)) { @@ -3336,7 +3392,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) "driver bug, MAC version not found in rtl_chip_info\n"); goto err_out_msi_4; } - tp->chipset = i; + chipset = i; + tp->txd_version = rtl_chip_info[chipset].txd_version; RTL_W8(Cfg9346, Cfg9346_Unlock); RTL_W8(Config1, RTL_R8(Config1) | PMEnable); @@ -3413,8 +3470,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, dev); netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n", - rtl_chip_info[tp->chipset].name, - dev->base_addr, dev->dev_addr, + rtl_chip_info[chipset].name, dev->base_addr, dev->dev_addr, (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); if ((tp->mac_version == RTL_GIGA_MAC_VER_27) || @@ -3572,7 +3628,7 @@ static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) void __iomem *ioaddr = tp->mmio_addr; u32 cfg = rtl8169_rx_config; - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); + cfg |= (RTL_R32(RxConfig) & RTL_RX_CONFIG_MASK); RTL_W32(RxConfig, cfg); /* Set DMA burst size and Interframe Gap Time */ @@ -4564,7 +4620,7 @@ static void rtl8169_tx_timeout(struct net_device *dev) } static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 opts1) + u32 *opts) { struct skb_shared_info *info = skb_shinfo(skb); unsigned int cur_frag, entry; @@ -4592,9 +4648,11 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, } /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); + status = opts[0] | len | + (RingEnd * !((entry + 1) % NUM_TX_DESC)); txd->opts1 = cpu_to_le32(status); + txd->opts2 = cpu_to_le32(opts[1]); txd->addr = cpu_to_le64(mapping); tp->tx_skb[entry].len = len; @@ -4612,23 +4670,26 @@ err_out: return -EIO; } -static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) +static inline void rtl8169_tso_csum(struct rtl8169_private *tp, + struct sk_buff *skb, u32 *opts) { + const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version; u32 mss = skb_shinfo(skb)->gso_size; + int offset = info->opts_offset; - if (mss) - return LargeSend | ((mss & MSSMask) << MSSShift); - - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (mss) { + opts[0] |= TD_LSO; + opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift; + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { const struct iphdr *ip = ip_hdr(skb); if (ip->protocol == IPPROTO_TCP) - return IPCS | TCPCS; + opts[offset] |= info->checksum.tcp; else if (ip->protocol == IPPROTO_UDP) - return IPCS | UDPCS; - WARN_ON(1); /* we need a WARN() */ + opts[offset] |= info->checksum.udp; + else + WARN_ON_ONCE(1); } - return 0; } static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, @@ -4641,7 +4702,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, struct device *d = &tp->pci_dev->dev; dma_addr_t mapping; u32 status, len; - u32 opts1; + u32 opts[2]; int frags; if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { @@ -4662,24 +4723,28 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, tp->tx_skb[entry].len = len; txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - opts1 = DescOwn | rtl8169_tso_csum(skb, dev); + opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); + opts[0] = DescOwn; - frags = rtl8169_xmit_frags(tp, skb, opts1); + rtl8169_tso_csum(tp, skb, opts); + + frags = rtl8169_xmit_frags(tp, skb, opts); if (frags < 0) goto err_dma_1; else if (frags) - opts1 |= FirstFrag; + opts[0] |= FirstFrag; else { - opts1 |= FirstFrag | LastFrag; + opts[0] |= FirstFrag | LastFrag; tp->tx_skb[entry].skb = skb; } + txd->opts2 = cpu_to_le32(opts[1]); + wmb(); /* anti gcc 2.95.3 bugware (sic) */ - status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); + status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); txd->opts1 = cpu_to_le32(status); tp->cur_tx += frags + 1; @@ -5167,7 +5232,7 @@ static void rtl_set_rx_mode(struct net_device *dev) spin_lock_irqsave(&tp->lock, flags); tmp = rtl8169_rx_config | rx_mode | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); + (RTL_R32(RxConfig) & RTL_RX_CONFIG_MASK); if (tp->mac_version > RTL_GIGA_MAC_VER_06) { u32 data = mc_filter[0]; -- cgit v1.2.3-58-ga151 From e5cb966c0838e4da43a3b0751bdcac7fe719f7b4 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Mon, 18 Apr 2011 13:31:20 +0000 Subject: net: fix section mismatches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix build warnings like the following: WARNING: drivers/net/built-in.o(.data+0x12434): Section mismatch in reference from the variable madgemc_driver to the variable .init.data:madgemc_adapter_ids And add some consts to EISA device ID tables along the way. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/3c509.c | 14 ++++++------- drivers/net/3c59x.c | 4 ++-- drivers/net/depca.c | 35 ++++++++++++++++---------------- drivers/net/hp100.c | 12 +++++------ drivers/net/ibmlana.c | 4 ++-- drivers/net/irda/smsc-ircc2.c | 44 ++++++++++++++++++++--------------------- drivers/net/ne3210.c | 15 ++++++++------ drivers/net/smc-mca.c | 6 +++--- drivers/net/tokenring/madgemc.c | 2 +- drivers/net/tulip/de4x5.c | 4 ++-- 10 files changed, 72 insertions(+), 68 deletions(-) diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 91abb965fb44..cb39dedf46bd 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -185,7 +185,7 @@ static int max_interrupt_work = 10; static int nopnp; #endif -static int __devinit el3_common_init(struct net_device *dev); +static int el3_common_init(struct net_device *dev); static void el3_common_remove(struct net_device *dev); static ushort id_read_eeprom(int index); static ushort read_eeprom(int ioaddr, int index); @@ -395,7 +395,7 @@ static struct isa_driver el3_isa_driver = { static int isa_registered; #ifdef CONFIG_PNP -static struct pnp_device_id el3_pnp_ids[] = { +static const struct pnp_device_id el3_pnp_ids[] __devinitconst = { { .id = "TCM5090" }, /* 3Com Etherlink III (TP) */ { .id = "TCM5091" }, /* 3Com Etherlink III */ { .id = "TCM5094" }, /* 3Com Etherlink III (combo) */ @@ -478,7 +478,7 @@ static int pnp_registered; #endif /* CONFIG_PNP */ #ifdef CONFIG_EISA -static struct eisa_device_id el3_eisa_ids[] = { +static const struct eisa_device_id el3_eisa_ids[] __devinitconst = { { "TCM5090" }, { "TCM5091" }, { "TCM5092" }, @@ -508,7 +508,7 @@ static int eisa_registered; #ifdef CONFIG_MCA static int el3_mca_probe(struct device *dev); -static short el3_mca_adapter_ids[] __initdata = { +static const short el3_mca_adapter_ids[] __devinitconst = { 0x627c, 0x627d, 0x62db, @@ -517,7 +517,7 @@ static short el3_mca_adapter_ids[] __initdata = { 0x0000 }; -static char *el3_mca_adapter_names[] __initdata = { +static const char *const el3_mca_adapter_names[] __devinitconst = { "3Com 3c529 EtherLink III (10base2)", "3Com 3c529 EtherLink III (10baseT)", "3Com 3c529 EtherLink III (test mode)", @@ -601,7 +601,7 @@ static void el3_common_remove (struct net_device *dev) } #ifdef CONFIG_MCA -static int __init el3_mca_probe(struct device *device) +static int __devinit el3_mca_probe(struct device *device) { /* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch, * heavily modified by Chris Beauregard @@ -671,7 +671,7 @@ static int __init el3_mca_probe(struct device *device) #endif /* CONFIG_MCA */ #ifdef CONFIG_EISA -static int __init el3_eisa_probe (struct device *device) +static int __devinit el3_eisa_probe (struct device *device) { short i; int ioaddr, irq, if_port; diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 8cc22568ebd3..99f43d275442 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -901,14 +901,14 @@ static const struct dev_pm_ops vortex_pm_ops = { #endif /* !CONFIG_PM */ #ifdef CONFIG_EISA -static struct eisa_device_id vortex_eisa_ids[] = { +static const struct eisa_device_id vortex_eisa_ids[] __devinitconst = { { "TCM5920", CH_3C592 }, { "TCM5970", CH_3C597 }, { "" } }; MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids); -static int __init vortex_eisa_probe(struct device *device) +static int __devinit vortex_eisa_probe(struct device *device) { void __iomem *ioaddr; struct eisa_device *edev; diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 8b0084d17c8c..17654059922d 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -331,18 +331,18 @@ static struct { "DE422",\ ""} -static char* __initdata depca_signature[] = DEPCA_SIGNATURE; +static const char* const depca_signature[] __devinitconst = DEPCA_SIGNATURE; enum depca_type { DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown }; -static char depca_string[] = "depca"; +static const char depca_string[] = "depca"; static int depca_device_remove (struct device *device); #ifdef CONFIG_EISA -static struct eisa_device_id depca_eisa_ids[] = { +static const struct eisa_device_id depca_eisa_ids[] __devinitconst = { { "DEC4220", de422 }, { "" } }; @@ -367,19 +367,19 @@ static struct eisa_driver depca_eisa_driver = { #define DE210_ID 0x628d #define DE212_ID 0x6def -static short depca_mca_adapter_ids[] = { +static const short depca_mca_adapter_ids[] __devinitconst = { DE210_ID, DE212_ID, 0x0000 }; -static char *depca_mca_adapter_name[] = { +static const char *depca_mca_adapter_name[] = { "DEC EtherWORKS MC Adapter (DE210)", "DEC EtherWORKS MC Adapter (DE212)", NULL }; -static enum depca_type depca_mca_adapter_type[] = { +static const enum depca_type depca_mca_adapter_type[] = { de210, de212, 0 @@ -541,10 +541,9 @@ static void SetMulticastFilter(struct net_device *dev); static int load_packet(struct net_device *dev, struct sk_buff *skb); static void depca_dbg_open(struct net_device *dev); -static u_char de1xx_irq[] __initdata = { 2, 3, 4, 5, 7, 9, 0 }; -static u_char de2xx_irq[] __initdata = { 5, 9, 10, 11, 15, 0 }; -static u_char de422_irq[] __initdata = { 5, 9, 10, 11, 0 }; -static u_char *depca_irq; +static const u_char de1xx_irq[] __devinitconst = { 2, 3, 4, 5, 7, 9, 0 }; +static const u_char de2xx_irq[] __devinitconst = { 5, 9, 10, 11, 15, 0 }; +static const u_char de422_irq[] __devinitconst = { 5, 9, 10, 11, 0 }; static int irq; static int io; @@ -580,7 +579,7 @@ static const struct net_device_ops depca_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __init depca_hw_init (struct net_device *dev, struct device *device) +static int __devinit depca_hw_init (struct net_device *dev, struct device *device) { struct depca_private *lp; int i, j, offset, netRAM, mem_len, status = 0; @@ -748,6 +747,7 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device) if (dev->irq < 2) { unsigned char irqnum; unsigned long irq_mask, delay; + const u_char *depca_irq; irq_mask = probe_irq_on(); @@ -770,6 +770,7 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device) break; default: + depca_irq = NULL; break; /* Not reached */ } @@ -1302,7 +1303,7 @@ static void SetMulticastFilter(struct net_device *dev) } } -static int __init depca_common_init (u_long ioaddr, struct net_device **devp) +static int __devinit depca_common_init (u_long ioaddr, struct net_device **devp) { int status = 0; @@ -1333,7 +1334,7 @@ static int __init depca_common_init (u_long ioaddr, struct net_device **devp) /* ** Microchannel bus I/O device probe */ -static int __init depca_mca_probe(struct device *device) +static int __devinit depca_mca_probe(struct device *device) { unsigned char pos[2]; unsigned char where; @@ -1457,7 +1458,7 @@ static int __init depca_mca_probe(struct device *device) ** ISA bus I/O device probe */ -static void __init depca_platform_probe (void) +static void __devinit depca_platform_probe (void) { int i; struct platform_device *pldev; @@ -1497,7 +1498,7 @@ static void __init depca_platform_probe (void) } } -static enum depca_type __init depca_shmem_probe (ulong *mem_start) +static enum depca_type __devinit depca_shmem_probe (ulong *mem_start) { u_long mem_base[] = DEPCA_RAM_BASE_ADDRESSES; enum depca_type adapter = unknown; @@ -1558,7 +1559,7 @@ static int __devinit depca_isa_probe (struct platform_device *device) */ #ifdef CONFIG_EISA -static int __init depca_eisa_probe (struct device *device) +static int __devinit depca_eisa_probe (struct device *device) { enum depca_type adapter = unknown; struct eisa_device *edev; @@ -1629,7 +1630,7 @@ static int __devexit depca_device_remove (struct device *device) ** and Boot (readb) ROM. This will also give us a clue to the network RAM ** base address. */ -static int __init DepcaSignature(char *name, u_long base_addr) +static int __devinit DepcaSignature(char *name, u_long base_addr) { u_int i, j, k; void __iomem *ptr; diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 8e10d2f6a5ad..c52a1df5d922 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -188,14 +188,14 @@ struct hp100_private { * variables */ #ifdef CONFIG_ISA -static const char *hp100_isa_tbl[] = { +static const char *const hp100_isa_tbl[] __devinitconst = { "HWPF150", /* HP J2573 rev A */ "HWP1950", /* HP J2573 */ }; #endif #ifdef CONFIG_EISA -static struct eisa_device_id hp100_eisa_tbl[] = { +static const struct eisa_device_id hp100_eisa_tbl[] __devinitconst = { { "HWPF180" }, /* HP J2577 rev A */ { "HWP1920" }, /* HP 27248B */ { "HWP1940" }, /* HP J2577 */ @@ -336,7 +336,7 @@ static __devinit const char *hp100_read_id(int ioaddr) } #ifdef CONFIG_ISA -static __init int hp100_isa_probe1(struct net_device *dev, int ioaddr) +static __devinit int hp100_isa_probe1(struct net_device *dev, int ioaddr) { const char *sig; int i; @@ -372,7 +372,7 @@ static __init int hp100_isa_probe1(struct net_device *dev, int ioaddr) * EISA and PCI are handled by device infrastructure. */ -static int __init hp100_isa_probe(struct net_device *dev, int addr) +static int __devinit hp100_isa_probe(struct net_device *dev, int addr) { int err = -ENODEV; @@ -396,7 +396,7 @@ static int __init hp100_isa_probe(struct net_device *dev, int addr) #endif /* CONFIG_ISA */ #if !defined(MODULE) && defined(CONFIG_ISA) -struct net_device * __init hp100_probe(int unit) +struct net_device * __devinit hp100_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private)); int err; @@ -2843,7 +2843,7 @@ static void cleanup_dev(struct net_device *d) } #ifdef CONFIG_EISA -static int __init hp100_eisa_probe (struct device *gendev) +static int __devinit hp100_eisa_probe (struct device *gendev) { struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private)); struct eisa_device *edev = to_eisa_device(gendev); diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c index a7d6cad32953..136d7544cc33 100644 --- a/drivers/net/ibmlana.c +++ b/drivers/net/ibmlana.c @@ -895,12 +895,12 @@ static int ibmlana_irq; static int ibmlana_io; static int startslot; /* counts through slots when probing multiple devices */ -static short ibmlana_adapter_ids[] __initdata = { +static const short ibmlana_adapter_ids[] __devinitconst = { IBM_LANA_ID, 0x0000 }; -static char *ibmlana_adapter_names[] __devinitdata = { +static const char *const ibmlana_adapter_names[] __devinitconst = { "IBM LAN Adapter/A", NULL }; diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index 8800e1fe4129..69b5707db369 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c @@ -222,19 +222,19 @@ static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 s static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self); /* Probing */ -static int __init smsc_ircc_look_for_chips(void); -static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type); -static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfg_base, char *type); -static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); -static int __init smsc_superio_fdc(unsigned short cfg_base); -static int __init smsc_superio_lpc(unsigned short cfg_base); +static int smsc_ircc_look_for_chips(void); +static const struct smsc_chip * smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type); +static int smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfg_base, char *type); +static int smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); +static int smsc_superio_fdc(unsigned short cfg_base); +static int smsc_superio_lpc(unsigned short cfg_base); #ifdef CONFIG_PCI -static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf); -static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); -static void __init preconfigure_ali_port(struct pci_dev *dev, +static int preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf); +static int preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); +static void preconfigure_ali_port(struct pci_dev *dev, unsigned short port); -static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); -static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, +static int preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); +static int smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, unsigned short ircc_fir, unsigned short ircc_sir, unsigned char ircc_dma, @@ -366,7 +366,7 @@ static inline void register_bank(int iobase, int bank) } /* PNP hotplug support */ -static const struct pnp_device_id smsc_ircc_pnp_table[] = { +static const struct pnp_device_id smsc_ircc_pnp_table[] __devinitconst = { { .id = "SMCf010", .driver_data = 0 }, /* and presumably others */ { } @@ -515,7 +515,7 @@ static const struct net_device_ops smsc_ircc_netdev_ops = { * Try to open driver instance * */ -static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq) +static int __devinit smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq) { struct smsc_ircc_cb *self; struct net_device *dev; @@ -2273,7 +2273,7 @@ static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned sho } -static int __init smsc_access(unsigned short cfg_base, unsigned char reg) +static int __devinit smsc_access(unsigned short cfg_base, unsigned char reg) { IRDA_DEBUG(1, "%s\n", __func__); @@ -2281,7 +2281,7 @@ static int __init smsc_access(unsigned short cfg_base, unsigned char reg) return inb(cfg_base) != reg ? -1 : 0; } -static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type) +static const struct smsc_chip * __devinit smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type) { u8 devid, xdevid, rev; @@ -2406,7 +2406,7 @@ static int __init smsc_superio_lpc(unsigned short cfg_base) #ifdef CONFIG_PCI #define PCIID_VENDOR_INTEL 0x8086 #define PCIID_VENDOR_ALI 0x10b9 -static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __initdata = { +static const struct smsc_ircc_subsystem_configuration subsystem_configurations[] __devinitconst = { /* * Subsystems needing entries: * 0x10b9:0x1533 0x103c:0x0850 HP nx9010 family @@ -2532,7 +2532,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini * (FIR port, SIR port, FIR DMA, FIR IRQ) * through the chip configuration port. */ -static int __init preconfigure_smsc_chip(struct +static int __devinit preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf) { @@ -2633,7 +2633,7 @@ static int __init preconfigure_smsc_chip(struct * or Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge. * They all work the same way! */ -static int __init preconfigure_through_82801(struct pci_dev *dev, +static int __devinit preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf) @@ -2786,7 +2786,7 @@ static int __init preconfigure_through_82801(struct pci_dev *dev, * This is based on reverse-engineering since ALi does not * provide any data sheet for the 1533 chip. */ -static void __init preconfigure_ali_port(struct pci_dev *dev, +static void __devinit preconfigure_ali_port(struct pci_dev *dev, unsigned short port) { unsigned char reg; @@ -2824,7 +2824,7 @@ static void __init preconfigure_ali_port(struct pci_dev *dev, IRDA_MESSAGE("Activated ALi 1533 ISA bridge port 0x%04x.\n", port); } -static int __init preconfigure_through_ali(struct pci_dev *dev, +static int __devinit preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf) @@ -2837,7 +2837,7 @@ static int __init preconfigure_through_ali(struct pci_dev *dev, return preconfigure_smsc_chip(conf); } -static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, +static int __devinit smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, unsigned short ircc_fir, unsigned short ircc_sir, unsigned char ircc_dma, @@ -2849,7 +2849,7 @@ static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, int ret = 0; for_each_pci_dev(dev) { - struct smsc_ircc_subsystem_configuration *conf; + const struct smsc_ircc_subsystem_configuration *conf; /* * Cache the subsystem vendor/device: diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c index 243ed2aee88e..e8984b0ca521 100644 --- a/drivers/net/ne3210.c +++ b/drivers/net/ne3210.c @@ -80,17 +80,20 @@ static void ne3210_block_output(struct net_device *dev, int count, const unsigne #define NE3210_DEBUG 0x0 -static unsigned char irq_map[] __initdata = {15, 12, 11, 10, 9, 7, 5, 3}; -static unsigned int shmem_map[] __initdata = {0xff0, 0xfe0, 0xfff0, 0xd8, 0xffe0, 0xffc0, 0xd0, 0x0}; -static const char *ifmap[] __initdata = {"UTP", "?", "BNC", "AUI"}; -static int ifmap_val[] __initdata = { +static const unsigned char irq_map[] __devinitconst = + { 15, 12, 11, 10, 9, 7, 5, 3 }; +static const unsigned int shmem_map[] __devinitconst = + { 0xff0, 0xfe0, 0xfff0, 0xd8, 0xffe0, 0xffc0, 0xd0, 0x0 }; +static const char *const ifmap[] __devinitconst = + { "UTP", "?", "BNC", "AUI" }; +static const int ifmap_val[] __devinitconst = { IF_PORT_10BASET, IF_PORT_UNKNOWN, IF_PORT_10BASE2, IF_PORT_AUI, }; -static int __init ne3210_eisa_probe (struct device *device) +static int __devinit ne3210_eisa_probe (struct device *device) { unsigned long ioaddr, phys_mem; int i, retval, port_index; @@ -313,7 +316,7 @@ static void ne3210_block_output(struct net_device *dev, int count, memcpy_toio(shmem, buf, count); } -static struct eisa_device_id ne3210_ids[] = { +static const struct eisa_device_id ne3210_ids[] __devinitconst = { { "EGL0101" }, { "NVL1801" }, { "" }, diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c index d07c39cb4daf..0f29f261fcfe 100644 --- a/drivers/net/smc-mca.c +++ b/drivers/net/smc-mca.c @@ -156,7 +156,7 @@ static const struct { { 14, 15 } }; -static short smc_mca_adapter_ids[] __initdata = { +static const short smc_mca_adapter_ids[] __devinitconst = { 0x61c8, 0x61c9, 0x6fc0, @@ -168,7 +168,7 @@ static short smc_mca_adapter_ids[] __initdata = { 0x0000 }; -static char *smc_mca_adapter_names[] __initdata = { +static const char *const smc_mca_adapter_names[] __devinitconst = { "SMC Ethercard PLUS Elite/A BNC/AUI (WD8013EP/A)", "SMC Ethercard PLUS Elite/A UTP/AUI (WD8013WP/A)", "WD Ethercard PLUS/A (WD8003E/A or WD8003ET/A)", @@ -199,7 +199,7 @@ static const struct net_device_ops ultramca_netdev_ops = { #endif }; -static int __init ultramca_probe(struct device *gen_dev) +static int __devinit ultramca_probe(struct device *gen_dev) { unsigned short ioaddr; struct net_device *dev; diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c index 2bedc0ace812..1313aa1315f0 100644 --- a/drivers/net/tokenring/madgemc.c +++ b/drivers/net/tokenring/madgemc.c @@ -727,7 +727,7 @@ static int __devexit madgemc_remove(struct device *device) return 0; } -static short madgemc_adapter_ids[] __initdata = { +static const short madgemc_adapter_ids[] __devinitconst = { 0x002d, 0x0000 }; diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index efaa1d69b720..45144d5bd11b 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -1995,7 +1995,7 @@ SetMulticastFilter(struct net_device *dev) static u_char de4x5_irq[] = EISA_ALLOWED_IRQ_LIST; -static int __init de4x5_eisa_probe (struct device *gendev) +static int __devinit de4x5_eisa_probe (struct device *gendev) { struct eisa_device *edev; u_long iobase; @@ -2097,7 +2097,7 @@ static int __devexit de4x5_eisa_remove (struct device *device) return 0; } -static struct eisa_device_id de4x5_eisa_ids[] = { +static const struct eisa_device_id de4x5_eisa_ids[] __devinitconst = { { "DEC4250", 0 }, /* 0 is the board name index... */ { "" } }; -- cgit v1.2.3-58-ga151 From b437a8cc7de4c9d8d0bdb37e7621c119f7640967 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Mon, 18 Apr 2011 13:31:20 +0000 Subject: net: s2io: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes advertising HW_CSUM as driver does not support it. Note: driver advertises TSO6 but not IPV6_CSUM - bug maybe? Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/s2io.c | 100 +++++++++++------------------------------------------ 1 file changed, 20 insertions(+), 80 deletions(-) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 2302d9743744..58b78f46e54f 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -6618,25 +6618,6 @@ static int s2io_ethtool_get_regs_len(struct net_device *dev) } -static u32 s2io_ethtool_get_rx_csum(struct net_device *dev) -{ - struct s2io_nic *sp = netdev_priv(dev); - - return sp->rx_csum; -} - -static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data) -{ - struct s2io_nic *sp = netdev_priv(dev); - - if (data) - sp->rx_csum = 1; - else - sp->rx_csum = 0; - - return 0; -} - static int s2io_get_eeprom_len(struct net_device *dev) { return XENA_EEPROM_SPACE; @@ -6688,61 +6669,27 @@ static void s2io_ethtool_get_strings(struct net_device *dev, } } -static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) -{ - if (data) - dev->features |= NETIF_F_IP_CSUM; - else - dev->features &= ~NETIF_F_IP_CSUM; - - return 0; -} - -static u32 s2io_ethtool_op_get_tso(struct net_device *dev) -{ - return (dev->features & NETIF_F_TSO) != 0; -} - -static int s2io_ethtool_op_set_tso(struct net_device *dev, u32 data) -{ - if (data) - dev->features |= (NETIF_F_TSO | NETIF_F_TSO6); - else - dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); - - return 0; -} - -static int s2io_ethtool_set_flags(struct net_device *dev, u32 data) +static int s2io_set_features(struct net_device *dev, u32 features) { struct s2io_nic *sp = netdev_priv(dev); - int rc = 0; - int changed = 0; - - if (ethtool_invalid_flags(dev, data, ETH_FLAG_LRO)) - return -EINVAL; - - if (data & ETH_FLAG_LRO) { - if (!(dev->features & NETIF_F_LRO)) { - dev->features |= NETIF_F_LRO; - changed = 1; - } - } else if (dev->features & NETIF_F_LRO) { - dev->features &= ~NETIF_F_LRO; - changed = 1; - } + u32 changed = (features ^ dev->features) & NETIF_F_LRO; if (changed && netif_running(dev)) { + int rc; + s2io_stop_all_tx_queue(sp); s2io_card_down(sp); + dev->features = features; rc = s2io_card_up(sp); if (rc) s2io_reset(sp); else s2io_start_all_tx_queue(sp); + + return rc ? rc : 1; } - return rc; + return 0; } static const struct ethtool_ops netdev_ethtool_ops = { @@ -6758,15 +6705,6 @@ static const struct ethtool_ops netdev_ethtool_ops = { .get_ringparam = s2io_ethtool_gringparam, .get_pauseparam = s2io_ethtool_getpause_data, .set_pauseparam = s2io_ethtool_setpause_data, - .get_rx_csum = s2io_ethtool_get_rx_csum, - .set_rx_csum = s2io_ethtool_set_rx_csum, - .set_tx_csum = s2io_ethtool_op_set_tx_csum, - .set_flags = s2io_ethtool_set_flags, - .get_flags = ethtool_op_get_flags, - .set_sg = ethtool_op_set_sg, - .get_tso = s2io_ethtool_op_get_tso, - .set_tso = s2io_ethtool_op_set_tso, - .set_ufo = ethtool_op_set_ufo, .self_test = s2io_ethtool_test, .get_strings = s2io_ethtool_get_strings, .set_phys_id = s2io_ethtool_set_led, @@ -7538,7 +7476,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && ((!ring_data->lro) || (ring_data->lro && (!(rxdp->Control_1 & RXD_FRAME_IP_FRAG)))) && - (sp->rx_csum)) { + (dev->features & NETIF_F_RXCSUM)) { l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1); l4_csum = RXD_GET_L4_CKSUM(rxdp->Control_1); if ((l3_csum == L3_CKSUM_OK) && (l4_csum == L4_CKSUM_OK)) { @@ -7799,6 +7737,7 @@ static const struct net_device_ops s2io_netdev_ops = { .ndo_do_ioctl = s2io_ioctl, .ndo_set_mac_address = s2io_set_mac_addr, .ndo_change_mtu = s2io_change_mtu, + .ndo_set_features = s2io_set_features, .ndo_vlan_rx_register = s2io_vlan_rx_register, .ndo_vlan_rx_kill_vid = s2io_vlan_rx_kill_vid, .ndo_tx_timeout = s2io_tx_watchdog, @@ -8040,17 +7979,18 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) /* Driver entry points */ dev->netdev_ops = &s2io_netdev_ops; SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->features |= NETIF_F_LRO; - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_RXCSUM | NETIF_F_LRO; + dev->features |= dev->hw_features | + NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + if (sp->device_type & XFRAME_II_DEVICE) { + dev->hw_features |= NETIF_F_UFO; + if (ufo) + dev->features |= NETIF_F_UFO; + } if (sp->high_dma_flag == true) dev->features |= NETIF_F_HIGHDMA; - dev->features |= NETIF_F_TSO; - dev->features |= NETIF_F_TSO6; - if ((sp->device_type & XFRAME_II_DEVICE) && (ufo)) { - dev->features |= NETIF_F_UFO; - dev->features |= NETIF_F_HW_CSUM; - } dev->watchdog_timeo = WATCH_DOG_TIMEOUT; INIT_WORK(&sp->rst_timer_task, s2io_restart_nic); INIT_WORK(&sp->set_link_task, s2io_set_link); -- cgit v1.2.3-58-ga151 From 30f554f925335abad89aaa38eec6828242b27527 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Mon, 18 Apr 2011 13:31:20 +0000 Subject: net: chelsio: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also remove flags that were not used or are now redundant to hw_features bits. No device had UDP_CSUM_CAPABLE set. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/chelsio/common.h | 5 ----- drivers/net/chelsio/cxgb2.c | 48 +++++++------------------------------------- drivers/net/chelsio/sge.c | 13 ++++++------ drivers/net/chelsio/tp.c | 5 ----- drivers/net/chelsio/tp.h | 1 - 5 files changed, 14 insertions(+), 58 deletions(-) diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index 092f31a126e6..c26d863e1697 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -264,11 +264,6 @@ struct adapter { enum { /* adapter flags */ FULL_INIT_DONE = 1 << 0, - TSO_CAPABLE = 1 << 2, - TCP_CSUM_CAPABLE = 1 << 3, - UDP_CSUM_CAPABLE = 1 << 4, - VLAN_ACCEL_CAPABLE = 1 << 5, - RX_CSUM_ENABLED = 1 << 6, }; struct mdio_ops; diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 0f71304e0542..5f82c9c34978 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -192,10 +192,8 @@ static void link_start(struct port_info *p) static void enable_hw_csum(struct adapter *adapter) { - if (adapter->flags & TSO_CAPABLE) + if (adapter->port[0].dev->hw_features & NETIF_F_TSO) t1_tp_set_ip_checksum_offload(adapter->tp, 1); /* for TSO only */ - if (adapter->flags & UDP_CSUM_CAPABLE) - t1_tp_set_udp_checksum_offload(adapter->tp, 1); t1_tp_set_tcp_checksum_offload(adapter->tp, 1); } @@ -705,33 +703,6 @@ static int set_pauseparam(struct net_device *dev, return 0; } -static u32 get_rx_csum(struct net_device *dev) -{ - struct adapter *adapter = dev->ml_priv; - - return (adapter->flags & RX_CSUM_ENABLED) != 0; -} - -static int set_rx_csum(struct net_device *dev, u32 data) -{ - struct adapter *adapter = dev->ml_priv; - - if (data) - adapter->flags |= RX_CSUM_ENABLED; - else - adapter->flags &= ~RX_CSUM_ENABLED; - return 0; -} - -static int set_tso(struct net_device *dev, u32 value) -{ - struct adapter *adapter = dev->ml_priv; - - if (!(adapter->flags & TSO_CAPABLE)) - return value ? -EOPNOTSUPP : 0; - return ethtool_op_set_tso(dev, value); -} - static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e) { struct adapter *adapter = dev->ml_priv; @@ -831,17 +802,12 @@ static const struct ethtool_ops t1_ethtool_ops = { .get_eeprom = get_eeprom, .get_pauseparam = get_pauseparam, .set_pauseparam = set_pauseparam, - .get_rx_csum = get_rx_csum, - .set_rx_csum = set_rx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_sg = ethtool_op_set_sg, .get_link = ethtool_op_get_link, .get_strings = get_strings, .get_sset_count = get_sset_count, .get_ethtool_stats = get_stats, .get_regs_len = get_regs_len, .get_regs = get_regs, - .set_tso = set_tso, }; static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd) @@ -1105,28 +1071,28 @@ static int __devinit init_one(struct pci_dev *pdev, netdev->mem_start = mmio_start; netdev->mem_end = mmio_start + mmio_len - 1; netdev->ml_priv = adapter; - netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - netdev->features |= NETIF_F_LLTX; + netdev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_RXCSUM; + netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_RXCSUM | NETIF_F_LLTX; - adapter->flags |= RX_CSUM_ENABLED | TCP_CSUM_CAPABLE; if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; if (vlan_tso_capable(adapter)) { #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) - adapter->flags |= VLAN_ACCEL_CAPABLE; netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; #endif /* T204: disable TSO */ if (!(is_T2(adapter)) || bi->port_number != 4) { - adapter->flags |= TSO_CAPABLE; + netdev->hw_features |= NETIF_F_TSO; netdev->features |= NETIF_F_TSO; } } netdev->netdev_ops = &cxgb_netdev_ops; - netdev->hard_header_len += (adapter->flags & TSO_CAPABLE) ? + netdev->hard_header_len += (netdev->hw_features & NETIF_F_TSO) ? sizeof(struct cpl_tx_pkt_lso) : sizeof(struct cpl_tx_pkt); netif_napi_add(netdev, &adapter->napi, t1_poll, 64); diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 8754d4473042..b948ea737550 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -929,7 +929,7 @@ void t1_sge_intr_enable(struct sge *sge) u32 en = SGE_INT_ENABLE; u32 val = readl(sge->adapter->regs + A_PL_ENABLE); - if (sge->adapter->flags & TSO_CAPABLE) + if (sge->adapter->port[0].dev->hw_features & NETIF_F_TSO) en &= ~F_PACKET_TOO_BIG; writel(en, sge->adapter->regs + A_SG_INT_ENABLE); writel(val | SGE_PL_INTR_MASK, sge->adapter->regs + A_PL_ENABLE); @@ -952,7 +952,7 @@ int t1_sge_intr_error_handler(struct sge *sge) struct adapter *adapter = sge->adapter; u32 cause = readl(adapter->regs + A_SG_INT_CAUSE); - if (adapter->flags & TSO_CAPABLE) + if (adapter->port[0].dev->hw_features & NETIF_F_TSO) cause &= ~F_PACKET_TOO_BIG; if (cause & F_RESPQ_EXHAUSTED) sge->stats.respQ_empty++; @@ -1369,6 +1369,7 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len) const struct cpl_rx_pkt *p; struct adapter *adapter = sge->adapter; struct sge_port_stats *st; + struct net_device *dev; skb = get_packet(adapter->pdev, fl, len - sge->rx_pkt_pad); if (unlikely(!skb)) { @@ -1384,9 +1385,10 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len) __skb_pull(skb, sizeof(*p)); st = this_cpu_ptr(sge->port_stats[p->iff]); + dev = adapter->port[p->iff].dev; - skb->protocol = eth_type_trans(skb, adapter->port[p->iff].dev); - if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff && + skb->protocol = eth_type_trans(skb, dev); + if ((dev->features & NETIF_F_RXCSUM) && p->csum == 0xffff && skb->protocol == htons(ETH_P_IP) && (skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) { ++st->rx_cso_good; @@ -1838,8 +1840,7 @@ netdev_tx_t t1_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } - if (!(adapter->flags & UDP_CSUM_CAPABLE) && - skb->ip_summed == CHECKSUM_PARTIAL && + if (skb->ip_summed == CHECKSUM_PARTIAL && ip_hdr(skb)->protocol == IPPROTO_UDP) { if (unlikely(skb_checksum_help(skb))) { pr_debug("%s: unable to do udp checksum\n", dev->name); diff --git a/drivers/net/chelsio/tp.c b/drivers/net/chelsio/tp.c index 6222d585e447..8bed4a59e65f 100644 --- a/drivers/net/chelsio/tp.c +++ b/drivers/net/chelsio/tp.c @@ -152,11 +152,6 @@ void t1_tp_set_ip_checksum_offload(struct petp *tp, int enable) set_csum_offload(tp, F_IP_CSUM, enable); } -void t1_tp_set_udp_checksum_offload(struct petp *tp, int enable) -{ - set_csum_offload(tp, F_UDP_CSUM, enable); -} - void t1_tp_set_tcp_checksum_offload(struct petp *tp, int enable) { set_csum_offload(tp, F_TCP_CSUM, enable); diff --git a/drivers/net/chelsio/tp.h b/drivers/net/chelsio/tp.h index 32fc71e58913..dfd8ce25106a 100644 --- a/drivers/net/chelsio/tp.h +++ b/drivers/net/chelsio/tp.h @@ -65,7 +65,6 @@ void t1_tp_intr_clear(struct petp *tp); int t1_tp_intr_handler(struct petp *tp); void t1_tp_get_mib_statistics(adapter_t *adap, struct tp_mib_statistics *tps); -void t1_tp_set_udp_checksum_offload(struct petp *tp, int enable); void t1_tp_set_tcp_checksum_offload(struct petp *tp, int enable); void t1_tp_set_ip_checksum_offload(struct petp *tp, int enable); int t1_tp_set_coalescing_size(struct petp *tp, unsigned int size); -- cgit v1.2.3-58-ga151 From feb990d467f76abe90ae68437eb1db351e67c674 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Mon, 18 Apr 2011 13:31:21 +0000 Subject: net: vxge: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Side effect: ->gro_enable is removed as napi_gro_receive() does the fallback itself. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/vxge/vxge-ethtool.c | 72 ----------------------------- drivers/net/vxge/vxge-main.c | 100 ++++++++++++++++++++++------------------ drivers/net/vxge/vxge-main.h | 14 ++---- 3 files changed, 59 insertions(+), 127 deletions(-) diff --git a/drivers/net/vxge/vxge-ethtool.c b/drivers/net/vxge/vxge-ethtool.c index 43c458323f83..5aef6c893aee 100644 --- a/drivers/net/vxge/vxge-ethtool.c +++ b/drivers/net/vxge/vxge-ethtool.c @@ -1071,35 +1071,6 @@ static int vxge_ethtool_get_regs_len(struct net_device *dev) return sizeof(struct vxge_hw_vpath_reg) * vdev->no_of_vpath; } -static u32 vxge_get_rx_csum(struct net_device *dev) -{ - struct vxgedev *vdev = netdev_priv(dev); - - return vdev->rx_csum; -} - -static int vxge_set_rx_csum(struct net_device *dev, u32 data) -{ - struct vxgedev *vdev = netdev_priv(dev); - - if (data) - vdev->rx_csum = 1; - else - vdev->rx_csum = 0; - - return 0; -} - -static int vxge_ethtool_op_set_tso(struct net_device *dev, u32 data) -{ - if (data) - dev->features |= (NETIF_F_TSO | NETIF_F_TSO6); - else - dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); - - return 0; -} - static int vxge_ethtool_get_sset_count(struct net_device *dev, int sset) { struct vxgedev *vdev = netdev_priv(dev); @@ -1119,40 +1090,6 @@ static int vxge_ethtool_get_sset_count(struct net_device *dev, int sset) } } -static int vxge_set_flags(struct net_device *dev, u32 data) -{ - struct vxgedev *vdev = netdev_priv(dev); - enum vxge_hw_status status; - - if (ethtool_invalid_flags(dev, data, ETH_FLAG_RXHASH)) - return -EINVAL; - - if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en) - return 0; - - if (netif_running(dev) || (vdev->config.rth_steering == NO_STEERING)) - return -EINVAL; - - vdev->devh->config.rth_en = !!(data & ETH_FLAG_RXHASH); - - /* Enabling RTH requires some of the logic in vxge_device_register and a - * vpath reset. Due to these restrictions, only allow modification - * while the interface is down. - */ - status = vxge_reset_all_vpaths(vdev); - if (status != VXGE_HW_OK) { - vdev->devh->config.rth_en = !vdev->devh->config.rth_en; - return -EFAULT; - } - - if (vdev->devh->config.rth_en) - dev->features |= NETIF_F_RXHASH; - else - dev->features &= ~NETIF_F_RXHASH; - - return 0; -} - static int vxge_fw_flash(struct net_device *dev, struct ethtool_flash *parms) { struct vxgedev *vdev = netdev_priv(dev); @@ -1181,19 +1118,10 @@ static const struct ethtool_ops vxge_ethtool_ops = { .get_link = ethtool_op_get_link, .get_pauseparam = vxge_ethtool_getpause_data, .set_pauseparam = vxge_ethtool_setpause_data, - .get_rx_csum = vxge_get_rx_csum, - .set_rx_csum = vxge_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_ipv6_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = vxge_ethtool_op_set_tso, .get_strings = vxge_ethtool_get_strings, .set_phys_id = vxge_ethtool_idnic, .get_sset_count = vxge_ethtool_get_sset_count, .get_ethtool_stats = vxge_get_ethtool_stats, - .set_flags = vxge_set_flags, .flash_device = vxge_fw_flash, }; diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index d192dad8ff21..fc837cf6bd4d 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -304,22 +304,14 @@ vxge_rx_complete(struct vxge_ring *ring, struct sk_buff *skb, u16 vlan, "%s: %s:%d skb protocol = %d", ring->ndev->name, __func__, __LINE__, skb->protocol); - if (ring->gro_enable) { - if (ring->vlgrp && ext_info->vlan && - (ring->vlan_tag_strip == - VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_ENABLE)) - vlan_gro_receive(ring->napi_p, ring->vlgrp, - ext_info->vlan, skb); - else - napi_gro_receive(ring->napi_p, skb); - } else { - if (ring->vlgrp && vlan && - (ring->vlan_tag_strip == - VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_ENABLE)) - vlan_hwaccel_receive_skb(skb, ring->vlgrp, vlan); - else - netif_receive_skb(skb); - } + if (ring->vlgrp && ext_info->vlan && + (ring->vlan_tag_strip == + VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_ENABLE)) + vlan_gro_receive(ring->napi_p, ring->vlgrp, + ext_info->vlan, skb); + else + napi_gro_receive(ring->napi_p, skb); + vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d Exiting...", ring->ndev->name, __func__, __LINE__); } @@ -490,7 +482,7 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr, if ((ext_info.proto & VXGE_HW_FRAME_PROTO_TCP_OR_UDP) && !(ext_info.proto & VXGE_HW_FRAME_PROTO_IP_FRAG) && - ring->rx_csum && /* Offload Rx side CSUM */ + (dev->features & NETIF_F_RXCSUM) && /* Offload Rx side CSUM */ ext_info.l3_cksum == VXGE_HW_L3_CKSUM_OK && ext_info.l4_cksum == VXGE_HW_L4_CKSUM_OK) skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -2094,11 +2086,9 @@ static int vxge_open_vpaths(struct vxgedev *vdev) vdev->config.fifo_indicate_max_pkts; vpath->fifo.tx_vector_no = 0; vpath->ring.rx_vector_no = 0; - vpath->ring.rx_csum = vdev->rx_csum; vpath->ring.rx_hwts = vdev->rx_hwts; vpath->is_open = 1; vdev->vp_handles[i] = vpath->handle; - vpath->ring.gro_enable = vdev->config.gro_enable; vpath->ring.vlan_tag_strip = vdev->vlan_tag_strip; vdev->stats.vpaths_open++; } else { @@ -2670,6 +2660,40 @@ static void vxge_poll_vp_lockup(unsigned long data) mod_timer(&vdev->vp_lockup_timer, jiffies + HZ / 1000); } +static u32 vxge_fix_features(struct net_device *dev, u32 features) +{ + u32 changed = dev->features ^ features; + + /* Enabling RTH requires some of the logic in vxge_device_register and a + * vpath reset. Due to these restrictions, only allow modification + * while the interface is down. + */ + if ((changed & NETIF_F_RXHASH) && netif_running(dev)) + features ^= NETIF_F_RXHASH; + + return features; +} + +static int vxge_set_features(struct net_device *dev, u32 features) +{ + struct vxgedev *vdev = netdev_priv(dev); + u32 changed = dev->features ^ features; + + if (!(changed & NETIF_F_RXHASH)) + return 0; + + /* !netif_running() ensured by vxge_fix_features() */ + + vdev->devh->config.rth_en = !!(features & NETIF_F_RXHASH); + if (vxge_reset_all_vpaths(vdev) != VXGE_HW_OK) { + dev->features = features ^ NETIF_F_RXHASH; + vdev->devh->config.rth_en = !!(dev->features & NETIF_F_RXHASH); + return -EIO; + } + + return 0; +} + /** * vxge_open * @dev: pointer to the device structure. @@ -3369,6 +3393,8 @@ static const struct net_device_ops vxge_netdev_ops = { .ndo_do_ioctl = vxge_ioctl, .ndo_set_mac_address = vxge_set_mac_addr, .ndo_change_mtu = vxge_change_mtu, + .ndo_fix_features = vxge_fix_features, + .ndo_set_features = vxge_set_features, .ndo_vlan_rx_register = vxge_vlan_rx_register, .ndo_vlan_rx_kill_vid = vxge_vlan_rx_kill_vid, .ndo_vlan_rx_add_vid = vxge_vlan_rx_add_vid, @@ -3415,14 +3441,21 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, vdev->devh = hldev; vdev->pdev = hldev->pdev; memcpy(&vdev->config, config, sizeof(struct vxge_config)); - vdev->rx_csum = 1; /* Enable Rx CSUM by default. */ vdev->rx_hwts = 0; vdev->titan1 = (vdev->pdev->revision == VXGE_HW_TITAN1_PCI_REVISION); SET_NETDEV_DEV(ndev, &vdev->pdev->dev); - ndev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | - NETIF_F_HW_VLAN_FILTER; + ndev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_HW_VLAN_TX; + if (vdev->config.rth_steering != NO_STEERING) + ndev->hw_features |= NETIF_F_RXHASH; + + ndev->features |= ndev->hw_features | + NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; + /* Driver entry points */ ndev->irq = vdev->pdev->irq; ndev->base_addr = (unsigned long) hldev->bar0; @@ -3434,11 +3467,6 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, vxge_initialize_ethtool_ops(ndev); - if (vdev->config.rth_steering != NO_STEERING) { - ndev->features |= NETIF_F_RXHASH; - hldev->config.rth_en = VXGE_HW_RTH_ENABLE; - } - /* Allocate memory for vpath */ vdev->vpaths = kzalloc((sizeof(struct vxge_vpath)) * no_of_vpath, GFP_KERNEL); @@ -3450,9 +3478,6 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, goto _out1; } - ndev->features |= NETIF_F_SG; - - ndev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; vxge_debug_init(vxge_hw_device_trace_level_get(hldev), "%s : checksuming enabled", __func__); @@ -3462,11 +3487,6 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, "%s : using High DMA", __func__); } - ndev->features |= NETIF_F_TSO | NETIF_F_TSO6; - - if (vdev->config.gro_enable) - ndev->features |= NETIF_F_GRO; - ret = register_netdev(ndev); if (ret) { vxge_debug_init(vxge_hw_device_trace_level_get(hldev), @@ -3996,15 +4016,6 @@ static void __devinit vxge_print_parm(struct vxgedev *vdev, u64 vpath_mask) vdev->config.tx_steering_type = 0; } - if (vdev->config.gro_enable) { - vxge_debug_init(VXGE_ERR, - "%s: Generic receive offload enabled", - vdev->ndev->name); - } else - vxge_debug_init(VXGE_TRACE, - "%s: Generic receive offload disabled", - vdev->ndev->name); - if (vdev->config.addr_learn_en) vxge_debug_init(VXGE_TRACE, "%s: MAC Address learning enabled", vdev->ndev->name); @@ -4589,7 +4600,6 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) /* set private device info */ pci_set_drvdata(pdev, hldev); - ll_config->gro_enable = VXGE_GRO_ALWAYS_AGGREGATE; ll_config->fifo_indicate_max_pkts = VXGE_FIFO_INDICATE_MAX_PKTS; ll_config->addr_learn_en = addr_learn_en; ll_config->rth_algorithm = RTH_ALG_JENKINS; diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/vxge/vxge-main.h index 40474f0da576..ed120aba443d 100644 --- a/drivers/net/vxge/vxge-main.h +++ b/drivers/net/vxge/vxge-main.h @@ -168,9 +168,6 @@ struct vxge_config { #define NEW_NAPI_WEIGHT 64 int napi_weight; -#define VXGE_GRO_DONOT_AGGREGATE 0 -#define VXGE_GRO_ALWAYS_AGGREGATE 1 - int gro_enable; int intr_type; #define INTA 0 #define MSI 1 @@ -290,13 +287,11 @@ struct vxge_ring { unsigned long interrupt_count; unsigned long jiffies; - /* copy of the flag indicating whether rx_csum is to be used */ - u32 rx_csum:1, - rx_hwts:1; + /* copy of the flag indicating whether rx_hwts is to be used */ + u32 rx_hwts:1; int pkts_processed; int budget; - int gro_enable; struct napi_struct napi; struct napi_struct *napi_p; @@ -369,9 +364,8 @@ struct vxgedev { */ u16 all_multi_flg; - /* A flag indicating whether rx_csum is to be used or not. */ - u32 rx_csum:1, - rx_hwts:1, + /* A flag indicating whether rx_hwts is to be used or not. */ + u32 rx_hwts:1, titan1:1; struct vxge_msix_entry *vxge_entries; -- cgit v1.2.3-58-ga151 From a0d2730c9571aeba793cb5d3009094ee1d8fda35 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Mon, 18 Apr 2011 13:31:21 +0000 Subject: net: vmxnet3: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also removes private feature flags that were always set to true. You may want to move vmxnet3_set_features() to vmxnet3_drv.c as a following cleanup. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/vmxnet3/vmxnet3_drv.c | 40 ++++++++------------- drivers/net/vmxnet3/vmxnet3_ethtool.c | 67 ++++++----------------------------- drivers/net/vmxnet3/vmxnet3_int.h | 7 ++-- 3 files changed, 28 insertions(+), 86 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 0d47c3a05307..7a494f79c88f 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -1082,7 +1082,7 @@ vmxnet3_rx_csum(struct vmxnet3_adapter *adapter, struct sk_buff *skb, union Vmxnet3_GenericDesc *gdesc) { - if (!gdesc->rcd.cnc && adapter->rxcsum) { + if (!gdesc->rcd.cnc && adapter->netdev->features & NETIF_F_RXCSUM) { /* typical case: TCP/UDP over IP and both csums are correct */ if ((le32_to_cpu(gdesc->dword[3]) & VMXNET3_RCD_CSUM_OK) == VMXNET3_RCD_CSUM_OK) { @@ -2081,10 +2081,10 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter) devRead->misc.ddLen = cpu_to_le32(sizeof(struct vmxnet3_adapter)); /* set up feature flags */ - if (adapter->rxcsum) + if (adapter->netdev->features & NETIF_F_RXCSUM) devRead->misc.uptFeatures |= UPT1_F_RXCSUM; - if (adapter->lro) { + if (adapter->netdev->features & NETIF_F_LRO) { devRead->misc.uptFeatures |= UPT1_F_LRO; devRead->misc.maxNumRxSG = cpu_to_le16(1 + MAX_SKB_FRAGS); } @@ -2593,9 +2593,6 @@ vmxnet3_change_mtu(struct net_device *netdev, int new_mtu) if (new_mtu < VMXNET3_MIN_MTU || new_mtu > VMXNET3_MAX_MTU) return -EINVAL; - if (new_mtu > 1500 && !adapter->jumbo_frame) - return -EINVAL; - netdev->mtu = new_mtu; /* @@ -2641,28 +2638,18 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter, bool dma64) { struct net_device *netdev = adapter->netdev; - netdev->features = NETIF_F_SG | - NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_TX | - NETIF_F_HW_VLAN_RX | - NETIF_F_HW_VLAN_FILTER | - NETIF_F_TSO | - NETIF_F_TSO6 | - NETIF_F_LRO; - - printk(KERN_INFO "features: sg csum vlan jf tso tsoIPv6 lro"); - - adapter->rxcsum = true; - adapter->jumbo_frame = true; - adapter->lro = true; - - if (dma64) { + netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | + NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX | + NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_LRO; + if (dma64) netdev->features |= NETIF_F_HIGHDMA; - printk(" highDMA"); - } + netdev->vlan_features = netdev->hw_features & ~NETIF_F_HW_VLAN_TX; + netdev->features = netdev->hw_features | + NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; - netdev->vlan_features = netdev->features; - printk("\n"); + netdev_info(adapter->netdev, + "features: sg csum vlan jf tso tsoIPv6 lro%s\n", + dma64 ? " highDMA" : ""); } @@ -2874,6 +2861,7 @@ vmxnet3_probe_device(struct pci_dev *pdev, .ndo_start_xmit = vmxnet3_xmit_frame, .ndo_set_mac_address = vmxnet3_set_mac_addr, .ndo_change_mtu = vmxnet3_change_mtu, + .ndo_set_features = vmxnet3_set_features, .ndo_get_stats = vmxnet3_get_stats, .ndo_tx_timeout = vmxnet3_tx_timeout, .ndo_set_multicast_list = vmxnet3_set_mc, diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index 51f2ef142a5b..70c1ab96ed27 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c @@ -33,40 +33,6 @@ struct vmxnet3_stat_desc { }; -static u32 -vmxnet3_get_rx_csum(struct net_device *netdev) -{ - struct vmxnet3_adapter *adapter = netdev_priv(netdev); - return adapter->rxcsum; -} - - -static int -vmxnet3_set_rx_csum(struct net_device *netdev, u32 val) -{ - struct vmxnet3_adapter *adapter = netdev_priv(netdev); - unsigned long flags; - - if (adapter->rxcsum != val) { - adapter->rxcsum = val; - if (netif_running(netdev)) { - if (val) - adapter->shared->devRead.misc.uptFeatures |= - UPT1_F_RXCSUM; - else - adapter->shared->devRead.misc.uptFeatures &= - ~UPT1_F_RXCSUM; - - spin_lock_irqsave(&adapter->cmd_lock, flags); - VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, - VMXNET3_CMD_UPDATE_FEATURE); - spin_unlock_irqrestore(&adapter->cmd_lock, flags); - } - } - return 0; -} - - /* per tq stats maintained by the device */ static const struct vmxnet3_stat_desc vmxnet3_tq_dev_stats[] = { @@ -296,28 +262,27 @@ vmxnet3_get_strings(struct net_device *netdev, u32 stringset, u8 *buf) } } -static int -vmxnet3_set_flags(struct net_device *netdev, u32 data) +int vmxnet3_set_features(struct net_device *netdev, u32 features) { struct vmxnet3_adapter *adapter = netdev_priv(netdev); - u8 lro_requested = (data & ETH_FLAG_LRO) == 0 ? 0 : 1; - u8 lro_present = (netdev->features & NETIF_F_LRO) == 0 ? 0 : 1; unsigned long flags; + u32 changed = features ^ netdev->features; - if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO)) - return -EINVAL; - - if (lro_requested ^ lro_present) { - /* toggle the LRO feature*/ - netdev->features ^= NETIF_F_LRO; + if (changed & (NETIF_F_RXCSUM|NETIF_F_LRO)) { + if (features & NETIF_F_RXCSUM) + adapter->shared->devRead.misc.uptFeatures |= + UPT1_F_RXCSUM; + else + adapter->shared->devRead.misc.uptFeatures &= + ~UPT1_F_RXCSUM; - /* update harware LRO capability accordingly */ - if (lro_requested) + if (features & NETIF_F_LRO) adapter->shared->devRead.misc.uptFeatures |= UPT1_F_LRO; else adapter->shared->devRead.misc.uptFeatures &= ~UPT1_F_LRO; + spin_lock_irqsave(&adapter->cmd_lock, flags); VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_UPDATE_FEATURE); @@ -654,17 +619,7 @@ static struct ethtool_ops vmxnet3_ethtool_ops = { .get_wol = vmxnet3_get_wol, .set_wol = vmxnet3_set_wol, .get_link = ethtool_op_get_link, - .get_rx_csum = vmxnet3_get_rx_csum, - .set_rx_csum = vmxnet3_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_hw_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, .get_strings = vmxnet3_get_strings, - .get_flags = ethtool_op_get_flags, - .set_flags = vmxnet3_set_flags, .get_sset_count = vmxnet3_get_sset_count, .get_ethtool_stats = vmxnet3_get_ethtool_stats, .get_ringparam = vmxnet3_get_ringparam, diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index fb5d245ac878..8ba7b5f67de2 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -329,10 +329,6 @@ struct vmxnet3_adapter { u8 __iomem *hw_addr0; /* for BAR 0 */ u8 __iomem *hw_addr1; /* for BAR 1 */ - /* feature control */ - bool rxcsum; - bool lro; - bool jumbo_frame; #ifdef VMXNET3_RSS struct UPT1_RSSConf *rss_conf; bool rss; @@ -403,6 +399,9 @@ vmxnet3_tq_destroy_all(struct vmxnet3_adapter *adapter); void vmxnet3_rq_destroy_all(struct vmxnet3_adapter *adapter); +int +vmxnet3_set_features(struct net_device *netdev, u32 features); + int vmxnet3_create_queues(struct vmxnet3_adapter *adapter, u32 tx_ring_size, u32 rx_ring_size, u32 rx_ring2_size); -- cgit v1.2.3-58-ga151 From 88230fd586b4ccc5ffe6d6c2df8cdc495e89ad83 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Mon, 18 Apr 2011 13:31:21 +0000 Subject: net: qlge: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Another simple conversion. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_ethtool.c | 34 ---------------------------------- drivers/net/qlge/qlge_main.c | 21 ++++++++------------- 2 files changed, 8 insertions(+), 47 deletions(-) diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index 687754da2a9f..78dc40c18c60 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c @@ -655,32 +655,6 @@ static int ql_set_pauseparam(struct net_device *netdev, return status; } -static u32 ql_get_rx_csum(struct net_device *netdev) -{ - struct ql_adapter *qdev = netdev_priv(netdev); - return qdev->rx_csum; -} - -static int ql_set_rx_csum(struct net_device *netdev, uint32_t data) -{ - struct ql_adapter *qdev = netdev_priv(netdev); - qdev->rx_csum = data; - return 0; -} - -static int ql_set_tso(struct net_device *ndev, uint32_t data) -{ - - if (data) { - ndev->features |= NETIF_F_TSO; - ndev->features |= NETIF_F_TSO6; - } else { - ndev->features &= ~NETIF_F_TSO; - ndev->features &= ~NETIF_F_TSO6; - } - return 0; -} - static u32 ql_get_msglevel(struct net_device *ndev) { struct ql_adapter *qdev = netdev_priv(ndev); @@ -707,14 +681,6 @@ const struct ethtool_ops qlge_ethtool_ops = { .self_test = ql_self_test, .get_pauseparam = ql_get_pauseparam, .set_pauseparam = ql_set_pauseparam, - .get_rx_csum = ql_get_rx_csum, - .set_rx_csum = ql_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = ql_set_tso, .get_coalesce = ql_get_coalesce, .set_coalesce = ql_set_coalesce, .get_sset_count = ql_get_sset_count, diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index f61e717adac4..6c9d124cfc76 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1571,7 +1571,7 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, skb->protocol = eth_type_trans(skb, ndev); skb_checksum_none_assert(skb); - if (qdev->rx_csum && + if ((ndev->features & NETIF_F_RXCSUM) && !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { /* TCP frame. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { @@ -1684,7 +1684,7 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, /* If rx checksum is on, and there are no * csum or frame errors. */ - if (qdev->rx_csum && + if ((ndev->features & NETIF_F_RXCSUM) && !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { /* TCP frame. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { @@ -2004,7 +2004,7 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, /* If rx checksum is on, and there are no * csum or frame errors. */ - if (qdev->rx_csum && + if ((ndev->features & NETIF_F_RXCSUM) && !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { /* TCP frame. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { @@ -4621,7 +4621,6 @@ static int __devinit ql_init_device(struct pci_dev *pdev, /* * Set up the operating parameters. */ - qdev->rx_csum = 1; qdev->workqueue = create_singlethread_workqueue(ndev->name); INIT_DELAYED_WORK(&qdev->asic_reset_work, ql_asic_reset_work); INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work); @@ -4695,15 +4694,11 @@ static int __devinit qlge_probe(struct pci_dev *pdev, qdev = netdev_priv(ndev); SET_NETDEV_DEV(ndev, &pdev->dev); - ndev->features = (0 - | NETIF_F_IP_CSUM - | NETIF_F_SG - | NETIF_F_TSO - | NETIF_F_TSO6 - | NETIF_F_TSO_ECN - | NETIF_F_HW_VLAN_TX - | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER); - ndev->features |= NETIF_F_GRO; + ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN | + NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM; + ndev->features = ndev->hw_features | + NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; if (test_bit(QL_DMA64, &qdev->flags)) ndev->features |= NETIF_F_HIGHDMA; -- cgit v1.2.3-58-ga151 From 62c7d085e1f2a1f2b4d89560551eff18d703b3b1 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 10 Mar 2011 16:42:47 +0200 Subject: wl12xx: add new board_tcxo_clock element to the platform data This new value is a new type of clock setting that is used by wl128x chipsets. Signed-off-by: Luciano Coelho --- include/linux/wl12xx.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h index bebb8efea0a6..eb8aacab8d4e 100644 --- a/include/linux/wl12xx.h +++ b/include/linux/wl12xx.h @@ -24,7 +24,7 @@ #ifndef _LINUX_WL12XX_H #define _LINUX_WL12XX_H -/* The board reference clock values */ +/* Reference clock values */ enum { WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */ WL12XX_REFCLOCK_26 = 1, /* 26 MHz */ @@ -32,12 +32,25 @@ enum { WL12XX_REFCLOCK_54 = 3, /* 54 MHz */ }; +/* TCXO clock values */ +enum { + WL12XX_TCXOCLOCK_19_2 = 0, /* 19.2MHz */ + WL12XX_TCXOCLOCK_26 = 1, /* 26 MHz */ + WL12XX_TCXOCLOCK_38_4 = 2, /* 38.4MHz */ + WL12XX_TCXOCLOCK_52 = 3, /* 52 MHz */ + WL12XX_TCXOCLOCK_16_368 = 4, /* 16.368 MHz */ + WL12XX_TCXOCLOCK_32_736 = 5, /* 32.736 MHz */ + WL12XX_TCXOCLOCK_16_8 = 6, /* 16.8 MHz */ + WL12XX_TCXOCLOCK_33_6 = 7, /* 33.6 MHz */ +}; + struct wl12xx_platform_data { void (*set_power)(bool enable); /* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */ int irq; bool use_eeprom; int board_ref_clock; + int board_tcxo_clock; }; #ifdef CONFIG_WL12XX_PLATFORM_DATA -- cgit v1.2.3-58-ga151 From b9b0fdead0e8d964a534e5b09f40d8bd4bf7dfe8 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 6 Mar 2011 16:32:06 +0200 Subject: wl12xx: 1281/1283 support - move IRQ polarity In order to prevent overran of IRQ polarity via FW the polarity setting move after FW download and before IRQ enable. Signed-off-by: Shahar Levi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/boot.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 6934dffd5174..69fe8703be42 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -585,13 +585,6 @@ int wl1271_load_firmware(struct wl1271 *wl) /* 6. read the EEPROM parameters */ tmp = wl1271_read32(wl, SCR_PAD2); - ret = wl1271_boot_write_irq_polarity(wl); - if (ret < 0) - goto out; - - wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, - WL1271_ACX_ALL_EVENTS_VECTOR); - /* WL1271: The reference driver skips steps 7 to 10 (jumps directly * to upload_fw) */ @@ -618,6 +611,13 @@ int wl1271_boot(struct wl1271 *wl) if (ret < 0) goto out; + ret = wl1271_boot_write_irq_polarity(wl); + if (ret < 0) + goto out; + + wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, + WL1271_ACX_ALL_EVENTS_VECTOR); + /* Enable firmware interrupts now */ wl1271_boot_enable_interrupts(wl); -- cgit v1.2.3-58-ga151 From 5aa42346bba2e385674eb1dd4019dfce4c2ef771 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 6 Mar 2011 16:32:07 +0200 Subject: wl12xx: 1281/1283 support - Add Definitions Definitions to support wl128x: - New FW file name - Chip ID - New PLL Configuration Algorithm macros that will be used at wl128x boot stage - Rename NVS macro name: wl127x and wl128x are using the same NVS file name. However, the ini parameters between them are different. The driver will validate the correct NVS size in wl1271_boot_upload_nvs(). [Cleaned up some of the definitions. -- Luca] Signed-off-by: Shahar Levi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/boot.h | 48 +++++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/conf.h | 4 ++- drivers/net/wireless/wl12xx/main.c | 2 +- drivers/net/wireless/wl12xx/reg.h | 15 ++--------- drivers/net/wireless/wl12xx/sdio.c | 1 + drivers/net/wireless/wl12xx/sdio_test.c | 2 +- drivers/net/wireless/wl12xx/spi.c | 1 + drivers/net/wireless/wl12xx/wl12xx.h | 8 +++++- 8 files changed, 64 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h index 17229b86fc71..1f5ee31dc0b1 100644 --- a/drivers/net/wireless/wl12xx/boot.h +++ b/drivers/net/wireless/wl12xx/boot.h @@ -74,4 +74,52 @@ struct wl1271_static_data { #define FREF_CLK_POLARITY_BITS 0xfffff8ff #define CLK_REQ_OUTN_SEL 0x700 +/* PLL configuration algorithm for wl128x */ +#define SYS_CLK_CFG_REG 0x2200 +/* Bit[0] - 0-TCXO, 1-FREF */ +#define MCS_PLL_CLK_SEL_FREF BIT(0) +/* Bit[3:2] - 01-TCXO, 10-FREF */ +#define WL_CLK_REQ_TYPE_FREF BIT(3) +#define WL_CLK_REQ_TYPE_PG2 (BIT(3) | BIT(2)) +/* Bit[4] - 0-TCXO, 1-FREF */ +#define PRCM_CM_EN_MUX_WLAN_FREF BIT(4) + +#define TCXO_ILOAD_INT_REG 0x2264 +#define TCXO_CLK_DETECT_REG 0x2266 + +#define TCXO_DET_FAILED BIT(4) + +#define FREF_ILOAD_INT_REG 0x2084 +#define FREF_CLK_DETECT_REG 0x2086 +#define FREF_CLK_DETECT_FAIL BIT(4) + +/* Use this reg for masking during driver access */ +#define WL_SPARE_REG 0x2320 +#define WL_SPARE_VAL BIT(2) +/* Bit[6:5:3] - mask wl write SYS_CLK_CFG[8:5:2:4] */ +#define WL_SPARE_MASK_8526 (BIT(6) | BIT(5) | BIT(3)) + +#define PLL_LOCK_COUNTERS_REG 0xD8C +#define PLL_LOCK_COUNTERS_COEX 0x0F +#define PLL_LOCK_COUNTERS_MCS 0xF0 +#define MCS_PLL_OVERRIDE_REG 0xD90 +#define MCS_PLL_CONFIG_REG 0xD92 +#define MCS_SEL_IN_FREQ_MASK 0x0070 +#define MCS_SEL_IN_FREQ_SHIFT 4 +#define MCS_PLL_CONFIG_REG_VAL 0x73 + +#define MCS_PLL_M_REG 0xD94 +#define MCS_PLL_N_REG 0xD96 +#define MCS_PLL_M_REG_VAL 0xC8 +#define MCS_PLL_N_REG_VAL 0x07 + +#define SDIO_IO_DS 0xd14 + +/* SDIO/wSPI DS configuration values */ +#define HCI_IO_DS_8MA 0 +#define HCI_IO_DS_4MA 1 /* default */ +#define HCI_IO_DS_6MA 2 +#define HCI_IO_DS_2MA 3 +/* end PLL configuration algorithm for wl128x */ + #endif diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 856a8a2fff4f..a00f22c6c74f 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -1004,7 +1004,9 @@ enum { CONF_REF_CLK_19_2_E, CONF_REF_CLK_26_E, CONF_REF_CLK_38_4_E, - CONF_REF_CLK_52_E + CONF_REF_CLK_52_E, + CONF_REF_CLK_38_4_M_XTAL, + CONF_REF_CLK_26_M_XTAL, }; enum single_dual_band_enum { diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8b3c8d196b03..b0c49352b56f 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -838,7 +838,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) const struct firmware *fw; int ret; - ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); + ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); if (ret < 0) { wl1271_error("could not get nvs file: %d", ret); diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/reg.h index 990960771528..440a4ee9cb42 100644 --- a/drivers/net/wireless/wl12xx/reg.h +++ b/drivers/net/wireless/wl12xx/reg.h @@ -207,6 +207,8 @@ #define CHIP_ID_1271_PG10 (0x4030101) #define CHIP_ID_1271_PG20 (0x4030111) +#define CHIP_ID_1283_PG10 (0x05030101) +#define CHIP_ID_1283_PG20 (0x05030111) #define ENABLE (REGISTERS_BASE + 0x5450) @@ -452,24 +454,11 @@ #define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200 #define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400 -/* - * NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile - * for platforms using active high interrupt level - */ -#ifdef USE_ACTIVE_HIGH #define HI_CFG_DEF_VAL \ (HI_CFG_UART_ENABLE | \ HI_CFG_RST232_ENABLE | \ HI_CFG_CLOCK_REQ_SELECT | \ HI_CFG_HOST_INT_ENABLE) -#else -#define HI_CFG_DEF_VAL \ - (HI_CFG_UART_ENABLE | \ - HI_CFG_RST232_ENABLE | \ - HI_CFG_CLOCK_REQ_SELECT | \ - HI_CFG_HOST_INT_ENABLE) - -#endif #define REF_FREQ_19_2 0 #define REF_FREQ_26_0 1 diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index b1c7d031c391..1b6a1adb81af 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -343,4 +343,5 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); MODULE_FIRMWARE(WL1271_FW_NAME); +MODULE_FIRMWARE(WL128X_FW_NAME); MODULE_FIRMWARE(WL1271_AP_FW_NAME); diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c index 9fcbd3dd8490..01adf1b1003b 100644 --- a/drivers/net/wireless/wl12xx/sdio_test.c +++ b/drivers/net/wireless/wl12xx/sdio_test.c @@ -227,7 +227,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) const struct firmware *fw; int ret; - ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); + ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); if (ret < 0) { wl1271_error("could not get nvs file: %d", ret); diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index ffc745b17f4d..80295f55f23f 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -490,5 +490,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); MODULE_FIRMWARE(WL1271_FW_NAME); +MODULE_FIRMWARE(WL128X_FW_NAME); MODULE_FIRMWARE(WL1271_AP_FW_NAME); MODULE_ALIAS("spi:wl1271"); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 86be83e25ec5..a2e899d4e1aa 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -131,9 +131,15 @@ extern u32 wl12xx_debug_level; #define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin" +#define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin" #define WL1271_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin" -#define WL1271_NVS_NAME "ti-connectivity/wl1271-nvs.bin" +/* + * wl127x and wl128x are using the same NVS file name. However, the + * ini parameters between them are different. The driver validates + * the correct NVS size in wl1271_boot_upload_nvs(). + */ +#define WL12XX_NVS_NAME "ti-connectivity/wl1271-nvs.bin" #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) -- cgit v1.2.3-58-ga151 From 48a61477bdc04896bd96d259388a0c42a7019943 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 6 Mar 2011 16:32:08 +0200 Subject: wl12xx: 1281/1283 support - Add acx commands New acx command that sets: Rx fifo enable reduced bus transactions in RX path. Tx bus transactions padding to SDIO block size that improve preference in Tx and essential for working with SDIO HS (48Mhz). The max SDIO block size is 256 when working with Tx bus transactions padding to SDIO block. Add new ops to SDIO & SPI that handles the win size change in case of transactions padding (relevant only for SDIO). [Fix endianess issues; simplify sdio-specific block_size handling; minor changes in comments; use "aligned_len" in one calculation instead of "pad" to avoid confusion -- Luca] Signed-off-by: Shahar Levi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 26 +++++++++++++++ drivers/net/wireless/wl12xx/acx.h | 11 +++++++ drivers/net/wireless/wl12xx/init.c | 27 +++++++++++++++ drivers/net/wireless/wl12xx/init.h | 1 + drivers/net/wireless/wl12xx/io.c | 10 ++++++ drivers/net/wireless/wl12xx/io.h | 1 + drivers/net/wireless/wl12xx/main.c | 7 ++++ drivers/net/wireless/wl12xx/tx.c | 64 +++++++++++++++++++++++++----------- drivers/net/wireless/wl12xx/tx.h | 46 +++++++++++++++++++++----- drivers/net/wireless/wl12xx/wl12xx.h | 3 ++ 10 files changed, 168 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index a3db755ceeda..50676b36ad26 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -1019,6 +1019,32 @@ out: return ret; } +int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap) +{ + struct wl1271_acx_host_config_bitmap *bitmap_conf; + int ret; + + bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL); + if (!bitmap_conf) { + ret = -ENOMEM; + goto out; + } + + bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap); + + ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP, + bitmap_conf, sizeof(*bitmap_conf)); + if (ret < 0) { + wl1271_warning("wl1271 bitmap config opt failed: %d", ret); + goto out; + } + +out: + kfree(bitmap_conf); + + return ret; +} + int wl1271_acx_init_mem_config(struct wl1271 *wl) { int ret; diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index dd19b01d807b..0a40caeab2a2 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -939,6 +939,16 @@ struct wl1271_acx_keep_alive_config { u8 padding; } __packed; +#define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0) +#define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1) +#define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3) + +struct wl1271_acx_host_config_bitmap { + struct acx_header header; + + __le32 host_cfg_bitmap; +} __packed; + enum { WL1271_ACX_TRIG_TYPE_LEVEL = 0, WL1271_ACX_TRIG_TYPE_EDGE, @@ -1275,6 +1285,7 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl); int wl1271_acx_ap_mem_cfg(struct wl1271 *wl); int wl1271_acx_sta_mem_cfg(struct wl1271 *wl); int wl1271_acx_init_mem_config(struct wl1271 *wl); +int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); int wl1271_acx_smart_reflex(struct wl1271 *wl); int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 6072fe457135..34c41084bcf1 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -31,6 +31,7 @@ #include "cmd.h" #include "reg.h" #include "tx.h" +#include "io.h" int wl1271_sta_init_templates_config(struct wl1271 *wl) { @@ -504,6 +505,27 @@ static int wl1271_set_ba_policies(struct wl1271 *wl) return ret; } +int wl1271_chip_specific_init(struct wl1271 *wl) +{ + int ret = 0; + + if (wl->chip.id == CHIP_ID_1283_PG20) { + u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; + + if (wl1271_set_block_size(wl)) + /* Enable SDIO padding */ + host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK; + + /* Must be before wl1271_acx_init_mem_config() */ + ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap); + if (ret < 0) + goto out; + } +out: + return ret; +} + + int wl1271_hw_init(struct wl1271 *wl) { struct conf_tx_ac_category *conf_ac; @@ -519,6 +541,11 @@ int wl1271_hw_init(struct wl1271 *wl) if (ret < 0) return ret; + /* Chip-specific init */ + ret = wl1271_chip_specific_init(wl); + if (ret < 0) + return ret; + /* Mode specific init */ if (is_ap) ret = wl1271_ap_hw_init(wl); diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h index 3a8bd3f426d2..4975270a91ab 100644 --- a/drivers/net/wireless/wl12xx/init.h +++ b/drivers/net/wireless/wl12xx/init.h @@ -31,6 +31,7 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl); int wl1271_init_phy_config(struct wl1271 *wl); int wl1271_init_pta(struct wl1271 *wl); int wl1271_init_energy_detection(struct wl1271 *wl); +int wl1271_chip_specific_init(struct wl1271 *wl); int wl1271_hw_init(struct wl1271 *wl); #endif diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c index d557f73e7c19..aa40c98e8fd3 100644 --- a/drivers/net/wireless/wl12xx/io.c +++ b/drivers/net/wireless/wl12xx/io.c @@ -43,6 +43,16 @@ #define OCP_STATUS_REQ_FAILED 0x20000 #define OCP_STATUS_RESP_ERROR 0x30000 +bool wl1271_set_block_size(struct wl1271 *wl) +{ + if (wl->if_ops->set_block_size) { + wl->if_ops->set_block_size(wl); + return true; + } + + return false; +} + void wl1271_disable_interrupts(struct wl1271 *wl) { wl->if_ops->disable_irq(wl); diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h index c1aac8292089..84454f6d8169 100644 --- a/drivers/net/wireless/wl12xx/io.h +++ b/drivers/net/wireless/wl12xx/io.h @@ -169,5 +169,6 @@ int wl1271_init_ieee80211(struct wl1271 *wl); struct ieee80211_hw *wl1271_alloc_hw(void); int wl1271_free_hw(struct wl1271 *wl); irqreturn_t wl1271_irq(int irq, void *data); +bool wl1271_set_block_size(struct wl1271 *wl); #endif diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index b0c49352b56f..f24906f54a71 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -450,6 +450,11 @@ static int wl1271_plt_init(struct wl1271 *wl) if (ret < 0) return ret; + /* Chip-specific initializations */ + ret = wl1271_chip_specific_init(wl); + if (ret < 0) + return ret; + ret = wl1271_sta_init_templates_config(wl); if (ret < 0) return ret; @@ -1335,6 +1340,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); wl->ap_fw_ps_map = 0; wl->ap_ps_map = 0; + wl->block_size = 0; for (i = 0; i < NUM_TX_QUEUES; i++) wl->tx_blocks_freed[i] = 0; @@ -3458,6 +3464,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->ap_ps_map = 0; wl->ap_fw_ps_map = 0; wl->quirks = 0; + wl->block_size = 0; memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); for (i = 0; i < ACX_TX_DESCRIPTORS; i++) diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 5e9ef7d53e7e..e296f0a5fe27 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -132,6 +132,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, { struct wl1271_tx_hw_descr *desc; u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; + u32 len; u32 total_blocks; int id, ret = -EBUSY; @@ -145,14 +146,20 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, /* approximate the number of blocks required for this packet in the firmware */ - total_blocks = total_len + TX_HW_BLOCK_SIZE - 1; - total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE; + if (wl->block_size) + len = ALIGN(total_len, wl->block_size); + else + len = total_len; + + total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE + + TX_HW_BLOCK_SPARE; + if (total_blocks <= wl->tx_blocks_available) { desc = (struct wl1271_tx_hw_descr *)skb_push( skb, total_len - skb->len); - desc->extra_mem_blocks = TX_HW_BLOCK_SPARE; - desc->total_mem_blocks = total_blocks; + desc->wl127x_mem.extra_blocks = TX_HW_BLOCK_SPARE; + desc->wl127x_mem.total_mem_blocks = total_blocks; desc->id = id; wl->tx_blocks_available -= total_blocks; @@ -178,7 +185,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, { struct timespec ts; struct wl1271_tx_hw_descr *desc; - int pad, ac, rate_idx; + int aligned_len, ac, rate_idx; s64 hosttime; u16 tx_attr; @@ -237,20 +244,32 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY; desc->reserved = 0; - /* align the length (and store in terms of words) */ - pad = ALIGN(skb->len, WL1271_TX_ALIGN_TO); - desc->length = cpu_to_le16(pad >> 2); + if (wl->block_size) { + aligned_len = ALIGN(skb->len, wl->block_size); + + desc->wl128x_mem.extra_bytes = aligned_len - skb->len; + desc->length = cpu_to_le16(aligned_len >> 2); + } else { + int pad; + + /* align the length (and store in terms of words) */ + aligned_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO); + desc->length = cpu_to_le16(aligned_len >> 2); + + /* calculate number of padding bytes */ + pad = aligned_len - skb->len; + tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; - /* calculate number of padding bytes */ - pad = pad - skb->len; - tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; + wl1271_debug(DEBUG_TX, "tx_fill_hdr: padding: %d", pad); + } desc->tx_attr = cpu_to_le16(tx_attr); - wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d " - "tx_attr: 0x%x len: %d life: %d mem: %d", pad, desc->hlid, - le16_to_cpu(desc->tx_attr), le16_to_cpu(desc->length), - le16_to_cpu(desc->life_time), desc->total_mem_blocks); + wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d tx_attr: 0x%x " + "len: %d life: %d mem: %d", + desc->hlid, le16_to_cpu(desc->tx_attr), + le16_to_cpu(desc->length), le16_to_cpu(desc->life_time), + desc->wl127x_mem.total_mem_blocks); } /* caller must hold wl->mutex */ @@ -305,11 +324,18 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, wl1271_tx_fill_hdr(wl, skb, extra, info, hlid); /* - * The length of each packet is stored in terms of words. Thus, we must - * pad the skb data to make sure its length is aligned. - * The number of padding bytes is computed and set in wl1271_tx_fill_hdr + * The length of each packet is stored in terms of + * words. Thus, we must pad the skb data to make sure its + * length is aligned. The number of padding bytes is computed + * and set in wl1271_tx_fill_hdr. + * In special cases, we want to align to a specific block size + * (eg. for wl128x with SDIO we align to 256). */ - total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO); + if (wl->block_size) + total_len = ALIGN(skb->len, wl->block_size); + else + total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO); + memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len); memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len); diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index 02f07fa66e82..e31317717ab2 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -55,20 +55,48 @@ #define WL1271_TX_ALIGN_TO 4 #define WL1271_TKIP_IV_SPACE 4 +struct wl127x_tx_mem { + /* + * Number of extra memory blocks to allocate for this packet + * in addition to the number of blocks derived from the packet + * length. + */ + u8 extra_blocks; + /* + * Total number of memory blocks allocated by the host for + * this packet. Must be equal or greater than the actual + * blocks number allocated by HW. + */ + u8 total_mem_blocks; +} __packed; + +struct wl128x_tx_mem { + /* + * Total number of memory blocks allocated by the host for + * this packet. + */ + u8 total_mem_blocks; + /* + * Number of extra bytes, at the end of the frame. the host + * uses this padding to complete each frame to integer number + * of SDIO blocks. + */ + u8 extra_bytes; +} __packed; + struct wl1271_tx_hw_descr { /* Length of packet in words, including descriptor+header+data */ __le16 length; - /* Number of extra memory blocks to allocate for this packet in - addition to the number of blocks derived from the packet length */ - u8 extra_mem_blocks; - /* Total number of memory blocks allocated by the host for this packet. - Must be equal or greater than the actual blocks number allocated by - HW!! */ - u8 total_mem_blocks; + union { + struct wl127x_tx_mem wl127x_mem; + struct wl128x_tx_mem wl128x_mem; + } __packed; /* Device time (in us) when the packet arrived to the driver */ __le32 start_time; - /* Max delay in TUs until transmission. The last device time the - packet can be transmitted is: startTime+(1024*LifeTime) */ + /* + * Max delay in TUs until transmission. The last device time the + * packet can be transmitted is: start_time + (1024 * life_time) + */ __le16 life_time; /* Bitwise fields - see TX_ATTR... definitions above. */ __le16 tx_attr; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index a2e899d4e1aa..959b338d0af4 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -303,6 +303,7 @@ struct wl1271_if_operations { struct device* (*dev)(struct wl1271 *wl); void (*enable_irq)(struct wl1271 *wl); void (*disable_irq)(struct wl1271 *wl); + void (*set_block_size) (struct wl1271 *wl); }; #define MAX_NUM_KEYS 14 @@ -533,6 +534,8 @@ struct wl1271 { bool ba_support; u8 ba_rx_bitmap; + u32 block_size; + /* * AP-mode - links indexed by HLID. The global and broadcast links * are always active. -- cgit v1.2.3-58-ga151 From a81159edf8d64011933df177ec42f82d7896a0c7 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Mon, 14 Mar 2011 14:05:13 +0200 Subject: wl12xx: 1281/1283 support - add block size handling for sdio and spi Add the the set_block_size op in the SDIO and in the SPI modules. Since it is only used with SDIO, just explicitly set the op to NULL in spi.c Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/sdio.c | 18 +++++++++++++++++- drivers/net/wireless/wl12xx/spi.c | 3 ++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 1b6a1adb81af..7491b3d8487a 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -51,6 +51,18 @@ static const struct sdio_device_id wl1271_devices[] = { }; MODULE_DEVICE_TABLE(sdio, wl1271_devices); +/* The max SDIO block size is 256 when working with tx padding to SDIO block */ +#define TX_PAD_SDIO_BLK_SIZE 256 + +static void wl1271_sdio_set_block_size(struct wl1271 *wl) +{ + wl->block_size = TX_PAD_SDIO_BLK_SIZE; + + sdio_claim_host(wl->if_priv); + sdio_set_block_size(wl->if_priv, TX_PAD_SDIO_BLK_SIZE); + sdio_release_host(wl->if_priv); +} + static inline struct sdio_func *wl_to_func(struct wl1271 *wl) { return wl->if_priv; @@ -166,6 +178,9 @@ static int wl1271_sdio_power_on(struct wl1271 *wl) sdio_claim_host(func); sdio_enable_func(func); + /* Set the default block size in case it was modified */ + sdio_set_block_size(func, 0); + out: return ret; } @@ -203,7 +218,8 @@ static struct wl1271_if_operations sdio_ops = { .power = wl1271_sdio_set_power, .dev = wl1271_sdio_wl_to_dev, .enable_irq = wl1271_sdio_enable_interrupts, - .disable_irq = wl1271_sdio_disable_interrupts + .disable_irq = wl1271_sdio_disable_interrupts, + .set_block_size = wl1271_sdio_set_block_size, }; static int __devinit wl1271_probe(struct sdio_func *func, diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 80295f55f23f..bfb1171176ca 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -355,7 +355,8 @@ static struct wl1271_if_operations spi_ops = { .power = wl1271_spi_set_power, .dev = wl1271_spi_wl_to_dev, .enable_irq = wl1271_spi_enable_interrupts, - .disable_irq = wl1271_spi_disable_interrupts + .disable_irq = wl1271_spi_disable_interrupts, + .set_block_size = NULL, }; static int __devinit wl1271_probe(struct spi_device *spi) -- cgit v1.2.3-58-ga151 From 49d750ca14cd49e76ab039b33b5a621e0a92b9fd Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 6 Mar 2011 16:32:09 +0200 Subject: wl12xx: 1281/1283 support - New radio structs and functions New general and radio parameters structures and functions. Implemented as separate functions due to auto-detection between wl127x and wl128x. Signed-off-by: Shahar Levi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 86 +++++++++++++++++++++++++++++++++- drivers/net/wireless/wl12xx/cmd.h | 34 ++++++++++++++ drivers/net/wireless/wl12xx/ini.h | 96 +++++++++++++++++++++++++++++++++++++- drivers/net/wireless/wl12xx/init.c | 18 +++++-- drivers/net/wireless/wl12xx/main.c | 16 +++++-- 5 files changed, 240 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index f0aa7ab97bf7..37eb9f366942 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -110,7 +110,47 @@ out: int wl1271_cmd_general_parms(struct wl1271 *wl) { struct wl1271_general_parms_cmd *gen_parms; - struct wl1271_ini_general_params *gp = &wl->nvs->general_params; + struct wl1271_ini_general_params *gp = + &((struct wl1271_nvs_file *)wl->nvs)->general_params; + bool answer = false; + int ret; + + if (!wl->nvs) + return -ENODEV; + + gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); + if (!gen_parms) + return -ENOMEM; + + gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; + + memcpy(&gen_parms->general_params, gp, sizeof(*gp)); + + if (gp->tx_bip_fem_auto_detect) + answer = true; + + ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); + if (ret < 0) { + wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); + goto out; + } + + gp->tx_bip_fem_manufacturer = + gen_parms->general_params.tx_bip_fem_manufacturer; + + wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", + answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); + +out: + kfree(gen_parms); + return ret; +} + +int wl128x_cmd_general_parms(struct wl1271 *wl) +{ + struct wl128x_general_parms_cmd *gen_parms; + struct wl128x_ini_general_params *gp = + &((struct wl128x_nvs_file *)wl->nvs)->general_params; bool answer = false; int ret; @@ -186,6 +226,50 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) return ret; } +int wl128x_cmd_radio_parms(struct wl1271 *wl) +{ + struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; + struct wl128x_radio_parms_cmd *radio_parms; + struct wl128x_ini_general_params *gp = &nvs->general_params; + int ret; + + if (!wl->nvs) + return -ENODEV; + + radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); + if (!radio_parms) + return -ENOMEM; + + radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; + + /* 2.4GHz parameters */ + memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, + sizeof(struct wl128x_ini_band_params_2)); + memcpy(&radio_parms->dyn_params_2, + &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, + sizeof(struct wl128x_ini_fem_params_2)); + + /* 5GHz parameters */ + memcpy(&radio_parms->static_params_5, + &nvs->stat_radio_params_5, + sizeof(struct wl128x_ini_band_params_5)); + memcpy(&radio_parms->dyn_params_5, + &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, + sizeof(struct wl128x_ini_fem_params_5)); + + radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; + + wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", + radio_parms, sizeof(*radio_parms)); + + ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); + if (ret < 0) + wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); + + kfree(radio_parms); + return ret; +} + int wl1271_cmd_ext_radio_parms(struct wl1271 *wl) { struct wl1271_ext_radio_parms_cmd *ext_radio_parms; diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 54c12e71417e..5cac95d9480c 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -32,7 +32,9 @@ struct acx_header; int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, size_t res_len); int wl1271_cmd_general_parms(struct wl1271 *wl); +int wl128x_cmd_general_parms(struct wl1271 *wl); int wl1271_cmd_radio_parms(struct wl1271 *wl); +int wl128x_cmd_radio_parms(struct wl1271 *wl); int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); @@ -415,6 +417,21 @@ struct wl1271_general_parms_cmd { u8 padding[3]; } __packed; +struct wl128x_general_parms_cmd { + struct wl1271_cmd_header header; + + struct wl1271_cmd_test_header test; + + struct wl128x_ini_general_params general_params; + + u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM]; + u8 sr_sen_n_p; + u8 sr_sen_n_p_gain; + u8 sr_sen_nrn; + u8 sr_sen_prn; + u8 padding[3]; +} __packed; + struct wl1271_radio_parms_cmd { struct wl1271_cmd_header header; @@ -431,6 +448,23 @@ struct wl1271_radio_parms_cmd { u8 padding3[2]; } __packed; +struct wl128x_radio_parms_cmd { + struct wl1271_cmd_header header; + + struct wl1271_cmd_test_header test; + + /* Static radio parameters */ + struct wl128x_ini_band_params_2 static_params_2; + struct wl128x_ini_band_params_5 static_params_5; + + u8 fem_vendor_and_options; + + /* Dynamic radio parameters */ + struct wl128x_ini_fem_params_2 dyn_params_2; + u8 padding2; + struct wl128x_ini_fem_params_5 dyn_params_5; +} __packed; + struct wl1271_ext_radio_parms_cmd { struct wl1271_cmd_header header; diff --git a/drivers/net/wireless/wl12xx/ini.h b/drivers/net/wireless/wl12xx/ini.h index c330a2583dfd..30efcd6643b1 100644 --- a/drivers/net/wireless/wl12xx/ini.h +++ b/drivers/net/wireless/wl12xx/ini.h @@ -41,6 +41,28 @@ struct wl1271_ini_general_params { u8 srf3[WL1271_INI_MAX_SMART_REFLEX_PARAM]; } __packed; +#define WL128X_INI_MAX_SETTINGS_PARAM 4 + +struct wl128x_ini_general_params { + u8 ref_clock; + u8 settling_time; + u8 clk_valid_on_wakeup; + u8 tcxo_ref_clock; + u8 tcxo_settling_time; + u8 tcxo_valid_on_wakeup; + u8 tcxo_ldo_voltage; + u8 xtal_itrim_val; + u8 platform_conf; + u8 dual_mode_select; + u8 tx_bip_fem_auto_detect; + u8 tx_bip_fem_manufacturer; + u8 general_settings[WL128X_INI_MAX_SETTINGS_PARAM]; + u8 sr_state; + u8 srf1[WL1271_INI_MAX_SMART_REFLEX_PARAM]; + u8 srf2[WL1271_INI_MAX_SMART_REFLEX_PARAM]; + u8 srf3[WL1271_INI_MAX_SMART_REFLEX_PARAM]; +} __packed; + #define WL1271_INI_RSSI_PROCESS_COMPENS_SIZE 15 struct wl1271_ini_band_params_2 { @@ -49,9 +71,16 @@ struct wl1271_ini_band_params_2 { u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; } __packed; -#define WL1271_INI_RATE_GROUP_COUNT 6 #define WL1271_INI_CHANNEL_COUNT_2 14 +struct wl128x_ini_band_params_2 { + u8 rx_trace_insertion_loss; + u8 tx_trace_loss[WL1271_INI_CHANNEL_COUNT_2]; + u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; +} __packed; + +#define WL1271_INI_RATE_GROUP_COUNT 6 + struct wl1271_ini_fem_params_2 { __le16 tx_bip_ref_pd_voltage; u8 tx_bip_ref_power; @@ -68,6 +97,28 @@ struct wl1271_ini_fem_params_2 { u8 normal_to_degraded_high_thr; } __packed; +#define WL128X_INI_RATE_GROUP_COUNT 7 +/* low and high temperatures */ +#define WL128X_INI_PD_VS_TEMPERATURE_RANGES 2 + +struct wl128x_ini_fem_params_2 { + __le16 tx_bip_ref_pd_voltage; + u8 tx_bip_ref_power; + u8 tx_bip_ref_offset; + u8 tx_per_rate_pwr_limits_normal[WL128X_INI_RATE_GROUP_COUNT]; + u8 tx_per_rate_pwr_limits_degraded[WL128X_INI_RATE_GROUP_COUNT]; + u8 tx_per_rate_pwr_limits_extreme[WL128X_INI_RATE_GROUP_COUNT]; + u8 tx_per_chan_pwr_limits_11b[WL1271_INI_CHANNEL_COUNT_2]; + u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_2]; + u8 tx_pd_vs_rate_offsets[WL128X_INI_RATE_GROUP_COUNT]; + u8 tx_ibias[WL128X_INI_RATE_GROUP_COUNT + 1]; + u8 tx_pd_vs_chan_offsets[WL1271_INI_CHANNEL_COUNT_2]; + u8 tx_pd_vs_temperature[WL128X_INI_PD_VS_TEMPERATURE_RANGES]; + u8 rx_fem_insertion_loss; + u8 degraded_low_to_normal_thr; + u8 normal_to_degraded_high_thr; +} __packed; + #define WL1271_INI_CHANNEL_COUNT_5 35 #define WL1271_INI_SUB_BAND_COUNT_5 7 @@ -77,6 +128,12 @@ struct wl1271_ini_band_params_5 { u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; } __packed; +struct wl128x_ini_band_params_5 { + u8 rx_trace_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5]; + u8 tx_trace_loss[WL1271_INI_CHANNEL_COUNT_5]; + u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; +} __packed; + struct wl1271_ini_fem_params_5 { __le16 tx_bip_ref_pd_voltage[WL1271_INI_SUB_BAND_COUNT_5]; u8 tx_bip_ref_power[WL1271_INI_SUB_BAND_COUNT_5]; @@ -92,6 +149,23 @@ struct wl1271_ini_fem_params_5 { u8 normal_to_degraded_high_thr; } __packed; +struct wl128x_ini_fem_params_5 { + __le16 tx_bip_ref_pd_voltage[WL1271_INI_SUB_BAND_COUNT_5]; + u8 tx_bip_ref_power[WL1271_INI_SUB_BAND_COUNT_5]; + u8 tx_bip_ref_offset[WL1271_INI_SUB_BAND_COUNT_5]; + u8 tx_per_rate_pwr_limits_normal[WL128X_INI_RATE_GROUP_COUNT]; + u8 tx_per_rate_pwr_limits_degraded[WL128X_INI_RATE_GROUP_COUNT]; + u8 tx_per_rate_pwr_limits_extreme[WL128X_INI_RATE_GROUP_COUNT]; + u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_5]; + u8 tx_pd_vs_rate_offsets[WL128X_INI_RATE_GROUP_COUNT]; + u8 tx_ibias[WL128X_INI_RATE_GROUP_COUNT]; + u8 tx_pd_vs_chan_offsets[WL1271_INI_CHANNEL_COUNT_5]; + u8 tx_pd_vs_temperature[WL1271_INI_SUB_BAND_COUNT_5 * + WL128X_INI_PD_VS_TEMPERATURE_RANGES]; + u8 rx_fem_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5]; + u8 degraded_low_to_normal_thr; + u8 normal_to_degraded_high_thr; +} __packed; /* NVS data structure */ #define WL1271_INI_NVS_SECTION_SIZE 468 @@ -120,4 +194,24 @@ struct wl1271_nvs_file { } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT]; } __packed; +struct wl128x_nvs_file { + /* NVS section */ + u8 nvs[WL1271_INI_NVS_SECTION_SIZE]; + + /* INI section */ + struct wl128x_ini_general_params general_params; + u8 fem_vendor_and_options; + struct wl128x_ini_band_params_2 stat_radio_params_2; + u8 padding2; + struct { + struct wl128x_ini_fem_params_2 params; + u8 padding; + } dyn_radio_params_2[WL1271_INI_FEM_MODULE_COUNT]; + struct wl128x_ini_band_params_5 stat_radio_params_5; + u8 padding3; + struct { + struct wl128x_ini_fem_params_5 params; + u8 padding; + } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT]; +} __packed; #endif diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 34c41084bcf1..2dbc08331ca9 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -322,9 +322,11 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) { int ret; - ret = wl1271_cmd_ext_radio_parms(wl); - if (ret < 0) - return ret; + if (wl->chip.id != CHIP_ID_1283_PG20) { + ret = wl1271_cmd_ext_radio_parms(wl); + if (ret < 0) + return ret; + } /* PS config */ ret = wl1271_acx_config_ps(wl); @@ -533,11 +535,17 @@ int wl1271_hw_init(struct wl1271 *wl) int ret, i; bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); - ret = wl1271_cmd_general_parms(wl); + if (wl->chip.id == CHIP_ID_1283_PG20) + ret = wl128x_cmd_general_parms(wl); + else + ret = wl1271_cmd_general_parms(wl); if (ret < 0) return ret; - ret = wl1271_cmd_radio_parms(wl); + if (wl->chip.id == CHIP_ID_1283_PG20) + ret = wl128x_cmd_radio_parms(wl); + else + ret = wl1271_cmd_radio_parms(wl); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index f24906f54a71..e1fd005dd048 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -438,15 +438,25 @@ static int wl1271_plt_init(struct wl1271 *wl) struct conf_tx_tid *conf_tid; int ret, i; - ret = wl1271_cmd_general_parms(wl); + if (wl->chip.id == CHIP_ID_1283_PG20) + ret = wl128x_cmd_general_parms(wl); + else + ret = wl1271_cmd_general_parms(wl); if (ret < 0) return ret; - ret = wl1271_cmd_radio_parms(wl); + if (wl->chip.id == CHIP_ID_1283_PG20) + ret = wl128x_cmd_radio_parms(wl); + else + ret = wl1271_cmd_radio_parms(wl); if (ret < 0) return ret; - ret = wl1271_cmd_ext_radio_parms(wl); + if (wl->chip.id != CHIP_ID_1283_PG20) { + ret = wl1271_cmd_ext_radio_parms(wl); + if (ret < 0) + return ret; + } if (ret < 0) return ret; -- cgit v1.2.3-58-ga151 From bc765bf3b9a095b3e41c8cda80643901884c3dd4 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 6 Mar 2011 16:32:10 +0200 Subject: wl12xx: 1281/1283 support - Loading FW & NVS Take care of FW & NVS with the auto-detection between wl127x and wl128x. [Moved some common code outside if statements and added notes about NVS structure assumptions; Fixed a bug when checking the nvs size: if the size was incorrect, the local nvs variable was set to NULL, it should be wl->nvs instead. -- Luca] [Merged with potential buffer overflow fix -- Luca] Signed-off-by: Shahar Levi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/boot.c | 83 ++++++++++++++++++++++----------- drivers/net/wireless/wl12xx/cmd.c | 11 +++-- drivers/net/wireless/wl12xx/ini.h | 4 +- drivers/net/wireless/wl12xx/main.c | 13 ++++-- drivers/net/wireless/wl12xx/sdio_test.c | 9 +++- drivers/net/wireless/wl12xx/testmode.c | 6 ++- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 7 files changed, 86 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 69fe8703be42..38f3e8ba2628 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -243,33 +243,57 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) if (wl->nvs == NULL) return -ENODEV; - /* - * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band - * configurations) can be removed when those NVS files stop floating - * around. - */ - if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || - wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { - /* for now 11a is unsupported in AP mode */ - if (wl->bss_type != BSS_TYPE_AP_BSS && - wl->nvs->general_params.dual_mode_select) - wl->enable_11a = true; - } + if (wl->chip.id == CHIP_ID_1283_PG20) { + struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; + + if (wl->nvs_len == sizeof(struct wl128x_nvs_file)) { + if (nvs->general_params.dual_mode_select) + wl->enable_11a = true; + } else { + wl1271_error("nvs size is not as expected: %zu != %zu", + wl->nvs_len, + sizeof(struct wl128x_nvs_file)); + kfree(wl->nvs); + wl->nvs = NULL; + wl->nvs_len = 0; + return -EILSEQ; + } - if (wl->nvs_len != sizeof(struct wl1271_nvs_file) && - (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE || - wl->enable_11a)) { - wl1271_error("nvs size is not as expected: %zu != %zu", - wl->nvs_len, sizeof(struct wl1271_nvs_file)); - kfree(wl->nvs); - wl->nvs = NULL; - wl->nvs_len = 0; - return -EILSEQ; - } + /* only the first part of the NVS needs to be uploaded */ + nvs_len = sizeof(nvs->nvs); + nvs_ptr = (u8 *)nvs->nvs; - /* only the first part of the NVS needs to be uploaded */ - nvs_len = sizeof(wl->nvs->nvs); - nvs_ptr = (u8 *)wl->nvs->nvs; + } else { + struct wl1271_nvs_file *nvs = + (struct wl1271_nvs_file *)wl->nvs; + /* + * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz + * band configurations) can be removed when those NVS files stop + * floating around. + */ + if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || + wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { + /* for now 11a is unsupported in AP mode */ + if (wl->bss_type != BSS_TYPE_AP_BSS && + nvs->general_params.dual_mode_select) + wl->enable_11a = true; + } + + if (wl->nvs_len != sizeof(struct wl1271_nvs_file) && + (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE || + wl->enable_11a)) { + wl1271_error("nvs size is not as expected: %zu != %zu", + wl->nvs_len, sizeof(struct wl1271_nvs_file)); + kfree(wl->nvs); + wl->nvs = NULL; + wl->nvs_len = 0; + return -EILSEQ; + } + + /* only the first part of the NVS needs to be uploaded */ + nvs_len = sizeof(nvs->nvs); + nvs_ptr = (u8 *) nvs->nvs; + } /* update current MAC address to NVS */ nvs_ptr[11] = wl->mac_addr[0]; @@ -319,10 +343,13 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) /* * We've reached the first zero length, the first NVS table * is located at an aligned offset which is at least 7 bytes further. + * NOTE: The wl->nvs->nvs element must be first, in order to + * simplify the casting, we assume it is at the beginning of + * the wl->nvs structure. */ - nvs_ptr = (u8 *)wl->nvs->nvs + - ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4); - nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs; + nvs_ptr = (u8 *)wl->nvs + + ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4); + nvs_len -= nvs_ptr - (u8 *)wl->nvs; /* Now we must set the partition correctly */ wl1271_set_partition(wl, &part_table[PART_WORK]); diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 37eb9f366942..246804428517 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -187,8 +187,9 @@ out: int wl1271_cmd_radio_parms(struct wl1271 *wl) { + struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; struct wl1271_radio_parms_cmd *radio_parms; - struct wl1271_ini_general_params *gp = &wl->nvs->general_params; + struct wl1271_ini_general_params *gp = &nvs->general_params; int ret; if (!wl->nvs) @@ -201,18 +202,18 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; /* 2.4GHz parameters */ - memcpy(&radio_parms->static_params_2, &wl->nvs->stat_radio_params_2, + memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, sizeof(struct wl1271_ini_band_params_2)); memcpy(&radio_parms->dyn_params_2, - &wl->nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, + &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, sizeof(struct wl1271_ini_fem_params_2)); /* 5GHz parameters */ memcpy(&radio_parms->static_params_5, - &wl->nvs->stat_radio_params_5, + &nvs->stat_radio_params_5, sizeof(struct wl1271_ini_band_params_5)); memcpy(&radio_parms->dyn_params_5, - &wl->nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, + &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, sizeof(struct wl1271_ini_fem_params_5)); wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", diff --git a/drivers/net/wireless/wl12xx/ini.h b/drivers/net/wireless/wl12xx/ini.h index 30efcd6643b1..1420c842b8f1 100644 --- a/drivers/net/wireless/wl12xx/ini.h +++ b/drivers/net/wireless/wl12xx/ini.h @@ -174,7 +174,7 @@ struct wl128x_ini_fem_params_5 { #define WL1271_INI_LEGACY_NVS_FILE_SIZE 800 struct wl1271_nvs_file { - /* NVS section */ + /* NVS section - must be first! */ u8 nvs[WL1271_INI_NVS_SECTION_SIZE]; /* INI section */ @@ -195,7 +195,7 @@ struct wl1271_nvs_file { } __packed; struct wl128x_nvs_file { - /* NVS section */ + /* NVS section - must be first! */ u8 nvs[WL1271_INI_NVS_SECTION_SIZE]; /* INI section */ diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index e1fd005dd048..fe0cf47a656c 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -804,7 +804,10 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) break; case BSS_TYPE_IBSS: case BSS_TYPE_STA_BSS: - fw_name = WL1271_FW_NAME; + if (wl->chip.id == CHIP_ID_1283_PG20) + fw_name = WL128X_FW_NAME; + else + fw_name = WL1271_FW_NAME; break; default: wl1271_error("no compatible firmware for bss_type %d", @@ -860,7 +863,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) return ret; } - wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); + wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); if (!wl->nvs) { wl1271_error("could not allocate memory for the nvs file"); @@ -3289,7 +3292,11 @@ int wl1271_register_hw(struct wl1271 *wl) ret = wl1271_fetch_nvs(wl); if (ret == 0) { - u8 *nvs_ptr = (u8 *)wl->nvs->nvs; + /* NOTE: The wl->nvs->nvs element must be first, in + * order to simplify the casting, we assume it is at + * the beginning of the wl->nvs structure. + */ + u8 *nvs_ptr = (u8 *)wl->nvs; wl->mac_addr[0] = nvs_ptr[11]; wl->mac_addr[1] = nvs_ptr[10]; diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c index 01adf1b1003b..e6e2ad63a1c1 100644 --- a/drivers/net/wireless/wl12xx/sdio_test.c +++ b/drivers/net/wireless/wl12xx/sdio_test.c @@ -189,7 +189,12 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) const struct firmware *fw; int ret; - ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); + if (wl->chip.id == CHIP_ID_1283_PG20) + ret = request_firmware(&fw, WL128X_FW_NAME, + wl1271_wl_to_dev(wl)); + else + ret = request_firmware(&fw, WL1271_FW_NAME, + wl1271_wl_to_dev(wl)); if (ret < 0) { wl1271_error("could not get firmware: %d", ret); @@ -234,7 +239,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) return ret; } - wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); + wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); if (!wl->nvs) { wl1271_error("could not allocate memory for the nvs file"); diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index 6ec06a4a4c6d..da351d7cd1f2 100644 --- a/drivers/net/wireless/wl12xx/testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c @@ -27,6 +27,7 @@ #include "wl12xx.h" #include "acx.h" +#include "reg.h" #define WL1271_TM_MAX_DATA_LENGTH 1024 @@ -204,7 +205,10 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) kfree(wl->nvs); - if (len != sizeof(struct wl1271_nvs_file)) + if ((wl->chip.id == CHIP_ID_1283_PG20) && + (len != sizeof(struct wl128x_nvs_file))) + return -EINVAL; + else if (len != sizeof(struct wl1271_nvs_file)) return -EINVAL; wl->nvs = kzalloc(len, GFP_KERNEL); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 959b338d0af4..e59f5392e909 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -378,7 +378,7 @@ struct wl1271 { u8 *fw; size_t fw_len; u8 fw_bss_type; - struct wl1271_nvs_file *nvs; + void *nvs; size_t nvs_len; s8 hw_pg_ver; -- cgit v1.2.3-58-ga151 From 5ea417ae7749076ddaacb5b36487cae6ac920413 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 6 Mar 2011 16:32:11 +0200 Subject: wl12xx: 1281/1283 support - New boot sequence Boot sequence support FREF clock and TCXO clock. WL128x has two clocks input - TCXO and FREF. TCXO is the main clock of the device, while FREF is used to sync between the GPS and the cellular modem. Auto-detection checks where TCXO is 32.736MHz or 16.368MHz, in that case the FREF will be used as the WLAN/BT main clock. [Use clock enumeration as defined in linux/wl12xx.h; remove unnecessary else block in wl128x_switch_fref; remove unnecessary change in main.c; remove some unnecessary debug prints and comments; fix potential use of uninitialized value (pll_config) -- Luca] Signed-off-by: Shahar Levi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/boot.c | 183 ++++++++++++++++++++++++++++++-- drivers/net/wireless/wl12xx/sdio.c | 1 + drivers/net/wireless/wl12xx/sdio_test.c | 1 + drivers/net/wireless/wl12xx/spi.c | 1 + drivers/net/wireless/wl12xx/wl12xx.h | 1 + 5 files changed, 179 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 38f3e8ba2628..9d742c1e75a9 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -22,6 +22,7 @@ */ #include +#include #include "acx.h" #include "reg.h" @@ -520,24 +521,159 @@ static void wl1271_boot_hw_version(struct wl1271 *wl) wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; } -/* uploads NVS and firmware */ -int wl1271_load_firmware(struct wl1271 *wl) +/* + * WL128x has two clocks input - TCXO and FREF. + * TCXO is the main clock of the device, while FREF is used to sync + * between the GPS and the cellular modem. + * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used + * as the WLAN/BT main clock. + */ +static int wl128x_switch_fref(struct wl1271 *wl, bool *is_ref_clk) { - int ret = 0; - u32 tmp, clk, pause; + u16 sys_clk_cfg_val; + + /* if working on XTAL-only mode go directly to TCXO TO FREF SWITCH */ + if ((wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) || + (wl->ref_clock == CONF_REF_CLK_26_M_XTAL)) + return true; + + /* Read clock source FREF or TCXO */ + sys_clk_cfg_val = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG); + + if (sys_clk_cfg_val & PRCM_CM_EN_MUX_WLAN_FREF) { + /* if bit 3 is set - working with FREF clock */ + wl1271_debug(DEBUG_BOOT, "working with FREF clock, skip" + " to FREF"); + + *is_ref_clk = true; + } else { + /* if bit 3 is clear - working with TCXO clock */ + wl1271_debug(DEBUG_BOOT, "working with TCXO clock"); + + /* TCXO to FREF switch, check TXCO clock config */ + if ((wl->tcxo_clock != WL12XX_TCXOCLOCK_16_368) && + (wl->tcxo_clock != WL12XX_TCXOCLOCK_32_736)) { + /* + * not 16.368Mhz and not 32.736Mhz - skip to + * configure ELP stage + */ + wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:" + " TcxoRefClk=%d - not 16.368Mhz and not" + " 32.736Mhz - skip to configure ELP" + " stage", wl->tcxo_clock); + + *is_ref_clk = false; + } else { + wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:" + "TcxoRefClk=%d - 16.368Mhz or 32.736Mhz" + " - TCXO to FREF switch", + wl->tcxo_clock); + + return true; + } + } + + return false; +} + +static int wl128x_boot_clk(struct wl1271 *wl, bool *is_ref_clk) +{ + if (wl128x_switch_fref(wl, is_ref_clk)) { + wl1271_debug(DEBUG_BOOT, "XTAL-only mode go directly to" + " TCXO TO FREF SWITCH"); + /* TCXO to FREF switch - for PG2.0 */ + wl1271_top_reg_write(wl, WL_SPARE_REG, + WL_SPARE_MASK_8526); + + wl1271_top_reg_write(wl, SYS_CLK_CFG_REG, + WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); + + *is_ref_clk = true; + mdelay(15); + } + + /* Set bit 2 in spare register to avoid illegal access */ + wl1271_top_reg_write(wl, WL_SPARE_REG, WL_SPARE_VAL); + + /* working with TCXO clock */ + if ((*is_ref_clk == false) && + ((wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8) || + (wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6))) { + wl1271_debug(DEBUG_BOOT, "16_8_M or 33_6_M TCXO detected"); + + /* Manually Configure MCS PLL settings PG2.0 Only */ + wl1271_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); + wl1271_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); + wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, + MCS_PLL_CONFIG_REG_VAL); + } else { + int pll_config; + u16 mcs_pll_config_val; + + /* + * Configure MCS PLL settings to FREF Freq + * Set the values that determine the time elapse since the PLL's + * get their enable signal until the lock indication is set + */ + wl1271_top_reg_write(wl, PLL_LOCK_COUNTERS_REG, + PLL_LOCK_COUNTERS_COEX | PLL_LOCK_COUNTERS_MCS); + + mcs_pll_config_val = wl1271_top_reg_read(wl, + MCS_PLL_CONFIG_REG); + /* + * Set the MCS PLL input frequency value according to the + * reference clock value detected/read + */ + if (*is_ref_clk == false) { + if ((wl->tcxo_clock == WL12XX_TCXOCLOCK_19_2) || + (wl->tcxo_clock == WL12XX_TCXOCLOCK_38_4)) + pll_config = 1; + else if ((wl->tcxo_clock == WL12XX_TCXOCLOCK_26) + || + (wl->tcxo_clock == WL12XX_TCXOCLOCK_52)) + pll_config = 2; + else + return -EINVAL; + } else { + if ((wl->ref_clock == CONF_REF_CLK_19_2_E) || + (wl->ref_clock == CONF_REF_CLK_38_4_E)) + pll_config = 1; + else if ((wl->ref_clock == CONF_REF_CLK_26_E) || + (wl->ref_clock == CONF_REF_CLK_52_E)) + pll_config = 2; + else + return -EINVAL; + } + + mcs_pll_config_val |= (pll_config << (MCS_SEL_IN_FREQ_SHIFT)) & + (MCS_SEL_IN_FREQ_MASK); + wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, + mcs_pll_config_val); + } + + return 0; +} + +static int wl127x_boot_clk(struct wl1271 *wl) +{ + u32 pause; + u32 clk; wl1271_boot_hw_version(wl); - if (wl->ref_clock == 0 || wl->ref_clock == 2 || wl->ref_clock == 4) + if (wl->ref_clock == CONF_REF_CLK_19_2_E || + wl->ref_clock == CONF_REF_CLK_38_4_E || + wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) /* ref clk: 19.2/38.4/38.4-XTAL */ clk = 0x3; - else if (wl->ref_clock == 1 || wl->ref_clock == 3) + else if (wl->ref_clock == CONF_REF_CLK_26_E || + wl->ref_clock == CONF_REF_CLK_52_E) /* ref clk: 26/52 */ clk = 0x5; else return -EINVAL; - if (wl->ref_clock != 0) { + if (wl->ref_clock != CONF_REF_CLK_19_2_E) { u16 val; /* Set clock type (open drain) */ val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); @@ -567,6 +703,26 @@ int wl1271_load_firmware(struct wl1271 *wl) pause |= WU_COUNTER_PAUSE_VAL; wl1271_write32(wl, WU_COUNTER_PAUSE, pause); + return 0; +} + +/* uploads NVS and firmware */ +int wl1271_load_firmware(struct wl1271 *wl) +{ + int ret = 0; + u32 tmp, clk; + bool is_ref_clk = false; + + if (wl->chip.id == CHIP_ID_1283_PG20) { + ret = wl128x_boot_clk(wl, &is_ref_clk); + if (ret < 0) + goto out; + } else { + ret = wl127x_boot_clk(wl); + if (ret < 0) + goto out; + } + /* Continue the ELP wake up sequence */ wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); udelay(500); @@ -582,7 +738,15 @@ int wl1271_load_firmware(struct wl1271 *wl) wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); - clk |= (wl->ref_clock << 1) << 4; + if (wl->chip.id == CHIP_ID_1283_PG20) { + if (is_ref_clk == false) + clk |= ((wl->tcxo_clock & 0x3) << 1) << 4; + else + clk |= ((wl->ref_clock & 0x3) << 1) << 4; + } else { + clk |= (wl->ref_clock << 1) << 4; + } + wl1271_write32(wl, DRPW_SCRATCH_START, clk); wl1271_set_partition(wl, &part_table[PART_WORK]); @@ -615,6 +779,9 @@ int wl1271_load_firmware(struct wl1271 *wl) /* WL1271: The reference driver skips steps 7 to 10 (jumps directly * to upload_fw) */ + if (wl->chip.id == CHIP_ID_1283_PG20) + wl1271_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); + ret = wl1271_boot_upload_firmware(wl); if (ret < 0) goto out; diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 7491b3d8487a..f6dd3dea4f30 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -255,6 +255,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, wl->irq = wlan_data->irq; wl->ref_clock = wlan_data->board_ref_clock; + wl->tcxo_clock = wlan_data->board_tcxo_clock; ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c index e6e2ad63a1c1..c02c87046615 100644 --- a/drivers/net/wireless/wl12xx/sdio_test.c +++ b/drivers/net/wireless/wl12xx/sdio_test.c @@ -421,6 +421,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, wl->irq = wlan_data->irq; wl->ref_clock = wlan_data->board_ref_clock; + wl->tcxo_clock = wlan_data->board_tcxo_clock; sdio_set_drvdata(func, wl_test); diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index bfb1171176ca..f5525361f2f5 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -401,6 +401,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) } wl->ref_clock = pdata->board_ref_clock; + wl->tcxo_clock = pdata->board_tcxo_clock; wl->irq = spi->irq; if (wl->irq < 0) { diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index e59f5392e909..4b556776fd57 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -535,6 +535,7 @@ struct wl1271 { u8 ba_rx_bitmap; u32 block_size; + int tcxo_clock; /* * AP-mode - links indexed by HLID. The global and broadcast links -- cgit v1.2.3-58-ga151 From 13b107dd9808343d05627f0fba7fbc764c86738e Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 6 Mar 2011 16:32:12 +0200 Subject: wl12xx: 1281/1283 support - use dynamic memory for the RX/TX pools Separate the memory configuration to chip-specific structures and implement dynamic memory for wl128x. This feature allows us to move TX memory blocks to the RX pool when the RX path is overloaded. Thanks for Arik Nemtsov for helping simplify the wl1271_fw_status() code. [Rewrote the commit subject and message for clarity; improved some comments and changed "spare" to "padding" for consistency; added a FIXME for the AP memory configuration -- Luca] Signed-off-by: Shahar Levi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 35 +++++++++++++++++--------- drivers/net/wireless/wl12xx/conf.h | 3 ++- drivers/net/wireless/wl12xx/main.c | 48 ++++++++++++++++++++++++++++++------ drivers/net/wireless/wl12xx/wl12xx.h | 5 ++++ 4 files changed, 70 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 50676b36ad26..e005aa40ef84 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -965,10 +965,13 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) } /* memory config */ - mem_conf->num_stations = wl->conf.mem.num_stations; - mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num; - mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num; - mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles; + /* FIXME: for now we always use mem_wl127x for AP, because it + * doesn't support dynamic memory and we don't have the + * optimal values for wl128x without dynamic memory yet */ + mem_conf->num_stations = wl->conf.mem_wl127x.num_stations; + mem_conf->rx_mem_block_num = wl->conf.mem_wl127x.rx_block_num; + mem_conf->tx_min_mem_block_num = wl->conf.mem_wl127x.tx_min_block_num; + mem_conf->num_ssid_profiles = wl->conf.mem_wl127x.ssid_profiles; mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, @@ -986,6 +989,7 @@ out: int wl1271_acx_sta_mem_cfg(struct wl1271 *wl) { struct wl1271_acx_sta_config_memory *mem_conf; + struct conf_memory_settings *mem; int ret; wl1271_debug(DEBUG_ACX, "wl1271 mem cfg"); @@ -996,16 +1000,21 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl) goto out; } + if (wl->chip.id == CHIP_ID_1283_PG20) + mem = &wl->conf.mem_wl128x; + else + mem = &wl->conf.mem_wl127x; + /* memory config */ - mem_conf->num_stations = wl->conf.mem.num_stations; - mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num; - mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num; - mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles; + mem_conf->num_stations = mem->num_stations; + mem_conf->rx_mem_block_num = mem->rx_block_num; + mem_conf->tx_min_mem_block_num = mem->tx_min_block_num; + mem_conf->num_ssid_profiles = mem->ssid_profiles; mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); - mem_conf->dyn_mem_enable = wl->conf.mem.dynamic_memory; - mem_conf->tx_free_req = wl->conf.mem.min_req_tx_blocks; - mem_conf->rx_free_req = wl->conf.mem.min_req_rx_blocks; - mem_conf->tx_min = wl->conf.mem.tx_min; + mem_conf->dyn_mem_enable = mem->dynamic_memory; + mem_conf->tx_free_req = mem->min_req_tx_blocks; + mem_conf->rx_free_req = mem->min_req_rx_blocks; + mem_conf->tx_min = mem->tx_min; ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, sizeof(*mem_conf)); @@ -1072,6 +1081,8 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl) wl1271_debug(DEBUG_TX, "available tx blocks: %d", wl->tx_blocks_available); + wl->tx_new_total = wl->tx_blocks_available; + return 0; } diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index a00f22c6c74f..743bd0beb63b 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -1204,7 +1204,8 @@ struct conf_drv_settings { struct conf_scan_settings scan; struct conf_rf_settings rf; struct conf_ht_setting ht; - struct conf_memory_settings mem; + struct conf_memory_settings mem_wl127x; + struct conf_memory_settings mem_wl128x; }; #endif diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index fe0cf47a656c..3c381ceadb98 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -298,7 +298,7 @@ static struct conf_drv_settings default_conf = { .tx_ba_win_size = 64, .inactivity_timeout = 10000, }, - .mem = { + .mem_wl127x = { .num_stations = 1, .ssid_profiles = 1, .rx_block_num = 70, @@ -307,7 +307,17 @@ static struct conf_drv_settings default_conf = { .min_req_tx_blocks = 100, .min_req_rx_blocks = 22, .tx_min = 27, - } + }, + .mem_wl128x = { + .num_stations = 1, + .ssid_profiles = 1, + .rx_block_num = 40, + .tx_min_block_num = 40, + .dynamic_memory = 1, + .min_req_tx_blocks = 45, + .min_req_rx_blocks = 22, + .tx_min = 27, + }, }; static void __wl1271_op_remove_interface(struct wl1271 *wl); @@ -608,16 +618,27 @@ static void wl1271_fw_status(struct wl1271 *wl, { struct wl1271_fw_common_status *status = &full_status->common; struct timespec ts; + u32 old_tx_blk_count = wl->tx_blocks_available; u32 total = 0; int i; - if (wl->bss_type == BSS_TYPE_AP_BSS) + if (wl->bss_type == BSS_TYPE_AP_BSS) { wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(struct wl1271_fw_ap_status), false); - else + } else { wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(struct wl1271_fw_sta_status), false); + /* Update tx total blocks change */ + wl->tx_total_diff += + ((struct wl1271_fw_sta_status *)status)->tx_total - + wl->tx_new_total; + + /* Update total tx blocks */ + wl->tx_new_total = + ((struct wl1271_fw_sta_status *)status)->tx_total; + } + wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " "drv_rx_counter = %d, tx_results_counter = %d)", status->intr, @@ -627,17 +648,28 @@ static void wl1271_fw_status(struct wl1271 *wl, /* update number of available TX blocks */ for (i = 0; i < NUM_TX_QUEUES; i++) { - u32 cnt = le32_to_cpu(status->tx_released_blks[i]) - + total += le32_to_cpu(status->tx_released_blks[i]) - wl->tx_blocks_freed[i]; wl->tx_blocks_freed[i] = le32_to_cpu(status->tx_released_blks[i]); - wl->tx_blocks_available += cnt; - total += cnt; + + } + + /* + * By adding the freed blocks to tx_total_diff we are actually + * moving them to the RX pool. + */ + wl->tx_total_diff += total; + + /* if we have positive difference, add the blocks to the TX pool */ + if (wl->tx_total_diff >= 0) { + wl->tx_blocks_available += wl->tx_total_diff; + wl->tx_total_diff = 0; } /* if more blocks are available now, tx work can be scheduled */ - if (total) + if (wl->tx_blocks_available > old_tx_blk_count) clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); /* for AP update num of allocated TX blocks per link and ps status */ diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 4b556776fd57..ad04b8337a25 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -267,6 +267,8 @@ struct wl1271_fw_sta_status { u8 tx_total; u8 reserved1; __le16 reserved2; + /* Total structure size is 68 bytes */ + u32 padding; } __packed; struct wl1271_fw_full_status { @@ -397,6 +399,9 @@ struct wl1271 { u32 tx_blocks_freed[NUM_TX_QUEUES]; u32 tx_blocks_available; u32 tx_results_count; + /* Indicates how many memory blocks should be moved to the RX pool */ + int tx_total_diff; + u32 tx_new_total; /* Transmitted TX packets counter for chipset interface */ u32 tx_packets_count; -- cgit v1.2.3-58-ga151 From ae77eccf04f8c36769bdba334e1bbcc7bb9d3644 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 6 Mar 2011 16:32:13 +0200 Subject: wl12xx: 1281/1283 support - Improve Tx & Rx path Reduced bus transactions in the Tx & Rx path. [Removed unnecessary check wl->chip.id != CHIP_ID_1283_PG20 when checking the quirk -- Luca] Signed-off-by: Shahar Levi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/rx.c | 31 +++++++++++++++++++------------ drivers/net/wireless/wl12xx/tx.c | 30 +++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 919b59f00301..132b0cab5696 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -163,18 +163,25 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) break; } - /* - * Choose the block we want to read - * For aggregated packets, only the first memory block should - * be retrieved. The FW takes care of the rest. - */ - mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter); - wl->rx_mem_pool_addr.addr = (mem_block << 8) + - le32_to_cpu(wl_mem_map->packet_memory_pool_start); - wl->rx_mem_pool_addr.addr_extra = - wl->rx_mem_pool_addr.addr + 4; - wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr, - sizeof(wl->rx_mem_pool_addr), false); + if (wl->chip.id != CHIP_ID_1283_PG20) { + /* + * Choose the block we want to read + * For aggregated packets, only the first memory block + * should be retrieved. The FW takes care of the rest. + */ + mem_block = wl1271_rx_get_mem_block(status, + drv_rx_counter); + + wl->rx_mem_pool_addr.addr = (mem_block << 8) + + le32_to_cpu(wl_mem_map->packet_memory_pool_start); + + wl->rx_mem_pool_addr.addr_extra = + wl->rx_mem_pool_addr.addr + 4; + + wl1271_write(wl, WL1271_SLV_REG_DATA, + &wl->rx_mem_pool_addr, + sizeof(wl->rx_mem_pool_addr), false); + } /* Read all available packets at once */ wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index e296f0a5fe27..afc8505abeb6 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -158,8 +158,14 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, desc = (struct wl1271_tx_hw_descr *)skb_push( skb, total_len - skb->len); - desc->wl127x_mem.extra_blocks = TX_HW_BLOCK_SPARE; - desc->wl127x_mem.total_mem_blocks = total_blocks; + /* HW descriptor fields change between wl127x and wl128x */ + if (wl->chip.id == CHIP_ID_1283_PG20) { + desc->wl128x_mem.total_mem_blocks = total_blocks; + } else { + desc->wl127x_mem.extra_blocks = TX_HW_BLOCK_SPARE; + desc->wl127x_mem.total_mem_blocks = total_blocks; + } + desc->id = id; wl->tx_blocks_available -= total_blocks; @@ -249,6 +255,13 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, desc->wl128x_mem.extra_bytes = aligned_len - skb->len; desc->length = cpu_to_le16(aligned_len >> 2); + + wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d " + "tx_attr: 0x%x len: %d life: %d mem: %d", + desc->hlid, tx_attr, + le16_to_cpu(desc->length), + le16_to_cpu(desc->life_time), + desc->wl128x_mem.total_mem_blocks); } else { int pad; @@ -260,16 +273,15 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, pad = aligned_len - skb->len; tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; - wl1271_debug(DEBUG_TX, "tx_fill_hdr: padding: %d", pad); + wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d " + "tx_attr: 0x%x len: %d life: %d mem: %d", pad, + desc->hlid, tx_attr, + le16_to_cpu(desc->length), + le16_to_cpu(desc->life_time), + desc->wl127x_mem.total_mem_blocks); } desc->tx_attr = cpu_to_le16(tx_attr); - - wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d tx_attr: 0x%x " - "len: %d life: %d mem: %d", - desc->hlid, le16_to_cpu(desc->tx_attr), - le16_to_cpu(desc->length), le16_to_cpu(desc->life_time), - desc->wl127x_mem.total_mem_blocks); } /* caller must hold wl->mutex */ -- cgit v1.2.3-58-ga151 From ae47c45fd02fdf88d57adc370e78e7a01e2bfcbc Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 6 Mar 2011 16:32:14 +0200 Subject: wl12xx: 1281/1283 support - Add dummy packet support Support sending dummy packet to wl128x FW as results of dummy packet event. That is part of dynamic TX mem blocks mechanism. Only send dummy packet when not in AP mode. [Even though the DUMMY_PACKET_EVENT_ID and the STA_REMOVE_COMPLETE_EVENT_ID events are defined to the same value, we need to treat them separately in the code. Keep the check and enable STA_REMOVE_COMPLETE_EVENT_ID for AP mode and DUMMY_PACKET_EVENT_ID for STA. Moved one warning to a cleaner place. Use WL1271_TID_MGMT for dummy packets -- Luca] Signed-off-by: Shahar Levi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/boot.c | 2 + drivers/net/wireless/wl12xx/event.c | 6 +++ drivers/net/wireless/wl12xx/event.h | 5 ++- drivers/net/wireless/wl12xx/io.h | 1 + drivers/net/wireless/wl12xx/main.c | 42 +++++++++++++++++++++ drivers/net/wireless/wl12xx/tx.c | 75 +++++++++++++++++++++++++++---------- drivers/net/wireless/wl12xx/tx.h | 6 +++ 7 files changed, 116 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 9d742c1e75a9..34bf2fe47dc7 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -482,6 +482,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) if (wl->bss_type == BSS_TYPE_AP_BSS) wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; + else + wl->event_mask |= DUMMY_PACKET_EVENT_ID; ret = wl1271_event_unmask(wl); if (ret < 0) { diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 1b170c5cc595..413d901985fe 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -228,6 +228,12 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) wl1271_event_rssi_trigger(wl, mbox); } + if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) { + wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); + if (wl->vif) + wl1271_tx_dummy_packet(wl); + } + if (wl->vif && beacon_loss) ieee80211_connection_loss(wl->vif); diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h index 0e80886f3031..b6cf06e565a4 100644 --- a/drivers/net/wireless/wl12xx/event.h +++ b/drivers/net/wireless/wl12xx/event.h @@ -59,7 +59,10 @@ enum { BSS_LOSE_EVENT_ID = BIT(18), REGAINED_BSS_EVENT_ID = BIT(19), ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20), - STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), /* AP */ + /* STA: dummy paket for dynamic mem blocks */ + DUMMY_PACKET_EVENT_ID = BIT(21), + /* AP: STA remove complete */ + STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h index 84454f6d8169..e6199eb51936 100644 --- a/drivers/net/wireless/wl12xx/io.h +++ b/drivers/net/wireless/wl12xx/io.h @@ -170,5 +170,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void); int wl1271_free_hw(struct wl1271 *wl); irqreturn_t wl1271_irq(int irq, void *data); bool wl1271_set_block_size(struct wl1271 *wl); +int wl1271_tx_dummy_packet(struct wl1271 *wl); #endif diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 3c381ceadb98..54ac6757c39b 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1174,6 +1174,48 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) spin_unlock_irqrestore(&wl->wl_lock, flags); } +#define TX_DUMMY_PACKET_SIZE 1400 +int wl1271_tx_dummy_packet(struct wl1271 *wl) +{ + struct sk_buff *skb = NULL; + struct ieee80211_hdr_3addr *hdr; + int ret = 0; + + skb = dev_alloc_skb( + sizeof(struct wl1271_tx_hw_descr) + sizeof(*hdr) + + TX_DUMMY_PACKET_SIZE); + if (!skb) { + wl1271_warning("failed to allocate buffer for dummy packet"); + ret = -ENOMEM; + goto out; + } + + skb_reserve(skb, sizeof(struct wl1271_tx_hw_descr)); + + hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr)); + memset(hdr, 0, sizeof(*hdr)); + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | + IEEE80211_FCTL_TODS | + IEEE80211_STYPE_NULLFUNC); + + memcpy(hdr->addr1, wl->bssid, ETH_ALEN); + memcpy(hdr->addr2, wl->mac_addr, ETH_ALEN); + memcpy(hdr->addr3, wl->bssid, ETH_ALEN); + + skb_put(skb, TX_DUMMY_PACKET_SIZE); + + memset(skb->data, 0, TX_DUMMY_PACKET_SIZE); + + skb->pkt_type = TX_PKT_TYPE_DUMMY_REQ; + /* CONF_TX_AC_VO */ + skb->queue_mapping = 0; + + wl1271_op_tx(wl->hw, skb); + +out: + return ret; +} + static struct notifier_block wl1271_dev_notifier = { .notifier_call = wl1271_dev_notify, }; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index afc8505abeb6..75222a681296 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -215,13 +215,29 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, else desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU); - /* configure the tx attributes */ - tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; - /* queue (we use same identifiers for tid's and ac's */ ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); desc->tid = ac; + if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) { + /* + * FW expects the dummy packet to have an invalid session id - + * any session id that is different than the one set in the join + */ + tx_attr = ((~wl->session_counter) << + TX_HW_ATTR_OFST_SESSION_COUNTER) & + TX_HW_ATTR_SESSION_COUNTER; + + tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ; + + /* Dummy packets require the TID to be management */ + desc->tid = WL1271_TID_MGMT; + } else { + /* configure the tx attributes */ + tx_attr = + wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; + } + if (wl->bss_type != BSS_TYPE_AP_BSS) { desc->aid = hlid; @@ -587,6 +603,12 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, skb = wl->tx_frames[id]; info = IEEE80211_SKB_CB(skb); + if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) { + dev_kfree_skb(skb); + wl1271_free_tx_id(wl, id); + return; + } + /* update the TX status info */ if (result->status == TX_SUCCESS) { if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) @@ -716,10 +738,15 @@ void wl1271_tx_reset(struct wl1271 *wl) while ((skb = skb_dequeue(&wl->tx_queue[i]))) { wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); - info = IEEE80211_SKB_CB(skb); - info->status.rates[0].idx = -1; - info->status.rates[0].count = 0; - ieee80211_tx_status(wl->hw, skb); + + if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) { + dev_kfree_skb(skb); + } else { + info = IEEE80211_SKB_CB(skb); + info->status.rates[0].idx = -1; + info->status.rates[0].count = 0; + ieee80211_tx_status(wl->hw, skb); + } } } } @@ -740,21 +767,29 @@ void wl1271_tx_reset(struct wl1271 *wl) wl1271_free_tx_id(wl, i); wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); - /* Remove private headers before passing the skb to mac80211 */ - info = IEEE80211_SKB_CB(skb); - skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); - if (info->control.hw_key && - info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { - int hdrlen = ieee80211_get_hdrlen_from_skb(skb); - memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, - hdrlen); - skb_pull(skb, WL1271_TKIP_IV_SPACE); - } + if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) { + dev_kfree_skb(skb); + } else { + /* + * Remove private headers before passing the skb to + * mac80211 + */ + info = IEEE80211_SKB_CB(skb); + skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); + if (info->control.hw_key && + info->control.hw_key->cipher == + WLAN_CIPHER_SUITE_TKIP) { + int hdrlen = ieee80211_get_hdrlen_from_skb(skb); + memmove(skb->data + WL1271_TKIP_IV_SPACE, + skb->data, hdrlen); + skb_pull(skb, WL1271_TKIP_IV_SPACE); + } - info->status.rates[0].idx = -1; - info->status.rates[0].count = 0; + info->status.rates[0].idx = -1; + info->status.rates[0].count = 0; - ieee80211_tx_status(wl->hw, skb); + ieee80211_tx_status(wl->hw, skb); + } } } diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index e31317717ab2..6f45e9108d9a 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -41,6 +41,9 @@ BIT(8) | BIT(9)) #define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11)) #define TX_HW_ATTR_TX_CMPLT_REQ BIT(12) +#define TX_HW_ATTR_TX_DUMMY_REQ BIT(13) + +#define TX_PKT_TYPE_DUMMY_REQ 5 #define TX_HW_ATTR_OFST_SAVE_RETRIES 0 #define TX_HW_ATTR_OFST_HEADER_PAD 1 @@ -55,6 +58,9 @@ #define WL1271_TX_ALIGN_TO 4 #define WL1271_TKIP_IV_SPACE 4 +/* Used for management frames and dummy packets */ +#define WL1271_TID_MGMT 7 + struct wl127x_tx_mem { /* * Number of extra memory blocks to allocate for this packet -- cgit v1.2.3-58-ga151 From 1aed55fd784d000fb6741cefb68712d64817bd68 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 6 Mar 2011 16:32:18 +0200 Subject: wl12xx: 1281/1283 support - Use different FW file for AP mode wl127x/wl128x chips Choose a different FW for AP-mode wl127x and wl128x chips, base on chip ID at boot time. Signed-off-by: Arik Nemtsov Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 5 ++++- drivers/net/wireless/wl12xx/sdio.c | 3 ++- drivers/net/wireless/wl12xx/spi.c | 3 ++- drivers/net/wireless/wl12xx/wl12xx.h | 3 ++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 54ac6757c39b..9a7ca6524d20 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -832,7 +832,10 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) switch (wl->bss_type) { case BSS_TYPE_AP_BSS: - fw_name = WL1271_AP_FW_NAME; + if (wl->chip.id == CHIP_ID_1283_PG20) + fw_name = WL128X_AP_FW_NAME; + else + fw_name = WL127X_AP_FW_NAME; break; case BSS_TYPE_IBSS: case BSS_TYPE_STA_BSS: diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index f6dd3dea4f30..5a2951ed6eda 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -361,4 +361,5 @@ MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); MODULE_FIRMWARE(WL1271_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME); -MODULE_FIRMWARE(WL1271_AP_FW_NAME); +MODULE_FIRMWARE(WL127X_AP_FW_NAME); +MODULE_FIRMWARE(WL128X_AP_FW_NAME); diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index f5525361f2f5..7b82b5f0e490 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -493,5 +493,6 @@ MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); MODULE_FIRMWARE(WL1271_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME); -MODULE_FIRMWARE(WL1271_AP_FW_NAME); +MODULE_FIRMWARE(WL127X_AP_FW_NAME); +MODULE_FIRMWARE(WL128X_AP_FW_NAME); MODULE_ALIAS("spi:wl1271"); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index ad04b8337a25..890c1a54382d 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -132,7 +132,8 @@ extern u32 wl12xx_debug_level; #define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin" #define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin" -#define WL1271_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin" +#define WL127X_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin" +#define WL128X_AP_FW_NAME "ti-connectivity/wl128x-fw-ap.bin" /* * wl127x and wl128x are using the same NVS file name. However, the -- cgit v1.2.3-58-ga151 From 0830ceedbfde20c9110c59597fdffbf51886565a Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 6 Mar 2011 16:32:20 +0200 Subject: wl12xx: 1281/1283 support - enable chip support Add support to wl128x chip via chip id Signed-off-by: Shahar Levi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/Kconfig | 2 +- drivers/net/wireless/wl12xx/main.c | 9 +++++++++ drivers/net/wireless/wl12xx/sdio_test.c | 5 +++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 692ebff38fc8..35ce7b0f4a60 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig @@ -3,7 +3,7 @@ menuconfig WL12XX_MENU depends on MAC80211 && EXPERIMENTAL ---help--- This will enable TI wl12xx driver support for the following chips: - wl1271 and wl1273. + wl1271, wl1273, wl1281 and wl1283. The drivers make use of the mac80211 stack. config WL12XX diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 9a7ca6524d20..0b9d41f14b28 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1007,6 +1007,15 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) if (ret < 0) goto out; break; + case CHIP_ID_1283_PG20: + wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", + wl->chip.id); + + ret = wl1271_setup(wl); + if (ret < 0) + goto out; + break; + case CHIP_ID_1283_PG10: default: wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); ret = -ENODEV; diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c index c02c87046615..968249a4da39 100644 --- a/drivers/net/wireless/wl12xx/sdio_test.c +++ b/drivers/net/wireless/wl12xx/sdio_test.c @@ -293,6 +293,11 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) wl1271_notice("chip id 0x%x (1271 PG20)", wl->chip.id); break; + case CHIP_ID_1283_PG20: + wl1271_notice("chip id 0x%x (1283 PG20)", + wl->chip.id); + break; + case CHIP_ID_1283_PG10: default: wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); return -ENODEV; -- cgit v1.2.3-58-ga151 From e7ddf549f3f2da156f5c12921e6699024e80a3f4 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 10 Mar 2011 15:24:57 +0200 Subject: wl12xx: use 1 spare TX block instead of two All the new firmware versions (>=6.1.3.50.58 for STA and >=6.2.0.0.47 for AP) use 1 spare TX block. We still want to support older firmwares that require 2 spare blocks, so added a quirk to handle the difference. Also implemented a generic way of setting quirks that depend on the firmware revision. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 24 ++++++++++++++++++++++++ drivers/net/wireless/wl12xx/tx.c | 10 ++++++++-- drivers/net/wireless/wl12xx/tx.h | 1 - drivers/net/wireless/wl12xx/wl12xx.h | 28 +++++++++++++++++++++++++--- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0b9d41f14b28..db7ab856363e 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1040,6 +1040,24 @@ out: return ret; } +static unsigned int wl1271_get_fw_ver_quirks(struct wl1271 *wl) +{ + unsigned int quirks = 0; + unsigned int *fw_ver = wl->chip.fw_ver; + + /* Only for wl127x */ + if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) && + /* Check STA version */ + (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && + (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) || + /* Check AP version */ + ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) && + (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN)))) + quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS; + + return quirks; +} + int wl1271_plt_start(struct wl1271 *wl) { int retries = WL1271_BOOT_RETRIES; @@ -1075,6 +1093,9 @@ int wl1271_plt_start(struct wl1271 *wl) wl->state = WL1271_STATE_PLT; wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver_str); + + /* Check if any quirks are needed with older fw versions */ + wl->quirks |= wl1271_get_fw_ver_quirks(wl); goto out; irq_disable: @@ -1353,6 +1374,9 @@ power_off: strncpy(wiphy->fw_version, wl->chip.fw_ver_str, sizeof(wiphy->fw_version)); + /* Check if any quirks are needed with older fw versions */ + wl->quirks |= wl1271_get_fw_ver_quirks(wl); + /* * Now we know if 11a is supported (info from the NVS), so disable * 11a channels if not supported diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 75222a681296..109878c3246e 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -135,6 +135,12 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, u32 len; u32 total_blocks; int id, ret = -EBUSY; + u32 spare_blocks; + + if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS)) + spare_blocks = 2; + else + spare_blocks = 1; if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) return -EAGAIN; @@ -152,7 +158,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, len = total_len; total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE + - TX_HW_BLOCK_SPARE; + spare_blocks; if (total_blocks <= wl->tx_blocks_available) { desc = (struct wl1271_tx_hw_descr *)skb_push( @@ -162,7 +168,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, if (wl->chip.id == CHIP_ID_1283_PG20) { desc->wl128x_mem.total_mem_blocks = total_blocks; } else { - desc->wl127x_mem.extra_blocks = TX_HW_BLOCK_SPARE; + desc->wl127x_mem.extra_blocks = spare_blocks; desc->wl127x_mem.total_mem_blocks = total_blocks; } diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index 6f45e9108d9a..a3877ba32d37 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -25,7 +25,6 @@ #ifndef __TX_H__ #define __TX_H__ -#define TX_HW_BLOCK_SPARE 2 #define TX_HW_BLOCK_SIZE 252 #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 890c1a54382d..b04481aadf9c 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -207,13 +207,29 @@ struct wl1271_partition_set { struct wl1271; -#define WL12XX_NUM_FW_VER 5 +enum { + FW_VER_CHIP, + FW_VER_IF_TYPE, + FW_VER_MAJOR, + FW_VER_SUBTYPE, + FW_VER_MINOR, + + NUM_FW_VER +}; + +#define FW_VER_CHIP_WL127X 6 +#define FW_VER_CHIP_WL128X 7 + +#define FW_VER_IF_TYPE_STA 1 +#define FW_VER_IF_TYPE_AP 2 + +#define FW_VER_MINOR_1_SPARE_STA_MIN 58 +#define FW_VER_MINOR_1_SPARE_AP_MIN 47 -/* FIXME: I'm not sure about this structure name */ struct wl1271_chip { u32 id; char fw_ver_str[ETHTOOL_BUSINFO_LEN]; - unsigned int fw_ver[WL12XX_NUM_FW_VER]; + unsigned int fw_ver[NUM_FW_VER]; }; struct wl1271_stats { @@ -594,4 +610,10 @@ int wl1271_plt_stop(struct wl1271 *wl); /* Each RX/TX transaction requires an end-of-transaction transfer */ #define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0) +/* + * Older firmwares use 2 spare TX blocks + * (for STA < 6.1.3.50.58 or for AP < 6.2.0.0.47) + */ +#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS BIT(1) + #endif -- cgit v1.2.3-58-ga151 From 0af0467f09207cbbeb387d2e09ea539534c6655c Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 10 Mar 2011 10:01:43 +0200 Subject: wl12xx: Fix potential incorrect band in rx-status The rx-status passed to mac80211 along with each received frame contains the band on which the frame was received. Under certain circumstances, this band information may be incorrect, causing in worst case a WARNING from mac80211, and causes the received frame to be dropped. This scenario mainly occurs when performing connected-mode scans, when the received scan results are from the other band than the one currently associated to. [Since desc_band doesn't exist anymore, use status->band in the later call to ieee80211_channel_to_frequency() to fix compilation -- Luca] Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/rx.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 132b0cab5696..2a581495d5c9 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -48,18 +48,14 @@ static void wl1271_rx_status(struct wl1271 *wl, struct ieee80211_rx_status *status, u8 beacon) { - enum ieee80211_band desc_band; - memset(status, 0, sizeof(struct ieee80211_rx_status)); - status->band = wl->band; - if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG) - desc_band = IEEE80211_BAND_2GHZ; + status->band = IEEE80211_BAND_2GHZ; else - desc_band = IEEE80211_BAND_5GHZ; + status->band = IEEE80211_BAND_5GHZ; - status->rate_idx = wl1271_rate_to_idx(desc->rate, desc_band); + status->rate_idx = wl1271_rate_to_idx(desc->rate, status->band); #ifdef CONFIG_WL12XX_HT /* 11n support */ @@ -76,7 +72,8 @@ static void wl1271_rx_status(struct wl1271 *wl, */ wl->noise = desc->rssi - (desc->snr >> 1); - status->freq = ieee80211_channel_to_frequency(desc->channel, desc_band); + status->freq = ieee80211_channel_to_frequency(desc->channel, + status->band); if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; -- cgit v1.2.3-58-ga151 From 871d0c3ba32c2d2e1e7d9ac0d231a440d2653fc5 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 13 Mar 2011 11:24:40 +0200 Subject: wl12xx: Add support for 11n Rx STBC one spatial stream The wl12xx chip supports one Rx STBC spatial stream. Announce this in the HT capabilities info field. Signed-off-by: Shahar Levi Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index db7ab856363e..28048474827a 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3132,7 +3132,8 @@ static const u8 wl1271_rate_to_idx_2ghz[] = { #ifdef CONFIG_WL12XX_HT #define WL12XX_HT_CAP { \ - .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20, \ + .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \ + (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \ .ht_supported = true, \ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \ -- cgit v1.2.3-58-ga151 From 958b20e068be2c6267c2b5764babf15b0d4f5c69 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Mon, 14 Mar 2011 18:53:10 +0200 Subject: wl12xx: update bet_max_consecutive Allow early termination of 50 consecutive beacons. This value is the recommended one by the 12xx's system/RF team, and tests show that power consumption is improved as expected. Reported-by: Ruthy Zaphir Tested-by: Danil Shalumov Signed-off-by: Ohad Ben-Cohen Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 28048474827a..dd49b2292b5f 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -254,7 +254,7 @@ static struct conf_drv_settings default_conf = { .ps_poll_threshold = 10, .ps_poll_recovery_period = 700, .bet_enable = CONF_BET_MODE_ENABLE, - .bet_max_consecutive = 10, + .bet_max_consecutive = 50, .psm_entry_retries = 5, .psm_exit_retries = 255, .psm_entry_nullfunc_retries = 3, -- cgit v1.2.3-58-ga151 From 1d732e8cf3dcc09d7c862b6c12f876533529073d Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Fri, 18 Mar 2011 14:49:57 +0200 Subject: wl12xx: Clamp byte mode transfers for 128x chips On wl128x based devices, when TX packets are aggregated, each packet size must be aligned to the SDIO block size, and sent using block mode transfers. The block size is set to 256 bytes, which is less than the maximum possible byte transfer. Thus, if two small packets (< 256 bytes) are aggregated, the aggregation buffer size would be 512, and will be sent using byte mode transfers. This can have undesired side effects. Fix this by setting the MMC_QUIRK_BLKSZ_FOR_BYTE_MODE mmc card quirk. For 127x chips this has no effect, as the block size is set to 512 bytes. Signed-off-by: Arik Nemtsov Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/sdio.c | 3 +++ drivers/net/wireless/wl12xx/sdio_test.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 5a2951ed6eda..2ade222f7cbb 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -246,6 +246,9 @@ static int __devinit wl1271_probe(struct sdio_func *func, /* Grab access to FN0 for ELP reg. */ func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + /* Use block mode for transferring over one block size of data */ + func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; + wlan_data = wl12xx_get_platform_data(); if (IS_ERR(wlan_data)) { ret = PTR_ERR(wlan_data); diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c index 968249a4da39..f28915392877 100644 --- a/drivers/net/wireless/wl12xx/sdio_test.c +++ b/drivers/net/wireless/wl12xx/sdio_test.c @@ -417,6 +417,9 @@ static int __devinit wl1271_probe(struct sdio_func *func, /* Grab access to FN0 for ELP reg. */ func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + /* Use block mode for transferring over one block size of data */ + func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; + wlan_data = wl12xx_get_platform_data(); if (IS_ERR(wlan_data)) { ret = PTR_ERR(wlan_data); -- cgit v1.2.3-58-ga151 From f9f774c17e19da6f98bd7b57527f55d0ec920fce Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Mon, 21 Mar 2011 10:43:36 +0200 Subject: wl12xx: Add mutex protection for interface list The interface list maintained in main.c is not mutex protected. This could cause issues, as the list is accessed from notifier chains. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index dd49b2292b5f..72e84a209e6c 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -339,6 +339,7 @@ static struct platform_device wl1271_device = { }, }; +static DEFINE_MUTEX(wl_list_mutex); static LIST_HEAD(wl_list); static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, @@ -369,10 +370,12 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, return NOTIFY_DONE; wl_temp = hw->priv; + mutex_lock(&wl_list_mutex); list_for_each_entry(wl, &wl_list, list) { if (wl == wl_temp) break; } + mutex_unlock(&wl_list_mutex); if (wl != wl_temp) return NOTIFY_DONE; @@ -1390,8 +1393,10 @@ power_off: out: mutex_unlock(&wl->mutex); + mutex_lock(&wl_list_mutex); if (!ret) list_add(&wl->list, &wl_list); + mutex_unlock(&wl_list_mutex); return ret; } @@ -1404,7 +1409,9 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) wl1271_info("down"); + mutex_lock(&wl_list_mutex); list_del(&wl->list); + mutex_unlock(&wl_list_mutex); WARN_ON(wl->state != WL1271_STATE_ON); -- cgit v1.2.3-58-ga151 From db674d249c1fa20fd6731048f41646b3a2e8bdf5 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 16 Mar 2011 23:03:54 +0200 Subject: wl12xx: set the actual tid instead of the ac When passing a tx frame, the driver incorrectly set desc->tid with the ac instead of the actual tid. It has some serious implications when using 802.11n + QoS, as the fw starts a BlockAck with the wrong tid (which finally cause beacon loss and disconnection / some fw crash) Fix it by using the actual tid stored in skb->priority. Reported-by: Shahar Levi Signed-off-by: Eliad Peller Reviewed-by: Juuso Oikarinen Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/tx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 109878c3246e..f3031cdd173e 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -221,9 +221,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, else desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU); - /* queue (we use same identifiers for tid's and ac's */ + /* queue */ ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); - desc->tid = ac; + desc->tid = skb->priority; if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) { /* -- cgit v1.2.3-58-ga151 From 18b92ffaf33c862e852992e82e17b9fffca8d5a4 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Mon, 21 Mar 2011 16:35:21 +0200 Subject: wl12xx: set the skbuff priority for dummy packets The firmware requires dummy packets to be sent using TID 7 (WL1271_TID_MGMT). Instead of hardcoding it in the tx_fill_hdr() function, set it when creating the packet itself. This requires Eliad's fix to set the actual TID in the TX descriptor. Cc: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 2 ++ drivers/net/wireless/wl12xx/tx.c | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 72e84a209e6c..59e0f79e3998 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1243,6 +1243,8 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl) memset(skb->data, 0, TX_DUMMY_PACKET_SIZE); skb->pkt_type = TX_PKT_TYPE_DUMMY_REQ; + /* Dummy packets require the TID to be management */ + skb->priority = WL1271_TID_MGMT; /* CONF_TX_AC_VO */ skb->queue_mapping = 0; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index f3031cdd173e..db9e47e09fba 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -235,9 +235,6 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, TX_HW_ATTR_SESSION_COUNTER; tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ; - - /* Dummy packets require the TID to be management */ - desc->tid = WL1271_TID_MGMT; } else { /* configure the tx attributes */ tx_attr = -- cgit v1.2.3-58-ga151 From d9482e2b5132fd40f8de528af6bb715accbab11d Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Mon, 21 Mar 2011 17:58:32 +0200 Subject: wl12xx: fix SG BT load value to reflect its new meaning The Soft Gemini BT load ratio value has changed its meaning with FW version 6.1.0.0.310. It now means the passive scan compensation percentage during A2DP EDR. Instead of 50, we need to use 200. Fix the SG configuration accordingly. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 59e0f79e3998..916ebd1d414c 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -54,7 +54,7 @@ static struct conf_drv_settings default_conf = { [CONF_SG_BT_PER_THRESHOLD] = 7500, [CONF_SG_HV3_MAX_OVERRIDE] = 0, [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, - [CONF_SG_BT_LOAD_RATIO] = 50, + [CONF_SG_BT_LOAD_RATIO] = 200, [CONF_SG_AUTO_PS_MODE] = 1, [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, -- cgit v1.2.3-58-ga151 From 4623ec7d97afaf7a8489036e2c2e71e8349716b4 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Mon, 21 Mar 2011 19:26:41 +0200 Subject: wl12xx: fix a couple of sparse warnings about undeclared functions Fix the following sparse warnings: drivers/net/wireless/wl12xx/main.c:1129:5: warning: symbol '__wl1271_plt_stop' was not declared. Should it be static? drivers/net/wireless/wl12xx/main.c:2988:5: warning: symbol 'wl1271_op_ampdu_action' was not declared. Should it be static? Both functions should be static. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 916ebd1d414c..85cb4daac9a0 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1126,7 +1126,7 @@ out: return ret; } -int __wl1271_plt_stop(struct wl1271 *wl) +static int __wl1271_plt_stop(struct wl1271 *wl) { int ret = 0; @@ -2985,10 +2985,11 @@ out: return ret; } -int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) +static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size) { struct wl1271 *wl = hw->priv; int ret; -- cgit v1.2.3-58-ga151 From 4a31c11c7d8c482598754a577a8fb71abb61ffa0 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Mon, 21 Mar 2011 23:16:14 +0200 Subject: wl12xx: use a bitmask instead of list of booleans in scanned_ch We were using an array of booleans to mark the channels we had already scanned. This was causing a sparse error, because bool is not a type with defined size. To fix this, use bitmasks instead, which is much cleaner anyway. Thanks Johannes Berg for the idea. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 7 +++++-- drivers/net/wireless/wl12xx/scan.c | 17 ++++++++++------- drivers/net/wireless/wl12xx/wl12xx.h | 3 ++- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 85cb4daac9a0..9663326c0dfa 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1423,8 +1423,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { wl->scan.state = WL1271_SCAN_STATE_IDLE; - kfree(wl->scan.scanned_ch); - wl->scan.scanned_ch = NULL; + memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); wl->scan.req = NULL; ieee80211_scan_completed(wl->hw, true); } @@ -3502,6 +3501,10 @@ int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - sizeof(struct ieee80211_header); + /* make sure all our channels fit in the scanned_ch bitmask */ + BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) + + ARRAY_SIZE(wl1271_channels_5ghz) > + WL1271_MAX_CHANNELS); /* * We keep local copies of the band structs because we need to * modify them on a per-device basis. diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 420653a2859c..5d0544c8f3f5 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -48,8 +48,7 @@ void wl1271_scan_complete_work(struct work_struct *work) goto out; wl->scan.state = WL1271_SCAN_STATE_IDLE; - kfree(wl->scan.scanned_ch); - wl->scan.scanned_ch = NULL; + memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); wl->scan.req = NULL; ieee80211_scan_completed(wl->hw, false); @@ -87,7 +86,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, flags = req->channels[i]->flags; - if (!wl->scan.scanned_ch[i] && + if (!test_bit(i, wl->scan.scanned_ch) && !(flags & IEEE80211_CHAN_DISABLED) && ((!!(flags & IEEE80211_CHAN_PASSIVE_SCAN)) == passive) && (req->channels[i]->band == band)) { @@ -124,7 +123,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, memset(&channels[j].bssid_msb, 0xff, 2); /* Mark the channels we already used */ - wl->scan.scanned_ch[i] = true; + set_bit(i, wl->scan.scanned_ch); j++; } @@ -291,6 +290,12 @@ void wl1271_scan_stm(struct wl1271 *wl) int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, struct cfg80211_scan_request *req) { + /* + * cfg80211 should guarantee that we don't get more channels + * than what we have registered. + */ + BUG_ON(req->n_channels > WL1271_MAX_CHANNELS); + if (wl->scan.state != WL1271_SCAN_STATE_IDLE) return -EBUSY; @@ -304,10 +309,8 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, } wl->scan.req = req; + memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); - wl->scan.scanned_ch = kcalloc(req->n_channels, - sizeof(*wl->scan.scanned_ch), - GFP_KERNEL); /* we assume failure so that timeout scenarios are handled correctly */ wl->scan.failed = true; ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index b04481aadf9c..ba98e1853842 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -302,9 +302,10 @@ struct wl1271_rx_mem_pool_addr { u32 addr_extra; }; +#define WL1271_MAX_CHANNELS 64 struct wl1271_scan { struct cfg80211_scan_request *req; - bool *scanned_ch; + unsigned long scanned_ch[BITS_TO_LONGS(WL1271_MAX_CHANNELS)]; bool failed; u8 state; u8 ssid[IW_ESSID_MAX_SIZE+1]; -- cgit v1.2.3-58-ga151 From 17e672d6e4b5a8a3f330a70dfd58d25a2cb497b5 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 22 Mar 2011 10:07:47 +0200 Subject: wl12xx: configure channel/band while FW is off Initialize the channel and band from mac80211 conf even when the FW is not yet loaded. This mitigates a bug in AP-mode where the channel was never changed from its initial setting after FW boot and was therefore never configured to FW. Reported-by: Alexander Boukaty Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 9663326c0dfa..5545c3b94d2e 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1706,7 +1706,12 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&wl->mutex); if (unlikely(wl->state == WL1271_STATE_OFF)) { - ret = -EAGAIN; + /* we support configuring the channel and band while off */ + if ((changed & IEEE80211_CONF_CHANGE_CHANNEL)) { + wl->band = conf->channel->band; + wl->channel = channel; + } + goto out; } -- cgit v1.2.3-58-ga151 From c1b193eb6557279d037ab18c00ab628c6c78847f Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 23 Mar 2011 22:22:15 +0200 Subject: wl12xx: rearrange some ELP wake_up/sleep calls ELP (Extremely/Enhanced Low Power, or something like that ;)) refers to the powerstate of the 12xx chip, in which very low power is consumed, and no commands (from the host) can be issued until the chip is woken up. Wakeup/sleep commands must be protected by a wl->mutex, so it's generally a good idea to call wakeup/sleep along with the mutex lock/unlock (where needed). However, in some places the wl12xx driver calls wakeup/sleep in some "inner" functions. This result in some "nested" wakeup/sleep calls which might end up letting the chip go to sleep prematurely (e.g. during event handling). Fix it by rearranging the elp calls to come along with mutex_lock/unlock. Signed-off-by: Eliad Peller Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/event.c | 11 +++++----- drivers/net/wireless/wl12xx/main.c | 43 ++++++++++++++++++------------------- drivers/net/wireless/wl12xx/ps.c | 3 --- drivers/net/wireless/wl12xx/tx.c | 22 ++++++++----------- 4 files changed, 36 insertions(+), 43 deletions(-) diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 413d901985fe..ae69330e807c 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -33,6 +33,7 @@ void wl1271_pspoll_work(struct work_struct *work) { struct delayed_work *dwork; struct wl1271 *wl; + int ret; dwork = container_of(work, struct delayed_work, work); wl = container_of(dwork, struct wl1271, pspoll_work); @@ -55,8 +56,13 @@ void wl1271_pspoll_work(struct work_struct *work) * delivery failure occurred, and no-one changed state since, so * we should go back to powersave. */ + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true); + wl1271_ps_elp_sleep(wl); out: mutex_unlock(&wl->mutex); }; @@ -129,11 +135,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl, /* enable beacon early termination */ ret = wl1271_acx_bet_enable(wl, true); - if (ret < 0) - break; - - /* go to extremely low power mode */ - wl1271_ps_elp_sleep(wl); break; default: break; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 5545c3b94d2e..3f6517dda629 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2792,32 +2792,31 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY; conf_tid->apsd_conf[0] = 0; conf_tid->apsd_conf[1] = 0; - } else { - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; + goto out; + } - /* - * the txop is confed in units of 32us by the mac80211, - * we need us - */ - ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), - params->cw_min, params->cw_max, - params->aifs, params->txop << 5); - if (ret < 0) - goto out_sleep; + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; - ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), - CONF_CHANNEL_TYPE_EDCF, - wl1271_tx_get_queue(queue), - ps_scheme, CONF_ACK_POLICY_LEGACY, - 0, 0); - if (ret < 0) - goto out_sleep; + /* + * the txop is confed in units of 32us by the mac80211, + * we need us + */ + ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), + params->cw_min, params->cw_max, + params->aifs, params->txop << 5); + if (ret < 0) + goto out_sleep; + + ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), + CONF_CHANNEL_TYPE_EDCF, + wl1271_tx_get_queue(queue), + ps_scheme, CONF_ACK_POLICY_LEGACY, + 0, 0); out_sleep: - wl1271_ps_elp_sleep(wl); - } + wl1271_ps_elp_sleep(wl); out: mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index 971f13e792da..b8deada5d020 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -149,9 +149,6 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, case STATION_ACTIVE_MODE: default: wl1271_debug(DEBUG_PSM, "leaving psm"); - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - return ret; /* disable beacon early termination */ ret = wl1271_acx_bet_enable(wl, false); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index db9e47e09fba..2019ed9ebfc4 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -511,22 +511,14 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) void wl1271_tx_work_locked(struct wl1271 *wl) { struct sk_buff *skb; - bool woken_up = false; u32 buf_offset = 0; bool sent_packets = false; int ret; if (unlikely(wl->state == WL1271_STATE_OFF)) - goto out; + return; while ((skb = wl1271_skb_dequeue(wl))) { - if (!woken_up) { - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out_ack; - woken_up = true; - } - ret = wl1271_prepare_tx_frame(wl, skb, buf_offset); if (ret == -EAGAIN) { /* @@ -573,18 +565,22 @@ out_ack: wl1271_handle_tx_low_watermark(wl); } - -out: - if (woken_up) - wl1271_ps_elp_sleep(wl); } void wl1271_tx_work(struct work_struct *work) { struct wl1271 *wl = container_of(work, struct wl1271, tx_work); + int ret; mutex_lock(&wl->mutex); + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + wl1271_tx_work_locked(wl); + + wl1271_ps_elp_wakeup(wl); +out: mutex_unlock(&wl->mutex); } -- cgit v1.2.3-58-ga151 From 13026decf7b74d0908df034dc6dc86c2caaec939 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Tue, 29 Mar 2011 16:43:50 +0300 Subject: wl12xx: Handle duplicate calling of remove interface Because of the hardware recovery mechanism, its possible the __wl1271_op_remove_interface is called twice. Currently, this leads to a kernel crash even before a kernel WARNing can be issued. Fix this. Signed-off-by: Juuso Oikarinen Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 29 ++++++++++++++++++++++++++--- drivers/net/wireless/wl12xx/wl12xx.h | 3 ++- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 3f6517dda629..57d0af6cfa64 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1304,6 +1304,16 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, goto out; } + /* + * in some very corner case HW recovery scenarios its possible to + * get here before __wl1271_op_remove_interface is complete, so + * opt out if that is the case. + */ + if (test_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags)) { + ret = -EBUSY; + goto out; + } + switch (vif->type) { case NL80211_IFTYPE_STATION: wl->bss_type = BSS_TYPE_STA_BSS; @@ -1372,6 +1382,7 @@ power_off: wl->vif = vif; wl->state = WL1271_STATE_ON; + set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags); wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); /* update hw/fw version info in wiphy struct */ @@ -1409,14 +1420,16 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); + /* because of hardware recovery, we may get here twice */ + if (wl->state != WL1271_STATE_ON) + return; + wl1271_info("down"); mutex_lock(&wl_list_mutex); list_del(&wl->list); mutex_unlock(&wl_list_mutex); - WARN_ON(wl->state != WL1271_STATE_ON); - /* enable dyn ps just in case (if left on due to fw crash etc) */ if (wl->bss_type == BSS_TYPE_STA_BSS) ieee80211_enable_dyn_ps(wl->vif); @@ -1428,6 +1441,10 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) ieee80211_scan_completed(wl->hw, true); } + /* + * this must be before the cancel_work calls below, so that the work + * functions don't perform further work. + */ wl->state = WL1271_STATE_OFF; mutex_unlock(&wl->mutex); @@ -1464,7 +1481,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) wl->time_offset = 0; wl->session_counter = 0; wl->rate_set = CONF_TX_RATE_MASK_BASIC; - wl->flags = 0; wl->vif = NULL; wl->filters = 0; wl1271_free_ap_keys(wl); @@ -1473,6 +1489,13 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) wl->ap_ps_map = 0; wl->block_size = 0; + /* + * this is performed after the cancel_work calls and the associated + * mutex_lock, so that wl1271_op_add_interface does not accidentally + * get executed before all these vars have been reset. + */ + wl->flags = 0; + for (i = 0; i < NUM_TX_QUEUES; i++) wl->tx_blocks_freed[i] = 0; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index ba98e1853842..c12945958848 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -354,7 +354,8 @@ enum wl12xx_flags { WL1271_FLAG_PSPOLL_FAILURE, WL1271_FLAG_STA_STATE_SENT, WL1271_FLAG_FW_TX_BUSY, - WL1271_FLAG_AP_STARTED + WL1271_FLAG_AP_STARTED, + WL1271_FLAG_IF_INITIALIZED, }; struct wl1271_link { -- cgit v1.2.3-58-ga151 From c5745187a4812f2991a58e469a866582a7326d91 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Wed, 30 Mar 2011 16:35:59 +0200 Subject: wl12xx: fix roaming The wl12xx device normally drops all frames coming from BSSID it is not joined with. This behavior is configured today by the wl12xx driver in response to a handful of ieee80211_bss_change and ieee80211_conf_changed notification flags, such as BSS_CHANGED_ASSOC, BSS_CHANGED_BSSID, IEEE80211_CONF_CHANGE_IDLE, etc.. This breaks when we roam to a new BSSID, where authentication frames are sent before any BSS_CHANGED/CONF_CHANGED flags are received. When this happens the hardware silently drops the authentication responses, and the roaming fails. Ideally this aggressive filtering behavior of the device should be disabled upon a notification from mac80211. Such notification will take place after multi-channel support will be added: mac80211 will likely send a remain-on-channel notification to drivers when entering sensitive states (like authentication), otherwise the firmware might jump to different channels (to serve a different role). Until those notifications materialize, disable the hw BSSID filter when authentication requests are sent, so roaming would work. Signed-off-by: Ohad Ben-Cohen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/io.h | 1 + drivers/net/wireless/wl12xx/main.c | 4 ++-- drivers/net/wireless/wl12xx/tx.c | 24 ++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h index e6199eb51936..36e185583ec4 100644 --- a/drivers/net/wireless/wl12xx/io.h +++ b/drivers/net/wireless/wl12xx/io.h @@ -171,5 +171,6 @@ int wl1271_free_hw(struct wl1271 *wl); irqreturn_t wl1271_irq(int irq, void *data); bool wl1271_set_block_size(struct wl1271 *wl); int wl1271_tx_dummy_packet(struct wl1271 *wl); +void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters); #endif diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 57d0af6cfa64..0efa7a055109 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1528,7 +1528,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, cancel_work_sync(&wl->recovery_work); } -static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) +void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) { wl1271_set_default_filters(wl); @@ -1650,7 +1650,7 @@ static int wl1271_unjoin(struct wl1271 *wl) clear_bit(WL1271_FLAG_JOINED, &wl->flags); memset(wl->bssid, 0, ETH_ALEN); - /* stop filterting packets based on bssid */ + /* stop filtering packets based on bssid */ wl1271_configure_filters(wl, FIF_OTHER_BSS); out: diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 2019ed9ebfc4..7686bc1ff16a 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -70,6 +70,28 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id) } } +static int wl1271_tx_update_filters(struct wl1271 *wl, + struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + + hdr = (struct ieee80211_hdr *)(skb->data + + sizeof(struct wl1271_tx_hw_descr)); + + /* + * stop bssid-based filtering before transmitting authentication + * requests. this way the hw will never drop authentication + * responses coming from BSSIDs it isn't familiar with (e.g. on + * roaming) + */ + if (!ieee80211_is_auth(hdr->frame_control)) + return 0; + + wl1271_configure_filters(wl, FIF_OTHER_BSS); + + return wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); +} + static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, struct sk_buff *skb) { @@ -350,6 +372,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, if (wl->bss_type == BSS_TYPE_AP_BSS) { wl1271_tx_ap_update_inconnection_sta(wl, skb); wl1271_tx_regulate_link(wl, hlid); + } else { + wl1271_tx_update_filters(wl, skb); } wl1271_tx_fill_hdr(wl, skb, extra, info, hlid); -- cgit v1.2.3-58-ga151 From 8bf69aae4cb9b196ba5ac386f83a1ca3865af11f Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Wed, 30 Mar 2011 19:18:31 +0200 Subject: wl12xx: fix "JOIN while associated" commentary Issuing multiple JOIN commands to the wl12xx's firmware, while we're associated, might have undesired implications, so the driver prints a message when that happens, and warn developers who check out the source. Update the commentary in order to consider the one valid scenario where this can happen: roaming. Cautiously keep the message for now, until we either gain confidence there are no unintentional JOIN-while-associated events, or until we move to the new multi-role fw who solves this multiple-join issue for good. Signed-off-by: Ohad Ben-Cohen Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0efa7a055109..01205ea5e7e4 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1591,10 +1591,10 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc) * One of the side effects of the JOIN command is that is clears * WPA/WPA2 keys from the chipset. Performing a JOIN while associated * to a WPA/WPA2 access point will therefore kill the data-path. - * Currently there is no supported scenario for JOIN during - * association - if it becomes a supported scenario, the WPA/WPA2 keys - * must be handled somehow. - * + * Currently the only valid scenario for JOIN during association + * is on roaming, in which case we will also be given new keys. + * Keep the below message for now, unless it starts bothering + * users who really like to roam a lot :) */ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) wl1271_info("JOIN while associated."); -- cgit v1.2.3-58-ga151 From d29633b40e6afc6b4276a4e381bc532cc84be104 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Thu, 31 Mar 2011 10:06:57 +0200 Subject: wl12xx: Clean up and fix the 128x boot sequence Clean up the boot sequence code & fix the following issues: 1. Always read the registers' values and set the relevant bits instead of zeroing all other bits 2. Handle cases where wl1271_top_reg_read returns an error 3. Verify that the HW can detect the selected clock source 4. Remove 128x PG10 initialization code 5. Configure the MCS PLL to work in HP mode Signed-off-by: Ido Yariv Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/boot.c | 235 ++++++++++++++++++------------------- drivers/net/wireless/wl12xx/boot.h | 1 + include/linux/wl12xx.h | 10 +- 3 files changed, 123 insertions(+), 123 deletions(-) diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 34bf2fe47dc7..b5ec2c2b6f78 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -523,137 +523,137 @@ static void wl1271_boot_hw_version(struct wl1271 *wl) wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; } -/* - * WL128x has two clocks input - TCXO and FREF. - * TCXO is the main clock of the device, while FREF is used to sync - * between the GPS and the cellular modem. - * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used - * as the WLAN/BT main clock. - */ -static int wl128x_switch_fref(struct wl1271 *wl, bool *is_ref_clk) +static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) { - u16 sys_clk_cfg_val; + u16 spare_reg; - /* if working on XTAL-only mode go directly to TCXO TO FREF SWITCH */ - if ((wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) || - (wl->ref_clock == CONF_REF_CLK_26_M_XTAL)) - return true; + /* Mask bits [2] & [8:4] in the sys_clk_cfg register */ + spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG); + if (spare_reg == 0xFFFF) + return -EFAULT; + spare_reg |= (BIT(3) | BIT(5) | BIT(6)); + wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg); - /* Read clock source FREF or TCXO */ - sys_clk_cfg_val = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG); + /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */ + wl1271_top_reg_write(wl, SYS_CLK_CFG_REG, + WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); - if (sys_clk_cfg_val & PRCM_CM_EN_MUX_WLAN_FREF) { - /* if bit 3 is set - working with FREF clock */ - wl1271_debug(DEBUG_BOOT, "working with FREF clock, skip" - " to FREF"); + /* Delay execution for 15msec, to let the HW settle */ + mdelay(15); - *is_ref_clk = true; - } else { - /* if bit 3 is clear - working with TCXO clock */ - wl1271_debug(DEBUG_BOOT, "working with TCXO clock"); - - /* TCXO to FREF switch, check TXCO clock config */ - if ((wl->tcxo_clock != WL12XX_TCXOCLOCK_16_368) && - (wl->tcxo_clock != WL12XX_TCXOCLOCK_32_736)) { - /* - * not 16.368Mhz and not 32.736Mhz - skip to - * configure ELP stage - */ - wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:" - " TcxoRefClk=%d - not 16.368Mhz and not" - " 32.736Mhz - skip to configure ELP" - " stage", wl->tcxo_clock); - - *is_ref_clk = false; - } else { - wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:" - "TcxoRefClk=%d - 16.368Mhz or 32.736Mhz" - " - TCXO to FREF switch", - wl->tcxo_clock); + return 0; +} - return true; - } - } +static bool wl128x_is_tcxo_valid(struct wl1271 *wl) +{ + u16 tcxo_detection; + + tcxo_detection = wl1271_top_reg_read(wl, TCXO_CLK_DETECT_REG); + if (tcxo_detection & TCXO_DET_FAILED) + return false; - return false; + return true; } -static int wl128x_boot_clk(struct wl1271 *wl, bool *is_ref_clk) +static bool wl128x_is_fref_valid(struct wl1271 *wl) { - if (wl128x_switch_fref(wl, is_ref_clk)) { - wl1271_debug(DEBUG_BOOT, "XTAL-only mode go directly to" - " TCXO TO FREF SWITCH"); - /* TCXO to FREF switch - for PG2.0 */ - wl1271_top_reg_write(wl, WL_SPARE_REG, - WL_SPARE_MASK_8526); - - wl1271_top_reg_write(wl, SYS_CLK_CFG_REG, - WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); - - *is_ref_clk = true; - mdelay(15); - } + u16 fref_detection; - /* Set bit 2 in spare register to avoid illegal access */ - wl1271_top_reg_write(wl, WL_SPARE_REG, WL_SPARE_VAL); + fref_detection = wl1271_top_reg_read(wl, FREF_CLK_DETECT_REG); + if (fref_detection & FREF_CLK_DETECT_FAIL) + return false; - /* working with TCXO clock */ - if ((*is_ref_clk == false) && - ((wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8) || - (wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6))) { - wl1271_debug(DEBUG_BOOT, "16_8_M or 33_6_M TCXO detected"); + return true; +} - /* Manually Configure MCS PLL settings PG2.0 Only */ - wl1271_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); - wl1271_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); - wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, - MCS_PLL_CONFIG_REG_VAL); - } else { - int pll_config; - u16 mcs_pll_config_val; +static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl) +{ + wl1271_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); + wl1271_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); + wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL); - /* - * Configure MCS PLL settings to FREF Freq - * Set the values that determine the time elapse since the PLL's - * get their enable signal until the lock indication is set - */ - wl1271_top_reg_write(wl, PLL_LOCK_COUNTERS_REG, - PLL_LOCK_COUNTERS_COEX | PLL_LOCK_COUNTERS_MCS); + return 0; +} - mcs_pll_config_val = wl1271_top_reg_read(wl, - MCS_PLL_CONFIG_REG); - /* - * Set the MCS PLL input frequency value according to the - * reference clock value detected/read - */ - if (*is_ref_clk == false) { - if ((wl->tcxo_clock == WL12XX_TCXOCLOCK_19_2) || - (wl->tcxo_clock == WL12XX_TCXOCLOCK_38_4)) - pll_config = 1; - else if ((wl->tcxo_clock == WL12XX_TCXOCLOCK_26) - || - (wl->tcxo_clock == WL12XX_TCXOCLOCK_52)) - pll_config = 2; - else - return -EINVAL; - } else { - if ((wl->ref_clock == CONF_REF_CLK_19_2_E) || - (wl->ref_clock == CONF_REF_CLK_38_4_E)) - pll_config = 1; - else if ((wl->ref_clock == CONF_REF_CLK_26_E) || - (wl->ref_clock == CONF_REF_CLK_52_E)) - pll_config = 2; - else - return -EINVAL; - } +static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) +{ + u16 spare_reg; + u16 pll_config; + u8 input_freq; + + /* Mask bits [3:1] in the sys_clk_cfg register */ + spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG); + if (spare_reg == 0xFFFF) + return -EFAULT; + spare_reg |= BIT(2); + wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg); + + /* Handle special cases of the TCXO clock */ + if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || + wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6) + return wl128x_manually_configure_mcs_pll(wl); + + /* Set the input frequency according to the selected clock source */ + input_freq = (clk & 1) + 1; + + pll_config = wl1271_top_reg_read(wl, MCS_PLL_CONFIG_REG); + if (pll_config == 0xFFFF) + return -EFAULT; + pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); + pll_config |= MCS_PLL_ENABLE_HP; + wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config); - mcs_pll_config_val |= (pll_config << (MCS_SEL_IN_FREQ_SHIFT)) & - (MCS_SEL_IN_FREQ_MASK); - wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, - mcs_pll_config_val); + return 0; +} + +/* + * WL128x has two clocks input - TCXO and FREF. + * TCXO is the main clock of the device, while FREF is used to sync + * between the GPS and the cellular modem. + * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used + * as the WLAN/BT main clock. + */ +static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) +{ + u16 sys_clk_cfg; + + /* For XTAL-only modes, FREF will be used after switching from TCXO */ + if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL || + wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) { + if (!wl128x_switch_tcxo_to_fref(wl)) + return -EINVAL; + goto fref_clk; } - return 0; + /* Query the HW, to determine which clock source we should use */ + sys_clk_cfg = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG); + if (sys_clk_cfg == 0xFFFF) + return -EINVAL; + if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF) + goto fref_clk; + + /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */ + if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 || + wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) { + if (!wl128x_switch_tcxo_to_fref(wl)) + return -EINVAL; + goto fref_clk; + } + + /* TCXO clock is selected */ + if (!wl128x_is_tcxo_valid(wl)) + return -EINVAL; + *selected_clock = wl->tcxo_clock; + goto config_mcs_pll; + +fref_clk: + /* FREF clock is selected */ + if (!wl128x_is_fref_valid(wl)) + return -EINVAL; + *selected_clock = wl->ref_clock; + +config_mcs_pll: + return wl128x_configure_mcs_pll(wl, *selected_clock); } static int wl127x_boot_clk(struct wl1271 *wl) @@ -713,10 +713,10 @@ int wl1271_load_firmware(struct wl1271 *wl) { int ret = 0; u32 tmp, clk; - bool is_ref_clk = false; + int selected_clock = -1; if (wl->chip.id == CHIP_ID_1283_PG20) { - ret = wl128x_boot_clk(wl, &is_ref_clk); + ret = wl128x_boot_clk(wl, &selected_clock); if (ret < 0) goto out; } else { @@ -741,10 +741,7 @@ int wl1271_load_firmware(struct wl1271 *wl) wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); if (wl->chip.id == CHIP_ID_1283_PG20) { - if (is_ref_clk == false) - clk |= ((wl->tcxo_clock & 0x3) << 1) << 4; - else - clk |= ((wl->ref_clock & 0x3) << 1) << 4; + clk |= ((selected_clock & 0x3) << 1) << 4; } else { clk |= (wl->ref_clock << 1) << 4; } diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h index 1f5ee31dc0b1..d9de64ac1442 100644 --- a/drivers/net/wireless/wl12xx/boot.h +++ b/drivers/net/wireless/wl12xx/boot.h @@ -107,6 +107,7 @@ struct wl1271_static_data { #define MCS_SEL_IN_FREQ_MASK 0x0070 #define MCS_SEL_IN_FREQ_SHIFT 4 #define MCS_PLL_CONFIG_REG_VAL 0x73 +#define MCS_PLL_ENABLE_HP (BIT(0) | BIT(1)) #define MCS_PLL_M_REG 0xD94 #define MCS_PLL_N_REG 0xD96 diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h index eb8aacab8d4e..c1a743ea7470 100644 --- a/include/linux/wl12xx.h +++ b/include/linux/wl12xx.h @@ -26,10 +26,12 @@ /* Reference clock values */ enum { - WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */ - WL12XX_REFCLOCK_26 = 1, /* 26 MHz */ - WL12XX_REFCLOCK_38 = 2, /* 38.4 MHz */ - WL12XX_REFCLOCK_54 = 3, /* 54 MHz */ + WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */ + WL12XX_REFCLOCK_26 = 1, /* 26 MHz */ + WL12XX_REFCLOCK_38 = 2, /* 38.4 MHz */ + WL12XX_REFCLOCK_52 = 3, /* 52 MHz */ + WL12XX_REFCLOCK_38_XTAL = 4, /* 38.4 MHz, XTAL */ + WL12XX_REFCLOCK_26_XTAL = 5, /* 26 MHz, XTAL */ }; /* TCXO clock values */ -- cgit v1.2.3-58-ga151 From 0da13da767cd568c1fe2a7b5b936e86e521b5ae7 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Thu, 31 Mar 2011 10:06:58 +0200 Subject: wl12xx: Clean up the block size alignment code Simplify and clean up the block size alignment code: 1. Set the block size according to the padding field type, as it cannot exceed the maximum value this field can hold. 2. Move the alignment code into a function instead of duplicating it in multiple places. 3. In the current implementation, the block_size member can be misleading because a zero value actually means that there's no need to align. Declare a block size alignment quirk instead. Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/init.c | 2 +- drivers/net/wireless/wl12xx/io.c | 3 ++- drivers/net/wireless/wl12xx/main.c | 4 ++-- drivers/net/wireless/wl12xx/sdio.c | 12 ++---------- drivers/net/wireless/wl12xx/tx.c | 26 ++++++++++++++------------ drivers/net/wireless/wl12xx/tx.h | 9 +++++++++ drivers/net/wireless/wl12xx/wl12xx.h | 10 ++++++---- 7 files changed, 36 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 2dbc08331ca9..cf466074237d 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -514,7 +514,7 @@ int wl1271_chip_specific_init(struct wl1271 *wl) if (wl->chip.id == CHIP_ID_1283_PG20) { u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; - if (wl1271_set_block_size(wl)) + if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT) /* Enable SDIO padding */ host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK; diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c index aa40c98e8fd3..da5c1ad942a4 100644 --- a/drivers/net/wireless/wl12xx/io.c +++ b/drivers/net/wireless/wl12xx/io.c @@ -29,6 +29,7 @@ #include "wl12xx.h" #include "wl12xx_80211.h" #include "io.h" +#include "tx.h" #define OCP_CMD_LOOP 32 @@ -46,7 +47,7 @@ bool wl1271_set_block_size(struct wl1271 *wl) { if (wl->if_ops->set_block_size) { - wl->if_ops->set_block_size(wl); + wl->if_ops->set_block_size(wl, WL12XX_BUS_BLOCK_SIZE); return true; } diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 01205ea5e7e4..1cd396306e7b 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1017,6 +1017,8 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) ret = wl1271_setup(wl); if (ret < 0) goto out; + if (wl1271_set_block_size(wl)) + wl->quirks |= WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT; break; case CHIP_ID_1283_PG10: default: @@ -1487,7 +1489,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); wl->ap_fw_ps_map = 0; wl->ap_ps_map = 0; - wl->block_size = 0; /* * this is performed after the cancel_work calls and the associated @@ -3632,7 +3633,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->ap_ps_map = 0; wl->ap_fw_ps_map = 0; wl->quirks = 0; - wl->block_size = 0; memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); for (i = 0; i < ACX_TX_DESCRIPTORS; i++) diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 2ade222f7cbb..8246e9de4306 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -51,15 +51,10 @@ static const struct sdio_device_id wl1271_devices[] = { }; MODULE_DEVICE_TABLE(sdio, wl1271_devices); -/* The max SDIO block size is 256 when working with tx padding to SDIO block */ -#define TX_PAD_SDIO_BLK_SIZE 256 - -static void wl1271_sdio_set_block_size(struct wl1271 *wl) +static void wl1271_sdio_set_block_size(struct wl1271 *wl, unsigned int blksz) { - wl->block_size = TX_PAD_SDIO_BLK_SIZE; - sdio_claim_host(wl->if_priv); - sdio_set_block_size(wl->if_priv, TX_PAD_SDIO_BLK_SIZE); + sdio_set_block_size(wl->if_priv, blksz); sdio_release_host(wl->if_priv); } @@ -178,9 +173,6 @@ static int wl1271_sdio_power_on(struct wl1271 *wl) sdio_claim_host(func); sdio_enable_func(func); - /* Set the default block size in case it was modified */ - sdio_set_block_size(func, 0); - out: return ret; } diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 7686bc1ff16a..ba69ba7051fa 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -149,6 +149,15 @@ u8 wl1271_tx_get_hlid(struct sk_buff *skb) } } +static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl, + unsigned int packet_length) +{ + if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT) + return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE); + else + return ALIGN(packet_length, WL1271_TX_ALIGN_TO); +} + static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, u32 buf_offset, u8 hlid) { @@ -174,10 +183,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, /* approximate the number of blocks required for this packet in the firmware */ - if (wl->block_size) - len = ALIGN(total_len, wl->block_size); - else - len = total_len; + len = wl12xx_calc_packet_alignment(wl, total_len); total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE + spare_blocks; @@ -291,9 +297,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY; desc->reserved = 0; - if (wl->block_size) { - aligned_len = ALIGN(skb->len, wl->block_size); + aligned_len = wl12xx_calc_packet_alignment(wl, skb->len); + if (wl->chip.id == CHIP_ID_1283_PG20) { desc->wl128x_mem.extra_bytes = aligned_len - skb->len; desc->length = cpu_to_le16(aligned_len >> 2); @@ -306,8 +312,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, } else { int pad; - /* align the length (and store in terms of words) */ - aligned_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO); + /* Store the aligned length in terms of words */ desc->length = cpu_to_le16(aligned_len >> 2); /* calculate number of padding bytes */ @@ -386,10 +391,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, * In special cases, we want to align to a specific block size * (eg. for wl128x with SDIO we align to 256). */ - if (wl->block_size) - total_len = ALIGN(skb->len, wl->block_size); - else - total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO); + total_len = wl12xx_calc_packet_alignment(wl, skb->len); memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len); memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len); diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index a3877ba32d37..d6b05d980626 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -89,6 +89,15 @@ struct wl128x_tx_mem { u8 extra_bytes; } __packed; +/* + * On wl128x based devices, when TX packets are aggregated, each packet + * size must be aligned to the SDIO block size. The maximum block size + * is bounded by the type of the padded bytes field that is sent to the + * FW. Currently the type is u8, so the maximum block size is 256 bytes. + */ +#define WL12XX_BUS_BLOCK_SIZE min(512u, \ + (1u << (8 * sizeof(((struct wl128x_tx_mem *) 0)->extra_bytes)))) + struct wl1271_tx_hw_descr { /* Length of packet in words, including descriptor+header+data */ __le16 length; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index c12945958848..c7c42b687f5e 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -323,7 +323,7 @@ struct wl1271_if_operations { struct device* (*dev)(struct wl1271 *wl); void (*enable_irq)(struct wl1271 *wl); void (*disable_irq)(struct wl1271 *wl); - void (*set_block_size) (struct wl1271 *wl); + void (*set_block_size) (struct wl1271 *wl, unsigned int blksz); }; #define MAX_NUM_KEYS 14 @@ -558,7 +558,6 @@ struct wl1271 { bool ba_support; u8 ba_rx_bitmap; - u32 block_size; int tcxo_clock; /* @@ -610,12 +609,15 @@ int wl1271_plt_stop(struct wl1271 *wl); /* Quirks */ /* Each RX/TX transaction requires an end-of-transaction transfer */ -#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0) +#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0) /* * Older firmwares use 2 spare TX blocks * (for STA < 6.1.3.50.58 or for AP < 6.2.0.0.47) */ -#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS BIT(1) +#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS BIT(1) + +/* WL128X requires aggregated packets to be aligned to the SDIO block size */ +#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2) #endif -- cgit v1.2.3-58-ga151 From 990f5de7384f9e5922e4c7c7572cbf4f29a9441e Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Thu, 31 Mar 2011 10:06:59 +0200 Subject: wl12xx: Clean up the dummy packet mechanism The current implementation allocates a skb each time one is requested by the firmware. Since dummy packets are handled differently than regular packets, the skb needs to be marked. Currently, this is done by setting the pkt_type member to 5. This might not be safe, as we cannot be sure that there won't be any other packets with this pkt_type value. Since the packet does not change from one request to another, we can simply allocate a dummy packet template and always send it. All changes to the skb done during packet preparation must be reverted, so the same skb can be reused. The dummy packets are not transmitted, therefore there's no need to set the BSSID or our own MAC address. In addition, the header portion of the packet was zeroed by mistake, so fix that as well. Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 79 ++++++++++++++++++++++++------------ drivers/net/wireless/wl12xx/tx.c | 43 ++++++++++++++------ drivers/net/wireless/wl12xx/tx.h | 2 - drivers/net/wireless/wl12xx/wl12xx.h | 4 ++ 4 files changed, 89 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 1cd396306e7b..7dce24c0b331 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1212,20 +1212,46 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) spin_unlock_irqrestore(&wl->wl_lock, flags); } -#define TX_DUMMY_PACKET_SIZE 1400 int wl1271_tx_dummy_packet(struct wl1271 *wl) { - struct sk_buff *skb = NULL; + unsigned long flags; + + spin_lock_irqsave(&wl->wl_lock, flags); + set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); + wl->tx_queue_count++; + spin_unlock_irqrestore(&wl->wl_lock, flags); + + /* The FW is low on RX memory blocks, so send the dummy packet asap */ + if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) + wl1271_tx_work_locked(wl); + + /* + * If the FW TX is busy, TX work will be scheduled by the threaded + * interrupt handler function + */ + return 0; +} + +/* + * The size of the dummy packet should be at least 1400 bytes. However, in + * order to minimize the number of bus transactions, aligning it to 512 bytes + * boundaries could be beneficial, performance wise + */ +#define TOTAL_TX_DUMMY_PACKET_SIZE (ALIGN(1400, 512)) + +struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) +{ + struct sk_buff *skb; struct ieee80211_hdr_3addr *hdr; - int ret = 0; + unsigned int dummy_packet_size; + + dummy_packet_size = TOTAL_TX_DUMMY_PACKET_SIZE - + sizeof(struct wl1271_tx_hw_descr) - sizeof(*hdr); - skb = dev_alloc_skb( - sizeof(struct wl1271_tx_hw_descr) + sizeof(*hdr) + - TX_DUMMY_PACKET_SIZE); + skb = dev_alloc_skb(TOTAL_TX_DUMMY_PACKET_SIZE); if (!skb) { - wl1271_warning("failed to allocate buffer for dummy packet"); - ret = -ENOMEM; - goto out; + wl1271_warning("Failed to allocate a dummy packet skb"); + return NULL; } skb_reserve(skb, sizeof(struct wl1271_tx_hw_descr)); @@ -1233,29 +1259,22 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl) hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr)); memset(hdr, 0, sizeof(*hdr)); hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_FCTL_TODS | - IEEE80211_STYPE_NULLFUNC); - - memcpy(hdr->addr1, wl->bssid, ETH_ALEN); - memcpy(hdr->addr2, wl->mac_addr, ETH_ALEN); - memcpy(hdr->addr3, wl->bssid, ETH_ALEN); + IEEE80211_STYPE_NULLFUNC | + IEEE80211_FCTL_TODS); - skb_put(skb, TX_DUMMY_PACKET_SIZE); + memset(skb_put(skb, dummy_packet_size), 0, dummy_packet_size); - memset(skb->data, 0, TX_DUMMY_PACKET_SIZE); - - skb->pkt_type = TX_PKT_TYPE_DUMMY_REQ; /* Dummy packets require the TID to be management */ skb->priority = WL1271_TID_MGMT; - /* CONF_TX_AC_VO */ - skb->queue_mapping = 0; - wl1271_op_tx(wl->hw, skb); + /* Initialize all fields that might be used */ + skb->queue_mapping = 0; + memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info)); -out: - return ret; + return skb; } + static struct notifier_block wl1271_dev_notifier = { .notifier_call = wl1271_dev_notify, }; @@ -3653,11 +3672,17 @@ struct ieee80211_hw *wl1271_alloc_hw(void) goto err_hw; } + wl->dummy_packet = wl12xx_alloc_dummy_packet(wl); + if (!wl->dummy_packet) { + ret = -ENOMEM; + goto err_aggr; + } + /* Register platform device */ ret = platform_device_register(wl->plat_dev); if (ret) { wl1271_error("couldn't register platform device"); - goto err_aggr; + goto err_dummy_packet; } dev_set_drvdata(&wl->plat_dev->dev, wl); @@ -3683,6 +3708,9 @@ err_bt_coex_state: err_platform: platform_device_unregister(wl->plat_dev); +err_dummy_packet: + dev_kfree_skb(wl->dummy_packet); + err_aggr: free_pages((unsigned long)wl->aggr_buf, order); @@ -3702,6 +3730,7 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw); int wl1271_free_hw(struct wl1271 *wl) { platform_device_unregister(wl->plat_dev); + dev_kfree_skb(wl->dummy_packet); free_pages((unsigned long)wl->aggr_buf, get_order(WL1271_AGGR_BUFFER_SIZE)); kfree(wl->plat_dev); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index ba69ba7051fa..67245ad396ea 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -219,6 +219,11 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, return ret; } +static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) +{ + return wl->dummy_packet == skb; +} + static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, u32 extra, struct ieee80211_tx_info *control, u8 hlid) @@ -253,7 +258,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); desc->tid = skb->priority; - if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) { + if (wl12xx_is_dummy_packet(wl, skb)) { /* * FW expects the dummy packet to have an invalid session id - * any session id that is different than the one set in the join @@ -396,6 +401,10 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len); memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len); + /* Revert side effects in the dummy packet skb, so it can be reused */ + if (wl12xx_is_dummy_packet(wl, skb)) + skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); + return total_len; } @@ -508,10 +517,23 @@ out: static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) { + unsigned long flags; + struct sk_buff *skb = NULL; + if (wl->bss_type == BSS_TYPE_AP_BSS) - return wl1271_ap_skb_dequeue(wl); + skb = wl1271_ap_skb_dequeue(wl); + else + skb = wl1271_sta_skb_dequeue(wl); - return wl1271_sta_skb_dequeue(wl); + if (!skb && + test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { + skb = wl->dummy_packet; + spin_lock_irqsave(&wl->wl_lock, flags); + wl->tx_queue_count--; + spin_unlock_irqrestore(&wl->wl_lock, flags); + } + + return skb; } static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) @@ -519,7 +541,9 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) unsigned long flags; int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); - if (wl->bss_type == BSS_TYPE_AP_BSS) { + if (wl12xx_is_dummy_packet(wl, skb)) { + set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); + } else if (wl->bss_type == BSS_TYPE_AP_BSS) { u8 hlid = wl1271_tx_get_hlid(skb); skb_queue_head(&wl->links[hlid].tx_queue[q], skb); @@ -628,8 +652,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, skb = wl->tx_frames[id]; info = IEEE80211_SKB_CB(skb); - if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) { - dev_kfree_skb(skb); + if (wl12xx_is_dummy_packet(wl, skb)) { wl1271_free_tx_id(wl, id); return; } @@ -764,9 +787,7 @@ void wl1271_tx_reset(struct wl1271 *wl) wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); - if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) { - dev_kfree_skb(skb); - } else { + if (!wl12xx_is_dummy_packet(wl, skb)) { info = IEEE80211_SKB_CB(skb); info->status.rates[0].idx = -1; info->status.rates[0].count = 0; @@ -792,9 +813,7 @@ void wl1271_tx_reset(struct wl1271 *wl) wl1271_free_tx_id(wl, i); wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); - if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) { - dev_kfree_skb(skb); - } else { + if (!wl12xx_is_dummy_packet(wl, skb)) { /* * Remove private headers before passing the skb to * mac80211 diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index d6b05d980626..fc7835c4cf63 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -42,8 +42,6 @@ #define TX_HW_ATTR_TX_CMPLT_REQ BIT(12) #define TX_HW_ATTR_TX_DUMMY_REQ BIT(13) -#define TX_PKT_TYPE_DUMMY_REQ 5 - #define TX_HW_ATTR_OFST_SAVE_RETRIES 0 #define TX_HW_ATTR_OFST_HEADER_PAD 1 #define TX_HW_ATTR_OFST_SESSION_COUNTER 2 diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index c7c42b687f5e..1b430d2aec4e 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -356,6 +356,7 @@ enum wl12xx_flags { WL1271_FLAG_FW_TX_BUSY, WL1271_FLAG_AP_STARTED, WL1271_FLAG_IF_INITIALIZED, + WL1271_FLAG_DUMMY_PACKET_PENDING, }; struct wl1271_link { @@ -461,6 +462,9 @@ struct wl1271 { /* Intermediate buffer, used for packet aggregation */ u8 *aggr_buf; + /* Reusable dummy packet template */ + struct sk_buff *dummy_packet; + /* Network stack work */ struct work_struct netstack_work; -- cgit v1.2.3-58-ga151 From d2f4d47d84f8c665ab9babb2cc84d2e7872a96e1 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Thu, 31 Mar 2011 10:07:00 +0200 Subject: wl12xx: Simplify TX blocks accounting The total number of TX memory blocks may change when the dynamic memory option is enabled. The current implementation only tracks the available memory blocks, which over-complicates TX blocks accounting. By tracking the number of allocated blocks, calculation of the number of available blocks becomes simpler and cleaner. It simply equals the total number of TX memory blocks minus the allocated ones. Also, remove some unnecessary castings and use union member accesses instead. Signed-off-by: Ido Yariv Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 2 -- drivers/net/wireless/wl12xx/main.c | 48 +++++++++++++++++------------------- drivers/net/wireless/wl12xx/tx.c | 1 + drivers/net/wireless/wl12xx/wl12xx.h | 4 +-- 4 files changed, 24 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index e005aa40ef84..b277947400b5 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -1081,8 +1081,6 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl) wl1271_debug(DEBUG_TX, "available tx blocks: %d", wl->tx_blocks_available); - wl->tx_new_total = wl->tx_blocks_available; - return 0; } diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 7dce24c0b331..1feb9551ef8f 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -622,7 +622,7 @@ static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_common_status *status = &full_status->common; struct timespec ts; u32 old_tx_blk_count = wl->tx_blocks_available; - u32 total = 0; + u32 freed_blocks = 0; int i; if (wl->bss_type == BSS_TYPE_AP_BSS) { @@ -631,15 +631,6 @@ static void wl1271_fw_status(struct wl1271 *wl, } else { wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(struct wl1271_fw_sta_status), false); - - /* Update tx total blocks change */ - wl->tx_total_diff += - ((struct wl1271_fw_sta_status *)status)->tx_total - - wl->tx_new_total; - - /* Update total tx blocks */ - wl->tx_new_total = - ((struct wl1271_fw_sta_status *)status)->tx_total; } wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " @@ -651,34 +642,38 @@ static void wl1271_fw_status(struct wl1271 *wl, /* update number of available TX blocks */ for (i = 0; i < NUM_TX_QUEUES; i++) { - total += le32_to_cpu(status->tx_released_blks[i]) - - wl->tx_blocks_freed[i]; + freed_blocks += le32_to_cpu(status->tx_released_blks[i]) - + wl->tx_blocks_freed[i]; wl->tx_blocks_freed[i] = le32_to_cpu(status->tx_released_blks[i]); - } - /* - * By adding the freed blocks to tx_total_diff we are actually - * moving them to the RX pool. - */ - wl->tx_total_diff += total; + wl->tx_allocated_blocks -= freed_blocks; + + if (wl->bss_type == BSS_TYPE_AP_BSS) { + /* Update num of allocated TX blocks per link and ps status */ + wl1271_irq_update_links_status(wl, &full_status->ap); + wl->tx_blocks_available += freed_blocks; + } else { + int avail = full_status->sta.tx_total - wl->tx_allocated_blocks; - /* if we have positive difference, add the blocks to the TX pool */ - if (wl->tx_total_diff >= 0) { - wl->tx_blocks_available += wl->tx_total_diff; - wl->tx_total_diff = 0; + /* + * The FW might change the total number of TX memblocks before + * we get a notification about blocks being released. Thus, the + * available blocks calculation might yield a temporary result + * which is lower than the actual available blocks. Keeping in + * mind that only blocks that were allocated can be moved from + * TX to RX, tx_blocks_available should never decrease here. + */ + wl->tx_blocks_available = max((int)wl->tx_blocks_available, + avail); } /* if more blocks are available now, tx work can be scheduled */ if (wl->tx_blocks_available > old_tx_blk_count) clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); - /* for AP update num of allocated TX blocks per link and ps status */ - if (wl->bss_type == BSS_TYPE_AP_BSS) - wl1271_irq_update_links_status(wl, &full_status->ap); - /* update the host-chipset time offset */ getnstimeofday(&ts); wl->time_offset = (timespec_to_ns(&ts) >> 10) - @@ -1495,6 +1490,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->tx_blocks_available = 0; + wl->tx_allocated_blocks = 0; wl->tx_results_count = 0; wl->tx_packets_count = 0; wl->tx_security_last_seq = 0; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 67245ad396ea..7a3339fd3415 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -203,6 +203,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, desc->id = id; wl->tx_blocks_available -= total_blocks; + wl->tx_allocated_blocks += total_blocks; if (wl->bss_type == BSS_TYPE_AP_BSS) wl->links[hlid].allocated_blks += total_blocks; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 1b430d2aec4e..9ccbcfdd0802 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -418,10 +418,8 @@ struct wl1271 { /* Accounting for allocated / available TX blocks on HW */ u32 tx_blocks_freed[NUM_TX_QUEUES]; u32 tx_blocks_available; + u32 tx_allocated_blocks; u32 tx_results_count; - /* Indicates how many memory blocks should be moved to the RX pool */ - int tx_total_diff; - u32 tx_new_total; /* Transmitted TX packets counter for chipset interface */ u32 tx_packets_count; -- cgit v1.2.3-58-ga151 From 341b7cde6ccc60672fcd7fc84dd24a1b7c0b8d94 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Thu, 31 Mar 2011 10:07:01 +0200 Subject: wl12xx: Handle platforms without level trigger interrupts Some platforms are incapable of triggering on level interrupts. Add a platform quirks member in the platform data structure, as well as an edge interrupt quirk which can be set on such platforms. When the interrupt is requested with IRQF_TRIGGER_RISING, IRQF_ONESHOT cannot be used, as we might miss interrupts that occur after the FW status is cleared and before the threaded interrupt handler exits. Moreover, when IRQF_ONESHOT is not set, iterating more than once in the threaded interrupt handler introduces a few race conditions between this handler and the hardirq handler. Currently this is worked around by limiting the loop to one iteration only. This workaround has an impact on performance. To remove to this restriction, the race conditions will need to be addressed. Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 9 +++++++++ drivers/net/wireless/wl12xx/sdio.c | 9 ++++++++- drivers/net/wireless/wl12xx/spi.c | 9 ++++++++- drivers/net/wireless/wl12xx/wl12xx.h | 3 +++ include/linux/wl12xx.h | 4 ++++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 1feb9551ef8f..7126506611c1 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "wl12xx.h" #include "wl12xx_80211.h" @@ -719,6 +720,13 @@ irqreturn_t wl1271_irq(int irq, void *cookie) set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); cancel_work_sync(&wl->tx_work); + /* + * In case edge triggered interrupt must be used, we cannot iterate + * more than once without introducing race conditions with the hardirq. + */ + if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) + loopcount = 1; + mutex_lock(&wl->mutex); wl1271_debug(DEBUG_IRQ, "IRQ work"); @@ -3648,6 +3656,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->ap_ps_map = 0; wl->ap_fw_ps_map = 0; wl->quirks = 0; + wl->platform_quirks = 0; memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); for (i = 0; i < ACX_TX_DESCRIPTORS; i++) diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 8246e9de4306..bcd4ad7ba90d 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -220,6 +220,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, struct ieee80211_hw *hw; const struct wl12xx_platform_data *wlan_data; struct wl1271 *wl; + unsigned long irqflags; int ret; /* We are only able to handle the wlan function */ @@ -251,9 +252,15 @@ static int __devinit wl1271_probe(struct sdio_func *func, wl->irq = wlan_data->irq; wl->ref_clock = wlan_data->board_ref_clock; wl->tcxo_clock = wlan_data->board_tcxo_clock; + wl->platform_quirks = wlan_data->platform_quirks; + + if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) + irqflags = IRQF_TRIGGER_RISING; + else + irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + irqflags, DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 7b82b5f0e490..51662bb68019 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -364,6 +364,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) struct wl12xx_platform_data *pdata; struct ieee80211_hw *hw; struct wl1271 *wl; + unsigned long irqflags; int ret; pdata = spi->dev.platform_data; @@ -402,6 +403,12 @@ static int __devinit wl1271_probe(struct spi_device *spi) wl->ref_clock = pdata->board_ref_clock; wl->tcxo_clock = pdata->board_tcxo_clock; + wl->platform_quirks = pdata->platform_quirks; + + if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) + irqflags = IRQF_TRIGGER_RISING; + else + irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; wl->irq = spi->irq; if (wl->irq < 0) { @@ -411,7 +418,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) } ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + irqflags, DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 9ccbcfdd0802..fb2b79fa42b4 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -579,6 +579,9 @@ struct wl1271 { /* Quirks of specific hardware revisions */ unsigned int quirks; + + /* Platform limitations */ + unsigned int platform_quirks; }; struct wl1271_station { diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h index c1a743ea7470..4b697395326e 100644 --- a/include/linux/wl12xx.h +++ b/include/linux/wl12xx.h @@ -53,8 +53,12 @@ struct wl12xx_platform_data { bool use_eeprom; int board_ref_clock; int board_tcxo_clock; + unsigned long platform_quirks; }; +/* Platform does not support level trigger interrupts */ +#define WL12XX_PLATFORM_QUIRK_EDGE_IRQ BIT(0) + #ifdef CONFIG_WL12XX_PLATFORM_DATA int wl12xx_set_platform_data(const struct wl12xx_platform_data *data); -- cgit v1.2.3-58-ga151 From 6277ed65704d19377b0874618e5f23d64c9e71a6 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 1 Apr 2011 17:49:54 +0300 Subject: wl12xx: use kstrtoul functions Use the new kstrtoul functions instead of the deprecated strict_strtoul(). Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 2 +- drivers/net/wireless/wl12xx/main.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 8e75b09723b9..70ab1986788e 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -267,7 +267,7 @@ static ssize_t gpio_power_write(struct file *file, } buf[len] = '\0'; - ret = strict_strtoul(buf, 0, &value); + ret = kstrtoul(buf, 0, &value); if (ret < 0) { wl1271_warning("illegal value in gpio_power"); return -EINVAL; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 7126506611c1..a5a5d0133023 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3397,8 +3397,7 @@ static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev, unsigned long res; int ret; - ret = strict_strtoul(buf, 10, &res); - + ret = kstrtoul(buf, 10, &res); if (ret < 0) { wl1271_warning("incorrect value written to bt_coex_mode"); return count; -- cgit v1.2.3-58-ga151 From afb7d3cd805df7a206439a7e7b5d1167d2bb06f6 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 1 Apr 2011 20:48:02 +0300 Subject: wl12xx: move hardcoded hci_io_ds value into the conf struct Instead of hardcoding the hci_io_ds configuration that we write to the SDIO_IO_DS top registed, read it from the default configuration so that it's easier to change for different platforms. Reported-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/boot.c | 2 +- drivers/net/wireless/wl12xx/boot.h | 11 +++++++---- drivers/net/wireless/wl12xx/conf.h | 1 + drivers/net/wireless/wl12xx/main.c | 1 + 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index b5ec2c2b6f78..2b0cf85788b3 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -779,7 +779,7 @@ int wl1271_load_firmware(struct wl1271 *wl) * to upload_fw) */ if (wl->chip.id == CHIP_ID_1283_PG20) - wl1271_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); + wl1271_top_reg_write(wl, SDIO_IO_DS, wl->conf.hci_io_ds); ret = wl1271_boot_upload_firmware(wl); if (ret < 0) diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h index d9de64ac1442..e8f8255bbabe 100644 --- a/drivers/net/wireless/wl12xx/boot.h +++ b/drivers/net/wireless/wl12xx/boot.h @@ -117,10 +117,13 @@ struct wl1271_static_data { #define SDIO_IO_DS 0xd14 /* SDIO/wSPI DS configuration values */ -#define HCI_IO_DS_8MA 0 -#define HCI_IO_DS_4MA 1 /* default */ -#define HCI_IO_DS_6MA 2 -#define HCI_IO_DS_2MA 3 +enum { + HCI_IO_DS_8MA = 0, + HCI_IO_DS_4MA = 1, /* default */ + HCI_IO_DS_6MA = 2, + HCI_IO_DS_2MA = 3, +}; + /* end PLL configuration algorithm for wl128x */ #endif diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 743bd0beb63b..52269d4d3623 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -1206,6 +1206,7 @@ struct conf_drv_settings { struct conf_ht_setting ht; struct conf_memory_settings mem_wl127x; struct conf_memory_settings mem_wl128x; + u8 hci_io_ds; }; #endif diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index a5a5d0133023..732fd21beafb 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -319,6 +319,7 @@ static struct conf_drv_settings default_conf = { .min_req_rx_blocks = 22, .tx_min = 27, }, + .hci_io_ds = HCI_IO_DS_6MA, }; static void __wl1271_op_remove_interface(struct wl1271 *wl); -- cgit v1.2.3-58-ga151 From 4ec23d6e136c890806f0e00bcf24e2e3a242b30a Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 1 Apr 2011 20:55:01 +0300 Subject: wl12xx: remove unused conf_radio_params structure This structure has not been used anymore since commit e6b190ff3c2f4e4859502c41fa17b5c595e82000. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/conf.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 52269d4d3623..6c9e3a673e6c 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -1020,15 +1020,6 @@ enum single_dual_band_enum { #define CONF_NUMBER_OF_CHANNELS_2_4 14 #define CONF_NUMBER_OF_CHANNELS_5 35 -struct conf_radio_parms { - /* - * FEM parameter set to use - * - * Range: 0 or 1 - */ - u8 fem; -}; - struct conf_itrim_settings { /* enable dco itrim */ u8 enable; -- cgit v1.2.3-58-ga151 From cf27d8677515441602f5e4e40f90448e964504b8 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 1 Apr 2011 21:08:23 +0300 Subject: wl12xx: fix sparse warning about undeclared wl12xx_alloc_dummy_packet Fix sparse warning: CHECK drivers/net/wireless/wl12xx/main.c drivers/net/wireless/wl12xx/main.c:1246:17: warning: symbol 'wl12xx_alloc_dummy_packet' was not declared. Should it be static? Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 732fd21beafb..866453bc1d1f 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1243,7 +1243,7 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl) */ #define TOTAL_TX_DUMMY_PACKET_SIZE (ALIGN(1400, 512)) -struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) +static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) { struct sk_buff *skb; struct ieee80211_hdr_3addr *hdr; -- cgit v1.2.3-58-ga151 From cbc6a6ed0900aed789b5ca77192845f2f987af70 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Wed, 13 Apr 2011 21:40:45 +0200 Subject: rfkill: Regulator consumer driver for rfkill Add a regulator consumer driver for rfkill to enable controlling radio transmitters connected to voltage regulators using the regulator framework. A new "vrfkill" virtual supply is provided to use in platform code. Signed-off-by: Guiming Zhuo Signed-off-by: Antonio Ospite Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/rfkill-regulator.h | 48 ++++++++++++ net/rfkill/Kconfig | 11 +++ net/rfkill/Makefile | 1 + net/rfkill/rfkill-regulator.c | 164 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 224 insertions(+) create mode 100644 include/linux/rfkill-regulator.h create mode 100644 net/rfkill/rfkill-regulator.c diff --git a/include/linux/rfkill-regulator.h b/include/linux/rfkill-regulator.h new file mode 100644 index 000000000000..aca36bc83315 --- /dev/null +++ b/include/linux/rfkill-regulator.h @@ -0,0 +1,48 @@ +/* + * rfkill-regulator.c - Regulator consumer driver for rfkill + * + * Copyright (C) 2009 Guiming Zhuo + * Copyright (C) 2011 Antonio Ospite + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __LINUX_RFKILL_REGULATOR_H +#define __LINUX_RFKILL_REGULATOR_H + +/* + * Use "vrfkill" as supply id when declaring the regulator consumer: + * + * static struct regulator_consumer_supply pcap_regulator_V6_consumers [] = { + * { .dev_name = "rfkill-regulator.0", .supply = "vrfkill" }, + * }; + * + * If you have several regulator driven rfkill, you can append a numerical id to + * .dev_name as done above, and use the same id when declaring the platform + * device: + * + * static struct rfkill_regulator_platform_data ezx_rfkill_bt_data = { + * .name = "ezx-bluetooth", + * .type = RFKILL_TYPE_BLUETOOTH, + * }; + * + * static struct platform_device a910_rfkill = { + * .name = "rfkill-regulator", + * .id = 0, + * .dev = { + * .platform_data = &ezx_rfkill_bt_data, + * }, + * }; + */ + +#include + +struct rfkill_regulator_platform_data { + char *name; /* the name for the rfkill switch */ + enum rfkill_type type; /* the type as specified in rfkill.h */ +}; + +#endif /* __LINUX_RFKILL_REGULATOR_H */ diff --git a/net/rfkill/Kconfig b/net/rfkill/Kconfig index 7fce6dfd2180..48464ca13b24 100644 --- a/net/rfkill/Kconfig +++ b/net/rfkill/Kconfig @@ -22,3 +22,14 @@ config RFKILL_INPUT depends on RFKILL depends on INPUT = y || RFKILL = INPUT default y if !EXPERT + +config RFKILL_REGULATOR + tristate "Generic rfkill regulator driver" + depends on RFKILL || !RFKILL + depends on REGULATOR + help + This options enable controlling radio transmitters connected to + voltage regulator using the regulator framework. + + To compile this driver as a module, choose M here: the module will + be called rfkill-regulator. diff --git a/net/rfkill/Makefile b/net/rfkill/Makefile index 662105352691..d9a5a58ffd8c 100644 --- a/net/rfkill/Makefile +++ b/net/rfkill/Makefile @@ -5,3 +5,4 @@ rfkill-y += core.o rfkill-$(CONFIG_RFKILL_INPUT) += input.o obj-$(CONFIG_RFKILL) += rfkill.o +obj-$(CONFIG_RFKILL_REGULATOR) += rfkill-regulator.o diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c new file mode 100644 index 000000000000..18dc512a10f3 --- /dev/null +++ b/net/rfkill/rfkill-regulator.c @@ -0,0 +1,164 @@ +/* + * rfkill-regulator.c - Regulator consumer driver for rfkill + * + * Copyright (C) 2009 Guiming Zhuo + * Copyright (C) 2011 Antonio Ospite + * + * Implementation inspired by leds-regulator driver. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +struct rfkill_regulator_data { + struct rfkill *rf_kill; + bool reg_enabled; + + struct regulator *vcc; +}; + +static int rfkill_regulator_set_block(void *data, bool blocked) +{ + struct rfkill_regulator_data *rfkill_data = data; + + pr_debug("%s: blocked: %d\n", __func__, blocked); + + if (blocked) { + if (rfkill_data->reg_enabled) { + regulator_disable(rfkill_data->vcc); + rfkill_data->reg_enabled = 0; + } + } else { + if (!rfkill_data->reg_enabled) { + regulator_enable(rfkill_data->vcc); + rfkill_data->reg_enabled = 1; + } + } + + pr_debug("%s: regulator_is_enabled after set_block: %d\n", __func__, + regulator_is_enabled(rfkill_data->vcc)); + + return 0; +} + +struct rfkill_ops rfkill_regulator_ops = { + .set_block = rfkill_regulator_set_block, +}; + +static int __devinit rfkill_regulator_probe(struct platform_device *pdev) +{ + struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data; + struct rfkill_regulator_data *rfkill_data; + struct regulator *vcc; + struct rfkill *rf_kill; + int ret = 0; + + if (pdata == NULL) { + dev_err(&pdev->dev, "no platform data\n"); + return -ENODEV; + } + + if (pdata->name == NULL || pdata->type == 0) { + dev_err(&pdev->dev, "invalid name or type in platform data\n"); + return -EINVAL; + } + + vcc = regulator_get_exclusive(&pdev->dev, "vrfkill"); + if (IS_ERR(vcc)) { + dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name); + ret = PTR_ERR(vcc); + goto out; + } + + rfkill_data = kzalloc(sizeof(*rfkill_data), GFP_KERNEL); + if (rfkill_data == NULL) { + ret = -ENOMEM; + goto err_data_alloc; + } + + rf_kill = rfkill_alloc(pdata->name, &pdev->dev, + pdata->type, + &rfkill_regulator_ops, rfkill_data); + if (rf_kill == NULL) { + dev_err(&pdev->dev, "Cannot alloc rfkill device\n"); + ret = -ENOMEM; + goto err_rfkill_alloc; + } + + if (regulator_is_enabled(vcc)) { + dev_dbg(&pdev->dev, "Regulator already enabled\n"); + rfkill_data->reg_enabled = 1; + } + rfkill_data->vcc = vcc; + rfkill_data->rf_kill = rf_kill; + + ret = rfkill_register(rf_kill); + if (ret) { + dev_err(&pdev->dev, "Cannot register rfkill device\n"); + goto err_rfkill_register; + } + + platform_set_drvdata(pdev, rfkill_data); + dev_info(&pdev->dev, "%s initialized\n", pdata->name); + + return 0; + +err_rfkill_register: + rfkill_destroy(rf_kill); +err_rfkill_alloc: + kfree(rfkill_data); +err_data_alloc: + regulator_put(vcc); +out: + return ret; +} + +static int __devexit rfkill_regulator_remove(struct platform_device *pdev) +{ + struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev); + struct rfkill *rf_kill = rfkill_data->rf_kill; + + rfkill_unregister(rf_kill); + rfkill_destroy(rf_kill); + regulator_put(rfkill_data->vcc); + kfree(rfkill_data); + + return 0; +} + +static struct platform_driver rfkill_regulator_driver = { + .probe = rfkill_regulator_probe, + .remove = __devexit_p(rfkill_regulator_remove), + .driver = { + .name = "rfkill-regulator", + .owner = THIS_MODULE, + }, +}; + +static int __init rfkill_regulator_init(void) +{ + return platform_driver_register(&rfkill_regulator_driver); +} +module_init(rfkill_regulator_init); + +static void __exit rfkill_regulator_exit(void) +{ + platform_driver_unregister(&rfkill_regulator_driver); +} +module_exit(rfkill_regulator_exit); + +MODULE_AUTHOR("Guiming Zhuo "); +MODULE_AUTHOR("Antonio Ospite "); +MODULE_DESCRIPTION("Regulator consumer driver for rfkill"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rfkill-regulator"); -- cgit v1.2.3-58-ga151 From 2290a9c35df271cc33601b69e7836fa288e2fc7d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 14 Apr 2011 14:55:36 -0700 Subject: ath: fix 0x6C for beaconing/passive scan flags based on country IE The 0x6C regulatory domain is just like the 0x6A regulatory domain but differs in that 0x6C will allow adhoc and active scan on its channels only if we are associated to an AP with a country IE that allows those channels. The ath_reg_apply_beaconing_flags() does just this -- we respect the manufacturer's intent on only enabling beaconing modes of operation if and only if blessed by the country IE. Cc: David Quan Cc: Senthil Balasubramanian Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 7e3b29015dda..02b896208b1a 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -334,6 +334,7 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy, case 0x63: case 0x66: case 0x67: + case 0x6C: ath_reg_apply_beaconing_flags(wiphy, initiator); break; case 0x68: -- cgit v1.2.3-58-ga151 From 00bca7e2f2b58b93ce408e92d18a8c42bbe8d6e5 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 15 Apr 2011 12:28:52 +0530 Subject: ath9k_htc: Add debugfs support to change debug mask Signed-off-by: Rajkumar Manoharan Acked-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 49 ++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index cc5d0a4b9da2..852cdcfbcbb6 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -366,6 +366,7 @@ struct ath9k_debug { struct dentry *debugfs_recv; struct dentry *debugfs_slot; struct dentry *debugfs_queue; + struct dentry *debugfs_debug; struct ath_tx_stats tx_stats; struct ath_rx_stats rx_stats; }; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 8d0de60e0c27..7394a1b9882a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -435,6 +435,47 @@ static const struct file_operations fops_queue = { .llseek = default_llseek, }; +static ssize_t read_file_debug(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + struct ath_common *common = ath9k_hw_common(priv->ah); + char buf[32]; + unsigned int len; + + len = sprintf(buf, "0x%08x\n", common->debug_mask); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_debug(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + struct ath_common *common = ath9k_hw_common(priv->ah); + unsigned long mask; + char buf[32]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + if (strict_strtoul(buf, 0, &mask)) + return -EINVAL; + + common->debug_mask = mask; + return count; +} + +static const struct file_operations fops_debug = { + .read = read_file_debug, + .write = write_file_debug, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + int ath9k_htc_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -493,6 +534,13 @@ int ath9k_htc_init_debug(struct ath_hw *ah) if (!priv->debug.debugfs_queue) goto err; + priv->debug.debugfs_debug = debugfs_create_file("debug", + S_IRUSR | S_IWUSR, + priv->debug.debugfs_phy, + priv, &fops_debug); + if (!priv->debug.debugfs_debug) + goto err; + return 0; err: @@ -512,6 +560,7 @@ void ath9k_htc_exit_debug(struct ath_hw *ah) debugfs_remove(priv->debug.debugfs_tgt_int_stats); debugfs_remove(priv->debug.debugfs_tgt_tx_stats); debugfs_remove(priv->debug.debugfs_tgt_rx_stats); + debugfs_remove(priv->debug.debugfs_debug); debugfs_remove(priv->debug.debugfs_phy); } -- cgit v1.2.3-58-ga151 From e5facc75fa9104f074c4610437a9c717c9e5ecde Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 15 Apr 2011 15:42:24 +0530 Subject: ath9k_htc: Cleanup HTC debugfs Move the ath9k_htc debugfs under ieee80211 to be inline with ath9k driver and it also helps to simplify debug code. Signed-off-by: Rajkumar Manoharan Acked-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 14 --- drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 113 +++++-------------------- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 37 ++------ 3 files changed, 27 insertions(+), 137 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 852cdcfbcbb6..48a885575085 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -359,14 +359,6 @@ struct ath_rx_stats { struct ath9k_debug { struct dentry *debugfs_phy; - struct dentry *debugfs_tgt_int_stats; - struct dentry *debugfs_tgt_tx_stats; - struct dentry *debugfs_tgt_rx_stats; - struct dentry *debugfs_xmit; - struct dentry *debugfs_recv; - struct dentry *debugfs_slot; - struct dentry *debugfs_queue; - struct dentry *debugfs_debug; struct ath_tx_stats tx_stats; struct ath_rx_stats rx_stats; }; @@ -613,15 +605,9 @@ void ath9k_htc_suspend(struct htc_target *htc_handle); int ath9k_htc_resume(struct htc_target *htc_handle); #endif #ifdef CONFIG_ATH9K_HTC_DEBUGFS -int ath9k_htc_debug_create_root(void); -void ath9k_htc_debug_remove_root(void); int ath9k_htc_init_debug(struct ath_hw *ah); -void ath9k_htc_exit_debug(struct ath_hw *ah); #else -static inline int ath9k_htc_debug_create_root(void) { return 0; }; -static inline void ath9k_htc_debug_remove_root(void) {}; static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; -static inline void ath9k_htc_exit_debug(struct ath_hw *ah) {}; #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ #endif /* HTC_H */ diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 7394a1b9882a..eca777497fe5 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -16,8 +16,6 @@ #include "htc.h" -static struct dentry *ath9k_debugfs_root; - static int ath9k_debugfs_open(struct inode *inode, struct file *file) { file->private_data = inode->i_private; @@ -481,100 +479,27 @@ int ath9k_htc_init_debug(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - if (!ath9k_debugfs_root) - return -ENOENT; - - priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy), - ath9k_debugfs_root); + priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME, + priv->hw->wiphy->debugfsdir); if (!priv->debug.debugfs_phy) - goto err; - - priv->debug.debugfs_tgt_int_stats = debugfs_create_file("tgt_int_stats", - S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_tgt_int_stats); - if (!priv->debug.debugfs_tgt_int_stats) - goto err; - - priv->debug.debugfs_tgt_tx_stats = debugfs_create_file("tgt_tx_stats", - S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_tgt_tx_stats); - if (!priv->debug.debugfs_tgt_tx_stats) - goto err; - - priv->debug.debugfs_tgt_rx_stats = debugfs_create_file("tgt_rx_stats", - S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_tgt_rx_stats); - if (!priv->debug.debugfs_tgt_rx_stats) - goto err; - - priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_xmit); - if (!priv->debug.debugfs_xmit) - goto err; - - priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_recv); - if (!priv->debug.debugfs_recv) - goto err; - - priv->debug.debugfs_slot = debugfs_create_file("slot", S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_slot); - if (!priv->debug.debugfs_slot) - goto err; - - priv->debug.debugfs_queue = debugfs_create_file("queue", S_IRUSR, - priv->debug.debugfs_phy, - priv, &fops_queue); - if (!priv->debug.debugfs_queue) - goto err; - - priv->debug.debugfs_debug = debugfs_create_file("debug", - S_IRUSR | S_IWUSR, - priv->debug.debugfs_phy, - priv, &fops_debug); - if (!priv->debug.debugfs_debug) - goto err; - - return 0; - -err: - ath9k_htc_exit_debug(ah); - return -ENOMEM; -} - -void ath9k_htc_exit_debug(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - - debugfs_remove(priv->debug.debugfs_queue); - debugfs_remove(priv->debug.debugfs_slot); - debugfs_remove(priv->debug.debugfs_recv); - debugfs_remove(priv->debug.debugfs_xmit); - debugfs_remove(priv->debug.debugfs_tgt_int_stats); - debugfs_remove(priv->debug.debugfs_tgt_tx_stats); - debugfs_remove(priv->debug.debugfs_tgt_rx_stats); - debugfs_remove(priv->debug.debugfs_debug); - debugfs_remove(priv->debug.debugfs_phy); -} + return -ENOMEM; -int ath9k_htc_debug_create_root(void) -{ - ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (!ath9k_debugfs_root) - return -ENOENT; + debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy, + priv, &fops_tgt_int_stats); + debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy, + priv, &fops_tgt_tx_stats); + debugfs_create_file("tgt_rx_stats", S_IRUSR, priv->debug.debugfs_phy, + priv, &fops_tgt_rx_stats); + debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy, + priv, &fops_xmit); + debugfs_create_file("recv", S_IRUSR, priv->debug.debugfs_phy, + priv, &fops_recv); + debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy, + priv, &fops_slot); + debugfs_create_file("queue", S_IRUSR, priv->debug.debugfs_phy, + priv, &fops_queue); + debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy, + priv, &fops_debug); return 0; } - -void ath9k_htc_debug_remove_root(void) -{ - debugfs_remove(ath9k_debugfs_root); - ath9k_debugfs_root = NULL; -} diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 22736eb901cf..06e043bffaf4 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -140,7 +140,6 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) { - ath9k_htc_exit_debug(priv->ah); ath9k_hw_deinit(priv->ah); kfree(priv->ah); priv->ah = NULL; @@ -700,12 +699,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, goto err_hw; } - ret = ath9k_htc_init_debug(ah); - if (ret) { - ath_err(common, "Unable to create debugfs files\n"); - goto err_debug; - } - ret = ath9k_init_queues(priv); if (ret) goto err_queues; @@ -725,8 +718,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, return 0; err_queues: - ath9k_htc_exit_debug(ah); -err_debug: ath9k_hw_deinit(ah); err_hw: @@ -867,6 +858,12 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, goto err_world; } + error = ath9k_htc_init_debug(priv->ah); + if (error) { + ath_err(common, "Unable to create debugfs files\n"); + goto err_world; + } + ath_dbg(common, ATH_DBG_CONFIG, "WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, " "BE:%d, BK:%d, VI:%d, VO:%d\n", @@ -987,38 +984,20 @@ int ath9k_htc_resume(struct htc_target *htc_handle) static int __init ath9k_htc_init(void) { - int error; - - error = ath9k_htc_debug_create_root(); - if (error < 0) { - printk(KERN_ERR - "ath9k_htc: Unable to create debugfs root: %d\n", - error); - goto err_dbg; - } - - error = ath9k_hif_usb_init(); - if (error < 0) { + if (ath9k_hif_usb_init() < 0) { printk(KERN_ERR "ath9k_htc: No USB devices found," " driver not installed.\n"); - error = -ENODEV; - goto err_usb; + return -ENODEV; } return 0; - -err_usb: - ath9k_htc_debug_remove_root(); -err_dbg: - return error; } module_init(ath9k_htc_init); static void __exit ath9k_htc_exit(void) { ath9k_hif_usb_exit(); - ath9k_htc_debug_remove_root(); printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); } module_exit(ath9k_htc_exit); -- cgit v1.2.3-58-ga151 From 0477ad72a12d4ee3f588de9349012948ea25702b Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 15 Apr 2011 19:23:11 +0400 Subject: iwlegacy: use pci_dev->revision Commit be663ab67077fac8e23eb8e231a8c1c94cb32e54 (iwlwifi: split the drivers for agn and legacy devices 3945/4965) added code to read the 4965's revision ID from the PCI configuration register while it's already stored by PCI subsystem in the 'revision' field of 'struct pci_dev'... Signed-off-by: Sergei Shtylyov Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl4965-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c index 91b3d8b9d7a5..dd90619fdce7 100644 --- a/drivers/net/wireless/iwlegacy/iwl4965-base.c +++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c @@ -3179,7 +3179,7 @@ static void iwl4965_hw_detect(struct iwl_priv *priv) { priv->hw_rev = _iwl_legacy_read32(priv, CSR_HW_REV); priv->hw_wa_rev = _iwl_legacy_read32(priv, CSR_HW_REV_WA_REG); - pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id); + priv->rev_id = priv->pci_dev->revision; IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id); } -- cgit v1.2.3-58-ga151 From 7762bb02ce13c191e0a2da159bcb8d9b374b88c4 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 15 Apr 2011 16:20:05 -0700 Subject: mac80211: fix debugfs printk format warning Fix printf() format warning (tm_year is long int): net/mac80211/debugfs_sta.c:113: warning: format '%d' expects type 'int', but argument 4 has type 'long int' Signed-off-by: Randy Dunlap Signed-off-by: John W. Linville --- net/mac80211/debugfs_sta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index c008232731eb..a01d2137fddc 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -108,7 +108,7 @@ static ssize_t sta_connected_time_read(struct file *file, char __user *userbuf, result.tm_year -= 70; result.tm_mday -= 1; res = scnprintf(buf, sizeof(buf), - "years - %d\nmonths - %d\ndays - %d\nclock - %d:%d:%d\n\n", + "years - %ld\nmonths - %d\ndays - %d\nclock - %d:%d:%d\n\n", result.tm_year, result.tm_mon, result.tm_mday, result.tm_hour, result.tm_min, result.tm_sec); return simple_read_from_buffer(userbuf, count, ppos, buf, res); -- cgit v1.2.3-58-ga151 From 636c4598499eeacce0893dc8d91113b904bd531e Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Fri, 15 Apr 2011 20:50:40 -0700 Subject: mwifiex: remove redundant local variables and comments Remove some local variables (mainly function return values) that are used only once. Also, one dummy function and some wordy comments are removed. Signed-off-by: Yogesh Ashok Powar Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n_rxreorder.c | 24 +---- drivers/net/wireless/mwifiex/cfg80211.c | 131 +++++++++------------------ drivers/net/wireless/mwifiex/cfp.c | 8 +- drivers/net/wireless/mwifiex/init.c | 5 +- drivers/net/wireless/mwifiex/join.c | 50 +++------- drivers/net/wireless/mwifiex/main.c | 19 ++-- drivers/net/wireless/mwifiex/scan.c | 23 ++--- drivers/net/wireless/mwifiex/sdio.c | 16 +--- drivers/net/wireless/mwifiex/sta_ioctl.c | 85 ++++------------- drivers/net/wireless/mwifiex/sta_tx.c | 6 +- drivers/net/wireless/mwifiex/txrx.c | 4 +- drivers/net/wireless/mwifiex/util.c | 6 +- drivers/net/wireless/mwifiex/wmm.c | 5 +- 13 files changed, 105 insertions(+), 277 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index 755e5d533c03..a93c03fdea82 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -26,19 +26,6 @@ #include "11n.h" #include "11n_rxreorder.h" -/* - * This function processes a received packet and forwards - * it to the kernel/upper layer. - */ -static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - - ret = mwifiex_process_rx_packet(adapter, (struct sk_buff *) payload); - return ret; -} - /* * This function dispatches all packets in the Rx reorder table. * @@ -51,7 +38,7 @@ mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv, struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr, int start_win) { - int no_pkt_to_send, i, xchg; + int no_pkt_to_send, i; void *rx_tmp_ptr = NULL; unsigned long flags; @@ -68,7 +55,7 @@ mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv, } spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); if (rx_tmp_ptr) - mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); + mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr); } spin_lock_irqsave(&priv->rx_pkt_lock, flags); @@ -76,8 +63,7 @@ mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv, * We don't have a circular buffer, hence use rotation to simulate * circular buffer */ - xchg = rx_reor_tbl_ptr->win_size - no_pkt_to_send; - for (i = 0; i < xchg; ++i) { + for (i = 0; i < rx_reor_tbl_ptr->win_size - no_pkt_to_send; ++i) { rx_reor_tbl_ptr->rx_reorder_ptr[i] = rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i]; rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i] = NULL; @@ -114,7 +100,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv, rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i]; rx_reor_tbl_ptr->rx_reorder_ptr[i] = NULL; spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); + mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr); } spin_lock_irqsave(&priv->rx_pkt_lock, flags); @@ -429,7 +415,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, tid, ta); if (!rx_reor_tbl_ptr) { if (pkt_type != PKT_TYPE_BAR) - mwifiex_11n_dispatch_pkt(priv, payload); + mwifiex_process_rx_packet(priv->adapter, payload); return 0; } start_win = rx_reor_tbl_ptr->start_win; diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 74b6cf20da04..b99ae2677d78 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -34,22 +34,17 @@ static int mwifiex_cfg80211_channel_type_to_mwifiex_channels(enum nl80211_channel_type channel_type) { - int channel; switch (channel_type) { case NL80211_CHAN_NO_HT: case NL80211_CHAN_HT20: - channel = NO_SEC_CHANNEL; - break; + return NO_SEC_CHANNEL; case NL80211_CHAN_HT40PLUS: - channel = SEC_CHANNEL_ABOVE; - break; + return SEC_CHANNEL_ABOVE; case NL80211_CHAN_HT40MINUS: - channel = SEC_CHANNEL_BELOW; - break; + return SEC_CHANNEL_BELOW; default: - channel = NO_SEC_CHANNEL; + return NO_SEC_CHANNEL; } - return channel; } /* @@ -64,21 +59,16 @@ mwifiex_cfg80211_channel_type_to_mwifiex_channels(enum nl80211_channel_type static enum nl80211_channel_type mwifiex_channels_to_cfg80211_channel_type(int channel_type) { - int channel; switch (channel_type) { case NO_SEC_CHANNEL: - channel = NL80211_CHAN_HT20; - break; + return NL80211_CHAN_HT20; case SEC_CHANNEL_ABOVE: - channel = NL80211_CHAN_HT40PLUS; - break; + return NL80211_CHAN_HT40PLUS; case SEC_CHANNEL_BELOW: - channel = NL80211_CHAN_HT40MINUS; - break; + return NL80211_CHAN_HT40MINUS; default: - channel = NL80211_CHAN_HT20; + return NL80211_CHAN_HT20; } - return channel; } /* @@ -117,10 +107,8 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool pairwise, const u8 *mac_addr) { struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - int ret = 0; - ret = mwifiex_set_encode(priv, NULL, 0, key_index, 1); - if (ret) { + if (mwifiex_set_encode(priv, NULL, 0, key_index, 1)) { wiphy_err(wiphy, "deleting the crypto keys\n"); return -EFAULT; } @@ -137,7 +125,6 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type, int dbm) { - int ret = 0; struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); struct mwifiex_power_cfg power_cfg; @@ -148,9 +135,7 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, power_cfg.is_power_auto = 1; } - ret = mwifiex_set_tx_power(priv, &power_cfg); - - return ret; + return mwifiex_set_tx_power(priv, &power_cfg); } /* @@ -163,7 +148,6 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout) { - int ret = 0; struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); u32 ps_mode; @@ -173,9 +157,8 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy, " for IEEE power save\n"); ps_mode = enabled; - ret = mwifiex_drv_set_power(priv, &ps_mode); - return ret; + return mwifiex_drv_set_power(priv, &ps_mode); } /* @@ -187,18 +170,15 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, bool multicast) { struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - int ret; /* Return if WEP key not configured */ if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED) return 0; - ret = mwifiex_set_encode(priv, NULL, 0, key_index, 0); - - wiphy_dbg(wiphy, "info: set default Tx key index\n"); - - if (ret) + if (mwifiex_set_encode(priv, NULL, 0, key_index, 0)) { + wiphy_err(wiphy, "set default Tx key index\n"); return -EFAULT; + } return 0; } @@ -212,15 +192,12 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, struct key_params *params) { struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - int ret = 0; - ret = mwifiex_set_encode(priv, params->key, params->key_len, - key_index, 0); - - wiphy_dbg(wiphy, "info: crypto keys added\n"); - - if (ret) + if (mwifiex_set_encode(priv, params->key, params->key_len, + key_index, 0)) { + wiphy_err(wiphy, "crypto keys added\n"); return -EFAULT; + } return 0; } @@ -245,7 +222,6 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg; - int ret = 0; /* Set country code */ domain_info->country_code[0] = priv->country_code[0]; @@ -300,13 +276,14 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) } domain_info->no_of_triplet = no_of_triplet; - /* Send cmd to FW to set domain info */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, - HostCmd_ACT_GEN_SET, 0, NULL); - if (ret) + + if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, + HostCmd_ACT_GEN_SET, 0, NULL)) { wiphy_err(wiphy, "11D: setting domain info in FW\n"); + return -1; + } - return ret; + return 0; } /* @@ -356,7 +333,6 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, enum nl80211_channel_type channel_type) { struct mwifiex_chan_freq_power cfp; - int ret = 0; struct mwifiex_ds_band_cfg band_cfg; u32 config_bands = 0; struct wiphy *wiphy = priv->wdev->wiphy; @@ -375,14 +351,14 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, band_cfg.config_bands = config_bands; band_cfg.adhoc_start_band = config_bands; } - /* Set channel offset */ + band_cfg.sec_chan_offset = mwifiex_cfg80211_channel_type_to_mwifiex_channels (channel_type); - ret = mwifiex_set_radio_band_cfg(priv, &band_cfg); - if (ret) + if (mwifiex_set_radio_band_cfg(priv, &band_cfg)) return -EFAULT; + mwifiex_send_domain_info_cmd_fw(wiphy); } @@ -390,20 +366,16 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, "mode %d\n", config_bands, band_cfg.sec_chan_offset, priv->bss_mode); if (!chan) - return ret; + return 0; memset(&cfp, 0, sizeof(cfp)); cfp.freq = chan->center_freq; - /* Convert frequency to channel */ cfp.channel = ieee80211_frequency_to_channel(chan->center_freq); - ret = mwifiex_bss_set_channel(priv, &cfp); - if (ret) + if (mwifiex_bss_set_channel(priv, &cfp)) return -EFAULT; - ret = mwifiex_drv_change_adhoc_chan(priv, cfp.channel); - - return ret; + return mwifiex_drv_change_adhoc_chan(priv, cfp.channel); } /* @@ -459,17 +431,12 @@ mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) static int mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr) { - int ret = 0; - if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE) rts_thr = MWIFIEX_RTS_MAX_VALUE; - /* Send request to firmware */ - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, + return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, HostCmd_ACT_GEN_SET, RTS_THRESH_I, &rts_thr); - - return ret; } /* @@ -485,8 +452,11 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) int ret = 0; - if (changed & WIPHY_PARAM_RTS_THRESHOLD) + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { ret = mwifiex_set_rts(priv, wiphy->rts_threshold); + if (ret) + return ret; + } if (changed & WIPHY_PARAM_FRAG_THRESHOLD) ret = mwifiex_set_frag(priv, wiphy->frag_threshold); @@ -598,7 +568,6 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, u8 *mac, struct station_info *sinfo) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - int ret = 0; mwifiex_dump_station_info(priv, sinfo); @@ -607,10 +576,7 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, if (memcmp(mac, priv->cfg_bssid, ETH_ALEN)) return -ENOENT; - - ret = mwifiex_dump_station_info(priv, sinfo); - - return ret; + return mwifiex_dump_station_info(priv, sinfo); } /* Supported rates to be advertised to the cfg80211 */ @@ -749,15 +715,13 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, */ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) { - int ret = 0; struct ieee80211_channel *chan; struct mwifiex_bss_info bss_info; int ie_len = 0; u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)]; - ret = mwifiex_get_bss_info(priv, &bss_info); - if (ret) - return ret; + if (mwifiex_get_bss_info(priv, &bss_info)) + return -1; ie_buf[0] = WLAN_EID_SSID; ie_buf[1] = bss_info.ssid.ssid_len; @@ -776,7 +740,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) 0, ie_buf, ie_len, 0, GFP_KERNEL); memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); - return ret; + return 0; } /* @@ -805,9 +769,8 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *scan_table; int i, j; struct ieee80211_channel *chan; - u8 *ie, *tmp, *ie_buf; + u8 *ie, *ie_buf; u32 ie_len; - u64 ts = 0; u8 *beacon; int beacon_size; u8 element_id, element_len; @@ -889,9 +852,9 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, case WLAN_EID_BSS_AC_ACCESS_DELAY: ie[0] = element_id; ie[1] = element_len; - tmp = (u8 *) beacon; memcpy(&ie[sizeof(struct ieee_types_header)], - tmp + sizeof(struct ieee_types_header), + (u8 *) beacon + + sizeof(struct ieee_types_header), element_len); ie_len += ie[1] + sizeof(struct ieee_types_header); @@ -908,7 +871,7 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, scan_table[i].freq); cfg80211_inform_bss(priv->wdev->wiphy, chan, scan_table[i].mac_address, - ts, scan_table[i].cap_info_bitmap, + 0, scan_table[i].cap_info_bitmap, scan_table[i].beacon_period, ie_buf, ie_len, scan_table[i].rssi, GFP_KERNEL); @@ -941,9 +904,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, struct mwifiex_802_11_ssid req_ssid; struct mwifiex_ssid_bssid ssid_bssid; int ret = 0; - int auth_type = 0, pairwise_encrypt_mode = 0; - int group_encrypt_mode = 0; - int alg_is_wep = 0; + int auth_type = 0; memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid)); memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); @@ -1009,9 +970,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len); if (sme->key) { - alg_is_wep = mwifiex_is_alg_wep(pairwise_encrypt_mode) - | mwifiex_is_alg_wep(group_encrypt_mode); - if (alg_is_wep) { + if (mwifiex_is_alg_wep(0) | mwifiex_is_alg_wep(0)) { dev_dbg(priv->adapter->dev, "info: setting wep encryption" " with key len %d\n", sme->key_len); diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c index bb73cfe14aeb..d0cada5a29a0 100644 --- a/drivers/net/wireless/mwifiex/cfp.c +++ b/drivers/net/wireless/mwifiex/cfp.c @@ -145,16 +145,12 @@ u8 mwifiex_data_rate_to_index(u32 rate) */ u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, u8 *rates) { - u32 k; - if (!priv->media_connected) - k = mwifiex_get_supported_rates(priv, rates); + return mwifiex_get_supported_rates(priv, rates); else - k = mwifiex_copy_rates(rates, 0, + return mwifiex_copy_rates(rates, 0, priv->curr_bss_params.data_rates, priv->curr_bss_params.num_of_rates); - - return k; } /* diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 1b79a5ac9214..fc2c0c5728d9 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -71,7 +71,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) static int mwifiex_init_priv(struct mwifiex_private *priv) { u32 i; - int ret = 0; priv->media_connected = false; memset(priv->curr_addr, 0xff, ETH_ALEN); @@ -139,9 +138,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) priv->scan_block = false; - ret = mwifiex_add_bss_prio_tbl(priv); - - return ret; + return mwifiex_add_bss_prio_tbl(priv); } /* diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 60d25c690c07..8e1cb4b3fbea 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -749,7 +749,7 @@ int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, void *data_buf) { - int ret = 0, rsn_ie_len = 0; + int rsn_ie_len = 0; struct mwifiex_adapter *adapter = priv->adapter; struct host_cmd_ds_802_11_ad_hoc_start *adhoc_start = &cmd->params.adhoc_start; @@ -879,11 +879,9 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, mwifiex_get_active_data_rates(priv, adhoc_start->DataRate); if ((adapter->adhoc_start_band & BAND_G) && (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) { - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, + if (mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, HostCmd_ACT_GEN_SET, 0, - &priv->curr_pkt_filter); - - if (ret) { + &priv->curr_pkt_filter)) { dev_err(adapter->dev, "ADHOC_S_CMD: G Protection config failed\n"); return -1; @@ -1039,7 +1037,7 @@ int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, void *data_buf) { - int ret = 0, rsn_ie_len = 0; + int rsn_ie_len = 0; struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join = &cmd->params.adhoc_join; struct mwifiex_bssdescriptor *bss_desc = @@ -1060,10 +1058,9 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, priv-> curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, + if (mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, HostCmd_ACT_GEN_SET, 0, - &curr_pkt_filter); - if (ret) { + &curr_pkt_filter)) { dev_err(priv->adapter->dev, "ADHOC_J_CMD: G Protection config failed\n"); return -1; @@ -1174,7 +1171,7 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap); - return ret; + return 0; } /* @@ -1192,15 +1189,13 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, struct mwifiex_adapter *adapter = priv->adapter; struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result; struct mwifiex_bssdescriptor *bss_desc; - u16 command = le16_to_cpu(resp->command); - u16 result = le16_to_cpu(resp->result); adhoc_result = &resp->params.adhoc_result; bss_desc = priv->attempted_bss_desc; /* Join result code 0 --> SUCCESS */ - if (result) { + if (le16_to_cpu(resp->result)) { dev_err(priv->adapter->dev, "ADHOC_RESP: failed\n"); if (priv->media_connected) mwifiex_reset_connect_state(priv); @@ -1215,7 +1210,7 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, /* Send a Media Connected event, according to the Spec */ priv->media_connected = true; - if (command == HostCmd_CMD_802_11_AD_HOC_START) { + if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) { dev_dbg(priv->adapter->dev, "info: ADHOC_S_RESP %s\n", bss_desc->ssid.ssid); @@ -1278,7 +1273,6 @@ done: int mwifiex_associate(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { - int ret = 0; u8 current_bssid[ETH_ALEN]; /* Return error if the adapter or table entry is not marked as infra */ @@ -1294,10 +1288,8 @@ int mwifiex_associate(struct mwifiex_private *priv, retrieval */ priv->assoc_rsp_size = 0; - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_ASSOCIATE, + return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_ASSOCIATE, HostCmd_ACT_GEN_SET, 0, bss_desc); - - return ret; } /* @@ -1309,8 +1301,6 @@ int mwifiex_adhoc_start(struct mwifiex_private *priv, struct mwifiex_802_11_ssid *adhoc_ssid) { - int ret = 0; - dev_dbg(priv->adapter->dev, "info: Adhoc Channel = %d\n", priv->adhoc_channel); dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", @@ -1318,10 +1308,8 @@ mwifiex_adhoc_start(struct mwifiex_private *priv, dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n", priv->curr_bss_params.band); - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START, + return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START, HostCmd_ACT_GEN_SET, 0, adhoc_ssid); - - return ret; } /* @@ -1333,8 +1321,6 @@ mwifiex_adhoc_start(struct mwifiex_private *priv, int mwifiex_adhoc_join(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { - int ret = 0; - dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid =%s\n", priv->curr_bss_params.bss_descriptor.ssid.ssid); dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid_len =%u\n", @@ -1360,10 +1346,8 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv, dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n", priv->curr_bss_params.band); - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, + return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, HostCmd_ACT_GEN_SET, 0, bss_desc); - - return ret; } /* @@ -1424,21 +1408,15 @@ EXPORT_SYMBOL_GPL(mwifiex_deauthenticate); u8 mwifiex_band_to_radio_type(u8 band) { - u8 ret_radio_type; - switch (band) { case BAND_A: case BAND_AN: case BAND_A | BAND_AN: - ret_radio_type = HostCmd_SCAN_RADIO_TYPE_A; - break; + return HostCmd_SCAN_RADIO_TYPE_A; case BAND_B: case BAND_G: case BAND_B | BAND_G: default: - ret_radio_type = HostCmd_SCAN_RADIO_TYPE_BG; - break; + return HostCmd_SCAN_RADIO_TYPE_BG; } - - return ret_radio_type; } diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 77abfc3d6c32..2c376dd4ad50 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -68,7 +68,6 @@ static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = { static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, struct mwifiex_device *mdevice, void **padapter) { - int ret = 0; struct mwifiex_adapter *adapter = NULL; u8 i = 0; @@ -84,8 +83,7 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, memmove(&adapter->if_ops, if_ops, sizeof(struct mwifiex_if_ops)); /* card specific initialization has been deferred until now .. */ - ret = adapter->if_ops.init_if(adapter); - if (ret) + if (adapter->if_ops.init_if(adapter)) goto error; adapter->priv_num = 0; @@ -893,7 +891,6 @@ int mwifiex_add_card(void *card, struct semaphore *sem, struct mwifiex_if_ops *if_ops) { - int status = 0; int i; struct mwifiex_adapter *adapter = NULL; struct mwifiex_drv_mode *drv_mode_info = &mwifiex_drv_mode_tbl[0]; @@ -943,12 +940,9 @@ mwifiex_add_card(void *card, struct semaphore *sem, for (i = 0; i < drv_mode_info->intf_num; i++) { if (!mwifiex_add_interface(adapter, i, adapter->drv_mode->bss_attr[i].bss_type)) { - status = -1; - break; + goto err_add_intf; } } - if (status) - goto err_add_intf; up(sem); @@ -969,8 +963,8 @@ err_kmalloc: (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) { pr_debug("info: %s: shutdown mwifiex\n", __func__); adapter->init_wait_q_woken = false; - status = mwifiex_shutdown_drv(adapter); - if (status == -EINPROGRESS) + + if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) wait_event_interruptible(adapter->init_wait_q, adapter->init_wait_q_woken); } @@ -999,7 +993,6 @@ EXPORT_SYMBOL_GPL(mwifiex_add_card); int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) { struct mwifiex_private *priv = NULL; - int status; int i; if (down_interruptible(sem)) @@ -1023,8 +1016,8 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n"); adapter->init_wait_q_woken = false; - status = mwifiex_shutdown_drv(adapter); - if (status == -EINPROGRESS) + + if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) wait_event_interruptible(adapter->init_wait_q, adapter->init_wait_q_woken); dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n"); diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 84742715893f..68d905d58606 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -181,7 +181,6 @@ int mwifiex_find_best_bss(struct mwifiex_private *priv, struct mwifiex_ssid_bssid *ssid_bssid) { struct mwifiex_ssid_bssid tmp_ssid_bssid; - int ret = 0; u8 *mac = NULL; if (!ssid_bssid) @@ -189,17 +188,17 @@ int mwifiex_find_best_bss(struct mwifiex_private *priv, memcpy(&tmp_ssid_bssid, ssid_bssid, sizeof(struct mwifiex_ssid_bssid)); - ret = mwifiex_bss_ioctl_find_bss(priv, &tmp_ssid_bssid); - if (!ret) { + if (!mwifiex_bss_ioctl_find_bss(priv, &tmp_ssid_bssid)) { memcpy(ssid_bssid, &tmp_ssid_bssid, sizeof(struct mwifiex_ssid_bssid)); mac = (u8 *) &ssid_bssid->bssid; dev_dbg(priv->adapter->dev, "cmd: found network: ssid=%s," " %pM\n", ssid_bssid->ssid.ssid, mac); + return 0; } - return ret; + return -1; } /* @@ -2061,19 +2060,13 @@ mwifiex_process_scan_results(struct mwifiex_private *priv) static u8 mwifiex_radio_type_to_band(u8 radio_type) { - u8 ret_band; - switch (radio_type) { case HostCmd_SCAN_RADIO_TYPE_A: - ret_band = BAND_A; - break; + return BAND_A; case HostCmd_SCAN_RADIO_TYPE_BG: default: - ret_band = BAND_G; - break; + return BAND_G; } - - return ret_band; } /* @@ -2226,8 +2219,7 @@ static int mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv, struct mwifiex_802_11_ssid *del_ssid) { - int ret = -1; - s32 table_idx; + s32 table_idx = -1; dev_dbg(priv->adapter->dev, "info: scan: delete ssid entry: %-32s\n", del_ssid->ssid); @@ -2240,11 +2232,10 @@ mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv, dev_dbg(priv->adapter->dev, "info: Scan: Delete SSID Entry: Found Idx = %d\n", table_idx); - ret = 0; mwifiex_scan_delete_table_entry(priv, table_idx); } - return ret; + return table_idx == -1 ? -1 : 0; } /* diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 41c087d3f0f5..5148d0e0fad6 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -347,12 +347,9 @@ static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer, */ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) { - int ret; - dev_dbg(adapter->dev, "event: wakeup device...\n"); - ret = mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP); - return ret; + return mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP); } /* @@ -362,12 +359,9 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) */ static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter) { - int ret; - dev_dbg(adapter->dev, "cmd: wakeup device completed\n"); - ret = mwifiex_write_reg(adapter, CONFIGURATION_REG, 0); - return ret; + return mwifiex_write_reg(adapter, CONFIGURATION_REG, 0); } /* @@ -1703,13 +1697,9 @@ static struct mwifiex_if_ops sdio_ops = { static int mwifiex_sdio_init_module(void) { - int ret; - sema_init(&add_remove_card_sem, 1); - ret = sdio_register_driver(&mwifiex_sdio); - - return ret; + return sdio_register_driver(&mwifiex_sdio); } /* diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 6489f264ef5f..03085a3b20db 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -216,7 +216,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, ret = mwifiex_adhoc_join(priv, &adapter->scan_table[i]); if (ret) return ret; - } else { /* i >= 0 */ + } else { dev_dbg(adapter->dev, "info: Network not found in " "the list, creating adhoc with ssid = %s\n", ssid_bssid->ssid.ssid); @@ -320,16 +320,13 @@ int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, */ int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type) { - int ret = 0; struct mwifiex_ds_hs_cfg hscfg; - /* Cancel Host Sleep */ hscfg.conditions = HOST_SLEEP_CFG_CANCEL; hscfg.is_invoke_hostcmd = true; - ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, - cmd_type, &hscfg); - return ret; + return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, + cmd_type, &hscfg); } EXPORT_SYMBOL_GPL(mwifiex_cancel_hs); @@ -348,7 +345,6 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) return true; } - /* Enable Host Sleep */ adapter->hs_activate_wait_q_woken = false; memset(&hscfg, 0, sizeof(struct mwifiex_hs_config_param)); @@ -385,23 +381,17 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv, if (!info) return -1; - /* Get current BSS info */ bss_desc = &priv->curr_bss_params.bss_descriptor; - /* BSS mode */ info->bss_mode = priv->bss_mode; - /* SSID */ memcpy(&info->ssid, &bss_desc->ssid, sizeof(struct mwifiex_802_11_ssid)); - /* BSSID */ memcpy(&info->bssid, &bss_desc->mac_address, ETH_ALEN); - /* Channel */ info->bss_chan = bss_desc->channel; - /* Region code */ info->region_code = adapter->region_code; /* Scan table index if connected */ @@ -415,20 +405,15 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv, info->scan_table_idx = tbl_idx; } - /* Connection status */ info->media_connected = priv->media_connected; - /* Tx power information */ info->max_power_level = priv->max_tx_power_level; info->min_power_level = priv->min_tx_power_level; - /* AdHoc state */ info->adhoc_state = priv->adhoc_state; - /* Last beacon NF */ info->bcn_nf_last = priv->bcn_nf_last; - /* wep status */ if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED) info->wep_status = true; else @@ -574,22 +559,17 @@ int mwifiex_bss_set_channel(struct mwifiex_private *priv, static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv, u16 action, u16 *channel) { - int ret = 0; - if (action == HostCmd_ACT_GEN_GET) { if (!priv->media_connected) { *channel = priv->adhoc_channel; - return ret; + return 0; } } else { priv->adhoc_channel = (u8) *channel; } - /* Send request to firmware */ - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_RF_CHANNEL, + return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_RF_CHANNEL, action, 0, channel); - - return ret; } /* @@ -602,7 +582,6 @@ int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv, struct mwifiex_ssid_bssid *ssid_bssid) { struct mwifiex_adapter *adapter = priv->adapter; - int ret = 0; struct mwifiex_bssdescriptor *bss_desc; u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; u8 mac[ETH_ALEN]; @@ -631,10 +610,10 @@ int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv, bss_desc = &adapter->scan_table[i]; memcpy(ssid_bssid->bssid, bss_desc->mac_address, ETH_ALEN); } else { - ret = mwifiex_find_best_network(priv, ssid_bssid); + return mwifiex_find_best_network(priv, ssid_bssid); } - return ret; + return 0; } /* @@ -718,7 +697,6 @@ static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv, struct mwifiex_rate_cfg *rate_cfg) { struct mwifiex_adapter *adapter = priv->adapter; - int ret = 0; rate_cfg->is_rate_auto = priv->is_data_rate_auto; if (!priv->media_connected) { @@ -757,13 +735,12 @@ static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv, break; } } else { - /* Send request to firmware */ - ret = mwifiex_send_cmd_sync(priv, + return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, HostCmd_ACT_GEN_GET, 0, NULL); } - return ret; + return 0; } /* @@ -827,7 +804,6 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv, } } - /* Send request to firmware */ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, HostCmd_ACT_GEN_SET, 0, bitmap_rates); @@ -969,7 +945,6 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, pg->power_max = (s8) dbm; pg->ht_bandwidth = HT_BW_40; } - /* Send request to firmware */ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TXPWR_CFG, HostCmd_ACT_GEN_SET, 0, buf); @@ -1088,13 +1063,10 @@ static int mwifiex_set_wapi_ie(struct mwifiex_private *priv, static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv, struct mwifiex_ds_encrypt_key *encrypt_key) { - int ret = 0; - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_KEY_MATERIAL, + return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_KEY_MATERIAL, HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, encrypt_key); - - return ret; } /* @@ -1128,7 +1100,6 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, priv->sec_info.wep_status = MWIFIEX_802_11_WEP_ENABLED; } else { wep_key = &priv->wep_key[index]; - /* Cleanup */ memset(wep_key, 0, sizeof(struct mwifiex_wep_key)); /* Copy the key in the driver */ memcpy(wep_key->key_material, @@ -1151,7 +1122,6 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, else priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; - /* Send request to firmware */ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL, HostCmd_ACT_GEN_SET, 0, &priv->curr_pkt_filter); @@ -1216,13 +1186,11 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; if (remove_key) - /* Send request to firmware */ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_KEY_MATERIAL, HostCmd_ACT_GEN_SET, !(KEY_INFO_ENABLED), encrypt_key); else - /* Send request to firmware */ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_KEY_MATERIAL, HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, @@ -1297,7 +1265,6 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv, return -1; } - /* Send request to firmware */ status = mwifiex_send_cmd_sync(priv, HostCmd_CMD_RSSI_INFO, HostCmd_ACT_GEN_GET, 0, signal); @@ -1324,7 +1291,6 @@ int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, int key_len, u8 key_index, int disable) { struct mwifiex_ds_encrypt_key encrypt_key; - int ret = 0; memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key)); encrypt_key.key_len = key_len; @@ -1336,9 +1302,7 @@ int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, encrypt_key.key_disable = true; } - ret = mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key); - - return ret; + return mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key); } /* @@ -1351,18 +1315,13 @@ int mwifiex_get_ver_ext(struct mwifiex_private *priv) { struct mwifiex_ver_ext ver_ext; - int ret = 0; - /* get fw version */ memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext)); - /* Send request to firmware */ - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_VERSION_EXT, - HostCmd_ACT_GEN_GET, 0, &ver_ext); - - if (ret) - ret = -1; + if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_VERSION_EXT, + HostCmd_ACT_GEN_GET, 0, &ver_ext)) + return -1; - return ret; + return 0; } /* @@ -1379,7 +1338,6 @@ mwifiex_get_stats_info(struct mwifiex_private *priv, struct mwifiex_ds_get_stats get_log; memset(&get_log, 0, sizeof(struct mwifiex_ds_get_stats)); - /* Send request to firmware */ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG, HostCmd_ACT_GEN_GET, 0, &get_log); @@ -1412,7 +1370,6 @@ static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv, struct mwifiex_ds_reg_rw *reg_rw, u16 action) { - int ret = 0; u16 cmd_no; switch (le32_to_cpu(reg_rw->type)) { @@ -1435,10 +1392,8 @@ static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv, return -1; } - /* Send request to firmware */ - ret = mwifiex_send_cmd_sync(priv, cmd_no, action, 0, reg_rw); + return mwifiex_send_cmd_sync(priv, cmd_no, action, 0, reg_rw); - return ret; } /* @@ -1451,15 +1406,13 @@ int mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type, u32 reg_offset, u32 reg_value) { - int ret = 0; struct mwifiex_ds_reg_rw reg_rw; reg_rw.type = cpu_to_le32(reg_type); reg_rw.offset = cpu_to_le32(reg_offset); reg_rw.value = cpu_to_le32(reg_value); - ret = mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_SET); - return ret; + return mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_SET); } /* @@ -1638,7 +1591,6 @@ int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len) { struct mwifiex_ds_misc_gen_ie gen_ie; - int status = 0; if (ie_len > IW_CUSTOM_MAX) return -EFAULT; @@ -1646,8 +1598,7 @@ mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len) gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE; gen_ie.len = ie_len; memcpy(gen_ie.ie_data, ie, ie_len); - status = mwifiex_misc_ioctl_gen_ie(priv, &gen_ie, HostCmd_ACT_GEN_SET); - if (status) + if (mwifiex_misc_ioctl_gen_ie(priv, &gen_ie, HostCmd_ACT_GEN_SET)) return -EFAULT; return 0; diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index b261d812c4d3..5d37ef160121 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c @@ -180,15 +180,11 @@ mwifiex_check_last_packet_indication(struct mwifiex_private *priv) { struct mwifiex_adapter *adapter = priv->adapter; u8 ret = false; - u8 prop_ps = true; if (!adapter->sleep_period.period) return ret; - if (mwifiex_wmm_lists_empty(adapter)) { - if ((priv->curr_bss_params.wmm_uapsd_enabled && - priv->wmm_qosinfo) || prop_ps) + if (mwifiex_wmm_lists_empty(adapter)) ret = true; - } if (ret && !adapter->cmd_sent && !adapter->curr_cmd && !is_command_pending(adapter)) { diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index f06923cb1c4b..ce772e078db8 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -36,7 +36,6 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) { - int ret = 0; struct mwifiex_private *priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); struct rxpd *local_rx_pd; @@ -50,9 +49,8 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); rx_info->bss_index = priv->bss_index; - ret = mwifiex_process_sta_rx_packet(adapter, skb); - return ret; + return mwifiex_process_sta_rx_packet(adapter, skb); } EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 9f65587622fd..7ab4fb279f8a 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c @@ -61,7 +61,6 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter) int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, u32 func_init_shutdown) { - int ret; u16 cmd; if (func_init_shutdown == MWIFIEX_FUNC_INIT) { @@ -73,10 +72,7 @@ int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, return -1; } - /* Send command to firmware */ - ret = mwifiex_send_cmd_sync(priv, cmd, HostCmd_ACT_GEN_SET, 0, NULL); - - return ret; + return mwifiex_send_cmd_sync(priv, cmd, HostCmd_ACT_GEN_SET, 0, NULL); } EXPORT_SYMBOL_GPL(mwifiex_init_shutdown_fw); diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 99e8431c1e93..c009370f309e 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -973,7 +973,6 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, struct sk_buff *skb, *skb_next; struct mwifiex_tx_param tx_param; struct mwifiex_adapter *adapter = priv->adapter; - int status = 0; struct mwifiex_txinfo *tx_info; if (skb_queue_empty(&ptr->skb_head)) { @@ -1000,9 +999,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, tx_param.next_pkt_len = ((skb_next) ? skb_next->len + sizeof(struct txpd) : 0); - status = mwifiex_process_tx(priv, skb, &tx_param); - - if (status == -EBUSY) { + if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) { /* Queue the packet back at the head */ spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); -- cgit v1.2.3-58-ga151 From a37316586d926a10d66b5585c5d91683d6468f68 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 15 Apr 2011 20:50:41 -0700 Subject: mwifiex: remove some macro definitions use corresponding macros defined in include/linux/ieee80211.h Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n.c | 2 +- drivers/net/wireless/mwifiex/fw.h | 2 -- drivers/net/wireless/mwifiex/ioctl.h | 3 +-- drivers/net/wireless/mwifiex/join.c | 2 +- drivers/net/wireless/mwifiex/sta_ioctl.c | 2 +- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index d64065ff235c..e22d761f2ef2 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -115,7 +115,7 @@ mwifiex_fill_cap_info(struct mwifiex_private *priv, SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); /* Clear RD responder bit */ - RESETHT_EXTCAP_RDG(ht_ext_cap); + ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER; ht_cap->ht_cap.cap_info = cpu_to_le16(ht_cap_info); ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap); diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index f8c008f8f476..6d1c4545eda6 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -134,7 +134,6 @@ enum MWIFIEX_802_11_WEP_STATUS { #define MWIFIEX_TX_DATA_BUF_SIZE_4K 4096 #define MWIFIEX_TX_DATA_BUF_SIZE_8K 8192 -#define NON_GREENFIELD_STAS 0x04 #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) @@ -159,7 +158,6 @@ enum MWIFIEX_802_11_WEP_STATUS { #define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) #define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f) -#define RESETHT_EXTCAP_RDG(HTExtCap) (HTExtCap &= ~BIT(11)) #define SETHT_MCS32(x) (x[4] |= 1) #define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4)) diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 703a6d12ebf3..5488e111fd2c 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -268,14 +268,13 @@ struct mwifiex_debug_info { }; #define MWIFIEX_KEY_INDEX_UNICAST 0x40000000 -#define MWIFIEX_MAX_KEY_LENGTH 32 #define WAPI_RXPN_LEN 16 struct mwifiex_ds_encrypt_key { u32 key_disable; u32 key_index; u32 key_len; - u8 key_material[MWIFIEX_MAX_KEY_LENGTH]; + u8 key_material[WLAN_MAX_KEY_LEN]; u8 mac_addr[ETH_ALEN]; u32 is_wapi_key; u8 wapi_rxpn[WAPI_RXPN_LEN]; diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 8e1cb4b3fbea..23d2d0b9a527 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -995,7 +995,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; } ht_info->ht_info.operation_mode = - cpu_to_le16(NON_GREENFIELD_STAS); + cpu_to_le16(IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); ht_info->ht_info.basic_set[0] = 0xff; pos += sizeof(struct mwifiex_ie_types_htinfo); cmd_append_size += diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 03085a3b20db..e7adaab35226 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -1147,7 +1147,7 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, struct host_cmd_ds_802_11_key_material *ibss_key; /* Current driver only supports key length of up to 32 bytes */ - if (encrypt_key->key_len > MWIFIEX_MAX_KEY_LENGTH) { + if (encrypt_key->key_len > WLAN_MAX_KEY_LEN) { dev_err(priv->adapter->dev, "key length too long\n"); return -1; } -- cgit v1.2.3-58-ga151 From 2be7859f41e9bcef5b15bd23d63e01536344e3df Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 15 Apr 2011 20:50:42 -0700 Subject: mwifiex: optimize driver initialization code 1) removal of unnecessary mwifiex_device structure 2) avoid passing adapter pointer to mwifiex_init_sw() 3) remove local variable drv_mode_info in mwifiex_add_card() 4) type change in mwifiex_bss_attr to match mwifiex_private 5) removal of more wordy comments Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/decl.h | 14 +++---- drivers/net/wireless/mwifiex/main.c | 81 +++++++++++++------------------------ drivers/net/wireless/mwifiex/main.h | 2 +- 3 files changed, 33 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 8364b62c3298..0e90b0986ed8 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h @@ -113,11 +113,11 @@ struct mwifiex_txinfo { }; struct mwifiex_bss_attr { - u32 bss_type; - u32 frame_type; - u32 active; - u32 bss_priority; - u32 bss_num; + u8 bss_type; + u8 frame_type; + u8 active; + u8 bss_priority; + u8 bss_num; }; enum mwifiex_wmm_ac_e { @@ -126,8 +126,4 @@ enum mwifiex_wmm_ac_e { WMM_AC_VI, WMM_AC_VO } __packed; - -struct mwifiex_device { - struct mwifiex_bss_attr bss_attr[MWIFIEX_MAX_BSS_NUM]; -}; #endif /* !_MWIFIEX_DECL_H_ */ diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 2c376dd4ad50..c5971880e7b3 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -40,14 +40,10 @@ static char fw_name[32] = DEFAULT_FW_NAME; /* Supported drv_mode table */ static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = { { - /* drv_mode */ - .drv_mode = DRV_MODE_STA, - /* intf number */ - .intf_num = ARRAY_SIZE(mwifiex_bss_sta), - /* bss_attr */ - .bss_attr = mwifiex_bss_sta, - } - , + .drv_mode = DRV_MODE_STA, + .intf_num = ARRAY_SIZE(mwifiex_bss_sta), + .bss_attr = mwifiex_bss_sta, + }, }; /* @@ -66,13 +62,12 @@ static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = { * proper cleanup before exiting. */ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, - struct mwifiex_device *mdevice, void **padapter) + struct mwifiex_drv_mode *drv_mode_ptr) { - struct mwifiex_adapter *adapter = NULL; - u8 i = 0; + struct mwifiex_adapter *adapter; + int i; adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL); - /* Allocate memory for adapter structure */ if (!adapter) return -1; @@ -87,14 +82,13 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, goto error; adapter->priv_num = 0; - for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) { + for (i = 0; i < drv_mode_ptr->intf_num; i++) { adapter->priv[i] = NULL; - if (!mdevice->bss_attr[i].active) + if (!drv_mode_ptr->bss_attr[i].active) continue; - /* For valid bss_attr, - allocate memory for private structure */ + /* Allocate memory for private structure */ adapter->priv[i] = kzalloc(sizeof(struct mwifiex_private), GFP_KERNEL); if (!adapter->priv[i]) { @@ -104,26 +98,26 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, } adapter->priv_num++; - memset(adapter->priv[i], 0, - sizeof(struct mwifiex_private)); adapter->priv[i]->adapter = adapter; /* Save bss_type, frame_type & bss_priority */ - adapter->priv[i]->bss_type = (u8) mdevice->bss_attr[i].bss_type; + adapter->priv[i]->bss_type = drv_mode_ptr->bss_attr[i].bss_type; adapter->priv[i]->frame_type = - (u8) mdevice->bss_attr[i].frame_type; + drv_mode_ptr->bss_attr[i].frame_type; adapter->priv[i]->bss_priority = - (u8) mdevice->bss_attr[i].bss_priority; - if (mdevice->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_STA) + drv_mode_ptr->bss_attr[i].bss_priority; + + if (drv_mode_ptr->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_STA) adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_STA; - else if (mdevice->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_UAP) + else if (drv_mode_ptr->bss_attr[i].bss_type == + MWIFIEX_BSS_TYPE_UAP) adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_UAP; /* Save bss_index & bss_num */ adapter->priv[i]->bss_index = i; - adapter->priv[i]->bss_num = mdevice->bss_attr[i].bss_num; + adapter->priv[i]->bss_num = drv_mode_ptr->bss_attr[i].bss_num; } + adapter->drv_mode = drv_mode_ptr; - /* Initialize lock variables */ if (mwifiex_init_lock_list(adapter)) goto error; @@ -131,16 +125,13 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, adapter->cmd_timer.function = mwifiex_cmd_timeout_func; adapter->cmd_timer.data = (unsigned long) adapter; - /* Return pointer of struct mwifiex_adapter */ - *padapter = adapter; return 0; error: dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n"); - /* Free lock variables */ mwifiex_free_lock_list(adapter); - for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) + for (i = 0; i < drv_mode_ptr->intf_num; i++) kfree(adapter->priv[i]); kfree(adapter); @@ -335,10 +326,9 @@ exit_main_proc: * and initializing the private structures. */ static int -mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **pmwifiex) +mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops) { int i; - struct mwifiex_device device; struct mwifiex_drv_mode *drv_mode_ptr; /* find mwifiex_drv_mode entry from mwifiex_drv_mode_tbl */ @@ -355,20 +345,7 @@ mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **pmwifiex) return -1; } - memset(&device, 0, sizeof(struct mwifiex_device)); - - for (i = 0; i < drv_mode_ptr->intf_num; i++) { - device.bss_attr[i].bss_type = - drv_mode_ptr->bss_attr[i].bss_type; - device.bss_attr[i].frame_type = - drv_mode_ptr->bss_attr[i].frame_type; - device.bss_attr[i].active = drv_mode_ptr->bss_attr[i].active; - device.bss_attr[i].bss_priority = - drv_mode_ptr->bss_attr[i].bss_priority; - device.bss_attr[i].bss_num = drv_mode_ptr->bss_attr[i].bss_num; - } - - if (mwifiex_register(card, if_ops, &device, pmwifiex)) + if (mwifiex_register(card, if_ops, drv_mode_ptr)) return -1; return 0; @@ -892,21 +869,19 @@ mwifiex_add_card(void *card, struct semaphore *sem, struct mwifiex_if_ops *if_ops) { int i; - struct mwifiex_adapter *adapter = NULL; - struct mwifiex_drv_mode *drv_mode_info = &mwifiex_drv_mode_tbl[0]; + struct mwifiex_adapter *adapter; if (down_interruptible(sem)) goto exit_sem_err; - if (mwifiex_init_sw(card, if_ops, (void **) &adapter)) { + if (mwifiex_init_sw(card, if_ops)) { pr_err("%s: software init failed\n", __func__); goto err_init_sw; } - adapter->drv_mode = drv_mode_info; + adapter = g_adapter; adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; - /* PnP and power profile */ adapter->surprise_removed = false; init_waitqueue_head(&adapter->init_wait_q); adapter->is_suspended = false; @@ -917,7 +892,6 @@ mwifiex_add_card(void *card, struct semaphore *sem, adapter->cmd_wait_q.condition = false; adapter->cmd_wait_q.status = 0; - /* Create workqueue */ adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE"); if (!adapter->workqueue) goto err_kmalloc; @@ -931,13 +905,13 @@ mwifiex_add_card(void *card, struct semaphore *sem, goto err_registerdev; } - /* Init FW and HW */ if (mwifiex_init_hw_fw(adapter)) { pr_err("%s: firmware init failed\n", __func__); goto err_init_fw; } + /* Add interfaces */ - for (i = 0; i < drv_mode_info->intf_num; i++) { + for (i = 0; i < adapter->drv_mode->intf_num; i++) { if (!mwifiex_add_interface(adapter, i, adapter->drv_mode->bss_attr[i].bss_type)) { goto err_add_intf; @@ -952,7 +926,6 @@ err_add_intf: for (i = 0; i < adapter->priv_num; i++) mwifiex_remove_interface(adapter, i); err_init_fw: - /* Unregister device */ pr_debug("info: %s: unregister device\n", __func__); adapter->if_ops.unregister_dev(adapter); err_registerdev: diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 2d296dcc210e..1b503038270e 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -872,7 +872,7 @@ mwifiex_copy_rates(u8 *dest, u32 pos, u8 *src, int len) */ static inline struct mwifiex_private * mwifiex_get_priv_by_id(struct mwifiex_adapter *adapter, - u32 bss_num, u32 bss_type) + u8 bss_num, u8 bss_type) { int i; -- cgit v1.2.3-58-ga151 From cea3235cf578b5e952f5a0cec9bc6c2e862eb697 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 16 Apr 2011 14:17:39 +0530 Subject: ath9k_htc: Fix free slot value for cab queue ath9k_htc_tx_get_slot can return zero as valid index. Signed-off-by: Rajkumar Manoharan Acked-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index bf7ef1b7eb3f..a157107b3f3b 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -322,7 +322,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, } tx_slot = ath9k_htc_tx_get_slot(priv); - if (tx_slot != 0) { + if (tx_slot < 0) { ath_dbg(common, ATH_DBG_XMIT, "No free CAB slot\n"); dev_kfree_skb_any(skb); goto next; -- cgit v1.2.3-58-ga151 From dcf55fb5d43bd82e1e3bf94f065cfe8f75a4bc5a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 17 Apr 2011 17:45:00 +0200 Subject: mac80211: add a function for setting the TIM bit for a specific station This allows a driver to buffer frames for a PS station and tell mac80211 to wake it up even though mac80211 does not have any buffered frames for it. This is necessary for properly handling aggregation related buffering, in ath9k, because the driver needs to keep its frames in order to keep track of the Block-ACK window. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- include/net/mac80211.h | 12 ++++++++++++ net/mac80211/sta_info.c | 13 ++++++++++++- net/mac80211/sta_info.h | 3 +++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 361bc5d85b1a..162363b6cb62 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2226,6 +2226,18 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta, */ #define IEEE80211_TX_STATUS_HEADROOM 13 +/** + * ieee80211_sta_set_tim - set the TIM bit for a sleeping station + * + * If a driver buffers frames for a powersave station instead of passing + * them back to mac80211 for retransmission, the station needs to be told + * to wake up using the TIM bitmap in the beacon. + * + * This function sets the station's TIM bit - it will be cleared when the + * station wakes up. + */ +void ieee80211_sta_set_tim(struct ieee80211_sta *sta); + /** * ieee80211_tx_status - transmit status callback * diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 8a9068ac0673..7c5c6da01bea 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -612,7 +612,8 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, #endif dev_kfree_skb(skb); - if (skb_queue_empty(&sta->ps_tx_buf)) + if (skb_queue_empty(&sta->ps_tx_buf) && + !test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF)) sta_info_clear_tim_bit(sta); } @@ -896,6 +897,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) struct ieee80211_local *local = sdata->local; int sent, buffered; + clear_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); @@ -988,3 +990,12 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, ieee80211_queue_work(hw, &sta->drv_unblock_wk); } EXPORT_SYMBOL(ieee80211_sta_block_awake); + +void ieee80211_sta_set_tim(struct ieee80211_sta *pubsta) +{ + struct sta_info *sta = container_of(pubsta, struct sta_info, sta); + + set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); + sta_info_set_tim_bit(sta); +} +EXPORT_SYMBOL(ieee80211_sta_set_tim); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 984a03db3553..af1a7f8c8675 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -43,6 +43,8 @@ * be in the queues * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping * station in power-save mode, reply when the driver unblocks. + * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal + * buffers. Automatically cleared on station wake-up. */ enum ieee80211_sta_info_flags { WLAN_STA_AUTH = 1<<0, @@ -58,6 +60,7 @@ enum ieee80211_sta_info_flags { WLAN_STA_BLOCK_BA = 1<<11, WLAN_STA_PS_DRIVER = 1<<12, WLAN_STA_PSPOLL = 1<<13, + WLAN_STA_PS_DRIVER_BUF = 1<<14, }; #define STA_TID_NUM 16 -- cgit v1.2.3-58-ga151 From 8e22ad323fb5b7cefb572bd8730e3abef95cdf90 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sun, 17 Apr 2011 21:38:10 +0530 Subject: ath9k: Fix beacon generation on foreign channel While leaving the oper channel, beacon generation is stopped by mac80211 and beacon slots are marked as inactive. During the scan, ath9k configures beacon timers based on IEEE80211_CONF_OFFCHANNEL which inturn generates beacon alert even though bslot is inactive. ath9k fails to disable beacon alert while moving to offchannel if none of the beacon slot is active. This is causing beacon transmission on foreign channel. This patch enables swba based on active bslots. This issue was reported with two vifs (AP+STA) and triggered scan in STA vif in unassociated state. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 36 ++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 9193a385ceb2..24f565ba9988 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -746,6 +746,25 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) ath_set_beacon(sc); } +static bool ath_has_valid_bslot(struct ath_softc *sc) +{ + struct ath_vif *avp; + int slot; + bool found = false; + + for (slot = 0; slot < ATH_BCBUF; slot++) { + if (sc->beacon.bslot[slot]) { + avp = (void *)sc->beacon.bslot[slot]->drv_priv; + if (avp->is_bslot_active) { + found = true; + break; + } + } + } + return found; +} + + void ath_set_beacon(struct ath_softc *sc) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); @@ -753,7 +772,8 @@ void ath_set_beacon(struct ath_softc *sc) switch (sc->sc_ah->opmode) { case NL80211_IFTYPE_AP: - ath_beacon_config_ap(sc, cur_conf); + if (ath_has_valid_bslot(sc)) + ath_beacon_config_ap(sc, cur_conf); break; case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: @@ -780,20 +800,8 @@ void ath_set_beacon(struct ath_softc *sc) void ath9k_set_beaconing_status(struct ath_softc *sc, bool status) { struct ath_hw *ah = sc->sc_ah; - struct ath_vif *avp; - int slot; - bool found = false; - for (slot = 0; slot < ATH_BCBUF; slot++) { - if (sc->beacon.bslot[slot]) { - avp = (void *)sc->beacon.bslot[slot]->drv_priv; - if (avp->is_bslot_active) { - found = true; - break; - } - } - } - if (!found) + if (!ath_has_valid_bslot(sc)) return; ath9k_ps_wakeup(sc); -- cgit v1.2.3-58-ga151 From 5519541d5a5f19893546883547e2f0f2e5934df7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 17 Apr 2011 23:28:09 +0200 Subject: ath9k: fix powersave frame filtering/buffering in AP mode This patch fixes a long standing issue of pending packets in the queue being sent (and retransmitted many times) to sleeping stations. This was made worse by aggregation through driver-internal retransmitting of A-MDPU subframes. Previously the hardware tx filter was cleared unconditionally for every single packet - with this patch it uses the IEEE80211_TX_CTL_CLEAR_PS_FILT for unaggregated frames. A sta_notify driver op is added to stop aggregation for stations when they enter powersave mode. Subframes stay buffered inside the driver, to ensure that the BlockAck window keeps a sane state. Since the driver uses software aggregation, the clearing of the tx filter needs to be handled by the driver instead of mac80211 for aggregated frames. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_mac.c | 12 +++- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 12 +++- drivers/net/wireless/ath/ath9k/ath9k.h | 6 ++ drivers/net/wireless/ath/ath9k/hw-ops.h | 5 ++ drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/mac.h | 1 - drivers/net/wireless/ath/ath9k/main.c | 22 ++++++ drivers/net/wireless/ath/ath9k/xmit.c | 101 ++++++++++++++++++++++++---- 8 files changed, 145 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 8dd8f6308502..c338efbccf40 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -290,7 +290,6 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | SM(txPower, AR_XmitPower) | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) - | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); @@ -311,6 +310,16 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, } } +static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + if (val) + ads->ds_ctl0 |= AR_ClrDestMask; + else + ads->ds_ctl0 &= ~AR_ClrDestMask; +} + static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, void *lastds, u32 durUpdateEn, u32 rtsctsRate, @@ -448,4 +457,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah) ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; ops->clr11n_aggr = ar9002_hw_clr11n_aggr; ops->set11n_burstduration = ar9002_hw_set11n_burstduration; + ops->set_clrdmask = ar9002_hw_set_clrdmask; } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 724ac2464ad5..c1264d60c499 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -329,7 +329,6 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | SM(txpower, AR_XmitPower) | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) - | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0); @@ -350,6 +349,16 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, ads->ctl22 = 0; } +static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) +{ + struct ar9003_txc *ads = (struct ar9003_txc *) ds; + + if (val) + ads->ctl11 |= AR_ClrDestMask; + else + ads->ctl11 &= ~AR_ClrDestMask; +} + static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, void *lastds, u32 durUpdateEn, u32 rtsctsRate, @@ -510,6 +519,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; ops->clr11n_aggr = ar9003_hw_clr11n_aggr; ops->set11n_burstduration = ar9003_hw_set11n_burstduration; + ops->set_clrdmask = ar9003_hw_set_clrdmask; } void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 77ad407e9fa3..a2ddabf0ca2f 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -200,6 +200,7 @@ struct ath_atx_ac { int sched; struct list_head list; struct list_head tid_q; + bool clear_ps_filter; }; struct ath_frame_info { @@ -257,6 +258,8 @@ struct ath_node { struct ath_atx_ac ac[WME_NUM_AC]; u16 maxampdu; u8 mpdudensity; + + bool sleeping; }; #define AGGR_CLEANUP BIT(1) @@ -338,6 +341,9 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); +void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); +bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an); + /********/ /* VIFs */ /********/ diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 22ee888b0baf..9dd90a85ad63 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -122,6 +122,11 @@ static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds, ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration); } +static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) +{ + ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val); +} + /* Private hardware call ops */ /* PHY ops */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 073bc9e1c792..1018d6cbd530 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -626,6 +626,7 @@ struct ath_hw_ops { void (*clr11n_aggr)(struct ath_hw *ah, void *ds); void (*set11n_burstduration)(struct ath_hw *ah, void *ds, u32 burstDuration); + void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val); }; struct ath_nf_limits { diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index b2b2ff852c32..a60edb44127b 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -239,7 +239,6 @@ struct ath_desc { void *ds_vdata; } __packed __aligned(4); -#define ATH9K_TXDESC_CLRDMASK 0x0001 #define ATH9K_TXDESC_NOACK 0x0002 #define ATH9K_TXDESC_RTSENA 0x0004 #define ATH9K_TXDESC_CTSENA 0x0008 diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a55a8929810b..01df5876fda1 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1749,6 +1749,27 @@ static int ath9k_sta_remove(struct ieee80211_hw *hw, return 0; } +static void ath9k_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) +{ + struct ath_softc *sc = hw->priv; + struct ath_node *an = (struct ath_node *) sta->drv_priv; + + switch (cmd) { + case STA_NOTIFY_SLEEP: + an->sleeping = true; + if (ath_tx_aggr_sleep(sc, an)) + ieee80211_sta_set_tim(sta); + break; + case STA_NOTIFY_AWAKE: + an->sleeping = false; + ath_tx_aggr_wakeup(sc, an); + break; + } +} + static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { @@ -2230,6 +2251,7 @@ struct ieee80211_ops ath9k_ops = { .configure_filter = ath9k_configure_filter, .sta_add = ath9k_sta_add, .sta_remove = ath9k_sta_remove, + .sta_notify = ath9k_sta_notify, .conf_tx = ath9k_conf_tx, .bss_info_changed = ath9k_bss_info_changed, .set_key = ath9k_set_key, diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 5943bdc4c8f9..48ff8c22ba1f 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -357,6 +357,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ath_frame_info *fi; int nframes; u8 tidno; + bool clear_filter; skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; @@ -441,22 +442,24 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, /* transmit completion */ acked_cnt++; } else { - if (!(tid->state & AGGR_CLEANUP) && retry) { - if (fi->retries < ATH_MAX_SW_RETRIES) { - ath_tx_set_retry(sc, txq, bf->bf_mpdu); - txpending = 1; - } else { - bf->bf_state.bf_type |= BUF_XRETRY; - txfail = 1; - sendbar = 1; - txfail_cnt++; - } - } else { + if ((tid->state & AGGR_CLEANUP) || !retry) { /* * cleanup in progress, just fail * the un-acked sub-frames */ txfail = 1; + } else if (fi->retries < ATH_MAX_SW_RETRIES) { + if (!(ts->ts_status & ATH9K_TXERR_FILT) || + !an->sleeping) + ath_tx_set_retry(sc, txq, bf->bf_mpdu); + + clear_filter = true; + txpending = 1; + } else { + bf->bf_state.bf_type |= BUF_XRETRY; + txfail = 1; + sendbar = 1; + txfail_cnt++; } } @@ -496,6 +499,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, !txfail, sendbar); } else { /* retry the un-acked ones */ + ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false); if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { if (bf->bf_next == NULL && bf_last->bf_stale) { struct ath_buf *tbf; @@ -546,7 +550,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, /* prepend un-acked frames to the beginning of the pending frame queue */ if (!list_empty(&bf_pending)) { + if (an->sleeping) + ieee80211_sta_set_tim(sta); + spin_lock_bh(&txq->axq_lock); + if (clear_filter) + tid->ac->clear_ps_filter = true; list_splice(&bf_pending, &tid->buf_q); ath_tx_queue_tid(txq, tid); spin_unlock_bh(&txq->axq_lock); @@ -816,6 +825,11 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, bf = list_first_entry(&bf_q, struct ath_buf, list); bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); + if (tid->ac->clear_ps_filter) { + tid->ac->clear_ps_filter = false; + ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); + } + /* if only one frame, send as non-aggregate */ if (bf == bf->bf_lastbf) { fi = get_frame_info(bf->bf_mpdu); @@ -896,6 +910,67 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) ath_tx_flush_tid(sc, txtid); } +bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) +{ + struct ath_atx_tid *tid; + struct ath_atx_ac *ac; + struct ath_txq *txq; + bool buffered = false; + int tidno; + + for (tidno = 0, tid = &an->tid[tidno]; + tidno < WME_NUM_TID; tidno++, tid++) { + + if (!tid->sched) + continue; + + ac = tid->ac; + txq = ac->txq; + + spin_lock_bh(&txq->axq_lock); + + if (!list_empty(&tid->buf_q)) + buffered = true; + + tid->sched = false; + list_del(&tid->list); + + if (ac->sched) { + ac->sched = false; + list_del(&ac->list); + } + + spin_unlock_bh(&txq->axq_lock); + } + + return buffered; +} + +void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) +{ + struct ath_atx_tid *tid; + struct ath_atx_ac *ac; + struct ath_txq *txq; + int tidno; + + for (tidno = 0, tid = &an->tid[tidno]; + tidno < WME_NUM_TID; tidno++, tid++) { + + ac = tid->ac; + txq = ac->txq; + + spin_lock_bh(&txq->axq_lock); + ac->clear_ps_filter = true; + + if (!list_empty(&tid->buf_q) && !tid->paused) { + ath_tx_queue_tid(txq, tid); + ath_txq_schedule(sc, txq); + } + + spin_unlock_bh(&txq->axq_lock); + } +} + void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) { struct ath_atx_tid *txtid; @@ -1491,7 +1566,6 @@ static int setup_tx_flags(struct sk_buff *skb) struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); int flags = 0; - flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ flags |= ATH9K_TXDESC_INTREQ; if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) @@ -1754,6 +1828,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, if (txctl->paprd) bf->bf_state.bfs_paprd_timestamp = jiffies; + if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) + ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); + ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); } -- cgit v1.2.3-58-ga151 From 93ae2dd2230393566738a5f211ffbaa33b056d56 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 17 Apr 2011 23:28:10 +0200 Subject: ath9k: assign keycache slots to unencrypted stations Frame filtering relies on having a valid destination index (keycache slot), to keep track of the destination. Assigning a keycache slot (configured to unencrypted, with no key data attached) improves powersave handling in AP mode with no encryption. The dummy keycache entry for a station is cleared, when a real key gets added. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 ++ drivers/net/wireless/ath/ath9k/main.c | 22 ++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/xmit.c | 10 +++++++--- drivers/net/wireless/ath/key.c | 6 +++++- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index a2ddabf0ca2f..a6b538802251 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -256,6 +256,8 @@ struct ath_node { #endif struct ath_atx_tid tid[WME_NUM_TID]; struct ath_atx_ac ac[WME_NUM_AC]; + int ps_key; + u16 maxampdu; u8 mpdudensity; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 01df5876fda1..e7d6d98ed1cc 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1732,18 +1732,37 @@ static int ath9k_sta_add(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct ath_softc *sc = hw->priv; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_node *an = (struct ath_node *) sta->drv_priv; + struct ieee80211_key_conf ps_key = { }; ath_node_attach(sc, sta); + an->ps_key = ath_key_config(common, vif, sta, &ps_key); return 0; } +static void ath9k_del_ps_key(struct ath_softc *sc, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_node *an = (struct ath_node *) sta->drv_priv; + struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key }; + + if (!an->ps_key) + return; + + ath_key_delete(common, &ps_key); +} + static int ath9k_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct ath_softc *sc = hw->priv; + ath9k_del_ps_key(sc, vif, sta); ath_node_detach(sc, sta); return 0; @@ -1844,6 +1863,9 @@ static int ath9k_set_key(struct ieee80211_hw *hw, switch (cmd) { case SET_KEY: + if (sta) + ath9k_del_ps_key(sc, vif, sta); + ret = ath_key_config(common, vif, sta, key); if (ret >= 0) { key->hw_key_idx = ret; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 48ff8c22ba1f..65d46c6ebced 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1526,7 +1526,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; struct ieee80211_hdr *hdr; struct ath_frame_info *fi = get_frame_info(skb); - struct ath_node *an; + struct ath_node *an = NULL; struct ath_atx_tid *tid; enum ath9k_key_type keytype; u16 seqno = 0; @@ -1534,11 +1534,13 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, keytype = ath9k_cmn_get_hw_crypto_keytype(skb); + if (sta) + an = (struct ath_node *) sta->drv_priv; + hdr = (struct ieee80211_hdr *)skb->data; - if (sta && ieee80211_is_data_qos(hdr->frame_control) && + if (an && ieee80211_is_data_qos(hdr->frame_control) && conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { - an = (struct ath_node *) sta->drv_priv; tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; /* @@ -1554,6 +1556,8 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, memset(fi, 0, sizeof(*fi)); if (hw_key) fi->keyix = hw_key->hw_key_idx; + else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0) + fi->keyix = an->ps_key; else fi->keyix = ATH9K_TXKEYIX_INVALID; fi->keytype = keytype; diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c index 0d4f39cbdcab..a61ef3d6d89c 100644 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c @@ -483,6 +483,9 @@ int ath_key_config(struct ath_common *common, memset(&hk, 0, sizeof(hk)); switch (key->cipher) { + case 0: + hk.kv_type = ATH_CIPHER_CLR; + break; case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: hk.kv_type = ATH_CIPHER_WEP; @@ -498,7 +501,8 @@ int ath_key_config(struct ath_common *common, } hk.kv_len = key->keylen; - memcpy(hk.kv_val, key->key, key->keylen); + if (key->keylen) + memcpy(hk.kv_val, key->key, key->keylen); if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { switch (vif->type) { -- cgit v1.2.3-58-ga151 From 44704e5d7d56625ff93d5a119ca846ae4de9061c Mon Sep 17 00:00:00 2001 From: Layne Edwards Date: Mon, 18 Apr 2011 15:26:00 +0200 Subject: rt2x00: Enable WLAN LED on Ralink SoC (rt305x) devices This patch adds WLAN LED support to the mac80211 rt2x00 driver for Ralink SoC (rt305x) devices. The current WLAN LED drivers in rt2800lib.c set the LED brightness via an MCU request, but do nothing for SoC. This patch checks for SoC and sets the register to enable the WLAN LED (instead of an MCU request). This enables the WLAN LED for RT305x devices. Signed-off-by: Layne Edwards Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 60 +++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 769c05c0cbaa..13ccc1bbeb4b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -949,25 +949,49 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev, unsigned int ledmode = rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, EEPROM_FREQ_LED_MODE); + u32 reg; - if (led->type == LED_TYPE_RADIO) { - rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, - enabled ? 0x20 : 0); - } else if (led->type == LED_TYPE_ASSOC) { - rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, - enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); - } else if (led->type == LED_TYPE_QUALITY) { - /* - * The brightness is divided into 6 levels (0 - 5), - * The specs tell us the following levels: - * 0, 1 ,3, 7, 15, 31 - * to determine the level in a simple way we can simply - * work with bitshifting: - * (1 << level) - 1 - */ - rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, - (1 << brightness / (LED_FULL / 6)) - 1, - polarity); + /* Check for SoC (SOC devices don't support MCU requests) */ + if (rt2x00_is_soc(led->rt2x00dev)) { + rt2800_register_read(led->rt2x00dev, LED_CFG, ®); + + /* Set LED Polarity */ + rt2x00_set_field32(®, LED_CFG_LED_POLAR, polarity); + + /* Set LED Mode */ + if (led->type == LED_TYPE_RADIO) { + rt2x00_set_field32(®, LED_CFG_G_LED_MODE, + enabled ? 3 : 0); + } else if (led->type == LED_TYPE_ASSOC) { + rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, + enabled ? 3 : 0); + } else if (led->type == LED_TYPE_QUALITY) { + rt2x00_set_field32(®, LED_CFG_R_LED_MODE, + enabled ? 3 : 0); + } + + rt2800_register_write(led->rt2x00dev, LED_CFG, reg); + + } else { + if (led->type == LED_TYPE_RADIO) { + rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, + enabled ? 0x20 : 0); + } else if (led->type == LED_TYPE_ASSOC) { + rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, + enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); + } else if (led->type == LED_TYPE_QUALITY) { + /* + * The brightness is divided into 6 levels (0 - 5), + * The specs tell us the following levels: + * 0, 1 ,3, 7, 15, 31 + * to determine the level in a simple way we can simply + * work with bitshifting: + * (1 << level) - 1 + */ + rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, + (1 << brightness / (LED_FULL / 6)) - 1, + polarity); + } } } -- cgit v1.2.3-58-ga151 From 62fe778412b36791b7897cfa139342906fbbf07b Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 18 Apr 2011 15:26:37 +0200 Subject: rt2x00: Fix stuck queue in tx failure case Since commit 0b7fde54f94979edc67bbf86b5adba702ebfefe8 "rt2x00: Protect queue control with mutex" rt2x00 used rt2x00queue_pause_queue for stopping a tx queue in mac80211. But in case of a failure in the tx path rt2x00 still called ieee80211_stop_queue which stopped the queue but prevented rt2x00queue_unpause_queue to wake the queue up again resulting in a stuck tx queue. Fix this by also using rt2x00queue_pause_queue in case of tx failures. Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 661c6baad2b9..4a1c41b59fea 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -158,7 +158,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return; exit_fail: - ieee80211_stop_queue(rt2x00dev->hw, qid); + rt2x00queue_pause_queue(queue); dev_kfree_skb_any(skb); } EXPORT_SYMBOL_GPL(rt2x00mac_tx); -- cgit v1.2.3-58-ga151 From 7dab73b37f5e8885cb73efd25e73861f9b4f0246 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 18 Apr 2011 15:27:06 +0200 Subject: rt2x00: Split rt2x00dev->flags The number of flags defined for the rt2x00dev->flags field, has been growing over the years. Currently we are approaching the maximum number of bits which are available in the field. A secondary problem, is that one part of the field are initialized only during boot, because the driver requirements are initialized or device requirements are loaded from the EEPROM. In both cases, the flags are fixed and will not change during device operation. The other flags are the device state, and will change frequently. So far this resulted in the fact that for some flags, the atomic bit accessors are used, while for the others the non-atomic variants are used. By splitting the flags up into a "flags" and "cap_flags" we can put all flags which are fixed inside "cap_flags". This field can then be read non-atomically. In the "flags" field we keep the device state, which is going to be read atomically. This adds more room for more flags in the future, and sanitizes the field access methods. Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 10 ++-- drivers/net/wireless/rt2x00/rt2500pci.c | 10 ++-- drivers/net/wireless/rt2x00/rt2500usb.c | 12 ++-- drivers/net/wireless/rt2x00/rt2800lib.c | 20 +++---- drivers/net/wireless/rt2x00/rt2800pci.c | 22 ++++---- drivers/net/wireless/rt2x00/rt2800usb.c | 14 ++--- drivers/net/wireless/rt2x00/rt2x00.h | 84 ++++++++++++++++------------ drivers/net/wireless/rt2x00/rt2x00config.c | 4 +- drivers/net/wireless/rt2x00/rt2x00crypto.c | 4 +- drivers/net/wireless/rt2x00/rt2x00debug.c | 42 +++++++++++++- drivers/net/wireless/rt2x00/rt2x00dev.c | 14 ++--- drivers/net/wireless/rt2x00/rt2x00firmware.c | 2 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 4 +- drivers/net/wireless/rt2x00/rt2x00link.c | 2 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 12 ++-- drivers/net/wireless/rt2x00/rt2x00queue.c | 20 +++---- drivers/net/wireless/rt2x00/rt2x00usb.c | 6 +- drivers/net/wireless/rt2x00/rt61pci.c | 42 +++++++------- drivers/net/wireless/rt2x00/rt73usb.c | 32 +++++------ 19 files changed, 203 insertions(+), 153 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 137a24e520da..5d1654a8bda8 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1536,13 +1536,13 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * Detect if this device has an hardware controlled radio. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); + __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); /* * Check if the BBP tuning should be enabled. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING)) - __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); + __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); return 0; } @@ -1640,9 +1640,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * This device requires the atim queue and DMA-mapped skbs. */ - __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags); + __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags); /* * Set the rssi offset. diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 198fc0a0d77c..3da954e1b4ab 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1687,14 +1687,14 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * Detect if this device has an hardware controlled radio. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); + __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); /* * Check if the BBP tuning should be enabled. */ rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE)) - __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); + __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); /* * Read the RSSI <-> dBm offset information. @@ -1958,9 +1958,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * This device requires the atim queue and DMA-mapped skbs. */ - __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags); + __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags); /* * Set the rssi offset. diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index eac788160f55..dbbd8bc851f1 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1519,7 +1519,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) * Detect if this device has an hardware controlled radio. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); + __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); /* * Read the RSSI <-> dBm offset information. @@ -1790,13 +1790,13 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) /* * This device requires the atim queue */ - __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); + __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags); if (!modparam_nohwcrypt) { - __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); + __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags); } - __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags); + __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags); /* * Set the rssi offset. diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 13ccc1bbeb4b..c6f5584128e9 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1763,8 +1763,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, if (rf->channel <= 14) { if (!rt2x00_rt(rt2x00dev, RT5390)) { - if (test_bit(CONFIG_EXTERNAL_LNA_BG, - &rt2x00dev->flags)) { + if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, + &rt2x00dev->cap_flags)) { rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 75, 0x46); } else { @@ -1775,7 +1775,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, } else { rt2800_bbp_write(rt2x00dev, 82, 0xf2); - if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) + if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) rt2800_bbp_write(rt2x00dev, 75, 0x46); else rt2800_bbp_write(rt2x00dev, 75, 0x50); @@ -2008,7 +2008,7 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b)) return txpower; - if (test_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags)) { + if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) { /* * Check if eirp txpower exceed txpower_limit. * We use OFDM 6M as criterion and its eirp txpower @@ -3309,8 +3309,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { - if (!test_bit(CONFIG_EXTERNAL_LNA_BG, - &rt2x00dev->flags)) + if (!test_bit(CAPABILITY_EXTERNAL_LNA_BG, + &rt2x00dev->cap_flags)) rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); } rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); @@ -3733,15 +3733,15 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G)) - __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); + __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G)) - __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); + __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); /* * Detect if this device has an hardware controlled radio. */ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO)) - __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); + __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); /* * Store led settings, for correct led behaviour. @@ -3761,7 +3761,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) < EIRP_MAX_TX_POWER_LIMIT) - __set_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags); + __set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags); return 0; } diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index adc3534254df..4241f1943842 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -966,28 +966,28 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) * This device has multiple filters for control frames * and has a separate filter for PS Poll frames. */ - __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); - __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); + __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); + __set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags); /* * This device has a pre tbtt interrupt and thus fetches * a new beacon directly prior to transmission. */ - __set_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags); + __set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags); /* * This device requires firmware. */ if (!rt2x00_is_soc(rt2x00dev)) - __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags); + __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags); if (!modparam_nohwcrypt) - __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); - __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags); + __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); + __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); /* * Set the rssi offset. diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index d2f5c87305a4..f3ce5e854be6 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -553,18 +553,18 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) * This device has multiple filters for control frames * and has a separate filter for PS Poll frames. */ - __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); - __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); + __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); + __set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags); /* * This device requires firmware. */ - __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); + __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags); if (!modparam_nohwcrypt) - __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); - __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags); + __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); + __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); /* * Set the rssi offset. diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index dd0f66ade6e8..79c385accfac 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -643,11 +643,11 @@ struct rt2x00_ops { }; /* - * rt2x00 device flags + * rt2x00 state flags */ -enum rt2x00_flags { +enum rt2x00_state_flags { /* - * Device state flags + * Device flags */ DEVICE_STATE_PRESENT, DEVICE_STATE_REGISTERED_HW, @@ -656,42 +656,47 @@ enum rt2x00_flags { DEVICE_STATE_ENABLED_RADIO, DEVICE_STATE_SCANNING, - /* - * Driver requirements - */ - DRIVER_REQUIRE_FIRMWARE, - DRIVER_REQUIRE_BEACON_GUARD, - DRIVER_REQUIRE_ATIM_QUEUE, - DRIVER_REQUIRE_DMA, - DRIVER_REQUIRE_COPY_IV, - DRIVER_REQUIRE_L2PAD, - DRIVER_REQUIRE_TXSTATUS_FIFO, - DRIVER_REQUIRE_TASKLET_CONTEXT, - DRIVER_REQUIRE_SW_SEQNO, - DRIVER_REQUIRE_HT_TX_DESC, - - /* - * Driver features - */ - CONFIG_SUPPORT_HW_BUTTON, - CONFIG_SUPPORT_HW_CRYPTO, - CONFIG_SUPPORT_POWER_LIMIT, - DRIVER_SUPPORT_CONTROL_FILTERS, - DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, - DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, - DRIVER_SUPPORT_LINK_TUNING, - /* * Driver configuration */ - CONFIG_FRAME_TYPE, - CONFIG_RF_SEQUENCE, - CONFIG_EXTERNAL_LNA_A, - CONFIG_EXTERNAL_LNA_BG, - CONFIG_DOUBLE_ANTENNA, CONFIG_CHANNEL_HT40, }; +/* + * rt2x00 capability flags + */ +enum rt2x00_capability_flags { + /* + * Requirements + */ + REQUIRE_FIRMWARE, + REQUIRE_BEACON_GUARD, + REQUIRE_ATIM_QUEUE, + REQUIRE_DMA, + REQUIRE_COPY_IV, + REQUIRE_L2PAD, + REQUIRE_TXSTATUS_FIFO, + REQUIRE_TASKLET_CONTEXT, + REQUIRE_SW_SEQNO, + REQUIRE_HT_TX_DESC, + + /* + * Capabilities + */ + CAPABILITY_HW_BUTTON, + CAPABILITY_HW_CRYPTO, + CAPABILITY_POWER_LIMIT, + CAPABILITY_CONTROL_FILTERS, + CAPABILITY_CONTROL_FILTER_PSPOLL, + CAPABILITY_PRE_TBTT_INTERRUPT, + CAPABILITY_LINK_TUNING, + CAPABILITY_FRAME_TYPE, + CAPABILITY_RF_SEQUENCE, + CAPABILITY_EXTERNAL_LNA_A, + CAPABILITY_EXTERNAL_LNA_BG, + CAPABILITY_DOUBLE_ANTENNA, +}; + /* * rt2x00 device structure. */ @@ -738,12 +743,19 @@ struct rt2x00_dev { #endif /* CONFIG_RT2X00_LIB_LEDS */ /* - * Device flags. - * In these flags the current status and some - * of the device capabilities are stored. + * Device state flags. + * In these flags the current status is stored. + * Access to these flags should occur atomically. */ unsigned long flags; + /* + * Device capabiltiy flags. + * In these flags the device/driver capabilities are stored. + * Access to these flags should occur non-atomically. + */ + unsigned long cap_flags; + /* * Device information, Bus IRQ and name (PCI, SoC) */ diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index e7f67d5eda52..e225a66f59a0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -176,10 +176,10 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { if (conf_is_ht40(conf)) { - __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); + set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); hw_value = rt2x00ht_center_channel(rt2x00dev, conf); } else { - __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); + clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); hw_value = conf->channel->hw_value; } diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 5e9074bf2b8e..e1e0c51fcde8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -52,7 +52,7 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; - if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !hw_key) + if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key) return; __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags); @@ -80,7 +80,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, struct ieee80211_key_conf *key = tx_info->control.hw_key; unsigned int overhead = 0; - if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !key) + if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !key) return overhead; /* diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 66166ef037f5..78787fcc919e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -63,7 +63,8 @@ struct rt2x00debug_intf { * - driver folder * - driver file * - chipset file - * - device flags file + * - device state flags file + * - device capability flags file * - register folder * - csr offset/value files * - eeprom offset/value files @@ -78,6 +79,7 @@ struct rt2x00debug_intf { struct dentry *driver_entry; struct dentry *chipset_entry; struct dentry *dev_flags; + struct dentry *cap_flags; struct dentry *register_folder; struct dentry *csr_off_entry; struct dentry *csr_val_entry; @@ -553,6 +555,35 @@ static const struct file_operations rt2x00debug_fop_dev_flags = { .llseek = default_llseek, }; +static ssize_t rt2x00debug_read_cap_flags(struct file *file, + char __user *buf, + size_t length, + loff_t *offset) +{ + struct rt2x00debug_intf *intf = file->private_data; + char line[16]; + size_t size; + + if (*offset) + return 0; + + size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->cap_flags); + + if (copy_to_user(buf, line, size)) + return -EFAULT; + + *offset += size; + return size; +} + +static const struct file_operations rt2x00debug_fop_cap_flags = { + .owner = THIS_MODULE, + .read = rt2x00debug_read_cap_flags, + .open = rt2x00debug_file_open, + .release = rt2x00debug_file_release, + .llseek = default_llseek, +}; + static struct dentry *rt2x00debug_create_file_driver(const char *name, struct rt2x00debug_intf *intf, @@ -652,6 +683,12 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) if (IS_ERR(intf->dev_flags) || !intf->dev_flags) goto exit; + intf->cap_flags = debugfs_create_file("cap_flags", S_IRUSR, + intf->driver_folder, intf, + &rt2x00debug_fop_cap_flags); + if (IS_ERR(intf->cap_flags) || !intf->cap_flags) + goto exit; + intf->register_folder = debugfs_create_dir("register", intf->driver_folder); if (IS_ERR(intf->register_folder) || !intf->register_folder) @@ -705,7 +742,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) intf, &rt2x00debug_fop_queue_stats); #ifdef CONFIG_RT2X00_LIB_CRYPTO - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) + if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) intf->crypto_stats_entry = debugfs_create_file("crypto", S_IRUGO, intf->queue_folder, intf, &rt2x00debug_fop_crypto_stats); @@ -743,6 +780,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) debugfs_remove(intf->csr_off_entry); debugfs_remove(intf->register_folder); debugfs_remove(intf->dev_flags); + debugfs_remove(intf->cap_flags); debugfs_remove(intf->chipset_entry); debugfs_remove(intf->driver_entry); debugfs_remove(intf->driver_folder); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 9bffe8438d1f..af25b0152cbc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -200,7 +200,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) * here as they will fetch the next beacon directly prior to * transmission. */ - if (test_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags)) + if (test_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags)) return; /* fetch next beacon */ @@ -271,7 +271,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, /* * Remove L2 padding which was added during */ - if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) + if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags)) rt2x00queue_remove_l2pad(entry->skb, header_length); /* @@ -280,7 +280,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, * mac80211 will expect the same data to be present it the * frame as it was passed to us. */ - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) + if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) rt2x00crypto_tx_insert_iv(entry->skb, header_length); /* @@ -377,7 +377,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, * send the status report back. */ if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) { - if (test_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags)) + if (test_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags)) ieee80211_tx_status(rt2x00dev->hw, entry->skb); else ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb); @@ -806,15 +806,15 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) /* * Take TX headroom required for alignment into account. */ - if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) + if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags)) rt2x00dev->hw->extra_tx_headroom += RT2X00_L2PAD_SIZE; - else if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) + else if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE; /* * Allocate tx status FIFO for driver use. */ - if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags)) { + if (test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags)) { /* * Allocate the txstatus fifo. In the worst case the tx * status fifo has to hold the tx status of all entries diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index be0ff78c1b16..f316aad30612 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -99,7 +99,7 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev) { int retval; - if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) + if (!test_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags)) return 0; if (!rt2x00dev->fw) { diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 88f2f9275528..bbee2cd40993 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -416,13 +416,13 @@ static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, */ static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) { - if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) + if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags)) wiphy_rfkill_start_polling(rt2x00dev->hw->wiphy); } static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) { - if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) + if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags)) wiphy_rfkill_stop_polling(rt2x00dev->hw->wiphy); } diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index 128b3615c08c..ba0bb766e59e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -383,7 +383,7 @@ static void rt2x00link_tuner(struct work_struct *work) * do not support link tuning at all, while other devices can disable * the feature from the EEPROM. */ - if (test_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags)) + if (test_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags)) rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 4a1c41b59fea..4770156df1a8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -119,7 +119,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * Use the ATIM queue if appropriate and present. */ if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM && - test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) + test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags)) qid = QID_ATIM; queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); @@ -411,11 +411,11 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, * of different types, but has no a separate filter for PS Poll frames, * FIF_CONTROL flag implies FIF_PSPOLL. */ - if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags)) { + if (!test_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags)) { if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL) *total_flags |= FIF_CONTROL | FIF_PSPOLL; } - if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags)) { + if (!test_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags)) { if (*total_flags & FIF_CONTROL) *total_flags |= FIF_PSPOLL; } @@ -496,7 +496,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return 0; - else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) + else if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) return -EOPNOTSUPP; else if (key->keylen > 32) return -ENOSPC; @@ -562,7 +562,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_set_key); void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; - __set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); + set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); rt2x00link_stop_tuner(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); @@ -570,7 +570,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; - __clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); + clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); rt2x00link_start_tuner(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_complete); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 9fc4a1ec4b43..d03eef28f036 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -60,7 +60,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry) * at least 8 bytes bytes available in headroom for IV/EIV * and 8 bytes for ICV data as tailroon. */ - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { + if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) { head_size += 8; tail_size += 8; } @@ -86,7 +86,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry) memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->entry = entry; - if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) { + if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) { skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len, @@ -213,7 +213,7 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); - if (!test_bit(DRIVER_REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->flags)) + if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags)) return; /* @@ -396,7 +396,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, rt2x00crypto_create_tx_descriptor(entry, txdesc); rt2x00queue_create_tx_descriptor_seq(entry, txdesc); - if (test_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags)) + if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags)) rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate); else rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); @@ -436,7 +436,7 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry, /* * Map the skb to DMA. */ - if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) + if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) rt2x00queue_map_txskb(entry); return 0; @@ -529,7 +529,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, */ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { - if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags)) + if (test_bit(REQUIRE_COPY_IV, &queue->rt2x00dev->cap_flags)) rt2x00crypto_tx_copy_iv(skb, &txdesc); else rt2x00crypto_tx_remove_iv(skb, &txdesc); @@ -543,9 +543,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, * PCI and USB devices, while header alignment only is valid * for PCI devices. */ - if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags)) + if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags)) rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length); - else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) + else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags)) rt2x00queue_align_frame(entry->skb); /* @@ -1069,7 +1069,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) if (status) goto exit; - if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) { + if (test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags)) { status = rt2x00queue_alloc_entries(rt2x00dev->atim, rt2x00dev->ops->atim); if (status) @@ -1121,7 +1121,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) struct data_queue *queue; enum data_queue_qid qid; unsigned int req_atim = - !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); + !!test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); /* * We need the following queues: diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index fbe735f5b352..94047e9b2ec6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -387,7 +387,7 @@ static void rt2x00usb_flush_entry(struct queue_entry *entry) * Kill guardian urb (if required by driver). */ if ((entry->queue->qid == QID_BEACON) && - (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))) + (test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))) usb_kill_urb(bcn_priv->guardian_urb); } @@ -583,7 +583,7 @@ static int rt2x00usb_alloc_entries(struct data_queue *queue) * then we are done. */ if (queue->qid != QID_BEACON || - !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) + !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags)) return 0; for (i = 0; i < queue->limit; i++) { @@ -618,7 +618,7 @@ static void rt2x00usb_free_entries(struct data_queue *queue) * then we are done. */ if (queue->qid != QID_BEACON || - !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) + !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags)) return; for (i = 0; i < queue->limit; i++) { diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 8ee1514a7943..c16c1501df18 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -683,7 +683,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529)); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); + !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)); /* * Configure the RX antenna. @@ -811,10 +811,10 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { sel = antenna_sel_a; - lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); + lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); } else { sel = antenna_sel_bg; - lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); + lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); } for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) @@ -834,7 +834,7 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, else if (rt2x00_rf(rt2x00dev, RF2527)) rt61pci_config_antenna_2x(rt2x00dev, ant); else if (rt2x00_rf(rt2x00dev, RF2529)) { - if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) + if (test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) rt61pci_config_antenna_2x(rt2x00dev, ant); else rt61pci_config_antenna_2529(rt2x00dev, ant); @@ -848,13 +848,13 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev, short lna_gain = 0; if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) { - if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) + if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) lna_gain += 14; rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1); } else { - if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) + if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) lna_gain += 14; rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom); @@ -1050,14 +1050,14 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { low_bound = 0x28; up_bound = 0x48; - if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { + if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { low_bound += 0x10; up_bound += 0x10; } } else { low_bound = 0x20; up_bound = 0x40; - if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { + if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) { low_bound += 0x10; up_bound += 0x10; } @@ -2537,7 +2537,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * Determine number of antennas. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2) - __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags); + __set_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags); /* * Identify default antenna configuration. @@ -2551,20 +2551,20 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * Read the Frame type. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE)) - __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags); + __set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags); /* * Detect if this device has a hardware controlled radio. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); + __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); /* * Read frequency offset and RF programming sequence. */ rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ)) - __set_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags); + __set_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags); rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); @@ -2574,9 +2574,9 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A)) - __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); + __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) - __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); + __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); /* * When working with a RF2529 chip without double antenna, @@ -2584,7 +2584,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * eeprom word. */ if (rt2x00_rf(rt2x00dev, RF2529) && - !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) { + !test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) { rt2x00dev->default_ant.rx = ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); rt2x00dev->default_ant.tx = @@ -2799,7 +2799,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->supported_bands = SUPPORT_BAND_2GHZ; spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; - if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) { + if (!test_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags)) { spec->num_channels = 14; spec->channels = rf_vals_noseq; } else { @@ -2869,16 +2869,16 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) * This device has multiple filters for control frames, * but has no a separate filter for PS Poll frames. */ - __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); + __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); /* * This device requires firmware and DMA mapped skbs. */ - __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); + __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); if (!modparam_nohwcrypt) - __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); - __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); + __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); + __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); /* * Set the rssi offset. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 6593059f9c7e..cdb026d076db 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -595,7 +595,7 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, switch (ant->rx) { case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); - temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags) + temp = !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags) && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp); break; @@ -636,7 +636,7 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); + !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)); /* * Configure the RX antenna. @@ -709,10 +709,10 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev, if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { sel = antenna_sel_a; - lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); + lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); } else { sel = antenna_sel_bg; - lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); + lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); } for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) @@ -740,7 +740,7 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev, short lna_gain = 0; if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) { - if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) + if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) lna_gain += 14; rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); @@ -930,7 +930,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, low_bound = 0x28; up_bound = 0x48; - if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { + if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { low_bound += 0x10; up_bound += 0x10; } @@ -946,7 +946,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, up_bound = 0x1c; } - if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { + if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) { low_bound += 0x14; up_bound += 0x10; } @@ -1661,7 +1661,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) } if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { - if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { + if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { if (lna == 3 || lna == 2) offset += 10; } else { @@ -1899,13 +1899,13 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) * Read the Frame type. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE)) - __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags); + __set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags); /* * Detect if this device has an hardware controlled radio. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); + __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); /* * Read frequency offset. @@ -1919,8 +1919,8 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) { - __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); - __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); + __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); + __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); } /* @@ -2200,15 +2200,15 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) * This device has multiple filters for control frames, * but has no a separate filter for PS Poll frames. */ - __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); + __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); /* * This device requires firmware. */ - __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); + __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); if (!modparam_nohwcrypt) - __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); - __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); + __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); + __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); /* * Set the rssi offset. -- cgit v1.2.3-58-ga151 From 10e11568ca8b8a15f7478f6a4ceebabcbdba1018 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 18 Apr 2011 15:27:43 +0200 Subject: rt2x00: Make rt2x00_queue_entry_for_each more flexible Allow passing a void pointer to rt2x00_queue_entry_for_each which in turn in provided to the callback function. Furthermore, allow the callback function to stop processing by returning true. And also notify the caller of rt2x00_queue_entry_for_each if the loop was canceled by the callback. No functional changes, just preparation for an upcoming patch. Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 28 ++++++++++++++++++--------- drivers/net/wireless/rt2x00/rt2x00queue.h | 10 ++++++++-- drivers/net/wireless/rt2x00/rt2x00usb.c | 32 +++++++++++++++++++++---------- 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index d03eef28f036..458bb489bc7c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -650,10 +650,12 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, return ret; } -void rt2x00queue_for_each_entry(struct data_queue *queue, +bool rt2x00queue_for_each_entry(struct data_queue *queue, enum queue_index start, enum queue_index end, - void (*fn)(struct queue_entry *entry)) + void *data, + bool (*fn)(struct queue_entry *entry, + void *data)) { unsigned long irqflags; unsigned int index_start; @@ -664,7 +666,7 @@ void rt2x00queue_for_each_entry(struct data_queue *queue, ERROR(queue->rt2x00dev, "Entry requested from invalid index range (%d - %d)\n", start, end); - return; + return true; } /* @@ -683,15 +685,23 @@ void rt2x00queue_for_each_entry(struct data_queue *queue, * send out all frames in the correct order. */ if (index_start < index_end) { - for (i = index_start; i < index_end; i++) - fn(&queue->entries[i]); + for (i = index_start; i < index_end; i++) { + if (fn(&queue->entries[i], data)) + return true; + } } else { - for (i = index_start; i < queue->limit; i++) - fn(&queue->entries[i]); + for (i = index_start; i < queue->limit; i++) { + if (fn(&queue->entries[i], data)) + return true; + } - for (i = 0; i < index_end; i++) - fn(&queue->entries[i]); + for (i = 0; i < index_end; i++) { + if (fn(&queue->entries[i], data)) + return true; + } } + + return false; } EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 6ae820093997..6b664525135d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -580,16 +580,22 @@ struct data_queue_desc { * @queue: Pointer to @data_queue * @start: &enum queue_index Pointer to start index * @end: &enum queue_index Pointer to end index + * @data: Data to pass to the callback function * @fn: The function to call for each &struct queue_entry * * This will walk through all entries in the queue, in chronological * order. This means it will start at the current @start pointer * and will walk through the queue until it reaches the @end pointer. + * + * If fn returns true for an entry rt2x00queue_for_each_entry will stop + * processing and return true as well. */ -void rt2x00queue_for_each_entry(struct data_queue *queue, +bool rt2x00queue_for_each_entry(struct data_queue *queue, enum queue_index start, enum queue_index end, - void (*fn)(struct queue_entry *entry)); + void *data, + bool (*fn)(struct queue_entry *entry, + void *data)); /** * rt2x00queue_empty - Check if the queue is empty. diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 94047e9b2ec6..0bc8dccd0f0a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -230,7 +230,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); } -static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) +static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); @@ -240,7 +240,7 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) || test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) - return; + return true; /* * USB devices cannot blindly pass the skb->len as the @@ -261,6 +261,8 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); rt2x00lib_dmadone(entry); } + + return false; } /* @@ -323,7 +325,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); } -static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) +static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); @@ -332,7 +334,7 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) - return; + return true; rt2x00lib_dmastart(entry); @@ -348,6 +350,8 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); rt2x00lib_dmadone(entry); } + + return false; } void rt2x00usb_kick_queue(struct data_queue *queue) @@ -358,12 +362,18 @@ void rt2x00usb_kick_queue(struct data_queue *queue) case QID_AC_BE: case QID_AC_BK: if (!rt2x00queue_empty(queue)) - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00queue_for_each_entry(queue, + Q_INDEX_DONE, + Q_INDEX, + NULL, rt2x00usb_kick_tx_entry); break; case QID_RX: if (!rt2x00queue_full(queue)) - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00queue_for_each_entry(queue, + Q_INDEX_DONE, + Q_INDEX, + NULL, rt2x00usb_kick_rx_entry); break; default: @@ -372,14 +382,14 @@ void rt2x00usb_kick_queue(struct data_queue *queue) } EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); -static void rt2x00usb_flush_entry(struct queue_entry *entry) +static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct queue_entry_priv_usb *entry_priv = entry->priv_data; struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) - return; + return true; usb_kill_urb(entry_priv->urb); @@ -389,6 +399,8 @@ static void rt2x00usb_flush_entry(struct queue_entry *entry) if ((entry->queue->qid == QID_BEACON) && (test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))) usb_kill_urb(bcn_priv->guardian_urb); + + return false; } void rt2x00usb_flush_queue(struct data_queue *queue) @@ -396,7 +408,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue) struct work_struct *completion; unsigned int i; - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, rt2x00usb_flush_entry); /* @@ -489,7 +501,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) entry->flags = 0; if (entry->queue->qid == QID_RX) - rt2x00usb_kick_rx_entry(entry); + rt2x00usb_kick_rx_entry(entry, NULL); } EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); -- cgit v1.2.3-58-ga151 From 15a533c47f9ebb8dec8e440275136cbf9c493a1f Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 18 Apr 2011 15:28:04 +0200 Subject: rt2x00: Use correct TBTT_SYNC config in AP mode This seems to fix problems with some powersaving clients since a positive value in TBTT_SYNC_CFG_TBTT_ADJUST introduces beacon skew, which is not wanted in AP mode. Also update the rest of the TBTT_SYNC config according to the legacy drivers in AP mode. Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index c6f5584128e9..e0fa559bfa39 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1245,6 +1245,25 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + + if (conf->sync == TSF_SYNC_AP_NONE) { + /* + * Tune beacon queue transmit parameters for AP mode + */ + rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, ®); + rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 0); + rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 1); + rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32); + rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 0); + rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg); + } else { + rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, ®); + rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 4); + rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 2); + rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32); + rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 16); + rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg); + } } if (flags & CONFIG_UPDATE_MAC) { -- cgit v1.2.3-58-ga151 From 961636ba17fa45b27ee4674430e1e775b8966b0e Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 18 Apr 2011 15:28:27 +0200 Subject: rt2x00: Update TX_SW_CFG2 init value Bring the TX_SW_CFG2 initialisation for rt305x devices in sync with the ralink legacy drivers. Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index e0fa559bfa39..0e2c0061cfda 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2427,7 +2427,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) } else if (rt2800_is_305x_soc(rt2x00dev)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); - rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000001f); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030); } else if (rt2x00_rt(rt2x00dev, RT5390)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); -- cgit v1.2.3-58-ga151 From 8da3efbb4a18be30ed03dd05af18d0b026b15173 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 18 Apr 2011 15:28:50 +0200 Subject: rt2x00: Use TXOP_HTTXOP for beacons Use TXOP_HTTXOP for beacons to stay in sync with the legacy drivers. Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00ht.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c index e8c0c3e92c2f..a30f68c7fd7e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c @@ -92,14 +92,15 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, /* * Determine IFS values - * - Use TXOP_BACKOFF for management frames + * - Use TXOP_BACKOFF for management frames except beacons * - Use TXOP_SIFS for fragment bursts * - Use TXOP_HTTXOP for everything else * * Note: rt2800 devices won't use CTS protection (if used) * for frames not transmitted with TXOP_HTTXOP */ - if (ieee80211_is_mgmt(hdr->frame_control)) + if (ieee80211_is_mgmt(hdr->frame_control) && + !ieee80211_is_beacon(hdr->frame_control)) txdesc->u.ht.txop = TXOP_BACKOFF; else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) txdesc->u.ht.txop = TXOP_SIFS; -- cgit v1.2.3-58-ga151 From 0e0d39e5f3a3e59c8513b59d4feeeadcb93b707d Mon Sep 17 00:00:00 2001 From: Johannes Stezenbach Date: Mon, 18 Apr 2011 15:29:12 +0200 Subject: rt2800usb: read TX_STA_FIFO asynchronously Trying to fix the "TX status report missed" warnings by reading the TX_STA_FIFO entries as quickly as possible. The TX_STA_FIFO is too small in hardware, thus reading it only from the workqueue is too slow and entries get lost. Start an asynchronous read of the TX_STA_FIFO directly from the TX URB completion callback (atomic context, thus it cannot use the blocking rt2800_register_read()). If the async read returns a valid FIFO entry, it is pushed into a larger FIFO inside struct rt2x00_dev, until rt2800_txdone() picks it up. A .tx_dma_done callback is added to struct rt2x00lib_ops to trigger the async read from the URB completion callback. Signed-off-by: Johannes Stezenbach Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 34 +++++++-------------- drivers/net/wireless/rt2x00/rt2800usb.c | 31 +++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00.h | 1 + drivers/net/wireless/rt2x00/rt2x00usb.c | 53 +++++++++++++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00usb.h | 15 ++++++++++ 5 files changed, 110 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 0e2c0061cfda..d79c8fd41138 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -730,34 +730,20 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev) struct data_queue *queue; struct queue_entry *entry; u32 reg; - u8 pid; - int i; + u8 qid; - /* - * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO - * at most X times and also stop processing once the TX_STA_FIFO_VALID - * flag is not set anymore. - * - * The legacy drivers use X=TX_RING_SIZE but state in a comment - * that the TX_STA_FIFO stack has a size of 16. We stick to our - * tx ring size for now. - */ - for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { - rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); - if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) - break; + while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) { - /* - * Skip this entry when it contains an invalid - * queue identication number. + /* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus + * qid is guaranteed to be one of the TX QIDs */ - pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); - if (pid >= QID_RX) - continue; - - queue = rt2x00queue_get_tx_queue(rt2x00dev, pid); - if (unlikely(!queue)) + qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); + queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); + if (unlikely(!queue)) { + WARNING(rt2x00dev, "Got TX status for an unavailable " + "queue %u, dropping\n", qid); continue; + } /* * Inside each queue, we process each entry in a chronological diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index f3ce5e854be6..862430e600ad 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -98,6 +98,35 @@ static void rt2800usb_stop_queue(struct data_queue *queue) } } +static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, + int urb_status, u32 tx_status) +{ + if (urb_status) { + WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status); + return; + } + + /* try to read all TX_STA_FIFO entries before scheduling txdone_work */ + if (rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID)) { + if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status)) { + WARNING(rt2x00dev, "TX status FIFO overrun, " + "drop tx status report.\n"); + queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); + } else + rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, + rt2800usb_tx_sta_fifo_read_completed); + } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) + queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); +} + +static void rt2800usb_tx_dma_done(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + + rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, + rt2800usb_tx_sta_fifo_read_completed); +} + /* * Firmware functions */ @@ -565,6 +594,7 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); /* * Set the rssi offset. @@ -635,6 +665,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .kick_queue = rt2x00usb_kick_queue, .stop_queue = rt2800usb_stop_queue, .flush_queue = rt2x00usb_flush_queue, + .tx_dma_done = rt2800usb_tx_dma_done, .write_tx_desc = rt2800usb_write_tx_desc, .write_tx_data = rt2800usb_write_tx_data, .write_beacon = rt2800_write_beacon, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 79c385accfac..e3b9b5146bf5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -571,6 +571,7 @@ struct rt2x00lib_ops { void (*kick_queue) (struct data_queue *queue); void (*stop_queue) (struct data_queue *queue); void (*flush_queue) (struct data_queue *queue); + void (*tx_dma_done) (struct queue_entry *entry); /* * TX control handlers diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 0bc8dccd0f0a..5fbab6f19706 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -165,6 +165,56 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); + +struct rt2x00_async_read_data { + __le32 reg; + struct usb_ctrlrequest cr; + struct rt2x00_dev *rt2x00dev; + void (*callback)(struct rt2x00_dev *,int,u32); +}; + +static void rt2x00usb_register_read_async_cb(struct urb *urb) +{ + struct rt2x00_async_read_data *rd = urb->context; + rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg)); + kfree(urb->context); +} + +void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + void (*callback)(struct rt2x00_dev*,int,u32)) +{ + struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); + struct urb *urb; + struct rt2x00_async_read_data *rd; + + rd = kmalloc(sizeof(*rd), GFP_ATOMIC); + if (!rd) + return; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + kfree(rd); + return; + } + + rd->rt2x00dev = rt2x00dev; + rd->callback = callback; + rd->cr.bRequestType = USB_VENDOR_REQUEST_IN; + rd->cr.bRequest = USB_MULTI_READ; + rd->cr.wValue = 0; + rd->cr.wIndex = cpu_to_le16(offset); + rd->cr.wLength = cpu_to_le16(sizeof(u32)); + + usb_fill_control_urb(urb, usb_dev, usb_rcvctrlpipe(usb_dev, 0), + (unsigned char *)(&rd->cr), &rd->reg, sizeof(rd->reg), + rt2x00usb_register_read_async_cb, rd); + if (usb_submit_urb(urb, GFP_ATOMIC) < 0) + kfree(rd); + usb_free_urb(urb); +} +EXPORT_SYMBOL_GPL(rt2x00usb_register_read_async); + /* * TX data handlers. */ @@ -212,6 +262,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; + if (rt2x00dev->ops->lib->tx_dma_done) + rt2x00dev->ops->lib->tx_dma_done(entry); + /* * Report the frame as DMA done */ diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 6aaf51fc7ad8..e3faca6d2a4f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -345,6 +345,21 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, const struct rt2x00_field32 field, u32 *reg); +/** + * rt2x00usb_register_read_async - Asynchronously read 32bit register word + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @offset: Register offset + * @callback: Functon to call when read completes. + * + * Submit a control URB to read a 32bit register. This safe to + * be called from atomic context. The callback will be called + * when the URB completes. Otherwise the function is similar + * to rt2x00usb_register_read(). + */ +void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + void (*callback)(struct rt2x00_dev*,int,u32)); + /* * Radio handlers */ -- cgit v1.2.3-58-ga151 From 75256f0348d38f414b7ac50ac78d4a4532bb6762 Mon Sep 17 00:00:00 2001 From: Johannes Stezenbach Date: Mon, 18 Apr 2011 15:29:38 +0200 Subject: rt2x00: fix queue timeout checks Add a timestamp to each queue entry which is updated whenever the status of the entry changes, and remove the per-queue timestamps. The previous check was incorrect and caused both false positives and false negatives. With the corrected check it comes apparent that the TX status usually times out on rt2800usb unless there is sufficient traffic (i.e. the next TX will complete the previous TX status). Signed-off-by: Johannes Stezenbach Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 8 ++++---- drivers/net/wireless/rt2x00/rt2x00lib.h | 6 +++--- drivers/net/wireless/rt2x00/rt2x00queue.c | 11 +++++------ drivers/net/wireless/rt2x00/rt2x00queue.h | 23 +++++++++++++---------- drivers/net/wireless/rt2x00/rt2x00usb.c | 20 ++++++++++++++++++-- 5 files changed, 43 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index af25b0152cbc..2e490e0998da 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -225,7 +225,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); void rt2x00lib_dmastart(struct queue_entry *entry) { set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - rt2x00queue_index_inc(entry->queue, Q_INDEX); + rt2x00queue_index_inc(entry, Q_INDEX); } EXPORT_SYMBOL_GPL(rt2x00lib_dmastart); @@ -233,7 +233,7 @@ void rt2x00lib_dmadone(struct queue_entry *entry) { set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags); clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE); + rt2x00queue_index_inc(entry, Q_INDEX_DMA_DONE); } EXPORT_SYMBOL_GPL(rt2x00lib_dmadone); @@ -392,7 +392,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, rt2x00dev->ops->lib->clear_entry(entry); - rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); + rt2x00queue_index_inc(entry, Q_INDEX_DONE); /* * If the data queue was below the threshold before the txdone @@ -559,7 +559,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry) submit_entry: entry->flags = 0; - rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); + rt2x00queue_index_inc(entry, Q_INDEX_DONE); if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) rt2x00dev->ops->lib->clear_entry(entry); diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index bbee2cd40993..57ede6ccf40c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -175,14 +175,14 @@ int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev, /** * rt2x00queue_index_inc - Index incrementation function - * @queue: Queue (&struct data_queue) to perform the action on. + * @entry: Queue entry (&struct queue_entry) to perform the action on. * @index: Index type (&enum queue_index) to perform the action on. * - * This function will increase the requested index on the queue, + * This function will increase the requested index on the entry's queue, * it will grab the appropriate locks and handle queue overflow events by * resetting the index to the start of the queue. */ -void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); +void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index); /** * rt2x00queue_init_queues - Initialize all data queues diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 458bb489bc7c..df8817fed09e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -561,7 +561,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, set_bit(ENTRY_DATA_PENDING, &entry->flags); - rt2x00queue_index_inc(queue, Q_INDEX); + rt2x00queue_index_inc(entry, Q_INDEX); rt2x00queue_write_tx_descriptor(entry, &txdesc); rt2x00queue_kick_tx_queue(queue, &txdesc); @@ -727,8 +727,9 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, } EXPORT_SYMBOL_GPL(rt2x00queue_get_entry); -void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) +void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index) { + struct data_queue *queue = entry->queue; unsigned long irqflags; if (unlikely(index >= Q_INDEX_MAX)) { @@ -743,7 +744,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) if (queue->index[index] >= queue->limit) queue->index[index] = 0; - queue->last_action[index] = jiffies; + entry->last_action = jiffies; if (index == Q_INDEX) { queue->length++; @@ -969,10 +970,8 @@ static void rt2x00queue_reset(struct data_queue *queue) queue->count = 0; queue->length = 0; - for (i = 0; i < Q_INDEX_MAX; i++) { + for (i = 0; i < Q_INDEX_MAX; i++) queue->index[i] = 0; - queue->last_action[i] = jiffies; - } spin_unlock_irqrestore(&queue->index_lock, irqflags); } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 6b664525135d..36f4d03eff61 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -364,6 +364,7 @@ enum queue_entry_flags { * struct queue_entry: Entry inside the &struct data_queue * * @flags: Entry flags, see &enum queue_entry_flags. + * @last_action: Timestamp of last change. * @queue: The data queue (&struct data_queue) to which this entry belongs. * @skb: The buffer which is currently being transmitted (for TX queue), * or used to directly recieve data in (for RX queue). @@ -373,6 +374,7 @@ enum queue_entry_flags { */ struct queue_entry { unsigned long flags; + unsigned long last_action; struct data_queue *queue; @@ -463,7 +465,6 @@ struct data_queue { unsigned short threshold; unsigned short length; unsigned short index[Q_INDEX_MAX]; - unsigned long last_action[Q_INDEX_MAX]; unsigned short txop; unsigned short aifs; @@ -635,22 +636,24 @@ static inline int rt2x00queue_threshold(struct data_queue *queue) /** * rt2x00queue_status_timeout - Check if a timeout occured for STATUS reports - * @queue: Queue to check. + * @entry: Queue entry to check. */ -static inline int rt2x00queue_status_timeout(struct data_queue *queue) +static inline int rt2x00queue_status_timeout(struct queue_entry *entry) { - return time_after(queue->last_action[Q_INDEX_DMA_DONE], - queue->last_action[Q_INDEX_DONE] + (HZ / 10)); + if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) + return false; + return time_after(jiffies, entry->last_action + msecs_to_jiffies(100)); } /** - * rt2x00queue_timeout - Check if a timeout occured for DMA transfers - * @queue: Queue to check. + * rt2x00queuedma__timeout - Check if a timeout occured for DMA transfers + * @entry: Queue entry to check. */ -static inline int rt2x00queue_dma_timeout(struct data_queue *queue) +static inline int rt2x00queue_dma_timeout(struct queue_entry *entry) { - return time_after(queue->last_action[Q_INDEX], - queue->last_action[Q_INDEX_DMA_DONE] + (HZ / 10)); + if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + return false; + return time_after(jiffies, entry->last_action + msecs_to_jiffies(100)); } /** diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 5fbab6f19706..14736e217947 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -521,15 +521,31 @@ static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work); } +static int rt2x00usb_status_timeout(struct data_queue *queue) +{ + struct queue_entry *entry; + + entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); + return rt2x00queue_status_timeout(entry); +} + +static int rt2x00usb_dma_timeout(struct data_queue *queue) +{ + struct queue_entry *entry; + + entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE); + return rt2x00queue_dma_timeout(entry); +} + void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; tx_queue_for_each(rt2x00dev, queue) { if (!rt2x00queue_empty(queue)) { - if (rt2x00queue_dma_timeout(queue)) + if (rt2x00usb_dma_timeout(queue)) rt2x00usb_watchdog_tx_dma(queue); - if (rt2x00queue_status_timeout(queue)) + if (rt2x00usb_status_timeout(queue)) rt2x00usb_watchdog_tx_status(queue); } } -- cgit v1.2.3-58-ga151 From 6e6d6932a3f525d734f6c2f5845e9cadfaeddce9 Mon Sep 17 00:00:00 2001 From: Johannes Stezenbach Date: Mon, 18 Apr 2011 15:30:01 +0200 Subject: rt2800usb: handle TX status timeouts The watchdog just triggers rt2800usb_work_txdone() when it detects a TX status timeout, thus rt2800usb_work_txdone() needs to handle this case. Signed-off-by: Johannes Stezenbach Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 862430e600ad..69004b968122 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -449,11 +449,14 @@ static void rt2800usb_work_txdone(struct work_struct *work) while (!rt2x00queue_empty(queue)) { entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || - !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + break; + if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) + rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); + else if (rt2x00queue_status_timeout(entry)) + rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); + else break; - - rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); } } } -- cgit v1.2.3-58-ga151 From f0187a1987ed6524518ff2a533eaf8394ac1a500 Mon Sep 17 00:00:00 2001 From: Johannes Stezenbach Date: Mon, 18 Apr 2011 15:30:36 +0200 Subject: rt2800usb: add timer to handle TX_STA_FIFO TX status is reported by the hardware when a packet has been sent (or after TX failed after possible retries), which is some time after the DMA completion. Since the rt2800usb hardware can not signal interrupts we have to use a timer, otherwise the TX status would only be read by the next packet's TX DMA completion, or by the watchdog thread. Signed-off-by: Johannes Stezenbach Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 41 ++++++++++++++++++++++++++++++++- drivers/net/wireless/rt2x00/rt2x00.h | 6 +++++ drivers/net/wireless/rt2x00/rt2x00dev.c | 1 + drivers/net/wireless/rt2x00/rt2x00usb.c | 5 +++- 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 69004b968122..20059727ef80 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -98,6 +98,22 @@ static void rt2800usb_stop_queue(struct data_queue *queue) } } +/* + * test if there is an entry in any TX queue for which DMA is done + * but the TX status has not been returned yet + */ +static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + + tx_queue_for_each(rt2x00dev, queue) { + if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) != + rt2x00queue_get_entry(queue, Q_INDEX_DONE)) + return true; + } + return false; +} + static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, int urb_status, u32 tx_status) { @@ -115,8 +131,11 @@ static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, } else rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, rt2800usb_tx_sta_fifo_read_completed); - } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) + } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) { queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); + } else if (rt2800usb_txstatus_pending(rt2x00dev)) { + mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20)); + } } static void rt2800usb_tx_dma_done(struct queue_entry *entry) @@ -127,6 +146,14 @@ static void rt2800usb_tx_dma_done(struct queue_entry *entry) rt2800usb_tx_sta_fifo_read_completed); } +static void rt2800usb_tx_sta_fifo_timeout(unsigned long data) +{ + struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; + + rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, + rt2800usb_tx_sta_fifo_read_completed); +} + /* * Firmware functions */ @@ -459,6 +486,14 @@ static void rt2800usb_work_txdone(struct work_struct *work) break; } } + + /* + * The hw may delay sending the packet after DMA complete + * if the medium is busy, thus the TX_STA_FIFO entry is + * also delayed -> use a timer to retrieve it. + */ + if (rt2800usb_txstatus_pending(rt2x00dev)) + mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20)); } /* @@ -599,6 +634,10 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); + setup_timer(&rt2x00dev->txstatus_timer, + rt2800usb_tx_sta_fifo_timeout, + (unsigned long) rt2x00dev); + /* * Set the rssi offset. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index e3b9b5146bf5..8f37121bb83f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -923,6 +924,11 @@ struct rt2x00_dev { */ DECLARE_KFIFO_PTR(txstatus_fifo, u32); + /* + * Timer to ensure tx status reports are read (rt2800usb). + */ + struct timer_list txstatus_timer; + /* * Tasklet for processing tx status reports (rt2800pci). */ diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 2e490e0998da..7776d9f1f297 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1071,6 +1071,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) /* * Stop all work. */ + del_timer_sync(&rt2x00dev->txstatus_timer); cancel_work_sync(&rt2x00dev->intf_work); if (rt2x00_is_usb(rt2x00dev)) { cancel_work_sync(&rt2x00dev->rxdone_work); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 14736e217947..34b8a887831b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -280,7 +280,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) * Schedule the delayed work for reading the TX status * from the device. */ - queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); + if (!test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags) || + !kfifo_is_empty(&rt2x00dev->txstatus_fifo)) + queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); } static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data) @@ -816,6 +818,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone); INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone); + init_timer(&rt2x00dev->txstatus_timer); retval = rt2x00usb_alloc_reg(rt2x00dev); if (retval) -- cgit v1.2.3-58-ga151 From 152a599274b15028604e24ae2d9c9d7f49853977 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 18 Apr 2011 15:31:02 +0200 Subject: rt2x00: Decrease association time for USB devices When powersaving is enabled, assocaition times are very high (for WPA2 networks, the time can easily be around the 3 seconds). This is caused, because the flushing of the queues takes too much time. Without the flushing callback mac80211 assumes a timeout of 100ms while scanning. Limit all flush waiting loops to the same maximum. We can apply this maximum by passing the drop status to the driver, which makes sure the driver performs extra actions during the waiting for the queue to become empty. After these changes, association times fall within the healthy range of ~0.6 seconds with powersaving enabled. The difference between association time between powersaving enabled and disabled is now only ~0.1 second (which can also be due to the measuring method). Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 1 + drivers/net/wireless/rt2x00/rt2500pci.c | 1 + drivers/net/wireless/rt2x00/rt2800pci.c | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 2 +- drivers/net/wireless/rt2x00/rt2x00pci.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt2x00pci.h | 10 ++++++++++ drivers/net/wireless/rt2x00/rt2x00queue.c | 19 +++++-------------- drivers/net/wireless/rt2x00/rt2x00usb.c | 9 +++++---- drivers/net/wireless/rt2x00/rt2x00usb.h | 8 +++++--- drivers/net/wireless/rt2x00/rt61pci.c | 1 + 10 files changed, 39 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 5d1654a8bda8..6b7206eddfa5 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1740,6 +1740,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .start_queue = rt2400pci_start_queue, .kick_queue = rt2400pci_kick_queue, .stop_queue = rt2400pci_stop_queue, + .flush_queue = rt2x00pci_flush_queue, .write_tx_desc = rt2400pci_write_tx_desc, .write_beacon = rt2400pci_write_beacon, .fill_rxdone = rt2400pci_fill_rxdone, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 3da954e1b4ab..82e8012c7c27 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -2033,6 +2033,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .start_queue = rt2500pci_start_queue, .kick_queue = rt2500pci_kick_queue, .stop_queue = rt2500pci_stop_queue, + .flush_queue = rt2x00pci_flush_queue, .write_tx_desc = rt2500pci_write_tx_desc, .write_beacon = rt2500pci_write_beacon, .fill_rxdone = rt2500pci_fill_rxdone, diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 4241f1943842..d2fe5fd6f1eb 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1057,6 +1057,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .start_queue = rt2800pci_start_queue, .kick_queue = rt2800pci_kick_queue, .stop_queue = rt2800pci_stop_queue, + .flush_queue = rt2x00pci_flush_queue, .write_tx_desc = rt2800pci_write_tx_desc, .write_tx_data = rt2800_write_tx_data, .write_beacon = rt2800_write_beacon, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 8f37121bb83f..dcdc50d27ea0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -571,7 +571,7 @@ struct rt2x00lib_ops { void (*start_queue) (struct data_queue *queue); void (*kick_queue) (struct data_queue *queue); void (*stop_queue) (struct data_queue *queue); - void (*flush_queue) (struct data_queue *queue); + void (*flush_queue) (struct data_queue *queue, bool drop); void (*tx_dma_done) (struct queue_entry *entry); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 9649bd0cd718..695aecf6bd03 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -99,6 +99,15 @@ bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); +void rt2x00pci_flush_queue(struct data_queue *queue, bool drop) +{ + unsigned int i; + + for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++) + msleep(10); +} +EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue); + /* * Device initialization handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 07961b8b369a..5d5887426f7a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -107,6 +107,16 @@ struct queue_entry_priv_pci { */ bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); +/** + * rt2x00pci_flush_queue - Flush data queue + * @queue: Data queue to stop + * @drop: True to drop all pending frames. + * + * This will wait for a maximum of 100ms, waiting for the queues + * to become empty. + */ +void rt2x00pci_flush_queue(struct data_queue *queue, bool drop); + /* * Device initialization handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index df8817fed09e..0d79278a0a19 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -849,7 +849,6 @@ EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue); void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) { - unsigned int i; bool started; bool tx_queue = (queue->qid == QID_AC_VO) || @@ -884,20 +883,12 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) } /* - * Check if driver supports flushing, we can only guarentee - * full support for flushing if the driver is able - * to cancel all pending frames (drop = true). - */ - if (drop && queue->rt2x00dev->ops->lib->flush_queue) - queue->rt2x00dev->ops->lib->flush_queue(queue); - - /* - * When we don't want to drop any frames, or when - * the driver doesn't fully flush the queue correcly, - * we must wait for the queue to become empty. + * Check if driver supports flushing, if that is the case we can + * defer the flushing to the driver. Otherwise we must use the + * alternative which just waits for the queue to become empty. */ - for (i = 0; !rt2x00queue_empty(queue) && i < 100; i++) - msleep(10); + if (likely(queue->rt2x00dev->ops->lib->flush_queue)) + queue->rt2x00dev->ops->lib->flush_queue(queue, drop); /* * The queue flush has failed... diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 34b8a887831b..9957579248c4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -458,13 +458,14 @@ static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data) return false; } -void rt2x00usb_flush_queue(struct data_queue *queue) +void rt2x00usb_flush_queue(struct data_queue *queue, bool drop) { struct work_struct *completion; unsigned int i; - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, - rt2x00usb_flush_entry); + if (drop) + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, + rt2x00usb_flush_entry); /* * Obtain the queue completion handler @@ -483,7 +484,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue) return; } - for (i = 0; i < 20; i++) { + for (i = 0; i < 10; i++) { /* * Check if the driver is already done, otherwise we * have to sleep a little while to give the driver/hw diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index e3faca6d2a4f..6aeba71b665b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -404,11 +404,13 @@ void rt2x00usb_kick_queue(struct data_queue *queue); /** * rt2x00usb_flush_queue - Flush data queue * @queue: Data queue to stop + * @drop: True to drop all pending frames. * - * This will walk through all entries of the queue and kill all - * URB's which were send to the device. + * This will walk through all entries of the queue and will optionally + * kill all URB's which were send to the device, or at least wait until + * they have been returned from the device.. */ -void rt2x00usb_flush_queue(struct data_queue *queue); +void rt2x00usb_flush_queue(struct data_queue *queue, bool drop); /** * rt2x00usb_watchdog - Watchdog for USB communication diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index c16c1501df18..35c5d20105a3 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -3003,6 +3003,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .start_queue = rt61pci_start_queue, .kick_queue = rt61pci_kick_queue, .stop_queue = rt61pci_stop_queue, + .flush_queue = rt2x00pci_flush_queue, .write_tx_desc = rt61pci_write_tx_desc, .write_beacon = rt61pci_write_beacon, .clear_beacon = rt61pci_clear_beacon, -- cgit v1.2.3-58-ga151 From 7a5a681a7df7d844b52f82a4388e078071eb883e Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 18 Apr 2011 15:31:31 +0200 Subject: rt2x00: Always inline rt2x00pci_enable_interrupt This allows the compiler to perform the necessary bitfield calculations during compile time instead of run time and thus reduces the number of instructions to run during each tasklet invocation. This should improve performance in the RX hotpath. This comes at the cost of a slight increase in the module size (for example rt2800pci): Before: text data bss dec hex filename 14133 832 4 14969 3a79 drivers/net/wireless/rt2x00/rt2800pci.ko After: text data bss dec hex filename 14149 832 4 14985 3a89 drivers/net/wireless/rt2x00/rt2800pci.ko Signed-off-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 4 ++-- drivers/net/wireless/rt2x00/rt2500pci.c | 4 ++-- drivers/net/wireless/rt2x00/rt2800pci.c | 4 ++-- drivers/net/wireless/rt2x00/rt61pci.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 6b7206eddfa5..01e951717f0f 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1314,8 +1314,8 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, } } -static void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, - struct rt2x00_field32 irq_field) +static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, + struct rt2x00_field32 irq_field) { u32 reg; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 82e8012c7c27..c8deeeb9d812 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1446,8 +1446,8 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, } } -static void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, - struct rt2x00_field32 irq_field) +static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, + struct rt2x00_field32 irq_field) { u32 reg; diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index d2fe5fd6f1eb..46c3e3c83e31 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -768,8 +768,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) return !max_tx_done; } -static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, - struct rt2x00_field32 irq_field) +static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, + struct rt2x00_field32 irq_field) { u32 reg; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 35c5d20105a3..264508f31a2a 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2260,8 +2260,8 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); } -static void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, - struct rt2x00_field32 irq_field) +static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, + struct rt2x00_field32 irq_field) { u32 reg; -- cgit v1.2.3-58-ga151 From ce2919c9fffe2aa52f9c3e327176d03764dbf9b5 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 18 Apr 2011 15:31:50 +0200 Subject: rt2x00: Linksys WUSB600N rev2 is a RT3572 device. Move the USB ID entry from the unknown devices to the list of RT35xx based devices. Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 20059727ef80..1bb9a7d09de5 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -983,6 +983,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Linksys */ { USB_DEVICE(0x13b1, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ralink */ { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ @@ -1041,7 +1042,6 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Linksys */ { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Motorola */ { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ovislink */ -- cgit v1.2.3-58-ga151 From e01ae27f8ce6bd3ee26ef33c704f62449ce8233b Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 18 Apr 2011 15:32:13 +0200 Subject: rt2x00: Allow dynamic addition of PCI/USB IDs. Both USB and PCI drivers allow a system administrator to dynamically add USB/PCI IDs to the device table that a driver supports via the /sys/bus/{usb,pci,pci_express}/drivers//new_id files. However, for the rt2x00 drivers using this method currently crashes the system with a NULL pointer failure. This is due to the set-up of rt2x00 where the probe functions require a rt2x00_ops structure in the driver_info field of the probed device. As this field is empty for the dynamically added devices this fails for these devices. Fix this by introducing driver-specific probe wrappers that do nothing but calling the bus-specific probe functions with the rt2x00_ops structure as an argument, rather than depending on the driver_info field. Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 11 +- drivers/net/wireless/rt2x00/rt2500pci.c | 10 +- drivers/net/wireless/rt2x00/rt2500usb.c | 70 ++--- drivers/net/wireless/rt2x00/rt2800pci.c | 58 +++-- drivers/net/wireless/rt2x00/rt2800usb.c | 440 ++++++++++++++++---------------- drivers/net/wireless/rt2x00/rt2x00pci.c | 3 +- drivers/net/wireless/rt2x00/rt2x00pci.h | 2 +- drivers/net/wireless/rt2x00/rt2x00usb.c | 3 +- drivers/net/wireless/rt2x00/rt2x00usb.h | 8 +- drivers/net/wireless/rt2x00/rt61pci.c | 14 +- drivers/net/wireless/rt2x00/rt73usb.c | 154 +++++------ 11 files changed, 404 insertions(+), 369 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 01e951717f0f..d4acdde7c75a 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1802,10 +1802,11 @@ static const struct rt2x00_ops rt2400pci_ops = { * RT2400pci module information. */ static DEFINE_PCI_DEVICE_TABLE(rt2400pci_device_table) = { - { PCI_DEVICE(0x1814, 0x0101), PCI_DEVICE_DATA(&rt2400pci_ops) }, + { PCI_DEVICE(0x1814, 0x0101) }, { 0, } }; + MODULE_AUTHOR(DRV_PROJECT); MODULE_VERSION(DRV_VERSION); MODULE_DESCRIPTION("Ralink RT2400 PCI & PCMCIA Wireless LAN driver."); @@ -1813,10 +1814,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2460 PCI & PCMCIA chipset based cards"); MODULE_DEVICE_TABLE(pci, rt2400pci_device_table); MODULE_LICENSE("GPL"); +static int rt2400pci_probe(struct pci_dev *pci_dev, + const struct pci_device_id *id) +{ + return rt2x00pci_probe(pci_dev, &rt2400pci_ops); +} + static struct pci_driver rt2400pci_driver = { .name = KBUILD_MODNAME, .id_table = rt2400pci_device_table, - .probe = rt2x00pci_probe, + .probe = rt2400pci_probe, .remove = __devexit_p(rt2x00pci_remove), .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index c8deeeb9d812..15f5649e2cae 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -2095,7 +2095,7 @@ static const struct rt2x00_ops rt2500pci_ops = { * RT2500pci module information. */ static DEFINE_PCI_DEVICE_TABLE(rt2500pci_device_table) = { - { PCI_DEVICE(0x1814, 0x0201), PCI_DEVICE_DATA(&rt2500pci_ops) }, + { PCI_DEVICE(0x1814, 0x0201) }, { 0, } }; @@ -2106,10 +2106,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2560 PCI & PCMCIA chipset based cards"); MODULE_DEVICE_TABLE(pci, rt2500pci_device_table); MODULE_LICENSE("GPL"); +static int rt2500pci_probe(struct pci_dev *pci_dev, + const struct pci_device_id *id) +{ + return rt2x00pci_probe(pci_dev, &rt2500pci_ops); +} + static struct pci_driver rt2500pci_driver = { .name = KBUILD_MODNAME, .id_table = rt2500pci_device_table, - .probe = rt2x00pci_probe, + .probe = rt2500pci_probe, .remove = __devexit_p(rt2x00pci_remove), .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index dbbd8bc851f1..d88c36712ef0 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1904,54 +1904,54 @@ static const struct rt2x00_ops rt2500usb_ops = { */ static struct usb_device_id rt2500usb_device_table[] = { /* ASUS */ - { USB_DEVICE(0x0b05, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0b05, 0x1707), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0b05, 0x1706) }, + { USB_DEVICE(0x0b05, 0x1707) }, /* Belkin */ - { USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x050d, 0x7051), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x050d, 0x7050) }, + { USB_DEVICE(0x050d, 0x7051) }, /* Cisco Systems */ - { USB_DEVICE(0x13b1, 0x000d), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x13b1, 0x0011), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x13b1, 0x001a), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x13b1, 0x000d) }, + { USB_DEVICE(0x13b1, 0x0011) }, + { USB_DEVICE(0x13b1, 0x001a) }, /* Conceptronic */ - { USB_DEVICE(0x14b2, 0x3c02), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c02) }, /* D-LINK */ - { USB_DEVICE(0x2001, 0x3c00), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x2001, 0x3c00) }, /* Gigabyte */ - { USB_DEVICE(0x1044, 0x8001), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x1044, 0x8007), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x1044, 0x8001) }, + { USB_DEVICE(0x1044, 0x8007) }, /* Hercules */ - { USB_DEVICE(0x06f8, 0xe000), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x06f8, 0xe000) }, /* Melco */ - { USB_DEVICE(0x0411, 0x005e), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0411, 0x0066), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0411, 0x0067), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0411, 0x008b), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0411, 0x0097), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0411, 0x005e) }, + { USB_DEVICE(0x0411, 0x0066) }, + { USB_DEVICE(0x0411, 0x0067) }, + { USB_DEVICE(0x0411, 0x008b) }, + { USB_DEVICE(0x0411, 0x0097) }, /* MSI */ - { USB_DEVICE(0x0db0, 0x6861), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0db0, 0x6865), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0db0, 0x6869), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0db0, 0x6861) }, + { USB_DEVICE(0x0db0, 0x6865) }, + { USB_DEVICE(0x0db0, 0x6869) }, /* Ralink */ - { USB_DEVICE(0x148f, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x148f, 0x2570), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x148f, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x148f, 0x1706) }, + { USB_DEVICE(0x148f, 0x2570) }, + { USB_DEVICE(0x148f, 0x9020) }, /* Sagem */ - { USB_DEVICE(0x079b, 0x004b), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x079b, 0x004b) }, /* Siemens */ - { USB_DEVICE(0x0681, 0x3c06), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0681, 0x3c06) }, /* SMC */ - { USB_DEVICE(0x0707, 0xee13), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0707, 0xee13) }, /* Spairon */ - { USB_DEVICE(0x114b, 0x0110), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x114b, 0x0110) }, /* SURECOM */ - { USB_DEVICE(0x0769, 0x11f3), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0769, 0x11f3) }, /* Trust */ - { USB_DEVICE(0x0eb0, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0eb0, 0x9020) }, /* VTech */ - { USB_DEVICE(0x0f88, 0x3012), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0f88, 0x3012) }, /* Zinwell */ - { USB_DEVICE(0x5a57, 0x0260), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x5a57, 0x0260) }, { 0, } }; @@ -1962,10 +1962,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2570 USB chipset based cards"); MODULE_DEVICE_TABLE(usb, rt2500usb_device_table); MODULE_LICENSE("GPL"); +static int rt2500usb_probe(struct usb_interface *usb_intf, + const struct usb_device_id *id) +{ + return rt2x00usb_probe(usb_intf, &rt2500usb_ops); +} + static struct usb_driver rt2500usb_driver = { .name = KBUILD_MODNAME, .id_table = rt2500usb_device_table, - .probe = rt2x00usb_probe, + .probe = rt2500usb_probe, .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 46c3e3c83e31..6f91a9ad4d31 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1117,36 +1117,36 @@ static const struct rt2x00_ops rt2800pci_ops = { */ #ifdef CONFIG_PCI static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { - { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1432, 0x7738), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x0601) }, + { PCI_DEVICE(0x1814, 0x0681) }, + { PCI_DEVICE(0x1814, 0x0701) }, + { PCI_DEVICE(0x1814, 0x0781) }, + { PCI_DEVICE(0x1814, 0x3090) }, + { PCI_DEVICE(0x1814, 0x3091) }, + { PCI_DEVICE(0x1814, 0x3092) }, + { PCI_DEVICE(0x1432, 0x7708) }, + { PCI_DEVICE(0x1432, 0x7727) }, + { PCI_DEVICE(0x1432, 0x7728) }, + { PCI_DEVICE(0x1432, 0x7738) }, + { PCI_DEVICE(0x1432, 0x7748) }, + { PCI_DEVICE(0x1432, 0x7758) }, + { PCI_DEVICE(0x1432, 0x7768) }, + { PCI_DEVICE(0x1462, 0x891a) }, + { PCI_DEVICE(0x1a3b, 0x1059) }, #ifdef CONFIG_RT2800PCI_RT33XX - { PCI_DEVICE(0x1814, 0x3390), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3390) }, #endif #ifdef CONFIG_RT2800PCI_RT35XX - { PCI_DEVICE(0x1432, 0x7711), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1432, 0x7722), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3593), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1432, 0x7711) }, + { PCI_DEVICE(0x1432, 0x7722) }, + { PCI_DEVICE(0x1814, 0x3060) }, + { PCI_DEVICE(0x1814, 0x3062) }, + { PCI_DEVICE(0x1814, 0x3562) }, + { PCI_DEVICE(0x1814, 0x3592) }, + { PCI_DEVICE(0x1814, 0x3593) }, #endif #ifdef CONFIG_RT2800PCI_RT53XX - { PCI_DEVICE(0x1814, 0x5390), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x5390) }, #endif { 0, } }; @@ -1182,10 +1182,16 @@ static struct platform_driver rt2800soc_driver = { #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ #ifdef CONFIG_PCI +static int rt2800pci_probe(struct pci_dev *pci_dev, + const struct pci_device_id *id) +{ + return rt2x00pci_probe(pci_dev, &rt2800pci_ops); +} + static struct pci_driver rt2800pci_driver = { .name = KBUILD_MODNAME, .id_table = rt2800pci_device_table, - .probe = rt2x00pci_probe, + .probe = rt2800pci_probe, .remove = __devexit_p(rt2x00pci_remove), .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 1bb9a7d09de5..6f7c16174575 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -768,230 +768,230 @@ static const struct rt2x00_ops rt2800usb_ops = { */ static struct usb_device_id rt2800usb_device_table[] = { /* Abocom */ - { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x2870) }, + { USB_DEVICE(0x07b8, 0x2770) }, + { USB_DEVICE(0x07b8, 0x3070) }, + { USB_DEVICE(0x07b8, 0x3071) }, + { USB_DEVICE(0x07b8, 0x3072) }, + { USB_DEVICE(0x1482, 0x3c09) }, /* AirTies */ - { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1eda, 0x2310) }, /* Allwin */ - { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x2070) }, + { USB_DEVICE(0x8516, 0x2770) }, + { USB_DEVICE(0x8516, 0x2870) }, + { USB_DEVICE(0x8516, 0x3070) }, + { USB_DEVICE(0x8516, 0x3071) }, + { USB_DEVICE(0x8516, 0x3072) }, /* Alpha Networks */ - { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c2c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c06) }, + { USB_DEVICE(0x14b2, 0x3c07) }, + { USB_DEVICE(0x14b2, 0x3c09) }, + { USB_DEVICE(0x14b2, 0x3c12) }, + { USB_DEVICE(0x14b2, 0x3c23) }, + { USB_DEVICE(0x14b2, 0x3c25) }, + { USB_DEVICE(0x14b2, 0x3c27) }, + { USB_DEVICE(0x14b2, 0x3c28) }, + { USB_DEVICE(0x14b2, 0x3c2c) }, /* Amit */ - { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x15c5, 0x0008) }, /* Askey */ - { USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1690, 0x0740) }, /* ASUS */ - { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1731) }, + { USB_DEVICE(0x0b05, 0x1732) }, + { USB_DEVICE(0x0b05, 0x1742) }, + { USB_DEVICE(0x0b05, 0x1784) }, + { USB_DEVICE(0x1761, 0x0b05) }, /* AzureWave */ - { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3247) }, + { USB_DEVICE(0x13d3, 0x3273) }, + { USB_DEVICE(0x13d3, 0x3305) }, + { USB_DEVICE(0x13d3, 0x3307) }, + { USB_DEVICE(0x13d3, 0x3321) }, /* Belkin */ - { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x050d, 0x825b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x050d, 0x935a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x050d, 0x935b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x8053) }, + { USB_DEVICE(0x050d, 0x805c) }, + { USB_DEVICE(0x050d, 0x815c) }, + { USB_DEVICE(0x050d, 0x825b) }, + { USB_DEVICE(0x050d, 0x935a) }, + { USB_DEVICE(0x050d, 0x935b) }, /* Buffalo */ - { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0411, 0x016f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0411, 0x01a2), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0411, 0x00e8) }, + { USB_DEVICE(0x0411, 0x016f) }, + { USB_DEVICE(0x0411, 0x01a2) }, /* Corega */ - { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07aa, 0x002f) }, + { USB_DEVICE(0x07aa, 0x003c) }, + { USB_DEVICE(0x07aa, 0x003f) }, + { USB_DEVICE(0x18c5, 0x0012) }, /* D-Link */ - { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c09) }, + { USB_DEVICE(0x07d1, 0x3c0a) }, + { USB_DEVICE(0x07d1, 0x3c0d) }, + { USB_DEVICE(0x07d1, 0x3c0e) }, + { USB_DEVICE(0x07d1, 0x3c0f) }, + { USB_DEVICE(0x07d1, 0x3c11) }, + { USB_DEVICE(0x07d1, 0x3c16) }, /* Draytek */ - { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07fa, 0x7712) }, /* Edimax */ - { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x7392, 0x7711) }, + { USB_DEVICE(0x7392, 0x7717) }, + { USB_DEVICE(0x7392, 0x7718) }, /* Encore */ - { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x203d, 0x1480) }, + { USB_DEVICE(0x203d, 0x14a9) }, /* EnGenius */ - { USB_DEVICE(0x1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9701) }, + { USB_DEVICE(0x1740, 0x9702) }, + { USB_DEVICE(0x1740, 0x9703) }, + { USB_DEVICE(0x1740, 0x9705) }, + { USB_DEVICE(0x1740, 0x9706) }, + { USB_DEVICE(0x1740, 0x9707) }, + { USB_DEVICE(0x1740, 0x9708) }, + { USB_DEVICE(0x1740, 0x9709) }, /* Gemtek */ - { USB_DEVICE(0x15a9, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x15a9, 0x0012) }, /* Gigabyte */ - { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1044, 0x800b) }, + { USB_DEVICE(0x1044, 0x800d) }, /* Hawking */ - { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e66, 0x0013), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e66, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e66, 0x0018), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0001) }, + { USB_DEVICE(0x0e66, 0x0003) }, + { USB_DEVICE(0x0e66, 0x0009) }, + { USB_DEVICE(0x0e66, 0x000b) }, + { USB_DEVICE(0x0e66, 0x0013) }, + { USB_DEVICE(0x0e66, 0x0017) }, + { USB_DEVICE(0x0e66, 0x0018) }, /* I-O DATA */ - { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x04bb, 0x0945) }, + { USB_DEVICE(0x04bb, 0x0947) }, + { USB_DEVICE(0x04bb, 0x0948) }, /* Linksys */ - { USB_DEVICE(0x13b1, 0x0031), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13b1, 0x0031) }, + { USB_DEVICE(0x1737, 0x0070) }, + { USB_DEVICE(0x1737, 0x0071) }, /* Logitec */ - { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0789, 0x0162) }, + { USB_DEVICE(0x0789, 0x0163) }, + { USB_DEVICE(0x0789, 0x0164) }, + { USB_DEVICE(0x0789, 0x0166) }, /* Motorola */ - { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x100d, 0x9031) }, /* MSI */ - { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3820) }, + { USB_DEVICE(0x0db0, 0x3821) }, + { USB_DEVICE(0x0db0, 0x3822) }, + { USB_DEVICE(0x0db0, 0x3870) }, + { USB_DEVICE(0x0db0, 0x3871) }, + { USB_DEVICE(0x0db0, 0x6899) }, + { USB_DEVICE(0x0db0, 0x821a) }, + { USB_DEVICE(0x0db0, 0x822a) }, + { USB_DEVICE(0x0db0, 0x822b) }, + { USB_DEVICE(0x0db0, 0x822c) }, + { USB_DEVICE(0x0db0, 0x870a) }, + { USB_DEVICE(0x0db0, 0x871a) }, + { USB_DEVICE(0x0db0, 0x871b) }, + { USB_DEVICE(0x0db0, 0x871c) }, + { USB_DEVICE(0x0db0, 0x899a) }, /* Para */ - { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x20b8, 0x8888) }, /* Pegatron */ - { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x000c) }, + { USB_DEVICE(0x1d4d, 0x000e) }, + { USB_DEVICE(0x1d4d, 0x0011) }, /* Philips */ - { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0471, 0x200f) }, /* Planex */ - { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x2019, 0xab25) }, + { USB_DEVICE(0x2019, 0xed06) }, /* Quanta */ - { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1a32, 0x0304) }, /* Ralink */ - { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x2070) }, + { USB_DEVICE(0x148f, 0x2770) }, + { USB_DEVICE(0x148f, 0x2870) }, + { USB_DEVICE(0x148f, 0x3070) }, + { USB_DEVICE(0x148f, 0x3071) }, + { USB_DEVICE(0x148f, 0x3072) }, /* Samsung */ - { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x04e8, 0x2018) }, /* Siemens */ - { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x129b, 0x1828) }, /* Sitecom */ - { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0017) }, + { USB_DEVICE(0x0df6, 0x002b) }, + { USB_DEVICE(0x0df6, 0x002c) }, + { USB_DEVICE(0x0df6, 0x002d) }, + { USB_DEVICE(0x0df6, 0x0039) }, + { USB_DEVICE(0x0df6, 0x003b) }, + { USB_DEVICE(0x0df6, 0x003d) }, + { USB_DEVICE(0x0df6, 0x003e) }, + { USB_DEVICE(0x0df6, 0x003f) }, + { USB_DEVICE(0x0df6, 0x0040) }, + { USB_DEVICE(0x0df6, 0x0042) }, + { USB_DEVICE(0x0df6, 0x0047) }, + { USB_DEVICE(0x0df6, 0x0048) }, /* SMC */ - { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x6618) }, + { USB_DEVICE(0x083a, 0x7511) }, + { USB_DEVICE(0x083a, 0x7512) }, + { USB_DEVICE(0x083a, 0x7522) }, + { USB_DEVICE(0x083a, 0x8522) }, + { USB_DEVICE(0x083a, 0xa618) }, + { USB_DEVICE(0x083a, 0xa701) }, + { USB_DEVICE(0x083a, 0xa702) }, + { USB_DEVICE(0x083a, 0xa703) }, + { USB_DEVICE(0x083a, 0xb522) }, /* Sparklan */ - { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x15a9, 0x0006) }, /* Sweex */ - { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x177f, 0x0302) }, /* U-Media */ - { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x157e, 0x3013), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x157e, 0x300e) }, + { USB_DEVICE(0x157e, 0x3013) }, /* ZCOM */ - { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0cde, 0x0022) }, + { USB_DEVICE(0x0cde, 0x0025) }, /* Zinwell */ - { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x0280) }, + { USB_DEVICE(0x5a57, 0x0282) }, + { USB_DEVICE(0x5a57, 0x0283) }, + { USB_DEVICE(0x5a57, 0x5257) }, /* Zyxel */ - { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0586, 0x3418), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0586, 0x341e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0586, 0x3416) }, + { USB_DEVICE(0x0586, 0x3418) }, + { USB_DEVICE(0x0586, 0x341e) }, #ifdef CONFIG_RT2800USB_RT33XX /* Ralink */ - { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3370) }, + { USB_DEVICE(0x148f, 0x8070) }, /* Sitecom */ - { USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0050) }, #endif #ifdef CONFIG_RT2800USB_RT35XX /* Allwin */ - { USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3572) }, /* Askey */ - { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1690, 0x0744) }, /* Cisco */ - { USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x167b, 0x4001) }, /* EnGenius */ - { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9801) }, /* I-O DATA */ - { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x04bb, 0x0944) }, /* Linksys */ - { USB_DEVICE(0x13b1, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13b1, 0x002f) }, + { USB_DEVICE(0x1737, 0x0079) }, /* Ralink */ - { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3572) }, /* Sitecom */ - { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0041) }, /* Toshiba */ - { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0930, 0x0a07) }, /* Zinwell */ - { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x0284) }, #endif #ifdef CONFIG_RT2800USB_UNKNOWN /* @@ -999,73 +999,73 @@ static struct usb_device_id rt2800usb_device_table[] = { * vendor linux driver). */ /* Alpha Networks */ - { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c08) }, + { USB_DEVICE(0x14b2, 0x3c11) }, /* Amigo */ - { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e0b, 0x9031) }, + { USB_DEVICE(0x0e0b, 0x9041) }, /* ASUS */ - { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1760) }, + { USB_DEVICE(0x0b05, 0x1761) }, + { USB_DEVICE(0x0b05, 0x1790) }, /* AzureWave */ - { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3322), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3262) }, + { USB_DEVICE(0x13d3, 0x3284) }, + { USB_DEVICE(0x13d3, 0x3322) }, /* Belkin */ - { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x825a) }, /* Buffalo */ - { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0411, 0x012e) }, + { USB_DEVICE(0x0411, 0x0148) }, + { USB_DEVICE(0x0411, 0x0150) }, + { USB_DEVICE(0x0411, 0x015d) }, /* Corega */ - { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07aa, 0x0041) }, + { USB_DEVICE(0x07aa, 0x0042) }, + { USB_DEVICE(0x18c5, 0x0008) }, /* D-Link */ - { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c17), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0b) }, + { USB_DEVICE(0x07d1, 0x3c13) }, + { USB_DEVICE(0x07d1, 0x3c15) }, + { USB_DEVICE(0x07d1, 0x3c17) }, /* Edimax */ - { USB_DEVICE(0x7392, 0x4085), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x7392, 0x4085) }, /* Encore */ - { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x203d, 0x14a1) }, /* Gemtek */ - { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x15a9, 0x0010) }, /* Gigabyte */ - { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1044, 0x800c) }, /* LevelOne */ - { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x0605) }, + { USB_DEVICE(0x1740, 0x0615) }, /* Linksys */ - { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1737, 0x0077) }, + { USB_DEVICE(0x1737, 0x0078) }, /* Motorola */ - { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x100d, 0x9032) }, /* Ovislink */ - { USB_DEVICE(0x1b75, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1b75, 0x3071) }, + { USB_DEVICE(0x1b75, 0x3072) }, /* Pegatron */ - { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x05a6, 0x0101) }, + { USB_DEVICE(0x1d4d, 0x0002) }, + { USB_DEVICE(0x1d4d, 0x0010) }, /* Planex */ - { USB_DEVICE(0x2019, 0x5201), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x2019, 0x5201) }, + { USB_DEVICE(0x2019, 0xab24) }, /* Qcom */ - { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x18e8, 0x6259) }, /* SMC */ - { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xf511), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa512) }, + { USB_DEVICE(0x083a, 0xc522) }, + { USB_DEVICE(0x083a, 0xd522) }, + { USB_DEVICE(0x083a, 0xf511) }, /* Sweex */ - { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x177f, 0x0153) }, + { USB_DEVICE(0x177f, 0x0313) }, /* Zyxel */ - { USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0586, 0x341a) }, #endif { 0, } }; @@ -1078,10 +1078,16 @@ MODULE_DEVICE_TABLE(usb, rt2800usb_device_table); MODULE_FIRMWARE(FIRMWARE_RT2870); MODULE_LICENSE("GPL"); +static int rt2800usb_probe(struct usb_interface *usb_intf, + const struct usb_device_id *id) +{ + return rt2x00usb_probe(usb_intf, &rt2800usb_ops); +} + static struct usb_driver rt2800usb_driver = { .name = KBUILD_MODNAME, .id_table = rt2800usb_device_table, - .probe = rt2x00usb_probe, + .probe = rt2800usb_probe, .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 695aecf6bd03..17148bb24426 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -251,9 +251,8 @@ exit: return -ENOMEM; } -int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) +int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops) { - struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_data; struct ieee80211_hw *hw; struct rt2x00_dev *rt2x00dev; int retval; diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 5d5887426f7a..e2c99f2b9a14 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -126,7 +126,7 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev); /* * PCI driver handlers. */ -int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id); +int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops); void rt2x00pci_remove(struct pci_dev *pci_dev); #ifdef CONFIG_PM int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 9957579248c4..570184ee163c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -791,10 +791,9 @@ exit: } int rt2x00usb_probe(struct usb_interface *usb_intf, - const struct usb_device_id *id) + const struct rt2x00_ops *ops) { struct usb_device *usb_dev = interface_to_usbdev(usb_intf); - struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info; struct ieee80211_hw *hw; struct rt2x00_dev *rt2x00dev; int retval; diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 6aeba71b665b..52b09d2e11de 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -34,12 +34,6 @@ interface_to_usbdev(intf); \ }) -/* - * This variable should be used with the - * usb_driver structure initialization. - */ -#define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops) - /* * For USB vendor requests we need to pass a timeout * time in ms, for this we use the REGISTER_TIMEOUT, @@ -433,7 +427,7 @@ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev); * USB driver handlers. */ int rt2x00usb_probe(struct usb_interface *usb_intf, - const struct usb_device_id *id); + const struct rt2x00_ops *ops); void rt2x00usb_disconnect(struct usb_interface *usb_intf); #ifdef CONFIG_PM int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 264508f31a2a..c5dccdb2f175 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -3061,11 +3061,11 @@ static const struct rt2x00_ops rt61pci_ops = { */ static DEFINE_PCI_DEVICE_TABLE(rt61pci_device_table) = { /* RT2561s */ - { PCI_DEVICE(0x1814, 0x0301), PCI_DEVICE_DATA(&rt61pci_ops) }, + { PCI_DEVICE(0x1814, 0x0301) }, /* RT2561 v2 */ - { PCI_DEVICE(0x1814, 0x0302), PCI_DEVICE_DATA(&rt61pci_ops) }, + { PCI_DEVICE(0x1814, 0x0302) }, /* RT2661 */ - { PCI_DEVICE(0x1814, 0x0401), PCI_DEVICE_DATA(&rt61pci_ops) }, + { PCI_DEVICE(0x1814, 0x0401) }, { 0, } }; @@ -3080,10 +3080,16 @@ MODULE_FIRMWARE(FIRMWARE_RT2561s); MODULE_FIRMWARE(FIRMWARE_RT2661); MODULE_LICENSE("GPL"); +static int rt61pci_probe(struct pci_dev *pci_dev, + const struct pci_device_id *id) +{ + return rt2x00pci_probe(pci_dev, &rt61pci_ops); +} + static struct pci_driver rt61pci_driver = { .name = KBUILD_MODNAME, .id_table = rt61pci_device_table, - .probe = rt2x00pci_probe, + .probe = rt61pci_probe, .remove = __devexit_p(rt2x00pci_remove), .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index cdb026d076db..be3eb5e894ef 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2388,113 +2388,113 @@ static const struct rt2x00_ops rt73usb_ops = { */ static struct usb_device_id rt73usb_device_table[] = { /* AboCom */ - { USB_DEVICE(0x07b8, 0xb21b), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07b8, 0xb21c), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07b8, 0xb21d), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07b8, 0xb21e), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07b8, 0xb21f), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07b8, 0xb21b) }, + { USB_DEVICE(0x07b8, 0xb21c) }, + { USB_DEVICE(0x07b8, 0xb21d) }, + { USB_DEVICE(0x07b8, 0xb21e) }, + { USB_DEVICE(0x07b8, 0xb21f) }, /* AL */ - { USB_DEVICE(0x14b2, 0x3c10), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c10) }, /* Amigo */ - { USB_DEVICE(0x148f, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0eb0, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x148f, 0x9021) }, + { USB_DEVICE(0x0eb0, 0x9021) }, /* AMIT */ - { USB_DEVICE(0x18c5, 0x0002), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x18c5, 0x0002) }, /* Askey */ - { USB_DEVICE(0x1690, 0x0722), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x1690, 0x0722) }, /* ASUS */ - { USB_DEVICE(0x0b05, 0x1723), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0b05, 0x1724), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0b05, 0x1723) }, + { USB_DEVICE(0x0b05, 0x1724) }, /* Belkin */ - { USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x050d, 0x905b), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x050d, 0x705a) }, + { USB_DEVICE(0x050d, 0x905b) }, + { USB_DEVICE(0x050d, 0x905c) }, /* Billionton */ - { USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x1631, 0xc019) }, + { USB_DEVICE(0x08dd, 0x0120) }, /* Buffalo */ - { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0411, 0x00d9), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0411, 0x0137), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0411, 0x00d8) }, + { USB_DEVICE(0x0411, 0x00d9) }, + { USB_DEVICE(0x0411, 0x00f4) }, + { USB_DEVICE(0x0411, 0x0116) }, + { USB_DEVICE(0x0411, 0x0119) }, + { USB_DEVICE(0x0411, 0x0137) }, /* CEIVA */ - { USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x178d, 0x02be) }, /* CNet */ - { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x1371, 0x9022) }, + { USB_DEVICE(0x1371, 0x9032) }, /* Conceptronic */ - { USB_DEVICE(0x14b2, 0x3c22), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c22) }, /* Corega */ - { USB_DEVICE(0x07aa, 0x002e), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07aa, 0x002e) }, /* D-Link */ - { USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c06), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c03) }, + { USB_DEVICE(0x07d1, 0x3c04) }, + { USB_DEVICE(0x07d1, 0x3c06) }, + { USB_DEVICE(0x07d1, 0x3c07) }, /* Edimax */ - { USB_DEVICE(0x7392, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x7392, 0x7618), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x7392, 0x7318) }, + { USB_DEVICE(0x7392, 0x7618) }, /* EnGenius */ - { USB_DEVICE(0x1740, 0x3701), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x1740, 0x3701) }, /* Gemtek */ - { USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x15a9, 0x0004) }, /* Gigabyte */ - { USB_DEVICE(0x1044, 0x8008), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x1044, 0x800a), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x1044, 0x8008) }, + { USB_DEVICE(0x1044, 0x800a) }, /* Huawei-3Com */ - { USB_DEVICE(0x1472, 0x0009), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x1472, 0x0009) }, /* Hercules */ - { USB_DEVICE(0x06f8, 0xe002), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x06f8, 0xe010), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x06f8, 0xe020), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x06f8, 0xe002) }, + { USB_DEVICE(0x06f8, 0xe010) }, + { USB_DEVICE(0x06f8, 0xe020) }, /* Linksys */ - { USB_DEVICE(0x13b1, 0x0020), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x13b1, 0x0020) }, + { USB_DEVICE(0x13b1, 0x0023) }, + { USB_DEVICE(0x13b1, 0x0028) }, /* MSI */ - { USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0db0, 0x4600) }, + { USB_DEVICE(0x0db0, 0x6877) }, + { USB_DEVICE(0x0db0, 0x6874) }, + { USB_DEVICE(0x0db0, 0xa861) }, + { USB_DEVICE(0x0db0, 0xa874) }, /* Ovislink */ - { USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x1b75, 0x7318) }, /* Ralink */ - { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0812, 0x3101), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x04bb, 0x093d) }, + { USB_DEVICE(0x148f, 0x2573) }, + { USB_DEVICE(0x148f, 0x2671) }, + { USB_DEVICE(0x0812, 0x3101) }, /* Qcom */ - { USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x18e8, 0x6238), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x18e8, 0x6196) }, + { USB_DEVICE(0x18e8, 0x6229) }, + { USB_DEVICE(0x18e8, 0x6238) }, /* Samsung */ - { USB_DEVICE(0x04e8, 0x4471), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x04e8, 0x4471) }, /* Senao */ - { USB_DEVICE(0x1740, 0x7100), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x1740, 0x7100) }, /* Sitecom */ - { USB_DEVICE(0x0df6, 0x0024), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0df6, 0x0027), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0df6, 0x002f), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0df6, 0x90ac), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0df6, 0x0024) }, + { USB_DEVICE(0x0df6, 0x0027) }, + { USB_DEVICE(0x0df6, 0x002f) }, + { USB_DEVICE(0x0df6, 0x90ac) }, + { USB_DEVICE(0x0df6, 0x9712) }, /* Surecom */ - { USB_DEVICE(0x0769, 0x31f3), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0769, 0x31f3) }, /* Tilgin */ - { USB_DEVICE(0x6933, 0x5001), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x6933, 0x5001) }, /* Philips */ - { USB_DEVICE(0x0471, 0x200a), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0471, 0x200a) }, /* Planex */ - { USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x2019, 0xab01) }, + { USB_DEVICE(0x2019, 0xab50) }, /* WideTell */ - { USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x7167, 0x3840) }, /* Zcom */ - { USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0cde, 0x001c) }, /* ZyXEL */ - { USB_DEVICE(0x0586, 0x3415), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0586, 0x3415) }, { 0, } }; @@ -2506,10 +2506,16 @@ MODULE_DEVICE_TABLE(usb, rt73usb_device_table); MODULE_FIRMWARE(FIRMWARE_RT2571); MODULE_LICENSE("GPL"); +static int rt73usb_probe(struct usb_interface *usb_intf, + const struct usb_device_id *id) +{ + return rt2x00usb_probe(usb_intf, &rt73usb_ops); +} + static struct usb_driver rt73usb_driver = { .name = KBUILD_MODNAME, .id_table = rt73usb_device_table, - .probe = rt2x00usb_probe, + .probe = rt73usb_probe, .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, -- cgit v1.2.3-58-ga151 From 87a3b89f34fb20f644b42fa57d579b1f2833fd4d Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 18 Apr 2011 15:32:33 +0200 Subject: rt2x00: Add USB IDs. Add USB IDs that are listed in the latest Ralink Windows and/or Linux drivers. Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6f7c16174575..fd8aa997fd2a 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -775,6 +775,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07b8, 0x3072) }, { USB_DEVICE(0x1482, 0x3c09) }, /* AirTies */ + { USB_DEVICE(0x1eda, 0x2012) }, { USB_DEVICE(0x1eda, 0x2310) }, /* Allwin */ { USB_DEVICE(0x8516, 0x2070) }, @@ -933,6 +934,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0df6, 0x0042) }, { USB_DEVICE(0x0df6, 0x0047) }, { USB_DEVICE(0x0df6, 0x0048) }, + { USB_DEVICE(0x0df6, 0x0051) }, + { USB_DEVICE(0x0df6, 0x005f) }, /* SMC */ { USB_DEVICE(0x083a, 0x6618) }, { USB_DEVICE(0x083a, 0x7511) }, @@ -963,6 +966,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0586, 0x3416) }, { USB_DEVICE(0x0586, 0x3418) }, { USB_DEVICE(0x0586, 0x341e) }, + { USB_DEVICE(0x0586, 0x343e) }, #ifdef CONFIG_RT2800USB_RT33XX /* Ralink */ { USB_DEVICE(0x148f, 0x3370) }, @@ -998,6 +1002,9 @@ static struct usb_device_id rt2800usb_device_table[] = { * Unclear what kind of devices these are (they aren't supported by the * vendor linux driver). */ + /* Abocom */ + { USB_DEVICE(0x07b8, 0x3073) }, + { USB_DEVICE(0x07b8, 0x3074) }, /* Alpha Networks */ { USB_DEVICE(0x14b2, 0x3c08) }, { USB_DEVICE(0x14b2, 0x3c11) }, @@ -1005,14 +1012,17 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0e0b, 0x9031) }, { USB_DEVICE(0x0e0b, 0x9041) }, /* ASUS */ + { USB_DEVICE(0x0b05, 0x166a) }, { USB_DEVICE(0x0b05, 0x1760) }, { USB_DEVICE(0x0b05, 0x1761) }, { USB_DEVICE(0x0b05, 0x1790) }, + { USB_DEVICE(0x0b05, 0x179d) }, /* AzureWave */ { USB_DEVICE(0x13d3, 0x3262) }, { USB_DEVICE(0x13d3, 0x3284) }, { USB_DEVICE(0x13d3, 0x3322) }, /* Belkin */ + { USB_DEVICE(0x050d, 0x1003) }, { USB_DEVICE(0x050d, 0x825a) }, /* Buffalo */ { USB_DEVICE(0x0411, 0x012e) }, @@ -1028,20 +1038,29 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07d1, 0x3c13) }, { USB_DEVICE(0x07d1, 0x3c15) }, { USB_DEVICE(0x07d1, 0x3c17) }, + { USB_DEVICE(0x2001, 0x3c17) }, /* Edimax */ { USB_DEVICE(0x7392, 0x4085) }, + { USB_DEVICE(0x7392, 0x7722) }, /* Encore */ { USB_DEVICE(0x203d, 0x14a1) }, /* Gemtek */ { USB_DEVICE(0x15a9, 0x0010) }, /* Gigabyte */ { USB_DEVICE(0x1044, 0x800c) }, + /* Huawei */ + { USB_DEVICE(0x148f, 0xf101) }, + /* I-O DATA */ + { USB_DEVICE(0x04bb, 0x094b) }, /* LevelOne */ { USB_DEVICE(0x1740, 0x0605) }, { USB_DEVICE(0x1740, 0x0615) }, /* Linksys */ { USB_DEVICE(0x1737, 0x0077) }, { USB_DEVICE(0x1737, 0x0078) }, + /* Logitec */ + { USB_DEVICE(0x0789, 0x0168) }, + { USB_DEVICE(0x0789, 0x0169) }, /* Motorola */ { USB_DEVICE(0x100d, 0x9032) }, /* Ovislink */ @@ -1056,6 +1075,15 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x2019, 0xab24) }, /* Qcom */ { USB_DEVICE(0x18e8, 0x6259) }, + /* RadioShack */ + { USB_DEVICE(0x08b9, 0x1197) }, + /* Sitecom */ + { USB_DEVICE(0x0df6, 0x003c) }, + { USB_DEVICE(0x0df6, 0x004a) }, + { USB_DEVICE(0x0df6, 0x004d) }, + { USB_DEVICE(0x0df6, 0x0053) }, + { USB_DEVICE(0x0df6, 0x0060) }, + { USB_DEVICE(0x0df6, 0x0062) }, /* SMC */ { USB_DEVICE(0x083a, 0xa512) }, { USB_DEVICE(0x083a, 0xc522) }, -- cgit v1.2.3-58-ga151 From ccd3caa4516c56540017d1af6c810940eff6afb8 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 18 Apr 2011 15:33:00 +0200 Subject: rt2x00: RT33xx device support is no longer experimental. The rt33xx devices support for both PCI and USB devices has been in the tree for a couple of months now, and seems to be functional and not in a worse shape than the support for rt28xx and rt30xx devices. No longer mark it as experimental and enable the support for these devices by default. Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index f630552427b7..e7e361e09f0a 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -74,17 +74,13 @@ config RT2800PCI if RT2800PCI config RT2800PCI_RT33XX - bool "rt2800pci - Include support for rt33xx devices (EXPERIMENTAL)" - depends on EXPERIMENTAL - default n + bool "rt2800pci - Include support for rt33xx devices" + default y ---help--- This adds support for rt33xx wireless chipset family to the rt2800pci driver. Supported chips: RT3390 - Support for these devices is non-functional at the moment and is - intended for testers and developers. - config RT2800PCI_RT35XX bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)" depends on EXPERIMENTAL @@ -153,17 +149,13 @@ config RT2800USB if RT2800USB config RT2800USB_RT33XX - bool "rt2800usb - Include support for rt33xx devices (EXPERIMENTAL)" - depends on EXPERIMENTAL - default n + bool "rt2800usb - Include support for rt33xx devices" + default y ---help--- This adds support for rt33xx wireless chipset family to the rt2800usb driver. Supported chips: RT3370 - Support for these devices is non-functional at the moment and is - intended for testers and developers. - config RT2800USB_RT35XX bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)" depends on EXPERIMENTAL -- cgit v1.2.3-58-ga151 From ea81966ccc2edd324c1fa382260a62a4400a032a Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 18 Apr 2011 15:33:20 +0200 Subject: rt2x00: Enable support for RT53xx PCI devices by default. Code seems to be feature-complete, so no reason to not enable these devices by default. Also, remove the sentence about the support for these devices being non-functional. Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index e7e361e09f0a..d7e27b348363 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -96,15 +96,12 @@ config RT2800PCI_RT35XX config RT2800PCI_RT53XX bool "rt2800-pci - Include support for rt53xx devices (EXPERIMENTAL)" depends on EXPERIMENTAL - default n + default y ---help--- This adds support for rt53xx wireless chipset family to the rt2800pci driver. Supported chips: RT5390 - Support for these devices is non-functional at the moment and is - intended for testers and developers. - endif config RT2500USB -- cgit v1.2.3-58-ga151 From 46a01ec00d05581c5bd0c37e680d5b37af4953b4 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 18 Apr 2011 15:33:41 +0200 Subject: rt2x00: Merge rt2x00ht.c contents in other files. The two functions that are in rt2x00ht.c can be much better placed closer to the places where the call-sites of these functions are (one in rt2x00config.c and one in rt2x00queue.c) allowing us to make these functions static. Also, conditional compilations doesn't seem to be necessary anymore as 802.11n support is quite common nowadays. This makes the code a bit easier readable and searchable. Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 5 -- drivers/net/wireless/rt2x00/Makefile | 1 - drivers/net/wireless/rt2x00/rt2x00config.c | 28 ++++++ drivers/net/wireless/rt2x00/rt2x00ht.c | 137 ----------------------------- drivers/net/wireless/rt2x00/rt2x00lib.h | 24 ----- drivers/net/wireless/rt2x00/rt2x00queue.c | 81 ++++++++++++++++- 6 files changed, 108 insertions(+), 168 deletions(-) delete mode 100644 drivers/net/wireless/rt2x00/rt2x00ht.c diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index d7e27b348363..c45773108283 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -59,7 +59,6 @@ config RT2800PCI select RT2800_LIB select RT2X00_LIB_PCI if PCI select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X - select RT2X00_LIB_HT select RT2X00_LIB_FIRMWARE select RT2X00_LIB_CRYPTO select CRC_CCITT @@ -133,7 +132,6 @@ config RT2800USB depends on USB select RT2800_LIB select RT2X00_LIB_USB - select RT2X00_LIB_HT select RT2X00_LIB_FIRMWARE select RT2X00_LIB_CRYPTO select CRC_CCITT @@ -196,9 +194,6 @@ config RT2X00_LIB_USB config RT2X00_LIB tristate -config RT2X00_LIB_HT - boolean - config RT2X00_LIB_FIRMWARE boolean select FW_LOADER diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index 971339858297..349d5b8284a4 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile @@ -7,7 +7,6 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o -rt2x00lib-$(CONFIG_RT2X00_LIB_HT) += rt2x00ht.o obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index e225a66f59a0..f70a2b45d430 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -163,6 +163,34 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, rt2x00queue_start_queue(rt2x00dev->rx); } +static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf) +{ + struct hw_mode_spec *spec = &rt2x00dev->spec; + int center_channel; + u16 i; + + /* + * Initialize center channel to current channel. + */ + center_channel = spec->channels[conf->channel->hw_value].channel; + + /* + * Adjust center channel to HT40+ and HT40- operation. + */ + if (conf_is_ht40_plus(conf)) + center_channel += 2; + else if (conf_is_ht40_minus(conf)) + center_channel -= (center_channel == 14) ? 1 : 2; + + for (i = 0; i < spec->num_channels; i++) + if (spec->channels[i].channel == center_channel) + return i; + + WARN_ON(1); + return conf->channel->hw_value; +} + void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, unsigned int ieee80211_flags) diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c deleted file mode 100644 index a30f68c7fd7e..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - Copyright (C) 2004 - 2009 Ivo van Doorn - - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the - Free Software Foundation, Inc., - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - Module: rt2x00lib - Abstract: rt2x00 HT specific routines. - */ - -#include -#include - -#include "rt2x00.h" -#include "rt2x00lib.h" - -void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc, - const struct rt2x00_rate *hwrate) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); - struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; - - if (tx_info->control.sta) - txdesc->u.ht.mpdu_density = - tx_info->control.sta->ht_cap.ampdu_density; - - txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */ - - /* - * Only one STBC stream is supported for now. - */ - if (tx_info->flags & IEEE80211_TX_CTL_STBC) - txdesc->u.ht.stbc = 1; - - /* - * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the - * mcs rate to be used - */ - if (txrate->flags & IEEE80211_TX_RC_MCS) { - txdesc->u.ht.mcs = txrate->idx; - - /* - * MIMO PS should be set to 1 for STA's using dynamic SM PS - * when using more then one tx stream (>MCS7). - */ - if (tx_info->control.sta && txdesc->u.ht.mcs > 7 && - ((tx_info->control.sta->ht_cap.cap & - IEEE80211_HT_CAP_SM_PS) >> - IEEE80211_HT_CAP_SM_PS_SHIFT) == - WLAN_HT_CAP_SM_PS_DYNAMIC) - __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); - } else { - txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs); - if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - txdesc->u.ht.mcs |= 0x08; - } - - /* - * This frame is eligible for an AMPDU, however, don't aggregate - * frames that are intended to probe a specific tx rate. - */ - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU && - !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) - __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); - - /* - * Set 40Mhz mode if necessary (for legacy rates this will - * duplicate the frame to both channels). - */ - if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH || - txrate->flags & IEEE80211_TX_RC_DUP_DATA) - __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); - if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) - __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); - - /* - * Determine IFS values - * - Use TXOP_BACKOFF for management frames except beacons - * - Use TXOP_SIFS for fragment bursts - * - Use TXOP_HTTXOP for everything else - * - * Note: rt2800 devices won't use CTS protection (if used) - * for frames not transmitted with TXOP_HTTXOP - */ - if (ieee80211_is_mgmt(hdr->frame_control) && - !ieee80211_is_beacon(hdr->frame_control)) - txdesc->u.ht.txop = TXOP_BACKOFF; - else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) - txdesc->u.ht.txop = TXOP_SIFS; - else - txdesc->u.ht.txop = TXOP_HTTXOP; -} - -u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf) -{ - struct hw_mode_spec *spec = &rt2x00dev->spec; - int center_channel; - u16 i; - - /* - * Initialize center channel to current channel. - */ - center_channel = spec->channels[conf->channel->hw_value].channel; - - /* - * Adjust center channel to HT40+ and HT40- operation. - */ - if (conf_is_ht40_plus(conf)) - center_channel += 2; - else if (conf_is_ht40_minus(conf)) - center_channel -= (center_channel == 14) ? 1 : 2; - - for (i = 0; i < spec->num_channels; i++) - if (spec->channels[i].channel == center_channel) - return i; - - WARN_ON(1); - return conf->channel->hw_value; -} diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 57ede6ccf40c..322cc4f3de5d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -387,30 +387,6 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, } #endif /* CONFIG_RT2X00_LIB_CRYPTO */ -/* - * HT handlers. - */ -#ifdef CONFIG_RT2X00_LIB_HT -void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc, - const struct rt2x00_rate *hwrate); - -u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf); -#else -static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc, - const struct rt2x00_rate *hwrate) -{ -} - -static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf) -{ - return conf->channel->hw_value; -} -#endif /* CONFIG_RT2X00_LIB_HT */ - /* * RFkill handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 0d79278a0a19..56f9d0df9c61 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -302,6 +302,85 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry, } } +static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry, + struct txentry_desc *txdesc, + const struct rt2x00_rate *hwrate) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); + struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; + + if (tx_info->control.sta) + txdesc->u.ht.mpdu_density = + tx_info->control.sta->ht_cap.ampdu_density; + + txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */ + + /* + * Only one STBC stream is supported for now. + */ + if (tx_info->flags & IEEE80211_TX_CTL_STBC) + txdesc->u.ht.stbc = 1; + + /* + * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the + * mcs rate to be used + */ + if (txrate->flags & IEEE80211_TX_RC_MCS) { + txdesc->u.ht.mcs = txrate->idx; + + /* + * MIMO PS should be set to 1 for STA's using dynamic SM PS + * when using more then one tx stream (>MCS7). + */ + if (tx_info->control.sta && txdesc->u.ht.mcs > 7 && + ((tx_info->control.sta->ht_cap.cap & + IEEE80211_HT_CAP_SM_PS) >> + IEEE80211_HT_CAP_SM_PS_SHIFT) == + WLAN_HT_CAP_SM_PS_DYNAMIC) + __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); + } else { + txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs); + if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + txdesc->u.ht.mcs |= 0x08; + } + + /* + * This frame is eligible for an AMPDU, however, don't aggregate + * frames that are intended to probe a specific tx rate. + */ + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU && + !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) + __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); + + /* + * Set 40Mhz mode if necessary (for legacy rates this will + * duplicate the frame to both channels). + */ + if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH || + txrate->flags & IEEE80211_TX_RC_DUP_DATA) + __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); + if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) + __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); + + /* + * Determine IFS values + * - Use TXOP_BACKOFF for management frames except beacons + * - Use TXOP_SIFS for fragment bursts + * - Use TXOP_HTTXOP for everything else + * + * Note: rt2800 devices won't use CTS protection (if used) + * for frames not transmitted with TXOP_HTTXOP + */ + if (ieee80211_is_mgmt(hdr->frame_control) && + !ieee80211_is_beacon(hdr->frame_control)) + txdesc->u.ht.txop = TXOP_BACKOFF; + else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) + txdesc->u.ht.txop = TXOP_SIFS; + else + txdesc->u.ht.txop = TXOP_HTTXOP; +} + static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc) { @@ -397,7 +476,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, rt2x00queue_create_tx_descriptor_seq(entry, txdesc); if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags)) - rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate); + rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate); else rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); } -- cgit v1.2.3-58-ga151 From 9a8199961b22e61221a6114b8bbbc26ddcc243f7 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 18 Apr 2011 15:34:01 +0200 Subject: rt2x00: Optimize register access in rt2800pci All register reads/writes in rt2800pci were previously done with rt2800_register_read/rt2800_register_write. These however indirectly call rt2x00pci_register_read/rt2x00pci_register_write which adds an additional overhead of at least one call and several move instructions to each register access. Replacing the calls to rt2800_register_read/rt2800_register_write with direct calls to rt2x00pci_register_read/rt2x00pci_register_write gets rid of quite a number of instructions in the drivers hotpaths (IRQ handling and txdone handling). For consistency replace all references to rt2800_register_read/write with the rt2x00pci_register_read/write variants. Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 158 +++++++++++++++++--------------- 1 file changed, 84 insertions(+), 74 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 6f91a9ad4d31..b0c729b25c73 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -66,7 +66,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) return; for (i = 0; i < 200; i++) { - rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); + rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) || (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || @@ -80,8 +80,8 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) if (i == 200) ERROR(rt2x00dev, "MCU request failed, no response from hardware\n"); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); + rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); + rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); } #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) @@ -105,7 +105,7 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) struct rt2x00_dev *rt2x00dev = eeprom->data; u32 reg; - rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); + rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN); eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT); @@ -127,7 +127,7 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom) rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT, !!eeprom->reg_chip_select); - rt2800_register_write(rt2x00dev, E2PROM_CSR, reg); + rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); } static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) @@ -135,7 +135,7 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) struct eeprom_93cx6 eeprom; u32 reg; - rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); + rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); eeprom.data = rt2x00dev; eeprom.register_read = rt2800pci_eepromregister_read; @@ -195,9 +195,9 @@ static void rt2800pci_start_queue(struct data_queue *queue) switch (queue->qid) { case QID_RX: - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); break; case QID_BEACON: /* @@ -207,15 +207,15 @@ static void rt2800pci_start_queue(struct data_queue *queue) tasklet_enable(&rt2x00dev->tbtt_tasklet); tasklet_enable(&rt2x00dev->pretbtt_tasklet); - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); - rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); + rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, ®); rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 1); - rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); + rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg); break; default: break; @@ -233,11 +233,13 @@ static void rt2800pci_kick_queue(struct data_queue *queue) case QID_AC_BE: case QID_AC_BK: entry = rt2x00queue_get_entry(queue, Q_INDEX); - rt2800_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), entry->entry_idx); + rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), + entry->entry_idx); break; case QID_MGMT: entry = rt2x00queue_get_entry(queue, Q_INDEX); - rt2800_register_write(rt2x00dev, TX_CTX_IDX(5), entry->entry_idx); + rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(5), + entry->entry_idx); break; default: break; @@ -251,20 +253,20 @@ static void rt2800pci_stop_queue(struct data_queue *queue) switch (queue->qid) { case QID_RX: - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); break; case QID_BEACON: - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); - rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); + rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, ®); rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 0); - rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); + rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg); /* * Wait for tbtt tasklets to finish. @@ -295,7 +297,7 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, */ reg = 0; rt2x00_set_field32(®, PBF_SYS_CTRL_HOST_RAM_WRITE, 1); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg); + rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg); /* * Write firmware to device. @@ -303,11 +305,11 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, data, len); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); + rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); + rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); - rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); return 0; } @@ -351,7 +353,7 @@ static void rt2800pci_clear_entry(struct queue_entry *entry) * Set RX IDX in register to inform hardware that we have * handled this entry and it is available for reuse again. */ - rt2800_register_write(rt2x00dev, RX_CRX_IDX, + rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx); } else { rt2x00_desc_read(entry_priv->desc, 1, &word); @@ -369,45 +371,51 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) * Initialize registers. */ entry_priv = rt2x00dev->tx[0].entries[0].priv_data; - rt2800_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma); - rt2800_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit); - rt2800_register_write(rt2x00dev, TX_CTX_IDX0, 0); - rt2800_register_write(rt2x00dev, TX_DTX_IDX0, 0); + rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma); + rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0, + rt2x00dev->tx[0].limit); + rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0); + rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX0, 0); entry_priv = rt2x00dev->tx[1].entries[0].priv_data; - rt2800_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma); - rt2800_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit); - rt2800_register_write(rt2x00dev, TX_CTX_IDX1, 0); - rt2800_register_write(rt2x00dev, TX_DTX_IDX1, 0); + rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma); + rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1, + rt2x00dev->tx[1].limit); + rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0); + rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX1, 0); entry_priv = rt2x00dev->tx[2].entries[0].priv_data; - rt2800_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma); - rt2800_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit); - rt2800_register_write(rt2x00dev, TX_CTX_IDX2, 0); - rt2800_register_write(rt2x00dev, TX_DTX_IDX2, 0); + rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma); + rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2, + rt2x00dev->tx[2].limit); + rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0); + rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX2, 0); entry_priv = rt2x00dev->tx[3].entries[0].priv_data; - rt2800_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma); - rt2800_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit); - rt2800_register_write(rt2x00dev, TX_CTX_IDX3, 0); - rt2800_register_write(rt2x00dev, TX_DTX_IDX3, 0); + rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma); + rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3, + rt2x00dev->tx[3].limit); + rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0); + rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0); entry_priv = rt2x00dev->rx->entries[0].priv_data; - rt2800_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); - rt2800_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit); - rt2800_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1); - rt2800_register_write(rt2x00dev, RX_DRX_IDX, 0); + rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); + rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT, + rt2x00dev->rx[0].limit); + rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, + rt2x00dev->rx[0].limit - 1); + rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0); /* * Enable global DMA configuration */ - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); - rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - rt2800_register_write(rt2x00dev, DELAY_INT_CFG, 0); + rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0); return 0; } @@ -427,8 +435,8 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, * should clear the register to assure a clean state. */ if (state == STATE_RADIO_IRQ_ON) { - rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); - rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); + rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); + rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); /* * Enable tasklets. The beacon related tasklets are @@ -440,7 +448,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, } spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); - rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); + rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, 0); rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, 0); rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, mask); @@ -459,7 +467,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, INT_MASK_CSR_GPTIMER, 0); rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, 0); rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, 0); - rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); + rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); if (state == STATE_RADIO_IRQ_OFF) { @@ -480,7 +488,7 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) /* * Reset DMA indexes */ - rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); + rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); @@ -488,26 +496,26 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); - rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); + rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); + rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); + rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); if (rt2x00_rt(rt2x00dev, RT5390)) { - rt2800_register_read(rt2x00dev, AUX_CTRL, ®); + rt2x00pci_register_read(rt2x00dev, AUX_CTRL, ®); rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); - rt2800_register_write(rt2x00dev, AUX_CTRL, reg); + rt2x00pci_register_write(rt2x00dev, AUX_CTRL, reg); } - rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); + rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); return 0; } @@ -525,8 +533,8 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) { if (rt2x00_is_soc(rt2x00dev)) { rt2800_disable_radio(rt2x00dev); - rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0); - rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0); + rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0); + rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0); } } @@ -537,8 +545,10 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02); rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP); } else if (state == STATE_SLEEP) { - rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, 0xffffffff); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, 0xffffffff); + rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, + 0xffffffff); + rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, + 0xffffffff); rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01); } @@ -778,9 +788,9 @@ static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, * access needs locking. */ spin_lock_irq(&rt2x00dev->irqmask_lock); - rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); + rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); rt2x00_set_field32(®, irq_field, 1); - rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); + rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); spin_unlock_irq(&rt2x00dev->irqmask_lock); } @@ -851,7 +861,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) * need to lock the kfifo. */ for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { - rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status); + rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, &status); if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) break; @@ -873,8 +883,8 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) u32 reg, mask; /* Read status and ACK all interrupts */ - rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); - rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); + rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); + rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); if (!reg) return IRQ_NONE; @@ -914,9 +924,9 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) * the tasklet will reenable the appropriate interrupts. */ spin_lock(&rt2x00dev->irqmask_lock); - rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); + rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); reg &= mask; - rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); + rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); spin_unlock(&rt2x00dev->irqmask_lock); return IRQ_HANDLED; -- cgit v1.2.3-58-ga151 From 8d0a2dcfb6f965781cde6d9dfbd4540ab22a0eb9 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 18 Apr 2011 15:34:22 +0200 Subject: rt2x00: Optimize register access in rt2800usb All register reads/writes in rt2800usb were previously done with rt2800_register_read/rt2800_register_write. These however indirectly call rt2x00usb_register_read/rt2x00usb_register_write which adds an additional overhead of at least one call and several move instructions to each register access. Replacing the calls to rt2800_register_read/rt2800_register_write with direct calls to rt2x00usb_register_read/rt2x00usb_register_write gets rid of quite a number of instructions in the drivers hotpaths (IRQ handling and txdone handling). For consistency replace all references to rt2800_register_read/write with the rt2x00usb_register_read/write variants. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 56 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index fd8aa997fd2a..44ead759e20f 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -59,16 +59,16 @@ static void rt2800usb_start_queue(struct data_queue *queue) switch (queue->qid) { case QID_RX: - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); break; case QID_BEACON: - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); break; default: break; @@ -82,16 +82,16 @@ static void rt2800usb_stop_queue(struct data_queue *queue) switch (queue->qid) { case QID_RX: - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); break; case QID_BEACON: - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); break; default: break; @@ -185,11 +185,11 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev, /* * Write firmware to device. */ - rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, - data + offset, length); + rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, + data + offset, length); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); /* * Send firmware request to device to load firmware, @@ -204,7 +204,7 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev, } msleep(10); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); return 0; } @@ -222,22 +222,22 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) if (rt2800_wait_csr_ready(rt2x00dev)) return -EBUSY; - rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); + rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); + rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); - rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); + rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); + rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, USB_MODE_RESET, REGISTER_TIMEOUT); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); return 0; } @@ -249,7 +249,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev))) return -EIO; - rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); + rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, ®); rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, 0); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); @@ -262,7 +262,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) / 1024) - 3); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); - rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg); + rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg); return rt2800_enable_radio(rt2x00dev); } @@ -338,12 +338,12 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev) unsigned int i; u32 reg; - rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); + rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, ®); if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) { WARNING(rt2x00dev, "TX HW queue 0 timed out," " invoke forced kick\n"); - rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012); + rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012); for (i = 0; i < 10; i++) { udelay(10); @@ -351,15 +351,15 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev) break; } - rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); + rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006); } - rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); + rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, ®); if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) { WARNING(rt2x00dev, "TX HW queue 1 timed out," " invoke forced kick\n"); - rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a); + rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a); for (i = 0; i < 10; i++) { udelay(10); @@ -367,7 +367,7 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev) break; } - rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); + rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006); } rt2x00usb_watchdog(rt2x00dev); -- cgit v1.2.3-58-ga151 From e7dee444263a103a9a2ac5fd5d0b5e9dc177d57c Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 18 Apr 2011 15:34:41 +0200 Subject: rt2x00: Implement get_ringparam callback function With the get_ringparam callback function we can export ring parameters to ethtool through the mac80211 interface. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 1 + drivers/net/wireless/rt2x00/rt2500pci.c | 1 + drivers/net/wireless/rt2x00/rt2500usb.c | 1 + drivers/net/wireless/rt2x00/rt2800pci.c | 1 + drivers/net/wireless/rt2x00/rt2800usb.c | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 2 ++ drivers/net/wireless/rt2x00/rt2x00mac.c | 16 ++++++++++++++++ drivers/net/wireless/rt2x00/rt61pci.c | 1 + drivers/net/wireless/rt2x00/rt73usb.c | 1 + 9 files changed, 25 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index d4acdde7c75a..bbe76f79b62e 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1720,6 +1720,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .tx_last_beacon = rt2400pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, + .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 15f5649e2cae..6f489968e7a4 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -2013,6 +2013,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .tx_last_beacon = rt2500pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, + .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index d88c36712ef0..5ef338671d73 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1823,6 +1823,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .conf_tx = rt2x00mac_conf_tx, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, + .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index b0c729b25c73..08d3947fcb26 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1028,6 +1028,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = { .ampdu_action = rt2800_ampdu_action, .flush = rt2x00mac_flush, .get_survey = rt2800_get_survey, + .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2800_ops rt2800pci_rt2800_ops = { diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 44ead759e20f..0d4e8fa3e1f8 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -673,6 +673,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = { .ampdu_action = rt2800_ampdu_action, .flush = rt2x00mac_flush, .get_survey = rt2800_get_survey, + .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2800_ops rt2800usb_rt2800_ops = { diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index dcdc50d27ea0..f1d8f55d3ca8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1254,6 +1254,8 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop); +void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, + u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); /* * Driver allocation handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 4770156df1a8..6d1d38329e52 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -737,3 +737,19 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop) rt2x00queue_flush_queue(queue, drop); } EXPORT_SYMBOL_GPL(rt2x00mac_flush); + +void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, + u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct data_queue *queue; + + tx_queue_for_each(rt2x00dev, queue) { + *tx += queue->length; + *tx_max += queue->limit; + } + + *rx = rt2x00dev->rx->length; + *rx_max = rt2x00dev->rx->limit; +} +EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index c5dccdb2f175..eb5403108394 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2979,6 +2979,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .get_tsf = rt61pci_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, + .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index be3eb5e894ef..bf7fea4cb961 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2310,6 +2310,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .get_tsf = rt73usb_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, + .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { -- cgit v1.2.3-58-ga151 From 0ed7b3c04434788ef03d267190c5e9e6e3f8e9ce Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 18 Apr 2011 15:35:12 +0200 Subject: rt2x00: Implement get_antenna and set_antenna callback functions Implement the get_antenna and set_antenna callback functions, which will allow clients to control the antenna for all non-11n hardware (Antenna handling in rt2800 is still a bit magical, so we can't use the set_antenna for those drivers yet). To best support the set_antenna callback some modifications are needed in the diversity handling. We should never look at the default antenna settings to determine if software diversity is enabled. Instead we should set the diversity flag when possible, which will allow the link_tuner to automatically pick up the tuning. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 2 + drivers/net/wireless/rt2x00/rt2500pci.c | 2 + drivers/net/wireless/rt2x00/rt2500usb.c | 2 + drivers/net/wireless/rt2x00/rt2x00.h | 2 + drivers/net/wireless/rt2x00/rt2x00config.c | 45 ++++++++++++--------- drivers/net/wireless/rt2x00/rt2x00link.c | 10 ----- drivers/net/wireless/rt2x00/rt2x00mac.c | 65 ++++++++++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt61pci.c | 2 + drivers/net/wireless/rt2x00/rt73usb.c | 2 + 9 files changed, 103 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index bbe76f79b62e..937f9e8bf05f 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1720,6 +1720,8 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .tx_last_beacon = rt2400pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, + .set_antenna = rt2x00mac_set_antenna, + .get_antenna = rt2x00mac_get_antenna, .get_ringparam = rt2x00mac_get_ringparam, }; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 6f489968e7a4..d27d7b8ba3b6 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -2013,6 +2013,8 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .tx_last_beacon = rt2500pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, + .set_antenna = rt2x00mac_set_antenna, + .get_antenna = rt2x00mac_get_antenna, .get_ringparam = rt2x00mac_get_ringparam, }; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 5ef338671d73..b21f81231a09 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1823,6 +1823,8 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .conf_tx = rt2x00mac_conf_tx, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, + .set_antenna = rt2x00mac_set_antenna, + .get_antenna = rt2x00mac_get_antenna, .get_ringparam = rt2x00mac_get_ringparam, }; diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index f1d8f55d3ca8..acf561f7cde3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1254,6 +1254,8 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop); +int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant); +int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant); void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index f70a2b45d430..2a313b6d378d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -109,15 +109,6 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed); } -static inline -enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant, - enum antenna default_ant) -{ - if (current_ant != ANTENNA_SW_DIVERSITY) - return current_ant; - return (default_ant != ANTENNA_SW_DIVERSITY) ? default_ant : ANTENNA_B; -} - void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, struct antenna_setup config) { @@ -126,19 +117,35 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, struct antenna_setup *active = &rt2x00dev->link.ant.active; /* - * Failsafe: Make sure we are not sending the - * ANTENNA_SW_DIVERSITY state to the driver. - * If that happens, fallback to hardware defaults, - * or our own default. + * When the caller tries to send the SW diversity, + * we must update the ANTENNA_RX_DIVERSITY flag to + * enable the antenna diversity in the link tuner. + * + * Secondly, we must guarentee we never send the + * software antenna diversity command to the driver. */ - if (!(ant->flags & ANTENNA_RX_DIVERSITY)) - config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); - else if (config.rx == ANTENNA_SW_DIVERSITY) + if (!(ant->flags & ANTENNA_RX_DIVERSITY)) { + if (config.rx == ANTENNA_SW_DIVERSITY) { + ant->flags |= ANTENNA_RX_DIVERSITY; + + if (def->rx == ANTENNA_SW_DIVERSITY) + config.rx = ANTENNA_B; + else + config.rx = def->rx; + } + } else if (config.rx == ANTENNA_SW_DIVERSITY) config.rx = active->rx; - if (!(ant->flags & ANTENNA_TX_DIVERSITY)) - config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx); - else if (config.tx == ANTENNA_SW_DIVERSITY) + if (!(ant->flags & ANTENNA_TX_DIVERSITY)) { + if (config.tx == ANTENNA_SW_DIVERSITY) { + ant->flags |= ANTENNA_TX_DIVERSITY; + + if (def->tx == ANTENNA_SW_DIVERSITY) + config.tx = ANTENNA_B; + else + config.tx = def->tx; + } + } else if (config.tx == ANTENNA_SW_DIVERSITY) config.tx = active->tx; /* diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index ba0bb766e59e..fa55399be192 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -192,17 +192,7 @@ static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev) /* * Determine if software diversity is enabled for * either the TX or RX antenna (or both). - * Always perform this check since within the link - * tuner interval the configuration might have changed. */ - ant->flags &= ~ANTENNA_RX_DIVERSITY; - ant->flags &= ~ANTENNA_TX_DIVERSITY; - - if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) - ant->flags |= ANTENNA_RX_DIVERSITY; - if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) - ant->flags |= ANTENNA_TX_DIVERSITY; - if (!(ant->flags & ANTENNA_RX_DIVERSITY) && !(ant->flags & ANTENNA_TX_DIVERSITY)) { ant->flags = 0; diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 6d1d38329e52..93bec140e598 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -738,6 +738,71 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop) } EXPORT_SYMBOL_GPL(rt2x00mac_flush); +int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct link_ant *ant = &rt2x00dev->link.ant; + struct antenna_setup *def = &rt2x00dev->default_ant; + struct antenna_setup setup; + + // The antenna value is not supposed to be 0, + // or exceed the maximum number of antenna's. + if (!tx_ant || (tx_ant & ~3) || !rx_ant || (rx_ant & ~3)) + return -EINVAL; + + // When the client tried to configure the antenna to or from + // diversity mode, we must reset the default antenna as well + // as that controls the diversity switch. + if (ant->flags & ANTENNA_TX_DIVERSITY && tx_ant != 3) + ant->flags &= ~ANTENNA_TX_DIVERSITY; + if (ant->flags & ANTENNA_RX_DIVERSITY && rx_ant != 3) + ant->flags &= ~ANTENNA_RX_DIVERSITY; + + // If diversity is being enabled, check if we need hardware + // or software diversity. In the latter case, reset the value, + // and make sure we update the antenna flags to have the + // link tuner pick up the diversity tuning. + if (tx_ant == 3 && def->tx == ANTENNA_SW_DIVERSITY) { + tx_ant = ANTENNA_SW_DIVERSITY; + ant->flags |= ANTENNA_TX_DIVERSITY; + } + + if (rx_ant == 3 && def->rx == ANTENNA_SW_DIVERSITY) { + rx_ant = ANTENNA_SW_DIVERSITY; + ant->flags |= ANTENNA_RX_DIVERSITY; + } + + setup.tx = tx_ant; + setup.rx = rx_ant; + + rt2x00lib_config_antenna(rt2x00dev, setup); + + return 0; +} +EXPORT_SYMBOL_GPL(rt2x00mac_set_antenna); + +int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct link_ant *ant = &rt2x00dev->link.ant; + struct antenna_setup *active = &rt2x00dev->link.ant.active; + + // When software diversity is active, we must report this to the + // client and not the current active antenna state. + if (ant->flags & ANTENNA_TX_DIVERSITY) + *tx_ant = ANTENNA_HW_DIVERSITY; + else + *tx_ant = active->tx; + + if (ant->flags & ANTENNA_RX_DIVERSITY) + *rx_ant = ANTENNA_HW_DIVERSITY; + else + *rx_ant = active->rx; + + return 0; +} +EXPORT_SYMBOL_GPL(rt2x00mac_get_antenna); + void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max) { diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index eb5403108394..9d35ec16a3a5 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2979,6 +2979,8 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .get_tsf = rt61pci_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, + .set_antenna = rt2x00mac_set_antenna, + .get_antenna = rt2x00mac_get_antenna, .get_ringparam = rt2x00mac_get_ringparam, }; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index bf7fea4cb961..a6ce7d6cbdfa 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2310,6 +2310,8 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .get_tsf = rt73usb_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, + .set_antenna = rt2x00mac_set_antenna, + .get_antenna = rt2x00mac_get_antenna, .get_ringparam = rt2x00mac_get_ringparam, }; -- cgit v1.2.3-58-ga151 From 73b48099cc265f88fa1255f3f43e52fe6a94fd5c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 18 Apr 2011 17:05:21 +0200 Subject: mac80211: explain padding in place of rate field Apparently this was confusing still ... add a note that the byte is needed as padding. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/rx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 54858a68abd7..1f06b31e21c1 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -143,7 +143,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, if (status->flag & RX_FLAG_HT) { /* * MCS information is a separate field in radiotap, - * added below. + * added below. The byte here is needed as padding + * for the channel though, so initialise it to 0. */ *pos = 0; } else { -- cgit v1.2.3-58-ga151 From 985762b2df4bcb4accc29fda76fc863dd79b8b58 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Tue, 19 Apr 2011 15:31:20 +0000 Subject: net: forcedeth: fix compile warning of not used nv_set_tso function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the below compile warning: drivers/net/forcedeth.c:4266: warning: ‘nv_set_tso’ defined but not used commit 569e146 converts forcedeth driver to use hw_features. So, implement function of .set_tso is abandoned. Signed-off-by: Shan Wei Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index ec9a32d01e61..0e1c76a8c045 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -4263,16 +4263,6 @@ static int nv_nway_reset(struct net_device *dev) return ret; } -static int nv_set_tso(struct net_device *dev, u32 value) -{ - struct fe_priv *np = netdev_priv(dev); - - if ((np->driver_data & DEV_HAS_CHECKSUM)) - return ethtool_op_set_tso(dev, value); - else - return -EOPNOTSUPP; -} - static void nv_get_ringparam(struct net_device *dev, struct ethtool_ringparam* ring) { struct fe_priv *np = netdev_priv(dev); -- cgit v1.2.3-58-ga151 From ce45ee955ff53255993c9300344e6437761ce2b2 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Tue, 19 Apr 2011 15:38:06 +0000 Subject: net:bna: fix compile warning of ‘bfa_ioc_smem_pgoff’ defined but not used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the below compile warning: drivers/net/bna/bfa_ioc.c:1922: warning: ‘bfa_ioc_smem_pgoff’ defined but not used Signed-off-by: Shan Wei Signed-off-by: David S. Miller --- drivers/net/bna/bfa_ioc.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c index ba2a4e13cf4f..fcb9bb3169e0 100644 --- a/drivers/net/bna/bfa_ioc.c +++ b/drivers/net/bna/bfa_ioc.c @@ -82,7 +82,6 @@ static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc); static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param); static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr); -static u32 bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr); static void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num); static void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, @@ -1923,12 +1922,6 @@ bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr) return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr); } -static u32 -bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr) -{ - return PSS_SMEM_PGOFF(fmaddr); -} - /** * Register mailbox message handler function, to be called by common modules */ -- cgit v1.2.3-58-ga151 From 16a871ef552ff55c80b6d8d895e371ea07c58281 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 19 Apr 2011 12:10:43 +0000 Subject: be2net: allow register dump only for PFs Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_ethtool.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 28716a6061bc..22523b92b92a 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -161,7 +161,9 @@ be_get_reg_len(struct net_device *netdev) struct be_adapter *adapter = netdev_priv(netdev); u32 log_size = 0; - be_cmd_get_reg_len(adapter, &log_size); + if (be_physfn(adapter)) + be_cmd_get_reg_len(adapter, &log_size); + return log_size; } @@ -170,8 +172,10 @@ be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf) { struct be_adapter *adapter = netdev_priv(netdev); - memset(buf, 0, regs->len); - be_cmd_get_regs(adapter, regs->len, buf); + if (be_physfn(adapter)) { + memset(buf, 0, regs->len); + be_cmd_get_regs(adapter, regs->len, buf); + } } static int -- cgit v1.2.3-58-ga151 From 4fa9ed07e3965a809fa309a769675ac1c6dc692b Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 19 Apr 2011 12:10:53 +0000 Subject: be2net: Add code to display nic speeds other than 1Gbps/10Gbps Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_ethtool.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 22523b92b92a..33c2beccaa8e 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -384,12 +384,21 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->speed = link_speed*10; } else { switch (mac_speed) { + case PHY_LINK_SPEED_10MBPS: + ecmd->speed = SPEED_10; + break; + case PHY_LINK_SPEED_100MBPS: + ecmd->speed = SPEED_100; + break; case PHY_LINK_SPEED_1GBPS: ecmd->speed = SPEED_1000; break; case PHY_LINK_SPEED_10GBPS: ecmd->speed = SPEED_10000; break; + case PHY_LINK_SPEED_ZERO: + ecmd->speed = 0; + break; } } -- cgit v1.2.3-58-ga151 From 6349935bdfa4a210fb557e7541caad1d41925ccc Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 19 Apr 2011 12:11:02 +0000 Subject: be2net: fix be_mcc_compl_process to identify eth_get_stat command eth_get_statistics and vlan_config command have same opcode. Use opcode subsystem id to differentiate one from other. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 11b774a5eaff..a94e98060c93 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -78,7 +78,8 @@ static int be_mcc_compl_process(struct be_adapter *adapter, } if (compl_status == MCC_STATUS_SUCCESS) { - if (compl->tag0 == OPCODE_ETH_GET_STATISTICS) { + if ((compl->tag0 == OPCODE_ETH_GET_STATISTICS) && + (compl->tag1 == CMD_SUBSYSTEM_ETH)) { struct be_cmd_resp_get_stats *resp = adapter->stats_cmd.va; be_dws_le_to_cpu(&resp->hw_stats, @@ -1096,6 +1097,7 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_GET_STATISTICS, sizeof(*req)); + wrb->tag1 = CMD_SUBSYSTEM_ETH; sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); sge->len = cpu_to_le32(nonemb_cmd->size); -- cgit v1.2.3-58-ga151 From 187e87566d22b0d0e99b5ae7c6e18569ab5f6aee Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 19 Apr 2011 12:11:46 +0000 Subject: be2net: pass domain id to be_cmd_link_status_query Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 2 +- drivers/net/benet/be_cmds.h | 2 +- drivers/net/benet/be_ethtool.c | 4 ++-- drivers/net/benet/be_main.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index a94e98060c93..af8cf3d7c1e3 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1112,7 +1112,7 @@ err: /* Uses synchronous mcc */ int be_cmd_link_status_query(struct be_adapter *adapter, - bool *link_up, u8 *mac_speed, u16 *link_speed) + bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom) { struct be_mcc_wrb *wrb; struct be_cmd_req_link_status *req; diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 3fb6e0a3ad7a..af4bbff5feba 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -1112,7 +1112,7 @@ extern int be_cmd_rxq_create(struct be_adapter *adapter, extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, int type); extern int be_cmd_link_status_query(struct be_adapter *adapter, - bool *link_up, u8 *mac_speed, u16 *link_speed); + bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom); extern int be_cmd_reset(struct be_adapter *adapter); extern int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 33c2beccaa8e..6565f3e55b26 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -376,7 +376,7 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) { status = be_cmd_link_status_query(adapter, &link_up, - &mac_speed, &link_speed); + &mac_speed, &link_speed, 0); be_link_status_update(adapter, link_up); /* link_speed is in units of 10 Mbps */ @@ -661,7 +661,7 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) } if (be_cmd_link_status_query(adapter, &link_up, &mac_speed, - &qos_link_speed) != 0) { + &qos_link_speed, 0) != 0) { test->flags |= ETH_TEST_FL_FAILED; data[4] = -1; } else if (!mac_speed) { diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 1bb763cda3ad..77a6e7e4593c 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2171,7 +2171,7 @@ static int be_open(struct net_device *netdev) be_async_mcc_enable(adapter); status = be_cmd_link_status_query(adapter, &link_up, &mac_speed, - &link_speed); + &link_speed, 0); if (status) goto err; be_link_status_update(adapter, link_up); -- cgit v1.2.3-58-ga151 From d0381c42aabdbd9402501d08ea44a89695ad58b4 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 19 Apr 2011 12:11:55 +0000 Subject: be2net: add code to display default value of tx rate for VFs This change will allow the default value of tx rate to be displayed when ip link show is called on a PF interface. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 77a6e7e4593c..35294005361b 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -3082,9 +3082,22 @@ static int __devinit be_probe(struct pci_dev *pdev, netif_carrier_off(netdev); if (be_physfn(adapter) && adapter->sriov_enabled) { + u8 mac_speed; + bool link_up; + u16 vf, lnk_speed; + status = be_vf_eth_addr_config(adapter); if (status) goto unreg_netdev; + + for (vf = 0; vf < num_vfs; vf++) { + status = be_cmd_link_status_query(adapter, &link_up, + &mac_speed, &lnk_speed, vf + 1); + if (!status) + adapter->vf_cfg[vf].vf_tx_rate = lnk_speed * 10; + else + goto unreg_netdev; + } } dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num); -- cgit v1.2.3-58-ga151 From 709d38714eff234432956931437457e0de806784 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Mon, 18 Apr 2011 19:19:29 +0000 Subject: sctp: delete unused macro definition of sctp_chunk_is_control The macro never be used. And if needed, can use !sctp_chunk_is_data instead of. Signed-off-by: Shan Wei Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- include/net/sctp/constants.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index c70d8ccc55cb..deac13dd8d02 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -150,7 +150,6 @@ SCTP_SUBTYPE_CONSTRUCTOR(OTHER, sctp_event_other_t, other) SCTP_SUBTYPE_CONSTRUCTOR(PRIMITIVE, sctp_event_primitive_t, primitive) -#define sctp_chunk_is_control(a) (a->chunk_hdr->type != SCTP_CID_DATA) #define sctp_chunk_is_data(a) (a->chunk_hdr->type == SCTP_CID_DATA) /* Calculate the actual data size in a data chunk */ -- cgit v1.2.3-58-ga151 From 33c7cfdbb0d2bc021979e4947c7030c30d572532 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Mon, 18 Apr 2011 19:11:01 +0000 Subject: sctp: fix the comment of sctp_sf_violation_paramlen() Update the comment about sctp_sf_violation_paramlen() to be more precise. Signed-off-by: Shan Wei Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/sctp/sm_statefuns.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 76792083c379..c08547270e8e 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -4343,8 +4343,9 @@ static sctp_disposition_t sctp_sf_violation_chunklen( /* * Handle a protocol violation when the parameter length is invalid. - * "Invalid" length is identified as smaller than the minimal length a - * given parameter can be. + * If the length is smaller than the minimum length of a given parameter, + * or accumulated length in multi parameters exceeds the end of the chunk, + * the length is considered as invalid. */ static sctp_disposition_t sctp_sf_violation_paramlen( const struct sctp_endpoint *ep, -- cgit v1.2.3-58-ga151 From 6a435732accd9e3f4a8d9c320fabe578b1bf5add Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Mon, 18 Apr 2011 19:11:47 +0000 Subject: sctp: use common head of addr parameter to access member in addr-unrelated code The 'p' member of struct sctp_paramhdr is common part for IPv4 addr parameter and IPv6 addr parameter in union sctp_addr_param. For addr-related code, use specified addr parameter. Otherwise, use common header to access type/length member. Signed-off-by: Shan Wei Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/sctp/input.c | 2 +- net/sctp/sm_make_chunk.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/net/sctp/input.c b/net/sctp/input.c index 5436c6921167..30cec7732e80 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -1017,7 +1017,7 @@ static struct sctp_association *__sctp_rcv_asconf_lookup( /* Skip over the ADDIP header and find the Address parameter */ param = (union sctp_addr_param *)(asconf + 1); - af = sctp_get_af_specific(param_type2af(param->v4.param_hdr.type)); + af = sctp_get_af_specific(param_type2af(param->p.type)); if (unlikely(!af)) return NULL; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b3434cc7d0cf..844adfdeb463 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2923,7 +2923,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, asconf_param->param_hdr.type != SCTP_PARAM_SET_PRIMARY) return SCTP_ERROR_UNKNOWN_PARAM; - switch (addr_param->v4.param_hdr.type) { + switch (addr_param->p.type) { case SCTP_PARAM_IPV6_ADDRESS: if (!asoc->peer.ipv6_address) return SCTP_ERROR_DNS_FAILED; @@ -2936,7 +2936,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, return SCTP_ERROR_DNS_FAILED; } - af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type)); + af = sctp_get_af_specific(param_type2af(addr_param->p.type)); if (unlikely(!af)) return SCTP_ERROR_DNS_FAILED; @@ -3100,7 +3100,7 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, /* Skip the address parameter and store a pointer to the first * asconf parameter. */ - length = ntohs(addr_param->v4.param_hdr.length); + length = ntohs(addr_param->p.length); asconf_param = (sctp_addip_param_t *)((void *)addr_param + length); chunk_len -= length; @@ -3177,7 +3177,7 @@ static void sctp_asconf_param_success(struct sctp_association *asoc, ((void *)asconf_param + sizeof(sctp_addip_param_t)); /* We have checked the packet before, so we do not check again. */ - af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type)); + af = sctp_get_af_specific(param_type2af(addr_param->p.type)); af->from_addr_param(&addr, addr_param, htons(bp->port), 0); switch (asconf_param->param_hdr.type) { @@ -3304,7 +3304,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc, /* Skip the address parameter in the last asconf sent and store a * pointer to the first asconf parameter. */ - length = ntohs(addr_param->v4.param_hdr.length); + length = ntohs(addr_param->p.length); asconf_param = (sctp_addip_param_t *)((void *)addr_param + length); asconf_len -= length; -- cgit v1.2.3-58-ga151 From 66009927f1e7374afdc6f9fdd25c493ee4eadf7c Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Mon, 18 Apr 2011 19:12:40 +0000 Subject: sctp: kill abandoned SCTP_CMD_TRANSMIT command Remove SCTP_CMD_TRANSMIT command as it never be used. Signed-off-by: Shan Wei Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- include/net/sctp/command.h | 1 - net/sctp/sm_sideeffect.c | 6 ------ 2 files changed, 7 deletions(-) diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index c01dc99def07..2b447646ce4b 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h @@ -73,7 +73,6 @@ typedef enum { SCTP_CMD_INIT_FAILED, /* High level, do init failure work. */ SCTP_CMD_REPORT_DUP, /* Report a duplicate TSN. */ SCTP_CMD_STRIKE, /* Mark a strike against a transport. */ - SCTP_CMD_TRANSMIT, /* Transmit the outqueue. */ SCTP_CMD_HB_TIMERS_START, /* Start the heartbeat timers. */ SCTP_CMD_HB_TIMER_UPDATE, /* Update a heartbeat timers. */ SCTP_CMD_HB_TIMERS_STOP, /* Stop the heartbeat timers. */ diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 5f86ee4b54c1..3b80fe24dabf 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1415,12 +1415,6 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, SCTP_RTXR_T3_RTX); break; - case SCTP_CMD_TRANSMIT: - /* Kick start transmission. */ - error = sctp_outq_uncork(&asoc->outqueue); - local_cork = 0; - break; - case SCTP_CMD_ECN_CE: /* Do delayed CE processing. */ sctp_do_ecn_ce_work(asoc, cmd->obj.u32); -- cgit v1.2.3-58-ga151 From 934253a7b4ab4151037ea9532552628723a14442 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Mon, 18 Apr 2011 19:13:18 +0000 Subject: sctp: use memdup_user to copy data from userspace Use common function to simply code. Signed-off-by: Shan Wei Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/sctp/socket.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index deb82e35a107..5c9980ae36bb 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3215,14 +3215,9 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, if (optlen < sizeof(struct sctp_hmacalgo)) return -EINVAL; - hmacs = kmalloc(optlen, GFP_KERNEL); - if (!hmacs) - return -ENOMEM; - - if (copy_from_user(hmacs, optval, optlen)) { - err = -EFAULT; - goto out; - } + hmacs= memdup_user(optval, optlen); + if (IS_ERR(hmacs)) + return PTR_ERR(hmacs); idents = hmacs->shmac_num_idents; if (idents == 0 || idents > SCTP_AUTH_NUM_HMACS || @@ -3257,14 +3252,9 @@ static int sctp_setsockopt_auth_key(struct sock *sk, if (optlen <= sizeof(struct sctp_authkey)) return -EINVAL; - authkey = kmalloc(optlen, GFP_KERNEL); - if (!authkey) - return -ENOMEM; - - if (copy_from_user(authkey, optval, optlen)) { - ret = -EFAULT; - goto out; - } + authkey= memdup_user(optval, optlen); + if (IS_ERR(authkey)) + return PTR_ERR(authkey); if (authkey->sca_keylength > optlen - sizeof(struct sctp_authkey)) { ret = -EINVAL; -- cgit v1.2.3-58-ga151 From f246a7b7c5b9df0ea0f0807a7101995af5e83213 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 18 Apr 2011 19:13:56 +0000 Subject: sctp: teach CACC algorithm about removed transports When we have have to remove a transport due to ASCONF, we move the data to a new active path. This can trigger CACC algorithm to not mark that data as missing when SACKs arrive. This is because the transport passed to the CACC algorithm is the one this data is sitting on, not the one it was sent on (that one may be gone). So, by sending the original transport (even if it's NULL), we may start marking data as missing. Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/sctp/outqueue.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index bf92a5b68f8b..7812772dbf74 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -131,7 +131,8 @@ static inline int sctp_cacc_skip_3_1_d(struct sctp_transport *primary, static inline int sctp_cacc_skip_3_1_f(struct sctp_transport *transport, int count_of_newacks) { - if (count_of_newacks < 2 && !transport->cacc.cacc_saw_newack) + if (count_of_newacks < 2 && + (transport && !transport->cacc.cacc_saw_newack)) return 1; return 0; } @@ -618,9 +619,12 @@ redo: /* If we are retransmitting, we should only * send a single packet. + * Otherwise, try appending this chunk again. */ if (rtx_timeout || fast_rtx) done = 1; + else + goto redo; /* Bundle next chunk in the next round. */ break; @@ -1683,8 +1687,9 @@ static void sctp_mark_missing(struct sctp_outq *q, /* SFR-CACC may require us to skip marking * this chunk as missing. */ - if (!transport || !sctp_cacc_skip(primary, transport, - count_of_newacks, tsn)) { + if (!transport || !sctp_cacc_skip(primary, + chunk->transport, + count_of_newacks, tsn)) { chunk->tsn_missing_report++; SCTP_DEBUG_PRINTK( -- cgit v1.2.3-58-ga151 From ee9cbaca7d73ea0098f00ecd10fe6e4a4792e32c Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 18 Apr 2011 19:14:47 +0000 Subject: sctp: Allow bindx_del to accept 0 port We allow 0 port when adding new addresses. It only makes sence to allow 0 port when removing addresses. When removing the currently bound port will be used when the port in the address is set to 0. Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/sctp/socket.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5c9980ae36bb..431b8905c570 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -658,11 +658,15 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) goto err_bindx_rem; } - if (sa_addr->v4.sin_port != htons(bp->port)) { + if (sa_addr->v4.sin_port && + sa_addr->v4.sin_port != htons(bp->port)) { retval = -EINVAL; goto err_bindx_rem; } + if (!sa_addr->v4.sin_port) + sa_addr->v4.sin_port = htons(bp->port); + /* FIXME - There is probably a need to check if sk->sk_saddr and * sk->sk_rcv_addr are currently set to one of the addresses to * be removed. This is something which needs to be looked into -- cgit v1.2.3-58-ga151 From c6ef006bf57fb6a8a0b134928b5c5606090ef0a0 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 18 Apr 2011 19:15:22 +0000 Subject: sctp: Release all routes when processing acks ADD_IP or DEL_IP When processing an ACK for ADD_IP parameter, we only release the routes on non-active transports. This can cause a wrong source address to be used. We can release the routes and cause new route lookups and source address selection so that new addresses can be used as source. Additionally, we don't need to lookup routes for all transports at the same time. We can let the transmit code path update the cached route when the transport actually sends something. Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 844adfdeb463..f87ccb11a520 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3193,11 +3193,8 @@ static void sctp_asconf_param_success(struct sctp_association *asoc, local_bh_enable(); list_for_each_entry(transport, &asoc->peer.transport_addr_list, transports) { - if (transport->state == SCTP_ACTIVE) - continue; dst_release(transport->dst); - sctp_transport_route(transport, NULL, - sctp_sk(asoc->base.sk)); + transport->dst = NULL; } break; case SCTP_PARAM_DEL_IP: @@ -3207,8 +3204,7 @@ static void sctp_asconf_param_success(struct sctp_association *asoc, list_for_each_entry(transport, &asoc->peer.transport_addr_list, transports) { dst_release(transport->dst); - sctp_transport_route(transport, NULL, - sctp_sk(asoc->base.sk)); + transport->dst = NULL; } break; default: -- cgit v1.2.3-58-ga151 From 290129f9880302d4fa468f7ff2f72de4b4d418ae Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 19 Apr 2011 00:43:19 +0000 Subject: net: dsa: remove ethtool_ops->set_sg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove set_sg from DSA slave ethtool_ops. Features inheritance looks broken/not fully implemented anyway. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- net/dsa/slave.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 64ca2a6fa0d4..0a47b6c37038 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -288,7 +288,6 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = { .get_drvinfo = dsa_slave_get_drvinfo, .nway_reset = dsa_slave_nway_reset, .get_link = dsa_slave_get_link, - .set_sg = ethtool_op_set_sg, .get_strings = dsa_slave_get_strings, .get_ethtool_stats = dsa_slave_get_ethtool_stats, .get_sset_count = dsa_slave_get_sset_count, -- cgit v1.2.3-58-ga151 From 97dbee73978497c615a46d324e4f5629b9772f86 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 19 Apr 2011 00:43:20 +0000 Subject: net: batman-adv: remove rx_csum ethtool_ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- net/batman-adv/soft-interface.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 1f6f756bc584..f4d80ad008c2 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -43,8 +43,6 @@ static void bat_get_drvinfo(struct net_device *dev, static u32 bat_get_msglevel(struct net_device *dev); static void bat_set_msglevel(struct net_device *dev, u32 value); static u32 bat_get_link(struct net_device *dev); -static u32 bat_get_rx_csum(struct net_device *dev); -static int bat_set_rx_csum(struct net_device *dev, u32 data); static const struct ethtool_ops bat_ethtool_ops = { .get_settings = bat_get_settings, @@ -52,8 +50,6 @@ static const struct ethtool_ops bat_ethtool_ops = { .get_msglevel = bat_get_msglevel, .set_msglevel = bat_set_msglevel, .get_link = bat_get_link, - .get_rx_csum = bat_get_rx_csum, - .set_rx_csum = bat_set_rx_csum }; int my_skb_head_push(struct sk_buff *skb, unsigned int len) @@ -736,12 +732,3 @@ static u32 bat_get_link(struct net_device *dev) return 1; } -static u32 bat_get_rx_csum(struct net_device *dev) -{ - return 0; -} - -static int bat_set_rx_csum(struct net_device *dev, u32 data) -{ - return -EOPNOTSUPP; -} -- cgit v1.2.3-58-ga151 From 8727bfaa8a723009e9c6eb1bb57b90ebdb0a4126 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 19 Apr 2011 00:43:20 +0000 Subject: Staging: convert hv network driver to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/staging/hv/netvsc_drv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 33973568214f..aaa81883f0ad 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -317,8 +317,6 @@ static void netvsc_get_drvinfo(struct net_device *net, static const struct ethtool_ops ethtool_ops = { .get_drvinfo = netvsc_get_drvinfo, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, .get_link = ethtool_op_get_link, }; @@ -406,6 +404,7 @@ static int netvsc_probe(struct device *device) net->netdev_ops = &device_ops; /* TODO: Add GSO and Checksum offload */ + net->hw_features = NETIF_F_SG; net->features = NETIF_F_SG; SET_ETHTOOL_OPS(net, ðtool_ops); -- cgit v1.2.3-58-ga151 From dd6f6d024906b8f05a0832c78c16a1e818958321 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 19 Apr 2011 00:43:20 +0000 Subject: net: infiniband/hw/nes: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/infiniband/hw/nes/nes_hw.c | 5 ++-- drivers/infiniband/hw/nes/nes_hw.h | 1 - drivers/infiniband/hw/nes/nes_nic.c | 55 ++++--------------------------------- 3 files changed, 7 insertions(+), 54 deletions(-) diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 10d0a5ec9add..96fa9a4cafdf 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -2885,9 +2885,8 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) if ((cqe_errv & (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_TCPUDP_CSUM_ERR | NES_NIC_ERRV_BITS_IPH_ERR | NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) { - if (nesvnic->rx_checksum_disabled == 0) { + if (nesvnic->netdev->features & NETIF_F_RXCSUM) rx_skb->ip_summed = CHECKSUM_UNNECESSARY; - } } else nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet." " errv = 0x%X, pkt_type = 0x%X.\n", @@ -2897,7 +2896,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) if ((cqe_errv & (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_IPH_ERR | NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) { - if (nesvnic->rx_checksum_disabled == 0) { + if (nesvnic->netdev->features & NETIF_F_RXCSUM) { rx_skb->ip_summed = CHECKSUM_UNNECESSARY; /* nes_debug(NES_DBG_CQ, "%s: Reporting successfully checksummed IPv4 packet.\n", nesvnic->netdev->name); */ diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index d2abe07133a5..91594116f947 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h @@ -1245,7 +1245,6 @@ struct nes_vnic { u8 next_qp_nic_index; u8 of_device_registered; u8 rdma_enabled; - u8 rx_checksum_disabled; u32 lro_max_aggr; struct net_lro_mgr lro_mgr; struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS]; diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index e96b8fb5d44c..d2e67c4e3228 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -1093,34 +1093,6 @@ static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = { }; #define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset) -/** - * nes_netdev_get_rx_csum - */ -static u32 nes_netdev_get_rx_csum (struct net_device *netdev) -{ - struct nes_vnic *nesvnic = netdev_priv(netdev); - - if (nesvnic->rx_checksum_disabled) - return 0; - else - return 1; -} - - -/** - * nes_netdev_set_rc_csum - */ -static int nes_netdev_set_rx_csum(struct net_device *netdev, u32 enable) -{ - struct nes_vnic *nesvnic = netdev_priv(netdev); - - if (enable) - nesvnic->rx_checksum_disabled = 0; - else - nesvnic->rx_checksum_disabled = 1; - return 0; -} - /** * nes_netdev_get_sset_count @@ -1598,19 +1570,10 @@ static int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd } -static int nes_netdev_set_flags(struct net_device *netdev, u32 flags) -{ - return ethtool_op_set_flags(netdev, flags, ETH_FLAG_LRO); -} - - static const struct ethtool_ops nes_ethtool_ops = { .get_link = ethtool_op_get_link, .get_settings = nes_netdev_get_settings, .set_settings = nes_netdev_set_settings, - .get_tx_csum = ethtool_op_get_tx_csum, - .get_rx_csum = nes_netdev_get_rx_csum, - .get_sg = ethtool_op_get_sg, .get_strings = nes_netdev_get_strings, .get_sset_count = nes_netdev_get_sset_count, .get_ethtool_stats = nes_netdev_get_ethtool_stats, @@ -1619,13 +1582,6 @@ static const struct ethtool_ops nes_ethtool_ops = { .set_coalesce = nes_netdev_set_coalesce, .get_pauseparam = nes_netdev_get_pauseparam, .set_pauseparam = nes_netdev_set_pauseparam, - .set_tx_csum = ethtool_op_set_tx_csum, - .set_rx_csum = nes_netdev_set_rx_csum, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, - .get_flags = ethtool_op_get_flags, - .set_flags = nes_netdev_set_flags, }; @@ -1727,12 +1683,11 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, netdev->dev_addr[5] = (u8)u64temp; memcpy(netdev->perm_addr, netdev->dev_addr, 6); - if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV)) { - netdev->features |= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM; - netdev->features |= NETIF_F_GSO | NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM; - } else { - netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } + netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM; + if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV)) + netdev->hw_features |= NETIF_F_TSO; + netdev->features |= netdev->hw_features; + netdev->hw_features |= NETIF_F_LRO; nes_debug(NES_DBG_INIT, "nesvnic = %p, reported features = 0x%lX, QPid = %d," " nic_index = %d, logical_port = %d, mac_index = %d.\n", -- cgit v1.2.3-58-ga151 From 6204b47ec4394f7e472885c8d05d9cda96d97a25 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 19 Apr 2011 00:43:20 +0000 Subject: net: s390: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit options.large_send was easy to get rid of. options.checksum_type has deeper roots so is left for later cleanup. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 7 --- drivers/s390/net/qeth_l3_main.c | 117 ++++++++++++---------------------------- drivers/s390/net/qeth_l3_sys.c | 35 ++++++------ 3 files changed, 52 insertions(+), 107 deletions(-) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index af3f7b095647..8d6146a107d9 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -407,12 +407,6 @@ struct qeth_qdio_q { int next_buf_to_init; } __attribute__ ((aligned(256))); -/* possible types of qeth large_send support */ -enum qeth_large_send_types { - QETH_LARGE_SEND_NO, - QETH_LARGE_SEND_TSO, -}; - struct qeth_qdio_out_buffer { struct qdio_buffer *buffer; atomic_t state; @@ -651,7 +645,6 @@ struct qeth_card_options { int fake_broadcast; int add_hhlen; int layer2; - enum qeth_large_send_types large_send; int performance_stats; int rx_sg_cb; enum qeth_ipa_isolation_modes isolation; diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 142e5f6ef4f3..1496661507ea 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -43,33 +43,6 @@ static int qeth_l3_deregister_addr_entry(struct qeth_card *, static int __qeth_l3_set_online(struct ccwgroup_device *, int); static int __qeth_l3_set_offline(struct ccwgroup_device *, int); -int qeth_l3_set_large_send(struct qeth_card *card, - enum qeth_large_send_types type) -{ - int rc = 0; - - card->options.large_send = type; - if (card->dev == NULL) - return 0; - - if (card->options.large_send == QETH_LARGE_SEND_TSO) { - if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) { - card->dev->features |= NETIF_F_TSO | NETIF_F_SG | - NETIF_F_IP_CSUM; - } else { - card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | - NETIF_F_IP_CSUM); - card->options.large_send = QETH_LARGE_SEND_NO; - rc = -EOPNOTSUPP; - } - } else { - card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | - NETIF_F_IP_CSUM); - card->options.large_send = QETH_LARGE_SEND_NO; - } - return rc; -} - static int qeth_l3_isxdigit(char *buf) { while (*buf) { @@ -1485,6 +1458,7 @@ int qeth_l3_set_rx_csum(struct qeth_card *card, if (rc) return -EIO; } + card->dev->features |= NETIF_F_RXCSUM; } else { if (csum_type == HW_CHECKSUMMING) { if (card->state != CARD_STATE_DOWN) { @@ -1496,6 +1470,7 @@ int qeth_l3_set_rx_csum(struct qeth_card *card, return -EIO; } } + card->dev->features &= ~NETIF_F_RXCSUM; } card->options.checksum_type = csum_type; return rc; @@ -1580,10 +1555,8 @@ static int qeth_l3_start_ipa_tso(struct qeth_card *card) dev_info(&card->gdev->dev, "Outbound TSO enabled\n"); } - if (rc && (card->options.large_send == QETH_LARGE_SEND_TSO)) { - card->options.large_send = QETH_LARGE_SEND_NO; - card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); - } + if (rc) + card->dev->features &= ~NETIF_F_TSO; return rc; } @@ -3024,7 +2997,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) struct qeth_qdio_out_q *queue = card->qdio.out_qs [qeth_get_priority_queue(card, skb, ipv, cast_type)]; int tx_bytes = skb->len; - enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; + bool large_send; int data_offset = -1; int nr_frags; @@ -3046,8 +3019,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) card->perf_stats.outbound_start_time = qeth_get_micros(); } - if (skb_is_gso(skb)) - large_send = card->options.large_send; + large_send = skb_is_gso(skb); if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) && (skb_shinfo(skb)->nr_frags == 0)) { @@ -3096,7 +3068,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) /* fix hardware limitation: as long as we do not have sbal * chaining we can not send long frag lists */ - if (large_send == QETH_LARGE_SEND_TSO) { + if (large_send) { if (qeth_l3_tso_elements(new_skb) + 1 > 16) { if (skb_linearize(new_skb)) goto tx_drop; @@ -3105,8 +3077,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } } - if ((large_send == QETH_LARGE_SEND_TSO) && - (cast_type == RTN_UNSPEC)) { + if (large_send && (cast_type == RTN_UNSPEC)) { hdr = (struct qeth_hdr *)skb_push(new_skb, sizeof(struct qeth_hdr_tso)); memset(hdr, 0, sizeof(struct qeth_hdr_tso)); @@ -3141,7 +3112,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) if (card->info.type != QETH_CARD_TYPE_IQD) { int len; - if (large_send == QETH_LARGE_SEND_TSO) + if (large_send) len = ((unsigned long)tcp_hdr(new_skb) + tcp_hdr(new_skb)->doff * 4) - (unsigned long)new_skb->data; @@ -3162,7 +3133,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) if (new_skb != skb) dev_kfree_skb_any(skb); if (card->options.performance_stats) { - if (large_send != QETH_LARGE_SEND_NO) { + if (large_send) { card->perf_stats.large_send_bytes += tx_bytes; card->perf_stats.large_send_cnt++; } @@ -3248,65 +3219,40 @@ static int qeth_l3_stop(struct net_device *dev) return 0; } -static u32 qeth_l3_ethtool_get_rx_csum(struct net_device *dev) +static u32 qeth_l3_fix_features(struct net_device *dev, u32 features) { struct qeth_card *card = dev->ml_priv; - return (card->options.checksum_type == HW_CHECKSUMMING); + if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM)) + features &= ~NETIF_F_IP_CSUM; + if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) + features &= ~NETIF_F_TSO; + if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) + features &= ~NETIF_F_RXCSUM; + + return features; } -static int qeth_l3_ethtool_set_rx_csum(struct net_device *dev, u32 data) +static int qeth_l3_set_features(struct net_device *dev, u32 features) { - struct qeth_card *card = dev->ml_priv; enum qeth_checksum_types csum_type; + struct qeth_card *card = dev->ml_priv; + u32 changed = dev->features ^ features; - if (data) + if (!(changed & NETIF_F_RXCSUM)) + return 0; + + if (features & NETIF_F_RXCSUM) csum_type = HW_CHECKSUMMING; else csum_type = SW_CHECKSUMMING; + dev->features = features ^ NETIF_F_RXCSUM; return qeth_l3_set_rx_csum(card, csum_type); } -static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data) -{ - struct qeth_card *card = dev->ml_priv; - int rc = 0; - - if (data) { - rc = qeth_l3_set_large_send(card, QETH_LARGE_SEND_TSO); - } else { - dev->features &= ~NETIF_F_TSO; - card->options.large_send = QETH_LARGE_SEND_NO; - } - return rc; -} - -static int qeth_l3_ethtool_set_tx_csum(struct net_device *dev, u32 data) -{ - struct qeth_card *card = dev->ml_priv; - - if (data) { - if (qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM)) - dev->features |= NETIF_F_IP_CSUM; - else - return -EPERM; - } else - dev->features &= ~NETIF_F_IP_CSUM; - - return 0; -} - static const struct ethtool_ops qeth_l3_ethtool_ops = { .get_link = ethtool_op_get_link, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = qeth_l3_ethtool_set_tx_csum, - .get_rx_csum = qeth_l3_ethtool_get_rx_csum, - .set_rx_csum = qeth_l3_ethtool_set_rx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = qeth_l3_ethtool_set_tso, .get_strings = qeth_core_get_strings, .get_ethtool_stats = qeth_core_get_ethtool_stats, .get_sset_count = qeth_core_get_sset_count, @@ -3347,6 +3293,8 @@ static const struct net_device_ops qeth_l3_netdev_ops = { .ndo_set_multicast_list = qeth_l3_set_multicast_list, .ndo_do_ioctl = qeth_l3_do_ioctl, .ndo_change_mtu = qeth_change_mtu, + .ndo_fix_features = qeth_l3_fix_features, + .ndo_set_features = qeth_l3_set_features, .ndo_vlan_rx_register = qeth_l3_vlan_rx_register, .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid, @@ -3362,6 +3310,8 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = { .ndo_set_multicast_list = qeth_l3_set_multicast_list, .ndo_do_ioctl = qeth_l3_do_ioctl, .ndo_change_mtu = qeth_change_mtu, + .ndo_fix_features = qeth_l3_fix_features, + .ndo_set_features = qeth_l3_set_features, .ndo_vlan_rx_register = qeth_l3_vlan_rx_register, .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid, @@ -3392,8 +3342,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD)) card->dev->dev_id = card->info.unique_id & 0xffff; - if (!card->info.guestlan) - card->dev->features |= NETIF_F_GRO; } } else if (card->info.type == QETH_CARD_TYPE_IQD) { card->dev = alloc_netdev(0, "hsi%d", ether_setup); @@ -3409,6 +3357,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) card->dev->watchdog_timeo = QETH_TX_TIMEOUT; card->dev->mtu = card->info.initial_mtu; SET_ETHTOOL_OPS(card->dev, &qeth_l3_ethtool_ops); + card->dev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | + NETIF_F_IP_CSUM | NETIF_F_TSO; card->dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; @@ -3516,7 +3466,6 @@ contin: rc = qeth_l3_start_ipassists(card); if (rc) QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); - qeth_l3_set_large_send(card, card->options.large_send); rc = qeth_l3_setrouting_v4(card); if (rc) QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc); diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index 67cfa68dcf1b..bf9f003e3a97 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -410,39 +410,42 @@ static ssize_t qeth_l3_dev_large_send_show(struct device *dev, if (!card) return -EINVAL; - switch (card->options.large_send) { - case QETH_LARGE_SEND_NO: + if (!(card->dev->features & NETIF_F_TSO)) return sprintf(buf, "%s\n", "no"); - case QETH_LARGE_SEND_TSO: + else return sprintf(buf, "%s\n", "TSO"); - default: - return sprintf(buf, "%s\n", "N/A"); - } } static ssize_t qeth_l3_dev_large_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct qeth_card *card = dev_get_drvdata(dev); - enum qeth_large_send_types type; - int rc = 0; + struct qeth_card *card; char *tmp; + int enable; if (!card) return -EINVAL; tmp = strsep((char **) &buf, "\n"); if (!strcmp(tmp, "no")) - type = QETH_LARGE_SEND_NO; + enable = 0; else if (!strcmp(tmp, "TSO")) - type = QETH_LARGE_SEND_TSO; + enable = 1; else return -EINVAL; - mutex_lock(&card->conf_mutex); - if (card->options.large_send != type) - rc = qeth_l3_set_large_send(card, type); - mutex_unlock(&card->conf_mutex); - return rc ? rc : count; + rtnl_lock(); + + card = dev_get_drvdata(dev); + + if (enable) + card->dev->wanted_features |= NETIF_F_TSO; + else + card->dev->wanted_features &= ~NETIF_F_TSO; + netdev_update_features(card->dev); + + rtnl_unlock(); + + return count; } static DEVICE_ATTR(large_send, 0644, qeth_l3_dev_large_send_show, -- cgit v1.2.3-58-ga151 From 3d96c74d8983b16bc7ecb196e61a2173fcc3f09f Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 19 Apr 2011 00:43:20 +0000 Subject: net: infiniband/ulp/ipoib: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/infiniband/ulp/ipoib/ipoib.h | 1 - drivers/infiniband/ulp/ipoib/ipoib_cm.c | 11 ++--------- drivers/infiniband/ulp/ipoib/ipoib_ethtool.c | 28 ---------------------------- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 2 +- drivers/infiniband/ulp/ipoib/ipoib_main.c | 24 +++++++++++++++++------- 5 files changed, 20 insertions(+), 46 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index ab97f92fc257..7b6985a2e652 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -91,7 +91,6 @@ enum { IPOIB_STOP_REAPER = 7, IPOIB_FLAG_ADMIN_CM = 9, IPOIB_FLAG_UMCAST = 10, - IPOIB_FLAG_CSUM = 11, IPOIB_MAX_BACKOFF_SECONDS = 16, diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 93d55806b967..39913a065f99 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -1463,8 +1463,7 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); ipoib_warn(priv, "enabling connected mode " "will cause multicast packet drops\n"); - - dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO); + netdev_update_features(dev); rtnl_unlock(); priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; @@ -1474,13 +1473,7 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, if (!strcmp(buf, "datagram\n")) { clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); - - if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) { - dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; - priv->dev->features |= NETIF_F_GRO; - if (priv->hca_caps & IB_DEVICE_UD_TSO) - dev->features |= NETIF_F_TSO; - } + netdev_update_features(dev); dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu)); rtnl_unlock(); ipoib_flush_paths(dev); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c index 19f7f5206f78..29bc7b5724ac 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c @@ -42,32 +42,6 @@ static void ipoib_get_drvinfo(struct net_device *netdev, strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1); } -static u32 ipoib_get_rx_csum(struct net_device *dev) -{ - struct ipoib_dev_priv *priv = netdev_priv(dev); - return test_bit(IPOIB_FLAG_CSUM, &priv->flags) && - !test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); -} - -static int ipoib_set_tso(struct net_device *dev, u32 data) -{ - struct ipoib_dev_priv *priv = netdev_priv(dev); - - if (data) { - if (!test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags) && - (dev->features & NETIF_F_SG) && - (priv->hca_caps & IB_DEVICE_UD_TSO)) { - dev->features |= NETIF_F_TSO; - } else { - ipoib_warn(priv, "can't set TSO on\n"); - return -EOPNOTSUPP; - } - } else - dev->features &= ~NETIF_F_TSO; - - return 0; -} - static int ipoib_get_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) { @@ -108,8 +82,6 @@ static int ipoib_set_coalesce(struct net_device *dev, static const struct ethtool_ops ipoib_ethtool_ops = { .get_drvinfo = ipoib_get_drvinfo, - .get_rx_csum = ipoib_get_rx_csum, - .set_tso = ipoib_set_tso, .get_coalesce = ipoib_get_coalesce, .set_coalesce = ipoib_set_coalesce, }; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 806d0292dc39..81ae61d68a22 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -292,7 +292,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) dev->stats.rx_bytes += skb->len; skb->dev = dev; - if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok)) + if ((dev->features & NETIF_F_RXCSUM) && likely(wc->csum_ok)) skb->ip_summed = CHECKSUM_UNNECESSARY; napi_gro_receive(&priv->napi, skb); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index aca3b44f7aed..86addca9ddf6 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -171,6 +171,16 @@ static int ipoib_stop(struct net_device *dev) return 0; } +static u32 ipoib_fix_features(struct net_device *dev, u32 features) +{ + struct ipoib_dev_priv *priv = netdev_priv(dev); + + if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags)) + features &= ~(NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + + return features; +} + static int ipoib_change_mtu(struct net_device *dev, int new_mtu) { struct ipoib_dev_priv *priv = netdev_priv(dev); @@ -970,6 +980,7 @@ static const struct net_device_ops ipoib_netdev_ops = { .ndo_open = ipoib_open, .ndo_stop = ipoib_stop, .ndo_change_mtu = ipoib_change_mtu, + .ndo_fix_features = ipoib_fix_features, .ndo_start_xmit = ipoib_start_xmit, .ndo_tx_timeout = ipoib_timeout, .ndo_set_multicast_list = ipoib_set_mcast_list, @@ -1154,19 +1165,18 @@ int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca) kfree(device_attr); if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) { - set_bit(IPOIB_FLAG_CSUM, &priv->flags); - priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } + priv->dev->hw_features = NETIF_F_SG | + NETIF_F_IP_CSUM | NETIF_F_RXCSUM; - priv->dev->features |= NETIF_F_GRO; + if (priv->hca_caps & IB_DEVICE_UD_TSO) + priv->dev->hw_features |= NETIF_F_TSO; - if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO) - priv->dev->features |= NETIF_F_TSO; + priv->dev->features |= priv->dev->hw_features; + } return 0; } - static struct net_device *ipoib_add_port(const char *format, struct ib_device *hca, u8 port) { -- cgit v1.2.3-58-ga151 From 756a6b03da98903fa22ad7f10752de11782249fc Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 19 Apr 2011 01:56:12 +0000 Subject: net: pch_gbe: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also fixes bug in xmit path, where TX checksum offload state was used instead of skb->ip_summed to decide if the offload was needed. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/pch_gbe/pch_gbe.h | 4 --- drivers/net/pch_gbe/pch_gbe_ethtool.c | 54 ----------------------------------- drivers/net/pch_gbe/pch_gbe_main.c | 42 ++++++++++++++++++++------- drivers/net/pch_gbe/pch_gbe_param.c | 16 +++++++---- 4 files changed, 42 insertions(+), 74 deletions(-) diff --git a/drivers/net/pch_gbe/pch_gbe.h b/drivers/net/pch_gbe/pch_gbe.h index bf126e76fabf..59fac77d0dbb 100644 --- a/drivers/net/pch_gbe/pch_gbe.h +++ b/drivers/net/pch_gbe/pch_gbe.h @@ -597,8 +597,6 @@ struct pch_gbe_hw_stats { * @rx_ring: Pointer of Rx descriptor ring structure * @rx_buffer_len: Receive buffer length * @tx_queue_len: Transmit queue length - * @rx_csum: Receive TCP/IP checksum enable/disable - * @tx_csum: Transmit TCP/IP checksum enable/disable * @have_msi: PCI MSI mode flag */ @@ -623,8 +621,6 @@ struct pch_gbe_adapter { struct pch_gbe_rx_ring *rx_ring; unsigned long rx_buffer_len; unsigned long tx_queue_len; - bool rx_csum; - bool tx_csum; bool have_msi; }; diff --git a/drivers/net/pch_gbe/pch_gbe_ethtool.c b/drivers/net/pch_gbe/pch_gbe_ethtool.c index d2174a40d708..c35d105ab285 100644 --- a/drivers/net/pch_gbe/pch_gbe_ethtool.c +++ b/drivers/net/pch_gbe/pch_gbe_ethtool.c @@ -433,57 +433,6 @@ static int pch_gbe_set_pauseparam(struct net_device *netdev, return ret; } -/** - * pch_gbe_get_rx_csum - Report whether receive checksums are turned on or off - * @netdev: Network interface device structure - * Returns - * true(1): Checksum On - * false(0): Checksum Off - */ -static u32 pch_gbe_get_rx_csum(struct net_device *netdev) -{ - struct pch_gbe_adapter *adapter = netdev_priv(netdev); - - return adapter->rx_csum; -} - -/** - * pch_gbe_set_rx_csum - Turn receive checksum on or off - * @netdev: Network interface device structure - * @data: Checksum On[true] or Off[false] - * Returns - * 0: Successful. - * Negative value: Failed. - */ -static int pch_gbe_set_rx_csum(struct net_device *netdev, u32 data) -{ - struct pch_gbe_adapter *adapter = netdev_priv(netdev); - - adapter->rx_csum = data; - if ((netif_running(netdev))) - pch_gbe_reinit_locked(adapter); - else - pch_gbe_reset(adapter); - - return 0; -} - -/** - * pch_gbe_set_tx_csum - Turn transmit checksums on or off - * @netdev: Network interface device structure - * @data: Checksum on[true] or off[false] - * Returns - * 0: Successful. - * Negative value: Failed. - */ -static int pch_gbe_set_tx_csum(struct net_device *netdev, u32 data) -{ - struct pch_gbe_adapter *adapter = netdev_priv(netdev); - - adapter->tx_csum = data; - return ethtool_op_set_tx_ipv6_csum(netdev, data); -} - /** * pch_gbe_get_strings - Return a set of strings that describe the requested * objects @@ -554,9 +503,6 @@ static const struct ethtool_ops pch_gbe_ethtool_ops = { .set_ringparam = pch_gbe_set_ringparam, .get_pauseparam = pch_gbe_get_pauseparam, .set_pauseparam = pch_gbe_set_pauseparam, - .get_rx_csum = pch_gbe_get_rx_csum, - .set_rx_csum = pch_gbe_set_rx_csum, - .set_tx_csum = pch_gbe_set_tx_csum, .get_strings = pch_gbe_get_strings, .get_ethtool_stats = pch_gbe_get_ethtool_stats, .get_sset_count = pch_gbe_get_sset_count, diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index 2ef2f9cdefa6..4cc9872f5ec4 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c @@ -656,6 +656,7 @@ static void pch_gbe_configure_tx(struct pch_gbe_adapter *adapter) */ static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter) { + struct net_device *netdev = adapter->netdev; struct pch_gbe_hw *hw = &adapter->hw; u32 rx_mode, tcpip; @@ -666,7 +667,7 @@ static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter) tcpip = ioread32(&hw->reg->TCPIP_ACC); - if (adapter->rx_csum) { + if (netdev->features & NETIF_F_RXCSUM) { tcpip &= ~PCH_GBE_RX_TCPIPACC_OFF; tcpip |= PCH_GBE_RX_TCPIPACC_EN; } else { @@ -950,7 +951,7 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter, frame_ctrl = 0; if (unlikely(skb->len < PCH_GBE_SHORT_PKT)) frame_ctrl |= PCH_GBE_TXD_CTRL_APAD; - if (unlikely(!adapter->tx_csum)) + if (skb->ip_summed == CHECKSUM_NONE) frame_ctrl |= PCH_GBE_TXD_CTRL_TCPIP_ACC_OFF; /* Performs checksum processing */ @@ -958,7 +959,7 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter, * It is because the hardware accelerator does not support a checksum, * when the received data size is less than 64 bytes. */ - if ((skb->len < PCH_GBE_SHORT_PKT) && (adapter->tx_csum)) { + if (skb->len < PCH_GBE_SHORT_PKT && skb->ip_summed != CHECKSUM_NONE) { frame_ctrl |= PCH_GBE_TXD_CTRL_APAD | PCH_GBE_TXD_CTRL_TCPIP_ACC_OFF; if (skb->protocol == htons(ETH_P_IP)) { @@ -1426,7 +1427,7 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, length = (rx_desc->rx_words_eob) - 3; /* Decide the data conversion method */ - if (!adapter->rx_csum) { + if (!(netdev->features & NETIF_F_RXCSUM)) { /* [Header:14][payload] */ if (NET_IP_ALIGN) { /* Because alignment differs, @@ -2029,6 +2030,29 @@ static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu) return 0; } +/** + * pch_gbe_set_features - Reset device after features changed + * @netdev: Network interface device structure + * @features: New features + * Returns + * 0: HW state updated successfully + */ +static int pch_gbe_set_features(struct net_device *netdev, u32 features) +{ + struct pch_gbe_adapter *adapter = netdev_priv(netdev); + u32 changed = features ^ netdev->features; + + if (!(changed & NETIF_F_RXCSUM)) + return 0; + + if (netif_running(netdev)) + pch_gbe_reinit_locked(adapter); + else + pch_gbe_reset(adapter); + + return 0; +} + /** * pch_gbe_ioctl - Controls register through a MII interface * @netdev: Network interface device structure @@ -2129,6 +2153,7 @@ static const struct net_device_ops pch_gbe_netdev_ops = { .ndo_set_mac_address = pch_gbe_set_mac, .ndo_tx_timeout = pch_gbe_tx_timeout, .ndo_change_mtu = pch_gbe_change_mtu, + .ndo_set_features = pch_gbe_set_features, .ndo_do_ioctl = pch_gbe_ioctl, .ndo_set_multicast_list = &pch_gbe_set_multi, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -2334,7 +2359,9 @@ static int pch_gbe_probe(struct pci_dev *pdev, netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD; netif_napi_add(netdev, &adapter->napi, pch_gbe_napi_poll, PCH_GBE_RX_WEIGHT); - netdev->features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_GRO; + netdev->hw_features = NETIF_F_RXCSUM | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + netdev->features = netdev->hw_features; pch_gbe_set_ethtool_ops(netdev); pch_gbe_mac_load_mac_addr(&adapter->hw); @@ -2373,11 +2400,6 @@ static int pch_gbe_probe(struct pci_dev *pdev, pch_gbe_check_options(adapter); - if (adapter->tx_csum) - netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - else - netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - /* initialize the wol settings based on the eeprom settings */ adapter->wake_up_evt = PCH_GBE_WL_INIT_SETTING; dev_info(&pdev->dev, "MAC address : %pM\n", netdev->dev_addr); diff --git a/drivers/net/pch_gbe/pch_gbe_param.c b/drivers/net/pch_gbe/pch_gbe_param.c index ef0996a0eaaa..5b5d90a47e29 100644 --- a/drivers/net/pch_gbe/pch_gbe_param.c +++ b/drivers/net/pch_gbe/pch_gbe_param.c @@ -426,6 +426,8 @@ full_duplex_only: void pch_gbe_check_options(struct pch_gbe_adapter *adapter) { struct pch_gbe_hw *hw = &adapter->hw; + struct net_device *dev = adapter->netdev; + int val; { /* Transmit Descriptor Count */ static const struct pch_gbe_option opt = { @@ -466,9 +468,10 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter) .err = "defaulting to Enabled", .def = PCH_GBE_DEFAULT_RX_CSUM }; - adapter->rx_csum = XsumRX; - pch_gbe_validate_option((int *)(&adapter->rx_csum), - &opt, adapter); + val = XsumRX; + pch_gbe_validate_option(&val, &opt, adapter); + if (!val) + dev->features &= ~NETIF_F_RXCSUM; } { /* Checksum Offload Enable/Disable */ static const struct pch_gbe_option opt = { @@ -477,9 +480,10 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter) .err = "defaulting to Enabled", .def = PCH_GBE_DEFAULT_TX_CSUM }; - adapter->tx_csum = XsumTX; - pch_gbe_validate_option((int *)(&adapter->tx_csum), - &opt, adapter); + val = XsumTX; + pch_gbe_validate_option(&val, &opt, adapter); + if (!val) + dev->features &= ~NETIF_F_ALL_CSUM; } { /* Flow Control */ static const struct pch_gbe_option opt = { -- cgit v1.2.3-58-ga151 From b9367bf3ee6da380e0c338bd75bb8e8e4e0b981b Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 19 Apr 2011 02:14:25 +0000 Subject: net: ibmveth: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A minimal conversion. ibmveth_set_csum_offload() can be folded into ibmveth_set_features() and adapter->rx_csum removed - left for later cleanup. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/ibmveth.c | 96 +++++++++++++++------------------------------------ 1 file changed, 27 insertions(+), 69 deletions(-) diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 5522d459654c..4855f1fdff52 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -729,45 +729,24 @@ static void netdev_get_drvinfo(struct net_device *dev, sizeof(info->version) - 1); } -static void ibmveth_set_rx_csum_flags(struct net_device *dev, u32 data) +static u32 ibmveth_fix_features(struct net_device *dev, u32 features) { - struct ibmveth_adapter *adapter = netdev_priv(dev); - - if (data) { - adapter->rx_csum = 1; - } else { - /* - * Since the ibmveth firmware interface does not have the - * concept of separate tx/rx checksum offload enable, if rx - * checksum is disabled we also have to disable tx checksum - * offload. Once we disable rx checksum offload, we are no - * longer allowed to send tx buffers that are not properly - * checksummed. - */ - adapter->rx_csum = 0; - dev->features &= ~NETIF_F_IP_CSUM; - dev->features &= ~NETIF_F_IPV6_CSUM; - } -} + /* + * Since the ibmveth firmware interface does not have the + * concept of separate tx/rx checksum offload enable, if rx + * checksum is disabled we also have to disable tx checksum + * offload. Once we disable rx checksum offload, we are no + * longer allowed to send tx buffers that are not properly + * checksummed. + */ -static void ibmveth_set_tx_csum_flags(struct net_device *dev, u32 data) -{ - struct ibmveth_adapter *adapter = netdev_priv(dev); + if (!(features & NETIF_F_RXCSUM)) + features &= ~NETIF_F_ALL_CSUM; - if (data) { - if (adapter->fw_ipv4_csum_support) - dev->features |= NETIF_F_IP_CSUM; - if (adapter->fw_ipv6_csum_support) - dev->features |= NETIF_F_IPV6_CSUM; - adapter->rx_csum = 1; - } else { - dev->features &= ~NETIF_F_IP_CSUM; - dev->features &= ~NETIF_F_IPV6_CSUM; - } + return features; } -static int ibmveth_set_csum_offload(struct net_device *dev, u32 data, - void (*done) (struct net_device *, u32)) +static int ibmveth_set_csum_offload(struct net_device *dev, u32 data) { struct ibmveth_adapter *adapter = netdev_priv(dev); unsigned long set_attr, clr_attr, ret_attr; @@ -827,8 +806,8 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data, } else adapter->fw_ipv6_csum_support = data; - if (ret == H_SUCCESS || ret6 == H_SUCCESS) - done(dev, data); + if (ret != H_SUCCESS || ret6 != H_SUCCESS) + adapter->rx_csum = data; else rc1 = -EIO; } else { @@ -844,41 +823,22 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data, return rc1 ? rc1 : rc2; } -static int ibmveth_set_rx_csum(struct net_device *dev, u32 data) +static int ibmveth_set_features(struct net_device *dev, u32 features) { struct ibmveth_adapter *adapter = netdev_priv(dev); + int rx_csum = !!(features & NETIF_F_RXCSUM); + int rc; - if ((data && adapter->rx_csum) || (!data && !adapter->rx_csum)) - return 0; - - return ibmveth_set_csum_offload(dev, data, ibmveth_set_rx_csum_flags); -} - -static int ibmveth_set_tx_csum(struct net_device *dev, u32 data) -{ - struct ibmveth_adapter *adapter = netdev_priv(dev); - int rc = 0; - - if (data && (dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))) - return 0; - if (!data && !(dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))) + if (rx_csum == adapter->rx_csum) return 0; - if (data && !adapter->rx_csum) - rc = ibmveth_set_csum_offload(dev, data, - ibmveth_set_tx_csum_flags); - else - ibmveth_set_tx_csum_flags(dev, data); + rc = ibmveth_set_csum_offload(dev, rx_csum); + if (rc && !adapter->rx_csum) + dev->features = features & ~(NETIF_F_ALL_CSUM | NETIF_F_RXCSUM); return rc; } -static u32 ibmveth_get_rx_csum(struct net_device *dev) -{ - struct ibmveth_adapter *adapter = netdev_priv(dev); - return adapter->rx_csum; -} - static void ibmveth_get_strings(struct net_device *dev, u32 stringset, u8 *data) { int i; @@ -914,13 +874,9 @@ static const struct ethtool_ops netdev_ethtool_ops = { .get_drvinfo = netdev_get_drvinfo, .get_settings = netdev_get_settings, .get_link = ethtool_op_get_link, - .set_tx_csum = ibmveth_set_tx_csum, - .get_rx_csum = ibmveth_get_rx_csum, - .set_rx_csum = ibmveth_set_rx_csum, .get_strings = ibmveth_get_strings, .get_sset_count = ibmveth_get_sset_count, .get_ethtool_stats = ibmveth_get_ethtool_stats, - .set_sg = ethtool_op_set_sg, }; static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) @@ -1345,6 +1301,8 @@ static const struct net_device_ops ibmveth_netdev_ops = { .ndo_set_multicast_list = ibmveth_set_multicast_list, .ndo_do_ioctl = ibmveth_ioctl, .ndo_change_mtu = ibmveth_change_mtu, + .ndo_fix_features = ibmveth_fix_features, + .ndo_set_features = ibmveth_set_features, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -1412,7 +1370,9 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, netdev->netdev_ops = &ibmveth_netdev_ops; netdev->ethtool_ops = &netdev_ethtool_ops; SET_NETDEV_DEV(netdev, &dev->dev); - netdev->features |= NETIF_F_SG; + netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + netdev->features |= netdev->hw_features; memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); @@ -1437,8 +1397,6 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, netdev_dbg(netdev, "registering netdev...\n"); - ibmveth_set_csum_offload(netdev, 1, ibmveth_set_tx_csum_flags); - rc = register_netdev(netdev); if (rc) { -- cgit v1.2.3-58-ga151 From 135d84a9f28854f875f32f97485737b0013c99d6 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 19 Apr 2011 03:03:57 +0000 Subject: net: qlcnic: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bit more than minimal conversion. There might be some issues because of qlcnic_set_netdev_features() if it's called after netdev init. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 3 +- drivers/net/qlcnic/qlcnic_ethtool.c | 120 ------------------------------------ drivers/net/qlcnic/qlcnic_hw.c | 37 +++++++++++ drivers/net/qlcnic/qlcnic_init.c | 4 +- drivers/net/qlcnic/qlcnic_main.c | 35 +++++------ 5 files changed, 57 insertions(+), 142 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index e5d30538f373..fa5b15c474b0 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -926,7 +926,6 @@ struct qlcnic_adapter { u8 max_rds_rings; u8 max_sds_rings; u8 msix_supported; - u8 rx_csum; u8 portnum; u8 physical_port; u8 reset_context; @@ -1247,6 +1246,8 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup); int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu); int qlcnic_change_mtu(struct net_device *netdev, int new_mtu); +u32 qlcnic_fix_features(struct net_device *netdev, u32 features); +int qlcnic_set_features(struct net_device *netdev, u32 features); int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable); int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable); int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter); diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 3cd8a169694a..615a5ab88456 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -764,73 +764,6 @@ qlcnic_get_ethtool_stats(struct net_device *dev, qlcnic_fill_device_stats(&index, data, &port_stats.tx); } -static int qlcnic_set_tx_csum(struct net_device *dev, u32 data) -{ - struct qlcnic_adapter *adapter = netdev_priv(dev); - - if ((adapter->flags & QLCNIC_ESWITCH_ENABLED)) - return -EOPNOTSUPP; - if (data) - dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - else - dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - - return 0; - -} -static u32 qlcnic_get_tx_csum(struct net_device *dev) -{ - return dev->features & NETIF_F_IP_CSUM; -} - -static u32 qlcnic_get_rx_csum(struct net_device *dev) -{ - struct qlcnic_adapter *adapter = netdev_priv(dev); - return adapter->rx_csum; -} - -static int qlcnic_set_rx_csum(struct net_device *dev, u32 data) -{ - struct qlcnic_adapter *adapter = netdev_priv(dev); - - if ((adapter->flags & QLCNIC_ESWITCH_ENABLED)) - return -EOPNOTSUPP; - if (!!data) { - adapter->rx_csum = !!data; - return 0; - } - - if (dev->features & NETIF_F_LRO) { - if (qlcnic_config_hw_lro(adapter, QLCNIC_LRO_DISABLED)) - return -EIO; - - dev->features &= ~NETIF_F_LRO; - qlcnic_send_lro_cleanup(adapter); - dev_info(&adapter->pdev->dev, - "disabling LRO as rx_csum is off\n"); - } - adapter->rx_csum = !!data; - return 0; -} - -static u32 qlcnic_get_tso(struct net_device *dev) -{ - return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0; -} - -static int qlcnic_set_tso(struct net_device *dev, u32 data) -{ - struct qlcnic_adapter *adapter = netdev_priv(dev); - if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)) - return -EOPNOTSUPP; - if (data) - dev->features |= (NETIF_F_TSO | NETIF_F_TSO6); - else - dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); - - return 0; -} - static int qlcnic_set_led(struct net_device *dev, enum ethtool_phys_id_state state) { @@ -993,50 +926,6 @@ static int qlcnic_get_intr_coalesce(struct net_device *netdev, return 0; } -static int qlcnic_set_flags(struct net_device *netdev, u32 data) -{ - struct qlcnic_adapter *adapter = netdev_priv(netdev); - int hw_lro; - - if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO)) - return -EINVAL; - - if (data & ETH_FLAG_LRO) { - - if (netdev->features & NETIF_F_LRO) - return 0; - - if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)) - return -EINVAL; - - if (!adapter->rx_csum) { - dev_info(&adapter->pdev->dev, "rx csum is off, " - "cannot toggle lro\n"); - return -EINVAL; - } - - hw_lro = QLCNIC_LRO_ENABLED; - netdev->features |= NETIF_F_LRO; - - } else { - - if (!(netdev->features & NETIF_F_LRO)) - return 0; - - hw_lro = 0; - netdev->features &= ~NETIF_F_LRO; - } - - if (qlcnic_config_hw_lro(adapter, hw_lro)) - return -EIO; - - if ((hw_lro == 0) && qlcnic_send_lro_cleanup(adapter)) - return -EIO; - - - return 0; -} - static u32 qlcnic_get_msglevel(struct net_device *netdev) { struct qlcnic_adapter *adapter = netdev_priv(netdev); @@ -1064,23 +953,14 @@ const struct ethtool_ops qlcnic_ethtool_ops = { .set_ringparam = qlcnic_set_ringparam, .get_pauseparam = qlcnic_get_pauseparam, .set_pauseparam = qlcnic_set_pauseparam, - .get_tx_csum = qlcnic_get_tx_csum, - .set_tx_csum = qlcnic_set_tx_csum, - .set_sg = ethtool_op_set_sg, - .get_tso = qlcnic_get_tso, - .set_tso = qlcnic_set_tso, .get_wol = qlcnic_get_wol, .set_wol = qlcnic_set_wol, .self_test = qlcnic_diag_test, .get_strings = qlcnic_get_strings, .get_ethtool_stats = qlcnic_get_ethtool_stats, .get_sset_count = qlcnic_get_sset_count, - .get_rx_csum = qlcnic_get_rx_csum, - .set_rx_csum = qlcnic_set_rx_csum, .get_coalesce = qlcnic_get_intr_coalesce, .set_coalesce = qlcnic_set_intr_coalesce, - .get_flags = ethtool_op_get_flags, - .set_flags = qlcnic_set_flags, .set_phys_id = qlcnic_set_led, .set_msglevel = qlcnic_set_msglevel, .get_msglevel = qlcnic_get_msglevel, diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 498cca92126a..cbb27f2df008 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -758,6 +758,43 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu) return rc; } + +u32 qlcnic_fix_features(struct net_device *netdev, u32 features) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + + if ((adapter->flags & QLCNIC_ESWITCH_ENABLED)) { + u32 changed = features ^ netdev->features; + features ^= changed & (NETIF_F_ALL_CSUM | NETIF_F_RXCSUM); + } + + if (!(features & NETIF_F_RXCSUM)) + features &= ~NETIF_F_LRO; + + return features; +} + + +int qlcnic_set_features(struct net_device *netdev, u32 features) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + u32 changed = netdev->features ^ features; + int hw_lro = (features & NETIF_F_LRO) ? QLCNIC_LRO_ENABLED : 0; + + if (!(changed & NETIF_F_LRO)) + return 0; + + netdev->features = features ^ NETIF_F_LRO; + + if (qlcnic_config_hw_lro(adapter, hw_lro)) + return -EIO; + + if ((hw_lro == 0) && qlcnic_send_lro_cleanup(adapter)) + return -EIO; + + return 0; +} + /* * Changes the CRB window to the specified window. */ diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 4ec0eeb6bff9..d0f338b01396 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -1390,8 +1390,8 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, skb = buffer->skb; - if (likely(adapter->rx_csum && (cksum == STATUS_CKSUM_OK || - cksum == STATUS_CKSUM_LOOP))) { + if (likely((adapter->netdev->features & NETIF_F_RXCSUM) && + (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) { adapter->stats.csummed++; skb->ip_summed = CHECKSUM_UNNECESSARY; } else { diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index e9e9ba6efc5f..6e619514feee 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -328,6 +328,8 @@ static const struct net_device_ops qlcnic_netdev_ops = { .ndo_set_multicast_list = qlcnic_set_multi, .ndo_set_mac_address = qlcnic_set_mac, .ndo_change_mtu = qlcnic_change_mtu, + .ndo_fix_features = qlcnic_fix_features, + .ndo_set_features = qlcnic_set_features, .ndo_tx_timeout = qlcnic_tx_timeout, .ndo_vlan_rx_add_vid = qlcnic_vlan_rx_add, .ndo_vlan_rx_kill_vid = qlcnic_vlan_rx_del, @@ -764,7 +766,7 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter, struct net_device *netdev = adapter->netdev; unsigned long features, vlan_features; - features = (NETIF_F_SG | NETIF_F_IP_CSUM | + features = (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_IPV6_CSUM | NETIF_F_GRO); vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_FILTER); @@ -779,14 +781,12 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter, if (esw_cfg->offload_flags & BIT_0) { netdev->features |= features; - adapter->rx_csum = 1; if (!(esw_cfg->offload_flags & BIT_1)) netdev->features &= ~NETIF_F_TSO; if (!(esw_cfg->offload_flags & BIT_2)) netdev->features &= ~NETIF_F_TSO6; } else { netdev->features &= ~features; - adapter->rx_csum = 0; } netdev->vlan_features = (features & vlan_features); @@ -1436,7 +1436,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, int err; struct pci_dev *pdev = adapter->pdev; - adapter->rx_csum = 1; adapter->mc_enabled = 0; adapter->max_mc_count = 38; @@ -1447,26 +1446,24 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops); - netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | NETIF_F_GRO | NETIF_F_HW_VLAN_RX); - netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_FILTER); + netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) { - netdev->features |= (NETIF_F_TSO | NETIF_F_TSO6); - netdev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6); - } + if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) + netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; + if (pci_using_dac) + netdev->hw_features |= NETIF_F_HIGHDMA; - if (pci_using_dac) { - netdev->features |= NETIF_F_HIGHDMA; - netdev->vlan_features |= NETIF_F_HIGHDMA; - } + netdev->vlan_features = netdev->hw_features; if (adapter->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX) - netdev->features |= (NETIF_F_HW_VLAN_TX); - + netdev->hw_features |= NETIF_F_HW_VLAN_TX; if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) - netdev->features |= NETIF_F_LRO; + netdev->hw_features |= NETIF_F_LRO; + + netdev->features |= netdev->hw_features | + NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; + netdev->irq = adapter->msix_entries[0].vector; netif_carrier_off(netdev); -- cgit v1.2.3-58-ga151 From 47103041e91794acdbc6165da0ae288d844c820b Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 19 Apr 2011 03:35:06 +0000 Subject: net: xen-netback: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Acked-by: Ian Campbell Signed-off-by: David S. Miller --- drivers/net/xen-netback/common.h | 3 -- drivers/net/xen-netback/interface.c | 84 +++++++------------------------------ 2 files changed, 15 insertions(+), 72 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 5d7bbf2b2ee7..8753e6ddff8f 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -73,9 +73,6 @@ struct xenvif { struct vm_struct *tx_comms_area; struct vm_struct *rx_comms_area; - /* Flags that must not be set in dev->features */ - u32 features_disabled; - /* Frontend feature information. */ u8 can_sg:1; u8 gso:1; diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index de569cc19da4..0ca86f9ec4ed 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -165,69 +165,18 @@ static int xenvif_change_mtu(struct net_device *dev, int mtu) return 0; } -static void xenvif_set_features(struct xenvif *vif) -{ - struct net_device *dev = vif->dev; - u32 features = dev->features; - - if (vif->can_sg) - features |= NETIF_F_SG; - if (vif->gso || vif->gso_prefix) - features |= NETIF_F_TSO; - if (vif->csum) - features |= NETIF_F_IP_CSUM; - - features &= ~(vif->features_disabled); - - if (!(features & NETIF_F_SG) && dev->mtu > ETH_DATA_LEN) - dev->mtu = ETH_DATA_LEN; - - dev->features = features; -} - -static int xenvif_set_tx_csum(struct net_device *dev, u32 data) -{ - struct xenvif *vif = netdev_priv(dev); - if (data) { - if (!vif->csum) - return -EOPNOTSUPP; - vif->features_disabled &= ~NETIF_F_IP_CSUM; - } else { - vif->features_disabled |= NETIF_F_IP_CSUM; - } - - xenvif_set_features(vif); - return 0; -} - -static int xenvif_set_sg(struct net_device *dev, u32 data) +static u32 xenvif_fix_features(struct net_device *dev, u32 features) { struct xenvif *vif = netdev_priv(dev); - if (data) { - if (!vif->can_sg) - return -EOPNOTSUPP; - vif->features_disabled &= ~NETIF_F_SG; - } else { - vif->features_disabled |= NETIF_F_SG; - } - xenvif_set_features(vif); - return 0; -} + if (!vif->can_sg) + features &= ~NETIF_F_SG; + if (!vif->gso && !vif->gso_prefix) + features &= ~NETIF_F_TSO; + if (!vif->csum) + features &= ~NETIF_F_IP_CSUM; -static int xenvif_set_tso(struct net_device *dev, u32 data) -{ - struct xenvif *vif = netdev_priv(dev); - if (data) { - if (!vif->gso && !vif->gso_prefix) - return -EOPNOTSUPP; - vif->features_disabled &= ~NETIF_F_TSO; - } else { - vif->features_disabled |= NETIF_F_TSO; - } - - xenvif_set_features(vif); - return 0; + return features; } static const struct xenvif_stat { @@ -274,12 +223,6 @@ static void xenvif_get_strings(struct net_device *dev, u32 stringset, u8 * data) } static struct ethtool_ops xenvif_ethtool_ops = { - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = xenvif_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = xenvif_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = xenvif_set_tso, .get_link = ethtool_op_get_link, .get_sset_count = xenvif_get_sset_count, @@ -293,6 +236,7 @@ static struct net_device_ops xenvif_netdev_ops = { .ndo_open = xenvif_open, .ndo_stop = xenvif_close, .ndo_change_mtu = xenvif_change_mtu, + .ndo_fix_features = xenvif_fix_features, }; struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, @@ -331,7 +275,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, vif->credit_timeout.expires = jiffies; dev->netdev_ops = &xenvif_netdev_ops; - xenvif_set_features(vif); + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; + dev->features = dev->hw_features; SET_ETHTOOL_OPS(dev, &xenvif_ethtool_ops); dev->tx_queue_len = XENVIF_QUEUE_LENGTH; @@ -367,8 +312,6 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, if (vif->irq) return 0; - xenvif_set_features(vif); - err = xen_netbk_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref); if (err < 0) goto err; @@ -384,9 +327,12 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, xenvif_get(vif); rtnl_lock(); - netif_carrier_on(vif->dev); if (netif_running(vif->dev)) xenvif_up(vif); + if (!vif->can_sg && vif->dev->mtu > ETH_DATA_LEN) + dev_set_mtu(vif->dev, ETH_DATA_LEN); + netdev_update_features(vif->dev); + netif_carrier_on(vif->dev); rtnl_unlock(); return 0; -- cgit v1.2.3-58-ga151 From 882553752196605bf27057e7adb298ecae8058c4 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 19 Apr 2011 06:13:10 +0000 Subject: net: tun: convert to hw_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This changes offload setting behaviour to what I think is correct: - offloads set via ethtool mean what admin wants to use (by default he wants 'em all) - offloads set via ioctl() mean what userspace is expecting to get (this limits which admin wishes are granted) - TUN_NOCHECKSUM is ignored, as it might cause broken packets when forwarded (ip_summed == CHECKSUM_UNNECESSARY means that checksum was verified, not that it can be ignored) If TUN_NOCHECKSUM is implemented, it should set skb->csum_* and skb->ip_summed (= CHECKSUM_PARTIAL) for known protocols and let others be verified by kernel when necessary. TUN_NOCHECKSUM handling was introduced by commit f43798c27684ab925adde7d8acc34c78c6e50df8: tun: Allow GSO using virtio_net_hdr Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/tun.c | 63 ++++++++++++++++++++++--------------------------------- 1 file changed, 25 insertions(+), 38 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index f5e9ac00a07b..ade3cf9cd326 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -123,6 +123,9 @@ struct tun_struct { gid_t group; struct net_device *dev; + u32 set_features; +#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ + NETIF_F_TSO6|NETIF_F_UFO) struct fasync_struct *fasync; struct tap_filter txflt; @@ -451,12 +454,20 @@ tun_net_change_mtu(struct net_device *dev, int new_mtu) return 0; } +static u32 tun_net_fix_features(struct net_device *dev, u32 features) +{ + struct tun_struct *tun = netdev_priv(dev); + + return (features & tun->set_features) | (features & ~TUN_USER_FEATURES); +} + static const struct net_device_ops tun_netdev_ops = { .ndo_uninit = tun_net_uninit, .ndo_open = tun_net_open, .ndo_stop = tun_net_close, .ndo_start_xmit = tun_net_xmit, .ndo_change_mtu = tun_net_change_mtu, + .ndo_fix_features = tun_net_fix_features, }; static const struct net_device_ops tap_netdev_ops = { @@ -465,6 +476,7 @@ static const struct net_device_ops tap_netdev_ops = { .ndo_stop = tun_net_close, .ndo_start_xmit = tun_net_xmit, .ndo_change_mtu = tun_net_change_mtu, + .ndo_fix_features = tun_net_fix_features, .ndo_set_multicast_list = tun_net_mclist, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, @@ -628,8 +640,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, kfree_skb(skb); return -EINVAL; } - } else if (tun->flags & TUN_NOCHECKSUM) - skb->ip_summed = CHECKSUM_UNNECESSARY; + } switch (tun->flags & TUN_TYPE_MASK) { case TUN_TUN_DEV: @@ -1094,6 +1105,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) goto err_free_sk; } + dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | + TUN_USER_FEATURES; + dev->features = dev->hw_features; + err = register_netdevice(tun->dev); if (err < 0) goto err_free_sk; @@ -1158,18 +1173,12 @@ static int tun_get_iff(struct net *net, struct tun_struct *tun, /* This is like a cut-down ethtool ops, except done via tun fd so no * privs required. */ -static int set_offload(struct net_device *dev, unsigned long arg) +static int set_offload(struct tun_struct *tun, unsigned long arg) { - u32 old_features, features; - - old_features = dev->features; - /* Unset features, set them as we chew on the arg. */ - features = (old_features & ~(NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST - |NETIF_F_TSO_ECN|NETIF_F_TSO|NETIF_F_TSO6 - |NETIF_F_UFO)); + u32 features = 0; if (arg & TUN_F_CSUM) { - features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; + features |= NETIF_F_HW_CSUM; arg &= ~TUN_F_CSUM; if (arg & (TUN_F_TSO4|TUN_F_TSO6)) { @@ -1195,9 +1204,8 @@ static int set_offload(struct net_device *dev, unsigned long arg) if (arg) return -EINVAL; - dev->features = features; - if (old_features != dev->features) - netdev_features_change(dev); + tun->set_features = features; + netdev_update_features(tun->dev); return 0; } @@ -1262,12 +1270,9 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, case TUNSETNOCSUM: /* Disable/Enable checksum */ - if (arg) - tun->flags |= TUN_NOCHECKSUM; - else - tun->flags &= ~TUN_NOCHECKSUM; - tun_debug(KERN_INFO, tun, "checksum %s\n", + /* [unimplemented] */ + tun_debug(KERN_INFO, tun, "ignored: set checksum %s\n", arg ? "disabled" : "enabled"); break; @@ -1316,7 +1321,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, break; #endif case TUNSETOFFLOAD: - ret = set_offload(tun->dev, arg); + ret = set_offload(tun, arg); break; case TUNSETTXFILTER: @@ -1595,30 +1600,12 @@ static void tun_set_msglevel(struct net_device *dev, u32 value) #endif } -static u32 tun_get_rx_csum(struct net_device *dev) -{ - struct tun_struct *tun = netdev_priv(dev); - return (tun->flags & TUN_NOCHECKSUM) == 0; -} - -static int tun_set_rx_csum(struct net_device *dev, u32 data) -{ - struct tun_struct *tun = netdev_priv(dev); - if (data) - tun->flags &= ~TUN_NOCHECKSUM; - else - tun->flags |= TUN_NOCHECKSUM; - return 0; -} - static const struct ethtool_ops tun_ethtool_ops = { .get_settings = tun_get_settings, .get_drvinfo = tun_get_drvinfo, .get_msglevel = tun_get_msglevel, .set_msglevel = tun_set_msglevel, .get_link = ethtool_op_get_link, - .get_rx_csum = tun_get_rx_csum, - .set_rx_csum = tun_set_rx_csum }; -- cgit v1.2.3-58-ga151 From 8a00be1c89cc17fda5f438794ff27449af6f00f1 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Tue, 19 Apr 2011 21:25:40 +0000 Subject: sctp: check parameter value of length in ERROR chunk When an endpoint receives ERROR that parameter value is invalid, send an ABORT to peer with a Protocol Violation error code. Signed-off-by: Shan Wei Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/sctp/sm_statefuns.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index c08547270e8e..fe2036d79f53 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -3204,6 +3204,7 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep, sctp_cmd_seq_t *commands) { struct sctp_chunk *chunk = arg; + sctp_errhdr_t *err; if (!sctp_vtag_verify(chunk, asoc)) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); @@ -3212,6 +3213,10 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep, if (!sctp_chunk_length_valid(chunk, sizeof(sctp_operr_chunk_t))) return sctp_sf_violation_chunklen(ep, asoc, type, arg, commands); + sctp_walk_errors(err, chunk->chunk_hdr); + if ((void *)err != (void *)chunk->chunk_end) + return sctp_sf_violation_paramlen(ep, asoc, type, arg, + (void *)err, commands); sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR, SCTP_CHUNK(chunk)); -- cgit v1.2.3-58-ga151 From 96ca468b86b09aa6a001ac65dba93a6c4a3692a5 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Tue, 19 Apr 2011 21:26:26 +0000 Subject: sctp: check invalid value of length parameter in error cause RFC4960, section 3.3.7 said: If an endpoint receives an ABORT with a format error or no TCB is found, it MUST silently discard it. When an endpoint receives ABORT that parameter value is invalid, drop it. Signed-off-by: Shan Wei Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/sctp/sm_statefuns.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index fe2036d79f53..194d5ecab5c3 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2412,8 +2412,15 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, /* See if we have an error cause code in the chunk. */ len = ntohs(chunk->chunk_hdr->length); - if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) + if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) { + + sctp_errhdr_t *err; + sctp_walk_errors(err, chunk->chunk_hdr); + if ((void *)err != (void *)chunk->chunk_end) + return sctp_sf_pdiscard(ep, asoc, type, arg, commands); + error = ((sctp_errhdr_t *)chunk->skb->data)->cause; + } sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET)); /* ASSOC_FAILED will DELETE_TCB. */ -- cgit v1.2.3-58-ga151 From 48669698c23339e0fa31753f04e77648fc210339 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Tue, 19 Apr 2011 21:27:07 +0000 Subject: sctp: remove redundant check when walking through a list of TLV parameters When pos.v <= (void *)chunk + end - ntohs(pos.p->length) and ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t) these two expressions are all true, pos.v <= (void *)chunk + end - sizeof(sctp_paramhdr_t) *must* be true. This patch removes this kind of redundant check. It's same to _sctp_walk_errors macro. Signed-off-by: Shan Wei Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 505845ddb0be..7e8e34c29270 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -531,7 +531,6 @@ _sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member) #define _sctp_walk_params(pos, chunk, end, member)\ for (pos.v = chunk->member;\ - pos.v <= (void *)chunk + end - sizeof(sctp_paramhdr_t) &&\ pos.v <= (void *)chunk + end - ntohs(pos.p->length) &&\ ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\ pos.v += WORD_ROUND(ntohs(pos.p->length))) @@ -542,7 +541,6 @@ _sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length)) #define _sctp_walk_errors(err, chunk_hdr, end)\ for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \ sizeof(sctp_chunkhdr_t));\ - (void *)err <= (void *)chunk_hdr + end - sizeof(sctp_errhdr_t) &&\ (void *)err <= (void *)chunk_hdr + end - ntohs(err->length) &&\ ntohs(err->length) >= sizeof(sctp_errhdr_t); \ err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length)))) -- cgit v1.2.3-58-ga151 From 0b8f9e25b0aaf5a5d9fd844a97e5c17746b865d4 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 19 Apr 2011 21:28:26 +0000 Subject: sctp: remove completely unsed EMPTY state SCTP does not SCTP_STATE_EMPTY and we can never be in that state. Remove useless code. Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- include/net/sctp/constants.h | 17 +++++----- net/sctp/debug.c | 1 - net/sctp/outqueue.c | 1 - net/sctp/sm_statetable.c | 76 -------------------------------------------- 4 files changed, 8 insertions(+), 87 deletions(-) diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index deac13dd8d02..942b864f6135 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -187,15 +187,14 @@ typedef enum { /* SCTP state defines for internal state machine */ typedef enum { - SCTP_STATE_EMPTY = 0, - SCTP_STATE_CLOSED = 1, - SCTP_STATE_COOKIE_WAIT = 2, - SCTP_STATE_COOKIE_ECHOED = 3, - SCTP_STATE_ESTABLISHED = 4, - SCTP_STATE_SHUTDOWN_PENDING = 5, - SCTP_STATE_SHUTDOWN_SENT = 6, - SCTP_STATE_SHUTDOWN_RECEIVED = 7, - SCTP_STATE_SHUTDOWN_ACK_SENT = 8, + SCTP_STATE_CLOSED = 0, + SCTP_STATE_COOKIE_WAIT = 1, + SCTP_STATE_COOKIE_ECHOED = 2, + SCTP_STATE_ESTABLISHED = 3, + SCTP_STATE_SHUTDOWN_PENDING = 4, + SCTP_STATE_SHUTDOWN_SENT = 5, + SCTP_STATE_SHUTDOWN_RECEIVED = 6, + SCTP_STATE_SHUTDOWN_ACK_SENT = 7, } sctp_state_t; diff --git a/net/sctp/debug.c b/net/sctp/debug.c index bf24fa697de2..ec997cfe0a7e 100644 --- a/net/sctp/debug.c +++ b/net/sctp/debug.c @@ -98,7 +98,6 @@ const char *sctp_cname(const sctp_subtype_t cid) /* These are printable forms of the states. */ const char *const sctp_state_tbl[SCTP_STATE_NUM_STATES] = { - "STATE_EMPTY", "STATE_CLOSED", "STATE_COOKIE_WAIT", "STATE_COOKIE_ECHOED", diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 7812772dbf74..3e9d8d2bbe71 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -320,7 +320,6 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) * chunk. */ switch (q->asoc->state) { - case SCTP_STATE_EMPTY: case SCTP_STATE_CLOSED: case SCTP_STATE_SHUTDOWN_PENDING: case SCTP_STATE_SHUTDOWN_SENT: diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 546d4387fb3c..881196b60a92 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -107,8 +107,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, #define TYPE_SCTP_FUNC(func) {.fn = func, .name = #func} #define TYPE_SCTP_DATA { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -128,8 +126,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_DATA */ #define TYPE_SCTP_INIT { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_do_5_1B_init), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -149,8 +145,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_INIT */ #define TYPE_SCTP_INIT_ACK { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_do_5_2_3_initack), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -170,8 +164,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_INIT_ACK */ #define TYPE_SCTP_SACK { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -191,8 +183,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_SACK */ #define TYPE_SCTP_HEARTBEAT { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -213,8 +203,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_HEARTBEAT */ #define TYPE_SCTP_HEARTBEAT_ACK { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -234,8 +222,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_HEARTBEAT_ACK */ #define TYPE_SCTP_ABORT { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_pdiscard), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -255,8 +241,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_ABORT */ #define TYPE_SCTP_SHUTDOWN { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -276,8 +260,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_SHUTDOWN */ #define TYPE_SCTP_SHUTDOWN_ACK { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -297,8 +279,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_SHUTDOWN_ACK */ #define TYPE_SCTP_ERROR { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -318,8 +298,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_ERROR */ #define TYPE_SCTP_COOKIE_ECHO { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_do_5_1D_ce), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -339,8 +317,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_COOKIE_ECHO */ #define TYPE_SCTP_COOKIE_ACK { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -360,8 +336,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_COOKIE_ACK */ #define TYPE_SCTP_ECN_ECNE { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -381,8 +355,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_ECN_ECNE */ #define TYPE_SCTP_ECN_CWR { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -402,8 +374,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, } /* TYPE_SCTP_ECN_CWR */ #define TYPE_SCTP_SHUTDOWN_COMPLETE { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -446,8 +416,6 @@ static const sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][ }; /* state_fn_t chunk_event_table[][] */ #define TYPE_SCTP_ASCONF { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -467,8 +435,6 @@ static const sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][ } /* TYPE_SCTP_ASCONF */ #define TYPE_SCTP_ASCONF_ACK { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -496,8 +462,6 @@ static const sctp_sm_table_entry_t addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_ }; /*state_fn_t addip_chunk_event_table[][] */ #define TYPE_SCTP_FWD_TSN { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -524,8 +488,6 @@ static const sctp_sm_table_entry_t prsctp_chunk_event_table[SCTP_NUM_PRSCTP_CHUN }; /*state_fn_t prsctp_chunk_event_table[][] */ #define TYPE_SCTP_AUTH { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -553,8 +515,6 @@ static const sctp_sm_table_entry_t auth_chunk_event_table[SCTP_NUM_AUTH_CHUNK_TY static const sctp_sm_table_entry_t chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { - /* SCTP_STATE_EMPTY */ - TYPE_SCTP_FUNC(sctp_sf_ootb), /* SCTP_STATE_CLOSED */ TYPE_SCTP_FUNC(sctp_sf_ootb), /* SCTP_STATE_COOKIE_WAIT */ @@ -575,8 +535,6 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { #define TYPE_SCTP_PRIMITIVE_ASSOCIATE { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_do_prm_asoc), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -596,8 +554,6 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { } /* TYPE_SCTP_PRIMITIVE_ASSOCIATE */ #define TYPE_SCTP_PRIMITIVE_SHUTDOWN { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_error_closed), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -617,8 +573,6 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { } /* TYPE_SCTP_PRIMITIVE_SHUTDOWN */ #define TYPE_SCTP_PRIMITIVE_ABORT { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_error_closed), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -638,8 +592,6 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { } /* TYPE_SCTP_PRIMITIVE_ABORT */ #define TYPE_SCTP_PRIMITIVE_SEND { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_error_closed), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -659,8 +611,6 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { } /* TYPE_SCTP_PRIMITIVE_SEND */ #define TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_error_closed), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -680,8 +630,6 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { } /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */ #define TYPE_SCTP_PRIMITIVE_ASCONF { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_error_closed), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -713,8 +661,6 @@ static const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPE }; #define TYPE_SCTP_OTHER_NO_PENDING_TSN { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -734,8 +680,6 @@ static const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPE } #define TYPE_SCTP_OTHER_ICMP_PROTO_UNREACH { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -760,8 +704,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ }; #define TYPE_SCTP_EVENT_TIMEOUT_NONE { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -781,8 +723,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ } #define TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -802,8 +742,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ } #define TYPE_SCTP_EVENT_TIMEOUT_T1_INIT { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -823,8 +761,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ } #define TYPE_SCTP_EVENT_TIMEOUT_T2_SHUTDOWN { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -844,8 +780,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ } #define TYPE_SCTP_EVENT_TIMEOUT_T3_RTX { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -865,8 +799,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ } #define TYPE_SCTP_EVENT_TIMEOUT_T4_RTO { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -886,8 +818,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ } #define TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -907,8 +837,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ } #define TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -928,8 +856,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ } #define TYPE_SCTP_EVENT_TIMEOUT_SACK { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_bug), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ @@ -949,8 +875,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ } #define TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE { \ - /* SCTP_STATE_EMPTY */ \ - TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_COOKIE_WAIT */ \ -- cgit v1.2.3-58-ga151 From deb85a6ecc432a4f342004a6ac2a0dad7cba6846 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 19 Apr 2011 21:29:23 +0000 Subject: sctp: bail from sctp_endpoint_lookup_assoc() if not bound The sctp_endpoint_lookup_assoc() function uses a port hash to lookup the association and then checks to see if any of them are on the current endpoint. However, if the current endpoint is not bound, there can't be any associations on it, thus we can bail early. Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/sctp/endpointola.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index e10acc01c75f..c8cc24e282c3 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -325,6 +325,7 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( struct sctp_transport **transport) { struct sctp_association *asoc = NULL; + struct sctp_association *tmp; struct sctp_transport *t = NULL; struct sctp_hashbucket *head; struct sctp_ep_common *epb; @@ -333,25 +334,32 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( int rport; *transport = NULL; + + /* If the local port is not set, there can't be any associations + * on this endpoint. + */ + if (!ep->base.bind_addr.port) + goto out; + rport = ntohs(paddr->v4.sin_port); hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport); head = &sctp_assoc_hashtable[hash]; read_lock(&head->lock); sctp_for_each_hentry(epb, node, &head->chain) { - asoc = sctp_assoc(epb); - if (asoc->ep != ep || rport != asoc->peer.port) - goto next; + tmp = sctp_assoc(epb); + if (tmp->ep != ep || rport != tmp->peer.port) + continue; - t = sctp_assoc_lookup_paddr(asoc, paddr); + t = sctp_assoc_lookup_paddr(tmp, paddr); if (t) { + asoc = tmp; *transport = t; break; } -next: - asoc = NULL; } read_unlock(&head->lock); +out: return asoc; } -- cgit v1.2.3-58-ga151 From 85c5ed4e44a262344ce43b4bf23204107923ca95 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Tue, 19 Apr 2011 21:30:01 +0000 Subject: sctp: handle ootb packet in chunk order as defined Changed the order of processing SHUTDOWN ACK and COOKIE ACK refer to section 8.4:Handle "Out of the Blue" Packets. SHUTDOWN ACK chunk should be processed before processing "Stale Cookie" ERROR or a COOKIE ACK. Signed-off-by: Wei Yongjun Signed-off-by: Shan Wei Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/input.c | 15 --------------- net/sctp/sm_statefuns.c | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/net/sctp/input.c b/net/sctp/input.c index 30cec7732e80..3a8eb79eb78b 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -661,7 +661,6 @@ static int sctp_rcv_ootb(struct sk_buff *skb) { sctp_chunkhdr_t *ch; __u8 *ch_end; - sctp_errhdr_t *err; ch = (sctp_chunkhdr_t *) skb->data; @@ -697,20 +696,6 @@ static int sctp_rcv_ootb(struct sk_buff *skb) if (SCTP_CID_INIT == ch->type && (void *)ch != skb->data) goto discard; - /* RFC 8.4, 7) If the packet contains a "Stale cookie" ERROR - * or a COOKIE ACK the SCTP Packet should be silently - * discarded. - */ - if (SCTP_CID_COOKIE_ACK == ch->type) - goto discard; - - if (SCTP_CID_ERROR == ch->type) { - sctp_walk_errors(err, ch) { - if (SCTP_ERROR_STALE_COOKIE == err->cause) - goto discard; - } - } - ch = (sctp_chunkhdr_t *) ch_end; } while (ch_end < skb_tail_pointer(skb)); diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 194d5ecab5c3..ad3b43bb75cc 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -3332,8 +3332,10 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, struct sctp_chunk *chunk = arg; struct sk_buff *skb = chunk->skb; sctp_chunkhdr_t *ch; + sctp_errhdr_t *err; __u8 *ch_end; int ootb_shut_ack = 0; + int ootb_cookie_ack = 0; SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); @@ -3358,6 +3360,23 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, if (SCTP_CID_ABORT == ch->type) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); + /* RFC 8.4, 7) If the packet contains a "Stale cookie" ERROR + * or a COOKIE ACK the SCTP Packet should be silently + * discarded. + */ + + if (SCTP_CID_COOKIE_ACK == ch->type) + ootb_cookie_ack = 1; + + if (SCTP_CID_ERROR == ch->type) { + sctp_walk_errors(err, ch) { + if (SCTP_ERROR_STALE_COOKIE == err->cause) { + ootb_cookie_ack = 1; + break; + } + } + } + /* Report violation if chunk len overflows */ ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); if (ch_end > skb_tail_pointer(skb)) @@ -3369,6 +3388,8 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, if (ootb_shut_ack) return sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands); + else if (ootb_cookie_ack) + return sctp_sf_pdiscard(ep, asoc, type, arg, commands); else return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); } -- cgit v1.2.3-58-ga151 From de6becdc0844ff92b38ffd9f0c4db1d3de02835f Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 19 Apr 2011 21:30:51 +0000 Subject: sctp: fix to check the source address of COOKIE-ECHO chunk SCTP does not check whether the source address of COOKIE-ECHO chunk is the original address of INIT chunk or part of the any address parameters saved in COOKIE in CLOSED state. So even if the COOKIE-ECHO chunk is from any address but with correct COOKIE, the COOKIE-ECHO chunk still be accepted. If the COOKIE is not from a valid address, the assoc should not be established. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 2 +- net/sctp/sm_make_chunk.c | 26 +++++++++++++++++++++----- net/sctp/sm_sideeffect.c | 3 +-- net/sctp/sm_statefuns.c | 14 +++++--------- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 0f6e60a9c308..5c9bada51d2d 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1400,7 +1400,7 @@ int sctp_has_association(const union sctp_addr *laddr, int sctp_verify_init(const struct sctp_association *asoc, sctp_cid_t, sctp_init_chunk_t *peer_init, struct sctp_chunk *chunk, struct sctp_chunk **err_chunk); -int sctp_process_init(struct sctp_association *, sctp_cid_t cid, +int sctp_process_init(struct sctp_association *, struct sctp_chunk *chunk, const union sctp_addr *peer, sctp_init_chunk_t *init, gfp_t gfp); __u32 sctp_generate_tag(const struct sctp_endpoint *); diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index f87ccb11a520..a7b65e9e44b3 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2242,14 +2242,17 @@ int sctp_verify_init(const struct sctp_association *asoc, * Returns 0 on failure, else success. * FIXME: This is an association method. */ -int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, +int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, const union sctp_addr *peer_addr, sctp_init_chunk_t *peer_init, gfp_t gfp) { union sctp_params param; struct sctp_transport *transport; struct list_head *pos, *temp; + struct sctp_af *af; + union sctp_addr addr; char *cookie; + int src_match = 0; /* We must include the address that the INIT packet came from. * This is the only address that matters for an INIT packet. @@ -2261,18 +2264,31 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, * added as the primary transport. The source address seems to * be a a better choice than any of the embedded addresses. */ - if (peer_addr) { - if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) - goto nomem; - } + if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) + goto nomem; + + if (sctp_cmp_addr_exact(sctp_source(chunk), peer_addr)) + src_match = 1; /* Process the initialization parameters. */ sctp_walk_params(param, peer_init, init_hdr.params) { + if (!src_match && (param.p->type == SCTP_PARAM_IPV4_ADDRESS || + param.p->type == SCTP_PARAM_IPV6_ADDRESS)) { + af = sctp_get_af_specific(param_type2af(param.p->type)); + af->from_addr_param(&addr, param.addr, + chunk->sctp_hdr->source, 0); + if (sctp_cmp_addr_exact(sctp_source(chunk), &addr)) + src_match = 1; + } if (!sctp_process_param(asoc, param, peer_addr, gfp)) goto clean_up; } + /* source address of chunk may not match any valid address */ + if (!src_match) + goto clean_up; + /* AUTH: After processing the parameters, make sure that we * have all the required info to potentially do authentications. */ diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 3b80fe24dabf..d612ca1ca6c0 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -595,8 +595,7 @@ static int sctp_cmd_process_init(sctp_cmd_seq_t *commands, * fail during INIT processing (due to malloc problems), * just return the error and stop processing the stack. */ - if (!sctp_process_init(asoc, chunk->chunk_hdr->type, - sctp_source(chunk), peer_init, gfp)) + if (!sctp_process_init(asoc, chunk, sctp_source(chunk), peer_init, gfp)) error = -ENOMEM; else error = 0; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index ad3b43bb75cc..ab949320468d 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -393,8 +393,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, goto nomem_init; /* The call, sctp_process_init(), can fail on memory allocation. */ - if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, - sctp_source(chunk), + if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), (sctp_init_chunk_t *)chunk->chunk_hdr, GFP_ATOMIC)) goto nomem_init; @@ -725,7 +724,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, */ peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; - if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, + if (!sctp_process_init(new_asoc, chunk, &chunk->subh.cookie_hdr->c.peer_addr, peer_init, GFP_ATOMIC)) goto nomem_init; @@ -1464,8 +1463,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( * Verification Tag and Peers Verification tag into a reserved * place (local tie-tag and per tie-tag) within the state cookie. */ - if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, - sctp_source(chunk), + if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), (sctp_init_chunk_t *)chunk->chunk_hdr, GFP_ATOMIC)) goto nomem; @@ -1694,8 +1692,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, */ peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; - if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, - sctp_source(chunk), peer_init, + if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init, GFP_ATOMIC)) goto nomem; @@ -1780,8 +1777,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep, * side effects--it is safe to run them here. */ peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; - if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, - sctp_source(chunk), peer_init, + if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init, GFP_ATOMIC)) goto nomem; -- cgit v1.2.3-58-ga151 From 92c73af58e9f1b487322ce25a7a67889c9d91343 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 19 Apr 2011 21:31:47 +0000 Subject: sctp: make heartbeat information in sctp_make_heartbeat() Make heartbeat information in sctp_make_heartbeat() instead of make it in sctp_sf_heartbeat() directly for common using. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/sm.h | 4 +--- net/sctp/sm_make_chunk.c | 18 +++++++++++++----- net/sctp/sm_statefuns.c | 11 +---------- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 9352d12f02de..652f09bba504 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -232,9 +232,7 @@ struct sctp_chunk *sctp_make_violation_paramlen(const struct sctp_association *, const struct sctp_chunk *, struct sctp_paramhdr *); struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *, - const struct sctp_transport *, - const void *payload, - const size_t paylen); + const struct sctp_transport *); struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *, const struct sctp_chunk *, const void *payload, diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index a7b65e9e44b3..58eb27fed4b4 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1075,20 +1075,28 @@ nodata: /* Make a HEARTBEAT chunk. */ struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, - const struct sctp_transport *transport, - const void *payload, const size_t paylen) + const struct sctp_transport *transport) { - struct sctp_chunk *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT, - 0, paylen); + struct sctp_chunk *retval; + sctp_sender_hb_info_t hbinfo; + + retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT, 0, sizeof(hbinfo)); if (!retval) goto nodata; + hbinfo.param_hdr.type = SCTP_PARAM_HEARTBEAT_INFO; + hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t)); + hbinfo.daddr = transport->ipaddr; + hbinfo.sent_at = jiffies; + hbinfo.hb_nonce = transport->hb_nonce; + /* Cast away the 'const', as this is just telling the chunk * what transport it belongs to. */ retval->transport = (struct sctp_transport *) transport; - retval->subh.hbs_hdr = sctp_addto_chunk(retval, paylen, payload); + retval->subh.hbs_hdr = sctp_addto_chunk(retval, sizeof(hbinfo), + &hbinfo); nodata: return retval; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index ab949320468d..736847e44e7e 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -941,18 +941,9 @@ static sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep, { struct sctp_transport *transport = (struct sctp_transport *) arg; struct sctp_chunk *reply; - sctp_sender_hb_info_t hbinfo; - size_t paylen = 0; - - hbinfo.param_hdr.type = SCTP_PARAM_HEARTBEAT_INFO; - hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t)); - hbinfo.daddr = transport->ipaddr; - hbinfo.sent_at = jiffies; - hbinfo.hb_nonce = transport->hb_nonce; /* Send a heartbeat to our peer. */ - paylen = sizeof(sctp_sender_hb_info_t); - reply = sctp_make_heartbeat(asoc, transport, &hbinfo, paylen); + reply = sctp_make_heartbeat(asoc, transport); if (!reply) return SCTP_DISPOSITION_NOMEM; -- cgit v1.2.3-58-ga151 From 4c6a6f42131dd750dcfe3c71e63bfc046e5a227e Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 19 Apr 2011 21:32:28 +0000 Subject: sctp: move chunk from retransmit queue to abandoned list If there is still data waiting to retransmit and remain in retransmit queue, while doing the next retransmit, if the chunk is abandoned, we should move it to abandoned list. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/outqueue.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 3e9d8d2bbe71..1c88c8911dc5 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -577,6 +577,13 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, * try to send as much as possible. */ list_for_each_entry_safe(chunk, chunk1, lqueue, transmitted_list) { + /* If the chunk is abandoned, move it to abandoned list. */ + if (sctp_chunk_abandoned(chunk)) { + list_del_init(&chunk->transmitted_list); + sctp_insert_list(&q->abandoned, + &chunk->transmitted_list); + continue; + } /* Make sure that Gap Acked TSNs are not retransmitted. A * simple approach is just to move such TSNs out of the -- cgit v1.2.3-58-ga151 From 358b1361bed42f4e6cbf8956a73aebf193957d4a Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 21 Apr 2011 10:55:07 +0200 Subject: netfilter: ctnetlink: fix timestamp support for new conntracks This patch fixes the missing initialization of the start time if the timestamp support is enabled. libnetfilter_conntrack/utils# conntrack -E & libnetfilter_conntrack/utils# ./conntrack_create tcp 6 109 ESTABLISHED src=1.1.1.1 dst=2.2.2.2 sport=1025 dport=21 packets=0 bytes=0 [UNREPLIED] src=2.2.2.2 dst=1.1.1.1 sport=21 dport=1025 packets=0 bytes=0 mark=0 delta-time=1303296401 use=2 Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 30bf8a167fc8..482e90c61850 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1334,6 +1334,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, struct nf_conn *ct; int err = -EINVAL; struct nf_conntrack_helper *helper; + struct nf_conn_tstamp *tstamp; ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); if (IS_ERR(ct)) @@ -1451,6 +1452,9 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, __set_bit(IPS_EXPECTED_BIT, &ct->status); ct->master = master_ct; } + tstamp = nf_conn_tstamp_find(ct); + if (tstamp) + tstamp->start = ktime_to_ns(ktime_get_real()); add_timer(&ct->timeout); nf_conntrack_hash_insert(ct); -- cgit v1.2.3-58-ga151 From 954d70388307eb1ccb328d9f960657022a316243 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 21 Apr 2011 10:57:21 +0200 Subject: netfilter: fix ebtables compat support commit 255d0dc34068a976 (netfilter: x_table: speedup compat operations) made ebtables not working anymore. 1) xt_compat_calc_jump() is not an exact match lookup 2) compat_table_info() has a typo in xt_compat_init_offsets() call 3) compat_do_replace() misses a xt_compat_init_offsets() call Reported-by: dann frazier Signed-off-by: Eric Dumazet Signed-off-by: Patrick McHardy --- net/bridge/netfilter/ebtables.c | 3 ++- net/netfilter/x_tables.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 893669caa8de..9707079bc40a 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1766,7 +1766,7 @@ static int compat_table_info(const struct ebt_table_info *info, newinfo->entries_size = size; - xt_compat_init_offsets(AF_INET, info->nentries); + xt_compat_init_offsets(NFPROTO_BRIDGE, info->nentries); return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, entries, newinfo); } @@ -2240,6 +2240,7 @@ static int compat_do_replace(struct net *net, void __user *user, xt_compat_lock(NFPROTO_BRIDGE); + xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries); ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); if (ret < 0) goto out_unlock; diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index a9adf4c6b299..8a025a585d2f 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -455,6 +455,7 @@ void xt_compat_flush_offsets(u_int8_t af) vfree(xt[af].compat_tab); xt[af].compat_tab = NULL; xt[af].number = 0; + xt[af].cur = 0; } } EXPORT_SYMBOL_GPL(xt_compat_flush_offsets); @@ -473,8 +474,7 @@ int xt_compat_calc_jump(u_int8_t af, unsigned int offset) else return mid ? tmp[mid - 1].delta : 0; } - WARN_ON_ONCE(1); - return 0; + return left ? tmp[left - 1].delta : 0; } EXPORT_SYMBOL_GPL(xt_compat_calc_jump); -- cgit v1.2.3-58-ga151 From e31b2b228439eee23b8ccc186d3c0e77bd69123b Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 21 Apr 2011 10:58:25 +0200 Subject: netfilter: ebtables: only call xt_compat_add_offset once per rule The optimizations in commit 255d0dc34068a976 (netfilter: x_table: speedup compat operations) assume that xt_compat_add_offset is called once per rule. ebtables however called it for each match/target found in a rule. The match/watcher/target parser already returns the needed delta, so it is sufficient to move the xt_compat_add_offset call to a more reasonable location. While at it, also get rid of the unused COMPAT iterator macros. Signed-off-by: Florian Westphal Signed-off-by: Patrick McHardy --- net/bridge/netfilter/ebtables.c | 61 ++++++----------------------------------- 1 file changed, 9 insertions(+), 52 deletions(-) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 9707079bc40a..1a92b369c820 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1882,7 +1882,7 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, struct xt_match *match; struct xt_target *wt; void *dst = NULL; - int off, pad = 0, ret = 0; + int off, pad = 0; unsigned int size_kern, entry_offset, match_size = mwt->match_size; strlcpy(name, mwt->u.name, sizeof(name)); @@ -1935,13 +1935,6 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, break; } - if (!dst) { - ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset, - off + ebt_compat_entry_padsize()); - if (ret < 0) - return ret; - } - state->buf_kern_offset += match_size + off; state->buf_user_offset += match_size; pad = XT_ALIGN(size_kern) - size_kern; @@ -2016,50 +2009,6 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, return growth; } -#define EBT_COMPAT_WATCHER_ITERATE(e, fn, args...) \ -({ \ - unsigned int __i; \ - int __ret = 0; \ - struct compat_ebt_entry_mwt *__watcher; \ - \ - for (__i = e->watchers_offset; \ - __i < (e)->target_offset; \ - __i += __watcher->watcher_size + \ - sizeof(struct compat_ebt_entry_mwt)) { \ - __watcher = (void *)(e) + __i; \ - __ret = fn(__watcher , ## args); \ - if (__ret != 0) \ - break; \ - } \ - if (__ret == 0) { \ - if (__i != (e)->target_offset) \ - __ret = -EINVAL; \ - } \ - __ret; \ -}) - -#define EBT_COMPAT_MATCH_ITERATE(e, fn, args...) \ -({ \ - unsigned int __i; \ - int __ret = 0; \ - struct compat_ebt_entry_mwt *__match; \ - \ - for (__i = sizeof(struct ebt_entry); \ - __i < (e)->watchers_offset; \ - __i += __match->match_size + \ - sizeof(struct compat_ebt_entry_mwt)) { \ - __match = (void *)(e) + __i; \ - __ret = fn(__match , ## args); \ - if (__ret != 0) \ - break; \ - } \ - if (__ret == 0) { \ - if (__i != (e)->watchers_offset) \ - __ret = -EINVAL; \ - } \ - __ret; \ -}) - /* called for all ebt_entry structures. */ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, unsigned int *total, @@ -2132,6 +2081,14 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, } } + if (state->buf_kern_start == NULL) { + unsigned int offset = buf_start - (char *) base; + + ret = xt_compat_add_offset(NFPROTO_BRIDGE, offset, new_offset); + if (ret < 0) + return ret; + } + startoff = state->buf_user_offset - startoff; BUG_ON(*total < startoff); -- cgit v1.2.3-58-ga151 From 209ba424c2c6e5ff4dd0ff79bb23659aa6048eac Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 17 Apr 2011 17:27:08 +0000 Subject: sctp: implement socket option SCTP_GET_ASSOC_ID_LIST This patch Implement socket option SCTP_GET_ASSOC_ID_LIST. SCTP Socket API Extension: 8.2.6. Get the Current Identifiers of Associations (SCTP_GET_ASSOC_ID_LIST) This option gets the current list of SCTP association identifiers of the SCTP associations handled by a one-to-many style socket. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/user.h | 13 +++++++++++++ net/sctp/socket.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index e73ebdae323d..793617ecbfdf 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h @@ -91,6 +91,7 @@ typedef __s32 sctp_assoc_t; #define SCTP_PEER_AUTH_CHUNKS 26 /* Read only */ #define SCTP_LOCAL_AUTH_CHUNKS 27 /* Read only */ #define SCTP_GET_ASSOC_NUMBER 28 /* Read only */ +#define SCTP_GET_ASSOC_ID_LIST 29 /* Read only */ /* Internal Socket Options. Some of the sctp library functions are * implemented using these socket options. @@ -668,6 +669,18 @@ struct sctp_authchunks { uint8_t gauth_chunks[]; }; +/* + * 8.2.6. Get the Current Identifiers of Associations + * (SCTP_GET_ASSOC_ID_LIST) + * + * This option gets the current list of SCTP association identifiers of + * the SCTP associations handled by a one-to-many style socket. + */ +struct sctp_assoc_ids { + __u32 gaids_number_of_ids; + sctp_assoc_t gaids_assoc_id[]; +}; + /* * 8.3, 8.5 get all peer/local addresses in an association. * This parameter struct is used by SCTP_GET_PEER_ADDRS and diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 431b8905c570..f694ee116746 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -5277,6 +5277,55 @@ static int sctp_getsockopt_assoc_number(struct sock *sk, int len, return 0; } +/* + * 8.2.6. Get the Current Identifiers of Associations + * (SCTP_GET_ASSOC_ID_LIST) + * + * This option gets the current list of SCTP association identifiers of + * the SCTP associations handled by a one-to-many style socket. + */ +static int sctp_getsockopt_assoc_ids(struct sock *sk, int len, + char __user *optval, int __user *optlen) +{ + struct sctp_sock *sp = sctp_sk(sk); + struct sctp_association *asoc; + struct sctp_assoc_ids *ids; + u32 num = 0; + + if (sctp_style(sk, TCP)) + return -EOPNOTSUPP; + + if (len < sizeof(struct sctp_assoc_ids)) + return -EINVAL; + + list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { + num++; + } + + if (len < sizeof(struct sctp_assoc_ids) + sizeof(sctp_assoc_t) * num) + return -EINVAL; + + len = sizeof(struct sctp_assoc_ids) + sizeof(sctp_assoc_t) * num; + + ids = kmalloc(len, GFP_KERNEL); + if (unlikely(!ids)) + return -ENOMEM; + + ids->gaids_number_of_ids = num; + num = 0; + list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { + ids->gaids_assoc_id[num++] = asoc->assoc_id; + } + + if (put_user(len, optlen) || copy_to_user(optval, ids, len)) { + kfree(ids); + return -EFAULT; + } + + kfree(ids); + return 0; +} + SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { @@ -5409,6 +5458,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, case SCTP_GET_ASSOC_NUMBER: retval = sctp_getsockopt_assoc_number(sk, len, optval, optlen); break; + case SCTP_GET_ASSOC_ID_LIST: + retval = sctp_getsockopt_assoc_ids(sk, len, optval, optlen); + break; default: retval = -ENOPROTOOPT; break; -- cgit v1.2.3-58-ga151 From ee916fd0fdb8f43dacaab431de3e1f7225039d72 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 17 Apr 2011 17:28:01 +0000 Subject: sctp: change auth event type name to SCTP_AUTHENTICATION_EVENT This patch change the auth event type name to SCTP_AUTHENTICATION_EVENT, which is based on API extension compliance. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/user.h | 3 ++- net/sctp/ulpevent.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index 793617ecbfdf..4525d8c7f71a 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h @@ -408,7 +408,8 @@ enum sctp_sn_type { SCTP_SHUTDOWN_EVENT, SCTP_PARTIAL_DELIVERY_EVENT, SCTP_ADAPTATION_INDICATION, - SCTP_AUTHENTICATION_INDICATION, + SCTP_AUTHENTICATION_EVENT, +#define SCTP_AUTHENTICATION_INDICATION SCTP_AUTHENTICATION_EVENT }; /* Notification error codes used to fill up the error fields in some diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index dff27d5e22fd..62d4a7bbaaea 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -843,7 +843,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_authkey( ak = (struct sctp_authkey_event *) skb_put(skb, sizeof(struct sctp_authkey_event)); - ak->auth_type = SCTP_AUTHENTICATION_INDICATION; + ak->auth_type = SCTP_AUTHENTICATION_EVENT; ak->auth_flags = 0; ak->auth_length = sizeof(struct sctp_authkey_event); -- cgit v1.2.3-58-ga151 From e1cdd553d482ceb083fac5e544e8702fccefbfd6 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 17 Apr 2011 17:29:03 +0000 Subject: sctp: implement event notification SCTP_SENDER_DRY_EVENT This patch implement event notification SCTP_SENDER_DRY_EVENT. SCTP Socket API Extensions: 6.1.9. SCTP_SENDER_DRY_EVENT When the SCTP stack has no more user data to send or retransmit, this notification is given to the user. Also, at the time when a user app subscribes to this event, if there is no data to be sent or retransmit, the stack will immediately send up this notification. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/sm.h | 1 + include/net/sctp/ulpevent.h | 3 +++ include/net/sctp/user.h | 17 +++++++++++++++++ net/sctp/sm_statefuns.c | 24 ++++++++++++++++++++++++ net/sctp/sm_statetable.c | 2 +- net/sctp/ulpevent.c | 28 ++++++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 1 deletion(-) diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 652f09bba504..9148632b8204 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -165,6 +165,7 @@ sctp_state_fn_t sctp_sf_do_prm_requestheartbeat; sctp_state_fn_t sctp_sf_do_prm_asconf; /* Prototypes for other event state functions. */ +sctp_state_fn_t sctp_sf_do_no_pending_tsn; sctp_state_fn_t sctp_sf_do_9_2_start_shutdown; sctp_state_fn_t sctp_sf_do_9_2_shutdown_ack; sctp_state_fn_t sctp_sf_ignore_other; diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index 7ea12e8e6676..99b027b2adce 100644 --- a/include/net/sctp/ulpevent.h +++ b/include/net/sctp/ulpevent.h @@ -132,6 +132,9 @@ struct sctp_ulpevent *sctp_ulpevent_make_authkey( const struct sctp_association *asoc, __u16 key_id, __u32 indication, gfp_t gfp); +struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event( + const struct sctp_association *asoc, gfp_t gfp); + void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, struct msghdr *); __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event); diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index 4525d8c7f71a..32fd51274037 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h @@ -354,6 +354,20 @@ struct sctp_authkey_event { enum { SCTP_AUTH_NEWKEY = 0, }; +/* + * 6.1.9. SCTP_SENDER_DRY_EVENT + * + * When the SCTP stack has no more user data to send or retransmit, this + * notification is given to the user. Also, at the time when a user app + * subscribes to this event, if there is no data to be sent or + * retransmit, the stack will immediately send up this notification. + */ +struct sctp_sender_dry_event { + __u16 sender_dry_type; + __u16 sender_dry_flags; + __u32 sender_dry_length; + sctp_assoc_t sender_dry_assoc_id; +}; /* * Described in Section 7.3 @@ -369,6 +383,7 @@ struct sctp_event_subscribe { __u8 sctp_partial_delivery_event; __u8 sctp_adaptation_layer_event; __u8 sctp_authentication_event; + __u8 sctp_sender_dry_event; }; /* @@ -392,6 +407,7 @@ union sctp_notification { struct sctp_adaptation_event sn_adaptation_event; struct sctp_pdapi_event sn_pdapi_event; struct sctp_authkey_event sn_authkey_event; + struct sctp_sender_dry_event sn_sender_dry_event; }; /* Section 5.3.1 @@ -410,6 +426,7 @@ enum sctp_sn_type { SCTP_ADAPTATION_INDICATION, SCTP_AUTHENTICATION_EVENT, #define SCTP_AUTHENTICATION_INDICATION SCTP_AUTHENTICATION_EVENT + SCTP_SENDER_DRY_EVENT, }; /* Notification error codes used to fill up the error fields in some diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 736847e44e7e..7f4a4f8368ee 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -5076,6 +5076,30 @@ sctp_disposition_t sctp_sf_ignore_primitive( * These are the state functions for the OTHER events. ***************************************************************************/ +/* + * When the SCTP stack has no more user data to send or retransmit, this + * notification is given to the user. Also, at the time when a user app + * subscribes to this event, if there is no data to be sent or + * retransmit, the stack will immediately send up this notification. + */ +sctp_disposition_t sctp_sf_do_no_pending_tsn( + const struct sctp_endpoint *ep, + const struct sctp_association *asoc, + const sctp_subtype_t type, + void *arg, + sctp_cmd_seq_t *commands) +{ + struct sctp_ulpevent *event; + + event = sctp_ulpevent_make_sender_dry_event(asoc, GFP_ATOMIC); + if (!event) + return SCTP_DISPOSITION_NOMEM; + + sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(event)); + + return SCTP_DISPOSITION_CONSUME; +} + /* * Start the shutdown negotiation. * diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 881196b60a92..0338dc6fdc9d 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -668,7 +668,7 @@ static const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPE /* SCTP_STATE_COOKIE_ECHOED */ \ TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ /* SCTP_STATE_ESTABLISHED */ \ - TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ + TYPE_SCTP_FUNC(sctp_sf_do_no_pending_tsn), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ TYPE_SCTP_FUNC(sctp_sf_do_9_2_start_shutdown), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 62d4a7bbaaea..c962c6062aab 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -862,6 +862,34 @@ fail: return NULL; } +/* + * Socket Extensions for SCTP + * 6.3.10. SCTP_SENDER_DRY_EVENT + */ +struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event( + const struct sctp_association *asoc, gfp_t gfp) +{ + struct sctp_ulpevent *event; + struct sctp_sender_dry_event *sdry; + struct sk_buff *skb; + + event = sctp_ulpevent_new(sizeof(struct sctp_sender_dry_event), + MSG_NOTIFICATION, gfp); + if (!event) + return NULL; + + skb = sctp_event2skb(event); + sdry = (struct sctp_sender_dry_event *) + skb_put(skb, sizeof(struct sctp_sender_dry_event)); + + sdry->sender_dry_type = SCTP_SENDER_DRY_EVENT; + sdry->sender_dry_flags = 0; + sdry->sender_dry_length = sizeof(struct sctp_sender_dry_event); + sctp_ulpevent_set_owner(event, asoc); + sdry->sender_dry_assoc_id = sctp_assoc2id(asoc); + + return event; +} /* Return the notification type, assuming this is a notification * event. -- cgit v1.2.3-58-ga151 From e138f96bf5142c400b6b00f4cf69031bccc48f32 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 21 Apr 2011 15:19:02 -0700 Subject: mv643xx_eth: Fix build regression. From Stephen Rothwell: -------------------- After merging the final tree, today's linux-next build (powerpc chrp32_defconfig) failed like this: drivers/net/mv643xx_eth.c: In function 'port_start': drivers/net/mv643xx_eth.c:2250: error: 'dev' undeclared (first use in this function) Caused by commit aad59c431b77 ("net: mv643xx: convert to hw_features"). -------------------- Reported-by: Stephen Rothwell Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 29605a34d4c1..57c2ac04f9ff 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2247,7 +2247,7 @@ static void port_start(struct mv643xx_eth_private *mp) * frames to RX queue #0, and include the pseudo-header when * calculating receive checksums. */ - mv643xx_eth_set_features(dev, dev->features); + mv643xx_eth_set_features(mp->dev, mp->dev->features); /* * Treat BPDUs as normal multicasts, and disable partition mode. -- cgit v1.2.3-58-ga151 From 4d95847381228639844c7197deb8b2211274ef22 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Apr 2011 07:57:35 +0000 Subject: tg3: Workaround rx_discards stat bug The 5717, 5718, 5719 A0, and 5720 A0 has a bug where the rx_discards statistic counter will increment when dropping unwanted multicast frames. This patch works around the problem by attempting to recreate the data using other means. The resulting value will not be accurate, but it can still serve as a problem indicator. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 27 ++++++++++++++++++++++++++- drivers/net/tg3.h | 2 ++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 9915734ac3e9..58787ea8b7a4 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -339,6 +339,7 @@ static const struct { { "dma_write_prioq_full" }, { "rxbds_empty" }, { "rx_discards" }, + { "mbuf_lwm_thresh_hit" }, { "rx_errors" }, { "rx_threshold_hit" }, @@ -8207,6 +8208,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) val = BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) val |= BUFMGR_MODE_NO_TX_UNDERRUN; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + tp->pci_chip_rev_id == CHIPREV_ID_5719_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5720_A0) + val |= BUFMGR_MODE_MBLOW_ATTN_ENAB; tw32(BUFMGR_MODE, val); for (i = 0; i < 2000; i++) { if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE) @@ -8870,7 +8875,19 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp) TG3_STAT_ADD32(&sp->rx_undersize_packets, MAC_RX_STATS_UNDERSIZE); TG3_STAT_ADD32(&sp->rxbds_empty, RCVLPC_NO_RCV_BD_CNT); - TG3_STAT_ADD32(&sp->rx_discards, RCVLPC_IN_DISCARDS_CNT); + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) { + TG3_STAT_ADD32(&sp->rx_discards, RCVLPC_IN_DISCARDS_CNT); + } else { + u32 val = tr32(HOSTCC_FLOW_ATTN); + val = (val & HOSTCC_FLOW_ATTN_MBUF_LWM) ? 1 : 0; + if (val) { + tw32(HOSTCC_FLOW_ATTN, HOSTCC_FLOW_ATTN_MBUF_LWM); + sp->rx_discards.low += val; + if (sp->rx_discards.low < val) + sp->rx_discards.high += 1; + } + sp->mbuf_lwm_thresh_hit = sp->rx_discards; + } TG3_STAT_ADD32(&sp->rx_errors, RCVLPC_IN_ERRORS_CNT); } @@ -13973,6 +13990,14 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX) tp->coalesce_mode |= HOSTCC_MODE_32BYTE; + /* Set these bits to enable statistics workaround. */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + tp->pci_chip_rev_id == CHIPREV_ID_5719_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5720_A0) { + tp->coalesce_mode |= HOSTCC_MODE_ATTN; + tp->grc_mode |= GRC_MODE_IRQ_ON_FLOW_ATTN; + } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) tp->tg3_flags3 |= TG3_FLG3_USE_PHYLIB; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 224c3e0ec695..db50bfe046e4 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -147,6 +147,7 @@ #define CHIPREV_ID_5717_A0 0x05717000 #define CHIPREV_ID_57765_A0 0x57785000 #define CHIPREV_ID_5719_A0 0x05719000 +#define CHIPREV_ID_5720_A0 0x05720000 #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define ASIC_REV_5700 0x07 #define ASIC_REV_5701 0x00 @@ -2602,6 +2603,7 @@ struct tg3_hw_stats { tg3_stat64_t dma_write_prioq_full; tg3_stat64_t rxbds_empty; tg3_stat64_t rx_discards; + tg3_stat64_t mbuf_lwm_thresh_hit; tg3_stat64_t rx_errors; tg3_stat64_t rx_threshold_hit; -- cgit v1.2.3-58-ga151 From eb07a9408e05f67caa671bdf2a509a4d2bd05abf Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Apr 2011 07:57:36 +0000 Subject: tg3: Adjust rx prod ring bd replenish thresholds The oldest tg3 devices had large rx producer ring BD caches. Back then, it made sense to make the BD cache replenish threshold only a function of the number of rx buffers posted by the driver. Since then, the BD cache sizes have shrunk to 25% of their original size and, in some cases, the ring sizes have quadrupled in size. Under such conditions, static BD cache replenish thresholds no longer match the hardware constraints. This patch attempts to factor in the BD cache size into the bd cache replenish strategy, taking the existing hardware bugs into account. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 67 ++++++++++++++++++++++++++++++++++++++----------------- drivers/net/tg3.h | 9 ++++++-- 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 58787ea8b7a4..4aecb0a82e56 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7952,6 +7952,48 @@ static void tg3_rings_reset(struct tg3 *tp) } } +static void tg3_setup_rxbd_thresholds(struct tg3 *tp) +{ + u32 val, bdcache_maxcnt, host_rep_thresh, nic_rep_thresh; + + if (!(tp->tg3_flags2 & TG3_FLG2_5750_PLUS) || + (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) + bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5700; + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5755; + else + bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5906; + + nic_rep_thresh = min(bdcache_maxcnt / 2, tp->rx_std_max_post); + host_rep_thresh = max_t(u32, tp->rx_pending / 8, 1); + + val = min(nic_rep_thresh, host_rep_thresh); + tw32(RCVBDI_STD_THRESH, val); + + if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) + tw32(STD_REPLENISH_LWM, bdcache_maxcnt); + + if (!(tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) || + (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) + return; + + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + bdcache_maxcnt = TG3_SRAM_RX_JMB_BDCACHE_SIZE_5700; + else + bdcache_maxcnt = TG3_SRAM_RX_JMB_BDCACHE_SIZE_5717; + + host_rep_thresh = max_t(u32, tp->rx_jumbo_pending / 8, 1); + + val = min(bdcache_maxcnt / 2, host_rep_thresh); + tw32(RCVBDI_JUMBO_THRESH, val); + + if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) + tw32(JMB_REPLENISH_LWM, bdcache_maxcnt); +} + /* tp->lock is held. */ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) { @@ -8223,21 +8265,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) return -ENODEV; } - /* Setup replenish threshold. */ - val = tp->rx_pending / 8; - if (val == 0) - val = 1; - else if (val > tp->rx_std_max_post) - val = tp->rx_std_max_post; - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { - if (tp->pci_chip_rev_id == CHIPREV_ID_5906_A1) - tw32(ISO_PKT_TX, (tr32(ISO_PKT_TX) & ~0x3) | 0x2); + if (tp->pci_chip_rev_id == CHIPREV_ID_5906_A1) + tw32(ISO_PKT_TX, (tr32(ISO_PKT_TX) & ~0x3) | 0x2); - if (val > (TG3_RX_INTERNAL_RING_SZ_5906 / 2)) - val = TG3_RX_INTERNAL_RING_SZ_5906 / 2; - } - - tw32(RCVBDI_STD_THRESH, val); + tg3_setup_rxbd_thresholds(tp); /* Initialize TG3_BDINFO's at: * RCVDBDI_STD_BD: standard eth size rx ring @@ -8275,8 +8306,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))) { - /* Setup replenish threshold. */ - tw32(RCVBDI_JUMBO_THRESH, tp->rx_jumbo_pending / 8); if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) { tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, @@ -8317,11 +8346,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->rx_jumbo_pending : 0; tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, tpr->rx_jmb_prod_idx); - if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) { - tw32(STD_REPLENISH_LWM, 32); - tw32(JMB_REPLENISH_LWM, 16); - } - tg3_rings_reset(tp); /* Initialize MAC address and backoff seed. */ @@ -13599,6 +13623,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) || (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)) tp->tg3_flags2 |= TG3_FLG2_5705_PLUS; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index db50bfe046e4..dd331f8d3f7a 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -23,8 +23,6 @@ #define TG3_BDINFO_NIC_ADDR 0xcUL /* 32-bit */ #define TG3_BDINFO_SIZE 0x10UL -#define TG3_RX_INTERNAL_RING_SZ_5906 32 - #define TG3_RX_STD_MAX_SIZE_5700 512 #define TG3_RX_STD_MAX_SIZE_5717 2048 #define TG3_RX_JMB_MAX_SIZE_5700 256 @@ -2136,6 +2134,13 @@ #define NIC_SRAM_MBUF_POOL_BASE5705 0x00010000 #define NIC_SRAM_MBUF_POOL_SIZE5705 0x0000e000 +#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5700 128 +#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5755 64 +#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5906 32 + +#define TG3_SRAM_RX_JMB_BDCACHE_SIZE_5700 64 +#define TG3_SRAM_RX_JMB_BDCACHE_SIZE_5717 16 + /* Currently this is fixed. */ #define TG3_PHY_MII_ADDR 0x01 -- cgit v1.2.3-58-ga151 From 4a85f09831329bc5a5e4b9bca3f3ecbffb78f858 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Apr 2011 07:57:37 +0000 Subject: tg3: Nullify RSS for loopback test The loopback test assumes all traffic goes to the first rx queue. There is a 1 in 4 chance this won't be true if RSS is enabled though. This patch reprograms the RSS indirection table to route all rx packets to the first queue. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 4aecb0a82e56..1f233c49b4f0 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -11269,6 +11269,15 @@ static int tg3_test_loopback(struct tg3 *tp) goto done; } + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) { + int i; + + /* Reroute all rx packets to the 1st queue */ + for (i = MAC_RSS_INDIR_TBL_0; + i < MAC_RSS_INDIR_TBL_0 + TG3_RSS_INDIR_TBL_SIZE; i += 4) + tw32(i, 0x0); + } + /* Turn off gphy autopowerdown. */ if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD) tg3_phy_toggle_apd(tp, false); -- cgit v1.2.3-58-ga151 From 34eea5ac214353ccd93ef7dd8dbd10aed87f5f46 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Apr 2011 07:57:38 +0000 Subject: tg3: Only allow phy ioctls while netif_running When tg3 was new, phy accesses through ioctl were allowable at any time. Then, the driver started shutting down the phy when the device was closed. Phy accesses would be allowed when the driver first attached to the device, but then would be forbidden after the device had been up'd and down'd. After that, management firmware made it illegal to access the phy unless the driver "owned" the device. Now that most firmware is being moved over to the APE, it is less clear when phy accesses are safe. While it is possible to attempt to identify these conditions and code the driver to navigate through the pitfalls, it could be perplexing to the admin why phy accesses work in some cases and not others. This patch brings some uniformity to the problem by only allowing phy accesses while the driver has control of the device. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 1f233c49b4f0..e134e484aee3 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -11444,9 +11444,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) break; /* We have no PHY */ - if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) || - ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && - !netif_running(dev))) + if (!netif_running(dev)) return -EAGAIN; spin_lock_bh(&tp->lock); @@ -11462,9 +11460,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) break; /* We have no PHY */ - if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) || - ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && - !netif_running(dev))) + if (!netif_running(dev)) return -EAGAIN; spin_lock_bh(&tp->lock); -- cgit v1.2.3-58-ga151 From b0988c15c12c40b9680730f55a8351f30ec7a564 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Apr 2011 07:57:39 +0000 Subject: tg3: Move phy accessor functions higher Phy accessor functions should live closer to where the base phy read / write routines are. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 136 +++++++++++++++++++++++++++--------------------------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e134e484aee3..ea41d76a70d3 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -881,6 +881,74 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) return ret; } +static int tg3_phy_cl45_write(struct tg3 *tp, u32 devad, u32 addr, u32 val) +{ + int err; + + err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad); + if (err) + goto done; + + err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr); + if (err) + goto done; + + err = tg3_writephy(tp, MII_TG3_MMD_CTRL, + MII_TG3_MMD_CTRL_DATA_NOINC | devad); + if (err) + goto done; + + err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, val); + +done: + return err; +} + +static int tg3_phy_cl45_read(struct tg3 *tp, u32 devad, u32 addr, u32 *val) +{ + int err; + + err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad); + if (err) + goto done; + + err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr); + if (err) + goto done; + + err = tg3_writephy(tp, MII_TG3_MMD_CTRL, + MII_TG3_MMD_CTRL_DATA_NOINC | devad); + if (err) + goto done; + + err = tg3_readphy(tp, MII_TG3_MMD_ADDRESS, val); + +done: + return err; +} + +static int tg3_phydsp_read(struct tg3 *tp, u32 reg, u32 *val) +{ + int err; + + err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg); + if (!err) + err = tg3_readphy(tp, MII_TG3_DSP_RW_PORT, val); + + return err; +} + +static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) +{ + int err; + + err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg); + if (!err) + err = tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val); + + return err; +} + static int tg3_bmcr_reset(struct tg3 *tp) { u32 phy_control; @@ -1154,52 +1222,6 @@ static void tg3_mdio_fini(struct tg3 *tp) } } -static int tg3_phy_cl45_write(struct tg3 *tp, u32 devad, u32 addr, u32 val) -{ - int err; - - err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad); - if (err) - goto done; - - err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr); - if (err) - goto done; - - err = tg3_writephy(tp, MII_TG3_MMD_CTRL, - MII_TG3_MMD_CTRL_DATA_NOINC | devad); - if (err) - goto done; - - err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, val); - -done: - return err; -} - -static int tg3_phy_cl45_read(struct tg3 *tp, u32 devad, u32 addr, u32 *val) -{ - int err; - - err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad); - if (err) - goto done; - - err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr); - if (err) - goto done; - - err = tg3_writephy(tp, MII_TG3_MMD_CTRL, - MII_TG3_MMD_CTRL_DATA_NOINC | devad); - if (err) - goto done; - - err = tg3_readphy(tp, MII_TG3_MMD_ADDRESS, val); - -done: - return err; -} - /* tp->lock is held. */ static inline void tg3_generate_fw_event(struct tg3 *tp) { @@ -1576,28 +1598,6 @@ static void tg3_phy_fini(struct tg3 *tp) } } -static int tg3_phydsp_read(struct tg3 *tp, u32 reg, u32 *val) -{ - int err; - - err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg); - if (!err) - err = tg3_readphy(tp, MII_TG3_DSP_RW_PORT, val); - - return err; -} - -static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) -{ - int err; - - err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg); - if (!err) - err = tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val); - - return err; -} - static void tg3_phy_fet_toggle_apd(struct tg3 *tp, bool enable) { u32 phytest; -- cgit v1.2.3-58-ga151 From 15ee95c36d355a9f47746eaa4ae8cc0ecafec550 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Apr 2011 07:57:40 +0000 Subject: tg3: Add read accessor for AUX CTRL phy reg This patch adds a read accessor for the aux ctrl register. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 39 ++++++++++++++++++++++++++++----------- drivers/net/tg3.h | 17 ++++++++++------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ea41d76a70d3..7be10cfb0a5f 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -949,6 +949,19 @@ static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) return err; } +static int tg3_phy_auxctl_read(struct tg3 *tp, int reg, u32 *val) +{ + int err; + + err = tg3_writephy(tp, MII_TG3_AUX_CTRL, + (reg << MII_TG3_AUXCTL_MISC_RDSEL_SHIFT) | + MII_TG3_AUXCTL_SHDWSEL_MISC); + if (!err) + err = tg3_readphy(tp, MII_TG3_AUX_CTRL, val); + + return err; +} + static int tg3_bmcr_reset(struct tg3 *tp) { u32 phy_control; @@ -1679,10 +1692,11 @@ static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable) tg3_writephy(tp, MII_TG3_FET_TEST, ephy); } } else { - phy = MII_TG3_AUXCTL_MISC_RDSEL_MISC | - MII_TG3_AUXCTL_SHDWSEL_MISC; - if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, phy) && - !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy)) { + int ret; + + ret = tg3_phy_auxctl_read(tp, + MII_TG3_AUXCTL_SHDWSEL_MISC, &phy); + if (!ret) { if (enable) phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX; else @@ -1695,13 +1709,14 @@ static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable) static void tg3_phy_set_wirespeed(struct tg3 *tp) { + int ret; u32 val; if (tp->phy_flags & TG3_PHYFLG_NO_ETH_WIRE_SPEED) return; - if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007) && - !tg3_readphy(tp, MII_TG3_AUX_CTRL, &val)) + ret = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_MISC, &val); + if (!ret) tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4))); } @@ -2092,8 +2107,9 @@ out: tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20); } else if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) { /* Set bit 14 with read-modify-write to preserve other bits */ - if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007) && - !tg3_readphy(tp, MII_TG3_AUX_CTRL, &val)) + err = tg3_phy_auxctl_read(tp, + MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val); + if (!err) tg3_writephy(tp, MII_TG3_AUX_CTRL, val | 0x4000); } @@ -3263,9 +3279,10 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) current_duplex = DUPLEX_INVALID; if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) { - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4007); - tg3_readphy(tp, MII_TG3_AUX_CTRL, &val); - if (!(val & (1 << 10))) { + err = tg3_phy_auxctl_read(tp, + MII_TG3_AUXCTL_SHDWSEL_MISCTEST, + &val); + if (!err && !(val & (1 << 10))) { val |= (1 << 10); tg3_writephy(tp, MII_TG3_AUX_CTRL, val); goto relink; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index dd331f8d3f7a..b9382f18b631 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2194,19 +2194,22 @@ #define MII_TG3_AUX_CTRL 0x18 /* auxiliary control register */ +#define MII_TG3_AUXCTL_SHDWSEL_AUXCTL 0x0000 +#define MII_TG3_AUXCTL_ACTL_TX_6DB 0x0400 +#define MII_TG3_AUXCTL_ACTL_SMDSP_ENA 0x0800 + +#define MII_TG3_AUXCTL_SHDWSEL_PWRCTL 0x0002 #define MII_TG3_AUXCTL_PCTL_100TX_LPWR 0x0010 #define MII_TG3_AUXCTL_PCTL_SPR_ISOLATE 0x0020 #define MII_TG3_AUXCTL_PCTL_VREG_11V 0x0180 -#define MII_TG3_AUXCTL_SHDWSEL_PWRCTL 0x0002 -#define MII_TG3_AUXCTL_MISC_WREN 0x8000 -#define MII_TG3_AUXCTL_MISC_FORCE_AMDIX 0x0200 -#define MII_TG3_AUXCTL_MISC_RDSEL_MISC 0x7000 +#define MII_TG3_AUXCTL_SHDWSEL_MISCTEST 0x0004 + #define MII_TG3_AUXCTL_SHDWSEL_MISC 0x0007 +#define MII_TG3_AUXCTL_MISC_FORCE_AMDIX 0x0200 +#define MII_TG3_AUXCTL_MISC_RDSEL_SHIFT 12 +#define MII_TG3_AUXCTL_MISC_WREN 0x8000 -#define MII_TG3_AUXCTL_ACTL_SMDSP_ENA 0x0800 -#define MII_TG3_AUXCTL_ACTL_TX_6DB 0x0400 -#define MII_TG3_AUXCTL_SHDWSEL_AUXCTL 0x0000 #define MII_TG3_AUX_STAT 0x19 /* auxiliary status register */ #define MII_TG3_AUX_STAT_LPASS 0x0004 -- cgit v1.2.3-58-ga151 From b4bd292933537e19107c3e151b27a15fefa5f8d0 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Apr 2011 07:57:41 +0000 Subject: tg3: Add write accessor for AUX CTRL phy reg This patch adds a write accessor for the aux ctrl phy register. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 48 +++++++++++++++++++++++++++++++----------------- drivers/net/tg3.h | 4 ++++ 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7be10cfb0a5f..69cd7cfa276b 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -962,6 +962,14 @@ static int tg3_phy_auxctl_read(struct tg3 *tp, int reg, u32 *val) return err; } +static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set) +{ + if (reg == MII_TG3_AUXCTL_SHDWSEL_MISC) + set |= MII_TG3_AUXCTL_MISC_WREN; + + return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg); +} + static int tg3_bmcr_reset(struct tg3 *tp) { u32 phy_control; @@ -1701,8 +1709,8 @@ static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable) phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX; else phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX; - phy |= MII_TG3_AUXCTL_MISC_WREN; - tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); + tg3_phy_auxctl_write(tp, + MII_TG3_AUXCTL_SHDWSEL_MISC, phy); } } } @@ -1717,8 +1725,8 @@ static void tg3_phy_set_wirespeed(struct tg3 *tp) ret = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_MISC, &val); if (!ret) - tg3_writephy(tp, MII_TG3_AUX_CTRL, - (val | (1 << 15) | (1 << 4))); + tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_MISC, + val | MII_TG3_AUXCTL_MISC_WIRESPD_EN); } static void tg3_phy_apply_otp(struct tg3 *tp) @@ -2104,13 +2112,14 @@ out: /* support jumbo frames */ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) { /* Cannot do read-modify-write on 5401 */ - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20); + tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20); } else if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) { /* Set bit 14 with read-modify-write to preserve other bits */ err = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val); if (!err) - tg3_writephy(tp, MII_TG3_AUX_CTRL, val | 0x4000); + tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, + val | MII_TG3_AUXCTL_ACTL_EXTPKTLEN); } /* Set phy register 0x10 bit 0 to high fifo elasticity to support @@ -2319,11 +2328,10 @@ static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power) tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_FORCE_LED_OFF); - tg3_writephy(tp, MII_TG3_AUX_CTRL, - MII_TG3_AUXCTL_SHDWSEL_PWRCTL | - MII_TG3_AUXCTL_PCTL_100TX_LPWR | - MII_TG3_AUXCTL_PCTL_SPR_ISOLATE | - MII_TG3_AUXCTL_PCTL_VREG_11V); + val = MII_TG3_AUXCTL_PCTL_100TX_LPWR | + MII_TG3_AUXCTL_PCTL_SPR_ISOLATE | + MII_TG3_AUXCTL_PCTL_VREG_11V; + tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_PWRCTL, val); } /* The PHY should not be powered down on some chips because @@ -2717,8 +2725,13 @@ static int tg3_power_down_prepare(struct tg3 *tp) u32 mac_mode; if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) { - if (do_low_power) { - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); + if (do_low_power && + !(tp->phy_flags & TG3_PHYFLG_IS_FET)) { + tg3_phy_auxctl_write(tp, + MII_TG3_AUXCTL_SHDWSEL_PWRCTL, + MII_TG3_AUXCTL_PCTL_WOL_EN | + MII_TG3_AUXCTL_PCTL_100TX_LPWR | + MII_TG3_AUXCTL_PCTL_CL_AB_TXDAC); udelay(40); } @@ -3092,7 +3105,7 @@ static int tg3_init_5401phy_dsp(struct tg3 *tp) /* Turn off tap power management. */ /* Set Extended packet length bit */ - err = tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20); + err = tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20); err |= tg3_phydsp_write(tp, 0x0012, 0x1804); err |= tg3_phydsp_write(tp, 0x0013, 0x1204); @@ -3198,7 +3211,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) udelay(80); } - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02); + tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_PWRCTL, 0); /* Some third-party PHYs need to be reset on link going * down. @@ -3283,8 +3296,9 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) MII_TG3_AUXCTL_SHDWSEL_MISCTEST, &val); if (!err && !(val & (1 << 10))) { - val |= (1 << 10); - tg3_writephy(tp, MII_TG3_AUX_CTRL, val); + tg3_phy_auxctl_write(tp, + MII_TG3_AUXCTL_SHDWSEL_MISCTEST, + val | (1 << 10)); goto relink; } } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index b9382f18b631..eaa76694efb5 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2197,15 +2197,19 @@ #define MII_TG3_AUXCTL_SHDWSEL_AUXCTL 0x0000 #define MII_TG3_AUXCTL_ACTL_TX_6DB 0x0400 #define MII_TG3_AUXCTL_ACTL_SMDSP_ENA 0x0800 +#define MII_TG3_AUXCTL_ACTL_EXTPKTLEN 0x4000 #define MII_TG3_AUXCTL_SHDWSEL_PWRCTL 0x0002 +#define MII_TG3_AUXCTL_PCTL_WOL_EN 0x0008 #define MII_TG3_AUXCTL_PCTL_100TX_LPWR 0x0010 #define MII_TG3_AUXCTL_PCTL_SPR_ISOLATE 0x0020 +#define MII_TG3_AUXCTL_PCTL_CL_AB_TXDAC 0x0040 #define MII_TG3_AUXCTL_PCTL_VREG_11V 0x0180 #define MII_TG3_AUXCTL_SHDWSEL_MISCTEST 0x0004 #define MII_TG3_AUXCTL_SHDWSEL_MISC 0x0007 +#define MII_TG3_AUXCTL_MISC_WIRESPD_EN 0x0010 #define MII_TG3_AUXCTL_MISC_FORCE_AMDIX 0x0200 #define MII_TG3_AUXCTL_MISC_RDSEL_SHIFT 12 #define MII_TG3_AUXCTL_MISC_WREN 0x8000 -- cgit v1.2.3-58-ga151 From 1d36ba450bf8c88eda57deb028370880d09a14bc Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Apr 2011 07:57:42 +0000 Subject: tg3: Add macro for SMDSP toggling A common AUX CTRL operation in the driver is to enable and disable the SMDSP. This patch consolidates the code so that the details of the operation are in one place. This patch also adds code to make sure the SMDSP is enabled before executing code that relies on it. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 102 ++++++++++++++++++++++++------------------------------ 1 file changed, 46 insertions(+), 56 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 69cd7cfa276b..9ed6bfb8e697 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -970,6 +970,15 @@ static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set) return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg); } +#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \ + tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ + MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \ + MII_TG3_AUXCTL_ACTL_TX_6DB) + +#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \ + tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ + MII_TG3_AUXCTL_ACTL_TX_6DB); + static int tg3_bmcr_reset(struct tg3 *tp) { u32 phy_control; @@ -1738,11 +1747,8 @@ static void tg3_phy_apply_otp(struct tg3 *tp) otp = tp->phy_otp; - /* Enable SM_DSP clock and tx 6dB coding. */ - phy = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | - MII_TG3_AUXCTL_ACTL_SMDSP_ENA | - MII_TG3_AUXCTL_ACTL_TX_6DB; - tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); + if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) + return; phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); phy |= MII_TG3_DSP_TAP1_AGCTGT_DFLT; @@ -1766,10 +1772,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT); tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); - /* Turn off SM_DSP clock. */ - phy = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | - MII_TG3_AUXCTL_ACTL_TX_6DB; - tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); + TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); } static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) @@ -1804,18 +1807,11 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) case ASIC_REV_5717: case ASIC_REV_5719: case ASIC_REV_57765: - /* Enable SM_DSP clock and tx 6dB coding. */ - val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | - MII_TG3_AUXCTL_ACTL_SMDSP_ENA | - MII_TG3_AUXCTL_ACTL_TX_6DB; - tg3_writephy(tp, MII_TG3_AUX_CTRL, val); - - tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000); - - /* Turn off SM_DSP clock. */ - val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | - MII_TG3_AUXCTL_ACTL_TX_6DB; - tg3_writephy(tp, MII_TG3_AUX_CTRL, val); + if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, + 0x0000); + TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + } } /* Fallthrough */ case TG3_CL45_D7_EEERES_STAT_LP_100TX: @@ -1967,8 +1963,9 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) (MII_TG3_CTRL_AS_MASTER | MII_TG3_CTRL_ENABLE_AS_MASTER)); - /* Enable SM_DSP_CLOCK and 6dB. */ - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); + err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + if (err) + return err; /* Block the PHY control access. */ tg3_phydsp_write(tp, 0x8005, 0x0800); @@ -1987,13 +1984,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { - /* Set Extended packet length bit for jumbo frames */ - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4400); - } else { - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); - } + TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); tg3_writephy(tp, MII_TG3_CTRL, phy9_orig); @@ -2081,33 +2072,39 @@ static int tg3_phy_reset(struct tg3 *tp) tg3_phy_toggle_apd(tp, false); out: - if (tp->phy_flags & TG3_PHYFLG_ADC_BUG) { - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); + if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) && + !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { tg3_phydsp_write(tp, 0x201f, 0x2aaa); tg3_phydsp_write(tp, 0x000a, 0x0323); - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); + TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); } + if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) { tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68); tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68); } + if (tp->phy_flags & TG3_PHYFLG_BER_BUG) { - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); - tg3_phydsp_write(tp, 0x000a, 0x310b); - tg3_phydsp_write(tp, 0x201f, 0x9506); - tg3_phydsp_write(tp, 0x401f, 0x14e2); - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); + if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + tg3_phydsp_write(tp, 0x000a, 0x310b); + tg3_phydsp_write(tp, 0x201f, 0x9506); + tg3_phydsp_write(tp, 0x401f, 0x14e2); + TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + } } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) { - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); - if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) { - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); - tg3_writephy(tp, MII_TG3_TEST1, - MII_TG3_TEST1_TRIM_EN | 0x4); - } else - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); + if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); + if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) { + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); + tg3_writephy(tp, MII_TG3_TEST1, + MII_TG3_TEST1_TRIM_EN | 0x4); + } else + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); + + TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + } } + /* Set Extended packet length bit (bit 14) on all chips that */ /* support jumbo frames */ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) { @@ -3011,11 +3008,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp) tw32(TG3_CPMU_EEE_MODE, tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); - /* Enable SM_DSP clock and tx 6dB coding. */ - val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | - MII_TG3_AUXCTL_ACTL_SMDSP_ENA | - MII_TG3_AUXCTL_ACTL_TX_6DB; - tg3_writephy(tp, MII_TG3_AUX_CTRL, val); + TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); switch (GET_ASIC_REV(tp->pci_chip_rev_id)) { case ASIC_REV_5717: @@ -3044,10 +3037,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp) } tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val); - /* Turn off SM_DSP clock. */ - val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | - MII_TG3_AUXCTL_ACTL_TX_6DB; - tg3_writephy(tp, MII_TG3_AUX_CTRL, val); + TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); } if (tp->link_config.autoneg == AUTONEG_DISABLE && -- cgit v1.2.3-58-ga151 From 470078312515f12e7cd916f1bd002acad313b9c8 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Apr 2011 07:57:43 +0000 Subject: tg3: Add additional EEE messaging This patch adds link messages and an item to the sign-on banner to make EEE status more visible. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 9ed6bfb8e697..693f36e94dab 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1360,6 +1360,11 @@ static void tg3_link_report(struct tg3 *tp) "on" : "off", (tp->link_config.active_flowctrl & FLOW_CTRL_RX) ? "on" : "off"); + + if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) + netdev_info(tp->dev, "EEE is %s\n", + tp->setlpicnt ? "enabled" : "disabled"); + tg3_ump_link_report(tp); } } @@ -15278,8 +15283,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, ethtype = "10/100/1000Base-T"; netdev_info(dev, "attached PHY is %s (%s Ethernet) " - "(WireSpeed[%d])\n", tg3_phy_string(tp), ethtype, - (tp->phy_flags & TG3_PHYFLG_NO_ETH_WIRE_SPEED) == 0); + "(WireSpeed[%d], EEE[%d])\n", + tg3_phy_string(tp), ethtype, + (tp->phy_flags & TG3_PHYFLG_NO_ETH_WIRE_SPEED) == 0, + (tp->phy_flags & TG3_PHYFLG_EEE_CAP) != 0); } netdev_info(dev, "RXcsums[%d] LinkChgREG[%d] MIirq[%d] ASF[%d] TSOcap[%d]\n", -- cgit v1.2.3-58-ga151 From 5f8629c526b4f7e529a6d27bbd802c0dc7fcc357 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 21 Apr 2011 13:59:21 +0000 Subject: net: fix hw_features ethtool_ops->set_flags compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit __ethtool_set_flags() was not taking into account features set but not user-toggleable. Since GFLAGS returns masked dev->features, EINVAL is returned when passed flags differ to it, and not to wanted_features. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- net/core/ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 13d79f5a86e5..d8b1a8d85a96 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -546,12 +546,12 @@ int __ethtool_set_flags(struct net_device *dev, u32 data) } /* allow changing only bits set in hw_features */ - changed = (data ^ dev->wanted_features) & flags_dup_features; + changed = (data ^ dev->features) & flags_dup_features; if (changed & ~dev->hw_features) return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP; dev->wanted_features = - (dev->wanted_features & ~changed) | data; + (dev->wanted_features & ~changed) | (data & dev->hw_features); __netdev_update_features(dev); -- cgit v1.2.3-58-ga151 From e46f6538c24f01bb68dc374358ce85a0af666682 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Apr 2011 03:14:43 -0700 Subject: iwlagn: simplify error table reading The current code to read the error table header just hardcodes all the offsets, which is a bit hard to understand. We can read in the entire header (as much as we need) into a structure, and then take the data from there, which makes it easier to understand. To read a bigger blob we also don't need to grab NIC access for each word read, making the code more efficient. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 27 +++++---- drivers/net/wireless/iwlwifi/iwl-commands.h | 90 ++++++++++++++++------------- drivers/net/wireless/iwlwifi/iwl-io.c | 18 +++++- drivers/net/wireless/iwlwifi/iwl-io.h | 10 ++++ 4 files changed, 91 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index cdeb09eee739..f8559cc974f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1878,6 +1878,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) u32 desc, time, count, base, data1; u32 blink1, blink2, ilink1, ilink2; u32 pc, hcmd; + struct iwl_error_event_table table; base = priv->device_pointers.error_event_table; if (priv->ucode_type == UCODE_INIT) { @@ -1895,7 +1896,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) return; } - count = iwl_read_targ_mem(priv, base); + iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); + + count = table.valid; if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { IWL_ERR(priv, "Start IWL Error Log Dump:\n"); @@ -1903,18 +1906,18 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) priv->status, count); } - desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); + desc = table.error_id; priv->isr_stats.err_code = desc; - pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32)); - blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); - blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); - ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); - ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32)); - data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32)); - data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); - line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); - time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); - hcmd = iwl_read_targ_mem(priv, base + 22 * sizeof(u32)); + pc = table.pc; + blink1 = table.blink1; + blink2 = table.blink2; + ilink1 = table.ilink1; + ilink2 = table.ilink2; + data1 = table.data1; + data2 = table.data2; + line = table.line; + time = table.tsf_low; + hcmd = table.hcmd; trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, blink1, blink2, ilink1, ilink2); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 0edba8a6419b..7aea7b34f36c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -422,49 +422,61 @@ struct iwl_tx_ant_config_cmd { * * 2) error_event_table_ptr indicates base of the error log. This contains * information about any uCode error that occurs. For agn, the format - * of the error log is: - * - * __le32 valid; (nonzero) valid, (0) log is empty - * __le32 error_id; type of error - * __le32 pc; program counter - * __le32 blink1; branch link - * __le32 blink2; branch link - * __le32 ilink1; interrupt link - * __le32 ilink2; interrupt link - * __le32 data1; error-specific data - * __le32 data2; error-specific data - * __le32 line; source code line of error - * __le32 bcon_time; beacon timer - * __le32 tsf_low; network timestamp function timer - * __le32 tsf_hi; network timestamp function timer - * __le32 gp1; GP1 timer register - * __le32 gp2; GP2 timer register - * __le32 gp3; GP3 timer register - * __le32 ucode_ver; uCode version - * __le32 hw_ver; HW Silicon version - * __le32 brd_ver; HW board version - * __le32 log_pc; log program counter - * __le32 frame_ptr; frame pointer - * __le32 stack_ptr; stack pointer - * __le32 hcmd; last host command - * __le32 isr0; isr status register LMPM_NIC_ISR0: rxtx_flag - * __le32 isr1; isr status register LMPM_NIC_ISR1: host_flag - * __le32 isr2; isr status register LMPM_NIC_ISR2: enc_flag - * __le32 isr3; isr status register LMPM_NIC_ISR3: time_flag - * __le32 isr4; isr status register LMPM_NIC_ISR4: wico interrupt - * __le32 isr_pref; isr status register LMPM_NIC_PREF_STAT - * __le32 wait_event; wait event() caller address - * __le32 l2p_control; L2pControlField - * __le32 l2p_duration; L2pDurationField - * __le32 l2p_mhvalid; L2pMhValidBits - * __le32 l2p_addr_match; L2pAddrMatchStat - * __le32 lmpm_pmg_sel; indicate which clocks are turned on (LMPM_PMG_SEL) - * __le32 u_timestamp; indicate when the date and time of the compilation - * __le32 reserved; + * of the error log is defined by struct iwl_error_event_table. * * The Linux driver can print both logs to the system log when a uCode error * occurs. */ + +/* + * Note: This structure is read from the device with IO accesses, + * and the reading already does the endian conversion. As it is + * read with u32-sized accesses, any members with a different size + * need to be ordered correctly though! + */ +struct iwl_error_event_table { + u32 valid; /* (nonzero) valid, (0) log is empty */ + u32 error_id; /* type of error */ + u32 pc; /* program counter */ + u32 blink1; /* branch link */ + u32 blink2; /* branch link */ + u32 ilink1; /* interrupt link */ + u32 ilink2; /* interrupt link */ + u32 data1; /* error-specific data */ + u32 data2; /* error-specific data */ + u32 line; /* source code line of error */ + u32 bcon_time; /* beacon timer */ + u32 tsf_low; /* network timestamp function timer */ + u32 tsf_hi; /* network timestamp function timer */ + u32 gp1; /* GP1 timer register */ + u32 gp2; /* GP2 timer register */ + u32 gp3; /* GP3 timer register */ + u32 ucode_ver; /* uCode version */ + u32 hw_ver; /* HW Silicon version */ + u32 brd_ver; /* HW board version */ + u32 log_pc; /* log program counter */ + u32 frame_ptr; /* frame pointer */ + u32 stack_ptr; /* stack pointer */ + u32 hcmd; /* last host command header */ +#if 0 + /* no need to read the remainder, we don't use the values */ + u32 isr0; /* isr status register LMPM_NIC_ISR0: rxtx_flag */ + u32 isr1; /* isr status register LMPM_NIC_ISR1: host_flag */ + u32 isr2; /* isr status register LMPM_NIC_ISR2: enc_flag */ + u32 isr3; /* isr status register LMPM_NIC_ISR3: time_flag */ + u32 isr4; /* isr status register LMPM_NIC_ISR4: wico interrupt */ + u32 isr_pref; /* isr status register LMPM_NIC_PREF_STAT */ + u32 wait_event; /* wait event() caller address */ + u32 l2p_control; /* L2pControlField */ + u32 l2p_duration; /* L2pDurationField */ + u32 l2p_mhvalid; /* L2pMhValidBits */ + u32 l2p_addr_match; /* L2pAddrMatchStat */ + u32 lmpm_pmg_sel; /* indicate which clocks are turned on (LMPM_PMG_SEL) */ + u32 u_timestamp; /* indicate when the date and time of the compilation */ + u32 flow_handler; /* FH read/write pointers, RX credit */ +#endif +} __packed; + struct iwl_alive_resp { u8 ucode_minor; u8 ucode_major; diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 51337416e4ca..993b3df1b72b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -242,20 +242,32 @@ void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) spin_unlock_irqrestore(&priv->reg_lock, flags); } -u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) +void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, + void *buf, int words) { unsigned long flags; - u32 value; + int offs; + u32 *vals = buf; spin_lock_irqsave(&priv->reg_lock, flags); iwl_grab_nic_access(priv); iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr); rmb(); - value = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + + for (offs = 0; offs < words; offs++) + vals[offs] = iwl_read32(priv, HBUS_TARG_MEM_RDAT); iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->reg_lock, flags); +} + +u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) +{ + u32 value; + + _iwl_read_targ_mem_words(priv, addr, &value, 1); + return value; } diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index ab632baf49d5..262e0262496d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -76,6 +76,16 @@ void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, u32 bits, u32 mask); void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); +void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, + void *buf, int words); + +#define iwl_read_targ_mem_words(priv, addr, buf, bufsize) \ + do { \ + BUILD_BUG_ON((bufsize) % sizeof(u32)); \ + _iwl_read_targ_mem_words(priv, addr, buf, \ + (bufsize) / sizeof(u32));\ + } while (0) + u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr); void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val); #endif -- cgit v1.2.3-58-ga151 From 1a10f43313481b99154b3b1ce6863742475422e0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Apr 2011 03:14:44 -0700 Subject: iwlagn: clean up some exit code There's no point in running through iwl_down() when we never registered with mac80211, as it just cleans up internal structures that were never initialised in this case. Therefore we can also remove the special handling for this case from __iwl_down(). Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f8559cc974f8..2845f6372110 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2382,20 +2382,7 @@ static void __iwl_down(struct iwl_priv *priv) if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); - /* If we have not previously called iwl_init() then - * clear all bits but the RF Kill bit and return */ - if (!iwl_is_init(priv)) { - priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << - STATUS_RF_KILL_HW | - test_bit(STATUS_GEO_CONFIGURED, &priv->status) << - STATUS_GEO_CONFIGURED | - test_bit(STATUS_EXIT_PENDING, &priv->status) << - STATUS_EXIT_PENDING; - goto exit; - } - - /* ...otherwise clear out all the status bits but the RF Kill - * bit and continue taking the NIC down. */ + /* Clear out all status bits but a few that are stable across reset */ priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << @@ -2421,7 +2408,6 @@ static void __iwl_down(struct iwl_priv *priv) /* Stop the device, and put it in low power state */ iwl_apm_stop(priv); - exit: dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = NULL; @@ -4072,17 +4058,9 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) if (priv->mac80211_registered) { ieee80211_unregister_hw(priv->hw); priv->mac80211_registered = 0; - } else { - iwl_down(priv); } - /* - * Make sure device is reset to low power before unloading driver. - * This may be redundant with iwl_down(), but there are paths to - * run iwl_down() without calling apm_ops.stop(), and there are - * paths to avoid running iwl_down() at all before leaving driver. - * This (inexpensive) call *makes sure* device is reset. - */ + /* Reset to low power before unloading driver. */ iwl_apm_stop(priv); iwl_tt_exit(priv); -- cgit v1.2.3-58-ga151 From bc4f8adac6b30ee5f03dad267896add7e58db729 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Apr 2011 03:14:45 -0700 Subject: iwlagn: refactor down path The iwl_down path really consists of multiple things, refactor out the hardware resetting (including, of course, related software state like irqs). Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 30 ++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 34 +----------------------------- drivers/net/wireless/iwlwifi/iwl-agn.h | 11 ++++++++++ 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index e741128842bb..5c7eeac74846 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2293,3 +2293,33 @@ void iwlagn_remove_notification(struct iwl_priv *priv, list_del(&wait_entry->list); spin_unlock_bh(&priv->_agn.notif_wait_lock); } + +void iwlagn_stop_device(struct iwl_priv *priv) +{ + unsigned long flags; + + /* stop and reset the on-board processor */ + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + + /* tell the device to stop sending interrupts */ + spin_lock_irqsave(&priv->lock, flags); + iwl_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + iwl_synchronize_irq(priv); + + /* device going down, Stop using ICT table */ + iwl_disable_ict(priv); + + iwlagn_txq_ctx_stop(priv); + iwlagn_rxq_stop(priv); + + /* Power-down device's busmaster DMA clocks */ + iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); + udelay(5); + + /* Make sure (redundant) we've released our request to stay awake */ + iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + + /* Stop the device, and put it in low power state */ + iwl_apm_stop(priv); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 2845f6372110..f3d905551298 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -846,14 +846,6 @@ static void iwl_rx_handle(struct iwl_priv *priv) iwlagn_rx_queue_restock(priv); } -/* call this function to flush any scheduled tasklet */ -static inline void iwl_synchronize_irq(struct iwl_priv *priv) -{ - /* wait to make sure we flush pending tasklet*/ - synchronize_irq(priv->pci_dev->irq); - tasklet_kill(&priv->irq_tasklet); -} - /* tasklet for iwlagn interrupt */ static void iwl_irq_tasklet(struct iwl_priv *priv) { @@ -2338,7 +2330,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv); static void __iwl_down(struct iwl_priv *priv) { - unsigned long flags; int exit_pending; IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); @@ -2370,15 +2361,6 @@ static void __iwl_down(struct iwl_priv *priv) if (!exit_pending) clear_bit(STATUS_EXIT_PENDING, &priv->status); - /* stop and reset the on-board processor */ - iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); - - /* tell the device to stop sending interrupts */ - spin_lock_irqsave(&priv->lock, flags); - iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - iwl_synchronize_irq(priv); - if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); @@ -2392,21 +2374,7 @@ static void __iwl_down(struct iwl_priv *priv) test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; - /* device going down, Stop using ICT table */ - iwl_disable_ict(priv); - - iwlagn_txq_ctx_stop(priv); - iwlagn_rxq_stop(priv); - - /* Power-down device's busmaster DMA clocks */ - iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); - udelay(5); - - /* Make sure (redundant) we've released our request to stay awake */ - iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - - /* Stop the device, and put it in low power state */ - iwl_apm_stop(priv); + iwlagn_stop_device(priv); dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = NULL; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 078a23e5d99d..1211f457ee4c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -120,6 +120,17 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv); void iwl_free_isr_ict(struct iwl_priv *priv); irqreturn_t iwl_isr_ict(int irq, void *data); +/* call this function to flush any scheduled tasklet */ +static inline void iwl_synchronize_irq(struct iwl_priv *priv) +{ + /* wait to make sure we flush pending tasklet*/ + synchronize_irq(priv->pci_dev->irq); + tasklet_kill(&priv->irq_tasklet); +} + + +void iwlagn_stop_device(struct iwl_priv *priv); + /* tx queue */ void iwlagn_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index); -- cgit v1.2.3-58-ga151 From 3e14c1fd75d909bfcc6caab79c544921fd02bf73 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Apr 2011 03:14:46 -0700 Subject: iwlagn: refactor up path Starting the device consists of many things, refactor out enabling the hardware and also return -ERFKILL when the rfkill signal is found to be asserted (which makes more sense anyway, but is also required now to make the __iwl_up function return right away.) Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 46 ++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 44 ++-------------------------- drivers/net/wireless/iwlwifi/iwl-agn.h | 2 ++ 3 files changed, 51 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 5c7eeac74846..5e62a089e9ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2294,6 +2294,52 @@ void iwlagn_remove_notification(struct iwl_priv *priv, spin_unlock_bh(&priv->_agn.notif_wait_lock); } +int iwlagn_start_device(struct iwl_priv *priv) +{ + int ret; + + iwl_prepare_card_hw(priv); + if (!priv->hw_ready) { + IWL_WARN(priv, "Exit HW not ready\n"); + return -EIO; + } + + /* If platform's RF_KILL switch is NOT set to KILL */ + if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) + clear_bit(STATUS_RF_KILL_HW, &priv->status); + else + set_bit(STATUS_RF_KILL_HW, &priv->status); + + if (iwl_is_rfkill(priv)) { + wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); + iwl_enable_interrupts(priv); + return -ERFKILL; + } + + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + + ret = iwlagn_hw_nic_init(priv); + if (ret) { + IWL_ERR(priv, "Unable to init nic\n"); + return ret; + } + + /* make sure rfkill handshake bits are cleared */ + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); + + /* clear (again), then enable host interrupts */ + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_enable_interrupts(priv); + + /* really make sure rfkill handshake bits are cleared */ + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + + return 0; +} + void iwlagn_stop_device(struct iwl_priv *priv) { unsigned long flags; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f3d905551298..e99cd9474ba8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2416,7 +2416,7 @@ static int iwl_set_hw_ready(struct iwl_priv *priv) return ret; } -static int iwl_prepare_card_hw(struct iwl_priv *priv) +int iwl_prepare_card_hw(struct iwl_priv *priv) { int ret = 0; @@ -2462,47 +2462,9 @@ static int __iwl_up(struct iwl_priv *priv) } } - iwl_prepare_card_hw(priv); - - if (!priv->hw_ready) { - IWL_WARN(priv, "Exit HW not ready\n"); - return -EIO; - } - - /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->status); - else - set_bit(STATUS_RF_KILL_HW, &priv->status); - - if (iwl_is_rfkill(priv)) { - wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); - - iwl_enable_interrupts(priv); - IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n"); - return 0; - } - - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - - ret = iwlagn_hw_nic_init(priv); - if (ret) { - IWL_ERR(priv, "Unable to init nic\n"); + ret = iwlagn_start_device(priv); + if (ret) return ret; - } - - /* make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - - /* clear (again), then enable host interrupts */ - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(priv); - - /* really make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); for (i = 0; i < MAX_HW_RESTARTS; i++) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 1211f457ee4c..ef1bbd415b16 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -128,7 +128,9 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv) tasklet_kill(&priv->irq_tasklet); } +int iwl_prepare_card_hw(struct iwl_priv *priv); +int iwlagn_start_device(struct iwl_priv *priv); void iwlagn_stop_device(struct iwl_priv *priv); /* tx queue */ -- cgit v1.2.3-58-ga151 From 09f18afe766ea3f2c749e3af195bf65fde71b62e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Apr 2011 03:14:47 -0700 Subject: iwlagn: extend notification wait function A notification wait function is called with the command, but currently has no way of passing data back to the caller -- fix that by adding a void pointer to the function that can be used between the caller and the function. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 7 +++++-- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 5 +++-- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 6 ++++-- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 +++- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 5e62a089e9ba..486a8d3a1f0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2256,11 +2256,14 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) /* notification wait support */ void iwlagn_init_notification_wait(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry, + u8 cmd, void (*fn)(struct iwl_priv *priv, - struct iwl_rx_packet *pkt), - u8 cmd) + struct iwl_rx_packet *pkt, + void *data), + void *fn_data) { wait_entry->fn = fn; + wait_entry->fn_data = fn_data; wait_entry->cmd = cmd; wait_entry->triggered = false; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 56f46ee3bacd..ee7c5ba95971 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -58,8 +58,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, u8 old_dev_type = send->dev_type; int ret; - iwlagn_init_notification_wait(priv, &disable_wait, NULL, - REPLY_WIPAN_DEACTIVATION_COMPLETE); + iwlagn_init_notification_wait(priv, &disable_wait, + REPLY_WIPAN_DEACTIVATION_COMPLETE, + NULL, NULL); send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->dev_type = RXON_DEV_TYPE_P2P; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e99cd9474ba8..a9204db377a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -769,7 +769,7 @@ static void iwl_rx_handle(struct iwl_priv *priv) if (w->cmd == pkt->hdr.cmd) { w->triggered = true; if (w->fn) - w->fn(priv, pkt); + w->fn(priv, pkt, w->fn_data); } } spin_unlock(&priv->_agn.notif_wait_lock); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index ef1bbd415b16..b9871c4b3c18 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -338,9 +338,11 @@ void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); void __acquires(wait_entry) iwlagn_init_notification_wait(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry, + u8 cmd, void (*fn)(struct iwl_priv *priv, - struct iwl_rx_packet *pkt), - u8 cmd); + struct iwl_rx_packet *pkt, + void *data), + void *fn_data); signed long __releases(wait_entry) iwlagn_wait_notification(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index e84534c4d956..d8bf11727aac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1105,7 +1105,9 @@ struct iwl_force_reset { struct iwl_notification_wait { struct list_head list; - void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt); + void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt, + void *data); + void *fn_data; u8 cmd; bool triggered; -- cgit v1.2.3-58-ga151 From a8674a1efca60d863d4caa47e102cc4d70d5ff9b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Apr 2011 03:14:48 -0700 Subject: iwlagn: make iwlagn_wait_notification return error code We're unlikely to care about the actual time spent waiting, so make the function return an error code which is less error prone in coding new uses. Also, while at it, mark __must_check. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 11 +++++++---- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 8 ++------ drivers/net/wireless/iwlwifi/iwl-agn.h | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 486a8d3a1f0d..828416881d6f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2272,9 +2272,9 @@ void iwlagn_init_notification_wait(struct iwl_priv *priv, spin_unlock_bh(&priv->_agn.notif_wait_lock); } -signed long iwlagn_wait_notification(struct iwl_priv *priv, - struct iwl_notification_wait *wait_entry, - unsigned long timeout) +int iwlagn_wait_notification(struct iwl_priv *priv, + struct iwl_notification_wait *wait_entry, + unsigned long timeout) { int ret; @@ -2286,7 +2286,10 @@ signed long iwlagn_wait_notification(struct iwl_priv *priv, list_del(&wait_entry->list); spin_unlock_bh(&priv->_agn.notif_wait_lock); - return ret; + /* return value is always >= 0 */ + if (ret <= 0) + return -ETIMEDOUT; + return 0; } void iwlagn_remove_notification(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index ee7c5ba95971..435dd2d6c0ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -73,13 +73,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); iwlagn_remove_notification(priv, &disable_wait); } else { - signed long wait_res; - - wait_res = iwlagn_wait_notification(priv, &disable_wait, HZ); - if (wait_res == 0) { + ret = iwlagn_wait_notification(priv, &disable_wait, HZ); + if (ret) IWL_ERR(priv, "Timed out waiting for PAN disable\n"); - ret = -EIO; - } } return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index b9871c4b3c18..ba90aa474777 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -343,7 +343,7 @@ iwlagn_init_notification_wait(struct iwl_priv *priv, struct iwl_rx_packet *pkt, void *data), void *fn_data); -signed long __releases(wait_entry) +int __must_check __releases(wait_entry) iwlagn_wait_notification(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry, unsigned long timeout); -- cgit v1.2.3-58-ga151 From e74fe2330a5a721610b2b69652d2ec2ebbd302e0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Apr 2011 03:14:49 -0700 Subject: iwlagn: leave notification waits on firmware errors When the firmware encounters an error while the driver is waiting for a notification, it will never get that notification. Therefore, instead of timing out, bail out on errors when waiting for notifications. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 6 +++++- drivers/net/wireless/iwlwifi/iwl-core.c | 15 +++++++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 828416881d6f..a29e2e267ee4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2266,6 +2266,7 @@ void iwlagn_init_notification_wait(struct iwl_priv *priv, wait_entry->fn_data = fn_data; wait_entry->cmd = cmd; wait_entry->triggered = false; + wait_entry->aborted = false; spin_lock_bh(&priv->_agn.notif_wait_lock); list_add(&wait_entry->list, &priv->_agn.notif_waits); @@ -2279,13 +2280,16 @@ int iwlagn_wait_notification(struct iwl_priv *priv, int ret; ret = wait_event_timeout(priv->_agn.notif_waitq, - wait_entry->triggered, + wait_entry->triggered || wait_entry->aborted, timeout); spin_lock_bh(&priv->_agn.notif_wait_lock); list_del(&wait_entry->list); spin_unlock_bh(&priv->_agn.notif_wait_lock); + if (wait_entry->aborted) + return -EIO; + /* return value is always >= 0 */ if (ret <= 0) return -ETIMEDOUT; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 885167f8168d..46d69657407c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -867,6 +867,19 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv, } #endif +static void iwlagn_abort_notification_waits(struct iwl_priv *priv) +{ + unsigned long flags; + struct iwl_notification_wait *wait_entry; + + spin_lock_irqsave(&priv->_agn.notif_wait_lock, flags); + list_for_each_entry(wait_entry, &priv->_agn.notif_waits, list) + wait_entry->aborted = true; + spin_unlock_irqrestore(&priv->_agn.notif_wait_lock, flags); + + wake_up_all(&priv->_agn.notif_waitq); +} + void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) { unsigned int reload_msec; @@ -878,6 +891,8 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) /* Cancel currently queued command. */ clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + iwlagn_abort_notification_waits(priv); + /* Keep the restart process from trying to send host * commands by clearing the ready bit */ clear_bit(STATUS_READY, &priv->status); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d8bf11727aac..03452925bae3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1110,7 +1110,7 @@ struct iwl_notification_wait { void *fn_data; u8 cmd; - bool triggered; + bool triggered, aborted; }; enum iwl_rxon_context_id { -- cgit v1.2.3-58-ga151 From ca7966c88e44233fac113579071a6f55e00ef5ac Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 22 Apr 2011 10:15:23 -0700 Subject: iwlagn: implement synchronous firmware load The current firmware loading mechanism in iwlwifi is very hard to follow, and thus hard to maintain. To make it easier, make the firmware loading synchronous. For now, as a side effect, this removes a number of retry possibilities we had. It isn't typical for this to fail, but if it does happen we restart from scratch which this also makes easier to do should it be necessary. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 - drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 240 +++++++++++++++++++-------- drivers/net/wireless/iwlwifi/iwl-agn.c | 190 ++++++--------------- drivers/net/wireless/iwlwifi/iwl-agn.h | 13 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 13 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 10 +- drivers/net/wireless/iwlwifi/iwl-rx.c | 50 ------ 8 files changed, 246 insertions(+), 274 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index a29e2e267ee4..8216e5ca918b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -483,8 +483,6 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv) /* init calibration handlers */ priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = iwlagn_rx_calib_result; - priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = - iwlagn_rx_calib_complete; priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; /* set up notification wait support */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 5c30f6b19a7f..56dc7712aa70 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -161,8 +161,8 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name, } static int iwlagn_load_given_ucode(struct iwl_priv *priv, - struct fw_desc *inst_image, - struct fw_desc *data_image) + struct fw_desc *inst_image, + struct fw_desc *data_image) { int ret = 0; @@ -175,33 +175,6 @@ static int iwlagn_load_given_ucode(struct iwl_priv *priv, IWLAGN_RTC_DATA_LOWER_BOUND); } -int iwlagn_load_ucode(struct iwl_priv *priv) -{ - int ret = 0; - - /* check whether init ucode should be loaded, or rather runtime ucode */ - if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { - IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n"); - ret = iwlagn_load_given_ucode(priv, - &priv->ucode_init, &priv->ucode_init_data); - if (!ret) { - IWL_DEBUG_INFO(priv, "Init ucode load complete.\n"); - priv->ucode_type = UCODE_INIT; - } - } else { - IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. " - "Loading runtime ucode...\n"); - ret = iwlagn_load_given_ucode(priv, - &priv->ucode_code, &priv->ucode_data); - if (!ret) { - IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n"); - priv->ucode_type = UCODE_RT; - } - } - - return ret; -} - /* * Calibration */ @@ -297,33 +270,9 @@ void iwlagn_rx_calib_result(struct iwl_priv *priv, iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); } -void iwlagn_rx_calib_complete(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) +static int iwlagn_init_alive_start(struct iwl_priv *priv) { - IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); - queue_work(priv->workqueue, &priv->restart); -} - -void iwlagn_init_alive_start(struct iwl_priv *priv) -{ - int ret = 0; - - /* initialize uCode was loaded... verify inst image. - * This is a paranoid check, because we would not have gotten the - * "initialize" alive if code weren't properly loaded. */ - if (iwl_verify_ucode(priv, &priv->ucode_init)) { - /* Runtime instruction load was bad; - * take it all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); - goto restart; - } - - ret = iwlagn_alive_notify(priv); - if (ret) { - IWL_WARN(priv, - "Could not complete ALIVE transition: %d\n", ret); - goto restart; - } + int ret; if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) { @@ -333,24 +282,25 @@ void iwlagn_init_alive_start(struct iwl_priv *priv) * no need to close the envlope since we are going * to load the runtime uCode later. */ - iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, + ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); + if (ret) + return ret; } - iwlagn_send_calib_cfg(priv); + + ret = iwlagn_send_calib_cfg(priv); + if (ret) + return ret; /** * temperature offset calibration is only needed for runtime ucode, * so prepare the value now. */ if (priv->cfg->need_temp_offset_calib) - iwlagn_set_temperature_offset_calib(priv); - - return; + return iwlagn_set_temperature_offset_calib(priv); -restart: - /* real restart (first load init_ucode) */ - queue_work(priv->workqueue, &priv->restart); + return 0; } static int iwlagn_send_wimax_coex(struct iwl_priv *priv) @@ -413,19 +363,22 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv) IWL_ERR(priv, "failed to send BT prio tbl command\n"); } -void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) +int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) { struct iwl_bt_coex_prot_env_cmd env_cmd; + int ret; env_cmd.action = action; env_cmd.type = type; - if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV, - sizeof(env_cmd), &env_cmd)) + ret = iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV, + sizeof(env_cmd), &env_cmd); + if (ret) IWL_ERR(priv, "failed to send BT env command\n"); + return ret; } -int iwlagn_alive_notify(struct iwl_priv *priv) +static int iwlagn_alive_notify(struct iwl_priv *priv) { const struct queue_to_fifo_ac *queue_to_fifo; struct iwl_rxon_context *ctx; @@ -604,7 +557,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, * iwl_verify_ucode - determine which instruction image is in SRAM, * and verify its contents */ -int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc) +static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc) { if (!iwlcore_verify_inst_sparse(priv, fw_desc)) { IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n"); @@ -616,3 +569,154 @@ int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc) iwl_print_mismatch_inst(priv, fw_desc); return -EIO; } + +struct iwlagn_alive_data { + bool valid; + u8 subtype; +}; + +static void iwlagn_alive_fn(struct iwl_priv *priv, + struct iwl_rx_packet *pkt, + void *data) +{ + struct iwlagn_alive_data *alive_data = data; + struct iwl_alive_resp *palive; + + palive = &pkt->u.alive_frame; + + IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " + "0x%01X 0x%01X\n", + palive->is_valid, palive->ver_type, + palive->ver_subtype); + + priv->device_pointers.error_event_table = + le32_to_cpu(palive->error_event_table_ptr); + priv->device_pointers.log_event_table = + le32_to_cpu(palive->log_event_table_ptr); + + alive_data->subtype = palive->ver_subtype; + alive_data->valid = palive->is_valid == UCODE_VALID_OK; +} + +#define UCODE_ALIVE_TIMEOUT HZ +#define UCODE_CALIB_TIMEOUT (2*HZ) + +int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, + struct fw_desc *inst_image, + struct fw_desc *data_image, + int subtype, int alternate_subtype) +{ + struct iwl_notification_wait alive_wait; + struct iwlagn_alive_data alive_data; + int ret; + enum iwlagn_ucode_subtype old_type; + + ret = iwlagn_start_device(priv); + if (ret) + return ret; + + iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE, + iwlagn_alive_fn, &alive_data); + + old_type = priv->ucode_type; + priv->ucode_type = subtype; + + ret = iwlagn_load_given_ucode(priv, inst_image, data_image); + if (ret) { + priv->ucode_type = old_type; + iwlagn_remove_notification(priv, &alive_wait); + return ret; + } + + /* Remove all resets to allow NIC to operate */ + iwl_write32(priv, CSR_RESET, 0); + + /* + * Some things may run in the background now, but we + * just wait for the ALIVE notification here. + */ + ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT); + if (ret) { + priv->ucode_type = old_type; + return ret; + } + + if (!alive_data.valid) { + IWL_ERR(priv, "Loaded ucode is not valid!\n"); + priv->ucode_type = old_type; + return -EIO; + } + + if (alive_data.subtype != subtype && + alive_data.subtype != alternate_subtype) { + IWL_ERR(priv, + "Loaded ucode is not expected type (got %d, expected %d)!\n", + alive_data.subtype, subtype); + priv->ucode_type = old_type; + return -EIO; + } + + ret = iwl_verify_ucode(priv, inst_image); + if (ret) { + priv->ucode_type = old_type; + return ret; + } + + /* delay a bit to give rfkill time to run */ + msleep(5); + + ret = iwlagn_alive_notify(priv); + if (ret) { + IWL_WARN(priv, + "Could not complete ALIVE transition: %d\n", ret); + priv->ucode_type = old_type; + return ret; + } + + return 0; +} + +int iwlagn_run_init_ucode(struct iwl_priv *priv) +{ + struct iwl_notification_wait calib_wait; + int ret; + + lockdep_assert_held(&priv->mutex); + + /* No init ucode required? Curious, but maybe ok */ + if (!priv->ucode_init.len) + return 0; + + if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED) + return 0; + + iwlagn_init_notification_wait(priv, &calib_wait, + CALIBRATION_COMPLETE_NOTIFICATION, + NULL, NULL); + + /* Will also start the device */ + ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init, + &priv->ucode_init_data, + UCODE_SUBTYPE_INIT, -1); + if (ret) + goto error; + + ret = iwlagn_init_alive_start(priv); + if (ret) + goto error; + + /* + * Some things may run in the background now, but we + * just wait for the calibration complete notification. + */ + ret = iwlagn_wait_notification(priv, &calib_wait, UCODE_CALIB_TIMEOUT); + + goto out; + + error: + iwlagn_remove_notification(priv, &calib_wait); + out: + /* Whatever happened, stop the device */ + iwlagn_stop_device(priv); + return ret; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a9204db377a8..12cd5e0352bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1181,12 +1181,6 @@ static void iwl_dealloc_ucode_pci(struct iwl_priv *priv) iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data); } -static void iwl_nic_start(struct iwl_priv *priv) -{ - /* Remove all resets to allow NIC to operate */ - iwl_write32(priv, CSR_RESET, 0); -} - struct iwlagn_ucode_capabilities { u32 max_probe_length; u32 standard_phy_calibration_size; @@ -1873,7 +1867,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) struct iwl_error_event_table table; base = priv->device_pointers.error_event_table; - if (priv->ucode_type == UCODE_INIT) { + if (priv->ucode_type == UCODE_SUBTYPE_INIT) { if (!base) base = priv->_agn.init_errlog_ptr; } else { @@ -1884,7 +1878,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { IWL_ERR(priv, "Not valid error log pointer 0x%08X for %s uCode\n", - base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); + base, + (priv->ucode_type == UCODE_SUBTYPE_INIT) + ? "Init" : "RT"); return; } @@ -1944,7 +1940,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, return pos; base = priv->device_pointers.log_event_table; - if (priv->ucode_type == UCODE_INIT) { + if (priv->ucode_type == UCODE_SUBTYPE_INIT) { if (!base) base = priv->_agn.init_evtlog_ptr; } else { @@ -2057,7 +2053,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, size_t bufsz = 0; base = priv->device_pointers.log_event_table; - if (priv->ucode_type == UCODE_INIT) { + if (priv->ucode_type == UCODE_SUBTYPE_INIT) { logsize = priv->_agn.init_evtlog_size; if (!base) base = priv->_agn.init_evtlog_ptr; @@ -2070,7 +2066,9 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { IWL_ERR(priv, "Invalid event log pointer 0x%08X for %s uCode\n", - base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); + base, + (priv->ucode_type == UCODE_SUBTYPE_INIT) + ? "Init" : "RT"); return -EINVAL; } @@ -2217,30 +2215,14 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) * from protocol/runtime uCode (initialization uCode's * Alive gets handled by iwl_init_alive_start()). */ -static void iwl_alive_start(struct iwl_priv *priv) +static int iwl_alive_start(struct iwl_priv *priv) { int ret = 0; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); - - /* Initialize uCode has loaded Runtime uCode ... verify inst image. - * This is a paranoid check, because we would not have gotten the - * "runtime" alive if code weren't properly loaded. */ - if (iwl_verify_ucode(priv, &priv->ucode_code)) { - /* Runtime instruction load was bad; - * take it all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n"); - goto restart; - } - - ret = iwlagn_alive_notify(priv); - if (ret) { - IWL_WARN(priv, - "Could not complete ALIVE transition [ntf]: %d\n", ret); - goto restart; - } + iwl_reset_ict(priv); + IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); /* After the ALIVE response, we can send host commands to the uCode */ set_bit(STATUS_ALIVE, &priv->status); @@ -2249,7 +2231,7 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl_setup_watchdog(priv); if (iwl_is_rfkill(priv)) - return; + return -ERFKILL; /* download priority table before any calibration request */ if (priv->cfg->bt_params && @@ -2263,10 +2245,14 @@ static void iwl_alive_start(struct iwl_priv *priv) iwlagn_send_prio_tbl(priv); /* FIXME: w/a to force change uCode BT state machine */ - iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, - BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); - iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, - BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); + ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, + BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); + if (ret) + return ret; + ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, + BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); + if (ret) + return ret; } if (priv->hw_params.calib_rt_cfg) iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg); @@ -2308,22 +2294,16 @@ static void iwl_alive_start(struct iwl_priv *priv) set_bit(STATUS_READY, &priv->status); /* Configure the adapter for unassociated operation */ - iwlcore_commit_rxon(priv, ctx); + ret = iwlcore_commit_rxon(priv, ctx); + if (ret) + return ret; /* At this point, the NIC is initialized and operational */ iwl_rf_kill_ct_config(priv); IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); - wake_up_interruptible(&priv->wait_command_queue); - - iwl_power_update_mode(priv, true); - IWL_DEBUG_INFO(priv, "Updated power mode\n"); - - return; - - restart: - queue_work(priv->workqueue, &priv->restart); + return iwl_power_update_mode(priv, true); } static void iwl_cancel_deferred_work(struct iwl_priv *priv); @@ -2446,9 +2426,10 @@ int iwl_prepare_card_hw(struct iwl_priv *priv) static int __iwl_up(struct iwl_priv *priv) { struct iwl_rxon_context *ctx; - int i; int ret; + lockdep_assert_held(&priv->mutex); + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); return -EIO; @@ -2462,39 +2443,34 @@ static int __iwl_up(struct iwl_priv *priv) } } - ret = iwlagn_start_device(priv); - if (ret) - return ret; - - for (i = 0; i < MAX_HW_RESTARTS; i++) { - - /* load bootstrap state machine, - * load bootstrap program into processor's memory, - * prepare to load the "initialize" uCode */ - ret = iwlagn_load_ucode(priv); - - if (ret) { - IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n", - ret); - continue; - } - - /* start card; "initialize" will load runtime ucode */ - iwl_nic_start(priv); - - IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n"); + ret = iwlagn_run_init_ucode(priv); + if (ret) { + IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret); + goto error; + } - return 0; + ret = iwlagn_load_ucode_wait_alive(priv, + &priv->ucode_code, + &priv->ucode_data, + UCODE_SUBTYPE_REGULAR, + UCODE_SUBTYPE_REGULAR_NEW); + if (ret) { + IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret); + goto error; } + ret = iwl_alive_start(priv); + if (ret) + goto error; + return 0; + + error: set_bit(STATUS_EXIT_PENDING, &priv->status); __iwl_down(priv); clear_bit(STATUS_EXIT_PENDING, &priv->status); - /* tried to restart and config the device for as long as our - * patience could withstand */ - IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i); - return -EIO; + IWL_ERR(priv, "Unable to initialize device.\n"); + return ret; } @@ -2504,39 +2480,6 @@ static int __iwl_up(struct iwl_priv *priv) * *****************************************************************************/ -static void iwl_bg_init_alive_start(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, init_alive_start.work); - - mutex_lock(&priv->mutex); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - mutex_unlock(&priv->mutex); - return; - } - - iwlagn_init_alive_start(priv); - mutex_unlock(&priv->mutex); -} - -static void iwl_bg_alive_start(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, alive_start.work); - - mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - goto unlock; - - /* enable dram interrupt */ - iwl_reset_ict(priv); - - iwl_alive_start(priv); -unlock: - mutex_unlock(&priv->mutex); -} - static void iwl_bg_run_time_calib_work(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, @@ -2602,14 +2545,7 @@ static void iwl_bg_restart(struct work_struct *data) iwl_cancel_deferred_work(priv); ieee80211_restart_hw(priv->hw); } else { - iwl_down(priv); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - __iwl_up(priv); - mutex_unlock(&priv->mutex); + WARN_ON(1); } } @@ -2720,8 +2656,6 @@ unlock: * *****************************************************************************/ -#define UCODE_READY_TIMEOUT (4 * HZ) - /* * Not a mac80211 entry point function, but it fits in with all the * other mac80211 functions grouped here. @@ -2814,31 +2748,17 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw) mutex_lock(&priv->mutex); ret = __iwl_up(priv); mutex_unlock(&priv->mutex); - if (ret) return ret; - if (iwl_is_rfkill(priv)) - goto out; - IWL_DEBUG_INFO(priv, "Start UP work done.\n"); - /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from - * mac80211 will not be run successfully. */ - ret = wait_event_interruptible_timeout(priv->wait_command_queue, - test_bit(STATUS_READY, &priv->status), - UCODE_READY_TIMEOUT); - if (!ret) { - if (!test_bit(STATUS_READY, &priv->status)) { - IWL_ERR(priv, "START_ALIVE timeout after %dms.\n", - jiffies_to_msecs(UCODE_READY_TIMEOUT)); - return -ETIMEDOUT; - } - } + /* Now we should be done, and the READY bit should be set. */ + if (WARN_ON(!test_bit(STATUS_READY, &priv->status))) + ret = -EIO; iwlagn_led_enable(priv); -out: priv->is_open = 1; IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; @@ -3425,8 +3345,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); - INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); - INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); INIT_DELAYED_WORK(&priv->_agn.hw_roc_work, iwlagn_bg_roc_done); iwl_setup_scan_deferred_work(priv); @@ -3455,8 +3373,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) if (priv->cfg->ops->lib->cancel_deferred_work) priv->cfg->ops->lib->cancel_deferred_work(priv); - cancel_delayed_work_sync(&priv->init_alive_start); - cancel_delayed_work(&priv->alive_start); cancel_work_sync(&priv->run_time_calib_work); cancel_work_sync(&priv->beacon_update); @@ -3691,6 +3607,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv = hw->priv; /* At this point both hw and priv are allocated. */ + priv->ucode_type = UCODE_SUBTYPE_NONE_LOADED; + /* * The default context is always valid, * more may be discovered when firmware diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index ba90aa474777..cf05f87ec80e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -158,16 +158,15 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, u32 changes); /* uCode */ -int iwlagn_load_ucode(struct iwl_priv *priv); void iwlagn_rx_calib_result(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); -void iwlagn_rx_calib_complete(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); -void iwlagn_init_alive_start(struct iwl_priv *priv); -int iwlagn_alive_notify(struct iwl_priv *priv); -int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc); -void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); +int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); void iwlagn_send_prio_tbl(struct iwl_priv *priv); +int iwlagn_run_init_ucode(struct iwl_priv *priv); +int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, + struct fw_desc *inst_image, + struct fw_desc *data_image, + int subtype, int alternate_subtype); /* lib */ void iwl_check_abort_status(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 7aea7b34f36c..e125896c8096 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -386,7 +386,18 @@ struct iwl_tx_ant_config_cmd { *****************************************************************************/ #define UCODE_VALID_OK cpu_to_le32(0x1) -#define INITIALIZE_SUBTYPE (9) + +enum iwlagn_ucode_subtype { + UCODE_SUBTYPE_REGULAR = 0, + UCODE_SUBTYPE_REGULAR_NEW = 1, + UCODE_SUBTYPE_INIT = 9, + + /* + * Not a valid subtype, the ucode has just a u8, so + * we can use something > 0xff for this value. + */ + UCODE_SUBTYPE_NONE_LOADED = 0x100, +}; /** * REPLY_ALIVE = 0x1 (response only, not a command) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index c272204fccff..2b606889b64b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -226,7 +226,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, /* default is to dump the entire data segment */ if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { priv->dbgfs_sram_offset = 0x800000; - if (priv->ucode_type == UCODE_INIT) + if (priv->ucode_type == UCODE_SUBTYPE_INIT) priv->dbgfs_sram_len = priv->ucode_init_data.len; else priv->dbgfs_sram_len = priv->ucode_data.len; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 03452925bae3..414968c6b7cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -794,12 +794,6 @@ struct iwl_calib_result { size_t buf_len; }; -enum ucode_type { - UCODE_NONE = 0, - UCODE_INIT, - UCODE_RT -}; - /* Sensitivity calib data */ struct iwl_sensitivity_data { u32 auto_corr_ofdm; @@ -1276,7 +1270,7 @@ struct iwl_priv { struct fw_desc ucode_data; /* runtime data original */ struct fw_desc ucode_init; /* initialization inst */ struct fw_desc ucode_init_data; /* initialization data */ - enum ucode_type ucode_type; + enum iwlagn_ucode_subtype ucode_type; u8 ucode_write_complete; /* the image write is complete */ char firmware_name[25]; @@ -1474,8 +1468,6 @@ struct iwl_priv { struct tasklet_struct irq_tasklet; - struct delayed_work init_alive_start; - struct delayed_work alive_start; struct delayed_work scan_check; /* TX Power */ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index b49819ca2cd6..aca9a1d40080 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -225,55 +225,6 @@ err_bd: * ******************************************************************************/ -static void iwl_rx_reply_alive(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_alive_resp *palive; - struct delayed_work *pwork; - - palive = &pkt->u.alive_frame; - - IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " - "0x%01X 0x%01X\n", - palive->is_valid, palive->ver_type, - palive->ver_subtype); - - priv->device_pointers.log_event_table = - le32_to_cpu(palive->log_event_table_ptr); - priv->device_pointers.error_event_table = - le32_to_cpu(palive->error_event_table_ptr); - - if (palive->ver_subtype == INITIALIZE_SUBTYPE) { - IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); - pwork = &priv->init_alive_start; - } else { - IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); - pwork = &priv->alive_start; - } - - /* We delay the ALIVE response by 5ms to - * give the HW RF Kill time to activate... */ - if (palive->is_valid == UCODE_VALID_OK) - queue_delayed_work(priv->workqueue, pwork, - msecs_to_jiffies(5)); - else { - IWL_WARN(priv, "%s uCode did not respond OK.\n", - (palive->ver_subtype == INITIALIZE_SUBTYPE) ? - "init" : "runtime"); - /* - * If fail to load init uCode, - * let's try to load the init uCode again. - * We should not get into this situation, but if it - * does happen, we should not move on and loading "runtime" - * without proper calibrate the device. - */ - if (palive->ver_subtype == INITIALIZE_SUBTYPE) - priv->ucode_type = UCODE_NONE; - queue_work(priv->workqueue, &priv->restart); - } -} - static void iwl_rx_reply_error(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -1125,7 +1076,6 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) handlers = priv->rx_handlers; - handlers[REPLY_ALIVE] = iwl_rx_reply_alive; handlers[REPLY_ERROR] = iwl_rx_reply_error; handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; handlers[SPECTRUM_MEASURE_NOTIFICATION] = iwl_rx_spectrum_measure_notif; -- cgit v1.2.3-58-ga151 From dbf28e21ca391110e90ccad05dda79d2e2f60e0e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 16 Apr 2011 08:29:24 -0700 Subject: iwlagn: combine firmware code/data On new hardware, ucode images always come in pairs: code and data. Therefore, combine the variables into an appropriate struct and use that when both code and data are needed. Also, combine allocation and copying so that we have less code in total. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 23 +++---- drivers/net/wireless/iwlwifi/iwl-agn.c | 98 +++++++++++++--------------- drivers/net/wireless/iwlwifi/iwl-agn.h | 3 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 4 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 11 ++-- drivers/net/wireless/iwlwifi/iwl-helpers.h | 24 ------- 6 files changed, 65 insertions(+), 98 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 56dc7712aa70..c3ae2e44fcc9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -161,17 +161,16 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name, } static int iwlagn_load_given_ucode(struct iwl_priv *priv, - struct fw_desc *inst_image, - struct fw_desc *data_image) + struct fw_img *image) { int ret = 0; - ret = iwlagn_load_section(priv, "INST", inst_image, + ret = iwlagn_load_section(priv, "INST", &image->code, IWLAGN_RTC_INST_LOWER_BOUND); if (ret) return ret; - return iwlagn_load_section(priv, "DATA", data_image, + return iwlagn_load_section(priv, "DATA", &image->data, IWLAGN_RTC_DATA_LOWER_BOUND); } @@ -557,16 +556,16 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, * iwl_verify_ucode - determine which instruction image is in SRAM, * and verify its contents */ -static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc) +static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img) { - if (!iwlcore_verify_inst_sparse(priv, fw_desc)) { + if (!iwlcore_verify_inst_sparse(priv, &img->code)) { IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n"); return 0; } IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); - iwl_print_mismatch_inst(priv, fw_desc); + iwl_print_mismatch_inst(priv, &img->code); return -EIO; } @@ -602,8 +601,7 @@ static void iwlagn_alive_fn(struct iwl_priv *priv, #define UCODE_CALIB_TIMEOUT (2*HZ) int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, - struct fw_desc *inst_image, - struct fw_desc *data_image, + struct fw_img *image, int subtype, int alternate_subtype) { struct iwl_notification_wait alive_wait; @@ -621,7 +619,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, old_type = priv->ucode_type; priv->ucode_type = subtype; - ret = iwlagn_load_given_ucode(priv, inst_image, data_image); + ret = iwlagn_load_given_ucode(priv, image); if (ret) { priv->ucode_type = old_type; iwlagn_remove_notification(priv, &alive_wait); @@ -656,7 +654,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, return -EIO; } - ret = iwl_verify_ucode(priv, inst_image); + ret = iwl_verify_ucode(priv, image); if (ret) { priv->ucode_type = old_type; return ret; @@ -684,7 +682,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) lockdep_assert_held(&priv->mutex); /* No init ucode required? Curious, but maybe ok */ - if (!priv->ucode_init.len) + if (!priv->ucode_init.code.len) return 0; if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED) @@ -696,7 +694,6 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) /* Will also start the device */ ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init, - &priv->ucode_init_data, UCODE_SUBTYPE_INIT, -1); if (ret) goto error; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 12cd5e0352bc..f30735b656c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1173,12 +1173,42 @@ static struct attribute_group iwl_attribute_group = { * ******************************************************************************/ +static void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc) +{ + if (desc->v_addr) + dma_free_coherent(&pci_dev->dev, desc->len, + desc->v_addr, desc->p_addr); + desc->v_addr = NULL; + desc->len = 0; +} + +static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img) +{ + iwl_free_fw_desc(pci_dev, &img->code); + iwl_free_fw_desc(pci_dev, &img->data); +} + +static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc, + const void *data, size_t len) +{ + if (!len) { + desc->v_addr = NULL; + return -EINVAL; + } + + desc->v_addr = dma_alloc_coherent(&pci_dev->dev, len, + &desc->p_addr, GFP_KERNEL); + if (!desc->v_addr) + return -ENOMEM; + desc->len = len; + memcpy(desc->v_addr, data, len); + return 0; +} + static void iwl_dealloc_ucode_pci(struct iwl_priv *priv) { - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data); + iwl_free_fw_img(priv->pci_dev, &priv->ucode_rt); + iwl_free_fw_img(priv->pci_dev, &priv->ucode_init); } struct iwlagn_ucode_capabilities { @@ -1647,24 +1677,20 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) /* Runtime instructions and 2 copies of data: * 1) unmodified from disk * 2) backup cache for save/restore during power-downs */ - priv->ucode_code.len = pieces.inst_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); - - priv->ucode_data.len = pieces.data_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); - - if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr) + if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.code, + pieces.inst, pieces.inst_size)) + goto err_pci_alloc; + if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.data, + pieces.data, pieces.data_size)) goto err_pci_alloc; /* Initialization instructions and data */ if (pieces.init_size && pieces.init_data_size) { - priv->ucode_init.len = pieces.init_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); - - priv->ucode_init_data.len = pieces.init_data_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); - - if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) + if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code, + pieces.init, pieces.init_size)) + goto err_pci_alloc; + if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data, + pieces.init_data, pieces.init_data_size)) goto err_pci_alloc; } @@ -1701,39 +1727,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) else priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; - /* Copy images into buffers for card's bus-master reads ... */ - - /* Runtime instructions (first block of data in file) */ - IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", - pieces.inst_size); - memcpy(priv->ucode_code.v_addr, pieces.inst, pieces.inst_size); - - IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", - priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); - - /* - * Runtime data - * NOTE: Copy into backup buffer will be done in iwl_up() - */ - IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", - pieces.data_size); - memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size); - - /* Initialization instructions */ - if (pieces.init_size) { - IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", - pieces.init_size); - memcpy(priv->ucode_init.v_addr, pieces.init, pieces.init_size); - } - - /* Initialization data */ - if (pieces.init_data_size) { - IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", - pieces.init_data_size); - memcpy(priv->ucode_init_data.v_addr, pieces.init_data, - pieces.init_data_size); - } - /* * figure out the offset of chain noise reset and gain commands * base on the size of standard phy calibration commands table size @@ -2450,8 +2443,7 @@ static int __iwl_up(struct iwl_priv *priv) } ret = iwlagn_load_ucode_wait_alive(priv, - &priv->ucode_code, - &priv->ucode_data, + &priv->ucode_rt, UCODE_SUBTYPE_REGULAR, UCODE_SUBTYPE_REGULAR_NEW); if (ret) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index cf05f87ec80e..c475ac427596 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -164,8 +164,7 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); void iwlagn_send_prio_tbl(struct iwl_priv *priv); int iwlagn_run_init_ucode(struct iwl_priv *priv); int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, - struct fw_desc *inst_image, - struct fw_desc *data_image, + struct fw_img *image, int subtype, int alternate_subtype); /* lib */ diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 2b606889b64b..7bd4f5af5b0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -227,9 +227,9 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { priv->dbgfs_sram_offset = 0x800000; if (priv->ucode_type == UCODE_SUBTYPE_INIT) - priv->dbgfs_sram_len = priv->ucode_init_data.len; + priv->dbgfs_sram_len = priv->ucode_init.data.len; else - priv->dbgfs_sram_len = priv->ucode_data.len; + priv->dbgfs_sram_len = priv->ucode_rt.data.len; } len = priv->dbgfs_sram_len; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 414968c6b7cf..857eb0e9e397 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -479,6 +479,10 @@ struct fw_desc { u32 len; /* bytes */ }; +struct fw_img { + struct fw_desc code, data; +}; + /* v1/v2 uCode file layout */ struct iwl_ucode_header { __le32 ver; /* major/minor/API/serial */ @@ -1266,10 +1270,9 @@ struct iwl_priv { int fw_index; /* firmware we're trying to load */ u32 ucode_ver; /* version of ucode, copy of iwl_ucode.ver */ - struct fw_desc ucode_code; /* runtime inst */ - struct fw_desc ucode_data; /* runtime data original */ - struct fw_desc ucode_init; /* initialization inst */ - struct fw_desc ucode_init_data; /* initialization data */ + struct fw_img ucode_rt; + struct fw_img ucode_init; + enum iwlagn_ucode_subtype ucode_type; u8 ucode_write_complete; /* the image write is complete */ char firmware_name[25]; diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 9309ff2df4c2..41207a3645b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -64,30 +64,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd) return --index & (n_bd - 1); } -/* TODO: Move fw_desc functions to iwl-pci.ko */ -static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, - struct fw_desc *desc) -{ - if (desc->v_addr) - dma_free_coherent(&pci_dev->dev, desc->len, - desc->v_addr, desc->p_addr); - desc->v_addr = NULL; - desc->len = 0; -} - -static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, - struct fw_desc *desc) -{ - if (!desc->len) { - desc->v_addr = NULL; - return -EINVAL; - } - - desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, - &desc->p_addr, GFP_KERNEL); - return (desc->v_addr != NULL) ? 0 : -ENOMEM; -} - /* * we have 8 bits used like this: * -- cgit v1.2.3-58-ga151 From 4cd2bf76a40a148bc92f4a3d17bc7f94277b0410 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Apr 2011 03:14:52 -0700 Subject: iwlagn: remove hw_ready variable This variable is only ever checked right after the function that sets it, but the same function will also return the status, so we can pass it through instead of checking hw_ready later. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 29 ++++++++++++++--------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 8216e5ca918b..e202a40cbcb7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2306,8 +2306,7 @@ int iwlagn_start_device(struct iwl_priv *priv) { int ret; - iwl_prepare_card_hw(priv); - if (!priv->hw_ready) { + if (iwl_prepare_card_hw(priv)) { IWL_WARN(priv, "Exit HW not ready\n"); return -EIO; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f30735b656c0..a4f1009cb137 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2367,9 +2367,10 @@ static void iwl_down(struct iwl_priv *priv) #define HW_READY_TIMEOUT (50) +/* Note: returns poll_bit return value, which is >= 0 if success */ static int iwl_set_hw_ready(struct iwl_priv *priv) { - int ret = 0; + int ret; iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); @@ -2379,25 +2380,21 @@ static int iwl_set_hw_ready(struct iwl_priv *priv) CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, HW_READY_TIMEOUT); - if (ret != -ETIMEDOUT) - priv->hw_ready = true; - else - priv->hw_ready = false; - IWL_DEBUG_INFO(priv, "hardware %s\n", - (priv->hw_ready == 1) ? "ready" : "not ready"); + IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : ""); return ret; } +/* Note: returns standard 0/-ERROR code */ int iwl_prepare_card_hw(struct iwl_priv *priv) { - int ret = 0; + int ret; IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n"); ret = iwl_set_hw_ready(priv); - if (priv->hw_ready) - return ret; + if (ret >= 0) + return 0; /* If HW is not ready, prepare the conditions to check again */ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, @@ -2407,10 +2404,13 @@ int iwl_prepare_card_hw(struct iwl_priv *priv) ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); - /* HW should be ready by now, check again. */ - if (ret != -ETIMEDOUT) - iwl_set_hw_ready(priv); + if (ret < 0) + return ret; + /* HW should be ready by now, check again. */ + ret = iwl_set_hw_ready(priv); + if (ret >= 0) + return 0; return ret; } @@ -3741,8 +3741,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * PCI Tx retries from interfering with C3 CPU state */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - iwl_prepare_card_hw(priv); - if (!priv->hw_ready) { + if (iwl_prepare_card_hw(priv)) { IWL_WARN(priv, "Failed, HW not ready\n"); goto out_iounmap; } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 857eb0e9e397..197fa742f79a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1503,7 +1503,6 @@ struct iwl_priv { struct timer_list statistics_periodic; struct timer_list ucode_trace; struct timer_list watchdog; - bool hw_ready; struct iwl_event_log event_log; -- cgit v1.2.3-58-ga151 From b71d1d426d263b0b6cb5760322efebbfc89d4463 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 22 Apr 2011 04:53:02 +0000 Subject: inet: constify ip headers and in6_addr Add const qualifiers to structs iphdr, ipv6hdr and in6_addr pointers where possible, to make code intention more obvious. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/addrconf.h | 22 ++++++++-------- include/net/if_inet6.h | 4 +-- include/net/inetpeer.h | 2 +- include/net/ip6_fib.h | 8 +++--- include/net/ip6_route.h | 18 ++++++------- include/net/ipv6.h | 4 +-- include/net/ndisc.h | 3 ++- include/net/route.h | 3 ++- include/net/xfrm.h | 6 ++--- net/bridge/br_multicast.c | 12 ++++----- net/bridge/br_netfilter.c | 4 +-- net/core/dev.c | 8 +++--- net/core/netpoll.c | 2 +- net/dccp/ipv6.c | 8 +++--- net/ipv4/af_inet.c | 4 +-- net/ipv4/ah4.c | 7 ++--- net/ipv4/esp4.c | 7 ++--- net/ipv4/icmp.c | 12 ++++----- net/ipv4/inet_diag.c | 2 +- net/ipv4/inet_lro.c | 4 +-- net/ipv4/ip_gre.c | 28 ++++++++++---------- net/ipv4/ip_input.c | 4 +-- net/ipv4/ip_sockglue.c | 2 +- net/ipv4/ipcomp.c | 4 +-- net/ipv4/ipip.c | 8 +++--- net/ipv4/ipmr.c | 2 +- net/ipv4/netfilter/nf_nat_helper.c | 2 +- net/ipv4/raw.c | 10 ++++---- net/ipv4/route.c | 2 +- net/ipv4/tcp_ipv4.c | 8 +++--- net/ipv4/udp.c | 2 +- net/ipv4/xfrm4_policy.c | 2 +- net/ipv4/xfrm4_state.c | 2 +- net/ipv6/addrconf.c | 16 ++++++------ net/ipv6/af_inet6.c | 2 +- net/ipv6/anycast.c | 16 ++++++------ net/ipv6/esp6.c | 5 ++-- net/ipv6/icmp.c | 8 +++--- net/ipv6/ip6_fib.c | 16 ++++++------ net/ipv6/ip6_input.c | 6 ++--- net/ipv6/ip6_output.c | 8 +++--- net/ipv6/ip6_tunnel.c | 36 +++++++++++++------------- net/ipv6/ip6mr.c | 4 +-- net/ipv6/ipcomp6.c | 5 ++-- net/ipv6/mcast.c | 36 +++++++++++++------------- net/ipv6/mip6.c | 8 +++--- net/ipv6/ndisc.c | 18 ++++++------- net/ipv6/netfilter.c | 10 ++++---- net/ipv6/raw.c | 14 +++++----- net/ipv6/reassembly.c | 4 +-- net/ipv6/route.c | 52 +++++++++++++++++++------------------- net/ipv6/sit.c | 25 +++++++++--------- net/ipv6/syncookies.c | 13 +++++----- net/ipv6/tcp_ipv6.c | 48 +++++++++++++++++------------------ net/ipv6/udp.c | 20 +++++++-------- net/ipv6/xfrm6_mode_beet.c | 2 -- net/ipv6/xfrm6_mode_tunnel.c | 6 ++--- net/ipv6/xfrm6_policy.c | 2 +- net/ipv6/xfrm6_tunnel.c | 10 ++++---- net/key/af_key.c | 2 +- net/sched/sch_sfq.c | 2 +- net/sctp/input.c | 2 +- net/sctp/ipv6.c | 2 +- net/xfrm/xfrm_state.c | 12 ++++----- 64 files changed, 316 insertions(+), 310 deletions(-) diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 23710aa6a181..7c4d92c0dd1d 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -61,16 +61,16 @@ extern int addrconf_set_dstaddr(struct net *net, void __user *arg); extern int ipv6_chk_addr(struct net *net, - struct in6_addr *addr, + const struct in6_addr *addr, struct net_device *dev, int strict); #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) extern int ipv6_chk_home_addr(struct net *net, - struct in6_addr *addr); + const struct in6_addr *addr); #endif -extern int ipv6_chk_prefix(struct in6_addr *addr, +extern int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev); extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, @@ -89,9 +89,9 @@ extern int ipv6_get_lladdr(struct net_device *dev, extern int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2); extern void addrconf_join_solict(struct net_device *dev, - struct in6_addr *addr); + const struct in6_addr *addr); extern void addrconf_leave_solict(struct inet6_dev *idev, - struct in6_addr *addr); + const struct in6_addr *addr); static inline unsigned long addrconf_timeout_fixup(u32 timeout, unsigned unit) @@ -158,15 +158,15 @@ extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len); /* * anycast prototypes (anycast.c) */ -extern int ipv6_sock_ac_join(struct sock *sk,int ifindex,struct in6_addr *addr); -extern int ipv6_sock_ac_drop(struct sock *sk,int ifindex,struct in6_addr *addr); +extern int ipv6_sock_ac_join(struct sock *sk,int ifindex, const struct in6_addr *addr); +extern int ipv6_sock_ac_drop(struct sock *sk,int ifindex, const struct in6_addr *addr); extern void ipv6_sock_ac_close(struct sock *sk); -extern int inet6_ac_check(struct sock *sk, struct in6_addr *addr, int ifindex); +extern int inet6_ac_check(struct sock *sk, const struct in6_addr *addr, int ifindex); -extern int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr); -extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr); +extern int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr); +extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr); extern int ipv6_chk_acast_addr(struct net *net, struct net_device *dev, - struct in6_addr *addr); + const struct in6_addr *addr); /* Device notifier */ diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index fccc2180c61b..3d982f72d48e 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -196,7 +196,7 @@ struct inet6_dev { struct rcu_head rcu; }; -static inline void ipv6_eth_mc_map(struct in6_addr *addr, char *buf) +static inline void ipv6_eth_mc_map(const struct in6_addr *addr, char *buf) { /* * +-------+-------+-------+-------+-------+-------+ @@ -210,7 +210,7 @@ static inline void ipv6_eth_mc_map(struct in6_addr *addr, char *buf) memcpy(buf + 2, &addr->s6_addr32[3], sizeof(__u32)); } -static inline void ipv6_tr_mc_map(struct in6_addr *addr, char *buf) +static inline void ipv6_tr_mc_map(const struct in6_addr *addr, char *buf) { /* All nodes FF01::1, FF02::1, FF02::1:FFxx:xxxx */ diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index e6dd8da6b2ad..8a159cc3d68b 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h @@ -80,7 +80,7 @@ static inline struct inet_peer *inet_getpeer_v4(__be32 v4daddr, int create) return inet_getpeer(&daddr, create); } -static inline struct inet_peer *inet_getpeer_v6(struct in6_addr *v6daddr, int create) +static inline struct inet_peer *inet_getpeer_v6(const struct in6_addr *v6daddr, int create) { struct inetpeer_addr daddr; diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 98348d53b2b6..aca8ef4dd67c 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -198,12 +198,12 @@ extern struct dst_entry *fib6_rule_lookup(struct net *net, pol_lookup_t lookup); extern struct fib6_node *fib6_lookup(struct fib6_node *root, - struct in6_addr *daddr, - struct in6_addr *saddr); + const struct in6_addr *daddr, + const struct in6_addr *saddr); struct fib6_node *fib6_locate(struct fib6_node *root, - struct in6_addr *daddr, int dst_len, - struct in6_addr *saddr, int src_len); + const struct in6_addr *daddr, int dst_len, + const struct in6_addr *saddr, int src_len); extern void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg), diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 86b1cb486903..d5c21d4d9e7e 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -86,7 +86,7 @@ extern int ip6_del_rt(struct rt6_info *); extern int ip6_route_get_saddr(struct net *net, struct rt6_info *rt, - struct in6_addr *daddr, + const struct in6_addr *daddr, unsigned int prefs, struct in6_addr *saddr); @@ -112,9 +112,9 @@ extern int ip6_dst_hoplimit(struct dst_entry *dst); * support functions for ND * */ -extern struct rt6_info * rt6_get_dflt_router(struct in6_addr *addr, +extern struct rt6_info * rt6_get_dflt_router(const struct in6_addr *addr, struct net_device *dev); -extern struct rt6_info * rt6_add_dflt_router(struct in6_addr *gwaddr, +extern struct rt6_info * rt6_add_dflt_router(const struct in6_addr *gwaddr, struct net_device *dev, unsigned int pref); @@ -122,17 +122,17 @@ extern void rt6_purge_dflt_routers(struct net *net); extern int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, - struct in6_addr *gwaddr); + const struct in6_addr *gwaddr); -extern void rt6_redirect(struct in6_addr *dest, - struct in6_addr *src, - struct in6_addr *saddr, +extern void rt6_redirect(const struct in6_addr *dest, + const struct in6_addr *src, + const struct in6_addr *saddr, struct neighbour *neigh, u8 *lladdr, int on_link); -extern void rt6_pmtu_discovery(struct in6_addr *daddr, - struct in6_addr *saddr, +extern void rt6_pmtu_discovery(const struct in6_addr *daddr, + const struct in6_addr *saddr, struct net_device *dev, u32 pmtu); diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 34200f9e6805..5da192653153 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -376,8 +376,8 @@ enum ip6_defrag_users { struct ip6_create_arg { __be32 id; u32 user; - struct in6_addr *src; - struct in6_addr *dst; + const struct in6_addr *src; + const struct in6_addr *dst; }; void ip6_frag_init(struct inet_frag_queue *q, void *a); diff --git a/include/net/ndisc.h b/include/net/ndisc.h index e0e594f8e9d9..6144685d601b 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -102,7 +102,8 @@ extern void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, const struct in6_addr *target); -extern int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir); +extern int ndisc_mc_map(const struct in6_addr *addr, char *buf, + struct net_device *dev, int dir); extern struct sk_buff *ndisc_build_skb(struct net_device *dev, const struct in6_addr *daddr, diff --git a/include/net/route.h b/include/net/route.h index 3782cddd1383..b3962e249e14 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -191,7 +191,8 @@ static inline int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 s return ip_route_input_common(skb, dst, src, tos, devin, true); } -extern unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph, unsigned short new_mtu, struct net_device *dev); +extern unsigned short ip_rt_frag_needed(struct net *net, const struct iphdr *iph, + unsigned short new_mtu, struct net_device *dev); extern void ip_rt_send_redirect(struct sk_buff *skb); extern unsigned inet_addr_type(struct net *net, __be32 addr); diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 65ea31348631..1cdd4b7b2861 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1475,7 +1475,7 @@ extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family); extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family); extern __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr); -extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr); +extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr); extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb); extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb); extern int xfrm6_output(struct sk_buff *skb); @@ -1569,8 +1569,8 @@ static inline int xfrm_addr_cmp(const xfrm_address_t *a, case AF_INET: return (__force u32)a->a4 - (__force u32)b->a4; case AF_INET6: - return ipv6_addr_cmp((struct in6_addr *)a, - (struct in6_addr *)b); + return ipv6_addr_cmp((const struct in6_addr *)a, + (const struct in6_addr *)b); } } diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 59660c909a7c..2f14eafdeeab 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -413,7 +413,7 @@ out: #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, - struct in6_addr *group) + const struct in6_addr *group) { struct sk_buff *skb; struct ipv6hdr *ip6h; @@ -1115,7 +1115,7 @@ static int br_ip4_multicast_query(struct net_bridge *br, struct net_bridge_port *port, struct sk_buff *skb) { - struct iphdr *iph = ip_hdr(skb); + const struct iphdr *iph = ip_hdr(skb); struct igmphdr *ih = igmp_hdr(skb); struct net_bridge_mdb_entry *mp; struct igmpv3_query *ih3; @@ -1190,7 +1190,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, struct net_bridge_port *port, struct sk_buff *skb) { - struct ipv6hdr *ip6h = ipv6_hdr(skb); + const struct ipv6hdr *ip6h = ipv6_hdr(skb); struct mld_msg *mld = (struct mld_msg *) icmp6_hdr(skb); struct net_bridge_mdb_entry *mp; struct mld2_query *mld2q; @@ -1198,7 +1198,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, struct net_bridge_port_group __rcu **pp; unsigned long max_delay; unsigned long now = jiffies; - struct in6_addr *group = NULL; + const struct in6_addr *group = NULL; int err = 0; spin_lock(&br->multicast_lock); @@ -1356,7 +1356,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, struct sk_buff *skb) { struct sk_buff *skb2 = skb; - struct iphdr *iph; + const struct iphdr *iph; struct igmphdr *ih; unsigned len; unsigned offset; @@ -1452,7 +1452,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, struct sk_buff *skb) { struct sk_buff *skb2; - struct ipv6hdr *ip6h; + const struct ipv6hdr *ip6h; struct icmp6hdr *icmp6h; u8 nexthdr; unsigned len; diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index f3bc322c5891..5614907525e1 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -219,7 +219,7 @@ static inline void nf_bridge_update_protocol(struct sk_buff *skb) static int br_parse_ip_options(struct sk_buff *skb) { struct ip_options *opt; - struct iphdr *iph; + const struct iphdr *iph; struct net_device *dev = skb->dev; u32 len; @@ -554,7 +554,7 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - struct ipv6hdr *hdr; + const struct ipv6hdr *hdr; u32 pkt_len; if (skb->len < sizeof(struct ipv6hdr)) diff --git a/net/core/dev.c b/net/core/dev.c index 3871bf69a386..379c993ff421 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2502,8 +2502,8 @@ static inline void ____napi_schedule(struct softnet_data *sd, __u32 __skb_get_rxhash(struct sk_buff *skb) { int nhoff, hash = 0, poff; - struct ipv6hdr *ip6; - struct iphdr *ip; + const struct ipv6hdr *ip6; + const struct iphdr *ip; u8 ip_proto; u32 addr1, addr2, ihl; union { @@ -2518,7 +2518,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb) if (!pskb_may_pull(skb, sizeof(*ip) + nhoff)) goto done; - ip = (struct iphdr *) (skb->data + nhoff); + ip = (const struct iphdr *) (skb->data + nhoff); if (ip->frag_off & htons(IP_MF | IP_OFFSET)) ip_proto = 0; else @@ -2531,7 +2531,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb) if (!pskb_may_pull(skb, sizeof(*ip6) + nhoff)) goto done; - ip6 = (struct ipv6hdr *) (skb->data + nhoff); + ip6 = (const struct ipv6hdr *) (skb->data + nhoff); ip_proto = ip6->nexthdr; addr1 = (__force u32) ip6->saddr.s6_addr32[3]; addr2 = (__force u32) ip6->daddr.s6_addr32[3]; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 06be2431753e..46d9c3a4de2f 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -539,7 +539,7 @@ int __netpoll_rx(struct sk_buff *skb) { int proto, len, ulen; int hits = 0; - struct iphdr *iph; + const struct iphdr *iph; struct udphdr *uh; struct netpoll_info *npinfo = skb->dev->npinfo; struct netpoll *np, *tmp; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index de1b7e37ad5b..73add2373247 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -54,8 +54,8 @@ static void dccp_v6_hash(struct sock *sk) /* add pseudo-header to DCCP checksum stored in skb->csum */ static inline __sum16 dccp_v6_csum_finish(struct sk_buff *skb, - struct in6_addr *saddr, - struct in6_addr *daddr) + const struct in6_addr *saddr, + const struct in6_addr *daddr) { return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum); } @@ -87,7 +87,7 @@ static inline __u32 dccp_v6_init_sequence(struct sk_buff *skb) static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, u8 type, u8 code, int offset, __be32 info) { - struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data; + const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data; const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); struct dccp_sock *dp; struct ipv6_pinfo *np; @@ -296,7 +296,7 @@ static void dccp_v6_reqsk_destructor(struct request_sock *req) static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) { - struct ipv6hdr *rxip6h; + const struct ipv6hdr *rxip6h; struct sk_buff *skb; struct flowi6 fl6; struct net *net = dev_net(skb_dst(rxskb)->dev); diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 807d83c02ef6..cae75ef21fea 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1186,7 +1186,7 @@ EXPORT_SYMBOL(inet_sk_rebuild_header); static int inet_gso_send_check(struct sk_buff *skb) { - struct iphdr *iph; + const struct iphdr *iph; const struct net_protocol *ops; int proto; int ihl; @@ -1293,7 +1293,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, const struct net_protocol *ops; struct sk_buff **pp = NULL; struct sk_buff *p; - struct iphdr *iph; + const struct iphdr *iph; unsigned int hlen; unsigned int off; unsigned int id; diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 4286fd3cc0e2..c1f4154552fc 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -73,7 +73,7 @@ static inline struct scatterlist *ah_req_sg(struct crypto_ahash *ahash, * into IP header for icv calculation. Options are already checked * for validity, so paranoia is not required. */ -static int ip_clear_mutable_options(struct iphdr *iph, __be32 *daddr) +static int ip_clear_mutable_options(const struct iphdr *iph, __be32 *daddr) { unsigned char * optptr = (unsigned char*)(iph+1); int l = iph->ihl*4 - sizeof(struct iphdr); @@ -396,7 +396,7 @@ out: static void ah4_err(struct sk_buff *skb, u32 info) { struct net *net = dev_net(skb->dev); - struct iphdr *iph = (struct iphdr *)skb->data; + const struct iphdr *iph = (const struct iphdr *)skb->data; struct ip_auth_hdr *ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2)); struct xfrm_state *x; @@ -404,7 +404,8 @@ static void ah4_err(struct sk_buff *skb, u32 info) icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) return; - x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET); + x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, + ah->spi, IPPROTO_AH, AF_INET); if (!x) return; printk(KERN_DEBUG "pmtu discovery on SA AH/%08x/%08x\n", diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 03f994bcf7de..a5b413416da3 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -276,7 +276,7 @@ error: static int esp_input_done2(struct sk_buff *skb, int err) { - struct iphdr *iph; + const struct iphdr *iph; struct xfrm_state *x = xfrm_input_state(skb); struct esp_data *esp = x->data; struct crypto_aead *aead = esp->aead; @@ -484,7 +484,7 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu) static void esp4_err(struct sk_buff *skb, u32 info) { struct net *net = dev_net(skb->dev); - struct iphdr *iph = (struct iphdr *)skb->data; + const struct iphdr *iph = (const struct iphdr *)skb->data; struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2)); struct xfrm_state *x; @@ -492,7 +492,8 @@ static void esp4_err(struct sk_buff *skb, u32 info) icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) return; - x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET); + x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, + esph->spi, IPPROTO_ESP, AF_INET); if (!x) return; NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n", diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index e5f8a71d3a2a..74e35e5736e2 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -373,7 +373,7 @@ out_unlock: } static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in, - struct iphdr *iph, + const struct iphdr *iph, __be32 saddr, u8 tos, int type, int code, struct icmp_bxm *param) @@ -637,7 +637,7 @@ EXPORT_SYMBOL(icmp_send); static void icmp_unreach(struct sk_buff *skb) { - struct iphdr *iph; + const struct iphdr *iph; struct icmphdr *icmph; int hash, protocol; const struct net_protocol *ipprot; @@ -656,7 +656,7 @@ static void icmp_unreach(struct sk_buff *skb) goto out_err; icmph = icmp_hdr(skb); - iph = (struct iphdr *)skb->data; + iph = (const struct iphdr *)skb->data; if (iph->ihl < 5) /* Mangled header, drop. */ goto out_err; @@ -729,7 +729,7 @@ static void icmp_unreach(struct sk_buff *skb) if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) goto out; - iph = (struct iphdr *)skb->data; + iph = (const struct iphdr *)skb->data; protocol = iph->protocol; /* @@ -758,7 +758,7 @@ out_err: static void icmp_redirect(struct sk_buff *skb) { - struct iphdr *iph; + const struct iphdr *iph; if (skb->len < sizeof(struct iphdr)) goto out_err; @@ -769,7 +769,7 @@ static void icmp_redirect(struct sk_buff *skb) if (!pskb_may_pull(skb, sizeof(struct iphdr))) goto out; - iph = (struct iphdr *)skb->data; + iph = (const struct iphdr *)skb->data; switch (icmp_hdr(skb)->code & 7) { case ICMP_REDIR_NET: diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 2ada17129fce..6ffe94ca5bc9 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -124,7 +124,7 @@ static int inet_csk_diag_fill(struct sock *sk, #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) if (r->idiag_family == AF_INET6) { - struct ipv6_pinfo *np = inet6_sk(sk); + const struct ipv6_pinfo *np = inet6_sk(sk); ipv6_addr_copy((struct in6_addr *)r->id.idiag_src, &np->rcv_saddr); diff --git a/net/ipv4/inet_lro.c b/net/ipv4/inet_lro.c index 47038cb6c138..85a0f75dae64 100644 --- a/net/ipv4/inet_lro.c +++ b/net/ipv4/inet_lro.c @@ -51,8 +51,8 @@ MODULE_DESCRIPTION("Large Receive Offload (ipv4 / tcp)"); * Basic tcp checks whether packet is suitable for LRO */ -static int lro_tcp_ip_check(struct iphdr *iph, struct tcphdr *tcph, - int len, struct net_lro_desc *lro_desc) +static int lro_tcp_ip_check(const struct iphdr *iph, const struct tcphdr *tcph, + int len, const struct net_lro_desc *lro_desc) { /* check ip header: don't aggregate padded frames */ if (ntohs(iph->tot_len) != len) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index da5941f18c3c..24efd353279a 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -462,7 +462,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) by themself??? */ - struct iphdr *iph = (struct iphdr *)skb->data; + const struct iphdr *iph = (const struct iphdr *)skb->data; __be16 *p = (__be16*)(skb->data+(iph->ihl<<2)); int grehlen = (iph->ihl<<2) + 4; const int type = icmp_hdr(skb)->type; @@ -534,7 +534,7 @@ out: rcu_read_unlock(); } -static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) +static inline void ipgre_ecn_decapsulate(const struct iphdr *iph, struct sk_buff *skb) { if (INET_ECN_is_ce(iph->tos)) { if (skb->protocol == htons(ETH_P_IP)) { @@ -546,19 +546,19 @@ static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) } static inline u8 -ipgre_ecn_encapsulate(u8 tos, struct iphdr *old_iph, struct sk_buff *skb) +ipgre_ecn_encapsulate(u8 tos, const struct iphdr *old_iph, struct sk_buff *skb) { u8 inner = 0; if (skb->protocol == htons(ETH_P_IP)) inner = old_iph->tos; else if (skb->protocol == htons(ETH_P_IPV6)) - inner = ipv6_get_dsfield((struct ipv6hdr *)old_iph); + inner = ipv6_get_dsfield((const struct ipv6hdr *)old_iph); return INET_ECN_encapsulate(tos, inner); } static int ipgre_rcv(struct sk_buff *skb) { - struct iphdr *iph; + const struct iphdr *iph; u8 *h; __be16 flags; __sum16 csum = 0; @@ -697,8 +697,8 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev { struct ip_tunnel *tunnel = netdev_priv(dev); struct pcpu_tstats *tstats; - struct iphdr *old_iph = ip_hdr(skb); - struct iphdr *tiph; + const struct iphdr *old_iph = ip_hdr(skb); + const struct iphdr *tiph; u8 tos; __be16 df; struct rtable *rt; /* Route to the other host */ @@ -714,7 +714,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev if (dev->header_ops && dev->type == ARPHRD_IPGRE) { gre_hlen = 0; - tiph = (struct iphdr *)skb->data; + tiph = (const struct iphdr *)skb->data; } else { gre_hlen = tunnel->hlen; tiph = &tunnel->parms.iph; @@ -735,14 +735,14 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) else if (skb->protocol == htons(ETH_P_IPV6)) { - struct in6_addr *addr6; + const struct in6_addr *addr6; int addr_type; struct neighbour *neigh = skb_dst(skb)->neighbour; if (neigh == NULL) goto tx_error; - addr6 = (struct in6_addr *)&neigh->primary_key; + addr6 = (const struct in6_addr *)&neigh->primary_key; addr_type = ipv6_addr_type(addr6); if (addr_type == IPV6_ADDR_ANY) { @@ -766,7 +766,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev if (skb->protocol == htons(ETH_P_IP)) tos = old_iph->tos; else if (skb->protocol == htons(ETH_P_IPV6)) - tos = ipv6_get_dsfield((struct ipv6hdr *)old_iph); + tos = ipv6_get_dsfield((const struct ipv6hdr *)old_iph); } rt = ip_route_output_gre(dev_net(dev), dst, tiph->saddr, @@ -881,7 +881,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev iph->ttl = old_iph->ttl; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) else if (skb->protocol == htons(ETH_P_IPV6)) - iph->ttl = ((struct ipv6hdr *)old_iph)->hop_limit; + iph->ttl = ((const struct ipv6hdr *)old_iph)->hop_limit; #endif else iph->ttl = ip4_dst_hoplimit(&rt->dst); @@ -927,7 +927,7 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev) { struct net_device *tdev = NULL; struct ip_tunnel *tunnel; - struct iphdr *iph; + const struct iphdr *iph; int hlen = LL_MAX_HEADER; int mtu = ETH_DATA_LEN; int addend = sizeof(struct iphdr) + 4; @@ -1180,7 +1180,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) { - struct iphdr *iph = (struct iphdr *) skb_mac_header(skb); + const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); memcpy(haddr, &iph->saddr, 4); return 4; } diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index d7b2b0987a3b..c8f48efc5fd3 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -268,7 +268,7 @@ int ip_local_deliver(struct sk_buff *skb) static inline int ip_rcv_options(struct sk_buff *skb) { struct ip_options *opt; - struct iphdr *iph; + const struct iphdr *iph; struct net_device *dev = skb->dev; /* It looks as overkill, because not all @@ -374,7 +374,7 @@ drop: */ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { - struct iphdr *iph; + const struct iphdr *iph; u32 len; /* When the interface is in promisc. mode, drop all the crap diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 3948c86e59ca..9640900309bb 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -131,7 +131,7 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb) static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb) { struct sockaddr_in sin; - struct iphdr *iph = ip_hdr(skb); + const struct iphdr *iph = ip_hdr(skb); __be16 *ports = (__be16 *)skb_transport_header(skb); if (skb_transport_offset(skb) + 4 > skb->len) diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 629067571f02..c857f6f49b03 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -27,7 +27,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) { struct net *net = dev_net(skb->dev); __be32 spi; - struct iphdr *iph = (struct iphdr *)skb->data; + const struct iphdr *iph = (const struct iphdr *)skb->data; struct ip_comp_hdr *ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2)); struct xfrm_state *x; @@ -36,7 +36,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) return; spi = htonl(ntohs(ipch->cpi)); - x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, + x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET); if (!x) return; diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index bfc17c5914e7..ef16377ec73f 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -319,7 +319,7 @@ static int ipip_err(struct sk_buff *skb, u32 info) 8 bytes of packet payload. It means, that precise relaying of ICMP in the real Internet is absolutely infeasible. */ - struct iphdr *iph = (struct iphdr *)skb->data; + const struct iphdr *iph = (const struct iphdr *)skb->data; const int type = icmp_hdr(skb)->type; const int code = icmp_hdr(skb)->code; struct ip_tunnel *t; @@ -433,12 +433,12 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); struct pcpu_tstats *tstats; - struct iphdr *tiph = &tunnel->parms.iph; + const struct iphdr *tiph = &tunnel->parms.iph; u8 tos = tunnel->parms.iph.tos; __be16 df = tiph->frag_off; struct rtable *rt; /* Route to the other host */ struct net_device *tdev; /* Device to other host */ - struct iphdr *old_iph = ip_hdr(skb); + const struct iphdr *old_iph = ip_hdr(skb); struct iphdr *iph; /* Our new IP header */ unsigned int max_headroom; /* The extra header space needed */ __be32 dst = tiph->daddr; @@ -572,7 +572,7 @@ static void ipip_tunnel_bind_dev(struct net_device *dev) { struct net_device *tdev = NULL; struct ip_tunnel *tunnel; - struct iphdr *iph; + const struct iphdr *iph; tunnel = netdev_priv(dev); iph = &tunnel->parms.iph; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 1f62eaeb6de4..c81b9b661d26 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1549,7 +1549,7 @@ static struct notifier_block ip_mr_notifier = { static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) { struct iphdr *iph; - struct iphdr *old_iph = ip_hdr(skb); + const struct iphdr *old_iph = ip_hdr(skb); skb_push(skb, sizeof(struct iphdr)); skb->transport_header = skb->network_header; diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 31427fb57aa8..99cfa28b6d38 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -153,7 +153,7 @@ void nf_nat_set_seq_adjust(struct nf_conn *ct, enum ip_conntrack_info ctinfo, } EXPORT_SYMBOL_GPL(nf_nat_set_seq_adjust); -static void nf_nat_csum(struct sk_buff *skb, struct iphdr *iph, void *data, +static void nf_nat_csum(struct sk_buff *skb, const struct iphdr *iph, void *data, int datalen, __sum16 *check, int oldlen) { struct rtable *rt = skb_rtable(skb); diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 2b50cc2da90a..abf14dbcb3b9 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -154,7 +154,7 @@ static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb) * RFC 1122: SHOULD pass TOS value up to the transport layer. * -> It does. And not only TOS, but all IP header. */ -static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash) +static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) { struct sock *sk; struct hlist_head *head; @@ -247,7 +247,7 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info) } if (inet->recverr) { - struct iphdr *iph = (struct iphdr *)skb->data; + const struct iphdr *iph = (const struct iphdr *)skb->data; u8 *payload = skb->data + (iph->ihl << 2); if (inet->hdrincl) @@ -265,7 +265,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) { int hash; struct sock *raw_sk; - struct iphdr *iph; + const struct iphdr *iph; struct net *net; hash = protocol & (RAW_HTABLE_SIZE - 1); @@ -273,7 +273,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) read_lock(&raw_v4_hashinfo.lock); raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); if (raw_sk != NULL) { - iph = (struct iphdr *)skb->data; + iph = (const struct iphdr *)skb->data; net = dev_net(skb->dev); while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol, @@ -281,7 +281,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) skb->dev->ifindex)) != NULL) { raw_err(raw_sk, skb, info); raw_sk = sk_next(raw_sk); - iph = (struct iphdr *)skb->data; + iph = (const struct iphdr *)skb->data; } } read_unlock(&raw_v4_hashinfo.lock); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index e9aee81de3e3..f4b7f806afd8 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1507,7 +1507,7 @@ static inline unsigned short guess_mtu(unsigned short old_mtu) return 68; } -unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph, +unsigned short ip_rt_frag_needed(struct net *net, const struct iphdr *iph, unsigned short new_mtu, struct net_device *dev) { diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index f7e6c2c2d2bb..edf18bd74b87 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -279,7 +279,7 @@ EXPORT_SYMBOL(tcp_v4_connect); /* * This routine does path mtu discovery as defined in RFC1191. */ -static void do_pmtu_discovery(struct sock *sk, struct iphdr *iph, u32 mtu) +static void do_pmtu_discovery(struct sock *sk, const struct iphdr *iph, u32 mtu) { struct dst_entry *dst; struct inet_sock *inet = inet_sk(sk); @@ -341,7 +341,7 @@ static void do_pmtu_discovery(struct sock *sk, struct iphdr *iph, u32 mtu) void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) { - struct iphdr *iph = (struct iphdr *)icmp_skb->data; + const struct iphdr *iph = (const struct iphdr *)icmp_skb->data; struct tcphdr *th = (struct tcphdr *)(icmp_skb->data + (iph->ihl << 2)); struct inet_connection_sock *icsk; struct tcp_sock *tp; @@ -2527,7 +2527,7 @@ void tcp4_proc_exit(void) struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) { - struct iphdr *iph = skb_gro_network_header(skb); + const struct iphdr *iph = skb_gro_network_header(skb); switch (skb->ip_summed) { case CHECKSUM_COMPLETE: @@ -2548,7 +2548,7 @@ struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) int tcp4_gro_complete(struct sk_buff *skb) { - struct iphdr *iph = ip_hdr(skb); + const struct iphdr *iph = ip_hdr(skb); struct tcphdr *th = tcp_hdr(skb); th->check = ~tcp_v4_check(skb->len - skb_transport_offset(skb), diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index a15c8fb653af..bc0dab2593e0 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -578,7 +578,7 @@ found: void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable) { struct inet_sock *inet; - struct iphdr *iph = (struct iphdr *)skb->data; + const struct iphdr *iph = (const struct iphdr *)skb->data; struct udphdr *uh = (struct udphdr *)(skb->data+(iph->ihl<<2)); const int type = icmp_hdr(skb)->type; const int code = icmp_hdr(skb)->code; diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index d20a05e970d8..59b1340fb3bf 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -102,7 +102,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, static void _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) { - struct iphdr *iph = ip_hdr(skb); + const struct iphdr *iph = ip_hdr(skb); u8 *xprth = skb_network_header(skb) + iph->ihl * 4; struct flowi4 *fl4 = &fl->u.ip4; diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 1717c64628d1..ea983ae96ae6 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c @@ -55,7 +55,7 @@ xfrm4_init_temprop(struct xfrm_state *x, const struct xfrm_tmpl *tmpl, int xfrm4_extract_header(struct sk_buff *skb) { - struct iphdr *iph = ip_hdr(skb); + const struct iphdr *iph = ip_hdr(skb); XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph); XFRM_MODE_SKB_CB(skb)->id = iph->id; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 129d7e1f311c..c663a3b70924 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1283,7 +1283,7 @@ static int ipv6_count_addresses(struct inet6_dev *idev) return cnt; } -int ipv6_chk_addr(struct net *net, struct in6_addr *addr, +int ipv6_chk_addr(struct net *net, const struct in6_addr *addr, struct net_device *dev, int strict) { struct inet6_ifaddr *ifp; @@ -1326,7 +1326,7 @@ static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, return false; } -int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) +int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev) { struct inet6_dev *idev; struct inet6_ifaddr *ifa; @@ -1457,7 +1457,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) /* Join to solicited addr multicast group. */ -void addrconf_join_solict(struct net_device *dev, struct in6_addr *addr) +void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) { struct in6_addr maddr; @@ -1468,7 +1468,7 @@ void addrconf_join_solict(struct net_device *dev, struct in6_addr *addr) ipv6_dev_mc_inc(dev, &maddr); } -void addrconf_leave_solict(struct inet6_dev *idev, struct in6_addr *addr) +void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) { struct in6_addr maddr; @@ -2113,7 +2113,7 @@ err_exit: /* * Manual configuration of address on an interface */ -static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, +static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *pfx, unsigned int plen, __u8 ifa_flags, __u32 prefered_lft, __u32 valid_lft) { @@ -2187,7 +2187,7 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, return PTR_ERR(ifp); } -static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, +static int inet6_addr_del(struct net *net, int ifindex, const struct in6_addr *pfx, unsigned int plen) { struct inet6_ifaddr *ifp; @@ -2350,7 +2350,7 @@ static void init_loopback(struct net_device *dev) add_addr(idev, &in6addr_loopback, 128, IFA_HOST); } -static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) +static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) { struct inet6_ifaddr * ifp; u32 addr_flags = IFA_F_PERMANENT; @@ -3121,7 +3121,7 @@ void if6_proc_exit(void) #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) /* Check if address is a home address configured on any interface. */ -int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) +int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr) { int ret = 0; struct inet6_ifaddr *ifp = NULL; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index afcc7099f96d..b7919f901fbf 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -740,7 +740,7 @@ static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto) static int ipv6_gso_send_check(struct sk_buff *skb) { - struct ipv6hdr *ipv6h; + const struct ipv6hdr *ipv6h; const struct inet6_protocol *ops; int err = -EINVAL; diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 0e5e943446f0..674255f5e6b7 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -44,7 +44,7 @@ #include -static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr); +static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr); /* Big ac list lock for all the sockets */ static DEFINE_RWLOCK(ipv6_sk_ac_lock); @@ -54,7 +54,7 @@ static DEFINE_RWLOCK(ipv6_sk_ac_lock); * socket join an anycast group */ -int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) +int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) { struct ipv6_pinfo *np = inet6_sk(sk); struct net_device *dev = NULL; @@ -145,7 +145,7 @@ error: /* * socket leave an anycast group */ -int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr) +int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) { struct ipv6_pinfo *np = inet6_sk(sk); struct net_device *dev; @@ -252,7 +252,7 @@ static void aca_put(struct ifacaddr6 *ac) /* * device anycast group inc (add if not found) */ -int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr) +int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr) { struct ifacaddr6 *aca; struct inet6_dev *idev; @@ -324,7 +324,7 @@ out: /* * device anycast group decrement */ -int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr) +int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr) { struct ifacaddr6 *aca, *prev_aca; @@ -358,7 +358,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr) } /* called with rcu_read_lock() */ -static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr) +static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr) { struct inet6_dev *idev = __in6_dev_get(dev); @@ -371,7 +371,7 @@ static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr) * check if the interface has this anycast address * called with rcu_read_lock() */ -static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr) +static int ipv6_chk_acast_dev(struct net_device *dev, const struct in6_addr *addr) { struct inet6_dev *idev; struct ifacaddr6 *aca; @@ -392,7 +392,7 @@ static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr) * check if given interface (or any, if dev==0) has this anycast address */ int ipv6_chk_acast_addr(struct net *net, struct net_device *dev, - struct in6_addr *addr) + const struct in6_addr *addr) { int found = 0; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 5aa8ec88f194..e97b4b7ca2f2 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -430,7 +430,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, u8 type, u8 code, int offset, __be32 info) { struct net *net = dev_net(skb->dev); - struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; + const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data; struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data + offset); struct xfrm_state *x; @@ -438,7 +438,8 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, type != ICMPV6_PKT_TOOBIG) return; - x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); + x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, + esph->spi, IPPROTO_ESP, AF_INET6); if (!x) return; printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%pI6\n", diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 83cb4f9add81..11900417b1cc 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -372,7 +372,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) struct ipv6hdr *hdr = ipv6_hdr(skb); struct sock *sk; struct ipv6_pinfo *np; - struct in6_addr *saddr = NULL; + const struct in6_addr *saddr = NULL; struct dst_entry *dst; struct icmp6hdr tmp_hdr; struct flowi6 fl6; @@ -521,7 +521,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) struct sock *sk; struct inet6_dev *idev; struct ipv6_pinfo *np; - struct in6_addr *saddr = NULL; + const struct in6_addr *saddr = NULL; struct icmp6hdr *icmph = icmp6_hdr(skb); struct icmp6hdr tmp_hdr; struct flowi6 fl6; @@ -645,8 +645,8 @@ static int icmpv6_rcv(struct sk_buff *skb) { struct net_device *dev = skb->dev; struct inet6_dev *idev = __in6_dev_get(dev); - struct in6_addr *saddr, *daddr; - struct ipv6hdr *orig_hdr; + const struct in6_addr *saddr, *daddr; + const struct ipv6hdr *orig_hdr; struct icmp6hdr *hdr; u8 type; diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 7548905e79e1..dd88df0a5d7f 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -134,9 +134,9 @@ static __inline__ u32 fib6_new_sernum(void) # define BITOP_BE32_SWIZZLE 0 #endif -static __inline__ __be32 addr_bit_set(void *token, int fn_bit) +static __inline__ __be32 addr_bit_set(const void *token, int fn_bit) { - __be32 *addr = token; + const __be32 *addr = token; /* * Here, * 1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f) @@ -822,7 +822,7 @@ st_failure: struct lookup_args { int offset; /* key offset on rt6_info */ - struct in6_addr *addr; /* search key */ + const struct in6_addr *addr; /* search key */ }; static struct fib6_node * fib6_lookup_1(struct fib6_node *root, @@ -881,8 +881,8 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root, return NULL; } -struct fib6_node * fib6_lookup(struct fib6_node *root, struct in6_addr *daddr, - struct in6_addr *saddr) +struct fib6_node * fib6_lookup(struct fib6_node *root, const struct in6_addr *daddr, + const struct in6_addr *saddr) { struct fib6_node *fn; struct lookup_args args[] = { @@ -916,7 +916,7 @@ struct fib6_node * fib6_lookup(struct fib6_node *root, struct in6_addr *daddr, static struct fib6_node * fib6_locate_1(struct fib6_node *root, - struct in6_addr *addr, + const struct in6_addr *addr, int plen, int offset) { struct fib6_node *fn; @@ -946,8 +946,8 @@ static struct fib6_node * fib6_locate_1(struct fib6_node *root, } struct fib6_node * fib6_locate(struct fib6_node *root, - struct in6_addr *daddr, int dst_len, - struct in6_addr *saddr, int src_len) + const struct in6_addr *daddr, int dst_len, + const struct in6_addr *saddr, int src_len) { struct fib6_node *fn; diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index a83e9209cecc..027c7ff6f1e5 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -57,7 +57,7 @@ inline int ip6_rcv_finish( struct sk_buff *skb) int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { - struct ipv6hdr *hdr; + const struct ipv6hdr *hdr; u32 pkt_len; struct inet6_dev *idev; struct net *net = dev_net(skb->dev); @@ -186,7 +186,7 @@ resubmit: int ret; if (ipprot->flags & INET6_PROTO_FINAL) { - struct ipv6hdr *hdr; + const struct ipv6hdr *hdr; /* Free reference early: we don't need it any more, and it may hold ip_conntrack module loaded @@ -242,7 +242,7 @@ int ip6_input(struct sk_buff *skb) int ip6_mc_input(struct sk_buff *skb) { - struct ipv6hdr *hdr; + const struct ipv6hdr *hdr; int deliver; IP6_UPD_PO_STATS_BH(dev_net(skb_dst(skb)->dev), diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index c614d02bf429..4cfbb24b9e04 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -869,9 +869,9 @@ fail: return err; } -static inline int ip6_rt_check(struct rt6key *rt_key, - struct in6_addr *fl_addr, - struct in6_addr *addr_cache) +static inline int ip6_rt_check(const struct rt6key *rt_key, + const struct in6_addr *fl_addr, + const struct in6_addr *addr_cache) { return (rt_key->plen != 128 || !ipv6_addr_equal(fl_addr, &rt_key->addr)) && (addr_cache == NULL || !ipv6_addr_equal(fl_addr, addr_cache)); @@ -879,7 +879,7 @@ static inline int ip6_rt_check(struct rt6key *rt_key, static struct dst_entry *ip6_sk_dst_check(struct sock *sk, struct dst_entry *dst, - struct flowi6 *fl6) + const struct flowi6 *fl6) { struct ipv6_pinfo *np = inet6_sk(sk); struct rt6_info *rt = (struct rt6_info *)dst; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index c1b1bd312df2..9dd0e964b8bd 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -162,7 +162,7 @@ static inline void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst) for (t = rcu_dereference(start); t; t = rcu_dereference(t->next)) static struct ip6_tnl * -ip6_tnl_lookup(struct net *net, struct in6_addr *remote, struct in6_addr *local) +ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_addr *local) { unsigned int h0 = HASH(remote); unsigned int h1 = HASH(local); @@ -194,10 +194,10 @@ ip6_tnl_lookup(struct net *net, struct in6_addr *remote, struct in6_addr *local) **/ static struct ip6_tnl __rcu ** -ip6_tnl_bucket(struct ip6_tnl_net *ip6n, struct ip6_tnl_parm *p) +ip6_tnl_bucket(struct ip6_tnl_net *ip6n, const struct ip6_tnl_parm *p) { - struct in6_addr *remote = &p->raddr; - struct in6_addr *local = &p->laddr; + const struct in6_addr *remote = &p->raddr; + const struct in6_addr *local = &p->laddr; unsigned h = 0; int prio = 0; @@ -321,8 +321,8 @@ failed: static struct ip6_tnl *ip6_tnl_locate(struct net *net, struct ip6_tnl_parm *p, int create) { - struct in6_addr *remote = &p->raddr; - struct in6_addr *local = &p->laddr; + const struct in6_addr *remote = &p->raddr; + const struct in6_addr *local = &p->laddr; struct ip6_tnl __rcu **tp; struct ip6_tnl *t; struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); @@ -374,7 +374,7 @@ ip6_tnl_dev_uninit(struct net_device *dev) static __u16 parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) { - struct ipv6hdr *ipv6h = (struct ipv6hdr *) raw; + const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw; __u8 nexthdr = ipv6h->nexthdr; __u16 off = sizeof (*ipv6h); @@ -435,7 +435,7 @@ static int ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, u8 *type, u8 *code, int *msg, __u32 *info, int offset) { - struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; + const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) skb->data; struct ip6_tnl *t; int rel_msg = 0; u8 rel_type = ICMPV6_DEST_UNREACH; @@ -535,7 +535,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, __u32 rel_info = ntohl(info); int err; struct sk_buff *skb2; - struct iphdr *eiph; + const struct iphdr *eiph; struct rtable *rt; err = ip6_tnl_err(skb, IPPROTO_IPIP, opt, &rel_type, &rel_code, @@ -669,8 +669,8 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, return 0; } -static void ip4ip6_dscp_ecn_decapsulate(struct ip6_tnl *t, - struct ipv6hdr *ipv6h, +static void ip4ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t, + const struct ipv6hdr *ipv6h, struct sk_buff *skb) { __u8 dsfield = ipv6_get_dsfield(ipv6h) & ~INET_ECN_MASK; @@ -682,8 +682,8 @@ static void ip4ip6_dscp_ecn_decapsulate(struct ip6_tnl *t, IP_ECN_set_ce(ip_hdr(skb)); } -static void ip6ip6_dscp_ecn_decapsulate(struct ip6_tnl *t, - struct ipv6hdr *ipv6h, +static void ip6ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t, + const struct ipv6hdr *ipv6h, struct sk_buff *skb) { if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) @@ -726,12 +726,12 @@ static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, __u8 ipproto, - void (*dscp_ecn_decapsulate)(struct ip6_tnl *t, - struct ipv6hdr *ipv6h, + void (*dscp_ecn_decapsulate)(const struct ip6_tnl *t, + const struct ipv6hdr *ipv6h, struct sk_buff *skb)) { struct ip6_tnl *t; - struct ipv6hdr *ipv6h = ipv6_hdr(skb); + const struct ipv6hdr *ipv6h = ipv6_hdr(skb); rcu_read_lock(); @@ -828,7 +828,7 @@ static void init_tel_txopt(struct ipv6_tel_txoption *opt, __u8 encap_limit) **/ static inline int -ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr) +ip6_tnl_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr) { return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); } @@ -1005,7 +1005,7 @@ static inline int ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); - struct iphdr *iph = ip_hdr(skb); + const struct iphdr *iph = ip_hdr(skb); int encap_limit = -1; struct flowi6 fl6; __u8 dsfield; diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 29e48593bf22..82a809901f8e 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -989,8 +989,8 @@ static int mif6_add(struct net *net, struct mr6_table *mrt, } static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt, - struct in6_addr *origin, - struct in6_addr *mcastgrp) + const struct in6_addr *origin, + const struct in6_addr *mcastgrp) { int line = MFC6_HASH(mcastgrp, origin); struct mfc6_cache *c; diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 85cccd6ed0b7..bba658d9a03c 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -55,7 +55,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, { struct net *net = dev_net(skb->dev); __be32 spi; - struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; + const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data; struct ip_comp_hdr *ipcomph = (struct ip_comp_hdr *)(skb->data + offset); struct xfrm_state *x; @@ -64,7 +64,8 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, return; spi = htonl(ntohs(ipcomph->cpi)); - x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); + x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, + spi, IPPROTO_COMP, AF_INET6); if (!x) return; diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 76b893771e6e..ff62e33ead07 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -92,16 +92,16 @@ static void mld_gq_timer_expire(unsigned long data); static void mld_ifc_timer_expire(unsigned long data); static void mld_ifc_event(struct inet6_dev *idev); static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc); -static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *addr); +static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *addr); static void mld_clear_delrec(struct inet6_dev *idev); static int sf_setstate(struct ifmcaddr6 *pmc); static void sf_markstate(struct ifmcaddr6 *pmc); static void ip6_mc_clear_src(struct ifmcaddr6 *pmc); -static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca, - int sfmode, int sfcount, struct in6_addr *psfsrc, +static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca, + int sfmode, int sfcount, const struct in6_addr *psfsrc, int delta); -static int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca, - int sfmode, int sfcount, struct in6_addr *psfsrc, +static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca, + int sfmode, int sfcount, const struct in6_addr *psfsrc, int delta); static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, struct inet6_dev *idev); @@ -250,7 +250,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) /* called with rcu_read_lock() */ static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net, - struct in6_addr *group, + const struct in6_addr *group, int ifindex) { struct net_device *dev = NULL; @@ -451,7 +451,7 @@ done: int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) { - struct in6_addr *group; + const struct in6_addr *group; struct ipv6_mc_socklist *pmc; struct inet6_dev *idev; struct ipv6_pinfo *inet6 = inet6_sk(sk); @@ -542,7 +542,7 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, struct group_filter __user *optval, int __user *optlen) { int err, i, count, copycount; - struct in6_addr *group; + const struct in6_addr *group; struct ipv6_mc_socklist *pmc; struct inet6_dev *idev; struct ipv6_pinfo *inet6 = inet6_sk(sk); @@ -752,7 +752,7 @@ static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im) spin_unlock_bh(&idev->mc_lock); } -static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *pmca) +static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *pmca) { struct ifmcaddr6 *pmc, *pmc_prev; struct ip6_sf_list *psf, *psf_next; @@ -1052,7 +1052,7 @@ static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime) /* mark EXCLUDE-mode sources */ static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, - struct in6_addr *srcs) + const struct in6_addr *srcs) { struct ip6_sf_list *psf; int i, scount; @@ -1080,7 +1080,7 @@ static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, } static int mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, - struct in6_addr *srcs) + const struct in6_addr *srcs) { struct ip6_sf_list *psf; int i, scount; @@ -1115,7 +1115,7 @@ int igmp6_event_query(struct sk_buff *skb) { struct mld2_query *mlh2 = NULL; struct ifmcaddr6 *ma; - struct in6_addr *group; + const struct in6_addr *group; unsigned long max_delay; struct inet6_dev *idev; struct mld_msg *mld; @@ -1821,7 +1821,7 @@ err_out: } static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, - struct in6_addr *psfsrc) + const struct in6_addr *psfsrc) { struct ip6_sf_list *psf, *psf_prev; int rv = 0; @@ -1857,8 +1857,8 @@ static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, return rv; } -static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca, - int sfmode, int sfcount, struct in6_addr *psfsrc, +static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca, + int sfmode, int sfcount, const struct in6_addr *psfsrc, int delta) { struct ifmcaddr6 *pmc; @@ -1918,7 +1918,7 @@ static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca, * Add multicast single-source filter to the interface list */ static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode, - struct in6_addr *psfsrc, int delta) + const struct in6_addr *psfsrc, int delta) { struct ip6_sf_list *psf, *psf_prev; @@ -2021,8 +2021,8 @@ static int sf_setstate(struct ifmcaddr6 *pmc) /* * Add multicast source filter list to the interface list */ -static int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca, - int sfmode, int sfcount, struct in6_addr *psfsrc, +static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca, + int sfmode, int sfcount, const struct in6_addr *psfsrc, int delta) { struct ifmcaddr6 *pmc; diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 9b210482fb05..43242e6e6103 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c @@ -126,7 +126,7 @@ static struct mip6_report_rate_limiter mip6_report_rl = { static int mip6_destopt_input(struct xfrm_state *x, struct sk_buff *skb) { - struct ipv6hdr *iph = ipv6_hdr(skb); + const struct ipv6hdr *iph = ipv6_hdr(skb); struct ipv6_destopt_hdr *destopt = (struct ipv6_destopt_hdr *)skb->data; int err = destopt->nexthdr; @@ -181,8 +181,8 @@ static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb) } static inline int mip6_report_rl_allow(struct timeval *stamp, - struct in6_addr *dst, - struct in6_addr *src, int iif) + const struct in6_addr *dst, + const struct in6_addr *src, int iif) { int allow = 0; @@ -349,7 +349,7 @@ static const struct xfrm_type mip6_destopt_type = static int mip6_rthdr_input(struct xfrm_state *x, struct sk_buff *skb) { - struct ipv6hdr *iph = ipv6_hdr(skb); + const struct ipv6hdr *iph = ipv6_hdr(skb); struct rt2_hdr *rt2 = (struct rt2_hdr *)skb->data; int err = rt2->rt_hdr.nexthdr; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 01a0ffc7b402..69aacd18e066 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -324,7 +324,7 @@ static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p, return lladdr + prepad; } -int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir) +int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev, int dir) { switch (dev->type) { case ARPHRD_ETHER: @@ -748,8 +748,8 @@ static int pndisc_is_router(const void *pkey, static void ndisc_recv_ns(struct sk_buff *skb) { struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); - struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; - struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; + const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; + const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; u8 *lladdr = NULL; u32 ndoptlen = skb->tail - (skb->transport_header + offsetof(struct nd_msg, opt)); @@ -924,8 +924,8 @@ out: static void ndisc_recv_na(struct sk_buff *skb) { struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); - struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; - struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; + const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; + const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; u8 *lladdr = NULL; u32 ndoptlen = skb->tail - (skb->transport_header + offsetof(struct nd_msg, opt)); @@ -1038,7 +1038,7 @@ static void ndisc_recv_rs(struct sk_buff *skb) unsigned long ndoptlen = skb->len - sizeof(*rs_msg); struct neighbour *neigh; struct inet6_dev *idev; - struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; + const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; struct ndisc_options ndopts; u8 *lladdr = NULL; @@ -1435,8 +1435,8 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) { struct inet6_dev *in6_dev; struct icmp6hdr *icmph; - struct in6_addr *dest; - struct in6_addr *target; /* new first hop to destination */ + const struct in6_addr *dest; + const struct in6_addr *target; /* new first hop to destination */ struct neighbour *neigh; int on_link = 0; struct ndisc_options ndopts; @@ -1469,7 +1469,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) } icmph = icmp6_hdr(skb); - target = (struct in6_addr *) (icmph + 1); + target = (const struct in6_addr *) (icmph + 1); dest = target + 1; if (ipv6_addr_is_multicast(dest)) { diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 28bc1f644b7b..30fcee465448 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -13,7 +13,7 @@ int ip6_route_me_harder(struct sk_buff *skb) { struct net *net = dev_net(skb_dst(skb)->dev); - struct ipv6hdr *iph = ipv6_hdr(skb); + const struct ipv6hdr *iph = ipv6_hdr(skb); struct dst_entry *dst; struct flowi6 fl6 = { .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, @@ -67,7 +67,7 @@ static void nf_ip6_saveroute(const struct sk_buff *skb, struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); if (entry->hook == NF_INET_LOCAL_OUT) { - struct ipv6hdr *iph = ipv6_hdr(skb); + const struct ipv6hdr *iph = ipv6_hdr(skb); rt_info->daddr = iph->daddr; rt_info->saddr = iph->saddr; @@ -81,7 +81,7 @@ static int nf_ip6_reroute(struct sk_buff *skb, struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); if (entry->hook == NF_INET_LOCAL_OUT) { - struct ipv6hdr *iph = ipv6_hdr(skb); + const struct ipv6hdr *iph = ipv6_hdr(skb); if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || !ipv6_addr_equal(&iph->saddr, &rt_info->saddr) || skb->mark != rt_info->mark) @@ -108,7 +108,7 @@ static int nf_ip6_route(struct net *net, struct dst_entry **dst, __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol) { - struct ipv6hdr *ip6h = ipv6_hdr(skb); + const struct ipv6hdr *ip6h = ipv6_hdr(skb); __sum16 csum = 0; switch (skb->ip_summed) { @@ -142,7 +142,7 @@ static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, unsigned int len, u_int8_t protocol) { - struct ipv6hdr *ip6h = ipv6_hdr(skb); + const struct ipv6hdr *ip6h = ipv6_hdr(skb); __wsum hsum; __sum16 csum = 0; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 4a1c3b46c56b..e5e5425fe7d0 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -67,8 +67,8 @@ static struct raw_hashinfo raw_v6_hashinfo = { }; static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, - unsigned short num, struct in6_addr *loc_addr, - struct in6_addr *rmt_addr, int dif) + unsigned short num, const struct in6_addr *loc_addr, + const struct in6_addr *rmt_addr, int dif) { struct hlist_node *node; int is_multicast = ipv6_addr_is_multicast(loc_addr); @@ -154,8 +154,8 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister); */ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) { - struct in6_addr *saddr; - struct in6_addr *daddr; + const struct in6_addr *saddr; + const struct in6_addr *daddr; struct sock *sk; int delivered = 0; __u8 hash; @@ -348,7 +348,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, { struct sock *sk; int hash; - struct in6_addr *saddr, *daddr; + const struct in6_addr *saddr, *daddr; struct net *net; hash = nexthdr & (RAW_HTABLE_SIZE - 1); @@ -357,7 +357,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, sk = sk_head(&raw_v6_hashinfo.ht[hash]); if (sk != NULL) { /* Note: ipv6_hdr(skb) != skb->data */ - struct ipv6hdr *ip6h = (struct ipv6hdr *)skb->data; + const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data; saddr = &ip6h->saddr; daddr = &ip6h->daddr; net = dev_net(skb->dev); @@ -1231,7 +1231,7 @@ struct proto rawv6_prot = { static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) { struct ipv6_pinfo *np = inet6_sk(sp); - struct in6_addr *dest, *src; + const struct in6_addr *dest, *src; __u16 destp, srcp; dest = &np->daddr; diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 07beeb06f752..7b954e2539d0 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -224,7 +224,7 @@ out: } static __inline__ struct frag_queue * -fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst) +fq_find(struct net *net, __be32 id, const struct in6_addr *src, const struct in6_addr *dst) { struct inet_frag_queue *q; struct ip6_create_arg arg; @@ -535,7 +535,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb) { struct frag_hdr *fhdr; struct frag_queue *fq; - struct ipv6hdr *hdr = ipv6_hdr(skb); + const struct ipv6hdr *hdr = ipv6_hdr(skb); struct net *net = dev_net(skb_dst(skb)->dev); IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index af26cc1073cb..852fc28ca818 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -89,12 +89,12 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); #ifdef CONFIG_IPV6_ROUTE_INFO static struct rt6_info *rt6_add_route_info(struct net *net, - struct in6_addr *prefix, int prefixlen, - struct in6_addr *gwaddr, int ifindex, + const struct in6_addr *prefix, int prefixlen, + const struct in6_addr *gwaddr, int ifindex, unsigned pref); static struct rt6_info *rt6_get_route_info(struct net *net, - struct in6_addr *prefix, int prefixlen, - struct in6_addr *gwaddr, int ifindex); + const struct in6_addr *prefix, int prefixlen, + const struct in6_addr *gwaddr, int ifindex); #endif static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) @@ -283,7 +283,7 @@ static __inline__ int rt6_check_expired(const struct rt6_info *rt) time_after(jiffies, rt->rt6i_expires); } -static inline int rt6_need_strict(struct in6_addr *daddr) +static inline int rt6_need_strict(const struct in6_addr *daddr) { return ipv6_addr_type(daddr) & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK); @@ -295,7 +295,7 @@ static inline int rt6_need_strict(struct in6_addr *daddr) static inline struct rt6_info *rt6_device_match(struct net *net, struct rt6_info *rt, - struct in6_addr *saddr, + const struct in6_addr *saddr, int oif, int flags) { @@ -507,7 +507,7 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) #ifdef CONFIG_IPV6_ROUTE_INFO int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, - struct in6_addr *gwaddr) + const struct in6_addr *gwaddr) { struct net *net = dev_net(dev); struct route_info *rinfo = (struct route_info *) opt; @@ -670,8 +670,8 @@ int ip6_ins_rt(struct rt6_info *rt) return __ip6_ins_rt(rt, &info); } -static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *daddr, - struct in6_addr *saddr) +static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_addr *daddr, + const struct in6_addr *saddr) { struct rt6_info *rt; @@ -739,7 +739,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad return rt; } -static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *daddr) +static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, const struct in6_addr *daddr) { struct rt6_info *rt = ip6_rt_copy(ort); if (rt) { @@ -830,7 +830,7 @@ static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table * void ip6_route_input(struct sk_buff *skb) { - struct ipv6hdr *iph = ipv6_hdr(skb); + const struct ipv6hdr *iph = ipv6_hdr(skb); struct net *net = dev_net(skb->dev); int flags = RT6_LOOKUP_F_HAS_SADDR; struct flowi6 fl6 = { @@ -1272,7 +1272,7 @@ int ip6_route_add(struct fib6_config *cfg) } if (cfg->fc_flags & RTF_GATEWAY) { - struct in6_addr *gw_addr; + const struct in6_addr *gw_addr; int gwa_type; gw_addr = &cfg->fc_gateway; @@ -1512,9 +1512,9 @@ out: return rt; }; -static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, - struct in6_addr *src, - struct in6_addr *gateway, +static struct rt6_info *ip6_route_redirect(const struct in6_addr *dest, + const struct in6_addr *src, + const struct in6_addr *gateway, struct net_device *dev) { int flags = RT6_LOOKUP_F_HAS_SADDR; @@ -1536,8 +1536,8 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, flags, __ip6_route_redirect); } -void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, - struct in6_addr *saddr, +void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, + const struct in6_addr *saddr, struct neighbour *neigh, u8 *lladdr, int on_link) { struct rt6_info *rt, *nrt = NULL; @@ -1611,7 +1611,7 @@ out: * i.e. Path MTU discovery */ -static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr, +static void rt6_do_pmtu_disc(const struct in6_addr *daddr, const struct in6_addr *saddr, struct net *net, u32 pmtu, int ifindex) { struct rt6_info *rt, *nrt; @@ -1696,7 +1696,7 @@ out: dst_release(&rt->dst); } -void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, +void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *saddr, struct net_device *dev, u32 pmtu) { struct net *net = dev_net(dev); @@ -1756,8 +1756,8 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) #ifdef CONFIG_IPV6_ROUTE_INFO static struct rt6_info *rt6_get_route_info(struct net *net, - struct in6_addr *prefix, int prefixlen, - struct in6_addr *gwaddr, int ifindex) + const struct in6_addr *prefix, int prefixlen, + const struct in6_addr *gwaddr, int ifindex) { struct fib6_node *fn; struct rt6_info *rt = NULL; @@ -1788,8 +1788,8 @@ out: } static struct rt6_info *rt6_add_route_info(struct net *net, - struct in6_addr *prefix, int prefixlen, - struct in6_addr *gwaddr, int ifindex, + const struct in6_addr *prefix, int prefixlen, + const struct in6_addr *gwaddr, int ifindex, unsigned pref) { struct fib6_config cfg = { @@ -1817,7 +1817,7 @@ static struct rt6_info *rt6_add_route_info(struct net *net, } #endif -struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev) +struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_device *dev) { struct rt6_info *rt; struct fib6_table *table; @@ -1839,7 +1839,7 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d return rt; } -struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, +struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr, struct net_device *dev, unsigned int pref) { @@ -2049,7 +2049,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, int ip6_route_get_saddr(struct net *net, struct rt6_info *rt, - struct in6_addr *daddr, + const struct in6_addr *daddr, unsigned int prefs, struct in6_addr *saddr) { diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 43b33373adb2..34d896426701 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -452,7 +452,7 @@ out: } static int -isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) +isatap_chksrc(struct sk_buff *skb, const struct iphdr *iph, struct ip_tunnel *t) { struct ip_tunnel_prl_entry *p; int ok = 1; @@ -465,7 +465,8 @@ isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) else skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT; } else { - struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr; + const struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr; + if (ipv6_addr_is_isatap(addr6) && (addr6->s6_addr32[3] == iph->saddr) && ipv6_chk_prefix(addr6, t->dev)) @@ -499,7 +500,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info) 8 bytes of packet payload. It means, that precise relaying of ICMP in the real Internet is absolutely infeasible. */ - struct iphdr *iph = (struct iphdr*)skb->data; + const struct iphdr *iph = (const struct iphdr *)skb->data; const int type = icmp_hdr(skb)->type; const int code = icmp_hdr(skb)->code; struct ip_tunnel *t; @@ -557,7 +558,7 @@ out: return err; } -static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) +static inline void ipip6_ecn_decapsulate(const struct iphdr *iph, struct sk_buff *skb) { if (INET_ECN_is_ce(iph->tos)) IP6_ECN_set_ce(ipv6_hdr(skb)); @@ -565,7 +566,7 @@ static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) static int ipip6_rcv(struct sk_buff *skb) { - struct iphdr *iph; + const struct iphdr *iph; struct ip_tunnel *tunnel; if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) @@ -621,7 +622,7 @@ out: * comes from 6rd / 6to4 (RFC 3056) addr space. */ static inline -__be32 try_6rd(struct in6_addr *v6dst, struct ip_tunnel *tunnel) +__be32 try_6rd(const struct in6_addr *v6dst, struct ip_tunnel *tunnel) { __be32 dst = 0; @@ -664,8 +665,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, { struct ip_tunnel *tunnel = netdev_priv(dev); struct pcpu_tstats *tstats; - struct iphdr *tiph = &tunnel->parms.iph; - struct ipv6hdr *iph6 = ipv6_hdr(skb); + const struct iphdr *tiph = &tunnel->parms.iph; + const struct ipv6hdr *iph6 = ipv6_hdr(skb); u8 tos = tunnel->parms.iph.tos; __be16 df = tiph->frag_off; struct rtable *rt; /* Route to the other host */ @@ -674,7 +675,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, unsigned int max_headroom; /* The extra header space needed */ __be32 dst = tiph->daddr; int mtu; - struct in6_addr *addr6; + const struct in6_addr *addr6; int addr_type; if (skb->protocol != htons(ETH_P_IPV6)) @@ -693,7 +694,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, goto tx_error; } - addr6 = (struct in6_addr*)&neigh->primary_key; + addr6 = (const struct in6_addr*)&neigh->primary_key; addr_type = ipv6_addr_type(addr6); if ((addr_type & IPV6_ADDR_UNICAST) && @@ -718,7 +719,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, goto tx_error; } - addr6 = (struct in6_addr*)&neigh->primary_key; + addr6 = (const struct in6_addr*)&neigh->primary_key; addr_type = ipv6_addr_type(addr6); if (addr_type == IPV6_ADDR_ANY) { @@ -849,7 +850,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) { struct net_device *tdev = NULL; struct ip_tunnel *tunnel; - struct iphdr *iph; + const struct iphdr *iph; tunnel = netdev_priv(dev); iph = &tunnel->parms.iph; diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 352c26081f5d..8b9644a8b697 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -66,7 +66,7 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, static DEFINE_PER_CPU(__u32 [16 + 5 + SHA_WORKSPACE_WORDS], ipv6_cookie_scratch); -static u32 cookie_hash(struct in6_addr *saddr, struct in6_addr *daddr, +static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *daddr, __be16 sport, __be16 dport, u32 count, int c) { __u32 *tmp = __get_cpu_var(ipv6_cookie_scratch); @@ -86,7 +86,8 @@ static u32 cookie_hash(struct in6_addr *saddr, struct in6_addr *daddr, return tmp[17]; } -static __u32 secure_tcp_syn_cookie(struct in6_addr *saddr, struct in6_addr *daddr, +static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr, + const struct in6_addr *daddr, __be16 sport, __be16 dport, __u32 sseq, __u32 count, __u32 data) { @@ -96,8 +97,8 @@ static __u32 secure_tcp_syn_cookie(struct in6_addr *saddr, struct in6_addr *dadd & COOKIEMASK)); } -static __u32 check_tcp_syn_cookie(__u32 cookie, struct in6_addr *saddr, - struct in6_addr *daddr, __be16 sport, +static __u32 check_tcp_syn_cookie(__u32 cookie, const struct in6_addr *saddr, + const struct in6_addr *daddr, __be16 sport, __be16 dport, __u32 sseq, __u32 count, __u32 maxdiff) { @@ -116,7 +117,7 @@ static __u32 check_tcp_syn_cookie(__u32 cookie, struct in6_addr *saddr, __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) { - struct ipv6hdr *iph = ipv6_hdr(skb); + const struct ipv6hdr *iph = ipv6_hdr(skb); const struct tcphdr *th = tcp_hdr(skb); int mssind; const __u16 mss = *mssp; @@ -138,7 +139,7 @@ __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) static inline int cookie_check(struct sk_buff *skb, __u32 cookie) { - struct ipv6hdr *iph = ipv6_hdr(skb); + const struct ipv6hdr *iph = ipv6_hdr(skb); const struct tcphdr *th = tcp_hdr(skb); __u32 seq = ntohl(th->seq) - 1; __u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr, diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 4f49e5dd41bb..cb7658aceb6c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -76,8 +76,8 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); static void __tcp_v6_send_check(struct sk_buff *skb, - struct in6_addr *saddr, - struct in6_addr *daddr); + const struct in6_addr *saddr, + const struct in6_addr *daddr); static const struct inet_connection_sock_af_ops ipv6_mapped; static const struct inet_connection_sock_af_ops ipv6_specific; @@ -86,7 +86,7 @@ static const struct tcp_sock_af_ops tcp_sock_ipv6_specific; static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; #else static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, - struct in6_addr *addr) + const struct in6_addr *addr) { return NULL; } @@ -106,8 +106,8 @@ static void tcp_v6_hash(struct sock *sk) } static __inline__ __sum16 tcp_v6_check(int len, - struct in6_addr *saddr, - struct in6_addr *daddr, + const struct in6_addr *saddr, + const struct in6_addr *daddr, __wsum base) { return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); @@ -331,7 +331,7 @@ failure: static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, u8 type, u8 code, int offset, __be32 info) { - struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; + const struct ipv6hdr *hdr = (const struct ipv6hdr*)skb->data; const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); struct ipv6_pinfo *np; struct sock *sk; @@ -551,7 +551,7 @@ static void tcp_v6_reqsk_destructor(struct request_sock *req) #ifdef CONFIG_TCP_MD5SIG static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, - struct in6_addr *addr) + const struct in6_addr *addr) { struct tcp_sock *tp = tcp_sk(sk); int i; @@ -580,7 +580,7 @@ static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk, return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr); } -static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, +static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer, char *newkey, u8 newkeylen) { /* Add key to the list */ @@ -645,7 +645,7 @@ static int tcp_v6_md5_add_func(struct sock *sk, struct sock *addr_sk, newkey, newkeylen); } -static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) +static int tcp_v6_md5_do_del(struct sock *sk, const struct in6_addr *peer) { struct tcp_sock *tp = tcp_sk(sk); int i; @@ -753,8 +753,8 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, } static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, - struct in6_addr *daddr, - struct in6_addr *saddr, int nbytes) + const struct in6_addr *daddr, + const struct in6_addr *saddr, int nbytes) { struct tcp6_pseudohdr *bp; struct scatterlist sg; @@ -771,7 +771,7 @@ static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, } static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, - struct in6_addr *daddr, struct in6_addr *saddr, + const struct in6_addr *daddr, struct in6_addr *saddr, struct tcphdr *th) { struct tcp_md5sig_pool *hp; @@ -807,7 +807,7 @@ static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, struct sock *sk, struct request_sock *req, struct sk_buff *skb) { - struct in6_addr *saddr, *daddr; + const struct in6_addr *saddr, *daddr; struct tcp_md5sig_pool *hp; struct hash_desc *desc; struct tcphdr *th = tcp_hdr(skb); @@ -819,7 +819,7 @@ static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, saddr = &inet6_rsk(req)->loc_addr; daddr = &inet6_rsk(req)->rmt_addr; } else { - struct ipv6hdr *ip6h = ipv6_hdr(skb); + const struct ipv6hdr *ip6h = ipv6_hdr(skb); saddr = &ip6h->saddr; daddr = &ip6h->daddr; } @@ -857,7 +857,7 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) { __u8 *hash_location = NULL; struct tcp_md5sig_key *hash_expected; - struct ipv6hdr *ip6h = ipv6_hdr(skb); + const struct ipv6hdr *ip6h = ipv6_hdr(skb); struct tcphdr *th = tcp_hdr(skb); int genhash; u8 newhash[16]; @@ -915,7 +915,7 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { #endif static void __tcp_v6_send_check(struct sk_buff *skb, - struct in6_addr *saddr, struct in6_addr *daddr) + const struct in6_addr *saddr, const struct in6_addr *daddr) { struct tcphdr *th = tcp_hdr(skb); @@ -939,7 +939,7 @@ static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb) static int tcp_v6_gso_send_check(struct sk_buff *skb) { - struct ipv6hdr *ipv6h; + const struct ipv6hdr *ipv6h; struct tcphdr *th; if (!pskb_may_pull(skb, sizeof(*th))) @@ -957,7 +957,7 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb) { - struct ipv6hdr *iph = skb_gro_network_header(skb); + const struct ipv6hdr *iph = skb_gro_network_header(skb); switch (skb->ip_summed) { case CHECKSUM_COMPLETE: @@ -978,7 +978,7 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, static int tcp6_gro_complete(struct sk_buff *skb) { - struct ipv6hdr *iph = ipv6_hdr(skb); + const struct ipv6hdr *iph = ipv6_hdr(skb); struct tcphdr *th = tcp_hdr(skb); th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb), @@ -1702,7 +1702,7 @@ ipv6_pktoptions: static int tcp_v6_rcv(struct sk_buff *skb) { struct tcphdr *th; - struct ipv6hdr *hdr; + const struct ipv6hdr *hdr; struct sock *sk; int ret; struct net *net = dev_net(skb->dev); @@ -2028,8 +2028,8 @@ static void get_openreq6(struct seq_file *seq, struct sock *sk, struct request_sock *req, int i, int uid) { int ttd = req->expires - jiffies; - struct in6_addr *src = &inet6_rsk(req)->loc_addr; - struct in6_addr *dest = &inet6_rsk(req)->rmt_addr; + const struct in6_addr *src = &inet6_rsk(req)->loc_addr; + const struct in6_addr *dest = &inet6_rsk(req)->rmt_addr; if (ttd < 0) ttd = 0; @@ -2057,7 +2057,7 @@ static void get_openreq6(struct seq_file *seq, static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) { - struct in6_addr *dest, *src; + const struct in6_addr *dest, *src; __u16 destp, srcp; int timer_active; unsigned long timer_expires; @@ -2114,7 +2114,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) static void get_timewait6_sock(struct seq_file *seq, struct inet_timewait_sock *tw, int i) { - struct in6_addr *dest, *src; + const struct in6_addr *dest, *src; __u16 destp, srcp; struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); int ttd = tw->tw_ttd - jiffies; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 15c37746845e..1bdc5f053db8 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -311,7 +311,7 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, struct udp_table *udptable) { struct sock *sk; - struct ipv6hdr *iph = ipv6_hdr(skb); + const struct ipv6hdr *iph = ipv6_hdr(skb); if (unlikely(sk = skb_steal_sock(skb))) return sk; @@ -463,9 +463,9 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct udp_table *udptable) { struct ipv6_pinfo *np; - struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; - struct in6_addr *saddr = &hdr->saddr; - struct in6_addr *daddr = &hdr->daddr; + const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data; + const struct in6_addr *saddr = &hdr->saddr; + const struct in6_addr *daddr = &hdr->daddr; struct udphdr *uh = (struct udphdr*)(skb->data+offset); struct sock *sk; int err; @@ -553,8 +553,8 @@ drop_no_sk_drops_inc: } static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, - __be16 loc_port, struct in6_addr *loc_addr, - __be16 rmt_port, struct in6_addr *rmt_addr, + __be16 loc_port, const struct in6_addr *loc_addr, + __be16 rmt_port, const struct in6_addr *rmt_addr, int dif) { struct hlist_nulls_node *node; @@ -633,7 +633,7 @@ drop: * so we don't need to lock the hashes. */ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, - struct in6_addr *saddr, struct in6_addr *daddr, + const struct in6_addr *saddr, const struct in6_addr *daddr, struct udp_table *udptable) { struct sock *sk, *stack[256 / sizeof(struct sock *)]; @@ -716,7 +716,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, struct net *net = dev_net(skb->dev); struct sock *sk; struct udphdr *uh; - struct in6_addr *saddr, *daddr; + const struct in6_addr *saddr, *daddr; u32 ulen = 0; if (!pskb_may_pull(skb, sizeof(struct udphdr))) @@ -1278,7 +1278,7 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname, static int udp6_ufo_send_check(struct sk_buff *skb) { - struct ipv6hdr *ipv6h; + const struct ipv6hdr *ipv6h; struct udphdr *uh; if (!pskb_may_pull(skb, sizeof(*uh))) @@ -1382,7 +1382,7 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket { struct inet_sock *inet = inet_sk(sp); struct ipv6_pinfo *np = inet6_sk(sp); - struct in6_addr *dest, *src; + const struct in6_addr *dest, *src; __u16 destp, srcp; dest = &np->daddr; diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index bbd48b101bae..3437d7d4eed6 100644 --- a/net/ipv6/xfrm6_mode_beet.c +++ b/net/ipv6/xfrm6_mode_beet.c @@ -41,10 +41,8 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) { struct ipv6hdr *top_iph; struct ip_beet_phdr *ph; - struct iphdr *iphv4; int optlen, hdr_len; - iphv4 = ip_hdr(skb); hdr_len = 0; optlen = XFRM_MODE_SKB_CB(skb)->optlen; if (unlikely(optlen)) diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 645cb968d450..4d6edff0498f 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c @@ -20,7 +20,7 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) { - struct ipv6hdr *outer_iph = ipv6_hdr(skb); + const struct ipv6hdr *outer_iph = ipv6_hdr(skb); struct ipv6hdr *inner_iph = ipipv6_hdr(skb); if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) @@ -55,8 +55,8 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) dsfield &= ~INET_ECN_MASK; ipv6_change_dsfield(top_iph, 0, dsfield); top_iph->hop_limit = ip6_dst_hoplimit(dst->child); - ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); - ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); + ipv6_addr_copy(&top_iph->saddr, (const struct in6_addr *)&x->props.saddr); + ipv6_addr_copy(&top_iph->daddr, (const struct in6_addr *)&x->id.daddr); return 0; } diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 05e34c8ec913..d879f7efbd10 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -124,7 +124,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) struct flowi6 *fl6 = &fl->u.ip6; int onlyproto = 0; u16 offset = skb_network_header_len(skb); - struct ipv6hdr *hdr = ipv6_hdr(skb); + const struct ipv6hdr *hdr = ipv6_hdr(skb); struct ipv6_opt_hdr *exthdr; const unsigned char *nh = skb_network_header(skb); u8 nexthdr = nh[IP6CB(skb)->nhoff]; diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 2969cad408de..a6770a04e3bd 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -68,7 +68,7 @@ static DEFINE_SPINLOCK(xfrm6_tunnel_spi_lock); static struct kmem_cache *xfrm6_tunnel_spi_kmem __read_mostly; -static inline unsigned xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr) +static inline unsigned xfrm6_tunnel_spi_hash_byaddr(const xfrm_address_t *addr) { unsigned h; @@ -85,7 +85,7 @@ static inline unsigned xfrm6_tunnel_spi_hash_byspi(u32 spi) return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE; } -static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr) +static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr) { struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); struct xfrm6_tunnel_spi *x6spi; @@ -101,7 +101,7 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, xfrm_ return NULL; } -__be32 xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr) +__be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr) { struct xfrm6_tunnel_spi *x6spi; u32 spi; @@ -237,10 +237,10 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) static int xfrm6_tunnel_rcv(struct sk_buff *skb) { struct net *net = dev_net(skb->dev); - struct ipv6hdr *iph = ipv6_hdr(skb); + const struct ipv6hdr *iph = ipv6_hdr(skb); __be32 spi; - spi = xfrm6_tunnel_spi_lookup(net, (xfrm_address_t *)&iph->saddr); + spi = xfrm6_tunnel_spi_lookup(net, (const xfrm_address_t *)&iph->saddr); return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi) > 0 ? : 0; } diff --git a/net/key/af_key.c b/net/key/af_key.c index 7db86ffcf070..d62401c25684 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -712,7 +712,7 @@ static unsigned int pfkey_sockaddr_fill(const xfrm_address_t *xaddr, __be16 port sin6->sin6_family = AF_INET6; sin6->sin6_port = port; sin6->sin6_flowinfo = 0; - ipv6_addr_copy(&sin6->sin6_addr, (struct in6_addr *)xaddr->a6); + ipv6_addr_copy(&sin6->sin6_addr, (const struct in6_addr *)xaddr->a6); sin6->sin6_scope_id = 0; return 128; } diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index c2e628dfaacc..7ef87f9eb675 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -169,7 +169,7 @@ static unsigned int sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) } case htons(ETH_P_IPV6): { - struct ipv6hdr *iph; + const struct ipv6hdr *iph; int poff; if (!pskb_network_may_pull(skb, sizeof(*iph))) diff --git a/net/sctp/input.c b/net/sctp/input.c index 3a8eb79eb78b..741ed1648838 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -565,7 +565,7 @@ void sctp_err_finish(struct sock *sk, struct sctp_association *asoc) */ void sctp_v4_err(struct sk_buff *skb, __u32 info) { - struct iphdr *iph = (struct iphdr *)skb->data; + const struct iphdr *iph = (const struct iphdr *)skb->data; const int ihlen = iph->ihl * 4; const int type = icmp_hdr(skb)->type; const int code = icmp_hdr(skb)->code; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 865ce7ba4e14..321f175055bf 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -531,7 +531,7 @@ static int sctp_v6_is_any(const union sctp_addr *addr) static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp) { int type; - struct in6_addr *in6 = (struct in6_addr *)&addr->v6.sin6_addr; + const struct in6_addr *in6 = (const struct in6_addr *)&addr->v6.sin6_addr; type = ipv6_addr_type(in6); if (IPV6_ADDR_ANY == type) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index dd78536d40de..d70f85eb7864 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1036,15 +1036,15 @@ static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m, case AF_INET6: ipv6_addr_copy((struct in6_addr *)x->sel.daddr.a6, - (struct in6_addr *)daddr); + (const struct in6_addr *)daddr); ipv6_addr_copy((struct in6_addr *)x->sel.saddr.a6, - (struct in6_addr *)saddr); + (const struct in6_addr *)saddr); x->sel.prefixlen_d = 128; x->sel.prefixlen_s = 128; ipv6_addr_copy((struct in6_addr *)x->props.saddr.a6, - (struct in6_addr *)saddr); + (const struct in6_addr *)saddr); ipv6_addr_copy((struct in6_addr *)x->id.daddr.a6, - (struct in6_addr *)daddr); + (const struct in6_addr *)daddr); break; } @@ -2092,8 +2092,8 @@ static void xfrm_audit_helper_sainfo(struct xfrm_state *x, static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family, struct audit_buffer *audit_buf) { - struct iphdr *iph4; - struct ipv6hdr *iph6; + const struct iphdr *iph4; + const struct ipv6hdr *iph6; switch (family) { case AF_INET: -- cgit v1.2.3-58-ga151 From 2a9e9507011440a57d6356ded630ba0c0f5d4b77 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Apr 2011 10:54:56 -0700 Subject: net: Remove __KERNEL__ cpp checks from include/net These header files are never installed to user consumption, so any __KERNEL__ cpp checks are superfluous. Projects should also not copy these files into their userland utility sources and try to use them there. If they insist on doing so, the onus is on them to sanitize the headers as needed. Signed-off-by: David S. Miller --- include/net/addrconf.h | 3 --- include/net/af_rxrpc.h | 3 --- include/net/af_unix.h | 2 -- include/net/atmclip.h | 2 -- include/net/bluetooth/hci.h | 2 -- include/net/dst.h | 3 --- include/net/if_inet6.h | 3 --- include/net/ip6_fib.h | 3 --- include/net/ip6_route.h | 3 --- include/net/ip_vs.h | 5 ----- include/net/ipv6.h | 7 ------- include/net/ipx.h | 2 -- include/net/ndisc.h | 6 ------ include/net/netevent.h | 2 -- include/net/netfilter/nf_conntrack.h | 2 -- include/net/netfilter/nf_conntrack_tuple.h | 4 ---- include/net/netfilter/nf_nat.h | 4 ---- include/net/rawv6.h | 4 ---- include/net/route.h | 4 ---- include/net/transp_v6.h | 4 ---- include/net/wimax.h | 5 ----- 21 files changed, 73 deletions(-) diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 7c4d92c0dd1d..582e4ae70753 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -42,8 +42,6 @@ struct prefix_info { }; -#ifdef __KERNEL__ - #include #include #include @@ -285,4 +283,3 @@ extern void if6_proc_exit(void); #endif #endif -#endif diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h index 00c2eaa07c25..03e6e9453623 100644 --- a/include/net/af_rxrpc.h +++ b/include/net/af_rxrpc.h @@ -12,8 +12,6 @@ #ifndef _NET_RXRPC_H #define _NET_RXRPC_H -#ifdef __KERNEL__ - #include struct rxrpc_call; @@ -53,5 +51,4 @@ extern struct rxrpc_call *rxrpc_kernel_accept_call(struct socket *, unsigned long); extern int rxrpc_kernel_reject_call(struct socket *); -#endif /* __KERNEL__ */ #endif /* _NET_RXRPC_H */ diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 18e5c3f67580..91ab5b01678a 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -41,7 +41,6 @@ struct unix_skb_parms { spin_lock_nested(&unix_sk(s)->lock, \ SINGLE_DEPTH_NESTING) -#ifdef __KERNEL__ /* The AF_UNIX socket */ struct unix_sock { /* WARNING: sk has to be the first member */ @@ -72,4 +71,3 @@ static inline int unix_sysctl_register(struct net *net) { return 0; } static inline void unix_sysctl_unregister(struct net *net) {} #endif #endif -#endif diff --git a/include/net/atmclip.h b/include/net/atmclip.h index 467c531b8a7e..497ef6444a7a 100644 --- a/include/net/atmclip.h +++ b/include/net/atmclip.h @@ -54,8 +54,6 @@ struct clip_priv { }; -#ifdef __KERNEL__ extern struct neigh_table *clip_tbl_hook; -#endif #endif diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 6138e313d175..499b7b7c7c9a 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1067,7 +1067,6 @@ struct hci_sco_hdr { __u8 dlen; } __packed; -#ifdef __KERNEL__ #include static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb) { @@ -1083,7 +1082,6 @@ static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb) { return (struct hci_sco_hdr *) skb->data; } -#endif /* Command opcode pack/unpack */ #define hci_opcode_pack(ogf, ocf) (__u16) ((ocf & 0x03ff)|(ogf << 10)) diff --git a/include/net/dst.h b/include/net/dst.h index 75b95df4afe7..d7bb74062df1 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -92,8 +92,6 @@ struct dst_entry { }; }; -#ifdef __KERNEL__ - extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); extern const u32 dst_default_metrics[RTAX_MAX]; @@ -438,6 +436,5 @@ extern struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig const struct flowi *fl, struct sock *sk, int flags); #endif -#endif #endif /* _NET_DST_H */ diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index 3d982f72d48e..0c603fe65377 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -30,8 +30,6 @@ #define IF_PREFIX_ONLINK 0x01 #define IF_PREFIX_AUTOCONF 0x02 -#ifdef __KERNEL__ - enum { INET6_IFADDR_STATE_DAD, INET6_IFADDR_STATE_POSTDAD, @@ -303,4 +301,3 @@ static inline int ipv6_ipgre_mc_map(const struct in6_addr *addr, } #endif -#endif diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index aca8ef4dd67c..477ef75f3873 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -13,8 +13,6 @@ #ifndef _IP6_FIB_H #define _IP6_FIB_H -#ifdef __KERNEL__ - #include #include #include @@ -240,4 +238,3 @@ static inline void fib6_rules_cleanup(void) } #endif #endif -#endif diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index d5c21d4d9e7e..5e91b72fc718 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -21,8 +21,6 @@ struct route_info { __u8 prefix[0]; /* 0,8 or 16 */ }; -#ifdef __KERNEL__ - #include #include #include @@ -193,4 +191,3 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) } #endif -#endif diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index d516f00c8e0f..e0b7f139aa88 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -8,9 +8,6 @@ #include /* definitions shared with userland */ -/* old ipvsadm versions still include this file directly */ -#ifdef __KERNEL__ - #include /* for __uXX types */ #include /* for ctl_path */ @@ -1415,6 +1412,4 @@ ip_vs_dest_conn_overhead(struct ip_vs_dest *dest) atomic_read(&dest->inactconns); } -#endif /* __KERNEL__ */ - #endif /* _NET_IP_VS_H */ diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 5da192653153..e1c60b43e73b 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -77,11 +77,9 @@ /* * Addr scopes */ -#ifdef __KERNEL__ #define IPV6_ADDR_MC_SCOPE(a) \ ((a)->s6_addr[1] & 0x0f) /* nonstandard */ #define __IPV6_ADDR_SCOPE_INVALID -1 -#endif #define IPV6_ADDR_SCOPE_NODELOCAL 0x01 #define IPV6_ADDR_SCOPE_LINKLOCAL 0x02 #define IPV6_ADDR_SCOPE_SITELOCAL 0x05 @@ -91,14 +89,12 @@ /* * Addr flags */ -#ifdef __KERNEL__ #define IPV6_ADDR_MC_FLAG_TRANSIENT(a) \ ((a)->s6_addr[1] & 0x10) #define IPV6_ADDR_MC_FLAG_PREFIX(a) \ ((a)->s6_addr[1] & 0x20) #define IPV6_ADDR_MC_FLAG_RENDEZVOUS(a) \ ((a)->s6_addr[1] & 0x40) -#endif /* * fragmentation header @@ -113,8 +109,6 @@ struct frag_hdr { #define IP6_MF 0x0001 -#ifdef __KERNEL__ - #include /* sysctls */ @@ -667,5 +661,4 @@ extern int ipv6_static_sysctl_register(void); extern void ipv6_static_sysctl_unregister(void); #endif -#endif /* __KERNEL__ */ #endif /* _NET_IPV6_H */ diff --git a/include/net/ipx.h b/include/net/ipx.h index 05d7e4a88b49..c1fec6b464cc 100644 --- a/include/net/ipx.h +++ b/include/net/ipx.h @@ -80,7 +80,6 @@ struct ipx_route { atomic_t refcnt; }; -#ifdef __KERNEL__ struct ipx_cb { u8 ipx_tctrl; __be32 ipx_dest_net; @@ -116,7 +115,6 @@ static inline struct ipx_sock *ipx_sk(struct sock *sk) } #define IPX_SKB_CB(__skb) ((struct ipx_cb *)&((__skb)->cb[0])) -#endif #define IPX_MIN_EPHEMERAL_SOCKET 0x4000 #define IPX_MAX_EPHEMERAL_SOCKET 0x7fff diff --git a/include/net/ndisc.h b/include/net/ndisc.h index 6144685d601b..62beeb97c4b1 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -42,8 +42,6 @@ enum { #define ND_REACHABLE_TIME (30*HZ) #define ND_RETRANS_TIMER HZ -#ifdef __KERNEL__ - #include #include #include @@ -156,8 +154,4 @@ static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, const s return ERR_PTR(-ENODEV); } - -#endif /* __KERNEL__ */ - - #endif diff --git a/include/net/netevent.h b/include/net/netevent.h index 22b239c17eaa..086f8a5b59dc 100644 --- a/include/net/netevent.h +++ b/include/net/netevent.h @@ -10,7 +10,6 @@ * * Changes: */ -#ifdef __KERNEL__ struct dst_entry; @@ -29,4 +28,3 @@ extern int unregister_netevent_notifier(struct notifier_block *nb); extern int call_netevent_notifiers(unsigned long val, void *v); #endif -#endif diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index d0d13378991e..c7c42e7acc31 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -14,7 +14,6 @@ #include -#ifdef __KERNEL__ #include #include #include @@ -326,5 +325,4 @@ do { \ #define MODULE_ALIAS_NFCT_HELPER(helper) \ MODULE_ALIAS("nfct-helper-" helper) -#endif /* __KERNEL__ */ #endif /* _NF_CONNTRACK_H */ diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index 4ee44c84a304..7ca6bdd5bae6 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h @@ -104,8 +104,6 @@ struct nf_conntrack_tuple_mask { } src; }; -#ifdef __KERNEL__ - static inline void nf_ct_dump_tuple_ip(const struct nf_conntrack_tuple *t) { #ifdef DEBUG @@ -148,8 +146,6 @@ struct nf_conntrack_tuple_hash { struct nf_conntrack_tuple tuple; }; -#endif /* __KERNEL__ */ - static inline bool __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1, const struct nf_conntrack_tuple *t2) { diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index aff80b190c12..0346b0070864 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -48,7 +48,6 @@ struct nf_nat_multi_range_compat { struct nf_nat_range range[1]; }; -#ifdef __KERNEL__ #include #include #include @@ -93,7 +92,4 @@ static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct) #endif } -#else /* !__KERNEL__: iptables wants this to compile. */ -#define nf_nat_multi_range nf_nat_multi_range_compat -#endif /*__KERNEL__*/ #endif diff --git a/include/net/rawv6.h b/include/net/rawv6.h index f6b9b830df8c..cf7577234457 100644 --- a/include/net/rawv6.h +++ b/include/net/rawv6.h @@ -1,8 +1,6 @@ #ifndef _NET_RAWV6_H #define _NET_RAWV6_H -#ifdef __KERNEL__ - #include void raw6_icmp_error(struct sk_buff *, int nexthdr, @@ -20,5 +18,3 @@ int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock, #endif #endif - -#endif diff --git a/include/net/route.h b/include/net/route.h index b3962e249e14..3684c3edbae4 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -35,10 +35,6 @@ #include #include -#ifndef __KERNEL__ -#warning This file is not supposed to be used outside of kernel. -#endif - #define RTO_ONLINK 0x01 #define RTO_CONN 0 diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index a8122dc56410..5271a741c3a3 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -7,8 +7,6 @@ * IPv6 transport protocols */ -#ifdef __KERNEL__ - extern struct proto rawv6_prot; extern struct proto udpv6_prot; extern struct proto udplitev6_prot; @@ -57,5 +55,3 @@ extern const struct inet_connection_sock_af_ops ipv4_specific; extern void inet6_destroy_sock(struct sock *sk); #endif - -#endif diff --git a/include/net/wimax.h b/include/net/wimax.h index c799ba7b708b..7328d5019d88 100644 --- a/include/net/wimax.h +++ b/include/net/wimax.h @@ -250,7 +250,6 @@ #ifndef __NET__WIMAX_H__ #define __NET__WIMAX_H__ -#ifdef __KERNEL__ #include #include @@ -518,8 +517,4 @@ extern ssize_t wimax_msg_len(struct sk_buff *); extern int wimax_rfkill(struct wimax_dev *, enum wimax_rf_state); extern int wimax_reset(struct wimax_dev *); -#else -/* You might be looking for linux/wimax.h */ -#error This file should not be included from user space. -#endif /* #ifdef __KERNEL__ */ #endif /* #ifndef __NET__WIMAX_H__ */ -- cgit v1.2.3-58-ga151 From b99a7be47dc37c60b6524d761ecfce432de84c01 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:28:59 +0530 Subject: ath9k_hw: Define devid and mac version for AR9340 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 +- drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/reg.h | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 3a8c41c782e9..d98b4c6d8dcf 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -552,7 +552,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) return -EOPNOTSUPP; } - if (AR_SREV_9271(ah) || AR_SREV_9100(ah)) + if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah)) ah->is_pciexpress = false; ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 1018d6cbd530..450b64263bc9 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -43,6 +43,7 @@ #define AR9287_DEVID_PCI 0x002d #define AR9287_DEVID_PCIE 0x002e #define AR9300_DEVID_PCIE 0x0030 +#define AR9300_DEVID_AR9340 0x0031 #define AR9300_DEVID_AR9485_PCIE 0x0032 #define AR5416_AR9100_DEVID 0x000b diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 6acbf0e2240b..1bf540561c41 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -790,6 +790,7 @@ #define AR_SREV_VERSION_9485 0x240 #define AR_SREV_REVISION_9485_10 0 #define AR_SREV_REVISION_9485_11 1 +#define AR_SREV_VERSION_9340 0x300 #define AR_SREV_5416(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ @@ -869,6 +870,9 @@ (AR_SREV_9485(_ah) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11)) +#define AR_SREV_9340(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9340)) + #define AR_SREV_9285E_20(_ah) \ (AR_SREV_9285_12_OR_LATER(_ah) && \ ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) -- cgit v1.2.3-58-ga151 From 35d5f56125aba8667ac12277dff02ce51efbee16 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:00 +0530 Subject: ath9k_hw: Take care of few host interface register changes for AR9340 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/reg.h | 73 +++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 1bf540561c41..42d9f1b7655c 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -693,7 +693,7 @@ #define AR_RC_APB 0x00000002 #define AR_RC_HOSTIF 0x00000100 -#define AR_WA 0x4004 +#define AR_WA (AR_SREV_9340(ah) ? 0x40c4 : 0x4004) #define AR_WA_BIT6 (1 << 6) #define AR_WA_BIT7 (1 << 7) #define AR_WA_BIT23 (1 << 23) @@ -712,7 +712,7 @@ #define AR_PM_STATE 0x4008 #define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000 -#define AR_HOST_TIMEOUT 0x4018 +#define AR_HOST_TIMEOUT (AR_SREV_9340(ah) ? 0x4008 : 0x4018) #define AR_HOST_TIMEOUT_APB_CNTR 0x0000FFFF #define AR_HOST_TIMEOUT_APB_CNTR_S 0 #define AR_HOST_TIMEOUT_LCL_CNTR 0xFFFF0000 @@ -742,7 +742,8 @@ #define EEPROM_PROTECT_WP_1024_2047 0x8000 #define AR_SREV \ - ((AR_SREV_9100(ah)) ? 0x0600 : 0x4020) + ((AR_SREV_9100(ah)) ? 0x0600 : (AR_SREV_9340(ah) \ + ? 0x400c : 0x4020)) #define AR_SREV_ID \ ((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF) @@ -914,11 +915,11 @@ enum ath_usb_dev { #define AR_INTR_SPURIOUS 0xFFFFFFFF -#define AR_INTR_SYNC_CAUSE_CLR 0x4028 +#define AR_INTR_SYNC_CAUSE (AR_SREV_9340(ah) ? 0x4010 : 0x4028) +#define AR_INTR_SYNC_CAUSE_CLR (AR_SREV_9340(ah) ? 0x4010 : 0x4028) -#define AR_INTR_SYNC_CAUSE 0x4028 -#define AR_INTR_SYNC_ENABLE 0x402c +#define AR_INTR_SYNC_ENABLE (AR_SREV_9340(ah) ? 0x4014 : 0x402c) #define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000 #define AR_INTR_SYNC_ENABLE_GPIO_S 18 @@ -958,24 +959,24 @@ enum { }; -#define AR_INTR_ASYNC_MASK 0x4030 +#define AR_INTR_ASYNC_MASK (AR_SREV_9340(ah) ? 0x4018 : 0x4030) #define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 #define AR_INTR_ASYNC_MASK_GPIO_S 18 -#define AR_INTR_SYNC_MASK 0x4034 +#define AR_INTR_SYNC_MASK (AR_SREV_9340(ah) ? 0x401c : 0x4034) #define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 #define AR_INTR_SYNC_MASK_GPIO_S 18 -#define AR_INTR_ASYNC_CAUSE_CLR 0x4038 -#define AR_INTR_ASYNC_CAUSE 0x4038 +#define AR_INTR_ASYNC_CAUSE_CLR (AR_SREV_9340(ah) ? 0x4020 : 0x4038) +#define AR_INTR_ASYNC_CAUSE (AR_SREV_9340(ah) ? 0x4020 : 0x4038) -#define AR_INTR_ASYNC_ENABLE 0x403c +#define AR_INTR_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4024 : 0x403c) #define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 #define AR_INTR_ASYNC_ENABLE_GPIO_S 18 #define AR_PCIE_SERDES 0x4040 #define AR_PCIE_SERDES2 0x4044 -#define AR_PCIE_PM_CTRL 0x4014 +#define AR_PCIE_PM_CTRL (AR_SREV_9340(ah) ? 0x4004 : 0x4014) #define AR_PCIE_PM_CTRL_ENA 0x00080000 #define AR_NUM_GPIO 14 @@ -986,7 +987,7 @@ enum { #define AR9300_NUM_GPIO 17 #define AR7010_NUM_GPIO 16 -#define AR_GPIO_IN_OUT 0x4048 +#define AR_GPIO_IN_OUT (AR_SREV_9340(ah) ? 0x4028 : 0x4048) #define AR_GPIO_IN_VAL 0x0FFFC000 #define AR_GPIO_IN_VAL_S 14 #define AR928X_GPIO_IN_VAL 0x000FFC00 @@ -1000,11 +1001,12 @@ enum { #define AR7010_GPIO_IN_VAL 0x0000FFFF #define AR7010_GPIO_IN_VAL_S 0 -#define AR_GPIO_IN 0x404c +#define AR_GPIO_IN (AR_SREV_9340(ah) ? 0x402c : 0x404c) #define AR9300_GPIO_IN_VAL 0x0001FFFF #define AR9300_GPIO_IN_VAL_S 0 -#define AR_GPIO_OE_OUT (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c) +#define AR_GPIO_OE_OUT (AR_SREV_9340(ah) ? 0x4030 : \ + (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c)) #define AR_GPIO_OE_OUT_DRV 0x3 #define AR_GPIO_OE_OUT_DRV_NO 0x0 #define AR_GPIO_OE_OUT_DRV_LOW 0x1 @@ -1026,11 +1028,13 @@ enum { #define AR7010_GPIO_INT_MASK 0x52024 #define AR7010_GPIO_FUNCTION 0x52028 -#define AR_GPIO_INTR_POL (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050) +#define AR_GPIO_INTR_POL (AR_SREV_9340(ah) ? 0x4038 : \ + (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050)) #define AR_GPIO_INTR_POL_VAL 0x0001FFFF #define AR_GPIO_INTR_POL_VAL_S 0 -#define AR_GPIO_INPUT_EN_VAL (AR_SREV_9300_20_OR_LATER(ah) ? 0x405c : 0x4054) +#define AR_GPIO_INPUT_EN_VAL (AR_SREV_9340(ah) ? 0x403c : \ + (AR_SREV_9300_20_OR_LATER(ah) ? 0x405c : 0x4054)) #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004 #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2 #define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008 @@ -1048,13 +1052,15 @@ enum { #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 #define AR_GPIO_JTAG_DISABLE 0x00020000 -#define AR_GPIO_INPUT_MUX1 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4060 : 0x4058) +#define AR_GPIO_INPUT_MUX1 (AR_SREV_9340(ah) ? 0x4040 : \ + (AR_SREV_9300_20_OR_LATER(ah) ? 0x4060 : 0x4058)) #define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 #define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 #define AR_GPIO_INPUT_MUX1_BT_PRIORITY 0x00000f00 #define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8 -#define AR_GPIO_INPUT_MUX2 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4064 : 0x405c) +#define AR_GPIO_INPUT_MUX2 (AR_SREV_9340(ah) ? 0x4044 : \ + (AR_SREV_9300_20_OR_LATER(ah) ? 0x4064 : 0x405c)) #define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f #define AR_GPIO_INPUT_MUX2_CLK25_S 0 #define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0 @@ -1062,13 +1068,18 @@ enum { #define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00 #define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8 -#define AR_GPIO_OUTPUT_MUX1 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4068 : 0x4060) -#define AR_GPIO_OUTPUT_MUX2 (AR_SREV_9300_20_OR_LATER(ah) ? 0x406c : 0x4064) -#define AR_GPIO_OUTPUT_MUX3 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4070 : 0x4068) +#define AR_GPIO_OUTPUT_MUX1 (AR_SREV_9340(ah) ? 0x4048 : \ + (AR_SREV_9300_20_OR_LATER(ah) ? 0x4068 : 0x4060)) +#define AR_GPIO_OUTPUT_MUX2 (AR_SREV_9340(ah) ? 0x404c : \ + (AR_SREV_9300_20_OR_LATER(ah) ? 0x406c : 0x4064)) +#define AR_GPIO_OUTPUT_MUX3 (AR_SREV_9340(ah) ? 0x4050 : \ + (AR_SREV_9300_20_OR_LATER(ah) ? 0x4070 : 0x4068)) -#define AR_INPUT_STATE (AR_SREV_9300_20_OR_LATER(ah) ? 0x4074 : 0x406c) +#define AR_INPUT_STATE (AR_SREV_9340(ah) ? 0x4054 : \ + (AR_SREV_9300_20_OR_LATER(ah) ? 0x4074 : 0x406c)) -#define AR_EEPROM_STATUS_DATA (AR_SREV_9300_20_OR_LATER(ah) ? 0x4084 : 0x407c) +#define AR_EEPROM_STATUS_DATA (AR_SREV_9340(ah) ? 0x40c8 : \ + (AR_SREV_9300_20_OR_LATER(ah) ? 0x4084 : 0x407c)) #define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff #define AR_EEPROM_STATUS_DATA_VAL_S 0 #define AR_EEPROM_STATUS_DATA_BUSY 0x00010000 @@ -1076,17 +1087,19 @@ enum { #define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 #define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 -#define AR_OBS (AR_SREV_9300_20_OR_LATER(ah) ? 0x4088 : 0x4080) +#define AR_OBS (AR_SREV_9340(ah) ? 0x405c : \ + (AR_SREV_9300_20_OR_LATER(ah) ? 0x4088 : 0x4080)) #define AR_GPIO_PDPU (AR_SREV_9300_20_OR_LATER(ah) ? 0x4090 : 0x4088) -#define AR_PCIE_MSI (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094) +#define AR_PCIE_MSI (AR_SREV_9340(ah) ? 0x40d8 : \ + (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094)) #define AR_PCIE_MSI_ENABLE 0x00000001 -#define AR_INTR_PRIO_SYNC_ENABLE 0x40c4 -#define AR_INTR_PRIO_ASYNC_MASK 0x40c8 -#define AR_INTR_PRIO_SYNC_MASK 0x40cc -#define AR_INTR_PRIO_ASYNC_ENABLE 0x40d4 +#define AR_INTR_PRIO_SYNC_ENABLE (AR_SREV_9340(ah) ? 0x4088 : 0x40c4) +#define AR_INTR_PRIO_ASYNC_MASK (AR_SREV_9340(ah) ? 0x408c : 0x40c8) +#define AR_INTR_PRIO_SYNC_MASK (AR_SREV_9340(ah) ? 0x4090 : 0x40cc) +#define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4) #define AR_ENT_OTP 0x40d8 #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 #define AR_ENT_OTP_MPSD 0x00800000 -- cgit v1.2.3-58-ga151 From f2f5f2a1cedc803a5a517557d436e6cb10c007de Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:01 +0530 Subject: ath9k_hw: Get AHB clock information from ath9k_platform_data Add a bool in ath9k_platform_data to pass AHB clock speed information. Driver needs this to configure PLL on some SOCs. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.h | 2 ++ drivers/net/wireless/ath/ath9k/init.c | 1 + include/linux/ath9k_platform.h | 2 ++ 3 files changed, 5 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 450b64263bc9..5a4ba09a2f1c 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -846,6 +846,8 @@ struct ath_hw { /* Enterprise mode cap */ u32 ent_mode; + + bool is_clk_25mhz; }; struct ath_bus_ops { diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 1ac8318d82a3..e78b6aefa108 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -574,6 +574,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, sc->sc_ah->gpio_mask = pdata->gpio_mask; sc->sc_ah->gpio_val = pdata->gpio_val; sc->sc_ah->led_pin = pdata->led_pin; + ah->is_clk_25mhz = pdata->is_clk_25mhz; } common = ath9k_hw_common(ah); diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h index 020387a114e3..60a7c49dcb49 100644 --- a/include/linux/ath9k_platform.h +++ b/include/linux/ath9k_platform.h @@ -28,6 +28,8 @@ struct ath9k_platform_data { int led_pin; u32 gpio_mask; u32 gpio_val; + + bool is_clk_25mhz; }; #endif /* _LINUX_ATH9K_PLATFORM_H */ -- cgit v1.2.3-58-ga151 From 0b488ac6ece598fda69b5f3348015994129c48b9 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Wed, 20 Apr 2011 10:26:15 +0530 Subject: ath9k_hw: Configure pll control register accordingly for AR9340 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 50 +++++++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/hw.h | 2 +- drivers/net/wireless/ath/ath9k/phy.h | 3 +++ drivers/net/wireless/ath/ath9k/reg.h | 4 ++- 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index d98b4c6d8dcf..a1eaacee605f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -716,13 +716,48 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); + } else if (AR_SREV_9340(ah)) { + u32 regval, pll2_divint, pll2_divfrac, refdiv; + + REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); + udelay(1000); + + REG_SET_BIT(ah, AR_PHY_PLL_MODE, 0x1 << 16); + udelay(100); + + if (ah->is_clk_25mhz) { + pll2_divint = 0x54; + pll2_divfrac = 0x1eb85; + refdiv = 3; + } else { + pll2_divint = 88; + pll2_divfrac = 0; + refdiv = 5; + } + + regval = REG_READ(ah, AR_PHY_PLL_MODE); + regval |= (0x1 << 16); + REG_WRITE(ah, AR_PHY_PLL_MODE, regval); + udelay(100); + + REG_WRITE(ah, AR_PHY_PLL_CONTROL, (refdiv << 27) | + (pll2_divint << 18) | pll2_divfrac); + udelay(100); + + regval = REG_READ(ah, AR_PHY_PLL_MODE); + regval = (regval & 0x80071fff) | (0x1 << 30) | (0x1 << 13) | + (0x4 << 26) | (0x18 << 19); + REG_WRITE(ah, AR_PHY_PLL_MODE, regval); + REG_WRITE(ah, AR_PHY_PLL_MODE, + REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff); + udelay(1000); } pll = ath9k_hw_compute_pll_control(ah, chan); REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); - if (AR_SREV_9485(ah)) + if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) udelay(1000); /* Switch the core clock for ar9271 to 117Mhz */ @@ -734,6 +769,19 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, udelay(RTC_PLL_SETTLE_DELAY); REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); + + if (AR_SREV_9340(ah)) { + if (ah->is_clk_25mhz) { + REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); + REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); + REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); + } else { + REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1); + REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); + REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); + } + udelay(100); + } } static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 5a4ba09a2f1c..9b1f415c36bc 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -122,7 +122,7 @@ #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) #define BASE_ACTIVATE_DELAY 100 -#define RTC_PLL_SETTLE_DELAY 100 +#define RTC_PLL_SETTLE_DELAY (AR_SREV_9340(ah) ? 1000 : 100) #define COEF_SCALE_S 24 #define HT40_CHANNEL_CENTER_SHIFT 10 diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 8e5fe9d7f174..9441bf8ca2fd 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -45,4 +45,7 @@ #define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 #define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 +#define AR_PHY_PLL_CONTROL 0x16180 +#define AR_PHY_PLL_MODE 0x16184 + #endif diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 42d9f1b7655c..b42e36c6f6ea 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1180,6 +1180,7 @@ enum { #define AR_RTC_PLL_REFDIV_5 0x000000c0 #define AR_RTC_PLL_CLKSEL 0x00000300 #define AR_RTC_PLL_CLKSEL_S 8 +#define AR_RTC_PLL_BYPASS 0x00010000 #define PLL3 0x16188 #define PLL3_DO_MEAS_MASK 0x40000000 @@ -1226,7 +1227,8 @@ enum { /* RTC_DERIVED_* - only for AR9100 */ -#define AR_RTC_DERIVED_CLK (AR_RTC_BASE + 0x0038) +#define AR_RTC_DERIVED_CLK \ + (AR_SREV_9100(ah) ? (AR_RTC_BASE + 0x0038) : 0x7038) #define AR_RTC_DERIVED_CLK_PERIOD 0x0000fffe #define AR_RTC_DERIVED_CLK_PERIOD_S 1 -- cgit v1.2.3-58-ga151 From 9aa5a8d5fd519d61a947c797cb917b38fd156cff Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:03 +0530 Subject: ath9k_hw: Add initvals.h for ar9340 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9340_initvals.h | 1525 ++++++++++++++++++++++ 1 file changed, 1525 insertions(+) create mode 100644 drivers/net/wireless/ath/ath9k/ar9340_initvals.h diff --git a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h new file mode 100644 index 000000000000..815a8af1beef --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h @@ -0,0 +1,1525 @@ +/* + * Copyright (c) 2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef INITVALS_9340_H +#define INITVALS_9340_H + +static const u32 ar9340_1p0_radio_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800}, + {0x0001610c, 0x08000000, 0x08000000, 0x00000000, 0x00000000}, + {0x00016140, 0x10804000, 0x10804000, 0x50804000, 0x50804000}, + {0x0001650c, 0x08000000, 0x08000000, 0x00000000, 0x00000000}, + {0x00016540, 0x10804000, 0x10804000, 0x50804000, 0x50804000}, +}; + +static const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, + {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402}, + {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, + {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, + {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, + {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, +}; + +static const u32 ar9340Modes_fast_clock_1p0[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + {0x00001030, 0x00000268, 0x000004d0}, + {0x00001070, 0x0000018c, 0x00000318}, + {0x000010b0, 0x00000fd0, 0x00001fa0}, + {0x00008014, 0x044c044c, 0x08980898}, + {0x0000801c, 0x148ec02b, 0x148ec057}, + {0x00008318, 0x000044c0, 0x00008980}, + {0x00009e00, 0x03721821, 0x03721821}, + {0x0000a230, 0x0000000b, 0x00000016}, + {0x0000a254, 0x00000898, 0x00001130}, +}; + +static const u32 ar9340_1p0_radio_core[][2] = { + /* Addr allmodes */ + {0x00016000, 0x36db6db6}, + {0x00016004, 0x6db6db40}, + {0x00016008, 0x73f00000}, + {0x0001600c, 0x00000000}, + {0x00016040, 0x7f80fff8}, + {0x00016044, 0x03b6d2db}, + {0x00016048, 0x24925266}, + {0x0001604c, 0x000f0278}, + {0x00016050, 0x6db6db6c}, + {0x00016054, 0x6db60000}, + {0x00016080, 0x00080000}, + {0x00016084, 0x0e48048c}, + {0x00016088, 0x14214514}, + {0x0001608c, 0x119f081c}, + {0x00016090, 0x24926490}, + {0x00016094, 0x00000000}, + {0x00016098, 0xd411eb84}, + {0x0001609c, 0x03e47f32}, + {0x000160a0, 0xc2108ffe}, + {0x000160a4, 0x812fc370}, + {0x000160a8, 0x423c8000}, + {0x000160ac, 0xa4646800}, + {0x000160b0, 0x00fe7f46}, + {0x000160b4, 0x92480000}, + {0x000160c0, 0x006db6db}, + {0x000160c4, 0x6db6db60}, + {0x000160c8, 0x6db6db6c}, + {0x000160cc, 0x6de6db6c}, + {0x000160d0, 0xb6da4924}, + {0x00016100, 0x04cb0001}, + {0x00016104, 0xfff80000}, + {0x00016108, 0x00080010}, + {0x0001610c, 0x00000000}, + {0x00016140, 0x50804008}, + {0x00016144, 0x01884080}, + {0x00016148, 0x000080c0}, + {0x00016280, 0x01000015}, + {0x00016284, 0x05530000}, + {0x00016288, 0x00318000}, + {0x0001628c, 0x50000000}, + {0x00016290, 0x4080294f}, + {0x00016380, 0x00000000}, + {0x00016384, 0x00000000}, + {0x00016388, 0x00800700}, + {0x0001638c, 0x00800700}, + {0x00016390, 0x00800700}, + {0x00016394, 0x00000000}, + {0x00016398, 0x00000000}, + {0x0001639c, 0x00000000}, + {0x000163a0, 0x00000001}, + {0x000163a4, 0x00000001}, + {0x000163a8, 0x00000000}, + {0x000163ac, 0x00000000}, + {0x000163b0, 0x00000000}, + {0x000163b4, 0x00000000}, + {0x000163b8, 0x00000000}, + {0x000163bc, 0x00000000}, + {0x000163c0, 0x000000a0}, + {0x000163c4, 0x000c0000}, + {0x000163c8, 0x14021402}, + {0x000163cc, 0x00001402}, + {0x000163d0, 0x00000000}, + {0x000163d4, 0x00000000}, + {0x00016400, 0x36db6db6}, + {0x00016404, 0x6db6db40}, + {0x00016408, 0x73f00000}, + {0x0001640c, 0x00000000}, + {0x00016440, 0x7f80fff8}, + {0x00016444, 0x03b6d2db}, + {0x00016448, 0x24927266}, + {0x0001644c, 0x000f0278}, + {0x00016450, 0x6db6db6c}, + {0x00016454, 0x6db60000}, + {0x00016500, 0x04cb0001}, + {0x00016504, 0xfff80000}, + {0x00016508, 0x00080010}, + {0x0001650c, 0x00000000}, + {0x00016540, 0x50804008}, + {0x00016544, 0x01884080}, + {0x00016548, 0x000080c0}, + {0x00016780, 0x00000000}, + {0x00016784, 0x00000000}, + {0x00016788, 0x00800700}, + {0x0001678c, 0x00800700}, + {0x00016790, 0x00800700}, + {0x00016794, 0x00000000}, + {0x00016798, 0x00000000}, + {0x0001679c, 0x00000000}, + {0x000167a0, 0x00000001}, + {0x000167a4, 0x00000001}, + {0x000167a8, 0x00000000}, + {0x000167ac, 0x00000000}, + {0x000167b0, 0x00000000}, + {0x000167b4, 0x00000000}, + {0x000167b8, 0x00000000}, + {0x000167bc, 0x00000000}, + {0x000167c0, 0x000000a0}, + {0x000167c4, 0x000c0000}, + {0x000167c8, 0x14021402}, + {0x000167cc, 0x00001402}, + {0x000167d0, 0x00000000}, + {0x000167d4, 0x00000000}, +}; + +static const u32 ar9340_1p0_radio_core_40M[][2] = { + {0x0001609c, 0x02566f3a}, + {0x000160ac, 0xa4647c00}, + {0x000160b0, 0x01885f5a}, +}; + +static const u32 ar9340_1p0_mac_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, + {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, + {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, +}; + +static const u32 ar9340_1p0_soc_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, +}; + +static const u32 ar9340_1p0_baseband_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, + {0x00009820, 0x206a022e, 0x206a022e, 0x206a022e, 0x206a022e}, + {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, + {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, + {0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044}, + {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, + {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020}, + {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, + {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e}, + {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, + {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, + {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, + {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, + {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, + {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, + {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, + {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0}, + {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, + {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, + {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, + {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, + {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, + {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, + {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, + {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, + {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, + {0x0000a288, 0x00000220, 0x00000220, 0x00000110, 0x00000110}, + {0x0000a28c, 0x00011111, 0x00011111, 0x00022222, 0x00022222}, + {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, + {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, + {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000ae04, 0x00180000, 0x00180000, 0x00180000, 0x00180000}, + {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, + {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, +}; + +static const u32 ar9340_1p0_baseband_core[][2] = { + /* Addr allmodes */ + {0x00009800, 0xafe68e30}, + {0x00009804, 0xfd14e000}, + {0x00009808, 0x9c0a9f6b}, + {0x0000980c, 0x04900000}, + {0x00009814, 0xb280c00a}, + {0x00009818, 0x00000000}, + {0x0000981c, 0x00020028}, + {0x00009834, 0x5f3ca3de}, + {0x00009838, 0x0108ecff}, + {0x0000983c, 0x14750600}, + {0x00009880, 0x201fff00}, + {0x00009884, 0x00001042}, + {0x000098a4, 0x00200400}, + {0x000098b0, 0x52440bbe}, + {0x000098d0, 0x004b6a8e}, + {0x000098d4, 0x00000820}, + {0x000098dc, 0x00000000}, + {0x000098f0, 0x00000000}, + {0x000098f4, 0x00000000}, + {0x00009c04, 0xff55ff55}, + {0x00009c08, 0x0320ff55}, + {0x00009c0c, 0x00000000}, + {0x00009c10, 0x00000000}, + {0x00009c14, 0x00046384}, + {0x00009c18, 0x05b6b440}, + {0x00009c1c, 0x00b6b440}, + {0x00009d00, 0xc080a333}, + {0x00009d04, 0x40206c10}, + {0x00009d08, 0x009c4060}, + {0x00009d0c, 0x9883800a}, + {0x00009d10, 0x01834061}, + {0x00009d14, 0x00c0040b}, + {0x00009d18, 0x00000000}, + {0x00009e08, 0x0038230c}, + {0x00009e24, 0x990bb515}, + {0x00009e28, 0x0c6f0000}, + {0x00009e30, 0x06336f77}, + {0x00009e34, 0x6af6532f}, + {0x00009e38, 0x0cc80c00}, + {0x00009e3c, 0xcf946222}, + {0x00009e40, 0x0d261820}, + {0x00009e4c, 0x00001004}, + {0x00009e50, 0x00ff03f1}, + {0x00009e54, 0x00000000}, + {0x00009fc0, 0x803e4788}, + {0x00009fc4, 0x0001efb5}, + {0x00009fcc, 0x40000014}, + {0x00009fd0, 0x01193b93}, + {0x0000a20c, 0x00000000}, + {0x0000a220, 0x00000000}, + {0x0000a224, 0x00000000}, + {0x0000a228, 0x10002310}, + {0x0000a22c, 0x01036a1e}, + {0x0000a234, 0x10000fff}, + {0x0000a23c, 0x00000000}, + {0x0000a244, 0x0c000000}, + {0x0000a2a0, 0x00000001}, + {0x0000a2c0, 0x00000001}, + {0x0000a2c8, 0x00000000}, + {0x0000a2cc, 0x18c43433}, + {0x0000a2d4, 0x00000000}, + {0x0000a2dc, 0x00000000}, + {0x0000a2e0, 0x00000000}, + {0x0000a2e4, 0x00000000}, + {0x0000a2e8, 0x00000000}, + {0x0000a2ec, 0x00000000}, + {0x0000a2f0, 0x00000000}, + {0x0000a2f4, 0x00000000}, + {0x0000a2f8, 0x00000000}, + {0x0000a344, 0x00000000}, + {0x0000a34c, 0x00000000}, + {0x0000a350, 0x0000a000}, + {0x0000a364, 0x00000000}, + {0x0000a370, 0x00000000}, + {0x0000a390, 0x00000001}, + {0x0000a394, 0x00000444}, + {0x0000a398, 0x001f0e0f}, + {0x0000a39c, 0x0075393f}, + {0x0000a3a0, 0xb79f6427}, + {0x0000a3a4, 0x00000000}, + {0x0000a3a8, 0xaaaaaaaa}, + {0x0000a3ac, 0x3c466478}, + {0x0000a3c0, 0x20202020}, + {0x0000a3c4, 0x22222220}, + {0x0000a3c8, 0x20200020}, + {0x0000a3cc, 0x20202020}, + {0x0000a3d0, 0x20202020}, + {0x0000a3d4, 0x20202020}, + {0x0000a3d8, 0x20202020}, + {0x0000a3dc, 0x20202020}, + {0x0000a3e0, 0x20202020}, + {0x0000a3e4, 0x20202020}, + {0x0000a3e8, 0x20202020}, + {0x0000a3ec, 0x20202020}, + {0x0000a3f0, 0x00000000}, + {0x0000a3f4, 0x00000246}, + {0x0000a3f8, 0x0cdbd380}, + {0x0000a3fc, 0x000f0f01}, + {0x0000a400, 0x8fa91f01}, + {0x0000a404, 0x00000000}, + {0x0000a408, 0x0e79e5c6}, + {0x0000a40c, 0x00820820}, + {0x0000a414, 0x1ce739ce}, + {0x0000a418, 0x2d001dce}, + {0x0000a41c, 0x1ce739ce}, + {0x0000a420, 0x000001ce}, + {0x0000a424, 0x1ce739ce}, + {0x0000a428, 0x000001ce}, + {0x0000a42c, 0x1ce739ce}, + {0x0000a430, 0x1ce739ce}, + {0x0000a434, 0x00000000}, + {0x0000a438, 0x00001801}, + {0x0000a43c, 0x00000000}, + {0x0000a440, 0x00000000}, + {0x0000a444, 0x00000000}, + {0x0000a448, 0x04000080}, + {0x0000a44c, 0x00000001}, + {0x0000a450, 0x00010000}, + {0x0000a458, 0x00000000}, + {0x0000a600, 0x00000000}, + {0x0000a604, 0x00000000}, + {0x0000a608, 0x00000000}, + {0x0000a60c, 0x00000000}, + {0x0000a610, 0x00000000}, + {0x0000a614, 0x00000000}, + {0x0000a618, 0x00000000}, + {0x0000a61c, 0x00000000}, + {0x0000a620, 0x00000000}, + {0x0000a624, 0x00000000}, + {0x0000a628, 0x00000000}, + {0x0000a62c, 0x00000000}, + {0x0000a630, 0x00000000}, + {0x0000a634, 0x00000000}, + {0x0000a638, 0x00000000}, + {0x0000a63c, 0x00000000}, + {0x0000a640, 0x00000000}, + {0x0000a644, 0x3fad9d74}, + {0x0000a648, 0x0048060a}, + {0x0000a64c, 0x00000637}, + {0x0000a670, 0x03020100}, + {0x0000a674, 0x09080504}, + {0x0000a678, 0x0d0c0b0a}, + {0x0000a67c, 0x13121110}, + {0x0000a680, 0x31301514}, + {0x0000a684, 0x35343332}, + {0x0000a688, 0x00000036}, + {0x0000a690, 0x00000838}, + {0x0000a7c0, 0x00000000}, + {0x0000a7c4, 0xfffffffc}, + {0x0000a7c8, 0x00000000}, + {0x0000a7cc, 0x00000000}, + {0x0000a7d0, 0x00000000}, + {0x0000a7d4, 0x00000004}, + {0x0000a7dc, 0x00000000}, + {0x0000a8d0, 0x004b6a8e}, + {0x0000a8d4, 0x00000820}, + {0x0000a8dc, 0x00000000}, + {0x0000a8f0, 0x00000000}, + {0x0000a8f4, 0x00000000}, + {0x0000b2d0, 0x00000080}, + {0x0000b2d4, 0x00000000}, + {0x0000b2dc, 0x00000000}, + {0x0000b2e0, 0x00000000}, + {0x0000b2e4, 0x00000000}, + {0x0000b2e8, 0x00000000}, + {0x0000b2ec, 0x00000000}, + {0x0000b2f0, 0x00000000}, + {0x0000b2f4, 0x00000000}, + {0x0000b2f8, 0x00000000}, + {0x0000b408, 0x0e79e5c0}, + {0x0000b40c, 0x00820820}, + {0x0000b420, 0x00000000}, +}; + +static const u32 ar9340Modes_high_power_tx_gain_table_1p0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, + {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, + {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, + {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, + {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, + {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, + {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, + {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, + {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, + {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, + {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, + {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, + {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, +}; + +static const u32 ar9340Modes_high_ob_db_tx_gain_table_1p0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, + {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, + {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, + {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, + {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, + {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, + {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, + {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, + {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, + {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x00016044, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4}, + {0x00016048, 0x8e481266, 0x8e481266, 0x8e481266, 0x8e481266}, + {0x00016444, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4}, + {0x00016448, 0x8e481266, 0x8e481266, 0x8e481266, 0x8e481266}, +}; +static const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, + {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, + {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, + {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, + {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, + {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, + {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, + {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, + {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, + {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x00016044, 0x036db2db, 0x036db2db, 0x036db2db, 0x036db2db}, + {0x00016048, 0x69b65266, 0x69b65266, 0x69b65266, 0x69b65266}, + {0x00016444, 0x036db2db, 0x036db2db, 0x036db2db, 0x036db2db}, + {0x00016448, 0x69b65266, 0x69b65266, 0x69b65266, 0x69b65266}, +}; + + +static const u32 ar9340Common_rx_gain_table_1p0[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x01910190}, + {0x0000a030, 0x01930192}, + {0x0000a034, 0x01950194}, + {0x0000a038, 0x038a0196}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x22222229}, + {0x0000a084, 0x1d1d1d1d}, + {0x0000a088, 0x1d1d1d1d}, + {0x0000a08c, 0x1d1d1d1d}, + {0x0000a090, 0x171d1d1d}, + {0x0000a094, 0x11111717}, + {0x0000a098, 0x00030311}, + {0x0000a09c, 0x00000000}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x32323232}, + {0x0000b084, 0x2f2f3232}, + {0x0000b088, 0x23282a2d}, + {0x0000b08c, 0x1c1e2123}, + {0x0000b090, 0x14171919}, + {0x0000b094, 0x0e0e1214}, + {0x0000b098, 0x03050707}, + {0x0000b09c, 0x00030303}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, + {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402}, + {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, + {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, + {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, + {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, + {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, +}; + +static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400}, + {0x0000a518, 0x21020220, 0x21020220, 0x15000402, 0x15000402}, + {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x61042a6c, 0x61042a6c, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x66062a6c, 0x66062a6c, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x7006308c, 0x7006308c, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x730a308a, 0x730a308a, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400}, + {0x0000a598, 0x21820220, 0x21820220, 0x15800402, 0x15800402}, + {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x7086308c, 0x7086308c, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x738a308a, 0x738a308a, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x00016044, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, + {0x00016048, 0x24927266, 0x24927266, 0x8e483266, 0x8e483266}, + {0x00016444, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, + {0x00016448, 0x24927266, 0x24927266, 0x8e482266, 0x8e482266}, +}; + +static const u32 ar9340_1p0_mac_core[][2] = { + /* Addr allmodes */ + {0x00000008, 0x00000000}, + {0x00000030, 0x00020085}, + {0x00000034, 0x00000005}, + {0x00000040, 0x00000000}, + {0x00000044, 0x00000000}, + {0x00000048, 0x00000008}, + {0x0000004c, 0x00000010}, + {0x00000050, 0x00000000}, + {0x00001040, 0x002ffc0f}, + {0x00001044, 0x002ffc0f}, + {0x00001048, 0x002ffc0f}, + {0x0000104c, 0x002ffc0f}, + {0x00001050, 0x002ffc0f}, + {0x00001054, 0x002ffc0f}, + {0x00001058, 0x002ffc0f}, + {0x0000105c, 0x002ffc0f}, + {0x00001060, 0x002ffc0f}, + {0x00001064, 0x002ffc0f}, + {0x000010f0, 0x00000100}, + {0x00001270, 0x00000000}, + {0x000012b0, 0x00000000}, + {0x000012f0, 0x00000000}, + {0x0000143c, 0x00000000}, + {0x0000147c, 0x00000000}, + {0x00008000, 0x00000000}, + {0x00008004, 0x00000000}, + {0x00008008, 0x00000000}, + {0x0000800c, 0x00000000}, + {0x00008018, 0x00000000}, + {0x00008020, 0x00000000}, + {0x00008038, 0x00000000}, + {0x0000803c, 0x00000000}, + {0x00008040, 0x00000000}, + {0x00008044, 0x00000000}, + {0x00008048, 0x00000000}, + {0x0000804c, 0xffffffff}, + {0x00008054, 0x00000000}, + {0x00008058, 0x00000000}, + {0x0000805c, 0x000fc78f}, + {0x00008060, 0x0000000f}, + {0x00008064, 0x00000000}, + {0x00008070, 0x00000310}, + {0x00008074, 0x00000020}, + {0x00008078, 0x00000000}, + {0x0000809c, 0x0000000f}, + {0x000080a0, 0x00000000}, + {0x000080a4, 0x02ff0000}, + {0x000080a8, 0x0e070605}, + {0x000080ac, 0x0000000d}, + {0x000080b0, 0x00000000}, + {0x000080b4, 0x00000000}, + {0x000080b8, 0x00000000}, + {0x000080bc, 0x00000000}, + {0x000080c0, 0x2a800000}, + {0x000080c4, 0x06900168}, + {0x000080c8, 0x13881c20}, + {0x000080cc, 0x01f40000}, + {0x000080d0, 0x00252500}, + {0x000080d4, 0x00a00000}, + {0x000080d8, 0x00400000}, + {0x000080dc, 0x00000000}, + {0x000080e0, 0xffffffff}, + {0x000080e4, 0x0000ffff}, + {0x000080e8, 0x3f3f3f3f}, + {0x000080ec, 0x00000000}, + {0x000080f0, 0x00000000}, + {0x000080f4, 0x00000000}, + {0x000080fc, 0x00020000}, + {0x00008100, 0x00000000}, + {0x00008108, 0x00000052}, + {0x0000810c, 0x00000000}, + {0x00008110, 0x00000000}, + {0x00008114, 0x000007ff}, + {0x00008118, 0x000000aa}, + {0x0000811c, 0x00003210}, + {0x00008124, 0x00000000}, + {0x00008128, 0x00000000}, + {0x0000812c, 0x00000000}, + {0x00008130, 0x00000000}, + {0x00008134, 0x00000000}, + {0x00008138, 0x00000000}, + {0x0000813c, 0x0000ffff}, + {0x00008144, 0xffffffff}, + {0x00008168, 0x00000000}, + {0x0000816c, 0x00000000}, + {0x00008170, 0x18486200}, + {0x00008174, 0x33332210}, + {0x00008178, 0x00000000}, + {0x0000817c, 0x00020000}, + {0x000081c0, 0x00000000}, + {0x000081c4, 0x33332210}, + {0x000081c8, 0x00000000}, + {0x000081cc, 0x00000000}, + {0x000081d4, 0x00000000}, + {0x000081ec, 0x00000000}, + {0x000081f0, 0x00000000}, + {0x000081f4, 0x00000000}, + {0x000081f8, 0x00000000}, + {0x000081fc, 0x00000000}, + {0x00008240, 0x00100000}, + {0x00008244, 0x0010f424}, + {0x00008248, 0x00000800}, + {0x0000824c, 0x0001e848}, + {0x00008250, 0x00000000}, + {0x00008254, 0x00000000}, + {0x00008258, 0x00000000}, + {0x0000825c, 0x40000000}, + {0x00008260, 0x00080922}, + {0x00008264, 0x9d400010}, + {0x00008268, 0xffffffff}, + {0x0000826c, 0x0000ffff}, + {0x00008270, 0x00000000}, + {0x00008274, 0x40000000}, + {0x00008278, 0x003e4180}, + {0x0000827c, 0x00000004}, + {0x00008284, 0x0000002c}, + {0x00008288, 0x0000002c}, + {0x0000828c, 0x000000ff}, + {0x00008294, 0x00000000}, + {0x00008298, 0x00000000}, + {0x0000829c, 0x00000000}, + {0x00008300, 0x00000140}, + {0x00008314, 0x00000000}, + {0x0000831c, 0x0000010d}, + {0x00008328, 0x00000000}, + {0x0000832c, 0x00000007}, + {0x00008330, 0x00000302}, + {0x00008334, 0x00000700}, + {0x00008338, 0x00ff0000}, + {0x0000833c, 0x02400000}, + {0x00008340, 0x000107ff}, + {0x00008344, 0xaa48105b}, + {0x00008348, 0x008f0000}, + {0x0000835c, 0x00000000}, + {0x00008360, 0xffffffff}, + {0x00008364, 0xffffffff}, + {0x00008368, 0x00000000}, + {0x00008370, 0x00000000}, + {0x00008374, 0x000000ff}, + {0x00008378, 0x00000000}, + {0x0000837c, 0x00000000}, + {0x00008380, 0xffffffff}, + {0x00008384, 0xffffffff}, + {0x00008390, 0xffffffff}, + {0x00008394, 0xffffffff}, + {0x00008398, 0x00000000}, + {0x0000839c, 0x00000000}, + {0x000083a0, 0x00000000}, + {0x000083a4, 0x0000fa14}, + {0x000083a8, 0x000f0c00}, + {0x000083ac, 0x33332210}, + {0x000083b0, 0x33332210}, + {0x000083b4, 0x33332210}, + {0x000083b8, 0x33332210}, + {0x000083bc, 0x00000000}, + {0x000083c0, 0x00000000}, + {0x000083c4, 0x00000000}, + {0x000083c8, 0x00000000}, + {0x000083cc, 0x00000200}, + {0x000083d0, 0x000301ff}, +}; + +static const u32 ar9340Common_wo_xlna_rx_gain_table_1p0[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x03820190}, + {0x0000a030, 0x03840383}, + {0x0000a034, 0x03880385}, + {0x0000a038, 0x038a0389}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x29292929}, + {0x0000a084, 0x29292929}, + {0x0000a088, 0x29292929}, + {0x0000a08c, 0x29292929}, + {0x0000a090, 0x22292929}, + {0x0000a094, 0x1d1d2222}, + {0x0000a098, 0x0c111117}, + {0x0000a09c, 0x00030303}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x32323232}, + {0x0000b084, 0x2f2f3232}, + {0x0000b088, 0x23282a2d}, + {0x0000b08c, 0x1c1e2123}, + {0x0000b090, 0x14171919}, + {0x0000b094, 0x0e0e1214}, + {0x0000b098, 0x03050707}, + {0x0000b09c, 0x00030303}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9340_1p0_soc_preamble[][2] = { + /* Addr allmodes */ + {0x000040a4, 0x00a0c1c9}, + {0x00007008, 0x00000000}, + {0x00007020, 0x00000000}, + {0x00007034, 0x00000002}, + {0x00007038, 0x000004c2}, +}; + +#endif -- cgit v1.2.3-58-ga151 From d89baac8b477d8f9eca72d186863a554d7137b40 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:04 +0530 Subject: ath9k_hw: Initialize mode registers from initvals.h for AR9340 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 59 ++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 3 ++ drivers/net/wireless/ath/ath9k/hw.h | 1 + 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index aebaad97b190..37af7216a1a2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -18,6 +18,7 @@ #include "ar9003_mac.h" #include "ar9003_2p2_initvals.h" #include "ar9485_initvals.h" +#include "ar9340_initvals.h" /* General hardware code for the AR9003 hadware family */ @@ -28,7 +29,63 @@ */ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) { - if (AR_SREV_9485_11(ah)) { + if (AR_SREV_9340(ah)) { + /* mac */ + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], + ar9340_1p0_mac_core, + ARRAY_SIZE(ar9340_1p0_mac_core), 2); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], + ar9340_1p0_mac_postamble, + ARRAY_SIZE(ar9340_1p0_mac_postamble), 5); + + /* bb */ + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], + ar9340_1p0_baseband_core, + ARRAY_SIZE(ar9340_1p0_baseband_core), 2); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], + ar9340_1p0_baseband_postamble, + ARRAY_SIZE(ar9340_1p0_baseband_postamble), 5); + + /* radio */ + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], + ar9340_1p0_radio_core, + ARRAY_SIZE(ar9340_1p0_radio_core), 2); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], + ar9340_1p0_radio_postamble, + ARRAY_SIZE(ar9340_1p0_radio_postamble), 5); + + /* soc */ + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], + ar9340_1p0_soc_preamble, + ARRAY_SIZE(ar9340_1p0_soc_preamble), 2); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], + ar9340_1p0_soc_postamble, + ARRAY_SIZE(ar9340_1p0_soc_postamble), 5); + + /* rx/tx gain */ + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9340Common_wo_xlna_rx_gain_table_1p0, + ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0), + 5); + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9340Modes_high_ob_db_tx_gain_table_1p0, + ARRAY_SIZE(ar9340Modes_high_ob_db_tx_gain_table_1p0), + 5); + + INIT_INI_ARRAY(&ah->iniModesAdditional, + ar9340Modes_fast_clock_1p0, + ARRAY_SIZE(ar9340Modes_fast_clock_1p0), + 3); + + INIT_INI_ARRAY(&ah->iniModesAdditional_40M, + ar9340_1p0_radio_core_40M, + ARRAY_SIZE(ar9340_1p0_radio_core_40M), + 2); + } else if (AR_SREV_9485_11(ah)) { /* mac */ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 1bc33f51e466..c4d08058d40b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -646,6 +646,9 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, regWrites); + if (AR_SREV_9340(ah) && !ah->is_clk_25mhz) + REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites); + ar9003_hw_override_ini(ah); ar9003_hw_set_channel_regs(ah, chan); ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 9b1f415c36bc..29a745c59e63 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -800,6 +800,7 @@ struct ath_hw { struct ar5416IniArray iniPcieSerdes; struct ar5416IniArray iniPcieSerdesLowPower; struct ar5416IniArray iniModesAdditional; + struct ar5416IniArray iniModesAdditional_40M; struct ar5416IniArray iniModesRxGain; struct ar5416IniArray iniModesTxGain; struct ar5416IniArray iniModes_9271_1_0_only; -- cgit v1.2.3-58-ga151 From 070c4d509b1edcd0b8a40177a02e4302416c56d7 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:05 +0530 Subject: ath9k_hw: Don't do ani initialization for AR9340 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index a1eaacee605f..72631b128a4c 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -462,7 +462,7 @@ static int ath9k_hw_post_init(struct ath_hw *ah) return ecode; } - if (!AR_SREV_9100(ah)) { + if (!AR_SREV_9100(ah) && !AR_SREV_9340(ah)) { ath9k_hw_ani_setup(ah); ath9k_hw_ani_init(ah); } -- cgit v1.2.3-58-ga151 From d7fd52a80f9537970da1f80d785cac67375c05df Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:06 +0530 Subject: ath9k_hw: Initialize tx and rx gain table from initvals.h for ar9340 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 42 +++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 37af7216a1a2..a55eddbb2589 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -220,7 +220,12 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) switch (ar9003_hw_get_tx_gain_idx(ah)) { case 0: default: - if (AR_SREV_9485_11(ah)) + if (AR_SREV_9340(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9340Modes_lowest_ob_db_tx_gain_table_1p0, + ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), + 5); + else if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9485_modes_lowest_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), @@ -232,7 +237,12 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) 5); break; case 1: - if (AR_SREV_9485_11(ah)) + if (AR_SREV_9340(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9340Modes_lowest_ob_db_tx_gain_table_1p0, + ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), + 5); + else if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9485Modes_high_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1), @@ -244,7 +254,12 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) 5); break; case 2: - if (AR_SREV_9485_11(ah)) + if (AR_SREV_9340(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9340Modes_lowest_ob_db_tx_gain_table_1p0, + ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), + 5); + else if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9485Modes_low_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1), @@ -256,7 +271,12 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) 5); break; case 3: - if (AR_SREV_9485_11(ah)) + if (AR_SREV_9340(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9340Modes_lowest_ob_db_tx_gain_table_1p0, + ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), + 5); + else if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9485Modes_high_power_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1), @@ -275,7 +295,12 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) switch (ar9003_hw_get_rx_gain_idx(ah)) { case 0: default: - if (AR_SREV_9485_11(ah)) + if (AR_SREV_9340(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9340Common_rx_gain_table_1p0, + ARRAY_SIZE(ar9340Common_rx_gain_table_1p0), + 2); + else if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9485Common_wo_xlna_rx_gain_1_1, ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), @@ -287,7 +312,12 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) 2); break; case 1: - if (AR_SREV_9485_11(ah)) + if (AR_SREV_9340(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9340Common_wo_xlna_rx_gain_table_1p0, + ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0), + 2); + else if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9485Common_wo_xlna_rx_gain_1_1, ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), -- cgit v1.2.3-58-ga151 From d1395d85fa58438c70b77185b7c5780b94046348 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:07 +0530 Subject: ath9k_hw: Read spur frequency information from eeprom for AR9340 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index c4d08058d40b..0b999f94cd95 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -151,7 +151,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, * is out-of-band and can be ignored. */ - if (AR_SREV_9485(ah)) { + if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) { spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah, IS_CHAN_2GHZ(chan)); if (spur_fbin_ptr[0] == 0) /* No spur */ @@ -176,7 +176,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, for (i = 0; i < max_spur_cnts; i++) { negative = 0; - if (AR_SREV_9485(ah)) + if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i], IS_CHAN_2GHZ(chan)) - synth_freq; else -- cgit v1.2.3-58-ga151 From 17869f4fe940407b5b80039110c0257c90e18a99 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:08 +0530 Subject: ath9k_hw: Configure RF channel freqency for AR9340 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 0b999f94cd95..ea2f60c08f8b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -86,14 +86,31 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) channelSel = (freq * 4) / 120; chan_frac = (((freq * 4) % 120) * 0x20000) / 120; channelSel = (channelSel << 17) | chan_frac; + } else if (AR_SREV_9340(ah)) { + if (ah->is_clk_25mhz) { + u32 chan_frac; + + channelSel = (freq * 2) / 75; + chan_frac = (((freq * 2) % 75) * 0x20000) / 75; + channelSel = (channelSel << 17) | chan_frac; + } else + channelSel = CHANSEL_2G(freq) >> 1; } else channelSel = CHANSEL_2G(freq); /* Set to 2G mode */ bMode = 1; } else { - channelSel = CHANSEL_5G(freq); - /* Doubler is ON, so, divide channelSel by 2. */ - channelSel >>= 1; + if (AR_SREV_9340(ah) && ah->is_clk_25mhz) { + u32 chan_frac; + + channelSel = (freq * 2) / 75; + chan_frac = ((freq % 75) * 0x20000) / 75; + channelSel = (channelSel << 17) | chan_frac; + } else { + channelSel = CHANSEL_5G(freq); + /* Doubler is ON, so, divide channelSel by 2. */ + channelSel >>= 1; + } /* Set to 5G mode */ bMode = 0; } -- cgit v1.2.3-58-ga151 From e758ff8f7fc9ce96e94131b13e70af2c197fa05e Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:09 +0530 Subject: ath9k_hw: Clean up rx/tx chain configuration before AGC/IQ cal Use hw supported chains instead of hard coded values. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 4a4cd88429c0..09f3aa7f82f5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -940,21 +940,18 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_hw_capabilities *pCap = &ah->caps; int val; val = REG_READ(ah, AR_ENT_OTP); ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); - if (AR_SREV_9485(ah)) - ar9003_hw_set_chain_masks(ah, 0x1, 0x1); - else if (val & AR_ENT_OTP_CHAIN2_DISABLE) + /* Configure rx/tx chains before running AGC/TxiQ cals */ + if (val & AR_ENT_OTP_CHAIN2_DISABLE) ar9003_hw_set_chain_masks(ah, 0x3, 0x3); else - /* - * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain - * mode before running AGC/TxIQ cals - */ - ar9003_hw_set_chain_masks(ah, 0x7, 0x7); + ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask, + pCap->tx_chainmask); /* Do Tx IQ Calibration */ if (AR_SREV_9485(ah)) -- cgit v1.2.3-58-ga151 From 66953d438576938b02e6ff0ade1958f3e90af4a9 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:10 +0530 Subject: ath9k_hw: Fix register offset AR_PHY_65NM_CH0_THERM for AR9340 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 8bdda2cf9dd7..d133ee820875 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -588,7 +588,7 @@ #define AR_PHY_65NM_CH0_BIAS2 0x160c4 #define AR_PHY_65NM_CH0_BIAS4 0x160cc #define AR_PHY_65NM_CH0_RXTX4 0x1610c -#define AR_PHY_65NM_CH0_THERM (AR_SREV_9485(ah) ? 0x1628c : 0x16290) +#define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : 0x1628c) #define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000 #define AR_PHY_65NM_CH0_THERM_LOCAL_S 31 -- cgit v1.2.3-58-ga151 From 160b7fb4a07f52a6ba883b52fbb992f0086f99f6 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:11 +0530 Subject: ath9k_hw: Don't configure AR_CH0_THERM for AR9340 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 4a9271802991..685ce91fb71e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3448,9 +3448,13 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); else { REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); - REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB, - bias >> 2); - REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1); + if (!AR_SREV_9340(ah)) { + REG_RMW_FIELD(ah, AR_CH0_THERM, + AR_CH0_THERM_XPABIASLVL_MSB, + bias >> 2); + REG_RMW_FIELD(ah, AR_CH0_THERM, + AR_CH0_THERM_XPASHORT2GND, 1); + } } } -- cgit v1.2.3-58-ga151 From 3594beae705523982823f84bf4997f680b2cf75f Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:12 +0530 Subject: ath9k_hw: Skip internal regulator configuration for AR9340 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 685ce91fb71e..6e5baa7b40c6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3753,7 +3753,8 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan)); ar9003_hw_drive_strength_apply(ah); ar9003_hw_atten_apply(ah, chan); - ar9003_hw_internal_regulator_apply(ah); + if (!AR_SREV_9340(ah)) + ar9003_hw_internal_regulator_apply(ah); if (AR_SREV_9485(ah)) ar9003_hw_apply_tuning_caps(ah); } -- cgit v1.2.3-58-ga151 From a969c09184e7cb7d14838598b54c6effbef8b584 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:13 +0530 Subject: ath9k_hw: Configure tuning capacitance value for AR9340 as well Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 6e5baa7b40c6..262fb62c9a8e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3755,7 +3755,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, ar9003_hw_atten_apply(ah, chan); if (!AR_SREV_9340(ah)) ar9003_hw_internal_regulator_apply(ah); - if (AR_SREV_9485(ah)) + if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) ar9003_hw_apply_tuning_caps(ah); } -- cgit v1.2.3-58-ga151 From 2be7bfe0b454bc7c60ede777907ec817baa6196e Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:14 +0530 Subject: ath9k_hw: Enable byte Tx/Rx data swap for AR9340 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 72631b128a4c..39dd90110f32 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1544,7 +1544,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); } #ifdef __BIG_ENDIAN - else + else if (AR_SREV_9340(ah)) + REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); + else REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); #endif } -- cgit v1.2.3-58-ga151 From 2976bc5ebfb6c6dd37b4513540e567de0a2313f7 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:15 +0530 Subject: ath9k_hw: Configure chain switch table and attenuation control only for active chains Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 44 +++++++++++++++----------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 262fb62c9a8e..fd9b8c400f7e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3501,23 +3501,28 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) { + int chain; + static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { + AR_PHY_SWITCH_CHAIN_0, + AR_PHY_SWITCH_CHAIN_1, + AR_PHY_SWITCH_CHAIN_2, + }; + u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); + REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value); value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); - value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz); - REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value); - - if (!AR_SREV_9485(ah)) { - value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); - REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, - value); - - value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz); - REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, - value); + for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { + if ((ah->rxchainmask & BIT(chain)) || + (ah->txchainmask & BIT(chain))) { + value = ar9003_hw_ant_ctrl_chain_get(ah, chain, + is2ghz); + REG_RMW_FIELD(ah, switch_chain_reg[chain], + AR_SWITCH_TABLE_ALL, value); + } } if (AR_SREV_9485(ah)) { @@ -3638,13 +3643,16 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan) /* Test value. if 0 then attenuation is unused. Don't load anything. */ for (i = 0; i < 3; i++) { - value = ar9003_hw_atten_chain_get(ah, i, chan); - REG_RMW_FIELD(ah, ext_atten_reg[i], - AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); - - value = ar9003_hw_atten_chain_get_margin(ah, i, chan); - REG_RMW_FIELD(ah, ext_atten_reg[i], - AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); + if (ah->txchainmask & BIT(i)) { + value = ar9003_hw_atten_chain_get(ah, i, chan); + REG_RMW_FIELD(ah, ext_atten_reg[i], + AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); + + value = ar9003_hw_atten_chain_get_margin(ah, i, chan); + REG_RMW_FIELD(ah, ext_atten_reg[i], + AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, + value); + } } } -- cgit v1.2.3-58-ga151 From 5d48ae78cf81b4006ee1b7690b850db84820dc14 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:16 +0530 Subject: ath9k_hw: Read iq calibration data only for active chains Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 09f3aa7f82f5..bceff49d150b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -185,17 +185,19 @@ static void ar9003_hw_iqcal_collect(struct ath_hw *ah) /* Accumulate IQ cal measures for active chains */ for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ah->totalPowerMeasI[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ah->totalPowerMeasQ[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ah->totalIqCorrMeas[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, - "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", - ah->cal_samples, i, ah->totalPowerMeasI[i], - ah->totalPowerMeasQ[i], - ah->totalIqCorrMeas[i]); + if (ah->txchainmask & BIT(i)) { + ah->totalPowerMeasI[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + ah->totalPowerMeasQ[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + ah->totalIqCorrMeas[i] += + (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", + ah->cal_samples, i, ah->totalPowerMeasI[i], + ah->totalPowerMeasQ[i], + ah->totalIqCorrMeas[i]); + } } } -- cgit v1.2.3-58-ga151 From 247eee0e4ee3e23fd4f2918cdffa1e20d2261fa8 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:17 +0530 Subject: ath9k: Add AR9340 platform id to id table Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ahb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 5193ed58a17b..090f3145e3b3 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -26,6 +26,10 @@ const struct platform_device_id ath9k_platform_id_table[] = { .name = "ath9k", .driver_data = AR5416_AR9100_DEVID, }, + { + .name = "ar934x_wmac", + .driver_data = AR9300_DEVID_AR9340, + }, {}, }; -- cgit v1.2.3-58-ga151 From ecb1d385ad61001ff85407e5370a40934a1cc50b Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:18 +0530 Subject: ath9k_hw: Assign macversion based on devid for built-in wmac Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 39dd90110f32..28076086f633 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -247,6 +247,17 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) { u32 val; + switch (ah->hw_version.devid) { + case AR5416_AR9100_DEVID: + ah->hw_version.macVersion = AR_SREV_VERSION_9100; + break; + case AR9300_DEVID_AR9340: + ah->hw_version.macVersion = AR_SREV_VERSION_9340; + val = REG_READ(ah, AR_SREV); + ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); + return; + } + val = REG_READ(ah, AR_SREV) & AR_SREV_ID; if (val == 0xFF) { @@ -484,9 +495,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); int r = 0; - if (ah->hw_version.devid == AR5416_AR9100_DEVID) - ah->hw_version.macVersion = AR_SREV_VERSION_9100; - ath9k_hw_read_revisions(ah); /* -- cgit v1.2.3-58-ga151 From 79d1d2b8a34fd36e63cc7f5267cf79217a44edcc Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:19 +0530 Subject: ath9k_hw: Disable INTR_HOST1_FATAL to avoid interrupt strom with ar9430 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 6 +++++- drivers/net/wireless/ath/ath9k/mac.c | 10 ++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 28076086f633..66566ef3b8a8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -795,12 +795,16 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, enum nl80211_iftype opmode) { + u32 sync_default = AR_INTR_SYNC_DEFAULT; u32 imr_reg = AR_IMR_TXERR | AR_IMR_TXURN | AR_IMR_RXERR | AR_IMR_RXORN | AR_IMR_BCNMISC; + if (AR_SREV_9340(ah)) + sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; + if (AR_SREV_9300_20_OR_LATER(ah)) { imr_reg |= AR_IMR_RXOK_HP; if (ah->config.rx_intr_mitigation) @@ -831,7 +835,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, if (!AR_SREV_9100(ah)) { REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default); REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); } diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 6f431cbff38a..d86b8393b8dd 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -793,10 +793,14 @@ EXPORT_SYMBOL(ath9k_hw_disable_interrupts); void ath9k_hw_enable_interrupts(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); + u32 sync_default = AR_INTR_SYNC_DEFAULT; if (!(ah->imask & ATH9K_INT_GLOBAL)) return; + if (AR_SREV_9340(ah)) + sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; + ath_dbg(common, ATH_DBG_INTERRUPT, "enable IER\n"); REG_WRITE(ah, AR_IER, AR_IER_ENABLE); if (!AR_SREV_9100(ah)) { @@ -805,10 +809,8 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah) REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, - AR_INTR_SYNC_DEFAULT); - REG_WRITE(ah, AR_INTR_SYNC_MASK, - AR_INTR_SYNC_DEFAULT); + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default); + REG_WRITE(ah, AR_INTR_SYNC_MASK, sync_default); } ath_dbg(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); -- cgit v1.2.3-58-ga151 From bca04689a2260ca4da227e7f7fa35f28f40e6a00 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 19 Apr 2011 19:29:20 +0530 Subject: ath9k_hw: Enable AR9340 support AR9340 is a AR9003 family built-in 2x2 wmac of ar934x SOCs. It is single band in ar9341 SOC and dual band in ar9344/ar9342 SOCs. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 66566ef3b8a8..b7eb7930ae38 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -552,6 +552,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) case AR_SREV_VERSION_9271: case AR_SREV_VERSION_9300: case AR_SREV_VERSION_9485: + case AR_SREV_VERSION_9340: break; default: ath_err(common, @@ -629,6 +630,7 @@ int ath9k_hw_init(struct ath_hw *ah) case AR2427_DEVID_PCIE: case AR9300_DEVID_PCIE: case AR9300_DEVID_AR9485_PCIE: + case AR9300_DEVID_AR9340: break; default: if (common->bus_ops->ath_bus_type == ATH_USB) -- cgit v1.2.3-58-ga151 From 9be1cb39c6551231a4f210097685da11aa6a537b Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 19 Apr 2011 22:40:22 +0200 Subject: ssb: pci: trivial: correct amount of maximum retries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_pcicore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 1ba9f0ee6f94..dbda168e501b 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -522,7 +522,7 @@ static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address) pcicore_write32(pc, mdio_data, v); /* Wait for the device to complete the transaction */ udelay(10); - for (i = 0; i < 200; i++) { + for (i = 0; i < max_retries; i++) { v = pcicore_read32(pc, mdio_control); if (v & 0x100 /* Trans complete */) { udelay(10); -- cgit v1.2.3-58-ga151 From 3c35c84a70fc7d76cf7d975481fcb30468c68818 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 19 Apr 2011 22:40:23 +0200 Subject: ssb: cc: use correct min_msk for 0x4312 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Default min_msk on my 0x4312 is 0x80000CBB, not 0xCBB. Now we follow specs and wl (noticed in MMIO dumps). Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_chipcommon_pmu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index 5732bb2c3578..305ade7825f7 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c @@ -423,6 +423,8 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) switch (bus->chip_id) { case 0x4312: + min_msk = 0xCBB; + break; case 0x4322: /* We keep the default settings: * min_msk = 0xCBB -- cgit v1.2.3-58-ga151 From 0ff2b5c05d4dd84222a8e163335c5b550e2ca195 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 20 Apr 2011 11:00:34 +0530 Subject: ath9k: Fix warnings from -Wunused-but-set-variable Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 6 ------ drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 -- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 6 +----- drivers/net/wireless/ath/ath9k/eeprom_9287.c | 3 +-- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 6 +++--- drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 4 ++++ drivers/net/wireless/ath/ath9k/htc_drv_main.c | 11 ++++++++++- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 2 -- drivers/net/wireless/ath/ath9k/hw.c | 4 +--- drivers/net/wireless/ath/ath9k/rc.c | 12 ++++-------- drivers/net/wireless/ath/ath9k/recv.c | 3 +-- 11 files changed, 25 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 2e31c775351f..5a1f4f511bc1 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -899,12 +899,6 @@ void ath9k_hw_ani_init(struct ath_hw *ah) * check here default level should not modify INI setting. */ if (use_new_ani(ah)) { - const struct ani_ofdm_level_entry *entry_ofdm; - const struct ani_cck_level_entry *entry_cck; - - entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL]; - entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL]; - ah->aniperiod = ATH9K_ANI_PERIOD_NEW; ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW; } else { diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index fd9b8c400f7e..97f970c5e4ec 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3217,7 +3217,6 @@ static int ar9300_compress_decision(struct ath_hw *ah, u8 *word, int length, int mdata_size) { struct ath_common *common = ath9k_hw_common(ah); - u8 *dptr; const struct ar9300_eeprom *eep = NULL; switch (code) { @@ -3235,7 +3234,6 @@ static int ar9300_compress_decision(struct ath_hw *ah, break; case _CompressBlock: if (reference == 0) { - dptr = mptr; } else { eep = ar9003_eeprom_struct_find_by_id(reference); if (eep == NULL) { diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index ea2f60c08f8b..c83be2dd5718 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -616,29 +616,25 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); unsigned int regWrites = 0, i; struct ieee80211_channel *channel = chan->chan; - u32 modesIndex, freqIndex; + u32 modesIndex; switch (chan->chanmode) { case CHANNEL_A: case CHANNEL_A_HT20: modesIndex = 1; - freqIndex = 1; break; case CHANNEL_A_HT40PLUS: case CHANNEL_A_HT40MINUS: modesIndex = 2; - freqIndex = 1; break; case CHANNEL_G: case CHANNEL_G_HT20: case CHANNEL_B: modesIndex = 4; - freqIndex = 2; break; case CHANNEL_G_HT40PLUS: case CHANNEL_G_HT40MINUS: modesIndex = 3; - freqIndex = 2; break; default: diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 13579752a300..b87db4763098 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -319,10 +319,9 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, u16 numXpdGain, xpdMask; u16 xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0}; u32 reg32, regOffset, regChainOffset, regval; - int16_t modalIdx, diff = 0; + int16_t diff = 0; struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; - modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; xpdMask = pEepData->modalHeader.xpdGain; if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index a157107b3f3b..0ded2c66d5ff 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -74,7 +74,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, __be32 htc_imask = 0; u64 tsf; int num_beacons, offset, dtim_dec_count, cfp_dec_count; - int ret; + int ret __attribute__ ((unused)); u8 cmd_rsp; memset(&bs, 0, sizeof(bs)); @@ -190,7 +190,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, enum ath9k_int imask = 0; u32 nexttbtt, intval, tsftu; __be32 htc_imask = 0; - int ret; + int ret __attribute__ ((unused)); u8 cmd_rsp; u64 tsf; @@ -246,7 +246,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, enum ath9k_int imask = 0; u32 nexttbtt, intval, tsftu; __be32 htc_imask = 0; - int ret; + int ret __attribute__ ((unused)); u8 cmd_rsp; u64 tsf; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index dc0b33d01210..138f8e1350d4 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -74,6 +74,10 @@ static void ath_btcoex_period_work(struct work_struct *work) aggr = priv->op_flags & OP_BT_PRIORITY_DETECTED; WMI_CMD_BUF(WMI_AGGR_LIMIT_CMD, &aggr); + if (ret) { + ath_err(common, "Unable to set BTCOEX parameters\n"); + return; + } ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : btcoex->bt_stomp_type); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 4de38643cb53..7cff5547b8c0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -332,6 +332,11 @@ static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); hvif.index = priv->mon_vif_idx; WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); + if (ret) { + ath_err(common, "Unable to remove monitor interface at idx: %d\n", + priv->mon_vif_idx); + } + priv->nvifs--; priv->vif_slot &= ~(1 << priv->mon_vif_idx); } @@ -964,7 +969,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) struct ath9k_htc_priv *priv = hw->priv; struct ath_hw *ah = priv->ah; struct ath_common *common = ath9k_hw_common(ah); - int ret = 0; + int ret __attribute__ ((unused)); u8 cmd_rsp; mutex_lock(&priv->mutex); @@ -1135,6 +1140,10 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); hvif.index = avp->index; WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); + if (ret) { + ath_err(common, "Unable to remove interface at idx: %d\n", + avp->index); + } priv->nvifs--; priv->vif_slot &= ~(1 << avp->index); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 723a3a9c5cd9..a898dac22337 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -446,7 +446,6 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, struct ieee80211_tx_info *tx_info; struct ieee80211_tx_rate *rate; struct ieee80211_conf *cur_conf = &priv->hw->conf; - struct ieee80211_supported_band *sband; bool txok; int slot; @@ -461,7 +460,6 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, tx_info = IEEE80211_SKB_CB(skb); vif = tx_info->control.vif; rate = &tx_info->status.rates[0]; - sband = priv->hw->wiphy->bands[cur_conf->channel->band]; memset(&tx_info->status, 0, sizeof(tx_info->status)); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index b7eb7930ae38..0fcfa5901a03 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1866,7 +1866,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; - u16 capField = 0, eeval; + u16 eeval; u8 ant_div_ctl1, tx_chainmask, rx_chainmask; eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); @@ -1877,8 +1877,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) eeval |= AR9285_RDEXT_DEFAULT; regulatory->current_rd_ext = eeval; - capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP); - if (ah->opmode != NL80211_IFTYPE_AP && ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { if (regulatory->current_rd == 0x64 || diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 2a40532126f3..b877d9639bdc 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -854,14 +854,13 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, ath_rc_rate_set_rtscts(sc, rate_table, tx_info); } -static bool ath_rc_update_per(struct ath_softc *sc, +static void ath_rc_update_per(struct ath_softc *sc, const struct ath_rate_table *rate_table, struct ath_rate_priv *ath_rc_priv, struct ieee80211_tx_info *tx_info, int tx_rate, int xretries, int retries, u32 now_msec) { - bool state_change = false; int count, n_bad_frames; u8 last_per; static const u32 nretry_to_per_lookup[10] = { @@ -992,8 +991,6 @@ static bool ath_rc_update_per(struct ath_softc *sc, } } - - return state_change; } static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, @@ -1017,7 +1014,6 @@ static void ath_rc_update_ht(struct ath_softc *sc, u32 now_msec = jiffies_to_msecs(jiffies); int rate; u8 last_per; - bool state_change = false; const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; int size = ath_rc_priv->rate_table_size; @@ -1027,9 +1023,9 @@ static void ath_rc_update_ht(struct ath_softc *sc, last_per = ath_rc_priv->per[tx_rate]; /* Update PER first */ - state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv, - tx_info, tx_rate, xretries, - retries, now_msec); + ath_rc_update_per(sc, rate_table, ath_rc_priv, + tx_info, tx_rate, xretries, + retries, now_msec); /* * If this rate looks bad (high PER) then stop using it for diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index b81bfc4d66ef..abff2d5229ee 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1339,7 +1339,7 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) struct ath_hw_antcomb_conf div_ant_conf; struct ath_ant_comb *antcomb = &sc->ant_comb; int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; - int curr_main_set, curr_bias; + int curr_main_set; int main_rssi = rs->rs_rssi_ctl0; int alt_rssi = rs->rs_rssi_ctl1; int rx_ant_conf, main_ant_conf; @@ -1393,7 +1393,6 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); curr_alt_set = div_ant_conf.alt_lna_conf; curr_main_set = div_ant_conf.main_lna_conf; - curr_bias = div_ant_conf.fast_div_bias; antcomb->count++; -- cgit v1.2.3-58-ga151 From 3a0593efd191c7eb13c79179c4c5ddbc519b2510 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 20 Apr 2011 14:33:28 +0530 Subject: ath9k_htc: Fix AMPDU subframe handling * Register the driver's maximum ampdu subframe limit to mac80211. * Cleanup the target capabilities structure and fix an endian issue. * Fix BTCOEX by sending a command to the target when the BT priority changes. * Bump the required firmware version to 1.1 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.h | 3 +++ drivers/net/wireless/ath/ath9k/htc.h | 14 +++++++------- drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 6 ++---- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 17 +++++++++++++++++ drivers/net/wireless/ath/ath9k/htc_drv_main.c | 15 ++++++--------- 5 files changed, 35 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index f59df48a86e2..9a52ccc94d12 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -17,6 +17,9 @@ #ifndef HTC_USB_H #define HTC_USB_H +#define MAJOR_VERSION_REQ 1 +#define MINOR_VERSION_REQ 1 + #define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB)) #define AR9271_FIRMWARE 0x501000 diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 48a885575085..af9082970845 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -106,15 +106,14 @@ struct tx_beacon_header { u16 rev; } __packed; +#define MAX_TX_AMPDU_SUBFRAMES_9271 17 +#define MAX_TX_AMPDU_SUBFRAMES_7010 22 + struct ath9k_htc_cap_target { - u32 flags; - u32 flags_ext; - u32 ampdu_limit; + __be32 ampdu_limit; u8 ampdu_subframes; + u8 enable_coex; u8 tx_chainmask; - u8 tx_chainmask_legacy; - u8 rtscts_ratecode; - u8 protmode; u8 pad; } __packed; @@ -551,7 +550,8 @@ void ath9k_htc_txep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, bool txok); -int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv); +int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, + u8 enable_coex); void ath9k_htc_station_work(struct work_struct *work); void ath9k_htc_aggr_work(struct work_struct *work); void ath9k_htc_ani_work(struct work_struct *work); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 138f8e1350d4..d051a4263e0c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -65,15 +65,13 @@ static void ath_btcoex_period_work(struct work_struct *work) u32 timer_period; bool is_btscan; int ret; - u8 cmd_rsp, aggr; ath_detect_bt_priority(priv); is_btscan = !!(priv->op_flags & OP_BT_SCAN); - aggr = priv->op_flags & OP_BT_PRIORITY_DETECTED; - - WMI_CMD_BUF(WMI_AGGR_LIMIT_CMD, &aggr); + ret = ath9k_htc_update_cap_target(priv, + !!(priv->op_flags & OP_BT_PRIORITY_DETECTED)); if (ret) { ath_err(common, "Unable to set BTCOEX parameters\n"); return; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 06e043bffaf4..dbf5f959cf9b 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -753,6 +753,12 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, hw->queues = 4; hw->channel_change_time = 5000; hw->max_listen_interval = 10; + + if (AR_SREV_9271(priv->ah)) + hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_9271; + else + hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_7010; + hw->vif_data_size = sizeof(struct ath9k_htc_vif); hw->sta_data_size = sizeof(struct ath9k_htc_sta); @@ -802,6 +808,17 @@ static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv) priv->fw_version_major, priv->fw_version_minor); + /* + * Check if the available FW matches the driver's + * required version. + */ + if (priv->fw_version_major != MAJOR_VERSION_REQ || + priv->fw_version_minor != MINOR_VERSION_REQ) { + dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n", + MAJOR_VERSION_REQ, MINOR_VERSION_REQ); + return -EINVAL; + } + return 0; } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 7cff5547b8c0..a6402681d58d 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -563,7 +563,8 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, return 0; } -int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) +int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, + u8 enable_coex) { struct ath9k_htc_cap_target tcap; int ret; @@ -571,13 +572,9 @@ int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); - /* FIXME: Values are hardcoded */ - tcap.flags = 0x240c40; - tcap.flags_ext = 0x80601000; - tcap.ampdu_limit = 0xffff0000; - tcap.ampdu_subframes = 20; - tcap.tx_chainmask_legacy = priv->ah->caps.tx_chainmask; - tcap.protmode = 1; + tcap.ampdu_limit = cpu_to_be32(0xffff); + tcap.ampdu_subframes = priv->hw->max_tx_aggregation_subframes; + tcap.enable_coex = enable_coex; tcap.tx_chainmask = priv->ah->caps.tx_chainmask; WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); @@ -936,7 +933,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) ath9k_host_rx_init(priv); - ret = ath9k_htc_update_cap_target(priv); + ret = ath9k_htc_update_cap_target(priv, 0); if (ret) ath_dbg(common, ATH_DBG_CONFIG, "Failed to update capability in target\n"); -- cgit v1.2.3-58-ga151 From f0dd49803b0c0f3a002f073ec1a82cac5795af2d Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 20 Apr 2011 11:01:00 +0530 Subject: ath9k_htc: Fix max A-MPDU size handling Set the maximum ampdu size of a station correctly in the target by using the ampdu_factor. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index a6402681d58d..fbc238a0b203 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -467,6 +467,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, struct ath9k_htc_sta *ista; int ret, sta_idx; u8 cmd_rsp; + u16 maxampdu; if (priv->nstations >= ATH9K_HTC_MAX_STA) return -ENOBUFS; @@ -490,7 +491,15 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, tsta.sta_index = sta_idx; tsta.vif_index = avp->index; - tsta.maxampdu = cpu_to_be16(0xffff); + + if (!sta) { + tsta.maxampdu = cpu_to_be16(0xffff); + } else { + maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + + sta->ht_cap.ampdu_factor); + tsta.maxampdu = cpu_to_be16(maxampdu); + } + if (sta && sta->ht_cap.ht_supported) tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); -- cgit v1.2.3-58-ga151 From c58ca5b5083befda31009a64abd95ae6ac315265 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 20 Apr 2011 11:01:10 +0530 Subject: ath9k_htc: Use power save wrappers when accessing HW Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 24 +++++++++++++++++++++--- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 ++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index eca777497fe5..894e5ef3f8d1 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -33,9 +33,15 @@ static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf, memset(&cmd_rsp, 0, sizeof(cmd_rsp)); + ath9k_htc_ps_wakeup(priv); + WMI_CMD(WMI_INT_STATS_CMDID); - if (ret) + if (ret) { + ath9k_htc_ps_restore(priv); return -EINVAL; + } + + ath9k_htc_ps_restore(priv); len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "RX", @@ -85,9 +91,15 @@ static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf, memset(&cmd_rsp, 0, sizeof(cmd_rsp)); + ath9k_htc_ps_wakeup(priv); + WMI_CMD(WMI_TX_STATS_CMDID); - if (ret) + if (ret) { + ath9k_htc_ps_restore(priv); return -EINVAL; + } + + ath9k_htc_ps_restore(priv); len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "Xretries", @@ -149,9 +161,15 @@ static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf, memset(&cmd_rsp, 0, sizeof(cmd_rsp)); + ath9k_htc_ps_wakeup(priv); + WMI_CMD(WMI_RX_STATS_CMDID); - if (ret) + if (ret) { + ath9k_htc_ps_restore(priv); return -EINVAL; + } + + ath9k_htc_ps_restore(priv); len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "NoBuf", diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index fbc238a0b203..c8577d5cd0f7 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1582,6 +1582,7 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, int ret = 0; mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); switch (action) { case IEEE80211_AMPDU_RX_START: @@ -1607,6 +1608,7 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); } + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); return ret; -- cgit v1.2.3-58-ga151 From 767ad6a0a2342d42f6f03b50198418b1475e0a7b Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 20 Apr 2011 11:01:25 +0530 Subject: ath9k_htc: Remove unused macros and structures Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 3 --- drivers/net/wireless/ath/ath9k/htc_hst.h | 11 ----------- 2 files changed, 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index af9082970845..55f4bb39c9ec 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -66,8 +66,6 @@ enum htc_opmode { HTC_M_WDS = 2 }; -#define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr) - #define ATH9K_HTC_AMPDU 1 #define ATH9K_HTC_NORMAL 2 #define ATH9K_HTC_BEACON 3 @@ -75,7 +73,6 @@ enum htc_opmode { #define ATH9K_HTC_TX_CTSONLY 0x1 #define ATH9K_HTC_TX_RTSCTS 0x2 -#define ATH9K_HTC_TX_USE_MIN_RATE 0x100 struct tx_frame_hdr { u8 data_type; diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index cb9174ade53e..91a5305db95a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -83,21 +83,10 @@ struct htc_ep_callbacks { void (*rx) (void *, struct sk_buff *, enum htc_endpoint_id); }; -#define HTC_TX_QUEUE_SIZE 256 - -struct htc_txq { - struct sk_buff *buf[HTC_TX_QUEUE_SIZE]; - u32 txqdepth; - u16 txbuf_cnt; - u16 txq_head; - u16 txq_tail; -}; - struct htc_endpoint { u16 service_id; struct htc_ep_callbacks ep_callbacks; - struct htc_txq htc_txq; u32 max_txqdepth; int max_msglen; -- cgit v1.2.3-58-ga151 From 9f2e731d1d278d853def1567735d8a823668a3c8 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 20 Apr 2011 11:12:30 +0200 Subject: ssb: cc: add & fix defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We probably got false positive results for checking PLL being down. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- include/linux/ssb/ssb_driver_chipcommon.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h index 2cdf249b4e5f..4f2d77a0c021 100644 --- a/include/linux/ssb/ssb_driver_chipcommon.h +++ b/include/linux/ssb/ssb_driver_chipcommon.h @@ -131,6 +131,9 @@ #define SSB_CHIPCO_GPIOIRQ 0x0074 #define SSB_CHIPCO_WATCHDOG 0x0080 #define SSB_CHIPCO_GPIOTIMER 0x0088 /* LED powersave (corerev >= 16) */ +#define SSB_CHIPCO_GPIOTIMER_OFFTIME 0x0000FFFF +#define SSB_CHIPCO_GPIOTIMER_OFFTIME_SHIFT 0 +#define SSB_CHIPCO_GPIOTIMER_ONTIME 0xFFFF0000 #define SSB_CHIPCO_GPIOTIMER_ONTIME_SHIFT 16 #define SSB_CHIPCO_GPIOTOUTM 0x008C /* LED powersave (corerev >= 16) */ #define SSB_CHIPCO_CLOCK_N 0x0090 @@ -189,8 +192,10 @@ #define SSB_CHIPCO_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */ #define SSB_CHIPCO_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */ #define SSB_CHIPCO_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */ -#define SSB_CHIPCO_CLKCTLST_HAVEHT 0x00010000 /* HT available */ -#define SSB_CHIPCO_CLKCTLST_HAVEALP 0x00020000 /* APL available */ +#define SSB_CHIPCO_CLKCTLST_HAVEALP 0x00010000 /* ALP available */ +#define SSB_CHIPCO_CLKCTLST_HAVEHT 0x00020000 /* HT available */ +#define SSB_CHIPCO_CLKCTLST_4328A0_HAVEHT 0x00010000 /* 4328a0 has reversed bits */ +#define SSB_CHIPCO_CLKCTLST_4328A0_HAVEALP 0x00020000 /* 4328a0 has reversed bits */ #define SSB_CHIPCO_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ #define SSB_CHIPCO_UART0_DATA 0x0300 #define SSB_CHIPCO_UART0_IMR 0x0304 -- cgit v1.2.3-58-ga151 From 2624e96ce16bacae0e422d5775eac6d4fc33239a Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 20 Apr 2011 16:02:58 +0200 Subject: iwlwifi: fix possible data overwrite in hcmd callback My commit 3598e1774c94e55c71b585340e7dc4538f310e3f "iwlwifi: fix enqueue hcmd race conditions" move hcmd callback after command queue reclaim, to avoid call it with hcmd_lock. But since queue read index was updated, cmd data can be overwritten. Fix problem by calling callback before taking hcmd_lock and queue reclaim. Signed-off-by: Stanislaw Gruszka Acked-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-tx.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 80c3565a66ae..52b1b66f32d0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -621,9 +621,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_cmd_meta *meta; struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; unsigned long flags; - void (*callback) (struct iwl_priv *priv, struct iwl_device_cmd *cmd, - struct iwl_rx_packet *pkt); - /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced @@ -637,8 +634,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) return; } - spin_lock_irqsave(&priv->hcmd_lock, flags); - cmd_index = get_cmd_index(&txq->q, index, huge); cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; @@ -648,13 +643,14 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) dma_unmap_len(meta, len), PCI_DMA_BIDIRECTIONAL); - callback = NULL; /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { meta->source->reply_page = (unsigned long)rxb_addr(rxb); rxb->page = NULL; - } else - callback = meta->callback; + } else if (meta->callback) + meta->callback(priv, cmd, pkt); + + spin_lock_irqsave(&priv->hcmd_lock, flags); iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); @@ -669,7 +665,4 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) meta->flags = 0; spin_unlock_irqrestore(&priv->hcmd_lock, flags); - - if (callback) - callback(priv, cmd, pkt); } -- cgit v1.2.3-58-ga151 From 3a7dbc3b2ac545efac75d4145839eaa7b59d9741 Mon Sep 17 00:00:00 2001 From: Pradeep Nemavat Date: Thu, 21 Apr 2011 16:34:56 +0530 Subject: mwl8k: Do not stop tx queues This is in preparation to support life time expiry of packets in the hardware to avoid head-of-line blocking where a slow client can hog a tx queue and affect the traffic to a faster client from the same queue. Time stamp the packets in driver to allow dropping them in the hardware if they are queued for more than 500ms. If queues are stopped, packets will be queued up outside the driver. Since we will be able to timestamp the packets only after they hit the driver, the timestamp will be less accurate since we cannot consider the time the packets spent in queues outside the driver. With this commit, to achieve accurate timestamping, the tx queues will not be stopped in normal conditions. The only scenarios where the queues will be stopped are when firmware commands are executing or if the interface is brought down. Now, we need to be prepared for a situation where packets hit the driver even after the tx queues are full. Drop all such packets in the driver itself. Signed-off-by: Pradeep Nemavat Signed-off-by: Nishant Sarmukadam Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 28ebaec80be6..33da25a349b7 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1666,10 +1666,6 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) processed++; } - if (index < MWL8K_TX_WMM_QUEUES && processed && priv->radio_on && - !mutex_is_locked(&priv->fw_mutex)) - ieee80211_wake_queue(hw, index); - return processed; } @@ -1951,13 +1947,14 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) txq = priv->txq + index; - if (index >= MWL8K_TX_WMM_QUEUES && txq->len >= MWL8K_TX_DESCS) { - /* This is the case in which the tx packet is destined for an - * AMPDU queue and that AMPDU queue is full. Because we don't - * start and stop the AMPDU queues, we must drop these packets. - */ - dev_kfree_skb(skb); + if (txq->len >= MWL8K_TX_DESCS) { + if (start_ba_session) { + spin_lock(&priv->stream_lock); + mwl8k_remove_stream(hw, stream); + spin_unlock(&priv->stream_lock); + } spin_unlock_bh(&priv->tx_lock); + dev_kfree_skb(skb); return; } @@ -1985,9 +1982,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) if (txq->tail == MWL8K_TX_DESCS) txq->tail = 0; - if (txq->head == txq->tail && index < MWL8K_TX_WMM_QUEUES) - ieee80211_stop_queue(hw, index); - mwl8k_tx_start(priv); spin_unlock_bh(&priv->tx_lock); -- cgit v1.2.3-58-ga151 From 566875db5058f582ea56da891f9c3cabc01efff5 Mon Sep 17 00:00:00 2001 From: Pradeep Nemavat Date: Thu, 21 Apr 2011 16:34:57 +0530 Subject: mwl8k: Add timestamp information for tx packets Timestamp tx packets using a HW micro-second timer. This timestamp will be compared to the current timestamp in the hardware and if the difference is greater than 500ms, the packet will be dropped. Signed-off-by: Pradeep Nemavat Signed-off-by: Nishant Sarmukadam Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 33da25a349b7..93fe1bd91c36 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -74,6 +74,14 @@ MODULE_PARM_DESC(ap_mode_default, #define MWL8K_A2H_INT_RX_READY (1 << 1) #define MWL8K_A2H_INT_TX_DONE (1 << 0) +/* HW micro second timer register + * located at offset 0xA600. This + * will be used to timestamp tx + * packets. + */ + +#define MWL8K_HW_TIMER_REGISTER 0x0000a600 + #define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \ MWL8K_A2H_INT_CHNL_SWITCHED | \ MWL8K_A2H_INT_QUEUE_EMPTY | \ @@ -1972,6 +1980,11 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id; else tx->peer_id = 0; + + if (priv->ap_fw) + tx->timestamp = cpu_to_le32(ioread32(priv->regs + + MWL8K_HW_TIMER_REGISTER)); + wmb(); tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); -- cgit v1.2.3-58-ga151 From 3a769888797b7117005e9c60d4cd73a2efc92f8d Mon Sep 17 00:00:00 2001 From: Nishant Sarmukadam Date: Thu, 21 Apr 2011 16:34:58 +0530 Subject: mwl8k: Reserve buffers for tx management frames Since queues are not stopped anymore, management frames would be dropped if the corresponding tx queue is full. This can cause issues say when we want to setup an ampdu stream and action frames i.e addba requests keep getting dropped frequently. Fix this by reserving some buffers to allow management frames to go through in queue full conditions. Signed-off-by: Nishant Sarmukadam Signed-off-by: Pradeep Nemavat Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 93fe1bd91c36..63ee8cfe322b 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1818,6 +1818,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) u8 tid = 0; struct mwl8k_ampdu_stream *stream = NULL; bool start_ba_session = false; + bool mgmtframe = false; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; wh = (struct ieee80211_hdr *)skb->data; @@ -1826,6 +1827,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) else qos = 0; + if (ieee80211_is_mgmt(wh->frame_control)) + mgmtframe = true; + if (priv->ap_fw) mwl8k_encapsulate_tx_frame(skb); else @@ -1955,15 +1959,26 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) txq = priv->txq + index; - if (txq->len >= MWL8K_TX_DESCS) { - if (start_ba_session) { - spin_lock(&priv->stream_lock); - mwl8k_remove_stream(hw, stream); - spin_unlock(&priv->stream_lock); + /* Mgmt frames that go out frequently are probe + * responses. Other mgmt frames got out relatively + * infrequently. Hence reserve 2 buffers so that + * other mgmt frames do not get dropped due to an + * already queued probe response in one of the + * reserved buffers. + */ + + if (txq->len >= MWL8K_TX_DESCS - 2) { + if (mgmtframe == false || + txq->len == MWL8K_TX_DESCS) { + if (start_ba_session) { + spin_lock(&priv->stream_lock); + mwl8k_remove_stream(hw, stream); + spin_unlock(&priv->stream_lock); + } + spin_unlock_bh(&priv->tx_lock); + dev_kfree_skb(skb); + return; } - spin_unlock_bh(&priv->tx_lock); - dev_kfree_skb(skb); - return; } BUG_ON(txq->skb[txq->tail] != NULL); -- cgit v1.2.3-58-ga151 From 31d291a769b4318cbf7943ca149e04d201e2c931 Mon Sep 17 00:00:00 2001 From: Nishant Sarmukadam Date: Thu, 21 Apr 2011 16:34:59 +0530 Subject: mwl8k: Enable life time expiry for tx packets in the hardware Tell the firmware to enable the life time expiry of tx packets in the hardware. The hardware will now refer to the timestamp in every tx packet and decide whether the packet needs to be dropped or transmitted. Signed-off-by: Nishant Sarmukadam Signed-off-by: Pradeep Nemavat Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 63ee8cfe322b..b8f2b12c8c7c 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2504,7 +2504,8 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT | MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP | - MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON); + MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON | + MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY); cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); -- cgit v1.2.3-58-ga151 From ca45de77ad706e86b135b8564e21aa2c8a63f09b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Apr 2011 13:38:00 +0200 Subject: mac80211: tear down BA sessions properly on suspend Currently, the code to tear down BA sessions will execute after queues are stopped, but attempt to send frames, so those frames will just get queued, which isn't intended. Move this code to before to tear down the sessions properly. Additionally, after stopping queues, flush the TX queues in the driver driver to make sure all the frames went out. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/pm.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index e37355193ed1..042461710880 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -14,12 +14,23 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) ieee80211_scan_cancel(local); + if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { + mutex_lock(&local->sta_mtx); + list_for_each_entry(sta, &local->sta_list, list) { + set_sta_flags(sta, WLAN_STA_BLOCK_BA); + ieee80211_sta_tear_down_BA_sessions(sta, true); + } + mutex_unlock(&local->sta_mtx); + } + ieee80211_stop_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_SUSPEND); /* flush out all packets */ synchronize_net(); + drv_flush(local, false); + local->quiescing = true; /* make quiescing visible to timers everywhere */ mb(); @@ -43,11 +54,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) /* tear down aggregation sessions and remove STAs */ mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) { - if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { - set_sta_flags(sta, WLAN_STA_BLOCK_BA); - ieee80211_sta_tear_down_BA_sessions(sta, true); - } - if (sta->uploaded) { sdata = sta->sdata; if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) -- cgit v1.2.3-58-ga151 From 788f6875fcf5d2bce221fbfd2318ac48df299031 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 21 Apr 2011 18:33:27 +0530 Subject: ath9k: Fix bug in configuring hw timer Hw next tigger time is configured as current_tsf + (timer_period * 10) which is wrong, it should be current_tsf + timer_period. The wrong hw timer configuration would cause btcoex related issues. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/gpio.c | 6 +++--- drivers/net/wireless/ath/ath9k/hw.c | 13 ++++--------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 44a0a886124d..cc5fad6a4019 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -138,10 +138,10 @@ static void ath_detect_bt_priority(struct ath_softc *sc) static void ath9k_gen_timer_start(struct ath_hw *ah, struct ath_gen_timer *timer, - u32 timer_next, + u32 trig_timeout, u32 timer_period) { - ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); + ath9k_hw_gen_timer_start(ah, timer, trig_timeout, timer_period); if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { ath9k_hw_disable_interrupts(ah); @@ -195,7 +195,7 @@ static void ath_btcoex_period_timer(unsigned long data) timer_period = is_btscan ? btcoex->btscan_no_stomp : btcoex->btcoex_no_stomp; - ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, 0, + ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period, timer_period * 10); btcoex->hw_timer_enabled = true; } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 0fcfa5901a03..577ca59b02bf 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2430,11 +2430,11 @@ EXPORT_SYMBOL(ath_gen_timer_alloc); void ath9k_hw_gen_timer_start(struct ath_hw *ah, struct ath_gen_timer *timer, - u32 timer_next, + u32 trig_timeout, u32 timer_period) { struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; - u32 tsf; + u32 tsf, timer_next; BUG_ON(!timer_period); @@ -2442,17 +2442,12 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah, tsf = ath9k_hw_gettsf32(ah); + timer_next = tsf + trig_timeout; + ath_dbg(ath9k_hw_common(ah), ATH_DBG_HWTIMER, "current tsf %x period %x timer_next %x\n", tsf, timer_period, timer_next); - /* - * Pull timer_next forward if the current TSF already passed it - * because of software latency - */ - if (timer_next < tsf) - timer_next = tsf + timer_period; - /* * Program generic timer registers */ -- cgit v1.2.3-58-ga151 From 0a6c9b1b666671a22905d38bc41ec1a04b85832f Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 21 Apr 2011 18:33:28 +0530 Subject: ath9k: Fix warning: symbol 'ath9k_platform_id_table' was not declared. Should it be static? Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ahb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 090f3145e3b3..61956392f2da 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -21,7 +21,7 @@ #include #include "ath9k.h" -const struct platform_device_id ath9k_platform_id_table[] = { +static const struct platform_device_id ath9k_platform_id_table[] = { { .name = "ath9k", .driver_data = AR5416_AR9100_DEVID, -- cgit v1.2.3-58-ga151 From 40db6c77ab48c3f3240422ff92fd6da222e2eb95 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 21 Apr 2011 14:10:27 -0700 Subject: cfg80211: module_param to disable HT40 in 2.4GHz band Currently mac80211 uses ieee80211_disable_40mhz_24ghz module parameter to allow disabling 40MHz operation in the 2.4GHz band. Move this handling from mac80211 to cfg80211 so that the feature will be more generic. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/main.c | 18 ------------------ net/wireless/core.c | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0ab2a8df312d..61877662e8f8 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -33,12 +33,6 @@ #include "cfg.h" #include "debugfs.h" - -static bool ieee80211_disable_40mhz_24ghz; -module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); -MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz, - "Disable 40MHz support in the 2.4GHz band"); - static struct lock_class_key ieee80211_rx_skb_queue_class; void ieee80211_configure_filter(struct ieee80211_local *local) @@ -728,18 +722,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) } channels += sband->n_channels; - /* - * Since ieee80211_disable_40mhz_24ghz is global, we can - * modify the sband's ht data even if the driver uses a - * global structure for that. - */ - if (ieee80211_disable_40mhz_24ghz && - band == IEEE80211_BAND_2GHZ && - sband->ht_cap.ht_supported) { - sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; - } - if (max_bitrates < sband->n_bitrates) max_bitrates = sband->n_bitrates; supp_ht = supp_ht || sband->ht_cap.ht_supported; diff --git a/net/wireless/core.c b/net/wireless/core.c index fe01de29bfe8..bbf1fa11107a 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -46,6 +46,11 @@ static struct dentry *ieee80211_debugfs_dir; /* for the cleanup, scan and event works */ struct workqueue_struct *cfg80211_wq; +static bool cfg80211_disable_40mhz_24ghz; +module_param(cfg80211_disable_40mhz_24ghz, bool, 0644); +MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz, + "Disable 40MHz support in the 2.4GHz band"); + /* requires cfg80211_mutex to be held! */ struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx) { @@ -450,6 +455,18 @@ int wiphy_register(struct wiphy *wiphy) if (WARN_ON(!sband->n_channels || !sband->n_bitrates)) return -EINVAL; + /* + * Since cfg80211_disable_40mhz_24ghz is global, we can + * modify the sband's ht data even if the driver uses a + * global structure for that. + */ + if (cfg80211_disable_40mhz_24ghz && + band == IEEE80211_BAND_2GHZ && + sband->ht_cap.ht_supported) { + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; + } + /* * Since we use a u32 for rate bitmaps in * ieee80211_get_response_rate, we cannot -- cgit v1.2.3-58-ga151 From 353e5019e048562dc8f434c6237d41ef5e758922 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Fri, 22 Apr 2011 11:32:08 +0530 Subject: ath9k: Fix LED gpio for AR93xx chipsets. The LED gpio is incorrectly programmed for AR9300 and so the led is not working propelry. AR93xx uses gpio 10 for LED and not the default. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/gpio.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index a6b538802251..5ebfc57c3110 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -453,6 +453,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc); #define ATH_LED_PIN_DEF 1 #define ATH_LED_PIN_9287 8 +#define ATH_LED_PIN_9300 10 #define ATH_LED_PIN_9485 6 #ifdef CONFIG_MAC80211_LEDS diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index cc5fad6a4019..2c59452a7207 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -46,6 +46,8 @@ void ath_init_leds(struct ath_softc *sc) sc->sc_ah->led_pin = ATH_LED_PIN_9287; else if (AR_SREV_9485(sc->sc_ah)) sc->sc_ah->led_pin = ATH_LED_PIN_9485; + else if (AR_SREV_9300(sc->sc_ah)) + sc->sc_ah->led_pin = ATH_LED_PIN_9300; else sc->sc_ah->led_pin = ATH_LED_PIN_DEF; } -- cgit v1.2.3-58-ga151 From d1c038d620c45fbbc65bcadf813a86bca686dd31 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Fri, 22 Apr 2011 11:32:09 +0530 Subject: ath9k_hw: Fix incorrect baseband PLL phase shift for AR9485 we should program the AR9485 baseband PLL phase shift to 6 and a redundant setting overwrites the correct value. Remove the incorrect and unwnated register setting. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 577ca59b02bf..6166ba0bca54 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -686,7 +686,6 @@ unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) } EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); -#define DPLL3_PHASE_SHIFT_VAL 0x1 static void ath9k_hw_init_pll(struct ath_hw *ah, struct ath9k_channel *chan) { @@ -723,9 +722,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_BB_DPLL2_PLL_PWD, 0x0); udelay(1000); - - REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, - AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); } else if (AR_SREV_9340(ah)) { u32 regval, pll2_divint, pll2_divfrac, refdiv; -- cgit v1.2.3-58-ga151 From 515139066928da040d1482f201ef1b769bc29aa0 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Fri, 22 Apr 2011 11:32:10 +0530 Subject: ath9k: optimize the usage of power save wrappers. We need not wake up the chip even before mutex lock is acquired and also that it is required only if we are going to drain the txq. So place the wrappers accordingly and this change is also useful when there are no pending frames in the txq as we do not wake up the chip unnecessarily. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index e7d6d98ed1cc..dd2fffbbef2e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2211,9 +2211,7 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) int timeout = 200; /* ms */ int i, j; - ath9k_ps_wakeup(sc); mutex_lock(&sc->mutex); - cancel_delayed_work_sync(&sc->tx_complete_work); if (drop) @@ -2236,15 +2234,15 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) goto out; } + ath9k_ps_wakeup(sc); if (!ath_drain_all_txq(sc, false)) ath_reset(sc, false); - + ath9k_ps_restore(sc); ieee80211_wake_queues(hw); out: ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0); mutex_unlock(&sc->mutex); - ath9k_ps_restore(sc); } static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) -- cgit v1.2.3-58-ga151 From 9eab61c2bff2f769ee771a7a9301fb720cec9b56 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Fri, 22 Apr 2011 11:32:11 +0530 Subject: ath9k: cleanup hw pll work handler There is no reason why pll work handler should be part of xmit file. move it to main.c so that reading hw check routines are all in the same place. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 1 + drivers/net/wireless/ath/ath9k/main.c | 23 +++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/xmit.c | 23 ----------------------- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 5ebfc57c3110..0312aa091807 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -423,6 +423,7 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); #define ATH_PAPRD_TIMEOUT 100 /* msecs */ void ath_hw_check(struct work_struct *work); +void ath_hw_pll_work(struct work_struct *work); void ath_paprd_calibrate(struct work_struct *work); void ath_ani_calibrate(unsigned long data); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index e78b6aefa108..b172d1509515 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -801,6 +801,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, INIT_WORK(&sc->hw_check_work, ath_hw_check); INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); + INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); sc->last_rssi = ATH_RSSI_DUMMY_MARKER; ath_init_leds(sc); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index dd2fffbbef2e..94d73c3f4458 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -624,6 +624,29 @@ out: ath9k_ps_restore(sc); } +void ath_hw_pll_work(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + hw_pll_work.work); + static int count; + + if (AR_SREV_9485(sc->sc_ah)) { + if (ar9003_get_pll_sqsum_dvc(sc->sc_ah) >= 0x40000) { + count++; + + if (count == 3) { + /* Rx is hung for more than 500ms. Reset it */ + ath_reset(sc, true); + count = 0; + } + } else + count = 0; + + ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); + } +} + + void ath9k_tasklet(unsigned long data) { struct ath_softc *sc = (struct ath_softc *)data; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 65d46c6ebced..55960fa70dc6 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2180,28 +2180,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) } } -static void ath_hw_pll_work(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, - hw_pll_work.work); - static int count; - - if (AR_SREV_9485(sc->sc_ah)) { - if (ar9003_get_pll_sqsum_dvc(sc->sc_ah) >= 0x40000) { - count++; - - if (count == 3) { - /* Rx is hung for more than 500ms. Reset it */ - ath_reset(sc, true); - count = 0; - } - } else - count = 0; - - ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); - } -} - static void ath_tx_complete_poll_work(struct work_struct *work) { struct ath_softc *sc = container_of(work, struct ath_softc, @@ -2396,7 +2374,6 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) } INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); - INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { error = ath_tx_edma_init(sc); -- cgit v1.2.3-58-ga151 From b84628eb574f04db714d34276383edbe6d8bfd96 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Fri, 22 Apr 2011 11:32:12 +0530 Subject: ath9k: Add power save wrappers and modularize hw_pll handler We should protect hw_pll handler with power save wrappers and also modularize hw_pll handler properly for better readability. Also add a debug message to track chip resets on pll hang condition. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 +- drivers/net/wireless/ath/ath9k/hw.h | 2 +- drivers/net/wireless/ath/ath9k/main.c | 34 ++++++++++++++++++++++++---------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 6166ba0bca54..2b4e7c0225ab 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -673,7 +673,7 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) REGWRITE_BUFFER_FLUSH(ah); } -unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) +u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) { REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); udelay(100); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 29a745c59e63..6a028bd67116 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -932,7 +932,7 @@ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); void ath9k_hw_reset_tsf(struct ath_hw *ah); void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); void ath9k_hw_init_global_settings(struct ath_hw *ah); -unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); +u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); void ath9k_hw_set11nmac2040(struct ath_hw *ah); void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 94d73c3f4458..20a2cf731d83 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -624,23 +624,37 @@ out: ath9k_ps_restore(sc); } +static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) +{ + static int count; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + + if (pll_sqsum >= 0x40000) { + count++; + if (count == 3) { + /* Rx is hung for more than 500ms. Reset it */ + ath_dbg(common, ATH_DBG_RESET, + "Possible RX hang, resetting"); + ath_reset(sc, true); + count = 0; + } + } else + count = 0; +} + void ath_hw_pll_work(struct work_struct *work) { struct ath_softc *sc = container_of(work, struct ath_softc, hw_pll_work.work); - static int count; + u32 pll_sqsum; if (AR_SREV_9485(sc->sc_ah)) { - if (ar9003_get_pll_sqsum_dvc(sc->sc_ah) >= 0x40000) { - count++; - if (count == 3) { - /* Rx is hung for more than 500ms. Reset it */ - ath_reset(sc, true); - count = 0; - } - } else - count = 0; + ath9k_ps_wakeup(sc); + pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); + ath9k_ps_restore(sc); + + ath_hw_pll_rx_hang_check(sc, pll_sqsum); ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); } -- cgit v1.2.3-58-ga151 From cedc7e3d0c847d602d2970120d0e4cca72f364a4 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 22 Apr 2011 13:12:23 +0530 Subject: ath9k: remove the unlikely check for autosleep newer chipsets support auto sleep feature, so remove the unlikely check which does not seems to help anything Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index abff2d5229ee..916b3409a0e8 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1742,7 +1742,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | PS_WAIT_FOR_PSPOLL_DATA)) || - unlikely(ath9k_check_auto_sleep(sc))) + ath9k_check_auto_sleep(sc)) ath_rx_ps(sc, skb); spin_unlock_irqrestore(&sc->sc_pm_lock, flags); -- cgit v1.2.3-58-ga151 From 6dde1aabf6759848512f19d76b89ee473584c46a Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 22 Apr 2011 17:27:01 +0530 Subject: ath9k: Add TSFOOR interrupt stats in debug info This helped the developers to fix an issue of chip not entering network sleep during idle state, previously this was only available as a debug message Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 5 +++++ drivers/net/wireless/ath/ath9k/debug.h | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 34f191ec8e8c..bad1a87249b6 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -326,6 +326,8 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) sc->debug.stats.istats.dtimsync++; if (status & ATH9K_INT_DTIM) sc->debug.stats.istats.dtim++; + if (status & ATH9K_INT_TSFOOR) + sc->debug.stats.istats.tsfoor++; } static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, @@ -379,9 +381,12 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, "%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync); len += snprintf(buf + len, sizeof(buf) - len, "%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "TSFOOR", sc->debug.stats.istats.tsfoor); len += snprintf(buf + len, sizeof(buf) - len, "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); + if (len > sizeof(buf)) len = sizeof(buf); diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 1f9f8eada465..5488a324cc10 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -54,6 +54,9 @@ struct ath_buf; * @dtimsync: DTIM sync lossage * @dtim: RX Beacon with DTIM * @bb_watchdog: Baseband watchdog + * @tsfoor: TSF out of range, indicates that the corrected TSF received + * from a beacon differs from the PCU's internal TSF by more than a + * (programmable) threshold */ struct ath_interrupt_stats { u32 total; @@ -78,6 +81,7 @@ struct ath_interrupt_stats { u32 dtimsync; u32 dtim; u32 bb_watchdog; + u32 tsfoor; }; /** -- cgit v1.2.3-58-ga151 From 9835a30e980561082beb02ce724f6e555787bc19 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 24 Apr 2011 11:04:19 +0200 Subject: ssb: cc: clear GPIOPULL registers on init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_chipcommon.c | 6 ++++++ include/linux/ssb/ssb_driver_chipcommon.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 7c031fdc8205..b4b3733aefcf 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c @@ -260,6 +260,12 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc) if (cc->dev->id.revision >= 11) cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); + + if (cc->dev->id.revision >= 20) { + chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0); + chipco_write32(cc, SSB_CHIPCO_GPIOPULLDOWN, 0); + } + ssb_pmu_init(cc); chipco_powercontrol_init(cc); ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h index 4f2d77a0c021..a08d693d8324 100644 --- a/include/linux/ssb/ssb_driver_chipcommon.h +++ b/include/linux/ssb/ssb_driver_chipcommon.h @@ -123,6 +123,8 @@ #define SSB_CHIPCO_FLASHDATA 0x0048 #define SSB_CHIPCO_BCAST_ADDR 0x0050 #define SSB_CHIPCO_BCAST_DATA 0x0054 +#define SSB_CHIPCO_GPIOPULLUP 0x0058 /* Rev >= 20 only */ +#define SSB_CHIPCO_GPIOPULLDOWN 0x005C /* Rev >= 20 only */ #define SSB_CHIPCO_GPIOIN 0x0060 #define SSB_CHIPCO_GPIOOUT 0x0064 #define SSB_CHIPCO_GPIOOUTEN 0x0068 -- cgit v1.2.3-58-ga151 From 22d5969fb450afd3a4aff606360f7d52c5a3a628 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 21 Apr 2011 12:42:15 +0000 Subject: net: make WARN_ON in dev_disable_lro() useful MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 379c993ff421..541f22a035a2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1315,7 +1315,8 @@ void dev_disable_lro(struct net_device *dev) return; __ethtool_set_flags(dev, flags & ~ETH_FLAG_LRO); - WARN_ON(dev->features & NETIF_F_LRO); + if (unlikely(dev->features & NETIF_F_LRO)) + netdev_WARN(dev, "failed to disable LRO!\n"); } EXPORT_SYMBOL(dev_disable_lro); -- cgit v1.2.3-58-ga151 From 3aba891dde3842d89ad022237b99c1ed308040b0 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 19 Apr 2011 03:48:16 +0000 Subject: bonding: move processing of recv handlers into handle_frame() Since now when bonding uses rx_handler, all traffic going into bond device goes thru bond_handle_frame. So there's no need to go back into bonding code later via ptype handlers. This patch converts original ptype handlers into "bonding receive probes". These functions are called from bond_handle_frame and they are registered per-mode. Note that vlan packets are also handled because they are always untagged thanks to vlan_untag() Note that this also allows arpmon for eth-bond-bridge-vlan topology. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 29 ++-------- drivers/net/bonding/bond_3ad.h | 4 +- drivers/net/bonding/bond_alb.c | 46 ++++----------- drivers/net/bonding/bond_alb.h | 1 - drivers/net/bonding/bond_main.c | 121 ++++++++------------------------------- drivers/net/bonding/bond_sysfs.c | 6 -- drivers/net/bonding/bonding.h | 4 +- net/core/dev.c | 21 ------- 8 files changed, 43 insertions(+), 189 deletions(-) diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 123dd602261f..d0981c2ffbda 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2465,35 +2465,16 @@ out: return NETDEV_TX_OK; } -int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev) +void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond, + struct slave *slave) { - struct bonding *bond = netdev_priv(dev); - struct slave *slave = NULL; - int ret = NET_RX_DROP; - - if (!(dev->flags & IFF_MASTER)) - goto out; - - skb = skb_share_check(skb, GFP_ATOMIC); - if (!skb) - goto out; + if (skb->protocol != PKT_TYPE_LACPDU) + return; if (!pskb_may_pull(skb, sizeof(struct lacpdu))) - goto out; + return; read_lock(&bond->lock); - slave = bond_get_slave_by_dev(netdev_priv(dev), orig_dev); - if (!slave) - goto out_unlock; - bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len); - - ret = NET_RX_SUCCESS; - -out_unlock: read_unlock(&bond->lock); -out: - dev_kfree_skb(skb); - - return ret; } diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h index b28baff70864..291dbd4d1f3d 100644 --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h @@ -258,7 +258,6 @@ struct ad_bond_info { * requested */ struct timer_list ad_timer; - struct packet_type ad_pkt_type; }; struct ad_slave_info { @@ -280,7 +279,8 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave); void bond_3ad_handle_link_change(struct slave *slave, char link); int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info); int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev); -int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev); +void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond, + struct slave *slave); int bond_3ad_set_carrier(struct bonding *bond); #endif //__BOND_3AD_H__ diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index ba715826e2a8..3b7b0409406f 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -308,49 +308,33 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp) _unlock_rx_hashtbl(bond); } -static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct packet_type *ptype, struct net_device *orig_dev) +static void rlb_arp_recv(struct sk_buff *skb, struct bonding *bond, + struct slave *slave) { - struct bonding *bond; - struct arp_pkt *arp = (struct arp_pkt *)skb->data; - int res = NET_RX_DROP; + struct arp_pkt *arp; - while (bond_dev->priv_flags & IFF_802_1Q_VLAN) - bond_dev = vlan_dev_real_dev(bond_dev); - - if (!(bond_dev->priv_flags & IFF_BONDING) || - !(bond_dev->flags & IFF_MASTER)) - goto out; + if (skb->protocol != cpu_to_be16(ETH_P_ARP)) + return; + arp = (struct arp_pkt *) skb->data; if (!arp) { pr_debug("Packet has no ARP data\n"); - goto out; + return; } - skb = skb_share_check(skb, GFP_ATOMIC); - if (!skb) - goto out; - - if (!pskb_may_pull(skb, arp_hdr_len(bond_dev))) - goto out; + if (!pskb_may_pull(skb, arp_hdr_len(bond->dev))) + return; if (skb->len < sizeof(struct arp_pkt)) { pr_debug("Packet is too small to be an ARP\n"); - goto out; + return; } if (arp->op_code == htons(ARPOP_REPLY)) { /* update rx hash table for this ARP */ - bond = netdev_priv(bond_dev); rlb_update_entry_from_arp(bond, arp); pr_debug("Server received an ARP Reply from client\n"); } - - res = NET_RX_SUCCESS; - -out: - dev_kfree_skb(skb); - - return res; } /* Caller must hold bond lock for read */ @@ -759,7 +743,6 @@ static void rlb_init_table_entry(struct rlb_client_info *entry) static int rlb_initialize(struct bonding *bond) { struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); - struct packet_type *pk_type = &(BOND_ALB_INFO(bond).rlb_pkt_type); struct rlb_client_info *new_hashtbl; int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info); int i; @@ -784,13 +767,8 @@ static int rlb_initialize(struct bonding *bond) _unlock_rx_hashtbl(bond); - /*initialize packet type*/ - pk_type->type = cpu_to_be16(ETH_P_ARP); - pk_type->dev = bond->dev; - pk_type->func = rlb_arp_recv; - /* register to receive ARPs */ - dev_add_pack(pk_type); + bond->recv_probe = rlb_arp_recv; return 0; } @@ -799,8 +777,6 @@ static void rlb_deinitialize(struct bonding *bond) { struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); - dev_remove_pack(&(bond_info->rlb_pkt_type)); - _lock_rx_hashtbl(bond); kfree(bond_info->rx_hashtbl); diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h index 8ca7158b2dda..90f140a2d197 100644 --- a/drivers/net/bonding/bond_alb.h +++ b/drivers/net/bonding/bond_alb.h @@ -129,7 +129,6 @@ struct alb_bond_info { int lp_counter; /* -------- rlb parameters -------- */ int rlb_enabled; - struct packet_type rlb_pkt_type; struct rlb_client_info *rx_hashtbl; /* Receive hash table */ spinlock_t rx_hashtbl_lock; u32 rx_hashtbl_head; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 4ce14bdf96dd..66d9dc6e5cac 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1439,27 +1439,17 @@ static void bond_setup_by_slave(struct net_device *bond_dev, } /* On bonding slaves other than the currently active slave, suppress - * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and - * ARP on active-backup slaves with arp_validate enabled. + * duplicates except for alb non-mcast/bcast. */ static bool bond_should_deliver_exact_match(struct sk_buff *skb, struct slave *slave, struct bonding *bond) { if (bond_is_slave_inactive(slave)) { - if (slave_do_arp_validate(bond, slave) && - skb->protocol == __cpu_to_be16(ETH_P_ARP)) - return false; - if (bond->params.mode == BOND_MODE_ALB && skb->pkt_type != PACKET_BROADCAST && skb->pkt_type != PACKET_MULTICAST) - return false; - - if (bond->params.mode == BOND_MODE_8023AD && - skb->protocol == __cpu_to_be16(ETH_P_SLOW)) return false; - return true; } return false; @@ -1483,6 +1473,15 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb) if (bond->params.arp_interval) slave->dev->last_rx = jiffies; + if (bond->recv_probe) { + struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); + + if (likely(nskb)) { + bond->recv_probe(nskb, bond, slave); + dev_kfree_skb(nskb); + } + } + if (bond_should_deliver_exact_match(skb, slave, bond)) { return RX_HANDLER_EXACT; } @@ -2743,48 +2742,26 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 } } -static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) +static void bond_arp_rcv(struct sk_buff *skb, struct bonding *bond, + struct slave *slave) { struct arphdr *arp; - struct slave *slave; - struct bonding *bond; unsigned char *arp_ptr; __be32 sip, tip; - if (dev->priv_flags & IFF_802_1Q_VLAN) { - /* - * When using VLANS and bonding, dev and oriv_dev may be - * incorrect if the physical interface supports VLAN - * acceleration. With this change ARP validation now - * works for hosts only reachable on the VLAN interface. - */ - dev = vlan_dev_real_dev(dev); - orig_dev = dev_get_by_index_rcu(dev_net(skb->dev),skb->skb_iif); - } - - if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER)) - goto out; + if (skb->protocol != __cpu_to_be16(ETH_P_ARP)) + return; - bond = netdev_priv(dev); read_lock(&bond->lock); - pr_debug("bond_arp_rcv: bond %s skb->dev %s orig_dev %s\n", - bond->dev->name, skb->dev ? skb->dev->name : "NULL", - orig_dev ? orig_dev->name : "NULL"); + pr_debug("bond_arp_rcv: bond %s skb->dev %s\n", + bond->dev->name, skb->dev->name); - slave = bond_get_slave_by_dev(bond, orig_dev); - if (!slave || !slave_do_arp_validate(bond, slave)) - goto out_unlock; - - skb = skb_share_check(skb, GFP_ATOMIC); - if (!skb) - goto out_unlock; - - if (!pskb_may_pull(skb, arp_hdr_len(dev))) + if (!pskb_may_pull(skb, arp_hdr_len(bond->dev))) goto out_unlock; arp = arp_hdr(skb); - if (arp->ar_hln != dev->addr_len || + if (arp->ar_hln != bond->dev->addr_len || skb->pkt_type == PACKET_OTHERHOST || skb->pkt_type == PACKET_LOOPBACK || arp->ar_hrd != htons(ARPHRD_ETHER) || @@ -2793,9 +2770,9 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack goto out_unlock; arp_ptr = (unsigned char *)(arp + 1); - arp_ptr += dev->addr_len; + arp_ptr += bond->dev->addr_len; memcpy(&sip, arp_ptr, 4); - arp_ptr += 4 + dev->addr_len; + arp_ptr += 4 + bond->dev->addr_len; memcpy(&tip, arp_ptr, 4); pr_debug("bond_arp_rcv: %s %s/%d av %d sv %d sip %pI4 tip %pI4\n", @@ -2818,9 +2795,6 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack out_unlock: read_unlock(&bond->lock); -out: - dev_kfree_skb(skb); - return NET_RX_SUCCESS; } /* @@ -3407,48 +3381,6 @@ static struct notifier_block bond_inetaddr_notifier = { .notifier_call = bond_inetaddr_event, }; -/*-------------------------- Packet type handling ---------------------------*/ - -/* register to receive lacpdus on a bond */ -static void bond_register_lacpdu(struct bonding *bond) -{ - struct packet_type *pk_type = &(BOND_AD_INFO(bond).ad_pkt_type); - - /* initialize packet type */ - pk_type->type = PKT_TYPE_LACPDU; - pk_type->dev = bond->dev; - pk_type->func = bond_3ad_lacpdu_recv; - - dev_add_pack(pk_type); -} - -/* unregister to receive lacpdus on a bond */ -static void bond_unregister_lacpdu(struct bonding *bond) -{ - dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type)); -} - -void bond_register_arp(struct bonding *bond) -{ - struct packet_type *pt = &bond->arp_mon_pt; - - if (pt->type) - return; - - pt->type = htons(ETH_P_ARP); - pt->dev = bond->dev; - pt->func = bond_arp_rcv; - dev_add_pack(pt); -} - -void bond_unregister_arp(struct bonding *bond) -{ - struct packet_type *pt = &bond->arp_mon_pt; - - dev_remove_pack(pt); - pt->type = 0; -} - /*---------------------------- Hashing Policies -----------------------------*/ /* @@ -3542,14 +3474,14 @@ static int bond_open(struct net_device *bond_dev) queue_delayed_work(bond->wq, &bond->arp_work, 0); if (bond->params.arp_validate) - bond_register_arp(bond); + bond->recv_probe = bond_arp_rcv; } if (bond->params.mode == BOND_MODE_8023AD) { INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler); queue_delayed_work(bond->wq, &bond->ad_work, 0); /* register to receive LACPDUs */ - bond_register_lacpdu(bond); + bond->recv_probe = bond_3ad_lacpdu_recv; bond_3ad_initiate_agg_selection(bond, 1); } @@ -3560,14 +3492,6 @@ static int bond_close(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); - if (bond->params.mode == BOND_MODE_8023AD) { - /* Unregister the receive of LACPDUs */ - bond_unregister_lacpdu(bond); - } - - if (bond->params.arp_validate) - bond_unregister_arp(bond); - write_lock_bh(&bond->lock); /* signal timers not to re-arm */ @@ -3604,6 +3528,7 @@ static int bond_close(struct net_device *bond_dev) */ bond_alb_deinitialize(bond); } + bond->recv_probe = NULL; return 0; } diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 259ff32cd573..935406aa5f0c 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -422,11 +422,6 @@ static ssize_t bonding_store_arp_validate(struct device *d, bond->dev->name, arp_validate_tbl[new_value].modename, new_value); - if (!bond->params.arp_validate && new_value) - bond_register_arp(bond); - else if (bond->params.arp_validate && !new_value) - bond_unregister_arp(bond); - bond->params.arp_validate = new_value; return count; @@ -923,7 +918,6 @@ static ssize_t bonding_store_miimon(struct device *d, bond->dev->name); bond->params.arp_interval = 0; if (bond->params.arp_validate) { - bond_unregister_arp(bond); bond->params.arp_validate = BOND_ARP_VALIDATE_NONE; } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 6126c6a13a74..85fb8220e283 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -226,6 +226,8 @@ struct bonding { struct slave *primary_slave; bool force_primary; s32 slave_cnt; /* never change this value outside the attach/detach wrappers */ + void (*recv_probe)(struct sk_buff *, struct bonding *, + struct slave *); rwlock_t lock; rwlock_t curr_slave_lock; s8 kill_timers; @@ -399,8 +401,6 @@ void bond_set_mode_ops(struct bonding *bond, int mode); int bond_parse_parm(const char *mode_arg, const struct bond_parm_tbl *tbl); void bond_select_active_slave(struct bonding *bond); void bond_change_active_slave(struct bonding *bond, struct slave *new_active); -void bond_register_arp(struct bonding *); -void bond_unregister_arp(struct bonding *); void bond_create_debugfs(void); void bond_destroy_debugfs(void); void bond_debug_register(struct bonding *bond); diff --git a/net/core/dev.c b/net/core/dev.c index 541f22a035a2..3bbb4c2ce92e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3077,25 +3077,6 @@ void netdev_rx_handler_unregister(struct net_device *dev) } EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); -static void vlan_on_bond_hook(struct sk_buff *skb) -{ - /* - * Make sure ARP frames received on VLAN interfaces stacked on - * bonding interfaces still make their way to any base bonding - * device that may have registered for a specific ptype. - */ - if (skb->dev->priv_flags & IFF_802_1Q_VLAN && - vlan_dev_real_dev(skb->dev)->priv_flags & IFF_BONDING && - skb->protocol == htons(ETH_P_ARP)) { - struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); - - if (!skb2) - return; - skb2->dev = vlan_dev_real_dev(skb->dev); - netif_rx(skb2); - } -} - static int __netif_receive_skb(struct sk_buff *skb) { struct packet_type *ptype, *pt_prev; @@ -3191,8 +3172,6 @@ ncls: goto out; } - vlan_on_bond_hook(skb); - /* deliver only exact match when indicated */ null_or_dev = deliver_exact ? skb->dev : NULL; -- cgit v1.2.3-58-ga151 From fe2a70eefa18a3e419dd9a23e16af14258b7cc20 Mon Sep 17 00:00:00 2001 From: Somnath Kotur Date: Thu, 21 Apr 2011 03:18:12 +0000 Subject: be2net: Fixed a bug in be_cmd_get_regs(). Same WRB entry was being reused over different iterations of a loop while issuing non-embedded IOCTL requests.Fixed couple of minor bugs in this path as well. Re-factored code to alloc/free memory for DMA outside of loop Signed-off-by: Somnath Kotur Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 53 ++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index af8cf3d7c1e3..0fc06d363806 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1214,8 +1214,8 @@ int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size) if (!status) { struct be_cmd_resp_get_fat *resp = embedded_payload(wrb); if (log_size && resp->log_size) - *log_size = le32_to_cpu(resp->log_size - - sizeof(u32)); + *log_size = le32_to_cpu(resp->log_size) - + sizeof(u32); } err: spin_unlock_bh(&adapter->mcc_lock); @@ -1228,7 +1228,8 @@ void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf) struct be_mcc_wrb *wrb; struct be_cmd_req_get_fat *req; struct be_sge *sge; - u32 offset = 0, total_size, buf_size, log_offset = sizeof(u32); + u32 offset = 0, total_size, buf_size, + log_offset = sizeof(u32), payload_len; int status; if (buf_len == 0) @@ -1236,37 +1237,39 @@ void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf) total_size = buf_len; + get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024; + get_fat_cmd.va = pci_alloc_consistent(adapter->pdev, + get_fat_cmd.size, + &get_fat_cmd.dma); + if (!get_fat_cmd.va) { + status = -ENOMEM; + dev_err(&adapter->pdev->dev, + "Memory allocation failure while retrieving FAT data\n"); + return; + } + spin_lock_bh(&adapter->mcc_lock); - wrb = wrb_from_mccq(adapter); - if (!wrb) { - status = -EBUSY; - goto err; - } while (total_size) { buf_size = min(total_size, (u32)60*1024); total_size -= buf_size; - get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + buf_size; - get_fat_cmd.va = pci_alloc_consistent(adapter->pdev, - get_fat_cmd.size, - &get_fat_cmd.dma); - if (!get_fat_cmd.va) { - status = -ENOMEM; - dev_err(&adapter->pdev->dev, - "Memory allocation failure while retrieving FAT data\n"); + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; goto err; } req = get_fat_cmd.va; sge = nonembedded_sgl(wrb); - be_wrb_hdr_prepare(wrb, get_fat_cmd.size, false, 1, + payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size; + be_wrb_hdr_prepare(wrb, payload_len, false, 1, OPCODE_COMMON_MANAGE_FAT); be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, - OPCODE_COMMON_MANAGE_FAT, get_fat_cmd.size); + OPCODE_COMMON_MANAGE_FAT, payload_len); - sge->pa_hi = cpu_to_le32(upper_32_bits(get_fat_cmd.size)); + sge->pa_hi = cpu_to_le32(upper_32_bits(get_fat_cmd.dma)); sge->pa_lo = cpu_to_le32(get_fat_cmd.dma & 0xFFFFFFFF); sge->len = cpu_to_le32(get_fat_cmd.size); @@ -1281,17 +1284,17 @@ void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf) memcpy(buf + offset, resp->data_buffer, resp->read_log_length); - } - pci_free_consistent(adapter->pdev, get_fat_cmd.size, - get_fat_cmd.va, - get_fat_cmd.dma); - if (status) + } else { dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n"); - + goto err; + } offset += buf_size; log_offset += buf_size; } err: + pci_free_consistent(adapter->pdev, get_fat_cmd.size, + get_fat_cmd.va, + get_fat_cmd.dma); spin_unlock_bh(&adapter->mcc_lock); } -- cgit v1.2.3-58-ga151 From bf734843120b905bacc3d24c88d7455ae70bf6e1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 25 Apr 2011 13:03:02 -0700 Subject: bluetooth: Fix use-before-initiailized var. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit net/bluetooth/l2cap_core.c: In function ‘l2cap_recv_frame’: net/bluetooth/l2cap_core.c:3612:15: warning: ‘sk’ may be used uninitialized in this function net/bluetooth/l2cap_core.c:3612:15: note: ‘sk’ was declared here Actually the problem is in the inline function l2cap_data_channel(), we branch to the label 'done' which tests 'sk' before we set it to anything. Initialize it to NULL to fix this. Signed-off-by: David S. Miller --- net/bluetooth/l2cap_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index d47de2b04b2e..8cfa2a663028 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -3609,7 +3609,7 @@ drop: static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) { struct l2cap_chan *chan; - struct sock *sk; + struct sock *sk = NULL; struct l2cap_pinfo *pi; u16 control; u8 tx_seq; -- cgit v1.2.3-58-ga151 From 0aebff4871d26410ae485b521870bb0ffe1736f0 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 25 Apr 2011 12:42:45 +0000 Subject: tg3: Fix int generation hw bug for 5719 / 5720 On the 5719 and 5720, there is a bug where the hardware will misinterpret a status tag update and leave interrupts permanently disabled. This patch enables a hardware fix that works around the issue. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 3 +++ drivers/net/tg3.h | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 693f36e94dab..a72d0314ca78 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8198,6 +8198,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) ~DMA_RWCTRL_DIS_CACHE_ALIGNMENT; if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) val &= ~DMA_RWCTRL_CRDRDR_RDMA_MRRS_MSK; + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) + val |= DMA_RWCTRL_TAGGED_STAT_WA; tw32(TG3PCI_DMA_RW_CTRL, val | tp->dma_rwctrl); } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) { diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index eaa76694efb5..6f37d2a23544 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -188,6 +188,7 @@ #define METAL_REV_B2 0x02 #define TG3PCI_DMA_RW_CTRL 0x0000006c #define DMA_RWCTRL_DIS_CACHE_ALIGNMENT 0x00000001 +#define DMA_RWCTRL_TAGGED_STAT_WA 0x00000080 #define DMA_RWCTRL_CRDRDR_RDMA_MRRS_MSK 0x00000380 #define DMA_RWCTRL_READ_BNDRY_MASK 0x00000700 #define DMA_RWCTRL_READ_BNDRY_DISAB 0x00000000 -- cgit v1.2.3-58-ga151 From 00c266b794d589dcf7d280926dfc27c5896a410a Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 25 Apr 2011 12:42:46 +0000 Subject: tg3: Organize loopback test failure flags As more test modes are added to each loopback mode, the need to organise the results increases. This patch groups the results by loopback mode, and then by test mode. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index a72d0314ca78..88cd23171510 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -11276,10 +11276,12 @@ out: return err; } -#define TG3_MAC_LOOPBACK_FAILED 1 -#define TG3_PHY_LOOPBACK_FAILED 2 -#define TG3_LOOPBACK_FAILED (TG3_MAC_LOOPBACK_FAILED | \ - TG3_PHY_LOOPBACK_FAILED) +#define TG3_STD_LOOPBACK_FAILED 1 +#define TG3_JMB_LOOPBACK_FAILED 2 + +#define TG3_MAC_LOOPBACK_SHIFT 0 +#define TG3_PHY_LOOPBACK_SHIFT 4 +#define TG3_LOOPBACK_FAILED 0x00000033 static int tg3_test_loopback(struct tg3 *tp) { @@ -11338,11 +11340,11 @@ static int tg3_test_loopback(struct tg3 *tp) } if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_MAC_LOOPBACK)) - err |= TG3_MAC_LOOPBACK_FAILED; + err |= TG3_STD_LOOPBACK_FAILED << TG3_MAC_LOOPBACK_SHIFT; if ((tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) && tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_MAC_LOOPBACK)) - err |= (TG3_MAC_LOOPBACK_FAILED << 2); + err |= TG3_JMB_LOOPBACK_FAILED << TG3_MAC_LOOPBACK_SHIFT; if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) { tw32(TG3_CPMU_CTRL, cpmuctrl); @@ -11354,10 +11356,12 @@ static int tg3_test_loopback(struct tg3 *tp) if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) && !(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_PHY_LOOPBACK)) - err |= TG3_PHY_LOOPBACK_FAILED; + err |= TG3_STD_LOOPBACK_FAILED << + TG3_PHY_LOOPBACK_SHIFT; if ((tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) && tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_PHY_LOOPBACK)) - err |= (TG3_PHY_LOOPBACK_FAILED << 2); + err |= TG3_JMB_LOOPBACK_FAILED << + TG3_PHY_LOOPBACK_SHIFT; } /* Re-enable gphy autopowerdown. */ -- cgit v1.2.3-58-ga151 From bb158d696489244f79fd4c3abd47968a06b48c79 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 25 Apr 2011 12:42:47 +0000 Subject: tg3: Add TSO loopback test This patch adds code to exercise the TSO portion of the device through a phy loopback test. Signed-off-by: Matt Carlson Signed-off-by: Benjamin Li Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 158 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 123 insertions(+), 35 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 88cd23171510..fb2139a80700 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -11076,11 +11076,35 @@ static int tg3_test_memory(struct tg3 *tp) #define TG3_MAC_LOOPBACK 0 #define TG3_PHY_LOOPBACK 1 +#define TG3_TSO_LOOPBACK 2 + +#define TG3_TSO_MSS 500 + +#define TG3_TSO_IP_HDR_LEN 20 +#define TG3_TSO_TCP_HDR_LEN 20 +#define TG3_TSO_TCP_OPT_LEN 12 + +static const u8 tg3_tso_header[] = { +0x08, 0x00, +0x45, 0x00, 0x00, 0x00, +0x00, 0x00, 0x40, 0x00, +0x40, 0x06, 0x00, 0x00, +0x0a, 0x00, 0x00, 0x01, +0x0a, 0x00, 0x00, 0x02, +0x0d, 0x00, 0xe0, 0x00, +0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x02, 0x00, +0x80, 0x10, 0x10, 0x00, +0x14, 0x09, 0x00, 0x00, +0x01, 0x01, 0x08, 0x0a, +0x11, 0x11, 0x11, 0x11, +0x11, 0x11, 0x11, 0x11, +}; static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) { u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key; - u32 desc_idx, coal_now; + u32 base_flags = 0, mss = 0, desc_idx, coal_now, data_off, val; struct sk_buff *skb, *rx_skb; u8 *tx_data; dma_addr_t map; @@ -11119,9 +11143,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) else mac_mode |= MAC_MODE_PORT_MODE_GMII; tw32(MAC_MODE, mac_mode); - } else if (loopback_mode == TG3_PHY_LOOPBACK) { - u32 val; - + } else { if (tp->phy_flags & TG3_PHYFLG_IS_FET) { tg3_phy_fet_toggle_apd(tp, false); val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100; @@ -11169,8 +11191,6 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) break; mdelay(1); } - } else { - return -EINVAL; } err = -EIO; @@ -11186,7 +11206,54 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) tw32(MAC_RX_MTU_SIZE, tx_len + ETH_FCS_LEN); - for (i = 14; i < tx_len; i++) + if (loopback_mode == TG3_TSO_LOOPBACK) { + struct iphdr *iph = (struct iphdr *)&tx_data[ETH_HLEN]; + + u32 hdr_len = TG3_TSO_IP_HDR_LEN + TG3_TSO_TCP_HDR_LEN + + TG3_TSO_TCP_OPT_LEN; + + memcpy(tx_data + ETH_ALEN * 2, tg3_tso_header, + sizeof(tg3_tso_header)); + mss = TG3_TSO_MSS; + + val = tx_len - ETH_ALEN * 2 - sizeof(tg3_tso_header); + num_pkts = DIV_ROUND_UP(val, TG3_TSO_MSS); + + /* Set the total length field in the IP header */ + iph->tot_len = htons((u16)(mss + hdr_len)); + + base_flags = (TXD_FLAG_CPU_PRE_DMA | + TXD_FLAG_CPU_POST_DMA); + + if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { + struct tcphdr *th; + val = ETH_HLEN + TG3_TSO_IP_HDR_LEN; + th = (struct tcphdr *)&tx_data[val]; + th->check = 0; + } else + base_flags |= TXD_FLAG_TCPUDP_CSUM; + + if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) { + mss |= (hdr_len & 0xc) << 12; + if (hdr_len & 0x10) + base_flags |= 0x00000010; + base_flags |= (hdr_len & 0x3e0) << 5; + } else if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) + mss |= hdr_len << 9; + else if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + mss |= (TG3_TSO_TCP_OPT_LEN << 9); + } else { + base_flags |= (TG3_TSO_TCP_OPT_LEN << 10); + } + + data_off = ETH_ALEN * 2 + sizeof(tg3_tso_header); + } else { + num_pkts = 1; + data_off = ETH_HLEN; + } + + for (i = data_off; i < tx_len; i++) tx_data[i] = (u8) (i & 0xff); map = pci_map_single(tp->pdev, skb->data, tx_len, PCI_DMA_TODEVICE); @@ -11202,12 +11269,10 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) rx_start_idx = rnapi->hw_status->idx[0].rx_producer; - num_pkts = 0; - - tg3_set_txd(tnapi, tnapi->tx_prod, map, tx_len, 0, 1); + tg3_set_txd(tnapi, tnapi->tx_prod, map, tx_len, + base_flags, (mss << 1) | 1); tnapi->tx_prod++; - num_pkts++; tw32_tx_mbox(tnapi->prodmbox, tnapi->tx_prod); tr32_mailbox(tnapi->prodmbox); @@ -11237,38 +11302,56 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) if (rx_idx != rx_start_idx + num_pkts) goto out; - desc = &rnapi->rx_rcb[rx_start_idx]; - desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; - opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; + val = data_off; + while (rx_idx != rx_start_idx) { + desc = &rnapi->rx_rcb[rx_start_idx++]; + desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; + opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; - if ((desc->err_vlan & RXD_ERR_MASK) != 0 && - (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) - goto out; + if ((desc->err_vlan & RXD_ERR_MASK) != 0 && + (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) + goto out; - rx_len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; - if (rx_len != tx_len) - goto out; + rx_len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) + - ETH_FCS_LEN; - if (pktsz <= TG3_RX_STD_DMA_SZ - ETH_FCS_LEN) { - if (opaque_key != RXD_OPAQUE_RING_STD) - goto out; + if (loopback_mode != TG3_TSO_LOOPBACK) { + if (rx_len != tx_len) + goto out; - rx_skb = tpr->rx_std_buffers[desc_idx].skb; - map = dma_unmap_addr(&tpr->rx_std_buffers[desc_idx], mapping); - } else { - if (opaque_key != RXD_OPAQUE_RING_JUMBO) + if (pktsz <= TG3_RX_STD_DMA_SZ - ETH_FCS_LEN) { + if (opaque_key != RXD_OPAQUE_RING_STD) + goto out; + } else { + if (opaque_key != RXD_OPAQUE_RING_JUMBO) + goto out; + } + } else if ((desc->type_flags & RXD_FLAG_TCPUDP_CSUM) && + (desc->ip_tcp_csum & RXD_TCPCSUM_MASK) + >> RXD_TCPCSUM_SHIFT == 0xffff) { goto out; + } - rx_skb = tpr->rx_jmb_buffers[desc_idx].skb; - map = dma_unmap_addr(&tpr->rx_jmb_buffers[desc_idx], mapping); - } + if (opaque_key == RXD_OPAQUE_RING_STD) { + rx_skb = tpr->rx_std_buffers[desc_idx].skb; + map = dma_unmap_addr(&tpr->rx_std_buffers[desc_idx], + mapping); + } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) { + rx_skb = tpr->rx_jmb_buffers[desc_idx].skb; + map = dma_unmap_addr(&tpr->rx_jmb_buffers[desc_idx], + mapping); + } else + goto out; - pci_dma_sync_single_for_cpu(tp->pdev, map, rx_len, PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_cpu(tp->pdev, map, rx_len, + PCI_DMA_FROMDEVICE); - for (i = 14; i < tx_len; i++) { - if (*(rx_skb->data + i) != (u8) (i & 0xff)) - goto out; + for (i = data_off; i < rx_len; i++, val++) { + if (*(rx_skb->data + i) != (u8) (val & 0xff)) + goto out; + } } + err = 0; /* tg3_free_rings will unmap and free the rx_skb */ @@ -11278,10 +11361,11 @@ out: #define TG3_STD_LOOPBACK_FAILED 1 #define TG3_JMB_LOOPBACK_FAILED 2 +#define TG3_TSO_LOOPBACK_FAILED 4 #define TG3_MAC_LOOPBACK_SHIFT 0 #define TG3_PHY_LOOPBACK_SHIFT 4 -#define TG3_LOOPBACK_FAILED 0x00000033 +#define TG3_LOOPBACK_FAILED 0x00000077 static int tg3_test_loopback(struct tg3 *tp) { @@ -11358,6 +11442,10 @@ static int tg3_test_loopback(struct tg3 *tp) if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_PHY_LOOPBACK)) err |= TG3_STD_LOOPBACK_FAILED << TG3_PHY_LOOPBACK_SHIFT; + if ((tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) && + tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_TSO_LOOPBACK)) + err |= TG3_TSO_LOOPBACK_FAILED << + TG3_PHY_LOOPBACK_SHIFT; if ((tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) && tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_PHY_LOOPBACK)) err |= TG3_JMB_LOOPBACK_FAILED << -- cgit v1.2.3-58-ga151 From b45aa2f6192e34a837ebdbb3548039c24440bc04 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 25 Apr 2011 12:42:48 +0000 Subject: tg3: Add EEH support This patch adds EEH support to the tg3 driver. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index fb2139a80700..6bc43ed172b5 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -15395,6 +15395,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, pdev->dma_mask == DMA_BIT_MASK(32) ? 32 : ((u64)pdev->dma_mask) == DMA_BIT_MASK(40) ? 40 : 64); + pci_save_state(pdev); + return 0; err_out_apeunmap: @@ -15551,11 +15553,156 @@ static SIMPLE_DEV_PM_OPS(tg3_pm_ops, tg3_suspend, tg3_resume); #endif /* CONFIG_PM_SLEEP */ +/** + * tg3_io_error_detected - called when PCI error is detected + * @pdev: Pointer to PCI device + * @state: The current pci connection state + * + * This function is called after a PCI bus error affecting + * this device has been detected. + */ +static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct tg3 *tp = netdev_priv(netdev); + pci_ers_result_t err = PCI_ERS_RESULT_NEED_RESET; + + netdev_info(netdev, "PCI I/O error detected\n"); + + rtnl_lock(); + + if (!netif_running(netdev)) + goto done; + + tg3_phy_stop(tp); + + tg3_netif_stop(tp); + + del_timer_sync(&tp->timer); + tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; + + /* Want to make sure that the reset task doesn't run */ + cancel_work_sync(&tp->reset_task); + tp->tg3_flags &= ~TG3_FLAG_TX_RECOVERY_PENDING; + tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; + + netif_device_detach(netdev); + + /* Clean up software state, even if MMIO is blocked */ + tg3_full_lock(tp, 0); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); + tg3_full_unlock(tp); + +done: + if (state == pci_channel_io_perm_failure) + err = PCI_ERS_RESULT_DISCONNECT; + else + pci_disable_device(pdev); + + rtnl_unlock(); + + return err; +} + +/** + * tg3_io_slot_reset - called after the pci bus has been reset. + * @pdev: Pointer to PCI device + * + * Restart the card from scratch, as if from a cold-boot. + * At this point, the card has exprienced a hard reset, + * followed by fixups by BIOS, and has its config space + * set up identically to what it was at cold boot. + */ +static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct tg3 *tp = netdev_priv(netdev); + pci_ers_result_t rc = PCI_ERS_RESULT_DISCONNECT; + int err; + + rtnl_lock(); + + if (pci_enable_device(pdev)) { + netdev_err(netdev, "Cannot re-enable PCI device after reset.\n"); + goto done; + } + + pci_set_master(pdev); + pci_restore_state(pdev); + pci_save_state(pdev); + + if (!netif_running(netdev)) { + rc = PCI_ERS_RESULT_RECOVERED; + goto done; + } + + err = tg3_power_up(tp); + if (err) { + netdev_err(netdev, "Failed to restore register access.\n"); + goto done; + } + + rc = PCI_ERS_RESULT_RECOVERED; + +done: + rtnl_unlock(); + + return rc; +} + +/** + * tg3_io_resume - called when traffic can start flowing again. + * @pdev: Pointer to PCI device + * + * This callback is called when the error recovery driver tells + * us that its OK to resume normal operation. + */ +static void tg3_io_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct tg3 *tp = netdev_priv(netdev); + int err; + + rtnl_lock(); + + if (!netif_running(netdev)) + goto done; + + tg3_full_lock(tp, 0); + tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; + err = tg3_restart_hw(tp, 1); + tg3_full_unlock(tp); + if (err) { + netdev_err(netdev, "Cannot restart hardware after reset.\n"); + goto done; + } + + netif_device_attach(netdev); + + tp->timer.expires = jiffies + tp->timer_offset; + add_timer(&tp->timer); + + tg3_netif_start(tp); + + tg3_phy_start(tp); + +done: + rtnl_unlock(); +} + +static struct pci_error_handlers tg3_err_handler = { + .error_detected = tg3_io_error_detected, + .slot_reset = tg3_io_slot_reset, + .resume = tg3_io_resume +}; + static struct pci_driver tg3_driver = { .name = DRV_MODULE_NAME, .id_table = tg3_pci_tbl, .probe = tg3_init_one, .remove = __devexit_p(tg3_remove_one), + .err_handler = &tg3_err_handler, .driver.pm = TG3_PM_OPS, }; -- cgit v1.2.3-58-ga151 From bea8a63b27eb8e705a957938aadeb975178c5ea6 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 25 Apr 2011 12:42:49 +0000 Subject: tg3: Whitespace cleanups This patch gets rid of some harmless whitespace errors. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 6bc43ed172b5..696be59e6e32 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7666,8 +7666,6 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) return 0; } -/* 5705 needs a special version of the TSO firmware. */ - /* tp->lock is held. */ static int tg3_load_tso_firmware(struct tg3 *tp) { @@ -10179,7 +10177,6 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE; spin_unlock_bh(&tp->lock); - return 0; } @@ -12925,7 +12922,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) done: if (tp->tg3_flags & TG3_FLAG_WOL_CAP) device_set_wakeup_enable(&tp->pdev->dev, - tp->tg3_flags & TG3_FLAG_WOL_ENABLE); + tp->tg3_flags & TG3_FLAG_WOL_ENABLE); else device_set_wakeup_capable(&tp->pdev->dev, false); } @@ -13749,7 +13746,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) || (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)) tp->tg3_flags2 |= TG3_FLG2_5705_PLUS; @@ -14034,7 +14030,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) (tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT; - /* Set up tp->grc_local_ctrl before calling tg_power_up(). + /* Set up tp->grc_local_ctrl before calling tg3_power_up(). * GPIO1 driven high will bring 5700's external PHY out of reset. * It is also used as eeprom write protect on LOMs. */ @@ -14829,7 +14825,6 @@ static int __devinit tg3_test_dma(struct tg3 *tp) } if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) != DMA_RWCTRL_WRITE_BNDRY_16) { - /* DMA test passed without adjusting DMA boundary, * now look for chipsets that are known to expose the * DMA bug without failing the test. -- cgit v1.2.3-58-ga151 From 64cad2ade1e6f890531a58318ca9ee013f92ef2f Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 25 Apr 2011 12:42:50 +0000 Subject: tg3: Update version to 3.118 This patch updates the tg3 version to 3.118. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 696be59e6e32..b20538a34fd1 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,10 +64,10 @@ #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 -#define TG3_MIN_NUM 117 +#define TG3_MIN_NUM 118 #define DRV_MODULE_VERSION \ __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM) -#define DRV_MODULE_RELDATE "January 25, 2011" +#define DRV_MODULE_RELDATE "April 22, 2011" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.3-58-ga151 From 3782c69d6e35e698bcc2aefe803e62d06c5c4997 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sun, 24 Apr 2011 21:34:39 +0530 Subject: ath9k_hw: Fix Tx IQ Calibration hang issue in AR9003 chips On AR9003 chips, doing three IQ calibrations will possibly cause chip in stuck state. In noisy environment, chip could receive a packet during the middle of three calibrations and it causes the conflict of HW access and the eventual failure. It also causes IQ calibration outliers which results in poor Tx EVM. The IQ Cal procedure is after resetting the chip, run IQ cal 3 times per each cal cycle and find the two closest readings and average of two. The advantage of running Tx IQ cal more than once is that we can compare calibration results for the same gain setting over multiple iterations. Most of the cases the IQ failures were observed after first pass. For the AR9485 and later chips, Tx IQ Calibration is performed along with AGC cal. But for pre-AR9485 chips, Tx IQ cal HW has to be separated from the rest of calibration HW to avoid chip hang. After all calibrations are done in HW, we can start SW post-processing. By doing this way, we minimize the SW difference among all chips. The order of calibration (run IQ cal before other calibration) is also needed to avoid chip hang for chips before AR9485. This issue was originally observed with AR9382. During the issue kernel log was filled with following message ath: timeout (100000 us) on reg 0xa640: 0x00000001 & 0x00000001 != 0x00000000 ath: timeout (100000 us) on reg 0xa2c4: 0x00158dd9 & 0x00000001 != 0x00000000 ath: Unable to reset channel (2412 MHz), reset status -5 ath: Unable to set channel Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 350 ++++++++++---------------- drivers/net/wireless/ath/ath9k/ar9003_phy.h | 23 +- drivers/net/wireless/ath/ath9k/reg.h | 2 + 3 files changed, 140 insertions(+), 235 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index bceff49d150b..f276cb922b4d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -18,13 +18,13 @@ #include "hw-ops.h" #include "ar9003_phy.h" -#define MPASS 3 #define MAX_MEASUREMENT 8 -#define MAX_DIFFERENCE 10 +#define MAX_MAG_DELTA 11 +#define MAX_PHS_DELTA 10 struct coeff { - int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; - int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; + int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; + int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; int iqc_coeff[2]; }; @@ -610,36 +610,48 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, return true; } -static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg) +static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, + int max_delta) { - int diff[MPASS]; - - diff[0] = abs(mp_coeff[0] - mp_coeff[1]); - diff[1] = abs(mp_coeff[1] - mp_coeff[2]); - diff[2] = abs(mp_coeff[2] - mp_coeff[0]); - - if (diff[0] > MAX_DIFFERENCE && - diff[1] > MAX_DIFFERENCE && - diff[2] > MAX_DIFFERENCE) - return false; + int mp_max = -64, max_idx = 0; + int mp_min = 63, min_idx = 0; + int mp_avg = 0, i, outlier_idx = 0; + + /* find min/max mismatch across all calibrated gains */ + for (i = 0; i < nmeasurement; i++) { + mp_avg += mp_coeff[i]; + if (mp_coeff[i] > mp_max) { + mp_max = mp_coeff[i]; + max_idx = i; + } else if (mp_coeff[i] < mp_min) { + mp_min = mp_coeff[i]; + min_idx = i; + } + } - if (diff[0] <= diff[1] && diff[0] <= diff[2]) - *mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2; - else if (diff[1] <= diff[2]) - *mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2; - else - *mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2; + /* find average (exclude max abs value) */ + for (i = 0; i < nmeasurement; i++) { + if ((abs(mp_coeff[i]) < abs(mp_max)) || + (abs(mp_coeff[i]) < abs(mp_min))) + mp_avg += mp_coeff[i]; + } + mp_avg /= (nmeasurement - 1); - return true; + /* detect outlier */ + if (abs(mp_max - mp_min) > max_delta) { + if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg)) + outlier_idx = max_idx; + else + outlier_idx = min_idx; + } + mp_coeff[outlier_idx] = mp_avg; } static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, u8 num_chains, struct coeff *coeff) { - struct ath_common *common = ath9k_hw_common(ah); int i, im, nmeasurement; - int magnitude, phase; u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS]; memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff)); @@ -659,37 +671,28 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, /* Load the average of 2 passes */ for (i = 0; i < num_chains; i++) { - if (AR_SREV_9485(ah)) - nmeasurement = REG_READ_FIELD(ah, - AR_PHY_TX_IQCAL_STATUS_B0_9485, - AR_PHY_CALIBRATED_GAINS_0); - else - nmeasurement = REG_READ_FIELD(ah, - AR_PHY_TX_IQCAL_STATUS_B0, - AR_PHY_CALIBRATED_GAINS_0); + nmeasurement = REG_READ_FIELD(ah, + AR_PHY_TX_IQCAL_STATUS_B0, + AR_PHY_CALIBRATED_GAINS_0); if (nmeasurement > MAX_MEASUREMENT) nmeasurement = MAX_MEASUREMENT; - for (im = 0; im < nmeasurement; im++) { - /* - * Determine which 2 passes are closest and compute avg - * magnitude - */ - if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im], - &magnitude)) - goto disable_txiqcal; + /* detect outlier only if nmeasurement > 1 */ + if (nmeasurement > 1) { + /* Detect magnitude outlier */ + ar9003_hw_detect_outlier(coeff->mag_coeff[i], + nmeasurement, MAX_MAG_DELTA); - /* - * Determine which 2 passes are closest and compute avg - * phase - */ - if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im], - &phase)) - goto disable_txiqcal; + /* Detect phase outlier */ + ar9003_hw_detect_outlier(coeff->phs_coeff[i], + nmeasurement, MAX_PHS_DELTA); + } - coeff->iqc_coeff[0] = (magnitude & 0x7f) | - ((phase & 0x7f) << 7); + for (im = 0; im < nmeasurement; im++) { + + coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) | + ((coeff->phs_coeff[i][im] & 0x7f) << 7); if ((im % 2) == 0) REG_RMW_FIELD(ah, tx_corr_coeff[im][i], @@ -709,141 +712,37 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, return; -disable_txiqcal: - REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, - AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0); - REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, - AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0); - - ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n"); } -static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) +static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - static const u32 txiqcal_status[AR9300_MAX_CHAINS] = { - AR_PHY_TX_IQCAL_STATUS_B0, - AR_PHY_TX_IQCAL_STATUS_B1, - AR_PHY_TX_IQCAL_STATUS_B2, - }; - static const u32 chan_info_tab[] = { - AR_PHY_CHAN_INFO_TAB_0, - AR_PHY_CHAN_INFO_TAB_1, - AR_PHY_CHAN_INFO_TAB_2, - }; - struct coeff coeff; - s32 iq_res[6]; - s32 i, j, ip, im, nmeasurement; - u8 nchains = get_streams(common->tx_chainmask); - - for (ip = 0; ip < MPASS; ip++) { - REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, - AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, - DELPT); - REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, - AR_PHY_TX_IQCAL_START_DO_CAL, - AR_PHY_TX_IQCAL_START_DO_CAL); - - if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, - AR_PHY_TX_IQCAL_START_DO_CAL, - 0, AH_WAIT_TIMEOUT)) { - ath_dbg(common, ATH_DBG_CALIBRATE, - "Tx IQ Cal not complete.\n"); - goto TX_IQ_CAL_FAILED; - } - - nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0, - AR_PHY_CALIBRATED_GAINS_0); - if (nmeasurement > MAX_MEASUREMENT) - nmeasurement = MAX_MEASUREMENT; - - for (i = 0; i < nchains; i++) { - ath_dbg(common, ATH_DBG_CALIBRATE, - "Doing Tx IQ Cal for chain %d.\n", i); - for (im = 0; im < nmeasurement; im++) { - if (REG_READ(ah, txiqcal_status[i]) & - AR_PHY_TX_IQCAL_STATUS_FAILED) { - ath_dbg(common, ATH_DBG_CALIBRATE, - "Tx IQ Cal failed for chain %d.\n", i); - goto TX_IQ_CAL_FAILED; - } - - for (j = 0; j < 3; j++) { - u8 idx = 2 * j, - offset = 4 * (3 * im + j); - - REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, - AR_PHY_CHAN_INFO_TAB_S2_READ, - 0); - - /* 32 bits */ - iq_res[idx] = REG_READ(ah, - chan_info_tab[i] + - offset); - - REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, - AR_PHY_CHAN_INFO_TAB_S2_READ, - 1); - - /* 16 bits */ - iq_res[idx+1] = 0xffff & REG_READ(ah, - chan_info_tab[i] + - offset); - - ath_dbg(common, ATH_DBG_CALIBRATE, - "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n", - idx, iq_res[idx], idx+1, iq_res[idx+1]); - } - - if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, - coeff.iqc_coeff)) { - ath_dbg(common, ATH_DBG_CALIBRATE, - "Failed in calculation of IQ correction.\n"); - goto TX_IQ_CAL_FAILED; - } - coeff.mag_coeff[i][im][ip] = - coeff.iqc_coeff[0] & 0x7f; - coeff.phs_coeff[i][im][ip] = - (coeff.iqc_coeff[0] >> 7) & 0x7f; - - if (coeff.mag_coeff[i][im][ip] > 63) - coeff.mag_coeff[i][im][ip] -= 128; - if (coeff.phs_coeff[i][im][ip] > 63) - coeff.phs_coeff[i][im][ip] -= 128; - - } - } - } - - ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff); - - return; - -TX_IQ_CAL_FAILED: - ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); -} - -static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) -{ u8 tx_gain_forced; - REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485, - AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN, AR_PHY_TXGAIN_FORCE); if (tx_gain_forced) REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, AR_PHY_TXGAIN_FORCE, 0); - REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485, - AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1); + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, + AR_PHY_TX_IQCAL_START_DO_CAL, 1); + + if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, + AR_PHY_TX_IQCAL_START_DO_CAL, 0, + AH_WAIT_TIMEOUT)) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Tx IQ Cal is not completed.\n"); + return false; + } + return true; } static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); const u32 txiqcal_status[AR9300_MAX_CHAINS] = { - AR_PHY_TX_IQCAL_STATUS_B0_9485, + AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_TX_IQCAL_STATUS_B1, AR_PHY_TX_IQCAL_STATUS_B2, }; @@ -855,7 +754,7 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) struct coeff coeff; s32 iq_res[6]; u8 num_chains = 0; - int i, ip, im, j; + int i, im, j; int nmeasurement; for (i = 0; i < AR9300_MAX_CHAINS; i++) { @@ -863,71 +762,69 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) num_chains++; } - for (ip = 0; ip < MPASS; ip++) { - for (i = 0; i < num_chains; i++) { - nmeasurement = REG_READ_FIELD(ah, - AR_PHY_TX_IQCAL_STATUS_B0_9485, - AR_PHY_CALIBRATED_GAINS_0); - if (nmeasurement > MAX_MEASUREMENT) - nmeasurement = MAX_MEASUREMENT; + for (i = 0; i < num_chains; i++) { + nmeasurement = REG_READ_FIELD(ah, + AR_PHY_TX_IQCAL_STATUS_B0, + AR_PHY_CALIBRATED_GAINS_0); + if (nmeasurement > MAX_MEASUREMENT) + nmeasurement = MAX_MEASUREMENT; - for (im = 0; im < nmeasurement; im++) { - ath_dbg(common, ATH_DBG_CALIBRATE, - "Doing Tx IQ Cal for chain %d.\n", i); + for (im = 0; im < nmeasurement; im++) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Doing Tx IQ Cal for chain %d.\n", i); - if (REG_READ(ah, txiqcal_status[i]) & - AR_PHY_TX_IQCAL_STATUS_FAILED) { - ath_dbg(common, ATH_DBG_CALIBRATE, + if (REG_READ(ah, txiqcal_status[i]) & + AR_PHY_TX_IQCAL_STATUS_FAILED) { + ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed for chain %d.\n", i); - goto tx_iqcal_fail; - } + goto tx_iqcal_fail; + } - for (j = 0; j < 3; j++) { - u32 idx = 2 * j, offset = 4 * (3 * im + j); + for (j = 0; j < 3; j++) { + u32 idx = 2 * j, offset = 4 * (3 * im + j); - REG_RMW_FIELD(ah, + REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, AR_PHY_CHAN_INFO_TAB_S2_READ, 0); - /* 32 bits */ - iq_res[idx] = REG_READ(ah, - chan_info_tab[i] + - offset); + /* 32 bits */ + iq_res[idx] = REG_READ(ah, + chan_info_tab[i] + + offset); - REG_RMW_FIELD(ah, + REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, AR_PHY_CHAN_INFO_TAB_S2_READ, 1); - /* 16 bits */ - iq_res[idx + 1] = 0xffff & REG_READ(ah, - chan_info_tab[i] + offset); + /* 16 bits */ + iq_res[idx + 1] = 0xffff & REG_READ(ah, + chan_info_tab[i] + offset); - ath_dbg(common, ATH_DBG_CALIBRATE, - "IQ RES[%d]=0x%x" - "IQ_RES[%d]=0x%x\n", - idx, iq_res[idx], idx + 1, - iq_res[idx + 1]); - } + ath_dbg(common, ATH_DBG_CALIBRATE, + "IQ RES[%d]=0x%x" + "IQ_RES[%d]=0x%x\n", + idx, iq_res[idx], idx + 1, + iq_res[idx + 1]); + } - if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, - coeff.iqc_coeff)) { - ath_dbg(common, ATH_DBG_CALIBRATE, - "Failed in calculation of IQ correction.\n"); - goto tx_iqcal_fail; - } + if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, + coeff.iqc_coeff)) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Failed in calculation of \ + IQ correction.\n"); + goto tx_iqcal_fail; + } - coeff.mag_coeff[i][im][ip] = - coeff.iqc_coeff[0] & 0x7f; - coeff.phs_coeff[i][im][ip] = - (coeff.iqc_coeff[0] >> 7) & 0x7f; + coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f; + coeff.phs_coeff[i][im] = + (coeff.iqc_coeff[0] >> 7) & 0x7f; - if (coeff.mag_coeff[i][im][ip] > 63) - coeff.mag_coeff[i][im][ip] -= 128; - if (coeff.phs_coeff[i][im][ip] > 63) - coeff.phs_coeff[i][im][ip] -= 128; - } + if (coeff.mag_coeff[i][im] > 63) + coeff.mag_coeff[i][im] -= 128; + if (coeff.phs_coeff[i][im] > 63) + coeff.phs_coeff[i][im] -= 128; } } ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff); @@ -944,6 +841,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, struct ath_common *common = ath9k_hw_common(ah); struct ath9k_hw_capabilities *pCap = &ah->caps; int val; + bool txiqcal_done = false; val = REG_READ(ah, AR_ENT_OTP); ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); @@ -956,14 +854,22 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, pCap->tx_chainmask); /* Do Tx IQ Calibration */ - if (AR_SREV_9485(ah)) - ar9003_hw_tx_iq_cal_run(ah); - else - ar9003_hw_tx_iq_cal(ah); + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, + AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, + DELPT); - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); - udelay(5); - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + /* + * For AR9485 or later chips, TxIQ cal runs as part of + * AGC calibration + */ + if (AR_SREV_9485_OR_LATER(ah)) + txiqcal_done = true; + else { + txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); + udelay(5); + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + } /* Calibrate the AGC */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, @@ -978,7 +884,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, return false; } - if (AR_SREV_9485(ah)) + if (txiqcal_done) ar9003_hw_tx_iq_cal_post_proc(ah); /* Revert chainmasks to their original values before NF cal */ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index d133ee820875..2a0d5cbb7e76 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -548,15 +548,12 @@ #define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300) -#define AR_PHY_TX_IQCAL_START_9485 (AR_SM_BASE + 0x3c4) -#define AR_PHY_TX_IQCAL_START_DO_CAL_9485 0x80000000 -#define AR_PHY_TX_IQCAL_START_DO_CAL_9485_S 31 -#define AR_PHY_TX_IQCAL_CONTROL_1_9485 (AR_SM_BASE + 0x3c8) -#define AR_PHY_TX_IQCAL_STATUS_B0_9485 (AR_SM_BASE + 0x3f0) - -#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448) -#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440) -#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) +#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + AR_SREV_9485(ah) ? \ + 0x3c8 : 0x448) +#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + AR_SREV_9485(ah) ? \ + 0x3c4 : 0x440) +#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + AR_SREV_9485(ah) ? \ + 0x3f0 : 0x48c) #define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \ (AR_SREV_9485(ah) ? \ 0x3d0 : 0x450) + ((_i) << 2)) @@ -758,10 +755,10 @@ #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 #define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004 -#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 -#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18 -#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001 -#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 +#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 +#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18 +#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001 +#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 #define AR_PHY_TX_IQCAL_STATUS_FAILED 0x00000001 #define AR_PHY_CALIBRATED_GAINS_0 0x3e diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index b42e36c6f6ea..d5cecdc6ca6e 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -870,6 +870,8 @@ #define AR_SREV_9485_11(_ah) \ (AR_SREV_9485(_ah) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11)) +#define AR_SREV_9485_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485)) #define AR_SREV_9340(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9340)) -- cgit v1.2.3-58-ga151 From 92c6f76c6d44a869bf3b252dbb2e358ae7399a96 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 22 Apr 2011 14:50:39 +0530 Subject: ath9k: set beacon related ps flags on bss_info change Requesting beacon sync up to configure beacon timers properly in hw, has be done after doing beacon config with default values. Setting the flags in beacon config is causing the device to not enter into network sleep on idle state. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 6 ------ drivers/net/wireless/ath/ath9k/main.c | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 24f565ba9988..22cd241a098b 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -781,12 +781,6 @@ void ath_set_beacon(struct ath_softc *sc) break; case NL80211_IFTYPE_STATION: ath_beacon_config_sta(sc, cur_conf); - /* - * Request a re-configuration of Beacon related timers - * on the receipt of the first Beacon frame (i.e., - * after time sync with the AP). - */ - sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; break; default: ath_dbg(common, ATH_DBG_CONFIG, diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 475009b578de..c3dbf2661a3f 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1969,6 +1969,12 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) "Bss Info ASSOC %d, bssid: %pM\n", bss_conf->aid, common->curbssid); ath_beacon_config(sc, vif); + /* + * Request a re-configuration of Beacon related timers + * on the receipt of the first Beacon frame (i.e., + * after time sync with the AP). + */ + sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; /* Reset rssi stats */ sc->last_rssi = ATH_RSSI_DUMMY_MARKER; sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; -- cgit v1.2.3-58-ga151 From 25f63a5a37f9cd925a01840bbb4c3ad9d5034175 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Sat, 23 Apr 2011 12:48:53 +0800 Subject: ath9k: fix AR9160 xpaBiasLvlFreq endianness handling The xpaBiasLvlFreq parameter array is made up of 16 bit words which aren't byte-swapped like the other 16-bit eeprom parameters are. It's only used by the AR9160. Signed-off-by: Adrian Chadd Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom_def.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 995949ddd63e..c031854b569f 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -231,6 +231,10 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) integer = swab32(pModal->antCtrlChain[i]); pModal->antCtrlChain[i] = integer; } + for (i = 0; i < 3; i++) { + word = swab16(pModal->xpaBiasLvlFreq[i]); + pModal->xpaBiasLvlFreq[i] = word; + } for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { word = swab16(pModal->spurChans[i].spurChan); -- cgit v1.2.3-58-ga151 From a6ef8143839a8640532ba473906beb1a38b03e29 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 23 Apr 2011 19:30:28 +0200 Subject: ssb: mark bus as powered up earlier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ssb_chipco_set_clockmode may want to touch CC registers to control power of the bus. However touching registers without powered_up set causes warnings. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index e05ba6eefc7e..74aa2cca7d8c 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -1309,20 +1309,20 @@ EXPORT_SYMBOL(ssb_bus_may_powerdown); int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl) { - struct ssb_chipcommon *cc; int err; enum ssb_clkmode mode; err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1); if (err) goto error; - cc = &bus->chipco; - mode = dynamic_pctl ? SSB_CLKMODE_DYNAMIC : SSB_CLKMODE_FAST; - ssb_chipco_set_clockmode(cc, mode); #ifdef CONFIG_SSB_DEBUG bus->powered_up = 1; #endif + + mode = dynamic_pctl ? SSB_CLKMODE_DYNAMIC : SSB_CLKMODE_FAST; + ssb_chipco_set_clockmode(&bus->chipco, mode); + return 0; error: ssb_printk(KERN_ERR PFX "Bus powerup failed\n"); -- cgit v1.2.3-58-ga151 From 04ad1fb2640a4f23e99ccb705c179d64abac03f2 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 23 Apr 2011 19:30:29 +0200 Subject: ssb: update reject bit for Target State Low MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit My 14e4:4315 is SSB_IDLOW_SSBREV_26: read32 0xfaafcff8 -> 0x600422d5 My 14e4:4328 is SSB_IDLOW_SSBREV_24: read32 0xfaafcff8 -> 0x400422c5 My 14e4:432b is SSB_IDLOW_SSBREV_26 again: read32 0xfaafcff8 -> 0x600422d5 For all of them wl driver is using 0x2 reject bit: write32(0xf98) <- 0x00010002 So it seems SSB 2.3 is the exception using another bit. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/main.c | 15 +++++++-------- include/linux/ssb/ssb_regs.h | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 74aa2cca7d8c..ad3da93a428c 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -1117,23 +1117,22 @@ static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev) { u32 rev = ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_SSBREV; - /* The REJECT bit changed position in TMSLOW between - * Backplane revisions. */ + /* The REJECT bit seems to be different for Backplane rev 2.3 */ switch (rev) { case SSB_IDLOW_SSBREV_22: - return SSB_TMSLOW_REJECT_22; + case SSB_IDLOW_SSBREV_24: + case SSB_IDLOW_SSBREV_26: + return SSB_TMSLOW_REJECT; case SSB_IDLOW_SSBREV_23: return SSB_TMSLOW_REJECT_23; - case SSB_IDLOW_SSBREV_24: /* TODO - find the proper REJECT bits */ - case SSB_IDLOW_SSBREV_25: /* same here */ - case SSB_IDLOW_SSBREV_26: /* same here */ + case SSB_IDLOW_SSBREV_25: /* TODO - find the proper REJECT bit */ case SSB_IDLOW_SSBREV_27: /* same here */ - return SSB_TMSLOW_REJECT_23; /* this is a guess */ + return SSB_TMSLOW_REJECT; /* this is a guess */ default: printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev); WARN_ON(1); } - return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23); + return (SSB_TMSLOW_REJECT | SSB_TMSLOW_REJECT_23); } int ssb_device_is_enabled(struct ssb_device *dev) diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index 402955ae48ce..efbf459d571c 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h @@ -97,7 +97,7 @@ #define SSB_INTVEC_ENET1 0x00000040 /* Enable interrupts for enet 1 */ #define SSB_TMSLOW 0x0F98 /* SB Target State Low */ #define SSB_TMSLOW_RESET 0x00000001 /* Reset */ -#define SSB_TMSLOW_REJECT_22 0x00000002 /* Reject (Backplane rev 2.2) */ +#define SSB_TMSLOW_REJECT 0x00000002 /* Reject (Standard Backplane) */ #define SSB_TMSLOW_REJECT_23 0x00000004 /* Reject (Backplane rev 2.3) */ #define SSB_TMSLOW_CLOCK 0x00010000 /* Clock Enable */ #define SSB_TMSLOW_FGC 0x00020000 /* Force Gated Clocks On */ -- cgit v1.2.3-58-ga151 From be8d98eab81d1f6445461a1631513f7091805e53 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 24 Apr 2011 17:22:59 +0200 Subject: p54: implement multicast filter "For best CPU usage and power consumption, having as few frames as possible percolate through the stack is desirable. Hence, the hardware should filter as much as possible." Note: Not all firmwares include the multicast filter feature and the stack does not filter them either. The ARP filter on the other hand was dropped from the patch since it does not work correctly: Quote from: Max Filippov "In the ARP case, when there's no other traffic on p54spi, all ARP requests are dropped. But if there's some egress traffic from p54spi, filter seems to work correctly: only ARP requests that match filter pass through. In the multicast case filter seems to work correctly, but it treats broadcast as subject to that filtering too. By default only 01:00:5e:00:00:01 gets into priv->mc_maclist, so we miss all broadcasts. These two filters seem to interfere: - if we set ARP filter and multicast filter without bc => we miss all ARPs if there's no egress traffic; - if we set ARP filter and multicast filter with bc or don't set mc filter at all => we get all ARPs. This effect does not depend on filter setup order." Signed-off-by: Christian Lamparter Tested-by: Max Filippov Signed-off-by: John W. Linville --- drivers/net/wireless/p54/fwio.c | 31 +++++++++++++++++++++++++++++++ drivers/net/wireless/p54/lmac.h | 1 + drivers/net/wireless/p54/main.c | 31 +++++++++++++++++++++++++++++++ drivers/net/wireless/p54/p54.h | 2 ++ 4 files changed, 65 insertions(+) diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index 2fab7d20ffc2..b6a061cbbdec 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c @@ -727,3 +727,34 @@ int p54_fetch_statistics(struct p54_common *priv) p54_tx(priv, skb); return 0; } + +int p54_set_groupfilter(struct p54_common *priv) +{ + struct p54_group_address_table *grp; + struct sk_buff *skb; + bool on = false; + + skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*grp), + P54_CONTROL_TYPE_GROUP_ADDRESS_TABLE, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + grp = (struct p54_group_address_table *)skb_put(skb, sizeof(*grp)); + + on = !(priv->filter_flags & FIF_ALLMULTI) && + (priv->mc_maclist_num > 0 && + priv->mc_maclist_num <= MC_FILTER_ADDRESS_NUM); + + if (on) { + grp->filter_enable = cpu_to_le16(1); + grp->num_address = cpu_to_le16(priv->mc_maclist_num); + memcpy(grp->mac_list, priv->mc_maclist, sizeof(grp->mac_list)); + } else { + grp->filter_enable = cpu_to_le16(0); + grp->num_address = cpu_to_le16(0); + memset(grp->mac_list, 0, sizeof(grp->mac_list)); + } + + p54_tx(priv, skb); + return 0; +} diff --git a/drivers/net/wireless/p54/lmac.h b/drivers/net/wireless/p54/lmac.h index eb581abc1079..3d8d622bec55 100644 --- a/drivers/net/wireless/p54/lmac.h +++ b/drivers/net/wireless/p54/lmac.h @@ -540,6 +540,7 @@ int p54_update_beacon_tim(struct p54_common *priv, u16 aid, bool set); int p54_setup_mac(struct p54_common *priv); int p54_set_ps(struct p54_common *priv); int p54_fetch_statistics(struct p54_common *priv); +int p54_set_groupfilter(struct p54_common *priv); /* e/v DCF setup */ int p54_set_edcf(struct p54_common *priv); diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 356e6bb443a6..c5c1254ec093 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -308,6 +308,31 @@ out: return ret; } +static u64 p54_prepare_multicast(struct ieee80211_hw *dev, + struct netdev_hw_addr_list *mc_list) +{ + struct p54_common *priv = dev->priv; + struct netdev_hw_addr *ha; + int i; + + BUILD_BUG_ON(ARRAY_SIZE(priv->mc_maclist) != + ARRAY_SIZE(((struct p54_group_address_table *)NULL)->mac_list)); + /* + * The first entry is reserved for the global broadcast MAC. + * Otherwise the firmware will drop it and ARP will no longer work. + */ + i = 1; + priv->mc_maclist_num = netdev_hw_addr_list_count(mc_list) + i; + netdev_hw_addr_list_for_each(ha, mc_list) { + memcpy(&priv->mc_maclist[i], ha->addr, ETH_ALEN); + i++; + if (i >= ARRAY_SIZE(priv->mc_maclist)) + break; + } + + return 1; /* update */ +} + static void p54_configure_filter(struct ieee80211_hw *dev, unsigned int changed_flags, unsigned int *total_flags, @@ -316,12 +341,16 @@ static void p54_configure_filter(struct ieee80211_hw *dev, struct p54_common *priv = dev->priv; *total_flags &= FIF_PROMISC_IN_BSS | + FIF_ALLMULTI | FIF_OTHER_BSS; priv->filter_flags = *total_flags; if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) p54_setup_mac(priv); + + if (changed_flags & FIF_ALLMULTI || multicast) + p54_set_groupfilter(priv); } static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue, @@ -591,6 +620,7 @@ static const struct ieee80211_ops p54_ops = { .config = p54_config, .flush = p54_flush, .bss_info_changed = p54_bss_info_changed, + .prepare_multicast = p54_prepare_multicast, .configure_filter = p54_configure_filter, .conf_tx = p54_conf_tx, .get_stats = p54_get_stats, @@ -660,6 +690,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) init_completion(&priv->beacon_comp); INIT_DELAYED_WORK(&priv->work, p54_work); + memset(&priv->mc_maclist[0], ~0, ETH_ALEN); return dev; } EXPORT_SYMBOL_GPL(p54_init_common); diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 50730fc23fe5..799d05e12595 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -211,8 +211,10 @@ struct p54_common { /* BBP/MAC state */ u8 mac_addr[ETH_ALEN]; u8 bssid[ETH_ALEN]; + u8 mc_maclist[4][ETH_ALEN]; u16 wakeup_timer; unsigned int filter_flags; + int mc_maclist_num; int mode; u32 tsf_low32, tsf_high32; u32 basic_rate_mask; -- cgit v1.2.3-58-ga151 From caf1eae206688210f61f3b48627ce4ca3c709784 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 24 Apr 2011 17:44:19 +0200 Subject: carl9170: improve unicast PS buffering Using the ieee80211_sta_block allows the PS code to handle awake->doze->awake transitions of our clients in a race-free manner. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/carl9170/carl9170.h | 2 + drivers/net/wireless/ath/carl9170/main.c | 92 +--------------- drivers/net/wireless/ath/carl9170/tx.c | 157 ++++++++++++++++++--------- 3 files changed, 112 insertions(+), 139 deletions(-) diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 9cad061cc1d2..beb725d7547f 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -448,6 +448,8 @@ struct carl9170_ba_stats { struct carl9170_sta_info { bool ht_sta; + bool sleeping; + atomic_t pending_frames; unsigned int ampdu_max_len; struct carl9170_sta_tid *agg[CARL9170_NUM_TID]; struct carl9170_ba_stats stats[CARL9170_NUM_TID]; diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 89fe60accf85..1638468be5a3 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1193,6 +1193,8 @@ static int carl9170_op_sta_add(struct ieee80211_hw *hw, struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; unsigned int i; + atomic_set(&sta_info->pending_frames, 0); + if (sta->ht_cap.ht_supported) { if (sta->ht_cap.ampdu_density > 6) { /* @@ -1467,99 +1469,17 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw, enum sta_notify_cmd cmd, struct ieee80211_sta *sta) { - struct ar9170 *ar = hw->priv; struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; - struct sk_buff *skb, *tmp; - struct sk_buff_head free; - int i; switch (cmd) { case STA_NOTIFY_SLEEP: - /* - * Since the peer is no longer listening, we have to return - * as many SKBs as possible back to the mac80211 stack. - * It will deal with the retry procedure, once the peer - * has become available again. - * - * NB: Ideally, the driver should return the all frames in - * the correct, ascending order. However, I think that this - * functionality should be implemented in the stack and not - * here... - */ - - __skb_queue_head_init(&free); - - if (sta->ht_cap.ht_supported) { - rcu_read_lock(); - for (i = 0; i < CARL9170_NUM_TID; i++) { - struct carl9170_sta_tid *tid_info; - - tid_info = rcu_dereference(sta_info->agg[i]); - - if (!tid_info) - continue; - - spin_lock_bh(&ar->tx_ampdu_list_lock); - if (tid_info->state > - CARL9170_TID_STATE_SUSPEND) - tid_info->state = - CARL9170_TID_STATE_SUSPEND; - spin_unlock_bh(&ar->tx_ampdu_list_lock); - - spin_lock_bh(&tid_info->lock); - while ((skb = __skb_dequeue(&tid_info->queue))) - __skb_queue_tail(&free, skb); - spin_unlock_bh(&tid_info->lock); - } - rcu_read_unlock(); - } - - for (i = 0; i < ar->hw->queues; i++) { - spin_lock_bh(&ar->tx_pending[i].lock); - skb_queue_walk_safe(&ar->tx_pending[i], skb, tmp) { - struct _carl9170_tx_superframe *super; - struct ieee80211_hdr *hdr; - struct ieee80211_tx_info *info; - - super = (void *) skb->data; - hdr = (void *) super->frame_data; - - if (compare_ether_addr(hdr->addr1, sta->addr)) - continue; - - __skb_unlink(skb, &ar->tx_pending[i]); - - info = IEEE80211_SKB_CB(skb); - if (info->flags & IEEE80211_TX_CTL_AMPDU) - atomic_dec(&ar->tx_ampdu_upload); - - carl9170_tx_status(ar, skb, false); - } - spin_unlock_bh(&ar->tx_pending[i].lock); - } - - while ((skb = __skb_dequeue(&free))) - carl9170_tx_status(ar, skb, false); - + sta_info->sleeping = true; + if (atomic_read(&sta_info->pending_frames)) + ieee80211_sta_block_awake(hw, sta, true); break; case STA_NOTIFY_AWAKE: - if (!sta->ht_cap.ht_supported) - return; - - rcu_read_lock(); - for (i = 0; i < CARL9170_NUM_TID; i++) { - struct carl9170_sta_tid *tid_info; - - tid_info = rcu_dereference(sta_info->agg[i]); - - if (!tid_info) - continue; - - if ((tid_info->state == CARL9170_TID_STATE_SUSPEND)) - tid_info->state = CARL9170_TID_STATE_IDLE; - } - rcu_read_unlock(); + sta_info->sleeping = false; break; } } diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index cb70ed7ec5cc..bf2eff9dd582 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c @@ -104,6 +104,56 @@ static void carl9170_tx_accounting(struct ar9170 *ar, struct sk_buff *skb) spin_unlock_bh(&ar->tx_stats_lock); } +/* needs rcu_read_lock */ +static struct ieee80211_sta *__carl9170_get_tx_sta(struct ar9170 *ar, + struct sk_buff *skb) +{ + struct _carl9170_tx_superframe *super = (void *) skb->data; + struct ieee80211_hdr *hdr = (void *) super->frame_data; + struct ieee80211_vif *vif; + unsigned int vif_id; + + vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> + CARL9170_TX_SUPER_MISC_VIF_ID_S; + + if (WARN_ON_ONCE(vif_id >= AR9170_MAX_VIRTUAL_MAC)) + return NULL; + + vif = rcu_dereference(ar->vif_priv[vif_id].vif); + if (unlikely(!vif)) + return NULL; + + /* + * Normally we should use wrappers like ieee80211_get_DA to get + * the correct peer ieee80211_sta. + * + * But there is a problem with indirect traffic (broadcasts, or + * data which is designated for other stations) in station mode. + * The frame will be directed to the AP for distribution and not + * to the actual destination. + */ + + return ieee80211_find_sta(vif, hdr->addr1); +} + +static void carl9170_tx_ps_unblock(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ieee80211_sta *sta; + struct carl9170_sta_info *sta_info; + + rcu_read_lock(); + sta = __carl9170_get_tx_sta(ar, skb); + if (unlikely(!sta)) + goto out_rcu; + + sta_info = (struct carl9170_sta_info *) sta->drv_priv; + if (atomic_dec_return(&sta_info->pending_frames) == 0) + ieee80211_sta_block_awake(ar->hw, sta, false); + +out_rcu: + rcu_read_unlock(); +} + static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb) { struct ieee80211_tx_info *txinfo; @@ -135,6 +185,7 @@ static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb) } spin_unlock_bh(&ar->tx_stats_lock); + if (atomic_dec_and_test(&ar->tx_total_queued)) complete(&ar->tx_flush); } @@ -329,13 +380,10 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, { struct _carl9170_tx_superframe *super = (void *) skb->data; struct ieee80211_hdr *hdr = (void *) super->frame_data; - struct ieee80211_tx_info *tx_info; struct carl9170_tx_info *ar_info; - struct carl9170_sta_info *sta_info; struct ieee80211_sta *sta; + struct carl9170_sta_info *sta_info; struct carl9170_sta_tid *tid_info; - struct ieee80211_vif *vif; - unsigned int vif_id; u8 tid; if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || @@ -343,30 +391,10 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) return; - tx_info = IEEE80211_SKB_CB(skb); - ar_info = (void *) tx_info->rate_driver_data; - - vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> - CARL9170_TX_SUPER_MISC_VIF_ID_S; - - if (WARN_ON_ONCE(vif_id >= AR9170_MAX_VIRTUAL_MAC)) - return; + ar_info = (void *) txinfo->rate_driver_data; rcu_read_lock(); - vif = rcu_dereference(ar->vif_priv[vif_id].vif); - if (unlikely(!vif)) - goto out_rcu; - - /* - * Normally we should use wrappers like ieee80211_get_DA to get - * the correct peer ieee80211_sta. - * - * But there is a problem with indirect traffic (broadcasts, or - * data which is designated for other stations) in station mode. - * The frame will be directed to the AP for distribution and not - * to the actual destination. - */ - sta = ieee80211_find_sta(vif, hdr->addr1); + sta = __carl9170_get_tx_sta(ar, skb); if (unlikely(!sta)) goto out_rcu; @@ -427,6 +455,7 @@ void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, if (txinfo->flags & IEEE80211_TX_CTL_AMPDU) carl9170_tx_status_process_ampdu(ar, skb, txinfo); + carl9170_tx_ps_unblock(ar, skb); carl9170_tx_put_skb(skb); } @@ -540,11 +569,7 @@ static void carl9170_tx_ampdu_timeout(struct ar9170 *ar) struct sk_buff *skb; struct ieee80211_tx_info *txinfo; struct carl9170_tx_info *arinfo; - struct _carl9170_tx_superframe *super; struct ieee80211_sta *sta; - struct ieee80211_vif *vif; - struct ieee80211_hdr *hdr; - unsigned int vif_id; rcu_read_lock(); list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) { @@ -562,20 +587,7 @@ static void carl9170_tx_ampdu_timeout(struct ar9170 *ar) msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT))) goto unlock; - super = (void *) skb->data; - hdr = (void *) super->frame_data; - - vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> - CARL9170_TX_SUPER_MISC_VIF_ID_S; - - if (WARN_ON(vif_id >= AR9170_MAX_VIRTUAL_MAC)) - goto unlock; - - vif = rcu_dereference(ar->vif_priv[vif_id].vif); - if (WARN_ON(!vif)) - goto unlock; - - sta = ieee80211_find_sta(vif, hdr->addr1); + sta = __carl9170_get_tx_sta(ar, skb); if (WARN_ON(!sta)) goto unlock; @@ -1199,15 +1211,6 @@ static struct sk_buff *carl9170_tx_pick_skb(struct ar9170 *ar, arinfo = (void *) info->rate_driver_data; arinfo->timeout = jiffies; - - /* - * increase ref count to "2". - * Ref counting is the easiest way to solve the race between - * the the urb's completion routine: carl9170_tx_callback and - * wlan tx status functions: carl9170_tx_status/janitor. - */ - carl9170_tx_get_skb(skb); - return skb; err_unlock: @@ -1228,6 +1231,36 @@ void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb) __carl9170_tx_process_status(ar, super->s.cookie, q); } +static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ieee80211_sta *sta; + struct carl9170_sta_info *sta_info; + + rcu_read_lock(); + sta = __carl9170_get_tx_sta(ar, skb); + if (!sta) + goto out_rcu; + + sta_info = (void *) sta->drv_priv; + if (unlikely(sta_info->sleeping)) { + struct ieee80211_tx_info *tx_info; + + rcu_read_unlock(); + + tx_info = IEEE80211_SKB_CB(skb); + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) + atomic_dec(&ar->tx_ampdu_upload); + + tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; + carl9170_tx_status(ar, skb, false); + return true; + } + +out_rcu: + rcu_read_unlock(); + return false; +} + static void carl9170_tx(struct ar9170 *ar) { struct sk_buff *skb; @@ -1247,6 +1280,9 @@ static void carl9170_tx(struct ar9170 *ar) if (unlikely(!skb)) break; + if (unlikely(carl9170_tx_ps_drop(ar, skb))) + continue; + atomic_inc(&ar->tx_total_pending); q = __carl9170_get_queue(ar, i); @@ -1256,6 +1292,16 @@ static void carl9170_tx(struct ar9170 *ar) */ skb_queue_tail(&ar->tx_status[q], skb); + /* + * increase ref count to "2". + * Ref counting is the easiest way to solve the + * race between the urb's completion routine: + * carl9170_tx_callback + * and wlan tx status functions: + * carl9170_tx_status/janitor. + */ + carl9170_tx_get_skb(skb); + carl9170_usb_tx(ar, skb); schedule_garbagecollector = true; } @@ -1368,6 +1414,11 @@ void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * all ressouces which are associated with the frame. */ + if (sta) { + struct carl9170_sta_info *stai = (void *) sta->drv_priv; + atomic_inc(&stai->pending_frames); + } + if (info->flags & IEEE80211_TX_CTL_AMPDU) { run = carl9170_tx_ampdu_queue(ar, sta, skb); if (run) -- cgit v1.2.3-58-ga151 From 334df731976ee4042c9bf18b2eec9c0a71f45389 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 24 Apr 2011 20:41:16 +0200 Subject: mac80211: fix too early reorder release timer The release timer has to expire "just" after a frame is up for release. Currently, if the timer callback starts on time, the "!time_after" check above will start a new timer instead of releasing the frames. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- net/mac80211/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 1f06b31e21c1..b04a4378adcc 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -652,7 +652,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, set_release_timer: mod_timer(&tid_agg_rx->reorder_timer, - tid_agg_rx->reorder_time[j] + + tid_agg_rx->reorder_time[j] + 1 + HT_RX_REORDER_BUF_TIMEOUT); } else { del_timer(&tid_agg_rx->reorder_timer); -- cgit v1.2.3-58-ga151 From 0915cba394268e68b6a8242b15f8c7283453df43 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 25 Apr 2011 15:56:17 +0530 Subject: mac80211: Fix warnings due to -Wunused-but-set-variable These warnings are exposed by gcc 4.6. net/mac80211/sta_info.c: In function 'sta_info_cleanup_expire_buffered': net/mac80211/sta_info.c:590:32: warning: variable 'sdata' set but not used net/mac80211/ibss.c: In function 'ieee80211_rx_mgmt_auth_ibss': net/mac80211/ibss.c:43:34: warning: variable 'status_code' set but not used net/mac80211/work.c: In function 'ieee80211_send_assoc': net/mac80211/work.c:203:9: warning: variable 'len' set but not used net/mac80211/tx.c: In function '__ieee80211_parse_tx_radiotap': net/mac80211/tx.c:1039:35: warning: variable 'sband' set but not used net/mac80211/mesh.c: In function 'ieee80211_mesh_rx_queued_mgmt': net/mac80211/mesh.c:616:28: warning: variable 'ifmsh' set but not used ... Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- net/mac80211/aes_ccm.c | 6 ++---- net/mac80211/ibss.c | 7 +------ net/mac80211/mesh.c | 3 --- net/mac80211/mesh_hwmp.c | 4 ---- net/mac80211/sta_info.c | 2 -- net/mac80211/tx.c | 8 -------- net/mac80211/work.c | 6 ++---- 7 files changed, 5 insertions(+), 31 deletions(-) diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index 4bd6ef0be380..b9b595c08112 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c @@ -54,13 +54,12 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, u8 *cdata, u8 *mic) { int i, j, last_len, num_blocks; - u8 *pos, *cpos, *b, *s_0, *e, *b_0, *aad; + u8 *pos, *cpos, *b, *s_0, *e, *b_0; b = scratch; s_0 = scratch + AES_BLOCK_LEN; e = scratch + 2 * AES_BLOCK_LEN; b_0 = scratch + 3 * AES_BLOCK_LEN; - aad = scratch + 4 * AES_BLOCK_LEN; num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); last_len = data_len % AES_BLOCK_LEN; @@ -94,13 +93,12 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, u8 *cdata, size_t data_len, u8 *mic, u8 *data) { int i, j, last_len, num_blocks; - u8 *pos, *cpos, *b, *s_0, *a, *b_0, *aad; + u8 *pos, *cpos, *b, *s_0, *a, *b_0; b = scratch; s_0 = scratch + AES_BLOCK_LEN; a = scratch + 2 * AES_BLOCK_LEN; b_0 = scratch + 3 * AES_BLOCK_LEN; - aad = scratch + 4 * AES_BLOCK_LEN; num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); last_len = data_len % AES_BLOCK_LEN; diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 14883966374e..b81860c94698 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -40,7 +40,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { - u16 auth_alg, auth_transaction, status_code; + u16 auth_alg, auth_transaction; lockdep_assert_held(&sdata->u.ibss.mtx); @@ -49,7 +49,6 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); - status_code = le16_to_cpu(mgmt->u.auth.status_code); /* * IEEE 802.11 standard does not require authentication in IBSS @@ -527,8 +526,6 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; u8 bssid[ETH_ALEN]; u16 capability; int i; @@ -551,8 +548,6 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", sdata->name, bssid); - sband = local->hw.wiphy->bands[ifibss->channel->band]; - capability = WLAN_CAPABILITY_IBSS; if (ifibss->privacy) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 11207979e2e2..c1299e249541 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -613,12 +613,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { struct ieee80211_rx_status *rx_status; - struct ieee80211_if_mesh *ifmsh; struct ieee80211_mgmt *mgmt; u16 stype; - ifmsh = &sdata->u.mesh; - rx_status = IEEE80211_SKB_RXCB(skb); mgmt = (struct ieee80211_mgmt *) skb->data; stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 5bf64d7112b3..e57f2e728cfe 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -633,7 +633,6 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, struct mesh_path *mpath; u8 ttl; u8 *ta, *target_addr; - u8 target_flags; u32 target_sn; u16 target_rcode; @@ -644,7 +643,6 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, return; } ttl--; - target_flags = PERR_IE_TARGET_FLAGS(perr_elem); target_addr = PERR_IE_TARGET_ADDR(perr_elem); target_sn = PERR_IE_TARGET_SN(perr_elem); target_rcode = PERR_IE_TARGET_RCODE(perr_elem); @@ -675,12 +673,10 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct mesh_path *mpath; - u8 *ta; u8 ttl, flags, hopcount; u8 *orig_addr; u32 orig_sn, metric; - ta = mgmt->sa; ttl = rann->rann_ttl; if (ttl <= 1) { ifmsh->mshstats.dropped_frames_ttl++; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 7c5c6da01bea..f05244dc773e 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -587,7 +587,6 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, { unsigned long flags; struct sk_buff *skb; - struct ieee80211_sub_if_data *sdata; if (skb_queue_empty(&sta->ps_tx_buf)) return false; @@ -604,7 +603,6 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, if (!skb) break; - sdata = sta->sdata; local->total_ps_buffered--; #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "Buffered frame expired (STA %pM)\n", diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 17b10be31f55..a2043e405493 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1036,14 +1036,11 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, struct ieee80211_radiotap_iterator iterator; struct ieee80211_radiotap_header *rthdr = (struct ieee80211_radiotap_header *) skb->data; - struct ieee80211_supported_band *sband; bool hw_frag; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, NULL); - sband = tx->local->hw.wiphy->bands[tx->channel->band]; - info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; tx->flags &= ~IEEE80211_TX_FRAGMENTED; @@ -1442,11 +1439,8 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, struct ieee80211_tx_data tx; ieee80211_tx_result res_prepare; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - u16 queue; bool result = true; - queue = skb_get_queue_mapping(skb); - if (unlikely(skb->len < 10)) { dev_kfree_skb(skb); return true; @@ -2485,7 +2479,6 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, { struct ieee80211_local *local = hw_to_local(hw); struct sk_buff *skb = NULL; - struct sta_info *sta; struct ieee80211_tx_data tx; struct ieee80211_sub_if_data *sdata; struct ieee80211_if_ap *bss = NULL; @@ -2527,7 +2520,6 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, info = IEEE80211_SKB_CB(skb); - sta = tx.sta; tx.flags |= IEEE80211_TX_PS_BUFFERED; tx.channel = local->hw.conf.channel; info->band = tx.channel->band; diff --git a/net/mac80211/work.c b/net/mac80211/work.c index e73c8cae036b..a94b312dbfac 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -198,9 +198,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos, qos_info; - const u8 *ies; size_t offset = 0, noffset; - int i, len, count, rates_len, supp_rates_len; + int i, count, rates_len, supp_rates_len; u16 capab; struct ieee80211_supported_band *sband; u32 rates = 0; @@ -285,7 +284,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, } /* SSID */ - ies = pos = skb_put(skb, 2 + wk->assoc.ssid_len); + pos = skb_put(skb, 2 + wk->assoc.ssid_len); *pos++ = WLAN_EID_SSID; *pos++ = wk->assoc.ssid_len; memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len); @@ -295,7 +294,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, if (supp_rates_len > 8) supp_rates_len = 8; - len = sband->n_bitrates; pos = skb_put(skb, supp_rates_len + 2); *pos++ = WLAN_EID_SUPP_RATES; *pos++ = supp_rates_len; -- cgit v1.2.3-58-ga151 From e25f51d4f9f8c45382a33b6283418be46425195c Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:52:44 -0500 Subject: rtlwifi: Change efuse routines addition of RTL8192SE and RTL8192DE Change efuse routines for addition of RTL8192SE and RTL8192DE code Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/efuse.c | 99 ++++++++++++++++++++++-------------- drivers/net/wireless/rtlwifi/efuse.h | 5 +- 2 files changed, 66 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index 5d73c0f7012c..664703ce9da8 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c @@ -52,8 +52,6 @@ static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { {11, 0, 0, 28} }; -static void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, - u8 *pbuf); static void efuse_shadow_read_1byte(struct ieee80211_hw *hw, u16 offset, u8 *value); static void efuse_shadow_read_2byte(struct ieee80211_hw *hw, u16 offset, @@ -79,7 +77,7 @@ static void efuse_word_enable_data_read(u8 word_en, u8 *sourdata, u8 *targetdata); static u8 efuse_word_enable_data_write(struct ieee80211_hw *hw, u16 efuse_addr, u8 word_en, u8 *data); -static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, +static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate); static u16 efuse_get_current_size(struct ieee80211_hw *hw); static u8 efuse_calculate_word_cnts(u8 word_en); @@ -115,8 +113,10 @@ u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address) u8 bytetemp; u8 temp; u32 k = 0; + const u32 efuse_len = + rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; - if (address < EFUSE_REAL_CONTENT_LEN) { + if (address < efuse_len) { temp = address & 0xFF; rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, temp); @@ -158,11 +158,13 @@ void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value) u8 bytetemp; u8 temp; u32 k = 0; + const u32 efuse_len = + rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("Addr=%x Data =%x\n", address, value)); - if (address < EFUSE_REAL_CONTENT_LEN) { + if (address < efuse_len) { rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], value); temp = address & 0xFF; @@ -198,7 +200,7 @@ void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value) } -static void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf) +void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 value32; @@ -233,24 +235,28 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 efuse_tbl[EFUSE_MAP_LEN]; + u8 efuse_tbl[rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]]; u8 rtemp8[1]; u16 efuse_addr = 0; u8 offset, wren; u16 i; u16 j; - u16 efuse_word[EFUSE_MAX_SECTION][EFUSE_MAX_WORD_UNIT]; + const u16 efuse_max_section = + rtlpriv->cfg->maps[EFUSE_MAX_SECTION_MAP]; + const u32 efuse_len = + rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; + u16 efuse_word[efuse_max_section][EFUSE_MAX_WORD_UNIT]; u16 efuse_utilized = 0; u8 efuse_usage; - if ((_offset + _size_byte) > EFUSE_MAP_LEN) { + if ((_offset + _size_byte) > rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]) { RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("read_efuse(): Invalid offset(%#x) with read " "bytes(%#x)!!\n", _offset, _size_byte)); return; } - for (i = 0; i < EFUSE_MAX_SECTION; i++) + for (i = 0; i < efuse_max_section; i++) for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) efuse_word[i][j] = 0xFFFF; @@ -262,10 +268,10 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) efuse_addr++; } - while ((*rtemp8 != 0xFF) && (efuse_addr < EFUSE_REAL_CONTENT_LEN)) { + while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) { offset = ((*rtemp8 >> 4) & 0x0f); - if (offset < EFUSE_MAX_SECTION) { + if (offset < efuse_max_section) { wren = (*rtemp8 & 0x0f); RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, ("offset-%d Worden=%x\n", offset, wren)); @@ -281,7 +287,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) efuse_utilized++; efuse_word[offset][i] = (*rtemp8 & 0xff); - if (efuse_addr >= EFUSE_REAL_CONTENT_LEN) + if (efuse_addr >= efuse_len) break; RTPRINT(rtlpriv, FEEPROM, @@ -294,7 +300,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) efuse_word[offset][i] |= (((u16)*rtemp8 << 8) & 0xff00); - if (efuse_addr >= EFUSE_REAL_CONTENT_LEN) + if (efuse_addr >= efuse_len) break; } @@ -305,13 +311,13 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, ("Addr=%d\n", efuse_addr)); read_efuse_byte(hw, efuse_addr, rtemp8); - if (*rtemp8 != 0xFF && (efuse_addr < 512)) { + if (*rtemp8 != 0xFF && (efuse_addr < efuse_len)) { efuse_utilized++; efuse_addr++; } } - for (i = 0; i < EFUSE_MAX_SECTION; i++) { + for (i = 0; i < efuse_max_section; i++) { for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { efuse_tbl[(i * 8) + (j * 2)] = (efuse_word[i][j] & 0xff); @@ -324,7 +330,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) pbuf[i] = efuse_tbl[_offset + i]; rtlefuse->efuse_usedbytes = efuse_utilized; - efuse_usage = (u8)((efuse_utilized * 100) / EFUSE_REAL_CONTENT_LEN); + efuse_usage = (u8) ((efuse_utilized * 100) / efuse_len); rtlefuse->efuse_usedpercentage = efuse_usage; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_utilized); @@ -478,9 +484,10 @@ void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - if (rtlefuse->autoload_failflag == true) { - memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF, 128); - } else + if (rtlefuse->autoload_failflag == true) + memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF, + rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); + else efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], @@ -632,8 +639,9 @@ static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data) static void efuse_read_all_map(struct ieee80211_hw *hw, u8 * efuse) { + struct rtl_priv *rtlpriv = rtl_priv(hw); efuse_power_switch(hw, false, true); - read_efuse(hw, 0, 128, efuse); + read_efuse(hw, 0, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], efuse); efuse_power_switch(hw, false, false); } @@ -641,7 +649,7 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, u8 efuse_data, u8 offset, u8 *tmpdata, u8 *readstate) { - bool bdataempty = true; + bool dataempty = true; u8 hoffset; u8 tmpidx; u8 hworden; @@ -657,13 +665,13 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, &efuse_data)) { tmpdata[tmpidx] = efuse_data; if (efuse_data != 0xff) - bdataempty = true; + dataempty = true; } } - if (bdataempty == true) + if (dataempty == true) { *readstate = PG_STATE_DATA; - else { + } else { *efuse_addr = *efuse_addr + (word_cnts * 2) + 1; *readstate = PG_STATE_HEADER; } @@ -677,9 +685,7 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) { u8 readstate = PG_STATE_HEADER; - bool continual = true; - u8 efuse_data, word_cnts = 0; u16 efuse_addr = 0; u8 tmpdata[8]; @@ -795,19 +801,20 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, tmp_word_en &= (~BIT(1)); if ((target_pkt->word_en & BIT(2)) ^ - (match_word_en & BIT(2))) + (match_word_en & BIT(2))) tmp_word_en &= (~BIT(2)); if ((target_pkt->word_en & BIT(3)) ^ - (match_word_en & BIT(3))) + (match_word_en & BIT(3))) tmp_word_en &= (~BIT(3)); if ((tmp_word_en & 0x0F) != 0x0F) { *efuse_addr = efuse_get_current_size(hw); target_pkt->offset = offset; target_pkt->word_en = tmp_word_en; - } else + } else { *continual = false; + } *write_state = PG_STATE_HEADER; *repeat_times += 1; if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { @@ -842,9 +849,9 @@ static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, efuse_one_byte_write(hw, *efuse_addr, pg_header); efuse_one_byte_read(hw, *efuse_addr, &tmp_header); - if (tmp_header == pg_header) + if (tmp_header == pg_header) { *write_state = PG_STATE_DATA; - else if (tmp_header == 0xFF) { + } else if (tmp_header == 0xFF) { *write_state = PG_STATE_HEADER; *repeat_times += 1; if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { @@ -871,11 +878,13 @@ static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, reorg_worden, originaldata); *efuse_addr = efuse_get_current_size(hw); - } else + } else { *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; - } else + } + } else { *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; + } *write_state = PG_STATE_HEADER; *repeat_times += 1; @@ -1069,10 +1078,12 @@ static u8 efuse_word_enable_data_write(struct ieee80211_hw *hw, static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u8 tempval; u16 tmpV16; - if (pwrstate) { + if (pwrstate && (rtlhal->hw_type != + HARDWARE_TYPE_RTL8192SE)) { tmpV16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL]); if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { @@ -1105,13 +1116,22 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) tempval = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3); - tempval &= 0x0F; - tempval |= (VOLTAGE_V25 << 4); + + if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) { + tempval &= 0x0F; + tempval |= (VOLTAGE_V25 << 4); + } + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3, (tempval | 0x80)); } + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK], + 0x03); + } + } else { if (write) { tempval = rtl_read_byte(rtlpriv, @@ -1122,6 +1142,11 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) (tempval & 0x7F)); } + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK], + 0x02); + } + } } diff --git a/drivers/net/wireless/rtlwifi/efuse.h b/drivers/net/wireless/rtlwifi/efuse.h index 47774dd4c2a6..164dabaa7615 100644 --- a/drivers/net/wireless/rtlwifi/efuse.h +++ b/drivers/net/wireless/rtlwifi/efuse.h @@ -30,9 +30,10 @@ #ifndef __RTL_EFUSE_H_ #define __RTL_EFUSE_H_ +#define EFUSE_IC_ID_OFFSET 506 + #define EFUSE_REAL_CONTENT_LEN 512 #define EFUSE_MAP_LEN 128 -#define EFUSE_MAX_SECTION 16 #define EFUSE_MAX_WORD_UNIT 4 #define EFUSE_INIT_MAP 0 @@ -52,6 +53,7 @@ #define _PRE_EXECUTE_READ_CMD_ #define EFUSE_REPEAT_THRESHOLD_ 3 +#define EFUSE_ERROE_HANDLE 1 struct efuse_map { u8 offset; @@ -103,6 +105,7 @@ struct efuse_priv { u8 tx_power_g[14]; }; +extern void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf); extern void efuse_initialize(struct ieee80211_hw *hw); extern u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address); extern void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value); -- cgit v1.2.3-58-ga151 From 3dad618b7b929010f05b179bbc4d56e3d5956083 Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:52:49 -0500 Subject: rtlwifi: Change wifi.h for rtl8192se and rtl8192de Change wifi.h for addition of RTL8192SE and RTL8192DE code Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 4 +- drivers/net/wireless/rtlwifi/wifi.h | 161 ++++++++++++++++++++-- 2 files changed, 155 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index c228b9ee3711..5ea3a5ef819b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -640,7 +640,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw u8 txpwr_level[2] = {0, 0}; u8 ofdm_min_index = 6, rf; - rtlpriv->dm.txpower_trackingInit = true; + rtlpriv->dm.txpower_trackinginit = true; RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("rtl92c_dm_txpower_tracking_callback_thermalmeter\n")); @@ -1062,7 +1062,7 @@ static void rtl92c_dm_initialize_txpower_tracking_thermalmeter( struct rtl_priv *rtlpriv = rtl_priv(hw); rtlpriv->dm.txpower_tracking = true; - rtlpriv->dm.txpower_trackingInit = false; + rtlpriv->dm.txpower_trackinginit = false; RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("pMgntInfo->txpower_tracking = %d\n", diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 4ce4853975f1..9124b30c605d 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -68,6 +68,8 @@ #define QBSS_LOAD_SIZE 5 #define MAX_WMMELE_LENGTH 64 +#define TOTAL_CAM_ENTRY 32 + /*slot time for 11g. */ #define RTL_SLOT_TIME_9 9 #define RTL_SLOT_TIME_20 20 @@ -94,8 +96,10 @@ #define CHANNEL_GROUP_MAX_5G 9 #define CHANNEL_MAX_NUMBER_2G 14 #define AVG_THERMAL_NUM 8 +#define MAX_TID_COUNT 9 /* for early mode */ +#define FCS_LEN 4 #define EM_HDR_LEN 8 enum intf_type { INTF_PCI = 0, @@ -159,6 +163,8 @@ enum hardware_type { (IS_HARDWARE_TYPE_8192DE(rtlhal) || IS_HARDWARE_TYPE_8192DU(rtlhal)) #define IS_HARDWARE_TYPE_8723(rtlhal) \ (IS_HARDWARE_TYPE_8723E(rtlhal) || IS_HARDWARE_TYPE_8723U(rtlhal)) +#define IS_HARDWARE_TYPE_8723U(rtlhal) \ + (rtlhal->hw_type == HARDWARE_TYPE_RTL8723U) enum scan_operation_backup_opt { SCAN_OPT_BACKUP = 0, @@ -843,6 +849,7 @@ struct rtl_phy { bool apk_done; u32 reg_rf3c[2]; /* pathA / pathB */ + /* bfsync */ u8 framesync; u32 framesync_c34; @@ -852,6 +859,10 @@ struct rtl_phy { }; #define MAX_TID_COUNT 9 +#define RTL_AGG_STOP 0 +#define RTL_AGG_PROGRESS 1 +#define RTL_AGG_START 2 +#define RTL_AGG_OPERATIONAL 3 #define RTL_AGG_OFF 0 #define RTL_AGG_ON 1 #define RTL_AGG_EMPTYING_HW_QUEUE_ADDBA 2 @@ -871,6 +882,13 @@ struct rtl_tid_data { struct rtl_ht_agg agg; }; +struct rtl_sta_info { + u8 ratr_index; + u8 wireless_mode; + u8 mimo_ps; + struct rtl_tid_data tids[MAX_TID_COUNT]; +} __packed; + struct rtl_priv; struct rtl_io { struct device *dev; @@ -894,6 +912,7 @@ struct rtl_io { u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr); int (*readN_sync) (struct rtl_priv *rtlpriv, u32 addr, u16 len, u8 *pdata); + }; struct rtl_mac { @@ -916,6 +935,8 @@ struct rtl_mac { int n_channels; int n_bitrates; + bool offchan_deley; + /*filters */ u32 rx_conf; u16 rx_mgt_filter; @@ -1032,7 +1053,9 @@ struct rtl_security { enum rt_enc_alg pairwise_enc_algorithm; /*Encryption Algorithm for Brocast/Multicast */ enum rt_enc_alg group_enc_algorithm; - + /*Cam Entry Bitmap */ + u32 hwsec_cam_bitmap; + u8 hwsec_cam_sta_addr[TOTAL_CAM_ENTRY][ETH_ALEN]; /*local Key buffer, indx 0 is for pairwise key 1-4 is for agoup key. */ u8 key_buf[KEY_BUF_SIZE][MAX_KEY_LEN]; @@ -1053,7 +1076,7 @@ struct rtl_dm { bool current_turbo_edca; bool is_any_nonbepkts; /*out dm */ bool is_cur_rdlstate; - bool txpower_trackingInit; + bool txpower_trackinginit; bool disable_framebursting; bool cck_inch14; bool txpower_tracking; @@ -1079,7 +1102,6 @@ struct rtl_dm { bool disable_tx_int; char ofdm_index[2]; char cck_index; - u8 power_index_backup[6]; }; #define EFUSE_MAX_LOGICAL_SIZE 256 @@ -1175,6 +1197,7 @@ struct rtl_ps_ctl { * otherwise Offset[560h] = 0x00. * */ bool support_aspm; + bool support_backdoor; /*for LPS */ @@ -1201,7 +1224,6 @@ struct rtl_ps_ctl { /*just for PCIE ASPM */ u8 const_amdpci_aspm; - bool pwrdown_mode; enum rf_pwrstate inactive_pwrstate; @@ -1282,6 +1304,10 @@ struct rt_link_detect { bool busytraffic; bool higher_busytraffic; bool higher_busyrxtraffic; + + u32 tidtx_in4period[MAX_TID_COUNT][4]; + u32 tidtx_inperiod[MAX_TID_COUNT]; + bool higher_busytxtraffic[MAX_TID_COUNT]; }; struct rtl_tcb_desc { @@ -1344,13 +1370,26 @@ struct rtl_hal_ops { u32 add_msr, u32 rm_msr); void (*get_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); void (*set_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); +#if 0 /* temporary */ + void (*update_rate_tbl) (struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level); +#else void (*update_rate_table) (struct ieee80211_hw *hw); +#endif void (*update_rate_mask) (struct ieee80211_hw *hw, u8 rssi_level); +#if 0 /* temporary */ + void (*fill_tx_desc) (struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + struct ieee80211_tx_info *info, + struct sk_buff *skb, u8 hw_queue, + struct rtl_tcb_desc *ptcb_desc); +#else void (*fill_tx_desc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, struct sk_buff *skb, unsigned int queue_index); - void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 * pDesc, +#endif + void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 *pDesc, u32 buffer_len, bool bIsPsPoll); void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, bool lastseg, @@ -1370,10 +1409,10 @@ struct rtl_hal_ops { enum led_ctl_mode ledaction); void (*set_desc) (u8 *pdesc, bool istx, u8 desc_name, u8 *val); u32 (*get_desc) (u8 *pdesc, bool istx, u8 desc_name); - void (*tx_polling) (struct ieee80211_hw *hw, unsigned int hw_queue); + void (*tx_polling) (struct ieee80211_hw *hw, u8 hw_queue); void (*enable_hw_sec) (struct ieee80211_hw *hw); void (*set_key) (struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, + u8 *macaddr, bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all); void (*init_sw_leds) (struct ieee80211_hw *hw); void (*deinit_sw_leds) (struct ieee80211_hw *hw); @@ -1384,6 +1423,7 @@ struct rtl_hal_ops { u32 regaddr, u32 bitmask); void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask, u32 data); + void (*linked_set_reg) (struct ieee80211_hw *hw); bool (*phy_rf6052_config) (struct ieee80211_hw *hw); void (*phy_rf6052_set_cck_txpower) (struct ieee80211_hw *hw, u8 *powerlevel); @@ -1404,7 +1444,13 @@ struct rtl_intf_ops { int (*adapter_start) (struct ieee80211_hw *hw); void (*adapter_stop) (struct ieee80211_hw *hw); +#if 0 /* temporary */ + int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb, + struct rtl_tcb_desc *ptcb_desc); +#else int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb); +#endif + void (*flush)(struct ieee80211_hw *hw, bool drop); int (*reset_trx_ring) (struct ieee80211_hw *hw); bool (*waitq_insert) (struct ieee80211_hw *hw, struct sk_buff *skb); @@ -1418,6 +1464,15 @@ struct rtl_intf_ops { struct rtl_mod_params { /* default: 0 = using hardware encryption */ int sw_crypto; + + /* default: 1 = using no linked power save */ + bool inactiveps; + + /* default: 1 = using linked sw power save */ + bool swctrl_lps; + + /* default: 1 = using linked fw power save */ + bool fwctrl_lps; }; struct rtl_hal_usbint_cfg { @@ -1445,6 +1500,7 @@ struct rtl_hal_usbint_cfg { struct rtl_hal_cfg { u8 bar_id; + bool write_readback; char *name; char *fw_name; struct rtl_hal_ops *ops; @@ -1469,7 +1525,6 @@ struct rtl_locks { spinlock_t rf_lock; spinlock_t lps_lock; spinlock_t waitq_lock; - spinlock_t tx_urb_lock; /*Dual mac*/ spinlock_t cck_and_rw_pagea_lock; @@ -1653,13 +1708,23 @@ struct bt_coexist_info { #define EF4BYTE(_val) \ (le32_to_cpu(_val)) +/* Read data from memory */ +#define READEF1BYTE(_ptr) \ + EF1BYTE(*((u8 *)(_ptr))) /* Read le16 data from memory and convert to host ordering */ #define READEF2BYTE(_ptr) \ EF2BYTE(*((u16 *)(_ptr))) +#define READEF4BYTE(_ptr) \ + EF4BYTE(*((u32 *)(_ptr))) +/* Write data to memory */ +#define WRITEEF1BYTE(_ptr, _val) \ + (*((u8 *)(_ptr))) = EF1BYTE(_val) /* Write le16 data to memory in host ordering */ #define WRITEEF2BYTE(_ptr, _val) \ (*((u16 *)(_ptr))) = EF2BYTE(_val) +#define WRITEEF4BYTE(_ptr, _val) \ + (*((u16 *)(_ptr))) = EF2BYTE(_val) /* Create a bit mask * Examples: @@ -1698,6 +1763,25 @@ struct bt_coexist_info { #define LE_P1BYTE_TO_HOST_1BYTE(__pstart) \ (EF1BYTE(*((u8 *)(__pstart)))) +/*Description: +Translate subfield (continuous bits in little-endian) of 4-byte +value to host byte ordering.*/ +#define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + (LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset)) & \ + BIT_LEN_MASK_32(__bitlen) \ + ) +#define LE_BITS_TO_2BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + (LE_P2BYTE_TO_HOST_2BYTE(__pstart) >> (__bitoffset)) & \ + BIT_LEN_MASK_16(__bitlen) \ + ) +#define LE_BITS_TO_1BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + (LE_P1BYTE_TO_HOST_1BYTE(__pstart) >> (__bitoffset)) & \ + BIT_LEN_MASK_8(__bitlen) \ + ) + /* Description: * Mask subfield (continuous bits in little-endian) of 4-byte value * and return the result in 4-byte value in host byte ordering. @@ -1721,6 +1805,18 @@ struct bt_coexist_info { /* Description: * Set subfield of little-endian 4-byte value to specified value. */ +#define SET_BITS_TO_LE_4BYTE(__pstart, __bitoffset, __bitlen, __val) \ + *((u32 *)(__pstart)) = EF4BYTE \ + ( \ + LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) | \ + ((((u32)__val) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset)) \ + ); +#define SET_BITS_TO_LE_2BYTE(__pstart, __bitoffset, __bitlen, __val) \ + *((u16 *)(__pstart)) = EF2BYTE \ + ( \ + LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \ + ((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset)) \ + ); #define SET_BITS_TO_LE_1BYTE(__pstart, __bitoffset, __bitlen, __val) \ *((u8 *)(__pstart)) = EF1BYTE \ ( \ @@ -1728,12 +1824,16 @@ struct bt_coexist_info { ((((u8)__val) & BIT_LEN_MASK_8(__bitlen)) << (__bitoffset)) \ ); +#define N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \ + (__value) : (((__value + __aligment - 1) / __aligment) * __aligment)) + /**************************************** mem access macro define end ****************************************/ #define byte(x, n) ((x >> (8 * n)) & 0xff) +#define packet_get_type(_packet) (EF1BYTE((_packet).octet[0]) & 0xFC) #define RTL_WATCH_DOG_TIME 2000 #define MSECS(t) msecs_to_jiffies(t) #define WLAN_FC_GET_VERS(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_VERS) @@ -1768,6 +1868,15 @@ struct bt_coexist_info { #define container_of_dwork_rtl(x, y, z) \ container_of(container_of(x, struct delayed_work, work), y, z) +#define FILL_OCTET_STRING(_os, _octet, _len) \ + (_os).octet = (u8 *)(_octet); \ + (_os).length = (_len); + +#define CP_MACADDR(des, src) \ + ((des)[0] = (src)[0], (des)[1] = (src)[1],\ + (des)[2] = (src)[2], (des)[3] = (src)[3],\ + (des)[4] = (src)[4], (des)[5] = (src)[5]) + static inline u8 rtl_read_byte(struct rtl_priv *rtlpriv, u32 addr) { return rtlpriv->io.read8_sync(rtlpriv, addr); @@ -1786,17 +1895,26 @@ static inline u32 rtl_read_dword(struct rtl_priv *rtlpriv, u32 addr) static inline void rtl_write_byte(struct rtl_priv *rtlpriv, u32 addr, u8 val8) { rtlpriv->io.write8_async(rtlpriv, addr, val8); + + if (rtlpriv->cfg->write_readback) + rtlpriv->io.read8_sync(rtlpriv, addr); } static inline void rtl_write_word(struct rtl_priv *rtlpriv, u32 addr, u16 val16) { rtlpriv->io.write16_async(rtlpriv, addr, val16); + + if (rtlpriv->cfg->write_readback) + rtlpriv->io.read16_sync(rtlpriv, addr); } static inline void rtl_write_dword(struct rtl_priv *rtlpriv, u32 addr, u32 val32) { rtlpriv->io.write32_async(rtlpriv, addr, val32); + + if (rtlpriv->cfg->write_readback) + rtlpriv->io.read32_sync(rtlpriv, addr); } static inline u32 rtl_get_bbreg(struct ieee80211_hw *hw, @@ -1855,4 +1973,31 @@ static inline u8 get_rf_type(struct rtl_phy *rtlphy) return rtlphy->rf_type; } +static inline struct ieee80211_hdr *rtl_get_hdr(struct sk_buff *skb) +{ + return (struct ieee80211_hdr *)(skb->data); +} + +static inline u16 rtl_get_fc(struct sk_buff *skb) +{ + return le16_to_cpu(rtl_get_hdr(skb)->frame_control); +} + +static inline u16 rtl_get_tid_h(struct ieee80211_hdr *hdr) +{ + return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; +} + +static inline u16 rtl_get_tid(struct sk_buff *skb) +{ + return rtl_get_tid_h(rtl_get_hdr(skb)); +} + +static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u8 *bssid) +{ + return ieee80211_find_sta(vif, bssid); +} + #endif -- cgit v1.2.3-58-ga151 From acd48572c396364bb480175d7de83944eefa2563 Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:52:54 -0500 Subject: rtlwifi: Change base routines for addition of rtl8192se and rtl8192de Change base routines for addition of RTL8192SE and RTL8192DE code. Additional files are modified to allow compilation. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/base.c | 726 ++++++++++++++++++++++----- drivers/net/wireless/rtlwifi/base.h | 60 ++- drivers/net/wireless/rtlwifi/pci.c | 2 - drivers/net/wireless/rtlwifi/ps.c | 8 + drivers/net/wireless/rtlwifi/ps.h | 7 + drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 2 +- drivers/net/wireless/rtlwifi/usb.c | 2 - drivers/net/wireless/rtlwifi/usb.h | 2 + drivers/net/wireless/rtlwifi/wifi.h | 5 +- 10 files changed, 675 insertions(+), 141 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 9477785f1168..7b3eadfdaf8c 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -50,8 +50,9 @@ *3) functions called by core.c *4) wq & timer callback functions *5) frame process functions - *6) sysfs functions - *7) ... + *6) IOT functions + *7) sysfs functions + *8) ... */ /********************************************************* @@ -59,7 +60,7 @@ * mac80211 init functions * *********************************************************/ -static struct ieee80211_channel rtl_channeltable[] = { +static struct ieee80211_channel rtl_channeltable_2g[] = { {.center_freq = 2412, .hw_value = 1,}, {.center_freq = 2417, .hw_value = 2,}, {.center_freq = 2422, .hw_value = 3,}, @@ -76,7 +77,34 @@ static struct ieee80211_channel rtl_channeltable[] = { {.center_freq = 2484, .hw_value = 14,}, }; -static struct ieee80211_rate rtl_ratetable[] = { +static struct ieee80211_channel rtl_channeltable_5g[] = { + {.center_freq = 5180, .hw_value = 36,}, + {.center_freq = 5200, .hw_value = 40,}, + {.center_freq = 5220, .hw_value = 44,}, + {.center_freq = 5240, .hw_value = 48,}, + {.center_freq = 5260, .hw_value = 52,}, + {.center_freq = 5280, .hw_value = 56,}, + {.center_freq = 5300, .hw_value = 60,}, + {.center_freq = 5320, .hw_value = 64,}, + {.center_freq = 5500, .hw_value = 100,}, + {.center_freq = 5520, .hw_value = 104,}, + {.center_freq = 5540, .hw_value = 108,}, + {.center_freq = 5560, .hw_value = 112,}, + {.center_freq = 5580, .hw_value = 116,}, + {.center_freq = 5600, .hw_value = 120,}, + {.center_freq = 5620, .hw_value = 124,}, + {.center_freq = 5640, .hw_value = 128,}, + {.center_freq = 5660, .hw_value = 132,}, + {.center_freq = 5680, .hw_value = 136,}, + {.center_freq = 5700, .hw_value = 140,}, + {.center_freq = 5745, .hw_value = 149,}, + {.center_freq = 5765, .hw_value = 153,}, + {.center_freq = 5785, .hw_value = 157,}, + {.center_freq = 5805, .hw_value = 161,}, + {.center_freq = 5825, .hw_value = 165,}, +}; + +static struct ieee80211_rate rtl_ratetable_2g[] = { {.bitrate = 10, .hw_value = 0x00,}, {.bitrate = 20, .hw_value = 0x01,}, {.bitrate = 55, .hw_value = 0x02,}, @@ -91,18 +119,57 @@ static struct ieee80211_rate rtl_ratetable[] = { {.bitrate = 540, .hw_value = 0x0b,}, }; +static struct ieee80211_rate rtl_ratetable_5g[] = { + {.bitrate = 60, .hw_value = 0x04,}, + {.bitrate = 90, .hw_value = 0x05,}, + {.bitrate = 120, .hw_value = 0x06,}, + {.bitrate = 180, .hw_value = 0x07,}, + {.bitrate = 240, .hw_value = 0x08,}, + {.bitrate = 360, .hw_value = 0x09,}, + {.bitrate = 480, .hw_value = 0x0a,}, + {.bitrate = 540, .hw_value = 0x0b,}, +}; + static const struct ieee80211_supported_band rtl_band_2ghz = { .band = IEEE80211_BAND_2GHZ, - .channels = rtl_channeltable, - .n_channels = ARRAY_SIZE(rtl_channeltable), + .channels = rtl_channeltable_2g, + .n_channels = ARRAY_SIZE(rtl_channeltable_2g), - .bitrates = rtl_ratetable, - .n_bitrates = ARRAY_SIZE(rtl_ratetable), + .bitrates = rtl_ratetable_2g, + .n_bitrates = ARRAY_SIZE(rtl_ratetable_2g), .ht_cap = {0}, }; +static struct ieee80211_supported_band rtl_band_5ghz = { + .band = IEEE80211_BAND_5GHZ, + + .channels = rtl_channeltable_5g, + .n_channels = ARRAY_SIZE(rtl_channeltable_5g), + + .bitrates = rtl_ratetable_5g, + .n_bitrates = ARRAY_SIZE(rtl_ratetable_5g), + + .ht_cap = {0}, +}; + +static const u8 tid_to_ac[] = { + 2, /* IEEE80211_AC_BE */ + 3, /* IEEE80211_AC_BK */ + 3, /* IEEE80211_AC_BK */ + 2, /* IEEE80211_AC_BE */ + 1, /* IEEE80211_AC_VI */ + 1, /* IEEE80211_AC_VI */ + 0, /* IEEE80211_AC_VO */ + 0, /* IEEE80211_AC_VO */ +}; + +u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid) +{ + return tid_to_ac[tid]; +} + static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, struct ieee80211_sta_ht_cap *ht_cap) { @@ -115,6 +182,9 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU; + if (rtlpriv->rtlhal.disable_amsdu_8k) + ht_cap->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; + /* *Maximum length of AMPDU that the STA can receive. *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) @@ -159,37 +229,99 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, static void _rtl_init_mac80211(struct ieee80211_hw *hw) { + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct ieee80211_supported_band *sband; - /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); - /* - * <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] - * to default value(1T1R) - */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, - sizeof(struct ieee80211_supported_band)); + if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && rtlhal->bandset == + BAND_ON_BOTH) { + /* 1: 2.4 G bands */ + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); + + /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] + * to default value(1T1R) */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, + sizeof(struct ieee80211_supported_band)); - /* <3> init ht cap base on ant_num */ - _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); - /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + /* 2: 5 G bands */ + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); + + /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] + * to default value(1T1R) */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, + sizeof(struct ieee80211_supported_band)); + + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; + } else { + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); + + /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] + * to default value(1T1R) */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), + &rtl_band_2ghz, + sizeof(struct ieee80211_supported_band)); + + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + } else if (rtlhal->current_bandtype == BAND_ON_5G) { + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); + + /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] + * to default value(1T1R) */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), + &rtl_band_5ghz, + sizeof(struct ieee80211_supported_band)); + + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + ("Err BAND %d\n", + rtlhal->current_bandtype)); + } + } /* <5> set hw caps */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_AMPDU_AGGREGATION | /*PS*/ - /*IEEE80211_HW_SUPPORTS_PS | */ - /*IEEE80211_HW_PS_NULLFUNC_STACK | */ - /*IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */ + IEEE80211_HW_BEACON_FILTER | + IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; + /* swlps or hwlps has been set in diff chip in init_sw_vars */ + if (rtlpriv->psc.swctrl_lps) + hw->flags |= IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK | + /* IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */ + 0; + hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->rts_threshold = 2347; @@ -199,9 +331,10 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) /* TODO: Correct this value for our hw */ /* TODO: define these hard code value */ hw->channel_change_time = 100; - hw->max_listen_interval = 5; + hw->max_listen_interval = 10; hw->max_rate_tries = 4; /* hw->max_rates = 1; */ + hw->sta_data_size = sizeof(struct rtl_sta_info); /* <6> mac address */ if (is_valid_ether_addr(rtlefuse->dev_addr)) { @@ -230,6 +363,10 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) (void *)rtl_watchdog_wq_callback); INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, (void *)rtl_ips_nic_off_wq_callback); + INIT_DELAYED_WORK(&rtlpriv->works.ps_work, + (void *)rtl_swlps_wq_callback); + INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, + (void *)rtl_swlps_rfon_wq_callback); } @@ -241,6 +378,8 @@ void rtl_deinit_deferred_work(struct ieee80211_hw *hw) cancel_delayed_work(&rtlpriv->works.watchdog_wq); cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); + cancel_delayed_work(&rtlpriv->works.ps_work); + cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); } void rtl_init_rfkill(struct ieee80211_hw *hw) @@ -310,6 +449,8 @@ int rtl_init_core(struct ieee80211_hw *hw) spin_lock_init(&rtlpriv->locks.rf_ps_lock); spin_lock_init(&rtlpriv->locks.rf_lock); spin_lock_init(&rtlpriv->locks.lps_lock); + spin_lock_init(&rtlpriv->locks.waitq_lock); + spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); rtlmac->link_state = MAC80211_NOLINK; @@ -329,12 +470,6 @@ void rtl_init_rx_config(struct ieee80211_hw *hw) struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MGT_FILTER, - (u8 *) (&mac->rx_mgt_filter)); - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CTRL_FILTER, - (u8 *) (&mac->rx_ctrl_filter)); - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_DATA_FILTER, - (u8 *) (&mac->rx_data_filter)); } /********************************************************* @@ -361,28 +496,40 @@ static void _rtl_qurey_shortpreamble_mode(struct ieee80211_hw *hw, } static void _rtl_query_shortgi(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, struct rtl_tcb_desc *tcb_desc, struct ieee80211_tx_info *info) { struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); u8 rate_flag = info->control.rates[0].flags; - + u8 sgi_40 = 0, sgi_20 = 0, bw_40 = 0; tcb_desc->use_shortgi = false; - if (!mac->ht_enable) + if (sta == NULL) + return; + + sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; + sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; + + if (!(sta->ht_cap.ht_supported)) return; - if (!mac->sgi_40 && !mac->sgi_20) + if (!sgi_40 && !sgi_20) return; - if ((mac->bw_40 == true) && mac->sgi_40) + if (mac->opmode == NL80211_IFTYPE_STATION) + bw_40 = mac->bw_40; + else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; + + if ((bw_40 == true) && sgi_40) tcb_desc->use_shortgi = true; - else if ((mac->bw_40 == false) && mac->sgi_20) + else if ((bw_40 == false) && sgi_20) tcb_desc->use_shortgi = true; if (!(rate_flag & IEEE80211_TX_RC_SHORT_GI)) tcb_desc->use_shortgi = false; - } static void _rtl_query_protection_mode(struct ieee80211_hw *hw, @@ -410,19 +557,25 @@ static void _rtl_query_protection_mode(struct ieee80211_hw *hw, tcb_desc->rts_enable = true; tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; } - } static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u8 ratr_index = 7; + if (sta) { + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + ratr_index = sta_entry->ratr_index; + } if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { - if (mac->opmode == NL80211_IFTYPE_STATION) + if (mac->opmode == NL80211_IFTYPE_STATION) { tcb_desc->ratr_index = 0; - else if (mac->opmode == NL80211_IFTYPE_ADHOC) { + } else if (mac->opmode == NL80211_IFTYPE_ADHOC) { if (tcb_desc->multicast || tcb_desc->broadcast) { tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; @@ -430,36 +583,61 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, } else { /* TODO */ } + tcb_desc->ratr_index = ratr_index; + } else if (mac->opmode == NL80211_IFTYPE_AP) { + tcb_desc->ratr_index = ratr_index; } } if (rtlpriv->dm.useramask) { - /* TODO adhoc and station handled differently in the future */ - tcb_desc->mac_id = 0; - - if ((mac->mode == WIRELESS_MODE_N_24G) || - (mac->mode == WIRELESS_MODE_N_5G)) { - tcb_desc->ratr_index = RATR_INX_WIRELESS_NGB; - } else if (mac->mode & WIRELESS_MODE_G) { - tcb_desc->ratr_index = RATR_INX_WIRELESS_GB; - } else if (mac->mode & WIRELESS_MODE_B) { - tcb_desc->ratr_index = RATR_INX_WIRELESS_B; + /* TODO we will differentiate adhoc and station futrue */ + if (mac->opmode == NL80211_IFTYPE_STATION) { + tcb_desc->mac_id = 0; + + if (mac->mode == WIRELESS_MODE_N_24G) + tcb_desc->ratr_index = RATR_INX_WIRELESS_NGB; + else if (mac->mode == WIRELESS_MODE_N_5G) + tcb_desc->ratr_index = RATR_INX_WIRELESS_NG; + else if (mac->mode & WIRELESS_MODE_G) + tcb_desc->ratr_index = RATR_INX_WIRELESS_GB; + else if (mac->mode & WIRELESS_MODE_B) + tcb_desc->ratr_index = RATR_INX_WIRELESS_B; + else if (mac->mode & WIRELESS_MODE_A) + tcb_desc->ratr_index = RATR_INX_WIRELESS_G; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (NULL != sta) { + if (sta->aid > 0) + tcb_desc->mac_id = sta->aid + 1; + else + tcb_desc->mac_id = 1; + } else { + tcb_desc->mac_id = 0; + } } } } static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); tcb_desc->packet_bw = false; - - if (!mac->bw_40 || !mac->ht_enable) + if (!sta) return; - + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (!(sta->ht_cap.ht_supported) || + !(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) + return; + } else if (mac->opmode == NL80211_IFTYPE_STATION) { + if (!mac->bw_40 || !(sta->ht_cap.ht_supported)) + return; + } if (tcb_desc->multicast || tcb_desc->broadcast) return; @@ -486,22 +664,21 @@ static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw) void rtl_get_tcb_desc(struct ieee80211_hw *hw, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); struct ieee80211_rate *txrate; __le16 fc = hdr->frame_control; - memset(tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + txrate = ieee80211_get_tx_rate(hw, info); + tcb_desc->hw_rate = txrate->hw_value; if (ieee80211_is_data(fc)) { - txrate = ieee80211_get_tx_rate(hw, info); - tcb_desc->hw_rate = txrate->hw_value; - /* - *we set data rate RTL_RC_CCK_RATE1M + *we set data rate INX 0 *in rtl_rc.c if skb is special data or *mgt which need low data rate. */ @@ -510,12 +687,11 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, *So tcb_desc->hw_rate is just used for *special data and mgt frames */ - if (tcb_desc->hw_rate < rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]) { + if (info->control.rates[0].idx == 0 && + ieee80211_is_nullfunc(fc)) { tcb_desc->use_driver_rate = true; - tcb_desc->ratr_index = 7; + tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; - tcb_desc->hw_rate = - rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; tcb_desc->disable_ratefallback = 1; } else { /* @@ -525,7 +701,7 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, *and N rate will all be controled by FW *when tcb_desc->use_driver_rate = false */ - if (rtlmac->ht_enable) { + if (sta && (sta->ht_cap.ht_supported)) { tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw); } else { if (rtlmac->mode == WIRELESS_MODE_B) { @@ -543,43 +719,25 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr))) tcb_desc->broadcast = 1; - _rtl_txrate_selectmode(hw, tcb_desc); - _rtl_query_bandwidth_mode(hw, tcb_desc); + _rtl_txrate_selectmode(hw, sta, tcb_desc); + _rtl_query_bandwidth_mode(hw, sta, tcb_desc); _rtl_qurey_shortpreamble_mode(hw, tcb_desc, info); - _rtl_query_shortgi(hw, tcb_desc, info); + _rtl_query_shortgi(hw, sta, tcb_desc, info); _rtl_query_protection_mode(hw, tcb_desc, info); } else { tcb_desc->use_driver_rate = true; - tcb_desc->ratr_index = 7; + tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; tcb_desc->disable_ratefallback = 1; tcb_desc->mac_id = 0; - - tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; + tcb_desc->packet_bw = false; } } EXPORT_SYMBOL(rtl_get_tcb_desc); -bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - __le16 fc = hdr->frame_control; - - if (ieee80211_is_auth(fc)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); - rtl_ips_nic_on(hw); - - mac->link_state = MAC80211_LINKING; - } - - return true; -} - bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) { struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); struct rtl_priv *rtlpriv = rtl_priv(hw); __le16 fc = hdr->frame_control; u8 *act = (u8 *) (((u8 *) skb->data + MAC80211_3ADDR_LEN)); @@ -624,9 +782,8 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - __le16 fc = hdr->frame_control; + __le16 fc = rtl_get_fc(skb); u16 ether_type; u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb); const struct iphdr *ip; @@ -634,12 +791,11 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) if (!ieee80211_is_data(fc)) return false; - if (ieee80211_is_nullfunc(fc)) - return true; ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len + SNAP_SIZE + PROTOC_TYPE_SIZE); ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE); + ether_type = ntohs(ether_type); if (ETH_P_IP == ether_type) { if (IPPROTO_UDP == ip->protocol) { @@ -696,61 +852,92 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) * functions called by core.c * *********************************************************/ -int rtl_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra, u16 tid, u16 *ssn) +int rtl_tx_agg_start(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tid, u16 *ssn) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_tid_data *tid_data; struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, - ("on ra = %pM tid = %d\n", ra, tid)); + if (sta == NULL) + return -EINVAL; if (unlikely(tid >= MAX_TID_COUNT)) return -EINVAL; - if (mac->tids[tid].agg.agg_state != RTL_AGG_OFF) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("Start AGG when state is not RTL_AGG_OFF !\n")); + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + if (!sta_entry) return -ENXIO; - } - - tid_data = &mac->tids[tid]; - *ssn = SEQ_TO_SN(tid_data->seq_number); + tid_data = &sta_entry->tids[tid]; RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, - ("HW queue is empty tid:%d\n", tid)); - tid_data->agg.agg_state = RTL_AGG_ON; + ("on ra = %pM tid = %d seq:%d\n", sta->addr, tid, + tid_data->seq_number)); - ieee80211_start_tx_ba_cb_irqsafe(mac->vif, ra, tid); + *ssn = tid_data->seq_number; + tid_data->agg.agg_state = RTL_AGG_START; + + ieee80211_start_tx_ba_cb_irqsafe(mac->vif, sta->addr, tid); return 0; } -int rtl_tx_agg_stop(struct ieee80211_hw *hw, const u8 * ra, u16 tid) +int rtl_tx_agg_stop(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tid) { - int ssn = -1; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_tid_data *tid_data; + struct rtl_sta_info *sta_entry = NULL; + + if (sta == NULL) + return -EINVAL; - if (!ra) { + if (!sta->addr) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("ra = NULL\n")); return -EINVAL; } + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, + ("on ra = %pM tid = %d\n", sta->addr, tid)); + if (unlikely(tid >= MAX_TID_COUNT)) return -EINVAL; - if (mac->tids[tid].agg.agg_state != RTL_AGG_ON) - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("Stopping AGG while state not ON or starting\n")); + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + tid_data = &sta_entry->tids[tid]; + sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP; - tid_data = &mac->tids[tid]; - ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; + ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, sta->addr, tid); - mac->tids[tid].agg.agg_state = RTL_AGG_OFF; + return 0; +} + +int rtl_tx_agg_oper(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_tid_data *tid_data; + struct rtl_sta_info *sta_entry = NULL; - ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, ra, tid); + if (sta == NULL) + return -EINVAL; + + if (!sta->addr) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("ra = NULL\n")); + return -EINVAL; + } + + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, + ("on ra = %pM tid = %d\n", sta->addr, tid)); + + if (unlikely(tid >= MAX_TID_COUNT)) + return -EINVAL; + + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + tid_data = &sta_entry->tids[tid]; + sta_entry->tids[tid].agg.agg_state = RTL_AGG_OPERATIONAL; return 0; } @@ -769,18 +956,16 @@ void rtl_watchdog_wq_callback(void *data) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - bool busytraffic = false; bool higher_busytraffic = false; bool higher_busyrxtraffic = false; - bool higher_busytxtraffic = false; - - u8 idx = 0; + u8 idx, tid; u32 rx_cnt_inp4eriod = 0; u32 tx_cnt_inp4eriod = 0; u32 aver_rx_cnt_inperiod = 0; u32 aver_tx_cnt_inperiod = 0; - + u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; + u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; bool enter_ps = false; if (is_hal_stop(rtlhal)) @@ -794,9 +979,6 @@ void rtl_watchdog_wq_callback(void *data) mac->cnt_after_linked = 0; } - /* <2> DM */ - rtlpriv->cfg->ops->dm_watchdog(hw); - /* *<3> to check if traffic busy, if * busytraffic we don't change channel @@ -835,8 +1017,27 @@ void rtl_watchdog_wq_callback(void *data) /* Extremely high Rx data. */ if (aver_rx_cnt_inperiod > 5000) higher_busyrxtraffic = true; + } + + /* check every tid's tx traffic */ + for (tid = 0; tid <= 7; tid++) { + for (idx = 0; idx <= 2; idx++) + rtlpriv->link_info.tidtx_in4period[tid][idx] = + rtlpriv->link_info.tidtx_in4period[tid] + [idx + 1]; + rtlpriv->link_info.tidtx_in4period[tid][3] = + rtlpriv->link_info.tidtx_inperiod[tid]; + + for (idx = 0; idx <= 3; idx++) + tidtx_inp4eriod[tid] += + rtlpriv->link_info.tidtx_in4period[tid][idx]; + aver_tidtx_inperiod[tid] = tidtx_inp4eriod[tid] / 4; + if (aver_tidtx_inperiod[tid] > 5000) + rtlpriv->link_info.higher_busytxtraffic[tid] = + true; else - higher_busytxtraffic = false; + rtlpriv->link_info.higher_busytxtraffic[tid] = + false; } if (((rtlpriv->link_info.num_rx_inperiod + @@ -855,11 +1056,15 @@ void rtl_watchdog_wq_callback(void *data) rtlpriv->link_info.num_rx_inperiod = 0; rtlpriv->link_info.num_tx_inperiod = 0; + for (tid = 0; tid <= 7; tid++) + rtlpriv->link_info.tidtx_inperiod[tid] = 0; rtlpriv->link_info.busytraffic = busytraffic; rtlpriv->link_info.higher_busytraffic = higher_busytraffic; rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; + /* <3> DM */ + rtlpriv->cfg->ops->dm_watchdog(hw); } void rtl_watch_dog_timer_callback(unsigned long data) @@ -874,6 +1079,274 @@ void rtl_watch_dog_timer_callback(unsigned long data) jiffies + MSECS(RTL_WATCH_DOG_TIME)); } +/********************************************************* + * + * frame process functions + * + *********************************************************/ +u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie) +{ + struct ieee80211_mgmt *mgmt = (void *)data; + u8 *pos, *end; + + pos = (u8 *)mgmt->u.beacon.variable; + end = data + len; + while (pos < end) { + if (pos + 2 + pos[1] > end) + return NULL; + + if (pos[0] == ie) + return pos; + + pos += 2 + pos[1]; + } + return NULL; +} + +/* when we use 2 rx ants we send IEEE80211_SMPS_OFF */ +/* when we use 1 rx ant we send IEEE80211_SMPS_STATIC */ +struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw, + enum ieee80211_smps_mode smps, u8 *da, u8 *bssid) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct sk_buff *skb; + struct ieee80211_mgmt *action_frame; + + /* 27 = header + category + action + smps mode */ + skb = dev_alloc_skb(27 + hw->extra_tx_headroom); + if (!skb) + return NULL; + + skb_reserve(skb, hw->extra_tx_headroom); + action_frame = (void *)skb_put(skb, 27); + memset(action_frame, 0, 27); + memcpy(action_frame->da, da, ETH_ALEN); + memcpy(action_frame->sa, rtlefuse->dev_addr, ETH_ALEN); + memcpy(action_frame->bssid, bssid, ETH_ALEN); + action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); + action_frame->u.action.category = WLAN_CATEGORY_HT; + action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS; + switch (smps) { + case IEEE80211_SMPS_AUTOMATIC:/* 0 */ + case IEEE80211_SMPS_NUM_MODES:/* 4 */ + WARN_ON(1); + case IEEE80211_SMPS_OFF:/* 1 */ /*MIMO_PS_NOLIMIT*/ + action_frame->u.action.u.ht_smps.smps_control = + WLAN_HT_SMPS_CONTROL_DISABLED;/* 0 */ + break; + case IEEE80211_SMPS_STATIC:/* 2 */ /*MIMO_PS_STATIC*/ + action_frame->u.action.u.ht_smps.smps_control = + WLAN_HT_SMPS_CONTROL_STATIC;/* 1 */ + break; + case IEEE80211_SMPS_DYNAMIC:/* 3 */ /*MIMO_PS_DYNAMIC*/ + action_frame->u.action.u.ht_smps.smps_control = + WLAN_HT_SMPS_CONTROL_DYNAMIC;/* 3 */ + break; + } + + return skb; +} + +int rtl_send_smps_action(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 *da, u8 *bssid, + enum ieee80211_smps_mode smps) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct sk_buff *skb = rtl_make_smps_action(hw, smps, da, bssid); + struct rtl_tcb_desc tcb_desc; + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + + if (rtlpriv->mac80211.act_scanning) + goto err_free; + + if (!sta) + goto err_free; + + if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) + goto err_free; + + if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) + goto err_free; + + /* this is a type = mgmt * stype = action frame */ + if (skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct rtl_sta_info *sta_entry = + (struct rtl_sta_info *) sta->drv_priv; + sta_entry->mimo_ps = smps; + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); + + info->control.rates[0].idx = 0; + info->control.sta = sta; + info->band = hw->conf.channel->band; +#if 0 + rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); +#else + rtlpriv->intf_ops->adapter_tx(hw, skb); +#endif + } + return 1; + +err_free: + return 0; +} + +/********************************************************* + * + * IOT functions + * + *********************************************************/ +static bool rtl_chk_vendor_ouisub(struct ieee80211_hw *hw, + struct octet_string vendor_ie) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool matched = false; + static u8 athcap_1[] = { 0x00, 0x03, 0x7F }; + static u8 athcap_2[] = { 0x00, 0x13, 0x74 }; + static u8 broadcap_1[] = { 0x00, 0x10, 0x18 }; + static u8 broadcap_2[] = { 0x00, 0x0a, 0xf7 }; + static u8 broadcap_3[] = { 0x00, 0x05, 0xb5 }; + static u8 racap[] = { 0x00, 0x0c, 0x43 }; + static u8 ciscocap[] = { 0x00, 0x40, 0x96 }; + static u8 marvcap[] = { 0x00, 0x50, 0x43 }; + + if (memcmp(vendor_ie.octet, athcap_1, 3) == 0 || + memcmp(vendor_ie.octet, athcap_2, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_ATH; + matched = true; + } else if (memcmp(vendor_ie.octet, broadcap_1, 3) == 0 || + memcmp(vendor_ie.octet, broadcap_2, 3) == 0 || + memcmp(vendor_ie.octet, broadcap_3, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_BROAD; + matched = true; + } else if (memcmp(vendor_ie.octet, racap, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_RAL; + matched = true; + } else if (memcmp(vendor_ie.octet, ciscocap, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_CISCO; + matched = true; + } else if (memcmp(vendor_ie.octet, marvcap, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_MARV; + matched = true; + } + + return matched; +} + +bool rtl_find_221_ie(struct ieee80211_hw *hw, u8 *data, + unsigned int len) +{ + struct ieee80211_mgmt *mgmt = (void *)data; + struct octet_string vendor_ie; + u8 *pos, *end; + + pos = (u8 *)mgmt->u.beacon.variable; + end = data + len; + while (pos < end) { + if (pos[0] == 221) { + vendor_ie.length = pos[1]; + vendor_ie.octet = &pos[2]; + if (rtl_chk_vendor_ouisub(hw, vendor_ie)) + return true; + } + + if (pos + 2 + pos[1] > end) + return false; + + pos += 2 + pos[1]; + } + return false; +} + +void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct ieee80211_hdr *hdr = (void *)data; + u32 vendor = PEER_UNKNOWN; + + static u8 ap3_1[3] = { 0x00, 0x14, 0xbf }; + static u8 ap3_2[3] = { 0x00, 0x1a, 0x70 }; + static u8 ap3_3[3] = { 0x00, 0x1d, 0x7e }; + static u8 ap4_1[3] = { 0x00, 0x90, 0xcc }; + static u8 ap4_2[3] = { 0x00, 0x0e, 0x2e }; + static u8 ap4_3[3] = { 0x00, 0x18, 0x02 }; + static u8 ap4_4[3] = { 0x00, 0x17, 0x3f }; + static u8 ap4_5[3] = { 0x00, 0x1c, 0xdf }; + static u8 ap5_1[3] = { 0x00, 0x1c, 0xf0 }; + static u8 ap5_2[3] = { 0x00, 0x21, 0x91 }; + static u8 ap5_3[3] = { 0x00, 0x24, 0x01 }; + static u8 ap5_4[3] = { 0x00, 0x15, 0xe9 }; + static u8 ap5_5[3] = { 0x00, 0x17, 0x9A }; + static u8 ap5_6[3] = { 0x00, 0x18, 0xE7 }; + static u8 ap6_1[3] = { 0x00, 0x17, 0x94 }; + static u8 ap7_1[3] = { 0x00, 0x14, 0xa4 }; + + if (mac->opmode != NL80211_IFTYPE_STATION) + return; + + if (mac->link_state == MAC80211_NOLINK) { + mac->vendor = PEER_UNKNOWN; + return; + } + + if (mac->cnt_after_linked > 2) + return; + + /* check if this really is a beacon */ + if (!ieee80211_is_beacon(hdr->frame_control)) + return; + + /* min. beacon length + FCS_LEN */ + if (len <= 40 + FCS_LEN) + return; + + /* and only beacons from the associated BSSID, please */ + if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) + return; + + if (rtl_find_221_ie(hw, data, len)) + vendor = mac->vendor; + + if ((memcmp(mac->bssid, ap5_1, 3) == 0) || + (memcmp(mac->bssid, ap5_2, 3) == 0) || + (memcmp(mac->bssid, ap5_3, 3) == 0) || + (memcmp(mac->bssid, ap5_4, 3) == 0) || + (memcmp(mac->bssid, ap5_5, 3) == 0) || + (memcmp(mac->bssid, ap5_6, 3) == 0) || + vendor == PEER_ATH) { + vendor = PEER_ATH; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>ath find\n")); + } else if ((memcmp(mac->bssid, ap4_4, 3) == 0) || + (memcmp(mac->bssid, ap4_5, 3) == 0) || + (memcmp(mac->bssid, ap4_1, 3) == 0) || + (memcmp(mac->bssid, ap4_2, 3) == 0) || + (memcmp(mac->bssid, ap4_3, 3) == 0) || + vendor == PEER_RAL) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>ral findn\n")); + vendor = PEER_RAL; + } else if (memcmp(mac->bssid, ap6_1, 3) == 0 || + vendor == PEER_CISCO) { + vendor = PEER_CISCO; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>cisco find\n")); + } else if ((memcmp(mac->bssid, ap3_1, 3) == 0) || + (memcmp(mac->bssid, ap3_2, 3) == 0) || + (memcmp(mac->bssid, ap3_3, 3) == 0) || + vendor == PEER_BROAD) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>broad find\n")); + vendor = PEER_BROAD; + } else if (memcmp(mac->bssid, ap7_1, 3) == 0 || + vendor == PEER_MARV) { + vendor = PEER_MARV; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>marv find\n")); + } + + mac->vendor = vendor; +} + /********************************************************* * * sysfs functions @@ -941,12 +1414,13 @@ static int __init rtl_core_module_init(void) if (rtl_rate_control_register()) printk(KERN_ERR "rtlwifi: Unable to register rtl_rc," "use default RC !!\n"); + return 0; } static void __exit rtl_core_module_exit(void) { - /*RC*/ + /*RC*/ rtl_rate_control_unregister(); } diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h index 043045342bc7..a91f3eee59c8 100644 --- a/drivers/net/wireless/rtlwifi/base.h +++ b/drivers/net/wireless/rtlwifi/base.h @@ -24,13 +24,26 @@ * Hsinchu 300, Taiwan. * * Larry Finger + * *****************************************************************************/ #ifndef __RTL_BASE_H__ #define __RTL_BASE_H__ +enum ap_peer { + PEER_UNKNOWN = 0, + PEER_RTL = 1, + PEER_RTL_92SE = 2, + PEER_BROAD = 3, + PEER_RAL = 4, + PEER_ATH = 5, + PEER_CISCO = 6, + PEER_MARV = 7, + PEER_AIRGO = 9, + PEER_MAX = 10, +} ; + #define RTL_DUMMY_OFFSET 0 -#define RTL_RX_DESC_SIZE 24 #define RTL_DUMMY_UNIT 8 #define RTL_TX_DUMMY_SIZE (RTL_DUMMY_OFFSET * RTL_DUMMY_UNIT) #define RTL_TX_DESC_SIZE 32 @@ -53,6 +66,14 @@ #define FRAME_OFFSET_SEQUENCE 22 #define FRAME_OFFSET_ADDRESS4 24 +#define SET_80211_HDR_FRAME_CONTROL(_hdr, _val) \ + WRITEEF2BYTE(_hdr, _val) +#define SET_80211_HDR_TYPE_AND_SUBTYPE(_hdr, _val) \ + WRITEEF1BYTE(_hdr, _val) +#define SET_80211_HDR_PWR_MGNT(_hdr, _val) \ + SET_BITS_TO_LE_2BYTE(_hdr, 12, 1, _val) +#define SET_80211_HDR_TO_DS(_hdr, _val) \ + SET_BITS_TO_LE_2BYTE(_hdr, 8, 1, _val) #define SET_80211_PS_POLL_AID(_hdr, _val) \ (*(u16 *)((u8 *)(_hdr) + 2) = le16_to_cpu(_val)) @@ -64,11 +85,27 @@ #define SET_80211_HDR_DURATION(_hdr, _val) \ (*(u16 *)((u8 *)(_hdr) + FRAME_OFFSET_DURATION) = le16_to_cpu(_val)) #define SET_80211_HDR_ADDRESS1(_hdr, _val) \ - memcpy((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8*)(_val), ETH_ALEN) + CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8 *)(_val)) #define SET_80211_HDR_ADDRESS2(_hdr, _val) \ - memcpy((u8 *)(_hdr) + FRAME_OFFSET_ADDRESS2, (u8 *)(_val), ETH_ALEN) + CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS2, (u8 *)(_val)) #define SET_80211_HDR_ADDRESS3(_hdr, _val) \ - memcpy((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val), ETH_ALEN) + CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val)) +#define SET_80211_HDR_FRAGMENT_SEQUENCE(_hdr, _val) \ + WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_SEQUENCE, _val) + +#define SET_BEACON_PROBE_RSP_TIME_STAMP_LOW(__phdr, __val) \ + WRITEEF4BYTE(((u8 *)(__phdr)) + 24, __val) +#define SET_BEACON_PROBE_RSP_TIME_STAMP_HIGH(__phdr, __val) \ + WRITEEF4BYTE(((u8 *)(__phdr)) + 28, __val) +#define SET_BEACON_PROBE_RSP_BEACON_INTERVAL(__phdr, __val) \ + WRITEEF2BYTE(((u8 *)(__phdr)) + 32, __val) +#define GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) \ + READEF2BYTE(((u8 *)(__phdr)) + 34) +#define SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ + WRITEEF2BYTE(((u8 *)(__phdr)) + 34, __val) +#define MASK_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ + SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, \ + (GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) & (~(__val)))) int rtl_init_core(struct ieee80211_hw *hw); void rtl_deinit_core(struct ieee80211_hw *hw); @@ -80,18 +117,27 @@ void rtl_watch_dog_timer_callback(unsigned long data); void rtl_deinit_deferred_work(struct ieee80211_hw *hw); bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); -bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); void rtl_watch_dog_timer_callback(unsigned long data); -int rtl_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra, +int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u16 tid, u16 *ssn); -int rtl_tx_agg_stop(struct ieee80211_hw *hw, const u8 *ra, u16 tid); +int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + u16 tid); +int rtl_tx_agg_oper(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + u16 tid); void rtl_watchdog_wq_callback(void *data); void rtl_get_tcb_desc(struct ieee80211_hw *hw, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc); +int rtl_send_smps_action(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 *da, u8 *bssid, + enum ieee80211_smps_mode smps); +u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); +void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); +u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid); extern struct attribute_group rtl_attribute_group; #endif diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 59a150ce3064..e2fa78bc1299 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1242,8 +1242,6 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb) u8 own; u8 temp_one = 1; - if (ieee80211_is_mgmt(fc)) - rtl_tx_mgmt_proc(hw, skb); rtl_action_proc(hw, skb, true); queue_index = skb_get_queue_mapping(skb); diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index c8395fb0c050..bdb3c5f5c4b0 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -416,6 +416,14 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) } } +void rtl_swlps_rfon_wq_callback(void *data) +{ +} + +void rtl_swlps_wq_callback(void *data) +{ +} + /*Enter the leisure power save mode.*/ void rtl_lps_enter(struct ieee80211_hw *hw) { diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h index ae56da801a23..36aa24d6041f 100644 --- a/drivers/net/wireless/rtlwifi/ps.h +++ b/drivers/net/wireless/rtlwifi/ps.h @@ -40,4 +40,11 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw); void rtl_ips_nic_off_wq_callback(void *data); void rtl_lps_enter(struct ieee80211_hw *hw); void rtl_lps_leave(struct ieee80211_hw *hw); + +void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len); +void rtl_swlps_wq_callback(void *data); +void rtl_swlps_rfon_wq_callback(void *data); +void rtl_swlps_rf_awake(struct ieee80211_hw *hw); +void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); + #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index aa2b5815600f..356b8513b8a6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -754,7 +754,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, skb, &tcb_desc); + rtl_get_tcb_desc(hw, info, sta, skb, &tcb_desc); CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c)); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 3f0cb81c424f..0df2fec27a08 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -517,7 +517,7 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, u8 *txdesc; seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, skb, &tcb_desc); + rtl_get_tcb_desc(hw, info, sta, skb, &tcb_desc); txdesc = (u8 *)skb_push(skb, RTL_TX_HEADER_SIZE); memset(txdesc, 0, RTL_TX_HEADER_SIZE); SET_TX_DESC_PKT_SIZE(txdesc, pktlen); diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index f5d85735d642..f4ab1b7732c3 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -860,8 +860,6 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, u8 tid = 0; u16 seq_number = 0; - if (ieee80211_is_mgmt(fc)) - rtl_tx_mgmt_proc(hw, skb); rtl_action_proc(hw, skb, true); if (is_multicast_ether_addr(pda_addr)) rtlpriv->stats.txbytesmulticast += skb->len; diff --git a/drivers/net/wireless/rtlwifi/usb.h b/drivers/net/wireless/rtlwifi/usb.h index abadfe918d30..d2a63fb3e1e6 100644 --- a/drivers/net/wireless/rtlwifi/usb.h +++ b/drivers/net/wireless/rtlwifi/usb.h @@ -31,6 +31,8 @@ #include #include +#define RTL_RX_DESC_SIZE 24 + #define RTL_USB_DEVICE(vend, prod, cfg) \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \ .idVendor = (vend), \ diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 9124b30c605d..7c52435a1180 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -1370,10 +1370,11 @@ struct rtl_hal_ops { u32 add_msr, u32 rm_msr); void (*get_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); void (*set_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); -#if 0 /* temporary */ +#if 1 /* temporary */ void (*update_rate_tbl) (struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 rssi_level); -#else +#endif +#if 1 /* temporary */ void (*update_rate_table) (struct ieee80211_hw *hw); #endif void (*update_rate_mask) (struct ieee80211_hw *hw, u8 rssi_level); -- cgit v1.2.3-58-ga151 From 46a6272c20d4f639093ad2ad8db1eba622187bee Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 13:23:05 -0500 Subject: rtlwifi: Change cam routines for addition of rtl8192se and rtl8192de Change cam routines for addition of RTL8192SE and RTL8192DE code Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/cam.c | 106 +++++++++++++++++++++++++++++-------- drivers/net/wireless/rtlwifi/cam.h | 5 +- 2 files changed, 89 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c index 52c9c1367cac..7295af0536b7 100644 --- a/drivers/net/wireless/rtlwifi/cam.c +++ b/drivers/net/wireless/rtlwifi/cam.c @@ -23,6 +23,8 @@ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, * Hsinchu 300, Taiwan. * + * Larry Finger + * *****************************************************************************/ #include "wifi.h" @@ -49,7 +51,7 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, u32 target_content = 0; u8 entry_i; - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, ("key_cont_128:\n %x:%x:%x:%x:%x:%x\n", key_cont_128[0], key_cont_128[1], key_cont_128[2], key_cont_128[3], @@ -68,15 +70,13 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], target_command); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("rtl_cam_program_entry(): " - "WRITE %x: %x\n", + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("WRITE %x: %x\n", rtlpriv->cfg->maps[WCAMI], target_content)); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, ("The Key ID is %d\n", entry_no)); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("rtl_cam_program_entry(): " - "WRITE %x: %x\n", + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("WRITE %x: %x\n", rtlpriv->cfg->maps[RWCAM], target_command)); } else if (entry_i == 1) { @@ -91,12 +91,10 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], target_command); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("rtl_cam_program_entry(): WRITE A4: %x\n", - target_content)); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("rtl_cam_program_entry(): WRITE A0: %x\n", - target_command)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("WRITE A4: %x\n", target_content)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("WRITE A0: %x\n", target_command)); } else { @@ -113,16 +111,14 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, target_command); udelay(100); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("rtl_cam_program_entry(): WRITE A4: %x\n", - target_content)); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("rtl_cam_program_entry(): WRITE A0: %x\n", - target_command)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("WRITE A4: %x\n", target_content)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("WRITE A0: %x\n", target_command)); } } - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, ("after set key, usconfig:%x\n", us_config)); } @@ -289,3 +285,71 @@ void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index) } EXPORT_SYMBOL(rtl_cam_empty_entry); + +u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> 4; + u8 entry_idx = 0; + u8 i, *addr; + + if (NULL == sta_addr) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, + ("sta_addr is NULL.\n")); + return TOTAL_CAM_ENTRY; + } + /* Does STA already exist? */ + for (i = 4; i < TOTAL_CAM_ENTRY; i++) { + addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; + if (memcmp(addr, sta_addr, ETH_ALEN) == 0) + return i; + } + /* Get a free CAM entry. */ + for (entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY; entry_idx++) { + if ((bitmap & BIT(0)) == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, + ("-----hwsec_cam_bitmap: 0x%x entry_idx=%d\n", + rtlpriv->sec.hwsec_cam_bitmap, entry_idx)); + rtlpriv->sec.hwsec_cam_bitmap |= BIT(0) << entry_idx; + memcpy(rtlpriv->sec.hwsec_cam_sta_addr[entry_idx], + sta_addr, ETH_ALEN); + return entry_idx; + } + bitmap = bitmap >> 1; + } + return TOTAL_CAM_ENTRY; +} +EXPORT_SYMBOL(rtl_cam_get_free_entry); + +void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 bitmap; + u8 i, *addr; + + if (NULL == sta_addr) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, + ("sta_addr is NULL.\n")); + } + + if ((sta_addr[0]|sta_addr[1]|sta_addr[2]|sta_addr[3]|\ + sta_addr[4]|sta_addr[5]) == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, + ("sta_addr is 00:00:00:00:00:00.\n")); + return; + } + /* Does STA already exist? */ + for (i = 4; i < TOTAL_CAM_ENTRY; i++) { + addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; + bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> i; + if (((bitmap & BIT(0)) == BIT(0)) && + (memcmp(addr, sta_addr, ETH_ALEN) == 0)) { + /* Remove from HW Security CAM */ + memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN); + rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i); + printk(KERN_INFO "&&&&&&&&&del entry %d\n", i); + } + } + return; +} +EXPORT_SYMBOL(rtl_cam_del_entry); diff --git a/drivers/net/wireless/rtlwifi/cam.h b/drivers/net/wireless/rtlwifi/cam.h index dd82f057d53d..c62da4eefc75 100644 --- a/drivers/net/wireless/rtlwifi/cam.h +++ b/drivers/net/wireless/rtlwifi/cam.h @@ -23,12 +23,13 @@ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, * Hsinchu 300, Taiwan. * + * Larry Finger + * *****************************************************************************/ #ifndef __RTL_CAM_H_ #define __RTL_CAM_H_ -#define TOTAL_CAM_ENTRY 32 #define CAM_CONTENT_COUNT 8 #define CFG_DEFAULT_KEY BIT(5) @@ -49,5 +50,7 @@ int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index); void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index); void rtl_cam_reset_sec_info(struct ieee80211_hw *hw); +u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr); +void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr); #endif -- cgit v1.2.3-58-ga151 From 0baa0fd76f3f5a134461d6cf30294f6bb1bb824c Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 13:23:10 -0500 Subject: rtlwifi: Convert core routines for addition of rtl8192se and rtl8192de Convert core routines for addition of RTL8192SE and RTL8192DE code. Additional files are changed to allow compilation. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/base.c | 6 - drivers/net/wireless/rtlwifi/core.c | 408 +++++++++++++++++---------- drivers/net/wireless/rtlwifi/core.h | 1 + drivers/net/wireless/rtlwifi/ps.c | 4 + drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 2 +- drivers/net/wireless/rtlwifi/usb.c | 3 +- drivers/net/wireless/rtlwifi/wifi.h | 4 - 7 files changed, 268 insertions(+), 160 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 7b3eadfdaf8c..2df99463a681 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -1182,14 +1182,8 @@ int rtl_send_smps_action(struct ieee80211_hw *hw, info->control.rates[0].idx = 0; info->control.sta = sta; info->band = hw->conf.channel->band; -#if 0 rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); -#else - rtlpriv->intf_ops->adapter_tx(hw, skb); -#endif } - return 1; - err_free: return 0; } diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 8fed3c687619..fc89cd8c8320 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -24,6 +24,7 @@ * Hsinchu 300, Taiwan. * * Larry Finger + * *****************************************************************************/ #include "wifi.h" @@ -70,6 +71,7 @@ static void rtl_op_stop(struct ieee80211_hw *hw) mac->link_state = MAC80211_NOLINK; memset(mac->bssid, 0, 6); + mac->vendor = PEER_UNKNOWN; /*reset sec info */ rtl_cam_reset_sec_info(hw); @@ -85,6 +87,8 @@ static void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_tcb_desc tcb_desc; + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) goto err_free; @@ -92,8 +96,8 @@ static void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) goto err_free; - - rtlpriv->intf_ops->adapter_tx(hw, skb); + if (!rtlpriv->intf_ops->waitq_insert(hw, skb)) + rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); return; @@ -134,10 +138,26 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, mac->link_state = MAC80211_LINKED; rtlpriv->cfg->ops->set_bcn_reg(hw); + if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) + mac->basic_rates = 0xfff; + else + mac->basic_rates = 0xff0; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, + (u8 *) (&mac->basic_rates)); + break; case NL80211_IFTYPE_AP: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("NL80211_IFTYPE_AP\n")); + + mac->link_state = MAC80211_LINKED; + rtlpriv->cfg->ops->set_bcn_reg(hw); + if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) + mac->basic_rates = 0xfff; + else + mac->basic_rates = 0xff0; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, + (u8 *) (&mac->basic_rates)); break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, @@ -184,13 +204,12 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, mac->vif = NULL; mac->link_state = MAC80211_NOLINK; memset(mac->bssid, 0, 6); + mac->vendor = PEER_UNKNOWN; mac->opmode = NL80211_IFTYPE_UNSPECIFIED; rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); - mutex_unlock(&rtlpriv->locks.conf_mutex); } - static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -222,10 +241,25 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) /*For LPS */ if (changed & IEEE80211_CONF_CHANGE_PS) { - if (conf->flags & IEEE80211_CONF_PS) - rtl_lps_enter(hw); - else - rtl_lps_leave(hw); + cancel_delayed_work(&rtlpriv->works.ps_work); + cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); + if (conf->flags & IEEE80211_CONF_PS) { + rtlpriv->psc.sw_ps_enabled = true; + /* sleep here is must, or we may recv the beacon and + * cause mac80211 into wrong ps state, this will cause + * power save nullfunc send fail, and further cause + * pkt loss, So sleep must quickly but not immediatly + * because that will cause nullfunc send by mac80211 + * fail, and cause pkt loss, we have tested that 5mA + * is worked very well */ + if (!rtlpriv->psc.multi_buffered) + queue_delayed_work(rtlpriv->works.rtl_wq, + &rtlpriv->works.ps_work, + MSECS(5)); + } else { + rtl_swlps_rf_awake(hw); + rtlpriv->psc.sw_ps_enabled = false; + } } if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { @@ -257,7 +291,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) case NL80211_CHAN_NO_HT: /* SC */ mac->cur_40_prime_sc = - PRIME_CHNL_OFFSET_DONT_CARE; + PRIME_CHNL_OFFSET_DONT_CARE; rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20; mac->bw_40 = false; break; @@ -265,7 +299,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) /* SC */ mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_UPPER; rtlphy->current_chan_bw = - HT_CHANNEL_WIDTH_20_40; + HT_CHANNEL_WIDTH_20_40; mac->bw_40 = true; /*wide channel */ @@ -276,7 +310,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) /* SC */ mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_LOWER; rtlphy->current_chan_bw = - HT_CHANNEL_WIDTH_20_40; + HT_CHANNEL_WIDTH_20_40; mac->bw_40 = true; /*wide channel */ @@ -286,16 +320,29 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) default: mac->bw_40 = false; RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("switch case not processed\n")); + ("switch case not processed\n")); break; } if (wide_chan <= 0) wide_chan = 1; + + /* In scanning, before we go offchannel we may send a ps=1 null + * to AP, and then we may send a ps = 0 null to AP quickly, but + * first null may have caused AP to put lots of packet to hw tx + * buffer. These packets must be tx'd before we go off channel + * so we must delay more time to let AP flush these packets + * before going offchannel, or dis-association or delete BA will + * happen by AP + */ + if (rtlpriv->mac80211.offchan_deley) { + rtlpriv->mac80211.offchan_deley = false; + mdelay(50); + } rtlphy->current_channel = wide_chan; - rtlpriv->cfg->ops->set_channel_access(hw); rtlpriv->cfg->ops->switch_channel(hw); + rtlpriv->cfg->ops->set_channel_access(hw); rtlpriv->cfg->ops->set_bw_mode(hw, hw->conf.channel_type); } @@ -343,27 +390,28 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw, } } - if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { - /* - *TODO: BIT(5) is probe response BIT(8) is beacon - *TODO: Use define for BIT(5) and BIT(8) - */ - if (*new_flags & FIF_BCN_PRBRESP_PROMISC) - mac->rx_mgt_filter |= (BIT(5) | BIT(8)); - else - mac->rx_mgt_filter &= ~(BIT(5) | BIT(8)); + /* if ssid not set to hw don't check bssid + * here just used for linked scanning, & linked + * and nolink check bssid is set in set network_type */ + if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && + (mac->link_state >= MAC80211_LINKED)) { + if (mac->opmode != NL80211_IFTYPE_AP) { + if (*new_flags & FIF_BCN_PRBRESP_PROMISC) { + rtlpriv->cfg->ops->set_chk_bssid(hw, false); + } else { + rtlpriv->cfg->ops->set_chk_bssid(hw, true); + } + } } if (changed_flags & FIF_CONTROL) { if (*new_flags & FIF_CONTROL) { mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF]; - mac->rx_ctrl_filter |= RTL_SUPPORTED_CTRL_FILTER; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("Enable receive control frame.\n")); } else { mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF]; - mac->rx_ctrl_filter &= ~RTL_SUPPORTED_CTRL_FILTER; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("Disable receive control frame.\n")); } @@ -380,14 +428,54 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw, ("Disable receive other BSS's frame.\n")); } } - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MGT_FILTER, - (u8 *) (&mac->rx_mgt_filter)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CTRL_FILTER, - (u8 *) (&mac->rx_ctrl_filter)); } +static int rtl_op_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_sta_info *sta_entry; + + if (sta) { + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + sta_entry->wireless_mode = WIRELESS_MODE_G; + if (sta->supp_rates[0] <= 0xf) + sta_entry->wireless_mode = WIRELESS_MODE_B; + if (sta->ht_cap.ht_supported == true) + sta_entry->wireless_mode = WIRELESS_MODE_N_24G; + } else if (rtlhal->current_bandtype == BAND_ON_5G) { + sta_entry->wireless_mode = WIRELESS_MODE_A; + if (sta->ht_cap.ht_supported == true) + sta_entry->wireless_mode = WIRELESS_MODE_N_24G; + } + + /* I found some times mac80211 give wrong supp_rates for adhoc*/ + if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) + sta_entry->wireless_mode = WIRELESS_MODE_G; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + ("Add sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr))); + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); + } + return 0; +} +static int rtl_op_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_sta_info *sta_entry; + if (sta) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + ("Remove sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr))); + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + sta_entry->wireless_mode = 0; + sta_entry->ratr_index = 0; + } + return 0; +} static int _rtl_get_hal_qnum(u16 queue) { int qnum; @@ -444,19 +532,18 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss_conf, u32 changed) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct ieee80211_sta *sta = NULL; mutex_lock(&rtlpriv->locks.conf_mutex); - if ((vif->type == NL80211_IFTYPE_ADHOC) || (vif->type == NL80211_IFTYPE_AP) || (vif->type == NL80211_IFTYPE_MESH_POINT)) { - if ((changed & BSS_CHANGED_BEACON) || (changed & BSS_CHANGED_BEACON_ENABLED && bss_conf->enable_beacon)) { - if (mac->beacon_enabled == 0) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, ("BSS_CHANGED_BEACON_ENABLED\n")); @@ -468,8 +555,13 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, rtlpriv->cfg->maps [RTL_IBSS_INT_MASKS], 0); + + if (rtlpriv->cfg->ops->linked_set_reg) + rtlpriv->cfg->ops->linked_set_reg(hw); } - } else { + } + if ((changed & BSS_CHANGED_BEACON_ENABLED && + !bss_conf->enable_beacon)) { if (mac->beacon_enabled == 1) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, ("ADHOC DISABLE BEACON\n")); @@ -480,7 +572,6 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, [RTL_IBSS_INT_MASKS]); } } - if (changed & BSS_CHANGED_BEACON_INT) { RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE, ("BSS_CHANGED_BEACON_INT\n")); @@ -492,11 +583,25 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, /*TODO: reference to enum ieee80211_bss_change */ if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { + /* we should reset all sec info & cam + * before set cam after linked, we should not + * reset in disassoc, that will cause tkip->wep + * fail because some flag will be wrong */ + /* reset sec info */ + rtl_cam_reset_sec_info(hw); + /* reset cam to fix wep fail issue + * when change from wpa to wep */ + rtl_cam_reset_all_entry(hw); + mac->link_state = MAC80211_LINKED; mac->cnt_after_linked = 0; mac->assoc_id = bss_conf->aid; memcpy(mac->bssid, bss_conf->bssid, 6); + if (rtlpriv->cfg->ops->linked_set_reg) + rtlpriv->cfg->ops->linked_set_reg(hw); + if (mac->opmode == NL80211_IFTYPE_STATION && sta) + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, ("BSS_CHANGED_ASSOC\n")); } else { @@ -505,9 +610,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, mac->link_state = MAC80211_NOLINK; memset(mac->bssid, 0, 6); - - /* reset sec info */ - rtl_cam_reset_sec_info(hw); + mac->vendor = PEER_UNKNOWN; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, ("BSS_CHANGED_UN_ASSOC\n")); @@ -544,14 +647,10 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_HT) { - struct ieee80211_sta *sta = NULL; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, ("BSS_CHANGED_HT\n")); - rcu_read_lock(); - sta = ieee80211_find_sta(mac->vif, mac->bssid); - + sta = get_sta(hw, vif, (u8 *)bss_conf->bssid); if (sta) { if (sta->ht_cap.ampdu_density > mac->current_ampdu_density) @@ -573,9 +672,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_BSSID) { - struct ieee80211_sta *sta = NULL; u32 basic_rates; - u8 i; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID, (u8 *) bss_conf->bssid); @@ -583,96 +680,65 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, (MAC_FMT "\n", MAC_ARG(bss_conf->bssid))); + mac->vendor = PEER_UNKNOWN; memcpy(mac->bssid, bss_conf->bssid, 6); - if (is_valid_ether_addr(bss_conf->bssid)) { - switch (vif->type) { - case NL80211_IFTYPE_UNSPECIFIED: - break; - case NL80211_IFTYPE_ADHOC: - break; - case NL80211_IFTYPE_STATION: - break; - case NL80211_IFTYPE_AP: - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("switch case not process\n")); - break; - } - rtlpriv->cfg->ops->set_network_type(hw, vif->type); - } else - rtlpriv->cfg->ops->set_network_type(hw, - NL80211_IFTYPE_UNSPECIFIED); - - memset(mac->mcs, 0, 16); - mac->ht_enable = false; - mac->sgi_40 = false; - mac->sgi_20 = false; - - if (!bss_conf->use_short_slot) - mac->mode = WIRELESS_MODE_B; - else - mac->mode = WIRELESS_MODE_G; + rtlpriv->cfg->ops->set_network_type(hw, vif->type); rcu_read_lock(); - sta = ieee80211_find_sta(mac->vif, mac->bssid); + sta = get_sta(hw, vif, (u8 *)bss_conf->bssid); + if (!sta) { + rcu_read_unlock(); + goto out; + } - if (sta) { - if (sta->ht_cap.ht_supported) { + if (rtlhal->current_bandtype == BAND_ON_5G) { + mac->mode = WIRELESS_MODE_A; + } else { + if (sta->supp_rates[0] <= 0xf) + mac->mode = WIRELESS_MODE_B; + else + mac->mode = WIRELESS_MODE_G; + } + + if (sta->ht_cap.ht_supported) { + if (rtlhal->current_bandtype == BAND_ON_2_4G) mac->mode = WIRELESS_MODE_N_24G; - mac->ht_enable = true; - } + else + mac->mode = WIRELESS_MODE_N_5G; + } - if (mac->ht_enable) { - u16 ht_cap = sta->ht_cap.cap; - memcpy(mac->mcs, (u8 *) (&sta->ht_cap.mcs), 16); - - for (i = 0; i < 16; i++) - RT_TRACE(rtlpriv, COMP_MAC80211, - DBG_LOUD, ("%x ", - mac->mcs[i])); - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - ("\n")); - - if (ht_cap & IEEE80211_HT_CAP_SGI_40) - mac->sgi_40 = true; - - if (ht_cap & IEEE80211_HT_CAP_SGI_20) - mac->sgi_20 = true; - - /* - * for cisco 1252 bw20 it's wrong - * if (ht_cap & - * IEEE80211_HT_CAP_SUP_WIDTH_20_40) { - * mac->bw_40 = true; - * } - */ - } + /* just station need it, because ibss & ap mode will + * set in sta_add, and will be NULL here */ + if (mac->opmode == NL80211_IFTYPE_STATION) { + struct rtl_sta_info *sta_entry; + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + sta_entry->wireless_mode = mac->mode; + } + + if (sta->ht_cap.ht_supported) { + mac->ht_enable = true; + + /* + * for cisco 1252 bw20 it's wrong + * if (ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { + * mac->bw_40 = true; + * } + * */ } - rcu_read_unlock(); - /*mac80211 just give us CCK rates any time - *So we add G rate in basic rates when - not in B mode*/ if (changed & BSS_CHANGED_BASIC_RATES) { - if (mac->mode == WIRELESS_MODE_B) - basic_rates = bss_conf->basic_rates | 0x00f; + /* for 5G must << RATE_6M_INDEX=4, + * because 5G have no cck rate*/ + if (rtlhal->current_bandtype == BAND_ON_5G) + basic_rates = sta->supp_rates[1] << 4; else - basic_rates = bss_conf->basic_rates | 0xff0; - - if (!vif) - goto out; + basic_rates = sta->supp_rates[0]; mac->basic_rates = basic_rates; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, (u8 *) (&basic_rates)); - - if (rtlpriv->dm.useramask) - rtlpriv->cfg->ops->update_rate_mask(hw, 0); - else - rtlpriv->cfg->ops->update_rate_table(hw); - } + rcu_read_unlock(); } /* @@ -758,16 +824,17 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_START: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, ("IEEE80211_AMPDU_TX_START: TID:%d\n", tid)); - return rtl_tx_agg_start(hw, sta->addr, tid, ssn); + return rtl_tx_agg_start(hw, sta, tid, ssn); break; case IEEE80211_AMPDU_TX_STOP: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, ("IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid)); - return rtl_tx_agg_stop(hw, sta->addr, tid); + return rtl_tx_agg_stop(hw, sta, tid); break; case IEEE80211_AMPDU_TX_OPERATIONAL: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, ("IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid)); + rtl_tx_agg_oper(hw, sta, tid); break; case IEEE80211_AMPDU_RX_START: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, @@ -797,8 +864,12 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) if (mac->link_state == MAC80211_LINKED) { rtl_lps_leave(hw); mac->link_state = MAC80211_LINKED_SCANNING; - } else + } else { rtl_ips_nic_on(hw); + } + + /* Dual mac */ + rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; rtlpriv->cfg->ops->led_control(hw, LED_CTL_SITE_SURVEY); rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP); @@ -810,22 +881,19 @@ static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw) struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("\n")); - - rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE); mac->act_scanning = false; + /* Dual mac */ + rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; + if (mac->link_state == MAC80211_LINKED_SCANNING) { mac->link_state = MAC80211_LINKED; - - /* fix fwlps issue */ - rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); - - if (rtlpriv->dm.useramask) - rtlpriv->cfg->ops->update_rate_mask(hw, 0); - else - rtlpriv->cfg->ops->update_rate_table(hw); - + if (mac->opmode == NL80211_IFTYPE_STATION) { + /* fix fwlps issue */ + rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); + } } + rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE); } static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, @@ -856,49 +924,73 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, rtl_ips_nic_on(hw); mutex_lock(&rtlpriv->locks.conf_mutex); /* <1> get encryption alg */ + switch (key->cipher) { case WLAN_CIPHER_SUITE_WEP40: key_type = WEP40_ENCRYPTION; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:WEP40\n")); - rtlpriv->sec.use_defaultkey = true; break; case WLAN_CIPHER_SUITE_WEP104: RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:WEP104\n")); key_type = WEP104_ENCRYPTION; - rtlpriv->sec.use_defaultkey = true; break; case WLAN_CIPHER_SUITE_TKIP: key_type = TKIP_ENCRYPTION; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:TKIP\n")); - if (mac->opmode == NL80211_IFTYPE_ADHOC) - rtlpriv->sec.use_defaultkey = true; break; case WLAN_CIPHER_SUITE_CCMP: key_type = AESCCMP_ENCRYPTION; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:CCMP\n")); - if (mac->opmode == NL80211_IFTYPE_ADHOC) - rtlpriv->sec.use_defaultkey = true; break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("alg_err:%x!!!!:\n", key->cipher)); goto out_unlock; } + if (key_type == WEP40_ENCRYPTION || + key_type == WEP104_ENCRYPTION || + mac->opmode == NL80211_IFTYPE_ADHOC) + rtlpriv->sec.use_defaultkey = true; + /* <2> get key_idx */ key_idx = (u8) (key->keyidx); if (key_idx > 3) goto out_unlock; /* <3> if pairwise key enable_hw_sec */ group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE); - if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) || - rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { - if (rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION && - (key_type == WEP40_ENCRYPTION || - key_type == WEP104_ENCRYPTION)) - wep_only = true; - rtlpriv->sec.pairwise_enc_algorithm = key_type; - rtlpriv->cfg->ops->enable_hw_sec(hw); + + /* wep always be group key, but there are two conditions: + * 1) wep only: is just for wep enc, in this condition + * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION + * will be true & enable_hw_sec will be set when wep + * ke setting. + * 2) wep(group) + AES(pairwise): some AP like cisco + * may use it, in this condition enable_hw_sec will not + * be set when wep key setting */ + /* we must reset sec_info after lingked before set key, + * or some flag will be wrong*/ + if (mac->opmode == NL80211_IFTYPE_AP) { + if (!group_key || key_type == WEP40_ENCRYPTION || + key_type == WEP104_ENCRYPTION) { + if (group_key) + wep_only = true; + rtlpriv->cfg->ops->enable_hw_sec(hw); + } + } else { + if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) || + rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { + if (rtlpriv->sec.pairwise_enc_algorithm == + NO_ENCRYPTION && + (key_type == WEP40_ENCRYPTION || + key_type == WEP104_ENCRYPTION)) + wep_only = true; + rtlpriv->sec.pairwise_enc_algorithm = key_type; + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1" + " TKIP:2 AES:4 WEP104:5)\n", key_type)); + rtlpriv->cfg->ops->enable_hw_sec(hw); + } } /* <4> set key based on cmd */ switch (cmd) { @@ -930,6 +1022,7 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (!sta) { RT_ASSERT(false, ("pairwise key withnot" "mac_addr\n")); + err = -EOPNOTSUPP; goto out_unlock; } @@ -957,6 +1050,10 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("disable key delete one entry\n")); /*set local buf about wep key. */ + if (mac->opmode == NL80211_IFTYPE_AP) { + if (sta) + rtl_cam_del_entry(hw, sta->addr); + } memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen); rtlpriv->sec.key_len[key_idx] = 0; memcpy(mac_addr, zero_addr, ETH_ALEN); @@ -1009,6 +1106,18 @@ static void rtl_op_rfkill_poll(struct ieee80211_hw *hw) mutex_unlock(&rtlpriv->locks.conf_mutex); } +/* this function is called by mac80211 to flush tx buffer + * before switch channle or power save, or tx buffer packet + * maybe send after offchannel or rf sleep, this may cause + * dis-association by AP */ +static void rtl_op_flush(struct ieee80211_hw *hw, bool drop) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->intf_ops->flush) + rtlpriv->intf_ops->flush(hw, drop); +} + const struct ieee80211_ops rtl_ops = { .start = rtl_op_start, .stop = rtl_op_stop, @@ -1017,6 +1126,8 @@ const struct ieee80211_ops rtl_ops = { .remove_interface = rtl_op_remove_interface, .config = rtl_op_config, .configure_filter = rtl_op_configure_filter, + .sta_add = rtl_op_sta_add, + .sta_remove = rtl_op_sta_remove, .set_key = rtl_op_set_key, .conf_tx = rtl_op_conf_tx, .bss_info_changed = rtl_op_bss_info_changed, @@ -1028,4 +1139,5 @@ const struct ieee80211_ops rtl_ops = { .sw_scan_start = rtl_op_sw_scan_start, .sw_scan_complete = rtl_op_sw_scan_complete, .rfkill_poll = rtl_op_rfkill_poll, + .flush = rtl_op_flush, }; diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h index 0ef31c3c6196..4b247db2861d 100644 --- a/drivers/net/wireless/rtlwifi/core.h +++ b/drivers/net/wireless/rtlwifi/core.h @@ -24,6 +24,7 @@ * Hsinchu 300, Taiwan. * * Larry Finger + * *****************************************************************************/ #ifndef __RTL_CORE_H__ diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index bdb3c5f5c4b0..861849013c54 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -424,6 +424,10 @@ void rtl_swlps_wq_callback(void *data) { } +void rtl_swlps_rf_awake(struct ieee80211_hw *hw) +{ +} + /*Enter the leisure power save mode.*/ void rtl_lps_enter(struct ieee80211_hw *hw) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 0df2fec27a08..cc5de0726938 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -504,7 +504,7 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool defaultadapter = true; - struct ieee80211_sta *sta; + struct ieee80211_sta *sta = info->control.sta; struct rtl_tcb_desc tcb_desc; u8 *qc = ieee80211_get_qos_ctl(hdr); u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index f4ab1b7732c3..14539eb9589e 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -885,7 +885,8 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); } -static int rtl_usb_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static int rtl_usb_tx(struct ieee80211_hw *hw, struct sk_buff *skb, + struct rtl_tcb_desc *dummy) { struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 7c52435a1180..4776cd1ee4f8 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -1445,12 +1445,8 @@ struct rtl_intf_ops { int (*adapter_start) (struct ieee80211_hw *hw); void (*adapter_stop) (struct ieee80211_hw *hw); -#if 0 /* temporary */ int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb, struct rtl_tcb_desc *ptcb_desc); -#else - int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb); -#endif void (*flush)(struct ieee80211_hw *hw, bool drop); int (*reset_trx_ring) (struct ieee80211_hw *hw); bool (*waitq_insert) (struct ieee80211_hw *hw, struct sk_buff *skb); -- cgit v1.2.3-58-ga151 From c7cfe38ee0f946415b0b39e3905a91a51d99cf7d Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 13:23:15 -0500 Subject: rtlwifi: Convert pci routines for addition of rtl8192se and rtl8192de Convert pci routines for addition of RTL8192SE and RTL8192DE code These changes allow the upper-level driver to specify the BAR to be used as it is different for rtl8192se than for the others. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 788 ++++++++++++++++++++++++++----------- drivers/net/wireless/rtlwifi/pci.h | 15 +- drivers/net/wireless/rtlwifi/ps.c | 4 + 3 files changed, 578 insertions(+), 229 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index e2fa78bc1299..fa66205d8b95 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -32,6 +32,7 @@ #include "pci.h" #include "base.h" #include "ps.h" +#include "efuse.h" static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { INTEL_VENDOR_ID, @@ -40,6 +41,31 @@ static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { SIS_VENDOR_ID }; +static const u8 ac_to_hwq[] = { + VO_QUEUE, + VI_QUEUE, + BE_QUEUE, + BK_QUEUE +}; + +u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, + struct sk_buff *skb) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u16 fc = rtl_get_fc(skb); + u8 queue_index = skb_get_queue_mapping(skb); + + if (unlikely(ieee80211_is_beacon(fc))) + return BEACON_QUEUE; + if (ieee80211_is_mgmt(fc)) + return MGNT_QUEUE; + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) + if (ieee80211_is_nullfunc(fc)) + return HIGH_QUEUE; + + return ac_to_hwq[queue_index]; +} + /* Update PCI dependent default settings*/ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) { @@ -48,6 +74,7 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; + u8 init_aspm; ppsc->reg_rfps_level = 0; ppsc->support_aspm = 0; @@ -113,25 +140,110 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) /*Set HW definition to determine if it supports ASPM. */ switch (rtlpci->const_support_pciaspm) { - case 0: - /*Not support ASPM. */ - ppsc->support_aspm = false; - break; - case 1: - /*Support ASPM. */ - ppsc->support_aspm = true; - ppsc->support_backdoor = true; - break; + case 0:{ + /*Not support ASPM. */ + bool support_aspm = false; + ppsc->support_aspm = support_aspm; + break; + } + case 1:{ + /*Support ASPM. */ + bool support_aspm = true; + bool support_backdoor = true; + ppsc->support_aspm = support_aspm; + + /*if (priv->oem_id == RT_CID_TOSHIBA && + !priv->ndis_adapter.amd_l1_patch) + support_backdoor = false; */ + + ppsc->support_backdoor = support_backdoor; + + break; + } case 2: /*ASPM value set by chipset. */ - if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) - ppsc->support_aspm = true; + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) { + bool support_aspm = true; + ppsc->support_aspm = support_aspm; + } break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case not process\n")); break; } + + /* toshiba aspm issue, toshiba will set aspm selfly + * so we should not set aspm in driver */ + pci_read_config_byte(rtlpci->pdev, 0x80, &init_aspm); + if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8192SE && + init_aspm == 0x43) + ppsc->support_aspm = false; +} + +/*Disable L0s dirtectly. We will disable host L0s by default. */ +void rtl_pci_disable_host_l0s(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 pcibridge_busnum = pcipriv->ndis_adapter.pcibridge_busnum; + u8 pcibridge_devnum = pcipriv->ndis_adapter.pcibridge_devnum; + u8 pcibridge_funcnum = pcipriv->ndis_adapter.pcibridge_funcnum; + u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport; + u8 num4bytes = pcipriv->ndis_adapter.num4bytes; + u8 u_pcibridge_aspmsetting = 0; + + /*Read Link Control Register */ + rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, + pcicfg_addrport + (num4bytes << 2)); + rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &u_pcibridge_aspmsetting); + + if (u_pcibridge_aspmsetting & BIT(0)) + u_pcibridge_aspmsetting &= ~(BIT(0)); + + rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, + pcicfg_addrport + (num4bytes << 2)); + rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, u_pcibridge_aspmsetting); + + udelay(50); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("PciBridge busnumber[%x], DevNumbe[%x], " + "funcnumber[%x], Write reg[%x] = %lx\n", + pcibridge_busnum, pcibridge_devnum, pcibridge_funcnum, + (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10), + (pcipriv->ndis_adapter.pcibridge_linkctrlreg | + (rtlpci->const_devicepci_aspm_setting & ~BIT(0))))); +} + +/*Enable rtl8192ce backdoor to control ASPM and clock request.*/ +bool rtl_pci_enable_back_door(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; + bool bresult = true; + u8 value; + + pci_read_config_byte(rtlpci->pdev, 0x70f, &value); + + /*0x70f BIT(7) is used to control L0S */ + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) { + value |= BIT(7); + } else { + /*Set 0x70f to 0x23 when non-Intel platform. */ + value = 0x23; + } + + pci_write_config_byte(rtlpci->pdev, 0x70f, value); + + pci_read_config_byte(rtlpci->pdev, 0x719, &value); + /*0x719 BIT(3) is for L1 BIT(4) is for clock request */ + value |= (BIT(3) | BIT(4)); + pci_write_config_byte(rtlpci->pdev, 0x719, value); + + return bresult; } static bool _rtl_pci_platform_switch_device_pci_aspm( @@ -139,8 +251,11 @@ static bool _rtl_pci_platform_switch_device_pci_aspm( u8 value) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) + value |= 0x40; - value |= 0x40; pci_write_config_byte(rtlpci->pdev, 0x80, value); return false; @@ -150,11 +265,13 @@ static bool _rtl_pci_platform_switch_device_pci_aspm( static bool _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 buffer; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - buffer = value; pci_write_config_byte(rtlpci->pdev, 0x81, value); + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) + udelay(100); + return true; } @@ -175,6 +292,9 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw) u16 aspmlevel = 0; u8 tmp_u1b = 0; + if (!ppsc->support_aspm) + return; + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, ("PCI(Bridge) UNKNOWN.\n")); @@ -228,6 +348,9 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) u8 u_pcibridge_aspmsetting; u8 u_device_aspmsetting; + if (!ppsc->support_aspm) + return; + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, ("PCI(Bridge) UNKNOWN.\n")); @@ -272,7 +395,7 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0); RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ); } - udelay(200); + udelay(100); } static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) @@ -303,19 +426,19 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) return status; } -static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) +void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) { struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset; u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport; u8 linkctrl_reg; - u8 num4bBytes; + u8 num4bbytes; - num4bBytes = (capabilityoffset + 0x10) / 4; + num4bbytes = (capabilityoffset + 0x10) / 4; /*Read Link Control Register */ rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, - pcicfg_addrport + (num4bBytes << 2)); + pcicfg_addrport + (num4bbytes << 2)); rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &linkctrl_reg); pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg; @@ -348,7 +471,7 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev, pci_write_config_byte(pdev, 0x70f, tmp); } -static void _rtl_pci_initialize_adapter_common(struct ieee80211_hw *hw) +static void rtl_pci_init_aspm(struct ieee80211_hw *hw) { struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); @@ -362,52 +485,6 @@ static void _rtl_pci_initialize_adapter_common(struct ieee80211_hw *hw) } -static void rtl_pci_init_aspm(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - /*close ASPM for AMD defaultly */ - rtlpci->const_amdpci_aspm = 0; - - /* - * ASPM PS mode. - * 0 - Disable ASPM, - * 1 - Enable ASPM without Clock Req, - * 2 - Enable ASPM with Clock Req, - * 3 - Alwyas Enable ASPM with Clock Req, - * 4 - Always Enable ASPM without Clock Req. - * set defult to RTL8192CE:3 RTL8192E:2 - * */ - rtlpci->const_pci_aspm = 3; - - /*Setting for PCI-E device */ - rtlpci->const_devicepci_aspm_setting = 0x03; - - /*Setting for PCI-E bridge */ - rtlpci->const_hostpci_aspm_setting = 0x02; - - /* - * In Hw/Sw Radio Off situation. - * 0 - Default, - * 1 - From ASPM setting without low Mac Pwr, - * 2 - From ASPM setting with low Mac Pwr, - * 3 - Bus D3 - * set default to RTL8192CE:0 RTL8192SE:2 - */ - rtlpci->const_hwsw_rfoff_d3 = 0; - - /* - * This setting works for those device with - * backdoor ASPM setting such as EPHY setting. - * 0 - Not support ASPM, - * 1 - Support ASPM, - * 2 - According to chipset. - */ - rtlpci->const_support_pciaspm = 1; - - _rtl_pci_initialize_adapter_common(hw); -} - static void _rtl_pci_io_handler_init(struct device *dev, struct ieee80211_hw *hw) { @@ -429,6 +506,92 @@ static void _rtl_pci_io_handler_release(struct ieee80211_hw *hw) { } +static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, + struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + u8 additionlen = FCS_LEN; + struct sk_buff *next_skb; + + /* here open is 4, wep/tkip is 8, aes is 12*/ + if (info->control.hw_key) + additionlen += info->control.hw_key->icv_len; + + /* The most skb num is 6 */ + tcb_desc->empkt_num = 0; + spin_lock_bh(&rtlpriv->locks.waitq_lock); + skb_queue_walk(&rtlpriv->mac80211.skb_waitq[tid], next_skb) { + struct ieee80211_tx_info *next_info; + + next_info = IEEE80211_SKB_CB(next_skb); + if (next_info->flags & IEEE80211_TX_CTL_AMPDU) { + tcb_desc->empkt_len[tcb_desc->empkt_num] = + next_skb->len + additionlen; + tcb_desc->empkt_num++; + } else { + break; + } + + if (skb_queue_is_last(&rtlpriv->mac80211.skb_waitq[tid], + next_skb)) + break; + + if (tcb_desc->empkt_num >= 5) + break; + } + spin_unlock_bh(&rtlpriv->locks.waitq_lock); + + return true; +} + +/* just for early mode now */ +static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct sk_buff *skb = NULL; + struct ieee80211_tx_info *info = NULL; + int tid; /* should be int */ + + if (!rtlpriv->rtlhal.earlymode_enable) + return; + + /* we juse use em for BE/BK/VI/VO */ + for (tid = 7; tid >= 0; tid--) { + u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(hw, tid)]; + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; + while (!mac->act_scanning && + rtlpriv->psc.rfpwr_state == ERFON) { + struct rtl_tcb_desc tcb_desc; + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + + spin_lock_bh(&rtlpriv->locks.waitq_lock); + if (!skb_queue_empty(&mac->skb_waitq[tid]) && + (ring->entries - skb_queue_len(&ring->queue) > 5)) { + skb = skb_dequeue(&mac->skb_waitq[tid]); + } else { + spin_unlock_bh(&rtlpriv->locks.waitq_lock); + break; + } + spin_unlock_bh(&rtlpriv->locks.waitq_lock); + + /* Some macaddr can't do early mode. like + * multicast/broadcast/no_qos data */ + info = IEEE80211_SKB_CB(skb); + if (info->flags & IEEE80211_TX_CTL_AMPDU) + _rtl_update_earlymode_info(hw, skb, + &tcb_desc, tid); + +#if 0 /* temporary */ + rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); +#endif + } + } +} + + static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -440,6 +603,8 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) struct rtl_tx_desc *entry = &ring->desc[ring->idx]; struct sk_buff *skb; struct ieee80211_tx_info *info; + __le16 fc; + u8 tid; u8 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, true, HW_DESC_OWN); @@ -455,11 +620,15 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) skb = __skb_dequeue(&ring->queue); pci_unmap_single(rtlpci->pdev, - rtlpriv->cfg->ops-> + le32_to_cpu(rtlpriv->cfg->ops-> get_desc((u8 *) entry, true, - HW_DESC_TXBUFF_ADDR), + HW_DESC_TXBUFF_ADDR)), skb->len, PCI_DMA_TODEVICE); + /* remove early mode header */ + if (rtlpriv->rtlhal.earlymode_enable) + skb_pull(skb, EM_HDR_LEN); + RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_TRACE, ("new ring->idx:%d, " "free: skb_queue_len:%d, free: seq:%x\n", @@ -467,6 +636,30 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) skb_queue_len(&ring->queue), *(u16 *) (skb->data + 22))); + if (prio == TXCMD_QUEUE) { + dev_kfree_skb(skb); + goto tx_status_ok; + + } + + /* for sw LPS, just after NULL skb send out, we can + * sure AP kown we are sleeped, our we should not let + * rf to sleep*/ + fc = rtl_get_fc(skb); + if (ieee80211_is_nullfunc(fc)) { + if (ieee80211_has_pm(fc)) { + rtlpriv->mac80211.offchan_deley = true; + rtlpriv->psc.state_inap = 1; + } else { + rtlpriv->psc.state_inap = 0; + } + } + + /* update tid tx pkt num */ + tid = rtl_get_tid(skb); + if (tid <= 7) + rtlpriv->link_info.tidtx_inperiod[tid]++; + info = IEEE80211_SKB_CB(skb); ieee80211_tx_info_clear_status(info); @@ -489,7 +682,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) skb_get_queue_mapping (skb)); } - +tx_status_ok: skb = NULL; } @@ -561,23 +754,21 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) *skb_trim(skb, skb->len - 4); */ - hdr = (struct ieee80211_hdr *)(skb->data); - fc = hdr->frame_control; + hdr = rtl_get_hdr(skb); + fc = rtl_get_fc(skb); - if (!stats.crc) { + if (!stats.crc || !stats.hwerror) { memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - if (is_broadcast_ether_addr(hdr->addr1)) + if (is_broadcast_ether_addr(hdr->addr1)) { ;/*TODO*/ - else { - if (is_multicast_ether_addr(hdr->addr1)) - ;/*TODO*/ - else { - unicast = true; - rtlpriv->stats.rxbytesunicast += - skb->len; - } + } else if (is_multicast_ether_addr(hdr->addr1)) { + ;/*TODO*/ + } else { + unicast = true; + rtlpriv->stats.rxbytesunicast += + skb->len; } rtl_is_special_data(hw, skb, false); @@ -591,28 +782,38 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) num_rx_inperiod++; } - if (unlikely(!rtl_action_proc(hw, skb, - false))) { + /* for sw lps */ + rtl_swlps_beacon(hw, (void *)skb->data, + skb->len); + rtl_recognize_peer(hw, (void *)skb->data, + skb->len); + if ((rtlpriv->mac80211.opmode == + NL80211_IFTYPE_AP) && + (rtlpriv->rtlhal.current_bandtype == + BAND_ON_2_4G) && + (ieee80211_is_beacon(fc) || + ieee80211_is_probe_resp(fc))) { dev_kfree_skb_any(skb); } else { - struct sk_buff *uskb = NULL; - u8 *pdata; - uskb = dev_alloc_skb(skb->len + 128); - if (!uskb) { - RT_TRACE(rtlpriv, - (COMP_INTR | COMP_RECV), - DBG_EMERG, - ("can't alloc rx skb\n")); - goto done; + if (unlikely(!rtl_action_proc(hw, skb, + false))) { + dev_kfree_skb_any(skb); + } else { + struct sk_buff *uskb = NULL; + u8 *pdata; + uskb = dev_alloc_skb(skb->len + + 128); + memcpy(IEEE80211_SKB_RXCB(uskb), + &rx_status, + sizeof(rx_status)); + pdata = (u8 *)skb_put(uskb, + skb->len); + memcpy(pdata, skb->data, + skb->len); + dev_kfree_skb_any(skb); + + ieee80211_rx_irqsafe(hw, uskb); } - memcpy(IEEE80211_SKB_RXCB(uskb), - &rx_status, - sizeof(rx_status)); - pdata = (u8 *)skb_put(uskb, skb->len); - memcpy(pdata, skb->data, skb->len); - dev_kfree_skb_any(skb); - - ieee80211_rx_irqsafe(hw, uskb); } } else { dev_kfree_skb_any(skb); @@ -627,7 +828,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) new_skb = dev_alloc_skb(rtlpci->rxbuffersize); if (unlikely(!new_skb)) { RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), - DBG_EMERG, + DBG_DMESG, ("can't alloc skb for rx\n")); goto done; } @@ -645,7 +846,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) } done: - bufferaddress = (u32)(*((dma_addr_t *) skb->cb)); + bufferaddress = cpu_to_le32(*((dma_addr_t *)skb->cb)); tmp_one = 1; rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false, HW_DESC_RXBUFF_ADDR, @@ -669,11 +870,81 @@ done: } +void _rtl_pci_tx_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + int prio; + + for (prio = 0; prio < RTL_PCI_MAX_TX_QUEUE_COUNT; prio++) { + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[prio]; + + while (skb_queue_len(&ring->queue)) { + struct rtl_tx_desc *entry = &ring->desc[ring->idx]; + struct sk_buff *skb; + struct ieee80211_tx_info *info; + u8 own; + + /* + *beacon packet will only use the first + *descriptor defautly, and the own may not + *be cleared by the hardware, and + *beacon will free in prepare beacon + */ + if (prio == BEACON_QUEUE || prio == TXCMD_QUEUE || + prio == HCCA_QUEUE) + break; + + own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, + true, + HW_DESC_OWN); + + if (own) + break; + + skb = __skb_dequeue(&ring->queue); + pci_unmap_single(rtlpci->pdev, + le32_to_cpu(rtlpriv->cfg->ops-> + get_desc((u8 *) entry, + true, + HW_DESC_TXBUFF_ADDR)), + skb->len, PCI_DMA_TODEVICE); + + ring->idx = (ring->idx + 1) % ring->entries; + + info = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(info); + + info->flags |= IEEE80211_TX_STAT_ACK; + /*info->status.rates[0].count = 1; */ + + ieee80211_tx_status_irqsafe(hw, skb); + + if ((ring->entries - skb_queue_len(&ring->queue)) + == 2 && prio != BEACON_QUEUE) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("more desc left, wake " + "skb_queue@%d,ring->idx = %d," + "skb_queue_len = 0x%d\n", + prio, ring->idx, + skb_queue_len(&ring->queue))); + + ieee80211_wake_queue(hw, + skb_get_queue_mapping + (skb)); + } + + skb = NULL; + } + } +} + static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) { struct ieee80211_hw *hw = dev_id; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); unsigned long flags; u32 inta = 0; u32 intb = 0; @@ -760,23 +1031,36 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) _rtl_pci_tx_isr(hw, VO_QUEUE); } + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { + if (inta & rtlpriv->cfg->maps[RTL_IMR_COMDOK]) { + rtlpriv->link_info.num_tx_inperiod++; + + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + ("CMD TX OK interrupt!\n")); + _rtl_pci_tx_isr(hw, TXCMD_QUEUE); + } + } + /*<2> Rx related */ if (inta & rtlpriv->cfg->maps[RTL_IMR_ROK]) { RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, ("Rx ok interrupt!\n")); - tasklet_schedule(&rtlpriv->works.irq_tasklet); + _rtl_pci_rx_interrupt(hw); } if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RDU])) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("rx descriptor unavailable!\n")); - tasklet_schedule(&rtlpriv->works.irq_tasklet); + _rtl_pci_rx_interrupt(hw); } if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RXFOVW])) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("rx overflow !\n")); - tasklet_schedule(&rtlpriv->works.irq_tasklet); + _rtl_pci_rx_interrupt(hw); } + if (rtlpriv->rtlhal.earlymode_enable) + tasklet_schedule(&rtlpriv->works.irq_tasklet); + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); return IRQ_HANDLED; @@ -787,7 +1071,7 @@ done: static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw) { - _rtl_pci_rx_interrupt(hw); + _rtl_pci_tx_chk_waitq(hw); } static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) @@ -795,14 +1079,15 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; + struct rtl8192_tx_ring *ring = NULL; struct ieee80211_hdr *hdr = NULL; struct ieee80211_tx_info *info = NULL; struct sk_buff *pskb = NULL; struct rtl_tx_desc *pdesc = NULL; - unsigned int queue_index; + struct rtl_tcb_desc tcb_desc; u8 temp_one = 1; + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); ring = &rtlpci->tx_ring[BEACON_QUEUE]; pskb = __skb_dequeue(&ring->queue); if (pskb) @@ -812,14 +1097,13 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) pskb = ieee80211_beacon_get(hw, mac->vif); if (pskb == NULL) return; - hdr = (struct ieee80211_hdr *)(pskb->data); + hdr = rtl_get_hdr(pskb); info = IEEE80211_SKB_CB(pskb); - - queue_index = BEACON_QUEUE; - pdesc = &ring->desc[0]; +#if 0 /* temporary */ rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, - info, pskb, queue_index); + info, pskb, BEACON_QUEUE, &tcb_desc); +#endif __skb_queue_tail(&ring->queue, pskb); @@ -861,7 +1145,6 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); rtlpci->up_first_time = true; rtlpci->being_init_adapter = false; @@ -869,31 +1152,20 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, rtlhal->hw = hw; rtlpci->pdev = pdev; - ppsc->inactiveps = false; - ppsc->leisure_ps = true; - ppsc->fwctrl_lps = true; - ppsc->reg_fwctrl_lps = 3; - ppsc->reg_max_lps_awakeintvl = 5; - - if (ppsc->reg_fwctrl_lps == 1) - ppsc->fwctrl_psmode = FW_PS_MIN_MODE; - else if (ppsc->reg_fwctrl_lps == 2) - ppsc->fwctrl_psmode = FW_PS_MAX_MODE; - else if (ppsc->reg_fwctrl_lps == 3) - ppsc->fwctrl_psmode = FW_PS_DTIM_MODE; - /*Tx/Rx related var */ _rtl_pci_init_trx_var(hw); - /*IBSS*/ mac->beacon_interval = 100; + /*IBSS*/ mac->beacon_interval = 100; - /*AMPDU*/ mac->min_space_cfg = 0; + /*AMPDU*/ + mac->min_space_cfg = 0; mac->max_mss_density = 0; /*set sane AMPDU defaults */ mac->current_ampdu_density = 7; mac->current_ampdu_factor = 3; - /*QOS*/ rtlpci->acm_method = eAcmWay2_SW; + /*QOS*/ + rtlpci->acm_method = eAcmWay2_SW; /*task */ tasklet_init(&rtlpriv->works.irq_tasklet, @@ -934,8 +1206,9 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, ("queue:%d, ring_addr:%p\n", prio, ring)); for (i = 0; i < entries; i++) { - nextdescaddress = (u32) dma + ((i + 1) % entries) * - sizeof(*ring); + nextdescaddress = cpu_to_le32((u32) dma + + ((i + 11) % entries) * + sizeof(*ring)); rtlpriv->cfg->ops->set_desc((u8 *)&(ring[i]), true, HW_DESC_TX_NEXTDESC_ADDR, @@ -999,7 +1272,7 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw) rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE); - bufferaddress = (u32)(*((dma_addr_t *)skb->cb)); + bufferaddress = cpu_to_le32(*((dma_addr_t *)skb->cb)); rtlpriv->cfg->ops->set_desc((u8 *)entry, false, HW_DESC_RXBUFF_ADDR, (u8 *)&bufferaddress); @@ -1030,9 +1303,9 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw, struct sk_buff *skb = __skb_dequeue(&ring->queue); pci_unmap_single(rtlpci->pdev, - rtlpriv->cfg-> + le32_to_cpu(rtlpriv->cfg-> ops->get_desc((u8 *) entry, true, - HW_DESC_TXBUFF_ADDR), + HW_DESC_TXBUFF_ADDR)), skb->len, PCI_DMA_TODEVICE); kfree_skb(skb); ring->idx = (ring->idx + 1) % ring->entries; @@ -1164,11 +1437,11 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) __skb_dequeue(&ring->queue); pci_unmap_single(rtlpci->pdev, - rtlpriv->cfg->ops-> + le32_to_cpu(rtlpriv->cfg->ops-> get_desc((u8 *) entry, true, - HW_DESC_TXBUFF_ADDR), + HW_DESC_TXBUFF_ADDR)), skb->len, PCI_DMA_TODEVICE); kfree_skb(skb); ring->idx = (ring->idx + 1) % ring->entries; @@ -1182,70 +1455,73 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) return 0; } -static unsigned int _rtl_mac_to_hwqueue(__le16 fc, - unsigned int mac80211_queue_index) +static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw, + struct sk_buff *skb) { - unsigned int hw_queue_index; - - if (unlikely(ieee80211_is_beacon(fc))) { - hw_queue_index = BEACON_QUEUE; - goto out; - } - - if (ieee80211_is_mgmt(fc)) { - hw_queue_index = MGNT_QUEUE; - goto out; - } - - switch (mac80211_queue_index) { - case 0: - hw_queue_index = VO_QUEUE; - break; - case 1: - hw_queue_index = VI_QUEUE; - break; - case 2: - hw_queue_index = BE_QUEUE;; - break; - case 3: - hw_queue_index = BK_QUEUE; - break; - default: - hw_queue_index = BE_QUEUE; - RT_ASSERT(false, ("QSLT_BE queue, skb_queue:%d\n", - mac80211_queue_index)); - break; - } + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = info->control.sta; + struct rtl_sta_info *sta_entry = NULL; + u8 tid = rtl_get_tid(skb); + + if (!sta) + return false; + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + + if (!rtlpriv->rtlhal.earlymode_enable) + return false; + if (sta_entry->tids[tid].agg.agg_state != RTL_AGG_OPERATIONAL) + return false; + if (_rtl_mac_to_hwqueue(hw, skb) > VO_QUEUE) + return false; + if (tid > 7) + return false; + + /* maybe every tid should be checked */ + if (!rtlpriv->link_info.higher_busytxtraffic[tid]) + return false; + + spin_lock_bh(&rtlpriv->locks.waitq_lock); + skb_queue_tail(&rtlpriv->mac80211.skb_waitq[tid], skb); + spin_unlock_bh(&rtlpriv->locks.waitq_lock); -out: - return hw_queue_index; + return true; } -static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb, + struct rtl_tcb_desc *ptcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = info->control.sta; struct rtl8192_tx_ring *ring; struct rtl_tx_desc *pdesc; u8 idx; - unsigned int queue_index, hw_queue; + u8 hw_queue = _rtl_mac_to_hwqueue(hw, skb); unsigned long flags; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - __le16 fc = hdr->frame_control; + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); + __le16 fc = rtl_get_fc(skb); u8 *pda_addr = hdr->addr1; struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); /*ssn */ - u8 *qc = NULL; u8 tid = 0; u16 seq_number = 0; u8 own; u8 temp_one = 1; - rtl_action_proc(hw, skb, true); + if (ieee80211_is_auth(fc)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); + rtl_ips_nic_on(hw); + } + + if (rtlpriv->psc.sw_ps_enabled) { + if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && + !ieee80211_has_pm(fc)) + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); + } - queue_index = skb_get_queue_mapping(skb); - hw_queue = _rtl_mac_to_hwqueue(fc, queue_index); + rtl_action_proc(hw, skb, true); if (is_multicast_ether_addr(pda_addr)) rtlpriv->stats.txbytesmulticast += skb->len; @@ -1255,7 +1531,6 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb) rtlpriv->stats.txbytesunicast += skb->len; spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - ring = &rtlpci->tx_ring[hw_queue]; if (hw_queue != BEACON_QUEUE) idx = (ring->idx + skb_queue_len(&ring->queue)) % @@ -1278,43 +1553,32 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return skb->len; } - /* - *if(ieee80211_is_nullfunc(fc)) { - * spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - * return 1; - *} - */ - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - - seq_number = mac->tids[tid].seq_number; - seq_number &= IEEE80211_SCTL_SEQ; - /* - *hdr->seq_ctrl = hdr->seq_ctrl & - *cpu_to_le16(IEEE80211_SCTL_FRAG); - *hdr->seq_ctrl |= cpu_to_le16(seq_number); - */ - - seq_number += 1; + tid = rtl_get_tid(skb); + if (sta) { + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + seq_number = (le16_to_cpu(hdr->seq_ctrl) & + IEEE80211_SCTL_SEQ) >> 4; + seq_number += 1; + + if (!ieee80211_has_morefrags(hdr->frame_control)) + sta_entry->tids[tid].seq_number = seq_number; + } } if (ieee80211_is_data(fc)) rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); - rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, - info, skb, hw_queue); +#if 0 /* temporary */ + rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, + info, skb, hw_queue, ptcb_desc); +#endif __skb_queue_tail(&ring->queue, skb); - rtlpriv->cfg->ops->set_desc((u8 *) pdesc, true, + rtlpriv->cfg->ops->set_desc((u8 *)pdesc, true, HW_DESC_OWN, (u8 *)&temp_one); - if (!ieee80211_has_morefrags(hdr->frame_control)) { - if (qc) - mac->tids[tid].seq_number = seq_number; - } if ((ring->entries - skb_queue_len(&ring->queue)) < 2 && hw_queue != BEACON_QUEUE) { @@ -1336,7 +1600,36 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return 0; } -static void rtl_pci_deinit(struct ieee80211_hw *hw) +static void rtl_pci_flush(struct ieee80211_hw *hw, bool drop) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u16 i = 0; + int queue_id; + struct rtl8192_tx_ring *ring; + + for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) { + u32 queue_len; + ring = &pcipriv->dev.tx_ring[queue_id]; + queue_len = skb_queue_len(&ring->queue); + if (queue_len == 0 || queue_id == BEACON_QUEUE || + queue_id == TXCMD_QUEUE) { + queue_id--; + continue; + } else { + msleep(20); + i++; + } + + /* we just wait 1s for all queues */ + if (rtlpriv->psc.rfpwr_state == ERFOFF || + is_hal_stop(rtlhal) || i >= 200) + return; + } +} + +void rtl_pci_deinit(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); @@ -1351,7 +1644,7 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw) } -static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) +int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) { struct rtl_priv *rtlpriv = rtl_priv(hw); int err; @@ -1368,7 +1661,7 @@ static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) return 1; } -static int rtl_pci_start(struct ieee80211_hw *hw) +int rtl_pci_start(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -1403,7 +1696,7 @@ static int rtl_pci_start(struct ieee80211_hw *hw) return 0; } -static void rtl_pci_stop(struct ieee80211_hw *hw) +void rtl_pci_stop(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); @@ -1454,11 +1747,13 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, struct pci_dev *bridge_pdev = pdev->bus->self; u16 venderid; u16 deviceid; + u8 revisionid; u16 irqline; u8 tmp; venderid = pdev->vendor; deviceid = pdev->device; + pci_read_config_byte(pdev, 0x8, &revisionid); pci_read_config_word(pdev, 0x3C, &irqline); if (deviceid == RTL_PCI_8192_DID || @@ -1469,7 +1764,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, deviceid == RTL_PCI_8173_DID || deviceid == RTL_PCI_8172_DID || deviceid == RTL_PCI_8171_DID) { - switch (pdev->revision) { + switch (revisionid) { case RTL_PCI_REVISION_ID_8192PCIE: RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("8192 PCI-E is found - " @@ -1498,6 +1793,12 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("8192C PCI-E is found - " "vid/did=%x/%x\n", venderid, deviceid)); + } else if (deviceid == RTL_PCI_8192DE_DID || + deviceid == RTL_PCI_8192DE_DID2) { + rtlhal->hw_type = HARDWARE_TYPE_RTL8192DE; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + ("8192D PCI-E is found - " + "vid/did=%x/%x\n", venderid, deviceid)); } else { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("Err: Unknown device -" @@ -1506,6 +1807,25 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, rtlhal->hw_type = RTL_DEFAULT_HARDWARE_TYPE; } + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE) { + if (revisionid == 0 || revisionid == 1) { + if (revisionid == 0) { + RT_TRACE(rtlpriv, COMP_INIT, + DBG_LOUD, ("Find 92DE MAC0.\n")); + rtlhal->interfaceindex = 0; + } else if (revisionid == 1) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("Find 92DE MAC1.\n")); + rtlhal->interfaceindex = 1; + } + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("Unknown device - " + "VendorID/DeviceID=%x/%x, Revision=%x\n", + venderid, deviceid, revisionid)); + rtlhal->interfaceindex = 0; + } + } /*find bus info */ pcipriv->ndis_adapter.busnumber = pdev->bus->number; pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); @@ -1531,12 +1851,12 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, PCI_SLOT(bridge_pdev->devfn); pcipriv->ndis_adapter.pcibridge_funcnum = PCI_FUNC(bridge_pdev->devfn); - pcipriv->ndis_adapter.pcibridge_pciehdr_offset = - pci_pcie_cap(bridge_pdev); pcipriv->ndis_adapter.pcicfg_addrport = (pcipriv->ndis_adapter.pcibridge_busnum << 16) | (pcipriv->ndis_adapter.pcibridge_devnum << 11) | (pcipriv->ndis_adapter.pcibridge_funcnum << 8) | (1 << 31); + pcipriv->ndis_adapter.pcibridge_pciehdr_offset = + pci_pcie_cap(bridge_pdev); pcipriv->ndis_adapter.num4bytes = (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10) / 4; @@ -1619,6 +1939,11 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, pcipriv = (void *)rtlpriv->priv; pcipriv->dev.pdev = pdev; + /* init cfg & intf_ops */ + rtlpriv->rtlhal.interface = INTF_PCI; + rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); + rtlpriv->intf_ops = &rtl_pci_ops; + /* *init dbgp flags before all *other functions, because we will @@ -1636,13 +1961,14 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, return err; } - pmem_start = pci_resource_start(pdev, 2); - pmem_len = pci_resource_len(pdev, 2); - pmem_flags = pci_resource_flags(pdev, 2); + pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id); + pmem_len = pci_resource_len(pdev, rtlpriv->cfg->bar_id); + pmem_flags = pci_resource_flags(pdev, rtlpriv->cfg->bar_id); /*shared mem start */ rtlpriv->io.pci_mem_start = - (unsigned long)pci_iomap(pdev, 2, pmem_len); + (unsigned long)pci_iomap(pdev, + rtlpriv->cfg->bar_id, pmem_len); if (rtlpriv->io.pci_mem_start == 0) { RT_ASSERT(false, ("Can't map PCI mem\n")); goto fail2; @@ -1661,11 +1987,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, pci_write_config_byte(pdev, 0x04, 0x06); pci_write_config_byte(pdev, 0x04, 0x07); - /* init cfg & intf_ops */ - rtlpriv->rtlhal.interface = INTF_PCI; - rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); - rtlpriv->intf_ops = &rtl_pci_ops; - /* find adapter */ _rtl_pci_find_adapter(pdev, hw); @@ -1783,8 +2104,6 @@ void rtl_pci_disconnect(struct pci_dev *pdev) rtl_pci_deinit(hw); rtl_deinit_core(hw); - if (rtlpriv->cfg->ops->deinit_sw_leds) - rtlpriv->cfg->ops->deinit_sw_leds(hw); _rtl_pci_io_handler_release(hw); rtlpriv->cfg->ops->deinit_sw_vars(hw); @@ -1799,6 +2118,9 @@ void rtl_pci_disconnect(struct pci_dev *pdev) } pci_disable_device(pdev); + + rtl_pci_disable_aspm(hw); + pci_set_drvdata(pdev, NULL); ieee80211_free_hw(hw); @@ -1822,10 +2144,15 @@ no need to call hw_disable here. ****************************************/ int rtl_pci_suspend(struct pci_dev *pdev, pm_message_t state) { + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->cfg->ops->hw_suspend(hw); + rtl_deinit_rfkill(hw); + pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); - return 0; } EXPORT_SYMBOL(rtl_pci_suspend); @@ -1833,6 +2160,8 @@ EXPORT_SYMBOL(rtl_pci_suspend); int rtl_pci_resume(struct pci_dev *pdev) { int ret; + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtl_priv *rtlpriv = rtl_priv(hw); pci_set_power_state(pdev, PCI_D0); ret = pci_enable_device(pdev); @@ -1843,15 +2172,20 @@ int rtl_pci_resume(struct pci_dev *pdev) pci_restore_state(pdev); + rtlpriv->cfg->ops->hw_resume(hw); + rtl_init_rfkill(hw); return 0; } EXPORT_SYMBOL(rtl_pci_resume); struct rtl_intf_ops rtl_pci_ops = { + .read_efuse_byte = read_efuse_byte, .adapter_start = rtl_pci_start, .adapter_stop = rtl_pci_stop, .adapter_tx = rtl_pci_tx, + .flush = rtl_pci_flush, .reset_trx_ring = rtl_pci_reset_trx_ring, + .waitq_insert = rtl_pci_tx_chk_waitq_insert, .disable_aspm = rtl_pci_disable_aspm, .enable_aspm = rtl_pci_enable_aspm, diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h index 12747b9c71e1..671b1f5aa0cf 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/rtlwifi/pci.h @@ -102,8 +102,8 @@ #define RTL_PCI_8191CE_DID 0x8177 /*8192ce */ #define RTL_PCI_8188CE_DID 0x8176 /*8192ce */ #define RTL_PCI_8192CU_DID 0x8191 /*8192ce */ -#define RTL_PCI_8192DE_DID 0x092D /*8192ce */ -#define RTL_PCI_8192DU_DID 0x092D /*8192ce */ +#define RTL_PCI_8192DE_DID 0x8193 /*8192de */ +#define RTL_PCI_8192DE_DID2 0x002B /*92DE*/ /*8192 support 16 pages of IO registers*/ #define RTL_MEM_MAPPED_IO_RANGE_8190PCI 0x1000 @@ -129,6 +129,11 @@ enum pci_bridge_vendor { PCI_BRIDGE_VENDOR_MAX, }; +struct rtl_pci_capabilities_header { + u8 capability_id; + u8 next; +}; + struct rtl_rx_desc { u32 dword[8]; } __packed; @@ -161,7 +166,9 @@ struct rtl_pci { bool driver_is_goingto_unload; bool up_first_time; + bool first_init; bool being_init_adapter; + bool init_ready; bool irq_enabled; /*Tx */ @@ -197,6 +204,9 @@ struct rtl_pci { /*QOS & EDCA */ enum acm_method acm_method; + + u16 shortretry_limit; + u16 longretry_limit; }; struct mp_adapter { @@ -227,6 +237,7 @@ struct rtl_pci_priv { struct rtl_pci dev; struct mp_adapter ndis_adapter; struct rtl_led_ctl ledctl; + struct bt_coexist_info bt_coexist; }; #define rtl_pcipriv(hw) (((struct rtl_pci_priv *)(rtl_priv(hw))->priv)) diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 861849013c54..cb31aefd7c70 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -428,6 +428,10 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw) { } +void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) +{ +} + /*Enter the leisure power save mode.*/ void rtl_lps_enter(struct ieee80211_hw *hw) { -- cgit v1.2.3-58-ga151 From cc7dc0c4ff7c091fb70ff0436f7e3b557e0ac1c3 Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:53:14 -0500 Subject: rtlwifi: Convert ps routines for addition of rtl8192se and rtl8192de Convert ps routines for addition of RTL8192SE and RTL8192DE code Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/ps.c | 274 +++++++++++++++++++++++++++++++++----- drivers/net/wireless/rtlwifi/ps.h | 2 + 2 files changed, 239 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index cb31aefd7c70..2bb71195e976 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -36,7 +36,6 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool init_status = true; /*<1> reset trx ring */ if (rtlhal->interface == INTF_PCI) @@ -49,7 +48,6 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) /*<2> Enable Adapter */ rtlpriv->cfg->ops->hw_init(hw); RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - /*init_status = false; */ /*<3> Enable Interrupt */ rtlpriv->cfg->ops->enable_interrupt(hw); @@ -57,7 +55,7 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) /* */ rtl_watch_dog_timer_callback((unsigned long)hw); - return init_status; + return true; } EXPORT_SYMBOL(rtl_ps_enable_nic); @@ -192,12 +190,13 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) ppsc->swrf_processing = true; - if (ppsc->inactive_pwrstate == ERFON && rtlhal->interface == INTF_PCI) { + if (ppsc->inactive_pwrstate == ERFOFF && + rtlhal->interface == INTF_PCI) { if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM) && + RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && rtlhal->interface == INTF_PCI) { rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } } @@ -206,9 +205,10 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) if (ppsc->inactive_pwrstate == ERFOFF && rtlhal->interface == INTF_PCI) { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && + !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { rtlpriv->intf_ops->enable_aspm(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } } @@ -232,6 +232,9 @@ void rtl_ips_nic_off_wq_callback(void *data) return; } + if (mac->link_state > MAC80211_NOLINK) + return; + if (is_hal_stop(rtlhal)) return; @@ -283,10 +286,14 @@ void rtl_ips_nic_off(struct ieee80211_hw *hw) void rtl_ips_nic_on(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); enum rf_pwrstate rtstate; unsigned long flags; + if (mac->opmode != NL80211_IFTYPE_STATION) + return; + spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags); if (ppsc->inactiveps) { @@ -369,8 +376,7 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) * mode and set RPWM to turn RF on. */ - if ((ppsc->fwctrl_lps) && (ppsc->leisure_ps) && - ppsc->report_linked) { + if ((ppsc->fwctrl_lps) && ppsc->report_linked) { bool fw_current_inps; if (ppsc->dot11_psmode == EACTIVE) { RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, @@ -416,22 +422,6 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) } } -void rtl_swlps_rfon_wq_callback(void *data) -{ -} - -void rtl_swlps_wq_callback(void *data) -{ -} - -void rtl_swlps_rf_awake(struct ieee80211_hw *hw) -{ -} - -void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) -{ -} - /*Enter the leisure power save mode.*/ void rtl_lps_enter(struct ieee80211_hw *hw) { @@ -440,7 +430,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); unsigned long flag; - if (!(ppsc->fwctrl_lps && ppsc->leisure_ps)) + if (!ppsc->fwctrl_lps) return; if (rtlpriv->sec.being_setkey) @@ -461,17 +451,16 @@ void rtl_lps_enter(struct ieee80211_hw *hw) spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - if (ppsc->leisure_ps) { - /* Idle for a while if we connect to AP a while ago. */ - if (mac->cnt_after_linked >= 2) { - if (ppsc->dot11_psmode == EACTIVE) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + /* Idle for a while if we connect to AP a while ago. */ + if (mac->cnt_after_linked >= 2) { + if (ppsc->dot11_psmode == EACTIVE) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("Enter 802.11 power save mode...\n")); - rtl_lps_set_psmode(hw, EAUTOPS); - } + rtl_lps_set_psmode(hw, EAUTOPS); } } + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); } @@ -485,17 +474,17 @@ void rtl_lps_leave(struct ieee80211_hw *hw) spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - if (ppsc->fwctrl_lps && ppsc->leisure_ps) { + if (ppsc->fwctrl_lps) { if (ppsc->dot11_psmode != EACTIVE) { /*FIX ME */ rtlpriv->cfg->ops->enable_interrupt(hw); if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && - RT_IN_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM) && + RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && rtlhal->interface == INTF_PCI) { rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM); + RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, @@ -506,3 +495,214 @@ void rtl_lps_leave(struct ieee80211_hw *hw) } spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); } + +/* For sw LPS*/ +void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct ieee80211_hdr *hdr = (void *) data; + struct ieee80211_tim_ie *tim_ie; + u8 *tim; + u8 tim_len; + bool u_buffed; + bool m_buffed; + + if (mac->opmode != NL80211_IFTYPE_STATION) + return; + + if (!rtlpriv->psc.swctrl_lps) + return; + + if (rtlpriv->mac80211.link_state != MAC80211_LINKED) + return; + + if (!rtlpriv->psc.sw_ps_enabled) + return; + + if (rtlpriv->psc.fwctrl_lps) + return; + + if (likely(!(hw->conf.flags & IEEE80211_CONF_PS))) + return; + + /* check if this really is a beacon */ + if (!ieee80211_is_beacon(hdr->frame_control)) + return; + + /* min. beacon length + FCS_LEN */ + if (len <= 40 + FCS_LEN) + return; + + /* and only beacons from the associated BSSID, please */ + if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) + return; + + rtlpriv->psc.last_beacon = jiffies; + + tim = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_TIM); + if (!tim) + return; + + if (tim[1] < sizeof(*tim_ie)) + return; + + tim_len = tim[1]; + tim_ie = (struct ieee80211_tim_ie *) &tim[2]; + + if (!WARN_ON_ONCE(!hw->conf.ps_dtim_period)) + rtlpriv->psc.dtim_counter = tim_ie->dtim_count; + + /* Check whenever the PHY can be turned off again. */ + + /* 1. What about buffered unicast traffic for our AID? */ + u_buffed = ieee80211_check_tim(tim_ie, tim_len, + rtlpriv->mac80211.assoc_id); + + /* 2. Maybe the AP wants to send multicast/broadcast data? */ + m_buffed = tim_ie->bitmap_ctrl & 0x01; + rtlpriv->psc.multi_buffered = m_buffed; + + /* unicast will process by mac80211 through + * set ~IEEE80211_CONF_PS, So we just check + * multicast frames here */ + if (!m_buffed) { + /* back to low-power land. and delay is + * prevent null power save frame tx fail */ + queue_delayed_work(rtlpriv->works.rtl_wq, + &rtlpriv->works.ps_work, MSECS(5)); + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, ("u_bufferd: %x, " + "m_buffered: %x\n", u_buffed, m_buffed)); + } +} + +void rtl_swlps_rf_awake(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + unsigned long flag; + + if (!rtlpriv->psc.swctrl_lps) + return; + if (mac->link_state != MAC80211_LINKED) + return; + + if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && + RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { + rtlpriv->intf_ops->disable_aspm(hw); + RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + } + + spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); + rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false); + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); +} + +void rtl_swlps_rfon_wq_callback(void *data) +{ + struct rtl_works *rtlworks = + container_of_dwork_rtl(data, struct rtl_works, ps_rfon_wq); + struct ieee80211_hw *hw = rtlworks->hw; + + rtl_swlps_rf_awake(hw); +} + +void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + unsigned long flag; + u8 sleep_intv; + + if (!rtlpriv->psc.sw_ps_enabled) + return; + + if ((rtlpriv->sec.being_setkey) || + (mac->opmode == NL80211_IFTYPE_ADHOC)) + return; + + /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */ + if ((mac->link_state != MAC80211_LINKED) || (mac->cnt_after_linked < 5)) + return; + + if (rtlpriv->link_info.busytraffic) + return; + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + if (rtlpriv->psc.rfchange_inprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + return; + } + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + + spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); + rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS, false); + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && + !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { + rtlpriv->intf_ops->enable_aspm(hw); + RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + } + + /* here is power save alg, when this beacon is DTIM + * we will set sleep time to dtim_period * n; + * when this beacon is not DTIM, we will set sleep + * time to sleep_intv = rtlpriv->psc.dtim_counter or + * MAX_SW_LPS_SLEEP_INTV(default set to 5) */ + + if (rtlpriv->psc.dtim_counter == 0) { + if (hw->conf.ps_dtim_period == 1) + sleep_intv = hw->conf.ps_dtim_period * 2; + else + sleep_intv = hw->conf.ps_dtim_period; + } else { + sleep_intv = rtlpriv->psc.dtim_counter; + } + + if (sleep_intv > MAX_SW_LPS_SLEEP_INTV) + sleep_intv = MAX_SW_LPS_SLEEP_INTV; + + /* this print should always be dtim_conter = 0 & + * sleep = dtim_period, that meaons, we should + * awake before every dtim */ + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + ("dtim_counter:%x will sleep :%d" + " beacon_intv\n", rtlpriv->psc.dtim_counter, sleep_intv)); + + /* we tested that 40ms is enough for sw & hw sw delay */ + queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq, + MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40)); +} + + +void rtl_swlps_wq_callback(void *data) +{ + struct rtl_works *rtlworks = container_of_dwork_rtl(data, + struct rtl_works, + ps_work); + struct ieee80211_hw *hw = rtlworks->hw; + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool ps = false; + + ps = (hw->conf.flags & IEEE80211_CONF_PS); + + /* we can sleep after ps null send ok */ + if (rtlpriv->psc.state_inap) { + rtl_swlps_rf_sleep(hw); + + if (rtlpriv->psc.state && !ps) { + rtlpriv->psc.sleep_ms = jiffies_to_msecs(jiffies - + rtlpriv->psc.last_action); + } + + if (ps) + rtlpriv->psc.last_slept = jiffies; + + rtlpriv->psc.last_action = jiffies; + rtlpriv->psc.state = ps; + } +} diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h index 36aa24d6041f..e3bf89840370 100644 --- a/drivers/net/wireless/rtlwifi/ps.h +++ b/drivers/net/wireless/rtlwifi/ps.h @@ -30,6 +30,8 @@ #ifndef __REALTEK_RTL_PCI_PS_H__ #define __REALTEK_RTL_PCI_PS_H__ +#define MAX_SW_LPS_SLEEP_INTV 5 + bool rtl_ps_set_rf_state(struct ieee80211_hw *hw, enum rf_pwrstate state_toset, u32 changesource, bool protect_or_not); -- cgit v1.2.3-58-ga151 From c6a9de0823e6f1335c93594f7b904f345860dafc Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:53:19 -0500 Subject: rtlwifi: Convert rc routines for addition of rtl8192se and rtl8192de Convert rc routines for addition of RTL8192SE and RTL8192DE code Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rc.c | 212 ++++++++++++++++---------------------- drivers/net/wireless/rtlwifi/rc.h | 9 +- 2 files changed, 95 insertions(+), 126 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c index 91634107434a..30da68a77786 100644 --- a/drivers/net/wireless/rtlwifi/rc.c +++ b/drivers/net/wireless/rtlwifi/rc.c @@ -38,17 +38,14 @@ *CCK11M or OFDM_54M based on wireless mode. */ static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, + struct ieee80211_sta *sta, struct sk_buff *skb, bool not_data) { struct rtl_mac *rtlmac = rtl_mac(rtlpriv); - - /* - *mgt use 1M, although we have check it - *before this function use rate_control_send_low, - *we still check it here - */ - if (not_data) - return rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_sta_info *sta_entry = NULL; + u8 wireless_mode = 0; /* *this rate is no use for true rate, firmware @@ -57,35 +54,78 @@ static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, *2.in rtl_get_tcb_desc when we check rate is * 1M we will not use FW rate but user rate. */ - if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true)) { - return rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; + if (rtlmac->opmode == NL80211_IFTYPE_AP || + rtlmac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta) { + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + wireless_mode = sta_entry->wireless_mode; + } else { + return 0; + } + } else { + wireless_mode = rtlmac->mode; + } + + if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true) || + not_data) { + return 0; } else { - if (rtlmac->mode == WIRELESS_MODE_B) - return rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]; - else - return rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]; + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + if (wireless_mode == WIRELESS_MODE_B) { + return B_MODE_MAX_RIX; + } else if (wireless_mode == WIRELESS_MODE_G) { + return G_MODE_MAX_RIX; + } else { + if (get_rf_type(rtlphy) != RF_2T2R) + return N_MODE_MCS7_RIX; + else + return N_MODE_MCS15_RIX; + } + } else { + if (wireless_mode == WIRELESS_MODE_A) { + return A_MODE_MAX_RIX; + } else { + if (get_rf_type(rtlphy) != RF_2T2R) + return N_MODE_MCS7_RIX; + else + return N_MODE_MCS15_RIX; + } + } } } static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, + struct ieee80211_sta *sta, struct ieee80211_tx_rate *rate, struct ieee80211_tx_rate_control *txrc, - u8 tries, u8 rix, int rtsctsenable, + u8 tries, char rix, int rtsctsenable, bool not_data) { struct rtl_mac *mac = rtl_mac(rtlpriv); + u8 sgi_20 = 0, sgi_40 = 0; + if (sta) { + sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; + sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; + } rate->count = tries; - rate->idx = (rix > 0x2) ? rix : 0x2; + rate->idx = rix >= 0x00 ? rix : 0x00; if (!not_data) { if (txrc->short_preamble) rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; - if (mac->bw_40) - rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (mac->sgi_20 || mac->sgi_40) + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta && (sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40)) + rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + } else { + if (mac->bw_40) + rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + } + if (sgi_20 || sgi_40) rate->flags |= IEEE80211_TX_RC_SHORT_GI; - if (mac->ht_enable) + if (sta && sta->ht_cap.ht_supported) rate->flags |= IEEE80211_TX_RC_MCS; } } @@ -97,39 +137,39 @@ static void rtl_get_rate(void *ppriv, struct ieee80211_sta *sta, struct sk_buff *skb = txrc->skb; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rates = tx_info->control.rates; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - __le16 fc = hdr->frame_control; + __le16 fc = rtl_get_fc(skb); u8 try_per_rate, i, rix; bool not_data = !ieee80211_is_data(fc); if (rate_control_send_low(sta, priv_sta, txrc)) return; - rix = _rtl_rc_get_highest_rix(rtlpriv, skb, not_data); - + rix = _rtl_rc_get_highest_rix(rtlpriv, sta, skb, not_data); try_per_rate = 1; - _rtl_rc_rate_set_series(rtlpriv, &rates[0], txrc, + _rtl_rc_rate_set_series(rtlpriv, sta, &rates[0], txrc, try_per_rate, rix, 1, not_data); if (!not_data) { for (i = 1; i < 4; i++) - _rtl_rc_rate_set_series(rtlpriv, &rates[i], + _rtl_rc_rate_set_series(rtlpriv, sta, &rates[i], txrc, i, (rix - i), 1, not_data); } } -static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, u16 tid) +static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, + struct rtl_sta_info *sta_entry, u16 tid) { struct rtl_mac *mac = rtl_mac(rtlpriv); if (mac->act_scanning) return false; - if (mac->cnt_after_linked < 3) + if (mac->opmode == NL80211_IFTYPE_STATION && + mac->cnt_after_linked < 3) return false; - if (mac->tids[tid].agg.agg_state == RTL_AGG_OFF) + if (sta_entry->tids[tid].agg.agg_state == RTL_AGG_STOP) return true; return false; @@ -143,11 +183,9 @@ static void rtl_tx_status(void *ppriv, { struct rtl_priv *rtlpriv = ppriv; struct rtl_mac *mac = rtl_mac(rtlpriv); - struct ieee80211_hdr *hdr; - __le16 fc; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); + __le16 fc = rtl_get_fc(skb); + struct rtl_sta_info *sta_entry; if (!priv_sta || !ieee80211_is_data(fc)) return; @@ -159,17 +197,21 @@ static void rtl_tx_status(void *ppriv, || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) return; - /* Check if aggregation has to be enabled for this tid */ - if (conf_is_ht(&mac->hw->conf) && - !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { - if (ieee80211_is_data_qos(fc)) { - u8 *qc, tid; - - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; - - if (_rtl_tx_aggr_check(rtlpriv, tid)) - ieee80211_start_tx_ba_session(sta, tid, 5000); + if (sta) { + /* Check if aggregation has to be enabled for this tid */ + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + if ((sta->ht_cap.ht_supported == true) && + !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { + if (ieee80211_is_data_qos(fc)) { + u8 tid = rtl_get_tid(skb); + if (_rtl_tx_aggr_check(rtlpriv, sta_entry, + tid)) { + sta_entry->tids[tid].agg.agg_state = + RTL_AGG_PROGRESS; + ieee80211_start_tx_ba_session(sta, + tid, 5000); + } + } } } } @@ -178,43 +220,6 @@ static void rtl_rate_init(void *ppriv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta) { - struct rtl_priv *rtlpriv = ppriv; - struct rtl_mac *mac = rtl_mac(rtlpriv); - u8 is_ht = conf_is_ht(&mac->hw->conf); - - if ((mac->opmode == NL80211_IFTYPE_STATION) || - (mac->opmode == NL80211_IFTYPE_MESH_POINT) || - (mac->opmode == NL80211_IFTYPE_ADHOC)) { - - switch (sband->band) { - case IEEE80211_BAND_2GHZ: - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_G; - if (is_ht) - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_NGB; - break; - case IEEE80211_BAND_5GHZ: - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_A; - if (is_ht) - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_NGB; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("Invalid band\n")); - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_NGB; - break; - } - - RT_TRACE(rtlpriv, COMP_RATE, DBG_DMESG, - ("Choosing rate table index: %d\n", - rtlpriv->rate_priv->cur_ratetab_idx)); - - } - } static void rtl_rate_update(void *ppriv, @@ -223,49 +228,6 @@ static void rtl_rate_update(void *ppriv, u32 changed, enum nl80211_channel_type oper_chan_type) { - struct rtl_priv *rtlpriv = ppriv; - struct rtl_mac *mac = rtl_mac(rtlpriv); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - bool oper_cw40 = false, oper_sgi40; - bool local_cw40 = mac->bw_40; - bool local_sgi40 = mac->sgi_40; - u8 is_ht = conf_is_ht(&mac->hw->conf); - - if (changed & IEEE80211_RC_HT_CHANGED) { - if (mac->opmode != NL80211_IFTYPE_STATION) - return; - - if (rtlhal->hw->conf.channel_type == NL80211_CHAN_HT40MINUS || - rtlhal->hw->conf.channel_type == NL80211_CHAN_HT40PLUS) - oper_cw40 = true; - - oper_sgi40 = mac->sgi_40; - - if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) { - switch (sband->band) { - case IEEE80211_BAND_2GHZ: - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_G; - if (is_ht) - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_NGB; - break; - case IEEE80211_BAND_5GHZ: - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_A; - if (is_ht) - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_NGB; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Invalid band\n")); - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_NGB; - break; - } - } - } } static void *rtl_rate_alloc(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rtlwifi/rc.h b/drivers/net/wireless/rtlwifi/rc.h index b4667c035f0b..4afa2c20adcf 100644 --- a/drivers/net/wireless/rtlwifi/rc.h +++ b/drivers/net/wireless/rtlwifi/rc.h @@ -30,8 +30,15 @@ #ifndef __RTL_RC_H__ #define __RTL_RC_H__ +#define B_MODE_MAX_RIX 3 +#define G_MODE_MAX_RIX 11 +#define A_MODE_MAX_RIX 7 + +/* in mac80211 mcs0-mcs15 is idx0-idx15*/ +#define N_MODE_MCS7_RIX 7 +#define N_MODE_MCS15_RIX 15 + struct rtl_rate_priv { - u8 cur_ratetab_idx; u8 ht_cap; }; -- cgit v1.2.3-58-ga151 From 81b290451122e93b9731bc333c6be2e49fa5bc0c Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:53:24 -0500 Subject: rtlwifi: Convert regulatory domain routines for addition of rtl8192se and rtl8192de Convert regulatory domain routines for addition of RTL8192SE and RTL8192DE code. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/regd.c | 97 +++++++++++++++++++++++++++++-------- drivers/net/wireless/rtlwifi/regd.h | 2 +- 2 files changed, 78 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c index 3336ca999dfd..714858abc4ac 100644 --- a/drivers/net/wireless/rtlwifi/regd.c +++ b/drivers/net/wireless/rtlwifi/regd.c @@ -66,31 +66,83 @@ static struct country_code_to_enum_rd allCountries[] = { NL80211_RRF_PASSIVE_SCAN | \ NL80211_RRF_NO_OFDM) +/* 5G chan 36 - chan 64*/ +#define RTL819x_5GHZ_5150_5350 \ + REG_RULE(5150-10, 5350+10, 40, 0, 30, \ + NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_NO_IBSS) + +/* 5G chan 100 - chan 165*/ +#define RTL819x_5GHZ_5470_5850 \ + REG_RULE(5470-10, 5850+10, 40, 0, 30, \ + NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_NO_IBSS) + +/* 5G chan 149 - chan 165*/ +#define RTL819x_5GHZ_5725_5850 \ + REG_RULE(5725-10, 5850+10, 40, 0, 30, \ + NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_NO_IBSS) + +#define RTL819x_5GHZ_ALL \ + (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850) + static const struct ieee80211_regdomain rtl_regdom_11 = { .n_reg_rules = 1, .alpha2 = "99", .reg_rules = { RTL819x_2GHZ_CH01_11, - } + } +}; + +static const struct ieee80211_regdomain rtl_regdom_12_13 = { + .n_reg_rules = 2, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + } }; -static const struct ieee80211_regdomain rtl_regdom_global = { +static const struct ieee80211_regdomain rtl_regdom_no_midband = { .n_reg_rules = 3, .alpha2 = "99", .reg_rules = { RTL819x_2GHZ_CH01_11, - RTL819x_2GHZ_CH12_13, - RTL819x_2GHZ_CH14, - } + RTL819x_5GHZ_5150_5350, + RTL819x_5GHZ_5725_5850, + } }; -static const struct ieee80211_regdomain rtl_regdom_world = { - .n_reg_rules = 2, +static const struct ieee80211_regdomain rtl_regdom_60_64 = { + .n_reg_rules = 3, .alpha2 = "99", .reg_rules = { RTL819x_2GHZ_CH01_11, - RTL819x_2GHZ_CH12_13, - } + RTL819x_2GHZ_CH12_13, + RTL819x_5GHZ_5725_5850, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_14_60_64 = { + .n_reg_rules = 4, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + RTL819x_2GHZ_CH14, + RTL819x_5GHZ_5725_5850, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_14 = { + .n_reg_rules = 3, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + RTL819x_2GHZ_CH14, + } }; static bool _rtl_is_radar_freq(u16 center_freq) @@ -162,6 +214,8 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, u32 bandwidth = 0; int r; + if (!wiphy->bands[IEEE80211_BAND_2GHZ]) + return; sband = wiphy->bands[IEEE80211_BAND_2GHZ]; /* @@ -292,25 +346,26 @@ static const struct ieee80211_regdomain *_rtl_regdomain_select( { switch (reg->country_code) { case COUNTRY_CODE_FCC: + return &rtl_regdom_no_midband; case COUNTRY_CODE_IC: return &rtl_regdom_11; case COUNTRY_CODE_ETSI: + case COUNTRY_CODE_TELEC_NETGEAR: + return &rtl_regdom_60_64; case COUNTRY_CODE_SPAIN: case COUNTRY_CODE_FRANCE: case COUNTRY_CODE_ISRAEL: - case COUNTRY_CODE_TELEC_NETGEAR: - return &rtl_regdom_world; + case COUNTRY_CODE_WORLD_WIDE_13: + return &rtl_regdom_12_13; case COUNTRY_CODE_MKK: case COUNTRY_CODE_MKK1: case COUNTRY_CODE_TELEC: case COUNTRY_CODE_MIC: - return &rtl_regdom_global; + return &rtl_regdom_14_60_64; case COUNTRY_CODE_GLOBAL_DOMAIN: - return &rtl_regdom_global; - case COUNTRY_CODE_WORLD_WIDE_13: - return &rtl_regdom_world; + return &rtl_regdom_14; default: - return &rtl_regdom_world; + return &rtl_regdom_no_midband; } } @@ -323,9 +378,11 @@ static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg, const struct ieee80211_regdomain *regd; wiphy->reg_notifier = reg_notifier; + wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY; wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS; + regd = _rtl_regdomain_select(reg); wiphy_apply_custom_regulatory(wiphy, regd); _rtl_reg_apply_radar_flags(wiphy); @@ -355,8 +412,8 @@ int rtl_regd_init(struct ieee80211_hw *hw, if (wiphy == NULL || &rtlpriv->regd == NULL) return -EINVAL; - /* force the channel plan to world wide 13 */ - rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13; + /* init country_code from efuse channel plan */ + rtlpriv->regd.country_code = rtlpriv->efuse.channel_plan; RT_TRACE(rtlpriv, COMP_REGD, DBG_TRACE, (KERN_DEBUG "rtl: EEPROM regdomain: 0x%0x\n", @@ -373,8 +430,8 @@ int rtl_regd_init(struct ieee80211_hw *hw, country = _rtl_regd_find_country(rtlpriv->regd.country_code); if (country) { - rtlpriv->regd.alpha2[0] = country->isoName[0]; - rtlpriv->regd.alpha2[1] = country->isoName[1]; + rtlpriv->regd.alpha2[0] = country->iso_name[0]; + rtlpriv->regd.alpha2[1] = country->iso_name[1]; } else { rtlpriv->regd.alpha2[0] = '0'; rtlpriv->regd.alpha2[1] = '0'; diff --git a/drivers/net/wireless/rtlwifi/regd.h b/drivers/net/wireless/rtlwifi/regd.h index 4cdbc4ae76d4..d23118938fac 100644 --- a/drivers/net/wireless/rtlwifi/regd.h +++ b/drivers/net/wireless/rtlwifi/regd.h @@ -32,7 +32,7 @@ struct country_code_to_enum_rd { u16 countrycode; - const char *isoName; + const char *iso_name; }; enum country_code_type_t { -- cgit v1.2.3-58-ga151 From d93cdee975bc6894b0a7c3f3eb4f2b34303163f8 Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:53:29 -0500 Subject: rtlwifi: Convert usb routines for addition of rtl8192se and rtl8192de Convert usb routines for addition of RTL8192SE and RTL8192DE code Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 2 -- drivers/net/wireless/rtlwifi/usb.c | 14 +++++++++++++- drivers/net/wireless/rtlwifi/wifi.h | 7 ------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index fa66205d8b95..e496361fa2c6 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1569,10 +1569,8 @@ int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb, if (ieee80211_is_data(fc)) rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); -#if 0 /* temporary */ rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, info, skb, hw_queue, ptcb_desc); -#endif __skb_queue_tail(&ring->queue, skb); diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 14539eb9589e..a9367eba1ea7 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -852,6 +852,7 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct rtl_tx_desc *pdesc = NULL; + struct rtl_tcb_desc tcb_desc; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); __le16 fc = hdr->frame_control; u8 *pda_addr = hdr->addr1; @@ -860,6 +861,17 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, u8 tid = 0; u16 seq_number = 0; + if (ieee80211_is_auth(fc)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); + rtl_ips_nic_on(hw); + } + + if (rtlpriv->psc.sw_ps_enabled) { + if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && + !ieee80211_has_pm(fc)) + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); + } + rtl_action_proc(hw, skb, true); if (is_multicast_ether_addr(pda_addr)) rtlpriv->stats.txbytesmulticast += skb->len; @@ -876,7 +888,7 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, seq_number <<= 4; } rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, info, skb, - hw_queue); + hw_queue, &tcb_desc); if (!ieee80211_has_morefrags(hdr->frame_control)) { if (qc) mac->tids[tid].seq_number = seq_number; diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 4776cd1ee4f8..683f7f71b6cd 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -1378,18 +1378,11 @@ struct rtl_hal_ops { void (*update_rate_table) (struct ieee80211_hw *hw); #endif void (*update_rate_mask) (struct ieee80211_hw *hw, u8 rssi_level); -#if 0 /* temporary */ void (*fill_tx_desc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, struct sk_buff *skb, u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); -#else - void (*fill_tx_desc) (struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - struct ieee80211_tx_info *info, - struct sk_buff *skb, unsigned int queue_index); -#endif void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 *pDesc, u32 buffer_len, bool bIsPsPoll); void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc, -- cgit v1.2.3-58-ga151 From beb5bc4020436ee50bd50e82c5a64eb087f0e3b3 Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:53:35 -0500 Subject: rtlwifi: rtl8192c-common: Convert common dynamic management routines for addition of rtl8192se and rtl8192de Convert common dynamic management routines for addition of RTL8192SE and RTL8192DE code. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 466 +++++++++++++++++++++- drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h | 2 + 2 files changed, 447 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index 5ea3a5ef819b..2836d7eb0d05 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -28,10 +28,26 @@ *****************************************************************************/ #include "dm_common.h" +#include "phy_common.h" +#include "../pci.h" +#include "../base.h" struct dig_t dm_digtable; static struct ps_t dm_pstable; +#define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1) +#define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1) +#define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1) +#define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1) +#define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1) + +#define RTLPRIV (struct rtl_priv *) +#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \ + ((RTLPRIV(_priv))->mac80211.opmode == \ + NL80211_IFTYPE_ADHOC) ? \ + ((RTLPRIV(_priv))->dm.entry_min_undecoratedsmoothed_pwdb) : \ + ((RTLPRIV(_priv))->dm.undecorated_smoothed_pwdb) + static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { 0x7f8001fe, 0x788001e2, @@ -461,10 +477,7 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) if (mac->act_scanning == true) return; - if ((mac->link_state > MAC80211_NOLINK) && - (mac->link_state < MAC80211_LINKED)) - dm_digtable.cursta_connectctate = DIG_STA_BEFORE_CONNECT; - else if (mac->link_state >= MAC80211_LINKED) + if (mac->link_state >= MAC80211_LINKED) dm_digtable.cursta_connectctate = DIG_STA_CONNECT; else dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT; @@ -562,23 +575,42 @@ EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo); static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + static u64 last_txok_cnt; static u64 last_rxok_cnt; - u64 cur_txok_cnt; - u64 cur_rxok_cnt; + static u32 last_bt_edca_ul; + static u32 last_bt_edca_dl; + u64 cur_txok_cnt = 0; + u64 cur_rxok_cnt = 0; u32 edca_be_ul = 0x5ea42b; u32 edca_be_dl = 0x5ea42b; + bool bt_change_edca = false; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - goto dm_checkedcaturbo_exit; + if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) || + (last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) { + rtlpriv->dm.current_turbo_edca = false; + last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul; + last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl; + } + + if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) { + edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul; + bt_change_edca = true; + } + + if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) { + edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl; + bt_change_edca = true; + } if (mac->link_state != MAC80211_LINKED) { rtlpriv->dm.current_turbo_edca = false; return; } - if (!mac->ht_enable) { /*FIX MERGE */ + if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) { if (!(edca_be_ul & 0xffff0000)) edca_be_ul |= 0x005e0000; @@ -586,10 +618,12 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) edca_be_dl |= 0x005e0000; } - if ((!rtlpriv->dm.is_any_nonbepkts) && - (!rtlpriv->dm.disable_framebursting)) { + if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) && + (!rtlpriv->dm.disable_framebursting))) { + cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; + if (cur_rxok_cnt > 4 * cur_txok_cnt) { if (!rtlpriv->dm.is_cur_rdlstate || !rtlpriv->dm.current_turbo_edca) { @@ -618,7 +652,6 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) } } -dm_checkedcaturbo_exit: rtlpriv->dm.is_any_nonbepkts = false; last_txok_cnt = rtlpriv->stats.txbytesunicast; last_rxok_cnt = rtlpriv->stats.rxbytesunicast; @@ -633,7 +666,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); u8 thermalvalue, delta, delta_lck, delta_iqk; long ele_a, ele_d, temp_cck, val_x, value32; - long val_y, ele_c; + long val_y, ele_c = 0; u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0; int i; bool is2t = IS_92C_SERIAL(rtlhal->version); @@ -683,7 +716,6 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw for (i = 0; i < OFDM_TABLE_LENGTH; i++) { if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { - ofdm_index_old[1] = (u8) i; RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, @@ -1132,6 +1164,7 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rate_adaptive *p_ra = &(rtlpriv->ra); u32 low_rssithresh_for_ra, high_rssithresh_for_ra; + struct ieee80211_sta *sta = NULL; if (is_hal_stop(rtlhal)) { RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, @@ -1145,8 +1178,8 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) return; } - if (mac->link_state == MAC80211_LINKED) { - + if (mac->link_state == MAC80211_LINKED && + mac->opmode == NL80211_IFTYPE_STATION) { switch (p_ra->pre_ratr_state) { case DM_RATR_STA_HIGH: high_rssithresh_for_ra = 50; @@ -1185,10 +1218,13 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) ("PreState = %d, CurState = %d\n", p_ra->pre_ratr_state, p_ra->ratr_state)); - rtlpriv->cfg->ops->update_rate_mask(hw, + rcu_read_lock(); + sta = ieee80211_find_sta(mac->vif, mac->bssid); + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, p_ra->ratr_state); p_ra->pre_ratr_state = p_ra->ratr_state; + rcu_read_unlock(); } } } @@ -1202,7 +1238,7 @@ static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) dm_pstable.rssi_val_min = 0; } -static void rtl92c_dm_1r_cca(struct ieee80211_hw *hw) +void rtl92c_dm_1r_cca(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -1352,7 +1388,9 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) } if (IS_92C_SERIAL(rtlhal->version)) - rtl92c_dm_1r_cca(hw); + ;/* rtl92c_dm_1r_cca(hw); */ + else + rtl92c_dm_rf_saving(hw, false); } void rtl92c_dm_init(struct ieee80211_hw *hw) @@ -1369,6 +1407,84 @@ void rtl92c_dm_init(struct ieee80211_hw *hw) } EXPORT_SYMBOL(rtl92c_dm_init); +void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undecorated_smoothed_pwdb; + + if (!rtlpriv->dm.dynamic_txpower_enable) + return; + + if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + ("Not connected to any\n")); + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + undecorated_smoothed_pwdb = + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("AP Client PWDB = 0x%lx\n", + undecorated_smoothed_pwdb)); + } else { + undecorated_smoothed_pwdb = + rtlpriv->dm.undecorated_smoothed_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("STA Default Port PWDB = 0x%lx\n", + undecorated_smoothed_pwdb)); + } + } else { + undecorated_smoothed_pwdb = + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("AP Ext Port PWDB = 0x%lx\n", + undecorated_smoothed_pwdb)); + } + + if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n")); + } else if ((undecorated_smoothed_pwdb < + (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && + (undecorated_smoothed_pwdb >= + TX_POWER_NEAR_FIELD_THRESH_LVL1)) { + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n")); + } else if (undecorated_smoothed_pwdb < + (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("TXHIGHPWRLEVEL_NORMAL\n")); + } + + if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("PHY_SetTxPowerLevel8192S() Channel = %d\n", + rtlphy->current_channel)); + rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); + } + + rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; +} + void rtl92c_dm_watchdog(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -1388,11 +1504,319 @@ void rtl92c_dm_watchdog(struct ieee80211_hw *hw) rtl92c_dm_dig(hw); rtl92c_dm_false_alarm_counter_statistics(hw); rtl92c_dm_dynamic_bb_powersaving(hw); - rtlpriv->cfg->ops->dm_dynamic_txpower(hw); + rtl92c_dm_dynamic_txpower(hw); rtl92c_dm_check_txpower_tracking(hw); rtl92c_dm_refresh_rate_adaptive_mask(hw); + rtl92c_dm_bt_coexist(hw); rtl92c_dm_check_edca_turbo(hw); - } } EXPORT_SYMBOL(rtl92c_dm_watchdog); + +static u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + long undecorated_smoothed_pwdb; + u8 curr_bt_rssi_state = 0x00; + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + undecorated_smoothed_pwdb = + GET_UNDECORATED_AVERAGE_RSSI(rtlpriv); + } else { + if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0) + undecorated_smoothed_pwdb = 100; + else + undecorated_smoothed_pwdb = + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + } + + /* Check RSSI to determine HighPower/NormalPower state for + * BT coexistence. */ + if (undecorated_smoothed_pwdb >= 67) + curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER); + else if (undecorated_smoothed_pwdb < 62) + curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER; + + /* Check RSSI to determine AMPDU setting for BT coexistence. */ + if (undecorated_smoothed_pwdb >= 40) + curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF); + else if (undecorated_smoothed_pwdb <= 32) + curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF; + + /* Marked RSSI state. It will be used to determine BT coexistence + * setting later. */ + if (undecorated_smoothed_pwdb < 35) + curr_bt_rssi_state |= BT_RSSI_STATE_SPECIAL_LOW; + else + curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW); + + /* Set Tx Power according to BT status. */ + if (undecorated_smoothed_pwdb >= 30) + curr_bt_rssi_state |= BT_RSSI_STATE_TXPOWER_LOW; + else if (undecorated_smoothed_pwdb < 25) + curr_bt_rssi_state &= (~BT_RSSI_STATE_TXPOWER_LOW); + + /* Check BT state related to BT_Idle in B/G mode. */ + if (undecorated_smoothed_pwdb < 15) + curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW; + else + curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW); + + if (curr_bt_rssi_state != rtlpcipriv->bt_coexist.bt_rssi_state) { + rtlpcipriv->bt_coexist.bt_rssi_state = curr_bt_rssi_state; + return true; + } else { + return false; + } +} + +static bool rtl92c_bt_state_change(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + u32 polling, ratio_tx, ratio_pri; + u32 bt_tx, bt_pri; + u8 bt_state; + u8 cur_service_type; + + if (rtlpriv->mac80211.link_state < MAC80211_LINKED) + return false; + + bt_state = rtl_read_byte(rtlpriv, 0x4fd); + bt_tx = rtl_read_dword(rtlpriv, 0x488); + bt_tx = bt_tx & 0x00ffffff; + bt_pri = rtl_read_dword(rtlpriv, 0x48c); + bt_pri = bt_pri & 0x00ffffff; + polling = rtl_read_dword(rtlpriv, 0x490); + + if (bt_tx == 0xffffffff && bt_pri == 0xffffffff && + polling == 0xffffffff && bt_state == 0xff) + return false; + + bt_state &= BIT_OFFSET_LEN_MASK_32(0, 1); + if (bt_state != rtlpcipriv->bt_coexist.bt_cur_state) { + rtlpcipriv->bt_coexist.bt_cur_state = bt_state; + + if (rtlpcipriv->bt_coexist.reg_bt_sco == 3) { + rtlpcipriv->bt_coexist.bt_service = BT_IDLE; + + bt_state = bt_state | + ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? + 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | + BIT_OFFSET_LEN_MASK_32(2, 1); + rtl_write_byte(rtlpriv, 0x4fd, bt_state); + } + return true; + } + + ratio_tx = bt_tx * 1000 / polling; + ratio_pri = bt_pri * 1000 / polling; + rtlpcipriv->bt_coexist.ratio_tx = ratio_tx; + rtlpcipriv->bt_coexist.ratio_pri = ratio_pri; + + if (bt_state && rtlpcipriv->bt_coexist.reg_bt_sco == 3) { + + if ((ratio_tx < 30) && (ratio_pri < 30)) + cur_service_type = BT_IDLE; + else if ((ratio_pri > 110) && (ratio_pri < 250)) + cur_service_type = BT_SCO; + else if ((ratio_tx >= 200) && (ratio_pri >= 200)) + cur_service_type = BT_BUSY; + else if ((ratio_tx >= 350) && (ratio_tx < 500)) + cur_service_type = BT_OTHERBUSY; + else if (ratio_tx >= 500) + cur_service_type = BT_PAN; + else + cur_service_type = BT_OTHER_ACTION; + + if (cur_service_type != rtlpcipriv->bt_coexist.bt_service) { + rtlpcipriv->bt_coexist.bt_service = cur_service_type; + bt_state = bt_state | + ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? + 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | + ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) ? + 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); + + /* Add interrupt migration when bt is not ini + * idle state (no traffic). */ + if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { + rtl_write_word(rtlpriv, 0x504, 0x0ccc); + rtl_write_byte(rtlpriv, 0x506, 0x54); + rtl_write_byte(rtlpriv, 0x507, 0x54); + } else { + rtl_write_byte(rtlpriv, 0x506, 0x00); + rtl_write_byte(rtlpriv, 0x507, 0x00); + } + + rtl_write_byte(rtlpriv, 0x4fd, bt_state); + return true; + } + } + + return false; + +} + +static bool rtl92c_bt_wifi_connect_change(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + static bool media_connect; + + if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { + media_connect = false; + } else { + if (!media_connect) { + media_connect = true; + return true; + } + media_connect = true; + } + + return false; +} + +static void rtl92c_bt_set_normal(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + + if (rtlpcipriv->bt_coexist.bt_service == BT_OTHERBUSY) { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72b; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72b; + } else if (rtlpcipriv->bt_coexist.bt_service == BT_BUSY) { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82f; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82f; + } else if (rtlpcipriv->bt_coexist.bt_service == BT_SCO) { + if (rtlpcipriv->bt_coexist.ratio_tx > 160) { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72f; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72f; + } else { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea32b; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea42b; + } + } else { + rtlpcipriv->bt_coexist.bt_edca_ul = 0; + rtlpcipriv->bt_coexist.bt_edca_dl = 0; + } + + if ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) && + (rtlpriv->mac80211.mode == WIRELESS_MODE_G || + (rtlpriv->mac80211.mode == (WIRELESS_MODE_G | WIRELESS_MODE_B))) && + (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_BG_EDCA_LOW)) { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82b; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82b; + } +} + +static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + + /* Only enable HW BT coexist when BT in "Busy" state. */ + if (rtlpriv->mac80211.vendor == PEER_CISCO && + rtlpcipriv->bt_coexist.bt_service == BT_OTHER_ACTION) { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); + } else { + if ((rtlpcipriv->bt_coexist.bt_service == BT_BUSY) && + (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_NORMAL_POWER)) { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); + } else if ((rtlpcipriv->bt_coexist.bt_service == + BT_OTHER_ACTION) && (rtlpriv->mac80211.mode < + WIRELESS_MODE_N_24G) && + (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_SPECIAL_LOW)) { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); + } else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); + } else { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); + } + } + + if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x10100); + else + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x0); + + if (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_NORMAL_POWER) { + rtl92c_bt_set_normal(hw); + } else { + rtlpcipriv->bt_coexist.bt_edca_ul = 0; + rtlpcipriv->bt_coexist.bt_edca_dl = 0; + } + + if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { + rtlpriv->cfg->ops->set_rfreg(hw, + RF90_PATH_A, + 0x1e, + 0xf0, 0xf); + } else { + rtlpriv->cfg->ops->set_rfreg(hw, + RF90_PATH_A, 0x1e, 0xf0, + rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); + } + + if (!rtlpriv->dm.dynamic_txpower_enable) { + if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { + if (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_TXPOWER_LOW) { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_BT2; + } else { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_BT1; + } + } else { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_NORMAL; + } + rtl92c_phy_set_txpower_level(hw, + rtlpriv->phy.current_channel); + } +} + +static void rtl92c_check_bt_change(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + if (rtlpcipriv->bt_coexist.bt_cur_state) { + if (rtlpcipriv->bt_coexist.bt_ant_isolation) + rtl92c_bt_ant_isolation(hw); + } else { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); + rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0, + rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); + + rtlpcipriv->bt_coexist.bt_edca_ul = 0; + rtlpcipriv->bt_coexist.bt_edca_dl = 0; + } +} + +void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + bool wifi_connect_change; + bool bt_state_change; + bool rssi_state_change; + + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) { + + wifi_connect_change = rtl92c_bt_wifi_connect_change(hw); + bt_state_change = rtl92c_bt_state_change(hw); + rssi_state_change = rtl92c_bt_rssi_state_change(hw); + + if (wifi_connect_change || bt_state_change || rssi_state_change) + rtl92c_check_bt_change(hw); + } +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h index b9cbb0a3c03f..b9736d3e9a39 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h @@ -200,5 +200,7 @@ void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery); +void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw); +void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); #endif -- cgit v1.2.3-58-ga151 From 3ac5e26a1e935469a8bdae1d624bc3b59d1fcdc5 Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:53:40 -0500 Subject: rtlwifi: rtl8192c-common: Change common firmware routines for addition of rtl8192se and rtl8192de Change common firmware routines for addition of RTL8192SE and RTL8192DE code. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 81 ++++++++++++++--------- drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h | 4 +- 2 files changed, 52 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index bc9d24134ac4..50303e1adff1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c @@ -223,29 +223,15 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) u8 *pfwdata; u32 fwsize; enum version_8192c version = rtlhal->version; - const struct firmware *firmware; printk(KERN_INFO "rtl8192c: Loading firmware file %s\n", rtlpriv->cfg->fw_name); - if (request_firmware(&firmware, rtlpriv->cfg->fw_name, - rtlpriv->io.dev)) { - printk(KERN_ERR "rtl8192c: Firmware loading failed\n"); + if (!rtlhal->pfirmware) return 1; - } - - if (firmware->size > 0x4000) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Firmware is too big!\n")); - release_firmware(firmware); - return 1; - } - - memcpy(rtlhal->pfirmware, firmware->data, firmware->size); - fwsize = firmware->size; - release_firmware(firmware); pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; pfwdata = (u8 *) rtlhal->pfirmware; + fwsize = rtlhal->fwsize; if (IS_FW_HEADER_EXIST(pfwheader)) { RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, @@ -553,6 +539,39 @@ void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) } EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd); +static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring; + struct rtl_tx_desc *pdesc; + u8 own; + unsigned long flags; + struct sk_buff *pskb = NULL; + + ring = &rtlpci->tx_ring[BEACON_QUEUE]; + + pskb = __skb_dequeue(&ring->queue); + if (pskb) + kfree_skb(pskb); + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + + pdesc = &ring->desc[0]; + own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN); + + rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); + + __skb_queue_tail(&ring->queue, skb); + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + + rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); + + return true; +} + #define BEACON_PG 0 /*->1*/ #define PSPOLL_PG 2 #define NULL_PG 3 @@ -670,7 +689,7 @@ static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) +void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); @@ -679,12 +698,12 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) u32 totalpacketlen; bool rtstatus; u8 u1RsvdPageLoc[3] = {0}; - bool b_dlok = false; + bool dlok = false; u8 *beacon; - u8 *p_pspoll; + u8 *pspoll; u8 *nullfunc; - u8 *p_probersp; + u8 *probersp; /*--------------------------------------------------------- (1) beacon ---------------------------------------------------------*/ @@ -695,10 +714,10 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) /*------------------------------------------------------- (2) ps-poll --------------------------------------------------------*/ - p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; - SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); - SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); - SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); + pspoll = &reserved_page_packet[PSPOLL_PG * 128]; + SET_80211_PS_POLL_AID(pspoll, (mac->assoc_id | 0xc000)); + SET_80211_PS_POLL_BSSID(pspoll, mac->bssid); + SET_80211_PS_POLL_TA(pspoll, mac->mac_addr); SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); @@ -715,10 +734,10 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) /*--------------------------------------------------------- (4) probe response ----------------------------------------------------------*/ - p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; - SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); - SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); - SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); + probersp = &reserved_page_packet[PROBERSP_PG * 128]; + SET_80211_HDR_ADDRESS1(probersp, mac->bssid); + SET_80211_HDR_ADDRESS2(probersp, mac->mac_addr); + SET_80211_HDR_ADDRESS3(probersp, mac->bssid); SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG); @@ -736,12 +755,12 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) memcpy((u8 *) skb_put(skb, totalpacketlen), &reserved_page_packet, totalpacketlen); - rtstatus = rtlpriv->cfg->ops->cmd_send_packet(hw, skb); + rtstatus = _rtl92c_cmd_send_packet(hw, skb); if (rtstatus) - b_dlok = true; + dlok = true; - if (b_dlok) { + if (dlok) { RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("Set RSVD page location to Fw.\n")); RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h index 3db33bd14666..3d5823c12621 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h @@ -27,8 +27,8 @@ * *****************************************************************************/ -#ifndef __RTL92C__FW__H__ -#define __RTL92C__FW__H__ +#ifndef __RTL92C__FW__COMMON__H__ +#define __RTL92C__FW__COMMON__H__ #define FW_8192C_SIZE 0x3000 #define FW_8192C_START_ADDRESS 0x1000 -- cgit v1.2.3-58-ga151 From c07ccff326a2b3d81520e8c7a8e0f5e8cbc77416 Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:53:45 -0500 Subject: rtlwifi: rtl8192c-common: Change common PHY routines for addition of rtl8192se and rtl8192de Change common PHY routines for addition of RTL8192SE and RTL8192DE code. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c | 119 ++++++++++----------- drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h | 60 +++++------ 2 files changed, 83 insertions(+), 96 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index a70228278398..3915a1ba59fb 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c @@ -78,18 +78,20 @@ void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," " data(%#x)\n", regaddr, bitmask, data)); + } EXPORT_SYMBOL(rtl92c_phy_set_bb_reg); -u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, +static u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset) { RT_ASSERT(false, ("deprecated!\n")); return 0; + } EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_read); -void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, +static void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset, u32 data) { @@ -97,7 +99,7 @@ void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, } EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_write); -u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, +static u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -148,7 +150,7 @@ u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, } EXPORT_SYMBOL(_rtl92c_phy_rf_serial_read); -void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, +static void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset, u32 data) { @@ -197,6 +199,7 @@ static void _rtl92c_phy_bb_config_1t(struct ieee80211_hw *hw) rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2); rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2); } + bool rtl92c_phy_rf_config(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -205,7 +208,7 @@ bool rtl92c_phy_rf_config(struct ieee80211_hw *hw) } EXPORT_SYMBOL(rtl92c_phy_rf_config); -bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) +static bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -241,6 +244,7 @@ bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, 0x200)); + return true; } EXPORT_SYMBOL(_rtl92c_phy_bb8192c_config_parafile); @@ -317,61 +321,48 @@ void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, } if (regaddr == RTXAGC_B_RATE54_24) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9])); } - if (regaddr == RTXAGC_B_CCK1_55_MCS32) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14])); } - if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15])); } - if (regaddr == RTXAGC_B_MCS03_MCS00) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10])); } - if (regaddr == RTXAGC_B_MCS07_MCS04) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11])); } - if (regaddr == RTXAGC_B_MCS11_MCS08) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12])); } - if (regaddr == RTXAGC_B_MCS15_MCS12) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][13] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", rtlphy->pwrgroup_cnt, @@ -583,6 +574,7 @@ static void _rtl92c_ccxpower_index_check(struct ieee80211_hw *hw, rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; + } void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) @@ -611,7 +603,6 @@ bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm) struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); u8 idx; u8 rf_path; - u8 ccktxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw, WIRELESS_MODE_B, power_indbm); @@ -639,11 +630,6 @@ bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm) } EXPORT_SYMBOL(rtl92c_phy_update_txpower_dbm); -void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval) -{ -} -EXPORT_SYMBOL(rtl92c_phy_set_beacon_hw_reg); - u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw, enum wireless_mode wirelessmode, long power_indbm) @@ -741,9 +727,9 @@ void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, if (rtlphy->set_bwmode_inprogress) return; rtlphy->set_bwmode_inprogress = true; - if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) - rtlpriv->cfg->ops->phy_set_bw_mode_callback(hw); - else { + if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtlphy->set_bwmode_inprogress = false; + } else { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("FALSE driver sleep or unload\n")); rtlphy->set_bwmode_inprogress = false; @@ -773,8 +759,9 @@ void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw) mdelay(delay); else continue; - } else + } else { rtlphy->sw_chnl_inprogress = false; + } break; } while (true); RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); @@ -811,9 +798,32 @@ u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw) } EXPORT_SYMBOL(rtl92c_phy_sw_chnl); -static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay) +static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, + enum swchnlcmd_id cmdid, + u32 para1, u32 para2, u32 msdelay) +{ + struct swchnlcmd *pcmd; + + if (cmdtable == NULL) { + RT_ASSERT(false, ("cmdtable cannot be NULL.\n")); + return false; + } + + if (cmdtableidx >= cmdtablesz) + return false; + + pcmd = cmdtable + cmdtableidx; + pcmd->cmdid = cmdid; + pcmd->para1 = para1; + pcmd->para2 = para2; + pcmd->msdelay = msdelay; + return true; +} + +bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -917,29 +927,6 @@ static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, return false; } -static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, u32 cmdtablesz, - enum swchnlcmd_id cmdid, - u32 para1, u32 para2, u32 msdelay) -{ - struct swchnlcmd *pcmd; - - if (cmdtable == NULL) { - RT_ASSERT(false, ("cmdtable cannot be NULL.\n")); - return false; - } - - if (cmdtableidx >= cmdtablesz) - return false; - - pcmd = cmdtable + cmdtableidx; - pcmd->cmdid = cmdid; - pcmd->para1 = para1; - pcmd->para2 = para2; - pcmd->msdelay = msdelay; - return true; -} - bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath) { return true; @@ -1002,13 +989,13 @@ static u8 _rtl92c_phy_path_b_iqk(struct ieee80211_hw *hw) reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); + if (!(reg_eac & BIT(31)) && (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) result |= 0x01; else return result; - if (!(reg_eac & BIT(30)) && (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) @@ -1023,9 +1010,9 @@ static void _rtl92c_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, u32 oldval_0, x, tx0_a, reg; long y, tx0_c; - if (final_candidate == 0xFF) + if (final_candidate == 0xFF) { return; - else if (iqk_ok) { + } else if (iqk_ok) { oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD) >> 22) & 0x3FF; x = result[final_candidate][0]; @@ -1063,9 +1050,9 @@ static void _rtl92c_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw, u32 oldval_1, x, tx1_a, reg; long y, tx1_c; - if (final_candidate == 0xFF) + if (final_candidate == 0xFF) { return; - else if (iqk_ok) { + } else if (iqk_ok) { oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD) >> 22) & 0x3FF; x = result[final_candidate][4]; @@ -1282,6 +1269,7 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, RFPGA0_XA_HSSIPARAMETER1, BIT(8)); } + if (!rtlphy->rfpi_enable) _rtl92c_phy_pi_mode_switch(hw, true); if (t == 0) { @@ -1317,9 +1305,10 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, 0x3FF0000) >> 16; break; } else if (i == (retrycount - 1) && patha_ok == 0x01) + result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & 0x3FF0000) >> - 16; + 16; result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16; @@ -1434,7 +1423,7 @@ static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, 0x04db25a4, 0x0b1b25a4 }; - u32 apk_offset[PATH_NUM] = { 0xb68, 0xb6c }; + const u32 apk_offset[PATH_NUM] = { 0xb68, 0xb6c }; u32 apk_normal_offset[PATH_NUM] = { 0xb28, 0xb98 }; @@ -1463,13 +1452,15 @@ static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, 0x00050006 }; - const u32 apk_result[PATH_NUM][APK_BB_REG_NUM]; + u32 apk_result[PATH_NUM][APK_BB_REG_NUM]; long bb_offset, delta_v, delta_offset; if (!is2t) pathbound = 1; + return; + for (index = 0; index < PATH_NUM; index++) { apk_offset[index] = apk_normal_offset[index]; apk_value[index] = apk_normal_value[index]; @@ -1730,8 +1721,7 @@ static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, 0x08)); } - - rtlphy->apk_done = true; + rtlphy->b_apk_done = true; #endif } @@ -1758,6 +1748,7 @@ static void _rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1); } + } #undef IQK_ADDA_REG_NUM diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h index 53ffb0981586..b09a45842d61 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h @@ -27,8 +27,8 @@ * *****************************************************************************/ -#ifndef __RTL92C_PHY_H__ -#define __RTL92C_PHY_H__ +#ifndef __RTL92C_PHY_COMMON_H__ +#define __RTL92C_PHY_COMMON_H__ #define MAX_PRECMD_CNT 16 #define MAX_RFDEPENDCMD_CNT 16 @@ -39,6 +39,7 @@ #define RT_CANNOT_IO(hw) false #define HIGHPOWER_RADIOA_ARRAYLEN 22 +#define IQK_ADDA_REG_NUM 16 #define MAX_TOLERANCE 5 #define IQK_DELAY_TIME 1 @@ -56,6 +57,7 @@ #define IQK_ADDA_REG_NUM 16 #define IQK_MAC_REG_NUM 4 +#define IQK_DELAY_TIME 1 #define RF90_PATH_MAX 2 #define CT_OFFSET_MAC_ADDR 0X16 @@ -77,6 +79,7 @@ #define RTL92C_MAX_PATH_NUM 2 #define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 + enum swchnlcmd_id { CMDID_END, CMDID_SET_TXPOWEROWER_LEVEL, @@ -184,45 +187,41 @@ struct tx_power_struct { u32 mcs_original_offset[4][16]; }; -extern u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, +u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); -extern void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, +void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, u32 data); -extern u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, +u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask); -extern void rtl92c_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask, u32 data); -extern bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); -extern bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); -extern bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); -extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, +bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); +bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); +bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); +bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, enum radio_path rfpath); -extern void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -extern void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, +void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel); -extern void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -extern bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, +void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm); -extern void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, +void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); -extern void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw); -extern void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, +void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, enum nl80211_channel_type ch_type); -extern void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); -extern u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); -extern void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); -extern void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, +void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); +u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); +void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); +void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval); void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, enum radio_path rfpath); -extern bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, +bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath); -extern bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, +bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state); void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw); void rtl92c_phy_set_io(struct ieee80211_hw *hw); @@ -235,12 +234,9 @@ u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw, enum wireless_mode wirelessmode, long power_indbm); void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); -static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, u32 cmdtablesz, - enum swchnlcmd_id cmdid, u32 para1, - u32 para2, u32 msdelay); -static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay); +void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); +bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay); #endif -- cgit v1.2.3-58-ga151 From f73b279cdb5fc850b4be355307905f2914b2c0bb Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:53:50 -0500 Subject: rtlwifi: rtl8192ce: Change hw routine for addition of rtl8192se and rtl8192de Change rtl8192ce hw routine for addition of RTL8192SE and RTL8192DE. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192ce/def.h | 27 -- drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | 511 ++++++++++++++++++--------- drivers/net/wireless/rtlwifi/rtl8192ce/hw.h | 34 +- drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 2 + drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | 1 + drivers/net/wireless/rtlwifi/rtl8192cu/hw.h | 2 +- 6 files changed, 362 insertions(+), 215 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 2f577c8828fc..35ff7df41a1d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -121,19 +121,6 @@ #define CHIP_92C 0x01 #define CHIP_88C 0x00 -/* Add vendor information into chip version definition. - * Add UMC B-Cut and RTL8723 chip info definition. - * - * BIT 7 Reserved - * BIT 6 UMC BCut - * BIT 5 Manufacturer(TSMC/UMC) - * BIT 4 TEST/NORMAL - * BIT 3 8723 Version - * BIT 2 8723? - * BIT 1 1T2R? - * BIT 0 88C/92C -*/ - enum version_8192c { VERSION_A_CHIP_92C = 0x01, VERSION_A_CHIP_88C = 0x00, @@ -280,20 +267,6 @@ struct h2c_cmd_8192c { u8 *p_cmdbuffer; }; -static inline u8 _rtl92c_get_chnl_group(u8 chnl) -{ - u8 group = 0; - - if (chnl < 3) - group = 0; - else if (chnl < 9) - group = 1; - else - group = 2; - - return group; -} - /* NOTE: reference to rtl8192c_rates struct */ static inline int _rtl92c_rate_mapping(struct ieee80211_hw *hw, bool isHT, u8 desc_rate, bool first_ampdu) diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 05477f465a75..bb604b8ee519 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -30,12 +30,14 @@ #include "../wifi.h" #include "../efuse.h" #include "../base.h" +#include "../regd.h" #include "../cam.h" #include "../ps.h" #include "../pci.h" #include "reg.h" #include "def.h" #include "phy.h" +#include "../rtl8192c/fw_common.h" #include "dm.h" #include "led.h" #include "hw.h" @@ -137,15 +139,6 @@ void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) break; } - case HW_VAR_MGT_FILTER: - *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP0); - break; - case HW_VAR_CTRL_FILTER: - *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP1); - break; - case HW_VAR_DATA_FILTER: - *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP2); - break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case not process\n")); @@ -156,6 +149,7 @@ void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -178,7 +172,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rate_cfg |= 0x01; rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); rtl_write_byte(rtlpriv, REG_RRSR + 1, - (rate_cfg >> 8)&0xff); + (rate_cfg >> 8) & 0xff); while (rate_cfg > 0x1) { rate_cfg = (rate_cfg >> 1); rate_index++; @@ -276,13 +270,19 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) break; } case HW_VAR_AMPDU_FACTOR:{ - u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; + u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9}; + u8 regtoset_bt[4] = {0x31, 0x74, 0x42, 0x97}; u8 factor_toset; u8 *p_regtoset = NULL; u8 index = 0; - p_regtoset = regtoset_normal; + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == + BT_CSR_BC4)) + p_regtoset = regtoset_bt; + else + p_regtoset = regtoset_normal; factor_toset = *((u8 *) val); if (factor_toset <= 3) { @@ -317,45 +317,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } case HW_VAR_AC_PARAM:{ u8 e_aci = *((u8 *) val); - u32 u4b_ac_param; - u16 cw_min = le16_to_cpu(mac->ac[e_aci].cw_min); - u16 cw_max = le16_to_cpu(mac->ac[e_aci].cw_max); - u16 tx_op = le16_to_cpu(mac->ac[e_aci].tx_op); - - u4b_ac_param = (u32) mac->ac[e_aci].aifs; - u4b_ac_param |= ((u32)cw_min - & 0xF) << AC_PARAM_ECW_MIN_OFFSET; - u4b_ac_param |= ((u32)cw_max & - 0xF) << AC_PARAM_ECW_MAX_OFFSET; - u4b_ac_param |= (u32)tx_op << AC_PARAM_TXOP_OFFSET; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - ("queue:%x, ac_param:%x\n", e_aci, - u4b_ac_param)); - - switch (e_aci) { - case AC1_BK: - rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, - u4b_ac_param); - break; - case AC0_BE: - rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, - u4b_ac_param); - break; - case AC2_VI: - rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, - u4b_ac_param); - break; - case AC3_VO: - rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, - u4b_ac_param); - break; - default: - RT_ASSERT(false, - ("SetHwReg8185(): invalid aci: %d !\n", - e_aci)); - break; - } + rtl92c_dm_init_edca_turbo(hw); if (rtlpci->acm_method != eAcmWay2_SW) rtlpriv->cfg->ops->set_hw_reg(hw, @@ -526,9 +488,6 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) case HW_VAR_CORRECT_TSF:{ u8 btype_ibss = ((u8 *) (val))[0]; - /*btype_ibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? - 1 : 0;*/ - if (btype_ibss == true) _rtl92ce_stop_tx_beacon(hw); @@ -537,7 +496,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtl_write_dword(rtlpriv, REG_TSFTR, (u32) (mac->tsf & 0xffffffff)); rtl_write_dword(rtlpriv, REG_TSFTR + 4, - (u32) ((mac->tsf >> 32)&0xffffffff)); + (u32) ((mac->tsf >> 32) & 0xffffffff)); _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); @@ -547,15 +506,6 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) break; } - case HW_VAR_MGT_FILTER: - rtl_write_word(rtlpriv, REG_RXFLTMAP0, *(u16 *) val); - break; - case HW_VAR_CTRL_FILTER: - rtl_write_word(rtlpriv, REG_RXFLTMAP1, *(u16 *) val); - break; - case HW_VAR_DATA_FILTER: - rtl_write_word(rtlpriv, REG_RXFLTMAP2, *(u16 *) val); - break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case " "not process\n")); @@ -679,12 +629,12 @@ static void _rtl92ce_gen_refresh_led_state(struct ieee80211_hw *hw) rtl92ce_sw_led_on(hw, pLed0); else rtl92ce_sw_led_off(hw, pLed0); - } static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -693,9 +643,22 @@ static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) u16 retry; rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); + if (rtlpcipriv->bt_coexist.bt_coexistence) { + u32 value32; + value32 = rtl_read_dword(rtlpriv, REG_APS_FSMCO); + value32 |= (SOP_ABG | SOP_AMB | XOP_BTCK); + rtl_write_dword(rtlpriv, REG_APS_FSMCO, value32); + } rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F); + if (rtlpcipriv->bt_coexist.bt_coexistence) { + u32 u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); + + u4b_tmp &= (~0x00024800); + rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, u4b_tmp); + } + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0); udelay(2); @@ -726,6 +689,11 @@ static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82); udelay(2); + if (rtlpcipriv->bt_coexist.bt_coexistence) { + bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+2) & 0xfd; + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+2, bytetmp); + } + rtl_write_word(rtlpriv, REG_CR, 0x2ff); if (_rtl92ce_llt_table_init(hw) == false) @@ -793,6 +761,7 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); u8 reg_bw_opmode; u32 reg_ratr, reg_prsr; @@ -824,7 +793,11 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw) rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x97427431); + else + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); @@ -840,11 +813,20 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); - - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) { + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0402); + } else { + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + } - rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666); + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) + rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); + else + rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666); rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); @@ -948,8 +930,10 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) } rtlhal->last_hmeboxnum = 0; - rtl92ce_phy_mac_config(hw); - rtl92ce_phy_bb_config(hw); +#if 0 /* temporary */ + rtl92c_phy_mac_config(hw); + rtl92c_phy_bb_config(hw); +#endif rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; rtl92c_phy_rf_config(hw); rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, @@ -962,15 +946,20 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) _rtl92ce_hw_configure(hw); rtl_cam_reset_all_entry(hw); rtl92ce_enable_hw_security_config(hw); + ppsc->rfpwr_state = ERFON; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); _rtl92ce_enable_aspm_back_door(hw); rtlpriv->intf_ops->enable_aspm(hw); + + rtl8192ce_bt_hw_init(hw); + if (ppsc->rfpwr_state == ERFON) { rtl92c_phy_set_rfpath_switch(hw, 1); - if (iqk_initialized) + if (iqk_initialized) { rtl92c_phy_iq_calibrate(hw, true); - else { + } else { rtl92c_phy_iq_calibrate(hw, false); iqk_initialized = true; } @@ -1128,75 +1117,62 @@ static int _rtl92ce_set_media_status(struct ieee80211_hw *hw, return 0; } -static void _rtl92ce_set_check_bssid(struct ieee80211_hw *hw, - enum nl80211_iftype type) +void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR); - u8 filterout_non_associated_bssid = false; - switch (type) { - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_STATION: - filterout_non_associated_bssid = true; - break; - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_AP: - default: - break; - } + if (rtlpriv->psc.rfpwr_state != ERFON) + return; - if (filterout_non_associated_bssid == true) { + if (check_bssid == true) { reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *) (®_rcr)); _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4)); - } else if (filterout_non_associated_bssid == false) { + } else if (check_bssid == false) { reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); _rtl92ce_set_bcn_ctrl_reg(hw, BIT(4), 0); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *) (®_rcr)); } + } int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) { + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (_rtl92ce_set_media_status(hw, type)) return -EOPNOTSUPP; - _rtl92ce_set_check_bssid(hw, type); + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + if (type != NL80211_IFTYPE_AP) + rtl92ce_set_check_bssid(hw, true); + } else { + rtl92ce_set_check_bssid(hw, false); + } + return 0; } +/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u32 u4b_ac_param; - u16 cw_min = le16_to_cpu(mac->ac[aci].cw_min); - u16 cw_max = le16_to_cpu(mac->ac[aci].cw_max); - u16 tx_op = le16_to_cpu(mac->ac[aci].tx_op); - rtl92c_dm_init_edca_turbo(hw); - u4b_ac_param = (u32) mac->ac[aci].aifs; - u4b_ac_param |= (u32) ((cw_min & 0xF) << AC_PARAM_ECW_MIN_OFFSET); - u4b_ac_param |= (u32) ((cw_max & 0xF) << AC_PARAM_ECW_MAX_OFFSET); - u4b_ac_param |= (u32) (tx_op << AC_PARAM_TXOP_OFFSET); - RT_TRACE(rtlpriv, COMP_QOS, DBG_DMESG, - ("queue:%x, ac_param:%x aifs:%x cwmin:%x cwmax:%x txop:%x\n", - aci, u4b_ac_param, mac->ac[aci].aifs, cw_min, - cw_max, tx_op)); switch (aci) { case AC1_BK: - rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param); + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); break; case AC0_BE: - rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); + /* rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); */ break; case AC2_VI: - rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, u4b_ac_param); + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); break; case AC3_VO: - rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, u4b_ac_param); + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); break; default: RT_ASSERT(false, ("invalid aci: %d !\n", aci)); @@ -1227,8 +1203,10 @@ void rtl92ce_disable_interrupt(struct ieee80211_hw *hw) static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u8 u1b_tmp; + u32 u4b_tmp; rtlpriv->intf_ops->enable_aspm(hw); rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); @@ -1243,13 +1221,27 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000); u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL); - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00FF0000 | - (u1b_tmp << 8)); + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + ((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) || + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8))) { + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00F30000 | + (u1b_tmp << 8)); + } else { + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00FF0000 | + (u1b_tmp << 8)); + } rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790); rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); + if (rtlpcipriv->bt_coexist.bt_coexistence) { + u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); + u4b_tmp |= 0x03824800; + rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, u4b_tmp); + } else { + rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); + } + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10); } @@ -1327,6 +1319,7 @@ void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, ("add_msr:%x, rm_msr:%x\n", add_msr, rm_msr)); + if (add_msr) rtlpci->irq_mask[0] |= add_msr; if (rm_msr) @@ -1582,7 +1575,7 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) ("RTL819X Not boot from eeprom, check it !!")); } - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, ("MAP\n"), + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"), hwinfo, HWSET_MAX_SIZE); eeprom_id = *((u16 *)&hwinfo[0]); @@ -1610,6 +1603,10 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) rtlefuse->autoload_failflag, hwinfo); + rtl8192ce_read_bt_coexist_info_from_hwpg(hw, + rtlefuse->autoload_failflag, + hwinfo); + rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; rtlefuse->txpwr_fromeprom = true; @@ -1618,6 +1615,9 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid)); + /* set channel paln to world wide 13 */ + rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; + if (rtlhal->oem_id == RT_CID_DEFAULT) { switch (rtlefuse->eeprom_oemid) { case EEPROM_CID_DEFAULT: @@ -1701,30 +1701,36 @@ void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw) } else { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Autoload ERR!!\n")); } - _rtl92ce_hal_customized_behavior(hw); } -void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw) +static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - u32 ratr_value = (u32) mac->basic_rates; - u8 *mcsrate = mac->mcs; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 ratr_value; u8 ratr_index = 0; u8 nmode = mac->ht_enable; - u8 mimo_ps = 1; + u8 mimo_ps = IEEE80211_SMPS_OFF; u16 shortgi_rate; u32 tmp_ratr_value; u8 curtxbw_40mhz = mac->bw_40; - u8 curshortgi_40mhz = mac->sgi_40; - u8 curshortgi_20mhz = mac->sgi_20; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; enum wireless_mode wirelessmode = mac->mode; - ratr_value |= ((*(u16 *) (mcsrate))) << 12; - + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_value = sta->supp_rates[1] << 4; + else + ratr_value = sta->supp_rates[0]; + ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); switch (wirelessmode) { case WIRELESS_MODE_B: if (ratr_value & 0x0000000c) @@ -1738,7 +1744,7 @@ void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw) case WIRELESS_MODE_N_24G: case WIRELESS_MODE_N_5G: nmode = 1; - if (mimo_ps == 0) { + if (mimo_ps == IEEE80211_SMPS_STATIC) { ratr_value &= 0x0007F005; } else { u32 ratr_mask; @@ -1761,10 +1767,19 @@ void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw) break; } - ratr_value &= 0x0FFFFFFF; + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) && + (rtlpcipriv->bt_coexist.bt_cur_state) && + (rtlpcipriv->bt_coexist.bt_ant_isolation) && + ((rtlpcipriv->bt_coexist.bt_service == BT_SCO) || + (rtlpcipriv->bt_coexist.bt_service == BT_BUSY))) + ratr_value &= 0x0fffcfc0; + else + ratr_value &= 0x0FFFFFFF; - if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) || (!curtxbw_40mhz && - curshortgi_20mhz))) { + if (nmode && ((curtxbw_40mhz && + curshortgi_40mhz) || (!curtxbw_40mhz && + curshortgi_20mhz))) { ratr_value |= 0x10000000; tmp_ratr_value = (ratr_value >> 12); @@ -1784,24 +1799,42 @@ void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw) ("%x\n", rtl_read_dword(rtlpriv, REG_ARFR0))); } -void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) +static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u32 ratr_bitmap = (u32) mac->basic_rates; - u8 *p_mcsrate = mac->mcs; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u32 ratr_bitmap; u8 ratr_index; - u8 curtxbw_40mhz = mac->bw_40; - u8 curshortgi_40mhz = mac->sgi_40; - u8 curshortgi_20mhz = mac->sgi_20; - enum wireless_mode wirelessmode = mac->mode; + u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) + ? 1 : 0; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = 0; bool shortgi = false; u8 rate_mask[5]; u8 macid = 0; - u8 mimops = 1; - - ratr_bitmap |= (p_mcsrate[1] << 20) | (p_mcsrate[0] << 12); + u8 mimo_ps = IEEE80211_SMPS_OFF; + + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + wirelessmode = sta_entry->wireless_mode; + if (mac->opmode == NL80211_IFTYPE_STATION) + curtxbw_40mhz = mac->bw_40; + else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + macid = sta->aid + 1; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_bitmap = sta->supp_rates[1] << 4; + else + ratr_bitmap = sta->supp_rates[0]; + ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); switch (wirelessmode) { case WIRELESS_MODE_B: ratr_index = RATR_INX_WIRELESS_B; @@ -1828,7 +1861,7 @@ void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) case WIRELESS_MODE_N_5G: ratr_index = RATR_INX_WIRELESS_NGB; - if (mimops == 0) { + if (mimo_ps == IEEE80211_SMPS_STATIC) { if (rssi_level == 1) ratr_bitmap &= 0x00070000; else if (rssi_level == 2) @@ -1892,8 +1925,8 @@ void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) } RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("ratr_bitmap :%x\n", ratr_bitmap)); - *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | - (ratr_index << 28); + *(u32 *)&rate_mask = EF4BYTE((ratr_bitmap & 0x0fffffff) | + (ratr_index << 28)); rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("Rate_index:%x, " "ratr_val:%x, %x:%x:%x:%x:%x\n", @@ -1902,6 +1935,20 @@ void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) rate_mask[2], rate_mask[3], rate_mask[4])); rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); + + if (macid != 0) + sta_entry->ratr_index = ratr_index; +} + +void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->dm.useramask) + rtl92ce_update_hal_rate_mask(hw, sta, rssi_level); + else + rtl92ce_update_hal_rate_table(hw, sta); } void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw) @@ -1919,7 +1966,7 @@ void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw) rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); } -bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) +bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); @@ -1929,7 +1976,7 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) bool actuallyset = false; unsigned long flag; - if ((rtlpci->up_first_time == 1) || (rtlpci->being_init_adapter)) + if (rtlpci->being_init_adapter) return false; if (ppsc->swrf_processing) @@ -1946,12 +1993,6 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) cur_rfstate = ppsc->rfpwr_state; - if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) { - rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); - } - rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG)&~(BIT(3))); @@ -1976,38 +2017,13 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) } if (actuallyset) { - if (e_rfpowerstate_toset == ERFON) { - if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) { - rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); - } - } - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); ppsc->rfchange_inprogress = false; spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - - if (e_rfpowerstate_toset == ERFOFF) { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { - rtlpriv->intf_ops->enable_aspm(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); - } - } - - } else if (e_rfpowerstate_toset == ERFOFF || cur_rfstate == ERFOFF) { + } else { if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { - rtlpriv->intf_ops->enable_aspm(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); - } - - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } else { spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); ppsc->rfchange_inprogress = false; spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); @@ -2086,15 +2102,31 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, macaddr = cam_const_broad; entry_id = key_index; } else { + if (mac->opmode == NL80211_IFTYPE_AP) { + entry_id = rtl_cam_get_free_entry(hw, + p_macaddr); + if (entry_id >= TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, COMP_SEC, + DBG_EMERG, + ("Can not find free hw" + " security cam entry\n")); + return; + } + } else { + entry_id = CAM_PAIRWISE_KEY_POSITION; + } + key_index = PAIRWISE_KEYIDX; - entry_id = CAM_PAIRWISE_KEY_POSITION; is_pairwise = true; } } if (rtlpriv->sec.key_len[key_index] == 0) { RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("delete one entry\n")); + ("delete one entry, entry_id is %d\n", + entry_id)); + if (mac->opmode == NL80211_IFTYPE_AP) + rtl_cam_del_entry(hw, p_macaddr); rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); } else { RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, @@ -2146,3 +2178,132 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, } } } + +void rtl8192ce_bt_var_init(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + rtlpcipriv->bt_coexist.bt_coexistence = + rtlpcipriv->bt_coexist.eeprom_bt_coexist; + rtlpcipriv->bt_coexist.bt_ant_num = + rtlpcipriv->bt_coexist.eeprom_bt_ant_num; + rtlpcipriv->bt_coexist.bt_coexist_type = + rtlpcipriv->bt_coexist.eeprom_bt_type; + + if (rtlpcipriv->bt_coexist.reg_bt_iso == 2) + rtlpcipriv->bt_coexist.bt_ant_isolation = + rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation; + else + rtlpcipriv->bt_coexist.bt_ant_isolation = + rtlpcipriv->bt_coexist.reg_bt_iso; + + rtlpcipriv->bt_coexist.bt_radio_shared_type = + rtlpcipriv->bt_coexist.eeprom_bt_radio_shared; + + if (rtlpcipriv->bt_coexist.bt_coexistence) { + + if (rtlpcipriv->bt_coexist.reg_bt_sco == 1) + rtlpcipriv->bt_coexist.bt_service = BT_OTHER_ACTION; + else if (rtlpcipriv->bt_coexist.reg_bt_sco == 2) + rtlpcipriv->bt_coexist.bt_service = BT_SCO; + else if (rtlpcipriv->bt_coexist.reg_bt_sco == 4) + rtlpcipriv->bt_coexist.bt_service = BT_BUSY; + else if (rtlpcipriv->bt_coexist.reg_bt_sco == 5) + rtlpcipriv->bt_coexist.bt_service = BT_OTHERBUSY; + else + rtlpcipriv->bt_coexist.bt_service = BT_IDLE; + + rtlpcipriv->bt_coexist.bt_edca_ul = 0; + rtlpcipriv->bt_coexist.bt_edca_dl = 0; + rtlpcipriv->bt_coexist.bt_rssi_state = 0xff; + } +} + +void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool auto_load_fail, u8 *hwinfo) +{ + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + u8 value; + + if (!auto_load_fail) { + rtlpcipriv->bt_coexist.eeprom_bt_coexist = + ((hwinfo[RF_OPTION1] & 0xe0) >> 5); + value = hwinfo[RF_OPTION4]; + rtlpcipriv->bt_coexist.eeprom_bt_type = ((value & 0xe) >> 1); + rtlpcipriv->bt_coexist.eeprom_bt_ant_num = (value & 0x1); + rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation = + ((value & 0x10) >> 4); + rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = + ((value & 0x20) >> 5); + } else { + rtlpcipriv->bt_coexist.eeprom_bt_coexist = 0; + rtlpcipriv->bt_coexist.eeprom_bt_type = BT_2WIRE; + rtlpcipriv->bt_coexist.eeprom_bt_ant_num = ANT_X2; + rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation = 0; + rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = BT_RADIO_SHARED; + } + + rtl8192ce_bt_var_init(hw); +} + +void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + /* 0:Low, 1:High, 2:From Efuse. */ + rtlpcipriv->bt_coexist.reg_bt_iso = 2; + /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ + rtlpcipriv->bt_coexist.reg_bt_sco = 3; + /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ + rtlpcipriv->bt_coexist.reg_bt_sco = 0; +} + + +void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + u8 u1_tmp; + + if (rtlpcipriv->bt_coexist.bt_coexistence && + ((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) || + rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8)) { + + if (rtlpcipriv->bt_coexist.bt_ant_isolation) + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); + + u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) & + BIT_OFFSET_LEN_MASK_32(0, 1); + u1_tmp = u1_tmp | + ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? + 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | + ((rtlpcipriv->bt_coexist.bt_service == BT_SCO) ? + 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); + rtl_write_byte(rtlpriv, 0x4fd, u1_tmp); + + rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+4, 0xaaaa9aaa); + rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+8, 0xffbd0040); + rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+0xc, 0x40000010); + + /* Config to 1T1R. */ + if (rtlphy->rf_type == RF_1T1R) { + u1_tmp = rtl_read_byte(rtlpriv, ROFDM0_TRXPATHENABLE); + u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); + rtl_write_byte(rtlpriv, ROFDM0_TRXPATHENABLE, u1_tmp); + + u1_tmp = rtl_read_byte(rtlpriv, ROFDM1_TRXPATHENABLE); + u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); + rtl_write_byte(rtlpriv, ROFDM1_TRXPATHENABLE, u1_tmp); + } + } +} + +void rtl92ce_suspend(struct ieee80211_hw *hw) +{ +} + +void rtl92ce_resume(struct ieee80211_hw *hw) +{ +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h index a3dfdb635168..07dbe3e340a5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h @@ -30,7 +30,18 @@ #ifndef __RTL92CE_HW_H__ #define __RTL92CE_HW_H__ -#define H2C_RA_MASK 6 +static inline u8 _rtl92c_get_chnl_group(u8 chnl) +{ + u8 group; + + if (chnl < 3) + group = 0; + else if (chnl < 9) + group = 1; + else + group = 2; + return group; +} void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw); @@ -41,28 +52,27 @@ void rtl92ce_card_disable(struct ieee80211_hw *hw); void rtl92ce_enable_interrupt(struct ieee80211_hw *hw); void rtl92ce_disable_interrupt(struct ieee80211_hw *hw); int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); +void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci); void rtl92ce_set_beacon_related_registers(struct ieee80211_hw *hw); void rtl92ce_set_beacon_interval(struct ieee80211_hw *hw); void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, u32 add_msr, u32 rm_msr); void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw); -void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level); +void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level); void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw); bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw); void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr, bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all); -bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); -void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); -void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); -void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); -int rtl92c_download_fw(struct ieee80211_hw *hw); -void rtl92c_firmware_selfreset(struct ieee80211_hw *hw); -void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, - u8 element_id, u32 cmd_len, u8 *p_cmdbuffer); -bool rtl92ce_phy_mac_config(struct ieee80211_hw *hw); + +void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo); +void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw); +void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw); +void rtl92ce_suspend(struct ieee80211_hw *hw); +void rtl92ce_resume(struct ieee80211_hw *hw); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index f4e2f3dcccae..0042e0ee89a8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -112,10 +112,12 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { .update_interrupt_mask = rtl92ce_update_interrupt_mask, .get_hw_reg = rtl92ce_get_hw_reg, .set_hw_reg = rtl92ce_set_hw_reg, +#if 0 /* temporary */ .update_rate_table = rtl92ce_update_hal_rate_table, .update_rate_mask = rtl92ce_update_hal_rate_mask, .fill_tx_desc = rtl92ce_tx_fill_desc, .fill_tx_cmddesc = rtl92ce_tx_fill_cmddesc, +#endif .query_rx_desc = rtl92ce_rx_query_desc, .set_channel_access = rtl92ce_update_channel_access_setting, .radio_onoff_checking = rtl92ce_gpio_radio_on_off_checking, diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index e43be2547827..be2d60fb9248 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -42,6 +42,7 @@ #include "trx.h" #include "led.h" #include "table.h" +#include "../rtl8192ce/hw.h" static void _rtl92cu_phy_param_tab_init(struct ieee80211_hw *hw) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h index 62af555bb61c..17dc5a3151cf 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h @@ -104,7 +104,7 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level); void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw); bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid); void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -u8 _rtl92c_get_chnl_group(u8 chnl); +static u8 _rtl92c_get_chnl_group(u8 chnl); int rtl92c_download_fw(struct ieee80211_hw *hw); void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished); -- cgit v1.2.3-58-ga151 From 2b8359f85b81dfe02a631e570582290859191756 Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:53:55 -0500 Subject: rtlwifi: rtl8192ce: Change sw and LED routines for addition of rtl8192se and rtl8192de Change rtl8192ce sw and LED routines for addition of RTL8192SE and RTL8192DE. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 12 +- drivers/net/wireless/rtlwifi/rtl8192ce/dm.c | 2 + drivers/net/wireless/rtlwifi/rtl8192ce/dm.h | 1 + drivers/net/wireless/rtlwifi/rtl8192ce/led.c | 5 +- drivers/net/wireless/rtlwifi/rtl8192ce/led.h | 2 - drivers/net/wireless/rtlwifi/rtl8192ce/reg.h | 58 ++-------- drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 132 +++++++++++++++++++--- drivers/net/wireless/rtlwifi/rtl8192ce/sw.h | 14 +-- drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | 2 + 9 files changed, 143 insertions(+), 85 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index 2836d7eb0d05..bfc84054cc07 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -320,7 +320,7 @@ static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) { - static u8 binitialized; /* initialized to false */ + static u8 initialized; /* initialized to false */ struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); long rssi_strength = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; @@ -331,11 +331,11 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) if ((multi_sta == false) || (dm_digtable.cursta_connectctate != DIG_STA_DISCONNECT)) { - binitialized = false; + initialized = false; dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; return; - } else if (binitialized == false) { - binitialized = true; + } else if (initialized == false) { + initialized = true; dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; dm_digtable.cur_igvalue = 0x20; rtl92c_dm_write_dig(hw); @@ -1513,7 +1513,7 @@ void rtl92c_dm_watchdog(struct ieee80211_hw *hw) } EXPORT_SYMBOL(rtl92c_dm_watchdog); -static u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw) +u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); @@ -1570,6 +1570,7 @@ static u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw) return false; } } +EXPORT_SYMBOL(rtl92c_bt_rssi_state_change); static bool rtl92c_bt_state_change(struct ieee80211_hw *hw) { @@ -1820,3 +1821,4 @@ void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw) rtl92c_check_bt_change(hw); } } +EXPORT_SYMBOL(rtl92c_dm_bt_coexist); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c index 7d76504df4d1..2df33e53e15a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c @@ -29,10 +29,12 @@ #include "../wifi.h" #include "../base.h" +#include "../pci.h" #include "reg.h" #include "def.h" #include "phy.h" #include "dm.h" +#include "../rtl8192c/fw_common.h" void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h index 36302ebae4a3..07dd9552e82f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h @@ -192,6 +192,7 @@ void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw); void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw); void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); +void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c index d21b934b5c33..9dd1ed7b6422 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c @@ -106,12 +106,11 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) void rtl92ce_init_sw_leds(struct ieee80211_hw *hw) { struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); } -void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, +static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) { struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); @@ -146,7 +145,7 @@ void rtl92ce_led_control(struct ieee80211_hw *hw, ledaction == LED_CTL_POWER_ON)) { return; } - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n", + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d.\n", ledaction)); _rtl92ce_sw_led_control(hw, ledaction); } diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/rtlwifi/rtl8192ce/led.h index 94332b3af5b1..7dfccea2095b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.h @@ -34,7 +34,5 @@ void rtl92ce_init_sw_leds(struct ieee80211_hw *hw); void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); void rtl92ce_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); -void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h index b0868a613841..115b3f841ddc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h @@ -72,6 +72,7 @@ #define REG_GPIO_IO_SEL_2 0x0062 /* RTL8723 WIFI/BT/GPS Multi-Function control source. */ #define REG_MULTI_FUNC_CTRL 0x0068 + #define REG_MCUFWDL 0x0080 #define REG_HMEBOX_EXT_0 0x0088 @@ -543,6 +544,8 @@ #define IMR_WLANOFF BIT(0) #define HWSET_MAX_SIZE 128 +#define EFUSE_MAX_SECTION 16 +#define EFUSE_REAL_CONTENT_LEN 512 #define EEPROM_DEFAULT_TSSI 0x0 #define EEPROM_DEFAULT_TXPOWERDIFF 0x0 @@ -656,6 +659,7 @@ #define STOPBE BIT(1) #define STOPBK BIT(0) +#define RCR_APPFCS BIT(31) #define RCR_APP_FCS BIT(31) #define RCR_APP_MIC BIT(30) #define RCR_APP_ICV BIT(29) @@ -688,6 +692,7 @@ #define REG_USB_INFO 0xFE17 #define REG_USB_SPECIAL_OPTION 0xFE55 + #define REG_USB_DMA_AGG_TO 0xFE5B #define REG_USB_AGG_TO 0xFE5C #define REG_USB_AGG_TH 0xFE5D @@ -775,7 +780,6 @@ #define BOOT_FROM_EEPROM BIT(4) #define EEPROM_EN BIT(5) -#define EEPROMSEL BOOT_FROM_EEPROM #define AFE_BGEN BIT(0) #define AFE_MBEN BIT(1) @@ -901,28 +905,7 @@ #define BD_PKG_SEL BIT(25) #define BD_HCI_SEL BIT(26) #define TYPE_ID BIT(27) - -/* REG_GPIO_OUTSTS (For RTL8723 only) */ -#define EFS_HCI_SEL (BIT(0)|BIT(1)) -#define PAD_HCI_SEL (BIT(2)|BIT(3)) -#define HCI_SEL (BIT(4)|BIT(5)) -#define PKG_SEL_HCI BIT(6) -#define FEN_GPS BIT(7) -#define FEN_BT BIT(8) -#define FEN_WL BIT(9) -#define FEN_PCI BIT(10) -#define FEN_USB BIT(11) -#define BTRF_HWPDN_N BIT(12) -#define WLRF_HWPDN_N BIT(13) -#define PDN_BT_N BIT(14) -#define PDN_GPS_N BIT(15) -#define BT_CTL_HWPDN BIT(16) -#define GPS_CTL_HWPDN BIT(17) -#define PPHY_SUSB BIT(20) -#define UPHY_SUSB BIT(21) -#define PCI_SUSEN BIT(22) -#define USB_SUSEN BIT(23) -#define RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28)) +#define RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28)) #define CHIP_VER_RTL_MASK 0xF000 #define CHIP_VER_RTL_SHIFT 12 @@ -1077,6 +1060,7 @@ #define _RARF_RC8(x) (((x) & 0x1F) << 24) #define AC_PARAM_TXOP_OFFSET 16 +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 #define AC_PARAM_ECW_MAX_OFFSET 12 #define AC_PARAM_ECW_MIN_OFFSET 8 #define AC_PARAM_AIFS_OFFSET 0 @@ -1221,33 +1205,11 @@ #define EPROM_CMD_CONFIG 0x3 #define EPROM_CMD_LOAD 1 -#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE +#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE -#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) - -/* REG_MULTI_FUNC_CTRL(For RTL8723 Only) */ -/* Enable GPIO[9] as WiFi HW PDn source */ #define WL_HWPDN_EN BIT(0) -/* WiFi HW PDn polarity control */ -#define WL_HWPDN_SL BIT(1) -/* WiFi function enable */ -#define WL_FUNC_EN BIT(2) -/* Enable GPIO[9] as WiFi RF HW PDn source */ -#define WL_HWROF_EN BIT(3) -/* Enable GPIO[11] as BT HW PDn source */ -#define BT_HWPDN_EN BIT(16) -/* BT HW PDn polarity control */ -#define BT_HWPDN_SL BIT(17) -/* BT function enable */ -#define BT_FUNC_EN BIT(18) -/* Enable GPIO[11] as BT/GPS RF HW PDn source */ -#define BT_HWROF_EN BIT(19) -/* Enable GPIO[10] as GPS HW PDn source */ -#define GPS_HWPDN_EN BIT(20) -/* GPS HW PDn polarity control */ -#define GPS_HWPDN_SL BIT(21) -/* GPS function enable */ -#define GPS_FUNC_EN BIT(22) + +#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) #define RPMAC_RESET 0x100 #define RPMAC_TXSTART 0x104 diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 0042e0ee89a8..5c920c6270c8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -42,10 +42,58 @@ #include "trx.h" #include "led.h" +void rtl92c_init_aspm_vars(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*close ASPM for AMD defaultly */ + rtlpci->const_amdpci_aspm = 0; + + /* + * ASPM PS mode. + * 0 - Disable ASPM, + * 1 - Enable ASPM without Clock Req, + * 2 - Enable ASPM with Clock Req, + * 3 - Alwyas Enable ASPM with Clock Req, + * 4 - Always Enable ASPM without Clock Req. + * set defult to RTL8192CE:3 RTL8192E:2 + * */ + rtlpci->const_pci_aspm = 3; + + /*Setting for PCI-E device */ + rtlpci->const_devicepci_aspm_setting = 0x03; + + /*Setting for PCI-E bridge */ + rtlpci->const_hostpci_aspm_setting = 0x02; + + /* + * In Hw/Sw Radio Off situation. + * 0 - Default, + * 1 - From ASPM setting without low Mac Pwr, + * 2 - From ASPM setting with low Mac Pwr, + * 3 - Bus D3 + * set default to RTL8192CE:0 RTL8192SE:2 + */ + rtlpci->const_hwsw_rfoff_d3 = 0; + + /* + * This setting works for those device with + * backdoor ASPM setting such as EPHY setting. + * 0 - Not support ASPM, + * 1 - Support ASPM, + * 2 - According to chipset. + */ + rtlpci->const_support_pciaspm = 1; +} + int rtl92c_init_sw_vars(struct ieee80211_hw *hw) { + int err; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + const struct firmware *firmware; + + rtl8192ce_bt_reg_init(hw); rtlpriv->dm.dm_initialgain_enable = 1; rtlpriv->dm.dm_flag = 0; @@ -53,7 +101,12 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->dm.thermalvalue = 0; rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13); - rtlpci->receive_config = (RCR_APP_FCS | + /* compatible 5G band 88ce just 2.4G band & smsp */ + rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; + rtlpriv->rtlhal.bandset = BAND_ON_2_4G; + rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; + + rtlpci->receive_config = (RCR_APPFCS | RCR_AMF | RCR_ADF | RCR_APP_MIC | @@ -76,13 +129,49 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD | 0); - rtlpriv->rtlhal.pfirmware = (u8 *) vmalloc(0x4000); + /* for LPS & IPS */ + rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; + rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; + rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; + rtlpriv->psc.reg_fwctrl_lps = 3; + rtlpriv->psc.reg_max_lps_awakeintvl = 5; + /* for ASPM, you can close aspm through + * set const_support_pciaspm = 0 */ + rtl92c_init_aspm_vars(hw); + + if (rtlpriv->psc.reg_fwctrl_lps == 1) + rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 2) + rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 3) + rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; + + /* for firmware buf */ + rtlpriv->rtlhal.pfirmware = vzalloc(0x4000); if (!rtlpriv->rtlhal.pfirmware) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Can't alloc buffer for fw.\n")); return 1; } + /* request fw */ + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Failed to request firmware!\n")); + return 1; + } + if (firmware->size > 0x4000) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Firmware is too big!\n")); + release_firmware(firmware); + return 1; + } + memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); + rtlpriv->rtlhal.fwsize = firmware->size; + release_firmware(firmware); + return 0; } @@ -96,28 +185,28 @@ void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw) } } -static struct rtl_hal_ops rtl8192ce_hal_ops = { +struct rtl_hal_ops rtl8192ce_hal_ops = { .init_sw_vars = rtl92c_init_sw_vars, .deinit_sw_vars = rtl92c_deinit_sw_vars, .read_eeprom_info = rtl92ce_read_eeprom_info, .interrupt_recognized = rtl92ce_interrupt_recognized, .hw_init = rtl92ce_hw_init, .hw_disable = rtl92ce_card_disable, + .hw_suspend = rtl92ce_suspend, + .hw_resume = rtl92ce_resume, .enable_interrupt = rtl92ce_enable_interrupt, .disable_interrupt = rtl92ce_disable_interrupt, .set_network_type = rtl92ce_set_network_type, + .set_chk_bssid = rtl92ce_set_check_bssid, .set_qos = rtl92ce_set_qos, .set_bcn_reg = rtl92ce_set_beacon_related_registers, .set_bcn_intv = rtl92ce_set_beacon_interval, .update_interrupt_mask = rtl92ce_update_interrupt_mask, .get_hw_reg = rtl92ce_get_hw_reg, .set_hw_reg = rtl92ce_set_hw_reg, -#if 0 /* temporary */ - .update_rate_table = rtl92ce_update_hal_rate_table, - .update_rate_mask = rtl92ce_update_hal_rate_mask, + .update_rate_tbl = rtl92ce_update_hal_rate_tbl, .fill_tx_desc = rtl92ce_tx_fill_desc, .fill_tx_cmddesc = rtl92ce_tx_fill_cmddesc, -#endif .query_rx_desc = rtl92ce_rx_query_desc, .set_channel_access = rtl92ce_update_channel_access_setting, .radio_onoff_checking = rtl92ce_gpio_radio_on_off_checking, @@ -125,7 +214,8 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { .switch_channel = rtl92c_phy_sw_chnl, .dm_watchdog = rtl92c_dm_watchdog, .scan_operation_backup = rtl92c_phy_scan_operation_backup, - .set_rf_power_state = rtl92ce_phy_set_rf_power_state, +#if 0 /* temporary */ + .set_rf_power_state = rtl92c_phy_set_rf_power_state, .led_control = rtl92ce_led_control, .set_desc = rtl92ce_set_desc, .get_desc = rtl92ce_get_desc, @@ -135,24 +225,28 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { .init_sw_leds = rtl92ce_init_sw_leds, .get_bbreg = rtl92c_phy_query_bb_reg, .set_bbreg = rtl92c_phy_set_bb_reg, - .get_rfreg = rtl92ce_phy_query_rf_reg, .set_rfreg = rtl92ce_phy_set_rf_reg, - .cmd_send_packet = _rtl92c_cmd_send_packet, + .get_rfreg = rtl92c_phy_query_rf_reg, .phy_rf6052_config = rtl92ce_phy_rf6052_config, .phy_rf6052_set_cck_txpower = rtl92ce_phy_rf6052_set_cck_txpower, .phy_rf6052_set_ofdm_txpower = rtl92ce_phy_rf6052_set_ofdm_txpower, .config_bb_with_headerfile = _rtl92ce_phy_config_bb_with_headerfile, .config_bb_with_pgheaderfile = _rtl92ce_phy_config_bb_with_pgheaderfile, .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate, - .phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback, .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower, +#endif }; -static struct rtl_mod_params rtl92ce_mod_params = { - .sw_crypto = 0, +struct rtl_mod_params rtl92ce_mod_params = { + .sw_crypto = false, + .inactiveps = true, + .swctrl_lps = false, + .fwctrl_lps = true, }; -static struct rtl_hal_cfg rtl92ce_hal_cfg = { +struct rtl_hal_cfg rtl92ce_hal_cfg = { + .bar_id = 2, + .write_readback = true, .name = "rtl92c_pci", .fw_name = "rtlwifi/rtl8192cfw.bin", .ops = &rtl8192ce_hal_ops, @@ -176,6 +270,8 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = { .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, .maps[EFUSE_ANA8M] = EFUSE_ANA8M, .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, + .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, + .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, .maps[RWCAM] = REG_CAMCMD, .maps[WCAMI] = REG_CAMWRITE, @@ -240,7 +336,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = { .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, }; -static struct pci_device_id rtl92ce_pci_ids[] __devinitdata = { +DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = { {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8191, rtl92ce_hal_cfg)}, {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8178, rtl92ce_hal_cfg)}, {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8177, rtl92ce_hal_cfg)}, @@ -258,7 +354,13 @@ MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n PCI wireless"); MODULE_FIRMWARE("rtlwifi/rtl8192cfw.bin"); module_param_named(swenc, rtl92ce_mod_params.sw_crypto, bool, 0444); +module_param_named(ips, rtl92ce_mod_params.inactiveps, bool, 0444); +module_param_named(swlps, rtl92ce_mod_params.swctrl_lps, bool, 0444); +module_param_named(fwlps, rtl92ce_mod_params.fwctrl_lps, bool, 0444); MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); +MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n"); +MODULE_PARM_DESC(fwlps, "using linked fw control power save " + "(default 1 is open)\n"); static struct pci_driver rtl92ce_driver = { .name = KBUILD_MODNAME, diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h index 36e657668c1e..b7dc3263e433 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h @@ -33,19 +33,9 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw); void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw); void rtl92c_init_var_map(struct ieee80211_hw *hw); -bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, - struct sk_buff *skb); -void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); + u8 configtype); bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); -void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); -u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask); -void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw); + u8 configtype); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index be2d60fb9248..861f39fad3ec 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -606,10 +606,12 @@ void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw) if (!IS_NORMAL_CHIP(rtlhal->version)) return; tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); +#if 0 /* temporary */ rtlefuse->epromtype = (tmp_u1b & EEPROMSEL) ? EEPROM_93C46 : EEPROM_BOOT_EFUSE; RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from %s\n", (tmp_u1b & EEPROMSEL) ? "EERROM" : "EFUSE")); +#endif rtlefuse->autoload_failflag = (tmp_u1b & EEPROM_EN) ? false : true; RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload %s\n", (tmp_u1b & EEPROM_EN) ? "OK!!" : "ERR!!")); -- cgit v1.2.3-58-ga151 From e0b5a5078675f58736787982af811244eeb98081 Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:54:00 -0500 Subject: rtlwifi: rtl8192ce: Change phy and rc routines for addition of rtl8192se and rtl8192de Change rtl8192ce routines phy and rc for addition of RTL8192SE and RTL8192DE. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192ce/phy.c | 191 ++++++++++++++++----------- drivers/net/wireless/rtlwifi/rtl8192ce/phy.h | 51 +++---- drivers/net/wireless/rtlwifi/rtl8192ce/rf.c | 24 ++-- drivers/net/wireless/rtlwifi/rtl8192ce/rf.h | 17 +-- 4 files changed, 157 insertions(+), 126 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c index d0541e8c6012..bbba6f8a8349 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c @@ -38,7 +38,9 @@ #include "dm.h" #include "table.h" -u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw, +static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); + +u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -73,9 +75,47 @@ u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw, return readback_value; } +bool rtl92c_phy_mac_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool is92c = IS_92C_SERIAL(rtlhal->version); + bool rtstatus = _rtl92c_phy_config_mac_with_headerfile(hw); + + if (is92c) + rtl_write_byte(rtlpriv, 0x14, 0x71); + return rtstatus; +} + +bool rtl92c_phy_bb_config(struct ieee80211_hw *hw) +{ + bool rtstatus = true; + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 regval; + u32 regvaldw; + u8 reg_hwparafile = 1; + + _rtl92c_phy_init_bb_rf_register_definition(hw); + regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, + regval | BIT(13) | BIT(0) | BIT(1)); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); + rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, + FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | + FEN_BB_GLB_RSTn | FEN_BBRSTB); + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); + regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); + rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); + if (reg_hwparafile == 1) + rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); + return rtstatus; +} + void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data) + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -121,45 +161,7 @@ void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, bitmask, data, rfpath)); } -bool rtl92ce_phy_mac_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool is92c = IS_92C_SERIAL(rtlhal->version); - bool rtstatus = _rtl92ce_phy_config_mac_with_headerfile(hw); - - if (is92c) - rtl_write_byte(rtlpriv, 0x14, 0x71); - return rtstatus; -} - -bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw) -{ - bool rtstatus = true; - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 regval; - u32 regvaldw; - u8 reg_hwparafile = 1; - - _rtl92c_phy_init_bb_rf_register_definition(hw); - regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, - regval | BIT(13) | BIT(0) | BIT(1)); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); - rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, - FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | - FEN_BB_GLB_RSTn | FEN_BBRSTB); - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); - regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); - rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); - if (reg_hwparafile == 1) - rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); - return rtstatus; -} - -bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) +static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 i; @@ -177,7 +179,7 @@ bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) } bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype) + u8 configtype) { int i; u32 *phy_regarray_table; @@ -236,7 +238,7 @@ bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, } bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype) + u8 configtype) { struct rtl_priv *rtlpriv = rtl_priv(hw); int i; @@ -274,7 +276,7 @@ bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, return true; } -bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, +bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, enum radio_path rfpath) { @@ -364,7 +366,7 @@ bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, return true; } -void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw) +static void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -378,8 +380,10 @@ void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw) rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? "20MHz" : "40MHz")) - if (is_hal_stop(rtlhal)) + if (is_hal_stop(rtlhal)) { + rtlphy->set_bwmode_inprogress = false; return; + } reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); @@ -389,16 +393,13 @@ void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw) reg_bw_opmode |= BW_OPMODE_20MHZ; rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); break; - case HT_CHANNEL_WIDTH_20_40: reg_bw_opmode &= ~BW_OPMODE_20MHZ; rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - reg_prsr_rsc = (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); break; - default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); @@ -414,10 +415,12 @@ void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw) case HT_CHANNEL_WIDTH_20_40: rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, (mac->cur_40_prime_sc >> 1)); rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); + rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), (mac->cur_40_prime_sc == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); @@ -427,11 +430,34 @@ void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw) ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); break; } - rtl92c_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); +#if 0 /* temporary */ + rtl92ce_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); +#endif rtlphy->set_bwmode_inprogress = false; RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); } +void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_bw = rtlphy->current_chan_bw; + + if (rtlphy->set_bwmode_inprogress) + return; + rtlphy->set_bwmode_inprogress = true; + if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtl92c_phy_set_bw_mode_callback(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("FALSE driver sleep or unload\n")); + rtlphy->set_bwmode_inprogress = false; + rtlphy->current_chan_bw = tmp_bw; + } +} + void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) { u8 tmpreg; @@ -477,6 +503,36 @@ void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) } } +static void _rtl92ce_phy_set_rf_sleep(struct ieee80211_hw *hw) +{ + u32 u4b_tmp; + u8 delay = 5; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + while (u4b_tmp != 0 && delay > 0) { + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + delay--; + } + if (delay == 0) { + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + ("Switch RF timeout !!!.\n")); + return; + } + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); +} + static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state) { @@ -523,33 +579,6 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, break; } case ERFOFF:{ - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (skb_queue_len(&ring->queue) == 0 || - queue_id == BEACON_QUEUE) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("eRf Off/Sleep: %d times " - "TcbBusyQueue[%d] " - "=%d before doze!\n", (i + 1), - queue_id, - skb_queue_len(&ring->queue))); - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("\nERFOFF: %d times " - "TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue))); - break; - } - } if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, ("IPS Set eRf nic disable\n")); @@ -581,6 +610,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, "TcbBusyQueue[%d] =%d before " "doze!\n", (i + 1), queue_id, skb_queue_len(&ring->queue))); + udelay(10); i++; } @@ -599,7 +629,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies))); ppsc->last_sleep_jiffies = jiffies; - _rtl92c_phy_set_rf_sleep(hw); + _rtl92ce_phy_set_rf_sleep(hw); break; } default: @@ -614,10 +644,11 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, return bresult; } -bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, +bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state) { struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = false; if (rfpwr_state == ppsc->rfpwr_state) diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h index a37267e3fc22..eb93088d0ed8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h @@ -39,6 +39,7 @@ #define RT_CANNOT_IO(hw) false #define HIGHPOWER_RADIOA_ARRAYLEN 22 +#define IQK_ADDA_REG_NUM 16 #define MAX_TOLERANCE 5 #define IQK_DELAY_TIME 1 @@ -56,6 +57,8 @@ #define IQK_ADDA_REG_NUM 16 #define IQK_MAC_REG_NUM 4 +#define IQK_DELAY_TIME 1 + #define RF90_PATH_MAX 2 #define CT_OFFSET_MAC_ADDR 0X16 @@ -76,7 +79,7 @@ #define CT_OFFSET_CUSTOMER_ID 0x7F #define RTL92C_MAX_PATH_NUM 2 -#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 + enum swchnlcmd_id { CMDID_END, CMDID_SET_TXPOWEROWER_LEVEL, @@ -184,43 +187,44 @@ struct tx_power_struct { u32 mcs_original_offset[4][16]; }; -extern u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, +bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); +u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); -extern void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, +void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, u32 data); -extern u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, +u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask); extern void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask, u32 data); -extern bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); + enum radio_path rfpath, u32 regaddr, + u32 bitmask, u32 data); +bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw); -extern bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); -extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, +bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); +bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, enum radio_path rfpath); -extern void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -extern void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, +void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel); -extern void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -extern bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, +void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm); -extern void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, +void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); -extern void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw); -extern void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, +void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, enum nl80211_channel_type ch_type); -extern void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); -extern u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); -extern void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); -extern void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, +void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); +u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); +void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); +void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval); void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); +void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, enum radio_path rfpath); -extern bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, +bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath); bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, @@ -237,9 +241,6 @@ u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask); void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset, u32 data); -void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, - u32 data); void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset, u32 data); @@ -250,5 +251,7 @@ bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); +bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c index e301b12e281a..90d0f2cf3b27 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c @@ -34,9 +34,9 @@ #include "rf.h" #include "dm.h" -static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw); +static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw); -void rtl92c_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -62,7 +62,7 @@ void rtl92c_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) } void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel) + u8 *ppowerlevel) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -128,8 +128,7 @@ void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, tmpval = tx_agc[RF90_PATH_A] >> 8; - if (mac->mode == WIRELESS_MODE_B) - tmpval = tmpval & 0xff00ffff; + tmpval = tmpval & 0xff00ffff; rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); @@ -440,16 +439,17 @@ bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw) else rtlphy->num_total_rfpath = 2; - return _rtl92c_phy_rf6052_config_parafile(hw); + return _rtl92ce_phy_rf6052_config_parafile(hw); + } -static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw) +static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); u32 u4_regvalue = 0; u8 rfpath; - bool rtstatus; + bool rtstatus = true; struct bb_reg_def *pphyreg; for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { @@ -484,12 +484,12 @@ static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw) switch (rfpath) { case RF90_PATH_A: - rtstatus = rtl92ce_phy_config_rf_with_headerfile(hw, - (enum radio_path) rfpath); + rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); break; case RF90_PATH_B: - rtstatus = rtl92ce_phy_config_rf_with_headerfile(hw, - (enum radio_path) rfpath); + rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); break; case RF90_PATH_C: break; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h index 3aa520c1c171..39ff03685986 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h @@ -34,14 +34,11 @@ #define RF6052_MAX_REG 0x3F #define RF6052_MAX_PATH 2 -extern void rtl92c_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, - u8 bandwidth); -extern void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); -bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw); -bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); - +extern void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, + u8 bandwidth); +extern void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +extern void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); +extern bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw); #endif -- cgit v1.2.3-58-ga151 From 76c34f910a5c99a402de5068444563d4c151e794 Mon Sep 17 00:00:00 2001 From: Chaoming_Li Date: Mon, 25 Apr 2011 12:54:05 -0500 Subject: rtlwifi: rtl8192ce: Change rtl8192ce routines phy and trx and modify rtl8192cu for addition of rtl8192se and rtl8192de Change rtl8192ce routines phy and trx for addition of RTL8192SE and RTL8192DE. In addition, make necessary modifications to rtl8192cu. This patch also removes the temporary patches needed to enable intermediate steps to build without error. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 4 - drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c | 13 +- drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | 2 - drivers/net/wireless/rtlwifi/rtl8192ce/phy.c | 25 +-- drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 2 - drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | 174 +++++++-------------- drivers/net/wireless/rtlwifi/rtl8192ce/trx.h | 7 +- drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | 14 +- drivers/net/wireless/rtlwifi/rtl8192cu/hw.h | 5 +- drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 48 +++--- drivers/net/wireless/rtlwifi/rtl8192cu/trx.h | 5 +- drivers/net/wireless/rtlwifi/wifi.h | 5 - 13 files changed, 109 insertions(+), 197 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index e496361fa2c6..aeb0901ce711 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -584,9 +584,7 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) _rtl_update_earlymode_info(hw, skb, &tcb_desc, tid); -#if 0 /* temporary */ rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); -#endif } } } @@ -1100,10 +1098,8 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) hdr = rtl_get_hdr(pskb); info = IEEE80211_SKB_CB(pskb); pdesc = &ring->desc[0]; -#if 0 /* temporary */ rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, info, pskb, BEACON_QUEUE, &tcb_desc); -#endif __skb_queue_tail(&ring->queue, pskb); diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index 3915a1ba59fb..991d865cb38c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c @@ -82,7 +82,7 @@ void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, } EXPORT_SYMBOL(rtl92c_phy_set_bb_reg); -static u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, +u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset) { RT_ASSERT(false, ("deprecated!\n")); @@ -91,7 +91,7 @@ static u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, } EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_read); -static void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, +void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset, u32 data) { @@ -99,7 +99,7 @@ static void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, } EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_write); -static u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, +u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -150,7 +150,7 @@ static u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, } EXPORT_SYMBOL(_rtl92c_phy_rf_serial_read); -static void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, +void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset, u32 data) { @@ -208,7 +208,7 @@ bool rtl92c_phy_rf_config(struct ieee80211_hw *hw) } EXPORT_SYMBOL(rtl92c_phy_rf_config); -static bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) +bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -1364,8 +1364,7 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta, bool is2t) { - /* This routine is deliberately dummied out for later fixes */ -#if 0 +#if 0 /* This routine is deliberately dummied out for later fixes */ struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index bb604b8ee519..794b4b6d09a2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -930,10 +930,8 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) } rtlhal->last_hmeboxnum = 0; -#if 0 /* temporary */ rtl92c_phy_mac_config(hw); rtl92c_phy_bb_config(hw); -#endif rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; rtl92c_phy_rf_config(hw); rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c index bbba6f8a8349..604540160a31 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c @@ -366,7 +366,7 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, return true; } -static void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw) +void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -430,34 +430,11 @@ static void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw) ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); break; } -#if 0 /* temporary */ rtl92ce_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); -#endif rtlphy->set_bwmode_inprogress = false; RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); } -void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_bw = rtlphy->current_chan_bw; - - if (rtlphy->set_bwmode_inprogress) - return; - rtlphy->set_bwmode_inprogress = true; - if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtl92c_phy_set_bw_mode_callback(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("FALSE driver sleep or unload\n")); - rtlphy->set_bwmode_inprogress = false; - rtlphy->current_chan_bw = tmp_bw; - } -} - void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) { u8 tmpreg; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 5c920c6270c8..702dd11b9370 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -214,7 +214,6 @@ struct rtl_hal_ops rtl8192ce_hal_ops = { .switch_channel = rtl92c_phy_sw_chnl, .dm_watchdog = rtl92c_dm_watchdog, .scan_operation_backup = rtl92c_phy_scan_operation_backup, -#if 0 /* temporary */ .set_rf_power_state = rtl92c_phy_set_rf_power_state, .led_control = rtl92ce_led_control, .set_desc = rtl92ce_set_desc, @@ -234,7 +233,6 @@ struct rtl_hal_ops rtl8192ce_hal_ops = { .config_bb_with_pgheaderfile = _rtl92ce_phy_config_bb_with_pgheaderfile, .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate, .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower, -#endif }; struct rtl_mod_params rtl92ce_mod_params = { diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index 356b8513b8a6..f76d406535dc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -36,42 +36,16 @@ #include "trx.h" #include "led.h" -static enum rtl_desc_qsel _rtl92ce_map_hwqueue_to_fwqueue(__le16 fc, - unsigned int - skb_queue) +u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) { - enum rtl_desc_qsel qsel; + u16 fc = rtl_get_fc(skb); - if (unlikely(ieee80211_is_beacon(fc))) { - qsel = QSLT_BEACON; - return qsel; - } - - if (ieee80211_is_mgmt(fc)) { - qsel = QSLT_MGNT; - return qsel; - } + if (unlikely(ieee80211_is_beacon(fc))) + return QSLT_BEACON; + if (ieee80211_is_mgmt(fc)) + return QSLT_MGNT; - switch (skb_queue) { - case VO_QUEUE: - qsel = QSLT_VO; - break; - case VI_QUEUE: - qsel = QSLT_VI; - break; - case BE_QUEUE: - qsel = QSLT_BE; - break; - case BK_QUEUE: - qsel = QSLT_BK; - break; - default: - qsel = QSLT_BE; - RT_ASSERT(false, ("BE queue, skb_queue:%d," - " set qsel = 0x%X\n", skb_queue, QSLT_BE)); - break; - } - return qsel; + return skb->priority; } static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) @@ -255,6 +229,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, u8 evm, pwdb_all, rf_rx_num = 0; u8 i, max_spatial_stream; u32 rssi, total_rssi = 0; + bool in_powersavemode = false; bool is_cck_rate; is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); @@ -270,9 +245,13 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, u8 report, cck_highpwr; cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; - cck_highpwr = (u8) rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, - BIT(9)); + if (!in_powersavemode) + cck_highpwr = (u8) rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + BIT(9)); + else + cck_highpwr = false; + if (!cck_highpwr) { u8 cck_agc_rpt = cck_buf->cck_agc_rpt; report = cck_buf->cck_agc_rpt & 0xc0; @@ -398,6 +377,7 @@ static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw, if (rtlpriv->stats.ui_rssi.total_num++ >= PHY_RSSI_SLID_WIN_MAX) { + rtlpriv->stats.ui_rssi.total_num = PHY_RSSI_SLID_WIN_MAX; last_rssi = @@ -424,10 +404,6 @@ static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw, if (!pstats->is_cck && pstats->packet_toself) { for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; rfpath++) { - - if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath)) - continue; - if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { rtlpriv->stats.rx_rssi_percentage[rfpath] = pstats->rx_mimo_signalstrength[rfpath]; @@ -723,7 +699,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, struct sk_buff *skb, - unsigned int queue_index) + u8 hw_queue, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); @@ -732,16 +708,9 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, bool defaultadapter = true; struct ieee80211_sta *sta; u8 *pdesc = (u8 *) pdesc_tx; - struct rtl_tcb_desc tcb_desc; - u8 *qc = ieee80211_get_qos_ctl(hdr); - u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; u16 seq_number; __le16 fc = hdr->frame_control; - u8 rate_flag = info->control.rates[0].flags; - - enum rtl_desc_qsel fw_qsel = - _rtl92ce_map_hwqueue_to_fwqueue(fc, queue_index); - + u8 fw_qsel = _rtl92ce_map_hwqueue_to_fwqueue(skb, hw_queue); bool firstseg = ((hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); @@ -751,56 +720,68 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + u8 bw_40 = 0; + + rcu_read_lock(); + sta = get_sta(hw, mac->vif, mac->bssid); + if (mac->opmode == NL80211_IFTYPE_STATION) { + bw_40 = mac->bw_40; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta) + bw_40 = sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40; + } seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, sta, skb, &tcb_desc); + rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c)); + if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { + firstseg = true; + lastseg = true; + } if (firstseg) { SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - SET_TX_DESC_TX_RATE(pdesc, tcb_desc.hw_rate); + SET_TX_DESC_TX_RATE(pdesc, tcb_desc->hw_rate); - if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble) + if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) SET_TX_DESC_DATA_SHORTGI(pdesc, 1); - if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && - info->flags & IEEE80211_TX_CTL_AMPDU) { + if (info->flags & IEEE80211_TX_CTL_AMPDU) { SET_TX_DESC_AGG_BREAK(pdesc, 1); SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); } SET_TX_DESC_SEQ(pdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc.rts_enable && - !tcb_desc. + SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc->rts_enable && + !tcb_desc-> cts_enable) ? 1 : 0)); SET_TX_DESC_HW_RTS_ENABLE(pdesc, - ((tcb_desc.rts_enable - || tcb_desc.cts_enable) ? 1 : 0)); - SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc.cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc.rts_stbc) ? 1 : 0)); + ((tcb_desc->rts_enable + || tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); - SET_TX_DESC_RTS_RATE(pdesc, tcb_desc.rts_rate); + SET_TX_DESC_RTS_RATE(pdesc, tcb_desc->rts_rate); SET_TX_DESC_RTS_BW(pdesc, 0); - SET_TX_DESC_RTS_SC(pdesc, tcb_desc.rts_sc); + SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(pdesc, - ((tcb_desc.rts_rate <= DESC92C_RATE54M) ? - (tcb_desc.rts_use_shortpreamble ? 1 : 0) - : (tcb_desc.rts_use_shortgi ? 1 : 0))); + ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? + (tcb_desc->rts_use_shortpreamble ? 1 : 0) + : (tcb_desc->rts_use_shortgi ? 1 : 0))); - if (mac->bw_40) { - if (tcb_desc.packet_bw) { + if (bw_40) { + if (tcb_desc->packet_bw) { SET_TX_DESC_DATA_BW(pdesc, 1); SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); } else { SET_TX_DESC_DATA_BW(pdesc, 0); - - if (rate_flag & IEEE80211_TX_RC_DUP_DATA) { - SET_TX_DESC_TX_SUB_CARRIER(pdesc, - mac->cur_40_prime_sc); - } + SET_TX_DESC_TX_SUB_CARRIER(pdesc, + mac->cur_40_prime_sc); } } else { SET_TX_DESC_DATA_BW(pdesc, 0); @@ -810,8 +791,6 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_LINIP(pdesc, 0); SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); - rcu_read_lock(); - sta = ieee80211_find_sta(mac->vif, mac->bssid); if (sta) { u8 ampdu_density = sta->ht_cap.ampdu_density; SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); @@ -844,7 +823,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); SET_TX_DESC_DISABLE_FB(pdesc, 0); - SET_TX_DESC_USE_RATE(pdesc, tcb_desc.use_driver_rate ? 1 : 0); + SET_TX_DESC_USE_RATE(pdesc, tcb_desc->use_driver_rate ? 1 : 0); if (ieee80211_is_data_qos(fc)) { if (mac->rdg_en) { @@ -864,15 +843,14 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(pdesc, tcb_desc.ratr_index); - SET_TX_DESC_MACID(pdesc, tcb_desc.mac_id); + SET_TX_DESC_RATE_ID(pdesc, tcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, tcb_desc->mac_id); } else { - SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc.ratr_index); - SET_TX_DESC_MACID(pdesc, tcb_desc.ratr_index); + SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, tcb_desc->ratr_index); } - if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && - ppsc->fwctrl_lps) { + if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) { SET_TX_DESC_HWSEQ_EN(pdesc, 1); SET_TX_DESC_PKT_ID(pdesc, 8); @@ -1021,7 +999,7 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name) return ret; } -void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue) +void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) { struct rtl_priv *rtlpriv = rtl_priv(hw); if (hw_queue == BEACON_QUEUE) { @@ -1032,35 +1010,3 @@ void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue) } } -bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring; - struct rtl_tx_desc *pdesc; - u8 own; - unsigned long flags; - struct sk_buff *pskb = NULL; - - ring = &rtlpci->tx_ring[BEACON_QUEUE]; - - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - - pskb = __skb_dequeue(&ring->queue); - if (pskb) - kfree_skb(pskb); - - pdesc = &ring->desc[0]; - own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN); - - rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); - - __skb_queue_tail(&ring->queue, skb); - - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - - rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); - - return true; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h index b0b0b13dd0ae..0f1177137501 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h @@ -724,17 +724,16 @@ struct rx_desc_92c { void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc, struct ieee80211_tx_info *info, - struct sk_buff *skb, unsigned int qsel); + struct sk_buff *skb, u8 hw_queue, + struct rtl_tcb_desc *ptcb_desc); bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, struct ieee80211_rx_status *rx_status, u8 *pdesc, struct sk_buff *skb); void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val); u32 rtl92ce_get_desc(u8 *pdesc, bool istx, u8 desc_name); -void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue); +void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool b_firstseg, bool b_lastseg, struct sk_buff *skb); -bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); - #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 861f39fad3ec..52e2af58c1ed 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -39,10 +39,10 @@ #include "mac.h" #include "dm.h" #include "hw.h" +#include "../rtl8192ce/hw.h" #include "trx.h" #include "led.h" #include "table.h" -#include "../rtl8192ce/hw.h" static void _rtl92cu_phy_param_tab_init(struct ieee80211_hw *hw) { @@ -606,12 +606,10 @@ void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw) if (!IS_NORMAL_CHIP(rtlhal->version)) return; tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); -#if 0 /* temporary */ - rtlefuse->epromtype = (tmp_u1b & EEPROMSEL) ? + rtlefuse->epromtype = (tmp_u1b & BOOT_FROM_EEPROM) ? EEPROM_93C46 : EEPROM_BOOT_EFUSE; RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from %s\n", - (tmp_u1b & EEPROMSEL) ? "EERROM" : "EFUSE")); -#endif + (tmp_u1b & BOOT_FROM_EEPROM) ? "EERROM" : "EFUSE")); rtlefuse->autoload_failflag = (tmp_u1b & EEPROM_EN) ? false : true; RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload %s\n", (tmp_u1b & EEPROM_EN) ? "OK!!" : "ERR!!")); @@ -980,7 +978,7 @@ static void _rtl92cu_init_wmac_setting(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - mac->rx_conf = (RCR_APM | RCR_AM | RCR_ADF | RCR_AB | RCR_APP_FCS | + mac->rx_conf = (RCR_APM | RCR_AM | RCR_ADF | RCR_AB | RCR_APPFCS | RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL | RCR_APP_MIC | RCR_APP_PHYSTS | RCR_ACRC32); rtl_write_dword(rtlpriv, REG_RCR, mac->rx_conf); @@ -2185,7 +2183,9 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } } -void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw) +void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h index 17dc5a3151cf..32f85cba106a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h @@ -98,13 +98,14 @@ void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw, u32 add_msr, u32 rm_msr); void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw); +void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level); void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level); void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw); bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid); void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -static u8 _rtl92c_get_chnl_group(u8 chnl); int rtl92c_download_fw(struct ieee80211_hw *hw); void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 71244a38d49e..bee7c1480f63 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -94,7 +94,7 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = { .update_interrupt_mask = rtl92cu_update_interrupt_mask, .get_hw_reg = rtl92cu_get_hw_reg, .set_hw_reg = rtl92cu_set_hw_reg, - .update_rate_table = rtl92cu_update_hal_rate_table, + .update_rate_tbl = rtl92cu_update_hal_rate_table, .update_rate_mask = rtl92cu_update_hal_rate_mask, .fill_tx_desc = rtl92cu_tx_fill_desc, .fill_fake_txdesc = rtl92cu_fill_fake_txdesc, diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index cc5de0726938..79c98f62175f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -498,14 +498,14 @@ static void _rtl_tx_desc_checksum(u8 *txdesc) void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, struct sk_buff *skb, - unsigned int queue_index) + u8 queue_index, + struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool defaultadapter = true; - struct ieee80211_sta *sta = info->control.sta; - struct rtl_tcb_desc tcb_desc; + struct ieee80211_sta *sta = info->control.sta = info->control.sta; u8 *qc = ieee80211_get_qos_ctl(hdr); u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; u16 seq_number; @@ -517,15 +517,15 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, u8 *txdesc; seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, sta, skb, &tcb_desc); + rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); txdesc = (u8 *)skb_push(skb, RTL_TX_HEADER_SIZE); memset(txdesc, 0, RTL_TX_HEADER_SIZE); SET_TX_DESC_PKT_SIZE(txdesc, pktlen); SET_TX_DESC_LINIP(txdesc, 0); SET_TX_DESC_PKT_OFFSET(txdesc, RTL_DUMMY_OFFSET); SET_TX_DESC_OFFSET(txdesc, RTL_TX_HEADER_SIZE); - SET_TX_DESC_TX_RATE(txdesc, tcb_desc.hw_rate); - if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble) + SET_TX_DESC_TX_RATE(txdesc, tcb_desc->hw_rate); + if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) SET_TX_DESC_DATA_SHORTGI(txdesc, 1); if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && info->flags & IEEE80211_TX_CTL_AMPDU) { @@ -535,21 +535,21 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_AGG_BREAK(txdesc, 1); } SET_TX_DESC_SEQ(txdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable && - !tcb_desc.cts_enable) ? 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable || - tcb_desc.cts_enable) ? 1 : 0)); - SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc.cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc.rts_stbc) ? 1 : 0)); - SET_TX_DESC_RTS_RATE(txdesc, tcb_desc.rts_rate); + SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable && + !tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable || + tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); + SET_TX_DESC_RTS_RATE(txdesc, tcb_desc->rts_rate); SET_TX_DESC_RTS_BW(txdesc, 0); - SET_TX_DESC_RTS_SC(txdesc, tcb_desc.rts_sc); + SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(txdesc, - ((tcb_desc.rts_rate <= DESC92C_RATE54M) ? - (tcb_desc.rts_use_shortpreamble ? 1 : 0) - : (tcb_desc.rts_use_shortgi ? 1 : 0))); + ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? + (tcb_desc->rts_use_shortpreamble ? 1 : 0) + : (tcb_desc->rts_use_shortgi ? 1 : 0))); if (mac->bw_40) { - if (tcb_desc.packet_bw) { + if (tcb_desc->packet_bw) { SET_TX_DESC_DATA_BW(txdesc, 1); SET_TX_DESC_DATA_SC(txdesc, 3); } else { @@ -590,7 +590,7 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_DATA_RATE_FB_LIMIT(txdesc, 0x1F); SET_TX_DESC_RTS_RATE_FB_LIMIT(txdesc, 0xF); SET_TX_DESC_DISABLE_FB(txdesc, 0); - SET_TX_DESC_USE_RATE(txdesc, tcb_desc.use_driver_rate ? 1 : 0); + SET_TX_DESC_USE_RATE(txdesc, tcb_desc->use_driver_rate ? 1 : 0); if (ieee80211_is_data_qos(fc)) { if (mac->rdg_en) { RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, @@ -600,11 +600,11 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, } } if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(txdesc, tcb_desc.ratr_index); - SET_TX_DESC_MACID(txdesc, tcb_desc.mac_id); + SET_TX_DESC_RATE_ID(txdesc, tcb_desc->ratr_index); + SET_TX_DESC_MACID(txdesc, tcb_desc->mac_id); } else { - SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc.ratr_index); - SET_TX_DESC_MACID(txdesc, tcb_desc.ratr_index); + SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc->ratr_index); + SET_TX_DESC_MACID(txdesc, tcb_desc->ratr_index); } if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && ppsc->fwctrl_lps) { @@ -656,7 +656,7 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); __le16 fc = hdr->frame_control; - memset(pdesc, 0, RTL_TX_HEADER_SIZE); + memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE); if (firstseg) SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h index b396d46edbb7..53de5f66e242 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h @@ -37,6 +37,8 @@ #define RTL92C_SIZE_MAX_RX_BUFFER 15360 /* 8192 */ #define RX_DRV_INFO_SIZE_UNIT 8 +#define RTL_AGG_ON 1 + enum usb_rx_agg_mode { USB_RX_AGG_DISABLE, USB_RX_AGG_DMA, @@ -419,7 +421,8 @@ struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *, void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, struct sk_buff *skb, - unsigned int queue_index); + u8 queue_index, + struct rtl_tcb_desc *tcb_desc); void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, u32 buffer_len, bool bIsPsPoll); void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 683f7f71b6cd..690508feafcc 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -1370,13 +1370,8 @@ struct rtl_hal_ops { u32 add_msr, u32 rm_msr); void (*get_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); void (*set_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); -#if 1 /* temporary */ void (*update_rate_tbl) (struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 rssi_level); -#endif -#if 1 /* temporary */ - void (*update_rate_table) (struct ieee80211_hw *hw); -#endif void (*update_rate_mask) (struct ieee80211_hw *hw, u8 rssi_level); void (*fill_tx_desc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, -- cgit v1.2.3-58-ga151 From d3bb1429a2c1470d1f84646c00e34dc6784ee06e Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 25 Apr 2011 13:23:20 -0500 Subject: rtlwifi: rtl8192ce: rtl8192cu: Fix most sparse warnings Fix most sparse warnings in rtlwifi, rtl8192ce and rtl8192cu drivers. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/base.c | 6 +- drivers/net/wireless/rtlwifi/efuse.c | 4 +- drivers/net/wireless/rtlwifi/pci.c | 170 +++------------------ drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 45 ------ drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c | 16 +- drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h | 16 ++ drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192ce/phy.c | 69 --------- drivers/net/wireless/rtlwifi/rtl8192ce/phy.h | 4 + drivers/net/wireless/rtlwifi/rtl8192ce/reg.h | 2 - drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 8 +- drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | 10 +- drivers/net/wireless/rtlwifi/rtl8192cu/phy.c | 14 +- drivers/net/wireless/rtlwifi/rtl8192cu/phy.h | 14 ++ drivers/net/wireless/rtlwifi/rtl8192cu/rf.c | 4 +- drivers/net/wireless/rtlwifi/rtl8192cu/rf.h | 4 + drivers/net/wireless/rtlwifi/wifi.h | 7 +- 17 files changed, 93 insertions(+), 302 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 2df99463a681..d3666573d6b8 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -795,7 +795,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len + SNAP_SIZE + PROTOC_TYPE_SIZE); ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE); - ether_type = ntohs(ether_type); + /* ether_type = ntohs(ether_type); */ if (ETH_P_IP == ether_type) { if (IPPROTO_UDP == ip->protocol) { @@ -1105,7 +1105,7 @@ u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie) /* when we use 2 rx ants we send IEEE80211_SMPS_OFF */ /* when we use 1 rx ant we send IEEE80211_SMPS_STATIC */ -struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw, +static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw, enum ieee80211_smps_mode smps, u8 *da, u8 *bssid) { struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); @@ -1230,7 +1230,7 @@ static bool rtl_chk_vendor_ouisub(struct ieee80211_hw *hw, return matched; } -bool rtl_find_221_ie(struct ieee80211_hw *hw, u8 *data, +static bool rtl_find_221_ie(struct ieee80211_hw *hw, u8 *data, unsigned int len) { struct ieee80211_mgmt *mgmt = (void *)data; diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index 664703ce9da8..510d42edb8ca 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c @@ -235,7 +235,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 efuse_tbl[rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]]; + u8 efuse_tbl[HWSET_MAX_SIZE]; u8 rtemp8[1]; u16 efuse_addr = 0; u8 offset, wren; @@ -245,7 +245,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) rtlpriv->cfg->maps[EFUSE_MAX_SECTION_MAP]; const u32 efuse_len = rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; - u16 efuse_word[efuse_max_section][EFUSE_MAX_WORD_UNIT]; + u16 efuse_word[EFUSE_MAX_SECTION][EFUSE_MAX_WORD_UNIT]; u16 efuse_utilized = 0; u8 efuse_usage; diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index aeb0901ce711..367d9b4ebd20 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -48,11 +48,11 @@ static const u8 ac_to_hwq[] = { BK_QUEUE }; -u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, +static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, struct sk_buff *skb) { struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u16 fc = rtl_get_fc(skb); + __le16 fc = rtl_get_fc(skb); u8 queue_index = skb_get_queue_mapping(skb); if (unlikely(ieee80211_is_beacon(fc))) @@ -181,71 +181,6 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) ppsc->support_aspm = false; } -/*Disable L0s dirtectly. We will disable host L0s by default. */ -void rtl_pci_disable_host_l0s(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 pcibridge_busnum = pcipriv->ndis_adapter.pcibridge_busnum; - u8 pcibridge_devnum = pcipriv->ndis_adapter.pcibridge_devnum; - u8 pcibridge_funcnum = pcipriv->ndis_adapter.pcibridge_funcnum; - u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport; - u8 num4bytes = pcipriv->ndis_adapter.num4bytes; - u8 u_pcibridge_aspmsetting = 0; - - /*Read Link Control Register */ - rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, - pcicfg_addrport + (num4bytes << 2)); - rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &u_pcibridge_aspmsetting); - - if (u_pcibridge_aspmsetting & BIT(0)) - u_pcibridge_aspmsetting &= ~(BIT(0)); - - rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, - pcicfg_addrport + (num4bytes << 2)); - rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, u_pcibridge_aspmsetting); - - udelay(50); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - ("PciBridge busnumber[%x], DevNumbe[%x], " - "funcnumber[%x], Write reg[%x] = %lx\n", - pcibridge_busnum, pcibridge_devnum, pcibridge_funcnum, - (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10), - (pcipriv->ndis_adapter.pcibridge_linkctrlreg | - (rtlpci->const_devicepci_aspm_setting & ~BIT(0))))); -} - -/*Enable rtl8192ce backdoor to control ASPM and clock request.*/ -bool rtl_pci_enable_back_door(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; - bool bresult = true; - u8 value; - - pci_read_config_byte(rtlpci->pdev, 0x70f, &value); - - /*0x70f BIT(7) is used to control L0S */ - if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) { - value |= BIT(7); - } else { - /*Set 0x70f to 0x23 when non-Intel platform. */ - value = 0x23; - } - - pci_write_config_byte(rtlpci->pdev, 0x70f, value); - - pci_read_config_byte(rtlpci->pdev, 0x719, &value); - /*0x719 BIT(3) is for L1 BIT(4) is for clock request */ - value |= (BIT(3) | BIT(4)); - pci_write_config_byte(rtlpci->pdev, 0x719, value); - - return bresult; -} - static bool _rtl_pci_platform_switch_device_pci_aspm( struct ieee80211_hw *hw, u8 value) @@ -426,7 +361,7 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) return status; } -void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) +static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) { struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset; @@ -618,9 +553,9 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) skb = __skb_dequeue(&ring->queue); pci_unmap_single(rtlpci->pdev, - le32_to_cpu(rtlpriv->cfg->ops-> + rtlpriv->cfg->ops-> get_desc((u8 *) entry, true, - HW_DESC_TXBUFF_ADDR)), + HW_DESC_TXBUFF_ADDR), skb->len, PCI_DMA_TODEVICE); /* remove early mode header */ @@ -844,7 +779,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) } done: - bufferaddress = cpu_to_le32(*((dma_addr_t *)skb->cb)); + bufferaddress = (*((dma_addr_t *)skb->cb)); tmp_one = 1; rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false, HW_DESC_RXBUFF_ADDR, @@ -868,75 +803,6 @@ done: } -void _rtl_pci_tx_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - int prio; - - for (prio = 0; prio < RTL_PCI_MAX_TX_QUEUE_COUNT; prio++) { - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[prio]; - - while (skb_queue_len(&ring->queue)) { - struct rtl_tx_desc *entry = &ring->desc[ring->idx]; - struct sk_buff *skb; - struct ieee80211_tx_info *info; - u8 own; - - /* - *beacon packet will only use the first - *descriptor defautly, and the own may not - *be cleared by the hardware, and - *beacon will free in prepare beacon - */ - if (prio == BEACON_QUEUE || prio == TXCMD_QUEUE || - prio == HCCA_QUEUE) - break; - - own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, - true, - HW_DESC_OWN); - - if (own) - break; - - skb = __skb_dequeue(&ring->queue); - pci_unmap_single(rtlpci->pdev, - le32_to_cpu(rtlpriv->cfg->ops-> - get_desc((u8 *) entry, - true, - HW_DESC_TXBUFF_ADDR)), - skb->len, PCI_DMA_TODEVICE); - - ring->idx = (ring->idx + 1) % ring->entries; - - info = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(info); - - info->flags |= IEEE80211_TX_STAT_ACK; - /*info->status.rates[0].count = 1; */ - - ieee80211_tx_status_irqsafe(hw, skb); - - if ((ring->entries - skb_queue_len(&ring->queue)) - == 2 && prio != BEACON_QUEUE) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("more desc left, wake " - "skb_queue@%d,ring->idx = %d," - "skb_queue_len = 0x%d\n", - prio, ring->idx, - skb_queue_len(&ring->queue))); - - ieee80211_wake_queue(hw, - skb_get_queue_mapping - (skb)); - } - - skb = NULL; - } - } -} - static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) { struct ieee80211_hw *hw = dev_id; @@ -1202,9 +1068,9 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, ("queue:%d, ring_addr:%p\n", prio, ring)); for (i = 0; i < entries; i++) { - nextdescaddress = cpu_to_le32((u32) dma + + nextdescaddress = (u32) dma + ((i + 11) % entries) * - sizeof(*ring)); + sizeof(*ring); rtlpriv->cfg->ops->set_desc((u8 *)&(ring[i]), true, HW_DESC_TX_NEXTDESC_ADDR, @@ -1268,7 +1134,7 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw) rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE); - bufferaddress = cpu_to_le32(*((dma_addr_t *)skb->cb)); + bufferaddress = (*((dma_addr_t *)skb->cb)); rtlpriv->cfg->ops->set_desc((u8 *)entry, false, HW_DESC_RXBUFF_ADDR, (u8 *)&bufferaddress); @@ -1299,9 +1165,9 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw, struct sk_buff *skb = __skb_dequeue(&ring->queue); pci_unmap_single(rtlpci->pdev, - le32_to_cpu(rtlpriv->cfg-> + rtlpriv->cfg-> ops->get_desc((u8 *) entry, true, - HW_DESC_TXBUFF_ADDR)), + HW_DESC_TXBUFF_ADDR), skb->len, PCI_DMA_TODEVICE); kfree_skb(skb); ring->idx = (ring->idx + 1) % ring->entries; @@ -1433,11 +1299,11 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) __skb_dequeue(&ring->queue); pci_unmap_single(rtlpci->pdev, - le32_to_cpu(rtlpriv->cfg->ops-> + rtlpriv->cfg->ops-> get_desc((u8 *) entry, true, - HW_DESC_TXBUFF_ADDR)), + HW_DESC_TXBUFF_ADDR), skb->len, PCI_DMA_TODEVICE); kfree_skb(skb); ring->idx = (ring->idx + 1) % ring->entries; @@ -1484,7 +1350,7 @@ static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw, return true; } -int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb, +static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb, struct rtl_tcb_desc *ptcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -1623,7 +1489,7 @@ static void rtl_pci_flush(struct ieee80211_hw *hw, bool drop) } } -void rtl_pci_deinit(struct ieee80211_hw *hw) +static void rtl_pci_deinit(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); @@ -1638,7 +1504,7 @@ void rtl_pci_deinit(struct ieee80211_hw *hw) } -int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) +static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) { struct rtl_priv *rtlpriv = rtl_priv(hw); int err; @@ -1655,7 +1521,7 @@ int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) return 1; } -int rtl_pci_start(struct ieee80211_hw *hw) +static int rtl_pci_start(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -1690,7 +1556,7 @@ int rtl_pci_start(struct ieee80211_hw *hw) return 0; } -void rtl_pci_stop(struct ieee80211_hw *hw) +static void rtl_pci_stop(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index bfc84054cc07..97183829b9be 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -1238,51 +1238,6 @@ static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) dm_pstable.rssi_val_min = 0; } -void rtl92c_dm_1r_cca(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - if (dm_pstable.rssi_val_min != 0) { - if (dm_pstable.pre_ccastate == CCA_2R) { - if (dm_pstable.rssi_val_min >= 35) - dm_pstable.cur_ccasate = CCA_1R; - else - dm_pstable.cur_ccasate = CCA_2R; - } else { - if (dm_pstable.rssi_val_min <= 30) - dm_pstable.cur_ccasate = CCA_2R; - else - dm_pstable.cur_ccasate = CCA_1R; - } - } else { - dm_pstable.cur_ccasate = CCA_MAX; - } - - if (dm_pstable.pre_ccastate != dm_pstable.cur_ccasate) { - if (dm_pstable.cur_ccasate == CCA_1R) { - if (get_rf_type(rtlphy) == RF_2T2R) { - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, - MASKBYTE0, 0x13); - rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x20); - } else { - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, - MASKBYTE0, 0x23); - rtl_set_bbreg(hw, 0xe70, 0x7fc00000, 0x10c); - } - } else { - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, - 0x33); - rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x63); - } - dm_pstable.pre_ccastate = dm_pstable.cur_ccasate; - } - - RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, ("CCAStage = %s\n", - (dm_pstable.cur_ccasate == - 0) ? "1RCCA" : "2RCCA")); -} - void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) { static u8 initialize; diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index 991d865cb38c..c5424cad43cb 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c @@ -83,7 +83,7 @@ void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, EXPORT_SYMBOL(rtl92c_phy_set_bb_reg); u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) + enum radio_path rfpath, u32 offset) { RT_ASSERT(false, ("deprecated!\n")); return 0; @@ -92,15 +92,15 @@ u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_read); void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data) + enum radio_path rfpath, u32 offset, + u32 data) { RT_ASSERT(false, ("deprecated!\n")); } EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_write); u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) + enum radio_path rfpath, u32 offset) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -151,8 +151,8 @@ u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, EXPORT_SYMBOL(_rtl92c_phy_rf_serial_read); void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data) + enum radio_path rfpath, u32 offset, + u32 data) { u32 data_and_addr; u32 newoffset; @@ -250,8 +250,8 @@ bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) EXPORT_SYMBOL(_rtl92c_phy_bb8192c_config_parafile); void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, - u32 data) + u32 regaddr, u32 bitmask, + u32 data) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h index b09a45842d61..9a264c0d6127 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h @@ -238,5 +238,21 @@ void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, u8 channel, u8 *stage, u8 *step, u32 *delay); +u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw); +u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset); +void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data); +u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset); +void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data); +bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); +void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, + u32 data); +bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 794b4b6d09a2..4a56138eb33c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -2177,7 +2177,7 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, } } -void rtl8192ce_bt_var_init(struct ieee80211_hw *hw) +static void rtl8192ce_bt_var_init(struct ieee80211_hw *hw) { struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c index 604540160a31..73ae8a431848 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c @@ -366,75 +366,6 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, return true; } -void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 reg_bw_opmode; - u8 reg_prsr_rsc; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - ("Switch to %s bandwidth\n", - rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? - "20MHz" : "40MHz")) - - if (is_hal_stop(rtlhal)) { - rtlphy->set_bwmode_inprogress = false; - return; - } - - reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); - reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - reg_bw_opmode |= BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - break; - case HT_CHANNEL_WIDTH_20_40: - reg_bw_opmode &= ~BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - reg_prsr_rsc = - (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); - break; - } - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); - break; - case HT_CHANNEL_WIDTH_20_40: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); - - rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, - (mac->cur_40_prime_sc >> 1)); - rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); - - rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), - (mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); - break; - } - rtl92ce_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); - rtlphy->set_bwmode_inprogress = false; - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); -} - void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) { u8 tmpreg; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h index eb93088d0ed8..ad580852cc76 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h @@ -253,5 +253,9 @@ bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state); +bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype); +bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h index 115b3f841ddc..598cecc63f41 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h @@ -543,8 +543,6 @@ #define IMR_OCPINT BIT(1) #define IMR_WLANOFF BIT(0) -#define HWSET_MAX_SIZE 128 -#define EFUSE_MAX_SECTION 16 #define EFUSE_REAL_CONTENT_LEN 512 #define EEPROM_DEFAULT_TSSI 0x0 diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 702dd11b9370..390bbb5ee11d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -42,7 +42,7 @@ #include "trx.h" #include "led.h" -void rtl92c_init_aspm_vars(struct ieee80211_hw *hw) +static void rtl92c_init_aspm_vars(struct ieee80211_hw *hw) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); @@ -185,7 +185,7 @@ void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw) } } -struct rtl_hal_ops rtl8192ce_hal_ops = { +static struct rtl_hal_ops rtl8192ce_hal_ops = { .init_sw_vars = rtl92c_init_sw_vars, .deinit_sw_vars = rtl92c_deinit_sw_vars, .read_eeprom_info = rtl92ce_read_eeprom_info, @@ -235,14 +235,14 @@ struct rtl_hal_ops rtl8192ce_hal_ops = { .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower, }; -struct rtl_mod_params rtl92ce_mod_params = { +static struct rtl_mod_params rtl92ce_mod_params = { .sw_crypto = false, .inactiveps = true, .swctrl_lps = false, .fwctrl_lps = true, }; -struct rtl_hal_cfg rtl92ce_hal_cfg = { +static struct rtl_hal_cfg rtl92ce_hal_cfg = { .bar_id = 2, .write_readback = true, .name = "rtl92c_pci", diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index f76d406535dc..54b2bd53d36a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -36,9 +36,9 @@ #include "trx.h" #include "led.h" -u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) +static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) { - u16 fc = rtl_get_fc(skb); + __le16 fc = rtl_get_fc(skb); if (unlikely(ieee80211_is_beacon(fc))) return QSLT_BEACON; @@ -795,7 +795,6 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, u8 ampdu_density = sta->ht_cap.ampdu_density; SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); } - rcu_read_unlock(); if (info->control.hw_key) { struct ieee80211_key_conf *keyconf = @@ -834,13 +833,14 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, } } } + rcu_read_unlock(); SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); if (rtlpriv->dm.useramask) { SET_TX_DESC_RATE_ID(pdesc, tcb_desc->ratr_index); @@ -901,7 +901,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len)); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); SET_TX_DESC_RATE_ID(pdesc, 7); SET_TX_DESC_MACID(pdesc, 0); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c index 4e020e654e6b..9a3d0239e27e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c @@ -38,7 +38,7 @@ #include "table.h" u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask) + enum radio_path rfpath, u32 regaddr, u32 bitmask) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 original_value, readback_value, bitshift; @@ -64,8 +64,8 @@ u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, } void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data) + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -163,7 +163,7 @@ bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) } bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype) + u8 configtype) { int i; u32 *phy_regarray_table; @@ -223,7 +223,7 @@ bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, } bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype) + u8 configtype) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -459,7 +459,7 @@ void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) } } -bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, +static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -595,7 +595,7 @@ bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, } bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) + enum rf_pwrstate rfpwr_state) { struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool bresult = false; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h index 06299559ab68..ff81a61729d7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h @@ -34,3 +34,17 @@ bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath); void rtl92c_phy_set_io(struct ieee80211_hw *hw); bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw); +u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, u32 bitmask); +void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data); +bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw); +bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype); +void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); +bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype); +void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw); +bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c index 1c79c226f145..c7576ec4744e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c @@ -62,7 +62,7 @@ void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) } void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel) + u8 *ppowerlevel) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -389,7 +389,7 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, } void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel) + u8 *ppowerlevel, u8 channel) { u32 writeVal[2], powerBase0[2], powerBase1[2]; u8 index = 0; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h index 86c2728cfa00..500a2094b6bb 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h @@ -43,5 +43,9 @@ extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw); bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, enum radio_path rfpath); +void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); #endif diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 690508feafcc..a406c616b697 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -303,6 +303,9 @@ enum hw_variables { HW_VAR_DATA_FILTER, }; +#define HWSET_MAX_SIZE 128 +#define EFUSE_MAX_SECTION 16 + enum _RT_MEDIA_STATUS { RT_MEDIA_DISCONNECT = 0, RT_MEDIA_CONNECT = 1 @@ -1963,9 +1966,9 @@ static inline struct ieee80211_hdr *rtl_get_hdr(struct sk_buff *skb) return (struct ieee80211_hdr *)(skb->data); } -static inline u16 rtl_get_fc(struct sk_buff *skb) +static inline __le16 rtl_get_fc(struct sk_buff *skb) { - return le16_to_cpu(rtl_get_hdr(skb)->frame_control); + return rtl_get_hdr(skb)->frame_control; } static inline u16 rtl_get_tid_h(struct ieee80211_hdr *hdr) -- cgit v1.2.3-58-ga151 From c989bb15e95a93e20fc86783264f6298116e8651 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 25 Apr 2011 18:35:48 -0700 Subject: cfg80211: fix regresion on reg user timeout The patch "cfg80211: add a timer for invalid user reg hints" introduced a regression for the case where a secondary identical regulatory hint from a user is sent. What would happen is the second hint would schedule delayed work in to catch a timeout but since we are never processing it given that the hint was already applied we'd always hit the timeout and and restore regulatory settings back to world regulatory domain. This is fixed by simply avoiding sheduling work if the hint was already applied. Tested-by: Felix Fietkau Reported-by: Felix Fietkau Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 2714379ce2d6..8982053f9961 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1455,7 +1455,8 @@ static void reg_process_hint(struct regulatory_request *reg_request) * We only time out user hints, given that they should be the only * source of bogus requests. */ - if (reg_request->initiator == NL80211_REGDOM_SET_BY_USER) + if (r != -EALREADY && + reg_request->initiator == NL80211_REGDOM_SET_BY_USER) schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); } -- cgit v1.2.3-58-ga151 From dbf80dcbd8ca0c50f343401fedd2d6200cb8097e Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Sat, 16 Apr 2011 00:34:40 +0000 Subject: e1000e: implement ethtool set_phys_id Based on a patch from Stephen Hemminger . The new ethtool set_phys_id takes over controlling the LED for identifying boards. This fixes the lockout during that period. For this device lots of extra infrastructure can also be removed by using set_phys_id. v2: - return blink frequency for parts that do not support blink in h/w - add blink_led function pointers for devices that do support blink in h/w to cleanup the test for this functionality Signed-off-by: Bruce Allan Cc: Stephen Hemminger Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/e1000e/82571.c | 2 ++ drivers/net/e1000e/e1000.h | 6 +--- drivers/net/e1000e/es2lan.c | 1 + drivers/net/e1000e/ethtool.c | 71 +++++++++++++------------------------------- drivers/net/e1000e/hw.h | 1 + drivers/net/e1000e/ich8lan.c | 4 +++ drivers/net/e1000e/lib.c | 4 +-- drivers/net/e1000e/netdev.c | 2 -- 8 files changed, 32 insertions(+), 59 deletions(-) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index ae07d37903ba..8295f2192439 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -300,6 +300,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) func->set_lan_id = e1000_set_lan_id_single_port; func->check_mng_mode = e1000e_check_mng_mode_generic; func->led_on = e1000e_led_on_generic; + func->blink_led = e1000e_blink_led_generic; /* FWSM register */ mac->has_fwsm = true; @@ -320,6 +321,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) default: func->check_mng_mode = e1000e_check_mng_mode_generic; func->led_on = e1000e_led_on_generic; + func->blink_led = e1000e_blink_led_generic; /* FWSM register */ mac->has_fwsm = true; diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 3be5478dfdf1..9549879e66a0 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -391,13 +391,10 @@ struct e1000_adapter { bool fc_autoneg; - unsigned long led_status; - unsigned int flags; unsigned int flags2; struct work_struct downshift_task; struct work_struct update_phy_task; - struct work_struct led_blink_task; struct work_struct print_hang_task; bool idle_check; @@ -487,7 +484,6 @@ extern const char e1000e_driver_version[]; extern void e1000e_check_options(struct e1000_adapter *adapter); extern void e1000e_set_ethtool_ops(struct net_device *netdev); -extern void e1000e_led_blink_task(struct work_struct *work); extern int e1000e_up(struct e1000_adapter *adapter); extern void e1000e_down(struct e1000_adapter *adapter); @@ -575,7 +571,7 @@ extern s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data); extern void e1000e_config_collision_dist(struct e1000_hw *hw); extern s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw); extern s32 e1000e_force_mac_fc(struct e1000_hw *hw); -extern s32 e1000e_blink_led(struct e1000_hw *hw); +extern s32 e1000e_blink_led_generic(struct e1000_hw *hw); extern void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); extern s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw); extern void e1000e_reset_adaptive(struct e1000_hw *hw); diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c index 0279695b6942..f4bbeb22f51f 100644 --- a/drivers/net/e1000e/es2lan.c +++ b/drivers/net/e1000e/es2lan.c @@ -1434,6 +1434,7 @@ static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw) static struct e1000_mac_operations es2_mac_ops = { .read_mac_addr = e1000_read_mac_addr_80003es2lan, .id_led_init = e1000e_id_led_init, + .blink_led = e1000e_blink_led_generic, .check_mng_mode = e1000e_check_mng_mode_generic, /* check_for_link dependent on media type */ .cleanup_led = e1000e_cleanup_led_generic, diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index a31d280ffb6d..1d7bf4049c02 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -1851,64 +1851,35 @@ static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) return 0; } -/* toggle LED 4 times per second = 2 "blinks" per second */ -#define E1000_ID_INTERVAL (HZ/4) - -/* bit defines for adapter->led_status */ -#define E1000_LED_ON 0 - -void e1000e_led_blink_task(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, led_blink_task); - - if (test_and_change_bit(E1000_LED_ON, &adapter->led_status)) - adapter->hw.mac.ops.led_off(&adapter->hw); - else - adapter->hw.mac.ops.led_on(&adapter->hw); -} - -static void e1000_led_blink_callback(unsigned long data) -{ - struct e1000_adapter *adapter = (struct e1000_adapter *) data; - - schedule_work(&adapter->led_blink_task); - mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL); -} - -static int e1000_phys_id(struct net_device *netdev, u32 data) +static int e1000_set_phys_id(struct net_device *netdev, + enum ethtool_phys_id_state state) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - if (!data) - data = INT_MAX; + switch (state) { + case ETHTOOL_ID_ACTIVE: + if (!hw->mac.ops.blink_led) + return 2; /* cycle on/off twice per second */ - if ((hw->phy.type == e1000_phy_ife) || - (hw->mac.type == e1000_pchlan) || - (hw->mac.type == e1000_pch2lan) || - (hw->mac.type == e1000_82583) || - (hw->mac.type == e1000_82574)) { - if (!adapter->blink_timer.function) { - init_timer(&adapter->blink_timer); - adapter->blink_timer.function = - e1000_led_blink_callback; - adapter->blink_timer.data = (unsigned long) adapter; - } - mod_timer(&adapter->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&adapter->blink_timer); + hw->mac.ops.blink_led(hw); + break; + + case ETHTOOL_ID_INACTIVE: if (hw->phy.type == e1000_phy_ife) e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0); - } else { - e1000e_blink_led(hw); - msleep_interruptible(data * 1000); - } + hw->mac.ops.led_off(hw); + hw->mac.ops.cleanup_led(hw); + break; - hw->mac.ops.led_off(hw); - clear_bit(E1000_LED_ON, &adapter->led_status); - hw->mac.ops.cleanup_led(hw); + case ETHTOOL_ID_ON: + adapter->hw.mac.ops.led_on(&adapter->hw); + break; + case ETHTOOL_ID_OFF: + adapter->hw.mac.ops.led_off(&adapter->hw); + break; + } return 0; } @@ -2074,7 +2045,7 @@ static const struct ethtool_ops e1000_ethtool_ops = { .set_tso = e1000_set_tso, .self_test = e1000_diag_test, .get_strings = e1000_get_strings, - .phys_id = e1000_phys_id, + .set_phys_id = e1000_set_phys_id, .get_ethtool_stats = e1000_get_ethtool_stats, .get_sset_count = e1000e_get_sset_count, .get_coalesce = e1000_get_coalesce, diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 307e1ec22417..6c2fa8327f5c 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -756,6 +756,7 @@ struct e1000_host_mng_command_info { /* Function pointers and static data for the MAC. */ struct e1000_mac_operations { s32 (*id_led_init)(struct e1000_hw *); + s32 (*blink_led)(struct e1000_hw *); bool (*check_mng_mode)(struct e1000_hw *); s32 (*check_for_link)(struct e1000_hw *); s32 (*cleanup_led)(struct e1000_hw *); diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 06ff884bc2c7..3369d1f6a39c 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -564,6 +564,8 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan; /* ID LED init */ mac->ops.id_led_init = e1000e_id_led_init; + /* blink LED */ + mac->ops.blink_led = e1000e_blink_led_generic; /* setup LED */ mac->ops.setup_led = e1000e_setup_led_generic; /* cleanup LED */ @@ -767,6 +769,8 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) (!(er32(CTRL_EXT) & E1000_CTRL_EXT_LSECCK)))) { adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES; adapter->max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN; + + hw->mac.ops.blink_led = NULL; } if ((adapter->hw.mac.type == e1000_ich8lan) && diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index 30ef8fa4968c..6432ddab40ce 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -1530,12 +1530,12 @@ s32 e1000e_cleanup_led_generic(struct e1000_hw *hw) } /** - * e1000e_blink_led - Blink LED + * e1000e_blink_led_generic - Blink LED * @hw: pointer to the HW structure * * Blink the LEDs which are set to be on. **/ -s32 e1000e_blink_led(struct e1000_hw *hw) +s32 e1000e_blink_led_generic(struct e1000_hw *hw) { u32 ledctl_blink = 0; u32 i; diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 4deb67d98e36..0939040305fa 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -6020,7 +6020,6 @@ static int __devinit e1000_probe(struct pci_dev *pdev, INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround); INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task); INIT_WORK(&adapter->print_hang_task, e1000_print_hw_hang); - INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task); /* Initialize link parameters. User can change them with ethtool */ adapter->hw.mac.autoneg = 1; @@ -6153,7 +6152,6 @@ static void __devexit e1000_remove(struct pci_dev *pdev) cancel_work_sync(&adapter->watchdog_task); cancel_work_sync(&adapter->downshift_task); cancel_work_sync(&adapter->update_phy_task); - cancel_work_sync(&adapter->led_blink_task); cancel_work_sync(&adapter->print_hang_task); if (!(netdev->flags & IFF_UP)) -- cgit v1.2.3-58-ga151 From 50c022e7936354d854091ebdc699872d3432e874 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 31 Mar 2011 09:36:12 +0000 Subject: ixgbe: explicitly disable 100H for x540 100H is not supported on this HW, but the bit is set on the PHY. This can result in link at 100F when advertising only 1000F. Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_phy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index fd381ea17e99..edcaaebd72b2 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -657,7 +657,8 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw) MDIO_MMD_AN, &autoneg_reg); - autoneg_reg &= ~ADVERTISE_100FULL; + autoneg_reg &= ~(ADVERTISE_100FULL | + ADVERTISE_100HALF); if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) autoneg_reg |= ADVERTISE_100FULL; -- cgit v1.2.3-58-ga151 From 83dfde405322320d538b7087ba741fc9a4780161 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 31 Mar 2011 09:36:24 +0000 Subject: ixgbe: register defines cleanup Remove duplicates. Fix incorrect defines. Fix/Update comments. Fix whitespace. Add new register defines. Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_mbx.h | 3 - drivers/net/ixgbe/ixgbe_type.h | 189 +++++++++++++++++++++++++++-------------- 2 files changed, 125 insertions(+), 67 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_mbx.h b/drivers/net/ixgbe/ixgbe_mbx.h index fe6ea81dc7f8..f53dc5bb28b7 100644 --- a/drivers/net/ixgbe/ixgbe_mbx.h +++ b/drivers/net/ixgbe/ixgbe_mbx.h @@ -36,9 +36,6 @@ #define IXGBE_VFMAILBOX 0x002FC #define IXGBE_VFMBMEM 0x00200 -#define IXGBE_PFMAILBOX(x) (0x04B00 + (4 * x)) -#define IXGBE_PFMBMEM(vfn) (0x13000 + (64 * vfn)) - #define IXGBE_PFMAILBOX_STS 0x00000001 /* Initiate message send to VF */ #define IXGBE_PFMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */ #define IXGBE_PFMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index f5bec9754c00..fab9737c0d61 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -164,6 +164,9 @@ (0x0D018 + ((_i - 64) * 0x40))) #define IXGBE_RXDCTL(_i) (((_i) < 64) ? (0x01028 + ((_i) * 0x40)) : \ (0x0D028 + ((_i - 64) * 0x40))) +#define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \ + (0x0D02C + ((_i - 64) * 0x40))) +#define IXGBE_RSCDBU 0x03028 #define IXGBE_RDDCC 0x02F20 #define IXGBE_RXMEMWRAP 0x03190 #define IXGBE_STARCTRL 0x03024 @@ -228,17 +231,23 @@ #define IXGBE_VLVF(_i) (0x0F100 + ((_i) * 4)) /* 64 of these (0-63) */ #define IXGBE_VLVFB(_i) (0x0F200 + ((_i) * 4)) /* 128 of these (0-127) */ #define IXGBE_VMVIR(_i) (0x08000 + ((_i) * 4)) /* 64 of these (0-63) */ -#define IXGBE_VT_CTL 0x051B0 -#define IXGBE_VFRE(_i) (0x051E0 + ((_i) * 4)) -#define IXGBE_VFTE(_i) (0x08110 + ((_i) * 4)) -#define IXGBE_VMECM(_i) (0x08790 + ((_i) * 4)) -#define IXGBE_QDE 0x2F04 -#define IXGBE_VMOLR(_i) (0x0F000 + ((_i) * 4)) /* 64 total */ -#define IXGBE_UTA(_i) (0x0F400 + ((_i) * 4)) -#define IXGBE_VMRCTL(_i) (0x0F600 + ((_i) * 4)) -#define IXGBE_VMRVLAN(_i) (0x0F610 + ((_i) * 4)) -#define IXGBE_VMRVM(_i) (0x0F630 + ((_i) * 4)) -#define IXGBE_L34T_IMIR(_i) (0x0E800 + ((_i) * 4)) /*128 of these (0-127)*/ +#define IXGBE_VT_CTL 0x051B0 +#define IXGBE_PFMAILBOX(_i) (0x04B00 + (4 * (_i))) /* 64 total */ +#define IXGBE_PFMBMEM(_i) (0x13000 + (64 * (_i))) /* 64 Mailboxes, 16 DW each */ +#define IXGBE_PFMBICR(_i) (0x00710 + (4 * (_i))) /* 4 total */ +#define IXGBE_PFMBIMR(_i) (0x00720 + (4 * (_i))) /* 4 total */ +#define IXGBE_VFRE(_i) (0x051E0 + ((_i) * 4)) +#define IXGBE_VFTE(_i) (0x08110 + ((_i) * 4)) +#define IXGBE_VMECM(_i) (0x08790 + ((_i) * 4)) +#define IXGBE_QDE 0x2F04 +#define IXGBE_VMTXSW(_i) (0x05180 + ((_i) * 4)) /* 2 total */ +#define IXGBE_VMOLR(_i) (0x0F000 + ((_i) * 4)) /* 64 total */ +#define IXGBE_UTA(_i) (0x0F400 + ((_i) * 4)) +#define IXGBE_MRCTL(_i) (0x0F600 + ((_i) * 4)) +#define IXGBE_VMRVLAN(_i) (0x0F610 + ((_i) * 4)) +#define IXGBE_VMRVM(_i) (0x0F630 + ((_i) * 4)) +#define IXGBE_L34T_IMIR(_i) (0x0E800 + ((_i) * 4)) /*128 of these (0-127)*/ +#define IXGBE_RXFECCERR0 0x051B8 #define IXGBE_LLITHRESH 0x0EC90 #define IXGBE_IMIR(_i) (0x05A80 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* 8 of these (0-7) */ @@ -365,7 +374,7 @@ #define IXGBE_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */ #define IXGBE_WUFC_FLX_FILTERS 0x000F0000 /* Mask for 4 flex filters */ #define IXGBE_WUFC_EXT_FLX_FILTERS 0x00300000 /* Mask for Ext. flex filters */ -#define IXGBE_WUFC_ALL_FILTERS 0x003F00FF /* Mask for all 6 wakeup filters*/ +#define IXGBE_WUFC_ALL_FILTERS 0x003F00FF /* Mask for all wakeup filters */ #define IXGBE_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */ /* Wake Up Status */ @@ -407,7 +416,6 @@ #define IXGBE_SECTXSTAT 0x08804 #define IXGBE_SECTXBUFFAF 0x08808 #define IXGBE_SECTXMINIFG 0x08810 -#define IXGBE_SECTXSTAT 0x08804 #define IXGBE_SECRXCTRL 0x08D00 #define IXGBE_SECRXSTAT 0x08D04 @@ -500,21 +508,6 @@ #define IXGBE_SECTXCTRL_STORE_FORWARD_ENABLE 0x4 -/* HW RSC registers */ -#define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \ - (0x0D02C + ((_i - 64) * 0x40))) -#define IXGBE_RSCDBU 0x03028 -#define IXGBE_RSCCTL_RSCEN 0x01 -#define IXGBE_RSCCTL_MAXDESC_1 0x00 -#define IXGBE_RSCCTL_MAXDESC_4 0x04 -#define IXGBE_RSCCTL_MAXDESC_8 0x08 -#define IXGBE_RSCCTL_MAXDESC_16 0x0C -#define IXGBE_RXDADV_RSCCNT_SHIFT 17 -#define IXGBE_GPIE_RSC_DELAY_SHIFT 11 -#define IXGBE_RXDADV_RSCCNT_MASK 0x001E0000 -#define IXGBE_RSCDBU_RSCACKDIS 0x00000080 -#define IXGBE_RDRXCTL_RSCFRSTSIZE 0x003E0000 - /* DCB registers */ #define IXGBE_RTRPCS 0x02430 #define IXGBE_RTTDCS 0x04900 @@ -523,6 +516,7 @@ #define IXGBE_RTRUP2TC 0x03020 #define IXGBE_RTTUP2TC 0x0C800 #define IXGBE_RTRPT4C(_i) (0x02140 + ((_i) * 4)) /* 8 of these (0-7) */ +#define IXGBE_TXLLQ(_i) (0x082E0 + ((_i) * 4)) /* 4 of these (0-3) */ #define IXGBE_RTRPT4S(_i) (0x02160 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RTTDT2C(_i) (0x04910 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RTTDT2S(_i) (0x04930 + ((_i) * 4)) /* 8 of these (0-7) */ @@ -541,7 +535,7 @@ (IXGBE_RTTBCNRC_RF_DEC_MASK << IXGBE_RTTBCNRC_RF_INT_SHIFT) -/* FCoE registers */ +/* FCoE DMA Context Registers */ #define IXGBE_FCPTRL 0x02410 /* FC User Desc. PTR Low */ #define IXGBE_FCPTRH 0x02414 /* FC USer Desc. PTR High */ #define IXGBE_FCBUFF 0x02418 /* FC Buffer Control */ @@ -743,17 +737,10 @@ #define IXGBE_PBACLR_82599 0x11068 #define IXGBE_CIAA_82599 0x11088 #define IXGBE_CIAD_82599 0x1108C -#define IXGBE_PCIE_DIAG_0_82599 0x11090 -#define IXGBE_PCIE_DIAG_1_82599 0x11094 -#define IXGBE_PCIE_DIAG_2_82599 0x11098 -#define IXGBE_PCIE_DIAG_3_82599 0x1109C -#define IXGBE_PCIE_DIAG_4_82599 0x110A0 -#define IXGBE_PCIE_DIAG_5_82599 0x110A4 -#define IXGBE_PCIE_DIAG_6_82599 0x110A8 -#define IXGBE_PCIE_DIAG_7_82599 0x110C0 -#define IXGBE_INTRPT_CSR_82599 0x110B0 -#define IXGBE_INTRPT_MASK_82599 0x110B8 +#define IXGBE_PICAUSE 0x110B0 +#define IXGBE_PIENA 0x110B8 #define IXGBE_CDQ_MBR_82599 0x110B4 +#define IXGBE_PCIESPARE 0x110BC #define IXGBE_MISC_REG_82599 0x110F0 #define IXGBE_ECC_CTRL_0_82599 0x11100 #define IXGBE_ECC_CTRL_1_82599 0x11104 @@ -786,7 +773,19 @@ #define IXGBE_SYSTIML 0x08C0C /* System time register Low - RO */ #define IXGBE_SYSTIMH 0x08C10 /* System time register High - RO */ #define IXGBE_TIMINCA 0x08C14 /* Increment attributes register - RW */ -#define IXGBE_RXUDP 0x08C1C /* Time Sync Rx UDP Port - RW */ +#define IXGBE_TIMADJL 0x08C18 /* Time Adjustment Offset register Low - RW */ +#define IXGBE_TIMADJH 0x08C1C /* Time Adjustment Offset register High - RW */ +#define IXGBE_TSAUXC 0x08C20 /* TimeSync Auxiliary Control register - RW */ +#define IXGBE_TRGTTIML0 0x08C24 /* Target Time Register 0 Low - RW */ +#define IXGBE_TRGTTIMH0 0x08C28 /* Target Time Register 0 High - RW */ +#define IXGBE_TRGTTIML1 0x08C2C /* Target Time Register 1 Low - RW */ +#define IXGBE_TRGTTIMH1 0x08C30 /* Target Time Register 1 High - RW */ +#define IXGBE_FREQOUT0 0x08C34 /* Frequency Out 0 Control register - RW */ +#define IXGBE_FREQOUT1 0x08C38 /* Frequency Out 1 Control register - RW */ +#define IXGBE_AUXSTMPL0 0x08C3C /* Auxiliary Time Stamp 0 register Low - RO */ +#define IXGBE_AUXSTMPH0 0x08C40 /* Auxiliary Time Stamp 0 register High - RO */ +#define IXGBE_AUXSTMPL1 0x08C44 /* Auxiliary Time Stamp 1 register Low - RO */ +#define IXGBE_AUXSTMPH1 0x08C48 /* Auxiliary Time Stamp 1 register High - RO */ /* Diagnostic Registers */ #define IXGBE_RDSTATCTL 0x02C20 @@ -830,8 +829,20 @@ #define IXGBE_TXDATARDPTR(_i) (0x0C720 + ((_i) * 4)) /* 8 of these C720-C72C*/ #define IXGBE_TXDESCRDPTR(_i) (0x0C730 + ((_i) * 4)) /* 8 of these C730-C73C*/ #define IXGBE_PCIEECCCTL 0x1106C +#define IXGBE_RXWRPTR(_i) (0x03100 + ((_i) * 4)) /* 8 of these 3100-310C*/ +#define IXGBE_RXUSED(_i) (0x03120 + ((_i) * 4)) /* 8 of these 3120-312C*/ +#define IXGBE_RXRDPTR(_i) (0x03140 + ((_i) * 4)) /* 8 of these 3140-314C*/ +#define IXGBE_RXRDWRPTR(_i) (0x03160 + ((_i) * 4)) /* 8 of these 3160-310C*/ +#define IXGBE_TXWRPTR(_i) (0x0C100 + ((_i) * 4)) /* 8 of these C100-C10C*/ +#define IXGBE_TXUSED(_i) (0x0C120 + ((_i) * 4)) /* 8 of these C120-C12C*/ +#define IXGBE_TXRDPTR(_i) (0x0C140 + ((_i) * 4)) /* 8 of these C140-C14C*/ +#define IXGBE_TXRDWRPTR(_i) (0x0C160 + ((_i) * 4)) /* 8 of these C160-C10C*/ #define IXGBE_PCIEECCCTL0 0x11100 #define IXGBE_PCIEECCCTL1 0x11104 +#define IXGBE_RXDBUECC 0x03F70 +#define IXGBE_TXDBUECC 0x0CF70 +#define IXGBE_RXDBUEST 0x03F74 +#define IXGBE_TXDBUEST 0x0CF74 #define IXGBE_PBTXECC 0x0C300 #define IXGBE_PBRXECC 0x03300 #define IXGBE_GHECCR 0x110B0 @@ -872,6 +883,7 @@ #define IXGBE_AUTOC3 0x042AC #define IXGBE_ANLP1 0x042B0 #define IXGBE_ANLP2 0x042B4 +#define IXGBE_MACC 0x04330 #define IXGBE_ATLASCTL 0x04800 #define IXGBE_MMNGC 0x042D0 #define IXGBE_ANLPNP1 0x042D4 @@ -884,14 +896,49 @@ #define IXGBE_MPVC 0x04318 #define IXGBE_SGMIIC 0x04314 +/* Statistics Registers */ +#define IXGBE_RXNFGPC 0x041B0 +#define IXGBE_RXNFGBCL 0x041B4 +#define IXGBE_RXNFGBCH 0x041B8 +#define IXGBE_RXDGPC 0x02F50 +#define IXGBE_RXDGBCL 0x02F54 +#define IXGBE_RXDGBCH 0x02F58 +#define IXGBE_RXDDGPC 0x02F5C +#define IXGBE_RXDDGBCL 0x02F60 +#define IXGBE_RXDDGBCH 0x02F64 +#define IXGBE_RXLPBKGPC 0x02F68 +#define IXGBE_RXLPBKGBCL 0x02F6C +#define IXGBE_RXLPBKGBCH 0x02F70 +#define IXGBE_RXDLPBKGPC 0x02F74 +#define IXGBE_RXDLPBKGBCL 0x02F78 +#define IXGBE_RXDLPBKGBCH 0x02F7C +#define IXGBE_TXDGPC 0x087A0 +#define IXGBE_TXDGBCL 0x087A4 +#define IXGBE_TXDGBCH 0x087A8 + +#define IXGBE_RXDSTATCTRL 0x02F40 + +/* Copper Pond 2 link timeout */ #define IXGBE_VALIDATE_LINK_READY_TIMEOUT 50 /* Omer CORECTL */ #define IXGBE_CORECTL 0x014F00 /* BARCTRL */ -#define IXGBE_BARCTRL 0x110F4 -#define IXGBE_BARCTRL_FLSIZE 0x0700 -#define IXGBE_BARCTRL_CSRSIZE 0x2000 +#define IXGBE_BARCTRL 0x110F4 +#define IXGBE_BARCTRL_FLSIZE 0x0700 +#define IXGBE_BARCTRL_FLSIZE_SHIFT 8 +#define IXGBE_BARCTRL_CSRSIZE 0x2000 + +/* RSCCTL Bit Masks */ +#define IXGBE_RSCCTL_RSCEN 0x01 +#define IXGBE_RSCCTL_MAXDESC_1 0x00 +#define IXGBE_RSCCTL_MAXDESC_4 0x04 +#define IXGBE_RSCCTL_MAXDESC_8 0x08 +#define IXGBE_RSCCTL_MAXDESC_16 0x0C + +/* RSCDBU Bit Masks */ +#define IXGBE_RSCDBU_RSCSMALDIS_MASK 0x0000007F +#define IXGBE_RSCDBU_RSCACKDIS 0x00000080 /* RDRXCTL Bit Masks */ #define IXGBE_RDRXCTL_RDMTS_1_2 0x00000000 /* Rx Desc Min Threshold Size */ @@ -899,6 +946,8 @@ #define IXGBE_RDRXCTL_MVMEN 0x00000020 #define IXGBE_RDRXCTL_DMAIDONE 0x00000008 /* DMA init cycle done */ #define IXGBE_RDRXCTL_AGGDIS 0x00010000 /* Aggregation disable */ +#define IXGBE_RDRXCTL_RSCFRSTSIZE 0x003E0000 /* RSC First packet size */ +#define IXGBE_RDRXCTL_RSCLLIDIS 0x00800000 /* Disable RSC compl on LLI */ #define IXGBE_RDRXCTL_RSCACKC 0x02000000 /* must set 1 when RSC enabled */ #define IXGBE_RDRXCTL_FCOE_WRFIX 0x04000000 /* must set 1 when RSC enabled */ @@ -970,8 +1019,8 @@ #define IXGBE_MSCA_OP_CODE_SHIFT 26 /* OP CODE shift */ #define IXGBE_MSCA_ADDR_CYCLE 0x00000000 /* OP CODE 00 (addr cycle) */ #define IXGBE_MSCA_WRITE 0x04000000 /* OP CODE 01 (write) */ -#define IXGBE_MSCA_READ 0x08000000 /* OP CODE 10 (read) */ -#define IXGBE_MSCA_READ_AUTOINC 0x0C000000 /* OP CODE 11 (read, auto inc)*/ +#define IXGBE_MSCA_READ 0x0C000000 /* OP CODE 11 (read) */ +#define IXGBE_MSCA_READ_AUTOINC 0x08000000 /* OP CODE 10 (read, auto inc)*/ #define IXGBE_MSCA_ST_CODE_MASK 0x30000000 /* ST Code mask */ #define IXGBE_MSCA_ST_CODE_SHIFT 28 /* ST Code shift */ #define IXGBE_MSCA_NEW_PROTOCOL 0x00000000 /* ST CODE 00 (new protocol) */ @@ -1058,6 +1107,7 @@ #define IXGBE_GPIE_EIMEN 0x00000040 /* Immediate Interrupt Enable */ #define IXGBE_GPIE_EIAME 0x40000000 #define IXGBE_GPIE_PBA_SUPPORT 0x80000000 +#define IXGBE_GPIE_RSC_DELAY_SHIFT 11 #define IXGBE_GPIE_VTMODE_MASK 0x0000C000 /* VT Mode Mask */ #define IXGBE_GPIE_VTMODE_16 0x00004000 /* 16 VFs 8 queues per VF */ #define IXGBE_GPIE_VTMODE_32 0x00008000 /* 32 VFs 4 queues per VF */ @@ -1292,6 +1342,11 @@ #define IXGBE_FTQF_POOL_SHIFT 8 #define IXGBE_FTQF_5TUPLE_MASK_MASK 0x0000001F #define IXGBE_FTQF_5TUPLE_MASK_SHIFT 25 +#define IXGBE_FTQF_SOURCE_ADDR_MASK 0x1E +#define IXGBE_FTQF_DEST_ADDR_MASK 0x1D +#define IXGBE_FTQF_SOURCE_PORT_MASK 0x1B +#define IXGBE_FTQF_DEST_PORT_MASK 0x17 +#define IXGBE_FTQF_PROTOCOL_COMP_MASK 0x0F #define IXGBE_FTQF_POOL_MASK_EN 0x40000000 #define IXGBE_FTQF_QUEUE_ENABLE 0x80000000 @@ -1334,11 +1389,11 @@ * * Current filters: * EAPOL 802.1x (0x888e): Filter 0 - * BCN (0x8904): Filter 1 + * FCoE (0x8906): Filter 2 * 1588 (0x88f7): Filter 3 + * FIP (0x8914): Filter 4 */ #define IXGBE_ETQF_FILTER_EAPOL 0 -#define IXGBE_ETQF_FILTER_BCN 1 #define IXGBE_ETQF_FILTER_FCOE 2 #define IXGBE_ETQF_FILTER_1588 3 #define IXGBE_ETQF_FILTER_FIP 4 @@ -1449,6 +1504,11 @@ #define IXGBE_AUTOC2_10G_XFI (0x1 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) #define IXGBE_AUTOC2_10G_SFI (0x2 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) +#define IXGBE_MACC_FLU 0x00000001 +#define IXGBE_MACC_FSV_10G 0x00030000 +#define IXGBE_MACC_FS 0x00040000 +#define IXGBE_MAC_RX2TX_LPBK 0x00000002 + /* LINKS Bit Masks */ #define IXGBE_LINKS_KX_AN_COMP 0x80000000 #define IXGBE_LINKS_UP 0x40000000 @@ -1502,7 +1562,6 @@ #define IXGBE_ANLP1_ASM_PAUSE 0x0800 #define IXGBE_ANLP1_AN_STATE_MASK 0x000f0000 - /* SW Semaphore Register bitmasks */ #define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ #define IXGBE_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ @@ -1515,6 +1574,10 @@ #define IXGBE_GSSR_PHY1_SM 0x0004 #define IXGBE_GSSR_MAC_CSR_SM 0x0008 #define IXGBE_GSSR_FLASH_SM 0x0010 +#define IXGBE_GSSR_SW_MNG_SM 0x0400 + +/* FW Status register bitmask */ +#define IXGBE_FWSTS_FWRI 0x00000200 /* Firmware Reset Indication */ /* EEC Register */ #define IXGBE_EEC_SK 0x00000001 /* EEPROM Clock */ @@ -1535,6 +1598,7 @@ /* EEPROM Addressing bits based on type (0-small, 1-large) */ #define IXGBE_EEC_ADDR_SIZE 0x00000400 #define IXGBE_EEC_SIZE 0x00007800 /* EEPROM Size */ +#define IXGBE_EERD_MAX_ADDR 0x00003FFF /* EERD alows 14 bits for addr. */ #define IXGBE_EEC_SIZE_SHIFT 11 #define IXGBE_EEPROM_WORD_SIZE_SHIFT 6 @@ -1564,8 +1628,10 @@ #define IXGBE_FW_PTR 0x0F #define IXGBE_PBANUM0_PTR 0x15 #define IXGBE_PBANUM1_PTR 0x16 -#define IXGBE_DEVICE_CAPS 0x2C +#define IXGBE_FREE_SPACE_PTR 0X3E #define IXGBE_SAN_MAC_ADDR_PTR 0x28 +#define IXGBE_DEVICE_CAPS 0x2C +#define IXGBE_SERIAL_NUMBER_MAC_ADDR 0x11 #define IXGBE_PCIE_MSIX_82599_CAPS 0x72 #define IXGBE_PCIE_MSIX_82598_CAPS 0x62 @@ -1630,9 +1696,12 @@ #define IXGBE_FW_LESM_STATE_1 0x1 #define IXGBE_FW_LESM_STATE_ENABLED 0x8000 /* LESM Enable bit */ #define IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR 0x4 -#define IXGBE_FW_PATCH_VERSION_4 0x7 - -/* Alternative SAN MAC Address Block */ +#define IXGBE_FW_PATCH_VERSION_4 0x7 +#define IXGBE_FCOE_IBA_CAPS_BLK_PTR 0x33 /* iSCSI/FCOE block */ +#define IXGBE_FCOE_IBA_CAPS_FCOE 0x20 /* FCOE flags */ +#define IXGBE_ISCSI_FCOE_BLK_PTR 0x17 /* iSCSI/FCOE block */ +#define IXGBE_ISCSI_FCOE_FLAGS_OFFSET 0x0 /* FCOE flags */ +#define IXGBE_ISCSI_FCOE_FLAGS_ENABLE 0x1 /* FCOE flags enable bit */ #define IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR 0x27 /* Alt. SAN MAC block */ #define IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET 0x0 /* Alt. SAN MAC capability */ #define IXGBE_ALT_SAN_MAC_ADDR_PORT0_OFFSET 0x1 /* Alt. SAN MAC 0 offset */ @@ -1697,6 +1766,7 @@ /* Transmit Config masks */ #define IXGBE_TXDCTL_ENABLE 0x02000000 /* Enable specific Tx Queue */ #define IXGBE_TXDCTL_SWFLSH 0x04000000 /* Tx Desc. write-back flushing */ +#define IXGBE_TXDCTL_WTHRESH_SHIFT 16 /* shift to WTHRESH bits */ /* Enable short packet padding to 64 bytes */ #define IXGBE_TX_PAD_ENABLE 0x00000400 #define IXGBE_JUMBO_FRAME_ENABLE 0x00000004 /* Allow jumbo frames */ @@ -1710,9 +1780,9 @@ #define IXGBE_RXCTRL_RXEN 0x00000001 /* Enable Receiver */ #define IXGBE_RXCTRL_DMBYPS 0x00000002 /* Descriptor Monitor Bypass */ #define IXGBE_RXDCTL_ENABLE 0x02000000 /* Enable specific Rx Queue */ -#define IXGBE_RXDCTL_VME 0x40000000 /* VLAN mode enable */ #define IXGBE_RXDCTL_RLPMLMASK 0x00003FFF /* Only supported on the X540 */ #define IXGBE_RXDCTL_RLPML_EN 0x00008000 +#define IXGBE_RXDCTL_VME 0x40000000 /* VLAN mode enable */ #define IXGBE_FCTRL_SBP 0x00000002 /* Store Bad Packet */ #define IXGBE_FCTRL_MPE 0x00000100 /* Multicast Promiscuous Ena*/ @@ -1870,6 +1940,8 @@ #define IXGBE_RXDADV_PKTTYPE_MASK 0x0000FFF0 #define IXGBE_RXDADV_PKTTYPE_MASK_EX 0x0001FFF0 #define IXGBE_RXDADV_HDRBUFLEN_MASK 0x00007FE0 +#define IXGBE_RXDADV_RSCCNT_MASK 0x001E0000 +#define IXGBE_RXDADV_RSCCNT_SHIFT 17 #define IXGBE_RXDADV_HDRBUFLEN_SHIFT 5 #define IXGBE_RXDADV_SPLITHEADER_EN 0x00001000 #define IXGBE_RXDADV_SPH 0x8000 @@ -1945,15 +2017,6 @@ #define IXGBE_VFLRE(_i) (((_i & 1) ? 0x001C0 : 0x00600)) #define IXGBE_VFLREC(_i) (0x00700 + (_i * 4)) -/* Little Endian defines */ -#ifndef __le32 -#define __le32 u32 -#endif -#ifndef __le64 -#define __le64 u64 - -#endif - enum ixgbe_fdir_pballoc_type { IXGBE_FDIR_PBALLOC_64K = 0, IXGBE_FDIR_PBALLOC_128K, @@ -2152,8 +2215,6 @@ typedef u32 ixgbe_link_speed; IXGBE_LINK_SPEED_1GB_FULL | \ IXGBE_LINK_SPEED_10GB_FULL) -#define IXGBE_PCIE_DEV_CTRL_2 0xC8 -#define PCIE_COMPL_TO_VALUE 0x05 /* Physical layer type */ typedef u32 ixgbe_physical_layer; -- cgit v1.2.3-58-ga151 From 0665b09f81760c38a882bed65d495a4bd31a5767 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Fri, 1 Apr 2011 08:17:19 +0000 Subject: ixgbe: add support for 64k EEPROM for 82599 82599 supports up to 32k EEPROM addressing via EERD register. If we wish to address larger EEPROM this have to be done via serial interface. This patch adds function ixgbe_read_eeprom_82599 which selects the best method to read the EEPROM. Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82599.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index b341ed8ef84f..d521baf1acd3 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -2064,6 +2064,35 @@ out: return lesm_enabled; } +/** + * ixgbe_read_eeprom_82599 - Read EEPROM word using + * fastest available method + * + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to read + * @data: word read from the EEPROM + * + * Reads a 16 bit word from the EEPROM + **/ +static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw, + u16 offset, u16 *data) +{ + struct ixgbe_eeprom_info *eeprom = &hw->eeprom; + s32 ret_val = IXGBE_ERR_CONFIG; + + /* + * If EEPROM is detected and can be addressed using 14 bits, + * use EERD otherwise use bit bang + */ + if ((eeprom->type == ixgbe_eeprom_spi) && + (offset <= IXGBE_EERD_MAX_ADDR)) + ret_val = ixgbe_read_eerd_generic(hw, offset, data); + else + ret_val = ixgbe_read_eeprom_bit_bang_generic(hw, offset, data); + + return ret_val; +} + static struct ixgbe_mac_operations mac_ops_82599 = { .init_hw = &ixgbe_init_hw_generic, .reset_hw = &ixgbe_reset_hw_82599, @@ -2110,7 +2139,7 @@ static struct ixgbe_mac_operations mac_ops_82599 = { static struct ixgbe_eeprom_operations eeprom_ops_82599 = { .init_params = &ixgbe_init_eeprom_params_generic, - .read = &ixgbe_read_eerd_generic, + .read = &ixgbe_read_eeprom_82599, .write = &ixgbe_write_eeprom_generic, .calc_checksum = &ixgbe_calc_eeprom_checksum_generic, .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, -- cgit v1.2.3-58-ga151 From 98508c93003d8d24662f32c66dbe4746340c33d4 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Fri, 8 Apr 2011 01:24:05 +0000 Subject: ixgbe: add LED blink code for x540 Implement blink_led_start and blink_led_stop functions for x540 using the MACC register. Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_x540.c | 64 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c index 932394fce439..75c6465db893 100644 --- a/drivers/net/ixgbe/ixgbe_x540.c +++ b/drivers/net/ixgbe/ixgbe_x540.c @@ -744,6 +744,66 @@ static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw) IXGBE_WRITE_FLUSH(hw); } +/** + * ixgbe_blink_led_start_X540 - Blink LED based on index. + * @hw: pointer to hardware structure + * @index: led number to blink + * + * Devices that implement the version 2 interface: + * X540 + **/ +static s32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index) +{ + u32 macc_reg; + u32 ledctl_reg; + + /* + * In order for the blink bit in the LED control register + * to work, link and speed must be forced in the MAC. We + * will reverse this when we stop the blinking. + */ + macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC); + macc_reg |= IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS; + IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg); + + /* Set the LED to LINK_UP + BLINK. */ + ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + ledctl_reg &= ~IXGBE_LED_MODE_MASK(index); + ledctl_reg |= IXGBE_LED_BLINK(index); + IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg); + IXGBE_WRITE_FLUSH(hw); + + return 0; +} + +/** + * ixgbe_blink_led_stop_X540 - Stop blinking LED based on index. + * @hw: pointer to hardware structure + * @index: led number to stop blinking + * + * Devices that implement the version 2 interface: + * X540 + **/ +static s32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index) +{ + u32 macc_reg; + u32 ledctl_reg; + + /* Restore the LED to its default value. */ + ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + ledctl_reg &= ~IXGBE_LED_MODE_MASK(index); + ledctl_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); + ledctl_reg &= ~IXGBE_LED_BLINK(index); + IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg); + + /* Unforce link and speed in the MAC. */ + macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC); + macc_reg &= ~(IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS); + IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg); + IXGBE_WRITE_FLUSH(hw); + + return 0; +} static struct ixgbe_mac_operations mac_ops_X540 = { .init_hw = &ixgbe_init_hw_generic, .reset_hw = &ixgbe_reset_hw_X540, @@ -767,8 +827,8 @@ static struct ixgbe_mac_operations mac_ops_X540 = { .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, .led_on = &ixgbe_led_on_generic, .led_off = &ixgbe_led_off_generic, - .blink_led_start = &ixgbe_blink_led_start_generic, - .blink_led_stop = &ixgbe_blink_led_stop_generic, + .blink_led_start = &ixgbe_blink_led_start_X540, + .blink_led_stop = &ixgbe_blink_led_stop_X540, .set_rar = &ixgbe_set_rar_generic, .clear_rar = &ixgbe_clear_rar_generic, .set_vmdq = &ixgbe_set_vmdq_generic, -- cgit v1.2.3-58-ga151 From 11b1d38e705fa05282661d2b1710f7a81a7f7045 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 9 Apr 2011 05:34:06 +0000 Subject: ixgbe: remove ntuple display support This change removes the ntuple display support from ixgbe. The reason for this change is to resolve a number of issues in the way display filtering is handled. I plan to add support for displaying these filters via the network flow classifier interface. Signed-off-by: Alexander Duyck Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_ethtool.c | 3 --- drivers/net/ixgbe/ixgbe_main.c | 3 --- 2 files changed, 6 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 5005a36f8593..6cf1c71ed7f1 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1030,9 +1030,6 @@ static int ixgbe_get_sset_count(struct net_device *netdev, int sset) return IXGBE_TEST_LEN; case ETH_SS_STATS: return IXGBE_STATS_LEN; - case ETH_SS_NTUPLE_FILTERS: - return ETHTOOL_MAX_NTUPLE_LIST_ENTRY * - ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY; default: return -EOPNOTSUPP; } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 200ae7e60ba0..dbe29e57280f 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4203,9 +4203,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter) break; } - /* clear n-tuple filters that are cached */ - ethtool_ntuple_flush(netdev); - if (!pci_channel_offline(adapter->pdev)) ixgbe_reset(adapter); -- cgit v1.2.3-58-ga151 From b32c8dcc33a74fb4f1e73ed2263504f5947ca76b Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Tue, 12 Apr 2011 02:44:55 +0000 Subject: ixgbe: fix static functions Define functions as static added C=1 (sparse) to my make line brought these to my attention. Signed-off-by: John Fastabend Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82599.c | 2 +- drivers/net/ixgbe/ixgbe_dcb_82598.c | 2 +- drivers/net/ixgbe/ixgbe_main.c | 4 ++-- drivers/net/ixgbe/ixgbe_sriov.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index d521baf1acd3..d1cda36507f8 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -494,7 +494,7 @@ static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) * * Set the link speed in the AUTOC register and restarts link. **/ -s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, +static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c index 1bc57e52cee3..771d01a60d06 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82598.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c @@ -289,7 +289,7 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en) * Configure queue statistics registers, all queues belonging to same traffic * class uses a single set of queue statistics counters. */ -s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw) +static s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw) { u32 reg = 0; u8 i = 0; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index dbe29e57280f..227a9b4c7028 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4566,8 +4566,8 @@ static inline bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter) #ifdef CONFIG_IXGBE_DCB /* ixgbe_get_first_reg_idx - Return first register index associated with ring */ -void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc, - unsigned int *tx, unsigned int *rx) +static void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc, + unsigned int *tx, unsigned int *rx) { struct net_device *dev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c index 6e50d8328942..47650278d414 100644 --- a/drivers/net/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ixgbe/ixgbe_sriov.c @@ -110,7 +110,7 @@ static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add); } -void ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf) +static void ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf) { struct ixgbe_hw *hw = &adapter->hw; int new_mtu = msgbuf[1]; -- cgit v1.2.3-58-ga151 From 7aba7b077f638deb9569e0b36256cd9ae76e468c Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Sat, 9 Apr 2011 08:34:12 +0000 Subject: ixgbe: do not clear FCoE DDP error status for received ABTS The ddp->err is initialized to be 1 to make sure outstanding DDP context is guaranteed to be invalidated when HW is not auto-invalidating it. However, in case of receiving ABTS response for a DDPed I/O, the ddp->err was cleared, bypassing the invalidating of the DDP context from upper protocol stack when ixgbe_fcoe_ddp_put() is called. This bug is fixed here by updating the error only when FCP_RSP is received. Signed-off-by: Yi Zou Tested-by: Ross Brattain Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_fcoe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c index dba7d77588ef..05920726e824 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ixgbe/ixgbe_fcoe.c @@ -416,8 +416,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, if (!ddp->udl) goto ddp_out; - ddp->err = (fcerr | fceofe); - if (ddp->err) + if (fcerr | fceofe) goto ddp_out; fcstat = (sterr & IXGBE_RXDADV_STAT_FCSTAT); @@ -428,6 +427,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, if (fcstat == IXGBE_RXDADV_STAT_FCSTAT_FCPRSP) { pci_unmap_sg(adapter->pdev, ddp->sgl, ddp->sgc, DMA_FROM_DEVICE); + ddp->err = (fcerr | fceofe); ddp->sgl = NULL; ddp->sgc = 0; } -- cgit v1.2.3-58-ga151 From 58be7666a897bb756477da72859f515da35ab805 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Tue, 12 Apr 2011 09:42:11 +0000 Subject: ixgbe: enable SCTP checksum offload for X540 X540 supports SCTP checksum offload so enable it. It was overlooked when X540 support was initially added to the driver. Signed-off-by: Don Skidmore Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 227a9b4c7028..a7da5d9c12d0 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -7361,8 +7361,14 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_TSO6; netdev->features |= NETIF_F_GRO; - if (adapter->hw.mac.type == ixgbe_mac_82599EB) + switch (adapter->hw.mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: netdev->features |= NETIF_F_SCTP_CSUM; + break; + default: + break; + } netdev->vlan_features |= NETIF_F_TSO; netdev->vlan_features |= NETIF_F_TSO6; -- cgit v1.2.3-58-ga151 From c89c7112d347acc3f4a6fe1459bcb6de02594dc9 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 14 Apr 2011 07:40:11 +0000 Subject: ixgbe: Bump version Bump the driver version number to better match up with the out of tree driver that has similar functionality. Signed-off-by: Don Skidmore Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index a7da5d9c12d0..9160811c6d7d 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -52,8 +52,8 @@ char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = "Intel(R) 10 Gigabit PCI Express Network Driver"; #define MAJ 3 -#define MIN 2 -#define BUILD 9 +#define MIN 3 +#define BUILD 8 #define KFIX 2 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ __stringify(BUILD) "-k" __stringify(KFIX) -- cgit v1.2.3-58-ga151 From e7fd9253d83703838953160ebb2899c5f6e2eee1 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Sat, 16 Apr 2011 05:29:14 +0000 Subject: ixgbe: fix X540 ethtool loopback test. On X540 we need to set the MACC.FLU bit to 1 in order to force the link up before entering MAC loopback. This is only used in the ethtool loopback test, which was failing. This patch corrects it. Signed-off-by: Don Skidmore Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_ethtool.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 6cf1c71ed7f1..bd7524e4a00c 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1595,6 +1595,13 @@ static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter) struct ixgbe_hw *hw = &adapter->hw; u32 reg_data; + /* X540 needs to set the MACC.FLU bit to force link up */ + if (adapter->hw.mac.type == ixgbe_mac_X540) { + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_MACC); + reg_data |= IXGBE_MACC_FLU; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_MACC, reg_data); + } + /* right now we only support MAC loopback in the driver */ reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0); /* Setup MAC loopback */ -- cgit v1.2.3-58-ga151 From 66e6961c8e53c0c0079d5b67faf9b7fe33525892 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Sat, 16 Apr 2011 06:12:51 +0000 Subject: ixgbe: convert to ethtool set_phys_id Based on the original patch submitted by Stephen Hemminger. This patch makes the following changes: - Change ETHTOOL_ID_INACTIVE return value to 2 (blinks/sec) - Fix restoring of IXGBE_LEDCTL CC: Stephen Hemminger Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe.h | 1 + drivers/net/ixgbe/ixgbe_ethtool.c | 29 +++++++++++++++++------------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 8d468028bb55..37ff531d59c0 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -461,6 +461,7 @@ struct ixgbe_adapter { u16 eeprom_version; int node; + u32 led_reg; struct work_struct check_overtemp_task; u32 interrupt_event; char lsc_int_name[IFNAMSIZ + 9]; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index bd7524e4a00c..7279345b1ed7 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -2003,25 +2003,30 @@ static int ixgbe_nway_reset(struct net_device *netdev) return 0; } -static int ixgbe_phys_id(struct net_device *netdev, u32 data) +static int ixgbe_set_phys_id(struct net_device *netdev, + enum ethtool_phys_id_state state) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; - u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); - u32 i; - if (!data || data > 300) - data = 300; + switch (state) { + case ETHTOOL_ID_ACTIVE: + adapter->led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + return 2; - for (i = 0; i < (data * 1000); i += 400) { + case ETHTOOL_ID_ON: hw->mac.ops.led_on(hw, IXGBE_LED_ON); - msleep_interruptible(200); + break; + + case ETHTOOL_ID_OFF: hw->mac.ops.led_off(hw, IXGBE_LED_ON); - msleep_interruptible(200); - } + break; - /* Restore LED settings */ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_LEDCTL, led_reg); + case ETHTOOL_ID_INACTIVE: + /* Restore LED settings */ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_LEDCTL, adapter->led_reg); + break; + } return 0; } @@ -2469,7 +2474,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = { .set_tso = ixgbe_set_tso, .self_test = ixgbe_diag_test, .get_strings = ixgbe_get_strings, - .phys_id = ixgbe_phys_id, + .set_phys_id = ixgbe_set_phys_id, .get_sset_count = ixgbe_get_sset_count, .get_ethtool_stats = ixgbe_get_ethtool_stats, .get_coalesce = ixgbe_get_coalesce, -- cgit v1.2.3-58-ga151 From 625034113bd45c71fb9e329f52f25fef9e6993a3 Mon Sep 17 00:00:00 2001 From: Weixing Shi Date: Tue, 26 Apr 2011 21:36:32 +0000 Subject: sctp: fix sctp to work with ipv6 source address routing In the below test case, using the source address routing, sctp can not work. Node-A 1)ifconfig eth0 inet6 add 2001:1::1/64 2)ip -6 rule add from 2001:1::1 table 100 pref 100 3)ip -6 route add 2001:2::1 dev eth0 table 100 4)sctp_darn -H 2001:1::1 -P 250 -l & Node-B 1)ifconfig eth0 inet6 add 2001:2::1/64 2)ip -6 rule add from 2001:2::1 table 100 pref 100 3)ip -6 route add 2001:1::1 dev eth0 table 100 4)sctp_darn -H 2001:2::1 -P 250 -h 2001:1::1 -p 250 -s root cause: Node-A and Node-B use the source address routing, and at begining, source address will be NULL,sctp will search the routing table by the destination address, because using the source address routing table, and the result dst_entry will be NULL. solution: walk through the bind address list to get the source address and then lookup the routing table again to get the correct dst_entry. Signed-off-by: Weixing Shi Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/sctp/ipv6.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 321f175055bf..3a571d6614f9 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -80,6 +80,9 @@ #include +static inline int sctp_v6_addr_match_len(union sctp_addr *s1, + union sctp_addr *s2); + /* Event handler for inet6 address addition/deletion events. * The sctp_local_addr_list needs to be protocted by a spin lock since * multiple notifiers (say IPv4 and IPv6) may be running at the same @@ -244,8 +247,14 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, union sctp_addr *daddr, union sctp_addr *saddr) { - struct dst_entry *dst; + struct dst_entry *dst = NULL; struct flowi6 fl6; + struct sctp_bind_addr *bp; + struct sctp_sockaddr_entry *laddr; + union sctp_addr *baddr = NULL; + __u8 matchlen = 0; + __u8 bmatchlen; + sctp_scope_t scope; memset(&fl6, 0, sizeof(fl6)); ipv6_addr_copy(&fl6.daddr, &daddr->v6.sin6_addr); @@ -261,6 +270,39 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, } dst = ip6_route_output(&init_net, NULL, &fl6); + if (!asoc || saddr) + goto out; + + if (dst->error) { + dst_release(dst); + dst = NULL; + bp = &asoc->base.bind_addr; + scope = sctp_scope(daddr); + /* Walk through the bind address list and try to get a dst that + * matches a bind address as the source address. + */ + rcu_read_lock(); + list_for_each_entry_rcu(laddr, &bp->address_list, list) { + if (!laddr->valid) + continue; + if ((laddr->state == SCTP_ADDR_SRC) && + (laddr->a.sa.sa_family == AF_INET6) && + (scope <= sctp_scope(&laddr->a))) { + bmatchlen = sctp_v6_addr_match_len(daddr, + &laddr->a); + if (!baddr || (matchlen < bmatchlen)) { + baddr = &laddr->a; + matchlen = bmatchlen; + } + } + } + rcu_read_unlock(); + if (baddr) { + ipv6_addr_copy(&fl6.saddr, &baddr->v6.sin6_addr); + dst = ip6_route_output(&init_net, NULL, &fl6); + } + } +out: if (!dst->error) { struct rt6_info *rt; rt = (struct rt6_info *)dst; -- cgit v1.2.3-58-ga151 From 9914ae3ca770389a3bec3114d0a07532a7f235dd Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 26 Apr 2011 21:51:31 +0000 Subject: sctp: cache the ipv6 source after route lookup The ipv6 routing lookup does give us a source address, but instead of filling it into the dst, it's stored in the flowi. We can use that instead of going through the entire source address selection again. Also the useless ->dst_saddr member of sctp_pf is removed. And sctp_v6_dst_saddr() is removed, instead by introduce sctp_v6_to_addr(), which can be reused to cleanup some dup code. Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 14 ++-- net/sctp/ipv6.c | 161 ++++++++++++++++++++------------------------- net/sctp/protocol.c | 47 +++++++------ net/sctp/socket.c | 2 +- net/sctp/transport.c | 15 +++-- 5 files changed, 112 insertions(+), 127 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 5c9bada51d2d..1d465d62f34f 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -566,17 +566,15 @@ struct sctp_af { int __user *optlen); struct dst_entry *(*get_dst) (struct sctp_association *asoc, union sctp_addr *daddr, - union sctp_addr *saddr); + union sctp_addr *saddr, + struct flowi *fl, + struct sock *sk); void (*get_saddr) (struct sctp_sock *sk, - struct sctp_association *asoc, - struct dst_entry *dst, + struct sctp_transport *t, union sctp_addr *daddr, - union sctp_addr *saddr); + struct flowi *fl); void (*copy_addrlist) (struct list_head *, struct net_device *); - void (*dst_saddr) (union sctp_addr *saddr, - struct dst_entry *dst, - __be16 port); int (*cmp_addr) (const union sctp_addr *addr1, const union sctp_addr *addr2); void (*addr_copy) (union sctp_addr *dst, @@ -1061,7 +1059,7 @@ void sctp_transport_set_owner(struct sctp_transport *, struct sctp_association *); void sctp_transport_route(struct sctp_transport *, union sctp_addr *, struct sctp_sock *); -void sctp_transport_pmtu(struct sctp_transport *); +void sctp_transport_pmtu(struct sctp_transport *, struct sock *sk); void sctp_transport_free(struct sctp_transport *); void sctp_transport_reset_timers(struct sctp_transport *); void sctp_transport_hold(struct sctp_transport *); diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 3a571d6614f9..51c048d256f5 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -82,6 +82,10 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1, union sctp_addr *s2); +static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr, + __be16 port); +static int sctp_v6_cmp_addr(const union sctp_addr *addr1, + const union sctp_addr *addr2); /* Event handler for inet6 address addition/deletion events. * The sctp_local_addr_list needs to be protocted by a spin lock since @@ -245,73 +249,99 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) */ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, union sctp_addr *daddr, - union sctp_addr *saddr) + union sctp_addr *saddr, + struct flowi *fl, + struct sock *sk) { struct dst_entry *dst = NULL; - struct flowi6 fl6; + struct flowi6 *fl6 = &fl->u.ip6; struct sctp_bind_addr *bp; struct sctp_sockaddr_entry *laddr; union sctp_addr *baddr = NULL; + union sctp_addr dst_saddr; __u8 matchlen = 0; __u8 bmatchlen; sctp_scope_t scope; + int err = 0; - memset(&fl6, 0, sizeof(fl6)); - ipv6_addr_copy(&fl6.daddr, &daddr->v6.sin6_addr); + memset(fl6, 0, sizeof(struct flowi6)); + ipv6_addr_copy(&fl6->daddr, &daddr->v6.sin6_addr); if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) - fl6.flowi6_oif = daddr->v6.sin6_scope_id; + fl6->flowi6_oif = daddr->v6.sin6_scope_id; - SCTP_DEBUG_PRINTK("%s: DST=%pI6 ", __func__, &fl6.daddr); + SCTP_DEBUG_PRINTK("%s: DST=%pI6 ", __func__, &fl6->daddr); if (saddr) { - ipv6_addr_copy(&fl6.saddr, &saddr->v6.sin6_addr); - SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6.saddr); + ipv6_addr_copy(&fl6->saddr, &saddr->v6.sin6_addr); + SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6->saddr); } - dst = ip6_route_output(&init_net, NULL, &fl6); + err = ip6_dst_lookup(sk, &dst, fl6); if (!asoc || saddr) goto out; - if (dst->error) { - dst_release(dst); - dst = NULL; - bp = &asoc->base.bind_addr; - scope = sctp_scope(daddr); - /* Walk through the bind address list and try to get a dst that - * matches a bind address as the source address. + bp = &asoc->base.bind_addr; + scope = sctp_scope(daddr); + /* ip6_dst_lookup has filled in the fl6->saddr for us. Check + * to see if we can use it. + */ + if (!err) { + /* Walk through the bind address list and look for a bind + * address that matches the source address of the returned dst. */ + sctp_v6_to_addr(&dst_saddr, &fl6->saddr, htons(bp->port)); rcu_read_lock(); list_for_each_entry_rcu(laddr, &bp->address_list, list) { - if (!laddr->valid) + if (!laddr->valid || (laddr->state != SCTP_ADDR_SRC)) continue; - if ((laddr->state == SCTP_ADDR_SRC) && - (laddr->a.sa.sa_family == AF_INET6) && - (scope <= sctp_scope(&laddr->a))) { - bmatchlen = sctp_v6_addr_match_len(daddr, - &laddr->a); - if (!baddr || (matchlen < bmatchlen)) { - baddr = &laddr->a; - matchlen = bmatchlen; - } + + /* Do not compare against v4 addrs */ + if ((laddr->a.sa.sa_family == AF_INET6) && + (sctp_v6_cmp_addr(&dst_saddr, &laddr->a))) { + rcu_read_unlock(); + goto out; } } rcu_read_unlock(); - if (baddr) { - ipv6_addr_copy(&fl6.saddr, &baddr->v6.sin6_addr); - dst = ip6_route_output(&init_net, NULL, &fl6); + /* None of the bound addresses match the source address of the + * dst. So release it. + */ + dst_release(dst); + dst = NULL; + } + + /* Walk through the bind address list and try to get the + * best source address for a given destination. + */ + rcu_read_lock(); + list_for_each_entry_rcu(laddr, &bp->address_list, list) { + if (!laddr->valid && laddr->state != SCTP_ADDR_SRC) + continue; + if ((laddr->a.sa.sa_family == AF_INET6) && + (scope <= sctp_scope(&laddr->a))) { + bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); + if (!baddr || (matchlen < bmatchlen)) { + baddr = &laddr->a; + matchlen = bmatchlen; + } } } + rcu_read_unlock(); + if (baddr) { + ipv6_addr_copy(&fl6->saddr, &baddr->v6.sin6_addr); + err = ip6_dst_lookup(sk, &dst, fl6); + } + out: - if (!dst->error) { + if (!err) { struct rt6_info *rt; rt = (struct rt6_info *)dst; SCTP_DEBUG_PRINTK("rt6_dst:%pI6 rt6_src:%pI6\n", - &rt->rt6i_dst.addr, &rt->rt6i_src.addr); + &rt->rt6i_dst.addr, &fl6->saddr); return dst; } SCTP_DEBUG_PRINTK("NO ROUTE\n"); - dst_release(dst); return NULL; } @@ -328,64 +358,21 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1, * and asoc's bind address list. */ static void sctp_v6_get_saddr(struct sctp_sock *sk, - struct sctp_association *asoc, - struct dst_entry *dst, + struct sctp_transport *t, union sctp_addr *daddr, - union sctp_addr *saddr) + struct flowi *fl) { - struct sctp_bind_addr *bp; - struct sctp_sockaddr_entry *laddr; - sctp_scope_t scope; - union sctp_addr *baddr = NULL; - __u8 matchlen = 0; - __u8 bmatchlen; + struct flowi6 *fl6 = &fl->u.ip6; + union sctp_addr *saddr = &t->saddr; SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p daddr:%pI6 ", - __func__, asoc, dst, &daddr->v6.sin6_addr); - - if (!asoc) { - ipv6_dev_get_saddr(sock_net(sctp_opt2sk(sk)), - dst ? ip6_dst_idev(dst)->dev : NULL, - &daddr->v6.sin6_addr, - inet6_sk(&sk->inet.sk)->srcprefs, - &saddr->v6.sin6_addr); - SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: %pI6\n", - &saddr->v6.sin6_addr); - return; - } - - scope = sctp_scope(daddr); + __func__, t->asoc, t->dst, &daddr->v6.sin6_addr); - bp = &asoc->base.bind_addr; - - /* Go through the bind address list and find the best source address - * that matches the scope of the destination address. - */ - rcu_read_lock(); - list_for_each_entry_rcu(laddr, &bp->address_list, list) { - if (!laddr->valid) - continue; - if ((laddr->state == SCTP_ADDR_SRC) && - (laddr->a.sa.sa_family == AF_INET6) && - (scope <= sctp_scope(&laddr->a))) { - bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); - if (!baddr || (matchlen < bmatchlen)) { - baddr = &laddr->a; - matchlen = bmatchlen; - } - } - } - if (baddr) { - memcpy(saddr, baddr, sizeof(union sctp_addr)); - SCTP_DEBUG_PRINTK("saddr: %pI6\n", &saddr->v6.sin6_addr); - } else { - pr_err("%s: asoc:%p Could not find a valid source " - "address for the dest:%pI6\n", - __func__, asoc, &daddr->v6.sin6_addr); + if (t->dst) { + saddr->v6.sin6_family = AF_INET6; + ipv6_addr_copy(&saddr->v6.sin6_addr, &fl6->saddr); } - - rcu_read_unlock(); } /* Make a copy of all potential local addresses. */ @@ -507,14 +494,13 @@ static int sctp_v6_to_addr_param(const union sctp_addr *addr, return length; } -/* Initialize a sctp_addr from a dst_entry. */ -static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst, +/* Initialize a sctp_addr from struct in6_addr. */ +static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr, __be16 port) { - struct rt6_info *rt = (struct rt6_info *)dst; addr->sa.sa_family = AF_INET6; addr->v6.sin6_port = port; - ipv6_addr_copy(&addr->v6.sin6_addr, &rt->rt6i_src.addr); + ipv6_addr_copy(&addr->v6.sin6_addr, saddr); } /* Compare addresses exactly. @@ -1001,7 +987,6 @@ static struct sctp_af sctp_af_inet6 = { .to_sk_daddr = sctp_v6_to_sk_daddr, .from_addr_param = sctp_v6_from_addr_param, .to_addr_param = sctp_v6_to_addr_param, - .dst_saddr = sctp_v6_dst_saddr, .cmp_addr = sctp_v6_cmp_addr, .scope = sctp_v6_scope, .addr_valid = sctp_v6_addr_valid, diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index d5bf91d04f63..34216458ded1 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -465,33 +465,35 @@ static sctp_scope_t sctp_v4_scope(union sctp_addr *addr) */ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, union sctp_addr *daddr, - union sctp_addr *saddr) + union sctp_addr *saddr, + struct flowi *fl, + struct sock *sk) { struct rtable *rt; - struct flowi4 fl4; + struct flowi4 *fl4 = &fl->u.ip4; struct sctp_bind_addr *bp; struct sctp_sockaddr_entry *laddr; struct dst_entry *dst = NULL; union sctp_addr dst_saddr; - memset(&fl4, 0x0, sizeof(struct flowi4)); - fl4.daddr = daddr->v4.sin_addr.s_addr; - fl4.fl4_dport = daddr->v4.sin_port; - fl4.flowi4_proto = IPPROTO_SCTP; + memset(fl4, 0x0, sizeof(struct flowi4)); + fl4->daddr = daddr->v4.sin_addr.s_addr; + fl4->fl4_dport = daddr->v4.sin_port; + fl4->flowi4_proto = IPPROTO_SCTP; if (asoc) { - fl4.flowi4_tos = RT_CONN_FLAGS(asoc->base.sk); - fl4.flowi4_oif = asoc->base.sk->sk_bound_dev_if; - fl4.fl4_sport = htons(asoc->base.bind_addr.port); + fl4->flowi4_tos = RT_CONN_FLAGS(asoc->base.sk); + fl4->flowi4_oif = asoc->base.sk->sk_bound_dev_if; + fl4->fl4_sport = htons(asoc->base.bind_addr.port); } if (saddr) { - fl4.saddr = saddr->v4.sin_addr.s_addr; - fl4.fl4_sport = saddr->v4.sin_port; + fl4->saddr = saddr->v4.sin_addr.s_addr; + fl4->fl4_sport = saddr->v4.sin_port; } SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", - __func__, &fl4.daddr, &fl4.saddr); + __func__, &fl4->daddr, &fl4->saddr); - rt = ip_route_output_key(&init_net, &fl4); + rt = ip_route_output_key(&init_net, fl4); if (!IS_ERR(rt)) dst = &rt->dst; @@ -533,9 +535,9 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, continue; if ((laddr->state == SCTP_ADDR_SRC) && (AF_INET == laddr->a.sa.sa_family)) { - fl4.saddr = laddr->a.v4.sin_addr.s_addr; - fl4.fl4_sport = laddr->a.v4.sin_port; - rt = ip_route_output_key(&init_net, &fl4); + fl4->saddr = laddr->a.v4.sin_addr.s_addr; + fl4->fl4_sport = laddr->a.v4.sin_port; + rt = ip_route_output_key(&init_net, fl4); if (!IS_ERR(rt)) { dst = &rt->dst; goto out_unlock; @@ -559,19 +561,15 @@ out: * to cache it separately and hence this is an empty routine. */ static void sctp_v4_get_saddr(struct sctp_sock *sk, - struct sctp_association *asoc, - struct dst_entry *dst, + struct sctp_transport *t, union sctp_addr *daddr, - union sctp_addr *saddr) + struct flowi *fl) { - struct rtable *rt = (struct rtable *)dst; - - if (!asoc) - return; + union sctp_addr *saddr = &t->saddr; + struct rtable *rt = (struct rtable *)t->dst; if (rt) { saddr->v4.sin_family = AF_INET; - saddr->v4.sin_port = htons(asoc->base.bind_addr.port); saddr->v4.sin_addr.s_addr = rt->rt_src; } } @@ -950,7 +948,6 @@ static struct sctp_af sctp_af_inet = { .to_sk_daddr = sctp_v4_to_sk_daddr, .from_addr_param = sctp_v4_from_addr_param, .to_addr_param = sctp_v4_to_addr_param, - .dst_saddr = sctp_v4_dst_saddr, .cmp_addr = sctp_v4_cmp_addr, .addr_valid = sctp_v4_addr_valid, .inaddr_any = sctp_v4_inaddr_any, diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f694ee116746..33d9ee629b4e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -2287,7 +2287,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, trans->param_flags = (trans->param_flags & ~SPP_PMTUD) | pmtud_change; if (update) { - sctp_transport_pmtu(trans); + sctp_transport_pmtu(trans, sctp_opt2sk(sp)); sctp_assoc_sync_pmtu(asoc); } } else if (asoc) { diff --git a/net/sctp/transport.c b/net/sctp/transport.c index d3ae493d234a..2544b9b21f86 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -211,11 +211,15 @@ void sctp_transport_set_owner(struct sctp_transport *transport, } /* Initialize the pmtu of a transport. */ -void sctp_transport_pmtu(struct sctp_transport *transport) +void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk) { struct dst_entry *dst; + struct flowi fl; - dst = transport->af_specific->get_dst(NULL, &transport->ipaddr, NULL); + dst = transport->af_specific->get_dst(transport->asoc, + &transport->ipaddr, + &transport->saddr, + &fl, sk); if (dst) { transport->pathmtu = dst_mtu(dst); @@ -272,15 +276,16 @@ void sctp_transport_route(struct sctp_transport *transport, struct sctp_af *af = transport->af_specific; union sctp_addr *daddr = &transport->ipaddr; struct dst_entry *dst; + struct flowi fl; - dst = af->get_dst(asoc, daddr, saddr); + dst = af->get_dst(asoc, daddr, saddr, &fl, sctp_opt2sk(opt)); + transport->dst = dst; if (saddr) memcpy(&transport->saddr, saddr, sizeof(union sctp_addr)); else - af->get_saddr(opt, asoc, dst, daddr, &transport->saddr); + af->get_saddr(opt, transport, daddr, &fl); - transport->dst = dst; if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { return; } -- cgit v1.2.3-58-ga151 From 9c6a02f41d10dc9fbf5dd42058e8846f38dd2d9a Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 26 Apr 2011 21:52:27 +0000 Subject: sctp: make sctp over IPv6 work with IPsec SCTP never called xfrm_output after it's v6 route lookups so that never really worked with ipsec. Additioanlly, we never passed port nubmers and protocol in the flowi, so any port based policies were never applied as well. Now that we can fixed ipv6 routing lookup code, using ip6_dst_lookup_flow() and pass port numbers. Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/sctp/ipv6.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 51c048d256f5..593c80162913 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -262,22 +262,27 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, __u8 matchlen = 0; __u8 bmatchlen; sctp_scope_t scope; - int err = 0; memset(fl6, 0, sizeof(struct flowi6)); ipv6_addr_copy(&fl6->daddr, &daddr->v6.sin6_addr); + fl6->fl6_dport = daddr->v6.sin6_port; + fl6->flowi6_proto = IPPROTO_SCTP; if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) fl6->flowi6_oif = daddr->v6.sin6_scope_id; SCTP_DEBUG_PRINTK("%s: DST=%pI6 ", __func__, &fl6->daddr); + if (asoc) + fl6->fl6_sport = htons(asoc->base.bind_addr.port); + if (saddr) { ipv6_addr_copy(&fl6->saddr, &saddr->v6.sin6_addr); + fl6->fl6_sport = saddr->v6.sin6_port; SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6->saddr); } - err = ip6_dst_lookup(sk, &dst, fl6); + dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); if (!asoc || saddr) goto out; @@ -286,7 +291,7 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, /* ip6_dst_lookup has filled in the fl6->saddr for us. Check * to see if we can use it. */ - if (!err) { + if (!IS_ERR(dst)) { /* Walk through the bind address list and look for a bind * address that matches the source address of the returned dst. */ @@ -330,11 +335,12 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, rcu_read_unlock(); if (baddr) { ipv6_addr_copy(&fl6->saddr, &baddr->v6.sin6_addr); - err = ip6_dst_lookup(sk, &dst, fl6); + fl6->fl6_sport = baddr->v6.sin6_port; + dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); } out: - if (!err) { + if (!IS_ERR(dst)) { struct rt6_info *rt; rt = (struct rt6_info *)dst; SCTP_DEBUG_PRINTK("rt6_dst:%pI6 rt6_src:%pI6\n", -- cgit v1.2.3-58-ga151 From af1384703f8a4ff3d245925d6596ef1c5c6e469e Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 26 Apr 2011 21:53:20 +0000 Subject: sctp: remove useless arguments from get_saddr() call There is no point in passing a destination address to a get_saddr() call. Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 1 - net/sctp/ipv6.c | 5 +---- net/sctp/protocol.c | 1 - net/sctp/transport.c | 2 +- 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 1d465d62f34f..bb2f43b7e9a8 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -571,7 +571,6 @@ struct sctp_af { struct sock *sk); void (*get_saddr) (struct sctp_sock *sk, struct sctp_transport *t, - union sctp_addr *daddr, struct flowi *fl); void (*copy_addrlist) (struct list_head *, struct net_device *); diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 593c80162913..a1913a4b6f3a 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -365,15 +365,12 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1, */ static void sctp_v6_get_saddr(struct sctp_sock *sk, struct sctp_transport *t, - union sctp_addr *daddr, struct flowi *fl) { struct flowi6 *fl6 = &fl->u.ip6; union sctp_addr *saddr = &t->saddr; - SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p daddr:%pI6 ", - __func__, t->asoc, t->dst, &daddr->v6.sin6_addr); - + SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p\n", __func__, t->asoc, t->dst); if (t->dst) { saddr->v6.sin6_family = AF_INET6; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 34216458ded1..68b4c4317d61 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -562,7 +562,6 @@ out: */ static void sctp_v4_get_saddr(struct sctp_sock *sk, struct sctp_transport *t, - union sctp_addr *daddr, struct flowi *fl) { union sctp_addr *saddr = &t->saddr; diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 2544b9b21f86..1fbb920f8dfb 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -284,7 +284,7 @@ void sctp_transport_route(struct sctp_transport *transport, if (saddr) memcpy(&transport->saddr, saddr, sizeof(union sctp_addr)); else - af->get_saddr(opt, transport, daddr, &fl); + af->get_saddr(opt, transport, &fl); if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { return; -- cgit v1.2.3-58-ga151 From da0420bee24a1ba54e55a61e95b1a53205d7e62d Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 26 Apr 2011 21:54:17 +0000 Subject: sctp: clean up route lookup calls Change the call to take the transport parameter and set the cached 'dst' appropriately inside the get_dst() function calls. This will allow us in the future to clean up source address storage as well. Signed-off-by: Vlad Yasevich Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 3 +-- net/sctp/ipv6.c | 17 ++++++++--------- net/sctp/protocol.c | 12 +++++------- net/sctp/transport.c | 23 ++++++++++------------- 4 files changed, 24 insertions(+), 31 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index bb2f43b7e9a8..ff3e8cce7d66 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -564,8 +564,7 @@ struct sctp_af { int optname, char __user *optval, int __user *optlen); - struct dst_entry *(*get_dst) (struct sctp_association *asoc, - union sctp_addr *daddr, + void (*get_dst) (struct sctp_transport *t, union sctp_addr *saddr, struct flowi *fl, struct sock *sk); diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index a1913a4b6f3a..500875f4dc41 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -247,17 +247,16 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) /* Returns the dst cache entry for the given source and destination ip * addresses. */ -static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, - union sctp_addr *daddr, - union sctp_addr *saddr, - struct flowi *fl, - struct sock *sk) +static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, + struct flowi *fl, struct sock *sk) { + struct sctp_association *asoc = t->asoc; struct dst_entry *dst = NULL; struct flowi6 *fl6 = &fl->u.ip6; struct sctp_bind_addr *bp; struct sctp_sockaddr_entry *laddr; union sctp_addr *baddr = NULL; + union sctp_addr *daddr = &t->ipaddr; union sctp_addr dst_saddr; __u8 matchlen = 0; __u8 bmatchlen; @@ -270,7 +269,6 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) fl6->flowi6_oif = daddr->v6.sin6_scope_id; - SCTP_DEBUG_PRINTK("%s: DST=%pI6 ", __func__, &fl6->daddr); if (asoc) @@ -343,12 +341,13 @@ out: if (!IS_ERR(dst)) { struct rt6_info *rt; rt = (struct rt6_info *)dst; + t->dst = dst; SCTP_DEBUG_PRINTK("rt6_dst:%pI6 rt6_src:%pI6\n", &rt->rt6i_dst.addr, &fl6->saddr); - return dst; + } else { + t->dst = NULL; + SCTP_DEBUG_PRINTK("NO ROUTE\n"); } - SCTP_DEBUG_PRINTK("NO ROUTE\n"); - return NULL; } /* Returns the number of consecutive initial bits that match in the 2 ipv6 diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 68b4c4317d61..9d3f15957d12 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -463,17 +463,16 @@ static sctp_scope_t sctp_v4_scope(union sctp_addr *addr) * addresses. If an association is passed, trys to get a dst entry with a * source address that matches an address in the bind address list. */ -static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, - union sctp_addr *daddr, - union sctp_addr *saddr, - struct flowi *fl, - struct sock *sk) +static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, + struct flowi *fl, struct sock *sk) { + struct sctp_association *asoc = t->asoc; struct rtable *rt; struct flowi4 *fl4 = &fl->u.ip4; struct sctp_bind_addr *bp; struct sctp_sockaddr_entry *laddr; struct dst_entry *dst = NULL; + union sctp_addr *daddr = &t->ipaddr; union sctp_addr dst_saddr; memset(fl4, 0x0, sizeof(struct flowi4)); @@ -548,13 +547,12 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, out_unlock: rcu_read_unlock(); out: + t->dst = dst; if (dst) SCTP_DEBUG_PRINTK("rt_dst:%pI4, rt_src:%pI4\n", &rt->rt_dst, &rt->rt_src); else SCTP_DEBUG_PRINTK("NO ROUTE\n"); - - return dst; } /* For v4, the source address is cached in the route entry(dst). So no need diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 1fbb920f8dfb..d8595dd1a8a7 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -213,17 +213,17 @@ void sctp_transport_set_owner(struct sctp_transport *transport, /* Initialize the pmtu of a transport. */ void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk) { - struct dst_entry *dst; struct flowi fl; - dst = transport->af_specific->get_dst(transport->asoc, - &transport->ipaddr, - &transport->saddr, + /* If we don't have a fresh route, look one up */ + if (!transport->dst || transport->dst->obsolete > 1) { + dst_release(transport->dst); + transport->af_specific->get_dst(transport, &transport->saddr, &fl, sk); + } - if (dst) { - transport->pathmtu = dst_mtu(dst); - dst_release(dst); + if (transport->dst) { + transport->pathmtu = dst_mtu(transport->dst); } else transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; } @@ -274,12 +274,9 @@ void sctp_transport_route(struct sctp_transport *transport, { struct sctp_association *asoc = transport->asoc; struct sctp_af *af = transport->af_specific; - union sctp_addr *daddr = &transport->ipaddr; - struct dst_entry *dst; struct flowi fl; - dst = af->get_dst(asoc, daddr, saddr, &fl, sctp_opt2sk(opt)); - transport->dst = dst; + af->get_dst(transport, saddr, &fl, sctp_opt2sk(opt)); if (saddr) memcpy(&transport->saddr, saddr, sizeof(union sctp_addr)); @@ -289,8 +286,8 @@ void sctp_transport_route(struct sctp_transport *transport, if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { return; } - if (dst) { - transport->pathmtu = dst_mtu(dst); + if (transport->dst) { + transport->pathmtu = dst_mtu(transport->dst); /* Initialize sk->sk_rcv_saddr, if the transport is the * association's active path for getsockname(). -- cgit v1.2.3-58-ga151 From 15ecd039b7182d725f4294e01f2fb12c3a88db17 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Wed, 27 Apr 2011 13:52:22 -0700 Subject: r8169: fix merge conflict fix. - use adequate MAC_VER id (see 01dc7fec4025f6bb72b6b98ec88b375346b6dbbb) - remove duplicate rtl_firmware_info record - remove duplicate functions Signed-off-by: Francois Romieu Cc: Realtek linux nic maintainers Signed-off-by: David S. Miller --- drivers/net/r8169.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 025dedda40a0..6364e0b03fdd 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -191,9 +191,8 @@ static const struct rtl_firmware_info { { .mac_version = RTL_GIGA_MAC_VER_26, .fw_name = FIRMWARE_8168D_2 }, { .mac_version = RTL_GIGA_MAC_VER_29, .fw_name = FIRMWARE_8105E_1 }, { .mac_version = RTL_GIGA_MAC_VER_30, .fw_name = FIRMWARE_8105E_1 }, - { .mac_version = RTL_GIGA_MAC_VER_30, .fw_name = FIRMWARE_8105E_1 }, - { .mac_version = RTL_GIGA_MAC_VER_31, .fw_name = FIRMWARE_8168E_1 }, - { .mac_version = RTL_GIGA_MAC_VER_32, .fw_name = FIRMWARE_8168E_2 } + { .mac_version = RTL_GIGA_MAC_VER_32, .fw_name = FIRMWARE_8168E_1 }, + { .mac_version = RTL_GIGA_MAC_VER_33, .fw_name = FIRMWARE_8168E_2 } }; enum cfg_version { @@ -2535,6 +2534,8 @@ static void rtl8168e_hw_phy_config(struct rtl8169_private *tp) { 0x1f, 0x0000 } }; + rtl_apply_firmware(tp); + rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); /* DCO enable for 10M IDLE Power */ @@ -2576,20 +2577,6 @@ static void rtl8168e_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x0d, 0x0000); } -static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp) -{ - rtl_apply_firmware(tp); - - rtl8168e_hw_phy_config(tp); -} - -static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp) -{ - rtl_apply_firmware(tp); - - rtl8168e_hw_phy_config(tp); -} - static void rtl8102e_hw_phy_config(struct rtl8169_private *tp) { static const struct phy_reg phy_reg_init[] = { @@ -2705,10 +2692,8 @@ static void rtl_hw_phy_config(struct net_device *dev) rtl8105e_hw_phy_config(tp); break; case RTL_GIGA_MAC_VER_32: - rtl8168e_1_hw_phy_config(tp); - break; case RTL_GIGA_MAC_VER_33: - rtl8168e_2_hw_phy_config(tp); + rtl8168e_hw_phy_config(tp); break; default: -- cgit v1.2.3-58-ga151 From 2d7192d6cbab20e153c47fa1559ffd41ceef0e79 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 26 Apr 2011 13:28:44 -0700 Subject: ipv4: Sanitize and simplify ip_route_{connect,newports}() These functions are used together as a unit for route resolution during connect(). They address the chicken-and-egg problem that exists when ports need to be allocated during connect() processing, yet such port allocations require addressing information from the routing code. It's currently more heavy handed than it needs to be, and in particular we allocate and initialize a flow object twice. Let the callers provide the on-stack flow object. That way we only need to initialize it once in the ip_route_connect() call. Later, if ip_route_newports() needs to do anything, it re-uses that flow object as-is except for the ports which it updates before the route re-lookup. Also, describe why this set of facilities are needed and how it works in a big comment. Signed-off-by: David S. Miller Reviewed-by: Eric Dumazet --- include/net/route.h | 88 ++++++++++++++++++++++++++++++++++------------------- net/dccp/ipv4.c | 10 +++--- net/ipv4/af_inet.c | 3 +- net/ipv4/datagram.c | 3 +- net/ipv4/tcp_ipv4.c | 10 +++--- net/l2tp/l2tp_ip.c | 8 ++--- 6 files changed, 74 insertions(+), 48 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index 3684c3edbae4..79530da31b34 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -217,17 +217,37 @@ static inline char rt_tos2priority(u8 tos) return ip_tos2prio[IPTOS_TOS(tos)>>1]; } -static inline struct rtable *ip_route_connect(__be32 dst, __be32 src, u32 tos, - int oif, u8 protocol, - __be16 sport, __be16 dport, - struct sock *sk, bool can_sleep) +/* ip_route_connect() and ip_route_newports() work in tandem whilst + * binding a socket for a new outgoing connection. + * + * In order to use IPSEC properly, we must, in the end, have a + * route that was looked up using all available keys including source + * and destination ports. + * + * However, if a source port needs to be allocated (the user specified + * a wildcard source port) we need to obtain addressing information + * in order to perform that allocation. + * + * So ip_route_connect() looks up a route using wildcarded source and + * destination ports in the key, simply so that we can get a pair of + * addresses to use for port allocation. + * + * Later, once the ports are allocated, ip_route_newports() will make + * another route lookup if needed to make sure we catch any IPSEC + * rules keyed on the port information. + * + * The callers allocate the flow key on their stack, and must pass in + * the same flowi4 object to both the ip_route_connect() and the + * ip_route_newports() calls. + */ + +static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32 src, + u32 tos, int oif, u8 protocol, + __be16 sport, __be16 dport, + struct sock *sk, bool can_sleep) { - struct net *net = sock_net(sk); - struct rtable *rt; - struct flowi4 fl4; - __u8 flow_flags; + __u8 flow_flags = 0; - flow_flags = 0; if (inet_sk(sk)->transparent) flow_flags |= FLOWI_FLAG_ANYSRC; if (protocol == IPPROTO_TCP) @@ -235,41 +255,45 @@ static inline struct rtable *ip_route_connect(__be32 dst, __be32 src, u32 tos, if (can_sleep) flow_flags |= FLOWI_FLAG_CAN_SLEEP; - flowi4_init_output(&fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE, + flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE, protocol, flow_flags, dst, src, dport, sport); +} + +static inline struct rtable *ip_route_connect(struct flowi4 *fl4, + __be32 dst, __be32 src, u32 tos, + int oif, u8 protocol, + __be16 sport, __be16 dport, + struct sock *sk, bool can_sleep) +{ + struct net *net = sock_net(sk); + struct rtable *rt; + + ip_route_connect_init(fl4, dst, src, tos, oif, protocol, + sport, dport, sk, can_sleep); if (!dst || !src) { - rt = __ip_route_output_key(net, &fl4); + rt = __ip_route_output_key(net, fl4); if (IS_ERR(rt)) return rt; - fl4.daddr = rt->rt_dst; - fl4.saddr = rt->rt_src; + fl4->daddr = rt->rt_dst; + fl4->saddr = rt->rt_src; ip_rt_put(rt); } - security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); - return ip_route_output_flow(net, &fl4, sk); + security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); + return ip_route_output_flow(net, fl4, sk); } -static inline struct rtable *ip_route_newports(struct rtable *rt, - u8 protocol, __be16 orig_sport, - __be16 orig_dport, __be16 sport, - __be16 dport, struct sock *sk) +static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable *rt, + __be16 orig_sport, __be16 orig_dport, + __be16 sport, __be16 dport, + struct sock *sk) { if (sport != orig_sport || dport != orig_dport) { - struct flowi4 fl4; - __u8 flow_flags; - - flow_flags = 0; - if (inet_sk(sk)->transparent) - flow_flags |= FLOWI_FLAG_ANYSRC; - if (protocol == IPPROTO_TCP) - flow_flags |= FLOWI_FLAG_PRECOW_METRICS; - flowi4_init_output(&fl4, rt->rt_oif, rt->rt_mark, rt->rt_tos, - RT_SCOPE_UNIVERSE, protocol, flow_flags, - rt->rt_dst, rt->rt_src, dport, sport); + fl4->fl4_dport = dport; + fl4->fl4_sport = sport; ip_rt_put(rt); - security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); - return ip_route_output_flow(sock_net(sk), &fl4, sk); + security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); + return ip_route_output_flow(sock_net(sk), fl4, sk); } return rt; } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index ae451c6d83ba..b92ab655d44e 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -40,12 +40,13 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { + const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr; struct inet_sock *inet = inet_sk(sk); struct dccp_sock *dp = dccp_sk(sk); - const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr; __be16 orig_sport, orig_dport; - struct rtable *rt; __be32 daddr, nexthop; + struct flowi4 fl4; + struct rtable *rt; int err; dp->dccps_role = DCCP_ROLE_CLIENT; @@ -65,7 +66,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) orig_sport = inet->inet_sport; orig_dport = usin->sin_port; - rt = ip_route_connect(nexthop, inet->inet_saddr, + rt = ip_route_connect(&fl4, nexthop, inet->inet_saddr, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, IPPROTO_DCCP, orig_sport, orig_dport, sk, true); @@ -101,8 +102,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (err != 0) goto failure; - rt = ip_route_newports(rt, IPPROTO_DCCP, - orig_sport, orig_dport, + rt = ip_route_newports(&fl4, rt, orig_sport, orig_dport, inet->inet_sport, inet->inet_dport, sk); if (IS_ERR(rt)) { rt = NULL; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index cae75ef21fea..0413af3e2285 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1103,6 +1103,7 @@ static int inet_sk_reselect_saddr(struct sock *sk) struct inet_sock *inet = inet_sk(sk); __be32 old_saddr = inet->inet_saddr; __be32 daddr = inet->inet_daddr; + struct flowi4 fl4; struct rtable *rt; __be32 new_saddr; @@ -1110,7 +1111,7 @@ static int inet_sk_reselect_saddr(struct sock *sk) daddr = inet->opt->faddr; /* Query new route. */ - rt = ip_route_connect(daddr, 0, RT_CONN_FLAGS(sk), + rt = ip_route_connect(&fl4, daddr, 0, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, sk->sk_protocol, inet->inet_sport, inet->inet_dport, sk, false); if (IS_ERR(rt)) diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index 85bd24ca4f6d..216ba2338b64 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -24,6 +24,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { struct inet_sock *inet = inet_sk(sk); struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; + struct flowi4 fl4; struct rtable *rt; __be32 saddr; int oif; @@ -46,7 +47,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (!saddr) saddr = inet->mc_addr; } - rt = ip_route_connect(usin->sin_addr.s_addr, saddr, + rt = ip_route_connect(&fl4, usin->sin_addr.s_addr, saddr, RT_CONN_FLAGS(sk), oif, sk->sk_protocol, inet->inet_sport, usin->sin_port, sk, true); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index edf18bd74b87..310454c2f4d1 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -146,12 +146,13 @@ EXPORT_SYMBOL_GPL(tcp_twsk_unique); /* This will initiate an outgoing connection. */ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { + struct sockaddr_in *usin = (struct sockaddr_in *)uaddr; struct inet_sock *inet = inet_sk(sk); struct tcp_sock *tp = tcp_sk(sk); - struct sockaddr_in *usin = (struct sockaddr_in *)uaddr; __be16 orig_sport, orig_dport; - struct rtable *rt; __be32 daddr, nexthop; + struct flowi4 fl4; + struct rtable *rt; int err; if (addr_len < sizeof(struct sockaddr_in)) @@ -169,7 +170,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) orig_sport = inet->inet_sport; orig_dport = usin->sin_port; - rt = ip_route_connect(nexthop, inet->inet_saddr, + rt = ip_route_connect(&fl4, nexthop, inet->inet_saddr, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, IPPROTO_TCP, orig_sport, orig_dport, sk, true); @@ -236,8 +237,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (err) goto failure; - rt = ip_route_newports(rt, IPPROTO_TCP, - orig_sport, orig_dport, + rt = ip_route_newports(&fl4, rt, orig_sport, orig_dport, inet->inet_sport, inet->inet_dport, sk); if (IS_ERR(rt)) { err = PTR_ERR(rt); diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index fce9bd3bd3fe..cc673677c5de 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -296,12 +296,12 @@ out_in_use: static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { - int rc; - struct inet_sock *inet = inet_sk(sk); struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *) uaddr; + struct inet_sock *inet = inet_sk(sk); + struct flowi4 fl4; struct rtable *rt; __be32 saddr; - int oif; + int oif, rc; rc = -EINVAL; if (addr_len < sizeof(*lsa)) @@ -320,7 +320,7 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len if (ipv4_is_multicast(lsa->l2tp_addr.s_addr)) goto out; - rt = ip_route_connect(lsa->l2tp_addr.s_addr, saddr, + rt = ip_route_connect(&fl4, lsa->l2tp_addr.s_addr, saddr, RT_CONN_FLAGS(sk), oif, IPPROTO_L2TP, 0, 0, sk, true); -- cgit v1.2.3-58-ga151 From 2e97e980b5653c23d01c911af6a0ab2d3431d7f1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 26 Apr 2011 13:57:47 -0700 Subject: ipv4: Remove erroneous check in igmpv3_newpack() and igmp_send_report(). Output route resolution never returns a route with rt_src set to zero (which is INADDR_ANY). Even if the flow key for the output route lookup specifies INADDR_ANY for the source address, the output route resolution chooses a real source address to use in the final route. This test has existed forever in igmp_send_report() and David Stevens simply copied over the erroneous test when implementing support for IGMPv3. Signed-off-by: David S. Miller Reviewed-by: Eric Dumazet --- net/ipv4/igmp.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 1fd3d9ce8398..8ae0a5702f56 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -328,11 +328,6 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) kfree_skb(skb); return NULL; } - if (rt->rt_src == 0) { - kfree_skb(skb); - ip_rt_put(rt); - return NULL; - } skb_dst_set(skb, &rt->dst); skb->dev = dev; @@ -670,11 +665,6 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, if (IS_ERR(rt)) return -1; - if (rt->rt_src == 0) { - ip_rt_put(rt); - return -1; - } - skb = alloc_skb(IGMP_SIZE+LL_ALLOCATED_SPACE(dev), GFP_ATOMIC); if (skb == NULL) { ip_rt_put(rt); -- cgit v1.2.3-58-ga151 From b678027cb77b079bc8e5b94172995d173bdb494b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 26 Apr 2011 14:58:35 -0700 Subject: ipv4: Kill RTO_CONN. It's not used by anything in the kernel, and defined in net/route.h so never exported to userspace. Therefore we can safely remove it. Signed-off-by: David S. Miller --- include/net/route.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index 79530da31b34..fdbdb9271d7f 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -37,10 +37,6 @@ #define RTO_ONLINK 0x01 -#define RTO_CONN 0 -/* RTO_CONN is not used (being alias for 0), but preserved not to break - * some modules referring to it. */ - #define RT_CONN_FLAGS(sk) (RT_TOS(inet_sk(sk)->tos) | sock_flag(sk, SOCK_LOCALROUTE)) struct fib_nh; -- cgit v1.2.3-58-ga151 From 5d41ce1dd91bce01d50aff79786dc5d5eedcfab7 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 8 Apr 2011 15:40:02 -0300 Subject: Bluetooth: Refactor L2CAP channel allocation If the allocation happens at l2cap_sock_create() will be able to use the struct l2cap_chan to store channel info that comes from the user via setsockopt. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 3 ++- net/bluetooth/l2cap_core.c | 23 +++++++---------------- net/bluetooth/l2cap_sock.c | 11 ++++++++++- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 7a215a7f9e39..537e3c16339f 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -465,7 +465,8 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent); struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); +struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); void l2cap_chan_del(struct l2cap_chan *chan, int err); -int l2cap_do_connect(struct sock *sk); +int l2cap_do_connect(struct l2cap_chan *chan); #endif /* __L2CAP_H */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9e8dc136ef16..4b857adc5361 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -149,7 +149,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) return 0; } -static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) +struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) { struct l2cap_chan *chan; @@ -648,6 +648,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) goto clean; } + l2cap_pi(sk)->chan = chan; + write_lock_bh(&conn->chan_lock); hci_conn_hold(conn->hcon); @@ -661,8 +663,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) __l2cap_chan_add(conn, chan); - l2cap_pi(sk)->chan = chan; - l2cap_sock_set_timer(sk, sk->sk_sndtimeo); sk->sk_state = BT_CONNECTED; @@ -847,12 +847,12 @@ static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) return node ? sk : sk1; } -int l2cap_do_connect(struct sock *sk) +int l2cap_do_connect(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; bdaddr_t *src = &bt_sk(sk)->src; bdaddr_t *dst = &bt_sk(sk)->dst; struct l2cap_conn *conn; - struct l2cap_chan *chan; struct hci_conn *hcon; struct hci_dev *hdev; __u8 auth_type; @@ -888,20 +888,11 @@ int l2cap_do_connect(struct sock *sk) goto done; } - chan = l2cap_chan_alloc(sk); - if (!chan) { - hci_conn_put(hcon); - err = -ENOMEM; - goto done; - } - /* Update source addr of the socket */ bacpy(src, conn->src); l2cap_chan_add(conn, chan); - l2cap_pi(sk)->chan = chan; - sk->sk_state = BT_CONNECT; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); @@ -2076,6 +2067,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd goto response; } + l2cap_pi(sk)->chan = chan; + write_lock_bh(&conn->chan_lock); /* Check if we already have channel with that dcid */ @@ -2098,8 +2091,6 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd __l2cap_chan_add(conn, chan); - l2cap_pi(sk)->chan = chan; - dcid = l2cap_pi(sk)->scid; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 473e5973d8fe..e3724572c448 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -229,7 +229,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al l2cap_pi(sk)->psm = la.l2_psm; l2cap_pi(sk)->dcid = la.l2_cid; - err = l2cap_do_connect(sk); + err = l2cap_do_connect(l2cap_pi(sk)->chan); if (err) goto done; @@ -1054,6 +1054,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, int kern) { struct sock *sk; + struct l2cap_chan *chan; BT_DBG("sock %p", sock); @@ -1072,6 +1073,14 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, if (!sk) return -ENOMEM; + chan = l2cap_chan_alloc(sk); + if (!chan) { + l2cap_sock_kill(sk); + return -ENOMEM; + } + + l2cap_pi(sk)->chan = chan; + l2cap_sock_init(sk, NULL); return 0; } -- cgit v1.2.3-58-ga151 From b44500351845e4f6df0d752a8870da246be8216f Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 12 Apr 2011 18:15:09 -0300 Subject: Bluetooth: Move conf_state to struct l2cap_chan First move of elements depending on user data. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 3 +- net/bluetooth/l2cap_core.c | 88 ++++++++++++++++++++++--------------------- net/bluetooth/l2cap_sock.c | 10 +++-- 3 files changed, 53 insertions(+), 48 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 537e3c16339f..b3bb3d492fff 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -291,6 +291,7 @@ struct l2cap_chan { __u8 num_conf_req; __u8 num_conf_rsp; + __u8 conf_state; __u16 conn_state; __u8 next_tx_seq; @@ -375,8 +376,6 @@ struct l2cap_pinfo { __u8 force_reliable; __u8 flushable; - __u8 conf_state; - __u8 tx_win; __u8 max_tx; __u16 retrans_timeout; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 4b857adc5361..190b04960dae 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -236,8 +236,8 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) } else sk->sk_state_change(sk); - if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE && - l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE)) + if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE && + chan->conf_state & L2CAP_CONF_INPUT_DONE)) goto free; skb_queue_purge(&chan->tx_q); @@ -411,9 +411,9 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control) l2cap_send_sframe(chan, control); } -static inline int __l2cap_no_conn_pending(struct sock *sk) +static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) { - return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND); + return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND); } static void l2cap_do_start(struct l2cap_chan *chan) @@ -425,13 +425,13 @@ static void l2cap_do_start(struct l2cap_chan *chan) if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) return; - if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) { + if (l2cap_check_security(sk) && __l2cap_no_conn_pending(chan)) { struct l2cap_conn_req req; req.scid = cpu_to_le16(l2cap_pi(sk)->scid); req.psm = l2cap_pi(sk)->psm; chan->ident = l2cap_get_ident(conn); - l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; + chan->conf_state |= L2CAP_CONF_CONNECT_PEND; l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); @@ -516,14 +516,14 @@ static void l2cap_conn_start(struct l2cap_conn *conn) struct l2cap_conn_req req; if (!l2cap_check_security(sk) || - !__l2cap_no_conn_pending(sk)) { + !__l2cap_no_conn_pending(chan)) { bh_unlock_sock(sk); continue; } if (!l2cap_mode_supported(l2cap_pi(sk)->mode, conn->feat_mask) - && l2cap_pi(sk)->conf_state & + && chan->conf_state & L2CAP_CONF_STATE2_DEVICE) { /* __l2cap_sock_close() calls list_del(chan) * so release the lock */ @@ -538,7 +538,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) req.psm = l2cap_pi(sk)->psm; chan->ident = l2cap_get_ident(conn); - l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; + chan->conf_state |= L2CAP_CONF_CONNECT_PEND; l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); @@ -569,13 +569,13 @@ static void l2cap_conn_start(struct l2cap_conn *conn) l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT || + if (chan->conf_state & L2CAP_CONF_REQ_SENT || rsp.result != L2CAP_CR_SUCCESS) { bh_unlock_sock(sk); continue; } - l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; + chan->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; @@ -1382,10 +1382,11 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le static void l2cap_chan_ready(struct sock *sk) { struct sock *parent = bt_sk(sk)->parent; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; BT_DBG("sk %p, parent %p", sk, parent); - l2cap_pi(sk)->conf_state = 0; + chan->conf_state = 0; l2cap_sock_clear_timer(sk); if (!parent) { @@ -1619,7 +1620,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) switch (pi->mode) { case L2CAP_MODE_STREAMING: case L2CAP_MODE_ERTM: - if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE) + if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE) break; /* fall through */ @@ -1666,7 +1667,7 @@ done: break; if (pi->fcs == L2CAP_FCS_NONE || - pi->conf_state & L2CAP_CONF_NO_FCS_RECV) { + chan->conf_state & L2CAP_CONF_NO_FCS_RECV) { pi->fcs = L2CAP_FCS_NONE; l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs); } @@ -1689,7 +1690,7 @@ done: break; if (pi->fcs == L2CAP_FCS_NONE || - pi->conf_state & L2CAP_CONF_NO_FCS_RECV) { + chan->conf_state & L2CAP_CONF_NO_FCS_RECV) { pi->fcs = L2CAP_FCS_NONE; l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs); } @@ -1742,7 +1743,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) case L2CAP_CONF_FCS: if (val == L2CAP_FCS_NONE) - pi->conf_state |= L2CAP_CONF_NO_FCS_RECV; + chan->conf_state |= L2CAP_CONF_NO_FCS_RECV; break; @@ -1762,7 +1763,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) switch (pi->mode) { case L2CAP_MODE_STREAMING: case L2CAP_MODE_ERTM: - if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) { + if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) { pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask); break; @@ -1795,14 +1796,14 @@ done: result = L2CAP_CONF_UNACCEPT; else { pi->omtu = mtu; - pi->conf_state |= L2CAP_CONF_MTU_DONE; + chan->conf_state |= L2CAP_CONF_MTU_DONE; } l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu); switch (rfc.mode) { case L2CAP_MODE_BASIC: pi->fcs = L2CAP_FCS_NONE; - pi->conf_state |= L2CAP_CONF_MODE_DONE; + chan->conf_state |= L2CAP_CONF_MODE_DONE; break; case L2CAP_MODE_ERTM: @@ -1819,7 +1820,7 @@ done: rfc.monitor_timeout = le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO); - pi->conf_state |= L2CAP_CONF_MODE_DONE; + chan->conf_state |= L2CAP_CONF_MODE_DONE; l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); @@ -1832,7 +1833,7 @@ done: chan->remote_mps = le16_to_cpu(rfc.max_pdu_size); - pi->conf_state |= L2CAP_CONF_MODE_DONE; + chan->conf_state |= L2CAP_CONF_MODE_DONE; l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); @@ -1847,7 +1848,7 @@ done: } if (result == L2CAP_CONF_SUCCESS) - pi->conf_state |= L2CAP_CONF_OUTPUT_DONE; + chan->conf_state |= L2CAP_CONF_OUTPUT_DONE; } rsp->scid = cpu_to_le16(pi->dcid); rsp->result = cpu_to_le16(result); @@ -1856,8 +1857,9 @@ done: return ptr - data; } -static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result) +static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); struct l2cap_conf_req *req = data; void *ptr = req->data; @@ -1890,7 +1892,7 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, if (olen == sizeof(rfc)) memcpy(&rfc, (void *)val, olen); - if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) && + if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) && rfc.mode != pi->mode) return -ECONNREFUSED; @@ -1955,10 +1957,10 @@ void __l2cap_connect_rsp_defer(struct sock *sk) l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) + if (chan->conf_state & L2CAP_CONF_REQ_SENT) return; - l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; + chan->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; @@ -2146,10 +2148,10 @@ sendresp: L2CAP_INFO_REQ, sizeof(info), &info); } - if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) && + if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) && result == L2CAP_CR_SUCCESS) { u8 buf[128]; - l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; + chan->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; @@ -2190,12 +2192,12 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd sk->sk_state = BT_CONFIG; chan->ident = 0; l2cap_pi(sk)->dcid = dcid; - l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND; + chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND; - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) + if (chan->conf_state & L2CAP_CONF_REQ_SENT) break; - l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; + chan->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, l2cap_build_conf_req(chan, req), req); @@ -2203,7 +2205,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd break; case L2CAP_CR_PEND: - l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; + chan->conf_state |= L2CAP_CONF_CONNECT_PEND; break; default: @@ -2230,7 +2232,7 @@ static inline void set_default_fcs(struct l2cap_pinfo *pi) */ if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING) pi->fcs = L2CAP_FCS_NONE; - else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV)) + else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV)) pi->fcs = L2CAP_FCS_CRC16; } @@ -2297,10 +2299,10 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr /* Reset config buffer. */ chan->conf_len = 0; - if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE)) + if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE)) goto unlock; - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) { + if (chan->conf_state & L2CAP_CONF_INPUT_DONE) { set_default_fcs(l2cap_pi(sk)); sk->sk_state = BT_CONNECTED; @@ -2315,9 +2317,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr goto unlock; } - if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) { + if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) { u8 buf[64]; - l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; + chan->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; @@ -2365,8 +2367,8 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr /* throw out any old stored conf requests */ result = L2CAP_CONF_SUCCESS; - len = l2cap_parse_conf_rsp(sk, rsp->data, - len, req, &result); + len = l2cap_parse_conf_rsp(chan, rsp->data, len, + req, &result); if (len < 0) { l2cap_send_disconn_req(conn, chan, ECONNRESET); goto done; @@ -2390,9 +2392,9 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr if (flags & 0x01) goto done; - l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE; + chan->conf_state |= L2CAP_CONF_INPUT_DONE; - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) { + if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) { set_default_fcs(l2cap_pi(sk)); sk->sk_state = BT_CONNECTED; @@ -3899,7 +3901,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) bh_lock_sock(sk); - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) { + if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) { bh_unlock_sock(sk); continue; } @@ -3918,7 +3920,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) req.psm = l2cap_pi(sk)->psm; chan->ident = l2cap_get_ident(conn); - l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; + chan->conf_state |= L2CAP_CONF_CONNECT_PEND; l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index e3724572c448..a29782a0083a 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -528,6 +528,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct l2cap_options opts; int len, err = 0; u32 opt; @@ -565,7 +566,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us l2cap_pi(sk)->mode = opts.mode; switch (l2cap_pi(sk)->mode) { case L2CAP_MODE_BASIC: - l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE; + chan->conf_state &= ~L2CAP_CONF_STATE2_DEVICE; break; case L2CAP_MODE_ERTM: case L2CAP_MODE_STREAMING: @@ -979,16 +980,19 @@ static void l2cap_sock_destruct(struct sock *sk) void l2cap_sock_init(struct sock *sk, struct sock *parent) { struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_chan *chan = pi->chan; BT_DBG("sk %p", sk); if (parent) { + struct l2cap_chan *pchan = l2cap_pi(parent)->chan; + sk->sk_type = parent->sk_type; bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup; pi->imtu = l2cap_pi(parent)->imtu; pi->omtu = l2cap_pi(parent)->omtu; - pi->conf_state = l2cap_pi(parent)->conf_state; + chan->conf_state = pchan->conf_state; pi->mode = l2cap_pi(parent)->mode; pi->fcs = l2cap_pi(parent)->fcs; pi->max_tx = l2cap_pi(parent)->max_tx; @@ -1002,7 +1006,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->omtu = 0; if (!disable_ertm && sk->sk_type == SOCK_STREAM) { pi->mode = L2CAP_MODE_ERTM; - pi->conf_state |= L2CAP_CONF_STATE2_DEVICE; + chan->conf_state |= L2CAP_CONF_STATE2_DEVICE; } else { pi->mode = L2CAP_MODE_BASIC; } -- cgit v1.2.3-58-ga151 From 77a74c7e0861e6ebac7effe233fd7e83f1ad9ecc Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 12 Apr 2011 18:17:14 -0300 Subject: Bluetooth: Rename l2cap_do_connect() to l2cap_chan_connect() l2cap_chan_connect() is a much better name and reflects what this functions is doing (or will do once socket dependence is removed from the core). Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 2 +- net/bluetooth/l2cap_core.c | 2 +- net/bluetooth/l2cap_sock.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index b3bb3d492fff..f70935000345 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -466,6 +466,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); void l2cap_chan_del(struct l2cap_chan *chan, int err); -int l2cap_do_connect(struct l2cap_chan *chan); +int l2cap_chan_connect(struct l2cap_chan *chan); #endif /* __L2CAP_H */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 190b04960dae..29742d875e60 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -847,7 +847,7 @@ static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) return node ? sk : sk1; } -int l2cap_do_connect(struct l2cap_chan *chan) +int l2cap_chan_connect(struct l2cap_chan *chan) { struct sock *sk = chan->sk; bdaddr_t *src = &bt_sk(sk)->src; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index a29782a0083a..50437c665d1e 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -229,7 +229,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al l2cap_pi(sk)->psm = la.l2_psm; l2cap_pi(sk)->dcid = la.l2_cid; - err = l2cap_do_connect(l2cap_pi(sk)->chan); + err = l2cap_chan_connect(l2cap_pi(sk)->chan); if (err) goto done; -- cgit v1.2.3-58-ga151 From 4343478f3a4806394136d8141b2e451aa5443f03 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 12 Apr 2011 18:31:57 -0300 Subject: Bluetooth: Move some more elements to struct l2cap_chan In this commit sec_level, force_reliable, role_switch and flushable. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 12 ++++--- net/bluetooth/l2cap_core.c | 78 +++++++++++++++++++++++-------------------- net/bluetooth/l2cap_sock.c | 52 ++++++++++++++++------------- 3 files changed, 77 insertions(+), 65 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index f70935000345..684deee6ec52 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -284,6 +284,12 @@ struct srej_list { struct l2cap_chan { struct sock *sk; + + __u8 sec_level; + __u8 role_switch; + __u8 force_reliable; + __u8 flushable; + __u8 ident; __u8 conf_req[64]; @@ -371,10 +377,6 @@ struct l2cap_pinfo { __u8 mode; __u8 fcs; - __u8 sec_level; - __u8 role_switch; - __u8 force_reliable; - __u8 flushable; __u8 tx_win; __u8 max_tx; @@ -452,7 +454,7 @@ struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, s struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len); struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen); int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); -void l2cap_do_send(struct sock *sk, struct sk_buff *skb); +void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb); void l2cap_streaming_send(struct l2cap_chan *chan); int l2cap_ertm_send(struct l2cap_chan *chan); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 29742d875e60..0fc6bbe85d41 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -262,10 +262,12 @@ free: kfree(chan); } -static inline u8 l2cap_get_auth_type(struct sock *sk) +static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; + if (sk->sk_type == SOCK_RAW) { - switch (l2cap_pi(sk)->sec_level) { + switch (chan->sec_level) { case BT_SECURITY_HIGH: return HCI_AT_DEDICATED_BONDING_MITM; case BT_SECURITY_MEDIUM: @@ -274,15 +276,15 @@ static inline u8 l2cap_get_auth_type(struct sock *sk) return HCI_AT_NO_BONDING; } } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) { - if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW) - l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; + if (chan->sec_level == BT_SECURITY_LOW) + chan->sec_level = BT_SECURITY_SDP; - if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH) + if (chan->sec_level == BT_SECURITY_HIGH) return HCI_AT_NO_BONDING_MITM; else return HCI_AT_NO_BONDING; } else { - switch (l2cap_pi(sk)->sec_level) { + switch (chan->sec_level) { case BT_SECURITY_HIGH: return HCI_AT_GENERAL_BONDING_MITM; case BT_SECURITY_MEDIUM: @@ -294,15 +296,14 @@ static inline u8 l2cap_get_auth_type(struct sock *sk) } /* Service level security */ -static inline int l2cap_check_security(struct sock *sk) +static inline int l2cap_check_security(struct l2cap_chan *chan) { - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = l2cap_pi(chan->sk)->conn; __u8 auth_type; - auth_type = l2cap_get_auth_type(sk); + auth_type = l2cap_get_auth_type(chan); - return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level, - auth_type); + return hci_conn_security(conn->hcon, chan->sec_level, auth_type); } u8 l2cap_get_ident(struct l2cap_conn *conn) @@ -425,7 +426,8 @@ static void l2cap_do_start(struct l2cap_chan *chan) if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) return; - if (l2cap_check_security(sk) && __l2cap_no_conn_pending(chan)) { + if (l2cap_check_security(chan) && + __l2cap_no_conn_pending(chan)) { struct l2cap_conn_req req; req.scid = cpu_to_le16(l2cap_pi(sk)->scid); req.psm = l2cap_pi(sk)->psm; @@ -515,7 +517,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) if (sk->sk_state == BT_CONNECT) { struct l2cap_conn_req req; - if (!l2cap_check_security(sk) || + if (!l2cap_check_security(chan) || !__l2cap_no_conn_pending(chan)) { bh_unlock_sock(sk); continue; @@ -549,7 +551,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); - if (l2cap_check_security(sk)) { + if (l2cap_check_security(chan)) { if (bt_sk(sk)->defer_setup) { struct sock *parent = bt_sk(sk)->parent; rsp.result = cpu_to_le16(L2CAP_CR_PEND); @@ -722,7 +724,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) list_for_each_entry(chan, &conn->chan_l, list) { struct sock *sk = chan->sk; - if (l2cap_pi(sk)->force_reliable) + if (chan->force_reliable) sk->sk_err = err; } @@ -867,14 +869,14 @@ int l2cap_chan_connect(struct l2cap_chan *chan) hci_dev_lock_bh(hdev); - auth_type = l2cap_get_auth_type(sk); + auth_type = l2cap_get_auth_type(chan); if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA) hcon = hci_connect(hdev, LE_LINK, dst, - l2cap_pi(sk)->sec_level, auth_type); + chan->sec_level, auth_type); else hcon = hci_connect(hdev, ACL_LINK, dst, - l2cap_pi(sk)->sec_level, auth_type); + chan->sec_level, auth_type); if (IS_ERR(hcon)) { err = PTR_ERR(hcon); @@ -900,7 +902,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan) if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM) { l2cap_sock_clear_timer(sk); - if (l2cap_check_security(sk)) + if (l2cap_check_security(chan)) sk->sk_state = BT_CONNECTED; } else l2cap_do_start(chan); @@ -1002,15 +1004,15 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan) del_timer(&chan->retrans_timer); } -void l2cap_do_send(struct sock *sk, struct sk_buff *skb) +void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) { - struct l2cap_pinfo *pi = l2cap_pi(sk); - struct hci_conn *hcon = pi->conn->hcon; + struct sock *sk = chan->sk; + struct hci_conn *hcon = l2cap_pi(sk)->conn->hcon; u16 flags; - BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len); + BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len); - if (!pi->flushable && lmp_no_flush_capable(hcon->hdev)) + if (!chan->flushable && lmp_no_flush_capable(hcon->hdev)) flags = ACL_START_NO_FLUSH; else flags = ACL_START; @@ -1035,7 +1037,7 @@ void l2cap_streaming_send(struct l2cap_chan *chan) put_unaligned_le16(fcs, skb->data + skb->len - 2); } - l2cap_do_send(sk, skb); + l2cap_do_send(chan, skb); chan->next_tx_seq = (chan->next_tx_seq + 1) % 64; } @@ -1087,7 +1089,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); } - l2cap_do_send(sk, tx_skb); + l2cap_do_send(chan, tx_skb); } int l2cap_ertm_send(struct l2cap_chan *chan) @@ -1130,7 +1132,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan) put_unaligned_le16(fcs, skb->data + tx_skb->len - 2); } - l2cap_do_send(sk, tx_skb); + l2cap_do_send(chan, tx_skb); __mod_retrans_timer(); @@ -2100,7 +2102,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd chan->ident = cmd->ident; if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { - if (l2cap_check_security(sk)) { + if (l2cap_check_security(chan)) { if (bt_sk(sk)->defer_setup) { sk->sk_state = BT_CONNECT2; result = L2CAP_CR_PEND; @@ -3805,17 +3807,19 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) /* Find listening sockets and check their link_mode */ read_lock(&l2cap_sk_list.lock); sk_for_each(sk, node, &l2cap_sk_list.head) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + if (sk->sk_state != BT_LISTEN) continue; if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { lm1 |= HCI_LM_ACCEPT; - if (l2cap_pi(sk)->role_switch) + if (chan->role_switch) lm1 |= HCI_LM_MASTER; exact++; } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { lm2 |= HCI_LM_ACCEPT; - if (l2cap_pi(sk)->role_switch) + if (chan->role_switch) lm2 |= HCI_LM_MASTER; } } @@ -3867,19 +3871,21 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) return 0; } -static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt) +static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) { + struct sock *sk = chan->sk; + if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM) return; if (encrypt == 0x00) { - if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) { + if (chan->sec_level == BT_SECURITY_MEDIUM) { l2cap_sock_clear_timer(sk); l2cap_sock_set_timer(sk, HZ * 5); - } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH) + } else if (chan->sec_level == BT_SECURITY_HIGH) __l2cap_sock_close(sk, ECONNREFUSED); } else { - if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) + if (chan->sec_level == BT_SECURITY_MEDIUM) l2cap_sock_clear_timer(sk); } } @@ -3908,7 +3914,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) if (!status && (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)) { - l2cap_check_encryption(sk, encrypt); + l2cap_check_encryption(chan, encrypt); bh_unlock_sock(sk); continue; } @@ -4083,7 +4089,7 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) batostr(&bt_sk(sk)->dst), sk->sk_state, __le16_to_cpu(pi->psm), pi->scid, pi->dcid, - pi->imtu, pi->omtu, pi->sec_level, + pi->imtu, pi->omtu, pi->chan->sec_level, pi->mode); } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 50437c665d1e..612955679b34 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -51,7 +51,7 @@ static void l2cap_sock_timeout(unsigned long arg) if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) reason = ECONNREFUSED; else if (sk->sk_state == BT_CONNECT && - l2cap_pi(sk)->sec_level != BT_SECURITY_SDP) + l2cap_pi(sk)->chan->sec_level != BT_SECURITY_SDP) reason = ECONNREFUSED; else reason = ETIMEDOUT; @@ -91,6 +91,7 @@ found: static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct sockaddr_l2 la; int len, err = 0; @@ -142,7 +143,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) if (__le16_to_cpu(la.l2_psm) == 0x0001 || __le16_to_cpu(la.l2_psm) == 0x0003) - l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; + chan->sec_level = BT_SECURITY_SDP; } if (la.l2_cid) @@ -382,6 +383,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct l2cap_options opts; struct l2cap_conninfo cinfo; int len, err = 0; @@ -412,7 +414,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us break; case L2CAP_LM: - switch (l2cap_pi(sk)->sec_level) { + switch (chan->sec_level) { case BT_SECURITY_LOW: opt = L2CAP_LM_AUTH; break; @@ -428,10 +430,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us break; } - if (l2cap_pi(sk)->role_switch) + if (chan->role_switch) opt |= L2CAP_LM_MASTER; - if (l2cap_pi(sk)->force_reliable) + if (chan->force_reliable) opt |= L2CAP_LM_RELIABLE; if (put_user(opt, (u32 __user *) optval)) @@ -467,6 +469,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct bt_security sec; int len, err = 0; @@ -491,7 +494,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch break; } - sec.level = l2cap_pi(sk)->sec_level; + sec.level = chan->sec_level; len = min_t(unsigned int, len, sizeof(sec)); if (copy_to_user(optval, (char *) &sec, len)) @@ -511,7 +514,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch break; case BT_FLUSHABLE: - if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval)) + if (put_user(chan->flushable, (u32 __user *) optval)) err = -EFAULT; break; @@ -592,14 +595,14 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us } if (opt & L2CAP_LM_AUTH) - l2cap_pi(sk)->sec_level = BT_SECURITY_LOW; + chan->sec_level = BT_SECURITY_LOW; if (opt & L2CAP_LM_ENCRYPT) - l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM; + chan->sec_level = BT_SECURITY_MEDIUM; if (opt & L2CAP_LM_SECURE) - l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH; + chan->sec_level = BT_SECURITY_HIGH; - l2cap_pi(sk)->role_switch = (opt & L2CAP_LM_MASTER); - l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE); + chan->role_switch = (opt & L2CAP_LM_MASTER); + chan->force_reliable = (opt & L2CAP_LM_RELIABLE); break; default: @@ -614,6 +617,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct bt_security sec; int len, err = 0; u32 opt; @@ -650,7 +654,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch break; } - l2cap_pi(sk)->sec_level = sec.level; + chan->sec_level = sec.level; break; case BT_DEFER_SETUP: @@ -688,7 +692,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch } } - l2cap_pi(sk)->flushable = opt; + chan->flushable = opt; break; default: @@ -730,7 +734,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms if (IS_ERR(skb)) { err = PTR_ERR(skb); } else { - l2cap_do_send(sk, skb); + l2cap_do_send(pi->chan, skb); err = len; } goto done; @@ -751,7 +755,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms goto done; } - l2cap_do_send(sk, skb); + l2cap_do_send(pi->chan, skb); err = len; break; @@ -997,10 +1001,10 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->fcs = l2cap_pi(parent)->fcs; pi->max_tx = l2cap_pi(parent)->max_tx; pi->tx_win = l2cap_pi(parent)->tx_win; - pi->sec_level = l2cap_pi(parent)->sec_level; - pi->role_switch = l2cap_pi(parent)->role_switch; - pi->force_reliable = l2cap_pi(parent)->force_reliable; - pi->flushable = l2cap_pi(parent)->flushable; + chan->sec_level = pchan->sec_level; + chan->role_switch = pchan->role_switch; + chan->force_reliable = pchan->force_reliable; + chan->flushable = pchan->flushable; } else { pi->imtu = L2CAP_DEFAULT_MTU; pi->omtu = 0; @@ -1013,10 +1017,10 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->max_tx = L2CAP_DEFAULT_MAX_TX; pi->fcs = L2CAP_FCS_CRC16; pi->tx_win = L2CAP_DEFAULT_TX_WINDOW; - pi->sec_level = BT_SECURITY_LOW; - pi->role_switch = 0; - pi->force_reliable = 0; - pi->flushable = BT_FLUSHABLE_OFF; + chan->sec_level = BT_SECURITY_LOW; + chan->role_switch = 0; + chan->force_reliable = 0; + chan->flushable = BT_FLUSHABLE_OFF; } /* Default config options */ -- cgit v1.2.3-58-ga151 From 47d1ec6161da2c7b9dbc56a5200fa26b17d5fdc1 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 13 Apr 2011 15:57:03 -0300 Subject: Bluetooth: Move more vars to struct l2cap_chan In this commit all ERTM and Streaming Mode specific vars. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 18 ++++---- net/bluetooth/l2cap_core.c | 100 +++++++++++++++++++++--------------------- net/bluetooth/l2cap_sock.c | 33 +++++++------- net/bluetooth/rfcomm/core.c | 2 +- 4 files changed, 77 insertions(+), 76 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 684deee6ec52..02db90210f8d 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -297,6 +297,14 @@ struct l2cap_chan { __u8 num_conf_req; __u8 num_conf_rsp; + __u8 fcs; + + __u8 tx_win; + __u8 max_tx; + __u16 retrans_timeout; + __u16 monitor_timeout; + __u16 mps; + __u8 conf_state; __u16 conn_state; @@ -376,14 +384,6 @@ struct l2cap_pinfo { __u16 flush_to; __u8 mode; - __u8 fcs; - - __u8 tx_win; - __u8 max_tx; - __u16 retrans_timeout; - __u16 monitor_timeout; - __u16 mps; - __le16 sport; struct l2cap_conn *conn; @@ -452,7 +452,7 @@ int __l2cap_wait_ack(struct sock *sk); struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len); struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len); -struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen); +struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen); int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb); void l2cap_streaming_send(struct l2cap_chan *chan); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 0fc6bbe85d41..cb3c4ed47ae2 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -359,7 +359,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) if (sk->sk_state != BT_CONNECTED) return; - if (pi->fcs == L2CAP_FCS_CRC16) + if (chan->fcs == L2CAP_FCS_CRC16) hlen += 2; BT_DBG("chan %p, control 0x%2.2x", chan, control); @@ -386,7 +386,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) lh->cid = cpu_to_le16(pi->dcid); put_unaligned_le16(control, skb_put(skb, 2)); - if (pi->fcs == L2CAP_FCS_CRC16) { + if (chan->fcs == L2CAP_FCS_CRC16) { u16 fcs = crc16(0, (u8 *)lh, count - 2); put_unaligned_le16(fcs, skb_put(skb, 2)); } @@ -1022,9 +1022,7 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) void l2cap_streaming_send(struct l2cap_chan *chan) { - struct sock *sk = chan->sk; struct sk_buff *skb; - struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; while ((skb = skb_dequeue(&chan->tx_q))) { @@ -1032,7 +1030,7 @@ void l2cap_streaming_send(struct l2cap_chan *chan) control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE); - if (pi->fcs == L2CAP_FCS_CRC16) { + if (chan->fcs == L2CAP_FCS_CRC16) { fcs = crc16(0, (u8 *)skb->data, skb->len - 2); put_unaligned_le16(fcs, skb->data + skb->len - 2); } @@ -1084,7 +1082,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); - if (pi->fcs == L2CAP_FCS_CRC16) { + if (chan->fcs == L2CAP_FCS_CRC16) { fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); } @@ -1127,7 +1125,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan) put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); - if (pi->fcs == L2CAP_FCS_CRC16) { + if (chan->fcs == L2CAP_FCS_CRC16) { fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2); put_unaligned_le16(fcs, skb->data + tx_skb->len - 2); } @@ -1290,8 +1288,9 @@ struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size return skb; } -struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen) +struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen) { + struct sock *sk = chan->sk; struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct sk_buff *skb; int err, count, hlen = L2CAP_HDR_SIZE + 2; @@ -1305,7 +1304,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz if (sdulen) hlen += 2; - if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) + if (chan->fcs == L2CAP_FCS_CRC16) hlen += 2; count = min_t(unsigned int, (conn->mtu - hlen), len); @@ -1328,7 +1327,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz return ERR_PTR(err); } - if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) + if (chan->fcs == L2CAP_FCS_CRC16) put_unaligned_le16(0, skb_put(skb, 2)); bt_cb(skb)->retries = 0; @@ -1337,7 +1336,6 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) { - struct sock *sk = chan->sk; struct sk_buff *skb; struct sk_buff_head sar_queue; u16 control; @@ -1345,7 +1343,7 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le skb_queue_head_init(&sar_queue); control = L2CAP_SDU_START; - skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len); + skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -1364,7 +1362,7 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le buflen = len; } - skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0); + skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0); if (IS_ERR(skb)) { skb_queue_purge(&sar_queue); return PTR_ERR(skb); @@ -1654,8 +1652,8 @@ done: case L2CAP_MODE_ERTM: rfc.mode = L2CAP_MODE_ERTM; - rfc.txwin_size = pi->tx_win; - rfc.max_transmit = pi->max_tx; + rfc.txwin_size = chan->tx_win; + rfc.max_transmit = chan->max_tx; rfc.retrans_timeout = 0; rfc.monitor_timeout = 0; rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); @@ -1668,10 +1666,10 @@ done: if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS)) break; - if (pi->fcs == L2CAP_FCS_NONE || + if (chan->fcs == L2CAP_FCS_NONE || chan->conf_state & L2CAP_CONF_NO_FCS_RECV) { - pi->fcs = L2CAP_FCS_NONE; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs); + chan->fcs = L2CAP_FCS_NONE; + l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); } break; @@ -1691,10 +1689,10 @@ done: if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS)) break; - if (pi->fcs == L2CAP_FCS_NONE || + if (chan->fcs == L2CAP_FCS_NONE || chan->conf_state & L2CAP_CONF_NO_FCS_RECV) { - pi->fcs = L2CAP_FCS_NONE; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs); + chan->fcs = L2CAP_FCS_NONE; + l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); } break; } @@ -1804,7 +1802,7 @@ done: switch (rfc.mode) { case L2CAP_MODE_BASIC: - pi->fcs = L2CAP_FCS_NONE; + chan->fcs = L2CAP_FCS_NONE; chan->conf_state |= L2CAP_CONF_MODE_DONE; break; @@ -1898,7 +1896,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi rfc.mode != pi->mode) return -ECONNREFUSED; - pi->fcs = 0; + chan->fcs = 0; l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); @@ -1914,12 +1912,12 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi if (*result == L2CAP_CONF_SUCCESS) { switch (rfc.mode) { case L2CAP_MODE_ERTM: - pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); - pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); - pi->mps = le16_to_cpu(rfc.max_pdu_size); + chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); + chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); + chan->mps = le16_to_cpu(rfc.max_pdu_size); break; case L2CAP_MODE_STREAMING: - pi->mps = le16_to_cpu(rfc.max_pdu_size); + chan->mps = le16_to_cpu(rfc.max_pdu_size); } } @@ -1968,14 +1966,14 @@ void __l2cap_connect_rsp_defer(struct sock *sk) chan->num_conf_req++; } -static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len) +static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); int type, olen; unsigned long val; struct l2cap_conf_rfc rfc; - BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len); + BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING)) return; @@ -1994,12 +1992,12 @@ static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len) done: switch (rfc.mode) { case L2CAP_MODE_ERTM: - pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); - pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); - pi->mps = le16_to_cpu(rfc.max_pdu_size); + chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); + chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); + chan->mps = le16_to_cpu(rfc.max_pdu_size); break; case L2CAP_MODE_STREAMING: - pi->mps = le16_to_cpu(rfc.max_pdu_size); + chan->mps = le16_to_cpu(rfc.max_pdu_size); } } @@ -2227,15 +2225,17 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd return 0; } -static inline void set_default_fcs(struct l2cap_pinfo *pi) +static inline void set_default_fcs(struct l2cap_chan *chan) { + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); + /* FCS is enabled only in ERTM or streaming mode, if one or both * sides request it. */ if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING) - pi->fcs = L2CAP_FCS_NONE; + chan->fcs = L2CAP_FCS_NONE; else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV)) - pi->fcs = L2CAP_FCS_CRC16; + chan->fcs = L2CAP_FCS_CRC16; } static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) @@ -2305,7 +2305,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr goto unlock; if (chan->conf_state & L2CAP_CONF_INPUT_DONE) { - set_default_fcs(l2cap_pi(sk)); + set_default_fcs(chan); sk->sk_state = BT_CONNECTED; @@ -2355,7 +2355,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr switch (result) { case L2CAP_CONF_SUCCESS: - l2cap_conf_rfc_get(sk, rsp->data, len); + l2cap_conf_rfc_get(chan, rsp->data, len); break; case L2CAP_CONF_UNACCEPT: @@ -2397,7 +2397,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr chan->conf_state |= L2CAP_CONF_INPUT_DONE; if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) { - set_default_fcs(l2cap_pi(sk)); + set_default_fcs(chan); sk->sk_state = BT_CONNECTED; chan->next_tx_seq = 0; @@ -2769,12 +2769,12 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, kfree_skb(skb); } -static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb) +static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) { u16 our_fcs, rcv_fcs; int hdr_size = L2CAP_HDR_SIZE + 2; - if (pi->fcs == L2CAP_FCS_CRC16) { + if (chan->fcs == L2CAP_FCS_CRC16) { skb_trim(skb, skb->len - 2); rcv_fcs = get_unaligned_le16(skb->data + skb->len); our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); @@ -3241,7 +3241,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont u8 req_seq = __get_reqseq(rx_control); u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; int tx_seq_offset, expected_tx_seq_offset; - int num_to_ack = (pi->tx_win/6) + 1; + int num_to_ack = (chan->tx_win/6) + 1; int err = 0; BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len, @@ -3266,7 +3266,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont tx_seq_offset += 64; /* invalid tx_seq */ - if (tx_seq_offset >= pi->tx_win) { + if (tx_seq_offset >= chan->tx_win) { l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } @@ -3548,16 +3548,16 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) * Receiver will miss it and start proper recovery * procedures and ask retransmission. */ - if (l2cap_check_fcs(pi, skb)) + if (l2cap_check_fcs(chan, skb)) goto drop; if (__is_sar_start(control) && __is_iframe(control)) len -= 2; - if (pi->fcs == L2CAP_FCS_CRC16) + if (chan->fcs == L2CAP_FCS_CRC16) len -= 2; - if (len > pi->mps) { + if (len > chan->mps) { l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } @@ -3654,16 +3654,16 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk skb_pull(skb, 2); len = skb->len; - if (l2cap_check_fcs(pi, skb)) + if (l2cap_check_fcs(chan, skb)) goto drop; if (__is_sar_start(control)) len -= 2; - if (pi->fcs == L2CAP_FCS_CRC16) + if (chan->fcs == L2CAP_FCS_CRC16) len -= 2; - if (len > pi->mps || len < 0 || __is_sframe(control)) + if (len > chan->mps || len < 0 || __is_sframe(control)) goto drop; tx_seq = __get_txseq(control); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 612955679b34..4ba15b3b2e6a 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -403,9 +403,9 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us opts.omtu = l2cap_pi(sk)->omtu; opts.flush_to = l2cap_pi(sk)->flush_to; opts.mode = l2cap_pi(sk)->mode; - opts.fcs = l2cap_pi(sk)->fcs; - opts.max_tx = l2cap_pi(sk)->max_tx; - opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; + opts.fcs = chan->fcs; + opts.max_tx = chan->max_tx; + opts.txwin_size = (__u16)chan->tx_win; len = min_t(unsigned int, len, sizeof(opts)); if (copy_to_user(optval, (char *) &opts, len)) @@ -551,9 +551,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us opts.omtu = l2cap_pi(sk)->omtu; opts.flush_to = l2cap_pi(sk)->flush_to; opts.mode = l2cap_pi(sk)->mode; - opts.fcs = l2cap_pi(sk)->fcs; - opts.max_tx = l2cap_pi(sk)->max_tx; - opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; + opts.fcs = chan->fcs; + opts.max_tx = chan->max_tx; + opts.txwin_size = (__u16)chan->tx_win; len = min_t(unsigned int, sizeof(opts), optlen); if (copy_from_user((char *) &opts, optval, len)) { @@ -583,9 +583,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us l2cap_pi(sk)->imtu = opts.imtu; l2cap_pi(sk)->omtu = opts.omtu; - l2cap_pi(sk)->fcs = opts.fcs; - l2cap_pi(sk)->max_tx = opts.max_tx; - l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size; + chan->fcs = opts.fcs; + chan->max_tx = opts.max_tx; + chan->tx_win = (__u8)opts.txwin_size; break; case L2CAP_LM: @@ -764,7 +764,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms /* Entire SDU fits into one PDU */ if (len <= pi->chan->remote_mps) { control = L2CAP_SDU_UNSEGMENTED; - skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0); + skb = l2cap_create_iframe_pdu(pi->chan, msg, len, + control, 0); if (IS_ERR(skb)) { err = PTR_ERR(skb); goto done; @@ -998,9 +999,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->omtu = l2cap_pi(parent)->omtu; chan->conf_state = pchan->conf_state; pi->mode = l2cap_pi(parent)->mode; - pi->fcs = l2cap_pi(parent)->fcs; - pi->max_tx = l2cap_pi(parent)->max_tx; - pi->tx_win = l2cap_pi(parent)->tx_win; + chan->fcs = pchan->fcs; + chan->max_tx = pchan->max_tx; + chan->tx_win = pchan->tx_win; chan->sec_level = pchan->sec_level; chan->role_switch = pchan->role_switch; chan->force_reliable = pchan->force_reliable; @@ -1014,9 +1015,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) } else { pi->mode = L2CAP_MODE_BASIC; } - pi->max_tx = L2CAP_DEFAULT_MAX_TX; - pi->fcs = L2CAP_FCS_CRC16; - pi->tx_win = L2CAP_DEFAULT_TX_WINDOW; + chan->max_tx = L2CAP_DEFAULT_MAX_TX; + chan->fcs = L2CAP_FCS_CRC16; + chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; chan->sec_level = BT_SECURITY_LOW; chan->role_switch = 0; chan->force_reliable = 0; diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index c9973932456f..4f728a4f7177 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -711,7 +711,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, sk = sock->sk; lock_sock(sk); l2cap_pi(sk)->imtu = l2cap_mtu; - l2cap_pi(sk)->sec_level = sec_level; + l2cap_pi(sk)->chan->sec_level = sec_level; if (l2cap_ertm) l2cap_pi(sk)->mode = L2CAP_MODE_ERTM; release_sock(sk); -- cgit v1.2.3-58-ga151 From 0c1bc5c626e9783034264ccca4b262b3acc628f1 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 13 Apr 2011 17:20:49 -0300 Subject: Bluetooth: Move more channel info to struct l2cap_chan In this commit, omtu, imtu, flush_to, mode and sport. It also remove the pi var from l2cap_sock_sendmsg(). Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 14 +++--- net/bluetooth/cmtp/core.c | 3 +- net/bluetooth/hidp/core.c | 6 ++- net/bluetooth/l2cap_core.c | 97 ++++++++++++++++++++-------------------- net/bluetooth/l2cap_sock.c | 100 +++++++++++++++++++++++------------------- net/bluetooth/rfcomm/core.c | 11 ++--- 6 files changed, 121 insertions(+), 110 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 02db90210f8d..7522835c24ee 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -285,6 +285,13 @@ struct srej_list { struct l2cap_chan { struct sock *sk; + __u16 imtu; + __u16 omtu; + __u16 flush_to; + __u8 mode; + + __le16 sport; + __u8 sec_level; __u8 role_switch; __u8 force_reliable; @@ -379,13 +386,6 @@ struct l2cap_pinfo { __u16 dcid; __u16 scid; - __u16 imtu; - __u16 omtu; - __u16 flush_to; - __u8 mode; - - __le16 sport; - struct l2cap_conn *conn; struct l2cap_chan *chan; }; diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index cce99b0919f5..c5b11af908be 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -346,7 +346,8 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) bacpy(&session->bdaddr, &bt_sk(sock->sk)->dst); - session->mtu = min_t(uint, l2cap_pi(sock->sk)->omtu, l2cap_pi(sock->sk)->imtu); + session->mtu = min_t(uint, l2cap_pi(sock->sk)->chan->omtu, + l2cap_pi(sock->sk)->chan->imtu); BT_DBG("mtu %d", session->mtu); diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index ae6ebc6c3481..c405a954a603 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -979,8 +979,10 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst); - session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu); - session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu); + session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu, + l2cap_pi(ctrl_sock->sk)->chan->imtu); + session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->chan->omtu, + l2cap_pi(intr_sock->sk)->chan->imtu); BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index cb3c4ed47ae2..7b06375d05a7 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -176,24 +176,24 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) { if (conn->hcon->type == LE_LINK) { /* LE connection */ - l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU; + chan->omtu = L2CAP_LE_DEFAULT_MTU; l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA; l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA; } else { /* Alloc CID for connection-oriented socket */ l2cap_pi(sk)->scid = l2cap_alloc_cid(conn); - l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; + chan->omtu = L2CAP_DEFAULT_MTU; } } else if (sk->sk_type == SOCK_DGRAM) { /* Connectionless socket */ l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS; l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS; - l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; + chan->omtu = L2CAP_DEFAULT_MTU; } else { /* Raw socket can send/recv signalling messages only */ l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING; l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING; - l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; + chan->omtu = L2CAP_DEFAULT_MTU; } sock_hold(sk); @@ -242,7 +242,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) skb_queue_purge(&chan->tx_q); - if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { + if (chan->mode == L2CAP_MODE_ERTM) { struct srej_list *l, *tmp; del_timer(&chan->retrans_timer); @@ -479,7 +479,7 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in sk = chan->sk; - if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { + if (chan->mode == L2CAP_MODE_ERTM) { del_timer(&chan->retrans_timer); del_timer(&chan->monitor_timer); del_timer(&chan->ack_timer); @@ -523,7 +523,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) continue; } - if (!l2cap_mode_supported(l2cap_pi(sk)->mode, + if (!l2cap_mode_supported(chan->mode, conn->feat_mask) && chan->conf_state & L2CAP_CONF_STATE2_DEVICE) { @@ -1609,7 +1609,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) { struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct l2cap_conf_req *req = data; - struct l2cap_conf_rfc rfc = { .mode = pi->mode }; + struct l2cap_conf_rfc rfc = { .mode = chan->mode }; void *ptr = req->data; BT_DBG("chan %p", chan); @@ -1617,7 +1617,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) if (chan->num_conf_req || chan->num_conf_rsp) goto done; - switch (pi->mode) { + switch (chan->mode) { case L2CAP_MODE_STREAMING: case L2CAP_MODE_ERTM: if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE) @@ -1625,15 +1625,15 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) /* fall through */ default: - pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask); + chan->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask); break; } done: - if (pi->imtu != L2CAP_DEFAULT_MTU) - l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu); + if (chan->imtu != L2CAP_DEFAULT_MTU) + l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); - switch (pi->mode) { + switch (chan->mode) { case L2CAP_MODE_BASIC: if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) && !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING)) @@ -1730,7 +1730,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) break; case L2CAP_CONF_FLUSH_TO: - pi->flush_to = val; + chan->flush_to = val; break; case L2CAP_CONF_QOS: @@ -1760,25 +1760,25 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) if (chan->num_conf_rsp || chan->num_conf_req > 1) goto done; - switch (pi->mode) { + switch (chan->mode) { case L2CAP_MODE_STREAMING: case L2CAP_MODE_ERTM: if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) { - pi->mode = l2cap_select_mode(rfc.mode, + chan->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask); break; } - if (pi->mode != rfc.mode) + if (chan->mode != rfc.mode) return -ECONNREFUSED; break; } done: - if (pi->mode != rfc.mode) { + if (chan->mode != rfc.mode) { result = L2CAP_CONF_UNACCEPT; - rfc.mode = pi->mode; + rfc.mode = chan->mode; if (chan->num_conf_rsp == 1) return -ECONNREFUSED; @@ -1795,10 +1795,10 @@ done: if (mtu < L2CAP_DEFAULT_MIN_MTU) result = L2CAP_CONF_UNACCEPT; else { - pi->omtu = mtu; + chan->omtu = mtu; chan->conf_state |= L2CAP_CONF_MTU_DONE; } - l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu); + l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); switch (rfc.mode) { case L2CAP_MODE_BASIC: @@ -1844,7 +1844,7 @@ done: result = L2CAP_CONF_UNACCEPT; memset(&rfc, 0, sizeof(rfc)); - rfc.mode = pi->mode; + rfc.mode = chan->mode; } if (result == L2CAP_CONF_SUCCESS) @@ -1876,16 +1876,16 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi case L2CAP_CONF_MTU: if (val < L2CAP_DEFAULT_MIN_MTU) { *result = L2CAP_CONF_UNACCEPT; - pi->imtu = L2CAP_DEFAULT_MIN_MTU; + chan->imtu = L2CAP_DEFAULT_MIN_MTU; } else - pi->imtu = val; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu); + chan->imtu = val; + l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); break; case L2CAP_CONF_FLUSH_TO: - pi->flush_to = val; + chan->flush_to = val; l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, - 2, pi->flush_to); + 2, chan->flush_to); break; case L2CAP_CONF_RFC: @@ -1893,7 +1893,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi memcpy(&rfc, (void *)val, olen); if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) && - rfc.mode != pi->mode) + rfc.mode != chan->mode) return -ECONNREFUSED; chan->fcs = 0; @@ -1904,10 +1904,10 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi } } - if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode) + if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) return -ECONNREFUSED; - pi->mode = rfc.mode; + chan->mode = rfc.mode; if (*result == L2CAP_CONF_SUCCESS) { switch (rfc.mode) { @@ -1968,14 +1968,13 @@ void __l2cap_connect_rsp_defer(struct sock *sk) static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); int type, olen; unsigned long val; struct l2cap_conf_rfc rfc; BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); - if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING)) + if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) return; while (len >= L2CAP_CONF_OPT_SIZE) { @@ -2232,7 +2231,7 @@ static inline void set_default_fcs(struct l2cap_chan *chan) /* FCS is enabled only in ERTM or streaming mode, if one or both * sides request it. */ - if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING) + if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) chan->fcs = L2CAP_FCS_NONE; else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV)) chan->fcs = L2CAP_FCS_CRC16; @@ -2312,7 +2311,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr chan->next_tx_seq = 0; chan->expected_tx_seq = 0; skb_queue_head_init(&chan->tx_q); - if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) + if (chan->mode == L2CAP_MODE_ERTM) l2cap_ertm_init(chan); l2cap_chan_ready(sk); @@ -2403,7 +2402,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr chan->next_tx_seq = 0; chan->expected_tx_seq = 0; skb_queue_head_init(&chan->tx_q); - if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) + if (chan->mode == L2CAP_MODE_ERTM) l2cap_ertm_init(chan); l2cap_chan_ready(sk); @@ -2876,7 +2875,7 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk chan->sdu_len = get_unaligned_le16(skb->data); - if (chan->sdu_len > pi->imtu) + if (chan->sdu_len > chan->imtu) goto disconnect; chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC); @@ -2919,7 +2918,7 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) { chan->partial_sdu_len += skb->len; - if (chan->partial_sdu_len > pi->imtu) + if (chan->partial_sdu_len > chan->imtu) goto drop; if (chan->partial_sdu_len != chan->sdu_len) @@ -3087,7 +3086,6 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct sk_buff *_skb; int err = -EINVAL; @@ -3118,7 +3116,7 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf chan->sdu_len = get_unaligned_le16(skb->data); skb_pull(skb, 2); - if (chan->sdu_len > pi->imtu) { + if (chan->sdu_len > chan->imtu) { err = -EMSGSIZE; break; } @@ -3159,7 +3157,7 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf chan->conn_state &= ~L2CAP_CONN_SAR_SDU; chan->partial_sdu_len += skb->len; - if (chan->partial_sdu_len > pi->imtu) + if (chan->partial_sdu_len > chan->imtu) goto drop; if (chan->partial_sdu_len == chan->sdu_len) { @@ -3625,14 +3623,14 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk if (sk->sk_state != BT_CONNECTED) goto drop; - switch (pi->mode) { + switch (chan->mode) { case L2CAP_MODE_BASIC: /* If socket recv buffers overflows we drop data here * which is *bad* because L2CAP has to be reliable. * But we don't have any other choice. L2CAP doesn't * provide flow control mechanism. */ - if (pi->imtu < skb->len) + if (chan->imtu < skb->len) goto drop; if (!sock_queue_rcv_skb(sk, skb)) @@ -3678,7 +3676,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk goto done; default: - BT_DBG("chan %p: bad mode 0x%2.2x", chan, pi->mode); + BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); break; } @@ -3707,7 +3705,7 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) goto drop; - if (l2cap_pi(sk)->imtu < skb->len) + if (l2cap_pi(sk)->chan->imtu < skb->len) goto drop; if (!sock_queue_rcv_skb(sk, skb)) @@ -3737,7 +3735,7 @@ static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) goto drop; - if (l2cap_pi(sk)->imtu < skb->len) + if (l2cap_pi(sk)->chan->imtu < skb->len) goto drop; if (!sock_queue_rcv_skb(sk, skb)) @@ -4020,10 +4018,10 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl if (chan && chan->sk) { struct sock *sk = chan->sk; - if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) { + if (chan->imtu < len - L2CAP_HDR_SIZE) { BT_ERR("Frame exceeding recv MTU (len %d, " "MTU %d)", len, - l2cap_pi(sk)->imtu); + chan->imtu); bh_unlock_sock(sk); l2cap_conn_unreliable(conn, ECOMM); goto drop; @@ -4083,14 +4081,15 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) sk_for_each(sk, node, &l2cap_sk_list.head) { struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_chan *chan = pi->chan; seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), sk->sk_state, __le16_to_cpu(pi->psm), pi->scid, pi->dcid, - pi->imtu, pi->omtu, pi->chan->sec_level, - pi->mode); + chan->imtu, chan->omtu, chan->sec_level, + chan->mode); } read_unlock_bh(&l2cap_sk_list.lock); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 4ba15b3b2e6a..eef33b179f02 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -80,9 +80,13 @@ static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) { struct sock *sk; struct hlist_node *node; - sk_for_each(sk, node, &l2cap_sk_list.head) - if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src)) + sk_for_each(sk, node, &l2cap_sk_list.head) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + + if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src)) goto found; + } + sk = NULL; found: return sk; @@ -138,7 +142,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) /* Save source address */ bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); l2cap_pi(sk)->psm = la.l2_psm; - l2cap_pi(sk)->sport = la.l2_psm; + chan->sport = la.l2_psm; sk->sk_state = BT_BOUND; if (__le16_to_cpu(la.l2_psm) == 0x0001 || @@ -159,6 +163,7 @@ done: static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct sockaddr_l2 la; int len, err = 0; @@ -183,7 +188,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al goto done; } - switch (l2cap_pi(sk)->mode) { + switch (chan->mode) { case L2CAP_MODE_BASIC: break; case L2CAP_MODE_ERTM: @@ -245,6 +250,7 @@ done: static int l2cap_sock_listen(struct socket *sock, int backlog) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; int err = 0; BT_DBG("sk %p backlog %d", sk, backlog); @@ -257,7 +263,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) goto done; } - switch (l2cap_pi(sk)->mode) { + switch (chan->mode) { case L2CAP_MODE_BASIC: break; case L2CAP_MODE_ERTM: @@ -281,7 +287,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) for (psm = 0x1001; psm < 0x1100; psm += 2) if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) { l2cap_pi(sk)->psm = cpu_to_le16(psm); - l2cap_pi(sk)->sport = cpu_to_le16(psm); + chan->sport = cpu_to_le16(psm); err = 0; break; } @@ -361,6 +367,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l { struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr; struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; BT_DBG("sock %p, sk %p", sock, sk); @@ -372,7 +379,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst); la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid); } else { - la->l2_psm = l2cap_pi(sk)->sport; + la->l2_psm = chan->sport; bacpy(&la->l2_bdaddr, &bt_sk(sk)->src); la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid); } @@ -399,10 +406,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us switch (optname) { case L2CAP_OPTIONS: memset(&opts, 0, sizeof(opts)); - opts.imtu = l2cap_pi(sk)->imtu; - opts.omtu = l2cap_pi(sk)->omtu; - opts.flush_to = l2cap_pi(sk)->flush_to; - opts.mode = l2cap_pi(sk)->mode; + opts.imtu = chan->imtu; + opts.omtu = chan->omtu; + opts.flush_to = chan->flush_to; + opts.mode = chan->mode; opts.fcs = chan->fcs; opts.max_tx = chan->max_tx; opts.txwin_size = (__u16)chan->tx_win; @@ -547,10 +554,10 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us break; } - opts.imtu = l2cap_pi(sk)->imtu; - opts.omtu = l2cap_pi(sk)->omtu; - opts.flush_to = l2cap_pi(sk)->flush_to; - opts.mode = l2cap_pi(sk)->mode; + opts.imtu = chan->imtu; + opts.omtu = chan->omtu; + opts.flush_to = chan->flush_to; + opts.mode = chan->mode; opts.fcs = chan->fcs; opts.max_tx = chan->max_tx; opts.txwin_size = (__u16)chan->tx_win; @@ -566,8 +573,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us break; } - l2cap_pi(sk)->mode = opts.mode; - switch (l2cap_pi(sk)->mode) { + chan->mode = opts.mode; + switch (chan->mode) { case L2CAP_MODE_BASIC: chan->conf_state &= ~L2CAP_CONF_STATE2_DEVICE; break; @@ -581,8 +588,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us break; } - l2cap_pi(sk)->imtu = opts.imtu; - l2cap_pi(sk)->omtu = opts.omtu; + chan->imtu = opts.imtu; + chan->omtu = opts.omtu; chan->fcs = opts.fcs; chan->max_tx = opts.max_tx; chan->tx_win = (__u8)opts.txwin_size; @@ -707,7 +714,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) { struct sock *sk = sock->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct sk_buff *skb; u16 control; int err; @@ -734,16 +741,16 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms if (IS_ERR(skb)) { err = PTR_ERR(skb); } else { - l2cap_do_send(pi->chan, skb); + l2cap_do_send(chan, skb); err = len; } goto done; } - switch (pi->mode) { + switch (chan->mode) { case L2CAP_MODE_BASIC: /* Check outgoing MTU */ - if (len > pi->omtu) { + if (len > chan->omtu) { err = -EMSGSIZE; goto done; } @@ -755,52 +762,52 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms goto done; } - l2cap_do_send(pi->chan, skb); + l2cap_do_send(chan, skb); err = len; break; case L2CAP_MODE_ERTM: case L2CAP_MODE_STREAMING: /* Entire SDU fits into one PDU */ - if (len <= pi->chan->remote_mps) { + if (len <= chan->remote_mps) { control = L2CAP_SDU_UNSEGMENTED; - skb = l2cap_create_iframe_pdu(pi->chan, msg, len, - control, 0); + skb = l2cap_create_iframe_pdu(chan, msg, len, control, + 0); if (IS_ERR(skb)) { err = PTR_ERR(skb); goto done; } - __skb_queue_tail(&pi->chan->tx_q, skb); + __skb_queue_tail(&chan->tx_q, skb); - if (pi->chan->tx_send_head == NULL) - pi->chan->tx_send_head = skb; + if (chan->tx_send_head == NULL) + chan->tx_send_head = skb; } else { /* Segment SDU into multiples PDUs */ - err = l2cap_sar_segment_sdu(pi->chan, msg, len); + err = l2cap_sar_segment_sdu(chan, msg, len); if (err < 0) goto done; } - if (pi->mode == L2CAP_MODE_STREAMING) { - l2cap_streaming_send(pi->chan); + if (chan->mode == L2CAP_MODE_STREAMING) { + l2cap_streaming_send(chan); err = len; break; } - if ((pi->chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && - (pi->chan->conn_state & L2CAP_CONN_WAIT_F)) { + if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && + (chan->conn_state & L2CAP_CONN_WAIT_F)) { err = len; break; } - err = l2cap_ertm_send(pi->chan); + err = l2cap_ertm_send(chan); if (err >= 0) err = len; break; default: - BT_DBG("bad state %1.1x", pi->mode); + BT_DBG("bad state %1.1x", chan->mode); err = -EBADFD; } @@ -929,6 +936,7 @@ void __l2cap_sock_close(struct sock *sk, int reason) static int l2cap_sock_shutdown(struct socket *sock, int how) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; int err = 0; BT_DBG("sock %p, sk %p", sock, sk); @@ -938,7 +946,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) lock_sock(sk); if (!sk->sk_shutdown) { - if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) + if (chan->mode == L2CAP_MODE_ERTM) err = __l2cap_wait_ack(sk); sk->sk_shutdown = SHUTDOWN_MASK; @@ -995,10 +1003,10 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) sk->sk_type = parent->sk_type; bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup; - pi->imtu = l2cap_pi(parent)->imtu; - pi->omtu = l2cap_pi(parent)->omtu; + chan->imtu = pchan->imtu; + chan->omtu = pchan->omtu; chan->conf_state = pchan->conf_state; - pi->mode = l2cap_pi(parent)->mode; + chan->mode = pchan->mode; chan->fcs = pchan->fcs; chan->max_tx = pchan->max_tx; chan->tx_win = pchan->tx_win; @@ -1007,13 +1015,13 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) chan->force_reliable = pchan->force_reliable; chan->flushable = pchan->flushable; } else { - pi->imtu = L2CAP_DEFAULT_MTU; - pi->omtu = 0; + chan->imtu = L2CAP_DEFAULT_MTU; + chan->omtu = 0; if (!disable_ertm && sk->sk_type == SOCK_STREAM) { - pi->mode = L2CAP_MODE_ERTM; + chan->mode = L2CAP_MODE_ERTM; chan->conf_state |= L2CAP_CONF_STATE2_DEVICE; } else { - pi->mode = L2CAP_MODE_BASIC; + chan->mode = L2CAP_MODE_BASIC; } chan->max_tx = L2CAP_DEFAULT_MAX_TX; chan->fcs = L2CAP_FCS_CRC16; @@ -1025,7 +1033,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) } /* Default config options */ - pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; + chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; } static struct proto l2cap_proto = { diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 4f728a4f7177..fdd8f5ab18c1 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -710,10 +710,10 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, /* Set L2CAP options */ sk = sock->sk; lock_sock(sk); - l2cap_pi(sk)->imtu = l2cap_mtu; + l2cap_pi(sk)->chan->imtu = l2cap_mtu; l2cap_pi(sk)->chan->sec_level = sec_level; if (l2cap_ertm) - l2cap_pi(sk)->mode = L2CAP_MODE_ERTM; + l2cap_pi(sk)->chan->mode = L2CAP_MODE_ERTM; release_sock(sk); s = rfcomm_session_add(sock, BT_BOUND); @@ -1890,7 +1890,8 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s) /* We should adjust MTU on incoming sessions. * L2CAP MTU minus UIH header and FCS. */ - s->mtu = min(l2cap_pi(nsock->sk)->omtu, l2cap_pi(nsock->sk)->imtu) - 5; + s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu, + l2cap_pi(nsock->sk)->chan->imtu) - 5; rfcomm_schedule(); } else @@ -1909,7 +1910,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s) /* We can adjust MTU on outgoing sessions. * L2CAP MTU minus UIH header and FCS. */ - s->mtu = min(l2cap_pi(sk)->omtu, l2cap_pi(sk)->imtu) - 5; + s->mtu = min(l2cap_pi(sk)->chan->omtu, l2cap_pi(sk)->chan->imtu) - 5; rfcomm_send_sabm(s, 0); break; @@ -1992,7 +1993,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) /* Set L2CAP options */ sk = sock->sk; lock_sock(sk); - l2cap_pi(sk)->imtu = l2cap_mtu; + l2cap_pi(sk)->chan->imtu = l2cap_mtu; release_sock(sk); /* Start listening on the socket */ -- cgit v1.2.3-58-ga151 From fe4128e0aabc3c748786c00da21e6eff9d3aeddb Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 13 Apr 2011 19:50:45 -0300 Subject: Bluetooth: Move more vars to struct l2cap_chan In this commit, psm, scid and dcid. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 10 ++-- net/bluetooth/l2cap_core.c | 116 +++++++++++++++++++++--------------------- net/bluetooth/l2cap_sock.c | 26 +++++----- 3 files changed, 77 insertions(+), 75 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 7522835c24ee..fd199cda752c 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -284,6 +284,9 @@ struct srej_list { struct l2cap_chan { struct sock *sk; + __le16 psm; + __u16 dcid; + __u16 scid; __u16 imtu; __u16 omtu; @@ -382,9 +385,6 @@ struct l2cap_conn { struct l2cap_pinfo { struct bt_sock bt; - __le16 psm; - __u16 dcid; - __u16 scid; struct l2cap_conn *conn; struct l2cap_chan *chan; @@ -450,8 +450,8 @@ void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *d void __l2cap_connect_rsp_defer(struct sock *sk); int __l2cap_wait_ack(struct sock *sk); -struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len); -struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len); +struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); +struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen); int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 7b06375d05a7..dd726bdd6e02 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -80,8 +80,7 @@ static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 struct l2cap_chan *c; list_for_each_entry(c, &conn->chan_l, list) { - struct sock *s = c->sk; - if (l2cap_pi(s)->dcid == cid) + if (c->dcid == cid) return c; } return NULL; @@ -93,8 +92,7 @@ static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 struct l2cap_chan *c; list_for_each_entry(c, &conn->chan_l, list) { - struct sock *s = c->sk; - if (l2cap_pi(s)->scid == cid) + if (c->scid == cid) return c; } return NULL; @@ -167,7 +165,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) struct sock *sk = chan->sk; BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, - l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid); + chan->psm, chan->dcid); conn->disc_reason = 0x13; @@ -177,22 +175,22 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) if (conn->hcon->type == LE_LINK) { /* LE connection */ chan->omtu = L2CAP_LE_DEFAULT_MTU; - l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA; - l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA; + chan->scid = L2CAP_CID_LE_DATA; + chan->dcid = L2CAP_CID_LE_DATA; } else { /* Alloc CID for connection-oriented socket */ - l2cap_pi(sk)->scid = l2cap_alloc_cid(conn); + chan->scid = l2cap_alloc_cid(conn); chan->omtu = L2CAP_DEFAULT_MTU; } } else if (sk->sk_type == SOCK_DGRAM) { /* Connectionless socket */ - l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS; - l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS; + chan->scid = L2CAP_CID_CONN_LESS; + chan->dcid = L2CAP_CID_CONN_LESS; chan->omtu = L2CAP_DEFAULT_MTU; } else { /* Raw socket can send/recv signalling messages only */ - l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING; - l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING; + chan->scid = L2CAP_CID_SIGNALING; + chan->dcid = L2CAP_CID_SIGNALING; chan->omtu = L2CAP_DEFAULT_MTU; } @@ -275,7 +273,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) default: return HCI_AT_NO_BONDING; } - } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) { + } else if (chan->psm == cpu_to_le16(0x0001)) { if (chan->sec_level == BT_SECURITY_LOW) chan->sec_level = BT_SECURITY_SDP; @@ -383,7 +381,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); - lh->cid = cpu_to_le16(pi->dcid); + lh->cid = cpu_to_le16(chan->dcid); put_unaligned_le16(control, skb_put(skb, 2)); if (chan->fcs == L2CAP_FCS_CRC16) { @@ -429,8 +427,8 @@ static void l2cap_do_start(struct l2cap_chan *chan) if (l2cap_check_security(chan) && __l2cap_no_conn_pending(chan)) { struct l2cap_conn_req req; - req.scid = cpu_to_le16(l2cap_pi(sk)->scid); - req.psm = l2cap_pi(sk)->psm; + req.scid = cpu_to_le16(chan->scid); + req.psm = chan->psm; chan->ident = l2cap_get_ident(conn); chan->conf_state |= L2CAP_CONF_CONNECT_PEND; @@ -485,8 +483,8 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in del_timer(&chan->ack_timer); } - req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid); - req.scid = cpu_to_le16(l2cap_pi(sk)->scid); + req.dcid = cpu_to_le16(chan->dcid); + req.scid = cpu_to_le16(chan->scid); l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, sizeof(req), &req); @@ -536,8 +534,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) continue; } - req.scid = cpu_to_le16(l2cap_pi(sk)->scid); - req.psm = l2cap_pi(sk)->psm; + req.scid = cpu_to_le16(chan->scid); + req.psm = chan->psm; chan->ident = l2cap_get_ident(conn); chan->conf_state |= L2CAP_CONF_CONNECT_PEND; @@ -548,8 +546,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) } else if (sk->sk_state == BT_CONNECT2) { struct l2cap_conn_rsp rsp; char buf[128]; - rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); - rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); + rsp.scid = cpu_to_le16(chan->dcid); + rsp.dcid = cpu_to_le16(chan->scid); if (l2cap_check_security(chan)) { if (bt_sk(sk)->defer_setup) { @@ -600,10 +598,12 @@ static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src) read_lock(&l2cap_sk_list.lock); sk_for_each(sk, node, &l2cap_sk_list.head) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + if (state && sk->sk_state != state) continue; - if (l2cap_pi(sk)->scid == cid) { + if (chan->scid == cid) { /* Exact match. */ if (!bacmp(&bt_sk(sk)->src, src)) break; @@ -830,10 +830,12 @@ static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) read_lock(&l2cap_sk_list.lock); sk_for_each(sk, node, &l2cap_sk_list.head) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + if (state && sk->sk_state != state) continue; - if (l2cap_pi(sk)->psm == psm) { + if (chan->psm == psm) { /* Exact match. */ if (!bacmp(&bt_sk(sk)->src, src)) break; @@ -861,7 +863,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan) int err; BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), - l2cap_pi(sk)->psm); + chan->psm); hdev = hci_get_route(dst, src); if (!hdev) @@ -871,7 +873,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan) auth_type = l2cap_get_auth_type(chan); - if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA) + if (chan->dcid == L2CAP_CID_LE_DATA) hcon = hci_connect(hdev, LE_LINK, dst, chan->sec_level, auth_type); else @@ -1231,8 +1233,9 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in return sent; } -struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len) +struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) { + struct sock *sk = chan->sk; struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct sk_buff *skb; int err, count, hlen = L2CAP_HDR_SIZE + 2; @@ -1248,9 +1251,9 @@ struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, s /* Create L2CAP header */ lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); - lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid); + lh->cid = cpu_to_le16(chan->dcid); lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); - put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2)); + put_unaligned_le16(chan->psm, skb_put(skb, 2)); err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb); if (unlikely(err < 0)) { @@ -1260,8 +1263,9 @@ struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, s return skb; } -struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len) +struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) { + struct sock *sk = chan->sk; struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct sk_buff *skb; int err, count, hlen = L2CAP_HDR_SIZE; @@ -1277,7 +1281,7 @@ struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size /* Create L2CAP header */ lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); - lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid); + lh->cid = cpu_to_le16(chan->dcid); lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb); @@ -1315,7 +1319,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr * /* Create L2CAP header */ lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); - lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid); + lh->cid = cpu_to_le16(chan->dcid); lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); put_unaligned_le16(control, skb_put(skb, 2)); if (sdulen) @@ -1697,7 +1701,7 @@ done: break; } - req->dcid = cpu_to_le16(pi->dcid); + req->dcid = cpu_to_le16(chan->dcid); req->flags = cpu_to_le16(0); return ptr - data; @@ -1850,7 +1854,7 @@ done: if (result == L2CAP_CONF_SUCCESS) chan->conf_state |= L2CAP_CONF_OUTPUT_DONE; } - rsp->scid = cpu_to_le16(pi->dcid); + rsp->scid = cpu_to_le16(chan->dcid); rsp->result = cpu_to_le16(result); rsp->flags = cpu_to_le16(0x0000); @@ -1859,15 +1863,13 @@ done: static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) { - struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); struct l2cap_conf_req *req = data; void *ptr = req->data; int type, olen; unsigned long val; struct l2cap_conf_rfc rfc; - BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data); + BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); while (len >= L2CAP_CONF_OPT_SIZE) { len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); @@ -1921,20 +1923,20 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi } } - req->dcid = cpu_to_le16(pi->dcid); + req->dcid = cpu_to_le16(chan->dcid); req->flags = cpu_to_le16(0x0000); return ptr - data; } -static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags) +static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) { struct l2cap_conf_rsp *rsp = data; void *ptr = rsp->data; - BT_DBG("sk %p", sk); + BT_DBG("chan %p", chan); - rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid); + rsp->scid = cpu_to_le16(chan->dcid); rsp->result = cpu_to_le16(result); rsp->flags = cpu_to_le16(flags); @@ -1950,8 +1952,8 @@ void __l2cap_connect_rsp_defer(struct sock *sk) sk->sk_state = BT_CONFIG; - rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); - rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); + rsp.scid = cpu_to_le16(chan->dcid); + rsp.dcid = cpu_to_le16(chan->scid); rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); l2cap_send_cmd(conn, chan->ident, @@ -2085,14 +2087,14 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd l2cap_sock_init(sk, parent); bacpy(&bt_sk(sk)->src, conn->src); bacpy(&bt_sk(sk)->dst, conn->dst); - l2cap_pi(sk)->psm = psm; - l2cap_pi(sk)->dcid = scid; + chan->psm = psm; + chan->dcid = scid; bt_accept_enqueue(parent, sk); __l2cap_chan_add(conn, chan); - dcid = l2cap_pi(sk)->scid; + dcid = chan->scid; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); @@ -2190,7 +2192,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd case L2CAP_CR_SUCCESS: sk->sk_state = BT_CONFIG; chan->ident = 0; - l2cap_pi(sk)->dcid = dcid; + chan->dcid = dcid; chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND; if (chan->conf_state & L2CAP_CONF_REQ_SENT) @@ -2270,7 +2272,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr len = cmd_len - sizeof(*req); if (chan->conf_len + len > sizeof(chan->conf_req)) { l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, - l2cap_build_conf_rsp(sk, rsp, + l2cap_build_conf_rsp(chan, rsp, L2CAP_CONF_REJECT, flags), rsp); goto unlock; } @@ -2282,7 +2284,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr if (flags & 0x0001) { /* Incomplete config. Send empty response. */ l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, - l2cap_build_conf_rsp(sk, rsp, + l2cap_build_conf_rsp(chan, rsp, L2CAP_CONF_SUCCESS, 0x0001), rsp); goto unlock; } @@ -2432,8 +2434,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd sk = chan->sk; - rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); - rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); + rsp.dcid = cpu_to_le16(chan->scid); + rsp.scid = cpu_to_le16(chan->dcid); l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); sk->sk_shutdown = SHUTDOWN_MASK; @@ -3920,8 +3922,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) if (sk->sk_state == BT_CONNECT) { if (!status) { struct l2cap_conn_req req; - req.scid = cpu_to_le16(l2cap_pi(sk)->scid); - req.psm = l2cap_pi(sk)->psm; + req.scid = cpu_to_le16(chan->scid); + req.psm = chan->psm; chan->ident = l2cap_get_ident(conn); chan->conf_state |= L2CAP_CONF_CONNECT_PEND; @@ -3945,8 +3947,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) result = L2CAP_CR_SEC_BLOCK; } - rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); - rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); + rsp.scid = cpu_to_le16(chan->dcid); + rsp.dcid = cpu_to_le16(chan->scid); rsp.result = cpu_to_le16(result); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, @@ -4086,8 +4088,8 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), - sk->sk_state, __le16_to_cpu(pi->psm), - pi->scid, pi->dcid, + sk->sk_state, __le16_to_cpu(chan->psm), + chan->scid, chan->dcid, chan->imtu, chan->omtu, chan->sec_level, chan->mode); } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index eef33b179f02..f5a27737c151 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -141,7 +141,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) } else { /* Save source address */ bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); - l2cap_pi(sk)->psm = la.l2_psm; + chan->psm = la.l2_psm; chan->sport = la.l2_psm; sk->sk_state = BT_BOUND; @@ -151,7 +151,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) } if (la.l2_cid) - l2cap_pi(sk)->scid = la.l2_cid; + chan->scid = la.l2_cid; write_unlock_bh(&l2cap_sk_list.lock); @@ -232,8 +232,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al /* Set destination address and psm */ bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr); - l2cap_pi(sk)->psm = la.l2_psm; - l2cap_pi(sk)->dcid = la.l2_cid; + chan->psm = la.l2_psm; + chan->dcid = la.l2_cid; err = l2cap_chan_connect(l2cap_pi(sk)->chan); if (err) @@ -276,7 +276,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) goto done; } - if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->scid) { + if (!chan->psm && !chan->scid) { bdaddr_t *src = &bt_sk(sk)->src; u16 psm; @@ -286,7 +286,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) for (psm = 0x1001; psm < 0x1100; psm += 2) if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) { - l2cap_pi(sk)->psm = cpu_to_le16(psm); + chan->psm = cpu_to_le16(psm); chan->sport = cpu_to_le16(psm); err = 0; break; @@ -375,13 +375,13 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l *len = sizeof(struct sockaddr_l2); if (peer) { - la->l2_psm = l2cap_pi(sk)->psm; + la->l2_psm = chan->psm; bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst); - la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid); + la->l2_cid = cpu_to_le16(chan->dcid); } else { la->l2_psm = chan->sport; bacpy(&la->l2_bdaddr, &bt_sk(sk)->src); - la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid); + la->l2_cid = cpu_to_le16(chan->scid); } return 0; @@ -737,7 +737,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms /* Connectionless channel */ if (sk->sk_type == SOCK_DGRAM) { - skb = l2cap_create_connless_pdu(sk, msg, len); + skb = l2cap_create_connless_pdu(chan, msg, len); if (IS_ERR(skb)) { err = PTR_ERR(skb); } else { @@ -756,7 +756,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms } /* Create a basic PDU */ - skb = l2cap_create_basic_pdu(sk, msg, len); + skb = l2cap_create_basic_pdu(chan, msg, len); if (IS_ERR(skb)) { err = PTR_ERR(skb); goto done; @@ -911,8 +911,8 @@ void __l2cap_sock_close(struct sock *sk, int reason) else result = L2CAP_CR_BAD_PSM; - rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); - rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); + rsp.scid = cpu_to_le16(chan->dcid); + rsp.dcid = cpu_to_le16(chan->scid); rsp.result = cpu_to_le16(result); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, -- cgit v1.2.3-58-ga151 From 8c1d787be4b62d2d1b6f04953eca4bcf7c839d44 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 13 Apr 2011 20:23:55 -0300 Subject: Bluetooth: Move conn to struct l2cap_chan There is no need to the socket deal directly with the channel, most of the time it cares about the channel only. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 7 ++-- net/bluetooth/l2cap_core.c | 92 +++++++++++++++++++------------------------ net/bluetooth/l2cap_sock.c | 12 +++--- net/bluetooth/rfcomm/core.c | 8 ++-- net/bluetooth/rfcomm/sock.c | 5 ++- 5 files changed, 59 insertions(+), 65 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index fd199cda752c..3de90a91a4e4 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -284,6 +284,9 @@ struct srej_list { struct l2cap_chan { struct sock *sk; + + struct l2cap_conn *conn; + __le16 psm; __u16 dcid; __u16 scid; @@ -385,8 +388,6 @@ struct l2cap_conn { struct l2cap_pinfo { struct bt_sock bt; - - struct l2cap_conn *conn; struct l2cap_chan *chan; }; @@ -447,7 +448,7 @@ int l2cap_init_sockets(void); void l2cap_cleanup_sockets(void); void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data); -void __l2cap_connect_rsp_defer(struct sock *sk); +void __l2cap_connect_rsp_defer(struct l2cap_chan *chan); int __l2cap_wait_ack(struct sock *sk); struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index dd726bdd6e02..8562ac1ba947 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -169,7 +169,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) conn->disc_reason = 0x13; - l2cap_pi(sk)->conn = conn; + chan->conn = conn; if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) { if (conn->hcon->type == LE_LINK) { @@ -204,7 +204,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) void l2cap_chan_del(struct l2cap_chan *chan, int err) { struct sock *sk = chan->sk; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = chan->conn; struct sock *parent = bt_sk(sk)->parent; l2cap_sock_clear_timer(sk); @@ -218,7 +218,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) write_unlock_bh(&conn->chan_lock); __sock_put(sk); - l2cap_pi(sk)->conn = NULL; + chan->conn = NULL; hci_conn_put(conn->hcon); } @@ -296,7 +296,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) /* Service level security */ static inline int l2cap_check_security(struct l2cap_chan *chan) { - struct l2cap_conn *conn = l2cap_pi(chan->sk)->conn; + struct l2cap_conn *conn = chan->conn; __u8 auth_type; auth_type = l2cap_get_auth_type(chan); @@ -349,7 +349,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) struct sk_buff *skb; struct l2cap_hdr *lh; struct l2cap_pinfo *pi = l2cap_pi(chan->sk); - struct l2cap_conn *conn = pi->conn; + struct l2cap_conn *conn = chan->conn; struct sock *sk = (struct sock *)pi; int count, hlen = L2CAP_HDR_SIZE + 2; u8 flags; @@ -394,7 +394,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) else flags = ACL_START; - hci_send_acl(pi->conn->hcon, skb, flags); + hci_send_acl(chan->conn->hcon, skb, flags); } static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control) @@ -417,8 +417,7 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) static void l2cap_do_start(struct l2cap_chan *chan) { - struct sock *sk = chan->sk; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = chan->conn; if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) @@ -920,12 +919,13 @@ done: int __l2cap_wait_ack(struct sock *sk) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; DECLARE_WAITQUEUE(wait, current); int err = 0; int timeo = HZ/5; add_wait_queue(sk_sleep(sk), &wait); - while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) { + while ((chan->unacked_frames > 0 && chan->conn)) { set_current_state(TASK_INTERRUPTIBLE); if (!timeo) @@ -958,7 +958,7 @@ static void l2cap_monitor_timeout(unsigned long arg) bh_lock_sock(sk); if (chan->retry_count >= chan->remote_max_tx) { - l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED); + l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); bh_unlock_sock(sk); return; } @@ -1008,8 +1008,7 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan) void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) { - struct sock *sk = chan->sk; - struct hci_conn *hcon = l2cap_pi(sk)->conn->hcon; + struct hci_conn *hcon = chan->conn->hcon; u16 flags; BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len); @@ -1045,8 +1044,6 @@ void l2cap_streaming_send(struct l2cap_chan *chan) static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) { - struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *skb, *tx_skb; u16 control, fcs; @@ -1065,7 +1062,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) if (chan->remote_max_tx && bt_cb(skb)->retries == chan->remote_max_tx) { - l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED); + l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); return; } @@ -1096,7 +1093,6 @@ int l2cap_ertm_send(struct l2cap_chan *chan) { struct sk_buff *skb, *tx_skb; struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; int nsent = 0; @@ -1107,7 +1103,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan) if (chan->remote_max_tx && bt_cb(skb)->retries == chan->remote_max_tx) { - l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED); + l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); break; } @@ -1203,7 +1199,7 @@ static void l2cap_send_srejtail(struct l2cap_chan *chan) static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb) { - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; struct sk_buff **frag; int err, sent = 0; @@ -1236,7 +1232,7 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) { struct sock *sk = chan->sk; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = chan->conn; struct sk_buff *skb; int err, count, hlen = L2CAP_HDR_SIZE + 2; struct l2cap_hdr *lh; @@ -1266,7 +1262,7 @@ struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) { struct sock *sk = chan->sk; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = chan->conn; struct sk_buff *skb; int err, count, hlen = L2CAP_HDR_SIZE; struct l2cap_hdr *lh; @@ -1295,7 +1291,7 @@ struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *m struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen) { struct sock *sk = chan->sk; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = chan->conn; struct sk_buff *skb; int err, count, hlen = L2CAP_HDR_SIZE + 2; struct l2cap_hdr *lh; @@ -1611,7 +1607,6 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct l2cap_conf_req *req = data; struct l2cap_conf_rfc rfc = { .mode = chan->mode }; void *ptr = req->data; @@ -1629,7 +1624,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) /* fall through */ default: - chan->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask); + chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); break; } @@ -1639,8 +1634,8 @@ done: switch (chan->mode) { case L2CAP_MODE_BASIC: - if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) && - !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING)) + if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && + !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) break; rfc.mode = L2CAP_MODE_BASIC; @@ -1661,13 +1656,13 @@ done: rfc.retrans_timeout = 0; rfc.monitor_timeout = 0; rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); - if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) - rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); + if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10) + rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10); l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); - if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS)) + if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) break; if (chan->fcs == L2CAP_FCS_NONE || @@ -1684,13 +1679,13 @@ done: rfc.retrans_timeout = 0; rfc.monitor_timeout = 0; rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); - if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) - rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); + if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10) + rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10); l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); - if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS)) + if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) break; if (chan->fcs == L2CAP_FCS_NONE || @@ -1709,7 +1704,6 @@ done: static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct l2cap_conf_rsp *rsp = data; void *ptr = rsp->data; void *req = chan->conf_req; @@ -1769,7 +1763,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) case L2CAP_MODE_ERTM: if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) { chan->mode = l2cap_select_mode(rfc.mode, - pi->conn->feat_mask); + chan->conn->feat_mask); break; } @@ -1814,8 +1808,8 @@ done: chan->remote_tx_win = rfc.txwin_size; chan->remote_max_tx = rfc.max_transmit; - if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10) - rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); + if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10) + rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10); chan->remote_mps = le16_to_cpu(rfc.max_pdu_size); @@ -1832,8 +1826,8 @@ done: break; case L2CAP_MODE_STREAMING: - if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10) - rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); + if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10) + rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10); chan->remote_mps = le16_to_cpu(rfc.max_pdu_size); @@ -1943,15 +1937,12 @@ static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, return ptr - data; } -void __l2cap_connect_rsp_defer(struct sock *sk) +void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) { struct l2cap_conn_rsp rsp; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; - struct l2cap_chan *chan = l2cap_pi(sk)->chan; + struct l2cap_conn *conn = chan->conn; u8 buf[128]; - sk->sk_state = BT_CONFIG; - rsp.scid = cpu_to_le16(chan->dcid); rsp.dcid = cpu_to_le16(chan->scid); rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); @@ -2856,7 +2847,6 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct sk_buff *_skb; int err; @@ -2957,7 +2947,7 @@ drop: chan->sdu = NULL; disconnect: - l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); kfree_skb(skb); return 0; } @@ -3018,7 +3008,7 @@ static void l2cap_busy_work(struct work_struct *work) if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) { err = -EBUSY; - l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY); + l2cap_send_disconn_req(chan->conn, chan, EBUSY); break; } @@ -3236,7 +3226,6 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_txseq(rx_control); u8 req_seq = __get_reqseq(rx_control); u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; @@ -3267,7 +3256,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont /* invalid tx_seq */ if (tx_seq_offset >= chan->tx_win) { - l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); goto drop; } @@ -3534,7 +3523,6 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_cont static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) { struct l2cap_chan *chan = l2cap_pi(sk)->chan; - struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control; u8 req_seq; int len, next_tx_seq_offset, req_seq_offset; @@ -3558,7 +3546,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) len -= 2; if (len > chan->mps) { - l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); goto drop; } @@ -3574,13 +3562,13 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) /* check for invalid req-seq */ if (req_seq_offset > next_tx_seq_offset) { - l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); goto drop; } if (__is_iframe(control)) { if (len < 0) { - l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); goto drop; } @@ -3588,7 +3576,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) } else { if (len != 0) { BT_ERR("%d", len); - l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); goto drop; } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index f5a27737c151..61d93f6c36c8 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -455,8 +455,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us break; } - cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle; - memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3); + cinfo.hci_handle = chan->conn->hcon->handle; + memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3); len = min_t(unsigned int, len, sizeof(cinfo)); if (copy_to_user(optval, (char *) &cinfo, len)) @@ -690,7 +690,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch } if (opt == BT_FLUSHABLE_OFF) { - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = chan->conn; /* proceed futher only when we have l2cap_conn and No Flush support in the LM */ if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { @@ -823,7 +823,9 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms lock_sock(sk); if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) { - __l2cap_connect_rsp_defer(sk); + sk->sk_state = BT_CONFIG; + + __l2cap_connect_rsp_defer(l2cap_pi(sk)->chan); release_sock(sk); return 0; } @@ -878,8 +880,8 @@ static void l2cap_sock_cleanup_listen(struct sock *parent) void __l2cap_sock_close(struct sock *sk, int reason) { - struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct l2cap_chan *chan = l2cap_pi(sk)->chan; + struct l2cap_conn *conn = chan->conn; BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index fdd8f5ab18c1..121a5c13b989 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -232,6 +232,8 @@ static int rfcomm_l2sock_create(struct socket **sock) static inline int rfcomm_check_security(struct rfcomm_dlc *d) { struct sock *sk = d->session->sock->sk; + struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; + __u8 auth_type; switch (d->sec_level) { @@ -246,8 +248,7 @@ static inline int rfcomm_check_security(struct rfcomm_dlc *d) break; } - return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level, - auth_type); + return hci_conn_security(conn->hcon, d->sec_level, auth_type); } static void rfcomm_session_timeout(unsigned long arg) @@ -1241,6 +1242,7 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci) void rfcomm_dlc_accept(struct rfcomm_dlc *d) { struct sock *sk = d->session->sock->sk; + struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; BT_DBG("dlc %p", d); @@ -1254,7 +1256,7 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d) rfcomm_dlc_unlock(d); if (d->role_switch) - hci_conn_switch_role(l2cap_pi(sk)->conn->hcon, 0x00); + hci_conn_switch_role(conn->hcon, 0x00); rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig); } diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 66cc1f0c3df8..386cfaffd4b7 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -743,6 +743,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u struct sock *sk = sock->sk; struct sock *l2cap_sk; struct rfcomm_conninfo cinfo; + struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; int len, err = 0; u32 opt; @@ -787,8 +788,8 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk; - cinfo.hci_handle = l2cap_pi(l2cap_sk)->conn->hcon->handle; - memcpy(cinfo.dev_class, l2cap_pi(l2cap_sk)->conn->hcon->dev_class, 3); + cinfo.hci_handle = conn->hcon->handle; + memcpy(cinfo.dev_class, conn->hcon->dev_class, 3); len = min_t(unsigned int, len, sizeof(cinfo)); if (copy_to_user(optval, (char *) &cinfo, len)) -- cgit v1.2.3-58-ga151 From 6ff5abbf4e4aa88feb9c2367d4fbd9ea081bf98c Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 25 Apr 2011 15:10:41 -0300 Subject: Bluetooth: Fix memory leak with L2CAP channels A new l2cap_chan_free() is added to free the channels. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 1 + net/bluetooth/l2cap_core.c | 10 ++++++---- net/bluetooth/l2cap_sock.c | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 3de90a91a4e4..0a0134161b1b 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -469,6 +469,7 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); void l2cap_chan_del(struct l2cap_chan *chan, int err); +void l2cap_chan_free(struct l2cap_chan *chan); int l2cap_chan_connect(struct l2cap_chan *chan); #endif /* __L2CAP_H */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8562ac1ba947..338d8c3eedab 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -160,6 +160,11 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) return chan; } +void l2cap_chan_free(struct l2cap_chan *chan) +{ + kfree(chan); +} + static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) { struct sock *sk = chan->sk; @@ -236,7 +241,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE && chan->conf_state & L2CAP_CONF_INPUT_DONE)) - goto free; + return; skb_queue_purge(&chan->tx_q); @@ -255,9 +260,6 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) kfree(l); } } - -free: - kfree(chan); } static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 61d93f6c36c8..0e23ebdf7c8f 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -849,6 +849,8 @@ void l2cap_sock_kill(struct sock *sk) BT_DBG("sk %p state %d", sk, sk->sk_state); /* Kill poor orphan */ + + l2cap_chan_free(l2cap_pi(sk)->chan); bt_sock_unlink(&l2cap_sk_list, sk); sock_set_flag(sk, SOCK_DEAD); sock_put(sk); -- cgit v1.2.3-58-ga151 From cf2f90f59bbf2c2a539d171cde6e1dfe72048555 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 27 Apr 2011 18:40:39 -0300 Subject: Bluetooth: Don't export l2cap_sock_ops l2cap_sk_ops can be static, it's not used outside l2cap_sock.c Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 1 - net/bluetooth/l2cap_sock.c | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 0a0134161b1b..c34b1c126363 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -441,7 +441,6 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch) #define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START) extern int disable_ertm; -extern const struct proto_ops l2cap_sock_ops; extern struct bt_sock_list l2cap_sk_list; int l2cap_init_sockets(void); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 0e23ebdf7c8f..09cc7a005349 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -30,6 +30,8 @@ #include #include +static const struct proto_ops l2cap_sock_ops; + /* ---- L2CAP timers ---- */ static void l2cap_sock_timeout(unsigned long arg) { @@ -1106,7 +1108,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, return 0; } -const struct proto_ops l2cap_sock_ops = { +static const struct proto_ops l2cap_sock_ops = { .family = PF_BLUETOOTH, .owner = THIS_MODULE, .release = l2cap_sock_release, -- cgit v1.2.3-58-ga151 From 14a53664138a8407382745bb470045d1817b7801 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 27 Apr 2011 10:29:56 -0400 Subject: Bluetooth: Add basic discovery commands to the management interface This patch adds start_discovery and stop_discovery commands to the management interface. Right now their implementation is fairly simplistic and the parameters are fixed to what user space has defaulted to so far. This is the very initial phase for discovery implementation into the kernel. Next steps include name resolution, LE scanning and bdaddr type handling. Signed-off-by: Johan Hedberg Signed-off-by: Anderson Briglia Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/mgmt.h | 4 +++ net/bluetooth/mgmt.c | 76 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 6b6ff92ab499..be93dd0eb962 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -195,6 +195,10 @@ struct mgmt_cp_remove_remote_oob_data { bdaddr_t bdaddr; } __packed; +#define MGMT_OP_START_DISCOVERY 0x001B + +#define MGMT_OP_STOP_DISCOVERY 0x001C + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index c304688252b8..dbc248f27b1b 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1569,6 +1569,75 @@ static int remove_remote_oob_data(struct sock *sk, u16 index, return err; } +static int start_discovery(struct sock *sk, u16 index) +{ + u8 lap[3] = { 0x33, 0x8b, 0x9e }; + struct hci_cp_inquiry cp; + struct pending_cmd *cmd; + struct hci_dev *hdev; + int err; + + BT_DBG("hci%u", index); + + hdev = hci_dev_get(index); + if (!hdev) + return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENODEV); + + hci_dev_lock_bh(hdev); + + cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, index, NULL, 0); + if (!cmd) { + err = -ENOMEM; + goto failed; + } + + memset(&cp, 0, sizeof(cp)); + memcpy(&cp.lap, lap, 3); + cp.length = 0x08; + cp.num_rsp = 0x00; + + err = hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp); + if (err < 0) + mgmt_pending_remove(cmd); + +failed: + hci_dev_unlock_bh(hdev); + hci_dev_put(hdev); + + return err; +} + +static int stop_discovery(struct sock *sk, u16 index) +{ + struct hci_dev *hdev; + struct pending_cmd *cmd; + int err; + + BT_DBG("hci%u", index); + + hdev = hci_dev_get(index); + if (!hdev) + return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, ENODEV); + + hci_dev_lock_bh(hdev); + + cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index, NULL, 0); + if (!cmd) { + err = -ENOMEM; + goto failed; + } + + err = hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL); + if (err < 0) + mgmt_pending_remove(cmd); + +failed: + hci_dev_unlock_bh(hdev); + hci_dev_put(hdev); + + return err; +} + int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) { unsigned char *buf; @@ -1677,7 +1746,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr), len); break; - + case MGMT_OP_START_DISCOVERY: + err = start_discovery(sk, index); + break; + case MGMT_OP_STOP_DISCOVERY: + err = stop_discovery(sk, index); + break; default: BT_DBG("Unknown op %u", opcode); err = cmd_status(sk, index, opcode, 0x01); -- cgit v1.2.3-58-ga151 From 314b2381a79c6bfe3ddc4ba3806ecb6aec27a3db Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 27 Apr 2011 10:29:57 -0400 Subject: Bluetooth: Add discovering event to the Management interface This patch adds a new event to the Management interface to track when local adapters are discovering remote devices. For now this only tracks BR/EDR discovery procedures. Signed-off-by: Johan Hedberg Signed-off-by: Anderson Briglia Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 1 + include/net/bluetooth/mgmt.h | 2 ++ net/bluetooth/hci_event.c | 40 ++++++++++++++++++++++++++++++++++------ net/bluetooth/mgmt.c | 6 ++++++ 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 4093133c1283..69967e540c96 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -790,6 +790,7 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, u8 *eir); int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); +int mgmt_discovering(u16 index, u8 discovering); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index be93dd0eb962..743440615349 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -285,3 +285,5 @@ struct mgmt_ev_remote_name { bdaddr_t bdaddr; __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; + +#define MGMT_EV_DISCOVERING 0x0014 diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index cb25628c0583..e64a3de70d77 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -56,7 +56,9 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) if (status) return; - clear_bit(HCI_INQUIRY, &hdev->flags); + if (test_bit(HCI_MGMT, &hdev->flags) && + test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) + mgmt_discovering(hdev->id, 0); hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); @@ -72,7 +74,9 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) if (status) return; - clear_bit(HCI_INQUIRY, &hdev->flags); + if (test_bit(HCI_MGMT, &hdev->flags) && + test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) + mgmt_discovering(hdev->id, 0); hci_conn_check_pending(hdev); } @@ -841,10 +845,14 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) if (status) { hci_req_complete(hdev, HCI_OP_INQUIRY, status); - hci_conn_check_pending(hdev); - } else - set_bit(HCI_INQUIRY, &hdev->flags); + return; + } + + if (test_bit(HCI_MGMT, &hdev->flags) && + !test_and_set_bit(HCI_INQUIRY, + &hdev->flags)) + mgmt_discovering(hdev->id, 1); } static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) @@ -1208,7 +1216,9 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff BT_DBG("%s status %d", hdev->name, status); - clear_bit(HCI_INQUIRY, &hdev->flags); + if (test_bit(HCI_MGMT, &hdev->flags) && + test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) + mgmt_discovering(hdev->id, 0); hci_req_complete(hdev, HCI_OP_INQUIRY, status); @@ -1228,6 +1238,12 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff * hci_dev_lock(hdev); + if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { + + if (test_bit(HCI_MGMT, &hdev->flags)) + mgmt_discovering(hdev->id, 1); + } + for (; num_rsp; num_rsp--, info++) { bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; @@ -2158,6 +2174,12 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct hci_dev_lock(hdev); + if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { + + if (test_bit(HCI_MGMT, &hdev->flags)) + mgmt_discovering(hdev->id, 1); + } + if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { struct inquiry_info_with_rssi_and_pscan_mode *info; info = (void *) (skb->data + 1); @@ -2320,6 +2342,12 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct if (!num_rsp) return; + if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { + + if (test_bit(HCI_MGMT, &hdev->flags)) + mgmt_discovering(hdev->id, 1); + } + hci_dev_lock(hdev); for (; num_rsp; num_rsp--, info++) { diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index dbc248f27b1b..4542396fc856 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2149,3 +2149,9 @@ int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name) return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL); } + +int mgmt_discovering(u16 index, u8 discovering) +{ + return mgmt_event(MGMT_EV_DISCOVERING, index, &discovering, + sizeof(discovering), NULL); +} -- cgit v1.2.3-58-ga151 From 0a14842f5a3c0e88a1e59fac5c3025db39721f74 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 20 Apr 2011 09:27:32 +0000 Subject: net: filter: Just In Time compiler for x86-64 In order to speedup packet filtering, here is an implementation of a JIT compiler for x86_64 It is disabled by default, and must be enabled by the admin. echo 1 >/proc/sys/net/core/bpf_jit_enable It uses module_alloc() and module_free() to get memory in the 2GB text kernel range since we call helpers functions from the generated code. EAX : BPF A accumulator EBX : BPF X accumulator RDI : pointer to skb (first argument given to JIT function) RBP : frame pointer (even if CONFIG_FRAME_POINTER=n) r9d : skb->len - skb->data_len (headlen) r8 : skb->data To get a trace of generated code, use : echo 2 >/proc/sys/net/core/bpf_jit_enable Example of generated code : # tcpdump -p -n -s 0 -i eth1 host 192.168.20.0/24 flen=18 proglen=147 pass=3 image=ffffffffa00b5000 JIT code: ffffffffa00b5000: 55 48 89 e5 48 83 ec 60 48 89 5d f8 44 8b 4f 60 JIT code: ffffffffa00b5010: 44 2b 4f 64 4c 8b 87 b8 00 00 00 be 0c 00 00 00 JIT code: ffffffffa00b5020: e8 24 7b f7 e0 3d 00 08 00 00 75 28 be 1a 00 00 JIT code: ffffffffa00b5030: 00 e8 fe 7a f7 e0 24 00 3d 00 14 a8 c0 74 49 be JIT code: ffffffffa00b5040: 1e 00 00 00 e8 eb 7a f7 e0 24 00 3d 00 14 a8 c0 JIT code: ffffffffa00b5050: 74 36 eb 3b 3d 06 08 00 00 74 07 3d 35 80 00 00 JIT code: ffffffffa00b5060: 75 2d be 1c 00 00 00 e8 c8 7a f7 e0 24 00 3d 00 JIT code: ffffffffa00b5070: 14 a8 c0 74 13 be 26 00 00 00 e8 b5 7a f7 e0 24 JIT code: ffffffffa00b5080: 00 3d 00 14 a8 c0 75 07 b8 ff ff 00 00 eb 02 31 JIT code: ffffffffa00b5090: c0 c9 c3 BPF program is 144 bytes long, so native program is almost same size ;) (000) ldh [12] (001) jeq #0x800 jt 2 jf 8 (002) ld [26] (003) and #0xffffff00 (004) jeq #0xc0a81400 jt 16 jf 5 (005) ld [30] (006) and #0xffffff00 (007) jeq #0xc0a81400 jt 16 jf 17 (008) jeq #0x806 jt 10 jf 9 (009) jeq #0x8035 jt 10 jf 17 (010) ld [28] (011) and #0xffffff00 (012) jeq #0xc0a81400 jt 16 jf 13 (013) ld [38] (014) and #0xffffff00 (015) jeq #0xc0a81400 jt 16 jf 17 (016) ret #65535 (017) ret #0 Signed-off-by: Eric Dumazet Cc: Arnaldo Carvalho de Melo Cc: Ben Hutchings Cc: Hagen Paul Pfeifer Signed-off-by: David S. Miller --- Documentation/sysctl/net.txt | 11 + MAINTAINERS | 1 + arch/x86/Kbuild | 1 + arch/x86/Kconfig | 1 + arch/x86/net/Makefile | 4 + arch/x86/net/bpf_jit.S | 140 +++++++++ arch/x86/net/bpf_jit_comp.c | 654 +++++++++++++++++++++++++++++++++++++++++++ include/linux/filter.h | 76 +++++ include/linux/netdevice.h | 1 + include/linux/skbuff.h | 2 +- net/Kconfig | 13 + net/core/filter.c | 65 +---- net/core/sysctl_net_core.c | 9 + net/packet/af_packet.c | 2 +- 14 files changed, 918 insertions(+), 62 deletions(-) create mode 100644 arch/x86/net/Makefile create mode 100644 arch/x86/net/bpf_jit.S create mode 100644 arch/x86/net/bpf_jit_comp.c diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt index cbd05ffc606b..3201a7097e4d 100644 --- a/Documentation/sysctl/net.txt +++ b/Documentation/sysctl/net.txt @@ -32,6 +32,17 @@ Table : Subdirectories in /proc/sys/net 1. /proc/sys/net/core - Network core options ------------------------------------------------------- +bpf_jit_enable +-------------- + +This enables Berkeley Packet Filter Just in Time compiler. +Currently supported on x86_64 architecture, bpf_jit provides a framework +to speed packet filtering, the one used by tcpdump/libpcap for example. +Values : + 0 - disable the JIT (default value) + 1 - enable the JIT + 2 - enable the JIT and ask the compiler to emit traces on kernel log. + rmem_default ------------ diff --git a/MAINTAINERS b/MAINTAINERS index b5266ad50167..17c0917a26ea 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4372,6 +4372,7 @@ S: Maintained F: net/ipv4/ F: net/ipv6/ F: include/net/ip* +F: arch/x86/net/* NETWORKING [LABELED] (NetLabel, CIPSO, Labeled IPsec, SECMARK) M: Paul Moore diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild index 0e103236b754..0e9dec6cadd1 100644 --- a/arch/x86/Kbuild +++ b/arch/x86/Kbuild @@ -15,3 +15,4 @@ obj-y += vdso/ obj-$(CONFIG_IA32_EMULATION) += ia32/ obj-y += platform/ +obj-y += net/ diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index cc6c53a95bfd..855a1bdc437d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -72,6 +72,7 @@ config X86 select IRQ_FORCED_THREADING select USE_GENERIC_SMP_HELPERS if SMP select ARCH_NO_SYSDEV_OPS + select HAVE_BPF_JIT if X86_64 config INSTRUCTION_DECODER def_bool (KPROBES || PERF_EVENTS) diff --git a/arch/x86/net/Makefile b/arch/x86/net/Makefile new file mode 100644 index 000000000000..90568c33ddb0 --- /dev/null +++ b/arch/x86/net/Makefile @@ -0,0 +1,4 @@ +# +# Arch-specific network modules +# +obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_jit_comp.o diff --git a/arch/x86/net/bpf_jit.S b/arch/x86/net/bpf_jit.S new file mode 100644 index 000000000000..66870223f8c5 --- /dev/null +++ b/arch/x86/net/bpf_jit.S @@ -0,0 +1,140 @@ +/* bpf_jit.S : BPF JIT helper functions + * + * Copyright (C) 2011 Eric Dumazet (eric.dumazet@gmail.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + */ +#include +#include + +/* + * Calling convention : + * rdi : skb pointer + * esi : offset of byte(s) to fetch in skb (can be scratched) + * r8 : copy of skb->data + * r9d : hlen = skb->len - skb->data_len + */ +#define SKBDATA %r8 + +sk_load_word_ind: + .globl sk_load_word_ind + + add %ebx,%esi /* offset += X */ +# test %esi,%esi /* if (offset < 0) goto bpf_error; */ + js bpf_error + +sk_load_word: + .globl sk_load_word + + mov %r9d,%eax # hlen + sub %esi,%eax # hlen - offset + cmp $3,%eax + jle bpf_slow_path_word + mov (SKBDATA,%rsi),%eax + bswap %eax /* ntohl() */ + ret + + +sk_load_half_ind: + .globl sk_load_half_ind + + add %ebx,%esi /* offset += X */ + js bpf_error + +sk_load_half: + .globl sk_load_half + + mov %r9d,%eax + sub %esi,%eax # hlen - offset + cmp $1,%eax + jle bpf_slow_path_half + movzwl (SKBDATA,%rsi),%eax + rol $8,%ax # ntohs() + ret + +sk_load_byte_ind: + .globl sk_load_byte_ind + add %ebx,%esi /* offset += X */ + js bpf_error + +sk_load_byte: + .globl sk_load_byte + + cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */ + jle bpf_slow_path_byte + movzbl (SKBDATA,%rsi),%eax + ret + +/** + * sk_load_byte_msh - BPF_S_LDX_B_MSH helper + * + * Implements BPF_S_LDX_B_MSH : ldxb 4*([offset]&0xf) + * Must preserve A accumulator (%eax) + * Inputs : %esi is the offset value, already known positive + */ +ENTRY(sk_load_byte_msh) + CFI_STARTPROC + cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte_msh */ + jle bpf_slow_path_byte_msh + movzbl (SKBDATA,%rsi),%ebx + and $15,%bl + shl $2,%bl + ret + CFI_ENDPROC +ENDPROC(sk_load_byte_msh) + +bpf_error: +# force a return 0 from jit handler + xor %eax,%eax + mov -8(%rbp),%rbx + leaveq + ret + +/* rsi contains offset and can be scratched */ +#define bpf_slow_path_common(LEN) \ + push %rdi; /* save skb */ \ + push %r9; \ + push SKBDATA; \ +/* rsi already has offset */ \ + mov $LEN,%ecx; /* len */ \ + lea -12(%rbp),%rdx; \ + call skb_copy_bits; \ + test %eax,%eax; \ + pop SKBDATA; \ + pop %r9; \ + pop %rdi + + +bpf_slow_path_word: + bpf_slow_path_common(4) + js bpf_error + mov -12(%rbp),%eax + bswap %eax + ret + +bpf_slow_path_half: + bpf_slow_path_common(2) + js bpf_error + mov -12(%rbp),%ax + rol $8,%ax + movzwl %ax,%eax + ret + +bpf_slow_path_byte: + bpf_slow_path_common(1) + js bpf_error + movzbl -12(%rbp),%eax + ret + +bpf_slow_path_byte_msh: + xchg %eax,%ebx /* dont lose A , X is about to be scratched */ + bpf_slow_path_common(1) + js bpf_error + movzbl -12(%rbp),%eax + and $15,%al + shl $2,%al + xchg %eax,%ebx + ret diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c new file mode 100644 index 000000000000..bfab3fa10edc --- /dev/null +++ b/arch/x86/net/bpf_jit_comp.c @@ -0,0 +1,654 @@ +/* bpf_jit_comp.c : BPF JIT compiler + * + * Copyright (C) 2011 Eric Dumazet (eric.dumazet@gmail.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + */ +#include +#include +#include +#include + +/* + * Conventions : + * EAX : BPF A accumulator + * EBX : BPF X accumulator + * RDI : pointer to skb (first argument given to JIT function) + * RBP : frame pointer (even if CONFIG_FRAME_POINTER=n) + * ECX,EDX,ESI : scratch registers + * r9d : skb->len - skb->data_len (headlen) + * r8 : skb->data + * -8(RBP) : saved RBX value + * -16(RBP)..-80(RBP) : BPF_MEMWORDS values + */ +int bpf_jit_enable __read_mostly; + +/* + * assembly code in arch/x86/net/bpf_jit.S + */ +extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[]; +extern u8 sk_load_word_ind[], sk_load_half_ind[], sk_load_byte_ind[]; + +static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len) +{ + if (len == 1) + *ptr = bytes; + else if (len == 2) + *(u16 *)ptr = bytes; + else { + *(u32 *)ptr = bytes; + barrier(); + } + return ptr + len; +} + +#define EMIT(bytes, len) do { prog = emit_code(prog, bytes, len); } while (0) + +#define EMIT1(b1) EMIT(b1, 1) +#define EMIT2(b1, b2) EMIT((b1) + ((b2) << 8), 2) +#define EMIT3(b1, b2, b3) EMIT((b1) + ((b2) << 8) + ((b3) << 16), 3) +#define EMIT4(b1, b2, b3, b4) EMIT((b1) + ((b2) << 8) + ((b3) << 16) + ((b4) << 24), 4) +#define EMIT1_off32(b1, off) do { EMIT1(b1); EMIT(off, 4);} while (0) + +#define CLEAR_A() EMIT2(0x31, 0xc0) /* xor %eax,%eax */ +#define CLEAR_X() EMIT2(0x31, 0xdb) /* xor %ebx,%ebx */ + +static inline bool is_imm8(int value) +{ + return value <= 127 && value >= -128; +} + +static inline bool is_near(int offset) +{ + return offset <= 127 && offset >= -128; +} + +#define EMIT_JMP(offset) \ +do { \ + if (offset) { \ + if (is_near(offset)) \ + EMIT2(0xeb, offset); /* jmp .+off8 */ \ + else \ + EMIT1_off32(0xe9, offset); /* jmp .+off32 */ \ + } \ +} while (0) + +/* list of x86 cond jumps opcodes (. + s8) + * Add 0x10 (and an extra 0x0f) to generate far jumps (. + s32) + */ +#define X86_JB 0x72 +#define X86_JAE 0x73 +#define X86_JE 0x74 +#define X86_JNE 0x75 +#define X86_JBE 0x76 +#define X86_JA 0x77 + +#define EMIT_COND_JMP(op, offset) \ +do { \ + if (is_near(offset)) \ + EMIT2(op, offset); /* jxx .+off8 */ \ + else { \ + EMIT2(0x0f, op + 0x10); \ + EMIT(offset, 4); /* jxx .+off32 */ \ + } \ +} while (0) + +#define COND_SEL(CODE, TOP, FOP) \ + case CODE: \ + t_op = TOP; \ + f_op = FOP; \ + goto cond_branch + + +#define SEEN_DATAREF 1 /* might call external helpers */ +#define SEEN_XREG 2 /* ebx is used */ +#define SEEN_MEM 4 /* use mem[] for temporary storage */ + +static inline void bpf_flush_icache(void *start, void *end) +{ + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + smp_wmb(); + flush_icache_range((unsigned long)start, (unsigned long)end); + set_fs(old_fs); +} + + +void bpf_jit_compile(struct sk_filter *fp) +{ + u8 temp[64]; + u8 *prog; + unsigned int proglen, oldproglen = 0; + int ilen, i; + int t_offset, f_offset; + u8 t_op, f_op, seen = 0, pass; + u8 *image = NULL; + u8 *func; + int pc_ret0 = -1; /* bpf index of first RET #0 instruction (if any) */ + unsigned int cleanup_addr; /* epilogue code offset */ + unsigned int *addrs; + const struct sock_filter *filter = fp->insns; + int flen = fp->len; + + if (!bpf_jit_enable) + return; + + addrs = kmalloc(flen * sizeof(*addrs), GFP_KERNEL); + if (addrs == NULL) + return; + + /* Before first pass, make a rough estimation of addrs[] + * each bpf instruction is translated to less than 64 bytes + */ + for (proglen = 0, i = 0; i < flen; i++) { + proglen += 64; + addrs[i] = proglen; + } + cleanup_addr = proglen; /* epilogue address */ + + for (pass = 0; pass < 10; pass++) { + /* no prologue/epilogue for trivial filters (RET something) */ + proglen = 0; + prog = temp; + + if (seen) { + EMIT4(0x55, 0x48, 0x89, 0xe5); /* push %rbp; mov %rsp,%rbp */ + EMIT4(0x48, 0x83, 0xec, 96); /* subq $96,%rsp */ + /* note : must save %rbx in case bpf_error is hit */ + if (seen & (SEEN_XREG | SEEN_DATAREF)) + EMIT4(0x48, 0x89, 0x5d, 0xf8); /* mov %rbx, -8(%rbp) */ + if (seen & SEEN_XREG) + CLEAR_X(); /* make sure we dont leek kernel memory */ + + /* + * If this filter needs to access skb data, + * loads r9 and r8 with : + * r9 = skb->len - skb->data_len + * r8 = skb->data + */ + if (seen & SEEN_DATAREF) { + if (offsetof(struct sk_buff, len) <= 127) + /* mov off8(%rdi),%r9d */ + EMIT4(0x44, 0x8b, 0x4f, offsetof(struct sk_buff, len)); + else { + /* mov off32(%rdi),%r9d */ + EMIT3(0x44, 0x8b, 0x8f); + EMIT(offsetof(struct sk_buff, len), 4); + } + if (is_imm8(offsetof(struct sk_buff, data_len))) + /* sub off8(%rdi),%r9d */ + EMIT4(0x44, 0x2b, 0x4f, offsetof(struct sk_buff, data_len)); + else { + EMIT3(0x44, 0x2b, 0x8f); + EMIT(offsetof(struct sk_buff, data_len), 4); + } + + if (is_imm8(offsetof(struct sk_buff, data))) + /* mov off8(%rdi),%r8 */ + EMIT4(0x4c, 0x8b, 0x47, offsetof(struct sk_buff, data)); + else { + /* mov off32(%rdi),%r8 */ + EMIT3(0x4c, 0x8b, 0x87); + EMIT(offsetof(struct sk_buff, data), 4); + } + } + } + + switch (filter[0].code) { + case BPF_S_RET_K: + case BPF_S_LD_W_LEN: + case BPF_S_ANC_PROTOCOL: + case BPF_S_ANC_IFINDEX: + case BPF_S_ANC_MARK: + case BPF_S_ANC_RXHASH: + case BPF_S_ANC_CPU: + case BPF_S_ANC_QUEUE: + case BPF_S_LD_W_ABS: + case BPF_S_LD_H_ABS: + case BPF_S_LD_B_ABS: + /* first instruction sets A register (or is RET 'constant') */ + break; + default: + /* make sure we dont leak kernel information to user */ + CLEAR_A(); /* A = 0 */ + } + + for (i = 0; i < flen; i++) { + unsigned int K = filter[i].k; + + switch (filter[i].code) { + case BPF_S_ALU_ADD_X: /* A += X; */ + seen |= SEEN_XREG; + EMIT2(0x01, 0xd8); /* add %ebx,%eax */ + break; + case BPF_S_ALU_ADD_K: /* A += K; */ + if (!K) + break; + if (is_imm8(K)) + EMIT3(0x83, 0xc0, K); /* add imm8,%eax */ + else + EMIT1_off32(0x05, K); /* add imm32,%eax */ + break; + case BPF_S_ALU_SUB_X: /* A -= X; */ + seen |= SEEN_XREG; + EMIT2(0x29, 0xd8); /* sub %ebx,%eax */ + break; + case BPF_S_ALU_SUB_K: /* A -= K */ + if (!K) + break; + if (is_imm8(K)) + EMIT3(0x83, 0xe8, K); /* sub imm8,%eax */ + else + EMIT1_off32(0x2d, K); /* sub imm32,%eax */ + break; + case BPF_S_ALU_MUL_X: /* A *= X; */ + seen |= SEEN_XREG; + EMIT3(0x0f, 0xaf, 0xc3); /* imul %ebx,%eax */ + break; + case BPF_S_ALU_MUL_K: /* A *= K */ + if (is_imm8(K)) + EMIT3(0x6b, 0xc0, K); /* imul imm8,%eax,%eax */ + else { + EMIT2(0x69, 0xc0); /* imul imm32,%eax */ + EMIT(K, 4); + } + break; + case BPF_S_ALU_DIV_X: /* A /= X; */ + seen |= SEEN_XREG; + EMIT2(0x85, 0xdb); /* test %ebx,%ebx */ + if (pc_ret0 != -1) + EMIT_COND_JMP(X86_JE, addrs[pc_ret0] - (addrs[i] - 4)); + else { + EMIT_COND_JMP(X86_JNE, 2 + 5); + CLEAR_A(); + EMIT1_off32(0xe9, cleanup_addr - (addrs[i] - 4)); /* jmp .+off32 */ + } + EMIT4(0x31, 0xd2, 0xf7, 0xf3); /* xor %edx,%edx; div %ebx */ + break; + case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */ + EMIT3(0x48, 0x69, 0xc0); /* imul imm32,%rax,%rax */ + EMIT(K, 4); + EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */ + break; + case BPF_S_ALU_AND_X: + seen |= SEEN_XREG; + EMIT2(0x21, 0xd8); /* and %ebx,%eax */ + break; + case BPF_S_ALU_AND_K: + if (K >= 0xFFFFFF00) { + EMIT2(0x24, K & 0xFF); /* and imm8,%al */ + } else if (K >= 0xFFFF0000) { + EMIT2(0x66, 0x25); /* and imm16,%ax */ + EMIT2(K, 2); + } else { + EMIT1_off32(0x25, K); /* and imm32,%eax */ + } + break; + case BPF_S_ALU_OR_X: + seen |= SEEN_XREG; + EMIT2(0x09, 0xd8); /* or %ebx,%eax */ + break; + case BPF_S_ALU_OR_K: + if (is_imm8(K)) + EMIT3(0x83, 0xc8, K); /* or imm8,%eax */ + else + EMIT1_off32(0x0d, K); /* or imm32,%eax */ + break; + case BPF_S_ALU_LSH_X: /* A <<= X; */ + seen |= SEEN_XREG; + EMIT4(0x89, 0xd9, 0xd3, 0xe0); /* mov %ebx,%ecx; shl %cl,%eax */ + break; + case BPF_S_ALU_LSH_K: + if (K == 0) + break; + else if (K == 1) + EMIT2(0xd1, 0xe0); /* shl %eax */ + else + EMIT3(0xc1, 0xe0, K); + break; + case BPF_S_ALU_RSH_X: /* A >>= X; */ + seen |= SEEN_XREG; + EMIT4(0x89, 0xd9, 0xd3, 0xe8); /* mov %ebx,%ecx; shr %cl,%eax */ + break; + case BPF_S_ALU_RSH_K: /* A >>= K; */ + if (K == 0) + break; + else if (K == 1) + EMIT2(0xd1, 0xe8); /* shr %eax */ + else + EMIT3(0xc1, 0xe8, K); + break; + case BPF_S_ALU_NEG: + EMIT2(0xf7, 0xd8); /* neg %eax */ + break; + case BPF_S_RET_K: + if (!K) { + if (pc_ret0 == -1) + pc_ret0 = i; + CLEAR_A(); + } else { + EMIT1_off32(0xb8, K); /* mov $imm32,%eax */ + } + /* fallinto */ + case BPF_S_RET_A: + if (seen) { + if (i != flen - 1) { + EMIT_JMP(cleanup_addr - addrs[i]); + break; + } + if (seen & SEEN_XREG) + EMIT4(0x48, 0x8b, 0x5d, 0xf8); /* mov -8(%rbp),%rbx */ + EMIT1(0xc9); /* leaveq */ + } + EMIT1(0xc3); /* ret */ + break; + case BPF_S_MISC_TAX: /* X = A */ + seen |= SEEN_XREG; + EMIT2(0x89, 0xc3); /* mov %eax,%ebx */ + break; + case BPF_S_MISC_TXA: /* A = X */ + seen |= SEEN_XREG; + EMIT2(0x89, 0xd8); /* mov %ebx,%eax */ + break; + case BPF_S_LD_IMM: /* A = K */ + if (!K) + CLEAR_A(); + else + EMIT1_off32(0xb8, K); /* mov $imm32,%eax */ + break; + case BPF_S_LDX_IMM: /* X = K */ + seen |= SEEN_XREG; + if (!K) + CLEAR_X(); + else + EMIT1_off32(0xbb, K); /* mov $imm32,%ebx */ + break; + case BPF_S_LD_MEM: /* A = mem[K] : mov off8(%rbp),%eax */ + seen |= SEEN_MEM; + EMIT3(0x8b, 0x45, 0xf0 - K*4); + break; + case BPF_S_LDX_MEM: /* X = mem[K] : mov off8(%rbp),%ebx */ + seen |= SEEN_XREG | SEEN_MEM; + EMIT3(0x8b, 0x5d, 0xf0 - K*4); + break; + case BPF_S_ST: /* mem[K] = A : mov %eax,off8(%rbp) */ + seen |= SEEN_MEM; + EMIT3(0x89, 0x45, 0xf0 - K*4); + break; + case BPF_S_STX: /* mem[K] = X : mov %ebx,off8(%rbp) */ + seen |= SEEN_XREG | SEEN_MEM; + EMIT3(0x89, 0x5d, 0xf0 - K*4); + break; + case BPF_S_LD_W_LEN: /* A = skb->len; */ + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4); + if (is_imm8(offsetof(struct sk_buff, len))) + /* mov off8(%rdi),%eax */ + EMIT3(0x8b, 0x47, offsetof(struct sk_buff, len)); + else { + EMIT2(0x8b, 0x87); + EMIT(offsetof(struct sk_buff, len), 4); + } + break; + case BPF_S_LDX_W_LEN: /* X = skb->len; */ + seen |= SEEN_XREG; + if (is_imm8(offsetof(struct sk_buff, len))) + /* mov off8(%rdi),%ebx */ + EMIT3(0x8b, 0x5f, offsetof(struct sk_buff, len)); + else { + EMIT2(0x8b, 0x9f); + EMIT(offsetof(struct sk_buff, len), 4); + } + break; + case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */ + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, protocol) != 2); + if (is_imm8(offsetof(struct sk_buff, protocol))) { + /* movzwl off8(%rdi),%eax */ + EMIT4(0x0f, 0xb7, 0x47, offsetof(struct sk_buff, protocol)); + } else { + EMIT3(0x0f, 0xb7, 0x87); /* movzwl off32(%rdi),%eax */ + EMIT(offsetof(struct sk_buff, protocol), 4); + } + EMIT2(0x86, 0xc4); /* ntohs() : xchg %al,%ah */ + break; + case BPF_S_ANC_IFINDEX: + if (is_imm8(offsetof(struct sk_buff, dev))) { + /* movq off8(%rdi),%rax */ + EMIT4(0x48, 0x8b, 0x47, offsetof(struct sk_buff, dev)); + } else { + EMIT3(0x48, 0x8b, 0x87); /* movq off32(%rdi),%rax */ + EMIT(offsetof(struct sk_buff, dev), 4); + } + EMIT3(0x48, 0x85, 0xc0); /* test %rax,%rax */ + EMIT_COND_JMP(X86_JE, cleanup_addr - (addrs[i] - 6)); + BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4); + EMIT2(0x8b, 0x80); /* mov off32(%rax),%eax */ + EMIT(offsetof(struct net_device, ifindex), 4); + break; + case BPF_S_ANC_MARK: + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4); + if (is_imm8(offsetof(struct sk_buff, mark))) { + /* mov off8(%rdi),%eax */ + EMIT3(0x8b, 0x47, offsetof(struct sk_buff, mark)); + } else { + EMIT2(0x8b, 0x87); + EMIT(offsetof(struct sk_buff, mark), 4); + } + break; + case BPF_S_ANC_RXHASH: + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4); + if (is_imm8(offsetof(struct sk_buff, rxhash))) { + /* mov off8(%rdi),%eax */ + EMIT3(0x8b, 0x47, offsetof(struct sk_buff, rxhash)); + } else { + EMIT2(0x8b, 0x87); + EMIT(offsetof(struct sk_buff, rxhash), 4); + } + break; + case BPF_S_ANC_QUEUE: + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, queue_mapping) != 2); + if (is_imm8(offsetof(struct sk_buff, queue_mapping))) { + /* movzwl off8(%rdi),%eax */ + EMIT4(0x0f, 0xb7, 0x47, offsetof(struct sk_buff, queue_mapping)); + } else { + EMIT3(0x0f, 0xb7, 0x87); /* movzwl off32(%rdi),%eax */ + EMIT(offsetof(struct sk_buff, queue_mapping), 4); + } + break; + case BPF_S_ANC_CPU: +#ifdef CONFIG_SMP + EMIT4(0x65, 0x8b, 0x04, 0x25); /* mov %gs:off32,%eax */ + EMIT((u32)(unsigned long)&cpu_number, 4); /* A = smp_processor_id(); */ +#else + CLEAR_A(); +#endif + break; + case BPF_S_LD_W_ABS: + func = sk_load_word; +common_load: seen |= SEEN_DATAREF; + if ((int)K < 0) + goto out; + t_offset = func - (image + addrs[i]); + EMIT1_off32(0xbe, K); /* mov imm32,%esi */ + EMIT1_off32(0xe8, t_offset); /* call */ + break; + case BPF_S_LD_H_ABS: + func = sk_load_half; + goto common_load; + case BPF_S_LD_B_ABS: + func = sk_load_byte; + goto common_load; + case BPF_S_LDX_B_MSH: + if ((int)K < 0) { + if (pc_ret0 != -1) { + EMIT_JMP(addrs[pc_ret0] - addrs[i]); + break; + } + CLEAR_A(); + EMIT_JMP(cleanup_addr - addrs[i]); + break; + } + seen |= SEEN_DATAREF | SEEN_XREG; + t_offset = sk_load_byte_msh - (image + addrs[i]); + EMIT1_off32(0xbe, K); /* mov imm32,%esi */ + EMIT1_off32(0xe8, t_offset); /* call sk_load_byte_msh */ + break; + case BPF_S_LD_W_IND: + func = sk_load_word_ind; +common_load_ind: seen |= SEEN_DATAREF | SEEN_XREG; + t_offset = func - (image + addrs[i]); + EMIT1_off32(0xbe, K); /* mov imm32,%esi */ + EMIT1_off32(0xe8, t_offset); /* call sk_load_xxx_ind */ + break; + case BPF_S_LD_H_IND: + func = sk_load_half_ind; + goto common_load_ind; + case BPF_S_LD_B_IND: + func = sk_load_byte_ind; + goto common_load_ind; + case BPF_S_JMP_JA: + t_offset = addrs[i + K] - addrs[i]; + EMIT_JMP(t_offset); + break; + COND_SEL(BPF_S_JMP_JGT_K, X86_JA, X86_JBE); + COND_SEL(BPF_S_JMP_JGE_K, X86_JAE, X86_JB); + COND_SEL(BPF_S_JMP_JEQ_K, X86_JE, X86_JNE); + COND_SEL(BPF_S_JMP_JSET_K,X86_JNE, X86_JE); + COND_SEL(BPF_S_JMP_JGT_X, X86_JA, X86_JBE); + COND_SEL(BPF_S_JMP_JGE_X, X86_JAE, X86_JB); + COND_SEL(BPF_S_JMP_JEQ_X, X86_JE, X86_JNE); + COND_SEL(BPF_S_JMP_JSET_X,X86_JNE, X86_JE); + +cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; + t_offset = addrs[i + filter[i].jt] - addrs[i]; + + /* same targets, can avoid doing the test :) */ + if (filter[i].jt == filter[i].jf) { + EMIT_JMP(t_offset); + break; + } + + switch (filter[i].code) { + case BPF_S_JMP_JGT_X: + case BPF_S_JMP_JGE_X: + case BPF_S_JMP_JEQ_X: + seen |= SEEN_XREG; + EMIT2(0x39, 0xd8); /* cmp %ebx,%eax */ + break; + case BPF_S_JMP_JSET_X: + seen |= SEEN_XREG; + EMIT2(0x85, 0xd8); /* test %ebx,%eax */ + break; + case BPF_S_JMP_JEQ_K: + if (K == 0) { + EMIT2(0x85, 0xc0); /* test %eax,%eax */ + break; + } + case BPF_S_JMP_JGT_K: + case BPF_S_JMP_JGE_K: + if (K <= 127) + EMIT3(0x83, 0xf8, K); /* cmp imm8,%eax */ + else + EMIT1_off32(0x3d, K); /* cmp imm32,%eax */ + break; + case BPF_S_JMP_JSET_K: + if (K <= 0xFF) + EMIT2(0xa8, K); /* test imm8,%al */ + else if (!(K & 0xFFFF00FF)) + EMIT3(0xf6, 0xc4, K >> 8); /* test imm8,%ah */ + else if (K <= 0xFFFF) { + EMIT2(0x66, 0xa9); /* test imm16,%ax */ + EMIT(K, 2); + } else { + EMIT1_off32(0xa9, K); /* test imm32,%eax */ + } + break; + } + if (filter[i].jt != 0) { + if (filter[i].jf) + t_offset += is_near(f_offset) ? 2 : 6; + EMIT_COND_JMP(t_op, t_offset); + if (filter[i].jf) + EMIT_JMP(f_offset); + break; + } + EMIT_COND_JMP(f_op, f_offset); + break; + default: + /* hmm, too complex filter, give up with jit compiler */ + goto out; + } + ilen = prog - temp; + if (image) { + if (unlikely(proglen + ilen > oldproglen)) { + pr_err("bpb_jit_compile fatal error\n"); + kfree(addrs); + module_free(NULL, image); + return; + } + memcpy(image + proglen, temp, ilen); + } + proglen += ilen; + addrs[i] = proglen; + prog = temp; + } + /* last bpf instruction is always a RET : + * use it to give the cleanup instruction(s) addr + */ + cleanup_addr = proglen - 1; /* ret */ + if (seen) + cleanup_addr -= 1; /* leaveq */ + if (seen & SEEN_XREG) + cleanup_addr -= 4; /* mov -8(%rbp),%rbx */ + + if (image) { + WARN_ON(proglen != oldproglen); + break; + } + if (proglen == oldproglen) { + image = module_alloc(max_t(unsigned int, + proglen, + sizeof(struct work_struct))); + if (!image) + goto out; + } + oldproglen = proglen; + } + if (bpf_jit_enable > 1) + pr_err("flen=%d proglen=%u pass=%d image=%p\n", + flen, proglen, pass, image); + + if (image) { + if (bpf_jit_enable > 1) + print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_ADDRESS, + 16, 1, image, proglen, false); + + bpf_flush_icache(image, image + proglen); + + fp->bpf_func = (void *)image; + } +out: + kfree(addrs); + return; +} + +static void jit_free_defer(struct work_struct *arg) +{ + module_free(NULL, arg); +} + +/* run from softirq, we must use a work_struct to call + * module_free() from process context + */ +void bpf_jit_free(struct sk_filter *fp) +{ + if (fp->bpf_func != sk_run_filter) { + struct work_struct *work = (struct work_struct *)fp->bpf_func; + + INIT_WORK(work, jit_free_defer); + schedule_work(work); + } +} diff --git a/include/linux/filter.h b/include/linux/filter.h index 45266b75409a..4609b85e559d 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -135,6 +135,8 @@ struct sk_filter { atomic_t refcnt; unsigned int len; /* Number of filter blocks */ + unsigned int (*bpf_func)(const struct sk_buff *skb, + const struct sock_filter *filter); struct rcu_head rcu; struct sock_filter insns[0]; }; @@ -153,6 +155,80 @@ extern unsigned int sk_run_filter(const struct sk_buff *skb, extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk); extern int sk_detach_filter(struct sock *sk); extern int sk_chk_filter(struct sock_filter *filter, int flen); + +#ifdef CONFIG_BPF_JIT +extern void bpf_jit_compile(struct sk_filter *fp); +extern void bpf_jit_free(struct sk_filter *fp); +#define SK_RUN_FILTER(FILTER, SKB) (*FILTER->bpf_func)(SKB, FILTER->insns) +#else +static inline void bpf_jit_compile(struct sk_filter *fp) +{ +} +static inline void bpf_jit_free(struct sk_filter *fp) +{ +} +#define SK_RUN_FILTER(FILTER, SKB) sk_run_filter(SKB, FILTER->insns) +#endif + +enum { + BPF_S_RET_K = 1, + BPF_S_RET_A, + BPF_S_ALU_ADD_K, + BPF_S_ALU_ADD_X, + BPF_S_ALU_SUB_K, + BPF_S_ALU_SUB_X, + BPF_S_ALU_MUL_K, + BPF_S_ALU_MUL_X, + BPF_S_ALU_DIV_X, + BPF_S_ALU_AND_K, + BPF_S_ALU_AND_X, + BPF_S_ALU_OR_K, + BPF_S_ALU_OR_X, + BPF_S_ALU_LSH_K, + BPF_S_ALU_LSH_X, + BPF_S_ALU_RSH_K, + BPF_S_ALU_RSH_X, + BPF_S_ALU_NEG, + BPF_S_LD_W_ABS, + BPF_S_LD_H_ABS, + BPF_S_LD_B_ABS, + BPF_S_LD_W_LEN, + BPF_S_LD_W_IND, + BPF_S_LD_H_IND, + BPF_S_LD_B_IND, + BPF_S_LD_IMM, + BPF_S_LDX_W_LEN, + BPF_S_LDX_B_MSH, + BPF_S_LDX_IMM, + BPF_S_MISC_TAX, + BPF_S_MISC_TXA, + BPF_S_ALU_DIV_K, + BPF_S_LD_MEM, + BPF_S_LDX_MEM, + BPF_S_ST, + BPF_S_STX, + BPF_S_JMP_JA, + BPF_S_JMP_JEQ_K, + BPF_S_JMP_JEQ_X, + BPF_S_JMP_JGE_K, + BPF_S_JMP_JGE_X, + BPF_S_JMP_JGT_K, + BPF_S_JMP_JGT_X, + BPF_S_JMP_JSET_K, + BPF_S_JMP_JSET_X, + /* Ancillary data */ + BPF_S_ANC_PROTOCOL, + BPF_S_ANC_PKTTYPE, + BPF_S_ANC_IFINDEX, + BPF_S_ANC_NLATTR, + BPF_S_ANC_NLATTR_NEST, + BPF_S_ANC_MARK, + BPF_S_ANC_QUEUE, + BPF_S_ANC_HATYPE, + BPF_S_ANC_RXHASH, + BPF_S_ANC_CPU, +}; + #endif /* __KERNEL__ */ #endif /* __LINUX_FILTER_H__ */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index cb8178ab3c52..364bcf212f71 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2514,6 +2514,7 @@ extern struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, extern int netdev_max_backlog; extern int netdev_tstamp_prequeue; extern int weight_p; +extern int bpf_jit_enable; extern int netdev_set_master(struct net_device *dev, struct net_device *master); extern int netdev_set_bond_master(struct net_device *dev, struct net_device *master); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index d0ae90af0b40..79aafbbf430a 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -391,8 +391,8 @@ struct sk_buff { __u32 rxhash; + __u16 queue_mapping; kmemcheck_bitfield_begin(flags2); - __u16 queue_mapping:16; #ifdef CONFIG_IPV6_NDISC_NODETYPE __u8 ndisc_nodetype:2; #endif diff --git a/net/Kconfig b/net/Kconfig index 79cabf1ee68b..745fb02d2fda 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -232,6 +232,19 @@ config XPS depends on SMP && SYSFS && USE_GENERIC_SMP_HELPERS default y +config HAVE_BPF_JIT + bool + +config BPF_JIT + bool "enable BPF Just In Time compiler" + depends on HAVE_BPF_JIT + ---help--- + Berkeley Packet Filter filtering capabilities are normally handled + by an interpreter. This option allows kernel to generate a native + code when filter is loaded in memory. This should speedup + packet sniffing (libpcap/tcpdump). Note : Admin should enable + this feature changing /proc/sys/net/core/bpf_jit_enable + menu "Network testing" config NET_PKTGEN diff --git a/net/core/filter.c b/net/core/filter.c index afb8afb066bb..0eb8c4466eaa 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -39,65 +39,6 @@ #include #include -enum { - BPF_S_RET_K = 1, - BPF_S_RET_A, - BPF_S_ALU_ADD_K, - BPF_S_ALU_ADD_X, - BPF_S_ALU_SUB_K, - BPF_S_ALU_SUB_X, - BPF_S_ALU_MUL_K, - BPF_S_ALU_MUL_X, - BPF_S_ALU_DIV_X, - BPF_S_ALU_AND_K, - BPF_S_ALU_AND_X, - BPF_S_ALU_OR_K, - BPF_S_ALU_OR_X, - BPF_S_ALU_LSH_K, - BPF_S_ALU_LSH_X, - BPF_S_ALU_RSH_K, - BPF_S_ALU_RSH_X, - BPF_S_ALU_NEG, - BPF_S_LD_W_ABS, - BPF_S_LD_H_ABS, - BPF_S_LD_B_ABS, - BPF_S_LD_W_LEN, - BPF_S_LD_W_IND, - BPF_S_LD_H_IND, - BPF_S_LD_B_IND, - BPF_S_LD_IMM, - BPF_S_LDX_W_LEN, - BPF_S_LDX_B_MSH, - BPF_S_LDX_IMM, - BPF_S_MISC_TAX, - BPF_S_MISC_TXA, - BPF_S_ALU_DIV_K, - BPF_S_LD_MEM, - BPF_S_LDX_MEM, - BPF_S_ST, - BPF_S_STX, - BPF_S_JMP_JA, - BPF_S_JMP_JEQ_K, - BPF_S_JMP_JEQ_X, - BPF_S_JMP_JGE_K, - BPF_S_JMP_JGE_X, - BPF_S_JMP_JGT_K, - BPF_S_JMP_JGT_X, - BPF_S_JMP_JSET_K, - BPF_S_JMP_JSET_X, - /* Ancillary data */ - BPF_S_ANC_PROTOCOL, - BPF_S_ANC_PKTTYPE, - BPF_S_ANC_IFINDEX, - BPF_S_ANC_NLATTR, - BPF_S_ANC_NLATTR_NEST, - BPF_S_ANC_MARK, - BPF_S_ANC_QUEUE, - BPF_S_ANC_HATYPE, - BPF_S_ANC_RXHASH, - BPF_S_ANC_CPU, -}; - /* No hurry in this branch */ static void *__load_pointer(const struct sk_buff *skb, int k, unsigned int size) { @@ -145,7 +86,7 @@ int sk_filter(struct sock *sk, struct sk_buff *skb) rcu_read_lock(); filter = rcu_dereference(sk->sk_filter); if (filter) { - unsigned int pkt_len = sk_run_filter(skb, filter->insns); + unsigned int pkt_len = SK_RUN_FILTER(filter, skb); err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM; } @@ -638,6 +579,7 @@ void sk_filter_release_rcu(struct rcu_head *rcu) { struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); + bpf_jit_free(fp); kfree(fp); } EXPORT_SYMBOL(sk_filter_release_rcu); @@ -672,6 +614,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) atomic_set(&fp->refcnt, 1); fp->len = fprog->len; + fp->bpf_func = sk_run_filter; err = sk_chk_filter(fp->insns, fp->len); if (err) { @@ -679,6 +622,8 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) return err; } + bpf_jit_compile(fp); + old_fp = rcu_dereference_protected(sk->sk_filter, sock_owned_by_user(sk)); rcu_assign_pointer(sk->sk_filter, fp); diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 385b6095fdc4..a829e3f60aeb 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -122,6 +122,15 @@ static struct ctl_table net_core_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, +#ifdef CONFIG_BPF_JIT + { + .procname = "bpf_jit_enable", + .data = &bpf_jit_enable, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, +#endif { .procname = "netdev_tstamp_prequeue", .data = &netdev_tstamp_prequeue, diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index b5362e96022b..549527bca87a 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -538,7 +538,7 @@ static inline unsigned int run_filter(const struct sk_buff *skb, rcu_read_lock(); filter = rcu_dereference(sk->sk_filter); if (filter != NULL) - res = sk_run_filter(skb, filter->insns); + res = SK_RUN_FILTER(filter, skb); rcu_read_unlock(); return res; -- cgit v1.2.3-58-ga151 From b6020ba055c7f1ca901dc8751ecc7c9de58164db Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Thu, 28 Apr 2011 12:07:53 +0200 Subject: Bluetooth: Add definitions for link key types Introduce the link key types defs and use them instead of magic numbers. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 9 +++++++++ net/bluetooth/hci_core.c | 2 +- net/bluetooth/hci_event.c | 7 ++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 6138e313d175..e0a3cf1234b2 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -246,6 +246,15 @@ enum { #define HCI_AT_GENERAL_BONDING 0x04 #define HCI_AT_GENERAL_BONDING_MITM 0x05 +/* Link Key types */ +#define HCI_LK_COMBINATION 0x00 +#define HCI_LK_LOCAL_UNIT 0x01 +#define HCI_LK_REMOTE_UNIT 0x02 +#define HCI_LK_DEBUG_COMBINATION 0x03 +#define HCI_LK_UNAUTH_COMBINATION 0x04 +#define HCI_LK_AUTH_COMBINATION 0x05 +#define HCI_LK_CHANGED_COMBINATION 0x06 + /* ----- HCI Commands ---- */ #define HCI_OP_NOP 0x0000 diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 98aa24b92c58..07d0ba35b9a5 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1050,7 +1050,7 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, if (new_key) mgmt_new_key(hdev->id, key, old_key_type); - if (type == 0x06) + if (type == HCI_LK_CHANGED_COMBINATION) key->type = old_key_type; return 0; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index e64a3de70d77..fbbb63f8a897 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2053,15 +2053,16 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff BT_DBG("%s found key type %u for %s", hdev->name, key->type, batostr(&ev->bdaddr)); - if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) { + if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && + key->type == HCI_LK_DEBUG_COMBINATION) { BT_DBG("%s ignoring debug key", hdev->name); goto not_found; } conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); - if (key->type == 0x04 && conn && conn->auth_type != 0xff && - (conn->auth_type & 0x01)) { + if (key->type == HCI_LK_UNAUTH_COMBINATION && conn && + conn->auth_type != 0xff && (conn->auth_type & 0x01)) { BT_DBG("%s ignoring unauthenticated key", hdev->name); goto not_found; } -- cgit v1.2.3-58-ga151 From 9003c4e220c2954a53c5da0d739ed15a46c13429 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Thu, 28 Apr 2011 12:07:54 +0200 Subject: Bluetooth: Don't modify sec_level if auth failed If authentication fails the security level should stay as it was set before the process has started. Setting BT_SECURITY_LOW can hide real security level on a link eg. having BT_SECURITY_MEDIUM on the link, re-authenticate with failure to get BT_SECURITY_HIGH, as a result we get BT_SECURITY_LOW on the link while the real security is still medium. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index fbbb63f8a897..35f98980070c 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1459,7 +1459,6 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s conn->sec_level = conn->pending_sec_level; } else { mgmt_auth_failed(hdev->id, &conn->dst, ev->status); - conn->sec_level = BT_SECURITY_LOW; } clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); -- cgit v1.2.3-58-ga151 From 13d39315c22b128f4796fc008b04914a7c32bb1a Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Thu, 28 Apr 2011 12:07:55 +0200 Subject: Bluetooth: Map sec_level to link key requirements Keep the link key type together with connection and use it to map security level to link key requirements. Authenticate and/or encrypt connection if the link is insufficiently secure. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/hci_conn.c | 61 +++++++++++++++++++++++++++++++++------- net/bluetooth/hci_event.c | 4 +++ 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 69967e540c96..2da2eb9f53ac 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -226,6 +226,7 @@ struct hci_conn { __u16 pkt_type; __u16 link_policy; __u32 link_mode; + __u8 key_type; __u8 auth_type; __u8 sec_level; __u8 pending_sec_level; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 7a6f56b2f49d..74cd755b38a7 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -287,6 +287,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) conn->auth_type = HCI_AT_GENERAL_BONDING; conn->io_capability = hdev->io_capability; conn->remote_auth = 0xff; + conn->key_type = 0xff; conn->power_save = 1; conn->disc_timeout = HCI_DISCONN_TIMEOUT; @@ -535,32 +536,72 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) return 0; } +/* Encrypt the the link */ +static void hci_conn_encrypt(struct hci_conn *conn) +{ + BT_DBG("conn %p", conn); + + if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { + struct hci_cp_set_conn_encrypt cp; + cp.handle = cpu_to_le16(conn->handle); + cp.encrypt = 0x01; + hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), + &cp); + } +} + /* Enable security */ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) { BT_DBG("conn %p", conn); + /* For sdp we don't need the link key. */ if (sec_level == BT_SECURITY_SDP) return 1; + /* For non 2.1 devices and low security level we don't need the link + key. */ if (sec_level == BT_SECURITY_LOW && (!conn->ssp_mode || !conn->hdev->ssp_mode)) return 1; - if (conn->link_mode & HCI_LM_ENCRYPT) - return hci_conn_auth(conn, sec_level, auth_type); - + /* For other security levels we need the link key. */ + if (!(conn->link_mode & HCI_LM_AUTH)) + goto auth; + + /* An authenticated combination key has sufficient security for any + security level. */ + if (conn->key_type == HCI_LK_AUTH_COMBINATION) + goto encrypt; + + /* An unauthenticated combination key has sufficient security for + security level 1 and 2. */ + if (conn->key_type == HCI_LK_UNAUTH_COMBINATION && + (sec_level == BT_SECURITY_MEDIUM || + sec_level == BT_SECURITY_LOW)) + goto encrypt; + + /* A combination key has always sufficient security for the security + levels 1 or 2. High security level requires the combination key + is generated using maximum PIN code length (16). + For pre 2.1 units. */ + if (conn->key_type == HCI_LK_COMBINATION && + (sec_level != BT_SECURITY_HIGH || + conn->pin_length == 16)) + goto encrypt; + +auth: if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) return 0; - if (hci_conn_auth(conn, sec_level, auth_type)) { - struct hci_cp_set_conn_encrypt cp; - cp.handle = cpu_to_le16(conn->handle); - cp.encrypt = 1; - hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, - sizeof(cp), &cp); - } + hci_conn_auth(conn, sec_level, auth_type); + return 0; + +encrypt: + if (conn->link_mode & HCI_LM_ENCRYPT) + return 1; + hci_conn_encrypt(conn); return 0; } EXPORT_SYMBOL(hci_conn_security); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 35f98980070c..655af8bc60e2 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2095,6 +2095,10 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff hci_conn_hold(conn); conn->disc_timeout = HCI_DISCONN_TIMEOUT; pin_len = conn->pin_length; + + if (ev->key_type != HCI_LK_CHANGED_COMBINATION) + conn->key_type = ev->key_type; + hci_conn_put(conn); } -- cgit v1.2.3-58-ga151 From 60b83f571cf17a7a8ca9ddf2090db63e6a594571 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Thu, 28 Apr 2011 12:07:56 +0200 Subject: Bluetooth: Ignore key unauthenticated for high security High security level for pre v2.1 devices requires combination link key authenticated by at least 16 digit PIN code. It's also necessary to update key_type and pin_length when the key exists and is sufficently secured for the connection as there will be no link key notify event in that case. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 655af8bc60e2..40e96cd79e4a 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2059,11 +2059,23 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff } conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); + if (conn) { + if (key->type == HCI_LK_UNAUTH_COMBINATION && + conn->auth_type != 0xff && + (conn->auth_type & 0x01)) { + BT_DBG("%s ignoring unauthenticated key", hdev->name); + goto not_found; + } - if (key->type == HCI_LK_UNAUTH_COMBINATION && conn && - conn->auth_type != 0xff && (conn->auth_type & 0x01)) { - BT_DBG("%s ignoring unauthenticated key", hdev->name); - goto not_found; + if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && + conn->pending_sec_level == BT_SECURITY_HIGH) { + BT_DBG("%s ignoring key unauthenticated for high \ + security", hdev->name); + goto not_found; + } + + conn->key_type = key->type; + conn->pin_length = key->pin_len; } bacpy(&cp.bdaddr, &ev->bdaddr); -- cgit v1.2.3-58-ga151 From 58797bf77234154a84827186bda316a1205bde05 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Thu, 28 Apr 2011 12:07:58 +0200 Subject: Bluetooth: Respect local MITM req in io_cap reply If host requires MITM protection notify that to controller in io capabilities reply even if the remote device requires no bonding. If it is not respected, host can get an unauthenticated link key while it expects authenticated one. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 40e96cd79e4a..9d50e90993ca 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2397,7 +2397,7 @@ static inline u8 hci_get_auth_req(struct hci_conn *conn) /* If remote requests no-bonding follow that lead */ if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) - return 0x00; + return conn->remote_auth | (conn->auth_type & 0x01); return conn->auth_type; } -- cgit v1.2.3-58-ga151 From a770bb5aea84ee2509d4775f9959665f96da3b9d Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Thu, 28 Apr 2011 12:07:59 +0200 Subject: Bluetooth: Add secure flag for mgmt_pin_code_req Extend the mgmt_pin_code_request interface to require secure pin code (16 digit) for authentication. This is a kernel part of the secure pin code requirement notification to user space agent. Code styling fix by Johan Hedberg. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 2 +- include/net/bluetooth/mgmt.h | 1 + net/bluetooth/hci_event.c | 12 ++++++++++-- net/bluetooth/mgmt.c | 3 ++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 2da2eb9f53ac..2995e2e63512 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -777,7 +777,7 @@ int mgmt_connected(u16 index, bdaddr_t *bdaddr); int mgmt_disconnected(u16 index, bdaddr_t *bdaddr); int mgmt_disconnect_failed(u16 index); int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status); -int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr); +int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure); int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value); diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 743440615349..0e7de636035d 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -253,6 +253,7 @@ struct mgmt_ev_connect_failed { #define MGMT_EV_PIN_CODE_REQUEST 0x000E struct mgmt_ev_pin_code_request { bdaddr_t bdaddr; + __u8 secure; } __packed; #define MGMT_EV_USER_CONFIRM_REQUEST 0x000F diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 9d50e90993ca..577d638600df 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2022,8 +2022,16 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(ev->bdaddr), &ev->bdaddr); - if (test_bit(HCI_MGMT, &hdev->flags)) - mgmt_pin_code_request(hdev->id, &ev->bdaddr); + if (test_bit(HCI_MGMT, &hdev->flags)) { + u8 secure; + + if (conn->pending_sec_level == BT_SECURITY_HIGH) + secure = 1; + else + secure = 0; + + mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure); + } hci_dev_unlock(hdev); } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 4542396fc856..a7b4937d761c 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1942,11 +1942,12 @@ int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status) return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL); } -int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr) +int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure) { struct mgmt_ev_pin_code_request ev; bacpy(&ev.bdaddr, bdaddr); + ev.secure = secure; return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev), NULL); -- cgit v1.2.3-58-ga151 From 8178d38b704f0a08a74b030c35e6eca5f5019d3d Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 18 Apr 2011 14:22:28 +0300 Subject: mac80211: allow low level drivers to report packet loss Add API that allows low level drivers to notify mac80211 about TX packet loss. This is useful when there are FW triggers to notify the low level driver about these events. Signed-off-by: Arik Nemtsov Signed-off-by: John W. Linville --- include/net/mac80211.h | 11 +++++++++++ net/mac80211/status.c | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 162363b6cb62..8aad6b37c689 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2291,6 +2291,17 @@ static inline void ieee80211_tx_status_ni(struct ieee80211_hw *hw, void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb); +/** + * ieee80211_report_low_ack - report non-responding station + * + * When operating in AP-mode, call this function to report a non-responding + * connected STA. + * + * @sta: the non-responding connected sta + * @num_packets: number of packets sent to @sta without a response + */ +void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets); + /** * ieee80211_beacon_get_tim - beacon generation function * @hw: pointer obtained from ieee80211_alloc_hw(). diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 3ed3c835fbbf..1658efaa2e8e 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -446,3 +446,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) dev_kfree_skb(skb); } EXPORT_SYMBOL(ieee80211_tx_status); + +void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets) +{ + struct sta_info *sta = container_of(pubsta, struct sta_info, sta); + cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr, + num_packets, GFP_ATOMIC); +} +EXPORT_SYMBOL(ieee80211_report_low_ack); -- cgit v1.2.3-58-ga151 From 978f78bf71372a48785ac9407ebc10170f14f56c Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 26 Apr 2011 10:39:52 +0530 Subject: ath9k_hw: Move bt_stomp to hw from common. Move bt_stomp to ath9k_hw and add its support for latest chipsets. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/btcoex.c | 66 +++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/btcoex.h | 10 ++++ drivers/net/wireless/ath/ath9k/common.c | 31 ------------- drivers/net/wireless/ath/ath9k/common.h | 8 ---- drivers/net/wireless/ath/ath9k/gpio.c | 7 ++- drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 6 +-- 6 files changed, 82 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index d33bf204c995..71e9e4841fa2 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -209,3 +209,69 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah) ah->btcoex_hw.enabled = false; } EXPORT_SYMBOL(ath9k_hw_btcoex_disable); + +static void ar9003_btcoex_bt_stomp(struct ath_hw *ah, + enum ath_stomp_type stomp_type) +{ + ah->bt_coex_bt_weight[0] = AR9300_BT_WGHT; + ah->bt_coex_bt_weight[1] = AR9300_BT_WGHT; + ah->bt_coex_bt_weight[2] = AR9300_BT_WGHT; + ah->bt_coex_bt_weight[3] = AR9300_BT_WGHT; + + + switch (stomp_type) { + case ATH_BTCOEX_STOMP_ALL: + ah->bt_coex_wlan_weight[0] = AR9300_STOMP_ALL_WLAN_WGHT0; + ah->bt_coex_wlan_weight[1] = AR9300_STOMP_ALL_WLAN_WGHT1; + break; + case ATH_BTCOEX_STOMP_LOW: + ah->bt_coex_wlan_weight[0] = AR9300_STOMP_LOW_WLAN_WGHT0; + ah->bt_coex_wlan_weight[1] = AR9300_STOMP_LOW_WLAN_WGHT1; + break; + case ATH_BTCOEX_STOMP_NONE: + ah->bt_coex_wlan_weight[0] = AR9300_STOMP_NONE_WLAN_WGHT0; + ah->bt_coex_wlan_weight[1] = AR9300_STOMP_NONE_WLAN_WGHT1; + break; + + default: + ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "Invalid Stomptype\n"); + break; + } + + ath9k_hw_btcoex_enable(ah); +} + +/* + * Configures appropriate weight based on stomp type. + */ +void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, + enum ath_stomp_type stomp_type) +{ + if (AR_SREV_9300_20_OR_LATER(ah)) { + ar9003_btcoex_bt_stomp(ah, stomp_type); + return; + } + + switch (stomp_type) { + case ATH_BTCOEX_STOMP_ALL: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_ALL_WLAN_WGHT); + break; + case ATH_BTCOEX_STOMP_LOW: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_LOW_WLAN_WGHT); + break; + case ATH_BTCOEX_STOMP_NONE: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_NONE_WLAN_WGHT); + break; + default: + ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "Invalid Stomptype\n"); + break; + } + + ath9k_hw_btcoex_enable(ah); +} +EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp); diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 588dfd464dd1..aac8fae50813 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h @@ -32,6 +32,14 @@ #define ATH_BT_CNT_THRESHOLD 3 #define ATH_BT_CNT_SCAN_THRESHOLD 15 +/* Defines the BT AR_BT_COEX_WGHT used */ +enum ath_stomp_type { + ATH_BTCOEX_NO_STOMP, + ATH_BTCOEX_STOMP_ALL, + ATH_BTCOEX_STOMP_LOW, + ATH_BTCOEX_STOMP_NONE +}; + enum ath_btcoex_scheme { ATH_BTCOEX_CFG_NONE, ATH_BTCOEX_CFG_2WIRE, @@ -57,5 +65,7 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, u32 wlan_weight); void ath9k_hw_btcoex_enable(struct ath_hw *ah); void ath9k_hw_btcoex_disable(struct ath_hw *ah); +void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, + enum ath_stomp_type stomp_type); #endif diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 16ba8c67fbd5..74535e6dfb82 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -158,37 +158,6 @@ int ath9k_cmn_count_streams(unsigned int chainmask, int max) } EXPORT_SYMBOL(ath9k_cmn_count_streams); -/* - * Configures appropriate weight based on stomp type. - */ -void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, - enum ath_stomp_type stomp_type) -{ - struct ath_hw *ah = common->ah; - - switch (stomp_type) { - case ATH_BTCOEX_STOMP_ALL: - ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_ALL_WLAN_WGHT); - break; - case ATH_BTCOEX_STOMP_LOW: - ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_LOW_WLAN_WGHT); - break; - case ATH_BTCOEX_STOMP_NONE: - ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_NONE_WLAN_WGHT); - break; - default: - ath_dbg(common, ATH_DBG_BTCOEX, - "Invalid Stomptype\n"); - break; - } - - ath9k_hw_btcoex_enable(ah); -} -EXPORT_SYMBOL(ath9k_cmn_btcoex_bt_stomp); - void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, u16 new_txpow, u16 *txpower) { diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index b2f7b5f89097..5124f1420b3a 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -50,14 +50,6 @@ #define ATH_EP_RND(x, mul) \ ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) -/* Defines the BT AR_BT_COEX_WGHT used */ -enum ath_stomp_type { - ATH_BTCOEX_NO_STOMP, - ATH_BTCOEX_STOMP_ALL, - ATH_BTCOEX_STOMP_LOW, - ATH_BTCOEX_STOMP_NONE -}; - int ath9k_cmn_padpos(__le16 frame_control); int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 2c59452a7207..3a4ddd19e60e 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -176,7 +176,6 @@ static void ath_btcoex_period_timer(unsigned long data) struct ath_softc *sc = (struct ath_softc *) data; struct ath_hw *ah = sc->sc_ah; struct ath_btcoex *btcoex = &sc->btcoex; - struct ath_common *common = ath9k_hw_common(ah); u32 timer_period; bool is_btscan; @@ -186,7 +185,7 @@ static void ath_btcoex_period_timer(unsigned long data) spin_lock_bh(&btcoex->btcoex_lock); - ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : + ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : btcoex->bt_stomp_type); spin_unlock_bh(&btcoex->btcoex_lock); @@ -224,9 +223,9 @@ static void ath_btcoex_no_stomp_timer(void *arg) spin_lock_bh(&btcoex->btcoex_lock); if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) - ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); + ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) - ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW); + ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); spin_unlock_bh(&btcoex->btcoex_lock); } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index d051a4263e0c..26ede1daa304 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -77,7 +77,7 @@ static void ath_btcoex_period_work(struct work_struct *work) return; } - ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : + ath9k_hw_btcoex_bt_stomp(priv->ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : btcoex->bt_stomp_type); timer_period = is_btscan ? btcoex->btscan_no_stomp : @@ -105,9 +105,9 @@ static void ath_btcoex_duty_cycle_work(struct work_struct *work) "time slice work for bt and wlan\n"); if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) - ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); + ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) - ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW); + ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); } void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv) -- cgit v1.2.3-58-ga151 From a6ef530f2b0bc7e871e8c2f2b2a0905eed57fead Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 26 Apr 2011 10:39:53 +0530 Subject: ath9k_hw: Add support for btcoexistence in AR9300. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/btcoex.c | 34 ++++++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath9k/btcoex.h | 10 +++++++--- drivers/net/wireless/ath/ath9k/hw.c | 24 +++++++++++++++-------- drivers/net/wireless/ath/ath9k/hw.h | 5 +++++ drivers/net/wireless/ath/ath9k/reg.h | 16 ++++++++++++++++ 5 files changed, 75 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 71e9e4841fa2..23f15a7ca7f1 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -51,6 +51,10 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) .bt_hold_rx_clear = true, }; u32 i; + bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity; + + if (AR_SREV_9300_20_OR_LATER(ah)) + rxclear_polarity = !ath_bt_config.bt_rxclear_polarity; btcoex_hw->bt_coex_mode = (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) | @@ -59,7 +63,7 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | SM(ath_bt_config.bt_mode, AR_BT_MODE) | SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) | - SM(ath_bt_config.bt_rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | + SM(rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) | SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | SM(qnum, AR_BT_QCU_THRESH); @@ -142,6 +146,7 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, } EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); + static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) { struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; @@ -152,9 +157,22 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) * enable coex 3-wire */ REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_hw->bt_coex_mode); - REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2); + + if (AR_SREV_9300_20_OR_LATER(ah)) { + REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, ah->bt_coex_wlan_weight[0]); + REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, ah->bt_coex_wlan_weight[1]); + REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, ah->bt_coex_bt_weight[0]); + REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, ah->bt_coex_bt_weight[1]); + REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, ah->bt_coex_bt_weight[2]); + REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, ah->bt_coex_bt_weight[3]); + + } else + REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); + + + if (AR_SREV_9271(ah)) { val = REG_READ(ah, 0x50040); val &= 0xFFFFFEFF; @@ -202,8 +220,18 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah) if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) { REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); - REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); REG_WRITE(ah, AR_BT_COEX_MODE2, 0); + + if (AR_SREV_9300_20_OR_LATER(ah)) { + REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, 0); + REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, 0); + REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, 0); + REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, 0); + REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, 0); + REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, 0); + } else + REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); + } ah->btcoex_hw.enabled = false; diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index aac8fae50813..a9efca83d676 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h @@ -19,9 +19,13 @@ #include "hw.h" -#define ATH_WLANACTIVE_GPIO 5 -#define ATH_BTACTIVE_GPIO 6 -#define ATH_BTPRIORITY_GPIO 7 +#define ATH_WLANACTIVE_GPIO_9280 5 +#define ATH_BTACTIVE_GPIO_9280 6 +#define ATH_BTPRIORITY_GPIO_9285 7 + +#define ATH_WLANACTIVE_GPIO_9300 5 +#define ATH_BTACTIVE_GPIO_9300 4 +#define ATH_BTPRIORITY_GPIO_9300 8 #define ATH_BTCOEX_DEF_BT_PERIOD 45 #define ATH_BTCOEX_DEF_DUTY_CYCLE 55 diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index e99e319feaa8..58f3d4210338 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1956,15 +1956,23 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) else pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; - if (AR_SREV_9280_20_OR_LATER(ah) && common->btcoex_enabled) { - btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; - btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO; - - if (AR_SREV_9285(ah)) { + if (common->btcoex_enabled) { + if (AR_SREV_9300_20_OR_LATER(ah)) { btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; - btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO; - } else { - btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE; + btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9300; + btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9300; + btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO_9300; + } else if (AR_SREV_9280_20_OR_LATER(ah)) { + btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9280; + btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9280; + + if (AR_SREV_9285(ah)) { + btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; + btcoex_hw->btpriority_gpio = + ATH_BTPRIORITY_GPIO_9285; + } else { + btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE; + } } } else { btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 6a028bd67116..34ed1bd0e855 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -56,6 +56,9 @@ #define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa #define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab +#define AR9300_NUM_BT_WEIGHTS 4 +#define AR9300_NUM_WLAN_WEIGHTS 4 + #define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) #define ATH_DEFAULT_NOISE_FLOOR -95 @@ -772,6 +775,8 @@ struct ath_hw { /* Bluetooth coexistance */ struct ath_btcoex_hw btcoex_hw; + u32 bt_coex_bt_weight[AR9300_NUM_BT_WEIGHTS]; + u32 bt_coex_wlan_weight[AR9300_NUM_WLAN_WEIGHTS]; u32 intr_txqs; u8 txchainmask; diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index d5cecdc6ca6e..456f3ec20fef 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1709,6 +1709,22 @@ enum { #define AR_BTCOEX_WL_WGHT 0xffff0000 #define AR_BTCOEX_WL_WGHT_S 16 +#define AR_BT_COEX_WL_WEIGHTS0 0x8174 +#define AR_BT_COEX_WL_WEIGHTS1 0x81c4 + +#define AR_BT_COEX_BT_WEIGHTS0 0x83ac +#define AR_BT_COEX_BT_WEIGHTS1 0x83b0 +#define AR_BT_COEX_BT_WEIGHTS2 0x83b4 +#define AR_BT_COEX_BT_WEIGHTS3 0x83b8 + +#define AR9300_BT_WGHT 0xcccc4444 +#define AR9300_STOMP_ALL_WLAN_WGHT0 0xfffffff0 +#define AR9300_STOMP_ALL_WLAN_WGHT1 0xfffffff0 +#define AR9300_STOMP_LOW_WLAN_WGHT0 0x88888880 +#define AR9300_STOMP_LOW_WLAN_WGHT1 0x88888880 +#define AR9300_STOMP_NONE_WLAN_WGHT0 0x00000000 +#define AR9300_STOMP_NONE_WLAN_WGHT1 0x00000000 + #define AR_BT_COEX_MODE2 0x817c #define AR_BT_BCN_MISS_THRESH 0x000000ff #define AR_BT_BCN_MISS_THRESH_S 0 -- cgit v1.2.3-58-ga151 From f78eb657f067ce87e19da94138d22cde8236c7db Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 26 Apr 2011 10:39:54 +0530 Subject: ath9k_hw: Enable generic timer interrupt. Generic timer interrupt was not triggered unless autosleep was disabled. Since autosleep is enabled in the newer chipsets, enable generic timer for using with bt coex logic. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/mac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index c8a4cedce805..9cf7a7d0e118 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -885,6 +885,9 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) mask |= AR_IMR_GENTMR; } + if (ints & ATH9K_INT_GENTIMER) + mask |= AR_IMR_GENTMR; + if (ints & (ATH9K_INT_BMISC)) { mask |= AR_IMR_BCNMISC; if (ints & ATH9K_INT_TIM) -- cgit v1.2.3-58-ga151 From a039a993496d79d09ae9709c82b545b9800954c9 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 26 Apr 2011 10:39:55 +0530 Subject: ath9k: Use ps wrappers for btcoex logic. Use ps wrappers before accessing hw registers in btcoex. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/gpio.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 3a4ddd19e60e..0349b3a1cc58 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -179,6 +179,7 @@ static void ath_btcoex_period_timer(unsigned long data) u32 timer_period; bool is_btscan; + ath9k_ps_wakeup(sc); ath_detect_bt_priority(sc); is_btscan = sc->sc_flags & SC_OP_BT_SCAN; @@ -201,6 +202,7 @@ static void ath_btcoex_period_timer(unsigned long data) btcoex->hw_timer_enabled = true; } + ath9k_ps_restore(sc); mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); } @@ -220,6 +222,7 @@ static void ath_btcoex_no_stomp_timer(void *arg) ath_dbg(common, ATH_DBG_BTCOEX, "no stomp timer running\n"); + ath9k_ps_wakeup(sc); spin_lock_bh(&btcoex->btcoex_lock); if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) @@ -228,6 +231,7 @@ static void ath_btcoex_no_stomp_timer(void *arg) ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); spin_unlock_bh(&btcoex->btcoex_lock); + ath9k_ps_restore(sc); } int ath_init_btcoex_timer(struct ath_softc *sc) -- cgit v1.2.3-58-ga151 From 47684808fd89d6809c0886e06f8ac324252499d8 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 26 Apr 2011 23:21:51 +0300 Subject: wl12xx: support FW TX inactivity triggers In AP mode we register for the MAX_TX_RETRY and INACTIVE_STA events. Both are reported to the upper layers as a TX failure in the offending stations. In STA mode we register only for the MAX_TX_RETRY event. A TX failure is interpreted as a loss of connection. Support for IEEE80211_HW_REPORTS_TX_ACK_STATUS has been removed to avoid the inherent race condition of a mac80211 TX failure counter in addition to the FW counter. This patch depends on "mac80211: allow low level driver to report packet loss" Signed-off-by: Arik Nemtsov Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/acx.c | 34 ++++++++++++++++++++++---- drivers/net/wireless/wl12xx/acx.h | 12 +++++++-- drivers/net/wireless/wl12xx/boot.c | 6 +++-- drivers/net/wireless/wl12xx/cmd.c | 2 +- drivers/net/wireless/wl12xx/conf.h | 12 +++++++-- drivers/net/wireless/wl12xx/event.c | 47 ++++++++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/event.h | 12 ++++++++- drivers/net/wireless/wl12xx/init.c | 6 ++++- drivers/net/wireless/wl12xx/main.c | 10 ++++++-- drivers/net/wireless/wl12xx/wl12xx.h | 1 - 10 files changed, 125 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index b277947400b5..a5c9c0aff83f 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -1524,22 +1524,46 @@ out: return ret; } -int wl1271_acx_max_tx_retry(struct wl1271 *wl) +int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) { - struct wl1271_acx_max_tx_retry *acx = NULL; + struct wl1271_acx_ap_max_tx_retry *acx = NULL; int ret; - wl1271_debug(DEBUG_ACX, "acx max tx retry"); + wl1271_debug(DEBUG_ACX, "acx ap max tx retry"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); if (!acx) return -ENOMEM; - acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries); + acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries); ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); if (ret < 0) { - wl1271_warning("acx max tx retry failed: %d", ret); + wl1271_warning("acx ap max tx retry failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} + +int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl) +{ + struct wl1271_acx_sta_max_tx_retry *acx = NULL; + int ret; + + wl1271_debug(DEBUG_ACX, "acx sta max tx retry"); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) + return -ENOMEM; + + acx->max_tx_retry = wl->conf.tx.max_tx_retries; + + ret = wl1271_cmd_configure(wl, ACX_CONS_TX_FAILURE, acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx sta max tx retry failed: %d", ret); goto out; } diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 0a40caeab2a2..942908cd53a3 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -1145,7 +1145,7 @@ struct wl1271_acx_fw_tsf_information { u8 padding[3]; } __packed; -struct wl1271_acx_max_tx_retry { +struct wl1271_acx_ap_max_tx_retry { struct acx_header header; /* @@ -1156,6 +1156,13 @@ struct wl1271_acx_max_tx_retry { u8 padding_1[2]; } __packed; +struct wl1271_acx_sta_max_tx_retry { + struct acx_header header; + + u8 max_tx_retry; + u8 padding_1[3]; +} __packed; + struct wl1271_acx_config_ps { struct acx_header header; @@ -1307,7 +1314,8 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl, int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, bool enable); int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); -int wl1271_acx_max_tx_retry(struct wl1271 *wl); +int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); +int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl); int wl1271_acx_config_ps(struct wl1271 *wl); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 2b0cf85788b3..d263ebb6f974 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -478,10 +478,12 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) DISCONNECT_EVENT_COMPLETE_ID | RSSI_SNR_TRIGGER_0_EVENT_ID | PSPOLL_DELIVERY_FAILURE_EVENT_ID | - SOFT_GEMINI_SENSE_EVENT_ID; + SOFT_GEMINI_SENSE_EVENT_ID | + MAX_TX_RETRY_EVENT_ID; if (wl->bss_type == BSS_TYPE_AP_BSS) - wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; + wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID | + INACTIVE_STA_EVENT_ID; else wl->event_mask |= DUMMY_PACKET_EVENT_ID; diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 246804428517..d48331682e7e 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -1070,7 +1070,7 @@ int wl1271_cmd_start_bss(struct wl1271 *wl) memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); - cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC); + cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); cmd->bss_index = WL1271_AP_BSS_INDEX; cmd->global_hlid = WL1271_AP_GLOBAL_HLID; cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 6c9e3a673e6c..d16094f2604f 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -683,10 +683,18 @@ struct conf_tx_settings { struct conf_tx_rate_class ap_bcst_conf; /* - * AP-mode - allow this number of TX retries to a station before an + * Allow this number of TX retries to a connected station/AP before an * event is triggered from FW. + * In AP-mode the hlids of unreachable stations are given in the + * "sta_tx_retry_exceeded" member in the event mailbox. */ - u16 ap_max_tx_retries; + u8 max_tx_retries; + + /* + * AP-mode - after this number of seconds a connected station is + * considered inactive. + */ + u16 ap_aging_period; /* * Configuration for TID parameters. diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index ae69330e807c..d7be3aec6fc3 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -174,6 +174,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) u32 vector; bool beacon_loss = false; bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); + bool disconnect_sta = false; + unsigned long sta_bitmap = 0; wl1271_event_mbox_dump(mbox); @@ -235,9 +237,54 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) wl1271_tx_dummy_packet(wl); } + /* + * "TX retries exceeded" has a different meaning according to mode. + * In AP mode the offending station is disconnected. In STA mode we + * report connection loss. + */ + if (vector & MAX_TX_RETRY_EVENT_ID) { + wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); + if (is_ap) { + sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); + disconnect_sta = true; + } else { + beacon_loss = true; + } + } + + if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) { + wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); + sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); + disconnect_sta = true; + } + if (wl->vif && beacon_loss) ieee80211_connection_loss(wl->vif); + if (is_ap && disconnect_sta) { + u32 num_packets = wl->conf.tx.max_tx_retries; + struct ieee80211_sta *sta; + const u8 *addr; + int h; + + for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS); + h < AP_MAX_LINKS; + h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) { + if (!wl1271_is_active_sta(wl, h)) + continue; + + addr = wl->links[h].addr; + + rcu_read_lock(); + sta = ieee80211_find_sta(wl->vif, addr); + if (sta) { + wl1271_debug(DEBUG_EVENT, "remove sta %d", h); + ieee80211_report_low_ack(sta, num_packets); + } + rcu_read_unlock(); + } + } + return 0; } diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h index b6cf06e565a4..7ae5a0821241 100644 --- a/drivers/net/wireless/wl12xx/event.h +++ b/drivers/net/wireless/wl12xx/event.h @@ -58,13 +58,16 @@ enum { CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), BSS_LOSE_EVENT_ID = BIT(18), REGAINED_BSS_EVENT_ID = BIT(19), - ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20), + MAX_TX_RETRY_EVENT_ID = BIT(20), /* STA: dummy paket for dynamic mem blocks */ DUMMY_PACKET_EVENT_ID = BIT(21), /* AP: STA remove complete */ STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), + /* STA: SG prediction */ SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), + /* AP: Inactive STA */ + INACTIVE_STA_EVENT_ID = BIT(23), SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), DBG_EVENT_ID = BIT(26), @@ -119,7 +122,11 @@ struct event_mailbox { /* AP FW only */ u8 hlid_removed; + + /* a bitmap of hlids for stations that have been inactive too long */ __le16 sta_aging_status; + + /* a bitmap of hlids for stations which didn't respond to TX */ __le16 sta_tx_retry_exceeded; u8 reserved_5[24]; @@ -130,4 +137,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl); int wl1271_event_handle(struct wl1271 *wl, u8 mbox); void wl1271_pspoll_work(struct work_struct *work); +/* Functions from main.c */ +bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid); + #endif diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index cf466074237d..ab3b1e21de29 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -375,6 +375,10 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) if (ret < 0) return ret; + ret = wl1271_acx_sta_max_tx_retry(wl); + if (ret < 0) + return ret; + ret = wl1271_acx_sta_mem_cfg(wl); if (ret < 0) return ret; @@ -441,7 +445,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_acx_max_tx_retry(wl); + ret = wl1271_acx_ap_max_tx_retry(wl); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 866453bc1d1f..0c69e959d0de 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -192,7 +192,8 @@ static struct conf_drv_settings default_conf = { .long_retry_limit = 10, .aflags = 0, }, - .ap_max_tx_retries = 100, + .max_tx_retries = 100, + .ap_aging_period = 300, .tid_conf_count = 4, .tid_conf = { [CONF_TX_AC_BE] = { @@ -2953,6 +2954,12 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); } +bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) +{ + int id = hlid - WL1271_AP_STA_HLID_START; + return test_bit(id, wl->ap_hlid_map); +} + static int wl1271_op_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) @@ -3535,7 +3542,6 @@ int wl1271_init_ieee80211(struct wl1271 *wl) IEEE80211_HW_HAS_RATE_CONTROL | IEEE80211_HW_CONNECTION_MONITOR | IEEE80211_HW_SUPPORTS_CQM_RSSI | - IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_AP_LINK_PS; wl->hw->wiphy->cipher_suites = cipher_suites; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index fb2b79fa42b4..7c521af58e7d 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -172,7 +172,6 @@ extern u32 wl12xx_debug_level; #define WL1271_PS_STA_MAX_BLOCKS (2 * 9) #define WL1271_AP_BSS_INDEX 0 -#define WL1271_AP_DEF_INACTIV_SEC 300 #define WL1271_AP_DEF_BEACON_EXP 20 #define ACX_TX_DESCRIPTORS 32 -- cgit v1.2.3-58-ga151 From 8973a6e770fc891f92daacbc1c92c7cd396fcf7e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 26 Apr 2011 15:25:29 -0700 Subject: libertas: use kernel-doc notation, fix comment style Convert all libertas/ files to use kernel-doc notation instead of whatever it was (doxygen?). Add or fix function parameters in several places. Use expected style for multi-line comments in lots of places. Remove erroneous /** in multiple places. Signed-off-by: Randy Dunlap Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cfg.c | 45 +++--- drivers/net/wireless/libertas/cmd.c | 245 +++++++++++++++++--------------- drivers/net/wireless/libertas/cmdresp.c | 19 +-- drivers/net/wireless/libertas/debugfs.c | 36 ++--- drivers/net/wireless/libertas/decl.h | 8 +- drivers/net/wireless/libertas/defs.h | 113 ++++++++------- drivers/net/wireless/libertas/dev.h | 20 +-- drivers/net/wireless/libertas/ethtool.c | 3 +- drivers/net/wireless/libertas/host.h | 33 +++-- drivers/net/wireless/libertas/if_cs.c | 35 +++-- drivers/net/wireless/libertas/if_spi.c | 134 +++++++++++------ drivers/net/wireless/libertas/if_spi.h | 68 ++++----- drivers/net/wireless/libertas/if_usb.c | 113 ++++++++------- drivers/net/wireless/libertas/if_usb.h | 14 +- drivers/net/wireless/libertas/main.c | 99 +++++++------ drivers/net/wireless/libertas/mesh.c | 210 ++++++++++++++++++--------- drivers/net/wireless/libertas/mesh.h | 6 +- drivers/net/wireless/libertas/rx.c | 34 ++--- drivers/net/wireless/libertas/tx.c | 34 ++--- drivers/net/wireless/libertas/types.h | 18 +-- 20 files changed, 730 insertions(+), 557 deletions(-) diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 30ef0351bfc4..f582dfd2927f 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -122,8 +122,10 @@ static u8 lbs_auth_to_authtype(enum nl80211_auth_type auth_type) } -/* Various firmware commands need the list of supported rates, but with - the hight-bit set for basic rates */ +/* + * Various firmware commands need the list of supported rates, but with + * the hight-bit set for basic rates + */ static int lbs_add_rates(u8 *rates) { size_t i; @@ -425,7 +427,7 @@ static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len) return ie_len + 2; } -/*************************************************************************** +/* * Set Channel */ @@ -452,7 +454,7 @@ static int lbs_cfg_set_channel(struct wiphy *wiphy, -/*************************************************************************** +/* * Scanning */ @@ -538,8 +540,10 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, goto done; } - /* Validity check: the TLV holds TSF values with 8 bytes each, so - * the size in the TLV must match the nr_sets value */ + /* + * Validity check: the TLV holds TSF values with 8 bytes each, so + * the size in the TLV must match the nr_sets value + */ i = get_unaligned_le16(tsfdesc); tsfdesc += 2; if (i / 8 != scanresp->nr_sets) { @@ -581,8 +585,10 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, /* To find out the channel, we must parse the IEs */ ie = pos; - /* 6+1+8+2+2: size of BSSID, RSSI, time stamp, beacon - interval, capabilities */ + /* + * 6+1+8+2+2: size of BSSID, RSSI, time stamp, beacon + * interval, capabilities + */ ielen = left = len - (6 + 1 + 8 + 2 + 2); while (left >= 2) { u8 id, elen; @@ -790,7 +796,7 @@ static int lbs_cfg_scan(struct wiphy *wiphy, -/*************************************************************************** +/* * Events */ @@ -825,7 +831,7 @@ void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event) -/*************************************************************************** +/* * Connect/disconnect */ @@ -950,8 +956,10 @@ static int lbs_enable_rsn(struct lbs_private *priv, int enable) * Set WPA/WPA key material */ -/* like "struct cmd_ds_802_11_key_material", but with cmd_header. Once we - * get rid of WEXT, this should go into host.h */ +/* + * like "struct cmd_ds_802_11_key_material", but with cmd_header. Once we + * get rid of WEXT, this should go into host.h + */ struct cmd_key_material { struct cmd_header hdr; @@ -1536,7 +1544,7 @@ static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev, } -/*************************************************************************** +/* * Get station */ @@ -1581,7 +1589,7 @@ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev, -/*************************************************************************** +/* * "Site survey", here just current channel and noise level */ @@ -1614,7 +1622,7 @@ static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev, -/*************************************************************************** +/* * Change interface */ @@ -1656,11 +1664,12 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev, -/*************************************************************************** +/* * IBSS (Ad-Hoc) */ -/* The firmware needs the following bits masked out of the beacon-derived +/* + * The firmware needs the following bits masked out of the beacon-derived * capability field when associating/joining to a BSS: * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused) */ @@ -1999,7 +2008,7 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev) -/*************************************************************************** +/* * Initialization */ diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 7e8a658b7670..6a96fc9c1cea 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1,7 +1,7 @@ -/** - * This file contains the handling of command. - * It prepares command and sends it to firmware when it is ready. - */ +/* + * This file contains the handling of command. + * It prepares command and sends it to firmware when it is ready. + */ #include #include @@ -16,14 +16,14 @@ #define CAL_RSSI(snr, nf) ((s32)((s32)(snr) + CAL_NF(nf))) /** - * @brief Simple callback that copies response back into command + * lbs_cmd_copyback - Simple callback that copies response back into command * - * @param priv A pointer to struct lbs_private structure - * @param extra A pointer to the original command structure for which - * 'resp' is a response - * @param resp A pointer to the command response + * @priv: A pointer to &struct lbs_private structure + * @extra: A pointer to the original command structure for which + * 'resp' is a response + * @resp: A pointer to the command response * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, struct cmd_header *resp) @@ -38,15 +38,15 @@ int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, EXPORT_SYMBOL_GPL(lbs_cmd_copyback); /** - * @brief Simple callback that ignores the result. Use this if - * you just want to send a command to the hardware, but don't + * lbs_cmd_async_callback - Simple callback that ignores the result. + * Use this if you just want to send a command to the hardware, but don't * care for the result. * - * @param priv ignored - * @param extra ignored - * @param resp ignored + * @priv: ignored + * @extra: ignored + * @resp: ignored * - * @return 0 for success + * returns: 0 for success */ static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra, struct cmd_header *resp) @@ -56,10 +56,11 @@ static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra, /** - * @brief Checks whether a command is allowed in Power Save mode + * is_command_allowed_in_ps - tests if a command is allowed in Power Save mode + * + * @cmd: the command ID * - * @param command the command ID - * @return 1 if allowed, 0 if not allowed + * returns: 1 if allowed, 0 if not allowed */ static u8 is_command_allowed_in_ps(u16 cmd) { @@ -75,11 +76,12 @@ static u8 is_command_allowed_in_ps(u16 cmd) } /** - * @brief Updates the hardware details like MAC address and regulatory region + * lbs_update_hw_spec - Updates the hardware details like MAC address + * and regulatory region * - * @param priv A pointer to struct lbs_private structure + * @priv: A pointer to &struct lbs_private structure * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_update_hw_spec(struct lbs_private *priv) { @@ -217,14 +219,14 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg); /** - * @brief Sets the Power Save mode + * lbs_set_ps_mode - Sets the Power Save mode * - * @param priv A pointer to struct lbs_private structure - * @param cmd_action The Power Save operation (PS_MODE_ACTION_ENTER_PS or + * @priv: A pointer to &struct lbs_private structure + * @cmd_action: The Power Save operation (PS_MODE_ACTION_ENTER_PS or * PS_MODE_ACTION_EXIT_PS) - * @param block Whether to block on a response or not + * @block: Whether to block on a response or not * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block) { @@ -417,13 +419,13 @@ int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep) } /** - * @brief Set an SNMP MIB value + * lbs_set_snmp_mib - Set an SNMP MIB value * - * @param priv A pointer to struct lbs_private structure - * @param oid The OID to set in the firmware - * @param val Value to set the OID to + * @priv: A pointer to &struct lbs_private structure + * @oid: The OID to set in the firmware + * @val: Value to set the OID to * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val) { @@ -467,13 +469,13 @@ out: } /** - * @brief Get an SNMP MIB value + * lbs_get_snmp_mib - Get an SNMP MIB value * - * @param priv A pointer to struct lbs_private structure - * @param oid The OID to retrieve from the firmware - * @param out_val Location for the returned value + * @priv: A pointer to &struct lbs_private structure + * @oid: The OID to retrieve from the firmware + * @out_val: Location for the returned value * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val) { @@ -510,14 +512,14 @@ out: } /** - * @brief Get the min, max, and current TX power + * lbs_get_tx_power - Get the min, max, and current TX power * - * @param priv A pointer to struct lbs_private structure - * @param curlevel Current power level in dBm - * @param minlevel Minimum supported power level in dBm (optional) - * @param maxlevel Maximum supported power level in dBm (optional) + * @priv: A pointer to &struct lbs_private structure + * @curlevel: Current power level in dBm + * @minlevel: Minimum supported power level in dBm (optional) + * @maxlevel: Maximum supported power level in dBm (optional) * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, s16 *maxlevel) @@ -545,12 +547,12 @@ int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, } /** - * @brief Set the TX power + * lbs_set_tx_power - Set the TX power * - * @param priv A pointer to struct lbs_private structure - * @param dbm The desired power level in dBm + * @priv: A pointer to &struct lbs_private structure + * @dbm: The desired power level in dBm * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm) { @@ -573,12 +575,13 @@ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm) } /** - * @brief Enable or disable monitor mode (only implemented on OLPC usb8388 FW) + * lbs_set_monitor_mode - Enable or disable monitor mode + * (only implemented on OLPC usb8388 FW) * - * @param priv A pointer to struct lbs_private structure - * @param enable 1 to enable monitor mode, 0 to disable + * @priv: A pointer to &struct lbs_private structure + * @enable: 1 to enable monitor mode, 0 to disable * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_set_monitor_mode(struct lbs_private *priv, int enable) { @@ -604,11 +607,11 @@ int lbs_set_monitor_mode(struct lbs_private *priv, int enable) } /** - * @brief Get the radio channel + * lbs_get_channel - Get the radio channel * - * @param priv A pointer to struct lbs_private structure + * @priv: A pointer to &struct lbs_private structure * - * @return The channel on success, error on failure + * returns: The channel on success, error on failure */ static int lbs_get_channel(struct lbs_private *priv) { @@ -650,12 +653,12 @@ int lbs_update_channel(struct lbs_private *priv) } /** - * @brief Set the radio channel + * lbs_set_channel - Set the radio channel * - * @param priv A pointer to struct lbs_private structure - * @param channel The desired channel, or 0 to clear a locked channel + * @priv: A pointer to &struct lbs_private structure + * @channel: The desired channel, or 0 to clear a locked channel * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_set_channel(struct lbs_private *priv, u8 channel) { @@ -686,12 +689,13 @@ out: } /** - * @brief Get current RSSI and noise floor + * lbs_get_rssi - Get current RSSI and noise floor * - * @param priv A pointer to struct lbs_private structure - * @param rssi On successful return, signal level in mBm + * @priv: A pointer to &struct lbs_private structure + * @rssi: On successful return, signal level in mBm + * @nf: On successful return, Noise floor * - * @return The channel on success, error on failure + * returns: The channel on success, error on failure */ int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf) { @@ -719,13 +723,14 @@ int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf) } /** - * @brief Send regulatory and 802.11d domain information to the firmware + * lbs_set_11d_domain_info - Send regulatory and 802.11d domain information + * to the firmware * - * @param priv pointer to struct lbs_private - * @param request cfg80211 regulatory request structure - * @param bands the device's supported bands and channels + * @priv: pointer to &struct lbs_private + * @request: cfg80211 regulatory request structure + * @bands: the device's supported bands and channels * - * @return 0 on success, error code on failure + * returns: 0 on success, error code on failure */ int lbs_set_11d_domain_info(struct lbs_private *priv, struct regulatory_request *request, @@ -842,15 +847,15 @@ int lbs_set_11d_domain_info(struct lbs_private *priv, } /** - * @brief Read a MAC, Baseband, or RF register + * lbs_get_reg - Read a MAC, Baseband, or RF register * - * @param priv pointer to struct lbs_private - * @param cmd register command, one of CMD_MAC_REG_ACCESS, - * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS - * @param offset byte offset of the register to get - * @param value on success, the value of the register at 'offset' + * @priv: pointer to &struct lbs_private + * @reg: register command, one of CMD_MAC_REG_ACCESS, + * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS + * @offset: byte offset of the register to get + * @value: on success, the value of the register at 'offset' * - * @return 0 on success, error code on failure + * returns: 0 on success, error code on failure */ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value) { @@ -886,15 +891,15 @@ out: } /** - * @brief Write a MAC, Baseband, or RF register + * lbs_set_reg - Write a MAC, Baseband, or RF register * - * @param priv pointer to struct lbs_private - * @param cmd register command, one of CMD_MAC_REG_ACCESS, - * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS - * @param offset byte offset of the register to set - * @param value the value to write to the register at 'offset' + * @priv: pointer to &struct lbs_private + * @reg: register command, one of CMD_MAC_REG_ACCESS, + * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS + * @offset: byte offset of the register to set + * @value: the value to write to the register at 'offset' * - * @return 0 on success, error code on failure + * returns: 0 on success, error code on failure */ int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value) { @@ -1023,7 +1028,7 @@ static void lbs_submit_command(struct lbs_private *priv, lbs_deb_leave(LBS_DEB_HOST); } -/** +/* * This function inserts command node to cmdfreeq * after cleans it. Requires priv->driver_lock held. */ @@ -1125,11 +1130,12 @@ void lbs_set_mac_control(struct lbs_private *priv) } /** - * @brief This function allocates the command buffer and link - * it to command free queue. + * lbs_allocate_cmd_buffer - allocates the command buffer and links + * it to command free queue + * + * @priv: A pointer to &struct lbs_private structure * - * @param priv A pointer to struct lbs_private structure - * @return 0 or -1 + * returns: 0 for success or -1 on error */ int lbs_allocate_cmd_buffer(struct lbs_private *priv) { @@ -1171,10 +1177,11 @@ done: } /** - * @brief This function frees the command buffer. + * lbs_free_cmd_buffer - free the command buffer * - * @param priv A pointer to struct lbs_private structure - * @return 0 or -1 + * @priv: A pointer to &struct lbs_private structure + * + * returns: 0 for success */ int lbs_free_cmd_buffer(struct lbs_private *priv) { @@ -1211,11 +1218,13 @@ done: } /** - * @brief This function gets a free command node if available in - * command free queue. + * lbs_get_free_cmd_node - gets a free command node if available in + * command free queue + * + * @priv: A pointer to &struct lbs_private structure * - * @param priv A pointer to struct lbs_private structure - * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL + * returns: A pointer to &cmd_ctrl_node structure on success + * or %NULL on error */ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv) { @@ -1245,12 +1254,12 @@ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv) } /** - * @brief This function executes next command in command - * pending queue. It will put firmware back to PS mode - * if applicable. + * lbs_execute_next_command - execute next command in command + * pending queue. Will put firmware back to PS mode if applicable. * - * @param priv A pointer to struct lbs_private structure - * @return 0 or -1 + * @priv: A pointer to &struct lbs_private structure + * + * returns: 0 on success or -1 on error */ int lbs_execute_next_command(struct lbs_private *priv) { @@ -1454,12 +1463,12 @@ out: } /** - * @brief This function checks condition and prepares to - * send sleep confirm command to firmware if ok. + * lbs_ps_confirm_sleep - checks condition and prepares to + * send sleep confirm command to firmware if ok + * + * @priv: A pointer to &struct lbs_private structure * - * @param priv A pointer to struct lbs_private structure - * @param psmode Power Saving mode - * @return n/a + * returns: n/a */ void lbs_ps_confirm_sleep(struct lbs_private *priv) { @@ -1499,16 +1508,16 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) /** - * @brief Configures the transmission power control functionality. + * lbs_set_tpc_cfg - Configures the transmission power control functionality * - * @param priv A pointer to struct lbs_private structure - * @param enable Transmission power control enable - * @param p0 Power level when link quality is good (dBm). - * @param p1 Power level when link quality is fair (dBm). - * @param p2 Power level when link quality is poor (dBm). - * @param usesnr Use Signal to Noise Ratio in TPC + * @priv: A pointer to &struct lbs_private structure + * @enable: Transmission power control enable + * @p0: Power level when link quality is good (dBm). + * @p1: Power level when link quality is fair (dBm). + * @p2: Power level when link quality is poor (dBm). + * @usesnr: Use Signal to Noise Ratio in TPC * - * @return 0 on success + * returns: 0 on success */ int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, int8_t p2, int usesnr) @@ -1531,15 +1540,15 @@ int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, } /** - * @brief Configures the power adaptation settings. + * lbs_set_power_adapt_cfg - Configures the power adaptation settings * - * @param priv A pointer to struct lbs_private structure - * @param enable Power adaptation enable - * @param p0 Power level for 1, 2, 5.5 and 11 Mbps (dBm). - * @param p1 Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm). - * @param p2 Power level for 48 and 54 Mbps (dBm). + * @priv: A pointer to &struct lbs_private structure + * @enable: Power adaptation enable + * @p0: Power level for 1, 2, 5.5 and 11 Mbps (dBm). + * @p1: Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm). + * @p2: Power level for 48 and 54 Mbps (dBm). * - * @return 0 on Success + * returns: 0 on Success */ int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 5e95da9dcc2e..03e528994a9e 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -1,7 +1,7 @@ -/** - * This file contains the handling of command - * responses as well as events generated by firmware. - */ +/* + * This file contains the handling of command + * responses as well as events generated by firmware. + */ #include #include #include @@ -12,12 +12,13 @@ #include "cmd.h" /** - * @brief This function handles disconnect event. it - * reports disconnect to upper layer, clean tx/rx packets, - * reset link state etc. + * lbs_mac_event_disconnected - handles disconnect event. It + * reports disconnect to upper layer, clean tx/rx packets, + * reset link state etc. + * + * @priv: A pointer to struct lbs_private structure * - * @param priv A pointer to struct lbs_private structure - * @return n/a + * returns: n/a */ void lbs_mac_event_disconnected(struct lbs_private *priv) { diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index fbf3b0332bb7..851fe7bd4ba4 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -849,15 +849,14 @@ static struct debug_data items[] = { static int num_of_items = ARRAY_SIZE(items); /** - * @brief proc read function + * lbs_debugfs_read - proc read function * - * @param page pointer to buffer - * @param s read data starting position - * @param off offset - * @param cnt counter - * @param eof end of file flag - * @param data data to output - * @return number of output data + * @file: file to read + * @userbuf: pointer to buffer + * @count: number of bytes to read + * @ppos: read data starting position + * + * returns: amount of data read or negative error code */ static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) @@ -897,13 +896,14 @@ static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf, } /** - * @brief proc write function + * lbs_debugfs_write - proc write function + * + * @f: file pointer + * @buf: pointer to data buffer + * @cnt: data number to write + * @ppos: file position * - * @param f file pointer - * @param buf pointer to data buffer - * @param cnt data number to write - * @param data data to write - * @return number of data + * returns: amount of data written */ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, size_t cnt, loff_t *ppos) @@ -966,11 +966,11 @@ static const struct file_operations lbs_debug_fops = { }; /** - * @brief create debug proc file + * lbs_debug_init - create debug proc file + * + * @priv: pointer to &struct lbs_private * - * @param priv pointer struct lbs_private - * @param dev pointer net_device - * @return N/A + * returns: N/A */ static void lbs_debug_init(struct lbs_private *priv) { diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 2ae752d10065..da0b05bb89fe 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -1,8 +1,8 @@ -/** - * This file contains declaration referring to - * functions defined in other source files - */ +/* + * This file contains declaration referring to + * functions defined in other source files + */ #ifndef _LBS_DECL_H_ #define _LBS_DECL_H_ diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index d00c728cec47..92b5b1f8fd75 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -1,7 +1,7 @@ -/** - * This header file contains global constant/enum definitions, - * global variable declaration. - */ +/* + * This header file contains global constant/enum definitions, + * global variable declaration. + */ #ifndef _LBS_DEFS_H_ #define _LBS_DEFS_H_ @@ -123,19 +123,19 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in -/** Buffer Constants */ +/* Buffer Constants */ /* The size of SQ memory PPA, DPA are 8 DWORDs, that keep the physical -* addresses of TxPD buffers. Station has only 8 TxPD available, Whereas -* driver has more local TxPDs. Each TxPD on the host memory is associated -* with a Tx control node. The driver maintains 8 RxPD descriptors for -* station firmware to store Rx packet information. -* -* Current version of MAC has a 32x6 multicast address buffer. -* -* 802.11b can have up to 14 channels, the driver keeps the -* BSSID(MAC address) of each APs or Ad hoc stations it has sensed. -*/ + * addresses of TxPD buffers. Station has only 8 TxPD available, Whereas + * driver has more local TxPDs. Each TxPD on the host memory is associated + * with a Tx control node. The driver maintains 8 RxPD descriptors for + * station firmware to store Rx packet information. + * + * Current version of MAC has a 32x6 multicast address buffer. + * + * 802.11b can have up to 14 channels, the driver keeps the + * BSSID(MAC address) of each APs or Ad hoc stations it has sensed. + */ #define MRVDRV_MAX_MULTICAST_LIST_SIZE 32 #define LBS_NUM_CMD_BUFFERS 10 @@ -166,7 +166,7 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define WOL_RESULT_NOSPC_ERR 1 #define WOL_RESULT_EEXIST_ERR 2 -/** Misc constants */ +/* Misc constants */ /* This section defines 802.11 specific contants */ #define MRVDRV_MAX_BSS_DESCRIPTS 16 @@ -183,7 +183,8 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define MARVELL_MESH_IE_LENGTH 9 -/* Values used to populate the struct mrvl_mesh_ie. The only time you need this +/* + * Values used to populate the struct mrvl_mesh_ie. The only time you need this * is when enabling the mesh using CMD_MESH_CONFIG. */ #define MARVELL_MESH_IE_TYPE 4 @@ -193,7 +194,7 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define MARVELL_MESH_METRIC_ID 0 #define MARVELL_MESH_CAPABILITY 0 -/** INT status Bit Definition*/ +/* INT status Bit Definition */ #define MRVDRV_TX_DNLD_RDY 0x0001 #define MRVDRV_RX_UPLD_RDY 0x0002 #define MRVDRV_CMD_DNLD_RDY 0x0004 @@ -208,59 +209,63 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define TPC_DEFAULT_P1 10 #define TPC_DEFAULT_P2 13 -/** TxPD status */ +/* TxPD status */ -/* Station firmware use TxPD status field to report final Tx transmit -* result, Bit masks are used to present combined situations. -*/ +/* + * Station firmware use TxPD status field to report final Tx transmit + * result, Bit masks are used to present combined situations. + */ #define MRVDRV_TxPD_POWER_MGMT_NULL_PACKET 0x01 #define MRVDRV_TxPD_POWER_MGMT_LAST_PACKET 0x08 -/** Tx mesh flag */ -/* Currently we are using normal WDS flag as mesh flag. +/* Tx mesh flag */ +/* + * Currently we are using normal WDS flag as mesh flag. * TODO: change to proper mesh flag when MAC understands it. */ #define TxPD_CONTROL_WDS_FRAME (1<<17) #define TxPD_MESH_FRAME TxPD_CONTROL_WDS_FRAME -/** Mesh interface ID */ +/* Mesh interface ID */ #define MESH_IFACE_ID 0x0001 -/** Mesh id should be in bits 14-13-12 */ +/* Mesh id should be in bits 14-13-12 */ #define MESH_IFACE_BIT_OFFSET 0x000c -/** Mesh enable bit in FW capability */ +/* Mesh enable bit in FW capability */ #define MESH_CAPINFO_ENABLE_MASK (1<<16) -/** FW definition from Marvell v4 */ +/* FW definition from Marvell v4 */ #define MRVL_FW_V4 (0x04) -/** FW definition from Marvell v5 */ +/* FW definition from Marvell v5 */ #define MRVL_FW_V5 (0x05) -/** FW definition from Marvell v10 */ +/* FW definition from Marvell v10 */ #define MRVL_FW_V10 (0x0a) -/** FW major revision definition */ +/* FW major revision definition */ #define MRVL_FW_MAJOR_REV(x) ((x)>>24) -/** RxPD status */ +/* RxPD status */ #define MRVDRV_RXPD_STATUS_OK 0x0001 -/** RxPD status - Received packet types */ -/** Rx mesh flag */ -/* Currently we are using normal WDS flag as mesh flag. +/* RxPD status - Received packet types */ +/* Rx mesh flag */ +/* + * Currently we are using normal WDS flag as mesh flag. * TODO: change to proper mesh flag when MAC understands it. */ #define RxPD_CONTROL_WDS_FRAME (0x40) #define RxPD_MESH_FRAME RxPD_CONTROL_WDS_FRAME -/** RSSI-related defines */ -/* RSSI constants are used to implement 802.11 RSSI threshold -* indication. if the Rx packet signal got too weak for 5 consecutive -* times, miniport driver (driver) will report this event to wrapper -*/ +/* RSSI-related defines */ +/* + * RSSI constants are used to implement 802.11 RSSI threshold + * indication. if the Rx packet signal got too weak for 5 consecutive + * times, miniport driver (driver) will report this event to wrapper + */ #define MRVDRV_NF_DEFAULT_SCAN_VALUE (-96) -/** RTS/FRAG related defines */ +/* RTS/FRAG related defines */ #define MRVDRV_RTS_MIN_VALUE 0 #define MRVDRV_RTS_MAX_VALUE 2347 #define MRVDRV_FRAG_MIN_VALUE 256 @@ -300,36 +305,36 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define MAX_LEDS 8 -/** Global Variable Declaration */ +/* Global Variable Declaration */ extern const char lbs_driver_version[]; extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE]; -/** ENUM definition*/ -/** SNRNF_TYPE */ +/* ENUM definition */ +/* SNRNF_TYPE */ enum SNRNF_TYPE { TYPE_BEACON = 0, TYPE_RXPD, MAX_TYPE_B }; -/** SNRNF_DATA*/ +/* SNRNF_DATA */ enum SNRNF_DATA { TYPE_NOAVG = 0, TYPE_AVG, MAX_TYPE_AVG }; -/** LBS_802_11_POWER_MODE */ +/* LBS_802_11_POWER_MODE */ enum LBS_802_11_POWER_MODE { LBS802_11POWERMODECAM, LBS802_11POWERMODEMAX_PSP, LBS802_11POWERMODEFAST_PSP, - /*not a real mode, defined as an upper bound */ + /* not a real mode, defined as an upper bound */ LBS802_11POWEMODEMAX }; -/** PS_STATE */ +/* PS_STATE */ enum PS_STATE { PS_STATE_FULL_POWER, PS_STATE_AWAKE, @@ -337,7 +342,7 @@ enum PS_STATE { PS_STATE_SLEEP }; -/** DNLD_STATE */ +/* DNLD_STATE */ enum DNLD_STATE { DNLD_RES_RECEIVED, DNLD_DATA_SENT, @@ -345,19 +350,19 @@ enum DNLD_STATE { DNLD_BOOTCMD_SENT, }; -/** LBS_MEDIA_STATE */ +/* LBS_MEDIA_STATE */ enum LBS_MEDIA_STATE { LBS_CONNECTED, LBS_DISCONNECTED }; -/** LBS_802_11_PRIVACY_FILTER */ +/* LBS_802_11_PRIVACY_FILTER */ enum LBS_802_11_PRIVACY_FILTER { LBS802_11PRIVFILTERACCEPTALL, LBS802_11PRIVFILTER8021XWEP }; -/** mv_ms_type */ +/* mv_ms_type */ enum mv_ms_type { MVMS_DAT = 0, MVMS_CMD = 1, @@ -365,14 +370,14 @@ enum mv_ms_type { MVMS_EVENT }; -/** KEY_TYPE_ID */ +/* KEY_TYPE_ID */ enum KEY_TYPE_ID { KEY_TYPE_ID_WEP = 0, KEY_TYPE_ID_TKIP, KEY_TYPE_ID_AES }; -/** KEY_INFO_WPA (applies to both TKIP and AES/CCMP) */ +/* KEY_INFO_WPA (applies to both TKIP and AES/CCMP) */ enum KEY_INFO_WPA { KEY_INFO_WPA_MCAST = 0x01, KEY_INFO_WPA_UNICAST = 0x02, diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index bc461eb39660..76d018beebf4 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -1,8 +1,8 @@ -/** - * This file contains definitions and data structures specific - * to Marvell 802.11 NIC. It contains the Device Information - * structure struct lbs_private.. - */ +/* + * This file contains definitions and data structures specific + * to Marvell 802.11 NIC. It contains the Device Information + * structure struct lbs_private.. + */ #ifndef _LBS_DEV_H_ #define _LBS_DEV_H_ @@ -12,7 +12,7 @@ #include -/** sleep_params */ +/* sleep_params */ struct sleep_params { uint16_t sp_error; uint16_t sp_offset; @@ -23,7 +23,7 @@ struct sleep_params { }; -/** Private structure for the MV device */ +/* Private structure for the MV device */ struct lbs_private { /* Basic networking */ @@ -125,12 +125,12 @@ struct lbs_private { /* Events sent from hardware to driver */ struct kfifo event_fifo; - /** thread to service interrupts */ + /* thread to service interrupts */ struct task_struct *main_thread; wait_queue_head_t waitq; struct workqueue_struct *work_thread; - /** Encryption stuff */ + /* Encryption stuff */ u8 authtype_auto; u8 wep_tx_key; u8 wep_key[4][WLAN_KEY_LEN_WEP104]; @@ -162,7 +162,7 @@ struct lbs_private { s16 txpower_min; s16 txpower_max; - /** Scanning */ + /* Scanning */ struct delayed_work scan_work; int scan_channel; /* Queue of things waiting for scan completion */ diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 50193aac679e..29dbce4a9f86 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c @@ -20,7 +20,8 @@ static void lbs_ethtool_get_drvinfo(struct net_device *dev, strcpy(info->version, lbs_driver_version); } -/* All 8388 parts have 16KiB EEPROM size at the time of writing. +/* + * All 8388 parts have 16KiB EEPROM size at the time of writing. * In case that changes this needs fixing. */ #define LBS_EEPROM_LEN 16384 diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index 6cb6935ee4a3..2e2dbfa2ee50 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h @@ -1,7 +1,7 @@ -/** - * This file function prototypes, data structure - * and definitions for all the host/station commands - */ +/* + * This file function prototypes, data structure + * and definitions for all the host/station commands + */ #ifndef _LBS_HOST_H_ #define _LBS_HOST_H_ @@ -13,9 +13,10 @@ #define CMD_OPTION_WAITFORRSP 0x0002 -/** Host command IDs */ +/* Host command IDs */ -/* Return command are almost always the same as the host command, but with +/* + * Return command are almost always the same as the host command, but with * bit 15 set high. There are a few exceptions, though... */ #define CMD_RET(cmd) (0x8000 | cmd) @@ -251,7 +252,7 @@ enum cmd_mesh_config_types { CMD_TYPE_MESH_GET_MESH_IE, /* GET_DEFAULTS is superset of GET_MESHIE */ }; -/** Card Event definition */ +/* Card Event definition */ #define MACREG_INT_CODE_TX_PPA_FREE 0 #define MACREG_INT_CODE_TX_DMA_DONE 1 #define MACREG_INT_CODE_LINK_LOST_W_SCAN 2 @@ -624,12 +625,14 @@ struct cmd_ds_802_11_rf_channel { struct cmd_ds_802_11_rssi { struct cmd_header hdr; - /* request: number of beacons (N) to average the SNR and NF over + /* + * request: number of beacons (N) to average the SNR and NF over * response: SNR of most recent beacon */ __le16 n_or_snr; - /* The following fields are only set in the response. + /* + * The following fields are only set in the response. * In the request these are reserved and should be set to 0. */ __le16 nf; /* most recent beacon noise floor */ @@ -680,14 +683,16 @@ struct cmd_ds_802_11_ps_mode { __le16 action; - /* Interval for keepalive in PS mode: + /* + * Interval for keepalive in PS mode: * 0x0000 = don't change * 0x001E = firmware default * 0xFFFF = disable */ __le16 nullpktinterval; - /* Number of DTIM intervals to wake up for: + /* + * Number of DTIM intervals to wake up for: * 0 = don't change * 1 = firmware default * 5 = max @@ -697,7 +702,8 @@ struct cmd_ds_802_11_ps_mode { __le16 reserved; __le16 locallisteninterval; - /* AdHoc awake period (FW v9+ only): + /* + * AdHoc awake period (FW v9+ only): * 0 = don't change * 1 = always awake (IEEE standard behavior) * 2 - 31 = sleep for (n - 1) periods and awake for 1 period @@ -771,7 +777,8 @@ struct adhoc_bssdesc { __le16 capability; u8 rates[MAX_RATES]; - /* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the + /* + * DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the * Adhoc join command and will cause a binary layout mismatch with * the firmware */ diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index fc8121190d38..4dfd48fe8b6e 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -312,7 +312,8 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r #define CF8385_MANFID 0x02df #define CF8385_CARDID 0x8103 -/* FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when +/* + * FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when * that gets fixed. Currently there's no way to access it from the probe hook. */ static inline u32 get_model(u16 manf_id, u16 card_id) @@ -621,8 +622,10 @@ static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw) if (remain < count) count = remain; - /* "write the number of bytes to be sent to the I/O Command - * write length register" */ + /* + * "write the number of bytes to be sent to the I/O Command + * write length register" + */ if_cs_write16(card, IF_CS_CMD_LEN, count); /* "write this to I/O Command port register as 16 bit writes */ @@ -631,16 +634,22 @@ static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw) &fw->data[sent], count >> 1); - /* "Assert the download over interrupt command in the Host - * status register" */ + /* + * "Assert the download over interrupt command in the Host + * status register" + */ if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND); - /* "Assert the download over interrupt command in the Card - * interrupt case register" */ + /* + * "Assert the download over interrupt command in the Card + * interrupt case register" + */ if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND); - /* "The host polls the Card Status register ... for 50 ms before - declaring a failure */ + /* + * "The host polls the Card Status register ... for 50 ms before + * declaring a failure" + */ ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS, IF_CS_BIT_COMMAND); if (ret < 0) { @@ -841,7 +850,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) /* * Most of the libertas cards can do unaligned register access, but some - * weird ones can not. That's especially true for the CF8305 card. + * weird ones cannot. That's especially true for the CF8305 card. */ card->align_regs = 0; @@ -913,8 +922,10 @@ static int if_cs_probe(struct pcmcia_device *p_dev) goto out3; } - /* Clear any interrupt cause that happend while sending - * firmware/initializing card */ + /* + * Clear any interrupt cause that happened while sending + * firmware/initializing card + */ if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK); if_cs_enable_ints(card); diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 078ef43d957d..67de5b3c68b2 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -143,8 +143,10 @@ static void spu_transaction_finish(struct if_spi_card *card) card->prev_xfer_time = jiffies; } -/* Write out a byte buffer to an SPI register, - * using a series of 16-bit transfers. */ +/* + * Write out a byte buffer to an SPI register, + * using a series of 16-bit transfers. + */ static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len) { int err = 0; @@ -208,8 +210,10 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) struct spi_transfer dummy_trans; struct spi_transfer data_trans; - /* You must take an even number of bytes from the SPU, even if you - * don't care about the last one. */ + /* + * You must take an even number of bytes from the SPU, even if you + * don't care about the last one. + */ BUG_ON(len & 0x1); spu_transaction_init(card); @@ -258,8 +262,10 @@ static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val) return ret; } -/* Read 32 bits from an SPI register. - * The low 16 bits are read first. */ +/* + * Read 32 bits from an SPI register. + * The low 16 bits are read first. + */ static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val) { __le32 buf; @@ -271,13 +277,15 @@ static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val) return err; } -/* Keep reading 16 bits from an SPI register until you get the correct result. +/* + * Keep reading 16 bits from an SPI register until you get the correct result. * * If mask = 0, the correct result is any non-zero number. * If mask != 0, the correct result is any number where * number & target_mask == target * - * Returns -ETIMEDOUT if a second passes without the correct result. */ + * Returns -ETIMEDOUT if a second passes without the correct result. + */ static int spu_wait_for_u16(struct if_spi_card *card, u16 reg, u16 target_mask, u16 target) { @@ -305,8 +313,10 @@ static int spu_wait_for_u16(struct if_spi_card *card, u16 reg, } } -/* Read 16 bits from an SPI register until you receive a specific value. - * Returns -ETIMEDOUT if a 4 tries pass without success. */ +/* + * Read 16 bits from an SPI register until you receive a specific value. + * Returns -ETIMEDOUT if a 4 tries pass without success. + */ static int spu_wait_for_u32(struct if_spi_card *card, u32 reg, u32 target) { int err, try; @@ -328,8 +338,10 @@ static int spu_set_interrupt_mode(struct if_spi_card *card, { int err = 0; - /* We can suppress a host interrupt by clearing the appropriate - * bit in the "host interrupt status mask" register */ + /* + * We can suppress a host interrupt by clearing the appropriate + * bit in the "host interrupt status mask" register + */ if (suppress_host_int) { err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0); if (err) @@ -345,10 +357,12 @@ static int spu_set_interrupt_mode(struct if_spi_card *card, return err; } - /* If auto-interrupts are on, the completion of certain transactions + /* + * If auto-interrupts are on, the completion of certain transactions * will trigger an interrupt automatically. If auto-interrupts * are off, we need to set the "Card Interrupt Cause" register to - * trigger a card interrupt. */ + * trigger a card interrupt. + */ if (auto_int) { err = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG, IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO | @@ -402,8 +416,10 @@ static int spu_init(struct if_spi_card *card, int use_dummy_writes) int err = 0; u32 delay; - /* We have to start up in timed delay mode so that we can safely - * read the Delay Read Register. */ + /* + * We have to start up in timed delay mode so that we can safely + * read the Delay Read Register. + */ card->use_dummy_writes = 0; err = spu_set_bus_mode(card, IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING | @@ -459,8 +475,10 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card, /* Load helper firmware image */ while (bytes_remaining > 0) { - /* Scratch pad 1 should contain the number of bytes we - * want to download to the firmware */ + /* + * Scratch pad 1 should contain the number of bytes we + * want to download to the firmware + */ err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, HELPER_FW_LOAD_CHUNK_SZ); if (err) @@ -472,8 +490,10 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card, if (err) goto out; - /* Feed the data into the command read/write port reg - * in chunks of 64 bytes */ + /* + * Feed the data into the command read/write port reg + * in chunks of 64 bytes + */ memset(temp, 0, sizeof(temp)); memcpy(temp, fw, min(bytes_remaining, HELPER_FW_LOAD_CHUNK_SZ)); @@ -495,9 +515,11 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card, fw += HELPER_FW_LOAD_CHUNK_SZ; } - /* Once the helper / single stage firmware download is complete, + /* + * Once the helper / single stage firmware download is complete, * write 0 to scratch pad 1 and interrupt the - * bootloader. This completes the helper download. */ + * bootloader. This completes the helper download. + */ err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); if (err) goto out; @@ -517,16 +539,20 @@ out: return err; } -/* Returns the length of the next packet the firmware expects us to send - * Sets crc_err if the previous transfer had a CRC error. */ +/* + * Returns the length of the next packet the firmware expects us to send. + * Sets crc_err if the previous transfer had a CRC error. + */ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, int *crc_err) { u16 len; int err = 0; - /* wait until the host interrupt status register indicates - * that we are ready to download */ + /* + * wait until the host interrupt status register indicates + * that we are ready to download + */ err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, IF_SPI_HIST_CMD_DOWNLOAD_RDY, IF_SPI_HIST_CMD_DOWNLOAD_RDY); @@ -587,8 +613,10 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card, goto out; } if (bytes < 0) { - /* If there are no more bytes left, we would normally - * expect to have terminated with len = 0 */ + /* + * If there are no more bytes left, we would normally + * expect to have terminated with len = 0 + */ lbs_pr_err("Firmware load wants more bytes " "than we have to offer.\n"); break; @@ -660,14 +688,18 @@ static int if_spi_c2h_cmd(struct if_spi_card *card) u16 len; u8 i; - /* We need a buffer big enough to handle whatever people send to - * hw_host_to_card */ + /* + * We need a buffer big enough to handle whatever people send to + * hw_host_to_card + */ BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_CMD_BUFFER_SIZE); BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_UPLD_SIZE); - /* It's just annoying if the buffer size isn't a multiple of 4, because - * then we might have len < IF_SPI_CMD_BUF_SIZE but - * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE */ + /* + * It's just annoying if the buffer size isn't a multiple of 4, because + * then we might have len < IF_SPI_CMD_BUF_SIZE but + * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE + */ BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0); lbs_deb_enter(LBS_DEB_SPI); @@ -838,8 +870,10 @@ static void if_spi_host_to_card_worker(struct work_struct *work) lbs_deb_enter(LBS_DEB_SPI); - /* Read the host interrupt status register to see what we - * can do. */ + /* + * Read the host interrupt status register to see what we + * can do. + */ err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG, &hiStatus); if (err) { @@ -858,12 +892,15 @@ static void if_spi_host_to_card_worker(struct work_struct *work) goto err; } - /* workaround: in PS mode, the card does not set the Command - * Download Ready bit, but it sets TX Download Ready. */ + /* + * workaround: in PS mode, the card does not set the Command + * Download Ready bit, but it sets TX Download Ready. + */ if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY || (card->priv->psstate != PS_STATE_FULL_POWER && (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) { - /* This means two things. First of all, + /* + * This means two things. First of all, * if there was a previous command sent, the card has * successfully received it. * Secondly, it is now ready to download another @@ -871,8 +908,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work) */ lbs_host_to_card_done(card->priv); - /* Do we have any command packets from the host to - * send? */ + /* Do we have any command packets from the host to send? */ packet = NULL; spin_lock_irqsave(&card->buffer_lock, flags); if (!list_empty(&card->cmd_packet_list)) { @@ -886,8 +922,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work) if_spi_h2c(card, packet, MVMS_CMD); } if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) { - /* Do we have any data packets from the host to - * send? */ + /* Do we have any data packets from the host to send? */ packet = NULL; spin_lock_irqsave(&card->buffer_lock, flags); if (!list_empty(&card->data_packet_list)) { @@ -914,7 +949,8 @@ err: * Host to Card * * Called from Libertas to transfer some data to the WLAN device - * We can't sleep here. */ + * We can't sleep here. + */ static int if_spi_host_to_card(struct lbs_private *priv, u8 type, u8 *buf, u16 nb) { @@ -1125,8 +1161,10 @@ static int __devinit if_spi_probe(struct spi_device *spi) if (err) goto free_card; - /* Register our card with libertas. - * This will call alloc_etherdev */ + /* + * Register our card with libertas. + * This will call alloc_etherdev. + */ priv = lbs_add_card(card, &spi->dev); if (!priv) { err = -ENOMEM; @@ -1153,9 +1191,11 @@ static int __devinit if_spi_probe(struct spi_device *spi) goto terminate_workqueue; } - /* Start the card. + /* + * Start the card. * This will call register_netdev, and we'll start - * getting interrupts... */ + * getting interrupts... + */ err = lbs_start_card(priv); if (err) goto release_irq; diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h index 8b1417d3b71b..9745bd407d76 100644 --- a/drivers/net/wireless/libertas/if_spi.h +++ b/drivers/net/wireless/libertas/if_spi.h @@ -86,34 +86,34 @@ #define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dc) (dc & 0x000000ff) /***************** IF_SPI_HOST_INT_CTRL_REG *****************/ -/** Host Interrupt Control bit : Wake up */ +/* Host Interrupt Control bit : Wake up */ #define IF_SPI_HICT_WAKE_UP (1<<0) -/** Host Interrupt Control bit : WLAN ready */ +/* Host Interrupt Control bit : WLAN ready */ #define IF_SPI_HICT_WLAN_READY (1<<1) /*#define IF_SPI_HICT_FIFO_FIRST_HALF_EMPTY (1<<2) */ /*#define IF_SPI_HICT_FIFO_SECOND_HALF_EMPTY (1<<3) */ /*#define IF_SPI_HICT_IRQSRC_WLAN (1<<4) */ -/** Host Interrupt Control bit : Tx auto download */ +/* Host Interrupt Control bit : Tx auto download */ #define IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO (1<<5) -/** Host Interrupt Control bit : Rx auto upload */ +/* Host Interrupt Control bit : Rx auto upload */ #define IF_SPI_HICT_RX_UPLOAD_OVER_AUTO (1<<6) -/** Host Interrupt Control bit : Command auto download */ +/* Host Interrupt Control bit : Command auto download */ #define IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO (1<<7) -/** Host Interrupt Control bit : Command auto upload */ +/* Host Interrupt Control bit : Command auto upload */ #define IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO (1<<8) /***************** IF_SPI_CARD_INT_CAUSE_REG *****************/ -/** Card Interrupt Case bit : Tx download over */ +/* Card Interrupt Case bit : Tx download over */ #define IF_SPI_CIC_TX_DOWNLOAD_OVER (1<<0) -/** Card Interrupt Case bit : Rx upload over */ +/* Card Interrupt Case bit : Rx upload over */ #define IF_SPI_CIC_RX_UPLOAD_OVER (1<<1) -/** Card Interrupt Case bit : Command download over */ +/* Card Interrupt Case bit : Command download over */ #define IF_SPI_CIC_CMD_DOWNLOAD_OVER (1<<2) -/** Card Interrupt Case bit : Host event */ +/* Card Interrupt Case bit : Host event */ #define IF_SPI_CIC_HOST_EVENT (1<<3) -/** Card Interrupt Case bit : Command upload over */ +/* Card Interrupt Case bit : Command upload over */ #define IF_SPI_CIC_CMD_UPLOAD_OVER (1<<4) -/** Card Interrupt Case bit : Power down */ +/* Card Interrupt Case bit : Power down */ #define IF_SPI_CIC_POWER_DOWN (1<<5) /***************** IF_SPI_CARD_INT_STATUS_REG *****************/ @@ -138,51 +138,51 @@ #define IF_SPI_HICU_CMD_RD_FIFO_UNDERFLOW (1<<10) /***************** IF_SPI_HOST_INT_STATUS_REG *****************/ -/** Host Interrupt Status bit : Tx download ready */ +/* Host Interrupt Status bit : Tx download ready */ #define IF_SPI_HIST_TX_DOWNLOAD_RDY (1<<0) -/** Host Interrupt Status bit : Rx upload ready */ +/* Host Interrupt Status bit : Rx upload ready */ #define IF_SPI_HIST_RX_UPLOAD_RDY (1<<1) -/** Host Interrupt Status bit : Command download ready */ +/* Host Interrupt Status bit : Command download ready */ #define IF_SPI_HIST_CMD_DOWNLOAD_RDY (1<<2) -/** Host Interrupt Status bit : Card event */ +/* Host Interrupt Status bit : Card event */ #define IF_SPI_HIST_CARD_EVENT (1<<3) -/** Host Interrupt Status bit : Command upload ready */ +/* Host Interrupt Status bit : Command upload ready */ #define IF_SPI_HIST_CMD_UPLOAD_RDY (1<<4) -/** Host Interrupt Status bit : I/O write FIFO overflow */ +/* Host Interrupt Status bit : I/O write FIFO overflow */ #define IF_SPI_HIST_IO_WR_FIFO_OVERFLOW (1<<5) -/** Host Interrupt Status bit : I/O read FIFO underflow */ +/* Host Interrupt Status bit : I/O read FIFO underflow */ #define IF_SPI_HIST_IO_RD_FIFO_UNDRFLOW (1<<6) -/** Host Interrupt Status bit : Data write FIFO overflow */ +/* Host Interrupt Status bit : Data write FIFO overflow */ #define IF_SPI_HIST_DATA_WR_FIFO_OVERFLOW (1<<7) -/** Host Interrupt Status bit : Data read FIFO underflow */ +/* Host Interrupt Status bit : Data read FIFO underflow */ #define IF_SPI_HIST_DATA_RD_FIFO_UNDERFLOW (1<<8) -/** Host Interrupt Status bit : Command write FIFO overflow */ +/* Host Interrupt Status bit : Command write FIFO overflow */ #define IF_SPI_HIST_CMD_WR_FIFO_OVERFLOW (1<<9) -/** Host Interrupt Status bit : Command read FIFO underflow */ +/* Host Interrupt Status bit : Command read FIFO underflow */ #define IF_SPI_HIST_CMD_RD_FIFO_UNDERFLOW (1<<10) /***************** IF_SPI_HOST_INT_STATUS_MASK_REG *****************/ -/** Host Interrupt Status Mask bit : Tx download ready */ +/* Host Interrupt Status Mask bit : Tx download ready */ #define IF_SPI_HISM_TX_DOWNLOAD_RDY (1<<0) -/** Host Interrupt Status Mask bit : Rx upload ready */ +/* Host Interrupt Status Mask bit : Rx upload ready */ #define IF_SPI_HISM_RX_UPLOAD_RDY (1<<1) -/** Host Interrupt Status Mask bit : Command download ready */ +/* Host Interrupt Status Mask bit : Command download ready */ #define IF_SPI_HISM_CMD_DOWNLOAD_RDY (1<<2) -/** Host Interrupt Status Mask bit : Card event */ +/* Host Interrupt Status Mask bit : Card event */ #define IF_SPI_HISM_CARDEVENT (1<<3) -/** Host Interrupt Status Mask bit : Command upload ready */ +/* Host Interrupt Status Mask bit : Command upload ready */ #define IF_SPI_HISM_CMD_UPLOAD_RDY (1<<4) -/** Host Interrupt Status Mask bit : I/O write FIFO overflow */ +/* Host Interrupt Status Mask bit : I/O write FIFO overflow */ #define IF_SPI_HISM_IO_WR_FIFO_OVERFLOW (1<<5) -/** Host Interrupt Status Mask bit : I/O read FIFO underflow */ +/* Host Interrupt Status Mask bit : I/O read FIFO underflow */ #define IF_SPI_HISM_IO_RD_FIFO_UNDERFLOW (1<<6) -/** Host Interrupt Status Mask bit : Data write FIFO overflow */ +/* Host Interrupt Status Mask bit : Data write FIFO overflow */ #define IF_SPI_HISM_DATA_WR_FIFO_OVERFLOW (1<<7) -/** Host Interrupt Status Mask bit : Data write FIFO underflow */ +/* Host Interrupt Status Mask bit : Data write FIFO underflow */ #define IF_SPI_HISM_DATA_RD_FIFO_UNDERFLOW (1<<8) -/** Host Interrupt Status Mask bit : Command write FIFO overflow */ +/* Host Interrupt Status Mask bit : Command write FIFO overflow */ #define IF_SPI_HISM_CMD_WR_FIFO_OVERFLOW (1<<9) -/** Host Interrupt Status Mask bit : Command write FIFO underflow */ +/* Host Interrupt Status Mask bit : Command write FIFO underflow */ #define IF_SPI_HISM_CMD_RD_FIFO_UNDERFLOW (1<<10) /***************** IF_SPI_SPU_BUS_MODE_REG *****************/ diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 6524c70363d9..e1e2128f4113 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -1,6 +1,6 @@ -/** - * This file contains functions used in USB interface module. - */ +/* + * This file contains functions used in USB interface module. + */ #include #include #include @@ -66,7 +66,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp); /* sysfs hooks */ -/** +/* * Set function to write firmware to device's persistent memory */ static ssize_t if_usb_firmware_set(struct device *dev, @@ -85,7 +85,7 @@ static ssize_t if_usb_firmware_set(struct device *dev, return ret; } -/** +/* * lbs_flash_fw attribute to be exported per ethX interface through sysfs * (/sys/class/net/ethX/lbs_flash_fw). Use this like so to write firmware to * the device's persistent memory: @@ -94,7 +94,14 @@ static ssize_t if_usb_firmware_set(struct device *dev, static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set); /** - * Set function to write firmware to device's persistent memory + * if_usb_boot2_set - write firmware to device's persistent memory + * + * @dev: target device + * @attr: device attributes + * @buf: firmware buffer to write + * @count: number of bytes to write + * + * returns: number of bytes written or negative error code */ static ssize_t if_usb_boot2_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -112,7 +119,7 @@ static ssize_t if_usb_boot2_set(struct device *dev, return ret; } -/** +/* * lbs_flash_boot2 attribute to be exported per ethX interface through sysfs * (/sys/class/net/ethX/lbs_flash_boot2). Use this like so to write firmware * to the device's persistent memory: @@ -121,9 +128,10 @@ static ssize_t if_usb_boot2_set(struct device *dev, static DEVICE_ATTR(lbs_flash_boot2, 0200, NULL, if_usb_boot2_set); /** - * @brief call back function to handle the status of the URB - * @param urb pointer to urb structure - * @return N/A + * if_usb_write_bulk_callback - callback function to handle the status + * of the URB + * @urb: pointer to &urb structure + * returns: N/A */ static void if_usb_write_bulk_callback(struct urb *urb) { @@ -150,9 +158,9 @@ static void if_usb_write_bulk_callback(struct urb *urb) } /** - * @brief free tx/rx urb, skb and rx buffer - * @param cardp pointer if_usb_card - * @return N/A + * if_usb_free - free tx/rx urb, skb and rx buffer + * @cardp: pointer to &if_usb_card + * returns: N/A */ static void if_usb_free(struct if_usb_card *cardp) { @@ -231,10 +239,10 @@ static void if_usb_reset_olpc_card(struct lbs_private *priv) #endif /** - * @brief sets the configuration values - * @param ifnum interface number - * @param id pointer to usb_device_id - * @return 0 on success, error code on failure + * if_usb_probe - sets the configuration values + * @intf: &usb_interface pointer + * @id: pointer to usb_device_id + * returns: 0 on success, error code on failure */ static int if_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -366,9 +374,9 @@ error: } /** - * @brief free resource and cleanup - * @param intf USB interface structure - * @return N/A + * if_usb_disconnect - free resource and cleanup + * @intf: USB interface structure + * returns: N/A */ static void if_usb_disconnect(struct usb_interface *intf) { @@ -398,9 +406,9 @@ static void if_usb_disconnect(struct usb_interface *intf) } /** - * @brief This function download FW - * @param priv pointer to struct lbs_private - * @return 0 + * if_usb_send_fw_pkt - download FW + * @cardp: pointer to &struct if_usb_card + * returns: 0 */ static int if_usb_send_fw_pkt(struct if_usb_card *cardp) { @@ -486,11 +494,11 @@ static int if_usb_reset_device(struct if_usb_card *cardp) } /** - * @brief This function transfer the data to the device. - * @param priv pointer to struct lbs_private - * @param payload pointer to payload data - * @param nb data length - * @return 0 or -1 + * usb_tx_block - transfer the data to the device + * @cardp: pointer to &struct if_usb_card + * @payload: pointer to payload data + * @nb: data length + * returns: 0 for success or negative error code */ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb) { @@ -727,11 +735,11 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, } /** - * @brief This function reads of the packet into the upload buff, - * wake up the main thread and initialise the Rx callack. + * if_usb_receive - read the packet into the upload buffer, + * wake up the main thread and initialise the Rx callack * - * @param urb pointer to struct urb - * @return N/A + * @urb: pointer to &struct urb + * returns: N/A */ static void if_usb_receive(struct urb *urb) { @@ -802,12 +810,12 @@ rx_exit: } /** - * @brief This function downloads data to FW - * @param priv pointer to struct lbs_private structure - * @param type type of data - * @param buf pointer to data buffer - * @param len number of bytes - * @return 0 or -1 + * if_usb_host_to_card - downloads data to FW + * @priv: pointer to &struct lbs_private structure + * @type: type of data + * @payload: pointer to data buffer + * @nb: number of bytes + * returns: 0 for success or negative error code */ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, uint8_t *payload, uint16_t nb) @@ -831,10 +839,11 @@ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, } /** - * @brief This function issues Boot command to the Boot2 code - * @param ivalue 1:Boot from FW by USB-Download - * 2:Boot from FW in EEPROM - * @return 0 + * if_usb_issue_boot_command - issues Boot command to the Boot2 code + * @cardp: pointer to &if_usb_card + * @ivalue: 1:Boot from FW by USB-Download + * 2:Boot from FW in EEPROM + * returns: 0 for success or negative error code */ static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue) { @@ -853,11 +862,11 @@ static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue) /** - * @brief This function checks the validity of Boot2/FW image. + * check_fwfile_format - check the validity of Boot2/FW image * - * @param data pointer to image - * len image length - * @return 0 or -1 + * @data: pointer to image + * @totlen: image length + * returns: 0 (good) or 1 (failure) */ static int check_fwfile_format(const uint8_t *data, uint32_t totlen) { @@ -901,13 +910,13 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen) /** -* @brief This function programs the firmware subject to cmd +* if_usb_prog_firmware - programs the firmware subject to cmd * -* @param cardp the if_usb_card descriptor -* fwname firmware or boot2 image file name -* cmd either BOOT_CMD_FW_BY_USB, BOOT_CMD_UPDATE_FW, -* or BOOT_CMD_UPDATE_BOOT2. -* @return 0 or error code +* @cardp: the if_usb_card descriptor +* @fwname: firmware or boot2 image file name +* @cmd: either BOOT_CMD_FW_BY_USB, BOOT_CMD_UPDATE_FW, +* or BOOT_CMD_UPDATE_BOOT2. +* returns: 0 or error code */ static int if_usb_prog_firmware(struct if_usb_card *cardp, const char *fwname, int cmd) diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h index d819e7e3c9aa..6e42eac331de 100644 --- a/drivers/net/wireless/libertas/if_usb.h +++ b/drivers/net/wireless/libertas/if_usb.h @@ -6,9 +6,9 @@ struct lbs_private; -/** - * This file contains definition for USB interface. - */ +/* + * This file contains definition for USB interface. + */ #define CMD_TYPE_REQUEST 0xF00DFACE #define CMD_TYPE_DATA 0xBEADC0DE #define CMD_TYPE_INDICATION 0xBEEFFACE @@ -40,7 +40,7 @@ struct bootcmdresp uint8_t pad[2]; }; -/** USB card description structure*/ +/* USB card description structure*/ struct if_usb_card { struct usb_device *udev; uint32_t model; /* MODEL_* */ @@ -77,7 +77,7 @@ struct if_usb_card { __le16 boot2_version; }; -/** fwheader */ +/* fwheader */ struct fwheader { __le32 dnldcmd; __le32 baseaddr; @@ -86,14 +86,14 @@ struct fwheader { }; #define FW_MAX_DATA_BLK_SIZE 600 -/** FWData */ +/* FWData */ struct fwdata { struct fwheader hdr; __le32 seqnum; uint8_t data[0]; }; -/** fwsyncheader */ +/* fwsyncheader */ struct fwsyncheader { __le32 cmd; __le32 seqnum; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index ca8149cd5bd9..ed57cf863b69 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1,8 +1,8 @@ -/** - * This file contains the major functions in WLAN - * driver. It includes init, exit, open, close and main - * thread etc.. - */ +/* + * This file contains the major functions in WLAN + * driver. It includes init, exit, open, close and main + * thread etc.. + */ #include #include @@ -35,18 +35,20 @@ EXPORT_SYMBOL_GPL(lbs_debug); module_param_named(libertas_debug, lbs_debug, int, 0644); -/* This global structure is used to send the confirm_sleep command as - * fast as possible down to the firmware. */ +/* + * This global structure is used to send the confirm_sleep command as + * fast as possible down to the firmware. + */ struct cmd_confirm_sleep confirm_sleep; -/** +/* * the table to keep region code */ u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE] = { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 }; -/** +/* * FW rate table. FW refers to rates by their index in this table, not by the * rate value itself. Values of 0x00 are * reserved positions. @@ -57,10 +59,10 @@ static u8 fw_data_rates[MAX_RATES] = }; /** - * @brief use index to get the data rate + * lbs_fw_index_to_data_rate - use index to get the data rate * - * @param idx The index of data rate - * @return data rate or 0 + * @idx: The index of data rate + * returns: data rate or 0 */ u32 lbs_fw_index_to_data_rate(u8 idx) { @@ -70,10 +72,10 @@ u32 lbs_fw_index_to_data_rate(u8 idx) } /** - * @brief use rate to get the index + * lbs_data_rate_to_fw_index - use rate to get the index * - * @param rate data rate - * @return index or 0 + * @rate: data rate + * returns: index or 0 */ u8 lbs_data_rate_to_fw_index(u32 rate) { @@ -91,10 +93,10 @@ u8 lbs_data_rate_to_fw_index(u32 rate) /** - * @brief This function opens the ethX interface + * lbs_dev_open - open the ethX interface * - * @param dev A pointer to net_device structure - * @return 0 or -EBUSY if monitor mode active + * @dev: A pointer to &net_device structure + * returns: 0 or -EBUSY if monitor mode active */ static int lbs_dev_open(struct net_device *dev) { @@ -120,10 +122,10 @@ static int lbs_dev_open(struct net_device *dev) } /** - * @brief This function closes the ethX interface + * lbs_eth_stop - close the ethX interface * - * @param dev A pointer to net_device structure - * @return 0 + * @dev: A pointer to &net_device structure + * returns: 0 */ static int lbs_eth_stop(struct net_device *dev) { @@ -336,12 +338,12 @@ void lbs_set_multicast_list(struct net_device *dev) } /** - * @brief This function handles the major jobs in the LBS driver. + * lbs_thread - handles the major jobs in the LBS driver. * It handles all events generated by firmware, RX data received * from firmware and TX data sent from kernel. * - * @param data A pointer to lbs_thread structure - * @return 0 + * @data: A pointer to &lbs_thread structure + * returns: 0 */ static int lbs_thread(void *data) { @@ -540,11 +542,11 @@ static int lbs_thread(void *data) } /** - * @brief This function gets the HW spec from the firmware and sets - * some basic parameters. + * lbs_setup_firmware - gets the HW spec from the firmware and sets + * some basic parameters * - * @param priv A pointer to struct lbs_private structure - * @return 0 or -1 + * @priv: A pointer to &struct lbs_private structure + * returns: 0 or -1 */ static int lbs_setup_firmware(struct lbs_private *priv) { @@ -630,8 +632,10 @@ int lbs_resume(struct lbs_private *priv) EXPORT_SYMBOL_GPL(lbs_resume); /** - * This function handles the timeout of command sending. - * It will re-send the same command again. + * lbs_cmd_timeout_handler - handles the timeout of command sending. + * It will re-send the same command again. + * + * @data: &struct lbs_private pointer */ static void lbs_cmd_timeout_handler(unsigned long data) { @@ -655,8 +659,10 @@ out: } /** - * This function put the device back to deep sleep mode when timer expires - * and no activity (command, event, data etc.) is detected. + * auto_deepsleep_timer_fn - put the device back to deep sleep mode when + * timer expires and no activity (command, event, data etc.) is detected. + * @data: &struct lbs_private pointer + * returns: N/A */ static void auto_deepsleep_timer_fn(unsigned long data) { @@ -792,11 +798,12 @@ static const struct net_device_ops lbs_netdev_ops = { }; /** - * @brief This function adds the card. it will probe the + * lbs_add_card - adds the card. It will probe the * card, allocate the lbs_priv and initialize the device. * - * @param card A pointer to card - * @return A pointer to struct lbs_private structure + * @card: A pointer to card + * @dmdev: A pointer to &struct device + * returns: A pointer to &struct lbs_private structure */ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) { @@ -1057,19 +1064,19 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) EXPORT_SYMBOL_GPL(lbs_notify_command_response); /** - * @brief Retrieves two-stage firmware + * lbs_get_firmware - Retrieves two-stage firmware * - * @param dev A pointer to device structure - * @param user_helper User-defined helper firmware file - * @param user_mainfw User-defined main firmware file - * @param card_model Bus-specific card model ID used to filter firmware table - * elements - * @param fw_table Table of firmware file names and device model numbers - * terminated by an entry with a NULL helper name - * @param helper On success, the helper firmware; caller must free - * @param mainfw On success, the main firmware; caller must free + * @dev: A pointer to &device structure + * @user_helper: User-defined helper firmware file + * @user_mainfw: User-defined main firmware file + * @card_model: Bus-specific card model ID used to filter firmware table + * elements + * @fw_table: Table of firmware file names and device model numbers + * terminated by an entry with a NULL helper name + * @helper: On success, the helper firmware; caller must free + * @mainfw: On success, the main firmware; caller must free * - * @return 0 on success, non-zero on failure + * returns: 0 on success, non-zero on failure */ int lbs_get_firmware(struct device *dev, const char *user_helper, const char *user_mainfw, u32 card_model, diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 9d097b9c8005..a0804d12bf20 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c @@ -16,12 +16,15 @@ * Mesh sysfs support */ -/** +/* * Attributes exported through sysfs */ /** - * @brief Get function for sysfs attribute anycast_mask + * lbs_anycast_get - Get function for sysfs attribute anycast_mask + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer where data will be returned */ static ssize_t lbs_anycast_get(struct device *dev, struct device_attribute *attr, char * buf) @@ -40,7 +43,11 @@ static ssize_t lbs_anycast_get(struct device *dev, } /** - * @brief Set function for sysfs attribute anycast_mask + * lbs_anycast_set - Set function for sysfs attribute anycast_mask + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer that contains new attribute value + * @count: size of buffer */ static ssize_t lbs_anycast_set(struct device *dev, struct device_attribute *attr, const char * buf, size_t count) @@ -62,7 +69,10 @@ static ssize_t lbs_anycast_set(struct device *dev, } /** - * @brief Get function for sysfs attribute prb_rsp_limit + * lbs_prb_rsp_limit_get - Get function for sysfs attribute prb_rsp_limit + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer where data will be returned */ static ssize_t lbs_prb_rsp_limit_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -85,7 +95,11 @@ static ssize_t lbs_prb_rsp_limit_get(struct device *dev, } /** - * @brief Set function for sysfs attribute prb_rsp_limit + * lbs_prb_rsp_limit_set - Set function for sysfs attribute prb_rsp_limit + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer that contains new attribute value + * @count: size of buffer */ static ssize_t lbs_prb_rsp_limit_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -114,7 +128,10 @@ static ssize_t lbs_prb_rsp_limit_set(struct device *dev, } /** - * Get function for sysfs attribute mesh + * lbs_mesh_get - Get function for sysfs attribute mesh + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer where data will be returned */ static ssize_t lbs_mesh_get(struct device *dev, struct device_attribute *attr, char * buf) @@ -124,7 +141,11 @@ static ssize_t lbs_mesh_get(struct device *dev, } /** - * Set function for sysfs attribute mesh + * lbs_mesh_set - Set function for sysfs attribute mesh + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer that contains new attribute value + * @count: size of buffer */ static ssize_t lbs_mesh_set(struct device *dev, struct device_attribute *attr, const char * buf, size_t count) @@ -151,19 +172,19 @@ static ssize_t lbs_mesh_set(struct device *dev, return count; } -/** +/* * lbs_mesh attribute to be exported per ethX interface * through sysfs (/sys/class/net/ethX/lbs_mesh) */ static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set); -/** +/* * anycast_mask attribute to be exported per mshX interface * through sysfs (/sys/class/net/mshX/anycast_mask) */ static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set); -/** +/* * prb_rsp_limit attribute to be exported per mshX interface * through sysfs (/sys/class/net/mshX/prb_rsp_limit) */ @@ -274,10 +295,10 @@ int lbs_deinit_mesh(struct lbs_private *priv) /** - * @brief This function closes the mshX interface + * lbs_mesh_stop - close the mshX interface * - * @param dev A pointer to net_device structure - * @return 0 + * @dev: A pointer to &net_device structure + * returns: 0 */ static int lbs_mesh_stop(struct net_device *dev) { @@ -301,10 +322,10 @@ static int lbs_mesh_stop(struct net_device *dev) } /** - * @brief This function opens the mshX interface + * lbs_mesh_dev_open - open the mshX interface * - * @param dev A pointer to net_device structure - * @return 0 or -EBUSY if monitor mode active + * @dev: A pointer to &net_device structure + * returns: 0 or -EBUSY if monitor mode active */ static int lbs_mesh_dev_open(struct net_device *dev) { @@ -342,10 +363,10 @@ static const struct net_device_ops mesh_netdev_ops = { }; /** - * @brief This function adds mshX interface + * lbs_add_mesh - add mshX interface * - * @param priv A pointer to the struct lbs_private structure - * @return 0 if successful, -X otherwise + * @priv: A pointer to the &struct lbs_private structure + * returns: 0 if successful, -X otherwise */ int lbs_add_mesh(struct lbs_private *priv) { @@ -456,13 +477,13 @@ void lbs_mesh_set_txpd(struct lbs_private *priv, */ /** - * @brief Add or delete Mesh Blinding Table entries + * lbs_mesh_bt_add_del - Add or delete Mesh Blinding Table entries * - * @param priv A pointer to struct lbs_private structure - * @param add TRUE to add the entry, FALSE to delete it - * @param addr1 Destination address to blind or unblind + * @priv: A pointer to &struct lbs_private structure + * @add: TRUE to add the entry, FALSE to delete it + * @addr1: Destination address to blind or unblind * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1) { @@ -493,11 +514,11 @@ int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1) } /** - * @brief Reset/clear the mesh blinding table + * lbs_mesh_bt_reset - Reset/clear the mesh blinding table * - * @param priv A pointer to struct lbs_private structure + * @priv: A pointer to &struct lbs_private structure * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_mesh_bt_reset(struct lbs_private *priv) { @@ -517,17 +538,18 @@ int lbs_mesh_bt_reset(struct lbs_private *priv) } /** - * @brief Gets the inverted status of the mesh blinding table + * lbs_mesh_bt_get_inverted - Gets the inverted status of the mesh + * blinding table * - * Normally the firmware "blinds" or ignores traffic from mesh nodes in the - * table, but an inverted table allows *only* traffic from nodes listed in - * the table. + * Normally the firmware "blinds" or ignores traffic from mesh nodes in the + * table, but an inverted table allows *only* traffic from nodes listed in + * the table. * - * @param priv A pointer to struct lbs_private structure - * @param invert On success, TRUE if the blinding table is inverted, - * FALSE if it is not inverted + * @priv: A pointer to &struct lbs_private structure + * @inverted: On success, TRUE if the blinding table is inverted, + * FALSE if it is not inverted * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted) { @@ -551,18 +573,19 @@ int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted) } /** - * @brief Sets the inverted status of the mesh blinding table + * lbs_mesh_bt_set_inverted - Sets the inverted status of the mesh + * blinding table * - * Normally the firmware "blinds" or ignores traffic from mesh nodes in the - * table, but an inverted table allows *only* traffic from nodes listed in - * the table. + * Normally the firmware "blinds" or ignores traffic from mesh nodes in the + * table, but an inverted table allows *only* traffic from nodes listed in + * the table. * - * @param priv A pointer to struct lbs_private structure - * @param invert TRUE to invert the blinding table (only traffic from - * listed nodes allowed), FALSE to return it - * to normal state (listed nodes ignored) + * @priv: A pointer to &struct lbs_private structure + * @inverted: TRUE to invert the blinding table (only traffic from + * listed nodes allowed), FALSE to return it + * to normal state (listed nodes ignored) * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted) { @@ -583,13 +606,13 @@ int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted) } /** - * @brief List an entry in the mesh blinding table + * lbs_mesh_bt_get_entry - List an entry in the mesh blinding table * - * @param priv A pointer to struct lbs_private structure - * @param id The ID of the entry to list - * @param addr1 MAC address associated with the table entry + * @priv: A pointer to &struct lbs_private structure + * @id: The ID of the entry to list + * @addr1: MAC address associated with the table entry * - * @return 0 on success, error on failure + * returns: 0 on success, error on failure */ int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1) { @@ -614,14 +637,14 @@ int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1) } /** - * @brief Access the mesh forwarding table + * lbs_cmd_fwt_access - Access the mesh forwarding table * - * @param priv A pointer to struct lbs_private structure - * @param cmd_action The forwarding table action to perform - * @param cmd The pre-filled FWT_ACCESS command + * @priv: A pointer to &struct lbs_private structure + * @cmd_action: The forwarding table action to perform + * @cmd: The pre-filled FWT_ACCESS command * - * @return 0 on success and 'cmd' will be filled with the - * firmware's response + * returns: 0 on success and 'cmd' will be filled with the + * firmware's response */ int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action, struct cmd_ds_fwt_access *cmd) @@ -774,7 +797,10 @@ static int mesh_get_default_parameters(struct device *dev, } /** - * @brief Get function for sysfs attribute bootflag + * bootflag_get - Get function for sysfs attribute bootflag + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer where data will be returned */ static ssize_t bootflag_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -791,7 +817,11 @@ static ssize_t bootflag_get(struct device *dev, } /** - * @brief Set function for sysfs attribute bootflag + * bootflag_set - Set function for sysfs attribute bootflag + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer that contains new attribute value + * @count: size of buffer */ static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -817,7 +847,10 @@ static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, } /** - * @brief Get function for sysfs attribute boottime + * boottime_get - Get function for sysfs attribute boottime + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer where data will be returned */ static ssize_t boottime_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -834,7 +867,11 @@ static ssize_t boottime_get(struct device *dev, } /** - * @brief Set function for sysfs attribute boottime + * boottime_set - Set function for sysfs attribute boottime + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer that contains new attribute value + * @count: size of buffer */ static ssize_t boottime_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -869,7 +906,10 @@ static ssize_t boottime_set(struct device *dev, } /** - * @brief Get function for sysfs attribute channel + * channel_get - Get function for sysfs attribute channel + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer where data will be returned */ static ssize_t channel_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -886,7 +926,11 @@ static ssize_t channel_get(struct device *dev, } /** - * @brief Set function for sysfs attribute channel + * channel_set - Set function for sysfs attribute channel + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer that contains new attribute value + * @count: size of buffer */ static ssize_t channel_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -912,7 +956,10 @@ static ssize_t channel_set(struct device *dev, struct device_attribute *attr, } /** - * @brief Get function for sysfs attribute mesh_id + * mesh_id_get - Get function for sysfs attribute mesh_id + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer where data will be returned */ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -938,7 +985,11 @@ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, } /** - * @brief Set function for sysfs attribute mesh_id + * mesh_id_set - Set function for sysfs attribute mesh_id + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer that contains new attribute value + * @count: size of buffer */ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -980,7 +1031,10 @@ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, } /** - * @brief Get function for sysfs attribute protocol_id + * protocol_id_get - Get function for sysfs attribute protocol_id + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer where data will be returned */ static ssize_t protocol_id_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -997,7 +1051,11 @@ static ssize_t protocol_id_get(struct device *dev, } /** - * @brief Set function for sysfs attribute protocol_id + * protocol_id_set - Set function for sysfs attribute protocol_id + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer that contains new attribute value + * @count: size of buffer */ static ssize_t protocol_id_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1034,7 +1092,10 @@ static ssize_t protocol_id_set(struct device *dev, } /** - * @brief Get function for sysfs attribute metric_id + * metric_id_get - Get function for sysfs attribute metric_id + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer where data will be returned */ static ssize_t metric_id_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -1051,7 +1112,11 @@ static ssize_t metric_id_get(struct device *dev, } /** - * @brief Set function for sysfs attribute metric_id + * metric_id_set - Set function for sysfs attribute metric_id + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer that contains new attribute value + * @count: size of buffer */ static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1088,7 +1153,10 @@ static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, } /** - * @brief Get function for sysfs attribute capability + * capability_get - Get function for sysfs attribute capability + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer where data will be returned */ static ssize_t capability_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -1105,7 +1173,11 @@ static ssize_t capability_get(struct device *dev, } /** - * @brief Set function for sysfs attribute capability + * capability_set - Set function for sysfs attribute capability + * @dev: the &struct device + * @attr: device attributes + * @buf: buffer that contains new attribute value + * @count: size of buffer */ static ssize_t capability_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h index afb2e8dead3f..ee95c73ed5f4 100644 --- a/drivers/net/wireless/libertas/mesh.h +++ b/drivers/net/wireless/libertas/mesh.h @@ -1,6 +1,6 @@ -/** - * Contains all definitions needed for the Libertas' MESH implementation. - */ +/* + * Contains all definitions needed for the Libertas' MESH implementation. + */ #ifndef _LBS_MESH_H_ #define _LBS_MESH_H_ diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index a2b1df21d286..a3f4b55aa41f 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -1,6 +1,6 @@ -/** - * This file contains the handling of RX in wlan driver. - */ +/* + * This file contains the handling of RX in wlan driver. + */ #include #include #include @@ -40,12 +40,12 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, struct sk_buff *skb); /** - * @brief This function processes received packet and forwards it - * to kernel/upper layer + * lbs_process_rxed_packet - processes received packet and forwards it + * to kernel/upper layer * - * @param priv A pointer to struct lbs_private - * @param skb A pointer to skb which includes the received packet - * @return 0 or -1 + * @priv: A pointer to &struct lbs_private + * @skb: A pointer to skb which includes the received packet + * returns: 0 or -1 */ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) { @@ -156,11 +156,11 @@ done: EXPORT_SYMBOL_GPL(lbs_process_rxed_packet); /** - * @brief This function converts Tx/Rx rates from the Marvell WLAN format - * (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s) + * convert_mv_rate_to_radiotap - converts Tx/Rx rates from Marvell WLAN format + * (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s) * - * @param rate Input rate - * @return Output Rate (0 if invalid) + * @rate: Input rate + * returns: Output Rate (0 if invalid) */ static u8 convert_mv_rate_to_radiotap(u8 rate) { @@ -196,12 +196,12 @@ static u8 convert_mv_rate_to_radiotap(u8 rate) } /** - * @brief This function processes a received 802.11 packet and forwards it - * to kernel/upper layer + * process_rxed_802_11_packet - processes a received 802.11 packet and forwards + * it to kernel/upper layer * - * @param priv A pointer to struct lbs_private - * @param skb A pointer to skb which includes the received packet - * @return 0 or -1 + * @priv: A pointer to &struct lbs_private + * @skb: A pointer to skb which includes the received packet + * returns: 0 or -1 */ static int process_rxed_802_11_packet(struct lbs_private *priv, struct sk_buff *skb) diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 8000ca6165d0..bbb95f88dc01 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -1,6 +1,6 @@ -/** - * This file contains the handling of TX in wlan driver. - */ +/* + * This file contains the handling of TX in wlan driver. + */ #include #include #include @@ -13,11 +13,11 @@ #include "dev.h" /** - * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE - * units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1) + * convert_radiotap_rate_to_mv - converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE + * units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1) * - * @param rate Input rate - * @return Output Rate (0 if invalid) + * @rate: Input rate + * returns: Output Rate (0 if invalid) */ static u32 convert_radiotap_rate_to_mv(u8 rate) { @@ -51,12 +51,12 @@ static u32 convert_radiotap_rate_to_mv(u8 rate) } /** - * @brief This function checks the conditions and sends packet to IF - * layer if everything is ok. + * lbs_hard_start_xmit - checks the conditions and sends packet to IF + * layer if everything is ok * - * @param priv A pointer to struct lbs_private structure - * @param skb A pointer to skb which includes TX packet - * @return 0 or -1 + * @skb: A pointer to skb which includes TX packet + * @dev: A pointer to the &struct net_device + * returns: 0 or -1 */ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -168,13 +168,13 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } /** - * @brief This function sends to the host the last transmitted packet, - * filling the radiotap headers with transmission information. + * lbs_send_tx_feedback - sends to the host the last transmitted packet, + * filling the radiotap headers with transmission information. * - * @param priv A pointer to struct lbs_private structure - * @param status A 32 bit value containing transmission status. + * @priv: A pointer to &struct lbs_private structure + * @try_count: A 32-bit value containing transmission retry status. * - * @returns void + * returns: void */ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) { diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h index 462fbb4cb743..cf1d9b047ee6 100644 --- a/drivers/net/wireless/libertas/types.h +++ b/drivers/net/wireless/libertas/types.h @@ -1,6 +1,6 @@ -/** - * This header file contains definition for global types - */ +/* + * This header file contains definition for global types + */ #ifndef _LBS_TYPES_H_ #define _LBS_TYPES_H_ @@ -54,7 +54,7 @@ union ieee_phy_param_set { struct ieee_ie_ds_param_set ds; } __packed; -/** TLV type ID definition */ +/* TLV type ID definition */ #define PROPRIETARY_TLV_BASE_ID 0x0100 /* Terminating TLV type */ @@ -96,7 +96,7 @@ union ieee_phy_param_set { #define TLV_TYPE_MESH_ID (PROPRIETARY_TLV_BASE_ID + 37) #define TLV_TYPE_OLD_MESH_ID (PROPRIETARY_TLV_BASE_ID + 291) -/** TLV related data structures*/ +/* TLV related data structures */ struct mrvl_ie_header { __le16 type; __le16 len; @@ -177,7 +177,7 @@ struct mrvl_ie_auth_type { __le16 auth; } __packed; -/** Local Power capability */ +/* Local Power capability */ struct mrvl_ie_power_capability { struct mrvl_ie_header header; s8 minpower; @@ -235,9 +235,11 @@ struct mrvl_ie_ledbhv { struct led_bhv ledbhv[1]; } __packed; -/* Meant to be packed as the value member of a struct ieee80211_info_element. +/* + * Meant to be packed as the value member of a struct ieee80211_info_element. * Note that the len member of the ieee80211_info_element varies depending on - * the mesh_id_len */ + * the mesh_id_len + */ struct mrvl_meshie_val { uint8_t oui[3]; uint8_t type; -- cgit v1.2.3-58-ga151 From bdbfd6b582f55384059d9ac5e65b3653092e6adf Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 27 Apr 2011 16:56:51 +0530 Subject: mac80211: Add new API for rate selection This patch adds a new API for setting a TX rate mask in drivers that have rate control in either the firmware or hardware. This can be used for various purposes, for example, masking out the 11b rates in P2P operation. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- include/net/mac80211.h | 6 ++++++ net/mac80211/cfg.c | 15 ++++++--------- net/mac80211/driver-ops.h | 18 ++++++++++++++++++ net/mac80211/driver-trace.h | 27 +++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 9 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 8aad6b37c689..63f75a06043b 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1822,6 +1822,10 @@ enum ieee80211_ampdu_mlme_action { * * @tx_frames_pending: Check if there is any pending frame in the hardware * queues before entering power save. + * + * @set_bitrate_mask: Set a mask of rates to be used for rate control selection + * when transmitting a frame. Currently only legacy rates are handled. + * The callback can sleep. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); @@ -1910,6 +1914,8 @@ struct ieee80211_ops { void (*get_ringparam)(struct ieee80211_hw *hw, u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); bool (*tx_frames_pending)(struct ieee80211_hw *hw); + int (*set_bitrate_mask)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + const struct cfg80211_bitrate_mask *mask); }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a9ddaf63ee14..12d52cec9515 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1633,16 +1633,13 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - int i; - - /* - * This _could_ be supported by providing a hook for - * drivers for this function, but at this point it - * doesn't seem worth bothering. - */ - if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) - return -EOPNOTSUPP; + int i, ret; + if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) { + ret = drv_set_bitrate_mask(local, sdata, mask); + if (ret) + return ret; + } for (i = 0; i < IEEE80211_NUM_BANDS; i++) sdata->rc_rateidx_mask[i] = mask->control[i].legacy; diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 00a0685f2403..2ddb56e5b51f 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -565,4 +565,22 @@ static inline bool drv_tx_frames_pending(struct ieee80211_local *local) return ret; } + +static inline int drv_set_bitrate_mask(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + const struct cfg80211_bitrate_mask *mask) +{ + int ret = -EOPNOTSUPP; + + might_sleep(); + + trace_drv_set_bitrate_mask(local, sdata, mask); + if (local->ops->set_bitrate_mask) + ret = local->ops->set_bitrate_mask(&local->hw, + &sdata->vif, mask); + trace_drv_return_int(local, ret); + + return ret; +} + #endif /* __MAC80211_DRIVER_OPS */ diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index c8c934d48b7a..191e834ec46b 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -989,6 +989,33 @@ DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait, TP_ARGS(local) ); +TRACE_EVENT(drv_set_bitrate_mask, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + const struct cfg80211_bitrate_mask *mask), + + TP_ARGS(local, sdata, mask), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + __field(u32, legacy_2g) + __field(u32, legacy_5g) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + __entry->legacy_2g = mask->control[IEEE80211_BAND_2GHZ].legacy; + __entry->legacy_5g = mask->control[IEEE80211_BAND_5GHZ].legacy; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT " 2G Mask:0x%x 5G Mask:0x%x", + LOCAL_PR_ARG, VIF_PR_ARG, __entry->legacy_2g, __entry->legacy_5g + ) +); + /* * Tracing for API calls that drivers call. */ -- cgit v1.2.3-58-ga151 From 484b1829c6a3c5bc38fe0cd626ce2e8a3dfd844c Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 27 Apr 2011 17:12:56 +0530 Subject: ath9k_htc: Increase credit size for AR7010 devices Bump the firmware version to 1.2 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.h | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 9a52ccc94d12..2bdcdbc14b1e 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -18,7 +18,7 @@ #define HTC_USB_H #define MAJOR_VERSION_REQ 1 -#define MINOR_VERSION_REQ 1 +#define MINOR_VERSION_REQ 2 #define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB)) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index dbf5f959cf9b..d2dd5a63e10a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -243,7 +243,7 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid, */ if (IS_AR7010_DEVICE(drv_info)) - priv->htc->credits = 45; + priv->htc->credits = 48; else priv->htc->credits = 33; -- cgit v1.2.3-58-ga151 From 155dcda6f11a58e4e1443d5fad530b0bf68370b7 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 27 Apr 2011 17:13:09 +0530 Subject: ath9k_htc: Remove unused WMI_AGGR_LIMIT_CMD Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/wmi.c | 2 -- drivers/net/wireless/ath/ath9k/wmi.h | 1 - 2 files changed, 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 8f095ad0a3db..463b76abbdf6 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -79,8 +79,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_TX_STATS_CMDID"; case WMI_RX_STATS_CMDID: return "WMI_RX_STATS_CMDID"; - case WMI_AGGR_LIMIT_CMD: - return "WMI_AGGR_LIMIT_CMD"; } return "Bogus"; diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 02ecb9f06db0..5dfc213e4524 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -111,7 +111,6 @@ enum wmi_cmd_id { WMI_INT_STATS_CMDID, WMI_TX_STATS_CMDID, WMI_RX_STATS_CMDID, - WMI_AGGR_LIMIT_CMD = 0x0026, }; enum wmi_event_id { -- cgit v1.2.3-58-ga151 From a55bb94aa37782fe9457751a3e508b1129fbbc7a Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 27 Apr 2011 17:13:23 +0530 Subject: ath9k_htc: Add a new WMI command to set a rate mask This patch adds WMI_BITRATE_MASK_CMDID which can be used by the set_bitrate_mask() handler. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 7 +++++++ drivers/net/wireless/ath/ath9k/wmi.c | 2 ++ drivers/net/wireless/ath/ath9k/wmi.h | 1 + 3 files changed, 10 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 55f4bb39c9ec..6bb71e311a4b 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -171,6 +171,13 @@ struct ath9k_htc_target_rate { struct ath9k_htc_rate rates; }; +struct ath9k_htc_target_rate_mask { + u8 vif_index; + u8 band; + __be32 mask; + u16 pad; +} __packed; + struct ath9k_htc_target_int_stats { __be32 rx; __be32 rxorn; diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 463b76abbdf6..f9b1eb4853c4 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -79,6 +79,8 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_TX_STATS_CMDID"; case WMI_RX_STATS_CMDID: return "WMI_RX_STATS_CMDID"; + case WMI_BITRATE_MASK_CMDID: + return "WMI_BITRATE_MASK_CMDID"; } return "Bogus"; diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 5dfc213e4524..6095eeb6e025 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -111,6 +111,7 @@ enum wmi_cmd_id { WMI_INT_STATS_CMDID, WMI_TX_STATS_CMDID, WMI_RX_STATS_CMDID, + WMI_BITRATE_MASK_CMDID, }; enum wmi_event_id { -- cgit v1.2.3-58-ga151 From e2186b7c25ef9cdb6d631c8dd6a672f41abe22d5 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 27 Apr 2011 17:13:40 +0530 Subject: ath9k_htc: Add set_bitrate_mask() callback This callback is used to set the minimum rate for management frames. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 50 +++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index c8577d5cd0f7..e9746e8ff8dd 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1659,6 +1659,55 @@ static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); } +/* + * Currently, this is used only for selecting the minimum rate + * for management frames, rate selection for data frames remain + * unaffected. + */ +static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const struct cfg80211_bitrate_mask *mask) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_target_rate_mask tmask; + struct ath9k_htc_vif *avp = (void *)vif->drv_priv; + int ret = 0; + u8 cmd_rsp; + + memset(&tmask, 0, sizeof(struct ath9k_htc_target_rate_mask)); + + tmask.vif_index = avp->index; + tmask.band = IEEE80211_BAND_2GHZ; + tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_2GHZ].legacy); + + WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); + if (ret) { + ath_err(common, + "Unable to set 2G rate mask for " + "interface at idx: %d\n", avp->index); + goto out; + } + + tmask.band = IEEE80211_BAND_5GHZ; + tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_5GHZ].legacy); + + WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); + if (ret) { + ath_err(common, + "Unable to set 5G rate mask for " + "interface at idx: %d\n", avp->index); + goto out; + } + + ath_dbg(common, ATH_DBG_CONFIG, + "Set bitrate masks: 0x%x, 0x%x\n", + mask->control[IEEE80211_BAND_2GHZ].legacy, + mask->control[IEEE80211_BAND_5GHZ].legacy); +out: + return ret; +} + struct ieee80211_ops ath9k_htc_ops = { .tx = ath9k_htc_tx, .start = ath9k_htc_start, @@ -1681,4 +1730,5 @@ struct ieee80211_ops ath9k_htc_ops = { .set_rts_threshold = ath9k_htc_set_rts_threshold, .rfkill_poll = ath9k_htc_rfkill_poll_state, .set_coverage_class = ath9k_htc_set_coverage_class, + .set_bitrate_mask = ath9k_htc_set_bitrate_mask, }; -- cgit v1.2.3-58-ga151 From aac6af5534fade2b18682a0b9efad1a6c04c34c6 Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Wed, 27 Apr 2011 18:40:29 +0530 Subject: mac80211: Skip tailroom reservation for full HW-crypto devices In xmit path, devices that do full hardware crypto (including TKIP MMIC) need no tailroom. For such devices, tailroom reservation can be skipped if all the keys are programmed into the hardware (i.e software crypto is not used for any of the keys) and none of the keys wants software to generate Michael MIC. Signed-off-by: Yogesh Ashok Powar Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 3 +++ net/mac80211/key.c | 19 +++++++++++++++++-- net/mac80211/tx.c | 7 +------ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8d6d6e3d95da..9e3b4f0f31bd 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -766,6 +766,9 @@ struct ieee80211_local { int tx_headroom; /* required headroom for hardware/radiotap */ + /* count for keys needing tailroom space allocation */ + int crypto_tx_tailroom_needed_cnt; + /* Tasklet and skb queue to process calls from IRQ mode. All frames * added to skb_queue will be processed, but frames in * skb_queue_unreliable may be dropped if the total length of these diff --git a/net/mac80211/key.c b/net/mac80211/key.c index af3c56482c80..ca3c626b011a 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -101,6 +101,10 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) if (!ret) { key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; + + if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) + key->local->crypto_tx_tailroom_needed_cnt--; + return 0; } @@ -156,6 +160,9 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; + + if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) + key->local->crypto_tx_tailroom_needed_cnt++; } void ieee80211_key_removed(struct ieee80211_key_conf *key_conf) @@ -388,8 +395,10 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) ieee80211_aes_key_free(key->u.ccmp.tfm); if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); - if (key->local) + if (key->local) { ieee80211_debugfs_key_remove(key); + key->local->crypto_tx_tailroom_needed_cnt--; + } kfree(key); } @@ -451,6 +460,8 @@ int ieee80211_key_link(struct ieee80211_key *key, ieee80211_debugfs_key_add(key); + key->local->crypto_tx_tailroom_needed_cnt++; + ret = ieee80211_key_enable_hw_accel(key); mutex_unlock(&sdata->local->key_mtx); @@ -492,8 +503,12 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) mutex_lock(&sdata->local->key_mtx); - list_for_each_entry(key, &sdata->key_list, list) + sdata->local->crypto_tx_tailroom_needed_cnt = 0; + + list_for_each_entry(key, &sdata->key_list, list) { + sdata->local->crypto_tx_tailroom_needed_cnt++; ieee80211_key_enable_hw_accel(key); + } mutex_unlock(&sdata->local->key_mtx); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index a2043e405493..e3e3aa173af0 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1476,12 +1476,7 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, { int tail_need = 0; - /* - * This could be optimised, devices that do full hardware - * crypto (including TKIP MMIC) need no tailroom... But we - * have no drivers for such devices currently. - */ - if (may_encrypt) { + if (may_encrypt && local->crypto_tx_tailroom_needed_cnt) { tail_need = IEEE80211_ENCRYPT_TAILROOM; tail_need -= skb_tailroom(skb); tail_need = max_t(int, tail_need, 0); -- cgit v1.2.3-58-ga151 From 6e914101d47c76e09b0568d094ef44257dd3d6e9 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 27 Apr 2011 17:39:47 +0200 Subject: ssb: pci: separate workarounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_pcicore.c | 98 ++++++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 40 deletions(-) diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index dbda168e501b..adde4f060fd8 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -21,6 +21,8 @@ static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address); static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, u8 address, u16 data); +static void ssb_commit_settings(struct ssb_bus *bus); + static inline u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset) { @@ -430,6 +432,60 @@ static void ssb_pcicore_serdes_workaround(struct ssb_pcicore *pc) ssb_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000); } +static void ssb_pcicore_pci_setup_workarounds(struct ssb_pcicore *pc) +{ + struct ssb_device *pdev = pc->dev; + struct ssb_bus *bus = pdev->bus; + u32 tmp; + + tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); + tmp |= SSB_PCICORE_SBTOPCI_PREF; + tmp |= SSB_PCICORE_SBTOPCI_BURST; + pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); + + if (pdev->id.revision < 5) { + tmp = ssb_read32(pdev, SSB_IMCFGLO); + tmp &= ~SSB_IMCFGLO_SERTO; + tmp |= 2; + tmp &= ~SSB_IMCFGLO_REQTO; + tmp |= 3 << SSB_IMCFGLO_REQTO_SHIFT; + ssb_write32(pdev, SSB_IMCFGLO, tmp); + ssb_commit_settings(bus); + } else if (pdev->id.revision >= 11) { + tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); + tmp |= SSB_PCICORE_SBTOPCI_MRM; + pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); + } +} + +static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc) +{ + struct ssb_device *pdev = pc->dev; + u32 tmp; + + if ((pdev->id.revision == 0) || (pdev->id.revision == 1)) { + /* TLP Workaround register. */ + tmp = ssb_pcie_read(pc, 0x4); + tmp |= 0x8; + ssb_pcie_write(pc, 0x4, tmp); + } + if (pdev->id.revision == 0) { + const u8 serdes_rx_device = 0x1F; + + ssb_pcie_mdio_write(pc, serdes_rx_device, + 2 /* Timer */, 0x8128); + ssb_pcie_mdio_write(pc, serdes_rx_device, + 6 /* CDR */, 0x0100); + ssb_pcie_mdio_write(pc, serdes_rx_device, + 7 /* CDR BW */, 0x1466); + } else if (pdev->id.revision == 1) { + /* DLLP Link Control register. */ + tmp = ssb_pcie_read(pc, 0x100); + tmp |= 0x40; + ssb_pcie_write(pc, 0x100, tmp); + } +} + /************************************************** * Generic and Clientmode operation code. **************************************************/ @@ -646,48 +702,10 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, if (pc->setup_done) goto out; if (pdev->id.coreid == SSB_DEV_PCI) { - tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); - tmp |= SSB_PCICORE_SBTOPCI_PREF; - tmp |= SSB_PCICORE_SBTOPCI_BURST; - pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); - - if (pdev->id.revision < 5) { - tmp = ssb_read32(pdev, SSB_IMCFGLO); - tmp &= ~SSB_IMCFGLO_SERTO; - tmp |= 2; - tmp &= ~SSB_IMCFGLO_REQTO; - tmp |= 3 << SSB_IMCFGLO_REQTO_SHIFT; - ssb_write32(pdev, SSB_IMCFGLO, tmp); - ssb_commit_settings(bus); - } else if (pdev->id.revision >= 11) { - tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); - tmp |= SSB_PCICORE_SBTOPCI_MRM; - pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); - } + ssb_pcicore_pci_setup_workarounds(pc); } else { WARN_ON(pdev->id.coreid != SSB_DEV_PCIE); - //TODO: Better make defines for all these magic PCIE values. - if ((pdev->id.revision == 0) || (pdev->id.revision == 1)) { - /* TLP Workaround register. */ - tmp = ssb_pcie_read(pc, 0x4); - tmp |= 0x8; - ssb_pcie_write(pc, 0x4, tmp); - } - if (pdev->id.revision == 0) { - const u8 serdes_rx_device = 0x1F; - - ssb_pcie_mdio_write(pc, serdes_rx_device, - 2 /* Timer */, 0x8128); - ssb_pcie_mdio_write(pc, serdes_rx_device, - 6 /* CDR */, 0x0100); - ssb_pcie_mdio_write(pc, serdes_rx_device, - 7 /* CDR BW */, 0x1466); - } else if (pdev->id.revision == 1) { - /* DLLP Link Control register. */ - tmp = ssb_pcie_read(pc, 0x100); - tmp |= 0x40; - ssb_pcie_write(pc, 0x100, tmp); - } + ssb_pcicore_pcie_setup_workarounds(pc); } pc->setup_done = 1; out: -- cgit v1.2.3-58-ga151 From 5890a3ca34aae94dd736557ad8cb898ac2802aa0 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 27 Apr 2011 17:39:48 +0200 Subject: ssb: pci: update PCIe workarounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_pcicore.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index adde4f060fd8..32a9b61f008d 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -460,16 +460,23 @@ static void ssb_pcicore_pci_setup_workarounds(struct ssb_pcicore *pc) static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc) { - struct ssb_device *pdev = pc->dev; u32 tmp; + u8 rev = pc->dev->id.revision; - if ((pdev->id.revision == 0) || (pdev->id.revision == 1)) { + if (rev == 0 || rev == 1) { /* TLP Workaround register. */ tmp = ssb_pcie_read(pc, 0x4); tmp |= 0x8; ssb_pcie_write(pc, 0x4, tmp); } - if (pdev->id.revision == 0) { + if (rev == 1) { + /* DLLP Link Control register. */ + tmp = ssb_pcie_read(pc, 0x100); + tmp |= 0x40; + ssb_pcie_write(pc, 0x100, tmp); + } + + if (rev == 0) { const u8 serdes_rx_device = 0x1F; ssb_pcie_mdio_write(pc, serdes_rx_device, @@ -478,11 +485,20 @@ static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc) 6 /* CDR */, 0x0100); ssb_pcie_mdio_write(pc, serdes_rx_device, 7 /* CDR BW */, 0x1466); - } else if (pdev->id.revision == 1) { - /* DLLP Link Control register. */ - tmp = ssb_pcie_read(pc, 0x100); - tmp |= 0x40; - ssb_pcie_write(pc, 0x100, tmp); + } else if (rev == 3 || rev == 4 || rev == 5) { + /* TODO: DLLP Power Management Threshold */ + ssb_pcicore_serdes_workaround(pc); + /* TODO: ASPM */ + } else if (rev == 7) { + /* TODO: No PLL down */ + } + + if (rev >= 6) { + /* Miscellaneous Configuration Fixup */ + tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(5)); + if (!(tmp & 0x8000)) + pcicore_write16(pc, SSB_PCICORE_SPROM(5), + tmp | 0x8000); } } @@ -513,7 +529,10 @@ void ssb_pcicore_init(struct ssb_pcicore *pc) if (!pc->hostmode) ssb_pcicore_init_clientmode(pc); + /* Additional always once-executed workarounds */ ssb_pcicore_serdes_workaround(pc); + /* TODO: ASPM */ + /* TODO: Clock Request Update */ } static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) -- cgit v1.2.3-58-ga151 From af335a6cbc3dfcba64ad31561c0da563d1c43a2d Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 27 Apr 2011 18:21:34 +0200 Subject: ssb: pci: early fix for SPROM core index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_pcicore.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 32a9b61f008d..8fde1220bc89 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -414,6 +414,16 @@ static int pcicore_is_in_hostmode(struct ssb_pcicore *pc) * Workarounds. **************************************************/ +static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc) +{ + u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0)); + if (((tmp & 0xF000) >> 12) != pc->dev->core_index) { + tmp &= ~0xF000; + tmp |= (pc->dev->core_index << 12); + pcicore_write16(pc, SSB_PCICORE_SPROM(0), tmp); + } +} + static u8 ssb_pcicore_polarity_workaround(struct ssb_pcicore *pc) { return (ssb_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80; @@ -521,6 +531,8 @@ void ssb_pcicore_init(struct ssb_pcicore *pc) if (!ssb_device_is_enabled(dev)) ssb_device_enable(dev, 0); + ssb_pcicore_fix_sprom_core_index(pc); + #ifdef CONFIG_SSB_PCICORE_HOSTMODE pc->hostmode = pcicore_is_in_hostmode(pc); if (pc->hostmode) -- cgit v1.2.3-58-ga151 From 49adc5ceb2b95e517baf625e0c8e06e91073009b Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 27 Apr 2011 15:04:28 -0400 Subject: mwl8k: replace rateinfo bitfields with mask and shift macros AFAICT, this driver is claiming that 24 bits of rate info fit into a 16-bit field in the Tx descriptor. Anyway, the use of bitfields is frowned-upon for a variety of well-documented reasons... Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index b8f2b12c8c7c..8a1b26255f03 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1562,24 +1562,11 @@ static int mwl8k_tid_queue_mapping(u8 tid) /* The firmware will fill in the rate information * for each packet that gets queued in the hardware - * in this structure + * and these macros will interpret that info. */ -struct rateinfo { - __le16 format:1; - __le16 short_gi:1; - __le16 band_width:1; - __le16 rate_id_mcs:6; - __le16 adv_coding:2; - __le16 antenna:2; - __le16 act_sub_chan:2; - __le16 preamble_type:1; - __le16 power_id:4; - __le16 antenna2:1; - __le16 reserved:1; - __le16 tx_bf_frame:1; - __le16 green_field:1; -} __packed; +#define RI_FORMAT(a) (a & 0x0001) +#define RI_RATE_ID_MCS(a) ((a & 0x01f8) >> 3) static int mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) @@ -1600,7 +1587,6 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) struct ieee80211_sta *sta; struct mwl8k_sta *sta_info = NULL; u16 rate_info; - struct rateinfo *rate; struct ieee80211_hdr *wh; tx = txq->head; @@ -1643,14 +1629,13 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) sta_info = MWL8K_STA(sta); BUG_ON(sta_info == NULL); rate_info = le16_to_cpu(tx_desc->rate_info); - rate = (struct rateinfo *)&rate_info; /* If rate is < 6.5 Mpbs for an ht station * do not form an ampdu. If the station is a * legacy station (format = 0), do not form an * ampdu */ - if (rate->rate_id_mcs < 1 || - rate->format == 0) { + if (RI_RATE_ID_MCS(rate_info) < 1 || + RI_FORMAT(rate_info) == 0) { sta_info->is_ampdu_allowed = false; } else { sta_info->is_ampdu_allowed = true; -- cgit v1.2.3-58-ga151 From adc89595732b92f78940fc0ccdb52afaec582a48 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 27 Apr 2011 19:13:11 -0700 Subject: mwifiex: check firmware capabilities while initialising 5GHz band parameters There are some SD8787 cards which don't support 5GHz band. Therefore initialise 5GHz band parameters only if hardware supports the band. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index b99ae2677d78..585575562127 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1235,20 +1235,23 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, wdev->wiphy->max_scan_ssids = 10; wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; - wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; + mwifiex_setup_ht_caps( + &wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv); + + if (priv->adapter->config_bands & BAND_A) { + wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; + mwifiex_setup_ht_caps( + &wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv); + } else { + wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + } /* Initialize cipher suits */ wdev->wiphy->cipher_suites = mwifiex_cipher_suites; wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); - /* Initialize parameters for 2GHz band */ - - mwifiex_setup_ht_caps(&wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, - priv); - mwifiex_setup_ht_caps(&wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, - priv); - memcpy(wdev->wiphy->perm_addr, mac, 6); wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; -- cgit v1.2.3-58-ga151 From a46b7b5c13b9ecfe2b4e045e06aaec644dcf55d8 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 27 Apr 2011 19:13:12 -0700 Subject: mwifiex: HT capability information handling 1) Initialise HT capabilities in cfg80211 properly. 2) Cfg80211 stack may modify "sband->ht_cap" to disable 40Mhz operation in 2.4GHz band (after recent patch "cfg80211: module_param to disable HT40 in 2.4GHz band") Therefore read "sband->ht_cap" instead of an adapter variable "hw_dot_11n_dev_cap" to get HT capabilities. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n.c | 102 ++++++++------------------------ drivers/net/wireless/mwifiex/11n.h | 2 +- drivers/net/wireless/mwifiex/cfg80211.c | 42 ++++++++++--- drivers/net/wireless/mwifiex/scan.c | 4 +- 4 files changed, 64 insertions(+), 86 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index e22d761f2ef2..1d294cfa6c9b 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -29,95 +29,38 @@ * Fills HT capability information field, AMPDU Parameters field, HT extended * capability field, and supported MCS set fields. * - * Only the following HT capability information fields are used, all other - * fields are always turned off. + * HT capability information field, AMPDU Parameters field, supported MCS set + * fields are retrieved from cfg80211 stack * - * Bit 1 : Supported channel width (0: 20MHz, 1: Both 20 and 40 MHz) - * Bit 4 : Greenfield support (0: Not supported, 1: Supported) - * Bit 5 : Short GI for 20 MHz support (0: Not supported, 1: Supported) - * Bit 6 : Short GI for 40 MHz support (0: Not supported, 1: Supported) - * Bit 7 : Tx STBC (0: Not supported, 1: Supported) - * Bit 8-9 : Rx STBC (0: Not supported, X: Support for up to X spatial streams) - * Bit 10 : Delayed BA support (0: Not supported, 1: Supported) - * Bit 11 : Maximum AMSDU length (0: 3839 octets, 1: 7935 octets) - * Bit 14 : 40-Mhz intolerant support (0: Not supported, 1: Supported) - * - * In addition, the following AMPDU Parameters are set - - * - Maximum AMPDU length exponent (set to 3) - * - Minimum AMPDU start spacing (set to 0 - No restrictions) - * - * MCS is set for 1x1, with MSC32 for infra mode or ad-hoc mode with 40 MHz - * support. - * - * RD responder bit to set to clear in the extended capability header. + * RD responder bit to set to clear in the extended capability header. */ void -mwifiex_fill_cap_info(struct mwifiex_private *priv, +mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type, struct mwifiex_ie_types_htcap *ht_cap) { - struct mwifiex_adapter *adapter = priv->adapter; - u8 *mcs; - int rx_mcs_supp; - uint16_t ht_cap_info = le16_to_cpu(ht_cap->ht_cap.cap_info); uint16_t ht_ext_cap = le16_to_cpu(ht_cap->ht_cap.extended_ht_cap_info); + struct ieee80211_supported_band *sband = + priv->wdev->wiphy->bands[radio_type]; - /* Convert dev_cap to IEEE80211_HT_CAP */ - if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) - ht_cap_info |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; - else - ht_cap_info &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - - if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap)) - ht_cap_info |= IEEE80211_HT_CAP_SGI_20; - else - ht_cap_info &= ~IEEE80211_HT_CAP_SGI_20; - - if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap)) - ht_cap_info |= IEEE80211_HT_CAP_SGI_40; - else - ht_cap_info &= ~IEEE80211_HT_CAP_SGI_40; - - if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) - ht_cap_info |= IEEE80211_HT_CAP_TX_STBC; - else - ht_cap_info &= ~IEEE80211_HT_CAP_TX_STBC; - - if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap)) - ht_cap_info |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; - else - ht_cap_info &= ~(3 << IEEE80211_HT_CAP_RX_STBC_SHIFT); - - if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap)) - ht_cap_info |= IEEE80211_HT_CAP_GRN_FLD; - else - ht_cap_info &= ~IEEE80211_HT_CAP_GRN_FLD; - - ht_cap_info &= ~IEEE80211_HT_CAP_MAX_AMSDU; - ht_cap_info |= IEEE80211_HT_CAP_SM_PS; + ht_cap->ht_cap.ampdu_params_info = + (sband->ht_cap.ampdu_factor & + IEEE80211_HT_AMPDU_PARM_FACTOR)| + ((sband->ht_cap.ampdu_density << + IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) & + IEEE80211_HT_AMPDU_PARM_DENSITY); - ht_cap->ht_cap.ampdu_params_info |= IEEE80211_HT_AMPDU_PARM_FACTOR; - ht_cap->ht_cap.ampdu_params_info &= ~IEEE80211_HT_AMPDU_PARM_DENSITY; - - rx_mcs_supp = GET_RXMCSSUPP(adapter->hw_dev_mcs_support); - - mcs = (u8 *)&ht_cap->ht_cap.mcs; - - /* Set MCS for 1x1 */ - memset(mcs, 0xff, rx_mcs_supp); - - /* Clear all the other values */ - memset(&mcs[rx_mcs_supp], 0, - sizeof(struct ieee80211_mcs_info) - rx_mcs_supp); + memcpy((u8 *) &ht_cap->ht_cap.mcs, &sband->ht_cap.mcs, + sizeof(sband->ht_cap.mcs)); if (priv->bss_mode == NL80211_IFTYPE_STATION || - (ht_cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) + (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); /* Clear RD responder bit */ ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER; - ht_cap->ht_cap.cap_info = cpu_to_le16(ht_cap_info); + ht_cap->ht_cap.cap_info = cpu_to_le16(sband->ht_cap.cap); ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap); } @@ -391,10 +334,15 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, struct mwifiex_ie_types_2040bssco *bss_co_2040; struct mwifiex_ie_types_extcap *ext_cap; int ret_len = 0; + struct ieee80211_supported_band *sband; + u8 radio_type; if (!buffer || !*buffer) return ret_len; + radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); + sband = priv->wdev->wiphy->bands[radio_type]; + if (bss_desc->bcn_ht_cap) { ht_cap = (struct mwifiex_ie_types_htcap *) *buffer; memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); @@ -406,7 +354,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, sizeof(struct ieee_types_header), le16_to_cpu(ht_cap->header.len)); - mwifiex_fill_cap_info(priv, ht_cap); + mwifiex_fill_cap_info(priv, radio_type, ht_cap); *buffer += sizeof(struct mwifiex_ie_types_htcap); ret_len += sizeof(struct mwifiex_ie_types_htcap); @@ -428,8 +376,8 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, sizeof(struct ieee_types_header), le16_to_cpu(ht_info->header.len)); - if (!ISSUPP_CHANWIDTH40 - (priv->adapter->hw_dot_11n_dev_cap)) + if (!(sband->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40)) ht_info->ht_info.ht_param &= ~(IEEE80211_HT_PARAM_CHAN_WIDTH_ANY | IEEE80211_HT_PARAM_CHA_SEC_OFFSET); @@ -451,7 +399,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, chan_list->chan_scan_param[0].radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); - if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) + if ((sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && (bss_desc->bcn_ht_info->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 02602ff30cbf..a4390a1a2a9f 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h @@ -38,7 +38,7 @@ int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, u8 **buffer); void mwifiex_cfg_tx_buf(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc); -void mwifiex_fill_cap_info(struct mwifiex_private *, +void mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type, struct mwifiex_ie_types_htcap *); int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv, u16 action, int *htcap_cfg); diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 585575562127..98009e2194c5 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1150,9 +1150,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, * * The following default values are set - * - HT Supported = True - * - Maximum AMPDU length factor = 0x3 - * - Minimum AMPDU spacing = 0x6 - * - HT Capabilities map = IEEE80211_HT_CAP_SUP_WIDTH_20_40 (0x0002) + * - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K + * - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE + * - HT Capabilities supported by firmware * - MCS information, Rx mask = 0xff * - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01) */ @@ -1166,13 +1166,41 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, struct mwifiex_adapter *adapter = priv->adapter; ht_info->ht_supported = true; - ht_info->ampdu_factor = 0x3; - ht_info->ampdu_density = 0x6; + ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40; - rx_mcs_supp = GET_RXMCSSUPP(priv->adapter->hw_dev_mcs_support); + /* Fill HT capability information */ + if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) + ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; + else + ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + + if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap)) + ht_info->cap |= IEEE80211_HT_CAP_SGI_20; + else + ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20; + + if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap)) + ht_info->cap |= IEEE80211_HT_CAP_SGI_40; + else + ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40; + + if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap)) + ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; + else + ht_info->cap &= ~(3 << IEEE80211_HT_CAP_RX_STBC_SHIFT); + + if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) + ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; + else + ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC; + + ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; + ht_info->cap |= IEEE80211_HT_CAP_SM_PS; + + rx_mcs_supp = GET_RXMCSSUPP(adapter->hw_dev_mcs_support); /* Set MCS for 1x1 */ memset(mcs, 0xff, rx_mcs_supp); /* Clear all the other values */ diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 68d905d58606..be708ad8c44d 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1007,7 +1007,9 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv, ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); ht_cap->header.len = cpu_to_le16(sizeof(struct ieee80211_ht_cap)); - mwifiex_fill_cap_info(priv, ht_cap); + radio_type = + mwifiex_band_to_radio_type(priv->adapter->config_bands); + mwifiex_fill_cap_info(priv, radio_type, ht_cap); tlv_pos += sizeof(struct mwifiex_ie_types_htcap); } -- cgit v1.2.3-58-ga151 From 030fe7974f48bd86bb706ec05188ebab0cb7af80 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 27 Apr 2011 19:13:13 -0700 Subject: mwifiex: fix bug in mwifiex_save_curr_bcn() Since timestamp in beacon buffer keeps changing all the time, the memcmp check in mwifiex_save_curr_bcn() is redundant. Remove that memcmp check and also avoid freeing and allocation of buffer if required beacon buffer size is same as previous one. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/scan.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index be708ad8c44d..31a529578805 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -2990,32 +2990,28 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv) struct mwifiex_bssdescriptor *curr_bss = &priv->curr_bss_params.bss_descriptor; - /* save the beacon buffer if it is not saved or updated */ - if ((priv->curr_bcn_buf == NULL) || - (priv->curr_bcn_size != curr_bss->beacon_buf_size) || - (memcmp(priv->curr_bcn_buf, curr_bss->beacon_buf, - curr_bss->beacon_buf_size))) { - - kfree(priv->curr_bcn_buf); - priv->curr_bcn_buf = NULL; + if (!curr_bss->beacon_buf_size) + return; + /* allocate beacon buffer at 1st time; or if it's size has changed */ + if (!priv->curr_bcn_buf || + priv->curr_bcn_size != curr_bss->beacon_buf_size) { priv->curr_bcn_size = curr_bss->beacon_buf_size; - if (!priv->curr_bcn_size) - return; + kfree(priv->curr_bcn_buf); priv->curr_bcn_buf = kzalloc(curr_bss->beacon_buf_size, GFP_KERNEL); if (!priv->curr_bcn_buf) { dev_err(priv->adapter->dev, "failed to alloc curr_bcn_buf\n"); - } else { - memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf, - curr_bss->beacon_buf_size); - dev_dbg(priv->adapter->dev, - "info: current beacon saved %d\n", - priv->curr_bcn_size); + return; } } + + memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf, + curr_bss->beacon_buf_size); + dev_dbg(priv->adapter->dev, "info: current beacon saved %d\n", + priv->curr_bcn_size); } /* -- cgit v1.2.3-58-ga151 From 7a828908a026d801c6192fd32cfb35d6843f1539 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:28:53 -0700 Subject: Bluetooth: Add automated SSP user confirmation responses This patch adds automated negative and positive (auto-accept) responses for Secure Simple Pairing user confirmation requests. The responses are only sent if the HCI_MGMT flag is set in order not to confuse older user space versions (without management interface support). Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 577d638600df..514e10e1e0ff 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2483,14 +2483,47 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_user_confirm_req *ev = (void *) skb->data; + int loc_mitm, rem_mitm; + struct hci_conn *conn; BT_DBG("%s", hdev->name); hci_dev_lock(hdev); - if (test_bit(HCI_MGMT, &hdev->flags)) - mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey); + if (!test_bit(HCI_MGMT, &hdev->flags)) + goto unlock; + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); + if (!conn) + goto unlock; + + loc_mitm = (conn->auth_type & 0x01); + rem_mitm = (conn->remote_auth & 0x01); + + /* If we require MITM but the remote device can't provide that + * (it has NoInputNoOutput) then reject the confirmation + * request. The only exception is when we're dedicated bonding + * initiators (connect_cfm_cb set) since then we always have the MITM + * bit set. */ + if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { + BT_DBG("Rejecting request: remote device can't provide MITM"); + hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, + sizeof(ev->bdaddr), &ev->bdaddr); + goto unlock; + } + + /* If no side requires MITM protection; auto-accept */ + if ((!loc_mitm || conn->remote_cap == 0x03) && + (!rem_mitm || conn->io_capability == 0x03)) { + BT_DBG("Auto-accept of user confirmation"); + hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, + sizeof(ev->bdaddr), &ev->bdaddr); + goto unlock; + } + + mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey); + +unlock: hci_dev_unlock(hdev); } -- cgit v1.2.3-58-ga151 From 9f61656a60c9506e3e4cd41af5efbcf6a30ee3b9 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:28:54 -0700 Subject: Bluetooth: Add variable SSP auto-accept delay support Some test systems require an arbitrary delay to the auto-accept test cases for Secure Simple Pairing in order for the tests to pass. Previously when this was handled in user space it was worked around by code modifications and recompilation, but now that it's on the kernel side it's more convenient if there's a debugfs interface for it. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 3 +++ net/bluetooth/hci_conn.c | 17 +++++++++++++++++ net/bluetooth/hci_event.c | 10 +++++++++- net/bluetooth/hci_sysfs.c | 31 +++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 2995e2e63512..09b9dd61e370 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -126,6 +126,8 @@ struct hci_dev { __u16 sniff_min_interval; __u16 sniff_max_interval; + unsigned int auto_accept_delay; + unsigned long quirks; atomic_t cmd_cnt; @@ -246,6 +248,7 @@ struct hci_conn { struct timer_list disc_timer; struct timer_list idle_timer; + struct timer_list auto_accept_timer; struct work_struct work_add; struct work_struct work_del; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 74cd755b38a7..7f5ad8a2b22d 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -269,6 +269,19 @@ static void hci_conn_idle(unsigned long arg) hci_conn_enter_sniff_mode(conn); } +static void hci_conn_auto_accept(unsigned long arg) +{ + struct hci_conn *conn = (void *) arg; + struct hci_dev *hdev = conn->hdev; + + hci_dev_lock(hdev); + + hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), + &conn->dst); + + hci_dev_unlock(hdev); +} + struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) { struct hci_conn *conn; @@ -312,6 +325,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn); setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); + setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept, + (unsigned long) conn); atomic_set(&conn->refcnt, 0); @@ -342,6 +357,8 @@ int hci_conn_del(struct hci_conn *conn) del_timer(&conn->disc_timer); + del_timer(&conn->auto_accept_timer); + if (conn->type == ACL_LINK) { struct hci_conn *sco = conn->link; if (sco) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 514e10e1e0ff..a479389668ef 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2515,7 +2515,15 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, /* If no side requires MITM protection; auto-accept */ if ((!loc_mitm || conn->remote_cap == 0x03) && (!rem_mitm || conn->io_capability == 0x03)) { - BT_DBG("Auto-accept of user confirmation"); + BT_DBG("Auto-accept of user confirmation with %ums delay", + hdev->auto_accept_delay); + + if (hdev->auto_accept_delay > 0) { + int delay = msecs_to_jiffies(hdev->auto_accept_delay); + mod_timer(&conn->auto_accept_timer, jiffies + delay); + goto unlock; + } + hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(ev->bdaddr), &ev->bdaddr); goto unlock; diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 8775933ea837..a6c3aa8be1f7 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -511,6 +511,35 @@ static const struct file_operations uuids_fops = { .release = single_release, }; +static int auto_accept_delay_set(void *data, u64 val) +{ + struct hci_dev *hdev = data; + + hci_dev_lock_bh(hdev); + + hdev->auto_accept_delay = val; + + hci_dev_unlock_bh(hdev); + + return 0; +} + +static int auto_accept_delay_get(void *data, u64 *val) +{ + struct hci_dev *hdev = data; + + hci_dev_lock_bh(hdev); + + *val = hdev->auto_accept_delay; + + hci_dev_unlock_bh(hdev); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get, + auto_accept_delay_set, "%llu\n"); + int hci_register_sysfs(struct hci_dev *hdev) { struct device *dev = &hdev->dev; @@ -545,6 +574,8 @@ int hci_register_sysfs(struct hci_dev *hdev) debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); + debugfs_create_file("auto_accept_delay", 0444, hdev->debugfs, hdev, + &auto_accept_delay_fops); return 0; } -- cgit v1.2.3-58-ga151 From 79c6c70cbe35c270e7b59207ab76b44183a1030a Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:28:55 -0700 Subject: Bluetooth: Fix HCI_CONN_AUTH_PEND flag for all authentication requests The HCI_CONN_AUTH_PEND flag should be set whenever requesting authentication so that multiple pending requests can't occur. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index a479389668ef..ce8e09955834 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1021,12 +1021,19 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); - if (conn && hci_outgoing_auth_needed(hdev, conn)) { + if (!conn) + goto unlock; + + if (!hci_outgoing_auth_needed(hdev, conn)) + goto unlock; + + if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { struct hci_cp_auth_requested cp; cp.handle = __cpu_to_le16(conn->handle); hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); } +unlock: hci_dev_unlock(hdev); } @@ -1516,12 +1523,19 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); - if (conn && hci_outgoing_auth_needed(hdev, conn)) { + if (!conn) + goto unlock; + + if (!hci_outgoing_auth_needed(hdev, conn)) + goto unlock; + + if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { struct hci_cp_auth_requested cp; cp.handle = __cpu_to_le16(conn->handle); hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); } +unlock: hci_dev_unlock(hdev); } -- cgit v1.2.3-58-ga151 From 55bc1a378cc35f21a26e07af2ff2b71820808cd4 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:28:56 -0700 Subject: Bluetooth: Add confirm_hint parameter to user confirmation requests When accepting a pairing request which fulfills the SSP auto-accept criteria we need to push the request all the way to the user for confirmation. This patch adds a new hint to the user_confirm_request management event so user space can know when to show a numeric comparison dialog and when to show a simple yes/no confirmation dialog. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 3 ++- include/net/bluetooth/mgmt.h | 1 + net/bluetooth/hci_event.c | 16 ++++++++++++++-- net/bluetooth/mgmt.c | 4 +++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 09b9dd61e370..135dfac1be12 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -783,7 +783,8 @@ int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure); int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); -int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value); +int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value, + u8 confirm_hint); int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 0e7de636035d..c444a2b87e72 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -259,6 +259,7 @@ struct mgmt_ev_pin_code_request { #define MGMT_EV_USER_CONFIRM_REQUEST 0x000F struct mgmt_ev_user_confirm_request { bdaddr_t bdaddr; + __u8 confirm_hint; __le32 value; } __packed; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index ce8e09955834..29310c78ebb3 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2497,7 +2497,7 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_user_confirm_req *ev = (void *) skb->data; - int loc_mitm, rem_mitm; + int loc_mitm, rem_mitm, confirm_hint = 0; struct hci_conn *conn; BT_DBG("%s", hdev->name); @@ -2529,6 +2529,16 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, /* If no side requires MITM protection; auto-accept */ if ((!loc_mitm || conn->remote_cap == 0x03) && (!rem_mitm || conn->io_capability == 0x03)) { + + /* If we're not the initiators request authorization to + * proceed from user space (mgmt_user_confirm with + * confirm_hint set to 1). */ + if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { + BT_DBG("Confirming auto-accept as acceptor"); + confirm_hint = 1; + goto confirm; + } + BT_DBG("Auto-accept of user confirmation with %ums delay", hdev->auto_accept_delay); @@ -2543,7 +2553,9 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, goto unlock; } - mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey); +confirm: + mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey, + confirm_hint); unlock: hci_dev_unlock(hdev); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a7b4937d761c..a1b0ec4e5178 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1995,13 +1995,15 @@ int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) return err; } -int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value) +int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value, + u8 confirm_hint) { struct mgmt_ev_user_confirm_request ev; BT_DBG("hci%u", index); bacpy(&ev.bdaddr, bdaddr); + ev.confirm_hint = confirm_hint; put_unaligned_le32(value, &ev.value); return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev), -- cgit v1.2.3-58-ga151 From be77159c3f37e73a18ecc5c1eab3c67e07c6ce22 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:28:57 -0700 Subject: Bluetooth: Fix reason code for pairing rejection "Pairing not allowed" is 0x18 and not 0x16. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 29310c78ebb3..d535ea4ccbed 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2462,7 +2462,7 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff struct hci_cp_io_capability_neg_reply cp; bacpy(&cp.bdaddr, &ev->bdaddr); - cp.reason = 0x16; /* Pairing not allowed */ + cp.reason = 0x18; /* Pairing not allowed */ hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, sizeof(cp), &cp); -- cgit v1.2.3-58-ga151 From 582fbe9ef9d6fc089ff20956595f046d4899e74e Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:28:58 -0700 Subject: Bluetooth: Fix logic in hci_pin_code_request_evt The mgmt_ev_pin_code_request event should not be sent to user space if the request gets rejected by the kernel due to the pairable flag not being set. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d535ea4ccbed..ebbaa6c8d015 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2035,8 +2035,7 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff if (!test_bit(HCI_PAIRABLE, &hdev->flags)) hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(ev->bdaddr), &ev->bdaddr); - - if (test_bit(HCI_MGMT, &hdev->flags)) { + else if (test_bit(HCI_MGMT, &hdev->flags)) { u8 secure; if (conn->pending_sec_level == BT_SECURITY_HIGH) -- cgit v1.2.3-58-ga151 From d25e28abe58d2bcedf6025a6ccc532c29a19046f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:28:59 -0700 Subject: Bluetooth: Fix link key persistent storage criteria Link keys should only be stored if very specific criteria of the authentication process are fulfilled. This patch essentially copies the criteria that user space has so far been using to the kernel side so that the management interface works properly. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 4 +-- net/bluetooth/hci_core.c | 54 ++++++++++++++++++++++++++++++++++++++-- net/bluetooth/hci_event.c | 2 +- net/bluetooth/mgmt.c | 2 +- 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 135dfac1be12..3a3f7b453803 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -515,8 +515,8 @@ int hci_uuids_clear(struct hci_dev *hdev); int hci_link_keys_clear(struct hci_dev *hdev); struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); -int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, - u8 *key, u8 type, u8 pin_len); +int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, + bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); int hci_remote_oob_data_clear(struct hci_dev *hdev); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 07d0ba35b9a5..5f55aef63e20 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1022,8 +1022,44 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) return NULL; } -int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, - u8 *val, u8 type, u8 pin_len) +static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, + u8 key_type, u8 old_key_type) +{ + /* Legacy key */ + if (key_type < 0x03) + return 1; + + /* Debug keys are insecure so don't store them persistently */ + if (key_type == HCI_LK_DEBUG_COMBINATION) + return 0; + + /* Changed combination key and there's no previous one */ + if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff) + return 0; + + /* Security mode 3 case */ + if (!conn) + return 1; + + /* Neither local nor remote side had no-bonding as requirement */ + if (conn->auth_type > 0x01 && conn->remote_auth > 0x01) + return 1; + + /* Local side had dedicated bonding as requirement */ + if (conn->auth_type == 0x02 || conn->auth_type == 0x03) + return 1; + + /* Remote side had dedicated bonding as requirement */ + if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) + return 1; + + /* If none of the above criteria match, then don't store the key + * persistently */ + return 0; +} + +int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, + bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) { struct link_key *key, *old_key; u8 old_key_type; @@ -1042,6 +1078,20 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type); + /* Some buggy controller combinations generate a changed + * combination key for legacy pairing even when there's no + * previous key */ + if (type == HCI_LK_CHANGED_COMBINATION && + (!conn || conn->remote_auth == 0xff) && + old_key_type == 0xff) + type = HCI_LK_COMBINATION; + + if (new_key && !hci_persistent_key(hdev, conn, type, old_key_type)) { + list_del(&key->list); + kfree(key); + return 0; + } + bacpy(&key->bdaddr, bdaddr); memcpy(key->val, val, 16); key->type = type; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index ebbaa6c8d015..8a63d3a463f7 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2136,7 +2136,7 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff } if (test_bit(HCI_LINK_KEYS, &hdev->flags)) - hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key, + hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, ev->key_type, pin_len); hci_dev_unlock(hdev); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a1b0ec4e5178..e1384fc6016c 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -945,7 +945,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) for (i = 0; i < key_count; i++) { struct mgmt_key_info *key = &cp->keys[i]; - hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->type, + hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type, key->pin_len); } -- cgit v1.2.3-58-ga151 From 12adcf3a953c3aa4006d855aa638133bf018ceac Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:29:00 -0700 Subject: Bluetooth: Fix old_key_type logic for non-persistent keys Even if there's no previous key stored the connection might still be secured with a non-persistent key and in that case the key type in the hci_conn struct should be checked. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 5f55aef63e20..2ac6036b70c3 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1069,7 +1069,7 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, old_key_type = old_key->type; key = old_key; } else { - old_key_type = 0xff; + old_key_type = conn ? conn->key_type : 0xff; key = kzalloc(sizeof(*key), GFP_ATOMIC); if (!key) return -ENOMEM; -- cgit v1.2.3-58-ga151 From 655fe6ece7e71b37c17577ae485d11bf701c95f7 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:29:01 -0700 Subject: Bluetooth: Fix connection key type updating for buggy controllers If a controller generates a changed combination key as its first key the connection key type will not be correctly set. In these situations make sure the update the connection key type when such a buggy controller is detected. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 2ac6036b70c3..59ca4755b6b3 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1083,8 +1083,11 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, * previous key */ if (type == HCI_LK_CHANGED_COMBINATION && (!conn || conn->remote_auth == 0xff) && - old_key_type == 0xff) + old_key_type == 0xff) { type = HCI_LK_COMBINATION; + if (conn) + conn->key_type = type; + } if (new_key && !hci_persistent_key(hdev, conn, type, old_key_type)) { list_del(&key->list); -- cgit v1.2.3-58-ga151 From 4748fed2d1a2a7a816277754498b8aa70850e051 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:29:02 -0700 Subject: Bluetooth: Remove old_key_type from mgmt_ev_new_key User space shouldn't have any need for the old key type so remove it from the corresponding Management interface event. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 2 +- include/net/bluetooth/mgmt.h | 1 - net/bluetooth/hci_core.c | 9 +++++---- net/bluetooth/mgmt.c | 3 +-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3a3f7b453803..88c2cd92eaea 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -775,7 +775,7 @@ int mgmt_index_removed(u16 index); int mgmt_powered(u16 index, u8 powered); int mgmt_discoverable(u16 index, u8 discoverable); int mgmt_connectable(u16 index, u8 connectable); -int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type); +int mgmt_new_key(u16 index, struct link_key *key); int mgmt_connected(u16 index, bdaddr_t *bdaddr); int mgmt_disconnected(u16 index, bdaddr_t *bdaddr); int mgmt_disconnect_failed(u16 index); diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index c444a2b87e72..353a85dc2de0 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -231,7 +231,6 @@ struct mgmt_ev_controller_error { #define MGMT_EV_NEW_KEY 0x000A struct mgmt_ev_new_key { struct mgmt_key_info key; - __u8 old_key_type; } __packed; #define MGMT_EV_CONNECTED 0x000B diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 59ca4755b6b3..60260cae3a04 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1097,14 +1097,15 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, bacpy(&key->bdaddr, bdaddr); memcpy(key->val, val, 16); - key->type = type; key->pin_len = pin_len; - if (new_key) - mgmt_new_key(hdev->id, key, old_key_type); - if (type == HCI_LK_CHANGED_COMBINATION) key->type = old_key_type; + else + key->type = type; + + if (new_key) + mgmt_new_key(hdev->id, key); return 0; } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index e1384fc6016c..232ea8bfff19 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1858,7 +1858,7 @@ int mgmt_connectable(u16 index, u8 connectable) return ret; } -int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type) +int mgmt_new_key(u16 index, struct link_key *key) { struct mgmt_ev_new_key ev; @@ -1868,7 +1868,6 @@ int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type) ev.key.type = key->type; memcpy(ev.key.val, key->val, 16); ev.key.pin_len = key->pin_len; - ev.old_key_type = old_key_type; return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL); } -- cgit v1.2.3-58-ga151 From 4df378a10e31698df1679f3329301d773a654b61 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:29:03 -0700 Subject: Bluetooth: Add store_hint parameter to mgmt_new_key Even for keys that shouldn't be stored some use cases require the knowledge of a new key having been created so that the conclusion of a successful pairing can be made. Therefore, always send the mgmt_new_key event but add a store_hint parameter to it to indicate to user space whether the key should be stored or not. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 2 +- include/net/bluetooth/mgmt.h | 1 + net/bluetooth/hci_core.c | 21 ++++++++++++--------- net/bluetooth/mgmt.c | 3 ++- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 88c2cd92eaea..14cc3249c1eb 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -775,7 +775,7 @@ int mgmt_index_removed(u16 index); int mgmt_powered(u16 index, u8 powered); int mgmt_discoverable(u16 index, u8 discoverable); int mgmt_connectable(u16 index, u8 connectable); -int mgmt_new_key(u16 index, struct link_key *key); +int mgmt_new_key(u16 index, struct link_key *key, u8 persistent); int mgmt_connected(u16 index, bdaddr_t *bdaddr); int mgmt_disconnected(u16 index, bdaddr_t *bdaddr); int mgmt_disconnect_failed(u16 index); diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 353a85dc2de0..4899286ed4e4 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -230,6 +230,7 @@ struct mgmt_ev_controller_error { #define MGMT_EV_NEW_KEY 0x000A struct mgmt_ev_new_key { + __u8 store_hint; struct mgmt_key_info key; } __packed; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 60260cae3a04..b6bda3fac10e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1062,7 +1062,7 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) { struct link_key *key, *old_key; - u8 old_key_type; + u8 old_key_type, persistent; old_key = hci_find_link_key(hdev, bdaddr); if (old_key) { @@ -1089,12 +1089,6 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, conn->key_type = type; } - if (new_key && !hci_persistent_key(hdev, conn, type, old_key_type)) { - list_del(&key->list); - kfree(key); - return 0; - } - bacpy(&key->bdaddr, bdaddr); memcpy(key->val, val, 16); key->pin_len = pin_len; @@ -1104,8 +1098,17 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, else key->type = type; - if (new_key) - mgmt_new_key(hdev->id, key); + if (!new_key) + return 0; + + persistent = hci_persistent_key(hdev, conn, type, old_key_type); + + mgmt_new_key(hdev->id, key, persistent); + + if (!persistent) { + list_del(&key->list); + kfree(key); + } return 0; } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 232ea8bfff19..2481d257ed98 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1858,12 +1858,13 @@ int mgmt_connectable(u16 index, u8 connectable) return ret; } -int mgmt_new_key(u16 index, struct link_key *key) +int mgmt_new_key(u16 index, struct link_key *key, u8 persistent) { struct mgmt_ev_new_key ev; memset(&ev, 0, sizeof(ev)); + ev.store_hint = persistent; bacpy(&ev.key.bdaddr, &key->bdaddr); ev.key.type = key->type; memcpy(ev.key.val, key->val, 16); -- cgit v1.2.3-58-ga151 From 7cbc9bd99542752ff570abca79d0027669a01fb8 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:29:04 -0700 Subject: Bluetooth: Fix updating conn->auth_type in hci_io_capa_request_evt In some circumstances hci_get_auth_req will return a value different from the current conn->auth_type. In these cases update conn->auth_type so that when a user confirm request comes it doesn't falsely trigger auto-accept. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8a63d3a463f7..d5aa97ee6ffa 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2447,7 +2447,8 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff bacpy(&cp.bdaddr, &ev->bdaddr); cp.capability = conn->io_capability; - cp.authentication = hci_get_auth_req(conn); + conn->auth_type = hci_get_auth_req(conn); + cp.authentication = conn->auth_type; if ((conn->out == 0x01 || conn->remote_oob == 0x01) && hci_find_remote_oob_data(hdev, &conn->dst)) -- cgit v1.2.3-58-ga151 From f6d8bd051c391c1c0458a30b2a7abcd939329259 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 21 Apr 2011 09:45:37 +0000 Subject: inet: add RCU protection to inet->opt We lack proper synchronization to manipulate inet->opt ip_options Problem is ip_make_skb() calls ip_setup_cork() and ip_setup_cork() possibly makes a copy of ipc->opt (struct ip_options), without any protection against another thread manipulating inet->opt. Another thread can change inet->opt pointer and free old one under us. Use RCU to protect inet->opt (changed to inet->inet_opt). Instead of handling atomic refcounts, just copy ip_options when necessary, to avoid cache line dirtying. We cant insert an rcu_head in struct ip_options since its included in skb->cb[], so this patch is large because I had to introduce a new ip_options_rcu structure. Signed-off-by: Eric Dumazet Cc: Herbert Xu Signed-off-by: David S. Miller --- include/net/inet_sock.h | 14 +++-- include/net/ip.h | 11 ++-- net/dccp/ipv4.c | 16 +++--- net/dccp/ipv6.c | 2 +- net/ipv4/af_inet.c | 17 ++++-- net/ipv4/cipso_ipv4.c | 113 ++++++++++++++++++++++------------------ net/ipv4/icmp.c | 23 ++++---- net/ipv4/inet_connection_sock.c | 6 +-- net/ipv4/ip_options.c | 38 +++++++------- net/ipv4/ip_output.c | 44 ++++++++-------- net/ipv4/ip_sockglue.c | 35 +++++++++---- net/ipv4/raw.c | 19 +++++-- net/ipv4/syncookies.c | 4 +- net/ipv4/tcp_ipv4.c | 34 +++++++----- net/ipv4/udp.c | 21 ++++++-- net/ipv6/tcp_ipv6.c | 2 +- net/l2tp/l2tp_ip.c | 10 ++-- 17 files changed, 241 insertions(+), 168 deletions(-) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 7a37369f8ea3..ed2ba6eca724 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -57,7 +57,15 @@ struct ip_options { unsigned char __data[0]; }; -#define optlength(opt) (sizeof(struct ip_options) + opt->optlen) +struct ip_options_rcu { + struct rcu_head rcu; + struct ip_options opt; +}; + +struct ip_options_data { + struct ip_options_rcu opt; + char data[40]; +}; struct inet_request_sock { struct request_sock req; @@ -78,7 +86,7 @@ struct inet_request_sock { acked : 1, no_srccheck: 1; kmemcheck_bitfield_end(flags); - struct ip_options *opt; + struct ip_options_rcu *opt; }; static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk) @@ -140,7 +148,7 @@ struct inet_sock { __be16 inet_sport; __u16 inet_id; - struct ip_options *opt; + struct ip_options_rcu __rcu *inet_opt; __u8 tos; __u8 min_ttl; __u8 mc_ttl; diff --git a/include/net/ip.h b/include/net/ip.h index 7c416583b710..3a59bf99aa3a 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -52,7 +52,7 @@ static inline unsigned int ip_hdrlen(const struct sk_buff *skb) struct ipcm_cookie { __be32 addr; int oif; - struct ip_options *opt; + struct ip_options_rcu *opt; __u8 tx_flags; }; @@ -92,7 +92,7 @@ extern int igmp_mc_proc_init(void); extern int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, __be32 saddr, __be32 daddr, - struct ip_options *opt); + struct ip_options_rcu *opt); extern int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); extern int ip_local_deliver(struct sk_buff *skb); @@ -416,14 +416,15 @@ extern int ip_forward(struct sk_buff *skb); * Functions provided by ip_options.c */ -extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, __be32 daddr, struct rtable *rt, int is_frag); +extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, + __be32 daddr, struct rtable *rt, int is_frag); extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb); extern void ip_options_fragment(struct sk_buff *skb); extern int ip_options_compile(struct net *net, struct ip_options *opt, struct sk_buff *skb); -extern int ip_options_get(struct net *net, struct ip_options **optp, +extern int ip_options_get(struct net *net, struct ip_options_rcu **optp, unsigned char *data, int optlen); -extern int ip_options_get_from_user(struct net *net, struct ip_options **optp, +extern int ip_options_get_from_user(struct net *net, struct ip_options_rcu **optp, unsigned char __user *data, int optlen); extern void ip_options_undo(struct ip_options * opt); extern void ip_forward_options(struct sk_buff *skb); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index b92ab655d44e..cbbcc6c036e0 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -48,6 +48,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) struct flowi4 fl4; struct rtable *rt; int err; + struct ip_options_rcu *inet_opt; dp->dccps_role = DCCP_ROLE_CLIENT; @@ -58,10 +59,13 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) return -EAFNOSUPPORT; nexthop = daddr = usin->sin_addr.s_addr; - if (inet->opt != NULL && inet->opt->srr) { + + inet_opt = rcu_dereference_protected(inet->inet_opt, + sock_owned_by_user(sk)); + if (inet_opt != NULL && inet_opt->opt.srr) { if (daddr == 0) return -EINVAL; - nexthop = inet->opt->faddr; + nexthop = inet_opt->opt.faddr; } orig_sport = inet->inet_sport; @@ -78,7 +82,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) return -ENETUNREACH; } - if (inet->opt == NULL || !inet->opt->srr) + if (inet_opt == NULL || !inet_opt->opt.srr) daddr = rt->rt_dst; if (inet->inet_saddr == 0) @@ -89,8 +93,8 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) inet->inet_daddr = daddr; inet_csk(sk)->icsk_ext_hdr_len = 0; - if (inet->opt != NULL) - inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen; + if (inet_opt) + inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen; /* * Socket identity is still unknown (sport may be zero). * However we set state to DCCP_REQUESTING and not releasing socket @@ -405,7 +409,7 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb, newinet->inet_daddr = ireq->rmt_addr; newinet->inet_rcv_saddr = ireq->loc_addr; newinet->inet_saddr = ireq->loc_addr; - newinet->opt = ireq->opt; + newinet->inet_opt = ireq->opt; ireq->opt = NULL; newinet->mc_index = inet_iif(skb); newinet->mc_ttl = ip_hdr(skb)->ttl; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 73add2373247..8dc4348774a5 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -573,7 +573,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, First: no IPv4 options. */ - newinet->opt = NULL; + newinet->inet_opt = NULL; /* Clone RX bits */ newnp->rxopt.all = np->rxopt.all; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 0413af3e2285..963a621e75c7 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -153,7 +153,7 @@ void inet_sock_destruct(struct sock *sk) WARN_ON(sk->sk_wmem_queued); WARN_ON(sk->sk_forward_alloc); - kfree(inet->opt); + kfree(rcu_dereference_protected(inet->inet_opt, 1)); dst_release(rcu_dereference_check(sk->sk_dst_cache, 1)); sk_refcnt_debug_dec(sk); } @@ -1106,9 +1106,12 @@ static int inet_sk_reselect_saddr(struct sock *sk) struct flowi4 fl4; struct rtable *rt; __be32 new_saddr; + struct ip_options_rcu *inet_opt; - if (inet->opt && inet->opt->srr) - daddr = inet->opt->faddr; + inet_opt = rcu_dereference_protected(inet->inet_opt, + sock_owned_by_user(sk)); + if (inet_opt && inet_opt->opt.srr) + daddr = inet_opt->opt.faddr; /* Query new route. */ rt = ip_route_connect(&fl4, daddr, 0, RT_CONN_FLAGS(sk), @@ -1148,6 +1151,7 @@ int inet_sk_rebuild_header(struct sock *sk) struct inet_sock *inet = inet_sk(sk); struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); __be32 daddr; + struct ip_options_rcu *inet_opt; int err; /* Route is OK, nothing to do. */ @@ -1155,9 +1159,12 @@ int inet_sk_rebuild_header(struct sock *sk) return 0; /* Reroute. */ + rcu_read_lock(); + inet_opt = rcu_dereference(inet->inet_opt); daddr = inet->inet_daddr; - if (inet->opt && inet->opt->srr) - daddr = inet->opt->faddr; + if (inet_opt && inet_opt->opt.srr) + daddr = inet_opt->opt.faddr; + rcu_read_unlock(); rt = ip_route_output_ports(sock_net(sk), sk, daddr, inet->inet_saddr, inet->inet_dport, inet->inet_sport, sk->sk_protocol, RT_CONN_FLAGS(sk), diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index a0af7ea87870..2b3c23c287cd 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1857,6 +1857,11 @@ static int cipso_v4_genopt(unsigned char *buf, u32 buf_len, return CIPSO_V4_HDR_LEN + ret_val; } +static void opt_kfree_rcu(struct rcu_head *head) +{ + kfree(container_of(head, struct ip_options_rcu, rcu)); +} + /** * cipso_v4_sock_setattr - Add a CIPSO option to a socket * @sk: the socket @@ -1879,7 +1884,7 @@ int cipso_v4_sock_setattr(struct sock *sk, unsigned char *buf = NULL; u32 buf_len; u32 opt_len; - struct ip_options *opt = NULL; + struct ip_options_rcu *old, *opt = NULL; struct inet_sock *sk_inet; struct inet_connection_sock *sk_conn; @@ -1915,22 +1920,25 @@ int cipso_v4_sock_setattr(struct sock *sk, ret_val = -ENOMEM; goto socket_setattr_failure; } - memcpy(opt->__data, buf, buf_len); - opt->optlen = opt_len; - opt->cipso = sizeof(struct iphdr); + memcpy(opt->opt.__data, buf, buf_len); + opt->opt.optlen = opt_len; + opt->opt.cipso = sizeof(struct iphdr); kfree(buf); buf = NULL; sk_inet = inet_sk(sk); + + old = rcu_dereference_protected(sk_inet->inet_opt, sock_owned_by_user(sk)); if (sk_inet->is_icsk) { sk_conn = inet_csk(sk); - if (sk_inet->opt) - sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen; - sk_conn->icsk_ext_hdr_len += opt->optlen; + if (old) + sk_conn->icsk_ext_hdr_len -= old->opt.optlen; + sk_conn->icsk_ext_hdr_len += opt->opt.optlen; sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie); } - opt = xchg(&sk_inet->opt, opt); - kfree(opt); + rcu_assign_pointer(sk_inet->inet_opt, opt); + if (old) + call_rcu(&old->rcu, opt_kfree_rcu); return 0; @@ -1960,7 +1968,7 @@ int cipso_v4_req_setattr(struct request_sock *req, unsigned char *buf = NULL; u32 buf_len; u32 opt_len; - struct ip_options *opt = NULL; + struct ip_options_rcu *opt = NULL; struct inet_request_sock *req_inet; /* We allocate the maximum CIPSO option size here so we are probably @@ -1988,15 +1996,16 @@ int cipso_v4_req_setattr(struct request_sock *req, ret_val = -ENOMEM; goto req_setattr_failure; } - memcpy(opt->__data, buf, buf_len); - opt->optlen = opt_len; - opt->cipso = sizeof(struct iphdr); + memcpy(opt->opt.__data, buf, buf_len); + opt->opt.optlen = opt_len; + opt->opt.cipso = sizeof(struct iphdr); kfree(buf); buf = NULL; req_inet = inet_rsk(req); opt = xchg(&req_inet->opt, opt); - kfree(opt); + if (opt) + call_rcu(&opt->rcu, opt_kfree_rcu); return 0; @@ -2016,34 +2025,34 @@ req_setattr_failure: * values on failure. * */ -static int cipso_v4_delopt(struct ip_options **opt_ptr) +static int cipso_v4_delopt(struct ip_options_rcu **opt_ptr) { int hdr_delta = 0; - struct ip_options *opt = *opt_ptr; + struct ip_options_rcu *opt = *opt_ptr; - if (opt->srr || opt->rr || opt->ts || opt->router_alert) { + if (opt->opt.srr || opt->opt.rr || opt->opt.ts || opt->opt.router_alert) { u8 cipso_len; u8 cipso_off; unsigned char *cipso_ptr; int iter; int optlen_new; - cipso_off = opt->cipso - sizeof(struct iphdr); - cipso_ptr = &opt->__data[cipso_off]; + cipso_off = opt->opt.cipso - sizeof(struct iphdr); + cipso_ptr = &opt->opt.__data[cipso_off]; cipso_len = cipso_ptr[1]; - if (opt->srr > opt->cipso) - opt->srr -= cipso_len; - if (opt->rr > opt->cipso) - opt->rr -= cipso_len; - if (opt->ts > opt->cipso) - opt->ts -= cipso_len; - if (opt->router_alert > opt->cipso) - opt->router_alert -= cipso_len; - opt->cipso = 0; + if (opt->opt.srr > opt->opt.cipso) + opt->opt.srr -= cipso_len; + if (opt->opt.rr > opt->opt.cipso) + opt->opt.rr -= cipso_len; + if (opt->opt.ts > opt->opt.cipso) + opt->opt.ts -= cipso_len; + if (opt->opt.router_alert > opt->opt.cipso) + opt->opt.router_alert -= cipso_len; + opt->opt.cipso = 0; memmove(cipso_ptr, cipso_ptr + cipso_len, - opt->optlen - cipso_off - cipso_len); + opt->opt.optlen - cipso_off - cipso_len); /* determining the new total option length is tricky because of * the padding necessary, the only thing i can think to do at @@ -2052,21 +2061,21 @@ static int cipso_v4_delopt(struct ip_options **opt_ptr) * from there we can determine the new total option length */ iter = 0; optlen_new = 0; - while (iter < opt->optlen) - if (opt->__data[iter] != IPOPT_NOP) { - iter += opt->__data[iter + 1]; + while (iter < opt->opt.optlen) + if (opt->opt.__data[iter] != IPOPT_NOP) { + iter += opt->opt.__data[iter + 1]; optlen_new = iter; } else iter++; - hdr_delta = opt->optlen; - opt->optlen = (optlen_new + 3) & ~3; - hdr_delta -= opt->optlen; + hdr_delta = opt->opt.optlen; + opt->opt.optlen = (optlen_new + 3) & ~3; + hdr_delta -= opt->opt.optlen; } else { /* only the cipso option was present on the socket so we can * remove the entire option struct */ *opt_ptr = NULL; - hdr_delta = opt->optlen; - kfree(opt); + hdr_delta = opt->opt.optlen; + call_rcu(&opt->rcu, opt_kfree_rcu); } return hdr_delta; @@ -2083,15 +2092,15 @@ static int cipso_v4_delopt(struct ip_options **opt_ptr) void cipso_v4_sock_delattr(struct sock *sk) { int hdr_delta; - struct ip_options *opt; + struct ip_options_rcu *opt; struct inet_sock *sk_inet; sk_inet = inet_sk(sk); - opt = sk_inet->opt; - if (opt == NULL || opt->cipso == 0) + opt = rcu_dereference_protected(sk_inet->inet_opt, 1); + if (opt == NULL || opt->opt.cipso == 0) return; - hdr_delta = cipso_v4_delopt(&sk_inet->opt); + hdr_delta = cipso_v4_delopt(&sk_inet->inet_opt); if (sk_inet->is_icsk && hdr_delta > 0) { struct inet_connection_sock *sk_conn = inet_csk(sk); sk_conn->icsk_ext_hdr_len -= hdr_delta; @@ -2109,12 +2118,12 @@ void cipso_v4_sock_delattr(struct sock *sk) */ void cipso_v4_req_delattr(struct request_sock *req) { - struct ip_options *opt; + struct ip_options_rcu *opt; struct inet_request_sock *req_inet; req_inet = inet_rsk(req); opt = req_inet->opt; - if (opt == NULL || opt->cipso == 0) + if (opt == NULL || opt->opt.cipso == 0) return; cipso_v4_delopt(&req_inet->opt); @@ -2184,14 +2193,18 @@ getattr_return: */ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) { - struct ip_options *opt; + struct ip_options_rcu *opt; + int res = -ENOMSG; - opt = inet_sk(sk)->opt; - if (opt == NULL || opt->cipso == 0) - return -ENOMSG; - - return cipso_v4_getattr(opt->__data + opt->cipso - sizeof(struct iphdr), - secattr); + rcu_read_lock(); + opt = rcu_dereference(inet_sk(sk)->inet_opt); + if (opt && opt->opt.cipso) + res = cipso_v4_getattr(opt->opt.__data + + opt->opt.cipso - + sizeof(struct iphdr), + secattr); + rcu_read_unlock(); + return res; } /** diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 74e35e5736e2..cfeca3c2152d 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -108,8 +108,7 @@ struct icmp_bxm { __be32 times[3]; } data; int head_len; - struct ip_options replyopts; - unsigned char optbuf[40]; + struct ip_options_data replyopts; }; /* An array of errno for error messages from dest unreach. */ @@ -333,7 +332,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) struct inet_sock *inet; __be32 daddr; - if (ip_options_echo(&icmp_param->replyopts, skb)) + if (ip_options_echo(&icmp_param->replyopts.opt.opt, skb)) return; sk = icmp_xmit_lock(net); @@ -347,10 +346,10 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) daddr = ipc.addr = rt->rt_src; ipc.opt = NULL; ipc.tx_flags = 0; - if (icmp_param->replyopts.optlen) { - ipc.opt = &icmp_param->replyopts; - if (ipc.opt->srr) - daddr = icmp_param->replyopts.faddr; + if (icmp_param->replyopts.opt.opt.optlen) { + ipc.opt = &icmp_param->replyopts.opt; + if (ipc.opt->opt.srr) + daddr = icmp_param->replyopts.opt.opt.faddr; } { struct flowi4 fl4 = { @@ -379,8 +378,8 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in, struct icmp_bxm *param) { struct flowi4 fl4 = { - .daddr = (param->replyopts.srr ? - param->replyopts.faddr : iph->saddr), + .daddr = (param->replyopts.opt.opt.srr ? + param->replyopts.opt.opt.faddr : iph->saddr), .saddr = saddr, .flowi4_tos = RT_TOS(tos), .flowi4_proto = IPPROTO_ICMP, @@ -581,7 +580,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) IPTOS_PREC_INTERNETCONTROL) : iph->tos; - if (ip_options_echo(&icmp_param.replyopts, skb_in)) + if (ip_options_echo(&icmp_param.replyopts.opt.opt, skb_in)) goto out_unlock; @@ -597,7 +596,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) icmp_param.offset = skb_network_offset(skb_in); inet_sk(sk)->tos = tos; ipc.addr = iph->saddr; - ipc.opt = &icmp_param.replyopts; + ipc.opt = &icmp_param.replyopts.opt; ipc.tx_flags = 0; rt = icmp_route_lookup(net, skb_in, iph, saddr, tos, @@ -613,7 +612,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) room = dst_mtu(&rt->dst); if (room > 576) room = 576; - room -= sizeof(struct iphdr) + icmp_param.replyopts.optlen; + room -= sizeof(struct iphdr) + icmp_param.replyopts.opt.opt.optlen; room -= sizeof(struct icmphdr); icmp_param.data_len = skb_in->len - icmp_param.offset; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 8514db54a7f4..3282cb2de393 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -354,20 +354,20 @@ struct dst_entry *inet_csk_route_req(struct sock *sk, { struct rtable *rt; const struct inet_request_sock *ireq = inet_rsk(req); - struct ip_options *opt = inet_rsk(req)->opt; + struct ip_options_rcu *opt = inet_rsk(req)->opt; struct net *net = sock_net(sk); struct flowi4 fl4; flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark, RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, sk->sk_protocol, inet_sk_flowi_flags(sk), - (opt && opt->srr) ? opt->faddr : ireq->rmt_addr, + (opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr, ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport); security_req_classify_flow(req, flowi4_to_flowi(&fl4)); rt = ip_route_output_flow(net, &fl4, sk); if (IS_ERR(rt)) goto no_route; - if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) + if (opt && opt->opt.is_strictroute && rt->rt_dst != rt->rt_gateway) goto route_err; return &rt->dst; diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 2391b24e8251..01fc40965848 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -36,7 +36,7 @@ * saddr is address of outgoing interface. */ -void ip_options_build(struct sk_buff * skb, struct ip_options * opt, +void ip_options_build(struct sk_buff *skb, struct ip_options *opt, __be32 daddr, struct rtable *rt, int is_frag) { unsigned char *iph = skb_network_header(skb); @@ -83,9 +83,9 @@ void ip_options_build(struct sk_buff * skb, struct ip_options * opt, * NOTE: dopt cannot point to skb. */ -int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) +int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb) { - struct ip_options *sopt; + const struct ip_options *sopt; unsigned char *sptr, *dptr; int soffset, doffset; int optlen; @@ -95,10 +95,8 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) sopt = &(IPCB(skb)->opt); - if (sopt->optlen == 0) { - dopt->optlen = 0; + if (sopt->optlen == 0) return 0; - } sptr = skb_network_header(skb); dptr = dopt->__data; @@ -157,7 +155,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) dopt->optlen += optlen; } if (sopt->srr) { - unsigned char * start = sptr+sopt->srr; + unsigned char *start = sptr+sopt->srr; __be32 faddr; optlen = start[1]; @@ -499,19 +497,19 @@ void ip_options_undo(struct ip_options * opt) } } -static struct ip_options *ip_options_get_alloc(const int optlen) +static struct ip_options_rcu *ip_options_get_alloc(const int optlen) { - return kzalloc(sizeof(struct ip_options) + ((optlen + 3) & ~3), + return kzalloc(sizeof(struct ip_options_rcu) + ((optlen + 3) & ~3), GFP_KERNEL); } -static int ip_options_get_finish(struct net *net, struct ip_options **optp, - struct ip_options *opt, int optlen) +static int ip_options_get_finish(struct net *net, struct ip_options_rcu **optp, + struct ip_options_rcu *opt, int optlen) { while (optlen & 3) - opt->__data[optlen++] = IPOPT_END; - opt->optlen = optlen; - if (optlen && ip_options_compile(net, opt, NULL)) { + opt->opt.__data[optlen++] = IPOPT_END; + opt->opt.optlen = optlen; + if (optlen && ip_options_compile(net, &opt->opt, NULL)) { kfree(opt); return -EINVAL; } @@ -520,29 +518,29 @@ static int ip_options_get_finish(struct net *net, struct ip_options **optp, return 0; } -int ip_options_get_from_user(struct net *net, struct ip_options **optp, +int ip_options_get_from_user(struct net *net, struct ip_options_rcu **optp, unsigned char __user *data, int optlen) { - struct ip_options *opt = ip_options_get_alloc(optlen); + struct ip_options_rcu *opt = ip_options_get_alloc(optlen); if (!opt) return -ENOMEM; - if (optlen && copy_from_user(opt->__data, data, optlen)) { + if (optlen && copy_from_user(opt->opt.__data, data, optlen)) { kfree(opt); return -EFAULT; } return ip_options_get_finish(net, optp, opt, optlen); } -int ip_options_get(struct net *net, struct ip_options **optp, +int ip_options_get(struct net *net, struct ip_options_rcu **optp, unsigned char *data, int optlen) { - struct ip_options *opt = ip_options_get_alloc(optlen); + struct ip_options_rcu *opt = ip_options_get_alloc(optlen); if (!opt) return -ENOMEM; if (optlen) - memcpy(opt->__data, data, optlen); + memcpy(opt->opt.__data, data, optlen); return ip_options_get_finish(net, optp, opt, optlen); } diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index bdad3d60aa82..362e66f7d2fb 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -140,14 +140,14 @@ static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst) * */ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, - __be32 saddr, __be32 daddr, struct ip_options *opt) + __be32 saddr, __be32 daddr, struct ip_options_rcu *opt) { struct inet_sock *inet = inet_sk(sk); struct rtable *rt = skb_rtable(skb); struct iphdr *iph; /* Build the IP header. */ - skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0)); + skb_push(skb, sizeof(struct iphdr) + (opt ? opt->opt.optlen : 0)); skb_reset_network_header(skb); iph = ip_hdr(skb); iph->version = 4; @@ -163,9 +163,9 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, iph->protocol = sk->sk_protocol; ip_select_ident(iph, &rt->dst, sk); - if (opt && opt->optlen) { - iph->ihl += opt->optlen>>2; - ip_options_build(skb, opt, daddr, rt, 0); + if (opt && opt->opt.optlen) { + iph->ihl += opt->opt.optlen>>2; + ip_options_build(skb, &opt->opt, daddr, rt, 0); } skb->priority = sk->sk_priority; @@ -316,7 +316,7 @@ int ip_queue_xmit(struct sk_buff *skb) { struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(sk); - struct ip_options *opt = inet->opt; + struct ip_options_rcu *inet_opt; struct rtable *rt; struct iphdr *iph; int res; @@ -325,6 +325,7 @@ int ip_queue_xmit(struct sk_buff *skb) * f.e. by something like SCTP. */ rcu_read_lock(); + inet_opt = rcu_dereference(inet->inet_opt); rt = skb_rtable(skb); if (rt != NULL) goto packet_routed; @@ -336,8 +337,8 @@ int ip_queue_xmit(struct sk_buff *skb) /* Use correct destination address if we have options. */ daddr = inet->inet_daddr; - if(opt && opt->srr) - daddr = opt->faddr; + if (inet_opt && inet_opt->opt.srr) + daddr = inet_opt->opt.faddr; /* If this fails, retransmit mechanism of transport layer will * keep trying until route appears or the connection times @@ -357,11 +358,11 @@ int ip_queue_xmit(struct sk_buff *skb) skb_dst_set_noref(skb, &rt->dst); packet_routed: - if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) + if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_dst != rt->rt_gateway) goto no_route; /* OK, we know where to send it, allocate and build IP header. */ - skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0)); + skb_push(skb, sizeof(struct iphdr) + (inet_opt ? inet_opt->opt.optlen : 0)); skb_reset_network_header(skb); iph = ip_hdr(skb); *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); @@ -375,9 +376,9 @@ packet_routed: iph->daddr = rt->rt_dst; /* Transport layer set skb->h.foo itself. */ - if (opt && opt->optlen) { - iph->ihl += opt->optlen >> 2; - ip_options_build(skb, opt, inet->inet_daddr, rt, 0); + if (inet_opt && inet_opt->opt.optlen) { + iph->ihl += inet_opt->opt.optlen >> 2; + ip_options_build(skb, &inet_opt->opt, inet->inet_daddr, rt, 0); } ip_select_ident_more(iph, &rt->dst, sk, @@ -1033,7 +1034,7 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, struct ipcm_cookie *ipc, struct rtable **rtp) { struct inet_sock *inet = inet_sk(sk); - struct ip_options *opt; + struct ip_options_rcu *opt; struct rtable *rt; /* @@ -1047,7 +1048,7 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, if (unlikely(cork->opt == NULL)) return -ENOBUFS; } - memcpy(cork->opt, opt, sizeof(struct ip_options) + opt->optlen); + memcpy(cork->opt, &opt->opt, sizeof(struct ip_options) + opt->opt.optlen); cork->flags |= IPCORK_OPT; cork->addr = ipc->addr; } @@ -1451,26 +1452,23 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar unsigned int len) { struct inet_sock *inet = inet_sk(sk); - struct { - struct ip_options opt; - char data[40]; - } replyopts; + struct ip_options_data replyopts; struct ipcm_cookie ipc; __be32 daddr; struct rtable *rt = skb_rtable(skb); - if (ip_options_echo(&replyopts.opt, skb)) + if (ip_options_echo(&replyopts.opt.opt, skb)) return; daddr = ipc.addr = rt->rt_src; ipc.opt = NULL; ipc.tx_flags = 0; - if (replyopts.opt.optlen) { + if (replyopts.opt.opt.optlen) { ipc.opt = &replyopts.opt; - if (ipc.opt->srr) - daddr = replyopts.opt.faddr; + if (replyopts.opt.opt.srr) + daddr = replyopts.opt.opt.faddr; } { diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 9640900309bb..ab0c9efd1efa 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -451,6 +451,11 @@ out: } +static void opt_kfree_rcu(struct rcu_head *head) +{ + kfree(container_of(head, struct ip_options_rcu, rcu)); +} + /* * Socket option code for IP. This is the end of the line after any * TCP,UDP etc options on an IP socket. @@ -497,13 +502,16 @@ static int do_ip_setsockopt(struct sock *sk, int level, switch (optname) { case IP_OPTIONS: { - struct ip_options *opt = NULL; + struct ip_options_rcu *old, *opt = NULL; + if (optlen > 40) goto e_inval; err = ip_options_get_from_user(sock_net(sk), &opt, optval, optlen); if (err) break; + old = rcu_dereference_protected(inet->inet_opt, + sock_owned_by_user(sk)); if (inet->is_icsk) { struct inet_connection_sock *icsk = inet_csk(sk); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) @@ -512,17 +520,18 @@ static int do_ip_setsockopt(struct sock *sk, int level, (TCPF_LISTEN | TCPF_CLOSE)) && inet->inet_daddr != LOOPBACK4_IPV6)) { #endif - if (inet->opt) - icsk->icsk_ext_hdr_len -= inet->opt->optlen; + if (old) + icsk->icsk_ext_hdr_len -= old->opt.optlen; if (opt) - icsk->icsk_ext_hdr_len += opt->optlen; + icsk->icsk_ext_hdr_len += opt->opt.optlen; icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) } #endif } - opt = xchg(&inet->opt, opt); - kfree(opt); + rcu_assign_pointer(inet->inet_opt, opt); + if (old) + call_rcu(&old->rcu, opt_kfree_rcu); break; } case IP_PKTINFO: @@ -1081,12 +1090,16 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, case IP_OPTIONS: { unsigned char optbuf[sizeof(struct ip_options)+40]; - struct ip_options * opt = (struct ip_options *)optbuf; + struct ip_options *opt = (struct ip_options *)optbuf; + struct ip_options_rcu *inet_opt; + + inet_opt = rcu_dereference_protected(inet->inet_opt, + sock_owned_by_user(sk)); opt->optlen = 0; - if (inet->opt) - memcpy(optbuf, inet->opt, - sizeof(struct ip_options)+ - inet->opt->optlen); + if (inet_opt) + memcpy(optbuf, &inet_opt->opt, + sizeof(struct ip_options) + + inet_opt->opt.optlen); release_sock(sk); if (opt->optlen == 0) diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index abf14dbcb3b9..a8659e0c4a6e 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -460,6 +460,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, __be32 saddr; u8 tos; int err; + struct ip_options_data opt_copy; err = -EMSGSIZE; if (len > 0xFFFF) @@ -520,8 +521,18 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, saddr = ipc.addr; ipc.addr = daddr; - if (!ipc.opt) - ipc.opt = inet->opt; + if (!ipc.opt) { + struct ip_options_rcu *inet_opt; + + rcu_read_lock(); + inet_opt = rcu_dereference(inet->inet_opt); + if (inet_opt) { + memcpy(&opt_copy, inet_opt, + sizeof(*inet_opt) + inet_opt->opt.optlen); + ipc.opt = &opt_copy.opt; + } + rcu_read_unlock(); + } if (ipc.opt) { err = -EINVAL; @@ -530,10 +541,10 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, */ if (inet->hdrincl) goto done; - if (ipc.opt->srr) { + if (ipc.opt->opt.srr) { if (!daddr) goto done; - daddr = ipc.opt->faddr; + daddr = ipc.opt->opt.faddr; } } tos = RT_CONN_FLAGS(sk); diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 71e029691908..26461492a847 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -321,10 +321,10 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, * the ACK carries the same options again (see RFC1122 4.2.3.8) */ if (opt && opt->optlen) { - int opt_size = sizeof(struct ip_options) + opt->optlen; + int opt_size = sizeof(struct ip_options_rcu) + opt->optlen; ireq->opt = kmalloc(opt_size, GFP_ATOMIC); - if (ireq->opt != NULL && ip_options_echo(ireq->opt, skb)) { + if (ireq->opt != NULL && ip_options_echo(&ireq->opt->opt, skb)) { kfree(ireq->opt); ireq->opt = NULL; } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 310454c2f4d1..d60732fe5f21 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -154,6 +154,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) struct flowi4 fl4; struct rtable *rt; int err; + struct ip_options_rcu *inet_opt; if (addr_len < sizeof(struct sockaddr_in)) return -EINVAL; @@ -162,10 +163,12 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) return -EAFNOSUPPORT; nexthop = daddr = usin->sin_addr.s_addr; - if (inet->opt && inet->opt->srr) { + inet_opt = rcu_dereference_protected(inet->inet_opt, + sock_owned_by_user(sk)); + if (inet_opt && inet_opt->opt.srr) { if (!daddr) return -EINVAL; - nexthop = inet->opt->faddr; + nexthop = inet_opt->opt.faddr; } orig_sport = inet->inet_sport; @@ -186,7 +189,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) return -ENETUNREACH; } - if (!inet->opt || !inet->opt->srr) + if (!inet_opt || !inet_opt->opt.srr) daddr = rt->rt_dst; if (!inet->inet_saddr) @@ -222,8 +225,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) inet->inet_daddr = daddr; inet_csk(sk)->icsk_ext_hdr_len = 0; - if (inet->opt) - inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen; + if (inet_opt) + inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen; tp->rx_opt.mss_clamp = TCP_MSS_DEFAULT; @@ -820,17 +823,18 @@ static void syn_flood_warning(const struct sk_buff *skb) /* * Save and compile IPv4 options into the request_sock if needed. */ -static struct ip_options *tcp_v4_save_options(struct sock *sk, - struct sk_buff *skb) +static struct ip_options_rcu *tcp_v4_save_options(struct sock *sk, + struct sk_buff *skb) { - struct ip_options *opt = &(IPCB(skb)->opt); - struct ip_options *dopt = NULL; + const struct ip_options *opt = &(IPCB(skb)->opt); + struct ip_options_rcu *dopt = NULL; if (opt && opt->optlen) { - int opt_size = optlength(opt); + int opt_size = sizeof(*dopt) + opt->optlen; + dopt = kmalloc(opt_size, GFP_ATOMIC); if (dopt) { - if (ip_options_echo(dopt, skb)) { + if (ip_options_echo(&dopt->opt, skb)) { kfree(dopt); dopt = NULL; } @@ -1411,6 +1415,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, #ifdef CONFIG_TCP_MD5SIG struct tcp_md5sig_key *key; #endif + struct ip_options_rcu *inet_opt; if (sk_acceptq_is_full(sk)) goto exit_overflow; @@ -1431,13 +1436,14 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newinet->inet_daddr = ireq->rmt_addr; newinet->inet_rcv_saddr = ireq->loc_addr; newinet->inet_saddr = ireq->loc_addr; - newinet->opt = ireq->opt; + inet_opt = ireq->opt; + rcu_assign_pointer(newinet->inet_opt, inet_opt); ireq->opt = NULL; newinet->mc_index = inet_iif(skb); newinet->mc_ttl = ip_hdr(skb)->ttl; inet_csk(newsk)->icsk_ext_hdr_len = 0; - if (newinet->opt) - inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen; + if (inet_opt) + inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen; newinet->inet_id = newtp->write_seq ^ jiffies; tcp_mtup_init(newsk); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index bc0dab2593e0..544f435d1aff 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -804,6 +804,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); struct sk_buff *skb; + struct ip_options_data opt_copy; if (len > 0xFFFF) return -EMSGSIZE; @@ -877,22 +878,32 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, free = 1; connected = 0; } - if (!ipc.opt) - ipc.opt = inet->opt; + if (!ipc.opt) { + struct ip_options_rcu *inet_opt; + + rcu_read_lock(); + inet_opt = rcu_dereference(inet->inet_opt); + if (inet_opt) { + memcpy(&opt_copy, inet_opt, + sizeof(*inet_opt) + inet_opt->opt.optlen); + ipc.opt = &opt_copy.opt; + } + rcu_read_unlock(); + } saddr = ipc.addr; ipc.addr = faddr = daddr; - if (ipc.opt && ipc.opt->srr) { + if (ipc.opt && ipc.opt->opt.srr) { if (!daddr) return -EINVAL; - faddr = ipc.opt->faddr; + faddr = ipc.opt->opt.faddr; connected = 0; } tos = RT_TOS(inet->tos); if (sock_flag(sk, SOCK_LOCALROUTE) || (msg->msg_flags & MSG_DONTROUTE) || - (ipc.opt && ipc.opt->is_strictroute)) { + (ipc.opt && ipc.opt->opt.is_strictroute)) { tos |= RTO_ONLINK; connected = 0; } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index cb7658aceb6c..868366470b4a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1469,7 +1469,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, First: no IPv4 options. */ - newinet->opt = NULL; + newinet->inet_opt = NULL; newnp->ipv6_fl_list = NULL; /* Clone RX bits */ diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index cc673677c5de..962a607b51da 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -416,7 +416,6 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m int rc; struct l2tp_ip_sock *lsa = l2tp_ip_sk(sk); struct inet_sock *inet = inet_sk(sk); - struct ip_options *opt = inet->opt; struct rtable *rt = NULL; int connected = 0; __be32 daddr; @@ -471,9 +470,14 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m rt = (struct rtable *) __sk_dst_check(sk, 0); if (rt == NULL) { + struct ip_options_rcu *inet_opt; + + inet_opt = rcu_dereference_protected(inet->inet_opt, + sock_owned_by_user(sk)); + /* Use correct destination address if we have options. */ - if (opt && opt->srr) - daddr = opt->faddr; + if (inet_opt && inet_opt->opt.srr) + daddr = inet_opt->opt.faddr; /* If this fails, retransmit mechanism of transport layer will * keep trying until route appears or the connection times -- cgit v1.2.3-58-ga151 From 96339d6c490a32de35fa798ca7922d13a8538ecd Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Fri, 22 Apr 2011 19:07:41 +0800 Subject: net:use help function of skb_checksum_start_offset to calculate offset Although these are equivalent, but the skb_checksum_start_offset() is more readable. Signed-off-by: Shan Wei Signed-off-by: David S. Miller --- drivers/net/tile/tilepro.c | 2 +- net/ipv6/udp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tile/tilepro.c b/drivers/net/tile/tilepro.c index 0825db6d883f..1e980fdd9d77 100644 --- a/drivers/net/tile/tilepro.c +++ b/drivers/net/tile/tilepro.c @@ -1930,7 +1930,7 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev) unsigned int len = skb->len; unsigned char *data = skb->data; - unsigned int csum_start = skb->csum_start - skb_headroom(skb); + unsigned int csum_start = skb_checksum_start_offset(skb); lepp_frag_t frags[LEPP_MAX_FRAGS]; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 98ecfd7359e2..fc0c42a88e54 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1328,7 +1328,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features) /* Do software UFO. Complete and fill in the UDP checksum as HW cannot * do checksum of UDP packets sent as multiple IP fragments. */ - offset = skb->csum_start - skb_headroom(skb); + offset = skb_checksum_start_offset(skb); csum = skb_checksum(skb, offset, skb->len- offset, 0); offset += skb->csum_offset; *(__sum16 *)(skb->data + offset) = csum_fold(csum); -- cgit v1.2.3-58-ga151 From 1742f183fc218798dab6fcf0ded25b6608fc0a48 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 22 Apr 2011 06:31:16 +0000 Subject: net: fix netdev_increment_features() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify and fix netdev_increment_features() to conform to what is stated in netdevice.h comments about NETIF_F_ONE_FOR_ALL. Include FCoE segmentation and VLAN-challedged flags in computation. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- include/linux/netdevice.h | 7 ++++++- net/core/dev.c | 35 +++++++++++------------------------ 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 364bcf212f71..b7d0304762aa 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1106,7 +1106,12 @@ struct net_device { */ #define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \ NETIF_F_SG | NETIF_F_HIGHDMA | \ - NETIF_F_FRAGLIST) + NETIF_F_FRAGLIST | NETIF_F_VLAN_CHALLENGED) + /* + * If one device doesn't support one of these features, then disable it + * for all in netdev_increment_features. + */ +#define NETIF_F_ALL_FOR_ALL (NETIF_F_NOCACHE_COPY | NETIF_F_FSO) /* changeable features with no special hardware requirements */ #define NETIF_F_SOFT_FEATURES (NETIF_F_GSO | NETIF_F_GRO) diff --git a/net/core/dev.c b/net/core/dev.c index 3bbb4c2ce92e..7db99b52679f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6164,33 +6164,20 @@ static int dev_cpu_callback(struct notifier_block *nfb, */ u32 netdev_increment_features(u32 all, u32 one, u32 mask) { - /* If device needs checksumming, downgrade to it. */ - if (all & NETIF_F_NO_CSUM && !(one & NETIF_F_NO_CSUM)) - all ^= NETIF_F_NO_CSUM | (one & NETIF_F_ALL_CSUM); - else if (mask & NETIF_F_ALL_CSUM) { - /* If one device supports v4/v6 checksumming, set for all. */ - if (one & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM) && - !(all & NETIF_F_GEN_CSUM)) { - all &= ~NETIF_F_ALL_CSUM; - all |= one & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - } - - /* If one device supports hw checksumming, set for all. */ - if (one & NETIF_F_GEN_CSUM && !(all & NETIF_F_GEN_CSUM)) { - all &= ~NETIF_F_ALL_CSUM; - all |= NETIF_F_HW_CSUM; - } - } + if (mask & NETIF_F_GEN_CSUM) + mask |= NETIF_F_ALL_CSUM; + mask |= NETIF_F_VLAN_CHALLENGED; - /* If device can't no cache copy, don't do for all */ - if (!(one & NETIF_F_NOCACHE_COPY)) - all &= ~NETIF_F_NOCACHE_COPY; + all |= one & (NETIF_F_ONE_FOR_ALL|NETIF_F_ALL_CSUM) & mask; + all &= one | ~NETIF_F_ALL_FOR_ALL; - one |= NETIF_F_ALL_CSUM; + /* If device needs checksumming, downgrade to it. */ + if (all & (NETIF_F_ALL_CSUM & ~NETIF_F_NO_CSUM)) + all &= ~NETIF_F_NO_CSUM; - one |= all & NETIF_F_ONE_FOR_ALL; - all &= one | NETIF_F_LLTX | NETIF_F_GSO | NETIF_F_UFO; - all |= one & mask & NETIF_F_ONE_FOR_ALL; + /* If one device supports hw checksumming, set for all. */ + if (all & NETIF_F_GEN_CSUM) + all &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_GEN_CSUM); return all; } -- cgit v1.2.3-58-ga151 From c4d27ef957cd9261c0bc8488edaf8390e412cd35 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 22 Apr 2011 06:31:16 +0000 Subject: bridge: convert br_features_recompute() to ndo_fix_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note: netdev_update_features() needs only rtnl_lock as br->port_list is only changed while holding it. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- net/bridge/br_device.c | 61 +++++++------------------------------------------ net/bridge/br_if.c | 17 +++++++------- net/bridge/br_notify.c | 5 +--- net/bridge/br_private.h | 3 +-- 4 files changed, 19 insertions(+), 67 deletions(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 45cfd54b06d3..a6b2f86378c7 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -90,8 +90,7 @@ static int br_dev_open(struct net_device *dev) struct net_bridge *br = netdev_priv(dev); netif_carrier_off(dev); - - br_features_recompute(br); + netdev_update_features(dev); netif_start_queue(dev); br_stp_enable_bridge(br); br_multicast_open(br); @@ -188,48 +187,11 @@ static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info) strcpy(info->bus_info, "N/A"); } -static int br_set_sg(struct net_device *dev, u32 data) -{ - struct net_bridge *br = netdev_priv(dev); - - if (data) - br->feature_mask |= NETIF_F_SG; - else - br->feature_mask &= ~NETIF_F_SG; - - br_features_recompute(br); - return 0; -} - -static int br_set_tso(struct net_device *dev, u32 data) +static u32 br_fix_features(struct net_device *dev, u32 features) { struct net_bridge *br = netdev_priv(dev); - if (data) - br->feature_mask |= NETIF_F_TSO; - else - br->feature_mask &= ~NETIF_F_TSO; - - br_features_recompute(br); - return 0; -} - -static int br_set_tx_csum(struct net_device *dev, u32 data) -{ - struct net_bridge *br = netdev_priv(dev); - - if (data) - br->feature_mask |= NETIF_F_NO_CSUM; - else - br->feature_mask &= ~NETIF_F_ALL_CSUM; - - br_features_recompute(br); - return 0; -} - -static int br_set_flags(struct net_device *netdev, u32 data) -{ - return ethtool_op_set_flags(netdev, data, ETH_FLAG_TXVLAN); + return br_features_recompute(br, features); } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -330,16 +292,6 @@ static int br_del_slave(struct net_device *dev, struct net_device *slave_dev) static const struct ethtool_ops br_ethtool_ops = { .get_drvinfo = br_getinfo, .get_link = ethtool_op_get_link, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = br_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = br_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = br_set_tso, - .get_ufo = ethtool_op_get_ufo, - .set_ufo = ethtool_op_set_ufo, - .get_flags = ethtool_op_get_flags, - .set_flags = br_set_flags, }; static const struct net_device_ops br_netdev_ops = { @@ -359,6 +311,7 @@ static const struct net_device_ops br_netdev_ops = { #endif .ndo_add_slave = br_add_slave, .ndo_del_slave = br_del_slave, + .ndo_fix_features = br_fix_features, }; static void br_dev_free(struct net_device *dev) @@ -389,7 +342,10 @@ void br_dev_setup(struct net_device *dev) dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX | - NETIF_F_NETNS_LOCAL | NETIF_F_GSO | NETIF_F_HW_VLAN_TX; + NETIF_F_NETNS_LOCAL | NETIF_F_HW_VLAN_TX; + dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | + NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | + NETIF_F_HW_VLAN_TX; br->dev = dev; spin_lock_init(&br->lock); @@ -401,7 +357,6 @@ void br_dev_setup(struct net_device *dev) memcpy(br->group_addr, br_group_address, ETH_ALEN); - br->feature_mask = dev->features; br->stp_enabled = BR_NO_STP; br->designated_root = br->bridge_id; br->bridge_max_age = br->max_age = 20 * HZ; diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 7f5379c593d9..1156460773dc 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -291,15 +291,15 @@ int br_min_mtu(const struct net_bridge *br) /* * Recomputes features using slave's features */ -void br_features_recompute(struct net_bridge *br) +u32 br_features_recompute(struct net_bridge *br, u32 features) { struct net_bridge_port *p; - u32 features, mask; + u32 mask; - features = mask = br->feature_mask; if (list_empty(&br->port_list)) - goto done; + return features; + mask = features; features &= ~NETIF_F_ONE_FOR_ALL; list_for_each_entry(p, &br->port_list, list) { @@ -307,8 +307,7 @@ void br_features_recompute(struct net_bridge *br) p->dev->features, mask); } -done: - br->dev->features = netdev_fix_features(br->dev, features); + return features; } /* called with RTNL */ @@ -373,9 +372,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) list_add_rcu(&p->list, &br->port_list); + netdev_update_features(br->dev); + spin_lock_bh(&br->lock); changed_addr = br_stp_recalculate_bridge_id(br); - br_features_recompute(br); if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) @@ -423,9 +423,10 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) spin_lock_bh(&br->lock); br_stp_recalculate_bridge_id(br); - br_features_recompute(br); spin_unlock_bh(&br->lock); + netdev_update_features(br->dev); + return 0; } diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 606b323e8a0c..6545ee9591d1 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c @@ -66,10 +66,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v break; case NETDEV_FEAT_CHANGE: - spin_lock_bh(&br->lock); - if (netif_running(br->dev)) - br_features_recompute(br); - spin_unlock_bh(&br->lock); + netdev_update_features(br->dev); break; case NETDEV_DOWN: diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index e2a40343aa09..54578f274d85 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -183,7 +183,6 @@ struct net_bridge struct br_cpu_netstats __percpu *stats; spinlock_t hash_lock; struct hlist_head hash[BR_HASH_SIZE]; - u32 feature_mask; #ifdef CONFIG_BRIDGE_NETFILTER struct rtable fake_rtable; bool nf_call_iptables; @@ -379,7 +378,7 @@ extern int br_add_if(struct net_bridge *br, extern int br_del_if(struct net_bridge *br, struct net_device *dev); extern int br_min_mtu(const struct net_bridge *br); -extern void br_features_recompute(struct net_bridge *br); +extern u32 br_features_recompute(struct net_bridge *br, u32 features); /* br_input.c */ extern int br_handle_frame_finish(struct sk_buff *skb); -- cgit v1.2.3-58-ga151 From fa2bd7ff9247f4218dfc907db14d000cd7edd862 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 22 Apr 2011 06:31:16 +0000 Subject: net: allow user to change NETIF_F_HIGHDMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NETIF_F_HIGHDMA is like any other TX offloads, so allow user to toggle it. This is needed later for bridge and bonding convertsion to hw_features. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- include/linux/netdevice.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b7d0304762aa..e03af35843bc 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1080,7 +1080,7 @@ struct net_device { /* Features valid for ethtool to change */ /* = all defined minus driver/device-class-related */ -#define NETIF_F_NEVER_CHANGE (NETIF_F_HIGHDMA | NETIF_F_VLAN_CHALLENGED | \ +#define NETIF_F_NEVER_CHANGE (NETIF_F_VLAN_CHALLENGED | \ NETIF_F_LLTX | NETIF_F_NETNS_LOCAL) #define NETIF_F_ETHTOOL_BITS (0x7f3fffff & ~NETIF_F_NEVER_CHANGE) @@ -1098,6 +1098,7 @@ struct net_device { #define NETIF_F_ALL_TX_OFFLOADS (NETIF_F_ALL_CSUM | NETIF_F_SG | \ NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \ + NETIF_F_HIGHDMA | \ NETIF_F_SCTP_CSUM | NETIF_F_FCOE_CRC) /* -- cgit v1.2.3-58-ga151 From 63c3a66fe6c827a731dcbdee181158b295626f83 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Apr 2011 08:12:10 +0000 Subject: tg3: Convert u32 flag,flg2,flg3 uses to bitmap Using a bitmap instead of separate u32 flags allows a consistent, simpler and more extensible mechanism to determine capabilities. Convert bitmasks to enum. Add tg3_flag, tg3_flag_clear and tg3_flag_set. Convert the flag & bitmask tests. Signed-off-by: Joe Perches Acked-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/tg3.c | 1299 ++++++++++++++++++++++++++--------------------------- drivers/net/tg3.h | 168 ++++--- 2 files changed, 728 insertions(+), 739 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b20538a34fd1..fa57e3d699de 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -62,6 +62,30 @@ #include "tg3.h" +/* Functions & macros to verify TG3_FLAGS types */ + +static inline int _tg3_flag(enum TG3_FLAGS flag, unsigned long *bits) +{ + return test_bit(flag, bits); +} + +static inline void _tg3_flag_set(enum TG3_FLAGS flag, unsigned long *bits) +{ + set_bit(flag, bits); +} + +static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) +{ + clear_bit(flag, bits); +} + +#define tg3_flag(tp, flag) \ + _tg3_flag(TG3_FLAG_##flag, (tp)->tg3_flags) +#define tg3_flag_set(tp, flag) \ + _tg3_flag_set(TG3_FLAG_##flag, (tp)->tg3_flags) +#define tg3_flag_clear(tp, flag) \ + _tg3_flag_clear(TG3_FLAG_##flag, (tp)->tg3_flags) + #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 #define TG3_MIN_NUM 118 @@ -85,23 +109,24 @@ /* length of time before we decide the hardware is borked, * and dev->tx_timeout() should be called to fix the problem */ + #define TG3_TX_TIMEOUT (5 * HZ) /* hardware minimum and maximum for a single frame's data payload */ #define TG3_MIN_MTU 60 #define TG3_MAX_MTU(tp) \ - ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) ? 9000 : 1500) + (tg3_flag(tp, JUMBO_CAPABLE) ? 9000 : 1500) /* These numbers seem to be hard coded in the NIC firmware somehow. * You can't change the ring sizes, but you can change where you place * them in the NIC onboard memory. */ #define TG3_RX_STD_RING_SIZE(tp) \ - ((tp->tg3_flags3 & TG3_FLG3_LRG_PROD_RING_CAP) ? \ + (tg3_flag(tp, LRG_PROD_RING_CAP) ? \ TG3_RX_STD_MAX_SIZE_5717 : TG3_RX_STD_MAX_SIZE_5700) #define TG3_DEF_RX_RING_PENDING 200 #define TG3_RX_JMB_RING_SIZE(tp) \ - ((tp->tg3_flags3 & TG3_FLG3_LRG_PROD_RING_CAP) ? \ + (tg3_flag(tp, LRG_PROD_RING_CAP) ? \ TG3_RX_JMB_MAX_SIZE_5717 : TG3_RX_JMB_MAX_SIZE_5700) #define TG3_DEF_RX_JUMBO_RING_PENDING 100 #define TG3_RSS_INDIR_TBL_SIZE 128 @@ -468,8 +493,7 @@ static u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off) */ static void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait) { - if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) || - (tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND)) + if (tg3_flag(tp, PCIX_TARGET_HWBUG) || tg3_flag(tp, ICH_WORKAROUND)) /* Non-posted methods */ tp->write32(tp, off, val); else { @@ -489,8 +513,7 @@ static void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait) static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val) { tp->write32_mbox(tp, off, val); - if (!(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) && - !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND)) + if (!tg3_flag(tp, MBOX_WRITE_REORDER) && !tg3_flag(tp, ICH_WORKAROUND)) tp->read32_mbox(tp, off); } @@ -498,9 +521,9 @@ static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val) { void __iomem *mbox = tp->regs + off; writel(val, mbox); - if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) + if (tg3_flag(tp, TXD_MBOX_HWBUG)) writel(val, mbox); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) + if (tg3_flag(tp, MBOX_WRITE_REORDER)) readl(mbox); } @@ -534,7 +557,7 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) return; spin_lock_irqsave(&tp->indirect_lock, flags); - if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { + if (tg3_flag(tp, SRAM_USE_CONFIG)) { pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); @@ -561,7 +584,7 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) } spin_lock_irqsave(&tp->indirect_lock, flags); - if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { + if (tg3_flag(tp, SRAM_USE_CONFIG)) { pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); @@ -598,7 +621,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) int ret = 0; u32 status, req, gnt; - if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) + if (!tg3_flag(tp, ENABLE_APE)) return 0; switch (locknum) { @@ -644,7 +667,7 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) { u32 gnt; - if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) + if (!tg3_flag(tp, ENABLE_APE)) return; switch (locknum) { @@ -688,14 +711,14 @@ static void tg3_enable_ints(struct tg3 *tp) struct tg3_napi *tnapi = &tp->napi[i]; tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24); - if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) + if (tg3_flag(tp, 1SHOT_MSI)) tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24); tp->coal_now |= tnapi->coal_now; } /* Force an initial interrupt */ - if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) && + if (!tg3_flag(tp, TAGGED_STATUS) && (tp->napi[0].hw_status->status & SD_STATUS_UPDATED)) tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT); else @@ -711,9 +734,7 @@ static inline unsigned int tg3_has_work(struct tg3_napi *tnapi) unsigned int work_exists = 0; /* check for phy events */ - if (!(tp->tg3_flags & - (TG3_FLAG_USE_LINKCHG_REG | - TG3_FLAG_POLL_SERDES))) { + if (!(tg3_flag(tp, USE_LINKCHG_REG) || tg3_flag(tp, POLL_SERDES))) { if (sblk->status & SD_STATUS_LINK_CHG) work_exists = 1; } @@ -741,8 +762,7 @@ static void tg3_int_reenable(struct tg3_napi *tnapi) * The last_tag we write above tells the chip which piece of * work we've completed. */ - if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) && - tg3_has_work(tnapi)) + if (!tg3_flag(tp, TAGGED_STATUS) && tg3_has_work(tnapi)) tw32(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | tnapi->coal_now); } @@ -752,8 +772,7 @@ static void tg3_switch_clocks(struct tg3 *tp) u32 clock_ctrl; u32 orig_clock_ctrl; - if ((tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) || - (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) + if (tg3_flag(tp, CPMU_PRESENT) || tg3_flag(tp, 5780_CLASS)) return; clock_ctrl = tr32(TG3PCI_CLOCK_CTRL); @@ -764,7 +783,7 @@ static void tg3_switch_clocks(struct tg3 *tp) 0x1f); tp->pci_clock_ctrl = clock_ctrl; - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + if (tg3_flag(tp, 5705_PLUS)) { if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) { tw32_wait_f(TG3PCI_CLOCK_CTRL, clock_ctrl | CLOCK_CTRL_625_CORE, 40); @@ -1081,7 +1100,7 @@ static void tg3_mdio_config_5785(struct tg3 *tp) return; } - if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_INBAND_DISABLE)) + if (!tg3_flag(tp, RGMII_INBAND_DISABLE)) val |= MAC_PHYCFG2_EMODE_MASK_MASK | MAC_PHYCFG2_FMODE_MASK_MASK | MAC_PHYCFG2_GMODE_MASK_MASK | @@ -1094,10 +1113,10 @@ static void tg3_mdio_config_5785(struct tg3 *tp) val = tr32(MAC_PHYCFG1); val &= ~(MAC_PHYCFG1_RXCLK_TO_MASK | MAC_PHYCFG1_TXCLK_TO_MASK | MAC_PHYCFG1_RGMII_EXT_RX_DEC | MAC_PHYCFG1_RGMII_SND_STAT_EN); - if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_INBAND_DISABLE)) { - if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) + if (!tg3_flag(tp, RGMII_INBAND_DISABLE)) { + if (tg3_flag(tp, RGMII_EXT_IBND_RX_EN)) val |= MAC_PHYCFG1_RGMII_EXT_RX_DEC; - if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN) + if (tg3_flag(tp, RGMII_EXT_IBND_TX_EN)) val |= MAC_PHYCFG1_RGMII_SND_STAT_EN; } val |= MAC_PHYCFG1_RXCLK_TIMEOUT | MAC_PHYCFG1_TXCLK_TIMEOUT | @@ -1112,13 +1131,13 @@ static void tg3_mdio_config_5785(struct tg3 *tp) MAC_RGMII_MODE_TX_ENABLE | MAC_RGMII_MODE_TX_LOWPWR | MAC_RGMII_MODE_TX_RESET); - if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_INBAND_DISABLE)) { - if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) + if (!tg3_flag(tp, RGMII_INBAND_DISABLE)) { + if (tg3_flag(tp, RGMII_EXT_IBND_RX_EN)) val |= MAC_RGMII_MODE_RX_INT_B | MAC_RGMII_MODE_RX_QUALITY | MAC_RGMII_MODE_RX_ACTIVITY | MAC_RGMII_MODE_RX_ENG_DET; - if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN) + if (tg3_flag(tp, RGMII_EXT_IBND_TX_EN)) val |= MAC_RGMII_MODE_TX_ENABLE | MAC_RGMII_MODE_TX_LOWPWR | MAC_RGMII_MODE_TX_RESET; @@ -1132,7 +1151,7 @@ static void tg3_mdio_start(struct tg3 *tp) tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(80); - if ((tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) && + if (tg3_flag(tp, MDIOBUS_INITED) && GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) tg3_mdio_config_5785(tp); } @@ -1143,7 +1162,7 @@ static int tg3_mdio_init(struct tg3 *tp) u32 reg; struct phy_device *phydev; - if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { + if (tg3_flag(tp, 5717_PLUS)) { u32 is_serdes; tp->phy_addr = PCI_FUNC(tp->pdev->devfn) + 1; @@ -1160,8 +1179,7 @@ static int tg3_mdio_init(struct tg3 *tp) tg3_mdio_start(tp); - if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) || - (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED)) + if (!tg3_flag(tp, USE_PHYLIB) || tg3_flag(tp, MDIOBUS_INITED)) return 0; tp->mdio_bus = mdiobus_alloc(); @@ -1217,11 +1235,11 @@ static int tg3_mdio_init(struct tg3 *tp) PHY_BRCM_RX_REFCLK_UNUSED | PHY_BRCM_DIS_TXCRXC_NOENRGY | PHY_BRCM_AUTO_PWRDWN_ENABLE; - if (tp->tg3_flags3 & TG3_FLG3_RGMII_INBAND_DISABLE) + if (tg3_flag(tp, RGMII_INBAND_DISABLE)) phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE; - if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) + if (tg3_flag(tp, RGMII_EXT_IBND_RX_EN)) phydev->dev_flags |= PHY_BRCM_EXT_IBND_RX_ENABLE; - if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN) + if (tg3_flag(tp, RGMII_EXT_IBND_TX_EN)) phydev->dev_flags |= PHY_BRCM_EXT_IBND_TX_ENABLE; /* fallthru */ case PHY_ID_RTL8211C: @@ -1235,7 +1253,7 @@ static int tg3_mdio_init(struct tg3 *tp) break; } - tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED; + tg3_flag_set(tp, MDIOBUS_INITED); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) tg3_mdio_config_5785(tp); @@ -1245,8 +1263,8 @@ static int tg3_mdio_init(struct tg3 *tp) static void tg3_mdio_fini(struct tg3 *tp) { - if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { - tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_INITED; + if (tg3_flag(tp, MDIOBUS_INITED)) { + tg3_flag_clear(tp, MDIOBUS_INITED); mdiobus_unregister(tp->mdio_bus); mdiobus_free(tp->mdio_bus); } @@ -1299,8 +1317,7 @@ static void tg3_ump_link_report(struct tg3 *tp) u32 reg; u32 val; - if (!(tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || - !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) + if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF)) return; tg3_wait_for_event_ack(tp); @@ -1430,13 +1447,12 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv) u32 old_rx_mode = tp->rx_mode; u32 old_tx_mode = tp->tx_mode; - if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) + if (tg3_flag(tp, USE_PHYLIB)) autoneg = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]->autoneg; else autoneg = tp->link_config.autoneg; - if (autoneg == AUTONEG_ENABLE && - (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG)) { + if (autoneg == AUTONEG_ENABLE && tg3_flag(tp, PAUSE_AUTONEG)) { if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES) flowctrl = tg3_resolve_flowctrl_1000X(lcladv, rmtadv); else @@ -1657,8 +1673,8 @@ static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable) { u32 reg; - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || - ((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && + if (!tg3_flag(tp, 5705_PLUS) || + (tg3_flag(tp, 5717_PLUS) && (tp->phy_flags & TG3_PHYFLG_MII_SERDES))) return; @@ -1692,7 +1708,7 @@ static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable) { u32 phy; - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || + if (!tg3_flag(tp, 5705_PLUS) || (tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) return; @@ -2065,7 +2081,7 @@ static int tg3_phy_reset(struct tg3 *tp) } } - if ((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) && + if (tg3_flag(tp, 5717_PLUS) && (tp->phy_flags & TG3_PHYFLG_MII_SERDES)) return 0; @@ -2115,7 +2131,7 @@ out: if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) { /* Cannot do read-modify-write on 5401 */ tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20); - } else if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) { + } else if (tg3_flag(tp, JUMBO_CAPABLE)) { /* Set bit 14 with read-modify-write to preserve other bits */ err = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val); @@ -2127,7 +2143,7 @@ out: /* Set phy register 0x10 bit 0 to high fifo elasticity to support * jumbo frames transmission. */ - if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) { + if (tg3_flag(tp, JUMBO_CAPABLE)) { if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &val)) tg3_writephy(tp, MII_TG3_EXT_CTRL, val | MII_TG3_EXT_CTRL_FIFO_ELASTIC); @@ -2148,7 +2164,7 @@ static void tg3_frob_aux_power(struct tg3 *tp) bool need_vaux = false; /* The GPIOs do something completely different on 57765. */ - if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0 || + if (!tg3_flag(tp, IS_NIC) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) return; @@ -2166,17 +2182,16 @@ static void tg3_frob_aux_power(struct tg3 *tp) if (dev_peer) { struct tg3 *tp_peer = netdev_priv(dev_peer); - if (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) + if (tg3_flag(tp_peer, INIT_COMPLETE)) return; - if ((tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) || - (tp_peer->tg3_flags & TG3_FLAG_ENABLE_ASF)) + if (tg3_flag(tp_peer, WOL_ENABLE) || + tg3_flag(tp_peer, ENABLE_ASF)) need_vaux = true; } } - if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) || - (tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) + if (tg3_flag(tp, WOL_ENABLE) || tg3_flag(tp, ENABLE_ASF)) need_vaux = true; if (need_vaux) { @@ -2359,7 +2374,7 @@ static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power) /* tp->lock is held. */ static int tg3_nvram_lock(struct tg3 *tp) { - if (tp->tg3_flags & TG3_FLAG_NVRAM) { + if (tg3_flag(tp, NVRAM)) { int i; if (tp->nvram_lock_cnt == 0) { @@ -2382,7 +2397,7 @@ static int tg3_nvram_lock(struct tg3 *tp) /* tp->lock is held. */ static void tg3_nvram_unlock(struct tg3 *tp) { - if (tp->tg3_flags & TG3_FLAG_NVRAM) { + if (tg3_flag(tp, NVRAM)) { if (tp->nvram_lock_cnt > 0) tp->nvram_lock_cnt--; if (tp->nvram_lock_cnt == 0) @@ -2393,8 +2408,7 @@ static void tg3_nvram_unlock(struct tg3 *tp) /* tp->lock is held. */ static void tg3_enable_nvram_access(struct tg3 *tp) { - if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && - !(tp->tg3_flags3 & TG3_FLG3_PROTECTED_NVRAM)) { + if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) { u32 nvaccess = tr32(NVRAM_ACCESS); tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); @@ -2404,8 +2418,7 @@ static void tg3_enable_nvram_access(struct tg3 *tp) /* tp->lock is held. */ static void tg3_disable_nvram_access(struct tg3 *tp) { - if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && - !(tp->tg3_flags3 & TG3_FLG3_PROTECTED_NVRAM)) { + if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) { u32 nvaccess = tr32(NVRAM_ACCESS); tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); @@ -2475,10 +2488,10 @@ static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd) static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr) { - if ((tp->tg3_flags & TG3_FLAG_NVRAM) && - (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) && - (tp->tg3_flags2 & TG3_FLG2_FLASH) && - !(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM_ADDR_TRANS) && + if (tg3_flag(tp, NVRAM) && + tg3_flag(tp, NVRAM_BUFFERED) && + tg3_flag(tp, FLASH) && + !tg3_flag(tp, NO_NVRAM_ADDR_TRANS) && (tp->nvram_jedecnum == JEDEC_ATMEL)) addr = ((addr / tp->nvram_pagesize) << @@ -2490,10 +2503,10 @@ static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr) static u32 tg3_nvram_logical_addr(struct tg3 *tp, u32 addr) { - if ((tp->tg3_flags & TG3_FLAG_NVRAM) && - (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) && - (tp->tg3_flags2 & TG3_FLG2_FLASH) && - !(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM_ADDR_TRANS) && + if (tg3_flag(tp, NVRAM) && + tg3_flag(tp, NVRAM_BUFFERED) && + tg3_flag(tp, FLASH) && + !tg3_flag(tp, NO_NVRAM_ADDR_TRANS) && (tp->nvram_jedecnum == JEDEC_ATMEL)) addr = ((addr >> ATMEL_AT45DB0X1B_PAGE_POS) * @@ -2513,7 +2526,7 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) { int ret; - if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) + if (!tg3_flag(tp, NVRAM)) return tg3_nvram_read_using_eeprom(tp, offset, val); offset = tg3_nvram_phys_addr(tp, offset); @@ -2605,7 +2618,7 @@ static int tg3_power_up(struct tg3 *tp) pci_set_power_state(tp->pdev, PCI_D0); /* Switch out of Vaux if it is a NIC */ - if (tp->tg3_flags2 & TG3_FLG2_IS_NIC) + if (tg3_flag(tp, IS_NIC)) tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100); return 0; @@ -2619,7 +2632,7 @@ static int tg3_power_down_prepare(struct tg3 *tp) tg3_enable_register_access(tp); /* Restore the CLKREQ setting. */ - if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) { + if (tg3_flag(tp, CLKREQ_BUG)) { u16 lnkctl; pci_read_config_word(tp->pdev, @@ -2636,9 +2649,9 @@ static int tg3_power_down_prepare(struct tg3 *tp) misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT); device_should_wake = device_may_wakeup(&tp->pdev->dev) && - (tp->tg3_flags & TG3_FLAG_WOL_ENABLE); + tg3_flag(tp, WOL_ENABLE); - if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if (tg3_flag(tp, USE_PHYLIB)) { do_low_power = false; if ((tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) && !(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) { @@ -2659,9 +2672,8 @@ static int tg3_power_down_prepare(struct tg3 *tp) ADVERTISED_Autoneg | ADVERTISED_10baseT_Half; - if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || - device_should_wake) { - if (tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) + if (tg3_flag(tp, ENABLE_ASF) || device_should_wake) { + if (tg3_flag(tp, WOL_SPEED_100MB)) advertising |= ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | @@ -2706,7 +2718,7 @@ static int tg3_power_down_prepare(struct tg3 *tp) val = tr32(GRC_VCPU_EXT_CTRL); tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_DISABLE_WOL); - } else if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { + } else if (!tg3_flag(tp, ENABLE_ASF)) { int i; u32 val; @@ -2717,7 +2729,7 @@ static int tg3_power_down_prepare(struct tg3 *tp) msleep(1); } } - if (tp->tg3_flags & TG3_FLAG_WOL_CAP) + if (tg3_flag(tp, WOL_CAP)) tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE | WOL_DRV_STATE_SHUTDOWN | WOL_DRV_WOL | @@ -2745,8 +2757,7 @@ static int tg3_power_down_prepare(struct tg3 *tp) mac_mode |= tp->mac_mode & MAC_MODE_LINK_POLARITY; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) { - u32 speed = (tp->tg3_flags & - TG3_FLAG_WOL_SPEED_100MB) ? + u32 speed = tg3_flag(tp, WOL_SPEED_100MB) ? SPEED_100 : SPEED_10; if (tg3_5700_link_polarity(tp, speed)) mac_mode |= MAC_MODE_LINK_POLARITY; @@ -2757,17 +2768,15 @@ static int tg3_power_down_prepare(struct tg3 *tp) mac_mode = MAC_MODE_PORT_MODE_TBI; } - if (!(tp->tg3_flags2 & TG3_FLG2_5750_PLUS)) + if (!tg3_flag(tp, 5750_PLUS)) tw32(MAC_LED_CTRL, tp->led_ctrl); mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE; - if (((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && - !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) && - ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || - (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))) + if ((tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, 5780_CLASS)) && + (tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE))) mac_mode |= MAC_MODE_KEEP_FRAME_IN_WOL; - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + if (tg3_flag(tp, ENABLE_APE)) mac_mode |= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN | MAC_MODE_TDE_ENABLE; @@ -2779,7 +2788,7 @@ static int tg3_power_down_prepare(struct tg3 *tp) udelay(10); } - if (!(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) && + if (!tg3_flag(tp, WOL_SPEED_100MB) && (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { u32 base_val; @@ -2790,12 +2799,11 @@ static int tg3_power_down_prepare(struct tg3 *tp) tw32_wait_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK | CLOCK_CTRL_PWRDOWN_PLL133, 40); - } else if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || - (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) || + } else if (tg3_flag(tp, 5780_CLASS) || + tg3_flag(tp, CPMU_PRESENT) || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)) { /* do nothing */ - } else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && - (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) { + } else if (!(tg3_flag(tp, 5750_PLUS) && tg3_flag(tp, ENABLE_ASF))) { u32 newbits1, newbits2; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || @@ -2804,7 +2812,7 @@ static int tg3_power_down_prepare(struct tg3 *tp) CLOCK_CTRL_TXCLK_DISABLE | CLOCK_CTRL_ALTCLK); newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE; - } else if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + } else if (tg3_flag(tp, 5705_PLUS)) { newbits1 = CLOCK_CTRL_625_CORE; newbits2 = newbits1 | CLOCK_CTRL_ALTCLK; } else { @@ -2818,7 +2826,7 @@ static int tg3_power_down_prepare(struct tg3 *tp) tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2, 40); - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + if (!tg3_flag(tp, 5705_PLUS)) { u32 newbits3; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || @@ -2835,8 +2843,7 @@ static int tg3_power_down_prepare(struct tg3 *tp) } } - if (!(device_should_wake) && - !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) + if (!(device_should_wake) && !tg3_flag(tp, ENABLE_ASF)) tg3_power_down_phy(tp, do_low_power); tg3_frob_aux_power(tp); @@ -2848,7 +2855,7 @@ static int tg3_power_down_prepare(struct tg3 *tp) val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1); tw32(0x7d00, val); - if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { + if (!tg3_flag(tp, ENABLE_ASF)) { int err; err = tg3_nvram_lock(tp); @@ -2867,7 +2874,7 @@ static void tg3_power_down(struct tg3 *tp) { tg3_power_down_prepare(tp); - pci_wake_from_d3(tp->pdev, tp->tg3_flags & TG3_FLAG_WOL_ENABLE); + pci_wake_from_d3(tp->pdev, tg3_flag(tp, WOL_ENABLE)); pci_set_power_state(tp->pdev, PCI_D3hot); } @@ -2931,7 +2938,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp) new_adv = (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); - if (tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) + if (tg3_flag(tp, WOL_SPEED_100MB)) new_adv |= (ADVERTISE_100HALF | ADVERTISE_100FULL); tg3_writephy(tp, MII_ADVERTISE, new_adv); @@ -3163,7 +3170,7 @@ static int tg3_adv_1000T_flowctrl_ok(struct tg3 *tp, u32 *lcladv, u32 *rmtadv) if (curadv != reqadv) return 0; - if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) + if (tg3_flag(tp, PAUSE_AUTONEG)) tg3_readphy(tp, MII_LPA, rmtadv); } else { /* Reprogram the advertisement register, even if it @@ -3226,7 +3233,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) { tg3_readphy(tp, MII_BMSR, &bmsr); if (tg3_readphy(tp, MII_BMSR, &bmsr) || - !(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) + !tg3_flag(tp, INIT_COMPLETE)) bmsr = 0; if (!(bmsr & BMSR_LSTATUS)) { @@ -3410,7 +3417,7 @@ relink: tg3_phy_eee_adjust(tp, current_link_up); - if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { + if (tg3_flag(tp, USE_LINKCHG_REG)) { /* Polled via timer. */ tw32_f(MAC_EVENT, 0); } else { @@ -3421,8 +3428,7 @@ relink: if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 && current_link_up == 1 && tp->link_config.active_speed == SPEED_1000 && - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) || - (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED))) { + (tg3_flag(tp, PCIX_MODE) || tg3_flag(tp, PCI_HIGH_SPEED))) { udelay(120); tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | @@ -3434,7 +3440,7 @@ relink: } /* Prevent send BD corruption. */ - if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) { + if (tg3_flag(tp, CLKREQ_BUG)) { u16 oldlnkctl, newlnkctl; pci_read_config_word(tp->pdev, @@ -3829,7 +3835,7 @@ static void tg3_init_bcm8002(struct tg3 *tp) int i; /* Reset when initting first time or we have a link. */ - if ((tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) && + if (tg3_flag(tp, INIT_COMPLETE) && !(mac_status & MAC_STATUS_PCS_SYNCED)) return; @@ -4090,9 +4096,9 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) orig_active_speed = tp->link_config.active_speed; orig_active_duplex = tp->link_config.active_duplex; - if (!(tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) && + if (!tg3_flag(tp, HW_AUTONEG) && netif_carrier_ok(tp->dev) && - (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) { + tg3_flag(tp, INIT_COMPLETE)) { mac_status = tr32(MAC_STATUS); mac_status &= (MAC_STATUS_PCS_SYNCED | MAC_STATUS_SIGNAL_DET | @@ -4123,7 +4129,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) current_link_up = 0; mac_status = tr32(MAC_STATUS); - if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) + if (tg3_flag(tp, HW_AUTONEG)) current_link_up = tg3_setup_fiber_hw_autoneg(tp, mac_status); else current_link_up = tg3_setup_fiber_by_hand(tp, mac_status); @@ -4322,7 +4328,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) current_duplex = DUPLEX_FULL; else current_duplex = DUPLEX_HALF; - } else if (!(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { + } else if (!tg3_flag(tp, 5780_CLASS)) { /* Link is up via parallel detect */ } else { current_link_up = 0; @@ -4460,7 +4466,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) tw32(MAC_TX_LENGTHS, val | (32 << TX_LENGTHS_SLOT_TIME_SHIFT)); - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + if (!tg3_flag(tp, 5705_PLUS)) { if (netif_carrier_ok(tp->dev)) { tw32(HOSTCC_STAT_COAL_TICKS, tp->coal.stats_block_coalesce_usecs); @@ -4469,7 +4475,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) } } - if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND) { + if (tg3_flag(tp, ASPM_WORKAROUND)) { val = tr32(PCIE_PWR_MGMT_THRESH); if (!netif_carrier_ok(tp->dev)) val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) | @@ -4518,7 +4524,7 @@ static void tg3_dump_legacy_regs(struct tg3 *tp, u32 *regs) tg3_rd32_loop(tp, regs, MBFREE_MODE, 0x08); tg3_rd32_loop(tp, regs, HOSTCC_MODE, 0x100); - if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) + if (tg3_flag(tp, SUPPORT_MSIX)) tg3_rd32_loop(tp, regs, HOSTCC_RXCOL_TICKS_VEC1, 0x180); tg3_rd32_loop(tp, regs, MEMARB_MODE, 0x10); @@ -4530,7 +4536,7 @@ static void tg3_dump_legacy_regs(struct tg3 *tp, u32 *regs) tg3_rd32_loop(tp, regs, RX_CPU_PGMCTR, 0x04); tg3_rd32_loop(tp, regs, RX_CPU_HWBKPT, 0x04); - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + if (!tg3_flag(tp, 5705_PLUS)) { tg3_rd32_loop(tp, regs, TX_CPU_MODE, 0x04); tg3_rd32_loop(tp, regs, TX_CPU_STATE, 0x04); tg3_rd32_loop(tp, regs, TX_CPU_PGMCTR, 0x04); @@ -4542,7 +4548,7 @@ static void tg3_dump_legacy_regs(struct tg3 *tp, u32 *regs) tg3_rd32_loop(tp, regs, DMAC_MODE, 0x04); tg3_rd32_loop(tp, regs, GRC_MODE, 0x4c); - if (tp->tg3_flags & TG3_FLAG_NVRAM) + if (tg3_flag(tp, NVRAM)) tg3_rd32_loop(tp, regs, NVRAM_CMD, 0x24); } @@ -4557,7 +4563,7 @@ static void tg3_dump_state(struct tg3 *tp) return; } - if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { + if (tg3_flag(tp, PCI_EXPRESS)) { /* Read up to but not including private PCI registers */ for (i = 0; i < TG3_PCIE_TLDLPL_PORT; i += sizeof(u32)) regs[i / sizeof(u32)] = tr32(i); @@ -4612,7 +4618,7 @@ static void tg3_dump_state(struct tg3 *tp) */ static void tg3_tx_recover(struct tg3 *tp) { - BUG_ON((tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) || + BUG_ON(tg3_flag(tp, MBOX_WRITE_REORDER) || tp->write32_tx_mbox == tg3_write_indirect_mbox); netdev_warn(tp->dev, @@ -4622,7 +4628,7 @@ static void tg3_tx_recover(struct tg3 *tp) "and include system chipset information.\n"); spin_lock(&tp->lock); - tp->tg3_flags |= TG3_FLAG_TX_RECOVERY_PENDING; + tg3_flag_set(tp, TX_RECOVERY_PENDING); spin_unlock(&tp->lock); } @@ -4646,7 +4652,7 @@ static void tg3_tx(struct tg3_napi *tnapi) struct netdev_queue *txq; int index = tnapi - tp->napi; - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) + if (tg3_flag(tp, ENABLE_TSS)) index--; txq = netdev_get_tx_queue(tp->dev, index); @@ -5014,7 +5020,7 @@ next_pkt_nopost: tw32_rx_mbox(tnapi->consmbox, sw_idx); /* Refill RX ring(s). */ - if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)) { + if (!tg3_flag(tp, ENABLE_RSS)) { if (work_mask & RXD_OPAQUE_RING_STD) { tpr->rx_std_prod_idx = std_prod_idx & tp->rx_std_ring_mask; @@ -5047,16 +5053,14 @@ next_pkt_nopost: static void tg3_poll_link(struct tg3 *tp) { /* handle link change and other phy events */ - if (!(tp->tg3_flags & - (TG3_FLAG_USE_LINKCHG_REG | - TG3_FLAG_POLL_SERDES))) { + if (!(tg3_flag(tp, USE_LINKCHG_REG) || tg3_flag(tp, POLL_SERDES))) { struct tg3_hw_status *sblk = tp->napi[0].hw_status; if (sblk->status & SD_STATUS_LINK_CHG) { sblk->status = SD_STATUS_UPDATED | (sblk->status & ~SD_STATUS_LINK_CHG); spin_lock(&tp->lock); - if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if (tg3_flag(tp, USE_PHYLIB)) { tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED | @@ -5203,7 +5207,7 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) /* run TX completion thread */ if (tnapi->hw_status->idx[0].tx_consumer != tnapi->tx_cons) { tg3_tx(tnapi); - if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) + if (unlikely(tg3_flag(tp, TX_RECOVERY_PENDING))) return work_done; } @@ -5214,7 +5218,7 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) if (*(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr) work_done += tg3_rx(tnapi, budget - work_done); - if ((tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) && tnapi == &tp->napi[1]) { + if (tg3_flag(tp, ENABLE_RSS) && tnapi == &tp->napi[1]) { struct tg3_rx_prodring_set *dpr = &tp->napi[0].prodring; int i, err = 0; u32 std_prod_idx = dpr->rx_std_prod_idx; @@ -5253,7 +5257,7 @@ static int tg3_poll_msix(struct napi_struct *napi, int budget) while (1) { work_done = tg3_poll_work(tnapi, work_done, budget); - if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) + if (unlikely(tg3_flag(tp, TX_RECOVERY_PENDING))) goto tx_recovery; if (unlikely(work_done >= budget)) @@ -5292,7 +5296,7 @@ static void tg3_process_error(struct tg3 *tp) u32 val; bool real_error = false; - if (tp->tg3_flags & TG3_FLAG_ERROR_PROCESSED) + if (tg3_flag(tp, ERROR_PROCESSED)) return; /* Check Flow Attention register */ @@ -5317,7 +5321,7 @@ static void tg3_process_error(struct tg3 *tp) tg3_dump_state(tp); - tp->tg3_flags |= TG3_FLAG_ERROR_PROCESSED; + tg3_flag_set(tp, ERROR_PROCESSED); schedule_work(&tp->reset_task); } @@ -5336,13 +5340,13 @@ static int tg3_poll(struct napi_struct *napi, int budget) work_done = tg3_poll_work(tnapi, work_done, budget); - if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) + if (unlikely(tg3_flag(tp, TX_RECOVERY_PENDING))) goto tx_recovery; if (unlikely(work_done >= budget)) break; - if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) { + if (tg3_flag(tp, TAGGED_STATUS)) { /* tp->last_tag is used in tg3_int_reenable() below * to tell the hw how much work has been processed, * so we must read it before checking for more work. @@ -5509,7 +5513,7 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id) * interrupt is ours and will flush the status block. */ if (unlikely(!(sblk->status & SD_STATUS_UPDATED))) { - if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) || + if (tg3_flag(tp, CHIP_RESETTING) || (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { handled = 0; goto out; @@ -5558,7 +5562,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) * interrupt is ours and will flush the status block. */ if (unlikely(sblk->status_tag == tnapi->last_irq_tag)) { - if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) || + if (tg3_flag(tp, CHIP_RESETTING) || (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { handled = 0; goto out; @@ -5671,14 +5675,14 @@ static void tg3_reset_task(struct work_struct *work) tg3_full_lock(tp, 1); - restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER; - tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; + restart_timer = tg3_flag(tp, RESTART_TIMER); + tg3_flag_clear(tp, RESTART_TIMER); - if (tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING) { + if (tg3_flag(tp, TX_RECOVERY_PENDING)) { tp->write32_tx_mbox = tg3_write32_tx_mbox; tp->write32_rx_mbox = tg3_write_flush_reg32; - tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER; - tp->tg3_flags &= ~TG3_FLAG_TX_RECOVERY_PENDING; + tg3_flag_set(tp, MBOX_WRITE_REORDER); + tg3_flag_clear(tp, TX_RECOVERY_PENDING); } tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); @@ -5723,7 +5727,7 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping, int len) { #if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64) - if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) + if (tg3_flag(tp, 40BIT_DMA_BUG)) return ((u64) mapping + len) > DMA_BIT_MASK(40); return 0; #else @@ -5770,8 +5774,8 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, /* Make sure new skb does not cross any 4G boundaries. * Drop the packet if it does. */ - } else if ((tp->tg3_flags3 & TG3_FLG3_4G_DMA_BNDRY_BUG) && - tg3_4g_overflow_test(new_addr, new_skb->len)) { + } else if (tg3_flag(tp, 4G_DMA_BNDRY_BUG) && + tg3_4g_overflow_test(new_addr, new_skb->len)) { pci_unmap_single(tp->pdev, new_addr, new_skb->len, PCI_DMA_TODEVICE); ret = -1; @@ -5838,7 +5842,7 @@ static void tg3_set_txd(struct tg3_napi *tnapi, int entry, } /* hard_start_xmit for devices that don't have any bugs and - * support TG3_FLG2_HW_TSO_2 and TG3_FLG2_HW_TSO_3 only. + * support TG3_FLAG_HW_TSO_2 and TG3_FLAG_HW_TSO_3 only. */ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) @@ -5852,7 +5856,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); tnapi = &tp->napi[skb_get_queue_mapping(skb)]; - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) + if (tg3_flag(tp, ENABLE_TSS)) tnapi++; /* We are running in BH disabled context with netif_tx_lock @@ -5897,7 +5901,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, hdrlen = ip_tcp_len + tcp_opt_len; } - if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) { + if (tg3_flag(tp, HW_TSO_3)) { mss |= (hdrlen & 0xc) << 12; if (hdrlen & 0x10) base_flags |= 0x00000010; @@ -5930,7 +5934,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, tnapi->tx_buffers[entry].skb = skb; dma_unmap_addr_set(&tnapi->tx_buffers[entry], mapping, mapping); - if ((tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) && + if (tg3_flag(tp, USE_JUMBO_BDFLAG) && !mss && skb->len > VLAN_ETH_FRAME_LEN) base_flags |= TXD_FLAG_JMB_PKT; @@ -6053,7 +6057,7 @@ tg3_tso_bug_end: } /* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and - * support TG3_FLG2_HW_TSO_1 or firmware TSO only. + * support TG3_FLAG_HW_TSO_1 or firmware TSO only. */ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) @@ -6068,7 +6072,7 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); tnapi = &tp->napi[skb_get_queue_mapping(skb)]; - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) + if (tg3_flag(tp, ENABLE_TSS)) tnapi++; /* We are running in BH disabled context with netif_tx_lock @@ -6119,13 +6123,15 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, } if (unlikely((ETH_HLEN + hdr_len) > 80) && - (tp->tg3_flags2 & TG3_FLG2_TSO_BUG)) + tg3_flag(tp, TSO_BUG)) return tg3_tso_bug(tp, skb); base_flags |= (TXD_FLAG_CPU_PRE_DMA | TXD_FLAG_CPU_POST_DMA); - if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { + if (tg3_flag(tp, HW_TSO_1) || + tg3_flag(tp, HW_TSO_2) || + tg3_flag(tp, HW_TSO_3)) { tcp_hdr(skb)->check = 0; base_flags &= ~TXD_FLAG_TCPUDP_CSUM; } else @@ -6134,14 +6140,14 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, IPPROTO_TCP, 0); - if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) { + if (tg3_flag(tp, HW_TSO_3)) { mss |= (hdr_len & 0xc) << 12; if (hdr_len & 0x10) base_flags |= 0x00000010; base_flags |= (hdr_len & 0x3e0) << 5; - } else if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) + } else if (tg3_flag(tp, HW_TSO_2)) mss |= hdr_len << 9; - else if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1) || + else if (tg3_flag(tp, HW_TSO_1) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { if (tcp_opt_len || iph->ihl > 5) { int tsflags; @@ -6163,7 +6169,7 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, base_flags |= (TXD_FLAG_VLAN | (vlan_tx_tag_get(skb) << 16)); - if ((tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) && + if (tg3_flag(tp, USE_JUMBO_BDFLAG) && !mss && skb->len > VLAN_ETH_FRAME_LEN) base_flags |= TXD_FLAG_JMB_PKT; @@ -6180,18 +6186,18 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, would_hit_hwbug = 0; - if ((tp->tg3_flags3 & TG3_FLG3_SHORT_DMA_BUG) && len <= 8) + if (tg3_flag(tp, SHORT_DMA_BUG) && len <= 8) would_hit_hwbug = 1; - if ((tp->tg3_flags3 & TG3_FLG3_4G_DMA_BNDRY_BUG) && + if (tg3_flag(tp, 4G_DMA_BNDRY_BUG) && tg3_4g_overflow_test(mapping, len)) would_hit_hwbug = 1; - if ((tp->tg3_flags3 & TG3_FLG3_40BIT_DMA_LIMIT_BUG) && + if (tg3_flag(tp, 40BIT_DMA_LIMIT_BUG) && tg3_40bit_overflow_test(tp, mapping, len)) would_hit_hwbug = 1; - if (tp->tg3_flags3 & TG3_FLG3_5701_DMA_BUG) + if (tg3_flag(tp, 5701_DMA_BUG)) would_hit_hwbug = 1; tg3_set_txd(tnapi, entry, mapping, len, base_flags, @@ -6217,19 +6223,21 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, if (pci_dma_mapping_error(tp->pdev, mapping)) goto dma_error; - if ((tp->tg3_flags3 & TG3_FLG3_SHORT_DMA_BUG) && + if (tg3_flag(tp, SHORT_DMA_BUG) && len <= 8) would_hit_hwbug = 1; - if ((tp->tg3_flags3 & TG3_FLG3_4G_DMA_BNDRY_BUG) && + if (tg3_flag(tp, 4G_DMA_BNDRY_BUG) && tg3_4g_overflow_test(mapping, len)) would_hit_hwbug = 1; - if ((tp->tg3_flags3 & TG3_FLG3_40BIT_DMA_LIMIT_BUG) && + if (tg3_flag(tp, 40BIT_DMA_LIMIT_BUG) && tg3_40bit_overflow_test(tp, mapping, len)) would_hit_hwbug = 1; - if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + if (tg3_flag(tp, HW_TSO_1) || + tg3_flag(tp, HW_TSO_2) || + tg3_flag(tp, HW_TSO_3)) tg3_set_txd(tnapi, entry, mapping, len, base_flags, (i == last)|(mss << 1)); else @@ -6305,7 +6313,7 @@ static u32 tg3_fix_features(struct net_device *dev, u32 features) { struct tg3 *tp = netdev_priv(dev); - if (dev->mtu > ETH_DATA_LEN && (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) + if (dev->mtu > ETH_DATA_LEN && tg3_flag(tp, 5780_CLASS)) features &= ~NETIF_F_ALL_TSO; return features; @@ -6317,18 +6325,18 @@ static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, dev->mtu = new_mtu; if (new_mtu > ETH_DATA_LEN) { - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { + if (tg3_flag(tp, 5780_CLASS)) { netdev_update_features(dev); - tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; + tg3_flag_clear(tp, TSO_CAPABLE); } else { - tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE; + tg3_flag_set(tp, JUMBO_RING_ENABLE); } } else { - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { - tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; + if (tg3_flag(tp, 5780_CLASS)) { + tg3_flag_set(tp, TSO_CAPABLE); netdev_update_features(dev); } - tp->tg3_flags &= ~TG3_FLAG_JUMBO_RING_ENABLE; + tg3_flag_clear(tp, JUMBO_RING_ENABLE); } } @@ -6382,7 +6390,7 @@ static void tg3_rx_prodring_free(struct tg3 *tp, tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i], tp->rx_pkt_map_sz); - if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) { + if (tg3_flag(tp, JUMBO_CAPABLE)) { for (i = tpr->rx_jmb_cons_idx; i != tpr->rx_jmb_prod_idx; i = (i + 1) & tp->rx_jmb_ring_mask) { @@ -6398,8 +6406,7 @@ static void tg3_rx_prodring_free(struct tg3 *tp, tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i], tp->rx_pkt_map_sz); - if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && - !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { + if (tg3_flag(tp, JUMBO_CAPABLE) && !tg3_flag(tp, 5780_CLASS)) { for (i = 0; i <= tp->rx_jmb_ring_mask; i++) tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i], TG3_RX_JMB_MAP_SZ); @@ -6436,7 +6443,7 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp, memset(tpr->rx_std, 0, TG3_RX_STD_RING_BYTES(tp)); rx_pkt_dma_sz = TG3_RX_STD_DMA_SZ; - if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) && + if (tg3_flag(tp, 5780_CLASS) && tp->dev->mtu > ETH_DATA_LEN) rx_pkt_dma_sz = TG3_RX_JMB_DMA_SZ; tp->rx_pkt_map_sz = TG3_RX_DMA_TO_MAP_SZ(rx_pkt_dma_sz); @@ -6469,13 +6476,12 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp, } } - if (!(tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) || - (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) + if (!tg3_flag(tp, JUMBO_CAPABLE) || tg3_flag(tp, 5780_CLASS)) goto done; memset(tpr->rx_jmb, 0, TG3_RX_JMB_RING_BYTES(tp)); - if (!(tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE)) + if (!tg3_flag(tp, JUMBO_RING_ENABLE)) goto done; for (i = 0; i <= tp->rx_jmb_ring_mask; i++) { @@ -6544,8 +6550,7 @@ static int tg3_rx_prodring_init(struct tg3 *tp, if (!tpr->rx_std) goto err_out; - if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && - !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { + if (tg3_flag(tp, JUMBO_CAPABLE) && !tg3_flag(tp, 5780_CLASS)) { tpr->rx_jmb_buffers = kzalloc(TG3_RX_JMB_BUFF_RING_SIZE(tp), GFP_KERNEL); if (!tpr->rx_jmb_buffers) @@ -6743,8 +6748,8 @@ static int tg3_alloc_consistent(struct tg3 *tp) /* If multivector TSS is enabled, vector 0 does not handle * tx interrupts. Don't allocate any resources for it. */ - if ((!i && !(tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS)) || - (i && (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS))) { + if ((!i && !tg3_flag(tp, ENABLE_TSS)) || + (i && tg3_flag(tp, ENABLE_TSS))) { tnapi->tx_buffers = kzalloc(sizeof(struct ring_info) * TG3_TX_RING_SIZE, GFP_KERNEL); @@ -6784,7 +6789,7 @@ static int tg3_alloc_consistent(struct tg3 *tp) * If multivector RSS is enabled, vector 0 does not handle * rx or tx interrupts. Don't allocate any resources for it. */ - if (!i && (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)) + if (!i && tg3_flag(tp, ENABLE_RSS)) continue; tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev, @@ -6814,7 +6819,7 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int unsigned int i; u32 val; - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + if (tg3_flag(tp, 5705_PLUS)) { switch (ofs) { case RCVLSC_MODE: case DMAC_MODE: @@ -6924,7 +6929,7 @@ static void tg3_ape_send_event(struct tg3 *tp, u32 event) u32 apedata; /* NCSI does not support APE events */ - if (tp->tg3_flags3 & TG3_FLG3_APE_HAS_NCSI) + if (tg3_flag(tp, APE_HAS_NCSI)) return; apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG); @@ -6963,7 +6968,7 @@ static void tg3_ape_driver_state_change(struct tg3 *tp, int kind) u32 event; u32 apedata; - if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) + if (!tg3_flag(tp, ENABLE_APE)) return; switch (kind) { @@ -6992,7 +6997,7 @@ static void tg3_ape_driver_state_change(struct tg3 *tp, int kind) tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, 0x0); if (device_may_wakeup(&tp->pdev->dev) && - (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)) { + tg3_flag(tp, WOL_ENABLE)) { tg3_ape_write32(tp, TG3_APE_HOST_WOL_SPEED, TG3_APE_HOST_WOL_SPEED_AUTO); apedata = TG3_APE_HOST_DRVR_STATE_WOL; @@ -7021,7 +7026,7 @@ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX, NIC_SRAM_FIRMWARE_MBOX_MAGIC1); - if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) { + if (tg3_flag(tp, ASF_NEW_HANDSHAKE)) { switch (kind) { case RESET_KIND_INIT: tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, @@ -7051,7 +7056,7 @@ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) /* tp->lock is held. */ static void tg3_write_sig_post_reset(struct tg3 *tp, int kind) { - if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) { + if (tg3_flag(tp, ASF_NEW_HANDSHAKE)) { switch (kind) { case RESET_KIND_INIT: tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, @@ -7075,7 +7080,7 @@ static void tg3_write_sig_post_reset(struct tg3 *tp, int kind) /* tp->lock is held. */ static void tg3_write_sig_legacy(struct tg3 *tp, int kind) { - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { + if (tg3_flag(tp, ENABLE_ASF)) { switch (kind) { case RESET_KIND_INIT: tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, @@ -7126,9 +7131,8 @@ static int tg3_poll_fw(struct tg3 *tp) * of the above loop as an error, but do report the lack of * running firmware once. */ - if (i >= 100000 && - !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) { - tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED; + if (i >= 100000 && !tg3_flag(tp, NO_FWARE_REPORTED)) { + tg3_flag_set(tp, NO_FWARE_REPORTED); netdev_info(tp->dev, "No firmware running\n"); } @@ -7161,10 +7165,10 @@ static void tg3_restore_pci_state(struct tg3 *tp) /* Set MAX PCI retry to zero. */ val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE); if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && - (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) + tg3_flag(tp, PCIX_MODE)) val |= PCISTATE_RETRY_SAME_DMA; /* Allow reads and writes to the APE register and memory space. */ - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + if (tg3_flag(tp, ENABLE_APE)) val |= PCISTATE_ALLOW_APE_CTLSPC_WR | PCISTATE_ALLOW_APE_SHMEM_WR | PCISTATE_ALLOW_APE_PSPACE_WR; @@ -7173,7 +7177,7 @@ static void tg3_restore_pci_state(struct tg3 *tp) pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd); if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) { - if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) + if (tg3_flag(tp, PCI_EXPRESS)) pcie_set_readrq(tp->pdev, tp->pcie_readrq); else { pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, @@ -7184,7 +7188,7 @@ static void tg3_restore_pci_state(struct tg3 *tp) } /* Make sure PCI-X relaxed ordering bit is clear. */ - if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) { + if (tg3_flag(tp, PCIX_MODE)) { u16 pcix_cmd; pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD, @@ -7194,12 +7198,12 @@ static void tg3_restore_pci_state(struct tg3 *tp) pcix_cmd); } - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { + if (tg3_flag(tp, 5780_CLASS)) { /* Chip reset on 5780 will reset MSI enable bit, * so need to restore it. */ - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { + if (tg3_flag(tp, USING_MSI)) { u16 ctrl; pci_read_config_word(tp->pdev, @@ -7239,7 +7243,7 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_save_pci_state(tp); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || - (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)) + tg3_flag(tp, 5755_PLUS)) tw32(GRC_FASTBOOT_PC, 0); /* @@ -7258,7 +7262,7 @@ static int tg3_chip_reset(struct tg3 *tp) * at this time, but the irq handler may still be called due to irq * sharing or irqpoll. */ - tp->tg3_flags |= TG3_FLAG_CHIP_RESETTING; + tg3_flag_set(tp, CHIP_RESETTING); for (i = 0; i < tp->irq_cnt; i++) { struct tg3_napi *tnapi = &tp->napi[i]; if (tnapi->hw_status) { @@ -7281,10 +7285,10 @@ static int tg3_chip_reset(struct tg3 *tp) /* do the reset */ val = GRC_MISC_CFG_CORECLK_RESET; - if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { + if (tg3_flag(tp, PCI_EXPRESS)) { /* Force PCIe 1.0a mode */ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && - !(tp->tg3_flags3 & TG3_FLG3_57765_PLUS) && + !tg3_flag(tp, 57765_PLUS) && tr32(TG3_PCIE_PHY_TSTCTL) == (TG3_PCIE_PHY_TSTCTL_PCIE10 | TG3_PCIE_PHY_TSTCTL_PSCRAM)) tw32(TG3_PCIE_PHY_TSTCTL, TG3_PCIE_PHY_TSTCTL_PSCRAM); @@ -7302,8 +7306,7 @@ static int tg3_chip_reset(struct tg3 *tp) } /* Manage gphy power for all CPMU absent PCIe devices. */ - if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && - !(tp->tg3_flags & TG3_FLAG_CPMU_PRESENT)) + if (tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, CPMU_PRESENT)) val |= GRC_MISC_CFG_KEEP_GPHY_POWER; tw32(GRC_MISC_CFG, val); @@ -7336,7 +7339,7 @@ static int tg3_chip_reset(struct tg3 *tp) udelay(120); - if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && tp->pcie_cap) { + if (tg3_flag(tp, PCI_EXPRESS) && tp->pcie_cap) { u16 val16; if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) { @@ -7362,7 +7365,7 @@ static int tg3_chip_reset(struct tg3 *tp) * Older PCIe devices only support the 128 byte * MPS setting. Enforce the restriction. */ - if (!(tp->tg3_flags & TG3_FLAG_CPMU_PRESENT)) + if (!tg3_flag(tp, CPMU_PRESENT)) val16 &= ~PCI_EXP_DEVCTL_PAYLOAD; pci_write_config_word(tp->pdev, tp->pcie_cap + PCI_EXP_DEVCTL, @@ -7381,11 +7384,11 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_restore_pci_state(tp); - tp->tg3_flags &= ~(TG3_FLAG_CHIP_RESETTING | - TG3_FLAG_ERROR_PROCESSED); + tg3_flag_clear(tp, CHIP_RESETTING); + tg3_flag_clear(tp, ERROR_PROCESSED); val = 0; - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) + if (tg3_flag(tp, 5780_CLASS)) val = tr32(MEMARB_MODE); tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE); @@ -7410,7 +7413,7 @@ static int tg3_chip_reset(struct tg3 *tp) tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); } - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + if (tg3_flag(tp, ENABLE_APE)) tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN | MAC_MODE_TDE_ENABLE; @@ -7435,10 +7438,10 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_mdio_start(tp); - if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && + if (tg3_flag(tp, PCI_EXPRESS) && tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && - !(tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) { + !tg3_flag(tp, 57765_PLUS)) { val = tr32(0x7c00); tw32(0x7c00, val | (1 << 25)); @@ -7450,18 +7453,18 @@ static int tg3_chip_reset(struct tg3 *tp) } /* Reprobe ASF enable state. */ - tp->tg3_flags &= ~TG3_FLAG_ENABLE_ASF; - tp->tg3_flags2 &= ~TG3_FLG2_ASF_NEW_HANDSHAKE; + tg3_flag_clear(tp, ENABLE_ASF); + tg3_flag_clear(tp, ASF_NEW_HANDSHAKE); tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); if (val == NIC_SRAM_DATA_SIG_MAGIC) { u32 nic_cfg; tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { - tp->tg3_flags |= TG3_FLAG_ENABLE_ASF; + tg3_flag_set(tp, ENABLE_ASF); tp->last_event_jiffies = jiffies; - if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) - tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE; + if (tg3_flag(tp, 5750_PLUS)) + tg3_flag_set(tp, ASF_NEW_HANDSHAKE); } } @@ -7471,8 +7474,7 @@ static int tg3_chip_reset(struct tg3 *tp) /* tp->lock is held. */ static void tg3_stop_fw(struct tg3 *tp) { - if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && - !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { + if (tg3_flag(tp, ENABLE_ASF) && !tg3_flag(tp, ENABLE_APE)) { /* Wait for RX cpu to ACK the previous event. */ tg3_wait_for_event_ack(tp); @@ -7518,8 +7520,7 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) { int i; - BUG_ON(offset == TX_CPU_BASE && - (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)); + BUG_ON(offset == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS)); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { u32 val = tr32(GRC_VCPU_EXT_CTRL); @@ -7554,7 +7555,7 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) } /* Clear firmware's nvram arbitration. */ - if (tp->tg3_flags & TG3_FLAG_NVRAM) + if (tg3_flag(tp, NVRAM)) tw32(NVRAM_SWARB, SWARB_REQ_CLR0); return 0; } @@ -7572,15 +7573,14 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b int err, lock_err, i; void (*write_op)(struct tg3 *, u32, u32); - if (cpu_base == TX_CPU_BASE && - (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + if (cpu_base == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS)) { netdev_err(tp->dev, "%s: Trying to load TX cpu firmware which is 5705\n", __func__); return -EINVAL; } - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + if (tg3_flag(tp, 5705_PLUS)) write_op = tg3_write_mem; else write_op = tg3_write_indirect_reg32; @@ -7674,7 +7674,9 @@ static int tg3_load_tso_firmware(struct tg3 *tp) unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size; int err, i; - if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + if (tg3_flag(tp, HW_TSO_1) || + tg3_flag(tp, HW_TSO_2) || + tg3_flag(tp, HW_TSO_3)) return 0; fw_data = (void *)tp->fw->data; @@ -7743,7 +7745,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) if (!netif_running(dev)) return 0; - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { + if (tg3_flag(tp, ENABLE_ASF)) { u32 addr0_high, addr0_low, addr1_high, addr1_low; addr0_high = tr32(MAC_ADDR_0_HIGH); @@ -7778,7 +7780,7 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr, (bdinfo_addr + TG3_BDINFO_MAXLEN_FLAGS), maxlen_flags); - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + if (!tg3_flag(tp, 5705_PLUS)) tg3_write_mem(tp, (bdinfo_addr + TG3_BDINFO_NIC_ADDR), nic_addr); @@ -7789,7 +7791,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) { int i; - if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS)) { + if (!tg3_flag(tp, ENABLE_TSS)) { tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs); tw32(HOSTCC_TXMAX_FRAMES, ec->tx_max_coalesced_frames); tw32(HOSTCC_TXCOAL_MAXF_INT, ec->tx_max_coalesced_frames_irq); @@ -7799,7 +7801,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) tw32(HOSTCC_TXCOAL_MAXF_INT, 0); } - if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)) { + if (!tg3_flag(tp, ENABLE_RSS)) { tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs); tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames); tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq); @@ -7809,7 +7811,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) tw32(HOSTCC_RXCOAL_MAXF_INT, 0); } - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + if (!tg3_flag(tp, 5705_PLUS)) { u32 val = ec->stats_block_coalesce_usecs; tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq); @@ -7831,7 +7833,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) reg = HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18; tw32(reg, ec->rx_max_coalesced_frames_irq); - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) { + if (tg3_flag(tp, ENABLE_TSS)) { reg = HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18; tw32(reg, ec->tx_coalesce_usecs); reg = HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18; @@ -7846,7 +7848,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) tw32(HOSTCC_RXMAX_FRAMES_VEC1 + i * 0x18, 0); tw32(HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18, 0); - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) { + if (tg3_flag(tp, ENABLE_TSS)) { tw32(HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18, 0); tw32(HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18, 0); tw32(HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18, 0); @@ -7862,9 +7864,9 @@ static void tg3_rings_reset(struct tg3 *tp) struct tg3_napi *tnapi = &tp->napi[0]; /* Disable all transmit rings but the first. */ - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + if (!tg3_flag(tp, 5705_PLUS)) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16; - else if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) + else if (tg3_flag(tp, 5717_PLUS)) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 4; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2; @@ -7878,9 +7880,9 @@ static void tg3_rings_reset(struct tg3 *tp) /* Disable all receive return rings but the first. */ - if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) + if (tg3_flag(tp, 5717_PLUS)) limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 17; - else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + else if (!tg3_flag(tp, 5705_PLUS)) limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) @@ -7897,16 +7899,16 @@ static void tg3_rings_reset(struct tg3 *tp) tw32_mailbox_f(tp->napi[0].int_mbox, 1); /* Zero mailbox registers. */ - if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) { + if (tg3_flag(tp, SUPPORT_MSIX)) { for (i = 1; i < tp->irq_max; i++) { tp->napi[i].tx_prod = 0; tp->napi[i].tx_cons = 0; - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) + if (tg3_flag(tp, ENABLE_TSS)) tw32_mailbox(tp->napi[i].prodmbox, 0); tw32_rx_mbox(tp->napi[i].consmbox, 0); tw32_mailbox_f(tp->napi[i].int_mbox, 1); } - if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS)) + if (!tg3_flag(tp, ENABLE_TSS)) tw32_mailbox(tp->napi[0].prodmbox, 0); } else { tp->napi[0].tx_prod = 0; @@ -7916,7 +7918,7 @@ static void tg3_rings_reset(struct tg3 *tp) } /* Make sure the NIC-based send BD rings are disabled. */ - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + if (!tg3_flag(tp, 5705_PLUS)) { u32 mbox = MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW; for (i = 0; i < 16; i++) tw32_tx_mbox(mbox + i * 8, 0); @@ -7980,8 +7982,8 @@ static void tg3_setup_rxbd_thresholds(struct tg3 *tp) { u32 val, bdcache_maxcnt, host_rep_thresh, nic_rep_thresh; - if (!(tp->tg3_flags2 & TG3_FLG2_5750_PLUS) || - (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || + if (!tg3_flag(tp, 5750_PLUS) || + tg3_flag(tp, 5780_CLASS) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5700; @@ -7997,14 +7999,13 @@ static void tg3_setup_rxbd_thresholds(struct tg3 *tp) val = min(nic_rep_thresh, host_rep_thresh); tw32(RCVBDI_STD_THRESH, val); - if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) + if (tg3_flag(tp, 57765_PLUS)) tw32(STD_REPLENISH_LWM, bdcache_maxcnt); - if (!(tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) || - (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) + if (!tg3_flag(tp, JUMBO_CAPABLE) || tg3_flag(tp, 5780_CLASS)) return; - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + if (!tg3_flag(tp, 5705_PLUS)) bdcache_maxcnt = TG3_SRAM_RX_JMB_BDCACHE_SIZE_5700; else bdcache_maxcnt = TG3_SRAM_RX_JMB_BDCACHE_SIZE_5717; @@ -8014,7 +8015,7 @@ static void tg3_setup_rxbd_thresholds(struct tg3 *tp) val = min(bdcache_maxcnt / 2, host_rep_thresh); tw32(RCVBDI_JUMBO_THRESH, val); - if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) + if (tg3_flag(tp, 57765_PLUS)) tw32(JMB_REPLENISH_LWM, bdcache_maxcnt); } @@ -8031,7 +8032,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tg3_write_sig_pre_reset(tp, RESET_KIND_INIT); - if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) + if (tg3_flag(tp, INIT_COMPLETE)) tg3_abort_hw(tp, 1); /* Enable MAC control of LPI */ @@ -8051,7 +8052,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) val |= TG3_CPMU_EEEMD_SND_IDX_DET_EN; - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + if (tg3_flag(tp, ENABLE_APE)) val |= TG3_CPMU_EEEMD_APE_TX_DET_EN; tw32_f(TG3_CPMU_EEE_MODE, val); @@ -8110,7 +8111,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS); } - if (tp->tg3_flags3 & TG3_FLG3_L1PLLPD_EN) { + if (tg3_flag(tp, L1PLLPD_EN)) { u32 grc_mode = tr32(GRC_MODE); /* Access the lower 1K of PL PCIE block registers. */ @@ -8151,20 +8152,20 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) * other revision. But do not set this on PCI Express * chips and don't even touch the clocks if the CPMU is present. */ - if (!(tp->tg3_flags & TG3_FLAG_CPMU_PRESENT)) { - if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) + if (!tg3_flag(tp, CPMU_PRESENT)) { + if (!tg3_flag(tp, PCI_EXPRESS)) tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT; tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); } if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && - (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) { + tg3_flag(tp, PCIX_MODE)) { val = tr32(TG3PCI_PCISTATE); val |= PCISTATE_RETRY_SAME_DMA; tw32(TG3PCI_PCISTATE, val); } - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { + if (tg3_flag(tp, ENABLE_APE)) { /* Allow reads and writes to the * APE register and memory space. */ @@ -8191,7 +8192,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (err) return err; - if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) { + if (tg3_flag(tp, 57765_PLUS)) { val = tr32(TG3PCI_DMA_RW_CTRL) & ~DMA_RWCTRL_DIS_CACHE_ALIGNMENT; if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) @@ -8233,7 +8234,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(GRC_MISC_CFG, val); /* Initialize MBUF/DESC pool. */ - if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { + if (tg3_flag(tp, 5750_PLUS)) { /* Do nothing. */ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE); @@ -8243,7 +8244,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96); tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE); tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE); - } else if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { + } else if (tg3_flag(tp, TSO_CAPABLE)) { int fw_len; fw_len = tp->fw_len; @@ -8318,12 +8319,12 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) ((u64) tpr->rx_std_mapping >> 32)); tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, ((u64) tpr->rx_std_mapping & 0xffffffff)); - if (!(tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) + if (!tg3_flag(tp, 5717_PLUS)) tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_BUFFER_DESC); /* Disable the mini ring */ - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + if (!tg3_flag(tp, 5705_PLUS)) tw32(RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED); @@ -8331,10 +8332,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) * blocks on those devices that have them. */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && - !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))) { + (tg3_flag(tp, JUMBO_CAPABLE) && !tg3_flag(tp, 5780_CLASS))) { - if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) { + if (tg3_flag(tp, JUMBO_RING_ENABLE)) { tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, ((u64) tpr->rx_jmb_mapping >> 32)); tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, @@ -8343,7 +8343,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) BDINFO_FLAGS_MAXLEN_SHIFT; tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, val | BDINFO_FLAGS_USE_EXT_RECV); - if (!(tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) || + if (!tg3_flag(tp, USE_JUMBO_BDFLAG) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_JUMBO_BUFFER_DESC); @@ -8352,7 +8352,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) BDINFO_FLAGS_DISABLED); } - if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) { + if (tg3_flag(tp, 57765_PLUS)) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) val = TG3_RX_STD_MAX_SIZE_5700; else @@ -8369,8 +8369,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tpr->rx_std_prod_idx = tp->rx_pending; tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, tpr->rx_std_prod_idx); - tpr->rx_jmb_prod_idx = (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) ? - tp->rx_jumbo_pending : 0; + tpr->rx_jmb_prod_idx = + tg3_flag(tp, JUMBO_RING_ENABLE) ? tp->rx_jumbo_pending : 0; tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, tpr->rx_jmb_prod_idx); tg3_rings_reset(tp); @@ -8421,22 +8421,24 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) { - if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE && + if (tg3_flag(tp, TSO_CAPABLE) && GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128; } else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) && - !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) { + !tg3_flag(tp, IS_5788)) { rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST; } } - if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) + if (tg3_flag(tp, PCI_EXPRESS)) rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST; - if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + if (tg3_flag(tp, HW_TSO_1) || + tg3_flag(tp, HW_TSO_2) || + tg3_flag(tp, HW_TSO_3)) rdmac_mode |= RDMAC_MODE_IPV4_LSO_EN; - if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) || + if (tg3_flag(tp, HW_TSO_3) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) rdmac_mode |= RDMAC_MODE_IPV6_LSO_EN; @@ -8448,7 +8450,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || - (tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) { + tg3_flag(tp, 57765_PLUS)) { val = tr32(TG3_RDMA_RSRVCTRL_REG); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { @@ -8472,12 +8474,12 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) } /* Receive/send statistics. */ - if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { + if (tg3_flag(tp, 5750_PLUS)) { val = tr32(RCVLPC_STATS_ENABLE); val &= ~RCVLPC_STATSENAB_DACK_FIX; tw32(RCVLPC_STATS_ENABLE, val); } else if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) && - (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { + tg3_flag(tp, TSO_CAPABLE)) { val = tr32(RCVLPC_STATS_ENABLE); val &= ~RCVLPC_STATSENAB_LNGBRST_RFIX; tw32(RCVLPC_STATS_ENABLE, val); @@ -8500,7 +8502,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) __tg3_set_coalesce(tp, &tp->coal); - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + if (!tg3_flag(tp, 5705_PLUS)) { /* Status/statistics block address. See tg3_timer, * the tg3_periodic_fetch_stats call there, and * tg3_get_stats to see how this works for 5705/5750 chips. @@ -8526,7 +8528,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE); tw32(RCVLPC_MODE, RCVLPC_MODE_ENABLE); - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + if (!tg3_flag(tp, 5705_PLUS)) tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE); if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) { @@ -8536,13 +8538,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) udelay(10); } - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + if (tg3_flag(tp, ENABLE_APE)) tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN; else tp->mac_mode = 0; tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && + if (!tg3_flag(tp, 5705_PLUS) && !(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) tp->mac_mode |= MAC_MODE_LINK_POLARITY; @@ -8550,12 +8552,12 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) udelay(40); /* tp->grc_local_ctrl is partially set up during tg3_get_invariants(). - * If TG3_FLG2_IS_NIC is zero, we should read the + * If TG3_FLAG_IS_NIC is zero, we should read the * register to preserve the GPIO settings for LOMs. The GPIOs, * whether used as inputs or outputs, are set by boot code after * reset. */ - if (!(tp->tg3_flags2 & TG3_FLG2_IS_NIC)) { + if (!tg3_flag(tp, IS_NIC)) { u32 gpio_mask; gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 | @@ -8573,21 +8575,20 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask; /* GPIO1 must be driven high for eeprom write protect */ - if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) + if (tg3_flag(tp, EEPROM_WRITE_PROT)) tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1); } tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); udelay(100); - if ((tp->tg3_flags2 & TG3_FLG2_USING_MSIX) && - tp->irq_cnt > 1) { + if (tg3_flag(tp, USING_MSIX) && tp->irq_cnt > 1) { val = tr32(MSGINT_MODE); val |= MSGINT_MODE_MULTIVEC_EN | MSGINT_MODE_ENABLE; tw32(MSGINT_MODE, val); } - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + if (!tg3_flag(tp, 5705_PLUS)) { tw32_f(DMAC_MODE, DMAC_MODE_ENABLE); udelay(40); } @@ -8600,18 +8601,18 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) { - if ((tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) && + if (tg3_flag(tp, TSO_CAPABLE) && (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 || tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) { /* nothing */ } else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) && - !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) { + !tg3_flag(tp, IS_5788)) { val |= WDMAC_MODE_RX_ACCEL; } } /* Enable host coalescing bug fix */ - if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) + if (tg3_flag(tp, 5755_PLUS)) val |= WDMAC_MODE_STATUS_TAG_FIX; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) @@ -8620,7 +8621,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32_f(WDMAC_MODE, val); udelay(40); - if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) { + if (tg3_flag(tp, PCIX_MODE)) { u16 pcix_cmd; pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD, @@ -8640,7 +8641,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) udelay(40); tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE); - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + if (!tg3_flag(tp, 5705_PLUS)) tw32(MBFREE_MODE, MBFREE_MODE_ENABLE); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) @@ -8652,14 +8653,16 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE); tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB); val = RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ; - if (tp->tg3_flags3 & TG3_FLG3_LRG_PROD_RING_CAP) + if (tg3_flag(tp, LRG_PROD_RING_CAP)) val |= RCVDBDI_MODE_LRG_RING_SZ; tw32(RCVDBDI_MODE, val); tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE); - if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + if (tg3_flag(tp, HW_TSO_1) || + tg3_flag(tp, HW_TSO_2) || + tg3_flag(tp, HW_TSO_3)) tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8); val = SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE; - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) + if (tg3_flag(tp, ENABLE_TSS)) val |= SNDBDI_MODE_MULTI_TXQ_EN; tw32(SNDBDI_MODE, val); tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE); @@ -8670,7 +8673,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) return err; } - if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { + if (tg3_flag(tp, TSO_CAPABLE)) { err = tg3_load_tso_firmware(tp); if (err) return err; @@ -8678,7 +8681,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->tx_mode = TX_MODE_ENABLE; - if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) || + if (tg3_flag(tp, 5755_PLUS) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tp->tx_mode |= TX_MODE_MBUF_LOCKUP_FIX; @@ -8691,7 +8694,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32_f(MAC_TX_MODE, tp->tx_mode); udelay(100); - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) { + if (tg3_flag(tp, ENABLE_RSS)) { u32 reg = MAC_RSS_INDIR_TBL_0; u8 *ent = (u8 *)&val; @@ -8720,10 +8723,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) } tp->rx_mode = RX_MODE_ENABLE; - if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) + if (tg3_flag(tp, 5755_PLUS)) tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE; - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) + if (tg3_flag(tp, ENABLE_RSS)) tp->rx_mode |= RX_MODE_RSS_ENABLE | RX_MODE_RSS_ITBL_HASH_BITS_7 | RX_MODE_RSS_IPV6_HASH_EN | @@ -8770,7 +8773,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) { /* Use hardware link auto-negotiation */ - tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG; + tg3_flag_set(tp, HW_AUTONEG); } if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) && @@ -8784,7 +8787,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl); } - if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { + if (!tg3_flag(tp, USE_PHYLIB)) { if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER; tp->link_config.speed = tp->link_config.orig_speed; @@ -8817,12 +8820,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(MAC_RCV_RULE_1, 0x86000004 & RCV_RULE_DISABLE_MASK); tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK); - if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && - !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) + if (tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, 5780_CLASS)) limit = 8; else limit = 16; - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) + if (tg3_flag(tp, ENABLE_ASF)) limit -= 4; switch (limit) { case 16: @@ -8860,7 +8862,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) break; } - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + if (tg3_flag(tp, ENABLE_APE)) /* Write our heartbeat update interval to APE. */ tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_INT_MS, APE_HOST_HEARTBEAT_INT_DISABLE); @@ -8951,7 +8953,7 @@ static void tg3_timer(unsigned long __opaque) spin_lock(&tp->lock); - if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) { + if (!tg3_flag(tp, TAGGED_STATUS)) { /* All of this garbage is because when using non-tagged * IRQ status the mailbox/status_block protocol the chip * uses with the cpu is race prone. @@ -8965,7 +8967,7 @@ static void tg3_timer(unsigned long __opaque) } if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { - tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER; + tg3_flag_set(tp, RESTART_TIMER); spin_unlock(&tp->lock); schedule_work(&tp->reset_task); return; @@ -8974,7 +8976,7 @@ static void tg3_timer(unsigned long __opaque) /* This part only runs once per second. */ if (!--tp->timer_counter) { - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + if (tg3_flag(tp, 5705_PLUS)) tg3_periodic_fetch_stats(tp); if (tp->setlpicnt && !--tp->setlpicnt) { @@ -8983,7 +8985,7 @@ static void tg3_timer(unsigned long __opaque) val | TG3_CPMU_EEEMD_LPI_ENABLE); } - if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { + if (tg3_flag(tp, USE_LINKCHG_REG)) { u32 mac_stat; int phy_event; @@ -8998,7 +9000,7 @@ static void tg3_timer(unsigned long __opaque) if (phy_event) tg3_setup_phy(tp, 0); - } else if (tp->tg3_flags & TG3_FLAG_POLL_SERDES) { + } else if (tg3_flag(tp, POLL_SERDES)) { u32 mac_stat = tr32(MAC_STATUS); int need_setup = 0; @@ -9023,7 +9025,7 @@ static void tg3_timer(unsigned long __opaque) tg3_setup_phy(tp, 0); } } else if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) && - (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { + tg3_flag(tp, 5780_CLASS)) { tg3_serdes_parallel_detect(tp); } @@ -9048,8 +9050,7 @@ static void tg3_timer(unsigned long __opaque) * resets. */ if (!--tp->asf_counter) { - if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && - !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { + if (tg3_flag(tp, ENABLE_ASF) && !tg3_flag(tp, ENABLE_APE)) { tg3_wait_for_event_ack(tp); tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, @@ -9085,14 +9086,14 @@ static int tg3_request_irq(struct tg3 *tp, int irq_num) name[IFNAMSIZ-1] = 0; } - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI_OR_MSIX) { + if (tg3_flag(tp, USING_MSI) || tg3_flag(tp, USING_MSIX)) { fn = tg3_msi; - if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) + if (tg3_flag(tp, 1SHOT_MSI)) fn = tg3_msi_1shot; flags = 0; } else { fn = tg3_interrupt; - if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) + if (tg3_flag(tp, TAGGED_STATUS)) fn = tg3_interrupt_tagged; flags = IRQF_SHARED; } @@ -9118,8 +9119,7 @@ static int tg3_test_interrupt(struct tg3 *tp) * Turn off MSI one shot mode. Otherwise this test has no * observable way to know whether the interrupt was delivered. */ - if ((tp->tg3_flags3 & TG3_FLG3_57765_PLUS) && - (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) { + if (tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, USING_MSI)) { val = tr32(MSGINT_MODE) | MSGINT_MODE_ONE_SHOT_DISABLE; tw32(MSGINT_MODE, val); } @@ -9161,8 +9161,7 @@ static int tg3_test_interrupt(struct tg3 *tp) if (intr_ok) { /* Reenable MSI one shot mode. */ - if ((tp->tg3_flags3 & TG3_FLG3_57765_PLUS) && - (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) { + if (tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, USING_MSI)) { val = tr32(MSGINT_MODE) & ~MSGINT_MODE_ONE_SHOT_DISABLE; tw32(MSGINT_MODE, val); } @@ -9180,7 +9179,7 @@ static int tg3_test_msi(struct tg3 *tp) int err; u16 pci_cmd; - if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSI)) + if (!tg3_flag(tp, USING_MSI)) return 0; /* Turn off SERR reporting in case MSI terminates with Master @@ -9210,7 +9209,7 @@ static int tg3_test_msi(struct tg3 *tp) pci_disable_msi(tp->pdev); - tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; + tg3_flag_clear(tp, USING_MSI); tp->napi[0].irq_vec = tp->pdev->irq; err = tg3_request_irq(tp, 0); @@ -9307,11 +9306,11 @@ static bool tg3_enable_msix(struct tg3 *tp) } if (tp->irq_cnt > 1) { - tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS; + tg3_flag_set(tp, ENABLE_RSS); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { - tp->tg3_flags3 |= TG3_FLG3_ENABLE_TSS; + tg3_flag_set(tp, ENABLE_TSS); netif_set_real_num_tx_queues(tp->dev, tp->irq_cnt - 1); } } @@ -9321,8 +9320,8 @@ static bool tg3_enable_msix(struct tg3 *tp) static void tg3_ints_init(struct tg3 *tp) { - if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSI_OR_MSIX) && - !(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) { + if ((tg3_flag(tp, SUPPORT_MSI) || tg3_flag(tp, SUPPORT_MSIX)) && + !tg3_flag(tp, TAGGED_STATUS)) { /* All MSI supporting chips should support tagged * status. Assert that this is the case. */ @@ -9331,21 +9330,19 @@ static void tg3_ints_init(struct tg3 *tp) goto defcfg; } - if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) && tg3_enable_msix(tp)) - tp->tg3_flags2 |= TG3_FLG2_USING_MSIX; - else if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) && - pci_enable_msi(tp->pdev) == 0) - tp->tg3_flags2 |= TG3_FLG2_USING_MSI; + if (tg3_flag(tp, SUPPORT_MSIX) && tg3_enable_msix(tp)) + tg3_flag_set(tp, USING_MSIX); + else if (tg3_flag(tp, SUPPORT_MSI) && pci_enable_msi(tp->pdev) == 0) + tg3_flag_set(tp, USING_MSI); - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI_OR_MSIX) { + if (tg3_flag(tp, USING_MSI) || tg3_flag(tp, USING_MSIX)) { u32 msi_mode = tr32(MSGINT_MODE); - if ((tp->tg3_flags2 & TG3_FLG2_USING_MSIX) && - tp->irq_cnt > 1) + if (tg3_flag(tp, USING_MSIX) && tp->irq_cnt > 1) msi_mode |= MSGINT_MODE_MULTIVEC_EN; tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE); } defcfg: - if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSIX)) { + if (!tg3_flag(tp, USING_MSIX)) { tp->irq_cnt = 1; tp->napi[0].irq_vec = tp->pdev->irq; netif_set_real_num_tx_queues(tp->dev, 1); @@ -9355,12 +9352,14 @@ defcfg: static void tg3_ints_fini(struct tg3 *tp) { - if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX) + if (tg3_flag(tp, USING_MSIX)) pci_disable_msix(tp->pdev); - else if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) + else if (tg3_flag(tp, USING_MSI)) pci_disable_msi(tp->pdev); - tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI_OR_MSIX; - tp->tg3_flags3 &= ~(TG3_FLG3_ENABLE_RSS | TG3_FLG3_ENABLE_TSS); + tg3_flag_clear(tp, USING_MSI); + tg3_flag_clear(tp, USING_MSIX); + tg3_flag_clear(tp, ENABLE_RSS); + tg3_flag_clear(tp, ENABLE_TSS); } static int tg3_open(struct net_device *dev) @@ -9375,10 +9374,10 @@ static int tg3_open(struct net_device *dev) return err; } else if (err) { netdev_warn(tp->dev, "TSO capability disabled\n"); - tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; - } else if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { + tg3_flag_clear(tp, TSO_CAPABLE); + } else if (!tg3_flag(tp, TSO_CAPABLE)) { netdev_notice(tp->dev, "TSO capability restored\n"); - tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; + tg3_flag_set(tp, TSO_CAPABLE); } } @@ -9391,7 +9390,7 @@ static int tg3_open(struct net_device *dev) tg3_full_lock(tp, 0); tg3_disable_ints(tp); - tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; + tg3_flag_clear(tp, INIT_COMPLETE); tg3_full_unlock(tp); @@ -9432,7 +9431,7 @@ static int tg3_open(struct net_device *dev) tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_free_rings(tp); } else { - if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) + if (tg3_flag(tp, TAGGED_STATUS)) tp->timer_offset = HZ; else tp->timer_offset = HZ / 10; @@ -9454,7 +9453,7 @@ static int tg3_open(struct net_device *dev) if (err) goto err_out3; - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { + if (tg3_flag(tp, USING_MSI)) { err = tg3_test_msi(tp); if (err) { @@ -9466,8 +9465,7 @@ static int tg3_open(struct net_device *dev) goto err_out2; } - if (!(tp->tg3_flags3 & TG3_FLG3_57765_PLUS) && - (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) { + if (!tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, USING_MSI)) { u32 val = tr32(PCIE_TRANSACTION_CFG); tw32(PCIE_TRANSACTION_CFG, @@ -9480,7 +9478,7 @@ static int tg3_open(struct net_device *dev) tg3_full_lock(tp, 0); add_timer(&tp->timer); - tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; + tg3_flag_set(tp, INIT_COMPLETE); tg3_enable_ints(tp); tg3_full_unlock(tp); @@ -9529,7 +9527,7 @@ static int tg3_close(struct net_device *dev) tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_free_rings(tp); - tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; + tg3_flag_clear(tp, INIT_COMPLETE); tg3_full_unlock(tp); @@ -9786,7 +9784,7 @@ static void __tg3_set_rx_mode(struct net_device *dev) /* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG * flag clear. */ - if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) + if (!tg3_flag(tp, ENABLE_ASF)) rx_mode |= RX_MODE_KEEP_VLAN_TAG; #endif @@ -9879,7 +9877,7 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u32 i, offset, len, b_offset, b_count; __be32 val; - if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) + if (tg3_flag(tp, NO_NVRAM)) return -EINVAL; if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) @@ -9947,7 +9945,7 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) return -EAGAIN; - if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || + if (tg3_flag(tp, NO_NVRAM) || eeprom->magic != TG3_EEPROM_MAGIC) return -EINVAL; @@ -9999,7 +9997,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct tg3 *tp = netdev_priv(dev); - if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if (tg3_flag(tp, USE_PHYLIB)) { struct phy_device *phydev; if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return -EAGAIN; @@ -10045,7 +10043,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct tg3 *tp = netdev_priv(dev); - if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if (tg3_flag(tp, USE_PHYLIB)) { struct phy_device *phydev; if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return -EAGAIN; @@ -10145,14 +10143,12 @@ static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct tg3 *tp = netdev_priv(dev); - if ((tp->tg3_flags & TG3_FLAG_WOL_CAP) && - device_can_wakeup(&tp->pdev->dev)) + if (tg3_flag(tp, WOL_CAP) && device_can_wakeup(&tp->pdev->dev)) wol->supported = WAKE_MAGIC; else wol->supported = 0; wol->wolopts = 0; - if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) && - device_can_wakeup(&tp->pdev->dev)) + if (tg3_flag(tp, WOL_ENABLE) && device_can_wakeup(&tp->pdev->dev)) wol->wolopts = WAKE_MAGIC; memset(&wol->sopass, 0, sizeof(wol->sopass)); } @@ -10165,16 +10161,16 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; if ((wol->wolopts & WAKE_MAGIC) && - !((tp->tg3_flags & TG3_FLAG_WOL_CAP) && device_can_wakeup(dp))) + !(tg3_flag(tp, WOL_CAP) && device_can_wakeup(dp))) return -EINVAL; device_set_wakeup_enable(dp, wol->wolopts & WAKE_MAGIC); spin_lock_bh(&tp->lock); if (device_may_wakeup(dp)) - tp->tg3_flags |= TG3_FLAG_WOL_ENABLE; + tg3_flag_set(tp, WOL_ENABLE); else - tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE; + tg3_flag_clear(tp, WOL_ENABLE); spin_unlock_bh(&tp->lock); return 0; @@ -10203,7 +10199,7 @@ static int tg3_nway_reset(struct net_device *dev) if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) return -EINVAL; - if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if (tg3_flag(tp, USE_PHYLIB)) { if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return -EAGAIN; r = phy_start_aneg(tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]); @@ -10232,7 +10228,7 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam * ering->rx_max_pending = tp->rx_std_ring_mask; ering->rx_mini_max_pending = 0; - if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) + if (tg3_flag(tp, JUMBO_RING_ENABLE)) ering->rx_jumbo_max_pending = tp->rx_jmb_ring_mask; else ering->rx_jumbo_max_pending = 0; @@ -10241,7 +10237,7 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam * ering->rx_pending = tp->rx_pending; ering->rx_mini_pending = 0; - if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) + if (tg3_flag(tp, JUMBO_RING_ENABLE)) ering->rx_jumbo_pending = tp->rx_jumbo_pending; else ering->rx_jumbo_pending = 0; @@ -10258,7 +10254,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e (ering->rx_jumbo_pending > tp->rx_jmb_ring_mask) || (ering->tx_pending > TG3_TX_RING_SIZE - 1) || (ering->tx_pending <= MAX_SKB_FRAGS) || - ((tp->tg3_flags2 & TG3_FLG2_TSO_BUG) && + (tg3_flag(tp, TSO_BUG) && (ering->tx_pending <= (MAX_SKB_FRAGS * 3)))) return -EINVAL; @@ -10272,7 +10268,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e tp->rx_pending = ering->rx_pending; - if ((tp->tg3_flags2 & TG3_FLG2_MAX_RXPEND_64) && + if (tg3_flag(tp, MAX_RXPEND_64) && tp->rx_pending > 63) tp->rx_pending = 63; tp->rx_jumbo_pending = ering->rx_jumbo_pending; @@ -10299,7 +10295,7 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam { struct tg3 *tp = netdev_priv(dev); - epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0; + epause->autoneg = !!tg3_flag(tp, PAUSE_AUTONEG); if (tp->link_config.active_flowctrl & FLOW_CTRL_RX) epause->rx_pause = 1; @@ -10317,7 +10313,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam struct tg3 *tp = netdev_priv(dev); int err = 0; - if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if (tg3_flag(tp, USE_PHYLIB)) { u32 newadv; struct phy_device *phydev; @@ -10345,9 +10341,9 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam newadv = 0; if (epause->autoneg) - tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; + tg3_flag_set(tp, PAUSE_AUTONEG); else - tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG; + tg3_flag_clear(tp, PAUSE_AUTONEG); if (tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) { u32 oldadv = phydev->advertising & @@ -10389,9 +10385,9 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam tg3_full_lock(tp, irq_sync); if (epause->autoneg) - tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; + tg3_flag_set(tp, PAUSE_AUTONEG); else - tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG; + tg3_flag_clear(tp, PAUSE_AUTONEG); if (epause->rx_pause) tp->link_config.flowctrl |= FLOW_CTRL_RX; else @@ -10490,8 +10486,7 @@ static __be32 * tg3_vpd_readblock(struct tg3 *tp) u32 offset = 0, len = 0; u32 magic, val; - if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || - tg3_nvram_read(tp, 0, &magic)) + if (tg3_flag(tp, NO_NVRAM) || tg3_nvram_read(tp, 0, &magic)) return NULL; if (magic == TG3_EEPROM_MAGIC) { @@ -10571,7 +10566,7 @@ static int tg3_test_nvram(struct tg3 *tp) __be32 *buf; int i, j, k, err = 0, size; - if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) + if (tg3_flag(tp, NO_NVRAM)) return 0; if (tg3_nvram_read(tp, 0, &magic) != 0) @@ -10913,9 +10908,9 @@ static int tg3_test_registers(struct tg3 *tp) }; is_5705 = is_5750 = 0; - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + if (tg3_flag(tp, 5705_PLUS)) { is_5705 = 1; - if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) + if (tg3_flag(tp, 5750_PLUS)) is_5750 = 1; } @@ -10926,7 +10921,7 @@ static int tg3_test_registers(struct tg3 *tp) if (!is_5705 && (reg_tbl[i].flags & TG3_FL_5705)) continue; - if ((tp->tg3_flags2 & TG3_FLG2_IS_5788) && + if (tg3_flag(tp, IS_5788) && (reg_tbl[i].flags & TG3_FL_NOT_5788)) continue; @@ -11049,15 +11044,15 @@ static int tg3_test_memory(struct tg3 *tp) int err = 0; int i; - if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) + if (tg3_flag(tp, 5717_PLUS)) mem_tbl = mem_tbl_5717; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) mem_tbl = mem_tbl_57765; - else if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) + else if (tg3_flag(tp, 5755_PLUS)) mem_tbl = mem_tbl_5755; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) mem_tbl = mem_tbl_5906; - else if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + else if (tg3_flag(tp, 5705_PLUS)) mem_tbl = mem_tbl_5705; else mem_tbl = mem_tbl_570x; @@ -11113,9 +11108,9 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) tnapi = &tp->napi[0]; rnapi = &tp->napi[0]; if (tp->irq_cnt > 1) { - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) + if (tg3_flag(tp, ENABLE_RSS)) rnapi = &tp->napi[1]; - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) + if (tg3_flag(tp, ENABLE_TSS)) tnapi = &tp->napi[1]; } coal_now = tnapi->coal_now | rnapi->coal_now; @@ -11127,13 +11122,13 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) * all newer ASIC revisions. */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 || - (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT)) + tg3_flag(tp, CPMU_PRESENT)) return 0; mac_mode = tp->mac_mode & ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); mac_mode |= MAC_MODE_PORT_INT_LPBACK; - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + if (!tg3_flag(tp, 5705_PLUS)) mac_mode |= MAC_MODE_LINK_POLARITY; if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) mac_mode |= MAC_MODE_PORT_MODE_MII; @@ -11222,7 +11217,9 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) base_flags = (TXD_FLAG_CPU_PRE_DMA | TXD_FLAG_CPU_POST_DMA); - if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { + if (tg3_flag(tp, HW_TSO_1) || + tg3_flag(tp, HW_TSO_2) || + tg3_flag(tp, HW_TSO_3)) { struct tcphdr *th; val = ETH_HLEN + TG3_TSO_IP_HDR_LEN; th = (struct tcphdr *)&tx_data[val]; @@ -11230,14 +11227,14 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) } else base_flags |= TXD_FLAG_TCPUDP_CSUM; - if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) { + if (tg3_flag(tp, HW_TSO_3)) { mss |= (hdr_len & 0xc) << 12; if (hdr_len & 0x10) base_flags |= 0x00000010; base_flags |= (hdr_len & 0x3e0) << 5; - } else if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) + } else if (tg3_flag(tp, HW_TSO_2)) mss |= hdr_len << 9; - else if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1) || + else if (tg3_flag(tp, HW_TSO_1) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { mss |= (TG3_TSO_TCP_OPT_LEN << 9); } else { @@ -11381,7 +11378,7 @@ static int tg3_test_loopback(struct tg3 *tp) goto done; } - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) { + if (tg3_flag(tp, ENABLE_RSS)) { int i; /* Reroute all rx packets to the 1st queue */ @@ -11394,7 +11391,7 @@ static int tg3_test_loopback(struct tg3 *tp) if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD) tg3_phy_toggle_apd(tp, false); - if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) { + if (tg3_flag(tp, CPMU_PRESENT)) { int i; u32 status; @@ -11423,11 +11420,11 @@ static int tg3_test_loopback(struct tg3 *tp) if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_MAC_LOOPBACK)) err |= TG3_STD_LOOPBACK_FAILED << TG3_MAC_LOOPBACK_SHIFT; - if ((tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) && + if (tg3_flag(tp, JUMBO_RING_ENABLE) && tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_MAC_LOOPBACK)) err |= TG3_JMB_LOOPBACK_FAILED << TG3_MAC_LOOPBACK_SHIFT; - if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) { + if (tg3_flag(tp, CPMU_PRESENT)) { tw32(TG3_CPMU_CTRL, cpmuctrl); /* Release the mutex */ @@ -11435,15 +11432,15 @@ static int tg3_test_loopback(struct tg3 *tp) } if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) && - !(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { + !tg3_flag(tp, USE_PHYLIB)) { if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_PHY_LOOPBACK)) err |= TG3_STD_LOOPBACK_FAILED << TG3_PHY_LOOPBACK_SHIFT; - if ((tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) && + if (tg3_flag(tp, TSO_CAPABLE) && tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_TSO_LOOPBACK)) err |= TG3_TSO_LOOPBACK_FAILED << TG3_PHY_LOOPBACK_SHIFT; - if ((tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) && + if (tg3_flag(tp, JUMBO_RING_ENABLE) && tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_PHY_LOOPBACK)) err |= TG3_JMB_LOOPBACK_FAILED << TG3_PHY_LOOPBACK_SHIFT; @@ -11491,7 +11488,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, tg3_halt(tp, RESET_KIND_SUSPEND, 1); err = tg3_nvram_lock(tp); tg3_halt_cpu(tp, RX_CPU_BASE); - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + if (!tg3_flag(tp, 5705_PLUS)) tg3_halt_cpu(tp, TX_CPU_BASE); if (!err) tg3_nvram_unlock(tp); @@ -11521,7 +11518,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); if (netif_running(dev)) { - tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; + tg3_flag_set(tp, INIT_COMPLETE); err2 = tg3_restart_hw(tp, 1); if (!err2) tg3_netif_start(tp); @@ -11543,7 +11540,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) struct tg3 *tp = netdev_priv(dev); int err; - if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if (tg3_flag(tp, USE_PHYLIB)) { struct phy_device *phydev; if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return -EAGAIN; @@ -11608,7 +11605,7 @@ static int tg3_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) u32 max_rxcoal_tick_int = 0, max_txcoal_tick_int = 0; u32 max_stat_coal_ticks = 0, min_stat_coal_ticks = 0; - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + if (!tg3_flag(tp, 5705_PLUS)) { max_rxcoal_tick_int = MAX_RXCOAL_TICK_INT; max_txcoal_tick_int = MAX_TXCOAL_TICK_INT; max_stat_coal_ticks = MAX_STAT_COAL_TICKS; @@ -11722,8 +11719,7 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp) { u32 val; - if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || - tg3_nvram_read(tp, 0, &val) != 0) + if (tg3_flag(tp, NO_NVRAM) || tg3_nvram_read(tp, 0, &val) != 0) return; /* Selfboot format */ @@ -11758,19 +11754,19 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp) nvcfg1 = tr32(NVRAM_CFG1); if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) { - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, FLASH); } else { nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; tw32(NVRAM_CFG1, nvcfg1); } if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) || - (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { + tg3_flag(tp, 5780_CLASS)) { switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) { case FLASH_VENDOR_ATMEL_FLASH_BUFFERED: tp->nvram_jedecnum = JEDEC_ATMEL; tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tg3_flag_set(tp, NVRAM_BUFFERED); break; case FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED: tp->nvram_jedecnum = JEDEC_ATMEL; @@ -11779,12 +11775,12 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp) case FLASH_VENDOR_ATMEL_EEPROM: tp->nvram_jedecnum = JEDEC_ATMEL; tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tg3_flag_set(tp, NVRAM_BUFFERED); break; case FLASH_VENDOR_ST: tp->nvram_jedecnum = JEDEC_ST; tp->nvram_pagesize = ST_M45PEX0_PAGE_SIZE; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tg3_flag_set(tp, NVRAM_BUFFERED); break; case FLASH_VENDOR_SAIFUN: tp->nvram_jedecnum = JEDEC_SAIFUN; @@ -11799,7 +11795,7 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp) } else { tp->nvram_jedecnum = JEDEC_ATMEL; tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tg3_flag_set(tp, NVRAM_BUFFERED); } } @@ -11838,29 +11834,29 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) /* NVRAM protection for TPM */ if (nvcfg1 & (1 << 27)) - tp->tg3_flags3 |= TG3_FLG3_PROTECTED_NVRAM; + tg3_flag_set(tp, PROTECTED_NVRAM); switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { case FLASH_5752VENDOR_ATMEL_EEPROM_64KHZ: case FLASH_5752VENDOR_ATMEL_EEPROM_376KHZ: tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tg3_flag_set(tp, NVRAM_BUFFERED); break; case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED: tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); break; case FLASH_5752VENDOR_ST_M45PE10: case FLASH_5752VENDOR_ST_M45PE20: case FLASH_5752VENDOR_ST_M45PE40: tp->nvram_jedecnum = JEDEC_ST; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); break; } - if (tp->tg3_flags2 & TG3_FLG2_FLASH) { + if (tg3_flag(tp, FLASH)) { tg3_nvram_get_pagesize(tp, nvcfg1); } else { /* For eeprom, set pagesize to maximum eeprom size */ @@ -11879,7 +11875,7 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) /* NVRAM protection for TPM */ if (nvcfg1 & (1 << 27)) { - tp->tg3_flags3 |= TG3_FLG3_PROTECTED_NVRAM; + tg3_flag_set(tp, PROTECTED_NVRAM); protect = 1; } @@ -11890,8 +11886,8 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) case FLASH_5755VENDOR_ATMEL_FLASH_3: case FLASH_5755VENDOR_ATMEL_FLASH_5: tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); tp->nvram_pagesize = 264; if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1 || nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_5) @@ -11908,8 +11904,8 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) case FLASH_5752VENDOR_ST_M45PE20: case FLASH_5752VENDOR_ST_M45PE40: tp->nvram_jedecnum = JEDEC_ST; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); tp->nvram_pagesize = 256; if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE10) tp->nvram_size = (protect ? @@ -11939,7 +11935,7 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) case FLASH_5787VENDOR_MICRO_EEPROM_64KHZ: case FLASH_5787VENDOR_MICRO_EEPROM_376KHZ: tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tg3_flag_set(tp, NVRAM_BUFFERED); tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; @@ -11950,16 +11946,16 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) case FLASH_5755VENDOR_ATMEL_FLASH_2: case FLASH_5755VENDOR_ATMEL_FLASH_3: tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); tp->nvram_pagesize = 264; break; case FLASH_5752VENDOR_ST_M45PE10: case FLASH_5752VENDOR_ST_M45PE20: case FLASH_5752VENDOR_ST_M45PE40: tp->nvram_jedecnum = JEDEC_ST; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); tp->nvram_pagesize = 256; break; } @@ -11973,7 +11969,7 @@ static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp) /* NVRAM protection for TPM */ if (nvcfg1 & (1 << 27)) { - tp->tg3_flags3 |= TG3_FLG3_PROTECTED_NVRAM; + tg3_flag_set(tp, PROTECTED_NVRAM); protect = 1; } @@ -11988,9 +11984,9 @@ static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp) case FLASH_5761VENDOR_ATMEL_MDB081D: case FLASH_5761VENDOR_ATMEL_MDB161D: tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; - tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); + tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS); tp->nvram_pagesize = 256; break; case FLASH_5761VENDOR_ST_A_M45PE20: @@ -12002,8 +11998,8 @@ static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp) case FLASH_5761VENDOR_ST_M_M45PE80: case FLASH_5761VENDOR_ST_M_M45PE16: tp->nvram_jedecnum = JEDEC_ST; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); tp->nvram_pagesize = 256; break; } @@ -12043,7 +12039,7 @@ static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp) static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp) { tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tg3_flag_set(tp, NVRAM_BUFFERED); tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; } @@ -12057,7 +12053,7 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp) case FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ: case FLASH_5787VENDOR_MICRO_EEPROM_376KHZ: tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tg3_flag_set(tp, NVRAM_BUFFERED); tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; @@ -12071,8 +12067,8 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp) case FLASH_57780VENDOR_ATMEL_AT45DB041D: case FLASH_57780VENDOR_ATMEL_AT45DB041B: tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED: @@ -12094,8 +12090,8 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp) case FLASH_5752VENDOR_ST_M45PE20: case FLASH_5752VENDOR_ST_M45PE40: tp->nvram_jedecnum = JEDEC_ST; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { case FLASH_5752VENDOR_ST_M45PE10: @@ -12110,13 +12106,13 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp) } break; default: - tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM; + tg3_flag_set(tp, NO_NVRAM); return; } tg3_nvram_get_pagesize(tp, nvcfg1); if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528) - tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS; + tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS); } @@ -12130,7 +12126,7 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp) case FLASH_5717VENDOR_ATMEL_EEPROM: case FLASH_5717VENDOR_MICRO_EEPROM: tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tg3_flag_set(tp, NVRAM_BUFFERED); tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; @@ -12144,8 +12140,8 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp) case FLASH_5717VENDOR_ATMEL_ADB021D: case FLASH_5717VENDOR_ATMEL_45USPT: tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { case FLASH_5717VENDOR_ATMEL_MDB021D: @@ -12171,8 +12167,8 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp) case FLASH_5717VENDOR_ST_25USPT: case FLASH_5717VENDOR_ST_45USPT: tp->nvram_jedecnum = JEDEC_ST; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { case FLASH_5717VENDOR_ST_M_M25PE20: @@ -12189,13 +12185,13 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp) } break; default: - tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM; + tg3_flag_set(tp, NO_NVRAM); return; } tg3_nvram_get_pagesize(tp, nvcfg1); if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528) - tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS; + tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS); } static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp) @@ -12209,7 +12205,7 @@ static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp) case FLASH_5720_EEPROM_HD: case FLASH_5720_EEPROM_LD: tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tg3_flag_set(tp, NVRAM_BUFFERED); nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; tw32(NVRAM_CFG1, nvcfg1); @@ -12231,8 +12227,8 @@ static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp) case FLASH_5720VENDOR_A_ATMEL_DB081D: case FLASH_5720VENDOR_ATMEL_45USPT: tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); switch (nvmpinstrp) { case FLASH_5720VENDOR_M_ATMEL_DB021D: @@ -12273,8 +12269,8 @@ static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp) case FLASH_5720VENDOR_ST_25USPT: case FLASH_5720VENDOR_ST_45USPT: tp->nvram_jedecnum = JEDEC_ST; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; + tg3_flag_set(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, FLASH); switch (nvmpinstrp) { case FLASH_5720VENDOR_M_ST_M25PE20: @@ -12301,13 +12297,13 @@ static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp) } break; default: - tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM; + tg3_flag_set(tp, NO_NVRAM); return; } tg3_nvram_get_pagesize(tp, nvcfg1); if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528) - tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS; + tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS); } /* Chips other than 5700/5701 use the NVRAM for fetching info. */ @@ -12327,7 +12323,7 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) { - tp->tg3_flags |= TG3_FLAG_NVRAM; + tg3_flag_set(tp, NVRAM); if (tg3_nvram_lock(tp)) { netdev_warn(tp->dev, @@ -12369,7 +12365,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) tg3_nvram_unlock(tp); } else { - tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED); + tg3_flag_clear(tp, NVRAM); + tg3_flag_clear(tp, NVRAM_BUFFERED); tg3_get_eeprom_size(tp); } @@ -12552,7 +12549,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, nvram_cmd |= NVRAM_CMD_LAST; if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && - !(tp->tg3_flags3 & TG3_FLG3_5755_PLUS) && + !tg3_flag(tp, 5755_PLUS) && (tp->nvram_jedecnum == JEDEC_ST) && (nvram_cmd & NVRAM_CMD_FIRST)) { @@ -12562,7 +12559,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, break; } - if (!(tp->tg3_flags2 & TG3_FLG2_FLASH)) { + if (!tg3_flag(tp, FLASH)) { /* We always do complete word writes to eeprom. */ nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST); } @@ -12578,13 +12575,13 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int ret; - if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) { + if (tg3_flag(tp, EEPROM_WRITE_PROT)) { tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl & ~GRC_LCLCTRL_GPIO_OUTPUT1); udelay(40); } - if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) { + if (!tg3_flag(tp, NVRAM)) { ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf); } else { u32 grc_mode; @@ -12594,16 +12591,13 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) return ret; tg3_enable_nvram_access(tp); - if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && - !(tp->tg3_flags3 & TG3_FLG3_PROTECTED_NVRAM)) + if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) tw32(NVRAM_WRITE1, 0x406); grc_mode = tr32(GRC_MODE); tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE); - if ((tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) || - !(tp->tg3_flags2 & TG3_FLG2_FLASH)) { - + if (tg3_flag(tp, NVRAM_BUFFERED) || !tg3_flag(tp, FLASH)) { ret = tg3_nvram_write_block_buffered(tp, offset, len, buf); } else { @@ -12618,7 +12612,7 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) tg3_nvram_unlock(tp); } - if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) { + if (tg3_flag(tp, EEPROM_WRITE_PROT)) { tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); udelay(40); } @@ -12740,19 +12734,20 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->led_ctrl = LED_CTRL_MODE_PHY_1; /* Assume an onboard device and WOL capable by default. */ - tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT | TG3_FLAG_WOL_CAP; + tg3_flag_set(tp, EEPROM_WRITE_PROT); + tg3_flag_set(tp, WOL_CAP); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM)) { - tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT; - tp->tg3_flags2 |= TG3_FLG2_IS_NIC; + tg3_flag_clear(tp, EEPROM_WRITE_PROT); + tg3_flag_set(tp, IS_NIC); } val = tr32(VCPU_CFGSHDW); if (val & VCPU_CFGSHDW_ASPM_DBNC) - tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND; + tg3_flag_set(tp, ASPM_WORKAROUND); if ((val & VCPU_CFGSHDW_WOL_ENABLE) && (val & VCPU_CFGSHDW_WOL_MAGPKT)) - tp->tg3_flags |= TG3_FLAG_WOL_ENABLE; + tg3_flag_set(tp, WOL_ENABLE); goto done; } @@ -12793,13 +12788,13 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->phy_id = eeprom_phy_id; if (eeprom_phy_serdes) { - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + if (!tg3_flag(tp, 5705_PLUS)) tp->phy_flags |= TG3_PHYFLG_PHY_SERDES; else tp->phy_flags |= TG3_PHYFLG_MII_SERDES; } - if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) + if (tg3_flag(tp, 5750_PLUS)) led_cfg = cfg2 & (NIC_SRAM_DATA_CFG_LED_MODE_MASK | SHASTA_EXT_LED_MODE_MASK); else @@ -12859,34 +12854,34 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->led_ctrl = LED_CTRL_MODE_PHY_1; if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) { - tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; + tg3_flag_set(tp, EEPROM_WRITE_PROT); if ((tp->pdev->subsystem_vendor == PCI_VENDOR_ID_ARIMA) && (tp->pdev->subsystem_device == 0x205a || tp->pdev->subsystem_device == 0x2063)) - tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT; + tg3_flag_clear(tp, EEPROM_WRITE_PROT); } else { - tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT; - tp->tg3_flags2 |= TG3_FLG2_IS_NIC; + tg3_flag_clear(tp, EEPROM_WRITE_PROT); + tg3_flag_set(tp, IS_NIC); } if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { - tp->tg3_flags |= TG3_FLAG_ENABLE_ASF; - if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) - tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE; + tg3_flag_set(tp, ENABLE_ASF); + if (tg3_flag(tp, 5750_PLUS)) + tg3_flag_set(tp, ASF_NEW_HANDSHAKE); } if ((nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE) && - (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)) - tp->tg3_flags3 |= TG3_FLG3_ENABLE_APE; + tg3_flag(tp, 5750_PLUS)) + tg3_flag_set(tp, ENABLE_APE); if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES && !(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)) - tp->tg3_flags &= ~TG3_FLAG_WOL_CAP; + tg3_flag_clear(tp, WOL_CAP); - if ((tp->tg3_flags & TG3_FLAG_WOL_CAP) && + if (tg3_flag(tp, WOL_CAP) && (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE)) - tp->tg3_flags |= TG3_FLAG_WOL_ENABLE; + tg3_flag_set(tp, WOL_ENABLE); if (cfg2 & (1 << 17)) tp->phy_flags |= TG3_PHYFLG_CAPACITIVE_COUPLING; @@ -12896,33 +12891,33 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) if (cfg2 & (1 << 18)) tp->phy_flags |= TG3_PHYFLG_SERDES_PREEMPHASIS; - if (((tp->tg3_flags3 & TG3_FLG3_57765_PLUS) || - ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && - GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX))) && + if ((tg3_flag(tp, 57765_PLUS) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && + GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX)) && (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN)) tp->phy_flags |= TG3_PHYFLG_ENABLE_APD; - if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && + if (tg3_flag(tp, PCI_EXPRESS) && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && - !(tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) { + !tg3_flag(tp, 57765_PLUS)) { u32 cfg3; tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &cfg3); if (cfg3 & NIC_SRAM_ASPM_DEBOUNCE) - tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND; + tg3_flag_set(tp, ASPM_WORKAROUND); } if (cfg4 & NIC_SRAM_RGMII_INBAND_DISABLE) - tp->tg3_flags3 |= TG3_FLG3_RGMII_INBAND_DISABLE; + tg3_flag_set(tp, RGMII_INBAND_DISABLE); if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_RX_EN) - tp->tg3_flags3 |= TG3_FLG3_RGMII_EXT_IBND_RX_EN; + tg3_flag_set(tp, RGMII_EXT_IBND_RX_EN); if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_TX_EN) - tp->tg3_flags3 |= TG3_FLG3_RGMII_EXT_IBND_TX_EN; + tg3_flag_set(tp, RGMII_EXT_IBND_TX_EN); } done: - if (tp->tg3_flags & TG3_FLAG_WOL_CAP) + if (tg3_flag(tp, WOL_CAP)) device_set_wakeup_enable(&tp->pdev->dev, - tp->tg3_flags & TG3_FLAG_WOL_ENABLE); + tg3_flag(tp, WOL_ENABLE)); else device_set_wakeup_capable(&tp->pdev->dev, false); } @@ -13012,18 +13007,17 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) int err; /* flow control autonegotiation is default behavior */ - tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; + tg3_flag_set(tp, PAUSE_AUTONEG); tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX; - if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) + if (tg3_flag(tp, USE_PHYLIB)) return tg3_phy_init(tp); /* Reading the PHY ID register can conflict with ASF * firmware access to the PHY hardware. */ err = 0; - if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || - (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { + if (tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE)) { hw_phy_id = hw_phy_id_masked = TG3_PHY_ID_INVALID; } else { /* Now read the physical PHY_ID from the chip and verify @@ -13079,8 +13073,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) tg3_phy_init_link_config(tp); if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && - !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) && - !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { + !tg3_flag(tp, ENABLE_APE) && + !tg3_flag(tp, ENABLE_ASF)) { u32 bmsr, adv_reg, tg3_ctrl, mask; tg3_readphy(tp, MII_BMSR, &bmsr); @@ -13399,7 +13393,7 @@ static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp) if (offset == TG3_NVM_DIR_END) return; - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + if (!tg3_flag(tp, 5705_PLUS)) start = 0x08000000; else if (tg3_nvram_read(tp, offset - 4, &start)) return; @@ -13439,8 +13433,7 @@ static void __devinit tg3_read_dash_ver(struct tg3 *tp) u32 apedata; char *fwtype; - if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) || - !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) + if (!tg3_flag(tp, ENABLE_APE) || !tg3_flag(tp, ENABLE_ASF)) return; apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG); @@ -13454,7 +13447,7 @@ static void __devinit tg3_read_dash_ver(struct tg3 *tp) apedata = tg3_ape_read32(tp, TG3_APE_FW_VERSION); if (tg3_ape_read32(tp, TG3_APE_FW_FEATURES) & TG3_APE_FW_FEATURE_NCSI) { - tp->tg3_flags3 |= TG3_FLG3_APE_HAS_NCSI; + tg3_flag_set(tp, APE_HAS_NCSI); fwtype = "NCSI"; } else { fwtype = "DASH"; @@ -13478,7 +13471,7 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) if (tp->fw_ver[0] != 0) vpd_vers = true; - if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) { + if (tg3_flag(tp, NO_NVRAM)) { strcat(tp->fw_ver, "sb"); return; } @@ -13495,8 +13488,7 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) else return; - if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || - (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) || vpd_vers) + if (!tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE) || vpd_vers) goto done; tg3_read_mgmtfw_ver(tp); @@ -13509,10 +13501,9 @@ static struct pci_dev * __devinit tg3_find_peer(struct tg3 *); static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp) { - if (tp->tg3_flags3 & TG3_FLG3_LRG_PROD_RING_CAP) + if (tg3_flag(tp, LRG_PROD_RING_CAP)) return TG3_RX_RET_MAX_SIZE_5717; - else if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && - !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) + else if (tg3_flag(tp, JUMBO_CAPABLE) && !tg3_flag(tp, 5780_CLASS)) return TG3_RX_RET_MAX_SIZE_5700; else return TG3_RX_RET_MAX_SIZE_5705; @@ -13638,8 +13629,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (bridge->subordinate && (bridge->subordinate->number == tp->pdev->bus->number)) { - - tp->tg3_flags2 |= TG3_FLG2_ICH_WORKAROUND; + tg3_flag_set(tp, ICH_WORKAROUND); pci_dev_put(bridge); break; } @@ -13671,7 +13661,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pdev->bus->number) && (bridge->subordinate->subordinate >= tp->pdev->bus->number)) { - tp->tg3_flags3 |= TG3_FLG3_5701_DMA_BUG; + tg3_flag_set(tp, 5701_DMA_BUG); pci_dev_put(bridge); break; } @@ -13686,8 +13676,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { - tp->tg3_flags2 |= TG3_FLG2_5780_CLASS; - tp->tg3_flags |= TG3_FLAG_40BIT_DMA_BUG; + tg3_flag_set(tp, 5780_CLASS); + tg3_flag_set(tp, 40BIT_DMA_BUG); tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI); } else { struct pci_dev *bridge = NULL; @@ -13701,7 +13691,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pdev->bus->number) && (bridge->subordinate->subordinate >= tp->pdev->bus->number)) { - tp->tg3_flags |= TG3_FLAG_40BIT_DMA_BUG; + tg3_flag_set(tp, 40BIT_DMA_BUG); pci_dev_put(bridge); break; } @@ -13723,11 +13713,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) - tp->tg3_flags3 |= TG3_FLG3_5717_PLUS; + tg3_flag_set(tp, 5717_PLUS); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 || - (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) - tp->tg3_flags3 |= TG3_FLG3_57765_PLUS; + tg3_flag(tp, 5717_PLUS)) + tg3_flag_set(tp, 57765_PLUS); /* Intentionally exclude ASIC_REV_5906 */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || @@ -13736,19 +13726,19 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || - (tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) - tp->tg3_flags3 |= TG3_FLG3_5755_PLUS; + tg3_flag(tp, 57765_PLUS)) + tg3_flag_set(tp, 5755_PLUS); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 || - (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) || - (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) - tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; + tg3_flag(tp, 5755_PLUS) || + tg3_flag(tp, 5780_CLASS)) + tg3_flag_set(tp, 5750_PLUS); if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) || - (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)) - tp->tg3_flags2 |= TG3_FLG2_5705_PLUS; + tg3_flag(tp, 5750_PLUS)) + tg3_flag_set(tp, 5705_PLUS); /* 5700 B0 chips do not support checksumming correctly due * to hardware bugs. @@ -13756,7 +13746,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->pci_chip_rev_id != CHIPREV_ID_5700_B0) { u32 features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM; - if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) + if (tg3_flag(tp, 5755_PLUS)) features |= NETIF_F_IPV6_CSUM; tp->dev->features |= features; tp->dev->hw_features |= features; @@ -13766,20 +13756,21 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Determine TSO capabilities */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) ; /* Do nothing. HW bug. */ - else if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) - tp->tg3_flags2 |= TG3_FLG2_HW_TSO_3; - else if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) || + else if (tg3_flag(tp, 57765_PLUS)) + tg3_flag_set(tp, HW_TSO_3); + else if (tg3_flag(tp, 5755_PLUS) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) - tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2; - else if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { - tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 | TG3_FLG2_TSO_BUG; + tg3_flag_set(tp, HW_TSO_2); + else if (tg3_flag(tp, 5750_PLUS)) { + tg3_flag_set(tp, HW_TSO_1); + tg3_flag_set(tp, TSO_BUG); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 && tp->pci_chip_rev_id >= CHIPREV_ID_5750_C2) - tp->tg3_flags2 &= ~TG3_FLG2_TSO_BUG; + tg3_flag_clear(tp, TSO_BUG); } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 && tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) { - tp->tg3_flags2 |= TG3_FLG2_TSO_BUG; + tg3_flag_set(tp, TSO_BUG); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) tp->fw_needed = FIRMWARE_TG3TSO5; else @@ -13788,22 +13779,22 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->irq_max = 1; - if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { - tp->tg3_flags |= TG3_FLAG_SUPPORT_MSI; + if (tg3_flag(tp, 5750_PLUS)) { + tg3_flag_set(tp, SUPPORT_MSI); if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX || GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 && tp->pci_chip_rev_id <= CHIPREV_ID_5714_A2 && tp->pdev_peer == tp->pdev)) - tp->tg3_flags &= ~TG3_FLAG_SUPPORT_MSI; + tg3_flag_clear(tp, SUPPORT_MSI); - if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) || + if (tg3_flag(tp, 5755_PLUS) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { - tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; + tg3_flag_set(tp, 1SHOT_MSI); } - if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) { - tp->tg3_flags |= TG3_FLAG_SUPPORT_MSIX; + if (tg3_flag(tp, 57765_PLUS)) { + tg3_flag_set(tp, SUPPORT_MSIX); tp->irq_max = TG3_IRQ_MAX_VECS; } } @@ -13811,23 +13802,23 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) - tp->tg3_flags3 |= TG3_FLG3_SHORT_DMA_BUG; - else if (!(tp->tg3_flags3 & TG3_FLG3_5755_PLUS)) { - tp->tg3_flags3 |= TG3_FLG3_4G_DMA_BNDRY_BUG; - tp->tg3_flags3 |= TG3_FLG3_40BIT_DMA_LIMIT_BUG; + tg3_flag_set(tp, SHORT_DMA_BUG); + else if (!tg3_flag(tp, 5755_PLUS)) { + tg3_flag_set(tp, 4G_DMA_BNDRY_BUG); + tg3_flag_set(tp, 40BIT_DMA_LIMIT_BUG); } - if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) - tp->tg3_flags3 |= TG3_FLG3_LRG_PROD_RING_CAP; + if (tg3_flag(tp, 5717_PLUS)) + tg3_flag_set(tp, LRG_PROD_RING_CAP); - if ((tp->tg3_flags3 & TG3_FLG3_57765_PLUS) && + if (tg3_flag(tp, 57765_PLUS) && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719) - tp->tg3_flags3 |= TG3_FLG3_USE_JUMBO_BDFLAG; + tg3_flag_set(tp, USE_JUMBO_BDFLAG); - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || - (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || - (tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG)) - tp->tg3_flags |= TG3_FLAG_JUMBO_CAPABLE; + if (!tg3_flag(tp, 5705_PLUS) || + tg3_flag(tp, 5780_CLASS) || + tg3_flag(tp, USE_JUMBO_BDFLAG)) + tg3_flag_set(tp, JUMBO_CAPABLE); pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &pci_state_reg); @@ -13836,7 +13827,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->pcie_cap != 0) { u16 lnkctl; - tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; + tg3_flag_set(tp, PCI_EXPRESS); tp->pcie_readrq = 4096; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || @@ -13850,19 +13841,19 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) &lnkctl); if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) - tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_2; + tg3_flag_clear(tp, HW_TSO_2); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || tp->pci_chip_rev_id == CHIPREV_ID_57780_A0 || tp->pci_chip_rev_id == CHIPREV_ID_57780_A1) - tp->tg3_flags3 |= TG3_FLG3_CLKREQ_BUG; + tg3_flag_set(tp, CLKREQ_BUG); } else if (tp->pci_chip_rev_id == CHIPREV_ID_5717_A0) { - tp->tg3_flags3 |= TG3_FLG3_L1PLLPD_EN; + tg3_flag_set(tp, L1PLLPD_EN); } } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) { - tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; - } else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || - (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { + tg3_flag_set(tp, PCI_EXPRESS); + } else if (!tg3_flag(tp, 5705_PLUS) || + tg3_flag(tp, 5780_CLASS)) { tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX); if (!tp->pcix_cap) { dev_err(&tp->pdev->dev, @@ -13871,7 +13862,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } if (!(pci_state_reg & PCISTATE_CONV_PCI_MODE)) - tp->tg3_flags |= TG3_FLAG_PCIX_MODE; + tg3_flag_set(tp, PCIX_MODE); } /* If we have an AMD 762 or VIA K8T800 chipset, write @@ -13881,8 +13872,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * posted to the chip in order. */ if (pci_dev_present(tg3_write_reorder_chipsets) && - !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) - tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER; + !tg3_flag(tp, PCI_EXPRESS)) + tg3_flag_set(tp, MBOX_WRITE_REORDER); pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &tp->pci_cacheline_sz); @@ -13899,17 +13890,17 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* 5700 BX chips need to have their TX producer index * mailboxes written twice to workaround a bug. */ - tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG; + tg3_flag_set(tp, TXD_MBOX_HWBUG); /* If we are in PCI-X mode, enable register write workaround. * * The workaround is to use indirect register accesses * for all chip writes not to mailbox registers. */ - if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) { + if (tg3_flag(tp, PCIX_MODE)) { u32 pm_reg; - tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG; + tg3_flag_set(tp, PCIX_TARGET_HWBUG); /* The chip can have it's power management PCI config * space registers clobbered due to this bug. @@ -13932,9 +13923,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0) - tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED; + tg3_flag_set(tp, PCI_HIGH_SPEED); if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0) - tp->tg3_flags |= TG3_FLAG_PCI_32BIT; + tg3_flag_set(tp, PCI_32BIT); /* Chip-specific fixup from Broadcom driver */ if ((tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) && @@ -13952,10 +13943,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->write32_rx_mbox = tg3_write32; /* Various workaround register access methods */ - if (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) + if (tg3_flag(tp, PCIX_TARGET_HWBUG)) tp->write32 = tg3_write_indirect_reg32; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 || - ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && + (tg3_flag(tp, PCI_EXPRESS) && tp->pci_chip_rev_id == CHIPREV_ID_5750_A0)) { /* * Back to back register writes can cause problems on these @@ -13967,14 +13958,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->write32 = tg3_write_flush_reg32; } - if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) || - (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) { + if (tg3_flag(tp, TXD_MBOX_HWBUG) || tg3_flag(tp, MBOX_WRITE_REORDER)) { tp->write32_tx_mbox = tg3_write32_tx_mbox; - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) + if (tg3_flag(tp, MBOX_WRITE_REORDER)) tp->write32_rx_mbox = tg3_write_flush_reg32; } - if (tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND) { + if (tg3_flag(tp, ICH_WORKAROUND)) { tp->read32 = tg3_read_indirect_reg32; tp->write32 = tg3_write_indirect_reg32; tp->read32_mbox = tg3_read_indirect_mbox; @@ -13997,13 +13987,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } if (tp->write32 == tg3_write_indirect_reg32 || - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) && + (tg3_flag(tp, PCIX_MODE) && (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701))) - tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG; + tg3_flag_set(tp, SRAM_USE_CONFIG); /* Get eeprom hw config before calling tg3_set_power_state(). - * In particular, the TG3_FLG2_IS_NIC flag must be + * In particular, the TG3_FLAG_IS_NIC flag must be * determined before calling tg3_set_power_state() so that * we know whether or not to switch out of Vaux power. * When the flag is set, it means that GPIO1 is used for eeprom @@ -14012,7 +14002,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) */ tg3_get_eeprom_hw_cfg(tp); - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { + if (tg3_flag(tp, ENABLE_APE)) { /* Allow reads and writes to the * APE register and memory space. */ @@ -14027,8 +14017,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || - (tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) - tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT; + tg3_flag(tp, 57765_PLUS)) + tg3_flag_set(tp, CPMU_PRESENT); /* Set up tp->grc_local_ctrl before calling tg3_power_up(). * GPIO1 driven high will bring 5700's external PHY out of reset. @@ -14036,7 +14026,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) */ tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM; if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) || - (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT)) + tg3_flag(tp, EEPROM_WRITE_PROT)) tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1); /* Unused GPIO3 must be driven as output on 5752 because there @@ -14054,7 +14044,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) { /* Turn off the debug UART. */ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; - if (tp->tg3_flags2 & TG3_FLG2_IS_NIC) + if (tg3_flag(tp, IS_NIC)) /* Keep VMain power. */ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OUTPUT0; @@ -14070,18 +14060,17 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Derive initial jumbo mode from MTU assigned in * ether_setup() via the alloc_etherdev() call */ - if (tp->dev->mtu > ETH_DATA_LEN && - !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) - tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE; + if (tp->dev->mtu > ETH_DATA_LEN && !tg3_flag(tp, 5780_CLASS)) + tg3_flag_set(tp, JUMBO_RING_ENABLE); /* Determine WakeOnLan speed to use. */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || tp->pci_chip_rev_id == CHIPREV_ID_5701_B0 || tp->pci_chip_rev_id == CHIPREV_ID_5701_B2) { - tp->tg3_flags &= ~(TG3_FLAG_WOL_SPEED_100MB); + tg3_flag_clear(tp, WOL_SPEED_100MB); } else { - tp->tg3_flags |= TG3_FLAG_WOL_SPEED_100MB; + tg3_flag_set(tp, WOL_SPEED_100MB); } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) @@ -14102,11 +14091,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) tp->phy_flags |= TG3_PHYFLG_5704_A0_BUG; - if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && + if (tg3_flag(tp, 5705_PLUS) && !(tp->phy_flags & TG3_PHYFLG_IS_FET) && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780 && - !(tp->tg3_flags3 & TG3_FLG3_57765_PLUS)) { + !tg3_flag(tp, 57765_PLUS)) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || @@ -14127,7 +14116,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->phy_otp = TG3_OTP_DEFAULT; } - if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) + if (tg3_flag(tp, CPMU_PRESENT)) tp->mi_mode = MAC_MI_MODE_500KHZ_CONST; else tp->mi_mode = MAC_MI_MODE_BASE; @@ -14147,7 +14136,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) - tp->tg3_flags3 |= TG3_FLG3_USE_PHYLIB; + tg3_flag_set(tp, USE_PHYLIB); err = tg3_mdio_init(tp); if (err) @@ -14174,7 +14163,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &pci_state_reg); if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 && - (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) == 0) { + !tg3_flag(tp, PCIX_TARGET_HWBUG)) { u32 chiprevid = GET_CHIP_REV_ID(tp->misc_host_ctrl); if (chiprevid == CHIPREV_ID_5701_A0 || @@ -14193,7 +14182,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) writel(0x00000000, sram_base + 4); writel(0xffffffff, sram_base + 4); if (readl(sram_base) != 0x00000000) - tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG; + tg3_flag_set(tp, PCIX_TARGET_HWBUG); } } @@ -14206,12 +14195,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 || grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M)) - tp->tg3_flags2 |= TG3_FLG2_IS_5788; + tg3_flag_set(tp, IS_5788); - if (!(tp->tg3_flags2 & TG3_FLG2_IS_5788) && + if (!tg3_flag(tp, IS_5788) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)) - tp->tg3_flags |= TG3_FLAG_TAGGED_STATUS; - if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) { + tg3_flag_set(tp, TAGGED_STATUS); + if (tg3_flag(tp, TAGGED_STATUS)) { tp->coalesce_mode |= (HOSTCC_MODE_CLRTICK_RXBD | HOSTCC_MODE_CLRTICK_TXBD); @@ -14221,7 +14210,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } /* Preserve the APE MAC_MODE bits */ - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + if (tg3_flag(tp, ENABLE_APE)) tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN; else tp->mac_mode = TG3_DEF_MAC_MODE; @@ -14268,9 +14257,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * status register in those cases. */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) - tp->tg3_flags |= TG3_FLAG_USE_LINKCHG_REG; + tg3_flag_set(tp, USE_LINKCHG_REG); else - tp->tg3_flags &= ~TG3_FLAG_USE_LINKCHG_REG; + tg3_flag_clear(tp, USE_LINKCHG_REG); /* The led_ctrl is set during tg3_phy_probe, here we might * have to force the link status polling mechanism based @@ -14280,19 +14269,19 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && !(tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) { tp->phy_flags |= TG3_PHYFLG_USE_MI_INTERRUPT; - tp->tg3_flags |= TG3_FLAG_USE_LINKCHG_REG; + tg3_flag_set(tp, USE_LINKCHG_REG); } /* For all SERDES we poll the MAC status register. */ if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) - tp->tg3_flags |= TG3_FLAG_POLL_SERDES; + tg3_flag_set(tp, POLL_SERDES); else - tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES; + tg3_flag_clear(tp, POLL_SERDES); tp->rx_offset = NET_IP_ALIGN; tp->rx_copy_thresh = TG3_RX_COPY_THRESHOLD; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && - (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) { + tg3_flag(tp, PCIX_MODE)) { tp->rx_offset = 0; #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS tp->rx_copy_thresh = ~(u16)0; @@ -14313,7 +14302,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) tp->rx_std_max_post = 8; - if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND) + if (tg3_flag(tp, ASPM_WORKAROUND)) tp->pwrmgmt_thresh = tr32(PCIE_PWR_MGMT_THRESH) & PCIE_PWR_MGMT_L1_THRESH_MSK; @@ -14361,14 +14350,14 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) mac_offset = 0x7c; if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || - (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { + tg3_flag(tp, 5780_CLASS)) { if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID) mac_offset = 0xcc; if (tg3_nvram_lock(tp)) tw32_f(NVRAM_CMD, NVRAM_CMD_RESET); else tg3_nvram_unlock(tp); - } else if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) { + } else if (tg3_flag(tp, 5717_PLUS)) { if (PCI_FUNC(tp->pdev->devfn) & 1) mac_offset = 0xcc; if (PCI_FUNC(tp->pdev->devfn) > 1) @@ -14393,7 +14382,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) } if (!addr_ok) { /* Next, try NVRAM. */ - if (!(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) && + if (!tg3_flag(tp, NO_NVRAM) && !tg3_nvram_read_be32(tp, mac_offset + 0, &hi) && !tg3_nvram_read_be32(tp, mac_offset + 4, &lo)) { memcpy(&dev->dev_addr[0], ((char *)&hi) + 2, 2); @@ -14444,7 +14433,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) */ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 && - !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) + !tg3_flag(tp, PCI_EXPRESS)) goto out; #if defined(CONFIG_PPC64) || defined(CONFIG_IA64) || defined(CONFIG_PARISC) @@ -14457,7 +14446,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) #endif #endif - if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) { + if (tg3_flag(tp, 57765_PLUS)) { val = goal ? 0 : DMA_RWCTRL_DIS_CACHE_ALIGNMENT; goto out; } @@ -14476,8 +14465,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) * other than 5700 and 5701 which do not implement the * boundary bits. */ - if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) && - !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) { + if (tg3_flag(tp, PCIX_MODE) && !tg3_flag(tp, PCI_EXPRESS)) { switch (cacheline_size) { case 16: case 32: @@ -14502,7 +14490,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) DMA_RWCTRL_WRITE_BNDRY_384_PCIX); break; } - } else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { + } else if (tg3_flag(tp, PCI_EXPRESS)) { switch (cacheline_size) { case 16: case 32: @@ -14674,13 +14662,13 @@ static int __devinit tg3_test_dma(struct tg3 *tp) tp->dma_rwctrl = tg3_calc_dma_bndry(tp, tp->dma_rwctrl); - if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) + if (tg3_flag(tp, 57765_PLUS)) goto out; - if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { + if (tg3_flag(tp, PCI_EXPRESS)) { /* DMA read watermark not used on PCIE */ tp->dma_rwctrl |= 0x00180000; - } else if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE)) { + } else if (!tg3_flag(tp, PCIX_MODE)) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) tp->dma_rwctrl |= 0x003f0000; @@ -14696,7 +14684,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp) * do the less restrictive ONE_DMA workaround for * better performance. */ - if ((tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) && + if (tg3_flag(tp, 40BIT_DMA_BUG) && GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) tp->dma_rwctrl |= 0x8000; else if (ccval == 0x6 || ccval == 0x7) @@ -14848,7 +14836,7 @@ out_nofree: static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) { - if (tp->tg3_flags3 & TG3_FLG3_57765_PLUS) { + if (tg3_flag(tp, 57765_PLUS)) { tp->bufmgr_config.mbuf_read_dma_low_water = DEFAULT_MB_RDMA_LOW_WATER_5705; tp->bufmgr_config.mbuf_mac_rx_low_water = @@ -14862,7 +14850,7 @@ static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) DEFAULT_MB_MACRX_LOW_WATER_JUMBO_57765; tp->bufmgr_config.mbuf_high_water_jumbo = DEFAULT_MB_HIGH_WATER_JUMBO_57765; - } else if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + } else if (tg3_flag(tp, 5705_PLUS)) { tp->bufmgr_config.mbuf_read_dma_low_water = DEFAULT_MB_RDMA_LOW_WATER_5705; tp->bufmgr_config.mbuf_mac_rx_low_water = @@ -14935,10 +14923,10 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) static char * __devinit tg3_bus_string(struct tg3 *tp, char *str) { - if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { + if (tg3_flag(tp, PCI_EXPRESS)) { strcpy(str, "PCI Express"); return str; - } else if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) { + } else if (tg3_flag(tp, PCIX_MODE)) { u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL) & 0x1f; strcpy(str, "PCIX:"); @@ -14957,12 +14945,12 @@ static char * __devinit tg3_bus_string(struct tg3 *tp, char *str) strcat(str, "100MHz"); } else { strcpy(str, "PCI:"); - if (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) + if (tg3_flag(tp, PCI_HIGH_SPEED)) strcat(str, "66MHz"); else strcat(str, "33MHz"); } - if (tp->tg3_flags & TG3_FLAG_PCI_32BIT) + if (tg3_flag(tp, PCI_32BIT)) strcat(str, ":32-bit"); else strcat(str, ":64-bit"); @@ -15021,7 +15009,7 @@ static void __devinit tg3_init_coal(struct tg3 *tp) ec->tx_coalesce_usecs_irq = DEFAULT_TXCOAL_TICK_INT_CLRTCKS; } - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + if (tg3_flag(tp, 5705_PLUS)) { ec->rx_coalesce_usecs_irq = 0; ec->tx_coalesce_usecs_irq = 0; ec->stats_block_coalesce_usecs = 0; @@ -15166,8 +15154,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_iounmap; } - if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) && - !(tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) + if (tg3_flag(tp, 5755_PLUS) && !tg3_flag(tp, 5717_PLUS)) dev->netdev_ops = &tg3_netdev_ops; else dev->netdev_ops = &tg3_netdev_ops_dma_bug; @@ -15179,9 +15166,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * On 64-bit systems without IOMMU, use 64-bit dma_mask and * do DMA address check in tg3_start_xmit(). */ - if (tp->tg3_flags2 & TG3_FLG2_IS_5788) + if (tg3_flag(tp, IS_5788)) persist_dma_mask = dma_mask = DMA_BIT_MASK(32); - else if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) { + else if (tg3_flag(tp, 40BIT_DMA_BUG)) { persist_dma_mask = dma_mask = DMA_BIT_MASK(40); #ifdef CONFIG_HIGHMEM dma_mask = DMA_BIT_MASK(64); @@ -15215,11 +15202,14 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_bufmgr_config(tp); /* Selectively allow TSO based on operating conditions */ - if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) || - (tp->fw_needed && !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) - tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; + if ((tg3_flag(tp, HW_TSO_1) || + tg3_flag(tp, HW_TSO_2) || + tg3_flag(tp, HW_TSO_3)) || + (tp->fw_needed && !tg3_flag(tp, ENABLE_ASF))) + tg3_flag_set(tp, TSO_CAPABLE); else { - tp->tg3_flags2 &= ~(TG3_FLG2_TSO_CAPABLE | TG3_FLG2_TSO_BUG); + tg3_flag_clear(tp, TSO_CAPABLE); + tg3_flag_clear(tp, TSO_BUG); tp->fw_needed = NULL; } @@ -15230,18 +15220,19 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * Firmware TSO on older chips gives lower performance, so it * is off by default, but can be enabled using ethtool. */ - if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) && + if ((tg3_flag(tp, HW_TSO_1) || + tg3_flag(tp, HW_TSO_2) || + tg3_flag(tp, HW_TSO_3)) && (dev->features & NETIF_F_IP_CSUM)) hw_features |= NETIF_F_TSO; - if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) || - (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3)) { + if (tg3_flag(tp, HW_TSO_2) || tg3_flag(tp, HW_TSO_3)) { if (dev->features & NETIF_F_IPV6_CSUM) hw_features |= NETIF_F_TSO6; - if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) || + if (tg3_flag(tp, HW_TSO_3) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) hw_features |= NETIF_F_TSO_ECN; } @@ -15251,9 +15242,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, dev->vlan_features |= hw_features; if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 && - !(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) && + !tg3_flag(tp, TSO_CAPABLE) && !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) { - tp->tg3_flags2 |= TG3_FLG2_MAX_RXPEND_64; + tg3_flag_set(tp, MAX_RXPEND_64); tp->rx_pending = 63; } @@ -15264,7 +15255,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_iounmap; } - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { + if (tg3_flag(tp, ENABLE_APE)) { tp->aperegs = pci_ioremap_bar(pdev, BAR_2); if (!tp->aperegs) { dev_err(&pdev->dev, @@ -15275,7 +15266,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_ape_lock_init(tp); - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) + if (tg3_flag(tp, ENABLE_ASF)) tg3_read_dash_ver(tp); } @@ -15319,7 +15310,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, else tnapi->coal_now = HOSTCC_MODE_NOW; - if (!(tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX)) + if (!tg3_flag(tp, SUPPORT_MSIX)) break; /* @@ -15381,10 +15372,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, netdev_info(dev, "RXcsums[%d] LinkChgREG[%d] MIirq[%d] ASF[%d] TSOcap[%d]\n", (dev->features & NETIF_F_RXCSUM) != 0, - (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0, + tg3_flag(tp, USE_LINKCHG_REG) != 0, (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT) != 0, - (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0, - (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0); + tg3_flag(tp, ENABLE_ASF) != 0, + tg3_flag(tp, TSO_CAPABLE) != 0); netdev_info(dev, "dma_rwctrl[%08x] dma_mask[%d-bit]\n", tp->dma_rwctrl, pdev->dma_mask == DMA_BIT_MASK(32) ? 32 : @@ -15430,7 +15421,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) cancel_work_sync(&tp->reset_task); - if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if (!tg3_flag(tp, USE_PHYLIB)) { tg3_phy_fini(tp); tg3_mdio_fini(tp); } @@ -15476,7 +15467,7 @@ static int tg3_suspend(struct device *device) tg3_full_lock(tp, 0); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; + tg3_flag_clear(tp, INIT_COMPLETE); tg3_full_unlock(tp); err = tg3_power_down_prepare(tp); @@ -15485,7 +15476,7 @@ static int tg3_suspend(struct device *device) tg3_full_lock(tp, 0); - tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; + tg3_flag_set(tp, INIT_COMPLETE); err2 = tg3_restart_hw(tp, 1); if (err2) goto out; @@ -15520,7 +15511,7 @@ static int tg3_resume(struct device *device) tg3_full_lock(tp, 0); - tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; + tg3_flag_set(tp, INIT_COMPLETE); err = tg3_restart_hw(tp, 1); if (err) goto out; @@ -15575,12 +15566,12 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, tg3_netif_stop(tp); del_timer_sync(&tp->timer); - tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; + tg3_flag_clear(tp, RESTART_TIMER); /* Want to make sure that the reset task doesn't run */ cancel_work_sync(&tp->reset_task); - tp->tg3_flags &= ~TG3_FLAG_TX_RECOVERY_PENDING; - tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; + tg3_flag_clear(tp, TX_RECOVERY_PENDING); + tg3_flag_clear(tp, RESTART_TIMER); netif_device_detach(netdev); @@ -15665,7 +15656,7 @@ static void tg3_io_resume(struct pci_dev *pdev) goto done; tg3_full_lock(tp, 0); - tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; + tg3_flag_set(tp, INIT_COMPLETE); err = tg3_restart_hw(tp, 1); tg3_full_unlock(tp); if (err) { diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 6f37d2a23544..ce010cd33895 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2816,6 +2816,86 @@ struct tg3_napi { unsigned int irq_vec; }; +enum TG3_FLAGS { + TG3_FLAG_TAGGED_STATUS = 0, + TG3_FLAG_TXD_MBOX_HWBUG, + TG3_FLAG_USE_LINKCHG_REG, + TG3_FLAG_ERROR_PROCESSED, + TG3_FLAG_ENABLE_ASF, + TG3_FLAG_ASPM_WORKAROUND, + TG3_FLAG_POLL_SERDES, + TG3_FLAG_MBOX_WRITE_REORDER, + TG3_FLAG_PCIX_TARGET_HWBUG, + TG3_FLAG_WOL_SPEED_100MB, + TG3_FLAG_WOL_ENABLE, + TG3_FLAG_EEPROM_WRITE_PROT, + TG3_FLAG_NVRAM, + TG3_FLAG_NVRAM_BUFFERED, + TG3_FLAG_SUPPORT_MSI, + TG3_FLAG_SUPPORT_MSIX, + TG3_FLAG_PCIX_MODE, + TG3_FLAG_PCI_HIGH_SPEED, + TG3_FLAG_PCI_32BIT, + TG3_FLAG_SRAM_USE_CONFIG, + TG3_FLAG_TX_RECOVERY_PENDING, + TG3_FLAG_WOL_CAP, + TG3_FLAG_JUMBO_RING_ENABLE, + TG3_FLAG_PAUSE_AUTONEG, + TG3_FLAG_CPMU_PRESENT, + TG3_FLAG_40BIT_DMA_BUG, + TG3_FLAG_BROKEN_CHECKSUMS, + TG3_FLAG_JUMBO_CAPABLE, + TG3_FLAG_CHIP_RESETTING, + TG3_FLAG_INIT_COMPLETE, + TG3_FLAG_RESTART_TIMER, + TG3_FLAG_TSO_BUG, + TG3_FLAG_IS_5788, + TG3_FLAG_MAX_RXPEND_64, + TG3_FLAG_TSO_CAPABLE, + TG3_FLAG_PCI_EXPRESS, + TG3_FLAG_ASF_NEW_HANDSHAKE, + TG3_FLAG_HW_AUTONEG, + TG3_FLAG_IS_NIC, + TG3_FLAG_FLASH, + TG3_FLAG_HW_TSO_1, + TG3_FLAG_5705_PLUS, + TG3_FLAG_5750_PLUS, + TG3_FLAG_HW_TSO_3, + TG3_FLAG_USING_MSI, + TG3_FLAG_USING_MSIX, + TG3_FLAG_ICH_WORKAROUND, + TG3_FLAG_5780_CLASS, + TG3_FLAG_HW_TSO_2, + TG3_FLAG_1SHOT_MSI, + TG3_FLAG_NO_FWARE_REPORTED, + TG3_FLAG_NO_NVRAM_ADDR_TRANS, + TG3_FLAG_ENABLE_APE, + TG3_FLAG_PROTECTED_NVRAM, + TG3_FLAG_5701_DMA_BUG, + TG3_FLAG_USE_PHYLIB, + TG3_FLAG_MDIOBUS_INITED, + TG3_FLAG_LRG_PROD_RING_CAP, + TG3_FLAG_RGMII_INBAND_DISABLE, + TG3_FLAG_RGMII_EXT_IBND_RX_EN, + TG3_FLAG_RGMII_EXT_IBND_TX_EN, + TG3_FLAG_CLKREQ_BUG, + TG3_FLAG_5755_PLUS, + TG3_FLAG_NO_NVRAM, + TG3_FLAG_ENABLE_RSS, + TG3_FLAG_ENABLE_TSS, + TG3_FLAG_4G_DMA_BNDRY_BUG, + TG3_FLAG_40BIT_DMA_LIMIT_BUG, + TG3_FLAG_SHORT_DMA_BUG, + TG3_FLAG_USE_JUMBO_BDFLAG, + TG3_FLAG_L1PLLPD_EN, + TG3_FLAG_57765_PLUS, + TG3_FLAG_APE_HAS_NCSI, + TG3_FLAG_5717_PLUS, + + /* Add new flags before this comment and TG3_FLAG_NUMBER_OF_FLAGS */ + TG3_FLAG_NUMBER_OF_FLAGS, /* Last entry in enum TG3_FLAGS */ +}; + struct tg3 { /* begin "general, frequently-used members" cacheline section */ @@ -2839,7 +2919,7 @@ struct tg3 { /* SMP locking strategy: * * lock: Held during reset, PHY access, timer, and when - * updating tg3_flags and tg3_flags2. + * updating tg3_flags. * * netif_tx_lock: Held during tg3_start_xmit. tg3_tx holds * netif_tx_lock when it needs to call @@ -2896,95 +2976,13 @@ struct tg3 { struct tg3_ethtool_stats estats; struct tg3_ethtool_stats estats_prev; + DECLARE_BITMAP(tg3_flags, TG3_FLAG_NUMBER_OF_FLAGS); + union { unsigned long phy_crc_errors; unsigned long last_event_jiffies; }; - u32 tg3_flags; -#define TG3_FLAG_TAGGED_STATUS 0x00000001 -#define TG3_FLAG_TXD_MBOX_HWBUG 0x00000002 -#define TG3_FLAG_USE_LINKCHG_REG 0x00000008 -#define TG3_FLAG_ERROR_PROCESSED 0x00000010 -#define TG3_FLAG_ENABLE_ASF 0x00000020 -#define TG3_FLAG_ASPM_WORKAROUND 0x00000040 -#define TG3_FLAG_POLL_SERDES 0x00000080 -#define TG3_FLAG_MBOX_WRITE_REORDER 0x00000100 -#define TG3_FLAG_PCIX_TARGET_HWBUG 0x00000200 -#define TG3_FLAG_WOL_SPEED_100MB 0x00000400 -#define TG3_FLAG_WOL_ENABLE 0x00000800 -#define TG3_FLAG_EEPROM_WRITE_PROT 0x00001000 -#define TG3_FLAG_NVRAM 0x00002000 -#define TG3_FLAG_NVRAM_BUFFERED 0x00004000 -#define TG3_FLAG_SUPPORT_MSI 0x00008000 -#define TG3_FLAG_SUPPORT_MSIX 0x00010000 -#define TG3_FLAG_SUPPORT_MSI_OR_MSIX (TG3_FLAG_SUPPORT_MSI | \ - TG3_FLAG_SUPPORT_MSIX) -#define TG3_FLAG_PCIX_MODE 0x00020000 -#define TG3_FLAG_PCI_HIGH_SPEED 0x00040000 -#define TG3_FLAG_PCI_32BIT 0x00080000 -#define TG3_FLAG_SRAM_USE_CONFIG 0x00100000 -#define TG3_FLAG_TX_RECOVERY_PENDING 0x00200000 -#define TG3_FLAG_WOL_CAP 0x00400000 -#define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 -#define TG3_FLAG_PAUSE_AUTONEG 0x02000000 -#define TG3_FLAG_CPMU_PRESENT 0x04000000 -#define TG3_FLAG_40BIT_DMA_BUG 0x08000000 -#define TG3_FLAG_JUMBO_CAPABLE 0x20000000 -#define TG3_FLAG_CHIP_RESETTING 0x40000000 -#define TG3_FLAG_INIT_COMPLETE 0x80000000 - u32 tg3_flags2; -#define TG3_FLG2_RESTART_TIMER 0x00000001 -#define TG3_FLG2_TSO_BUG 0x00000002 -#define TG3_FLG2_IS_5788 0x00000008 -#define TG3_FLG2_MAX_RXPEND_64 0x00000010 -#define TG3_FLG2_TSO_CAPABLE 0x00000020 -#define TG3_FLG2_PCI_EXPRESS 0x00000200 -#define TG3_FLG2_ASF_NEW_HANDSHAKE 0x00000400 -#define TG3_FLG2_HW_AUTONEG 0x00000800 -#define TG3_FLG2_IS_NIC 0x00001000 -#define TG3_FLG2_FLASH 0x00008000 -#define TG3_FLG2_HW_TSO_1 0x00010000 -#define TG3_FLG2_5705_PLUS 0x00040000 -#define TG3_FLG2_5750_PLUS 0x00080000 -#define TG3_FLG2_HW_TSO_3 0x00100000 -#define TG3_FLG2_USING_MSI 0x00200000 -#define TG3_FLG2_USING_MSIX 0x00400000 -#define TG3_FLG2_USING_MSI_OR_MSIX (TG3_FLG2_USING_MSI | \ - TG3_FLG2_USING_MSIX) -#define TG3_FLG2_ICH_WORKAROUND 0x02000000 -#define TG3_FLG2_5780_CLASS 0x04000000 -#define TG3_FLG2_HW_TSO_2 0x08000000 -#define TG3_FLG2_HW_TSO (TG3_FLG2_HW_TSO_1 | \ - TG3_FLG2_HW_TSO_2 | \ - TG3_FLG2_HW_TSO_3) -#define TG3_FLG2_1SHOT_MSI 0x10000000 -#define TG3_FLG2_NO_FWARE_REPORTED 0x40000000 - u32 tg3_flags3; -#define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001 -#define TG3_FLG3_ENABLE_APE 0x00000002 -#define TG3_FLG3_PROTECTED_NVRAM 0x00000004 -#define TG3_FLG3_5701_DMA_BUG 0x00000008 -#define TG3_FLG3_USE_PHYLIB 0x00000010 -#define TG3_FLG3_MDIOBUS_INITED 0x00000020 -#define TG3_FLG3_LRG_PROD_RING_CAP 0x00000080 -#define TG3_FLG3_RGMII_INBAND_DISABLE 0x00000100 -#define TG3_FLG3_RGMII_EXT_IBND_RX_EN 0x00000200 -#define TG3_FLG3_RGMII_EXT_IBND_TX_EN 0x00000400 -#define TG3_FLG3_CLKREQ_BUG 0x00000800 -#define TG3_FLG3_5755_PLUS 0x00002000 -#define TG3_FLG3_NO_NVRAM 0x00004000 -#define TG3_FLG3_ENABLE_RSS 0x00020000 -#define TG3_FLG3_ENABLE_TSS 0x00040000 -#define TG3_FLG3_4G_DMA_BNDRY_BUG 0x00080000 -#define TG3_FLG3_40BIT_DMA_LIMIT_BUG 0x00100000 -#define TG3_FLG3_SHORT_DMA_BUG 0x00200000 -#define TG3_FLG3_USE_JUMBO_BDFLAG 0x00400000 -#define TG3_FLG3_L1PLLPD_EN 0x00800000 -#define TG3_FLG3_57765_PLUS 0x01000000 -#define TG3_FLG3_APE_HAS_NCSI 0x02000000 -#define TG3_FLG3_5717_PLUS 0x04000000 - struct timer_list timer; u16 timer_counter; u16 timer_multiplier; -- cgit v1.2.3-58-ga151 From 89b4208e2861bc7dc325840b44bae302a4e30add Mon Sep 17 00:00:00 2001 From: Sucheta Chakraborty Date: Wed, 27 Apr 2011 14:43:44 +0000 Subject: qlcnic: fix memory leak in qlcnic_blink_led. o Memory allocated in ETHTOOL_ACTIVE mode, is not getting freed. So, in ETHTOOL_ID_INACTIVE mode, return after freeing allocated memory. o Using set bit instead of blink_down field, as it is also required in internal Loopback test and etc. Signed-off-by: Sucheta Chakraborty Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 2 +- drivers/net/qlcnic/qlcnic_ethtool.c | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index fa5b15c474b0..f7acb807a03d 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -884,6 +884,7 @@ struct qlcnic_ipaddr { #define __QLCNIC_RESETTING 2 #define __QLCNIC_START_FW 4 #define __QLCNIC_AER 5 +#define __QLCNIC_DIAG_RES_ALLOC 6 #define QLCNIC_INTERRUPT_TEST 1 #define QLCNIC_LOOPBACK_TEST 2 @@ -913,7 +914,6 @@ struct qlcnic_adapter { struct net_device *netdev; struct pci_dev *pdev; - bool blink_was_down; unsigned long state; u32 flags; diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 615a5ab88456..de65847f3559 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -772,7 +772,6 @@ static int qlcnic_set_led(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: - adapter->blink_was_down = false; if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) return -EIO; @@ -781,7 +780,7 @@ static int qlcnic_set_led(struct net_device *dev, clear_bit(__QLCNIC_RESETTING, &adapter->state); return -EIO; } - adapter->blink_was_down = true; + set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state); } if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) @@ -792,18 +791,17 @@ static int qlcnic_set_led(struct net_device *dev, break; case ETHTOOL_ID_INACTIVE: - if (adapter->nic_ops->config_led(adapter, 0, 0xf) == 0) - return 0; + if (adapter->nic_ops->config_led(adapter, 0, 0xf)) + dev_err(&adapter->pdev->dev, + "Failed to reset LED blink state.\n"); - dev_err(&adapter->pdev->dev, - "Failed to reset LED blink state.\n"); break; default: return -EINVAL; } - if (adapter->blink_was_down) { + if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) { qlcnic_diag_free_res(dev, max_sds_rings); clear_bit(__QLCNIC_RESETTING, &adapter->state); } -- cgit v1.2.3-58-ga151 From b801a4e7092bb869fb5a7d8ee11a9435c5c7b2b1 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 28 Apr 2011 11:59:15 +1000 Subject: net: ibmveth: force reconfiguring checksum settings on startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b9367bf3ee6d ("net: ibmveth: convert to hw_features") accidentally removed call to ibmveth_set_csum_offload() in ibmveth_probe(). Put the call back where it was, but with additional error checking provided by ibmveth_set_features(). Signed-off-by: Michał Mirosław Reported-by: Stephen Rothwell [sfr: dev -> netdev] Signed-off-by: Stephen Rothwell Signed-off-by: David S. Miller --- drivers/net/ibmveth.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 4855f1fdff52..be3fe71b9c90 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1397,6 +1397,8 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, netdev_dbg(netdev, "registering netdev...\n"); + ibmveth_set_features(netdev, netdev->features); + rc = register_netdev(netdev); if (rc) { -- cgit v1.2.3-58-ga151 From 778865a550e7958c1211242cc481f48d46de0f04 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 13:54:06 -0700 Subject: l2tp: Fix inet_opt conversion. We don't actually hold the socket lock at this point, so the rcu_dereference_protected() isn't' correct. Thanks to Eric Dumazet for pointing this out. Thankfully, we're only interested in fetching the faddr value if srr is enabled, so we can simply make this an RCU sequence and use plain rcu_dereference(). Reported-by: Eric Dumazet Signed-off-by: David S. Miller --- net/l2tp/l2tp_ip.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 962a607b51da..e13c166824e0 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -472,13 +472,15 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m if (rt == NULL) { struct ip_options_rcu *inet_opt; - inet_opt = rcu_dereference_protected(inet->inet_opt, - sock_owned_by_user(sk)); + rcu_read_lock(); + inet_opt = rcu_dereference(inet->inet_opt); /* Use correct destination address if we have options. */ if (inet_opt && inet_opt->opt.srr) daddr = inet_opt->opt.faddr; + rcu_read_unlock(); + /* If this fails, retransmit mechanism of transport layer will * keep trying until route appears or the connection times * itself out. -- cgit v1.2.3-58-ga151 From 5c1e6aa300a7a669dc469d2dcb20172c6bd8fed9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 14:13:38 -0700 Subject: net: Make dst_alloc() take more explicit initializations. Now the dst->dev, dev->obsolete, and dst->flags values can be specified as well. Signed-off-by: David S. Miller --- include/net/dst.h | 3 ++- net/core/dst.c | 18 +++++++++++++----- net/decnet/dn_route.c | 13 ++----------- net/ipv4/route.c | 40 +++++++++++++++------------------------- net/ipv6/route.c | 29 +++++++++++------------------ net/xfrm/xfrm_policy.c | 2 +- 6 files changed, 44 insertions(+), 61 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index d7bb74062df1..2588a9a88cc6 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -350,7 +350,8 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) } extern int dst_discard(struct sk_buff *skb); -extern void *dst_alloc(struct dst_ops * ops, int initial_ref); +extern void *dst_alloc(struct dst_ops * ops, struct net_device *dev, + int initial_ref, int initial_obsolete, int flags); extern void __dst_free(struct dst_entry * dst); extern struct dst_entry *dst_destroy(struct dst_entry * dst); diff --git a/net/core/dst.c b/net/core/dst.c index 91104d35de7d..9505778ec800 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -166,7 +166,8 @@ EXPORT_SYMBOL(dst_discard); const u32 dst_default_metrics[RTAX_MAX]; -void *dst_alloc(struct dst_ops *ops, int initial_ref) +void *dst_alloc(struct dst_ops *ops, struct net_device *dev, + int initial_ref, int initial_obsolete, int flags) { struct dst_entry *dst; @@ -177,12 +178,19 @@ void *dst_alloc(struct dst_ops *ops, int initial_ref) dst = kmem_cache_zalloc(ops->kmem_cachep, GFP_ATOMIC); if (!dst) return NULL; - atomic_set(&dst->__refcnt, initial_ref); dst->ops = ops; - dst->lastuse = jiffies; - dst->path = dst; - dst->input = dst->output = dst_discard; + dst->dev = dev; + if (dev) + dev_hold(dev); dst_init_metrics(dst, dst_default_metrics, true); + dst->path = dst; + dst->input = dst_discard; + dst->output = dst_discard; + + dst->obsolete = initial_obsolete; + atomic_set(&dst->__refcnt, initial_ref); + dst->lastuse = jiffies; + dst->flags = flags; #if RT_CACHE_DEBUG >= 2 atomic_inc(&dst_total); #endif diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 9f09d4fc2880..f489b081c25d 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -1125,13 +1125,10 @@ make_route: if (dev_out->flags & IFF_LOOPBACK) flags |= RTCF_LOCAL; - rt = dst_alloc(&dn_dst_ops, 0); + rt = dst_alloc(&dn_dst_ops, dev_out, 1, 0, DST_HOST); if (rt == NULL) goto e_nobufs; - atomic_set(&rt->dst.__refcnt, 1); - rt->dst.flags = DST_HOST; - rt->fld.saddr = oldflp->saddr; rt->fld.daddr = oldflp->daddr; rt->fld.flowidn_oif = oldflp->flowidn_oif; @@ -1146,8 +1143,6 @@ make_route: rt->rt_dst_map = fld.daddr; rt->rt_src_map = fld.saddr; - rt->dst.dev = dev_out; - dev_hold(dev_out); rt->dst.neighbour = neigh; neigh = NULL; @@ -1399,7 +1394,7 @@ static int dn_route_input_slow(struct sk_buff *skb) } make_route: - rt = dst_alloc(&dn_dst_ops, 0); + rt = dst_alloc(&dn_dst_ops, out_dev, 0, 0, DST_HOST); if (rt == NULL) goto e_nobufs; @@ -1419,9 +1414,7 @@ make_route: rt->fld.flowidn_iif = in_dev->ifindex; rt->fld.flowidn_mark = fld.flowidn_mark; - rt->dst.flags = DST_HOST; rt->dst.neighbour = neigh; - rt->dst.dev = out_dev; rt->dst.lastuse = jiffies; rt->dst.output = dn_rt_bug; switch(res.type) { @@ -1440,8 +1433,6 @@ make_route: rt->dst.input = dst_discard; } rt->rt_flags = flags; - if (rt->dst.dev) - dev_hold(rt->dst.dev); err = dn_rt_set_next_hop(rt, &res); if (err) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d63f780c6941..b471d89b57ee 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1833,17 +1833,13 @@ static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *oldflp4, rt->rt_type = type; } -static struct rtable *rt_dst_alloc(bool nopolicy, bool noxfrm) +static struct rtable *rt_dst_alloc(struct net_device *dev, + bool nopolicy, bool noxfrm) { - struct rtable *rt = dst_alloc(&ipv4_dst_ops, 1); - if (rt) { - rt->dst.obsolete = -1; - - rt->dst.flags = DST_HOST | - (nopolicy ? DST_NOPOLICY : 0) | - (noxfrm ? DST_NOXFRM : 0); - } - return rt; + return dst_alloc(&ipv4_dst_ops, dev, 1, -1, + DST_HOST | + (nopolicy ? DST_NOPOLICY : 0) | + (noxfrm ? DST_NOXFRM : 0)); } /* called in rcu_read_lock() section */ @@ -1876,7 +1872,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, if (err < 0) goto e_err; } - rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), false); + rth = rt_dst_alloc(init_net.loopback_dev, + IN_DEV_CONF_GET(in_dev, NOPOLICY), false); if (!rth) goto e_nobufs; @@ -1893,8 +1890,6 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, #endif rth->rt_route_iif = dev->ifindex; rth->rt_iif = dev->ifindex; - rth->dst.dev = init_net.loopback_dev; - dev_hold(rth->dst.dev); rth->rt_oif = 0; rth->rt_gateway = daddr; rth->rt_spec_dst= spec_dst; @@ -2013,7 +2008,8 @@ static int __mkroute_input(struct sk_buff *skb, } } - rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), + rth = rt_dst_alloc(out_dev->dev, + IN_DEV_CONF_GET(in_dev, NOPOLICY), IN_DEV_CONF_GET(out_dev, NOXFRM)); if (!rth) { err = -ENOBUFS; @@ -2029,8 +2025,6 @@ static int __mkroute_input(struct sk_buff *skb, rth->rt_gateway = daddr; rth->rt_route_iif = in_dev->dev->ifindex; rth->rt_iif = in_dev->dev->ifindex; - rth->dst.dev = (out_dev)->dev; - dev_hold(rth->dst.dev); rth->rt_oif = 0; rth->rt_spec_dst= spec_dst; @@ -2188,7 +2182,8 @@ brd_input: RT_CACHE_STAT_INC(in_brd); local_input: - rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), false); + rth = rt_dst_alloc(net->loopback_dev, + IN_DEV_CONF_GET(in_dev, NOPOLICY), false); if (!rth) goto e_nobufs; @@ -2206,8 +2201,6 @@ local_input: #endif rth->rt_route_iif = dev->ifindex; rth->rt_iif = dev->ifindex; - rth->dst.dev = net->loopback_dev; - dev_hold(rth->dst.dev); rth->rt_gateway = daddr; rth->rt_spec_dst= spec_dst; rth->dst.input= ip_local_deliver; @@ -2392,7 +2385,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, fi = NULL; } - rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), + rth = rt_dst_alloc(dev_out, + IN_DEV_CONF_GET(in_dev, NOPOLICY), IN_DEV_CONF_GET(in_dev, NOXFRM)); if (!rth) return ERR_PTR(-ENOBUFS); @@ -2406,10 +2400,6 @@ static struct rtable *__mkroute_output(const struct fib_result *res, rth->rt_src = fl4->saddr; rth->rt_route_iif = 0; rth->rt_iif = oldflp4->flowi4_oif ? : dev_out->ifindex; - /* get references to the devices that are to be hold by the routing - cache entry */ - rth->dst.dev = dev_out; - dev_hold(dev_out); rth->rt_gateway = fl4->daddr; rth->rt_spec_dst= fl4->saddr; @@ -2711,7 +2701,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = { struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig) { - struct rtable *rt = dst_alloc(&ipv4_dst_blackhole_ops, 1); + struct rtable *rt = dst_alloc(&ipv4_dst_blackhole_ops, NULL, 1, 0, 0); struct rtable *ort = (struct rtable *) dst_orig; if (rt) { diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 19a77d0e0308..e8b2bb9060ef 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -227,9 +227,10 @@ static struct rt6_info ip6_blk_hole_entry_template = { #endif /* allocate dst with ip6_dst_ops */ -static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops) +static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, + struct net_device *dev) { - return (struct rt6_info *)dst_alloc(ops, 0); + return (struct rt6_info *)dst_alloc(ops, dev, 0, 0, 0); } static void ip6_dst_destroy(struct dst_entry *dst) @@ -881,10 +882,10 @@ EXPORT_SYMBOL(ip6_route_output); struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig) { - struct rt6_info *rt = dst_alloc(&ip6_dst_blackhole_ops, 1); - struct rt6_info *ort = (struct rt6_info *) dst_orig; + struct rt6_info *rt, *ort = (struct rt6_info *) dst_orig; struct dst_entry *new = NULL; + rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, 0, 0); if (rt) { new = &rt->dst; @@ -893,9 +894,6 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori new->output = dst_discard; dst_copy_metrics(new, &ort->dst); - new->dev = ort->dst.dev; - if (new->dev) - dev_hold(new->dev); rt->rt6i_idev = ort->rt6i_idev; if (rt->rt6i_idev) in6_dev_hold(rt->rt6i_idev); @@ -1038,13 +1036,12 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, if (unlikely(idev == NULL)) return NULL; - rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); + rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev); if (unlikely(rt == NULL)) { in6_dev_put(idev); goto out; } - dev_hold(dev); if (neigh) neigh_hold(neigh); else { @@ -1053,7 +1050,6 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, neigh = NULL; } - rt->rt6i_dev = dev; rt->rt6i_idev = idev; rt->rt6i_nexthop = neigh; atomic_set(&rt->dst.__refcnt, 1); @@ -1212,7 +1208,7 @@ int ip6_route_add(struct fib6_config *cfg) goto out; } - rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); + rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL); if (rt == NULL) { err = -ENOMEM; @@ -1731,7 +1727,8 @@ void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *sad static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) { struct net *net = dev_net(ort->rt6i_dev); - struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); + struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, + ort->dst.dev); if (rt) { rt->dst.input = ort->dst.input; @@ -1739,9 +1736,6 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) dst_copy_metrics(&rt->dst, &ort->dst); rt->dst.error = ort->dst.error; - rt->dst.dev = ort->dst.dev; - if (rt->dst.dev) - dev_hold(rt->dst.dev); rt->rt6i_idev = ort->rt6i_idev; if (rt->rt6i_idev) in6_dev_hold(rt->rt6i_idev); @@ -2011,7 +2005,8 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, int anycast) { struct net *net = dev_net(idev->dev); - struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); + struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, + net->loopback_dev); struct neighbour *neigh; if (rt == NULL) { @@ -2021,13 +2016,11 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, return ERR_PTR(-ENOMEM); } - dev_hold(net->loopback_dev); in6_dev_hold(idev); rt->dst.flags = DST_HOST; rt->dst.input = ip6_input; rt->dst.output = ip6_output; - rt->rt6i_dev = net->loopback_dev; rt->rt6i_idev = idev; rt->dst.obsolete = -1; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 15792d8b6272..70552c4e2272 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1348,7 +1348,7 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) default: BUG(); } - xdst = dst_alloc(dst_ops, 0); + xdst = dst_alloc(dst_ops, NULL, 0, 0, 0); xfrm_policy_put_afinfo(afinfo); if (likely(xdst)) -- cgit v1.2.3-58-ga151 From cf91166223772ef4a2ed98b9874958bf6a2470df Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 14:31:47 -0700 Subject: net: Use non-zero allocations in dst_alloc(). Make dst_alloc() and it's users explicitly initialize the entire entry. The zero'ing done by kmem_cache_zalloc() was almost entirely redundant. Signed-off-by: David S. Miller --- net/core/dst.c | 20 +++++++++++-- net/decnet/dn_route.c | 2 ++ net/ipv4/route.c | 78 ++++++++++++++++++++++++++++++-------------------- net/ipv6/route.c | 8 +++++- net/xfrm/xfrm_policy.c | 1 + 5 files changed, 74 insertions(+), 35 deletions(-) diff --git a/net/core/dst.c b/net/core/dst.c index 9505778ec800..30f009327b62 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -175,22 +175,36 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev, if (ops->gc(ops)) return NULL; } - dst = kmem_cache_zalloc(ops->kmem_cachep, GFP_ATOMIC); + dst = kmem_cache_alloc(ops->kmem_cachep, GFP_ATOMIC); if (!dst) return NULL; - dst->ops = ops; + dst->child = NULL; dst->dev = dev; if (dev) dev_hold(dev); + dst->ops = ops; dst_init_metrics(dst, dst_default_metrics, true); + dst->expires = 0UL; dst->path = dst; + dst->neighbour = NULL; + dst->hh = NULL; +#ifdef CONFIG_XFRM + dst->xfrm = NULL; +#endif dst->input = dst_discard; dst->output = dst_discard; - + dst->error = 0; dst->obsolete = initial_obsolete; + dst->header_len = 0; + dst->trailer_len = 0; +#ifdef CONFIG_IP_ROUTE_CLASSID + dst->tclassid = 0; +#endif atomic_set(&dst->__refcnt, initial_ref); + dst->__use = 0; dst->lastuse = jiffies; dst->flags = flags; + dst->next = NULL; #if RT_CACHE_DEBUG >= 2 atomic_inc(&dst_total); #endif diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index f489b081c25d..74544bc6fdec 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -1129,6 +1129,7 @@ make_route: if (rt == NULL) goto e_nobufs; + memset(&rt->fld, 0, sizeof(rt->fld)); rt->fld.saddr = oldflp->saddr; rt->fld.daddr = oldflp->daddr; rt->fld.flowidn_oif = oldflp->flowidn_oif; @@ -1398,6 +1399,7 @@ make_route: if (rt == NULL) goto e_nobufs; + memset(&rt->fld, 0, sizeof(rt->fld)); rt->rt_saddr = fld.saddr; rt->rt_daddr = fld.daddr; rt->rt_gateway = fld.daddr; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index b471d89b57ee..fb9211adf079 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1830,7 +1830,6 @@ static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *oldflp4, #endif set_class_tag(rt, itag); #endif - rt->rt_type = type; } static struct rtable *rt_dst_alloc(struct net_device *dev, @@ -1877,25 +1876,28 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, if (!rth) goto e_nobufs; +#ifdef CONFIG_IP_ROUTE_CLASSID + rth->dst.tclassid = itag; +#endif rth->dst.output = ip_rt_bug; rth->rt_key_dst = daddr; - rth->rt_dst = daddr; - rth->rt_tos = tos; - rth->rt_mark = skb->mark; rth->rt_key_src = saddr; + rth->rt_genid = rt_genid(dev_net(dev)); + rth->rt_flags = RTCF_MULTICAST; + rth->rt_type = RTN_MULTICAST; + rth->rt_tos = tos; + rth->rt_dst = daddr; rth->rt_src = saddr; -#ifdef CONFIG_IP_ROUTE_CLASSID - rth->dst.tclassid = itag; -#endif rth->rt_route_iif = dev->ifindex; rth->rt_iif = dev->ifindex; rth->rt_oif = 0; + rth->rt_mark = skb->mark; rth->rt_gateway = daddr; rth->rt_spec_dst= spec_dst; - rth->rt_genid = rt_genid(dev_net(dev)); - rth->rt_flags = RTCF_MULTICAST; - rth->rt_type = RTN_MULTICAST; + rth->rt_peer_genid = 0; + rth->peer = NULL; + rth->fi = NULL; if (our) { rth->dst.input= ip_local_deliver; rth->rt_flags |= RTCF_LOCAL; @@ -2017,25 +2019,28 @@ static int __mkroute_input(struct sk_buff *skb, } rth->rt_key_dst = daddr; - rth->rt_dst = daddr; - rth->rt_tos = tos; - rth->rt_mark = skb->mark; rth->rt_key_src = saddr; + rth->rt_genid = rt_genid(dev_net(rth->dst.dev)); + rth->rt_flags = flags; + rth->rt_type = res->type; + rth->rt_tos = tos; + rth->rt_dst = daddr; rth->rt_src = saddr; - rth->rt_gateway = daddr; rth->rt_route_iif = in_dev->dev->ifindex; rth->rt_iif = in_dev->dev->ifindex; rth->rt_oif = 0; + rth->rt_mark = skb->mark; + rth->rt_gateway = daddr; rth->rt_spec_dst= spec_dst; + rth->rt_peer_genid = 0; + rth->peer = NULL; + rth->fi = NULL; rth->dst.input = ip_forward; rth->dst.output = ip_output; - rth->rt_genid = rt_genid(dev_net(rth->dst.dev)); rt_set_nexthop(rth, NULL, res, res->fi, res->type, itag); - rth->rt_flags = flags; - *result = rth; err = 0; cleanup: @@ -2187,30 +2192,37 @@ local_input: if (!rth) goto e_nobufs; + rth->dst.input= ip_local_deliver; rth->dst.output= ip_rt_bug; - rth->rt_genid = rt_genid(net); +#ifdef CONFIG_IP_ROUTE_CLASSID + rth->dst.tclassid = itag; +#endif rth->rt_key_dst = daddr; - rth->rt_dst = daddr; - rth->rt_tos = tos; - rth->rt_mark = skb->mark; rth->rt_key_src = saddr; + rth->rt_genid = rt_genid(net); + rth->rt_flags = flags|RTCF_LOCAL; + rth->rt_type = res.type; + rth->rt_tos = tos; + rth->rt_dst = daddr; rth->rt_src = saddr; #ifdef CONFIG_IP_ROUTE_CLASSID rth->dst.tclassid = itag; #endif rth->rt_route_iif = dev->ifindex; rth->rt_iif = dev->ifindex; + rth->rt_oif = 0; + rth->rt_mark = skb->mark; rth->rt_gateway = daddr; rth->rt_spec_dst= spec_dst; - rth->dst.input= ip_local_deliver; - rth->rt_flags = flags|RTCF_LOCAL; + rth->rt_peer_genid = 0; + rth->peer = NULL; + rth->fi = NULL; if (res.type == RTN_UNREACHABLE) { rth->dst.input= ip_error; rth->dst.error= -err; rth->rt_flags &= ~RTCF_LOCAL; } - rth->rt_type = res.type; hash = rt_hash(daddr, saddr, fl4.flowi4_iif, rt_genid(net)); rth = rt_intern_hash(hash, rth, skb, fl4.flowi4_iif); err = 0; @@ -2391,20 +2403,25 @@ static struct rtable *__mkroute_output(const struct fib_result *res, if (!rth) return ERR_PTR(-ENOBUFS); + rth->dst.output = ip_output; + rth->rt_key_dst = oldflp4->daddr; - rth->rt_tos = tos; rth->rt_key_src = oldflp4->saddr; - rth->rt_oif = oldflp4->flowi4_oif; - rth->rt_mark = oldflp4->flowi4_mark; + rth->rt_genid = rt_genid(dev_net(dev_out)); + rth->rt_flags = flags; + rth->rt_type = type; + rth->rt_tos = tos; rth->rt_dst = fl4->daddr; rth->rt_src = fl4->saddr; rth->rt_route_iif = 0; rth->rt_iif = oldflp4->flowi4_oif ? : dev_out->ifindex; + rth->rt_oif = oldflp4->flowi4_oif; + rth->rt_mark = oldflp4->flowi4_mark; rth->rt_gateway = fl4->daddr; rth->rt_spec_dst= fl4->saddr; - - rth->dst.output=ip_output; - rth->rt_genid = rt_genid(dev_net(dev_out)); + rth->rt_peer_genid = 0; + rth->peer = NULL; + rth->fi = NULL; RT_CACHE_STAT_INC(out_slow_tot); @@ -2432,7 +2449,6 @@ static struct rtable *__mkroute_output(const struct fib_result *res, rt_set_nexthop(rth, oldflp4, res, fi, type, 0); - rth->rt_flags = flags; return rth; } diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e8b2bb9060ef..f1be5c5c85ef 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -230,7 +230,11 @@ static struct rt6_info ip6_blk_hole_entry_template = { static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, struct net_device *dev) { - return (struct rt6_info *)dst_alloc(ops, dev, 0, 0, 0); + struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, 0); + + memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); + + return rt; } static void ip6_dst_destroy(struct dst_entry *dst) @@ -887,6 +891,8 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, 0, 0); if (rt) { + memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); + new = &rt->dst; new->__use = 1; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 70552c4e2272..00bcb88386c2 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1349,6 +1349,7 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) BUG(); } xdst = dst_alloc(dst_ops, NULL, 0, 0, 0); + memset(&xdst->u.rt6.rt6i_table, 0, sizeof(*xdst) - sizeof(struct dst_entry)); xfrm_policy_put_afinfo(afinfo); if (likely(xdst)) -- cgit v1.2.3-58-ga151 From 813b3b5db831ddbd92b5ce0fdeb74e3368f1323c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 14:48:42 -0700 Subject: ipv4: Use caller's on-stack flowi as-is in output route lookups. Signed-off-by: David S. Miller --- include/net/route.h | 2 +- net/ipv4/route.c | 158 ++++++++++++++++++++++++++-------------------------- 2 files changed, 81 insertions(+), 79 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index fdbdb9271d7f..81b6cf276549 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -115,7 +115,7 @@ extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw, __be32 src, struct net_device *dev); extern void rt_cache_flush(struct net *net, int how); extern void rt_cache_flush_batch(struct net *net); -extern struct rtable *__ip_route_output_key(struct net *, const struct flowi4 *flp); +extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp); extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp, struct sock *sk); extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index fb9211adf079..93f71be1d5d1 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1767,7 +1767,7 @@ static unsigned int ipv4_default_mtu(const struct dst_entry *dst) return mtu; } -static void rt_init_metrics(struct rtable *rt, const struct flowi4 *oldflp4, +static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, struct fib_info *fi) { struct inet_peer *peer; @@ -1776,7 +1776,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *oldflp4, /* If a peer entry exists for this destination, we must hook * it up in order to get at cached metrics. */ - if (oldflp4 && (oldflp4->flowi4_flags & FLOWI_FLAG_PRECOW_METRICS)) + if (fl4 && (fl4->flowi4_flags & FLOWI_FLAG_PRECOW_METRICS)) create = 1; rt->peer = peer = inet_getpeer_v4(rt->rt_dst, create); @@ -1803,7 +1803,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *oldflp4, } } -static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *oldflp4, +static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *fl4, const struct fib_result *res, struct fib_info *fi, u16 type, u32 itag) { @@ -1813,7 +1813,7 @@ static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *oldflp4, if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) rt->rt_gateway = FIB_RES_GW(*res); - rt_init_metrics(rt, oldflp4, fi); + rt_init_metrics(rt, fl4, fi); #ifdef CONFIG_IP_ROUTE_CLASSID dst->tclassid = FIB_RES_NH(*res).nh_tclassid; #endif @@ -2354,12 +2354,12 @@ EXPORT_SYMBOL(ip_route_input_common); /* called with rcu_read_lock() */ static struct rtable *__mkroute_output(const struct fib_result *res, const struct flowi4 *fl4, - const struct flowi4 *oldflp4, - struct net_device *dev_out, + __be32 orig_daddr, __be32 orig_saddr, + int orig_oif, struct net_device *dev_out, unsigned int flags) { struct fib_info *fi = res->fi; - u32 tos = RT_FL_TOS(oldflp4); + u32 tos = RT_FL_TOS(fl4); struct in_device *in_dev; u16 type = res->type; struct rtable *rth; @@ -2386,8 +2386,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, fi = NULL; } else if (type == RTN_MULTICAST) { flags |= RTCF_MULTICAST | RTCF_LOCAL; - if (!ip_check_mc_rcu(in_dev, oldflp4->daddr, oldflp4->saddr, - oldflp4->flowi4_proto)) + if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr, + fl4->flowi4_proto)) flags &= ~RTCF_LOCAL; /* If multicast route do not exist use * default one, but do not gateway in this case. @@ -2405,8 +2405,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, rth->dst.output = ip_output; - rth->rt_key_dst = oldflp4->daddr; - rth->rt_key_src = oldflp4->saddr; + rth->rt_key_dst = orig_daddr; + rth->rt_key_src = orig_saddr; rth->rt_genid = rt_genid(dev_net(dev_out)); rth->rt_flags = flags; rth->rt_type = type; @@ -2414,9 +2414,9 @@ static struct rtable *__mkroute_output(const struct fib_result *res, rth->rt_dst = fl4->daddr; rth->rt_src = fl4->saddr; rth->rt_route_iif = 0; - rth->rt_iif = oldflp4->flowi4_oif ? : dev_out->ifindex; - rth->rt_oif = oldflp4->flowi4_oif; - rth->rt_mark = oldflp4->flowi4_mark; + rth->rt_iif = orig_oif ? : dev_out->ifindex; + rth->rt_oif = orig_oif; + rth->rt_mark = fl4->flowi4_mark; rth->rt_gateway = fl4->daddr; rth->rt_spec_dst= fl4->saddr; rth->rt_peer_genid = 0; @@ -2439,7 +2439,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, #ifdef CONFIG_IP_MROUTE if (type == RTN_MULTICAST) { if (IN_DEV_MFORWARD(in_dev) && - !ipv4_is_local_multicast(oldflp4->daddr)) { + !ipv4_is_local_multicast(fl4->daddr)) { rth->dst.input = ip_mr_input; rth->dst.output = ip_mc_output; } @@ -2447,7 +2447,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, #endif } - rt_set_nexthop(rth, oldflp4, res, fi, type, 0); + rt_set_nexthop(rth, fl4, res, fi, type, 0); return rth; } @@ -2457,36 +2457,37 @@ static struct rtable *__mkroute_output(const struct fib_result *res, * called with rcu_read_lock(); */ -static struct rtable *ip_route_output_slow(struct net *net, - const struct flowi4 *oldflp4) +static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4) { - u32 tos = RT_FL_TOS(oldflp4); - struct flowi4 fl4; - struct fib_result res; - unsigned int flags = 0; struct net_device *dev_out = NULL; + u32 tos = RT_FL_TOS(fl4); + unsigned int flags = 0; + struct fib_result res; struct rtable *rth; + __be32 orig_daddr; + __be32 orig_saddr; + int orig_oif; res.fi = NULL; #ifdef CONFIG_IP_MULTIPLE_TABLES res.r = NULL; #endif - fl4.flowi4_oif = oldflp4->flowi4_oif; - fl4.flowi4_iif = net->loopback_dev->ifindex; - fl4.flowi4_mark = oldflp4->flowi4_mark; - fl4.daddr = oldflp4->daddr; - fl4.saddr = oldflp4->saddr; - fl4.flowi4_tos = tos & IPTOS_RT_MASK; - fl4.flowi4_scope = ((tos & RTO_ONLINK) ? - RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); + orig_daddr = fl4->daddr; + orig_saddr = fl4->saddr; + orig_oif = fl4->flowi4_oif; + + fl4->flowi4_iif = net->loopback_dev->ifindex; + fl4->flowi4_tos = tos & IPTOS_RT_MASK; + fl4->flowi4_scope = ((tos & RTO_ONLINK) ? + RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); rcu_read_lock(); - if (oldflp4->saddr) { + if (fl4->saddr) { rth = ERR_PTR(-EINVAL); - if (ipv4_is_multicast(oldflp4->saddr) || - ipv4_is_lbcast(oldflp4->saddr) || - ipv4_is_zeronet(oldflp4->saddr)) + if (ipv4_is_multicast(fl4->saddr) || + ipv4_is_lbcast(fl4->saddr) || + ipv4_is_zeronet(fl4->saddr)) goto out; /* I removed check for oif == dev_out->oif here. @@ -2497,11 +2498,11 @@ static struct rtable *ip_route_output_slow(struct net *net, of another iface. --ANK */ - if (oldflp4->flowi4_oif == 0 && - (ipv4_is_multicast(oldflp4->daddr) || - ipv4_is_lbcast(oldflp4->daddr))) { + if (fl4->flowi4_oif == 0 && + (ipv4_is_multicast(fl4->daddr) || + ipv4_is_lbcast(fl4->daddr))) { /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ - dev_out = __ip_dev_find(net, oldflp4->saddr, false); + dev_out = __ip_dev_find(net, fl4->saddr, false); if (dev_out == NULL) goto out; @@ -2520,20 +2521,20 @@ static struct rtable *ip_route_output_slow(struct net *net, Luckily, this hack is good workaround. */ - fl4.flowi4_oif = dev_out->ifindex; + fl4->flowi4_oif = dev_out->ifindex; goto make_route; } - if (!(oldflp4->flowi4_flags & FLOWI_FLAG_ANYSRC)) { + if (!(fl4->flowi4_flags & FLOWI_FLAG_ANYSRC)) { /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ - if (!__ip_dev_find(net, oldflp4->saddr, false)) + if (!__ip_dev_find(net, fl4->saddr, false)) goto out; } } - if (oldflp4->flowi4_oif) { - dev_out = dev_get_by_index_rcu(net, oldflp4->flowi4_oif); + if (fl4->flowi4_oif) { + dev_out = dev_get_by_index_rcu(net, fl4->flowi4_oif); rth = ERR_PTR(-ENODEV); if (dev_out == NULL) goto out; @@ -2543,37 +2544,37 @@ static struct rtable *ip_route_output_slow(struct net *net, rth = ERR_PTR(-ENETUNREACH); goto out; } - if (ipv4_is_local_multicast(oldflp4->daddr) || - ipv4_is_lbcast(oldflp4->daddr)) { - if (!fl4.saddr) - fl4.saddr = inet_select_addr(dev_out, 0, - RT_SCOPE_LINK); + if (ipv4_is_local_multicast(fl4->daddr) || + ipv4_is_lbcast(fl4->daddr)) { + if (!fl4->saddr) + fl4->saddr = inet_select_addr(dev_out, 0, + RT_SCOPE_LINK); goto make_route; } - if (!fl4.saddr) { - if (ipv4_is_multicast(oldflp4->daddr)) - fl4.saddr = inet_select_addr(dev_out, 0, - fl4.flowi4_scope); - else if (!oldflp4->daddr) - fl4.saddr = inet_select_addr(dev_out, 0, - RT_SCOPE_HOST); + if (fl4->saddr) { + if (ipv4_is_multicast(fl4->daddr)) + fl4->saddr = inet_select_addr(dev_out, 0, + fl4->flowi4_scope); + else if (!fl4->daddr) + fl4->saddr = inet_select_addr(dev_out, 0, + RT_SCOPE_HOST); } } - if (!fl4.daddr) { - fl4.daddr = fl4.saddr; - if (!fl4.daddr) - fl4.daddr = fl4.saddr = htonl(INADDR_LOOPBACK); + if (!fl4->daddr) { + fl4->daddr = fl4->saddr; + if (!fl4->daddr) + fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK); dev_out = net->loopback_dev; - fl4.flowi4_oif = net->loopback_dev->ifindex; + fl4->flowi4_oif = net->loopback_dev->ifindex; res.type = RTN_LOCAL; flags |= RTCF_LOCAL; goto make_route; } - if (fib_lookup(net, &fl4, &res)) { + if (fib_lookup(net, fl4, &res)) { res.fi = NULL; - if (oldflp4->flowi4_oif) { + if (fl4->flowi4_oif) { /* Apparently, routing tables are wrong. Assume, that the destination is on link. @@ -2592,9 +2593,9 @@ static struct rtable *ip_route_output_slow(struct net *net, likely IPv6, but we do not. */ - if (fl4.saddr == 0) - fl4.saddr = inet_select_addr(dev_out, 0, - RT_SCOPE_LINK); + if (fl4->saddr == 0) + fl4->saddr = inet_select_addr(dev_out, 0, + RT_SCOPE_LINK); res.type = RTN_UNICAST; goto make_route; } @@ -2603,44 +2604,45 @@ static struct rtable *ip_route_output_slow(struct net *net, } if (res.type == RTN_LOCAL) { - if (!fl4.saddr) { + if (!fl4->saddr) { if (res.fi->fib_prefsrc) - fl4.saddr = res.fi->fib_prefsrc; + fl4->saddr = res.fi->fib_prefsrc; else - fl4.saddr = fl4.daddr; + fl4->saddr = fl4->daddr; } dev_out = net->loopback_dev; - fl4.flowi4_oif = dev_out->ifindex; + fl4->flowi4_oif = dev_out->ifindex; res.fi = NULL; flags |= RTCF_LOCAL; goto make_route; } #ifdef CONFIG_IP_ROUTE_MULTIPATH - if (res.fi->fib_nhs > 1 && fl4.flowi4_oif == 0) + if (res.fi->fib_nhs > 1 && fl4->flowi4_oif == 0) fib_select_multipath(&res); else #endif if (!res.prefixlen && res.table->tb_num_default > 1 && - res.type == RTN_UNICAST && !fl4.flowi4_oif) + res.type == RTN_UNICAST && !fl4->flowi4_oif) fib_select_default(&res); - if (!fl4.saddr) - fl4.saddr = FIB_RES_PREFSRC(net, res); + if (!fl4->saddr) + fl4->saddr = FIB_RES_PREFSRC(net, res); dev_out = FIB_RES_DEV(res); - fl4.flowi4_oif = dev_out->ifindex; + fl4->flowi4_oif = dev_out->ifindex; make_route: - rth = __mkroute_output(&res, &fl4, oldflp4, dev_out, flags); + rth = __mkroute_output(&res, fl4, orig_daddr, orig_saddr, orig_oif, + dev_out, flags); if (!IS_ERR(rth)) { unsigned int hash; - hash = rt_hash(oldflp4->daddr, oldflp4->saddr, oldflp4->flowi4_oif, + hash = rt_hash(orig_daddr, orig_saddr, orig_oif, rt_genid(dev_net(dev_out))); - rth = rt_intern_hash(hash, rth, NULL, oldflp4->flowi4_oif); + rth = rt_intern_hash(hash, rth, NULL, orig_oif); } out: @@ -2648,7 +2650,7 @@ out: return rth; } -struct rtable *__ip_route_output_key(struct net *net, const struct flowi4 *flp4) +struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4) { struct rtable *rth; unsigned int hash; -- cgit v1.2.3-58-ga151 From 6706b6ebab85dfca4e2886e35ec9c3c4ee13e27e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 23:13:17 -0700 Subject: ipv4: Remove now superfluous code in ip_route_connect(). Now that output route lookups update the flow with source address et al. selections, the fl4->{saddr,daddr} assignments here are no longer necessary. Signed-off-by: David S. Miller --- include/net/route.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index 81b6cf276549..16eb59cd7080 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -271,8 +271,6 @@ static inline struct rtable *ip_route_connect(struct flowi4 *fl4, rt = __ip_route_output_key(net, fl4); if (IS_ERR(rt)) return rt; - fl4->daddr = rt->rt_dst; - fl4->saddr = rt->rt_src; ip_rt_put(rt); } security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); -- cgit v1.2.3-58-ga151 From b883187785004cacea053569f1655fada0dfc299 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 23:16:53 -0700 Subject: ipv4: Fetch route saddr from flow key in inet_sk_reselect_saddr(). Now that output route lookups update the flow with source address selection, we can fetch it from fl4->saddr instead of rt->rt_src Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 963a621e75c7..4e734992e266 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1122,7 +1122,7 @@ static int inet_sk_reselect_saddr(struct sock *sk) sk_setup_caps(sk, &rt->dst); - new_saddr = rt->rt_src; + new_saddr = fl4.saddr; if (new_saddr == old_saddr) return 0; -- cgit v1.2.3-58-ga151 From a406b611b5f26a18773e4237d79f6df3eaed1d32 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 23:17:16 -0700 Subject: ipv4: Fetch route saddr from flow key in ip4_datagram_connect(). Now that output route lookups update the flow with source address selection, we can fetch it from fl4->saddr instead of rt->rt_src Signed-off-by: David S. Miller --- net/ipv4/datagram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index 216ba2338b64..b7f583c93ca1 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -63,9 +63,9 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) return -EACCES; } if (!inet->inet_saddr) - inet->inet_saddr = rt->rt_src; /* Update source address */ + inet->inet_saddr = fl4.saddr; /* Update source address */ if (!inet->inet_rcv_saddr) { - inet->inet_rcv_saddr = rt->rt_src; + inet->inet_rcv_saddr = fl4.saddr; if (sk->sk_prot->rehash) sk->sk_prot->rehash(sk); } -- cgit v1.2.3-58-ga151 From 4071cfff84c5b084762fe288781cd7faab14cb4b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 23:17:31 -0700 Subject: ipv4: Fetch route saddr from flow key in tcp_v4_connect(). Now that output route lookups update the flow with source address selection, we can fetch it from fl4->saddr instead of rt->rt_src Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index d60732fe5f21..3be00afc8900 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -193,7 +193,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) daddr = rt->rt_dst; if (!inet->inet_saddr) - inet->inet_saddr = rt->rt_src; + inet->inet_saddr = fl4.saddr; inet->inet_rcv_saddr = inet->inet_saddr; if (tp->rx_opt.ts_recent_stamp && inet->inet_daddr != daddr) { -- cgit v1.2.3-58-ga151 From 44901666a1a736b3f43eac7894b07183f127e9a9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 23:17:58 -0700 Subject: ipv4: Fetch route saddr from flow key in l2tp_ip_connect(). Now that output route lookups update the flow with source address selection, we can fetch it from fl4->saddr instead of rt->rt_src Signed-off-by: David S. Miller --- net/l2tp/l2tp_ip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index e13c166824e0..c100fa99cf8e 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -340,9 +340,9 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id; if (!inet->inet_saddr) - inet->inet_saddr = rt->rt_src; + inet->inet_saddr = fl4.saddr; if (!inet->inet_rcv_saddr) - inet->inet_rcv_saddr = rt->rt_src; + inet->inet_rcv_saddr = fl4.saddr; inet->inet_daddr = rt->rt_dst; sk->sk_state = TCP_ESTABLISHED; inet->inet_id = jiffies; -- cgit v1.2.3-58-ga151 From 91ab0b60a12833b4715b838474f23496af8de30c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 23:49:30 -0700 Subject: ipv4: Get route daddr from flow key in dccp_v4_connect(). Now that output route lookups update the flow with destination address selection, we can fetch it from fl4->daddr instead of rt->rt_dst Signed-off-by: David S. Miller --- net/dccp/ipv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index cbbcc6c036e0..f4254bb4745d 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -83,7 +83,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) } if (inet_opt == NULL || !inet_opt->opt.srr) - daddr = rt->rt_dst; + daddr = fl4.daddr; if (inet->inet_saddr == 0) inet->inet_saddr = rt->rt_src; -- cgit v1.2.3-58-ga151 From 87321c839fb4a65b5d78c16d79d1674cf223a452 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 23:49:45 -0700 Subject: ipv4: Get route daddr from flow key in ip4_datagram_connect(). Now that output route lookups update the flow with destination address selection, we can fetch it from fl4->daddr instead of rt->rt_dst Signed-off-by: David S. Miller --- net/ipv4/datagram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index b7f583c93ca1..d5a2e6995bae 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -69,7 +69,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (sk->sk_prot->rehash) sk->sk_prot->rehash(sk); } - inet->inet_daddr = rt->rt_dst; + inet->inet_daddr = fl4.daddr; inet->inet_dport = usin->sin_port; sk->sk_state = TCP_ESTABLISHED; inet->inet_id = jiffies; -- cgit v1.2.3-58-ga151 From 072d8c94142a3a95151774975f6c1fd1dc1f1e1b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 23:50:09 -0700 Subject: ipv4: Get route daddr from flow key in inet_csk_route_req(). Now that output route lookups update the flow with destination address selection, we can fetch it from fl4->daddr instead of rt->rt_dst Signed-off-by: David S. Miller --- net/ipv4/inet_connection_sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 3282cb2de393..54944da2f794 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -367,7 +367,7 @@ struct dst_entry *inet_csk_route_req(struct sock *sk, rt = ip_route_output_flow(net, &fl4, sk); if (IS_ERR(rt)) goto no_route; - if (opt && opt->opt.is_strictroute && rt->rt_dst != rt->rt_gateway) + if (opt && opt->opt.is_strictroute && fl4.daddr != rt->rt_gateway) goto route_err; return &rt->dst; -- cgit v1.2.3-58-ga151 From d4fb3d74d7a17833de2ba8cbd4f029b30feb4825 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 23:50:32 -0700 Subject: ipv4: Get route daddr from flow key in tcp_v4_connect(). Now that output route lookups update the flow with destination address selection, we can fetch it from fl4->daddr instead of rt->rt_dst Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3be00afc8900..f3d16d8918c7 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -190,7 +190,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) } if (!inet_opt || !inet_opt->opt.srr) - daddr = rt->rt_dst; + daddr = fl4.daddr; if (!inet->inet_saddr) inet->inet_saddr = fl4.saddr; @@ -204,7 +204,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) } if (tcp_death_row.sysctl_tw_recycle && - !tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) { + !tp->rx_opt.ts_recent_stamp && fl4.daddr == daddr) { struct inet_peer *peer = rt_get_peer(rt); /* * VJ's idea. We save last timestamp seen from -- cgit v1.2.3-58-ga151 From ad227425c9ca907b5498e2558320b7e585d86ec9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 23:50:49 -0700 Subject: ipv4: Get route daddr from flow key in l2tp_ip_connect(). Now that output route lookups update the flow with destination address selection, we can fetch it from fl4->daddr instead of rt->rt_dst Signed-off-by: David S. Miller --- net/l2tp/l2tp_ip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index c100fa99cf8e..a4d2dfa1fdbf 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -343,7 +343,7 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len inet->inet_saddr = fl4.saddr; if (!inet->inet_rcv_saddr) inet->inet_rcv_saddr = fl4.saddr; - inet->inet_daddr = rt->rt_dst; + inet->inet_daddr = fl4.daddr; sk->sk_state = TCP_ESTABLISHED; inet->inet_id = jiffies; -- cgit v1.2.3-58-ga151 From b6202f97897a13ef531b822ab326dfc7eb90bdaf Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 29 Apr 2011 10:20:53 -0700 Subject: bpf: depends on MODULES module_alloc() and module_free() are available only if CONFIG_MODULES=y Reported-by: Randy Dunlap Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/net/Kconfig b/net/Kconfig index 745fb02d2fda..878151c772c9 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -238,6 +238,7 @@ config HAVE_BPF_JIT config BPF_JIT bool "enable BPF Just In Time compiler" depends on HAVE_BPF_JIT + depends on MODULES ---help--- Berkeley Packet Filter filtering capabilities are normally handled by an interpreter. This option allows kernel to generate a native -- cgit v1.2.3-58-ga151 From 7d36a991e8d36b8ae87e2aa1158d3735e656253b Mon Sep 17 00:00:00 2001 From: amit salecha Date: Fri, 22 Apr 2011 16:22:20 +0000 Subject: pktgen: create num frags requested Pktgen doesn't generate number of frags requested. Divide packet size by number of frags and fill that in every frags. Example: With packet size 1470, it generate only 11 frags. Initial frags get lenght 706, 353, 177....so on. Last frag get divided by 2. Now with this fix, each frags will get 78 bytes. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- net/core/pktgen.c | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 2fa6fee1b46f..ff79d94b5944 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2622,6 +2622,7 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, } else { int frags = pkt_dev->nfrags; int i, len; + int frag_len; if (frags > MAX_SKB_FRAGS) @@ -2633,6 +2634,8 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, } i = 0; + frag_len = (datalen/frags) < PAGE_SIZE ? + (datalen/frags) : PAGE_SIZE; while (datalen > 0) { if (unlikely(!pkt_dev->page)) { int node = numa_node_id(); @@ -2646,38 +2649,18 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, skb_shinfo(skb)->frags[i].page = pkt_dev->page; get_page(pkt_dev->page); skb_shinfo(skb)->frags[i].page_offset = 0; - skb_shinfo(skb)->frags[i].size = - (datalen < PAGE_SIZE ? datalen : PAGE_SIZE); + /*last fragment, fill rest of data*/ + if (i == (frags - 1)) + skb_shinfo(skb)->frags[i].size = + (datalen < PAGE_SIZE ? datalen : PAGE_SIZE); + else + skb_shinfo(skb)->frags[i].size = frag_len; datalen -= skb_shinfo(skb)->frags[i].size; skb->len += skb_shinfo(skb)->frags[i].size; skb->data_len += skb_shinfo(skb)->frags[i].size; i++; skb_shinfo(skb)->nr_frags = i; } - - while (i < frags) { - int rem; - - if (i == 0) - break; - - rem = skb_shinfo(skb)->frags[i - 1].size / 2; - if (rem == 0) - break; - - skb_shinfo(skb)->frags[i - 1].size -= rem; - - skb_shinfo(skb)->frags[i] = - skb_shinfo(skb)->frags[i - 1]; - get_page(skb_shinfo(skb)->frags[i].page); - skb_shinfo(skb)->frags[i].page = - skb_shinfo(skb)->frags[i - 1].page; - skb_shinfo(skb)->frags[i].page_offset += - skb_shinfo(skb)->frags[i - 1].size; - skb_shinfo(skb)->frags[i].size = rem; - i++; - skb_shinfo(skb)->nr_frags = i; - } } /* Stamp the time, and sequence number, -- cgit v1.2.3-58-ga151 From e245292e0a98bfbf2b54c5c0f079033f4d06dd32 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 29 Apr 2011 14:35:14 -0400 Subject: ath5k: fix uninitialized var warning for txf2txs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC [M] drivers/net/wireless/ath/ath5k/reset.o drivers/net/wireless/ath/ath5k/reset.c: In function ‘ath5k_hw_init_core_clock’: drivers/net/wireless/ath/ath5k/reset.c:100:51: warning: ‘txf2txs’ may be used uninitialized in this function Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/reset.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 84206898f77d..3510de2cf622 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -158,6 +158,11 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) txlat = AR5K_REG_MS(usec_reg, AR5K_USEC_TX_LATENCY_5211); rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211); + /* + * Set default Tx frame to Tx data start delay + */ + txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT; + /* * 5210 initvals don't include usec settings * so we need to use magic values here for -- cgit v1.2.3-58-ga151 From 2eeb6fd063d812a528118536857d078bca5a1e05 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 29 Apr 2011 14:54:27 -0400 Subject: b43: avoid uninitialized variable warnings in phy_n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC [M] drivers/net/wireless/b43/phy_n.o drivers/net/wireless/b43/phy_n.c: In function ‘b43_nphy_set_channel’: drivers/net/wireless/b43/phy_n.c:3848:47: warning: ‘tabent_r2’ may be used uninitialized in this function drivers/net/wireless/b43/phy_n.c:3849:47: warning: ‘tabent_r3’ may be used uninitialized in this function drivers/net/wireless/b43/phy_n.c: In function ‘b43_nphy_poll_rssi.clone.14’: drivers/net/wireless/b43/phy_n.c:2270:6: warning: ‘save_regs_phy$7’ may be used uninitialized in this function drivers/net/wireless/b43/phy_n.c:2270:6: warning: ‘save_regs_phy$8’ may be used uninitialized in this function FWIW, the usage of these variables is goverened by checks that match their initializations. So, I think these are actually false warnings. Still, I would rather avoid the warning SPAM... Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 8a00f9a95dbb..6755063f955a 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -2281,6 +2281,7 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1); + save_regs_phy[8] = 0; } else { save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); @@ -2289,6 +2290,8 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER); save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1); save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2); + save_regs_phy[7] = 0; + save_regs_phy[8] = 0; } b43_nphy_rssi_select(dev, 5, type); @@ -3845,8 +3848,8 @@ static int b43_nphy_set_channel(struct b43_wldev *dev, { struct b43_phy *phy = &dev->phy; - const struct b43_nphy_channeltab_entry_rev2 *tabent_r2; - const struct b43_nphy_channeltab_entry_rev3 *tabent_r3; + const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL; + const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL; u8 tmp; -- cgit v1.2.3-58-ga151 From f9c2fdbab1f1854f2bfcc75c326d0f4537ec2a7e Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 29 Apr 2011 15:04:58 -0400 Subject: mwifiex: fix copy-n-paste 'thinko' for tsf_val MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC [M] drivers/net/wireless/mwifiex/join.o drivers/net/wireless/mwifiex/join.c: In function ‘mwifiex_cmd_802_11_associate’: drivers/net/wireless/mwifiex/join.c:119:8: warning: ‘tsf_val’ may be used uninitialized in this function drivers/net/wireless/mwifiex/join.c:103:12: note: ‘tsf_val’ was declared here Looks like a copy-n-paste error, identical lines are a few lines below the ones removed, with an actual memcpy to tsf_val in between... Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/join.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 23d2d0b9a527..042eb7701d04 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -116,9 +116,6 @@ mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer, memcpy(*buffer, &tsf_tlv, sizeof(tsf_tlv.header)); *buffer += sizeof(tsf_tlv.header); - memcpy(*buffer, &tsf_val, sizeof(tsf_val)); - *buffer += sizeof(tsf_val); - memcpy(&tsf_val, bss_desc->time_stamp, sizeof(tsf_val)); dev_dbg(priv->adapter->dev, "info: %s: TSF offset calc: %016llx - " -- cgit v1.2.3-58-ga151 From ce6cac88a4f1e52a51a31c31562f4da347543147 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 29 Apr 2011 15:09:39 -0400 Subject: p54: avoid uninitialized variable warning for freq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC [M] drivers/net/wireless/p54/eeprom.o drivers/net/wireless/p54/eeprom.c: In function ‘p54_parse_rssical’: drivers/net/wireless/p54/eeprom.c:494:8: warning: ‘freq’ may be used uninitialized in this function Signed-off-by: John W. Linville --- drivers/net/wireless/p54/eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 13d750da9301..54cc0bba66b9 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -491,7 +491,7 @@ static int p54_parse_rssical(struct ieee80211_hw *dev, struct pda_rssi_cal_entry *cal = (void *) &data[offset]; for (i = 0; i < entries; i++) { - u16 freq; + u16 freq = 0; switch (i) { case IEEE80211_BAND_2GHZ: freq = 2437; -- cgit v1.2.3-58-ga151 From 80d887c3b4566f4d14cd7cd5374eba30131d020f Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Thu, 28 Apr 2011 14:28:33 +0530 Subject: ath9k_htc: Dump base eeprom header for UB91/94/95 Debugfs file location: /ieee80211/phy#/ath9k_htc/base_eeprom Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 170 +++++++++++++++++++++++-- 1 file changed, 162 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 894e5ef3f8d1..cff2d217725f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -492,6 +492,158 @@ static const struct file_operations fops_debug = { .llseek = default_llseek, }; +static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + struct ath_common *common = ath9k_hw_common(priv->ah); + struct base_eep_header *pBase = NULL; + unsigned int len = 0, size = 1500; + ssize_t retval = 0; + char *buf; + + /* + * This can be done since all the 3 EEPROM families have the + * same base header upto a certain point, and we are interested in + * the data only upto that point. + */ + + if (AR_SREV_9271(priv->ah)) + pBase = (struct base_eep_header *) + &priv->ah->eeprom.map4k.baseEepHeader; + else if (priv->ah->hw_version.usbdev == AR9280_USB) + pBase = (struct base_eep_header *) + &priv->ah->eeprom.def.baseEepHeader; + else if (priv->ah->hw_version.usbdev == AR9287_USB) + pBase = (struct base_eep_header *) + &priv->ah->eeprom.map9287.baseEepHeader; + + if (pBase == NULL) { + ath_err(common, "Unknown EEPROM type\n"); + return 0; + } + + buf = kzalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + len += snprintf(buf + len, size - len, + "%20s : %10d\n", "Major Version", + pBase->version >> 12); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", "Minor Version", + pBase->version & 0xFFF); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", "Checksum", + pBase->checksum); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", "Length", + pBase->length); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", "RegDomain1", + pBase->regDmn[0]); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", "RegDomain2", + pBase->regDmn[1]); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "TX Mask", pBase->txMask); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "RX Mask", pBase->rxMask); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "Allow 5GHz", + !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "Allow 2GHz", + !!(pBase->opCapFlags & AR5416_OPFLAGS_11G)); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "Disable 2GHz HT20", + !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT20)); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "Disable 2GHz HT40", + !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT40)); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "Disable 5Ghz HT20", + !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT20)); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "Disable 5Ghz HT40", + !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT40)); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "Big Endian", + !!(pBase->eepMisc & 0x01)); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "Cal Bin Major Ver", + (pBase->binBuildNumber >> 24) & 0xFF); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "Cal Bin Minor Ver", + (pBase->binBuildNumber >> 16) & 0xFF); + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "Cal Bin Build", + (pBase->binBuildNumber >> 8) & 0xFF); + + /* + * UB91 specific data. + */ + if (AR_SREV_9271(priv->ah)) { + struct base_eep_header_4k *pBase4k = + &priv->ah->eeprom.map4k.baseEepHeader; + + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "TX Gain type", + pBase4k->txGainType); + } + + /* + * UB95 specific data. + */ + if (priv->ah->hw_version.usbdev == AR9287_USB) { + struct base_eep_ar9287_header *pBase9287 = + &priv->ah->eeprom.map9287.baseEepHeader; + + len += snprintf(buf + len, size - len, + "%20s : %10ddB\n", + "Power Table Offset", + pBase9287->pwrTableOffset); + + len += snprintf(buf + len, size - len, + "%20s : %10d\n", + "OpenLoop Power Ctrl", + pBase9287->openLoopPwrCntl); + } + + len += snprintf(buf + len, size - len, + "%20s : %02X:%02X:%02X:%02X:%02X:%02X\n", + "MacAddress", + pBase->macAddr[0], pBase->macAddr[1], pBase->macAddr[2], + pBase->macAddr[3], pBase->macAddr[4], pBase->macAddr[5]); + if (len > size) + len = size; + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + + return retval; +} + +static const struct file_operations fops_base_eeprom = { + .read = read_file_base_eeprom, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + int ath9k_htc_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -503,21 +655,23 @@ int ath9k_htc_init_debug(struct ath_hw *ah) return -ENOMEM; debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_tgt_int_stats); + priv, &fops_tgt_int_stats); debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_tgt_tx_stats); + priv, &fops_tgt_tx_stats); debugfs_create_file("tgt_rx_stats", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_tgt_rx_stats); + priv, &fops_tgt_rx_stats); debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_xmit); + priv, &fops_xmit); debugfs_create_file("recv", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_recv); + priv, &fops_recv); debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_slot); + priv, &fops_slot); debugfs_create_file("queue", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_queue); + priv, &fops_queue); debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy, - priv, &fops_debug); + priv, &fops_debug); + debugfs_create_file("base_eeprom", S_IRUSR, priv->debug.debugfs_phy, + priv, &fops_base_eeprom); return 0; } -- cgit v1.2.3-58-ga151 From 44368796b87d321e6ea84295a23b2e8eb415d300 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Thu, 28 Apr 2011 14:28:51 +0530 Subject: ath9k_htc: Dump modal eeprom header for UB91/94/95 Debugfs file location: /ieee80211/phy#/ath9k_htc/modal_eeprom Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 283 +++++++++++++++++++++++++ 1 file changed, 283 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index cff2d217725f..aa48b3abbc48 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -644,6 +644,287 @@ static const struct file_operations fops_base_eeprom = { .llseek = default_llseek, }; +static ssize_t read_4k_modal_eeprom(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ +#define PR_EEP(_s, _val) \ + do { \ + len += snprintf(buf + len, size - len, "%20s : %10d\n", \ + _s, (_val)); \ + } while (0) + + struct ath9k_htc_priv *priv = file->private_data; + struct modal_eep_4k_header *pModal = &priv->ah->eeprom.map4k.modalHeader; + unsigned int len = 0, size = 2048; + ssize_t retval = 0; + char *buf; + + buf = kzalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); + PR_EEP("Ant. Common Control", pModal->antCtrlCommon); + PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]); + PR_EEP("Switch Settle", pModal->switchSettling); + PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]); + PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]); + PR_EEP("ADC Desired size", pModal->adcDesiredSize); + PR_EEP("PGA Desired size", pModal->pgaDesiredSize); + PR_EEP("Chain0 xlna Gain", pModal->xlnaGainCh[0]); + PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff); + PR_EEP("txEndToRxOn", pModal->txEndToRxOn); + PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn); + PR_EEP("CCA Threshold)", pModal->thresh62); + PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]); + PR_EEP("xpdGain", pModal->xpdGain); + PR_EEP("External PD", pModal->xpd); + PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]); + PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]); + PR_EEP("pdGainOverlap", pModal->pdGainOverlap); + PR_EEP("O/D Bias Version", pModal->version); + PR_EEP("CCK OutputBias", pModal->ob_0); + PR_EEP("BPSK OutputBias", pModal->ob_1); + PR_EEP("QPSK OutputBias", pModal->ob_2); + PR_EEP("16QAM OutputBias", pModal->ob_3); + PR_EEP("64QAM OutputBias", pModal->ob_4); + PR_EEP("CCK Driver1_Bias", pModal->db1_0); + PR_EEP("BPSK Driver1_Bias", pModal->db1_1); + PR_EEP("QPSK Driver1_Bias", pModal->db1_2); + PR_EEP("16QAM Driver1_Bias", pModal->db1_3); + PR_EEP("64QAM Driver1_Bias", pModal->db1_4); + PR_EEP("CCK Driver2_Bias", pModal->db2_0); + PR_EEP("BPSK Driver2_Bias", pModal->db2_1); + PR_EEP("QPSK Driver2_Bias", pModal->db2_2); + PR_EEP("16QAM Driver2_Bias", pModal->db2_3); + PR_EEP("64QAM Driver2_Bias", pModal->db2_4); + PR_EEP("xPA Bias Level", pModal->xpaBiasLvl); + PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart); + PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn); + PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc); + PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]); + PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]); + PR_EEP("HT40 Switch Settle", pModal->swSettleHt40); + PR_EEP("Chain0 xatten2Db", pModal->xatten2Db[0]); + PR_EEP("Chain0 xatten2Margin", pModal->xatten2Margin[0]); + PR_EEP("Ant. Diversity ctl1", pModal->antdiv_ctl1); + PR_EEP("Ant. Diversity ctl2", pModal->antdiv_ctl2); + PR_EEP("TX Diversity", pModal->tx_diversity); + + if (len > size) + len = size; + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + + return retval; + +#undef PR_EEP +} + +static ssize_t read_def_modal_eeprom(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ +#define PR_EEP(_s, _val) \ + do { \ + if (pBase->opCapFlags & AR5416_OPFLAGS_11G) { \ + pModal = &priv->ah->eeprom.def.modalHeader[1]; \ + len += snprintf(buf + len, size - len, "%20s : %8d%7s", \ + _s, (_val), "|"); \ + } \ + if (pBase->opCapFlags & AR5416_OPFLAGS_11A) { \ + pModal = &priv->ah->eeprom.def.modalHeader[0]; \ + len += snprintf(buf + len, size - len, "%9d\n", \ + (_val)); \ + } \ + } while (0) + + struct ath9k_htc_priv *priv = file->private_data; + struct base_eep_header *pBase = &priv->ah->eeprom.def.baseEepHeader; + struct modal_eep_header *pModal = NULL; + unsigned int len = 0, size = 3500; + ssize_t retval = 0; + char *buf; + + buf = kzalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + len += snprintf(buf + len, size - len, + "%31s %15s\n", "2G", "5G"); + len += snprintf(buf + len, size - len, + "%32s %16s\n", "====", "====\n"); + + PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); + PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]); + PR_EEP("Chain2 Ant. Control", pModal->antCtrlChain[2]); + PR_EEP("Ant. Common Control", pModal->antCtrlCommon); + PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]); + PR_EEP("Chain1 Ant. Gain", pModal->antennaGainCh[1]); + PR_EEP("Chain2 Ant. Gain", pModal->antennaGainCh[2]); + PR_EEP("Switch Settle", pModal->switchSettling); + PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]); + PR_EEP("Chain1 TxRxAtten", pModal->txRxAttenCh[1]); + PR_EEP("Chain2 TxRxAtten", pModal->txRxAttenCh[2]); + PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]); + PR_EEP("Chain1 RxTxMargin", pModal->rxTxMarginCh[1]); + PR_EEP("Chain2 RxTxMargin", pModal->rxTxMarginCh[2]); + PR_EEP("ADC Desired size", pModal->adcDesiredSize); + PR_EEP("PGA Desired size", pModal->pgaDesiredSize); + PR_EEP("Chain0 xlna Gain", pModal->xlnaGainCh[0]); + PR_EEP("Chain1 xlna Gain", pModal->xlnaGainCh[1]); + PR_EEP("Chain2 xlna Gain", pModal->xlnaGainCh[2]); + PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff); + PR_EEP("txEndToRxOn", pModal->txEndToRxOn); + PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn); + PR_EEP("CCA Threshold)", pModal->thresh62); + PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]); + PR_EEP("Chain1 NF Threshold", pModal->noiseFloorThreshCh[1]); + PR_EEP("Chain2 NF Threshold", pModal->noiseFloorThreshCh[2]); + PR_EEP("xpdGain", pModal->xpdGain); + PR_EEP("External PD", pModal->xpd); + PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]); + PR_EEP("Chain1 I Coefficient", pModal->iqCalICh[1]); + PR_EEP("Chain2 I Coefficient", pModal->iqCalICh[2]); + PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]); + PR_EEP("Chain1 Q Coefficient", pModal->iqCalQCh[1]); + PR_EEP("Chain2 Q Coefficient", pModal->iqCalQCh[2]); + PR_EEP("pdGainOverlap", pModal->pdGainOverlap); + PR_EEP("Chain0 OutputBias", pModal->ob); + PR_EEP("Chain0 DriverBias", pModal->db); + PR_EEP("xPA Bias Level", pModal->xpaBiasLvl); + PR_EEP("2chain pwr decrease", pModal->pwrDecreaseFor2Chain); + PR_EEP("3chain pwr decrease", pModal->pwrDecreaseFor3Chain); + PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart); + PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn); + PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc); + PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]); + PR_EEP("Chain1 bswAtten", pModal->bswAtten[1]); + PR_EEP("Chain2 bswAtten", pModal->bswAtten[2]); + PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]); + PR_EEP("Chain1 bswMargin", pModal->bswMargin[1]); + PR_EEP("Chain2 bswMargin", pModal->bswMargin[2]); + PR_EEP("HT40 Switch Settle", pModal->swSettleHt40); + PR_EEP("Chain0 xatten2Db", pModal->xatten2Db[0]); + PR_EEP("Chain1 xatten2Db", pModal->xatten2Db[1]); + PR_EEP("Chain2 xatten2Db", pModal->xatten2Db[2]); + PR_EEP("Chain0 xatten2Margin", pModal->xatten2Margin[0]); + PR_EEP("Chain1 xatten2Margin", pModal->xatten2Margin[1]); + PR_EEP("Chain2 xatten2Margin", pModal->xatten2Margin[2]); + PR_EEP("Chain1 OutputBias", pModal->ob_ch1); + PR_EEP("Chain1 DriverBias", pModal->db_ch1); + PR_EEP("LNA Control", pModal->lna_ctl); + PR_EEP("XPA Bias Freq0", pModal->xpaBiasLvlFreq[0]); + PR_EEP("XPA Bias Freq1", pModal->xpaBiasLvlFreq[1]); + PR_EEP("XPA Bias Freq2", pModal->xpaBiasLvlFreq[2]); + + if (len > size) + len = size; + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + + return retval; + +#undef PR_EEP +} + +static ssize_t read_9287_modal_eeprom(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ +#define PR_EEP(_s, _val) \ + do { \ + len += snprintf(buf + len, size - len, "%20s : %10d\n", \ + _s, (_val)); \ + } while (0) + + struct ath9k_htc_priv *priv = file->private_data; + struct modal_eep_ar9287_header *pModal = &priv->ah->eeprom.map9287.modalHeader; + unsigned int len = 0, size = 3000; + ssize_t retval = 0; + char *buf; + + buf = kzalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); + PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]); + PR_EEP("Ant. Common Control", pModal->antCtrlCommon); + PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]); + PR_EEP("Chain1 Ant. Gain", pModal->antennaGainCh[1]); + PR_EEP("Switch Settle", pModal->switchSettling); + PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]); + PR_EEP("Chain1 TxRxAtten", pModal->txRxAttenCh[1]); + PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]); + PR_EEP("Chain1 RxTxMargin", pModal->rxTxMarginCh[1]); + PR_EEP("ADC Desired size", pModal->adcDesiredSize); + PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff); + PR_EEP("txEndToRxOn", pModal->txEndToRxOn); + PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn); + PR_EEP("CCA Threshold)", pModal->thresh62); + PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]); + PR_EEP("Chain1 NF Threshold", pModal->noiseFloorThreshCh[1]); + PR_EEP("xpdGain", pModal->xpdGain); + PR_EEP("External PD", pModal->xpd); + PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]); + PR_EEP("Chain1 I Coefficient", pModal->iqCalICh[1]); + PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]); + PR_EEP("Chain1 Q Coefficient", pModal->iqCalQCh[1]); + PR_EEP("pdGainOverlap", pModal->pdGainOverlap); + PR_EEP("xPA Bias Level", pModal->xpaBiasLvl); + PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart); + PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn); + PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc); + PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]); + PR_EEP("Chain1 bswAtten", pModal->bswAtten[1]); + PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]); + PR_EEP("Chain1 bswMargin", pModal->bswMargin[1]); + PR_EEP("HT40 Switch Settle", pModal->swSettleHt40); + PR_EEP("AR92x7 Version", pModal->version); + PR_EEP("DriverBias1", pModal->db1); + PR_EEP("DriverBias2", pModal->db1); + PR_EEP("CCK OutputBias", pModal->ob_cck); + PR_EEP("PSK OutputBias", pModal->ob_psk); + PR_EEP("QAM OutputBias", pModal->ob_qam); + PR_EEP("PAL_OFF OutputBias", pModal->ob_pal_off); + + if (len > size) + len = size; + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + + return retval; + +#undef PR_EEP +} + +static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + + if (AR_SREV_9271(priv->ah)) + return read_4k_modal_eeprom(file, user_buf, count, ppos); + else if (priv->ah->hw_version.usbdev == AR9280_USB) + return read_def_modal_eeprom(file, user_buf, count, ppos); + else if (priv->ah->hw_version.usbdev == AR9287_USB) + return read_9287_modal_eeprom(file, user_buf, count, ppos); + + return 0; +} + +static const struct file_operations fops_modal_eeprom = { + .read = read_file_modal_eeprom, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + int ath9k_htc_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -672,6 +953,8 @@ int ath9k_htc_init_debug(struct ath_hw *ah) priv, &fops_debug); debugfs_create_file("base_eeprom", S_IRUSR, priv->debug.debugfs_phy, priv, &fops_base_eeprom); + debugfs_create_file("modal_eeprom", S_IRUSR, priv->debug.debugfs_phy, + priv, &fops_modal_eeprom); return 0; } -- cgit v1.2.3-58-ga151 From 75d80cadf4ceb238e55487ff6d3f9a0706e1028d Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 28 Apr 2011 11:12:10 +0200 Subject: iwlagn: fix tx power initialization Since commit f844a709a7d8f8be61a571afc31dfaca9e779621 Author: Stanislaw Gruszka Date: Fri Jan 28 16:47:44 2011 +0100 iwlwifi: do not set tx power when channel is changing we set device tx power during initialization to priv->tx_power_next, which itself is initialized to minimum power. That changed default behaviour of driver. Previously we initialized device to transmit at maximum available power by default. Patch change again to previous behaviour and cleanup tx power initialization. Fortunately this is not critical fix, as mac80211 layer setup tx power lately to 14dB, hence device does not operate at minimal transmit power all the time. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ------ drivers/net/wireless/iwlwifi/iwl-core.c | 9 +++++++-- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 7 ------- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a4f1009cb137..a4ec524f4655 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3444,12 +3444,6 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; } - /* Set the tx_power_user_lmt to the lowest power level - * this value will get overwritten by channel max power avg - * from eeprom */ - priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN; - priv->tx_power_next = IWLAGN_TX_POWER_TARGET_POWER_MIN; - ret = iwl_init_channel_map(priv); if (ret) { IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 46d69657407c..af72fd51ea74 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -135,6 +135,7 @@ int iwlcore_init_geos(struct iwl_priv *priv) struct ieee80211_channel *geo_ch; struct ieee80211_rate *rates; int i = 0; + s8 max_tx_power = IWLAGN_TX_POWER_TARGET_POWER_MIN; if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { @@ -208,8 +209,8 @@ int iwlcore_init_geos(struct iwl_priv *priv) geo_ch->flags |= ch->ht40_extension_channel; - if (ch->max_power_avg > priv->tx_power_device_lmt) - priv->tx_power_device_lmt = ch->max_power_avg; + if (ch->max_power_avg > max_tx_power) + max_tx_power = ch->max_power_avg; } else { geo_ch->flags |= IEEE80211_CHAN_DISABLED; } @@ -222,6 +223,10 @@ int iwlcore_init_geos(struct iwl_priv *priv) geo_ch->flags); } + priv->tx_power_device_lmt = max_tx_power; + priv->tx_power_user_lmt = max_tx_power; + priv->tx_power_next = max_tx_power; + if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->cfg->sku & IWL_SKU_A) { IWL_INFO(priv, "Incorrectly detected BG card as ABG. " diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 402733638f50..1e1a2d8df1da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -711,13 +711,6 @@ int iwl_init_channel_map(struct iwl_priv *priv) flags & EEPROM_CHANNEL_RADAR)) ? "" : "not "); - /* Set the tx_power_user_lmt to the highest power - * supported by any channel */ - if (eeprom_ch_info[ch].max_power_avg > - priv->tx_power_user_lmt) - priv->tx_power_user_lmt = - eeprom_ch_info[ch].max_power_avg; - ch_info++; } } -- cgit v1.2.3-58-ga151 From ab42b4041707f075533845ecb320c7a1c5621f1b Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 28 Apr 2011 11:51:24 +0200 Subject: iwlegacy: remove duplicate initialization in iwl4956_down() Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl4965-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c index f8870543d68f..038738355ab7 100644 --- a/drivers/net/wireless/iwlegacy/iwl4965-base.c +++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c @@ -2139,7 +2139,7 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv); static void __iwl4965_down(struct iwl_priv *priv) { unsigned long flags; - int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status); + int exit_pending; IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); -- cgit v1.2.3-58-ga151 From a078a1fde11b350161e7db2c44353dfae7749212 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 28 Apr 2011 11:51:25 +0200 Subject: iwlegacy: enable only rfkill interrupt when device is down Add two below iwlwifi commits to iwlegacy: commit 554d1d027b19265c4aa3f718b3126d2b86e09a08 Author: Stanislaw Gruszka Date: Thu Dec 23 12:38:21 2010 +0100 iwlagn: enable only rfkill interrupt when device is down commit 3dd823e6b86407aed1a025041d8f1df77e43a9c8 Author: Don Fry Date: Sun Feb 6 09:29:45 2011 -0800 iwlagn: Re-enable RF_KILL interrupt when down Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-helpers.h | 6 ++++++ drivers/net/wireless/iwlegacy/iwl4965-base.c | 12 ++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-helpers.h b/drivers/net/wireless/iwlegacy/iwl-helpers.h index 02132e755831..a6effdae63f9 100644 --- a/drivers/net/wireless/iwlegacy/iwl-helpers.h +++ b/drivers/net/wireless/iwlegacy/iwl-helpers.h @@ -149,6 +149,12 @@ static inline void iwl_legacy_disable_interrupts(struct iwl_priv *priv) IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); } +static inline void iwl_legacy_enable_rfkill_int(struct iwl_priv *priv) +{ + IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); + iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); +} + static inline void iwl_legacy_enable_interrupts(struct iwl_priv *priv) { IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c index 038738355ab7..58a2e63bd0bc 100644 --- a/drivers/net/wireless/iwlegacy/iwl4965-base.c +++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c @@ -1072,6 +1072,9 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv) /* only Re-enable if diabled by irq */ if (test_bit(STATUS_INT_ENABLED, &priv->status)) iwl_legacy_enable_interrupts(priv); + /* Re-enable RF_KILL if it occurred */ + else if (handled & CSR_INT_BIT_RF_KILL) + iwl_legacy_enable_rfkill_int(priv); #ifdef CONFIG_IWLWIFI_LEGACY_DEBUG if (iwl_legacy_get_debug_level(priv) & (IWL_DL_ISR)) { @@ -2624,9 +2627,10 @@ void iwl4965_mac_stop(struct ieee80211_hw *hw) flush_workqueue(priv->workqueue); - /* enable interrupts again in order to receive rfkill changes */ + /* User space software may expect getting rfkill changes + * even if interface is down */ iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - iwl_legacy_enable_interrupts(priv); + iwl_legacy_enable_rfkill_int(priv); IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -3406,14 +3410,14 @@ iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * 8. Enable interrupts and read RFKILL state *********************************************/ - /* enable interrupts if needed: hw bug w/a */ + /* enable rfkill interrupt: hw bug w/a */ pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd); } - iwl_legacy_enable_interrupts(priv); + iwl_legacy_enable_rfkill_int(priv); /* If platform's RF_KILL switch is NOT set to KILL */ if (iwl_read32(priv, CSR_GP_CNTRL) & -- cgit v1.2.3-58-ga151 From 3e41de85f8e3419257df62dd6fe6bdd95a1fdcab Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 28 Apr 2011 11:51:26 +0200 Subject: iwlegacy: simplify init geos Don't need to use conditional as ch->band is already assigned to IEEE80211_BAND_5GHZ or IEEE80211_BAND_2GHZ Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c index 2b08efb3b658..82201aca8e99 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.c +++ b/drivers/net/wireless/iwlegacy/iwl-core.c @@ -211,10 +211,7 @@ int iwl_legacy_init_geos(struct iwl_priv *priv) if (!iwl_legacy_is_channel_valid(ch)) continue; - if (iwl_legacy_is_channel_a_band(ch)) - sband = &priv->bands[IEEE80211_BAND_5GHZ]; - else - sband = &priv->bands[IEEE80211_BAND_2GHZ]; + sband = &priv->bands[ch->band]; geo_ch = &sband->channels[sband->n_channels++]; -- cgit v1.2.3-58-ga151 From 8eb0ac70a7a53cf851027d022616c01591ee4c33 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 28 Apr 2011 11:51:27 +0200 Subject: iwlegacy: remove unneeded disable_hw_scan check We never set STATUS_SCANNING in softwre scanning mode, disable_hw_scan check is unneeded. Correct debug message while at it. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c index 82201aca8e99..9676b3d5b91c 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.c +++ b/drivers/net/wireless/iwlegacy/iwl-core.c @@ -2114,10 +2114,9 @@ int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed) IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", channel->hw_value, changed); - if (unlikely(!priv->cfg->mod_params->disable_hw_scan && - test_bit(STATUS_SCANNING, &priv->status))) { + if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { scan_active = 1; - IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); + IWL_DEBUG_MAC80211(priv, "scan active\n"); } if (changed & (IEEE80211_CONF_CHANGE_SMPS | -- cgit v1.2.3-58-ga151 From 5855c7d81530aaf82293aaa252c4f9ff69ef33f9 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 28 Apr 2011 11:51:28 +0200 Subject: iwlegacy: remove unneeded __packed struct iwl_queue is not part of firmware interface, so __packed is not needed. Remove it since is may affect performance. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-dev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h index 9ee849d669f3..36c01aa3b7c2 100644 --- a/drivers/net/wireless/iwlegacy/iwl-dev.h +++ b/drivers/net/wireless/iwlegacy/iwl-dev.h @@ -134,7 +134,7 @@ struct iwl_queue { * space more than this */ int high_mark; /* high watermark, stop queue if free * space less than this */ -} __packed; +}; /* One for each TFD */ struct iwl_tx_info { -- cgit v1.2.3-58-ga151 From 7a55237ac9f133c1d48fbe54d22dc2bd715e7b51 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 28 Apr 2011 11:51:29 +0200 Subject: iwlegacy: remove scan_tx_antennas Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-4965-lib.c | 3 --- drivers/net/wireless/iwlegacy/iwl-core.h | 1 - 2 files changed, 4 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c index 5a8a3cce27bc..7e5e85a017b5 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c @@ -955,9 +955,6 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) if (priv->cfg->scan_rx_antennas[band]) rx_ant = priv->cfg->scan_rx_antennas[band]; - if (priv->cfg->scan_tx_antennas[band]) - scan_tx_antennas = priv->cfg->scan_tx_antennas[band]; - priv->scan_tx_ant[band] = iwl4965_toggle_tx_ant(priv, priv->scan_tx_ant[band], scan_tx_antennas); diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h index f03b463e4378..bc66c604106c 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.h +++ b/drivers/net/wireless/iwlegacy/iwl-core.h @@ -287,7 +287,6 @@ struct iwl_cfg { struct iwl_base_params *base_params; /* params likely to change within a device family */ u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; - u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; enum iwl_led_mode led_mode; }; -- cgit v1.2.3-58-ga151 From 93fd74e3d5471c4c91a239599a88fa7e52686e71 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 28 Apr 2011 11:51:30 +0200 Subject: iwlegacy: comment typo fix diable -> disable Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-core.c | 2 +- drivers/net/wireless/iwlegacy/iwl4965-base.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c index 9676b3d5b91c..553c91b3a258 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.c +++ b/drivers/net/wireless/iwlegacy/iwl-core.c @@ -2642,7 +2642,7 @@ unplugged: none: /* re-enable interrupts here since we don't have anything to service. */ - /* only Re-enable if diabled by irq */ + /* only Re-enable if disabled by irq */ if (test_bit(STATUS_INT_ENABLED, &priv->status)) iwl_legacy_enable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c index 58a2e63bd0bc..2da60702fab2 100644 --- a/drivers/net/wireless/iwlegacy/iwl4965-base.c +++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c @@ -1069,7 +1069,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv) } /* Re-enable all interrupts */ - /* only Re-enable if diabled by irq */ + /* only Re-enable if disabled by irq */ if (test_bit(STATUS_INT_ENABLED, &priv->status)) iwl_legacy_enable_interrupts(priv); /* Re-enable RF_KILL if it occurred */ -- cgit v1.2.3-58-ga151 From 81e63263aa3c5bfa64aa3206f4be3e59afc1c183 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 28 Apr 2011 11:51:31 +0200 Subject: iwlegacy: fix enqueue hcmd race conditions We mark command as huge by using meta->flags from other (non huge) command, but flags can be possibly overridden, when non huge command is enqueued, what can lead to: WARNING: at lib/dma-debug.c:696 dma_debug_device_change+0x1a3/0x1f0() DMA-API: device driver has pending DMA allocations while released from device [count=1] To fix introduce additional CMD_MAPPED to mark command as mapped and serialize iwl_enqueue_hcmd() with iwl_tx_cmd_complete() using hcmd_lock. Serialization will also fix possible race conditions, because q->read_ptr, q->write_ptr are modified/used in parallel. Do not change callback, I did (and fixed) that mistake in iwlagn. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-dev.h | 1 + drivers/net/wireless/iwlegacy/iwl-tx.c | 52 +++++++++++++++------------------ 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h index 36c01aa3b7c2..df19d5c69e7f 100644 --- a/drivers/net/wireless/iwlegacy/iwl-dev.h +++ b/drivers/net/wireless/iwlegacy/iwl-dev.h @@ -290,6 +290,7 @@ enum { CMD_SIZE_HUGE = (1 << 0), CMD_ASYNC = (1 << 1), CMD_WANT_SKB = (1 << 2), + CMD_MAPPED = (1 << 3), }; #define DEF_CMD_PAYLOAD_SIZE 320 diff --git a/drivers/net/wireless/iwlegacy/iwl-tx.c b/drivers/net/wireless/iwlegacy/iwl-tx.c index a227773cb384..4fff995c6f3e 100644 --- a/drivers/net/wireless/iwlegacy/iwl-tx.c +++ b/drivers/net/wireless/iwlegacy/iwl-tx.c @@ -146,33 +146,32 @@ void iwl_legacy_cmd_queue_unmap(struct iwl_priv *priv) { struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; struct iwl_queue *q = &txq->q; - bool huge = false; int i; if (q->n_bd == 0) return; while (q->read_ptr != q->write_ptr) { - /* we have no way to tell if it is a huge cmd ATM */ i = iwl_legacy_get_cmd_index(q, q->read_ptr, 0); - if (txq->meta[i].flags & CMD_SIZE_HUGE) - huge = true; - else + if (txq->meta[i].flags & CMD_MAPPED) { pci_unmap_single(priv->pci_dev, dma_unmap_addr(&txq->meta[i], mapping), dma_unmap_len(&txq->meta[i], len), PCI_DMA_BIDIRECTIONAL); + txq->meta[i].flags = 0; + } q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd); } - if (huge) { - i = q->n_window; + i = q->n_window; + if (txq->meta[i].flags & CMD_MAPPED) { pci_unmap_single(priv->pci_dev, dma_unmap_addr(&txq->meta[i], mapping), dma_unmap_len(&txq->meta[i], len), PCI_DMA_BIDIRECTIONAL); + txq->meta[i].flags = 0; } } EXPORT_SYMBOL(iwl_legacy_cmd_queue_unmap); @@ -467,29 +466,27 @@ int iwl_legacy_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) return -EIO; } + spin_lock_irqsave(&priv->hcmd_lock, flags); + if (iwl_legacy_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { - IWL_ERR(priv, "No space in command queue\n"); - IWL_ERR(priv, "Restarting adapter due to queue full\n"); + spin_unlock_irqrestore(&priv->hcmd_lock, flags); + + IWL_ERR(priv, "Restarting adapter due to command queue full\n"); queue_work(priv->workqueue, &priv->restart); return -ENOSPC; } - spin_lock_irqsave(&priv->hcmd_lock, flags); - - /* If this is a huge cmd, mark the huge flag also on the meta.flags - * of the _original_ cmd. This is used for DMA mapping clean up. - */ - if (cmd->flags & CMD_SIZE_HUGE) { - idx = iwl_legacy_get_cmd_index(q, q->write_ptr, 0); - txq->meta[idx].flags = CMD_SIZE_HUGE; - } - idx = iwl_legacy_get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); out_cmd = txq->cmd[idx]; out_meta = &txq->meta[idx]; + if (WARN_ON(out_meta->flags & CMD_MAPPED)) { + spin_unlock_irqrestore(&priv->hcmd_lock, flags); + return -ENOSPC; + } + memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ - out_meta->flags = cmd->flags; + out_meta->flags = cmd->flags | CMD_MAPPED; if (cmd->flags & CMD_WANT_SKB) out_meta->source = cmd; if (cmd->flags & CMD_ASYNC) @@ -610,6 +607,7 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; + unsigned long flags; /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced @@ -623,14 +621,6 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) return; } - /* If this is a huge cmd, clear the huge flag on the meta.flags - * of the _original_ cmd. So that iwl_legacy_cmd_queue_free won't unmap - * the DMA buffer for the scan (huge) command. - */ - if (huge) { - cmd_index = iwl_legacy_get_cmd_index(&txq->q, index, 0); - txq->meta[cmd_index].flags = 0; - } cmd_index = iwl_legacy_get_cmd_index(&txq->q, index, huge); cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; @@ -647,6 +637,8 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) } else if (meta->callback) meta->callback(priv, cmd, pkt); + spin_lock_irqsave(&priv->hcmd_lock, flags); + iwl_legacy_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); if (!(meta->flags & CMD_ASYNC)) { @@ -655,6 +647,10 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) iwl_legacy_get_cmd_string(cmd->hdr.cmd)); wake_up_interruptible(&priv->wait_command_queue); } + + /* Mark as unmapped */ meta->flags = 0; + + spin_unlock_irqrestore(&priv->hcmd_lock, flags); } EXPORT_SYMBOL(iwl_legacy_tx_cmd_complete); -- cgit v1.2.3-58-ga151 From 28a6e577c65cc317fed5265efc43ce9282928bd4 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 28 Apr 2011 11:51:32 +0200 Subject: iwlegacy: more priv->mutex serialization Check status bits with mutex taken, because when we wait for mutex unlock, status can change. Patch should also make remaining sync commands be send with priv->mutex taken. That will prevent execute these commands when we are currently reset firmware, what could possibly cause troubles. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-core.c | 8 +++++--- drivers/net/wireless/iwlegacy/iwl3945-base.c | 21 +++++++++++++-------- drivers/net/wireless/iwlegacy/iwl4965-base.c | 28 ++++++++++++++++------------ 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c index 553c91b3a258..0073f9239197 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.c +++ b/drivers/net/wireless/iwlegacy/iwl-core.c @@ -2429,11 +2429,13 @@ void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); - if (!iwl_legacy_is_alive(priv)) - return; - mutex_lock(&priv->mutex); + if (!iwl_legacy_is_alive(priv)) { + mutex_unlock(&priv->mutex); + return; + } + if (changes & BSS_CHANGED_QOS) { unsigned long flags; diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c index cc7ebcee60e5..5bdcc36f543f 100644 --- a/drivers/net/wireless/iwlegacy/iwl3945-base.c +++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c @@ -2748,11 +2748,12 @@ static void iwl3945_bg_init_alive_start(struct work_struct *data) struct iwl_priv *priv = container_of(data, struct iwl_priv, init_alive_start.work); + mutex_lock(&priv->mutex); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; + goto out; - mutex_lock(&priv->mutex); iwl3945_init_alive_start(priv); +out: mutex_unlock(&priv->mutex); } @@ -2761,11 +2762,12 @@ static void iwl3945_bg_alive_start(struct work_struct *data) struct iwl_priv *priv = container_of(data, struct iwl_priv, alive_start.work); + mutex_lock(&priv->mutex); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; + goto out; - mutex_lock(&priv->mutex); iwl3945_alive_start(priv); +out: mutex_unlock(&priv->mutex); } @@ -2995,10 +2997,12 @@ static void iwl3945_bg_restart(struct work_struct *data) } else { iwl3945_down(priv); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + mutex_lock(&priv->mutex); + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { + mutex_unlock(&priv->mutex); return; + } - mutex_lock(&priv->mutex); __iwl3945_up(priv); mutex_unlock(&priv->mutex); } @@ -3009,11 +3013,12 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data) struct iwl_priv *priv = container_of(data, struct iwl_priv, rx_replenish); + mutex_lock(&priv->mutex); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; + goto out; - mutex_lock(&priv->mutex); iwl3945_rx_replenish(priv); +out: mutex_unlock(&priv->mutex); } diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c index 2da60702fab2..55851ac3add9 100644 --- a/drivers/net/wireless/iwlegacy/iwl4965-base.c +++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c @@ -2404,11 +2404,12 @@ static void iwl4965_bg_init_alive_start(struct work_struct *data) struct iwl_priv *priv = container_of(data, struct iwl_priv, init_alive_start.work); + mutex_lock(&priv->mutex); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; + goto out; - mutex_lock(&priv->mutex); priv->cfg->ops->lib->init_alive_start(priv); +out: mutex_unlock(&priv->mutex); } @@ -2417,11 +2418,12 @@ static void iwl4965_bg_alive_start(struct work_struct *data) struct iwl_priv *priv = container_of(data, struct iwl_priv, alive_start.work); + mutex_lock(&priv->mutex); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; + goto out; - mutex_lock(&priv->mutex); iwl4965_alive_start(priv); +out: mutex_unlock(&priv->mutex); } @@ -2471,10 +2473,12 @@ static void iwl4965_bg_restart(struct work_struct *data) } else { iwl4965_down(priv); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + mutex_lock(&priv->mutex); + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { + mutex_unlock(&priv->mutex); return; + } - mutex_lock(&priv->mutex); __iwl4965_up(priv); mutex_unlock(&priv->mutex); } @@ -2851,21 +2855,22 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); + mutex_lock(&priv->mutex); + if (iwl_legacy_is_rfkill(priv)) - goto out_exit; + goto out; if (test_bit(STATUS_EXIT_PENDING, &priv->status) || test_bit(STATUS_SCANNING, &priv->status)) - goto out_exit; + goto out; if (!iwl_legacy_is_associated_ctx(ctx)) - goto out_exit; + goto out; /* channel switch in progress */ if (priv->switch_rxon.switch_in_progress == true) - goto out_exit; + goto out; - mutex_lock(&priv->mutex); if (priv->cfg->ops->lib->set_channel_switch) { ch = channel->hw_value; @@ -2921,7 +2926,6 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw, } out: mutex_unlock(&priv->mutex); -out_exit: if (!priv->switch_rxon.switch_in_progress) ieee80211_chswitch_done(ctx->vif, false); IWL_DEBUG_MAC80211(priv, "leave\n"); -- cgit v1.2.3-58-ga151 From 22450902e4a13479acf6f4e93475af7ca1829d92 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 28 Apr 2011 11:51:33 +0200 Subject: iwlegacy: remove sync_cmd_mutex We now use priv->mutex to serialize sync command, remove old priv->sync_cmd_mutex and add assertion that priv->mutex must be locked. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-dev.h | 1 - drivers/net/wireless/iwlegacy/iwl-hcmd.c | 4 ++-- drivers/net/wireless/iwlegacy/iwl3945-base.c | 1 - drivers/net/wireless/iwlegacy/iwl4965-base.c | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h index df19d5c69e7f..2d87dba2cfa3 100644 --- a/drivers/net/wireless/iwlegacy/iwl-dev.h +++ b/drivers/net/wireless/iwlegacy/iwl-dev.h @@ -1077,7 +1077,6 @@ struct iwl_priv { spinlock_t hcmd_lock; /* protect hcmd */ spinlock_t reg_lock; /* protect hw register access */ struct mutex mutex; - struct mutex sync_cmd_mutex; /* enable serialization of sync commands */ /* basic pci-network driver stuff */ struct pci_dev *pci_dev; diff --git a/drivers/net/wireless/iwlegacy/iwl-hcmd.c b/drivers/net/wireless/iwlegacy/iwl-hcmd.c index 9d721cbda5bb..62b4b09122cb 100644 --- a/drivers/net/wireless/iwlegacy/iwl-hcmd.c +++ b/drivers/net/wireless/iwlegacy/iwl-hcmd.c @@ -145,6 +145,8 @@ int iwl_legacy_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) int cmd_idx; int ret; + lockdep_assert_held(&priv->mutex); + BUG_ON(cmd->flags & CMD_ASYNC); /* A synchronous command can not have a callback set. */ @@ -152,7 +154,6 @@ int iwl_legacy_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", iwl_legacy_get_cmd_string(cmd->id)); - mutex_lock(&priv->sync_cmd_mutex); set_bit(STATUS_HCMD_ACTIVE, &priv->status); IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", @@ -224,7 +225,6 @@ fail: cmd->reply_page = 0; } out: - mutex_unlock(&priv->sync_cmd_mutex); return ret; } EXPORT_SYMBOL(iwl_legacy_send_cmd_sync); diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c index 5bdcc36f543f..0ee6be6a9c5d 100644 --- a/drivers/net/wireless/iwlegacy/iwl3945-base.c +++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c @@ -3815,7 +3815,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) INIT_LIST_HEAD(&priv->free_frames); mutex_init(&priv->mutex); - mutex_init(&priv->sync_cmd_mutex); priv->ieee_channels = NULL; priv->ieee_rates = NULL; diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c index 55851ac3add9..f781b7e225b4 100644 --- a/drivers/net/wireless/iwlegacy/iwl4965-base.c +++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c @@ -3124,7 +3124,6 @@ static int iwl4965_init_drv(struct iwl_priv *priv) INIT_LIST_HEAD(&priv->free_frames); mutex_init(&priv->mutex); - mutex_init(&priv->sync_cmd_mutex); priv->ieee_channels = NULL; priv->ieee_rates = NULL; -- cgit v1.2.3-58-ga151 From d244f21e79162b829c9af09845421d9b4fac4253 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Thu, 28 Apr 2011 16:14:05 +0530 Subject: ath9k_htc: Revamp LED management Remove all the convoluted hacks in the driver and simplify things by making use of mac80211's LED triggers. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 65 ++++----- drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 188 +++++--------------------- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 22 +++ drivers/net/wireless/ath/ath9k/htc_drv_main.c | 6 +- 4 files changed, 85 insertions(+), 196 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 6bb71e311a4b..dfc7a982fc7e 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -385,25 +385,6 @@ static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, #define ATH_LED_PIN_9287 10 #define ATH_LED_PIN_9271 15 #define ATH_LED_PIN_7010 12 -#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ -#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ - -enum ath_led_type { - ATH_LED_RADIO, - ATH_LED_ASSOC, - ATH_LED_TX, - ATH_LED_RX -}; - -struct ath_led { - struct ath9k_htc_priv *priv; - struct led_classdev led_cdev; - enum ath_led_type led_type; - struct delayed_work brightness_work; - char name[32]; - bool registered; - int brightness; -}; #define BSTUCK_THRESHOLD 10 @@ -437,14 +418,11 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv); #define OP_INVALID BIT(0) #define OP_SCANNING BIT(1) -#define OP_LED_ASSOCIATED BIT(2) -#define OP_LED_ON BIT(3) -#define OP_ENABLE_BEACON BIT(4) -#define OP_LED_DEINIT BIT(5) -#define OP_BT_PRIORITY_DETECTED BIT(6) -#define OP_BT_SCAN BIT(7) -#define OP_ANI_RUNNING BIT(8) -#define OP_TSF_RESET BIT(9) +#define OP_ENABLE_BEACON BIT(2) +#define OP_BT_PRIORITY_DETECTED BIT(3) +#define OP_BT_SCAN BIT(4) +#define OP_ANI_RUNNING BIT(5) +#define OP_TSF_RESET BIT(6) struct ath9k_htc_priv { struct device *dev; @@ -504,15 +482,13 @@ struct ath9k_htc_priv { bool ps_enabled; bool ps_idle; - struct ath_led radio_led; - struct ath_led assoc_led; - struct ath_led tx_led; - struct ath_led rx_led; - struct delayed_work ath9k_led_blink_work; - int led_on_duration; - int led_off_duration; - int led_on_cnt; - int led_off_cnt; +#ifdef CONFIG_MAC80211_LEDS + enum led_brightness brightness; + bool led_registered; + char led_name[32]; + struct led_classdev led_cdev; + struct work_struct led_work; +#endif int beaconq; int cabq; @@ -597,9 +573,24 @@ void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); void ath9k_htc_radio_enable(struct ieee80211_hw *hw); void ath9k_htc_radio_disable(struct ieee80211_hw *hw); -void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv); + +#ifdef CONFIG_MAC80211_LEDS void ath9k_init_leds(struct ath9k_htc_priv *priv); void ath9k_deinit_leds(struct ath9k_htc_priv *priv); +void ath9k_led_work(struct work_struct *work); +#else +static inline void ath9k_init_leds(struct ath9k_htc_priv *priv) +{ +} + +static inline void ath9k_deinit_leds(struct ath9k_htc_priv *priv) +{ +} + +static inline void ath9k_led_work(struct work_struct *work) +{ +} +#endif int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, u16 devid, char *product, u32 drv_info); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 26ede1daa304..af57fe5aab98 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -154,140 +154,41 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv) /* LED */ /*******/ -static void ath9k_led_blink_work(struct work_struct *work) +#ifdef CONFIG_MAC80211_LEDS +void ath9k_led_work(struct work_struct *work) { - struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, - ath9k_led_blink_work.work); - - if (!(priv->op_flags & OP_LED_ASSOCIATED)) - return; + struct ath9k_htc_priv *priv = container_of(work, + struct ath9k_htc_priv, + led_work); - if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) || - (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); - else - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, - (priv->op_flags & OP_LED_ON) ? 1 : 0); - - ieee80211_queue_delayed_work(priv->hw, - &priv->ath9k_led_blink_work, - (priv->op_flags & OP_LED_ON) ? - msecs_to_jiffies(priv->led_off_duration) : - msecs_to_jiffies(priv->led_on_duration)); - - priv->led_on_duration = priv->led_on_cnt ? - max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) : - ATH_LED_ON_DURATION_IDLE; - priv->led_off_duration = priv->led_off_cnt ? - max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) : - ATH_LED_OFF_DURATION_IDLE; - priv->led_on_cnt = priv->led_off_cnt = 0; - - if (priv->op_flags & OP_LED_ON) - priv->op_flags &= ~OP_LED_ON; - else - priv->op_flags |= OP_LED_ON; -} - -static void ath9k_led_brightness_work(struct work_struct *work) -{ - struct ath_led *led = container_of(work, struct ath_led, - brightness_work.work); - struct ath9k_htc_priv *priv = led->priv; - - switch (led->brightness) { - case LED_OFF: - if (led->led_type == ATH_LED_ASSOC || - led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, - (led->led_type == ATH_LED_RADIO)); - priv->op_flags &= ~OP_LED_ASSOCIATED; - if (led->led_type == ATH_LED_RADIO) - priv->op_flags &= ~OP_LED_ON; - } else { - priv->led_off_cnt++; - } - break; - case LED_FULL: - if (led->led_type == ATH_LED_ASSOC) { - priv->op_flags |= OP_LED_ASSOCIATED; - ieee80211_queue_delayed_work(priv->hw, - &priv->ath9k_led_blink_work, 0); - } else if (led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); - priv->op_flags |= OP_LED_ON; - } else { - priv->led_on_cnt++; - } - break; - default: - break; - } + ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, + (priv->brightness == LED_OFF)); } static void ath9k_led_brightness(struct led_classdev *led_cdev, enum led_brightness brightness) { - struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); - struct ath9k_htc_priv *priv = led->priv; - - led->brightness = brightness; - if (!(priv->op_flags & OP_LED_DEINIT)) - ieee80211_queue_delayed_work(priv->hw, - &led->brightness_work, 0); -} + struct ath9k_htc_priv *priv = container_of(led_cdev, + struct ath9k_htc_priv, + led_cdev); -void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv) -{ - cancel_delayed_work_sync(&priv->radio_led.brightness_work); - cancel_delayed_work_sync(&priv->assoc_led.brightness_work); - cancel_delayed_work_sync(&priv->tx_led.brightness_work); - cancel_delayed_work_sync(&priv->rx_led.brightness_work); -} - -static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led, - char *trigger) -{ - int ret; - - led->priv = priv; - led->led_cdev.name = led->name; - led->led_cdev.default_trigger = trigger; - led->led_cdev.brightness_set = ath9k_led_brightness; - - ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev); - if (ret) - ath_err(ath9k_hw_common(priv->ah), - "Failed to register led:%s", led->name); - else - led->registered = 1; - - INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work); - - return ret; -} - -static void ath9k_unregister_led(struct ath_led *led) -{ - if (led->registered) { - led_classdev_unregister(&led->led_cdev); - led->registered = 0; - } + /* Not locked, but it's just a tiny green light..*/ + priv->brightness = brightness; + ieee80211_queue_work(priv->hw, &priv->led_work); } void ath9k_deinit_leds(struct ath9k_htc_priv *priv) { - priv->op_flags |= OP_LED_DEINIT; - ath9k_unregister_led(&priv->assoc_led); - priv->op_flags &= ~OP_LED_ASSOCIATED; - ath9k_unregister_led(&priv->tx_led); - ath9k_unregister_led(&priv->rx_led); - ath9k_unregister_led(&priv->radio_led); + if (!priv->led_registered) + return; + + ath9k_led_brightness(&priv->led_cdev, LED_OFF); + led_classdev_unregister(&priv->led_cdev); + cancel_work_sync(&priv->led_work); } void ath9k_init_leds(struct ath9k_htc_priv *priv) { - char *trigger; int ret; if (AR_SREV_9287(priv->ah)) @@ -305,48 +206,21 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv) /* LED off, active low */ ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); - INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work); - - trigger = ieee80211_get_radio_led_name(priv->hw); - snprintf(priv->radio_led.name, sizeof(priv->radio_led.name), - "ath9k-%s::radio", wiphy_name(priv->hw->wiphy)); - ret = ath9k_register_led(priv, &priv->radio_led, trigger); - priv->radio_led.led_type = ATH_LED_RADIO; - if (ret) - goto fail; - - trigger = ieee80211_get_assoc_led_name(priv->hw); - snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name), - "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy)); - ret = ath9k_register_led(priv, &priv->assoc_led, trigger); - priv->assoc_led.led_type = ATH_LED_ASSOC; - if (ret) - goto fail; - - trigger = ieee80211_get_tx_led_name(priv->hw); - snprintf(priv->tx_led.name, sizeof(priv->tx_led.name), - "ath9k-%s::tx", wiphy_name(priv->hw->wiphy)); - ret = ath9k_register_led(priv, &priv->tx_led, trigger); - priv->tx_led.led_type = ATH_LED_TX; - if (ret) - goto fail; - - trigger = ieee80211_get_rx_led_name(priv->hw); - snprintf(priv->rx_led.name, sizeof(priv->rx_led.name), - "ath9k-%s::rx", wiphy_name(priv->hw->wiphy)); - ret = ath9k_register_led(priv, &priv->rx_led, trigger); - priv->rx_led.led_type = ATH_LED_RX; - if (ret) - goto fail; - - priv->op_flags &= ~OP_LED_DEINIT; + snprintf(priv->led_name, sizeof(priv->led_name), + "ath9k_htc-%s", wiphy_name(priv->hw->wiphy)); + priv->led_cdev.name = priv->led_name; + priv->led_cdev.brightness_set = ath9k_led_brightness; - return; + ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &priv->led_cdev); + if (ret < 0) + return; -fail: - cancel_delayed_work_sync(&priv->ath9k_led_blink_work); - ath9k_deinit_leds(priv); + INIT_WORK(&priv->led_work, ath9k_led_work); + priv->led_registered = true; + + return; } +#endif /*******************/ /* Rfkill */ diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index d2dd5a63e10a..bfdc8a887183 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -117,6 +117,21 @@ static struct ieee80211_rate ath9k_legacy_rates[] = { RATE(540, 0x0c, 0), }; +#ifdef CONFIG_MAC80211_LEDS +static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { + { .throughput = 0 * 1024, .blink_time = 334 }, + { .throughput = 1 * 1024, .blink_time = 260 }, + { .throughput = 5 * 1024, .blink_time = 220 }, + { .throughput = 10 * 1024, .blink_time = 190 }, + { .throughput = 20 * 1024, .blink_time = 170 }, + { .throughput = 50 * 1024, .blink_time = 150 }, + { .throughput = 70 * 1024, .blink_time = 130 }, + { .throughput = 100 * 1024, .blink_time = 110 }, + { .throughput = 200 * 1024, .blink_time = 80 }, + { .throughput = 300 * 1024, .blink_time = 50 }, +}; +#endif + static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) { int time_left; @@ -863,6 +878,13 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, if (error != 0) goto err_rx; +#ifdef CONFIG_MAC80211_LEDS + /* must be initialized before ieee80211_register_hw */ + priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw, + IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_htc_tpt_blink, + ARRAY_SIZE(ath9k_htc_tpt_blink)); +#endif + /* Register with mac80211 */ error = ieee80211_register_hw(hw); if (error) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index e9746e8ff8dd..5aa104fe7eeb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1003,9 +1003,11 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) /* Cancel all the running timers/work .. */ cancel_work_sync(&priv->fatal_work); cancel_work_sync(&priv->ps_work); - cancel_delayed_work_sync(&priv->ath9k_led_blink_work); + +#ifdef CONFIG_MAC80211_LEDS + cancel_work_sync(&priv->led_work); +#endif ath9k_htc_stop_ani(priv); - ath9k_led_stop_brightness(priv); mutex_lock(&priv->mutex); -- cgit v1.2.3-58-ga151 From ff776cecec92fe7cac4a9ce1919576ad6e737e08 Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Thu, 28 Apr 2011 17:34:48 +0530 Subject: mwl8k: Reducing extra_tx_headroom for tx optimization in AP mode The tx_headroom required for mwl8k driver is 32 bytes and it can use the space for 802.11 header received from mac80211. mwl8k considers the smallest 802.11 frame (CTS2self of 10 bytes) that can be received from mac80211 to compute the extra_tx_headroom as 22 (32 - 10) bytes. When the wireless interface is part of bridge, this extra_tx_headroom requirement results in a memcpy in mac80211 (in function pskb_expand_head) for all the data frames needing L2 forwarding/bridging, when NET_SKB_PAD is defined as 32. This patch reduces the extra_tx_headroom by 8 bytes so that memcpy of data frames in mac80211 is avoided in this case. The resize will be required in driver for frames with 802.11 header size of less than 18 bytes. Signed-off-by: Yogesh Ashok Powar Signed-off-by: Pradeep Nemavat Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 8a1b26255f03..9f5ecef297e5 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -781,8 +781,10 @@ static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos) skb_pull(skb, sizeof(*tr) - hdrlen); } +#define REDUCED_TX_HEADROOM 8 + static void -mwl8k_add_dma_header(struct sk_buff *skb, int tail_pad) +mwl8k_add_dma_header(struct mwl8k_priv *priv, struct sk_buff *skb, int tail_pad) { struct ieee80211_hdr *wh; int hdrlen; @@ -798,6 +800,22 @@ mwl8k_add_dma_header(struct sk_buff *skb, int tail_pad) wh = (struct ieee80211_hdr *)skb->data; hdrlen = ieee80211_hdrlen(wh->frame_control); + + /* + * Check if skb_resize is required because of + * tx_headroom adjustment. + */ + if (priv->ap_fw && (hdrlen < (sizeof(struct ieee80211_cts) + + REDUCED_TX_HEADROOM))) { + if (pskb_expand_head(skb, REDUCED_TX_HEADROOM, 0, GFP_ATOMIC)) { + + wiphy_err(priv->hw->wiphy, + "Failed to reallocate TX buffer\n"); + return; + } + skb->truesize += REDUCED_TX_HEADROOM; + } + reqd_hdrlen = sizeof(*tr); if (hdrlen != reqd_hdrlen) @@ -820,7 +838,8 @@ mwl8k_add_dma_header(struct sk_buff *skb, int tail_pad) tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr) + tail_pad); } -static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb) +static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, + struct sk_buff *skb) { struct ieee80211_hdr *wh; struct ieee80211_tx_info *tx_info; @@ -861,7 +880,7 @@ static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb) break; } } - mwl8k_add_dma_header(skb, data_pad); + mwl8k_add_dma_header(priv, skb, data_pad); } /* @@ -1816,9 +1835,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) mgmtframe = true; if (priv->ap_fw) - mwl8k_encapsulate_tx_frame(skb); + mwl8k_encapsulate_tx_frame(priv, skb); else - mwl8k_add_dma_header(skb, 0); + mwl8k_add_dma_header(priv, skb, 0); wh = &((struct mwl8k_dma_data *)skb->data)->wh; @@ -5474,6 +5493,8 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) hw->extra_tx_headroom = sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts); + hw->extra_tx_headroom -= priv->ap_fw ? REDUCED_TX_HEADROOM : 0; + hw->channel_change_time = 10; hw->queues = MWL8K_TX_WMM_QUEUES; -- cgit v1.2.3-58-ga151 From ad246c992bea6d33c6421ba1f03e2b405792adf9 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 26 Apr 2011 15:25:52 +0000 Subject: ipv4, ipv6, bonding: Restore control over number of peer notifications For backward compatibility, we should retain the module parameters and sysfs attributes to control the number of peer notifications (gratuitous ARPs and unsolicited NAs) sent after bonding failover. Also, it is possible for failover to take place even though the new active slave does not have link up, and in that case the peer notification should be deferred until it does. Change ipv4 and ipv6 so they do not automatically send peer notifications on bonding failover. Change the bonding driver to send separate NETDEV_NOTIFY_PEERS notifications when the link is up, as many times as requested. Since it does not directly control which protocols send notifications, make num_grat_arp and num_unsol_na aliases for a single parameter. Bump the bonding version number and update its documentation. Signed-off-by: Ben Hutchings Signed-off-by: Jay Vosburgh Acked-by: Brian Haley Signed-off-by: David S. Miller --- Documentation/networking/bonding.txt | 34 ++++++++++----------- drivers/net/bonding/bond_main.c | 59 ++++++++++++++++++++++++++++++++++++ drivers/net/bonding/bond_sysfs.c | 26 ++++++++++++++++ drivers/net/bonding/bonding.h | 6 ++-- net/ipv4/devinet.c | 1 - net/ipv6/ndisc.c | 1 - 6 files changed, 105 insertions(+), 22 deletions(-) diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt index e27202bb8d75..1f45bd887d65 100644 --- a/Documentation/networking/bonding.txt +++ b/Documentation/networking/bonding.txt @@ -1,7 +1,7 @@ Linux Ethernet Bonding Driver HOWTO - Latest update: 23 September 2009 + Latest update: 27 April 2011 Initial release : Thomas Davis Corrections, HA extensions : 2000/10/03-15 : @@ -585,25 +585,23 @@ mode chosen. num_grat_arp - - Specifies the number of gratuitous ARPs to be issued after a - failover event. One gratuitous ARP is issued immediately after - the failover, subsequent ARPs are sent at a rate of one per link - monitor interval (arp_interval or miimon, whichever is active). - - The valid range is 0 - 255; the default value is 1. This option - affects only the active-backup mode. This option was added for - bonding version 3.3.0. - num_unsol_na - Specifies the number of unsolicited IPv6 Neighbor Advertisements - to be issued after a failover event. One unsolicited NA is issued - immediately after the failover. - - The valid range is 0 - 255; the default value is 1. This option - affects only the active-backup mode. This option was added for - bonding version 3.4.0. + Specify the number of peer notifications (gratuitous ARPs and + unsolicited IPv6 Neighbor Advertisements) to be issued after a + failover event. As soon as the link is up on the new slave + (possibly immediately) a peer notification is sent on the + bonding device and each VLAN sub-device. This is repeated at + each link monitor interval (arp_interval or miimon, whichever + is active) if the number is greater than 1. + + The valid range is 0 - 255; the default value is 1. These options + affect only the active-backup mode. These options were added for + bonding versions 3.3.0 and 3.4.0 respectively. + + From Linux 2.6.40 and bonding version 3.7.1, these notifications + are generated by the ipv4 and ipv6 code and the numbers of + repetitions cannot be set independently. primary diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 66d9dc6e5cac..22bd03bd1d35 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -89,6 +89,7 @@ static int max_bonds = BOND_DEFAULT_MAX_BONDS; static int tx_queues = BOND_DEFAULT_TX_QUEUES; +static int num_peer_notif = 1; static int miimon = BOND_LINK_MON_INTERV; static int updelay; static int downdelay; @@ -111,6 +112,10 @@ module_param(max_bonds, int, 0); MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); module_param(tx_queues, int, 0); MODULE_PARM_DESC(tx_queues, "Max number of transmit queues (default = 16)"); +module_param_named(num_grat_arp, num_peer_notif, int, 0644); +MODULE_PARM_DESC(num_grat_arp, "Number of peer notifications to send on failover event (alias of num_unsol_na)"); +module_param_named(num_unsol_na, num_peer_notif, int, 0644); +MODULE_PARM_DESC(num_unsol_na, "Number of peer notifications to send on failover event (alias of num_grat_arp)"); module_param(miimon, int, 0); MODULE_PARM_DESC(miimon, "Link check interval in milliseconds"); module_param(updelay, int, 0); @@ -1082,6 +1087,21 @@ static struct slave *bond_find_best_slave(struct bonding *bond) return bestslave; } +static bool bond_should_notify_peers(struct bonding *bond) +{ + struct slave *slave = bond->curr_active_slave; + + pr_debug("bond_should_notify_peers: bond %s slave %s\n", + bond->dev->name, slave ? slave->dev->name : "NULL"); + + if (!slave || !bond->send_peer_notif || + test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state)) + return false; + + bond->send_peer_notif--; + return true; +} + /** * change_active_interface - change the active slave into the specified one * @bond: our bonding struct @@ -1149,16 +1169,28 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) bond_set_slave_inactive_flags(old_active); if (new_active) { + bool should_notify_peers = false; + bond_set_slave_active_flags(new_active); if (bond->params.fail_over_mac) bond_do_fail_over_mac(bond, new_active, old_active); + if (netif_running(bond->dev)) { + bond->send_peer_notif = + bond->params.num_peer_notif; + should_notify_peers = + bond_should_notify_peers(bond); + } + write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); netdev_bonding_change(bond->dev, NETDEV_BONDING_FAILOVER); + if (should_notify_peers) + netdev_bonding_change(bond->dev, + NETDEV_NOTIFY_PEERS); read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); @@ -2556,6 +2588,7 @@ void bond_mii_monitor(struct work_struct *work) { struct bonding *bond = container_of(work, struct bonding, mii_work.work); + bool should_notify_peers = false; read_lock(&bond->lock); if (bond->kill_timers) @@ -2564,6 +2597,8 @@ void bond_mii_monitor(struct work_struct *work) if (bond->slave_cnt == 0) goto re_arm; + should_notify_peers = bond_should_notify_peers(bond); + if (bond_miimon_inspect(bond)) { read_unlock(&bond->lock); rtnl_lock(); @@ -2582,6 +2617,12 @@ re_arm: msecs_to_jiffies(bond->params.miimon)); out: read_unlock(&bond->lock); + + if (should_notify_peers) { + rtnl_lock(); + netdev_bonding_change(bond->dev, NETDEV_NOTIFY_PEERS); + rtnl_unlock(); + } } static __be32 bond_glean_dev_ip(struct net_device *dev) @@ -3154,6 +3195,7 @@ void bond_activebackup_arp_mon(struct work_struct *work) { struct bonding *bond = container_of(work, struct bonding, arp_work.work); + bool should_notify_peers = false; int delta_in_ticks; read_lock(&bond->lock); @@ -3166,6 +3208,8 @@ void bond_activebackup_arp_mon(struct work_struct *work) if (bond->slave_cnt == 0) goto re_arm; + should_notify_peers = bond_should_notify_peers(bond); + if (bond_ab_arp_inspect(bond, delta_in_ticks)) { read_unlock(&bond->lock); rtnl_lock(); @@ -3185,6 +3229,12 @@ re_arm: queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); out: read_unlock(&bond->lock); + + if (should_notify_peers) { + rtnl_lock(); + netdev_bonding_change(bond->dev, NETDEV_NOTIFY_PEERS); + rtnl_unlock(); + } } /*-------------------------- netdev event handling --------------------------*/ @@ -3494,6 +3544,8 @@ static int bond_close(struct net_device *bond_dev) write_lock_bh(&bond->lock); + bond->send_peer_notif = 0; + /* signal timers not to re-arm */ bond->kill_timers = 1; @@ -4571,6 +4623,12 @@ static int bond_check_params(struct bond_params *params) use_carrier = 1; } + if (num_peer_notif < 0 || num_peer_notif > 255) { + pr_warning("Warning: num_grat_arp/num_unsol_na (%d) not in range 0-255 so it was reset to 1\n", + num_peer_notif); + num_peer_notif = 1; + } + /* reset values for 802.3ad */ if (bond_mode == BOND_MODE_8023AD) { if (!miimon) { @@ -4760,6 +4818,7 @@ static int bond_check_params(struct bond_params *params) params->mode = bond_mode; params->xmit_policy = xmit_hashtype; params->miimon = miimon; + params->num_peer_notif = num_peer_notif; params->arp_interval = arp_interval; params->arp_validate = arp_validate_value; params->updelay = updelay; diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 935406aa5f0c..4059bfc73dbf 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -868,6 +868,30 @@ out: static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR, bonding_show_ad_select, bonding_store_ad_select); +/* + * Show and set the number of peer notifications to send after a failover event. + */ +static ssize_t bonding_show_num_peer_notif(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct bonding *bond = to_bond(d); + return sprintf(buf, "%d\n", bond->params.num_peer_notif); +} + +static ssize_t bonding_store_num_peer_notif(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct bonding *bond = to_bond(d); + int err = kstrtou8(buf, 10, &bond->params.num_peer_notif); + return err ? err : count; +} +static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, + bonding_show_num_peer_notif, bonding_store_num_peer_notif); +static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR, + bonding_show_num_peer_notif, bonding_store_num_peer_notif); + /* * Show and set the MII monitor interval. There are two tricky bits * here. First, if MII monitoring is activated, then we must disable @@ -1566,6 +1590,8 @@ static struct attribute *per_bond_attrs[] = { &dev_attr_lacp_rate.attr, &dev_attr_ad_select.attr, &dev_attr_xmit_hash_policy.attr, + &dev_attr_num_grat_arp.attr, + &dev_attr_num_unsol_na.attr, &dev_attr_miimon.attr, &dev_attr_primary.attr, &dev_attr_primary_reselect.attr, diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 85fb8220e283..d08362e1a0dd 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -24,8 +24,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.7.0" -#define DRV_RELDATE "June 2, 2010" +#define DRV_VERSION "3.7.1" +#define DRV_RELDATE "April 27, 2011" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" @@ -149,6 +149,7 @@ struct bond_params { int mode; int xmit_policy; int miimon; + u8 num_peer_notif; int arp_interval; int arp_validate; int use_carrier; @@ -231,6 +232,7 @@ struct bonding { rwlock_t lock; rwlock_t curr_slave_lock; s8 kill_timers; + u8 send_peer_notif; s8 setup_by_slave; s8 igmp_retrans; #ifdef CONFIG_PROC_FS diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index acf553f95b5b..5345b0bee6df 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1203,7 +1203,6 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, break; /* fall through */ case NETDEV_NOTIFY_PEERS: - case NETDEV_BONDING_FAILOVER: /* Send gratuitous ARP to notify of link change */ inetdev_send_gratuitous_arp(dev, in_dev); break; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 69aacd18e066..7596f071d308 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1747,7 +1747,6 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, fib6_run_gc(~0UL, net); break; case NETDEV_NOTIFY_PEERS: - case NETDEV_BONDING_FAILOVER: ndisc_send_unsol_na(dev); break; default: -- cgit v1.2.3-58-ga151 From f94bc1e70281c5a587049015af8f3e024d45ad66 Mon Sep 17 00:00:00 2001 From: Sucheta Chakraborty Date: Thu, 28 Apr 2011 11:48:18 +0000 Subject: qlcnic: support rcv ring configuration through ethtool o Support ethtool command ETHTOOL_GCHANNELS and ETHTOOL_SCHANNELS. o Number of rcv rings configuration depend upon number of msix vector. Signed-off-by: Sucheta Chakraborty Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 8 +- drivers/net/qlcnic/qlcnic_ethtool.c | 35 +++++++++ drivers/net/qlcnic/qlcnic_main.c | 146 ++++++++++++++++++++++++++++-------- 3 files changed, 156 insertions(+), 33 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index f7acb807a03d..1934ed9a1aad 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -118,7 +118,6 @@ #define PHAN_PEG_RCV_INITIALIZED 0xff01 #define NUM_RCV_DESC_RINGS 3 -#define NUM_STS_DESC_RINGS 4 #define RCV_RING_NORMAL 0 #define RCV_RING_JUMBO 1 @@ -871,7 +870,8 @@ struct qlcnic_ipaddr { #define QLCNIC_IS_MSI_FAMILY(adapter) \ ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) -#define MSIX_ENTRIES_PER_ADAPTER NUM_STS_DESC_RINGS +#define QLCNIC_DEF_NUM_STS_DESC_RINGS 4 +#define QLCNIC_MIN_NUM_RSS_RINGS 2 #define QLCNIC_MSIX_TBL_SPACE 8192 #define QLCNIC_PCI_REG_MSIX_TBL 0x44 #define QLCNIC_MSIX_TBL_PGSIZE 4096 @@ -987,7 +987,7 @@ struct qlcnic_adapter { void __iomem *crb_int_state_reg; void __iomem *isr_int_vec; - struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER]; + struct msix_entry *msix_entries; struct delayed_work fw_work; @@ -1262,6 +1262,8 @@ u32 qlcnic_issue_cmd(struct qlcnic_adapter *adapter, void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings); int qlcnic_diag_alloc_res(struct net_device *netdev, int test); netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); +int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val); +int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data); /* Management functions */ int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*); diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index de65847f3559..8db1d1983cfe 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -474,6 +474,39 @@ qlcnic_set_ringparam(struct net_device *dev, return qlcnic_reset_context(adapter); } +static void qlcnic_get_channels(struct net_device *dev, + struct ethtool_channels *channel) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + + channel->max_rx = rounddown_pow_of_two(min_t(int, + adapter->max_rx_ques, num_online_cpus())); + channel->max_tx = adapter->max_tx_ques; + + channel->rx_count = adapter->max_sds_rings; + channel->tx_count = adapter->max_tx_ques; +} + +static int qlcnic_set_channels(struct net_device *dev, + struct ethtool_channels *channel) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + int err; + + if (channel->other_count || channel->combined_count || + channel->tx_count != channel->max_tx) + return -EINVAL; + + err = qlcnic_validate_max_rss(dev, channel->max_rx, channel->rx_count); + if (err) + return err; + + err = qlcnic_set_max_rss(adapter, channel->rx_count); + netdev_info(dev, "allocated 0x%x sds rings\n", + adapter->max_sds_rings); + return err; +} + static void qlcnic_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) @@ -949,6 +982,8 @@ const struct ethtool_ops qlcnic_ethtool_ops = { .get_eeprom = qlcnic_get_eeprom, .get_ringparam = qlcnic_get_ringparam, .set_ringparam = qlcnic_set_ringparam, + .get_channels = qlcnic_get_channels, + .set_channels = qlcnic_set_channels, .get_pauseparam = qlcnic_get_pauseparam, .set_pauseparam = qlcnic_set_pauseparam, .get_wol = qlcnic_get_wol, diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 6e619514feee..d6cc4d479591 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -18,6 +18,7 @@ #include #include #include +#include MODULE_DESCRIPTION("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver"); MODULE_LICENSE("GPL"); @@ -350,39 +351,17 @@ static struct qlcnic_nic_template qlcnic_vf_ops = { .start_firmware = qlcnicvf_start_firmware }; -static void -qlcnic_setup_intr(struct qlcnic_adapter *adapter) +static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) { - const struct qlcnic_legacy_intr_set *legacy_intrp; struct pci_dev *pdev = adapter->pdev; - int err, num_msix; - - if (adapter->msix_supported) { - num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ? - MSIX_ENTRIES_PER_ADAPTER : 2; - } else - num_msix = 1; + int err = -1; adapter->max_sds_rings = 1; - adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED); - - legacy_intrp = &legacy_intr[adapter->ahw->pci_func]; - - adapter->int_vec_bit = legacy_intrp->int_vec_bit; - adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter, - legacy_intrp->tgt_status_reg); - adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter, - legacy_intrp->tgt_mask_reg); - adapter->isr_int_vec = qlcnic_get_ioaddr(adapter, ISR_INT_VECTOR); - - adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter, - ISR_INT_STATE_REG); - qlcnic_set_msix_bit(pdev, 0); if (adapter->msix_supported) { - + enable_msix: qlcnic_init_msix_entries(adapter, num_msix); err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); if (err == 0) { @@ -392,14 +371,22 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter) adapter->max_sds_rings = num_msix; dev_info(&pdev->dev, "using msi-x interrupts\n"); - return; + return err; } + if (err > 0) { + num_msix = rounddown_pow_of_two(err); + if (num_msix) + goto enable_msix; + } + } + return err; +} - if (err > 0) - pci_disable_msix(pdev); - /* fall through for msi */ - } +static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter) +{ + const struct qlcnic_legacy_intr_set *legacy_intrp; + struct pci_dev *pdev = adapter->pdev; if (use_msi && !pci_enable_msi(pdev)) { adapter->flags |= QLCNIC_MSI_ENABLED; @@ -410,10 +397,40 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter) return; } + legacy_intrp = &legacy_intr[adapter->ahw->pci_func]; + + adapter->int_vec_bit = legacy_intrp->int_vec_bit; + adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter, + legacy_intrp->tgt_status_reg); + adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter, + legacy_intrp->tgt_mask_reg); + adapter->isr_int_vec = qlcnic_get_ioaddr(adapter, ISR_INT_VECTOR); + + adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter, + ISR_INT_STATE_REG); dev_info(&pdev->dev, "using legacy interrupts\n"); adapter->msix_entries[0].vector = pdev->irq; } +static void +qlcnic_setup_intr(struct qlcnic_adapter *adapter) +{ + int num_msix; + + if (adapter->msix_supported) { + num_msix = (num_online_cpus() >= + QLCNIC_DEF_NUM_STS_DESC_RINGS) ? + QLCNIC_DEF_NUM_STS_DESC_RINGS : + QLCNIC_MIN_NUM_RSS_RINGS; + } else + num_msix = 1; + + if (!qlcnic_enable_msix(adapter, num_msix)) + return; + + qlcnic_enable_msi_legacy(adapter); +} + static void qlcnic_teardown_intr(struct qlcnic_adapter *adapter) { @@ -1493,6 +1510,19 @@ static int qlcnic_set_dma_mask(struct pci_dev *pdev, u8 *pci_using_dac) return 0; } +static int +qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count) +{ + adapter->msix_entries = kcalloc(count, sizeof(struct msix_entry), + GFP_KERNEL); + + if (adapter->msix_entries) + return 0; + + dev_err(&adapter->pdev->dev, "failed allocating msix_entries\n"); + return -ENOMEM; +} + static int __devinit qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -1587,6 +1617,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) qlcnic_clear_stats(adapter); + err = qlcnic_alloc_msix_entries(adapter, adapter->max_rx_ques); + if (err) + goto err_out_decr_ref; + qlcnic_setup_intr(adapter); err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac); @@ -1615,6 +1649,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err_out_disable_msi: qlcnic_teardown_intr(adapter); + kfree(adapter->msix_entries); err_out_decr_ref: qlcnic_clr_all_drv_state(adapter, 0); @@ -1666,6 +1701,7 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev) qlcnic_free_lb_filters_mem(adapter); qlcnic_teardown_intr(adapter); + kfree(adapter->msix_entries); qlcnic_remove_diag_entries(adapter); @@ -3299,6 +3335,56 @@ static struct device_attribute dev_attr_diag_mode = { .store = qlcnic_store_diag_mode, }; +int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val) +{ + if (!use_msi_x && !use_msi) { + netdev_info(netdev, "no msix or msi support, hence no rss\n"); + return -EINVAL; + } + + if ((val > max_hw) || (val < 2) || !is_power_of_2(val)) { + netdev_info(netdev, "rss_ring valid range [2 - %x] in " + " powers of 2\n", max_hw); + return -EINVAL; + } + return 0; + +} + +int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data) +{ + struct net_device *netdev = adapter->netdev; + int err = 0; + + if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) + return -EBUSY; + + netif_device_detach(netdev); + if (netif_running(netdev)) + __qlcnic_down(adapter, netdev); + qlcnic_detach(adapter); + qlcnic_teardown_intr(adapter); + + if (qlcnic_enable_msix(adapter, data)) { + netdev_info(netdev, "failed setting max_rss; rss disabled\n"); + qlcnic_enable_msi_legacy(adapter); + } + + if (netif_running(netdev)) { + err = qlcnic_attach(adapter); + if (err) + goto done; + err = __qlcnic_up(adapter, netdev); + if (err) + goto done; + qlcnic_restore_indev_addr(netdev, NETDEV_UP); + } + done: + netif_device_attach(netdev); + clear_bit(__QLCNIC_RESETTING, &adapter->state); + return err; +} + static int qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter, loff_t offset, size_t size) -- cgit v1.2.3-58-ga151 From 7e610caaa5b32d3be9216f040f178e4a23b678b2 Mon Sep 17 00:00:00 2001 From: Sony Chacko Date: Thu, 28 Apr 2011 11:48:19 +0000 Subject: qlcnic: Support for GBE port settings Enable setting speed and auto negotiation parameters for GbE ports. Hardware do not support half duplex setting currently. o Update driver version to 5.0.17. Signed-off-by: Sony Chacko Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 9 ++--- drivers/net/qlcnic/qlcnic_ctx.c | 26 +++----------- drivers/net/qlcnic/qlcnic_ethtool.c | 68 +++++++++++++++++-------------------- 3 files changed, 40 insertions(+), 63 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 1934ed9a1aad..f729363b3fc3 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -36,8 +36,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 0 -#define _QLCNIC_LINUX_SUBVERSION 16 -#define QLCNIC_LINUX_VERSIONID "5.0.16" +#define _QLCNIC_LINUX_SUBVERSION 17 +#define QLCNIC_LINUX_VERSIONID "5.0.17" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) @@ -573,8 +573,10 @@ struct qlcnic_recv_context { #define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028 #define QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG 0x00000029 #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a +#define QLCNIC_CDRP_CMD_CONFIG_PORT 0x0000002E #define QLCNIC_RCODE_SUCCESS 0 +#define QLCNIC_RCODE_NOT_SUPPORTED 9 #define QLCNIC_RCODE_TIMEOUT 17 #define QLCNIC_DESTROY_CTX_RESET 0 @@ -1155,8 +1157,7 @@ struct qlcnic_esw_statistics { struct __qlcnic_esw_statistics tx; }; -int qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val); -int qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val); +int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config); u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off); int qlcnic_hw_write_wx_2M(struct qlcnic_adapter *, ulong off, u32 data); diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c index 050fa5a99ff7..3a99886e4736 100644 --- a/drivers/net/qlcnic/qlcnic_ctx.c +++ b/drivers/net/qlcnic/qlcnic_ctx.c @@ -359,33 +359,15 @@ qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter) } int -qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val) -{ - - if (qlcnic_issue_cmd(adapter, - adapter->ahw->pci_func, - adapter->fw_hal_version, - reg, - 0, - 0, - QLCNIC_CDRP_CMD_READ_PHY)) { - - return -EIO; - } - - return QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); -} - -int -qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val) +qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config) { return qlcnic_issue_cmd(adapter, adapter->ahw->pci_func, adapter->fw_hal_version, - reg, - val, + config, + 0, 0, - QLCNIC_CDRP_CMD_WRITE_PHY); + QLCNIC_CDRP_CMD_CONFIG_PORT); } int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 8db1d1983cfe..27726ebfba2a 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -284,50 +284,44 @@ skip: static int qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { + u32 config = 0; + u32 ret = 0; struct qlcnic_adapter *adapter = netdev_priv(dev); - __u32 status; + + if (adapter->ahw->port_type != QLCNIC_GBE) + return -EOPNOTSUPP; /* read which mode */ - if (adapter->ahw->port_type == QLCNIC_GBE) { - /* autonegotiation */ - if (qlcnic_fw_cmd_set_phy(adapter, - QLCNIC_NIU_GB_MII_MGMT_ADDR_AUTONEG, - ecmd->autoneg) != 0) - return -EIO; - else - adapter->link_autoneg = ecmd->autoneg; + if (ecmd->duplex) + config |= 0x1; - if (qlcnic_fw_cmd_query_phy(adapter, - QLCNIC_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, - &status) != 0) - return -EIO; + if (ecmd->autoneg) + config |= 0x2; - switch (ecmd->speed) { - case SPEED_10: - qlcnic_set_phy_speed(status, 0); - break; - case SPEED_100: - qlcnic_set_phy_speed(status, 1); - break; - case SPEED_1000: - qlcnic_set_phy_speed(status, 2); - break; - } + switch (ethtool_cmd_speed(ecmd)) { + case SPEED_10: + config |= (0 << 8); + break; + case SPEED_100: + config |= (1 << 8); + break; + case SPEED_1000: + config |= (10 << 8); + break; + default: + return -EIO; + } - if (ecmd->duplex == DUPLEX_HALF) - qlcnic_clear_phy_duplex(status); - if (ecmd->duplex == DUPLEX_FULL) - qlcnic_set_phy_duplex(status); - if (qlcnic_fw_cmd_set_phy(adapter, - QLCNIC_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, - *((int *)&status)) != 0) - return -EIO; - else { - adapter->link_speed = ecmd->speed; - adapter->link_duplex = ecmd->duplex; - } - } else + ret = qlcnic_fw_cmd_set_port(adapter, config); + + if (ret == QLCNIC_RCODE_NOT_SUPPORTED) return -EOPNOTSUPP; + else if (ret) + return -EIO; + + adapter->link_speed = ethtool_cmd_speed(ecmd); + adapter->link_duplex = ecmd->duplex; + adapter->link_autoneg = ecmd->autoneg; if (!netif_running(dev)) return 0; -- cgit v1.2.3-58-ga151 From 36504605432996590f889e33d47e2d9c581f7569 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 27 Apr 2011 18:32:37 +0000 Subject: ethtool: cosmetics: enforce const-ness in ethtool_cmd_speed The 'ep' argument of ethtool_cmd_speed is not altered: advertise it in protoype. +Indentation fix. Also add comments to advise using the ethtool_cmd_speed API to get/set the link speed. Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- include/linux/ethtool.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 9de31274341d..7e6e0a89ca26 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -24,7 +24,10 @@ struct ethtool_cmd { __u32 cmd; __u32 supported; /* Features this interface supports */ __u32 advertising; /* Features this interface advertises */ - __u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */ + __u16 speed; /* The forced speed (lower bits) in + * Mbps. Please use + * ethtool_cmd_speed()/_set() to + * access it */ __u8 duplex; /* Duplex, half or full */ __u8 port; /* Which connector port */ __u8 phy_address; @@ -33,7 +36,10 @@ struct ethtool_cmd { __u8 mdio_support; __u32 maxtxpkt; /* Tx pkts before generating tx int */ __u32 maxrxpkt; /* Rx pkts before generating rx int */ - __u16 speed_hi; + __u16 speed_hi; /* The forced speed (upper + * bits) in Mbps. Please use + * ethtool_cmd_speed()/_set() to + * access it */ __u8 eth_tp_mdix; __u8 reserved2; __u32 lp_advertising; /* Features the link partner advertises */ @@ -41,14 +47,14 @@ struct ethtool_cmd { }; static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep, - __u32 speed) + __u32 speed) { ep->speed = (__u16)speed; ep->speed_hi = (__u16)(speed >> 16); } -static inline __u32 ethtool_cmd_speed(struct ethtool_cmd *ep) +static inline __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep) { return (ep->speed_hi << 16) | ep->speed; } -- cgit v1.2.3-58-ga151 From 8ae6daca85c8bbd6a32c382db5e2a2a989f8bed2 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 27 Apr 2011 18:32:38 +0000 Subject: ethtool: Call ethtool's get/set_settings callbacks with cleaned data This makes sure that when a driver calls the ethtool's get/set_settings() callback of another driver, the data passed to it is clean. This guarantees that speed_hi will be zeroed correctly if the called callback doesn't explicitely set it: we are sure we don't get a corrupted speed from the underlying driver. We also take care of setting the cmd field appropriately (ETHTOOL_GSET/SSET). This applies to dev_ethtool_get_settings(), which now makes sure it sets up that ethtool command parameter correctly before passing it to drivers. This also means that whoever calls dev_ethtool_get_settings() does not have to clean the ethtool command parameter. This function also becomes an exported symbol instead of an inline. All drivers visible to make allyesconfig under x86_64 have been updated. Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- arch/mips/txx9/generic/setup_tx4939.c | 21 ++++++++------------- drivers/net/e100.c | 2 +- drivers/net/mdio.c | 3 +++ drivers/net/mii.c | 3 +++ drivers/net/pch_gbe/pch_gbe_main.c | 6 +++--- drivers/net/pch_gbe/pch_gbe_phy.c | 2 +- drivers/net/pcnet32.c | 16 ++++++++-------- drivers/net/sfc/mdio_10g.c | 4 ++-- drivers/net/stmmac/stmmac_ethtool.c | 5 ++--- drivers/net/usb/asix.c | 28 +++++++++++++++------------- drivers/net/usb/dm9601.c | 6 +++--- drivers/net/usb/smsc75xx.c | 7 ++++--- drivers/net/usb/smsc95xx.c | 7 ++++--- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 11 +++++++---- drivers/scsi/fcoe/fcoe.c | 11 +++++++---- include/linux/ethtool.h | 4 +++- include/linux/netdevice.h | 9 ++------- include/rdma/ib_addr.h | 13 +++++++------ net/core/dev.c | 24 ++++++++++++++++++++++++ net/core/net-sysfs.c | 24 ++++++++++-------------- 20 files changed, 117 insertions(+), 89 deletions(-) diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c index 3dc19f482959..e9f95dcde379 100644 --- a/arch/mips/txx9/generic/setup_tx4939.c +++ b/arch/mips/txx9/generic/setup_tx4939.c @@ -318,19 +318,15 @@ void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask) } #if defined(CONFIG_TC35815) || defined(CONFIG_TC35815_MODULE) -static int tx4939_get_eth_speed(struct net_device *dev) +static u32 tx4939_get_eth_speed(struct net_device *dev) { - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - int speed = 100; /* default 100Mbps */ - int err; - if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) - return speed; - err = dev->ethtool_ops->get_settings(dev, &cmd); - if (err < 0) - return speed; - speed = cmd.speed == SPEED_100 ? 100 : 10; - return speed; + struct ethtool_cmd cmd; + if (dev_ethtool_get_settings(dev, &cmd)) + return 100; /* default 100Mbps */ + + return ethtool_cmd_speed(&cmd); } + static int tx4939_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) @@ -343,8 +339,7 @@ static int tx4939_netdev_event(struct notifier_block *this, else if (dev->irq == TXX9_IRQ_BASE + TX4939_IR_ETH(1)) bit = TX4939_PCFG_SPEED1; if (bit) { - int speed = tx4939_get_eth_speed(dev); - if (speed == 100) + if (tx4939_get_eth_speed(dev) == 100) txx9_set64(&tx4939_ccfgptr->pcfg, bit); else txx9_clear64(&tx4939_ccfgptr->pcfg, bit); diff --git a/drivers/net/e100.c b/drivers/net/e100.c index b0aa9e68990a..66ba596a4d37 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1668,7 +1668,7 @@ static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) static void e100_watchdog(unsigned long data) { struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; + struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; netif_printk(nic, timer, KERN_DEBUG, nic->netdev, "right now = %ld\n", jiffies); diff --git a/drivers/net/mdio.c b/drivers/net/mdio.c index e85bf04cf813..f2d10abd0403 100644 --- a/drivers/net/mdio.c +++ b/drivers/net/mdio.c @@ -176,6 +176,9 @@ static u32 mdio45_get_an(const struct mdio_if_info *mdio, u16 addr) * @npage_adv: Modes currently advertised on next pages * @npage_lpa: Modes advertised by link partner on next pages * + * The @ecmd parameter is expected to have been cleared before calling + * mdio45_ethtool_gset_npage(). + * * Since the CSRs for auto-negotiation using next pages are not fully * standardised, this function does not attempt to decode them. The * caller must pass them in. diff --git a/drivers/net/mii.c b/drivers/net/mii.c index 0a6c6a2e7550..05acca78f63a 100644 --- a/drivers/net/mii.c +++ b/drivers/net/mii.c @@ -58,6 +58,9 @@ static u32 mii_get_an(struct mii_if_info *mii, u16 addr) * @mii: MII interface * @ecmd: requested ethtool_cmd * + * The @ecmd parameter is expected to have been cleared before calling + * mii_ethtool_gset(). + * * Returns 0 for success, negative on error. */ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index 4cc9872f5ec4..f3e4b0adae93 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c @@ -888,12 +888,12 @@ static void pch_gbe_watchdog(unsigned long data) struct pch_gbe_adapter *adapter = (struct pch_gbe_adapter *)data; struct net_device *netdev = adapter->netdev; struct pch_gbe_hw *hw = &adapter->hw; - struct ethtool_cmd cmd; pr_debug("right now = %ld\n", jiffies); pch_gbe_update_stats(adapter); if ((mii_link_ok(&adapter->mii)) && (!netif_carrier_ok(netdev))) { + struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; netdev->tx_queue_len = adapter->tx_queue_len; /* mii library handles link maintenance tasks */ if (mii_ethtool_gset(&adapter->mii, &cmd)) { @@ -903,7 +903,7 @@ static void pch_gbe_watchdog(unsigned long data) PCH_GBE_WATCHDOG_PERIOD)); return; } - hw->mac.link_speed = cmd.speed; + hw->mac.link_speed = ethtool_cmd_speed(&cmd); hw->mac.link_duplex = cmd.duplex; /* Set the RGMII control. */ pch_gbe_set_rgmii_ctrl(adapter, hw->mac.link_speed, @@ -913,7 +913,7 @@ static void pch_gbe_watchdog(unsigned long data) hw->mac.link_duplex); netdev_dbg(netdev, "Link is Up %d Mbps %s-Duplex\n", - cmd.speed, + hw->mac.link_speed, cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); netif_carrier_on(netdev); netif_wake_queue(netdev); diff --git a/drivers/net/pch_gbe/pch_gbe_phy.c b/drivers/net/pch_gbe/pch_gbe_phy.c index 923a687acd30..9a8207f686fd 100644 --- a/drivers/net/pch_gbe/pch_gbe_phy.c +++ b/drivers/net/pch_gbe/pch_gbe_phy.c @@ -247,7 +247,7 @@ inline void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw) void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw) { struct pch_gbe_adapter *adapter; - struct ethtool_cmd cmd; + struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; int ret; u16 mii_reg; diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 0a1efbae1bc0..b48aba9e4227 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -2099,7 +2099,7 @@ static int pcnet32_open(struct net_device *dev) int first_phy = -1; u16 bmcr; u32 bcr9; - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; /* * There is really no good other way to handle multiple PHYs @@ -2115,9 +2115,9 @@ static int pcnet32_open(struct net_device *dev) ecmd.port = PORT_MII; ecmd.transceiver = XCVR_INTERNAL; ecmd.autoneg = AUTONEG_DISABLE; - ecmd.speed = - lp-> - options & PCNET32_PORT_100 ? SPEED_100 : SPEED_10; + ethtool_cmd_speed_set(&ecmd, + (lp->options & PCNET32_PORT_100) ? + SPEED_100 : SPEED_10); bcr9 = lp->a.read_bcr(ioaddr, 9); if (lp->options & PCNET32_PORT_FD) { @@ -2763,11 +2763,11 @@ static void pcnet32_check_media(struct net_device *dev, int verbose) netif_carrier_on(dev); if (lp->mii) { if (netif_msg_link(lp)) { - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { + .cmd = ETHTOOL_GSET }; mii_ethtool_gset(&lp->mii_if, &ecmd); - netdev_info(dev, "link up, %sMbps, %s-duplex\n", - (ecmd.speed == SPEED_100) - ? "100" : "10", + netdev_info(dev, "link up, %uMbps, %s-duplex\n", + ethtool_cmd_speed(&ecmd), (ecmd.duplex == DUPLEX_FULL) ? "full" : "half"); } diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index 19e68c26d103..71159145b4bf 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c @@ -232,12 +232,12 @@ void efx_mdio_set_mmds_lpower(struct efx_nic *efx, */ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - struct ethtool_cmd prev; + struct ethtool_cmd prev = { .cmd = ETHTOOL_GSET }; efx->phy_op->get_settings(efx, &prev); if (ecmd->advertising == prev.advertising && - ecmd->speed == prev.speed && + ethtool_cmd_speed(ecmd) == ethtool_cmd_speed(&prev) && ecmd->duplex == prev.duplex && ecmd->port == prev.port && ecmd->autoneg == prev.autoneg) diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c index 0e61ac8707cb..6f5aaeb986ff 100644 --- a/drivers/net/stmmac/stmmac_ethtool.c +++ b/drivers/net/stmmac/stmmac_ethtool.c @@ -237,13 +237,12 @@ stmmac_set_pauseparam(struct net_device *netdev, if (phy->autoneg) { if (netif_running(netdev)) { - struct ethtool_cmd cmd; + struct ethtool_cmd cmd = { .cmd = ETHTOOL_SSET }; /* auto-negotiation automatically restarted */ - cmd.cmd = ETHTOOL_NWAY_RST; cmd.supported = phy->supported; cmd.advertising = phy->advertising; cmd.autoneg = phy->autoneg; - cmd.speed = phy->speed; + ethtool_cmd_speed_set(&cmd, phy->speed); cmd.duplex = phy->duplex; cmd.phy_address = phy->addr; ret = phy_ethtool_sset(phy, &cmd); diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 6140b56cce53..6998aa6b7bb7 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -847,7 +847,7 @@ static void ax88172_set_multicast(struct net_device *net) static int ax88172_link_reset(struct usbnet *dev) { u8 mode; - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; mii_check_media(&dev->mii, 1, 1); mii_ethtool_gset(&dev->mii, &ecmd); @@ -856,8 +856,8 @@ static int ax88172_link_reset(struct usbnet *dev) if (ecmd.duplex != DUPLEX_FULL) mode |= ~AX88172_MEDIUM_FD; - netdev_dbg(dev->net, "ax88172_link_reset() speed: %d duplex: %d setting mode to 0x%04x\n", - ecmd.speed, ecmd.duplex, mode); + netdev_dbg(dev->net, "ax88172_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n", + ethtool_cmd_speed(&ecmd), ecmd.duplex, mode); asix_write_medium_mode(dev, mode); @@ -947,20 +947,20 @@ static const struct ethtool_ops ax88772_ethtool_ops = { static int ax88772_link_reset(struct usbnet *dev) { u16 mode; - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; mii_check_media(&dev->mii, 1, 1); mii_ethtool_gset(&dev->mii, &ecmd); mode = AX88772_MEDIUM_DEFAULT; - if (ecmd.speed != SPEED_100) + if (ethtool_cmd_speed(&ecmd) != SPEED_100) mode &= ~AX_MEDIUM_PS; if (ecmd.duplex != DUPLEX_FULL) mode &= ~AX_MEDIUM_FD; - netdev_dbg(dev->net, "ax88772_link_reset() speed: %d duplex: %d setting mode to 0x%04x\n", - ecmd.speed, ecmd.duplex, mode); + netdev_dbg(dev->net, "ax88772_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n", + ethtool_cmd_speed(&ecmd), ecmd.duplex, mode); asix_write_medium_mode(dev, mode); @@ -1173,18 +1173,20 @@ static int marvell_led_status(struct usbnet *dev, u16 speed) static int ax88178_link_reset(struct usbnet *dev) { u16 mode; - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; struct asix_data *data = (struct asix_data *)&dev->data; + u32 speed; netdev_dbg(dev->net, "ax88178_link_reset()\n"); mii_check_media(&dev->mii, 1, 1); mii_ethtool_gset(&dev->mii, &ecmd); mode = AX88178_MEDIUM_DEFAULT; + speed = ethtool_cmd_speed(&ecmd); - if (ecmd.speed == SPEED_1000) + if (speed == SPEED_1000) mode |= AX_MEDIUM_GM; - else if (ecmd.speed == SPEED_100) + else if (speed == SPEED_100) mode |= AX_MEDIUM_PS; else mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM); @@ -1196,13 +1198,13 @@ static int ax88178_link_reset(struct usbnet *dev) else mode &= ~AX_MEDIUM_FD; - netdev_dbg(dev->net, "ax88178_link_reset() speed: %d duplex: %d setting mode to 0x%04x\n", - ecmd.speed, ecmd.duplex, mode); + netdev_dbg(dev->net, "ax88178_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n", + speed, ecmd.duplex, mode); asix_write_medium_mode(dev, mode); if (data->phymode == PHY_MODE_MARVELL && data->ledmode) - marvell_led_status(dev, ecmd.speed); + marvell_led_status(dev, speed); return 0; } diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 5002f5be47be..1d93133e9b74 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -599,13 +599,13 @@ static void dm9601_status(struct usbnet *dev, struct urb *urb) static int dm9601_link_reset(struct usbnet *dev) { - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; mii_check_media(&dev->mii, 1, 1); mii_ethtool_gset(&dev->mii, &ecmd); - netdev_dbg(dev->net, "link_reset() speed: %d duplex: %d\n", - ecmd.speed, ecmd.duplex); + netdev_dbg(dev->net, "link_reset() speed: %u duplex: %d\n", + ethtool_cmd_speed(&ecmd), ecmd.duplex); return 0; } diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 860a20c938b4..15b3d6888ae9 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -503,7 +503,7 @@ static int smsc75xx_update_flowcontrol(struct usbnet *dev, u8 duplex, static int smsc75xx_link_reset(struct usbnet *dev) { struct mii_if_info *mii = &dev->mii; - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; u16 lcladv, rmtadv; int ret; @@ -519,8 +519,9 @@ static int smsc75xx_link_reset(struct usbnet *dev) lcladv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); rmtadv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_LPA); - netif_dbg(dev, link, dev->net, "speed: %d duplex: %d lcladv: %04x" - " rmtadv: %04x", ecmd.speed, ecmd.duplex, lcladv, rmtadv); + netif_dbg(dev, link, dev->net, "speed: %u duplex: %d lcladv: %04x" + " rmtadv: %04x", ethtool_cmd_speed(&ecmd), + ecmd.duplex, lcladv, rmtadv); return smsc75xx_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv); } diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 24f4b3739dd2..b374a9997908 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -457,7 +457,7 @@ static int smsc95xx_link_reset(struct usbnet *dev) { struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); struct mii_if_info *mii = &dev->mii; - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; unsigned long flags; u16 lcladv, rmtadv; u32 intdata; @@ -472,8 +472,9 @@ static int smsc95xx_link_reset(struct usbnet *dev) lcladv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); rmtadv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_LPA); - netif_dbg(dev, link, dev->net, "speed: %d duplex: %d lcladv: %04x rmtadv: %04x\n", - ecmd.speed, ecmd.duplex, lcladv, rmtadv); + netif_dbg(dev, link, dev->net, + "speed: %u duplex: %d lcladv: %04x rmtadv: %04x\n", + ethtool_cmd_speed(&ecmd), ecmd.duplex, lcladv, rmtadv); spin_lock_irqsave(&pdata->mac_cr_lock, flags); if (ecmd.duplex != DUPLEX_FULL) { diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index e2e647509a73..cd050196a163 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -664,7 +664,7 @@ static void bnx2fc_link_speed_update(struct fc_lport *lport) struct fcoe_port *port = lport_priv(lport); struct bnx2fc_hba *hba = port->priv; struct net_device *netdev = hba->netdev; - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; + struct ethtool_cmd ecmd; if (!dev_ethtool_get_settings(netdev, &ecmd)) { lport->link_supported_speeds &= @@ -675,12 +675,15 @@ static void bnx2fc_link_speed_update(struct fc_lport *lport) if (ecmd.supported & SUPPORTED_10000baseT_Full) lport->link_supported_speeds |= FC_PORTSPEED_10GBIT; - if (ecmd.speed == SPEED_1000) + switch (ethtool_cmd_speed(&ecmd)) { + case SPEED_1000: lport->link_speed = FC_PORTSPEED_1GBIT; - if (ecmd.speed == SPEED_10000) + break; + case SPEED_10000: lport->link_speed = FC_PORTSPEED_10GBIT; + break; + } } - return; } static int bnx2fc_link_ok(struct fc_lport *lport) { diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index bde6ee5333eb..04f346b562da 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -2026,7 +2026,7 @@ out_nodev: int fcoe_link_speed_update(struct fc_lport *lport) { struct net_device *netdev = fcoe_netdev(lport); - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; + struct ethtool_cmd ecmd; if (!dev_ethtool_get_settings(netdev, &ecmd)) { lport->link_supported_speeds &= @@ -2037,11 +2037,14 @@ int fcoe_link_speed_update(struct fc_lport *lport) if (ecmd.supported & SUPPORTED_10000baseT_Full) lport->link_supported_speeds |= FC_PORTSPEED_10GBIT; - if (ecmd.speed == SPEED_1000) + switch (ethtool_cmd_speed(&ecmd)) { + case SPEED_1000: lport->link_speed = FC_PORTSPEED_1GBIT; - if (ecmd.speed == SPEED_10000) + break; + case SPEED_10000: lport->link_speed = FC_PORTSPEED_10GBIT; - + break; + } return 0; } return -1; diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 7e6e0a89ca26..4194a2067a14 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -744,7 +744,9 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); /** * struct ethtool_ops - optional netdev operations * @get_settings: Get various device settings including Ethernet link - * settings. Returns a negative error code or zero. + * settings. The @cmd parameter is expected to have been cleared + * before get_settings is called. Returns a negative error code or + * zero. * @set_settings: Set various device settings including Ethernet link * settings. Returns a negative error code or zero. * @get_drvinfo: Report driver/device information. Should only set the diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e03af35843bc..d5de66af46f9 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2597,13 +2597,8 @@ static inline int netif_is_bond_slave(struct net_device *dev) extern struct pernet_operations __net_initdata loopback_net_ops; -static inline int dev_ethtool_get_settings(struct net_device *dev, - struct ethtool_cmd *cmd) -{ - if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) - return -EOPNOTSUPP; - return dev->ethtool_ops->get_settings(dev, cmd); -} +int dev_ethtool_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd); static inline u32 dev_ethtool_get_rx_csum(struct net_device *dev) { diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h index b5fc9f39122b..ae8c68f30f1b 100644 --- a/include/rdma/ib_addr.h +++ b/include/rdma/ib_addr.h @@ -217,18 +217,19 @@ static inline enum ib_mtu iboe_get_mtu(int mtu) static inline int iboe_get_rate(struct net_device *dev) { struct ethtool_cmd cmd; + u32 speed; - if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings || - dev->ethtool_ops->get_settings(dev, &cmd)) + if (dev_ethtool_get_settings(dev, &cmd)) return IB_RATE_PORT_CURRENT; - if (cmd.speed >= 40000) + speed = ethtool_cmd_speed(&cmd); + if (speed >= 40000) return IB_RATE_40_GBPS; - else if (cmd.speed >= 30000) + else if (speed >= 30000) return IB_RATE_30_GBPS; - else if (cmd.speed >= 20000) + else if (speed >= 20000) return IB_RATE_20_GBPS; - else if (cmd.speed >= 10000) + else if (speed >= 10000) return IB_RATE_10_GBPS; else return IB_RATE_PORT_CURRENT; diff --git a/net/core/dev.c b/net/core/dev.c index 7db99b52679f..e95dc30110eb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4495,6 +4495,30 @@ void dev_set_rx_mode(struct net_device *dev) netif_addr_unlock_bh(dev); } +/** + * dev_ethtool_get_settings - call device's ethtool_ops::get_settings() + * @dev: device + * @cmd: memory area for ethtool_ops::get_settings() result + * + * The cmd arg is initialized properly (cleared and + * ethtool_cmd::cmd field set to ETHTOOL_GSET). + * + * Return device's ethtool_ops::get_settings() result value or + * -EOPNOTSUPP when device doesn't expose + * ethtool_ops::get_settings() operation. + */ +int dev_ethtool_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) + return -EOPNOTSUPP; + + memset(cmd, 0, sizeof(struct ethtool_cmd)); + cmd->cmd = ETHTOOL_GSET; + return dev->ethtool_ops->get_settings(dev, cmd); +} +EXPORT_SYMBOL(dev_ethtool_get_settings); + /** * dev_get_flags - get flags reported to userspace * @dev: device diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 5ceb257e860c..381813eae46c 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -28,6 +28,7 @@ static const char fmt_hex[] = "%#x\n"; static const char fmt_long_hex[] = "%#lx\n"; static const char fmt_dec[] = "%d\n"; +static const char fmt_udec[] = "%u\n"; static const char fmt_ulong[] = "%lu\n"; static const char fmt_u64[] = "%llu\n"; @@ -145,13 +146,10 @@ static ssize_t show_speed(struct device *dev, if (!rtnl_trylock()) return restart_syscall(); - if (netif_running(netdev) && - netdev->ethtool_ops && - netdev->ethtool_ops->get_settings) { - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - - if (!netdev->ethtool_ops->get_settings(netdev, &cmd)) - ret = sprintf(buf, fmt_dec, ethtool_cmd_speed(&cmd)); + if (netif_running(netdev)) { + struct ethtool_cmd cmd; + if (!dev_ethtool_get_settings(netdev, &cmd)) + ret = sprintf(buf, fmt_udec, ethtool_cmd_speed(&cmd)); } rtnl_unlock(); return ret; @@ -166,13 +164,11 @@ static ssize_t show_duplex(struct device *dev, if (!rtnl_trylock()) return restart_syscall(); - if (netif_running(netdev) && - netdev->ethtool_ops && - netdev->ethtool_ops->get_settings) { - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - - if (!netdev->ethtool_ops->get_settings(netdev, &cmd)) - ret = sprintf(buf, "%s\n", cmd.duplex ? "full" : "half"); + if (netif_running(netdev)) { + struct ethtool_cmd cmd; + if (!dev_ethtool_get_settings(netdev, &cmd)) + ret = sprintf(buf, "%s\n", + cmd.duplex ? "full" : "half"); } rtnl_unlock(); return ret; -- cgit v1.2.3-58-ga151 From 25db0338813a8915457636b1f6abe6a28fa73f8d Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 27 Apr 2011 18:32:39 +0000 Subject: ethtool: Use full 32 bit speed range in ethtool's set_settings This makes sure the ethtool's set_settings() callback of network drivers don't ignore the 16 most significant bits when ethtool calls their set_settings(). All drivers compiled with make allyesconfig on x86_64 have been updated. Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- drivers/net/acenic.c | 2 +- drivers/net/atl1c/atl1c_ethtool.c | 5 +++-- drivers/net/atlx/atl1.c | 5 +++-- drivers/net/b44.c | 7 ++++--- drivers/net/bna/bnad_ethtool.c | 3 ++- drivers/net/bnx2.c | 12 ++++++------ drivers/net/cassini.c | 12 +++++++----- drivers/net/chelsio/cxgb2.c | 7 ++++--- drivers/net/cxgb3/cxgb3_main.c | 10 ++++++---- drivers/net/cxgb4/cxgb4_main.c | 11 ++++++----- drivers/net/dl2k.c | 25 +++++++------------------ drivers/net/e100.c | 8 +++++--- drivers/net/e1000/e1000_ethtool.c | 6 ++++-- drivers/net/e1000e/ethtool.c | 3 ++- drivers/net/enc28j60.c | 3 ++- drivers/net/forcedeth.c | 11 ++++++----- drivers/net/igb/igb_ethtool.c | 3 ++- drivers/net/ixgb/ixgb_ethtool.c | 3 ++- drivers/net/ixgbe/ixgbe_ethtool.c | 3 ++- drivers/net/jme.c | 3 ++- drivers/net/ksz884x.c | 9 +++++---- drivers/net/mii.c | 13 +++++++------ drivers/net/mlx4/en_ethtool.c | 3 ++- drivers/net/natsemi.c | 5 +++-- drivers/net/netxen/netxen_nic_ethtool.c | 5 +++-- drivers/net/niu.c | 2 +- drivers/net/pch_gbe/pch_gbe_ethtool.c | 11 +++++++---- drivers/net/pcmcia/smc91c92_cs.c | 4 ++-- drivers/net/phy/phy.c | 10 ++++++---- drivers/net/r8169.c | 3 ++- drivers/net/s2io.c | 2 +- drivers/net/sc92031.c | 5 +++-- drivers/net/sfc/ethtool.c | 3 ++- drivers/net/sfc/mcdi_phy.c | 4 ++-- drivers/net/skge.c | 5 +++-- drivers/net/sky2.c | 5 +++-- drivers/net/sungem.c | 9 +++++---- drivers/net/sunhme.c | 6 +++--- drivers/net/tg3.c | 9 +++++---- drivers/net/tulip/de2104x.c | 5 +++-- drivers/net/typhoon.c | 17 +++++++++-------- drivers/net/via-velocity.c | 10 ++++++---- drivers/net/vxge/vxge-ethtool.c | 3 ++- net/bridge/br_if.c | 4 ++-- 44 files changed, 163 insertions(+), 131 deletions(-) diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index ee648fe5d96f..0b4d8d13c488 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -2718,7 +2718,7 @@ static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) link |= LNK_TX_FLOW_CTL_Y; if (ecmd->autoneg == AUTONEG_ENABLE) link |= LNK_NEGOTIATE; - if (ecmd->speed != speed) { + if (ethtool_cmd_speed(ecmd) != speed) { link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB); switch (speed) { case SPEED_1000: diff --git a/drivers/net/atl1c/atl1c_ethtool.c b/drivers/net/atl1c/atl1c_ethtool.c index 3af5a336a5af..b1eceee424aa 100644 --- a/drivers/net/atl1c/atl1c_ethtool.c +++ b/drivers/net/atl1c/atl1c_ethtool.c @@ -77,7 +77,8 @@ static int atl1c_set_settings(struct net_device *netdev, if (ecmd->autoneg == AUTONEG_ENABLE) { autoneg_advertised = ADVERTISED_Autoneg; } else { - if (ecmd->speed == SPEED_1000) { + u32 speed = ethtool_cmd_speed(ecmd); + if (speed == SPEED_1000) { if (ecmd->duplex != DUPLEX_FULL) { if (netif_msg_link(adapter)) dev_warn(&adapter->pdev->dev, @@ -86,7 +87,7 @@ static int atl1c_set_settings(struct net_device *netdev, return -EINVAL; } autoneg_advertised = ADVERTISED_1000baseT_Full; - } else if (ecmd->speed == SPEED_100) { + } else if (speed == SPEED_100) { if (ecmd->duplex == DUPLEX_FULL) autoneg_advertised = ADVERTISED_100baseT_Full; else diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index dffa6919a419..37a092fa2ba6 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -3268,7 +3268,8 @@ static int atl1_set_settings(struct net_device *netdev, if (ecmd->autoneg == AUTONEG_ENABLE) hw->media_type = MEDIA_TYPE_AUTO_SENSOR; else { - if (ecmd->speed == SPEED_1000) { + u32 speed = ethtool_cmd_speed(ecmd); + if (speed == SPEED_1000) { if (ecmd->duplex != DUPLEX_FULL) { if (netif_msg_link(adapter)) dev_warn(&adapter->pdev->dev, @@ -3277,7 +3278,7 @@ static int atl1_set_settings(struct net_device *netdev, goto exit_sset; } hw->media_type = MEDIA_TYPE_1000M_FULL; - } else if (ecmd->speed == SPEED_100) { + } else if (speed == SPEED_100) { if (ecmd->duplex == DUPLEX_FULL) hw->media_type = MEDIA_TYPE_100M_FULL; else diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 2e2b76258ab4..909cc4b2a2f3 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1831,6 +1831,7 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct b44 *bp = netdev_priv(dev); + u32 speed = ethtool_cmd_speed(cmd); /* We do not support gigabit. */ if (cmd->autoneg == AUTONEG_ENABLE) { @@ -1838,8 +1839,8 @@ static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) return -EINVAL; - } else if ((cmd->speed != SPEED_100 && - cmd->speed != SPEED_10) || + } else if ((speed != SPEED_100 && + speed != SPEED_10) || (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL)) { return -EINVAL; @@ -1873,7 +1874,7 @@ static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) } else { bp->flags |= B44_FLAG_FORCE_LINK; bp->flags &= ~(B44_FLAG_100_BASE_T | B44_FLAG_FULL_DUPLEX); - if (cmd->speed == SPEED_100) + if (speed == SPEED_100) bp->flags |= B44_FLAG_100_BASE_T; if (cmd->duplex == DUPLEX_FULL) bp->flags |= B44_FLAG_FULL_DUPLEX; diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c index c51e078e8f0d..ae1e118f9c3a 100644 --- a/drivers/net/bna/bnad_ethtool.c +++ b/drivers/net/bna/bnad_ethtool.c @@ -256,7 +256,8 @@ bnad_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) /* 10G full duplex setting supported only */ if (cmd->autoneg == AUTONEG_ENABLE) return -EOPNOTSUPP; else { - if ((cmd->speed == SPEED_10000) && (cmd->duplex == DUPLEX_FULL)) + if ((ethtool_cmd_speed(cmd) == SPEED_10000) + && (cmd->duplex == DUPLEX_FULL)) return 0; } diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index bf729ee6acbd..e43efd86425b 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -6758,21 +6758,21 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) advertising |= ADVERTISED_Autoneg; } else { + u32 speed = ethtool_cmd_speed(cmd); if (cmd->port == PORT_FIBRE) { - if ((cmd->speed != SPEED_1000 && - cmd->speed != SPEED_2500) || + if ((speed != SPEED_1000 && + speed != SPEED_2500) || (cmd->duplex != DUPLEX_FULL)) goto err_out_unlock; - if (cmd->speed == SPEED_2500 && + if (speed == SPEED_2500 && !(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)) goto err_out_unlock; - } - else if (cmd->speed == SPEED_1000 || cmd->speed == SPEED_2500) + } else if (speed == SPEED_1000 || speed == SPEED_2500) goto err_out_unlock; autoneg &= ~AUTONEG_SPEED; - req_line_speed = cmd->speed; + req_line_speed = speed; req_duplex = cmd->duplex; advertising = 0; } diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 143a28c666af..a6c3f8c8c302 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -709,10 +709,11 @@ static void cas_begin_auto_negotiation(struct cas *cp, struct ethtool_cmd *ep) if (ep->autoneg == AUTONEG_ENABLE) cp->link_cntl = BMCR_ANENABLE; else { + u32 speed = ethtool_cmd_speed(ep); cp->link_cntl = 0; - if (ep->speed == SPEED_100) + if (speed == SPEED_100) cp->link_cntl |= BMCR_SPEED100; - else if (ep->speed == SPEED_1000) + else if (speed == SPEED_1000) cp->link_cntl |= CAS_BMCR_SPEED1000; if (ep->duplex == DUPLEX_FULL) cp->link_cntl |= BMCR_FULLDPLX; @@ -4653,6 +4654,7 @@ static int cas_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct cas *cp = netdev_priv(dev); unsigned long flags; + u32 speed = ethtool_cmd_speed(cmd); /* Verify the settings we care about. */ if (cmd->autoneg != AUTONEG_ENABLE && @@ -4660,9 +4662,9 @@ static int cas_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) return -EINVAL; if (cmd->autoneg == AUTONEG_DISABLE && - ((cmd->speed != SPEED_1000 && - cmd->speed != SPEED_100 && - cmd->speed != SPEED_10) || + ((speed != SPEED_1000 && + speed != SPEED_100 && + speed != SPEED_10) || (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL))) return -EINVAL; diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 5f82c9c34978..8e14d652996b 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -638,11 +638,12 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) return -EOPNOTSUPP; /* can't change speed/duplex */ if (cmd->autoneg == AUTONEG_DISABLE) { - int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex); + u32 speed = ethtool_cmd_speed(cmd); + int cap = speed_duplex_to_caps(speed, cmd->duplex); - if (!(lc->supported & cap) || cmd->speed == SPEED_1000) + if (!(lc->supported & cap) || (speed == SPEED_1000)) return -EINVAL; - lc->requested_speed = cmd->speed; + lc->requested_speed = speed; lc->requested_duplex = cmd->duplex; lc->advertising = 0; } else { diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 040491804efb..0526715cc8c7 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1821,7 +1821,8 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) * being requested. */ if (cmd->autoneg == AUTONEG_DISABLE) { - int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex); + u32 speed = ethtool_cmd_speed(cmd); + int cap = speed_duplex_to_caps(speed, cmd->duplex); if (lc->supported & cap) return 0; } @@ -1829,11 +1830,12 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) } if (cmd->autoneg == AUTONEG_DISABLE) { - int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex); + u32 speed = ethtool_cmd_speed(cmd); + int cap = speed_duplex_to_caps(speed, cmd->duplex); - if (!(lc->supported & cap) || cmd->speed == SPEED_1000) + if (!(lc->supported & cap) || (speed == SPEED_1000)) return -EINVAL; - lc->requested_speed = cmd->speed; + lc->requested_speed = speed; lc->requested_duplex = cmd->duplex; lc->advertising = 0; } else { diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c index bdc868ca47ec..c02b4d3b73fc 100644 --- a/drivers/net/cxgb4/cxgb4_main.c +++ b/drivers/net/cxgb4/cxgb4_main.c @@ -1460,6 +1460,7 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) unsigned int cap; struct port_info *p = netdev_priv(dev); struct link_config *lc = &p->link_cfg; + u32 speed = ethtool_cmd_speed(cmd); if (cmd->duplex != DUPLEX_FULL) /* only full-duplex supported */ return -EINVAL; @@ -1470,16 +1471,16 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) * being requested. */ if (cmd->autoneg == AUTONEG_DISABLE && - (lc->supported & speed_to_caps(cmd->speed))) - return 0; + (lc->supported & speed_to_caps(speed))) + return 0; return -EINVAL; } if (cmd->autoneg == AUTONEG_DISABLE) { - cap = speed_to_caps(cmd->speed); + cap = speed_to_caps(speed); - if (!(lc->supported & cap) || cmd->speed == SPEED_1000 || - cmd->speed == SPEED_10000) + if (!(lc->supported & cap) || (speed == SPEED_1000) || + (speed == SPEED_10000)) return -EINVAL; lc->requested_speed = cap; lc->advertising = 0; diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index c05db6046050..ab63989619d4 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -1219,31 +1219,20 @@ static int rio_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) } else { np->an_enable = 0; if (np->speed == 1000) { - cmd->speed = SPEED_100; + ethtool_cmd_speed_set(cmd, SPEED_100); cmd->duplex = DUPLEX_FULL; printk("Warning!! Can't disable Auto negotiation in 1000Mbps, change to Manual 100Mbps, Full duplex.\n"); } - switch(cmd->speed + cmd->duplex) { - - case SPEED_10 + DUPLEX_HALF: - np->speed = 10; - np->full_duplex = 0; - break; - - case SPEED_10 + DUPLEX_FULL: + switch (ethtool_cmd_speed(cmd)) { + case SPEED_10: np->speed = 10; - np->full_duplex = 1; + np->full_duplex = (cmd->duplex == DUPLEX_FULL); break; - case SPEED_100 + DUPLEX_HALF: + case SPEED_100: np->speed = 100; - np->full_duplex = 0; - break; - case SPEED_100 + DUPLEX_FULL: - np->speed = 100; - np->full_duplex = 1; + np->full_duplex = (cmd->duplex == DUPLEX_FULL); break; - case SPEED_1000 + DUPLEX_HALF:/* not supported */ - case SPEED_1000 + DUPLEX_FULL:/* not supported */ + case SPEED_1000: /* not supported */ default: return -EINVAL; } diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 66ba596a4d37..c810cda3bf1f 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1669,6 +1669,7 @@ static void e100_watchdog(unsigned long data) { struct nic *nic = (struct nic *)data; struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; + u32 speed; netif_printk(nic, timer, KERN_DEBUG, nic->netdev, "right now = %ld\n", jiffies); @@ -1676,10 +1677,11 @@ static void e100_watchdog(unsigned long data) /* mii library handles link maintenance tasks */ mii_ethtool_gset(&nic->mii, &cmd); + speed = ethtool_cmd_speed(&cmd); if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { netdev_info(nic->netdev, "NIC Link is Up %u Mbps %s Duplex\n", - cmd.speed == SPEED_100 ? 100 : 10, + speed == SPEED_100 ? 100 : 10, cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { netdev_info(nic->netdev, "NIC Link is Down\n"); @@ -1698,13 +1700,13 @@ static void e100_watchdog(unsigned long data) spin_unlock_irq(&nic->cmd_lock); e100_update_stats(nic); - e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); + e100_adjust_adaptive_ifs(nic, speed, cmd.duplex); if (nic->mac <= mac_82557_D100_C) /* Issue a multicast command to workaround a 557 lock up */ e100_set_multicast_list(nic->netdev); - if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) + if (nic->flags & ich && speed == SPEED_10 && cmd.duplex == DUPLEX_HALF) /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ nic->flags |= ich_10h_workaround; else diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index dd70738eb2f4..a53629d9325d 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -197,11 +197,13 @@ static int e1000_set_settings(struct net_device *netdev, ADVERTISED_TP | ADVERTISED_Autoneg; ecmd->advertising = hw->autoneg_advertised; - } else - if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) { + } else { + u32 speed = ethtool_cmd_speed(ecmd); + if (e1000_set_spd_dplx(adapter, speed + ecmd->duplex)) { clear_bit(__E1000_RESETTING, &adapter->flags); return -EINVAL; } + } /* reset the link */ diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 1d7bf4049c02..bc02c6b91f15 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -269,7 +269,8 @@ static int e1000_set_settings(struct net_device *netdev, if (adapter->fc_autoneg) hw->fc.requested_mode = e1000_fc_default; } else { - if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) { + u32 speed = ethtool_cmd_speed(ecmd); + if (e1000_set_spd_dplx(adapter, speed + ecmd->duplex)) { clear_bit(__E1000_RESETTING, &adapter->state); return -EINVAL; } diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index 907b05a1c659..81a793747f2e 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c @@ -1499,7 +1499,8 @@ enc28j60_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int enc28j60_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - return enc28j60_setlink(dev, cmd->autoneg, cmd->speed, cmd->duplex); + return enc28j60_setlink(dev, cmd->autoneg, + ethtool_cmd_speed(cmd), cmd->duplex); } static u32 enc28j60_get_msglevel(struct net_device *dev) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 0e1c76a8c045..d24b3f3e646b 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -4029,6 +4029,7 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct fe_priv *np = netdev_priv(dev); + u32 speed = ethtool_cmd_speed(ecmd); if (ecmd->port != PORT_MII) return -EINVAL; @@ -4054,7 +4055,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) /* Note: autonegotiation disable, speed 1000 intentionally * forbidden - no one should need that. */ - if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100) + if (speed != SPEED_10 && speed != SPEED_100) return -EINVAL; if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) return -EINVAL; @@ -4138,13 +4139,13 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF) + if (speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF) adv |= ADVERTISE_10HALF; - if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL) + if (speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL) adv |= ADVERTISE_10FULL; - if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_HALF) + if (speed == SPEED_100 && ecmd->duplex == DUPLEX_HALF) adv |= ADVERTISE_100HALF; - if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL) + if (speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL) adv |= ADVERTISE_100FULL; np->pause_flags &= ~(NV_PAUSEFRAME_AUTONEG|NV_PAUSEFRAME_RX_ENABLE|NV_PAUSEFRAME_TX_ENABLE); if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) {/* for rx we set both advertisements but disable tx pause */ diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index d976733bbcc2..2cc221b65cd4 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -223,7 +223,8 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) if (adapter->fc_autoneg) hw->fc.requested_mode = e1000_fc_default; } else { - if (igb_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) { + u32 speed = ethtool_cmd_speed(ecmd); + if (igb_set_spd_dplx(adapter, speed + ecmd->duplex)) { clear_bit(__IGB_RESETTING, &adapter->state); return -EINVAL; } diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c index cc53aa1541ba..edb3d7eaf6d5 100644 --- a/drivers/net/ixgb/ixgb_ethtool.c +++ b/drivers/net/ixgb/ixgb_ethtool.c @@ -129,9 +129,10 @@ static int ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { struct ixgb_adapter *adapter = netdev_priv(netdev); + u32 speed = ethtool_cmd_speed(ecmd); if (ecmd->autoneg == AUTONEG_ENABLE || - ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL) + (speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)) return -EINVAL; if (netif_running(adapter->netdev)) { diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 7279345b1ed7..c52243d67edc 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -346,9 +346,10 @@ static int ixgbe_set_settings(struct net_device *netdev, } } else { /* in this case we currently only support 10Gb/FULL */ + u32 speed = ethtool_cmd_speed(ecmd); if ((ecmd->autoneg == AUTONEG_ENABLE) || (ecmd->advertising != ADVERTISED_10000baseT_Full) || - (ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)) + (speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)) return -EINVAL; } diff --git a/drivers/net/jme.c b/drivers/net/jme.c index be4773f54a24..b5b174a8c149 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -2555,7 +2555,8 @@ jme_set_settings(struct net_device *netdev, struct jme_adapter *jme = netdev_priv(netdev); int rc, fdc = 0; - if (ecmd->speed == SPEED_1000 && ecmd->autoneg != AUTONEG_ENABLE) + if (ethtool_cmd_speed(ecmd) == SPEED_1000 + && ecmd->autoneg != AUTONEG_ENABLE) return -EINVAL; /* diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c index 2c37a3804303..41ea5920c158 100644 --- a/drivers/net/ksz884x.c +++ b/drivers/net/ksz884x.c @@ -5998,6 +5998,7 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) struct dev_priv *priv = netdev_priv(dev); struct dev_info *hw_priv = priv->adapter; struct ksz_port *port = &priv->port; + u32 speed = ethtool_cmd_speed(cmd); int rc; /* @@ -6006,11 +6007,11 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) */ if (cmd->autoneg && priv->advertising == cmd->advertising) { cmd->advertising |= ADVERTISED_ALL; - if (10 == cmd->speed) + if (10 == speed) cmd->advertising &= ~(ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half); - else if (100 == cmd->speed) + else if (100 == speed) cmd->advertising &= ~(ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half); @@ -6032,8 +6033,8 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) port->force_link = 0; } else { port->duplex = cmd->duplex + 1; - if (cmd->speed != 1000) - port->speed = cmd->speed; + if (1000 != speed) + port->speed = speed; if (cmd->autoneg) port->force_link = 0; else diff --git a/drivers/net/mii.c b/drivers/net/mii.c index 05acca78f63a..e8198edeaa76 100644 --- a/drivers/net/mii.c +++ b/drivers/net/mii.c @@ -157,10 +157,11 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) { struct net_device *dev = mii->dev; + u32 speed = ethtool_cmd_speed(ecmd); - if (ecmd->speed != SPEED_10 && - ecmd->speed != SPEED_100 && - ecmd->speed != SPEED_1000) + if (speed != SPEED_10 && + speed != SPEED_100 && + speed != SPEED_1000) return -EINVAL; if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) return -EINVAL; @@ -172,7 +173,7 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) return -EINVAL; if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) return -EINVAL; - if ((ecmd->speed == SPEED_1000) && (!mii->supports_gmii)) + if ((speed == SPEED_1000) && (!mii->supports_gmii)) return -EINVAL; /* ignore supported, maxtxpkt, maxrxpkt */ @@ -230,9 +231,9 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_FULLDPLX); - if (ecmd->speed == SPEED_1000) + if (speed == SPEED_1000) tmp |= BMCR_SPEED1000; - else if (ecmd->speed == SPEED_100) + else if (speed == SPEED_100) tmp |= BMCR_SPEED100; if (ecmd->duplex == DUPLEX_FULL) { tmp |= BMCR_FULLDPLX; diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c index da1b64d68607..be4a9e0b2406 100644 --- a/drivers/net/mlx4/en_ethtool.c +++ b/drivers/net/mlx4/en_ethtool.c @@ -292,7 +292,8 @@ static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int mlx4_en_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { if ((cmd->autoneg == AUTONEG_ENABLE) || - (cmd->speed != SPEED_10000) || (cmd->duplex != DUPLEX_FULL)) + (ethtool_cmd_speed(cmd) != SPEED_10000) || + (cmd->duplex != DUPLEX_FULL)) return -EINVAL; /* Nothing to change */ diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 1074231f0a0d..7633c67b7842 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2908,7 +2908,8 @@ static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) return -EINVAL; } } else if (ecmd->autoneg == AUTONEG_DISABLE) { - if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100) + u32 speed = ethtool_cmd_speed(ecmd); + if (speed != SPEED_10 && speed != SPEED_100) return -EINVAL; if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) return -EINVAL; @@ -2956,7 +2957,7 @@ static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) if (ecmd->advertising & ADVERTISED_100baseT_Full) np->advertising |= ADVERTISE_100FULL; } else { - np->speed = ecmd->speed; + np->speed = ethtool_cmd_speed(ecmd); np->duplex = ecmd->duplex; /* user overriding the initial full duplex parm? */ if (np->duplex == DUPLEX_HALF) diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 29f90baaa79b..e8d16f6f11e3 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -251,6 +251,7 @@ static int netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct netxen_adapter *adapter = netdev_priv(dev); + u32 speed = ethtool_cmd_speed(ecmd); int ret; if (adapter->ahw.port_type != NETXEN_NIC_GBE) @@ -259,14 +260,14 @@ netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) if (!(adapter->capabilities & NX_FW_CAPABILITY_GBE_LINK_CFG)) return -EOPNOTSUPP; - ret = nx_fw_cmd_set_gbe_port(adapter, ecmd->speed, ecmd->duplex, + ret = nx_fw_cmd_set_gbe_port(adapter, speed, ecmd->duplex, ecmd->autoneg); if (ret == NX_RCODE_NOT_SUPPORTED) return -EOPNOTSUPP; else if (ret) return -EIO; - adapter->link_speed = ecmd->speed; + adapter->link_speed = speed; adapter->link_duplex = ecmd->duplex; adapter->link_autoneg = ecmd->autoneg; diff --git a/drivers/net/niu.c b/drivers/net/niu.c index a7072174ffa7..524e800ddcf4 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -6859,7 +6859,7 @@ static int niu_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) struct niu_link_config *lp = &np->link_config; lp->advertising = cmd->advertising; - lp->speed = cmd->speed; + lp->speed = ethtool_cmd_speed(cmd); lp->duplex = cmd->duplex; lp->autoneg = cmd->autoneg; return niu_init_link(np); diff --git a/drivers/net/pch_gbe/pch_gbe_ethtool.c b/drivers/net/pch_gbe/pch_gbe_ethtool.c index c35d105ab285..ea2d8e41887a 100644 --- a/drivers/net/pch_gbe/pch_gbe_ethtool.c +++ b/drivers/net/pch_gbe/pch_gbe_ethtool.c @@ -92,7 +92,7 @@ static int pch_gbe_get_settings(struct net_device *netdev, ecmd->advertising &= ~(ADVERTISED_TP | ADVERTISED_1000baseT_Half); if (!netif_carrier_ok(adapter->netdev)) - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); return ret; } @@ -109,12 +109,15 @@ static int pch_gbe_set_settings(struct net_device *netdev, { struct pch_gbe_adapter *adapter = netdev_priv(netdev); struct pch_gbe_hw *hw = &adapter->hw; + u32 speed = ethtool_cmd_speed(ecmd); int ret; pch_gbe_hal_write_phy_reg(hw, MII_BMCR, BMCR_RESET); - if (ecmd->speed == USHRT_MAX) { - ecmd->speed = SPEED_1000; + /* when set_settings() is called with a ethtool_cmd previously + * filled by get_settings() on a down link, speed is -1: */ + if (speed == UINT_MAX) { + speed = SPEED_1000; ecmd->duplex = DUPLEX_FULL; } ret = mii_ethtool_sset(&adapter->mii, ecmd); @@ -122,7 +125,7 @@ static int pch_gbe_set_settings(struct net_device *netdev, pr_err("Error: mii_ethtool_sset\n"); return ret; } - hw->mac.link_speed = ecmd->speed; + hw->mac.link_speed = speed; hw->mac.link_duplex = ecmd->duplex; hw->phy.autoneg_advertised = ecmd->advertising; hw->mac.autoneg = ecmd->autoneg; diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 108591756440..bc71cb260ff4 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1875,8 +1875,8 @@ static int smc_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) u16 tmp; unsigned int ioaddr = dev->base_addr; - if (ecmd->speed != SPEED_10) - return -EINVAL; + if (ethtool_cmd_speed(ecmd) != SPEED_10) + return -EINVAL; if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) return -EINVAL; if (ecmd->port != PORT_TP && ecmd->port != PORT_AUI) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index f7670330f988..e3f3501d4347 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -238,6 +238,8 @@ static void phy_sanitize_settings(struct phy_device *phydev) */ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd) { + u32 speed = ethtool_cmd_speed(cmd); + if (cmd->phy_address != phydev->addr) return -EINVAL; @@ -253,16 +255,16 @@ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd) return -EINVAL; if (cmd->autoneg == AUTONEG_DISABLE && - ((cmd->speed != SPEED_1000 && - cmd->speed != SPEED_100 && - cmd->speed != SPEED_10) || + ((speed != SPEED_1000 && + speed != SPEED_100 && + speed != SPEED_10) || (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL))) return -EINVAL; phydev->autoneg = cmd->autoneg; - phydev->speed = cmd->speed; + phydev->speed = speed; phydev->advertising = cmd->advertising; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 6364e0b03fdd..b52ee17de74d 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1349,7 +1349,8 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) spin_lock_irqsave(&tp->lock, flags); ret = rtl8169_set_speed(dev, - cmd->autoneg, cmd->speed, cmd->duplex, cmd->advertising); + cmd->autoneg, ethtool_cmd_speed(cmd), + cmd->duplex, cmd->advertising); spin_unlock_irqrestore(&tp->lock, flags); return ret; diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 58b78f46e54f..5443985c019e 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -5380,7 +5380,7 @@ static int s2io_ethtool_sset(struct net_device *dev, { struct s2io_nic *sp = netdev_priv(dev); if ((info->autoneg == AUTONEG_ENABLE) || - (info->speed != SPEED_10000) || + (ethtool_cmd_speed(info) != SPEED_10000) || (info->duplex != DUPLEX_FULL)) return -EINVAL; else { diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 76290a8c3c14..f3ffc1df3b2d 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -1188,10 +1188,11 @@ static int sc92031_ethtool_set_settings(struct net_device *dev, { struct sc92031_priv *priv = netdev_priv(dev); void __iomem *port_base = priv->port_base; + u32 speed = ethtool_cmd_speed(cmd); u32 phy_ctrl; u32 old_phy_ctrl; - if (!(cmd->speed == SPEED_10 || cmd->speed == SPEED_100)) + if (!(speed == SPEED_10 || speed == SPEED_100)) return -EINVAL; if (!(cmd->duplex == DUPLEX_HALF || cmd->duplex == DUPLEX_FULL)) return -EINVAL; @@ -1229,7 +1230,7 @@ static int sc92031_ethtool_set_settings(struct net_device *dev, // FIXME: Whole branch guessed phy_ctrl = 0; - if (cmd->speed == SPEED_10) + if (speed == SPEED_10) phy_ctrl |= PhyCtrlSpd10; else /* cmd->speed == SPEED_100 */ phy_ctrl |= PhyCtrlSpd100; diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 5d8468fc5804..10b160a508f3 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -234,7 +234,8 @@ static int efx_ethtool_set_settings(struct net_device *net_dev, int rc; /* GMAC does not support 1000Mbps HD */ - if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) { + if ((ethtool_cmd_speed(ecmd) == SPEED_1000) && + (ecmd->duplex != DUPLEX_FULL)) { netif_dbg(efx, drv, efx->net_dev, "rejecting unsupported 1000Mbps HD setting\n"); return -EINVAL; diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c index 1fcda2d82399..6c5fccbdeca2 100644 --- a/drivers/net/sfc/mcdi_phy.c +++ b/drivers/net/sfc/mcdi_phy.c @@ -545,7 +545,7 @@ static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ec caps = (ethtool_to_mcdi_cap(ecmd->advertising) | 1 << MC_CMD_PHY_CAP_AN_LBN); } else if (ecmd->duplex) { - switch (ecmd->speed) { + switch (ethtool_cmd_speed(ecmd)) { case 10: caps = 1 << MC_CMD_PHY_CAP_10FDX_LBN; break; case 100: caps = 1 << MC_CMD_PHY_CAP_100FDX_LBN; break; case 1000: caps = 1 << MC_CMD_PHY_CAP_1000FDX_LBN; break; @@ -553,7 +553,7 @@ static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ec default: return -EINVAL; } } else { - switch (ecmd->speed) { + switch (ethtool_cmd_speed(ecmd)) { case 10: caps = 1 << MC_CMD_PHY_CAP_10HDX_LBN; break; case 100: caps = 1 << MC_CMD_PHY_CAP_100HDX_LBN; break; case 1000: caps = 1 << MC_CMD_PHY_CAP_1000HDX_LBN; break; diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 176d784cbb54..a05e864de674 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -321,8 +321,9 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) skge->speed = -1; } else { u32 setting; + u32 speed = ethtool_cmd_speed(ecmd); - switch (ecmd->speed) { + switch (speed) { case SPEED_1000: if (ecmd->duplex == DUPLEX_FULL) setting = SUPPORTED_1000baseT_Full; @@ -355,7 +356,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) if ((setting & supported) == 0) return -EINVAL; - skge->speed = ecmd->speed; + skge->speed = speed; skge->duplex = ecmd->duplex; } diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index c8d045114c66..5c7e2d68df2a 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3452,8 +3452,9 @@ static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) sky2->speed = -1; } else { u32 setting; + u32 speed = ethtool_cmd_speed(ecmd); - switch (ecmd->speed) { + switch (speed) { case SPEED_1000: if (ecmd->duplex == DUPLEX_FULL) setting = SUPPORTED_1000baseT_Full; @@ -3486,7 +3487,7 @@ static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) if ((setting & supported) == 0) return -EINVAL; - sky2->speed = ecmd->speed; + sky2->speed = speed; sky2->duplex = ecmd->duplex; sky2->flags &= ~SKY2_FLAG_AUTO_SPEED; } diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 81b6eb8ed4d7..40a755dd1a26 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -1294,7 +1294,7 @@ static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep) autoneg = 1; } else { autoneg = 0; - speed = ep->speed; + speed = ethtool_cmd_speed(ep); duplex = ep->duplex; } @@ -2686,6 +2686,7 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct gem *gp = netdev_priv(dev); + u32 speed = ethtool_cmd_speed(cmd); /* Verify the settings we care about. */ if (cmd->autoneg != AUTONEG_ENABLE && @@ -2697,9 +2698,9 @@ static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) return -EINVAL; if (cmd->autoneg == AUTONEG_DISABLE && - ((cmd->speed != SPEED_1000 && - cmd->speed != SPEED_100 && - cmd->speed != SPEED_10) || + ((speed != SPEED_1000 && + speed != SPEED_100 && + speed != SPEED_10) || (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL))) return -EINVAL; diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 80e907df36b4..8f3f02802427 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -1383,7 +1383,7 @@ force_link: if (ep == NULL || ep->autoneg == AUTONEG_ENABLE) { hp->sw_bmcr = BMCR_SPEED100; } else { - if (ep->speed == SPEED_100) + if (ethtool_cmd_speed(ep) == SPEED_100) hp->sw_bmcr = BMCR_SPEED100; else hp->sw_bmcr = 0; @@ -2452,8 +2452,8 @@ static int hme_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->autoneg != AUTONEG_DISABLE) return -EINVAL; if (cmd->autoneg == AUTONEG_DISABLE && - ((cmd->speed != SPEED_100 && - cmd->speed != SPEED_10) || + ((ethtool_cmd_speed(cmd) != SPEED_100 && + ethtool_cmd_speed(cmd) != SPEED_10) || (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL))) return -EINVAL; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index fa57e3d699de..004f266e4352 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10042,6 +10042,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct tg3 *tp = netdev_priv(dev); + u32 speed = ethtool_cmd_speed(cmd); if (tg3_flag(tp, USE_PHYLIB)) { struct phy_device *phydev; @@ -10091,14 +10092,14 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->advertising &= mask; } else { if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES) { - if (cmd->speed != SPEED_1000) + if (speed != SPEED_1000) return -EINVAL; if (cmd->duplex != DUPLEX_FULL) return -EINVAL; } else { - if (cmd->speed != SPEED_100 && - cmd->speed != SPEED_10) + if (speed != SPEED_100 && + speed != SPEED_10) return -EINVAL; } } @@ -10113,7 +10114,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) tp->link_config.duplex = DUPLEX_INVALID; } else { tp->link_config.advertising = 0; - tp->link_config.speed = cmd->speed; + tp->link_config.speed = speed; tp->link_config.duplex = cmd->duplex; } diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index b13c6b040be3..f8d26bf9b2c4 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -1549,10 +1549,11 @@ static int __de_set_settings(struct de_private *de, struct ethtool_cmd *ecmd) { u32 new_media; unsigned int media_lock; + u32 speed = ethtool_cmd_speed(ecmd); - if (ecmd->speed != SPEED_10 && ecmd->speed != 5 && ecmd->speed != 2) + if (speed != SPEED_10 && speed != 5 && speed != 2) return -EINVAL; - if (de->de21040 && ecmd->speed == 2) + if (de->de21040 && speed == 2) return -EINVAL; if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) return -EINVAL; diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 119c394f71ce..9f11c111b65d 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -1068,25 +1068,26 @@ static int typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct typhoon *tp = netdev_priv(dev); + u32 speed = ethtool_cmd_speed(cmd); struct cmd_desc xp_cmd; __le16 xcvr; int err; err = -EINVAL; - if(cmd->autoneg == AUTONEG_ENABLE) { + if (cmd->autoneg == AUTONEG_ENABLE) { xcvr = TYPHOON_XCVR_AUTONEG; } else { - if(cmd->duplex == DUPLEX_HALF) { - if(cmd->speed == SPEED_10) + if (cmd->duplex == DUPLEX_HALF) { + if (speed == SPEED_10) xcvr = TYPHOON_XCVR_10HALF; - else if(cmd->speed == SPEED_100) + else if (speed == SPEED_100) xcvr = TYPHOON_XCVR_100HALF; else goto out; - } else if(cmd->duplex == DUPLEX_FULL) { - if(cmd->speed == SPEED_10) + } else if (cmd->duplex == DUPLEX_FULL) { + if (speed == SPEED_10) xcvr = TYPHOON_XCVR_10FULL; - else if(cmd->speed == SPEED_100) + else if (speed == SPEED_100) xcvr = TYPHOON_XCVR_100FULL; else goto out; @@ -1105,7 +1106,7 @@ typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) tp->speed = 0xff; /* invalid */ tp->duplex = 0xff; /* invalid */ } else { - tp->speed = cmd->speed; + tp->speed = speed; tp->duplex = cmd->duplex; } diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index baf04b0a6575..9a8f116e6920 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -3247,9 +3247,11 @@ static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd return 0; } -static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +static int velocity_set_settings(struct net_device *dev, + struct ethtool_cmd *cmd) { struct velocity_info *vptr = netdev_priv(dev); + u32 speed = ethtool_cmd_speed(cmd); u32 curr_status; u32 new_status = 0; int ret = 0; @@ -3258,9 +3260,9 @@ static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd curr_status &= (~VELOCITY_LINK_FAIL); new_status |= ((cmd->autoneg) ? VELOCITY_AUTONEG_ENABLE : 0); - new_status |= ((cmd->speed == SPEED_1000) ? VELOCITY_SPEED_1000 : 0); - new_status |= ((cmd->speed == SPEED_100) ? VELOCITY_SPEED_100 : 0); - new_status |= ((cmd->speed == SPEED_10) ? VELOCITY_SPEED_10 : 0); + new_status |= ((speed == SPEED_1000) ? VELOCITY_SPEED_1000 : 0); + new_status |= ((speed == SPEED_100) ? VELOCITY_SPEED_100 : 0); + new_status |= ((speed == SPEED_10) ? VELOCITY_SPEED_10 : 0); new_status |= ((cmd->duplex == DUPLEX_FULL) ? VELOCITY_DUPLEX_FULL : 0); if ((new_status & VELOCITY_AUTONEG_ENABLE) && diff --git a/drivers/net/vxge/vxge-ethtool.c b/drivers/net/vxge/vxge-ethtool.c index 5aef6c893aee..a70874e64d0e 100644 --- a/drivers/net/vxge/vxge-ethtool.c +++ b/drivers/net/vxge/vxge-ethtool.c @@ -33,7 +33,8 @@ static int vxge_ethtool_sset(struct net_device *dev, struct ethtool_cmd *info) { /* We currently only support 10Gb/FULL */ if ((info->autoneg == AUTONEG_ENABLE) || - (info->speed != SPEED_10000) || (info->duplex != DUPLEX_FULL)) + (ethtool_cmd_speed(info) != SPEED_10000) || + (info->duplex != DUPLEX_FULL)) return -EINVAL; return 0; diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 1156460773dc..5dbdfdfc3a34 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -36,8 +36,8 @@ static int port_cost(struct net_device *dev) if (dev->ethtool_ops && dev->ethtool_ops->get_settings) { struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, }; - if (!dev->ethtool_ops->get_settings(dev, &ecmd)) { - switch(ecmd.speed) { + if (!dev_ethtool_get_settings(dev, &ecmd)) { + switch (ethtool_cmd_speed(&ecmd)) { case SPEED_10000: return 2; case SPEED_1000: -- cgit v1.2.3-58-ga151 From 707394972093e2056e1e8cc39be19cf9bcb3e7b3 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 27 Apr 2011 18:32:40 +0000 Subject: ethtool: cosmetic: Use ethtool ethtool_cmd_speed API This updates the network drivers so that they don't access the ethtool_cmd::speed field directly, but use ethtool_cmd_speed() instead. For most of the drivers, these changes are purely cosmetic and don't fix any problem, such as for those 1GbE/10GbE drivers that indirectly call their own ethtool get_settings()/mii_ethtool_gset(). The changes are meant to enforce code consistency and provide robustness with future larger throughputs, at the expense of a few CPU cycles for each ethtool operation. All drivers compiled with make allyesconfig ion x86_64 have been updated. Tested: make allyesconfig on x86_64 + e1000e/bnx2x work Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- drivers/infiniband/hw/nes/nes_nic.c | 4 ++-- drivers/net/3c509.c | 2 +- drivers/net/acenic.c | 8 ++++---- drivers/net/arm/etherh.c | 5 +++-- drivers/net/arm/ks8695net.c | 7 ++++--- drivers/net/atl1c/atl1c_ethtool.c | 4 ++-- drivers/net/atl1e/atl1e_ethtool.c | 4 ++-- drivers/net/atlx/atl1.c | 4 ++-- drivers/net/atlx/atl2.c | 4 ++-- drivers/net/b44.c | 6 +++--- drivers/net/bcm63xx_enet.c | 3 ++- drivers/net/benet/be_ethtool.c | 16 ++++++++-------- drivers/net/bna/bnad_ethtool.c | 4 ++-- drivers/net/bnx2.c | 7 +++---- drivers/net/cassini.c | 25 ++++++++++++------------- drivers/net/chelsio/cxgb2.c | 4 ++-- drivers/net/cxgb3/cxgb3_main.c | 4 ++-- drivers/net/cxgb4/cxgb4_main.c | 3 ++- drivers/net/cxgb4vf/cxgb4vf_main.c | 3 ++- drivers/net/dl2k.c | 4 ++-- drivers/net/e1000/e1000_ethtool.c | 4 ++-- drivers/net/e1000e/ethtool.c | 12 +++++++----- drivers/net/eepro.c | 2 +- drivers/net/ehea/ehea_ethtool.c | 23 ++++++++++++++++++----- drivers/net/enc28j60.c | 2 +- drivers/net/enic/enic_main.c | 4 ++-- drivers/net/ewrk3.c | 2 +- drivers/net/forcedeth.c | 14 +++++++++----- drivers/net/ibmveth.c | 2 +- drivers/net/igb/igb_ethtool.c | 8 ++++---- drivers/net/igbvf/ethtool.c | 8 ++++---- drivers/net/ixgb/ixgb_ethtool.c | 4 ++-- drivers/net/ixgbe/ixgbe_ethtool.c | 8 ++++---- drivers/net/ixgbevf/ethtool.c | 8 +++++--- drivers/net/mdio.c | 20 ++++++++++++-------- drivers/net/mii.c | 15 +++++++++------ drivers/net/mlx4/en_ethtool.c | 4 ++-- drivers/net/mv643xx_eth.c | 6 +++--- drivers/net/myri10ge/myri10ge.c | 2 +- drivers/net/natsemi.c | 6 +++--- drivers/net/netxen/netxen_nic_ethtool.c | 10 +++++----- drivers/net/niu.c | 2 +- drivers/net/ns83820.c | 8 ++++---- drivers/net/pch_gbe/pch_gbe_phy.c | 2 +- drivers/net/pcmcia/smc91c92_cs.c | 2 +- drivers/net/phy/phy.c | 2 +- drivers/net/ps3_gelic_net.c | 8 ++++---- drivers/net/qla3xxx.c | 2 +- drivers/net/qlcnic/qlcnic_ethtool.c | 8 ++++---- drivers/net/qlge/qlge_ethtool.c | 2 +- drivers/net/r8169.c | 2 +- drivers/net/s2io.c | 4 ++-- drivers/net/sc92031.c | 3 ++- drivers/net/sfc/ethtool.c | 2 +- drivers/net/sfc/mcdi_phy.c | 2 +- drivers/net/sfc/tenxpress.c | 2 +- drivers/net/skge.c | 2 +- drivers/net/sky2.c | 4 ++-- drivers/net/smc911x.c | 4 ++-- drivers/net/smc91x.c | 4 ++-- drivers/net/spider_net_ethtool.c | 2 +- drivers/net/sungem.c | 6 +++--- drivers/net/sunhme.c | 13 ++++++------- drivers/net/tehuti.c | 2 +- drivers/net/tg3.c | 4 ++-- drivers/net/tulip/de2104x.c | 6 +++--- drivers/net/tulip/uli526x.c | 6 +++--- drivers/net/tun.c | 2 +- drivers/net/typhoon.c | 2 +- drivers/net/usb/catc.c | 2 +- drivers/net/usb/rtl8150.c | 11 ++++++----- drivers/net/veth.c | 2 +- drivers/net/via-velocity.c | 11 +++++++---- drivers/net/vmxnet3/vmxnet3_ethtool.c | 4 ++-- drivers/net/vxge/vxge-ethtool.c | 4 ++-- net/batman-adv/soft-interface.c | 2 +- 76 files changed, 232 insertions(+), 197 deletions(-) diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index d2e67c4e3228..d3a1c41cfd27 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -1493,7 +1493,7 @@ static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd et_cmd->maxrxpkt = 511; if (nesadapter->OneG_Mode) { - et_cmd->speed = SPEED_1000; + ethtool_cmd_speed_set(et_cmd, SPEED_1000); if (phy_type == NES_PHY_TYPE_PUMA_1G) { et_cmd->supported = SUPPORTED_1000baseT_Full; et_cmd->advertising = ADVERTISED_1000baseT_Full; @@ -1532,7 +1532,7 @@ static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd et_cmd->advertising = ADVERTISED_10000baseT_Full; et_cmd->phy_address = mac_index; } - et_cmd->speed = SPEED_10000; + ethtool_cmd_speed_set(et_cmd, SPEED_10000); et_cmd->autoneg = AUTONEG_DISABLE; return 0; } diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index cb39dedf46bd..5f25889e27ef 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -1207,7 +1207,7 @@ el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->duplex = DUPLEX_FULL; } - ecmd->speed = SPEED_10; + ethtool_cmd_speed_set(ecmd, SPEED_10); EL3WINDOW(1); return 0; } diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 0b4d8d13c488..a5798991c8b1 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -2658,15 +2658,15 @@ static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) link = readl(®s->GigLnkState); if (link & LNK_1000MB) - ecmd->speed = SPEED_1000; + ethtool_cmd_speed_set(ecmd, SPEED_1000); else { link = readl(®s->FastLnkState); if (link & LNK_100MB) - ecmd->speed = SPEED_100; + ethtool_cmd_speed_set(ecmd, SPEED_100); else if (link & LNK_10MB) - ecmd->speed = SPEED_10; + ethtool_cmd_speed_set(ecmd, SPEED_10); else - ecmd->speed = 0; + ethtool_cmd_speed_set(ecmd, 0); } if (link & LNK_FULL_DUPLEX) ecmd->duplex = DUPLEX_FULL; diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 4af235d41fda..e252cd595016 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -591,10 +591,11 @@ static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i static int etherh_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { cmd->supported = etherh_priv(dev)->supported; - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); cmd->duplex = DUPLEX_HALF; cmd->port = dev->if_port == IF_PORT_10BASET ? PORT_TP : PORT_BNC; - cmd->autoneg = dev->flags & IFF_AUTOMEDIA ? AUTONEG_ENABLE : AUTONEG_DISABLE; + cmd->autoneg = (dev->flags & IFF_AUTOMEDIA ? + AUTONEG_ENABLE : AUTONEG_DISABLE); return 0; } diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index aa07657744c3..a7b0caa18179 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -891,15 +891,16 @@ ks8695_wan_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) cmd->advertising |= ADVERTISED_Pause; cmd->autoneg = AUTONEG_ENABLE; - cmd->speed = (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10; + ethtool_cmd_speed_set(cmd, + (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10); cmd->duplex = (ctrl & WMC_WDS) ? DUPLEX_FULL : DUPLEX_HALF; } else { /* auto-negotiation is disabled */ cmd->autoneg = AUTONEG_DISABLE; - cmd->speed = (ctrl & WMC_WANF100) ? - SPEED_100 : SPEED_10; + ethtool_cmd_speed_set(cmd, ((ctrl & WMC_WANF100) ? + SPEED_100 : SPEED_10)); cmd->duplex = (ctrl & WMC_WANFF) ? DUPLEX_FULL : DUPLEX_HALF; } diff --git a/drivers/net/atl1c/atl1c_ethtool.c b/drivers/net/atl1c/atl1c_ethtool.c index b1eceee424aa..7be884d0aaf6 100644 --- a/drivers/net/atl1c/atl1c_ethtool.c +++ b/drivers/net/atl1c/atl1c_ethtool.c @@ -50,13 +50,13 @@ static int atl1c_get_settings(struct net_device *netdev, ecmd->transceiver = XCVR_INTERNAL; if (adapter->link_speed != SPEED_0) { - ecmd->speed = adapter->link_speed; + ethtool_cmd_speed_set(ecmd, adapter->link_speed); if (adapter->link_duplex == FULL_DUPLEX) ecmd->duplex = DUPLEX_FULL; else ecmd->duplex = DUPLEX_HALF; } else { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } diff --git a/drivers/net/atl1e/atl1e_ethtool.c b/drivers/net/atl1e/atl1e_ethtool.c index 47783749d9fa..6269438d365f 100644 --- a/drivers/net/atl1e/atl1e_ethtool.c +++ b/drivers/net/atl1e/atl1e_ethtool.c @@ -51,13 +51,13 @@ static int atl1e_get_settings(struct net_device *netdev, ecmd->transceiver = XCVR_INTERNAL; if (adapter->link_speed != SPEED_0) { - ecmd->speed = adapter->link_speed; + ethtool_cmd_speed_set(ecmd, adapter->link_speed); if (adapter->link_duplex == FULL_DUPLEX) ecmd->duplex = DUPLEX_FULL; else ecmd->duplex = DUPLEX_HALF; } else { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 37a092fa2ba6..c5298d1ab744 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -3231,13 +3231,13 @@ static int atl1_get_settings(struct net_device *netdev, if (netif_carrier_ok(adapter->netdev)) { u16 link_speed, link_duplex; atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex); - ecmd->speed = link_speed; + ethtool_cmd_speed_set(ecmd, link_speed); if (link_duplex == FULL_DUPLEX) ecmd->duplex = DUPLEX_FULL; else ecmd->duplex = DUPLEX_HALF; } else { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR || diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index b75aa295d37e..16249e9b6b95 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c @@ -1769,13 +1769,13 @@ static int atl2_get_settings(struct net_device *netdev, ecmd->transceiver = XCVR_INTERNAL; if (adapter->link_speed != SPEED_0) { - ecmd->speed = adapter->link_speed; + ethtool_cmd_speed_set(ecmd, adapter->link_speed); if (adapter->link_duplex == FULL_DUPLEX) ecmd->duplex = DUPLEX_FULL; else ecmd->duplex = DUPLEX_HALF; } else { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 909cc4b2a2f3..a69331e06b8d 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1807,8 +1807,8 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (bp->flags & B44_FLAG_ADV_100FULL) cmd->advertising |= ADVERTISED_100baseT_Full; cmd->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause; - cmd->speed = (bp->flags & B44_FLAG_100_BASE_T) ? - SPEED_100 : SPEED_10; + ethtool_cmd_speed_set(cmd, ((bp->flags & B44_FLAG_100_BASE_T) ? + SPEED_100 : SPEED_10)); cmd->duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF; cmd->port = 0; @@ -1820,7 +1820,7 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (cmd->autoneg == AUTONEG_ENABLE) cmd->advertising |= ADVERTISED_Autoneg; if (!netif_running(dev)){ - cmd->speed = 0; + ethtool_cmd_speed_set(cmd, 0); cmd->duplex = 0xff; } cmd->maxtxpkt = 0; diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c index e68ffe622e69..f1573d492e90 100644 --- a/drivers/net/bcm63xx_enet.c +++ b/drivers/net/bcm63xx_enet.c @@ -1346,7 +1346,8 @@ static int bcm_enet_get_settings(struct net_device *dev, return phy_ethtool_gset(priv->phydev, cmd); } else { cmd->autoneg = 0; - cmd->speed = (priv->force_speed_100) ? SPEED_100 : SPEED_10; + ethtool_cmd_speed_set(cmd, ((priv->force_speed_100) + ? SPEED_100 : SPEED_10)); cmd->duplex = (priv->force_duplex_full) ? DUPLEX_FULL : DUPLEX_HALF; cmd->supported = ADVERTISED_10baseT_Half | diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 6565f3e55b26..8e770e8275df 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -381,23 +381,23 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) be_link_status_update(adapter, link_up); /* link_speed is in units of 10 Mbps */ if (link_speed) { - ecmd->speed = link_speed*10; + ethtool_cmd_speed_set(ecmd, link_speed*10); } else { switch (mac_speed) { case PHY_LINK_SPEED_10MBPS: - ecmd->speed = SPEED_10; + ethtool_cmd_speed_set(ecmd, SPEED_10); break; case PHY_LINK_SPEED_100MBPS: - ecmd->speed = SPEED_100; + ethtool_cmd_speed_set(ecmd, SPEED_100); break; case PHY_LINK_SPEED_1GBPS: - ecmd->speed = SPEED_1000; + ethtool_cmd_speed_set(ecmd, SPEED_1000); break; case PHY_LINK_SPEED_10GBPS: - ecmd->speed = SPEED_10000; + ethtool_cmd_speed_set(ecmd, SPEED_10000); break; case PHY_LINK_SPEED_ZERO: - ecmd->speed = 0; + ethtool_cmd_speed_set(ecmd, 0); break; } } @@ -440,14 +440,14 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) } /* Save for future use */ - adapter->link_speed = ecmd->speed; + adapter->link_speed = ethtool_cmd_speed(ecmd); adapter->port_type = ecmd->port; adapter->transceiver = ecmd->transceiver; adapter->autoneg = ecmd->autoneg; dma_free_coherent(&adapter->pdev->dev, phy_cmd.size, phy_cmd.va, phy_cmd.dma); } else { - ecmd->speed = adapter->link_speed; + ethtool_cmd_speed_set(ecmd, adapter->link_speed); ecmd->port = adapter->port_type; ecmd->transceiver = adapter->transceiver; ecmd->autoneg = adapter->autoneg; diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c index ae1e118f9c3a..3330cd78da2c 100644 --- a/drivers/net/bna/bnad_ethtool.c +++ b/drivers/net/bna/bnad_ethtool.c @@ -237,10 +237,10 @@ bnad_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) cmd->phy_address = 0; if (netif_carrier_ok(netdev)) { - cmd->speed = SPEED_10000; + ethtool_cmd_speed_set(cmd, SPEED_10000); cmd->duplex = DUPLEX_FULL; } else { - cmd->speed = -1; + ethtool_cmd_speed_set(cmd, -1); cmd->duplex = -1; } cmd->transceiver = XCVR_EXTERNAL; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index e43efd86425b..1bebdfb9679f 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -6696,17 +6696,16 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (bp->autoneg & AUTONEG_SPEED) { cmd->autoneg = AUTONEG_ENABLE; - } - else { + } else { cmd->autoneg = AUTONEG_DISABLE; } if (netif_carrier_ok(dev)) { - cmd->speed = bp->line_speed; + ethtool_cmd_speed_set(cmd, bp->line_speed); cmd->duplex = bp->duplex; } else { - cmd->speed = -1; + ethtool_cmd_speed_set(cmd, -1); cmd->duplex = -1; } spin_unlock_bh(&bp->phy_lock); diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index a6c3f8c8c302..22ce03e55b83 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -4606,18 +4606,17 @@ static int cas_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (bmcr & BMCR_ANENABLE) { cmd->advertising |= ADVERTISED_Autoneg; cmd->autoneg = AUTONEG_ENABLE; - cmd->speed = ((speed == 10) ? - SPEED_10 : - ((speed == 1000) ? - SPEED_1000 : SPEED_100)); + ethtool_cmd_speed_set(cmd, ((speed == 10) ? + SPEED_10 : + ((speed == 1000) ? + SPEED_1000 : SPEED_100))); cmd->duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF; } else { cmd->autoneg = AUTONEG_DISABLE; - cmd->speed = - (bmcr & CAS_BMCR_SPEED1000) ? - SPEED_1000 : - ((bmcr & BMCR_SPEED100) ? SPEED_100: - SPEED_10); + ethtool_cmd_speed_set(cmd, ((bmcr & CAS_BMCR_SPEED1000) ? + SPEED_1000 : + ((bmcr & BMCR_SPEED100) ? + SPEED_100 : SPEED_10))); cmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; @@ -4634,14 +4633,14 @@ static int cas_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) * settings that we configured. */ if (cp->link_cntl & BMCR_ANENABLE) { - cmd->speed = 0; + ethtool_cmd_speed_set(cmd, 0); cmd->duplex = 0xff; } else { - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); if (cp->link_cntl & BMCR_SPEED100) { - cmd->speed = SPEED_100; + ethtool_cmd_speed_set(cmd, SPEED_100); } else if (cp->link_cntl & CAS_BMCR_SPEED1000) { - cmd->speed = SPEED_1000; + ethtool_cmd_speed_set(cmd, SPEED_1000); } cmd->duplex = (cp->link_cntl & BMCR_FULLDPLX)? DUPLEX_FULL : DUPLEX_HALF; diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 8e14d652996b..b422d83f5343 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -577,10 +577,10 @@ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->advertising = p->link_config.advertising; if (netif_carrier_ok(dev)) { - cmd->speed = p->link_config.speed; + ethtool_cmd_speed_set(cmd, p->link_config.speed); cmd->duplex = p->link_config.duplex; } else { - cmd->speed = -1; + ethtool_cmd_speed_set(cmd, -1); cmd->duplex = -1; } diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 0526715cc8c7..9081ce037149 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1759,10 +1759,10 @@ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->advertising = p->link_config.advertising; if (netif_carrier_ok(dev)) { - cmd->speed = p->link_config.speed; + ethtool_cmd_speed_set(cmd, p->link_config.speed); cmd->duplex = p->link_config.duplex; } else { - cmd->speed = -1; + ethtool_cmd_speed_set(cmd, -1); cmd->duplex = -1; } diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c index c02b4d3b73fc..7e3cfbe89e3b 100644 --- a/drivers/net/cxgb4/cxgb4_main.c +++ b/drivers/net/cxgb4/cxgb4_main.c @@ -1436,7 +1436,8 @@ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->supported = from_fw_linkcaps(p->port_type, p->link_cfg.supported); cmd->advertising = from_fw_linkcaps(p->port_type, p->link_cfg.advertising); - cmd->speed = netif_carrier_ok(dev) ? p->link_cfg.speed : 0; + ethtool_cmd_speed_set(cmd, + netif_carrier_ok(dev) ? p->link_cfg.speed : 0); cmd->duplex = DUPLEX_FULL; cmd->autoneg = p->link_cfg.autoneg; cmd->maxtxpkt = 0; diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c index 8cf9890cafaf..e71c08e547e4 100644 --- a/drivers/net/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/cxgb4vf/cxgb4vf_main.c @@ -1167,7 +1167,8 @@ static int cxgb4vf_get_settings(struct net_device *dev, cmd->supported = pi->link_cfg.supported; cmd->advertising = pi->link_cfg.advertising; - cmd->speed = netif_carrier_ok(dev) ? pi->link_cfg.speed : -1; + ethtool_cmd_speed_set(cmd, + netif_carrier_ok(dev) ? pi->link_cfg.speed : -1); cmd->duplex = DUPLEX_FULL; cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE; diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index ab63989619d4..c445457b66d5 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -1189,10 +1189,10 @@ static int rio_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->transceiver = XCVR_INTERNAL; } if ( np->link_status ) { - cmd->speed = np->speed; + ethtool_cmd_speed_set(cmd, np->speed); cmd->duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; } else { - cmd->speed = -1; + ethtool_cmd_speed_set(cmd, -1); cmd->duplex = -1; } if ( np->an_enable) diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index a53629d9325d..127fef4fce49 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -158,7 +158,7 @@ static int e1000_get_settings(struct net_device *netdev, e1000_get_speed_and_duplex(hw, &adapter->link_speed, &adapter->link_duplex); - ecmd->speed = adapter->link_speed; + ethtool_cmd_speed_set(ecmd, adapter->link_speed); /* unfortunately FULL_DUPLEX != DUPLEX_FULL * and HALF_DUPLEX != DUPLEX_HALF */ @@ -168,7 +168,7 @@ static int e1000_get_settings(struct net_device *netdev, else ecmd->duplex = DUPLEX_HALF; } else { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index bc02c6b91f15..12f1ee250522 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -122,6 +122,7 @@ static int e1000_get_settings(struct net_device *netdev, { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; + u32 speed; if (hw->phy.media_type == e1000_media_type_copper) { @@ -159,23 +160,23 @@ static int e1000_get_settings(struct net_device *netdev, ecmd->transceiver = XCVR_EXTERNAL; } - ecmd->speed = -1; + speed = -1; ecmd->duplex = -1; if (netif_running(netdev)) { if (netif_carrier_ok(netdev)) { - ecmd->speed = adapter->link_speed; + speed = adapter->link_speed; ecmd->duplex = adapter->link_duplex - 1; } } else { u32 status = er32(STATUS); if (status & E1000_STATUS_LU) { if (status & E1000_STATUS_SPEED_1000) - ecmd->speed = 1000; + speed = SPEED_1000; else if (status & E1000_STATUS_SPEED_100) - ecmd->speed = 100; + speed = SPEED_100; else - ecmd->speed = 10; + speed = SPEED_10; if (status & E1000_STATUS_FD) ecmd->duplex = DUPLEX_FULL; @@ -184,6 +185,7 @@ static int e1000_get_settings(struct net_device *netdev, } } + ethtool_cmd_speed_set(ecmd, speed); ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) || hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index eb35951a2442..dfeb006035df 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -1703,7 +1703,7 @@ static int eepro_ethtool_get_settings(struct net_device *dev, cmd->advertising |= ADVERTISED_AUI; } - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); if (dev->if_port == TPE && lp->word[1] & ee_Duplex) { cmd->duplex = DUPLEX_FULL; diff --git a/drivers/net/ehea/ehea_ethtool.c b/drivers/net/ehea/ehea_ethtool.c index 5f13491cf2a9..1df5f40c646d 100644 --- a/drivers/net/ehea/ehea_ethtool.c +++ b/drivers/net/ehea/ehea_ethtool.c @@ -34,6 +34,7 @@ static int ehea_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct ehea_port *port = netdev_priv(dev); + u32 speed; int ret; ret = ehea_sense_port_attr(port); @@ -43,17 +44,29 @@ static int ehea_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (netif_carrier_ok(dev)) { switch (port->port_speed) { - case EHEA_SPEED_10M: cmd->speed = SPEED_10; break; - case EHEA_SPEED_100M: cmd->speed = SPEED_100; break; - case EHEA_SPEED_1G: cmd->speed = SPEED_1000; break; - case EHEA_SPEED_10G: cmd->speed = SPEED_10000; break; + case EHEA_SPEED_10M: + speed = SPEED_10; + break; + case EHEA_SPEED_100M: + speed = SPEED_100; + break; + case EHEA_SPEED_1G: + speed = SPEED_1000; + break; + case EHEA_SPEED_10G: + speed = SPEED_10000; + break; + default: + speed = -1; + break; /* BUG */ } cmd->duplex = port->full_duplex == 1 ? DUPLEX_FULL : DUPLEX_HALF; } else { - cmd->speed = -1; + speed = ~0; cmd->duplex = -1; } + ethtool_cmd_speed_set(cmd, speed); cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Half diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index 81a793747f2e..2837ce209cd7 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c @@ -1488,7 +1488,7 @@ enc28j60_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_TP; - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); cmd->duplex = priv->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; cmd->port = PORT_TP; cmd->autoneg = AUTONEG_DISABLE; diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index b2245511c51a..3d99b0f1a236 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -180,10 +180,10 @@ static int enic_get_settings(struct net_device *netdev, ecmd->transceiver = XCVR_EXTERNAL; if (netif_carrier_ok(netdev)) { - ecmd->speed = vnic_dev_port_speed(enic->vdev); + ethtool_cmd_speed_set(ecmd, vnic_dev_port_speed(enic->vdev)); ecmd->duplex = DUPLEX_FULL; } else { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index 17b6027d8be8..b5f6173130f4 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -1545,7 +1545,7 @@ static int ewrk3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } ecmd->supported |= SUPPORTED_10baseT_Half; - ecmd->speed = SPEED_10; + ethtool_cmd_speed_set(ecmd, SPEED_10); ecmd->duplex = DUPLEX_HALF; return 0; } diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index d24b3f3e646b..d09e8b0add01 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3955,6 +3955,7 @@ static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo) static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct fe_priv *np = netdev_priv(dev); + u32 speed; int adv; spin_lock_irq(&np->lock); @@ -3974,23 +3975,26 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) if (netif_carrier_ok(dev)) { switch (np->linkspeed & (NVREG_LINKSPEED_MASK)) { case NVREG_LINKSPEED_10: - ecmd->speed = SPEED_10; + speed = SPEED_10; break; case NVREG_LINKSPEED_100: - ecmd->speed = SPEED_100; + speed = SPEED_100; break; case NVREG_LINKSPEED_1000: - ecmd->speed = SPEED_1000; + speed = SPEED_1000; + break; + default: + speed = -1; break; } ecmd->duplex = DUPLEX_HALF; if (np->duplex) ecmd->duplex = DUPLEX_FULL; } else { - ecmd->speed = -1; + speed = -1; ecmd->duplex = -1; } - + ethtool_cmd_speed_set(ecmd, speed); ecmd->autoneg = np->autoneg; ecmd->advertising = ADVERTISED_MII; diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index be3fe71b9c90..b388d782c7c4 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -710,7 +710,7 @@ static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) SUPPORTED_FIBRE); cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | ADVERTISED_FIBRE); - cmd->speed = SPEED_1000; + ethtool_cmd_speed_set(cmd, SPEED_1000); cmd->duplex = DUPLEX_FULL; cmd->port = PORT_FIBRE; cmd->phy_address = 0; diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 2cc221b65cd4..023aa9b10654 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -178,11 +178,11 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) if ((status & E1000_STATUS_SPEED_1000) || hw->phy.media_type != e1000_media_type_copper) - ecmd->speed = SPEED_1000; + ethtool_cmd_speed_set(ecmd, SPEED_1000); else if (status & E1000_STATUS_SPEED_100) - ecmd->speed = SPEED_100; + ethtool_cmd_speed_set(ecmd, SPEED_100); else - ecmd->speed = SPEED_10; + ethtool_cmd_speed_set(ecmd, SPEED_10); if ((status & E1000_STATUS_FD) || hw->phy.media_type != e1000_media_type_copper) @@ -190,7 +190,7 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) else ecmd->duplex = DUPLEX_HALF; } else { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c index 1d943aa7c7a6..112ae15b2d49 100644 --- a/drivers/net/igbvf/ethtool.c +++ b/drivers/net/igbvf/ethtool.c @@ -90,18 +90,18 @@ static int igbvf_get_settings(struct net_device *netdev, status = er32(STATUS); if (status & E1000_STATUS_LU) { if (status & E1000_STATUS_SPEED_1000) - ecmd->speed = 1000; + ethtool_cmd_speed_set(ecmd, SPEED_1000); else if (status & E1000_STATUS_SPEED_100) - ecmd->speed = 100; + ethtool_cmd_speed_set(ecmd, SPEED_100); else - ecmd->speed = 10; + ethtool_cmd_speed_set(ecmd, SPEED_10); if (status & E1000_STATUS_FD) ecmd->duplex = DUPLEX_FULL; else ecmd->duplex = DUPLEX_HALF; } else { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c index edb3d7eaf6d5..5f224c387e0c 100644 --- a/drivers/net/ixgb/ixgb_ethtool.c +++ b/drivers/net/ixgb/ixgb_ethtool.c @@ -104,10 +104,10 @@ ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->transceiver = XCVR_EXTERNAL; if (netif_carrier_ok(adapter->netdev)) { - ecmd->speed = SPEED_10000; + ethtool_cmd_speed_set(ecmd, SPEED_10000); ecmd->duplex = DUPLEX_FULL; } else { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index c52243d67edc..bcba057b510f 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -288,20 +288,20 @@ static int ixgbe_get_settings(struct net_device *netdev, if (link_up) { switch (link_speed) { case IXGBE_LINK_SPEED_10GB_FULL: - ecmd->speed = SPEED_10000; + ethtool_cmd_speed_set(ecmd, SPEED_10000); break; case IXGBE_LINK_SPEED_1GB_FULL: - ecmd->speed = SPEED_1000; + ethtool_cmd_speed_set(ecmd, SPEED_1000); break; case IXGBE_LINK_SPEED_100_FULL: - ecmd->speed = SPEED_100; + ethtool_cmd_speed_set(ecmd, SPEED_100); break; default: break; } ecmd->duplex = DUPLEX_FULL; } else { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } diff --git a/drivers/net/ixgbevf/ethtool.c b/drivers/net/ixgbevf/ethtool.c index 0563ab29264e..deee3754b1f7 100644 --- a/drivers/net/ixgbevf/ethtool.c +++ b/drivers/net/ixgbevf/ethtool.c @@ -104,11 +104,13 @@ static int ixgbevf_get_settings(struct net_device *netdev, hw->mac.ops.check_link(hw, &link_speed, &link_up, false); if (link_up) { - ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? - SPEED_10000 : SPEED_1000; + ethtool_cmd_speed_set( + ecmd, + (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? + SPEED_10000 : SPEED_1000); ecmd->duplex = DUPLEX_FULL; } else { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } diff --git a/drivers/net/mdio.c b/drivers/net/mdio.c index f2d10abd0403..16fbb11d92ac 100644 --- a/drivers/net/mdio.c +++ b/drivers/net/mdio.c @@ -188,6 +188,7 @@ void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, u32 npage_adv, u32 npage_lpa) { int reg; + u32 speed; ecmd->transceiver = XCVR_INTERNAL; ecmd->phy_address = mdio->prtad; @@ -290,33 +291,36 @@ void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, if (modes & (ADVERTISED_10000baseT_Full | ADVERTISED_10000baseKX4_Full | ADVERTISED_10000baseKR_Full)) { - ecmd->speed = SPEED_10000; + speed = SPEED_10000; ecmd->duplex = DUPLEX_FULL; } else if (modes & (ADVERTISED_1000baseT_Full | ADVERTISED_1000baseT_Half | ADVERTISED_1000baseKX_Full)) { - ecmd->speed = SPEED_1000; + speed = SPEED_1000; ecmd->duplex = !(modes & ADVERTISED_1000baseT_Half); } else if (modes & (ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half)) { - ecmd->speed = SPEED_100; + speed = SPEED_100; ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full); } else { - ecmd->speed = SPEED_10; + speed = SPEED_10; ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full); } } else { /* Report forced settings */ reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, MDIO_CTRL1); - ecmd->speed = (((reg & MDIO_PMA_CTRL1_SPEED1000) ? 100 : 1) * - ((reg & MDIO_PMA_CTRL1_SPEED100) ? 100 : 10)); + speed = (((reg & MDIO_PMA_CTRL1_SPEED1000) ? 100 : 1) + * ((reg & MDIO_PMA_CTRL1_SPEED100) ? 100 : 10)); ecmd->duplex = (reg & MDIO_CTRL1_FULLDPLX || - ecmd->speed == SPEED_10000); + speed == SPEED_10000); } + ethtool_cmd_speed_set(ecmd, speed); + /* 10GBASE-T MDI/MDI-X */ - if (ecmd->port == PORT_TP && ecmd->speed == SPEED_10000) { + if (ecmd->port == PORT_TP + && (ethtool_cmd_speed(ecmd) == SPEED_10000)) { switch (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_SWAPPOL)) { case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX: diff --git a/drivers/net/mii.c b/drivers/net/mii.c index e8198edeaa76..4fbc816efee2 100644 --- a/drivers/net/mii.c +++ b/drivers/net/mii.c @@ -121,22 +121,25 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) if (nego & (ADVERTISED_1000baseT_Full | ADVERTISED_1000baseT_Half)) { - ecmd->speed = SPEED_1000; + ethtool_cmd_speed_set(ecmd, SPEED_1000); ecmd->duplex = !!(nego & ADVERTISED_1000baseT_Full); } else if (nego & (ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half)) { - ecmd->speed = SPEED_100; + ethtool_cmd_speed_set(ecmd, SPEED_100); ecmd->duplex = !!(nego & ADVERTISED_100baseT_Full); } else { - ecmd->speed = SPEED_10; + ethtool_cmd_speed_set(ecmd, SPEED_10); ecmd->duplex = !!(nego & ADVERTISED_10baseT_Full); } } else { ecmd->autoneg = AUTONEG_DISABLE; - ecmd->speed = ((bmcr & BMCR_SPEED1000 && - (bmcr & BMCR_SPEED100) == 0) ? SPEED_1000 : - (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10); + ethtool_cmd_speed_set(ecmd, + ((bmcr & BMCR_SPEED1000 && + (bmcr & BMCR_SPEED100) == 0) ? + SPEED_1000 : + ((bmcr & BMCR_SPEED100) ? + SPEED_100 : SPEED_10))); ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; } diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c index be4a9e0b2406..2e858e4dcf4d 100644 --- a/drivers/net/mlx4/en_ethtool.c +++ b/drivers/net/mlx4/en_ethtool.c @@ -265,10 +265,10 @@ static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) trans_type = priv->port_state.transciver; if (netif_carrier_ok(dev)) { - cmd->speed = priv->port_state.link_speed; + ethtool_cmd_speed_set(cmd, priv->port_state.link_speed); cmd->duplex = DUPLEX_FULL; } else { - cmd->speed = -1; + ethtool_cmd_speed_set(cmd, -1); cmd->duplex = -1; } diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 57c2ac04f9ff..a5d9b1c310b3 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1444,13 +1444,13 @@ mv643xx_eth_get_settings_phyless(struct mv643xx_eth_private *mp, cmd->advertising = ADVERTISED_MII; switch (port_status & PORT_SPEED_MASK) { case PORT_SPEED_10: - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); break; case PORT_SPEED_100: - cmd->speed = SPEED_100; + ethtool_cmd_speed_set(cmd, SPEED_100); break; case PORT_SPEED_1000: - cmd->speed = SPEED_1000; + ethtool_cmd_speed_set(cmd, SPEED_1000); break; default: cmd->speed = -1; diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index e7f801643c12..b1358f79ba0a 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1644,7 +1644,7 @@ myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) int i; cmd->autoneg = AUTONEG_DISABLE; - cmd->speed = SPEED_10000; + ethtool_cmd_speed_set(cmd, SPEED_10000); cmd->duplex = DUPLEX_FULL; /* diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 7633c67b7842..b78be088c4ad 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2820,7 +2820,7 @@ static int netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) u32 tmp; ecmd->port = dev->if_port; - ecmd->speed = np->speed; + ethtool_cmd_speed_set(ecmd, np->speed); ecmd->duplex = np->duplex; ecmd->autoneg = np->autoneg; ecmd->advertising = 0; @@ -2878,9 +2878,9 @@ static int netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) tmp = mii_nway_result( np->advertising & mdio_read(dev, MII_LPA)); if (tmp == LPA_100FULL || tmp == LPA_100HALF) - ecmd->speed = SPEED_100; + ethtool_cmd_speed_set(ecmd, SPEED_100); else - ecmd->speed = SPEED_10; + ethtool_cmd_speed_set(ecmd, SPEED_10); if (tmp == LPA_100FULL || tmp == LPA_10FULL) ecmd->duplex = DUPLEX_FULL; else diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index e8d16f6f11e3..b34fb74d07e3 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -117,7 +117,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->port = PORT_TP; - ecmd->speed = adapter->link_speed; + ethtool_cmd_speed_set(ecmd, adapter->link_speed); ecmd->duplex = adapter->link_duplex; ecmd->autoneg = adapter->link_autoneg; @@ -134,7 +134,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } if (netif_running(dev) && adapter->has_link_events) { - ecmd->speed = adapter->link_speed; + ethtool_cmd_speed_set(ecmd, adapter->link_speed); ecmd->autoneg = adapter->link_autoneg; ecmd->duplex = adapter->link_duplex; goto skip; @@ -146,10 +146,10 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) u16 pcifn = adapter->ahw.pci_func; val = NXRD32(adapter, P3_LINK_SPEED_REG(pcifn)); - ecmd->speed = P3_LINK_SPEED_MHZ * - P3_LINK_SPEED_VAL(pcifn, val); + ethtool_cmd_speed_set(ecmd, P3_LINK_SPEED_MHZ * + P3_LINK_SPEED_VAL(pcifn, val)); } else - ecmd->speed = SPEED_10000; + ethtool_cmd_speed_set(ecmd, SPEED_10000); ecmd->duplex = DUPLEX_FULL; ecmd->autoneg = AUTONEG_DISABLE; diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 524e800ddcf4..cc25bff0bd3b 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -6844,7 +6844,7 @@ static int niu_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->supported = lp->supported; cmd->advertising = lp->active_advertising; cmd->autoneg = lp->active_autoneg; - cmd->speed = lp->active_speed; + ethtool_cmd_speed_set(cmd, lp->active_speed); cmd->duplex = lp->active_duplex; cmd->port = (np->flags & NIU_FLAGS_FIBER) ? PORT_FIBRE : PORT_TP; cmd->transceiver = (np->flags & NIU_FLAGS_XCVR_SERDES) ? diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 6667e0667a88..3e4040f2f3cb 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -1251,7 +1251,7 @@ static int ns83820_get_settings(struct net_device *ndev, /* * Here's the list of available ethtool commands from other drivers: * cmd->advertising = - * cmd->speed = + * ethtool_cmd_speed_set(cmd, ...) * cmd->duplex = * cmd->port = 0; * cmd->phy_address = @@ -1289,13 +1289,13 @@ static int ns83820_get_settings(struct net_device *ndev, cmd->duplex = fullduplex ? DUPLEX_FULL : DUPLEX_HALF; switch (cfg / CFG_SPDSTS0 & 3) { case 2: - cmd->speed = SPEED_1000; + ethtool_cmd_speed_set(cmd, SPEED_1000); break; case 1: - cmd->speed = SPEED_100; + ethtool_cmd_speed_set(cmd, SPEED_100); break; default: - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); break; } cmd->autoneg = (tbicr & TBICR_MR_AN_ENABLE) diff --git a/drivers/net/pch_gbe/pch_gbe_phy.c b/drivers/net/pch_gbe/pch_gbe_phy.c index 9a8207f686fd..28bb9603d736 100644 --- a/drivers/net/pch_gbe/pch_gbe_phy.c +++ b/drivers/net/pch_gbe/pch_gbe_phy.c @@ -256,7 +256,7 @@ void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw) if (ret) pr_err("Error: mii_ethtool_gset\n"); - cmd.speed = hw->mac.link_speed; + ethtool_cmd_speed_set(&cmd, hw->mac.link_speed); cmd.duplex = hw->mac.link_duplex; cmd.advertising = hw->phy.autoneg_advertised; cmd.autoneg = hw->mac.autoneg; diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index bc71cb260ff4..288e4f1317ee 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1860,7 +1860,7 @@ static int smc_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) tmp = inw(ioaddr + CONFIG); ecmd->port = (tmp & CFG_AUI_SELECT) ? PORT_AUI : PORT_TP; ecmd->transceiver = XCVR_INTERNAL; - ecmd->speed = SPEED_10; + ethtool_cmd_speed_set(ecmd, SPEED_10); ecmd->phy_address = ioaddr + MGMT; SMC_SELECT_BANK(0); diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index e3f3501d4347..a47595760751 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -288,7 +288,7 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd) cmd->advertising = phydev->advertising; - cmd->speed = phydev->speed; + ethtool_cmd_speed_set(cmd, phydev->speed); cmd->duplex = phydev->duplex; cmd->port = PORT_MII; cmd->phy_address = phydev->addr; diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index 4383ed21813e..b1f251da1535 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c @@ -1243,17 +1243,17 @@ static int gelic_ether_get_settings(struct net_device *netdev, switch (card->ether_port_status & GELIC_LV1_ETHER_SPEED_MASK) { case GELIC_LV1_ETHER_SPEED_10: - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); break; case GELIC_LV1_ETHER_SPEED_100: - cmd->speed = SPEED_100; + ethtool_cmd_speed_set(cmd, SPEED_100); break; case GELIC_LV1_ETHER_SPEED_1000: - cmd->speed = SPEED_1000; + ethtool_cmd_speed_set(cmd, SPEED_1000); break; default: pr_info("%s: speed unknown\n", __func__); - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); break; } diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index f3f737b91248..d495a6859fd9 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -1725,7 +1725,7 @@ static int ql_get_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) } ecmd->advertising = ql_supported_modes(qdev); ecmd->autoneg = ql_get_auto_cfg_status(qdev); - ecmd->speed = ql_get_speed(qdev); + ethtool_cmd_speed_set(ecmd, ql_get_speed(qdev)); ecmd->duplex = ql_get_full_dup(qdev); return 0; } diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 27726ebfba2a..c541461bc12c 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -166,7 +166,7 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full); - ecmd->speed = adapter->link_speed; + ethtool_cmd_speed_set(ecmd, adapter->link_speed); ecmd->duplex = adapter->link_duplex; ecmd->autoneg = adapter->link_autoneg; @@ -183,15 +183,15 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } if (netif_running(dev) && adapter->has_link_events) { - ecmd->speed = adapter->link_speed; + ethtool_cmd_speed_set(ecmd, adapter->link_speed); ecmd->autoneg = adapter->link_autoneg; ecmd->duplex = adapter->link_duplex; goto skip; } val = QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn)); - ecmd->speed = P3P_LINK_SPEED_MHZ * - P3P_LINK_SPEED_VAL(pcifn, val); + ethtool_cmd_speed_set(ecmd, P3P_LINK_SPEED_MHZ * + P3P_LINK_SPEED_VAL(pcifn, val)); ecmd->duplex = DUPLEX_FULL; ecmd->autoneg = AUTONEG_DISABLE; } else diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index 78dc40c18c60..19b00fa0eaf0 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c @@ -356,7 +356,7 @@ static int ql_get_settings(struct net_device *ndev, ecmd->port = PORT_FIBRE; } - ecmd->speed = SPEED_10000; + ethtool_cmd_speed_set(ecmd, SPEED_10000); ecmd->duplex = DUPLEX_FULL; return 0; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index b52ee17de74d..a8976a753814 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1422,7 +1422,7 @@ static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; cmd->autoneg = !!(status & TBINwEnable); - cmd->speed = SPEED_1000; + ethtool_cmd_speed_set(cmd, SPEED_1000); cmd->duplex = DUPLEX_FULL; /* Always set */ return 0; diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 5443985c019e..89cfee7e8643 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -5414,10 +5414,10 @@ static int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info) info->transceiver = XCVR_EXTERNAL; if (netif_carrier_ok(sp->dev)) { - info->speed = 10000; + ethtool_cmd_speed_set(info, SPEED_10000); info->duplex = DUPLEX_FULL; } else { - info->speed = -1; + ethtool_cmd_speed_set(info, -1); info->duplex = -1; } diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index f3ffc1df3b2d..fa74314ef789 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -1173,7 +1173,8 @@ static int sc92031_ethtool_get_settings(struct net_device *dev, if (phy_ctrl & PhyCtrlAne) cmd->advertising |= ADVERTISED_Autoneg; - cmd->speed = (output_status & 0x2) ? SPEED_100 : SPEED_10; + ethtool_cmd_speed_set(cmd, + (output_status & 0x2) ? SPEED_100 : SPEED_10); cmd->duplex = (output_status & 0x4) ? DUPLEX_FULL : DUPLEX_HALF; cmd->port = PORT_MII; cmd->phy_address = phy_address; diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 10b160a508f3..8c5e0052c44a 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -219,7 +219,7 @@ static int efx_ethtool_get_settings(struct net_device *net_dev, ecmd->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; if (LOOPBACK_INTERNAL(efx)) { - ecmd->speed = link_state->speed; + ethtool_cmd_speed_set(ecmd, link_state->speed); ecmd->duplex = link_state->fd ? DUPLEX_FULL : DUPLEX_HALF; } diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c index 6c5fccbdeca2..6c63ab0710af 100644 --- a/drivers/net/sfc/mcdi_phy.c +++ b/drivers/net/sfc/mcdi_phy.c @@ -513,7 +513,7 @@ static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *e ecmd->supported = mcdi_to_ethtool_cap(phy_cfg->media, phy_cfg->supported_cap); ecmd->advertising = efx->link_advertising; - ecmd->speed = efx->link_state.speed; + ethtool_cmd_speed_set(ecmd, efx->link_state.speed); ecmd->duplex = efx->link_state.fd; ecmd->port = mcdi_to_ethtool_media(phy_cfg->media); ecmd->phy_address = phy_cfg->port; diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 204ecdaac9ab..7b0fd89e7b85 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -460,7 +460,7 @@ tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) /* In loopback, the PHY automatically brings up the correct interface, * but doesn't advertise the correct speed. So override it */ if (LOOPBACK_EXTERNAL(efx)) - ecmd->speed = SPEED_10000; + ethtool_cmd_speed_set(ecmd, SPEED_10000); } static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index a05e864de674..52a48cb75440 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -303,7 +303,7 @@ static int skge_get_settings(struct net_device *dev, ecmd->advertising = skge->advertising; ecmd->autoneg = skge->autoneg; - ecmd->speed = skge->speed; + ethtool_cmd_speed_set(ecmd, skge->speed); ecmd->duplex = skge->duplex; return 0; } diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 5c7e2d68df2a..3ee41da130c2 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3413,10 +3413,10 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->phy_address = PHY_ADDR_MARV; if (sky2_is_copper(hw)) { ecmd->port = PORT_TP; - ecmd->speed = sky2->speed; + ethtool_cmd_speed_set(ecmd, sky2->speed); ecmd->supported |= SUPPORTED_Autoneg | SUPPORTED_TP; } else { - ecmd->speed = SPEED_1000; + ethtool_cmd_speed_set(ecmd, SPEED_1000); ecmd->port = PORT_FIBRE; ecmd->supported |= SUPPORTED_Autoneg | SUPPORTED_FIBRE; } diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 66831f378396..053863aefb12 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1488,9 +1488,9 @@ smc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) SUPPORTED_TP | SUPPORTED_AUI; if (lp->ctl_rspeed == 10) - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); else if (lp->ctl_rspeed == 100) - cmd->speed = SPEED_100; + ethtool_cmd_speed_set(cmd, SPEED_100); cmd->autoneg = AUTONEG_DISABLE; if (lp->mii.phy_id==1) diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 43654a3bb0ec..dc4805f473e3 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1565,9 +1565,9 @@ smc_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) SUPPORTED_TP | SUPPORTED_AUI; if (lp->ctl_rspeed == 10) - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); else if (lp->ctl_rspeed == 100) - cmd->speed = SPEED_100; + ethtool_cmd_speed_set(cmd, SPEED_100); cmd->autoneg = AUTONEG_DISABLE; cmd->transceiver = XCVR_INTERNAL; diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c index d723fca872ce..9c288cd7d171 100644 --- a/drivers/net/spider_net_ethtool.c +++ b/drivers/net/spider_net_ethtool.c @@ -58,7 +58,7 @@ spider_net_ethtool_get_settings(struct net_device *netdev, cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_FIBRE); cmd->port = PORT_FIBRE; - cmd->speed = card->phy.speed; + ethtool_cmd_speed_set(cmd, card->phy.speed); cmd->duplex = DUPLEX_FULL; return 0; diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 40a755dd1a26..ab5930099267 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2642,7 +2642,7 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) /* Return current PHY settings */ spin_lock_irq(&gp->lock); cmd->autoneg = gp->want_autoneg; - cmd->speed = gp->phy_mii.speed; + ethtool_cmd_speed_set(cmd, gp->phy_mii.speed); cmd->duplex = gp->phy_mii.duplex; cmd->advertising = gp->phy_mii.advertising; @@ -2659,7 +2659,7 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_Autoneg); cmd->advertising = cmd->supported; - cmd->speed = 0; + ethtool_cmd_speed_set(cmd, 0); cmd->duplex = cmd->port = cmd->phy_address = cmd->transceiver = cmd->autoneg = 0; @@ -2673,7 +2673,7 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->advertising = cmd->supported; cmd->transceiver = XCVR_INTERNAL; if (gp->lstate == link_up) - cmd->speed = SPEED_1000; + ethtool_cmd_speed_set(cmd, SPEED_1000); cmd->duplex = DUPLEX_FULL; cmd->autoneg = 1; } diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 8f3f02802427..d381a0f9ee18 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2401,6 +2401,7 @@ static void happy_meal_set_multicast(struct net_device *dev) static int hme_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct happy_meal *hp = netdev_priv(dev); + u32 speed; cmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | @@ -2420,10 +2421,9 @@ static int hme_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (hp->sw_bmcr & BMCR_ANENABLE) { cmd->autoneg = AUTONEG_ENABLE; - cmd->speed = - (hp->sw_lpa & (LPA_100HALF | LPA_100FULL)) ? - SPEED_100 : SPEED_10; - if (cmd->speed == SPEED_100) + speed = ((hp->sw_lpa & (LPA_100HALF | LPA_100FULL)) ? + SPEED_100 : SPEED_10); + if (speed == SPEED_100) cmd->duplex = (hp->sw_lpa & (LPA_100FULL)) ? DUPLEX_FULL : DUPLEX_HALF; @@ -2433,13 +2433,12 @@ static int hme_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) DUPLEX_FULL : DUPLEX_HALF; } else { cmd->autoneg = AUTONEG_DISABLE; - cmd->speed = - (hp->sw_bmcr & BMCR_SPEED100) ? - SPEED_100 : SPEED_10; + speed = (hp->sw_bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; cmd->duplex = (hp->sw_bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; } + ethtool_cmd_speed_set(cmd, speed); return 0; } diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 8be71de725e5..80fbee0d40af 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -2151,7 +2151,7 @@ static int bdx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); - ecmd->speed = SPEED_10000; + ethtool_cmd_speed_set(ecmd, SPEED_10000); ecmd->duplex = DUPLEX_FULL; ecmd->port = PORT_FIBRE; ecmd->transceiver = XCVR_EXTERNAL; /* what does it mean? */ diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 004f266e4352..7c7c9a897c09 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10025,10 +10025,10 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->advertising = tp->link_config.advertising; if (netif_running(dev)) { - cmd->speed = tp->link_config.active_speed; + ethtool_cmd_speed_set(cmd, tp->link_config.active_speed); cmd->duplex = tp->link_config.active_duplex; } else { - cmd->speed = SPEED_INVALID; + ethtool_cmd_speed_set(cmd, SPEED_INVALID); cmd->duplex = DUPLEX_INVALID; } cmd->phy_address = tp->phy_addr; diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index f8d26bf9b2c4..ab78e1d58cb6 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -1518,15 +1518,15 @@ static int __de_get_settings(struct de_private *de, struct ethtool_cmd *ecmd) switch (de->media_type) { case DE_MEDIA_AUI: ecmd->port = PORT_AUI; - ecmd->speed = 5; + ethtool_cmd_speed_set(ecmd, 5); break; case DE_MEDIA_BNC: ecmd->port = PORT_BNC; - ecmd->speed = 2; + ethtool_cmd_speed_set(ecmd, 2); break; default: ecmd->port = PORT_TP; - ecmd->speed = SPEED_10; + ethtool_cmd_speed_set(ecmd, SPEED_10); break; } diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 74217dbf0143..a4375c406b5f 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -945,12 +945,12 @@ ULi_ethtool_gset(struct uli526x_board_info *db, struct ethtool_cmd *ecmd) ecmd->transceiver = XCVR_EXTERNAL; - ecmd->speed = 10; + ethtool_cmd_speed_set(ecmd, SPEED_10); ecmd->duplex = DUPLEX_HALF; if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD) { - ecmd->speed = 100; + ethtool_cmd_speed_set(ecmd, SPEED_100); } if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD) { @@ -958,7 +958,7 @@ ULi_ethtool_gset(struct uli526x_board_info *db, struct ethtool_cmd *ecmd) } if(db->link_failed) { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } diff --git a/drivers/net/tun.c b/drivers/net/tun.c index ade3cf9cd326..0636f7040325 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1553,7 +1553,7 @@ static int tun_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { cmd->supported = 0; cmd->advertising = 0; - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); cmd->duplex = DUPLEX_FULL; cmd->port = PORT_TP; cmd->phy_address = 0; diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 9f11c111b65d..3de4283344e9 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -1050,7 +1050,7 @@ typhoon_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) /* need to get stats to make these link speed/duplex valid */ typhoon_do_get_stats(tp); - cmd->speed = tp->speed; + ethtool_cmd_speed_set(cmd, tp->speed); cmd->duplex = tp->duplex; cmd->phy_address = 0; cmd->transceiver = XCVR_INTERNAL; diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 97687d335903..d7221c4a5dcf 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -686,7 +686,7 @@ static int catc_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_TP; cmd->advertising = ADVERTISED_10baseT_Half | ADVERTISED_TP; - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); cmd->duplex = DUPLEX_HALF; cmd->port = PORT_TP; cmd->phy_address = 0; diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index e85c89c6706d..041fb7d43c4f 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -843,10 +843,11 @@ static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *e get_registers(dev, BMCR, 2, &bmcr); get_registers(dev, ANLP, 2, &lpa); if (bmcr & BMCR_ANENABLE) { + u32 speed = ((lpa & (LPA_100HALF | LPA_100FULL)) ? + SPEED_100 : SPEED_10); + ethtool_cmd_speed_set(ecmd, speed); ecmd->autoneg = AUTONEG_ENABLE; - ecmd->speed = (lpa & (LPA_100HALF | LPA_100FULL)) ? - SPEED_100 : SPEED_10; - if (ecmd->speed == SPEED_100) + if (speed == SPEED_100) ecmd->duplex = (lpa & LPA_100FULL) ? DUPLEX_FULL : DUPLEX_HALF; else @@ -854,8 +855,8 @@ static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *e DUPLEX_FULL : DUPLEX_HALF; } else { ecmd->autoneg = AUTONEG_DISABLE; - ecmd->speed = (bmcr & BMCR_SPEED100) ? - SPEED_100 : SPEED_10; + ethtool_cmd_speed_set(ecmd, ((bmcr & BMCR_SPEED100) ? + SPEED_100 : SPEED_10)); ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; } diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 654228849951..cbe953a5bf5a 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -52,7 +52,7 @@ static int veth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { cmd->supported = 0; cmd->advertising = 0; - cmd->speed = SPEED_10000; + ethtool_cmd_speed_set(cmd, SPEED_10000); cmd->duplex = DUPLEX_FULL; cmd->port = PORT_TP; cmd->phy_address = 0; diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 9a8f116e6920..06daa9d6fee8 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -3182,7 +3182,8 @@ static void velocity_ethtool_down(struct net_device *dev) pci_set_power_state(vptr->pdev, PCI_D3hot); } -static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +static int velocity_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd) { struct velocity_info *vptr = netdev_priv(dev); struct mac_regs __iomem *regs = vptr->mac_regs; @@ -3228,12 +3229,14 @@ static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd break; } } + if (status & VELOCITY_SPEED_1000) - cmd->speed = SPEED_1000; + ethtool_cmd_speed_set(cmd, SPEED_1000); else if (status & VELOCITY_SPEED_100) - cmd->speed = SPEED_100; + ethtool_cmd_speed_set(cmd, SPEED_100); else - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); + cmd->autoneg = (status & VELOCITY_AUTONEG_ENABLE) ? AUTONEG_ENABLE : AUTONEG_DISABLE; cmd->port = PORT_TP; cmd->transceiver = XCVR_INTERNAL; diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index 70c1ab96ed27..64303eb3a5fc 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c @@ -424,10 +424,10 @@ vmxnet3_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->transceiver = XCVR_INTERNAL; if (adapter->link_speed) { - ecmd->speed = adapter->link_speed; + ethtool_cmd_speed_set(ecmd, adapter->link_speed); ecmd->duplex = DUPLEX_FULL; } else { - ecmd->speed = -1; + ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1; } return 0; diff --git a/drivers/net/vxge/vxge-ethtool.c b/drivers/net/vxge/vxge-ethtool.c index a70874e64d0e..92dd72d3f9de 100644 --- a/drivers/net/vxge/vxge-ethtool.c +++ b/drivers/net/vxge/vxge-ethtool.c @@ -59,10 +59,10 @@ static int vxge_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info) info->transceiver = XCVR_EXTERNAL; if (netif_carrier_ok(dev)) { - info->speed = SPEED_10000; + ethtool_cmd_speed_set(info, SPEED_10000); info->duplex = DUPLEX_FULL; } else { - info->speed = -1; + ethtool_cmd_speed_set(info, -1); info->duplex = -1; } diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index f4d80ad008c2..eeabbb89172c 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -697,7 +697,7 @@ static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { cmd->supported = 0; cmd->advertising = 0; - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); cmd->duplex = DUPLEX_FULL; cmd->port = PORT_TP; cmd->phy_address = 0; -- cgit v1.2.3-58-ga151 From 1258c076edcf4a253657320cfc2bd24fd5981d79 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 27 Apr 2011 18:32:41 +0000 Subject: acenic: Fix using the specified speed when configuring NIC This tells the NIC to take the speed specified by ethtool into account when configuring the NIC, instead of keeping the previous speed. Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- drivers/net/acenic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index a5798991c8b1..82260ca70323 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -2720,7 +2720,7 @@ static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) link |= LNK_NEGOTIATE; if (ethtool_cmd_speed(ecmd) != speed) { link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB); - switch (speed) { + switch (ethtool_cmd_speed(ecmd)) { case SPEED_1000: link |= LNK_1000MB; break; -- cgit v1.2.3-58-ga151 From fbef7139a8b89a7f49ba1410593ed894b4c8b017 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 27 Apr 2011 18:32:42 +0000 Subject: tulip/de2104x: don't report different speeds depending on port type Initial driver reported different speeds depending on the port being used. This advertises the speed to be 10Mbps in any case, which is what it actually is on the wire. Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- drivers/net/tulip/de2104x.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index ab78e1d58cb6..46d5a1b15036 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -1518,18 +1518,17 @@ static int __de_get_settings(struct de_private *de, struct ethtool_cmd *ecmd) switch (de->media_type) { case DE_MEDIA_AUI: ecmd->port = PORT_AUI; - ethtool_cmd_speed_set(ecmd, 5); break; case DE_MEDIA_BNC: ecmd->port = PORT_BNC; - ethtool_cmd_speed_set(ecmd, 2); break; default: ecmd->port = PORT_TP; - ethtool_cmd_speed_set(ecmd, SPEED_10); break; } + ethtool_cmd_speed_set(ecmd, 10); + if (dr32(MacMode) & FullDuplex) ecmd->duplex = DUPLEX_FULL; else @@ -1549,11 +1548,8 @@ static int __de_set_settings(struct de_private *de, struct ethtool_cmd *ecmd) { u32 new_media; unsigned int media_lock; - u32 speed = ethtool_cmd_speed(ecmd); - if (speed != SPEED_10 && speed != 5 && speed != 2) - return -EINVAL; - if (de->de21040 && speed == 2) + if (ethtool_cmd_speed(ecmd) != 10) return -EINVAL; if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) return -EINVAL; -- cgit v1.2.3-58-ga151 From 14ad2513ed5b709e566a853f4b515d91c5d83311 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 27 Apr 2011 18:32:43 +0000 Subject: net/igb/e1000/e1000e: more robust ethtool duplex/speed configuration This makes sure that one cannot request a 99Mbps full-duplex and get a 100Mbps half-duplex configuration in return due to the way the speed/duplex parameters are handled internally. Tested: e1000 works Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- drivers/net/e1000/e1000.h | 2 +- drivers/net/e1000/e1000_ethtool.c | 2 +- drivers/net/e1000/e1000_main.c | 42 ++++++++++++++++++++++----------------- drivers/net/e1000e/ethtool.c | 24 ++++++++++++++-------- drivers/net/igb/igb.h | 2 +- drivers/net/igb/igb_ethtool.c | 2 +- drivers/net/igb/igb_main.c | 23 +++++++++++++-------- 7 files changed, 59 insertions(+), 38 deletions(-) diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index a881dd0093bd..b1b23ddd4eed 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -349,7 +349,7 @@ extern int e1000_up(struct e1000_adapter *adapter); extern void e1000_down(struct e1000_adapter *adapter); extern void e1000_reinit_locked(struct e1000_adapter *adapter); extern void e1000_reset(struct e1000_adapter *adapter); -extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx); +extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx); extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter); diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 127fef4fce49..4fa727ce8374 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -199,7 +199,7 @@ static int e1000_set_settings(struct net_device *netdev, ecmd->advertising = hw->autoneg_advertised; } else { u32 speed = ethtool_cmd_speed(ecmd); - if (e1000_set_spd_dplx(adapter, speed + ecmd->duplex)) { + if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) { clear_bit(__E1000_RESETTING, &adapter->flags); return -EINVAL; } diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 477e066a1cf0..c18cb8e883dd 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -96,7 +96,6 @@ int e1000_up(struct e1000_adapter *adapter); void e1000_down(struct e1000_adapter *adapter); void e1000_reinit_locked(struct e1000_adapter *adapter); void e1000_reset(struct e1000_adapter *adapter); -int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx); int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); void e1000_free_all_tx_resources(struct e1000_adapter *adapter); @@ -4385,7 +4384,6 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, struct mii_ioctl_data *data = if_mii(ifr); int retval; u16 mii_reg; - u16 spddplx; unsigned long flags; if (hw->media_type != e1000_media_type_copper) @@ -4424,17 +4422,18 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, hw->autoneg = 1; hw->autoneg_advertised = 0x2F; } else { + u32 speed; if (mii_reg & 0x40) - spddplx = SPEED_1000; + speed = SPEED_1000; else if (mii_reg & 0x2000) - spddplx = SPEED_100; + speed = SPEED_100; else - spddplx = SPEED_10; - spddplx += (mii_reg & 0x100) - ? DUPLEX_FULL : - DUPLEX_HALF; - retval = e1000_set_spd_dplx(adapter, - spddplx); + speed = SPEED_10; + retval = e1000_set_spd_dplx( + adapter, speed, + ((mii_reg & 0x100) + ? DUPLEX_FULL : + DUPLEX_HALF)); if (retval) return retval; } @@ -4596,20 +4595,24 @@ static void e1000_restore_vlan(struct e1000_adapter *adapter) } } -int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) +int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx) { struct e1000_hw *hw = &adapter->hw; hw->autoneg = 0; + /* Make sure dplx is at most 1 bit and lsb of speed is not set + * for the switch() below to work */ + if ((spd & 1) || (dplx & ~1)) + goto err_inval; + /* Fiber NICs only allow 1000 gbps Full duplex */ if ((hw->media_type == e1000_media_type_fiber) && - spddplx != (SPEED_1000 + DUPLEX_FULL)) { - e_err(probe, "Unsupported Speed/Duplex configuration\n"); - return -EINVAL; - } + spd != SPEED_1000 && + dplx != DUPLEX_FULL) + goto err_inval; - switch (spddplx) { + switch (spd + dplx) { case SPEED_10 + DUPLEX_HALF: hw->forced_speed_duplex = e1000_10_half; break; @@ -4628,10 +4631,13 @@ int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) break; case SPEED_1000 + DUPLEX_HALF: /* not supported */ default: - e_err(probe, "Unsupported Speed/Duplex configuration\n"); - return -EINVAL; + goto err_inval; } return 0; + +err_inval: + e_err(probe, "Unsupported Speed/Duplex configuration\n"); + return -EINVAL; } static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake) diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 12f1ee250522..859d0d3af6c9 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -200,20 +200,25 @@ static int e1000_get_settings(struct net_device *netdev, return 0; } -static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) +static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx) { struct e1000_mac_info *mac = &adapter->hw.mac; mac->autoneg = 0; + /* Make sure dplx is at most 1 bit and lsb of speed is not set + * for the switch() below to work */ + if ((spd & 1) || (dplx & ~1)) + goto err_inval; + /* Fiber NICs only allow 1000 gbps Full duplex */ if ((adapter->hw.phy.media_type == e1000_media_type_fiber) && - spddplx != (SPEED_1000 + DUPLEX_FULL)) { - e_err("Unsupported Speed/Duplex configuration\n"); - return -EINVAL; + spd != SPEED_1000 && + dplx != DUPLEX_FULL) { + goto err_inval; } - switch (spddplx) { + switch (spd + dplx) { case SPEED_10 + DUPLEX_HALF: mac->forced_speed_duplex = ADVERTISE_10_HALF; break; @@ -232,10 +237,13 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) break; case SPEED_1000 + DUPLEX_HALF: /* not supported */ default: - e_err("Unsupported Speed/Duplex configuration\n"); - return -EINVAL; + goto err_inval; } return 0; + +err_inval: + e_err("Unsupported Speed/Duplex configuration\n"); + return -EINVAL; } static int e1000_set_settings(struct net_device *netdev, @@ -272,7 +280,7 @@ static int e1000_set_settings(struct net_device *netdev, hw->fc.requested_mode = e1000_fc_default; } else { u32 speed = ethtool_cmd_speed(ecmd); - if (e1000_set_spd_dplx(adapter, speed + ecmd->duplex)) { + if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) { clear_bit(__E1000_RESETTING, &adapter->state); return -EINVAL; } diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 1c687e298d5e..f4fa4b1751cf 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -360,7 +360,7 @@ extern int igb_up(struct igb_adapter *); extern void igb_down(struct igb_adapter *); extern void igb_reinit_locked(struct igb_adapter *); extern void igb_reset(struct igb_adapter *); -extern int igb_set_spd_dplx(struct igb_adapter *, u16); +extern int igb_set_spd_dplx(struct igb_adapter *, u32, u8); extern int igb_setup_tx_resources(struct igb_ring *); extern int igb_setup_rx_resources(struct igb_ring *); extern void igb_free_tx_resources(struct igb_ring *); diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 023aa9b10654..6e29634b1fb5 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -224,7 +224,7 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) hw->fc.requested_mode = e1000_fc_default; } else { u32 speed = ethtool_cmd_speed(ecmd); - if (igb_set_spd_dplx(adapter, speed + ecmd->duplex)) { + if (igb_set_spd_dplx(adapter, speed, ecmd->duplex)) { clear_bit(__IGB_RESETTING, &adapter->state); return -EINVAL; } diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index cdfd57271051..ce7838e55827 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -6349,21 +6349,25 @@ static void igb_restore_vlan(struct igb_adapter *adapter) } } -int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx) +int igb_set_spd_dplx(struct igb_adapter *adapter, u32 spd, u8 dplx) { struct pci_dev *pdev = adapter->pdev; struct e1000_mac_info *mac = &adapter->hw.mac; mac->autoneg = 0; + /* Make sure dplx is at most 1 bit and lsb of speed is not set + * for the switch() below to work */ + if ((spd & 1) || (dplx & ~1)) + goto err_inval; + /* Fiber NIC's only allow 1000 Gbps Full duplex */ if ((adapter->hw.phy.media_type == e1000_media_type_internal_serdes) && - spddplx != (SPEED_1000 + DUPLEX_FULL)) { - dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n"); - return -EINVAL; - } + spd != SPEED_1000 && + dplx != DUPLEX_FULL) + goto err_inval; - switch (spddplx) { + switch (spd + dplx) { case SPEED_10 + DUPLEX_HALF: mac->forced_speed_duplex = ADVERTISE_10_HALF; break; @@ -6382,10 +6386,13 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx) break; case SPEED_1000 + DUPLEX_HALF: /* not supported */ default: - dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n"); - return -EINVAL; + goto err_inval; } return 0; + +err_inval: + dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n"); + return -EINVAL; } static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake) -- cgit v1.2.3-58-ga151 From 9d39e5bad76a8830a8fa0c03cadc1e36ce2ec2ef Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 19 Apr 2011 07:38:23 -0700 Subject: iwlagn: avoid hangs when restarting device If a device error happens while the uCode is being loaded or initialised, we will attempt to restart the device (which will likely fail again, but that's not the issue here). During this new restart, we turn off the device, but as the uCode failed to initialise it already is turned off. As a consequence, grabbing NIC access will fail and cause excessive messages and hangs. To fix this issue, introduce a new status bit and only attempt to reprogram the device when it isn't already disabled. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 21 +++++++++++++++------ drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++++ drivers/net/wireless/iwlwifi/iwl-core.h | 1 + 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index e202a40cbcb7..75e1035330be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2363,12 +2363,21 @@ void iwlagn_stop_device(struct iwl_priv *priv) /* device going down, Stop using ICT table */ iwl_disable_ict(priv); - iwlagn_txq_ctx_stop(priv); - iwlagn_rxq_stop(priv); - - /* Power-down device's busmaster DMA clocks */ - iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); - udelay(5); + /* + * If a HW restart happens during firmware loading, + * then the firmware loading might call this function + * and later it might be called again due to the + * restart. So don't process again if the device is + * already dead. + */ + if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) { + iwlagn_txq_ctx_stop(priv); + iwlagn_rxq_stop(priv); + + /* Power-down device's busmaster DMA clocks */ + iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); + udelay(5); + } /* Make sure (redundant) we've released our request to stay awake */ iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index af72fd51ea74..66da1dec982c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -995,6 +995,8 @@ void iwl_apm_stop(struct iwl_priv *priv) { IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n"); + clear_bit(STATUS_DEVICE_ENABLED, &priv->status); + /* Stop device's DMA activity */ iwl_apm_stop_master(priv); @@ -1109,6 +1111,8 @@ int iwl_apm_init(struct iwl_priv *priv) iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); + set_bit(STATUS_DEVICE_ENABLED, &priv->status); + out: return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 32a990ff09ae..6226e3d9f101 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -592,6 +592,7 @@ void iwlcore_free_geos(struct iwl_priv *priv); #define STATUS_SCAN_HW 15 #define STATUS_POWER_PMI 16 #define STATUS_FW_ERROR 17 +#define STATUS_DEVICE_ENABLED 18 static inline int iwl_is_ready(struct iwl_priv *priv) -- cgit v1.2.3-58-ga151 From 4119904f3ebf30c25afb42195740f9ee5dc7749c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 19 Apr 2011 07:42:03 -0700 Subject: iwlagn: introduce silent grabbing of NIC access There are a few cases like the WoWLAN support I'm writing that require attempting to access the NIC when it is known that it might not be accessible, e.g. after the system woke up and the platform might have reset the device. To avoid messages in this case, introduce the new function iwl_grab_nic_access_silent(), it will only return an error status. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-io.c | 18 +++++++++++++----- drivers/net/wireless/iwlwifi/iwl-io.h | 1 + 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 993b3df1b72b..aa4a90674452 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -73,10 +73,9 @@ int iwl_poll_bit(struct iwl_priv *priv, u32 addr, return -ETIMEDOUT; } -int iwl_grab_nic_access(struct iwl_priv *priv) +int iwl_grab_nic_access_silent(struct iwl_priv *priv) { int ret; - u32 val; lockdep_assert_held(&priv->reg_lock); @@ -107,9 +106,6 @@ int iwl_grab_nic_access(struct iwl_priv *priv) (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); if (ret < 0) { - val = iwl_read32(priv, CSR_GP_CNTRL); - IWL_ERR(priv, - "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); return -EIO; } @@ -117,6 +113,18 @@ int iwl_grab_nic_access(struct iwl_priv *priv) return 0; } +int iwl_grab_nic_access(struct iwl_priv *priv) +{ + int ret = iwl_grab_nic_access_silent(priv); + if (ret) { + u32 val = iwl_read32(priv, CSR_GP_CNTRL); + IWL_ERR(priv, + "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); + } + + return ret; +} + void iwl_release_nic_access(struct iwl_priv *priv) { lockdep_assert_held(&priv->reg_lock); diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 262e0262496d..869edc580ec6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -62,6 +62,7 @@ int iwl_poll_bit(struct iwl_priv *priv, u32 addr, int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, int timeout); +int iwl_grab_nic_access_silent(struct iwl_priv *priv); int iwl_grab_nic_access(struct iwl_priv *priv); void iwl_release_nic_access(struct iwl_priv *priv); -- cgit v1.2.3-58-ga151 From e43e85c40d83f0a7a6ff5631d1009d142b72dbca Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 19 Apr 2011 07:45:16 -0700 Subject: iwlagn: refactor restart The WoWLAN resume code will have to essentially do a restart, but without going through the work struct. To support that, refactor the restart by splitting out the preparation code into a new function. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 68 ++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a4ec524f4655..c27147c4d4a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2493,6 +2493,42 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) mutex_unlock(&priv->mutex); } +static void iwlagn_prepare_restart(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx; + bool bt_full_concurrent; + u8 bt_ci_compliance; + u8 bt_load; + u8 bt_status; + + lockdep_assert_held(&priv->mutex); + + for_each_context(priv, ctx) + ctx->vif = NULL; + priv->is_open = 0; + + /* + * __iwl_down() will clear the BT status variables, + * which is correct, but when we restart we really + * want to keep them so restore them afterwards. + * + * The restart process will later pick them up and + * re-configure the hw when we reconfigure the BT + * command. + */ + bt_full_concurrent = priv->bt_full_concurrent; + bt_ci_compliance = priv->bt_ci_compliance; + bt_load = priv->bt_traffic_load; + bt_status = priv->bt_status; + + __iwl_down(priv); + + priv->bt_full_concurrent = bt_full_concurrent; + priv->bt_ci_compliance = bt_ci_compliance; + priv->bt_traffic_load = bt_load; + priv->bt_status = bt_status; +} + static void iwl_bg_restart(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); @@ -2501,38 +2537,8 @@ static void iwl_bg_restart(struct work_struct *data) return; if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { - struct iwl_rxon_context *ctx; - bool bt_full_concurrent; - u8 bt_ci_compliance; - u8 bt_load; - u8 bt_status; - mutex_lock(&priv->mutex); - for_each_context(priv, ctx) - ctx->vif = NULL; - priv->is_open = 0; - - /* - * __iwl_down() will clear the BT status variables, - * which is correct, but when we restart we really - * want to keep them so restore them afterwards. - * - * The restart process will later pick them up and - * re-configure the hw when we reconfigure the BT - * command. - */ - bt_full_concurrent = priv->bt_full_concurrent; - bt_ci_compliance = priv->bt_ci_compliance; - bt_load = priv->bt_traffic_load; - bt_status = priv->bt_status; - - __iwl_down(priv); - - priv->bt_full_concurrent = bt_full_concurrent; - priv->bt_ci_compliance = bt_ci_compliance; - priv->bt_traffic_load = bt_load; - priv->bt_status = bt_status; - + iwlagn_prepare_restart(priv); mutex_unlock(&priv->mutex); iwl_cancel_deferred_work(priv); ieee80211_restart_hw(priv->hw); -- cgit v1.2.3-58-ga151 From c3f6e9cff950c312d409e5767365aeb2475b2ab7 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 19 Apr 2011 16:52:57 -0700 Subject: iwlagn: make rxon_assoc static function Move rxon_assoc to static function from ops Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 50 ----------------------------- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 50 ++++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-agn.h | 2 -- drivers/net/wireless/iwlwifi/iwl-core.h | 6 ---- 4 files changed, 49 insertions(+), 59 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 861cc93957a9..49dd03f9feda 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -37,54 +37,6 @@ #include "iwl-io.h" #include "iwl-agn.h" -int iwlagn_send_rxon_assoc(struct iwl_priv *priv, - struct iwl_rxon_context *ctx) -{ - int ret = 0; - struct iwl5000_rxon_assoc_cmd rxon_assoc; - const struct iwl_rxon_cmd *rxon1 = &ctx->staging; - const struct iwl_rxon_cmd *rxon2 = &ctx->active; - - if ((rxon1->flags == rxon2->flags) && - (rxon1->filter_flags == rxon2->filter_flags) && - (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && - (rxon1->ofdm_ht_single_stream_basic_rates == - rxon2->ofdm_ht_single_stream_basic_rates) && - (rxon1->ofdm_ht_dual_stream_basic_rates == - rxon2->ofdm_ht_dual_stream_basic_rates) && - (rxon1->ofdm_ht_triple_stream_basic_rates == - rxon2->ofdm_ht_triple_stream_basic_rates) && - (rxon1->acquisition_data == rxon2->acquisition_data) && - (rxon1->rx_chain == rxon2->rx_chain) && - (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { - IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); - return 0; - } - - rxon_assoc.flags = ctx->staging.flags; - rxon_assoc.filter_flags = ctx->staging.filter_flags; - rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; - rxon_assoc.reserved1 = 0; - rxon_assoc.reserved2 = 0; - rxon_assoc.reserved3 = 0; - rxon_assoc.ofdm_ht_single_stream_basic_rates = - ctx->staging.ofdm_ht_single_stream_basic_rates; - rxon_assoc.ofdm_ht_dual_stream_basic_rates = - ctx->staging.ofdm_ht_dual_stream_basic_rates; - rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain; - rxon_assoc.ofdm_ht_triple_stream_basic_rates = - ctx->staging.ofdm_ht_triple_stream_basic_rates; - rxon_assoc.acquisition_data = ctx->staging.acquisition_data; - - ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd, - sizeof(rxon_assoc), &rxon_assoc, NULL); - if (ret) - return ret; - - return ret; -} - int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) { struct iwl_tx_ant_config_cmd tx_ant_cmd = { @@ -364,7 +316,6 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) } struct iwl_hcmd_ops iwlagn_hcmd = { - .rxon_assoc = iwlagn_send_rxon_assoc, .commit_rxon = iwlagn_commit_rxon, .set_rxon_chain = iwlagn_set_rxon_chain, .set_tx_ant = iwlagn_send_tx_ant_config, @@ -373,7 +324,6 @@ struct iwl_hcmd_ops iwlagn_hcmd = { }; struct iwl_hcmd_ops iwlagn_bt_hcmd = { - .rxon_assoc = iwlagn_send_rxon_assoc, .commit_rxon = iwlagn_commit_rxon, .set_rxon_chain = iwlagn_set_rxon_chain, .set_tx_ant = iwlagn_send_tx_ant_config, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 202ef64a14d5..aba5bc9cf6e0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -121,6 +121,54 @@ static int iwlagn_update_beacon(struct iwl_priv *priv, return iwlagn_send_beacon_cmd(priv); } +static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) +{ + int ret = 0; + struct iwl5000_rxon_assoc_cmd rxon_assoc; + const struct iwl_rxon_cmd *rxon1 = &ctx->staging; + const struct iwl_rxon_cmd *rxon2 = &ctx->active; + + if ((rxon1->flags == rxon2->flags) && + (rxon1->filter_flags == rxon2->filter_flags) && + (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && + (rxon1->ofdm_ht_single_stream_basic_rates == + rxon2->ofdm_ht_single_stream_basic_rates) && + (rxon1->ofdm_ht_dual_stream_basic_rates == + rxon2->ofdm_ht_dual_stream_basic_rates) && + (rxon1->ofdm_ht_triple_stream_basic_rates == + rxon2->ofdm_ht_triple_stream_basic_rates) && + (rxon1->acquisition_data == rxon2->acquisition_data) && + (rxon1->rx_chain == rxon2->rx_chain) && + (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { + IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); + return 0; + } + + rxon_assoc.flags = ctx->staging.flags; + rxon_assoc.filter_flags = ctx->staging.filter_flags; + rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; + rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; + rxon_assoc.reserved1 = 0; + rxon_assoc.reserved2 = 0; + rxon_assoc.reserved3 = 0; + rxon_assoc.ofdm_ht_single_stream_basic_rates = + ctx->staging.ofdm_ht_single_stream_basic_rates; + rxon_assoc.ofdm_ht_dual_stream_basic_rates = + ctx->staging.ofdm_ht_dual_stream_basic_rates; + rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain; + rxon_assoc.ofdm_ht_triple_stream_basic_rates = + ctx->staging.ofdm_ht_triple_stream_basic_rates; + rxon_assoc.acquisition_data = ctx->staging.acquisition_data; + + ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd, + sizeof(rxon_assoc), &rxon_assoc, NULL); + if (ret) + return ret; + + return ret; +} + /** * iwlagn_commit_rxon - commit staging_rxon to hardware * @@ -200,7 +248,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) * and other flags for the current radio configuration. */ if (!iwl_full_rxon_required(priv, ctx)) { - ret = iwl_send_rxon_assoc(priv, ctx); + ret = iwlagn_send_rxon_assoc(priv, ctx); if (ret) { IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index c475ac427596..7d8e16ec608c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -256,8 +256,6 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add); /* hcmd */ -int iwlagn_send_rxon_assoc(struct iwl_priv *priv, - struct iwl_rxon_context *ctx); int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); int iwlagn_send_beacon_cmd(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 6226e3d9f101..4cdb85d971ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -90,7 +90,6 @@ struct iwl_cmd; #define IWL_CMD(x) case x: return #x struct iwl_hcmd_ops { - int (*rxon_assoc)(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int (*commit_rxon)(struct iwl_priv *priv, struct iwl_rxon_context *ctx); void (*set_rxon_chain)(struct iwl_priv *priv, struct iwl_rxon_context *ctx); @@ -645,11 +644,6 @@ void iwl_apm_stop(struct iwl_priv *priv); int iwl_apm_init(struct iwl_priv *priv); int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx); -static inline int iwl_send_rxon_assoc(struct iwl_priv *priv, - struct iwl_rxon_context *ctx) -{ - return priv->cfg->ops->hcmd->rxon_assoc(priv, ctx); -} static inline int iwlcore_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { -- cgit v1.2.3-58-ga151 From 89e746b244064406c3bfe442bb64c3230f42fa98 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 19 Apr 2011 16:52:58 -0700 Subject: iwlagn: remove 5000 from rxon_assoc structure The data structure is shared by all _agn devices, remove the reference to 5000 Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 2 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index aba5bc9cf6e0..7f52ab8f5848 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -125,7 +125,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { int ret = 0; - struct iwl5000_rxon_assoc_cmd rxon_assoc; + struct iwl_rxon_assoc_cmd rxon_assoc; const struct iwl_rxon_cmd *rxon1 = &ctx->staging; const struct iwl_rxon_cmd *rxon2 = &ctx->active; diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index e125896c8096..5fdad6532118 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -661,7 +661,7 @@ struct iwl_rxon_cmd { /* * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response) */ -struct iwl5000_rxon_assoc_cmd { +struct iwl_rxon_assoc_cmd { __le32 flags; __le32 filter_flags; u8 ofdm_basic_rates; -- cgit v1.2.3-58-ga151 From c1821c95c13240c2c8d3da8845c2021e575e29c6 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 19 Apr 2011 16:52:59 -0700 Subject: iwlagn: connect and disconnect sequence for RXON No functional changes, separate the connect and disconnect sequences in RXON commit function, easier to read and understand. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 194 ++++++++++++++++------------ 1 file changed, 111 insertions(+), 83 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 7f52ab8f5848..178b2b5a53b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -169,6 +169,103 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, return ret; } +static int iwlagn_rxon_disconn(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) +{ + int ret; + struct iwl_rxon_cmd *active = (void *)&ctx->active; + + if (ctx->ctxid == IWL_RXON_CTX_BSS) + ret = iwlagn_disable_bss(priv, ctx, &ctx->staging); + else + ret = iwlagn_disable_pan(priv, ctx, &ctx->staging); + if (ret) + return ret; + + /* + * Un-assoc RXON clears the station table and WEP + * keys, so we have to restore those afterwards. + */ + iwl_clear_ucode_stations(priv, ctx); + iwl_restore_stations(priv, ctx); + ret = iwl_restore_default_wep_keys(priv, ctx); + if (ret) { + IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); + return ret; + } + + memcpy(active, &ctx->staging, sizeof(*active)); + return 0; +} + +static int iwlagn_rxon_connect(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) +{ + int ret; + struct iwl_rxon_cmd *active = (void *)&ctx->active; + + /* RXON timing must be before associated RXON */ + ret = iwl_send_rxon_timing(priv, ctx); + if (ret) { + IWL_ERR(priv, "Failed to send timing (%d)!\n", ret); + return ret; + } + /* QoS info may be cleared by previous un-assoc RXON */ + iwlagn_update_qos(priv, ctx); + + /* + * We'll run into this code path when beaconing is + * enabled, but then we also need to send the beacon + * to the device. + */ + if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) { + ret = iwlagn_update_beacon(priv, ctx->vif); + if (ret) { + IWL_ERR(priv, + "Error sending required beacon (%d)!\n", + ret); + return ret; + } + } + + priv->start_calib = 0; + /* + * Apply the new configuration. + * + * Associated RXON doesn't clear the station table in uCode, + * so we don't need to restore stations etc. after this. + */ + ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, + sizeof(struct iwl_rxon_cmd), &ctx->staging); + if (ret) { + IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); + return ret; + } + memcpy(active, &ctx->staging, sizeof(*active)); + + iwl_reprogram_ap_sta(priv, ctx); + + /* IBSS beacon needs to be sent after setting assoc */ + if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC)) + if (iwlagn_update_beacon(priv, ctx->vif)) + IWL_ERR(priv, "Error sending IBSS beacon\n"); + iwl_init_sensitivity(priv); + + /* + * If we issue a new RXON command which required a tune then + * we must send a new TXPOWER command or we won't be able to + * Tx any frames. + * + * It's expected we set power here if channel is changing. + */ + ret = iwl_set_tx_power(priv, priv->tx_power_next, true); + if (ret) { + IWL_ERR(priv, "Error sending TX power (%d)\n", ret); + return ret; + } + return 0; +} + /** * iwlagn_commit_rxon - commit staging_rxon to hardware * @@ -176,6 +273,16 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, * the active_rxon structure is updated with the new data. This * function correctly transitions out of the RXON_ASSOC_MSK state if * a HW tune is required based on the RXON structure changes. + * + * The connect/disconnect flow should be as the following: + * + * 1. make sure send RXON command with association bit unset if not connect + * this should include the channel and the band for the candidate + * to be connected to + * 2. Add Station before RXON association with the AP + * 3. RXON_timing has to send before RXON for connection + * 4. full RXON command - associated bit set + * 5. use RXON_ASSOC command to update any flags changes */ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { @@ -225,6 +332,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) else ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + iwl_print_rx_config_cmd(priv, ctx); ret = iwl_check_rxon_cmd(priv, ctx); if (ret) { IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); @@ -255,7 +363,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } memcpy(active, &ctx->staging, sizeof(*active)); - iwl_print_rx_config_cmd(priv, ctx); return 0; } @@ -283,92 +390,13 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) * set up filters in the device. */ if ((old_assoc && new_assoc) || !new_assoc) { - if (ctx->ctxid == IWL_RXON_CTX_BSS) - ret = iwlagn_disable_bss(priv, ctx, &ctx->staging); - else - ret = iwlagn_disable_pan(priv, ctx, &ctx->staging); + ret = iwlagn_rxon_disconn(priv, ctx); if (ret) return ret; - - memcpy(active, &ctx->staging, sizeof(*active)); - - /* - * Un-assoc RXON clears the station table and WEP - * keys, so we have to restore those afterwards. - */ - iwl_clear_ucode_stations(priv, ctx); - iwl_restore_stations(priv, ctx); - ret = iwl_restore_default_wep_keys(priv, ctx); - if (ret) { - IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); - return ret; - } } - /* RXON timing must be before associated RXON */ - ret = iwl_send_rxon_timing(priv, ctx); - if (ret) { - IWL_ERR(priv, "Failed to send timing (%d)!\n", ret); - return ret; - } - - if (new_assoc) { - /* QoS info may be cleared by previous un-assoc RXON */ - iwlagn_update_qos(priv, ctx); - - /* - * We'll run into this code path when beaconing is - * enabled, but then we also need to send the beacon - * to the device. - */ - if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) { - ret = iwlagn_update_beacon(priv, ctx->vif); - if (ret) { - IWL_ERR(priv, - "Error sending required beacon (%d)!\n", - ret); - return ret; - } - } - - priv->start_calib = 0; - /* - * Apply the new configuration. - * - * Associated RXON doesn't clear the station table in uCode, - * so we don't need to restore stations etc. after this. - */ - ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, - sizeof(struct iwl_rxon_cmd), &ctx->staging); - if (ret) { - IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); - return ret; - } - memcpy(active, &ctx->staging, sizeof(*active)); - - iwl_reprogram_ap_sta(priv, ctx); - - /* IBSS beacon needs to be sent after setting assoc */ - if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC)) - if (iwlagn_update_beacon(priv, ctx->vif)) - IWL_ERR(priv, "Error sending IBSS beacon\n"); - } - - iwl_print_rx_config_cmd(priv, ctx); - - iwl_init_sensitivity(priv); - - /* - * If we issue a new RXON command which required a tune then we must - * send a new TXPOWER command or we won't be able to Tx any frames. - * - * It's expected we set power here if channel is changing. - */ - ret = iwl_set_tx_power(priv, priv->tx_power_next, true); - if (ret) { - IWL_ERR(priv, "Error sending TX power (%d)\n", ret); - return ret; - } + if (new_assoc) + return iwlagn_rxon_connect(priv, ctx); return 0; } -- cgit v1.2.3-58-ga151 From d2690c0db7146b12e4fc2d572053c823e512758a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 20 Apr 2011 09:10:39 -0700 Subject: iwlagn: use proper good CRC threshold behaviour New microcode versions use the good CRC threshold field differently, as a flag, and in that case we should set it to 1/0 instead of 1/65535 for an active/passive scan. The new behaviour is advertised by the uCode with a feature flag. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 12 ++++++++++-- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 +++ drivers/net/wireless/iwlwifi/iwl-dev.h | 7 +++++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 75e1035330be..7fe9e0f17b1e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1294,9 +1294,17 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) * mean we never reach it, but at the same time work around * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER * here instead of IWL_GOOD_CRC_TH_DISABLED. + * + * This was fixed in later versions along with some other + * scan changes, and the threshold behaves as a flag in those + * versions. */ - scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : - IWL_GOOD_CRC_TH_NEVER; + if (priv->new_scan_threshold_behaviour) + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : + IWL_GOOD_CRC_TH_DISABLED; + else + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : + IWL_GOOD_CRC_TH_NEVER; band = priv->scan_band; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c27147c4d4a7..395d1ade39d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1716,6 +1716,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) priv->cfg->base_params->max_event_log_size; priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; + priv->new_scan_threshold_behaviour = + !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); + if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN); priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 197fa742f79a..f098eff263f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -547,12 +547,13 @@ enum iwl_ucode_tlv_type { * enum iwl_ucode_tlv_flag - ucode API flags * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously * was a separate TLV but moved here to save space. - * @IWL_UCODE_TLV_FLAGS_RESERVED_1: reserved + * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID, + * treats good CRC threshold as a boolean * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). */ enum iwl_ucode_tlv_flag { IWL_UCODE_TLV_FLAGS_PAN = BIT(0), - IWL_UCODE_TLV_FLAGS_RESERVED_1 = BIT(1), + IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), IWL_UCODE_TLV_FLAGS_MFP = BIT(2), }; @@ -1263,6 +1264,8 @@ struct iwl_priv { /* max number of station keys */ u8 sta_key_max_num; + bool new_scan_threshold_behaviour; + /* EEPROM MAC addresses */ struct mac_address addresses[2]; -- cgit v1.2.3-58-ga151 From b4ed221daba1b129c3efff8a7352d9791d034330 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 30 Apr 2011 08:55:16 -0700 Subject: iwlagn: new 105 series device Correction for new 105 series devices Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-2000.c | 58 ++++++++++++++++----------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 30 ++++++++--------- drivers/net/wireless/iwlwifi/iwl-agn.h | 8 ++--- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index e76e02c28928..f90d6afc58c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -51,12 +51,12 @@ /* Highest firmware API version supported */ #define IWL2030_UCODE_API_MAX 5 #define IWL2000_UCODE_API_MAX 5 -#define IWL200_UCODE_API_MAX 5 +#define IWL105_UCODE_API_MAX 5 /* Lowest firmware API version supported */ #define IWL2030_UCODE_API_MIN 5 #define IWL2000_UCODE_API_MIN 5 -#define IWL200_UCODE_API_MIN 5 +#define IWL105_UCODE_API_MIN 5 #define IWL2030_FW_PRE "iwlwifi-2030-" #define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode" @@ -64,8 +64,8 @@ #define IWL2000_FW_PRE "iwlwifi-2000-" #define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode" -#define IWL200_FW_PRE "iwlwifi-200-" -#define IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE #api ".ucode" +#define IWL105_FW_PRE "iwlwifi-105-" +#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE #api ".ucode" static void iwl2000_set_ct_threshold(struct iwl_priv *priv) { @@ -312,13 +312,13 @@ static const struct iwl_ops iwl2030_ops = { .utils = &iwlagn_hcmd_utils, }; -static const struct iwl_ops iwl200_ops = { +static const struct iwl_ops iwl105_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, }; -static const struct iwl_ops iwl230_ops = { +static const struct iwl_ops iwl135_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_bt_hcmd, .utils = &iwlagn_hcmd_utils, @@ -429,13 +429,13 @@ struct iwl_cfg iwl2030_2bg_cfg = { IWL_DEVICE_2030, }; -#define IWL_DEVICE_200 \ - .fw_name_pre = IWL200_FW_PRE, \ - .ucode_api_max = IWL200_UCODE_API_MAX, \ - .ucode_api_min = IWL200_UCODE_API_MIN, \ +#define IWL_DEVICE_105 \ + .fw_name_pre = IWL105_FW_PRE, \ + .ucode_api_max = IWL105_UCODE_API_MAX, \ + .ucode_api_min = IWL105_UCODE_API_MIN, \ .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ - .ops = &iwl200_ops, \ + .ops = &iwl105_ops, \ .mod_params = &iwlagn_mod_params, \ .base_params = &iwl2000_base_params, \ .need_dc_calib = true, \ @@ -444,24 +444,24 @@ struct iwl_cfg iwl2030_2bg_cfg = { .adv_pm = true, \ .rx_with_siso_diversity = true \ -struct iwl_cfg iwl200_bg_cfg = { - .name = "200 Series 1x1 BG", - IWL_DEVICE_200, +struct iwl_cfg iwl105_bg_cfg = { + .name = "105 Series 1x1 BG", + IWL_DEVICE_105, }; -struct iwl_cfg iwl200_bgn_cfg = { - .name = "200 Series 1x1 BGN", - IWL_DEVICE_200, +struct iwl_cfg iwl105_bgn_cfg = { + .name = "105 Series 1x1 BGN", + IWL_DEVICE_105, .ht_params = &iwl2000_ht_params, }; -#define IWL_DEVICE_230 \ - .fw_name_pre = IWL200_FW_PRE, \ - .ucode_api_max = IWL200_UCODE_API_MAX, \ - .ucode_api_min = IWL200_UCODE_API_MIN, \ +#define IWL_DEVICE_135 \ + .fw_name_pre = IWL105_FW_PRE, \ + .ucode_api_max = IWL105_UCODE_API_MAX, \ + .ucode_api_min = IWL105_UCODE_API_MIN, \ .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ - .ops = &iwl230_ops, \ + .ops = &iwl135_ops, \ .mod_params = &iwlagn_mod_params, \ .base_params = &iwl2030_base_params, \ .bt_params = &iwl2030_bt_params, \ @@ -471,17 +471,17 @@ struct iwl_cfg iwl200_bgn_cfg = { .adv_pm = true, \ .rx_with_siso_diversity = true \ -struct iwl_cfg iwl230_bg_cfg = { - .name = "200 Series 1x1 BG/BT", - IWL_DEVICE_230, +struct iwl_cfg iwl135_bg_cfg = { + .name = "105 Series 1x1 BG/BT", + IWL_DEVICE_135, }; -struct iwl_cfg iwl230_bgn_cfg = { - .name = "200 Series 1x1 BGN/BT", - IWL_DEVICE_230, +struct iwl_cfg iwl135_bgn_cfg = { + .name = "105 Series 1x1 BGN/BT", + IWL_DEVICE_135, .ht_params = &iwl2000_ht_params, }; MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL200_MODULE_FIRMWARE(IWL200_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 395d1ade39d3..8232245b7b6f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -4129,21 +4129,21 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)}, {IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)}, -/* 200 Series */ - {IWL_PCI_DEVICE(0x0894, 0x0022, iwl200_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0895, 0x0222, iwl200_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0894, 0x0422, iwl200_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0894, 0x0026, iwl200_bg_cfg)}, - {IWL_PCI_DEVICE(0x0895, 0x0226, iwl200_bg_cfg)}, - {IWL_PCI_DEVICE(0x0894, 0x0426, iwl200_bg_cfg)}, - -/* 230 Series */ - {IWL_PCI_DEVICE(0x0892, 0x0062, iwl230_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0893, 0x0262, iwl230_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0892, 0x0462, iwl230_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0892, 0x0066, iwl230_bg_cfg)}, - {IWL_PCI_DEVICE(0x0893, 0x0266, iwl230_bg_cfg)}, - {IWL_PCI_DEVICE(0x0892, 0x0466, iwl230_bg_cfg)}, +/* 105 Series */ + {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)}, + {IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)}, + {IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)}, + {IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)}, + {IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)}, + {IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)}, + +/* 135 Series */ + {IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)}, + {IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)}, + {IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)}, + {IWL_PCI_DEVICE(0x0892, 0x0066, iwl135_bg_cfg)}, + {IWL_PCI_DEVICE(0x0893, 0x0266, iwl135_bg_cfg)}, + {IWL_PCI_DEVICE(0x0892, 0x0466, iwl135_bg_cfg)}, {0} }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 7d8e16ec608c..9d644d413b40 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -102,10 +102,10 @@ extern struct iwl_cfg iwl2030_2bg_cfg; extern struct iwl_cfg iwl6035_2agn_cfg; extern struct iwl_cfg iwl6035_2abg_cfg; extern struct iwl_cfg iwl6035_2bg_cfg; -extern struct iwl_cfg iwl200_bg_cfg; -extern struct iwl_cfg iwl200_bgn_cfg; -extern struct iwl_cfg iwl230_bg_cfg; -extern struct iwl_cfg iwl230_bgn_cfg; +extern struct iwl_cfg iwl105_bg_cfg; +extern struct iwl_cfg iwl105_bgn_cfg; +extern struct iwl_cfg iwl135_bg_cfg; +extern struct iwl_cfg iwl135_bgn_cfg; extern struct iwl_mod_params iwlagn_mod_params; extern struct iwl_hcmd_ops iwlagn_hcmd; -- cgit v1.2.3-58-ga151 From 9d143e9a0d68025efe902d86eb6207cbec36dcdb Mon Sep 17 00:00:00 2001 From: Don Fry Date: Wed, 20 Apr 2011 15:23:57 -0700 Subject: iwlagn: mod param cleanup All agn devices use the same module parameter structure. Delete the indirection and access the structure diretly. Signed-off-by: Don Fry Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 8 +++----- drivers/net/wireless/iwlwifi/iwl-2000.c | 10 +++------- drivers/net/wireless/iwlwifi/iwl-5000.c | 15 ++++++--------- drivers/net/wireless/iwlwifi/iwl-6000.c | 12 +++--------- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-core.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-core.h | 2 -- drivers/net/wireless/iwlwifi/iwl-rx.c | 7 +++---- 10 files changed, 27 insertions(+), 44 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index baf80111efaf..d2b1be65f903 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -121,10 +121,10 @@ static struct iwl_sensitivity_ranges iwl1000_sensitivity = { static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) { - if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && - priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) + if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && + iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) priv->cfg->base_params->num_of_queues = - priv->cfg->mod_params->num_of_queues; + iwlagn_mod_params.num_of_queues; priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; @@ -249,7 +249,6 @@ static struct iwl_ht_params iwl1000_ht_params = { .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ .ops = &iwl1000_ops, \ - .mod_params = &iwlagn_mod_params, \ .base_params = &iwl1000_base_params, \ .led_mode = IWL_LED_BLINK @@ -271,7 +270,6 @@ struct iwl_cfg iwl1000_bg_cfg = { .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ .ops = &iwl1000_ops, \ - .mod_params = &iwlagn_mod_params, \ .base_params = &iwl1000_base_params, \ .led_mode = IWL_LED_RF_STATE, \ .rx_with_siso_diversity = true diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index f90d6afc58c1..476150f67d29 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -128,10 +128,10 @@ static struct iwl_sensitivity_ranges iwl2000_sensitivity = { static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) { - if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && - priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) + if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && + iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) priv->cfg->base_params->num_of_queues = - priv->cfg->mod_params->num_of_queues; + iwlagn_mod_params.num_of_queues; priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; @@ -383,7 +383,6 @@ static struct iwl_bt_params iwl2030_bt_params = { .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .ops = &iwl2000_ops, \ - .mod_params = &iwlagn_mod_params, \ .base_params = &iwl2000_base_params, \ .need_dc_calib = true, \ .need_temp_offset_calib = true, \ @@ -409,7 +408,6 @@ struct iwl_cfg iwl2000_2bg_cfg = { .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .ops = &iwl2030_ops, \ - .mod_params = &iwlagn_mod_params, \ .base_params = &iwl2030_base_params, \ .bt_params = &iwl2030_bt_params, \ .need_dc_calib = true, \ @@ -436,7 +434,6 @@ struct iwl_cfg iwl2030_2bg_cfg = { .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .ops = &iwl105_ops, \ - .mod_params = &iwlagn_mod_params, \ .base_params = &iwl2000_base_params, \ .need_dc_calib = true, \ .need_temp_offset_calib = true, \ @@ -462,7 +459,6 @@ struct iwl_cfg iwl105_bgn_cfg = { .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .ops = &iwl135_ops, \ - .mod_params = &iwlagn_mod_params, \ .base_params = &iwl2030_base_params, \ .bt_params = &iwl2030_bt_params, \ .need_dc_calib = true, \ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 655afc19f68f..969c91a2974e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -165,10 +165,10 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) { - if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && - priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) + if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && + iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) priv->cfg->base_params->num_of_queues = - priv->cfg->mod_params->num_of_queues; + iwlagn_mod_params.num_of_queues; priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; @@ -210,10 +210,10 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) { - if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && - priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) + if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && + iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) priv->cfg->base_params->num_of_queues = - priv->cfg->mod_params->num_of_queues; + iwlagn_mod_params.num_of_queues; priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; @@ -468,7 +468,6 @@ static struct iwl_ht_params iwl5000_ht_params = { .eeprom_ver = EEPROM_5000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \ .ops = &iwl5000_ops, \ - .mod_params = &iwlagn_mod_params, \ .base_params = &iwl5000_base_params, \ .led_mode = IWL_LED_BLINK @@ -512,7 +511,6 @@ struct iwl_cfg iwl5350_agn_cfg = { .eeprom_ver = EEPROM_5050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, .ops = &iwl5000_ops, - .mod_params = &iwlagn_mod_params, .base_params = &iwl5000_base_params, .ht_params = &iwl5000_ht_params, .led_mode = IWL_LED_BLINK, @@ -526,7 +524,6 @@ struct iwl_cfg iwl5350_agn_cfg = { .eeprom_ver = EEPROM_5050_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ .ops = &iwl5150_ops, \ - .mod_params = &iwlagn_mod_params, \ .base_params = &iwl5000_base_params, \ .need_dc_calib = true, \ .led_mode = IWL_LED_BLINK, \ diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 905eb57f7cab..91edb57371e7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -154,10 +154,10 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = { static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) { - if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && - priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) + if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && + iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) priv->cfg->base_params->num_of_queues = - priv->cfg->mod_params->num_of_queues; + iwlagn_mod_params.num_of_queues; priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; @@ -482,7 +482,6 @@ static struct iwl_bt_params iwl6000_bt_params = { .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ .ops = &iwl6000_ops, \ - .mod_params = &iwlagn_mod_params, \ .base_params = &iwl6000_g2_base_params, \ .need_dc_calib = true, \ .need_temp_offset_calib = true, \ @@ -511,7 +510,6 @@ struct iwl_cfg iwl6005_2bg_cfg = { .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ .ops = &iwl6030_ops, \ - .mod_params = &iwlagn_mod_params, \ .base_params = &iwl6000_g2_base_params, \ .bt_params = &iwl6000_bt_params, \ .need_dc_calib = true, \ @@ -593,7 +591,6 @@ struct iwl_cfg iwl130_bg_cfg = { .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ .ops = &iwl6000_ops, \ - .mod_params = &iwlagn_mod_params, \ .base_params = &iwl6000_base_params, \ .pa_type = IWL_PA_INTERNAL, \ .led_mode = IWL_LED_BLINK @@ -623,7 +620,6 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .ops = &iwl6050_ops, \ .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ - .mod_params = &iwlagn_mod_params, \ .base_params = &iwl6050_base_params, \ .need_dc_calib = true, \ .led_mode = IWL_LED_BLINK, \ @@ -648,7 +644,6 @@ struct iwl_cfg iwl6150_bgn_cfg = { .eeprom_ver = EEPROM_6150_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, .ops = &iwl6150_ops, - .mod_params = &iwlagn_mod_params, .base_params = &iwl6050_base_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, @@ -664,7 +659,6 @@ struct iwl_cfg iwl6000_3agn_cfg = { .eeprom_ver = EEPROM_6000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .ops = &iwl6000_ops, - .mod_params = &iwlagn_mod_params, .base_params = &iwl6000_base_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 7fe9e0f17b1e..8e79653aed9a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -665,7 +665,7 @@ int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) rb_timeout = RX_RB_TIMEOUT; - if (priv->cfg->mod_params->amsdu_size_8K) + if (iwlagn_mod_params.amsdu_size_8K) rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; else rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 178b2b5a53b4..02387430f7fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -372,7 +372,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) return ret; } - iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); + iwl_set_rxon_hwcrypto(priv, ctx, !iwlagn_mod_params.sw_crypto); IWL_DEBUG_INFO(priv, "Going to commit RXON\n" diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8232245b7b6f..003d5243542b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2834,7 +2834,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, IWL_DEBUG_MAC80211(priv, "enter\n"); - if (priv->cfg->mod_params->sw_crypto) { + if (iwlagn_mod_params.sw_crypto) { IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); return -EOPNOTSUPP; } @@ -3522,14 +3522,14 @@ static int iwl_set_hw_params(struct iwl_priv *priv) { priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; - if (priv->cfg->mod_params->amsdu_size_8K) + if (iwlagn_mod_params.amsdu_size_8K) priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); else priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; - if (priv->cfg->mod_params->disable_11n) + if (iwlagn_mod_params.disable_11n) priv->cfg->sku &= ~IWL_SKU_N; /* Device-specific setup */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 66da1dec982c..1b2a7d9141c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -41,6 +41,7 @@ #include "iwl-power.h" #include "iwl-sta.h" #include "iwl-helpers.h" +#include "iwl-agn.h" /* @@ -94,7 +95,7 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, max_bit_rate = MAX_BIT_RATE_40_MHZ; } - if (priv->cfg->mod_params->amsdu_size_8K) + if (iwlagn_mod_params.amsdu_size_8K) ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; @@ -926,7 +927,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) } if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { - if (priv->cfg->mod_params->restart_fw) { + if (iwlagn_mod_params.restart_fw) { IWL_DEBUG(priv, IWL_DL_FW_ERRORS, "Restarting adapter due to uCode error.\n"); queue_work(priv->workqueue, &priv->restart); @@ -1747,7 +1748,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) * detect failure), then fw_restart module parameter * need to be check before performing firmware reload */ - if (!external && !priv->cfg->mod_params->restart_fw) { + if (!external && !iwlagn_mod_params.restart_fw) { IWL_DEBUG_INFO(priv, "Cancel firmware reload based on " "module parameter setting\n"); break; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4cdb85d971ce..ca6bd07f4765 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -325,8 +325,6 @@ struct iwl_cfg { u16 eeprom_ver; u16 eeprom_calib_ver; const struct iwl_ops *ops; - /* module based parameters which can be set from modprobe cmd */ - const struct iwl_mod_params *mod_params; /* params not likely to change within a device family */ struct iwl_base_params *base_params; /* params likely to change within a device family */ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index aca9a1d40080..0053e9ea9021 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -433,7 +433,6 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv, struct statistics_tx *tx, unsigned long stamp) { - const struct iwl_mod_params *mod_params = priv->cfg->mod_params; unsigned int msecs; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) @@ -449,13 +448,13 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv, if (msecs < 99) return; - if (mod_params->ack_check && !iwl_good_ack_health(priv, tx)) { + if (iwlagn_mod_params.ack_check && !iwl_good_ack_health(priv, tx)) { IWL_ERR(priv, "low ack count detected, restart firmware\n"); if (!iwl_force_reset(priv, IWL_FW_RESET, false)) return; } - if (mod_params->plcp_check && + if (iwlagn_mod_params.plcp_check && !iwl_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs)) iwl_force_reset(priv, IWL_RF_RESET, false); } @@ -846,7 +845,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, } /* In case of HW accelerated crypto and bad decryption, drop */ - if (!priv->cfg->mod_params->sw_crypto && + if (!iwlagn_mod_params.sw_crypto && iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) return; -- cgit v1.2.3-58-ga151 From 16b80b714f8ef86d47680e4afa0eeb8cc61daef4 Mon Sep 17 00:00:00 2001 From: Don Fry Date: Wed, 20 Apr 2011 15:25:14 -0700 Subject: iwlagn: semaphore and calib cleanup All agn devices use the same eeprom semaphore and calib version routines. Delete the indirection and move the semaphore routines to where they are used and make static. Signed-off-by: Don Fry Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 3 -- drivers/net/wireless/iwlwifi/iwl-2000.c | 3 -- drivers/net/wireless/iwlwifi/iwl-5000.c | 6 ---- drivers/net/wireless/iwlwifi/iwl-6000.c | 10 ++----- drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c | 41 +------------------------ drivers/net/wireless/iwlwifi/iwl-agn.h | 2 -- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 43 +++++++++++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 3 -- 8 files changed, 44 insertions(+), 67 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index d2b1be65f903..4767edfa451d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -197,9 +197,6 @@ static struct iwl_lib_ops iwl1000_lib = { EEPROM_REG_BAND_24_HT40_CHANNELS, EEPROM_REGULATORY_BAND_NO_HT40, }, - .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, - .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, .temp_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 476150f67d29..80137ed5b34a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -280,9 +280,6 @@ static struct iwl_lib_ops iwl2000_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REGULATORY_BAND_NO_HT40, }, - .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, - .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 969c91a2974e..cc25351fb5dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -366,9 +366,6 @@ static struct iwl_lib_ops iwl5000_lib = { EEPROM_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, - .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, .temp_ops = { @@ -413,9 +410,6 @@ static struct iwl_lib_ops iwl5150_lib = { EEPROM_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, - .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, .temp_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 91edb57371e7..f9ef22721312 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -80,7 +80,7 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) static void iwl6050_additional_nic_config(struct iwl_priv *priv) { /* Indicate calibration version to uCode. */ - if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6) + if (iwlagn_eeprom_calib_version(priv) >= 6) iwl_set_bit(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); } @@ -88,7 +88,7 @@ static void iwl6050_additional_nic_config(struct iwl_priv *priv) static void iwl6150_additional_nic_config(struct iwl_priv *priv) { /* Indicate calibration version to uCode. */ - if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6) + if (iwlagn_eeprom_calib_version(priv) >= 6) iwl_set_bit(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); iwl_set_bit(priv, CSR_GP_DRIVER_REG, @@ -305,9 +305,6 @@ static struct iwl_lib_ops iwl6000_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, - .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, @@ -354,9 +351,6 @@ static struct iwl_lib_ops iwl6030_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, - .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c index 3bcaa10f9929..2ef9448b1c20 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -81,52 +81,13 @@ * ******************************************************************************/ -/* - * The device's EEPROM semaphore prevents conflicts between driver and uCode - * when accessing the EEPROM; each access is a series of pulses to/from the - * EEPROM chip, not a single event, so even reads could conflict if they - * weren't arbitrated by the semaphore. - */ -int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv) -{ - u16 count; - int ret; - - for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { - /* Request semaphore */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); - - /* See if we got it */ - ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, - EEPROM_SEM_TIMEOUT); - if (ret >= 0) { - IWL_DEBUG_EEPROM(priv, - "Acquired semaphore after %d tries.\n", - count+1); - return ret; - } - } - - return ret; -} - -void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv) -{ - iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); - -} - int iwl_eeprom_check_version(struct iwl_priv *priv) { u16 eeprom_ver; u16 calib_ver; eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); - calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv); + calib_ver = iwlagn_eeprom_calib_version(priv); if (eeprom_ver < priv->cfg->eeprom_ver || calib_ver < priv->cfg->eeprom_calib_ver) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 9d644d413b40..b477336ff53a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -327,8 +327,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) /* eeprom */ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv); void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); -int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); -void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); /* notification wait support */ void __acquires(wait_entry) diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 1e1a2d8df1da..c8397962632c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -142,6 +142,45 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */ * ******************************************************************************/ +/* + * The device's EEPROM semaphore prevents conflicts between driver and uCode + * when accessing the EEPROM; each access is a series of pulses to/from the + * EEPROM chip, not a single event, so even reads could conflict if they + * weren't arbitrated by the semaphore. + */ +static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv) +{ + u16 count; + int ret; + + for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { + /* Request semaphore */ + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); + + /* See if we got it */ + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, + EEPROM_SEM_TIMEOUT); + if (ret >= 0) { + IWL_DEBUG_EEPROM(priv, + "Acquired semaphore after %d tries.\n", + count+1); + return ret; + } + } + + return ret; +} + +static void iwl_eeprom_release_semaphore(struct iwl_priv *priv) +{ + iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); + +} + static int iwl_eeprom_verify_signature(struct iwl_priv *priv) { u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; @@ -421,7 +460,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) } /* Make sure driver (instead of uCode) is allowed to read EEPROM */ - ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv); + ret = iwl_eeprom_acquire_semaphore(priv); if (ret < 0) { IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n"); ret = -ENOENT; @@ -488,7 +527,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) ret = 0; done: - priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); + iwl_eeprom_release_semaphore(priv); err: if (ret) diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 9ce052573c6a..c960c6fa009b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -294,9 +294,6 @@ extern const u8 iwl_eeprom_band_1[14]; struct iwl_eeprom_ops { const u32 regulatory_bands[7]; - int (*acquire_semaphore) (struct iwl_priv *priv); - void (*release_semaphore) (struct iwl_priv *priv); - u16 (*calib_version) (struct iwl_priv *priv); const u8* (*query_addr) (const struct iwl_priv *priv, size_t offset); void (*update_enhanced_txpower) (struct iwl_priv *priv); }; -- cgit v1.2.3-58-ga151 From bbf18ff1be8a3c6567bc052e690189b55e16b8eb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Apr 2011 07:09:43 -0700 Subject: iwlagn: remove spectrum measurement header This header file isn't used, and if we ever need these definitions they shouldn't be added to a driver but rather to the common 802.11 include file that has all frame definitions. Thus, just remove it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-spectrum.h | 92 ----------------------------- 1 file changed, 92 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-spectrum.h diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/drivers/net/wireless/iwlwifi/iwl-spectrum.h deleted file mode 100644 index cb80bb4ce45e..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.h +++ /dev/null @@ -1,92 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl_spectrum_h__ -#define __iwl_spectrum_h__ -enum { /* ieee80211_basic_report.map */ - IEEE80211_BASIC_MAP_BSS = (1 << 0), - IEEE80211_BASIC_MAP_OFDM = (1 << 1), - IEEE80211_BASIC_MAP_UNIDENTIFIED = (1 << 2), - IEEE80211_BASIC_MAP_RADAR = (1 << 3), - IEEE80211_BASIC_MAP_UNMEASURED = (1 << 4), - /* Bits 5-7 are reserved */ - -}; -struct ieee80211_basic_report { - u8 channel; - __le64 start_time; - __le16 duration; - u8 map; -} __packed; - -enum { /* ieee80211_measurement_request.mode */ - /* Bit 0 is reserved */ - IEEE80211_MEASUREMENT_ENABLE = (1 << 1), - IEEE80211_MEASUREMENT_REQUEST = (1 << 2), - IEEE80211_MEASUREMENT_REPORT = (1 << 3), - /* Bits 4-7 are reserved */ -}; - -enum { - IEEE80211_REPORT_BASIC = 0, /* required */ - IEEE80211_REPORT_CCA = 1, /* optional */ - IEEE80211_REPORT_RPI = 2, /* optional */ - /* 3-255 reserved */ -}; - -struct ieee80211_measurement_params { - u8 channel; - __le64 start_time; - __le16 duration; -} __packed; - -struct ieee80211_info_element { - u8 id; - u8 len; - u8 data[0]; -} __packed; - -struct ieee80211_measurement_request { - struct ieee80211_info_element ie; - u8 token; - u8 mode; - u8 type; - struct ieee80211_measurement_params params[0]; -} __packed; - -struct ieee80211_measurement_report { - struct ieee80211_info_element ie; - u8 token; - u8 mode; - u8 type; - union { - struct ieee80211_basic_report basic[0]; - } u; -} __packed; - -#endif -- cgit v1.2.3-58-ga151 From c914ac26caf462567078f9615ffcedf1962087f2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Apr 2011 10:57:23 -0700 Subject: iwlagn: improve RXON checking The current RXON checking doesn't verify that the channel is valid (or at least non-zero), so add that. Also, add a WARN() so we get a stacktrace, and capture a bitmask of errors in order to capture all necessary information in the warning itself (in case the previous messages are snipped off.) Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.c | 38 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 1b2a7d9141c6..98cfbb6d2369 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -416,72 +416,72 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { struct iwl_rxon_cmd *rxon = &ctx->staging; - bool error = false; + u32 errors = 0; if (rxon->flags & RXON_FLG_BAND_24G_MSK) { if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) { IWL_WARN(priv, "check 2.4G: wrong narrow\n"); - error = true; + errors |= BIT(0); } if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) { IWL_WARN(priv, "check 2.4G: wrong radar\n"); - error = true; + errors |= BIT(1); } } else { if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) { IWL_WARN(priv, "check 5.2G: not short slot!\n"); - error = true; + errors |= BIT(2); } if (rxon->flags & RXON_FLG_CCK_MSK) { IWL_WARN(priv, "check 5.2G: CCK!\n"); - error = true; + errors |= BIT(3); } } if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) { IWL_WARN(priv, "mac/bssid mcast!\n"); - error = true; + errors |= BIT(4); } /* make sure basic rates 6Mbps and 1Mbps are supported */ if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 && (rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) { IWL_WARN(priv, "neither 1 nor 6 are basic\n"); - error = true; + errors |= BIT(5); } if (le16_to_cpu(rxon->assoc_id) > 2007) { IWL_WARN(priv, "aid > 2007\n"); - error = true; + errors |= BIT(6); } if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) { IWL_WARN(priv, "CCK and short slot\n"); - error = true; + errors |= BIT(7); } if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) { IWL_WARN(priv, "CCK and auto detect"); - error = true; + errors |= BIT(8); } if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK) { IWL_WARN(priv, "TGg but no auto-detect\n"); - error = true; + errors |= BIT(9); } - if (error) - IWL_WARN(priv, "Tuning to channel %d\n", - le16_to_cpu(rxon->channel)); - - if (error) { - IWL_ERR(priv, "Invalid RXON\n"); - return -EINVAL; + if (rxon->channel == 0) { + IWL_WARN(priv, "zero channel is invalid\n"); + errors |= BIT(10); } - return 0; + + WARN(errors, "Invalid RXON (%#x), channel %d", + errors, le16_to_cpu(rxon->channel)); + + return errors ? -EINVAL : 0; } /** -- cgit v1.2.3-58-ga151 From ebf8dc8060e4b10e8e13abbf98544f5c6cc8b25e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 27 Apr 2011 05:19:34 -0700 Subject: iwlagn: prefer BSS context If an interface type changes from a type that is only supported on the PAN context (e.g. P2P GO) to a type that is supported on the BSS context, and the BSS context is not in use, then we need to use the BSS context instead of changing the device type within the context. To achieve this, refuse the type change, which causes a down/up cycle that will allocate the BSS context for the interface. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 98cfbb6d2369..4653deada05b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1765,6 +1765,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct iwl_priv *priv = hw->priv; struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); + struct iwl_rxon_context *bss_ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_rxon_context *tmp; u32 interface_modes; int err; @@ -1789,6 +1790,19 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, goto out; } + /* + * Refuse a change that should be done by moving from the PAN + * context to the BSS context instead, if the BSS context is + * available and can support the new interface type. + */ + if (ctx->ctxid == IWL_RXON_CTX_PAN && !bss_ctx->vif && + (bss_ctx->interface_modes & BIT(newtype) || + bss_ctx->exclusive_interface_modes & BIT(newtype))) { + BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); + err = -EBUSY; + goto out; + } + if (ctx->exclusive_interface_modes & BIT(newtype)) { for_each_context(priv, tmp) { if (ctx == tmp) -- cgit v1.2.3-58-ga151 From d6d023a1948d13652d719238f8039c09acceda8c Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 30 Apr 2011 09:10:53 -0700 Subject: iwlagn: remove un-necessary debugfs callback After driver split, no need for debugfs callback, remove those Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/Makefile | 1 - drivers/net/wireless/iwlwifi/iwl-1000.c | 8 - drivers/net/wireless/iwlwifi/iwl-2000.c | 8 - drivers/net/wireless/iwlwifi/iwl-5000.c | 15 - drivers/net/wireless/iwlwifi/iwl-6000.c | 15 - drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c | 1025 ------------------------ drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h | 70 -- drivers/net/wireless/iwlwifi/iwl-core.h | 14 - drivers/net/wireless/iwlwifi/iwl-debugfs.c | 1006 ++++++++++++++++++++++- 9 files changed, 978 insertions(+), 1184 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c delete mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index bb6a737de61f..89a41d320c36 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -14,7 +14,6 @@ iwlagn-objs += iwl-6000.o iwlagn-objs += iwl-1000.o iwlagn-objs += iwl-2000.o -iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 4767edfa451d..3da8cf27dcb9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -45,7 +45,6 @@ #include "iwl-agn.h" #include "iwl-helpers.h" #include "iwl-agn-hw.h" -#include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ #define IWL1000_UCODE_API_MAX 5 @@ -202,13 +201,6 @@ static struct iwl_lib_ops iwl1000_lib = { .temp_ops = { .temperature = iwlagn_temperature, }, - .debugfs_ops = { - .rx_stats_read = iwl_ucode_rx_stats_read, - .tx_stats_read = iwl_ucode_tx_stats_read, - .general_stats_read = iwl_ucode_general_stats_read, - .bt_stats_read = iwl_ucode_bt_stats_read, - .reply_tx_error = iwl_reply_tx_error_read, - }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 80137ed5b34a..bca462c47e37 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -46,7 +46,6 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" -#include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ #define IWL2030_UCODE_API_MAX 5 @@ -286,13 +285,6 @@ static struct iwl_lib_ops iwl2000_lib = { .temp_ops = { .temperature = iwlagn_temperature, }, - .debugfs_ops = { - .rx_stats_read = iwl_ucode_rx_stats_read, - .tx_stats_read = iwl_ucode_tx_stats_read, - .general_stats_read = iwl_ucode_general_stats_read, - .bt_stats_read = iwl_ucode_bt_stats_read, - .reply_tx_error = iwl_reply_tx_error_read, - }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index cc25351fb5dc..561f2cd65dd4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -47,7 +47,6 @@ #include "iwl-agn.h" #include "iwl-agn-hw.h" #include "iwl-5000-hw.h" -#include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ #define IWL5000_UCODE_API_MAX 5 @@ -371,13 +370,6 @@ static struct iwl_lib_ops iwl5000_lib = { .temp_ops = { .temperature = iwlagn_temperature, }, - .debugfs_ops = { - .rx_stats_read = iwl_ucode_rx_stats_read, - .tx_stats_read = iwl_ucode_tx_stats_read, - .general_stats_read = iwl_ucode_general_stats_read, - .bt_stats_read = iwl_ucode_bt_stats_read, - .reply_tx_error = iwl_reply_tx_error_read, - }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, }; @@ -415,13 +407,6 @@ static struct iwl_lib_ops iwl5150_lib = { .temp_ops = { .temperature = iwl5150_temperature, }, - .debugfs_ops = { - .rx_stats_read = iwl_ucode_rx_stats_read, - .tx_stats_read = iwl_ucode_tx_stats_read, - .general_stats_read = iwl_ucode_general_stats_read, - .bt_stats_read = iwl_ucode_bt_stats_read, - .reply_tx_error = iwl_reply_tx_error_read, - }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index f9ef22721312..6045457cc722 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -46,7 +46,6 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" -#include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ #define IWL6000_UCODE_API_MAX 4 @@ -311,13 +310,6 @@ static struct iwl_lib_ops iwl6000_lib = { .temp_ops = { .temperature = iwlagn_temperature, }, - .debugfs_ops = { - .rx_stats_read = iwl_ucode_rx_stats_read, - .tx_stats_read = iwl_ucode_tx_stats_read, - .general_stats_read = iwl_ucode_general_stats_read, - .bt_stats_read = iwl_ucode_bt_stats_read, - .reply_tx_error = iwl_reply_tx_error_read, - }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, }; @@ -357,13 +349,6 @@ static struct iwl_lib_ops iwl6030_lib = { .temp_ops = { .temperature = iwlagn_temperature, }, - .debugfs_ops = { - .rx_stats_read = iwl_ucode_rx_stats_read, - .tx_stats_read = iwl_ucode_tx_stats_read, - .general_stats_read = iwl_ucode_general_stats_read, - .bt_stats_read = iwl_ucode_bt_stats_read, - .reply_tx_error = iwl_reply_tx_error_read, - }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c deleted file mode 100644 index 71a5f31cd7cc..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ /dev/null @@ -1,1025 +0,0 @@ -/****************************************************************************** - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ -#include "iwl-agn.h" -#include "iwl-agn-debugfs.h" - -static const char *fmt_value = " %-30s %10u\n"; -static const char *fmt_hex = " %-30s 0x%02X\n"; -static const char *fmt_table = " %-30s %10u %10u %10u %10u\n"; -static const char *fmt_header = - "%-32s current cumulative delta max\n"; - -static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) -{ - int p = 0; - u32 flag; - - flag = le32_to_cpu(priv->statistics.flag); - - p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag); - if (flag & UCODE_STATISTICS_CLEAR_MSK) - p += scnprintf(buf + p, bufsz - p, - "\tStatistics have been cleared\n"); - p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", - (flag & UCODE_STATISTICS_FREQUENCY_MSK) - ? "2.4 GHz" : "5.2 GHz"); - p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", - (flag & UCODE_STATISTICS_NARROW_BAND_MSK) - ? "enabled" : "disabled"); - - return p; -} - -ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) - { - struct iwl_priv *priv = file->private_data; - int pos = 0; - char *buf; - int bufsz = sizeof(struct statistics_rx_phy) * 40 + - sizeof(struct statistics_rx_non_phy) * 40 + - sizeof(struct statistics_rx_ht_phy) * 40 + 400; - ssize_t ret; - struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; - struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; - struct statistics_rx_non_phy *general, *accum_general; - struct statistics_rx_non_phy *delta_general, *max_general; - struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - /* - * the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - ofdm = &priv->statistics.rx_ofdm; - cck = &priv->statistics.rx_cck; - general = &priv->statistics.rx_non_phy; - ht = &priv->statistics.rx_ofdm_ht; - accum_ofdm = &priv->accum_stats.rx_ofdm; - accum_cck = &priv->accum_stats.rx_cck; - accum_general = &priv->accum_stats.rx_non_phy; - accum_ht = &priv->accum_stats.rx_ofdm_ht; - delta_ofdm = &priv->delta_stats.rx_ofdm; - delta_cck = &priv->delta_stats.rx_cck; - delta_general = &priv->delta_stats.rx_non_phy; - delta_ht = &priv->delta_stats.rx_ofdm_ht; - max_ofdm = &priv->max_delta_stats.rx_ofdm; - max_cck = &priv->max_delta_stats.rx_cck; - max_general = &priv->max_delta_stats.rx_non_phy; - max_ht = &priv->max_delta_stats.rx_ofdm_ht; - - pos += iwl_statistics_flag(priv, buf, bufsz); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_header, "Statistics_Rx - OFDM:"); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "ina_cnt:", - le32_to_cpu(ofdm->ina_cnt), - accum_ofdm->ina_cnt, - delta_ofdm->ina_cnt, max_ofdm->ina_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "fina_cnt:", - le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, - delta_ofdm->fina_cnt, max_ofdm->fina_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "plcp_err:", - le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, - delta_ofdm->plcp_err, max_ofdm->plcp_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "crc32_err:", - le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, - delta_ofdm->crc32_err, max_ofdm->crc32_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "overrun_err:", - le32_to_cpu(ofdm->overrun_err), - accum_ofdm->overrun_err, delta_ofdm->overrun_err, - max_ofdm->overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "early_overrun_err:", - le32_to_cpu(ofdm->early_overrun_err), - accum_ofdm->early_overrun_err, - delta_ofdm->early_overrun_err, - max_ofdm->early_overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "crc32_good:", - le32_to_cpu(ofdm->crc32_good), - accum_ofdm->crc32_good, delta_ofdm->crc32_good, - max_ofdm->crc32_good); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "false_alarm_cnt:", - le32_to_cpu(ofdm->false_alarm_cnt), - accum_ofdm->false_alarm_cnt, - delta_ofdm->false_alarm_cnt, - max_ofdm->false_alarm_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "fina_sync_err_cnt:", - le32_to_cpu(ofdm->fina_sync_err_cnt), - accum_ofdm->fina_sync_err_cnt, - delta_ofdm->fina_sync_err_cnt, - max_ofdm->fina_sync_err_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "sfd_timeout:", - le32_to_cpu(ofdm->sfd_timeout), - accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout, - max_ofdm->sfd_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "fina_timeout:", - le32_to_cpu(ofdm->fina_timeout), - accum_ofdm->fina_timeout, delta_ofdm->fina_timeout, - max_ofdm->fina_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "unresponded_rts:", - le32_to_cpu(ofdm->unresponded_rts), - accum_ofdm->unresponded_rts, - delta_ofdm->unresponded_rts, - max_ofdm->unresponded_rts); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "rxe_frame_lmt_ovrun:", - le32_to_cpu(ofdm->rxe_frame_limit_overrun), - accum_ofdm->rxe_frame_limit_overrun, - delta_ofdm->rxe_frame_limit_overrun, - max_ofdm->rxe_frame_limit_overrun); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "sent_ack_cnt:", - le32_to_cpu(ofdm->sent_ack_cnt), - accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt, - max_ofdm->sent_ack_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "sent_cts_cnt:", - le32_to_cpu(ofdm->sent_cts_cnt), - accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt, - max_ofdm->sent_cts_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "sent_ba_rsp_cnt:", - le32_to_cpu(ofdm->sent_ba_rsp_cnt), - accum_ofdm->sent_ba_rsp_cnt, - delta_ofdm->sent_ba_rsp_cnt, - max_ofdm->sent_ba_rsp_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "dsp_self_kill:", - le32_to_cpu(ofdm->dsp_self_kill), - accum_ofdm->dsp_self_kill, - delta_ofdm->dsp_self_kill, - max_ofdm->dsp_self_kill); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "mh_format_err:", - le32_to_cpu(ofdm->mh_format_err), - accum_ofdm->mh_format_err, - delta_ofdm->mh_format_err, - max_ofdm->mh_format_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "re_acq_main_rssi_sum:", - le32_to_cpu(ofdm->re_acq_main_rssi_sum), - accum_ofdm->re_acq_main_rssi_sum, - delta_ofdm->re_acq_main_rssi_sum, - max_ofdm->re_acq_main_rssi_sum); - - pos += scnprintf(buf + pos, bufsz - pos, - fmt_header, "Statistics_Rx - CCK:"); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "ina_cnt:", - le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, - delta_cck->ina_cnt, max_cck->ina_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "fina_cnt:", - le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, - delta_cck->fina_cnt, max_cck->fina_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "plcp_err:", - le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, - delta_cck->plcp_err, max_cck->plcp_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "crc32_err:", - le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, - delta_cck->crc32_err, max_cck->crc32_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "overrun_err:", - le32_to_cpu(cck->overrun_err), - accum_cck->overrun_err, delta_cck->overrun_err, - max_cck->overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "early_overrun_err:", - le32_to_cpu(cck->early_overrun_err), - accum_cck->early_overrun_err, - delta_cck->early_overrun_err, - max_cck->early_overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "crc32_good:", - le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, - delta_cck->crc32_good, max_cck->crc32_good); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "false_alarm_cnt:", - le32_to_cpu(cck->false_alarm_cnt), - accum_cck->false_alarm_cnt, - delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "fina_sync_err_cnt:", - le32_to_cpu(cck->fina_sync_err_cnt), - accum_cck->fina_sync_err_cnt, - delta_cck->fina_sync_err_cnt, - max_cck->fina_sync_err_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "sfd_timeout:", - le32_to_cpu(cck->sfd_timeout), - accum_cck->sfd_timeout, delta_cck->sfd_timeout, - max_cck->sfd_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "fina_timeout:", - le32_to_cpu(cck->fina_timeout), - accum_cck->fina_timeout, delta_cck->fina_timeout, - max_cck->fina_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "unresponded_rts:", - le32_to_cpu(cck->unresponded_rts), - accum_cck->unresponded_rts, delta_cck->unresponded_rts, - max_cck->unresponded_rts); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "rxe_frame_lmt_ovrun:", - le32_to_cpu(cck->rxe_frame_limit_overrun), - accum_cck->rxe_frame_limit_overrun, - delta_cck->rxe_frame_limit_overrun, - max_cck->rxe_frame_limit_overrun); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "sent_ack_cnt:", - le32_to_cpu(cck->sent_ack_cnt), - accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt, - max_cck->sent_ack_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "sent_cts_cnt:", - le32_to_cpu(cck->sent_cts_cnt), - accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt, - max_cck->sent_cts_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "sent_ba_rsp_cnt:", - le32_to_cpu(cck->sent_ba_rsp_cnt), - accum_cck->sent_ba_rsp_cnt, - delta_cck->sent_ba_rsp_cnt, - max_cck->sent_ba_rsp_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "dsp_self_kill:", - le32_to_cpu(cck->dsp_self_kill), - accum_cck->dsp_self_kill, delta_cck->dsp_self_kill, - max_cck->dsp_self_kill); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "mh_format_err:", - le32_to_cpu(cck->mh_format_err), - accum_cck->mh_format_err, delta_cck->mh_format_err, - max_cck->mh_format_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "re_acq_main_rssi_sum:", - le32_to_cpu(cck->re_acq_main_rssi_sum), - accum_cck->re_acq_main_rssi_sum, - delta_cck->re_acq_main_rssi_sum, - max_cck->re_acq_main_rssi_sum); - - pos += scnprintf(buf + pos, bufsz - pos, - fmt_header, "Statistics_Rx - GENERAL:"); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "bogus_cts:", - le32_to_cpu(general->bogus_cts), - accum_general->bogus_cts, delta_general->bogus_cts, - max_general->bogus_cts); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "bogus_ack:", - le32_to_cpu(general->bogus_ack), - accum_general->bogus_ack, delta_general->bogus_ack, - max_general->bogus_ack); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "non_bssid_frames:", - le32_to_cpu(general->non_bssid_frames), - accum_general->non_bssid_frames, - delta_general->non_bssid_frames, - max_general->non_bssid_frames); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "filtered_frames:", - le32_to_cpu(general->filtered_frames), - accum_general->filtered_frames, - delta_general->filtered_frames, - max_general->filtered_frames); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "non_channel_beacons:", - le32_to_cpu(general->non_channel_beacons), - accum_general->non_channel_beacons, - delta_general->non_channel_beacons, - max_general->non_channel_beacons); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "channel_beacons:", - le32_to_cpu(general->channel_beacons), - accum_general->channel_beacons, - delta_general->channel_beacons, - max_general->channel_beacons); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "num_missed_bcon:", - le32_to_cpu(general->num_missed_bcon), - accum_general->num_missed_bcon, - delta_general->num_missed_bcon, - max_general->num_missed_bcon); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "adc_rx_saturation_time:", - le32_to_cpu(general->adc_rx_saturation_time), - accum_general->adc_rx_saturation_time, - delta_general->adc_rx_saturation_time, - max_general->adc_rx_saturation_time); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "ina_detect_search_tm:", - le32_to_cpu(general->ina_detection_search_time), - accum_general->ina_detection_search_time, - delta_general->ina_detection_search_time, - max_general->ina_detection_search_time); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "beacon_silence_rssi_a:", - le32_to_cpu(general->beacon_silence_rssi_a), - accum_general->beacon_silence_rssi_a, - delta_general->beacon_silence_rssi_a, - max_general->beacon_silence_rssi_a); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "beacon_silence_rssi_b:", - le32_to_cpu(general->beacon_silence_rssi_b), - accum_general->beacon_silence_rssi_b, - delta_general->beacon_silence_rssi_b, - max_general->beacon_silence_rssi_b); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "beacon_silence_rssi_c:", - le32_to_cpu(general->beacon_silence_rssi_c), - accum_general->beacon_silence_rssi_c, - delta_general->beacon_silence_rssi_c, - max_general->beacon_silence_rssi_c); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "interference_data_flag:", - le32_to_cpu(general->interference_data_flag), - accum_general->interference_data_flag, - delta_general->interference_data_flag, - max_general->interference_data_flag); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "channel_load:", - le32_to_cpu(general->channel_load), - accum_general->channel_load, - delta_general->channel_load, - max_general->channel_load); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "dsp_false_alarms:", - le32_to_cpu(general->dsp_false_alarms), - accum_general->dsp_false_alarms, - delta_general->dsp_false_alarms, - max_general->dsp_false_alarms); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "beacon_rssi_a:", - le32_to_cpu(general->beacon_rssi_a), - accum_general->beacon_rssi_a, - delta_general->beacon_rssi_a, - max_general->beacon_rssi_a); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "beacon_rssi_b:", - le32_to_cpu(general->beacon_rssi_b), - accum_general->beacon_rssi_b, - delta_general->beacon_rssi_b, - max_general->beacon_rssi_b); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "beacon_rssi_c:", - le32_to_cpu(general->beacon_rssi_c), - accum_general->beacon_rssi_c, - delta_general->beacon_rssi_c, - max_general->beacon_rssi_c); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "beacon_energy_a:", - le32_to_cpu(general->beacon_energy_a), - accum_general->beacon_energy_a, - delta_general->beacon_energy_a, - max_general->beacon_energy_a); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "beacon_energy_b:", - le32_to_cpu(general->beacon_energy_b), - accum_general->beacon_energy_b, - delta_general->beacon_energy_b, - max_general->beacon_energy_b); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "beacon_energy_c:", - le32_to_cpu(general->beacon_energy_c), - accum_general->beacon_energy_c, - delta_general->beacon_energy_c, - max_general->beacon_energy_c); - - pos += scnprintf(buf + pos, bufsz - pos, - fmt_header, "Statistics_Rx - OFDM_HT:"); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "plcp_err:", - le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, - delta_ht->plcp_err, max_ht->plcp_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "overrun_err:", - le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, - delta_ht->overrun_err, max_ht->overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "early_overrun_err:", - le32_to_cpu(ht->early_overrun_err), - accum_ht->early_overrun_err, - delta_ht->early_overrun_err, - max_ht->early_overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "crc32_good:", - le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, - delta_ht->crc32_good, max_ht->crc32_good); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "crc32_err:", - le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, - delta_ht->crc32_err, max_ht->crc32_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "mh_format_err:", - le32_to_cpu(ht->mh_format_err), - accum_ht->mh_format_err, - delta_ht->mh_format_err, max_ht->mh_format_err); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "agg_crc32_good:", - le32_to_cpu(ht->agg_crc32_good), - accum_ht->agg_crc32_good, - delta_ht->agg_crc32_good, max_ht->agg_crc32_good); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "agg_mpdu_cnt:", - le32_to_cpu(ht->agg_mpdu_cnt), - accum_ht->agg_mpdu_cnt, - delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "agg_cnt:", - le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, - delta_ht->agg_cnt, max_ht->agg_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "unsupport_mcs:", - le32_to_cpu(ht->unsupport_mcs), - accum_ht->unsupport_mcs, - delta_ht->unsupport_mcs, max_ht->unsupport_mcs); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -ssize_t iwl_ucode_tx_stats_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - int pos = 0; - char *buf; - int bufsz = (sizeof(struct statistics_tx) * 48) + 250; - ssize_t ret; - struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - /* the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - tx = &priv->statistics.tx; - accum_tx = &priv->accum_stats.tx; - delta_tx = &priv->delta_stats.tx; - max_tx = &priv->max_delta_stats.tx; - - pos += iwl_statistics_flag(priv, buf, bufsz); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_header, "Statistics_Tx:"); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "preamble:", - le32_to_cpu(tx->preamble_cnt), - accum_tx->preamble_cnt, - delta_tx->preamble_cnt, max_tx->preamble_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "rx_detected_cnt:", - le32_to_cpu(tx->rx_detected_cnt), - accum_tx->rx_detected_cnt, - delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "bt_prio_defer_cnt:", - le32_to_cpu(tx->bt_prio_defer_cnt), - accum_tx->bt_prio_defer_cnt, - delta_tx->bt_prio_defer_cnt, - max_tx->bt_prio_defer_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "bt_prio_kill_cnt:", - le32_to_cpu(tx->bt_prio_kill_cnt), - accum_tx->bt_prio_kill_cnt, - delta_tx->bt_prio_kill_cnt, - max_tx->bt_prio_kill_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "few_bytes_cnt:", - le32_to_cpu(tx->few_bytes_cnt), - accum_tx->few_bytes_cnt, - delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "cts_timeout:", - le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, - delta_tx->cts_timeout, max_tx->cts_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "ack_timeout:", - le32_to_cpu(tx->ack_timeout), - accum_tx->ack_timeout, - delta_tx->ack_timeout, max_tx->ack_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "expected_ack_cnt:", - le32_to_cpu(tx->expected_ack_cnt), - accum_tx->expected_ack_cnt, - delta_tx->expected_ack_cnt, - max_tx->expected_ack_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "actual_ack_cnt:", - le32_to_cpu(tx->actual_ack_cnt), - accum_tx->actual_ack_cnt, - delta_tx->actual_ack_cnt, - max_tx->actual_ack_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "dump_msdu_cnt:", - le32_to_cpu(tx->dump_msdu_cnt), - accum_tx->dump_msdu_cnt, - delta_tx->dump_msdu_cnt, - max_tx->dump_msdu_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "abort_nxt_frame_mismatch:", - le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), - accum_tx->burst_abort_next_frame_mismatch_cnt, - delta_tx->burst_abort_next_frame_mismatch_cnt, - max_tx->burst_abort_next_frame_mismatch_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "abort_missing_nxt_frame:", - le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), - accum_tx->burst_abort_missing_next_frame_cnt, - delta_tx->burst_abort_missing_next_frame_cnt, - max_tx->burst_abort_missing_next_frame_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "cts_timeout_collision:", - le32_to_cpu(tx->cts_timeout_collision), - accum_tx->cts_timeout_collision, - delta_tx->cts_timeout_collision, - max_tx->cts_timeout_collision); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "ack_ba_timeout_collision:", - le32_to_cpu(tx->ack_or_ba_timeout_collision), - accum_tx->ack_or_ba_timeout_collision, - delta_tx->ack_or_ba_timeout_collision, - max_tx->ack_or_ba_timeout_collision); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "agg ba_timeout:", - le32_to_cpu(tx->agg.ba_timeout), - accum_tx->agg.ba_timeout, - delta_tx->agg.ba_timeout, - max_tx->agg.ba_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "agg ba_resched_frames:", - le32_to_cpu(tx->agg.ba_reschedule_frames), - accum_tx->agg.ba_reschedule_frames, - delta_tx->agg.ba_reschedule_frames, - max_tx->agg.ba_reschedule_frames); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "agg scd_query_agg_frame:", - le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), - accum_tx->agg.scd_query_agg_frame_cnt, - delta_tx->agg.scd_query_agg_frame_cnt, - max_tx->agg.scd_query_agg_frame_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "agg scd_query_no_agg:", - le32_to_cpu(tx->agg.scd_query_no_agg), - accum_tx->agg.scd_query_no_agg, - delta_tx->agg.scd_query_no_agg, - max_tx->agg.scd_query_no_agg); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "agg scd_query_agg:", - le32_to_cpu(tx->agg.scd_query_agg), - accum_tx->agg.scd_query_agg, - delta_tx->agg.scd_query_agg, - max_tx->agg.scd_query_agg); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "agg scd_query_mismatch:", - le32_to_cpu(tx->agg.scd_query_mismatch), - accum_tx->agg.scd_query_mismatch, - delta_tx->agg.scd_query_mismatch, - max_tx->agg.scd_query_mismatch); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "agg frame_not_ready:", - le32_to_cpu(tx->agg.frame_not_ready), - accum_tx->agg.frame_not_ready, - delta_tx->agg.frame_not_ready, - max_tx->agg.frame_not_ready); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "agg underrun:", - le32_to_cpu(tx->agg.underrun), - accum_tx->agg.underrun, - delta_tx->agg.underrun, max_tx->agg.underrun); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "agg bt_prio_kill:", - le32_to_cpu(tx->agg.bt_prio_kill), - accum_tx->agg.bt_prio_kill, - delta_tx->agg.bt_prio_kill, - max_tx->agg.bt_prio_kill); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "agg rx_ba_rsp_cnt:", - le32_to_cpu(tx->agg.rx_ba_rsp_cnt), - accum_tx->agg.rx_ba_rsp_cnt, - delta_tx->agg.rx_ba_rsp_cnt, - max_tx->agg.rx_ba_rsp_cnt); - - if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { - pos += scnprintf(buf + pos, bufsz - pos, - "tx power: (1/2 dB step)\n"); - if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a) - pos += scnprintf(buf + pos, bufsz - pos, - fmt_hex, "antenna A:", - tx->tx_power.ant_a); - if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b) - pos += scnprintf(buf + pos, bufsz - pos, - fmt_hex, "antenna B:", - tx->tx_power.ant_b); - if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c) - pos += scnprintf(buf + pos, bufsz - pos, - fmt_hex, "antenna C:", - tx->tx_power.ant_c); - } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - int pos = 0; - char *buf; - int bufsz = sizeof(struct statistics_general) * 10 + 300; - ssize_t ret; - struct statistics_general_common *general, *accum_general; - struct statistics_general_common *delta_general, *max_general; - struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; - struct statistics_div *div, *accum_div, *delta_div, *max_div; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - /* the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - general = &priv->statistics.common; - dbg = &priv->statistics.common.dbg; - div = &priv->statistics.common.div; - accum_general = &priv->accum_stats.common; - accum_dbg = &priv->accum_stats.common.dbg; - accum_div = &priv->accum_stats.common.div; - delta_general = &priv->delta_stats.common; - max_general = &priv->max_delta_stats.common; - delta_dbg = &priv->delta_stats.common.dbg; - max_dbg = &priv->max_delta_stats.common.dbg; - delta_div = &priv->delta_stats.common.div; - max_div = &priv->max_delta_stats.common.div; - - pos += iwl_statistics_flag(priv, buf, bufsz); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_header, "Statistics_General:"); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_value, "temperature:", - le32_to_cpu(general->temperature)); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_value, "temperature_m:", - le32_to_cpu(general->temperature_m)); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_value, "ttl_timestamp:", - le32_to_cpu(general->ttl_timestamp)); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "burst_check:", - le32_to_cpu(dbg->burst_check), - accum_dbg->burst_check, - delta_dbg->burst_check, max_dbg->burst_check); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "burst_count:", - le32_to_cpu(dbg->burst_count), - accum_dbg->burst_count, - delta_dbg->burst_count, max_dbg->burst_count); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "wait_for_silence_timeout_count:", - le32_to_cpu(dbg->wait_for_silence_timeout_cnt), - accum_dbg->wait_for_silence_timeout_cnt, - delta_dbg->wait_for_silence_timeout_cnt, - max_dbg->wait_for_silence_timeout_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "sleep_time:", - le32_to_cpu(general->sleep_time), - accum_general->sleep_time, - delta_general->sleep_time, max_general->sleep_time); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "slots_out:", - le32_to_cpu(general->slots_out), - accum_general->slots_out, - delta_general->slots_out, max_general->slots_out); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "slots_idle:", - le32_to_cpu(general->slots_idle), - accum_general->slots_idle, - delta_general->slots_idle, max_general->slots_idle); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "tx_on_a:", - le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, - delta_div->tx_on_a, max_div->tx_on_a); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "tx_on_b:", - le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, - delta_div->tx_on_b, max_div->tx_on_b); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "exec_time:", - le32_to_cpu(div->exec_time), accum_div->exec_time, - delta_div->exec_time, max_div->exec_time); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "probe_time:", - le32_to_cpu(div->probe_time), accum_div->probe_time, - delta_div->probe_time, max_div->probe_time); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "rx_enable_counter:", - le32_to_cpu(general->rx_enable_counter), - accum_general->rx_enable_counter, - delta_general->rx_enable_counter, - max_general->rx_enable_counter); - pos += scnprintf(buf + pos, bufsz - pos, - fmt_table, "num_of_sos_states:", - le32_to_cpu(general->num_of_sos_states), - accum_general->num_of_sos_states, - delta_general->num_of_sos_states, - max_general->num_of_sos_states); - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -ssize_t iwl_ucode_bt_stats_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - int pos = 0; - char *buf; - int bufsz = (sizeof(struct statistics_bt_activity) * 24) + 200; - ssize_t ret; - struct statistics_bt_activity *bt, *accum_bt; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - if (!priv->bt_enable_flag) - return -EINVAL; - - /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->mutex); - ret = iwl_send_statistics_request(priv, CMD_SYNC, false); - mutex_unlock(&priv->mutex); - - if (ret) { - IWL_ERR(priv, - "Error sending statistics request: %zd\n", ret); - return -EAGAIN; - } - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - /* - * the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - bt = &priv->statistics.bt_activity; - accum_bt = &priv->accum_stats.bt_activity; - - pos += iwl_statistics_flag(priv, buf, bufsz); - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "\t\t\tcurrent\t\t\taccumulative\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "hi_priority_tx_req_cnt:\t\t%u\t\t\t%u\n", - le32_to_cpu(bt->hi_priority_tx_req_cnt), - accum_bt->hi_priority_tx_req_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "hi_priority_tx_denied_cnt:\t%u\t\t\t%u\n", - le32_to_cpu(bt->hi_priority_tx_denied_cnt), - accum_bt->hi_priority_tx_denied_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "lo_priority_tx_req_cnt:\t\t%u\t\t\t%u\n", - le32_to_cpu(bt->lo_priority_tx_req_cnt), - accum_bt->lo_priority_tx_req_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "lo_priority_tx_denied_cnt:\t%u\t\t\t%u\n", - le32_to_cpu(bt->lo_priority_tx_denied_cnt), - accum_bt->lo_priority_tx_denied_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "hi_priority_rx_req_cnt:\t\t%u\t\t\t%u\n", - le32_to_cpu(bt->hi_priority_rx_req_cnt), - accum_bt->hi_priority_rx_req_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "hi_priority_rx_denied_cnt:\t%u\t\t\t%u\n", - le32_to_cpu(bt->hi_priority_rx_denied_cnt), - accum_bt->hi_priority_rx_denied_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "lo_priority_rx_req_cnt:\t\t%u\t\t\t%u\n", - le32_to_cpu(bt->lo_priority_rx_req_cnt), - accum_bt->lo_priority_rx_req_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n", - le32_to_cpu(bt->lo_priority_rx_denied_cnt), - accum_bt->lo_priority_rx_denied_cnt); - - pos += scnprintf(buf + pos, bufsz - pos, - "(rx)num_bt_kills:\t\t%u\t\t\t%u\n", - le32_to_cpu(priv->statistics.num_bt_kills), - priv->statistics.accum_num_bt_kills); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -ssize_t iwl_reply_tx_error_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - int pos = 0; - char *buf; - int bufsz = (sizeof(struct reply_tx_error_statistics) * 24) + - (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200; - ssize_t ret; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n"); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY), - priv->_agn.reply_tx_stats.pp_delay); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES), - priv->_agn.reply_tx_stats.pp_few_bytes); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO), - priv->_agn.reply_tx_stats.pp_bt_prio); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD), - priv->_agn.reply_tx_stats.pp_quiet_period); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK), - priv->_agn.reply_tx_stats.pp_calc_ttak); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", - iwl_get_tx_fail_reason( - TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY), - priv->_agn.reply_tx_stats.int_crossed_retry); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT), - priv->_agn.reply_tx_stats.short_limit); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT), - priv->_agn.reply_tx_stats.long_limit); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN), - priv->_agn.reply_tx_stats.fifo_underrun); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW), - priv->_agn.reply_tx_stats.drain_flow); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH), - priv->_agn.reply_tx_stats.rfkill_flush); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE), - priv->_agn.reply_tx_stats.life_expire); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS), - priv->_agn.reply_tx_stats.dest_ps); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED), - priv->_agn.reply_tx_stats.host_abort); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY), - priv->_agn.reply_tx_stats.pp_delay); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID), - priv->_agn.reply_tx_stats.sta_invalid); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED), - priv->_agn.reply_tx_stats.frag_drop); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE), - priv->_agn.reply_tx_stats.tid_disable); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED), - priv->_agn.reply_tx_stats.fifo_flush); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", - iwl_get_tx_fail_reason( - TX_STATUS_FAIL_INSUFFICIENT_CF_POLL), - priv->_agn.reply_tx_stats.insuff_cf_poll); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX), - priv->_agn.reply_tx_stats.fail_hw_drop); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", - iwl_get_tx_fail_reason( - TX_STATUS_FAIL_NO_BEACON_ON_RADAR), - priv->_agn.reply_tx_stats.sta_color_mismatch); - pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", - priv->_agn.reply_tx_stats.unknown); - - pos += scnprintf(buf + pos, bufsz - pos, - "\nStatistics_Agg_TX_Error:\n"); - - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK), - priv->_agn.reply_agg_tx_stats.underrun); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK), - priv->_agn.reply_agg_tx_stats.bt_prio); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK), - priv->_agn.reply_agg_tx_stats.few_bytes); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK), - priv->_agn.reply_agg_tx_stats.abort); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", - iwl_get_agg_tx_fail_reason( - AGG_TX_STATE_LAST_SENT_TTL_MSK), - priv->_agn.reply_agg_tx_stats.last_sent_ttl); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", - iwl_get_agg_tx_fail_reason( - AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK), - priv->_agn.reply_agg_tx_stats.last_sent_try); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", - iwl_get_agg_tx_fail_reason( - AGG_TX_STATE_LAST_SENT_BT_KILL_MSK), - priv->_agn.reply_agg_tx_stats.last_sent_bt_kill); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK), - priv->_agn.reply_agg_tx_stats.scd_query); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", - iwl_get_agg_tx_fail_reason( - AGG_TX_STATE_TEST_BAD_CRC32_MSK), - priv->_agn.reply_agg_tx_stats.bad_crc32); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK), - priv->_agn.reply_agg_tx_stats.response); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK), - priv->_agn.reply_agg_tx_stats.dump_tx); - pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", - iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK), - priv->_agn.reply_agg_tx_stats.delay_tx); - pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", - priv->_agn.reply_agg_tx_stats.unknown); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h deleted file mode 100644 index 9a3f329e508f..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h +++ /dev/null @@ -1,70 +0,0 @@ -/****************************************************************************** - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ - -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-debug.h" - -#ifdef CONFIG_IWLWIFI_DEBUGFS -ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos); -ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos); -ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos); -ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos); -ssize_t iwl_reply_tx_error_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos); -#else -static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - return 0; -} -static ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - return 0; -} -static ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - return 0; -} -static ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - return 0; -} -static ssize_t iwl_reply_tx_error_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - return 0; -} -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index ca6bd07f4765..dec9820753f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -121,19 +121,6 @@ struct iwl_apm_ops { void (*config)(struct iwl_priv *priv); }; -struct iwl_debugfs_ops { - ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos); - ssize_t (*tx_stats_read)(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos); - ssize_t (*general_stats_read)(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos); - ssize_t (*bt_stats_read)(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos); - ssize_t (*reply_tx_error)(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos); -}; - struct iwl_temp_ops { void (*temperature)(struct iwl_priv *priv); }; @@ -182,7 +169,6 @@ struct iwl_lib_ops { int (*txfifo_flush)(struct iwl_priv *priv, u16 flush_control); void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control); - struct iwl_debugfs_ops debugfs_ops; }; /* NIC specific ops */ diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 7bd4f5af5b0d..0e6a04b739ad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -39,6 +39,7 @@ #include "iwl-debug.h" #include "iwl-core.h" #include "iwl-io.h" +#include "iwl-agn.h" /* create and remove of files */ #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ @@ -1037,13 +1038,463 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } +static const char *fmt_value = " %-30s %10u\n"; +static const char *fmt_hex = " %-30s 0x%02X\n"; +static const char *fmt_table = " %-30s %10u %10u %10u %10u\n"; +static const char *fmt_header = + "%-32s current cumulative delta max\n"; + +static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) +{ + int p = 0; + u32 flag; + + flag = le32_to_cpu(priv->statistics.flag); + + p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag); + if (flag & UCODE_STATISTICS_CLEAR_MSK) + p += scnprintf(buf + p, bufsz - p, + "\tStatistics have been cleared\n"); + p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", + (flag & UCODE_STATISTICS_FREQUENCY_MSK) + ? "2.4 GHz" : "5.2 GHz"); + p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", + (flag & UCODE_STATISTICS_NARROW_BAND_MSK) + ? "enabled" : "disabled"); + + return p; +} + static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; - return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file, - user_buf, count, ppos); + int pos = 0; + char *buf; + int bufsz = sizeof(struct statistics_rx_phy) * 40 + + sizeof(struct statistics_rx_non_phy) * 40 + + sizeof(struct statistics_rx_ht_phy) * 40 + 400; + ssize_t ret; + struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; + struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; + struct statistics_rx_non_phy *general, *accum_general; + struct statistics_rx_non_phy *delta_general, *max_general; + struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + /* + * the statistic information display here is based on + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + ofdm = &priv->statistics.rx_ofdm; + cck = &priv->statistics.rx_cck; + general = &priv->statistics.rx_non_phy; + ht = &priv->statistics.rx_ofdm_ht; + accum_ofdm = &priv->accum_stats.rx_ofdm; + accum_cck = &priv->accum_stats.rx_cck; + accum_general = &priv->accum_stats.rx_non_phy; + accum_ht = &priv->accum_stats.rx_ofdm_ht; + delta_ofdm = &priv->delta_stats.rx_ofdm; + delta_cck = &priv->delta_stats.rx_cck; + delta_general = &priv->delta_stats.rx_non_phy; + delta_ht = &priv->delta_stats.rx_ofdm_ht; + max_ofdm = &priv->max_delta_stats.rx_ofdm; + max_cck = &priv->max_delta_stats.rx_cck; + max_general = &priv->max_delta_stats.rx_non_phy; + max_ht = &priv->max_delta_stats.rx_ofdm_ht; + + pos += iwl_statistics_flag(priv, buf, bufsz); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_header, "Statistics_Rx - OFDM:"); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "ina_cnt:", + le32_to_cpu(ofdm->ina_cnt), + accum_ofdm->ina_cnt, + delta_ofdm->ina_cnt, max_ofdm->ina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "fina_cnt:", + le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, + delta_ofdm->fina_cnt, max_ofdm->fina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "plcp_err:", + le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, + delta_ofdm->plcp_err, max_ofdm->plcp_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "crc32_err:", + le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, + delta_ofdm->crc32_err, max_ofdm->crc32_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "overrun_err:", + le32_to_cpu(ofdm->overrun_err), + accum_ofdm->overrun_err, delta_ofdm->overrun_err, + max_ofdm->overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "early_overrun_err:", + le32_to_cpu(ofdm->early_overrun_err), + accum_ofdm->early_overrun_err, + delta_ofdm->early_overrun_err, + max_ofdm->early_overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "crc32_good:", + le32_to_cpu(ofdm->crc32_good), + accum_ofdm->crc32_good, delta_ofdm->crc32_good, + max_ofdm->crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "false_alarm_cnt:", + le32_to_cpu(ofdm->false_alarm_cnt), + accum_ofdm->false_alarm_cnt, + delta_ofdm->false_alarm_cnt, + max_ofdm->false_alarm_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "fina_sync_err_cnt:", + le32_to_cpu(ofdm->fina_sync_err_cnt), + accum_ofdm->fina_sync_err_cnt, + delta_ofdm->fina_sync_err_cnt, + max_ofdm->fina_sync_err_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "sfd_timeout:", + le32_to_cpu(ofdm->sfd_timeout), + accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout, + max_ofdm->sfd_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "fina_timeout:", + le32_to_cpu(ofdm->fina_timeout), + accum_ofdm->fina_timeout, delta_ofdm->fina_timeout, + max_ofdm->fina_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "unresponded_rts:", + le32_to_cpu(ofdm->unresponded_rts), + accum_ofdm->unresponded_rts, + delta_ofdm->unresponded_rts, + max_ofdm->unresponded_rts); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "rxe_frame_lmt_ovrun:", + le32_to_cpu(ofdm->rxe_frame_limit_overrun), + accum_ofdm->rxe_frame_limit_overrun, + delta_ofdm->rxe_frame_limit_overrun, + max_ofdm->rxe_frame_limit_overrun); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "sent_ack_cnt:", + le32_to_cpu(ofdm->sent_ack_cnt), + accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt, + max_ofdm->sent_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "sent_cts_cnt:", + le32_to_cpu(ofdm->sent_cts_cnt), + accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt, + max_ofdm->sent_cts_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "sent_ba_rsp_cnt:", + le32_to_cpu(ofdm->sent_ba_rsp_cnt), + accum_ofdm->sent_ba_rsp_cnt, + delta_ofdm->sent_ba_rsp_cnt, + max_ofdm->sent_ba_rsp_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "dsp_self_kill:", + le32_to_cpu(ofdm->dsp_self_kill), + accum_ofdm->dsp_self_kill, + delta_ofdm->dsp_self_kill, + max_ofdm->dsp_self_kill); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "mh_format_err:", + le32_to_cpu(ofdm->mh_format_err), + accum_ofdm->mh_format_err, + delta_ofdm->mh_format_err, + max_ofdm->mh_format_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "re_acq_main_rssi_sum:", + le32_to_cpu(ofdm->re_acq_main_rssi_sum), + accum_ofdm->re_acq_main_rssi_sum, + delta_ofdm->re_acq_main_rssi_sum, + max_ofdm->re_acq_main_rssi_sum); + + pos += scnprintf(buf + pos, bufsz - pos, + fmt_header, "Statistics_Rx - CCK:"); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "ina_cnt:", + le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, + delta_cck->ina_cnt, max_cck->ina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "fina_cnt:", + le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, + delta_cck->fina_cnt, max_cck->fina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "plcp_err:", + le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, + delta_cck->plcp_err, max_cck->plcp_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "crc32_err:", + le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, + delta_cck->crc32_err, max_cck->crc32_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "overrun_err:", + le32_to_cpu(cck->overrun_err), + accum_cck->overrun_err, delta_cck->overrun_err, + max_cck->overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "early_overrun_err:", + le32_to_cpu(cck->early_overrun_err), + accum_cck->early_overrun_err, + delta_cck->early_overrun_err, + max_cck->early_overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "crc32_good:", + le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, + delta_cck->crc32_good, max_cck->crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "false_alarm_cnt:", + le32_to_cpu(cck->false_alarm_cnt), + accum_cck->false_alarm_cnt, + delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "fina_sync_err_cnt:", + le32_to_cpu(cck->fina_sync_err_cnt), + accum_cck->fina_sync_err_cnt, + delta_cck->fina_sync_err_cnt, + max_cck->fina_sync_err_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "sfd_timeout:", + le32_to_cpu(cck->sfd_timeout), + accum_cck->sfd_timeout, delta_cck->sfd_timeout, + max_cck->sfd_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "fina_timeout:", + le32_to_cpu(cck->fina_timeout), + accum_cck->fina_timeout, delta_cck->fina_timeout, + max_cck->fina_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "unresponded_rts:", + le32_to_cpu(cck->unresponded_rts), + accum_cck->unresponded_rts, delta_cck->unresponded_rts, + max_cck->unresponded_rts); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "rxe_frame_lmt_ovrun:", + le32_to_cpu(cck->rxe_frame_limit_overrun), + accum_cck->rxe_frame_limit_overrun, + delta_cck->rxe_frame_limit_overrun, + max_cck->rxe_frame_limit_overrun); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "sent_ack_cnt:", + le32_to_cpu(cck->sent_ack_cnt), + accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt, + max_cck->sent_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "sent_cts_cnt:", + le32_to_cpu(cck->sent_cts_cnt), + accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt, + max_cck->sent_cts_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "sent_ba_rsp_cnt:", + le32_to_cpu(cck->sent_ba_rsp_cnt), + accum_cck->sent_ba_rsp_cnt, + delta_cck->sent_ba_rsp_cnt, + max_cck->sent_ba_rsp_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "dsp_self_kill:", + le32_to_cpu(cck->dsp_self_kill), + accum_cck->dsp_self_kill, delta_cck->dsp_self_kill, + max_cck->dsp_self_kill); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "mh_format_err:", + le32_to_cpu(cck->mh_format_err), + accum_cck->mh_format_err, delta_cck->mh_format_err, + max_cck->mh_format_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "re_acq_main_rssi_sum:", + le32_to_cpu(cck->re_acq_main_rssi_sum), + accum_cck->re_acq_main_rssi_sum, + delta_cck->re_acq_main_rssi_sum, + max_cck->re_acq_main_rssi_sum); + + pos += scnprintf(buf + pos, bufsz - pos, + fmt_header, "Statistics_Rx - GENERAL:"); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "bogus_cts:", + le32_to_cpu(general->bogus_cts), + accum_general->bogus_cts, delta_general->bogus_cts, + max_general->bogus_cts); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "bogus_ack:", + le32_to_cpu(general->bogus_ack), + accum_general->bogus_ack, delta_general->bogus_ack, + max_general->bogus_ack); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "non_bssid_frames:", + le32_to_cpu(general->non_bssid_frames), + accum_general->non_bssid_frames, + delta_general->non_bssid_frames, + max_general->non_bssid_frames); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "filtered_frames:", + le32_to_cpu(general->filtered_frames), + accum_general->filtered_frames, + delta_general->filtered_frames, + max_general->filtered_frames); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "non_channel_beacons:", + le32_to_cpu(general->non_channel_beacons), + accum_general->non_channel_beacons, + delta_general->non_channel_beacons, + max_general->non_channel_beacons); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "channel_beacons:", + le32_to_cpu(general->channel_beacons), + accum_general->channel_beacons, + delta_general->channel_beacons, + max_general->channel_beacons); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "num_missed_bcon:", + le32_to_cpu(general->num_missed_bcon), + accum_general->num_missed_bcon, + delta_general->num_missed_bcon, + max_general->num_missed_bcon); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "adc_rx_saturation_time:", + le32_to_cpu(general->adc_rx_saturation_time), + accum_general->adc_rx_saturation_time, + delta_general->adc_rx_saturation_time, + max_general->adc_rx_saturation_time); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "ina_detect_search_tm:", + le32_to_cpu(general->ina_detection_search_time), + accum_general->ina_detection_search_time, + delta_general->ina_detection_search_time, + max_general->ina_detection_search_time); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "beacon_silence_rssi_a:", + le32_to_cpu(general->beacon_silence_rssi_a), + accum_general->beacon_silence_rssi_a, + delta_general->beacon_silence_rssi_a, + max_general->beacon_silence_rssi_a); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "beacon_silence_rssi_b:", + le32_to_cpu(general->beacon_silence_rssi_b), + accum_general->beacon_silence_rssi_b, + delta_general->beacon_silence_rssi_b, + max_general->beacon_silence_rssi_b); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "beacon_silence_rssi_c:", + le32_to_cpu(general->beacon_silence_rssi_c), + accum_general->beacon_silence_rssi_c, + delta_general->beacon_silence_rssi_c, + max_general->beacon_silence_rssi_c); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "interference_data_flag:", + le32_to_cpu(general->interference_data_flag), + accum_general->interference_data_flag, + delta_general->interference_data_flag, + max_general->interference_data_flag); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "channel_load:", + le32_to_cpu(general->channel_load), + accum_general->channel_load, + delta_general->channel_load, + max_general->channel_load); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "dsp_false_alarms:", + le32_to_cpu(general->dsp_false_alarms), + accum_general->dsp_false_alarms, + delta_general->dsp_false_alarms, + max_general->dsp_false_alarms); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "beacon_rssi_a:", + le32_to_cpu(general->beacon_rssi_a), + accum_general->beacon_rssi_a, + delta_general->beacon_rssi_a, + max_general->beacon_rssi_a); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "beacon_rssi_b:", + le32_to_cpu(general->beacon_rssi_b), + accum_general->beacon_rssi_b, + delta_general->beacon_rssi_b, + max_general->beacon_rssi_b); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "beacon_rssi_c:", + le32_to_cpu(general->beacon_rssi_c), + accum_general->beacon_rssi_c, + delta_general->beacon_rssi_c, + max_general->beacon_rssi_c); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "beacon_energy_a:", + le32_to_cpu(general->beacon_energy_a), + accum_general->beacon_energy_a, + delta_general->beacon_energy_a, + max_general->beacon_energy_a); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "beacon_energy_b:", + le32_to_cpu(general->beacon_energy_b), + accum_general->beacon_energy_b, + delta_general->beacon_energy_b, + max_general->beacon_energy_b); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "beacon_energy_c:", + le32_to_cpu(general->beacon_energy_c), + accum_general->beacon_energy_c, + delta_general->beacon_energy_c, + max_general->beacon_energy_c); + + pos += scnprintf(buf + pos, bufsz - pos, + fmt_header, "Statistics_Rx - OFDM_HT:"); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "plcp_err:", + le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, + delta_ht->plcp_err, max_ht->plcp_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "overrun_err:", + le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, + delta_ht->overrun_err, max_ht->overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "early_overrun_err:", + le32_to_cpu(ht->early_overrun_err), + accum_ht->early_overrun_err, + delta_ht->early_overrun_err, + max_ht->early_overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "crc32_good:", + le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, + delta_ht->crc32_good, max_ht->crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "crc32_err:", + le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, + delta_ht->crc32_err, max_ht->crc32_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "mh_format_err:", + le32_to_cpu(ht->mh_format_err), + accum_ht->mh_format_err, + delta_ht->mh_format_err, max_ht->mh_format_err); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "agg_crc32_good:", + le32_to_cpu(ht->agg_crc32_good), + accum_ht->agg_crc32_good, + delta_ht->agg_crc32_good, max_ht->agg_crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "agg_mpdu_cnt:", + le32_to_cpu(ht->agg_mpdu_cnt), + accum_ht->agg_mpdu_cnt, + delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "agg_cnt:", + le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, + delta_ht->agg_cnt, max_ht->agg_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "unsupport_mcs:", + le32_to_cpu(ht->unsupport_mcs), + accum_ht->unsupport_mcs, + delta_ht->unsupport_mcs, max_ht->unsupport_mcs); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; } static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, @@ -1051,8 +1502,190 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; - return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file, - user_buf, count, ppos); + int pos = 0; + char *buf; + int bufsz = (sizeof(struct statistics_tx) * 48) + 250; + ssize_t ret; + struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + /* the statistic information display here is based on + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + tx = &priv->statistics.tx; + accum_tx = &priv->accum_stats.tx; + delta_tx = &priv->delta_stats.tx; + max_tx = &priv->max_delta_stats.tx; + + pos += iwl_statistics_flag(priv, buf, bufsz); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_header, "Statistics_Tx:"); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "preamble:", + le32_to_cpu(tx->preamble_cnt), + accum_tx->preamble_cnt, + delta_tx->preamble_cnt, max_tx->preamble_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "rx_detected_cnt:", + le32_to_cpu(tx->rx_detected_cnt), + accum_tx->rx_detected_cnt, + delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "bt_prio_defer_cnt:", + le32_to_cpu(tx->bt_prio_defer_cnt), + accum_tx->bt_prio_defer_cnt, + delta_tx->bt_prio_defer_cnt, + max_tx->bt_prio_defer_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "bt_prio_kill_cnt:", + le32_to_cpu(tx->bt_prio_kill_cnt), + accum_tx->bt_prio_kill_cnt, + delta_tx->bt_prio_kill_cnt, + max_tx->bt_prio_kill_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "few_bytes_cnt:", + le32_to_cpu(tx->few_bytes_cnt), + accum_tx->few_bytes_cnt, + delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "cts_timeout:", + le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, + delta_tx->cts_timeout, max_tx->cts_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "ack_timeout:", + le32_to_cpu(tx->ack_timeout), + accum_tx->ack_timeout, + delta_tx->ack_timeout, max_tx->ack_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "expected_ack_cnt:", + le32_to_cpu(tx->expected_ack_cnt), + accum_tx->expected_ack_cnt, + delta_tx->expected_ack_cnt, + max_tx->expected_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "actual_ack_cnt:", + le32_to_cpu(tx->actual_ack_cnt), + accum_tx->actual_ack_cnt, + delta_tx->actual_ack_cnt, + max_tx->actual_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "dump_msdu_cnt:", + le32_to_cpu(tx->dump_msdu_cnt), + accum_tx->dump_msdu_cnt, + delta_tx->dump_msdu_cnt, + max_tx->dump_msdu_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "abort_nxt_frame_mismatch:", + le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), + accum_tx->burst_abort_next_frame_mismatch_cnt, + delta_tx->burst_abort_next_frame_mismatch_cnt, + max_tx->burst_abort_next_frame_mismatch_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "abort_missing_nxt_frame:", + le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), + accum_tx->burst_abort_missing_next_frame_cnt, + delta_tx->burst_abort_missing_next_frame_cnt, + max_tx->burst_abort_missing_next_frame_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "cts_timeout_collision:", + le32_to_cpu(tx->cts_timeout_collision), + accum_tx->cts_timeout_collision, + delta_tx->cts_timeout_collision, + max_tx->cts_timeout_collision); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "ack_ba_timeout_collision:", + le32_to_cpu(tx->ack_or_ba_timeout_collision), + accum_tx->ack_or_ba_timeout_collision, + delta_tx->ack_or_ba_timeout_collision, + max_tx->ack_or_ba_timeout_collision); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "agg ba_timeout:", + le32_to_cpu(tx->agg.ba_timeout), + accum_tx->agg.ba_timeout, + delta_tx->agg.ba_timeout, + max_tx->agg.ba_timeout); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "agg ba_resched_frames:", + le32_to_cpu(tx->agg.ba_reschedule_frames), + accum_tx->agg.ba_reschedule_frames, + delta_tx->agg.ba_reschedule_frames, + max_tx->agg.ba_reschedule_frames); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "agg scd_query_agg_frame:", + le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), + accum_tx->agg.scd_query_agg_frame_cnt, + delta_tx->agg.scd_query_agg_frame_cnt, + max_tx->agg.scd_query_agg_frame_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "agg scd_query_no_agg:", + le32_to_cpu(tx->agg.scd_query_no_agg), + accum_tx->agg.scd_query_no_agg, + delta_tx->agg.scd_query_no_agg, + max_tx->agg.scd_query_no_agg); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "agg scd_query_agg:", + le32_to_cpu(tx->agg.scd_query_agg), + accum_tx->agg.scd_query_agg, + delta_tx->agg.scd_query_agg, + max_tx->agg.scd_query_agg); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "agg scd_query_mismatch:", + le32_to_cpu(tx->agg.scd_query_mismatch), + accum_tx->agg.scd_query_mismatch, + delta_tx->agg.scd_query_mismatch, + max_tx->agg.scd_query_mismatch); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "agg frame_not_ready:", + le32_to_cpu(tx->agg.frame_not_ready), + accum_tx->agg.frame_not_ready, + delta_tx->agg.frame_not_ready, + max_tx->agg.frame_not_ready); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "agg underrun:", + le32_to_cpu(tx->agg.underrun), + accum_tx->agg.underrun, + delta_tx->agg.underrun, max_tx->agg.underrun); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "agg bt_prio_kill:", + le32_to_cpu(tx->agg.bt_prio_kill), + accum_tx->agg.bt_prio_kill, + delta_tx->agg.bt_prio_kill, + max_tx->agg.bt_prio_kill); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "agg rx_ba_rsp_cnt:", + le32_to_cpu(tx->agg.rx_ba_rsp_cnt), + accum_tx->agg.rx_ba_rsp_cnt, + delta_tx->agg.rx_ba_rsp_cnt, + max_tx->agg.rx_ba_rsp_cnt); + + if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { + pos += scnprintf(buf + pos, bufsz - pos, + "tx power: (1/2 dB step)\n"); + if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a) + pos += scnprintf(buf + pos, bufsz - pos, + fmt_hex, "antenna A:", + tx->tx_power.ant_a); + if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b) + pos += scnprintf(buf + pos, bufsz - pos, + fmt_hex, "antenna B:", + tx->tx_power.ant_b); + if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c) + pos += scnprintf(buf + pos, bufsz - pos, + fmt_hex, "antenna C:", + tx->tx_power.ant_c); + } + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; } static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, @@ -1060,8 +1693,347 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; - return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file, - user_buf, count, ppos); + int pos = 0; + char *buf; + int bufsz = sizeof(struct statistics_general) * 10 + 300; + ssize_t ret; + struct statistics_general_common *general, *accum_general; + struct statistics_general_common *delta_general, *max_general; + struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; + struct statistics_div *div, *accum_div, *delta_div, *max_div; + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + /* the statistic information display here is based on + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + general = &priv->statistics.common; + dbg = &priv->statistics.common.dbg; + div = &priv->statistics.common.div; + accum_general = &priv->accum_stats.common; + accum_dbg = &priv->accum_stats.common.dbg; + accum_div = &priv->accum_stats.common.div; + delta_general = &priv->delta_stats.common; + max_general = &priv->max_delta_stats.common; + delta_dbg = &priv->delta_stats.common.dbg; + max_dbg = &priv->max_delta_stats.common.dbg; + delta_div = &priv->delta_stats.common.div; + max_div = &priv->max_delta_stats.common.div; + + pos += iwl_statistics_flag(priv, buf, bufsz); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_header, "Statistics_General:"); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_value, "temperature:", + le32_to_cpu(general->temperature)); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_value, "temperature_m:", + le32_to_cpu(general->temperature_m)); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_value, "ttl_timestamp:", + le32_to_cpu(general->ttl_timestamp)); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "burst_check:", + le32_to_cpu(dbg->burst_check), + accum_dbg->burst_check, + delta_dbg->burst_check, max_dbg->burst_check); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "burst_count:", + le32_to_cpu(dbg->burst_count), + accum_dbg->burst_count, + delta_dbg->burst_count, max_dbg->burst_count); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "wait_for_silence_timeout_count:", + le32_to_cpu(dbg->wait_for_silence_timeout_cnt), + accum_dbg->wait_for_silence_timeout_cnt, + delta_dbg->wait_for_silence_timeout_cnt, + max_dbg->wait_for_silence_timeout_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "sleep_time:", + le32_to_cpu(general->sleep_time), + accum_general->sleep_time, + delta_general->sleep_time, max_general->sleep_time); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "slots_out:", + le32_to_cpu(general->slots_out), + accum_general->slots_out, + delta_general->slots_out, max_general->slots_out); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "slots_idle:", + le32_to_cpu(general->slots_idle), + accum_general->slots_idle, + delta_general->slots_idle, max_general->slots_idle); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "tx_on_a:", + le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, + delta_div->tx_on_a, max_div->tx_on_a); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "tx_on_b:", + le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, + delta_div->tx_on_b, max_div->tx_on_b); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "exec_time:", + le32_to_cpu(div->exec_time), accum_div->exec_time, + delta_div->exec_time, max_div->exec_time); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "probe_time:", + le32_to_cpu(div->probe_time), accum_div->probe_time, + delta_div->probe_time, max_div->probe_time); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "rx_enable_counter:", + le32_to_cpu(general->rx_enable_counter), + accum_general->rx_enable_counter, + delta_general->rx_enable_counter, + max_general->rx_enable_counter); + pos += scnprintf(buf + pos, bufsz - pos, + fmt_table, "num_of_sos_states:", + le32_to_cpu(general->num_of_sos_states), + accum_general->num_of_sos_states, + delta_general->num_of_sos_states, + max_general->num_of_sos_states); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + int pos = 0; + char *buf; + int bufsz = (sizeof(struct statistics_bt_activity) * 24) + 200; + ssize_t ret; + struct statistics_bt_activity *bt, *accum_bt; + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + if (!priv->bt_enable_flag) + return -EINVAL; + + /* make request to uCode to retrieve statistics information */ + mutex_lock(&priv->mutex); + ret = iwl_send_statistics_request(priv, CMD_SYNC, false); + mutex_unlock(&priv->mutex); + + if (ret) { + IWL_ERR(priv, + "Error sending statistics request: %zd\n", ret); + return -EAGAIN; + } + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + /* + * the statistic information display here is based on + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + bt = &priv->statistics.bt_activity; + accum_bt = &priv->accum_stats.bt_activity; + + pos += iwl_statistics_flag(priv, buf, bufsz); + pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n"); + pos += scnprintf(buf + pos, bufsz - pos, + "\t\t\tcurrent\t\t\taccumulative\n"); + pos += scnprintf(buf + pos, bufsz - pos, + "hi_priority_tx_req_cnt:\t\t%u\t\t\t%u\n", + le32_to_cpu(bt->hi_priority_tx_req_cnt), + accum_bt->hi_priority_tx_req_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "hi_priority_tx_denied_cnt:\t%u\t\t\t%u\n", + le32_to_cpu(bt->hi_priority_tx_denied_cnt), + accum_bt->hi_priority_tx_denied_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "lo_priority_tx_req_cnt:\t\t%u\t\t\t%u\n", + le32_to_cpu(bt->lo_priority_tx_req_cnt), + accum_bt->lo_priority_tx_req_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "lo_priority_tx_denied_cnt:\t%u\t\t\t%u\n", + le32_to_cpu(bt->lo_priority_tx_denied_cnt), + accum_bt->lo_priority_tx_denied_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "hi_priority_rx_req_cnt:\t\t%u\t\t\t%u\n", + le32_to_cpu(bt->hi_priority_rx_req_cnt), + accum_bt->hi_priority_rx_req_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "hi_priority_rx_denied_cnt:\t%u\t\t\t%u\n", + le32_to_cpu(bt->hi_priority_rx_denied_cnt), + accum_bt->hi_priority_rx_denied_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "lo_priority_rx_req_cnt:\t\t%u\t\t\t%u\n", + le32_to_cpu(bt->lo_priority_rx_req_cnt), + accum_bt->lo_priority_rx_req_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n", + le32_to_cpu(bt->lo_priority_rx_denied_cnt), + accum_bt->lo_priority_rx_denied_cnt); + + pos += scnprintf(buf + pos, bufsz - pos, + "(rx)num_bt_kills:\t\t%u\t\t\t%u\n", + le32_to_cpu(priv->statistics.num_bt_kills), + priv->statistics.accum_num_bt_kills); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + int pos = 0; + char *buf; + int bufsz = (sizeof(struct reply_tx_error_statistics) * 24) + + (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200; + ssize_t ret; + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n"); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY), + priv->_agn.reply_tx_stats.pp_delay); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES), + priv->_agn.reply_tx_stats.pp_few_bytes); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO), + priv->_agn.reply_tx_stats.pp_bt_prio); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD), + priv->_agn.reply_tx_stats.pp_quiet_period); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK), + priv->_agn.reply_tx_stats.pp_calc_ttak); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", + iwl_get_tx_fail_reason( + TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY), + priv->_agn.reply_tx_stats.int_crossed_retry); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT), + priv->_agn.reply_tx_stats.short_limit); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT), + priv->_agn.reply_tx_stats.long_limit); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN), + priv->_agn.reply_tx_stats.fifo_underrun); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW), + priv->_agn.reply_tx_stats.drain_flow); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH), + priv->_agn.reply_tx_stats.rfkill_flush); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE), + priv->_agn.reply_tx_stats.life_expire); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS), + priv->_agn.reply_tx_stats.dest_ps); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED), + priv->_agn.reply_tx_stats.host_abort); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY), + priv->_agn.reply_tx_stats.pp_delay); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID), + priv->_agn.reply_tx_stats.sta_invalid); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED), + priv->_agn.reply_tx_stats.frag_drop); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE), + priv->_agn.reply_tx_stats.tid_disable); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED), + priv->_agn.reply_tx_stats.fifo_flush); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", + iwl_get_tx_fail_reason( + TX_STATUS_FAIL_INSUFFICIENT_CF_POLL), + priv->_agn.reply_tx_stats.insuff_cf_poll); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX), + priv->_agn.reply_tx_stats.fail_hw_drop); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", + iwl_get_tx_fail_reason( + TX_STATUS_FAIL_NO_BEACON_ON_RADAR), + priv->_agn.reply_tx_stats.sta_color_mismatch); + pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", + priv->_agn.reply_tx_stats.unknown); + + pos += scnprintf(buf + pos, bufsz - pos, + "\nStatistics_Agg_TX_Error:\n"); + + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK), + priv->_agn.reply_agg_tx_stats.underrun); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK), + priv->_agn.reply_agg_tx_stats.bt_prio); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK), + priv->_agn.reply_agg_tx_stats.few_bytes); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK), + priv->_agn.reply_agg_tx_stats.abort); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", + iwl_get_agg_tx_fail_reason( + AGG_TX_STATE_LAST_SENT_TTL_MSK), + priv->_agn.reply_agg_tx_stats.last_sent_ttl); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", + iwl_get_agg_tx_fail_reason( + AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK), + priv->_agn.reply_agg_tx_stats.last_sent_try); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", + iwl_get_agg_tx_fail_reason( + AGG_TX_STATE_LAST_SENT_BT_KILL_MSK), + priv->_agn.reply_agg_tx_stats.last_sent_bt_kill); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK), + priv->_agn.reply_agg_tx_stats.scd_query); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", + iwl_get_agg_tx_fail_reason( + AGG_TX_STATE_TEST_BAD_CRC32_MSK), + priv->_agn.reply_agg_tx_stats.bad_crc32); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK), + priv->_agn.reply_agg_tx_stats.response); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK), + priv->_agn.reply_agg_tx_stats.dump_tx); + pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", + iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK), + priv->_agn.reply_agg_tx_stats.delay_tx); + pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", + priv->_agn.reply_agg_tx_stats.unknown); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; } static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, @@ -1526,16 +2498,6 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, return count; } -static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - - return priv->cfg->ops->lib->debugfs_ops.bt_stats_read(file, - user_buf, count, ppos); -} - static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { @@ -1650,18 +2612,6 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, return count; } -static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - - if (priv->cfg->ops->lib->debugfs_ops.reply_tx_error) - return priv->cfg->ops->lib->debugfs_ops.reply_tx_error( - file, user_buf, count, ppos); - else - return -ENODATA; -} DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); -- cgit v1.2.3-58-ga151 From b5a6f69c5ca024bea43496d517c3b7ccfdb084a6 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sat, 16 Apr 2011 11:30:57 +0200 Subject: batman-adv: orig_hash_find() manages rcu_lock/unlock internally orig_hash_find() manages rcu_lock/unlock internally and doesn't need to be surrounded by rcu_read_lock() / rcu_read_unlock() anymore Signed-off-by: Antonio Quartulli Acked-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/routing.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index f6c642246972..2d77bd3a3e9a 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1310,13 +1310,10 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) } /* get routing information */ - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, unicast_packet->dest); if (!orig_node) - goto unlock; - - rcu_read_unlock(); + goto out; /* find_router() increases neigh_nodes refcount if found. */ neigh_node = find_router(bat_priv, orig_node, recv_if); @@ -1362,10 +1359,7 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) /* route it */ send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); ret = NET_RX_SUCCESS; - goto out; -unlock: - rcu_read_unlock(); out: if (neigh_node) neigh_node_free_ref(neigh_node); @@ -1464,13 +1458,10 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) if (bcast_packet->ttl < 2) goto out; - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, bcast_packet->orig); if (!orig_node) - goto rcu_unlock; - - rcu_read_unlock(); + goto out; spin_lock_bh(&orig_node->bcast_seqno_lock); @@ -1501,9 +1492,6 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) ret = NET_RX_SUCCESS; goto out; -rcu_unlock: - rcu_read_unlock(); - goto out; spin_unlock: spin_unlock_bh(&orig_node->bcast_seqno_lock); out: -- cgit v1.2.3-58-ga151 From 5f657ec0d2103571a31707711926b443a27b0c66 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Wed, 20 Apr 2011 09:52:56 +0200 Subject: batman-adv: Move definition of atomic_dec_not_zero() into main.h atomic_dec_not_zero() is very useful and it is currently defined multiple times. So it is possible to move it in main.h Signed-off-by: Antonio Quartulli Signed-off-by: Sven Eckelmann --- net/batman-adv/aggregation.c | 1 - net/batman-adv/main.h | 2 ++ net/batman-adv/send.c | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c index af45d6b2031f..c11788c4c1a1 100644 --- a/net/batman-adv/aggregation.c +++ b/net/batman-adv/aggregation.c @@ -95,7 +95,6 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet, return false; } -#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) /* create a new aggregated packet and add this packet to it */ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, unsigned long send_time, bool direct_link, diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index dc248697de71..ace72852ed7b 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -175,4 +175,6 @@ static inline int compare_eth(void *data1, void *data2) return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); } +#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) + #endif /* _NET_BATMAN_ADV_MAIN_H_ */ diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index e78670c3c4b7..7650e2bf187d 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -393,7 +393,6 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv, send_time); } -#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) /* add a broadcast packet to the queue and setup timers. broadcast packets * are sent multiple times to increase probability for beeing received. * -- cgit v1.2.3-58-ga151 From 71e4aa9c465fd66c110667ab5d620fb6a4ef2157 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Mon, 25 Apr 2011 22:44:32 +0200 Subject: batman-adv: fix gw_node_update() and gw_election() This is a regression from c4aac1ab9b973798163b34939b522f01e4d28ac9 - gw_node_update() doesn't add a new gw_node in case of empty curr_gw. This means that at the beginning no gw_node is added, leading to an empty gateway list. - gw_election() is terminating in case of curr_gw == NULL. It has to terminate in case of curr_gw != NULL Signed-off-by: Antonio Quartulli Signed-off-by: Sven Eckelmann --- net/batman-adv/gateway_client.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 2acd7a666bda..af128eff2edf 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -127,7 +127,7 @@ void gw_election(struct bat_priv *bat_priv) return; curr_gw = gw_get_selected_gw_node(bat_priv); - if (!curr_gw) + if (curr_gw) goto out; rcu_read_lock(); @@ -310,9 +310,13 @@ void gw_node_update(struct bat_priv *bat_priv, struct hlist_node *node; struct gw_node *gw_node, *curr_gw; + /** + * Note: We don't need a NULL check here, since curr_gw never gets + * dereferenced. If curr_gw is NULL we also should not exit as we may + * have this gateway in our list (duplication check!) even though we + * have no currently selected gateway. + */ curr_gw = gw_get_selected_gw_node(bat_priv); - if (!curr_gw) - goto out; rcu_read_lock(); hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { @@ -350,7 +354,7 @@ deselect: gw_deselect(bat_priv); unlock: rcu_read_unlock(); -out: + if (curr_gw) gw_node_free_ref(curr_gw); } -- cgit v1.2.3-58-ga151 From 32ae9b221e788413ce68feaae2ca39e406211a0a Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Wed, 20 Apr 2011 15:40:58 +0200 Subject: batman-adv: Make bat_priv->primary_if an rcu protected pointer The rcu protected macros rcu_dereference() and rcu_assign_pointer() for the bat_priv->primary_if need to be used, as well as spin/rcu locking. Otherwise we might end up using a primary_if pointer pointing to already freed memory. Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/gateway_client.c | 33 ++++++++------- net/batman-adv/hard-interface.c | 83 ++++++++++++++++++++++++++------------ net/batman-adv/hard-interface.h | 18 +++++++++ net/batman-adv/icmp_socket.c | 19 ++++++--- net/batman-adv/originator.c | 34 ++++++++++------ net/batman-adv/routing.c | 18 ++++++--- net/batman-adv/send.c | 17 ++++++-- net/batman-adv/soft-interface.c | 64 ++++++++++++++++++++--------- net/batman-adv/translation-table.c | 57 +++++++++++++++++++------- net/batman-adv/types.h | 2 +- net/batman-adv/unicast.c | 16 +++++--- net/batman-adv/vis.c | 37 ++++++++++++----- 12 files changed, 280 insertions(+), 118 deletions(-) diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index af128eff2edf..65f39530799d 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -439,30 +439,32 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); + struct hard_iface *primary_if; struct gw_node *gw_node; struct hlist_node *node; - int gw_count = 0; + int gw_count = 0, ret = 0; - if (!bat_priv->primary_if) { - - return seq_printf(seq, "BATMAN mesh %s disabled - please " - "specify interfaces to enable it\n", - net_dev->name); + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - please " + "specify interfaces to enable it\n", + net_dev->name); + goto out; } - if (bat_priv->primary_if->if_status != IF_ACTIVE) { - - return seq_printf(seq, "BATMAN mesh %s disabled - " - "primary interface not active\n", - net_dev->name); + if (primary_if->if_status != IF_ACTIVE) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - " + "primary interface not active\n", + net_dev->name); + goto out; } seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... " "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", "Gateway", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, - bat_priv->primary_if->net_dev->name, - bat_priv->primary_if->net_dev->dev_addr, net_dev->name); + primary_if->net_dev->name, + primary_if->net_dev->dev_addr, net_dev->name); rcu_read_lock(); hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { @@ -480,7 +482,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) if (gw_count == 0) seq_printf(seq, "No gateways in range ...\n"); - return 0; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index b3058e46ee6b..3e888f133d75 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -110,47 +110,60 @@ out: return hard_iface; } -static void update_primary_addr(struct bat_priv *bat_priv) +static void primary_if_update_addr(struct bat_priv *bat_priv) { struct vis_packet *vis_packet; + struct hard_iface *primary_if; + + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; vis_packet = (struct vis_packet *) bat_priv->my_vis_info->skb_packet->data; - memcpy(vis_packet->vis_orig, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); memcpy(vis_packet->sender_orig, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + primary_if->net_dev->dev_addr, ETH_ALEN); + +out: + if (primary_if) + hardif_free_ref(primary_if); } -static void set_primary_if(struct bat_priv *bat_priv, - struct hard_iface *hard_iface) +static void primary_if_select(struct bat_priv *bat_priv, + struct hard_iface *new_hard_iface) { + struct hard_iface *curr_hard_iface; struct batman_packet *batman_packet; - struct hard_iface *old_if; - if (hard_iface && !atomic_inc_not_zero(&hard_iface->refcount)) - hard_iface = NULL; + spin_lock_bh(&hardif_list_lock); - old_if = bat_priv->primary_if; - bat_priv->primary_if = hard_iface; + if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount)) + new_hard_iface = NULL; - if (old_if) - hardif_free_ref(old_if); + curr_hard_iface = bat_priv->primary_if; + rcu_assign_pointer(bat_priv->primary_if, new_hard_iface); - if (!bat_priv->primary_if) - return; + if (curr_hard_iface) + hardif_free_ref(curr_hard_iface); - batman_packet = (struct batman_packet *)(hard_iface->packet_buff); + if (!new_hard_iface) + goto out; + + batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff); batman_packet->flags = PRIMARIES_FIRST_HOP; batman_packet->ttl = TTL; - update_primary_addr(bat_priv); + primary_if_update_addr(bat_priv); /*** * hacky trick to make sure that we send the HNA information via * our new primary interface */ atomic_set(&bat_priv->hna_local_changed, 1); + +out: + spin_unlock_bh(&hardif_list_lock); } static bool hardif_is_iface_up(struct hard_iface *hard_iface) @@ -236,9 +249,10 @@ void update_min_mtu(struct net_device *soft_iface) static void hardif_activate_interface(struct hard_iface *hard_iface) { struct bat_priv *bat_priv; + struct hard_iface *primary_if = NULL; if (hard_iface->if_status != IF_INACTIVE) - return; + goto out; bat_priv = netdev_priv(hard_iface->soft_iface); @@ -249,14 +263,18 @@ static void hardif_activate_interface(struct hard_iface *hard_iface) * the first active interface becomes our primary interface or * the next active interface after the old primay interface was removed */ - if (!bat_priv->primary_if) - set_primary_if(bat_priv, hard_iface); + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + primary_if_select(bat_priv, hard_iface); bat_info(hard_iface->soft_iface, "Interface activated: %s\n", hard_iface->net_dev->name); update_min_mtu(hard_iface->soft_iface); - return; + +out: + if (primary_if) + hardif_free_ref(primary_if); } static void hardif_deactivate_interface(struct hard_iface *hard_iface) @@ -386,12 +404,13 @@ err: void hardif_disable_interface(struct hard_iface *hard_iface) { struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); + struct hard_iface *primary_if = NULL; if (hard_iface->if_status == IF_ACTIVE) hardif_deactivate_interface(hard_iface); if (hard_iface->if_status != IF_INACTIVE) - return; + goto out; bat_info(hard_iface->soft_iface, "Removing interface: %s\n", hard_iface->net_dev->name); @@ -400,11 +419,12 @@ void hardif_disable_interface(struct hard_iface *hard_iface) bat_priv->num_ifaces--; orig_hash_del_if(hard_iface, bat_priv->num_ifaces); - if (hard_iface == bat_priv->primary_if) { + primary_if = primary_if_get_selected(bat_priv); + if (hard_iface == primary_if) { struct hard_iface *new_if; new_if = hardif_get_active(hard_iface->soft_iface); - set_primary_if(bat_priv, new_if); + primary_if_select(bat_priv, new_if); if (new_if) hardif_free_ref(new_if); @@ -425,6 +445,10 @@ void hardif_disable_interface(struct hard_iface *hard_iface) hard_iface->soft_iface = NULL; hardif_free_ref(hard_iface); + +out: + if (primary_if) + hardif_free_ref(primary_if); } static struct hard_iface *hardif_add_interface(struct net_device *net_dev) @@ -514,6 +538,7 @@ static int hard_if_event(struct notifier_block *this, { struct net_device *net_dev = (struct net_device *)ptr; struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); + struct hard_iface *primary_if = NULL; struct bat_priv *bat_priv; if (!hard_iface && event == NETDEV_REGISTER) @@ -549,8 +574,12 @@ static int hard_if_event(struct notifier_block *this, update_mac_addresses(hard_iface); bat_priv = netdev_priv(hard_iface->soft_iface); - if (hard_iface == bat_priv->primary_if) - update_primary_addr(bat_priv); + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto hardif_put; + + if (hard_iface == primary_if) + primary_if_update_addr(bat_priv); break; default: break; @@ -559,6 +588,8 @@ static int hard_if_event(struct notifier_block *this, hardif_put: hardif_free_ref(hard_iface); out: + if (primary_if) + hardif_free_ref(primary_if); return NOTIFY_DONE; } diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h index a9ddf36e51c8..64265991460b 100644 --- a/net/batman-adv/hard-interface.h +++ b/net/batman-adv/hard-interface.h @@ -45,4 +45,22 @@ static inline void hardif_free_ref(struct hard_iface *hard_iface) call_rcu(&hard_iface->rcu, hardif_free_rcu); } +static inline struct hard_iface *primary_if_get_selected( + struct bat_priv *bat_priv) +{ + struct hard_iface *hard_iface; + + rcu_read_lock(); + hard_iface = rcu_dereference(bat_priv->primary_if); + if (!hard_iface) + goto out; + + if (!atomic_inc_not_zero(&hard_iface->refcount)) + hard_iface = NULL; + +out: + rcu_read_unlock(); + return hard_iface; +} + #endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */ diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index 49079c254476..fa22ba2bb832 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c @@ -153,6 +153,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, { struct socket_client *socket_client = file->private_data; struct bat_priv *bat_priv = socket_client->bat_priv; + struct hard_iface *primary_if = NULL; struct sk_buff *skb; struct icmp_packet_rr *icmp_packet; @@ -167,15 +168,21 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, return -EINVAL; } - if (!bat_priv->primary_if) - return -EFAULT; + primary_if = primary_if_get_selected(bat_priv); + + if (!primary_if) { + len = -EFAULT; + goto out; + } if (len >= sizeof(struct icmp_packet_rr)) packet_len = sizeof(struct icmp_packet_rr); skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr)); - if (!skb) - return -ENOMEM; + if (!skb) { + len = -ENOMEM; + goto out; + } skb_reserve(skb, sizeof(struct ethhdr)); icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len); @@ -233,7 +240,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, goto dst_unreach; memcpy(icmp_packet->orig, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + primary_if->net_dev->dev_addr, ETH_ALEN); if (packet_len == sizeof(struct icmp_packet_rr)) memcpy(icmp_packet->rr, @@ -248,6 +255,8 @@ dst_unreach: free_skb: kfree_skb(skb); out: + if (primary_if) + hardif_free_ref(primary_if); if (neigh_node) neigh_node_free_ref(neigh_node); if (orig_node) diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 5b8fe32043da..ef4a9be7613a 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -405,29 +405,34 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) struct hashtable_t *hash = bat_priv->orig_hash; struct hlist_node *node, *node_tmp; struct hlist_head *head; + struct hard_iface *primary_if; struct orig_node *orig_node; struct neigh_node *neigh_node, *neigh_node_tmp; int batman_count = 0; int last_seen_secs; int last_seen_msecs; - int i; + int i, ret = 0; + + primary_if = primary_if_get_selected(bat_priv); - if ((!bat_priv->primary_if) || - (bat_priv->primary_if->if_status != IF_ACTIVE)) { - if (!bat_priv->primary_if) - return seq_printf(seq, "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); + if (!primary_if) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); + goto out; + } - return seq_printf(seq, "BATMAN mesh %s " - "disabled - primary interface not active\n", - net_dev->name); + if (primary_if->if_status != IF_ACTIVE) { + ret = seq_printf(seq, "BATMAN mesh %s " + "disabled - primary interface not active\n", + net_dev->name); + goto out; } seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", SOURCE_VERSION, REVISION_VERSION_STR, - bat_priv->primary_if->net_dev->name, - bat_priv->primary_if->net_dev->dev_addr, net_dev->name); + primary_if->net_dev->name, + primary_if->net_dev->dev_addr, net_dev->name); seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n", "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", "Potential nexthops"); @@ -474,7 +479,10 @@ next: if (batman_count == 0) seq_printf(seq, "No batman nodes in range ...\n"); - return 0; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 2d77bd3a3e9a..49f571553050 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -904,6 +904,7 @@ int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface) static int recv_my_icmp_packet(struct bat_priv *bat_priv, struct sk_buff *skb, size_t icmp_len) { + struct hard_iface *primary_if = NULL; struct orig_node *orig_node = NULL; struct neigh_node *router = NULL; struct icmp_packet_rr *icmp_packet; @@ -917,7 +918,8 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, goto out; } - if (!bat_priv->primary_if) + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) goto out; /* answer echo request (ping) */ @@ -937,8 +939,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, icmp_packet = (struct icmp_packet_rr *)skb->data; memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); - memcpy(icmp_packet->orig, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); icmp_packet->msg_type = ECHO_REPLY; icmp_packet->ttl = TTL; @@ -946,6 +947,8 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, ret = NET_RX_SUCCESS; out: + if (primary_if) + hardif_free_ref(primary_if); if (router) neigh_node_free_ref(router); if (orig_node) @@ -956,6 +959,7 @@ out: static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, struct sk_buff *skb) { + struct hard_iface *primary_if = NULL; struct orig_node *orig_node = NULL; struct neigh_node *router = NULL; struct icmp_packet *icmp_packet; @@ -971,7 +975,8 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, goto out; } - if (!bat_priv->primary_if) + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) goto out; /* get routing information */ @@ -990,8 +995,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, icmp_packet = (struct icmp_packet *)skb->data; memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); - memcpy(icmp_packet->orig, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); icmp_packet->msg_type = TTL_EXCEEDED; icmp_packet->ttl = TTL; @@ -999,6 +1003,8 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, ret = NET_RX_SUCCESS; out: + if (primary_if) + hardif_free_ref(primary_if); if (router) neigh_node_free_ref(router); if (orig_node) diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 7650e2bf187d..02b541a6dfef 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -244,6 +244,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv, void schedule_own_packet(struct hard_iface *hard_iface) { struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); + struct hard_iface *primary_if; unsigned long send_time; struct batman_packet *batman_packet; int vis_server; @@ -253,6 +254,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) return; vis_server = atomic_read(&bat_priv->vis_mode); + primary_if = primary_if_get_selected(bat_priv); /** * the interface gets activated here to avoid race conditions between @@ -266,7 +268,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) /* if local hna has changed and interface is a primary interface */ if ((atomic_read(&bat_priv->hna_local_changed)) && - (hard_iface == bat_priv->primary_if)) + (hard_iface == primary_if)) rebuild_batman_packet(bat_priv, hard_iface); /** @@ -284,7 +286,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) else batman_packet->flags &= ~VIS_SERVER; - if ((hard_iface == bat_priv->primary_if) && + if ((hard_iface == primary_if) && (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)) batman_packet->gw_flags = (uint8_t)atomic_read(&bat_priv->gw_bandwidth); @@ -299,6 +301,9 @@ void schedule_own_packet(struct hard_iface *hard_iface) hard_iface->packet_buff, hard_iface->packet_len, hard_iface, 1, send_time); + + if (primary_if) + hardif_free_ref(primary_if); } void schedule_forward_packet(struct orig_node *orig_node, @@ -403,6 +408,7 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv, * skb is freed. */ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) { + struct hard_iface *primary_if = NULL; struct forw_packet *forw_packet; struct bcast_packet *bcast_packet; @@ -411,7 +417,8 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) goto out; } - if (!bat_priv->primary_if) + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) goto out; forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); @@ -430,7 +437,7 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) skb_reset_mac_header(skb); forw_packet->skb = skb; - forw_packet->if_incoming = bat_priv->primary_if; + forw_packet->if_incoming = primary_if; /* how often did we send the bcast packet ? */ forw_packet->num_packets = 0; @@ -443,6 +450,8 @@ packet_free: out_and_inc: atomic_inc(&bat_priv->bcast_queue_left); out: + if (primary_if) + hardif_free_ref(primary_if); return NETDEV_TX_BUSY; } diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 58ce4400d581..ea5e58c252f0 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -215,13 +215,24 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct softif_neigh *softif_neigh; + struct hard_iface *primary_if; struct hlist_node *node; struct softif_neigh *curr_softif_neigh; + int ret = 0; - if (!bat_priv->primary_if) { - return seq_printf(seq, "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); + goto out; + } + + if (primary_if->if_status != IF_ACTIVE) { + ret = seq_printf(seq, "BATMAN mesh %s " + "disabled - primary interface not active\n", + net_dev->name); + goto out; } seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); @@ -238,7 +249,10 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) if (curr_softif_neigh) softif_neigh_free_ref(curr_softif_neigh); - return 0; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, @@ -247,7 +261,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, struct bat_priv *bat_priv = netdev_priv(dev); struct ethhdr *ethhdr = (struct ethhdr *)skb->data; struct batman_packet *batman_packet; - struct softif_neigh *softif_neigh; + struct softif_neigh *softif_neigh = NULL; + struct hard_iface *primary_if = NULL; struct softif_neigh *curr_softif_neigh = NULL; if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) @@ -257,28 +272,34 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN); if (batman_packet->version != COMPAT_VERSION) - goto err; + goto out; if (batman_packet->packet_type != BAT_PACKET) - goto err; + goto out; if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) - goto err; + goto out; if (is_my_mac(batman_packet->orig)) - goto err; + goto out; softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid); - if (!softif_neigh) - goto err; + goto out; curr_softif_neigh = softif_neigh_get_selected(bat_priv); + if (!curr_softif_neigh) + goto out; + if (curr_softif_neigh == softif_neigh) goto out; + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; + /* we got a neighbor but its mac is 'bigger' than ours */ - if (memcmp(bat_priv->primary_if->net_dev->dev_addr, + if (memcmp(primary_if->net_dev->dev_addr, softif_neigh->addr, ETH_ALEN) < 0) goto out; @@ -300,7 +321,7 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, /* close own batX device and use softif_neigh as exit node */ if ((!curr_softif_neigh) && (memcmp(softif_neigh->addr, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) { + primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) { bat_dbg(DBG_ROUTES, bat_priv, "Setting mesh exit point to %pM (vid: %d).\n", softif_neigh->addr, softif_neigh->vid); @@ -310,12 +331,13 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, } out: - softif_neigh_free_ref(softif_neigh); -err: kfree_skb(skb); + if (softif_neigh) + softif_neigh_free_ref(softif_neigh); if (curr_softif_neigh) softif_neigh_free_ref(curr_softif_neigh); - + if (primary_if) + hardif_free_ref(primary_if); return; } @@ -371,6 +393,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) { struct ethhdr *ethhdr = (struct ethhdr *)skb->data; struct bat_priv *bat_priv = netdev_priv(soft_iface); + struct hard_iface *primary_if = NULL; struct bcast_packet *bcast_packet; struct vlan_ethhdr *vhdr; struct softif_neigh *curr_softif_neigh = NULL; @@ -420,7 +443,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) /* ethernet packet should be broadcasted */ if (do_bcast) { - if (!bat_priv->primary_if) + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) goto dropped; if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0) @@ -436,7 +460,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) /* hw address of first interface is the orig mac because only * this mac is known throughout the mesh */ memcpy(bcast_packet->orig, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + primary_if->net_dev->dev_addr, ETH_ALEN); /* set broadcast sequence number */ bcast_packet->seqno = @@ -466,6 +490,8 @@ dropped_freed: end: if (curr_softif_neigh) softif_neigh_free_ref(curr_softif_neigh); + if (primary_if) + hardif_free_ref(primary_if); return NETDEV_TX_OK; } diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 8d15b48d1692..f931830d630e 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -22,6 +22,7 @@ #include "main.h" #include "translation-table.h" #include "soft-interface.h" +#include "hard-interface.h" #include "hash.h" #include "originator.h" @@ -237,16 +238,26 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) struct bat_priv *bat_priv = netdev_priv(net_dev); struct hashtable_t *hash = bat_priv->hna_local_hash; struct hna_local_entry *hna_local_entry; + struct hard_iface *primary_if; struct hlist_node *node; struct hlist_head *head; size_t buf_size, pos; char *buff; - int i; + int i, ret = 0; - if (!bat_priv->primary_if) { - return seq_printf(seq, "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); + goto out; + } + + if (primary_if->if_status != IF_ACTIVE) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - " + "primary interface not active\n", + net_dev->name); + goto out; } seq_printf(seq, "Locally retrieved addresses (from %s) " @@ -269,7 +280,8 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { spin_unlock_bh(&bat_priv->hna_lhash_lock); - return -ENOMEM; + ret = -ENOMEM; + goto out; } buff[0] = '\0'; @@ -291,7 +303,10 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) seq_printf(seq, "%s", buff); kfree(buff); - return 0; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } static void _hna_local_del(struct hlist_node *node, void *arg) @@ -468,16 +483,26 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) struct bat_priv *bat_priv = netdev_priv(net_dev); struct hashtable_t *hash = bat_priv->hna_global_hash; struct hna_global_entry *hna_global_entry; + struct hard_iface *primary_if; struct hlist_node *node; struct hlist_head *head; size_t buf_size, pos; char *buff; - int i; + int i, ret = 0; - if (!bat_priv->primary_if) { - return seq_printf(seq, "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - please " + "specify interfaces to enable it\n", + net_dev->name); + goto out; + } + + if (primary_if->if_status != IF_ACTIVE) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - " + "primary interface not active\n", + net_dev->name); + goto out; } seq_printf(seq, "Globally announced HNAs received via the mesh %s\n", @@ -499,7 +524,8 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { spin_unlock_bh(&bat_priv->hna_ghash_lock); - return -ENOMEM; + ret = -ENOMEM; + goto out; } buff[0] = '\0'; pos = 0; @@ -522,7 +548,10 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) seq_printf(seq, "%s", buff); kfree(buff); - return 0; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } static void _hna_global_del_orig(struct bat_priv *bat_priv, diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 75123b1ae0de..947bafc6431a 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -149,7 +149,6 @@ struct bat_priv { struct hlist_head softif_neigh_list; struct softif_neigh __rcu *softif_neigh; struct debug_log *debug_log; - struct hard_iface *primary_if; struct kobject *mesh_obj; struct dentry *debug_dir; struct hlist_head forw_bat_list; @@ -174,6 +173,7 @@ struct bat_priv { struct delayed_work orig_work; struct delayed_work vis_work; struct gw_node __rcu *curr_gw; /* rcu protected pointer */ + struct hard_iface __rcu *primary_if; /* rcu protected pointer */ struct vis_info *my_vis_info; }; diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index d46acc815138..b46cbf1507e4 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c @@ -221,15 +221,17 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, struct hard_iface *hard_iface, uint8_t dstaddr[]) { struct unicast_packet tmp_uc, *unicast_packet; + struct hard_iface *primary_if; struct sk_buff *frag_skb; struct unicast_frag_packet *frag1, *frag2; int uc_hdr_len = sizeof(struct unicast_packet); int ucf_hdr_len = sizeof(struct unicast_frag_packet); int data_len = skb->len - uc_hdr_len; - int large_tail = 0; + int large_tail = 0, ret = NET_RX_DROP; uint16_t seqno; - if (!bat_priv->primary_if) + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) goto dropped; frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len); @@ -254,7 +256,7 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, frag1->version = COMPAT_VERSION; frag1->packet_type = BAT_UNICAST_FRAG; - memcpy(frag1->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + memcpy(frag1->orig, primary_if->net_dev->dev_addr, ETH_ALEN); memcpy(frag2, frag1, sizeof(struct unicast_frag_packet)); if (data_len & 1) @@ -269,13 +271,17 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, send_skb_packet(skb, hard_iface, dstaddr); send_skb_packet(frag_skb, hard_iface, dstaddr); - return NET_RX_SUCCESS; + ret = NET_RX_SUCCESS; + goto out; drop_frag: kfree_skb(frag_skb); dropped: kfree_skb(skb); - return NET_RX_DROP; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index d4cc4f5399f4..c8f571d3b5d4 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c @@ -204,6 +204,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, int vis_seq_print_text(struct seq_file *seq, void *offset) { + struct hard_iface *primary_if; struct hlist_node *node; struct hlist_head *head; struct vis_info *info; @@ -215,15 +216,18 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) HLIST_HEAD(vis_if_list); struct if_list_entry *entry; struct hlist_node *pos, *n; - int i, j; + int i, j, ret = 0; int vis_server = atomic_read(&bat_priv->vis_mode); size_t buff_pos, buf_size; char *buff; int compare; - if ((!bat_priv->primary_if) || - (vis_server == VIS_TYPE_CLIENT_UPDATE)) - return 0; + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; + + if (vis_server == VIS_TYPE_CLIENT_UPDATE) + goto out; buf_size = 1; /* Estimate length */ @@ -270,7 +274,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { spin_unlock_bh(&bat_priv->vis_hash_lock); - return -ENOMEM; + ret = -ENOMEM; + goto out; } buff[0] = '\0'; buff_pos = 0; @@ -328,7 +333,10 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) seq_printf(seq, "%s", buff); kfree(buff); - return 0; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } /* add the info packet to the send list, if it was not @@ -815,16 +823,20 @@ out: /* only send one vis packet. called from send_vis_packets() */ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) { + struct hard_iface *primary_if; struct vis_packet *packet; + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; + packet = (struct vis_packet *)info->skb_packet->data; if (packet->ttl < 2) { pr_debug("Error - can't send vis packet: ttl exceeded\n"); - return; + goto out; } - memcpy(packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr, - ETH_ALEN); + memcpy(packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN); packet->ttl--; if (is_broadcast_ether_addr(packet->target_orig)) @@ -832,6 +844,10 @@ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) else unicast_vis_packet(bat_priv, info); packet->ttl++; /* restore TTL */ + +out: + if (primary_if) + hardif_free_ref(primary_if); } /* called from timer; send (and maybe generate) vis packet. */ @@ -858,8 +874,7 @@ static void send_vis_packets(struct work_struct *work) kref_get(&info->refcount); spin_unlock_bh(&bat_priv->vis_hash_lock); - if (bat_priv->primary_if) - send_vis_packet(bat_priv, info); + send_vis_packet(bat_priv, info); spin_lock_bh(&bat_priv->vis_hash_lock); send_list_del(info); -- cgit v1.2.3-58-ga151 From 564f59509e26355965949c677f9d6eb064a3aa0b Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Mon, 4 Apr 2011 10:20:39 +0300 Subject: wl12xx: Set End-of-transaction Flag at Wl127x AP Mode End-of-transaction flag should be set when working with wl127x chip on AP mode. Thanks Ido Yariv for the guidance with that. Signed-off-by: Shahar Levi Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0c69e959d0de..11497a90463b 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1011,6 +1011,10 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", wl->chip.id); + /* end-of-transaction flag should be set in wl127x AP mode */ + if (wl->bss_type == BSS_TYPE_AP_BSS) + wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; + ret = wl1271_setup(wl); if (ret < 0) goto out; -- cgit v1.2.3-58-ga151 From c75bbcdb200e2815c855e42a4685d170858af306 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 4 Apr 2011 10:38:47 +0300 Subject: wl12xx: sleep instead of wakeup after tx work commit d05c806 ("wl12xx: rearrange some ELP wake_up/sleep calls") introduced a bug in which wl1271_ps_elp_wakeup() was called instead of wl1271_ps_elp_sleep() after completing the tx work. Reported-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 7a3339fd3415..c83665964467 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -630,7 +630,7 @@ void wl1271_tx_work(struct work_struct *work) wl1271_tx_work_locked(wl); - wl1271_ps_elp_wakeup(wl); + wl1271_ps_elp_sleep(wl); out: mutex_unlock(&wl->mutex); } -- cgit v1.2.3-58-ga151 From a665d6e260f0233aac73f74d15bb6a029cc5ec47 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 3 Apr 2011 02:01:59 +0300 Subject: wl12xx: avoid premature elp entrance The elp_work is being enqueued on wl1271_ps_elp_sleep, but doesn't get cancelled on wl1271_ps_elp_wakeup. This might cause immediate entrance to elp when the wl->mutex is being released, rather than using the delayed enqueueing optimization. Cancel elp_work on wakeup request, and add a new WL1271_FLAG_ELP_REQUESTED flag to further synchronize the elp actions. [Fixed a couple of typos in some comments -- Luca] Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/ps.c | 30 ++++++++++++++++++++++++------ drivers/net/wireless/wl12xx/wl12xx.h | 1 + 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index b8deada5d020..b59b67711a17 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -43,6 +43,10 @@ void wl1271_elp_work(struct work_struct *work) if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; + /* our work might have been already cancelled */ + if (unlikely(!test_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) + goto out; + if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || (!test_bit(WL1271_FLAG_PSM, &wl->flags) && !test_bit(WL1271_FLAG_IDLE, &wl->flags))) @@ -61,12 +65,16 @@ out: /* Routines to toggle sleep mode while in ELP */ void wl1271_ps_elp_sleep(struct wl1271 *wl) { - if (test_bit(WL1271_FLAG_PSM, &wl->flags) || - test_bit(WL1271_FLAG_IDLE, &wl->flags)) { - cancel_delayed_work(&wl->elp_work); - ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, - msecs_to_jiffies(ELP_ENTRY_DELAY)); - } + /* we shouldn't get consecutive sleep requests */ + if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) + return; + + if (!test_bit(WL1271_FLAG_PSM, &wl->flags) && + !test_bit(WL1271_FLAG_IDLE, &wl->flags)) + return; + + ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, + msecs_to_jiffies(ELP_ENTRY_DELAY)); } int wl1271_ps_elp_wakeup(struct wl1271 *wl) @@ -77,6 +85,16 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) u32 start_time = jiffies; bool pending = false; + /* + * we might try to wake up even if we didn't go to sleep + * before (e.g. on boot) + */ + if (!test_and_clear_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)) + return 0; + + /* don't cancel_sync as it might contend for a mutex and deadlock */ + cancel_delayed_work(&wl->elp_work); + if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) return 0; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 7c521af58e7d..f3de96212b96 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -345,6 +345,7 @@ enum wl12xx_flags { WL1271_FLAG_TX_QUEUE_STOPPED, WL1271_FLAG_TX_PENDING, WL1271_FLAG_IN_ELP, + WL1271_FLAG_ELP_REQUESTED, WL1271_FLAG_PSM, WL1271_FLAG_PSM_REQUESTED, WL1271_FLAG_IRQ_RUNNING, -- cgit v1.2.3-58-ga151 From b03acadea4f46884aa3c3e4d3a6ce03d283525e6 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 3 Apr 2011 13:54:54 +0300 Subject: wl12xx: Set correct REF CLK and TCXO CLK values to the FW Fix mismatch between the REF CLK and TCXO CLK information that is set in the platform data and the NVS, so we override what comes from the NVS and replace it with what comes from the platform data. [Small fix in a comment -- Luca] Signed-off-by: Shahar Levi Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index d48331682e7e..a9ffdd86f9b8 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -129,6 +129,9 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) if (gp->tx_bip_fem_auto_detect) answer = true; + /* Override the REF CLK from the NVS with the one from platform data */ + gen_parms->general_params.ref_clock = wl->ref_clock; + ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); if (ret < 0) { wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); @@ -168,6 +171,10 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) if (gp->tx_bip_fem_auto_detect) answer = true; + /* Replace REF and TCXO CLKs with the ones from platform data */ + gen_parms->general_params.ref_clock = wl->ref_clock; + gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock; + ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); if (ret < 0) { wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); -- cgit v1.2.3-58-ga151 From a20a5b7e48e24c1bf9c10ba27cb1862f8f777d00 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 5 Apr 2011 18:21:31 +0300 Subject: wl12xx: print actual rx packet size (without padding) When debugging, reduce the padding size from each rx packet, to get the actual packet size (so comparing it against a cap file will be easier) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/rx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 2a581495d5c9..faf5a1d3c2c3 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -121,7 +121,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); - wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, + wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, + skb->len - desc->pad_len, beacon ? "beacon" : ""); skb_trim(skb, skb->len - desc->pad_len); -- cgit v1.2.3-58-ga151 From 30df14d0d35dd166d50b8ea80d5f0b7ef1edb6da Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 5 Apr 2011 19:13:28 +0300 Subject: wl12xx: avoid redundant join on interface reconfiguration ieee80211_reconfig() sets most of the "changed" flags regardless of the actual change (e.g. BSS_CHANGED_ASSOC will be set even if the interface is still not associated). in this case the driver will issue some unneeded commands. Since the driver relies solely on the BSS_CHANGED_ASSOC flag, without checking if there was an actual change, it will end up issuing unjoin() and dummy_join() commands, although it was never associated and should just remain idle. Avoid it by checking the actual state change, in addition to the "changed" flag. (there seem to be more redundant configuration commands being issued, but they shouldn't harm) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 11497a90463b..1dd735cc38b1 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2698,8 +2698,10 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, } } else { /* use defaults when not associated */ + bool was_assoc = + !!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED, + &wl->flags); clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); - clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); wl->aid = 0; /* free probe-request template */ @@ -2725,8 +2727,10 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, goto out; /* restore the bssid filter and go to dummy bssid */ - wl1271_unjoin(wl); - wl1271_dummy_join(wl); + if (was_assoc) { + wl1271_unjoin(wl); + wl1271_dummy_join(wl); + } } } -- cgit v1.2.3-58-ga151 From cb5ae0530e0e2af86d128ce758645b6b4a9132e1 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 7 Apr 2011 15:52:05 +0300 Subject: wl12xx: configure rates when working in ibss mode When working in ibss mode, we don't configure rate policy per station (as we use the same link for multiple stations), so currently the 1mb/s rate is being used. Instead, configure the firmware to use the whole 11b rates by default. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/conf.h | 7 +++++++ drivers/net/wireless/wl12xx/main.c | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index d16094f2604f..5551d9d4016b 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -516,6 +516,13 @@ struct conf_rx_settings { #define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \ CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS) +/* + * Default rates for working as IBSS. use 11b rates + */ +#define CONF_TX_IBSS_DEFAULT_RATES (CONF_HW_BIT_RATE_1MBPS | \ + CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \ + CONF_HW_BIT_RATE_11MBPS); + struct conf_tx_rate_class { /* diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 1dd735cc38b1..53a8e2357ccf 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2509,6 +2509,24 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, } } + if (changed & BSS_CHANGED_IBSS) { + wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d", + bss_conf->ibss_joined); + + if (bss_conf->ibss_joined) { + u32 rates = bss_conf->basic_rates; + wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, + rates); + wl->basic_rate = wl1271_tx_min_rate_get(wl); + + /* by default, use 11b rates */ + wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; + ret = wl1271_acx_sta_rate_policies(wl); + if (ret < 0) + goto out; + } + } + ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); if (ret < 0) goto out; -- cgit v1.2.3-58-ga151 From ff86843dfbb368766d0aecd0147821d9a2b60edb Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Mon, 11 Apr 2011 15:41:46 +0300 Subject: wl12xx: FM WLAN coexistence Add support to FM WLAN coexistence (STA only). Some WiFi harmonics may interfere with FM operation, to avoid this problem special coexistence techniques are activated around some FM frequencies. Signed-off-by: Shahar Levi Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 40 +++++++++++++++++++++++++ drivers/net/wireless/wl12xx/acx.h | 61 ++++++++++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/conf.h | 14 +++++++++ drivers/net/wireless/wl12xx/init.c | 5 ++++ drivers/net/wireless/wl12xx/main.c | 17 +++++++++++ 5 files changed, 137 insertions(+) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index a5c9c0aff83f..8a39d1e40a68 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -1626,3 +1626,43 @@ out: kfree(acx); return ret; } + +int wl1271_acx_fm_coex(struct wl1271 *wl) +{ + struct wl1271_acx_fm_coex *acx; + int ret; + + wl1271_debug(DEBUG_ACX, "acx fm coex setting"); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) { + ret = -ENOMEM; + goto out; + } + + acx->enable = wl->conf.fm_coex.enable; + acx->swallow_period = wl->conf.fm_coex.swallow_period; + acx->n_divider_fref_set_1 = wl->conf.fm_coex.n_divider_fref_set_1; + acx->n_divider_fref_set_2 = wl->conf.fm_coex.n_divider_fref_set_2; + acx->m_divider_fref_set_1 = + cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_1); + acx->m_divider_fref_set_2 = + cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_2); + acx->coex_pll_stabilization_time = + cpu_to_le32(wl->conf.fm_coex.coex_pll_stabilization_time); + acx->ldo_stabilization_time = + cpu_to_le16(wl->conf.fm_coex.ldo_stabilization_time); + acx->fm_disturbed_band_margin = + wl->conf.fm_coex.fm_disturbed_band_margin; + acx->swallow_clk_diff = wl->conf.fm_coex.swallow_clk_diff; + + ret = wl1271_cmd_configure(wl, ACX_FM_COEX_CFG, acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx fm coex setting failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 942908cd53a3..2dde0346e955 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -1179,6 +1179,65 @@ struct wl1271_acx_inconnection_sta { u8 padding1[2]; } __packed; +/* + * ACX_FM_COEX_CFG + * set the FM co-existence parameters. + */ +struct wl1271_acx_fm_coex { + struct acx_header header; + /* enable(1) / disable(0) the FM Coex feature */ + u8 enable; + /* + * Swallow period used in COEX PLL swallowing mechanism. + * 0xFF = use FW default + */ + u8 swallow_period; + /* + * The N divider used in COEX PLL swallowing mechanism for Fref of + * 38.4/19.2 Mhz. 0xFF = use FW default + */ + u8 n_divider_fref_set_1; + /* + * The N divider used in COEX PLL swallowing mechanism for Fref of + * 26/52 Mhz. 0xFF = use FW default + */ + u8 n_divider_fref_set_2; + /* + * The M divider used in COEX PLL swallowing mechanism for Fref of + * 38.4/19.2 Mhz. 0xFFFF = use FW default + */ + __le16 m_divider_fref_set_1; + /* + * The M divider used in COEX PLL swallowing mechanism for Fref of + * 26/52 Mhz. 0xFFFF = use FW default + */ + __le16 m_divider_fref_set_2; + /* + * The time duration in uSec required for COEX PLL to stabilize. + * 0xFFFFFFFF = use FW default + */ + __le32 coex_pll_stabilization_time; + /* + * The time duration in uSec required for LDO to stabilize. + * 0xFFFFFFFF = use FW default + */ + __le16 ldo_stabilization_time; + /* + * The disturbed frequency band margin around the disturbed frequency + * center (single sided). + * For example, if 2 is configured, the following channels will be + * considered disturbed channel: + * 80 +- 0.1 MHz, 91 +- 0.1 MHz, 98 +- 0.1 MHz, 102 +- 0.1 MH + * 0xFF = use FW default + */ + u8 fm_disturbed_band_margin; + /* + * The swallow clock difference of the swallowing mechanism. + * 0xFF = use FW default + */ + u8 swallow_clk_diff; +} __packed; + enum { ACX_WAKE_UP_CONDITIONS = 0x0002, ACX_MEM_CFG = 0x0003, @@ -1208,6 +1267,7 @@ enum { ACX_BCN_DTIM_OPTIONS = 0x0031, ACX_SG_ENABLE = 0x0032, ACX_SG_CFG = 0x0033, + ACX_FM_COEX_CFG = 0x0034, ACX_BEACON_FILTER_TABLE = 0x0038, ACX_ARP_IP_FILTER = 0x0039, ACX_ROAMING_STATISTICS_TBL = 0x003B, @@ -1318,5 +1378,6 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl); int wl1271_acx_config_ps(struct wl1271 *wl); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); +int wl1271_acx_fm_coex(struct wl1271 *wl); #endif /* __WL1271_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 5551d9d4016b..a4e0acff8674 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -1199,6 +1199,19 @@ struct conf_memory_settings { u8 tx_min; }; +struct conf_fm_coex { + u8 enable; + u8 swallow_period; + u8 n_divider_fref_set_1; + u8 n_divider_fref_set_2; + u16 m_divider_fref_set_1; + u16 m_divider_fref_set_2; + u32 coex_pll_stabilization_time; + u16 ldo_stabilization_time; + u8 fm_disturbed_band_margin; + u8 swallow_clk_diff; +}; + struct conf_drv_settings { struct conf_sg_settings sg; struct conf_rx_settings rx; @@ -1212,6 +1225,7 @@ struct conf_drv_settings { struct conf_ht_setting ht; struct conf_memory_settings mem_wl127x; struct conf_memory_settings mem_wl128x; + struct conf_fm_coex fm_coex; u8 hci_io_ds; }; diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index ab3b1e21de29..46fd7212b238 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -356,6 +356,11 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) if (ret < 0) return ret; + /* FM WLAN coexistence */ + ret = wl1271_acx_fm_coex(wl); + if (ret < 0) + return ret; + /* Beacons and broadcast settings */ ret = wl1271_init_beacon_broadcast(wl); if (ret < 0) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 53a8e2357ccf..8a7a8c5fcf5b 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -320,6 +320,18 @@ static struct conf_drv_settings default_conf = { .min_req_rx_blocks = 22, .tx_min = 27, }, + .fm_coex = { + .enable = true, + .swallow_period = 5, + .n_divider_fref_set_1 = 0xff, /* default */ + .n_divider_fref_set_2 = 12, + .m_divider_fref_set_1 = 148, + .m_divider_fref_set_2 = 0xffff, /* default */ + .coex_pll_stabilization_time = 0xffffffff, /* default */ + .ldo_stabilization_time = 0xffff, /* default */ + .fm_disturbed_band_margin = 0xff, /* default */ + .swallow_clk_diff = 0xff, /* default */ + }, .hci_io_ds = HCI_IO_DS_6MA, }; @@ -508,6 +520,11 @@ static int wl1271_plt_init(struct wl1271 *wl) if (ret < 0) goto out_free_memmap; + /* FM WLAN coexistence */ + ret = wl1271_acx_fm_coex(wl); + if (ret < 0) + goto out_free_memmap; + /* Energy detection */ ret = wl1271_init_energy_detection(wl); if (ret < 0) -- cgit v1.2.3-58-ga151 From 2370841bf1a735661db3d3ae63385be3475b7452 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Wed, 13 Apr 2011 14:52:50 +0300 Subject: wl12xx: Update Power Save Exit Retries Packets Reducing the retries of sending PS exit packets to the peer AP. That fix is to avoid sending unrealizable number of PS exit packets in case of ap lost. Signed-off-by: Shahar Levi Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8a7a8c5fcf5b..c0cfcc7e11ac 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -258,7 +258,7 @@ static struct conf_drv_settings default_conf = { .bet_enable = CONF_BET_MODE_ENABLE, .bet_max_consecutive = 50, .psm_entry_retries = 5, - .psm_exit_retries = 255, + .psm_exit_retries = 16, .psm_entry_nullfunc_retries = 3, .psm_entry_hangover_period = 1, .keep_alive_interval = 55000, -- cgit v1.2.3-58-ga151 From 1fe9e2464c667903d7eec0314db26c462ca9d276 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 17 Apr 2011 11:20:47 +0300 Subject: wl12xx: add debugfs entries for dtim_interval and beacon_interval When configuring ACX_WAKE_UP_CONDITIONS (before entering psm), we tell the firmware to wake up once in N DTIMs/beacons. Allow control of this value via debugfs (for debugging purposes). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 132 ++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 70ab1986788e..88c6efe33ecc 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -291,6 +291,136 @@ static const struct file_operations gpio_power_ops = { .llseek = default_llseek, }; +static ssize_t dtim_interval_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + u8 value; + + if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_DTIM || + wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM) + value = wl->conf.conn.listen_interval; + else + value = 0; + + return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); +} + +static ssize_t dtim_interval_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + char buf[10]; + size_t len; + unsigned long value; + int ret; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + buf[len] = '\0'; + + ret = strict_strtoul(buf, 0, &value); + if (ret < 0) { + wl1271_warning("illegal value for dtim_interval"); + return -EINVAL; + } + + if (value < 1 || value > 10) { + wl1271_warning("dtim value is not in valid range"); + return -ERANGE; + } + + mutex_lock(&wl->mutex); + + wl->conf.conn.listen_interval = value; + /* for some reason there are different event types for 1 and >1 */ + if (value == 1) + wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_DTIM; + else + wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM; + + /* + * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only + * take effect on the next time we enter psm. + */ + mutex_unlock(&wl->mutex); + return count; +} + +static const struct file_operations dtim_interval_ops = { + .read = dtim_interval_read, + .write = dtim_interval_write, + .open = wl1271_open_file_generic, + .llseek = default_llseek, +}; + +static ssize_t beacon_interval_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + u8 value; + + if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_BEACON || + wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_BEACONS) + value = wl->conf.conn.listen_interval; + else + value = 0; + + return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); +} + +static ssize_t beacon_interval_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + char buf[10]; + size_t len; + unsigned long value; + int ret; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + buf[len] = '\0'; + + ret = strict_strtoul(buf, 0, &value); + if (ret < 0) { + wl1271_warning("illegal value for beacon_interval"); + return -EINVAL; + } + + if (value < 1 || value > 255) { + wl1271_warning("beacon interval value is not in valid range"); + return -ERANGE; + } + + mutex_lock(&wl->mutex); + + wl->conf.conn.listen_interval = value; + /* for some reason there are different event types for 1 and >1 */ + if (value == 1) + wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_BEACON; + else + wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_BEACONS; + + /* + * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only + * take effect on the next time we enter psm. + */ + mutex_unlock(&wl->mutex); + return count; +} + +static const struct file_operations beacon_interval_ops = { + .read = beacon_interval_read, + .write = beacon_interval_write, + .open = wl1271_open_file_generic, + .llseek = default_llseek, +}; + static int wl1271_debugfs_add_files(struct wl1271 *wl, struct dentry *rootdir) { @@ -399,6 +529,8 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, DEBUGFS_ADD(excessive_retries, rootdir); DEBUGFS_ADD(gpio_power, rootdir); + DEBUGFS_ADD(dtim_interval, rootdir); + DEBUGFS_ADD(beacon_interval, rootdir); return 0; -- cgit v1.2.3-58-ga151 From ae825e4ba81203e1b3d3159f24327cdc2629dbd8 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Mon, 18 Apr 2011 16:40:14 +0300 Subject: wl12xx: Modify memory configuration for 128x/AP The 128x/AP firmware does not yet support dynamic memory. Temporarily, the memory configuration for the 127x was used both for 127x/AP as well as 128x/AP. Since the two chips don't have the same number of memory blocks, TP was significantly degraded. This hasn't been fine tuned yet, but using the base 128x numbers (without dynamic memory) seems to yield much better results (around 30% more). Additional fine tuning will be required in the future. Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 8a39d1e40a68..b1b5139139e7 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -954,6 +954,7 @@ out: int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) { struct wl1271_acx_ap_config_memory *mem_conf; + struct conf_memory_settings *mem; int ret; wl1271_debug(DEBUG_ACX, "wl1271 mem cfg"); @@ -964,14 +965,21 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) goto out; } + if (wl->chip.id == CHIP_ID_1283_PG20) + /* + * FIXME: The 128x AP FW does not yet support dynamic memory. + * Use the base memory configuration for 128x for now. This + * should be fine tuned in the future. + */ + mem = &wl->conf.mem_wl128x; + else + mem = &wl->conf.mem_wl127x; + /* memory config */ - /* FIXME: for now we always use mem_wl127x for AP, because it - * doesn't support dynamic memory and we don't have the - * optimal values for wl128x without dynamic memory yet */ - mem_conf->num_stations = wl->conf.mem_wl127x.num_stations; - mem_conf->rx_mem_block_num = wl->conf.mem_wl127x.rx_block_num; - mem_conf->tx_min_mem_block_num = wl->conf.mem_wl127x.tx_min_block_num; - mem_conf->num_ssid_profiles = wl->conf.mem_wl127x.ssid_profiles; + mem_conf->num_stations = mem->num_stations; + mem_conf->rx_mem_block_num = mem->rx_block_num; + mem_conf->tx_min_mem_block_num = mem->tx_min_block_num; + mem_conf->num_ssid_profiles = mem->ssid_profiles; mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, -- cgit v1.2.3-58-ga151 From ef2e3004855e90d2919105e4a91d7df6ab9845a9 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Mon, 18 Apr 2011 16:44:11 +0300 Subject: wl12xx: Restart TX when TX descriptors are available The driver stops sending TX packets when either there aren't enough memory blocks, or it runs out of TX descriptors. The driver continues to send packets to the FW only when more memory blocks are available. The FW might free TX descriptors without freeing the corresponding memory blocks, especially when dynamic memory is enabled. In cases where memory blocks are not freed at all, the driver will keep waiting for more memory blocks indefinitely. Fix this by clearing the WL1271_FLAG_FW_TX_BUSY flag when there are available TX descriptors. Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/tx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index c83665964467..cc837bba5468 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -65,6 +65,9 @@ static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb) static void wl1271_free_tx_id(struct wl1271 *wl, int id) { if (__test_and_clear_bit(id, wl->tx_frames_map)) { + if (unlikely(wl->tx_frames_cnt == ACX_TX_DESCRIPTORS)) + clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); + wl->tx_frames[id] = NULL; wl->tx_frames_cnt--; } -- cgit v1.2.3-58-ga151 From 4cf557fcf01e352fb418e110dd013e4128493c5f Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Mon, 18 Apr 2011 16:45:10 +0300 Subject: wl12xx: Enable dynamic memory for 127x The FW can dynamically manage its internal TX & RX memory pools, moving blocks from one pool to another when necessary. This can significantly improve performance. Currently this feature is enabled only for 128x. Enable dynamic memory for 127x as well. Other parameters in the memory configuration structure may need to be fine tuned, as the optimal values for these may change once dynamic memory is enabled. Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index c0cfcc7e11ac..6dd72365b63a 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -305,7 +305,7 @@ static struct conf_drv_settings default_conf = { .ssid_profiles = 1, .rx_block_num = 70, .tx_min_block_num = 40, - .dynamic_memory = 0, + .dynamic_memory = 1, .min_req_tx_blocks = 100, .min_req_rx_blocks = 22, .tx_min = 27, -- cgit v1.2.3-58-ga151 From 33437893025aa3c0195b933ac99ef7de924019f4 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 26 Apr 2011 23:35:39 +0300 Subject: wl12xx: implement the tx_frames_pending mac80211 callback Frames are considered pending when they reside in the driver TX queue or already queued in the FW. This notion of "pending" is appropriate for power save considerations in STA mode, but not necessarily in other modes (for instance P2P-GO). [Fixed a sparse warning about missing "static" in a function declaration -- Luca] Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 6dd72365b63a..e177764e7140 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3147,6 +3147,28 @@ out: return ret; } +static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) +{ + struct wl1271 *wl = hw->priv; + bool ret = false; + + mutex_lock(&wl->mutex); + + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + + /* packets are considered pending if in the TX queue or the FW */ + ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0); + + /* the above is appropriate for STA mode for PS purposes */ + WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); + +out: + mutex_unlock(&wl->mutex); + + return ret; +} + /* can't be const, mac80211 writes to this */ static struct ieee80211_rate wl1271_rates[] = { { .bitrate = 10, @@ -3398,6 +3420,7 @@ static const struct ieee80211_ops wl1271_ops = { .sta_add = wl1271_op_sta_add, .sta_remove = wl1271_op_sta_remove, .ampdu_action = wl1271_op_ampdu_action, + .tx_frames_pending = wl1271_tx_frames_pending, CFG80211_TESTMODE_CMD(wl1271_tm_cmd) }; -- cgit v1.2.3-58-ga151 From 34c8e3d2bb901b2920d2a8930c0de82e7fefac76 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 26 Apr 2011 23:35:40 +0300 Subject: wl12xx: discard corrupted packets in RX When packets arrive with a RX descriptor indicating corruption, discard them. In general white-list the RX descriptor status to prevent rouge data from being sent up. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/rx.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index faf5a1d3c2c3..70091035e019 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -76,12 +76,15 @@ static void wl1271_rx_status(struct wl1271 *wl, status->band); if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { - status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; + u8 desc_err_code = desc->status & WL1271_RX_DESC_STATUS_MASK; - if (likely(!(desc->status & WL1271_RX_DESC_DECRYPT_FAIL))) - status->flag |= RX_FLAG_DECRYPTED; - if (unlikely(desc->status & WL1271_RX_DESC_MIC_FAIL)) + status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED | + RX_FLAG_DECRYPTED; + + if (unlikely(desc_err_code == WL1271_RX_DESC_MIC_FAIL)) { status->flag |= RX_FLAG_MMIC_ERROR; + wl1271_warning("Michael MIC error"); + } } } @@ -100,6 +103,25 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) if (unlikely(wl->state == WL1271_STATE_PLT)) return -EINVAL; + /* the data read starts with the descriptor */ + desc = (struct wl1271_rx_descriptor *) data; + + switch (desc->status & WL1271_RX_DESC_STATUS_MASK) { + /* discard corrupted packets */ + case WL1271_RX_DESC_DRIVER_RX_Q_FAIL: + case WL1271_RX_DESC_DECRYPT_FAIL: + wl1271_warning("corrupted packet in RX with status: 0x%x", + desc->status & WL1271_RX_DESC_STATUS_MASK); + return -EINVAL; + case WL1271_RX_DESC_SUCCESS: + case WL1271_RX_DESC_MIC_FAIL: + break; + default: + wl1271_error("invalid RX descriptor status: 0x%x", + desc->status & WL1271_RX_DESC_STATUS_MASK); + return -EINVAL; + } + skb = __dev_alloc_skb(length, GFP_KERNEL); if (!skb) { wl1271_error("Couldn't allocate RX frame"); @@ -109,9 +131,6 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) buf = skb_put(skb, length); memcpy(buf, data, length); - /* the data read starts with the descriptor */ - desc = (struct wl1271_rx_descriptor *) buf; - /* now we pull the descriptor out of the buffer */ skb_pull(skb, sizeof(*desc)); -- cgit v1.2.3-58-ga151 From 86c438f40cf3e0f6ce2da80f2d759e61d3e85ad7 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 26 Apr 2011 23:27:44 +0200 Subject: wl12xx: do not set queue_mapping directly It is preferred to use the setter that to set queue_mapping directly. This also helps backporting in compat-wireless. Signed-off-by: Hauke Mehrtens Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index e177764e7140..a8770102a74a 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1294,7 +1294,7 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) skb->priority = WL1271_TID_MGMT; /* Initialize all fields that might be used */ - skb->queue_mapping = 0; + skb_set_queue_mapping(skb, 0); memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info)); return skb; -- cgit v1.2.3-58-ga151 From f7c7c7e69cbc3c5b660a32cc2cb31720b2b420c8 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 29 Apr 2011 22:25:28 +0300 Subject: wl12xx: strict_stroul introduced converted to kstrtoul One new patch applied added a couple of new strict_strtoul calls. Converted those to kstroul(). Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 88c6efe33ecc..b17cff6cd756 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -321,7 +321,7 @@ static ssize_t dtim_interval_write(struct file *file, return -EFAULT; buf[len] = '\0'; - ret = strict_strtoul(buf, 0, &value); + ret = kstrtoul(buf, 0, &value); if (ret < 0) { wl1271_warning("illegal value for dtim_interval"); return -EINVAL; @@ -386,7 +386,7 @@ static ssize_t beacon_interval_write(struct file *file, return -EFAULT; buf[len] = '\0'; - ret = strict_strtoul(buf, 0, &value); + ret = kstrtoul(buf, 0, &value); if (ret < 0) { wl1271_warning("illegal value for beacon_interval"); return -EINVAL; -- cgit v1.2.3-58-ga151 From 801f870bc0524bad7ebef9cea52d20e4d4992e4a Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 18 Apr 2011 14:15:20 +0300 Subject: wl12xx: add BT-coexistance for AP Initialize AP specific BT coexitance parameters to default values and enable them in AP mode. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 40 ++++++++++++++++++++++---- drivers/net/wireless/wl12xx/acx.h | 16 +++++++++-- drivers/net/wireless/wl12xx/conf.h | 35 +++++++++++++++++++++-- drivers/net/wireless/wl12xx/init.c | 15 ++++++---- drivers/net/wireless/wl12xx/main.c | 57 +++++++++++++++++++++++++++++++++++++- 5 files changed, 146 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index b1b5139139e7..2b5fb3d2df1b 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -540,13 +540,13 @@ out: return ret; } -int wl1271_acx_sg_cfg(struct wl1271 *wl) +int wl1271_acx_sta_sg_cfg(struct wl1271 *wl) { - struct acx_bt_wlan_coex_param *param; + struct acx_sta_bt_wlan_coex_param *param; struct conf_sg_settings *c = &wl->conf.sg; int i, ret; - wl1271_debug(DEBUG_ACX, "acx sg cfg"); + wl1271_debug(DEBUG_ACX, "acx sg sta cfg"); param = kzalloc(sizeof(*param), GFP_KERNEL); if (!param) { @@ -555,8 +555,38 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) } /* BT-WLAN coext parameters */ - for (i = 0; i < CONF_SG_PARAMS_MAX; i++) - param->params[i] = cpu_to_le32(c->params[i]); + for (i = 0; i < CONF_SG_STA_PARAMS_MAX; i++) + param->params[i] = cpu_to_le32(c->sta_params[i]); + param->param_idx = CONF_SG_PARAMS_ALL; + + ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); + if (ret < 0) { + wl1271_warning("failed to set sg config: %d", ret); + goto out; + } + +out: + kfree(param); + return ret; +} + +int wl1271_acx_ap_sg_cfg(struct wl1271 *wl) +{ + struct acx_ap_bt_wlan_coex_param *param; + struct conf_sg_settings *c = &wl->conf.sg; + int i, ret; + + wl1271_debug(DEBUG_ACX, "acx sg ap cfg"); + + param = kzalloc(sizeof(*param), GFP_KERNEL); + if (!param) { + ret = -ENOMEM; + goto out; + } + + /* BT-WLAN coext parameters */ + for (i = 0; i < CONF_SG_AP_PARAMS_MAX; i++) + param->params[i] = cpu_to_le32(c->ap_params[i]); param->param_idx = CONF_SG_PARAMS_ALL; ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 2dde0346e955..cd7548dacd59 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -370,14 +370,23 @@ struct acx_bt_wlan_coex { u8 pad[3]; } __packed; -struct acx_bt_wlan_coex_param { +struct acx_sta_bt_wlan_coex_param { struct acx_header header; - __le32 params[CONF_SG_PARAMS_MAX]; + __le32 params[CONF_SG_STA_PARAMS_MAX]; u8 param_idx; u8 padding[3]; } __packed; +struct acx_ap_bt_wlan_coex_param { + struct acx_header header; + + __le32 params[CONF_SG_AP_PARAMS_MAX]; + u8 param_idx; + u8 padding[3]; +} __packed; + + struct acx_dco_itrim_params { struct acx_header header; @@ -1330,7 +1339,8 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); int wl1271_acx_beacon_filter_table(struct wl1271 *wl); int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); -int wl1271_acx_sg_cfg(struct wl1271 *wl); +int wl1271_acx_sta_sg_cfg(struct wl1271 *wl); +int wl1271_acx_ap_sg_cfg(struct wl1271 *wl); int wl1271_acx_cca_threshold(struct wl1271 *wl); int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); int wl1271_acx_aid(struct wl1271 *wl, u16 aid); diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index a4e0acff8674..2ffbe3e06019 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -396,12 +396,43 @@ enum { CONF_SG_TEMP_PARAM_3, CONF_SG_TEMP_PARAM_4, CONF_SG_TEMP_PARAM_5, - CONF_SG_PARAMS_MAX, + + /* + * AP beacon miss + * + * Range: 0 - 255 + */ + CONF_SG_AP_BEACON_MISS_TX, + + /* + * AP RX window length + * + * Range: 0 - 50 + */ + CONF_SG_RX_WINDOW_LENGTH, + + /* + * AP connection protection time + * + * Range: 0 - 5000 + */ + CONF_SG_AP_CONNECTION_PROTECTION_TIME, + + CONF_SG_TEMP_PARAM_6, + CONF_SG_TEMP_PARAM_7, + CONF_SG_TEMP_PARAM_8, + CONF_SG_TEMP_PARAM_9, + CONF_SG_TEMP_PARAM_10, + + CONF_SG_STA_PARAMS_MAX = CONF_SG_TEMP_PARAM_5 + 1, + CONF_SG_AP_PARAMS_MAX = CONF_SG_TEMP_PARAM_10 + 1, + CONF_SG_PARAMS_ALL = 0xff }; struct conf_sg_settings { - u32 params[CONF_SG_PARAMS_MAX]; + u32 sta_params[CONF_SG_STA_PARAMS_MAX]; + u32 ap_params[CONF_SG_AP_PARAMS_MAX]; u8 state; }; diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 46fd7212b238..1be656914785 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -285,7 +285,10 @@ int wl1271_init_pta(struct wl1271 *wl) { int ret; - ret = wl1271_acx_sg_cfg(wl); + if (wl->bss_type == BSS_TYPE_AP_BSS) + ret = wl1271_acx_ap_sg_cfg(wl); + else + ret = wl1271_acx_sta_sg_cfg(wl); if (ret < 0) return ret; @@ -351,11 +354,6 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - /* Bluetooth WLAN coexistence */ - ret = wl1271_init_pta(wl); - if (ret < 0) - return ret; - /* FM WLAN coexistence */ ret = wl1271_acx_fm_coex(wl); if (ret < 0) @@ -572,6 +570,11 @@ int wl1271_hw_init(struct wl1271 *wl) if (ret < 0) return ret; + /* Bluetooth WLAN coexistence */ + ret = wl1271_init_pta(wl); + if (ret < 0) + return ret; + /* Default memory configuration */ ret = wl1271_acx_init_mem_config(wl); if (ret < 0) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index a8770102a74a..5f8bb35c6475 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -51,7 +51,7 @@ static struct conf_drv_settings default_conf = { .sg = { - .params = { + .sta_params = { [CONF_SG_BT_PER_THRESHOLD] = 7500, [CONF_SG_HV3_MAX_OVERRIDE] = 0, [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, @@ -101,6 +101,61 @@ static struct conf_drv_settings default_conf = { [CONF_SG_DHCP_TIME] = 5000, [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, }, + .ap_params = { + [CONF_SG_BT_PER_THRESHOLD] = 7500, + [CONF_SG_HV3_MAX_OVERRIDE] = 0, + [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, + [CONF_SG_BT_LOAD_RATIO] = 50, + [CONF_SG_AUTO_PS_MODE] = 1, + [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, + [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, + [CONF_SG_ANTENNA_CONFIGURATION] = 0, + [CONF_SG_BEACON_MISS_PERCENT] = 60, + [CONF_SG_RATE_ADAPT_THRESH] = 64, + [CONF_SG_RATE_ADAPT_SNR] = 1, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 25, + [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 25, + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20, + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 25, + [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 25, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25, + [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 25, + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8, + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 25, + [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 25, + [CONF_SG_RXT] = 1200, + [CONF_SG_TXT] = 1000, + [CONF_SG_ADAPTIVE_RXT_TXT] = 1, + [CONF_SG_PS_POLL_TIMEOUT] = 10, + [CONF_SG_UPSD_TIMEOUT] = 10, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15, + [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15, + [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8, + [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20, + [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50, + [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10, + [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, + [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800, + [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75, + [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15, + [CONF_SG_HV3_MAX_SERVED] = 6, + [CONF_SG_DHCP_TIME] = 5000, + [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, + [CONF_SG_TEMP_PARAM_1] = 0, + [CONF_SG_TEMP_PARAM_2] = 0, + [CONF_SG_TEMP_PARAM_3] = 0, + [CONF_SG_TEMP_PARAM_4] = 0, + [CONF_SG_TEMP_PARAM_5] = 0, + [CONF_SG_AP_BEACON_MISS_TX] = 3, + [CONF_SG_RX_WINDOW_LENGTH] = 6, + [CONF_SG_AP_CONNECTION_PROTECTION_TIME] = 50, + [CONF_SG_TEMP_PARAM_6] = 1, + }, .state = CONF_SG_PROTECTIVE, }, .rx = { -- cgit v1.2.3-58-ga151 From 5f704d180e448d05859e1cb6572822ba27dbcdc7 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 18 Apr 2011 14:15:21 +0300 Subject: wl12xx: use wiphy values for setting rts, frag thresholds on init Use the wiphy RTS and fragmentation thresholds for initializing the FW when possible. This mitigates a bug where previously set values are forgotten after interface down/up. Add checks before settings these values to ensure they are valid. Use default values when invalid thresholds are configured. Update the default RTS threshold to the maximum value given by the specification. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 26 ++++++++++++++++++++------ drivers/net/wireless/wl12xx/acx.h | 4 ++-- drivers/net/wireless/wl12xx/init.c | 4 ++-- drivers/net/wireless/wl12xx/main.c | 6 +++--- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 2b5fb3d2df1b..729f72a7b912 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -325,12 +325,19 @@ out: return ret; } -int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold) +int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold) { struct acx_rts_threshold *rts; int ret; - wl1271_debug(DEBUG_ACX, "acx rts threshold"); + /* + * If the RTS threshold is not configured or out of range, use the + * default value. + */ + if (rts_threshold > IEEE80211_MAX_RTS_THRESHOLD) + rts_threshold = wl->conf.rx.rts_threshold; + + wl1271_debug(DEBUG_ACX, "acx rts threshold: %d", rts_threshold); rts = kzalloc(sizeof(*rts), GFP_KERNEL); if (!rts) { @@ -338,7 +345,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold) goto out; } - rts->threshold = cpu_to_le16(rts_threshold); + rts->threshold = cpu_to_le16((u16)rts_threshold); ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); if (ret < 0) { @@ -928,12 +935,19 @@ out: return ret; } -int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold) +int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold) { struct acx_frag_threshold *acx; int ret = 0; - wl1271_debug(DEBUG_ACX, "acx frag threshold"); + /* + * If the fragmentation is not configured or out of range, use the + * default value. + */ + if (frag_threshold > IEEE80211_MAX_FRAG_THRESHOLD) + frag_threshold = wl->conf.tx.frag_threshold; + + wl1271_debug(DEBUG_ACX, "acx frag threshold: %d", frag_threshold); acx = kzalloc(sizeof(*acx), GFP_KERNEL); @@ -942,7 +956,7 @@ int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold) goto out; } - acx->frag_threshold = cpu_to_le16(frag_threshold); + acx->frag_threshold = cpu_to_le16((u16)frag_threshold); ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx)); if (ret < 0) { wl1271_warning("Setting of frag threshold failed: %d", ret); diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index cd7548dacd59..828367d62668 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -1333,7 +1333,7 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time); int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, void *mc_list, u32 mc_list_len); int wl1271_acx_service_period_timeout(struct wl1271 *wl); -int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); +int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold); int wl1271_acx_dco_itrim_params(struct wl1271 *wl); int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); int wl1271_acx_beacon_filter_table(struct wl1271 *wl); @@ -1357,7 +1357,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, u8 tsid, u8 ps_scheme, u8 ack_policy, u32 apsd_conf0, u32 apsd_conf1); -int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold); +int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold); int wl1271_acx_tx_config_options(struct wl1271 *wl); int wl1271_acx_ap_mem_cfg(struct wl1271 *wl); int wl1271_acx_sta_mem_cfg(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 1be656914785..060ca31818eb 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -258,7 +258,7 @@ int wl1271_init_phy_config(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_acx_rts_threshold(wl, wl->conf.rx.rts_threshold); + ret = wl1271_acx_rts_threshold(wl, wl->hw->wiphy->rts_threshold); if (ret < 0) return ret; @@ -614,7 +614,7 @@ int wl1271_hw_init(struct wl1271 *wl) goto out_free_memmap; /* Default fragmentation threshold */ - ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); + ret = wl1271_acx_frag_threshold(wl, wl->hw->wiphy->frag_threshold); if (ret < 0) goto out_free_memmap; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 5f8bb35c6475..81a0c8ed5a4a 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -163,7 +163,7 @@ static struct conf_drv_settings default_conf = { .packet_detection_threshold = 0, .ps_poll_timeout = 15, .upsd_timeout = 15, - .rts_threshold = 2347, + .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD, .rx_cca_threshold = 0, .irq_blk_threshold = 0xFFFF, .irq_pkt_threshold = 0, @@ -2360,7 +2360,7 @@ static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) if (ret < 0) goto out; - ret = wl1271_acx_frag_threshold(wl, (u16)value); + ret = wl1271_acx_frag_threshold(wl, value); if (ret < 0) wl1271_warning("wl1271_op_set_frag_threshold failed: %d", ret); @@ -2388,7 +2388,7 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) if (ret < 0) goto out; - ret = wl1271_acx_rts_threshold(wl, (u16) value); + ret = wl1271_acx_rts_threshold(wl, value); if (ret < 0) wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); -- cgit v1.2.3-58-ga151 From 521a4a23261354885c01bf75b42150629004ed83 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 18 Apr 2011 14:15:22 +0300 Subject: wl12xx: AP-mode - disable beacon filtering on start up New AP-mode FWs filter external beacons by default. Disable this filtering on start up so we can properly configure ERP protection. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 25 +++++++++++++++++++++++++ drivers/net/wireless/wl12xx/acx.h | 10 +++++++++- drivers/net/wireless/wl12xx/init.c | 8 ++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 729f72a7b912..6860d7e9df70 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -1679,6 +1679,31 @@ out: return ret; } +int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable) +{ + struct acx_ap_beacon_filter *acx = NULL; + int ret; + + wl1271_debug(DEBUG_ACX, "acx set ap beacon filter: %d", enable); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) + return -ENOMEM; + + acx->enable = enable ? 1 : 0; + + ret = wl1271_cmd_configure(wl, ACX_AP_BEACON_FILTER_OPT, + acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx set ap beacon filter failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} + int wl1271_acx_fm_coex(struct wl1271 *wl) { struct wl1271_acx_fm_coex *acx; diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 828367d62668..75338f9947cf 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -303,7 +303,6 @@ struct acx_beacon_filter_option { struct acx_header header; u8 enable; - /* * The number of beacons without the unicast TIM * bit set that the firmware buffers before @@ -1188,6 +1187,13 @@ struct wl1271_acx_inconnection_sta { u8 padding1[2]; } __packed; +struct acx_ap_beacon_filter { + struct acx_header header; + + u8 enable; + u8 pad[3]; +} __packed; + /* * ACX_FM_COEX_CFG * set the FM co-existence parameters. @@ -1265,6 +1271,7 @@ enum { ACX_TID_CFG = 0x001A, ACX_PS_RX_STREAMING = 0x001B, ACX_BEACON_FILTER_OPT = 0x001F, + ACX_AP_BEACON_FILTER_OPT = 0x0020, ACX_NOISE_HIST = 0x0021, ACX_HDK_VERSION = 0x0022, /* ??? */ ACX_PD_THRESHOLD = 0x0023, @@ -1388,6 +1395,7 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl); int wl1271_acx_config_ps(struct wl1271 *wl); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); +int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable); int wl1271_acx_fm_coex(struct wl1271 *wl); #endif /* __WL1271_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 060ca31818eb..e0de041e38f1 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -475,6 +475,14 @@ static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) if (ret < 0) return ret; + /* + * when operating as AP we want to receive external beacons for + * configuring ERP protection. + */ + ret = wl1271_acx_set_ap_beacon_filter(wl, false); + if (ret < 0) + return ret; + return 0; } -- cgit v1.2.3-58-ga151 From f482b76202f4ac0f62a77b0e55ac1a1cfe480e2b Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 18 Apr 2011 14:15:23 +0300 Subject: wl12xx: schedule recovery on command timeout We use a long timeout (2 seconds) when sending commands to the FW. When a command times out, it means the FW is stuck, and we should commence recovery. This should make recovery times shorter as we'll recover on the first timeout indication. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index a9ffdd86f9b8..d8596ae3a64f 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -76,7 +76,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, if (time_after(jiffies, timeout)) { wl1271_error("command complete timeout"); ret = -ETIMEDOUT; - goto out; + goto fail; } poll_count++; @@ -96,14 +96,17 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, status = le16_to_cpu(cmd->status); if (status != CMD_STATUS_SUCCESS) { wl1271_error("command execute failure %d", status); - ieee80211_queue_work(wl->hw, &wl->recovery_work); ret = -EIO; + goto fail; } wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, WL1271_ACX_INTR_CMD_COMPLETE); + return 0; -out: +fail: + WARN_ON(1); + ieee80211_queue_work(wl->hw, &wl->recovery_work); return ret; } -- cgit v1.2.3-58-ga151 From 52dcaf577f3b6d878a337a44a99a122017c85ff6 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 18 Apr 2011 14:15:24 +0300 Subject: wl12xx: print firmware program counter during recovery When performing recovery, print the firmware version and program counter (by reading the SCR_PAD4 register). The value of the firmware program counter during assert can be useful for debugging. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 81a0c8ed5a4a..7b88dd2e85ee 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1004,7 +1004,8 @@ static void wl1271_recovery_work(struct work_struct *work) if (wl->state != WL1271_STATE_ON) goto out; - wl1271_info("Hardware recovery in progress."); + wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", + wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) ieee80211_connection_loss(wl->vif); -- cgit v1.2.3-58-ga151 From 70f474241b3d5fb633635a2ce39ea9da4afeea6c Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 18 Apr 2011 14:15:25 +0300 Subject: wl12xx: AP-mode - overhaul rate policy configuration Use the minimal rate configured in the basic rates set as the AP broadcast and multicast rate. The minimal rate is used to ensure weak links can still communicate. When the basic rates contains at least one OFDM rate, configure all unicast TX rates to OFDM only. Unify rate configuration on initialization and on change notification into a single function. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 3 +- drivers/net/wireless/wl12xx/conf.h | 22 ++++-------- drivers/net/wireless/wl12xx/init.c | 71 ++++++++++++++++++++++++++++---------- drivers/net/wireless/wl12xx/init.h | 1 + drivers/net/wireless/wl12xx/main.c | 53 ++-------------------------- 5 files changed, 65 insertions(+), 85 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 6860d7e9df70..ec0156b3e276 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -841,7 +841,8 @@ int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, struct acx_ap_rate_policy *acx; int ret = 0; - wl1271_debug(DEBUG_ACX, "acx ap rate policy"); + wl1271_debug(DEBUG_ACX, "acx ap rate policy %d rates 0x%x", + idx, c->enabled_rates); acx = kzalloc(sizeof(*acx), GFP_KERNEL); if (!acx) { diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 2ffbe3e06019..c0045f0b8b4e 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -540,6 +540,12 @@ struct conf_rx_settings { CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ CONF_HW_BIT_RATE_54MBPS) +#define CONF_TX_OFDM_RATES (CONF_HW_BIT_RATE_6MBPS | \ + CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS | \ + CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ + CONF_HW_BIT_RATE_54MBPS) + + /* * Default rates for management traffic when operating in AP mode. This * should be configured according to the basic rate set of the AP @@ -704,22 +710,6 @@ struct conf_tx_settings { u8 ac_conf_count; struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT]; - /* - * Configuration for rate classes in AP-mode. These rate classes - * are for the AC TX queues - */ - struct conf_tx_rate_class ap_rc_conf[CONF_TX_MAX_AC_COUNT]; - - /* - * Management TX rate class for AP-mode. - */ - struct conf_tx_rate_class ap_mgmt_conf; - - /* - * Broadcast TX rate class for AP-mode. - */ - struct conf_tx_rate_class ap_bcst_conf; - /* * Allow this number of TX retries to a connected station/AP before an * event is triggered from FW. diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index e0de041e38f1..5d0ecd2018bf 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -417,7 +417,7 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl) static int wl1271_ap_hw_init(struct wl1271 *wl) { - int ret, i; + int ret; ret = wl1271_ap_init_templates_config(wl); if (ret < 0) @@ -428,23 +428,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - /* Configure initial TX rate classes */ - for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { - ret = wl1271_acx_ap_rate_policy(wl, - &wl->conf.tx.ap_rc_conf[i], i); - if (ret < 0) - return ret; - } - - ret = wl1271_acx_ap_rate_policy(wl, - &wl->conf.tx.ap_mgmt_conf, - ACX_TX_AP_MODE_MGMT_RATE); - if (ret < 0) - return ret; - - ret = wl1271_acx_ap_rate_policy(wl, - &wl->conf.tx.ap_bcst_conf, - ACX_TX_AP_MODE_BCST_RATE); + ret = wl1271_init_ap_rates(wl); if (ret < 0) return ret; @@ -486,6 +470,57 @@ static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) return 0; } +int wl1271_init_ap_rates(struct wl1271 *wl) +{ + int i, ret; + struct conf_tx_rate_class rc; + u32 supported_rates; + + wl1271_debug(DEBUG_AP, "AP basic rate set: 0x%x", wl->basic_rate_set); + + if (wl->basic_rate_set == 0) + return -EINVAL; + + rc.enabled_rates = wl->basic_rate_set; + rc.long_retry_limit = 10; + rc.short_retry_limit = 10; + rc.aflags = 0; + ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_MGMT_RATE); + if (ret < 0) + return ret; + + /* use the min basic rate for AP broadcast/multicast */ + rc.enabled_rates = wl1271_tx_min_rate_get(wl); + rc.short_retry_limit = 10; + rc.long_retry_limit = 10; + rc.aflags = 0; + ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_BCST_RATE); + if (ret < 0) + return ret; + + /* + * If the basic rates contain OFDM rates, use OFDM only + * rates for unicast TX as well. Else use all supported rates. + */ + if ((wl->basic_rate_set & CONF_TX_OFDM_RATES)) + supported_rates = CONF_TX_OFDM_RATES; + else + supported_rates = CONF_TX_AP_ENABLED_RATES; + + /* configure unicast TX rate classes */ + for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { + rc.enabled_rates = supported_rates; + rc.short_retry_limit = 10; + rc.long_retry_limit = 10; + rc.aflags = 0; + ret = wl1271_acx_ap_rate_policy(wl, &rc, i); + if (ret < 0) + return ret; + } + + return 0; +} + static void wl1271_check_ba_support(struct wl1271 *wl) { /* validate FW cose ver x.x.x.50-60.x */ diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h index 4975270a91ab..0dd2414a30d1 100644 --- a/drivers/net/wireless/wl12xx/init.h +++ b/drivers/net/wireless/wl12xx/init.h @@ -33,5 +33,6 @@ int wl1271_init_pta(struct wl1271 *wl); int wl1271_init_energy_detection(struct wl1271 *wl); int wl1271_chip_specific_init(struct wl1271 *wl); int wl1271_hw_init(struct wl1271 *wl); +int wl1271_init_ap_rates(struct wl1271 *wl); #endif diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 7b88dd2e85ee..e9d4cf48ba35 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -209,44 +209,6 @@ static struct conf_drv_settings default_conf = { .tx_op_limit = 1504, }, }, - .ap_rc_conf = { - [0] = { - .enabled_rates = CONF_TX_AP_ENABLED_RATES, - .short_retry_limit = 10, - .long_retry_limit = 10, - .aflags = 0, - }, - [1] = { - .enabled_rates = CONF_TX_AP_ENABLED_RATES, - .short_retry_limit = 10, - .long_retry_limit = 10, - .aflags = 0, - }, - [2] = { - .enabled_rates = CONF_TX_AP_ENABLED_RATES, - .short_retry_limit = 10, - .long_retry_limit = 10, - .aflags = 0, - }, - [3] = { - .enabled_rates = CONF_TX_AP_ENABLED_RATES, - .short_retry_limit = 10, - .long_retry_limit = 10, - .aflags = 0, - }, - }, - .ap_mgmt_conf = { - .enabled_rates = CONF_TX_AP_DEFAULT_MGMT_RATES, - .short_retry_limit = 10, - .long_retry_limit = 10, - .aflags = 0, - }, - .ap_bcst_conf = { - .enabled_rates = CONF_HW_BIT_RATE_1MBPS, - .short_retry_limit = 10, - .long_retry_limit = 10, - .aflags = 0, - }, .max_tx_retries = 100, .ap_aging_period = 300, .tid_conf_count = 4, @@ -2532,22 +2494,13 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, if ((changed & BSS_CHANGED_BASIC_RATES)) { u32 rates = bss_conf->basic_rates; - struct conf_tx_rate_class mgmt_rc; wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); wl->basic_rate = wl1271_tx_min_rate_get(wl); - wl1271_debug(DEBUG_AP, "basic rates: 0x%x", - wl->basic_rate_set); - - /* update the AP management rate policy with the new rates */ - mgmt_rc.enabled_rates = wl->basic_rate_set; - mgmt_rc.long_retry_limit = 10; - mgmt_rc.short_retry_limit = 10; - mgmt_rc.aflags = 0; - ret = wl1271_acx_ap_rate_policy(wl, &mgmt_rc, - ACX_TX_AP_MODE_MGMT_RATE); + + ret = wl1271_init_ap_rates(wl); if (ret < 0) { - wl1271_error("AP mgmt policy change failed %d", ret); + wl1271_error("AP rate policy change failed %d", ret); goto out; } } -- cgit v1.2.3-58-ga151 From c45a85b5a3c0ca841a7ffc700bdece8ee01486be Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 18 Apr 2011 14:15:26 +0300 Subject: wl12xx: AP-mode - reconfigure templates after basic rates change When there's a change in the basic rates of the AP, reconfigure relevant templates with the new rates. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/init.c | 7 ++++++- drivers/net/wireless/wl12xx/init.h | 1 + drivers/net/wireless/wl12xx/main.c | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 5d0ecd2018bf..b1242a6de27b 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -443,7 +443,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) return 0; } -static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) +int wl1271_ap_init_templates(struct wl1271 *wl) { int ret; @@ -470,6 +470,11 @@ static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) return 0; } +static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) +{ + return wl1271_ap_init_templates(wl); +} + int wl1271_init_ap_rates(struct wl1271 *wl) { int i, ret; diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h index 0dd2414a30d1..3a3c230fd292 100644 --- a/drivers/net/wireless/wl12xx/init.h +++ b/drivers/net/wireless/wl12xx/init.h @@ -34,5 +34,6 @@ int wl1271_init_energy_detection(struct wl1271 *wl); int wl1271_chip_specific_init(struct wl1271 *wl); int wl1271_hw_init(struct wl1271 *wl); int wl1271_init_ap_rates(struct wl1271 *wl); +int wl1271_ap_init_templates(struct wl1271 *wl); #endif diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index e9d4cf48ba35..433bc035741a 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2503,6 +2503,10 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, wl1271_error("AP rate policy change failed %d", ret); goto out; } + + ret = wl1271_ap_init_templates(wl); + if (ret < 0) + goto out; } ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); -- cgit v1.2.3-58-ga151 From 2dc5a5c2c656b9029a0e635bb3a1cbcfbcb4ca5c Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 18 Apr 2011 14:15:27 +0300 Subject: wl12xx: add debugfs entry for starting recovery This entry is useful for debugging the driver state machine during recovery. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index b17cff6cd756..a2b55e556714 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -291,6 +291,25 @@ static const struct file_operations gpio_power_ops = { .llseek = default_llseek, }; +static ssize_t start_recovery_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + + mutex_lock(&wl->mutex); + ieee80211_queue_work(wl->hw, &wl->recovery_work); + mutex_unlock(&wl->mutex); + + return count; +} + +static const struct file_operations start_recovery_ops = { + .write = start_recovery_write, + .open = wl1271_open_file_generic, + .llseek = default_llseek, +}; + static ssize_t dtim_interval_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -529,6 +548,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, DEBUGFS_ADD(excessive_retries, rootdir); DEBUGFS_ADD(gpio_power, rootdir); + DEBUGFS_ADD(start_recovery, rootdir); DEBUGFS_ADD(dtim_interval, rootdir); DEBUGFS_ADD(beacon_interval, rootdir); -- cgit v1.2.3-58-ga151 From 7dece1c8e1044287287d44ac183a946333b55fc3 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 18 Apr 2011 14:15:28 +0300 Subject: wl12xx: fix race condition during recovery in AP mode When operating as AP, the TX queues are not stopped when we start recovery. mac80211 is notified only after the fact. When there is pending TX, it will be queued even after the FW is down. This leads to situations where the TX queues are stopped (because of the TX-watermark mechanism), and are never woken up when we return from recovery. Fix this by explicitly stopping the TX queues when before initiating recovery. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 21 ++++++++++++++++----- drivers/net/wireless/wl12xx/tx.c | 8 +++++--- drivers/net/wireless/wl12xx/tx.h | 2 +- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 433bc035741a..6dd42c987663 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -352,7 +352,8 @@ static struct conf_drv_settings default_conf = { .hci_io_ds = HCI_IO_DS_6MA, }; -static void __wl1271_op_remove_interface(struct wl1271 *wl); +static void __wl1271_op_remove_interface(struct wl1271 *wl, + bool reset_tx_queues); static void wl1271_free_ap_keys(struct wl1271 *wl); @@ -972,10 +973,19 @@ static void wl1271_recovery_work(struct work_struct *work) if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) ieee80211_connection_loss(wl->vif); + /* Prevent spurious TX during FW restart */ + ieee80211_stop_queues(wl->hw); + /* reboot the chipset */ - __wl1271_op_remove_interface(wl); + __wl1271_op_remove_interface(wl, false); ieee80211_restart_hw(wl->hw); + /* + * Its safe to enable TX now - the queues are stopped after a request + * to restart the HW. + */ + ieee80211_wake_queues(wl->hw); + out: mutex_unlock(&wl->mutex); } @@ -1479,7 +1489,8 @@ out: return ret; } -static void __wl1271_op_remove_interface(struct wl1271 *wl) +static void __wl1271_op_remove_interface(struct wl1271 *wl, + bool reset_tx_queues) { int i; @@ -1525,7 +1536,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) mutex_lock(&wl->mutex); /* let's notify MAC80211 about the remaining pending TX frames */ - wl1271_tx_reset(wl); + wl1271_tx_reset(wl, reset_tx_queues); wl1271_power_off(wl); memset(wl->bssid, 0, ETH_ALEN); @@ -1586,7 +1597,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, */ if (wl->vif) { WARN_ON(wl->vif != vif); - __wl1271_op_remove_interface(wl); + __wl1271_op_remove_interface(wl, true); } mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index cc837bba5468..ca3ab1c1acef 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -769,8 +769,8 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) wl1271_handle_tx_low_watermark(wl); } -/* caller must hold wl->mutex */ -void wl1271_tx_reset(struct wl1271 *wl) +/* caller must hold wl->mutex and TX must be stopped */ +void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) { int i; struct sk_buff *skb; @@ -806,8 +806,10 @@ void wl1271_tx_reset(struct wl1271 *wl) /* * Make sure the driver is at a consistent state, in case this * function is called from a context other than interface removal. + * This call will always wake the TX queues. */ - wl1271_handle_tx_low_watermark(wl); + if (reset_tx_queues) + wl1271_handle_tx_low_watermark(wl); for (i = 0; i < ACX_TX_DESCRIPTORS; i++) { if (wl->tx_frames[i] == NULL) diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index fc7835c4cf63..832f9258d675 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -185,7 +185,7 @@ static inline int wl1271_tx_get_queue(int queue) void wl1271_tx_work(struct work_struct *work); void wl1271_tx_work_locked(struct wl1271 *wl); void wl1271_tx_complete(struct wl1271 *wl); -void wl1271_tx_reset(struct wl1271 *wl); +void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues); void wl1271_tx_flush(struct wl1271 *wl); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); -- cgit v1.2.3-58-ga151 From 2d66bee7fbd38d28e9ed12f45b8e9db8e6aa0c49 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 18 Apr 2011 14:15:29 +0300 Subject: wl12xx: export driver state to debugfs By reading the "driver_state" debugfs value we get all the important state information from the wl12xx driver. This helps testing and debugging, particularly in situations where the driver seems "stuck". Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 87 +++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index a2b55e556714..b2f692babed7 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -310,6 +310,92 @@ static const struct file_operations start_recovery_ops = { .llseek = default_llseek, }; +static ssize_t driver_state_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + int res = 0; + char buf[1024]; + + mutex_lock(&wl->mutex); + +#define DRIVER_STATE_PRINT(x, fmt) \ + (res += scnprintf(buf + res, sizeof(buf) - res,\ + #x " = " fmt "\n", wl->x)) + +#define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld") +#define DRIVER_STATE_PRINT_INT(x) DRIVER_STATE_PRINT(x, "%d") +#define DRIVER_STATE_PRINT_STR(x) DRIVER_STATE_PRINT(x, "%s") +#define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx") +#define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") + + DRIVER_STATE_PRINT_INT(tx_blocks_available); + DRIVER_STATE_PRINT_INT(tx_allocated_blocks); + DRIVER_STATE_PRINT_INT(tx_frames_cnt); + DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]); + DRIVER_STATE_PRINT_INT(tx_queue_count); + DRIVER_STATE_PRINT_INT(tx_packets_count); + DRIVER_STATE_PRINT_INT(tx_results_count); + DRIVER_STATE_PRINT_LHEX(flags); + DRIVER_STATE_PRINT_INT(tx_blocks_freed[0]); + DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]); + DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]); + DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]); + DRIVER_STATE_PRINT_INT(tx_security_last_seq); + DRIVER_STATE_PRINT_INT(rx_counter); + DRIVER_STATE_PRINT_INT(session_counter); + DRIVER_STATE_PRINT_INT(state); + DRIVER_STATE_PRINT_INT(bss_type); + DRIVER_STATE_PRINT_INT(channel); + DRIVER_STATE_PRINT_HEX(rate_set); + DRIVER_STATE_PRINT_HEX(basic_rate_set); + DRIVER_STATE_PRINT_HEX(basic_rate); + DRIVER_STATE_PRINT_INT(band); + DRIVER_STATE_PRINT_INT(beacon_int); + DRIVER_STATE_PRINT_INT(psm_entry_retry); + DRIVER_STATE_PRINT_INT(ps_poll_failures); + DRIVER_STATE_PRINT_HEX(filters); + DRIVER_STATE_PRINT_HEX(rx_config); + DRIVER_STATE_PRINT_HEX(rx_filter); + DRIVER_STATE_PRINT_INT(power_level); + DRIVER_STATE_PRINT_INT(rssi_thold); + DRIVER_STATE_PRINT_INT(last_rssi_event); + DRIVER_STATE_PRINT_INT(sg_enabled); + DRIVER_STATE_PRINT_INT(enable_11a); + DRIVER_STATE_PRINT_INT(noise); + DRIVER_STATE_PRINT_LHEX(ap_hlid_map[0]); + DRIVER_STATE_PRINT_INT(last_tx_hlid); + DRIVER_STATE_PRINT_INT(ba_support); + DRIVER_STATE_PRINT_HEX(ba_rx_bitmap); + DRIVER_STATE_PRINT_HEX(ap_fw_ps_map); + DRIVER_STATE_PRINT_LHEX(ap_ps_map); + DRIVER_STATE_PRINT_HEX(quirks); + DRIVER_STATE_PRINT_HEX(irq); + DRIVER_STATE_PRINT_HEX(ref_clock); + DRIVER_STATE_PRINT_HEX(tcxo_clock); + DRIVER_STATE_PRINT_HEX(hw_pg_ver); + DRIVER_STATE_PRINT_HEX(platform_quirks); + DRIVER_STATE_PRINT_HEX(chip.id); + DRIVER_STATE_PRINT_STR(chip.fw_ver_str); + +#undef DRIVER_STATE_PRINT_INT +#undef DRIVER_STATE_PRINT_LONG +#undef DRIVER_STATE_PRINT_HEX +#undef DRIVER_STATE_PRINT_LHEX +#undef DRIVER_STATE_PRINT_STR +#undef DRIVER_STATE_PRINT + + mutex_unlock(&wl->mutex); + + return simple_read_from_buffer(user_buf, count, ppos, buf, res); +} + +static const struct file_operations driver_state_ops = { + .read = driver_state_read, + .open = wl1271_open_file_generic, + .llseek = default_llseek, +}; + static ssize_t dtim_interval_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -549,6 +635,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, DEBUGFS_ADD(gpio_power, rootdir); DEBUGFS_ADD(start_recovery, rootdir); + DEBUGFS_ADD(driver_state, rootdir); DEBUGFS_ADD(dtim_interval, rootdir); DEBUGFS_ADD(beacon_interval, rootdir); -- cgit v1.2.3-58-ga151 From 25eaea30cd7b009ba2ca693708330d2f395cbc4d Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Mon, 2 May 2011 12:37:33 +0300 Subject: Revert "wl12xx: support FW TX inactivity triggers" This reverts commit 47684808fd89d6809c0886e06f8ac324252499d8. Conflicts: drivers/net/wireless/wl12xx/conf.h drivers/net/wireless/wl12xx/main.c --- drivers/net/wireless/wl12xx/acx.c | 34 ++++---------------------- drivers/net/wireless/wl12xx/acx.h | 12 ++------- drivers/net/wireless/wl12xx/boot.c | 6 ++--- drivers/net/wireless/wl12xx/cmd.c | 2 +- drivers/net/wireless/wl12xx/conf.h | 12 ++------- drivers/net/wireless/wl12xx/event.c | 47 ------------------------------------ drivers/net/wireless/wl12xx/event.h | 12 +-------- drivers/net/wireless/wl12xx/init.c | 6 +---- drivers/net/wireless/wl12xx/main.c | 10 ++------ drivers/net/wireless/wl12xx/wl12xx.h | 1 + 10 files changed, 17 insertions(+), 125 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index ec0156b3e276..c6ee530e5bf7 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -1577,46 +1577,22 @@ out: return ret; } -int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) +int wl1271_acx_max_tx_retry(struct wl1271 *wl) { - struct wl1271_acx_ap_max_tx_retry *acx = NULL; + struct wl1271_acx_max_tx_retry *acx = NULL; int ret; - wl1271_debug(DEBUG_ACX, "acx ap max tx retry"); + wl1271_debug(DEBUG_ACX, "acx max tx retry"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); if (!acx) return -ENOMEM; - acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries); + acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries); ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); if (ret < 0) { - wl1271_warning("acx ap max tx retry failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl) -{ - struct wl1271_acx_sta_max_tx_retry *acx = NULL; - int ret; - - wl1271_debug(DEBUG_ACX, "acx sta max tx retry"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) - return -ENOMEM; - - acx->max_tx_retry = wl->conf.tx.max_tx_retries; - - ret = wl1271_cmd_configure(wl, ACX_CONS_TX_FAILURE, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("acx sta max tx retry failed: %d", ret); + wl1271_warning("acx max tx retry failed: %d", ret); goto out; } diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 75338f9947cf..9a895e3cc613 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -1153,7 +1153,7 @@ struct wl1271_acx_fw_tsf_information { u8 padding[3]; } __packed; -struct wl1271_acx_ap_max_tx_retry { +struct wl1271_acx_max_tx_retry { struct acx_header header; /* @@ -1164,13 +1164,6 @@ struct wl1271_acx_ap_max_tx_retry { u8 padding_1[2]; } __packed; -struct wl1271_acx_sta_max_tx_retry { - struct acx_header header; - - u8 max_tx_retry; - u8 padding_1[3]; -} __packed; - struct wl1271_acx_config_ps { struct acx_header header; @@ -1391,8 +1384,7 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl, int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, bool enable); int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); -int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); -int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl); +int wl1271_acx_max_tx_retry(struct wl1271 *wl); int wl1271_acx_config_ps(struct wl1271 *wl); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable); diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index d263ebb6f974..2b0cf85788b3 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -478,12 +478,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) DISCONNECT_EVENT_COMPLETE_ID | RSSI_SNR_TRIGGER_0_EVENT_ID | PSPOLL_DELIVERY_FAILURE_EVENT_ID | - SOFT_GEMINI_SENSE_EVENT_ID | - MAX_TX_RETRY_EVENT_ID; + SOFT_GEMINI_SENSE_EVENT_ID; if (wl->bss_type == BSS_TYPE_AP_BSS) - wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID | - INACTIVE_STA_EVENT_ID; + wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; else wl->event_mask |= DUMMY_PACKET_EVENT_ID; diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index d8596ae3a64f..2116a376c3f3 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -1080,7 +1080,7 @@ int wl1271_cmd_start_bss(struct wl1271 *wl) memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); - cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); + cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC); cmd->bss_index = WL1271_AP_BSS_INDEX; cmd->global_hlid = WL1271_AP_GLOBAL_HLID; cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index c0045f0b8b4e..1f947368f9ee 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -711,18 +711,10 @@ struct conf_tx_settings { struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT]; /* - * Allow this number of TX retries to a connected station/AP before an + * AP-mode - allow this number of TX retries to a station before an * event is triggered from FW. - * In AP-mode the hlids of unreachable stations are given in the - * "sta_tx_retry_exceeded" member in the event mailbox. */ - u8 max_tx_retries; - - /* - * AP-mode - after this number of seconds a connected station is - * considered inactive. - */ - u16 ap_aging_period; + u16 ap_max_tx_retries; /* * Configuration for TID parameters. diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index d7be3aec6fc3..ae69330e807c 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -174,8 +174,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) u32 vector; bool beacon_loss = false; bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); - bool disconnect_sta = false; - unsigned long sta_bitmap = 0; wl1271_event_mbox_dump(mbox); @@ -237,54 +235,9 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) wl1271_tx_dummy_packet(wl); } - /* - * "TX retries exceeded" has a different meaning according to mode. - * In AP mode the offending station is disconnected. In STA mode we - * report connection loss. - */ - if (vector & MAX_TX_RETRY_EVENT_ID) { - wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); - if (is_ap) { - sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); - disconnect_sta = true; - } else { - beacon_loss = true; - } - } - - if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) { - wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); - sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); - disconnect_sta = true; - } - if (wl->vif && beacon_loss) ieee80211_connection_loss(wl->vif); - if (is_ap && disconnect_sta) { - u32 num_packets = wl->conf.tx.max_tx_retries; - struct ieee80211_sta *sta; - const u8 *addr; - int h; - - for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS); - h < AP_MAX_LINKS; - h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) { - if (!wl1271_is_active_sta(wl, h)) - continue; - - addr = wl->links[h].addr; - - rcu_read_lock(); - sta = ieee80211_find_sta(wl->vif, addr); - if (sta) { - wl1271_debug(DEBUG_EVENT, "remove sta %d", h); - ieee80211_report_low_ack(sta, num_packets); - } - rcu_read_unlock(); - } - } - return 0; } diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h index 7ae5a0821241..b6cf06e565a4 100644 --- a/drivers/net/wireless/wl12xx/event.h +++ b/drivers/net/wireless/wl12xx/event.h @@ -58,16 +58,13 @@ enum { CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), BSS_LOSE_EVENT_ID = BIT(18), REGAINED_BSS_EVENT_ID = BIT(19), - MAX_TX_RETRY_EVENT_ID = BIT(20), + ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20), /* STA: dummy paket for dynamic mem blocks */ DUMMY_PACKET_EVENT_ID = BIT(21), /* AP: STA remove complete */ STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), - /* STA: SG prediction */ SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), - /* AP: Inactive STA */ - INACTIVE_STA_EVENT_ID = BIT(23), SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), DBG_EVENT_ID = BIT(26), @@ -122,11 +119,7 @@ struct event_mailbox { /* AP FW only */ u8 hlid_removed; - - /* a bitmap of hlids for stations that have been inactive too long */ __le16 sta_aging_status; - - /* a bitmap of hlids for stations which didn't respond to TX */ __le16 sta_tx_retry_exceeded; u8 reserved_5[24]; @@ -137,7 +130,4 @@ void wl1271_event_mbox_config(struct wl1271 *wl); int wl1271_event_handle(struct wl1271 *wl, u8 mbox); void wl1271_pspoll_work(struct work_struct *work); -/* Functions from main.c */ -bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid); - #endif diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index b1242a6de27b..a8f4f156c055 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -378,10 +378,6 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_acx_sta_max_tx_retry(wl); - if (ret < 0) - return ret; - ret = wl1271_acx_sta_mem_cfg(wl); if (ret < 0) return ret; @@ -432,7 +428,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_acx_ap_max_tx_retry(wl); + ret = wl1271_acx_max_tx_retry(wl); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 6dd42c987663..6dab6f0c91bc 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -209,8 +209,7 @@ static struct conf_drv_settings default_conf = { .tx_op_limit = 1504, }, }, - .max_tx_retries = 100, - .ap_aging_period = 300, + .ap_max_tx_retries = 100, .tid_conf_count = 4, .tid_conf = { [CONF_TX_AC_BE] = { @@ -3021,12 +3020,6 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); } -bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) -{ - int id = hlid - WL1271_AP_STA_HLID_START; - return test_bit(id, wl->ap_hlid_map); -} - static int wl1271_op_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) @@ -3632,6 +3625,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) IEEE80211_HW_HAS_RATE_CONTROL | IEEE80211_HW_CONNECTION_MONITOR | IEEE80211_HW_SUPPORTS_CQM_RSSI | + IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_AP_LINK_PS; wl->hw->wiphy->cipher_suites = cipher_suites; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index f3de96212b96..b7601438ecac 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -172,6 +172,7 @@ extern u32 wl12xx_debug_level; #define WL1271_PS_STA_MAX_BLOCKS (2 * 9) #define WL1271_AP_BSS_INDEX 0 +#define WL1271_AP_DEF_INACTIV_SEC 300 #define WL1271_AP_DEF_BEACON_EXP 20 #define ACX_TX_DESCRIPTORS 32 -- cgit v1.2.3-58-ga151 From 0ca699552c441e2c4201a6f60eac98b8865c1743 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 27 Apr 2011 17:40:11 +0200 Subject: ssb: cc: prepare clockmode support for cores rev 10+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_chipcommon.c | 62 +++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index b4b3733aefcf..06d15b6f2215 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c @@ -46,40 +46,66 @@ void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, if (!ccdev) return; bus = ccdev->bus; + + /* We support SLOW only on 6..9 */ + if (ccdev->id.revision >= 10 && mode == SSB_CLKMODE_SLOW) + mode = SSB_CLKMODE_DYNAMIC; + + if (cc->capabilities & SSB_CHIPCO_CAP_PMU) + return; /* PMU controls clockmode, separated function needed */ + SSB_WARN_ON(ccdev->id.revision >= 20); + /* chipcommon cores prior to rev6 don't support dynamic clock control */ if (ccdev->id.revision < 6) return; - /* chipcommon cores rev10 are a whole new ball game */ + + /* ChipCommon cores rev10+ need testing */ if (ccdev->id.revision >= 10) return; + if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL)) return; switch (mode) { - case SSB_CLKMODE_SLOW: + case SSB_CLKMODE_SLOW: /* For revs 6..9 only */ tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); tmp |= SSB_CHIPCO_SLOWCLKCTL_FSLOW; chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); break; case SSB_CLKMODE_FAST: - ssb_pci_xtal(bus, SSB_GPIO_XTAL, 1); /* Force crystal on */ - tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); - tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; - tmp |= SSB_CHIPCO_SLOWCLKCTL_IPLL; - chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); + if (ccdev->id.revision < 10) { + ssb_pci_xtal(bus, SSB_GPIO_XTAL, 1); /* Force crystal on */ + tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); + tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; + tmp |= SSB_CHIPCO_SLOWCLKCTL_IPLL; + chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); + } else { + chipco_write32(cc, SSB_CHIPCO_SYSCLKCTL, + (chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL) | + SSB_CHIPCO_SYSCLKCTL_FORCEHT)); + /* udelay(150); TODO: not available in early init */ + } break; case SSB_CLKMODE_DYNAMIC: - tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); - tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; - tmp &= ~SSB_CHIPCO_SLOWCLKCTL_IPLL; - tmp &= ~SSB_CHIPCO_SLOWCLKCTL_ENXTAL; - if ((tmp & SSB_CHIPCO_SLOWCLKCTL_SRC) != SSB_CHIPCO_SLOWCLKCTL_SRC_XTAL) - tmp |= SSB_CHIPCO_SLOWCLKCTL_ENXTAL; - chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); - - /* for dynamic control, we have to release our xtal_pu "force on" */ - if (tmp & SSB_CHIPCO_SLOWCLKCTL_ENXTAL) - ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0); + if (ccdev->id.revision < 10) { + tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); + tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; + tmp &= ~SSB_CHIPCO_SLOWCLKCTL_IPLL; + tmp &= ~SSB_CHIPCO_SLOWCLKCTL_ENXTAL; + if ((tmp & SSB_CHIPCO_SLOWCLKCTL_SRC) != + SSB_CHIPCO_SLOWCLKCTL_SRC_XTAL) + tmp |= SSB_CHIPCO_SLOWCLKCTL_ENXTAL; + chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); + + /* For dynamic control, we have to release our xtal_pu + * "force on" */ + if (tmp & SSB_CHIPCO_SLOWCLKCTL_ENXTAL) + ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0); + } else { + chipco_write32(cc, SSB_CHIPCO_SYSCLKCTL, + (chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL) & + ~SSB_CHIPCO_SYSCLKCTL_FORCEHT)); + } break; default: SSB_WARN_ON(1); -- cgit v1.2.3-58-ga151 From 816c04fe7ef01dd9649f5ccfe796474db8708be5 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 30 Apr 2011 15:24:30 +0200 Subject: mac80211: consolidate MIC failure report handling Currently, mac80211 handles MIC failures differently depending on whenever they are detected by the stack's own software crypto or when are handed down from the driver. This patch tries to unify both by moving the special branch out of mac80211 rx hotpath and into into the software crypto part. This has the advantage that we can run a few more sanity checks on the data and verify if the key type was TKIP. This is very handy because several devices generate false postive MIC failure reports. Like carl9170, ath9k and wl12xx: "mac80211: report MIC failure for truncated packets in AP mode" Cc: Luciano Coelho Cc: Arik Nemtsov Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- net/mac80211/rx.c | 47 ----------------------------------------- net/mac80211/wpa.c | 62 ++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 48 insertions(+), 61 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b04a4378adcc..81241e18f3a4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2368,47 +2368,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) return RX_QUEUED; } -static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr, - struct ieee80211_rx_data *rx) -{ - int keyidx; - unsigned int hdrlen; - - hdrlen = ieee80211_hdrlen(hdr->frame_control); - if (rx->skb->len >= hdrlen + 4) - keyidx = rx->skb->data[hdrlen + 3] >> 6; - else - keyidx = -1; - - if (!rx->sta) { - /* - * Some hardware seem to generate incorrect Michael MIC - * reports; ignore them to avoid triggering countermeasures. - */ - return; - } - - if (!ieee80211_has_protected(hdr->frame_control)) - return; - - if (rx->sdata->vif.type == NL80211_IFTYPE_AP && keyidx) { - /* - * APs with pairwise keys should never receive Michael MIC - * errors for non-zero keyidx because these are reserved for - * group keys and only the AP is sending real multicast - * frames in the BSS. - */ - return; - } - - if (!ieee80211_is_data(hdr->frame_control) && - !ieee80211_is_auth(hdr->frame_control)) - return; - - mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL, - GFP_ATOMIC); -} - /* TODO: use IEEE80211_RX_FRAGMENTED */ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, struct ieee80211_rate *rate) @@ -2752,12 +2711,6 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx, if (!prepares) return false; - if (status->flag & RX_FLAG_MMIC_ERROR) { - if (status->rx_flags & IEEE80211_RX_RA_MATCH) - ieee80211_rx_michael_mic_report(hdr, rx); - return false; - } - if (!consume) { skb = skb_copy(skb, GFP_ATOMIC); if (!skb) { diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index f1765de2f4bf..9dc3b5f26e80 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -87,42 +87,76 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - /* No way to verify the MIC if the hardware stripped it */ - if (status->flag & RX_FLAG_MMIC_STRIPPED) + /* + * it makes no sense to check for MIC errors on anything other + * than data frames. + */ + if (!ieee80211_is_data_present(hdr->frame_control)) + return RX_CONTINUE; + + /* + * No way to verify the MIC if the hardware stripped it or + * the IV with the key index. In this case we have solely rely + * on the driver to set RX_FLAG_MMIC_ERROR in the event of a + * MIC failure report. + */ + if (status->flag & (RX_FLAG_MMIC_STRIPPED | RX_FLAG_IV_STRIPPED)) { + if (status->flag & RX_FLAG_MMIC_ERROR) + goto mic_fail; + + if (!(status->flag & RX_FLAG_IV_STRIPPED)) + goto update_iv; + return RX_CONTINUE; + } + /* + * Some hardware seems to generate Michael MIC failure reports; even + * though, the frame was not encrypted with TKIP and therefore has no + * MIC. Ignore the flag them to avoid triggering countermeasures. + */ if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP || - !ieee80211_has_protected(hdr->frame_control) || - !ieee80211_is_data_present(hdr->frame_control)) + !(status->flag & RX_FLAG_DECRYPTED)) return RX_CONTINUE; + if (rx->sdata->vif.type == NL80211_IFTYPE_AP && rx->key->conf.keyidx) { + /* + * APs with pairwise keys should never receive Michael MIC + * errors for non-zero keyidx because these are reserved for + * group keys and only the AP is sending real multicast + * frames in the BSS. ( + */ + return RX_DROP_UNUSABLE; + } + + if (status->flag & RX_FLAG_MMIC_ERROR) + goto mic_fail; + hdrlen = ieee80211_hdrlen(hdr->frame_control); if (skb->len < hdrlen + MICHAEL_MIC_LEN) return RX_DROP_UNUSABLE; data = skb->data + hdrlen; data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; - key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; michael_mic(key, hdr, data, data_len, mic); - if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0) { - if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) - return RX_DROP_UNUSABLE; - - mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, - (void *) skb->data, NULL, - GFP_ATOMIC); - return RX_DROP_UNUSABLE; - } + if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0) + goto mic_fail; /* remove Michael MIC from payload */ skb_trim(skb, skb->len - MICHAEL_MIC_LEN); +update_iv: /* update IV in key information to be able to detect replays */ rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32; rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16; return RX_CONTINUE; + +mic_fail: + mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, + (void *) skb->data, NULL, GFP_ATOMIC); + return RX_DROP_UNUSABLE; } -- cgit v1.2.3-58-ga151 From 16763478892c271293d02872475a67a648ae12fc Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 30 Apr 2011 17:13:46 +0200 Subject: rt2x00: Reduce tx status reading timeout When no TX status was available, the default timeout of 20ms is a bit high. The frame is highly likely already send out, so the TX status should be available within only a few milliseconds. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 0d4e8fa3e1f8..e4f82d2f341b 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -134,7 +134,7 @@ static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) { queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); } else if (rt2800usb_txstatus_pending(rt2x00dev)) { - mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20)); + mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(2)); } } @@ -493,7 +493,7 @@ static void rt2800usb_work_txdone(struct work_struct *work) * also delayed -> use a timer to retrieve it. */ if (rt2800usb_txstatus_pending(rt2x00dev)) - mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20)); + mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(2)); } /* -- cgit v1.2.3-58-ga151 From a073fdef46d50440ee573452a436023dcf4f9edf Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 30 Apr 2011 17:14:23 +0200 Subject: rt2x00: Optimize TX_STA_FIFO register reading Add recycling functionality to rt2x00usb_register_read_async. When the callback function returns true, resubmit the urb to read the register again. This optimizes the rt2800usb driver when multiple TX status reports are pending in the register, because now we don't need to allocate the rt2x00_async_read_data and urb structure each time. Signed-off-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 9 +++++---- drivers/net/wireless/rt2x00/rt2x00usb.c | 11 +++++++---- drivers/net/wireless/rt2x00/rt2x00usb.h | 4 +++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index e4f82d2f341b..b5d5f2203c52 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -114,12 +114,12 @@ static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev) return false; } -static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, +static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, int urb_status, u32 tx_status) { if (urb_status) { WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status); - return; + return false; } /* try to read all TX_STA_FIFO entries before scheduling txdone_work */ @@ -129,13 +129,14 @@ static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, "drop tx status report.\n"); queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); } else - rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, - rt2800usb_tx_sta_fifo_read_completed); + return true; } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) { queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); } else if (rt2800usb_txstatus_pending(rt2x00dev)) { mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(2)); } + + return false; } static void rt2800usb_tx_dma_done(struct queue_entry *entry) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 570184ee163c..e027ebd44583 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -170,19 +170,22 @@ struct rt2x00_async_read_data { __le32 reg; struct usb_ctrlrequest cr; struct rt2x00_dev *rt2x00dev; - void (*callback)(struct rt2x00_dev *,int,u32); + bool (*callback)(struct rt2x00_dev *, int, u32); }; static void rt2x00usb_register_read_async_cb(struct urb *urb) { struct rt2x00_async_read_data *rd = urb->context; - rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg)); - kfree(urb->context); + if (rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg))) { + if (usb_submit_urb(urb, GFP_ATOMIC) < 0) + kfree(rd); + } else + kfree(rd); } void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, const unsigned int offset, - void (*callback)(struct rt2x00_dev*,int,u32)) + bool (*callback)(struct rt2x00_dev*, int, u32)) { struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); struct urb *urb; diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 52b09d2e11de..a69f18758871 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -349,10 +349,12 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, * be called from atomic context. The callback will be called * when the URB completes. Otherwise the function is similar * to rt2x00usb_register_read(). + * When the callback function returns false, the memory will be cleaned up, + * when it returns true, the urb will be fired again. */ void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, const unsigned int offset, - void (*callback)(struct rt2x00_dev*,int,u32)); + bool (*callback)(struct rt2x00_dev*, int, u32)); /* * Radio handlers -- cgit v1.2.3-58-ga151 From d4c838ef5e5c2c7e205adf9e011d2e8bd6eae738 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 30 Apr 2011 17:14:49 +0200 Subject: rt2x00: Fix optimize register access for rt2800pci The patch rt2x00: Optimize register access in rt2800pci from Helmut Schaa missed one register call, namely the rt2800_register_multiwrite which should be changed to rt2x00pci_register_multiwrite. Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 08d3947fcb26..cc4a54f571b8 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -302,8 +302,8 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, /* * Write firmware to device. */ - rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, - data, len); + rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, + data, len); rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); -- cgit v1.2.3-58-ga151 From 9328fdac499b969ec57a195845f168e7c5168ccd Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 30 Apr 2011 17:15:13 +0200 Subject: rt2x00: Streamline rt2800 eeprom initialisations. In rt2800lib.c the rt2800_init_eeprom function the same eeprom words were read multiple times, due to inefficient ordering of the eeprom checks. Reorder the checks so that each EEPROM word only has to be read once. Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index d79c8fd41138..71c16c618c4d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3727,16 +3727,8 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) } /* - * Read frequency offset and RF programming sequence. + * Determine external LNA informations. */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); - rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); - - /* - * Read external LNA informations. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G)) __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G)) @@ -3748,6 +3740,12 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO)) __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); + /* + * Read frequency offset and RF programming sequence. + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); + rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); + /* * Store led settings, for correct led behaviour. */ @@ -3756,7 +3754,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); - rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg); + rt2x00dev->led_mcu_reg = eeprom; #endif /* CONFIG_RT2X00_LIB_LEDS */ /* -- cgit v1.2.3-58-ga151 From fdbc7b0a262e24a3ee00f1f9acb5a97309a173d5 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 30 Apr 2011 17:15:37 +0200 Subject: rt2x00: Introduce capability flag for Bluetooth co-existence. Use flag instead of re-reading the eeprom every time. Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 13 ++++++++----- drivers/net/wireless/rt2x00/rt2x00.h | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 71c16c618c4d..6ed646a02d49 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1640,7 +1640,6 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, struct channel_info *info) { u8 rfcsr; - u16 eeprom; rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); @@ -1670,11 +1669,10 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); if (rf->channel <= 14) { int idx = rf->channel-1; - if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) { + if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { /* r55/r59 value array of channel 1~14 */ static const char r55_bt_rev[] = {0x83, 0x83, @@ -2917,8 +2915,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) ant = (div_mode == 3) ? 1 : 0; /* check if this is a Bluetooth combo card */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) { + if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { u32 reg; rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); @@ -3740,6 +3737,12 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO)) __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); + /* + * Detect if this device has Bluetooth co-existence. + */ + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) + __set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags); + /* * Read frequency offset and RF programming sequence. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index acf561f7cde3..86e141000156 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -697,6 +697,7 @@ enum rt2x00_capability_flags { CAPABILITY_EXTERNAL_LNA_A, CAPABILITY_EXTERNAL_LNA_BG, CAPABILITY_DOUBLE_ANTENNA, + CAPABILITY_BT_COEXIST, }; /* -- cgit v1.2.3-58-ga151 From 1c0bcf89d85cc97a0d9ce4cd909351a81fa4fdde Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 30 Apr 2011 17:18:18 +0200 Subject: rt2x00: Add autowake support for USB hardware The USB drivers don't support automatically waking up when in powersaving mode, add a work object which will wakeup the device in time to receive the next beacon. Based on that beacon, we either go back into powersaving mode, or we remain awake to receive the buffered frames for our station. Some part of the code, especially rt2x00lib_find_ie and rt2x00lib_rxdone_check_ps are inspired on the code from carl9170. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 1 + drivers/net/wireless/rt2x00/rt2800usb.c | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 17 ++++++ drivers/net/wireless/rt2x00/rt2x00config.c | 31 +++++++++++ drivers/net/wireless/rt2x00/rt2x00dev.c | 88 ++++++++++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt73usb.c | 1 + 6 files changed, 139 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index b21f81231a09..15237c275486 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1797,6 +1797,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) __set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags); } __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags); /* * Set the rssi offset. diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index b5d5f2203c52..0eb44cf2f44a 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -634,6 +634,7 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags); setup_timer(&rt2x00dev->txstatus_timer, rt2800usb_tx_sta_fifo_timeout, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 86e141000156..73d3332be614 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -662,6 +662,7 @@ enum rt2x00_state_flags { * Driver configuration */ CONFIG_CHANNEL_HT40, + CONFIG_POWERSAVING, }; /* @@ -681,6 +682,7 @@ enum rt2x00_capability_flags { REQUIRE_TASKLET_CONTEXT, REQUIRE_SW_SEQNO, REQUIRE_HT_TX_DESC, + REQUIRE_PS_AUTOWAKE, /* * Capabilities @@ -874,11 +876,21 @@ struct rt2x00_dev { */ u8 calibration[2]; + /* + * Association id. + */ + u16 aid; + /* * Beacon interval. */ u16 beacon_int; + /** + * Timestamp of last received beacon + */ + unsigned long last_beacon; + /* * Low level statistics which will have * to be kept up to date while device is running. @@ -906,6 +918,11 @@ struct rt2x00_dev { struct work_struct rxdone_work; struct work_struct txdone_work; + /* + * Powersaving work + */ + struct delayed_work autowakeup_work; + /* * Data queue arrays for RX, TX, Beacon and ATIM. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 2a313b6d378d..edebbf04bc57 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -100,6 +100,10 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, erp.basic_rates = bss_conf->basic_rates; erp.beacon_int = bss_conf->beacon_int; + /* Update the AID, this is needed for dynamic PS support */ + rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0; + rt2x00dev->last_beacon = bss_conf->timestamp; + /* Update global beacon interval time, this is needed for PS support */ rt2x00dev->beacon_int = bss_conf->beacon_int; @@ -204,6 +208,9 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, { struct rt2x00lib_conf libconf; u16 hw_value; + u16 autowake_timeout; + u16 beacon_int; + u16 beacon_diff; memset(&libconf, 0, sizeof(libconf)); @@ -227,6 +234,10 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, sizeof(libconf.channel)); } + if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) && + (ieee80211_flags & IEEE80211_CONF_CHANGE_PS)) + cancel_delayed_work_sync(&rt2x00dev->autowakeup_work); + /* * Start configuration. */ @@ -239,6 +250,26 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) rt2x00link_reset_tuner(rt2x00dev, false); + if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) && + (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) && + (conf->flags & IEEE80211_CONF_PS)) { + beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon; + beacon_int = msecs_to_jiffies(rt2x00dev->beacon_int); + + if (beacon_diff > beacon_int) + beacon_diff = 0; + + autowake_timeout = (conf->max_sleep_period * beacon_int) - beacon_diff; + queue_delayed_work(rt2x00dev->workqueue, + &rt2x00dev->autowakeup_work, + autowake_timeout - 15); + } + + if (conf->flags & IEEE80211_CONF_PS) + set_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); + else + clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); + rt2x00dev->curr_band = conf->channel->band; rt2x00dev->curr_freq = conf->channel->center_freq; rt2x00dev->tx_power = conf->power_level; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 7776d9f1f297..2eb5196977fd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -141,6 +141,16 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work) rt2x00dev); } +static void rt2x00lib_autowakeup(struct work_struct *work) +{ + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, autowakeup_work.work); + + if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) + ERROR(rt2x00dev, "Device failed to wakeup.\n"); + clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); +} + /* * Interrupt context handlers. */ @@ -416,6 +426,77 @@ void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status) } EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo); +static u8 *rt2x00lib_find_ie(u8 *data, unsigned int len, u8 ie) +{ + struct ieee80211_mgmt *mgmt = (void *)data; + u8 *pos, *end; + + pos = (u8 *)mgmt->u.beacon.variable; + end = data + len; + while (pos < end) { + if (pos + 2 + pos[1] > end) + return NULL; + + if (pos[0] == ie) + return pos; + + pos += 2 + pos[1]; + } + + return NULL; +} + +static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb, + struct rxdone_entry_desc *rxdesc) +{ + struct ieee80211_hdr *hdr = (void *) skb->data; + struct ieee80211_tim_ie *tim_ie; + u8 *tim; + u8 tim_len; + bool cam; + + /* If this is not a beacon, or if mac80211 has no powersaving + * configured, or if the device is already in powersaving mode + * we can exit now. */ + if (likely(!ieee80211_is_beacon(hdr->frame_control) || + !(rt2x00dev->hw->conf.flags & IEEE80211_CONF_PS))) + return; + + /* min. beacon length + FCS_LEN */ + if (skb->len <= 40 + FCS_LEN) + return; + + /* and only beacons from the associated BSSID, please */ + if (!(rxdesc->dev_flags & RXDONE_MY_BSS) || + !rt2x00dev->aid) + return; + + rt2x00dev->last_beacon = jiffies; + + tim = rt2x00lib_find_ie(skb->data, skb->len - FCS_LEN, WLAN_EID_TIM); + if (!tim) + return; + + if (tim[1] < sizeof(*tim_ie)) + return; + + tim_len = tim[1]; + tim_ie = (struct ieee80211_tim_ie *) &tim[2]; + + /* Check whenever the PHY can be turned off again. */ + + /* 1. What about buffered unicast traffic for our AID? */ + cam = ieee80211_check_tim(tim_ie, tim_len, rt2x00dev->aid); + + /* 2. Maybe the AP wants to send multicast/broadcast data? */ + cam |= (tim_ie->bitmap_ctrl & 0x01); + + if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags)) + rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf, + IEEE80211_CONF_CHANGE_PS); +} + static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, struct rxdone_entry_desc *rxdesc) { @@ -530,6 +611,12 @@ void rt2x00lib_rxdone(struct queue_entry *entry) rxdesc.rate_mode == RATE_MODE_HT_GREENFIELD) rxdesc.flags |= RX_FLAG_HT; + /* + * Check if this is a beacon, and more frames have been + * buffered while we were in powersaving mode. + */ + rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc); + /* * Update extra components */ @@ -1017,6 +1104,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) } INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); + INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup); /* * Let the driver probe the device to detect the capabilities. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index a6ce7d6cbdfa..ad20953cbf05 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2209,6 +2209,7 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (!modparam_nohwcrypt) __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); + __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags); /* * Set the rssi offset. -- cgit v1.2.3-58-ga151 From 982d96bbb7f084644ee10214812ab167e52c2c5d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 1 May 2011 22:30:54 -0500 Subject: rtlwifi: Fix typo in pci.c Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 367d9b4ebd20..3550c9fb96e5 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1069,7 +1069,7 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, for (i = 0; i < entries; i++) { nextdescaddress = (u32) dma + - ((i + 11) % entries) * + ((i + 1) % entries) * sizeof(*ring); rtlpriv->cfg->ops->set_desc((u8 *)&(ring[i]), -- cgit v1.2.3-58-ga151 From 1a5b306f5d7398c7ffb0f69fe9a2d0023f28deb9 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Mon, 2 May 2011 11:00:45 -0700 Subject: mwifiex: fix missing tsf_val TLV In mwifiex_cmd_append_tsf_tlv(), two tsf_val TLVs should be filled in the buffer and then sent to firmware. The missing first TLV for tsf_val is added back in this patch. Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/join.c | 7 ++++++- drivers/net/wireless/mwifiex/main.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 042eb7701d04..85fca5eb4195 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -100,7 +100,7 @@ mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer, struct mwifiex_bssdescriptor *bss_desc) { struct mwifiex_ie_types_tsf_timestamp tsf_tlv; - long long tsf_val; + __le64 tsf_val; /* Null Checks */ if (buffer == NULL) @@ -116,6 +116,11 @@ mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer, memcpy(*buffer, &tsf_tlv, sizeof(tsf_tlv.header)); *buffer += sizeof(tsf_tlv.header); + /* TSF at the time when beacon/probe_response was received */ + tsf_val = cpu_to_le64(bss_desc->network_tsf); + memcpy(*buffer, &tsf_val, sizeof(tsf_val)); + *buffer += sizeof(tsf_val); + memcpy(&tsf_val, bss_desc->time_stamp, sizeof(tsf_val)); dev_dbg(priv->adapter->dev, "info: %s: TSF offset calc: %016llx - " diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 1b503038270e..5043fcd22565 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -280,7 +280,7 @@ struct mwifiex_bssdescriptor { * BAND_A(0X04): 'a' band */ u16 bss_band; - long long network_tsf; + u64 network_tsf; u8 time_stamp[8]; union ieee_types_phy_param_set phy_param_set; union ieee_types_ss_param_set ss_param_set; -- cgit v1.2.3-58-ga151 From 5615787257742aab42ecf17c11e3244d9536a48d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 2 May 2011 14:37:45 -0700 Subject: ipv4: Make sure flowi4->{saddr,daddr} are always set. Slow path output route resolution always makes sure that ->{saddr,daddr} are set, and also if we trigger into IPSEC resolution we initialize them as well, because xfrm_lookup() expects them to be fully resolved. But if we hit the fast path and flowi4->flowi4_proto is zero, we won't do this initialization. Therefore, move the IPSEC path initialization to the route cache lookup fast path to make sure these are always set. Signed-off-by: David S. Miller --- net/ipv4/route.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 93f71be1d5d1..64f360d853fb 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2675,6 +2675,10 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4) dst_use(&rth->dst, jiffies); RT_CACHE_STAT_INC(out_hit); rcu_read_unlock_bh(); + if (!flp4->saddr) + flp4->saddr = rth->rt_src; + if (!flp4->daddr) + flp4->daddr = rth->rt_dst; return rth; } RT_CACHE_STAT_INC(out_hlist_search); @@ -2772,15 +2776,10 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4, if (IS_ERR(rt)) return rt; - if (flp4->flowi4_proto) { - if (!flp4->saddr) - flp4->saddr = rt->rt_src; - if (!flp4->daddr) - flp4->daddr = rt->rt_dst; + if (flp4->flowi4_proto) rt = (struct rtable *) xfrm_lookup(net, &rt->dst, flowi4_to_flowi(flp4), sk, 0); - } return rt; } -- cgit v1.2.3-58-ga151 From e67f88dd12f610da98ca838822f2c9b4e7c6100e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2011 22:56:07 +0000 Subject: net: dont hold rtnl mutex during netlink dump callbacks Four years ago, Patrick made a change to hold rtnl mutex during netlink dump callbacks. I believe it was a wrong move. This slows down concurrent dumps, making good old /proc/net/ files faster than rtnetlink in some situations. This occurred to me because one "ip link show dev ..." was _very_ slow on a workload adding/removing network devices in background. All dump callbacks are able to use RCU locking now, so this patch does roughly a revert of commits : 1c2d670f366 : [RTNETLINK]: Hold rtnl_mutex during netlink dump callbacks 6313c1e0992 : [RTNETLINK]: Remove unnecessary locking in dump callbacks This let writers fight for rtnl mutex and readers going full speed. It also takes care of phonet : phonet_route_get() is now called from rcu read section. I renamed it to phonet_route_get_rcu() Signed-off-by: Eric Dumazet Cc: Patrick McHardy Cc: Remi Denis-Courmont Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/net/phonet/pn_dev.h | 2 +- net/bridge/br_netlink.c | 7 ++++--- net/core/fib_rules.c | 3 ++- net/core/rtnetlink.c | 12 +++++------- net/decnet/dn_dev.c | 10 ++++++---- net/ipv6/ip6_fib.c | 4 +++- net/phonet/pn_dev.c | 6 +----- net/phonet/pn_netlink.c | 4 +++- 8 files changed, 25 insertions(+), 23 deletions(-) diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h index 13649eb57413..8639de5750f6 100644 --- a/include/net/phonet/pn_dev.h +++ b/include/net/phonet/pn_dev.h @@ -51,7 +51,7 @@ void phonet_address_notify(int event, struct net_device *dev, u8 addr); int phonet_route_add(struct net_device *dev, u8 daddr); int phonet_route_del(struct net_device *dev, u8 daddr); void rtm_phonet_notify(int event, struct net_device *dev, u8 dst); -struct net_device *phonet_route_get(struct net *net, u8 daddr); +struct net_device *phonet_route_get_rcu(struct net *net, u8 daddr); struct net_device *phonet_route_output(struct net *net, u8 daddr); #define PN_NO_ADDR 0xff diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 134a2ff6b98b..ffb0dc4cc0e8 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -120,8 +120,9 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) int idx; idx = 0; - for_each_netdev(net, dev) { - struct net_bridge_port *port = br_port_get_rtnl(dev); + rcu_read_lock(); + for_each_netdev_rcu(net, dev) { + struct net_bridge_port *port = br_port_get_rcu(dev); /* not a bridge port */ if (!port || idx < cb->args[0]) @@ -135,7 +136,7 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) skip: ++idx; } - + rcu_read_unlock(); cb->args[0] = idx; return skb->len; diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 8248ebb5891d..3911586e12e4 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -590,7 +590,8 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb, int idx = 0; struct fib_rule *rule; - list_for_each_entry(rule, &ops->rules_list, list) { + rcu_read_lock(); + list_for_each_entry_rcu(rule, &ops->rules_list, list) { if (idx < cb->args[1]) goto skip; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index d7c4bb4b1820..296331257195 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1007,10 +1007,11 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) s_h = cb->args[0]; s_idx = cb->args[1]; + rcu_read_lock(); for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { idx = 0; head = &net->dev_index_head[h]; - hlist_for_each_entry(dev, node, head, index_hlist) { + hlist_for_each_entry_rcu(dev, node, head, index_hlist) { if (idx < s_idx) goto cont; if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, @@ -1023,6 +1024,7 @@ cont: } } out: + rcu_read_unlock(); cb->args[1] = idx; cb->args[0] = h; @@ -1879,7 +1881,6 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) int min_len; int family; int type; - int err; type = nlh->nlmsg_type; if (type > RTM_MAX) @@ -1906,11 +1907,8 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (dumpit == NULL) return -EOPNOTSUPP; - __rtnl_unlock(); rtnl = net->rtnl; - err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL); - rtnl_lock(); - return err; + return netlink_dump_start(rtnl, skb, nlh, dumpit, NULL); } memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *))); @@ -1980,7 +1978,7 @@ static int __net_init rtnetlink_net_init(struct net *net) { struct sock *sk; sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX, - rtnetlink_rcv, &rtnl_mutex, THIS_MODULE); + rtnetlink_rcv, NULL, THIS_MODULE); if (!sk) return -ENOMEM; net->rtnl = sk; diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 0dcaa903e00e..404fa1591027 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -752,7 +752,8 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) skip_naddr = cb->args[1]; idx = 0; - for_each_netdev(&init_net, dev) { + rcu_read_lock(); + for_each_netdev_rcu(&init_net, dev) { if (idx < skip_ndevs) goto cont; else if (idx > skip_ndevs) { @@ -761,11 +762,11 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) skip_naddr = 0; } - if ((dn_db = rtnl_dereference(dev->dn_ptr)) == NULL) + if ((dn_db = rcu_dereference(dev->dn_ptr)) == NULL) goto cont; - for (ifa = rtnl_dereference(dn_db->ifa_list), dn_idx = 0; ifa; - ifa = rtnl_dereference(ifa->ifa_next), dn_idx++) { + for (ifa = rcu_dereference(dn_db->ifa_list), dn_idx = 0; ifa; + ifa = rcu_dereference(ifa->ifa_next), dn_idx++) { if (dn_idx < skip_naddr) continue; @@ -778,6 +779,7 @@ cont: idx++; } done: + rcu_read_unlock(); cb->args[0] = idx; cb->args[1] = dn_idx; diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index dd88df0a5d7f..4076a0b14b20 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -394,10 +394,11 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) arg.net = net; w->args = &arg; + rcu_read_lock(); for (h = s_h; h < FIB6_TABLE_HASHSZ; h++, s_e = 0) { e = 0; head = &net->ipv6.fib_table_hash[h]; - hlist_for_each_entry(tb, node, head, tb6_hlist) { + hlist_for_each_entry_rcu(tb, node, head, tb6_hlist) { if (e < s_e) goto next; res = fib6_dump_table(tb, skb, cb); @@ -408,6 +409,7 @@ next: } } out: + rcu_read_unlock(); cb->args[1] = e; cb->args[0] = h; diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 947038ddd04c..47b3452675b6 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -426,18 +426,14 @@ int phonet_route_del(struct net_device *dev, u8 daddr) return 0; } -struct net_device *phonet_route_get(struct net *net, u8 daddr) +struct net_device *phonet_route_get_rcu(struct net *net, u8 daddr) { struct phonet_net *pnn = phonet_pernet(net); struct phonet_routes *routes = &pnn->routes; struct net_device *dev; - ASSERT_RTNL(); /* no need to hold the device */ - daddr >>= 2; - rcu_read_lock(); dev = rcu_dereference(routes->table[daddr]); - rcu_read_unlock(); return dev; } diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index 58b3b1f991ed..438accb7a5a8 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c @@ -264,10 +264,11 @@ static int route_dumpit(struct sk_buff *skb, struct netlink_callback *cb) struct net *net = sock_net(skb->sk); u8 addr, addr_idx = 0, addr_start_idx = cb->args[0]; + rcu_read_lock(); for (addr = 0; addr < 64; addr++) { struct net_device *dev; - dev = phonet_route_get(net, addr << 2); + dev = phonet_route_get_rcu(net, addr << 2); if (!dev) continue; @@ -279,6 +280,7 @@ static int route_dumpit(struct sk_buff *skb, struct netlink_callback *cb) } out: + rcu_read_unlock(); cb->args[0] = addr_idx; cb->args[1] = 0; -- cgit v1.2.3-58-ga151 From 57a503c61db077b923e23f36050c02166a4a1db2 Mon Sep 17 00:00:00 2001 From: Viresh KUMAR Date: Mon, 2 May 2011 18:36:45 +0000 Subject: net/stmmac: Move "#include " to linux/stmmac.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit stmmac.h uses struct platform_device and doesn't include . Whereas drivers/net/stmmac/stmmac.h includes it, but doesn't directly use it. And so we get following compilation warning while using this file: warning: ‘struct platform_device’ declared inside parameter list This patch includes in linux/stmmac.h and removes it from drivers/net/stmmac/stmmac.h Signed-off-by: Viresh Kumar Acked-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/stmmac.h | 1 - include/linux/stmmac.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h index 5f06c4706abe..2b076b313622 100644 --- a/drivers/net/stmmac/stmmac.h +++ b/drivers/net/stmmac/stmmac.h @@ -21,7 +21,6 @@ *******************************************************************************/ #define DRV_MODULE_VERSION "Nov_2010" -#include #include #include "common.h" diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index f29197a4b227..9529e49b0385 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -26,6 +26,8 @@ #ifndef __STMMAC_PLATFORM_DATA #define __STMMAC_PLATFORM_DATA +#include + /* platform data for platform device structure's platform_data field */ /* Private data for the STM on-board ethernet driver */ -- cgit v1.2.3-58-ga151 From 417da66fa9d2f14b1a90b04095413b87907d8183 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 3 May 2011 19:42:43 -0700 Subject: ipv4: Rework ipmr_rt_fib_lookup() flow key initialization. Use information from the skb as much as possible, currently this means daddr, saddr, and TOS. Signed-off-by: David S. Miller --- net/ipv4/ipmr.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index c81b9b661d26..3ad38a449588 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1788,12 +1788,14 @@ dont_forward: return 0; } -static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct rtable *rt) +static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct sk_buff *skb) { + struct rtable *rt = skb_rtable(skb); + struct iphdr *iph = ip_hdr(skb); struct flowi4 fl4 = { - .daddr = rt->rt_key_dst, - .saddr = rt->rt_key_src, - .flowi4_tos = rt->rt_tos, + .daddr = iph->daddr, + .saddr = iph->saddr, + .flowi4_tos = iph->tos, .flowi4_oif = rt->rt_oif, .flowi4_iif = rt->rt_iif, .flowi4_mark = rt->rt_mark, @@ -1825,7 +1827,7 @@ int ip_mr_input(struct sk_buff *skb) if (IPCB(skb)->flags & IPSKB_FORWARDED) goto dont_forward; - mrt = ipmr_rt_fib_lookup(net, skb_rtable(skb)); + mrt = ipmr_rt_fib_lookup(net, skb); if (IS_ERR(mrt)) { kfree_skb(skb); return PTR_ERR(mrt); @@ -1957,7 +1959,7 @@ int pim_rcv_v1(struct sk_buff *skb) pim = igmp_hdr(skb); - mrt = ipmr_rt_fib_lookup(net, skb_rtable(skb)); + mrt = ipmr_rt_fib_lookup(net, skb); if (IS_ERR(mrt)) goto drop; if (!mrt->mroute_do_pim || @@ -1989,7 +1991,7 @@ static int pim_rcv(struct sk_buff *skb) csum_fold(skb_checksum(skb, 0, skb->len, 0)))) goto drop; - mrt = ipmr_rt_fib_lookup(net, skb_rtable(skb)); + mrt = ipmr_rt_fib_lookup(net, skb); if (IS_ERR(mrt)) goto drop; if (__pim_rcv(mrt, skb, sizeof(*pim))) { -- cgit v1.2.3-58-ga151 From 475949d8e86bbde5ea3ffa4d95e022ca69233b14 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 3 May 2011 19:45:15 -0700 Subject: ipv4: Renamt struct rtable's rt_tos to rt_key_tos. To more accurately reflect that it is purely a routing cache lookup key and is used in no other context. Signed-off-by: David S. Miller --- include/net/route.h | 2 +- net/ipv4/route.c | 24 ++++++++++++------------ net/ipv4/xfrm4_policy.c | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index 16eb59cd7080..f07609e83141 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -52,7 +52,7 @@ struct rtable { int rt_genid; unsigned rt_flags; __u16 rt_type; - __u8 rt_tos; + __u8 rt_key_tos; __be32 rt_dst; /* Path destination */ __be32 rt_src; /* Path source */ diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 64f360d853fb..3bc685454b5b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -424,7 +424,7 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) dst_metric(&r->dst, RTAX_WINDOW), (int)((dst_metric(&r->dst, RTAX_RTT) >> 3) + dst_metric(&r->dst, RTAX_RTTVAR)), - r->rt_tos, + r->rt_key_tos, r->dst.hh ? atomic_read(&r->dst.hh->hh_refcnt) : -1, r->dst.hh ? (r->dst.hh->hh_output == dev_queue_xmit) : 0, @@ -724,7 +724,7 @@ static inline int compare_keys(struct rtable *rt1, struct rtable *rt2) return (((__force u32)rt1->rt_key_dst ^ (__force u32)rt2->rt_key_dst) | ((__force u32)rt1->rt_key_src ^ (__force u32)rt2->rt_key_src) | (rt1->rt_mark ^ rt2->rt_mark) | - (rt1->rt_tos ^ rt2->rt_tos) | + (rt1->rt_key_tos ^ rt2->rt_key_tos) | (rt1->rt_oif ^ rt2->rt_oif) | (rt1->rt_iif ^ rt2->rt_iif)) == 0; } @@ -1349,7 +1349,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) rt_genid(dev_net(dst->dev))); #if RT_CACHE_DEBUG >= 1 printk(KERN_DEBUG "ipv4_negative_advice: redirect to %pI4/%02x dropped\n", - &rt->rt_dst, rt->rt_tos); + &rt->rt_dst, rt->rt_key_tos); #endif rt_del(hash, rt); ret = NULL; @@ -1710,7 +1710,7 @@ void ip_rt_get_source(u8 *addr, struct rtable *rt) struct flowi4 fl4 = { .daddr = rt->rt_key_dst, .saddr = rt->rt_key_src, - .flowi4_tos = rt->rt_tos, + .flowi4_tos = rt->rt_key_tos, .flowi4_oif = rt->rt_oif, .flowi4_iif = rt->rt_iif, .flowi4_mark = rt->rt_mark, @@ -1886,7 +1886,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_genid = rt_genid(dev_net(dev)); rth->rt_flags = RTCF_MULTICAST; rth->rt_type = RTN_MULTICAST; - rth->rt_tos = tos; + rth->rt_key_tos = tos; rth->rt_dst = daddr; rth->rt_src = saddr; rth->rt_route_iif = dev->ifindex; @@ -2023,7 +2023,7 @@ static int __mkroute_input(struct sk_buff *skb, rth->rt_genid = rt_genid(dev_net(rth->dst.dev)); rth->rt_flags = flags; rth->rt_type = res->type; - rth->rt_tos = tos; + rth->rt_key_tos = tos; rth->rt_dst = daddr; rth->rt_src = saddr; rth->rt_route_iif = in_dev->dev->ifindex; @@ -2203,7 +2203,7 @@ local_input: rth->rt_genid = rt_genid(net); rth->rt_flags = flags|RTCF_LOCAL; rth->rt_type = res.type; - rth->rt_tos = tos; + rth->rt_key_tos = tos; rth->rt_dst = daddr; rth->rt_src = saddr; #ifdef CONFIG_IP_ROUTE_CLASSID @@ -2293,7 +2293,7 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, ((__force u32)rth->rt_key_src ^ (__force u32)saddr) | (rth->rt_iif ^ iif) | rth->rt_oif | - (rth->rt_tos ^ tos)) == 0 && + (rth->rt_key_tos ^ tos)) == 0 && rth->rt_mark == skb->mark && net_eq(dev_net(rth->dst.dev), net) && !rt_is_expired(rth)) { @@ -2410,7 +2410,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, rth->rt_genid = rt_genid(dev_net(dev_out)); rth->rt_flags = flags; rth->rt_type = type; - rth->rt_tos = tos; + rth->rt_key_tos = tos; rth->rt_dst = fl4->daddr; rth->rt_src = fl4->saddr; rth->rt_route_iif = 0; @@ -2668,7 +2668,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4) rt_is_output_route(rth) && rth->rt_oif == flp4->flowi4_oif && rth->rt_mark == flp4->flowi4_mark && - !((rth->rt_tos ^ flp4->flowi4_tos) & + !((rth->rt_key_tos ^ flp4->flowi4_tos) & (IPTOS_RT_MASK | RTO_ONLINK)) && net_eq(dev_net(rth->dst.dev), net) && !rt_is_expired(rth)) { @@ -2740,7 +2740,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or rt->rt_key_dst = ort->rt_key_dst; rt->rt_key_src = ort->rt_key_src; - rt->rt_tos = ort->rt_tos; + rt->rt_key_tos = ort->rt_key_tos; rt->rt_route_iif = ort->rt_route_iif; rt->rt_iif = ort->rt_iif; rt->rt_oif = ort->rt_oif; @@ -2803,7 +2803,7 @@ static int rt_fill_info(struct net *net, r->rtm_family = AF_INET; r->rtm_dst_len = 32; r->rtm_src_len = 0; - r->rtm_tos = rt->rt_tos; + r->rtm_tos = rt->rt_key_tos; r->rtm_table = RT_TABLE_MAIN; NLA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN); r->rtm_type = rt->rt_type; diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 59b1340fb3bf..7ff973bd02dd 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -73,7 +73,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, rt->rt_key_dst = fl4->daddr; rt->rt_key_src = fl4->saddr; - rt->rt_tos = fl4->flowi4_tos; + rt->rt_key_tos = fl4->flowi4_tos; rt->rt_route_iif = fl4->flowi4_iif; rt->rt_iif = fl4->flowi4_iif; rt->rt_oif = fl4->flowi4_oif; -- cgit v1.2.3-58-ga151 From f1390160ddcd64a3cfd48b3280d0a616a31b9520 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 3 May 2011 20:06:41 -0700 Subject: dccp: Use flowi4->saddr in dccp_v4_connect() Signed-off-by: David S. Miller --- net/dccp/ipv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index f4254bb4745d..36700a46b245 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -86,7 +86,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) daddr = fl4.daddr; if (inet->inet_saddr == 0) - inet->inet_saddr = rt->rt_src; + inet->inet_saddr = fl4.saddr; inet->inet_rcv_saddr = inet->inet_saddr; inet->inet_dport = usin->sin_port; -- cgit v1.2.3-58-ga151 From 31e4543db29fb85496a122b965d6482c8d1a2bfe Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 3 May 2011 20:25:42 -0700 Subject: ipv4: Make caller provide on-stack flow key to ip_route_output_ports(). Signed-off-by: David S. Miller --- drivers/infiniband/hw/cxgb3/iwch_cm.c | 3 ++- drivers/infiniband/hw/cxgb4/cm.c | 3 ++- drivers/net/pptp.c | 6 ++++-- drivers/scsi/cxgbi/libcxgbi.c | 3 ++- include/net/route.h | 11 +++++------ net/ipv4/af_inet.c | 3 ++- net/ipv4/igmp.c | 6 ++++-- net/ipv4/ip_output.c | 3 ++- net/ipv4/ipip.c | 19 +++++++++++-------- net/ipv4/ipmr.c | 5 +++-- net/ipv6/ip6_tunnel.c | 5 +++-- net/ipv6/sit.c | 6 ++++-- net/l2tp/l2tp_ip.c | 3 ++- net/rxrpc/ar-peer.c | 3 ++- 14 files changed, 48 insertions(+), 31 deletions(-) diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index 3216bcad7e82..239184138994 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -338,8 +338,9 @@ static struct rtable *find_route(struct t3cdev *dev, __be32 local_ip, __be16 peer_port, u8 tos) { struct rtable *rt; + struct flowi4 fl4; - rt = ip_route_output_ports(&init_net, NULL, peer_ip, local_ip, + rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip, peer_port, local_port, IPPROTO_TCP, tos, 0); if (IS_ERR(rt)) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 9d8dcfab2b38..6aa53cd69478 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -315,8 +315,9 @@ static struct rtable *find_route(struct c4iw_dev *dev, __be32 local_ip, __be16 peer_port, u8 tos) { struct rtable *rt; + struct flowi4 fl4; - rt = ip_route_output_ports(&init_net, NULL, peer_ip, local_ip, + rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip, peer_port, local_port, IPPROTO_TCP, tos, 0); if (IS_ERR(rt)) diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c index 51dfcf8023c7..e771e8d27eb7 100644 --- a/drivers/net/pptp.c +++ b/drivers/net/pptp.c @@ -175,6 +175,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) struct pptp_opt *opt = &po->proto.pptp; struct pptp_gre_header *hdr; unsigned int header_len = sizeof(*hdr); + struct flowi4 fl4; int islcp; int len; unsigned char *data; @@ -189,7 +190,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) if (sk_pppox(po)->sk_state & PPPOX_DEAD) goto tx_error; - rt = ip_route_output_ports(&init_net, NULL, + rt = ip_route_output_ports(&init_net, &fl4, NULL, opt->dst_addr.sin_addr.s_addr, opt->src_addr.sin_addr.s_addr, 0, 0, IPPROTO_GRE, @@ -434,6 +435,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, struct pppox_sock *po = pppox_sk(sk); struct pptp_opt *opt = &po->proto.pptp; struct rtable *rt; + struct flowi4 fl4; int error = 0; if (sp->sa_protocol != PX_PROTO_PPTP) @@ -463,7 +465,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, po->chan.private = sk; po->chan.ops = &pptp_chan_ops; - rt = ip_route_output_ports(&init_net, sk, + rt = ip_route_output_ports(&init_net, &fl4, sk, opt->dst_addr.sin_addr.s_addr, opt->src_addr.sin_addr.s_addr, 0, 0, diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index de764ea7419d..0c33d250c7d7 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -454,8 +454,9 @@ static struct rtable *find_route_ipv4(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport, u8 tos) { struct rtable *rt; + struct flowi4 fl4; - rt = ip_route_output_ports(&init_net, NULL, daddr, saddr, + rt = ip_route_output_ports(&init_net, &fl4, NULL, daddr, saddr, dport, sport, IPPROTO_TCP, tos, 0); if (IS_ERR(rt)) return NULL; diff --git a/include/net/route.h b/include/net/route.h index f07609e83141..8c02c871a8ce 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -137,20 +137,19 @@ static inline struct rtable *ip_route_output(struct net *net, __be32 daddr, return ip_route_output_key(net, &fl4); } -static inline struct rtable *ip_route_output_ports(struct net *net, struct sock *sk, +static inline struct rtable *ip_route_output_ports(struct net *net, struct flowi4 *fl4, + struct sock *sk, __be32 daddr, __be32 saddr, __be16 dport, __be16 sport, __u8 proto, __u8 tos, int oif) { - struct flowi4 fl4; - - flowi4_init_output(&fl4, oif, sk ? sk->sk_mark : 0, tos, + flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos, RT_SCOPE_UNIVERSE, proto, sk ? inet_sk_flowi_flags(sk) : 0, daddr, saddr, dport, sport); if (sk) - security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); - return ip_route_output_flow(net, &fl4, sk); + security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); + return ip_route_output_flow(net, fl4, sk); } static inline struct rtable *ip_route_output_gre(struct net *net, diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 4e734992e266..7b91fa8bf83c 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1152,6 +1152,7 @@ int inet_sk_rebuild_header(struct sock *sk) struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); __be32 daddr; struct ip_options_rcu *inet_opt; + struct flowi4 fl4; int err; /* Route is OK, nothing to do. */ @@ -1165,7 +1166,7 @@ int inet_sk_rebuild_header(struct sock *sk) if (inet_opt && inet_opt->opt.srr) daddr = inet_opt->opt.faddr; rcu_read_unlock(); - rt = ip_route_output_ports(sock_net(sk), sk, daddr, inet->inet_saddr, + rt = ip_route_output_ports(sock_net(sk), &fl4, sk, daddr, inet->inet_saddr, inet->inet_dport, inet->inet_sport, sk->sk_protocol, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if); diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 8ae0a5702f56..7c2ef59e3f7d 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -309,6 +309,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) struct iphdr *pip; struct igmpv3_report *pig; struct net *net = dev_net(dev); + struct flowi4 fl4; while (1) { skb = alloc_skb(size + LL_ALLOCATED_SPACE(dev), @@ -321,7 +322,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) } igmp_skb_size(skb) = size; - rt = ip_route_output_ports(net, NULL, IGMPV3_ALL_MCR, 0, + rt = ip_route_output_ports(net, &fl4, NULL, IGMPV3_ALL_MCR, 0, 0, 0, IPPROTO_IGMP, 0, dev->ifindex); if (IS_ERR(rt)) { @@ -650,6 +651,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, struct net_device *dev = in_dev->dev; struct net *net = dev_net(dev); __be32 group = pmc ? pmc->multiaddr : 0; + struct flowi4 fl4; __be32 dst; if (type == IGMPV3_HOST_MEMBERSHIP_REPORT) @@ -659,7 +661,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, else dst = group; - rt = ip_route_output_ports(net, NULL, dst, 0, + rt = ip_route_output_ports(net, &fl4, NULL, dst, 0, 0, 0, IPPROTO_IGMP, 0, dev->ifindex); if (IS_ERR(rt)) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 362e66f7d2fb..3aa4c31e5448 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -333,6 +333,7 @@ int ip_queue_xmit(struct sk_buff *skb) /* Make sure we can route this packet. */ rt = (struct rtable *)__sk_dst_check(sk, 0); if (rt == NULL) { + struct flowi4 fl4; __be32 daddr; /* Use correct destination address if we have options. */ @@ -344,7 +345,7 @@ int ip_queue_xmit(struct sk_buff *skb) * keep trying until route appears or the connection times * itself out. */ - rt = ip_route_output_ports(sock_net(sk), sk, + rt = ip_route_output_ports(sock_net(sk), &fl4, sk, daddr, inet->inet_saddr, inet->inet_dport, inet->inet_sport, diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index ef16377ec73f..88d96bde9500 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -442,6 +442,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) struct iphdr *iph; /* Our new IP header */ unsigned int max_headroom; /* The extra header space needed */ __be32 dst = tiph->daddr; + struct flowi4 fl4; int mtu; if (skb->protocol != htons(ETH_P_IP)) @@ -460,7 +461,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) goto tx_error_icmp; } - rt = ip_route_output_ports(dev_net(dev), NULL, + rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, dst, tiph->saddr, 0, 0, IPPROTO_IPIP, RT_TOS(tos), @@ -578,13 +579,15 @@ static void ipip_tunnel_bind_dev(struct net_device *dev) iph = &tunnel->parms.iph; if (iph->daddr) { - struct rtable *rt = ip_route_output_ports(dev_net(dev), NULL, - iph->daddr, iph->saddr, - 0, 0, - IPPROTO_IPIP, - RT_TOS(iph->tos), - tunnel->parms.link); - + struct rtable *rt; + struct flowi4 fl4; + + rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, + iph->daddr, iph->saddr, + 0, 0, + IPPROTO_IPIP, + RT_TOS(iph->tos), + tunnel->parms.link); if (!IS_ERR(rt)) { tdev = rt->dst.dev; ip_rt_put(rt); diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 3ad38a449588..86033b7a05ba 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1595,6 +1595,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, struct vif_device *vif = &mrt->vif_table[vifi]; struct net_device *dev; struct rtable *rt; + struct flowi4 fl4; int encap = 0; if (vif->dev == NULL) @@ -1612,7 +1613,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, #endif if (vif->flags & VIFF_TUNNEL) { - rt = ip_route_output_ports(net, NULL, + rt = ip_route_output_ports(net, &fl4, NULL, vif->remote, vif->local, 0, 0, IPPROTO_IPIP, @@ -1621,7 +1622,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, goto out_free; encap = sizeof(struct iphdr); } else { - rt = ip_route_output_ports(net, NULL, iph->daddr, 0, + rt = ip_route_output_ports(net, &fl4, NULL, iph->daddr, 0, 0, 0, IPPROTO_IPIP, RT_TOS(iph->tos), vif->link); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 9dd0e964b8bd..3dff27cba95c 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -537,6 +537,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct sk_buff *skb2; const struct iphdr *eiph; struct rtable *rt; + struct flowi4 fl4; err = ip6_tnl_err(skb, IPPROTO_IPIP, opt, &rel_type, &rel_code, &rel_msg, &rel_info, offset); @@ -577,7 +578,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, eiph = ip_hdr(skb2); /* Try to guess incoming interface */ - rt = ip_route_output_ports(dev_net(skb->dev), NULL, + rt = ip_route_output_ports(dev_net(skb->dev), &fl4, NULL, eiph->saddr, 0, 0, 0, IPPROTO_IPIP, RT_TOS(eiph->tos), 0); @@ -590,7 +591,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (rt->rt_flags & RTCF_LOCAL) { ip_rt_put(rt); rt = NULL; - rt = ip_route_output_ports(dev_net(skb->dev), NULL, + rt = ip_route_output_ports(dev_net(skb->dev), &fl4, NULL, eiph->daddr, eiph->saddr, 0, 0, IPPROTO_IPIP, diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 34d896426701..a24fb14d91f3 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -674,6 +674,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, struct iphdr *iph; /* Our new IP header */ unsigned int max_headroom; /* The extra header space needed */ __be32 dst = tiph->daddr; + struct flowi4 fl4; int mtu; const struct in6_addr *addr6; int addr_type; @@ -733,7 +734,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, dst = addr6->s6_addr32[3]; } - rt = ip_route_output_ports(dev_net(dev), NULL, + rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, dst, tiph->saddr, 0, 0, IPPROTO_IPV6, RT_TOS(tos), @@ -851,12 +852,13 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) struct net_device *tdev = NULL; struct ip_tunnel *tunnel; const struct iphdr *iph; + struct flowi4 fl4; tunnel = netdev_priv(dev); iph = &tunnel->parms.iph; if (iph->daddr) { - struct rtable *rt = ip_route_output_ports(dev_net(dev), NULL, + struct rtable *rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, iph->daddr, iph->saddr, 0, 0, IPPROTO_IPV6, diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index a4d2dfa1fdbf..81899600abe2 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -471,6 +471,7 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m if (rt == NULL) { struct ip_options_rcu *inet_opt; + struct flowi4 fl4; rcu_read_lock(); inet_opt = rcu_dereference(inet->inet_opt); @@ -485,7 +486,7 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m * keep trying until route appears or the connection times * itself out. */ - rt = ip_route_output_ports(sock_net(sk), sk, + rt = ip_route_output_ports(sock_net(sk), &fl4, sk, daddr, inet->inet_saddr, inet->inet_dport, inet->inet_sport, sk->sk_protocol, RT_CONN_FLAGS(sk), diff --git a/net/rxrpc/ar-peer.c b/net/rxrpc/ar-peer.c index 55b93dc60d0c..b6ff06351d67 100644 --- a/net/rxrpc/ar-peer.c +++ b/net/rxrpc/ar-peer.c @@ -36,10 +36,11 @@ static void rxrpc_destroy_peer(struct work_struct *work); static void rxrpc_assess_MTU_size(struct rxrpc_peer *peer) { struct rtable *rt; + struct flowi4 fl4; peer->if_mtu = 1500; - rt = ip_route_output_ports(&init_net, NULL, + rt = ip_route_output_ports(&init_net, &fl4, NULL, peer->srx.transport.sin.sin_addr.s_addr, 0, htons(7000), htons(7001), IPPROTO_UDP, 0, 0); -- cgit v1.2.3-58-ga151 From 28c90da02ed7367fc5714adefce2a961e5bae306 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 3 May 2011 20:41:42 -0700 Subject: pptp: Use flowi4's daddr/saddr in pptp_xmit(). Instead of rt->rt_{src,dst} Signed-off-by: David S. Miller --- drivers/net/pptp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c index e771e8d27eb7..1286fe212dc4 100644 --- a/drivers/net/pptp.c +++ b/drivers/net/pptp.c @@ -271,8 +271,8 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) iph->frag_off = 0; iph->protocol = IPPROTO_GRE; iph->tos = 0; - iph->daddr = rt->rt_dst; - iph->saddr = rt->rt_src; + iph->daddr = fl4.daddr; + iph->saddr = fl4.saddr; iph->ttl = ip4_dst_hoplimit(&rt->dst); iph->tot_len = htons(skb->len); -- cgit v1.2.3-58-ga151 From f4bfd99f8519e2d35541cc4fc383b1b3141a657a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 3 May 2011 20:43:40 -0700 Subject: libcxgbi: Use flowi4's saddr in cxgbi_check_route(). Instead of rt->rt_src Signed-off-by: David S. Miller --- drivers/scsi/cxgbi/libcxgbi.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index 0c33d250c7d7..a2a9c7c6c643 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -450,13 +450,13 @@ static struct cxgbi_sock *cxgbi_sock_create(struct cxgbi_device *cdev) return csk; } -static struct rtable *find_route_ipv4(__be32 saddr, __be32 daddr, +static struct rtable *find_route_ipv4(struct flowi4 *fl4, + __be32 saddr, __be32 daddr, __be16 sport, __be16 dport, u8 tos) { struct rtable *rt; - struct flowi4 fl4; - rt = ip_route_output_ports(&init_net, &fl4, NULL, daddr, saddr, + rt = ip_route_output_ports(&init_net, fl4, NULL, daddr, saddr, dport, sport, IPPROTO_TCP, tos, 0); if (IS_ERR(rt)) return NULL; @@ -471,6 +471,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr) struct net_device *ndev; struct cxgbi_device *cdev; struct rtable *rt = NULL; + struct flowi4 fl4; struct cxgbi_sock *csk = NULL; unsigned int mtu = 0; int port = 0xFFFF; @@ -483,7 +484,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr) goto err_out; } - rt = find_route_ipv4(0, daddr->sin_addr.s_addr, 0, daddr->sin_port, 0); + rt = find_route_ipv4(&fl4, 0, daddr->sin_addr.s_addr, 0, daddr->sin_port, 0); if (!rt) { pr_info("no route to ipv4 0x%x, port %u.\n", daddr->sin_addr.s_addr, daddr->sin_port); @@ -532,7 +533,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr) csk->daddr.sin_addr.s_addr = daddr->sin_addr.s_addr; csk->daddr.sin_port = daddr->sin_port; csk->daddr.sin_family = daddr->sin_family; - csk->saddr.sin_addr.s_addr = rt->rt_src; + csk->saddr.sin_addr.s_addr = fl4.saddr; return csk; -- cgit v1.2.3-58-ga151 From 492f64ce12e259abd85714d05b885e105bd8aeef Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 3 May 2011 20:53:12 -0700 Subject: ipv4: Use flowi4's {saddr,daddr} in igmpv3_newpack() and igmp_send_report() Instead of rt->rt_{src,dst} Signed-off-by: David S. Miller --- net/ipv4/igmp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 7c2ef59e3f7d..ec03c2fda6ce 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -344,8 +344,8 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) pip->tos = 0xc0; pip->frag_off = htons(IP_DF); pip->ttl = 1; - pip->daddr = rt->rt_dst; - pip->saddr = rt->rt_src; + pip->daddr = fl4.daddr; + pip->saddr = fl4.saddr; pip->protocol = IPPROTO_IGMP; pip->tot_len = 0; /* filled in later */ ip_select_ident(pip, &rt->dst, NULL); @@ -687,7 +687,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, iph->frag_off = htons(IP_DF); iph->ttl = 1; iph->daddr = dst; - iph->saddr = rt->rt_src; + iph->saddr = fl4.saddr; iph->protocol = IPPROTO_IGMP; ip_select_ident(iph, &rt->dst, NULL); ((u8*)&iph[1])[0] = IPOPT_RA; -- cgit v1.2.3-58-ga151 From 18a353f42817f08e3501162ceda9d2efddb08a40 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 3 May 2011 20:55:05 -0700 Subject: sctp: Use flowi4's {saddr,daddr} in sctp_v4_dst_saddr() and sctp_v4_get_dst() Instead of rt->rt_{src,dst} Signed-off-by: David S. Miller --- net/sctp/protocol.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 9d3f15957d12..69fbc55cf18e 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -339,13 +339,12 @@ static int sctp_v4_to_addr_param(const union sctp_addr *addr, } /* Initialize a sctp_addr from a dst_entry. */ -static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst, +static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct flowi4 *fl4, __be16 port) { - struct rtable *rt = (struct rtable *)dst; saddr->v4.sin_family = AF_INET; saddr->v4.sin_port = port; - saddr->v4.sin_addr.s_addr = rt->rt_src; + saddr->v4.sin_addr.s_addr = fl4->saddr; } /* Compare two addresses exactly. */ @@ -508,7 +507,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, /* Walk through the bind address list and look for a bind * address that matches the source address of the returned dst. */ - sctp_v4_dst_saddr(&dst_saddr, dst, htons(bp->port)); + sctp_v4_dst_saddr(&dst_saddr, fl4, htons(bp->port)); rcu_read_lock(); list_for_each_entry_rcu(laddr, &bp->address_list, list) { if (!laddr->valid || (laddr->state != SCTP_ADDR_SRC)) @@ -550,7 +549,7 @@ out: t->dst = dst; if (dst) SCTP_DEBUG_PRINTK("rt_dst:%pI4, rt_src:%pI4\n", - &rt->rt_dst, &rt->rt_src); + &fl4->daddr, &fl4->saddr); else SCTP_DEBUG_PRINTK("NO ROUTE\n"); } -- cgit v1.2.3-58-ga151 From 9cddf15f18865c4f7124d829be41799f59aaa5cf Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 4 May 2011 11:06:05 -0700 Subject: x86/net: only select BPF_JIT when NET is enabled Fix kconfig unmet dependency warning: HAVE_BPF_JIT depends on NET, so make the "select" of it depend on NET also. warning: (X86) selects HAVE_BPF_JIT which has unmet direct dependencies (NET) Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 855a1bdc437d..2096cf180648 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -72,7 +72,7 @@ config X86 select IRQ_FORCED_THREADING select USE_GENERIC_SMP_HELPERS if SMP select ARCH_NO_SYSDEV_OPS - select HAVE_BPF_JIT if X86_64 + select HAVE_BPF_JIT if (X86_64 && NET) config INSTRUCTION_DECODER def_bool (KPROBES || PERF_EVENTS) -- cgit v1.2.3-58-ga151 From 69458cb194e82972347a004054e0baed719ed008 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 4 May 2011 11:10:28 -0700 Subject: ipv4: Use flowi4->{daddr,saddr} in ipip_tunnel_xmit(). Instead of rt->rt_{dst,src} Signed-off-by: David S. Miller --- net/ipv4/ipip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 88d96bde9500..bfa0b9895040 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -550,8 +550,8 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) iph->frag_off = df; iph->protocol = IPPROTO_IPIP; iph->tos = INET_ECN_encapsulate(tos, old_iph->tos); - iph->daddr = rt->rt_dst; - iph->saddr = rt->rt_src; + iph->daddr = fl4.daddr; + iph->saddr = fl4.saddr; if ((iph->ttl = tiph->ttl) == 0) iph->ttl = old_iph->ttl; -- cgit v1.2.3-58-ga151 From dca97ad2ec37aa98c45dfe1d531d9ba7048e814e Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Wed, 27 Apr 2011 08:51:29 +0000 Subject: e100: fix build warning In function 'e100_hw_init': warning: 'err' may be used uninitialized in this function Signed-off-by: Emil Tantilov Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/e100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index c810cda3bf1f..29f812dc1098 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1512,7 +1512,7 @@ static int e100_phy_init(struct nic *nic) static int e100_hw_init(struct nic *nic) { - int err; + int err = 0; e100_hw_reset(nic); -- cgit v1.2.3-58-ga151 From dd927a2694ee412b440284dd72dd8e32caada3fc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 4 May 2011 12:03:30 -0700 Subject: ipv4: In ip_build_and_send_pkt() use 'saddr' and 'daddr' args passed in. Instead of rt->rt_{dst,src} The only tricky part is source route option handling. If the source route option is enabled we can't just use plain 'daddr', we have to use opt->opt.faddr. Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 3aa4c31e5448..db38c1822de8 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -158,8 +158,8 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, else iph->frag_off = 0; iph->ttl = ip_select_ttl(inet, &rt->dst); - iph->daddr = rt->rt_dst; - iph->saddr = rt->rt_src; + iph->daddr = (opt && opt->opt.srr ? opt->opt.faddr : daddr); + iph->saddr = saddr; iph->protocol = sk->sk_protocol; ip_select_ident(iph, &rt->dst, sk); -- cgit v1.2.3-58-ga151 From ec7e97e9a0265255485e217f4f2d3513949e7083 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Tue, 3 May 2011 05:17:34 +0000 Subject: ixgb: convert to set_phys_id Based on the original patch sent by Stephen Hemminger. This version incorporates the ethtool changes that Bruce Allan submitted. CC: Stephen Hemminger Signed-off-by: Jeff Kirsher Tested-by: Evan Swanson --- drivers/net/ixgb/ixgb.h | 3 --- drivers/net/ixgb/ixgb_ethtool.c | 46 +++++++++++------------------------------ 2 files changed, 12 insertions(+), 37 deletions(-) diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h index 8f3df044e81e..49e8408f05fc 100644 --- a/drivers/net/ixgb/ixgb.h +++ b/drivers/net/ixgb/ixgb.h @@ -157,9 +157,6 @@ struct ixgb_adapter { u16 link_duplex; struct work_struct tx_timeout_task; - struct timer_list blink_timer; - unsigned long led_status; - /* TX */ struct ixgb_desc_ring tx_ring ____cacheline_aligned_in_smp; unsigned int restart_queue; diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c index 5f224c387e0c..6da890b9534c 100644 --- a/drivers/net/ixgb/ixgb_ethtool.c +++ b/drivers/net/ixgb/ixgb_ethtool.c @@ -611,45 +611,23 @@ err_setup_rx: return err; } -/* toggle LED 4 times per second = 2 "blinks" per second */ -#define IXGB_ID_INTERVAL (HZ/4) - -/* bit defines for adapter->led_status */ -#define IXGB_LED_ON 0 - -static void -ixgb_led_blink_callback(unsigned long data) -{ - struct ixgb_adapter *adapter = (struct ixgb_adapter *)data; - - if (test_and_change_bit(IXGB_LED_ON, &adapter->led_status)) - ixgb_led_off(&adapter->hw); - else - ixgb_led_on(&adapter->hw); - - mod_timer(&adapter->blink_timer, jiffies + IXGB_ID_INTERVAL); -} - static int -ixgb_phys_id(struct net_device *netdev, u32 data) +ixgb_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) { struct ixgb_adapter *adapter = netdev_priv(netdev); - if (!data) - data = INT_MAX; - - if (!adapter->blink_timer.function) { - init_timer(&adapter->blink_timer); - adapter->blink_timer.function = ixgb_led_blink_callback; - adapter->blink_timer.data = (unsigned long)adapter; - } + switch (state) { + case ETHTOOL_ID_ACTIVE: + return 2; - mod_timer(&adapter->blink_timer, jiffies); + case ETHTOOL_ID_ON: + ixgb_led_on(&adapter->hw); + break; - msleep_interruptible(data * 1000); - del_timer_sync(&adapter->blink_timer); - ixgb_led_off(&adapter->hw); - clear_bit(IXGB_LED_ON, &adapter->led_status); + case ETHTOOL_ID_OFF: + case ETHTOOL_ID_INACTIVE: + ixgb_led_off(&adapter->hw); + } return 0; } @@ -767,7 +745,7 @@ static const struct ethtool_ops ixgb_ethtool_ops = { .set_msglevel = ixgb_set_msglevel, .set_tso = ixgb_set_tso, .get_strings = ixgb_get_strings, - .phys_id = ixgb_phys_id, + .set_phys_id = ixgb_set_phys_id, .get_sset_count = ixgb_get_sset_count, .get_ethtool_stats = ixgb_get_ethtool_stats, .get_flags = ethtool_op_get_flags, -- cgit v1.2.3-58-ga151 From f6b1bfd17d42f9dc1d799b7e0eed817ed75005ec Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Wed, 4 May 2011 04:29:51 +0000 Subject: igb: Add check for invalid size to igb_get_invariants_82575() Recent commits have changed how EEPROM size is checked and if the size word is misconfigured, the driver will fail to load. This patch adds a check for invalid size word in the EEPROM and uses default size instead for 82576 parts. Reported-by: Stefan Assmann Signed-off-by: Carolyn Wyborny Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/igb/e1000_82575.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 0cd41c49bc17..0f563c8c5ffc 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -244,6 +244,14 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) */ size += NVM_WORD_SIZE_BASE_SHIFT; + /* + * Check for invalid size + */ + if ((hw->mac.type == e1000_82576) && (size > 15)) { + printk("igb: The NVM size is not valid, " + "defaulting to 32K.\n"); + size = 15; + } nvm->word_size = 1 << size; if (nvm->word_size == (1 << 15)) nvm->page_size = 128; -- cgit v1.2.3-58-ga151 From 97322b3303a1de979b973dc1d0a43091f27258ac Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Tue, 5 Apr 2011 04:26:27 +0000 Subject: igbvf: remove bogus phys_id This device lies about supporting phys_id. Remove it and just let the upper layer report not supported. Signed-off-by: Stephen Hemminger Tested-by: Signed-off-by: Jeff Kirsher --- drivers/net/igbvf/ethtool.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c index 112ae15b2d49..b0b14d63dfbf 100644 --- a/drivers/net/igbvf/ethtool.c +++ b/drivers/net/igbvf/ethtool.c @@ -391,11 +391,6 @@ static int igbvf_set_wol(struct net_device *netdev, return -EOPNOTSUPP; } -static int igbvf_phys_id(struct net_device *netdev, u32 data) -{ - return 0; -} - static int igbvf_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { @@ -527,7 +522,6 @@ static const struct ethtool_ops igbvf_ethtool_ops = { .self_test = igbvf_diag_test, .get_sset_count = igbvf_get_sset_count, .get_strings = igbvf_get_strings, - .phys_id = igbvf_phys_id, .get_ethtool_stats = igbvf_get_ethtool_stats, .get_coalesce = igbvf_get_coalesce, .set_coalesce = igbvf_set_coalesce, -- cgit v1.2.3-58-ga151 From 6d980c3e50189e5437fdb5ef2c6e6d3c282035dc Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Wed, 13 Apr 2011 04:56:15 +0000 Subject: ixgbe: Use function pointer for ixgbe_acquire/release_swfw_sync() Change remaining direct calls to function pointers. Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82599.c | 3 +-- drivers/net/ixgbe/ixgbe_phy.c | 10 +++++----- drivers/net/ixgbe/ixgbe_x540.c | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index d1cda36507f8..5b8e17efd8d2 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -110,7 +110,6 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset, &data_offset); - if (ret_val != 0) goto setup_sfp_out; @@ -130,7 +129,7 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) } /* Release the semaphore */ - ixgbe_release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); /* * Delay obtaining semaphore again to allow FW access, * semaphore_delay is in ms usleep_range needs us. diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index edcaaebd72b2..735f686c3b36 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -1222,7 +1222,7 @@ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, swfw_mask = IXGBE_GSSR_PHY0_SM; do { - if (ixgbe_acquire_swfw_sync(hw, swfw_mask) != 0) { + if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != 0) { status = IXGBE_ERR_SWFW_SYNC; goto read_byte_out; } @@ -1269,7 +1269,7 @@ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, break; fail: - ixgbe_release_swfw_sync(hw, swfw_mask); + hw->mac.ops.release_swfw_sync(hw, swfw_mask); msleep(100); ixgbe_i2c_bus_clear(hw); retry++; @@ -1280,7 +1280,7 @@ fail: } while (retry < max_retry); - ixgbe_release_swfw_sync(hw, swfw_mask); + hw->mac.ops.release_swfw_sync(hw, swfw_mask); read_byte_out: return status; @@ -1308,7 +1308,7 @@ s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, else swfw_mask = IXGBE_GSSR_PHY0_SM; - if (ixgbe_acquire_swfw_sync(hw, swfw_mask) != 0) { + if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != 0) { status = IXGBE_ERR_SWFW_SYNC; goto write_byte_out; } @@ -1352,7 +1352,7 @@ fail: hw_dbg(hw, "I2C byte write error.\n"); } while (retry < max_retry); - ixgbe_release_swfw_sync(hw, swfw_mask); + hw->mac.ops.release_swfw_sync(hw, swfw_mask); write_byte_out: return status; diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c index 75c6465db893..179ee8226d04 100644 --- a/drivers/net/ixgbe/ixgbe_x540.c +++ b/drivers/net/ixgbe/ixgbe_x540.c @@ -318,7 +318,7 @@ static s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data) else status = IXGBE_ERR_SWFW_SYNC; - ixgbe_release_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM); + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); return status; } -- cgit v1.2.3-58-ga151 From 2698b20842884d7d4de55ea559baa57e2f2ebea4 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Wed, 13 Apr 2011 07:01:52 +0000 Subject: ixgbe: fix typo error with software defined pins on 82599 Correcting a simple typo with enabling software defined pins. I don't believe this was causing any issues but this is how it was meant to be implemented. Signed-off-by: Don Skidmore Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 9160811c6d7d..bd3d21d01853 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3862,9 +3862,10 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter) if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) gpie |= IXGBE_SDP1_GPIEN; - if (hw->mac.type == ixgbe_mac_82599EB) + if (hw->mac.type == ixgbe_mac_82599EB) { gpie |= IXGBE_SDP1_GPIEN; gpie |= IXGBE_SDP2_GPIEN; + } IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); } -- cgit v1.2.3-58-ga151 From 95a46011843a3c49e1a002eddb6b2735c201e378 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 14 Apr 2011 07:46:41 +0000 Subject: ixgbe: fix sparse warning warning: symbol 'before' shadows an earlier one Convert large macros to functions similar to e1000e. Signed-off-by: Emil Tantilov Acked-by: Don Skidmore Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_ethtool.c | 108 ++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 46 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index bcba057b510f..410c29875785 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1236,46 +1236,62 @@ static const struct ixgbe_reg_test reg_test_82598[] = { { 0, 0, 0, 0 } }; -static const u32 register_test_patterns[] = { - 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF -}; - -#define REG_PATTERN_TEST(R, M, W) \ -{ \ - u32 pat, val, before; \ - for (pat = 0; pat < ARRAY_SIZE(register_test_patterns); pat++) { \ - before = readl(adapter->hw.hw_addr + R); \ - writel((register_test_patterns[pat] & W), \ - (adapter->hw.hw_addr + R)); \ - val = readl(adapter->hw.hw_addr + R); \ - if (val != (register_test_patterns[pat] & W & M)) { \ - e_err(drv, "pattern test reg %04X failed: got " \ - "0x%08X expected 0x%08X\n", \ - R, val, (register_test_patterns[pat] & W & M)); \ - *data = R; \ - writel(before, adapter->hw.hw_addr + R); \ - return 1; \ - } \ - writel(before, adapter->hw.hw_addr + R); \ - } \ +static bool reg_pattern_test(struct ixgbe_adapter *adapter, u64 *data, int reg, + u32 mask, u32 write) +{ + u32 pat, val, before; + static const u32 test_pattern[] = { + 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; + + for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) { + before = readl(adapter->hw.hw_addr + reg); + writel((test_pattern[pat] & write), + (adapter->hw.hw_addr + reg)); + val = readl(adapter->hw.hw_addr + reg); + if (val != (test_pattern[pat] & write & mask)) { + e_err(drv, "pattern test reg %04X failed: got " + "0x%08X expected 0x%08X\n", + reg, val, (test_pattern[pat] & write & mask)); + *data = reg; + writel(before, adapter->hw.hw_addr + reg); + return 1; + } + writel(before, adapter->hw.hw_addr + reg); + } + return 0; } -#define REG_SET_AND_CHECK(R, M, W) \ -{ \ - u32 val, before; \ - before = readl(adapter->hw.hw_addr + R); \ - writel((W & M), (adapter->hw.hw_addr + R)); \ - val = readl(adapter->hw.hw_addr + R); \ - if ((W & M) != (val & M)) { \ - e_err(drv, "set/check reg %04X test failed: got 0x%08X " \ - "expected 0x%08X\n", R, (val & M), (W & M)); \ - *data = R; \ - writel(before, (adapter->hw.hw_addr + R)); \ - return 1; \ - } \ - writel(before, (adapter->hw.hw_addr + R)); \ +static bool reg_set_and_check(struct ixgbe_adapter *adapter, u64 *data, int reg, + u32 mask, u32 write) +{ + u32 val, before; + before = readl(adapter->hw.hw_addr + reg); + writel((write & mask), (adapter->hw.hw_addr + reg)); + val = readl(adapter->hw.hw_addr + reg); + if ((write & mask) != (val & mask)) { + e_err(drv, "set/check reg %04X test failed: got 0x%08X " + "expected 0x%08X\n", reg, (val & mask), (write & mask)); + *data = reg; + writel(before, (adapter->hw.hw_addr + reg)); + return 1; + } + writel(before, (adapter->hw.hw_addr + reg)); + return 0; } +#define REG_PATTERN_TEST(reg, mask, write) \ + do { \ + if (reg_pattern_test(adapter, data, reg, mask, write)) \ + return 1; \ + } while (0) \ + + +#define REG_SET_AND_CHECK(reg, mask, write) \ + do { \ + if (reg_set_and_check(adapter, data, reg, mask, write)) \ + return 1; \ + } while (0) \ + static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data) { const struct ixgbe_reg_test *test; @@ -1326,13 +1342,13 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data) switch (test->test_type) { case PATTERN_TEST: REG_PATTERN_TEST(test->reg + (i * 0x40), - test->mask, - test->write); + test->mask, + test->write); break; case SET_READ_TEST: REG_SET_AND_CHECK(test->reg + (i * 0x40), - test->mask, - test->write); + test->mask, + test->write); break; case WRITE_NO_TEST: writel(test->write, @@ -1341,18 +1357,18 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data) break; case TABLE32_TEST: REG_PATTERN_TEST(test->reg + (i * 4), - test->mask, - test->write); + test->mask, + test->write); break; case TABLE64_TEST_LO: REG_PATTERN_TEST(test->reg + (i * 8), - test->mask, - test->write); + test->mask, + test->write); break; case TABLE64_TEST_HI: REG_PATTERN_TEST((test->reg + 4) + (i * 8), - test->mask, - test->write); + test->mask, + test->write); break; } } -- cgit v1.2.3-58-ga151 From 68c7005d664724eab87627b042e149a736622d54 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Wed, 20 Apr 2011 08:49:06 +0000 Subject: ixgbe: improve EEPROM read/write operations Introduce buffered read/writes which greatly improves performance on parts with large EEPROMs. Previously reading/writing a word requires taking/releasing of synchronization semaphores which adds 10ms to each operation. The optimization is to read/write in buffers, but make sure the semaphore is not held for >500ms according to the datasheet. Since we can't read the EEPROM page size ixgbe_detect_eeprom_page_size() is used to discover the EEPROM size when needed and keeps the result in word_page_size for the rest of the run time. Use buffered reads for ethtool -e. Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82598.c | 1 + drivers/net/ixgbe/ixgbe_82599.c | 35 +++ drivers/net/ixgbe/ixgbe_common.c | 440 ++++++++++++++++++++++++++++++-------- drivers/net/ixgbe/ixgbe_common.h | 8 + drivers/net/ixgbe/ixgbe_ethtool.c | 7 +- drivers/net/ixgbe/ixgbe_type.h | 7 + drivers/net/ixgbe/ixgbe_x540.c | 67 +++++- 7 files changed, 465 insertions(+), 100 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 7a64f50435cf..8179e5060a18 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -1281,6 +1281,7 @@ static struct ixgbe_mac_operations mac_ops_82598 = { static struct ixgbe_eeprom_operations eeprom_ops_82598 = { .init_params = &ixgbe_init_eeprom_params_generic, .read = &ixgbe_read_eerd_generic, + .read_buffer = &ixgbe_read_eerd_buffer_generic, .calc_checksum = &ixgbe_calc_eeprom_checksum_generic, .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, .update_checksum = &ixgbe_update_eeprom_checksum_generic, diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 5b8e17efd8d2..dba5ca6e35c4 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -2063,6 +2063,39 @@ out: return lesm_enabled; } +/** + * ixgbe_read_eeprom_buffer_82599 - Read EEPROM word(s) using + * fastest available method + * + * @hw: pointer to hardware structure + * @offset: offset of word in EEPROM to read + * @words: number of words + * @data: word(s) read from the EEPROM + * + * Retrieves 16 bit word(s) read from EEPROM + **/ +static s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset, + u16 words, u16 *data) +{ + struct ixgbe_eeprom_info *eeprom = &hw->eeprom; + s32 ret_val = IXGBE_ERR_CONFIG; + + /* + * If EEPROM is detected and can be addressed using 14 bits, + * use EERD otherwise use bit bang + */ + if ((eeprom->type == ixgbe_eeprom_spi) && + (offset + (words - 1) <= IXGBE_EERD_MAX_ADDR)) + ret_val = ixgbe_read_eerd_buffer_generic(hw, offset, words, + data); + else + ret_val = ixgbe_read_eeprom_buffer_bit_bang_generic(hw, offset, + words, + data); + + return ret_val; +} + /** * ixgbe_read_eeprom_82599 - Read EEPROM word using * fastest available method @@ -2139,7 +2172,9 @@ static struct ixgbe_mac_operations mac_ops_82599 = { static struct ixgbe_eeprom_operations eeprom_ops_82599 = { .init_params = &ixgbe_init_eeprom_params_generic, .read = &ixgbe_read_eeprom_82599, + .read_buffer = &ixgbe_read_eeprom_buffer_82599, .write = &ixgbe_write_eeprom_generic, + .write_buffer = &ixgbe_write_eeprom_buffer_bit_bang_generic, .calc_checksum = &ixgbe_calc_eeprom_checksum_generic, .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, .update_checksum = &ixgbe_update_eeprom_checksum_generic, diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index cb2e8e18dd39..c4730cd39b22 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -55,6 +55,12 @@ static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm); static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num); static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg); +static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, + u16 words, u16 *data); +static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, + u16 words, u16 *data); +static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, + u16 offset); /** * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx @@ -585,6 +591,8 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) /* Set default semaphore delay to 10ms which is a well * tested value */ eeprom->semaphore_delay = 10; + /* Clear EEPROM page size, it will be initialized as needed */ + eeprom->word_page_size = 0; /* * Check for EEPROM present first. @@ -617,26 +625,78 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) } /** - * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM + * ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang * @hw: pointer to hardware structure - * @offset: offset within the EEPROM to be written to - * @data: 16 bit word to be written to the EEPROM + * @offset: offset within the EEPROM to write + * @words: number of words + * @data: 16 bit word(s) to write to EEPROM * - * If ixgbe_eeprom_update_checksum is not called after this function, the - * EEPROM will most likely contain an invalid checksum. + * Reads 16 bit word(s) from EEPROM through bit-bang method **/ -s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) +s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, + u16 words, u16 *data) { - s32 status; - u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; + s32 status = 0; + u16 i, count; hw->eeprom.ops.init_params(hw); - if (offset >= hw->eeprom.word_size) { + if (words == 0) { + status = IXGBE_ERR_INVALID_ARGUMENT; + goto out; + } + + if (offset + words > hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } + /* + * The EEPROM page size cannot be queried from the chip. We do lazy + * initialization. It is worth to do that when we write large buffer. + */ + if ((hw->eeprom.word_page_size == 0) && + (words > IXGBE_EEPROM_PAGE_SIZE_MAX)) + ixgbe_detect_eeprom_page_size_generic(hw, offset); + + /* + * We cannot hold synchronization semaphores for too long + * to avoid other entity starvation. However it is more efficient + * to read in bursts than synchronizing access for each word. + */ + for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { + count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? + IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); + status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i, + count, &data[i]); + + if (status != 0) + break; + } + +out: + return status; +} + +/** + * ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM + * @hw: pointer to hardware structure + * @offset: offset within the EEPROM to be written to + * @words: number of word(s) + * @data: 16 bit word(s) to be written to the EEPROM + * + * If ixgbe_eeprom_update_checksum is not called after this function, the + * EEPROM will most likely contain an invalid checksum. + **/ +static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, + u16 words, u16 *data) +{ + s32 status; + u16 word; + u16 page_size; + u16 i; + u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; + /* Prepare the EEPROM for writing */ status = ixgbe_acquire_eeprom(hw); @@ -648,62 +708,147 @@ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) } if (status == 0) { - ixgbe_standby_eeprom(hw); + for (i = 0; i < words; i++) { + ixgbe_standby_eeprom(hw); - /* Send the WRITE ENABLE command (8 bit opcode ) */ - ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI, - IXGBE_EEPROM_OPCODE_BITS); + /* Send the WRITE ENABLE command (8 bit opcode ) */ + ixgbe_shift_out_eeprom_bits(hw, + IXGBE_EEPROM_WREN_OPCODE_SPI, + IXGBE_EEPROM_OPCODE_BITS); - ixgbe_standby_eeprom(hw); + ixgbe_standby_eeprom(hw); - /* - * Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((hw->eeprom.address_bits == 8) && (offset >= 128)) - write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; + /* + * Some SPI eeproms use the 8th address bit embedded + * in the opcode + */ + if ((hw->eeprom.address_bits == 8) && + ((offset + i) >= 128)) + write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; + + /* Send the Write command (8-bit opcode + addr) */ + ixgbe_shift_out_eeprom_bits(hw, write_opcode, + IXGBE_EEPROM_OPCODE_BITS); + ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), + hw->eeprom.address_bits); + + page_size = hw->eeprom.word_page_size; + + /* Send the data in burst via SPI*/ + do { + word = data[i]; + word = (word >> 8) | (word << 8); + ixgbe_shift_out_eeprom_bits(hw, word, 16); + + if (page_size == 0) + break; + + /* do not wrap around page */ + if (((offset + i) & (page_size - 1)) == + (page_size - 1)) + break; + } while (++i < words); + + ixgbe_standby_eeprom(hw); + usleep_range(10000, 20000); + } + /* Done with writing - release the EEPROM */ + ixgbe_release_eeprom(hw); + } - /* Send the Write command (8-bit opcode + addr) */ - ixgbe_shift_out_eeprom_bits(hw, write_opcode, - IXGBE_EEPROM_OPCODE_BITS); - ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2), - hw->eeprom.address_bits); + return status; +} - /* Send the data */ - data = (data >> 8) | (data << 8); - ixgbe_shift_out_eeprom_bits(hw, data, 16); - ixgbe_standby_eeprom(hw); +/** + * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM + * @hw: pointer to hardware structure + * @offset: offset within the EEPROM to be written to + * @data: 16 bit word to be written to the EEPROM + * + * If ixgbe_eeprom_update_checksum is not called after this function, the + * EEPROM will most likely contain an invalid checksum. + **/ +s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) +{ + s32 status; - /* Done with writing - release the EEPROM */ - ixgbe_release_eeprom(hw); + hw->eeprom.ops.init_params(hw); + + if (offset >= hw->eeprom.word_size) { + status = IXGBE_ERR_EEPROM; + goto out; } + status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data); + out: return status; } /** - * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang + * ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be read - * @data: read 16 bit value from EEPROM + * @words: number of word(s) + * @data: read 16 bit words(s) from EEPROM * - * Reads 16 bit value from EEPROM through bit-bang method + * Reads 16 bit word(s) from EEPROM through bit-bang method **/ -s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, - u16 *data) +s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, + u16 words, u16 *data) { - s32 status; - u16 word_in; - u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; + s32 status = 0; + u16 i, count; hw->eeprom.ops.init_params(hw); - if (offset >= hw->eeprom.word_size) { + if (words == 0) { + status = IXGBE_ERR_INVALID_ARGUMENT; + goto out; + } + + if (offset + words > hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } + /* + * We cannot hold synchronization semaphores for too long + * to avoid other entity starvation. However it is more efficient + * to read in bursts than synchronizing access for each word. + */ + for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { + count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? + IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); + + status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i, + count, &data[i]); + + if (status != 0) + break; + } + +out: + return status; +} + +/** + * ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang + * @hw: pointer to hardware structure + * @offset: offset within the EEPROM to be read + * @words: number of word(s) + * @data: read 16 bit word(s) from EEPROM + * + * Reads 16 bit word(s) from EEPROM through bit-bang method + **/ +static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, + u16 words, u16 *data) +{ + s32 status; + u16 word_in; + u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; + u16 i; + /* Prepare the EEPROM for reading */ status = ixgbe_acquire_eeprom(hw); @@ -715,110 +860,227 @@ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, } if (status == 0) { - ixgbe_standby_eeprom(hw); + for (i = 0; i < words; i++) { + ixgbe_standby_eeprom(hw); + /* + * Some SPI eeproms use the 8th address bit embedded + * in the opcode + */ + if ((hw->eeprom.address_bits == 8) && + ((offset + i) >= 128)) + read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; + + /* Send the READ command (opcode + addr) */ + ixgbe_shift_out_eeprom_bits(hw, read_opcode, + IXGBE_EEPROM_OPCODE_BITS); + ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), + hw->eeprom.address_bits); + + /* Read the data. */ + word_in = ixgbe_shift_in_eeprom_bits(hw, 16); + data[i] = (word_in >> 8) | (word_in << 8); + } - /* - * Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((hw->eeprom.address_bits == 8) && (offset >= 128)) - read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; + /* End this read operation */ + ixgbe_release_eeprom(hw); + } - /* Send the READ command (opcode + addr) */ - ixgbe_shift_out_eeprom_bits(hw, read_opcode, - IXGBE_EEPROM_OPCODE_BITS); - ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2), - hw->eeprom.address_bits); + return status; +} - /* Read the data. */ - word_in = ixgbe_shift_in_eeprom_bits(hw, 16); - *data = (word_in >> 8) | (word_in << 8); +/** + * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang + * @hw: pointer to hardware structure + * @offset: offset within the EEPROM to be read + * @data: read 16 bit value from EEPROM + * + * Reads 16 bit value from EEPROM through bit-bang method + **/ +s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, + u16 *data) +{ + s32 status; - /* End this read operation */ - ixgbe_release_eeprom(hw); + hw->eeprom.ops.init_params(hw); + + if (offset >= hw->eeprom.word_size) { + status = IXGBE_ERR_EEPROM; + goto out; } + status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); + out: return status; } /** - * ixgbe_read_eerd_generic - Read EEPROM word using EERD + * ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD * @hw: pointer to hardware structure - * @offset: offset of word in the EEPROM to read - * @data: word read from the EEPROM + * @offset: offset of word in the EEPROM to read + * @words: number of word(s) + * @data: 16 bit word(s) from the EEPROM * - * Reads a 16 bit word from the EEPROM using the EERD register. + * Reads a 16 bit word(s) from the EEPROM using the EERD register. **/ -s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) +s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset, + u16 words, u16 *data) { u32 eerd; - s32 status; + s32 status = 0; + u32 i; hw->eeprom.ops.init_params(hw); + if (words == 0) { + status = IXGBE_ERR_INVALID_ARGUMENT; + goto out; + } + if (offset >= hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } - eerd = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) + - IXGBE_EEPROM_RW_REG_START; + for (i = 0; i < words; i++) { + eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) + + IXGBE_EEPROM_RW_REG_START; - IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); - status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); + IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); + status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); - if (status == 0) - *data = (IXGBE_READ_REG(hw, IXGBE_EERD) >> - IXGBE_EEPROM_RW_REG_DATA); - else - hw_dbg(hw, "Eeprom read timed out\n"); + if (status == 0) { + data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >> + IXGBE_EEPROM_RW_REG_DATA); + } else { + hw_dbg(hw, "Eeprom read timed out\n"); + goto out; + } + } +out: + return status; +} +/** + * ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size + * @hw: pointer to hardware structure + * @offset: offset within the EEPROM to be used as a scratch pad + * + * Discover EEPROM page size by writing marching data at given offset. + * This function is called only when we are writing a new large buffer + * at given offset so the data would be overwritten anyway. + **/ +static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, + u16 offset) +{ + u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX]; + s32 status = 0; + u16 i; + + for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++) + data[i] = i; + + hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX; + status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, + IXGBE_EEPROM_PAGE_SIZE_MAX, data); + hw->eeprom.word_page_size = 0; + if (status != 0) + goto out; + + status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); + if (status != 0) + goto out; + + /* + * When writing in burst more than the actual page size + * EEPROM address wraps around current page. + */ + hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0]; + + hw_dbg(hw, "Detected EEPROM page size = %d words.", + hw->eeprom.word_page_size); out: return status; } /** - * ixgbe_write_eewr_generic - Write EEPROM word using EEWR + * ixgbe_read_eerd_generic - Read EEPROM word using EERD + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to read + * @data: word read from the EEPROM + * + * Reads a 16 bit word from the EEPROM using the EERD register. + **/ +s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) +{ + return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data); +} + +/** + * ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to write - * @data: word write to the EEPROM + * @words: number of words + * @data: word(s) write to the EEPROM * - * Write a 16 bit word to the EEPROM using the EEWR register. + * Write a 16 bit word(s) to the EEPROM using the EEWR register. **/ -s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data) +s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset, + u16 words, u16 *data) { u32 eewr; - s32 status; + s32 status = 0; + u16 i; hw->eeprom.ops.init_params(hw); + if (words == 0) { + status = IXGBE_ERR_INVALID_ARGUMENT; + goto out; + } + if (offset >= hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } - eewr = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) | - (data << IXGBE_EEPROM_RW_REG_DATA) | IXGBE_EEPROM_RW_REG_START; + for (i = 0; i < words; i++) { + eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | + (data[i] << IXGBE_EEPROM_RW_REG_DATA) | + IXGBE_EEPROM_RW_REG_START; - status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); - if (status != 0) { - hw_dbg(hw, "Eeprom write EEWR timed out\n"); - goto out; - } + status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); + if (status != 0) { + hw_dbg(hw, "Eeprom write EEWR timed out\n"); + goto out; + } - IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); + IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); - status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); - if (status != 0) { - hw_dbg(hw, "Eeprom write EEWR timed out\n"); - goto out; + status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); + if (status != 0) { + hw_dbg(hw, "Eeprom write EEWR timed out\n"); + goto out; + } } out: return status; } +/** + * ixgbe_write_eewr_generic - Write EEPROM word using EEWR + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to write + * @data: word write to the EEPROM + * + * Write a 16 bit word to the EEPROM using the EEWR register. + **/ +s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data) +{ + return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data); +} + /** * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status * @hw: pointer to hardware structure diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index e850adbb32a1..46be83cfb500 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -49,10 +49,18 @@ s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw); s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data); +s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, + u16 words, u16 *data); s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); +s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset, + u16 words, u16 *data); s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data); +s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset, + u16 words, u16 *data); s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); +s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, + u16 words, u16 *data); u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw); s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, u16 *checksum_val); diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 410c29875785..f2efa3245352 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -847,11 +847,8 @@ static int ixgbe_get_eeprom(struct net_device *netdev, if (!eeprom_buff) return -ENOMEM; - for (i = 0; i < eeprom_len; i++) { - if ((ret_val = hw->eeprom.ops.read(hw, first_word + i, - &eeprom_buff[i]))) - break; - } + ret_val = hw->eeprom.ops.read_buffer(hw, first_word, eeprom_len, + eeprom_buff); /* Device's eeprom is always little-endian, word addressable */ for (i = 0; i < eeprom_len; i++) diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index fab9737c0d61..b1d523ca4d81 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1668,6 +1668,10 @@ #define IXGBE_ETH_LENGTH_OF_ADDRESS 6 +#define IXGBE_EEPROM_PAGE_SIZE_MAX 128 +#define IXGBE_EEPROM_RD_BUFFER_MAX_COUNT 512 /* EEPROM words # read in burst */ +#define IXGBE_EEPROM_WR_BUFFER_MAX_COUNT 256 /* EEPROM words # wr in burst */ + #ifndef IXGBE_EEPROM_GRANT_ATTEMPTS #define IXGBE_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */ #endif @@ -2563,7 +2567,9 @@ typedef u8* (*ixgbe_mc_addr_itr) (struct ixgbe_hw *hw, u8 **mc_addr_ptr, struct ixgbe_eeprom_operations { s32 (*init_params)(struct ixgbe_hw *); s32 (*read)(struct ixgbe_hw *, u16, u16 *); + s32 (*read_buffer)(struct ixgbe_hw *, u16, u16, u16 *); s32 (*write)(struct ixgbe_hw *, u16, u16); + s32 (*write_buffer)(struct ixgbe_hw *, u16, u16, u16 *); s32 (*validate_checksum)(struct ixgbe_hw *, u16 *); s32 (*update_checksum)(struct ixgbe_hw *); u16 (*calc_checksum)(struct ixgbe_hw *); @@ -2649,6 +2655,7 @@ struct ixgbe_eeprom_info { u32 semaphore_delay; u16 word_size; u16 address_bits; + u16 word_page_size; }; #define IXGBE_FLAGS_DOUBLE_RESET_REQUIRED 0x01 diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c index 179ee8226d04..4ed687be2fe3 100644 --- a/drivers/net/ixgbe/ixgbe_x540.c +++ b/drivers/net/ixgbe/ixgbe_x540.c @@ -304,16 +304,19 @@ static s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw) } /** - * ixgbe_read_eerd_X540 - Read EEPROM word using EERD - * @hw: pointer to hardware structure - * @offset: offset of word in the EEPROM to read - * @data: word read from the EERPOM + * ixgbe_read_eerd_X540- Read EEPROM word using EERD + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to read + * @data: word read from the EEPROM + * + * Reads a 16 bit word from the EEPROM using the EERD register. **/ static s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data) { - s32 status; + s32 status = 0; - if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) + if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == + 0) status = ixgbe_read_eerd_generic(hw, offset, data); else status = IXGBE_ERR_SWFW_SYNC; @@ -322,6 +325,31 @@ static s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data) return status; } +/** + * ixgbe_read_eerd_buffer_X540 - Read EEPROM word(s) using EERD + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to read + * @words: number of words + * @data: word(s) read from the EEPROM + * + * Reads a 16 bit word(s) from the EEPROM using the EERD register. + **/ +static s32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw, + u16 offset, u16 words, u16 *data) +{ + s32 status = 0; + + if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == + 0) + status = ixgbe_read_eerd_buffer_generic(hw, offset, + words, data); + else + status = IXGBE_ERR_SWFW_SYNC; + + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); + return status; +} + /** * ixgbe_write_eewr_X540 - Write EEPROM word using EEWR * @hw: pointer to hardware structure @@ -343,6 +371,31 @@ static s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data) return status; } +/** + * ixgbe_write_eewr_buffer_X540 - Write EEPROM word(s) using EEWR + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to write + * @words: number of words + * @data: word(s) write to the EEPROM + * + * Write a 16 bit word(s) to the EEPROM using the EEWR register. + **/ +static s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw, + u16 offset, u16 words, u16 *data) +{ + s32 status = 0; + + if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == + 0) + status = ixgbe_write_eewr_buffer_generic(hw, offset, + words, data); + else + status = IXGBE_ERR_SWFW_SYNC; + + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); + return status; +} + /** * ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum * @@ -851,7 +904,9 @@ static struct ixgbe_mac_operations mac_ops_X540 = { static struct ixgbe_eeprom_operations eeprom_ops_X540 = { .init_params = &ixgbe_init_eeprom_params_X540, .read = &ixgbe_read_eerd_X540, + .read_buffer = &ixgbe_read_eerd_buffer_X540, .write = &ixgbe_write_eewr_X540, + .write_buffer = &ixgbe_write_eewr_buffer_X540, .calc_checksum = &ixgbe_calc_eeprom_checksum_X540, .validate_checksum = &ixgbe_validate_eeprom_checksum_X540, .update_checksum = &ixgbe_update_eeprom_checksum_X540, -- cgit v1.2.3-58-ga151 From 6716344c521bb585c1b89987c918d4b83b81adbe Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Tue, 26 Apr 2011 08:00:00 +0000 Subject: ixgbe: Cleanup PCIe bus speed info PCIe connections should be expressed as GT/s (GigaTransfers per second) instead of the current Gb/s (Gigabits per second). In addition, it is incorrect because (due to PCIe gen 1 & 2 having a 20% overhead) the actually data rate, when expressed in Gb/s, is only 80% of the rate of GT/s. Signed-off-by: Don Skidmore Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index bd3d21d01853..eebb1921c660 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -7469,8 +7469,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, /* print bus type/speed/width info */ e_dev_info("(PCI Express:%s:%s) %pM\n", - (hw->bus.speed == ixgbe_bus_speed_5000 ? "5.0Gb/s" : - hw->bus.speed == ixgbe_bus_speed_2500 ? "2.5Gb/s" : + (hw->bus.speed == ixgbe_bus_speed_5000 ? "5.0GT/s" : + hw->bus.speed == ixgbe_bus_speed_2500 ? "2.5GT/s" : "Unknown"), (hw->bus.width == ixgbe_bus_width_pcie_x8 ? "Width x8" : hw->bus.width == ixgbe_bus_width_pcie_x4 ? "Width x4" : -- cgit v1.2.3-58-ga151 From 9a1b9496cd2b013f74885218947fa7120d53e74c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 4 May 2011 12:18:54 -0700 Subject: ipv4: Pass explicit saddr/daddr args to ipmr_get_route(). This eliminates the need to use rt->rt_{src,dst}. Signed-off-by: David S. Miller --- include/linux/mroute.h | 1 + net/ipv4/ipmr.c | 16 ++++++++-------- net/ipv4/route.c | 4 +++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/linux/mroute.h b/include/linux/mroute.h index b21d567692b2..46caaf44339d 100644 --- a/include/linux/mroute.h +++ b/include/linux/mroute.h @@ -244,6 +244,7 @@ struct mfc_cache { #ifdef __KERNEL__ struct rtmsg; extern int ipmr_get_route(struct net *net, struct sk_buff *skb, + __be32 saddr, __be32 daddr, struct rtmsg *rtm, int nowait); #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 86033b7a05ba..30a7763c400e 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -2041,20 +2041,20 @@ rtattr_failure: return -EMSGSIZE; } -int ipmr_get_route(struct net *net, - struct sk_buff *skb, struct rtmsg *rtm, int nowait) +int ipmr_get_route(struct net *net, struct sk_buff *skb, + __be32 saddr, __be32 daddr, + struct rtmsg *rtm, int nowait) { - int err; - struct mr_table *mrt; struct mfc_cache *cache; - struct rtable *rt = skb_rtable(skb); + struct mr_table *mrt; + int err; mrt = ipmr_get_table(net, RT_TABLE_DEFAULT); if (mrt == NULL) return -ENOENT; rcu_read_lock(); - cache = ipmr_cache_find(mrt, rt->rt_src, rt->rt_dst); + cache = ipmr_cache_find(mrt, saddr, daddr); if (cache == NULL) { struct sk_buff *skb2; @@ -2087,8 +2087,8 @@ int ipmr_get_route(struct net *net, skb_reset_network_header(skb2); iph = ip_hdr(skb2); iph->ihl = sizeof(struct iphdr) >> 2; - iph->saddr = rt->rt_src; - iph->daddr = rt->rt_dst; + iph->saddr = saddr; + iph->daddr = daddr; iph->version = 0; err = ipmr_cache_unresolved(mrt, vif, skb2); read_unlock(&mrt_lock); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 3bc685454b5b..6a83840b16af 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2857,7 +2857,9 @@ static int rt_fill_info(struct net *net, if (ipv4_is_multicast(dst) && !ipv4_is_local_multicast(dst) && IPV4_DEVCONF_ALL(net, MC_FORWARDING)) { - int err = ipmr_get_route(net, skb, r, nowait); + int err = ipmr_get_route(net, skb, + rt->rt_src, rt->rt_dst, + r, nowait); if (err <= 0) { if (!nowait) { if (err == 0) -- cgit v1.2.3-58-ga151 From cbb1e85f9cfd2bd9b7edfd21d167e89a4279faf0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 4 May 2011 12:33:34 -0700 Subject: ipv4: Kill rt->rt_{src, dst} usage in IP GRE tunnels. First, make callers pass on-stack flowi4 to ip_route_output_gre() so they can get at the fully resolved flow key. Next, use that in ipgre_tunnel_xmit() to avoid the need to use rt->rt_{dst,src}. Signed-off-by: David S. Miller --- include/net/route.h | 19 +++++++++---------- net/ipv4/ip_gre.c | 37 +++++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index 8c02c871a8ce..9f8070b251fb 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -152,19 +152,18 @@ static inline struct rtable *ip_route_output_ports(struct net *net, struct flowi return ip_route_output_flow(net, fl4, sk); } -static inline struct rtable *ip_route_output_gre(struct net *net, +static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4 *fl4, __be32 daddr, __be32 saddr, __be32 gre_key, __u8 tos, int oif) { - struct flowi4 fl4 = { - .flowi4_oif = oif, - .daddr = daddr, - .saddr = saddr, - .flowi4_tos = tos, - .flowi4_proto = IPPROTO_GRE, - .fl4_gre_key = gre_key, - }; - return ip_route_output_key(net, &fl4); + memset(fl4, 0, sizeof(*fl4)); + fl4->flowi4_oif = oif; + fl4->daddr = daddr; + fl4->saddr = saddr; + fl4->flowi4_tos = tos; + fl4->flowi4_proto = IPPROTO_GRE; + fl4->fl4_gre_key = gre_key; + return ip_route_output_key(net, fl4); } extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src, diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 24efd353279a..10e9b5aea070 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -699,6 +699,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev struct pcpu_tstats *tstats; const struct iphdr *old_iph = ip_hdr(skb); const struct iphdr *tiph; + struct flowi4 fl4; u8 tos; __be16 df; struct rtable *rt; /* Route to the other host */ @@ -769,7 +770,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev tos = ipv6_get_dsfield((const struct ipv6hdr *)old_iph); } - rt = ip_route_output_gre(dev_net(dev), dst, tiph->saddr, + rt = ip_route_output_gre(dev_net(dev), &fl4, dst, tiph->saddr, tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link); if (IS_ERR(rt)) { @@ -873,8 +874,8 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev iph->frag_off = df; iph->protocol = IPPROTO_GRE; iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb); - iph->daddr = rt->rt_dst; - iph->saddr = rt->rt_src; + iph->daddr = fl4.daddr; + iph->saddr = fl4.saddr; if ((iph->ttl = tiph->ttl) == 0) { if (skb->protocol == htons(ETH_P_IP)) @@ -938,12 +939,14 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev) /* Guess output device to choose reasonable mtu and needed_headroom */ if (iph->daddr) { - struct rtable *rt = ip_route_output_gre(dev_net(dev), - iph->daddr, iph->saddr, - tunnel->parms.o_key, - RT_TOS(iph->tos), - tunnel->parms.link); - + struct flowi4 fl4; + struct rtable *rt; + + rt = ip_route_output_gre(dev_net(dev), &fl4, + iph->daddr, iph->saddr, + tunnel->parms.o_key, + RT_TOS(iph->tos), + tunnel->parms.link); if (!IS_ERR(rt)) { tdev = rt->dst.dev; ip_rt_put(rt); @@ -1196,13 +1199,15 @@ static int ipgre_open(struct net_device *dev) struct ip_tunnel *t = netdev_priv(dev); if (ipv4_is_multicast(t->parms.iph.daddr)) { - struct rtable *rt = ip_route_output_gre(dev_net(dev), - t->parms.iph.daddr, - t->parms.iph.saddr, - t->parms.o_key, - RT_TOS(t->parms.iph.tos), - t->parms.link); - + struct flowi4 fl4; + struct rtable *rt; + + rt = ip_route_output_gre(dev_net(dev), &fl4, + t->parms.iph.daddr, + t->parms.iph.saddr, + t->parms.o_key, + RT_TOS(t->parms.iph.tos), + t->parms.link); if (IS_ERR(rt)) return -EADDRNOTAVAIL; dev = rt->dst.dev; -- cgit v1.2.3-58-ga151 From 301102cc832f9f3e24c5748705f152eaa7c307f6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 4 May 2011 12:46:24 -0700 Subject: ipv6: Use flowi4->{daddr,saddr} in ipip6_tunnel_xmit(). Instead of rt->rt_{dst,src} Signed-off-by: David S. Miller --- net/ipv6/sit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index a24fb14d91f3..c53abcf50d29 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -828,8 +828,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, iph->frag_off = df; iph->protocol = IPPROTO_IPV6; iph->tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); - iph->daddr = rt->rt_dst; - iph->saddr = rt->rt_src; + iph->daddr = fl4.daddr; + iph->saddr = fl4.saddr; if ((iph->ttl = tiph->ttl) == 0) iph->ttl = iph6->hop_limit; -- cgit v1.2.3-58-ga151 From 1650629d1800bf05ad775f974e931ca2fa03b0ff Mon Sep 17 00:00:00 2001 From: Kurt Van Dijck Date: Tue, 3 May 2011 18:40:57 +0000 Subject: can: make struct can_proto const commit 53914b67993c724cec585863755c9ebc8446e83b had the same message. That commit did put everything in place but did not make can_proto const itself. Signed-off-by: Kurt Van Dijck Acked-by: Oliver Hartkopp Signed-off-by: David S. Miller --- include/linux/can/core.h | 4 ++-- net/can/af_can.c | 12 ++++++------ net/can/bcm.c | 2 +- net/can/raw.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/linux/can/core.h b/include/linux/can/core.h index 6f70a6d3a16e..5ce6b5d62ecc 100644 --- a/include/linux/can/core.h +++ b/include/linux/can/core.h @@ -44,8 +44,8 @@ struct can_proto { /* function prototypes for the CAN networklayer core (af_can.c) */ -extern int can_proto_register(struct can_proto *cp); -extern void can_proto_unregister(struct can_proto *cp); +extern int can_proto_register(const struct can_proto *cp); +extern void can_proto_unregister(const struct can_proto *cp); extern int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask, diff --git a/net/can/af_can.c b/net/can/af_can.c index a8dcaa49675a..5b52762b9f20 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -84,7 +84,7 @@ static DEFINE_SPINLOCK(can_rcvlists_lock); static struct kmem_cache *rcv_cache __read_mostly; /* table of registered CAN protocols */ -static struct can_proto *proto_tab[CAN_NPROTO] __read_mostly; +static const struct can_proto *proto_tab[CAN_NPROTO] __read_mostly; static DEFINE_MUTEX(proto_tab_lock); struct timer_list can_stattimer; /* timer for statistics update */ @@ -115,9 +115,9 @@ static void can_sock_destruct(struct sock *sk) skb_queue_purge(&sk->sk_receive_queue); } -static struct can_proto *can_try_module_get(int protocol) +static const struct can_proto *can_try_module_get(int protocol) { - struct can_proto *cp; + const struct can_proto *cp; rcu_read_lock(); cp = rcu_dereference(proto_tab[protocol]); @@ -132,7 +132,7 @@ static int can_create(struct net *net, struct socket *sock, int protocol, int kern) { struct sock *sk; - struct can_proto *cp; + const struct can_proto *cp; int err = 0; sock->state = SS_UNCONNECTED; @@ -691,7 +691,7 @@ drop: * -EBUSY protocol already in use * -ENOBUF if proto_register() fails */ -int can_proto_register(struct can_proto *cp) +int can_proto_register(const struct can_proto *cp) { int proto = cp->protocol; int err = 0; @@ -728,7 +728,7 @@ EXPORT_SYMBOL(can_proto_register); * can_proto_unregister - unregister CAN transport protocol * @cp: pointer to CAN protocol structure */ -void can_proto_unregister(struct can_proto *cp) +void can_proto_unregister(const struct can_proto *cp) { int proto = cp->protocol; diff --git a/net/can/bcm.c b/net/can/bcm.c index 8a6a05e7c3c8..cced806098a9 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1601,7 +1601,7 @@ static struct proto bcm_proto __read_mostly = { .init = bcm_init, }; -static struct can_proto bcm_can_proto __read_mostly = { +static const struct can_proto bcm_can_proto = { .type = SOCK_DGRAM, .protocol = CAN_BCM, .ops = &bcm_ops, diff --git a/net/can/raw.c b/net/can/raw.c index 0eb39a7fdf64..dea99a6e596c 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -774,7 +774,7 @@ static struct proto raw_proto __read_mostly = { .init = raw_init, }; -static struct can_proto raw_can_proto __read_mostly = { +static const struct can_proto raw_can_proto = { .type = SOCK_RAW, .protocol = CAN_RAW, .ops = &raw_ops, -- cgit v1.2.3-58-ga151 From c8d55a9d9e257e67d02a6f673a943dd77e6bf24e Mon Sep 17 00:00:00 2001 From: Kurt Van Dijck Date: Tue, 3 May 2011 18:42:04 +0000 Subject: can: rename can_try_module_get to can_get_proto can: rename can_try_module_get to can_get_proto can_try_module_get does return a struct can_proto. The name explains what is done in so much detail that a caller may not notice that a struct can_proto is locked/unlocked. Signed-off-by: Kurt Van Dijck Acked-by: Oliver Hartkopp Signed-off-by: David S. Miller --- net/can/af_can.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/net/can/af_can.c b/net/can/af_can.c index 5b52762b9f20..094fc5332d42 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -115,7 +115,7 @@ static void can_sock_destruct(struct sock *sk) skb_queue_purge(&sk->sk_receive_queue); } -static const struct can_proto *can_try_module_get(int protocol) +static const struct can_proto *can_get_proto(int protocol) { const struct can_proto *cp; @@ -128,6 +128,11 @@ static const struct can_proto *can_try_module_get(int protocol) return cp; } +static inline void can_put_proto(const struct can_proto *cp) +{ + module_put(cp->prot->owner); +} + static int can_create(struct net *net, struct socket *sock, int protocol, int kern) { @@ -143,7 +148,7 @@ static int can_create(struct net *net, struct socket *sock, int protocol, if (!net_eq(net, &init_net)) return -EAFNOSUPPORT; - cp = can_try_module_get(protocol); + cp = can_get_proto(protocol); #ifdef CONFIG_MODULES if (!cp) { @@ -160,7 +165,7 @@ static int can_create(struct net *net, struct socket *sock, int protocol, printk(KERN_ERR "can: request_module " "(can-proto-%d) failed.\n", protocol); - cp = can_try_module_get(protocol); + cp = can_get_proto(protocol); } #endif @@ -195,7 +200,7 @@ static int can_create(struct net *net, struct socket *sock, int protocol, } errout: - module_put(cp->prot->owner); + can_put_proto(cp); return err; } -- cgit v1.2.3-58-ga151 From eaef6a93bd52a2cc47b9fce201310010707afdb4 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Thu, 5 May 2011 10:59:24 +0530 Subject: mac80211: Fix a warning due to skipping tailroom reservation for IV The devices that require IV generation in software need tailroom reservation for ICVs used in TKIP or WEP encryptions. Currently, decision to skip the tailroom reservation in the tx path was taken only on whether driver wants MMIC to be generated in software or not. Following patch appends IV generation check for such decisions and fixes the following warning. WARNING: at net/mac80211/wep.c:101 ieee80211_wep_add_iv+0x56/0xf3() Hardware name: 64756D6 Modules linked in: ath9k ath9k_common ath9k_hw Pid: 0, comm: swapper Tainted: G W 2.6.39-rc5-wl Call Trace: [] warn_slowpath_common+0x65/0x7a [] ? ieee80211_wep_add_iv+0x56/0xf3 [] warn_slowpath_null+0xf/0x13 [] ieee80211_wep_add_iv+0x56/0xf3 [] ieee80211_crypto_wep_encrypt+0x63/0x88 [] ieee80211_tx_h_encrypt+0x2f/0x63 [] invoke_tx_handlers+0x93/0xe1 [] ieee80211_tx+0x4b/0x6d [] ieee80211_xmit+0x180/0x188 [] ? ieee80211_skb_resize+0x95/0xd9 [] ieee80211_subif_start_xmit+0x64f/0x668 [] dev_hard_start_xmit+0x368/0x48c [] sch_direct_xmit+0x4d/0x101 [] dev_queue_xmit+0x2c1/0x43f [] ? eth_header+0x1e/0x90 [] ? eth_type_trans+0x91/0xc2 [] ? eth_rebuild_header+0x53/0x53 [] neigh_resolve_output+0x223/0x27e [] ip_finish_output2+0x1d4/0x1fe [] ip_finish_output+0x79/0x7d [] T.1075+0x43/0x48 [] ip_output+0x75/0x7b [] dst_output+0xc/0xe [] ip_local_out+0x17/0x1a [] ip_queue_xmit+0x2aa/0x2f8 [] ? sk_setup_caps+0x21/0x92 [] ? __tcp_v4_send_check+0x7e/0xb7 [] tcp_transmit_skb+0x6a1/0x6d7 [] ? tcp_established_options+0x20/0x8b [] tcp_retransmit_skb+0x43a/0x527 [] tcp_retransmit_timer+0x32e/0x45d [] tcp_write_timer+0x87/0x16c [] run_timer_softirq+0x156/0x1f9 [] ? tcp_retransmit_timer+0x45d/0x45d [] __do_softirq+0x97/0x14a [] ? irq_enter+0x4d/0x4d Cc: Yogesh Powar Reported-by: Fabio Rossi Tested-by: Fabio Rossi Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- net/mac80211/key.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/mac80211/key.c b/net/mac80211/key.c index ca3c626b011a..b510721e3b3d 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -102,7 +102,8 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) if (!ret) { key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; - if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) + if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || + (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))) key->local->crypto_tx_tailroom_needed_cnt--; return 0; @@ -161,7 +162,8 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; - if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) + if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || + (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))) key->local->crypto_tx_tailroom_needed_cnt++; } -- cgit v1.2.3-58-ga151 From 9e4425fff9e0a0fb6a8c705777ed861f991f8747 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 18 Apr 2011 18:38:43 -0300 Subject: Bluetooth: Add l2cap_add_psm() and l2cap_add_scid() The intention is to get rid of the l2cap_sk_list usage inside l2cap_core.c. l2cap_sk_list will soon be replaced by a list that does not depend on socket usage. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 4 ++++ net/bluetooth/l2cap_core.c | 44 +++++++++++++++++++++++++++++++++++++++++++ net/bluetooth/l2cap_sock.c | 44 +++++++++++-------------------------------- 3 files changed, 59 insertions(+), 33 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index c34b1c126363..f5f3c2cf8a3e 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -458,6 +458,10 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb); void l2cap_streaming_send(struct l2cap_chan *chan); int l2cap_ertm_send(struct l2cap_chan *chan); +struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src); +int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); +int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); + void l2cap_sock_set_timer(struct sock *sk, long timeout); void l2cap_sock_clear_timer(struct sock *sk); void __l2cap_sock_close(struct sock *sk, int reason); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 338d8c3eedab..98ddd867cfd4 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -135,6 +135,50 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn return c; } +struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) +{ + struct sock *sk; + struct hlist_node *node; + sk_for_each(sk, node, &l2cap_sk_list.head) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + + if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src)) + goto found; + } + + sk = NULL; +found: + return sk; +} + +int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) +{ + write_lock_bh(&l2cap_sk_list.lock); + + if (__l2cap_get_sock_by_addr(psm, src)) { + write_unlock_bh(&l2cap_sk_list.lock); + return -EADDRINUSE; + } + + chan->psm = psm; + chan->sport = psm; + + write_unlock_bh(&l2cap_sk_list.lock); + + return 0; +} + +int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) +{ + write_lock_bh(&l2cap_sk_list.lock); + + chan->scid = scid; + + write_unlock_bh(&l2cap_sk_list.lock); + + return 0; +} + static u16 l2cap_alloc_cid(struct l2cap_conn *conn) { u16 cid = L2CAP_CID_DYN_START; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 09cc7a005349..2156dcecec0b 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -78,22 +78,6 @@ void l2cap_sock_clear_timer(struct sock *sk) sk_stop_timer(sk, &sk->sk_timer); } -static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) -{ - struct sock *sk; - struct hlist_node *node; - sk_for_each(sk, node, &l2cap_sk_list.head) { - struct l2cap_chan *chan = l2cap_pi(sk)->chan; - - if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src)) - goto found; - } - - sk = NULL; -found: - return sk; -} - static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) { struct sock *sk = sock->sk; @@ -136,26 +120,20 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) } } - write_lock_bh(&l2cap_sk_list.lock); + if (la.l2_cid) + err = l2cap_add_scid(chan, la.l2_cid); + else + err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm); - if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) { - err = -EADDRINUSE; - } else { - /* Save source address */ - bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); - chan->psm = la.l2_psm; - chan->sport = la.l2_psm; - sk->sk_state = BT_BOUND; - - if (__le16_to_cpu(la.l2_psm) == 0x0001 || - __le16_to_cpu(la.l2_psm) == 0x0003) - chan->sec_level = BT_SECURITY_SDP; - } + if (err < 0) + goto done; - if (la.l2_cid) - chan->scid = la.l2_cid; + if (__le16_to_cpu(la.l2_psm) == 0x0001 || + __le16_to_cpu(la.l2_psm) == 0x0003) + chan->sec_level = BT_SECURITY_SDP; - write_unlock_bh(&l2cap_sk_list.lock); + bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); + sk->sk_state = BT_BOUND; done: release_sock(sk); -- cgit v1.2.3-58-ga151 From 73b2ec18532f45e9028ce4c7bc8d7f8818eabd2a Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 18 Apr 2011 19:36:44 -0300 Subject: Bluetooth: Handle psm == 0 case inside l2cap_add_psm() When the user doesn't specify a psm we have the choose one for the channel. Now we do this inside l2cap_add_psm(). Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 1 - net/bluetooth/l2cap_core.c | 32 ++++++++++++++++++++++++-------- net/bluetooth/l2cap_sock.c | 22 ---------------------- 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index f5f3c2cf8a3e..fb3f90eaaaa4 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -458,7 +458,6 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb); void l2cap_streaming_send(struct l2cap_chan *chan); int l2cap_ertm_send(struct l2cap_chan *chan); -struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src); int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 98ddd867cfd4..9e3f64f05d49 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -135,7 +135,7 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn return c; } -struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) +static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) { struct sock *sk; struct hlist_node *node; @@ -153,19 +153,35 @@ found: int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) { + int err; + write_lock_bh(&l2cap_sk_list.lock); - if (__l2cap_get_sock_by_addr(psm, src)) { - write_unlock_bh(&l2cap_sk_list.lock); - return -EADDRINUSE; + if (psm && __l2cap_get_sock_by_addr(psm, src)) { + err = -EADDRINUSE; + goto done; } - chan->psm = psm; - chan->sport = psm; + if (psm) { + chan->psm = psm; + chan->sport = psm; + err = 0; + } else { + u16 p; - write_unlock_bh(&l2cap_sk_list.lock); + err = -EINVAL; + for (p = 0x1001; p < 0x1100; p += 2) + if (!__l2cap_get_sock_by_addr(cpu_to_le16(p), src)) { + chan->psm = cpu_to_le16(p); + chan->sport = cpu_to_le16(p); + err = 0; + break; + } + } - return 0; +done: + write_unlock_bh(&l2cap_sk_list.lock); + return err; } int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 2156dcecec0b..aca99cd5377d 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -256,28 +256,6 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) goto done; } - if (!chan->psm && !chan->scid) { - bdaddr_t *src = &bt_sk(sk)->src; - u16 psm; - - err = -EINVAL; - - write_lock_bh(&l2cap_sk_list.lock); - - for (psm = 0x1001; psm < 0x1100; psm += 2) - if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) { - chan->psm = cpu_to_le16(psm); - chan->sport = cpu_to_le16(psm); - err = 0; - break; - } - - write_unlock_bh(&l2cap_sk_list.lock); - - if (err < 0) - goto done; - } - sk->sk_max_ack_backlog = backlog; sk->sk_ack_backlog = 0; sk->sk_state = BT_LISTEN; -- cgit v1.2.3-58-ga151 From 23691d75cdc69c3b285211b4d77746aa20a17d18 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 27 Apr 2011 18:26:32 -0300 Subject: Bluetooth: Remove l2cap_sk_list A new list was added to replace the socket based one. This new list doesn't depent on sock and then fits better inside l2cap_core.c code. It also rename l2cap_chan_alloc() to l2cap_chan_create() and l2cap_chan_free() to l2cap_chan_destroy) Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 6 +- net/bluetooth/l2cap_core.c | 165 +++++++++++++++++++++++------------------- net/bluetooth/l2cap_sock.c | 6 +- 3 files changed, 95 insertions(+), 82 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index fb3f90eaaaa4..d09c9b1118e3 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -350,6 +350,7 @@ struct l2cap_chan { struct list_head srej_l; struct list_head list; + struct list_head global_l; }; struct l2cap_conn { @@ -441,7 +442,6 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch) #define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START) extern int disable_ertm; -extern struct bt_sock_list l2cap_sk_list; int l2cap_init_sockets(void); void l2cap_cleanup_sockets(void); @@ -469,9 +469,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent); struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); -struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); +struct l2cap_chan *l2cap_chan_create(struct sock *sk); void l2cap_chan_del(struct l2cap_chan *chan, int err); -void l2cap_chan_free(struct l2cap_chan *chan); +void l2cap_chan_destroy(struct l2cap_chan *chan); int l2cap_chan_connect(struct l2cap_chan *chan); #endif /* __L2CAP_H */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9e3f64f05d49..d0769a83cb58 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -62,9 +62,8 @@ static u8 l2cap_fixed_chan[8] = { 0x02, }; static struct workqueue_struct *_busy_wq; -struct bt_sock_list l2cap_sk_list = { - .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) -}; +LIST_HEAD(chan_list); +DEFINE_RWLOCK(chan_list_lock); static void l2cap_busy_work(struct work_struct *work); @@ -135,29 +134,27 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn return c; } -static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) +static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) { - struct sock *sk; - struct hlist_node *node; - sk_for_each(sk, node, &l2cap_sk_list.head) { - struct l2cap_chan *chan = l2cap_pi(sk)->chan; + struct l2cap_chan *c; - if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src)) + list_for_each_entry(c, &chan_list, global_l) { + if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) goto found; } - sk = NULL; + c = NULL; found: - return sk; + return c; } int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) { int err; - write_lock_bh(&l2cap_sk_list.lock); + write_lock_bh(&chan_list_lock); - if (psm && __l2cap_get_sock_by_addr(psm, src)) { + if (psm && __l2cap_global_chan_by_addr(psm, src)) { err = -EADDRINUSE; goto done; } @@ -171,7 +168,7 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) err = -EINVAL; for (p = 0x1001; p < 0x1100; p += 2) - if (!__l2cap_get_sock_by_addr(cpu_to_le16(p), src)) { + if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { chan->psm = cpu_to_le16(p); chan->sport = cpu_to_le16(p); err = 0; @@ -180,17 +177,17 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) } done: - write_unlock_bh(&l2cap_sk_list.lock); + write_unlock_bh(&chan_list_lock); return err; } int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) { - write_lock_bh(&l2cap_sk_list.lock); + write_lock_bh(&chan_list_lock); chan->scid = scid; - write_unlock_bh(&l2cap_sk_list.lock); + write_unlock_bh(&chan_list_lock); return 0; } @@ -207,7 +204,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) return 0; } -struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) +struct l2cap_chan *l2cap_chan_create(struct sock *sk) { struct l2cap_chan *chan; @@ -217,11 +214,19 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) chan->sk = sk; + write_lock_bh(&chan_list_lock); + list_add(&chan->global_l, &chan_list); + write_unlock_bh(&chan_list_lock); + return chan; } -void l2cap_chan_free(struct l2cap_chan *chan) +void l2cap_chan_destroy(struct l2cap_chan *chan) { + write_lock_bh(&chan_list_lock); + list_del(&chan->global_l); + write_unlock_bh(&chan_list_lock); + kfree(chan); } @@ -651,48 +656,51 @@ static void l2cap_conn_start(struct l2cap_conn *conn) /* Find socket with cid and source bdaddr. * Returns closest match, locked. */ -static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src) +static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src) { - struct sock *sk = NULL, *sk1 = NULL; - struct hlist_node *node; + struct l2cap_chan *c, *c1 = NULL; - read_lock(&l2cap_sk_list.lock); + read_lock(&chan_list_lock); - sk_for_each(sk, node, &l2cap_sk_list.head) { - struct l2cap_chan *chan = l2cap_pi(sk)->chan; + list_for_each_entry(c, &chan_list, global_l) { + struct sock *sk = c->sk; if (state && sk->sk_state != state) continue; - if (chan->scid == cid) { + if (c->scid == cid) { /* Exact match. */ - if (!bacmp(&bt_sk(sk)->src, src)) - break; + if (!bacmp(&bt_sk(sk)->src, src)) { + read_unlock(&chan_list_lock); + return c; + } /* Closest match */ if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) - sk1 = sk; + c1 = c; } } - read_unlock(&l2cap_sk_list.lock); + read_unlock(&chan_list_lock); - return node ? sk : sk1; + return c1; } static void l2cap_le_conn_ready(struct l2cap_conn *conn) { struct sock *parent, *sk; - struct l2cap_chan *chan; + struct l2cap_chan *chan, *pchan; BT_DBG(""); /* Check if we have socket listening on cid */ - parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, + pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, conn->src); - if (!parent) + if (!pchan) return; + parent = pchan->sk; + bh_lock_sock(parent); /* Check for backlog size */ @@ -705,7 +713,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) if (!sk) goto clean; - chan = l2cap_chan_alloc(sk); + chan = l2cap_chan_create(sk); if (!chan) { l2cap_sock_kill(sk); goto clean; @@ -883,33 +891,34 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *ch /* Find socket with psm and source bdaddr. * Returns closest match. */ -static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) +static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src) { - struct sock *sk = NULL, *sk1 = NULL; - struct hlist_node *node; + struct l2cap_chan *c, *c1 = NULL; - read_lock(&l2cap_sk_list.lock); + read_lock(&chan_list_lock); - sk_for_each(sk, node, &l2cap_sk_list.head) { - struct l2cap_chan *chan = l2cap_pi(sk)->chan; + list_for_each_entry(c, &chan_list, global_l) { + struct sock *sk = c->sk; if (state && sk->sk_state != state) continue; - if (chan->psm == psm) { + if (c->psm == psm) { /* Exact match. */ - if (!bacmp(&bt_sk(sk)->src, src)) - break; + if (!bacmp(&bt_sk(sk)->src, src)) { + read_unlock_bh(&chan_list_lock); + return c; + } /* Closest match */ if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) - sk1 = sk; + c1 = c; } } - read_unlock(&l2cap_sk_list.lock); + read_unlock(&chan_list_lock); - return node ? sk : sk1; + return c1; } int l2cap_chan_connect(struct l2cap_chan *chan) @@ -2079,22 +2088,26 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd { struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; struct l2cap_conn_rsp rsp; - struct l2cap_chan *chan = NULL; + struct l2cap_chan *chan = NULL, *pchan; struct sock *parent, *sk = NULL; int result, status = L2CAP_CS_NO_INFO; u16 dcid = 0, scid = __le16_to_cpu(req->scid); __le16 psm = req->psm; - BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); + BT_ERR("psm 0x%2.2x scid 0x%4.4x", psm, scid); /* Check if we have socket listening on psm */ - parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src); - if (!parent) { + pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src); + if (!pchan) { result = L2CAP_CR_BAD_PSM; goto sendresp; } + BT_ERR("%p 0x%2.2x", pchan, pchan->psm); + + parent = pchan->sk; + bh_lock_sock(parent); /* Check if the ACL is secure enough (if not SDP) */ @@ -2117,7 +2130,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd if (!sk) goto response; - chan = l2cap_chan_alloc(sk); + chan = l2cap_chan_create(sk); if (!chan) { l2cap_sock_kill(sk); goto response; @@ -3745,11 +3758,14 @@ done: static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) { struct sock *sk; + struct l2cap_chan *chan; - sk = l2cap_get_sock_by_psm(0, psm, conn->src); - if (!sk) + chan = l2cap_global_chan_by_psm(0, psm, conn->src); + if (!chan) goto drop; + sk = chan->sk; + bh_lock_sock(sk); BT_DBG("sk %p, len %d", sk, skb->len); @@ -3775,11 +3791,14 @@ done: static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb) { struct sock *sk; + struct l2cap_chan *chan; - sk = l2cap_get_sock_by_scid(0, cid, conn->src); - if (!sk) + chan = l2cap_global_chan_by_scid(0, cid, conn->src); + if (!chan) goto drop; + sk = chan->sk; + bh_lock_sock(sk); BT_DBG("sk %p, len %d", sk, skb->len); @@ -3846,8 +3865,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) { int exact = 0, lm1 = 0, lm2 = 0; - register struct sock *sk; - struct hlist_node *node; + struct l2cap_chan *c; if (type != ACL_LINK) return -EINVAL; @@ -3855,25 +3873,25 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); /* Find listening sockets and check their link_mode */ - read_lock(&l2cap_sk_list.lock); - sk_for_each(sk, node, &l2cap_sk_list.head) { - struct l2cap_chan *chan = l2cap_pi(sk)->chan; + read_lock(&chan_list_lock); + list_for_each_entry(c, &chan_list, global_l) { + struct sock *sk = c->sk; if (sk->sk_state != BT_LISTEN) continue; if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { lm1 |= HCI_LM_ACCEPT; - if (chan->role_switch) + if (c->role_switch) lm1 |= HCI_LM_MASTER; exact++; } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { lm2 |= HCI_LM_ACCEPT; - if (chan->role_switch) + if (c->role_switch) lm2 |= HCI_LM_MASTER; } } - read_unlock(&l2cap_sk_list.lock); + read_unlock(&chan_list_lock); return exact ? lm1 : lm2; } @@ -4126,25 +4144,22 @@ drop: static int l2cap_debugfs_show(struct seq_file *f, void *p) { - struct sock *sk; - struct hlist_node *node; + struct l2cap_chan *c; - read_lock_bh(&l2cap_sk_list.lock); + read_lock_bh(&chan_list_lock); - sk_for_each(sk, node, &l2cap_sk_list.head) { - struct l2cap_pinfo *pi = l2cap_pi(sk); - struct l2cap_chan *chan = pi->chan; + list_for_each_entry(c, &chan_list, global_l) { + struct sock *sk = c->sk; seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), - sk->sk_state, __le16_to_cpu(chan->psm), - chan->scid, chan->dcid, - chan->imtu, chan->omtu, chan->sec_level, - chan->mode); + sk->sk_state, __le16_to_cpu(c->psm), + c->scid, c->dcid, c->imtu, c->omtu, + c->sec_level, c->mode); } - read_unlock_bh(&l2cap_sk_list.lock); + read_unlock_bh(&chan_list_lock); return 0; } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index aca99cd5377d..c98360d40b84 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -808,8 +808,7 @@ void l2cap_sock_kill(struct sock *sk) /* Kill poor orphan */ - l2cap_chan_free(l2cap_pi(sk)->chan); - bt_sock_unlink(&l2cap_sk_list, sk); + l2cap_chan_destroy(l2cap_pi(sk)->chan); sock_set_flag(sk, SOCK_DEAD); sock_put(sk); } @@ -1025,7 +1024,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, g setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk); - bt_sock_link(&l2cap_sk_list, sk); return sk; } @@ -1052,7 +1050,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, if (!sk) return -ENOMEM; - chan = l2cap_chan_alloc(sk); + chan = l2cap_chan_create(sk); if (!chan) { l2cap_sock_kill(sk); return -ENOMEM; -- cgit v1.2.3-58-ga151 From 34da9e50e908c4553ddefb38da2c5bacbe2bba58 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Thu, 5 May 2011 00:10:50 +0000 Subject: stmmac: removed not used definitions Reported-by: Karim Hamiti Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/stmmac_main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index ba9daeccb8af..e15c4a0bb96d 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -116,9 +116,6 @@ static int tc = TC_DEFAULT; module_param(tc, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(tc, "DMA threshold control value"); -#define RX_NO_COALESCE 1 /* Always interrupt on completion */ -#define TX_NO_COALESCE -1 /* No moderation by default */ - /* Pay attention to tune this parameter; take care of both * hardware capability and network stabitily/performance impact. * Many tests showed that ~4ms latency seems to be good enough. */ -- cgit v1.2.3-58-ga151 From 2ae17f666099c952053eea7c64cac8189dd76f72 Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Wed, 4 May 2011 23:48:23 +0000 Subject: bnx2x: link report improvements To avoid link notification duplication Signed-off-by: Dmitry Kravkov Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x.h | 21 +++++++ drivers/net/bnx2x/bnx2x_cmn.c | 129 ++++++++++++++++++++++++++++++++++------- drivers/net/bnx2x/bnx2x_cmn.h | 5 +- drivers/net/bnx2x/bnx2x_main.c | 21 +++---- 4 files changed, 141 insertions(+), 35 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 9e87417f6ec7..1a005a484bea 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -893,6 +893,22 @@ typedef enum { (&bp->def_status_blk->sp_sb.\ index_values[HC_SP_INDEX_EQ_CONS]) +/* This is a data that will be used to create a link report message. + * We will keep the data used for the last link report in order + * to prevent reporting the same link parameters twice. + */ +struct bnx2x_link_report_data { + u16 line_speed; /* Effective line speed */ + unsigned long link_report_flags;/* BNX2X_LINK_REPORT_XXX flags */ +}; + +enum { + BNX2X_LINK_REPORT_FD, /* Full DUPLEX */ + BNX2X_LINK_REPORT_LINK_DOWN, + BNX2X_LINK_REPORT_RX_FC_ON, + BNX2X_LINK_REPORT_TX_FC_ON, +}; + struct bnx2x { /* Fields used in the tx and intr/napi performance paths * are grouped together in the beginning of the structure @@ -1025,6 +1041,9 @@ struct bnx2x { struct link_params link_params; struct link_vars link_vars; + u32 link_cnt; + struct bnx2x_link_report_data last_reported_link; + struct mdio_if_info mdio; struct bnx2x_common common; @@ -1441,6 +1460,8 @@ struct bnx2x_func_init_params { #define WAIT_RAMROD_POLL 0x01 #define WAIT_RAMROD_COMMON 0x02 +void bnx2x_read_mf_cfg(struct bnx2x *bp); + /* dmae */ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32); void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr, diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 8729061a4fd5..8853ae2a042e 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -758,35 +758,119 @@ u16 bnx2x_get_mf_speed(struct bnx2x *bp) return line_speed; } +/** + * bnx2x_fill_report_data - fill link report data to report + * + * @bp: driver handle + * @data: link state to update + * + * It uses a none-atomic bit operations because is called under the mutex. + */ +static inline void bnx2x_fill_report_data(struct bnx2x *bp, + struct bnx2x_link_report_data *data) +{ + u16 line_speed = bnx2x_get_mf_speed(bp); + + memset(data, 0, sizeof(*data)); + + /* Fill the report data: efective line speed */ + data->line_speed = line_speed; + + /* Link is down */ + if (!bp->link_vars.link_up || (bp->flags & MF_FUNC_DIS)) + __set_bit(BNX2X_LINK_REPORT_LINK_DOWN, + &data->link_report_flags); + + /* Full DUPLEX */ + if (bp->link_vars.duplex == DUPLEX_FULL) + __set_bit(BNX2X_LINK_REPORT_FD, &data->link_report_flags); + + /* Rx Flow Control is ON */ + if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) + __set_bit(BNX2X_LINK_REPORT_RX_FC_ON, &data->link_report_flags); + + /* Tx Flow Control is ON */ + if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX) + __set_bit(BNX2X_LINK_REPORT_TX_FC_ON, &data->link_report_flags); +} + +/** + * bnx2x_link_report - report link status to OS. + * + * @bp: driver handle + * + * Calls the __bnx2x_link_report() under the same locking scheme + * as a link/PHY state managing code to ensure a consistent link + * reporting. + */ + void bnx2x_link_report(struct bnx2x *bp) { - if (bp->flags & MF_FUNC_DIS) { - netif_carrier_off(bp->dev); - netdev_err(bp->dev, "NIC Link is Down\n"); - return; - } + bnx2x_acquire_phy_lock(bp); + __bnx2x_link_report(bp); + bnx2x_release_phy_lock(bp); +} - if (bp->link_vars.link_up) { - u16 line_speed; +/** + * __bnx2x_link_report - report link status to OS. + * + * @bp: driver handle + * + * None atomic inmlementation. + * Should be called under the phy_lock. + */ +void __bnx2x_link_report(struct bnx2x *bp) +{ + struct bnx2x_link_report_data cur_data; - if (bp->state == BNX2X_STATE_OPEN) - netif_carrier_on(bp->dev); - netdev_info(bp->dev, "NIC Link is Up, "); + /* reread mf_cfg */ + if (!CHIP_IS_E1(bp)) + bnx2x_read_mf_cfg(bp); + + /* Read the current link report info */ + bnx2x_fill_report_data(bp, &cur_data); + + /* Don't report link down or exactly the same link status twice */ + if (!memcmp(&cur_data, &bp->last_reported_link, sizeof(cur_data)) || + (test_bit(BNX2X_LINK_REPORT_LINK_DOWN, + &bp->last_reported_link.link_report_flags) && + test_bit(BNX2X_LINK_REPORT_LINK_DOWN, + &cur_data.link_report_flags))) + return; + + bp->link_cnt++; - line_speed = bnx2x_get_mf_speed(bp); + /* We are going to report a new link parameters now - + * remember the current data for the next time. + */ + memcpy(&bp->last_reported_link, &cur_data, sizeof(cur_data)); - pr_cont("%d Mbps ", line_speed); + if (test_bit(BNX2X_LINK_REPORT_LINK_DOWN, + &cur_data.link_report_flags)) { + netif_carrier_off(bp->dev); + netdev_err(bp->dev, "NIC Link is Down\n"); + return; + } else { + netif_carrier_on(bp->dev); + netdev_info(bp->dev, "NIC Link is Up, "); + pr_cont("%d Mbps ", cur_data.line_speed); - if (bp->link_vars.duplex == DUPLEX_FULL) + if (test_and_clear_bit(BNX2X_LINK_REPORT_FD, + &cur_data.link_report_flags)) pr_cont("full duplex"); else pr_cont("half duplex"); - if (bp->link_vars.flow_ctrl != BNX2X_FLOW_CTRL_NONE) { - if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) { + /* Handle the FC at the end so that only these flags would be + * possibly set. This way we may easily check if there is no FC + * enabled. + */ + if (cur_data.link_report_flags) { + if (test_bit(BNX2X_LINK_REPORT_RX_FC_ON, + &cur_data.link_report_flags)) { pr_cont(", receive "); - if (bp->link_vars.flow_ctrl & - BNX2X_FLOW_CTRL_TX) + if (test_bit(BNX2X_LINK_REPORT_TX_FC_ON, + &cur_data.link_report_flags)) pr_cont("& transmit "); } else { pr_cont(", transmit "); @@ -794,10 +878,6 @@ void bnx2x_link_report(struct bnx2x *bp) pr_cont("flow control ON"); } pr_cont("\n"); - - } else { /* link_down */ - netif_carrier_off(bp->dev); - netdev_err(bp->dev, "NIC Link is Down\n"); } } @@ -1345,6 +1425,13 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; + /* Set the initial link reported state to link down */ + bnx2x_acquire_phy_lock(bp); + memset(&bp->last_reported_link, 0, sizeof(bp->last_reported_link)); + __set_bit(BNX2X_LINK_REPORT_LINK_DOWN, + &bp->last_reported_link.link_report_flags); + bnx2x_release_phy_lock(bp); + /* must be called before memory allocation and HW init */ bnx2x_ilt_set_info(bp); diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index 1cdab69b2a51..007f29495c2e 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h @@ -67,11 +67,12 @@ void bnx2x__link_status_update(struct bnx2x *bp); * Report link status to upper layer * * @param bp - * - * @return int */ void bnx2x_link_report(struct bnx2x *bp); +/* None-atomic version of bnx2x_link_report() */ +void __bnx2x_link_report(struct bnx2x *bp); + /** * calculates MF speed according to current linespeed and MF * configuration diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index bfd7ac98248b..3f4ff41cd333 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -2036,7 +2036,7 @@ static int bnx2x_get_cmng_fns_mode(struct bnx2x *bp) return CMNG_FNS_NONE; } -static void bnx2x_read_mf_cfg(struct bnx2x *bp) +void bnx2x_read_mf_cfg(struct bnx2x *bp) { int vn, n = (CHIP_MODE_IS_4_PORT(bp) ? 2 : 1); @@ -2123,7 +2123,6 @@ static inline void bnx2x_link_sync_notify(struct bnx2x *bp) /* This function is called upon link interrupt */ static void bnx2x_link_attn(struct bnx2x *bp) { - u32 prev_link_status = bp->link_vars.link_status; /* Make sure that we are synced with the current statistics */ bnx2x_stats_handle(bp, STATS_EVENT_STOP); @@ -2168,17 +2167,15 @@ static void bnx2x_link_attn(struct bnx2x *bp) "single function mode without fairness\n"); } + __bnx2x_link_report(bp); + if (IS_MF(bp)) bnx2x_link_sync_notify(bp); - - /* indicate link status only if link status actually changed */ - if (prev_link_status != bp->link_vars.link_status) - bnx2x_link_report(bp); } void bnx2x__link_status_update(struct bnx2x *bp) { - if ((bp->state != BNX2X_STATE_OPEN) || (bp->flags & MF_FUNC_DIS)) + if (bp->state != BNX2X_STATE_OPEN) return; bnx2x_link_status_update(&bp->link_params, &bp->link_vars); @@ -2188,10 +2185,6 @@ void bnx2x__link_status_update(struct bnx2x *bp) else bnx2x_stats_handle(bp, STATS_EVENT_STOP); - /* the link status update could be the result of a DCC event - hence re-read the shmem mf configuration */ - bnx2x_read_mf_cfg(bp); - /* indicate link status */ bnx2x_link_report(bp); } @@ -3120,10 +3113,14 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn) if (val & DRV_STATUS_SET_MF_BW) bnx2x_set_mf_bw(bp); - bnx2x__link_status_update(bp); if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF)) bnx2x_pmf_update(bp); + /* Always call it here: bnx2x_link_report() will + * prevent the link indication duplication. + */ + bnx2x__link_status_update(bp); + if (bp->port.pmf && (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) && bp->dcbx_enabled > 0) -- cgit v1.2.3-58-ga151 From f9a3ebbe657b5dcd562224b32d1703da499063db Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Wed, 4 May 2011 23:49:11 +0000 Subject: bnx2x: allow WoL on every function in MF modes Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_main.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 3f4ff41cd333..1b3c9f664306 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -8052,13 +8052,9 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) (val >= REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL) ? FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY : 0; - if (BP_E1HVN(bp) == 0) { - pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc); - bp->flags |= (pmc & PCI_PM_CAP_PME_D3cold) ? 0 : NO_WOL_FLAG; - } else { - /* no WOL capability for E1HVN != 0 */ - bp->flags |= NO_WOL_FLAG; - } + pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc); + bp->flags |= (pmc & PCI_PM_CAP_PME_D3cold) ? 0 : NO_WOL_FLAG; + BNX2X_DEV_INFO("%sWoL capable\n", (bp->flags & NO_WOL_FLAG) ? "not " : ""); -- cgit v1.2.3-58-ga151 From 426b92415074d6d268c7aac4561efecd3785d0b1 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Wed, 4 May 2011 23:49:53 +0000 Subject: bnx2x: Do storage mac address validation for SF mode. Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_main.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 1b3c9f664306..660c94560266 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -8560,15 +8560,6 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) BNX2X_DEV_INFO("Read iSCSI MAC: " "0x%x:0x%04x\n", val2, val); bnx2x_set_mac_buf(iscsi_mac, val, val2); - - /* Disable iSCSI OOO if MAC configuration is - * invalid. - */ - if (!is_valid_ether_addr(iscsi_mac)) { - bp->flags |= NO_ISCSI_OOO_FLAG | - NO_ISCSI_FLAG; - memset(iscsi_mac, 0, ETH_ALEN); - } } else bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG; @@ -8581,13 +8572,6 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) "0x%x:0x%04x\n", val2, val); bnx2x_set_mac_buf(fip_mac, val, val2); - /* Disable FCoE if MAC configuration is - * invalid. - */ - if (!is_valid_ether_addr(fip_mac)) { - bp->flags |= NO_FCOE_FLAG; - memset(bp->fip_mac, 0, ETH_ALEN); - } } else bp->flags |= NO_FCOE_FLAG; } @@ -8618,6 +8602,22 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) else if (!IS_MF(bp)) memcpy(fip_mac, iscsi_mac, ETH_ALEN); } + + /* Disable iSCSI if MAC configuration is + * invalid. + */ + if (!is_valid_ether_addr(iscsi_mac)) { + bp->flags |= NO_ISCSI_FLAG; + memset(iscsi_mac, 0, ETH_ALEN); + } + + /* Disable FCoE if MAC configuration is + * invalid. + */ + if (!is_valid_ether_addr(fip_mac)) { + bp->flags |= NO_FCOE_FLAG; + memset(bp->fip_mac, 0, ETH_ALEN); + } #endif } -- cgit v1.2.3-58-ga151 From b3b83c3f3c640b239f1f1dfc49c0ecafbc074fdb Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Wed, 4 May 2011 23:50:33 +0000 Subject: bnx2x: improve memory handling, low memory recovery flows Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x.h | 3 +- drivers/net/bnx2x/bnx2x_cmn.c | 402 ++++++++++++++++++++++++++++++-------- drivers/net/bnx2x/bnx2x_cmn.h | 128 +++++++++--- drivers/net/bnx2x/bnx2x_ethtool.c | 3 +- drivers/net/bnx2x/bnx2x_main.c | 189 ++---------------- 5 files changed, 449 insertions(+), 276 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 1a005a484bea..498a1003d049 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -473,7 +473,8 @@ struct bnx2x_fastpath { #define NUM_RX_BD (RX_DESC_CNT * NUM_RX_RINGS) #define MAX_RX_BD (NUM_RX_BD - 1) #define MAX_RX_AVAIL (MAX_RX_DESC_CNT * NUM_RX_RINGS - 2) -#define MIN_RX_AVAIL 128 +#define MIN_RX_SIZE_TPA 72 +#define MIN_RX_SIZE_NONTPA 10 #define INIT_JUMBO_RX_RING_SIZE MAX_RX_AVAIL #define INIT_RX_RING_SIZE MAX_RX_AVAIL #define NEXT_RX_IDX(x) ((((x) & RX_DESC_MASK) == \ diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 8853ae2a042e..218a7ad7cdd4 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -27,6 +27,49 @@ static int bnx2x_setup_irqs(struct bnx2x *bp); +/** + * bnx2x_bz_fp - zero content of the fastpath structure. + * + * @bp: driver handle + * @index: fastpath index to be zeroed + * + * Makes sure the contents of the bp->fp[index].napi is kept + * intact. + */ +static inline void bnx2x_bz_fp(struct bnx2x *bp, int index) +{ + struct bnx2x_fastpath *fp = &bp->fp[index]; + struct napi_struct orig_napi = fp->napi; + /* bzero bnx2x_fastpath contents */ + memset(fp, 0, sizeof(*fp)); + + /* Restore the NAPI object as it has been already initialized */ + fp->napi = orig_napi; +} + +/** + * bnx2x_move_fp - move content of the fastpath structure. + * + * @bp: driver handle + * @from: source FP index + * @to: destination FP index + * + * Makes sure the contents of the bp->fp[to].napi is kept + * intact. + */ +static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to) +{ + struct bnx2x_fastpath *from_fp = &bp->fp[from]; + struct bnx2x_fastpath *to_fp = &bp->fp[to]; + struct napi_struct orig_napi = to_fp->napi; + /* Move bnx2x_fastpath contents */ + memcpy(to_fp, from_fp, sizeof(*to_fp)); + to_fp->index = to; + + /* Restore the NAPI object as it has been already initialized */ + to_fp->napi = orig_napi; +} + /* free skb in the packet ring at pos idx * return idx of last bd freed */ @@ -881,55 +924,6 @@ void __bnx2x_link_report(struct bnx2x *bp) } } -/* Returns the number of actually allocated BDs */ -static inline int bnx2x_alloc_rx_bds(struct bnx2x_fastpath *fp, - int rx_ring_size) -{ - struct bnx2x *bp = fp->bp; - u16 ring_prod, cqe_ring_prod; - int i; - - fp->rx_comp_cons = 0; - cqe_ring_prod = ring_prod = 0; - for (i = 0; i < rx_ring_size; i++) { - if (bnx2x_alloc_rx_skb(bp, fp, ring_prod) < 0) { - BNX2X_ERR("was only able to allocate " - "%d rx skbs on queue[%d]\n", i, fp->index); - fp->eth_q_stats.rx_skb_alloc_failed++; - break; - } - ring_prod = NEXT_RX_IDX(ring_prod); - cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod); - WARN_ON(ring_prod <= i); - } - - fp->rx_bd_prod = ring_prod; - /* Limit the CQE producer by the CQE ring size */ - fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT, - cqe_ring_prod); - fp->rx_pkt = fp->rx_calls = 0; - - return i; -} - -static inline void bnx2x_alloc_rx_bd_ring(struct bnx2x_fastpath *fp) -{ - struct bnx2x *bp = fp->bp; - int rx_ring_size = bp->rx_ring_size ? bp->rx_ring_size : - MAX_RX_AVAIL/bp->num_queues; - - rx_ring_size = max_t(int, MIN_RX_AVAIL, rx_ring_size); - - bnx2x_alloc_rx_bds(fp, rx_ring_size); - - /* Warning! - * this will generate an interrupt (to the TSTORM) - * must only be done after chip is initialized - */ - bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod, - fp->rx_sge_prod); -} - void bnx2x_init_rx_rings(struct bnx2x *bp) { int func = BP_FUNC(bp); @@ -938,6 +932,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) u16 ring_prod; int i, j; + /* Allocate TPA resources */ for_each_rx_queue(bp, j) { struct bnx2x_fastpath *fp = &bp->fp[j]; @@ -945,6 +940,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) "mtu %d rx_buf_size %d\n", bp->dev->mtu, fp->rx_buf_size); if (!fp->disable_tpa) { + /* Fill the per-aggregation pool */ for (i = 0; i < max_agg_queues; i++) { fp->tpa_pool[i].skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size); @@ -999,13 +995,13 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) fp->rx_bd_cons = 0; - bnx2x_set_next_page_rx_bd(fp); - - /* CQ ring */ - bnx2x_set_next_page_rx_cq(fp); - - /* Allocate BDs and initialize BD ring */ - bnx2x_alloc_rx_bd_ring(fp); + /* Activate BD ring */ + /* Warning! + * this will generate an interrupt (to the TSTORM) + * must only be done after chip is initialized + */ + bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod, + fp->rx_sge_prod); if (j != 0) continue; @@ -1039,27 +1035,40 @@ static void bnx2x_free_tx_skbs(struct bnx2x *bp) } } +static void bnx2x_free_rx_bds(struct bnx2x_fastpath *fp) +{ + struct bnx2x *bp = fp->bp; + int i; + + /* ring wasn't allocated */ + if (fp->rx_buf_ring == NULL) + return; + + for (i = 0; i < NUM_RX_BD; i++) { + struct sw_rx_bd *rx_buf = &fp->rx_buf_ring[i]; + struct sk_buff *skb = rx_buf->skb; + + if (skb == NULL) + continue; + + dma_unmap_single(&bp->pdev->dev, + dma_unmap_addr(rx_buf, mapping), + fp->rx_buf_size, DMA_FROM_DEVICE); + + rx_buf->skb = NULL; + dev_kfree_skb(skb); + } +} + static void bnx2x_free_rx_skbs(struct bnx2x *bp) { - int i, j; + int j; for_each_rx_queue(bp, j) { struct bnx2x_fastpath *fp = &bp->fp[j]; - for (i = 0; i < NUM_RX_BD; i++) { - struct sw_rx_bd *rx_buf = &fp->rx_buf_ring[i]; - struct sk_buff *skb = rx_buf->skb; + bnx2x_free_rx_bds(fp); - if (skb == NULL) - continue; - - dma_unmap_single(&bp->pdev->dev, - dma_unmap_addr(rx_buf, mapping), - fp->rx_buf_size, DMA_FROM_DEVICE); - - rx_buf->skb = NULL; - dev_kfree_skb(skb); - } if (!fp->disable_tpa) bnx2x_free_tpa_pool(bp, fp, CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 : @@ -1435,26 +1444,37 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) /* must be called before memory allocation and HW init */ bnx2x_ilt_set_info(bp); + /* zero fastpath structures preserving invariants like napi which are + * allocated only once + */ + for_each_queue(bp, i) + bnx2x_bz_fp(bp, i); + /* Set the receive queues buffer size */ bnx2x_set_rx_buf_size(bp); + for_each_queue(bp, i) + bnx2x_fp(bp, i, disable_tpa) = + ((bp->flags & TPA_ENABLE_FLAG) == 0); + +#ifdef BCM_CNIC + /* We don't want TPA on FCoE L2 ring */ + bnx2x_fcoe(bp, disable_tpa) = 1; +#endif + if (bnx2x_alloc_mem(bp)) return -ENOMEM; + /* As long as bnx2x_alloc_mem() may possibly update + * bp->num_queues, bnx2x_set_real_num_queues() should always + * come after it. + */ rc = bnx2x_set_real_num_queues(bp); if (rc) { BNX2X_ERR("Unable to set real_num_queues\n"); goto load_error0; } - for_each_queue(bp, i) - bnx2x_fp(bp, i, disable_tpa) = - ((bp->flags & TPA_ENABLE_FLAG) == 0); - -#ifdef BCM_CNIC - /* We don't want TPA on FCoE L2 ring */ - bnx2x_fcoe(bp, disable_tpa) = 1; -#endif bnx2x_napi_enable(bp); /* Send LOAD_REQUEST command to MCP @@ -2480,6 +2500,232 @@ int bnx2x_change_mac_addr(struct net_device *dev, void *p) return 0; } +static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index) +{ + union host_hc_status_block *sb = &bnx2x_fp(bp, fp_index, status_blk); + struct bnx2x_fastpath *fp = &bp->fp[fp_index]; + + /* Common */ +#ifdef BCM_CNIC + if (IS_FCOE_IDX(fp_index)) { + memset(sb, 0, sizeof(union host_hc_status_block)); + fp->status_blk_mapping = 0; + + } else { +#endif + /* status blocks */ + if (CHIP_IS_E2(bp)) + BNX2X_PCI_FREE(sb->e2_sb, + bnx2x_fp(bp, fp_index, + status_blk_mapping), + sizeof(struct host_hc_status_block_e2)); + else + BNX2X_PCI_FREE(sb->e1x_sb, + bnx2x_fp(bp, fp_index, + status_blk_mapping), + sizeof(struct host_hc_status_block_e1x)); +#ifdef BCM_CNIC + } +#endif + /* Rx */ + if (!skip_rx_queue(bp, fp_index)) { + bnx2x_free_rx_bds(fp); + + /* fastpath rx rings: rx_buf rx_desc rx_comp */ + BNX2X_FREE(bnx2x_fp(bp, fp_index, rx_buf_ring)); + BNX2X_PCI_FREE(bnx2x_fp(bp, fp_index, rx_desc_ring), + bnx2x_fp(bp, fp_index, rx_desc_mapping), + sizeof(struct eth_rx_bd) * NUM_RX_BD); + + BNX2X_PCI_FREE(bnx2x_fp(bp, fp_index, rx_comp_ring), + bnx2x_fp(bp, fp_index, rx_comp_mapping), + sizeof(struct eth_fast_path_rx_cqe) * + NUM_RCQ_BD); + + /* SGE ring */ + BNX2X_FREE(bnx2x_fp(bp, fp_index, rx_page_ring)); + BNX2X_PCI_FREE(bnx2x_fp(bp, fp_index, rx_sge_ring), + bnx2x_fp(bp, fp_index, rx_sge_mapping), + BCM_PAGE_SIZE * NUM_RX_SGE_PAGES); + } + + /* Tx */ + if (!skip_tx_queue(bp, fp_index)) { + /* fastpath tx rings: tx_buf tx_desc */ + BNX2X_FREE(bnx2x_fp(bp, fp_index, tx_buf_ring)); + BNX2X_PCI_FREE(bnx2x_fp(bp, fp_index, tx_desc_ring), + bnx2x_fp(bp, fp_index, tx_desc_mapping), + sizeof(union eth_tx_bd_types) * NUM_TX_BD); + } + /* end of fastpath */ +} + +void bnx2x_free_fp_mem(struct bnx2x *bp) +{ + int i; + for_each_queue(bp, i) + bnx2x_free_fp_mem_at(bp, i); +} + +static inline void set_sb_shortcuts(struct bnx2x *bp, int index) +{ + union host_hc_status_block status_blk = bnx2x_fp(bp, index, status_blk); + if (CHIP_IS_E2(bp)) { + bnx2x_fp(bp, index, sb_index_values) = + (__le16 *)status_blk.e2_sb->sb.index_values; + bnx2x_fp(bp, index, sb_running_index) = + (__le16 *)status_blk.e2_sb->sb.running_index; + } else { + bnx2x_fp(bp, index, sb_index_values) = + (__le16 *)status_blk.e1x_sb->sb.index_values; + bnx2x_fp(bp, index, sb_running_index) = + (__le16 *)status_blk.e1x_sb->sb.running_index; + } +} + +static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index) +{ + union host_hc_status_block *sb; + struct bnx2x_fastpath *fp = &bp->fp[index]; + int ring_size = 0; + + /* if rx_ring_size specified - use it */ + int rx_ring_size = bp->rx_ring_size ? bp->rx_ring_size : + MAX_RX_AVAIL/bp->num_queues; + + /* allocate at least number of buffers required by FW */ + rx_ring_size = max_t(int, fp->disable_tpa ? MIN_RX_SIZE_NONTPA : + MIN_RX_SIZE_TPA, + rx_ring_size); + + bnx2x_fp(bp, index, bp) = bp; + bnx2x_fp(bp, index, index) = index; + + /* Common */ + sb = &bnx2x_fp(bp, index, status_blk); +#ifdef BCM_CNIC + if (!IS_FCOE_IDX(index)) { +#endif + /* status blocks */ + if (CHIP_IS_E2(bp)) + BNX2X_PCI_ALLOC(sb->e2_sb, + &bnx2x_fp(bp, index, status_blk_mapping), + sizeof(struct host_hc_status_block_e2)); + else + BNX2X_PCI_ALLOC(sb->e1x_sb, + &bnx2x_fp(bp, index, status_blk_mapping), + sizeof(struct host_hc_status_block_e1x)); +#ifdef BCM_CNIC + } +#endif + set_sb_shortcuts(bp, index); + + /* Tx */ + if (!skip_tx_queue(bp, index)) { + /* fastpath tx rings: tx_buf tx_desc */ + BNX2X_ALLOC(bnx2x_fp(bp, index, tx_buf_ring), + sizeof(struct sw_tx_bd) * NUM_TX_BD); + BNX2X_PCI_ALLOC(bnx2x_fp(bp, index, tx_desc_ring), + &bnx2x_fp(bp, index, tx_desc_mapping), + sizeof(union eth_tx_bd_types) * NUM_TX_BD); + } + + /* Rx */ + if (!skip_rx_queue(bp, index)) { + /* fastpath rx rings: rx_buf rx_desc rx_comp */ + BNX2X_ALLOC(bnx2x_fp(bp, index, rx_buf_ring), + sizeof(struct sw_rx_bd) * NUM_RX_BD); + BNX2X_PCI_ALLOC(bnx2x_fp(bp, index, rx_desc_ring), + &bnx2x_fp(bp, index, rx_desc_mapping), + sizeof(struct eth_rx_bd) * NUM_RX_BD); + + BNX2X_PCI_ALLOC(bnx2x_fp(bp, index, rx_comp_ring), + &bnx2x_fp(bp, index, rx_comp_mapping), + sizeof(struct eth_fast_path_rx_cqe) * + NUM_RCQ_BD); + + /* SGE ring */ + BNX2X_ALLOC(bnx2x_fp(bp, index, rx_page_ring), + sizeof(struct sw_rx_page) * NUM_RX_SGE); + BNX2X_PCI_ALLOC(bnx2x_fp(bp, index, rx_sge_ring), + &bnx2x_fp(bp, index, rx_sge_mapping), + BCM_PAGE_SIZE * NUM_RX_SGE_PAGES); + /* RX BD ring */ + bnx2x_set_next_page_rx_bd(fp); + + /* CQ ring */ + bnx2x_set_next_page_rx_cq(fp); + + /* BDs */ + ring_size = bnx2x_alloc_rx_bds(fp, rx_ring_size); + if (ring_size < rx_ring_size) + goto alloc_mem_err; + } + + return 0; + +/* handles low memory cases */ +alloc_mem_err: + BNX2X_ERR("Unable to allocate full memory for queue %d (size %d)\n", + index, ring_size); + /* FW will drop all packets if queue is not big enough, + * In these cases we disable the queue + * Min size diferent for TPA and non-TPA queues + */ + if (ring_size < (fp->disable_tpa ? + MIN_RX_SIZE_TPA : MIN_RX_SIZE_NONTPA)) { + /* release memory allocated for this queue */ + bnx2x_free_fp_mem_at(bp, index); + return -ENOMEM; + } + return 0; +} + +int bnx2x_alloc_fp_mem(struct bnx2x *bp) +{ + int i; + + /** + * 1. Allocate FP for leading - fatal if error + * 2. {CNIC} Allocate FCoE FP - fatal if error + * 3. Allocate RSS - fix number of queues if error + */ + + /* leading */ + if (bnx2x_alloc_fp_mem_at(bp, 0)) + return -ENOMEM; +#ifdef BCM_CNIC + /* FCoE */ + if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX)) + return -ENOMEM; +#endif + /* RSS */ + for_each_nondefault_eth_queue(bp, i) + if (bnx2x_alloc_fp_mem_at(bp, i)) + break; + + /* handle memory failures */ + if (i != BNX2X_NUM_ETH_QUEUES(bp)) { + int delta = BNX2X_NUM_ETH_QUEUES(bp) - i; + + WARN_ON(delta < 0); +#ifdef BCM_CNIC + /** + * move non eth FPs next to last eth FP + * must be done in that order + * FCOE_IDX < FWD_IDX < OOO_IDX + */ + + /* move FCoE fp */ + bnx2x_move_fp(bp, FCOE_IDX, FCOE_IDX - delta); +#endif + bp->num_queues -= delta; + BNX2X_ERR("Adjusted num of queues from %d to %d\n", + bp->num_queues + delta, bp->num_queues); + } + + return 0; +} static int bnx2x_setup_irqs(struct bnx2x *bp) { diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index 007f29495c2e..68b79a1082ce 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h @@ -25,6 +25,39 @@ extern int num_queues; +/************************ Macros ********************************/ +#define BNX2X_PCI_FREE(x, y, size) \ + do { \ + if (x) { \ + dma_free_coherent(&bp->pdev->dev, size, (void *)x, y); \ + x = NULL; \ + y = 0; \ + } \ + } while (0) + +#define BNX2X_FREE(x) \ + do { \ + if (x) { \ + kfree((void *)x); \ + x = NULL; \ + } \ + } while (0) + +#define BNX2X_PCI_ALLOC(x, y, size) \ + do { \ + x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \ + if (x == NULL) \ + goto alloc_mem_err; \ + memset((void *)x, 0, size); \ + } while (0) + +#define BNX2X_ALLOC(x, size) \ + do { \ + x = kzalloc(size, GFP_KERNEL); \ + if (x == NULL) \ + goto alloc_mem_err; \ + } while (0) + /*********************** Interfaces **************************** * Functions that need to be implemented by each driver version */ @@ -378,6 +411,9 @@ int bnx2x_resume(struct pci_dev *pdev); /* Release IRQ vectors */ void bnx2x_free_irq(struct bnx2x *bp); +void bnx2x_free_fp_mem(struct bnx2x *bp); +int bnx2x_alloc_fp_mem(struct bnx2x *bp); + void bnx2x_init_rx_rings(struct bnx2x *bp); void bnx2x_free_skbs(struct bnx2x *bp); void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw); @@ -884,6 +920,9 @@ static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp, { int i; + if (fp->disable_tpa) + return; + for (i = 0; i < last; i++) bnx2x_free_rx_sge(bp, fp, i); } @@ -912,36 +951,39 @@ static inline void bnx2x_free_tpa_pool(struct bnx2x *bp, } } - -static inline void bnx2x_init_tx_rings(struct bnx2x *bp) +static inline void bnx2x_init_tx_ring_one(struct bnx2x_fastpath *fp) { - int i, j; + int i; - for_each_tx_queue(bp, j) { - struct bnx2x_fastpath *fp = &bp->fp[j]; + for (i = 1; i <= NUM_TX_RINGS; i++) { + struct eth_tx_next_bd *tx_next_bd = + &fp->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd; - for (i = 1; i <= NUM_TX_RINGS; i++) { - struct eth_tx_next_bd *tx_next_bd = - &fp->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd; + tx_next_bd->addr_hi = + cpu_to_le32(U64_HI(fp->tx_desc_mapping + + BCM_PAGE_SIZE*(i % NUM_TX_RINGS))); + tx_next_bd->addr_lo = + cpu_to_le32(U64_LO(fp->tx_desc_mapping + + BCM_PAGE_SIZE*(i % NUM_TX_RINGS))); + } - tx_next_bd->addr_hi = - cpu_to_le32(U64_HI(fp->tx_desc_mapping + - BCM_PAGE_SIZE*(i % NUM_TX_RINGS))); - tx_next_bd->addr_lo = - cpu_to_le32(U64_LO(fp->tx_desc_mapping + - BCM_PAGE_SIZE*(i % NUM_TX_RINGS))); - } + SET_FLAG(fp->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1); + fp->tx_db.data.zero_fill1 = 0; + fp->tx_db.data.prod = 0; - SET_FLAG(fp->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1); - fp->tx_db.data.zero_fill1 = 0; - fp->tx_db.data.prod = 0; + fp->tx_pkt_prod = 0; + fp->tx_pkt_cons = 0; + fp->tx_bd_prod = 0; + fp->tx_bd_cons = 0; + fp->tx_pkt = 0; +} - fp->tx_pkt_prod = 0; - fp->tx_pkt_cons = 0; - fp->tx_bd_prod = 0; - fp->tx_bd_cons = 0; - fp->tx_pkt = 0; - } +static inline void bnx2x_init_tx_rings(struct bnx2x *bp) +{ + int i; + + for_each_tx_queue(bp, i) + bnx2x_init_tx_ring_one(&bp->fp[i]); } static inline void bnx2x_set_next_page_rx_bd(struct bnx2x_fastpath *fp) @@ -996,6 +1038,44 @@ static inline void bnx2x_set_next_page_rx_cq(struct bnx2x_fastpath *fp) } } +/* Returns the number of actually allocated BDs */ +static inline int bnx2x_alloc_rx_bds(struct bnx2x_fastpath *fp, + int rx_ring_size) +{ + struct bnx2x *bp = fp->bp; + u16 ring_prod, cqe_ring_prod; + int i; + + fp->rx_comp_cons = 0; + cqe_ring_prod = ring_prod = 0; + + /* This routine is called only during fo init so + * fp->eth_q_stats.rx_skb_alloc_failed = 0 + */ + for (i = 0; i < rx_ring_size; i++) { + if (bnx2x_alloc_rx_skb(bp, fp, ring_prod) < 0) { + fp->eth_q_stats.rx_skb_alloc_failed++; + continue; + } + ring_prod = NEXT_RX_IDX(ring_prod); + cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod); + WARN_ON(ring_prod <= (i - fp->eth_q_stats.rx_skb_alloc_failed)); + } + + if (fp->eth_q_stats.rx_skb_alloc_failed) + BNX2X_ERR("was only able to allocate " + "%d rx skbs on queue[%d]\n", + (i - fp->eth_q_stats.rx_skb_alloc_failed), fp->index); + + fp->rx_bd_prod = ring_prod; + /* Limit the CQE producer by the CQE ring size */ + fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT, + cqe_ring_prod); + fp->rx_pkt = fp->rx_calls = 0; + + return i - fp->eth_q_stats.rx_skb_alloc_failed; +} + #ifdef BCM_CNIC static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp) { diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index 4f42c314986c..7556fde23294 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c @@ -1220,7 +1220,8 @@ static int bnx2x_set_ringparam(struct net_device *dev, } if ((ering->rx_pending > MAX_RX_AVAIL) || - (ering->rx_pending < MIN_RX_AVAIL) || + (ering->rx_pending < (bp->disable_tpa ? MIN_RX_SIZE_NONTPA : + MIN_RX_SIZE_TPA)) || (ering->tx_pending > MAX_TX_AVAIL) || (ering->tx_pending <= MAX_SKB_FRAGS + 4)) return -EINVAL; diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 660c94560266..4be5480ecc5b 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -4447,7 +4447,7 @@ static void bnx2x_init_fp_sb(struct bnx2x *bp, int fp_idx) fp->state = BNX2X_FP_STATE_CLOSED; - fp->index = fp->cid = fp_idx; + fp->cid = fp_idx; fp->cl_id = BP_L_ID(bp) + fp_idx; fp->fw_sb_id = bp->base_fw_ndsb + fp->cl_id + CNIC_CONTEXT_USE; fp->igu_sb_id = bp->igu_base_sb + fp_idx + CNIC_CONTEXT_USE; @@ -4559,9 +4559,11 @@ gunzip_nomem1: static void bnx2x_gunzip_end(struct bnx2x *bp) { - kfree(bp->strm->workspace); - kfree(bp->strm); - bp->strm = NULL; + if (bp->strm) { + kfree(bp->strm->workspace); + kfree(bp->strm); + bp->strm = NULL; + } if (bp->gunzip_buf) { dma_free_coherent(&bp->pdev->dev, FW_BUF_SIZE, bp->gunzip_buf, @@ -5869,9 +5871,6 @@ int bnx2x_init_hw(struct bnx2x *bp, u32 load_code) bp->dmae_ready = 0; spin_lock_init(&bp->dmae_lock); - rc = bnx2x_gunzip_init(bp); - if (rc) - return rc; switch (load_code) { case FW_MSG_CODE_DRV_LOAD_COMMON: @@ -5915,80 +5914,10 @@ init_hw_err: void bnx2x_free_mem(struct bnx2x *bp) { - -#define BNX2X_PCI_FREE(x, y, size) \ - do { \ - if (x) { \ - dma_free_coherent(&bp->pdev->dev, size, (void *)x, y); \ - x = NULL; \ - y = 0; \ - } \ - } while (0) - -#define BNX2X_FREE(x) \ - do { \ - if (x) { \ - kfree((void *)x); \ - x = NULL; \ - } \ - } while (0) - - int i; + bnx2x_gunzip_end(bp); /* fastpath */ - /* Common */ - for_each_queue(bp, i) { -#ifdef BCM_CNIC - /* FCoE client uses default status block */ - if (IS_FCOE_IDX(i)) { - union host_hc_status_block *sb = - &bnx2x_fp(bp, i, status_blk); - memset(sb, 0, sizeof(union host_hc_status_block)); - bnx2x_fp(bp, i, status_blk_mapping) = 0; - } else { -#endif - /* status blocks */ - if (CHIP_IS_E2(bp)) - BNX2X_PCI_FREE(bnx2x_fp(bp, i, status_blk.e2_sb), - bnx2x_fp(bp, i, status_blk_mapping), - sizeof(struct host_hc_status_block_e2)); - else - BNX2X_PCI_FREE(bnx2x_fp(bp, i, status_blk.e1x_sb), - bnx2x_fp(bp, i, status_blk_mapping), - sizeof(struct host_hc_status_block_e1x)); -#ifdef BCM_CNIC - } -#endif - } - /* Rx */ - for_each_rx_queue(bp, i) { - - /* fastpath rx rings: rx_buf rx_desc rx_comp */ - BNX2X_FREE(bnx2x_fp(bp, i, rx_buf_ring)); - BNX2X_PCI_FREE(bnx2x_fp(bp, i, rx_desc_ring), - bnx2x_fp(bp, i, rx_desc_mapping), - sizeof(struct eth_rx_bd) * NUM_RX_BD); - - BNX2X_PCI_FREE(bnx2x_fp(bp, i, rx_comp_ring), - bnx2x_fp(bp, i, rx_comp_mapping), - sizeof(struct eth_fast_path_rx_cqe) * - NUM_RCQ_BD); - - /* SGE ring */ - BNX2X_FREE(bnx2x_fp(bp, i, rx_page_ring)); - BNX2X_PCI_FREE(bnx2x_fp(bp, i, rx_sge_ring), - bnx2x_fp(bp, i, rx_sge_mapping), - BCM_PAGE_SIZE * NUM_RX_SGE_PAGES); - } - /* Tx */ - for_each_tx_queue(bp, i) { - - /* fastpath tx rings: tx_buf tx_desc */ - BNX2X_FREE(bnx2x_fp(bp, i, tx_buf_ring)); - BNX2X_PCI_FREE(bnx2x_fp(bp, i, tx_desc_ring), - bnx2x_fp(bp, i, tx_desc_mapping), - sizeof(union eth_tx_bd_types) * NUM_TX_BD); - } + bnx2x_free_fp_mem(bp); /* end of fastpath */ BNX2X_PCI_FREE(bp->def_status_blk, bp->def_status_blk_mapping, @@ -6021,101 +5950,13 @@ void bnx2x_free_mem(struct bnx2x *bp) BCM_PAGE_SIZE * NUM_EQ_PAGES); BNX2X_FREE(bp->rx_indir_table); - -#undef BNX2X_PCI_FREE -#undef BNX2X_KFREE } -static inline void set_sb_shortcuts(struct bnx2x *bp, int index) -{ - union host_hc_status_block status_blk = bnx2x_fp(bp, index, status_blk); - if (CHIP_IS_E2(bp)) { - bnx2x_fp(bp, index, sb_index_values) = - (__le16 *)status_blk.e2_sb->sb.index_values; - bnx2x_fp(bp, index, sb_running_index) = - (__le16 *)status_blk.e2_sb->sb.running_index; - } else { - bnx2x_fp(bp, index, sb_index_values) = - (__le16 *)status_blk.e1x_sb->sb.index_values; - bnx2x_fp(bp, index, sb_running_index) = - (__le16 *)status_blk.e1x_sb->sb.running_index; - } -} int bnx2x_alloc_mem(struct bnx2x *bp) { -#define BNX2X_PCI_ALLOC(x, y, size) \ - do { \ - x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \ - if (x == NULL) \ - goto alloc_mem_err; \ - memset(x, 0, size); \ - } while (0) - -#define BNX2X_ALLOC(x, size) \ - do { \ - x = kzalloc(size, GFP_KERNEL); \ - if (x == NULL) \ - goto alloc_mem_err; \ - } while (0) - - int i; - - /* fastpath */ - /* Common */ - for_each_queue(bp, i) { - union host_hc_status_block *sb = &bnx2x_fp(bp, i, status_blk); - bnx2x_fp(bp, i, bp) = bp; - /* status blocks */ -#ifdef BCM_CNIC - if (!IS_FCOE_IDX(i)) { -#endif - if (CHIP_IS_E2(bp)) - BNX2X_PCI_ALLOC(sb->e2_sb, - &bnx2x_fp(bp, i, status_blk_mapping), - sizeof(struct host_hc_status_block_e2)); - else - BNX2X_PCI_ALLOC(sb->e1x_sb, - &bnx2x_fp(bp, i, status_blk_mapping), - sizeof(struct host_hc_status_block_e1x)); -#ifdef BCM_CNIC - } -#endif - set_sb_shortcuts(bp, i); - } - /* Rx */ - for_each_queue(bp, i) { - - /* fastpath rx rings: rx_buf rx_desc rx_comp */ - BNX2X_ALLOC(bnx2x_fp(bp, i, rx_buf_ring), - sizeof(struct sw_rx_bd) * NUM_RX_BD); - BNX2X_PCI_ALLOC(bnx2x_fp(bp, i, rx_desc_ring), - &bnx2x_fp(bp, i, rx_desc_mapping), - sizeof(struct eth_rx_bd) * NUM_RX_BD); - - BNX2X_PCI_ALLOC(bnx2x_fp(bp, i, rx_comp_ring), - &bnx2x_fp(bp, i, rx_comp_mapping), - sizeof(struct eth_fast_path_rx_cqe) * - NUM_RCQ_BD); - - /* SGE ring */ - BNX2X_ALLOC(bnx2x_fp(bp, i, rx_page_ring), - sizeof(struct sw_rx_page) * NUM_RX_SGE); - BNX2X_PCI_ALLOC(bnx2x_fp(bp, i, rx_sge_ring), - &bnx2x_fp(bp, i, rx_sge_mapping), - BCM_PAGE_SIZE * NUM_RX_SGE_PAGES); - } - /* Tx */ - for_each_queue(bp, i) { - - /* fastpath tx rings: tx_buf tx_desc */ - BNX2X_ALLOC(bnx2x_fp(bp, i, tx_buf_ring), - sizeof(struct sw_tx_bd) * NUM_TX_BD); - BNX2X_PCI_ALLOC(bnx2x_fp(bp, i, tx_desc_ring), - &bnx2x_fp(bp, i, tx_desc_mapping), - sizeof(union eth_tx_bd_types) * NUM_TX_BD); - } - /* end of fastpath */ + if (bnx2x_gunzip_init(bp)) + return -ENOMEM; #ifdef BCM_CNIC if (CHIP_IS_E2(bp)) @@ -6155,14 +5996,18 @@ int bnx2x_alloc_mem(struct bnx2x *bp) BNX2X_ALLOC(bp->rx_indir_table, sizeof(bp->rx_indir_table[0]) * TSTORM_INDIRECTION_TABLE_SIZE); + + /* fastpath */ + /* need to be done at the end, since it's self adjusting to amount + * of memory available for RSS queues + */ + if (bnx2x_alloc_fp_mem(bp)) + goto alloc_mem_err; return 0; alloc_mem_err: bnx2x_free_mem(bp); return -ENOMEM; - -#undef BNX2X_PCI_ALLOC -#undef BNX2X_ALLOC } /* -- cgit v1.2.3-58-ga151 From 5de924086aca9f17eee9ad569e0af2f699f591b3 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Wed, 4 May 2011 23:51:13 +0000 Subject: bnx2x: update year to 2011 and version to 1.62.12-0 Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x.h | 6 +++--- drivers/net/bnx2x/bnx2x_cmn.c | 2 +- drivers/net/bnx2x/bnx2x_cmn.h | 2 +- drivers/net/bnx2x/bnx2x_dcb.c | 2 +- drivers/net/bnx2x/bnx2x_dcb.h | 2 +- drivers/net/bnx2x/bnx2x_ethtool.c | 2 +- drivers/net/bnx2x/bnx2x_fw_defs.h | 2 +- drivers/net/bnx2x/bnx2x_fw_file_hdr.h | 2 +- drivers/net/bnx2x/bnx2x_hsi.h | 2 +- drivers/net/bnx2x/bnx2x_init.h | 2 +- drivers/net/bnx2x/bnx2x_init_ops.h | 2 +- drivers/net/bnx2x/bnx2x_main.c | 2 +- drivers/net/bnx2x/bnx2x_reg.h | 2 +- drivers/net/bnx2x/bnx2x_stats.c | 2 +- drivers/net/bnx2x/bnx2x_stats.h | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 498a1003d049..16a76f074df5 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -1,6 +1,6 @@ /* bnx2x.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2010 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,8 +22,8 @@ * (you will need to reboot afterwards) */ /* #define BNX2X_STOP_ON_ERROR */ -#define DRV_MODULE_VERSION "1.62.11-0" -#define DRV_MODULE_RELDATE "2011/01/31" +#define DRV_MODULE_VERSION "1.62.12-0" +#define DRV_MODULE_RELDATE "2011/03/20" #define BNX2X_BC_VER 0x040200 #define BNX2X_MULTI_QUEUE diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 218a7ad7cdd4..269d6d1e0d2f 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -1,6 +1,6 @@ /* bnx2x_cmn.c: Broadcom Everest network driver. * - * Copyright (c) 2007-2010 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index 68b79a1082ce..72f206e49911 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h @@ -1,6 +1,6 @@ /* bnx2x_cmn.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2010 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c index 1214907d00d9..3396ff2dac61 100644 --- a/drivers/net/bnx2x/bnx2x_dcb.c +++ b/drivers/net/bnx2x/bnx2x_dcb.c @@ -1,6 +1,6 @@ /* bnx2x_dcb.c: Broadcom Everest network driver. * - * Copyright 2009-2010 Broadcom Corporation + * Copyright 2009-2011 Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you diff --git a/drivers/net/bnx2x/bnx2x_dcb.h b/drivers/net/bnx2x/bnx2x_dcb.h index 1e14775a18cb..bb6e9a5b4004 100644 --- a/drivers/net/bnx2x/bnx2x_dcb.h +++ b/drivers/net/bnx2x/bnx2x_dcb.h @@ -1,6 +1,6 @@ /* bnx2x_dcb.h: Broadcom Everest network driver. * - * Copyright 2009-2010 Broadcom Corporation + * Copyright 2009-2011 Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index 7556fde23294..727fe89ff37f 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c @@ -1,6 +1,6 @@ /* bnx2x_ethtool.c: Broadcom Everest network driver. * - * Copyright (c) 2007-2010 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x/bnx2x_fw_defs.h b/drivers/net/bnx2x/bnx2x_fw_defs.h index f4e5b1ce8149..9fe367836a57 100644 --- a/drivers/net/bnx2x/bnx2x_fw_defs.h +++ b/drivers/net/bnx2x/bnx2x_fw_defs.h @@ -1,6 +1,6 @@ /* bnx2x_fw_defs.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2010 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x/bnx2x_fw_file_hdr.h b/drivers/net/bnx2x/bnx2x_fw_file_hdr.h index f807262911e5..f4a07fbaed05 100644 --- a/drivers/net/bnx2x/bnx2x_fw_file_hdr.h +++ b/drivers/net/bnx2x/bnx2x_fw_file_hdr.h @@ -1,6 +1,6 @@ /* bnx2x_fw_file_hdr.h: FW binary file header structure. * - * Copyright (c) 2007-2009 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h index 2b5940af5d1b..cdf19fe7c7f6 100644 --- a/drivers/net/bnx2x/bnx2x_hsi.h +++ b/drivers/net/bnx2x/bnx2x_hsi.h @@ -1,6 +1,6 @@ /* bnx2x_hsi.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2010 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x/bnx2x_init.h b/drivers/net/bnx2x/bnx2x_init.h index fa6dbe3f2058..d5399206f66e 100644 --- a/drivers/net/bnx2x/bnx2x_init.h +++ b/drivers/net/bnx2x/bnx2x_init.h @@ -1,7 +1,7 @@ /* bnx2x_init.h: Broadcom Everest network driver. * Structures and macroes needed during the initialization. * - * Copyright (c) 2007-2009 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x/bnx2x_init_ops.h b/drivers/net/bnx2x/bnx2x_init_ops.h index 66df29fcf751..aafd0232393f 100644 --- a/drivers/net/bnx2x/bnx2x_init_ops.h +++ b/drivers/net/bnx2x/bnx2x_init_ops.h @@ -2,7 +2,7 @@ * Static functions needed during the initialization. * This file is "included" in bnx2x_main.c. * - * Copyright (c) 2007-2010 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 4be5480ecc5b..0c31b9127636 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -1,6 +1,6 @@ /* bnx2x_main.c: Broadcom Everest network driver. * - * Copyright (c) 2007-2010 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h index 1509a2318af9..86bba25d2d3f 100644 --- a/drivers/net/bnx2x/bnx2x_reg.h +++ b/drivers/net/bnx2x/bnx2x_reg.h @@ -1,6 +1,6 @@ /* bnx2x_reg.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2010 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/bnx2x/bnx2x_stats.c index 3445ded6674f..e535bfa08945 100644 --- a/drivers/net/bnx2x/bnx2x_stats.c +++ b/drivers/net/bnx2x/bnx2x_stats.c @@ -1,6 +1,6 @@ /* bnx2x_stats.c: Broadcom Everest network driver. * - * Copyright (c) 2007-2010 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x/bnx2x_stats.h b/drivers/net/bnx2x/bnx2x_stats.h index 596798c47452..45d14d8bc1aa 100644 --- a/drivers/net/bnx2x/bnx2x_stats.h +++ b/drivers/net/bnx2x/bnx2x_stats.h @@ -1,6 +1,6 @@ /* bnx2x_stats.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2010 Broadcom Corporation + * Copyright (c) 2007-2011 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- cgit v1.2.3-58-ga151 From e8920674979705392abc4db4ebbe78feb68a4da1 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Wed, 4 May 2011 23:52:40 +0000 Subject: bnx2x: function descriptions format fixed Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_cmn.c | 45 +++--- drivers/net/bnx2x/bnx2x_cmn.h | 305 ++++++++++++++++++----------------------- drivers/net/bnx2x/bnx2x_dcb.c | 26 ---- drivers/net/bnx2x/bnx2x_dcb.h | 6 - drivers/net/bnx2x/bnx2x_link.c | 14 +- drivers/net/bnx2x/bnx2x_main.c | 64 ++++----- 6 files changed, 194 insertions(+), 266 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 269d6d1e0d2f..6ee6601b5176 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -308,13 +308,15 @@ static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue, */ #define TPA_TSTAMP_OPT_LEN 12 /** - * Calculate the approximate value of the MSS for this - * aggregation using the first packet of it. + * bnx2x_set_lro_mss - calculate the approximate value of the MSS * - * @param bp - * @param parsing_flags Parsing flags from the START CQE - * @param len_on_bd Total length of the first packet for the - * aggregation. + * @bp: driver handle + * @parsing_flags: parsing flags from the START CQE + * @len_on_bd: total length of the first packet for the + * aggregation. + * + * Approximate value of the MSS for this aggregation calculated using + * the first packet of it. */ static inline u16 bnx2x_set_lro_mss(struct bnx2x *bp, u16 parsing_flags, u16 len_on_bd) @@ -2083,12 +2085,11 @@ static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, u32 *parsing_data, } /** - * Update PBD in GSO case. + * bnx2x_set_pbd_gso - update PBD in GSO case. * - * @param skb - * @param tx_start_bd - * @param pbd - * @param xmit_type + * @skb: packet skb + * @pbd: parse BD + * @xmit_type: xmit flags */ static inline void bnx2x_set_pbd_gso(struct sk_buff *skb, struct eth_tx_parse_bd_e1x *pbd, @@ -2115,13 +2116,14 @@ static inline void bnx2x_set_pbd_gso(struct sk_buff *skb, } /** + * bnx2x_set_pbd_csum_e2 - update PBD with checksum and return header length * - * @param skb - * @param tx_start_bd - * @param pbd_e2 - * @param xmit_type + * @bp: driver handle + * @skb: packet skb + * @parsing_data: data to be updated + * @xmit_type: xmit flags * - * @return header len + * 57712 related */ static inline u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb, u32 *parsing_data, u32 xmit_type) @@ -2146,13 +2148,12 @@ static inline u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb, } /** + * bnx2x_set_pbd_csum - update PBD with checksum and return header length * - * @param skb - * @param tx_start_bd - * @param pbd - * @param xmit_type - * - * @return Header length + * @bp: driver handle + * @skb: packet skb + * @pbd: parse BD to be updated + * @xmit_type: xmit flags */ static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb, struct eth_tx_parse_bd_e1x *pbd, diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index 72f206e49911..fab161e8030d 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h @@ -63,43 +63,41 @@ extern int num_queues; */ /** - * Initialize link parameters structure variables. + * bnx2x_initial_phy_init - initialize link parameters structure variables. * - * @param bp - * @param load_mode - * - * @return u8 + * @bp: driver handle + * @load_mode: current mode */ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode); /** - * Configure hw according to link parameters structure. + * bnx2x_link_set - configure hw according to link parameters structure. * - * @param bp + * @bp: driver handle */ void bnx2x_link_set(struct bnx2x *bp); /** - * Query link status + * bnx2x_link_test - query link status. * - * @param bp - * @param is_serdes + * @bp: driver handle + * @is_serdes: bool * - * @return 0 - link is UP + * Returns 0 if link is UP. */ u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes); /** - * Handles link status change + * bnx2x__link_status_update - handles link status change. * - * @param bp + * @bp: driver handle */ void bnx2x__link_status_update(struct bnx2x *bp); /** - * Report link status to upper layer + * bnx2x_link_report - report link status to upper layer. * - * @param bp + * @bp: driver handle */ void bnx2x_link_report(struct bnx2x *bp); @@ -107,212 +105,197 @@ void bnx2x_link_report(struct bnx2x *bp); void __bnx2x_link_report(struct bnx2x *bp); /** - * calculates MF speed according to current linespeed and MF - * configuration + * bnx2x_get_mf_speed - calculate MF speed. * - * @param bp + * @bp: driver handle * - * @return u16 + * Takes into account current linespeed and MF configuration. */ u16 bnx2x_get_mf_speed(struct bnx2x *bp); /** - * MSI-X slowpath interrupt handler - * - * @param irq - * @param dev_instance + * bnx2x_msix_sp_int - MSI-X slowpath interrupt handler * - * @return irqreturn_t + * @irq: irq number + * @dev_instance: private instance */ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance); /** - * non MSI-X interrupt handler - * - * @param irq - * @param dev_instance + * bnx2x_interrupt - non MSI-X interrupt handler * - * @return irqreturn_t + * @irq: irq number + * @dev_instance: private instance */ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance); #ifdef BCM_CNIC /** - * Send command to cnic driver + * bnx2x_cnic_notify - send command to cnic driver * - * @param bp - * @param cmd + * @bp: driver handle + * @cmd: command */ int bnx2x_cnic_notify(struct bnx2x *bp, int cmd); /** - * Provides cnic information for proper interrupt handling + * bnx2x_setup_cnic_irq_info - provides cnic with IRQ information * - * @param bp + * @bp: driver handle */ void bnx2x_setup_cnic_irq_info(struct bnx2x *bp); #endif /** - * Enable HW interrupts. + * bnx2x_int_enable - enable HW interrupts. * - * @param bp + * @bp: driver handle */ void bnx2x_int_enable(struct bnx2x *bp); /** - * Disable interrupts. This function ensures that there are no - * ISRs or SP DPCs (sp_task) are running after it returns. + * bnx2x_int_disable_sync - disable interrupts. + * + * @bp: driver handle + * @disable_hw: true, disable HW interrupts. * - * @param bp - * @param disable_hw if true, disable HW interrupts. + * This function ensures that there are no + * ISRs or SP DPCs (sp_task) are running after it returns. */ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw); /** - * Loads device firmware - * - * @param bp + * bnx2x_init_firmware - loads device firmware * - * @return int + * @bp: driver handle */ int bnx2x_init_firmware(struct bnx2x *bp); /** - * Init HW blocks according to current initialization stage: - * COMMON, PORT or FUNCTION. + * bnx2x_init_hw - init HW blocks according to current initialization stage. * - * @param bp - * @param load_code: COMMON, PORT or FUNCTION - * - * @return int + * @bp: driver handle + * @load_code: COMMON, PORT or FUNCTION */ int bnx2x_init_hw(struct bnx2x *bp, u32 load_code); /** - * Init driver internals: + * bnx2x_nic_init - init driver internals. + * + * @bp: driver handle + * @load_code: COMMON, PORT or FUNCTION + * + * Initializes: * - rings * - status blocks * - etc. - * - * @param bp - * @param load_code COMMON, PORT or FUNCTION */ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code); /** - * Allocate driver's memory. - * - * @param bp + * bnx2x_alloc_mem - allocate driver's memory. * - * @return int + * @bp: driver handle */ int bnx2x_alloc_mem(struct bnx2x *bp); /** - * Release driver's memory. + * bnx2x_free_mem - release driver's memory. * - * @param bp + * @bp: driver handle */ void bnx2x_free_mem(struct bnx2x *bp); /** - * Setup eth Client. + * bnx2x_setup_client - setup eth client. * - * @param bp - * @param fp - * @param is_leading - * - * @return int + * @bp: driver handle + * @fp: pointer to fastpath structure + * @is_leading: boolean */ int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp, int is_leading); /** - * Set number of queues according to mode - * - * @param bp + * bnx2x_set_num_queues - set number of queues according to mode. * + * @bp: driver handle */ void bnx2x_set_num_queues(struct bnx2x *bp); /** - * Cleanup chip internals: + * bnx2x_chip_cleanup - cleanup chip internals. + * + * @bp: driver handle + * @unload_mode: COMMON, PORT, FUNCTION + * * - Cleanup MAC configuration. - * - Close clients. + * - Closes clients. * - etc. - * - * @param bp - * @param unload_mode */ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode); /** - * Acquire HW lock. - * - * @param bp - * @param resource Resource bit which was locked + * bnx2x_acquire_hw_lock - acquire HW lock. * - * @return int + * @bp: driver handle + * @resource: resource bit which was locked */ int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource); /** - * Release HW lock. + * bnx2x_release_hw_lock - release HW lock. * - * @param bp driver handle - * @param resource Resource bit which was locked - * - * @return int + * @bp: driver handle + * @resource: resource bit which was locked */ int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource); /** - * Configure eth MAC address in the HW according to the value in - * netdev->dev_addr. + * bnx2x_set_eth_mac - configure eth MAC address in the HW + * + * @bp: driver handle + * @set: set or clear * - * @param bp driver handle - * @param set + * Configures according to the value in netdev->dev_addr. */ void bnx2x_set_eth_mac(struct bnx2x *bp, int set); #ifdef BCM_CNIC /** - * Set/Clear FIP MAC(s) at the next enties in the CAM after the ETH - * MAC(s). This function will wait until the ramdord completion - * returns. + * bnx2x_set_fip_eth_mac_addr - Set/Clear FIP MAC(s) * - * @param bp driver handle - * @param set set or clear the CAM entry + * @bp: driver handle + * @set: set or clear the CAM entry * - * @return 0 if cussess, -ENODEV if ramrod doesn't return. + * Used next enties in the CAM after the ETH MAC(s). + * This function will wait until the ramdord completion returns. + * Return 0 if cussess, -ENODEV if ramrod doesn't return. */ int bnx2x_set_fip_eth_mac_addr(struct bnx2x *bp, int set); /** - * Set/Clear ALL_ENODE mcast MAC. - * - * @param bp - * @param set + * bnx2x_set_all_enode_macs - Set/Clear ALL_ENODE mcast MAC. * - * @return int + * @bp: driver handle + * @set: set or clear */ int bnx2x_set_all_enode_macs(struct bnx2x *bp, int set); #endif /** - * Set MAC filtering configurations. + * bnx2x_set_rx_mode - set MAC filtering configurations. * - * @remarks called with netif_tx_lock from dev_mcast.c + * @dev: netdevice * - * @param dev net_device + * called with netif_tx_lock from dev_mcast.c */ void bnx2x_set_rx_mode(struct net_device *dev); /** - * Configure MAC filtering rules in a FW. + * bnx2x_set_storm_rx_mode - configure MAC filtering rules in a FW. * - * @param bp driver handle + * @bp: driver handle */ void bnx2x_set_storm_rx_mode(struct bnx2x *bp); @@ -324,63 +307,59 @@ bool bnx2x_reset_is_done(struct bnx2x *bp); void bnx2x_disable_close_the_gate(struct bnx2x *bp); /** - * Perform statistics handling according to event + * bnx2x_stats_handle - perform statistics handling according to event. * - * @param bp driver handle - * @param event bnx2x_stats_event + * @bp: driver handle + * @event: bnx2x_stats_event */ void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event); /** - * Handle ramrods completion + * bnx2x_sp_event - handle ramrods completion. * - * @param fp fastpath handle for the event - * @param rr_cqe eth_rx_cqe + * @fp: fastpath handle for the event + * @rr_cqe: eth_rx_cqe */ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe); /** - * Init/halt function before/after sending - * CLIENT_SETUP/CFC_DEL for the first/last client. + * bnx2x_func_start - init function * - * @param bp + * @bp: driver handle * - * @return int + * Must be called before sending CLIENT_SETUP for the first client. */ int bnx2x_func_start(struct bnx2x *bp); /** - * Prepare ILT configurations according to current driver - * parameters. + * bnx2x_ilt_set_info - prepare ILT configurations. * - * @param bp + * @bp: driver handle */ void bnx2x_ilt_set_info(struct bnx2x *bp); /** - * Inintialize dcbx protocol + * bnx2x_dcbx_init - initialize dcbx protocol. * - * @param bp + * @bp: driver handle */ void bnx2x_dcbx_init(struct bnx2x *bp); /** - * Set power state to the requested value. Currently only D0 and - * D3hot are supported. + * bnx2x_set_power_state - set power state to the requested value. * - * @param bp - * @param state D0 or D3hot + * @bp: driver handle + * @state: required state D0 or D3hot * - * @return int + * Currently only D0 and D3hot are supported. */ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state); /** - * Updates MAX part of MF configuration in HW - * (if required) + * bnx2x_update_max_mf_config - update MAX part of MF configuration in HW. * - * @param bp - * @param value + * @bp: driver handle + * @value: new value */ void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value); @@ -420,51 +399,51 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw); void bnx2x_netif_start(struct bnx2x *bp); /** - * Fill msix_table, request vectors, update num_queues according - * to number of available vectors + * bnx2x_enable_msix - set msix configuration. * - * @param bp + * @bp: driver handle * - * @return int + * fills msix_table, requests vectors, updates num_queues + * according to number of available vectors. */ int bnx2x_enable_msix(struct bnx2x *bp); /** - * Request msi mode from OS, updated internals accordingly + * bnx2x_enable_msi - request msi mode from OS, updated internals accordingly * - * @param bp - * - * @return int + * @bp: driver handle */ int bnx2x_enable_msi(struct bnx2x *bp); /** - * NAPI callback + * bnx2x_poll - NAPI callback * - * @param napi - * @param budget + * @napi: napi structure + * @budget: * - * @return int */ int bnx2x_poll(struct napi_struct *napi, int budget); /** - * Allocate/release memories outsize main driver structure - * - * @param bp + * bnx2x_alloc_mem_bp - allocate memories outsize main driver structure * - * @return int + * @bp: driver handle */ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp); + +/** + * bnx2x_free_mem_bp - release memories outsize main driver structure + * + * @bp: driver handle + */ void bnx2x_free_mem_bp(struct bnx2x *bp); /** - * Change mtu netdev callback + * bnx2x_change_mtu - change mtu netdev callback * - * @param dev - * @param new_mtu + * @dev: net device + * @new_mtu: requested mtu * - * @return int */ int bnx2x_change_mtu(struct net_device *dev, int new_mtu); @@ -472,29 +451,12 @@ u32 bnx2x_fix_features(struct net_device *dev, u32 features); int bnx2x_set_features(struct net_device *dev, u32 features); /** - * tx timeout netdev callback + * bnx2x_tx_timeout - tx timeout netdev callback * - * @param dev - * @param new_mtu - * - * @return int + * @dev: net device */ void bnx2x_tx_timeout(struct net_device *dev); -#ifdef BCM_VLAN -/** - * vlan rx register netdev callback - * - * @param dev - * @param new_mtu - * - * @return int - */ -void bnx2x_vlan_rx_register(struct net_device *dev, - struct vlan_group *vlgrp); - -#endif - static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp) { barrier(); /* status block is written to by the chip */ @@ -745,7 +707,7 @@ static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp) /** * disables tx from stack point of view * - * @param bp + * @bp: driver handle */ static inline void bnx2x_tx_disable(struct bnx2x *bp) { @@ -1149,12 +1111,11 @@ void bnx2x_acquire_phy_lock(struct bnx2x *bp); void bnx2x_release_phy_lock(struct bnx2x *bp); /** - * Extracts MAX BW part from MF configuration. + * bnx2x_extract_max_cfg - extract MAX BW part from MF configuration. * - * @param bp - * @param mf_cfg + * @bp: driver handle + * @mf_cfg: MF configuration * - * @return u16 */ static inline u16 bnx2x_extract_max_cfg(struct bnx2x *bp, u32 mf_cfg) { diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c index 3396ff2dac61..0f8309233ff2 100644 --- a/drivers/net/bnx2x/bnx2x_dcb.c +++ b/drivers/net/bnx2x/bnx2x_dcb.c @@ -1079,12 +1079,6 @@ static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp, } } - -/******************************************************************************* - * Description: single priority group - * - * Return: - ******************************************************************************/ static void bnx2x_dcbx_ets_disabled_entry_data(struct bnx2x *bp, struct cos_help_data *cos_data, u32 pri_join_mask) @@ -1097,11 +1091,6 @@ static void bnx2x_dcbx_ets_disabled_entry_data(struct bnx2x *bp, cos_data->num_of_cos = 1; } -/******************************************************************************* - * Description: updating the cos bw - * - * Return: - ******************************************************************************/ static inline void bnx2x_dcbx_add_to_cos_bw(struct bnx2x *bp, struct cos_entry_help_data *data, u8 pg_bw) @@ -1112,11 +1101,6 @@ static inline void bnx2x_dcbx_add_to_cos_bw(struct bnx2x *bp, data->cos_bw += pg_bw; } -/******************************************************************************* - * Description: single priority group - * - * Return: - ******************************************************************************/ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp, struct cos_help_data *cos_data, u32 *pg_pri_orginal_spread, @@ -1369,11 +1353,6 @@ static void bnx2x_dcbx_two_pg_to_cos_params( } } -/******************************************************************************* - * Description: Still - * - * Return: - ******************************************************************************/ static void bnx2x_dcbx_three_pg_to_cos_params( struct bnx2x *bp, struct pg_help_data *pg_help_data, @@ -1561,11 +1540,6 @@ static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp, } } -/******************************************************************************* - * Description: Fill pfc_config struct that will be sent in DCBX start ramrod - * - * Return: - ******************************************************************************/ static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp) { struct flow_control_configuration *pfc_fw_cfg = NULL; diff --git a/drivers/net/bnx2x/bnx2x_dcb.h b/drivers/net/bnx2x/bnx2x_dcb.h index bb6e9a5b4004..bed369d67e02 100644 --- a/drivers/net/bnx2x/bnx2x_dcb.h +++ b/drivers/net/bnx2x/bnx2x_dcb.h @@ -61,9 +61,6 @@ struct bnx2x_dcbx_port_params { #define BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE 1 #define BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID (BNX2X_DCBX_CONFIG_INV_VALUE) -/******************************************************************************* - * LLDP protocol configuration parameters. - ******************************************************************************/ struct bnx2x_config_lldp_params { u32 overwrite_settings; u32 msg_tx_hold; @@ -83,9 +80,6 @@ struct bnx2x_admin_priority_app_table { u32 app_id; }; -/******************************************************************************* - * DCBX protocol configuration parameters. - ******************************************************************************/ struct bnx2x_config_dcbx_params { u32 overwrite_settings; u32 admin_dcbx_version; diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index 974ef2be36a5..076e11f5769f 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c @@ -385,7 +385,7 @@ u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos) return 0; } /******************************************************************/ -/* ETS section */ +/* PFC section */ /******************************************************************/ static void bnx2x_bmac2_get_pfc_stat(struct link_params *params, @@ -1301,14 +1301,12 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl, return 0; } -/* - * get_emac_base - * - * @param cb - * @param mdc_mdio_access - * @param port +/** + * bnx2x_get_emac_base - retrive emac base address * - * @return u32 + * @bp: driver handle + * @mdc_mdio_access: access type + * @port: port id * * This function selects the MDC/MDIO access (through emac0 or * emac1) depend on the mdc_mdio_access, port, port swapped. Each diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 0c31b9127636..2762edf956e9 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -6035,14 +6035,14 @@ static int bnx2x_func_stop(struct bnx2x *bp) } /** - * Sets a MAC in a CAM for a few L2 Clients for E1x chips + * bnx2x_set_mac_addr_gen - set a MAC in a CAM for a few L2 Clients for E1x chips * - * @param bp driver descriptor - * @param set set or clear an entry (1 or 0) - * @param mac pointer to a buffer containing a MAC - * @param cl_bit_vec bit vector of clients to register a MAC for - * @param cam_offset offset in a CAM to use - * @param is_bcast is the set MAC a broadcast address (for E1 only) + * @bp: driver handle + * @set: set or clear an entry (1 or 0) + * @mac: pointer to a buffer containing a MAC + * @cl_bit_vec: bit vector of clients to register a MAC for + * @cam_offset: offset in a CAM to use + * @is_bcast: is the set MAC a broadcast address (for E1 only) */ static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, const u8 *mac, u32 cl_bit_vec, u8 cam_offset, @@ -6402,14 +6402,13 @@ void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp) #ifdef BCM_CNIC /** - * Set iSCSI MAC(s) at the next enties in the CAM after the ETH - * MAC(s). This function will wait until the ramdord completion - * returns. + * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s). * - * @param bp driver handle - * @param set set or clear the CAM entry + * @bp: driver handle + * @set: set or clear the CAM entry * - * @return 0 if cussess, -ENODEV if ramrod doesn't return. + * This function will wait until the ramdord completion returns. + * Return 0 if success, -ENODEV if ramrod doesn't return. */ static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set) { @@ -6430,14 +6429,13 @@ static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set) } /** - * Set FCoE L2 MAC(s) at the next enties in the CAM after the - * ETH MAC(s). This function will wait until the ramdord - * completion returns. + * bnx2x_set_fip_eth_mac_addr - set FCoE L2 MAC(s) * - * @param bp driver handle - * @param set set or clear the CAM entry + * @bp: driver handle + * @set: set or clear the CAM entry * - * @return 0 if cussess, -ENODEV if ramrod doesn't return. + * This function will wait until the ramrod completion returns. + * Returns 0 if success, -ENODEV if ramrod doesn't return. */ int bnx2x_set_fip_eth_mac_addr(struct bnx2x *bp, int set) { @@ -6641,12 +6639,11 @@ static int bnx2x_setup_fw_client(struct bnx2x *bp, } /** - * Configure interrupt mode according to current configuration. - * In case of MSI-X it will also try to enable MSI-X. + * bnx2x_set_int_mode - configure interrupt mode * - * @param bp + * @bp: driver handle * - * @return int + * In case of MSI-X it will also try to enable MSI-X. */ static int __devinit bnx2x_set_int_mode(struct bnx2x *bp) { @@ -7230,10 +7227,11 @@ static void bnx2x_clp_reset_prep(struct bnx2x *bp, u32 *magic_val) MF_CFG_WR(bp, shared_mf_config.clp_mb, val | SHARED_MF_CLP_MAGIC); } -/* Restore the value of the `magic' bit. +/** + * bnx2x_clp_reset_done - restore the value of the `magic' bit. * - * @param pdev Device handle. - * @param magic_val Old value of the `magic' bit. + * @bp: driver handle + * @magic_val: old value of the `magic' bit. */ static void bnx2x_clp_reset_done(struct bnx2x *bp, u32 magic_val) { @@ -7244,10 +7242,12 @@ static void bnx2x_clp_reset_done(struct bnx2x *bp, u32 magic_val) } /** - * Prepares for MCP reset: takes care of CLP configurations. + * bnx2x_reset_mcp_prep - prepare for MCP reset. * - * @param bp - * @param magic_val Old value of 'magic' bit. + * @bp: driver handle + * @magic_val: old value of 'magic' bit. + * + * Takes care of CLP configurations. */ static void bnx2x_reset_mcp_prep(struct bnx2x *bp, u32 *magic_val) { @@ -7272,10 +7272,10 @@ static void bnx2x_reset_mcp_prep(struct bnx2x *bp, u32 *magic_val) #define MCP_TIMEOUT 5000 /* 5 seconds (in ms) */ #define MCP_ONE_TIMEOUT 100 /* 100 ms */ -/* Waits for MCP_ONE_TIMEOUT or MCP_ONE_TIMEOUT*10, - * depending on the HW type. +/** + * bnx2x_mcp_wait_one - wait for MCP_ONE_TIMEOUT * - * @param bp + * @bp: driver handle */ static inline void bnx2x_mcp_wait_one(struct bnx2x *bp) { -- cgit v1.2.3-58-ga151 From 1c5cae815d19ffe02bdfda1260949ef2b1806171 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sat, 30 Apr 2011 01:21:32 +0000 Subject: net: call dev_alloc_name from register_netdevice Force dev_alloc_name() to be called from register_netdevice() by dev_get_valid_name(). That allows to remove multiple explicit dev_alloc_name() calls. The possibility to call dev_alloc_name in advance remains. This also fixes veth creation regresion caused by 84c49d8c3e4abefb0a41a77b25aa37ebe8d6b743 Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/ieee802154/fakehard.c | 10 ---------- drivers/net/bonding/bond_main.c | 21 +++------------------ drivers/net/dummy.c | 4 ---- drivers/net/hamradio/bpqether.c | 4 ---- drivers/net/ifb.c | 4 ---- drivers/net/tun.c | 6 ------ drivers/net/wan/dlci.c | 4 ---- drivers/net/wan/hdlc_fr.c | 9 +-------- drivers/net/wan/lapbether.c | 4 ---- drivers/net/wireless/hostap/hostap_main.c | 7 +------ drivers/net/wireless/mac80211_hwsim.c | 11 +---------- drivers/net/wireless/mwifiex/main.c | 4 ---- drivers/s390/net/netiucv.c | 2 -- net/core/dev.c | 24 ++++++------------------ net/core/rtnetlink.c | 8 -------- net/ipv4/ip_gre.c | 5 ----- net/ipv4/ipip.c | 5 ----- net/ipv6/ip6_tunnel.c | 5 ----- net/ipv6/sit.c | 5 ----- net/mac80211/iface.c | 4 ---- 20 files changed, 12 insertions(+), 134 deletions(-) diff --git a/drivers/ieee802154/fakehard.c b/drivers/ieee802154/fakehard.c index d9d0e13efe47..a5a49a1baae7 100644 --- a/drivers/ieee802154/fakehard.c +++ b/drivers/ieee802154/fakehard.c @@ -393,16 +393,6 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev) priv = netdev_priv(dev); priv->phy = phy; - /* - * If the name is a format string the caller wants us to do a - * name allocation. - */ - if (strchr(dev->name, '%')) { - err = dev_alloc_name(dev, dev->name); - if (err < 0) - goto out; - } - wpan_phy_set_dev(phy, &pdev->dev); SET_NETDEV_DEV(dev, &phy->dev); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 22bd03bd1d35..9a5feaf4bab9 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4917,8 +4917,9 @@ int bond_create(struct net *net, const char *name) rtnl_lock(); - bond_dev = alloc_netdev_mq(sizeof(struct bonding), name ? name : "", - bond_setup, tx_queues); + bond_dev = alloc_netdev_mq(sizeof(struct bonding), + name ? name : "bond%d", + bond_setup, tx_queues); if (!bond_dev) { pr_err("%s: eek! can't alloc netdev!\n", name); rtnl_unlock(); @@ -4928,26 +4929,10 @@ int bond_create(struct net *net, const char *name) dev_net_set(bond_dev, net); bond_dev->rtnl_link_ops = &bond_link_ops; - if (!name) { - res = dev_alloc_name(bond_dev, "bond%d"); - if (res < 0) - goto out; - } else { - /* - * If we're given a name to register - * we need to ensure that its not already - * registered - */ - res = -EEXIST; - if (__dev_get_by_name(net, name) != NULL) - goto out; - } - res = register_netdevice(bond_dev); netif_carrier_off(bond_dev); -out: rtnl_unlock(); if (res < 0) bond_destructor(bond_dev); diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index ff2d29b17858..39cf9b9bd673 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -168,10 +168,6 @@ static int __init dummy_init_one(void) if (!dev_dummy) return -ENOMEM; - err = dev_alloc_name(dev_dummy, dev_dummy->name); - if (err < 0) - goto err; - dev_dummy->rtnl_link_ops = &dummy_link_ops; err = register_netdevice(dev_dummy); if (err < 0) diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 8931168d3e74..18d8affecd1b 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -516,10 +516,6 @@ static int bpq_new_device(struct net_device *edev) memcpy(bpq->dest_addr, bcast_addr, sizeof(bpq_eth_addr)); memcpy(bpq->acpt_addr, bcast_addr, sizeof(bpq_eth_addr)); - err = dev_alloc_name(ndev, ndev->name); - if (err < 0) - goto error; - err = register_netdevice(ndev); if (err) goto error; diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index e07d487f015a..4fecaed67fc4 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -233,10 +233,6 @@ static int __init ifb_init_one(int index) if (!dev_ifb) return -ENOMEM; - err = dev_alloc_name(dev_ifb, dev_ifb->name); - if (err < 0) - goto err; - dev_ifb->rtnl_link_ops = &ifb_link_ops; err = register_netdevice(dev_ifb); if (err < 0) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 0636f7040325..74e94054ab1a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1099,12 +1099,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) tun_net_init(dev); - if (strchr(dev->name, '%')) { - err = dev_alloc_name(dev, dev->name); - if (err < 0) - goto err_free_sk; - } - dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | TUN_USER_FEATURES; dev->features = dev->hw_features; diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index 1481a446fefb..21b104db5a90 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -341,10 +341,6 @@ static int dlci_add(struct dlci_add *dlci) } } - err = dev_alloc_name(master, master->name); - if (err < 0) - goto err2; - *(short *)(master->dev_addr) = dlci->dlci; dlp = netdev_priv(master); diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index 0edb535bb2b5..fc433f28c047 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -1070,7 +1070,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) hdlc_device *hdlc = dev_to_hdlc(frad); pvc_device *pvc; struct net_device *dev; - int result, used; + int used; if ((pvc = add_pvc(frad, dlci)) == NULL) { printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n", @@ -1106,13 +1106,6 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) dev->tx_queue_len = 0; dev->ml_priv = pvc; - result = dev_alloc_name(dev, dev->name); - if (result < 0) { - free_netdev(dev); - delete_unused_pvcs(hdlc); - return result; - } - if (register_netdevice(dev) != 0) { free_netdev(dev); delete_unused_pvcs(hdlc); diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index 7f5bb913c8b9..eec463f99c09 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -338,10 +338,6 @@ static int lapbeth_new_device(struct net_device *dev) dev_hold(dev); lapbeth->ethdev = dev; - rc = dev_alloc_name(ndev, ndev->name); - if (rc < 0) - goto fail; - rc = -EIO; if (register_netdevice(ndev)) goto fail; diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 1d9aed645723..d5084829c9e5 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c @@ -79,13 +79,8 @@ struct net_device * hostap_add_interface(struct local_info *local, if (!rtnl_locked) rtnl_lock(); - ret = 0; - if (strchr(dev->name, '%')) - ret = dev_alloc_name(dev, dev->name); - SET_NETDEV_DEV(dev, mdev->dev.parent); - if (ret >= 0) - ret = register_netdevice(dev); + ret = register_netdevice(dev); if (!rtnl_locked) rtnl_unlock(); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index f4f4257a9d67..9d4a40ee16c4 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1515,19 +1515,10 @@ static int __init init_mac80211_hwsim(void) if (hwsim_mon == NULL) goto failed; - rtnl_lock(); - - err = dev_alloc_name(hwsim_mon, hwsim_mon->name); + err = register_netdev(hwsim_mon); if (err < 0) goto failed_mon; - - err = register_netdevice(hwsim_mon); - if (err < 0) - goto failed_mon; - - rtnl_unlock(); - return 0; failed_mon: diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index c5971880e7b3..d16cea770fa3 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -706,10 +706,6 @@ static struct mwifiex_private *mwifiex_add_interface( dev_err(adapter->dev, "no memory available for netdevice\n"); goto error; } - if (dev_alloc_name(dev, dev->name)) { - dev_err(adapter->dev, "unable to alloc name for netdevice\n"); - goto error; - } if (mwifiex_register_cfg80211(dev, adapter->priv[bss_index]->curr_addr, adapter->priv[bss_index]) != 0) { diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index b6a6356d09b3..3251333a23df 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1994,8 +1994,6 @@ static struct net_device *netiucv_init_netdevice(char *username) netiucv_setup_netdevice); if (!dev) return NULL; - if (dev_alloc_name(dev, dev->name) < 0) - goto out_netdev; privptr = netdev_priv(dev); privptr->fsm = init_fsm("netiucvdev", dev_state_names, diff --git a/net/core/dev.c b/net/core/dev.c index e95dc30110eb..3b79bad3d02d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -948,7 +948,7 @@ int dev_alloc_name(struct net_device *dev, const char *name) } EXPORT_SYMBOL(dev_alloc_name); -static int dev_get_valid_name(struct net_device *dev, const char *name, bool fmt) +static int dev_get_valid_name(struct net_device *dev, const char *name) { struct net *net; @@ -958,7 +958,7 @@ static int dev_get_valid_name(struct net_device *dev, const char *name, bool fmt if (!dev_valid_name(name)) return -EINVAL; - if (fmt && strchr(name, '%')) + if (strchr(name, '%')) return dev_alloc_name(dev, name); else if (__dev_get_by_name(net, name)) return -EEXIST; @@ -995,7 +995,7 @@ int dev_change_name(struct net_device *dev, const char *newname) memcpy(oldname, dev->name, IFNAMSIZ); - err = dev_get_valid_name(dev, newname, 1); + err = dev_get_valid_name(dev, newname); if (err < 0) return err; @@ -5420,8 +5420,8 @@ int register_netdevice(struct net_device *dev) } } - ret = dev_get_valid_name(dev, dev->name, 0); - if (ret) + ret = dev_get_valid_name(dev, dev->name); + if (ret < 0) goto err_uninit; dev->ifindex = dev_new_index(net); @@ -5562,19 +5562,7 @@ int register_netdev(struct net_device *dev) int err; rtnl_lock(); - - /* - * If the name is a format string the caller wants us to do a - * name allocation. - */ - if (strchr(dev->name, '%')) { - err = dev_alloc_name(dev, dev->name); - if (err < 0) - goto out; - } - err = register_netdevice(dev); -out: rtnl_unlock(); return err; } @@ -6056,7 +6044,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char /* We get here if we can't use the current device name */ if (!pat) goto out; - if (dev_get_valid_name(dev, pat, 1)) + if (dev_get_valid_name(dev, pat) < 0) goto out; } diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 296331257195..5a160f4a1ba0 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1572,12 +1572,6 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net, dev->rtnl_link_state = RTNL_LINK_INITIALIZING; dev->real_num_tx_queues = real_num_queues; - if (strchr(dev->name, '%')) { - err = dev_alloc_name(dev, dev->name); - if (err < 0) - goto err_free; - } - if (tb[IFLA_MTU]) dev->mtu = nla_get_u32(tb[IFLA_MTU]); if (tb[IFLA_ADDRESS]) @@ -1597,8 +1591,6 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net, return dev; -err_free: - free_netdev(dev); err: return ERR_PTR(err); } diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 10e9b5aea070..8871067560db 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -413,11 +413,6 @@ static struct ip_tunnel *ipgre_tunnel_locate(struct net *net, dev_net_set(dev, net); - if (strchr(name, '%')) { - if (dev_alloc_name(dev, name) < 0) - goto failed_free; - } - nt = netdev_priv(dev); nt->parms = *parms; dev->rtnl_link_ops = &ipgre_link_ops; diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index bfa0b9895040..378b20b7ca6e 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -276,11 +276,6 @@ static struct ip_tunnel * ipip_tunnel_locate(struct net *net, dev_net_set(dev, net); - if (strchr(name, '%')) { - if (dev_alloc_name(dev, name) < 0) - goto failed_free; - } - nt = netdev_priv(dev); nt->parms = *parms; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 3dff27cba95c..36c2842a86b2 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -280,11 +280,6 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p) dev_net_set(dev, net); - if (strchr(name, '%')) { - if (dev_alloc_name(dev, name) < 0) - goto failed_free; - } - t = netdev_priv(dev); t->parms = *p; err = ip6_tnl_dev_init(dev); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index c53abcf50d29..a6a32b39b607 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -250,11 +250,6 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, dev_net_set(dev, net); - if (strchr(name, '%')) { - if (dev_alloc_name(dev, name) < 0) - goto failed_free; - } - nt = netdev_priv(dev); nt->parms = *parms; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 4054399be907..80c29d626aa4 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1144,10 +1144,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, + IEEE80211_ENCRYPT_HEADROOM; ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; - ret = dev_alloc_name(ndev, ndev->name); - if (ret < 0) - goto fail; - ieee80211_assign_perm_addr(local, ndev, type); memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); -- cgit v1.2.3-58-ga151 From 228e548e602061b08ee8e8966f567c12aa079682 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 2 May 2011 20:21:35 +0000 Subject: net: Add sendmmsg socket system call This patch adds a multiple message send syscall and is the send version of the existing recvmmsg syscall. This is heavily based on the patch by Arnaldo that added recvmmsg. I wrote a microbenchmark to test the performance gains of using this new syscall: http://ozlabs.org/~anton/junkcode/sendmmsg_test.c The test was run on a ppc64 box with a 10 Gbit network card. The benchmark can send both UDP and RAW ethernet packets. 64B UDP batch pkts/sec 1 804570 2 872800 (+ 8 %) 4 916556 (+14 %) 8 939712 (+17 %) 16 952688 (+18 %) 32 956448 (+19 %) 64 964800 (+20 %) 64B raw socket batch pkts/sec 1 1201449 2 1350028 (+12 %) 4 1461416 (+22 %) 8 1513080 (+26 %) 16 1541216 (+28 %) 32 1553440 (+29 %) 64 1557888 (+30 %) We see a 20% improvement in throughput on UDP send and 30% on raw socket send. [ Add sparc syscall entries. -DaveM ] Signed-off-by: Anton Blanchard Signed-off-by: David S. Miller --- arch/powerpc/include/asm/systbl.h | 1 + arch/powerpc/include/asm/unistd.h | 3 +- arch/sparc/include/asm/unistd.h | 3 +- arch/sparc/kernel/systbls_32.S | 2 +- arch/sparc/kernel/systbls_64.S | 4 +- arch/x86/ia32/ia32entry.S | 1 + arch/x86/include/asm/unistd_32.h | 3 +- arch/x86/include/asm/unistd_64.h | 2 + arch/x86/kernel/syscall_table_32.S | 1 + include/linux/net.h | 1 + include/linux/socket.h | 2 + include/linux/syscalls.h | 2 + include/net/compat.h | 2 + kernel/sys_ni.c | 2 + net/compat.c | 16 ++- net/socket.c | 199 +++++++++++++++++++++++++++++-------- 16 files changed, 192 insertions(+), 52 deletions(-) diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index 60f64b132bd4..8489d372077f 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h @@ -352,3 +352,4 @@ SYSCALL_SPU(name_to_handle_at) COMPAT_SYS_SPU(open_by_handle_at) COMPAT_SYS_SPU(clock_adjtime) SYSCALL_SPU(syncfs) +COMPAT_SYS_SPU(sendmmsg) diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index 3c215648ce6d..6d23c8193caa 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -371,10 +371,11 @@ #define __NR_open_by_handle_at 346 #define __NR_clock_adjtime 347 #define __NR_syncfs 348 +#define __NR_sendmmsg 349 #ifdef __KERNEL__ -#define __NR_syscalls 349 +#define __NR_syscalls 350 #define __NR__exit __NR_exit #define NR_syscalls __NR_syscalls diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index 9d897b6db983..c5387ed0add8 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h @@ -404,8 +404,9 @@ #define __NR_open_by_handle_at 333 #define __NR_clock_adjtime 334 #define __NR_syncfs 335 +#define __NR_sendmmsg 336 -#define NR_syscalls 336 +#define NR_syscalls 337 #ifdef __32bit_syscall_numbers__ /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index 47ac73c32e88..332c83ff7701 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -84,4 +84,4 @@ sys_call_table: /*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv /*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init /*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime -/*335*/ .long sys_syncfs +/*335*/ .long sys_syncfs, sys_sendmmsg diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index 4f3170c1ef47..43887ca0be0e 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -85,7 +85,7 @@ sys_call_table32: /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init /*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime - .word sys_syncfs + .word sys_syncfs, compat_sys_sendmmsg #endif /* CONFIG_COMPAT */ @@ -162,4 +162,4 @@ sys_call_table: /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init /*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime - .word sys_syncfs + .word sys_syncfs, sys_sendmmsg diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 849a9d23c71d..95f5826be458 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -848,4 +848,5 @@ ia32_sys_call_table: .quad compat_sys_open_by_handle_at .quad compat_sys_clock_adjtime .quad sys_syncfs + .quad compat_sys_sendmmsg /* 345 */ ia32_syscall_end: diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h index a755ef5e5977..fb6a625c99bf 100644 --- a/arch/x86/include/asm/unistd_32.h +++ b/arch/x86/include/asm/unistd_32.h @@ -350,10 +350,11 @@ #define __NR_open_by_handle_at 342 #define __NR_clock_adjtime 343 #define __NR_syncfs 344 +#define __NR_sendmmsg 345 #ifdef __KERNEL__ -#define NR_syscalls 345 +#define NR_syscalls 346 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h index 160fa76bd578..79f90eb15aad 100644 --- a/arch/x86/include/asm/unistd_64.h +++ b/arch/x86/include/asm/unistd_64.h @@ -677,6 +677,8 @@ __SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at) __SYSCALL(__NR_clock_adjtime, sys_clock_adjtime) #define __NR_syncfs 306 __SYSCALL(__NR_syncfs, sys_syncfs) +#define __NR_sendmmsg 307 +__SYSCALL(__NR_sendmmsg, sys_sendmmsg) #ifndef __NO_STUBS #define __ARCH_WANT_OLD_READDIR diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S index abce34d5c79d..32cbffb0c494 100644 --- a/arch/x86/kernel/syscall_table_32.S +++ b/arch/x86/kernel/syscall_table_32.S @@ -344,3 +344,4 @@ ENTRY(sys_call_table) .long sys_open_by_handle_at .long sys_clock_adjtime .long sys_syncfs + .long sys_sendmmsg /* 345 */ diff --git a/include/linux/net.h b/include/linux/net.h index 94de83c0f877..1da55e9b6f01 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -42,6 +42,7 @@ #define SYS_RECVMSG 17 /* sys_recvmsg(2) */ #define SYS_ACCEPT4 18 /* sys_accept4(2) */ #define SYS_RECVMMSG 19 /* sys_recvmmsg(2) */ +#define SYS_SENDMMSG 20 /* sys_sendmmsg(2) */ typedef enum { SS_FREE = 0, /* not allocated */ diff --git a/include/linux/socket.h b/include/linux/socket.h index d2b5e982f079..4ef98e422fde 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -333,5 +333,7 @@ struct timespec; extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, unsigned int flags, struct timespec *timeout); +extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, + unsigned int vlen, unsigned int flags); #endif /* not kernel and not glibc */ #endif /* _LINUX_SOCKET_H */ diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 83ecc1749ef6..ab71447d0c5a 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -610,6 +610,8 @@ asmlinkage long sys_send(int, void __user *, size_t, unsigned); asmlinkage long sys_sendto(int, void __user *, size_t, unsigned, struct sockaddr __user *, int); asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags); +asmlinkage long sys_sendmmsg(int fd, struct mmsghdr __user *msg, + unsigned int vlen, unsigned flags); asmlinkage long sys_recv(int, void __user *, size_t, unsigned); asmlinkage long sys_recvfrom(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *); diff --git a/include/net/compat.h b/include/net/compat.h index 28d5428ec6a2..9ee75edcc295 100644 --- a/include/net/compat.h +++ b/include/net/compat.h @@ -43,6 +43,8 @@ extern int compat_sock_get_timestampns(struct sock *, struct timespec __user *); extern int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *); extern int verify_compat_iovec(struct msghdr *, struct iovec *, struct sockaddr *, int); extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned); +extern asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *, + unsigned, unsigned); extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned); extern asmlinkage long compat_sys_recvmmsg(int, struct compat_mmsghdr __user *, unsigned, unsigned, diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 25cc41cd8f33..97e966f171c6 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -46,7 +46,9 @@ cond_syscall(sys_getsockopt); cond_syscall(compat_sys_getsockopt); cond_syscall(sys_shutdown); cond_syscall(sys_sendmsg); +cond_syscall(sys_sendmmsg); cond_syscall(compat_sys_sendmsg); +cond_syscall(compat_sys_sendmmsg); cond_syscall(sys_recvmsg); cond_syscall(sys_recvmmsg); cond_syscall(compat_sys_recvmsg); diff --git a/net/compat.c b/net/compat.c index 3649d5895361..c578d9382e19 100644 --- a/net/compat.c +++ b/net/compat.c @@ -722,11 +722,11 @@ EXPORT_SYMBOL(compat_mc_getsockopt); /* Argument list sizes for compat_sys_socketcall */ #define AL(x) ((x) * sizeof(u32)) -static unsigned char nas[20] = { +static unsigned char nas[21] = { AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), - AL(4), AL(5) + AL(4), AL(5), AL(4) }; #undef AL @@ -735,6 +735,13 @@ asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, uns return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); } +asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, + unsigned vlen, unsigned int flags) +{ + return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, + flags | MSG_CMSG_COMPAT); +} + asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) { return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); @@ -780,7 +787,7 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args) u32 a[6]; u32 a0, a1; - if (call < SYS_SOCKET || call > SYS_RECVMMSG) + if (call < SYS_SOCKET || call > SYS_SENDMMSG) return -EINVAL; if (copy_from_user(a, args, nas[call])) return -EFAULT; @@ -839,6 +846,9 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args) case SYS_SENDMSG: ret = compat_sys_sendmsg(a0, compat_ptr(a1), a[2]); break; + case SYS_SENDMMSG: + ret = compat_sys_sendmmsg(a0, compat_ptr(a1), a[2], a[3]); + break; case SYS_RECVMSG: ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]); break; diff --git a/net/socket.c b/net/socket.c index d25f5a9d6fa2..ed50255143d5 100644 --- a/net/socket.c +++ b/net/socket.c @@ -551,11 +551,10 @@ int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags) } EXPORT_SYMBOL(sock_tx_timestamp); -static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, size_t size) +static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock, + struct msghdr *msg, size_t size) { struct sock_iocb *si = kiocb_to_siocb(iocb); - int err; sock_update_classid(sock->sk); @@ -564,13 +563,17 @@ static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, si->msg = msg; si->size = size; - err = security_socket_sendmsg(sock, msg, size); - if (err) - return err; - return sock->ops->sendmsg(iocb, sock, msg, size); } +static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *msg, size_t size) +{ + int err = security_socket_sendmsg(sock, msg, size); + + return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size); +} + int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) { struct kiocb iocb; @@ -586,6 +589,20 @@ int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) } EXPORT_SYMBOL(sock_sendmsg); +int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size) +{ + struct kiocb iocb; + struct sock_iocb siocb; + int ret; + + init_sync_kiocb(&iocb, NULL); + iocb.private = &siocb; + ret = __sock_sendmsg_nosec(&iocb, sock, msg, size); + if (-EIOCBQUEUED == ret) + ret = wait_on_sync_kiocb(&iocb); + return ret; +} + int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, size_t num, size_t size) { @@ -1863,57 +1880,47 @@ SYSCALL_DEFINE2(shutdown, int, fd, int, how) #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) -/* - * BSD sendmsg interface - */ - -SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) +static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, + struct msghdr *msg_sys, unsigned flags, int nosec) { struct compat_msghdr __user *msg_compat = (struct compat_msghdr __user *)msg; - struct socket *sock; struct sockaddr_storage address; struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; unsigned char ctl[sizeof(struct cmsghdr) + 20] __attribute__ ((aligned(sizeof(__kernel_size_t)))); /* 20 is size of ipv6_pktinfo */ unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; int err, ctl_len, iov_size, total_len; - int fput_needed; err = -EFAULT; if (MSG_CMSG_COMPAT & flags) { - if (get_compat_msghdr(&msg_sys, msg_compat)) + if (get_compat_msghdr(msg_sys, msg_compat)) return -EFAULT; - } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr))) + } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) return -EFAULT; - sock = sockfd_lookup_light(fd, &err, &fput_needed); - if (!sock) - goto out; - /* do not move before msg_sys is valid */ err = -EMSGSIZE; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; + if (msg_sys->msg_iovlen > UIO_MAXIOV) + goto out; /* Check whether to allocate the iovec area */ err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { + iov_size = msg_sys->msg_iovlen * sizeof(struct iovec); + if (msg_sys->msg_iovlen > UIO_FASTIOV) { iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); if (!iov) - goto out_put; + goto out; } /* This will also move the address data into kernel space */ if (MSG_CMSG_COMPAT & flags) { - err = verify_compat_iovec(&msg_sys, iov, + err = verify_compat_iovec(msg_sys, iov, (struct sockaddr *)&address, VERIFY_READ); } else - err = verify_iovec(&msg_sys, iov, + err = verify_iovec(msg_sys, iov, (struct sockaddr *)&address, VERIFY_READ); if (err < 0) @@ -1922,17 +1929,17 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) err = -ENOBUFS; - if (msg_sys.msg_controllen > INT_MAX) + if (msg_sys->msg_controllen > INT_MAX) goto out_freeiov; - ctl_len = msg_sys.msg_controllen; + ctl_len = msg_sys->msg_controllen; if ((MSG_CMSG_COMPAT & flags) && ctl_len) { err = - cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl, + cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl, sizeof(ctl)); if (err) goto out_freeiov; - ctl_buf = msg_sys.msg_control; - ctl_len = msg_sys.msg_controllen; + ctl_buf = msg_sys->msg_control; + ctl_len = msg_sys->msg_controllen; } else if (ctl_len) { if (ctl_len > sizeof(ctl)) { ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); @@ -1941,21 +1948,22 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) } err = -EFAULT; /* - * Careful! Before this, msg_sys.msg_control contains a user pointer. + * Careful! Before this, msg_sys->msg_control contains a user pointer. * Afterwards, it will be a kernel pointer. Thus the compiler-assisted * checking falls down on this. */ if (copy_from_user(ctl_buf, - (void __user __force *)msg_sys.msg_control, + (void __user __force *)msg_sys->msg_control, ctl_len)) goto out_freectl; - msg_sys.msg_control = ctl_buf; + msg_sys->msg_control = ctl_buf; } - msg_sys.msg_flags = flags; + msg_sys->msg_flags = flags; if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); + msg_sys->msg_flags |= MSG_DONTWAIT; + err = (nosec ? sock_sendmsg_nosec : sock_sendmsg)(sock, msg_sys, + total_len); out_freectl: if (ctl_buf != ctl) @@ -1963,12 +1971,114 @@ out_freectl: out_freeiov: if (iov != iovstack) sock_kfree_s(sock->sk, iov, iov_size); -out_put: +out: + return err; +} + +/* + * BSD sendmsg interface + */ + +SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) +{ + int fput_needed, err; + struct msghdr msg_sys; + struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed); + + if (!sock) + goto out; + + err = __sys_sendmsg(sock, msg, &msg_sys, flags, 0); + fput_light(sock->file, fput_needed); out: return err; } +/* + * Linux sendmmsg interface + */ + +int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, + unsigned int flags) +{ + int fput_needed, err, datagrams; + struct socket *sock; + struct mmsghdr __user *entry; + struct compat_mmsghdr __user *compat_entry; + struct msghdr msg_sys; + + datagrams = 0; + + sock = sockfd_lookup_light(fd, &err, &fput_needed); + if (!sock) + return err; + + err = sock_error(sock->sk); + if (err) + goto out_put; + + entry = mmsg; + compat_entry = (struct compat_mmsghdr __user *)mmsg; + + while (datagrams < vlen) { + /* + * No need to ask LSM for more than the first datagram. + */ + if (MSG_CMSG_COMPAT & flags) { + err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry, + &msg_sys, flags, datagrams); + if (err < 0) + break; + err = __put_user(err, &compat_entry->msg_len); + ++compat_entry; + } else { + err = __sys_sendmsg(sock, (struct msghdr __user *)entry, + &msg_sys, flags, datagrams); + if (err < 0) + break; + err = put_user(err, &entry->msg_len); + ++entry; + } + + if (err) + break; + ++datagrams; + } + +out_put: + fput_light(sock->file, fput_needed); + + if (err == 0) + return datagrams; + + if (datagrams != 0) { + /* + * We may send less entries than requested (vlen) if the + * sock is non blocking... + */ + if (err != -EAGAIN) { + /* + * ... or if sendmsg returns an error after we + * send some datagrams, where we record the + * error to return on the next call or if the + * app asks about it using getsockopt(SO_ERROR). + */ + sock->sk->sk_err = -err; + } + + return datagrams; + } + + return err; +} + +SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, + unsigned int, vlen, unsigned int, flags) +{ + return __sys_sendmmsg(fd, mmsg, vlen, flags); +} + static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, struct msghdr *msg_sys, unsigned flags, int nosec) { @@ -2214,11 +2324,11 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, #ifdef __ARCH_WANT_SYS_SOCKETCALL /* Argument list sizes for sys_socketcall */ #define AL(x) ((x) * sizeof(unsigned long)) -static const unsigned char nargs[20] = { +static const unsigned char nargs[21] = { AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), - AL(4), AL(5) + AL(4), AL(5), AL(4) }; #undef AL @@ -2238,7 +2348,7 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) int err; unsigned int len; - if (call < 1 || call > SYS_RECVMMSG) + if (call < 1 || call > SYS_SENDMMSG) return -EINVAL; len = nargs[call]; @@ -2313,6 +2423,9 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) case SYS_SENDMSG: err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); break; + case SYS_SENDMMSG: + err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); + break; case SYS_RECVMSG: err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); break; -- cgit v1.2.3-58-ga151 From 2f6fc351e6e8c1b6a95140e733607e32bc3a4322 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 28 Apr 2011 15:31:57 +0530 Subject: ath9k: Fix drain txq failure in flush While draining the txq in flush, the buffers can be added into the tx queue by tx_tasklet which leads to unneccesary chip reset. This issue was originially found with AR9382 and running heavy uplink udp traffic with higher bandwidth and doing frequent bgscan. Cc: stable@kernel.org Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c3dbf2661a3f..efdafd28fab0 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2261,6 +2261,7 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) struct ath_softc *sc = hw->priv; int timeout = 200; /* ms */ int i, j; + bool drain_txq; mutex_lock(&sc->mutex); cancel_delayed_work_sync(&sc->tx_complete_work); @@ -2286,7 +2287,10 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) } ath9k_ps_wakeup(sc); - if (!ath_drain_all_txq(sc, false)) + spin_lock_bh(&sc->sc_pcu_lock); + drain_txq = ath_drain_all_txq(sc, false); + spin_unlock_bh(&sc->sc_pcu_lock); + if (!drain_txq) ath_reset(sc, false); ath9k_ps_restore(sc); ieee80211_wake_queues(hw); -- cgit v1.2.3-58-ga151 From 470ab2a23b453518ac86937572b4531d8925ca55 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 29 Apr 2011 14:48:45 +0530 Subject: mac80211: use wake_queue to restart trasmit netif_tx_start_all_queues is used to allow the upper layer to transmit frames but it does not restart transmission. To restart the trasmission use netif_tx_wake_all_queues. Not doing so, sometimes stalls the transmission and the application has to be restarted to proceed further. This issue was originally found while sending udp traffic in higer bandwidth in open environment without bgscan. Cc: stable@kernel.org Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a41f234bd486..8d752b4d72ce 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -781,7 +781,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); } - netif_tx_start_all_queues(sdata->dev); + netif_tx_wake_all_queues(sdata->dev); } void ieee80211_dynamic_ps_timer(unsigned long data) -- cgit v1.2.3-58-ga151 From 7e4b4eecedb3c6bd5f9fec479ef33ccc6ce72375 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Mon, 2 May 2011 21:38:16 +0100 Subject: libertas: remove tx_timeout handler As described at http://marc.info/?l=linux-netdev&m=130428493104730&w=2 libertas frequently generates spurious tx timeouts, because the tx queue is brought down for extended periods during scanning. The net layer takes a look and incorrectly assumes the queue has been down for several seconds, and generates a tx_timeout. One way to fix this is to bump the trans_start counter while scanning so that the network layer knows that the device is still alive, but I think the tx_timeout handler is implemented wrongly here and not of any real use, so I vote to remove it. As explained at http://marc.info/?l=linux-wireless&m=130430311115755&w=2 the watchdog is primarily meant to deal with lockup on the hardware TX path (detected by the tx queue being stopped for an extended period of time), but this is unlikely to happen with libertas. In this case, the tx queue is stopped only while waiting for lbs_thread to send the queued frame to the driver, and lbs_thread wakes up the queue immediately after, even if the frame could not be sent correctly. So, the only hardware-related possibility that this catches is if hw_host_to_card hangs - this is something I have never seen. And if it were to happen, nothing done by lbs_tx_timeout would actually wake up lbs_thread any quicker than otherwise. Removing this oddly-behaving spuriously-firing tx_timeout handler should fix an occasional kernel crash during resume (http://dev.laptop.org/ticket/10748) Signed-off-by: Daniel Drake Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/main.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index ed57cf863b69..ae02e6b7bc41 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -149,28 +149,6 @@ static int lbs_eth_stop(struct net_device *dev) return 0; } -static void lbs_tx_timeout(struct net_device *dev) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_TX); - - lbs_pr_err("tx watch dog timeout\n"); - - dev->trans_start = jiffies; /* prevent tx timeout */ - - if (priv->currenttxskb) - lbs_send_tx_feedback(priv, 0); - - /* XX: Shouldn't we also call into the hw-specific driver - to kick it somehow? */ - lbs_host_to_card_done(priv); - - /* FIXME: reset the card */ - - lbs_deb_leave(LBS_DEB_TX); -} - void lbs_host_to_card_done(struct lbs_private *priv) { unsigned long flags; @@ -791,7 +769,6 @@ static const struct net_device_ops lbs_netdev_ops = { .ndo_stop = lbs_eth_stop, .ndo_start_xmit = lbs_hard_start_xmit, .ndo_set_mac_address = lbs_set_mac_address, - .ndo_tx_timeout = lbs_tx_timeout, .ndo_set_multicast_list = lbs_set_multicast_list, .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, -- cgit v1.2.3-58-ga151 From cbe8c735f1af88037c3dab570f816e3a77896cc7 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Tue, 3 May 2011 13:14:06 +0530 Subject: ath9k_hw: remove aggregation protection mode when aggregation protection mode is enabled the hardware needs to send RTS/CTS for each HT frame. Currently its disabled so remove the unused call backs. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_mac.c | 10 ---------- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 11 ----------- drivers/net/wireless/ath/ath9k/ath9k.h | 1 - drivers/net/wireless/ath/ath9k/hw-ops.h | 6 ------ drivers/net/wireless/ath/ath9k/hw.h | 2 -- drivers/net/wireless/ath/ath9k/main.c | 3 --- drivers/net/wireless/ath/ath9k/xmit.c | 5 +---- 7 files changed, 1 insertion(+), 37 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index c338efbccf40..7a332f16b79a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -415,15 +415,6 @@ static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds) ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); } -static void ar9002_hw_set11n_burstduration(struct ath_hw *ah, void *ds, - u32 burstDuration) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_ctl2 &= ~AR_BurstDur; - ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); -} - void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, u32 size, u32 flags) { @@ -456,6 +447,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah) ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle; ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; ops->clr11n_aggr = ar9002_hw_clr11n_aggr; - ops->set11n_burstduration = ar9002_hw_set11n_burstduration; ops->set_clrdmask = ar9002_hw_set_clrdmask; } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index c1264d60c499..be6adec33ddb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -484,16 +484,6 @@ static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds) ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr); } -static void ar9003_hw_set11n_burstduration(struct ath_hw *ah, void *ds, - u32 burstDuration) -{ - struct ar9003_txc *ads = (struct ar9003_txc *) ds; - - ads->ctl13 &= ~AR_BurstDur; - ads->ctl13 |= SM(burstDuration, AR_BurstDur); - -} - void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) { struct ar9003_txc *ads = ds; @@ -518,7 +508,6 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle; ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; ops->clr11n_aggr = ar9003_hw_clr11n_aggr; - ops->set11n_burstduration = ar9003_hw_set11n_burstduration; ops->set_clrdmask = ar9003_hw_set_clrdmask; } diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 0312aa091807..1bffd156b155 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -62,7 +62,6 @@ struct ath_node; #define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<clr11n_aggr(ah, ds); } -static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds, - u32 burstDuration) -{ - ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration); -} - static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) { ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 34ed1bd0e855..b2248bba25a2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -628,8 +628,6 @@ struct ath_hw_ops { u32 numDelims); void (*set11n_aggr_last)(struct ath_hw *ah, void *ds); void (*clr11n_aggr)(struct ath_hw *ah, void *ds); - void (*set11n_burstduration)(struct ath_hw *ah, void *ds, - u32 burstDuration); void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val); }; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index efdafd28fab0..3de115df9164 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2039,9 +2039,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BSSID) { ath9k_config_bss(sc, vif); - /* Set aggregation protection mode parameters */ - sc->config.ath_aggr_prot = 0; - ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n", common->curbssid, common->curaid); } diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 55960fa70dc6..947d5b3b6e05 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1663,8 +1663,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) rix = rates[i].idx; series[i].Tries = rates[i].count; - if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) || - (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) { + if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) { series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; flags |= ATH9K_TXDESC_RTSENA; } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { @@ -1733,8 +1732,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) !is_pspoll, ctsrate, 0, series, 4, flags); - if (sc->config.ath_aggr_prot && flags) - ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192); } static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, -- cgit v1.2.3-58-ga151 From 4c468fe559f7910b1c6b10d3d223943fdd1b653c Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 3 May 2011 11:53:07 +0300 Subject: mac80211: set TID of internal mgmt packets to 7 The queue mapping of internal mgmt packets is set to VO. Set the TID value to match the queue mapping. Otherwise drivers that only look at the TID might get confused. Signed-off-by: Arik Nemtsov Signed-off-by: John W. Linville --- net/mac80211/tx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e3e3aa173af0..e1a39ed1ef5e 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2534,8 +2534,9 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) skb_set_network_header(skb, 0); skb_set_transport_header(skb, 0); - /* send all internal mgmt frames on VO */ - skb_set_queue_mapping(skb, 0); + /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */ + skb_set_queue_mapping(skb, IEEE80211_AC_VO); + skb->priority = 7; /* * The other path calling ieee80211_xmit is from the tasklet, -- cgit v1.2.3-58-ga151 From 1ddc286731134ad52a74b6956d9bc2a4369219a8 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 3 May 2011 17:03:59 +0530 Subject: mac80211: Postpond ps timer if tx is stopped by others Whenever the driver's queue depth reaches the max, the queues are stopped by the driver till the driver can accept the frames. At the mean time dynamic_ps_timer can be expired due to not receiving packet from upper layer which could restart the transmission at the end of ps work. Due to the mismatch with driver state, mac80211 is unneccesarity buffering all the frames till the driver wakes up the queue. Check whether there is no transmit or the tx queues were stopped by some reasons. If any of the queue was stopped, the postpond ps timer and do not restart netif_tx. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 8d752b4d72ce..4f6b2675e41d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -750,6 +750,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) dynamic_ps_enable_work); struct ieee80211_sub_if_data *sdata = local->ps_sdata; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + unsigned long flags; + int q; /* can only happen when PS was just disabled anyway */ if (!sdata) @@ -758,6 +760,24 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) if (local->hw.conf.flags & IEEE80211_CONF_PS) return; + /* + * transmission can be stopped by others which leads to + * dynamic_ps_timer expiry. Postpond the ps timer if it + * is not the actual idle state. + */ + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + for (q = 0; q < local->hw.queues; q++) { + if (local->queue_stop_reasons[q]) { + spin_unlock_irqrestore(&local->queue_stop_reason_lock, + flags); + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies( + local->hw.conf.dynamic_ps_timeout)); + return; + } + } + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { netif_tx_stop_all_queues(sdata->dev); -- cgit v1.2.3-58-ga151 From e52dadb341c9c5ac25d6abd9216dd62752784f03 Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Tue, 3 May 2011 09:47:45 -0500 Subject: rtlwifi: rtl8192se: Merge def.h Introduce routine def.h for rtl8192se. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192se/def.h | 598 +++++++++++++++++++++++++++ 1 file changed, 598 insertions(+) create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/def.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h new file mode 100644 index 000000000000..69828f2b3fab --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h @@ -0,0 +1,598 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __REALTEK_92S_DEF_H__ +#define __REALTEK_92S_DEF_H__ + +#define RX_MPDU_QUEUE 0 +#define RX_CMD_QUEUE 1 +#define RX_MAX_QUEUE 2 + +#define DESC92S_RATE1M 0x00 +#define DESC92S_RATE2M 0x01 +#define DESC92S_RATE5_5M 0x02 +#define DESC92S_RATE11M 0x03 +#define DESC92S_RATE6M 0x04 +#define DESC92S_RATE9M 0x05 +#define DESC92S_RATE12M 0x06 +#define DESC92S_RATE18M 0x07 +#define DESC92S_RATE24M 0x08 +#define DESC92S_RATE36M 0x09 +#define DESC92S_RATE48M 0x0a +#define DESC92S_RATE54M 0x0b +#define DESC92S_RATEMCS0 0x0c +#define DESC92S_RATEMCS1 0x0d +#define DESC92S_RATEMCS2 0x0e +#define DESC92S_RATEMCS3 0x0f +#define DESC92S_RATEMCS4 0x10 +#define DESC92S_RATEMCS5 0x11 +#define DESC92S_RATEMCS6 0x12 +#define DESC92S_RATEMCS7 0x13 +#define DESC92S_RATEMCS8 0x14 +#define DESC92S_RATEMCS9 0x15 +#define DESC92S_RATEMCS10 0x16 +#define DESC92S_RATEMCS11 0x17 +#define DESC92S_RATEMCS12 0x18 +#define DESC92S_RATEMCS13 0x19 +#define DESC92S_RATEMCS14 0x1a +#define DESC92S_RATEMCS15 0x1b +#define DESC92S_RATEMCS15_SG 0x1c +#define DESC92S_RATEMCS32 0x20 + +#define SHORT_SLOT_TIME 9 +#define NON_SHORT_SLOT_TIME 20 + +/* Rx smooth factor */ +#define RX_SMOOTH_FACTOR 20 + +/* Queue Select Value in TxDesc */ +#define QSLT_BK 0x2 +#define QSLT_BE 0x0 +#define QSLT_VI 0x5 +#define QSLT_VO 0x6 +#define QSLT_BEACON 0x10 +#define QSLT_HIGH 0x11 +#define QSLT_MGNT 0x12 +#define QSLT_CMD 0x13 + +#define PHY_RSSI_SLID_WIN_MAX 100 +#define PHY_LINKQUALITY_SLID_WIN_MAX 20 +#define PHY_BEACON_RSSI_SLID_WIN_MAX 10 + +/* Tx Desc */ +#define TX_DESC_SIZE_RTL8192S (16 * 4) +#define TX_CMDDESC_SIZE_RTL8192S (16 * 4) + +/* Define a macro that takes a le32 word, converts it to host ordering, + * right shifts by a specified count, creates a mask of the specified + * bit count, and extracts that number of bits. + */ + +#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask) \ + ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \ + BIT_LEN_MASK_32(__mask)) + +/* Define a macro that clears a bit field in an le32 word and + * sets the specified value into that bit field. The resulting + * value remains in le32 ordering; however, it is properly converted + * to host ordering for the clear and set operations before conversion + * back to le32. + */ + +#define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val) \ + (*(__le32 *)(__pdesc) = \ + (cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) & \ + (~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) | \ + (((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift))))); + +/* macros to read/write various fields in RX or TX descriptors */ + +/* Dword 0 */ +#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val) +#define SET_TX_DESC_OFFSET(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val) +#define SET_TX_DESC_TYPE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 24, 2, __val) +#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) +#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) +#define SET_TX_DESC_LINIP(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) +#define SET_TX_DESC_AMSDU(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) +#define SET_TX_DESC_GREEN_FIELD(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) +#define SET_TX_DESC_OWN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) + +#define GET_TX_DESC_OWN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 31, 1) + +/* Dword 1 */ +#define SET_TX_DESC_MACID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 0, 5, __val) +#define SET_TX_DESC_MORE_DATA(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 5, 1, __val) +#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 6, 1, __val) +#define SET_TX_DESC_PIFS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 7, 1, __val) +#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 8, 5, __val) +#define SET_TX_DESC_ACK_POLICY(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 13, 2, __val) +#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 15, 1, __val) +#define SET_TX_DESC_NON_QOS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 16, 1, __val) +#define SET_TX_DESC_KEY_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 17, 2, __val) +#define SET_TX_DESC_OUI(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 19, 1, __val) +#define SET_TX_DESC_PKT_TYPE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 20, 1, __val) +#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 21, 1, __val) +#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 22, 2, __val) +#define SET_TX_DESC_WDS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 24, 1, __val) +#define SET_TX_DESC_HTC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 25, 1, __val) +#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 26, 5, __val) +#define SET_TX_DESC_HWPC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 27, 1, __val) + +/* Dword 2 */ +#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 0, 6, __val) +#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 6, 1, __val) +#define SET_TX_DESC_TSFL(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 7, 5, __val) +#define SET_TX_DESC_RTS_RETRY_COUNT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 12, 6, __val) +#define SET_TX_DESC_DATA_RETRY_COUNT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 18, 6, __val) +#define SET_TX_DESC_RSVD_MACID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(((__pdesc) + 8), 24, 5, __val) +#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 29, 1, __val) +#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 30, 1, __val) +#define SET_TX_DESC_OWN_MAC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 31, 1, __val) + +/* Dword 3 */ +#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 0, 8, __val) +#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 8, 8, __val) +#define SET_TX_DESC_SEQ(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 16, 12, __val) +#define SET_TX_DESC_FRAG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 28, 4, __val) + +/* Dword 4 */ +#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 0, 6, __val) +#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 6, 1, __val) +#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 7, 4, __val) +#define SET_TX_DESC_CTS_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 11, 1, __val) +#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 12, 1, __val) +#define SET_TX_DESC_RA_BRSR_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 13, 3, __val) +#define SET_TX_DESC_TXHT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 16, 1, __val) +#define SET_TX_DESC_TX_SHORT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 17, 1, __val) +#define SET_TX_DESC_TX_BANDWIDTH(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 18, 1, __val) +#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 19, 2, __val) +#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 21, 2, __val) +#define SET_TX_DESC_TX_REVERSE_DIRECTION(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 23, 1, __val) +#define SET_TX_DESC_RTS_HT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 24, 1, __val) +#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 25, 1, __val) +#define SET_TX_DESC_RTS_BANDWIDTH(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 26, 1, __val) +#define SET_TX_DESC_RTS_SUB_CARRIER(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 27, 2, __val) +#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 29, 2, __val) +#define SET_TX_DESC_USER_RATE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 31, 1, __val) + +/* Dword 5 */ +#define SET_TX_DESC_PACKET_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 20, 0, 9, __val) +#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 20, 9, 6, __val) +#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 20, 15, 1, __val) +#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 20, 16, 5, __val) +#define SET_TX_DESC_TX_AGC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 20, 21, 11, __val) + +/* Dword 6 */ +#define SET_TX_DESC_IP_CHECK_SUM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 24, 0, 16, __val) +#define SET_TX_DESC_TCP_CHECK_SUM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 24, 16, 16, __val) + +/* Dword 7 */ +#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 28, 0, 16, __val) +#define SET_TX_DESC_IP_HEADER_OFFSET(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 28, 16, 8, __val) +#define SET_TX_DESC_TCP_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 28, 31, 1, __val) + +/* Dword 8 */ +#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 32, 0, 32, __val) +#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 32, 0, 32) + +/* Dword 9 */ +#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 36, 0, 32, __val) + +/* Because the PCI Tx descriptors are chaied at the + * initialization and all the NextDescAddresses in + * these descriptors cannot not be cleared (,or + * driver/HW cannot find the next descriptor), the + * offset 36 (NextDescAddresses) is reserved when + * the desc is cleared. */ +#define TX_DESC_NEXT_DESC_OFFSET 36 +#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ +do { \ + if (_size > TX_DESC_NEXT_DESC_OFFSET) \ + memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ + else \ + memset(__pdesc, 0, _size); \ +} while (0); + +/* Rx Desc */ +#define RX_STATUS_DESC_SIZE 24 +#define RX_DRV_INFO_SIZE_UNIT 8 + +/* DWORD 0 */ +#define SET_RX_STATUS_DESC_PKT_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val) +#define SET_RX_STATUS_DESC_CRC32(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 14, 1, __val) +#define SET_RX_STATUS_DESC_ICV(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 15, 1, __val) +#define SET_RX_STATUS_DESC_DRVINFO_SIZE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 16, 4, __val) +#define SET_RX_STATUS_DESC_SECURITY(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 20, 3, __val) +#define SET_RX_STATUS_DESC_QOS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 23, 1, __val) +#define SET_RX_STATUS_DESC_SHIFT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 24, 2, __val) +#define SET_RX_STATUS_DESC_PHY_STATUS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) +#define SET_RX_STATUS_DESC_SWDEC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) +#define SET_RX_STATUS_DESC_LAST_SEG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) +#define SET_RX_STATUS_DESC_FIRST_SEG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) +#define SET_RX_STATUS_DESC_EOR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) +#define SET_RX_STATUS_DESC_OWN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) + +#define GET_RX_STATUS_DESC_PKT_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 0, 14) +#define GET_RX_STATUS_DESC_CRC32(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 14, 1) +#define GET_RX_STATUS_DESC_ICV(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 15, 1) +#define GET_RX_STATUS_DESC_DRVINFO_SIZE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 16, 4) +#define GET_RX_STATUS_DESC_SECURITY(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 20, 3) +#define GET_RX_STATUS_DESC_QOS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 23, 1) +#define GET_RX_STATUS_DESC_SHIFT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 24, 2) +#define GET_RX_STATUS_DESC_PHY_STATUS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 26, 1) +#define GET_RX_STATUS_DESC_SWDEC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 27, 1) +#define GET_RX_STATUS_DESC_LAST_SEG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 28, 1) +#define GET_RX_STATUS_DESC_FIRST_SEG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 29, 1) +#define GET_RX_STATUS_DESC_EOR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 30, 1) +#define GET_RX_STATUS_DESC_OWN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 31, 1) + +/* DWORD 1 */ +#define SET_RX_STATUS_DESC_MACID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 0, 5, __val) +#define SET_RX_STATUS_DESC_TID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 5, 4, __val) +#define SET_RX_STATUS_DESC_PAGGR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 14, 1, __val) +#define SET_RX_STATUS_DESC_FAGGR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 15, 1, __val) +#define SET_RX_STATUS_DESC_A1_FIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 16, 4, __val) +#define SET_RX_STATUS_DESC_A2_FIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 20, 4, __val) +#define SET_RX_STATUS_DESC_PAM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 24, 1, __val) +#define SET_RX_STATUS_DESC_PWR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 25, 1, __val) +#define SET_RX_STATUS_DESC_MOREDATA(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 26, 1, __val) +#define SET_RX_STATUS_DESC_MOREFRAG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 27, 1, __val) +#define SET_RX_STATUS_DESC_TYPE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 28, 2, __val) +#define SET_RX_STATUS_DESC_MC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 30, 1, __val) +#define SET_RX_STATUS_DESC_BC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 31, 1, __val) + +#define GET_RX_STATUS_DEC_MACID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 0, 5) +#define GET_RX_STATUS_DESC_TID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 5, 4) +#define GET_RX_STATUS_DESC_PAGGR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 14, 1) +#define GET_RX_STATUS_DESC_FAGGR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 15, 1) +#define GET_RX_STATUS_DESC_A1_FIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 16, 4) +#define GET_RX_STATUS_DESC_A2_FIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 20, 4) +#define GET_RX_STATUS_DESC_PAM(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 24, 1) +#define GET_RX_STATUS_DESC_PWR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 25, 1) +#define GET_RX_STATUS_DESC_MORE_DATA(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 26, 1) +#define GET_RX_STATUS_DESC_MORE_FRAG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 27, 1) +#define GET_RX_STATUS_DESC_TYPE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 28, 2) +#define GET_RX_STATUS_DESC_MC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 30, 1) +#define GET_RX_STATUS_DESC_BC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 31, 1) + +/* DWORD 2 */ +#define SET_RX_STATUS_DESC_SEQ(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 0, 12, __val) +#define SET_RX_STATUS_DESC_FRAG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 12, 4, __val) +#define SET_RX_STATUS_DESC_NEXT_PKTLEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 16, 8, __val) +#define SET_RX_STATUS_DESC_NEXT_IND(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 30, 1, __val) + +#define GET_RX_STATUS_DESC_SEQ(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 8, 0, 12) +#define GET_RX_STATUS_DESC_FRAG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 8, 12, 4) +#define GET_RX_STATUS_DESC_NEXT_PKTLEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 8, 16, 8) +#define GET_RX_STATUS_DESC_NEXT_IND(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 8, 30, 1) + +/* DWORD 3 */ +#define SET_RX_STATUS_DESC_RX_MCS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 0, 6, __val) +#define SET_RX_STATUS_DESC_RX_HT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 6, 1, __val) +#define SET_RX_STATUS_DESC_AMSDU(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 7, 1, __val) +#define SET_RX_STATUS_DESC_SPLCP(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 8, 1, __val) +#define SET_RX_STATUS_DESC_BW(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 9, 1, __val) +#define SET_RX_STATUS_DESC_HTC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 10, 1, __val) +#define SET_RX_STATUS_DESC_TCP_CHK_RPT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 11, 1, __val) +#define SET_RX_STATUS_DESC_IP_CHK_RPT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 12, 1, __val) +#define SET_RX_STATUS_DESC_TCP_CHK_VALID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 13, 1, __val) +#define SET_RX_STATUS_DESC_HWPC_ERR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 14, 1, __val) +#define SET_RX_STATUS_DESC_HWPC_IND(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 15, 1, __val) +#define SET_RX_STATUS_DESC_IV0(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 16, 16, __val) + +#define GET_RX_STATUS_DESC_RX_MCS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 0, 6) +#define GET_RX_STATUS_DESC_RX_HT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 6, 1) +#define GET_RX_STATUS_DESC_AMSDU(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 7, 1) +#define GET_RX_STATUS_DESC_SPLCP(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 8, 1) +#define GET_RX_STATUS_DESC_BW(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 9, 1) +#define GET_RX_STATUS_DESC_HTC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 10, 1) +#define GET_RX_STATUS_DESC_TCP_CHK_RPT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 11, 1) +#define GET_RX_STATUS_DESC_IP_CHK_RPT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 12, 1) +#define GET_RX_STATUS_DESC_TCP_CHK_VALID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 13, 1) +#define GET_RX_STATUS_DESC_HWPC_ERR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 14, 1) +#define GET_RX_STATUS_DESC_HWPC_IND(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 15, 1) +#define GET_RX_STATUS_DESC_IV0(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 16, 16) + +/* DWORD 4 */ +#define SET_RX_STATUS_DESC_IV1(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 0, 32, __val) +#define GET_RX_STATUS_DESC_IV1(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 16, 0, 32) + +/* DWORD 5 */ +#define SET_RX_STATUS_DESC_TSFL(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 20, 0, 32, __val) +#define GET_RX_STATUS_DESC_TSFL(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 20, 0, 32) + +/* DWORD 6 */ +#define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val) + +#define RX_HAL_IS_CCK_RATE(_pdesc)\ + (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE1M || \ + GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE2M || \ + GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE5_5M ||\ + GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE11M) + +enum rf_optype { + RF_OP_BY_SW_3WIRE = 0, + RF_OP_BY_FW, + RF_OP_MAX +}; + +enum ic_inferiority { + IC_INFERIORITY_A = 0, + IC_INFERIORITY_B = 1, +}; + +enum fwcmd_iotype { + /* For DIG DM */ + FW_CMD_DIG_ENABLE = 0, + FW_CMD_DIG_DISABLE = 1, + FW_CMD_DIG_HALT = 2, + FW_CMD_DIG_RESUME = 3, + /* For High Power DM */ + FW_CMD_HIGH_PWR_ENABLE = 4, + FW_CMD_HIGH_PWR_DISABLE = 5, + /* For Rate adaptive DM */ + FW_CMD_RA_RESET = 6, + FW_CMD_RA_ACTIVE = 7, + FW_CMD_RA_REFRESH_N = 8, + FW_CMD_RA_REFRESH_BG = 9, + FW_CMD_RA_INIT = 10, + /* For FW supported IQK */ + FW_CMD_IQK_INIT = 11, + /* Tx power tracking switch, + * MP driver only */ + FW_CMD_TXPWR_TRACK_ENABLE = 12, + /* Tx power tracking switch, + * MP driver only */ + FW_CMD_TXPWR_TRACK_DISABLE = 13, + /* Tx power tracking with thermal + * indication, for Normal driver */ + FW_CMD_TXPWR_TRACK_THERMAL = 14, + FW_CMD_PAUSE_DM_BY_SCAN = 15, + FW_CMD_RESUME_DM_BY_SCAN = 16, + FW_CMD_RA_REFRESH_N_COMB = 17, + FW_CMD_RA_REFRESH_BG_COMB = 18, + FW_CMD_ANTENNA_SW_ENABLE = 19, + FW_CMD_ANTENNA_SW_DISABLE = 20, + /* Tx Status report for CCX from FW */ + FW_CMD_TX_FEEDBACK_CCX_ENABLE = 21, + /* Indifate firmware that driver + * enters LPS, For PS-Poll issue */ + FW_CMD_LPS_ENTER = 22, + /* Indicate firmware that driver + * leave LPS*/ + FW_CMD_LPS_LEAVE = 23, + /* Set DIG mode to signal strength */ + FW_CMD_DIG_MODE_SS = 24, + /* Set DIG mode to false alarm. */ + FW_CMD_DIG_MODE_FA = 25, + FW_CMD_ADD_A2_ENTRY = 26, + FW_CMD_CTRL_DM_BY_DRIVER = 27, + FW_CMD_CTRL_DM_BY_DRIVER_NEW = 28, + FW_CMD_PAPE_CONTROL = 29, + FW_CMD_IQK_ENABLE = 30, +}; + +/* + * Driver info contain PHY status + * and other variabel size info + * PHY Status content as below + */ +struct rx_fwinfo { + /* DWORD 0 */ + u8 gain_trsw[4]; + /* DWORD 1 */ + u8 pwdb_all; + u8 cfosho[4]; + /* DWORD 2 */ + u8 cfotail[4]; + /* DWORD 3 */ + s8 rxevm[2]; + s8 rxsnr[4]; + /* DWORD 4 */ + u8 pdsnr[2]; + /* DWORD 5 */ + u8 csi_current[2]; + u8 csi_target[2]; + /* DWORD 6 */ + u8 sigevm; + u8 max_ex_pwr; + u8 ex_intf_flag:1; + u8 sgi_en:1; + u8 rxsc:2; + u8 reserve:4; +}; + +struct phy_sts_cck_8192s_t { + u8 adc_pwdb_x[4]; + u8 sq_rpt; + u8 cck_agc_rpt; +}; + +#endif + -- cgit v1.2.3-58-ga151 From 9fe255ee3c0dd81c134b354e4b328c51f863ac40 Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Tue, 3 May 2011 09:47:55 -0500 Subject: rtlwifi: rtl8192se: Merge dynamic management routines Merge routines dm.c and dm.h for RTL8192SE. Signed-off-by: Larry Finger Signed-off-by: Chaoming_Li Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192se/dm.c | 733 ++++++++++++++++++++++++++++ drivers/net/wireless/rtlwifi/rtl8192se/dm.h | 164 +++++++ 2 files changed, 897 insertions(+) create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/dm.c create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/dm.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c new file mode 100644 index 000000000000..da86db86fa4a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c @@ -0,0 +1,733 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" + +struct dig_t digtable; +static const u32 edca_setting_dl[PEER_MAX] = { + 0xa44f, /* 0 UNKNOWN */ + 0x5ea44f, /* 1 REALTEK_90 */ + 0x5ea44f, /* 2 REALTEK_92SE */ + 0xa630, /* 3 BROAD */ + 0xa44f, /* 4 RAL */ + 0xa630, /* 5 ATH */ + 0xa630, /* 6 CISCO */ + 0xa42b, /* 7 MARV */ +}; + +static const u32 edca_setting_dl_gmode[PEER_MAX] = { + 0x4322, /* 0 UNKNOWN */ + 0xa44f, /* 1 REALTEK_90 */ + 0x5ea44f, /* 2 REALTEK_92SE */ + 0xa42b, /* 3 BROAD */ + 0x5e4322, /* 4 RAL */ + 0x4322, /* 5 ATH */ + 0xa430, /* 6 CISCO */ + 0x5ea44f, /* 7 MARV */ +}; + +static const u32 edca_setting_ul[PEER_MAX] = { + 0x5e4322, /* 0 UNKNOWN */ + 0xa44f, /* 1 REALTEK_90 */ + 0x5ea44f, /* 2 REALTEK_92SE */ + 0x5ea322, /* 3 BROAD */ + 0x5ea422, /* 4 RAL */ + 0x5ea322, /* 5 ATH */ + 0x3ea44f, /* 6 CISCO */ + 0x5ea44f, /* 7 MARV */ +}; + +static void _rtl92s_dm_check_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + static u64 last_txok_cnt; + static u64 last_rxok_cnt; + u64 cur_txok_cnt = 0; + u64 cur_rxok_cnt = 0; + + u32 edca_be_ul = edca_setting_ul[mac->vendor]; + u32 edca_be_dl = edca_setting_dl[mac->vendor]; + u32 edca_gmode = edca_setting_dl_gmode[mac->vendor]; + + if (mac->link_state != MAC80211_LINKED) { + rtlpriv->dm.current_turbo_edca = false; + goto dm_checkedcaturbo_exit; + } + + if ((!rtlpriv->dm.is_any_nonbepkts) && + (!rtlpriv->dm.disable_framebursting)) { + cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; + cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; + + if (rtlpriv->phy.rf_type == RF_1T2R) { + if (cur_txok_cnt > 4 * cur_rxok_cnt) { + /* Uplink TP is present. */ + if (rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + rtl_write_dword(rtlpriv, EDCAPARA_BE, + edca_be_ul); + rtlpriv->dm.is_cur_rdlstate = false; + } + } else {/* Balance TP is present. */ + if (!rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + if (mac->mode == WIRELESS_MODE_G || + mac->mode == WIRELESS_MODE_B) + rtl_write_dword(rtlpriv, + EDCAPARA_BE, + edca_gmode); + else + rtl_write_dword(rtlpriv, + EDCAPARA_BE, + edca_be_dl); + rtlpriv->dm.is_cur_rdlstate = true; + } + } + rtlpriv->dm.current_turbo_edca = true; + } else { + if (cur_rxok_cnt > 4 * cur_txok_cnt) { + if (!rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + if (mac->mode == WIRELESS_MODE_G || + mac->mode == WIRELESS_MODE_B) + rtl_write_dword(rtlpriv, + EDCAPARA_BE, + edca_gmode); + else + rtl_write_dword(rtlpriv, + EDCAPARA_BE, + edca_be_dl); + rtlpriv->dm.is_cur_rdlstate = true; + } + } else { + if (rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + rtl_write_dword(rtlpriv, EDCAPARA_BE, + edca_be_ul); + rtlpriv->dm.is_cur_rdlstate = false; + } + } + rtlpriv->dm.current_turbo_edca = true; + } + } else { + if (rtlpriv->dm.current_turbo_edca) { + u8 tmp = AC0_BE; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, + (u8 *)(&tmp)); + rtlpriv->dm.current_turbo_edca = false; + } + } + +dm_checkedcaturbo_exit: + rtlpriv->dm.is_any_nonbepkts = false; + last_txok_cnt = rtlpriv->stats.txbytesunicast; + last_rxok_cnt = rtlpriv->stats.rxbytesunicast; +} + +static void _rtl92s_dm_txpowertracking_callback_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 thermalvalue = 0; + + rtlpriv->dm.txpower_trackinginit = true; + + thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x " + "eeprom_thermalmeter 0x%x\n", thermalvalue, + rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter)); + + if (thermalvalue) { + rtlpriv->dm.thermalvalue = thermalvalue; + rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL); + } + + rtlpriv->dm.txpowercount = 0; +} + +static void _rtl92s_dm_check_txpowertracking_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + static u8 tm_trigger; + u8 tx_power_checkcnt = 5; + + /* 2T2R TP issue */ + if (rtlphy->rf_type == RF_2T2R) + return; + + if (!rtlpriv->dm.txpower_tracking) + return; + + if (rtlpriv->dm.txpowercount <= tx_power_checkcnt) { + rtlpriv->dm.txpowercount++; + return; + } + + if (!tm_trigger) { + rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, + RFREG_OFFSET_MASK, 0x60); + tm_trigger = 1; + } else { + _rtl92s_dm_txpowertracking_callback_thermalmeter(hw); + tm_trigger = 0; + } +} + +static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rate_adaptive *ra = &(rtlpriv->ra); + + u32 low_rssi_thresh = 0; + u32 middle_rssi_thresh = 0; + u32 high_rssi_thresh = 0; + u8 rssi_level; + struct ieee80211_sta *sta = NULL; + + if (is_hal_stop(rtlhal)) + return; + + if (!rtlpriv->dm.useramask) + return; + + if (!rtlpriv->dm.inform_fw_driverctrldm) { + rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER); + rtlpriv->dm.inform_fw_driverctrldm = true; + } + + rcu_read_lock(); + if (mac->opmode == NL80211_IFTYPE_STATION) + sta = get_sta(hw, mac->vif, mac->bssid); + if ((mac->link_state == MAC80211_LINKED) && + (mac->opmode == NL80211_IFTYPE_STATION)) { + switch (ra->pre_ratr_state) { + case DM_RATR_STA_HIGH: + high_rssi_thresh = 40; + middle_rssi_thresh = 30; + low_rssi_thresh = 20; + break; + case DM_RATR_STA_MIDDLE: + high_rssi_thresh = 44; + middle_rssi_thresh = 30; + low_rssi_thresh = 20; + break; + case DM_RATR_STA_LOW: + high_rssi_thresh = 44; + middle_rssi_thresh = 34; + low_rssi_thresh = 20; + break; + case DM_RATR_STA_ULTRALOW: + high_rssi_thresh = 44; + middle_rssi_thresh = 34; + low_rssi_thresh = 24; + break; + default: + high_rssi_thresh = 44; + middle_rssi_thresh = 34; + low_rssi_thresh = 24; + break; + } + + if (rtlpriv->dm.undecorated_smoothed_pwdb > + (long)high_rssi_thresh) { + ra->ratr_state = DM_RATR_STA_HIGH; + rssi_level = 1; + } else if (rtlpriv->dm.undecorated_smoothed_pwdb > + (long)middle_rssi_thresh) { + ra->ratr_state = DM_RATR_STA_LOW; + rssi_level = 3; + } else if (rtlpriv->dm.undecorated_smoothed_pwdb > + (long)low_rssi_thresh) { + ra->ratr_state = DM_RATR_STA_LOW; + rssi_level = 5; + } else { + ra->ratr_state = DM_RATR_STA_ULTRALOW; + rssi_level = 6; + } + + if (ra->pre_ratr_state != ra->ratr_state) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, ("RSSI = %ld " + "RSSI_LEVEL = %d PreState = %d, CurState = %d\n", + rtlpriv->dm.undecorated_smoothed_pwdb, + ra->ratr_state, + ra->pre_ratr_state, ra->ratr_state)); + + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, + ra->ratr_state); + ra->pre_ratr_state = ra->ratr_state; + } + } + rcu_read_unlock(); +} + +static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + bool current_mrc; + bool enable_mrc = true; + long tmpentry_maxpwdb = 0; + u8 rssi_a = 0; + u8 rssi_b = 0; + + if (is_hal_stop(rtlhal)) + return; + + if ((rtlphy->rf_type == RF_1T1R) || (rtlphy->rf_type == RF_2T2R)) + return; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(¤t_mrc)); + + if (mac->link_state >= MAC80211_LINKED) { + if (rtlpriv->dm.undecorated_smoothed_pwdb > tmpentry_maxpwdb) { + rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A]; + rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B]; + } + } + + /* MRC settings would NOT affect TP on Wireless B mode. */ + if (mac->mode != WIRELESS_MODE_B) { + if ((rssi_a == 0) && (rssi_b == 0)) { + enable_mrc = true; + } else if (rssi_b > 30) { + /* Turn on B-Path */ + enable_mrc = true; + } else if (rssi_b < 5) { + /* Turn off B-path */ + enable_mrc = false; + /* Take care of RSSI differentiation. */ + } else if (rssi_a > 15 && (rssi_a >= rssi_b)) { + if ((rssi_a - rssi_b) > 15) + /* Turn off B-path */ + enable_mrc = false; + else if ((rssi_a - rssi_b) < 10) + /* Turn on B-Path */ + enable_mrc = true; + else + enable_mrc = current_mrc; + } else { + /* Turn on B-Path */ + enable_mrc = true; + } + } + + /* Update MRC settings if needed. */ + if (enable_mrc != current_mrc) + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC, + (u8 *)&enable_mrc); + +} + +void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.current_turbo_edca = false; + rtlpriv->dm.is_any_nonbepkts = false; + rtlpriv->dm.is_cur_rdlstate = false; +} + +static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rate_adaptive *ra = &(rtlpriv->ra); + + ra->ratr_state = DM_RATR_STA_MAX; + ra->pre_ratr_state = DM_RATR_STA_MAX; + + if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) + rtlpriv->dm.useramask = true; + else + rtlpriv->dm.useramask = false; + + rtlpriv->dm.useramask = false; + rtlpriv->dm.inform_fw_driverctrldm = false; +} + +static void _rtl92s_dm_init_txpowertracking_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.txpower_tracking = true; + rtlpriv->dm.txpowercount = 0; + rtlpriv->dm.txpower_trackinginit = false; +} + +static void _rtl92s_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); + u32 ret_value; + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); + falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); + falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); + falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); + falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); + + falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail; + + /* read CCK false alarm */ + ret_value = rtl_get_bbreg(hw, 0xc64, MASKDWORD); + falsealm_cnt->cnt_cck_fail = (ret_value & 0xffff); + falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail + + falsealm_cnt->cnt_cck_fail; +} + +static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); + + if (falsealm_cnt->cnt_all > digtable.fa_highthresh) { + if ((digtable.backoff_val - 6) < + digtable.backoffval_range_min) + digtable.backoff_val = digtable.backoffval_range_min; + else + digtable.backoff_val -= 6; + } else if (falsealm_cnt->cnt_all < digtable.fa_lowthresh) { + if ((digtable.backoff_val + 6) > + digtable.backoffval_range_max) + digtable.backoff_val = + digtable.backoffval_range_max; + else + digtable.backoff_val += 6; + } +} + +static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); + static u8 initialized, force_write; + u8 initial_gain = 0; + + if ((digtable.pre_sta_connectstate == digtable.cur_sta_connectstate) || + (digtable.cur_sta_connectstate == DIG_STA_BEFORE_CONNECT)) { + if (digtable.cur_sta_connectstate == DIG_STA_BEFORE_CONNECT) { + if (rtlpriv->psc.rfpwr_state != ERFON) + return; + + if (digtable.backoff_enable_flag == true) + rtl92s_backoff_enable_flag(hw); + else + digtable.backoff_val = DM_DIG_BACKOFF; + + if ((digtable.rssi_val + 10 - digtable.backoff_val) > + digtable.rx_gain_range_max) + digtable.cur_igvalue = + digtable.rx_gain_range_max; + else if ((digtable.rssi_val + 10 - digtable.backoff_val) + < digtable.rx_gain_range_min) + digtable.cur_igvalue = + digtable.rx_gain_range_min; + else + digtable.cur_igvalue = digtable.rssi_val + 10 - + digtable.backoff_val; + + if (falsealm_cnt->cnt_all > 10000) + digtable.cur_igvalue = + (digtable.cur_igvalue > 0x33) ? + digtable.cur_igvalue : 0x33; + + if (falsealm_cnt->cnt_all > 16000) + digtable.cur_igvalue = + digtable.rx_gain_range_max; + /* connected -> connected or disconnected -> disconnected */ + } else { + /* Firmware control DIG, do nothing in driver dm */ + return; + } + /* disconnected -> connected or connected -> + * disconnected or beforeconnect->(dis)connected */ + } else { + /* Enable FW DIG */ + digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; + rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE); + + digtable.backoff_val = DM_DIG_BACKOFF; + digtable.cur_igvalue = rtlpriv->phy.default_initialgain[0]; + digtable.pre_igvalue = 0; + return; + } + + /* Forced writing to prevent from fw-dig overwriting. */ + if (digtable.pre_igvalue != rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, + MASKBYTE0)) + force_write = 1; + + if ((digtable.pre_igvalue != digtable.cur_igvalue) || + !initialized || force_write) { + /* Disable FW DIG */ + rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_DISABLE); + + initial_gain = (u8)digtable.cur_igvalue; + + /* Set initial gain. */ + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, initial_gain); + rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, initial_gain); + digtable.pre_igvalue = digtable.cur_igvalue; + initialized = 1; + force_write = 0; + } +} + +static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->mac80211.act_scanning) + return; + + /* Decide the current status and if modify initial gain or not */ + if (rtlpriv->mac80211.link_state >= MAC80211_LINKED || + rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) + digtable.cur_sta_connectstate = DIG_STA_CONNECT; + else + digtable.cur_sta_connectstate = DIG_STA_DISCONNECT; + + digtable.rssi_val = rtlpriv->dm.undecorated_smoothed_pwdb; + + /* Change dig mode to rssi */ + if (digtable.cur_sta_connectstate != DIG_STA_DISCONNECT) { + if (digtable.dig_twoport_algorithm == + DIG_TWO_PORT_ALGO_FALSE_ALARM) { + digtable.dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; + rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS); + } + } + + _rtl92s_dm_false_alarm_counter_statistics(hw); + _rtl92s_dm_initial_gain_sta_beforeconnect(hw); + + digtable.pre_sta_connectstate = digtable.cur_sta_connectstate; +} + +static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + /* 2T2R TP issue */ + if (rtlphy->rf_type == RF_2T2R) + return; + + if (!rtlpriv->dm.dm_initialgain_enable) + return; + + if (digtable.dig_enable_flag == false) + return; + + _rtl92s_dm_ctrl_initgain_bytwoport(hw); +} + +static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undecorated_smoothed_pwdb; + long txpwr_threshold_lv1, txpwr_threshold_lv2; + + /* 2T2R TP issue */ + if (rtlphy->rf_type == RF_2T2R) + return; + + if (!rtlpriv->dm.dynamic_txpower_enable || + rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; + return; + } + + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + ("Not connected to any\n")); + + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; + + rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL; + return; + } + + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + undecorated_smoothed_pwdb = + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("AP Client PWDB = 0x%lx\n", + undecorated_smoothed_pwdb)); + } else { + undecorated_smoothed_pwdb = + rtlpriv->dm.undecorated_smoothed_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("STA Default Port PWDB = 0x%lx\n", + undecorated_smoothed_pwdb)); + } + } else { + undecorated_smoothed_pwdb = + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("AP Ext Port PWDB = 0x%lx\n", + undecorated_smoothed_pwdb)); + } + + txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2; + txpwr_threshold_lv1 = TX_POWER_NEAR_FIELD_THRESH_LVL1; + + if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1) + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; + else if (undecorated_smoothed_pwdb >= txpwr_threshold_lv2) + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2; + else if ((undecorated_smoothed_pwdb < (txpwr_threshold_lv2 - 3)) && + (undecorated_smoothed_pwdb >= txpwr_threshold_lv1)) + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1; + else if (undecorated_smoothed_pwdb < (txpwr_threshold_lv1 - 3)) + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; + + if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) + rtl92s_phy_set_txpower(hw, rtlphy->current_channel); + + rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; +} + +static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* Disable DIG scheme now.*/ + digtable.dig_enable_flag = true; + digtable.backoff_enable_flag = true; + + if ((rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) && + (hal_get_firmwareversion(rtlpriv) >= 0x3c)) + digtable.dig_algorithm = DIG_ALGO_BY_TOW_PORT; + else + digtable.dig_algorithm = + DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM; + + digtable.dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; + digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; + /* off=by real rssi value, on=by digtable.rssi_val for new dig */ + digtable.dig_dbgmode = DM_DBG_OFF; + digtable.dig_slgorithm_switch = 0; + + /* 2007/10/04 MH Define init gain threshol. */ + digtable.dig_state = DM_STA_DIG_MAX; + digtable.dig_highpwrstate = DM_STA_DIG_MAX; + + digtable.cur_sta_connectstate = DIG_STA_DISCONNECT; + digtable.pre_sta_connectstate = DIG_STA_DISCONNECT; + digtable.cur_ap_connectstate = DIG_AP_DISCONNECT; + digtable.pre_ap_connectstate = DIG_AP_DISCONNECT; + + digtable.rssi_lowthresh = DM_DIG_THRESH_LOW; + digtable.rssi_highthresh = DM_DIG_THRESH_HIGH; + + digtable.fa_lowthresh = DM_FALSEALARM_THRESH_LOW; + digtable.fa_highthresh = DM_FALSEALARM_THRESH_HIGH; + + digtable.rssi_highpower_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW; + digtable.rssi_highpower_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH; + + /* for dig debug rssi value */ + digtable.rssi_val = 50; + digtable.backoff_val = DM_DIG_BACKOFF; + digtable.rx_gain_range_max = DM_DIG_MAX; + + digtable.rx_gain_range_min = DM_DIG_MIN; + + digtable.backoffval_range_max = DM_DIG_BACKOFF_MAX; + digtable.backoffval_range_min = DM_DIG_BACKOFF_MIN; +} + +static void _rtl92s_dm_init_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if ((hal_get_firmwareversion(rtlpriv) >= 60) && + (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)) + rtlpriv->dm.dynamic_txpower_enable = true; + else + rtlpriv->dm.dynamic_txpower_enable = false; + + rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL; + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; +} + +void rtl92s_dm_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; + rtlpriv->dm.undecorated_smoothed_pwdb = -1; + + _rtl92s_dm_init_dynamic_txpower(hw); + rtl92s_dm_init_edca_turbo(hw); + _rtl92s_dm_init_rate_adaptive_mask(hw); + _rtl92s_dm_init_txpowertracking_thermalmeter(hw); + _rtl92s_dm_init_dig(hw); + + rtl_write_dword(rtlpriv, WFM5, FW_CCA_CHK_ENABLE); +} + +void rtl92s_dm_watchdog(struct ieee80211_hw *hw) +{ + _rtl92s_dm_check_edca_turbo(hw); + _rtl92s_dm_check_txpowertracking_thermalmeter(hw); + _rtl92s_dm_ctrl_initgain_byrssi(hw); + _rtl92s_dm_dynamic_txpower(hw); + _rtl92s_dm_refresh_rateadaptive_mask(hw); + _rtl92s_dm_switch_baseband_mrc(hw); +} + diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.h b/drivers/net/wireless/rtlwifi/rtl8192se/dm.h new file mode 100644 index 000000000000..9051a556acc4 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.h @@ -0,0 +1,164 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __RTL_92S_DM_H__ +#define __RTL_92S_DM_H__ + +struct dig_t { + u8 dig_enable_flag; + u8 dig_algorithm; + u8 dig_twoport_algorithm; + u8 dig_ext_port_stage; + u8 dig_dbgmode; + u8 dig_slgorithm_switch; + + long rssi_lowthresh; + long rssi_highthresh; + + u32 fa_lowthresh; + u32 fa_highthresh; + + long rssi_highpower_lowthresh; + long rssi_highpower_highthresh; + + u8 dig_state; + u8 dig_highpwrstate; + u8 cur_sta_connectstate; + u8 pre_sta_connectstate; + u8 cur_ap_connectstate; + u8 pre_ap_connectstate; + + u8 cur_pd_thstate; + u8 pre_pd_thstate; + u8 cur_cs_ratiostate; + u8 pre_cs_ratiostate; + + u32 pre_igvalue; + u32 cur_igvalue; + + u8 backoff_enable_flag; + char backoff_val; + char backoffval_range_max; + char backoffval_range_min; + u8 rx_gain_range_max; + u8 rx_gain_range_min; + + long rssi_val; +}; + +enum dm_dig_alg { + DIG_ALGO_BY_FALSE_ALARM = 0, + DIG_ALGO_BY_RSSI = 1, + DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM = 2, + DIG_ALGO_BY_TOW_PORT = 3, + DIG_ALGO_MAX +}; + +enum dm_dig_two_port_alg { + DIG_TWO_PORT_ALGO_RSSI = 0, + DIG_TWO_PORT_ALGO_FALSE_ALARM = 1, +}; + +enum dm_dig_dbg { + DM_DBG_OFF = 0, + DM_DBG_ON = 1, + DM_DBG_MAX +}; + +enum dm_dig_sta { + DM_STA_DIG_OFF = 0, + DM_STA_DIG_ON, + DM_STA_DIG_MAX +}; + +enum dm_dig_connect { + DIG_STA_DISCONNECT = 0, + DIG_STA_CONNECT = 1, + DIG_STA_BEFORE_CONNECT = 2, + DIG_AP_DISCONNECT = 3, + DIG_AP_CONNECT = 4, + DIG_AP_ADD_STATION = 5, + DIG_CONNECT_MAX +}; + +enum dm_dig_ext_port_alg { + DIG_EXT_PORT_STAGE_0 = 0, + DIG_EXT_PORT_STAGE_1 = 1, + DIG_EXT_PORT_STAGE_2 = 2, + DIG_EXT_PORT_STAGE_3 = 3, + DIG_EXT_PORT_STAGE_MAX = 4, +}; + +enum dm_ratr_sta { + DM_RATR_STA_HIGH = 0, + DM_RATR_STA_MIDDLEHIGH = 1, + DM_RATR_STA_MIDDLE = 2, + DM_RATR_STA_MIDDLELOW = 3, + DM_RATR_STA_LOW = 4, + DM_RATR_STA_ULTRALOW = 5, + DM_RATR_STA_MAX +}; + +#define DM_TYPE_BYFW 0 +#define DM_TYPE_BYDRIVER 1 + +#define TX_HIGH_PWR_LEVEL_NORMAL 0 +#define TX_HIGH_PWR_LEVEL_LEVEL1 1 +#define TX_HIGH_PWR_LEVEL_LEVEL2 2 + +#define HAL_DM_DIG_DISABLE BIT(0) /* Disable Dig */ +#define HAL_DM_HIPWR_DISABLE BIT(1) /* Disable High Power */ + +#define TX_HIGHPWR_LEVEL_NORMAL 0 +#define TX_HIGHPWR_LEVEL_NORMAL1 1 +#define TX_HIGHPWR_LEVEL_NORMAL2 2 + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 + +#define DM_DIG_THRESH_HIGH 40 +#define DM_DIG_THRESH_LOW 35 +#define DM_FALSEALARM_THRESH_LOW 40 +#define DM_FALSEALARM_THRESH_HIGH 1000 +#define DM_DIG_HIGH_PWR_THRESH_HIGH 75 +#define DM_DIG_HIGH_PWR_THRESH_LOW 70 +#define DM_DIG_BACKOFF 12 +#define DM_DIG_MAX 0x3e +#define DM_DIG_MIN 0x1c +#define DM_DIG_MIN_Netcore 0x12 +#define DM_DIG_BACKOFF_MAX 12 +#define DM_DIG_BACKOFF_MIN -4 + +extern struct dig_t digtable; + +void rtl92s_dm_watchdog(struct ieee80211_hw *hw); +void rtl92s_dm_init(struct ieee80211_hw *hw); +void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw); + +#endif + -- cgit v1.2.3-58-ga151 From 701307a885b13a1790b94e232923de1d199e3cc9 Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Tue, 3 May 2011 09:48:05 -0500 Subject: rtlwifi: rtl8192se: Merge firmware routines Merge routines fw.c and fw.h for RTL8192SE. In addition, make changes to rtlwifi/wifi.h to support RTL8192SE. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192se/fw.c | 654 ++++++++++++++++++++++++++++ drivers/net/wireless/rtlwifi/rtl8192se/fw.h | 375 ++++++++++++++++ 2 files changed, 1029 insertions(+) create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/fw.c create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/fw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c new file mode 100644 index 000000000000..3b5af0113d7f --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c @@ -0,0 +1,654 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "fw.h" + +static void _rtl92s_fw_set_rqpn(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_dword(rtlpriv, RQPN, 0xffffffff); + rtl_write_dword(rtlpriv, RQPN + 4, 0xffffffff); + rtl_write_byte(rtlpriv, RQPN + 8, 0xff); + rtl_write_byte(rtlpriv, RQPN + 0xB, 0x80); +} + +static bool _rtl92s_firmware_enable_cpu(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 ichecktime = 200; + u16 tmpu2b; + u8 tmpu1b, cpustatus = 0; + + _rtl92s_fw_set_rqpn(hw); + + /* Enable CPU. */ + tmpu1b = rtl_read_byte(rtlpriv, SYS_CLKR); + /* AFE source */ + rtl_write_byte(rtlpriv, SYS_CLKR, (tmpu1b | SYS_CPU_CLKSEL)); + + tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | FEN_CPUEN)); + + /* Polling IMEM Ready after CPU has refilled. */ + do { + cpustatus = rtl_read_byte(rtlpriv, TCR); + if (cpustatus & IMEM_RDY) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("IMEM Ready after CPU has refilled.\n")); + break; + } + + udelay(100); + } while (ichecktime--); + + if (!(cpustatus & IMEM_RDY)) + return false; + + return true; +} + +static enum fw_status _rtl92s_firmware_get_nextstatus( + enum fw_status fw_currentstatus) +{ + enum fw_status next_fwstatus = 0; + + switch (fw_currentstatus) { + case FW_STATUS_INIT: + next_fwstatus = FW_STATUS_LOAD_IMEM; + break; + case FW_STATUS_LOAD_IMEM: + next_fwstatus = FW_STATUS_LOAD_EMEM; + break; + case FW_STATUS_LOAD_EMEM: + next_fwstatus = FW_STATUS_LOAD_DMEM; + break; + case FW_STATUS_LOAD_DMEM: + next_fwstatus = FW_STATUS_READY; + break; + default: + break; + } + + return next_fwstatus; +} + +static u8 _rtl92s_firmware_header_map_rftype(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + switch (rtlphy->rf_type) { + case RF_1T1R: + return 0x11; + break; + case RF_1T2R: + return 0x12; + break; + case RF_2T2R: + return 0x22; + break; + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + ("Unknown RF type(%x)\n", + rtlphy->rf_type)); + break; + } + return 0x22; +} + +static void _rtl92s_firmwareheader_priveupdate(struct ieee80211_hw *hw, + struct fw_priv *pfw_priv) +{ + /* Update RF types for RATR settings. */ + pfw_priv->rf_config = _rtl92s_firmware_header_map_rftype(hw); +} + + + +static bool _rtl92s_cmd_send_packet(struct ieee80211_hw *hw, + struct sk_buff *skb, u8 last) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring; + struct rtl_tx_desc *pdesc; + unsigned long flags; + u8 idx = 0; + + ring = &rtlpci->tx_ring[TXCMD_QUEUE]; + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + + idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; + pdesc = &ring->desc[idx]; + rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); + __skb_queue_tail(&ring->queue, skb); + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + + return true; +} + +static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw, + u8 *code_virtual_address, u32 buffer_len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct sk_buff *skb; + struct rtl_tcb_desc *tcb_desc; + unsigned char *seg_ptr; + u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE; + u16 frag_length, frag_offset = 0; + u16 extra_descoffset = 0; + u8 last_inipkt = 0; + + _rtl92s_fw_set_rqpn(hw); + + if (buffer_len >= MAX_FIRMWARE_CODE_SIZE) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Size over FIRMWARE_CODE_SIZE!\n")); + + return false; + } + + extra_descoffset = 0; + + do { + if ((buffer_len - frag_offset) > frag_threshold) { + frag_length = frag_threshold + extra_descoffset; + } else { + frag_length = (u16)(buffer_len - frag_offset + + extra_descoffset); + last_inipkt = 1; + } + + /* Allocate skb buffer to contain firmware */ + /* info and tx descriptor info. */ + skb = dev_alloc_skb(frag_length); + skb_reserve(skb, extra_descoffset); + seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length - + extra_descoffset)); + memcpy(seg_ptr, code_virtual_address + frag_offset, + (u32)(frag_length - extra_descoffset)); + + tcb_desc = (struct rtl_tcb_desc *)(skb->cb); + tcb_desc->queue_index = TXCMD_QUEUE; + tcb_desc->cmd_or_init = DESC_PACKET_TYPE_INIT; + tcb_desc->last_inipkt = last_inipkt; + + _rtl92s_cmd_send_packet(hw, skb, last_inipkt); + + frag_offset += (frag_length - extra_descoffset); + + } while (frag_offset < buffer_len); + + rtl_write_byte(rtlpriv, TP_POLL, TPPOLL_CQ); + + return true ; +} + +static bool _rtl92s_firmware_checkready(struct ieee80211_hw *hw, + u8 loadfw_status) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rt_firmware *firmware = (struct rt_firmware *)rtlhal->pfirmware; + u32 tmpu4b; + u8 cpustatus = 0; + short pollingcnt = 1000; + bool rtstatus = true; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("LoadStaus(%d)\n", + loadfw_status)); + + firmware->fwstatus = (enum fw_status)loadfw_status; + + switch (loadfw_status) { + case FW_STATUS_LOAD_IMEM: + /* Polling IMEM code done. */ + do { + cpustatus = rtl_read_byte(rtlpriv, TCR); + if (cpustatus & IMEM_CODE_DONE) + break; + udelay(5); + } while (pollingcnt--); + + if (!(cpustatus & IMEM_CHK_RPT) || (pollingcnt <= 0)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("FW_STATUS_LOAD_IMEM" + " FAIL CPU, Status=%x\r\n", cpustatus)); + goto status_check_fail; + } + break; + + case FW_STATUS_LOAD_EMEM: + /* Check Put Code OK and Turn On CPU */ + /* Polling EMEM code done. */ + do { + cpustatus = rtl_read_byte(rtlpriv, TCR); + if (cpustatus & EMEM_CODE_DONE) + break; + udelay(5); + } while (pollingcnt--); + + if (!(cpustatus & EMEM_CHK_RPT) || (pollingcnt <= 0)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("FW_STATUS_LOAD_EMEM" + " FAIL CPU, Status=%x\r\n", cpustatus)); + goto status_check_fail; + } + + /* Turn On CPU */ + rtstatus = _rtl92s_firmware_enable_cpu(hw); + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Enable CPU fail!\n")); + goto status_check_fail; + } + break; + + case FW_STATUS_LOAD_DMEM: + /* Polling DMEM code done */ + do { + cpustatus = rtl_read_byte(rtlpriv, TCR); + if (cpustatus & DMEM_CODE_DONE) + break; + udelay(5); + } while (pollingcnt--); + + if (!(cpustatus & DMEM_CODE_DONE) || (pollingcnt <= 0)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Polling DMEM code done" + " fail ! cpustatus(%#x)\n", cpustatus)); + goto status_check_fail; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("DMEM code download success," + " cpustatus(%#x)\n", cpustatus)); + + /* Prevent Delay too much and being scheduled out */ + /* Polling Load Firmware ready */ + pollingcnt = 2000; + do { + cpustatus = rtl_read_byte(rtlpriv, TCR); + if (cpustatus & FWRDY) + break; + udelay(40); + } while (pollingcnt--); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("Polling Load Firmware ready," + " cpustatus(%x)\n", cpustatus)); + + if (((cpustatus & LOAD_FW_READY) != LOAD_FW_READY) || + (pollingcnt <= 0)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Polling Load Firmware" + " ready fail ! cpustatus(%x)\n", cpustatus)); + goto status_check_fail; + } + + /* If right here, we can set TCR/RCR to desired value */ + /* and config MAC lookback mode to normal mode */ + tmpu4b = rtl_read_dword(rtlpriv, TCR); + rtl_write_dword(rtlpriv, TCR, (tmpu4b & (~TCR_ICV))); + + tmpu4b = rtl_read_dword(rtlpriv, RCR); + rtl_write_dword(rtlpriv, RCR, (tmpu4b | RCR_APPFCS | + RCR_APP_ICV | RCR_APP_MIC)); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("Current RCR settings(%#x)\n", tmpu4b)); + + /* Set to normal mode. */ + rtl_write_byte(rtlpriv, LBKMD_SEL, LBK_NORMAL); + break; + + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + ("Unknown status check!\n")); + rtstatus = false; + break; + } + +status_check_fail: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("loadfw_status(%d), " + "rtstatus(%x)\n", loadfw_status, rtstatus)); + return rtstatus; +} + +int rtl92s_download_fw(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rt_firmware *firmware = NULL; + struct fw_hdr *pfwheader; + struct fw_priv *pfw_priv = NULL; + u8 *puc_mappedfile = NULL; + u32 ul_filelength = 0; + u32 file_length = 0; + u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE; + u8 fwstatus = FW_STATUS_INIT; + bool rtstatus = true; + + if (!rtlhal->pfirmware) + return 1; + + firmware = (struct rt_firmware *)rtlhal->pfirmware; + firmware->fwstatus = FW_STATUS_INIT; + + puc_mappedfile = firmware->sz_fw_tmpbuffer; + file_length = firmware->sz_fw_tmpbufferlen; + + /* 1. Retrieve FW header. */ + firmware->pfwheader = (struct fw_hdr *) puc_mappedfile; + pfwheader = firmware->pfwheader; + firmware->firmwareversion = byte(pfwheader->version, 0); + firmware->pfwheader->fwpriv.hci_sel = 1;/* pcie */ + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("signature:%x, version:" + "%x, size:%x," + "imemsize:%x, sram size:%x\n", pfwheader->signature, + pfwheader->version, pfwheader->dmem_size, + pfwheader->img_imem_size, pfwheader->img_sram_size)); + + /* 2. Retrieve IMEM image. */ + if ((pfwheader->img_imem_size == 0) || (pfwheader->img_imem_size > + sizeof(firmware->fw_imem))) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("memory for data image is less than IMEM required\n")); + goto fail; + } else { + puc_mappedfile += fwhdr_size; + + memcpy(firmware->fw_imem, puc_mappedfile, + pfwheader->img_imem_size); + firmware->fw_imem_len = pfwheader->img_imem_size; + } + + /* 3. Retriecve EMEM image. */ + if (pfwheader->img_sram_size > sizeof(firmware->fw_emem)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("memory for data image is less than EMEM required\n")); + goto fail; + } else { + puc_mappedfile += firmware->fw_imem_len; + + memcpy(firmware->fw_emem, puc_mappedfile, + pfwheader->img_sram_size); + firmware->fw_emem_len = pfwheader->img_sram_size; + } + + /* 4. download fw now */ + fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus); + while (fwstatus != FW_STATUS_READY) { + /* Image buffer redirection. */ + switch (fwstatus) { + case FW_STATUS_LOAD_IMEM: + puc_mappedfile = firmware->fw_imem; + ul_filelength = firmware->fw_imem_len; + break; + case FW_STATUS_LOAD_EMEM: + puc_mappedfile = firmware->fw_emem; + ul_filelength = firmware->fw_emem_len; + break; + case FW_STATUS_LOAD_DMEM: + /* Partial update the content of header private. */ + pfwheader = firmware->pfwheader; + pfw_priv = &pfwheader->fwpriv; + _rtl92s_firmwareheader_priveupdate(hw, pfw_priv); + puc_mappedfile = (u8 *)(firmware->pfwheader) + + RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; + ul_filelength = fwhdr_size - + RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Unexpected Download step!!\n")); + goto fail; + break; + } + + /* <2> Download image file */ + rtstatus = _rtl92s_firmware_downloadcode(hw, puc_mappedfile, + ul_filelength); + + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("fail!\n")); + goto fail; + } + + /* <3> Check whether load FW process is ready */ + rtstatus = _rtl92s_firmware_checkready(hw, fwstatus); + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("fail!\n")); + goto fail; + } + + fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus); + } + + return rtstatus; +fail: + return 0; +} + +static u32 _rtl92s_fill_h2c_cmd(struct sk_buff *skb, u32 h2cbufferlen, + u32 cmd_num, u32 *pelement_id, u32 *pcmd_len, + u8 **pcmb_buffer, u8 *cmd_start_seq) +{ + u32 totallen = 0, len = 0, tx_desclen = 0; + u32 pre_continueoffset = 0; + u8 *ph2c_buffer; + u8 i = 0; + + do { + /* 8 - Byte aligment */ + len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8); + + /* Buffer length is not enough */ + if (h2cbufferlen < totallen + len + tx_desclen) + break; + + /* Clear content */ + ph2c_buffer = (u8 *)skb_put(skb, (u32)len); + memset((ph2c_buffer + totallen + tx_desclen), 0, len); + + /* CMD len */ + SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), + 0, 16, pcmd_len[i]); + + /* CMD ID */ + SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), + 16, 8, pelement_id[i]); + + /* CMD Sequence */ + *cmd_start_seq = *cmd_start_seq % 0x80; + SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), + 24, 7, *cmd_start_seq); + ++*cmd_start_seq; + + /* Copy memory */ + memcpy((ph2c_buffer + totallen + tx_desclen + + H2C_TX_CMD_HDR_LEN), pcmb_buffer[i], pcmd_len[i]); + + /* CMD continue */ + /* set the continue in prevoius cmd. */ + if (i < cmd_num - 1) + SET_BITS_TO_LE_4BYTE((ph2c_buffer + pre_continueoffset), + 31, 1, 1); + + pre_continueoffset = totallen; + + totallen += len; + } while (++i < cmd_num); + + return totallen; +} + +static u32 _rtl92s_get_h2c_cmdlen(u32 h2cbufferlen, u32 cmd_num, u32 *pcmd_len) +{ + u32 totallen = 0, len = 0, tx_desclen = 0; + u8 i = 0; + + do { + /* 8 - Byte aligment */ + len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8); + + /* Buffer length is not enough */ + if (h2cbufferlen < totallen + len + tx_desclen) + break; + + totallen += len; + } while (++i < cmd_num); + + return totallen + tx_desclen; +} + +static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd, + u8 *pcmd_buffer) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_tcb_desc *cb_desc; + struct sk_buff *skb; + u32 element_id = 0; + u32 cmd_len = 0; + u32 len; + + switch (h2c_cmd) { + case FW_H2C_SETPWRMODE: + element_id = H2C_SETPWRMODE_CMD ; + cmd_len = sizeof(struct h2c_set_pwrmode_parm); + break; + case FW_H2C_JOINBSSRPT: + element_id = H2C_JOINBSSRPT_CMD; + cmd_len = sizeof(struct h2c_joinbss_rpt_parm); + break; + case FW_H2C_WOWLAN_UPDATE_GTK: + element_id = H2C_WOWLAN_UPDATE_GTK_CMD; + cmd_len = sizeof(struct h2c_wpa_two_way_parm); + break; + case FW_H2C_WOWLAN_UPDATE_IV: + element_id = H2C_WOWLAN_UPDATE_IV_CMD; + cmd_len = sizeof(unsigned long long); + break; + case FW_H2C_WOWLAN_OFFLOAD: + element_id = H2C_WOWLAN_FW_OFFLOAD; + cmd_len = sizeof(u8); + break; + default: + break; + } + + len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len); + skb = dev_alloc_skb(len); + cb_desc = (struct rtl_tcb_desc *)(skb->cb); + cb_desc->queue_index = TXCMD_QUEUE; + cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL; + cb_desc->last_inipkt = false; + + _rtl92s_fill_h2c_cmd(skb, MAX_TRANSMIT_BUFFER_SIZE, 1, &element_id, + &cmd_len, &pcmd_buffer, &rtlhal->h2c_txcmd_seq); + _rtl92s_cmd_send_packet(hw, skb, false); + rtlpriv->cfg->ops->tx_polling(hw, TXCMD_QUEUE); + + return true; +} + +void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 Mode) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct h2c_set_pwrmode_parm pwrmode; + u16 max_wakeup_period = 0; + + pwrmode.mode = Mode; + pwrmode.flag_low_traffic_en = 0; + pwrmode.flag_lpnav_en = 0; + pwrmode.flag_rf_low_snr_en = 0; + pwrmode.flag_dps_en = 0; + pwrmode.bcn_rx_en = 0; + pwrmode.bcn_to = 0; + SET_BITS_TO_LE_2BYTE((u8 *)(&pwrmode) + 8, 0, 16, + mac->vif->bss_conf.beacon_int); + pwrmode.app_itv = 0; + pwrmode.awake_bcn_itvl = ppsc->reg_max_lps_awakeintvl; + pwrmode.smart_ps = 1; + pwrmode.bcn_pass_period = 10; + + /* Set beacon pass count */ + if (pwrmode.mode == FW_PS_MIN_MODE) + max_wakeup_period = mac->vif->bss_conf.beacon_int; + else if (pwrmode.mode == FW_PS_MAX_MODE) + max_wakeup_period = mac->vif->bss_conf.beacon_int * + mac->vif->bss_conf.dtim_period; + + if (max_wakeup_period >= 500) + pwrmode.bcn_pass_cnt = 1; + else if ((max_wakeup_period >= 300) && (max_wakeup_period < 500)) + pwrmode.bcn_pass_cnt = 2; + else if ((max_wakeup_period >= 200) && (max_wakeup_period < 300)) + pwrmode.bcn_pass_cnt = 3; + else if ((max_wakeup_period >= 20) && (max_wakeup_period < 200)) + pwrmode.bcn_pass_cnt = 5; + else + pwrmode.bcn_pass_cnt = 1; + + _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_SETPWRMODE, (u8 *)&pwrmode); + +} + +void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, + u8 mstatus, u8 ps_qosinfo) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct h2c_joinbss_rpt_parm joinbss_rpt; + + joinbss_rpt.opmode = mstatus; + joinbss_rpt.ps_qos_info = ps_qosinfo; + joinbss_rpt.bssid[0] = mac->bssid[0]; + joinbss_rpt.bssid[1] = mac->bssid[1]; + joinbss_rpt.bssid[2] = mac->bssid[2]; + joinbss_rpt.bssid[3] = mac->bssid[3]; + joinbss_rpt.bssid[4] = mac->bssid[4]; + joinbss_rpt.bssid[5] = mac->bssid[5]; + SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 8, 0, 16, + mac->vif->bss_conf.beacon_int); + SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 10, 0, 16, mac->assoc_id); + + _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_JOINBSSRPT, (u8 *)&joinbss_rpt); +} + diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.h b/drivers/net/wireless/rtlwifi/rtl8192se/fw.h new file mode 100644 index 000000000000..74cc503efe8a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.h @@ -0,0 +1,375 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __REALTEK_FIRMWARE92S_H__ +#define __REALTEK_FIRMWARE92S_H__ + +#define RTL8190_MAX_FIRMWARE_CODE_SIZE 64000 +#define RTL8190_CPU_START_OFFSET 0x80 +/* Firmware Local buffer size. 64k */ +#define MAX_FIRMWARE_CODE_SIZE 0xFF00 + +#define RT_8192S_FIRMWARE_HDR_SIZE 80 +#define RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE 32 + +/* support till 64 bit bus width OS */ +#define MAX_DEV_ADDR_SIZE 8 +#define MAX_FIRMWARE_INFORMATION_SIZE 32 +#define MAX_802_11_HEADER_LENGTH (40 + \ + MAX_FIRMWARE_INFORMATION_SIZE) +#define ENCRYPTION_MAX_OVERHEAD 128 +#define MAX_FRAGMENT_COUNT 8 +#define MAX_TRANSMIT_BUFFER_SIZE (1600 + \ + (MAX_802_11_HEADER_LENGTH + \ + ENCRYPTION_MAX_OVERHEAD) *\ + MAX_FRAGMENT_COUNT) + +#define H2C_TX_CMD_HDR_LEN 8 + +/* The following DM control code are for Reg0x364, */ +#define FW_DIG_ENABLE_CTL BIT(0) +#define FW_HIGH_PWR_ENABLE_CTL BIT(1) +#define FW_SS_CTL BIT(2) +#define FW_RA_INIT_CTL BIT(3) +#define FW_RA_BG_CTL BIT(4) +#define FW_RA_N_CTL BIT(5) +#define FW_PWR_TRK_CTL BIT(6) +#define FW_IQK_CTL BIT(7) +#define FW_FA_CTL BIT(8) +#define FW_DRIVER_CTRL_DM_CTL BIT(9) +#define FW_PAPE_CTL_BY_SW_HW BIT(10) +#define FW_DISABLE_ALL_DM 0 +#define FW_PWR_TRK_PARAM_CLR 0x0000ffff +#define FW_RA_PARAM_CLR 0xffff0000 + +enum desc_packet_type { + DESC_PACKET_TYPE_INIT = 0, + DESC_PACKET_TYPE_NORMAL = 1, +}; + +/* 8-bytes alignment required */ +struct fw_priv { + /* --- long word 0 ---- */ + /* 0x12: CE product, 0x92: IT product */ + u8 signature_0; + /* 0x87: CE product, 0x81: IT product */ + u8 signature_1; + /* 0x81: PCI-AP, 01:PCIe, 02: 92S-U, + * 0x82: USB-AP, 0x12: 72S-U, 03:SDIO */ + u8 hci_sel; + /* the same value as reigster value */ + u8 chip_version; + /* customer ID low byte */ + u8 customer_id_0; + /* customer ID high byte */ + u8 customer_id_1; + /* 0x11: 1T1R, 0x12: 1T2R, + * 0x92: 1T2R turbo, 0x22: 2T2R */ + u8 rf_config; + /* 4: 4EP, 6: 6EP, 11: 11EP */ + u8 usb_ep_num; + + /* --- long word 1 ---- */ + /* regulatory class bit map 0 */ + u8 regulatory_class_0; + /* regulatory class bit map 1 */ + u8 regulatory_class_1; + /* regulatory class bit map 2 */ + u8 regulatory_class_2; + /* regulatory class bit map 3 */ + u8 regulatory_class_3; + /* 0:SWSI, 1:HWSI, 2:HWPI */ + u8 rfintfs; + u8 def_nettype; + u8 rsvd010; + u8 rsvd011; + + /* --- long word 2 ---- */ + /* 0x00: normal, 0x03: MACLBK, 0x01: PHYLBK */ + u8 lbk_mode; + /* 1: for MP use, 0: for normal + * driver (to be discussed) */ + u8 mp_mode; + u8 rsvd020; + u8 rsvd021; + u8 rsvd022; + u8 rsvd023; + u8 rsvd024; + u8 rsvd025; + + /* --- long word 3 ---- */ + /* QoS enable */ + u8 qos_en; + /* 40MHz BW enable */ + /* 4181 convert AMSDU to AMPDU, 0: disable */ + u8 bw_40mhz_en; + u8 amsdu2ampdu_en; + /* 11n AMPDU enable */ + u8 ampdu_en; + /* FW offloads, 0: driver handles */ + u8 rate_control_offload; + /* FW offloads, 0: driver handles */ + u8 aggregation_offload; + u8 rsvd030; + u8 rsvd031; + + /* --- long word 4 ---- */ + /* 1. FW offloads, 0: driver handles */ + u8 beacon_offload; + /* 2. FW offloads, 0: driver handles */ + u8 mlme_offload; + /* 3. FW offloads, 0: driver handles */ + u8 hwpc_offload; + /* 4. FW offloads, 0: driver handles */ + u8 tcp_checksum_offload; + /* 5. FW offloads, 0: driver handles */ + u8 tcp_offload; + /* 6. FW offloads, 0: driver handles */ + u8 ps_control_offload; + /* 7. FW offloads, 0: driver handles */ + u8 wwlan_offload; + u8 rsvd040; + + /* --- long word 5 ---- */ + /* tcp tx packet length low byte */ + u8 tcp_tx_frame_len_L; + /* tcp tx packet length high byte */ + u8 tcp_tx_frame_len_H; + /* tcp rx packet length low byte */ + u8 tcp_rx_frame_len_L; + /* tcp rx packet length high byte */ + u8 tcp_rx_frame_len_H; + u8 rsvd050; + u8 rsvd051; + u8 rsvd052; + u8 rsvd053; +}; + +/* 8-byte alinment required */ +struct fw_hdr { + + /* --- LONG WORD 0 ---- */ + u16 signature; + /* 0x8000 ~ 0x8FFF for FPGA version, + * 0x0000 ~ 0x7FFF for ASIC version, */ + u16 version; + /* define the size of boot loader */ + u32 dmem_size; + + + /* --- LONG WORD 1 ---- */ + /* define the size of FW in IMEM */ + u32 img_imem_size; + /* define the size of FW in SRAM */ + u32 img_sram_size; + + /* --- LONG WORD 2 ---- */ + /* define the size of DMEM variable */ + u32 fw_priv_size; + u32 rsvd0; + + /* --- LONG WORD 3 ---- */ + u32 rsvd1; + u32 rsvd2; + + struct fw_priv fwpriv; + +} ; + +enum fw_status { + FW_STATUS_INIT = 0, + FW_STATUS_LOAD_IMEM = 1, + FW_STATUS_LOAD_EMEM = 2, + FW_STATUS_LOAD_DMEM = 3, + FW_STATUS_READY = 4, +}; + +struct rt_firmware { + struct fw_hdr *pfwheader; + enum fw_status fwstatus; + u16 firmwareversion; + u8 fw_imem[RTL8190_MAX_FIRMWARE_CODE_SIZE]; + u8 fw_emem[RTL8190_MAX_FIRMWARE_CODE_SIZE]; + u32 fw_imem_len; + u32 fw_emem_len; + u8 sz_fw_tmpbuffer[164000]; + u32 sz_fw_tmpbufferlen; + u16 cmdpacket_fragthresold; +}; + +struct h2c_set_pwrmode_parm { + u8 mode; + u8 flag_low_traffic_en; + u8 flag_lpnav_en; + u8 flag_rf_low_snr_en; + /* 1: dps, 0: 32k */ + u8 flag_dps_en; + u8 bcn_rx_en; + u8 bcn_pass_cnt; + /* beacon TO (ms). ¡§=0¡¨ no limit. */ + u8 bcn_to; + u16 bcn_itv; + /* only for VOIP mode. */ + u8 app_itv; + u8 awake_bcn_itvl; + u8 smart_ps; + /* unit: 100 ms */ + u8 bcn_pass_period; +}; + +struct h2c_joinbss_rpt_parm { + u8 opmode; + u8 ps_qos_info; + u8 bssid[6]; + u16 bcnitv; + u16 aid; +} ; + +struct h2c_wpa_ptk { + /* EAPOL-Key Key Confirmation Key (KCK) */ + u8 kck[16]; + /* EAPOL-Key Key Encryption Key (KEK) */ + u8 kek[16]; + /* Temporal Key 1 (TK1) */ + u8 tk1[16]; + union { + /* Temporal Key 2 (TK2) */ + u8 tk2[16]; + struct { + u8 tx_mic_key[8]; + u8 rx_mic_key[8]; + } athu; + } u; +}; + +struct h2c_wpa_two_way_parm { + /* algorithm TKIP or AES */ + u8 pairwise_en_alg; + u8 group_en_alg; + struct h2c_wpa_ptk wpa_ptk_value; +} ; + +enum h2c_cmd { + FW_H2C_SETPWRMODE = 0, + FW_H2C_JOINBSSRPT = 1, + FW_H2C_WOWLAN_UPDATE_GTK = 2, + FW_H2C_WOWLAN_UPDATE_IV = 3, + FW_H2C_WOWLAN_OFFLOAD = 4, +}; + +enum fw_h2c_cmd { + H2C_READ_MACREG_CMD, /*0*/ + H2C_WRITE_MACREG_CMD, + H2C_READBB_CMD, + H2C_WRITEBB_CMD, + H2C_READRF_CMD, + H2C_WRITERF_CMD, /*5*/ + H2C_READ_EEPROM_CMD, + H2C_WRITE_EEPROM_CMD, + H2C_READ_EFUSE_CMD, + H2C_WRITE_EFUSE_CMD, + H2C_READ_CAM_CMD, /*10*/ + H2C_WRITE_CAM_CMD, + H2C_SETBCNITV_CMD, + H2C_SETMBIDCFG_CMD, + H2C_JOINBSS_CMD, + H2C_DISCONNECT_CMD, /*15*/ + H2C_CREATEBSS_CMD, + H2C_SETOPMode_CMD, + H2C_SITESURVEY_CMD, + H2C_SETAUTH_CMD, + H2C_SETKEY_CMD, /*20*/ + H2C_SETSTAKEY_CMD, + H2C_SETASSOCSTA_CMD, + H2C_DELASSOCSTA_CMD, + H2C_SETSTAPWRSTATE_CMD, + H2C_SETBASICRATE_CMD, /*25*/ + H2C_GETBASICRATE_CMD, + H2C_SETDATARATE_CMD, + H2C_GETDATARATE_CMD, + H2C_SETPHYINFO_CMD, + H2C_GETPHYINFO_CMD, /*30*/ + H2C_SETPHY_CMD, + H2C_GETPHY_CMD, + H2C_READRSSI_CMD, + H2C_READGAIN_CMD, + H2C_SETATIM_CMD, /*35*/ + H2C_SETPWRMODE_CMD, + H2C_JOINBSSRPT_CMD, + H2C_SETRATABLE_CMD, + H2C_GETRATABLE_CMD, + H2C_GETCCXREPORT_CMD, /*40*/ + H2C_GETDTMREPORT_CMD, + H2C_GETTXRATESTATICS_CMD, + H2C_SETUSBSUSPEND_CMD, + H2C_SETH2CLBK_CMD, + H2C_TMP1, /*45*/ + H2C_WOWLAN_UPDATE_GTK_CMD, + H2C_WOWLAN_FW_OFFLOAD, + H2C_TMP2, + H2C_TMP3, + H2C_WOWLAN_UPDATE_IV_CMD, /*50*/ + H2C_TMP4, + MAX_H2CCMD /*52*/ +}; + +/* The following macros are used for FW + * CMD map and parameter updated. */ +#define FW_CMD_IO_CLR(rtlpriv, _Bit) \ + do { \ + udelay(1000); \ + rtlpriv->rtlhal.fwcmd_iomap &= (~_Bit); \ + } while (0); + +#define FW_CMD_IO_UPDATE(rtlpriv, _val) \ + rtlpriv->rtlhal.fwcmd_iomap = _val; + +#define FW_CMD_IO_SET(rtlpriv, _val) \ + do { \ + rtl_write_word(rtlpriv, LBUS_MON_ADDR, (u16)_val); \ + FW_CMD_IO_UPDATE(rtlpriv, _val); \ + } while (0); + +#define FW_CMD_PARA_SET(rtlpriv, _val) \ + do { \ + rtl_write_dword(rtlpriv, LBUS_ADDR_MASK, _val); \ + rtlpriv->rtlhal.fwcmd_ioparam = _val; \ + } while (0); + +#define FW_CMD_IO_QUERY(rtlpriv) \ + (u16)(rtlpriv->rtlhal.fwcmd_iomap) +#define FW_CMD_IO_PARA_QUERY(rtlpriv) \ + ((u32)(rtlpriv->rtlhal.fwcmd_ioparam)) + +int rtl92s_download_fw(struct ieee80211_hw *hw); +void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); +void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, + u8 mstatus, u8 ps_qosinfo); + +#endif + -- cgit v1.2.3-58-ga151 From 24284531497def77d0c3c0de9046880b1c4e6b13 Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Tue, 3 May 2011 09:48:15 -0500 Subject: rtlwifi: rtl8192se: Merge hardware routines Merge routines hw.c and hw.h for RTL8192SE. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192se/hw.c | 2512 +++++++++++++++++++++++++++ drivers/net/wireless/rtlwifi/rtl8192se/hw.h | 79 + 2 files changed, 2591 insertions(+) create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/hw.c create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/hw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c new file mode 100644 index 000000000000..2e9005d0454b --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c @@ -0,0 +1,2512 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../efuse.h" +#include "../base.h" +#include "../regd.h" +#include "../cam.h" +#include "../ps.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "led.h" +#include "hw.h" + +void rtl92se_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + switch (variable) { + case HW_VAR_RCR: { + *((u32 *) (val)) = rtlpci->receive_config; + break; + } + case HW_VAR_RF_STATE: { + *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; + break; + } + case HW_VAR_FW_PSMODE_STATUS: { + *((bool *) (val)) = ppsc->fw_current_inpsmode; + break; + } + case HW_VAR_CORRECT_TSF: { + u64 tsf; + u32 *ptsf_low = (u32 *)&tsf; + u32 *ptsf_high = ((u32 *)&tsf) + 1; + + *ptsf_high = rtl_read_dword(rtlpriv, (TSFR + 4)); + *ptsf_low = rtl_read_dword(rtlpriv, TSFR); + + *((u64 *) (val)) = tsf; + + break; + } + case HW_VAR_MRC: { + *((bool *)(val)) = rtlpriv->dm.current_mrc_switch; + break; + } + default: { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + } +} + +void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + switch (variable) { + case HW_VAR_ETHER_ADDR:{ + rtl_write_dword(rtlpriv, IDR0, ((u32 *)(val))[0]); + rtl_write_word(rtlpriv, IDR4, ((u16 *)(val + 4))[0]); + break; + } + case HW_VAR_BASIC_RATE:{ + u16 rate_cfg = ((u16 *) val)[0]; + u8 rate_index = 0; + + if (rtlhal->version == VERSION_8192S_ACUT) + rate_cfg = rate_cfg & 0x150; + else + rate_cfg = rate_cfg & 0x15f; + + rate_cfg |= 0x01; + + rtl_write_byte(rtlpriv, RRSR, rate_cfg & 0xff); + rtl_write_byte(rtlpriv, RRSR + 1, + (rate_cfg >> 8) & 0xff); + + while (rate_cfg > 0x1) { + rate_cfg = (rate_cfg >> 1); + rate_index++; + } + rtl_write_byte(rtlpriv, INIRTSMCS_SEL, rate_index); + + break; + } + case HW_VAR_BSSID:{ + rtl_write_dword(rtlpriv, BSSIDR, ((u32 *)(val))[0]); + rtl_write_word(rtlpriv, BSSIDR + 4, + ((u16 *)(val + 4))[0]); + break; + } + case HW_VAR_SIFS:{ + rtl_write_byte(rtlpriv, SIFS_OFDM, val[0]); + rtl_write_byte(rtlpriv, SIFS_OFDM + 1, val[1]); + break; + } + case HW_VAR_SLOT_TIME:{ + u8 e_aci; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + ("HW_VAR_SLOT_TIME %x\n", val[0])); + + rtl_write_byte(rtlpriv, SLOT_TIME, val[0]); + + for (e_aci = 0; e_aci < AC_MAX; e_aci++) { + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_AC_PARAM, + (u8 *)(&e_aci)); + } + break; + } + case HW_VAR_ACK_PREAMBLE:{ + u8 reg_tmp; + u8 short_preamble = (bool) (*(u8 *) val); + reg_tmp = (mac->cur_40_prime_sc) << 5; + if (short_preamble) + reg_tmp |= 0x80; + + rtl_write_byte(rtlpriv, RRSR + 2, reg_tmp); + break; + } + case HW_VAR_AMPDU_MIN_SPACE:{ + u8 min_spacing_to_set; + u8 sec_min_space; + + min_spacing_to_set = *((u8 *)val); + if (min_spacing_to_set <= 7) { + if (rtlpriv->sec.pairwise_enc_algorithm == + NO_ENCRYPTION) + sec_min_space = 0; + else + sec_min_space = 1; + + if (min_spacing_to_set < sec_min_space) + min_spacing_to_set = sec_min_space; + if (min_spacing_to_set > 5) + min_spacing_to_set = 5; + + mac->min_space_cfg = + ((mac->min_space_cfg & 0xf8) | + min_spacing_to_set); + + *val = min_spacing_to_set; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + ("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", + mac->min_space_cfg)); + + rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, + mac->min_space_cfg); + } + break; + } + case HW_VAR_SHORTGI_DENSITY:{ + u8 density_to_set; + + density_to_set = *((u8 *) val); + mac->min_space_cfg = rtlpriv->rtlhal.minspace_cfg; + mac->min_space_cfg |= (density_to_set << 3); + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + ("Set HW_VAR_SHORTGI_DENSITY: %#x\n", + mac->min_space_cfg)); + + rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, + mac->min_space_cfg); + + break; + } + case HW_VAR_AMPDU_FACTOR:{ + u8 factor_toset; + u8 regtoset; + u8 factorlevel[18] = { + 2, 4, 4, 7, 7, 13, 13, + 13, 2, 7, 7, 13, 13, + 15, 15, 15, 15, 0}; + u8 index = 0; + + factor_toset = *((u8 *) val); + if (factor_toset <= 3) { + factor_toset = (1 << (factor_toset + 2)); + if (factor_toset > 0xf) + factor_toset = 0xf; + + for (index = 0; index < 17; index++) { + if (factorlevel[index] > factor_toset) + factorlevel[index] = + factor_toset; + } + + for (index = 0; index < 8; index++) { + regtoset = ((factorlevel[index * 2]) | + (factorlevel[index * + 2 + 1] << 4)); + rtl_write_byte(rtlpriv, + AGGLEN_LMT_L + index, + regtoset); + } + + regtoset = ((factorlevel[16]) | + (factorlevel[17] << 4)); + rtl_write_byte(rtlpriv, AGGLEN_LMT_H, regtoset); + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + ("Set HW_VAR_AMPDU_FACTOR: %#x\n", + factor_toset)); + } + break; + } + case HW_VAR_AC_PARAM:{ + u8 e_aci = *((u8 *) val); + rtl92s_dm_init_edca_turbo(hw); + + if (rtlpci->acm_method != eAcmWay2_SW) + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_ACM_CTRL, + (u8 *)(&e_aci)); + break; + } + case HW_VAR_ACM_CTRL:{ + u8 e_aci = *((u8 *) val); + union aci_aifsn *p_aci_aifsn = (union aci_aifsn *)(&( + mac->ac[0].aifs)); + u8 acm = p_aci_aifsn->f.acm; + u8 acm_ctrl = rtl_read_byte(rtlpriv, AcmHwCtrl); + + acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? + 0x0 : 0x1); + + if (acm) { + switch (e_aci) { + case AC0_BE: + acm_ctrl |= AcmHw_BeqEn; + break; + case AC2_VI: + acm_ctrl |= AcmHw_ViqEn; + break; + case AC3_VO: + acm_ctrl |= AcmHw_VoqEn; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("HW_VAR_ACM_CTRL acm set " + "failed: eACI is %d\n", acm)); + break; + } + } else { + switch (e_aci) { + case AC0_BE: + acm_ctrl &= (~AcmHw_BeqEn); + break; + case AC2_VI: + acm_ctrl &= (~AcmHw_ViqEn); + break; + case AC3_VO: + acm_ctrl &= (~AcmHw_BeqEn); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + } + + RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, + ("HW_VAR_ACM_CTRL Write 0x%X\n", acm_ctrl)); + rtl_write_byte(rtlpriv, AcmHwCtrl, acm_ctrl); + break; + } + case HW_VAR_RCR:{ + rtl_write_dword(rtlpriv, RCR, ((u32 *) (val))[0]); + rtlpci->receive_config = ((u32 *) (val))[0]; + break; + } + case HW_VAR_RETRY_LIMIT:{ + u8 retry_limit = ((u8 *) (val))[0]; + + rtl_write_word(rtlpriv, RETRY_LIMIT, + retry_limit << RETRY_LIMIT_SHORT_SHIFT | + retry_limit << RETRY_LIMIT_LONG_SHIFT); + break; + } + case HW_VAR_DUAL_TSF_RST: { + break; + } + case HW_VAR_EFUSE_BYTES: { + rtlefuse->efuse_usedbytes = *((u16 *) val); + break; + } + case HW_VAR_EFUSE_USAGE: { + rtlefuse->efuse_usedpercentage = *((u8 *) val); + break; + } + case HW_VAR_IO_CMD: { + break; + } + case HW_VAR_WPA_CONFIG: { + rtl_write_byte(rtlpriv, REG_SECR, *((u8 *) val)); + break; + } + case HW_VAR_SET_RPWM:{ + break; + } + case HW_VAR_H2C_FW_PWRMODE:{ + break; + } + case HW_VAR_FW_PSMODE_STATUS: { + ppsc->fw_current_inpsmode = *((bool *) val); + break; + } + case HW_VAR_H2C_FW_JOINBSSRPT:{ + break; + } + case HW_VAR_AID:{ + break; + } + case HW_VAR_CORRECT_TSF:{ + break; + } + case HW_VAR_MRC: { + bool bmrc_toset = *((bool *)val); + u8 u1bdata = 0; + + if (bmrc_toset) { + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, + MASKBYTE0, 0x33); + u1bdata = (u8)rtl_get_bbreg(hw, + ROFDM1_TRXPATHENABLE, + MASKBYTE0); + rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, + MASKBYTE0, + ((u1bdata & 0xf0) | 0x03)); + u1bdata = (u8)rtl_get_bbreg(hw, + ROFDM0_TRXPATHENABLE, + MASKBYTE1); + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, + MASKBYTE1, + (u1bdata | 0x04)); + + /* Update current settings. */ + rtlpriv->dm.current_mrc_switch = bmrc_toset; + } else { + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, + MASKBYTE0, 0x13); + u1bdata = (u8)rtl_get_bbreg(hw, + ROFDM1_TRXPATHENABLE, + MASKBYTE0); + rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, + MASKBYTE0, + ((u1bdata & 0xf0) | 0x01)); + u1bdata = (u8)rtl_get_bbreg(hw, + ROFDM0_TRXPATHENABLE, + MASKBYTE1); + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, + MASKBYTE1, (u1bdata & 0xfb)); + + /* Update current settings. */ + rtlpriv->dm.current_mrc_switch = bmrc_toset; + } + + break; + } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + +} + +void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 sec_reg_value = 0x0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("PairwiseEncAlgorithm = %d " + "GroupEncAlgorithm = %d\n", + rtlpriv->sec.pairwise_enc_algorithm, + rtlpriv->sec.group_enc_algorithm)); + + if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("not open hw encryption\n")); + return; + } + + sec_reg_value = SCR_TXENCENABLE | SCR_RXENCENABLE; + + if (rtlpriv->sec.use_defaultkey) { + sec_reg_value |= SCR_TXUSEDK; + sec_reg_value |= SCR_RXUSEDK; + } + + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, ("The SECR-value %x\n", + sec_reg_value)); + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); + +} + +static u8 _rtl92ce_halset_sysclk(struct ieee80211_hw *hw, u8 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 waitcount = 100; + bool bresult = false; + u8 tmpvalue; + + rtl_write_byte(rtlpriv, SYS_CLKR + 1, data); + + /* Wait the MAC synchronized. */ + udelay(400); + + /* Check if it is set ready. */ + tmpvalue = rtl_read_byte(rtlpriv, SYS_CLKR + 1); + bresult = ((tmpvalue & BIT(7)) == (data & BIT(7))); + + if ((data & (BIT(6) | BIT(7))) == false) { + waitcount = 100; + tmpvalue = 0; + + while (1) { + waitcount--; + + tmpvalue = rtl_read_byte(rtlpriv, SYS_CLKR + 1); + if ((tmpvalue & BIT(6))) + break; + + printk(KERN_ERR "wait for BIT(6) return value %x\n", + tmpvalue); + if (waitcount == 0) + break; + + udelay(10); + } + + if (waitcount == 0) + bresult = false; + else + bresult = true; + } + + return bresult; +} + +void rtl8192se_gpiobit3_cfg_inputmode(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1tmp; + + /* The following config GPIO function */ + rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); + u1tmp = rtl_read_byte(rtlpriv, GPIO_IO_SEL); + + /* config GPIO3 to input */ + u1tmp &= HAL_8192S_HW_GPIO_OFF_MASK; + rtl_write_byte(rtlpriv, GPIO_IO_SEL, u1tmp); + +} + +static u8 _rtl92se_rf_onoff_detect(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1tmp; + u8 retval = ERFON; + + /* The following config GPIO function */ + rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); + u1tmp = rtl_read_byte(rtlpriv, GPIO_IO_SEL); + + /* config GPIO3 to input */ + u1tmp &= HAL_8192S_HW_GPIO_OFF_MASK; + rtl_write_byte(rtlpriv, GPIO_IO_SEL, u1tmp); + + /* On some of the platform, driver cannot read correct + * value without delay between Write_GPIO_SEL and Read_GPIO_IN */ + mdelay(10); + + /* check GPIO3 */ + u1tmp = rtl_read_byte(rtlpriv, GPIO_IN); + retval = (u1tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? ERFON : ERFOFF; + + return retval; +} + +static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + u8 i; + u8 tmpu1b; + u16 tmpu2b; + u8 pollingcnt = 20; + + if (rtlpci->first_init) { + /* Reset PCIE Digital */ + tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + tmpu1b &= 0xFE; + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b); + udelay(1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b | BIT(0)); + } + + /* Switch to SW IO control */ + tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); + if (tmpu1b & BIT(7)) { + tmpu1b &= ~(BIT(6) | BIT(7)); + + /* Set failed, return to prevent hang. */ + if (!_rtl92ce_halset_sysclk(hw, tmpu1b)) + return; + } + + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x0); + udelay(50); + rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); + udelay(50); + + /* Clear FW RPWM for FW control LPS.*/ + rtl_write_byte(rtlpriv, RPWM, 0x0); + + /* Reset MAC-IO and CPU and Core Digital BIT(10)/11/15 */ + tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + tmpu1b &= 0x73; + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b); + /* wait for BIT 10/11/15 to pull high automatically!! */ + mdelay(1); + + rtl_write_byte(rtlpriv, CMDR, 0); + rtl_write_byte(rtlpriv, TCR, 0); + + /* Data sheet not define 0x562!!! Copy from WMAC!!!!! */ + tmpu1b = rtl_read_byte(rtlpriv, 0x562); + tmpu1b |= 0x08; + rtl_write_byte(rtlpriv, 0x562, tmpu1b); + tmpu1b &= ~(BIT(3)); + rtl_write_byte(rtlpriv, 0x562, tmpu1b); + + /* Enable AFE clock source */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL); + rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, (tmpu1b | 0x01)); + /* Delay 1.5ms */ + mdelay(2); + tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL + 1); + rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, (tmpu1b & 0xfb)); + + /* Enable AFE Macro Block's Bandgap */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); + rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | BIT(0))); + mdelay(1); + + /* Enable AFE Mbias */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); + rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | 0x02)); + mdelay(1); + + /* Enable LDOA15 block */ + tmpu1b = rtl_read_byte(rtlpriv, LDOA15_CTRL); + rtl_write_byte(rtlpriv, LDOA15_CTRL, (tmpu1b | BIT(0))); + + /* Set Digital Vdd to Retention isolation Path. */ + tmpu2b = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL); + rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, (tmpu2b | BIT(11))); + + /* For warm reboot NIC disappera bug. */ + tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(13))); + + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x68); + + /* Enable AFE PLL Macro Block */ + /* We need to delay 100u before enabling PLL. */ + udelay(200); + tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); + + /* for divider reset */ + udelay(100); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | + BIT(4) | BIT(6))); + udelay(10); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); + udelay(10); + + /* Enable MAC 80MHZ clock */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL + 1); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, (tmpu1b | BIT(0))); + mdelay(1); + + /* Release isolation AFE PLL & MD */ + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, 0xA6); + + /* Enable MAC clock */ + tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); + rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b | BIT(12) | BIT(11))); + + /* Enable Core digital and enable IOREG R/W */ + tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11))); + + tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b & ~(BIT(7))); + + /* enable REG_EN */ + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15))); + + /* Switch the control path. */ + tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); + rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b & (~BIT(2)))); + + tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); + tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); + if (!_rtl92ce_halset_sysclk(hw, tmpu1b)) + return; /* Set failed, return to prevent hang. */ + + rtl_write_word(rtlpriv, CMDR, 0x07FC); + + /* MH We must enable the section of code to prevent load IMEM fail. */ + /* Load MAC register from WMAc temporarily We simulate macreg. */ + /* txt HW will provide MAC txt later */ + rtl_write_byte(rtlpriv, 0x6, 0x30); + rtl_write_byte(rtlpriv, 0x49, 0xf0); + + rtl_write_byte(rtlpriv, 0x4b, 0x81); + + rtl_write_byte(rtlpriv, 0xb5, 0x21); + + rtl_write_byte(rtlpriv, 0xdc, 0xff); + rtl_write_byte(rtlpriv, 0xdd, 0xff); + rtl_write_byte(rtlpriv, 0xde, 0xff); + rtl_write_byte(rtlpriv, 0xdf, 0xff); + + rtl_write_byte(rtlpriv, 0x11a, 0x00); + rtl_write_byte(rtlpriv, 0x11b, 0x00); + + for (i = 0; i < 32; i++) + rtl_write_byte(rtlpriv, INIMCS_SEL + i, 0x1b); + + rtl_write_byte(rtlpriv, 0x236, 0xff); + + rtl_write_byte(rtlpriv, 0x503, 0x22); + + if (ppsc->support_aspm && !ppsc->support_backdoor) + rtl_write_byte(rtlpriv, 0x560, 0x40); + else + rtl_write_byte(rtlpriv, 0x560, 0x00); + + rtl_write_byte(rtlpriv, DBG_PORT, 0x91); + + /* Set RX Desc Address */ + rtl_write_dword(rtlpriv, RDQDA, rtlpci->rx_ring[RX_MPDU_QUEUE].dma); + rtl_write_dword(rtlpriv, RCDA, rtlpci->rx_ring[RX_CMD_QUEUE].dma); + + /* Set TX Desc Address */ + rtl_write_dword(rtlpriv, TBKDA, rtlpci->tx_ring[BK_QUEUE].dma); + rtl_write_dword(rtlpriv, TBEDA, rtlpci->tx_ring[BE_QUEUE].dma); + rtl_write_dword(rtlpriv, TVIDA, rtlpci->tx_ring[VI_QUEUE].dma); + rtl_write_dword(rtlpriv, TVODA, rtlpci->tx_ring[VO_QUEUE].dma); + rtl_write_dword(rtlpriv, TBDA, rtlpci->tx_ring[BEACON_QUEUE].dma); + rtl_write_dword(rtlpriv, TCDA, rtlpci->tx_ring[TXCMD_QUEUE].dma); + rtl_write_dword(rtlpriv, TMDA, rtlpci->tx_ring[MGNT_QUEUE].dma); + rtl_write_dword(rtlpriv, THPDA, rtlpci->tx_ring[HIGH_QUEUE].dma); + rtl_write_dword(rtlpriv, HDA, rtlpci->tx_ring[HCCA_QUEUE].dma); + + rtl_write_word(rtlpriv, CMDR, 0x37FC); + + /* To make sure that TxDMA can ready to download FW. */ + /* We should reset TxDMA if IMEM RPT was not ready. */ + do { + tmpu1b = rtl_read_byte(rtlpriv, TCR); + if ((tmpu1b & TXDMA_INIT_VALUE) == TXDMA_INIT_VALUE) + break; + + udelay(5); + } while (pollingcnt--); + + if (pollingcnt <= 0) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Polling TXDMA_INIT_VALUE " + "timeout!! Current TCR(%#x)\n", tmpu1b)); + tmpu1b = rtl_read_byte(rtlpriv, CMDR); + rtl_write_byte(rtlpriv, CMDR, tmpu1b & (~TXDMA_EN)); + udelay(2); + /* Reset TxDMA */ + rtl_write_byte(rtlpriv, CMDR, tmpu1b | TXDMA_EN); + } + + /* After MACIO reset,we must refresh LED state. */ + if ((ppsc->rfoff_reason == RF_CHANGE_BY_IPS) || + (ppsc->rfoff_reason == 0)) { + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + enum rf_pwrstate rfpwr_state_toset; + rfpwr_state_toset = _rtl92se_rf_onoff_detect(hw); + + if (rfpwr_state_toset == ERFON) + rtl92se_sw_led_on(hw, pLed0); + } +} + +static void _rtl92se_macconfig_after_fwdownload(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 i; + u16 tmpu2b; + + /* 1. System Configure Register (Offset: 0x0000 - 0x003F) */ + + /* 2. Command Control Register (Offset: 0x0040 - 0x004F) */ + /* Turn on 0x40 Command register */ + rtl_write_word(rtlpriv, CMDR, (BBRSTN | BB_GLB_RSTN | + SCHEDULE_EN | MACRXEN | MACTXEN | DDMA_EN | FW2HW_EN | + RXDMA_EN | TXDMA_EN | HCI_RXDMA_EN | HCI_TXDMA_EN)); + + /* Set TCR TX DMA pre 2 FULL enable bit */ + rtl_write_dword(rtlpriv, TCR, rtl_read_dword(rtlpriv, TCR) | + TXDMAPRE2FULL); + + /* Set RCR */ + rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config); + + /* 3. MACID Setting Register (Offset: 0x0050 - 0x007F) */ + + /* 4. Timing Control Register (Offset: 0x0080 - 0x009F) */ + /* Set CCK/OFDM SIFS */ + /* CCK SIFS shall always be 10us. */ + rtl_write_word(rtlpriv, SIFS_CCK, 0x0a0a); + rtl_write_word(rtlpriv, SIFS_OFDM, 0x1010); + + /* Set AckTimeout */ + rtl_write_byte(rtlpriv, ACK_TIMEOUT, 0x40); + + /* Beacon related */ + rtl_write_word(rtlpriv, BCN_INTERVAL, 100); + rtl_write_word(rtlpriv, ATIMWND, 2); + + /* 5. FIFO Control Register (Offset: 0x00A0 - 0x015F) */ + /* 5.1 Initialize Number of Reserved Pages in Firmware Queue */ + /* Firmware allocate now, associate with FW internal setting.!!! */ + + /* 5.2 Setting TX/RX page size 0/1/2/3/4=64/128/256/512/1024 */ + /* 5.3 Set driver info, we only accept PHY status now. */ + /* 5.4 Set RXDMA arbitration to control RXDMA/MAC/FW R/W for RXFIFO */ + rtl_write_byte(rtlpriv, RXDMA, rtl_read_byte(rtlpriv, RXDMA) | BIT(6)); + + /* 6. Adaptive Control Register (Offset: 0x0160 - 0x01CF) */ + /* Set RRSR to all legacy rate and HT rate + * CCK rate is supported by default. + * CCK rate will be filtered out only when associated + * AP does not support it. + * Only enable ACK rate to OFDM 24M + * Disable RRSR for CCK rate in A-Cut */ + + if (rtlhal->version == VERSION_8192S_ACUT) + rtl_write_byte(rtlpriv, RRSR, 0xf0); + else if (rtlhal->version == VERSION_8192S_BCUT) + rtl_write_byte(rtlpriv, RRSR, 0xff); + rtl_write_byte(rtlpriv, RRSR + 1, 0x01); + rtl_write_byte(rtlpriv, RRSR + 2, 0x00); + + /* A-Cut IC do not support CCK rate. We forbid ARFR to */ + /* fallback to CCK rate */ + for (i = 0; i < 8; i++) { + /*Disable RRSR for CCK rate in A-Cut */ + if (rtlhal->version == VERSION_8192S_ACUT) + rtl_write_dword(rtlpriv, ARFR0 + i * 4, 0x1f0ff0f0); + } + + /* Different rate use different AMPDU size */ + /* MCS32/ MCS15_SG use max AMPDU size 15*2=30K */ + rtl_write_byte(rtlpriv, AGGLEN_LMT_H, 0x0f); + /* MCS0/1/2/3 use max AMPDU size 4*2=8K */ + rtl_write_word(rtlpriv, AGGLEN_LMT_L, 0x7442); + /* MCS4/5 use max AMPDU size 8*2=16K 6/7 use 10*2=20K */ + rtl_write_word(rtlpriv, AGGLEN_LMT_L + 2, 0xddd7); + /* MCS8/9 use max AMPDU size 8*2=16K 10/11 use 10*2=20K */ + rtl_write_word(rtlpriv, AGGLEN_LMT_L + 4, 0xd772); + /* MCS12/13/14/15 use max AMPDU size 15*2=30K */ + rtl_write_word(rtlpriv, AGGLEN_LMT_L + 6, 0xfffd); + + /* Set Data / Response auto rate fallack retry count */ + rtl_write_dword(rtlpriv, DARFRC, 0x04010000); + rtl_write_dword(rtlpriv, DARFRC + 4, 0x09070605); + rtl_write_dword(rtlpriv, RARFRC, 0x04010000); + rtl_write_dword(rtlpriv, RARFRC + 4, 0x09070605); + + /* 7. EDCA Setting Register (Offset: 0x01D0 - 0x01FF) */ + /* Set all rate to support SG */ + rtl_write_word(rtlpriv, SG_RATE, 0xFFFF); + + /* 8. WMAC, BA, and CCX related Register (Offset: 0x0200 - 0x023F) */ + /* Set NAV protection length */ + rtl_write_word(rtlpriv, NAV_PROT_LEN, 0x0080); + /* CF-END Threshold */ + rtl_write_byte(rtlpriv, CFEND_TH, 0xFF); + /* Set AMPDU minimum space */ + rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, 0x07); + /* Set TXOP stall control for several queue/HI/BCN/MGT/ */ + rtl_write_byte(rtlpriv, TXOP_STALL_CTRL, 0x00); + + /* 9. Security Control Register (Offset: 0x0240 - 0x025F) */ + /* 10. Power Save Control Register (Offset: 0x0260 - 0x02DF) */ + /* 11. General Purpose Register (Offset: 0x02E0 - 0x02FF) */ + /* 12. Host Interrupt Status Register (Offset: 0x0300 - 0x030F) */ + /* 13. Test Mode and Debug Control Register (Offset: 0x0310 - 0x034F) */ + + /* 14. Set driver info, we only accept PHY status now. */ + rtl_write_byte(rtlpriv, RXDRVINFO_SZ, 4); + + /* 15. For EEPROM R/W Workaround */ + /* 16. For EFUSE to share REG_SYS_FUNC_EN with EEPROM!!! */ + tmpu2b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, tmpu2b | BIT(13)); + tmpu2b = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL); + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, tmpu2b & (~BIT(8))); + + /* 17. For EFUSE */ + /* We may R/W EFUSE in EEPROM mode */ + if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { + u8 tempval; + + tempval = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL + 1); + tempval &= 0xFE; + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, tempval); + + /* Change Program timing */ + rtl_write_byte(rtlpriv, REG_EFUSE_CTRL + 3, 0x72); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("EFUSE CONFIG OK\n")); + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("OK\n")); + +} + +static void _rtl92se_hw_configure(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + u8 reg_bw_opmode = 0; + u32 reg_ratr = 0, reg_rrsr = 0; + u8 regtmp = 0; + + reg_bw_opmode = BW_OPMODE_20MHZ; + reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | + RATE_ALL_OFDM_2SS; + reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + + regtmp = rtl_read_byte(rtlpriv, INIRTSMCS_SEL); + reg_rrsr = ((reg_rrsr & 0x000fffff) << 8) | regtmp; + rtl_write_dword(rtlpriv, INIRTSMCS_SEL, reg_rrsr); + rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); + + /* Set Retry Limit here */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT, + (u8 *)(&rtlpci->shortretry_limit)); + + rtl_write_byte(rtlpriv, MLT, 0x8f); + + /* For Min Spacing configuration. */ + switch (rtlphy->rf_type) { + case RF_1T2R: + case RF_1T1R: + rtlhal->minspace_cfg = (MAX_MSS_DENSITY_1T << 3); + break; + case RF_2T2R: + case RF_2T2R_GREEN: + rtlhal->minspace_cfg = (MAX_MSS_DENSITY_2T << 3); + break; + } + rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, rtlhal->minspace_cfg); +} + +int rtl92se_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 tmp_byte = 0; + + bool rtstatus = true; + u8 tmp_u1b; + int err = false; + u8 i; + int wdcapra_add[] = { + EDCAPARA_BE, EDCAPARA_BK, + EDCAPARA_VI, EDCAPARA_VO}; + u8 secr_value = 0x0; + + rtlpci->being_init_adapter = true; + + rtlpriv->intf_ops->disable_aspm(hw); + + /* 1. MAC Initialize */ + /* Before FW download, we have to set some MAC register */ + _rtl92se_macconfig_before_fwdownload(hw); + + rtlhal->version = (enum version_8192s)((rtl_read_dword(rtlpriv, + PMC_FSM) >> 16) & 0xF); + + rtl8192se_gpiobit3_cfg_inputmode(hw); + + /* 2. download firmware */ + rtstatus = rtl92s_download_fw(hw); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("Failed to download FW. " + "Init HW without FW now.., Please copy FW into" + "/lib/firmware/rtlwifi\n")); + rtlhal->fw_ready = false; + } else { + rtlhal->fw_ready = true; + } + + /* After FW download, we have to reset MAC register */ + _rtl92se_macconfig_after_fwdownload(hw); + + /*Retrieve default FW Cmd IO map. */ + rtlhal->fwcmd_iomap = rtl_read_word(rtlpriv, LBUS_MON_ADDR); + rtlhal->fwcmd_ioparam = rtl_read_dword(rtlpriv, LBUS_ADDR_MASK); + + /* 3. Initialize MAC/PHY Config by MACPHY_reg.txt */ + if (rtl92s_phy_mac_config(hw) != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("MAC Config failed\n")); + return rtstatus; + } + + /* Make sure BB/RF write OK. We should prevent enter IPS. radio off. */ + /* We must set flag avoid BB/RF config period later!! */ + rtl_write_dword(rtlpriv, CMDR, 0x37FC); + + /* 4. Initialize BB After MAC Config PHY_reg.txt, AGC_Tab.txt */ + if (rtl92s_phy_bb_config(hw) != true) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, ("BB Config failed\n")); + return rtstatus; + } + + /* 5. Initiailze RF RAIO_A.txt RF RAIO_B.txt */ + /* Before initalizing RF. We can not use FW to do RF-R/W. */ + + rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; + + /* RF Power Save */ +#if 0 + /* H/W or S/W RF OFF before sleep. */ + if (rtlpriv->psc.rfoff_reason > RF_CHANGE_BY_PS) { + u32 rfoffreason = rtlpriv->psc.rfoff_reason; + + rtlpriv->psc.rfoff_reason = RF_CHANGE_BY_INIT; + rtlpriv->psc.rfpwr_state = ERFON; + rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason, true); + } else { + /* gpio radio on/off is out of adapter start */ + if (rtlpriv->psc.hwradiooff == false) { + rtlpriv->psc.rfpwr_state = ERFON; + rtlpriv->psc.rfoff_reason = 0; + } + } +#endif + + /* Before RF-R/W we must execute the IO from Scott's suggestion. */ + rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, 0xDB); + if (rtlhal->version == VERSION_8192S_ACUT) + rtl_write_byte(rtlpriv, SPS1_CTRL + 3, 0x07); + else + rtl_write_byte(rtlpriv, RF_CTRL, 0x07); + + if (rtl92s_phy_rf_config(hw) != true) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("RF Config failed\n")); + return rtstatus; + } + + /* After read predefined TXT, we must set BB/MAC/RF + * register as our requirement */ + + rtlphy->rfreg_chnlval[0] = rtl92s_phy_query_rf_reg(hw, + (enum radio_path)0, + RF_CHNLBW, + RFREG_OFFSET_MASK); + rtlphy->rfreg_chnlval[1] = rtl92s_phy_query_rf_reg(hw, + (enum radio_path)1, + RF_CHNLBW, + RFREG_OFFSET_MASK); + + /*---- Set CCK and OFDM Block "ON"----*/ + rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); + + /*3 Set Hardware(Do nothing now) */ + _rtl92se_hw_configure(hw); + + /* Read EEPROM TX power index and PHY_REG_PG.txt to capture correct */ + /* TX power index for different rate set. */ + /* Get original hw reg values */ + rtl92s_phy_get_hw_reg_originalvalue(hw); + /* Write correct tx power index */ + rtl92s_phy_set_txpower(hw, rtlphy->current_channel); + + /* We must set MAC address after firmware download. */ + for (i = 0; i < 6; i++) + rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]); + + /* EEPROM R/W workaround */ + tmp_u1b = rtl_read_byte(rtlpriv, MAC_PINMUX_CFG); + rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, tmp_u1b & (~BIT(3))); + + rtl_write_byte(rtlpriv, 0x4d, 0x0); + + if (hal_get_firmwareversion(rtlpriv) >= 0x49) { + tmp_byte = rtl_read_byte(rtlpriv, FW_RSVD_PG_CRTL) & (~BIT(4)); + tmp_byte = tmp_byte | BIT(5); + rtl_write_byte(rtlpriv, FW_RSVD_PG_CRTL, tmp_byte); + rtl_write_dword(rtlpriv, TXDESC_MSK, 0xFFFFCFFF); + } + + /* We enable high power and RA related mechanism after NIC + * initialized. */ + rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT); + + /* Add to prevent ASPM bug. */ + /* Always enable hst and NIC clock request. */ + rtl92s_phy_switch_ephy_parameter(hw); + + /* Security related + * 1. Clear all H/W keys. + * 2. Enable H/W encryption/decryption. */ + rtl_cam_reset_all_entry(hw); + secr_value |= SCR_TXENCENABLE; + secr_value |= SCR_RXENCENABLE; + secr_value |= SCR_NOSKMC; + rtl_write_byte(rtlpriv, REG_SECR, secr_value); + + for (i = 0; i < 4; i++) + rtl_write_dword(rtlpriv, wdcapra_add[i], 0x5e4322); + + if (rtlphy->rf_type == RF_1T2R) { + bool mrc2set = true; + /* Turn on B-Path */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC, (u8 *)&mrc2set); + } + + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_ON); + rtl92s_dm_init(hw); + rtlpci->being_init_adapter = false; + + return err; +} + +void rtl92se_set_mac_addr(struct rtl_io *io, const u8 * addr) +{ +} + +void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 reg_rcr = rtlpci->receive_config; + + if (rtlpriv->psc.rfpwr_state != ERFON) + return; + + if (check_bssid == true) { + reg_rcr |= (RCR_CBSSID); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); + } else if (check_bssid == false) { + reg_rcr &= (~RCR_CBSSID); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); + } + +} + +static int _rtl92se_set_media_status(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bt_msr = rtl_read_byte(rtlpriv, MSR); + enum led_ctl_mode ledaction = LED_CTL_NO_LINK; + u32 temp; + bt_msr &= ~MSR_LINK_MASK; + + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + bt_msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT); + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Set Network type to NO LINK!\n")); + break; + case NL80211_IFTYPE_ADHOC: + bt_msr |= (MSR_LINK_ADHOC << MSR_LINK_SHIFT); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Set Network type to Ad Hoc!\n")); + break; + case NL80211_IFTYPE_STATION: + bt_msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT); + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Set Network type to STA!\n")); + break; + case NL80211_IFTYPE_AP: + bt_msr |= (MSR_LINK_MASTER << MSR_LINK_SHIFT); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + ("Set Network type to AP!\n")); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Network type %d not support!\n", type)); + return 1; + break; + + } + + rtl_write_byte(rtlpriv, (MSR), bt_msr); + + temp = rtl_read_dword(rtlpriv, TCR); + rtl_write_dword(rtlpriv, TCR, temp & (~BIT(8))); + rtl_write_dword(rtlpriv, TCR, temp | BIT(8)); + + + return 0; +} + +/* HW_VAR_MEDIA_STATUS & HW_VAR_CECHK_BSSID */ +int rtl92se_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (_rtl92se_set_media_status(hw, type)) + return -EOPNOTSUPP; + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + if (type != NL80211_IFTYPE_AP) + rtl92se_set_check_bssid(hw, true); + } else { + rtl92se_set_check_bssid(hw, false); + } + + return 0; +} + +/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ +void rtl92se_set_qos(struct ieee80211_hw *hw, int aci) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + rtl92s_dm_init_edca_turbo(hw); + + switch (aci) { + case AC1_BK: + rtl_write_dword(rtlpriv, EDCAPARA_BK, 0xa44f); + break; + case AC0_BE: + /* rtl_write_dword(rtlpriv, EDCAPARA_BE, u4b_ac_param); */ + break; + case AC2_VI: + rtl_write_dword(rtlpriv, EDCAPARA_VI, 0x5e4322); + break; + case AC3_VO: + rtl_write_dword(rtlpriv, EDCAPARA_VO, 0x2f3222); + break; + default: + RT_ASSERT(false, ("invalid aci: %d !\n", aci)); + break; + } +} + +void rtl92se_enable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]); + /* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */ + rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F); + + rtlpci->irq_enabled = true; +} + +void rtl92se_disable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, INTA_MASK, 0); + rtl_write_dword(rtlpriv, INTA_MASK + 4, 0); + + rtlpci->irq_enabled = false; +} + + +static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 waitcnt = 100; + bool result = false; + u8 tmp; + + rtl_write_byte(rtlpriv, SYS_CLKR + 1, data); + + /* Wait the MAC synchronized. */ + udelay(400); + + /* Check if it is set ready. */ + tmp = rtl_read_byte(rtlpriv, SYS_CLKR + 1); + result = ((tmp & BIT(7)) == (data & BIT(7))); + + if ((data & (BIT(6) | BIT(7))) == false) { + waitcnt = 100; + tmp = 0; + + while (1) { + waitcnt--; + tmp = rtl_read_byte(rtlpriv, SYS_CLKR + 1); + + if ((tmp & BIT(6))) + break; + + printk(KERN_ERR "wait for BIT(6) return value %x\n", + tmp); + + if (waitcnt == 0) + break; + udelay(10); + } + + if (waitcnt == 0) + result = false; + else + result = true; + } + + return result; +} + +static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 u1btmp; + + if (rtlhal->driver_going2unload) + rtl_write_byte(rtlpriv, 0x560, 0x0); + + /* Power save for BB/RF */ + u1btmp = rtl_read_byte(rtlpriv, LDOV12D_CTRL); + u1btmp |= BIT(0); + rtl_write_byte(rtlpriv, LDOV12D_CTRL, u1btmp); + rtl_write_byte(rtlpriv, SPS1_CTRL, 0x0); + rtl_write_byte(rtlpriv, TXPAUSE, 0xFF); + rtl_write_word(rtlpriv, CMDR, 0x57FC); + udelay(100); + rtl_write_word(rtlpriv, CMDR, 0x77FC); + rtl_write_byte(rtlpriv, PHY_CCA, 0x0); + udelay(10); + rtl_write_word(rtlpriv, CMDR, 0x37FC); + udelay(10); + rtl_write_word(rtlpriv, CMDR, 0x77FC); + udelay(10); + rtl_write_word(rtlpriv, CMDR, 0x57FC); + rtl_write_word(rtlpriv, CMDR, 0x0000); + + if (rtlhal->driver_going2unload) { + u1btmp = rtl_read_byte(rtlpriv, (REG_SYS_FUNC_EN + 1)); + u1btmp &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1btmp); + } + + u1btmp = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); + + /* Add description. After switch control path. register + * after page1 will be invisible. We can not do any IO + * for register>0x40. After resume&MACIO reset, we need + * to remember previous reg content. */ + if (u1btmp & BIT(7)) { + u1btmp &= ~(BIT(6) | BIT(7)); + if (!_rtl92s_set_sysclk(hw, u1btmp)) { + printk(KERN_ERR "Switch ctrl path fail\n"); + return; + } + } + + /* Power save for MAC */ + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS && + !rtlhal->driver_going2unload) { + /* enable LED function */ + rtl_write_byte(rtlpriv, 0x03, 0xF9); + /* SW/HW radio off or halt adapter!! For example S3/S4 */ + } else { + /* LED function disable. Power range is about 8mA now. */ + /* if write 0xF1 disconnet_pci power + * ifconfig wlan0 down power are both high 35:70 */ + /* if write oxF9 disconnet_pci power + * ifconfig wlan0 down power are both low 12:45*/ + rtl_write_byte(rtlpriv, 0x03, 0xF9); + } + + rtl_write_byte(rtlpriv, SYS_CLKR + 1, 0x70); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, 0x68); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x00); + rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); + rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, 0x0E); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + +} + +static void _rtl92se_gen_refreshledstate(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + + if (rtlpci->up_first_time == 1) + return; + + if (rtlpriv->psc.rfoff_reason == RF_CHANGE_BY_IPS) + rtl92se_sw_led_on(hw, pLed0); + else + rtl92se_sw_led_off(hw, pLed0); +} + + +static void _rtl92se_power_domain_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 tmpu2b; + u8 tmpu1b; + + rtlpriv->psc.pwrdomain_protect = true; + + tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); + if (tmpu1b & BIT(7)) { + tmpu1b &= ~(BIT(6) | BIT(7)); + if (!_rtl92s_set_sysclk(hw, tmpu1b)) { + rtlpriv->psc.pwrdomain_protect = false; + return; + } + } + + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x0); + rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); + + /* Reset MAC-IO and CPU and Core Digital BIT10/11/15 */ + tmpu1b = rtl_read_byte(rtlpriv, SYS_FUNC_EN + 1); + + /* If IPS we need to turn LED on. So we not + * not disable BIT 3/7 of reg3. */ + if (rtlpriv->psc.rfoff_reason & (RF_CHANGE_BY_IPS | RF_CHANGE_BY_HW)) + tmpu1b &= 0xFB; + else + tmpu1b &= 0x73; + + rtl_write_byte(rtlpriv, SYS_FUNC_EN + 1, tmpu1b); + /* wait for BIT 10/11/15 to pull high automatically!! */ + mdelay(1); + + rtl_write_byte(rtlpriv, CMDR, 0); + rtl_write_byte(rtlpriv, TCR, 0); + + /* Data sheet not define 0x562!!! Copy from WMAC!!!!! */ + tmpu1b = rtl_read_byte(rtlpriv, 0x562); + tmpu1b |= 0x08; + rtl_write_byte(rtlpriv, 0x562, tmpu1b); + tmpu1b &= ~(BIT(3)); + rtl_write_byte(rtlpriv, 0x562, tmpu1b); + + /* Enable AFE clock source */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL); + rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, (tmpu1b | 0x01)); + /* Delay 1.5ms */ + udelay(1500); + tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL + 1); + rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, (tmpu1b & 0xfb)); + + /* Enable AFE Macro Block's Bandgap */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); + rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | BIT(0))); + mdelay(1); + + /* Enable AFE Mbias */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); + rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | 0x02)); + mdelay(1); + + /* Enable LDOA15 block */ + tmpu1b = rtl_read_byte(rtlpriv, LDOA15_CTRL); + rtl_write_byte(rtlpriv, LDOA15_CTRL, (tmpu1b | BIT(0))); + + /* Set Digital Vdd to Retention isolation Path. */ + tmpu2b = rtl_read_word(rtlpriv, SYS_ISO_CTRL); + rtl_write_word(rtlpriv, SYS_ISO_CTRL, (tmpu2b | BIT(11))); + + + /* For warm reboot NIC disappera bug. */ + tmpu2b = rtl_read_word(rtlpriv, SYS_FUNC_EN); + rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(13))); + + rtl_write_byte(rtlpriv, SYS_ISO_CTRL + 1, 0x68); + + /* Enable AFE PLL Macro Block */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); + /* Enable MAC 80MHZ clock */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL + 1); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, (tmpu1b | BIT(0))); + mdelay(1); + + /* Release isolation AFE PLL & MD */ + rtl_write_byte(rtlpriv, SYS_ISO_CTRL, 0xA6); + + /* Enable MAC clock */ + tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); + rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b | BIT(12) | BIT(11))); + + /* Enable Core digital and enable IOREG R/W */ + tmpu2b = rtl_read_word(rtlpriv, SYS_FUNC_EN); + rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(11))); + /* enable REG_EN */ + rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15))); + + /* Switch the control path. */ + tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); + rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b & (~BIT(2)))); + + tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); + tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); + if (!_rtl92s_set_sysclk(hw, tmpu1b)) { + rtlpriv->psc.pwrdomain_protect = false; + return; + } + + rtl_write_word(rtlpriv, CMDR, 0x37FC); + + /* After MACIO reset,we must refresh LED state. */ + _rtl92se_gen_refreshledstate(hw); + + rtlpriv->psc.pwrdomain_protect = false; +} + +void rtl92se_card_disable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + enum nl80211_iftype opmode; + u8 wait = 30; + + rtlpriv->intf_ops->enable_aspm(hw); + + if (rtlpci->driver_is_goingto_unload || + ppsc->rfoff_reason > RF_CHANGE_BY_PS) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); + + /* we should chnge GPIO to input mode + * this will drop away current about 25mA*/ + rtl8192se_gpiobit3_cfg_inputmode(hw); + + /* this is very important for ips power save */ + while (wait-- >= 10 && rtlpriv->psc.pwrdomain_protect) { + if (rtlpriv->psc.pwrdomain_protect) + mdelay(20); + else + break; + } + + mac->link_state = MAC80211_NOLINK; + opmode = NL80211_IFTYPE_UNSPECIFIED; + _rtl92se_set_media_status(hw, opmode); + + _rtl92s_phy_set_rfhalt(hw); + udelay(100); +} + +void rtl92se_interrupt_recognized(struct ieee80211_hw *hw, u32 *p_inta, + u32 *p_intb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; + rtl_write_dword(rtlpriv, ISR, *p_inta); + + *p_intb = rtl_read_dword(rtlpriv, ISR + 4) & rtlpci->irq_mask[1]; + rtl_write_dword(rtlpriv, ISR + 4, *p_intb); +} + +void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcntime_cfg = 0; + u16 bcn_cw = 6, bcn_ifs = 0xf; + u16 atim_window = 2; + + /* ATIM Window (in unit of TU). */ + rtl_write_word(rtlpriv, ATIMWND, atim_window); + + /* Beacon interval (in unit of TU). */ + rtl_write_word(rtlpriv, BCN_INTERVAL, mac->beacon_interval); + + /* DrvErlyInt (in unit of TU). (Time to send + * interrupt to notify driver to change + * beacon content) */ + rtl_write_word(rtlpriv, BCN_DRV_EARLY_INT, 10 << 4); + + /* BcnDMATIM(in unit of us). Indicates the + * time before TBTT to perform beacon queue DMA */ + rtl_write_word(rtlpriv, BCN_DMATIME, 256); + + /* Force beacon frame transmission even + * after receiving beacon frame from + * other ad hoc STA */ + rtl_write_byte(rtlpriv, BCN_ERR_THRESH, 100); + + /* Beacon Time Configuration */ + if (mac->opmode == NL80211_IFTYPE_ADHOC) + bcntime_cfg |= (bcn_cw << BCN_TCFG_CW_SHIFT); + + /* TODO: bcn_ifs may required to be changed on ASIC */ + bcntime_cfg |= bcn_ifs << BCN_TCFG_IFS; + + /*for beacon changed */ + rtl92s_phy_set_beacon_hwreg(hw, mac->beacon_interval); +} + +void rtl92se_set_beacon_interval(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval = mac->beacon_interval; + + /* Beacon interval (in unit of TU). */ + rtl_write_word(rtlpriv, BCN_INTERVAL, bcn_interval); + /* 2008.10.24 added by tynli for beacon changed. */ + rtl92s_phy_set_beacon_hwreg(hw, bcn_interval); +} + +void rtl92se_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, + ("add_msr:%x, rm_msr:%x\n", add_msr, rm_msr)); + + if (add_msr) + rtlpci->irq_mask[0] |= add_msr; + + if (rm_msr) + rtlpci->irq_mask[0] &= (~rm_msr); + + rtl92se_disable_interrupt(hw); + rtl92se_enable_interrupt(hw); +} + +static void _rtl8192se_get_IC_Inferiority(struct ieee80211_hw *hw) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 efuse_id; + + rtlhal->ic_class = IC_INFERIORITY_A; + + /* Only retrieving while using EFUSE. */ + if ((rtlefuse->epromtype == EEPROM_BOOT_EFUSE) && + !rtlefuse->autoload_failflag) { + efuse_id = efuse_read_1byte(hw, EFUSE_IC_ID_OFFSET); + + if (efuse_id == 0xfe) + rtlhal->ic_class = IC_INFERIORITY_B; + } +} + +static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u16 i, usvalue; + u16 eeprom_id; + u8 tempval; + u8 hwinfo[HWSET_MAX_SIZE_92S]; + u8 rf_path, index; + + if (rtlefuse->epromtype == EEPROM_93C46) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("RTL819X Not boot from eeprom, check it !!")); + } else if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { + rtl_efuse_shadow_map_update(hw); + + memcpy((void *)hwinfo, (void *) + &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + HWSET_MAX_SIZE_92S); + } + + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"), + hwinfo, HWSET_MAX_SIZE_92S); + + eeprom_id = *((u16 *)&hwinfo[0]); + if (eeprom_id != RTL8190_EEPROM_ID) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("EEPROM ID(%#x) is invalid!!\n", eeprom_id)); + rtlefuse->autoload_failflag = true; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n")); + rtlefuse->autoload_failflag = false; + } + + if (rtlefuse->autoload_failflag == true) + return; + + _rtl8192se_get_IC_Inferiority(hw); + + /* Read IC Version && Channel Plan */ + /* VID, DID SE 0xA-D */ + rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; + rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; + rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; + rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; + rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("EEPROMId = 0x%4x\n", eeprom_id)); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid)); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did)); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid)); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid)); + + for (i = 0; i < 6; i += 2) { + usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; + *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; + } + + for (i = 0; i < 6; i++) + rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr))); + + /* Get Tx Power Level by Channel */ + /* Read Tx power of Channel 1 ~ 14 from EEPROM. */ + /* 92S suupport RF A & B */ + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 3; i++) { + /* Read CCK RF A & B Tx power */ + rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][i] = + hwinfo[EEPROM_TXPOWERBASE + rf_path * 3 + i]; + + /* Read OFDM RF A & B Tx power for 1T */ + rtlefuse->eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = + hwinfo[EEPROM_TXPOWERBASE + 6 + rf_path * 3 + i]; + + /* Read OFDM RF A & B Tx power for 2T */ + rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][i] + = hwinfo[EEPROM_TXPOWERBASE + 12 + + rf_path * 3 + i]; + } + } + + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + ("RF(%d) EEPROM CCK Area(%d) = 0x%x\n", rf_path, + i, rtlefuse->eeprom_chnlarea_txpwr_cck + [rf_path][i])); + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + ("RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse->eeprom_chnlarea_txpwr_ht40_1s + [rf_path][i])); + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + ("RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif + [rf_path][i])); + + for (rf_path = 0; rf_path < 2; rf_path++) { + + /* Assign dedicated channel tx power */ + for (i = 0; i < 14; i++) { + /* channel 1~3 use the same Tx Power Level. */ + if (i < 3) + index = 0; + /* Channel 4-8 */ + else if (i < 8) + index = 1; + /* Channel 9-14 */ + else + index = 2; + + /* Record A & B CCK /OFDM - 1T/2T Channel area + * tx power */ + rtlefuse->txpwrlevel_cck[rf_path][i] = + rtlefuse->eeprom_chnlarea_txpwr_cck + [rf_path][index]; + rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = + rtlefuse->eeprom_chnlarea_txpwr_ht40_1s + [rf_path][index]; + rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = + rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif + [rf_path][index]; + } + + for (i = 0; i < 14; i++) { + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = " + "[0x%x / 0x%x / 0x%x]\n", rf_path, i, + rtlefuse->txpwrlevel_cck[rf_path][i], + rtlefuse->txpwrlevel_ht40_1s[rf_path][i], + rtlefuse->txpwrlevel_ht40_2s[rf_path][i])); + } + } + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 3; i++) { + /* Read Power diff limit. */ + rtlefuse->eeprom_pwrgroup[rf_path][i] = + hwinfo[EEPROM_TXPWRGROUP + rf_path * 3 + i]; + } + } + + for (rf_path = 0; rf_path < 2; rf_path++) { + /* Fill Pwr group */ + for (i = 0; i < 14; i++) { + /* Chanel 1-3 */ + if (i < 3) + index = 0; + /* Channel 4-8 */ + else if (i < 8) + index = 1; + /* Channel 9-13 */ + else + index = 2; + + rtlefuse->pwrgroup_ht20[rf_path][i] = + (rtlefuse->eeprom_pwrgroup[rf_path][index] & + 0xf); + rtlefuse->pwrgroup_ht40[rf_path][i] = + ((rtlefuse->eeprom_pwrgroup[rf_path][index] & + 0xf0) >> 4); + + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF-%d pwrgroup_ht20[%d] = 0x%x\n", + rf_path, i, + rtlefuse->pwrgroup_ht20[rf_path][i])); + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF-%d pwrgroup_ht40[%d] = 0x%x\n", + rf_path, i, + rtlefuse->pwrgroup_ht40[rf_path][i])); + } + } + + for (i = 0; i < 14; i++) { + /* Read tx power difference between HT OFDM 20/40 MHZ */ + /* channel 1-3 */ + if (i < 3) + index = 0; + /* Channel 4-8 */ + else if (i < 8) + index = 1; + /* Channel 9-14 */ + else + index = 2; + + tempval = (*(u8 *)&hwinfo[EEPROM_TX_PWR_HT20_DIFF + + index]) & 0xff; + rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF); + rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] = + ((tempval >> 4) & 0xF); + + /* Read OFDM<->HT tx power diff */ + /* Channel 1-3 */ + if (i < 3) + index = 0; + /* Channel 4-8 */ + else if (i < 8) + index = 0x11; + /* Channel 9-14 */ + else + index = 1; + + tempval = (*(u8 *)&hwinfo[EEPROM_TX_PWR_OFDM_DIFF + index]) + & 0xff; + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = + (tempval & 0xF); + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] = + ((tempval >> 4) & 0xF); + + tempval = (*(u8 *)&hwinfo[TX_PWR_SAFETY_CHK]); + rtlefuse->txpwr_safetyflag = (tempval & 0x01); + } + + rtlefuse->eeprom_regulatory = 0; + if (rtlefuse->eeprom_version >= 2) { + /* BIT(0)~2 */ + if (rtlefuse->eeprom_version >= 4) + rtlefuse->eeprom_regulatory = + (hwinfo[EEPROM_REGULATORY] & 0x7); + else /* BIT(0) */ + rtlefuse->eeprom_regulatory = + (hwinfo[EEPROM_REGULATORY] & 0x1); + } + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory)); + + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i, + rtlefuse->txpwr_ht20diff[RF90_PATH_A][i])); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i, + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i])); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i, + rtlefuse->txpwr_ht20diff[RF90_PATH_B][i])); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TxPower, + ("RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i, + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i])); + + RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("TxPwrSafetyFlag = %d\n", + rtlefuse->txpwr_safetyflag)); + + /* Read RF-indication and Tx Power gain + * index diff of legacy to HT OFDM rate. */ + tempval = (*(u8 *)&hwinfo[EEPROM_RFIND_POWERDIFF]) & 0xff; + rtlefuse->eeprom_txpowerdiff = tempval; + rtlefuse->legacy_httxpowerdiff = + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][0]; + + RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("TxPowerDiff = %#x\n", + rtlefuse->eeprom_txpowerdiff)); + + /* Get TSSI value for each path. */ + usvalue = *(u16 *)&hwinfo[EEPROM_TSSI_A]; + rtlefuse->eeprom_tssi[RF90_PATH_A] = (u8)((usvalue & 0xff00) >> 8); + usvalue = *(u8 *)&hwinfo[EEPROM_TSSI_B]; + rtlefuse->eeprom_tssi[RF90_PATH_B] = (u8)(usvalue & 0xff); + + RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("TSSI_A = 0x%x, TSSI_B = 0x%x\n", + rtlefuse->eeprom_tssi[RF90_PATH_A], + rtlefuse->eeprom_tssi[RF90_PATH_B])); + + /* Read antenna tx power offset of B/C/D to A from EEPROM */ + /* and read ThermalMeter from EEPROM */ + tempval = *(u8 *)&hwinfo[EEPROM_THERMALMETER]; + rtlefuse->eeprom_thermalmeter = tempval; + RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("thermalmeter = 0x%x\n", + rtlefuse->eeprom_thermalmeter)); + + /* ThermalMeter, BIT(0)~3 for RFIC1, BIT(4)~7 for RFIC2 */ + rtlefuse->thermalmeter[0] = (rtlefuse->eeprom_thermalmeter & 0x1f); + rtlefuse->tssi_13dbm = rtlefuse->eeprom_thermalmeter * 100; + + /* Read CrystalCap from EEPROM */ + tempval = (*(u8 *)&hwinfo[EEPROM_CRYSTALCAP]) >> 4; + rtlefuse->eeprom_crystalcap = tempval; + /* CrystalCap, BIT(12)~15 */ + rtlefuse->crystalcap = rtlefuse->eeprom_crystalcap; + + /* Read IC Version && Channel Plan */ + /* Version ID, Channel plan */ + rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; + rtlefuse->txpwr_fromeprom = true; + RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("EEPROM ChannelPlan = 0x%4x\n", + rtlefuse->eeprom_channelplan)); + + /* Read Customer ID or Board Type!!! */ + tempval = *(u8 *)&hwinfo[EEPROM_BOARDTYPE]; + /* Change RF type definition */ + if (tempval == 0) + rtlphy->rf_type = RF_2T2R; + else if (tempval == 1) + rtlphy->rf_type = RF_1T2R; + else if (tempval == 2) + rtlphy->rf_type = RF_1T2R; + else if (tempval == 3) + rtlphy->rf_type = RF_1T1R; + + /* 1T2R but 1SS (1x1 receive combining) */ + rtlefuse->b1x1_recvcombine = false; + if (rtlphy->rf_type == RF_1T2R) { + tempval = rtl_read_byte(rtlpriv, 0x07); + if (!(tempval & BIT(0))) { + rtlefuse->b1x1_recvcombine = true; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("RF_TYPE=1T2R but only 1SS\n")); + } + } + rtlefuse->b1ss_support = rtlefuse->b1x1_recvcombine; + rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMID]; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("EEPROM Customer ID: 0x%2x", + rtlefuse->eeprom_oemid)); + + /* set channel paln to world wide 13 */ + rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; +} + +void rtl92se_read_eeprom_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 tmp_u1b = 0; + + tmp_u1b = rtl_read_byte(rtlpriv, EPROM_CMD); + + if (tmp_u1b & BIT(4)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EEPROM\n")); + rtlefuse->epromtype = EEPROM_93C46; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EFUSE\n")); + rtlefuse->epromtype = EEPROM_BOOT_EFUSE; + } + + if (tmp_u1b & BIT(5)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n")); + rtlefuse->autoload_failflag = false; + _rtl92se_read_adapter_info(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Autoload ERR!!\n")); + rtlefuse->autoload_failflag = true; + } +} + +static void rtl92se_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 ratr_value; + u8 ratr_index = 0; + u8 nmode = mac->ht_enable; + u8 mimo_ps = IEEE80211_SMPS_OFF; + u16 shortgi_rate = 0; + u32 tmp_ratr_value = 0; + u8 curtxbw_40mhz = mac->bw_40; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = mac->mode; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_value = sta->supp_rates[1] << 4; + else + ratr_value = sta->supp_rates[0]; + ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + ratr_value &= 0x0000000D; + break; + case WIRELESS_MODE_G: + ratr_value &= 0x00000FF5; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + nmode = 1; + if (mimo_ps == IEEE80211_SMPS_STATIC) { + ratr_value &= 0x0007F005; + } else { + u32 ratr_mask; + + if (get_rf_type(rtlphy) == RF_1T2R || + get_rf_type(rtlphy) == RF_1T1R) { + if (curtxbw_40mhz) + ratr_mask = 0x000ff015; + else + ratr_mask = 0x000ff005; + } else { + if (curtxbw_40mhz) + ratr_mask = 0x0f0ff015; + else + ratr_mask = 0x0f0ff005; + } + + ratr_value &= ratr_mask; + } + break; + default: + if (rtlphy->rf_type == RF_1T2R) + ratr_value &= 0x000ff0ff; + else + ratr_value &= 0x0f0ff0ff; + + break; + } + + if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) + ratr_value &= 0x0FFFFFFF; + else if (rtlpriv->rtlhal.version == VERSION_8192S_ACUT) + ratr_value &= 0x0FFFFFF0; + + if (nmode && ((curtxbw_40mhz && + curshortgi_40mhz) || (!curtxbw_40mhz && + curshortgi_20mhz))) { + + ratr_value |= 0x10000000; + tmp_ratr_value = (ratr_value >> 12); + + for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { + if ((1 << shortgi_rate) & tmp_ratr_value) + break; + } + + shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | + (shortgi_rate << 4) | (shortgi_rate); + + rtl_write_byte(rtlpriv, SG_RATE, shortgi_rate); + } + + rtl_write_dword(rtlpriv, ARFR0 + ratr_index * 4, ratr_value); + if (ratr_value & 0xfffff000) + rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_REFRESH_N); + else + rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_REFRESH_BG); + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + ("%x\n", rtl_read_dword(rtlpriv, ARFR0))); +} + +static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u32 ratr_bitmap; + u8 ratr_index = 0; + u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) + ? 1 : 0; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = 0; + bool shortgi = false; + u32 ratr_value = 0; + u8 shortgi_rate = 0; + u32 mask = 0; + u32 band = 0; + bool bmulticast = false; + u8 macid = 0; + u8 mimo_ps = IEEE80211_SMPS_OFF; + + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + wirelessmode = sta_entry->wireless_mode; + if (mac->opmode == NL80211_IFTYPE_STATION) + curtxbw_40mhz = mac->bw_40; + else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + macid = sta->aid + 1; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_bitmap = sta->supp_rates[1] << 4; + else + ratr_bitmap = sta->supp_rates[0]; + ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + band |= WIRELESS_11B; + ratr_index = RATR_INX_WIRELESS_B; + if (ratr_bitmap & 0x0000000c) + ratr_bitmap &= 0x0000000d; + else + ratr_bitmap &= 0x0000000f; + break; + case WIRELESS_MODE_G: + band |= (WIRELESS_11G | WIRELESS_11B); + ratr_index = RATR_INX_WIRELESS_GB; + + if (rssi_level == 1) + ratr_bitmap &= 0x00000f00; + else if (rssi_level == 2) + ratr_bitmap &= 0x00000ff0; + else + ratr_bitmap &= 0x00000ff5; + break; + case WIRELESS_MODE_A: + band |= WIRELESS_11A; + ratr_index = RATR_INX_WIRELESS_A; + ratr_bitmap &= 0x00000ff0; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + band |= (WIRELESS_11N | WIRELESS_11G | WIRELESS_11B); + ratr_index = RATR_INX_WIRELESS_NGB; + + if (mimo_ps == IEEE80211_SMPS_STATIC) { + if (rssi_level == 1) + ratr_bitmap &= 0x00070000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0007f000; + else + ratr_bitmap &= 0x0007f005; + } else { + if (rtlphy->rf_type == RF_1T2R || + rtlphy->rf_type == RF_1T1R) { + if (rssi_level == 1) { + ratr_bitmap &= 0x000f0000; + } else if (rssi_level == 3) { + ratr_bitmap &= 0x000fc000; + } else if (rssi_level == 5) { + ratr_bitmap &= 0x000ff000; + } else { + if (curtxbw_40mhz) + ratr_bitmap &= 0x000ff015; + else + ratr_bitmap &= 0x000ff005; + } + } else { + if (rssi_level == 1) { + ratr_bitmap &= 0x0f8f0000; + } else if (rssi_level == 3) { + ratr_bitmap &= 0x0f8fc000; + } else if (rssi_level == 5) { + ratr_bitmap &= 0x0f8ff000; + } else { + if (curtxbw_40mhz) + ratr_bitmap &= 0x0f8ff015; + else + ratr_bitmap &= 0x0f8ff005; + } + } + } + + if ((curtxbw_40mhz && curshortgi_40mhz) || + (!curtxbw_40mhz && curshortgi_20mhz)) { + if (macid == 0) + shortgi = true; + else if (macid == 1) + shortgi = false; + } + break; + default: + band |= (WIRELESS_11N | WIRELESS_11G | WIRELESS_11B); + ratr_index = RATR_INX_WIRELESS_NGB; + + if (rtlphy->rf_type == RF_1T2R) + ratr_bitmap &= 0x000ff0ff; + else + ratr_bitmap &= 0x0f8ff0ff; + break; + } + + if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) + ratr_bitmap &= 0x0FFFFFFF; + else if (rtlpriv->rtlhal.version == VERSION_8192S_ACUT) + ratr_bitmap &= 0x0FFFFFF0; + + if (shortgi) { + ratr_bitmap |= 0x10000000; + /* Get MAX MCS available. */ + ratr_value = (ratr_bitmap >> 12); + for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { + if ((1 << shortgi_rate) & ratr_value) + break; + } + + shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | + (shortgi_rate << 4) | (shortgi_rate); + rtl_write_byte(rtlpriv, SG_RATE, shortgi_rate); + } + + mask |= (bmulticast ? 1 : 0) << 9 | (macid & 0x1f) << 4 | (band & 0xf); + + RT_TRACE(rtlpriv, COMP_RATR, DBG_TRACE, ("mask = %x, bitmap = %x\n", + mask, ratr_bitmap)); + rtl_write_dword(rtlpriv, 0x2c4, ratr_bitmap); + rtl_write_dword(rtlpriv, WFM5, (FW_RA_UPDATE_MASK | (mask << 8))); + + if (macid != 0) + sta_entry->ratr_index = ratr_index; +} + +void rtl92se_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->dm.useramask) + rtl92se_update_hal_rate_mask(hw, sta, rssi_level); + else + rtl92se_update_hal_rate_table(hw, sta); +} + +void rtl92se_update_channel_access_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 sifs_timer; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, + (u8 *)&mac->slot_time); + sifs_timer = 0x0e0e; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); + +} + +/* this ifunction is for RFKILL, it's different with windows, + * because UI will disable wireless when GPIO Radio Off. + * And here we not check or Disable/Enable ASPM like windows*/ +bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + enum rf_pwrstate rfpwr_toset, cur_rfstate; + unsigned long flag = 0; + bool actuallyset = false; + bool turnonbypowerdomain = false; + + /* just 8191se can check gpio before firstup, 92c/92d have fixed it */ + if ((rtlpci->up_first_time == 1) || (rtlpci->being_init_adapter)) + return false; + + if (ppsc->swrf_processing) + return false; + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + if (ppsc->rfchange_inprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + return false; + } else { + ppsc->rfchange_inprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } + + cur_rfstate = ppsc->rfpwr_state; + + /* because after _rtl92s_phy_set_rfhalt, all power + * closed, so we must open some power for GPIO check, + * or we will always check GPIO RFOFF here, + * And we should close power after GPIO check */ + if (RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { + _rtl92se_power_domain_init(hw); + turnonbypowerdomain = true; + } + + rfpwr_toset = _rtl92se_rf_onoff_detect(hw); + + if ((ppsc->hwradiooff == true) && (rfpwr_toset == ERFON)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + ("RFKILL-HW Radio ON, RF ON\n")); + + rfpwr_toset = ERFON; + ppsc->hwradiooff = false; + actuallyset = true; + } else if ((ppsc->hwradiooff == false) && (rfpwr_toset == ERFOFF)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + ("RFKILL-HW Radio OFF, RF OFF\n")); + + rfpwr_toset = ERFOFF; + ppsc->hwradiooff = true; + actuallyset = true; + } + + if (actuallyset) { + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + + /* this not include ifconfig wlan0 down case */ + /* } else if (rfpwr_toset == ERFOFF || cur_rfstate == ERFOFF) { */ + } else { + /* because power_domain_init may be happen when + * _rtl92s_phy_set_rfhalt, this will open some powers + * and cause current increasing about 40 mA for ips, + * rfoff and ifconfig down, so we set + * _rtl92s_phy_set_rfhalt again here */ + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC && + turnonbypowerdomain) { + _rtl92s_phy_set_rfhalt(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } + + *valid = 1; + return !ppsc->hwradiooff; + +} + +/* Is_wepkey just used for WEP used as group & pairwise key + * if pairwise is AES ang group is WEP Is_wepkey == false.*/ +void rtl92se_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr, + bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 *macaddr = p_macaddr; + + u32 entry_id = 0; + bool is_pairwise = false; + + static u8 cam_const_addr[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} + }; + static u8 cam_const_broad[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + if (clear_all) { + u8 idx = 0; + u8 cam_offset = 0; + u8 clear_number = 5; + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("clear_all\n")); + + for (idx = 0; idx < clear_number; idx++) { + rtl_cam_mark_invalid(hw, cam_offset + idx); + rtl_cam_empty_entry(hw, cam_offset + idx); + + if (idx < 5) { + memset(rtlpriv->sec.key_buf[idx], 0, + MAX_KEY_LEN); + rtlpriv->sec.key_len[idx] = 0; + } + } + + } else { + switch (enc_algo) { + case WEP40_ENCRYPTION: + enc_algo = CAM_WEP40; + break; + case WEP104_ENCRYPTION: + enc_algo = CAM_WEP104; + break; + case TKIP_ENCRYPTION: + enc_algo = CAM_TKIP; + break; + case AESCCMP_ENCRYPTION: + enc_algo = CAM_AES; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + enc_algo = CAM_TKIP; + break; + } + + if (is_wepkey || rtlpriv->sec.use_defaultkey) { + macaddr = cam_const_addr[key_index]; + entry_id = key_index; + } else { + if (is_group) { + macaddr = cam_const_broad; + entry_id = key_index; + } else { + if (mac->opmode == NL80211_IFTYPE_AP) { + entry_id = rtl_cam_get_free_entry(hw, + p_macaddr); + if (entry_id >= TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, + COMP_SEC, DBG_EMERG, + ("Can not find free hw" + " security cam entry\n")); + return; + } + } else { + entry_id = CAM_PAIRWISE_KEY_POSITION; + } + + key_index = PAIRWISE_KEYIDX; + is_pairwise = true; + } + } + + if (rtlpriv->sec.key_len[key_index] == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("delete one entry, entry_id is %d\n", + entry_id)); + if (mac->opmode == NL80211_IFTYPE_AP) + rtl_cam_del_entry(hw, p_macaddr); + rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("The insert KEY length is %d\n", + rtlpriv->sec.key_len[PAIRWISE_KEYIDX])); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("The insert KEY is %x %x\n", + rtlpriv->sec.key_buf[0][0], + rtlpriv->sec.key_buf[0][1])); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("add one entry\n")); + if (is_pairwise) { + RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, + "Pairwiase Key content :", + rtlpriv->sec.pairwise_key, + rtlpriv->sec.key_len[PAIRWISE_KEYIDX]); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("set Pairwiase key\n")); + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[key_index]); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("set group key\n")); + + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_cam_add_one_entry(hw, + rtlefuse->dev_addr, + PAIRWISE_KEYIDX, + CAM_PAIRWISE_KEY_POSITION, + enc_algo, CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + + } + } +} + +void rtl92se_suspend(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtlpci->up_first_time = true; +} + +void rtl92se_resume(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 val; + + pci_read_config_dword(rtlpci->pdev, 0x40, &val); + if ((val & 0x0000ff00) != 0) + pci_write_config_dword(rtlpci->pdev, 0x40, + val & 0xffff00ff); +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h new file mode 100644 index 000000000000..6160a9bfe98a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __REALTEK_PCI92SE_HW_H__ +#define __REALTEK_PCI92SE_HW_H__ + +#define MSR_LINK_MANAGED 2 +#define MSR_LINK_NONE 0 +#define MSR_LINK_SHIFT 0 +#define MSR_LINK_ADHOC 1 +#define MSR_LINK_MASTER 3 + +enum WIRELESS_NETWORK_TYPE { + WIRELESS_11B = 1, + WIRELESS_11G = 2, + WIRELESS_11A = 4, + WIRELESS_11N = 8 +}; + +void rtl92se_get_hw_reg(struct ieee80211_hw *hw, + u8 variable, u8 *val); +void rtl92se_read_eeprom_info(struct ieee80211_hw *hw); +void rtl92se_interrupt_recognized(struct ieee80211_hw *hw, + u32 *inta, u32 *intb); +int rtl92se_hw_init(struct ieee80211_hw *hw); +void rtl92se_card_disable(struct ieee80211_hw *hw); +void rtl92se_enable_interrupt(struct ieee80211_hw *hw); +void rtl92se_disable_interrupt(struct ieee80211_hw *hw); +int rtl92se_set_network_type(struct ieee80211_hw *hw, + enum nl80211_iftype type); +void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); +void rtl92se_set_mac_addr(struct rtl_io *io, const u8 * addr); +void rtl92se_set_qos(struct ieee80211_hw *hw, int aci); +void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw); +void rtl92se_set_beacon_interval(struct ieee80211_hw *hw); +void rtl92se_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr); +void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, + u8 *val); +void rtl92se_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level); +void rtl92se_update_channel_access_setting(struct ieee80211_hw *hw); +bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, + u8 *valid); +void rtl8192se_gpiobit3_cfg_inputmode(struct ieee80211_hw *hw); +void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw); +void rtl92se_set_key(struct ieee80211_hw *hw, + u32 key_index, u8 *macaddr, bool is_group, + u8 enc_algo, bool is_wepkey, bool clear_all); +void rtl92se_suspend(struct ieee80211_hw *hw); +void rtl92se_resume(struct ieee80211_hw *hw); + +#endif + -- cgit v1.2.3-58-ga151 From 293380046bf1a80872d611143a5ee6a23f662472 Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Tue, 3 May 2011 09:48:25 -0500 Subject: rtlwifi: rtl8192se: Merge led routines Merge routines led.c and led.h for RTL8192SE. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192se/led.c | 149 +++++++++++++++++++++++++++ drivers/net/wireless/rtlwifi/rtl8192se/led.h | 37 +++++++ 2 files changed, 186 insertions(+) create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/led.c create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/led.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/rtlwifi/rtl8192se/led.c new file mode 100644 index 000000000000..6d4f66616680 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/led.c @@ -0,0 +1,149 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "reg.h" +#include "led.h" + +static void _rtl92se_init_led(struct ieee80211_hw *hw, + struct rtl_led *pled, enum rtl_led_pin ledpin) +{ + pled->hw = hw; + pled->ledpin = ledpin; + pled->ledon = false; +} + +void rtl92se_init_sw_leds(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + _rtl92se_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); + _rtl92se_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); +} + +void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + u8 ledcfg; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + ("LedAddr:%X ledpin=%d\n", LEDCFG, pled->ledpin)); + + ledcfg = rtl_read_byte(rtlpriv, LEDCFG); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0xf0); + break; + case LED_PIN_LED1: + rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0x0f); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + pled->ledon = true; +} + +void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + u8 ledcfg; + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + ("LedAddr:%X ledpin=%d\n", LEDCFG, pled->ledpin)); + + ledcfg = rtl_read_byte(rtlpriv, LEDCFG); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg &= 0xf0; + if (pcipriv->ledctl.led_opendrain == true) + rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(1))); + else + rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3))); + break; + case LED_PIN_LED1: + ledcfg &= 0x0f; + rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3))); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + pled->ledon = false; +} + +static void _rtl92se_sw_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + switch (ledaction) { + case LED_CTL_POWER_ON: + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + rtl92se_sw_led_on(hw, pLed0); + break; + case LED_CTL_POWER_OFF: + rtl92se_sw_led_off(hw, pLed0); + break; + default: + break; + } +} + +void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && + (ledaction == LED_CTL_TX || + ledaction == LED_CTL_RX || + ledaction == LED_CTL_SITE_SURVEY || + ledaction == LED_CTL_LINK || + ledaction == LED_CTL_NO_LINK || + ledaction == LED_CTL_START_TO_LINK || + ledaction == LED_CTL_POWER_ON)) { + return; + } + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n", + ledaction)); + + _rtl92se_sw_led_control(hw, ledaction); +} + diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.h b/drivers/net/wireless/rtlwifi/rtl8192se/led.h new file mode 100644 index 000000000000..8cce3870af3c --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/led.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __REALTEK_PCI92SE_LED_H__ +#define __REALTEK_PCI92SE_LED_H__ + +void rtl92se_init_sw_leds(struct ieee80211_hw *hw); +void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); + +#endif -- cgit v1.2.3-58-ga151 From d15853163bea3d31c3b2cc9c74d018a861c128cf Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Tue, 3 May 2011 09:48:35 -0500 Subject: rtlwifi: rtl8192se: Merge phy routines Merge routines phy.c and phy.h for RTL8192SE. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192se/phy.c | 1740 ++++++++++++++++++++++++++ drivers/net/wireless/rtlwifi/rtl8192se/phy.h | 101 ++ 2 files changed, 1841 insertions(+) create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/phy.c create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/phy.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c new file mode 100644 index 000000000000..63b45e60a95e --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c @@ -0,0 +1,1740 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../ps.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" +#include "fw.h" +#include "hw.h" +#include "table.h" + +static u32 _rtl92s_phy_calculate_bit_shift(u32 bitmask) +{ + u32 i; + + for (i = 0; i <= 31; i++) { + if (((bitmask >> i) & 0x1) == 1) + break; + } + + return i; +} + +u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 returnvalue = 0, originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)\n", + regaddr, bitmask)); + + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); + returnvalue = (originalvalue & bitmask) >> bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + ("BBR MASK=0x%x Addr[0x%x]=0x%x\n", + bitmask, regaddr, originalvalue)); + + return returnvalue; + +} + +void rtl92s_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, + u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," + " data(%#x)\n", regaddr, bitmask, data)); + + if (bitmask != MASKDWORD) { + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); + data = ((originalvalue & (~bitmask)) | (data << bitshift)); + } + + rtl_write_dword(rtlpriv, regaddr, data); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," + " data(%#x)\n", regaddr, bitmask, data)); + +} + +static u32 _rtl92s_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset) +{ + + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + u32 newoffset; + u32 tmplong, tmplong2; + u8 rfpi_enable = 0; + u32 retvalue = 0; + + offset &= 0x3f; + newoffset = offset; + + tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); + + if (rfpath == RF90_PATH_A) + tmplong2 = tmplong; + else + tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); + + tmplong2 = (tmplong2 & (~BLSSI_READADDRESS)) | (newoffset << 23) | + BLSSI_READEDGE; + + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, + tmplong & (~BLSSI_READEDGE)); + + mdelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); + mdelay(1); + + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, tmplong | + BLSSI_READEDGE); + mdelay(1); + + if (rfpath == RF90_PATH_A) + rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, + BIT(8)); + else if (rfpath == RF90_PATH_B) + rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, + BIT(8)); + + if (rfpi_enable) + retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi, + BLSSI_READBACK_DATA); + else + retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback, + BLSSI_READBACK_DATA); + + retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback, + BLSSI_READBACK_DATA); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFR-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rflssi_readback, retvalue)); + + return retvalue; + +} + +static void _rtl92s_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + u32 data_and_addr = 0; + u32 newoffset; + + offset &= 0x3f; + newoffset = offset; + + data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; + rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFW-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rf3wire_offset, data_and_addr)); +} + + +u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, readback_value, bitshift; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), " + "bitmask(%#x)\n", regaddr, rfpath, bitmask)); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, regaddr); + + bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); + readback_value = (original_value & bitmask) >> bitshift; + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), " + "bitmask(%#x), original_value(%#x)\n", regaddr, rfpath, + bitmask, original_value)); + + return readback_value; +} + +void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 original_value, bitshift; + unsigned long flags; + + if (!((rtlphy->rf_pathmap >> rfpath) & 0x1)) + return; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," + " data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath)); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + if (bitmask != RFREG_OFFSET_MASK) { + original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, + regaddr); + bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); + data = ((original_value & (~bitmask)) | (data << bitshift)); + } + + _rtl92s_phy_rf_serial_write(hw, rfpath, regaddr, data); + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x), " + "data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath)); + +} + +void rtl92s_phy_scan_operation_backup(struct ieee80211_hw *hw, + u8 operation) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (!is_hal_stop(rtlhal)) { + switch (operation) { + case SCAN_OPT_BACKUP: + rtl92s_phy_set_fw_cmd(hw, FW_CMD_PAUSE_DM_BY_SCAN); + break; + case SCAN_OPT_RESTORE: + rtl92s_phy_set_fw_cmd(hw, FW_CMD_RESUME_DM_BY_SCAN); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Unknown operation.\n")); + break; + } + } +} + +void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 reg_bw_opmode; + u8 reg_prsr_rsc; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("Switch to %s bandwidth\n", + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : "40MHz")); + + if (rtlphy->set_bwmode_inprogress) + return; + if (is_hal_stop(rtlhal)) + return; + + rtlphy->set_bwmode_inprogress = true; + + reg_bw_opmode = rtl_read_byte(rtlpriv, BW_OPMODE); + reg_prsr_rsc = rtl_read_byte(rtlpriv, RRSR + 2); + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + reg_bw_opmode |= BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); + break; + case HT_CHANNEL_WIDTH_20_40: + reg_bw_opmode &= ~BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("unknown bandwidth: %#X\n", + rtlphy->current_chan_bw)); + break; + } + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); + + if (rtlhal->version >= VERSION_8192S_BCUT) + rtl_write_byte(rtlpriv, RFPGA0_ANALOGPARAMETER2, 0x58); + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, + (mac->cur_40_prime_sc >> 1)); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); + + if (rtlhal->version >= VERSION_8192S_BCUT) + rtl_write_byte(rtlpriv, RFPGA0_ANALOGPARAMETER2, 0x18); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); + break; + } + + rtl92s_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); +} + +static bool _rtl92s_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, enum swchnlcmd_id cmdid, + u32 para1, u32 para2, u32 msdelay) +{ + struct swchnlcmd *pcmd; + + if (cmdtable == NULL) { + RT_ASSERT(false, ("cmdtable cannot be NULL.\n")); + return false; + } + + if (cmdtableidx >= cmdtablesz) + return false; + + pcmd = cmdtable + cmdtableidx; + pcmd->cmdid = cmdid; + pcmd->para1 = para1; + pcmd->para2 = para2; + pcmd->msdelay = msdelay; + + return true; +} + +static bool _rtl92s_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, u32 *delay) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; + u32 precommoncmdcnt; + struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; + u32 postcommoncmdcnt; + struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; + u32 rfdependcmdcnt; + struct swchnlcmd *currentcmd = NULL; + u8 rfpath; + u8 num_total_rfpath = rtlphy->num_total_rfpath; + + precommoncmdcnt = 0; + _rtl92s_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); + _rtl92s_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); + + postcommoncmdcnt = 0; + + _rtl92s_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, + MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); + + rfdependcmdcnt = 0; + + RT_ASSERT((channel >= 1 && channel <= 14), + ("illegal channel for Zebra: %d\n", channel)); + + _rtl92s_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, + RF_CHNLBW, channel, 10); + + _rtl92s_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, 0); + + do { + switch (*stage) { + case 0: + currentcmd = &precommoncmd[*step]; + break; + case 1: + currentcmd = &rfdependcmd[*step]; + break; + case 2: + currentcmd = &postcommoncmd[*step]; + break; + } + + if (currentcmd->cmdid == CMDID_END) { + if ((*stage) == 2) { + return true; + } else { + (*stage)++; + (*step) = 0; + continue; + } + } + + switch (currentcmd->cmdid) { + case CMDID_SET_TXPOWEROWER_LEVEL: + rtl92s_phy_set_txpower(hw, channel); + break; + case CMDID_WRITEPORT_ULONG: + rtl_write_dword(rtlpriv, currentcmd->para1, + currentcmd->para2); + break; + case CMDID_WRITEPORT_USHORT: + rtl_write_word(rtlpriv, currentcmd->para1, + (u16)currentcmd->para2); + break; + case CMDID_WRITEPORT_UCHAR: + rtl_write_byte(rtlpriv, currentcmd->para1, + (u8)currentcmd->para2); + break; + case CMDID_RF_WRITEREG: + for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { + rtlphy->rfreg_chnlval[rfpath] = + ((rtlphy->rfreg_chnlval[rfpath] & + 0xfffffc00) | currentcmd->para2); + rtl_set_rfreg(hw, (enum radio_path)rfpath, + currentcmd->para1, + RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[rfpath]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + + break; + } while (true); + + (*delay) = currentcmd->msdelay; + (*step)++; + return false; +} + +u8 rtl92s_phy_sw_chnl(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 delay; + bool ret; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + ("switch to channel%d\n", + rtlphy->current_channel)); + + if (rtlphy->sw_chnl_inprogress) + return 0; + + if (rtlphy->set_bwmode_inprogress) + return 0; + + if (is_hal_stop(rtlhal)) + return 0; + + rtlphy->sw_chnl_inprogress = true; + rtlphy->sw_chnl_stage = 0; + rtlphy->sw_chnl_step = 0; + + do { + if (!rtlphy->sw_chnl_inprogress) + break; + + ret = _rtl92s_phy_sw_chnl_step_by_step(hw, + rtlphy->current_channel, + &rtlphy->sw_chnl_stage, + &rtlphy->sw_chnl_step, &delay); + if (!ret) { + if (delay > 0) + mdelay(delay); + else + continue; + } else { + rtlphy->sw_chnl_inprogress = false; + } + break; + } while (true); + + rtlphy->sw_chnl_inprogress = false; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); + + return 1; +} + +static void _rtl92se_phy_set_rf_sleep(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1btmp; + + u1btmp = rtl_read_byte(rtlpriv, LDOV12D_CTRL); + u1btmp |= BIT(0); + + rtl_write_byte(rtlpriv, LDOV12D_CTRL, u1btmp); + rtl_write_byte(rtlpriv, SPS1_CTRL, 0x0); + rtl_write_byte(rtlpriv, TXPAUSE, 0xFF); + rtl_write_word(rtlpriv, CMDR, 0x57FC); + udelay(100); + + rtl_write_word(rtlpriv, CMDR, 0x77FC); + rtl_write_byte(rtlpriv, PHY_CCA, 0x0); + udelay(10); + + rtl_write_word(rtlpriv, CMDR, 0x37FC); + udelay(10); + + rtl_write_word(rtlpriv, CMDR, 0x77FC); + udelay(10); + + rtl_write_word(rtlpriv, CMDR, 0x57FC); + + /* we should chnge GPIO to input mode + * this will drop away current about 25mA*/ + rtl8192se_gpiobit3_cfg_inputmode(hw); +} + +bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = true; + u8 i, queue_id; + struct rtl8192_tx_ring *ring = NULL; + + if (rfpwr_state == ppsc->rfpwr_state) + return false; + + ppsc->set_rfpowerstate_inprogress = true; + + switch (rfpwr_state) { + case ERFON:{ + if ((ppsc->rfpwr_state == ERFOFF) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { + + bool rtstatus; + u32 InitializeCount = 0; + do { + InitializeCount++; + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + ("IPS Set eRf nic enable\n")); + rtstatus = rtl_ps_enable_nic(hw); + } while ((rtstatus != true) && + (InitializeCount < 10)); + + RT_CLEAR_PS_LEVEL(ppsc, + RT_RF_OFF_LEVL_HALT_NIC); + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + ("awake, sleeped:%d ms " + "state_inap:%x\n", + jiffies_to_msecs(jiffies - + ppsc->last_sleep_jiffies), + rtlpriv->psc.state_inap)); + ppsc->last_awake_jiffies = jiffies; + rtl_write_word(rtlpriv, CMDR, 0x37FC); + rtl_write_byte(rtlpriv, TXPAUSE, 0x00); + rtl_write_byte(rtlpriv, PHY_CCA, 0x3); + } + + if (mac->link_state == MAC80211_LINKED) + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_LINK); + else + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + break; + } + case ERFOFF:{ + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + ("IPS Set eRf nic disable\n")); + rtl_ps_disable_nic(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } else { + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + else + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_POWER_OFF); + } + break; + } + case ERFSLEEP: + if (ppsc->rfpwr_state == ERFOFF) + break; + + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (skb_queue_len(&ring->queue) == 0 || + queue_id == BEACON_QUEUE) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("eRf Off/Sleep: " + "%d times TcbBusyQueue[%d] = " + "%d before doze!\n", + (i + 1), queue_id, + skb_queue_len(&ring->queue))); + + udelay(10); + i++; + } + + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("\nERFOFF: %d times" + "TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue))); + break; + } + } + + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + ("Set ERFSLEEP awaked:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc->last_awake_jiffies))); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + ("sleep awaked:%d ms " + "state_inap:%x\n", jiffies_to_msecs(jiffies - + ppsc->last_awake_jiffies), + rtlpriv->psc.state_inap)); + ppsc->last_sleep_jiffies = jiffies; + _rtl92se_phy_set_rf_sleep(hw); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + bresult = false; + break; + } + + if (bresult) + ppsc->rfpwr_state = rfpwr_state; + + ppsc->set_rfpowerstate_inprogress = false; + + return bresult; +} + +static bool _rtl92s_phy_config_rfpa_bias_current(struct ieee80211_hw *hw, + enum radio_path rfpath) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool rtstatus = true; + u32 tmpval = 0; + + /* If inferiority IC, we have to increase the PA bias current */ + if (rtlhal->ic_class != IC_INFERIORITY_A) { + tmpval = rtl92s_phy_query_rf_reg(hw, rfpath, RF_IPA, 0xf); + rtl92s_phy_set_rf_reg(hw, rfpath, RF_IPA, 0xf, tmpval + 1); + } + + return rtstatus; +} + +static void _rtl92s_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, + u32 reg_addr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + if (reg_addr == RTXAGC_RATE18_06) + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] = + data; + if (reg_addr == RTXAGC_RATE54_24) + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] = + data; + if (reg_addr == RTXAGC_CCK_MCS32) + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] = + data; + if (reg_addr == RTXAGC_MCS03_MCS00) + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] = + data; + if (reg_addr == RTXAGC_MCS07_MCS04) + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] = + data; + if (reg_addr == RTXAGC_MCS11_MCS08) + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] = + data; + if (reg_addr == RTXAGC_MCS15_MCS12) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] = + data; + rtlphy->pwrgroup_cnt++; + } +} + +static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + /*RF Interface Sowrtware Control */ + rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; + + /* RF Interface Readback Value */ + rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; + + /* RF Interface Output (and Enable) */ + rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_C].rfintfo = RFPGA0_XC_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_D].rfintfo = RFPGA0_XD_RFINTERFACEOE; + + /* RF Interface (Output and) Enable */ + rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_C].rfintfe = RFPGA0_XC_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_D].rfintfe = RFPGA0_XD_RFINTERFACEOE; + + /* Addr of LSSI. Wirte RF register by driver */ + rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = + RFPGA0_XA_LSSIPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = + RFPGA0_XB_LSSIPARAMETER; + rtlphy->phyreg_def[RF90_PATH_C].rf3wire_offset = + RFPGA0_XC_LSSIPARAMETER; + rtlphy->phyreg_def[RF90_PATH_D].rf3wire_offset = + RFPGA0_XD_LSSIPARAMETER; + + /* RF parameter */ + rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER; + + /* Tx AGC Gain Stage (same for all path. Should we remove this?) */ + rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; + + /* Tranceiver A~D HSSI Parameter-1 */ + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; + rtlphy->phyreg_def[RF90_PATH_C].rfhssi_para1 = RFPGA0_XC_HSSIPARAMETER1; + rtlphy->phyreg_def[RF90_PATH_D].rfhssi_para1 = RFPGA0_XD_HSSIPARAMETER1; + + /* Tranceiver A~D HSSI Parameter-2 */ + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; + rtlphy->phyreg_def[RF90_PATH_C].rfhssi_para2 = RFPGA0_XC_HSSIPARAMETER2; + rtlphy->phyreg_def[RF90_PATH_D].rfhssi_para2 = RFPGA0_XD_HSSIPARAMETER2; + + /* RF switch Control */ + rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control = + RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control = + RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control = + RFPGA0_XCD_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control = + RFPGA0_XCD_SWITCHCONTROL; + + /* AGC control 1 */ + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; + + /* AGC control 2 */ + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; + + /* RX AFE control 1 */ + rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance = + ROFDM0_XARXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance = + ROFDM0_XBRXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance = + ROFDM0_XCRXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance = + ROFDM0_XDRXIQIMBALANCE; + + /* RX AFE control 1 */ + rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; + rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; + rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; + + /* Tx AFE control 1 */ + rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance = + ROFDM0_XATXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance = + ROFDM0_XBTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance = + ROFDM0_XCTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance = + ROFDM0_XDTXIQIMBALANCE; + + /* Tx AFE control 2 */ + rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; + rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE; + rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE; + + /* Tranceiver LSSI Readback */ + rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback = + RFPGA0_XA_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback = + RFPGA0_XB_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback = + RFPGA0_XC_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback = + RFPGA0_XD_LSSIREADBACK; + + /* Tranceiver LSSI Readback PI mode */ + rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi = + TRANSCEIVERA_HSPI_READBACK; + rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi = + TRANSCEIVERB_HSPI_READBACK; +} + + +static bool _rtl92s_phy_config_bb(struct ieee80211_hw *hw, u8 configtype) +{ + int i; + u32 *phy_reg_table; + u32 *agc_table; + u16 phy_reg_len, agc_len; + + agc_len = AGCTAB_ARRAYLENGTH; + agc_table = rtl8192seagctab_array; + /* Default RF_type: 2T2R */ + phy_reg_len = PHY_REG_2T2RARRAYLENGTH; + phy_reg_table = rtl8192sephy_reg_2t2rarray; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_reg_len; i = i + 2) { + if (phy_reg_table[i] == 0xfe) + mdelay(50); + else if (phy_reg_table[i] == 0xfd) + mdelay(5); + else if (phy_reg_table[i] == 0xfc) + mdelay(1); + else if (phy_reg_table[i] == 0xfb) + udelay(50); + else if (phy_reg_table[i] == 0xfa) + udelay(5); + else if (phy_reg_table[i] == 0xf9) + udelay(1); + + /* Add delay for ECS T20 & LG malow platform, */ + udelay(1); + + rtl92s_phy_set_bb_reg(hw, phy_reg_table[i], MASKDWORD, + phy_reg_table[i + 1]); + } + } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { + for (i = 0; i < agc_len; i = i + 2) { + rtl92s_phy_set_bb_reg(hw, agc_table[i], MASKDWORD, + agc_table[i + 1]); + + /* Add delay for ECS T20 & LG malow platform */ + udelay(1); + } + } + + return true; +} + +static bool _rtl92s_phy_set_bb_to_diff_rf(struct ieee80211_hw *hw, + u8 configtype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 *phy_regarray2xtxr_table; + u16 phy_regarray2xtxr_len; + int i; + + if (rtlphy->rf_type == RF_1T1R) { + phy_regarray2xtxr_table = rtl8192sephy_changeto_1t1rarray; + phy_regarray2xtxr_len = PHY_CHANGETO_1T1RARRAYLENGTH; + } else if (rtlphy->rf_type == RF_1T2R) { + phy_regarray2xtxr_table = rtl8192sephy_changeto_1t2rarray; + phy_regarray2xtxr_len = PHY_CHANGETO_1T2RARRAYLENGTH; + } else { + return false; + } + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_regarray2xtxr_len; i = i + 3) { + if (phy_regarray2xtxr_table[i] == 0xfe) + mdelay(50); + else if (phy_regarray2xtxr_table[i] == 0xfd) + mdelay(5); + else if (phy_regarray2xtxr_table[i] == 0xfc) + mdelay(1); + else if (phy_regarray2xtxr_table[i] == 0xfb) + udelay(50); + else if (phy_regarray2xtxr_table[i] == 0xfa) + udelay(5); + else if (phy_regarray2xtxr_table[i] == 0xf9) + udelay(1); + + rtl92s_phy_set_bb_reg(hw, phy_regarray2xtxr_table[i], + phy_regarray2xtxr_table[i + 1], + phy_regarray2xtxr_table[i + 2]); + } + } + + return true; +} + +static bool _rtl92s_phy_config_bb_with_pg(struct ieee80211_hw *hw, + u8 configtype) +{ + int i; + u32 *phy_table_pg; + u16 phy_pg_len; + + phy_pg_len = PHY_REG_ARRAY_PGLENGTH; + phy_table_pg = rtl8192sephy_reg_array_pg; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_pg_len; i = i + 3) { + if (phy_table_pg[i] == 0xfe) + mdelay(50); + else if (phy_table_pg[i] == 0xfd) + mdelay(5); + else if (phy_table_pg[i] == 0xfc) + mdelay(1); + else if (phy_table_pg[i] == 0xfb) + udelay(50); + else if (phy_table_pg[i] == 0xfa) + udelay(5); + else if (phy_table_pg[i] == 0xf9) + udelay(1); + + _rtl92s_store_pwrindex_diffrate_offset(hw, + phy_table_pg[i], + phy_table_pg[i + 1], + phy_table_pg[i + 2]); + rtl92s_phy_set_bb_reg(hw, phy_table_pg[i], + phy_table_pg[i + 1], + phy_table_pg[i + 2]); + } + } + + return true; +} + +static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + bool rtstatus = true; + + /* 1. Read PHY_REG.TXT BB INIT!! */ + /* We will separate as 1T1R/1T2R/1T2R_GREEN/2T2R */ + if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_2T2R || + rtlphy->rf_type == RF_1T1R || rtlphy->rf_type == RF_2T2R_GREEN) { + rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_PHY_REG); + + if (rtlphy->rf_type != RF_2T2R && + rtlphy->rf_type != RF_2T2R_GREEN) + /* so we should reconfig BB reg with the right + * PHY parameters. */ + rtstatus = _rtl92s_phy_set_bb_to_diff_rf(hw, + BASEBAND_CONFIG_PHY_REG); + } else { + rtstatus = false; + } + + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + ("Write BB Reg Fail!!")); + goto phy_BB8190_Config_ParaFile_Fail; + } + + /* 2. If EEPROM or EFUSE autoload OK, We must config by + * PHY_REG_PG.txt */ + if (rtlefuse->autoload_failflag == false) { + rtlphy->pwrgroup_cnt = 0; + + rtstatus = _rtl92s_phy_config_bb_with_pg(hw, + BASEBAND_CONFIG_PHY_REG); + } + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + ("_rtl92s_phy_bb_config_parafile(): " + "BB_PG Reg Fail!!")); + goto phy_BB8190_Config_ParaFile_Fail; + } + + /* 3. BB AGC table Initialization */ + rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_AGC_TAB); + + if (rtstatus != true) { + printk(KERN_ERR "_rtl92s_phy_bb_config_parafile(): " + "AGC Table Fail\n"); + goto phy_BB8190_Config_ParaFile_Fail; + } + + /* Check if the CCK HighPower is turned ON. */ + /* This is used to calculate PWDB. */ + rtlphy->cck_high_power = (bool)(rtl92s_phy_query_bb_reg(hw, + RFPGA0_XA_HSSIPARAMETER2, 0x200)); + +phy_BB8190_Config_ParaFile_Fail: + return rtstatus; +} + +u8 rtl92s_phy_config_rf(struct ieee80211_hw *hw, enum radio_path rfpath) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + int i; + bool rtstatus = true; + u32 *radio_a_table; + u32 *radio_b_table; + u16 radio_a_tblen, radio_b_tblen; + + radio_a_tblen = RADIOA_1T_ARRAYLENGTH; + radio_a_table = rtl8192seradioa_1t_array; + + /* Using Green mode array table for RF_2T2R_GREEN */ + if (rtlphy->rf_type == RF_2T2R_GREEN) { + radio_b_table = rtl8192seradiob_gm_array; + radio_b_tblen = RADIOB_GM_ARRAYLENGTH; + } else { + radio_b_table = rtl8192seradiob_array; + radio_b_tblen = RADIOB_ARRAYLENGTH; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Radio No %x\n", rfpath)); + rtstatus = true; + + switch (rfpath) { + case RF90_PATH_A: + for (i = 0; i < radio_a_tblen; i = i + 2) { + if (radio_a_table[i] == 0xfe) + /* Delay specific ms. Only RF configuration + * requires delay. */ + mdelay(50); + else if (radio_a_table[i] == 0xfd) + mdelay(5); + else if (radio_a_table[i] == 0xfc) + mdelay(1); + else if (radio_a_table[i] == 0xfb) + udelay(50); + else if (radio_a_table[i] == 0xfa) + udelay(5); + else if (radio_a_table[i] == 0xf9) + udelay(1); + else + rtl92s_phy_set_rf_reg(hw, rfpath, + radio_a_table[i], + MASK20BITS, + radio_a_table[i + 1]); + + /* Add delay for ECS T20 & LG malow platform */ + udelay(1); + } + + /* PA Bias current for inferiority IC */ + _rtl92s_phy_config_rfpa_bias_current(hw, rfpath); + break; + case RF90_PATH_B: + for (i = 0; i < radio_b_tblen; i = i + 2) { + if (radio_b_table[i] == 0xfe) + /* Delay specific ms. Only RF configuration + * requires delay.*/ + mdelay(50); + else if (radio_b_table[i] == 0xfd) + mdelay(5); + else if (radio_b_table[i] == 0xfc) + mdelay(1); + else if (radio_b_table[i] == 0xfb) + udelay(50); + else if (radio_b_table[i] == 0xfa) + udelay(5); + else if (radio_b_table[i] == 0xf9) + udelay(1); + else + rtl92s_phy_set_rf_reg(hw, rfpath, + radio_b_table[i], + MASK20BITS, + radio_b_table[i + 1]); + + /* Add delay for ECS T20 & LG malow platform */ + udelay(1); + } + break; + case RF90_PATH_C: + ; + break; + case RF90_PATH_D: + ; + break; + default: + break; + } + + return rtstatus; +} + + +bool rtl92s_phy_mac_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + u32 arraylength; + u32 *ptraArray; + + arraylength = MAC_2T_ARRAYLENGTH; + ptraArray = rtl8192semac_2t_array; + + for (i = 0; i < arraylength; i = i + 2) + rtl_write_byte(rtlpriv, ptraArray[i], (u8)ptraArray[i + 1]); + + return true; +} + + +bool rtl92s_phy_bb_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + bool rtstatus = true; + u8 pathmap, index, rf_num = 0; + u8 path1, path2; + + _rtl92s_phy_init_register_definition(hw); + + /* Config BB and AGC */ + rtstatus = _rtl92s_phy_bb_config_parafile(hw); + + + /* Check BB/RF confiuration setting. */ + /* We only need to configure RF which is turned on. */ + path1 = (u8)(rtl92s_phy_query_bb_reg(hw, RFPGA0_TXINFO, 0xf)); + mdelay(10); + path2 = (u8)(rtl92s_phy_query_bb_reg(hw, ROFDM0_TRXPATHENABLE, 0xf)); + pathmap = path1 | path2; + + rtlphy->rf_pathmap = pathmap; + for (index = 0; index < 4; index++) { + if ((pathmap >> index) & 0x1) + rf_num++; + } + + if ((rtlphy->rf_type == RF_1T1R && rf_num != 1) || + (rtlphy->rf_type == RF_1T2R && rf_num != 2) || + (rtlphy->rf_type == RF_2T2R && rf_num != 2) || + (rtlphy->rf_type == RF_2T2R_GREEN && rf_num != 2)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + ("RF_Type(%x) does not match " + "RF_Num(%x)!!\n", rtlphy->rf_type, rf_num)); + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + ("path1 0x%x, path2 0x%x, pathmap " + "0x%x\n", path1, path2, pathmap)); + } + + return rtstatus; +} + +bool rtl92s_phy_rf_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + /* Initialize general global value */ + if (rtlphy->rf_type == RF_1T1R) + rtlphy->num_total_rfpath = 1; + else + rtlphy->num_total_rfpath = 2; + + /* Config BB and RF */ + return rtl92s_phy_rf6052_config(hw); +} + +void rtl92s_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + /* read rx initial gain */ + rtlphy->default_initialgain[0] = rtl_get_bbreg(hw, + ROFDM0_XAAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[1] = rtl_get_bbreg(hw, + ROFDM0_XBAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[2] = rtl_get_bbreg(hw, + ROFDM0_XCAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[3] = rtl_get_bbreg(hw, + ROFDM0_XDAGCCORE1, MASKBYTE0); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Default initial gain " + "(c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x)\n", + rtlphy->default_initialgain[0], + rtlphy->default_initialgain[1], + rtlphy->default_initialgain[2], + rtlphy->default_initialgain[3])); + + /* read framesync */ + rtlphy->framesync = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, MASKBYTE0); + rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, + MASKDWORD); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("Default framesync (0x%x) = 0x%x\n", + ROFDM0_RXDETECTOR3, rtlphy->framesync)); + +} + +static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel, + u8 *cckpowerlevel, u8 *ofdmpowerLevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 index = (channel - 1); + + /* 1. CCK */ + /* RF-A */ + cckpowerlevel[0] = rtlefuse->txpwrlevel_cck[0][index]; + /* RF-B */ + cckpowerlevel[1] = rtlefuse->txpwrlevel_cck[1][index]; + + /* 2. OFDM for 1T or 2T */ + if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_1T1R) { + /* Read HT 40 OFDM TX power */ + ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_1s[0][index]; + ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_1s[1][index]; + } else if (rtlphy->rf_type == RF_2T2R) { + /* Read HT 40 OFDM TX power */ + ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index]; + ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index]; + } +} + +static void _rtl92s_phy_ccxpower_indexcheck(struct ieee80211_hw *hw, + u8 channel, u8 *cckpowerlevel, u8 *ofdmpowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; + rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; +} + +void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + /* [0]:RF-A, [1]:RF-B */ + u8 cckpowerlevel[2], ofdmpowerLevel[2]; + + if (rtlefuse->txpwr_fromeprom == false) + return; + + /* Mainly we use RF-A Tx Power to write the Tx Power registers, + * but the RF-B Tx Power must be calculated by the antenna diff. + * So we have to rewrite Antenna gain offset register here. + * Please refer to BB register 0x80c + * 1. For CCK. + * 2. For OFDM 1T or 2T */ + _rtl92s_phy_get_txpower_index(hw, channel, &cckpowerlevel[0], + &ofdmpowerLevel[0]); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("Channel-%d, cckPowerLevel (A / B) = " + "0x%x / 0x%x, ofdmPowerLevel (A / B) = 0x%x / 0x%x\n", + channel, cckpowerlevel[0], cckpowerlevel[1], + ofdmpowerLevel[0], ofdmpowerLevel[1])); + + _rtl92s_phy_ccxpower_indexcheck(hw, channel, &cckpowerlevel[0], + &ofdmpowerLevel[0]); + + rtl92s_phy_rf6052_set_ccktxpower(hw, cckpowerlevel[0]); + rtl92s_phy_rf6052_set_ofdmtxpower(hw, &ofdmpowerLevel[0], channel); + +} + +void rtl92s_phy_chk_fwcmd_iodone(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 pollingcnt = 10000; + u32 tmpvalue; + + /* Make sure that CMD IO has be accepted by FW. */ + do { + udelay(10); + + tmpvalue = rtl_read_dword(rtlpriv, WFM5); + if (tmpvalue == 0) + break; + } while (--pollingcnt); + + if (pollingcnt == 0) + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Set FW Cmd fail!!\n")); +} + + +static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 input, current_aid = 0; + + if (is_hal_stop(rtlhal)) + return; + + /* We re-map RA related CMD IO to combinational ones */ + /* if FW version is v.52 or later. */ + switch (rtlhal->current_fwcmd_io) { + case FW_CMD_RA_REFRESH_N: + rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_N_COMB; + break; + case FW_CMD_RA_REFRESH_BG: + rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_BG_COMB; + break; + default: + break; + } + + switch (rtlhal->current_fwcmd_io) { + case FW_CMD_RA_RESET: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, + ("FW_CMD_RA_RESET\n")); + rtl_write_dword(rtlpriv, WFM5, FW_RA_RESET); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_RA_ACTIVE: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, + ("FW_CMD_RA_ACTIVE\n")); + rtl_write_dword(rtlpriv, WFM5, FW_RA_ACTIVE); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_RA_REFRESH_N: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, + ("FW_CMD_RA_REFRESH_N\n")); + input = FW_RA_REFRESH; + rtl_write_dword(rtlpriv, WFM5, input); + rtl92s_phy_chk_fwcmd_iodone(hw); + rtl_write_dword(rtlpriv, WFM5, FW_RA_ENABLE_RSSI_MASK); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_RA_REFRESH_BG: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, + ("FW_CMD_RA_REFRESH_BG\n")); + rtl_write_dword(rtlpriv, WFM5, FW_RA_REFRESH); + rtl92s_phy_chk_fwcmd_iodone(hw); + rtl_write_dword(rtlpriv, WFM5, FW_RA_DISABLE_RSSI_MASK); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_RA_REFRESH_N_COMB: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, + ("FW_CMD_RA_REFRESH_N_COMB\n")); + input = FW_RA_IOT_N_COMB; + rtl_write_dword(rtlpriv, WFM5, input); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_RA_REFRESH_BG_COMB: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, + ("FW_CMD_RA_REFRESH_BG_COMB\n")); + input = FW_RA_IOT_BG_COMB; + rtl_write_dword(rtlpriv, WFM5, input); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_IQK_ENABLE: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, + ("FW_CMD_IQK_ENABLE\n")); + rtl_write_dword(rtlpriv, WFM5, FW_IQK_ENABLE); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_PAUSE_DM_BY_SCAN: + /* Lower initial gain */ + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, 0x17); + rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, 0x17); + /* CCA threshold */ + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x40); + break; + case FW_CMD_RESUME_DM_BY_SCAN: + /* CCA threshold */ + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); + rtl92s_phy_set_txpower(hw, rtlphy->current_channel); + break; + case FW_CMD_HIGH_PWR_DISABLE: + if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) + break; + + /* Lower initial gain */ + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, 0x17); + rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, 0x17); + /* CCA threshold */ + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x40); + break; + case FW_CMD_HIGH_PWR_ENABLE: + if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) || + (rtlpriv->dm.dynamic_txpower_enable == true)) + break; + + /* CCA threshold */ + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); + break; + case FW_CMD_LPS_ENTER: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, + ("FW_CMD_LPS_ENTER\n")); + current_aid = rtlpriv->mac80211.assoc_id; + rtl_write_dword(rtlpriv, WFM5, (FW_LPS_ENTER | + ((current_aid | 0xc000) << 8))); + rtl92s_phy_chk_fwcmd_iodone(hw); + /* FW set TXOP disable here, so disable EDCA + * turbo mode until driver leave LPS */ + break; + case FW_CMD_LPS_LEAVE: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, + ("FW_CMD_LPS_LEAVE\n")); + rtl_write_dword(rtlpriv, WFM5, FW_LPS_LEAVE); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_ADD_A2_ENTRY: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, + ("FW_CMD_ADD_A2_ENTRY\n")); + rtl_write_dword(rtlpriv, WFM5, FW_ADD_A2_ENTRY); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_CTRL_DM_BY_DRIVER: + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("FW_CMD_CTRL_DM_BY_DRIVER\n")); + rtl_write_dword(rtlpriv, WFM5, FW_CTRL_DM_BY_DRIVER); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + + default: + break; + } + + rtl92s_phy_chk_fwcmd_iodone(hw); + + /* Clear FW CMD operation flag. */ + rtlhal->set_fwcmd_inprogress = false; +} + +bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 fw_param = FW_CMD_IO_PARA_QUERY(rtlpriv); + u16 fw_cmdmap = FW_CMD_IO_QUERY(rtlpriv); + bool bPostProcessing = false; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("Set FW Cmd(%#x), set_fwcmd_inprogress(%d)\n", + fw_cmdio, rtlhal->set_fwcmd_inprogress)); + + do { + /* We re-map to combined FW CMD ones if firmware version */ + /* is v.53 or later. */ + switch (fw_cmdio) { + case FW_CMD_RA_REFRESH_N: + fw_cmdio = FW_CMD_RA_REFRESH_N_COMB; + break; + case FW_CMD_RA_REFRESH_BG: + fw_cmdio = FW_CMD_RA_REFRESH_BG_COMB; + break; + default: + break; + } + + /* If firmware version is v.62 or later, + * use FW_CMD_IO_SET for FW_CMD_CTRL_DM_BY_DRIVER */ + if (hal_get_firmwareversion(rtlpriv) >= 0x3E) { + if (fw_cmdio == FW_CMD_CTRL_DM_BY_DRIVER) + fw_cmdio = FW_CMD_CTRL_DM_BY_DRIVER_NEW; + } + + + /* We shall revise all FW Cmd IO into Reg0x364 + * DM map table in the future. */ + switch (fw_cmdio) { + case FW_CMD_RA_INIT: + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("RA init!!\n")); + fw_cmdmap |= FW_RA_INIT_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + /* Clear control flag to sync with FW. */ + FW_CMD_IO_CLR(rtlpriv, FW_RA_INIT_CTL); + break; + case FW_CMD_DIG_DISABLE: + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("Set DIG disable!!\n")); + fw_cmdmap &= ~FW_DIG_ENABLE_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + break; + case FW_CMD_DIG_ENABLE: + case FW_CMD_DIG_RESUME: + if (!(rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE)) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("Set DIG enable or resume!!\n")); + fw_cmdmap |= (FW_DIG_ENABLE_CTL | FW_SS_CTL); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + } + break; + case FW_CMD_DIG_HALT: + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("Set DIG halt!!\n")); + fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | FW_SS_CTL); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + break; + case FW_CMD_TXPWR_TRACK_THERMAL: { + u8 thermalval = 0; + fw_cmdmap |= FW_PWR_TRK_CTL; + + /* Clear FW parameter in terms of thermal parts. */ + fw_param &= FW_PWR_TRK_PARAM_CLR; + + thermalval = rtlpriv->dm.thermalvalue; + fw_param |= ((thermalval << 24) | + (rtlefuse->thermalmeter[0] << 16)); + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("Set TxPwr tracking!! " + "FwCmdMap(%#x), FwParam(%#x)\n", + fw_cmdmap, fw_param)); + + FW_CMD_PARA_SET(rtlpriv, fw_param); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + + /* Clear control flag to sync with FW. */ + FW_CMD_IO_CLR(rtlpriv, FW_PWR_TRK_CTL); + } + break; + /* The following FW CMDs are only compatible to + * v.53 or later. */ + case FW_CMD_RA_REFRESH_N_COMB: + fw_cmdmap |= FW_RA_N_CTL; + + /* Clear RA BG mode control. */ + fw_cmdmap &= ~(FW_RA_BG_CTL | FW_RA_INIT_CTL); + + /* Clear FW parameter in terms of RA parts. */ + fw_param &= FW_RA_PARAM_CLR; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("[FW CMD] [New Version] " + "Set RA/IOT Comb in n mode!! FwCmdMap(%#x), " + "FwParam(%#x)\n", fw_cmdmap, fw_param)); + + FW_CMD_PARA_SET(rtlpriv, fw_param); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + + /* Clear control flag to sync with FW. */ + FW_CMD_IO_CLR(rtlpriv, FW_RA_N_CTL); + break; + case FW_CMD_RA_REFRESH_BG_COMB: + fw_cmdmap |= FW_RA_BG_CTL; + + /* Clear RA n-mode control. */ + fw_cmdmap &= ~(FW_RA_N_CTL | FW_RA_INIT_CTL); + /* Clear FW parameter in terms of RA parts. */ + fw_param &= FW_RA_PARAM_CLR; + + FW_CMD_PARA_SET(rtlpriv, fw_param); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + + /* Clear control flag to sync with FW. */ + FW_CMD_IO_CLR(rtlpriv, FW_RA_BG_CTL); + break; + case FW_CMD_IQK_ENABLE: + fw_cmdmap |= FW_IQK_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + /* Clear control flag to sync with FW. */ + FW_CMD_IO_CLR(rtlpriv, FW_IQK_CTL); + break; + /* The following FW CMD is compatible to v.62 or later. */ + case FW_CMD_CTRL_DM_BY_DRIVER_NEW: + fw_cmdmap |= FW_DRIVER_CTRL_DM_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + break; + /* The followed FW Cmds needs post-processing later. */ + case FW_CMD_RESUME_DM_BY_SCAN: + fw_cmdmap |= (FW_DIG_ENABLE_CTL | + FW_HIGH_PWR_ENABLE_CTL | + FW_SS_CTL); + + if (rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE || + !digtable.dig_enable_flag) + fw_cmdmap &= ~FW_DIG_ENABLE_CTL; + + if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) || + (rtlpriv->dm.dynamic_txpower_enable == true)) + fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; + + if ((digtable.dig_ext_port_stage == + DIG_EXT_PORT_STAGE_0) || + (digtable.dig_ext_port_stage == + DIG_EXT_PORT_STAGE_1)) + fw_cmdmap &= ~FW_DIG_ENABLE_CTL; + + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + bPostProcessing = true; + break; + case FW_CMD_PAUSE_DM_BY_SCAN: + fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | + FW_HIGH_PWR_ENABLE_CTL | + FW_SS_CTL); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + bPostProcessing = true; + break; + case FW_CMD_HIGH_PWR_DISABLE: + fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + bPostProcessing = true; + break; + case FW_CMD_HIGH_PWR_ENABLE: + if (!(rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) && + (rtlpriv->dm.dynamic_txpower_enable != true)) { + fw_cmdmap |= (FW_HIGH_PWR_ENABLE_CTL | + FW_SS_CTL); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + bPostProcessing = true; + } + break; + case FW_CMD_DIG_MODE_FA: + fw_cmdmap |= FW_FA_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + break; + case FW_CMD_DIG_MODE_SS: + fw_cmdmap &= ~FW_FA_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + break; + case FW_CMD_PAPE_CONTROL: + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + ("[FW CMD] Set PAPE Control\n")); + fw_cmdmap &= ~FW_PAPE_CTL_BY_SW_HW; + + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + break; + default: + /* Pass to original FW CMD processing callback + * routine. */ + bPostProcessing = true; + break; + } + } while (false); + + /* We shall post processing these FW CMD if + * variable bPostProcessing is set. */ + if (bPostProcessing && !rtlhal->set_fwcmd_inprogress) { + rtlhal->set_fwcmd_inprogress = true; + /* Update current FW Cmd for callback use. */ + rtlhal->current_fwcmd_io = fw_cmdio; + } else { + return false; + } + + _rtl92s_phy_set_fwcmd_io(hw); + return true; +} + +static void _rtl92s_phy_check_ephy_switchready(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 delay = 100; + u8 regu1; + + regu1 = rtl_read_byte(rtlpriv, 0x554); + while ((regu1 & BIT(5)) && (delay > 0)) { + regu1 = rtl_read_byte(rtlpriv, 0x554); + delay--; + /* We delay only 50us to prevent + * being scheduled out. */ + udelay(50); + } +} + +void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + /* The way to be capable to switch clock request + * when the PG setting does not support clock request. + * This is the backdoor solution to switch clock + * request before ASPM or D3. */ + rtl_write_dword(rtlpriv, 0x540, 0x73c11); + rtl_write_dword(rtlpriv, 0x548, 0x2407c); + + /* Switch EPHY parameter!!!! */ + rtl_write_word(rtlpriv, 0x550, 0x1000); + rtl_write_byte(rtlpriv, 0x554, 0x20); + _rtl92s_phy_check_ephy_switchready(hw); + + rtl_write_word(rtlpriv, 0x550, 0xa0eb); + rtl_write_byte(rtlpriv, 0x554, 0x3e); + _rtl92s_phy_check_ephy_switchready(hw); + + rtl_write_word(rtlpriv, 0x550, 0xff80); + rtl_write_byte(rtlpriv, 0x554, 0x39); + _rtl92s_phy_check_ephy_switchready(hw); + + /* Delay L1 enter time */ + if (ppsc->support_aspm && !ppsc->support_backdoor) + rtl_write_byte(rtlpriv, 0x560, 0x40); + else + rtl_write_byte(rtlpriv, 0x560, 0x00); + +} + +void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 BeaconInterval) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + rtl_write_dword(rtlpriv, WFM5, 0xF1000000 | (BeaconInterval << 8)); +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h b/drivers/net/wireless/rtlwifi/rtl8192se/phy.h new file mode 100644 index 000000000000..37e504af6446 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __RTL92S_PHY_H__ +#define __RTL92S_PHY_H__ + +#define MAX_TXPWR_IDX_NMODE_92S 63 +#define MAX_DOZE_WAITING_TIMES_9x 64 + +/* Channel switch:The size of + * command tables for switch channel */ +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +#define RF90_PATH_MAX 4 + +enum version_8192s { + VERSION_8192S_ACUT, + VERSION_8192S_BCUT, + VERSION_8192S_CCUT +}; + +enum swchnlcmd_id { + CMDID_END, + CMDID_SET_TXPOWEROWER_LEVEL, + CMDID_BBREGWRITE10, + CMDID_WRITEPORT_ULONG, + CMDID_WRITEPORT_USHORT, + CMDID_WRITEPORT_UCHAR, + CMDID_RF_WRITEREG, +}; + +struct swchnlcmd { + enum swchnlcmd_id cmdid; + u32 para1; + u32 para2; + u32 msdelay; +}; + +enum baseband_config_type { + /* Radio Path A */ + BASEBAND_CONFIG_PHY_REG = 0, + /* Radio Path B */ + BASEBAND_CONFIG_AGC_TAB = 1, +}; + +#define hal_get_firmwareversion(rtlpriv) \ + (((struct rt_firmware *)(rtlpriv->rtlhal.pfirmware))->firmwareversion) + +u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); +void rtl92s_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, + u32 data); +void rtl92s_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); +u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask); +void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data); +void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type); +u8 rtl92s_phy_sw_chnl(struct ieee80211_hw *hw); +bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpower_state); +bool rtl92s_phy_mac_config(struct ieee80211_hw *hw); +void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw); +bool rtl92s_phy_bb_config(struct ieee80211_hw *hw); +bool rtl92s_phy_rf_config(struct ieee80211_hw *hw); +void rtl92s_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel); +bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fwcmd_io); +void rtl92s_phy_chk_fwcmd_iodone(struct ieee80211_hw *hw); +void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 beaconinterval); +u8 rtl92s_phy_config_rf(struct ieee80211_hw *hw, enum radio_path rfpath) ; + +#endif + -- cgit v1.2.3-58-ga151 From cf76bbf7c0d0315ec17c950d14de939a81465f6b Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Tue, 3 May 2011 09:48:45 -0500 Subject: rtlwifi: rtl8192se: Merge register definitions Merge routines reg.h for RTL8192SE. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192se/reg.h | 1188 ++++++++++++++++++++++++++ 1 file changed, 1188 insertions(+) create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/reg.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h new file mode 100644 index 000000000000..0116eaddbfac --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h @@ -0,0 +1,1188 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __REALTEK_92S_REG_H__ +#define __REALTEK_92S_REG_H__ + +/* 1. System Configuration Registers */ +#define REG_SYS_ISO_CTRL 0x0000 +#define REG_SYS_FUNC_EN 0x0002 +#define PMC_FSM 0x0004 +#define SYS_CLKR 0x0008 +#define EPROM_CMD 0x000A +#define EE_VPD 0x000C +#define AFE_MISC 0x0010 +#define SPS0_CTRL 0x0011 +#define SPS1_CTRL 0x0018 +#define RF_CTRL 0x001F +#define LDOA15_CTRL 0x0020 +#define LDOV12D_CTRL 0x0021 +#define LDOHCI12_CTRL 0x0022 +#define LDO_USB_SDIO 0x0023 +#define LPLDO_CTRL 0x0024 +#define AFE_XTAL_CTRL 0x0026 +#define AFE_PLL_CTRL 0x0028 +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define PWR_DATA 0x0038 +#define DBG_PORT 0x003A +#define DPS_TIMER 0x003C +#define RCLK_MON 0x003E + +/* 2. Command Control Registers */ +#define CMDR 0x0040 +#define TXPAUSE 0x0042 +#define LBKMD_SEL 0x0043 +#define TCR 0x0044 +#define RCR 0x0048 +#define MSR 0x004C +#define SYSF_CFG 0x004D +#define RX_PKY_LIMIT 0x004E +#define MBIDCTRL 0x004F + +/* 3. MACID Setting Registers */ +#define MACIDR 0x0050 +#define MACIDR0 0x0050 +#define MACIDR4 0x0054 +#define BSSIDR 0x0058 +#define HWVID 0x005E +#define MAR 0x0060 +#define MBIDCAMCONTENT 0x0068 +#define MBIDCAMCFG 0x0070 +#define BUILDTIME 0x0074 +#define BUILDUSER 0x0078 + +#define IDR0 MACIDR0 +#define IDR4 MACIDR4 + +/* 4. Timing Control Registers */ +#define TSFR 0x0080 +#define SLOT_TIME 0x0089 +#define USTIME 0x008A +#define SIFS_CCK 0x008C +#define SIFS_OFDM 0x008E +#define PIFS_TIME 0x0090 +#define ACK_TIMEOUT 0x0091 +#define EIFSTR 0x0092 +#define BCN_INTERVAL 0x0094 +#define ATIMWND 0x0096 +#define BCN_DRV_EARLY_INT 0x0098 +#define BCN_DMATIME 0x009A +#define BCN_ERR_THRESH 0x009C +#define MLT 0x009D +#define RSVD_MAC_TUNE_US 0x009E + +/* 5. FIFO Control Registers */ +#define RQPN 0x00A0 +#define RQPN1 0x00A0 +#define RQPN2 0x00A1 +#define RQPN3 0x00A2 +#define RQPN4 0x00A3 +#define RQPN5 0x00A4 +#define RQPN6 0x00A5 +#define RQPN7 0x00A6 +#define RQPN8 0x00A7 +#define RQPN9 0x00A8 +#define RQPN10 0x00A9 +#define LD_RQPN 0x00AB +#define RXFF_BNDY 0x00AC +#define RXRPT_BNDY 0x00B0 +#define TXPKTBUF_PGBNDY 0x00B4 +#define PBP 0x00B5 +#define RXDRVINFO_SZ 0x00B6 +#define TXFF_STATUS 0x00B7 +#define RXFF_STATUS 0x00B8 +#define TXFF_EMPTY_TH 0x00B9 +#define SDIO_RX_BLKSZ 0x00BC +#define RXDMA 0x00BD +#define RXPKT_NUM 0x00BE +#define C2HCMD_UDT_SIZE 0x00C0 +#define C2HCMD_UDT_ADDR 0x00C2 +#define FIFOPAGE1 0x00C4 +#define FIFOPAGE2 0x00C8 +#define FIFOPAGE3 0x00CC +#define FIFOPAGE4 0x00D0 +#define FIFOPAGE5 0x00D4 +#define FW_RSVD_PG_CRTL 0x00D8 +#define RXDMA_AGG_PG_TH 0x00D9 +#define TXDESC_MSK 0x00DC +#define TXRPTFF_RDPTR 0x00E0 +#define TXRPTFF_WTPTR 0x00E4 +#define C2HFF_RDPTR 0x00E8 +#define C2HFF_WTPTR 0x00EC +#define RXFF0_RDPTR 0x00F0 +#define RXFF0_WTPTR 0x00F4 +#define RXFF1_RDPTR 0x00F8 +#define RXFF1_WTPTR 0x00FC +#define RXRPT0_RDPTR 0x0100 +#define RXRPT0_WTPTR 0x0104 +#define RXRPT1_RDPTR 0x0108 +#define RXRPT1_WTPTR 0x010C +#define RX0_UDT_SIZE 0x0110 +#define RX1PKTNUM 0x0114 +#define RXFILTERMAP 0x0116 +#define RXFILTERMAP_GP1 0x0118 +#define RXFILTERMAP_GP2 0x011A +#define RXFILTERMAP_GP3 0x011C +#define BCNQ_CTRL 0x0120 +#define MGTQ_CTRL 0x0124 +#define HIQ_CTRL 0x0128 +#define VOTID7_CTRL 0x012c +#define VOTID6_CTRL 0x0130 +#define VITID5_CTRL 0x0134 +#define VITID4_CTRL 0x0138 +#define BETID3_CTRL 0x013c +#define BETID0_CTRL 0x0140 +#define BKTID2_CTRL 0x0144 +#define BKTID1_CTRL 0x0148 +#define CMDQ_CTRL 0x014c +#define TXPKT_NUM_CTRL 0x0150 +#define TXQ_PGADD 0x0152 +#define TXFF_PG_NUM 0x0154 +#define TRXDMA_STATUS 0x0156 + +/* 6. Adaptive Control Registers */ +#define INIMCS_SEL 0x0160 +#define TX_RATE_REG INIMCS_SEL +#define INIRTSMCS_SEL 0x0180 +#define RRSR 0x0181 +#define ARFR0 0x0184 +#define ARFR1 0x0188 +#define ARFR2 0x018C +#define ARFR3 0x0190 +#define ARFR4 0x0194 +#define ARFR5 0x0198 +#define ARFR6 0x019C +#define ARFR7 0x01A0 +#define AGGLEN_LMT_H 0x01A7 +#define AGGLEN_LMT_L 0x01A8 +#define DARFRC 0x01B0 +#define RARFRC 0x01B8 +#define MCS_TXAGC 0x01C0 +#define CCK_TXAGC 0x01C8 + +/* 7. EDCA Setting Registers */ +#define EDCAPARA_VO 0x01D0 +#define EDCAPARA_VI 0x01D4 +#define EDCAPARA_BE 0x01D8 +#define EDCAPARA_BK 0x01DC +#define BCNTCFG 0x01E0 +#define CWRR 0x01E2 +#define ACMAVG 0x01E4 +#define AcmHwCtrl 0x01E7 +#define VO_ADMTM 0x01E8 +#define VI_ADMTM 0x01EC +#define BE_ADMTM 0x01F0 +#define RETRY_LIMIT 0x01F4 +#define SG_RATE 0x01F6 + +/* 8. WMAC, BA and CCX related Register. */ +#define NAV_CTRL 0x0200 +#define BW_OPMODE 0x0203 +#define BACAMCMD 0x0204 +#define BACAMCONTENT 0x0208 + +/* the 0x2xx register WMAC definition */ +#define LBDLY 0x0210 +#define FWDLY 0x0211 +#define HWPC_RX_CTRL 0x0218 +#define MQIR 0x0220 +#define MAIR 0x0222 +#define MSIR 0x0224 +#define CLM_RESULT 0x0227 +#define NHM_RPI_CNT 0x0228 +#define RXERR_RPT 0x0230 +#define NAV_PROT_LEN 0x0234 +#define CFEND_TH 0x0236 +#define AMPDU_MIN_SPACE 0x0237 +#define TXOP_STALL_CTRL 0x0238 + +/* 9. Security Control Registers */ +#define REG_RWCAM 0x0240 +#define REG_WCAMI 0x0244 +#define REG_RCAMO 0x0248 +#define REG_CAMDBG 0x024C +#define REG_SECR 0x0250 + +/* 10. Power Save Control Registers */ +#define WOW_CTRL 0x0260 +#define PSSTATUS 0x0261 +#define PSSWITCH 0x0262 +#define MIMOPS_WAIT_PERIOD 0x0263 +#define LPNAV_CTRL 0x0264 +#define WFM0 0x0270 +#define WFM1 0x0280 +#define WFM2 0x0290 +#define WFM3 0x02A0 +#define WFM4 0x02B0 +#define WFM5 0x02C0 +#define WFCRC 0x02D0 +#define FW_RPT_REG 0x02c4 + +/* 11. General Purpose Registers */ +#define PSTIME 0x02E0 +#define TIMER0 0x02E4 +#define TIMER1 0x02E8 +#define GPIO_CTRL 0x02EC +#define GPIO_IN 0x02EC +#define GPIO_OUT 0x02ED +#define GPIO_IO_SEL 0x02EE +#define GPIO_MOD 0x02EF +#define GPIO_INTCTRL 0x02F0 +#define MAC_PINMUX_CFG 0x02F1 +#define LEDCFG 0x02F2 +#define PHY_REG 0x02F3 +#define PHY_REG_DATA 0x02F4 +#define REG_EFUSE_CLK 0x02F8 + +/* 12. Host Interrupt Status Registers */ +#define INTA_MASK 0x0300 +#define ISR 0x0308 + +/* 13. Test Mode and Debug Control Registers */ +#define DBG_PORT_SWITCH 0x003A +#define BIST 0x0310 +#define DBS 0x0314 +#define CPUINST 0x0318 +#define CPUCAUSE 0x031C +#define LBUS_ERR_ADDR 0x0320 +#define LBUS_ERR_CMD 0x0324 +#define LBUS_ERR_DATA_L 0x0328 +#define LBUS_ERR_DATA_H 0x032C +#define LX_EXCEPTION_ADDR 0x0330 +#define WDG_CTRL 0x0334 +#define INTMTU 0x0338 +#define INTM 0x033A +#define FDLOCKTURN0 0x033C +#define FDLOCKTURN1 0x033D +#define TRXPKTBUF_DBG_DATA 0x0340 +#define TRXPKTBUF_DBG_CTRL 0x0348 +#define DPLL 0x034A +#define CBUS_ERR_ADDR 0x0350 +#define CBUS_ERR_CMD 0x0354 +#define CBUS_ERR_DATA_L 0x0358 +#define CBUS_ERR_DATA_H 0x035C +#define USB_SIE_INTF_ADDR 0x0360 +#define USB_SIE_INTF_WD 0x0361 +#define USB_SIE_INTF_RD 0x0362 +#define USB_SIE_INTF_CTRL 0x0363 +#define LBUS_MON_ADDR 0x0364 +#define LBUS_ADDR_MASK 0x0368 + +/* Boundary is 0x37F */ + +/* 14. PCIE config register */ +#define TP_POLL 0x0500 +#define PM_CTRL 0x0502 +#define PCIF 0x0503 + +#define THPDA 0x0514 +#define TMDA 0x0518 +#define TCDA 0x051C +#define HDA 0x0520 +#define TVODA 0x0524 +#define TVIDA 0x0528 +#define TBEDA 0x052C +#define TBKDA 0x0530 +#define TBDA 0x0534 +#define RCDA 0x0538 +#define RDQDA 0x053C +#define DBI_WDATA 0x0540 +#define DBI_RDATA 0x0544 +#define DBI_CTRL 0x0548 +#define MDIO_DATA 0x0550 +#define MDIO_CTRL 0x0554 +#define PCI_RPWM 0x0561 +#define PCI_CPWM 0x0563 + +/* Config register (Offset 0x800-) */ +#define PHY_CCA 0x803 + +/* Min Spacing related settings. */ +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +/* Rx DMA Control related settings */ +#define RXDMA_AGG_EN BIT(7) + +#define RPWM PCI_RPWM + +/* Regsiter Bit and Content definition */ + +#define ISO_MD2PP BIT(0) +#define ISO_PA2PCIE BIT(3) +#define ISO_PLL2MD BIT(4) +#define ISO_PWC_DV2RP BIT(11) +#define ISO_PWC_RV2RP BIT(12) + + +#define FEN_MREGEN BIT(15) +#define FEN_DCORE BIT(11) +#define FEN_CPUEN BIT(10) + +#define PAD_HWPD_IDN BIT(22) + +#define SYS_CLKSEL_80M BIT(0) +#define SYS_PS_CLKSEL BIT(1) +#define SYS_CPU_CLKSEL BIT(2) +#define SYS_MAC_CLK_EN BIT(11) +#define SYS_SWHW_SEL BIT(14) +#define SYS_FWHW_SEL BIT(15) + +#define CmdEEPROM_En BIT(5) +#define CmdEERPOMSEL BIT(4) +#define Cmd9346CR_9356SEL BIT(4) + +#define AFE_MBEN BIT(1) +#define AFE_BGEN BIT(0) + +#define SPS1_SWEN BIT(1) +#define SPS1_LDEN BIT(0) + +#define RF_EN BIT(0) +#define RF_RSTB BIT(1) +#define RF_SDMRSTB BIT(2) + +#define LDA15_EN BIT(0) + +#define LDV12_EN BIT(0) +#define LDV12_SDBY BIT(1) + +#define XTAL_GATE_AFE BIT(10) + +#define APLL_EN BIT(0) + +#define AFR_CardBEn BIT(0) +#define AFR_CLKRUN_SEL BIT(1) +#define AFR_FuncRegEn BIT(2) + +#define APSDOFF_STATUS BIT(15) +#define APSDOFF BIT(14) +#define BBRSTN BIT(13) +#define BB_GLB_RSTN BIT(12) +#define SCHEDULE_EN BIT(10) +#define MACRXEN BIT(9) +#define MACTXEN BIT(8) +#define DDMA_EN BIT(7) +#define FW2HW_EN BIT(6) +#define RXDMA_EN BIT(5) +#define TXDMA_EN BIT(4) +#define HCI_RXDMA_EN BIT(3) +#define HCI_TXDMA_EN BIT(2) + +#define StopHCCA BIT(6) +#define StopHigh BIT(5) +#define StopMgt BIT(4) +#define StopVO BIT(3) +#define StopVI BIT(2) +#define StopBE BIT(1) +#define StopBK BIT(0) + +#define LBK_NORMAL 0x00 +#define LBK_MAC_LB (BIT(0) | BIT(1) | BIT(3)) +#define LBK_MAC_DLB (BIT(0) | BIT(1)) +#define LBK_DMA_LB (BIT(0) | BIT(1) | BIT(2)) + +#define TCP_OFDL_EN BIT(25) +#define HWPC_TX_EN BIT(24) +#define TXDMAPRE2FULL BIT(23) +#define DISCW BIT(20) +#define TCRICV BIT(19) +#define CfendForm BIT(17) +#define TCRCRC BIT(16) +#define FAKE_IMEM_EN BIT(15) +#define TSFRST BIT(9) +#define TSFEN BIT(8) +#define FWALLRDY (BIT(0) | BIT(1) | BIT(2) | \ + BIT(3) | BIT(4) | BIT(5) | \ + BIT(6) | BIT(7)) +#define FWRDY BIT(7) +#define BASECHG BIT(6) +#define IMEM BIT(5) +#define DMEM_CODE_DONE BIT(4) +#define EXT_IMEM_CHK_RPT BIT(3) +#define EXT_IMEM_CODE_DONE BIT(2) +#define IMEM_CHK_RPT BIT(1) +#define IMEM_CODE_DONE BIT(0) +#define IMEM_CODE_DONE BIT(0) +#define IMEM_CHK_RPT BIT(1) +#define EMEM_CODE_DONE BIT(2) +#define EMEM_CHK_RPT BIT(3) +#define DMEM_CODE_DONE BIT(4) +#define IMEM_RDY BIT(5) +#define BASECHG BIT(6) +#define FWRDY BIT(7) +#define LOAD_FW_READY (IMEM_CODE_DONE | \ + IMEM_CHK_RPT | \ + EMEM_CODE_DONE | \ + EMEM_CHK_RPT | \ + DMEM_CODE_DONE | \ + IMEM_RDY | \ + BASECHG | \ + FWRDY) +#define TCR_TSFEN BIT(8) +#define TCR_TSFRST BIT(9) +#define TCR_FAKE_IMEM_EN BIT(15) +#define TCR_CRC BIT(16) +#define TCR_ICV BIT(19) +#define TCR_DISCW BIT(20) +#define TCR_HWPC_TX_EN BIT(24) +#define TCR_TCP_OFDL_EN BIT(25) +#define TXDMA_INIT_VALUE (IMEM_CHK_RPT | \ + EXT_IMEM_CHK_RPT) + +#define RCR_APPFCS BIT(31) +#define RCR_DIS_ENC_2BYTE BIT(30) +#define RCR_DIS_AES_2BYTE BIT(29) +#define RCR_HTC_LOC_CTRL BIT(28) +#define RCR_ENMBID BIT(27) +#define RCR_RX_TCPOFDL_EN BIT(26) +#define RCR_APP_PHYST_RXFF BIT(25) +#define RCR_APP_PHYST_STAFF BIT(24) +#define RCR_CBSSID BIT(23) +#define RCR_APWRMGT BIT(22) +#define RCR_ADD3 BIT(21) +#define RCR_AMF BIT(20) +#define RCR_ACF BIT(19) +#define RCR_ADF BIT(18) +#define RCR_APP_MIC BIT(17) +#define RCR_APP_ICV BIT(16) +#define RCR_RXFTH BIT(13) +#define RCR_AICV BIT(12) +#define RCR_RXDESC_LK_EN BIT(11) +#define RCR_APP_BA_SSN BIT(6) +#define RCR_ACRC32 BIT(5) +#define RCR_RXSHFT_EN BIT(4) +#define RCR_AB BIT(3) +#define RCR_AM BIT(2) +#define RCR_APM BIT(1) +#define RCR_AAP BIT(0) +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 + + +#define MSR_LINK_MASK ((1 << 0) | (1 << 1)) +#define MSR_LINK_MANAGED 2 +#define MSR_LINK_NONE 0 +#define MSR_LINK_SHIFT 0 +#define MSR_LINK_ADHOC 1 +#define MSR_LINK_MASTER 3 +#define MSR_NOLINK 0x00 +#define MSR_ADHOC 0x01 +#define MSR_INFRA 0x02 +#define MSR_AP 0x03 + +#define ENUART BIT(7) +#define ENJTAG BIT(3) +#define BTMODE (BIT(2) | BIT(1)) +#define ENBT BIT(0) + +#define ENMBID BIT(7) +#define BCNUM (BIT(6) | BIT(5) | BIT(4)) + +#define USTIME_EDCA 0xFF00 +#define USTIME_TSF 0x00FF + +#define SIFS_TRX 0xFF00 +#define SIFS_CTX 0x00FF + +#define ENSWBCN BIT(15) +#define DRVERLY_TU 0x0FF0 +#define DRVERLY_US 0x000F +#define BCN_TCFG_CW_SHIFT 8 +#define BCN_TCFG_IFS 0 + +#define RRSR_RSC_OFFSET 21 +#define RRSR_SHORT_OFFSET 23 +#define RRSR_RSC_BW_40M 0x600000 +#define RRSR_RSC_UPSUBCHNL 0x400000 +#define RRSR_RSC_LOWSUBCHNL 0x200000 +#define RRSR_SHORT 0x800000 +#define RRSR_1M BIT(0) +#define RRSR_2M BIT(1) +#define RRSR_5_5M BIT(2) +#define RRSR_11M BIT(3) +#define RRSR_6M BIT(4) +#define RRSR_9M BIT(5) +#define RRSR_12M BIT(6) +#define RRSR_18M BIT(7) +#define RRSR_24M BIT(8) +#define RRSR_36M BIT(9) +#define RRSR_48M BIT(10) +#define RRSR_54M BIT(11) +#define RRSR_MCS0 BIT(12) +#define RRSR_MCS1 BIT(13) +#define RRSR_MCS2 BIT(14) +#define RRSR_MCS3 BIT(15) +#define RRSR_MCS4 BIT(16) +#define RRSR_MCS5 BIT(17) +#define RRSR_MCS6 BIT(18) +#define RRSR_MCS7 BIT(19) +#define BRSR_AckShortPmb BIT(23) + +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 + +#define RATE_ALL_CCK (RATR_1M | RATR_2M | \ + RATR_55M | RATR_11M) +#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | \ + RATR_12M | RATR_18M | \ + RATR_24M | RATR_36M | \ + RATR_48M | RATR_54M) +#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | \ + RATR_MCS2 | RATR_MCS3 | \ + RATR_MCS4 | RATR_MCS5 | \ + RATR_MCS6 | RATR_MCS7) +#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | \ + RATR_MCS10 | RATR_MCS11 | \ + RATR_MCS12 | RATR_MCS13 | \ + RATR_MCS14 | RATR_MCS15) + +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 +#define AC_PARAM_ECW_MAX_OFFSET 12 +#define AC_PARAM_ECW_MIN_OFFSET 8 +#define AC_PARAM_AIFS_OFFSET 0 + +#define AcmHw_HwEn BIT(0) +#define AcmHw_BeqEn BIT(1) +#define AcmHw_ViqEn BIT(2) +#define AcmHw_VoqEn BIT(3) +#define AcmHw_BeqStatus BIT(4) +#define AcmHw_ViqStatus BIT(5) +#define AcmHw_VoqStatus BIT(6) + +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_LONG_SHIFT 0 + +#define NAV_UPPER_EN BIT(16) +#define NAV_UPPER 0xFF00 +#define NAV_RTSRST 0xFF + +#define BW_OPMODE_20MHZ BIT(2) +#define BW_OPMODE_5G BIT(1) +#define BW_OPMODE_11J BIT(0) + +#define RXERR_RPT_RST BIT(27) +#define RXERR_OFDM_PPDU 0 +#define RXERR_OFDM_FALSE_ALARM 1 +#define RXERR_OFDM_MPDU_OK 2 +#define RXERR_OFDM_MPDU_FAIL 3 +#define RXERR_CCK_PPDU 4 +#define RXERR_CCK_FALSE_ALARM 5 +#define RXERR_CCK_MPDU_OK 6 +#define RXERR_CCK_MPDU_FAIL 7 +#define RXERR_HT_PPDU 8 +#define RXERR_HT_FALSE_ALARM 9 +#define RXERR_HT_MPDU_TOTAL 10 +#define RXERR_HT_MPDU_OK 11 +#define RXERR_HT_MPDU_FAIL 12 +#define RXERR_RX_FULL_DROP 15 + +#define SCR_TXUSEDK BIT(0) +#define SCR_RXUSEDK BIT(1) +#define SCR_TXENCENABLE BIT(2) +#define SCR_RXENCENABLE BIT(3) +#define SCR_SKBYA2 BIT(4) +#define SCR_NOSKMC BIT(5) + +#define CAM_VALID BIT(15) +#define CAM_NOTVALID 0x0000 +#define CAM_USEDK BIT(5) + +#define CAM_NONE 0x0 +#define CAM_WEP40 0x01 +#define CAM_TKIP 0x02 +#define CAM_AES 0x04 +#define CAM_WEP104 0x05 + +#define TOTAL_CAM_ENTRY 32 +#define HALF_CAM_ENTRY 16 + +#define CAM_WRITE BIT(16) +#define CAM_READ 0x00000000 +#define CAM_POLLINIG BIT(31) + +#define WOW_PMEN BIT(0) +#define WOW_WOMEN BIT(1) +#define WOW_MAGIC BIT(2) +#define WOW_UWF BIT(3) + +#define GPIOMUX_EN BIT(3) +#define GPIOSEL_GPIO 0 +#define GPIOSEL_PHYDBG 1 +#define GPIOSEL_BT 2 +#define GPIOSEL_WLANDBG 3 +#define GPIOSEL_GPIO_MASK (~(BIT(0)|BIT(1))) + +#define HST_RDBUSY BIT(0) +#define CPU_WTBUSY BIT(1) + +#define IMR8190_DISABLED 0x0 +#define IMR_CPUERR BIT(5) +#define IMR_ATIMEND BIT(4) +#define IMR_TBDOK BIT(3) +#define IMR_TBDER BIT(2) +#define IMR_BCNDMAINT8 BIT(1) +#define IMR_BCNDMAINT7 BIT(0) +#define IMR_BCNDMAINT6 BIT(31) +#define IMR_BCNDMAINT5 BIT(30) +#define IMR_BCNDMAINT4 BIT(29) +#define IMR_BCNDMAINT3 BIT(28) +#define IMR_BCNDMAINT2 BIT(27) +#define IMR_BCNDMAINT1 BIT(26) +#define IMR_BCNDOK8 BIT(25) +#define IMR_BCNDOK7 BIT(24) +#define IMR_BCNDOK6 BIT(23) +#define IMR_BCNDOK5 BIT(22) +#define IMR_BCNDOK4 BIT(21) +#define IMR_BCNDOK3 BIT(20) +#define IMR_BCNDOK2 BIT(19) +#define IMR_BCNDOK1 BIT(18) +#define IMR_TIMEOUT2 BIT(17) +#define IMR_TIMEOUT1 BIT(16) +#define IMR_TXFOVW BIT(15) +#define IMR_PSTIMEOUT BIT(14) +#define IMR_BCNINT BIT(13) +#define IMR_RXFOVW BIT(12) +#define IMR_RDU BIT(11) +#define IMR_RXCMDOK BIT(10) +#define IMR_BDOK BIT(9) +#define IMR_HIGHDOK BIT(8) +#define IMR_COMDOK BIT(7) +#define IMR_MGNTDOK BIT(6) +#define IMR_HCCADOK BIT(5) +#define IMR_BKDOK BIT(4) +#define IMR_BEDOK BIT(3) +#define IMR_VIDOK BIT(2) +#define IMR_VODOK BIT(1) +#define IMR_ROK BIT(0) + +#define TPPOLL_BKQ BIT(0) +#define TPPOLL_BEQ BIT(1) +#define TPPOLL_VIQ BIT(2) +#define TPPOLL_VOQ BIT(3) +#define TPPOLL_BQ BIT(4) +#define TPPOLL_CQ BIT(5) +#define TPPOLL_MQ BIT(6) +#define TPPOLL_HQ BIT(7) +#define TPPOLL_HCCAQ BIT(8) +#define TPPOLL_STOPBK BIT(9) +#define TPPOLL_STOPBE BIT(10) +#define TPPOLL_STOPVI BIT(11) +#define TPPOLL_STOPVO BIT(12) +#define TPPOLL_STOPMGT BIT(13) +#define TPPOLL_STOPHIGH BIT(14) +#define TPPOLL_STOPHCCA BIT(15) +#define TPPOLL_SHIFT 8 + +#define CCX_CMD_CLM_ENABLE BIT(0) +#define CCX_CMD_NHM_ENABLE BIT(1) +#define CCX_CMD_FUNCTION_ENABLE BIT(8) +#define CCX_CMD_IGNORE_CCA BIT(9) +#define CCX_CMD_IGNORE_TXON BIT(10) +#define CCX_CLM_RESULT_READY BIT(16) +#define CCX_NHM_RESULT_READY BIT(16) +#define CCX_CMD_RESET 0x0 + + +#define HWSET_MAX_SIZE_92S 128 +#define EFUSE_MAX_SECTION 16 +#define EFUSE_REAL_CONTENT_LEN 512 + +#define RTL8190_EEPROM_ID 0x8129 +#define EEPROM_HPON 0x02 +#define EEPROM_CLK 0x06 +#define EEPROM_TESTR 0x08 + +#define EEPROM_VID 0x0A +#define EEPROM_DID 0x0C +#define EEPROM_SVID 0x0E +#define EEPROM_SMID 0x10 + +#define EEPROM_MAC_ADDR 0x12 +#define EEPROM_NODE_ADDRESS_BYTE_0 0x12 + +#define EEPROM_PWDIFF 0x54 + +#define EEPROM_TXPOWERBASE 0x50 +#define EEPROM_TX_PWR_INDEX_RANGE 28 + +#define EEPROM_TX_PWR_HT20_DIFF 0x62 +#define DEFAULT_HT20_TXPWR_DIFF 2 +#define EEPROM_TX_PWR_OFDM_DIFF 0x65 + +#define EEPROM_TXPWRGROUP 0x67 +#define EEPROM_REGULATORY 0x6D + +#define TX_PWR_SAFETY_CHK 0x6D +#define EEPROM_TXPWINDEX_CCK_24G 0x5D +#define EEPROM_TXPWINDEX_OFDM_24G 0x6B +#define EEPROM_HT2T_CH1_A 0x6c +#define EEPROM_HT2T_CH7_A 0x6d +#define EEPROM_HT2T_CH13_A 0x6e +#define EEPROM_HT2T_CH1_B 0x6f +#define EEPROM_HT2T_CH7_B 0x70 +#define EEPROM_HT2T_CH13_B 0x71 + +#define EEPROM_TSSI_A 0x74 +#define EEPROM_TSSI_B 0x75 + +#define EEPROM_RFIND_POWERDIFF 0x76 +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 + +#define EEPROM_THERMALMETER 0x77 +#define EEPROM_BLUETOOTH_COEXIST 0x78 +#define EEPROM_BLUETOOTH_TYPE 0x4f + +#define EEPROM_OPTIONAL 0x78 +#define EEPROM_WOWLAN 0x78 + +#define EEPROM_CRYSTALCAP 0x79 +#define EEPROM_CHANNELPLAN 0x7B +#define EEPROM_VERSION 0x7C +#define EEPROM_CUSTOMID 0x7A +#define EEPROM_BOARDTYPE 0x7E + +#define EEPROM_CHANNEL_PLAN_FCC 0x0 +#define EEPROM_CHANNEL_PLAN_IC 0x1 +#define EEPROM_CHANNEL_PLAN_ETSI 0x2 +#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 +#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 +#define EEPROM_CHANNEL_PLAN_MKK 0x5 +#define EEPROM_CHANNEL_PLAN_MKK1 0x6 +#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 +#define EEPROM_CHANNEL_PLAN_TELEC 0x8 +#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 +#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA +#define EEPROM_CHANNEL_PLAN_NCC 0xB +#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 + +#define FW_DIG_DISABLE 0xfd00cc00 +#define FW_DIG_ENABLE 0xfd000000 +#define FW_DIG_HALT 0xfd000001 +#define FW_DIG_RESUME 0xfd000002 +#define FW_HIGH_PWR_DISABLE 0xfd000008 +#define FW_HIGH_PWR_ENABLE 0xfd000009 +#define FW_ADD_A2_ENTRY 0xfd000016 +#define FW_TXPWR_TRACK_ENABLE 0xfd000017 +#define FW_TXPWR_TRACK_DISABLE 0xfd000018 +#define FW_TXPWR_TRACK_THERMAL 0xfd000019 +#define FW_TXANT_SWITCH_ENABLE 0xfd000023 +#define FW_TXANT_SWITCH_DISABLE 0xfd000024 +#define FW_RA_INIT 0xfd000026 +#define FW_CTRL_DM_BY_DRIVER 0Xfd00002a +#define FW_RA_IOT_BG_COMB 0xfd000030 +#define FW_RA_IOT_N_COMB 0xfd000031 +#define FW_RA_REFRESH 0xfd0000a0 +#define FW_RA_UPDATE_MASK 0xfd0000a2 +#define FW_RA_DISABLE 0xfd0000a4 +#define FW_RA_ACTIVE 0xfd0000a6 +#define FW_RA_DISABLE_RSSI_MASK 0xfd0000ac +#define FW_RA_ENABLE_RSSI_MASK 0xfd0000ad +#define FW_RA_RESET 0xfd0000af +#define FW_DM_DISABLE 0xfd00aa00 +#define FW_IQK_ENABLE 0xf0000020 +#define FW_IQK_SUCCESS 0x0000dddd +#define FW_IQK_FAIL 0x0000ffff +#define FW_OP_FAILURE 0xffffffff +#define FW_TX_FEEDBACK_NONE 0xfb000000 +#define FW_TX_FEEDBACK_DTM_ENABLE (FW_TX_FEEDBACK_NONE | 0x1) +#define FW_TX_FEEDBACK_CCX_ENABL (FW_TX_FEEDBACK_NONE | 0x2) +#define FW_BB_RESET_ENABLE 0xff00000d +#define FW_BB_RESET_DISABLE 0xff00000e +#define FW_CCA_CHK_ENABLE 0xff000011 +#define FW_CCK_RESET_CNT 0xff000013 +#define FW_LPS_ENTER 0xfe000010 +#define FW_LPS_LEAVE 0xfe000011 +#define FW_INDIRECT_READ 0xf2000000 +#define FW_INDIRECT_WRITE 0xf2000001 +#define FW_CHAN_SET 0xf3000001 + +#define RFPC 0x5F +#define RCR_9356SEL BIT(6) +#define TCR_LRL_OFFSET 0 +#define TCR_SRL_OFFSET 8 +#define TCR_MXDMA_OFFSET 21 +#define TCR_SAT BIT(24) +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 +#define RCR_OnlyErlPkt BIT(31) +#define CWR 0xDC +#define RETRYCTR 0xDE + +#define CPU_GEN_SYSTEM_RESET 0x00000001 + +#define CCX_COMMAND_REG 0x890 +#define CLM_PERIOD_REG 0x894 +#define NHM_PERIOD_REG 0x896 + +#define NHM_THRESHOLD0 0x898 +#define NHM_THRESHOLD1 0x899 +#define NHM_THRESHOLD2 0x89A +#define NHM_THRESHOLD3 0x89B +#define NHM_THRESHOLD4 0x89C +#define NHM_THRESHOLD5 0x89D +#define NHM_THRESHOLD6 0x89E +#define CLM_RESULT_REG 0x8D0 +#define NHM_RESULT_REG 0x8D4 +#define NHM_RPI_COUNTER0 0x8D8 +#define NHM_RPI_COUNTER1 0x8D9 +#define NHM_RPI_COUNTER2 0x8DA +#define NHM_RPI_COUNTER3 0x8DB +#define NHM_RPI_COUNTER4 0x8DC +#define NHM_RPI_COUNTER5 0x8DD +#define NHM_RPI_COUNTER6 0x8DE +#define NHM_RPI_COUNTER7 0x8DF + +#define HAL_8192S_HW_GPIO_OFF_BIT BIT(3) +#define HAL_8192S_HW_GPIO_OFF_MASK 0xF7 +#define HAL_8192S_HW_GPIO_WPS_BIT BIT(4) + +#define RPMAC_RESET 0x100 +#define RPMAC_TXSTART 0x104 +#define RPMAC_TXLEGACYSIG 0x108 +#define RPMAC_TXHTSIG1 0x10c +#define RPMAC_TXHTSIG2 0x110 +#define RPMAC_PHYDEBUG 0x114 +#define RPMAC_TXPACKETNNM 0x118 +#define RPMAC_TXIDLE 0x11c +#define RPMAC_TXMACHEADER0 0x120 +#define RPMAC_TXMACHEADER1 0x124 +#define RPMAC_TXMACHEADER2 0x128 +#define RPMAC_TXMACHEADER3 0x12c +#define RPMAC_TXMACHEADER4 0x130 +#define RPMAC_TXMACHEADER5 0x134 +#define RPMAC_TXDATATYPE 0x138 +#define RPMAC_TXRANDOMSEED 0x13c +#define RPMAC_CCKPLCPPREAMBLE 0x140 +#define RPMAC_CCKPLCPHEADER 0x144 +#define RPMAC_CCKCRC16 0x148 +#define RPMAC_OFDMRXCRC32OK 0x170 +#define RPMAC_OFDMRXCRC32ER 0x174 +#define RPMAC_OFDMRXPARITYER 0x178 +#define RPMAC_OFDMRXCRC8ER 0x17c +#define RPMAC_CCKCRXRC16ER 0x180 +#define RPMAC_CCKCRXRC32ER 0x184 +#define RPMAC_CCKCRXRC32OK 0x188 +#define RPMAC_TXSTATUS 0x18c + +#define RF_BB_CMD_ADDR 0x02c0 +#define RF_BB_CMD_DATA 0x02c4 + +#define RFPGA0_RFMOD 0x800 + +#define RFPGA0_TXINFO 0x804 +#define RFPGA0_PSDFUNCTION 0x808 + +#define RFPGA0_TXGAINSTAGE 0x80c + +#define RFPGA0_RFTIMING1 0x810 +#define RFPGA0_RFTIMING2 0x814 +#define RFPGA0_XA_HSSIPARAMETER1 0x820 +#define RFPGA0_XA_HSSIPARAMETER2 0x824 +#define RFPGA0_XB_HSSIPARAMETER1 0x828 +#define RFPGA0_XB_HSSIPARAMETER2 0x82c +#define RFPGA0_XC_HSSIPARAMETER1 0x830 +#define RFPGA0_XC_HSSIPARAMETER2 0x834 +#define RFPGA0_XD_HSSIPARAMETER1 0x838 +#define RFPGA0_XD_HSSIPARAMETER2 0x83c +#define RFPGA0_XA_LSSIPARAMETER 0x840 +#define RFPGA0_XB_LSSIPARAMETER 0x844 +#define RFPGA0_XC_LSSIPARAMETER 0x848 +#define RFPGA0_XD_LSSIPARAMETER 0x84c + +#define RFPGA0_RFWAKEUP_PARAMETER 0x850 +#define RFPGA0_RFSLEEPUP_PARAMETER 0x854 + +#define RFPGA0_XAB_SWITCHCONTROL 0x858 +#define RFPGA0_XCD_SWITCHCONTROL 0x85c + +#define RFPGA0_XA_RFINTERFACEOE 0x860 +#define RFPGA0_XB_RFINTERFACEOE 0x864 +#define RFPGA0_XC_RFINTERFACEOE 0x868 +#define RFPGA0_XD_RFINTERFACEOE 0x86c + +#define RFPGA0_XAB_RFINTERFACESW 0x870 +#define RFPGA0_XCD_RFINTERFACESW 0x874 + +#define RFPGA0_XAB_RFPARAMETER 0x878 +#define RFPGA0_XCD_RFPARAMETER 0x87c + +#define RFPGA0_ANALOGPARAMETER1 0x880 +#define RFPGA0_ANALOGPARAMETER2 0x884 +#define RFPGA0_ANALOGPARAMETER3 0x888 +#define RFPGA0_ANALOGPARAMETER4 0x88c + +#define RFPGA0_XA_LSSIREADBACK 0x8a0 +#define RFPGA0_XB_LSSIREADBACK 0x8a4 +#define RFPGA0_XC_LSSIREADBACK 0x8a8 +#define RFPGA0_XD_LSSIREADBACK 0x8ac + +#define RFPGA0_PSDREPORT 0x8b4 +#define TRANSCEIVERA_HSPI_READBACK 0x8b8 +#define TRANSCEIVERB_HSPI_READBACK 0x8bc +#define RFPGA0_XAB_RFINTERFACERB 0x8e0 +#define RFPGA0_XCD_RFINTERFACERB 0x8e4 +#define RFPGA1_RFMOD 0x900 + +#define RFPGA1_TXBLOCK 0x904 +#define RFPGA1_DEBUGSELECT 0x908 +#define RFPGA1_TXINFO 0x90c + +#define RCCK0_SYSTEM 0xa00 + +#define RCCK0_AFESETTING 0xa04 +#define RCCK0_CCA 0xa08 + +#define RCCK0_RXAGC1 0xa0c +#define RCCK0_RXAGC2 0xa10 + +#define RCCK0_RXHP 0xa14 + +#define RCCK0_DSPPARAMETER1 0xa18 +#define RCCK0_DSPPARAMETER2 0xa1c + +#define RCCK0_TXFILTER1 0xa20 +#define RCCK0_TXFILTER2 0xa24 +#define RCCK0_DEBUGPORT 0xa28 +#define RCCK0_FALSEALARMREPORT 0xa2c +#define RCCK0_TRSSIREPORT 0xa50 +#define RCCK0_RXREPORT 0xa54 +#define RCCK0_FACOUNTERLOWER 0xa5c +#define RCCK0_FACOUNTERUPPER 0xa58 + +#define ROFDM0_LSTF 0xc00 + +#define ROFDM0_TRXPATHENABLE 0xc04 +#define ROFDM0_TRMUXPAR 0xc08 +#define ROFDM0_TRSWISOLATION 0xc0c + +#define ROFDM0_XARXAFE 0xc10 +#define ROFDM0_XARXIQIMBALANCE 0xc14 +#define ROFDM0_XBRXAFE 0xc18 +#define ROFDM0_XBRXIQIMBALANCE 0xc1c +#define ROFDM0_XCRXAFE 0xc20 +#define ROFDM0_XCRXIQIMBALANCE 0xc24 +#define ROFDM0_XDRXAFE 0xc28 +#define ROFDM0_XDRXIQIMBALANCE 0xc2c + +#define ROFDM0_RXDETECTOR1 0xc30 +#define ROFDM0_RXDETECTOR2 0xc34 +#define ROFDM0_RXDETECTOR3 0xc38 +#define ROFDM0_RXDETECTOR4 0xc3c + +#define ROFDM0_RXDSP 0xc40 +#define ROFDM0_CFO_AND_DAGC 0xc44 +#define ROFDM0_CCADROP_THRESHOLD 0xc48 +#define ROFDM0_ECCA_THRESHOLD 0xc4c + +#define ROFDM0_XAAGCCORE1 0xc50 +#define ROFDM0_XAAGCCORE2 0xc54 +#define ROFDM0_XBAGCCORE1 0xc58 +#define ROFDM0_XBAGCCORE2 0xc5c +#define ROFDM0_XCAGCCORE1 0xc60 +#define ROFDM0_XCAGCCORE2 0xc64 +#define ROFDM0_XDAGCCORE1 0xc68 +#define ROFDM0_XDAGCCORE2 0xc6c + +#define ROFDM0_AGCPARAMETER1 0xc70 +#define ROFDM0_AGCPARAMETER2 0xc74 +#define ROFDM0_AGCRSSITABLE 0xc78 +#define ROFDM0_HTSTFAGC 0xc7c + +#define ROFDM0_XATXIQIMBALANCE 0xc80 +#define ROFDM0_XATXAFE 0xc84 +#define ROFDM0_XBTXIQIMBALANCE 0xc88 +#define ROFDM0_XBTXAFE 0xc8c +#define ROFDM0_XCTXIQIMBALANCE 0xc90 +#define ROFDM0_XCTXAFE 0xc94 +#define ROFDM0_XDTXIQIMBALANCE 0xc98 +#define ROFDM0_XDTXAFE 0xc9c + +#define ROFDM0_RXHP_PARAMETER 0xce0 +#define ROFDM0_TXPSEUDO_NOISE_WGT 0xce4 +#define ROFDM0_FRAME_SYNC 0xcf0 +#define ROFDM0_DFSREPORT 0xcf4 +#define ROFDM0_TXCOEFF1 0xca4 +#define ROFDM0_TXCOEFF2 0xca8 +#define ROFDM0_TXCOEFF3 0xcac +#define ROFDM0_TXCOEFF4 0xcb0 +#define ROFDM0_TXCOEFF5 0xcb4 +#define ROFDM0_TXCOEFF6 0xcb8 + + +#define ROFDM1_LSTF 0xd00 +#define ROFDM1_TRXPATHENABLE 0xd04 + +#define ROFDM1_CFO 0xd08 +#define ROFDM1_CSI1 0xd10 +#define ROFDM1_SBD 0xd14 +#define ROFDM1_CSI2 0xd18 +#define ROFDM1_CFOTRACKING 0xd2c +#define ROFDM1_TRXMESAURE1 0xd34 +#define ROFDM1_INTF_DET 0xd3c +#define ROFDM1_PSEUDO_NOISESTATEAB 0xd50 +#define ROFDM1_PSEUDO_NOISESTATECD 0xd54 +#define ROFDM1_RX_PSEUDO_NOISE_WGT 0xd58 + +#define ROFDM_PHYCOUNTER1 0xda0 +#define ROFDM_PHYCOUNTER2 0xda4 +#define ROFDM_PHYCOUNTER3 0xda8 + +#define ROFDM_SHORT_CFOAB 0xdac +#define ROFDM_SHORT_CFOCD 0xdb0 +#define ROFDM_LONG_CFOAB 0xdb4 +#define ROFDM_LONG_CFOCD 0xdb8 +#define ROFDM_TAIL_CFOAB 0xdbc +#define ROFDM_TAIL_CFOCD 0xdc0 +#define ROFDM_PW_MEASURE1 0xdc4 +#define ROFDM_PW_MEASURE2 0xdc8 +#define ROFDM_BW_REPORT 0xdcc +#define ROFDM_AGC_REPORT 0xdd0 +#define ROFDM_RXSNR 0xdd4 +#define ROFDM_RXEVMCSI 0xdd8 +#define ROFDM_SIG_REPORT 0xddc + + +#define RTXAGC_RATE18_06 0xe00 +#define RTXAGC_RATE54_24 0xe04 +#define RTXAGC_CCK_MCS32 0xe08 +#define RTXAGC_MCS03_MCS00 0xe10 +#define RTXAGC_MCS07_MCS04 0xe14 +#define RTXAGC_MCS11_MCS08 0xe18 +#define RTXAGC_MCS15_MCS12 0xe1c + + +#define RF_AC 0x00 +#define RF_IQADJ_G1 0x01 +#define RF_IQADJ_G2 0x02 +#define RF_POW_TRSW 0x05 +#define RF_GAIN_RX 0x06 +#define RF_GAIN_TX 0x07 +#define RF_TXM_IDAC 0x08 +#define RF_BS_IQGEN 0x0F + +#define RF_MODE1 0x10 +#define RF_MODE2 0x11 +#define RF_RX_AGC_HP 0x12 +#define RF_TX_AGC 0x13 +#define RF_BIAS 0x14 +#define RF_IPA 0x15 +#define RF_POW_ABILITY 0x17 +#define RF_MODE_AG 0x18 +#define RF_CHANNEL 0x18 +#define RF_CHNLBW 0x18 +#define RF_TOP 0x19 +#define RF_RX_G1 0x1A +#define RF_RX_G2 0x1B +#define RF_RX_BB2 0x1C +#define RF_RX_BB1 0x1D +#define RF_RCK1 0x1E +#define RF_RCK2 0x1F + +#define RF_TX_G1 0x20 +#define RF_TX_G2 0x21 +#define RF_TX_G3 0x22 +#define RF_TX_BB1 0x23 +#define RF_T_METER 0x24 +#define RF_SYN_G1 0x25 +#define RF_SYN_G2 0x26 +#define RF_SYN_G3 0x27 +#define RF_SYN_G4 0x28 +#define RF_SYN_G5 0x29 +#define RF_SYN_G6 0x2A +#define RF_SYN_G7 0x2B +#define RF_SYN_G8 0x2C + +#define RF_RCK_OS 0x30 +#define RF_TXPA_G1 0x31 +#define RF_TXPA_G2 0x32 +#define RF_TXPA_G3 0x33 + +#define BRFMOD 0x1 +#define BCCKEN 0x1000000 +#define BOFDMEN 0x2000000 + +#define BXBTXAGC 0xf00 +#define BXCTXAGC 0xf000 +#define BXDTXAGC 0xf0000 + +#define B3WIRE_DATALENGTH 0x800 +#define B3WIRE_ADDRESSLENGTH 0x400 + +#define BRFSI_RFENV 0x10 + +#define BLSSI_READADDRESS 0x7f800000 +#define BLSSI_READEDGE 0x80000000 +#define BLSSI_READBACK_DATA 0xfffff + +#define BADCLKPHASE 0x4000000 + +#define BCCK_SIDEBAND 0x10 + +#define BTX_AGCRATECCK 0x7f00 + +#define MASKBYTE0 0xff +#define MASKBYTE1 0xff00 +#define MASKBYTE2 0xff0000 +#define MASKBYTE3 0xff000000 +#define MASKHWORD 0xffff0000 +#define MASKLWORD 0x0000ffff +#define MASKDWORD 0xffffffff + +#define MAKS12BITS 0xfffff +#define MASK20BITS 0xfffff +#define RFREG_OFFSET_MASK 0xfffff + +#endif -- cgit v1.2.3-58-ga151 From e5e8cd76511cb62391a5b64fa4ffdf88b09b6826 Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Tue, 3 May 2011 09:48:56 -0500 Subject: rtlwifi: rtl8192se: Merge rf routines Merge routines rf.c and rf.h for RTL8192SE. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192se/rf.c | 546 ++++++++++++++++++++++++++++ drivers/net/wireless/rtlwifi/rtl8192se/rf.h | 43 +++ 2 files changed, 589 insertions(+) create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/rf.c create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/rf.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c new file mode 100644 index 000000000000..1d3a48330399 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c @@ -0,0 +1,546 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" + + +static void _rtl92s_get_powerbase(struct ieee80211_hw *hw, u8 *p_pwrlevel, + u8 chnl, u32 *ofdmbase, u32 *mcsbase, + u8 *p_final_pwridx) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 pwrbase0, pwrbase1; + u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0; + u8 i, pwrlevel[4]; + + for (i = 0; i < 2; i++) + pwrlevel[i] = p_pwrlevel[i]; + + /* We only care about the path A for legacy. */ + if (rtlefuse->eeprom_version < 2) { + pwrbase0 = pwrlevel[0] + (rtlefuse->legacy_httxpowerdiff & 0xf); + } else if (rtlefuse->eeprom_version >= 2) { + legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff + [RF90_PATH_A][chnl - 1]; + + /* For legacy OFDM, tx pwr always > HT OFDM pwr. + * We do not care Path B + * legacy OFDM pwr diff. NO BB register + * to notify HW. */ + pwrbase0 = pwrlevel[0] + legacy_pwrdiff; + } + + pwrbase0 = (pwrbase0 << 24) | (pwrbase0 << 16) | (pwrbase0 << 8) | + pwrbase0; + *ofdmbase = pwrbase0; + + /* MCS rates */ + if (rtlefuse->eeprom_version >= 2) { + /* Check HT20 to HT40 diff */ + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { + for (i = 0; i < 2; i++) { + /* rf-A, rf-B */ + /* HT 20<->40 pwr diff */ + ht20_pwrdiff = rtlefuse->txpwr_ht20diff + [i][chnl - 1]; + + if (ht20_pwrdiff < 8) /* 0~+7 */ + pwrlevel[i] += ht20_pwrdiff; + else /* index8-15=-8~-1 */ + pwrlevel[i] -= (16 - ht20_pwrdiff); + } + } + } + + /* use index of rf-A */ + pwrbase1 = pwrlevel[0]; + pwrbase1 = (pwrbase1 << 24) | (pwrbase1 << 16) | (pwrbase1 << 8) | + pwrbase1; + *mcsbase = pwrbase1; + + /* The following is for Antenna + * diff from Ant-B to Ant-A */ + p_final_pwridx[0] = pwrlevel[0]; + p_final_pwridx[1] = pwrlevel[1]; + + switch (rtlefuse->eeprom_regulatory) { + case 3: + /* The following is for calculation + * of the power diff for Ant-B to Ant-A. */ + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + p_final_pwridx[0] += rtlefuse->pwrgroup_ht40 + [RF90_PATH_A][ + chnl - 1]; + p_final_pwridx[1] += rtlefuse->pwrgroup_ht40 + [RF90_PATH_B][ + chnl - 1]; + } else { + p_final_pwridx[0] += rtlefuse->pwrgroup_ht20 + [RF90_PATH_A][ + chnl - 1]; + p_final_pwridx[1] += rtlefuse->pwrgroup_ht20 + [RF90_PATH_B][ + chnl - 1]; + } + break; + default: + break; + } + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("40MHz finalpwr_idx " + "(A / B) = 0x%x / 0x%x\n", p_final_pwridx[0], + p_final_pwridx[1])); + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("20MHz finalpwr_idx " + "(A / B) = 0x%x / 0x%x\n", p_final_pwridx[0], + p_final_pwridx[1])); + } +} + +static void _rtl92s_set_antennadiff(struct ieee80211_hw *hw, + u8 *p_final_pwridx) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + char ant_pwr_diff = 0; + u32 u4reg_val = 0; + + if (rtlphy->rf_type == RF_2T2R) { + ant_pwr_diff = p_final_pwridx[1] - p_final_pwridx[0]; + + /* range is from 7~-8, + * index = 0x0~0xf */ + if (ant_pwr_diff > 7) + ant_pwr_diff = 7; + if (ant_pwr_diff < -8) + ant_pwr_diff = -8; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("Antenna Diff from RF-B " + "to RF-A = %d (0x%x)\n", ant_pwr_diff, + ant_pwr_diff & 0xf)); + + ant_pwr_diff &= 0xf; + } + + /* Antenna TX power difference */ + rtlefuse->antenna_txpwdiff[2] = 0;/* RF-D, don't care */ + rtlefuse->antenna_txpwdiff[1] = 0;/* RF-C, don't care */ + rtlefuse->antenna_txpwdiff[0] = (u8)(ant_pwr_diff); /* RF-B */ + + u4reg_val = rtlefuse->antenna_txpwdiff[2] << 8 | + rtlefuse->antenna_txpwdiff[1] << 4 | + rtlefuse->antenna_txpwdiff[0]; + + rtl_set_bbreg(hw, RFPGA0_TXGAINSTAGE, (BXBTXAGC | BXCTXAGC | BXDTXAGC), + u4reg_val); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("Write BCD-Diff(0x%x) = 0x%x\n", + RFPGA0_TXGAINSTAGE, u4reg_val)); +} + +static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw, + u8 chnl, u8 index, + u32 pwrbase0, + u32 pwrbase1, + u32 *p_outwrite_val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 i, chnlgroup, pwrdiff_limit[4]; + u32 writeval, customer_limit; + + /* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */ + switch (rtlefuse->eeprom_regulatory) { + case 0: + /* Realtek better performance increase power diff + * defined by Realtek for large power */ + chnlgroup = 0; + + writeval = rtlphy->mcs_txpwrlevel_origoffset + [chnlgroup][index] + + ((index < 2) ? pwrbase0 : pwrbase1); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("RTK better performance, " + "writeval = 0x%x\n", writeval)); + break; + case 1: + /* Realtek regulatory increase power diff defined + * by Realtek for regulatory */ + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + writeval = ((index < 2) ? pwrbase0 : pwrbase1); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("Realtek regulatory, " + "40MHz, writeval = 0x%x\n", writeval)); + } else { + if (rtlphy->pwrgroup_cnt == 1) + chnlgroup = 0; + + if (rtlphy->pwrgroup_cnt >= 3) { + if (chnl <= 3) + chnlgroup = 0; + else if (chnl >= 4 && chnl <= 8) + chnlgroup = 1; + else if (chnl > 8) + chnlgroup = 2; + if (rtlphy->pwrgroup_cnt == 4) + chnlgroup++; + } + + writeval = rtlphy->mcs_txpwrlevel_origoffset + [chnlgroup][index] + + ((index < 2) ? + pwrbase0 : pwrbase1); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("Realtek regulatory, " + "20MHz, writeval = 0x%x\n", writeval)); + } + break; + case 2: + /* Better regulatory don't increase any power diff */ + writeval = ((index < 2) ? pwrbase0 : pwrbase1); + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("Better regulatory, " + "writeval = 0x%x\n", writeval)); + break; + case 3: + /* Customer defined power diff. increase power diff + defined by customer. */ + chnlgroup = 0; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("customer's limit, 40MHz = 0x%x\n", + rtlefuse->pwrgroup_ht40 + [RF90_PATH_A][chnl - 1])); + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("customer's limit, 20MHz = 0x%x\n", + rtlefuse->pwrgroup_ht20 + [RF90_PATH_A][chnl - 1])); + } + + for (i = 0; i < 4; i++) { + pwrdiff_limit[i] = + (u8)((rtlphy->mcs_txpwrlevel_origoffset + [chnlgroup][index] & (0x7f << (i * 8))) + >> (i * 8)); + + if (rtlphy->current_chan_bw == + HT_CHANNEL_WIDTH_20_40) { + if (pwrdiff_limit[i] > + rtlefuse->pwrgroup_ht40 + [RF90_PATH_A][chnl - 1]) { + pwrdiff_limit[i] = + rtlefuse->pwrgroup_ht20 + [RF90_PATH_A][chnl - 1]; + } + } else { + if (pwrdiff_limit[i] > + rtlefuse->pwrgroup_ht20 + [RF90_PATH_A][chnl - 1]) { + pwrdiff_limit[i] = + rtlefuse->pwrgroup_ht20 + [RF90_PATH_A][chnl - 1]; + } + } + } + + customer_limit = (pwrdiff_limit[3] << 24) | + (pwrdiff_limit[2] << 16) | + (pwrdiff_limit[1] << 8) | + (pwrdiff_limit[0]); + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("Customer's limit = 0x%x\n", + customer_limit)); + + writeval = customer_limit + ((index < 2) ? + pwrbase0 : pwrbase1); + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("Customer, writeval = " + "0x%x\n", writeval)); + break; + default: + chnlgroup = 0; + writeval = rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index] + + ((index < 2) ? pwrbase0 : pwrbase1); + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("RTK better performance, " + "writeval = 0x%x\n", writeval)); + break; + } + + if (rtlpriv->dm.dynamic_txhighpower_lvl == TX_HIGH_PWR_LEVEL_LEVEL1) + writeval = 0x10101010; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TX_HIGH_PWR_LEVEL_LEVEL2) + writeval = 0x0; + + *p_outwrite_val = writeval; + +} + +static void _rtl92s_write_ofdm_powerreg(struct ieee80211_hw *hw, + u8 index, u32 val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u16 regoffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c}; + u8 i, rfa_pwr[4]; + u8 rfa_lower_bound = 0, rfa_upper_bound = 0, rf_pwr_diff = 0; + u32 writeval = val; + + /* If path A and Path B coexist, we must limit Path A tx power. + * Protect Path B pwr over or under flow. We need to calculate + * upper and lower bound of path A tx power. */ + if (rtlphy->rf_type == RF_2T2R) { + rf_pwr_diff = rtlefuse->antenna_txpwdiff[0]; + + /* Diff=-8~-1 */ + if (rf_pwr_diff >= 8) { + /* Prevent underflow!! */ + rfa_lower_bound = 0x10 - rf_pwr_diff; + /* if (rf_pwr_diff >= 0) Diff = 0-7 */ + } else { + rfa_upper_bound = RF6052_MAX_TX_PWR - rf_pwr_diff; + } + } + + for (i = 0; i < 4; i++) { + rfa_pwr[i] = (u8)((writeval & (0x7f << (i * 8))) >> (i * 8)); + if (rfa_pwr[i] > RF6052_MAX_TX_PWR) + rfa_pwr[i] = RF6052_MAX_TX_PWR; + + /* If path A and Path B coexist, we must limit Path A tx power. + * Protect Path B pwr over or under flow. We need to calculate + * upper and lower bound of path A tx power. */ + if (rtlphy->rf_type == RF_2T2R) { + /* Diff=-8~-1 */ + if (rf_pwr_diff >= 8) { + /* Prevent underflow!! */ + if (rfa_pwr[i] < rfa_lower_bound) + rfa_pwr[i] = rfa_lower_bound; + /* Diff = 0-7 */ + } else if (rf_pwr_diff >= 1) { + /* Prevent overflow */ + if (rfa_pwr[i] > rfa_upper_bound) + rfa_pwr[i] = rfa_upper_bound; + } + } + + } + + writeval = (rfa_pwr[3] << 24) | (rfa_pwr[2] << 16) | (rfa_pwr[1] << 8) | + rfa_pwr[0]; + + rtl_set_bbreg(hw, regoffset[index], 0x7f7f7f7f, writeval); +} + +void rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw, + u8 *p_pwrlevel, u8 chnl) +{ + u32 writeval, pwrbase0, pwrbase1; + u8 index = 0; + u8 finalpwr_idx[4]; + + _rtl92s_get_powerbase(hw, p_pwrlevel, chnl, &pwrbase0, &pwrbase1, + &finalpwr_idx[0]); + _rtl92s_set_antennadiff(hw, &finalpwr_idx[0]); + + for (index = 0; index < 6; index++) { + _rtl92s_get_txpower_writeval_byregulatory(hw, chnl, index, + pwrbase0, pwrbase1, &writeval); + + _rtl92s_write_ofdm_powerreg(hw, index, writeval); + } +} + +void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, u8 pwrlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 txagc = 0; + bool dont_inc_cck_or_turboscanoff = false; + + if (((rtlefuse->eeprom_version >= 2) && + (rtlefuse->txpwr_safetyflag == 1)) || + ((rtlefuse->eeprom_version >= 2) && + (rtlefuse->eeprom_regulatory != 0))) + dont_inc_cck_or_turboscanoff = true; + + if (mac->act_scanning == true) { + txagc = 0x3f; + if (dont_inc_cck_or_turboscanoff) + txagc = pwrlevel; + } else { + txagc = pwrlevel; + + if (rtlpriv->dm.dynamic_txhighpower_lvl == + TX_HIGH_PWR_LEVEL_LEVEL1) + txagc = 0x10; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TX_HIGH_PWR_LEVEL_LEVEL2) + txagc = 0x0; + } + + if (txagc > RF6052_MAX_TX_PWR) + txagc = RF6052_MAX_TX_PWR; + + rtl_set_bbreg(hw, RTXAGC_CCK_MCS32, BTX_AGCRATECCK, txagc); + +} + +bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 u4reg_val = 0; + u8 rfpath; + bool rtstatus = true; + struct bb_reg_def *pphyreg; + + /* Initialize RF */ + for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { + + pphyreg = &rtlphy->phyreg_def[rfpath]; + + /* Store original RFENV control type */ + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + u4reg_val = rtl92s_phy_query_bb_reg(hw, + pphyreg->rfintfs, + BRFSI_RFENV); + break; + case RF90_PATH_B: + case RF90_PATH_D: + u4reg_val = rtl92s_phy_query_bb_reg(hw, + pphyreg->rfintfs, + BRFSI_RFENV << 16); + break; + } + + /* Set RF_ENV enable */ + rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfe, + BRFSI_RFENV << 16, 0x1); + + /* Set RF_ENV output high */ + rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); + + /* Set bit number of Address and Data for RF register */ + rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2, + B3WIRE_ADDRESSLENGTH, 0x0); + rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2, + B3WIRE_DATALENGTH, 0x0); + + /* Initialize RF fom connfiguration file */ + switch (rfpath) { + case RF90_PATH_A: + rtstatus = rtl92s_phy_config_rf(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_B: + rtstatus = rtl92s_phy_config_rf(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_C: + break; + case RF90_PATH_D: + break; + } + + /* Restore RFENV control type */ + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs, BRFSI_RFENV, + u4reg_val); + break; + case RF90_PATH_B: + case RF90_PATH_D: + rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16, + u4reg_val); + break; + } + + if (rtstatus != true) { + printk(KERN_ERR "Radio[%d] Fail!!", rfpath); + goto fail; + } + + } + + return rtstatus; + +fail: + return rtstatus; +} + +void rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff) | 0x0400); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + case HT_CHANNEL_WIDTH_20_40: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff)); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("unknown bandwidth: %#X\n", + bandwidth)); + break; + } +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.h b/drivers/net/wireless/rtlwifi/rtl8192se/rf.h new file mode 100644 index 000000000000..3843baa1a874 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __INC_RTL92S_RF_H +#define __INC_RTL92S_RF_H + +#define RF6052_MAX_TX_PWR 0x3F + +void rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, + u8 bandwidth); +bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw) ; +void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, + u8 powerlevel); +void rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw, + u8 *p_pwrlevel, u8 chnl); + +#endif + -- cgit v1.2.3-58-ga151 From 5a183eec6247d3d992afbd3a1a9658571d9c4970 Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Tue, 3 May 2011 09:49:06 -0500 Subject: rtlwifi: rtl8192se: Merge main (sw) routines Merge routines sw.c and sw.h for RTL8192SE. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192se/sw.c | 421 ++++++++++++++++++++++++++++ drivers/net/wireless/rtlwifi/rtl8192se/sw.h | 36 +++ 2 files changed, 457 insertions(+) create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/sw.c create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/sw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c new file mode 100644 index 000000000000..c5351b65b339 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c @@ -0,0 +1,421 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include + +#include "../wifi.h" +#include "../core.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "hw.h" +#include "sw.h" +#include "trx.h" +#include "led.h" + +static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*close ASPM for AMD defaultly */ + rtlpci->const_amdpci_aspm = 0; + + /* + * ASPM PS mode. + * 0 - Disable ASPM, + * 1 - Enable ASPM without Clock Req, + * 2 - Enable ASPM with Clock Req, + * 3 - Alwyas Enable ASPM with Clock Req, + * 4 - Always Enable ASPM without Clock Req. + * set defult to RTL8192CE:3 RTL8192E:2 + * */ + rtlpci->const_pci_aspm = 2; + + /*Setting for PCI-E device */ + rtlpci->const_devicepci_aspm_setting = 0x03; + + /*Setting for PCI-E bridge */ + rtlpci->const_hostpci_aspm_setting = 0x02; + + /* + * In Hw/Sw Radio Off situation. + * 0 - Default, + * 1 - From ASPM setting without low Mac Pwr, + * 2 - From ASPM setting with low Mac Pwr, + * 3 - Bus D3 + * set default to RTL8192CE:0 RTL8192SE:2 + */ + rtlpci->const_hwsw_rfoff_d3 = 2; + + /* + * This setting works for those device with + * backdoor ASPM setting such as EPHY setting. + * 0 - Not support ASPM, + * 1 - Support ASPM, + * 2 - According to chipset. + */ + rtlpci->const_support_pciaspm = 2; +} + +static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + const struct firmware *firmware; + struct rt_firmware *pfirmware = NULL; + int err = 0; + u16 earlyrxthreshold = 7; + + rtlpriv->dm.dm_initialgain_enable = 1; + rtlpriv->dm.dm_flag = 0; + rtlpriv->dm.disable_framebursting = 0; + rtlpriv->dm.thermalvalue = 0; + rtlpriv->dm.useramask = true; + + /* compatible 5G band 91se just 2.4G band & smsp */ + rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; + rtlpriv->rtlhal.bandset = BAND_ON_2_4G; + rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; + + rtlpci->transmit_config = 0; + + rtlpci->receive_config = + RCR_APPFCS | + RCR_APWRMGT | + /*RCR_ADD3 |*/ + RCR_AMF | + RCR_ADF | + RCR_APP_MIC | + RCR_APP_ICV | + RCR_AICV | + /* Accept ICV error, CRC32 Error */ + RCR_ACRC32 | + RCR_AB | + /* Accept Broadcast, Multicast */ + RCR_AM | + /* Accept Physical match */ + RCR_APM | + /* Accept Destination Address packets */ + /*RCR_AAP |*/ + RCR_APP_PHYST_STAFF | + /* Accept PHY status */ + RCR_APP_PHYST_RXFF | + (earlyrxthreshold << RCR_FIFO_OFFSET); + + rtlpci->irq_mask[0] = (u32) + (IMR_ROK | + IMR_VODOK | + IMR_VIDOK | + IMR_BEDOK | + IMR_BKDOK | + IMR_HCCADOK | + IMR_MGNTDOK | + IMR_COMDOK | + IMR_HIGHDOK | + IMR_BDOK | + IMR_RXCMDOK | + /*IMR_TIMEOUT0 |*/ + IMR_RDU | + IMR_RXFOVW | + IMR_BCNINT + /*| IMR_TXFOVW*/ + /*| IMR_TBDOK | + IMR_TBDER*/); + + rtlpci->irq_mask[1] = (u32) 0; + + rtlpci->shortretry_limit = 0x30; + rtlpci->longretry_limit = 0x30; + + rtlpci->first_init = true; + + /* for LPS & IPS */ + rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; + rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; + rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; + rtlpriv->psc.reg_fwctrl_lps = 3; + rtlpriv->psc.reg_max_lps_awakeintvl = 5; + /* for ASPM, you can close aspm through + * set const_support_pciaspm = 0 */ + rtl92s_init_aspm_vars(hw); + + if (rtlpriv->psc.reg_fwctrl_lps == 1) + rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 2) + rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 3) + rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; + + /* for firmware buf */ + rtlpriv->rtlhal.pfirmware = vzalloc(sizeof(struct rt_firmware)); + if (!rtlpriv->rtlhal.pfirmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Can't alloc buffer for fw.\n")); + return 1; + } + + /* request fw */ + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Failed to request firmware!\n")); + return 1; + } + if (firmware->size > sizeof(struct rt_firmware)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Firmware is too big!\n")); + release_firmware(firmware); + return 1; + } + + pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware; + memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size); + pfirmware->sz_fw_tmpbufferlen = firmware->size; + release_firmware(firmware); + + return err; +} + +static void rtl92s_deinit_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->rtlhal.pfirmware) { + vfree(rtlpriv->rtlhal.pfirmware); + rtlpriv->rtlhal.pfirmware = NULL; + } +} + +static struct rtl_hal_ops rtl8192se_hal_ops = { + .init_sw_vars = rtl92s_init_sw_vars, + .deinit_sw_vars = rtl92s_deinit_sw_vars, + .read_eeprom_info = rtl92se_read_eeprom_info, + .interrupt_recognized = rtl92se_interrupt_recognized, + .hw_init = rtl92se_hw_init, + .hw_disable = rtl92se_card_disable, + .hw_suspend = rtl92se_suspend, + .hw_resume = rtl92se_resume, + .enable_interrupt = rtl92se_enable_interrupt, + .disable_interrupt = rtl92se_disable_interrupt, + .set_network_type = rtl92se_set_network_type, + .set_chk_bssid = rtl92se_set_check_bssid, + .set_qos = rtl92se_set_qos, + .set_bcn_reg = rtl92se_set_beacon_related_registers, + .set_bcn_intv = rtl92se_set_beacon_interval, + .update_interrupt_mask = rtl92se_update_interrupt_mask, + .get_hw_reg = rtl92se_get_hw_reg, + .set_hw_reg = rtl92se_set_hw_reg, + .update_rate_tbl = rtl92se_update_hal_rate_tbl, + .fill_tx_desc = rtl92se_tx_fill_desc, + .fill_tx_cmddesc = rtl92se_tx_fill_cmddesc, + .query_rx_desc = rtl92se_rx_query_desc, + .set_channel_access = rtl92se_update_channel_access_setting, + .radio_onoff_checking = rtl92se_gpio_radio_on_off_checking, + .set_bw_mode = rtl92s_phy_set_bw_mode, + .switch_channel = rtl92s_phy_sw_chnl, + .dm_watchdog = rtl92s_dm_watchdog, + .scan_operation_backup = rtl92s_phy_scan_operation_backup, + .set_rf_power_state = rtl92s_phy_set_rf_power_state, + .led_control = rtl92se_led_control, + .set_desc = rtl92se_set_desc, + .get_desc = rtl92se_get_desc, + .tx_polling = rtl92se_tx_polling, + .enable_hw_sec = rtl92se_enable_hw_security_config, + .set_key = rtl92se_set_key, + .init_sw_leds = rtl92se_init_sw_leds, + .get_bbreg = rtl92s_phy_query_bb_reg, + .set_bbreg = rtl92s_phy_set_bb_reg, + .get_rfreg = rtl92s_phy_query_rf_reg, + .set_rfreg = rtl92s_phy_set_rf_reg, +}; + +static struct rtl_mod_params rtl92se_mod_params = { + .sw_crypto = false, + .inactiveps = true, + .swctrl_lps = true, + .fwctrl_lps = false, +}; + +/* Because memory R/W bursting will cause system hang/crash + * for 92se, so we don't read back after every write action */ +static struct rtl_hal_cfg rtl92se_hal_cfg = { + .bar_id = 1, + .write_readback = false, + .name = "rtl92s_pci", + .fw_name = "rtlwifi/rtl8192sefw.bin", + .ops = &rtl8192se_hal_ops, + .mod_params = &rtl92se_mod_params, + + .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, + .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, + .maps[SYS_CLK] = SYS_CLKR, + .maps[MAC_RCR_AM] = RCR_AM, + .maps[MAC_RCR_AB] = RCR_AB, + .maps[MAC_RCR_ACRC32] = RCR_ACRC32, + .maps[MAC_RCR_ACF] = RCR_ACF, + .maps[MAC_RCR_AAP] = RCR_AAP, + + .maps[EFUSE_TEST] = REG_EFUSE_TEST, + .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_CLK] = REG_EFUSE_CLK, + .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_PWC_EV12V] = 0, /* nouse for 8192se */ + .maps[EFUSE_FEN_ELDR] = 0, /* nouse for 8192se */ + .maps[EFUSE_LOADER_CLK_EN] = 0,/* nouse for 8192se */ + .maps[EFUSE_ANA8M] = EFUSE_ANA8M, + .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE_92S, + .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, + .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, + + .maps[RWCAM] = REG_RWCAM, + .maps[WCAMI] = REG_WCAMI, + .maps[RCAMO] = REG_RCAMO, + .maps[CAMDBG] = REG_CAMDBG, + .maps[SECR] = REG_SECR, + .maps[SEC_CAM_NONE] = CAM_NONE, + .maps[SEC_CAM_WEP40] = CAM_WEP40, + .maps[SEC_CAM_TKIP] = CAM_TKIP, + .maps[SEC_CAM_AES] = CAM_AES, + .maps[SEC_CAM_WEP104] = CAM_WEP104, + + .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, + .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, + .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, + .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, + .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, + .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, + .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, + .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, + .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, + .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, + .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, + .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, + .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, + .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, + .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, + .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, + + .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, + .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, + .maps[RTL_IMR_BcnInt] = IMR_BCNINT, + .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, + .maps[RTL_IMR_RDU] = IMR_RDU, + .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, + .maps[RTL_IMR_BDOK] = IMR_BDOK, + .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, + .maps[RTL_IMR_TBDER] = IMR_TBDER, + .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, + .maps[RTL_IMR_COMDOK] = IMR_COMDOK, + .maps[RTL_IMR_TBDOK] = IMR_TBDOK, + .maps[RTL_IMR_BKDOK] = IMR_BKDOK, + .maps[RTL_IMR_BEDOK] = IMR_BEDOK, + .maps[RTL_IMR_VIDOK] = IMR_VIDOK, + .maps[RTL_IMR_VODOK] = IMR_VODOK, + .maps[RTL_IMR_ROK] = IMR_ROK, + .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), + + .maps[RTL_RC_CCK_RATE1M] = DESC92S_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92S_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92S_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92S_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92S_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92S_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92S_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92S_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92S_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92S_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92S_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92S_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC92S_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92S_RATEMCS15, +}; + +static struct pci_device_id rtl92se_pci_ids[] __devinitdata = { + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8192, rtl92se_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8171, rtl92se_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8172, rtl92se_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8173, rtl92se_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8174, rtl92se_hal_cfg)}, + {}, +}; + +MODULE_DEVICE_TABLE(pci, rtl92se_pci_ids); + +MODULE_AUTHOR("lizhaoming "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Realtek 8192S/8191S 802.11n PCI wireless"); +MODULE_FIRMWARE("rtlwifi/rtl8192sefw.bin"); + +module_param_named(swenc, rtl92se_mod_params.sw_crypto, bool, 0444); +module_param_named(ips, rtl92se_mod_params.inactiveps, bool, 0444); +module_param_named(swlps, rtl92se_mod_params.swctrl_lps, bool, 0444); +module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, bool, 0444); +MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); +MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n"); +MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1 is " + "open)\n"); + + +static struct pci_driver rtl92se_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl92se_pci_ids, + .probe = rtl_pci_probe, + .remove = rtl_pci_disconnect, + +#ifdef CONFIG_PM + .suspend = rtl_pci_suspend, + .resume = rtl_pci_resume, +#endif + +}; + +static int __init rtl92se_module_init(void) +{ + int ret = 0; + + ret = pci_register_driver(&rtl92se_driver); + if (ret) + RT_ASSERT(false, (": No device found\n")); + + return ret; +} + +static void __exit rtl92se_module_exit(void) +{ + pci_unregister_driver(&rtl92se_driver); +} + +module_init(rtl92se_module_init); +module_exit(rtl92se_module_exit); diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.h b/drivers/net/wireless/rtlwifi/rtl8192se/sw.h new file mode 100644 index 000000000000..fc4eb285a0ac --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.h @@ -0,0 +1,36 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + *****************************************************************************/ +#ifndef __REALTEK_PCI92SE_SW_H__ +#define __REALTEK_PCI92SE_SW_H__ + +#define EFUSE_MAX_SECTION 16 + +int rtl92se_init_sw(struct ieee80211_hw *hw); +void rtl92se_deinit_sw(struct ieee80211_hw *hw); +void rtl92se_init_var_map(struct ieee80211_hw *hw); + +#endif -- cgit v1.2.3-58-ga151 From 18906ae27d233914d54f41e5fcf3fdfdf2fb69a9 Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Tue, 3 May 2011 09:49:16 -0500 Subject: rtlwifi: rtl8192se: Merge table routines Merge routines table.c and table.h for RTL8192SE. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192se/table.c | 634 +++++++++++++++++++++++++ drivers/net/wireless/rtlwifi/rtl8192se/table.h | 49 ++ 2 files changed, 683 insertions(+) create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/table.c create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/table.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/table.c b/drivers/net/wireless/rtlwifi/rtl8192se/table.c new file mode 100644 index 000000000000..154185b3969d --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/table.c @@ -0,0 +1,634 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + * Created on 2010/ 5/18, 1:41 + *****************************************************************************/ + +#include "table.h" + +u32 rtl8192sephy_reg_2t2rarray[PHY_REG_2T2RARRAYLENGTH] = { + 0x01c, 0x07000000, + 0x800, 0x00040000, + 0x804, 0x00008003, + 0x808, 0x0000fc00, + 0x80c, 0x0000000a, + 0x810, 0x10005088, + 0x814, 0x020c3d10, + 0x818, 0x00200185, + 0x81c, 0x00000000, + 0x820, 0x01000000, + 0x824, 0x00390004, + 0x828, 0x01000000, + 0x82c, 0x00390004, + 0x830, 0x00000004, + 0x834, 0x00690200, + 0x838, 0x00000004, + 0x83c, 0x00690200, + 0x840, 0x00010000, + 0x844, 0x00010000, + 0x848, 0x00000000, + 0x84c, 0x00000000, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x48484848, + 0x85c, 0x65a965a9, + 0x860, 0x0f7f0130, + 0x864, 0x0f7f0130, + 0x868, 0x0f7f0130, + 0x86c, 0x0f7f0130, + 0x870, 0x03000700, + 0x874, 0x03000300, + 0x878, 0x00020002, + 0x87c, 0x004f0201, + 0x880, 0xa8300ac1, + 0x884, 0x00000058, + 0x888, 0x00000008, + 0x88c, 0x00000004, + 0x890, 0x00000000, + 0x894, 0xfffffffe, + 0x898, 0x40302010, + 0x89c, 0x00706050, + 0x8b0, 0x00000000, + 0x8e0, 0x00000000, + 0x8e4, 0x00000000, + 0xe00, 0x30333333, + 0xe04, 0x2a2d2e2f, + 0xe08, 0x00003232, + 0xe10, 0x30333333, + 0xe14, 0x2a2d2e2f, + 0xe18, 0x30333333, + 0xe1c, 0x2a2d2e2f, + 0xe30, 0x01007c00, + 0xe34, 0x01004800, + 0xe38, 0x1000dc1f, + 0xe3c, 0x10008c1f, + 0xe40, 0x021400a0, + 0xe44, 0x281600a0, + 0xe48, 0xf8000001, + 0xe4c, 0x00002910, + 0xe50, 0x01007c00, + 0xe54, 0x01004800, + 0xe58, 0x1000dc1f, + 0xe5c, 0x10008c1f, + 0xe60, 0x021400a0, + 0xe64, 0x281600a0, + 0xe6c, 0x00002910, + 0xe70, 0x31ed92fb, + 0xe74, 0x361536fb, + 0xe78, 0x361536fb, + 0xe7c, 0x361536fb, + 0xe80, 0x361536fb, + 0xe84, 0x000d92fb, + 0xe88, 0x000d92fb, + 0xe8c, 0x31ed92fb, + 0xed0, 0x31ed92fb, + 0xed4, 0x31ed92fb, + 0xed8, 0x000d92fb, + 0xedc, 0x000d92fb, + 0xee0, 0x000d92fb, + 0xee4, 0x015e5448, + 0xee8, 0x21555448, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90c, 0x01121313, + 0xa00, 0x00d047c8, + 0xa04, 0x80ff0008, + 0xa08, 0x8ccd8300, + 0xa0c, 0x2e62120f, + 0xa10, 0x9500bb78, + 0xa14, 0x11144028, + 0xa18, 0x00881117, + 0xa1c, 0x89140f00, + 0xa20, 0x1a1b0000, + 0xa24, 0x090e1317, + 0xa28, 0x00000204, + 0xa2c, 0x10d30000, + 0xc00, 0x40071d40, + 0xc04, 0x00a05633, + 0xc08, 0x000000e4, + 0xc0c, 0x6c6c6c6c, + 0xc10, 0x08800000, + 0xc14, 0x40000100, + 0xc18, 0x08000000, + 0xc1c, 0x40000100, + 0xc20, 0x08000000, + 0xc24, 0x40000100, + 0xc28, 0x08000000, + 0xc2c, 0x40000100, + 0xc30, 0x6de9ac44, + 0xc34, 0x469652cf, + 0xc38, 0x49795994, + 0xc3c, 0x0a979764, + 0xc40, 0x1f7c403f, + 0xc44, 0x000100b7, + 0xc48, 0xec020000, + 0xc4c, 0x007f037f, + 0xc50, 0x69543420, + 0xc54, 0x433c0094, + 0xc58, 0x69543420, + 0xc5c, 0x433c0094, + 0xc60, 0x69543420, + 0xc64, 0x433c0094, + 0xc68, 0x69543420, + 0xc6c, 0x433c0094, + 0xc70, 0x2c7f000d, + 0xc74, 0x0186155b, + 0xc78, 0x0000001f, + 0xc7c, 0x00b91612, + 0xc80, 0x40000100, + 0xc84, 0x20f60000, + 0xc88, 0x20000080, + 0xc8c, 0x20200000, + 0xc90, 0x40000100, + 0xc94, 0x00000000, + 0xc98, 0x40000100, + 0xc9c, 0x00000000, + 0xca0, 0x00492492, + 0xca4, 0x00000000, + 0xca8, 0x00000000, + 0xcac, 0x00000000, + 0xcb0, 0x00000000, + 0xcb4, 0x00000000, + 0xcb8, 0x00000000, + 0xcbc, 0x28000000, + 0xcc0, 0x00000000, + 0xcc4, 0x00000000, + 0xcc8, 0x00000000, + 0xccc, 0x00000000, + 0xcd0, 0x00000000, + 0xcd4, 0x00000000, + 0xcd8, 0x64b22427, + 0xcdc, 0x00766932, + 0xce0, 0x00222222, + 0xce4, 0x00000000, + 0xce8, 0x37644302, + 0xcec, 0x2f97d40c, + 0xd00, 0x00000750, + 0xd04, 0x00000403, + 0xd08, 0x0000907f, + 0xd0c, 0x00000001, + 0xd10, 0xa0633333, + 0xd14, 0x33333c63, + 0xd18, 0x6a8f5b6b, + 0xd1c, 0x00000000, + 0xd20, 0x00000000, + 0xd24, 0x00000000, + 0xd28, 0x00000000, + 0xd2c, 0xcc979975, + 0xd30, 0x00000000, + 0xd34, 0x00000000, + 0xd38, 0x00000000, + 0xd3c, 0x00027293, + 0xd40, 0x00000000, + 0xd44, 0x00000000, + 0xd48, 0x00000000, + 0xd50, 0x6437140a, + 0xd54, 0x024dbd02, + 0xd58, 0x00000000, + 0xd5c, 0x30032064, + 0xd60, 0x4653de68, + 0xd64, 0x00518a3c, + 0xd68, 0x00002101, + 0xf14, 0x00000003, + 0xf4c, 0x00000000, + 0xf00, 0x00000300, +}; + +u32 rtl8192sephy_changeto_1t1rarray[PHY_CHANGETO_1T1RARRAYLENGTH] = { + 0x844, 0xffffffff, 0x00010000, + 0x804, 0x0000000f, 0x00000001, + 0x824, 0x00f0000f, 0x00300004, + 0x82c, 0x00f0000f, 0x00100002, + 0x870, 0x04000000, 0x00000001, + 0x864, 0x00000400, 0x00000000, + 0x878, 0x000f000f, 0x00000002, + 0xe74, 0x0f000000, 0x00000002, + 0xe78, 0x0f000000, 0x00000002, + 0xe7c, 0x0f000000, 0x00000002, + 0xe80, 0x0f000000, 0x00000002, + 0x90c, 0x000000ff, 0x00000011, + 0xc04, 0x000000ff, 0x00000011, + 0xd04, 0x0000000f, 0x00000001, + 0x1f4, 0xffff0000, 0x00007777, + 0x234, 0xf8000000, 0x0000000a, +}; + +u32 rtl8192sephy_changeto_1t2rarray[PHY_CHANGETO_1T2RARRAYLENGTH] = { + 0x804, 0x0000000f, 0x00000003, + 0x824, 0x00f0000f, 0x00300004, + 0x82c, 0x00f0000f, 0x00300002, + 0x870, 0x04000000, 0x00000001, + 0x864, 0x00000400, 0x00000000, + 0x878, 0x000f000f, 0x00000002, + 0xe74, 0x0f000000, 0x00000002, + 0xe78, 0x0f000000, 0x00000002, + 0xe7c, 0x0f000000, 0x00000002, + 0xe80, 0x0f000000, 0x00000002, + 0x90c, 0x000000ff, 0x00000011, + 0xc04, 0x000000ff, 0x00000033, + 0xd04, 0x0000000f, 0x00000003, + 0x1f4, 0xffff0000, 0x00007777, + 0x234, 0xf8000000, 0x0000000a, +}; + +u32 rtl8192sephy_reg_array_pg[PHY_REG_ARRAY_PGLENGTH] = { + 0xe00, 0xffffffff, 0x06090909, + 0xe04, 0xffffffff, 0x00030406, + 0xe08, 0x0000ff00, 0x00000000, + 0xe10, 0xffffffff, 0x0a0c0d0e, + 0xe14, 0xffffffff, 0x04070809, + 0xe18, 0xffffffff, 0x0a0c0d0e, + 0xe1c, 0xffffffff, 0x04070809, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0xe10, 0xffffffff, 0x02040404, + 0xe14, 0xffffffff, 0x00000002, + 0xe18, 0xffffffff, 0x02040404, + 0xe1c, 0xffffffff, 0x00000002, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0xe10, 0xffffffff, 0x02040404, + 0xe14, 0xffffffff, 0x00000002, + 0xe18, 0xffffffff, 0x02040404, + 0xe1c, 0xffffffff, 0x00000002, + 0xe00, 0xffffffff, 0x02020202, + 0xe04, 0xffffffff, 0x00020202, + 0xe08, 0x0000ff00, 0x00000000, + 0xe10, 0xffffffff, 0x02020202, + 0xe14, 0xffffffff, 0x00000002, + 0xe18, 0xffffffff, 0x02020202, + 0xe1c, 0xffffffff, 0x00000002, +}; + +u32 rtl8192seradioa_1t_array[RADIOA_1T_ARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00030250, + 0x002, 0x00010000, + 0x010, 0x0008000f, + 0x011, 0x000231fc, + 0x010, 0x000c000f, + 0x011, 0x0003f9f8, + 0x010, 0x0002000f, + 0x011, 0x00020101, + 0x014, 0x0001093e, + 0x014, 0x0009093e, + 0x015, 0x0000f8f4, + 0x017, 0x000f6500, + 0x01a, 0x00013056, + 0x01b, 0x00060000, + 0x01c, 0x00000300, + 0x01e, 0x00031059, + 0x021, 0x00054000, + 0x022, 0x0000083c, + 0x023, 0x00001558, + 0x024, 0x00000060, + 0x025, 0x00022583, + 0x026, 0x0000f200, + 0x027, 0x000eacf1, + 0x028, 0x0009bd54, + 0x029, 0x00004582, + 0x02a, 0x00000001, + 0x02b, 0x00021334, + 0x02a, 0x00000000, + 0x02b, 0x0000000a, + 0x02a, 0x00000001, + 0x02b, 0x00000808, + 0x02b, 0x00053333, + 0x02c, 0x0000000c, + 0x02a, 0x00000002, + 0x02b, 0x00000808, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000003, + 0x02b, 0x00000808, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000004, + 0x02b, 0x00000808, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000005, + 0x02b, 0x00000709, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x00000006, + 0x02b, 0x00000709, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000007, + 0x02b, 0x00000709, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000008, + 0x02b, 0x00000709, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000009, + 0x02b, 0x0000060a, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000a, + 0x02b, 0x0000060a, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000b, + 0x02b, 0x0000060a, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000c, + 0x02b, 0x0000060a, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000d, + 0x02b, 0x0000050b, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000e, + 0x02b, 0x0000050b, + 0x02b, 0x00066623, + 0x02c, 0x0000001a, + 0x02a, 0x000e4000, + 0x030, 0x00020000, + 0x031, 0x000b9631, + 0x032, 0x0000130d, + 0x033, 0x00000187, + 0x013, 0x00019e6c, + 0x013, 0x00015e94, + 0x000, 0x00010159, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x01e, 0x0003105b, + 0x0fe, 0x00000000, + 0x000, 0x00030159, + 0x010, 0x0004000f, + 0x011, 0x000203f9, +}; + +u32 rtl8192seradiob_array[RADIOB_ARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00001041, + 0x002, 0x00011000, + 0x005, 0x00080fc0, + 0x007, 0x000fc803, + 0x013, 0x00017cb0, + 0x013, 0x00011cc0, + 0x013, 0x0000dc60, + 0x013, 0x00008c60, + 0x013, 0x00004450, + 0x013, 0x00000020, +}; + +u32 rtl8192seradiob_gm_array[RADIOB_GM_ARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00001041, + 0x002, 0x00011000, + 0x005, 0x00080fc0, + 0x007, 0x000fc803, +}; + +u32 rtl8192semac_2t_array[MAC_2T_ARRAYLENGTH] = { + 0x020, 0x00000035, + 0x048, 0x0000000e, + 0x049, 0x000000f0, + 0x04a, 0x00000077, + 0x04b, 0x00000083, + 0x0b5, 0x00000021, + 0x0dc, 0x000000ff, + 0x0dd, 0x000000ff, + 0x0de, 0x000000ff, + 0x0df, 0x000000ff, + 0x116, 0x00000000, + 0x117, 0x00000000, + 0x118, 0x00000000, + 0x119, 0x00000000, + 0x11a, 0x00000000, + 0x11b, 0x00000000, + 0x11c, 0x00000000, + 0x11d, 0x00000000, + 0x160, 0x0000000b, + 0x161, 0x0000000b, + 0x162, 0x0000000b, + 0x163, 0x0000000b, + 0x164, 0x0000000b, + 0x165, 0x0000000b, + 0x166, 0x0000000b, + 0x167, 0x0000000b, + 0x168, 0x0000000b, + 0x169, 0x0000000b, + 0x16a, 0x0000000b, + 0x16b, 0x0000000b, + 0x16c, 0x0000000b, + 0x16d, 0x0000000b, + 0x16e, 0x0000000b, + 0x16f, 0x0000000b, + 0x170, 0x0000000b, + 0x171, 0x0000000b, + 0x172, 0x0000000b, + 0x173, 0x0000000b, + 0x174, 0x0000000b, + 0x175, 0x0000000b, + 0x176, 0x0000000b, + 0x177, 0x0000000b, + 0x178, 0x0000000b, + 0x179, 0x0000000b, + 0x17a, 0x0000000b, + 0x17b, 0x0000000b, + 0x17c, 0x0000000b, + 0x17d, 0x0000000b, + 0x17e, 0x0000000b, + 0x17f, 0x0000000b, + 0x236, 0x0000000c, + 0x503, 0x00000022, + 0x560, 0x00000000, +}; + +u32 rtl8192seagctab_array[AGCTAB_ARRAYLENGTH] = { + 0xc78, 0x7f000001, + 0xc78, 0x7f010001, + 0xc78, 0x7e020001, + 0xc78, 0x7d030001, + 0xc78, 0x7c040001, + 0xc78, 0x7b050001, + 0xc78, 0x7a060001, + 0xc78, 0x79070001, + 0xc78, 0x78080001, + 0xc78, 0x77090001, + 0xc78, 0x760a0001, + 0xc78, 0x750b0001, + 0xc78, 0x740c0001, + 0xc78, 0x730d0001, + 0xc78, 0x720e0001, + 0xc78, 0x710f0001, + 0xc78, 0x70100001, + 0xc78, 0x6f110001, + 0xc78, 0x6f120001, + 0xc78, 0x6e130001, + 0xc78, 0x6d140001, + 0xc78, 0x6d150001, + 0xc78, 0x6c160001, + 0xc78, 0x6b170001, + 0xc78, 0x6a180001, + 0xc78, 0x6a190001, + 0xc78, 0x691a0001, + 0xc78, 0x681b0001, + 0xc78, 0x671c0001, + 0xc78, 0x661d0001, + 0xc78, 0x651e0001, + 0xc78, 0x641f0001, + 0xc78, 0x63200001, + 0xc78, 0x4c210001, + 0xc78, 0x4b220001, + 0xc78, 0x4a230001, + 0xc78, 0x49240001, + 0xc78, 0x48250001, + 0xc78, 0x47260001, + 0xc78, 0x46270001, + 0xc78, 0x45280001, + 0xc78, 0x44290001, + 0xc78, 0x2c2a0001, + 0xc78, 0x2b2b0001, + 0xc78, 0x2a2c0001, + 0xc78, 0x292d0001, + 0xc78, 0x282e0001, + 0xc78, 0x272f0001, + 0xc78, 0x26300001, + 0xc78, 0x25310001, + 0xc78, 0x24320001, + 0xc78, 0x23330001, + 0xc78, 0x22340001, + 0xc78, 0x09350001, + 0xc78, 0x08360001, + 0xc78, 0x07370001, + 0xc78, 0x06380001, + 0xc78, 0x05390001, + 0xc78, 0x043a0001, + 0xc78, 0x033b0001, + 0xc78, 0x023c0001, + 0xc78, 0x013d0001, + 0xc78, 0x003e0001, + 0xc78, 0x003f0001, + 0xc78, 0x7f400001, + 0xc78, 0x7f410001, + 0xc78, 0x7e420001, + 0xc78, 0x7d430001, + 0xc78, 0x7c440001, + 0xc78, 0x7b450001, + 0xc78, 0x7a460001, + 0xc78, 0x79470001, + 0xc78, 0x78480001, + 0xc78, 0x77490001, + 0xc78, 0x764a0001, + 0xc78, 0x754b0001, + 0xc78, 0x744c0001, + 0xc78, 0x734d0001, + 0xc78, 0x724e0001, + 0xc78, 0x714f0001, + 0xc78, 0x70500001, + 0xc78, 0x6f510001, + 0xc78, 0x6f520001, + 0xc78, 0x6e530001, + 0xc78, 0x6d540001, + 0xc78, 0x6d550001, + 0xc78, 0x6c560001, + 0xc78, 0x6b570001, + 0xc78, 0x6a580001, + 0xc78, 0x6a590001, + 0xc78, 0x695a0001, + 0xc78, 0x685b0001, + 0xc78, 0x675c0001, + 0xc78, 0x665d0001, + 0xc78, 0x655e0001, + 0xc78, 0x645f0001, + 0xc78, 0x63600001, + 0xc78, 0x4c610001, + 0xc78, 0x4b620001, + 0xc78, 0x4a630001, + 0xc78, 0x49640001, + 0xc78, 0x48650001, + 0xc78, 0x47660001, + 0xc78, 0x46670001, + 0xc78, 0x45680001, + 0xc78, 0x44690001, + 0xc78, 0x2c6a0001, + 0xc78, 0x2b6b0001, + 0xc78, 0x2a6c0001, + 0xc78, 0x296d0001, + 0xc78, 0x286e0001, + 0xc78, 0x276f0001, + 0xc78, 0x26700001, + 0xc78, 0x25710001, + 0xc78, 0x24720001, + 0xc78, 0x23730001, + 0xc78, 0x22740001, + 0xc78, 0x09750001, + 0xc78, 0x08760001, + 0xc78, 0x07770001, + 0xc78, 0x06780001, + 0xc78, 0x05790001, + 0xc78, 0x047a0001, + 0xc78, 0x037b0001, + 0xc78, 0x027c0001, + 0xc78, 0x017d0001, + 0xc78, 0x007e0001, + 0xc78, 0x007f0001, + 0xc78, 0x3000001e, + 0xc78, 0x3001001e, + 0xc78, 0x3002001e, + 0xc78, 0x3003001e, + 0xc78, 0x3004001e, + 0xc78, 0x3405001e, + 0xc78, 0x3806001e, + 0xc78, 0x3e07001e, + 0xc78, 0x3e08001e, + 0xc78, 0x4409001e, + 0xc78, 0x460a001e, + 0xc78, 0x480b001e, + 0xc78, 0x480c001e, + 0xc78, 0x4e0d001e, + 0xc78, 0x560e001e, + 0xc78, 0x5a0f001e, + 0xc78, 0x5e10001e, + 0xc78, 0x6211001e, + 0xc78, 0x6c12001e, + 0xc78, 0x7213001e, + 0xc78, 0x7214001e, + 0xc78, 0x7215001e, + 0xc78, 0x7216001e, + 0xc78, 0x7217001e, + 0xc78, 0x7218001e, + 0xc78, 0x7219001e, + 0xc78, 0x721a001e, + 0xc78, 0x721b001e, + 0xc78, 0x721c001e, + 0xc78, 0x721d001e, + 0xc78, 0x721e001e, + 0xc78, 0x721f001e, +}; + diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/table.h b/drivers/net/wireless/rtlwifi/rtl8192se/table.h new file mode 100644 index 000000000000..b4ed6d951ebb --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/table.h @@ -0,0 +1,49 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * + * Larry Finger + * + ******************************************************************************/ +#ifndef __INC_HAL8192SE_FW_IMG_H +#define __INC_HAL8192SE_FW_IMG_H + +#include + +/*Created on 2010/ 4/12, 5:56*/ + +#define PHY_REG_2T2RARRAYLENGTH 372 +extern u32 rtl8192sephy_reg_2t2rarray[PHY_REG_2T2RARRAYLENGTH]; +#define PHY_CHANGETO_1T1RARRAYLENGTH 48 +extern u32 rtl8192sephy_changeto_1t1rarray[PHY_CHANGETO_1T1RARRAYLENGTH]; +#define PHY_CHANGETO_1T2RARRAYLENGTH 45 +extern u32 rtl8192sephy_changeto_1t2rarray[PHY_CHANGETO_1T2RARRAYLENGTH]; +#define PHY_REG_ARRAY_PGLENGTH 84 +extern u32 rtl8192sephy_reg_array_pg[PHY_REG_ARRAY_PGLENGTH]; +#define RADIOA_1T_ARRAYLENGTH 202 +extern u32 rtl8192seradioa_1t_array[RADIOA_1T_ARRAYLENGTH]; +#define RADIOB_ARRAYLENGTH 22 +extern u32 rtl8192seradiob_array[RADIOB_ARRAYLENGTH]; +#define RADIOB_GM_ARRAYLENGTH 10 +extern u32 rtl8192seradiob_gm_array[RADIOB_GM_ARRAYLENGTH]; +#define MAC_2T_ARRAYLENGTH 106 +extern u32 rtl8192semac_2t_array[MAC_2T_ARRAYLENGTH]; +#define AGCTAB_ARRAYLENGTH 320 +extern u32 rtl8192seagctab_array[AGCTAB_ARRAYLENGTH]; + +#endif + -- cgit v1.2.3-58-ga151 From 84f494cef7d98d67aa7d50ede12784464aa0c274 Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Tue, 3 May 2011 09:49:26 -0500 Subject: rtlwifi: rtl8192se: Merge TX and RX routines Merge routines trx.c and trx.h for RTL8192SE. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192se/trx.c | 976 +++++++++++++++++++++++++++ drivers/net/wireless/rtlwifi/rtl8192se/trx.h | 45 ++ 2 files changed, 1021 insertions(+) create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/trx.c create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/trx.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c new file mode 100644 index 000000000000..5cf442373d46 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c @@ -0,0 +1,976 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "fw.h" +#include "trx.h" +#include "led.h" + +static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) +{ + __le16 fc = rtl_get_fc(skb); + + if (unlikely(ieee80211_is_beacon(fc))) + return QSLT_BEACON; + if (ieee80211_is_mgmt(fc)) + return QSLT_MGNT; + if (ieee80211_is_nullfunc(fc)) + return QSLT_HIGH; + + return skb->priority; +} + +static int _rtl92se_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) +{ + int rate_idx = 0; + + if (first_ampdu) { + if (false == isht) { + switch (desc_rate) { + case DESC92S_RATE1M: + rate_idx = 0; + break; + case DESC92S_RATE2M: + rate_idx = 1; + break; + case DESC92S_RATE5_5M: + rate_idx = 2; + break; + case DESC92S_RATE11M: + rate_idx = 3; + break; + case DESC92S_RATE6M: + rate_idx = 4; + break; + case DESC92S_RATE9M: + rate_idx = 5; + break; + case DESC92S_RATE12M: + rate_idx = 6; + break; + case DESC92S_RATE18M: + rate_idx = 7; + break; + case DESC92S_RATE24M: + rate_idx = 8; + break; + case DESC92S_RATE36M: + rate_idx = 9; + break; + case DESC92S_RATE48M: + rate_idx = 10; + break; + case DESC92S_RATE54M: + rate_idx = 11; + break; + default: + rate_idx = 0; + break; + } + } else { + rate_idx = 11; + } + + return rate_idx; + } + + switch (desc_rate) { + case DESC92S_RATE1M: + rate_idx = 0; + break; + case DESC92S_RATE2M: + rate_idx = 1; + break; + case DESC92S_RATE5_5M: + rate_idx = 2; + break; + case DESC92S_RATE11M: + rate_idx = 3; + break; + case DESC92S_RATE6M: + rate_idx = 4; + break; + case DESC92S_RATE9M: + rate_idx = 5; + break; + case DESC92S_RATE12M: + rate_idx = 6; + break; + case DESC92S_RATE18M: + rate_idx = 7; + break; + case DESC92S_RATE24M: + rate_idx = 8; + break; + case DESC92S_RATE36M: + rate_idx = 9; + break; + case DESC92S_RATE48M: + rate_idx = 10; + break; + case DESC92S_RATE54M: + rate_idx = 11; + break; + default: + rate_idx = 11; + break; + } + return rate_idx; +} + +static u8 _rtl92s_query_rxpwrpercentage(char antpower) +{ + if ((antpower <= -100) || (antpower >= 20)) + return 0; + else if (antpower >= 0) + return 100; + else + return 100 + antpower; +} + +static u8 _rtl92s_evm_db_to_percentage(char value) +{ + char ret_val; + ret_val = value; + + if (ret_val >= 0) + ret_val = 0; + + if (ret_val <= -33) + ret_val = -33; + + ret_val = 0 - ret_val; + ret_val *= 3; + + if (ret_val == 99) + ret_val = 100; + + return ret_val; +} + +static long _rtl92se_translate_todbm(struct ieee80211_hw *hw, + u8 signal_strength_index) +{ + long signal_power; + + signal_power = (long)((signal_strength_index + 1) >> 1); + signal_power -= 95; + return signal_power; +} + +static long _rtl92se_signal_scale_mapping(struct ieee80211_hw *hw, + long currsig) +{ + long retsig = 0; + + /* Step 1. Scale mapping. */ + if (currsig > 47) + retsig = 100; + else if (currsig > 14 && currsig <= 47) + retsig = 100 - ((47 - currsig) * 3) / 2; + else if (currsig > 2 && currsig <= 14) + retsig = 48 - ((14 - currsig) * 15) / 7; + else if (currsig >= 0) + retsig = currsig * 9 + 1; + + return retsig; +} + + +static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, + struct rtl_stats *pstats, u8 *pdesc, + struct rx_fwinfo *p_drvinfo, + bool packet_match_bssid, + bool packet_toself, + bool packet_beacon) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct phy_sts_cck_8192s_t *cck_buf; + s8 rx_pwr_all = 0, rx_pwr[4]; + u8 rf_rx_num = 0, evm, pwdb_all; + u8 i, max_spatial_stream; + u32 rssi, total_rssi = 0; + bool in_powersavemode = false; + bool is_cck_rate; + + is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); + pstats->packet_matchbssid = packet_match_bssid; + pstats->packet_toself = packet_toself; + pstats->is_cck = is_cck_rate; + pstats->packet_beacon = packet_beacon; + pstats->is_cck = is_cck_rate; + pstats->rx_mimo_signalquality[0] = -1; + pstats->rx_mimo_signalquality[1] = -1; + + if (is_cck_rate) { + u8 report, cck_highpwr; + cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; + + if (!in_powersavemode) + cck_highpwr = (u8) rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + 0x200); + else + cck_highpwr = false; + + if (!cck_highpwr) { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = cck_buf->cck_agc_rpt & 0xc0; + report = report >> 6; + switch (report) { + case 0x3: + rx_pwr_all = -40 - (cck_agc_rpt & 0x3e); + break; + case 0x2: + rx_pwr_all = -20 - (cck_agc_rpt & 0x3e); + break; + case 0x1: + rx_pwr_all = -2 - (cck_agc_rpt & 0x3e); + break; + case 0x0: + rx_pwr_all = 14 - (cck_agc_rpt & 0x3e); + break; + } + } else { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = p_drvinfo->cfosho[0] & 0x60; + report = report >> 5; + switch (report) { + case 0x3: + rx_pwr_all = -40 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x2: + rx_pwr_all = -20 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x1: + rx_pwr_all = -2 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x0: + rx_pwr_all = 14 - ((cck_agc_rpt & 0x1f) << 1); + break; + } + } + + pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all); + + /* CCK gain is smaller than OFDM/MCS gain, */ + /* so we add gain diff by experiences, the val is 6 */ + pwdb_all += 6; + if (pwdb_all > 100) + pwdb_all = 100; + /* modify the offset to make the same gain index with OFDM. */ + if (pwdb_all > 34 && pwdb_all <= 42) + pwdb_all -= 2; + else if (pwdb_all > 26 && pwdb_all <= 34) + pwdb_all -= 6; + else if (pwdb_all > 14 && pwdb_all <= 26) + pwdb_all -= 8; + else if (pwdb_all > 4 && pwdb_all <= 14) + pwdb_all -= 4; + + pstats->rx_pwdb_all = pwdb_all; + pstats->recvsignalpower = rx_pwr_all; + + if (packet_match_bssid) { + u8 sq; + if (pstats->rx_pwdb_all > 40) { + sq = 100; + } else { + sq = cck_buf->sq_rpt; + if (sq > 64) + sq = 0; + else if (sq < 20) + sq = 100; + else + sq = ((64 - sq) * 100) / 44; + } + + pstats->signalquality = sq; + pstats->rx_mimo_signalquality[0] = sq; + pstats->rx_mimo_signalquality[1] = -1; + } + } else { + rtlpriv->dm.rfpath_rxenable[0] = + rtlpriv->dm.rfpath_rxenable[1] = true; + for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { + if (rtlpriv->dm.rfpath_rxenable[i]) + rf_rx_num++; + + rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & + 0x3f) * 2) - 110; + rssi = _rtl92s_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += rssi; + rtlpriv->stats.rx_snr_db[i] = + (long)(p_drvinfo->rxsnr[i] / 2); + + if (packet_match_bssid) + pstats->rx_mimo_signalstrength[i] = (u8) rssi; + } + + rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; + pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all); + pstats->rx_pwdb_all = pwdb_all; + pstats->rxpower = rx_pwr_all; + pstats->recvsignalpower = rx_pwr_all; + + if (GET_RX_STATUS_DESC_RX_HT(pdesc) && + GET_RX_STATUS_DESC_RX_MCS(pdesc) >= DESC92S_RATEMCS8 && + GET_RX_STATUS_DESC_RX_MCS(pdesc) <= DESC92S_RATEMCS15) + max_spatial_stream = 2; + else + max_spatial_stream = 1; + + for (i = 0; i < max_spatial_stream; i++) { + evm = _rtl92s_evm_db_to_percentage(p_drvinfo->rxevm[i]); + + if (packet_match_bssid) { + if (i == 0) + pstats->signalquality = (u8)(evm & + 0xff); + pstats->rx_mimo_signalquality[i] = + (u8) (evm & 0xff); + } + } + } + + if (is_cck_rate) + pstats->signalstrength = (u8)(_rtl92se_signal_scale_mapping(hw, + pwdb_all)); + else if (rf_rx_num != 0) + pstats->signalstrength = (u8) (_rtl92se_signal_scale_mapping(hw, + total_rssi /= rf_rx_num)); +} + +static void _rtl92se_process_ui_rssi(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u8 rfpath; + u32 last_rssi, tmpval; + + if (pstats->packet_toself || pstats->packet_beacon) { + rtlpriv->stats.rssi_calculate_cnt++; + + if (rtlpriv->stats.ui_rssi.total_num++ >= + PHY_RSSI_SLID_WIN_MAX) { + rtlpriv->stats.ui_rssi.total_num = + PHY_RSSI_SLID_WIN_MAX; + last_rssi = rtlpriv->stats.ui_rssi.elements[ + rtlpriv->stats.ui_rssi.index]; + rtlpriv->stats.ui_rssi.total_val -= last_rssi; + } + + rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; + rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++] + = pstats->signalstrength; + + if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) + rtlpriv->stats.ui_rssi.index = 0; + + tmpval = rtlpriv->stats.ui_rssi.total_val / + rtlpriv->stats.ui_rssi.total_num; + rtlpriv->stats.signal_strength = _rtl92se_translate_todbm(hw, + (u8) tmpval); + pstats->rssi = rtlpriv->stats.signal_strength; + } + + if (!pstats->is_cck && pstats->packet_toself) { + for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; + rfpath++) { + if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { + rtlpriv->stats.rx_rssi_percentage[rfpath] = + pstats->rx_mimo_signalstrength[rfpath]; + + } + + if (pstats->rx_mimo_signalstrength[rfpath] > + rtlpriv->stats.rx_rssi_percentage[rfpath]) { + rtlpriv->stats.rx_rssi_percentage[rfpath] = + ((rtlpriv->stats.rx_rssi_percentage[rfpath] + * (RX_SMOOTH_FACTOR - 1)) + + (pstats->rx_mimo_signalstrength[rfpath])) / + (RX_SMOOTH_FACTOR); + + rtlpriv->stats.rx_rssi_percentage[rfpath] = + rtlpriv->stats.rx_rssi_percentage[rfpath] + + 1; + } else { + rtlpriv->stats.rx_rssi_percentage[rfpath] = + ((rtlpriv->stats.rx_rssi_percentage[rfpath] + * (RX_SMOOTH_FACTOR - 1)) + + (pstats->rx_mimo_signalstrength[rfpath])) / + (RX_SMOOTH_FACTOR); + } + + } + } +} + +static void _rtl92se_update_rxsignalstatistics(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int weighting = 0; + + if (rtlpriv->stats.recv_signal_power == 0) + rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; + + if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) + weighting = 5; + else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) + weighting = (-5); + + rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power * 5 + + pstats->recvsignalpower + + weighting) / 6; +} + +static void _rtl92se_process_pwdb(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undec_sm_pwdb = 0; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + return; + } else { + undec_sm_pwdb = + rtlpriv->dm.undecorated_smoothed_pwdb; + } + + if (pstats->packet_toself || pstats->packet_beacon) { + if (undec_sm_pwdb < 0) + undec_sm_pwdb = pstats->rx_pwdb_all; + + if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) { + undec_sm_pwdb = + (((undec_sm_pwdb) * + (RX_SMOOTH_FACTOR - 1)) + + (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); + + undec_sm_pwdb = undec_sm_pwdb + 1; + } else { + undec_sm_pwdb = (((undec_sm_pwdb) * + (RX_SMOOTH_FACTOR - 1)) + (pstats->rx_pwdb_all)) / + (RX_SMOOTH_FACTOR); + } + + rtlpriv->dm.undecorated_smoothed_pwdb = undec_sm_pwdb; + _rtl92se_update_rxsignalstatistics(hw, pstats); + } +} + +static void rtl_92s_process_streams(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 stream; + + for (stream = 0; stream < 2; stream++) { + if (pstats->rx_mimo_signalquality[stream] != -1) { + if (rtlpriv->stats.rx_evm_percentage[stream] == 0) { + rtlpriv->stats.rx_evm_percentage[stream] = + pstats->rx_mimo_signalquality[stream]; + } + + rtlpriv->stats.rx_evm_percentage[stream] = + ((rtlpriv->stats.rx_evm_percentage[stream] * + (RX_SMOOTH_FACTOR - 1)) + + (pstats->rx_mimo_signalquality[stream] * + 1)) / (RX_SMOOTH_FACTOR); + } + } +} + +static void _rtl92se_process_ui_link_quality(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 last_evm = 0, tmpval; + + if (pstats->signalquality != 0) { + if (pstats->packet_toself || pstats->packet_beacon) { + + if (rtlpriv->stats.ui_link_quality.total_num++ >= + PHY_LINKQUALITY_SLID_WIN_MAX) { + rtlpriv->stats.ui_link_quality.total_num = + PHY_LINKQUALITY_SLID_WIN_MAX; + last_evm = + rtlpriv->stats.ui_link_quality.elements[ + rtlpriv->stats.ui_link_quality.index]; + rtlpriv->stats.ui_link_quality.total_val -= + last_evm; + } + + rtlpriv->stats.ui_link_quality.total_val += + pstats->signalquality; + rtlpriv->stats.ui_link_quality.elements[ + rtlpriv->stats.ui_link_quality.index++] = + pstats->signalquality; + + if (rtlpriv->stats.ui_link_quality.index >= + PHY_LINKQUALITY_SLID_WIN_MAX) + rtlpriv->stats.ui_link_quality.index = 0; + + tmpval = rtlpriv->stats.ui_link_quality.total_val / + rtlpriv->stats.ui_link_quality.total_num; + rtlpriv->stats.signal_quality = tmpval; + + rtlpriv->stats.last_sigstrength_inpercent = tmpval; + + rtl_92s_process_streams(hw, pstats); + + } + } +} + +static void _rtl92se_process_phyinfo(struct ieee80211_hw *hw, + u8 *buffer, + struct rtl_stats *pcurrent_stats) +{ + + if (!pcurrent_stats->packet_matchbssid && + !pcurrent_stats->packet_beacon) + return; + + _rtl92se_process_ui_rssi(hw, pcurrent_stats); + _rtl92se_process_pwdb(hw, pcurrent_stats); + _rtl92se_process_ui_link_quality(hw, pcurrent_stats); +} + +static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw, + struct sk_buff *skb, struct rtl_stats *pstats, + u8 *pdesc, struct rx_fwinfo *p_drvinfo) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + struct ieee80211_hdr *hdr; + u8 *tmp_buf; + u8 *praddr; + u8 *psaddr; + __le16 fc; + u16 type, cfc; + bool packet_matchbssid, packet_toself, packet_beacon; + + tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; + + hdr = (struct ieee80211_hdr *)tmp_buf; + fc = hdr->frame_control; + cfc = le16_to_cpu(fc); + type = WLAN_FC_GET_TYPE(fc); + praddr = hdr->addr1; + psaddr = hdr->addr2; + + packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && + (!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ? + hdr->addr1 : (cfc & IEEE80211_FCTL_FROMDS) ? + hdr->addr2 : hdr->addr3)) && (!pstats->hwerror) && + (!pstats->crc) && (!pstats->icv)); + + packet_toself = packet_matchbssid && + (!compare_ether_addr(praddr, rtlefuse->dev_addr)); + + if (ieee80211_is_beacon(fc)) + packet_beacon = true; + + _rtl92se_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, + packet_matchbssid, packet_toself, packet_beacon); + _rtl92se_process_phyinfo(hw, tmp_buf, pstats); +} + +bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, u8 *pdesc, + struct sk_buff *skb) +{ + struct rx_fwinfo *p_drvinfo; + u32 phystatus = (u32)GET_RX_STATUS_DESC_PHY_STATUS(pdesc); + + stats->length = (u16)GET_RX_STATUS_DESC_PKT_LEN(pdesc); + stats->rx_drvinfo_size = (u8)GET_RX_STATUS_DESC_DRVINFO_SIZE(pdesc) * 8; + stats->rx_bufshift = (u8)(GET_RX_STATUS_DESC_SHIFT(pdesc) & 0x03); + stats->icv = (u16)GET_RX_STATUS_DESC_ICV(pdesc); + stats->crc = (u16)GET_RX_STATUS_DESC_CRC32(pdesc); + stats->hwerror = (u16)(stats->crc | stats->icv); + stats->decrypted = !GET_RX_STATUS_DESC_SWDEC(pdesc); + + stats->rate = (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc); + stats->shortpreamble = (u16)GET_RX_STATUS_DESC_SPLCP(pdesc); + stats->isampdu = (bool)(GET_RX_STATUS_DESC_PAGGR(pdesc) == 1); + stats->timestamp_low = GET_RX_STATUS_DESC_TSFL(pdesc); + stats->rx_is40Mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc); + + if (stats->hwerror) + return false; + + rx_status->freq = hw->conf.channel->center_freq; + rx_status->band = hw->conf.channel->band; + + if (GET_RX_STATUS_DESC_CRC32(pdesc)) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (!GET_RX_STATUS_DESC_SWDEC(pdesc)) + rx_status->flag |= RX_FLAG_DECRYPTED; + + if (GET_RX_STATUS_DESC_BW(pdesc)) + rx_status->flag |= RX_FLAG_40MHZ; + + if (GET_RX_STATUS_DESC_RX_HT(pdesc)) + rx_status->flag |= RX_FLAG_HT; + + rx_status->flag |= RX_FLAG_MACTIME_MPDU; + + if (stats->decrypted) + rx_status->flag |= RX_FLAG_DECRYPTED; + + rx_status->rate_idx = _rtl92se_rate_mapping((bool) + GET_RX_STATUS_DESC_RX_HT(pdesc), + (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc), + (bool)GET_RX_STATUS_DESC_PAGGR(pdesc)); + + + rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc); + if (phystatus == true) { + p_drvinfo = (struct rx_fwinfo *)(skb->data + + stats->rx_bufshift); + _rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc, + p_drvinfo); + } + + /*rx_status->qual = stats->signal; */ + rx_status->signal = stats->rssi + 10; + /*rx_status->noise = -stats->noise; */ + + return true; +} + +void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + struct ieee80211_tx_info *info, struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct ieee80211_sta *sta = info->control.sta; + u8 *pdesc = (u8 *) pdesc_tx; + u16 seq_number; + __le16 fc = hdr->frame_control; + u8 reserved_macid = 0; + u8 fw_qsel = _rtl92se_map_hwqueue_to_fwqueue(skb, hw_queue); + bool firstseg = (!(hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG))); + bool lastseg = (!(hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_MOREFRAGS))); + dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + u8 bw_40 = 0; + + if (mac->opmode == NL80211_IFTYPE_STATION) { + bw_40 = mac->bw_40; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta) + bw_40 = sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40; + } + + seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; + + rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); + + CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S); + + if (firstseg) { + if (rtlpriv->dm.useramask) { + /* set txdesc macId */ + if (ptcb_desc->mac_id < 32) { + SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); + reserved_macid |= ptcb_desc->mac_id; + } + } + SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid); + + SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >= + DESC92S_RATEMCS0) ? 1 : 0)); + + if (rtlhal->version == VERSION_8192S_ACUT) { + if (ptcb_desc->hw_rate == DESC92S_RATE1M || + ptcb_desc->hw_rate == DESC92S_RATE2M || + ptcb_desc->hw_rate == DESC92S_RATE5_5M || + ptcb_desc->hw_rate == DESC92S_RATE11M) { + ptcb_desc->hw_rate = DESC92S_RATE12M; + } + } + + SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); + + if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble) + SET_TX_DESC_TX_SHORT(pdesc, 0); + + /* Aggregation related */ + if (info->flags & IEEE80211_TX_CTL_AMPDU) + SET_TX_DESC_AGG_ENABLE(pdesc, 1); + + /* For AMPDU, we must insert SSN into TX_DESC */ + SET_TX_DESC_SEQ(pdesc, seq_number); + + /* Protection mode related */ + /* For 92S, if RTS/CTS are set, HW will execute RTS. */ + /* We choose only one protection mode to execute */ + SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && + !ptcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS_ENABLE(pdesc, ((ptcb_desc->cts_enable) ? + 1 : 0)); + SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); + + SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); + SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0); + SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc); + SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= + DESC92S_RATE54M) ? + (ptcb_desc->rts_use_shortpreamble ? 1 : 0) + : (ptcb_desc->rts_use_shortgi ? 1 : 0))); + + + /* Set Bandwidth and sub-channel settings. */ + if (bw_40) { + if (ptcb_desc->packet_bw) { + SET_TX_DESC_TX_BANDWIDTH(pdesc, 1); + /* use duplicated mode */ + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); + } else { + SET_TX_DESC_TX_BANDWIDTH(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, + mac->cur_40_prime_sc); + } + } else { + SET_TX_DESC_TX_BANDWIDTH(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); + } + + /* 3 Fill necessary field in First Descriptor */ + /*DWORD 0*/ + SET_TX_DESC_LINIP(pdesc, 0); + SET_TX_DESC_OFFSET(pdesc, 32); + SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); + + /*DWORD 1*/ + SET_TX_DESC_RA_BRSR_ID(pdesc, ptcb_desc->ratr_index); + + /* Fill security related */ + if (info->control.hw_key) { + struct ieee80211_key_conf *keyconf; + + keyconf = info->control.hw_key; + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + SET_TX_DESC_SEC_TYPE(pdesc, 0x1); + break; + case WLAN_CIPHER_SUITE_TKIP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x2); + break; + case WLAN_CIPHER_SUITE_CCMP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x3); + break; + default: + SET_TX_DESC_SEC_TYPE(pdesc, 0x0); + break; + + } + } + + /* Set Packet ID */ + SET_TX_DESC_PACKET_ID(pdesc, 0); + + /* We will assign magement queue to BK. */ + SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); + + /* Alwasy enable all rate fallback range */ + SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); + + /* Fix: I don't kown why hw use 6.5M to tx when set it */ + SET_TX_DESC_USER_RATE(pdesc, + ptcb_desc->use_driver_rate ? 1 : 0); + + /* Set NON_QOS bit. */ + if (!ieee80211_is_data_qos(fc)) + SET_TX_DESC_NON_QOS(pdesc, 1); + + } + + /* Fill fields that are required to be initialized + * in all of the descriptors */ + /*DWORD 0 */ + SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); + SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); + + /* DWORD 7 */ + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); + + /* DOWRD 8 */ + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); + + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n")); +} + +void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + bool firstseg, bool lastseg, struct sk_buff *skb) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb); + + dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + + /* Clear all status */ + CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S); + + /* This bit indicate this packet is used for FW download. */ + if (tcb_desc->cmd_or_init == DESC_PACKET_TYPE_INIT) { + /* For firmware downlaod we only need to set LINIP */ + SET_TX_DESC_LINIP(pdesc, tcb_desc->last_inipkt); + + /* 92SE must set as 1 for firmware download HW DMA error */ + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + /* 92SE need not to set TX packet size when firmware download */ + SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); + + SET_TX_DESC_OWN(pdesc, 1); + } else { /* H2C Command Desc format (Host TXCMD) */ + /* 92SE must set as 1 for firmware download HW DMA error */ + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_OFFSET(pdesc, 0x20); + + /* Buffer size + command header */ + SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); + /* Fixed queue of H2C command */ + SET_TX_DESC_QUEUE_SEL(pdesc, 0x13); + + SET_BITS_TO_LE_4BYTE(skb->data, 24, 7, rtlhal->h2c_txcmd_seq); + + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); + + SET_TX_DESC_OWN(pdesc, 1); + + } +} + +void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val) +{ + if (istx == true) { + switch (desc_name) { + case HW_DESC_OWN: + SET_TX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_TX_NEXTDESC_ADDR: + SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); + break; + default: + RT_ASSERT(false, ("ERR txdesc :%d not process\n", + desc_name)); + break; + } + } else { + switch (desc_name) { + case HW_DESC_RXOWN: + SET_RX_STATUS_DESC_OWN(pdesc, 1); + break; + case HW_DESC_RXBUFF_ADDR: + SET_RX_STATUS__DESC_BUFF_ADDR(pdesc, *(u32 *) val); + break; + case HW_DESC_RXPKT_LEN: + SET_RX_STATUS_DESC_PKT_LEN(pdesc, *(u32 *) val); + break; + case HW_DESC_RXERO: + SET_RX_STATUS_DESC_EOR(pdesc, 1); + break; + default: + RT_ASSERT(false, ("ERR rxdesc :%d not process\n", + desc_name)); + break; + } + } +} + +u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name) +{ + u32 ret = 0; + + if (istx == true) { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_TX_DESC_OWN(desc); + break; + case HW_DESC_TXBUFF_ADDR: + ret = GET_TX_DESC_TX_BUFFER_ADDRESS(desc); + break; + default: + RT_ASSERT(false, ("ERR txdesc :%d not process\n", + desc_name)); + break; + } + } else { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_RX_STATUS_DESC_OWN(desc); + break; + case HW_DESC_RXPKT_LEN: + ret = GET_RX_STATUS_DESC_PKT_LEN(desc); + break; + default: + RT_ASSERT(false, ("ERR rxdesc :%d not process\n", + desc_name)); + break; + } + } + return ret; +} + +void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + rtl_write_word(rtlpriv, TP_POLL, BIT(0) << (hw_queue)); +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.h b/drivers/net/wireless/rtlwifi/rtl8192se/trx.h new file mode 100644 index 000000000000..05862c51b861 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __REALTEK_PCI92SE_TRX_H__ +#define __REALTEK_PCI92SE_TRX_H__ + +void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, + u8 *pdesc, struct ieee80211_tx_info *info, + struct sk_buff *skb, u8 hw_queue, + struct rtl_tcb_desc *ptcb_desc); +void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, + bool lastseg, struct sk_buff *skb); +bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, u8 *pdesc, + struct sk_buff *skb); +void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val); +u32 rtl92se_get_desc(u8 *pdesc, bool istx, u8 desc_name); +void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); + +#endif -- cgit v1.2.3-58-ga151 From 85e09b40405b44b049500702beb6856646b4be46 Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Tue, 3 May 2011 09:49:36 -0500 Subject: rtlwifi: rtl8192se: Modify Kconfig and Makefile routines for new driver Modify rtlwifi routines for rtl8192se and set up Kconfig and Makefile for new driver. This patch also disables ASPM for the RTL8192SE to prevent some strange crashes on LF's system. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/Kconfig | 15 +++++++++++++-- drivers/net/wireless/rtlwifi/Makefile | 1 + drivers/net/wireless/rtlwifi/rtl8192se/Makefile | 15 +++++++++++++++ drivers/net/wireless/rtlwifi/rtl8192se/sw.c | 2 +- 4 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/Makefile diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig index ce49e0ce7cad..5aee8b22d74e 100644 --- a/drivers/net/wireless/rtlwifi/Kconfig +++ b/drivers/net/wireless/rtlwifi/Kconfig @@ -10,6 +10,17 @@ config RTL8192CE If you choose to build it as a module, it will be called rtl8192ce +config RTL8192SE + tristate "Realtek RTL8192SE/RTL8191SE PCIe Wireless Network Adapter" + depends on MAC80211 && EXPERIMENTAL + select FW_LOADER + select RTLWIFI + ---help--- + This is the driver for Realtek RTL8192SE/RTL8191SE 802.11n PCIe + wireless network adapters. + + If you choose to build it as a module, it will be called rtl8192se + config RTL8192CU tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter" depends on MAC80211 && USB && EXPERIMENTAL @@ -24,10 +35,10 @@ config RTL8192CU config RTLWIFI tristate - depends on RTL8192CE || RTL8192CU + depends on RTL8192CE || RTL8192CU || RTL8192SE default m config RTL8192C_COMMON tristate - depends on RTL8192CE || RTL8192CU + depends on RTL8192CE || RTL8192CU || RTL8192SE default m diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile index ec9393f24799..7acce83c3785 100644 --- a/drivers/net/wireless/rtlwifi/Makefile +++ b/drivers/net/wireless/rtlwifi/Makefile @@ -22,5 +22,6 @@ endif obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c/ obj-$(CONFIG_RTL8192CE) += rtl8192ce/ obj-$(CONFIG_RTL8192CU) += rtl8192cu/ +obj-$(CONFIG_RTL8192SE) += rtl8192se/ ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/Makefile b/drivers/net/wireless/rtlwifi/rtl8192se/Makefile new file mode 100644 index 000000000000..b7eb13819cbc --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/Makefile @@ -0,0 +1,15 @@ +rtl8192se-objs := \ + dm.o \ + fw.o \ + hw.o \ + led.o \ + phy.o \ + rf.o \ + sw.o \ + table.o \ + trx.o + +obj-$(CONFIG_RTL8192SE) += rtl8192se.o + +ccflags-y += -D__CHECK_ENDIAN__ + diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index c5351b65b339..7cfd6a2cb140 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c @@ -58,7 +58,7 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) * 4 - Always Enable ASPM without Clock Req. * set defult to RTL8192CE:3 RTL8192E:2 * */ - rtlpci->const_pci_aspm = 2; + rtlpci->const_pci_aspm = 0; /* changed from 2 due to crashes */ /*Setting for PCI-E device */ rtlpci->const_devicepci_aspm_setting = 0x03; -- cgit v1.2.3-58-ga151 From 57f16b5da03784d1660133fbec7281ea5735da69 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Tue, 3 May 2011 20:11:45 -0700 Subject: mwifiex: fix simultaneous assoc and scan issue When scan and assoc (infra/ibss) commands are simultaneously given in two terminals, association response is erroneously served while serving the scan response. mwifiex_cfg80211_results() is the common routine for sending ioctl (scan, assoc etc.) results to cfg80211 stack. In above scenario even if the common routine is called for scan ioctl context, it also tries to send information about assoc ioctl to cfg80211 because "priv->assoc_request/priv->ibss_join_request" flag is on at that time. Fix the issue by updating request variable after assoc handling and modifying the variable check in mwifiex_cfg80211_results. Signed-off-by: Amitkumar Karwar Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 11 +++++++---- drivers/net/wireless/mwifiex/main.h | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 98009e2194c5..77a80296b6cb 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1044,7 +1044,7 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, goto done; } - priv->assoc_request = 1; + priv->assoc_request = -EINPROGRESS; wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", (char *) sme->ssid, sme->bssid); @@ -1052,6 +1052,7 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, priv->bss_mode, sme->channel, sme, 0); + priv->assoc_request = 1; done: priv->assoc_result = ret; queue_work(priv->workqueue, &priv->cfg_workqueue); @@ -1080,7 +1081,7 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, goto done; } - priv->ibss_join_request = 1; + priv->ibss_join_request = -EINPROGRESS; wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n", (char *) params->ssid, params->bssid); @@ -1088,6 +1089,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid, params->bssid, priv->bss_mode, params->channel, NULL, params->privacy); + + priv->ibss_join_request = 1; done: priv->ibss_join_result = ret; queue_work(priv->workqueue, &priv->cfg_workqueue); @@ -1380,7 +1383,7 @@ done: kfree(scan_req); } - if (priv->assoc_request) { + if (priv->assoc_request == 1) { if (!priv->assoc_result) { cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0, NULL, 0, @@ -1399,7 +1402,7 @@ done: priv->assoc_result = 0; } - if (priv->ibss_join_request) { + if (priv->ibss_join_request == 1) { if (!priv->ibss_join_result) { cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL); diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 5043fcd22565..b4bb5ec4723e 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -479,9 +479,9 @@ struct mwifiex_private { u8 report_scan_result; struct cfg80211_scan_request *scan_request; int scan_result_status; - bool assoc_request; + int assoc_request; u16 assoc_result; - bool ibss_join_request; + int ibss_join_request; u16 ibss_join_result; bool disconnect; u8 cfg_bssid[6]; -- cgit v1.2.3-58-ga151 From 270e58e8898c8be40451ebee45b6c9b5bd5db04b Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Tue, 3 May 2011 20:11:46 -0700 Subject: mwifiex: remove unnecessary variable initialization Skip initialization of local variables with some default values if the values are not going to be used further down the code path. Signed-off-by: Yogesh Ashok Powar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n.c | 7 ++-- drivers/net/wireless/mwifiex/11n_aggr.c | 7 ++-- drivers/net/wireless/mwifiex/11n_rxreorder.c | 15 ++++----- drivers/net/wireless/mwifiex/cfg80211.c | 23 +++++-------- drivers/net/wireless/mwifiex/cmdevt.c | 28 ++++++++-------- drivers/net/wireless/mwifiex/debugfs.c | 10 +++--- drivers/net/wireless/mwifiex/init.c | 29 +++++++--------- drivers/net/wireless/mwifiex/join.c | 9 +++-- drivers/net/wireless/mwifiex/main.c | 19 +++++------ drivers/net/wireless/mwifiex/scan.c | 22 ++++++------ drivers/net/wireless/mwifiex/sdio.c | 30 ++++++++--------- drivers/net/wireless/mwifiex/sta_cmd.c | 8 ++--- drivers/net/wireless/mwifiex/sta_cmdresp.c | 28 ++++++++-------- drivers/net/wireless/mwifiex/sta_ioctl.c | 50 +++++++++++++--------------- drivers/net/wireless/mwifiex/sta_rx.c | 4 +-- drivers/net/wireless/mwifiex/sta_tx.c | 4 +-- drivers/net/wireless/mwifiex/txrx.c | 10 +++--- drivers/net/wireless/mwifiex/util.c | 8 ++--- drivers/net/wireless/mwifiex/wmm.c | 2 +- 19 files changed, 148 insertions(+), 165 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 1d294cfa6c9b..916183d39009 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -187,7 +187,7 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, */ int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf) { - struct mwifiex_ds_11n_tx_cfg *tx_cfg = NULL; + struct mwifiex_ds_11n_tx_cfg *tx_cfg; struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg; if (data_buf) { @@ -274,7 +274,7 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp, void *data_buf) { - struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl = NULL; + struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl; struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl = &resp->params.amsdu_aggr_ctrl; @@ -461,8 +461,7 @@ mwifiex_cfg_tx_buf(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { u16 max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_2K; - u16 tx_buf = 0; - u16 curr_tx_buf_size = 0; + u16 tx_buf, curr_tx_buf_size = 0; if (bss_desc->bcn_ht_cap) { if (le16_to_cpu(bss_desc->bcn_ht_cap->cap_info) & diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index c9fb0627de43..12cf4246f96b 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -60,7 +60,7 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr, * later with ethertype */ }; - struct tx_packet_hdr *tx_header = NULL; + struct tx_packet_hdr *tx_header; skb_put(skb_aggr, sizeof(*tx_header)); @@ -182,7 +182,7 @@ int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); struct rxpd *local_rx_pd = (struct rxpd *) skb->data; struct sk_buff *skb_daggr; - struct mwifiex_rxinfo *rx_info_daggr = NULL; + struct mwifiex_rxinfo *rx_info_daggr; int ret = -1; struct rx_packet_hdr *rx_pkt_hdr; struct mwifiex_adapter *adapter = priv->adapter; @@ -285,8 +285,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, struct mwifiex_adapter *adapter = priv->adapter; struct sk_buff *skb_aggr, *skb_src; struct mwifiex_txinfo *tx_info_aggr, *tx_info_src; - int pad = 0; - int ret = 0; + int pad = 0, ret; struct mwifiex_tx_param tx_param; struct txpd *ptx_pd = NULL; diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index a93c03fdea82..e5dfdc39a921 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -39,7 +39,7 @@ mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv, *rx_reor_tbl_ptr, int start_win) { int no_pkt_to_send, i; - void *rx_tmp_ptr = NULL; + void *rx_tmp_ptr; unsigned long flags; no_pkt_to_send = (start_win > rx_reor_tbl_ptr->start_win) ? @@ -88,7 +88,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv, struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr) { int i, j, xchg; - void *rx_tmp_ptr = NULL; + void *rx_tmp_ptr; unsigned long flags; for (i = 0; i < rx_reor_tbl_ptr->win_size; ++i) { @@ -335,8 +335,8 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, &cmd->params.add_ba_rsp; struct host_cmd_ds_11n_addba_req *cmd_addba_req = (struct host_cmd_ds_11n_addba_req *) data_buf; - u8 tid = 0; - int win_size = 0; + u8 tid; + int win_size; uint16_t block_ack_param_set; cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP); @@ -406,9 +406,8 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, u8 *ta, u8 pkt_type, void *payload) { struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; - int start_win, end_win, win_size; - int ret = 0; - u16 pkt_index = 0; + int start_win, end_win, win_size, ret; + u16 pkt_index; rx_reor_tbl_ptr = mwifiex_11n_get_rx_reorder_tbl((struct mwifiex_private *) priv, @@ -540,7 +539,7 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, (struct host_cmd_ds_11n_addba_rsp *) &resp->params.add_ba_rsp; int tid, win_size; - struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr = NULL; + struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; uint16_t block_ack_param_set; block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 77a80296b6cb..0c0116374d7d 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -77,18 +77,15 @@ mwifiex_channels_to_cfg80211_channel_type(int channel_type) static int mwifiex_is_alg_wep(u32 cipher) { - int alg = 0; - switch (cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: - alg = 1; - break; + return 1; default: - alg = 0; break; } - return alg; + + return 0; } /* @@ -408,7 +405,7 @@ mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, static int mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) { - int ret = 0; + int ret; if (frag_thr < MWIFIEX_FRAG_MIN_VALUE || frag_thr > MWIFIEX_FRAG_MAX_VALUE) @@ -449,7 +446,6 @@ static int mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) { struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - int ret = 0; if (changed & WIPHY_PARAM_RTS_THRESHOLD) { @@ -473,7 +469,7 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { - int ret = 0; + int ret; struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); if (priv->bss_mode == type) { @@ -717,7 +713,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) { struct ieee80211_channel *chan; struct mwifiex_bss_info bss_info; - int ie_len = 0; + int ie_len; u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)]; if (mwifiex_get_bss_info(priv, &bss_info)) @@ -903,8 +899,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, { struct mwifiex_802_11_ssid req_ssid; struct mwifiex_ssid_bssid ssid_bssid; - int ret = 0; - int auth_type = 0; + int ret, auth_type = 0; memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid)); memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); @@ -1247,8 +1242,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, struct mwifiex_private *priv) { - int ret = 0; - void *wdev_priv = NULL; + int ret; + void *wdev_priv; struct wireless_dev *wdev; wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 776146a104ec..b75cc9271a19 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -128,7 +128,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, { struct mwifiex_adapter *adapter = priv->adapter; - int ret = 0; + int ret; struct host_cmd_ds_command *host_cmd; uint16_t cmd_code; uint16_t cmd_size; @@ -222,8 +222,8 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, */ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) { - int ret = 0; - u16 cmd_len = 0; + int ret; + u16 cmd_len; struct mwifiex_private *priv; struct mwifiex_opt_sleep_confirm_buffer *sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm_buffer *) @@ -364,13 +364,13 @@ int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter) */ int mwifiex_process_event(struct mwifiex_adapter *adapter) { - int ret = 0; + int ret; struct mwifiex_private *priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); struct sk_buff *skb = adapter->event_skb; u32 eventcause = adapter->event_cause; struct timeval tstamp; - struct mwifiex_rxinfo *rx_info = NULL; + struct mwifiex_rxinfo *rx_info; /* Save the last event to debug log */ adapter->dbg.last_event_index = @@ -446,10 +446,10 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, u16 cmd_action, u32 cmd_oid, void *data_buf) { - int ret = 0; + int ret; struct mwifiex_adapter *adapter = priv->adapter; - struct cmd_ctrl_node *cmd_node = NULL; - struct host_cmd_ds_command *cmd_ptr = NULL; + struct cmd_ctrl_node *cmd_node; + struct host_cmd_ds_command *cmd_ptr; if (!adapter) { pr_err("PREP_CMD: adapter is NULL\n"); @@ -605,8 +605,8 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, */ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter) { - struct mwifiex_private *priv = NULL; - struct cmd_ctrl_node *cmd_node = NULL; + struct mwifiex_private *priv; + struct cmd_ctrl_node *cmd_node; int ret = 0; struct host_cmd_ds_command *host_cmd; unsigned long cmd_flags; @@ -673,7 +673,7 @@ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter) */ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) { - struct host_cmd_ds_command *resp = NULL; + struct host_cmd_ds_command *resp; struct mwifiex_private *priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); int ret = 0; @@ -805,7 +805,7 @@ mwifiex_cmd_timeout_func(unsigned long function_context) { struct mwifiex_adapter *adapter = (struct mwifiex_adapter *) function_context; - struct cmd_ctrl_node *cmd_node = NULL; + struct cmd_ctrl_node *cmd_node; struct timeval tstamp; adapter->num_cmd_timeout++; @@ -877,7 +877,7 @@ mwifiex_cmd_timeout_func(unsigned long function_context) void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) { - struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; + struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; unsigned long flags; /* Cancel current cmd */ @@ -1160,7 +1160,7 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv, { struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh = &cmd->params.psmode_enh; - u8 *tlv = NULL; + u8 *tlv; u16 cmd_size = 0; cmd->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index 7ddcb062f103..46d65e02c7ba 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c @@ -193,7 +193,7 @@ mwifiex_info_read(struct file *file, char __user *ubuf, unsigned long page = get_zeroed_page(GFP_KERNEL); char *p = (char *) page, fmt[64]; struct mwifiex_bss_info info; - ssize_t ret = 0; + ssize_t ret; int i = 0; if (!p) @@ -288,7 +288,7 @@ mwifiex_getlog_read(struct file *file, char __user *ubuf, (struct mwifiex_private *) file->private_data; unsigned long page = get_zeroed_page(GFP_KERNEL); char *p = (char *) page; - ssize_t ret = 0; + ssize_t ret; struct mwifiex_ds_get_stats stats; if (!p) @@ -400,7 +400,7 @@ mwifiex_debug_read(struct file *file, char __user *ubuf, struct mwifiex_debug_data *d = &items[0]; unsigned long page = get_zeroed_page(GFP_KERNEL); char *p = (char *) page; - ssize_t ret = 0; + ssize_t ret; size_t size, addr; long val; int i, j; @@ -507,7 +507,7 @@ mwifiex_regrdwr_write(struct file *file, unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *) addr; size_t buf_size = min(count, (size_t) (PAGE_SIZE - 1)); - int ret = 0; + int ret; u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX; if (!buf) @@ -650,7 +650,7 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, (struct mwifiex_private *) file->private_data; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *) addr; - int pos = 0, ret = 0, i = 0; + int pos = 0, ret = 0, i; u8 value[MAX_EEPROM_DATA]; if (!buf) diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index fc2c0c5728d9..27ad72b291b7 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -151,7 +151,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) */ static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) { - int ret = 0; + int ret; u32 buf_size; struct mwifiex_bssdescriptor *temp_scan_table; @@ -342,9 +342,8 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter) */ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) { - struct mwifiex_private *priv = NULL; - s32 i = 0; - u32 j = 0; + struct mwifiex_private *priv; + s32 i, j; spin_lock_init(&adapter->mwifiex_lock); spin_lock_init(&adapter->int_lock); @@ -400,9 +399,8 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) */ void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) { - struct mwifiex_private *priv = NULL; - s32 i = 0; - s32 j = 0; + struct mwifiex_private *priv; + s32 i, j; /* Free lists */ list_del(&adapter->cmd_free_q); @@ -436,10 +434,9 @@ void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) */ int mwifiex_init_fw(struct mwifiex_adapter *adapter) { - int ret = 0; - struct mwifiex_private *priv = NULL; - u8 i = 0; - u8 first_sta = true; + int ret; + struct mwifiex_private *priv; + u8 i, first_sta = true; int is_cmd_pend_q_empty; unsigned long flags; @@ -497,8 +494,7 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv) { int i; struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bss_prio_node *bssprio_node = NULL, *tmp_node = NULL, - **cur = NULL; + struct mwifiex_bss_prio_node *bssprio_node, *tmp_node, **cur; struct list_head *head; spinlock_t *lock; unsigned long flags; @@ -552,8 +548,8 @@ int mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) { int ret = -EINPROGRESS; - struct mwifiex_private *priv = NULL; - s32 i = 0; + struct mwifiex_private *priv; + s32 i; unsigned long flags; /* mwifiex already shutdown */ @@ -608,9 +604,8 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, struct mwifiex_fw_image *pmfw) { - int ret = 0; + int ret, winner; u32 poll_num = 1; - int winner; /* Check if firmware is already running */ ret = adapter->if_ops.check_fw_status(adapter, poll_num, &winner); diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 85fca5eb4195..5eab3dc29b1c 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -143,9 +143,8 @@ mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer, static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1, u32 rate1_size, u8 *rate2, u32 rate2_size) { - int ret = 0; - u8 *ptr = rate1; - u8 *tmp = NULL; + int ret; + u8 *ptr = rate1, *tmp; u32 i, j; tmp = kmalloc(rate1_size, GFP_KERNEL); @@ -203,7 +202,7 @@ mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv, u8 *out_rates, u32 *out_rates_size) { u8 card_rates[MWIFIEX_SUPPORTED_RATES]; - u32 card_rates_size = 0; + u32 card_rates_size; /* Copy AP supported rates */ memcpy(out_rates, bss_desc->supported_rates, MWIFIEX_SUPPORTED_RATES); @@ -1359,7 +1358,7 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv, static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac) { u8 mac_address[ETH_ALEN]; - int ret = 0; + int ret; u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; if (mac) { diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index c5971880e7b3..38f912b8fcec 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -150,7 +150,7 @@ error: */ static int mwifiex_unregister(struct mwifiex_adapter *adapter) { - s32 i = 0; + s32 i; del_timer(&adapter->cmd_timer); @@ -379,8 +379,7 @@ static void mwifiex_free_adapter(struct mwifiex_adapter *adapter) */ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) { - int ret = 0; - int err; + int ret, err; struct mwifiex_fw_image fw; memset(&fw, 0, sizeof(struct mwifiex_fw_image)); @@ -449,7 +448,7 @@ done: static void mwifiex_fill_buffer(struct sk_buff *skb) { - struct ethhdr *eth = NULL; + struct ethhdr *eth; struct iphdr *iph; struct timeval tv; u8 tid = 0; @@ -510,7 +509,7 @@ static int mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct sk_buff *new_skb = NULL; + struct sk_buff *new_skb; struct mwifiex_txinfo *tx_info; dev_dbg(priv->adapter->dev, "data: %lu BSS(%d): Data <= kernel\n", @@ -571,7 +570,7 @@ mwifiex_set_mac_address(struct net_device *dev, void *addr) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); struct sockaddr *hw_addr = (struct sockaddr *) addr; - int ret = 0; + int ret; memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN); @@ -696,9 +695,9 @@ static struct mwifiex_private *mwifiex_add_interface( struct mwifiex_adapter *adapter, u8 bss_index, u8 bss_type) { - struct net_device *dev = NULL; - struct mwifiex_private *priv = NULL; - void *mdev_priv = NULL; + struct net_device *dev; + struct mwifiex_private *priv; + void *mdev_priv; dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), "mlan%d", ether_setup, 1); @@ -763,7 +762,7 @@ error: static void mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index) { - struct net_device *dev = NULL; + struct net_device *dev; struct mwifiex_private *priv = adapter->priv[bss_index]; if (!priv) diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 31a529578805..4968974f3427 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -117,8 +117,8 @@ mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui) static u8 mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) { - u8 *oui = NULL; - struct ie_body *iebody = NULL; + u8 *oui; + struct ie_body *iebody; u8 ret = MWIFIEX_OUI_NOT_PRESENT; if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)). @@ -144,8 +144,8 @@ mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) static u8 mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) { - u8 *oui = NULL; - struct ie_body *iebody = NULL; + u8 *oui; + struct ie_body *iebody; u8 ret = MWIFIEX_OUI_NOT_PRESENT; if (((bss_desc->bcn_wpa_ie) && ((*(bss_desc->bcn_wpa_ie)). @@ -181,7 +181,7 @@ int mwifiex_find_best_bss(struct mwifiex_private *priv, struct mwifiex_ssid_bssid *ssid_bssid) { struct mwifiex_ssid_bssid tmp_ssid_bssid; - u8 *mac = NULL; + u8 *mac; if (!ssid_bssid) return -1; @@ -213,7 +213,7 @@ int mwifiex_find_best_bss(struct mwifiex_private *priv, int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, struct mwifiex_user_scan_cfg *scan_req) { - int status = 0; + int status; priv->adapter->cmd_wait_q.condition = false; @@ -2253,8 +2253,8 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, { int ret = 0; struct mwifiex_adapter *adapter = priv->adapter; - struct cmd_ctrl_node *cmd_node = NULL; - union mwifiex_scan_cmd_config_tlv *scan_cfg_out = NULL; + struct cmd_ctrl_node *cmd_node; + union mwifiex_scan_cmd_config_tlv *scan_cfg_out; struct mwifiex_ie_types_chan_list_param_set *chan_list_out; u32 buf_size; struct mwifiex_chan_scan_param_set *scan_chan_list; @@ -2404,8 +2404,8 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, { int ret = 0; struct mwifiex_adapter *adapter = priv->adapter; - struct cmd_ctrl_node *cmd_node = NULL; - struct host_cmd_ds_802_11_scan_rsp *scan_rsp = NULL; + struct cmd_ctrl_node *cmd_node; + struct host_cmd_ds_802_11_scan_rsp *scan_rsp; struct mwifiex_bssdescriptor *bss_new_entry = NULL; struct mwifiex_ie_types_data *tlv_data; struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; @@ -2906,7 +2906,7 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, int mwifiex_request_scan(struct mwifiex_private *priv, struct mwifiex_802_11_ssid *req_ssid) { - int ret = 0; + int ret; if (down_interruptible(&priv->async_sem)) { dev_err(priv->adapter->dev, "%s: acquire semaphore\n", diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 5148d0e0fad6..470dbaaeaa02 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -46,7 +46,7 @@ static struct semaphore add_remove_card_sem; static int mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { - int ret = 0; + int ret; struct sdio_mmc_card *card = NULL; pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n", @@ -119,7 +119,7 @@ static int mwifiex_sdio_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); struct sdio_mmc_card *card; - struct mwifiex_adapter *adapter = NULL; + struct mwifiex_adapter *adapter; mmc_pm_flag_t pm_flag = 0; int hs_actived = 0; int i; @@ -177,7 +177,7 @@ static int mwifiex_sdio_resume(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); struct sdio_mmc_card *card; - struct mwifiex_adapter *adapter = NULL; + struct mwifiex_adapter *adapter; mmc_pm_flag_t pm_flag = 0; int i; @@ -420,7 +420,7 @@ static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter, u8 *payload, u32 pkt_len, u32 port) { u32 i = 0; - int ret = 0; + int ret; do { ret = mwifiex_write_data_sync(adapter, payload, pkt_len, port); @@ -531,7 +531,7 @@ static int mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) { u32 tries; - u32 cs = 0; + u32 cs; for (tries = 0; tries < MAX_POLL_TRIES; tries++) { if (mwifiex_read_reg(adapter, CARD_STATUS_REG, &cs)) @@ -553,7 +553,7 @@ mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) static int mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) { - u32 fws0 = 0, fws1 = 0; + u32 fws0, fws1; if (mwifiex_read_reg(adapter, CARD_FW_STATUS0_REG, &fws0)) return -1; @@ -574,7 +574,7 @@ mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) */ static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) { - u32 host_int_mask = 0; + u32 host_int_mask; /* Read back the host_int_mask register */ if (mwifiex_read_reg(adapter, HOST_INT_MASK_REG, &host_int_mask)) @@ -614,7 +614,7 @@ static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter, u32 *type, u8 *buffer, u32 npayload, u32 ioport) { - int ret = 0; + int ret; u32 nb; if (!buffer) { @@ -652,14 +652,14 @@ static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter, static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, struct mwifiex_fw_image *fw) { - int ret = 0; + int ret; u8 *firmware = fw->fw_buf; u32 firmware_len = fw->fw_len; u32 offset = 0; u32 base0, base1; u8 *fwbuf; u16 len = 0; - u32 txlen = 0, tx_blocks = 0, tries = 0; + u32 txlen, tx_blocks = 0, tries; u32 i = 0; if (!firmware_len) { @@ -830,7 +830,7 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) { struct sdio_mmc_card *card = adapter->card; - u32 sdio_ireg = 0; + u32 sdio_ireg; unsigned long flags; if (mwifiex_read_data_sync(adapter, card->mp_regs, MAX_MP_REGS, @@ -964,7 +964,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, s32 f_do_rx_cur = 0; s32 f_aggr_cur = 0; struct sk_buff *skb_deaggr; - u32 pind = 0; + u32 pind; u32 pkt_len, pkt_type = 0; u8 *curr_ptr; u32 rx_len = skb->len; @@ -1114,7 +1114,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) struct sdio_mmc_card *card = adapter->card; int ret = 0; u8 sdio_ireg; - struct sk_buff *skb = NULL; + struct sk_buff *skb; u8 port = CTRL_PORT; u32 len_reg_l, len_reg_u; u32 rx_blocks; @@ -1377,7 +1377,7 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, struct mwifiex_tx_param *tx_param) { struct sdio_mmc_card *card = adapter->card; - int ret = 0; + int ret; u32 buf_block_len; u32 blk_size; u8 port = CTRL_PORT; @@ -1560,7 +1560,7 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) { struct sdio_mmc_card *card = adapter->card; int ret; - u32 sdio_ireg = 0; + u32 sdio_ireg; /* * Read the HOST_INT_STATUS_REG for ACK the first interrupt got diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 33c8ba1f5e33..8af3a78d2723 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -274,8 +274,8 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, void *data_buf) { - struct mwifiex_types_power_group *pg_tlv = NULL; - struct host_cmd_ds_txpwr_cfg *txp = NULL; + struct mwifiex_types_power_group *pg_tlv; + struct host_cmd_ds_txpwr_cfg *txp; struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg; cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG); @@ -478,7 +478,7 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv, struct mwifiex_ie_type_key_param_set *key_param_set, u16 *key_param_len) { - int cur_key_param_len = 0; + int cur_key_param_len; u8 i; /* Multi-key_param_set TLV is supported */ @@ -1121,7 +1121,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, */ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) { - int ret = 0; + int ret; u16 enable = true; struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; struct mwifiex_ds_auto_ds auto_ds; diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 7f4f10b752fb..d08f76429a0a 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -43,7 +43,7 @@ static void mwifiex_process_cmdresp_error(struct mwifiex_private *priv, struct host_cmd_ds_command *resp) { - struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; + struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; struct mwifiex_adapter *adapter = priv->adapter; struct host_cmd_ds_802_11_ps_mode_enh *pm; unsigned long flags; @@ -124,7 +124,7 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, { struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = &resp->params.rssi_info_rsp; - struct mwifiex_ds_get_signal *signal = NULL; + struct mwifiex_ds_get_signal *signal; priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); @@ -232,7 +232,7 @@ static int mwifiex_ret_get_log(struct mwifiex_private *priv, { struct host_cmd_ds_802_11_get_log *get_log = (struct host_cmd_ds_802_11_get_log *) &resp->params.get_log; - struct mwifiex_ds_get_stats *stats = NULL; + struct mwifiex_ds_get_stats *stats; if (data_buf) { stats = (struct mwifiex_ds_get_stats *) data_buf; @@ -280,10 +280,10 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, struct host_cmd_ds_command *resp, void *data_buf) { - struct mwifiex_rate_cfg *ds_rate = NULL; + struct mwifiex_rate_cfg *ds_rate; struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg; struct mwifiex_rate_scope *rate_scope; - struct mwifiex_ie_types_header *head = NULL; + struct mwifiex_ie_types_header *head; u16 tlv, tlv_buf_len; u8 *tlv_buf; u32 i; @@ -368,9 +368,9 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, */ static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf) { - int length = -1, max_power = -1, min_power = -1; - struct mwifiex_types_power_group *pg_tlv_hdr = NULL; - struct mwifiex_power_group *pg = NULL; + int length, max_power = -1, min_power = -1; + struct mwifiex_types_power_group *pg_tlv_hdr; + struct mwifiex_power_group *pg; if (data_buf) { pg_tlv_hdr = @@ -418,8 +418,8 @@ static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv, { struct mwifiex_adapter *adapter = priv->adapter; struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg; - struct mwifiex_types_power_group *pg_tlv_hdr = NULL; - struct mwifiex_power_group *pg = NULL; + struct mwifiex_types_power_group *pg_tlv_hdr; + struct mwifiex_power_group *pg; u16 action = le16_to_cpu(txp_cfg->action); switch (action) { @@ -593,7 +593,7 @@ static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv, &resp->params.domain_info_resp; struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain; u16 action = le16_to_cpu(domain_info->action); - u8 no_of_triplet = 0; + u8 no_of_triplet; no_of_triplet = (u8) ((le16_to_cpu(domain->header.len) - IEEE80211_COUNTRY_STRING_LEN) / @@ -661,7 +661,7 @@ static int mwifiex_ret_ver_ext(struct mwifiex_private *priv, void *data_buf) { struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext; - struct host_cmd_ds_version_ext *version_ext = NULL; + struct host_cmd_ds_version_ext *version_ext; if (data_buf) { version_ext = (struct host_cmd_ds_version_ext *)data_buf; @@ -682,8 +682,8 @@ static int mwifiex_ret_ver_ext(struct mwifiex_private *priv, static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp, void *data_buf) { - struct mwifiex_ds_reg_rw *reg_rw = NULL; - struct mwifiex_ds_read_eeprom *eeprom = NULL; + struct mwifiex_ds_reg_rw *reg_rw; + struct mwifiex_ds_read_eeprom *eeprom; if (data_buf) { reg_rw = (struct mwifiex_ds_reg_rw *) data_buf; diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index e7adaab35226..4585c1bb9fa9 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -149,7 +149,7 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, int mwifiex_bss_start(struct mwifiex_private *priv, struct mwifiex_ssid_bssid *ssid_bssid) { - int ret = 0; + int ret; struct mwifiex_adapter *adapter = priv->adapter; s32 i = -1; @@ -376,7 +376,7 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv, { struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_bssdescriptor *bss_desc; - s32 tbl_idx = 0; + s32 tbl_idx; if (!info) return -1; @@ -436,9 +436,8 @@ int mwifiex_set_radio_band_cfg(struct mwifiex_private *priv, struct mwifiex_ds_band_cfg *radio_cfg) { struct mwifiex_adapter *adapter = priv->adapter; - u8 infra_band = 0; - u8 adhoc_band = 0; - u32 adhoc_channel = 0; + u8 infra_band, adhoc_band; + u32 adhoc_channel; infra_band = (u8) radio_cfg->config_bands; adhoc_band = (u8) radio_cfg->adhoc_start_band; @@ -636,7 +635,7 @@ int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv, int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) { - int ret = 0; + int ret; struct mwifiex_bss_info bss_info; struct mwifiex_ssid_bssid ssid_bssid; u16 curr_chan = 0; @@ -755,11 +754,10 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv, struct mwifiex_rate_cfg *rate_cfg) { u8 rates[MWIFIEX_SUPPORTED_RATES]; - u8 *rate = NULL; - int rate_index = 0; + u8 *rate; + int rate_index, ret; u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; - u32 i = 0; - int ret = 0; + u32 i; struct mwifiex_adapter *adapter = priv->adapter; if (rate_cfg->is_rate_auto) { @@ -819,7 +817,7 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv, static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv, struct mwifiex_rate_cfg *rate_cfg) { - int status = 0; + int status; if (!rate_cfg) return -1; @@ -841,7 +839,7 @@ static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv, int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, struct mwifiex_rate_cfg *rate) { - int ret = 0; + int ret; memset(rate, 0, sizeof(struct mwifiex_rate_cfg)); rate->action = HostCmd_ACT_GEN_GET; @@ -875,11 +873,11 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, int mwifiex_set_tx_power(struct mwifiex_private *priv, struct mwifiex_power_cfg *power_cfg) { - int ret = 0; - struct host_cmd_ds_txpwr_cfg *txp_cfg = NULL; - struct mwifiex_types_power_group *pg_tlv = NULL; - struct mwifiex_power_group *pg = NULL; - u8 *buf = NULL; + int ret; + struct host_cmd_ds_txpwr_cfg *txp_cfg; + struct mwifiex_types_power_group *pg_tlv; + struct mwifiex_power_group *pg; + u8 *buf; u16 dbm = 0; if (!power_cfg->is_power_auto) { @@ -960,7 +958,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, */ int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode) { - int ret = 0; + int ret; struct mwifiex_adapter *adapter = priv->adapter; u16 sub_cmd; @@ -1078,8 +1076,8 @@ static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv, static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, struct mwifiex_ds_encrypt_key *encrypt_key) { - int ret = 0; - struct mwifiex_wep_key *wep_key = NULL; + int ret; + struct mwifiex_wep_key *wep_key; int index; if (priv->wep_key_curr_index >= NUM_WEP_KEYS) @@ -1142,7 +1140,7 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, struct mwifiex_ds_encrypt_key *encrypt_key) { - int ret = 0; + int ret; u8 remove_key = false; struct host_cmd_ds_802_11_key_material *ibss_key; @@ -1209,7 +1207,7 @@ static int mwifiex_sec_ioctl_encrypt_key(struct mwifiex_private *priv, struct mwifiex_ds_encrypt_key *encrypt_key) { - int status = 0; + int status; if (encrypt_key->is_wapi_key) status = mwifiex_sec_ioctl_set_wapi_key(priv, encrypt_key); @@ -1253,7 +1251,7 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv, struct mwifiex_ds_get_signal *signal) { struct mwifiex_ds_get_signal info; - int status = 0; + int status; memset(&info, 0, sizeof(struct mwifiex_ds_get_signal)); info.selector = ALL_RSSI_INFO_MASK; @@ -1334,7 +1332,7 @@ int mwifiex_get_stats_info(struct mwifiex_private *priv, struct mwifiex_ds_get_stats *log) { - int ret = 0; + int ret; struct mwifiex_ds_get_stats get_log; memset(&get_log, 0, sizeof(struct mwifiex_ds_get_stats)); @@ -1425,7 +1423,7 @@ int mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type, u32 reg_offset, u32 *value) { - int ret = 0; + int ret; struct mwifiex_ds_reg_rw reg_rw; reg_rw.type = cpu_to_le32(reg_type); @@ -1451,7 +1449,7 @@ int mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, u8 *value) { - int ret = 0; + int ret; struct mwifiex_ds_read_eeprom rd_eeprom; rd_eeprom.offset = cpu_to_le16((u16) offset); diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index 8282679e64fd..e047f0d8a983 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c @@ -41,7 +41,7 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) { - int ret = 0; + int ret; struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); struct mwifiex_private *priv = adapter->priv[rx_info->bss_index]; struct rx_packet_hdr *rx_pkt_hdr; @@ -123,7 +123,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); struct rx_packet_hdr *rx_pkt_hdr; u8 ta[ETH_ALEN]; - u16 rx_pkt_type = 0; + u16 rx_pkt_type; struct mwifiex_private *priv = adapter->priv[rx_info->bss_index]; local_rx_pd = (struct rxpd *) (skb->data); diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 5d37ef160121..fa6221bc9104 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c @@ -113,8 +113,8 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) /* sizeof(struct txpd) + Interface specific header */ #define NULL_PACKET_HDR 64 u32 data_len = NULL_PACKET_HDR; - struct sk_buff *skb = NULL; - int ret = 0; + struct sk_buff *skb; + int ret; struct mwifiex_txinfo *tx_info = NULL; if (adapter->surprise_removed) diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index ce772e078db8..210120889dfe 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -68,7 +68,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, { int ret = -1; struct mwifiex_adapter *adapter = priv->adapter; - u8 *head_ptr = NULL; + u8 *head_ptr; struct txpd *local_tx_pd = NULL; head_ptr = (u8 *) mwifiex_process_sta_txpd(priv, skb); @@ -121,8 +121,8 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, struct sk_buff *skb, int status) { - struct mwifiex_private *priv = NULL, *tpriv = NULL; - struct mwifiex_txinfo *tx_info = NULL; + struct mwifiex_private *priv, *tpriv; + struct mwifiex_txinfo *tx_info; int i; if (!skb) @@ -169,9 +169,9 @@ int mwifiex_recv_packet_complete(struct mwifiex_adapter *adapter, struct sk_buff *skb, int status) { struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); - struct mwifiex_rxinfo *rx_info_parent = NULL; + struct mwifiex_rxinfo *rx_info_parent; struct mwifiex_private *priv; - struct sk_buff *skb_parent = NULL; + struct sk_buff *skb_parent; unsigned long flags; priv = adapter->priv[rx_info->bss_index]; diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 7ab4fb279f8a..a8d53aa7e38d 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c @@ -152,8 +152,8 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv, */ int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) { - struct mwifiex_rxinfo *rx_info = NULL; - struct mwifiex_private *priv = NULL; + struct mwifiex_rxinfo *rx_info; + struct mwifiex_private *priv; if (!skb) return -1; @@ -184,8 +184,8 @@ int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) int mwifiex_recv_complete(struct mwifiex_adapter *adapter, struct sk_buff *skb, int status) { - struct mwifiex_private *priv = NULL; - struct mwifiex_rxinfo *rx_info = NULL; + struct mwifiex_private *priv; + struct mwifiex_rxinfo *rx_info; if (!skb) return 0; diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index c009370f309e..faa09e32902e 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -799,7 +799,7 @@ u8 mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, const struct sk_buff *skb) { - u8 ret_val = 0; + u8 ret_val; struct timeval out_tstamp, in_tstamp; u32 queue_delay; -- cgit v1.2.3-58-ga151 From 0e579d6a8f4aea346da818f13ee71401c125e639 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 3 May 2011 22:45:16 -0700 Subject: nl80211: Fix set_key regression with some drivers Commit dbd2fd656f2060abfd3a16257f8b51ec60f6d2ed added a mechanism for user space to indicate whether a default key is being configured for only unicast or only multicast frames instead of all frames. This commit added a driver capability flag for indicating whether separate default keys are supported and validation of the set_key command based on that capability. However, this single capability flag is not enough to cover possible difference based on mode (AP/IBSS/STA) and the way this change was introduced resulted in a regression with drivers that do not indicate the new capability (i.e.., more or less any non-mac80211 driver using cfg80211) when using a recent wpa_supplicant snapshot. Fix the regression by removing the new check which is not strictly speaking needed. The new separate default key functionality is needed only for RSN IBSS which has a separate capability indication. Cc: stable@kernel.org Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 0efa7fd01150..ab77f943dc04 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1682,14 +1682,6 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) if (err) goto out; - if (!(rdev->wiphy.flags & - WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS)) { - if (!key.def_uni || !key.def_multi) { - err = -EOPNOTSUPP; - goto out; - } - } - err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx, key.def_uni, key.def_multi); -- cgit v1.2.3-58-ga151 From f0dc7999b54ae0464d7144b81d21e1d39a389d49 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 3 May 2011 22:50:15 -0700 Subject: cfg80211: Remove unused wiphy flag The only user of WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS was removed and consequently, this flag can be removed, too. In addition, a single capability flag was not enough to indicate this capability clearly since the device behavior may be different based on which operating mode is being used. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- include/net/cfg80211.h | 3 --- net/mac80211/main.c | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d30eada7c6cd..4932dfcb72b4 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1455,8 +1455,6 @@ struct cfg80211_ops { * control port protocol ethertype. The device also honours the * control_port_no_encrypt flag. * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN. - * @WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS: The device supports separate - * unicast and multicast TX keys. * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing * auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH. */ @@ -1470,7 +1468,6 @@ enum wiphy_flags { WIPHY_FLAG_4ADDR_STATION = BIT(6), WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), WIPHY_FLAG_IBSS_RSN = BIT(8), - WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS= BIT(9), WIPHY_FLAG_MESH_AUTH = BIT(10), }; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 61877662e8f8..d8be1986a108 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -580,8 +580,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, wiphy->flags |= WIPHY_FLAG_NETNS_OK | WIPHY_FLAG_4ADDR_AP | - WIPHY_FLAG_4ADDR_STATION | - WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS; + WIPHY_FLAG_4ADDR_STATION; if (!ops->set_key) wiphy->flags |= WIPHY_FLAG_IBSS_RSN; -- cgit v1.2.3-58-ga151 From 9b571e24a9922f79ed2440b4482cb9f11a8f1889 Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Wed, 4 May 2011 17:22:16 +0530 Subject: mwl8k: Fix broken WEP The WEP key length was being set to 0 erroneously which broke WEP support. Fix the same by setting the key length appropriately. Signed-off-by: Yogesh Ashok Powar Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 9f5ecef297e5..d06591a7e566 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3997,7 +3997,7 @@ static int mwl8k_cmd_encryption_set_key(struct ieee80211_hw *hw, mwl8k_vif->wep_key_conf[idx].enabled = 1; } - keymlen = 0; + keymlen = key->keylen; action = MWL8K_ENCR_SET_KEY; break; case WLAN_CIPHER_SUITE_TKIP: -- cgit v1.2.3-58-ga151 From 8f7f3b2fcc4ccbba0be776049df41a2f96c986ac Mon Sep 17 00:00:00 2001 From: Nicolas Cavallari Date: Wed, 4 May 2011 15:26:52 +0200 Subject: carl9170: fix allmulticast mode Currently, the driver only disable multicast filtering when the FIF_ALLMULTI driver flag has been just set (ie, if changed_flags& FIF_ALLMULTI and *new_flags& FIF_ALLMULTI) or else it will reenable multicast filtering. But next time, this condition will be false and multicast filtering will be reenabled, even through FIF_ALLMULTI is still set. This mean that allmulticast only works for less than two minutes in ad-hoc mode. This patch fixes that to disable multicast filtering as long as FIF_ALLMULTI is set. Signed-off-by: Nicolas Cavallari Acked-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/carl9170/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 1638468be5a3..7d5c65ea94e6 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -883,7 +883,7 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw, * then checking the error flags, later. */ - if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI) + if (*new_flags & FIF_ALLMULTI) multicast = ~0ULL; if (multicast != ar->cur_mc_hash) -- cgit v1.2.3-58-ga151 From ff1b6e69ad4f31fb3c9c6da2665655f2e798dd70 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 4 May 2011 15:37:28 +0200 Subject: nl80211/cfg80211: WoWLAN support This is based on (but now quite far from) the original work from Luis and Eliad. Add support for configuring WoWLAN triggers, and getting the configuration out again. Changes from the original patchset are too numerous to list, but one important change needs highlighting: the suspend() callback is passed NULL for the trigger configuration if userspace has not configured WoWLAN at all. Signed-off-by: Luis R. Rodriguez Signed-off-by: Eliad Peller Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 99 ++++++++++++++++++++ include/net/cfg80211.h | 74 ++++++++++++++- net/mac80211/cfg.c | 3 +- net/wireless/core.c | 8 ++ net/wireless/core.h | 14 +++ net/wireless/nl80211.c | 243 ++++++++++++++++++++++++++++++++++++++++++++++++ net/wireless/sysfs.c | 2 +- 7 files changed, 439 insertions(+), 4 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index be8df57b789d..a75dea9c416e 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -420,6 +420,14 @@ * new station with the AUTHENTICATED flag unset and maybe change it later * depending on the authentication result. * + * @NL80211_CMD_GET_WOWLAN: get Wake-on-Wireless-LAN (WoWLAN) settings. + * @NL80211_CMD_SET_WOWLAN: set Wake-on-Wireless-LAN (WoWLAN) settings. + * Since wireless is more complex than wired ethernet, it supports + * various triggers. These triggers can be configured through this + * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For + * more background information, see + * http://wireless.kernel.org/en/users/Documentation/WoWLAN. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -534,6 +542,9 @@ enum nl80211_commands { NL80211_CMD_NEW_PEER_CANDIDATE, + NL80211_CMD_GET_WOWLAN, + NL80211_CMD_SET_WOWLAN, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -903,6 +914,13 @@ enum nl80211_commands { * allows auth frames in a mesh to be passed to userspace for processing via * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. * + * @NL80211_ATTR_WOWLAN_SUPPORTED: indicates, as part of the wiphy capabilities, + * the supported WoWLAN triggers + * @NL80211_ATTR_WOWLAN_TRIGGERS: used by %NL80211_CMD_SET_WOWLAN to + * indicate which WoW triggers should be enabled. This is also + * used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN + * triggers. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1092,6 +1110,9 @@ enum nl80211_attrs { NL80211_ATTR_SUPPORT_MESH_AUTH, + NL80211_ATTR_WOWLAN_TRIGGERS, + NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -2061,4 +2082,82 @@ enum nl80211_tx_power_setting { NL80211_TX_POWER_FIXED, }; +/** + * enum nl80211_wowlan_packet_pattern_attr - WoWLAN packet pattern attribute + * @__NL80211_WOWLAN_PKTPAT_INVALID: invalid number for nested attribute + * @NL80211_WOWLAN_PKTPAT_PATTERN: the pattern, values where the mask has + * a zero bit are ignored + * @NL80211_WOWLAN_PKTPAT_MASK: pattern mask, must be long enough to have + * a bit for each byte in the pattern. The lowest-order bit corresponds + * to the first byte of the pattern, but the bytes of the pattern are + * in a little-endian-like format, i.e. the 9th byte of the pattern + * corresponds to the lowest-order bit in the second byte of the mask. + * For example: The match 00:xx:00:00:xx:00:00:00:00:xx:xx:xx (where + * xx indicates "don't care") would be represented by a pattern of + * twelve zero bytes, and a mask of "0xed,0x07". + * Note that the pattern matching is done as though frames were not + * 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked + * first (including SNAP header unpacking) and then matched. + * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes + * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number + */ +enum nl80211_wowlan_packet_pattern_attr { + __NL80211_WOWLAN_PKTPAT_INVALID, + NL80211_WOWLAN_PKTPAT_MASK, + NL80211_WOWLAN_PKTPAT_PATTERN, + + NUM_NL80211_WOWLAN_PKTPAT, + MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1, +}; + +/** + * struct nl80211_wowlan_pattern_support - pattern support information + * @max_patterns: maximum number of patterns supported + * @min_pattern_len: minimum length of each pattern + * @max_pattern_len: maximum length of each pattern + * + * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when + * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the + * capability information given by the kernel to userspace. + */ +struct nl80211_wowlan_pattern_support { + __u32 max_patterns; + __u32 min_pattern_len; + __u32 max_pattern_len; +} __attribute__((packed)); + +/** + * enum nl80211_wowlan_triggers - WoWLAN trigger definitions + * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes + * @NL80211_WOWLAN_TRIG_ANY: wake up on any activity, do not really put + * the chip into a special state -- works best with chips that have + * support for low-power operation already (flag) + * @NL80211_WOWLAN_TRIG_DISCONNECT: wake up on disconnect, the way disconnect + * is detected is implementation-specific (flag) + * @NL80211_WOWLAN_TRIG_MAGIC_PKT: wake up on magic packet (6x 0xff, followed + * by 16 repetitions of MAC addr, anywhere in payload) (flag) + * @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns + * which are passed in an array of nested attributes, each nested attribute + * defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern. + * Each pattern defines a wakeup packet. The matching is done on the MSDU, + * i.e. as though the packet was an 802.3 packet, so the pattern matching + * is done after the packet is converted to the MSDU. + * + * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute + * carrying a &struct nl80211_wowlan_pattern_support. + * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers + * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number + */ +enum nl80211_wowlan_triggers { + __NL80211_WOWLAN_TRIG_INVALID, + NL80211_WOWLAN_TRIG_ANY, + NL80211_WOWLAN_TRIG_DISCONNECT, + NL80211_WOWLAN_TRIG_MAGIC_PKT, + NL80211_WOWLAN_TRIG_PKT_PATTERN, + + /* keep last */ + NUM_NL80211_WOWLAN_TRIG, + MAX_NL80211_WOWLAN_TRIG = NUM_NL80211_WOWLAN_TRIG - 1 +}; + #endif /* __LINUX_NL80211_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 4932dfcb72b4..0920daf36807 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1087,6 +1087,38 @@ struct cfg80211_pmksa { u8 *pmkid; }; +/** + * struct cfg80211_wowlan_trig_pkt_pattern - packet pattern + * @mask: bitmask where to match pattern and where to ignore bytes, + * one bit per byte, in same format as nl80211 + * @pattern: bytes to match where bitmask is 1 + * @pattern_len: length of pattern (in bytes) + * + * Internal note: @mask and @pattern are allocated in one chunk of + * memory, free @mask only! + */ +struct cfg80211_wowlan_trig_pkt_pattern { + u8 *mask, *pattern; + int pattern_len; +}; + +/** + * struct cfg80211_wowlan - Wake on Wireless-LAN support info + * + * This structure defines the enabled WoWLAN triggers for the device. + * @any: wake up on any activity -- special trigger if device continues + * operating as normal during suspend + * @disconnect: wake up if getting disconnected + * @magic_pkt: wake up on receiving magic packet + * @patterns: wake up on receiving packet matching a pattern + * @n_patterns: number of patterns + */ +struct cfg80211_wowlan { + bool any, disconnect, magic_pkt; + struct cfg80211_wowlan_trig_pkt_pattern *patterns; + int n_patterns; +}; + /** * struct cfg80211_ops - backend description for wireless configuration * @@ -1100,7 +1132,9 @@ struct cfg80211_pmksa { * wireless extensions but this is subject to reevaluation as soon as this * code is used more widely and we have a first user without wext. * - * @suspend: wiphy device needs to be suspended + * @suspend: wiphy device needs to be suspended. The variable @wow will + * be %NULL or contain the enabled Wake-on-Wireless triggers that are + * configured for the device. * @resume: wiphy device needs to be resumed * * @add_virtual_intf: create a new virtual interface with the given name, @@ -1244,7 +1278,7 @@ struct cfg80211_pmksa { * @get_ringparam: Get tx and rx ring current and maximum sizes. */ struct cfg80211_ops { - int (*suspend)(struct wiphy *wiphy); + int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); int (*resume)(struct wiphy *wiphy); struct net_device * (*add_virtual_intf)(struct wiphy *wiphy, @@ -1479,6 +1513,38 @@ struct ieee80211_txrx_stypes { u16 tx, rx; }; +/** + * enum wiphy_wowlan_support_flags - WoWLAN support flags + * @WIPHY_WOWLAN_ANY: supports wakeup for the special "any" + * trigger that keeps the device operating as-is and + * wakes up the host on any activity, for example a + * received packet that passed filtering; note that the + * packet should be preserved in that case + * @WIPHY_WOWLAN_MAGIC_PKT: supports wakeup on magic packet + * (see nl80211.h) + * @WIPHY_WOWLAN_DISCONNECT: supports wakeup on disconnect + */ +enum wiphy_wowlan_support_flags { + WIPHY_WOWLAN_ANY = BIT(0), + WIPHY_WOWLAN_MAGIC_PKT = BIT(1), + WIPHY_WOWLAN_DISCONNECT = BIT(2), +}; + +/** + * struct wiphy_wowlan_support - WoWLAN support data + * @flags: see &enum wiphy_wowlan_support_flags + * @n_patterns: number of supported wakeup patterns + * (see nl80211.h for the pattern definition) + * @pattern_max_len: maximum length of each pattern + * @pattern_min_len: minimum length of each pattern + */ +struct wiphy_wowlan_support { + u32 flags; + int n_patterns; + int pattern_max_len; + int pattern_min_len; +}; + /** * struct wiphy - wireless hardware description * @reg_notifier: the driver's regulatory notification callback, @@ -1546,6 +1612,8 @@ struct ieee80211_txrx_stypes { * * @max_remain_on_channel_duration: Maximum time a remain-on-channel operation * may request, if implemented. + * + * @wowlan: WoWLAN support information */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -1583,6 +1651,8 @@ struct wiphy { char fw_version[ETHTOOL_BUSINFO_LEN]; u32 hw_version; + struct wiphy_wowlan_support wowlan; + u16 max_remain_on_channel_duration; u8 max_num_pmkids; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 12d52cec9515..321d598eb8cb 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1297,7 +1297,8 @@ static int ieee80211_set_channel(struct wiphy *wiphy, } #ifdef CONFIG_PM -static int ieee80211_suspend(struct wiphy *wiphy) +static int ieee80211_suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wowlan) { return __ieee80211_suspend(wiphy_priv(wiphy)); } diff --git a/net/wireless/core.c b/net/wireless/core.c index bbf1fa11107a..bea0d80710c8 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -493,6 +493,13 @@ int wiphy_register(struct wiphy *wiphy) return -EINVAL; } + if (rdev->wiphy.wowlan.n_patterns) { + if (WARN_ON(!rdev->wiphy.wowlan.pattern_min_len || + rdev->wiphy.wowlan.pattern_min_len > + rdev->wiphy.wowlan.pattern_max_len)) + return -EINVAL; + } + /* check and set up bitrates */ ieee80211_set_bitrate_flags(wiphy); @@ -631,6 +638,7 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) mutex_destroy(&rdev->devlist_mtx); list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) cfg80211_put_bss(&scan->pub); + cfg80211_rdev_free_wowlan(rdev); kfree(rdev); } diff --git a/net/wireless/core.h b/net/wireless/core.h index 26a0a084e16b..7a18c10a7fb6 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -70,6 +70,8 @@ struct cfg80211_registered_device { struct work_struct conn_work; struct work_struct event_work; + struct cfg80211_wowlan *wowlan; + /* must be last because of the way we do wiphy_priv(), * and it should at least be aligned to NETDEV_ALIGN */ struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); @@ -89,6 +91,18 @@ bool wiphy_idx_valid(int wiphy_idx) return wiphy_idx >= 0; } +static inline void +cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) +{ + int i; + + if (!rdev->wowlan) + return; + for (i = 0; i < rdev->wowlan->n_patterns; i++) + kfree(rdev->wowlan->patterns[i].mask); + kfree(rdev->wowlan->patterns); + kfree(rdev->wowlan); +} extern struct workqueue_struct *cfg80211_wq; extern struct mutex cfg80211_mutex; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index ab77f943dc04..0a199a1ca9b6 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -173,6 +173,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 }, [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, + [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED }, }; /* policy for the key attributes */ @@ -194,6 +195,15 @@ nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = { [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG }, }; +/* policy for WoWLAN attributes */ +static const struct nla_policy +nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = { + [NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG }, + [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG }, + [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG }, + [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED }, +}; + /* ifidx get helper */ static int nl80211_get_ifidx(struct netlink_callback *cb) { @@ -821,6 +831,35 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, nla_nest_end(msg, nl_ifs); } + if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) { + struct nlattr *nl_wowlan; + + nl_wowlan = nla_nest_start(msg, + NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED); + if (!nl_wowlan) + goto nla_put_failure; + + if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY); + if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); + if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); + if (dev->wiphy.wowlan.n_patterns) { + struct nl80211_wowlan_pattern_support pat = { + .max_patterns = dev->wiphy.wowlan.n_patterns, + .min_pattern_len = + dev->wiphy.wowlan.pattern_min_len, + .max_pattern_len = + dev->wiphy.wowlan.pattern_max_len, + }; + NLA_PUT(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, + sizeof(pat), &pat); + } + + nla_nest_end(msg, nl_wowlan); + } + return genlmsg_end(msg, hdr); nla_put_failure: @@ -4808,6 +4847,194 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) return cfg80211_leave_mesh(rdev, dev); } +static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct sk_buff *msg; + void *hdr; + + if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns) + return -EOPNOTSUPP; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, + NL80211_CMD_GET_WOWLAN); + if (!hdr) + goto nla_put_failure; + + if (rdev->wowlan) { + struct nlattr *nl_wowlan; + + nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS); + if (!nl_wowlan) + goto nla_put_failure; + + if (rdev->wowlan->any) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY); + if (rdev->wowlan->disconnect) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); + if (rdev->wowlan->magic_pkt) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); + if (rdev->wowlan->n_patterns) { + struct nlattr *nl_pats, *nl_pat; + int i, pat_len; + + nl_pats = nla_nest_start(msg, + NL80211_WOWLAN_TRIG_PKT_PATTERN); + if (!nl_pats) + goto nla_put_failure; + + for (i = 0; i < rdev->wowlan->n_patterns; i++) { + nl_pat = nla_nest_start(msg, i + 1); + if (!nl_pat) + goto nla_put_failure; + pat_len = rdev->wowlan->patterns[i].pattern_len; + NLA_PUT(msg, NL80211_WOWLAN_PKTPAT_MASK, + DIV_ROUND_UP(pat_len, 8), + rdev->wowlan->patterns[i].mask); + NLA_PUT(msg, NL80211_WOWLAN_PKTPAT_PATTERN, + pat_len, + rdev->wowlan->patterns[i].pattern); + nla_nest_end(msg, nl_pat); + } + nla_nest_end(msg, nl_pats); + } + + nla_nest_end(msg, nl_wowlan); + } + + genlmsg_end(msg, hdr); + return genlmsg_reply(msg, info); + +nla_put_failure: + nlmsg_free(msg); + return -ENOBUFS; +} + +static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG]; + struct cfg80211_wowlan no_triggers = {}; + struct cfg80211_wowlan new_triggers = {}; + struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; + int err, i; + + if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns) + return -EOPNOTSUPP; + + if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) + goto no_triggers; + + err = nla_parse(tb, MAX_NL80211_WOWLAN_TRIG, + nla_data(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), + nla_len(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), + nl80211_wowlan_policy); + if (err) + return err; + + if (tb[NL80211_WOWLAN_TRIG_ANY]) { + if (!(wowlan->flags & WIPHY_WOWLAN_ANY)) + return -EINVAL; + new_triggers.any = true; + } + + if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) { + if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT)) + return -EINVAL; + new_triggers.disconnect = true; + } + + if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) { + if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT)) + return -EINVAL; + new_triggers.magic_pkt = true; + } + + if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { + struct nlattr *pat; + int n_patterns = 0; + int rem, pat_len, mask_len; + struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT]; + + nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], + rem) + n_patterns++; + if (n_patterns > wowlan->n_patterns) + return -EINVAL; + + new_triggers.patterns = kcalloc(n_patterns, + sizeof(new_triggers.patterns[0]), + GFP_KERNEL); + if (!new_triggers.patterns) + return -ENOMEM; + + new_triggers.n_patterns = n_patterns; + i = 0; + + nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], + rem) { + nla_parse(pat_tb, MAX_NL80211_WOWLAN_PKTPAT, + nla_data(pat), nla_len(pat), NULL); + err = -EINVAL; + if (!pat_tb[NL80211_WOWLAN_PKTPAT_MASK] || + !pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]) + goto error; + pat_len = nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]); + mask_len = DIV_ROUND_UP(pat_len, 8); + if (nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]) != + mask_len) + goto error; + if (pat_len > wowlan->pattern_max_len || + pat_len < wowlan->pattern_min_len) + goto error; + + new_triggers.patterns[i].mask = + kmalloc(mask_len + pat_len, GFP_KERNEL); + if (!new_triggers.patterns[i].mask) { + err = -ENOMEM; + goto error; + } + new_triggers.patterns[i].pattern = + new_triggers.patterns[i].mask + mask_len; + memcpy(new_triggers.patterns[i].mask, + nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]), + mask_len); + new_triggers.patterns[i].pattern_len = pat_len; + memcpy(new_triggers.patterns[i].pattern, + nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]), + pat_len); + i++; + } + } + + if (memcmp(&new_triggers, &no_triggers, sizeof(new_triggers))) { + struct cfg80211_wowlan *ntrig; + ntrig = kmemdup(&new_triggers, sizeof(new_triggers), + GFP_KERNEL); + if (!ntrig) { + err = -ENOMEM; + goto error; + } + cfg80211_rdev_free_wowlan(rdev); + rdev->wowlan = ntrig; + } else { + no_triggers: + cfg80211_rdev_free_wowlan(rdev); + rdev->wowlan = NULL; + } + + return 0; + error: + for (i = 0; i < new_triggers.n_patterns; i++) + kfree(new_triggers.patterns[i].mask); + kfree(new_triggers.patterns); + return err; +} + #define NL80211_FLAG_NEED_WIPHY 0x01 #define NL80211_FLAG_NEED_NETDEV 0x02 #define NL80211_FLAG_NEED_RTNL 0x04 @@ -5306,6 +5533,22 @@ static struct genl_ops nl80211_ops[] = { .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, + { + .cmd = NL80211_CMD_GET_WOWLAN, + .doit = nl80211_get_wowlan, + .policy = nl80211_policy, + /* can be retrieved by unprivileged users */ + .internal_flags = NL80211_FLAG_NEED_WIPHY | + NL80211_FLAG_NEED_RTNL, + }, + { + .cmd = NL80211_CMD_SET_WOWLAN, + .doit = nl80211_set_wowlan, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_WIPHY | + NL80211_FLAG_NEED_RTNL, + }, }; static struct genl_multicast_group nl80211_mlme_mcgrp = { diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 4294fa22bb2d..c6e4ca6a7d2e 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c @@ -93,7 +93,7 @@ static int wiphy_suspend(struct device *dev, pm_message_t state) if (rdev->ops->suspend) { rtnl_lock(); - ret = rdev->ops->suspend(&rdev->wiphy); + ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan); rtnl_unlock(); } -- cgit v1.2.3-58-ga151 From eecc48000afe2ca6da22122d553b7cad294e42fc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 4 May 2011 15:37:29 +0200 Subject: mac80211: add basic support for WoWLAN This adds basic support for the new WoWLAN configuration in mac80211. The behaviour is completely offloaded to the driver though, with two new callbacks (suspend/resume). Options for the driver include a complete reconfiguration after wakeup, and exposing all the triggers it wants to support. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 16 ++++++++++++++++ net/mac80211/cfg.c | 2 +- net/mac80211/debugfs.c | 2 +- net/mac80211/driver-ops.h | 27 +++++++++++++++++++++++++++ net/mac80211/driver-trace.h | 10 ++++++++++ net/mac80211/ieee80211_i.h | 9 +++++++-- net/mac80211/main.c | 4 ++++ net/mac80211/pm.c | 13 ++++++++++++- net/mac80211/util.c | 19 +++++++++++++++++++ 9 files changed, 97 insertions(+), 5 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 63f75a06043b..9e5542794b95 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1606,6 +1606,18 @@ enum ieee80211_ampdu_mlme_action { * you should ensure to cancel it on this callback. * Must be implemented and can sleep. * + * @suspend: Suspend the device; mac80211 itself will quiesce before and + * stop transmitting and doing any other configuration, and then + * ask the device to suspend. This is only invoked when WoWLAN is + * configured, otherwise the device is deconfigured completely and + * reconfigured at resume time. + * + * @resume: If WoWLAN was configured, this indicates that mac80211 is + * now resuming its operation, after this the device must be fully + * functional again. If this returns an error, the only way out is + * to also unregister the device. If it returns 1, then mac80211 + * will also go through the regular complete restart on resume. + * * @add_interface: Called when a netdevice attached to the hardware is * enabled. Because it is not called for monitor mode devices, @start * and @stop must be implemented. @@ -1831,6 +1843,10 @@ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); int (*start)(struct ieee80211_hw *hw); void (*stop)(struct ieee80211_hw *hw); +#ifdef CONFIG_PM + int (*suspend)(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); + int (*resume)(struct ieee80211_hw *hw); +#endif int (*add_interface)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int (*change_interface)(struct ieee80211_hw *hw, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 321d598eb8cb..1ebc13383ae7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1300,7 +1300,7 @@ static int ieee80211_set_channel(struct wiphy *wiphy, static int ieee80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wowlan) { - return __ieee80211_suspend(wiphy_priv(wiphy)); + return __ieee80211_suspend(wiphy_priv(wiphy), wowlan); } static int ieee80211_resume(struct wiphy *wiphy) diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 0a602dbfdb2b..186e02f7cc32 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -135,7 +135,7 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf, struct ieee80211_local *local = file->private_data; rtnl_lock(); - __ieee80211_suspend(&local->hw); + __ieee80211_suspend(&local->hw, NULL); __ieee80211_resume(&local->hw); rtnl_unlock(); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 2ddb56e5b51f..aa16bd8ef789 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -41,6 +41,33 @@ static inline void drv_stop(struct ieee80211_local *local) local->started = false; } +#ifdef CONFIG_PM +static inline int drv_suspend(struct ieee80211_local *local, + struct cfg80211_wowlan *wowlan) +{ + int ret; + + might_sleep(); + + trace_drv_suspend(local); + ret = local->ops->suspend(&local->hw, wowlan); + trace_drv_return_int(local, ret); + return ret; +} + +static inline int drv_resume(struct ieee80211_local *local) +{ + int ret; + + might_sleep(); + + trace_drv_resume(local); + ret = local->ops->resume(&local->hw); + trace_drv_return_int(local, ret); + return ret; +} +#endif + static inline int drv_add_interface(struct ieee80211_local *local, struct ieee80211_vif *vif) { diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 191e834ec46b..11e1ea5111ea 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -108,6 +108,16 @@ DEFINE_EVENT(local_only_evt, drv_start, TP_ARGS(local) ); +DEFINE_EVENT(local_only_evt, drv_suspend, + TP_PROTO(struct ieee80211_local *local), + TP_ARGS(local) +); + +DEFINE_EVENT(local_only_evt, drv_resume, + TP_PROTO(struct ieee80211_local *local), + TP_ARGS(local) +); + DEFINE_EVENT(local_only_evt, drv_stop, TP_PROTO(struct ieee80211_local *local), TP_ARGS(local) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 9e3b4f0f31bd..e89bc27f8dc3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -764,6 +764,9 @@ struct ieee80211_local { /* device is started */ bool started; + /* wowlan is enabled -- don't reconfig on resume */ + bool wowlan; + int tx_headroom; /* required headroom for hardware/radiotap */ /* count for keys needing tailroom space allocation */ @@ -1250,7 +1253,8 @@ int ieee80211_reconfig(struct ieee80211_local *local); void ieee80211_stop_device(struct ieee80211_local *local); #ifdef CONFIG_PM -int __ieee80211_suspend(struct ieee80211_hw *hw); +int __ieee80211_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan); static inline int __ieee80211_resume(struct ieee80211_hw *hw) { @@ -1263,7 +1267,8 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw) return ieee80211_reconfig(hw_to_local(hw)); } #else -static inline int __ieee80211_suspend(struct ieee80211_hw *hw) +static inline int __ieee80211_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan) { return 0; } diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d8be1986a108..cb326d36be9c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -696,6 +696,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) WLAN_CIPHER_SUITE_AES_CMAC }; + if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) && + (!local->ops->suspend || !local->ops->resume)) + return -EINVAL; + if (hw->max_report_rates == 0) hw->max_report_rates = hw->max_rates; diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 042461710880..730778a2c90c 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -6,7 +6,7 @@ #include "driver-ops.h" #include "led.h" -int __ieee80211_suspend(struct ieee80211_hw *hw) +int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; @@ -47,6 +47,16 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) cancel_work_sync(&local->dynamic_ps_enable_work); del_timer_sync(&local->dynamic_ps_timer); + local->wowlan = wowlan && local->open_count; + if (local->wowlan) { + int err = drv_suspend(local, wowlan); + if (err) { + local->quiescing = false; + return err; + } + goto suspend; + } + /* disable keys */ list_for_each_entry(sdata, &local->interfaces, list) ieee80211_disable_keys(sdata); @@ -104,6 +114,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) if (local->open_count) ieee80211_stop_device(local); + suspend: local->suspended = true; /* need suspended to be visible before quiescing is false */ barrier(); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ef0560a2346a..d3fe2d237485 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1125,9 +1125,27 @@ int ieee80211_reconfig(struct ieee80211_local *local) struct sta_info *sta; int res; +#ifdef CONFIG_PM if (local->suspended) local->resuming = true; + if (local->wowlan) { + local->wowlan = false; + res = drv_resume(local); + if (res < 0) { + local->resuming = false; + return res; + } + if (res == 0) + goto wake_up; + WARN_ON(res > 1); + /* + * res is 1, which means the driver requested + * to go through a regular reset on wakeup. + */ + } +#endif + /* restart hardware */ if (local->open_count) { /* @@ -1258,6 +1276,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) if (ieee80211_sdata_running(sdata)) ieee80211_enable_keys(sdata); + wake_up: ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_SUSPEND); -- cgit v1.2.3-58-ga151 From 28ef6450f0182f95c4f50aaa0ab2043a09c72b0a Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Wed, 4 May 2011 19:37:17 +0530 Subject: ath9k_hw: do noise floor calibration only on required chains At present the noise floor calibration is processed in supported control and extension chains rather than required chains. Unnccesarily doing nfcal in all supported chains leads to invalid nf readings on extn chains and these invalid values got updated into history buffer. While loading those values from history buffer is moving the chip to deaf state. This issue was observed in AR9002/AR9003 chips while doing associate/dissociate in HT40 mode and interface up/down in iterative manner. After some iterations, the chip was moved to deaf state. Somehow the pci devices are recovered by poll work after chip reset. Raading the nf values in all supported extension chains when the hw is not yet configured in HT40 mode results invalid values. Cc: stable@kernel.org Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 8649581fa4dd..fe3c10e6b276 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -69,15 +69,21 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, int16_t *nfarray) { struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_conf *conf = &common->hw->conf; struct ath_nf_limits *limit; struct ath9k_nfcal_hist *h; bool high_nf_mid = false; + u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; int i; h = cal->nfCalHist; limit = ath9k_hw_get_nf_limits(ah, ah->curchan); for (i = 0; i < NUM_NF_READINGS; i++) { + if (!(chainmask & (1 << i)) || + ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) + continue; + h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) @@ -225,6 +231,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) int32_t val; u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_conf *conf = &common->hw->conf; s16 default_nf = ath9k_hw_get_default_nf(ah, chan); if (ah->caldata) @@ -234,6 +241,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) if (chainmask & (1 << i)) { s16 nfval; + if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) + continue; + if (h) nfval = h[i].privNF; else @@ -293,6 +303,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) ENABLE_REGWRITE_BUFFER(ah); for (i = 0; i < NUM_NF_READINGS; i++) { if (chainmask & (1 << i)) { + if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) + continue; + val = REG_READ(ah, ah->nf_regs[i]); val &= 0xFFFFFE00; val |= (((u32) (-50) << 1) & 0x1ff); -- cgit v1.2.3-58-ga151 From aca355b9784fbc960c9caa6b30f953a965296420 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Wed, 4 May 2011 21:41:36 +0200 Subject: rt2x00: Initial support for RT5370 USB devices. Add necessary RF chipset define and basic support for these devices. Tested-by: Juan Carlos Garza Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 11 ++++++++++- drivers/net/wireless/rt2x00/rt2800.h | 2 ++ drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++++- drivers/net/wireless/rt2x00/rt2800usb.c | 8 ++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index c45773108283..9def1e5369a1 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -93,7 +93,7 @@ config RT2800PCI_RT35XX intended for testers and developers. config RT2800PCI_RT53XX - bool "rt2800-pci - Include support for rt53xx devices (EXPERIMENTAL)" + bool "rt2800pci - Include support for rt53xx devices (EXPERIMENTAL)" depends on EXPERIMENTAL default y ---help--- @@ -163,6 +163,15 @@ config RT2800USB_RT35XX Support for these devices is non-functional at the moment and is intended for testers and developers. +config RT2800USB_RT53XX + bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL + default y + ---help--- + This adds support for rt53xx wireless chipset family to the + rt2800pci driver. + Supported chips: RT5370 + config RT2800USB_UNKNOWN bool "rt2800usb - Include support for unknown (USB) devices" default n diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 3b3d851fe266..47a04d2dad4b 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -51,6 +51,7 @@ * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) * RF3853 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) + * RF5370 2.4G 1T1R * RF5390 2.4G 1T1R */ #define RF2820 0x0001 @@ -66,6 +67,7 @@ #define RF3320 0x000b #define RF3322 0x000c #define RF3853 0x000d +#define RF5370 0x5370 #define RF5390 0x5390 /* diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 6ed646a02d49..93fb67491acc 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1751,7 +1751,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2x00_rf(rt2x00dev, RF3052) || rt2x00_rf(rt2x00dev, RF3320)) rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); - else if (rt2x00_rf(rt2x00dev, RF5390)) + else if (rt2x00_rf(rt2x00dev, RF5370) || + rt2x00_rf(rt2x00dev, RF5390)) rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); else rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); @@ -3686,6 +3687,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) !rt2x00_rf(rt2x00dev, RF3022) && !rt2x00_rf(rt2x00dev, RF3052) && !rt2x00_rf(rt2x00dev, RF3320) && + !rt2x00_rf(rt2x00dev, RF5370) && !rt2x00_rf(rt2x00dev, RF5390)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); return -ENODEV; @@ -3988,6 +3990,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00_rf(rt2x00dev, RF3021) || rt2x00_rf(rt2x00dev, RF3022) || rt2x00_rf(rt2x00dev, RF3320) || + rt2x00_rf(rt2x00dev, RF5370) || rt2x00_rf(rt2x00dev, RF5390)) { spec->num_channels = 14; spec->channels = rf_vals_3x; diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 0eb44cf2f44a..ba82c972703a 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1000,6 +1000,14 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Zinwell */ { USB_DEVICE(0x5a57, 0x0284) }, #endif +#ifdef CONFIG_RT2800USB_RT53XX + /* Azurewave */ + { USB_DEVICE(0x13d3, 0x3329) }, + { USB_DEVICE(0x13d3, 0x3365) }, + /* Ralink */ + { USB_DEVICE(0x148f, 0x5370) }, + { USB_DEVICE(0x148f, 0x5372) }, +#endif #ifdef CONFIG_RT2800USB_UNKNOWN /* * Unclear what kind of devices these are (they aren't supported by the -- cgit v1.2.3-58-ga151 From 4268d8ed64ed918384954924284ba396cdb0e388 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 4 May 2011 21:42:05 +0200 Subject: rt2x00: Fix transfer speed regression for USB hardware Patch: rt2x00: Make rt2x00_queue_entry_for_each more flexible commit: 10e11568ca8b8a15f7478f6a4ceebabcbdba1018 introduced a severe regression on the throughput for USB hardware. It turns out that the exiting of the rt2x00queue_for_each_entry() was done too early. The exact cause for this regression is unknown, but by disabling the premature exiting of the loop seems to resolve the issue. Signed-off-by: Ivo van Doorn Reported-by: Yasushi SHOJI Reported-by: Balint Viragh Tested-by: Balint Viragh Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index e027ebd44583..dc6b662ad5f1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -298,7 +298,7 @@ static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data) if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) || test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) - return true; + return false; /* * USB devices cannot blindly pass the skb->len as the @@ -392,7 +392,7 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data) if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) - return true; + return false; rt2x00lib_dmastart(entry); @@ -447,7 +447,7 @@ static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data) struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) - return true; + return false; usb_kill_urb(entry_priv->urb); -- cgit v1.2.3-58-ga151 From cf3a03b9c99a0b2715741d116f50f513f545bb2d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 4 May 2011 14:01:26 -0700 Subject: ath9k_hw: fix power for the HT40 duplicate frames With AR9003 at about ~ 10 feet from an AP that uses RTS / CTS you will be able to associate but not not get data through given that the power for the rates used was set too low. This increases the power and permits data connectivity at longer distances from access points when connected with HT40. Without this you will not get any data through when associated to APs configured in HT40 at about more than 10 feet away. Cc: stable@kernel.org Cc: Fiona Cain Cc: Zhen Xie Cc: Kathy Giori Cc: Neha Choksi Cc: Wayne Daniel Cc: Gaurav Jauhar Cc: Samira Naraghi CC: Ashok Chennupati Cc: Lance Zimmerman Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 97f970c5e4ec..a9dd3a4b4af5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -4005,6 +4005,16 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0) ); + /* Write the power for duplicated frames - HT40 */ + + /* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */ + REG_WRITE(ah, 0xa3e0, + POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) | + POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) | + POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) | + POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0) + ); + /* Write the HT20 power per rate set */ /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ -- cgit v1.2.3-58-ga151 From fc2b1e0cfe9b4cabde8afeacc2bb81a95bf83afb Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 5 May 2011 12:45:52 +0200 Subject: b43: drop invalid IMCFGLO workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were performing it on wrong core, it was outdated and is already implemented in ssb. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 57eb5b649730..675e288a3c53 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4212,33 +4212,7 @@ static void b43_bluetooth_coext_disable(struct b43_wldev *dev) static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev) { -#ifdef CONFIG_SSB_DRIVER_PCICORE - struct ssb_bus *bus = dev->dev->bus; - u32 tmp; - - if (bus->pcicore.dev && - bus->pcicore.dev->id.coreid == SSB_DEV_PCI && - bus->pcicore.dev->id.revision <= 5) { - /* IMCFGLO timeouts workaround. */ - tmp = ssb_read32(dev->dev, SSB_IMCFGLO); - switch (bus->bustype) { - case SSB_BUSTYPE_PCI: - case SSB_BUSTYPE_PCMCIA: - tmp &= ~SSB_IMCFGLO_REQTO; - tmp &= ~SSB_IMCFGLO_SERTO; - tmp |= 0x32; - break; - case SSB_BUSTYPE_SSB: - tmp &= ~SSB_IMCFGLO_REQTO; - tmp &= ~SSB_IMCFGLO_SERTO; - tmp |= 0x53; - break; - default: - break; - } - ssb_write32(dev->dev, SSB_IMCFGLO, tmp); - } -#endif /* CONFIG_SSB_DRIVER_PCICORE */ + /* TODO: implement 80211 core workaround here */ } static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle) -- cgit v1.2.3-58-ga151 From eee40820e95e6dbd7b0709e7b8cca453004ae7b1 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 5 May 2011 12:46:04 +0200 Subject: b43legacy: drop invalid IMCFGLO workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were performing it on wrong core, it was outdated and is already implemented in ssb. Signed-off-by: Rafał Miłecki Tested-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/main.c | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index c7fd73e3ad76..2162663293c0 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3104,37 +3104,6 @@ static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev) memset(&dev->noisecalc, 0, sizeof(dev->noisecalc)); } -static void b43legacy_imcfglo_timeouts_workaround(struct b43legacy_wldev *dev) -{ -#ifdef CONFIG_SSB_DRIVER_PCICORE - struct ssb_bus *bus = dev->dev->bus; - u32 tmp; - - if (bus->pcicore.dev && - bus->pcicore.dev->id.coreid == SSB_DEV_PCI && - bus->pcicore.dev->id.revision <= 5) { - /* IMCFGLO timeouts workaround. */ - tmp = ssb_read32(dev->dev, SSB_IMCFGLO); - switch (bus->bustype) { - case SSB_BUSTYPE_PCI: - case SSB_BUSTYPE_PCMCIA: - tmp &= ~SSB_IMCFGLO_REQTO; - tmp &= ~SSB_IMCFGLO_SERTO; - tmp |= 0x32; - break; - case SSB_BUSTYPE_SSB: - tmp &= ~SSB_IMCFGLO_REQTO; - tmp &= ~SSB_IMCFGLO_SERTO; - tmp |= 0x53; - break; - default: - break; - } - ssb_write32(dev->dev, SSB_IMCFGLO, tmp); - } -#endif /* CONFIG_SSB_DRIVER_PCICORE */ -} - static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev, bool idle) { u16 pu_delay = 1050; @@ -3278,7 +3247,6 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev) /* Enable IRQ routing to this device. */ ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); - b43legacy_imcfglo_timeouts_workaround(dev); prepare_phy_data_for_init(dev); b43legacy_phy_calibrate(dev); err = b43legacy_chip_init(dev); -- cgit v1.2.3-58-ga151 From e4eefec73ea0a740bfe8736e3ac30dfe92fe392b Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Thu, 5 May 2011 16:30:48 +0530 Subject: mwl8k: Do not ask mac80211 to generate IV for crypto keys Since firmware is capable of generating IV's for all crypto suits (TKIP, CCMP and WEP), do not ask mac80211 to generate IV when HW crypto is being used. Instead only reserve appropriate space in tx skb's in the driver, so that the firmware can write IV's values. Signed-off-by: Yogesh Ashok Powar Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index d06591a7e566..32261189bcef 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -784,7 +784,8 @@ static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos) #define REDUCED_TX_HEADROOM 8 static void -mwl8k_add_dma_header(struct mwl8k_priv *priv, struct sk_buff *skb, int tail_pad) +mwl8k_add_dma_header(struct mwl8k_priv *priv, struct sk_buff *skb, + int head_pad, int tail_pad) { struct ieee80211_hdr *wh; int hdrlen; @@ -816,7 +817,7 @@ mwl8k_add_dma_header(struct mwl8k_priv *priv, struct sk_buff *skb, int tail_pad) skb->truesize += REDUCED_TX_HEADROOM; } - reqd_hdrlen = sizeof(*tr); + reqd_hdrlen = sizeof(*tr) + head_pad; if (hdrlen != reqd_hdrlen) skb_push(skb, reqd_hdrlen - hdrlen); @@ -845,6 +846,7 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, struct ieee80211_tx_info *tx_info; struct ieee80211_key_conf *key_conf; int data_pad; + int head_pad = 0; wh = (struct ieee80211_hdr *)skb->data; @@ -856,9 +858,7 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, /* * Make sure the packet header is in the DMA header format (4-address - * without QoS), the necessary crypto padding between the header and the - * payload has already been provided by mac80211, but it doesn't add - * tail padding when HW crypto is enabled. + * without QoS), and add head & tail padding when HW crypto is enabled. * * We have the following trailer padding requirements: * - WEP: 4 trailer bytes (ICV) @@ -867,6 +867,7 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, */ data_pad = 0; if (key_conf != NULL) { + head_pad = key_conf->iv_len; switch (key_conf->cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: @@ -880,7 +881,7 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, break; } } - mwl8k_add_dma_header(priv, skb, data_pad); + mwl8k_add_dma_header(priv, skb, head_pad, data_pad); } /* @@ -1837,7 +1838,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) if (priv->ap_fw) mwl8k_encapsulate_tx_frame(priv, skb); else - mwl8k_add_dma_header(priv, skb, 0); + mwl8k_add_dma_header(priv, skb, 0, 0); wh = &((struct mwl8k_dma_data *)skb->data)->wh; @@ -4071,7 +4072,6 @@ static int mwl8k_set_key(struct ieee80211_hw *hw, addr = sta->addr; if (cmd_param == SET_KEY) { - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; rc = mwl8k_cmd_encryption_set_key(hw, vif, addr, key); if (rc) goto out; -- cgit v1.2.3-58-ga151 From 4613e72dbdc9a44bfc4625d835511264121c4244 Mon Sep 17 00:00:00 2001 From: "Cindy H. Kao" Date: Fri, 6 May 2011 10:40:15 -0700 Subject: iwlwifi: support the svtool messages interactions through nl80211 test mode This patch adds the feature to support the test mode operation through the generic netlink channel NL80211_CMD_TESTMODE between intel wireless device iwlwifi and the user space application svtool. The main purpose is to create a transportation layer between the iwlwifi device and the user space application so that the interaction between the user space application svtool and the iwlwifi device in the kernel space is in a way of generic netlink messaging. The detail specific functions are: 1. The function iwl_testmode_cmd() is added to digest the svtool test command from the user space application. The svtool test commands are categorized to three types : commands to be processed by the device ucode, commands to access the registers, and commands to be processed at the driver level(such as reload the ucode). iwl_testmode_cmd() dispatches the commands the corresponding handlers and reply to user space regarding the command execution status. Extra data is returned to the user space application if there's any. 2. The function iwl_testmode_ucode_rx_pkt() is added to multicast all the spontaneous messages from the iwlwifi device to the user space. Regardless the message types, whenever there is a valid spontaneous message received by the iwlwifi ISR, iwl_testmode_ucode_rx_pkt() is invoked to multicast the message content to user space. The message content is not attacked and the message parsing is left to the user space application. Implementation guidelines: 1. The generic netlink messaging for iwliwif test mode is through NL80211_CMD_TESTMODE channel, therefore, the codes need to follow the regulations set by cfg80211.ko to get the actual device instance ieee80211_ops via cfg80211.ko, so that the iwlwifi device is indicated with ieee80211_ops and can be actually accessed. Therefore, a callback iwl_testmode_cmd() is added to the structure iwlagn_hw_ops in iwl-agn.c. 2. It intends to utilize those low level device access APIs from iwlwifi device driver (ie. iwlagn.ko) rather than creating it's own set of device access functions. For example, iwl_send_cmd(), iwl_read32(), iwl_write8(), and iwl_write32() are reused. 3. The main functions are maintained in new files instead of spreading all over the existing iwlwifi driver files. The new files added are : drivers/net/wireless/iwlwifi/iwl-sv-open.c - to handle the user space test mode application command and reply the respective command status to the user space application. - to multicast the spontaneous messages from device to user space. drivers/net/wireless/iwlwifi/iwl-testmode.h - the commonly referenced definitions for the TLVs used in the generic netlink messages Signed-off-by: Cindy H. Kao Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/Kconfig | 10 + drivers/net/wireless/iwlwifi/Makefile | 1 + drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 17 + drivers/net/wireless/iwlwifi/iwl-dev.h | 2 + drivers/net/wireless/iwlwifi/iwl-sv-open.c | 469 +++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-testmode.h | 151 +++++++++ 8 files changed, 656 insertions(+), 2 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-sv-open.c create mode 100644 drivers/net/wireless/iwlwifi/iwl-testmode.h diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 17d555f2215a..ad3bdba6beed 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -102,6 +102,16 @@ config IWLWIFI_DEVICE_TRACING occur. endmenu +config IWLWIFI_DEVICE_SVTOOL + bool "iwlwifi device svtool support" + depends on IWLAGN + select NL80211_TESTMODE + help + This option enables the svtool support for iwlwifi device through + NL80211_TESTMODE. svtool is a software validation tool that runs in + the user space and interacts with the device in the kernel space + through the generic netlink message via NL80211_TESTMODE channel. + config IWL_P2P bool "iwlwifi experimental P2P support" depends on IWLAGN diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 89a41d320c36..822660483f9f 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -16,6 +16,7 @@ iwlagn-objs += iwl-2000.o iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o +iwlagn-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-sv-open.o CFLAGS_iwl-devtrace.o := -I$(src) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index c3ae2e44fcc9..8bda0e8d6661 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -269,7 +269,7 @@ void iwlagn_rx_calib_result(struct iwl_priv *priv, iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); } -static int iwlagn_init_alive_start(struct iwl_priv *priv) +int iwlagn_init_alive_start(struct iwl_priv *priv) { int ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 003d5243542b..09fe841f0281 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -776,6 +776,8 @@ static void iwl_rx_handle(struct iwl_priv *priv) wake_up_all(&priv->_agn.notif_waitq); } + if (priv->pre_rx_handler) + priv->pre_rx_handler(priv, rxb); /* Based on type of command response or notification, * handle those that need handling via function in @@ -2211,7 +2213,7 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) * from protocol/runtime uCode (initialization uCode's * Alive gets handled by iwl_init_alive_start()). */ -static int iwl_alive_start(struct iwl_priv *priv) +int iwl_alive_start(struct iwl_priv *priv) { int ret = 0; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; @@ -3507,6 +3509,7 @@ struct ieee80211_ops iwlagn_hw_ops = { .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel, .offchannel_tx = iwl_mac_offchannel_tx, .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait, + CFG80211_TESTMODE_CMD(iwl_testmode_cmd) }; static u32 iwl_hw_detect(struct iwl_priv *priv) @@ -3816,6 +3819,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_setup_deferred_work(priv); iwl_setup_rx_handlers(priv); + iwl_testmode_init(priv); /********************************************* * 8. Enable interrupts and read RFKILL state diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index b477336ff53a..aa398b6dab1f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -344,5 +344,22 @@ iwlagn_wait_notification(struct iwl_priv *priv, void __releases(wait_entry) iwlagn_remove_notification(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry); +extern int iwlagn_init_alive_start(struct iwl_priv *priv); +extern int iwl_alive_start(struct iwl_priv *priv); +/* svtool */ +#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL +extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len); +extern void iwl_testmode_init(struct iwl_priv *priv); +#else +static inline +int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) +{ + return -ENOSYS; +} +static inline +void iwl_testmode_init(struct iwl_priv *priv) +{ +} +#endif #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f098eff263f8..3d28ad258077 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1194,6 +1194,8 @@ struct iwl_priv { enum ieee80211_band band; + void (*pre_rx_handler)(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c new file mode 100644 index 000000000000..89b6696622c1 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -0,0 +1,469 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-debug.h" +#include "iwl-fh.h" +#include "iwl-io.h" +#include "iwl-agn.h" +#include "iwl-testmode.h" + + +/* The TLVs used in the gnl message policy between the kernel module and + * user space application. iwl_testmode_gnl_msg_policy is to be carried + * through the NL80211_CMD_TESTMODE channel regulated by nl80211. + * See iwl-testmode.h + */ +static +struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { + [IWL_TM_ATTR_COMMAND] = { .type = NLA_U32, }, + + [IWL_TM_ATTR_UCODE_CMD_ID] = { .type = NLA_U8, }, + [IWL_TM_ATTR_UCODE_CMD_DATA] = { .type = NLA_UNSPEC, }, + + [IWL_TM_ATTR_REG_OFFSET] = { .type = NLA_U32, }, + [IWL_TM_ATTR_REG_VALUE8] = { .type = NLA_U8, }, + [IWL_TM_ATTR_REG_VALUE32] = { .type = NLA_U32, }, + + [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, }, + [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, }, +}; + +/* + * See the struct iwl_rx_packet in iwl-commands.h for the format of the + * received events from the device + */ +static inline int get_event_length(struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + if (pkt) + return le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; + else + return 0; +} + + +/* + * This function multicasts the spontaneous messages from the device to the + * user space. It is invoked whenever there is a received messages + * from the device. This function is called within the ISR of the rx handlers + * in iwlagn driver. + * + * The parsing of the message content is left to the user space application, + * The message content is treated as unattacked raw data and is encapsulated + * with IWL_TM_ATTR_UCODE_RX_PKT multicasting to the user space. + * + * @priv: the instance of iwlwifi device + * @rxb: pointer to rx data content received by the ISR + * + * See the message policies and TLVs in iwl_testmode_gnl_msg_policy[]. + * For the messages multicasting to the user application, the mandatory + * TLV fields are : + * IWL_TM_ATTR_COMMAND must be IWL_TM_CMD_DEV2APP_UCODE_RX_PKT + * IWL_TM_ATTR_UCODE_RX_PKT for carrying the message content + */ + +static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct ieee80211_hw *hw = priv->hw; + struct sk_buff *skb; + void *data; + int length; + + data = (void *)rxb_addr(rxb); + length = get_event_length(rxb); + + if (!data || length == 0) + return; + + skb = cfg80211_testmode_alloc_event_skb(hw->wiphy, 20 + length, + GFP_ATOMIC); + if (skb == NULL) { + IWL_DEBUG_INFO(priv, + "Run out of memory for messages to user space ?\n"); + return; + } + NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT); + NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data); + cfg80211_testmode_event(skb, GFP_ATOMIC); + return; + +nla_put_failure: + kfree_skb(skb); + IWL_DEBUG_INFO(priv, "Ouch, overran buffer, check allocation!\n"); +} + +void iwl_testmode_init(struct iwl_priv *priv) +{ + priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; +} + +/* + * This function handles the user application commands to the ucode. + * + * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_CMD_ID and + * IWL_TM_ATTR_UCODE_CMD_DATA and calls to the handler to send the + * host command to the ucode. + * + * If any mandatory field is missing, -ENOMSG is replied to the user space + * application; otherwise, the actual execution result of the host command to + * ucode is replied. + * + * @hw: ieee80211_hw object that represents the device + * @tb: gnl message fields from the user space + */ +static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_host_cmd cmd; + + memset(&cmd, 0, sizeof(struct iwl_host_cmd)); + + if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] || + !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) { + IWL_DEBUG_INFO(priv, + "Error finding ucode command mandatory fields\n"); + return -ENOMSG; + } + + cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); + cmd.data = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); + cmd.len = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); + IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," + " len %d\n", cmd.id, cmd.flags, cmd.len); + /* ok, let's submit the command to ucode */ + return iwl_send_cmd(priv, &cmd); +} + + +/* + * This function handles the user application commands for register access. + * + * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the + * handlers respectively. + * + * If it's an unknown commdn ID, -ENOSYS is returned; or -ENOMSG if the + * mandatory fields(IWL_TM_ATTR_REG_OFFSET,IWL_TM_ATTR_REG_VALUE32, + * IWL_TM_ATTR_REG_VALUE8) are missing; Otherwise 0 is replied indicating + * the success of the command execution. + * + * If IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_READ32, the register read + * value is returned with IWL_TM_ATTR_REG_VALUE32. + * + * @hw: ieee80211_hw object that represents the device + * @tb: gnl message fields from the user space + */ +static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct iwl_priv *priv = hw->priv; + u32 ofs, val32; + u8 val8; + struct sk_buff *skb; + int status = 0; + + if (!tb[IWL_TM_ATTR_REG_OFFSET]) { + IWL_DEBUG_INFO(priv, "Error finding register offset\n"); + return -ENOMSG; + } + ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]); + IWL_INFO(priv, "testmode register access command offset 0x%x\n", ofs); + + switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { + case IWL_TM_CMD_APP2DEV_REG_READ32: + val32 = iwl_read32(priv, ofs); + IWL_INFO(priv, "32bit value to read 0x%x\n", val32); + + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); + if (!skb) { + IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + return -ENOMEM; + } + NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32); + status = cfg80211_testmode_reply(skb); + if (status < 0) + IWL_DEBUG_INFO(priv, + "Error sending msg : %d\n", status); + break; + case IWL_TM_CMD_APP2DEV_REG_WRITE32: + if (!tb[IWL_TM_ATTR_REG_VALUE32]) { + IWL_DEBUG_INFO(priv, + "Error finding value to write\n"); + return -ENOMSG; + } else { + val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); + IWL_INFO(priv, "32bit value to write 0x%x\n", val32); + iwl_write32(priv, ofs, val32); + } + break; + case IWL_TM_CMD_APP2DEV_REG_WRITE8: + if (!tb[IWL_TM_ATTR_REG_VALUE8]) { + IWL_DEBUG_INFO(priv, "Error finding value to write\n"); + return -ENOMSG; + } else { + val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); + IWL_INFO(priv, "8bit value to write 0x%x\n", val8); + iwl_write8(priv, ofs, val8); + } + break; + default: + IWL_DEBUG_INFO(priv, "Unknown testmode register command ID\n"); + return -ENOSYS; + } + + return status; + +nla_put_failure: + kfree_skb(skb); + return -EMSGSIZE; +} + + +static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) +{ + struct iwl_notification_wait calib_wait; + int ret; + + iwlagn_init_notification_wait(priv, &calib_wait, + CALIBRATION_COMPLETE_NOTIFICATION, + NULL, NULL); + ret = iwlagn_init_alive_start(priv); + if (ret) { + IWL_DEBUG_INFO(priv, + "Error configuring init calibration: %d\n", ret); + goto cfg_init_calib_error; + } + + ret = iwlagn_wait_notification(priv, &calib_wait, 2 * HZ); + if (ret) + IWL_DEBUG_INFO(priv, "Error detecting" + " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); + return ret; + +cfg_init_calib_error: + iwlagn_remove_notification(priv, &calib_wait); + return ret; +} + +/* + * This function handles the user application commands for driver. + * + * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the + * handlers respectively. + * + * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned + * value of the actual command execution is replied to the user application. + * + * If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP + * is used for carry the message while IWL_TM_ATTR_COMMAND must set to + * IWL_TM_CMD_DEV2APP_SYNC_RSP. + * + * @hw: ieee80211_hw object that represents the device + * @tb: gnl message fields from the user space + */ +static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct iwl_priv *priv = hw->priv; + struct sk_buff *skb; + unsigned char *rsp_data_ptr = NULL; + int status = 0, rsp_data_len = 0; + + switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { + case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: + rsp_data_ptr = (unsigned char *)priv->cfg->name; + rsp_data_len = strlen(priv->cfg->name); + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, + rsp_data_len + 20); + if (!skb) { + IWL_DEBUG_INFO(priv, + "Error allocating memory\n"); + return -ENOMEM; + } + NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, + IWL_TM_CMD_DEV2APP_SYNC_RSP); + NLA_PUT(skb, IWL_TM_ATTR_SYNC_RSP, + rsp_data_len, rsp_data_ptr); + status = cfg80211_testmode_reply(skb); + if (status < 0) + IWL_DEBUG_INFO(priv, "Error sending msg : %d\n", + status); + break; + + case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: + status = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init, + UCODE_SUBTYPE_INIT, -1); + if (status) + IWL_DEBUG_INFO(priv, + "Error loading init ucode: %d\n", status); + break; + + case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: + iwl_testmode_cfg_init_calib(priv); + iwlagn_stop_device(priv); + break; + + case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: + status = iwlagn_load_ucode_wait_alive(priv, + &priv->ucode_rt, + UCODE_SUBTYPE_REGULAR, + UCODE_SUBTYPE_REGULAR_NEW); + if (status) { + IWL_DEBUG_INFO(priv, + "Error loading runtime ucode: %d\n", status); + break; + } + status = iwl_alive_start(priv); + if (status) + IWL_DEBUG_INFO(priv, + "Error starting the device: %d\n", status); + break; + + default: + IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); + return -ENOSYS; + } + return status; + +nla_put_failure: + kfree_skb(skb); + return -EMSGSIZE; +} + +/* The testmode gnl message handler that takes the gnl message from the + * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then + * invoke the corresponding handlers. + * + * This function is invoked when there is user space application sending + * gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated + * by nl80211. + * + * It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before + * dispatching it to the corresponding handler. + * + * If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application; + * -ENOSYS is replied to the user application if the command is unknown; + * Otherwise, the command is dispatched to the respective handler. + * + * @hw: ieee80211_hw object that represents the device + * @data: pointer to user space message + * @len: length in byte of @data + */ +int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) +{ + struct nlattr *tb[IWL_TM_ATTR_MAX - 1]; + struct iwl_priv *priv = hw->priv; + int result; + + result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, + iwl_testmode_gnl_msg_policy); + if (result != 0) { + IWL_DEBUG_INFO(priv, + "Error parsing the gnl message : %d\n", result); + return result; + } + + /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ + if (!tb[IWL_TM_ATTR_COMMAND]) { + IWL_DEBUG_INFO(priv, "Error finding testmode command type\n"); + return -ENOMSG; + } + /* in case multiple accesses to the device happens */ + mutex_lock(&priv->mutex); + + switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { + case IWL_TM_CMD_APP2DEV_UCODE: + IWL_DEBUG_INFO(priv, "testmode cmd to uCode\n"); + result = iwl_testmode_ucode(hw, tb); + break; + case IWL_TM_CMD_APP2DEV_REG_READ32: + case IWL_TM_CMD_APP2DEV_REG_WRITE32: + case IWL_TM_CMD_APP2DEV_REG_WRITE8: + IWL_DEBUG_INFO(priv, "testmode cmd to register\n"); + result = iwl_testmode_reg(hw, tb); + break; + case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: + case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: + case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: + case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: + IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); + result = iwl_testmode_driver(hw, tb); + break; + default: + IWL_DEBUG_INFO(priv, "Unknown testmode command\n"); + result = -ENOSYS; + break; + } + + mutex_unlock(&priv->mutex); + return result; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h new file mode 100644 index 000000000000..31f8949f2801 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -0,0 +1,151 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef __IWL_TESTMODE_H__ +#define __IWL_TESTMODE_H__ + +#include + + +/* Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and + * from and kernel space to user space(IWL_TM_CMD_ID_DEV2APP_XX). + * The command ID is carried with IWL_TM_ATTR_COMMAND. There are three types of + * of command from user space and two types of command from kernel space. + * See below. + */ +enum iwl_tm_cmd_t { + /* commands from user application to the uCode, + * the actual uCode host command ID is carried with + * IWL_TM_ATTR_UCODE_CMD_ID */ + IWL_TM_CMD_APP2DEV_UCODE = 1, + + /* commands from user applicaiton to access register */ + IWL_TM_CMD_APP2DEV_REG_READ32, + IWL_TM_CMD_APP2DEV_REG_WRITE32, + IWL_TM_CMD_APP2DEV_REG_WRITE8, + + /* commands fom user space for pure driver level operations */ + IWL_TM_CMD_APP2DEV_GET_DEVICENAME, + IWL_TM_CMD_APP2DEV_LOAD_INIT_FW, + IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB, + IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW, + /* if there is other new command for the driver layer operation, + * append them here */ + + + /* commands from kernel space to carry the synchronous response + * to user application */ + IWL_TM_CMD_DEV2APP_SYNC_RSP, + + /* commands from kernel space to multicast the spontaneous messages + * to user application */ + IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, + IWL_TM_CMD_MAX, +}; + +enum iwl_tm_attr_t { + IWL_TM_ATTR_NOT_APPLICABLE = 0, + + /* From user space to kernel space: + * the command either destines to ucode, driver, or register; + * See enum iwl_tm_cmd_t. + * + * From kernel space to user space: + * the command either carries synchronous response, + * or the spontaneous message multicast from the device; + * See enum iwl_tm_cmd_t. */ + IWL_TM_ATTR_COMMAND, + + /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE, + * The mandatory fields are : + * IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID; + * IWL_TM_ATTR_COMMAND_FLAG for the flags of the commands; + * The optional fields are: + * IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload + * to the ucode */ + IWL_TM_ATTR_UCODE_CMD_ID, + IWL_TM_ATTR_UCODE_CMD_DATA, + + /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX, + * The mandatory fields are: + * IWL_TM_ATTR_REG_OFFSET for the offset of the target register; + * IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value */ + IWL_TM_ATTR_REG_OFFSET, + IWL_TM_ATTR_REG_VALUE8, + IWL_TM_ATTR_REG_VALUE32, + + /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP, + * The mandatory fields are: + * IWL_TM_ATTR_SYNC_RSP for the data content responding to the user + * application command */ + IWL_TM_ATTR_SYNC_RSP, + /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, + * The mandatory fields are: + * IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user + * application */ + IWL_TM_ATTR_UCODE_RX_PKT, + + IWL_TM_ATTR_MAX, +}; + + +#endif -- cgit v1.2.3-58-ga151 From 46975f78fe1f480682e51c9acb03a5089b784cb6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 28 Apr 2011 07:27:05 -0700 Subject: iwlagn: remove get_hcmd_size indirection There's no need for this, all commands are the right size. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 7 ------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - drivers/net/wireless/iwlwifi/iwl-tx.c | 1 - 3 files changed, 9 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 49dd03f9feda..b12c72d63ccb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -54,12 +54,6 @@ int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) } } -/* Currently this is the superset of everything */ -static u16 iwlagn_get_hcmd_size(u8 cmd_id, u16 len) -{ - return len; -} - static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) { u16 size = (u16)sizeof(struct iwl_addsta_cmd); @@ -332,7 +326,6 @@ struct iwl_hcmd_ops iwlagn_bt_hcmd = { }; struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { - .get_hcmd_size = iwlagn_get_hcmd_size, .build_addsta_hcmd = iwlagn_build_addsta_hcmd, .gain_computation = iwlagn_gain_computation, .chain_noise_reset = iwlagn_chain_noise_reset, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index dec9820753f8..9d7e36d0fb2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -99,7 +99,6 @@ struct iwl_hcmd_ops { }; struct iwl_hcmd_utils_ops { - u16 (*get_hcmd_size)(u8 cmd_id, u16 len); u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data); void (*gain_computation)(struct iwl_priv *priv, u32 *average_noise, diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 52b1b66f32d0..608d7a12c438 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -447,7 +447,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) u16 fix_size; bool is_ct_kill = false; - cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); /* -- cgit v1.2.3-58-ga151 From 8a98d49ec1f38d9f3eef7e34f148c3f1f5590fdf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 29 Apr 2011 09:48:14 -0700 Subject: iwlagn: remove frame pre-allocation The frame pre-allocation is quite a bit of complex code, all to avoid a single allocation. Remove it and consolidate the beacon sending code. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 137 ++++++--------------------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 13 ---- 2 files changed, 25 insertions(+), 125 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 09fe841f0281..3ecc3198d9bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -102,70 +102,6 @@ void iwl_update_chain_flags(struct iwl_priv *priv) } } -static void iwl_clear_free_frames(struct iwl_priv *priv) -{ - struct list_head *element; - - IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n", - priv->frames_count); - - while (!list_empty(&priv->free_frames)) { - element = priv->free_frames.next; - list_del(element); - kfree(list_entry(element, struct iwl_frame, list)); - priv->frames_count--; - } - - if (priv->frames_count) { - IWL_WARN(priv, "%d frames still in use. Did we lose one?\n", - priv->frames_count); - priv->frames_count = 0; - } -} - -static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv) -{ - struct iwl_frame *frame; - struct list_head *element; - if (list_empty(&priv->free_frames)) { - frame = kzalloc(sizeof(*frame), GFP_KERNEL); - if (!frame) { - IWL_ERR(priv, "Could not allocate frame!\n"); - return NULL; - } - - priv->frames_count++; - return frame; - } - - element = priv->free_frames.next; - list_del(element); - return list_entry(element, struct iwl_frame, list); -} - -static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame) -{ - memset(frame, 0, sizeof(*frame)); - list_add(&frame->list, &priv->free_frames); -} - -static u32 iwl_fill_beacon_frame(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, - int left) -{ - lockdep_assert_held(&priv->mutex); - - if (!priv->beacon_skb) - return 0; - - if (priv->beacon_skb->len > left) - return 0; - - memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len); - - return priv->beacon_skb->len; -} - /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */ static void iwl_set_beacon_tim(struct iwl_priv *priv, struct iwl_tx_beacon_cmd *tx_beacon_cmd, @@ -193,13 +129,18 @@ static void iwl_set_beacon_tim(struct iwl_priv *priv, IWL_WARN(priv, "Unable to find TIM Element in beacon\n"); } -static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, - struct iwl_frame *frame) +int iwlagn_send_beacon_cmd(struct iwl_priv *priv) { struct iwl_tx_beacon_cmd *tx_beacon_cmd; + struct iwl_host_cmd cmd = { + .id = REPLY_TX_BEACON, + .flags = CMD_SIZE_HUGE, + }; u32 frame_size; u32 rate_flags; u32 rate; + int err; + /* * We have to set up the TX command, the TX Beacon command, and the * beacon contents. @@ -212,17 +153,19 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, return 0; } - /* Initialize memory */ - tx_beacon_cmd = &frame->u.beacon; - memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); + if (WARN_ON(!priv->beacon_skb)) + return -EINVAL; + + /* Allocate beacon memory */ + tx_beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd) + priv->beacon_skb->len, + GFP_KERNEL); + if (!tx_beacon_cmd) + return -ENOMEM; + + frame_size = priv->beacon_skb->len; /* Set up TX beacon contents */ - frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, - sizeof(frame->u) - sizeof(*tx_beacon_cmd)); - if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE)) - return 0; - if (!frame_size) - return 0; + memcpy(tx_beacon_cmd->frame, priv->beacon_skb->data, frame_size); /* Set up TX command fields */ tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); @@ -245,41 +188,16 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); - return sizeof(*tx_beacon_cmd) + frame_size; -} + /* Submit command */ + cmd.len = sizeof(*tx_beacon_cmd) + frame_size; + cmd.data = tx_beacon_cmd; -int iwlagn_send_beacon_cmd(struct iwl_priv *priv) -{ - struct iwl_frame *frame; - unsigned int frame_size; - int rc; - struct iwl_host_cmd cmd = { - .id = REPLY_TX_BEACON, - .flags = CMD_SIZE_HUGE, - }; - - frame = iwl_get_free_frame(priv); - if (!frame) { - IWL_ERR(priv, "Could not obtain free frame buffer for beacon " - "command.\n"); - return -ENOMEM; - } - - frame_size = iwl_hw_get_beacon_cmd(priv, frame); - if (!frame_size) { - IWL_ERR(priv, "Error configuring the beacon command\n"); - iwl_free_frame(priv, frame); - return -EINVAL; - } - - cmd.len = frame_size; - cmd.data = &frame->u.cmd[0]; - - rc = iwl_send_cmd_sync(priv, &cmd); + err = iwl_send_cmd_sync(priv, &cmd); - iwl_free_frame(priv, frame); + /* Free temporary storage */ + kfree(tx_beacon_cmd); - return rc; + return err; } static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) @@ -2356,9 +2274,6 @@ static void __iwl_down(struct iwl_priv *priv) dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = NULL; - - /* clear out any free frames */ - iwl_clear_free_frames(priv); } static void iwl_down(struct iwl_priv *priv) @@ -3416,8 +3331,6 @@ static int iwl_init_drv(struct iwl_priv *priv) spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); - INIT_LIST_HEAD(&priv->free_frames); - mutex_init(&priv->mutex); priv->ieee_channels = NULL; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 3d28ad258077..2fd752a9aac8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -238,15 +238,6 @@ struct iwl_channel_info { #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) #define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) -struct iwl_frame { - union { - struct ieee80211_hdr frame; - struct iwl_tx_beacon_cmd beacon; - u8 raw[IEEE80211_FRAME_LEN]; - u8 cmd[360]; - } u; - struct list_head list; -}; #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) @@ -1188,10 +1179,6 @@ struct iwl_priv { struct ieee80211_rate *ieee_rates; struct iwl_cfg *cfg; - /* temporary frame storage list */ - struct list_head free_frames; - int frames_count; - enum ieee80211_band band; void (*pre_rx_handler)(struct iwl_priv *priv, -- cgit v1.2.3-58-ga151 From 4c2cde3b59d923d2952ef0accdde892e23b4997b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 28 Apr 2011 07:27:07 -0700 Subject: iwlagn: remove unused variable The variable 'len' here is set but never used. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-tx.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 608d7a12c438..517d1049d7d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -442,7 +442,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) struct iwl_cmd_meta *out_meta; dma_addr_t phys_addr; unsigned long flags; - int len; u32 idx; u16 fix_size; bool is_ct_kill = false; @@ -518,9 +517,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) INDEX_TO_SEQ(q->write_ptr)); if (cmd->flags & CMD_SIZE_HUGE) out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; - len = sizeof(struct iwl_device_cmd); - if (idx == TFD_CMD_SLOTS) - len = IWL_MAX_CMD_SIZE; #ifdef CONFIG_IWLWIFI_DEBUG switch (out_cmd->hdr.cmd) { -- cgit v1.2.3-58-ga151 From ccb6c1c0ec2b76a41c8c85747b1a671e71b97e64 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 28 Apr 2011 07:27:08 -0700 Subject: iwlagn: dont update bytecount table for command queue The device doesn't use the bytecount table for the command queue, only for aggregation queues to make aggregation decisions. So don't update it for the command queue (and we even updated it with wrong values). Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 28 +++++++++++++--------------- drivers/net/wireless/iwlwifi/iwl-tx.c | 4 ---- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 494de0e59cb4..5445fd6a5a91 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -112,21 +112,19 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); - if (txq_id != priv->cmd_queue) { - sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; - sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; - - switch (sec_ctl & TX_CMD_SEC_MSK) { - case TX_CMD_SEC_CCM: - len += CCMP_MIC_LEN; - break; - case TX_CMD_SEC_TKIP: - len += TKIP_ICV_LEN; - break; - case TX_CMD_SEC_WEP: - len += WEP_IV_LEN + WEP_ICV_LEN; - break; - } + sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; + sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; + + switch (sec_ctl & TX_CMD_SEC_MSK) { + case TX_CMD_SEC_CCM: + len += CCMP_MIC_LEN; + break; + case TX_CMD_SEC_TKIP: + len += TKIP_ICV_LEN; + break; + case TX_CMD_SEC_WEP: + len += WEP_IV_LEN + WEP_ICV_LEN; + break; } bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 517d1049d7d9..5a7cd177fe5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -540,10 +540,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) #endif txq->need_update = 1; - if (priv->cfg->ops->lib->txq_update_byte_cnt_tbl) - /* Set up entry in queue's byte count circular buffer */ - priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0); - phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, fix_size, PCI_DMA_BIDIRECTIONAL); dma_unmap_addr_set(out_meta, mapping, phys_addr); -- cgit v1.2.3-58-ga151 From 94b00658ffc719427c9c09d7920957bc35915c6f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 28 Apr 2011 07:27:09 -0700 Subject: iwlagn: remove bytecount indirection All AGN devices need the bytecount table, so remove the indirection and make the functions static again. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-2000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-6000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 17 ++++++++--------- drivers/net/wireless/iwlwifi/iwl-agn.h | 5 ----- drivers/net/wireless/iwlwifi/iwl-core.h | 5 ----- 7 files changed, 8 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 3da8cf27dcb9..b4c81931e136 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -171,8 +171,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) static struct iwl_lib_ops iwl1000_lib = { .set_hw_params = iwl1000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index bca462c47e37..89b8da7a6c8b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -252,8 +252,6 @@ static int iwl2030_hw_channel_switch(struct iwl_priv *priv, static struct iwl_lib_ops iwl2000_lib = { .set_hw_params = iwl2000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 561f2cd65dd4..98f81df166e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -339,8 +339,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, static struct iwl_lib_ops iwl5000_lib = { .set_hw_params = iwl5000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, @@ -376,8 +374,6 @@ static struct iwl_lib_ops iwl5000_lib = { static struct iwl_lib_ops iwl5150_lib = { .set_hw_params = iwl5150_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 6045457cc722..a7921f9a03c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -278,8 +278,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, static struct iwl_lib_ops iwl6000_lib = { .set_hw_params = iwl6000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, @@ -316,8 +314,6 @@ static struct iwl_lib_ops iwl6000_lib = { static struct iwl_lib_ops iwl6030_lib = { .set_hw_params = iwl6000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 5445fd6a5a91..26601b7048f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -98,9 +98,9 @@ static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid) /** * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array */ -void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - u16 byte_cnt) +static void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + u16 byte_cnt) { struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; int write_ptr = txq->q.write_ptr; @@ -136,8 +136,8 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; } -void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq) +static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq) { struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; int txq_id = txq->q.id; @@ -766,8 +766,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Set up entry for this TFD in Tx byte-count array */ if (info->flags & IEEE80211_TX_CTL_AMPDU) - priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, - le16_to_cpu(tx_cmd->len)); + iwlagn_txq_update_byte_cnt_tbl(priv, txq, + le16_to_cpu(tx_cmd->len)); pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, firstlen, PCI_DMA_BIDIRECTIONAL); @@ -1246,8 +1246,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); tx_info->skb = NULL; - if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) - priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); + iwlagn_txq_inval_byte_cnt_tbl(priv, txq); priv->cfg->ops->lib->txq_free_tfd(priv, txq); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index aa398b6dab1f..fe33fe8aa418 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -139,11 +139,6 @@ void iwlagn_set_wr_ptrs(struct iwl_priv *priv, void iwlagn_tx_queue_set_status(struct iwl_priv *priv, struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry); -void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - u16 byte_cnt); -void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq); void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); void iwl_free_tfds_in_queue(struct iwl_priv *priv, int sta_id, int tid, int freed); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 9d7e36d0fb2a..5b5b0cce4a54 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -128,11 +128,6 @@ struct iwl_lib_ops { /* set hw dependent parameters */ int (*set_hw_params)(struct iwl_priv *priv); /* Handling TX */ - void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - u16 byte_cnt); - void (*txq_inval_byte_cnt_tbl)(struct iwl_priv *priv, - struct iwl_tx_queue *txq); void (*txq_set_sched)(struct iwl_priv *priv, u32 mask); int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv, struct iwl_tx_queue *txq, -- cgit v1.2.3-58-ga151 From 2c46f72e069eef5e98f2b04df08cde6bdc673aa7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 28 Apr 2011 07:27:10 -0700 Subject: iwlagn: check DMA mapping errors DMA mappings can fail, but the current code doesn't check for that. Add checking, which requires some restructuring for proper error paths. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 60 ++++++++++++++++++------------- drivers/net/wireless/iwlwifi/iwl-tx.c | 13 +++++-- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 26601b7048f2..7c1becf9e2c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -537,7 +537,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct iwl_tx_cmd *tx_cmd; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; int txq_id; - dma_addr_t phys_addr; + dma_addr_t phys_addr = 0; dma_addr_t txcmd_phys; dma_addr_t scratch_phys; u16 len, firstlen, secondlen; @@ -564,7 +564,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_lock_irqsave(&priv->lock, flags); if (iwl_is_rfkill(priv)) { IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); - goto drop_unlock; + goto drop_unlock_priv; } fc = hdr->frame_control; @@ -585,7 +585,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); - goto drop_unlock; + goto drop_unlock_priv; } IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); @@ -628,10 +628,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (ieee80211_is_data_qos(fc)) { qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) { - spin_unlock(&priv->sta_lock); - goto drop_unlock; - } + + if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) + goto drop_unlock_sta; + seq_number = priv->stations[sta_id].tid[tid].seq_number; seq_number &= IEEE80211_SCTL_SEQ; hdr->seq_ctrl = hdr->seq_ctrl & @@ -649,18 +649,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) txq = &priv->txq[txq_id]; q = &txq->q; - if (unlikely(iwl_queue_space(q) < q->high_mark)) { - spin_unlock(&priv->sta_lock); - goto drop_unlock; - } - - if (ieee80211_is_data_qos(fc)) { - priv->stations[sta_id].tid[tid].tfds_in_queue++; - if (!ieee80211_has_morefrags(fc)) - priv->stations[sta_id].tid[tid].seq_number = seq_number; - } - - spin_unlock(&priv->sta_lock); + if (unlikely(iwl_queue_space(q) < q->high_mark)) + goto drop_unlock_sta; /* Set up driver data for this TFD */ memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); @@ -724,12 +714,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr, firstlen, PCI_DMA_BIDIRECTIONAL); + if (unlikely(pci_dma_mapping_error(priv->pci_dev, txcmd_phys))) + goto drop_unlock_sta; dma_unmap_addr_set(out_meta, mapping, txcmd_phys); dma_unmap_len_set(out_meta, len, firstlen); - /* Add buffer containing Tx command and MAC(!) header to TFD's - * first entry */ - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - txcmd_phys, firstlen, 1, 0); if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; @@ -744,10 +732,30 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (secondlen > 0) { phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, secondlen, PCI_DMA_TODEVICE); + if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) { + pci_unmap_single(priv->pci_dev, + dma_unmap_addr(out_meta, mapping), + dma_unmap_len(out_meta, len), + PCI_DMA_BIDIRECTIONAL); + goto drop_unlock_sta; + } + } + + if (ieee80211_is_data_qos(fc)) { + priv->stations[sta_id].tid[tid].tfds_in_queue++; + if (!ieee80211_has_morefrags(fc)) + priv->stations[sta_id].tid[tid].seq_number = seq_number; + } + + spin_unlock(&priv->sta_lock); + + /* Attach buffers to TFD */ + priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, + txcmd_phys, firstlen, 1, 0); + if (secondlen > 0) priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, phys_addr, secondlen, 0, 0); - } scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + offsetof(struct iwl_tx_cmd, scratch); @@ -813,7 +821,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) return 0; -drop_unlock: +drop_unlock_sta: + spin_unlock(&priv->sta_lock); +drop_unlock_priv: spin_unlock_irqrestore(&priv->lock, flags); return -1; } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 5a7cd177fe5e..e69597ea43e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -500,7 +500,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) } memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ - out_meta->flags = cmd->flags | CMD_MAPPED; if (cmd->flags & CMD_WANT_SKB) out_meta->source = cmd; if (cmd->flags & CMD_ASYNC) @@ -538,13 +537,20 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) q->write_ptr, idx, priv->cmd_queue); } #endif - txq->need_update = 1; - phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, fix_size, PCI_DMA_BIDIRECTIONAL); + if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) { + idx = -ENOMEM; + goto out; + } + dma_unmap_addr_set(out_meta, mapping, phys_addr); dma_unmap_len_set(out_meta, len, fix_size); + out_meta->flags = cmd->flags | CMD_MAPPED; + + txq->need_update = 1; + trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, @@ -555,6 +561,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); iwl_txq_update_write_ptr(priv, txq); + out: spin_unlock_irqrestore(&priv->hcmd_lock, flags); return idx; } -- cgit v1.2.3-58-ga151 From ad638bd16d91012a512979327b5c17c867d260c6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 11:58:55 -0700 Subject: hamachi: Delete TX checksumming code commented out since 1999 TX checksumming support has been ifdef commented out of this driver for more than 10 years, and it makes references to aspects of the IPv4 stack from back then as well. If someone has one of these rare cards and wants to properly resurrect TX checksumming support, they can still get at this code in the version control history. Signed-off-by: David S. Miller --- drivers/net/hamachi.c | 79 --------------------------------------------------- 1 file changed, 79 deletions(-) diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 80d25ed53344..f5fba73c8738 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -132,14 +132,8 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; /* * RX_CHECKSUM turns on card-generated receive checksum generation for * TCP and UDP packets. Otherwise the upper layers do the calculation. - * TX_CHECKSUM won't do anything too useful, even if it works. There's no - * easy mechanism by which to tell the TCP/UDP stack that it need not - * generate checksums for this device. But if somebody can find a way - * to get that to work, most of the card work is in here already. * 3/10/1999 Pete Wyckoff */ -#undef TX_CHECKSUM -#define RX_CHECKSUM /* Operational parameters that usually are not changed. */ /* Time in jiffies before concluding the transmitter is hung. */ @@ -630,11 +624,6 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev, SET_NETDEV_DEV(dev, &pdev->dev); -#ifdef TX_CHECKSUM - printk("check that skbcopy in ip_queue_xmit isn't happening\n"); - dev->hard_header_len += 8; /* for cksum tag */ -#endif - for (i = 0; i < 6; i++) dev->dev_addr[i] = 1 ? read_eeprom(ioaddr, 4 + i) : readb(ioaddr + StationAddr + i); @@ -937,11 +926,7 @@ static int hamachi_open(struct net_device *dev) /* always 1, takes no more time to do it */ writew(0x0001, ioaddr + RxChecksum); -#ifdef TX_CHECKSUM - writew(0x0001, ioaddr + TxChecksum); -#else writew(0x0000, ioaddr + TxChecksum); -#endif writew(0x8000, ioaddr + MACCnfg); /* Soft reset the MAC */ writew(0x215F, ioaddr + MACCnfg); writew(0x000C, ioaddr + FrameGap0); @@ -1226,40 +1211,6 @@ static void hamachi_init_ring(struct net_device *dev) } -#ifdef TX_CHECKSUM -#define csum_add(it, val) \ -do { \ - it += (u16) (val); \ - if (it & 0xffff0000) { \ - it &= 0xffff; \ - ++it; \ - } \ -} while (0) - /* printk("add %04x --> %04x\n", val, it); \ */ - -/* uh->len already network format, do not swap */ -#define pseudo_csum_udp(sum,ih,uh) do { \ - sum = 0; \ - csum_add(sum, (ih)->saddr >> 16); \ - csum_add(sum, (ih)->saddr & 0xffff); \ - csum_add(sum, (ih)->daddr >> 16); \ - csum_add(sum, (ih)->daddr & 0xffff); \ - csum_add(sum, cpu_to_be16(IPPROTO_UDP)); \ - csum_add(sum, (uh)->len); \ -} while (0) - -/* swap len */ -#define pseudo_csum_tcp(sum,ih,len) do { \ - sum = 0; \ - csum_add(sum, (ih)->saddr >> 16); \ - csum_add(sum, (ih)->saddr & 0xffff); \ - csum_add(sum, (ih)->daddr >> 16); \ - csum_add(sum, (ih)->daddr & 0xffff); \ - csum_add(sum, cpu_to_be16(IPPROTO_TCP)); \ - csum_add(sum, htons(len)); \ -} while (0) -#endif - static netdev_tx_t hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -1292,36 +1243,6 @@ static netdev_tx_t hamachi_start_xmit(struct sk_buff *skb, hmp->tx_skbuff[entry] = skb; -#ifdef TX_CHECKSUM - { - /* tack on checksum tag */ - u32 tagval = 0; - struct ethhdr *eh = (struct ethhdr *)skb->data; - if (eh->h_proto == cpu_to_be16(ETH_P_IP)) { - struct iphdr *ih = (struct iphdr *)((char *)eh + ETH_HLEN); - if (ih->protocol == IPPROTO_UDP) { - struct udphdr *uh - = (struct udphdr *)((char *)ih + ih->ihl*4); - u32 offset = ((unsigned char *)uh + 6) - skb->data; - u32 pseudo; - pseudo_csum_udp(pseudo, ih, uh); - pseudo = htons(pseudo); - printk("udp cksum was %04x, sending pseudo %04x\n", - uh->check, pseudo); - uh->check = 0; /* zero out uh->check before card calc */ - /* - * start at 14 (skip ethhdr), store at offset (uh->check), - * use pseudo value given. - */ - tagval = (14 << 24) | (offset << 16) | pseudo; - } else if (ih->protocol == IPPROTO_TCP) { - printk("tcp, no auto cksum\n"); - } - } - *(u32 *)skb_push(skb, 8) = tagval; - } -#endif - hmp->tx_ring[entry].addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE)); -- cgit v1.2.3-58-ga151 From bdc712b4c2baf9515887de3a52e7ecd89fafc0c7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 15:02:07 -0700 Subject: inet: Decrease overhead of on-stack inet_cork. When we fast path datagram sends to avoid locking by putting the inet_cork on the stack we use up lots of space that isn't necessary. This is because inet_cork contains a "struct flowi" which isn't used in these code paths. Split inet_cork to two parts, "inet_cork" and "inet_cork_full". Only the latter of which has the "struct flowi" and is what is stored in inet_sock. Signed-off-by: David S. Miller Acked-by: Eric Dumazet --- include/net/inet_sock.h | 12 ++++++++---- include/net/ip.h | 2 +- net/ipv4/ip_output.c | 22 ++++++++++++---------- net/ipv6/ip6_output.c | 34 ++++++++++++++++++---------------- net/ipv6/raw.c | 4 ++-- 5 files changed, 41 insertions(+), 33 deletions(-) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index ed2ba6eca724..caaff5f5f39f 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -96,17 +96,21 @@ static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk) struct inet_cork { unsigned int flags; - unsigned int fragsize; + __be32 addr; struct ip_options *opt; + unsigned int fragsize; struct dst_entry *dst; int length; /* Total length of all frames */ - __be32 addr; - struct flowi fl; struct page *page; u32 off; u8 tx_flags; }; +struct inet_cork_full { + struct inet_cork base; + struct flowi fl; +}; + struct ip_mc_socklist; struct ipv6_pinfo; struct rtable; @@ -164,7 +168,7 @@ struct inet_sock { int mc_index; __be32 mc_addr; struct ip_mc_socklist __rcu *mc_list; - struct inet_cork cork; + struct inet_cork_full cork; }; #define IPCORK_OPT 1 /* ip-options has been held in ipcork.opt */ diff --git a/include/net/ip.h b/include/net/ip.h index 3a59bf99aa3a..095e392d5f16 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -132,7 +132,7 @@ extern struct sk_buff *ip_make_skb(struct sock *sk, static inline struct sk_buff *ip_finish_skb(struct sock *sk) { - return __ip_make_skb(sk, &sk->sk_write_queue, &inet_sk(sk)->cork); + return __ip_make_skb(sk, &sk->sk_write_queue, &inet_sk(sk)->cork.base); } /* datagram.c */ diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index db38c1822de8..eb0647a2f073 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1096,14 +1096,14 @@ int ip_append_data(struct sock *sk, return 0; if (skb_queue_empty(&sk->sk_write_queue)) { - err = ip_setup_cork(sk, &inet->cork, ipc, rtp); + err = ip_setup_cork(sk, &inet->cork.base, ipc, rtp); if (err) return err; } else { transhdrlen = 0; } - return __ip_append_data(sk, &sk->sk_write_queue, &inet->cork, getfrag, + return __ip_append_data(sk, &sk->sk_write_queue, &inet->cork.base, getfrag, from, length, transhdrlen, flags); } @@ -1114,6 +1114,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, struct sk_buff *skb; struct rtable *rt; struct ip_options *opt = NULL; + struct inet_cork *cork; int hh_len; int mtu; int len; @@ -1129,20 +1130,21 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, if (skb_queue_empty(&sk->sk_write_queue)) return -EINVAL; - rt = (struct rtable *)inet->cork.dst; - if (inet->cork.flags & IPCORK_OPT) - opt = inet->cork.opt; + cork = &inet->cork.base; + rt = (struct rtable *)cork->dst; + if (cork->flags & IPCORK_OPT) + opt = cork->opt; if (!(rt->dst.dev->features&NETIF_F_SG)) return -EOPNOTSUPP; hh_len = LL_RESERVED_SPACE(rt->dst.dev); - mtu = inet->cork.fragsize; + mtu = cork->fragsize; fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; - if (inet->cork.length + size > 0xFFFF - fragheaderlen) { + if (cork->length + size > 0xFFFF - fragheaderlen) { ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport, mtu); return -EMSGSIZE; } @@ -1150,7 +1152,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) return -EINVAL; - inet->cork.length += size; + cork->length += size; if ((size + skb->len > mtu) && (sk->sk_protocol == IPPROTO_UDP) && (rt->dst.dev->features & NETIF_F_UFO)) { @@ -1245,7 +1247,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, return 0; error: - inet->cork.length -= size; + cork->length -= size; IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS); return err; } @@ -1396,7 +1398,7 @@ static void __ip_flush_pending_frames(struct sock *sk, void ip_flush_pending_frames(struct sock *sk) { - __ip_flush_pending_frames(sk, &sk->sk_write_queue, &inet_sk(sk)->cork); + __ip_flush_pending_frames(sk, &sk->sk_write_queue, &inet_sk(sk)->cork.base); } struct sk_buff *ip_make_skb(struct sock *sk, diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4cfbb24b9e04..9d4b165837d6 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1150,6 +1150,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, { struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); + struct inet_cork *cork; struct sk_buff *skb; unsigned int maxfraglen, fragheaderlen; int exthdrlen; @@ -1163,6 +1164,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, if (flags&MSG_PROBE) return 0; + cork = &inet->cork.base; if (skb_queue_empty(&sk->sk_write_queue)) { /* * setup for corking @@ -1202,7 +1204,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, /* need source address above miyazawa*/ } dst_hold(&rt->dst); - inet->cork.dst = &rt->dst; + cork->dst = &rt->dst; inet->cork.fl.u.ip6 = *fl6; np->cork.hop_limit = hlimit; np->cork.tclass = tclass; @@ -1212,10 +1214,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, if (np->frag_size) mtu = np->frag_size; } - inet->cork.fragsize = mtu; + cork->fragsize = mtu; if (dst_allfrag(rt->dst.path)) - inet->cork.flags |= IPCORK_ALLFRAG; - inet->cork.length = 0; + cork->flags |= IPCORK_ALLFRAG; + cork->length = 0; sk->sk_sndmsg_page = NULL; sk->sk_sndmsg_off = 0; exthdrlen = rt->dst.header_len + (opt ? opt->opt_flen : 0) - @@ -1223,12 +1225,12 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, length += exthdrlen; transhdrlen += exthdrlen; } else { - rt = (struct rt6_info *)inet->cork.dst; + rt = (struct rt6_info *)cork->dst; fl6 = &inet->cork.fl.u.ip6; opt = np->cork.opt; transhdrlen = 0; exthdrlen = 0; - mtu = inet->cork.fragsize; + mtu = cork->fragsize; } hh_len = LL_RESERVED_SPACE(rt->dst.dev); @@ -1238,7 +1240,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { - if (inet->cork.length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) { + if (cork->length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) { ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen); return -EMSGSIZE; } @@ -1267,7 +1269,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, * --yoshfuji */ - inet->cork.length += length; + cork->length += length; if (length > mtu) { int proto = sk->sk_protocol; if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ @@ -1292,7 +1294,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, while (length > 0) { /* Check if the remaining data fits into current packet. */ - copy = (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - skb->len; + copy = (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - skb->len; if (copy < length) copy = maxfraglen - skb->len; @@ -1317,7 +1319,7 @@ alloc_new_skb: * we know we need more fragment(s). */ datalen = length + fraggap; - if (datalen > (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen) + if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen) datalen = maxfraglen - fragheaderlen; fraglen = datalen + fragheaderlen; @@ -1481,7 +1483,7 @@ alloc_new_skb: } return 0; error: - inet->cork.length -= length; + cork->length -= length; IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); return err; } @@ -1497,10 +1499,10 @@ static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) np->cork.opt = NULL; } - if (inet->cork.dst) { - dst_release(inet->cork.dst); - inet->cork.dst = NULL; - inet->cork.flags &= ~IPCORK_ALLFRAG; + if (inet->cork.base.dst) { + dst_release(inet->cork.base.dst); + inet->cork.base.dst = NULL; + inet->cork.base.flags &= ~IPCORK_ALLFRAG; } memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); } @@ -1515,7 +1517,7 @@ int ip6_push_pending_frames(struct sock *sk) struct net *net = sock_net(sk); struct ipv6hdr *hdr; struct ipv6_txoptions *opt = np->cork.opt; - struct rt6_info *rt = (struct rt6_info *)inet->cork.dst; + struct rt6_info *rt = (struct rt6_info *)inet->cork.base.dst; struct flowi6 *fl6 = &inet->cork.fl.u.ip6; unsigned char proto = fl6->flowi6_proto; int err = 0; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index e5e5425fe7d0..ae64984f81aa 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -542,8 +542,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, goto out; offset = rp->offset; - total_len = inet_sk(sk)->cork.length - (skb_network_header(skb) - - skb->data); + total_len = inet_sk(sk)->cork.base.length - (skb_network_header(skb) - + skb->data); if (offset >= total_len - 1) { err = -EINVAL; ip6_flush_pending_frames(sk); -- cgit v1.2.3-58-ga151 From b80d72261aec5e763a76497eba5fddc84833a154 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 15:06:01 -0700 Subject: ipv4: Initialize on-stack cork more efficiently. ip_setup_cork() explicitly initializes every member of inet_cork except flags, addr, and opt. So we can simply set those three members to zero instead of using a memset() via an empty struct assignment. Signed-off-by: David S. Miller Acked-by: Eric Dumazet --- net/ipv4/ip_output.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index eb0647a2f073..5f5fe4f742b9 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1408,7 +1408,7 @@ struct sk_buff *ip_make_skb(struct sock *sk, struct ipcm_cookie *ipc, struct rtable **rtp, unsigned int flags) { - struct inet_cork cork = {}; + struct inet_cork cork; struct sk_buff_head queue; int err; @@ -1417,6 +1417,9 @@ struct sk_buff *ip_make_skb(struct sock *sk, __skb_queue_head_init(&queue); + cork.flags = 0; + cork.addr = 0; + cork.opt = 0; err = ip_setup_cork(sk, &cork, ipc, rtp); if (err) return ERR_PTR(err); -- cgit v1.2.3-58-ga151 From 706527280ec38fcdcd0466f10b607105fd23801b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 16:01:15 -0700 Subject: ipv4: Initialize cork->opt using NULL not 0. Noticed by Joe Perches. Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 5f5fe4f742b9..0a2f49a442e8 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1419,7 +1419,7 @@ struct sk_buff *ip_make_skb(struct sock *sk, cork.flags = 0; cork.addr = 0; - cork.opt = 0; + cork.opt = NULL; err = ip_setup_cork(sk, &cork, ipc, rtp); if (err) return ERR_PTR(err); -- cgit v1.2.3-58-ga151 From a70b86ae206fdd3bef13c5ac148c22a805e83896 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Tue, 3 May 2011 05:28:23 +0000 Subject: e100: implemenet set_phys_id Based on the original patch from Stephen Hemminger. Implement set_phys_id to control LED. CC: Stephen Hemminger Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/e100.c | 66 +++++++++++++++++++++++------------------------------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 29f812dc1098..e336c7937f05 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -593,7 +593,6 @@ struct nic { enum phy phy; struct params params; struct timer_list watchdog; - struct timer_list blink_timer; struct mii_if_info mii; struct work_struct tx_timeout_task; enum loopback loopback; @@ -618,7 +617,6 @@ struct nic { u32 rx_tco_frames; u32 rx_over_length_errors; - u16 leds; u16 eeprom_wc; __le16 eeprom[256]; spinlock_t mdio_lock; @@ -2353,30 +2351,6 @@ err_clean_rx: #define E100_82552_LED_OVERRIDE 0x19 #define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ #define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ -static void e100_blink_led(unsigned long data) -{ - struct nic *nic = (struct nic *)data; - enum led_state { - led_on = 0x01, - led_off = 0x04, - led_on_559 = 0x05, - led_on_557 = 0x07, - }; - u16 led_reg = MII_LED_CONTROL; - - if (nic->phy == phy_82552_v) { - led_reg = E100_82552_LED_OVERRIDE; - - nic->leds = (nic->leds == E100_82552_LED_ON) ? - E100_82552_LED_OFF : E100_82552_LED_ON; - } else { - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : - led_on_559; - } - mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds); - mod_timer(&nic->blink_timer, jiffies + HZ / 4); -} static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) { @@ -2600,19 +2574,38 @@ static void e100_diag_test(struct net_device *netdev, msleep_interruptible(4 * 1000); } -static int e100_phys_id(struct net_device *netdev, u32 data) +static int e100_set_phys_id(struct net_device *netdev, + enum ethtool_phys_id_state state) { struct nic *nic = netdev_priv(netdev); + enum led_state { + led_on = 0x01, + led_off = 0x04, + led_on_559 = 0x05, + led_on_557 = 0x07, + }; u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : - MII_LED_CONTROL; + MII_LED_CONTROL; + u16 leds = 0; + + switch (state) { + case ETHTOOL_ID_ACTIVE: + return 2; - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - mod_timer(&nic->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, led_reg, 0); + case ETHTOOL_ID_ON: + leds = (nic->phy == phy_82552_v) ? E100_82552_LED_ON : + (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; + break; + + case ETHTOOL_ID_OFF: + leds = (nic->phy == phy_82552_v) ? E100_82552_LED_OFF : led_off; + break; + + case ETHTOOL_ID_INACTIVE: + break; + } + mdio_write(netdev, nic->mii.phy_id, led_reg, leds); return 0; } @@ -2693,7 +2686,7 @@ static const struct ethtool_ops e100_ethtool_ops = { .set_ringparam = e100_set_ringparam, .self_test = e100_diag_test, .get_strings = e100_get_strings, - .phys_id = e100_phys_id, + .set_phys_id = e100_set_phys_id, .get_ethtool_stats = e100_get_ethtool_stats, .get_sset_count = e100_get_sset_count, }; @@ -2834,9 +2827,6 @@ static int __devinit e100_probe(struct pci_dev *pdev, init_timer(&nic->watchdog); nic->watchdog.function = e100_watchdog; nic->watchdog.data = (unsigned long)nic; - init_timer(&nic->blink_timer); - nic->blink_timer.function = e100_blink_led; - nic->blink_timer.data = (unsigned long)nic; INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); -- cgit v1.2.3-58-ga151 From 6435909199c2d1b0aad3ebbfa01f641aaa24fa2a Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Tue, 3 May 2011 05:26:13 +0000 Subject: e1000: convert to set_phys_id Based on the original patch from Stephen Hemminger. Convert to new LED control infrastucture and remove no longer necessary bits. CC: Stephen Hemminger Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/e1000/e1000.h | 3 --- drivers/net/e1000/e1000_ethtool.c | 50 +++++++++++++-------------------------- 2 files changed, 16 insertions(+), 37 deletions(-) diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index b1b23ddd4eed..8676899120c3 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -238,9 +238,6 @@ struct e1000_adapter { struct work_struct reset_task; u8 fc_autoneg; - struct timer_list blink_timer; - unsigned long led_status; - /* TX */ struct e1000_tx_ring *tx_ring; /* One per active queue */ unsigned int restart_queue; diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 4fa727ce8374..ec0fa426cce2 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -1755,46 +1755,28 @@ static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) return 0; } -/* toggle LED 4 times per second = 2 "blinks" per second */ -#define E1000_ID_INTERVAL (HZ/4) - -/* bit defines for adapter->led_status */ -#define E1000_LED_ON 0 - -static void e1000_led_blink_callback(unsigned long data) +static int e1000_set_phys_id(struct net_device *netdev, + enum ethtool_phys_id_state state) { - struct e1000_adapter *adapter = (struct e1000_adapter *) data; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - if (test_and_change_bit(E1000_LED_ON, &adapter->led_status)) - e1000_led_off(hw); - else - e1000_led_on(hw); - - mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL); -} + switch (state) { + case ETHTOOL_ID_ACTIVE: + e1000_setup_led(hw); + return 2; -static int e1000_phys_id(struct net_device *netdev, u32 data) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; + case ETHTOOL_ID_ON: + e1000_led_on(hw); + break; - if (!data) - data = INT_MAX; + case ETHTOOL_ID_OFF: + e1000_led_off(hw); + break; - if (!adapter->blink_timer.function) { - init_timer(&adapter->blink_timer); - adapter->blink_timer.function = e1000_led_blink_callback; - adapter->blink_timer.data = (unsigned long)adapter; + case ETHTOOL_ID_INACTIVE: + e1000_cleanup_led(hw); } - e1000_setup_led(hw); - mod_timer(&adapter->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&adapter->blink_timer); - - e1000_led_off(hw); - clear_bit(E1000_LED_ON, &adapter->led_status); - e1000_cleanup_led(hw); return 0; } @@ -1931,7 +1913,7 @@ static const struct ethtool_ops e1000_ethtool_ops = { .set_tso = e1000_set_tso, .self_test = e1000_diag_test, .get_strings = e1000_get_strings, - .phys_id = e1000_phys_id, + .set_phys_id = e1000_set_phys_id, .get_ethtool_stats = e1000_get_ethtool_stats, .get_sset_count = e1000_get_sset_count, .get_coalesce = e1000_get_coalesce, -- cgit v1.2.3-58-ga151 From 936db3559fc4f6d2892234cadcbd88b8a7d34898 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Sat, 7 May 2011 06:37:14 +0000 Subject: igb: convert to ethtool set_phys_id Based on patch from Stephen Hemminger. Convert igb driver to use new set_phys_id ethtool interface. CC: Stephen Hemminger Signed-off-by: Jeff Kirsher --- drivers/net/igb/igb_ethtool.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 6e29634b1fb5..fdc895e5a3f8 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1964,27 +1964,28 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) /* bit defines for adapter->led_status */ #define IGB_LED_ON 0 -static int igb_phys_id(struct net_device *netdev, u32 data) +static int igb_set_phys_id(struct net_device *netdev, + enum ethtool_phys_id_state state) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - unsigned long timeout; - timeout = data * 1000; - - /* - * msleep_interruptable only accepts unsigned int so we are limited - * in how long a duration we can wait - */ - if (!timeout || timeout > UINT_MAX) - timeout = UINT_MAX; - - igb_blink_led(hw); - msleep_interruptible(timeout); - - igb_led_off(hw); - clear_bit(IGB_LED_ON, &adapter->led_status); - igb_cleanup_led(hw); + switch (state) { + case ETHTOOL_ID_ACTIVE: + igb_blink_led(hw); + return 2; + case ETHTOOL_ID_ON: + igb_blink_led(hw); + break; + case ETHTOOL_ID_OFF: + igb_led_off(hw); + break; + case ETHTOOL_ID_INACTIVE: + igb_led_off(hw); + clear_bit(IGB_LED_ON, &adapter->led_status); + igb_cleanup_led(hw); + break; + } return 0; } @@ -2216,7 +2217,7 @@ static const struct ethtool_ops igb_ethtool_ops = { .set_tso = igb_set_tso, .self_test = igb_diag_test, .get_strings = igb_get_strings, - .phys_id = igb_phys_id, + .set_phys_id = igb_set_phys_id, .get_sset_count = igb_get_sset_count, .get_ethtool_stats = igb_get_ethtool_stats, .get_coalesce = igb_get_coalesce, -- cgit v1.2.3-58-ga151 From 67a74ee2a24957012661dc4400e4f8e363d25fbb Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Sat, 23 Apr 2011 04:50:40 +0000 Subject: ixgbe: add rxhash support feed RSS hash into skb->rxhash Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_ethtool.c | 7 ++++++- drivers/net/ixgbe/ixgbe_main.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index f2efa3245352..545b231b2a74 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -2253,8 +2253,13 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data) need_reset = (data & ETH_FLAG_RXVLAN) != (netdev->features & NETIF_F_HW_VLAN_RX); + if ((data & ETH_FLAG_RXHASH) && + !(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) + return -EOPNOTSUPP; + rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_LRO | ETH_FLAG_NTUPLE | - ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN); + ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN | + ETH_FLAG_RXHASH); if (rc) return rc; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index eebb1921c660..56cc9a10c717 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1063,8 +1063,14 @@ static int __ixgbe_notify_dca(struct device *dev, void *data) return 0; } - #endif /* CONFIG_IXGBE_DCA */ + +static inline void ixgbe_rx_hash(union ixgbe_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss); +} + /** * ixgbe_receive_skb - Send a completed packet up the stack * @adapter: board private structure @@ -1456,6 +1462,8 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, } ixgbe_rx_checksum(adapter, rx_desc, skb); + if (adapter->netdev->features & NETIF_F_RXHASH) + ixgbe_rx_hash(rx_desc, skb); /* probably a little skewed due to removing CRC */ total_rx_bytes += skb->len; @@ -7361,6 +7369,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_TSO; netdev->features |= NETIF_F_TSO6; netdev->features |= NETIF_F_GRO; + netdev->features |= NETIF_F_RXHASH; switch (adapter->hw.mac.type) { case ixgbe_mac_82599EB: @@ -7441,6 +7450,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (err) goto err_sw_init; + if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) + netdev->features &= ~NETIF_F_RXHASH; + switch (pdev->device) { case IXGBE_DEV_ID_82599_SFP: /* Only this subdevice supports WOL */ -- cgit v1.2.3-58-ga151 From 58f6bcf96e95f042a2bee6ace238365cb8fb1ce6 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 21 Apr 2011 08:43:43 +0000 Subject: ixgbe: add ethtool counters for OS2BMC OS2BMC registers are available for X540. This patch adds ethtool counters based on those registers. Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_ethtool.c | 4 ++++ drivers/net/ixgbe/ixgbe_main.c | 7 ++++++- drivers/net/ixgbe/ixgbe_type.h | 8 ++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 545b231b2a74..1fdd075afe79 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -102,6 +102,10 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = { {"alloc_rx_page_failed", IXGBE_STAT(alloc_rx_page_failed)}, {"alloc_rx_buff_failed", IXGBE_STAT(alloc_rx_buff_failed)}, {"rx_no_dma_resources", IXGBE_STAT(hw_rx_no_dma_resources)}, + {"os2bmc_rx_by_bmc", IXGBE_STAT(stats.o2bgptc)}, + {"os2bmc_tx_by_bmc", IXGBE_STAT(stats.b2ospc)}, + {"os2bmc_tx_by_host", IXGBE_STAT(stats.o2bspc)}, + {"os2bmc_rx_by_host", IXGBE_STAT(stats.b2ogprc)}, #ifdef IXGBE_FCOE {"fcoe_bad_fccrc", IXGBE_STAT(stats.fccrc)}, {"rx_fcoe_dropped", IXGBE_STAT(stats.fcoerpdc)}, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 56cc9a10c717..a3e384bc50fe 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -5912,8 +5912,13 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORH); break; - case ixgbe_mac_82599EB: case ixgbe_mac_X540: + /* OS2BMC stats are X540 only*/ + hwstats->o2bgptc += IXGBE_READ_REG(hw, IXGBE_O2BGPTC); + hwstats->o2bspc += IXGBE_READ_REG(hw, IXGBE_O2BSPC); + hwstats->b2ospc += IXGBE_READ_REG(hw, IXGBE_B2OSPC); + hwstats->b2ogprc += IXGBE_READ_REG(hw, IXGBE_B2OGPRC); + case ixgbe_mac_82599EB: hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL); IXGBE_READ_REG(hw, IXGBE_GORCH); /* to clear */ hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL); diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index b1d523ca4d81..70e6870be01f 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -672,6 +672,10 @@ #define IXGBE_FCOEDWRC 0x0242C /* Number of FCoE DWords Received */ #define IXGBE_FCOEPTC 0x08784 /* Number of FCoE Packets Transmitted */ #define IXGBE_FCOEDWTC 0x08788 /* Number of FCoE DWords Transmitted */ +#define IXGBE_O2BGPTC 0x041C4 +#define IXGBE_O2BSPC 0x087B0 +#define IXGBE_B2OSPC 0x041C0 +#define IXGBE_B2OGPRC 0x02F90 #define IXGBE_PCRC8ECL 0x0E810 #define IXGBE_PCRC8ECH 0x0E811 #define IXGBE_PCRC8ECH_MASK 0x1F @@ -2554,6 +2558,10 @@ struct ixgbe_hw_stats { u64 fcoeptc; u64 fcoedwrc; u64 fcoedwtc; + u64 b2ospc; + u64 b2ogprc; + u64 o2bgptc; + u64 o2bspc; }; /* forward declaration */ -- cgit v1.2.3-58-ga151 From 0f020dec545629bb068310e8ee374648867e391c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 7 May 2011 01:02:28 -0700 Subject: hamachi: Put back RX_CHECKSUM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I deleted it by mistake in the TX_CHECKSUM removal commit. Reported-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/hamachi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index f5fba73c8738..a09041aa8509 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -134,6 +134,7 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; * TCP and UDP packets. Otherwise the upper layers do the calculation. * 3/10/1999 Pete Wyckoff */ +#define RX_CHECKSUM /* Operational parameters that usually are not changed. */ /* Time in jiffies before concluding the transmitter is hung. */ -- cgit v1.2.3-58-ga151 From 28f8e546e6bc4c2bc6687d7c8dcbe9934cebe639 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Mon, 2 May 2011 16:37:13 +0200 Subject: batman-adv: remove misplaced comment Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/originator.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index ef4a9be7613a..51af91b7a35b 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -19,8 +19,6 @@ * */ -/* increase the reference counter for this originator */ - #include "main.h" #include "originator.h" #include "hash.h" -- cgit v1.2.3-58-ga151 From 61906ae86d8989e5bd3bc1f51b2fb8d32ffde2c5 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Thu, 21 Apr 2011 15:52:17 +0200 Subject: batman-adv: multi vlan support for bridge loop detection The bridge loop detection for batman-adv allows the bat0 interface to be bridged into an ethernet segment which other batman-adv nodes are connected to. In order to also allow multiple VLANs on top of the bat0 interface to be bridged into the ethernet segment this patch extends the aforementioned bridge loop detection. Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/main.c | 3 +- net/batman-adv/soft-interface.c | 393 +++++++++++++++++++++++++++++----------- net/batman-adv/types.h | 15 +- 3 files changed, 298 insertions(+), 113 deletions(-) diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 709b33bbdf43..705e8be07c8d 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -87,11 +87,12 @@ int mesh_init(struct net_device *soft_iface) spin_lock_init(&bat_priv->vis_hash_lock); spin_lock_init(&bat_priv->vis_list_lock); spin_lock_init(&bat_priv->softif_neigh_lock); + spin_lock_init(&bat_priv->softif_neigh_vid_lock); INIT_HLIST_HEAD(&bat_priv->forw_bat_list); INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); INIT_HLIST_HEAD(&bat_priv->gw_list); - INIT_HLIST_HEAD(&bat_priv->softif_neigh_list); + INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids); if (originator_init(bat_priv) < 1) goto err; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index ea5e58c252f0..8cb13a03b0e1 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -90,135 +90,251 @@ static void softif_neigh_free_ref(struct softif_neigh *softif_neigh) call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu); } -static struct softif_neigh *softif_neigh_get_selected(struct bat_priv *bat_priv) +static void softif_neigh_vid_free_rcu(struct rcu_head *rcu) { - struct softif_neigh *neigh; - - rcu_read_lock(); - neigh = rcu_dereference(bat_priv->softif_neigh); - - if (neigh && !atomic_inc_not_zero(&neigh->refcount)) - neigh = NULL; - - rcu_read_unlock(); - return neigh; -} + struct softif_neigh_vid *softif_neigh_vid; + struct softif_neigh *softif_neigh; + struct hlist_node *node, *node_tmp; + struct bat_priv *bat_priv; -static void softif_neigh_select(struct bat_priv *bat_priv, - struct softif_neigh *new_neigh) -{ - struct softif_neigh *curr_neigh; + softif_neigh_vid = container_of(rcu, struct softif_neigh_vid, rcu); + bat_priv = softif_neigh_vid->bat_priv; spin_lock_bh(&bat_priv->softif_neigh_lock); - - if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount)) - new_neigh = NULL; - - curr_neigh = bat_priv->softif_neigh; - rcu_assign_pointer(bat_priv->softif_neigh, new_neigh); - - if (curr_neigh) - softif_neigh_free_ref(curr_neigh); - + hlist_for_each_entry_safe(softif_neigh, node, node_tmp, + &softif_neigh_vid->softif_neigh_list, list) { + hlist_del_rcu(&softif_neigh->list); + softif_neigh_free_ref(softif_neigh); + } spin_unlock_bh(&bat_priv->softif_neigh_lock); + + kfree(softif_neigh_vid); } -static void softif_neigh_deselect(struct bat_priv *bat_priv) +static void softif_neigh_vid_free_ref(struct softif_neigh_vid *softif_neigh_vid) { - softif_neigh_select(bat_priv, NULL); + if (atomic_dec_and_test(&softif_neigh_vid->refcount)) + call_rcu(&softif_neigh_vid->rcu, softif_neigh_vid_free_rcu); } -void softif_neigh_purge(struct bat_priv *bat_priv) +static struct softif_neigh_vid *softif_neigh_vid_get(struct bat_priv *bat_priv, + short vid) { - struct softif_neigh *softif_neigh, *curr_softif_neigh; - struct hlist_node *node, *node_tmp; - char do_deselect = 0; - - curr_softif_neigh = softif_neigh_get_selected(bat_priv); - - spin_lock_bh(&bat_priv->softif_neigh_lock); - - hlist_for_each_entry_safe(softif_neigh, node, node_tmp, - &bat_priv->softif_neigh_list, list) { + struct softif_neigh_vid *softif_neigh_vid; + struct hlist_node *node; - if ((!time_after(jiffies, softif_neigh->last_seen + - msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) && - (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) + rcu_read_lock(); + hlist_for_each_entry_rcu(softif_neigh_vid, node, + &bat_priv->softif_neigh_vids, list) { + if (softif_neigh_vid->vid != vid) continue; - if (curr_softif_neigh == softif_neigh) { - bat_dbg(DBG_ROUTES, bat_priv, - "Current mesh exit point '%pM' vanished " - "(vid: %d).\n", - softif_neigh->addr, softif_neigh->vid); - do_deselect = 1; - } + if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) + continue; - hlist_del_rcu(&softif_neigh->list); - softif_neigh_free_ref(softif_neigh); + goto out; } - spin_unlock_bh(&bat_priv->softif_neigh_lock); + softif_neigh_vid = kzalloc(sizeof(struct softif_neigh_vid), + GFP_ATOMIC); + if (!softif_neigh_vid) + goto out; - /* soft_neigh_deselect() needs to acquire the softif_neigh_lock */ - if (do_deselect) - softif_neigh_deselect(bat_priv); + softif_neigh_vid->vid = vid; + softif_neigh_vid->bat_priv = bat_priv; - if (curr_softif_neigh) - softif_neigh_free_ref(curr_softif_neigh); + /* initialize with 2 - caller decrements counter by one */ + atomic_set(&softif_neigh_vid->refcount, 2); + INIT_HLIST_HEAD(&softif_neigh_vid->softif_neigh_list); + INIT_HLIST_NODE(&softif_neigh_vid->list); + spin_lock_bh(&bat_priv->softif_neigh_vid_lock); + hlist_add_head_rcu(&softif_neigh_vid->list, + &bat_priv->softif_neigh_vids); + spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); + +out: + rcu_read_unlock(); + return softif_neigh_vid; } static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv, uint8_t *addr, short vid) { - struct softif_neigh *softif_neigh; + struct softif_neigh_vid *softif_neigh_vid; + struct softif_neigh *softif_neigh = NULL; struct hlist_node *node; + softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); + if (!softif_neigh_vid) + goto out; + rcu_read_lock(); hlist_for_each_entry_rcu(softif_neigh, node, - &bat_priv->softif_neigh_list, list) { + &softif_neigh_vid->softif_neigh_list, + list) { if (!compare_eth(softif_neigh->addr, addr)) continue; - if (softif_neigh->vid != vid) - continue; - if (!atomic_inc_not_zero(&softif_neigh->refcount)) continue; softif_neigh->last_seen = jiffies; - goto out; + goto unlock; } softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC); if (!softif_neigh) - goto out; + goto unlock; memcpy(softif_neigh->addr, addr, ETH_ALEN); - softif_neigh->vid = vid; softif_neigh->last_seen = jiffies; /* initialize with 2 - caller decrements counter by one */ atomic_set(&softif_neigh->refcount, 2); INIT_HLIST_NODE(&softif_neigh->list); spin_lock_bh(&bat_priv->softif_neigh_lock); - hlist_add_head_rcu(&softif_neigh->list, &bat_priv->softif_neigh_list); + hlist_add_head_rcu(&softif_neigh->list, + &softif_neigh_vid->softif_neigh_list); spin_unlock_bh(&bat_priv->softif_neigh_lock); +unlock: + rcu_read_unlock(); out: + if (softif_neigh_vid) + softif_neigh_vid_free_ref(softif_neigh_vid); + return softif_neigh; +} + +static struct softif_neigh *softif_neigh_get_selected( + struct softif_neigh_vid *softif_neigh_vid) +{ + struct softif_neigh *softif_neigh; + + rcu_read_lock(); + softif_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); + + if (softif_neigh && !atomic_inc_not_zero(&softif_neigh->refcount)) + softif_neigh = NULL; + rcu_read_unlock(); return softif_neigh; } +static struct softif_neigh *softif_neigh_vid_get_selected( + struct bat_priv *bat_priv, + short vid) +{ + struct softif_neigh_vid *softif_neigh_vid; + struct softif_neigh *softif_neigh = NULL; + + softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); + if (!softif_neigh_vid) + goto out; + + softif_neigh = softif_neigh_get_selected(softif_neigh_vid); +out: + if (softif_neigh_vid) + softif_neigh_vid_free_ref(softif_neigh_vid); + return softif_neigh; +} + +static void softif_neigh_vid_select(struct bat_priv *bat_priv, + struct softif_neigh *new_neigh, + short vid) +{ + struct softif_neigh_vid *softif_neigh_vid; + struct softif_neigh *curr_neigh; + + softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); + if (!softif_neigh_vid) + goto out; + + spin_lock_bh(&bat_priv->softif_neigh_lock); + + if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount)) + new_neigh = NULL; + + curr_neigh = softif_neigh_vid->softif_neigh; + rcu_assign_pointer(softif_neigh_vid->softif_neigh, new_neigh); + + if ((curr_neigh) && (!new_neigh)) + bat_dbg(DBG_ROUTES, bat_priv, + "Removing mesh exit point on vid: %d (prev: %pM).\n", + vid, curr_neigh->addr); + else if ((curr_neigh) && (new_neigh)) + bat_dbg(DBG_ROUTES, bat_priv, + "Changing mesh exit point on vid: %d from %pM " + "to %pM.\n", vid, curr_neigh->addr, new_neigh->addr); + else if ((!curr_neigh) && (new_neigh)) + bat_dbg(DBG_ROUTES, bat_priv, + "Setting mesh exit point on vid: %d to %pM.\n", + vid, new_neigh->addr); + + if (curr_neigh) + softif_neigh_free_ref(curr_neigh); + + spin_unlock_bh(&bat_priv->softif_neigh_lock); + +out: + if (softif_neigh_vid) + softif_neigh_vid_free_ref(softif_neigh_vid); +} + +static void softif_neigh_vid_deselect(struct bat_priv *bat_priv, + struct softif_neigh_vid *softif_neigh_vid) +{ + struct softif_neigh *curr_neigh; + struct softif_neigh *softif_neigh = NULL, *softif_neigh_tmp; + struct hard_iface *primary_if = NULL; + struct hlist_node *node; + + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; + + /* find new softif_neigh immediately to avoid temporary loops */ + rcu_read_lock(); + curr_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); + + hlist_for_each_entry_rcu(softif_neigh_tmp, node, + &softif_neigh_vid->softif_neigh_list, + list) { + if (softif_neigh_tmp == curr_neigh) + continue; + + /* we got a neighbor but its mac is 'bigger' than ours */ + if (memcmp(primary_if->net_dev->dev_addr, + softif_neigh_tmp->addr, ETH_ALEN) < 0) + continue; + + if (!atomic_inc_not_zero(&softif_neigh_tmp->refcount)) + continue; + + softif_neigh = softif_neigh_tmp; + goto unlock; + } + +unlock: + rcu_read_unlock(); +out: + softif_neigh_vid_select(bat_priv, softif_neigh, softif_neigh_vid->vid); + + if (primary_if) + hardif_free_ref(primary_if); + if (softif_neigh) + softif_neigh_free_ref(softif_neigh); +} + int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); + struct softif_neigh_vid *softif_neigh_vid; struct softif_neigh *softif_neigh; struct hard_iface *primary_if; - struct hlist_node *node; + struct hlist_node *node, *node_tmp; struct softif_neigh *curr_softif_neigh; - int ret = 0; + int ret = 0, last_seen_secs, last_seen_msecs; primary_if = primary_if_get_selected(bat_priv); if (!primary_if) { @@ -237,17 +353,33 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); - curr_softif_neigh = softif_neigh_get_selected(bat_priv); rcu_read_lock(); - hlist_for_each_entry_rcu(softif_neigh, node, - &bat_priv->softif_neigh_list, list) - seq_printf(seq, "%s %pM (vid: %d)\n", - curr_softif_neigh == softif_neigh - ? "=>" : " ", softif_neigh->addr, - softif_neigh->vid); + hlist_for_each_entry_rcu(softif_neigh_vid, node, + &bat_priv->softif_neigh_vids, list) { + seq_printf(seq, " %-15s %s on vid: %d\n", + "Originator", "last-seen", softif_neigh_vid->vid); + + curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); + + hlist_for_each_entry_rcu(softif_neigh, node_tmp, + &softif_neigh_vid->softif_neigh_list, + list) { + last_seen_secs = jiffies_to_msecs(jiffies - + softif_neigh->last_seen) / 1000; + last_seen_msecs = jiffies_to_msecs(jiffies - + softif_neigh->last_seen) % 1000; + seq_printf(seq, "%s %pM %3i.%03is\n", + curr_softif_neigh == softif_neigh + ? "=>" : " ", softif_neigh->addr, + last_seen_secs, last_seen_msecs); + } + + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); + + seq_printf(seq, "\n"); + } rcu_read_unlock(); - if (curr_softif_neigh) - softif_neigh_free_ref(curr_softif_neigh); out: if (primary_if) @@ -255,6 +387,70 @@ out: return ret; } +void softif_neigh_purge(struct bat_priv *bat_priv) +{ + struct softif_neigh *softif_neigh, *curr_softif_neigh; + struct softif_neigh_vid *softif_neigh_vid; + struct hlist_node *node, *node_tmp, *node_tmp2; + char do_deselect; + + rcu_read_lock(); + hlist_for_each_entry_rcu(softif_neigh_vid, node, + &bat_priv->softif_neigh_vids, list) { + if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) + continue; + + curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); + do_deselect = 0; + + spin_lock_bh(&bat_priv->softif_neigh_lock); + hlist_for_each_entry_safe(softif_neigh, node_tmp, node_tmp2, + &softif_neigh_vid->softif_neigh_list, + list) { + if ((!time_after(jiffies, softif_neigh->last_seen + + msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) && + (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) + continue; + + if (curr_softif_neigh == softif_neigh) { + bat_dbg(DBG_ROUTES, bat_priv, + "Current mesh exit point on vid: %d " + "'%pM' vanished.\n", + softif_neigh_vid->vid, + softif_neigh->addr); + do_deselect = 1; + } + + hlist_del_rcu(&softif_neigh->list); + softif_neigh_free_ref(softif_neigh); + } + spin_unlock_bh(&bat_priv->softif_neigh_lock); + + /* soft_neigh_vid_deselect() needs to acquire the + * softif_neigh_lock */ + if (do_deselect) + softif_neigh_vid_deselect(bat_priv, softif_neigh_vid); + + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); + + softif_neigh_vid_free_ref(softif_neigh_vid); + } + rcu_read_unlock(); + + spin_lock_bh(&bat_priv->softif_neigh_vid_lock); + hlist_for_each_entry_safe(softif_neigh_vid, node, node_tmp, + &bat_priv->softif_neigh_vids, list) { + if (!hlist_empty(&softif_neigh_vid->softif_neigh_list)) + continue; + + hlist_del_rcu(&softif_neigh_vid->list); + softif_neigh_vid_free_ref(softif_neigh_vid); + } + spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); + +} + static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, short vid) { @@ -287,10 +483,7 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, if (!softif_neigh) goto out; - curr_softif_neigh = softif_neigh_get_selected(bat_priv); - if (!curr_softif_neigh) - goto out; - + curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); if (curr_softif_neigh == softif_neigh) goto out; @@ -303,33 +496,16 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, softif_neigh->addr, ETH_ALEN) < 0) goto out; - /* switch to new 'smallest neighbor' */ - if ((curr_softif_neigh) && - (memcmp(softif_neigh->addr, curr_softif_neigh->addr, - ETH_ALEN) < 0)) { - bat_dbg(DBG_ROUTES, bat_priv, - "Changing mesh exit point from %pM (vid: %d) " - "to %pM (vid: %d).\n", - curr_softif_neigh->addr, - curr_softif_neigh->vid, - softif_neigh->addr, softif_neigh->vid); - - softif_neigh_select(bat_priv, softif_neigh); - goto out; - } - /* close own batX device and use softif_neigh as exit node */ - if ((!curr_softif_neigh) && - (memcmp(softif_neigh->addr, - primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) { - bat_dbg(DBG_ROUTES, bat_priv, - "Setting mesh exit point to %pM (vid: %d).\n", - softif_neigh->addr, softif_neigh->vid); - - softif_neigh_select(bat_priv, softif_neigh); + if (!curr_softif_neigh) { + softif_neigh_vid_select(bat_priv, softif_neigh, vid); goto out; } + /* switch to new 'smallest neighbor' */ + if (memcmp(softif_neigh->addr, curr_softif_neigh->addr, ETH_ALEN) < 0) + softif_neigh_vid_select(bat_priv, softif_neigh, vid); + out: kfree_skb(skb); if (softif_neigh) @@ -424,8 +600,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) * if we have a another chosen mesh exit node in range * it will transport the packets to the mesh */ - curr_softif_neigh = softif_neigh_get_selected(bat_priv); - if ((curr_softif_neigh) && (curr_softif_neigh->vid == vid)) + curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); + if (curr_softif_neigh) goto dropped; /* TODO: check this for locks */ @@ -533,8 +709,8 @@ void interface_rx(struct net_device *soft_iface, * if we have a another chosen mesh exit node in range * it will transport the packets to the non-mesh network */ - curr_softif_neigh = softif_neigh_get_selected(bat_priv); - if (curr_softif_neigh && (curr_softif_neigh->vid == vid)) { + curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); + if (curr_softif_neigh) { skb_push(skb, hdr_size); unicast_packet = (struct unicast_packet *)skb->data; @@ -671,7 +847,6 @@ struct net_device *softif_create(char *name) bat_priv->primary_if = NULL; bat_priv->num_ifaces = 0; - bat_priv->softif_neigh = NULL; ret = sysfs_add_meshif(soft_iface); if (ret < 0) diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 947bafc6431a..9ae507ab7bbe 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -146,14 +146,13 @@ struct bat_priv { atomic_t bcast_queue_left; atomic_t batman_queue_left; char num_ifaces; - struct hlist_head softif_neigh_list; - struct softif_neigh __rcu *softif_neigh; struct debug_log *debug_log; struct kobject *mesh_obj; struct dentry *debug_dir; struct hlist_head forw_bat_list; struct hlist_head forw_bcast_list; struct hlist_head gw_list; + struct hlist_head softif_neigh_vids; struct list_head vis_send_list; struct hashtable_t *orig_hash; struct hashtable_t *hna_local_hash; @@ -167,6 +166,7 @@ struct bat_priv { spinlock_t vis_hash_lock; /* protects vis_hash */ spinlock_t vis_list_lock; /* protects vis_info::recv_list */ spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */ + spinlock_t softif_neigh_vid_lock; /* protects soft-interface vid list */ int16_t num_local_hna; atomic_t hna_local_changed; struct delayed_work hna_work; @@ -270,11 +270,20 @@ struct recvlist_node { uint8_t mac[ETH_ALEN]; }; +struct softif_neigh_vid { + struct hlist_node list; + struct bat_priv *bat_priv; + short vid; + atomic_t refcount; + struct softif_neigh __rcu *softif_neigh; + struct rcu_head rcu; + struct hlist_head softif_neigh_list; +}; + struct softif_neigh { struct hlist_node list; uint8_t addr[ETH_ALEN]; unsigned long last_seen; - short vid; atomic_t refcount; struct rcu_head rcu; }; -- cgit v1.2.3-58-ga151 From c3caf5196c47a5d1c325308d8eb7f6b020ba12df Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 3 May 2011 11:51:38 +0200 Subject: batman-adv: Remove unnecessary hardif_list_lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hardif_list_lock is unneccessary because we already ensure that no multiple admin operations can take place through rtnl_lock. hardif_list_lock only adds additional overhead and complexity. Critical functions now check whether they are called with rtnl_lock using ASSERT_RTNL. It indirectly fixes the problem that orig_hash_del_if() expects that only one interface is deleted from hardif_list at a time, but hardif_remove_interfaces() removes all at once and then calls orig_hash_del_if(). Reported-by: Linus Lüssing Signed-off-by: Sven Eckelmann --- net/batman-adv/bat_sysfs.c | 2 ++ net/batman-adv/hard-interface.c | 30 +++++++----------------------- net/batman-adv/main.c | 3 +++ net/batman-adv/soft-interface.c | 2 +- 4 files changed, 13 insertions(+), 24 deletions(-) diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c index e449bf6353e0..85ba20d98a66 100644 --- a/net/batman-adv/bat_sysfs.c +++ b/net/batman-adv/bat_sysfs.c @@ -502,7 +502,9 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr, rtnl_unlock(); } + rtnl_lock(); ret = hardif_enable_interface(hard_iface, buff); + rtnl_unlock(); out: hardif_free_ref(hard_iface); diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 3e888f133d75..7e2f7728f706 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -31,9 +31,6 @@ #include -/* protect update critical side of hardif_list - but not the content */ -static DEFINE_SPINLOCK(hardif_list_lock); - static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, @@ -136,7 +133,7 @@ static void primary_if_select(struct bat_priv *bat_priv, struct hard_iface *curr_hard_iface; struct batman_packet *batman_packet; - spin_lock_bh(&hardif_list_lock); + ASSERT_RTNL(); if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount)) new_hard_iface = NULL; @@ -148,7 +145,7 @@ static void primary_if_select(struct bat_priv *bat_priv, hardif_free_ref(curr_hard_iface); if (!new_hard_iface) - goto out; + return; batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff); batman_packet->flags = PRIMARIES_FIRST_HOP; @@ -161,9 +158,6 @@ static void primary_if_select(struct bat_priv *bat_priv, * our new primary interface */ atomic_set(&bat_priv->hna_local_changed, 1); - -out: - spin_unlock_bh(&hardif_list_lock); } static bool hardif_is_iface_up(struct hard_iface *hard_iface) @@ -456,6 +450,8 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev) struct hard_iface *hard_iface; int ret; + ASSERT_RTNL(); + ret = is_valid_iface(net_dev); if (ret != 1) goto out; @@ -482,10 +478,7 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev) atomic_set(&hard_iface->refcount, 2); check_known_mac_addr(hard_iface->net_dev); - - spin_lock(&hardif_list_lock); list_add_tail_rcu(&hard_iface->list, &hardif_list); - spin_unlock(&hardif_list_lock); return hard_iface; @@ -499,6 +492,8 @@ out: static void hardif_remove_interface(struct hard_iface *hard_iface) { + ASSERT_RTNL(); + /* first deactivate interface */ if (hard_iface->if_status != IF_NOT_IN_USE) hardif_disable_interface(hard_iface); @@ -514,20 +509,11 @@ static void hardif_remove_interface(struct hard_iface *hard_iface) void hardif_remove_interfaces(void) { struct hard_iface *hard_iface, *hard_iface_tmp; - struct list_head if_queue; - - INIT_LIST_HEAD(&if_queue); - spin_lock(&hardif_list_lock); + rtnl_lock(); list_for_each_entry_safe(hard_iface, hard_iface_tmp, &hardif_list, list) { list_del_rcu(&hard_iface->list); - list_add_tail(&hard_iface->list, &if_queue); - } - spin_unlock(&hardif_list_lock); - - rtnl_lock(); - list_for_each_entry_safe(hard_iface, hard_iface_tmp, &if_queue, list) { hardif_remove_interface(hard_iface); } rtnl_unlock(); @@ -556,9 +542,7 @@ static int hard_if_event(struct notifier_block *this, hardif_deactivate_interface(hard_iface); break; case NETDEV_UNREGISTER: - spin_lock(&hardif_list_lock); list_del_rcu(&hard_iface->list); - spin_unlock(&hardif_list_lock); hardif_remove_interface(hard_iface); break; diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 705e8be07c8d..7edf8d719e15 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -33,6 +33,9 @@ #include "vis.h" #include "hash.h" + +/* List manipulations on hardif_list have to be rtnl_lock()'ed, + * list traversals just rcu-locked */ struct list_head hardif_list; unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 8cb13a03b0e1..9301e21052e7 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -819,7 +819,7 @@ struct net_device *softif_create(char *name) goto out; } - ret = register_netdev(soft_iface); + ret = register_netdevice(soft_iface); if (ret < 0) { pr_err("Unable to register the batman interface '%s': %i\n", name, ret); -- cgit v1.2.3-58-ga151 From 3a4375a9f0080e6ae40af63e2e2c1e70a6dcb775 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 3 May 2011 13:10:06 +0200 Subject: batman-adv: Avoid deadlock between rtnl_lock and s_active The hard_if_event is called by the notifier with rtnl_lock and tries to remove sysfs entries when a NETDEV_UNREGISTER event is received. This will automatically take the s_active lock. The s_active lock is also used when a new interface is added to a meshif through sysfs. In that situation we cannot wait for the rntl_lock before creating the actual batman-adv interface to prevent a deadlock. It is still possible to try to get the rtnl_lock and immediately abort the current operation when the trylock call failed. Signed-off-by: Sven Eckelmann --- net/batman-adv/bat_sysfs.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c index 85ba20d98a66..497a0700cc3c 100644 --- a/net/batman-adv/bat_sysfs.c +++ b/net/batman-adv/bat_sysfs.c @@ -488,24 +488,24 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr, (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) goto out; + if (!rtnl_trylock()) { + ret = -ERESTARTSYS; + goto out; + } + if (status_tmp == IF_NOT_IN_USE) { - rtnl_lock(); hardif_disable_interface(hard_iface); - rtnl_unlock(); - goto out; + goto unlock; } /* if the interface already is in use */ - if (hard_iface->if_status != IF_NOT_IN_USE) { - rtnl_lock(); + if (hard_iface->if_status != IF_NOT_IN_USE) hardif_disable_interface(hard_iface); - rtnl_unlock(); - } - rtnl_lock(); ret = hardif_enable_interface(hard_iface, buff); - rtnl_unlock(); +unlock: + rtnl_unlock(); out: hardif_free_ref(hard_iface); return ret; -- cgit v1.2.3-58-ga151 From 01df2b65e97735547ce37844f4134b5ea99b4037 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Thu, 5 May 2011 14:14:46 +0200 Subject: batman-adv: Fix refcount imbalance in find_router Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/routing.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 49f571553050..d8cde2b8d1cf 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1213,7 +1213,7 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, router = orig_node_get_router(orig_node); if (!router) - return NULL; + goto err; /* without bonding, the first node should * always choose the default router. */ @@ -1222,10 +1222,8 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, rcu_read_lock(); /* select default router to output */ router_orig = router->orig_node; - if (!router_orig) { - rcu_read_unlock(); - return NULL; - } + if (!router_orig) + goto err_unlock; if ((!recv_if) && (!bonding_enabled)) goto return_router; @@ -1268,6 +1266,12 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, return_router: rcu_read_unlock(); return router; +err_unlock: + rcu_read_unlock(); +err: + if (router) + neigh_node_free_ref(router); + return NULL; } static int check_unicast_packet(struct sk_buff *skb, int hdr_size) -- cgit v1.2.3-58-ga151 From 2dafb49d84a9195193b28ac5047df1bbab6053b9 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Thu, 5 May 2011 08:42:45 +0200 Subject: batman-adv: rename everything from *hna* into *tt* (translation table) To be coherent, all the functions/variables/constants have been renamed to the TranslationTable style Signed-off-by: Antonio Quartulli Signed-off-by: Sven Eckelmann --- Documentation/networking/batman-adv.txt | 11 +- net/batman-adv/aggregation.c | 16 +- net/batman-adv/aggregation.h | 4 +- net/batman-adv/bat_debugfs.c | 4 +- net/batman-adv/hard-interface.c | 6 +- net/batman-adv/main.c | 14 +- net/batman-adv/main.h | 4 +- net/batman-adv/originator.c | 8 +- net/batman-adv/packet.h | 2 +- net/batman-adv/routing.c | 74 +++--- net/batman-adv/routing.h | 6 +- net/batman-adv/send.c | 16 +- net/batman-adv/send.h | 2 +- net/batman-adv/soft-interface.c | 10 +- net/batman-adv/translation-table.c | 417 ++++++++++++++++---------------- net/batman-adv/translation-table.h | 24 +- net/batman-adv/types.h | 24 +- net/batman-adv/unicast.c | 2 +- net/batman-adv/vis.c | 18 +- 19 files changed, 332 insertions(+), 330 deletions(-) diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt index 18afcd8afd51..713f7c0c4ab3 100644 --- a/Documentation/networking/batman-adv.txt +++ b/Documentation/networking/batman-adv.txt @@ -1,4 +1,4 @@ -[state: 27-01-2011] +[state: 17-04-2011] BATMAN-ADV ---------- @@ -19,6 +19,7 @@ duce the overhead to a minimum. It does not depend on any (other) network driver, and can be used on wifi as well as ethernet lan, vpn, etc ... (anything with ethernet-style layer 2). + CONFIGURATION ------------- @@ -160,13 +161,13 @@ face. Each entry can/has to have the following values: -> "TQ mac value" - src mac's link quality towards mac address of a neighbor originator's interface which is being used for routing --> "HNA mac" - HNA announced by source mac +-> "TT mac" - TT announced by source mac -> "PRIMARY" - this is a primary interface -> "SEC mac" - secondary mac address of source (requires preceding PRIMARY) The TQ value has a range from 4 to 255 with 255 being the best. -The HNA entries are showing which hosts are connected to the mesh +The TT entries are showing which hosts are connected to the mesh via bat0 or being bridged into the mesh network. The PRIMARY/SEC values are only applied on primary interfaces @@ -199,7 +200,7 @@ abled during run time. Following log_levels are defined: 0 - All debug output disabled 1 - Enable messages related to routing / flooding / broadcasting -2 - Enable route or hna added / changed / deleted +2 - Enable route or tt entry added / changed / deleted 3 - Enable all messages The debug output can be changed at runtime using the file @@ -207,7 +208,7 @@ The debug output can be changed at runtime using the file # echo 2 > /sys/class/net/bat0/mesh/log_level -will enable debug messages for when routes or HNAs change. +will enable debug messages for when routes or TTs change. BATCTL diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c index c11788c4c1a1..9b9459024479 100644 --- a/net/batman-adv/aggregation.c +++ b/net/batman-adv/aggregation.c @@ -24,10 +24,10 @@ #include "send.h" #include "routing.h" -/* calculate the size of the hna information for a given packet */ -static int hna_len(struct batman_packet *batman_packet) +/* calculate the size of the tt information for a given packet */ +static int tt_len(struct batman_packet *batman_packet) { - return batman_packet->num_hna * ETH_ALEN; + return batman_packet->num_tt * ETH_ALEN; } /* return true if new_packet can be aggregated with forw_packet */ @@ -250,7 +250,7 @@ void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff, { struct batman_packet *batman_packet; int buff_pos = 0; - unsigned char *hna_buff; + unsigned char *tt_buff; batman_packet = (struct batman_packet *)packet_buff; @@ -259,14 +259,14 @@ void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff, orig_interval. */ batman_packet->seqno = ntohl(batman_packet->seqno); - hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN; + tt_buff = packet_buff + buff_pos + BAT_PACKET_LEN; receive_bat_packet(ethhdr, batman_packet, - hna_buff, hna_len(batman_packet), + tt_buff, tt_len(batman_packet), if_incoming); - buff_pos += BAT_PACKET_LEN + hna_len(batman_packet); + buff_pos += BAT_PACKET_LEN + tt_len(batman_packet); batman_packet = (struct batman_packet *) (packet_buff + buff_pos); } while (aggregated_packet(buff_pos, packet_len, - batman_packet->num_hna)); + batman_packet->num_tt)); } diff --git a/net/batman-adv/aggregation.h b/net/batman-adv/aggregation.h index 062204289d1f..7e6d72fbf540 100644 --- a/net/batman-adv/aggregation.h +++ b/net/batman-adv/aggregation.h @@ -25,9 +25,9 @@ #include "main.h" /* is there another aggregated packet here? */ -static inline int aggregated_packet(int buff_pos, int packet_len, int num_hna) +static inline int aggregated_packet(int buff_pos, int packet_len, int num_tt) { - int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_hna * ETH_ALEN); + int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_tt * ETH_ALEN); return (next_buff_pos <= packet_len) && (next_buff_pos <= MAX_AGGREGATION_BYTES); diff --git a/net/batman-adv/bat_debugfs.c b/net/batman-adv/bat_debugfs.c index 0e9d43509935..abaeec5f6247 100644 --- a/net/batman-adv/bat_debugfs.c +++ b/net/batman-adv/bat_debugfs.c @@ -241,13 +241,13 @@ static int softif_neigh_open(struct inode *inode, struct file *file) static int transtable_global_open(struct inode *inode, struct file *file) { struct net_device *net_dev = (struct net_device *)inode->i_private; - return single_open(file, hna_global_seq_print_text, net_dev); + return single_open(file, tt_global_seq_print_text, net_dev); } static int transtable_local_open(struct inode *inode, struct file *file) { struct net_device *net_dev = (struct net_device *)inode->i_private; - return single_open(file, hna_local_seq_print_text, net_dev); + return single_open(file, tt_local_seq_print_text, net_dev); } static int vis_data_open(struct inode *inode, struct file *file) diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 7e2f7728f706..dfbfccc9fe40 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -154,10 +154,10 @@ static void primary_if_select(struct bat_priv *bat_priv, primary_if_update_addr(bat_priv); /*** - * hacky trick to make sure that we send the HNA information via + * hacky trick to make sure that we send the TT information via * our new primary interface */ - atomic_set(&bat_priv->hna_local_changed, 1); + atomic_set(&bat_priv->tt_local_changed, 1); } static bool hardif_is_iface_up(struct hard_iface *hard_iface) @@ -339,7 +339,7 @@ int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name) batman_packet->flags = 0; batman_packet->ttl = 2; batman_packet->tq = TQ_MAX_VALUE; - batman_packet->num_hna = 0; + batman_packet->num_tt = 0; hard_iface->if_num = bat_priv->num_ifaces; bat_priv->num_ifaces++; diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 7edf8d719e15..0a7cee0076f4 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -84,8 +84,8 @@ int mesh_init(struct net_device *soft_iface) spin_lock_init(&bat_priv->forw_bat_list_lock); spin_lock_init(&bat_priv->forw_bcast_list_lock); - spin_lock_init(&bat_priv->hna_lhash_lock); - spin_lock_init(&bat_priv->hna_ghash_lock); + spin_lock_init(&bat_priv->tt_lhash_lock); + spin_lock_init(&bat_priv->tt_ghash_lock); spin_lock_init(&bat_priv->gw_list_lock); spin_lock_init(&bat_priv->vis_hash_lock); spin_lock_init(&bat_priv->vis_list_lock); @@ -100,13 +100,13 @@ int mesh_init(struct net_device *soft_iface) if (originator_init(bat_priv) < 1) goto err; - if (hna_local_init(bat_priv) < 1) + if (tt_local_init(bat_priv) < 1) goto err; - if (hna_global_init(bat_priv) < 1) + if (tt_global_init(bat_priv) < 1) goto err; - hna_local_add(soft_iface, soft_iface->dev_addr); + tt_local_add(soft_iface, soft_iface->dev_addr); if (vis_init(bat_priv) < 1) goto err; @@ -137,8 +137,8 @@ void mesh_free(struct net_device *soft_iface) gw_node_purge(bat_priv); originator_free(bat_priv); - hna_local_free(bat_priv); - hna_global_free(bat_priv); + tt_local_free(bat_priv); + tt_global_free(bat_priv); softif_neigh_purge(bat_priv); diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index ace72852ed7b..9ef6ef9b1e18 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -39,7 +39,7 @@ #define PURGE_TIMEOUT 200 /* purge originators after time in seconds if no * valid packet comes in -> TODO: check * influence on TQ_LOCAL_WINDOW_SIZE */ -#define LOCAL_HNA_TIMEOUT 3600 /* in seconds */ +#define TT_LOCAL_TIMEOUT 3600 /* in seconds */ #define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator * messages in squence numbers (should be a @@ -89,7 +89,7 @@ #define DBG_BATMAN 1 /* all messages related to routing / flooding / * broadcasting / etc */ -#define DBG_ROUTES 2 /* route or hna added / changed / deleted */ +#define DBG_ROUTES 2 /* route or tt entry added / changed / deleted */ #define DBG_ALL 3 diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 51af91b7a35b..080ec88330a3 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -142,7 +142,7 @@ static void orig_node_free_rcu(struct rcu_head *rcu) spin_unlock_bh(&orig_node->neigh_list_lock); frag_list_free(&orig_node->frag_list); - hna_global_del_orig(orig_node->bat_priv, orig_node, + tt_global_del_orig(orig_node->bat_priv, orig_node, "originator timed out"); kfree(orig_node->bcast_own); @@ -220,7 +220,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr) orig_node->bat_priv = bat_priv; memcpy(orig_node->orig, addr, ETH_ALEN); orig_node->router = NULL; - orig_node->hna_buff = NULL; + orig_node->tt_buff = NULL; orig_node->bcast_seqno_reset = jiffies - 1 - msecs_to_jiffies(RESET_PROTECTION_MS); orig_node->batman_seqno_reset = jiffies - 1 @@ -331,8 +331,8 @@ static bool purge_orig_node(struct bat_priv *bat_priv, &best_neigh_node)) { update_routes(bat_priv, orig_node, best_neigh_node, - orig_node->hna_buff, - orig_node->hna_buff_len); + orig_node->tt_buff, + orig_node->tt_buff_len); } } diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index e7571879af3f..c225c3acc55f 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@ -61,7 +61,7 @@ struct batman_packet { uint8_t orig[6]; uint8_t prev_sender[6]; uint8_t ttl; - uint8_t num_hna; + uint8_t num_tt; uint8_t gw_flags; /* flags related to gateway class */ uint8_t align; } __packed; diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index d8cde2b8d1cf..7648b92aec47 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -64,28 +64,28 @@ void slide_own_bcast_window(struct hard_iface *hard_iface) } } -static void update_HNA(struct bat_priv *bat_priv, struct orig_node *orig_node, - unsigned char *hna_buff, int hna_buff_len) +static void update_TT(struct bat_priv *bat_priv, struct orig_node *orig_node, + unsigned char *tt_buff, int tt_buff_len) { - if ((hna_buff_len != orig_node->hna_buff_len) || - ((hna_buff_len > 0) && - (orig_node->hna_buff_len > 0) && - (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) { - - if (orig_node->hna_buff_len > 0) - hna_global_del_orig(bat_priv, orig_node, - "originator changed hna"); - - if ((hna_buff_len > 0) && (hna_buff)) - hna_global_add_orig(bat_priv, orig_node, - hna_buff, hna_buff_len); + if ((tt_buff_len != orig_node->tt_buff_len) || + ((tt_buff_len > 0) && + (orig_node->tt_buff_len > 0) && + (memcmp(orig_node->tt_buff, tt_buff, tt_buff_len) != 0))) { + + if (orig_node->tt_buff_len > 0) + tt_global_del_orig(bat_priv, orig_node, + "originator changed tt"); + + if ((tt_buff_len > 0) && (tt_buff)) + tt_global_add_orig(bat_priv, orig_node, + tt_buff, tt_buff_len); } } static void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, struct neigh_node *neigh_node, - unsigned char *hna_buff, int hna_buff_len) + unsigned char *tt_buff, int tt_buff_len) { struct neigh_node *curr_router; @@ -96,7 +96,7 @@ static void update_route(struct bat_priv *bat_priv, bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", orig_node->orig); - hna_global_del_orig(bat_priv, orig_node, + tt_global_del_orig(bat_priv, orig_node, "originator timed out"); /* route added */ @@ -105,8 +105,8 @@ static void update_route(struct bat_priv *bat_priv, bat_dbg(DBG_ROUTES, bat_priv, "Adding route towards: %pM (via %pM)\n", orig_node->orig, neigh_node->addr); - hna_global_add_orig(bat_priv, orig_node, - hna_buff, hna_buff_len); + tt_global_add_orig(bat_priv, orig_node, + tt_buff, tt_buff_len); /* route changed */ } else { @@ -135,8 +135,8 @@ static void update_route(struct bat_priv *bat_priv, void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, - struct neigh_node *neigh_node, unsigned char *hna_buff, - int hna_buff_len) + struct neigh_node *neigh_node, unsigned char *tt_buff, + int tt_buff_len) { struct neigh_node *router = NULL; @@ -147,10 +147,10 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, if (router != neigh_node) update_route(bat_priv, orig_node, neigh_node, - hna_buff, hna_buff_len); - /* may be just HNA changed */ + tt_buff, tt_buff_len); + /* may be just TT changed */ else - update_HNA(bat_priv, orig_node, hna_buff, hna_buff_len); + update_TT(bat_priv, orig_node, tt_buff, tt_buff_len); out: if (router) @@ -387,14 +387,14 @@ static void update_orig(struct bat_priv *bat_priv, struct ethhdr *ethhdr, struct batman_packet *batman_packet, struct hard_iface *if_incoming, - unsigned char *hna_buff, int hna_buff_len, + unsigned char *tt_buff, int tt_buff_len, char is_duplicate) { struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; struct neigh_node *router = NULL; struct orig_node *orig_node_tmp; struct hlist_node *node; - int tmp_hna_buff_len; + int tmp_tt_buff_len; uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " @@ -459,18 +459,18 @@ static void update_orig(struct bat_priv *bat_priv, bonding_candidate_add(orig_node, neigh_node); - tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ? - batman_packet->num_hna * ETH_ALEN : hna_buff_len); + tmp_tt_buff_len = (tt_buff_len > batman_packet->num_tt * ETH_ALEN ? + batman_packet->num_tt * ETH_ALEN : tt_buff_len); /* if this neighbor already is our next hop there is nothing * to change */ router = orig_node_get_router(orig_node); if (router == neigh_node) - goto update_hna; + goto update_tt; /* if this neighbor does not offer a better TQ we won't consider it */ if (router && (router->tq_avg > neigh_node->tq_avg)) - goto update_hna; + goto update_tt; /* if the TQ is the same and the link not more symetric we * won't consider it either */ @@ -488,16 +488,16 @@ static void update_orig(struct bat_priv *bat_priv, spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); if (bcast_own_sum_orig >= bcast_own_sum_neigh) - goto update_hna; + goto update_tt; } update_routes(bat_priv, orig_node, neigh_node, - hna_buff, tmp_hna_buff_len); + tt_buff, tmp_tt_buff_len); goto update_gw; -update_hna: +update_tt: update_routes(bat_priv, orig_node, router, - hna_buff, tmp_hna_buff_len); + tt_buff, tmp_tt_buff_len); update_gw: if (orig_node->gw_flags != batman_packet->gw_flags) @@ -621,7 +621,7 @@ out: void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, - unsigned char *hna_buff, int hna_buff_len, + unsigned char *tt_buff, int tt_buff_len, struct hard_iface *if_incoming) { struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); @@ -818,14 +818,14 @@ void receive_bat_packet(struct ethhdr *ethhdr, ((orig_node->last_real_seqno == batman_packet->seqno) && (orig_node->last_ttl - 3 <= batman_packet->ttl)))) update_orig(bat_priv, orig_node, ethhdr, batman_packet, - if_incoming, hna_buff, hna_buff_len, is_duplicate); + if_incoming, tt_buff, tt_buff_len, is_duplicate); /* is single hop (direct) neighbor */ if (is_single_hop_neigh) { /* mark direct link on incoming interface */ schedule_forward_packet(orig_node, ethhdr, batman_packet, - 1, hna_buff_len, if_incoming); + 1, tt_buff_len, if_incoming); bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " "rebroadcast neighbor packet with direct link flag\n"); @@ -848,7 +848,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: rebroadcast originator packet\n"); schedule_forward_packet(orig_node, ethhdr, batman_packet, - 0, hna_buff_len, if_incoming); + 0, tt_buff_len, if_incoming); out_neigh: if ((orig_neigh_node) && (!is_single_hop_neigh)) diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h index b5a064c88a4f..870f29842b28 100644 --- a/net/batman-adv/routing.h +++ b/net/batman-adv/routing.h @@ -25,11 +25,11 @@ void slide_own_bcast_window(struct hard_iface *hard_iface); void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, - unsigned char *hna_buff, int hna_buff_len, + unsigned char *tt_buff, int tt_buff_len, struct hard_iface *if_incoming); void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, - struct neigh_node *neigh_node, unsigned char *hna_buff, - int hna_buff_len); + struct neigh_node *neigh_node, unsigned char *tt_buff, + int tt_buff_len); int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if); int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 02b541a6dfef..f30d0c69ccbb 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -121,7 +121,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet, /* adjust all flags and log packets */ while (aggregated_packet(buff_pos, forw_packet->packet_len, - batman_packet->num_hna)) { + batman_packet->num_tt)) { /* we might have aggregated direct link packets with an * ordinary base packet */ @@ -146,7 +146,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet, hard_iface->net_dev->dev_addr); buff_pos += sizeof(struct batman_packet) + - (batman_packet->num_hna * ETH_ALEN); + (batman_packet->num_tt * ETH_ALEN); packet_num++; batman_packet = (struct batman_packet *) (forw_packet->skb->data + buff_pos); @@ -222,7 +222,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv, struct batman_packet *batman_packet; new_len = sizeof(struct batman_packet) + - (bat_priv->num_local_hna * ETH_ALEN); + (bat_priv->num_local_tt * ETH_ALEN); new_buff = kmalloc(new_len, GFP_ATOMIC); /* keep old buffer if kmalloc should fail */ @@ -231,7 +231,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv, sizeof(struct batman_packet)); batman_packet = (struct batman_packet *)new_buff; - batman_packet->num_hna = hna_local_fill_buffer(bat_priv, + batman_packet->num_tt = tt_local_fill_buffer(bat_priv, new_buff + sizeof(struct batman_packet), new_len - sizeof(struct batman_packet)); @@ -266,8 +266,8 @@ void schedule_own_packet(struct hard_iface *hard_iface) if (hard_iface->if_status == IF_TO_BE_ACTIVATED) hard_iface->if_status = IF_ACTIVE; - /* if local hna has changed and interface is a primary interface */ - if ((atomic_read(&bat_priv->hna_local_changed)) && + /* if local tt has changed and interface is a primary interface */ + if ((atomic_read(&bat_priv->tt_local_changed)) && (hard_iface == primary_if)) rebuild_batman_packet(bat_priv, hard_iface); @@ -309,7 +309,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) void schedule_forward_packet(struct orig_node *orig_node, struct ethhdr *ethhdr, struct batman_packet *batman_packet, - uint8_t directlink, int hna_buff_len, + uint8_t directlink, int tt_buff_len, struct hard_iface *if_incoming) { struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); @@ -369,7 +369,7 @@ void schedule_forward_packet(struct orig_node *orig_node, send_time = forward_send_time(); add_bat_packet_to_list(bat_priv, (unsigned char *)batman_packet, - sizeof(struct batman_packet) + hna_buff_len, + sizeof(struct batman_packet) + tt_buff_len, if_incoming, 0, send_time); } diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h index 7b2ff19c05e7..247172d71e4b 100644 --- a/net/batman-adv/send.h +++ b/net/batman-adv/send.h @@ -29,7 +29,7 @@ void schedule_own_packet(struct hard_iface *hard_iface); void schedule_forward_packet(struct orig_node *orig_node, struct ethhdr *ethhdr, struct batman_packet *batman_packet, - uint8_t directlink, int hna_buff_len, + uint8_t directlink, int tt_buff_len, struct hard_iface *if_outgoing); int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb); void send_outstanding_bat_packet(struct work_struct *work); diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 9301e21052e7..d6aaf9fa64d4 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -543,11 +543,11 @@ static int interface_set_mac_addr(struct net_device *dev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - /* only modify hna-table if it has been initialised before */ + /* only modify transtable if it has been initialised before */ if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { - hna_local_remove(bat_priv, dev->dev_addr, + tt_local_remove(bat_priv, dev->dev_addr, "mac address changed"); - hna_local_add(dev, addr->sa_data); + tt_local_add(dev, addr->sa_data); } memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); @@ -605,7 +605,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) goto dropped; /* TODO: check this for locks */ - hna_local_add(soft_iface, ethhdr->h_source); + tt_local_add(soft_iface, ethhdr->h_source); if (is_multicast_ether_addr(ethhdr->h_dest)) { ret = gw_is_target(bat_priv, skb); @@ -843,7 +843,7 @@ struct net_device *softif_create(char *name) atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); atomic_set(&bat_priv->bcast_seqno, 1); - atomic_set(&bat_priv->hna_local_changed, 0); + atomic_set(&bat_priv->tt_local_changed, 0); bat_priv->primary_if = NULL; bat_priv->num_ifaces = 0; diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index f931830d630e..7b729660cbfd 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -26,40 +26,40 @@ #include "hash.h" #include "originator.h" -static void hna_local_purge(struct work_struct *work); -static void _hna_global_del_orig(struct bat_priv *bat_priv, - struct hna_global_entry *hna_global_entry, +static void tt_local_purge(struct work_struct *work); +static void _tt_global_del_orig(struct bat_priv *bat_priv, + struct tt_global_entry *tt_global_entry, char *message); /* returns 1 if they are the same mac addr */ -static int compare_lhna(struct hlist_node *node, void *data2) +static int compare_ltt(struct hlist_node *node, void *data2) { - void *data1 = container_of(node, struct hna_local_entry, hash_entry); + void *data1 = container_of(node, struct tt_local_entry, hash_entry); return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); } /* returns 1 if they are the same mac addr */ -static int compare_ghna(struct hlist_node *node, void *data2) +static int compare_gtt(struct hlist_node *node, void *data2) { - void *data1 = container_of(node, struct hna_global_entry, hash_entry); + void *data1 = container_of(node, struct tt_global_entry, hash_entry); return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); } -static void hna_local_start_timer(struct bat_priv *bat_priv) +static void tt_local_start_timer(struct bat_priv *bat_priv) { - INIT_DELAYED_WORK(&bat_priv->hna_work, hna_local_purge); - queue_delayed_work(bat_event_workqueue, &bat_priv->hna_work, 10 * HZ); + INIT_DELAYED_WORK(&bat_priv->tt_work, tt_local_purge); + queue_delayed_work(bat_event_workqueue, &bat_priv->tt_work, 10 * HZ); } -static struct hna_local_entry *hna_local_hash_find(struct bat_priv *bat_priv, +static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv, void *data) { - struct hashtable_t *hash = bat_priv->hna_local_hash; + struct hashtable_t *hash = bat_priv->tt_local_hash; struct hlist_head *head; struct hlist_node *node; - struct hna_local_entry *hna_local_entry, *hna_local_entry_tmp = NULL; + struct tt_local_entry *tt_local_entry, *tt_local_entry_tmp = NULL; int index; if (!hash) @@ -69,26 +69,26 @@ static struct hna_local_entry *hna_local_hash_find(struct bat_priv *bat_priv, head = &hash->table[index]; rcu_read_lock(); - hlist_for_each_entry_rcu(hna_local_entry, node, head, hash_entry) { - if (!compare_eth(hna_local_entry, data)) + hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { + if (!compare_eth(tt_local_entry, data)) continue; - hna_local_entry_tmp = hna_local_entry; + tt_local_entry_tmp = tt_local_entry; break; } rcu_read_unlock(); - return hna_local_entry_tmp; + return tt_local_entry_tmp; } -static struct hna_global_entry *hna_global_hash_find(struct bat_priv *bat_priv, +static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv, void *data) { - struct hashtable_t *hash = bat_priv->hna_global_hash; + struct hashtable_t *hash = bat_priv->tt_global_hash; struct hlist_head *head; struct hlist_node *node; - struct hna_global_entry *hna_global_entry; - struct hna_global_entry *hna_global_entry_tmp = NULL; + struct tt_global_entry *tt_global_entry; + struct tt_global_entry *tt_global_entry_tmp = NULL; int index; if (!hash) @@ -98,125 +98,125 @@ static struct hna_global_entry *hna_global_hash_find(struct bat_priv *bat_priv, head = &hash->table[index]; rcu_read_lock(); - hlist_for_each_entry_rcu(hna_global_entry, node, head, hash_entry) { - if (!compare_eth(hna_global_entry, data)) + hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) { + if (!compare_eth(tt_global_entry, data)) continue; - hna_global_entry_tmp = hna_global_entry; + tt_global_entry_tmp = tt_global_entry; break; } rcu_read_unlock(); - return hna_global_entry_tmp; + return tt_global_entry_tmp; } -int hna_local_init(struct bat_priv *bat_priv) +int tt_local_init(struct bat_priv *bat_priv) { - if (bat_priv->hna_local_hash) + if (bat_priv->tt_local_hash) return 1; - bat_priv->hna_local_hash = hash_new(1024); + bat_priv->tt_local_hash = hash_new(1024); - if (!bat_priv->hna_local_hash) + if (!bat_priv->tt_local_hash) return 0; - atomic_set(&bat_priv->hna_local_changed, 0); - hna_local_start_timer(bat_priv); + atomic_set(&bat_priv->tt_local_changed, 0); + tt_local_start_timer(bat_priv); return 1; } -void hna_local_add(struct net_device *soft_iface, uint8_t *addr) +void tt_local_add(struct net_device *soft_iface, uint8_t *addr) { struct bat_priv *bat_priv = netdev_priv(soft_iface); - struct hna_local_entry *hna_local_entry; - struct hna_global_entry *hna_global_entry; + struct tt_local_entry *tt_local_entry; + struct tt_global_entry *tt_global_entry; int required_bytes; - spin_lock_bh(&bat_priv->hna_lhash_lock); - hna_local_entry = hna_local_hash_find(bat_priv, addr); - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); + tt_local_entry = tt_local_hash_find(bat_priv, addr); + spin_unlock_bh(&bat_priv->tt_lhash_lock); - if (hna_local_entry) { - hna_local_entry->last_seen = jiffies; + if (tt_local_entry) { + tt_local_entry->last_seen = jiffies; return; } /* only announce as many hosts as possible in the batman-packet and - space in batman_packet->num_hna That also should give a limit to + space in batman_packet->num_tt That also should give a limit to MAC-flooding. */ - required_bytes = (bat_priv->num_local_hna + 1) * ETH_ALEN; + required_bytes = (bat_priv->num_local_tt + 1) * ETH_ALEN; required_bytes += BAT_PACKET_LEN; if ((required_bytes > ETH_DATA_LEN) || (atomic_read(&bat_priv->aggregated_ogms) && required_bytes > MAX_AGGREGATION_BYTES) || - (bat_priv->num_local_hna + 1 > 255)) { + (bat_priv->num_local_tt + 1 > 255)) { bat_dbg(DBG_ROUTES, bat_priv, - "Can't add new local hna entry (%pM): " - "number of local hna entries exceeds packet size\n", + "Can't add new local tt entry (%pM): " + "number of local tt entries exceeds packet size\n", addr); return; } bat_dbg(DBG_ROUTES, bat_priv, - "Creating new local hna entry: %pM\n", addr); + "Creating new local tt entry: %pM\n", addr); - hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC); - if (!hna_local_entry) + tt_local_entry = kmalloc(sizeof(struct tt_local_entry), GFP_ATOMIC); + if (!tt_local_entry) return; - memcpy(hna_local_entry->addr, addr, ETH_ALEN); - hna_local_entry->last_seen = jiffies; + memcpy(tt_local_entry->addr, addr, ETH_ALEN); + tt_local_entry->last_seen = jiffies; /* the batman interface mac address should never be purged */ if (compare_eth(addr, soft_iface->dev_addr)) - hna_local_entry->never_purge = 1; + tt_local_entry->never_purge = 1; else - hna_local_entry->never_purge = 0; + tt_local_entry->never_purge = 0; - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); - hash_add(bat_priv->hna_local_hash, compare_lhna, choose_orig, - hna_local_entry, &hna_local_entry->hash_entry); - bat_priv->num_local_hna++; - atomic_set(&bat_priv->hna_local_changed, 1); + hash_add(bat_priv->tt_local_hash, compare_ltt, choose_orig, + tt_local_entry, &tt_local_entry->hash_entry); + bat_priv->num_local_tt++; + atomic_set(&bat_priv->tt_local_changed, 1); - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); /* remove address from global hash if present */ - spin_lock_bh(&bat_priv->hna_ghash_lock); + spin_lock_bh(&bat_priv->tt_ghash_lock); - hna_global_entry = hna_global_hash_find(bat_priv, addr); + tt_global_entry = tt_global_hash_find(bat_priv, addr); - if (hna_global_entry) - _hna_global_del_orig(bat_priv, hna_global_entry, - "local hna received"); + if (tt_global_entry) + _tt_global_del_orig(bat_priv, tt_global_entry, + "local tt received"); - spin_unlock_bh(&bat_priv->hna_ghash_lock); + spin_unlock_bh(&bat_priv->tt_ghash_lock); } -int hna_local_fill_buffer(struct bat_priv *bat_priv, +int tt_local_fill_buffer(struct bat_priv *bat_priv, unsigned char *buff, int buff_len) { - struct hashtable_t *hash = bat_priv->hna_local_hash; - struct hna_local_entry *hna_local_entry; + struct hashtable_t *hash = bat_priv->tt_local_hash; + struct tt_local_entry *tt_local_entry; struct hlist_node *node; struct hlist_head *head; int i, count = 0; - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; rcu_read_lock(); - hlist_for_each_entry_rcu(hna_local_entry, node, + hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { if (buff_len < (count + 1) * ETH_ALEN) break; - memcpy(buff + (count * ETH_ALEN), hna_local_entry->addr, + memcpy(buff + (count * ETH_ALEN), tt_local_entry->addr, ETH_ALEN); count++; @@ -224,20 +224,20 @@ int hna_local_fill_buffer(struct bat_priv *bat_priv, rcu_read_unlock(); } - /* if we did not get all new local hnas see you next time ;-) */ - if (count == bat_priv->num_local_hna) - atomic_set(&bat_priv->hna_local_changed, 0); + /* if we did not get all new local tts see you next time ;-) */ + if (count == bat_priv->num_local_tt) + atomic_set(&bat_priv->tt_local_changed, 0); - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); return count; } -int hna_local_seq_print_text(struct seq_file *seq, void *offset) +int tt_local_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); - struct hashtable_t *hash = bat_priv->hna_local_hash; - struct hna_local_entry *hna_local_entry; + struct hashtable_t *hash = bat_priv->tt_local_hash; + struct tt_local_entry *tt_local_entry; struct hard_iface *primary_if; struct hlist_node *node; struct hlist_head *head; @@ -261,10 +261,10 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) } seq_printf(seq, "Locally retrieved addresses (from %s) " - "announced via HNA:\n", + "announced via TT:\n", net_dev->name); - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); buf_size = 1; /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */ @@ -279,7 +279,7 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); ret = -ENOMEM; goto out; } @@ -291,15 +291,15 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) head = &hash->table[i]; rcu_read_lock(); - hlist_for_each_entry_rcu(hna_local_entry, node, + hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { pos += snprintf(buff + pos, 22, " * %pM\n", - hna_local_entry->addr); + tt_local_entry->addr); } rcu_read_unlock(); } - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); seq_printf(seq, "%s", buff); kfree(buff); @@ -309,180 +309,180 @@ out: return ret; } -static void _hna_local_del(struct hlist_node *node, void *arg) +static void _tt_local_del(struct hlist_node *node, void *arg) { struct bat_priv *bat_priv = (struct bat_priv *)arg; - void *data = container_of(node, struct hna_local_entry, hash_entry); + void *data = container_of(node, struct tt_local_entry, hash_entry); kfree(data); - bat_priv->num_local_hna--; - atomic_set(&bat_priv->hna_local_changed, 1); + bat_priv->num_local_tt--; + atomic_set(&bat_priv->tt_local_changed, 1); } -static void hna_local_del(struct bat_priv *bat_priv, - struct hna_local_entry *hna_local_entry, +static void tt_local_del(struct bat_priv *bat_priv, + struct tt_local_entry *tt_local_entry, char *message) { - bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n", - hna_local_entry->addr, message); + bat_dbg(DBG_ROUTES, bat_priv, "Deleting local tt entry (%pM): %s\n", + tt_local_entry->addr, message); - hash_remove(bat_priv->hna_local_hash, compare_lhna, choose_orig, - hna_local_entry->addr); - _hna_local_del(&hna_local_entry->hash_entry, bat_priv); + hash_remove(bat_priv->tt_local_hash, compare_ltt, choose_orig, + tt_local_entry->addr); + _tt_local_del(&tt_local_entry->hash_entry, bat_priv); } -void hna_local_remove(struct bat_priv *bat_priv, +void tt_local_remove(struct bat_priv *bat_priv, uint8_t *addr, char *message) { - struct hna_local_entry *hna_local_entry; + struct tt_local_entry *tt_local_entry; - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); - hna_local_entry = hna_local_hash_find(bat_priv, addr); + tt_local_entry = tt_local_hash_find(bat_priv, addr); - if (hna_local_entry) - hna_local_del(bat_priv, hna_local_entry, message); + if (tt_local_entry) + tt_local_del(bat_priv, tt_local_entry, message); - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); } -static void hna_local_purge(struct work_struct *work) +static void tt_local_purge(struct work_struct *work) { struct delayed_work *delayed_work = container_of(work, struct delayed_work, work); struct bat_priv *bat_priv = - container_of(delayed_work, struct bat_priv, hna_work); - struct hashtable_t *hash = bat_priv->hna_local_hash; - struct hna_local_entry *hna_local_entry; + container_of(delayed_work, struct bat_priv, tt_work); + struct hashtable_t *hash = bat_priv->tt_local_hash; + struct tt_local_entry *tt_local_entry; struct hlist_node *node, *node_tmp; struct hlist_head *head; unsigned long timeout; int i; - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; - hlist_for_each_entry_safe(hna_local_entry, node, node_tmp, + hlist_for_each_entry_safe(tt_local_entry, node, node_tmp, head, hash_entry) { - if (hna_local_entry->never_purge) + if (tt_local_entry->never_purge) continue; - timeout = hna_local_entry->last_seen; - timeout += LOCAL_HNA_TIMEOUT * HZ; + timeout = tt_local_entry->last_seen; + timeout += TT_LOCAL_TIMEOUT * HZ; if (time_before(jiffies, timeout)) continue; - hna_local_del(bat_priv, hna_local_entry, + tt_local_del(bat_priv, tt_local_entry, "address timed out"); } } - spin_unlock_bh(&bat_priv->hna_lhash_lock); - hna_local_start_timer(bat_priv); + spin_unlock_bh(&bat_priv->tt_lhash_lock); + tt_local_start_timer(bat_priv); } -void hna_local_free(struct bat_priv *bat_priv) +void tt_local_free(struct bat_priv *bat_priv) { - if (!bat_priv->hna_local_hash) + if (!bat_priv->tt_local_hash) return; - cancel_delayed_work_sync(&bat_priv->hna_work); - hash_delete(bat_priv->hna_local_hash, _hna_local_del, bat_priv); - bat_priv->hna_local_hash = NULL; + cancel_delayed_work_sync(&bat_priv->tt_work); + hash_delete(bat_priv->tt_local_hash, _tt_local_del, bat_priv); + bat_priv->tt_local_hash = NULL; } -int hna_global_init(struct bat_priv *bat_priv) +int tt_global_init(struct bat_priv *bat_priv) { - if (bat_priv->hna_global_hash) + if (bat_priv->tt_global_hash) return 1; - bat_priv->hna_global_hash = hash_new(1024); + bat_priv->tt_global_hash = hash_new(1024); - if (!bat_priv->hna_global_hash) + if (!bat_priv->tt_global_hash) return 0; return 1; } -void hna_global_add_orig(struct bat_priv *bat_priv, +void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, - unsigned char *hna_buff, int hna_buff_len) + unsigned char *tt_buff, int tt_buff_len) { - struct hna_global_entry *hna_global_entry; - struct hna_local_entry *hna_local_entry; - int hna_buff_count = 0; - unsigned char *hna_ptr; + struct tt_global_entry *tt_global_entry; + struct tt_local_entry *tt_local_entry; + int tt_buff_count = 0; + unsigned char *tt_ptr; - while ((hna_buff_count + 1) * ETH_ALEN <= hna_buff_len) { - spin_lock_bh(&bat_priv->hna_ghash_lock); + while ((tt_buff_count + 1) * ETH_ALEN <= tt_buff_len) { + spin_lock_bh(&bat_priv->tt_ghash_lock); - hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); - hna_global_entry = hna_global_hash_find(bat_priv, hna_ptr); + tt_ptr = tt_buff + (tt_buff_count * ETH_ALEN); + tt_global_entry = tt_global_hash_find(bat_priv, tt_ptr); - if (!hna_global_entry) { - spin_unlock_bh(&bat_priv->hna_ghash_lock); + if (!tt_global_entry) { + spin_unlock_bh(&bat_priv->tt_ghash_lock); - hna_global_entry = - kmalloc(sizeof(struct hna_global_entry), + tt_global_entry = + kmalloc(sizeof(struct tt_global_entry), GFP_ATOMIC); - if (!hna_global_entry) + if (!tt_global_entry) break; - memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN); + memcpy(tt_global_entry->addr, tt_ptr, ETH_ALEN); bat_dbg(DBG_ROUTES, bat_priv, - "Creating new global hna entry: " + "Creating new global tt entry: " "%pM (via %pM)\n", - hna_global_entry->addr, orig_node->orig); + tt_global_entry->addr, orig_node->orig); - spin_lock_bh(&bat_priv->hna_ghash_lock); - hash_add(bat_priv->hna_global_hash, compare_ghna, - choose_orig, hna_global_entry, - &hna_global_entry->hash_entry); + spin_lock_bh(&bat_priv->tt_ghash_lock); + hash_add(bat_priv->tt_global_hash, compare_gtt, + choose_orig, tt_global_entry, + &tt_global_entry->hash_entry); } - hna_global_entry->orig_node = orig_node; - spin_unlock_bh(&bat_priv->hna_ghash_lock); + tt_global_entry->orig_node = orig_node; + spin_unlock_bh(&bat_priv->tt_ghash_lock); /* remove address from local hash if present */ - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); - hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); - hna_local_entry = hna_local_hash_find(bat_priv, hna_ptr); + tt_ptr = tt_buff + (tt_buff_count * ETH_ALEN); + tt_local_entry = tt_local_hash_find(bat_priv, tt_ptr); - if (hna_local_entry) - hna_local_del(bat_priv, hna_local_entry, - "global hna received"); + if (tt_local_entry) + tt_local_del(bat_priv, tt_local_entry, + "global tt received"); - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); - hna_buff_count++; + tt_buff_count++; } /* initialize, and overwrite if malloc succeeds */ - orig_node->hna_buff = NULL; - orig_node->hna_buff_len = 0; - - if (hna_buff_len > 0) { - orig_node->hna_buff = kmalloc(hna_buff_len, GFP_ATOMIC); - if (orig_node->hna_buff) { - memcpy(orig_node->hna_buff, hna_buff, hna_buff_len); - orig_node->hna_buff_len = hna_buff_len; + orig_node->tt_buff = NULL; + orig_node->tt_buff_len = 0; + + if (tt_buff_len > 0) { + orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC); + if (orig_node->tt_buff) { + memcpy(orig_node->tt_buff, tt_buff, tt_buff_len); + orig_node->tt_buff_len = tt_buff_len; } } } -int hna_global_seq_print_text(struct seq_file *seq, void *offset) +int tt_global_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); - struct hashtable_t *hash = bat_priv->hna_global_hash; - struct hna_global_entry *hna_global_entry; + struct hashtable_t *hash = bat_priv->tt_global_hash; + struct tt_global_entry *tt_global_entry; struct hard_iface *primary_if; struct hlist_node *node; struct hlist_head *head; @@ -505,10 +505,11 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) goto out; } - seq_printf(seq, "Globally announced HNAs received via the mesh %s\n", + seq_printf(seq, + "Globally announced TT entries received via the mesh %s\n", net_dev->name); - spin_lock_bh(&bat_priv->hna_ghash_lock); + spin_lock_bh(&bat_priv->tt_ghash_lock); buf_size = 1; /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/ @@ -523,7 +524,7 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { - spin_unlock_bh(&bat_priv->hna_ghash_lock); + spin_unlock_bh(&bat_priv->tt_ghash_lock); ret = -ENOMEM; goto out; } @@ -534,17 +535,17 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) head = &hash->table[i]; rcu_read_lock(); - hlist_for_each_entry_rcu(hna_global_entry, node, + hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) { pos += snprintf(buff + pos, 44, " * %pM via %pM\n", - hna_global_entry->addr, - hna_global_entry->orig_node->orig); + tt_global_entry->addr, + tt_global_entry->orig_node->orig); } rcu_read_unlock(); } - spin_unlock_bh(&bat_priv->hna_ghash_lock); + spin_unlock_bh(&bat_priv->tt_ghash_lock); seq_printf(seq, "%s", buff); kfree(buff); @@ -554,84 +555,84 @@ out: return ret; } -static void _hna_global_del_orig(struct bat_priv *bat_priv, - struct hna_global_entry *hna_global_entry, +static void _tt_global_del_orig(struct bat_priv *bat_priv, + struct tt_global_entry *tt_global_entry, char *message) { bat_dbg(DBG_ROUTES, bat_priv, - "Deleting global hna entry %pM (via %pM): %s\n", - hna_global_entry->addr, hna_global_entry->orig_node->orig, + "Deleting global tt entry %pM (via %pM): %s\n", + tt_global_entry->addr, tt_global_entry->orig_node->orig, message); - hash_remove(bat_priv->hna_global_hash, compare_ghna, choose_orig, - hna_global_entry->addr); - kfree(hna_global_entry); + hash_remove(bat_priv->tt_global_hash, compare_gtt, choose_orig, + tt_global_entry->addr); + kfree(tt_global_entry); } -void hna_global_del_orig(struct bat_priv *bat_priv, +void tt_global_del_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, char *message) { - struct hna_global_entry *hna_global_entry; - int hna_buff_count = 0; - unsigned char *hna_ptr; + struct tt_global_entry *tt_global_entry; + int tt_buff_count = 0; + unsigned char *tt_ptr; - if (orig_node->hna_buff_len == 0) + if (orig_node->tt_buff_len == 0) return; - spin_lock_bh(&bat_priv->hna_ghash_lock); + spin_lock_bh(&bat_priv->tt_ghash_lock); - while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) { - hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN); - hna_global_entry = hna_global_hash_find(bat_priv, hna_ptr); + while ((tt_buff_count + 1) * ETH_ALEN <= orig_node->tt_buff_len) { + tt_ptr = orig_node->tt_buff + (tt_buff_count * ETH_ALEN); + tt_global_entry = tt_global_hash_find(bat_priv, tt_ptr); - if ((hna_global_entry) && - (hna_global_entry->orig_node == orig_node)) - _hna_global_del_orig(bat_priv, hna_global_entry, + if ((tt_global_entry) && + (tt_global_entry->orig_node == orig_node)) + _tt_global_del_orig(bat_priv, tt_global_entry, message); - hna_buff_count++; + tt_buff_count++; } - spin_unlock_bh(&bat_priv->hna_ghash_lock); + spin_unlock_bh(&bat_priv->tt_ghash_lock); - orig_node->hna_buff_len = 0; - kfree(orig_node->hna_buff); - orig_node->hna_buff = NULL; + orig_node->tt_buff_len = 0; + kfree(orig_node->tt_buff); + orig_node->tt_buff = NULL; } -static void hna_global_del(struct hlist_node *node, void *arg) +static void tt_global_del(struct hlist_node *node, void *arg) { - void *data = container_of(node, struct hna_global_entry, hash_entry); + void *data = container_of(node, struct tt_global_entry, hash_entry); kfree(data); } -void hna_global_free(struct bat_priv *bat_priv) +void tt_global_free(struct bat_priv *bat_priv) { - if (!bat_priv->hna_global_hash) + if (!bat_priv->tt_global_hash) return; - hash_delete(bat_priv->hna_global_hash, hna_global_del, NULL); - bat_priv->hna_global_hash = NULL; + hash_delete(bat_priv->tt_global_hash, tt_global_del, NULL); + bat_priv->tt_global_hash = NULL; } struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr) { - struct hna_global_entry *hna_global_entry; + struct tt_global_entry *tt_global_entry; struct orig_node *orig_node = NULL; - spin_lock_bh(&bat_priv->hna_ghash_lock); - hna_global_entry = hna_global_hash_find(bat_priv, addr); + spin_lock_bh(&bat_priv->tt_ghash_lock); + tt_global_entry = tt_global_hash_find(bat_priv, addr); - if (!hna_global_entry) + if (!tt_global_entry) goto out; - if (!atomic_inc_not_zero(&hna_global_entry->orig_node->refcount)) + if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount)) goto out; - orig_node = hna_global_entry->orig_node; + orig_node = tt_global_entry->orig_node; out: - spin_unlock_bh(&bat_priv->hna_ghash_lock); + spin_unlock_bh(&bat_priv->tt_ghash_lock); return orig_node; } diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index f19931ca1457..46152c38cc95 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h @@ -22,22 +22,22 @@ #ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ #define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ -int hna_local_init(struct bat_priv *bat_priv); -void hna_local_add(struct net_device *soft_iface, uint8_t *addr); -void hna_local_remove(struct bat_priv *bat_priv, +int tt_local_init(struct bat_priv *bat_priv); +void tt_local_add(struct net_device *soft_iface, uint8_t *addr); +void tt_local_remove(struct bat_priv *bat_priv, uint8_t *addr, char *message); -int hna_local_fill_buffer(struct bat_priv *bat_priv, +int tt_local_fill_buffer(struct bat_priv *bat_priv, unsigned char *buff, int buff_len); -int hna_local_seq_print_text(struct seq_file *seq, void *offset); -void hna_local_free(struct bat_priv *bat_priv); -int hna_global_init(struct bat_priv *bat_priv); -void hna_global_add_orig(struct bat_priv *bat_priv, +int tt_local_seq_print_text(struct seq_file *seq, void *offset); +void tt_local_free(struct bat_priv *bat_priv); +int tt_global_init(struct bat_priv *bat_priv); +void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, - unsigned char *hna_buff, int hna_buff_len); -int hna_global_seq_print_text(struct seq_file *seq, void *offset); -void hna_global_del_orig(struct bat_priv *bat_priv, + unsigned char *tt_buff, int tt_buff_len); +int tt_global_seq_print_text(struct seq_file *seq, void *offset); +void tt_global_del_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, char *message); -void hna_global_free(struct bat_priv *bat_priv); +void tt_global_free(struct bat_priv *bat_priv); struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr); #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 9ae507ab7bbe..6b6c32e01c54 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -75,8 +75,8 @@ struct orig_node { unsigned long batman_seqno_reset; uint8_t gw_flags; uint8_t flags; - unsigned char *hna_buff; - int16_t hna_buff_len; + unsigned char *tt_buff; + int16_t tt_buff_len; uint32_t last_real_seqno; uint8_t last_ttl; unsigned long bcast_bits[NUM_WORDS]; @@ -155,21 +155,21 @@ struct bat_priv { struct hlist_head softif_neigh_vids; struct list_head vis_send_list; struct hashtable_t *orig_hash; - struct hashtable_t *hna_local_hash; - struct hashtable_t *hna_global_hash; + struct hashtable_t *tt_local_hash; + struct hashtable_t *tt_global_hash; struct hashtable_t *vis_hash; spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ spinlock_t forw_bcast_list_lock; /* protects */ - spinlock_t hna_lhash_lock; /* protects hna_local_hash */ - spinlock_t hna_ghash_lock; /* protects hna_global_hash */ + spinlock_t tt_lhash_lock; /* protects tt_local_hash */ + spinlock_t tt_ghash_lock; /* protects tt_global_hash */ spinlock_t gw_list_lock; /* protects gw_list and curr_gw */ spinlock_t vis_hash_lock; /* protects vis_hash */ spinlock_t vis_list_lock; /* protects vis_info::recv_list */ spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */ spinlock_t softif_neigh_vid_lock; /* protects soft-interface vid list */ - int16_t num_local_hna; - atomic_t hna_local_changed; - struct delayed_work hna_work; + int16_t num_local_tt; + atomic_t tt_local_changed; + struct delayed_work tt_work; struct delayed_work orig_work; struct delayed_work vis_work; struct gw_node __rcu *curr_gw; /* rcu protected pointer */ @@ -192,14 +192,14 @@ struct socket_packet { struct icmp_packet_rr icmp_packet; }; -struct hna_local_entry { +struct tt_local_entry { uint8_t addr[ETH_ALEN]; unsigned long last_seen; char never_purge; struct hlist_node hash_entry; }; -struct hna_global_entry { +struct tt_global_entry { uint8_t addr[ETH_ALEN]; struct orig_node *orig_node; struct hlist_node hash_entry; @@ -262,7 +262,7 @@ struct vis_info { struct vis_info_entry { uint8_t src[ETH_ALEN]; uint8_t dest[ETH_ALEN]; - uint8_t quality; /* quality = 0 means HNA */ + uint8_t quality; /* quality = 0 client */ } __packed; struct recvlist_node { diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index b46cbf1507e4..19c3daf34ac6 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c @@ -300,7 +300,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) goto find_router; } - /* check for hna host - increases orig_node refcount */ + /* check for tt host - increases orig_node refcount */ orig_node = transtable_search(bat_priv, ethhdr->h_dest); find_router: diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index c8f571d3b5d4..c39f20cc1ba6 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c @@ -194,7 +194,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, { /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ if (primary && entry->quality == 0) - return sprintf(buff, "HNA %pM, ", entry->dest); + return sprintf(buff, "TT %pM, ", entry->dest); else if (compare_eth(entry->src, src)) return sprintf(buff, "TQ %pM %d, ", entry->dest, entry->quality); @@ -622,7 +622,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv) struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; struct vis_info_entry *entry; - struct hna_local_entry *hna_local_entry; + struct tt_local_entry *tt_local_entry; int best_tq = -1, i; info->first_seen = jiffies; @@ -678,29 +678,29 @@ next: rcu_read_unlock(); } - hash = bat_priv->hna_local_hash; + hash = bat_priv->tt_local_hash; - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; - hlist_for_each_entry(hna_local_entry, node, head, hash_entry) { + hlist_for_each_entry(tt_local_entry, node, head, hash_entry) { entry = (struct vis_info_entry *) skb_put(info->skb_packet, sizeof(*entry)); memset(entry->src, 0, ETH_ALEN); - memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN); - entry->quality = 0; /* 0 means HNA */ + memcpy(entry->dest, tt_local_entry->addr, ETH_ALEN); + entry->quality = 0; /* 0 means TT */ packet->entries++; if (vis_packet_full(info)) { - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); return 0; } } } - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); return 0; unlock: -- cgit v1.2.3-58-ga151 From 6e215fd8eb4930373d01da0fac16a0889804fac3 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 8 May 2011 12:45:45 +0200 Subject: batman-adv: Remove multiline comments from line ending It is slightly irritating that comments after a long line span over multiple lines without any code. It is easier to put them before the actual code and reduce the number of lines which the eye has to read. Signed-off-by: Sven Eckelmann --- net/batman-adv/main.h | 40 +++++++++++++++++++++------------------- net/batman-adv/packet.h | 3 +-- net/batman-adv/soft-interface.c | 4 ++-- net/batman-adv/types.h | 10 +++++----- 4 files changed, 29 insertions(+), 28 deletions(-) diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 9ef6ef9b1e18..148b49e02642 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -34,16 +34,18 @@ #define TQ_MAX_VALUE 255 #define JITTER 20 -#define TTL 50 /* Time To Live of broadcast messages */ -#define PURGE_TIMEOUT 200 /* purge originators after time in seconds if no - * valid packet comes in -> TODO: check - * influence on TQ_LOCAL_WINDOW_SIZE */ + /* Time To Live of broadcast messages */ +#define TTL 50 + +/* purge originators after time in seconds if no valid packet comes in + * -> TODO: check influence on TQ_LOCAL_WINDOW_SIZE */ +#define PURGE_TIMEOUT 200 #define TT_LOCAL_TIMEOUT 3600 /* in seconds */ -#define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator - * messages in squence numbers (should be a - * multiple of our word size) */ +/* sliding packet range of received originator messages in squence numbers + * (should be a multiple of our word size) */ +#define TQ_LOCAL_WINDOW_SIZE 64 #define TQ_GLOBAL_WINDOW_SIZE 5 #define TQ_LOCAL_BIDRECT_SEND_MINIMUM 1 #define TQ_LOCAL_BIDRECT_RECV_MINIMUM 1 @@ -55,21 +57,20 @@ #define VIS_INTERVAL 5000 /* 5 seconds */ -/* how much worse secondary interfaces may be to - * to be considered as bonding candidates */ - +/* how much worse secondary interfaces may be to be considered as bonding + * candidates */ #define BONDING_TQ_THRESHOLD 50 -#define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or - * change the size of - * forw_packet->direct_link_flags */ +/* should not be bigger than 512 bytes or change the size of + * forw_packet->direct_link_flags */ +#define MAX_AGGREGATION_BYTES 512 #define MAX_AGGREGATION_MS 100 #define SOFTIF_NEIGH_TIMEOUT 180000 /* 3 minutes */ +/* don't reset again within 30 seconds */ #define RESET_PROTECTION_MS 30000 #define EXPECTED_SEQNO_RANGE 65536 -/* don't reset again within 30 seconds */ #define MESH_INACTIVE 0 #define MESH_ACTIVE 1 @@ -84,12 +85,13 @@ #ifdef pr_fmt #undef pr_fmt #endif -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt /* Append 'batman-adv: ' before - * kernel messages */ +/* Append 'batman-adv: ' before kernel messages */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define DBG_BATMAN 1 /* all messages related to routing / flooding / - * broadcasting / etc */ -#define DBG_ROUTES 2 /* route or tt entry added / changed / deleted */ +/* all messages related to routing / flooding / broadcasting / etc */ +#define DBG_BATMAN 1 +/* route or tt entry added / changed / deleted */ +#define DBG_ROUTES 2 #define DBG_ALL 3 diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index c225c3acc55f..eda99650e9f8 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@ -128,8 +128,7 @@ struct vis_packet { uint8_t entries; /* number of entries behind this struct */ uint32_t seqno; /* sequence number */ uint8_t ttl; /* TTL */ - uint8_t vis_orig[6]; /* originator that informs about its - * neighbors */ + uint8_t vis_orig[6]; /* originator that announces its neighbors */ uint8_t target_orig[6]; /* who should receive this packet */ uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */ } __packed; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index d6aaf9fa64d4..8e962e3aa427 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -793,8 +793,8 @@ static void interface_setup(struct net_device *dev) * have not been initialized yet */ dev->mtu = ETH_DATA_LEN; - dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the - * skbuff for our header */ + /* reserve more space in the skbuff for our header */ + dev->hard_header_len = BAT_HEADER_LEN; /* generate random address */ random_ether_addr(dev_addr); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 6b6c32e01c54..fab70e8b16ee 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -89,11 +89,11 @@ struct orig_node { struct hlist_node hash_entry; struct bat_priv *bat_priv; unsigned long last_frag_packet; - spinlock_t ogm_cnt_lock; /* protects: bcast_own, bcast_own_sum, - * neigh_node->real_bits, - * neigh_node->real_packet_count */ - spinlock_t bcast_seqno_lock; /* protects bcast_bits, - * last_bcast_seqno */ + /* ogm_cnt_lock protects: bcast_own, bcast_own_sum, + * neigh_node->real_bits, neigh_node->real_packet_count */ + spinlock_t ogm_cnt_lock; + /* bcast_seqno_lock protects bcast_bits, last_bcast_seqno */ + spinlock_t bcast_seqno_lock; atomic_t bond_candidates; struct list_head bond_list; }; -- cgit v1.2.3-58-ga151 From 27aea2128ec09924dfe08e97739b2bf8b15c8619 Mon Sep 17 00:00:00 2001 From: Daniele Furlan Date: Sat, 7 May 2011 22:45:19 +0200 Subject: batman-adv: remove duplicate code from function is_bidirectional_neigh() In function is_bidirectional_neigh the code that find out the one hop neighbor is duplicated. Signed-off-by: Daniele Furlan Signed-off-by: Sven Eckelmann --- net/batman-adv/routing.c | 74 ++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 49 deletions(-) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 7648b92aec47..bb1c3ec7e3ff 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -169,65 +169,41 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, uint8_t orig_eq_count, neigh_rq_count, tq_own; int tq_asym_penalty, ret = 0; - if (orig_node == orig_neigh_node) { - rcu_read_lock(); - hlist_for_each_entry_rcu(tmp_neigh_node, node, - &orig_node->neigh_list, list) { - - if (!compare_eth(tmp_neigh_node->addr, - orig_neigh_node->orig)) - continue; - - if (tmp_neigh_node->if_incoming != if_incoming) - continue; - - if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) - continue; - - neigh_node = tmp_neigh_node; - } - rcu_read_unlock(); + /* find corresponding one hop neighbor */ + rcu_read_lock(); + hlist_for_each_entry_rcu(tmp_neigh_node, node, + &orig_neigh_node->neigh_list, list) { - if (!neigh_node) - neigh_node = create_neighbor(orig_node, - orig_neigh_node, - orig_neigh_node->orig, - if_incoming); - if (!neigh_node) - goto out; + if (!compare_eth(tmp_neigh_node->addr, orig_neigh_node->orig)) + continue; - neigh_node->last_valid = jiffies; - } else { - /* find packet count of corresponding one hop neighbor */ - rcu_read_lock(); - hlist_for_each_entry_rcu(tmp_neigh_node, node, - &orig_neigh_node->neigh_list, list) { + if (tmp_neigh_node->if_incoming != if_incoming) + continue; - if (!compare_eth(tmp_neigh_node->addr, - orig_neigh_node->orig)) - continue; + if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + continue; - if (tmp_neigh_node->if_incoming != if_incoming) - continue; + neigh_node = tmp_neigh_node; + break; + } + rcu_read_unlock(); - if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) - continue; + if (!neigh_node) + neigh_node = create_neighbor(orig_neigh_node, + orig_neigh_node, + orig_neigh_node->orig, + if_incoming); - neigh_node = tmp_neigh_node; - } - rcu_read_unlock(); + if (!neigh_node) + goto out; - if (!neigh_node) - neigh_node = create_neighbor(orig_neigh_node, - orig_neigh_node, - orig_neigh_node->orig, - if_incoming); - if (!neigh_node) - goto out; - } + /* if orig_node is direct neighbour update neigh_node last_valid */ + if (orig_node == orig_neigh_node) + neigh_node->last_valid = jiffies; orig_node->last_valid = jiffies; + /* find packet count of corresponding one hop neighbor */ spin_lock_bh(&orig_node->ogm_cnt_lock); orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num]; neigh_rq_count = neigh_node->real_packet_count; -- cgit v1.2.3-58-ga151 From 1ab7b6ac2709d0eb05a7144cd0e14faa3a7ea162 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 14 Apr 2011 23:46:06 -0700 Subject: ethtool: remove phys_id from ethtool_ops After that all the upstream kernel drivers now use phys_id, and the old ethtool_ops interface (phys_id) can be removed. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/ethtool.h | 7 ------- net/core/ethtool.c | 6 +----- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 4194a2067a14..d659fdc77eb3 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -814,12 +814,6 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * the indicator accordingly. Finally, it is called with the argument * %ETHTOOL_ID_INACTIVE and must deactivate the indicator. Returns a * negative error code or zero. - * @phys_id: Deprecated in favour of @set_phys_id. - * Identify the physical device, e.g. by flashing an LED - * attached to it until interrupted by a signal or the given time - * (in seconds) elapses. If the given time is zero, use a default - * time limit. Returns a negative error code or zero. Being - * interrupted by a signal is not an error. * @get_ethtool_stats: Return extended statistics about the device. * This is only useful if the device maintains statistics not * included in &struct rtnl_link_stats64. @@ -908,7 +902,6 @@ struct ethtool_ops { void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); void (*get_strings)(struct net_device *, u32 stringset, u8 *); int (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state); - int (*phys_id)(struct net_device *, u32); void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *); int (*begin)(struct net_device *); diff --git a/net/core/ethtool.c b/net/core/ethtool.c index d8b1a8d85a96..927819d92248 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1655,7 +1655,7 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) static bool busy; int rc; - if (!dev->ethtool_ops->set_phys_id && !dev->ethtool_ops->phys_id) + if (!dev->ethtool_ops->set_phys_id) return -EOPNOTSUPP; if (busy) @@ -1664,10 +1664,6 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) if (copy_from_user(&id, useraddr, sizeof(id))) return -EFAULT; - if (!dev->ethtool_ops->set_phys_id) - /* Do it the old way */ - return dev->ethtool_ops->phys_id(dev, id.data); - rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ACTIVE); if (rc < 0) return rc; -- cgit v1.2.3-58-ga151 From 2c42758cf6683e9c1657d20dcf2a7edd323d98ca Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 16:10:41 -0700 Subject: dccp: Use cork flow in dccp_v4_connect() Since this is invoked from inet_stream_connect() the socket is locked and therefore this usage is safe. Signed-off-by: David S. Miller --- net/dccp/ipv4.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 36700a46b245..4ac1a728083a 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -45,7 +45,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) struct dccp_sock *dp = dccp_sk(sk); __be16 orig_sport, orig_dport; __be32 daddr, nexthop; - struct flowi4 fl4; + struct flowi4 *fl4; struct rtable *rt; int err; struct ip_options_rcu *inet_opt; @@ -70,7 +70,8 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) orig_sport = inet->inet_sport; orig_dport = usin->sin_port; - rt = ip_route_connect(&fl4, nexthop, inet->inet_saddr, + fl4 = &inet->cork.fl.u.ip4; + rt = ip_route_connect(fl4, nexthop, inet->inet_saddr, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, IPPROTO_DCCP, orig_sport, orig_dport, sk, true); @@ -83,10 +84,10 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) } if (inet_opt == NULL || !inet_opt->opt.srr) - daddr = fl4.daddr; + daddr = fl4->daddr; if (inet->inet_saddr == 0) - inet->inet_saddr = fl4.saddr; + inet->inet_saddr = fl4->saddr; inet->inet_rcv_saddr = inet->inet_saddr; inet->inet_dport = usin->sin_port; @@ -106,7 +107,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (err != 0) goto failure; - rt = ip_route_newports(&fl4, rt, orig_sport, orig_dport, + rt = ip_route_newports(fl4, rt, orig_sport, orig_dport, inet->inet_sport, inet->inet_dport, sk); if (IS_ERR(rt)) { rt = NULL; -- cgit v1.2.3-58-ga151 From da905bd1d5a6480d206f4b3dc61243f95adfae2c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 16:11:19 -0700 Subject: tcp: Use cork flow in tcp_v4_connect() Since this is invoked from inet_stream_connect() the socket is locked and therefore this usage is safe. Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index f3d16d8918c7..a71217156856 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -151,7 +151,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) struct tcp_sock *tp = tcp_sk(sk); __be16 orig_sport, orig_dport; __be32 daddr, nexthop; - struct flowi4 fl4; + struct flowi4 *fl4; struct rtable *rt; int err; struct ip_options_rcu *inet_opt; @@ -173,7 +173,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) orig_sport = inet->inet_sport; orig_dport = usin->sin_port; - rt = ip_route_connect(&fl4, nexthop, inet->inet_saddr, + fl4 = &inet->cork.fl.u.ip4; + rt = ip_route_connect(fl4, nexthop, inet->inet_saddr, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, IPPROTO_TCP, orig_sport, orig_dport, sk, true); @@ -190,10 +191,10 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) } if (!inet_opt || !inet_opt->opt.srr) - daddr = fl4.daddr; + daddr = fl4->daddr; if (!inet->inet_saddr) - inet->inet_saddr = fl4.saddr; + inet->inet_saddr = fl4->saddr; inet->inet_rcv_saddr = inet->inet_saddr; if (tp->rx_opt.ts_recent_stamp && inet->inet_daddr != daddr) { @@ -204,7 +205,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) } if (tcp_death_row.sysctl_tw_recycle && - !tp->rx_opt.ts_recent_stamp && fl4.daddr == daddr) { + !tp->rx_opt.ts_recent_stamp && fl4->daddr == daddr) { struct inet_peer *peer = rt_get_peer(rt); /* * VJ's idea. We save last timestamp seen from @@ -240,7 +241,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (err) goto failure; - rt = ip_route_newports(&fl4, rt, orig_sport, orig_dport, + rt = ip_route_newports(fl4, rt, orig_sport, orig_dport, inet->inet_sport, inet->inet_dport, sk); if (IS_ERR(rt)) { err = PTR_ERR(rt); -- cgit v1.2.3-58-ga151 From 2f16270f41e1499e23e6be25c51be87d950ffc91 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 8 May 2011 13:39:01 -0700 Subject: l2tp: Fix locking in l2tp_ip.c Both l2tp_ip_connect() and l2tp_ip_sendmsg() must take the socket lock. They both modify socket state non-atomically, and in particular l2tp_ip_sendmsg() increments socket private counters without using atomic operations. Signed-off-by: David S. Miller --- net/l2tp/l2tp_ip.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 81899600abe2..bd0cc0b8f32f 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -311,6 +311,8 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len if (lsa->l2tp_family != AF_INET) goto out; + lock_sock(sk); + sk_dst_reset(sk); oif = sk->sk_bound_dev_if; @@ -356,6 +358,7 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len rc = 0; out: + release_sock(sk); return rc; } @@ -420,18 +423,23 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m int connected = 0; __be32 daddr; + lock_sock(sk); + + rc = -ENOTCONN; if (sock_flag(sk, SOCK_DEAD)) - return -ENOTCONN; + goto out; /* Get and verify the address. */ if (msg->msg_name) { struct sockaddr_l2tpip *lip = (struct sockaddr_l2tpip *) msg->msg_name; + rc = -EINVAL; if (msg->msg_namelen < sizeof(*lip)) - return -EINVAL; + goto out; if (lip->l2tp_family != AF_INET) { + rc = -EAFNOSUPPORT; if (lip->l2tp_family != AF_UNSPEC) - return -EAFNOSUPPORT; + goto out; } daddr = lip->l2tp_addr.s_addr; @@ -510,12 +518,15 @@ error: lsa->tx_errors++; } +out: + release_sock(sk); return rc; no_route: IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); kfree_skb(skb); - return -EHOSTUNREACH; + rc = -EHOSTUNREACH; + goto out; } static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, -- cgit v1.2.3-58-ga151 From 6af88da14ee284aaad6e4326da09a89191ab6165 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 8 May 2011 13:45:20 -0700 Subject: l2tp: Fix locking in l2tp_core.c l2tp_xmit_skb() must take the socket lock. It makes use of ip_queue_xmit() which expects to execute in a socket atomic context. Since we execute this function in software interrupts, we cannot use the usual lock_sock()/release_sock() sequence, instead we have to use bh_lock_sock() and see if a user has the socket locked, and if so drop the packet. Signed-off-by: David S. Miller --- net/l2tp/l2tp_core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index c64ce0a0bb03..78530299ae38 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1060,6 +1060,12 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len IPSKB_REROUTED); nf_reset(skb); + bh_lock_sock(sk); + if (sock_owned_by_user(sk)) { + dev_kfree_skb(skb); + goto out_unlock; + } + /* Get routing info from the tunnel socket */ skb_dst_drop(skb); skb_dst_set(skb, dst_clone(__sk_dst_get(sk))); @@ -1106,6 +1112,8 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len l2tp_skb_set_owner_w(skb, sk); l2tp_xmit_core(session, skb, data_len); +out_unlock: + bh_unlock_sock(sk); abort: return 0; -- cgit v1.2.3-58-ga151 From fdbb0f076b065a0c753ba26925f10357505f1d42 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 8 May 2011 13:48:37 -0700 Subject: l2tp: Use cork flow in l2tp_ip_connect() and l2tp_ip_sendmsg() Now that the socket is consistently locked in these two routines, this transformation is legal. Signed-off-by: David S. Miller --- net/l2tp/l2tp_ip.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index bd0cc0b8f32f..1ca74892ff09 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -298,7 +298,7 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len { struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *) uaddr; struct inet_sock *inet = inet_sk(sk); - struct flowi4 fl4; + struct flowi4 *fl4; struct rtable *rt; __be32 saddr; int oif, rc; @@ -322,7 +322,8 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len if (ipv4_is_multicast(lsa->l2tp_addr.s_addr)) goto out; - rt = ip_route_connect(&fl4, lsa->l2tp_addr.s_addr, saddr, + fl4 = &inet->cork.fl.u.ip4; + rt = ip_route_connect(fl4, lsa->l2tp_addr.s_addr, saddr, RT_CONN_FLAGS(sk), oif, IPPROTO_L2TP, 0, 0, sk, true); @@ -342,10 +343,10 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id; if (!inet->inet_saddr) - inet->inet_saddr = fl4.saddr; + inet->inet_saddr = fl4->saddr; if (!inet->inet_rcv_saddr) - inet->inet_rcv_saddr = fl4.saddr; - inet->inet_daddr = fl4.daddr; + inet->inet_rcv_saddr = fl4->saddr; + inet->inet_daddr = fl4->daddr; sk->sk_state = TCP_ESTABLISHED; inet->inet_id = jiffies; @@ -420,6 +421,7 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m struct l2tp_ip_sock *lsa = l2tp_ip_sk(sk); struct inet_sock *inet = inet_sk(sk); struct rtable *rt = NULL; + struct flowi4 *fl4; int connected = 0; __be32 daddr; @@ -474,12 +476,12 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m goto error; } + fl4 = &inet->cork.fl.u.ip4; if (connected) rt = (struct rtable *) __sk_dst_check(sk, 0); if (rt == NULL) { struct ip_options_rcu *inet_opt; - struct flowi4 fl4; rcu_read_lock(); inet_opt = rcu_dereference(inet->inet_opt); @@ -494,7 +496,7 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m * keep trying until route appears or the connection times * itself out. */ - rt = ip_route_output_ports(sock_net(sk), &fl4, sk, + rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr, inet->inet_saddr, inet->inet_dport, inet->inet_sport, sk->sk_protocol, RT_CONN_FLAGS(sk), -- cgit v1.2.3-58-ga151 From 3038eeac027d8ec62e4936143498f2b37baf4cb5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 22:27:25 -0700 Subject: ipv4: Lock socket and use cork flow in ip4_datagram_connect(). This is to make sure that an l2tp socket's inet cork flow is fully filled in, when it's encapsulated in UDP. Signed-off-by: David S. Miller --- net/ipv4/datagram.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index d5a2e6995bae..424fafbc8cb0 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -24,7 +24,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { struct inet_sock *inet = inet_sk(sk); struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; - struct flowi4 fl4; + struct flowi4 *fl4; struct rtable *rt; __be32 saddr; int oif; @@ -39,6 +39,8 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) sk_dst_reset(sk); + lock_sock(sk); + oif = sk->sk_bound_dev_if; saddr = inet->inet_saddr; if (ipv4_is_multicast(usin->sin_addr.s_addr)) { @@ -47,7 +49,8 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (!saddr) saddr = inet->mc_addr; } - rt = ip_route_connect(&fl4, usin->sin_addr.s_addr, saddr, + fl4 = &inet->cork.fl.u.ip4; + rt = ip_route_connect(fl4, usin->sin_addr.s_addr, saddr, RT_CONN_FLAGS(sk), oif, sk->sk_protocol, inet->inet_sport, usin->sin_port, sk, true); @@ -55,26 +58,30 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) err = PTR_ERR(rt); if (err == -ENETUNREACH) IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); - return err; + goto out; } if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) { ip_rt_put(rt); - return -EACCES; + err = -EACCES; + goto out; } if (!inet->inet_saddr) - inet->inet_saddr = fl4.saddr; /* Update source address */ + inet->inet_saddr = fl4->saddr; /* Update source address */ if (!inet->inet_rcv_saddr) { - inet->inet_rcv_saddr = fl4.saddr; + inet->inet_rcv_saddr = fl4->saddr; if (sk->sk_prot->rehash) sk->sk_prot->rehash(sk); } - inet->inet_daddr = fl4.daddr; + inet->inet_daddr = fl4->daddr; inet->inet_dport = usin->sin_port; sk->sk_state = TCP_ESTABLISHED; inet->inet_id = jiffies; sk_dst_set(sk, &rt->dst); - return 0; + err = 0; +out: + release_sock(sk); + return err; } EXPORT_SYMBOL(ip4_datagram_connect); -- cgit v1.2.3-58-ga151 From 6e869138101bc607e4780187210b79d531f9b2ce Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 16:18:04 -0700 Subject: ipv4: Use cork flow in inet_sk_{reselect_saddr,rebuild_header}() These two functions must be invoked only when the socket is locked (because socket identity modifications are made non-atomically). Therefore we can use the cork flow for output route lookups. Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 7b91fa8bf83c..851aa056854b 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1103,7 +1103,7 @@ static int inet_sk_reselect_saddr(struct sock *sk) struct inet_sock *inet = inet_sk(sk); __be32 old_saddr = inet->inet_saddr; __be32 daddr = inet->inet_daddr; - struct flowi4 fl4; + struct flowi4 *fl4; struct rtable *rt; __be32 new_saddr; struct ip_options_rcu *inet_opt; @@ -1114,7 +1114,8 @@ static int inet_sk_reselect_saddr(struct sock *sk) daddr = inet_opt->opt.faddr; /* Query new route. */ - rt = ip_route_connect(&fl4, daddr, 0, RT_CONN_FLAGS(sk), + fl4 = &inet->cork.fl.u.ip4; + rt = ip_route_connect(fl4, daddr, 0, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, sk->sk_protocol, inet->inet_sport, inet->inet_dport, sk, false); if (IS_ERR(rt)) @@ -1122,7 +1123,7 @@ static int inet_sk_reselect_saddr(struct sock *sk) sk_setup_caps(sk, &rt->dst); - new_saddr = fl4.saddr; + new_saddr = fl4->saddr; if (new_saddr == old_saddr) return 0; @@ -1152,7 +1153,7 @@ int inet_sk_rebuild_header(struct sock *sk) struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); __be32 daddr; struct ip_options_rcu *inet_opt; - struct flowi4 fl4; + struct flowi4 *fl4; int err; /* Route is OK, nothing to do. */ @@ -1166,7 +1167,8 @@ int inet_sk_rebuild_header(struct sock *sk) if (inet_opt && inet_opt->opt.srr) daddr = inet_opt->opt.faddr; rcu_read_unlock(); - rt = ip_route_output_ports(sock_net(sk), &fl4, sk, daddr, inet->inet_saddr, + fl4 = &inet->cork.fl.u.ip4; + rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr, inet->inet_saddr, inet->inet_dport, inet->inet_sport, sk->sk_protocol, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if); -- cgit v1.2.3-58-ga151 From b57ae01a8a8446dbbed7365c9b05aef1fc6dea20 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 16:24:06 -0700 Subject: ipv4: Use cork flow in ip_queue_xmit() All invokers of ip_queue_xmit() must make certain that the socket is locked. All of SCTP, TCP, DCCP, and L2TP now make sure this is the case. Therefore we can use the cork flow during output route lookup in ip_queue_xmit() when the socket route check fails. Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 0a2f49a442e8..4ba26d4040ed 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -317,6 +317,7 @@ int ip_queue_xmit(struct sk_buff *skb) struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(sk); struct ip_options_rcu *inet_opt; + struct flowi4 *fl4; struct rtable *rt; struct iphdr *iph; int res; @@ -331,9 +332,9 @@ int ip_queue_xmit(struct sk_buff *skb) goto packet_routed; /* Make sure we can route this packet. */ + fl4 = &inet->cork.fl.u.ip4; rt = (struct rtable *)__sk_dst_check(sk, 0); if (rt == NULL) { - struct flowi4 fl4; __be32 daddr; /* Use correct destination address if we have options. */ @@ -345,7 +346,7 @@ int ip_queue_xmit(struct sk_buff *skb) * keep trying until route appears or the connection times * itself out. */ - rt = ip_route_output_ports(sock_net(sk), &fl4, sk, + rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr, inet->inet_saddr, inet->inet_dport, inet->inet_sport, -- cgit v1.2.3-58-ga151 From 8663c938ceb72f47941c95ff0ea491ebbdd68f26 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 16:32:47 -0700 Subject: sctp: Store a flowi in transports to provide persistent keying. Several future simplifications are possible now because of this. For example, the sctp_addr unions can simply refer directly to the flowi information. Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 1 + net/sctp/transport.c | 9 +++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index ff3e8cce7d66..795f4886e111 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -894,6 +894,7 @@ struct sctp_transport { /* Is this structure kfree()able? */ malloced:1; + struct flowi fl; /* This is the peer's IP address and port. */ union sctp_addr ipaddr; diff --git a/net/sctp/transport.c b/net/sctp/transport.c index d8595dd1a8a7..394c57ca2f54 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -213,13 +213,11 @@ void sctp_transport_set_owner(struct sctp_transport *transport, /* Initialize the pmtu of a transport. */ void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk) { - struct flowi fl; - /* If we don't have a fresh route, look one up */ if (!transport->dst || transport->dst->obsolete > 1) { dst_release(transport->dst); transport->af_specific->get_dst(transport, &transport->saddr, - &fl, sk); + &transport->fl, sk); } if (transport->dst) { @@ -274,14 +272,13 @@ void sctp_transport_route(struct sctp_transport *transport, { struct sctp_association *asoc = transport->asoc; struct sctp_af *af = transport->af_specific; - struct flowi fl; - af->get_dst(transport, saddr, &fl, sctp_opt2sk(opt)); + af->get_dst(transport, saddr, &transport->fl, sctp_opt2sk(opt)); if (saddr) memcpy(&transport->saddr, saddr, sizeof(union sctp_addr)); else - af->get_saddr(opt, transport, &fl); + af->get_saddr(opt, transport, &transport->fl); if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { return; -- cgit v1.2.3-58-ga151 From 77357a95522ba645bbfd65253b34317c824103f9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 8 May 2011 14:34:22 -0700 Subject: ipv4: Create inet_csk_route_child_sock(). This is just like inet_csk_route_req() except that it operates after we've created the new child socket. In this way we can use the new socket's cork flow for proper route key storage. This will be used by DCCP and TCP child socket creation handling. Signed-off-by: David S. Miller --- include/net/inet_connection_sock.h | 3 +++ net/ipv4/inet_connection_sock.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 6ac4e3b5007f..4367d913c0e2 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -250,6 +250,9 @@ extern int inet_csk_get_port(struct sock *sk, unsigned short snum); extern struct dst_entry* inet_csk_route_req(struct sock *sk, const struct request_sock *req); +extern struct dst_entry* inet_csk_route_child_sock(struct sock *sk, + struct sock *newsk, + const struct request_sock *req); static inline void inet_csk_reqsk_queue_add(struct sock *sk, struct request_sock *req, diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 54944da2f794..3a2ba5632dff 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -379,6 +379,39 @@ no_route: } EXPORT_SYMBOL_GPL(inet_csk_route_req); +struct dst_entry *inet_csk_route_child_sock(struct sock *sk, + struct sock *newsk, + const struct request_sock *req) +{ + const struct inet_request_sock *ireq = inet_rsk(req); + struct inet_sock *newinet = inet_sk(newsk); + struct ip_options_rcu *opt = ireq->opt; + struct net *net = sock_net(sk); + struct flowi4 *fl4; + struct rtable *rt; + + fl4 = &newinet->cork.fl.u.ip4; + flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, + RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, + sk->sk_protocol, inet_sk_flowi_flags(sk), + (opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr, + ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport); + security_req_classify_flow(req, flowi4_to_flowi(fl4)); + rt = ip_route_output_flow(net, fl4, sk); + if (IS_ERR(rt)) + goto no_route; + if (opt && opt->opt.is_strictroute && fl4->daddr != rt->rt_gateway) + goto route_err; + return &rt->dst; + +route_err: + ip_rt_put(rt); +no_route: + IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); + return NULL; +} +EXPORT_SYMBOL_GPL(inet_csk_route_child_sock); + static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport, const u32 rnd, const u32 synq_hsize) { -- cgit v1.2.3-58-ga151 From 421eab4cf318ce47c1daae391e54d1b427c6687b Mon Sep 17 00:00:00 2001 From: Hans Schillstrom Date: Tue, 3 May 2011 22:09:30 +0200 Subject: IPVS: Change of socket usage to enable name space exit. If the sync daemons run in a name space while it crashes or get killed, there is no way to stop them except for a reboot. When all patches are there, ip_vs_core will handle register_pernet_(), i.e. ip_vs_sync_init() and ip_vs_sync_cleanup() will be removed. Kernel threads should not increment the use count of a socket. By calling sk_change_net() after creating a socket this is avoided. sock_release cant be used intead sk_release_kernel() should be used. Thanks Eric W Biederman for your advices. Signed-off-by: Hans Schillstrom [horms@verge.net.au: minor edit to changelog] Signed-off-by: Simon Horman --- net/netfilter/ipvs/ip_vs_core.c | 2 +- net/netfilter/ipvs/ip_vs_sync.c | 58 ++++++++++++++++++++++++++--------------- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 07accf6b2401..a0791dc05a27 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1896,7 +1896,7 @@ static int __net_init __ip_vs_init(struct net *net) static void __net_exit __ip_vs_cleanup(struct net *net) { - IP_VS_DBG(10, "ipvs netns %d released\n", net_ipvs(net)->gen); + IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen); } static struct pernet_operations ipvs_core_ops = { diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 3e7961e85e9c..0cce95310820 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c @@ -1303,13 +1303,18 @@ static struct socket *make_send_sock(struct net *net) struct socket *sock; int result; - /* First create a socket */ - result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1); + /* First create a socket move it to right name space later */ + result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); if (result < 0) { pr_err("Error during creation of socket; terminating\n"); return ERR_PTR(result); } - + /* + * Kernel sockets that are a part of a namespace, should not + * hold a reference to a namespace in order to allow to stop it. + * After sk_change_net should be released using sk_release_kernel. + */ + sk_change_net(sock->sk, net); result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn); if (result < 0) { pr_err("Error setting outbound mcast interface\n"); @@ -1334,8 +1339,8 @@ static struct socket *make_send_sock(struct net *net) return sock; - error: - sock_release(sock); +error: + sk_release_kernel(sock->sk); return ERR_PTR(result); } @@ -1350,12 +1355,17 @@ static struct socket *make_receive_sock(struct net *net) int result; /* First create a socket */ - result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1); + result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); if (result < 0) { pr_err("Error during creation of socket; terminating\n"); return ERR_PTR(result); } - + /* + * Kernel sockets that are a part of a namespace, should not + * hold a reference to a namespace in order to allow to stop it. + * After sk_change_net should be released using sk_release_kernel. + */ + sk_change_net(sock->sk, net); /* it is equivalent to the REUSEADDR option in user-space */ sock->sk->sk_reuse = 1; @@ -1377,8 +1387,8 @@ static struct socket *make_receive_sock(struct net *net) return sock; - error: - sock_release(sock); +error: + sk_release_kernel(sock->sk); return ERR_PTR(result); } @@ -1473,7 +1483,7 @@ static int sync_thread_master(void *data) ip_vs_sync_buff_release(sb); /* release the sending multicast socket */ - sock_release(tinfo->sock); + sk_release_kernel(tinfo->sock->sk); kfree(tinfo); return 0; @@ -1513,7 +1523,7 @@ static int sync_thread_backup(void *data) } /* release the sending multicast socket */ - sock_release(tinfo->sock); + sk_release_kernel(tinfo->sock->sk); kfree(tinfo->buf); kfree(tinfo); @@ -1601,7 +1611,7 @@ outtinfo: outbuf: kfree(buf); outsocket: - sock_release(sock); + sk_release_kernel(sock->sk); out: return result; } @@ -1610,6 +1620,7 @@ out: int stop_sync_thread(struct net *net, int state) { struct netns_ipvs *ipvs = net_ipvs(net); + int retc = -EINVAL; IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current)); @@ -1629,7 +1640,7 @@ int stop_sync_thread(struct net *net, int state) spin_lock_bh(&ipvs->sync_lock); ipvs->sync_state &= ~IP_VS_STATE_MASTER; spin_unlock_bh(&ipvs->sync_lock); - kthread_stop(ipvs->master_thread); + retc = kthread_stop(ipvs->master_thread); ipvs->master_thread = NULL; } else if (state == IP_VS_STATE_BACKUP) { if (!ipvs->backup_thread) @@ -1639,16 +1650,14 @@ int stop_sync_thread(struct net *net, int state) task_pid_nr(ipvs->backup_thread)); ipvs->sync_state &= ~IP_VS_STATE_BACKUP; - kthread_stop(ipvs->backup_thread); + retc = kthread_stop(ipvs->backup_thread); ipvs->backup_thread = NULL; - } else { - return -EINVAL; } /* decrease the module use count */ ip_vs_use_count_dec(); - return 0; + return retc; } /* @@ -1670,8 +1679,15 @@ static int __net_init __ip_vs_sync_init(struct net *net) static void __ip_vs_sync_cleanup(struct net *net) { - stop_sync_thread(net, IP_VS_STATE_MASTER); - stop_sync_thread(net, IP_VS_STATE_BACKUP); + int retc; + + retc = stop_sync_thread(net, IP_VS_STATE_MASTER); + if (retc && retc != -ESRCH) + pr_err("Failed to stop Master Daemon\n"); + + retc = stop_sync_thread(net, IP_VS_STATE_BACKUP); + if (retc && retc != -ESRCH) + pr_err("Failed to stop Backup Daemon\n"); } static struct pernet_operations ipvs_sync_ops = { @@ -1682,10 +1698,10 @@ static struct pernet_operations ipvs_sync_ops = { int __init ip_vs_sync_init(void) { - return register_pernet_subsys(&ipvs_sync_ops); + return register_pernet_device(&ipvs_sync_ops); } void ip_vs_sync_cleanup(void) { - unregister_pernet_subsys(&ipvs_sync_ops); + unregister_pernet_device(&ipvs_sync_ops); } -- cgit v1.2.3-58-ga151 From 74973f6fbfcd1b084c3ccc75b783a6dacac94a10 Mon Sep 17 00:00:00 2001 From: Hans Schillstrom Date: Tue, 3 May 2011 22:09:31 +0200 Subject: IPVS: init and cleanup restructuring DESCRIPTION This patch tries to restore the initial init and cleanup sequences that was before namspace patch. Netns also requires action when net devices unregister which has never been implemented. I.e this patch also covers when a device moves into a network namespace, and has to be released. IMPLEMENTATION The number of calls to register_pernet_device have been reduced to one for the ip_vs.ko Schedulers still have their own calls. This patch adds a function __ip_vs_service_cleanup() and an enable flag for the netfilter hooks. The nf hooks will be enabled when the first service is loaded and never disabled again, except when a namespace exit starts. Signed-off-by: Hans Schillstrom Acked-by: Julian Anastasov [horms@verge.net.au: minor edit to changelog] Signed-off-by: Simon Horman --- include/net/ip_vs.h | 17 ++++++ net/netfilter/ipvs/ip_vs_app.c | 15 +---- net/netfilter/ipvs/ip_vs_conn.c | 12 +--- net/netfilter/ipvs/ip_vs_core.c | 101 +++++++++++++++++++++++++++++--- net/netfilter/ipvs/ip_vs_ctl.c | 120 ++++++++++++++++++++++++++++++++------- net/netfilter/ipvs/ip_vs_est.c | 14 +---- net/netfilter/ipvs/ip_vs_proto.c | 11 +--- net/netfilter/ipvs/ip_vs_sync.c | 13 +---- 8 files changed, 223 insertions(+), 80 deletions(-) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 4d1b71ae82ba..02f67021e079 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -791,6 +791,7 @@ struct ip_vs_app { /* IPVS in network namespace */ struct netns_ipvs { int gen; /* Generation */ + int enable; /* enable like nf_hooks do */ /* * Hash table: for real service lookups */ @@ -1089,6 +1090,22 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp) atomic_inc(&ctl_cp->n_control); } +/* + * IPVS netns init & cleanup functions + */ +extern int __ip_vs_estimator_init(struct net *net); +extern int __ip_vs_control_init(struct net *net); +extern int __ip_vs_protocol_init(struct net *net); +extern int __ip_vs_app_init(struct net *net); +extern int __ip_vs_conn_init(struct net *net); +extern int __ip_vs_sync_init(struct net *net); +extern void __ip_vs_conn_cleanup(struct net *net); +extern void __ip_vs_app_cleanup(struct net *net); +extern void __ip_vs_protocol_cleanup(struct net *net); +extern void __ip_vs_control_cleanup(struct net *net); +extern void __ip_vs_estimator_cleanup(struct net *net); +extern void __ip_vs_sync_cleanup(struct net *net); +extern void __ip_vs_service_cleanup(struct net *net); /* * IPVS application functions diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c index 2dc6de13ac18..51f3af7c4743 100644 --- a/net/netfilter/ipvs/ip_vs_app.c +++ b/net/netfilter/ipvs/ip_vs_app.c @@ -576,7 +576,7 @@ static const struct file_operations ip_vs_app_fops = { }; #endif -static int __net_init __ip_vs_app_init(struct net *net) +int __net_init __ip_vs_app_init(struct net *net) { struct netns_ipvs *ipvs = net_ipvs(net); @@ -585,26 +585,17 @@ static int __net_init __ip_vs_app_init(struct net *net) return 0; } -static void __net_exit __ip_vs_app_cleanup(struct net *net) +void __net_exit __ip_vs_app_cleanup(struct net *net) { proc_net_remove(net, "ip_vs_app"); } -static struct pernet_operations ip_vs_app_ops = { - .init = __ip_vs_app_init, - .exit = __ip_vs_app_cleanup, -}; - int __init ip_vs_app_init(void) { - int rv; - - rv = register_pernet_subsys(&ip_vs_app_ops); - return rv; + return 0; } void ip_vs_app_cleanup(void) { - unregister_pernet_subsys(&ip_vs_app_ops); } diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index f289306cbf12..5092505f27a7 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -1258,22 +1258,17 @@ int __net_init __ip_vs_conn_init(struct net *net) return 0; } -static void __net_exit __ip_vs_conn_cleanup(struct net *net) +void __net_exit __ip_vs_conn_cleanup(struct net *net) { /* flush all the connection entries first */ ip_vs_conn_flush(net); proc_net_remove(net, "ip_vs_conn"); proc_net_remove(net, "ip_vs_conn_sync"); } -static struct pernet_operations ipvs_conn_ops = { - .init = __ip_vs_conn_init, - .exit = __ip_vs_conn_cleanup, -}; int __init ip_vs_conn_init(void) { int idx; - int retc; /* Compute size and mask */ ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits; @@ -1309,17 +1304,14 @@ int __init ip_vs_conn_init(void) rwlock_init(&__ip_vs_conntbl_lock_array[idx].l); } - retc = register_pernet_subsys(&ipvs_conn_ops); - /* calculate the random value for connection hash */ get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd)); - return retc; + return 0; } void ip_vs_conn_cleanup(void) { - unregister_pernet_subsys(&ipvs_conn_ops); /* Release the empty cache */ kmem_cache_destroy(ip_vs_conn_cachep); vfree(ip_vs_conn_tab); diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index a0791dc05a27..a74dae6c5dbc 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1113,6 +1113,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) return NF_ACCEPT; net = skb_net(skb); + if (!net_ipvs(net)->enable) + return NF_ACCEPT; + ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) { @@ -1343,6 +1346,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) return NF_ACCEPT; /* The packet looks wrong, ignore */ net = skb_net(skb); + pd = ip_vs_proto_data_get(net, cih->protocol); if (!pd) return NF_ACCEPT; @@ -1529,6 +1533,11 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) IP_VS_DBG_ADDR(af, &iph.daddr), hooknum); return NF_ACCEPT; } + /* ipvs enabled in this netns ? */ + net = skb_net(skb); + if (!net_ipvs(net)->enable) + return NF_ACCEPT; + ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); /* Bad... Do not break raw sockets */ @@ -1562,7 +1571,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); } - net = skb_net(skb); /* Protocol supported? */ pd = ip_vs_proto_data_get(net, iph.protocol); if (unlikely(!pd)) @@ -1588,7 +1596,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) } IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet"); - net = skb_net(skb); ipvs = net_ipvs(net); /* Check the server status */ if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { @@ -1743,10 +1750,16 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb, int (*okfn)(struct sk_buff *)) { int r; + struct net *net; if (ip_hdr(skb)->protocol != IPPROTO_ICMP) return NF_ACCEPT; + /* ipvs enabled in this netns ? */ + net = skb_net(skb); + if (!net_ipvs(net)->enable) + return NF_ACCEPT; + return ip_vs_in_icmp(skb, &r, hooknum); } @@ -1757,10 +1770,16 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb, int (*okfn)(struct sk_buff *)) { int r; + struct net *net; if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6) return NF_ACCEPT; + /* ipvs enabled in this netns ? */ + net = skb_net(skb); + if (!net_ipvs(net)->enable) + return NF_ACCEPT; + return ip_vs_in_icmp_v6(skb, &r, hooknum); } #endif @@ -1884,21 +1903,72 @@ static int __net_init __ip_vs_init(struct net *net) pr_err("%s(): no memory.\n", __func__); return -ENOMEM; } + /* Hold the beast until a service is registerd */ + ipvs->enable = 0; ipvs->net = net; /* Counters used for creating unique names */ ipvs->gen = atomic_read(&ipvs_netns_cnt); atomic_inc(&ipvs_netns_cnt); net->ipvs = ipvs; + + if (__ip_vs_estimator_init(net) < 0) + goto estimator_fail; + + if (__ip_vs_control_init(net) < 0) + goto control_fail; + + if (__ip_vs_protocol_init(net) < 0) + goto protocol_fail; + + if (__ip_vs_app_init(net) < 0) + goto app_fail; + + if (__ip_vs_conn_init(net) < 0) + goto conn_fail; + + if (__ip_vs_sync_init(net) < 0) + goto sync_fail; + printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n", sizeof(struct netns_ipvs), ipvs->gen); return 0; +/* + * Error handling + */ + +sync_fail: + __ip_vs_conn_cleanup(net); +conn_fail: + __ip_vs_app_cleanup(net); +app_fail: + __ip_vs_protocol_cleanup(net); +protocol_fail: + __ip_vs_control_cleanup(net); +control_fail: + __ip_vs_estimator_cleanup(net); +estimator_fail: + return -ENOMEM; } static void __net_exit __ip_vs_cleanup(struct net *net) { + __ip_vs_service_cleanup(net); /* ip_vs_flush() with locks */ + __ip_vs_conn_cleanup(net); + __ip_vs_app_cleanup(net); + __ip_vs_protocol_cleanup(net); + __ip_vs_control_cleanup(net); + __ip_vs_estimator_cleanup(net); IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen); } +static void __net_exit __ip_vs_dev_cleanup(struct net *net) +{ + EnterFunction(2); + net_ipvs(net)->enable = 0; /* Disable packet reception */ + __ip_vs_sync_cleanup(net); + LeaveFunction(2); +} + static struct pernet_operations ipvs_core_ops = { .init = __ip_vs_init, .exit = __ip_vs_cleanup, @@ -1906,6 +1976,10 @@ static struct pernet_operations ipvs_core_ops = { .size = sizeof(struct netns_ipvs), }; +static struct pernet_operations ipvs_core_dev_ops = { + .exit = __ip_vs_dev_cleanup, +}; + /* * Initialize IP Virtual Server */ @@ -1913,10 +1987,6 @@ static int __init ip_vs_init(void) { int ret; - ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */ - if (ret < 0) - return ret; - ip_vs_estimator_init(); ret = ip_vs_control_init(); if (ret < 0) { @@ -1944,15 +2014,28 @@ static int __init ip_vs_init(void) goto cleanup_conn; } + ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */ + if (ret < 0) + goto cleanup_sync; + + ret = register_pernet_device(&ipvs_core_dev_ops); + if (ret < 0) + goto cleanup_sub; + ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); if (ret < 0) { pr_err("can't register hooks.\n"); - goto cleanup_sync; + goto cleanup_dev; } pr_info("ipvs loaded.\n"); + return ret; +cleanup_dev: + unregister_pernet_device(&ipvs_core_dev_ops); +cleanup_sub: + unregister_pernet_subsys(&ipvs_core_ops); cleanup_sync: ip_vs_sync_cleanup(); cleanup_conn: @@ -1964,20 +2047,20 @@ cleanup_sync: ip_vs_control_cleanup(); cleanup_estimator: ip_vs_estimator_cleanup(); - unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ return ret; } static void __exit ip_vs_cleanup(void) { nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); + unregister_pernet_device(&ipvs_core_dev_ops); + unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ ip_vs_sync_cleanup(); ip_vs_conn_cleanup(); ip_vs_app_cleanup(); ip_vs_protocol_cleanup(); ip_vs_control_cleanup(); ip_vs_estimator_cleanup(); - unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ pr_info("ipvs unloaded.\n"); } diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index ae47090bf45f..ea722810faf3 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -69,6 +69,11 @@ int ip_vs_get_debug_level(void) } #endif + +/* Protos */ +static void __ip_vs_del_service(struct ip_vs_service *svc); + + #ifdef CONFIG_IP_VS_IPV6 /* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */ static int __ip_vs_addr_is_local_v6(struct net *net, @@ -1214,6 +1219,8 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u, write_unlock_bh(&__ip_vs_svc_lock); *svc_p = svc; + /* Now there is a service - full throttle */ + ipvs->enable = 1; return 0; @@ -1472,6 +1479,84 @@ static int ip_vs_flush(struct net *net) return 0; } +/* + * Delete service by {netns} in the service table. + * Called by __ip_vs_cleanup() + */ +void __ip_vs_service_cleanup(struct net *net) +{ + EnterFunction(2); + /* Check for "full" addressed entries */ + mutex_lock(&__ip_vs_mutex); + ip_vs_flush(net); + mutex_unlock(&__ip_vs_mutex); + LeaveFunction(2); +} +/* + * Release dst hold by dst_cache + */ +static inline void +__ip_vs_dev_reset(struct ip_vs_dest *dest, struct net_device *dev) +{ + spin_lock_bh(&dest->dst_lock); + if (dest->dst_cache && dest->dst_cache->dev == dev) { + IP_VS_DBG_BUF(3, "Reset dev:%s dest %s:%u ,dest->refcnt=%d\n", + dev->name, + IP_VS_DBG_ADDR(dest->af, &dest->addr), + ntohs(dest->port), + atomic_read(&dest->refcnt)); + ip_vs_dst_reset(dest); + } + spin_unlock_bh(&dest->dst_lock); + +} +/* + * Netdev event receiver + * Currently only NETDEV_UNREGISTER is handled, i.e. if we hold a reference to + * a device that is "unregister" it must be released. + */ +static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, + void *ptr) +{ + struct net_device *dev = ptr; + struct net *net = dev_net(dev); + struct ip_vs_service *svc; + struct ip_vs_dest *dest; + unsigned int idx; + + if (event != NETDEV_UNREGISTER) + return NOTIFY_DONE; + IP_VS_DBG(3, "%s() dev=%s\n", __func__, dev->name); + EnterFunction(2); + mutex_lock(&__ip_vs_mutex); + for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { + list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { + if (net_eq(svc->net, net)) { + list_for_each_entry(dest, &svc->destinations, + n_list) { + __ip_vs_dev_reset(dest, dev); + } + } + } + + list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { + if (net_eq(svc->net, net)) { + list_for_each_entry(dest, &svc->destinations, + n_list) { + __ip_vs_dev_reset(dest, dev); + } + } + + } + } + + list_for_each_entry(dest, &net_ipvs(net)->dest_trash, n_list) { + __ip_vs_dev_reset(dest, dev); + } + mutex_unlock(&__ip_vs_mutex); + LeaveFunction(2); + return NOTIFY_DONE; +} /* * Zero counters in a service or all services @@ -3588,6 +3673,10 @@ void __net_init __ip_vs_control_cleanup_sysctl(struct net *net) { } #endif +static struct notifier_block ip_vs_dst_notifier = { + .notifier_call = ip_vs_dst_event, +}; + int __net_init __ip_vs_control_init(struct net *net) { int idx; @@ -3626,7 +3715,7 @@ err: return -ENOMEM; } -static void __net_exit __ip_vs_control_cleanup(struct net *net) +void __net_exit __ip_vs_control_cleanup(struct net *net) { struct netns_ipvs *ipvs = net_ipvs(net); @@ -3639,11 +3728,6 @@ static void __net_exit __ip_vs_control_cleanup(struct net *net) free_percpu(ipvs->tot_stats.cpustats); } -static struct pernet_operations ipvs_control_ops = { - .init = __ip_vs_control_init, - .exit = __ip_vs_control_cleanup, -}; - int __init ip_vs_control_init(void) { int idx; @@ -3657,33 +3741,32 @@ int __init ip_vs_control_init(void) INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); } - ret = register_pernet_subsys(&ipvs_control_ops); - if (ret) { - pr_err("cannot register namespace.\n"); - goto err; - } - smp_wmb(); /* Do we really need it now ? */ ret = nf_register_sockopt(&ip_vs_sockopts); if (ret) { pr_err("cannot register sockopt.\n"); - goto err_net; + goto err_sock; } ret = ip_vs_genl_register(); if (ret) { pr_err("cannot register Generic Netlink interface.\n"); - nf_unregister_sockopt(&ip_vs_sockopts); - goto err_net; + goto err_genl; } + ret = register_netdevice_notifier(&ip_vs_dst_notifier); + if (ret < 0) + goto err_notf; + LeaveFunction(2); return 0; -err_net: - unregister_pernet_subsys(&ipvs_control_ops); -err: +err_notf: + ip_vs_genl_unregister(); +err_genl: + nf_unregister_sockopt(&ip_vs_sockopts); +err_sock: return ret; } @@ -3691,7 +3774,6 @@ err: void ip_vs_control_cleanup(void) { EnterFunction(2); - unregister_pernet_subsys(&ipvs_control_ops); ip_vs_genl_unregister(); nf_unregister_sockopt(&ip_vs_sockopts); LeaveFunction(2); diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c index 8c8766ca56ad..508cce98777c 100644 --- a/net/netfilter/ipvs/ip_vs_est.c +++ b/net/netfilter/ipvs/ip_vs_est.c @@ -192,7 +192,7 @@ void ip_vs_read_estimator(struct ip_vs_stats_user *dst, dst->outbps = (e->outbps + 0xF) >> 5; } -static int __net_init __ip_vs_estimator_init(struct net *net) +int __net_init __ip_vs_estimator_init(struct net *net) { struct netns_ipvs *ipvs = net_ipvs(net); @@ -203,24 +203,16 @@ static int __net_init __ip_vs_estimator_init(struct net *net) return 0; } -static void __net_exit __ip_vs_estimator_exit(struct net *net) +void __net_exit __ip_vs_estimator_cleanup(struct net *net) { del_timer_sync(&net_ipvs(net)->est_timer); } -static struct pernet_operations ip_vs_app_ops = { - .init = __ip_vs_estimator_init, - .exit = __ip_vs_estimator_exit, -}; int __init ip_vs_estimator_init(void) { - int rv; - - rv = register_pernet_subsys(&ip_vs_app_ops); - return rv; + return 0; } void ip_vs_estimator_cleanup(void) { - unregister_pernet_subsys(&ip_vs_app_ops); } diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c index 17484a4416ef..eb86028536fc 100644 --- a/net/netfilter/ipvs/ip_vs_proto.c +++ b/net/netfilter/ipvs/ip_vs_proto.c @@ -316,7 +316,7 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp, /* * per network name-space init */ -static int __net_init __ip_vs_protocol_init(struct net *net) +int __net_init __ip_vs_protocol_init(struct net *net) { #ifdef CONFIG_IP_VS_PROTO_TCP register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp); @@ -336,7 +336,7 @@ static int __net_init __ip_vs_protocol_init(struct net *net) return 0; } -static void __net_exit __ip_vs_protocol_cleanup(struct net *net) +void __net_exit __ip_vs_protocol_cleanup(struct net *net) { struct netns_ipvs *ipvs = net_ipvs(net); struct ip_vs_proto_data *pd; @@ -349,11 +349,6 @@ static void __net_exit __ip_vs_protocol_cleanup(struct net *net) } } -static struct pernet_operations ipvs_proto_ops = { - .init = __ip_vs_protocol_init, - .exit = __ip_vs_protocol_cleanup, -}; - int __init ip_vs_protocol_init(void) { char protocols[64]; @@ -382,7 +377,6 @@ int __init ip_vs_protocol_init(void) REGISTER_PROTOCOL(&ip_vs_protocol_esp); #endif pr_info("Registered protocols (%s)\n", &protocols[2]); - return register_pernet_subsys(&ipvs_proto_ops); return 0; } @@ -393,7 +387,6 @@ void ip_vs_protocol_cleanup(void) struct ip_vs_protocol *pp; int i; - unregister_pernet_subsys(&ipvs_proto_ops); /* unregister all the ipvs protocols */ for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) { while ((pp = ip_vs_proto_table[i]) != NULL) diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 0cce95310820..e292e5bddc70 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c @@ -1663,7 +1663,7 @@ int stop_sync_thread(struct net *net, int state) /* * Initialize data struct for each netns */ -static int __net_init __ip_vs_sync_init(struct net *net) +int __net_init __ip_vs_sync_init(struct net *net) { struct netns_ipvs *ipvs = net_ipvs(net); @@ -1677,7 +1677,7 @@ static int __net_init __ip_vs_sync_init(struct net *net) return 0; } -static void __ip_vs_sync_cleanup(struct net *net) +void __ip_vs_sync_cleanup(struct net *net) { int retc; @@ -1690,18 +1690,11 @@ static void __ip_vs_sync_cleanup(struct net *net) pr_err("Failed to stop Backup Daemon\n"); } -static struct pernet_operations ipvs_sync_ops = { - .init = __ip_vs_sync_init, - .exit = __ip_vs_sync_cleanup, -}; - - int __init ip_vs_sync_init(void) { - return register_pernet_device(&ipvs_sync_ops); + return 0; } void ip_vs_sync_cleanup(void) { - unregister_pernet_device(&ipvs_sync_ops); } -- cgit v1.2.3-58-ga151 From 0e734419923bd8e599858f8fc196c7804bb85564 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 8 May 2011 15:28:03 -0700 Subject: ipv4: Use inet_csk_route_child_sock() in DCCP and TCP. Operation order is now transposed, we first create the child socket then we try to hook up the route. Signed-off-by: David S. Miller --- net/dccp/ipv4.c | 19 ++++++++++--------- net/ipv4/tcp_ipv4.c | 18 ++++++++++-------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 4ac1a728083a..46b15e9e9b57 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -396,15 +396,10 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb, if (sk_acceptq_is_full(sk)) goto exit_overflow; - if (dst == NULL && (dst = inet_csk_route_req(sk, req)) == NULL) - goto exit; - newsk = dccp_create_openreq_child(sk, req, skb); if (newsk == NULL) goto exit_nonewsk; - sk_setup_caps(newsk, dst); - newinet = inet_sk(newsk); ireq = inet_rsk(req); newinet->inet_daddr = ireq->rmt_addr; @@ -416,12 +411,15 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb, newinet->mc_ttl = ip_hdr(skb)->ttl; newinet->inet_id = jiffies; + if (dst == NULL && (dst = inet_csk_route_child_sock(sk, newsk, req)) == NULL) + goto put_and_exit; + + sk_setup_caps(newsk, dst); + dccp_sync_mss(newsk, dst_mtu(dst)); - if (__inet_inherit_port(sk, newsk) < 0) { - sock_put(newsk); - goto exit; - } + if (__inet_inherit_port(sk, newsk) < 0) + goto put_and_exit; __inet_hash_nolisten(newsk, NULL); return newsk; @@ -433,6 +431,9 @@ exit_nonewsk: exit: NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); return NULL; +put_and_exit: + sock_put(newsk); + goto exit; } EXPORT_SYMBOL_GPL(dccp_v4_request_recv_sock); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index a71217156856..374de3c98d5e 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1421,15 +1421,11 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, if (sk_acceptq_is_full(sk)) goto exit_overflow; - if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL) - goto exit; - newsk = tcp_create_openreq_child(sk, req, skb); if (!newsk) goto exit_nonewsk; newsk->sk_gso_type = SKB_GSO_TCPV4; - sk_setup_caps(newsk, dst); newtp = tcp_sk(newsk); newinet = inet_sk(newsk); @@ -1447,6 +1443,11 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen; newinet->inet_id = newtp->write_seq ^ jiffies; + if (!dst && (dst = inet_csk_route_child_sock(sk, newsk, req)) == NULL) + goto put_and_exit; + + sk_setup_caps(newsk, dst); + tcp_mtup_init(newsk); tcp_sync_mss(newsk, dst_mtu(dst)); newtp->advmss = dst_metric_advmss(dst); @@ -1474,10 +1475,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, } #endif - if (__inet_inherit_port(sk, newsk) < 0) { - sock_put(newsk); - goto exit; - } + if (__inet_inherit_port(sk, newsk) < 0) + goto put_and_exit; __inet_hash_nolisten(newsk, NULL); return newsk; @@ -1489,6 +1488,9 @@ exit_nonewsk: exit: NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); return NULL; +put_and_exit: + sock_put(newsk); + goto exit; } EXPORT_SYMBOL(tcp_v4_syn_recv_sock); -- cgit v1.2.3-58-ga151 From d9d8da805dcb503ef8ee49918a94d49085060f23 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 22:23:20 -0700 Subject: inet: Pass flowi to ->queue_xmit(). This allows us to acquire the exact route keying information from the protocol, however that might be managed. It handles all of the possibilities, from the simplest case of storing the key in inet->cork.fl to the more complex setup SCTP has where individual transports determine the flow. Signed-off-by: David S. Miller --- include/net/inet6_connection_sock.h | 2 +- include/net/inet_connection_sock.h | 2 +- include/net/ip.h | 2 +- net/dccp/output.c | 4 ++-- net/ipv4/ip_output.c | 4 ++-- net/ipv4/tcp_output.c | 2 +- net/ipv6/inet6_connection_sock.c | 2 +- net/l2tp/l2tp_core.c | 10 ++++++---- net/l2tp/l2tp_ip.c | 2 +- net/sctp/protocol.c | 2 +- 10 files changed, 17 insertions(+), 15 deletions(-) diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h index ff013505236b..3207e58ee019 100644 --- a/include/net/inet6_connection_sock.h +++ b/include/net/inet6_connection_sock.h @@ -41,5 +41,5 @@ extern void inet6_csk_reqsk_queue_hash_add(struct sock *sk, extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr); -extern int inet6_csk_xmit(struct sk_buff *skb); +extern int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl); #endif /* _INET6_CONNECTION_SOCK_H */ diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 4367d913c0e2..96546cae1cba 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -36,7 +36,7 @@ struct tcp_congestion_ops; * (i.e. things that depend on the address family) */ struct inet_connection_sock_af_ops { - int (*queue_xmit)(struct sk_buff *skb); + int (*queue_xmit)(struct sk_buff *skb, struct flowi *fl); void (*send_check)(struct sock *sk, struct sk_buff *skb); int (*rebuild_header)(struct sock *sk); int (*conn_request)(struct sock *sk, struct sk_buff *skb); diff --git a/include/net/ip.h b/include/net/ip.h index 095e392d5f16..acf8b7814c4e 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -104,7 +104,7 @@ extern int ip_do_nat(struct sk_buff *skb); extern void ip_send_check(struct iphdr *ip); extern int __ip_local_out(struct sk_buff *skb); extern int ip_local_out(struct sk_buff *skb); -extern int ip_queue_xmit(struct sk_buff *skb); +extern int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl); extern void ip_init(void); extern int ip_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, diff --git a/net/dccp/output.c b/net/dccp/output.c index 136d41cbcd02..fab108e51e5a 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -43,7 +43,7 @@ static void dccp_skb_entail(struct sock *sk, struct sk_buff *skb) static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) { if (likely(skb != NULL)) { - const struct inet_sock *inet = inet_sk(sk); + struct inet_sock *inet = inet_sk(sk); const struct inet_connection_sock *icsk = inet_csk(sk); struct dccp_sock *dp = dccp_sk(sk); struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); @@ -136,7 +136,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) DCCP_INC_STATS(DCCP_MIB_OUTSEGS); - err = icsk->icsk_af_ops->queue_xmit(skb); + err = icsk->icsk_af_ops->queue_xmit(skb, &inet->cork.fl); return net_xmit_eval(err); } return -ENOBUFS; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 4ba26d4040ed..14ee1e47720c 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -312,7 +312,7 @@ int ip_output(struct sk_buff *skb) !(IPCB(skb)->flags & IPSKB_REROUTED)); } -int ip_queue_xmit(struct sk_buff *skb) +int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) { struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(sk); @@ -332,7 +332,7 @@ int ip_queue_xmit(struct sk_buff *skb) goto packet_routed; /* Make sure we can route this packet. */ - fl4 = &inet->cork.fl.u.ip4; + fl4 = &fl->u.ip4; rt = (struct rtable *)__sk_dst_check(sk, 0); if (rt == NULL) { __be32 daddr; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 17388c7f49c4..882e0b0964d0 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -899,7 +899,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS, tcp_skb_pcount(skb)); - err = icsk->icsk_af_ops->queue_xmit(skb); + err = icsk->icsk_af_ops->queue_xmit(skb, &inet->cork.fl); if (likely(err <= 0)) return err; diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index f2c5b0fc0f21..8a58e8cf6646 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -203,7 +203,7 @@ struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) return dst; } -int inet6_csk_xmit(struct sk_buff *skb) +int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) { struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(sk); diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 78530299ae38..9be095e00450 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -954,7 +954,7 @@ static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf) } static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, - size_t data_len) + struct flowi *fl, size_t data_len) { struct l2tp_tunnel *tunnel = session->tunnel; unsigned int len = skb->len; @@ -987,7 +987,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, /* Queue the packet to IP for output */ skb->local_df = 1; - error = ip_queue_xmit(skb); + error = ip_queue_xmit(skb, fl); /* Update stats */ if (error >= 0) { @@ -1028,6 +1028,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len int data_len = skb->len; struct l2tp_tunnel *tunnel = session->tunnel; struct sock *sk = tunnel->sock; + struct flowi *fl; struct udphdr *uh; struct inet_sock *inet; __wsum csum; @@ -1070,10 +1071,11 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len skb_dst_drop(skb); skb_dst_set(skb, dst_clone(__sk_dst_get(sk))); + inet = inet_sk(sk); + fl = &inet->cork.fl; switch (tunnel->encap) { case L2TP_ENCAPTYPE_UDP: /* Setup UDP header */ - inet = inet_sk(sk); __skb_push(skb, sizeof(*uh)); skb_reset_transport_header(skb); uh = udp_hdr(skb); @@ -1111,7 +1113,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len l2tp_skb_set_owner_w(skb, sk); - l2tp_xmit_core(session, skb, data_len); + l2tp_xmit_core(session, skb, fl, data_len); out_unlock: bh_unlock_sock(sk); diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 1ca74892ff09..f7fb09ecaf89 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -508,7 +508,7 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m skb_dst_set(skb, dst_clone(&rt->dst)); /* Queue the packet to IP for output */ - rc = ip_queue_xmit(skb); + rc = ip_queue_xmit(skb, &inet->cork.fl); error: /* Update stats */ diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 69fbc55cf18e..847193b7995f 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -855,7 +855,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, IP_PMTUDISC_DO : IP_PMTUDISC_DONT; SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); - return ip_queue_xmit(skb); + return ip_queue_xmit(skb, &transport->fl); } static struct sctp_af sctp_af_inet; -- cgit v1.2.3-58-ga151 From ea4fc0d6193ff56fcef39b0d2210d402a7acb5f0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 22:30:20 -0700 Subject: ipv4: Don't use rt->rt_{src,dst} in ip_queue_xmit(). Now we can pick it out of the provided flow key. Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 14ee1e47720c..b88ee5fdcbca 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -327,12 +327,12 @@ int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) */ rcu_read_lock(); inet_opt = rcu_dereference(inet->inet_opt); + fl4 = &fl->u.ip4; rt = skb_rtable(skb); if (rt != NULL) goto packet_routed; /* Make sure we can route this packet. */ - fl4 = &fl->u.ip4; rt = (struct rtable *)__sk_dst_check(sk, 0); if (rt == NULL) { __be32 daddr; @@ -360,7 +360,7 @@ int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) skb_dst_set_noref(skb, &rt->dst); packet_routed: - if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_dst != rt->rt_gateway) + if (inet_opt && inet_opt->opt.is_strictroute && fl4->daddr != rt->rt_gateway) goto no_route; /* OK, we know where to send it, allocate and build IP header. */ @@ -374,8 +374,8 @@ packet_routed: iph->frag_off = 0; iph->ttl = ip_select_ttl(inet, &rt->dst); iph->protocol = sk->sk_protocol; - iph->saddr = rt->rt_src; - iph->daddr = rt->rt_dst; + iph->saddr = fl4->saddr; + iph->daddr = fl4->daddr; /* Transport layer set skb->h.foo itself. */ if (inet_opt && inet_opt->opt.optlen) { -- cgit v1.2.3-58-ga151 From f1c0a276ea1786213bda2313cd9034f3a23f2e77 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 22:34:29 -0700 Subject: sctp: Don't use rt->rt_{src,dst} in sctp_v4_xmit() Now we can pick it out of the transport's flow key. Signed-off-by: David S. Miller --- net/sctp/protocol.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 847193b7995f..acb2ee70271f 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -848,8 +848,8 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", __func__, skb, skb->len, - &skb_rtable(skb)->rt_src, - &skb_rtable(skb)->rt_dst); + transport->fl.u.ip4.saddr, + transport->fl.u.ip4.daddr); inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; -- cgit v1.2.3-58-ga151 From c5216cc70fa769e5a51837f2cf07c4a0aa734fcf Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 22:36:30 -0700 Subject: tcp: Use cork flow info instead of rt->rt_dst in tcp_v4_get_peer() Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 374de3c98d5e..2b655031b392 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1773,7 +1773,8 @@ struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it) struct inet_sock *inet = inet_sk(sk); struct inet_peer *peer; - if (!rt || rt->rt_dst != inet->inet_daddr) { + if (!rt || + inet->cork.fl.u.ip4.daddr != inet->inet_daddr) { peer = inet_getpeer_v4(inet->inet_daddr, 1); *release_it = true; } else { -- cgit v1.2.3-58-ga151 From 57cc71bc3c0cf18bfd1b7bc8cd0eb6c303da24c5 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Mon, 2 May 2011 21:30:08 +0000 Subject: ethtool: Add 20G bit definitions Add 20G supported and advertising bit definitions. 20G will be supported with the 57840 chips. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein ------ include/linux/ethtool.h | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) Signed-off-by: David S. Miller --- include/linux/ethtool.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index d659fdc77eb3..bd0b50b85f06 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -1025,6 +1025,8 @@ struct ethtool_ops { #define SUPPORTED_10000baseKX4_Full (1 << 18) #define SUPPORTED_10000baseKR_Full (1 << 19) #define SUPPORTED_10000baseR_FEC (1 << 20) +#define SUPPORTED_20000baseMLD2_Full (1 << 21) +#define SUPPORTED_20000baseKR2_Full (1 << 22) /* Indicates what features are advertised by the interface. */ #define ADVERTISED_10baseT_Half (1 << 0) @@ -1048,6 +1050,8 @@ struct ethtool_ops { #define ADVERTISED_10000baseKX4_Full (1 << 18) #define ADVERTISED_10000baseKR_Full (1 << 19) #define ADVERTISED_10000baseR_FEC (1 << 20) +#define ADVERTISED_20000baseMLD2_Full (1 << 21) +#define ADVERTISED_20000baseKR2_Full (1 << 22) /* The following are all involved in forcing a particular link * mode for the device for setting things. When getting the -- cgit v1.2.3-58-ga151 From 47a0200d535f08ac8f784a709c48995ca0b10288 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 3 May 2011 11:23:40 +0000 Subject: pktgen: use %pI6c for printing IPv6 addresses I don't know why %pI6 doesn't compress, but the format specifier is kernel-standard, so use it. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/core/pktgen.c | 109 +++++++----------------------------------------------- 1 file changed, 13 insertions(+), 96 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index ff79d94b5944..d41d88b53e18 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -449,7 +449,6 @@ static void pktgen_stop(struct pktgen_thread *t); static void pktgen_clear_counters(struct pktgen_dev *pkt_dev); static unsigned int scan_ip6(const char *s, char ip[16]); -static unsigned int fmt_ip6(char *s, const char ip[16]); /* Module parameters, defaults. */ static int pg_count_d __read_mostly = 1000; @@ -556,21 +555,13 @@ static int pktgen_if_show(struct seq_file *seq, void *v) pkt_dev->skb_priority); if (pkt_dev->flags & F_IPV6) { - char b1[128], b2[128], b3[128]; - fmt_ip6(b1, pkt_dev->in6_saddr.s6_addr); - fmt_ip6(b2, pkt_dev->min_in6_saddr.s6_addr); - fmt_ip6(b3, pkt_dev->max_in6_saddr.s6_addr); seq_printf(seq, - " saddr: %s min_saddr: %s max_saddr: %s\n", b1, - b2, b3); - - fmt_ip6(b1, pkt_dev->in6_daddr.s6_addr); - fmt_ip6(b2, pkt_dev->min_in6_daddr.s6_addr); - fmt_ip6(b3, pkt_dev->max_in6_daddr.s6_addr); - seq_printf(seq, - " daddr: %s min_daddr: %s max_daddr: %s\n", b1, - b2, b3); - + " saddr: %pI6c min_saddr: %pI6c max_saddr: %pI6c\n" + " daddr: %pI6c min_daddr: %pI6c max_daddr: %pI6c\n", + &pkt_dev->in6_saddr, + &pkt_dev->min_in6_saddr, &pkt_dev->max_in6_saddr, + &pkt_dev->in6_daddr, + &pkt_dev->min_in6_daddr, &pkt_dev->max_in6_daddr); } else { seq_printf(seq, " dst_min: %s dst_max: %s\n", @@ -706,10 +697,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v) pkt_dev->cur_src_mac_offset); if (pkt_dev->flags & F_IPV6) { - char b1[128], b2[128]; - fmt_ip6(b1, pkt_dev->cur_in6_daddr.s6_addr); - fmt_ip6(b2, pkt_dev->cur_in6_saddr.s6_addr); - seq_printf(seq, " cur_saddr: %s cur_daddr: %s\n", b2, b1); + seq_printf(seq, " cur_saddr: %pI6c cur_daddr: %pI6c\n", + &pkt_dev->cur_in6_saddr, + &pkt_dev->cur_in6_daddr); } else seq_printf(seq, " cur_saddr: 0x%x cur_daddr: 0x%x\n", pkt_dev->cur_saddr, pkt_dev->cur_daddr); @@ -1309,7 +1299,7 @@ static ssize_t pktgen_if_write(struct file *file, buf[len] = 0; scan_ip6(buf, pkt_dev->in6_daddr.s6_addr); - fmt_ip6(buf, pkt_dev->in6_daddr.s6_addr); + snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_daddr); ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->in6_daddr); @@ -1332,7 +1322,7 @@ static ssize_t pktgen_if_write(struct file *file, buf[len] = 0; scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); - fmt_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); + snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->min_in6_daddr); ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->min_in6_daddr); @@ -1355,7 +1345,7 @@ static ssize_t pktgen_if_write(struct file *file, buf[len] = 0; scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); - fmt_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); + snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->max_in6_daddr); if (debug) printk(KERN_DEBUG "pktgen: dst6_max set to: %s\n", buf); @@ -1376,7 +1366,7 @@ static ssize_t pktgen_if_write(struct file *file, buf[len] = 0; scan_ip6(buf, pkt_dev->in6_saddr.s6_addr); - fmt_ip6(buf, pkt_dev->in6_saddr.s6_addr); + snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_saddr); ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &pkt_dev->in6_saddr); @@ -2898,79 +2888,6 @@ static unsigned int scan_ip6(const char *s, char ip[16]) return len; } -static char tohex(char hexdigit) -{ - return hexdigit > 9 ? hexdigit + 'a' - 10 : hexdigit + '0'; -} - -static int fmt_xlong(char *s, unsigned int i) -{ - char *bak = s; - *s = tohex((i >> 12) & 0xf); - if (s != bak || *s != '0') - ++s; - *s = tohex((i >> 8) & 0xf); - if (s != bak || *s != '0') - ++s; - *s = tohex((i >> 4) & 0xf); - if (s != bak || *s != '0') - ++s; - *s = tohex(i & 0xf); - return s - bak + 1; -} - -static unsigned int fmt_ip6(char *s, const char ip[16]) -{ - unsigned int len; - unsigned int i; - unsigned int temp; - unsigned int compressing; - int j; - - len = 0; - compressing = 0; - for (j = 0; j < 16; j += 2) { - -#ifdef V4MAPPEDPREFIX - if (j == 12 && !memcmp(ip, V4mappedprefix, 12)) { - inet_ntoa_r(*(struct in_addr *)(ip + 12), s); - temp = strlen(s); - return len + temp; - } -#endif - temp = ((unsigned long)(unsigned char)ip[j] << 8) + - (unsigned long)(unsigned char)ip[j + 1]; - if (temp == 0) { - if (!compressing) { - compressing = 1; - if (j == 0) { - *s++ = ':'; - ++len; - } - } - } else { - if (compressing) { - compressing = 0; - *s++ = ':'; - ++len; - } - i = fmt_xlong(s, temp); - len += i; - s += i; - if (j < 14) { - *s++ = ':'; - ++len; - } - } - } - if (compressing) { - *s++ = ':'; - ++len; - } - *s = 0; - return len; -} - static struct sk_buff *fill_packet_ipv6(struct net_device *odev, struct pktgen_dev *pkt_dev) { -- cgit v1.2.3-58-ga151 From eed2a12f1ed9aabf0676f4d0db34aad51976c5c6 Mon Sep 17 00:00:00 2001 From: Mahesh Bandewar Date: Wed, 4 May 2011 15:30:11 +0000 Subject: net: Allow ethtool to set interface in loopback mode. This patch enables ethtool to set the loopback mode on a given interface. By configuring the interface in loopback mode in conjunction with a policy route / rule, a userland application can stress the egress / ingress path exposing the flows of the change in progress and potentially help developer(s) understand the impact of those changes without even sending a packet out on the network. Following set of commands illustrates one such example - a) ip -4 addr add 192.168.1.1/24 dev eth1 b) ip -4 rule add from all iif eth1 lookup 250 c) ip -4 route add local 0/0 dev lo proto kernel scope host table 250 d) arp -Ds 192.168.1.100 eth1 e) arp -Ds 192.168.1.200 eth1 f) sysctl -w net.ipv4.ip_nonlocal_bind=1 g) sysctl -w net.ipv4.conf.all.accept_local=1 # Assuming that the machine has 8 cores h) taskset 000f netserver -L 192.168.1.200 i) taskset 00f0 netperf -t TCP_CRR -L 192.168.1.100 -H 192.168.1.200 -l 30 Signed-off-by: Mahesh Bandewar Acked-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/loopback.c | 3 ++- include/linux/netdevice.h | 3 ++- net/core/ethtool.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index d70fb76edb77..4ce9e5f2c069 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -174,7 +174,8 @@ static void loopback_setup(struct net_device *dev) | NETIF_F_HIGHDMA | NETIF_F_LLTX | NETIF_F_NETNS_LOCAL - | NETIF_F_VLAN_CHALLENGED; + | NETIF_F_VLAN_CHALLENGED + | NETIF_F_LOOPBACK; dev->ethtool_ops = &loopback_ethtool_ops; dev->header_ops = ð_header_ops; dev->netdev_ops = &loopback_ops; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index d5de66af46f9..e7244ed1f9a8 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1067,6 +1067,7 @@ struct net_device { #define NETIF_F_RXHASH (1 << 28) /* Receive hashing offload */ #define NETIF_F_RXCSUM (1 << 29) /* Receive checksumming offload */ #define NETIF_F_NOCACHE_COPY (1 << 30) /* Use no-cache copyfromuser */ +#define NETIF_F_LOOPBACK (1 << 31) /* Enable loopback */ /* Segmentation offload features */ #define NETIF_F_GSO_SHIFT 16 @@ -1082,7 +1083,7 @@ struct net_device { /* = all defined minus driver/device-class-related */ #define NETIF_F_NEVER_CHANGE (NETIF_F_VLAN_CHALLENGED | \ NETIF_F_LLTX | NETIF_F_NETNS_LOCAL) -#define NETIF_F_ETHTOOL_BITS (0x7f3fffff & ~NETIF_F_NEVER_CHANGE) +#define NETIF_F_ETHTOOL_BITS (0xff3fffff & ~NETIF_F_NEVER_CHANGE) /* List of features with software fallbacks. */ #define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | \ diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 927819d92248..b6f405888538 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -362,7 +362,7 @@ static const char netdev_features_strings[ETHTOOL_DEV_FEATURE_WORDS * 32][ETH_GS /* NETIF_F_RXHASH */ "rx-hashing", /* NETIF_F_RXCSUM */ "rx-checksum", /* NETIF_F_NOCACHE_COPY */ "tx-nocache-copy" - "", + /* NETIF_F_LOOPBACK */ "loopback", }; static int __ethtool_get_sset_count(struct net_device *dev, int sset) -- cgit v1.2.3-58-ga151 From e474995f290ff7bc236b549aa9a89ae445ee5b1b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 8 May 2011 16:38:45 -0700 Subject: udp: Use flow key information instead of rt->rt_{src,dst} We have two cases. Either the socket is in TCP_ESTABLISHED state and connect() filled in the inet socket cork flow, or we looked up the route here and used an on-stack flow. Track which one it was, and use it to obtain src/dst addrs. Signed-off-by: David S. Miller --- net/ipv4/udp.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 544f435d1aff..ba9f137f5aa7 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -791,6 +791,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, { struct inet_sock *inet = inet_sk(sk); struct udp_sock *up = udp_sk(sk); + struct flowi4 fl4_stack; struct flowi4 *fl4; int ulen = len; struct ipcm_cookie ipc; @@ -919,17 +920,18 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (connected) rt = (struct rtable *)sk_dst_check(sk, 0); + fl4 = &inet->cork.fl.u.ip4; if (rt == NULL) { - struct flowi4 fl4; struct net *net = sock_net(sk); - flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, + fl4 = &fl4_stack; + flowi4_init_output(fl4, ipc.oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE, sk->sk_protocol, inet_sk_flowi_flags(sk)|FLOWI_FLAG_CAN_SLEEP, faddr, saddr, dport, inet->inet_sport); - security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); - rt = ip_route_output_flow(net, &fl4, sk); + security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); + rt = ip_route_output_flow(net, fl4, sk); if (IS_ERR(rt)) { err = PTR_ERR(rt); rt = NULL; @@ -950,9 +952,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto do_confirm; back_from_confirm: - saddr = rt->rt_src; + saddr = fl4->saddr; if (!ipc.addr) - daddr = ipc.addr = rt->rt_dst; + daddr = ipc.addr = fl4->daddr; /* Lockless fast path for the non-corking case. */ if (!corkreq) { -- cgit v1.2.3-58-ga151 From 77968b78242ee25e2a4d759f0fca8dd52df6d479 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 8 May 2011 17:12:19 -0700 Subject: ipv4: Pass flow keys down into datagram packet building engine. This way ip_output.c no longer needs rt->rt_{src,dst}. We already have these keys sitting, ready and waiting, on the stack or in a socket structure. Signed-off-by: David S. Miller --- include/net/ip.h | 8 +++--- net/ipv4/icmp.c | 74 +++++++++++++++++++++++++--------------------------- net/ipv4/ip_output.c | 39 ++++++++++++++------------- net/ipv4/raw.c | 59 ++++++++++++++++++++--------------------- net/ipv4/udp.c | 4 +-- 5 files changed, 91 insertions(+), 93 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index acf8b7814c4e..a4253795c5c5 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -117,12 +117,14 @@ extern int ip_generic_getfrag(void *from, char *to, int offset, int len, int od extern ssize_t ip_append_page(struct sock *sk, struct page *page, int offset, size_t size, int flags); extern struct sk_buff *__ip_make_skb(struct sock *sk, + struct flowi4 *fl4, struct sk_buff_head *queue, struct inet_cork *cork); extern int ip_send_skb(struct sk_buff *skb); -extern int ip_push_pending_frames(struct sock *sk); +extern int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4); extern void ip_flush_pending_frames(struct sock *sk); extern struct sk_buff *ip_make_skb(struct sock *sk, + struct flowi4 *fl4, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from, int length, int transhdrlen, @@ -130,9 +132,9 @@ extern struct sk_buff *ip_make_skb(struct sock *sk, struct rtable **rtp, unsigned int flags); -static inline struct sk_buff *ip_finish_skb(struct sock *sk) +static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4) { - return __ip_make_skb(sk, &sk->sk_write_queue, &inet_sk(sk)->cork.base); + return __ip_make_skb(sk, fl4, &sk->sk_write_queue, &inet_sk(sk)->cork.base); } /* datagram.c */ diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index cfeca3c2152d..be5cc8d04c00 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -290,6 +290,7 @@ static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd, } static void icmp_push_reply(struct icmp_bxm *icmp_param, + struct flowi4 *fl4, struct ipcm_cookie *ipc, struct rtable **rt) { struct sock *sk; @@ -315,7 +316,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param, icmp_param->head_len, csum); icmph->checksum = csum_fold(csum); skb->ip_summed = CHECKSUM_NONE; - ip_push_pending_frames(sk); + ip_push_pending_frames(sk, fl4); } } @@ -328,6 +329,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) struct ipcm_cookie ipc; struct rtable *rt = skb_rtable(skb); struct net *net = dev_net(rt->dst.dev); + struct flowi4 fl4; struct sock *sk; struct inet_sock *inet; __be32 daddr; @@ -351,57 +353,52 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) if (ipc.opt->opt.srr) daddr = icmp_param->replyopts.opt.opt.faddr; } - { - struct flowi4 fl4 = { - .daddr = daddr, - .saddr = rt->rt_spec_dst, - .flowi4_tos = RT_TOS(ip_hdr(skb)->tos), - .flowi4_proto = IPPROTO_ICMP, - }; - security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); - rt = ip_route_output_key(net, &fl4); - if (IS_ERR(rt)) - goto out_unlock; - } + memset(&fl4, 0, sizeof(fl4)); + fl4.daddr = daddr; + fl4.saddr = rt->rt_spec_dst; + fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); + fl4.flowi4_proto = IPPROTO_ICMP; + security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); + rt = ip_route_output_key(net, &fl4); + if (IS_ERR(rt)) + goto out_unlock; if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type, icmp_param->data.icmph.code)) - icmp_push_reply(icmp_param, &ipc, &rt); + icmp_push_reply(icmp_param, &fl4, &ipc, &rt); ip_rt_put(rt); out_unlock: icmp_xmit_unlock(sk); } -static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in, +static struct rtable *icmp_route_lookup(struct net *net, + struct flowi4 *fl4, + struct sk_buff *skb_in, const struct iphdr *iph, __be32 saddr, u8 tos, int type, int code, struct icmp_bxm *param) { - struct flowi4 fl4 = { - .daddr = (param->replyopts.opt.opt.srr ? - param->replyopts.opt.opt.faddr : iph->saddr), - .saddr = saddr, - .flowi4_tos = RT_TOS(tos), - .flowi4_proto = IPPROTO_ICMP, - .fl4_icmp_type = type, - .fl4_icmp_code = code, - }; struct rtable *rt, *rt2; int err; - security_skb_classify_flow(skb_in, flowi4_to_flowi(&fl4)); - rt = __ip_route_output_key(net, &fl4); + memset(fl4, 0, sizeof(*fl4)); + fl4->daddr = (param->replyopts.opt.opt.srr ? + param->replyopts.opt.opt.faddr : iph->saddr); + fl4->saddr = saddr; + fl4->flowi4_tos = RT_TOS(tos); + fl4->flowi4_proto = IPPROTO_ICMP; + fl4->fl4_icmp_type = type; + fl4->fl4_icmp_code = code; + security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4)); + rt = __ip_route_output_key(net, fl4); if (IS_ERR(rt)) return rt; /* No need to clone since we're just using its address. */ rt2 = rt; - if (!fl4.saddr) - fl4.saddr = rt->rt_src; - rt = (struct rtable *) xfrm_lookup(net, &rt->dst, - flowi4_to_flowi(&fl4), NULL, 0); + flowi4_to_flowi(fl4), NULL, 0); if (!IS_ERR(rt)) { if (rt != rt2) return rt; @@ -410,19 +407,19 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in, } else return rt; - err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(&fl4), AF_INET); + err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(fl4), AF_INET); if (err) goto relookup_failed; - if (inet_addr_type(net, fl4.saddr) == RTN_LOCAL) { - rt2 = __ip_route_output_key(net, &fl4); + if (inet_addr_type(net, fl4->saddr) == RTN_LOCAL) { + rt2 = __ip_route_output_key(net, fl4); if (IS_ERR(rt2)) err = PTR_ERR(rt2); } else { struct flowi4 fl4_2 = {}; unsigned long orefdst; - fl4_2.daddr = fl4.saddr; + fl4_2.daddr = fl4->saddr; rt2 = ip_route_output_key(net, &fl4_2); if (IS_ERR(rt2)) { err = PTR_ERR(rt2); @@ -430,7 +427,7 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in, } /* Ugh! */ orefdst = skb_in->_skb_refdst; /* save old refdst */ - err = ip_route_input(skb_in, fl4.daddr, fl4.saddr, + err = ip_route_input(skb_in, fl4->daddr, fl4->saddr, RT_TOS(tos), rt2->dst.dev); dst_release(&rt2->dst); @@ -442,7 +439,7 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in, goto relookup_failed; rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst, - flowi4_to_flowi(&fl4), NULL, + flowi4_to_flowi(fl4), NULL, XFRM_LOOKUP_ICMP); if (!IS_ERR(rt2)) { dst_release(&rt->dst); @@ -481,6 +478,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) struct icmp_bxm icmp_param; struct rtable *rt = skb_rtable(skb_in); struct ipcm_cookie ipc; + struct flowi4 fl4; __be32 saddr; u8 tos; struct net *net; @@ -599,7 +597,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) ipc.opt = &icmp_param.replyopts.opt; ipc.tx_flags = 0; - rt = icmp_route_lookup(net, skb_in, iph, saddr, tos, + rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos, type, code, &icmp_param); if (IS_ERR(rt)) goto out_unlock; @@ -620,7 +618,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) icmp_param.data_len = room; icmp_param.head_len = sizeof(struct icmphdr); - icmp_push_reply(&icmp_param, &ipc, &rt); + icmp_push_reply(&icmp_param, &fl4, &ipc, &rt); ende: ip_rt_put(rt); out_unlock: diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index b88ee5fdcbca..dca637b9d8ae 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1267,6 +1267,7 @@ static void ip_cork_release(struct inet_cork *cork) * and push them out. */ struct sk_buff *__ip_make_skb(struct sock *sk, + struct flowi4 *fl4, struct sk_buff_head *queue, struct inet_cork *cork) { @@ -1333,8 +1334,8 @@ struct sk_buff *__ip_make_skb(struct sock *sk, ip_select_ident(iph, &rt->dst, sk); iph->ttl = ttl; iph->protocol = sk->sk_protocol; - iph->saddr = rt->rt_src; - iph->daddr = rt->rt_dst; + iph->saddr = fl4->saddr; + iph->daddr = fl4->daddr; skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; @@ -1370,11 +1371,11 @@ int ip_send_skb(struct sk_buff *skb) return err; } -int ip_push_pending_frames(struct sock *sk) +int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4) { struct sk_buff *skb; - skb = ip_finish_skb(sk); + skb = ip_finish_skb(sk, fl4); if (!skb) return 0; @@ -1403,6 +1404,7 @@ void ip_flush_pending_frames(struct sock *sk) } struct sk_buff *ip_make_skb(struct sock *sk, + struct flowi4 *fl4, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from, int length, int transhdrlen, @@ -1432,7 +1434,7 @@ struct sk_buff *ip_make_skb(struct sock *sk, return ERR_PTR(err); } - return __ip_make_skb(sk, &queue, &cork); + return __ip_make_skb(sk, fl4, &queue, &cork); } /* @@ -1461,6 +1463,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar struct inet_sock *inet = inet_sk(sk); struct ip_options_data replyopts; struct ipcm_cookie ipc; + struct flowi4 fl4; __be32 daddr; struct rtable *rt = skb_rtable(skb); @@ -1478,20 +1481,16 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar daddr = replyopts.opt.opt.faddr; } - { - struct flowi4 fl4; - - flowi4_init_output(&fl4, arg->bound_dev_if, 0, - RT_TOS(ip_hdr(skb)->tos), - RT_SCOPE_UNIVERSE, sk->sk_protocol, - ip_reply_arg_flowi_flags(arg), - daddr, rt->rt_spec_dst, - tcp_hdr(skb)->source, tcp_hdr(skb)->dest); - security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); - rt = ip_route_output_key(sock_net(sk), &fl4); - if (IS_ERR(rt)) - return; - } + flowi4_init_output(&fl4, arg->bound_dev_if, 0, + RT_TOS(ip_hdr(skb)->tos), + RT_SCOPE_UNIVERSE, sk->sk_protocol, + ip_reply_arg_flowi_flags(arg), + daddr, rt->rt_spec_dst, + tcp_hdr(skb)->source, tcp_hdr(skb)->dest); + security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); + rt = ip_route_output_key(sock_net(sk), &fl4); + if (IS_ERR(rt)) + return; /* And let IP do all the hard work. @@ -1512,7 +1511,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar arg->csumoffset) = csum_fold(csum_add(skb->csum, arg->csum)); skb->ip_summed = CHECKSUM_NONE; - ip_push_pending_frames(sk); + ip_push_pending_frames(sk, &fl4); } bh_unlock_sock(sk); diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index a8659e0c4a6e..6fee91f656a9 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -314,9 +314,10 @@ int raw_rcv(struct sock *sk, struct sk_buff *skb) return 0; } -static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, - struct rtable **rtp, - unsigned int flags) +static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, + void *from, size_t length, + struct rtable **rtp, + unsigned int flags) { struct inet_sock *inet = inet_sk(sk); struct net *net = sock_net(sk); @@ -327,7 +328,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, struct rtable *rt = *rtp; if (length > rt->dst.dev->mtu) { - ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport, + ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, rt->dst.dev->mtu); return -EMSGSIZE; } @@ -372,7 +373,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, if (iphlen >= sizeof(*iph)) { if (!iph->saddr) - iph->saddr = rt->rt_src; + iph->saddr = fl4->saddr; iph->check = 0; iph->tot_len = htons(length); if (!iph->id) @@ -455,6 +456,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, struct inet_sock *inet = inet_sk(sk); struct ipcm_cookie ipc; struct rtable *rt = NULL; + struct flowi4 fl4; int free = 0; __be32 daddr; __be32 saddr; @@ -558,27 +560,23 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, saddr = inet->mc_addr; } - { - struct flowi4 fl4; + flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, + RT_SCOPE_UNIVERSE, + inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, + FLOWI_FLAG_CAN_SLEEP, daddr, saddr, 0, 0); - flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, - RT_SCOPE_UNIVERSE, - inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, - FLOWI_FLAG_CAN_SLEEP, daddr, saddr, 0, 0); - - if (!inet->hdrincl) { - err = raw_probe_proto_opt(&fl4, msg); - if (err) - goto done; - } - - security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); - rt = ip_route_output_flow(sock_net(sk), &fl4, sk); - if (IS_ERR(rt)) { - err = PTR_ERR(rt); - rt = NULL; + if (!inet->hdrincl) { + err = raw_probe_proto_opt(&fl4, msg); + if (err) goto done; - } + } + + security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); + rt = ip_route_output_flow(sock_net(sk), &fl4, sk); + if (IS_ERR(rt)) { + err = PTR_ERR(rt); + rt = NULL; + goto done; } err = -EACCES; @@ -590,19 +588,20 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, back_from_confirm: if (inet->hdrincl) - err = raw_send_hdrinc(sk, msg->msg_iov, len, - &rt, msg->msg_flags); + err = raw_send_hdrinc(sk, &fl4, msg->msg_iov, len, + &rt, msg->msg_flags); else { if (!ipc.addr) - ipc.addr = rt->rt_dst; + ipc.addr = fl4.daddr; lock_sock(sk); - err = ip_append_data(sk, ip_generic_getfrag, msg->msg_iov, len, 0, - &ipc, &rt, msg->msg_flags); + err = ip_append_data(sk, ip_generic_getfrag, + msg->msg_iov, len, 0, + &ipc, &rt, msg->msg_flags); if (err) ip_flush_pending_frames(sk); else if (!(msg->msg_flags & MSG_MORE)) { - err = ip_push_pending_frames(sk); + err = ip_push_pending_frames(sk, &fl4); if (err == -ENOBUFS && !inet->recverr) err = 0; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index ba9f137f5aa7..006e2ccd6cc2 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -774,7 +774,7 @@ static int udp_push_pending_frames(struct sock *sk) struct sk_buff *skb; int err = 0; - skb = ip_finish_skb(sk); + skb = ip_finish_skb(sk, fl4); if (!skb) goto out; @@ -958,7 +958,7 @@ back_from_confirm: /* Lockless fast path for the non-corking case. */ if (!corkreq) { - skb = ip_make_skb(sk, getfrag, msg->msg_iov, ulen, + skb = ip_make_skb(sk, fl4, getfrag, msg->msg_iov, ulen, sizeof(struct udphdr), &ipc, &rt, msg->msg_flags); err = PTR_ERR(skb); -- cgit v1.2.3-58-ga151 From f5fca6086511294653a9e821f8e22f041415ba7b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 8 May 2011 17:24:10 -0700 Subject: ipv4: Pass flow key down into ip_append_*(). This way rt->rt_dst accesses are unnecessary. Signed-off-by: David S. Miller --- include/net/ip.h | 4 ++-- net/ipv4/icmp.c | 2 +- net/ipv4/ip_output.c | 18 ++++++++++-------- net/ipv4/raw.c | 2 +- net/ipv4/udp.c | 12 +++++++----- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index a4253795c5c5..0b30d3ab4a30 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -106,7 +106,7 @@ extern int __ip_local_out(struct sk_buff *skb); extern int ip_local_out(struct sk_buff *skb); extern int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl); extern void ip_init(void); -extern int ip_append_data(struct sock *sk, +extern int ip_append_data(struct sock *sk, struct flowi4 *fl4, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from, int len, int protolen, @@ -114,7 +114,7 @@ extern int ip_append_data(struct sock *sk, struct rtable **rt, unsigned int flags); extern int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb); -extern ssize_t ip_append_page(struct sock *sk, struct page *page, +extern ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, int offset, size_t size, int flags); extern struct sk_buff *__ip_make_skb(struct sock *sk, struct flowi4 *fl4, diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index be5cc8d04c00..853a670f6df6 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -297,7 +297,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb; sk = icmp_sk(dev_net((*rt)->dst.dev)); - if (ip_append_data(sk, icmp_glue_bits, icmp_param, + if (ip_append_data(sk, fl4, icmp_glue_bits, icmp_param, icmp_param->data_len+icmp_param->head_len, icmp_param->head_len, ipc, rt, MSG_DONTWAIT) < 0) { diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index dca637b9d8ae..cd89d22902a9 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -776,7 +776,9 @@ static inline int ip_ufo_append_data(struct sock *sk, (length - transhdrlen)); } -static int __ip_append_data(struct sock *sk, struct sk_buff_head *queue, +static int __ip_append_data(struct sock *sk, + struct flowi4 *fl4, + struct sk_buff_head *queue, struct inet_cork *cork, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), @@ -808,7 +810,7 @@ static int __ip_append_data(struct sock *sk, struct sk_buff_head *queue, maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; if (cork->length + length > 0xFFFF - fragheaderlen) { - ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport, + ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, mtu-exthdrlen); return -EMSGSIZE; } @@ -1083,7 +1085,7 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, * * LATER: length must be adjusted by pad at tail, when it is required. */ -int ip_append_data(struct sock *sk, +int ip_append_data(struct sock *sk, struct flowi4 *fl4, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from, int length, int transhdrlen, @@ -1104,11 +1106,11 @@ int ip_append_data(struct sock *sk, transhdrlen = 0; } - return __ip_append_data(sk, &sk->sk_write_queue, &inet->cork.base, getfrag, + return __ip_append_data(sk, fl4, &sk->sk_write_queue, &inet->cork.base, getfrag, from, length, transhdrlen, flags); } -ssize_t ip_append_page(struct sock *sk, struct page *page, +ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, int offset, size_t size, int flags) { struct inet_sock *inet = inet_sk(sk); @@ -1146,7 +1148,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; if (cork->length + size > 0xFFFF - fragheaderlen) { - ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport, mtu); + ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, mtu); return -EMSGSIZE; } @@ -1427,7 +1429,7 @@ struct sk_buff *ip_make_skb(struct sock *sk, if (err) return ERR_PTR(err); - err = __ip_append_data(sk, &queue, &cork, getfrag, + err = __ip_append_data(sk, fl4, &queue, &cork, getfrag, from, length, transhdrlen, flags); if (err) { __ip_flush_pending_frames(sk, &queue, &cork); @@ -1503,7 +1505,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar sk->sk_priority = skb->priority; sk->sk_protocol = ip_hdr(skb)->protocol; sk->sk_bound_dev_if = arg->bound_dev_if; - ip_append_data(sk, ip_reply_glue_bits, arg->iov->iov_base, len, 0, + ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, len, 0, &ipc, &rt, MSG_DONTWAIT); if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) { if (arg->csumoffset >= 0) diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 6fee91f656a9..11e1780455f2 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -595,7 +595,7 @@ back_from_confirm: if (!ipc.addr) ipc.addr = fl4.daddr; lock_sock(sk); - err = ip_append_data(sk, ip_generic_getfrag, + err = ip_append_data(sk, &fl4, ip_generic_getfrag, msg->msg_iov, len, 0, &ipc, &rt, msg->msg_flags); if (err) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 006e2ccd6cc2..66341a3c8d36 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -822,6 +822,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; + fl4 = &inet->cork.fl.u.ip4; if (up->pending) { /* * There are pending frames. @@ -920,7 +921,6 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (connected) rt = (struct rtable *)sk_dst_check(sk, 0); - fl4 = &inet->cork.fl.u.ip4; if (rt == NULL) { struct net *net = sock_net(sk); @@ -989,9 +989,9 @@ back_from_confirm: do_append_data: up->len += ulen; - err = ip_append_data(sk, getfrag, msg->msg_iov, ulen, - sizeof(struct udphdr), &ipc, &rt, - corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); + err = ip_append_data(sk, fl4, getfrag, msg->msg_iov, ulen, + sizeof(struct udphdr), &ipc, &rt, + corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); if (err) udp_flush_pending_frames(sk); else if (!corkreq) @@ -1031,6 +1031,7 @@ EXPORT_SYMBOL(udp_sendmsg); int udp_sendpage(struct sock *sk, struct page *page, int offset, size_t size, int flags) { + struct inet_sock *inet = inet_sk(sk); struct udp_sock *up = udp_sk(sk); int ret; @@ -1055,7 +1056,8 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset, return -EINVAL; } - ret = ip_append_page(sk, page, offset, size, flags); + ret = ip_append_page(sk, &inet->cork.fl.u.ip4, + page, offset, size, flags); if (ret == -EOPNOTSUPP) { release_sock(sk); return sock_no_sendpage(sk->sk_socket, page, offset, -- cgit v1.2.3-58-ga151 From 7ef73bca731fea9d4b706db2acb96b6488aa1b0e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 8 May 2011 21:14:41 -0700 Subject: sctp: Fix debug message args. I messed things up when I converted over to the transport flow, I passed the ipv4 address value instead of it's address. Reported-by: Stephen Rothwell Signed-off-by: David S. Miller --- net/sctp/protocol.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index acb2ee70271f..4f270ac48226 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -848,8 +848,8 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", __func__, skb, skb->len, - transport->fl.u.ip4.saddr, - transport->fl.u.ip4.daddr); + &transport->fl.u.ip4.saddr, + &transport->fl.u.ip4.daddr); inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; -- cgit v1.2.3-58-ga151 From 226bd3411471af42f7edbdfaf73f2d54ebb62a66 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 8 May 2011 23:17:57 +0000 Subject: net: use batched device unregister in veth and macvlan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit veth devices dont use the batched device unregisters yet. Since veth are a pair of devices, it makes sense to use a batch of two unregisters, this roughly divides dismantle time by two. Fix this by changing dellink() callers to always provide a non NULL head. (Idea from Michał Mirosław) This patch also handles macvlan case : We now dismantle all macvlans on top of a lower dev at once. Reported-by: Alex Bligh Signed-off-by: Eric Dumazet Cc: Michał Mirosław Cc: Jesse Gross Cc: Paul E. McKenney Cc: Ben Greear Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 5 ++++- net/core/rtnetlink.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 3ad5425b82dd..d7c0bc62da7f 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -785,6 +785,7 @@ static int macvlan_device_event(struct notifier_block *unused, struct net_device *dev = ptr; struct macvlan_dev *vlan, *next; struct macvlan_port *port; + LIST_HEAD(list_kill); if (!macvlan_port_exists(dev)) return NOTIFY_DONE; @@ -810,7 +811,9 @@ static int macvlan_device_event(struct notifier_block *unused, break; list_for_each_entry_safe(vlan, next, &port->vlans, list) - vlan->dev->rtnl_link_ops->dellink(vlan->dev, NULL); + vlan->dev->rtnl_link_ops->dellink(vlan->dev, &list_kill); + unregister_netdevice_many(&list_kill); + list_del(&list_kill); break; case NETDEV_PRE_TYPE_CHANGE: /* Forbid underlaying device to change its type. */ diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 5a160f4a1ba0..d2ba2597c75a 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1501,6 +1501,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) char ifname[IFNAMSIZ]; struct nlattr *tb[IFLA_MAX+1]; int err; + LIST_HEAD(list_kill); err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); if (err < 0) @@ -1524,7 +1525,9 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) if (!ops) return -EOPNOTSUPP; - ops->dellink(dev, NULL); + ops->dellink(dev, &list_kill); + unregister_netdevice_many(&list_kill); + list_del(&list_kill); return 0; } -- cgit v1.2.3-58-ga151 From da37e368763f708d2ae5a81e61ec59372b831cf5 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 9 May 2011 03:35:55 +0000 Subject: garp: remove one synchronize_rcu() call Speedup vlan dismantling in CONFIG_VLAN_8021Q_GVRP=y cases, by using a call_rcu() to free the memory instead of waiting with expensive synchronize_rcu() [ while RTNL is held ] Signed-off-by: Eric Dumazet Cc: Ben Greear Cc: Patrick McHardy Cc: Paul E. McKenney Signed-off-by: David S. Miller --- include/net/garp.h | 1 + net/802/garp.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/net/garp.h b/include/net/garp.h index f4c295984c45..8cabbf087169 100644 --- a/include/net/garp.h +++ b/include/net/garp.h @@ -108,6 +108,7 @@ struct garp_applicant { struct garp_port { struct garp_applicant __rcu *applicants[GARP_APPLICATION_MAX + 1]; + struct rcu_head rcu; }; extern int garp_register_application(struct garp_application *app); diff --git a/net/802/garp.c b/net/802/garp.c index c1df2dad8c6b..5dbe8967bbd5 100644 --- a/net/802/garp.c +++ b/net/802/garp.c @@ -544,6 +544,11 @@ static int garp_init_port(struct net_device *dev) return 0; } +static void garp_kfree_rcu(struct rcu_head *head) +{ + kfree(container_of(head, struct garp_port, rcu)); +} + static void garp_release_port(struct net_device *dev) { struct garp_port *port = rtnl_dereference(dev->garp_port); @@ -554,8 +559,7 @@ static void garp_release_port(struct net_device *dev) return; } rcu_assign_pointer(dev->garp_port, NULL); - synchronize_rcu(); - kfree(port); + call_rcu(&port->rcu, garp_kfree_rcu); } int garp_init_applicant(struct net_device *dev, struct garp_application *appl) -- cgit v1.2.3-58-ga151 From 48752e1b1802231ef2a076f34d861918b7d571c3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 9 May 2011 04:40:44 +0000 Subject: vlan: remove one synchronize_net() call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At VLAN dismantle phase, unregister_vlan_dev() makes one synchronize_net() call after vlan_group_set_device(grp, vlan_id, NULL). This call can be safely removed because we are calling unregister_netdevice_queue() to queue device for deletion, and this process needs at least one rcu grace period to complete. Signed-off-by: Eric Dumazet Cc: Ben Greear Cc: Patrick McHardy Cc: Paul E. McKenney Cc: Jesse Gross Cc: Michał Mirosław Acked-by: Jesse Gross Signed-off-by: David S. Miller --- include/linux/if_vlan.h | 1 - net/8021q/vlan.c | 10 ++++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 546d9d35fbd4..290bd8ac94cf 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -86,7 +86,6 @@ struct vlan_group { * the vlan is attached to. */ unsigned int nr_vlans; - int killall; struct hlist_node hlist; /* linked list */ struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS]; struct rcu_head rcu; diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 969e7004cf86..718d635d3379 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -120,9 +120,10 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) grp->nr_vlans--; vlan_group_set_device(grp, vlan_id, NULL); - if (!grp->killall) - synchronize_net(); - + /* Because unregister_netdevice_queue() makes sure at least one rcu + * grace period is respected before device freeing, + * we dont need to call synchronize_net() here. + */ unregister_netdevice_queue(dev, head); /* If the group is now empty, kill off the group. */ @@ -478,9 +479,6 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, if (dev->reg_state != NETREG_UNREGISTERING) break; - /* Delete all VLANs for this dev. */ - grp->killall = 1; - for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); if (!vlandev) -- cgit v1.2.3-58-ga151 From cecb5fd7c277c1bba161980bb41792a60b56df4a Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 1 Apr 2011 10:21:07 +0200 Subject: r8169: style cleanups. Signed-off-by: Francois Romieu Cc: Realtek linux nic maintainers --- drivers/net/r8169.c | 206 +++++++++++++++++++++++++--------------------------- 1 file changed, 98 insertions(+), 108 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index a8976a753814..c51515f53df1 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -345,7 +345,7 @@ enum rtl8168_registers { #define OCPAR_GPHY_READ_CMD 0x0000f060 RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */ MISC = 0xf0, /* 8168e only. */ - txpla_rst = (1 << 29) +#define TXPLA_RST (1 << 29) }; enum rtl_register_content { @@ -423,7 +423,7 @@ enum rtl_register_content { BWF = (1 << 6), /* Accept Broadcast wakeup frame */ MWF = (1 << 5), /* Accept Multicast wakeup frame */ UWF = (1 << 4), /* Accept Unicast wakeup frame */ - spi_en = (1 << 3), + Spi_en = (1 << 3), LanWake = (1 << 1), /* LanWake enable/disable */ PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ @@ -594,10 +594,10 @@ struct rtl8169_counters { struct rtl8169_private { void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ + struct pci_dev *pci_dev; struct net_device *dev; struct napi_struct napi; - spinlock_t lock; /* spin lock flag */ + spinlock_t lock; u32 msg_enable; u16 txd_version; u16 mac_version; @@ -730,17 +730,19 @@ static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd) #define OOB_CMD_DRIVER_START 0x05 #define OOB_CMD_DRIVER_STOP 0x06 +static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp) +{ + return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10; +} + static void rtl8168_driver_start(struct rtl8169_private *tp) { + u16 reg; int i; - u32 reg; rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START); - if (tp->mac_version == RTL_GIGA_MAC_VER_31) - reg = 0xb8; - else - reg = 0x10; + reg = rtl8168_get_ocp_reg(tp); for (i = 0; i < 10; i++) { msleep(10); @@ -751,15 +753,12 @@ static void rtl8168_driver_start(struct rtl8169_private *tp) static void rtl8168_driver_stop(struct rtl8169_private *tp) { + u16 reg; int i; - u32 reg; rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP); - if (tp->mac_version == RTL_GIGA_MAC_VER_31) - reg = 0xb8; - else - reg = 0x10; + reg = rtl8168_get_ocp_reg(tp); for (i = 0; i < 10; i++) { msleep(10); @@ -770,17 +769,9 @@ static void rtl8168_driver_stop(struct rtl8169_private *tp) static int r8168dp_check_dash(struct rtl8169_private *tp) { - u32 reg; - - if (tp->mac_version == RTL_GIGA_MAC_VER_31) - reg = 0xb8; - else - reg = 0x10; + u16 reg = rtl8168_get_ocp_reg(tp); - if (ocp_read(tp, 0xF, reg) & 0x00008000) - return 1; - else - return 0; + return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0; } static void r8169_mdio_write(void __iomem *ioaddr, int reg_addr, int value) @@ -1080,9 +1071,8 @@ static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp) } static void __rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, - bool pm) + struct rtl8169_private *tp, + void __iomem *ioaddr, bool pm) { unsigned long flags; @@ -1268,16 +1258,16 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && - (tp->mac_version != RTL_GIGA_MAC_VER_08) && - (tp->mac_version != RTL_GIGA_MAC_VER_09) && - (tp->mac_version != RTL_GIGA_MAC_VER_10) && - (tp->mac_version != RTL_GIGA_MAC_VER_13) && - (tp->mac_version != RTL_GIGA_MAC_VER_14) && - (tp->mac_version != RTL_GIGA_MAC_VER_15) && - (tp->mac_version != RTL_GIGA_MAC_VER_16) && - (tp->mac_version != RTL_GIGA_MAC_VER_29) && - (tp->mac_version != RTL_GIGA_MAC_VER_30)) { + if (tp->mac_version != RTL_GIGA_MAC_VER_07 && + tp->mac_version != RTL_GIGA_MAC_VER_08 && + tp->mac_version != RTL_GIGA_MAC_VER_09 && + tp->mac_version != RTL_GIGA_MAC_VER_10 && + tp->mac_version != RTL_GIGA_MAC_VER_13 && + tp->mac_version != RTL_GIGA_MAC_VER_14 && + tp->mac_version != RTL_GIGA_MAC_VER_15 && + tp->mac_version != RTL_GIGA_MAC_VER_16 && + tp->mac_version != RTL_GIGA_MAC_VER_29 && + tp->mac_version != RTL_GIGA_MAC_VER_30) { if (adv & ADVERTISED_1000baseT_Half) giga_ctrl |= ADVERTISE_1000HALF; if (adv & ADVERTISED_1000baseT_Full) @@ -1311,8 +1301,8 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, rtl_writephy(tp, MII_BMCR, bmcr); - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { + if (tp->mac_version == RTL_GIGA_MAC_VER_02 || + tp->mac_version == RTL_GIGA_MAC_VER_03) { if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { rtl_writephy(tp, 0x17, 0x2138); rtl_writephy(tp, 0x0e, 0x0260); @@ -1348,8 +1338,7 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) int ret; spin_lock_irqsave(&tp->lock, flags); - ret = rtl8169_set_speed(dev, - cmd->autoneg, ethtool_cmd_speed(cmd), + ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd), cmd->duplex, cmd->advertising); spin_unlock_irqrestore(&tp->lock, flags); @@ -1507,11 +1496,11 @@ static void rtl8169_update_counters(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; + struct device *d = &tp->pci_dev->dev; struct rtl8169_counters *counters; dma_addr_t paddr; u32 cmd; int wait = 1000; - struct device *d = &tp->pci_dev->dev; /* * Some chips are unable to dump tally counters when the receiver @@ -1531,7 +1520,6 @@ static void rtl8169_update_counters(struct net_device *dev) while (wait--) { if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) { - /* copy updated counters */ memcpy(&tp->counters, counters, sizeof(*counters)); break; } @@ -1751,14 +1739,14 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw) case PHY_BJMPN: if (regno > index) { netif_err(tp, probe, tp->dev, - "Out of range of firmware\n"); + "Out of range of firmware\n"); return; } break; case PHY_READCOUNT_EQ_SKIP: if (index + 2 >= fw_size) { netif_err(tp, probe, tp->dev, - "Out of range of firmware\n"); + "Out of range of firmware\n"); return; } break; @@ -1767,7 +1755,7 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw) case PHY_SKIPN: if (index + 1 + regno >= fw_size) { netif_err(tp, probe, tp->dev, - "Out of range of firmware\n"); + "Out of range of firmware\n"); return; } break; @@ -1823,10 +1811,7 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw) index++; break; case PHY_READCOUNT_EQ_SKIP: - if (count == data) - index += 2; - else - index += 1; + index += (count == data) ? 2 : 1; break; case PHY_COMP_EQ_SKIPN: if (predata == data) @@ -2237,7 +2222,7 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) /* * Tx Error Issue - * enhance line driver power + * Enhance line driver power */ { 0x1f, 0x0002 }, { 0x06, 0x5561 }, @@ -2349,7 +2334,7 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp) /* * Tx Error Issue - * enhance line driver power + * Enhance line driver power */ { 0x1f, 0x0002 }, { 0x06, 0x5561 }, @@ -2548,7 +2533,7 @@ static void rtl8168e_hw_phy_config(struct rtl8169_private *tp) /* For impedance matching */ rtl_writephy(tp, 0x1f, 0x0002); rtl_w1w0_phy(tp, 0x08, 0x8000, 0x7f00); - rtl_writephy(tp, 0x1F, 0x0000); + rtl_writephy(tp, 0x1f, 0x0000); /* PHY auto speed down */ rtl_writephy(tp, 0x1f, 0x0007); @@ -2692,6 +2677,9 @@ static void rtl_hw_phy_config(struct net_device *dev) case RTL_GIGA_MAC_VER_30: rtl8105e_hw_phy_config(tp); break; + case RTL_GIGA_MAC_VER_31: + /* None. */ + break; case RTL_GIGA_MAC_VER_32: case RTL_GIGA_MAC_VER_33: rtl8168e_hw_phy_config(tp); @@ -2828,11 +2816,11 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) rtl8169_phy_reset(dev, tp); rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL, - ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | - (tp->mii.supports_gmii ? - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full : 0)); + ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | + (tp->mii.supports_gmii ? + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full : 0)); if (RTL_R8(PHYstatus) & TBI_Enable) netif_info(tp, link, dev, "TBI auto-negotiating\n"); @@ -2885,7 +2873,8 @@ static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; } -static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) +static int rtl_xmii_ioctl(struct rtl8169_private *tp, + struct mii_ioctl_data *data, int cmd) { switch (cmd) { case SIOCGMIIPHY: @@ -3107,15 +3096,15 @@ static void r8168_pll_power_down(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; - if (((tp->mac_version == RTL_GIGA_MAC_VER_27) || - (tp->mac_version == RTL_GIGA_MAC_VER_28) || - (tp->mac_version == RTL_GIGA_MAC_VER_31)) && + if ((tp->mac_version == RTL_GIGA_MAC_VER_27 || + tp->mac_version == RTL_GIGA_MAC_VER_28 || + tp->mac_version == RTL_GIGA_MAC_VER_31) && r8168dp_check_dash(tp)) { return; } - if (((tp->mac_version == RTL_GIGA_MAC_VER_23) || - (tp->mac_version == RTL_GIGA_MAC_VER_24)) && + if ((tp->mac_version == RTL_GIGA_MAC_VER_23 || + tp->mac_version == RTL_GIGA_MAC_VER_24) && (RTL_R16(CPlusCmd) & ASF)) { return; } @@ -3152,9 +3141,9 @@ static void r8168_pll_power_up(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; - if (((tp->mac_version == RTL_GIGA_MAC_VER_27) || - (tp->mac_version == RTL_GIGA_MAC_VER_28) || - (tp->mac_version == RTL_GIGA_MAC_VER_31)) && + if ((tp->mac_version == RTL_GIGA_MAC_VER_27 || + tp->mac_version == RTL_GIGA_MAC_VER_28 || + tp->mac_version == RTL_GIGA_MAC_VER_31) && r8168dp_check_dash(tp)) { return; } @@ -3469,9 +3458,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl_chip_info[chipset].name, dev->base_addr, dev->dev_addr, (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); - if ((tp->mac_version == RTL_GIGA_MAC_VER_27) || - (tp->mac_version == RTL_GIGA_MAC_VER_28) || - (tp->mac_version == RTL_GIGA_MAC_VER_31)) { + if (tp->mac_version == RTL_GIGA_MAC_VER_27 || + tp->mac_version == RTL_GIGA_MAC_VER_28 || + tp->mac_version == RTL_GIGA_MAC_VER_31) { rtl8168_driver_start(tp); } @@ -3503,9 +3492,9 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); struct rtl8169_private *tp = netdev_priv(dev); - if ((tp->mac_version == RTL_GIGA_MAC_VER_27) || - (tp->mac_version == RTL_GIGA_MAC_VER_28) || - (tp->mac_version == RTL_GIGA_MAC_VER_31)) { + if (tp->mac_version == RTL_GIGA_MAC_VER_27 || + tp->mac_version == RTL_GIGA_MAC_VER_28 || + tp->mac_version == RTL_GIGA_MAC_VER_31) { rtl8168_driver_stop(tp); } @@ -3753,26 +3742,26 @@ static void rtl_hw_start_8169(struct net_device *dev) } RTL_W8(Cfg9346, Cfg9346_Unlock); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) + if (tp->mac_version == RTL_GIGA_MAC_VER_01 || + tp->mac_version == RTL_GIGA_MAC_VER_02 || + tp->mac_version == RTL_GIGA_MAC_VER_03 || + tp->mac_version == RTL_GIGA_MAC_VER_04) RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); RTL_W8(EarlyTxThres, NoEarlyTx); rtl_set_rx_max_size(ioaddr, rx_buf_sz); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) + if (tp->mac_version == RTL_GIGA_MAC_VER_01 || + tp->mac_version == RTL_GIGA_MAC_VER_02 || + tp->mac_version == RTL_GIGA_MAC_VER_03 || + tp->mac_version == RTL_GIGA_MAC_VER_04) rtl_set_rx_tx_config_registers(tp); tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { + if (tp->mac_version == RTL_GIGA_MAC_VER_02 || + tp->mac_version == RTL_GIGA_MAC_VER_03) { dprintk("Set MAC Reg C+CR Offset 0xE0. " "Bit-3 and bit-14 MUST be 1\n"); tp->cp_cmd |= (1 << 14); @@ -3790,10 +3779,10 @@ static void rtl_hw_start_8169(struct net_device *dev) rtl_set_rx_tx_desc_registers(tp, ioaddr); - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { + if (tp->mac_version != RTL_GIGA_MAC_VER_01 && + tp->mac_version != RTL_GIGA_MAC_VER_02 && + tp->mac_version != RTL_GIGA_MAC_VER_03 && + tp->mac_version != RTL_GIGA_MAC_VER_04) { RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); rtl_set_rx_tx_config_registers(tp); } @@ -4103,10 +4092,10 @@ static void rtl_hw_start_8168e(void __iomem *ioaddr, struct pci_dev *pdev) rtl_disable_clock_request(pdev); /* Reset tx FIFO pointer */ - RTL_W32(MISC, RTL_R32(MISC) | txpla_rst); - RTL_W32(MISC, RTL_R32(MISC) & ~txpla_rst); + RTL_W32(MISC, RTL_R32(MISC) | TXPLA_RST); + RTL_W32(MISC, RTL_R32(MISC) & ~TXPLA_RST); - RTL_W8(Config5, RTL_R8(Config5) & ~spi_en); + RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); } static void rtl_hw_start_8168(struct net_device *dev) @@ -4190,6 +4179,7 @@ static void rtl_hw_start_8168(struct net_device *dev) case RTL_GIGA_MAC_VER_28: rtl_hw_start_8168d_4(ioaddr, pdev); break; + case RTL_GIGA_MAC_VER_31: rtl_hw_start_8168dp(ioaddr, pdev); break; @@ -4286,10 +4276,10 @@ static void rtl_hw_start_8105e_1(void __iomem *ioaddr, struct pci_dev *pdev) { 0x0a, 0, 0x0020 } }; - /* Force LAN exit from ASPM if Rx/Tx are not idel */ + /* Force LAN exit from ASPM if Rx/Tx are not idle */ RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); - /* disable Early Tally Counter */ + /* Disable Early Tally Counter */ RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000); RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); @@ -4310,8 +4300,8 @@ static void rtl_hw_start_8101(struct net_device *dev) void __iomem *ioaddr = tp->mmio_addr; struct pci_dev *pdev = tp->pci_dev; - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { + if (tp->mac_version == RTL_GIGA_MAC_VER_13 || + tp->mac_version == RTL_GIGA_MAC_VER_16) { int cap = tp->pcie_cap; if (cap) { @@ -4677,7 +4667,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, goto err_out; } - /* anti gcc 2.95.3 bugware (sic) */ + /* Anti gcc 2.95.3 bugware (sic) */ status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); @@ -4773,7 +4763,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, wmb(); - /* anti gcc 2.95.3 bugware (sic) */ + /* Anti gcc 2.95.3 bugware (sic) */ status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); txd->opts1 = cpu_to_le32(status); @@ -4781,7 +4771,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, wmb(); - RTL_W8(TxPoll, NPQ); /* set polling bit */ + RTL_W8(TxPoll, NPQ); if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { netif_stop_queue(dev); @@ -5207,7 +5197,7 @@ static int rtl8169_close(struct net_device *dev) pm_runtime_get_sync(&pdev->dev); - /* update counters before going down */ + /* Update counters before going down */ rtl8169_update_counters(dev); rtl8169_down(dev); @@ -5400,15 +5390,15 @@ static int rtl8169_runtime_idle(struct device *device) } static const struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, - .runtime_suspend = rtl8169_runtime_suspend, - .runtime_resume = rtl8169_runtime_resume, - .runtime_idle = rtl8169_runtime_idle, + .suspend = rtl8169_suspend, + .resume = rtl8169_resume, + .freeze = rtl8169_suspend, + .thaw = rtl8169_resume, + .poweroff = rtl8169_suspend, + .restore = rtl8169_resume, + .runtime_suspend = rtl8169_runtime_suspend, + .runtime_resume = rtl8169_runtime_resume, + .runtime_idle = rtl8169_runtime_idle, }; #define RTL8169_PM_OPS (&rtl8169_pm_ops) @@ -5427,7 +5417,7 @@ static void rtl_shutdown(struct pci_dev *pdev) rtl8169_net_suspend(dev); - /* restore original MAC address */ + /* Restore original MAC address */ rtl_rar_set(tp, dev->perm_addr); spin_lock_irq(&tp->lock); -- cgit v1.2.3-58-ga151 From 6f43adc88f49cb8164fbd665e968de4de380dc35 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 29 Apr 2011 15:05:51 +0200 Subject: r8169: remove some code duplication. Signed-off-by: Francois Romieu Cc: Realtek linux nic maintainers --- drivers/net/r8169.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index c51515f53df1..976bb31b2092 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -3224,6 +3224,22 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) } } +static void rtl_hw_reset(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + int i; + + /* Soft reset the chip. */ + RTL_W8(ChipCmd, CmdReset); + + /* Check that the chip has finished the reset. */ + for (i = 0; i < 100; i++) { + if ((RTL_R8(ChipCmd) & CmdReset) == 0) + break; + msleep_interruptible(1); + } +} + static int __devinit rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -3323,6 +3339,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rc = -EIO; goto err_out_free_res_3; } + tp->mmio_addr = ioaddr; tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (!tp->pcie_cap) @@ -3330,15 +3347,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) RTL_W16(IntrMask, 0x0000); - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } + rtl_hw_reset(tp); RTL_W16(IntrStatus, 0xffff); @@ -3409,8 +3418,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) spin_lock_init(&tp->lock); - tp->mmio_addr = ioaddr; - /* Get MAC address */ for (i = 0; i < MAC_ADDR_LEN; i++) dev->dev_addr[i] = RTL_R8(MAC0 + i); @@ -3658,25 +3665,14 @@ static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) static void rtl_hw_start(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - msleep_interruptible(1); - } + rtl_hw_reset(tp); tp->hw_start(dev); netif_start_queue(dev); } - static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, void __iomem *ioaddr) { -- cgit v1.2.3-58-ga151 From 826e6cbdadfa51495c7189641df2514cc48e23da Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 11 Mar 2011 20:30:24 +0100 Subject: r8169: rtl8169_set_speed_xmii cleanup. Shorten chipset version test. No functional change. Careful readers will notice that the 'supports_gmii' flag is deduced from the device PCI id. Though less specific than the chipset related RTL_GIGA_MAC_VER_XY, it is good enough to detect a GMII deprieved 810x. Some features push for a device specific configuration (improved jumbo frame support for instance). 'supports_gmii' will follow this path if / when the device PCI id test stops working. Signed-off-by: Francois Romieu Cc: Realtek linux nic maintainers --- drivers/net/r8169.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 976bb31b2092..182c79474434 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1258,16 +1258,7 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if (tp->mac_version != RTL_GIGA_MAC_VER_07 && - tp->mac_version != RTL_GIGA_MAC_VER_08 && - tp->mac_version != RTL_GIGA_MAC_VER_09 && - tp->mac_version != RTL_GIGA_MAC_VER_10 && - tp->mac_version != RTL_GIGA_MAC_VER_13 && - tp->mac_version != RTL_GIGA_MAC_VER_14 && - tp->mac_version != RTL_GIGA_MAC_VER_15 && - tp->mac_version != RTL_GIGA_MAC_VER_16 && - tp->mac_version != RTL_GIGA_MAC_VER_29 && - tp->mac_version != RTL_GIGA_MAC_VER_30) { + if (tp->mii.supports_gmii) { if (adv & ADVERTISED_1000baseT_Half) giga_ctrl |= ADVERTISE_1000HALF; if (adv & ADVERTISED_1000baseT_Full) -- cgit v1.2.3-58-ga151 From 4876cc1e49efac03827a51a2422cfbbb7f6335de Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 11 Mar 2011 21:07:11 +0100 Subject: r8169: link speed selection timer rework. The implementation was a bit krusty. The 10s rtl8169_phy_timer timer has been (was ?) required with older 8169 for adequate phy operation when full gigabit is advertised in autonegotiated mode. The timer does nothing if the link is up. Otherwise it keeps resetting the phy until things improve. - the device private data field phy_1000_ctrl_reg was used to schedule the timer. Avoid it and save a few bytes. - rtl8169_set_settings pending timer is disabled before changing the link settings as rtl8169_phy_timer is not always needed (see the removed test in rtl8169_phy_timer). - rtl8169_set_speed the requested link parameters may not match the chipset : bail out early on failure. - rtl8169_open Calling rtl8169_request_timer is redundant with -> rtl8169_open -> rtl8169_init_phy -> rtl8169_set_speed -> mod_timer The latter always enables the phy timer whereas the former did not for RTL_GIGA_MAC_VER_01. It should not make things worse but only time will tell if reality agrees. - rtl8169_request_timer : unused yet. Removed. - rtl8169_delete_timer : useless. Bloat. Removed. Side effect : the timer may kick in if the TBI is enabled. I do not know if the TBI has ever been used in real life. Signed-off-by: Francois Romieu Cc: Realtek linux nic maintainers --- drivers/net/r8169.c | 44 +++++++++----------------------------------- 1 file changed, 9 insertions(+), 35 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 182c79474434..b3cf1d20ba2c 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -616,7 +616,6 @@ struct rtl8169_private { u16 intr_event; u16 napi_event; u16 intr_mask; - int phy_1000_ctrl_reg; struct mdio_ops { void (*write)(void __iomem *, int, int); @@ -1288,8 +1287,6 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, bmcr |= BMCR_FULLDPLX; } - tp->phy_1000_ctrl_reg = giga_ctrl; - rtl_writephy(tp, MII_BMCR, bmcr); if (tp->mac_version == RTL_GIGA_MAC_VER_02 || @@ -1315,10 +1312,14 @@ static int rtl8169_set_speed(struct net_device *dev, int ret; ret = tp->set_speed(dev, autoneg, speed, duplex, advertising); + if (ret < 0) + goto out; - if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) + if (netif_running(dev) && (autoneg == AUTONEG_ENABLE) && + (advertising & ADVERTISED_1000baseT_Full)) { mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - + } +out: return ret; } @@ -1328,6 +1329,8 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) unsigned long flags; int ret; + del_timer_sync(&tp->timer); + spin_lock_irqsave(&tp->lock, flags); ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd), cmd->duplex, cmd->advertising); @@ -2691,9 +2694,6 @@ static void rtl8169_phy_timer(unsigned long __opaque) assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)) - return; - spin_lock_irq(&tp->lock); if (tp->phy_reset_pending(tp)) { @@ -2718,28 +2718,6 @@ out_unlock: spin_unlock_irq(&tp->lock); } -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - del_timer_sync(timer); -} - -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->timer; - - if (tp->mac_version <= RTL_GIGA_MAC_VER_01) - return; - - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); -} - #ifdef CONFIG_NET_POLL_CONTROLLER /* * Polling 'interrupt' - used by things like netconsole to send skbs @@ -3396,8 +3374,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->phy_reset_pending = rtl8169_tbi_reset_pending; tp->link_ok = rtl8169_tbi_link_ok; tp->do_ioctl = rtl_tbi_ioctl; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ } else { tp->set_speed = rtl8169_set_speed_xmii; tp->get_settings = rtl8169_gset_xmii; @@ -3593,8 +3569,6 @@ static int rtl8169_open(struct net_device *dev) rtl_hw_start(dev); - rtl8169_request_timer(dev); - tp->saved_wolopts = 0; pm_runtime_put_noidle(&pdev->dev); @@ -5147,7 +5121,7 @@ static void rtl8169_down(struct net_device *dev) struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - rtl8169_delete_timer(dev); + del_timer_sync(&tp->timer); netif_stop_queue(dev); -- cgit v1.2.3-58-ga151 From 56de414c0c7333f1e1adedc23057e131ce84233e Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Tue, 15 Mar 2011 17:29:31 +0100 Subject: r8169: remove non-NAPI context invocation of rtl8169_rx_interrupt. Invocation of rtl8169_rx_interrupt from rtl8169_reset_task was originally intended to retrieve as much packets as possible from the rx ring when a reset was needed. Nowadays rtl8169_reset_task is only scheduled, with some delay a. from the tx timeout watchdog b. when resuming c. from rtl8169_rx_interrupt itself It's dubious that the loss of outdated packets will matter much for a) and b). c) does not need to call itself again. Signed-off-by: Francois Romieu Cc: Realtek linux nic maintainers --- drivers/net/r8169.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index b3cf1d20ba2c..81906bc919a4 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -4564,6 +4564,7 @@ static void rtl8169_reset_task(struct work_struct *work) struct rtl8169_private *tp = container_of(work, struct rtl8169_private, task.work); struct net_device *dev = tp->dev; + int i; rtnl_lock(); @@ -4572,19 +4573,15 @@ static void rtl8169_reset_task(struct work_struct *work) rtl8169_wait_for_quiescence(dev); - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); + for (i = 0; i < NUM_RX_DESC; i++) + rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz); + rtl8169_tx_clear(tp); - if (tp->dirty_rx == tp->cur_rx) { - rtl8169_init_ring_indexes(tp); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); - } else { - if (net_ratelimit()) - netif_emerg(tp, intr, dev, "Rx buffers shortage\n"); - rtl8169_schedule_work(dev, rtl8169_reset_task); - } + rtl8169_init_ring_indexes(tp); + rtl_hw_start(dev); + netif_wake_queue(dev); + rtl8169_check_link_status(dev, tp, tp->mmio_addr); out_unlock: rtnl_unlock(); @@ -4889,20 +4886,12 @@ static struct sk_buff *rtl8169_try_rx_copy(void *data, return skb; } -/* - * Warning : rtl8169_rx_interrupt() might be called : - * 1) from NAPI (softirq) context - * (polling = 1 : we should call netif_receive_skb()) - * 2) from process context (rtl8169_reset_task()) - * (polling = 0 : we must call netif_rx() instead) - */ static int rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, void __iomem *ioaddr, u32 budget) { unsigned int cur_rx, rx_left; unsigned int count; - int polling = (budget != ~(u32)0) ? 1 : 0; cur_rx = tp->cur_rx; rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; @@ -4962,10 +4951,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, rtl8169_rx_vlan_tag(desc, skb); - if (likely(polling)) - napi_gro_receive(&tp->napi, skb); - else - netif_rx(skb); + napi_gro_receive(&tp->napi, skb); dev->stats.rx_bytes += pkt_size; dev->stats.rx_packets++; -- cgit v1.2.3-58-ga151 From 31bd204f97e3796c5cfcfc582a93a10e45b99946 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Tue, 26 Apr 2011 18:58:59 +0200 Subject: r8169: provide some firmware information via ethtool. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no real firmware version yet but the manpage of ethtool is rather terse about the driver information. Former output: $ ethtool -i eth1 driver: r8169 version: 2.3LK-NAPI firmware-version: bus-info: 0000:01:00.0 $ ethtool -i eth0 driver: r8169 version: 2.3LK-NAPI firmware-version: bus-info: 0000:03:00.0 Current output: $ ethtool -i eth1 driver: r8169 version: 2.3LK-NAPI firmware-version: N/A bus-info: 0000:01:00.0 $ ethtool -i eth0 driver: r8169 version: 2.3LK-NAPI firmware-version: rtl_nic/rtl8168d-1.fw bus-info: 0000:03:00.0 Signed-off-by: Francois Romieu Fixed-by Ciprian Docan Cc: Realtek linux nic maintainers Cc: Fejes József Cc: Borislav Petkov --- drivers/net/r8169.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 81906bc919a4..83e5202d30aa 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1188,6 +1188,19 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) return 0; } +static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(rtl_firmware_infos); i++) { + const struct rtl_firmware_info *info = rtl_firmware_infos + i; + + if (info->mac_version == tp->mac_version) + return info->fw_name; + } + return NULL; +} + static void rtl8169_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { @@ -1196,6 +1209,8 @@ static void rtl8169_get_drvinfo(struct net_device *dev, strcpy(info->driver, MODULENAME); strcpy(info->version, RTL8169_VERSION); strcpy(info->bus_info, pci_name(tp->pci_dev)); + strncpy(info->fw_version, IS_ERR_OR_NULL(tp->fw) ? "N/A" : + rtl_lookup_firmware_name(tp), sizeof(info->fw_version) - 1); } static int rtl8169_get_regs_len(struct net_device *dev) @@ -3491,33 +3506,23 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) static void rtl_request_firmware(struct rtl8169_private *tp) { - int i; - /* Return early if the firmware is already loaded / cached. */ - if (!IS_ERR(tp->fw)) - goto out; - - for (i = 0; i < ARRAY_SIZE(rtl_firmware_infos); i++) { - const struct rtl_firmware_info *info = rtl_firmware_infos + i; + if (IS_ERR(tp->fw)) { + const char *name; - if (info->mac_version == tp->mac_version) { - const char *name = info->fw_name; + name = rtl_lookup_firmware_name(tp); + if (name) { int rc; rc = request_firmware(&tp->fw, name, &tp->pci_dev->dev); - if (rc < 0) { - netif_warn(tp, ifup, tp->dev, "unable to load " - "firmware patch %s (%d)\n", name, rc); - goto out_disable_request_firmware; - } - goto out; + if (rc >= 0) + return; + + netif_warn(tp, ifup, tp->dev, "unable to load " + "firmware patch %s (%d)\n", name, rc); } + tp->fw = NULL; } - -out_disable_request_firmware: - tp->fw = NULL; -out: - return; } static int rtl8169_open(struct net_device *dev) -- cgit v1.2.3-58-ga151 From 85bffe6ca2e2d7e9510c115aa4f11c3d4209051f Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Wed, 27 Apr 2011 08:22:39 +0200 Subject: r8169: merge firmware information into the chipset description data. - RTL_GIGA_MAC_NONE is a fake index so put it at the end of the enumeration and shift everybody. - RTL_GIGA_MAC_VER_17 / RTL_GIGA_MAC_VER_16 ordering fixed. Though not wrong it was confusing enough to wonder if things were right. Renaming rtl_chip_info was not strictly necessary. It allows to check the patch for the correct use of the indexes though. Signed-off-by: Francois Romieu Cc: Realtek linux nic maintainers --- drivers/net/r8169.c | 214 +++++++++++++++++++++++++++------------------------- 1 file changed, 110 insertions(+), 104 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 83e5202d30aa..4f1d45bd3303 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -98,40 +98,40 @@ static const int multicast_filter_limit = 32; #define RTL_R32(reg) readl (ioaddr + (reg)) enum mac_version { - RTL_GIGA_MAC_NONE = 0x00, - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19, // 8168D - RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D - RTL_GIGA_MAC_VER_27 = 0x1b, // 8168DP - RTL_GIGA_MAC_VER_28 = 0x1c, // 8168DP - RTL_GIGA_MAC_VER_29 = 0x1d, // 8105E - RTL_GIGA_MAC_VER_30 = 0x1e, // 8105E - RTL_GIGA_MAC_VER_31 = 0x1f, // 8168DP - RTL_GIGA_MAC_VER_32 = 0x20, // 8168E - RTL_GIGA_MAC_VER_33 = 0x21, // 8168E + RTL_GIGA_MAC_VER_01 = 0, + RTL_GIGA_MAC_VER_02, + RTL_GIGA_MAC_VER_03, + RTL_GIGA_MAC_VER_04, + RTL_GIGA_MAC_VER_05, + RTL_GIGA_MAC_VER_06, + RTL_GIGA_MAC_VER_07, + RTL_GIGA_MAC_VER_08, + RTL_GIGA_MAC_VER_09, + RTL_GIGA_MAC_VER_10, + RTL_GIGA_MAC_VER_11, + RTL_GIGA_MAC_VER_12, + RTL_GIGA_MAC_VER_13, + RTL_GIGA_MAC_VER_14, + RTL_GIGA_MAC_VER_15, + RTL_GIGA_MAC_VER_16, + RTL_GIGA_MAC_VER_17, + RTL_GIGA_MAC_VER_18, + RTL_GIGA_MAC_VER_19, + RTL_GIGA_MAC_VER_20, + RTL_GIGA_MAC_VER_21, + RTL_GIGA_MAC_VER_22, + RTL_GIGA_MAC_VER_23, + RTL_GIGA_MAC_VER_24, + RTL_GIGA_MAC_VER_25, + RTL_GIGA_MAC_VER_26, + RTL_GIGA_MAC_VER_27, + RTL_GIGA_MAC_VER_28, + RTL_GIGA_MAC_VER_29, + RTL_GIGA_MAC_VER_30, + RTL_GIGA_MAC_VER_31, + RTL_GIGA_MAC_VER_32, + RTL_GIGA_MAC_VER_33, + RTL_GIGA_MAC_NONE = 0xff, }; enum rtl_tx_desc_version { @@ -139,61 +139,84 @@ enum rtl_tx_desc_version { RTL_TD_1 = 1, }; -#define _R(NAME,MAC,TD) \ - { .name = NAME, .mac_version = MAC, .txd_version = TD } +#define _R(NAME,TD,FW) \ + { .name = NAME, .txd_version = TD, .fw_name = FW } static const struct { const char *name; - u8 mac_version; enum rtl_tx_desc_version txd_version; -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, RTL_TD_0), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, RTL_TD_0), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, RTL_TD_0), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, RTL_TD_0), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, RTL_TD_0), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, RTL_TD_0), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, RTL_TD_1), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, RTL_TD_1), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, RTL_TD_1), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, RTL_TD_0), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, RTL_TD_0), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, RTL_TD_0), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, RTL_TD_0), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, RTL_TD_0), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, RTL_TD_0), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, RTL_TD_0), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, RTL_TD_0), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, RTL_TD_1), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, RTL_TD_1), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, RTL_TD_1), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, RTL_TD_1), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, RTL_TD_1), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, RTL_TD_1), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, RTL_TD_1), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, RTL_TD_1), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, RTL_TD_1), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, RTL_TD_1), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_28, RTL_TD_1), // PCI-E - _R("RTL8105e", RTL_GIGA_MAC_VER_29, RTL_TD_1), // PCI-E - _R("RTL8105e", RTL_GIGA_MAC_VER_30, RTL_TD_1), // PCI-E - _R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_31, RTL_TD_1), // PCI-E - _R("RTL8168e/8111e", RTL_GIGA_MAC_VER_32, RTL_TD_1), // PCI-E - _R("RTL8168e/8111e", RTL_GIGA_MAC_VER_33, RTL_TD_1) // PCI-E -}; -#undef _R - -static const struct rtl_firmware_info { - int mac_version; const char *fw_name; -} rtl_firmware_infos[] = { - { .mac_version = RTL_GIGA_MAC_VER_25, .fw_name = FIRMWARE_8168D_1 }, - { .mac_version = RTL_GIGA_MAC_VER_26, .fw_name = FIRMWARE_8168D_2 }, - { .mac_version = RTL_GIGA_MAC_VER_29, .fw_name = FIRMWARE_8105E_1 }, - { .mac_version = RTL_GIGA_MAC_VER_30, .fw_name = FIRMWARE_8105E_1 }, - { .mac_version = RTL_GIGA_MAC_VER_32, .fw_name = FIRMWARE_8168E_1 }, - { .mac_version = RTL_GIGA_MAC_VER_33, .fw_name = FIRMWARE_8168E_2 } +} rtl_chip_infos[] = { + /* PCI devices. */ + [RTL_GIGA_MAC_VER_01] = + _R("RTL8169", RTL_TD_0, NULL), + [RTL_GIGA_MAC_VER_02] = + _R("RTL8169s", RTL_TD_0, NULL), + [RTL_GIGA_MAC_VER_03] = + _R("RTL8110s", RTL_TD_0, NULL), + [RTL_GIGA_MAC_VER_04] = + _R("RTL8169sb/8110sb", RTL_TD_0, NULL), + [RTL_GIGA_MAC_VER_05] = + _R("RTL8169sc/8110sc", RTL_TD_0, NULL), + [RTL_GIGA_MAC_VER_06] = + _R("RTL8169sc/8110sc", RTL_TD_0, NULL), + /* PCI-E devices. */ + [RTL_GIGA_MAC_VER_07] = + _R("RTL8102e", RTL_TD_1, NULL), + [RTL_GIGA_MAC_VER_08] = + _R("RTL8102e", RTL_TD_1, NULL), + [RTL_GIGA_MAC_VER_09] = + _R("RTL8102e", RTL_TD_1, NULL), + [RTL_GIGA_MAC_VER_10] = + _R("RTL8101e", RTL_TD_0, NULL), + [RTL_GIGA_MAC_VER_11] = + _R("RTL8168b/8111b", RTL_TD_0, NULL), + [RTL_GIGA_MAC_VER_12] = + _R("RTL8168b/8111b", RTL_TD_0, NULL), + [RTL_GIGA_MAC_VER_13] = + _R("RTL8101e", RTL_TD_0, NULL), + [RTL_GIGA_MAC_VER_14] = + _R("RTL8100e", RTL_TD_0, NULL), + [RTL_GIGA_MAC_VER_15] = + _R("RTL8100e", RTL_TD_0, NULL), + [RTL_GIGA_MAC_VER_16] = + _R("RTL8101e", RTL_TD_0, NULL), + [RTL_GIGA_MAC_VER_17] = + _R("RTL8168b/8111b", RTL_TD_0, NULL), + [RTL_GIGA_MAC_VER_18] = + _R("RTL8168cp/8111cp", RTL_TD_1, NULL), + [RTL_GIGA_MAC_VER_19] = + _R("RTL8168c/8111c", RTL_TD_1, NULL), + [RTL_GIGA_MAC_VER_20] = + _R("RTL8168c/8111c", RTL_TD_1, NULL), + [RTL_GIGA_MAC_VER_21] = + _R("RTL8168c/8111c", RTL_TD_1, NULL), + [RTL_GIGA_MAC_VER_22] = + _R("RTL8168c/8111c", RTL_TD_1, NULL), + [RTL_GIGA_MAC_VER_23] = + _R("RTL8168cp/8111cp", RTL_TD_1, NULL), + [RTL_GIGA_MAC_VER_24] = + _R("RTL8168cp/8111cp", RTL_TD_1, NULL), + [RTL_GIGA_MAC_VER_25] = + _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1), + [RTL_GIGA_MAC_VER_26] = + _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2), + [RTL_GIGA_MAC_VER_27] = + _R("RTL8168dp/8111dp", RTL_TD_1, NULL), + [RTL_GIGA_MAC_VER_28] = + _R("RTL8168dp/8111dp", RTL_TD_1, NULL), + [RTL_GIGA_MAC_VER_29] = + _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1), + [RTL_GIGA_MAC_VER_30] = + _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1), + [RTL_GIGA_MAC_VER_31] = + _R("RTL8168dp/8111dp", RTL_TD_1, NULL), + [RTL_GIGA_MAC_VER_32] = + _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1), + [RTL_GIGA_MAC_VER_33] = + _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2) }; +#undef _R enum cfg_version { RTL_CFG_0 = 0x00, @@ -1190,15 +1213,7 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp) { - int i; - - for (i = 0; i < ARRAY_SIZE(rtl_firmware_infos); i++) { - const struct rtl_firmware_info *info = rtl_firmware_infos + i; - - if (info->mac_version == tp->mac_version) - return info->fw_name; - } - return NULL; + return rtl_chip_infos[tp->mac_version].fw_name; } static void rtl8169_get_drvinfo(struct net_device *dev, @@ -3359,17 +3374,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl8169_print_mac_version(tp); - for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; - } - if (i == ARRAY_SIZE(rtl_chip_info)) { - dev_err(&pdev->dev, - "driver bug, MAC version not found in rtl_chip_info\n"); - goto err_out_msi_4; - } - chipset = i; - tp->txd_version = rtl_chip_info[chipset].txd_version; + chipset = tp->mac_version; + tp->txd_version = rtl_chip_infos[chipset].txd_version; RTL_W8(Cfg9346, Cfg9346_Unlock); RTL_W8(Config1, RTL_R8(Config1) | PMEnable); @@ -3444,7 +3450,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, dev); netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n", - rtl_chip_info[chipset].name, dev->base_addr, dev->dev_addr, + rtl_chip_infos[chipset].name, dev->base_addr, dev->dev_addr, (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); if (tp->mac_version == RTL_GIGA_MAC_VER_27 || -- cgit v1.2.3-58-ga151 From 5d320a205de277774962782a4b1923e4f8cdf781 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 8 May 2011 17:47:36 +0200 Subject: r8169: avoid late chip identifier initialisation. Unknown 8168 chips did not have any PLL power method set as they did not inherit a default family soon enough. Fix it. Signed-off-by: Francois Romieu Cc: Realtek linux nic maintainers --- drivers/net/r8169.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 4f1d45bd3303..04f4e6086cd0 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1606,8 +1606,9 @@ static const struct ethtool_ops rtl8169_ethtool_ops = { }; static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void __iomem *ioaddr) + struct net_device *dev, u8 default_version) { + void __iomem *ioaddr = tp->mmio_addr; /* * The driver currently handles the 8168Bf and the 8168Be identically * but they can be identified more specifically through the test below @@ -1694,6 +1695,12 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, while ((reg & p->mask) != p->val) p++; tp->mac_version = p->mac_version; + + if (tp->mac_version == RTL_GIGA_MAC_NONE) { + netif_notice(tp, probe, dev, + "unknown MAC, using family default\n"); + tp->mac_version = default_version; + } } static void rtl8169_print_mac_version(struct rtl8169_private *tp) @@ -3353,7 +3360,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_master(pdev); /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, ioaddr); + rtl8169_get_mac_version(tp, dev, cfg->default_ver); /* * Pretend we are using VLANs; This bypasses a nasty bug where @@ -3365,13 +3372,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl_init_mdio_ops(tp); rtl_init_pll_power_ops(tp); - /* Use appropriate default if unknown */ - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - netif_notice(tp, probe, dev, - "unknown MAC, using family default\n"); - tp->mac_version = cfg->default_ver; - } - rtl8169_print_mac_version(tp); chipset = tp->mac_version; -- cgit v1.2.3-58-ga151 From 0693e88e6ccf615d9674548d8b924cdd9a1c976c Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sat, 7 May 2011 01:48:02 +0000 Subject: net: bonding: factor out rlock(bond->lock) in xmit path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull read_lock(&bond->lock) and BOND_IS_OK() to bond_start_xmit() from mode-dependent xmit functions. netif_running() is always true in hard_start_xmit. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 10 +----- drivers/net/bonding/bond_alb.c | 11 ++---- drivers/net/bonding/bond_main.c | 74 ++++++++++++++++++----------------------- 3 files changed, 35 insertions(+), 60 deletions(-) diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index d4160f87e910..c7537abca4f2 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2403,14 +2403,6 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) struct ad_info ad_info; int res = 1; - /* make sure that the slaves list will - * not change during tx - */ - read_lock(&bond->lock); - - if (!BOND_IS_OK(bond)) - goto out; - if (bond_3ad_get_active_agg_info(bond, &ad_info)) { pr_debug("%s: Error: bond_3ad_get_active_agg_info failed\n", dev->name); @@ -2464,7 +2456,7 @@ out: /* no suitable interface, frame not sent */ dev_kfree_skb(skb); } - read_unlock(&bond->lock); + return NETDEV_TX_OK; } diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 3b7b0409406f..8f2d2e7c70e5 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -1225,16 +1225,10 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) skb_reset_mac_header(skb); eth_data = eth_hdr(skb); - /* make sure that the curr_active_slave and the slaves list do - * not change during tx + /* make sure that the curr_active_slave do not change during tx */ - read_lock(&bond->lock); read_lock(&bond->curr_slave_lock); - if (!BOND_IS_OK(bond)) { - goto out; - } - switch (ntohs(skb->protocol)) { case ETH_P_IP: { const struct iphdr *iph = ip_hdr(skb); @@ -1334,13 +1328,12 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) } } -out: if (res) { /* no suitable interface, frame not sent */ dev_kfree_skb(skb); } read_unlock(&bond->curr_slave_lock); - read_unlock(&bond->lock); + return NETDEV_TX_OK; } diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 9a5feaf4bab9..6312db1f7838 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4004,10 +4004,6 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev int i, slave_no, res = 1; struct iphdr *iph = ip_hdr(skb); - read_lock(&bond->lock); - - if (!BOND_IS_OK(bond)) - goto out; /* * Start with the curr_active_slave that joined the bond as the * default for sending IGMP traffic. For failover purposes one @@ -4054,7 +4050,7 @@ out: /* no suitable interface, frame not sent */ dev_kfree_skb(skb); } - read_unlock(&bond->lock); + return NETDEV_TX_OK; } @@ -4068,24 +4064,18 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d struct bonding *bond = netdev_priv(bond_dev); int res = 1; - read_lock(&bond->lock); read_lock(&bond->curr_slave_lock); - if (!BOND_IS_OK(bond)) - goto out; + if (bond->curr_active_slave) + res = bond_dev_queue_xmit(bond, skb, + bond->curr_active_slave->dev); - if (!bond->curr_active_slave) - goto out; - - res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev); - -out: if (res) /* no suitable interface, frame not sent */ dev_kfree_skb(skb); read_unlock(&bond->curr_slave_lock); - read_unlock(&bond->lock); + return NETDEV_TX_OK; } @@ -4102,11 +4092,6 @@ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev) int i; int res = 1; - read_lock(&bond->lock); - - if (!BOND_IS_OK(bond)) - goto out; - slave_no = bond->xmit_hash_policy(skb, bond->slave_cnt); bond_for_each_slave(bond, slave, i) { @@ -4126,12 +4111,11 @@ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev) } } -out: if (res) { /* no suitable interface, frame not sent */ dev_kfree_skb(skb); } - read_unlock(&bond->lock); + return NETDEV_TX_OK; } @@ -4146,11 +4130,6 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) int i; int res = 1; - read_lock(&bond->lock); - - if (!BOND_IS_OK(bond)) - goto out; - read_lock(&bond->curr_slave_lock); start_at = bond->curr_active_slave; read_unlock(&bond->curr_slave_lock); @@ -4189,7 +4168,6 @@ out: dev_kfree_skb(skb); /* frame sent to all suitable interfaces */ - read_unlock(&bond->lock); return NETDEV_TX_OK; } @@ -4221,10 +4199,8 @@ static inline int bond_slave_override(struct bonding *bond, struct slave *slave = NULL; struct slave *check_slave; - read_lock(&bond->lock); - - if (!BOND_IS_OK(bond) || !skb->queue_mapping) - goto out; + if (!skb->queue_mapping) + return 1; /* Find out if any slaves have the same mapping as this skb. */ bond_for_each_slave(bond, check_slave, i) { @@ -4240,8 +4216,6 @@ static inline int bond_slave_override(struct bonding *bond, res = bond_dev_queue_xmit(bond, skb, slave->dev); } -out: - read_unlock(&bond->lock); return res; } @@ -4263,17 +4237,10 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) return txq; } -static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct bonding *bond = netdev_priv(dev); - /* - * If we risk deadlock from transmitting this in the - * netpoll path, tell netpoll to queue the frame for later tx - */ - if (is_netpoll_tx_blocked(dev)) - return NETDEV_TX_BUSY; - if (TX_QUEUE_OVERRIDE(bond->params.mode)) { if (!bond_slave_override(bond, skb)) return NETDEV_TX_OK; @@ -4303,6 +4270,29 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev) } } +static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct bonding *bond = netdev_priv(dev); + netdev_tx_t ret = NETDEV_TX_OK; + + /* + * If we risk deadlock from transmitting this in the + * netpoll path, tell netpoll to queue the frame for later tx + */ + if (is_netpoll_tx_blocked(dev)) + return NETDEV_TX_BUSY; + + read_lock(&bond->lock); + + if (bond->slave_cnt) + ret = __bond_start_xmit(skb, dev); + else + dev_kfree_skb(skb); + + read_unlock(&bond->lock); + + return ret; +} /* * set bond mode specific net device operations -- cgit v1.2.3-58-ga151 From 99f823f98fb981b55c663a3783c3d2293958ece4 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 7 May 2011 20:33:13 +0000 Subject: netconsole: switch to kstrto*() functions Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/net/netconsole.c | 62 +++++++++++------------------------------------- 1 file changed, 14 insertions(+), 48 deletions(-) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index eb41e44921e6..62fdbaa1fb60 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -241,34 +241,6 @@ static struct netconsole_target *to_target(struct config_item *item) NULL; } -/* - * Wrapper over simple_strtol (base 10) with sanity and range checking. - * We return (signed) long only because we may want to return errors. - * Do not use this to convert numbers that are allowed to be negative. - */ -static long strtol10_check_range(const char *cp, long min, long max) -{ - long ret; - char *p = (char *) cp; - - WARN_ON(min < 0); - WARN_ON(max < min); - - ret = simple_strtol(p, &p, 10); - - if (*p && (*p != '\n')) { - printk(KERN_ERR "netconsole: invalid input\n"); - return -EINVAL; - } - if ((ret < min) || (ret > max)) { - printk(KERN_ERR "netconsole: input %ld must be between " - "%ld and %ld\n", ret, min, max); - return -EINVAL; - } - - return ret; -} - /* * Attribute operations for netconsole_target. */ @@ -327,12 +299,14 @@ static ssize_t store_enabled(struct netconsole_target *nt, const char *buf, size_t count) { + int enabled; int err; - long enabled; - enabled = strtol10_check_range(buf, 0, 1); - if (enabled < 0) - return enabled; + err = kstrtoint(buf, 10, &enabled); + if (err < 0) + return err; + if (enabled < 0 || enabled > 1) + return -EINVAL; if (enabled) { /* 1 */ @@ -384,8 +358,7 @@ static ssize_t store_local_port(struct netconsole_target *nt, const char *buf, size_t count) { - long local_port; -#define __U16_MAX ((__u16) ~0U) + int rv; if (nt->enabled) { printk(KERN_ERR "netconsole: target (%s) is enabled, " @@ -394,12 +367,9 @@ static ssize_t store_local_port(struct netconsole_target *nt, return -EINVAL; } - local_port = strtol10_check_range(buf, 0, __U16_MAX); - if (local_port < 0) - return local_port; - - nt->np.local_port = local_port; - + rv = kstrtou16(buf, 10, &nt->np.local_port); + if (rv < 0) + return rv; return strnlen(buf, count); } @@ -407,8 +377,7 @@ static ssize_t store_remote_port(struct netconsole_target *nt, const char *buf, size_t count) { - long remote_port; -#define __U16_MAX ((__u16) ~0U) + int rv; if (nt->enabled) { printk(KERN_ERR "netconsole: target (%s) is enabled, " @@ -417,12 +386,9 @@ static ssize_t store_remote_port(struct netconsole_target *nt, return -EINVAL; } - remote_port = strtol10_check_range(buf, 0, __U16_MAX); - if (remote_port < 0) - return remote_port; - - nt->np.remote_port = remote_port; - + rv = kstrtou16(buf, 10, &nt->np.remote_port); + if (rv < 0) + return rv; return strnlen(buf, count); } -- cgit v1.2.3-58-ga151 From 4940fc889e1e63667a15243028ddcd84d471cd8e Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 7 May 2011 23:00:07 +0000 Subject: net: add mac_pton() for parsing MAC address mac_pton() parses MAC address in form XX:XX:XX:XX:XX:XX and only in that form. mac_pton() doesn't dirty result until it's sure string representation is valid. mac_pton() doesn't care about characters _after_ last octet, it's up to caller to deal with it. mac_pton() diverges from 0/-E return value convention. Target usage: if (!mac_pton(str, whatever->mac)) return -EINVAL; /* ->mac being u8 [ETH_ALEN] is filled at this point. */ /* optionally check str[3 * ETH_ALEN - 1] for termination */ Use mac_pton() in pktgen and netconsole for start. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/net/netconsole.c | 20 ++++-------------- include/linux/if_ether.h | 1 + net/core/netpoll.c | 26 +----------------------- net/core/pktgen.c | 53 ++++++++---------------------------------------- net/core/utils.c | 24 ++++++++++++++++++++++ 5 files changed, 38 insertions(+), 86 deletions(-) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 62fdbaa1fb60..a83e101440fd 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -429,8 +429,6 @@ static ssize_t store_remote_mac(struct netconsole_target *nt, size_t count) { u8 remote_mac[ETH_ALEN]; - char *p = (char *) buf; - int i; if (nt->enabled) { printk(KERN_ERR "netconsole: target (%s) is enabled, " @@ -439,23 +437,13 @@ static ssize_t store_remote_mac(struct netconsole_target *nt, return -EINVAL; } - for (i = 0; i < ETH_ALEN - 1; i++) { - remote_mac[i] = simple_strtoul(p, &p, 16); - if (*p != ':') - goto invalid; - p++; - } - remote_mac[ETH_ALEN - 1] = simple_strtoul(p, &p, 16); - if (*p && (*p != '\n')) - goto invalid; - + if (!mac_pton(buf, remote_mac)) + return -EINVAL; + if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n') + return -EINVAL; memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN); return strnlen(buf, count); - -invalid: - printk(KERN_ERR "netconsole: invalid input\n"); - return -EINVAL; } /* diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index be69043d2896..0f1325d98295 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -136,6 +136,7 @@ int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr); extern struct ctl_table ether_table[]; #endif +int mac_pton(const char *s, u8 *mac); extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); #endif diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 46d9c3a4de2f..2d7d6d473781 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -698,32 +698,8 @@ int netpoll_parse_options(struct netpoll *np, char *opt) if (*cur != 0) { /* MAC address */ - if ((delim = strchr(cur, ':')) == NULL) + if (!mac_pton(cur, np->remote_mac)) goto parse_failed; - *delim = 0; - np->remote_mac[0] = simple_strtol(cur, NULL, 16); - cur = delim + 1; - if ((delim = strchr(cur, ':')) == NULL) - goto parse_failed; - *delim = 0; - np->remote_mac[1] = simple_strtol(cur, NULL, 16); - cur = delim + 1; - if ((delim = strchr(cur, ':')) == NULL) - goto parse_failed; - *delim = 0; - np->remote_mac[2] = simple_strtol(cur, NULL, 16); - cur = delim + 1; - if ((delim = strchr(cur, ':')) == NULL) - goto parse_failed; - *delim = 0; - np->remote_mac[3] = simple_strtol(cur, NULL, 16); - cur = delim + 1; - if ((delim = strchr(cur, ':')) == NULL) - goto parse_failed; - *delim = 0; - np->remote_mac[4] = simple_strtol(cur, NULL, 16); - cur = delim + 1; - np->remote_mac[5] = simple_strtol(cur, NULL, 16); } netpoll_print_options(np); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index d41d88b53e18..379270f14771 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -1420,11 +1420,6 @@ static ssize_t pktgen_if_write(struct file *file, return count; } if (!strcmp(name, "dst_mac")) { - char *v = valstr; - unsigned char old_dmac[ETH_ALEN]; - unsigned char *m = pkt_dev->dst_mac; - memcpy(old_dmac, pkt_dev->dst_mac, ETH_ALEN); - len = strn_len(&user_buffer[i], sizeof(valstr) - 1); if (len < 0) return len; @@ -1432,35 +1427,16 @@ static ssize_t pktgen_if_write(struct file *file, memset(valstr, 0, sizeof(valstr)); if (copy_from_user(valstr, &user_buffer[i], len)) return -EFAULT; - i += len; - - for (*m = 0; *v && m < pkt_dev->dst_mac + 6; v++) { - int value; - - value = hex_to_bin(*v); - if (value >= 0) - *m = *m * 16 + value; - - if (*v == ':') { - m++; - *m = 0; - } - } + if (!mac_pton(valstr, pkt_dev->dst_mac)) + return -EINVAL; /* Set up Dest MAC */ - if (compare_ether_addr(old_dmac, pkt_dev->dst_mac)) - memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); + memcpy(&pkt_dev->hh[0], pkt_dev->dst_mac, ETH_ALEN); - sprintf(pg_result, "OK: dstmac"); + sprintf(pg_result, "OK: dstmac %pM", pkt_dev->dst_mac); return count; } if (!strcmp(name, "src_mac")) { - char *v = valstr; - unsigned char old_smac[ETH_ALEN]; - unsigned char *m = pkt_dev->src_mac; - - memcpy(old_smac, pkt_dev->src_mac, ETH_ALEN); - len = strn_len(&user_buffer[i], sizeof(valstr) - 1); if (len < 0) return len; @@ -1468,26 +1444,13 @@ static ssize_t pktgen_if_write(struct file *file, memset(valstr, 0, sizeof(valstr)); if (copy_from_user(valstr, &user_buffer[i], len)) return -EFAULT; - i += len; - - for (*m = 0; *v && m < pkt_dev->src_mac + 6; v++) { - int value; - - value = hex_to_bin(*v); - if (value >= 0) - *m = *m * 16 + value; - - if (*v == ':') { - m++; - *m = 0; - } - } + if (!mac_pton(valstr, pkt_dev->src_mac)) + return -EINVAL; /* Set up Src MAC */ - if (compare_ether_addr(old_smac, pkt_dev->src_mac)) - memcpy(&(pkt_dev->hh[6]), pkt_dev->src_mac, ETH_ALEN); + memcpy(&pkt_dev->hh[6], pkt_dev->src_mac, ETH_ALEN); - sprintf(pg_result, "OK: srcmac"); + sprintf(pg_result, "OK: srcmac %pM", pkt_dev->src_mac); return count; } diff --git a/net/core/utils.c b/net/core/utils.c index 5fea0ab21902..2012bc797f9c 100644 --- a/net/core/utils.c +++ b/net/core/utils.c @@ -296,3 +296,27 @@ void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, csum_unfold(*sum))); } EXPORT_SYMBOL(inet_proto_csum_replace4); + +int mac_pton(const char *s, u8 *mac) +{ + int i; + + /* XX:XX:XX:XX:XX:XX */ + if (strlen(s) < 3 * ETH_ALEN - 1) + return 0; + + /* Don't dirty result unless string is valid MAC. */ + for (i = 0; i < ETH_ALEN; i++) { + if (!strchr("0123456789abcdefABCDEF", s[i * 3])) + return 0; + if (!strchr("0123456789abcdefABCDEF", s[i * 3 + 1])) + return 0; + if (i != ETH_ALEN - 1 && s[i * 3 + 2] != ':') + return 0; + } + for (i = 0; i < ETH_ALEN; i++) { + mac[i] = (hex_to_bin(s[i * 3]) << 4) | hex_to_bin(s[i * 3 + 1]); + } + return 1; +} +EXPORT_SYMBOL(mac_pton); -- cgit v1.2.3-58-ga151 From 54668b84bd2ee808e6b43ed9bd7aa3338fa95857 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 9 May 2011 09:45:20 +0000 Subject: tulip: xircom_cb: Convert #ifdef DEBUG blocks and enter/leave uses Change the blocks that are guarded by #if DEBUG to be #if defined DEBUG && DEBUG > 1 so that pr_debug can be used later. Remove enter/leave macros and uses. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/xircom_cb.c | 134 ++++-------------------------------------- 1 file changed, 13 insertions(+), 121 deletions(-) diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 5a73752be2ca..d0d0cbe3dc17 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -37,15 +37,6 @@ #include #endif -#ifdef DEBUG -#define enter(x) printk("Enter: %s, %s line %i\n",x,__FILE__,__LINE__) -#define leave(x) printk("Leave: %s, %s line %i\n",x,__FILE__,__LINE__) -#else -#define enter(x) do {} while (0) -#define leave(x) do {} while (0) -#endif - - MODULE_DESCRIPTION("Xircom Cardbus ethernet driver"); MODULE_AUTHOR("Arjan van de Ven "); MODULE_LICENSE("GPL"); @@ -161,7 +152,7 @@ static struct pci_driver xircom_ops = { }; -#ifdef DEBUG +#if defined DEBUG && DEBUG > 1 static void print_binary(unsigned int number) { int i,i2; @@ -176,7 +167,7 @@ static void print_binary(unsigned int number) if ((i&3)==0) buffer[i2++]=' '; } - printk("%s\n",buffer); + pr_debug("%s\n",buffer); } #endif @@ -205,7 +196,6 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ struct xircom_private *private; unsigned long flags; unsigned short tmp16; - enter("xircom_probe"); /* First do the PCI initialisation */ @@ -285,7 +275,6 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ trigger_receive(private); - leave("xircom_probe"); return 0; reg_fail: @@ -310,7 +299,6 @@ static void __devexit xircom_remove(struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); struct xircom_private *card = netdev_priv(dev); - enter("xircom_remove"); pci_free_consistent(pdev,8192,card->rx_buffer,card->rx_dma_handle); pci_free_consistent(pdev,8192,card->tx_buffer,card->tx_dma_handle); @@ -318,7 +306,6 @@ static void __devexit xircom_remove(struct pci_dev *pdev) unregister_netdev(dev); free_netdev(dev); pci_set_drvdata(pdev, NULL); - leave("xircom_remove"); } static irqreturn_t xircom_interrupt(int irq, void *dev_instance) @@ -328,17 +315,15 @@ static irqreturn_t xircom_interrupt(int irq, void *dev_instance) unsigned int status; int i; - enter("xircom_interrupt\n"); - spin_lock(&card->lock); status = inl(card->io_port+CSR5); -#ifdef DEBUG +#if defined DEBUG && DEBUG > 1 print_binary(status); - printk("tx status 0x%08x 0x%08x\n", - card->tx_buffer[0], card->tx_buffer[4]); - printk("rx status 0x%08x 0x%08x\n", - card->rx_buffer[0], card->rx_buffer[4]); + pr_debug("tx status 0x%08x 0x%08x\n", + card->tx_buffer[0], card->tx_buffer[4]); + pr_debug("rx status 0x%08x 0x%08x\n", + card->rx_buffer[0], card->rx_buffer[4]); #endif /* Handle shared irq and hotplug */ if (status == 0 || status == 0xffffffff) { @@ -369,9 +354,7 @@ static irqreturn_t xircom_interrupt(int irq, void *dev_instance) for (i=0;ilock); - leave("xircom_interrupt"); return IRQ_HANDLED; } @@ -382,7 +365,6 @@ static netdev_tx_t xircom_start_xmit(struct sk_buff *skb, unsigned long flags; int nextdescriptor; int desc; - enter("xircom_start_xmit"); card = netdev_priv(dev); spin_lock_irqsave(&card->lock,flags); @@ -424,13 +406,10 @@ static netdev_tx_t xircom_start_xmit(struct sk_buff *skb, netif_stop_queue(dev); } card->transmit_used = nextdescriptor; - leave("xircom-start_xmit - sent"); spin_unlock_irqrestore(&card->lock,flags); return NETDEV_TX_OK; } - - /* Uh oh... no free descriptor... drop the packet */ netif_stop_queue(dev); spin_unlock_irqrestore(&card->lock,flags); @@ -446,18 +425,16 @@ static int xircom_open(struct net_device *dev) { struct xircom_private *xp = netdev_priv(dev); int retval; - enter("xircom_open"); + pr_info("xircom cardbus adaptor found, registering as %s, using irq %i\n", dev->name, dev->irq); retval = request_irq(dev->irq, xircom_interrupt, IRQF_SHARED, dev->name, dev); - if (retval) { - leave("xircom_open - No IRQ"); + if (retval) return retval; - } xircom_up(xp); xp->open = 1; - leave("xircom_open"); + return 0; } @@ -466,7 +443,6 @@ static int xircom_close(struct net_device *dev) struct xircom_private *card; unsigned long flags; - enter("xircom_close"); card = netdev_priv(dev); netif_stop_queue(dev); /* we don't want new packets */ @@ -486,8 +462,6 @@ static int xircom_close(struct net_device *dev) card->open = 0; free_irq(dev->irq,dev); - leave("xircom_close"); - return 0; } @@ -507,8 +481,6 @@ static void initialize_card(struct xircom_private *card) { unsigned int val; unsigned long flags; - enter("initialize_card"); - spin_lock_irqsave(&card->lock, flags); @@ -534,8 +506,6 @@ static void initialize_card(struct xircom_private *card) deactivate_transmitter(card); spin_unlock_irqrestore(&card->lock, flags); - - leave("initialize_card"); } /* @@ -547,12 +517,9 @@ ignored; I chose zero. static void trigger_transmit(struct xircom_private *card) { unsigned int val; - enter("trigger_transmit"); val = 0; outl(val, card->io_port + CSR1); - - leave("trigger_transmit"); } /* @@ -565,12 +532,9 @@ ignored; I chose zero. static void trigger_receive(struct xircom_private *card) { unsigned int val; - enter("trigger_receive"); val = 0; outl(val, card->io_port + CSR2); - - leave("trigger_receive"); } /* @@ -581,8 +545,6 @@ static void setup_descriptors(struct xircom_private *card) { u32 address; int i; - enter("setup_descriptors"); - BUG_ON(card->rx_buffer == NULL); BUG_ON(card->tx_buffer == NULL); @@ -636,8 +598,6 @@ static void setup_descriptors(struct xircom_private *card) /* wite the transmit descriptor ring to the card */ address = card->tx_dma_handle; outl(address, card->io_port + CSR4); /* xmit descr list address */ - - leave("setup_descriptors"); } /* @@ -647,13 +607,10 @@ valid by setting the address in the card to 0x00. static void remove_descriptors(struct xircom_private *card) { unsigned int val; - enter("remove_descriptors"); val = 0; outl(val, card->io_port + CSR3); /* Receive descriptor address */ outl(val, card->io_port + CSR4); /* Send descriptor address */ - - leave("remove_descriptors"); } /* @@ -665,21 +622,17 @@ This function also clears the status-bit. static int link_status_changed(struct xircom_private *card) { unsigned int val; - enter("link_status_changed"); val = inl(card->io_port + CSR5); /* Status register */ - if ((val & (1 << 27)) == 0) { /* no change */ - leave("link_status_changed - nochange"); + if ((val & (1 << 27)) == 0) /* no change */ return 0; - } /* clear the event by writing a 1 to the bit in the status register. */ val = (1 << 27); outl(val, card->io_port + CSR5); - leave("link_status_changed - changed"); return 1; } @@ -691,16 +644,12 @@ in a non-stopped state. static int transmit_active(struct xircom_private *card) { unsigned int val; - enter("transmit_active"); val = inl(card->io_port + CSR5); /* Status register */ - if ((val & (7 << 20)) == 0) { /* transmitter disabled */ - leave("transmit_active - inactive"); + if ((val & (7 << 20)) == 0) /* transmitter disabled */ return 0; - } - leave("transmit_active - active"); return 1; } @@ -711,17 +660,12 @@ in a non-stopped state. static int receive_active(struct xircom_private *card) { unsigned int val; - enter("receive_active"); - val = inl(card->io_port + CSR5); /* Status register */ - if ((val & (7 << 17)) == 0) { /* receiver disabled */ - leave("receive_active - inactive"); + if ((val & (7 << 17)) == 0) /* receiver disabled */ return 0; - } - leave("receive_active - active"); return 1; } @@ -739,8 +683,6 @@ static void activate_receiver(struct xircom_private *card) { unsigned int val; int counter; - enter("activate_receiver"); - val = inl(card->io_port + CSR6); /* Operation mode */ @@ -780,8 +722,6 @@ static void activate_receiver(struct xircom_private *card) if (counter <= 0) pr_err("Receiver failed to re-activate\n"); } - - leave("activate_receiver"); } /* @@ -795,7 +735,6 @@ static void deactivate_receiver(struct xircom_private *card) { unsigned int val; int counter; - enter("deactivate_receiver"); val = inl(card->io_port + CSR6); /* Operation mode */ val = val & ~2; /* disable the receiver */ @@ -811,9 +750,6 @@ static void deactivate_receiver(struct xircom_private *card) if (counter <= 0) pr_err("Receiver failed to deactivate\n"); } - - - leave("deactivate_receiver"); } @@ -831,8 +767,6 @@ static void activate_transmitter(struct xircom_private *card) { unsigned int val; int counter; - enter("activate_transmitter"); - val = inl(card->io_port + CSR6); /* Operation mode */ @@ -871,8 +805,6 @@ static void activate_transmitter(struct xircom_private *card) if (counter <= 0) pr_err("Transmitter failed to re-activate\n"); } - - leave("activate_transmitter"); } /* @@ -886,7 +818,6 @@ static void deactivate_transmitter(struct xircom_private *card) { unsigned int val; int counter; - enter("deactivate_transmitter"); val = inl(card->io_port + CSR6); /* Operation mode */ val = val & ~2; /* disable the transmitter */ @@ -902,9 +833,6 @@ static void deactivate_transmitter(struct xircom_private *card) if (counter <= 0) pr_err("Transmitter failed to deactivate\n"); } - - - leave("deactivate_transmitter"); } @@ -916,13 +844,10 @@ must be called with the lock held and interrupts disabled. static void enable_transmit_interrupt(struct xircom_private *card) { unsigned int val; - enter("enable_transmit_interrupt"); val = inl(card->io_port + CSR7); /* Interrupt enable register */ val |= 1; /* enable the transmit interrupt */ outl(val, card->io_port + CSR7); - - leave("enable_transmit_interrupt"); } @@ -934,13 +859,10 @@ must be called with the lock held and interrupts disabled. static void enable_receive_interrupt(struct xircom_private *card) { unsigned int val; - enter("enable_receive_interrupt"); val = inl(card->io_port + CSR7); /* Interrupt enable register */ val = val | (1 << 6); /* enable the receive interrupt */ outl(val, card->io_port + CSR7); - - leave("enable_receive_interrupt"); } /* @@ -951,13 +873,10 @@ must be called with the lock held and interrupts disabled. static void enable_link_interrupt(struct xircom_private *card) { unsigned int val; - enter("enable_link_interrupt"); val = inl(card->io_port + CSR7); /* Interrupt enable register */ val = val | (1 << 27); /* enable the link status chage interrupt */ outl(val, card->io_port + CSR7); - - leave("enable_link_interrupt"); } @@ -970,12 +889,9 @@ must be called with the lock held and interrupts disabled. static void disable_all_interrupts(struct xircom_private *card) { unsigned int val; - enter("enable_all_interrupts"); val = 0; /* disable all interrupts */ outl(val, card->io_port + CSR7); - - leave("disable_all_interrupts"); } /* @@ -986,7 +902,6 @@ must be called with the lock held and interrupts disabled. static void enable_common_interrupts(struct xircom_private *card) { unsigned int val; - enter("enable_link_interrupt"); val = inl(card->io_port + CSR7); /* Interrupt enable register */ val |= (1<<16); /* Normal Interrupt Summary */ @@ -998,8 +913,6 @@ static void enable_common_interrupts(struct xircom_private *card) val |= (1<<2); /* Transmit Buffer Unavailable */ val |= (1<<1); /* Transmit Process Stopped */ outl(val, card->io_port + CSR7); - - leave("enable_link_interrupt"); } /* @@ -1010,13 +923,11 @@ must be called with the lock held and interrupts disabled. static int enable_promisc(struct xircom_private *card) { unsigned int val; - enter("enable_promisc"); val = inl(card->io_port + CSR6); val = val | (1 << 6); outl(val, card->io_port + CSR6); - leave("enable_promisc"); return 1; } @@ -1031,7 +942,6 @@ Must be called in locked state with interrupts disabled static int link_status(struct xircom_private *card) { unsigned int val; - enter("link_status"); val = inb(card->io_port + CSR12); @@ -1042,7 +952,6 @@ static int link_status(struct xircom_private *card) /* If we get here -> no link at all */ - leave("link_status"); return 0; } @@ -1061,8 +970,6 @@ static void read_mac_address(struct xircom_private *card) unsigned long flags; int i; - enter("read_mac_address"); - spin_lock_irqsave(&card->lock, flags); outl(1 << 12, card->io_port + CSR9); /* enable boot rom access */ @@ -1090,7 +997,6 @@ static void read_mac_address(struct xircom_private *card) } spin_unlock_irqrestore(&card->lock, flags); pr_debug(" %pM\n", card->dev->dev_addr); - leave("read_mac_address"); } @@ -1103,8 +1009,6 @@ static void transceiver_voodoo(struct xircom_private *card) { unsigned long flags; - enter("transceiver_voodoo"); - /* disable all powermanagement */ pci_write_config_dword(card->pdev, PCI_POWERMGMT, 0x0000); @@ -1122,7 +1026,6 @@ static void transceiver_voodoo(struct xircom_private *card) spin_unlock_irqrestore(&card->lock, flags); netif_start_queue(card->dev); - leave("transceiver_voodoo"); } @@ -1131,8 +1034,6 @@ static void xircom_up(struct xircom_private *card) unsigned long flags; int i; - enter("xircom_up"); - /* disable all powermanagement */ pci_write_config_dword(card->pdev, PCI_POWERMGMT, 0x0000); @@ -1156,7 +1057,6 @@ static void xircom_up(struct xircom_private *card) trigger_receive(card); trigger_transmit(card); netif_start_queue(card->dev); - leave("xircom_up"); } /* Bufferoffset is in BYTES */ @@ -1164,7 +1064,6 @@ static void investigate_read_descriptor(struct net_device *dev,struct xircom_pri { int status; - enter("investigate_read_descriptor"); status = le32_to_cpu(card->rx_buffer[4*descnr]); if ((status > 0)) { /* packet received */ @@ -1197,9 +1096,6 @@ static void investigate_read_descriptor(struct net_device *dev,struct xircom_pri card->rx_buffer[4*descnr] = cpu_to_le32(0x80000000); trigger_receive(card); } - - leave("investigate_read_descriptor"); - } @@ -1208,8 +1104,6 @@ static void investigate_write_descriptor(struct net_device *dev, struct xircom_p { int status; - enter("investigate_write_descriptor"); - status = le32_to_cpu(card->tx_buffer[4*descnr]); #if 0 if (status & 0x8000) { /* Major error */ @@ -1232,8 +1126,6 @@ static void investigate_write_descriptor(struct net_device *dev, struct xircom_p dev->stats.tx_packets++; } - leave("investigate_write_descriptor"); - } -- cgit v1.2.3-58-ga151 From 163ef0b5922b14751e93218bdf2c9fe8f74b9c9d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 9 May 2011 09:45:21 +0000 Subject: tulip: Convert printks to netdev_ Use the current more descriptive logging styles. Add pr_fmt and remove PFX where appropriate. Use netif_, netdev_ Indent a few blocks in xircom_cb where appropriate. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/de2104x.c | 139 ++++++++++++++++++---------------------- drivers/net/tulip/dmfe.c | 2 +- drivers/net/tulip/eeprom.c | 4 +- drivers/net/tulip/tulip_core.c | 25 ++++---- drivers/net/tulip/uli526x.c | 42 ++++++------ drivers/net/tulip/winbond-840.c | 6 +- drivers/net/tulip/xircom_cb.c | 132 ++++++++++++++++++++------------------ 7 files changed, 170 insertions(+), 180 deletions(-) diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 46d5a1b15036..62883a0b0618 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -27,6 +27,8 @@ */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRV_NAME "de2104x" #define DRV_VERSION "0.7" #define DRV_RELDATE "Mar 17, 2004" @@ -73,8 +75,6 @@ static int rx_copybreak = 100; module_param (rx_copybreak, int, 0); MODULE_PARM_DESC (rx_copybreak, "de2104x Breakpoint at which Rx packets are copied"); -#define PFX DRV_NAME ": " - #define DE_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ NETIF_MSG_LINK | \ @@ -377,18 +377,16 @@ static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; static void de_rx_err_acct (struct de_private *de, unsigned rx_tail, u32 status, u32 len) { - if (netif_msg_rx_err (de)) - printk (KERN_DEBUG - "%s: rx err, slot %d status 0x%x len %d\n", - de->dev->name, rx_tail, status, len); + netif_printk(de, rx_err, KERN_DEBUG, de->dev, + "rx err, slot %d status 0x%x len %d\n", + rx_tail, status, len); if ((status & 0x38000300) != 0x0300) { /* Ingore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { - if (netif_msg_rx_err(de)) - dev_warn(&de->dev->dev, - "Oversized Ethernet frame spanned multiple buffers, status %08x!\n", - status); + netif_warn(de, rx_err, de->dev, + "Oversized Ethernet frame spanned multiple buffers, status %08x!\n", + status); de->net_stats.rx_length_errors++; } } else if (status & RxError) { @@ -491,7 +489,7 @@ rx_next: } if (!rx_work) - dev_warn(&de->dev->dev, "rx work limit reached\n"); + netdev_warn(de->dev, "rx work limit reached\n"); de->rx_tail = rx_tail; } @@ -534,9 +532,9 @@ static irqreturn_t de_interrupt (int irq, void *dev_instance) pci_read_config_word(de->pdev, PCI_STATUS, &pci_status); pci_write_config_word(de->pdev, PCI_STATUS, pci_status); - dev_err(&de->dev->dev, - "PCI bus error, status=%08x, PCI status=%04x\n", - status, pci_status); + netdev_err(de->dev, + "PCI bus error, status=%08x, PCI status=%04x\n", + status, pci_status); } return IRQ_HANDLED; @@ -873,7 +871,7 @@ static void de_stop_rxtx (struct de_private *de) udelay(100); } - dev_warn(&de->dev->dev, "timeout expired stopping DMA\n"); + netdev_warn(de->dev, "timeout expired, stopping DMA\n"); } static inline void de_start_rxtx (struct de_private *de) @@ -907,9 +905,8 @@ static void de_link_up(struct de_private *de) { if (!netif_carrier_ok(de->dev)) { netif_carrier_on(de->dev); - if (netif_msg_link(de)) - dev_info(&de->dev->dev, "link up, media %s\n", - media_name[de->media_type]); + netif_info(de, link, de->dev, "link up, media %s\n", + media_name[de->media_type]); } } @@ -917,8 +914,7 @@ static void de_link_down(struct de_private *de) { if (netif_carrier_ok(de->dev)) { netif_carrier_off(de->dev); - if (netif_msg_link(de)) - dev_info(&de->dev->dev, "link down\n"); + netif_info(de, link, de->dev, "link down\n"); } } @@ -928,8 +924,7 @@ static void de_set_media (struct de_private *de) u32 macmode = dr32(MacMode); if (de_is_running(de)) - dev_warn(&de->dev->dev, - "chip is running while changing media!\n"); + netdev_warn(de->dev, "chip is running while changing media!\n"); if (de->de21040) dw32(CSR11, FULL_DUPLEX_MAGIC); @@ -948,18 +943,13 @@ static void de_set_media (struct de_private *de) else macmode &= ~FullDuplex; - if (netif_msg_link(de)) - dev_info(&de->dev->dev, "set link %s\n", media_name[media]); - if (netif_msg_hw(de)) { - dev_info(&de->dev->dev, "mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n", - dr32(MacMode), dr32(SIAStatus), - dr32(CSR13), dr32(CSR14), dr32(CSR15)); - - dev_info(&de->dev->dev, - "set mode 0x%x, set sia 0x%x,0x%x,0x%x\n", - macmode, de->media[media].csr13, - de->media[media].csr14, de->media[media].csr15); - } + netif_info(de, link, de->dev, "set link %s\n", media_name[media]); + netif_info(de, hw, de->dev, "mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n", + dr32(MacMode), dr32(SIAStatus), + dr32(CSR13), dr32(CSR14), dr32(CSR15)); + netif_info(de, hw, de->dev, "set mode 0x%x, set sia 0x%x,0x%x,0x%x\n", + macmode, de->media[media].csr13, + de->media[media].csr14, de->media[media].csr15); if (macmode != dr32(MacMode)) dw32(MacMode, macmode); } @@ -996,9 +986,8 @@ static void de21040_media_timer (unsigned long data) if (!netif_carrier_ok(dev)) de_link_up(de); else - if (netif_msg_timer(de)) - dev_info(&dev->dev, "%s link ok, status %x\n", - media_name[de->media_type], status); + netif_info(de, timer, dev, "%s link ok, status %x\n", + media_name[de->media_type], status); return; } @@ -1025,9 +1014,8 @@ no_link_yet: de->media_timer.expires = jiffies + DE_TIMER_NO_LINK; add_timer(&de->media_timer); - if (netif_msg_timer(de)) - dev_info(&dev->dev, "no link, trying media %s, status %x\n", - media_name[de->media_type], status); + netif_info(de, timer, dev, "no link, trying media %s, status %x\n", + media_name[de->media_type], status); } static unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media) @@ -1085,11 +1073,10 @@ static void de21041_media_timer (unsigned long data) if (!netif_carrier_ok(dev)) de_link_up(de); else - if (netif_msg_timer(de)) - dev_info(&dev->dev, - "%s link ok, mode %x status %x\n", - media_name[de->media_type], - dr32(MacMode), status); + netif_info(de, timer, dev, + "%s link ok, mode %x status %x\n", + media_name[de->media_type], + dr32(MacMode), status); return; } @@ -1163,9 +1150,8 @@ no_link_yet: de->media_timer.expires = jiffies + DE_TIMER_NO_LINK; add_timer(&de->media_timer); - if (netif_msg_timer(de)) - dev_info(&dev->dev, "no link, trying media %s, status %x\n", - media_name[de->media_type], status); + netif_info(de, timer, dev, "no link, trying media %s, status %x\n", + media_name[de->media_type], status); } static void de_media_interrupt (struct de_private *de, u32 status) @@ -1401,14 +1387,13 @@ static int de_open (struct net_device *dev) struct de_private *de = netdev_priv(dev); int rc; - if (netif_msg_ifup(de)) - printk(KERN_DEBUG "%s: enabling interface\n", dev->name); + netif_printk(de, ifup, KERN_DEBUG, dev, "enabling interface\n"); de->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); rc = de_alloc_rings(de); if (rc) { - dev_err(&dev->dev, "ring allocation failure, err=%d\n", rc); + netdev_err(dev, "ring allocation failure, err=%d\n", rc); return rc; } @@ -1416,14 +1401,14 @@ static int de_open (struct net_device *dev) rc = request_irq(dev->irq, de_interrupt, IRQF_SHARED, dev->name, dev); if (rc) { - dev_err(&dev->dev, "IRQ %d request failure, err=%d\n", - dev->irq, rc); + netdev_err(dev, "IRQ %d request failure, err=%d\n", + dev->irq, rc); goto err_out_free; } rc = de_init_hw(de); if (rc) { - dev_err(&dev->dev, "h/w init failure, err=%d\n", rc); + netdev_err(dev, "h/w init failure, err=%d\n", rc); goto err_out_free_irq; } @@ -1444,8 +1429,7 @@ static int de_close (struct net_device *dev) struct de_private *de = netdev_priv(dev); unsigned long flags; - if (netif_msg_ifdown(de)) - printk(KERN_DEBUG "%s: disabling interface\n", dev->name); + netif_printk(de, ifdown, KERN_DEBUG, dev, "disabling interface\n"); del_timer_sync(&de->media_timer); @@ -1466,9 +1450,10 @@ static void de_tx_timeout (struct net_device *dev) { struct de_private *de = netdev_priv(dev); - printk(KERN_DEBUG "%s: NIC status %08x mode %08x sia %08x desc %u/%u/%u\n", - dev->name, dr32(MacStatus), dr32(MacMode), dr32(SIAStatus), - de->rx_tail, de->tx_head, de->tx_tail); + netdev_printk(KERN_DEBUG, dev, + "NIC status %08x mode %08x sia %08x desc %u/%u/%u\n", + dr32(MacStatus), dr32(MacMode), dr32(SIAStatus), + de->rx_tail, de->tx_head, de->tx_tail); del_timer_sync(&de->media_timer); @@ -1693,9 +1678,8 @@ static int de_nway_reset(struct net_device *dev) status = dr32(SIAStatus); dw32(SIAStatus, (status & ~NWayState) | NWayRestart); - if (netif_msg_link(de)) - dev_info(&de->dev->dev, "link nway restart, status %x,%x\n", - status, dr32(SIAStatus)); + netif_info(de, link, dev, "link nway restart, status %x,%x\n", + status, dr32(SIAStatus)); return 0; } @@ -1740,7 +1724,8 @@ static void __devinit de21040_get_mac_address (struct de_private *de) de->dev->dev_addr[i] = value; udelay(1); if (boguscnt <= 0) - pr_warning(PFX "timeout reading 21040 MAC address byte %u\n", i); + pr_warn("timeout reading 21040 MAC address byte %u\n", + i); } } @@ -1926,8 +1911,10 @@ static void __devinit de21041_get_srom_info (struct de_private *de) de->media[idx].csr14, de->media[idx].csr15); - } else if (netif_msg_probe(de)) - pr_cont("\n"); + } else { + if (netif_msg_probe(de)) + pr_cont("\n"); + } if (bufp > ((void *)&ee_data[DE_EEPROM_SIZE - 3])) break; @@ -2038,7 +2025,7 @@ static int __devinit de_init_one (struct pci_dev *pdev, /* check for invalid IRQ value */ if (pdev->irq < 2) { rc = -EIO; - pr_err(PFX "invalid irq (%d) for pci dev %s\n", + pr_err("invalid irq (%d) for pci dev %s\n", pdev->irq, pci_name(pdev)); goto err_out_res; } @@ -2049,12 +2036,12 @@ static int __devinit de_init_one (struct pci_dev *pdev, pciaddr = pci_resource_start(pdev, 1); if (!pciaddr) { rc = -EIO; - pr_err(PFX "no MMIO resource for pci dev %s\n", pci_name(pdev)); + pr_err("no MMIO resource for pci dev %s\n", pci_name(pdev)); goto err_out_res; } if (pci_resource_len(pdev, 1) < DE_REGS_SIZE) { rc = -EIO; - pr_err(PFX "MMIO resource (%llx) too small on pci dev %s\n", + pr_err("MMIO resource (%llx) too small on pci dev %s\n", (unsigned long long)pci_resource_len(pdev, 1), pci_name(pdev)); goto err_out_res; @@ -2064,7 +2051,7 @@ static int __devinit de_init_one (struct pci_dev *pdev, regs = ioremap_nocache(pciaddr, DE_REGS_SIZE); if (!regs) { rc = -EIO; - pr_err(PFX "Cannot map PCI MMIO (%llx@%lx) on pci dev %s\n", + pr_err("Cannot map PCI MMIO (%llx@%lx) on pci dev %s\n", (unsigned long long)pci_resource_len(pdev, 1), pciaddr, pci_name(pdev)); goto err_out_res; @@ -2077,7 +2064,7 @@ static int __devinit de_init_one (struct pci_dev *pdev, /* make sure hardware is not running */ rc = de_reset_mac(de); if (rc) { - pr_err(PFX "Cannot reset MAC, pci dev %s\n", pci_name(pdev)); + pr_err("Cannot reset MAC, pci dev %s\n", pci_name(pdev)); goto err_out_iomap; } @@ -2097,11 +2084,11 @@ static int __devinit de_init_one (struct pci_dev *pdev, goto err_out_iomap; /* print info about board and interface just registered */ - dev_info(&dev->dev, "%s at 0x%lx, %pM, IRQ %d\n", - de->de21040 ? "21040" : "21041", - dev->base_addr, - dev->dev_addr, - dev->irq); + netdev_info(dev, "%s at 0x%lx, %pM, IRQ %d\n", + de->de21040 ? "21040" : "21041", + dev->base_addr, + dev->dev_addr, + dev->irq); pci_set_drvdata(pdev, dev); @@ -2189,7 +2176,7 @@ static int de_resume (struct pci_dev *pdev) if (!netif_running(dev)) goto out_attach; if ((retval = pci_enable_device(pdev))) { - dev_err(&dev->dev, "pci_enable_device failed in resume\n"); + netdev_err(dev, "pci_enable_device failed in resume\n"); goto out; } pci_set_master(pdev); diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index fb07f48910ae..96e8541a76e9 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -406,7 +406,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, SET_NETDEV_DEV(dev, &pdev->dev); if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - pr_warning("32-bit PCI DMA not available\n"); + pr_warn("32-bit PCI DMA not available\n"); err = -ENODEV; goto err_out_free; } diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c index 296486bf0956..fa5eee925f25 100644 --- a/drivers/net/tulip/eeprom.c +++ b/drivers/net/tulip/eeprom.c @@ -222,8 +222,8 @@ subsequent_board: /* there is no phy information, don't even try to build mtable */ if (count == 0) { if (tulip_debug > 0) - pr_warning("%s: no phy info, aborting mtable build\n", - dev->name); + pr_warn("%s: no phy info, aborting mtable build\n", + dev->name); return; } diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 5c01e260f1ba..f46898a588d1 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -12,6 +12,7 @@ Please submit bugs to http://bugzilla.kernel.org/ . */ +#define pr_fmt(fmt) "tulip: " fmt #define DRV_NAME "tulip" #ifdef CONFIG_TULIP_NAPI @@ -119,8 +120,6 @@ module_param(csr0, int, 0); module_param_array(options, int, NULL, 0); module_param_array(full_duplex, int, NULL, 0); -#define PFX DRV_NAME ": " - #ifdef TULIP_DEBUG int tulip_debug = TULIP_DEBUG; #else @@ -1340,13 +1339,13 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, */ if (pdev->subsystem_vendor == PCI_VENDOR_ID_LMC) { - pr_err(PFX "skipping LMC card\n"); + pr_err("skipping LMC card\n"); return -ENODEV; } else if (pdev->subsystem_vendor == PCI_VENDOR_ID_SBE && (pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_T3E3 || pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_2T3E3_P0 || pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_2T3E3_P1)) { - pr_err(PFX "skipping SBE T3E3 port\n"); + pr_err("skipping SBE T3E3 port\n"); return -ENODEV; } @@ -1362,13 +1361,13 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, if (pdev->vendor == 0x1282 && pdev->device == 0x9100 && pdev->revision < 0x30) { - pr_info(PFX "skipping early DM9100 with Crc bug (use dmfe)\n"); + pr_info("skipping early DM9100 with Crc bug (use dmfe)\n"); return -ENODEV; } dp = pci_device_to_OF_node(pdev); if (!(dp && of_get_property(dp, "local-mac-address", NULL))) { - pr_info(PFX "skipping DM910x expansion card (use dmfe)\n"); + pr_info("skipping DM910x expansion card (use dmfe)\n"); return -ENODEV; } } @@ -1415,16 +1414,14 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, i = pci_enable_device(pdev); if (i) { - pr_err(PFX "Cannot enable tulip board #%d, aborting\n", - board_idx); + pr_err("Cannot enable tulip board #%d, aborting\n", board_idx); return i; } /* The chip will fail to enter a low-power state later unless * first explicitly commanded into D0 */ if (pci_set_power_state(pdev, PCI_D0)) { - printk (KERN_NOTICE PFX - "Failed to set power state to D0\n"); + pr_notice("Failed to set power state to D0\n"); } irq = pdev->irq; @@ -1432,13 +1429,13 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, /* alloc_etherdev ensures aligned and zeroed private structures */ dev = alloc_etherdev (sizeof (*tp)); if (!dev) { - pr_err(PFX "ether device alloc failed, aborting\n"); + pr_err("ether device alloc failed, aborting\n"); return -ENOMEM; } SET_NETDEV_DEV(dev, &pdev->dev); if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) { - pr_err(PFX "%s: I/O region (0x%llx@0x%llx) too small, aborting\n", + pr_err("%s: I/O region (0x%llx@0x%llx) too small, aborting\n", pci_name(pdev), (unsigned long long)pci_resource_len (pdev, 0), (unsigned long long)pci_resource_start (pdev, 0)); @@ -1905,12 +1902,12 @@ static int tulip_resume(struct pci_dev *pdev) return 0; if ((retval = pci_enable_device(pdev))) { - pr_err(PFX "pci_enable_device failed in resume\n"); + pr_err("pci_enable_device failed in resume\n"); return retval; } if ((retval = request_irq(dev->irq, tulip_interrupt, IRQF_SHARED, dev->name, dev))) { - pr_err(PFX "request_irq failed in resume\n"); + pr_err("request_irq failed in resume\n"); return retval; } diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index a4375c406b5f..92c00ee55961 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -292,7 +292,7 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev, SET_NETDEV_DEV(dev, &pdev->dev); if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - pr_warning("32-bit PCI DMA not available\n"); + pr_warn("32-bit PCI DMA not available\n"); err = -ENODEV; goto err_out_free; } @@ -390,9 +390,9 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev, if (err) goto err_out_res; - dev_info(&dev->dev, "ULi M%04lx at pci%s, %pM, irq %d\n", - ent->driver_data >> 16, pci_name(pdev), - dev->dev_addr, dev->irq); + netdev_info(dev, "ULi M%04lx at pci%s, %pM, irq %d\n", + ent->driver_data >> 16, pci_name(pdev), + dev->dev_addr, dev->irq); pci_set_master(pdev); @@ -524,7 +524,7 @@ static void uli526x_init(struct net_device *dev) } } if(phy_tmp == 32) - pr_warning("Can not find the phy address!!!"); + pr_warn("Can not find the phy address!!!\n"); /* Parser SROM and media mode */ db->media_mode = uli526x_media_mode; @@ -590,7 +590,7 @@ static netdev_tx_t uli526x_start_xmit(struct sk_buff *skb, /* Too large packet check */ if (skb->len > MAX_PACKET_SIZE) { - pr_err("big packet = %d\n", (u16)skb->len); + netdev_err(dev, "big packet = %d\n", (u16)skb->len); dev_kfree_skb(skb); return NETDEV_TX_OK; } @@ -600,7 +600,7 @@ static netdev_tx_t uli526x_start_xmit(struct sk_buff *skb, /* No Tx resource check, it never happen nromally */ if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) { spin_unlock_irqrestore(&db->lock, flags); - pr_err("No Tx resource %ld\n", db->tx_packet_cnt); + netdev_err(dev, "No Tx resource %ld\n", db->tx_packet_cnt); return NETDEV_TX_BUSY; } @@ -1024,7 +1024,6 @@ static void uli526x_timer(unsigned long data) struct net_device *dev = (struct net_device *) data; struct uli526x_board_info *db = netdev_priv(dev); unsigned long flags; - u8 TmpSpeed=10; //ULI526X_DBUG(0, "uli526x_timer()", 0); spin_lock_irqsave(&db->lock, flags); @@ -1070,7 +1069,7 @@ static void uli526x_timer(unsigned long data) /* Link Failed */ ULI526X_DBUG(0, "Link Failed", tmp_cr12); netif_carrier_off(dev); - pr_info("%s NIC Link is Down\n",dev->name); + netdev_info(dev, "NIC Link is Down\n"); db->link_failed = 1; /* For Force 10/100M Half/Full mode: Enable Auto-Nego mode */ @@ -1096,18 +1095,13 @@ static void uli526x_timer(unsigned long data) if(db->link_failed==0) { - if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD) - { - TmpSpeed = 100; - } - if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD) - { - pr_info("%s NIC Link is Up %d Mbps Full duplex\n",dev->name,TmpSpeed); - } - else - { - pr_info("%s NIC Link is Up %d Mbps Half duplex\n",dev->name,TmpSpeed); - } + netdev_info(dev, "NIC Link is Up %d Mbps %s duplex\n", + (db->op_mode == ULI526X_100MHF || + db->op_mode == ULI526X_100MFD) + ? 100 : 10, + (db->op_mode == ULI526X_10MFD || + db->op_mode == ULI526X_100MFD) + ? "Full" : "Half"); netif_carrier_on(dev); } /* SHOW_MEDIA_TYPE(db->op_mode); */ @@ -1116,7 +1110,7 @@ static void uli526x_timer(unsigned long data) { if(db->init==1) { - pr_info("%s NIC Link is Down\n",dev->name); + netdev_info(dev, "NIC Link is Down\n"); netif_carrier_off(dev); } } @@ -1242,7 +1236,7 @@ static int uli526x_resume(struct pci_dev *pdev) err = pci_set_power_state(pdev, PCI_D0); if (err) { - dev_warn(&dev->dev, "Could not put device into D0\n"); + netdev_warn(dev, "Could not put device into D0\n"); return err; } @@ -1443,7 +1437,7 @@ static void send_filter_frame(struct net_device *dev, int mc_cnt) update_cr6(db->cr6_data, dev->base_addr); dev->trans_start = jiffies; } else - pr_err("No Tx resource - Send_filter_frame!\n"); + netdev_err(dev, "No Tx resource - Send_filter_frame!\n"); } diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index f0b231035dee..939c96e2438a 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -44,6 +44,8 @@ * Wake-On-LAN */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRV_NAME "winbond-840" #define DRV_VERSION "1.01-e" #define DRV_RELDATE "Sep-11-2006" @@ -375,8 +377,8 @@ static int __devinit w840_probe1 (struct pci_dev *pdev, irq = pdev->irq; if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - pr_warning("Winbond-840: Device %s disabled due to DMA limitations\n", - pci_name(pdev)); + pr_warn("Device %s disabled due to DMA limitations\n", + pci_name(pdev)); return -EIO; } dev = alloc_etherdev(sizeof(*np)); diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index d0d0cbe3dc17..7e8287260c2f 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -262,8 +262,8 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ goto reg_fail; } - dev_info(&dev->dev, "Xircom cardbus revision %i at irq %i\n", - pdev->revision, pdev->irq); + netdev_info(dev, "Xircom cardbus revision %i at irq %i\n", + pdev->revision, pdev->irq); /* start the transmitter to get a heartbeat */ /* TODO: send 2 dummy packets here */ transceiver_voodoo(private); @@ -335,7 +335,7 @@ static irqreturn_t xircom_interrupt(int irq, void *dev_instance) int newlink; printk(KERN_DEBUG "xircom_cb: Link status has changed\n"); newlink = link_status(card); - dev_info(&dev->dev, "Link is %i mbit\n", newlink); + netdev_info(dev, "Link is %d mbit\n", newlink); if (newlink) netif_carrier_on(dev); else @@ -426,8 +426,8 @@ static int xircom_open(struct net_device *dev) struct xircom_private *xp = netdev_priv(dev); int retval; - pr_info("xircom cardbus adaptor found, registering as %s, using irq %i\n", - dev->name, dev->irq); + netdev_info(dev, "xircom cardbus adaptor found, using irq %i\n", + dev->irq); retval = request_irq(dev->irq, xircom_interrupt, IRQF_SHARED, dev->name, dev); if (retval) return retval; @@ -703,7 +703,7 @@ static void activate_receiver(struct xircom_private *card) udelay(50); counter--; if (counter <= 0) - pr_err("Receiver failed to deactivate\n"); + netdev_err(card->dev, "Receiver failed to deactivate\n"); } /* enable the receiver */ @@ -720,7 +720,8 @@ static void activate_receiver(struct xircom_private *card) udelay(50); counter--; if (counter <= 0) - pr_err("Receiver failed to re-activate\n"); + netdev_err(card->dev, + "Receiver failed to re-activate\n"); } } @@ -748,7 +749,7 @@ static void deactivate_receiver(struct xircom_private *card) udelay(50); counter--; if (counter <= 0) - pr_err("Receiver failed to deactivate\n"); + netdev_err(card->dev, "Receiver failed to deactivate\n"); } } @@ -786,7 +787,8 @@ static void activate_transmitter(struct xircom_private *card) udelay(50); counter--; if (counter <= 0) - pr_err("Transmitter failed to deactivate\n"); + netdev_err(card->dev, + "Transmitter failed to deactivate\n"); } /* enable the transmitter */ @@ -803,7 +805,8 @@ static void activate_transmitter(struct xircom_private *card) udelay(50); counter--; if (counter <= 0) - pr_err("Transmitter failed to re-activate\n"); + netdev_err(card->dev, + "Transmitter failed to re-activate\n"); } } @@ -831,7 +834,8 @@ static void deactivate_transmitter(struct xircom_private *card) udelay(50); counter--; if (counter <= 0) - pr_err("Transmitter failed to deactivate\n"); + netdev_err(card->dev, + "Transmitter failed to deactivate\n"); } } @@ -1060,75 +1064,81 @@ static void xircom_up(struct xircom_private *card) } /* Bufferoffset is in BYTES */ -static void investigate_read_descriptor(struct net_device *dev,struct xircom_private *card, int descnr, unsigned int bufferoffset) +static void +investigate_read_descriptor(struct net_device *dev, struct xircom_private *card, + int descnr, unsigned int bufferoffset) { - int status; + int status; - status = le32_to_cpu(card->rx_buffer[4*descnr]); + status = le32_to_cpu(card->rx_buffer[4*descnr]); - if ((status > 0)) { /* packet received */ + if (status > 0) { /* packet received */ - /* TODO: discard error packets */ + /* TODO: discard error packets */ - short pkt_len = ((status >> 16) & 0x7ff) - 4; /* minus 4, we don't want the CRC */ - struct sk_buff *skb; + short pkt_len = ((status >> 16) & 0x7ff) - 4; + /* minus 4, we don't want the CRC */ + struct sk_buff *skb; - if (pkt_len > 1518) { - pr_err("Packet length %i is bogus\n", pkt_len); - pkt_len = 1518; - } + if (pkt_len > 1518) { + netdev_err(dev, "Packet length %i is bogus\n", pkt_len); + pkt_len = 1518; + } - skb = dev_alloc_skb(pkt_len + 2); - if (skb == NULL) { - dev->stats.rx_dropped++; - goto out; - } - skb_reserve(skb, 2); - skb_copy_to_linear_data(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len); - skb_put(skb, pkt_len); - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += pkt_len; - - out: - /* give the buffer back to the card */ - card->rx_buffer[4*descnr] = cpu_to_le32(0x80000000); - trigger_receive(card); + skb = dev_alloc_skb(pkt_len + 2); + if (skb == NULL) { + dev->stats.rx_dropped++; + goto out; } + skb_reserve(skb, 2); + skb_copy_to_linear_data(skb, + &card->rx_buffer[bufferoffset / 4], + pkt_len); + skb_put(skb, pkt_len); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + dev->stats.rx_packets++; + dev->stats.rx_bytes += pkt_len; + +out: + /* give the buffer back to the card */ + card->rx_buffer[4*descnr] = cpu_to_le32(0x80000000); + trigger_receive(card); + } } /* Bufferoffset is in BYTES */ -static void investigate_write_descriptor(struct net_device *dev, struct xircom_private *card, int descnr, unsigned int bufferoffset) +static void +investigate_write_descriptor(struct net_device *dev, + struct xircom_private *card, + int descnr, unsigned int bufferoffset) { - int status; + int status; - status = le32_to_cpu(card->tx_buffer[4*descnr]); + status = le32_to_cpu(card->tx_buffer[4*descnr]); #if 0 - if (status & 0x8000) { /* Major error */ - pr_err("Major transmit error status %x\n", status); - card->tx_buffer[4*descnr] = 0; - netif_wake_queue (dev); - } + if (status & 0x8000) { /* Major error */ + pr_err("Major transmit error status %x\n", status); + card->tx_buffer[4*descnr] = 0; + netif_wake_queue (dev); + } #endif - if (status > 0) { /* bit 31 is 0 when done */ - if (card->tx_skb[descnr]!=NULL) { - dev->stats.tx_bytes += card->tx_skb[descnr]->len; - dev_kfree_skb_irq(card->tx_skb[descnr]); - } - card->tx_skb[descnr] = NULL; - /* Bit 8 in the status field is 1 if there was a collision */ - if (status&(1<<8)) - dev->stats.collisions++; - card->tx_buffer[4*descnr] = 0; /* descriptor is free again */ - netif_wake_queue (dev); - dev->stats.tx_packets++; + if (status > 0) { /* bit 31 is 0 when done */ + if (card->tx_skb[descnr]!=NULL) { + dev->stats.tx_bytes += card->tx_skb[descnr]->len; + dev_kfree_skb_irq(card->tx_skb[descnr]); } - + card->tx_skb[descnr] = NULL; + /* Bit 8 in the status field is 1 if there was a collision */ + if (status & (1 << 8)) + dev->stats.collisions++; + card->tx_buffer[4*descnr] = 0; /* descriptor is free again */ + netif_wake_queue (dev); + dev->stats.tx_packets++; + } } - static int __init xircom_init(void) { return pci_register_driver(&xircom_ops); -- cgit v1.2.3-58-ga151 From 726b65ad444dd142e34d0087fcbba03d16b34ca6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 9 May 2011 09:45:22 +0000 Subject: tulip: Convert uses of KERN_DEBUG Convert logging messages to more current styles. Added -DDEBUG to Makefile to maintain current message logging. This could be converted to a specific CONFIG_TULIP_DEBUG option. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/21142.c | 14 ++++---- drivers/net/tulip/Makefile | 2 ++ drivers/net/tulip/de2104x.c | 47 ++++++++++++-------------- drivers/net/tulip/interrupt.c | 48 +++++++++++++-------------- drivers/net/tulip/media.c | 49 ++++++++++++++------------- drivers/net/tulip/pnic.c | 22 ++++++------- drivers/net/tulip/pnic2.c | 16 ++++----- drivers/net/tulip/timer.c | 47 +++++++++++++------------- drivers/net/tulip/tulip.h | 8 ++--- drivers/net/tulip/tulip_core.c | 20 +++++------ drivers/net/tulip/winbond-840.c | 73 +++++++++++++++++++---------------------- drivers/net/tulip/xircom_cb.c | 2 +- 12 files changed, 166 insertions(+), 182 deletions(-) diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c index 007d8e75666d..092c3faa882a 100644 --- a/drivers/net/tulip/21142.c +++ b/drivers/net/tulip/21142.c @@ -122,8 +122,8 @@ void t21142_start_nway(struct net_device *dev) tp->nway = tp->mediasense = 1; tp->nwayset = tp->lpar = 0; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Restarting 21143 autonegotiation, csr14=%08x\n", - dev->name, csr14); + netdev_dbg(dev, "Restarting 21143 autonegotiation, csr14=%08x\n", + csr14); iowrite32(0x0001, ioaddr + CSR13); udelay(100); iowrite32(csr14, ioaddr + CSR14); @@ -206,14 +206,14 @@ void t21142_lnk_change(struct net_device *dev, int csr5) #if 0 /* Restart shouldn't be needed. */ iowrite32(tp->csr6 | RxOn, ioaddr + CSR6); if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Restarting Tx and Rx, CSR5 is %08x\n", - dev->name, ioread32(ioaddr + CSR5)); + netdev_dbg(dev, " Restarting Tx and Rx, CSR5 is %08x\n", + ioread32(ioaddr + CSR5)); #endif tulip_start_rxtx(tp); if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Setting CSR6 %08x/%x CSR12 %08x\n", - dev->name, tp->csr6, ioread32(ioaddr + CSR6), - ioread32(ioaddr + CSR12)); + netdev_dbg(dev, " Setting CSR6 %08x/%x CSR12 %08x\n", + tp->csr6, ioread32(ioaddr + CSR6), + ioread32(ioaddr + CSR12)); } else if ((tp->nwayset && (csr5 & 0x08000000) && (dev->if_port == 3 || dev->if_port == 5) && (csr12 & 2) == 2) || diff --git a/drivers/net/tulip/Makefile b/drivers/net/tulip/Makefile index 200cbf7c815c..5e8be38b45bb 100644 --- a/drivers/net/tulip/Makefile +++ b/drivers/net/tulip/Makefile @@ -2,6 +2,8 @@ # Makefile for the Linux "Tulip" family network device drivers. # +ccflags-$(CONFIG_NET_TULIP) := -DDEBUG + obj-$(CONFIG_PCMCIA_XIRCOM) += xircom_cb.o obj-$(CONFIG_DM9102) += dmfe.o obj-$(CONFIG_WINBOND_840) += winbond-840.o diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 62883a0b0618..e925c1ea04bb 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -377,9 +377,9 @@ static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; static void de_rx_err_acct (struct de_private *de, unsigned rx_tail, u32 status, u32 len) { - netif_printk(de, rx_err, KERN_DEBUG, de->dev, - "rx err, slot %d status 0x%x len %d\n", - rx_tail, status, len); + netif_dbg(de, rx_err, de->dev, + "rx err, slot %d status 0x%x len %d\n", + rx_tail, status, len); if ((status & 0x38000300) != 0x0300) { /* Ingore earlier buffers. */ @@ -433,10 +433,9 @@ static void de_rx (struct de_private *de) copying_skb = (len <= rx_copybreak); - if (unlikely(netif_msg_rx_status(de))) - printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d copying? %d\n", - de->dev->name, rx_tail, status, len, - copying_skb); + netif_dbg(de, rx_status, de->dev, + "rx slot %d status 0x%x len %d copying? %d\n", + rx_tail, status, len, copying_skb); buflen = copying_skb ? (len + RX_OFFSET) : de->rx_buf_sz; copy_skb = dev_alloc_skb (buflen); @@ -504,10 +503,9 @@ static irqreturn_t de_interrupt (int irq, void *dev_instance) if ((!(status & (IntrOK|IntrErr))) || (status == 0xFFFF)) return IRQ_NONE; - if (netif_msg_intr(de)) - printk(KERN_DEBUG "%s: intr, status %08x mode %08x desc %u/%u/%u\n", - dev->name, status, dr32(MacMode), - de->rx_tail, de->tx_head, de->tx_tail); + netif_dbg(de, intr, dev, "intr, status %08x mode %08x desc %u/%u/%u\n", + status, dr32(MacMode), + de->rx_tail, de->tx_head, de->tx_tail); dw32(MacStatus, status); @@ -570,9 +568,9 @@ static void de_tx (struct de_private *de) if (status & LastFrag) { if (status & TxError) { - if (netif_msg_tx_err(de)) - printk(KERN_DEBUG "%s: tx err, status 0x%x\n", - de->dev->name, status); + netif_dbg(de, tx_err, de->dev, + "tx err, status 0x%x\n", + status); de->net_stats.tx_errors++; if (status & TxOWC) de->net_stats.tx_window_errors++; @@ -585,9 +583,8 @@ static void de_tx (struct de_private *de) } else { de->net_stats.tx_packets++; de->net_stats.tx_bytes += skb->len; - if (netif_msg_tx_done(de)) - printk(KERN_DEBUG "%s: tx done, slot %d\n", - de->dev->name, tx_tail); + netif_dbg(de, tx_done, de->dev, + "tx done, slot %d\n", tx_tail); } dev_kfree_skb_irq(skb); } @@ -644,9 +641,8 @@ static netdev_tx_t de_start_xmit (struct sk_buff *skb, wmb(); de->tx_head = NEXT_TX(entry); - if (netif_msg_tx_queued(de)) - printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n", - dev->name, entry, skb->len); + netif_dbg(de, tx_queued, dev, "tx queued, slot %d, skblen %d\n", + entry, skb->len); if (tx_free == 0) netif_stop_queue(dev); @@ -1387,7 +1383,7 @@ static int de_open (struct net_device *dev) struct de_private *de = netdev_priv(dev); int rc; - netif_printk(de, ifup, KERN_DEBUG, dev, "enabling interface\n"); + netif_dbg(de, ifup, dev, "enabling interface\n"); de->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); @@ -1429,7 +1425,7 @@ static int de_close (struct net_device *dev) struct de_private *de = netdev_priv(dev); unsigned long flags; - netif_printk(de, ifdown, KERN_DEBUG, dev, "disabling interface\n"); + netif_dbg(de, ifdown, dev, "disabling interface\n"); del_timer_sync(&de->media_timer); @@ -1450,10 +1446,9 @@ static void de_tx_timeout (struct net_device *dev) { struct de_private *de = netdev_priv(dev); - netdev_printk(KERN_DEBUG, dev, - "NIC status %08x mode %08x sia %08x desc %u/%u/%u\n", - dr32(MacStatus), dr32(MacMode), dr32(SIAStatus), - de->rx_tail, de->tx_head, de->tx_tail); + netdev_dbg(dev, "NIC status %08x mode %08x sia %08x desc %u/%u/%u\n", + dr32(MacStatus), dr32(MacMode), dr32(SIAStatus), + de->rx_tail, de->tx_head, de->tx_tail); del_timer_sync(&de->media_timer); diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c index 0013642903ee..5350d753e0ff 100644 --- a/drivers/net/tulip/interrupt.c +++ b/drivers/net/tulip/interrupt.c @@ -125,12 +125,12 @@ int tulip_poll(struct napi_struct *napi, int budget) #endif if (tulip_debug > 4) - printk(KERN_DEBUG " In tulip_rx(), entry %d %08x\n", - entry, tp->rx_ring[entry].status); + netdev_dbg(dev, " In tulip_rx(), entry %d %08x\n", + entry, tp->rx_ring[entry].status); do { if (ioread32(tp->base_addr + CSR5) == 0xffffffff) { - printk(KERN_DEBUG " In tulip_poll(), hardware disappeared\n"); + netdev_dbg(dev, " In tulip_poll(), hardware disappeared\n"); break; } /* Acknowledge current RX interrupt sources. */ @@ -145,9 +145,9 @@ int tulip_poll(struct napi_struct *napi, int budget) if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx) break; - if (tulip_debug > 5) - printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %08x\n", - dev->name, entry, status); + if (tulip_debug > 5) + netdev_dbg(dev, "In tulip_rx(), entry %d %08x\n", + entry, status); if (++work_done >= budget) goto not_done; @@ -184,9 +184,9 @@ int tulip_poll(struct napi_struct *napi, int budget) } } else { /* There was a fatal error. */ - if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Receive error, Rx status %08x\n", - dev->name, status); + if (tulip_debug > 2) + netdev_dbg(dev, "Receive error, Rx status %08x\n", + status); dev->stats.rx_errors++; /* end of a packet.*/ if (pkt_len > 1518 || (status & RxDescRunt)) @@ -367,16 +367,16 @@ static int tulip_rx(struct net_device *dev) int received = 0; if (tulip_debug > 4) - printk(KERN_DEBUG " In tulip_rx(), entry %d %08x\n", - entry, tp->rx_ring[entry].status); + netdev_dbg(dev, "In tulip_rx(), entry %d %08x\n", + entry, tp->rx_ring[entry].status); /* If we own the next entry, it is a new packet. Send it up. */ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { s32 status = le32_to_cpu(tp->rx_ring[entry].status); short pkt_len; if (tulip_debug > 5) - printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %08x\n", - dev->name, entry, status); + netdev_dbg(dev, "In tulip_rx(), entry %d %08x\n", + entry, status); if (--rx_work_limit < 0) break; @@ -404,16 +404,16 @@ static int tulip_rx(struct net_device *dev) /* Ingore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { if (tulip_debug > 1) - dev_warn(&dev->dev, - "Oversized Ethernet frame spanned multiple buffers, status %08x!\n", - status); + netdev_warn(dev, + "Oversized Ethernet frame spanned multiple buffers, status %08x!\n", + status); dev->stats.rx_length_errors++; } } else { /* There was a fatal error. */ if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Receive error, Rx status %08x\n", - dev->name, status); + netdev_dbg(dev, "Receive error, Rx status %08x\n", + status); dev->stats.rx_errors++; /* end of a packet.*/ if (pkt_len > 1518 || (status & RxDescRunt)) @@ -573,8 +573,8 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) #endif /* CONFIG_TULIP_NAPI */ if (tulip_debug > 4) - printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x\n", - dev->name, csr5, ioread32(ioaddr + CSR5)); + netdev_dbg(dev, "interrupt csr5=%#8.8x new csr5=%#8.8x\n", + csr5, ioread32(ioaddr + CSR5)); if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { @@ -605,8 +605,8 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) /* There was an major error, log it. */ #ifndef final_version if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Transmit error, Tx status %08x\n", - dev->name, status); + netdev_dbg(dev, "Transmit error, Tx status %08x\n", + status); #endif dev->stats.tx_errors++; if (status & 0x4104) @@ -804,8 +804,8 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) } if (tulip_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#04x\n", - dev->name, ioread32(ioaddr + CSR5)); + netdev_dbg(dev, "exiting interrupt, csr5=%#04x\n", + ioread32(ioaddr + CSR5)); return IRQ_HANDLED; } diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c index a0c770ee4b64..4bd13922875d 100644 --- a/drivers/net/tulip/media.c +++ b/drivers/net/tulip/media.c @@ -182,8 +182,8 @@ void tulip_select_media(struct net_device *dev, int startup) switch (mleaf->type) { case 0: /* 21140 non-MII xcvr. */ if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Using a 21140 non-MII transceiver with control setting %02x\n", - dev->name, p[1]); + netdev_dbg(dev, "Using a 21140 non-MII transceiver with control setting %02x\n", + p[1]); dev->if_port = p[0]; if (startup) iowrite32(mtable->csr12dir | 0x100, ioaddr + CSR12); @@ -204,15 +204,14 @@ void tulip_select_media(struct net_device *dev, int startup) struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset]; unsigned char *rst = rleaf->leafdata; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Resetting the transceiver\n", - dev->name); + netdev_dbg(dev, "Resetting the transceiver\n"); for (i = 0; i < rst[0]; i++) iowrite32(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); } if (tulip_debug > 1) - printk(KERN_DEBUG "%s: 21143 non-MII %s transceiver control %04x/%04x\n", - dev->name, medianame[dev->if_port], - setup[0], setup[1]); + netdev_dbg(dev, "21143 non-MII %s transceiver control %04x/%04x\n", + medianame[dev->if_port], + setup[0], setup[1]); if (p[0] & 0x40) { /* SIA (CSR13-15) setup values are provided. */ csr13val = setup[0]; csr14val = setup[1]; @@ -239,8 +238,8 @@ void tulip_select_media(struct net_device *dev, int startup) if (startup) iowrite32(csr13val, ioaddr + CSR13); } if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Setting CSR15 to %08x/%08x\n", - dev->name, csr15dir, csr15val); + netdev_dbg(dev, "Setting CSR15 to %08x/%08x\n", + csr15dir, csr15val); if (mleaf->type == 4) new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18); else @@ -316,9 +315,9 @@ void tulip_select_media(struct net_device *dev, int startup) if (tp->mii_advertise == 0) tp->mii_advertise = tp->advertising[phy_num]; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Advertising %04x on MII %d\n", - dev->name, tp->mii_advertise, - tp->phys[phy_num]); + netdev_dbg(dev, " Advertising %04x on MII %d\n", + tp->mii_advertise, + tp->phys[phy_num]); tulip_mdio_write(dev, tp->phys[phy_num], 4, tp->mii_advertise); } break; @@ -335,8 +334,7 @@ void tulip_select_media(struct net_device *dev, int startup) struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset]; unsigned char *rst = rleaf->leafdata; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Resetting the transceiver\n", - dev->name); + netdev_dbg(dev, "Resetting the transceiver\n"); for (i = 0; i < rst[0]; i++) iowrite32(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); } @@ -344,20 +342,21 @@ void tulip_select_media(struct net_device *dev, int startup) break; } default: - printk(KERN_DEBUG "%s: Invalid media table selection %d\n", - dev->name, mleaf->type); + netdev_dbg(dev, " Invalid media table selection %d\n", + mleaf->type); new_csr6 = 0x020E0000; } if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Using media type %s, CSR12 is %02x\n", - dev->name, medianame[dev->if_port], + netdev_dbg(dev, "Using media type %s, CSR12 is %02x\n", + medianame[dev->if_port], ioread32(ioaddr + CSR12) & 0xff); } else if (tp->chip_id == LC82C168) { if (startup && ! tp->medialock) dev->if_port = tp->mii_cnt ? 11 : 0; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC PHY status is %3.3x, media %s\n", - dev->name, ioread32(ioaddr + 0xB8), medianame[dev->if_port]); + netdev_dbg(dev, "PNIC PHY status is %3.3x, media %s\n", + ioread32(ioaddr + 0xB8), + medianame[dev->if_port]); if (tp->mii_cnt) { new_csr6 = 0x810C0000; iowrite32(0x0001, ioaddr + CSR15); @@ -388,9 +387,9 @@ void tulip_select_media(struct net_device *dev, int startup) } else new_csr6 = 0x03860000; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: No media description table, assuming %s transceiver, CSR12 %02x\n", - dev->name, medianame[dev->if_port], - ioread32(ioaddr + CSR12)); + netdev_dbg(dev, "No media description table, assuming %s transceiver, CSR12 %02x\n", + medianame[dev->if_port], + ioread32(ioaddr + CSR12)); } tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0); @@ -504,8 +503,8 @@ void __devinit tulip_find_mii (struct net_device *dev, int board_idx) /* Fixup for DLink with miswired PHY. */ if (mii_advert != to_advert) { - printk(KERN_DEBUG "tulip%d: Advertising %04x on PHY %d, previously advertising %04x\n", - board_idx, to_advert, phy, mii_advert); + pr_debug("tulip%d: Advertising %04x on PHY %d, previously advertising %04x\n", + board_idx, to_advert, phy, mii_advert); tulip_mdio_write (dev, phy, 4, to_advert); } diff --git a/drivers/net/tulip/pnic.c b/drivers/net/tulip/pnic.c index a63e64b6863d..aa4d9dad0395 100644 --- a/drivers/net/tulip/pnic.c +++ b/drivers/net/tulip/pnic.c @@ -40,8 +40,8 @@ void pnic_do_nway(struct net_device *dev) new_csr6 |= 0x00000200; } if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC autonegotiated status %08x, %s\n", - dev->name, phy_reg, medianame[dev->if_port]); + netdev_dbg(dev, "PNIC autonegotiated status %08x, %s\n", + phy_reg, medianame[dev->if_port]); if (tp->csr6 != new_csr6) { tp->csr6 = new_csr6; /* Restart Tx */ @@ -58,8 +58,8 @@ void pnic_lnk_change(struct net_device *dev, int csr5) int phy_reg = ioread32(ioaddr + 0xB8); if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC link changed state %08x, CSR5 %08x\n", - dev->name, phy_reg, csr5); + netdev_dbg(dev, "PNIC link changed state %08x, CSR5 %08x\n", + phy_reg, csr5); if (ioread32(ioaddr + CSR5) & TPLnkFail) { iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7); /* If we use an external MII, then we mustn't use the @@ -114,8 +114,8 @@ void pnic_timer(unsigned long data) int csr5 = ioread32(ioaddr + CSR5); if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC timer PHY status %08x, %s CSR5 %08x\n", - dev->name, phy_reg, medianame[dev->if_port], csr5); + netdev_dbg(dev, "PNIC timer PHY status %08x, %s CSR5 %08x\n", + phy_reg, medianame[dev->if_port], csr5); if (phy_reg & 0x04000000) { /* Remote link fault */ iowrite32(0x0201F078, ioaddr + 0xB8); next_tick = 1*HZ; @@ -125,11 +125,11 @@ void pnic_timer(unsigned long data) next_tick = 60*HZ; } else if (csr5 & TPLnkFail) { /* 100baseTx link beat */ if (tulip_debug > 1) - printk(KERN_DEBUG "%s: %s link beat failed, CSR12 %04x, CSR5 %08x, PHY %03x\n", - dev->name, medianame[dev->if_port], - csr12, - ioread32(ioaddr + CSR5), - ioread32(ioaddr + 0xB8)); + netdev_dbg(dev, "%s link beat failed, CSR12 %04x, CSR5 %08x, PHY %03x\n", + medianame[dev->if_port], + csr12, + ioread32(ioaddr + CSR5), + ioread32(ioaddr + 0xB8)); next_tick = 3*HZ; if (tp->medialock) { } else if (tp->nwayset && (dev->if_port & 1)) { diff --git a/drivers/net/tulip/pnic2.c b/drivers/net/tulip/pnic2.c index 4690c8e69207..93358ee4d830 100644 --- a/drivers/net/tulip/pnic2.c +++ b/drivers/net/tulip/pnic2.c @@ -125,8 +125,8 @@ void pnic2_start_nway(struct net_device *dev) csr14 |= 0x00001184; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Restarting PNIC2 autonegotiation, csr14=%08x\n", - dev->name, csr14); + netdev_dbg(dev, "Restarting PNIC2 autonegotiation, csr14=%08x\n", + csr14); /* tell pnic2_lnk_change we are doing an nway negotiation */ dev->if_port = 0; @@ -137,8 +137,7 @@ void pnic2_start_nway(struct net_device *dev) tp->csr6 = ioread32(ioaddr + CSR6); if (tulip_debug > 1) - printk(KERN_DEBUG "%s: On Entry to Nway, csr6=%08x\n", - dev->name, tp->csr6); + netdev_dbg(dev, "On Entry to Nway, csr6=%08x\n", tp->csr6); /* mask off any bits not to touch * comment at top of file explains mask value @@ -271,9 +270,10 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) iowrite32(1, ioaddr + CSR13); if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Setting CSR6 %08x/%x CSR12 %08x\n", - dev->name, tp->csr6, - ioread32(ioaddr + CSR6), ioread32(ioaddr + CSR12)); + netdev_dbg(dev, "Setting CSR6 %08x/%x CSR12 %08x\n", + tp->csr6, + ioread32(ioaddr + CSR6), + ioread32(ioaddr + CSR12)); /* now the following actually writes out the * new csr6 values @@ -324,7 +324,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) /* Link blew? Maybe restart NWay. */ if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Ugh! Link blew?\n", dev->name); + netdev_dbg(dev, "Ugh! Link blew?\n"); del_timer_sync(&tp->timer); pnic2_start_nway(dev); diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c index 36c2725ec886..2017faf2d0e6 100644 --- a/drivers/net/tulip/timer.c +++ b/drivers/net/tulip/timer.c @@ -28,11 +28,11 @@ void tulip_media_task(struct work_struct *work) unsigned long flags; if (tulip_debug > 2) { - printk(KERN_DEBUG "%s: Media selection tick, %s, status %08x mode %08x SIA %08x %08x %08x %08x\n", - dev->name, medianame[dev->if_port], - ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR6), - csr12, ioread32(ioaddr + CSR13), - ioread32(ioaddr + CSR14), ioread32(ioaddr + CSR15)); + netdev_dbg(dev, "Media selection tick, %s, status %08x mode %08x SIA %08x %08x %08x %08x\n", + medianame[dev->if_port], + ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR6), + csr12, ioread32(ioaddr + CSR13), + ioread32(ioaddr + CSR14), ioread32(ioaddr + CSR15)); } switch (tp->chip_id) { case DC21140: @@ -48,9 +48,9 @@ void tulip_media_task(struct work_struct *work) Assume this a generic MII or SYM transceiver. */ next_tick = 60*HZ; if (tulip_debug > 2) - printk(KERN_DEBUG "%s: network media monitor CSR6 %08x CSR12 0x%02x\n", - dev->name, - ioread32(ioaddr + CSR6), csr12 & 0xff); + netdev_dbg(dev, "network media monitor CSR6 %08x CSR12 0x%02x\n", + ioread32(ioaddr + CSR6), + csr12 & 0xff); break; } mleaf = &tp->mtable->mleaf[tp->cur_index]; @@ -62,8 +62,8 @@ void tulip_media_task(struct work_struct *work) s8 bitnum = p[offset]; if (p[offset+1] & 0x80) { if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Transceiver monitor tick CSR12=%#02x, no media sense\n", - dev->name, csr12); + netdev_dbg(dev, "Transceiver monitor tick CSR12=%#02x, no media sense\n", + csr12); if (mleaf->type == 4) { if (mleaf->media == 3 && (csr12 & 0x02)) goto select_next_media; @@ -71,17 +71,16 @@ void tulip_media_task(struct work_struct *work) break; } if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Transceiver monitor tick: CSR12=%#02x bit %d is %d, expecting %d\n", - dev->name, csr12, (bitnum >> 1) & 7, - (csr12 & (1 << ((bitnum >> 1) & 7))) != 0, - (bitnum >= 0)); + netdev_dbg(dev, "Transceiver monitor tick: CSR12=%#02x bit %d is %d, expecting %d\n", + csr12, (bitnum >> 1) & 7, + (csr12 & (1 << ((bitnum >> 1) & 7))) != 0, + (bitnum >= 0)); /* Check that the specified bit has the proper value. */ if ((bitnum < 0) != ((csr12 & (1 << ((bitnum >> 1) & 7))) != 0)) { if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Link beat detected for %s\n", - dev->name, - medianame[mleaf->media & MEDIA_MASK]); + netdev_dbg(dev, "Link beat detected for %s\n", + medianame[mleaf->media & MEDIA_MASK]); if ((p[2] & 0x61) == 0x01) /* Bogus Znyx board. */ goto actually_mii; netif_carrier_on(dev); @@ -99,10 +98,9 @@ void tulip_media_task(struct work_struct *work) if (tulip_media_cap[dev->if_port] & MediaIsFD) goto select_next_media; /* Skip FD entries. */ if (tulip_debug > 1) - printk(KERN_DEBUG "%s: No link beat on media %s, trying transceiver type %s\n", - dev->name, - medianame[mleaf->media & MEDIA_MASK], - medianame[tp->mtable->mleaf[tp->cur_index].media]); + netdev_dbg(dev, "No link beat on media %s, trying transceiver type %s\n", + medianame[mleaf->media & MEDIA_MASK], + medianame[tp->mtable->mleaf[tp->cur_index].media]); tulip_select_media(dev, 0); /* Restart the transmit process. */ tulip_restart_rxtx(tp); @@ -166,10 +164,9 @@ void comet_timer(unsigned long data) int next_tick = 60*HZ; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Comet link status %04x partner capability %04x\n", - dev->name, - tulip_mdio_read(dev, tp->phys[0], 1), - tulip_mdio_read(dev, tp->phys[0], 5)); + netdev_dbg(dev, "Comet link status %04x partner capability %04x\n", + tulip_mdio_read(dev, tp->phys[0], 1), + tulip_mdio_read(dev, tp->phys[0], 5)); /* mod_timer synchronizes us with potential add_timer calls * from interrupts. */ diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h index ed66a16711dc..9db528967da9 100644 --- a/drivers/net/tulip/tulip.h +++ b/drivers/net/tulip/tulip.h @@ -547,11 +547,9 @@ static inline void tulip_stop_rxtx(struct tulip_private *tp) udelay(10); if (!i) - printk(KERN_DEBUG "%s: tulip_stop_rxtx() failed" - " (CSR5 0x%x CSR6 0x%x)\n", - pci_name(tp->pdev), - ioread32(ioaddr + CSR5), - ioread32(ioaddr + CSR6)); + netdev_dbg(tp->dev, "tulip_stop_rxtx() failed (CSR5 0x%x CSR6 0x%x)\n", + ioread32(ioaddr + CSR5), + ioread32(ioaddr + CSR6)); } } diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index f46898a588d1..ebc805893205 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -330,8 +330,7 @@ static void tulip_up(struct net_device *dev) udelay(100); if (tulip_debug > 1) - printk(KERN_DEBUG "%s: tulip_up(), irq==%d\n", - dev->name, dev->irq); + netdev_dbg(dev, "tulip_up(), irq==%d\n", dev->irq); iowrite32(tp->rx_ring_dma, ioaddr + CSR3); iowrite32(tp->tx_ring_dma, ioaddr + CSR4); @@ -498,10 +497,10 @@ media_picked: iowrite32(0, ioaddr + CSR2); /* Rx poll demand */ if (tulip_debug > 2) { - printk(KERN_DEBUG "%s: Done tulip_up(), CSR0 %08x, CSR5 %08x CSR6 %08x\n", - dev->name, ioread32(ioaddr + CSR0), - ioread32(ioaddr + CSR5), - ioread32(ioaddr + CSR6)); + netdev_dbg(dev, "Done tulip_up(), CSR0 %08x, CSR5 %08x CSR6 %08x\n", + ioread32(ioaddr + CSR0), + ioread32(ioaddr + CSR5), + ioread32(ioaddr + CSR6)); } /* Set the timer to switch to check for link beat and perhaps switch @@ -842,8 +841,7 @@ static int tulip_close (struct net_device *dev) tulip_down (dev); if (tulip_debug > 1) - dev_printk(KERN_DEBUG, &dev->dev, - "Shutting down ethercard, status was %02x\n", + netdev_dbg(dev, "Shutting down ethercard, status was %02x\n", ioread32 (ioaddr + CSR5)); free_irq (dev->irq, dev); @@ -1206,7 +1204,7 @@ static void __devinit tulip_mwi_config (struct pci_dev *pdev, u32 csr0; if (tulip_debug > 3) - printk(KERN_DEBUG "%s: tulip_mwi_config()\n", pci_name(pdev)); + netdev_dbg(dev, "tulip_mwi_config()\n"); tp->csr0 = csr0 = 0; @@ -1268,8 +1266,8 @@ static void __devinit tulip_mwi_config (struct pci_dev *pdev, out: tp->csr0 = csr0; if (tulip_debug > 2) - printk(KERN_DEBUG "%s: MWI config cacheline=%d, csr0=%08x\n", - pci_name(pdev), cache, csr0); + netdev_dbg(dev, "MWI config cacheline=%d, csr0=%08x\n", + cache, csr0); } #endif diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 939c96e2438a..64e3f01e9980 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -645,8 +645,7 @@ static int netdev_open(struct net_device *dev) goto out_err; if (debug > 1) - printk(KERN_DEBUG "%s: w89c840_open() irq %d\n", - dev->name, dev->irq); + netdev_dbg(dev, "w89c840_open() irq %d\n", dev->irq); if((i=alloc_ringdesc(dev))) goto out_err; @@ -658,7 +657,7 @@ static int netdev_open(struct net_device *dev) netif_start_queue(dev); if (debug > 2) - printk(KERN_DEBUG "%s: Done netdev_open()\n", dev->name); + netdev_dbg(dev, "Done netdev_open()\n"); /* Set the timer to check for link beat. */ init_timer(&np->timer); @@ -787,9 +786,9 @@ static void netdev_timer(unsigned long data) void __iomem *ioaddr = np->base_addr; if (debug > 2) - printk(KERN_DEBUG "%s: Media selection timer tick, status %08x config %08x\n", - dev->name, ioread32(ioaddr + IntrStatus), - ioread32(ioaddr + NetworkConfig)); + netdev_dbg(dev, "Media selection timer tick, status %08x config %08x\n", + ioread32(ioaddr + IntrStatus), + ioread32(ioaddr + NetworkConfig)); spin_lock_irq(&np->lock); update_csr6(dev, update_link(dev)); spin_unlock_irq(&np->lock); @@ -1056,8 +1055,8 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) spin_unlock_irq(&np->lock); if (debug > 4) { - printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d\n", - dev->name, np->cur_tx, entry); + netdev_dbg(dev, "Transmit frame #%d queued in slot %d\n", + np->cur_tx, entry); } return NETDEV_TX_OK; } @@ -1074,8 +1073,8 @@ static void netdev_tx_done(struct net_device *dev) if (tx_status & 0x8000) { /* There was an error, log it. */ #ifndef final_version if (debug > 1) - printk(KERN_DEBUG "%s: Transmit error, Tx status %08x\n", - dev->name, tx_status); + netdev_dbg(dev, "Transmit error, Tx status %08x\n", + tx_status); #endif np->stats.tx_errors++; if (tx_status & 0x0104) np->stats.tx_aborted_errors++; @@ -1087,8 +1086,8 @@ static void netdev_tx_done(struct net_device *dev) } else { #ifndef final_version if (debug > 3) - printk(KERN_DEBUG "%s: Transmit slot %d ok, Tx status %08x\n", - dev->name, entry, tx_status); + netdev_dbg(dev, "Transmit slot %d ok, Tx status %08x\n", + entry, tx_status); #endif np->stats.tx_bytes += np->tx_skbuff[entry]->len; np->stats.collisions += (tx_status >> 3) & 15; @@ -1131,8 +1130,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) iowrite32(intr_status & 0x001ffff, ioaddr + IntrStatus); if (debug > 4) - printk(KERN_DEBUG "%s: Interrupt, status %04x\n", - dev->name, intr_status); + netdev_dbg(dev, "Interrupt, status %04x\n", intr_status); if ((intr_status & (NormalIntr|AbnormalIntr)) == 0) break; @@ -1173,8 +1171,8 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) } while (1); if (debug > 3) - printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x\n", - dev->name, ioread32(ioaddr + IntrStatus)); + netdev_dbg(dev, "exiting interrupt, status=%#4.4x\n", + ioread32(ioaddr + IntrStatus)); return IRQ_RETVAL(handled); } @@ -1187,8 +1185,8 @@ static int netdev_rx(struct net_device *dev) int work_limit = np->dirty_rx + RX_RING_SIZE - np->cur_rx; if (debug > 4) { - printk(KERN_DEBUG " In netdev_rx(), entry %d status %04x\n", - entry, np->rx_ring[entry].status); + netdev_dbg(dev, " In netdev_rx(), entry %d status %04x\n", + entry, np->rx_ring[entry].status); } /* If EOP is set on the next entry, it's a new packet. Send it up. */ @@ -1197,8 +1195,8 @@ static int netdev_rx(struct net_device *dev) s32 status = desc->status; if (debug > 4) - printk(KERN_DEBUG " netdev_rx() status was %08x\n", - status); + netdev_dbg(dev, " netdev_rx() status was %08x\n", + status); if (status < 0) break; if ((status & 0x38008300) != 0x0300) { @@ -1213,8 +1211,8 @@ static int netdev_rx(struct net_device *dev) } else if (status & 0x8000) { /* There was a fatal error. */ if (debug > 2) - printk(KERN_DEBUG "%s: Receive error, Rx status %08x\n", - dev->name, status); + netdev_dbg(dev, "Receive error, Rx status %08x\n", + status); np->stats.rx_errors++; /* end of a packet.*/ if (status & 0x0890) np->stats.rx_length_errors++; if (status & 0x004C) np->stats.rx_frame_errors++; @@ -1227,8 +1225,8 @@ static int netdev_rx(struct net_device *dev) #ifndef final_version if (debug > 4) - printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d status %x\n", - pkt_len, status); + netdev_dbg(dev, " netdev_rx() normal Rx pkt length %d status %x\n", + pkt_len, status); #endif /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ @@ -1253,10 +1251,10 @@ static int netdev_rx(struct net_device *dev) #ifndef final_version /* Remove after testing. */ /* You will want this info for the initial debug. */ if (debug > 5) - printk(KERN_DEBUG " Rx data %pM %pM %02x%02x %pI4\n", - &skb->data[0], &skb->data[6], - skb->data[12], skb->data[13], - &skb->data[14]); + netdev_dbg(dev, " Rx data %pM %pM %02x%02x %pI4\n", + &skb->data[0], &skb->data[6], + skb->data[12], skb->data[13], + &skb->data[14]); #endif skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); @@ -1294,8 +1292,7 @@ static void netdev_error(struct net_device *dev, int intr_status) void __iomem *ioaddr = np->base_addr; if (debug > 2) - printk(KERN_DEBUG "%s: Abnormal event, %08x\n", - dev->name, intr_status); + netdev_dbg(dev, "Abnormal event, %08x\n", intr_status); if (intr_status == 0xffffffff) return; spin_lock(&np->lock); @@ -1315,8 +1312,7 @@ static void netdev_error(struct net_device *dev, int intr_status) new = 127; /* load full packet before starting */ new = (np->csr6 & ~(0x7F << 14)) | (new<<14); #endif - printk(KERN_DEBUG "%s: Tx underflow, new csr6 %08x\n", - dev->name, new); + netdev_dbg(dev, "Tx underflow, new csr6 %08x\n", new); update_csr6(dev, new); } if (intr_status & RxDied) { /* Missed a Rx frame. */ @@ -1489,13 +1485,12 @@ static int netdev_close(struct net_device *dev) netif_stop_queue(dev); if (debug > 1) { - printk(KERN_DEBUG "%s: Shutting down ethercard, status was %08x Config %08x\n", - dev->name, ioread32(ioaddr + IntrStatus), - ioread32(ioaddr + NetworkConfig)); - printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d, Rx %d / %d\n", - dev->name, - np->cur_tx, np->dirty_tx, - np->cur_rx, np->dirty_rx); + netdev_dbg(dev, "Shutting down ethercard, status was %08x Config %08x\n", + ioread32(ioaddr + IntrStatus), + ioread32(ioaddr + NetworkConfig)); + netdev_dbg(dev, "Queue pointers were Tx %d / %d, Rx %d / %d\n", + np->cur_tx, np->dirty_tx, + np->cur_rx, np->dirty_rx); } /* Stop the chip's Tx and Rx processes. */ diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 7e8287260c2f..988b8eb24d37 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -333,7 +333,7 @@ static irqreturn_t xircom_interrupt(int irq, void *dev_instance) if (link_status_changed(card)) { int newlink; - printk(KERN_DEBUG "xircom_cb: Link status has changed\n"); + netdev_dbg(dev, "Link status has changed\n"); newlink = link_status(card); netdev_info(dev, "Link is %d mbit\n", newlink); if (newlink) -- cgit v1.2.3-58-ga151 From 1c3319fb69c29376fe23c1aa0cd7cb6df91c7883 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 9 May 2011 09:45:23 +0000 Subject: tulip: Use pr_ where appropriate Use the current logging styles. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/de2104x.c | 6 +++--- drivers/net/tulip/dmfe.c | 7 +++---- drivers/net/tulip/tulip_core.c | 5 +++-- drivers/net/tulip/uli526x.c | 23 ++++------------------- drivers/net/tulip/winbond-840.c | 2 +- 5 files changed, 14 insertions(+), 29 deletions(-) diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index e925c1ea04bb..e2f692351180 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -53,7 +53,7 @@ /* These identify the driver base version and may not be removed. */ static char version[] = -KERN_INFO DRV_NAME " PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; +"PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")"; MODULE_AUTHOR("Jeff Garzik "); MODULE_DESCRIPTION("Intel/Digital 21040/1 series PCI Ethernet driver"); @@ -1978,7 +1978,7 @@ static int __devinit de_init_one (struct pci_dev *pdev, #ifndef MODULE if (board_idx == 0) - printk("%s", version); + pr_info("%s\n", version); #endif /* allocate a new ethernet device structure, and fill in defaults */ @@ -2200,7 +2200,7 @@ static struct pci_driver de_driver = { static int __init de_init (void) { #ifdef MODULE - printk("%s", version); + pr_info("%s\n", version); #endif return pci_register_driver(&de_driver); } diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 96e8541a76e9..468512731966 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -295,8 +295,7 @@ enum dmfe_CR6_bits { /* Global variable declaration ----------------------------- */ static int __devinitdata printed_version; static const char version[] __devinitconst = - KERN_INFO DRV_NAME ": Davicom DM9xxx net driver, version " - DRV_VERSION " (" DRV_RELDATE ")\n"; + "Davicom DM9xxx net driver, version " DRV_VERSION " (" DRV_RELDATE ")"; static int dmfe_debug; static unsigned char dmfe_media_mode = DMFE_AUTO; @@ -381,7 +380,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, DMFE_DBUG(0, "dmfe_init_one()", 0); if (!printed_version++) - printk(version); + pr_info("%s\n", version); /* * SPARC on-board DM910x chips should be handled by the main @@ -2203,7 +2202,7 @@ static int __init dmfe_init_module(void) { int rc; - printk(version); + pr_info("%s\n", version); printed_version = 1; DMFE_DBUG(0, "init_module() ", debug); diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index ebc805893205..82f87647207e 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -1478,7 +1478,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, if (sig == 0x09811317) { tp->flags |= COMET_PM; tp->wolinfo.supported = WAKE_PHY | WAKE_MAGIC; - printk(KERN_INFO "tulip_init_one: Enabled WOL support for AN983B\n"); + pr_info("%s: Enabled WOL support for AN983B\n", + __func__); } } tp->pdev = pdev; @@ -1874,7 +1875,7 @@ save_state: tulip_set_wolopts(pdev, tp->wolinfo.wolopts); rc = pci_enable_wake(pdev, pstate, tp->wolinfo.wolopts); if (rc) - printk("tulip: pci_enable_wake failed (%d)\n", rc); + pr_err("pci_enable_wake failed (%d)\n", rc); } pci_set_power_state(pdev, pstate); diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 92c00ee55961..9e63f406f72d 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -209,8 +209,7 @@ enum uli526x_CR6_bits { /* Global variable declaration ----------------------------- */ static int __devinitdata printed_version; static const char version[] __devinitconst = - KERN_INFO DRV_NAME ": ULi M5261/M5263 net driver, version " - DRV_VERSION " (" DRV_RELDATE ")\n"; + "ULi M5261/M5263 net driver, version " DRV_VERSION " (" DRV_RELDATE ")"; static int uli526x_debug; static unsigned char uli526x_media_mode = ULI526X_AUTO; @@ -283,7 +282,7 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev, ULI526X_DBUG(0, "uli526x_init_one()", 0); if (!printed_version++) - printk(version); + pr_info("%s\n", version); /* Init network device */ dev = alloc_etherdev(sizeof(*db)); @@ -667,15 +666,6 @@ static int uli526x_stop(struct net_device *dev) /* free allocated rx buffer */ uli526x_free_rxbuffer(db); -#if 0 - /* show statistic counter */ - printk(DRV_NAME ": FU:%lx EC:%lx LC:%lx NC:%lx LOC:%lx TXJT:%lx RESET:%lx RCR8:%lx FAL:%lx TT:%lx\n", - db->tx_fifo_underrun, db->tx_excessive_collision, - db->tx_late_collision, db->tx_no_carrier, db->tx_loss_carrier, - db->tx_jabber_timeout, db->reset_count, db->reset_cr8, - db->reset_fatal, db->reset_TXtimeout); -#endif - return 0; } @@ -755,7 +745,6 @@ static void uli526x_free_tx_pkt(struct net_device *dev, txptr = db->tx_remove_ptr; while(db->tx_packet_cnt) { tdes0 = le32_to_cpu(txptr->tdes0); - /* printk(DRV_NAME ": tdes0=%x\n", tdes0); */ if (tdes0 & 0x80000000) break; @@ -765,7 +754,6 @@ static void uli526x_free_tx_pkt(struct net_device *dev, /* Transmit statistic counter */ if ( tdes0 != 0x7fffffff ) { - /* printk(DRV_NAME ": tdes0=%x\n", tdes0); */ dev->stats.collisions += (tdes0 >> 3) & 0xf; dev->stats.tx_bytes += le32_to_cpu(txptr->tdes1) & 0x7ff; if (tdes0 & TDES0_ERR_MASK) { @@ -838,7 +826,6 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info /* error summary bit check */ if (rdes0 & 0x8000) { /* This is a error packet */ - //printk(DRV_NAME ": rdes0: %lx\n", rdes0); dev->stats.rx_errors++; if (rdes0 & 1) dev->stats.rx_fifo_errors++; @@ -1046,8 +1033,7 @@ static void uli526x_timer(unsigned long data) if ( time_after(jiffies, dev_trans_start(dev) + ULI526X_TX_TIMEOUT) ) { db->reset_TXtimeout++; db->wait_reset = 1; - printk( "%s: Tx timeout - resetting\n", - dev->name); + netdev_err(dev, " Tx timeout - resetting\n"); } } @@ -1534,7 +1520,6 @@ static u8 uli526x_sense_speed(struct uli526x_board_info * db) else phy_mode = 0x1000; - /* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */ switch (phy_mode) { case 0x1000: db->op_mode = ULI526X_10MHF; break; case 0x2000: db->op_mode = ULI526X_10MFD; break; @@ -1823,7 +1808,7 @@ MODULE_PARM_DESC(mode, "ULi M5261/M5263: Bit 0: 10/100Mbps, bit 2: duplex, bit 8 static int __init uli526x_init_module(void) { - printk(version); + pr_info("%s\n", version); printed_version = 1; ULI526X_DBUG(0, "init_module() ", debug); diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 64e3f01e9980..862eadf07191 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -141,7 +141,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; /* These identify the driver base version and may not be removed. */ static const char version[] __initconst = - KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " + "v" DRV_VERSION " (2.4 port) " DRV_RELDATE " Donald Becker \n" " http://www.scyld.com/network/drivers.html\n"; -- cgit v1.2.3-58-ga151 From 97fbdc1f77e9ce50ed0be543273d78f8de8675ac Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 5 Apr 2011 16:59:16 +0200 Subject: tipc: Drop __TIME__ usage The kernel already prints its build timestamp during boot, no need to repeat it in random drivers and produce different object files each time. Signed-off-by: Michal Marek Cc: Jon Maloy Cc: netdev@vger.kernel.org Cc: tipc-discussion@lists.sourceforge.net Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/tipc/core.c b/net/tipc/core.c index c9a73e7763f6..943b6af84265 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -179,8 +179,7 @@ static int __init tipc_init(void) if (tipc_log_resize(CONFIG_TIPC_LOG) != 0) warn("Unable to create log buffer\n"); - info("Activated (version " TIPC_MOD_VER - " compiled " __DATE__ " " __TIME__ ")\n"); + info("Activated (version " TIPC_MOD_VER ")\n"); tipc_own_addr = 0; tipc_remote_management = 1; -- cgit v1.2.3-58-ga151 From 6572e91d5fa61bb3f879a00b96d763c566ced6cb Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 25 Apr 2011 15:56:16 +0530 Subject: wireless: Fix warnings due to -Wunused-but-set-variable These warnings are exposed by gcc 4.6. net/wireless/reg.c: In function 'freq_reg_info_regd': net/wireless/reg.c:675:38: warning: variable 'pr' set but not used [-Wunused-but-set-variable] net/wireless/lib80211_crypt_wep.c: In function 'lib80211_wep_build_iv': net/wireless/lib80211_crypt_wep.c:99:12: warning: variable 'len' set but not used [-Wunused-but-set-variable] Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- net/wireless/lib80211_crypt_wep.c | 3 +-- net/wireless/reg.c | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/net/wireless/lib80211_crypt_wep.c b/net/wireless/lib80211_crypt_wep.c index e2e88878ba35..2f265e033ae2 100644 --- a/net/wireless/lib80211_crypt_wep.c +++ b/net/wireless/lib80211_crypt_wep.c @@ -96,13 +96,12 @@ static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len, u8 *key, int keylen, void *priv) { struct lib80211_wep_data *wep = priv; - u32 klen, len; + u32 klen; u8 *pos; if (skb_headroom(skb) < 4 || skb->len < hdr_len) return -1; - len = skb->len - hdr_len; pos = skb_push(skb, 4); memmove(pos, pos + 4, hdr_len); pos += hdr_len; diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 8982053f9961..798cb4cd0702 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -672,11 +672,9 @@ static int freq_reg_info_regd(struct wiphy *wiphy, for (i = 0; i < regd->n_reg_rules; i++) { const struct ieee80211_reg_rule *rr; const struct ieee80211_freq_range *fr = NULL; - const struct ieee80211_power_rule *pr = NULL; rr = ®d->reg_rules[i]; fr = &rr->freq_range; - pr = &rr->power_rule; /* * We only need to know if one frequency rule was -- cgit v1.2.3-58-ga151 From 3782cf4a04c272bdaa8476463b1d0208edbc505d Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 30 Apr 2011 08:38:16 -0700 Subject: iwlagn: led stay solid on when no traffic commit 5ed540aecc2aae92d5c97b9a9306a5bf88ad5574 change the led behavior for iwlwifi driver; the side effect cause led blink all the time. Modify the led blink table to fix this problem Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-led.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index d798c2a152d3..439187f903c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -48,8 +48,21 @@ module_param(led_mode, int, S_IRUGO); MODULE_PARM_DESC(led_mode, "0=system default, " "1=On(RF On)/Off(RF Off), 2=blinking"); +/* Throughput OFF time(ms) ON time (ms) + * >300 25 25 + * >200 to 300 40 40 + * >100 to 200 55 55 + * >70 to 100 65 65 + * >50 to 70 75 75 + * >20 to 50 85 85 + * >10 to 20 95 95 + * >5 to 10 110 110 + * >1 to 5 130 130 + * >0 to 1 167 167 + * <=0 SOLID ON + */ static const struct ieee80211_tpt_blink iwl_blink[] = { - { .throughput = 0 * 1024 - 1, .blink_time = 334 }, + { .throughput = 0, .blink_time = 334 }, { .throughput = 1 * 1024 - 1, .blink_time = 260 }, { .throughput = 5 * 1024 - 1, .blink_time = 220 }, { .throughput = 10 * 1024 - 1, .blink_time = 190 }, @@ -125,6 +138,11 @@ static int iwl_led_cmd(struct iwl_priv *priv, if (priv->blink_on == on && priv->blink_off == off) return 0; + if (off == 0) { + /* led is SOLID_ON */ + on = IWL_LED_SOLID; + } + IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n", priv->cfg->base_params->led_compensation); led_cmd.on = iwl_blink_compensation(priv, on, -- cgit v1.2.3-58-ga151 From 38bb3e9da62f6ebf1c6940d5482f0d6f431dac1c Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 5 May 2011 18:48:47 -0500 Subject: mac80211: Fix build error when CONFIG_PM is not defined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When mac80211 is built without CONFIG_PM being defined, the following errors are output: net/mac80211/main.c: In function ‘ieee80211_register_hw’: net/mac80211/main.c:700: error: ‘const struct ieee80211_ops’ has no member named ‘suspend’ net/mac80211/main.c:700: error: ‘const struct ieee80211_ops’ has no member named ‘resume’ make[2]: *** [net/mac80211/main.o] Error 1 make[1]: *** [net/mac80211] Error 2 make[1]: *** Waiting for unfinished jobs.... make: *** [net] Error 2 Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- net/mac80211/main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index cb326d36be9c..ab1f464817af 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -696,8 +696,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) WLAN_CIPHER_SUITE_AES_CMAC }; - if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) && - (!local->ops->suspend || !local->ops->resume)) + if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) +#ifdef CONFIG_PM + && (!local->ops->suspend || !local->ops->resume) +#endif + ) return -EINVAL; if (hw->max_report_rates == 0) -- cgit v1.2.3-58-ga151 From deb751880af6f2dce6cdc232a7b023f2b58cd815 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 6 May 2011 18:27:46 +0530 Subject: ath9k: avoid enabling interrupts while processing rx The assumsion is that while processing ath9k tasklet, interrupts were already disabled and it will be enabled at the completion of ath9k tasklet. But whenever TSFOOR is raised, the driver configures the beacon timers after having received a beacon frame from the AP which inturn enables the interrupts. Cc: stable@kernel.org Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/beacon.c | 15 +++++++++++++-- drivers/net/wireless/ath/ath9k/main.c | 3 ++- drivers/net/wireless/ath/ath9k/recv.c | 1 + 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 1bffd156b155..f2f672bc5966 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -564,6 +564,7 @@ struct ath_ant_comb { #define PS_WAIT_FOR_PSPOLL_DATA BIT(2) #define PS_WAIT_FOR_TX_ACK BIT(3) #define PS_BEACON_SYNC BIT(4) +#define PS_TSFOOR_SYNC BIT(5) struct ath_rate_table; diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 22cd241a098b..637dbc5f7b67 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -620,7 +620,13 @@ static void ath_beacon_config_sta(struct ath_softc *sc, ath9k_hw_disable_interrupts(ah); ath9k_hw_set_sta_beacon_timers(ah, &bs); ah->imask |= ATH9K_INT_BMISS; - ath9k_hw_set_interrupts(ah, ah->imask); + + /* + * If the beacon config is called beacause of TSFOOR, + * Interrupts will be enabled back at the end of ath9k_tasklet + */ + if (!(sc->ps_flags & PS_TSFOOR_SYNC)) + ath9k_hw_set_interrupts(ah, ah->imask); } static void ath_beacon_config_adhoc(struct ath_softc *sc, @@ -661,7 +667,12 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, ath9k_hw_disable_interrupts(ah); ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; - ath9k_hw_set_interrupts(ah, ah->imask); + /* + * If the beacon config is called beacause of TSFOOR, + * Interrupts will be enabled back at the end of ath9k_tasklet + */ + if (!(sc->ps_flags & PS_TSFOOR_SYNC)) + ath9k_hw_set_interrupts(ah, ah->imask); } static bool ath9k_allow_beacon_config(struct ath_softc *sc, diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3de115df9164..c171d111ecf7 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -718,7 +718,8 @@ void ath9k_tasklet(unsigned long data) */ ath_dbg(common, ATH_DBG_PS, "TSFOOR - Sync with next Beacon\n"); - sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC; + sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC | + PS_TSFOOR_SYNC; } if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index c5b7cbe59bfa..a485c040bf80 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -572,6 +572,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) ath_dbg(common, ATH_DBG_PS, "Reconfigure Beacon timers based on timestamp from the AP\n"); ath_set_beacon(sc); + sc->ps_flags &= ~PS_TSFOOR_SYNC; } if (ath_beacon_dtim_pending_cab(skb)) { -- cgit v1.2.3-58-ga151 From 4105f8075051b62816830c95de1ec17ceb364d09 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 6 May 2011 18:27:47 +0530 Subject: ath9k: process TSF out of range before RX Processing TSF out of range before RX helps to update beacon timers so early in the succeeding rx process. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c171d111ecf7..11d9eca8fb6e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -689,6 +689,17 @@ void ath9k_tasklet(unsigned long data) !ath9k_hw_check_alive(ah)) ieee80211_queue_work(sc->hw, &sc->hw_check_work); + if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { + /* + * TSF sync does not look correct; remain awake to sync with + * the next Beacon. + */ + ath_dbg(common, ATH_DBG_PS, + "TSFOOR - Sync with next Beacon\n"); + sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC | + PS_TSFOOR_SYNC; + } + if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL | ATH9K_INT_RXORN); @@ -711,17 +722,6 @@ void ath9k_tasklet(unsigned long data) ath_tx_tasklet(sc); } - if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { - /* - * TSF sync does not look correct; remain awake to sync with - * the next Beacon. - */ - ath_dbg(common, ATH_DBG_PS, - "TSFOOR - Sync with next Beacon\n"); - sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC | - PS_TSFOOR_SYNC; - } - if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) if (status & ATH9K_INT_GENTIMER) ath_gen_timer_isr(sc->sc_ah); -- cgit v1.2.3-58-ga151 From 054ec924944912413e4ee927b8cf02f476d08783 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 6 May 2011 11:11:20 -0700 Subject: iwlagn: fix iwl_is_any_associated The function iwl_is_any_associated() was intended to check both contexts, but due to an oversight it only checks the BSS context. This leads to a problem with scanning since the passive dwell time isn't restricted appropriately and a scan that includes passive channels will never finish if only the PAN context is associated since the default dwell time of 120ms won't fit into the normal 100 TU DTIM interval. Fix the function by using for_each_context() and also reorganise the other functions a bit to take advantage of each other making the code easier to read. Cc: stable@kernel.org Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2fd752a9aac8..214e4658c495 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1558,21 +1558,24 @@ iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++) \ if (priv->valid_contexts & BIT(ctx->ctxid)) -static inline int iwl_is_associated(struct iwl_priv *priv, - enum iwl_rxon_context_id ctxid) +static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx) { - return (priv->contexts[ctxid].active.filter_flags & - RXON_FILTER_ASSOC_MSK) ? 1 : 0; + return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; } -static inline int iwl_is_any_associated(struct iwl_priv *priv) +static inline int iwl_is_associated(struct iwl_priv *priv, + enum iwl_rxon_context_id ctxid) { - return iwl_is_associated(priv, IWL_RXON_CTX_BSS); + return iwl_is_associated_ctx(&priv->contexts[ctxid]); } -static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx) +static inline int iwl_is_any_associated(struct iwl_priv *priv) { - return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; + struct iwl_rxon_context *ctx; + for_each_context(priv, ctx) + if (iwl_is_associated_ctx(ctx)) + return true; + return false; } static inline int is_channel_valid(const struct iwl_channel_info *ch_info) -- cgit v1.2.3-58-ga151 From c84aa5af996a306c8ce66aac2cc4d5f4a74e27ca Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 6 May 2011 13:56:18 -0500 Subject: rtlwifi: Move 2 large arrays off stack In driver rtlwifi, efuse_read() places two relatively large arrays on the stack - a 1D u8 array of size 128, and a 2D array of u16 with 128 * 4 elements. With driver rtl8192de, the sizes will be 256 and 256 * 4 respectively. As that will make the 2D array be 2048 bytes, I have changed the code to use kmalloc to allocate the space. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/efuse.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index 510d42edb8ca..50de6f5d8a56 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c @@ -235,7 +235,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 efuse_tbl[HWSET_MAX_SIZE]; + u8 *efuse_tbl; u8 rtemp8[1]; u16 efuse_addr = 0; u8 offset, wren; @@ -245,7 +245,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) rtlpriv->cfg->maps[EFUSE_MAX_SECTION_MAP]; const u32 efuse_len = rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; - u16 efuse_word[EFUSE_MAX_SECTION][EFUSE_MAX_WORD_UNIT]; + u16 **efuse_word; u16 efuse_utilized = 0; u8 efuse_usage; @@ -256,9 +256,24 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) return; } + /* allocate memory for efuse_tbl and efuse_word */ + efuse_tbl = kmalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE] * + sizeof(u8), GFP_ATOMIC); + if (!efuse_tbl) + return; + efuse_word = kmalloc(EFUSE_MAX_WORD_UNIT * sizeof(u16 *), GFP_ATOMIC); + if (!efuse_word) + goto done; + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { + efuse_word[i] = kmalloc(efuse_max_section * sizeof(u16), + GFP_ATOMIC); + if (!efuse_word[i]) + goto done; + } + for (i = 0; i < efuse_max_section; i++) for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) - efuse_word[i][j] = 0xFFFF; + efuse_word[j][i] = 0xFFFF; read_efuse_byte(hw, efuse_addr, rtemp8); if (*rtemp8 != 0xFF) { @@ -285,7 +300,8 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) read_efuse_byte(hw, efuse_addr, rtemp8); efuse_addr++; efuse_utilized++; - efuse_word[offset][i] = (*rtemp8 & 0xff); + efuse_word[i][offset] = + (*rtemp8 & 0xff); if (efuse_addr >= efuse_len) break; @@ -297,7 +313,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) read_efuse_byte(hw, efuse_addr, rtemp8); efuse_addr++; efuse_utilized++; - efuse_word[offset][i] |= + efuse_word[i][offset] |= (((u16)*rtemp8 << 8) & 0xff00); if (efuse_addr >= efuse_len) @@ -320,9 +336,9 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) for (i = 0; i < efuse_max_section; i++) { for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { efuse_tbl[(i * 8) + (j * 2)] = - (efuse_word[i][j] & 0xff); + (efuse_word[j][i] & 0xff); efuse_tbl[(i * 8) + ((j * 2) + 1)] = - ((efuse_word[i][j] >> 8) & 0xff); + ((efuse_word[j][i] >> 8) & 0xff); } } @@ -336,6 +352,11 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) (u8 *)&efuse_utilized); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_USAGE, (u8 *)&efuse_usage); +done: + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) + kfree(efuse_word[i]); + kfree(efuse_word); + kfree(efuse_tbl); } bool efuse_shadow_update_chk(struct ieee80211_hw *hw) -- cgit v1.2.3-58-ga151 From fc7707a469785fe786ddc66d723c150226ddc40e Mon Sep 17 00:00:00 2001 From: Chaoming Li Date: Fri, 6 May 2011 15:32:02 -0500 Subject: rtlwifi: rtl8192se: Remove need to disable ASPM When this driver was initially submitted, the system would crash unless ASPM was disabled. This problem has been fixed. This patch also adds a printk that outputs the name of the firmware file that is used. Signed-off-by: Chaoming_Li Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 1 + drivers/net/wireless/rtlwifi/rtl8192se/sw.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 3550c9fb96e5..a40952845436 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1611,6 +1611,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, u16 irqline; u8 tmp; + pcipriv->ndis_adapter.pcibridge_vendor = PCI_BRIDGE_VENDOR_UNKNOWN; venderid = pdev->vendor; deviceid = pdev->device; pci_read_config_byte(pdev, 0x8, &revisionid); diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index 7cfd6a2cb140..1c6cb1d7d660 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c @@ -58,7 +58,7 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) * 4 - Always Enable ASPM without Clock Req. * set defult to RTL8192CE:3 RTL8192E:2 * */ - rtlpci->const_pci_aspm = 0; /* changed from 2 due to crashes */ + rtlpci->const_pci_aspm = 2; /*Setting for PCI-E device */ rtlpci->const_devicepci_aspm_setting = 0x03; @@ -183,6 +183,8 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) return 1; } + printk(KERN_INFO "rtl8192se: Driver for Realtek RTL8192SE/RTL8191SE\n" + " Loading firmware %s\n", rtlpriv->cfg->fw_name); /* request fw */ err = request_firmware(&firmware, rtlpriv->cfg->fw_name, rtlpriv->io.dev); -- cgit v1.2.3-58-ga151 From 6490e334bc3af960965adfcef5acf6e5cbdd925c Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 7 May 2011 11:13:37 +0200 Subject: carl9170: fix -Wunused-but-set-variable warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tx.c: In function ‘carl9170_tx_accounting_free’: tx.c:159:28: warning: variable ‘txinfo’ set but not used tx.c: In function ‘carl9170_tx_status_process_ampdu’: tx.c:383:27: warning: variable ‘ar_info’ set but not used tx.c: In function ‘__carl9170_tx_process_status’: tx.c:626:27: warning: variable ‘arinfo’ set but not used tx.c: In function ‘carl9170_tx_ampdu_queue’: tx.c:1324:15: warning: variable ‘max’ set but not used Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/carl9170/tx.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index bf2eff9dd582..e94084fcf6f5 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c @@ -156,10 +156,8 @@ out_rcu: static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb) { - struct ieee80211_tx_info *txinfo; int queue; - txinfo = IEEE80211_SKB_CB(skb); queue = skb_get_queue_mapping(skb); spin_lock_bh(&ar->tx_stats_lock); @@ -380,7 +378,6 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, { struct _carl9170_tx_superframe *super = (void *) skb->data; struct ieee80211_hdr *hdr = (void *) super->frame_data; - struct carl9170_tx_info *ar_info; struct ieee80211_sta *sta; struct carl9170_sta_info *sta_info; struct carl9170_sta_tid *tid_info; @@ -391,8 +388,6 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) return; - ar_info = (void *) txinfo->rate_driver_data; - rcu_read_lock(); sta = __carl9170_get_tx_sta(ar, skb); if (unlikely(!sta)) @@ -623,7 +618,6 @@ static void __carl9170_tx_process_status(struct ar9170 *ar, { struct sk_buff *skb; struct ieee80211_tx_info *txinfo; - struct carl9170_tx_info *arinfo; unsigned int r, t, q; bool success = true; @@ -639,7 +633,6 @@ static void __carl9170_tx_process_status(struct ar9170 *ar, } txinfo = IEEE80211_SKB_CB(skb); - arinfo = (void *) txinfo->rate_driver_data; if (!(info & CARL9170_TX_STATUS_SUCCESS)) success = false; @@ -1321,7 +1314,6 @@ static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, struct carl9170_sta_info *sta_info; struct carl9170_sta_tid *agg; struct sk_buff *iter; - unsigned int max; u16 tid, seq, qseq, off; bool run = false; @@ -1331,7 +1323,6 @@ static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, rcu_read_lock(); agg = rcu_dereference(sta_info->agg[tid]); - max = sta_info->ampdu_max_len; if (!agg) goto err_unlock_rcu; -- cgit v1.2.3-58-ga151 From 1816fcdcbbe9ff42ba1a9dac5198d18efb9d95e9 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 7 May 2011 11:16:08 +0200 Subject: p54pci: fix -Wunused-but-set-variable warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit p54pci.c: In function ‘p54p_tx’: p54pci.c:334:6: warning: variable ‘device_idx’ set but not used Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 0494d7b102d4..1b753173680f 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -331,10 +331,9 @@ static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb) struct p54p_ring_control *ring_control = priv->ring_control; struct p54p_desc *desc; dma_addr_t mapping; - u32 device_idx, idx, i; + u32 idx, i; spin_lock_irqsave(&priv->lock, flags); - device_idx = le32_to_cpu(ring_control->device_idx[1]); idx = le32_to_cpu(ring_control->host_idx[1]); i = idx % ARRAY_SIZE(ring_control->tx_data); -- cgit v1.2.3-58-ga151 From 9a24af1136e6d08c73010205caa282f46223aed5 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 7 May 2011 17:27:46 +0200 Subject: rt2x00: Fix rmmod hang of rt2800pci txstatus_timer should only be deleted for USB devices, as it is only initialized for USB devices. Reported-by: Andreas Hartmann Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 2eb5196977fd..c018d67aab8e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1159,9 +1159,9 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) /* * Stop all work. */ - del_timer_sync(&rt2x00dev->txstatus_timer); cancel_work_sync(&rt2x00dev->intf_work); if (rt2x00_is_usb(rt2x00dev)) { + del_timer_sync(&rt2x00dev->txstatus_timer); cancel_work_sync(&rt2x00dev->rxdone_work); cancel_work_sync(&rt2x00dev->txdone_work); } -- cgit v1.2.3-58-ga151 From 25ea0dd9ffb7459f3b2948430f75d99b46ca1870 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 8 May 2011 20:30:32 +0200 Subject: b43: drop ssb-duplicated workaround for dangling cores MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the code to detect inactive 802.11 cores, as that function is now done in ssb. Signed-off-by: Rafał Miłecki Tested-by: Larry Finger Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 675e288a3c53..70838e825341 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4836,25 +4836,8 @@ static void b43_one_core_detach(struct ssb_device *dev) static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) { struct b43_wldev *wldev; - struct pci_dev *pdev; int err = -ENOMEM; - if (!list_empty(&wl->devlist)) { - /* We are not the first core on this chip. */ - pdev = (dev->bus->bustype == SSB_BUSTYPE_PCI) ? dev->bus->host_pci : NULL; - /* Only special chips support more than one wireless - * core, although some of the other chips have more than - * one wireless core as well. Check for this and - * bail out early. - */ - if (!pdev || - ((pdev->device != 0x4321) && - (pdev->device != 0x4313) && (pdev->device != 0x431A))) { - b43dbg(wl, "Ignoring unconnected 802.11 core\n"); - return -ENODEV; - } - } - wldev = kzalloc(sizeof(*wldev), GFP_KERNEL); if (!wldev) goto out; -- cgit v1.2.3-58-ga151 From 3ed3f49473985718ce51f84d990ed5b8b6472598 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 8 May 2011 20:30:33 +0200 Subject: b43legacy: drop ssb-duplicated workaround for dangling cores MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the code to detect inactive 802.11 cores, as that function is now done in ssb. Signed-off-by: Rafał Miłecki Tested-by: Larry Finger Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/main.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 2162663293c0..f6d54463b24f 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3696,26 +3696,8 @@ static int b43legacy_one_core_attach(struct ssb_device *dev, struct b43legacy_wl *wl) { struct b43legacy_wldev *wldev; - struct pci_dev *pdev; int err = -ENOMEM; - if (!list_empty(&wl->devlist)) { - /* We are not the first core on this chip. */ - pdev = (dev->bus->bustype == SSB_BUSTYPE_PCI) ? dev->bus->host_pci : NULL; - /* Only special chips support more than one wireless - * core, although some of the other chips have more than - * one wireless core as well. Check for this and - * bail out early. - */ - if (!pdev || - ((pdev->device != 0x4321) && - (pdev->device != 0x4313) && - (pdev->device != 0x431A))) { - b43legacydbg(wl, "Ignoring unconnected 802.11 core\n"); - return -ENODEV; - } - } - wldev = kzalloc(sizeof(*wldev), GFP_KERNEL); if (!wldev) goto out; -- cgit v1.2.3-58-ga151 From b53575ecf939a4f752de87eabf1adbcfa4478a6c Mon Sep 17 00:00:00 2001 From: Christoph Fritz Date: Sun, 8 May 2011 22:50:09 +0200 Subject: mwifiex: fix null derefs, mem leaks and trivia This patch: - adds kfree() where necessary - prevents potential null dereferences - makes use of kfree_skb() - replaces -1 for failed kzallocs with -ENOMEM Signed-off-by: Christoph Fritz Reviewed-by: Kiran Divekar Tested-by: Amitkumar Karwar Acked-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n_aggr.c | 6 ++++-- drivers/net/wireless/mwifiex/cfg80211.c | 5 ++++- drivers/net/wireless/mwifiex/cmdevt.c | 2 +- drivers/net/wireless/mwifiex/init.c | 4 ++-- drivers/net/wireless/mwifiex/main.c | 8 ++++---- drivers/net/wireless/mwifiex/scan.c | 8 ++++---- drivers/net/wireless/mwifiex/sdio.c | 5 +++-- drivers/net/wireless/mwifiex/sta_ioctl.c | 2 +- 8 files changed, 23 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 12cf4246f96b..2b2cca5e6d0f 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -318,7 +318,8 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, else skb_src = NULL; - pra_list->total_pkts_size -= skb_src->len; + if (skb_src) + pra_list->total_pkts_size -= skb_src->len; spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); @@ -373,7 +374,8 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, (adapter->pps_uapsd_mode) && (adapter->tx_lock_flag)) { priv->adapter->tx_lock_flag = false; - ptx_pd->flags = 0; + if (ptx_pd) + ptx_pd->flags = 0; } skb_queue_tail(&pra_list->skb_head, skb_aggr); diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 0c0116374d7d..19be8870c683 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1255,8 +1255,10 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, wdev->wiphy = wiphy_new(&mwifiex_cfg80211_ops, sizeof(struct mwifiex_private *)); - if (!wdev->wiphy) + if (!wdev->wiphy) { + kfree(wdev); return -ENOMEM; + } wdev->iftype = NL80211_IFTYPE_STATION; wdev->wiphy->max_scan_ssids = 10; wdev->wiphy->interface_modes = @@ -1296,6 +1298,7 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", __func__); wiphy_free(wdev->wiphy); + kfree(wdev); return ret; } else { dev_dbg(priv->adapter->dev, diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index b75cc9271a19..1c8b4f7cba47 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -292,7 +292,7 @@ int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter) if (!cmd_array) { dev_err(adapter->dev, "%s: failed to alloc cmd_array\n", __func__); - return -1; + return -ENOMEM; } adapter->cmd_pool = cmd_array; diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 27ad72b291b7..6a8fd9989a23 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -41,7 +41,7 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) if (!bss_prio) { dev_err(adapter->dev, "%s: failed to alloc bss_prio\n", __func__); - return -1; + return -ENOMEM; } bss_prio->priv = priv; @@ -161,7 +161,7 @@ static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) if (!temp_scan_table) { dev_err(adapter->dev, "%s: failed to alloc temp_scan_table\n", __func__); - return -1; + return -ENOMEM; } adapter->scan_table = temp_scan_table; diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 38f912b8fcec..44957cac61e1 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -69,7 +69,7 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL); if (!adapter) - return -1; + return -ENOMEM; g_adapter = adapter; adapter->card = card; @@ -516,13 +516,13 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) jiffies, priv->bss_index); if (priv->adapter->surprise_removed) { - kfree(skb); + kfree_skb(skb); priv->stats.tx_dropped++; return 0; } if (!skb->len || (skb->len > ETH_FRAME_LEN)) { dev_err(priv->adapter->dev, "Tx: bad skb len %d\n", skb->len); - kfree(skb); + kfree_skb(skb); priv->stats.tx_dropped++; return 0; } @@ -535,7 +535,7 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN); if (unlikely(!new_skb)) { dev_err(priv->adapter->dev, "Tx: cannot alloca new_skb\n"); - kfree(skb); + kfree_skb(skb); priv->stats.tx_dropped++; return 0; } diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 4968974f3427..5c22860fb40a 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -2283,7 +2283,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, GFP_KERNEL); if (!scan_cfg_out) { dev_err(adapter->dev, "failed to alloc scan_cfg_out\n"); - return -1; + return -ENOMEM; } buf_size = sizeof(struct mwifiex_chan_scan_param_set) * @@ -2292,7 +2292,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, if (!scan_chan_list) { dev_err(adapter->dev, "failed to alloc scan_chan_list\n"); kfree(scan_cfg_out); - return -1; + return -ENOMEM; } keep_previous_scan = false; @@ -2491,7 +2491,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, GFP_KERNEL); if (!bss_new_entry) { dev_err(adapter->dev, " failed to alloc bss_new_entry\n"); - return -1; + return -ENOMEM; } for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { @@ -2881,7 +2881,7 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); if (!scan_cfg) { dev_err(adapter->dev, "failed to alloc scan_cfg\n"); - return -1; + return -ENOMEM; } memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid, diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 470dbaaeaa02..d425dbd91d19 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -68,6 +68,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) if (ret) { pr_err("%s: failed to enable function\n", __func__); + kfree(card); return -EIO; } @@ -676,7 +677,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, if (!fwbuf) { dev_err(adapter->dev, "unable to alloc buffer for firmware." " Terminating download\n"); - return -1; + return -ENOMEM; } /* Perform firmware data transfer */ @@ -1605,7 +1606,7 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) card->mp_regs = kzalloc(MAX_MP_REGS, GFP_KERNEL); if (!card->mp_regs) { dev_err(adapter->dev, "failed to alloc mp_regs\n"); - return -1; + return -ENOMEM; } ret = mwifiex_alloc_sdio_mpa_buffers(adapter, diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 4585c1bb9fa9..75bca56449cb 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -895,7 +895,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, if (!buf) { dev_err(priv->adapter->dev, "%s: failed to alloc cmd buffer\n", __func__); - return -1; + return -ENOMEM; } txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf; -- cgit v1.2.3-58-ga151 From 5ee9c6afcb72eb41c3607e424c3b969f8c56031b Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 9 May 2011 00:21:18 +0200 Subject: b43: trivial: include ssb word in ssb specific functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This can be helpful when we decide to add support for other buses. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 70838e825341..f7582c096f8d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4958,7 +4958,7 @@ out: return err; } -static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id) +static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id) { struct b43_wl *wl; int err; @@ -4996,7 +4996,7 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id) return err; } -static void b43_remove(struct ssb_device *dev) +static void b43_ssb_remove(struct ssb_device *dev) { struct b43_wl *wl = ssb_get_devtypedata(dev); struct b43_wldev *wldev = ssb_get_drvdata(dev); @@ -5039,8 +5039,8 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason) static struct ssb_driver b43_ssb_driver = { .name = KBUILD_MODNAME, .id_table = b43_ssb_tbl, - .probe = b43_probe, - .remove = b43_remove, + .probe = b43_ssb_probe, + .remove = b43_ssb_remove, }; static void b43_print_driverinfo(void) -- cgit v1.2.3-58-ga151 From 8c12c7b0efce09b87e67d05332bdcb86ea83f65a Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Mon, 9 May 2011 10:29:01 +0530 Subject: ath9k_hw: remove get_channel_noise function currently ath9k_hw_getchan_noise is not used anywhere Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 8 -------- drivers/net/wireless/ath/ath9k/calib.h | 1 - 2 files changed, 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index fe3c10e6b276..558b228a717f 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -409,14 +409,6 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, } } -s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) -{ - if (!ah->curchan || !ah->curchan->noisefloor) - return ath9k_hw_get_default_nf(ah, chan); - - return ah->curchan->noisefloor; -} -EXPORT_SYMBOL(ath9k_hw_getchan_noise); void ath9k_hw_bstuck_nfcal(struct ath_hw *ah) { diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index b8973eb8d858..4420780fa3b8 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -106,7 +106,6 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, struct ath9k_channel *chan); void ath9k_hw_bstuck_nfcal(struct ath_hw *ah); -s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); void ath9k_hw_reset_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal); -- cgit v1.2.3-58-ga151 From 73f743670d36ddd61247d709711227b0e2e1a497 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 9 May 2011 12:51:57 -0700 Subject: rtlwifi: rtl8192cu: Fix memset/memcpy using sizeof(ptr) not sizeof(*ptr) Found via coccinelle script @@ type T; T* ptr; expression E1; @@ * memset(E1, 0, sizeof(ptr)); Signed-off-by: Joe Perches Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 79c98f62175f..3a92ba3c4a1e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -372,7 +372,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) __le16 fc; struct ieee80211_hdr *hdr; - memset(rx_status, 0, sizeof(rx_status)); + memset(rx_status, 0, sizeof(*rx_status)); rxdesc = skb->data; skb_len = skb->len; drvinfo_len = (GET_RX_DESC_DRVINFO_SIZE(rxdesc) * RTL_RX_DRV_INFO_UNIT); @@ -434,7 +434,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) "0x%02X\n", fc, (u32)hdr->addr1[0], (u32)hdr->addr1[1], (u32)hdr->addr1[2], (u32)hdr->addr1[3], (u32)hdr->addr1[4], (u32)hdr->addr1[5])); - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); + memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); ieee80211_rx_irqsafe(hw, skb); } -- cgit v1.2.3-58-ga151 From 165af96d56dce3bd0cd09567106f22215f80bb63 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 9 May 2011 19:11:26 +0530 Subject: ath9k_hw: Corrected xpabiaslevel register settings for AR9340 Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index a9dd3a4b4af5..070dc8b882b1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3442,17 +3442,15 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) { int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz); - if (AR_SREV_9485(ah)) + if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); else { REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); - if (!AR_SREV_9340(ah)) { - REG_RMW_FIELD(ah, AR_CH0_THERM, - AR_CH0_THERM_XPABIASLVL_MSB, - bias >> 2); - REG_RMW_FIELD(ah, AR_CH0_THERM, - AR_CH0_THERM_XPASHORT2GND, 1); - } + REG_RMW_FIELD(ah, AR_CH0_THERM, + AR_CH0_THERM_XPABIASLVL_MSB, + bias >> 2); + REG_RMW_FIELD(ah, AR_CH0_THERM, + AR_CH0_THERM_XPASHORT2GND, 1); } } -- cgit v1.2.3-58-ga151 From 94333f59cba08a1f6513ecd7e2fc5b85c1949a98 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 9 May 2011 19:11:27 +0530 Subject: ath9k_hw: Change DCU backoff thresh for AR9340 By changing DCU backoff threshold for AR9340 to 1, helps to reduce rx overrurns seen while running bidirectional traffic. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/mac.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 9cf7a7d0e118..bd6d2b9d736f 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -430,8 +430,13 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)); REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); - REG_WRITE(ah, AR_DMISC(q), - AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); + + if (AR_SREV_9340(ah)) + REG_WRITE(ah, AR_DMISC(q), + AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1); + else + REG_WRITE(ah, AR_DMISC(q), + AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); if (qi->tqi_cbrPeriod) { REG_WRITE(ah, AR_QCBRCFG(q), -- cgit v1.2.3-58-ga151 From 2b892a98db269b96ed097d560aaaa371907d20f5 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 9 May 2011 19:11:28 +0530 Subject: ath9k: Fix rssi update in ad-hoc mode The average beacon rssi which will be used by ani is not updated in adhoc mode. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index a485c040bf80..9fcd1e4f4504 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -917,7 +917,8 @@ static void ath9k_process_rssi(struct ath_common *common, int last_rssi; __le16 fc; - if (ah->opmode != NL80211_IFTYPE_STATION) + if ((ah->opmode != NL80211_IFTYPE_STATION) && + (ah->opmode != NL80211_IFTYPE_ADHOC)) return; fc = hdr->frame_control; -- cgit v1.2.3-58-ga151 From 729da390034d04ff1b3a3f188dfb04a54f458e35 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 9 May 2011 19:11:29 +0530 Subject: ath9k: Failed to set default beacon rssi in AP/IBSS mode This beacon rssi will be used to set noisefloor during ani reset. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 11d9eca8fb6e..c4d32c54224d 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1409,6 +1409,7 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, /* Set up ANI */ if ((iter_data.naps + iter_data.nadhocs) > 0) { + sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; sc->sc_flags |= SC_OP_ANI_RUN; ath_start_ani(common); } else { -- cgit v1.2.3-58-ga151 From 306fe9384f06d31219778cece2d3c646146e7bb6 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Mon, 9 May 2011 19:15:04 +0300 Subject: mac80211: don't drop frames where skb->len < 24 in ieee80211_scan_rx() This seems to be a leftover from the old days, when we didn't support any frames that didn't contain the full ieee802.11 header. This is not the case anymore. It does not cause problems now, because they are only dropped during scan. But when scheduled scans get merged, this would become a problem because we would drop all small frames while scheduled scan is running. To fix this, return RX_CONTINUE instead of RX_DROP_MONITOR. Cc: Johannes Berg Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- net/mac80211/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 489b6ad200d4..8acce724f0dc 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -170,7 +170,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) return RX_CONTINUE; if (skb->len < 24) - return RX_DROP_MONITOR; + return RX_CONTINUE; presp = ieee80211_is_probe_resp(fc); if (presp) { -- cgit v1.2.3-58-ga151 From 8369ae33b705222aa05ab53c7d6b4458f4ed161b Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 9 May 2011 18:56:46 +0200 Subject: bcma: add Broadcom specific AMBA bus driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Broadcom has released cards based on a new AMBA-based bus type. From a programming point of view, this new bus type differs from AMBA and does not use AMBA common registers. It also differs enough from SSB. We decided that a new bus driver is needed to keep the code clean. In its current form, the driver detects devices present on the bus and registers them in the system. It allows registering BCMA drivers for specified bus devices and provides them basic operations. The bus driver itself includes two important bus managing drivers: ChipCommon core driver and PCI(c) core driver. They are early used to allow correct initialization. Currently code is limited to supporting buses on PCI(e) devices, however the driver is designed to be used also on other hosts. The host abstraction layer is implemented and already used for PCI(e). Support for PCI(e) hosts is working and seems to be stable (access to 80211 core was tested successfully on a few devices). We can still optimize it by using some fixed windows, but this can be done later without affecting any external code. Windows are just ranges in MMIO used for accessing cores on the bus. Cc: Greg KH Cc: Michael Büsch Cc: Larry Finger Cc: George Kashperko Cc: Arend van Spriel Cc: linux-arm-kernel@lists.infradead.org Cc: Russell King Cc: Arnd Bergmann Cc: Andy Botting Cc: linuxdriverproject Cc: linux-kernel@vger.kernel.org Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- Documentation/ABI/testing/sysfs-bus-bcma | 31 +++ MAINTAINERS | 7 + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/bcma/Kconfig | 33 +++ drivers/bcma/Makefile | 7 + drivers/bcma/README | 19 ++ drivers/bcma/TODO | 3 + drivers/bcma/bcma_private.h | 28 +++ drivers/bcma/core.c | 51 ++++ drivers/bcma/driver_chipcommon.c | 87 +++++++ drivers/bcma/driver_chipcommon_pmu.c | 134 +++++++++++ drivers/bcma/driver_pci.c | 163 +++++++++++++ drivers/bcma/host_pci.c | 196 +++++++++++++++ drivers/bcma/main.c | 247 +++++++++++++++++++ drivers/bcma/scan.c | 360 ++++++++++++++++++++++++++++ drivers/bcma/scan.h | 56 +++++ include/linux/bcma/bcma.h | 224 +++++++++++++++++ include/linux/bcma/bcma_driver_chipcommon.h | 297 +++++++++++++++++++++++ include/linux/bcma/bcma_driver_pci.h | 89 +++++++ include/linux/bcma/bcma_regs.h | 34 +++ include/linux/mod_devicetable.h | 17 ++ scripts/mod/file2alias.c | 22 ++ 23 files changed, 2108 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-bcma create mode 100644 drivers/bcma/Kconfig create mode 100644 drivers/bcma/Makefile create mode 100644 drivers/bcma/README create mode 100644 drivers/bcma/TODO create mode 100644 drivers/bcma/bcma_private.h create mode 100644 drivers/bcma/core.c create mode 100644 drivers/bcma/driver_chipcommon.c create mode 100644 drivers/bcma/driver_chipcommon_pmu.c create mode 100644 drivers/bcma/driver_pci.c create mode 100644 drivers/bcma/host_pci.c create mode 100644 drivers/bcma/main.c create mode 100644 drivers/bcma/scan.c create mode 100644 drivers/bcma/scan.h create mode 100644 include/linux/bcma/bcma.h create mode 100644 include/linux/bcma/bcma_driver_chipcommon.h create mode 100644 include/linux/bcma/bcma_driver_pci.h create mode 100644 include/linux/bcma/bcma_regs.h diff --git a/Documentation/ABI/testing/sysfs-bus-bcma b/Documentation/ABI/testing/sysfs-bus-bcma new file mode 100644 index 000000000000..06b62badddd1 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-bcma @@ -0,0 +1,31 @@ +What: /sys/bus/bcma/devices/.../manuf +Date: May 2011 +KernelVersion: 2.6.40 +Contact: Rafał Miłecki +Description: + Each BCMA core has it's manufacturer id. See + include/linux/bcma/bcma.h for possible values. + +What: /sys/bus/bcma/devices/.../id +Date: May 2011 +KernelVersion: 2.6.40 +Contact: Rafał Miłecki +Description: + There are a few types of BCMA cores, they can be identified by + id field. + +What: /sys/bus/bcma/devices/.../rev +Date: May 2011 +KernelVersion: 2.6.40 +Contact: Rafał Miłecki +Description: + BCMA cores of the same type can still slightly differ depending + on their revision. Use it for detailed programming. + +What: /sys/bus/bcma/devices/.../class +Date: May 2011 +KernelVersion: 2.6.40 +Contact: Rafał Miłecki +Description: + Each BCMA core is identified by few fields, including class it + belongs to. See include/linux/bcma/bcma.h for possible values. diff --git a/MAINTAINERS b/MAINTAINERS index 9f9104987a73..df5585819a62 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5810,6 +5810,13 @@ S: Maintained F: drivers/ssb/ F: include/linux/ssb/ +BROADCOM SPECIFIC AMBA DRIVER (BCMA) +M: Rafał Miłecki +L: linux-wireless@vger.kernel.org +S: Maintained +F: drivers/bcma/ +F: include/linux/bcma/ + SONY VAIO CONTROL DEVICE DRIVER M: Mattia Dongili L: platform-driver-x86@vger.kernel.org diff --git a/drivers/Kconfig b/drivers/Kconfig index 177c7d156933..aca706751469 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -68,6 +68,8 @@ source "drivers/watchdog/Kconfig" source "drivers/ssb/Kconfig" +source "drivers/bcma/Kconfig" + source "drivers/mfd/Kconfig" source "drivers/regulator/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 3f135b6fb014..a29527f4ded6 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -110,6 +110,7 @@ obj-$(CONFIG_HID) += hid/ obj-$(CONFIG_PPC_PS3) += ps3/ obj-$(CONFIG_OF) += of/ obj-$(CONFIG_SSB) += ssb/ +obj-$(CONFIG_BCMA) += bcma/ obj-$(CONFIG_VHOST_NET) += vhost/ obj-$(CONFIG_VLYNQ) += vlynq/ obj-$(CONFIG_STAGING) += staging/ diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig new file mode 100644 index 000000000000..353781b5b78b --- /dev/null +++ b/drivers/bcma/Kconfig @@ -0,0 +1,33 @@ +config BCMA_POSSIBLE + bool + depends on HAS_IOMEM && HAS_DMA + default y + +menu "Broadcom specific AMBA" + depends on BCMA_POSSIBLE + +config BCMA + tristate "BCMA support" + depends on BCMA_POSSIBLE + help + Bus driver for Broadcom specific Advanced Microcontroller Bus + Architecture. + +config BCMA_HOST_PCI_POSSIBLE + bool + depends on BCMA && PCI = y + default y + +config BCMA_HOST_PCI + bool "Support for BCMA on PCI-host bus" + depends on BCMA_HOST_PCI_POSSIBLE + +config BCMA_DEBUG + bool "BCMA debugging" + depends on BCMA + help + This turns on additional debugging messages. + + If unsure, say N + +endmenu diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile new file mode 100644 index 000000000000..0d56245bcb79 --- /dev/null +++ b/drivers/bcma/Makefile @@ -0,0 +1,7 @@ +bcma-y += main.o scan.o core.o +bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o +bcma-y += driver_pci.o +bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o +obj-$(CONFIG_BCMA) += bcma.o + +ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG diff --git a/drivers/bcma/README b/drivers/bcma/README new file mode 100644 index 000000000000..f7e7ce46c603 --- /dev/null +++ b/drivers/bcma/README @@ -0,0 +1,19 @@ +Broadcom introduced new bus as replacement for older SSB. It is based on AMBA, +however from programming point of view there is nothing AMBA specific we use. + +Standard AMBA drivers are platform specific, have hardcoded addresses and use +AMBA standard fields like CID and PID. + +In case of Broadcom's cards every device consists of: +1) Broadcom specific AMBA device. It is put on AMBA bus, but can not be treated + as standard AMBA device. Reading it's CID or PID can cause machine lockup. +2) AMBA standard devices called ports or wrappers. They have CIDs (AMBA_CID) + and PIDs (0x103BB369), but we do not use that info for anything. One of that + devices is used for managing Broadcom specific core. + +Addresses of AMBA devices are not hardcoded in driver and have to be read from +EPROM. + +In this situation we decided to introduce separated bus. It can contain up to +16 devices identified by Broadcom specific fields: manufacturer, id, revision +and class. diff --git a/drivers/bcma/TODO b/drivers/bcma/TODO new file mode 100644 index 000000000000..da7aa99fe81c --- /dev/null +++ b/drivers/bcma/TODO @@ -0,0 +1,3 @@ +- Interrupts +- Defines for PCI core driver +- Create kernel Documentation (use info from README) diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h new file mode 100644 index 000000000000..2f72e9c585fd --- /dev/null +++ b/drivers/bcma/bcma_private.h @@ -0,0 +1,28 @@ +#ifndef LINUX_BCMA_PRIVATE_H_ +#define LINUX_BCMA_PRIVATE_H_ + +#ifndef pr_fmt +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#endif + +#include +#include + +#define BCMA_CORE_SIZE 0x1000 + +struct bcma_bus; + +/* main.c */ +extern int bcma_bus_register(struct bcma_bus *bus); +extern void bcma_bus_unregister(struct bcma_bus *bus); + +/* scan.c */ +int bcma_bus_scan(struct bcma_bus *bus); + +#ifdef CONFIG_BCMA_HOST_PCI +/* host_pci.c */ +extern int __init bcma_host_pci_init(void); +extern void __exit bcma_host_pci_exit(void); +#endif /* CONFIG_BCMA_HOST_PCI */ + +#endif diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c new file mode 100644 index 000000000000..ced379f7b371 --- /dev/null +++ b/drivers/bcma/core.c @@ -0,0 +1,51 @@ +/* + * Broadcom specific AMBA + * Core ops + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "bcma_private.h" +#include + +bool bcma_core_is_enabled(struct bcma_device *core) +{ + if ((bcma_aread32(core, BCMA_IOCTL) & (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC)) + != BCMA_IOCTL_CLK) + return false; + if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET) + return false; + return true; +} +EXPORT_SYMBOL_GPL(bcma_core_is_enabled); + +static void bcma_core_disable(struct bcma_device *core, u32 flags) +{ + if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET) + return; + + bcma_awrite32(core, BCMA_IOCTL, flags); + bcma_aread32(core, BCMA_IOCTL); + udelay(10); + + bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); + udelay(1); +} + +int bcma_core_enable(struct bcma_device *core, u32 flags) +{ + bcma_core_disable(core, flags); + + bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC | flags)); + bcma_aread32(core, BCMA_IOCTL); + + bcma_awrite32(core, BCMA_RESET_CTL, 0); + udelay(1); + + bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | flags)); + bcma_aread32(core, BCMA_IOCTL); + udelay(1); + + return 0; +} +EXPORT_SYMBOL_GPL(bcma_core_enable); diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c new file mode 100644 index 000000000000..caf596091d4d --- /dev/null +++ b/drivers/bcma/driver_chipcommon.c @@ -0,0 +1,87 @@ +/* + * Broadcom specific AMBA + * ChipCommon core driver + * + * Copyright 2005, Broadcom Corporation + * Copyright 2006, 2007, Michael Buesch + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "bcma_private.h" +#include + +static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, + u32 mask, u32 value) +{ + value &= mask; + value |= bcma_cc_read32(cc, offset) & ~mask; + bcma_cc_write32(cc, offset, value); + + return value; +} + +void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) +{ + if (cc->core->id.rev >= 11) + cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); + cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP); + if (cc->core->id.rev >= 35) + cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT); + + bcma_cc_write32(cc, 0x58, 0); + bcma_cc_write32(cc, 0x5C, 0); + + if (cc->capabilities & BCMA_CC_CAP_PMU) + bcma_pmu_init(cc); + if (cc->capabilities & BCMA_CC_CAP_PCTL) + pr_err("Power control not implemented!\n"); +} + +/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ +void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) +{ + /* instant NMI */ + bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks); +} + +void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value) +{ + bcma_cc_write32_masked(cc, BCMA_CC_IRQMASK, mask, value); +} + +u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask) +{ + return bcma_cc_read32(cc, BCMA_CC_IRQSTAT) & mask; +} + +u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask) +{ + return bcma_cc_read32(cc, BCMA_CC_GPIOIN) & mask; +} + +u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) +{ + return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value); +} + +u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) +{ + return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value); +} + +u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value) +{ + return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value); +} +EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control); + +u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value) +{ + return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value); +} + +u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value) +{ + return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); +} diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c new file mode 100644 index 000000000000..f44177a644c7 --- /dev/null +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -0,0 +1,134 @@ +/* + * Broadcom specific AMBA + * ChipCommon Power Management Unit driver + * + * Copyright 2009, Michael Buesch + * Copyright 2007, Broadcom Corporation + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "bcma_private.h" +#include + +static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, + u32 offset, u32 mask, u32 set) +{ + u32 value; + + bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); + bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset); + bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); + value = bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA); + value &= mask; + value |= set; + bcma_cc_write32(cc, BCMA_CC_CHIPCTL_DATA, value); + bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA); +} + +static void bcma_pmu_pll_init(struct bcma_drv_cc *cc) +{ + struct bcma_bus *bus = cc->core->bus; + + switch (bus->chipinfo.id) { + case 0x4313: + case 0x4331: + case 43224: + case 43225: + break; + default: + pr_err("PLL init unknown for device 0x%04X\n", + bus->chipinfo.id); + } +} + +static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) +{ + struct bcma_bus *bus = cc->core->bus; + u32 min_msk = 0, max_msk = 0; + + switch (bus->chipinfo.id) { + case 0x4313: + min_msk = 0x200D; + max_msk = 0xFFFF; + break; + case 43224: + break; + default: + pr_err("PMU resource config unknown for device 0x%04X\n", + bus->chipinfo.id); + } + + /* Set the resource masks. */ + if (min_msk) + bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); + if (max_msk) + bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); +} + +void bcma_pmu_swreg_init(struct bcma_drv_cc *cc) +{ + struct bcma_bus *bus = cc->core->bus; + + switch (bus->chipinfo.id) { + case 0x4313: + case 0x4331: + case 43224: + break; + default: + pr_err("PMU switch/regulators init unknown for device " + "0x%04X\n", bus->chipinfo.id); + } +} + +void bcma_pmu_workarounds(struct bcma_drv_cc *cc) +{ + struct bcma_bus *bus = cc->core->bus; + + switch (bus->chipinfo.id) { + case 0x4313: + bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); + break; + case 0x4331: + pr_err("Enabling Ext PA lines not implemented\n"); + break; + case 43224: + if (bus->chipinfo.rev == 0) { + pr_err("Workarounds for 43224 rev 0 not fully " + "implemented\n"); + bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); + } else { + bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); + } + break; + default: + pr_err("Workarounds unknown for device 0x%04X\n", + bus->chipinfo.id); + } +} + +void bcma_pmu_init(struct bcma_drv_cc *cc) +{ + u32 pmucap; + + pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP); + cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); + + pr_debug("Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, + pmucap); + + if (cc->pmu.rev == 1) + bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, + ~BCMA_CC_PMU_CTL_NOILPONW); + else + bcma_cc_set32(cc, BCMA_CC_PMU_CTL, + BCMA_CC_PMU_CTL_NOILPONW); + + if (cc->core->id.id == 0x4329 && cc->core->id.rev == 2) + pr_err("Fix for 4329b0 bad LPOM state not implemented!\n"); + + bcma_pmu_pll_init(cc); + bcma_pmu_resources_init(cc); + bcma_pmu_swreg_init(cc); + bcma_pmu_workarounds(cc); +} diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c new file mode 100644 index 000000000000..b98b8359bef5 --- /dev/null +++ b/drivers/bcma/driver_pci.c @@ -0,0 +1,163 @@ +/* + * Broadcom specific AMBA + * PCI Core + * + * Copyright 2005, Broadcom Corporation + * Copyright 2006, 2007, Michael Buesch + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "bcma_private.h" +#include + +/************************************************** + * R/W ops. + **************************************************/ + +static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address) +{ + pcicore_write32(pc, 0x130, address); + pcicore_read32(pc, 0x130); + return pcicore_read32(pc, 0x134); +} + +#if 0 +static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data) +{ + pcicore_write32(pc, 0x130, address); + pcicore_read32(pc, 0x130); + pcicore_write32(pc, 0x134, data); +} +#endif + +static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) +{ + const u16 mdio_control = 0x128; + const u16 mdio_data = 0x12C; + u32 v; + int i; + + v = (1 << 30); /* Start of Transaction */ + v |= (1 << 28); /* Write Transaction */ + v |= (1 << 17); /* Turnaround */ + v |= (0x1F << 18); + v |= (phy << 4); + pcicore_write32(pc, mdio_data, v); + + udelay(10); + for (i = 0; i < 200; i++) { + v = pcicore_read32(pc, mdio_control); + if (v & 0x100 /* Trans complete */) + break; + msleep(1); + } +} + +static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) +{ + const u16 mdio_control = 0x128; + const u16 mdio_data = 0x12C; + int max_retries = 10; + u16 ret = 0; + u32 v; + int i; + + v = 0x80; /* Enable Preamble Sequence */ + v |= 0x2; /* MDIO Clock Divisor */ + pcicore_write32(pc, mdio_control, v); + + if (pc->core->id.rev >= 10) { + max_retries = 200; + bcma_pcie_mdio_set_phy(pc, device); + } + + v = (1 << 30); /* Start of Transaction */ + v |= (1 << 29); /* Read Transaction */ + v |= (1 << 17); /* Turnaround */ + if (pc->core->id.rev < 10) + v |= (u32)device << 22; + v |= (u32)address << 18; + pcicore_write32(pc, mdio_data, v); + /* Wait for the device to complete the transaction */ + udelay(10); + for (i = 0; i < 200; i++) { + v = pcicore_read32(pc, mdio_control); + if (v & 0x100 /* Trans complete */) { + udelay(10); + ret = pcicore_read32(pc, mdio_data); + break; + } + msleep(1); + } + pcicore_write32(pc, mdio_control, 0); + return ret; +} + +static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, + u8 address, u16 data) +{ + const u16 mdio_control = 0x128; + const u16 mdio_data = 0x12C; + int max_retries = 10; + u32 v; + int i; + + v = 0x80; /* Enable Preamble Sequence */ + v |= 0x2; /* MDIO Clock Divisor */ + pcicore_write32(pc, mdio_control, v); + + if (pc->core->id.rev >= 10) { + max_retries = 200; + bcma_pcie_mdio_set_phy(pc, device); + } + + v = (1 << 30); /* Start of Transaction */ + v |= (1 << 28); /* Write Transaction */ + v |= (1 << 17); /* Turnaround */ + if (pc->core->id.rev < 10) + v |= (u32)device << 22; + v |= (u32)address << 18; + v |= data; + pcicore_write32(pc, mdio_data, v); + /* Wait for the device to complete the transaction */ + udelay(10); + for (i = 0; i < max_retries; i++) { + v = pcicore_read32(pc, mdio_control); + if (v & 0x100 /* Trans complete */) + break; + msleep(1); + } + pcicore_write32(pc, mdio_control, 0); +} + +/************************************************** + * Workarounds. + **************************************************/ + +static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc) +{ + return (bcma_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80; +} + +static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) +{ + const u8 serdes_pll_device = 0x1D; + const u8 serdes_rx_device = 0x1F; + u16 tmp; + + bcma_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */, + bcma_pcicore_polarity_workaround(pc)); + tmp = bcma_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */); + if (tmp & 0x4000) + bcma_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000); +} + +/************************************************** + * Init. + **************************************************/ + +void bcma_core_pci_init(struct bcma_drv_pci *pc) +{ + bcma_pcicore_serdes_workaround(pc); +} diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c new file mode 100644 index 000000000000..99dd36e8500b --- /dev/null +++ b/drivers/bcma/host_pci.c @@ -0,0 +1,196 @@ +/* + * Broadcom specific AMBA + * PCI Host + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "bcma_private.h" +#include +#include + +static void bcma_host_pci_switch_core(struct bcma_device *core) +{ + pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN, + core->addr); + pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2, + core->wrap); + core->bus->mapped_core = core; + pr_debug("Switched to core: 0x%X\n", core->id.id); +} + +static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset) +{ + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); + return ioread8(core->bus->mmio + offset); +} + +static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset) +{ + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); + return ioread16(core->bus->mmio + offset); +} + +static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset) +{ + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); + return ioread32(core->bus->mmio + offset); +} + +static void bcma_host_pci_write8(struct bcma_device *core, u16 offset, + u8 value) +{ + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); + iowrite8(value, core->bus->mmio + offset); +} + +static void bcma_host_pci_write16(struct bcma_device *core, u16 offset, + u16 value) +{ + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); + iowrite16(value, core->bus->mmio + offset); +} + +static void bcma_host_pci_write32(struct bcma_device *core, u16 offset, + u32 value) +{ + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); + iowrite32(value, core->bus->mmio + offset); +} + +static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset) +{ + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); + return ioread32(core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset); +} + +static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset, + u32 value) +{ + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); + iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset); +} + +const struct bcma_host_ops bcma_host_pci_ops = { + .read8 = bcma_host_pci_read8, + .read16 = bcma_host_pci_read16, + .read32 = bcma_host_pci_read32, + .write8 = bcma_host_pci_write8, + .write16 = bcma_host_pci_write16, + .write32 = bcma_host_pci_write32, + .aread32 = bcma_host_pci_aread32, + .awrite32 = bcma_host_pci_awrite32, +}; + +static int bcma_host_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + struct bcma_bus *bus; + int err = -ENOMEM; + const char *name; + u32 val; + + /* Alloc */ + bus = kzalloc(sizeof(*bus), GFP_KERNEL); + if (!bus) + goto out; + + /* Basic PCI configuration */ + err = pci_enable_device(dev); + if (err) + goto err_kfree_bus; + + name = dev_name(&dev->dev); + if (dev->driver && dev->driver->name) + name = dev->driver->name; + err = pci_request_regions(dev, name); + if (err) + goto err_pci_disable; + pci_set_master(dev); + + /* Disable the RETRY_TIMEOUT register (0x41) to keep + * PCI Tx retries from interfering with C3 CPU state */ + pci_read_config_dword(dev, 0x40, &val); + if ((val & 0x0000ff00) != 0) + pci_write_config_dword(dev, 0x40, val & 0xffff00ff); + + /* SSB needed additional powering up, do we have any AMBA PCI cards? */ + if (!pci_is_pcie(dev)) + pr_err("PCI card detected, report problems.\n"); + + /* Map MMIO */ + err = -ENOMEM; + bus->mmio = pci_iomap(dev, 0, ~0UL); + if (!bus->mmio) + goto err_pci_release_regions; + + /* Host specific */ + bus->host_pci = dev; + bus->hosttype = BCMA_HOSTTYPE_PCI; + bus->ops = &bcma_host_pci_ops; + + /* Register */ + err = bcma_bus_register(bus); + if (err) + goto err_pci_unmap_mmio; + + pci_set_drvdata(dev, bus); + +out: + return err; + +err_pci_unmap_mmio: + pci_iounmap(dev, bus->mmio); +err_pci_release_regions: + pci_release_regions(dev); +err_pci_disable: + pci_disable_device(dev); +err_kfree_bus: + kfree(bus); + return err; +} + +static void bcma_host_pci_remove(struct pci_dev *dev) +{ + struct bcma_bus *bus = pci_get_drvdata(dev); + + bcma_bus_unregister(bus); + pci_iounmap(dev, bus->mmio); + pci_release_regions(dev); + pci_disable_device(dev); + kfree(bus); + pci_set_drvdata(dev, NULL); +} + +static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); + +static struct pci_driver bcma_pci_bridge_driver = { + .name = "bcma-pci-bridge", + .id_table = bcma_pci_bridge_tbl, + .probe = bcma_host_pci_probe, + .remove = bcma_host_pci_remove, +}; + +int __init bcma_host_pci_init(void) +{ + return pci_register_driver(&bcma_pci_bridge_driver); +} + +void __exit bcma_host_pci_exit(void) +{ + pci_unregister_driver(&bcma_pci_bridge_driver); +} diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c new file mode 100644 index 000000000000..be52344ed19d --- /dev/null +++ b/drivers/bcma/main.c @@ -0,0 +1,247 @@ +/* + * Broadcom specific AMBA + * Bus subsystem + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "bcma_private.h" +#include + +MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); +MODULE_LICENSE("GPL"); + +static int bcma_bus_match(struct device *dev, struct device_driver *drv); +static int bcma_device_probe(struct device *dev); +static int bcma_device_remove(struct device *dev); + +static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct bcma_device *core = container_of(dev, struct bcma_device, dev); + return sprintf(buf, "0x%03X\n", core->id.manuf); +} +static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct bcma_device *core = container_of(dev, struct bcma_device, dev); + return sprintf(buf, "0x%03X\n", core->id.id); +} +static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct bcma_device *core = container_of(dev, struct bcma_device, dev); + return sprintf(buf, "0x%02X\n", core->id.rev); +} +static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct bcma_device *core = container_of(dev, struct bcma_device, dev); + return sprintf(buf, "0x%X\n", core->id.class); +} +static struct device_attribute bcma_device_attrs[] = { + __ATTR_RO(manuf), + __ATTR_RO(id), + __ATTR_RO(rev), + __ATTR_RO(class), + __ATTR_NULL, +}; + +static struct bus_type bcma_bus_type = { + .name = "bcma", + .match = bcma_bus_match, + .probe = bcma_device_probe, + .remove = bcma_device_remove, + .dev_attrs = bcma_device_attrs, +}; + +static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) +{ + struct bcma_device *core; + + list_for_each_entry(core, &bus->cores, list) { + if (core->id.id == coreid) + return core; + } + return NULL; +} + +static void bcma_release_core_dev(struct device *dev) +{ + struct bcma_device *core = container_of(dev, struct bcma_device, dev); + kfree(core); +} + +static int bcma_register_cores(struct bcma_bus *bus) +{ + struct bcma_device *core; + int err, dev_id = 0; + + list_for_each_entry(core, &bus->cores, list) { + /* We support that cores ourself */ + switch (core->id.id) { + case BCMA_CORE_CHIPCOMMON: + case BCMA_CORE_PCI: + case BCMA_CORE_PCIE: + continue; + } + + core->dev.release = bcma_release_core_dev; + core->dev.bus = &bcma_bus_type; + dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id); + + switch (bus->hosttype) { + case BCMA_HOSTTYPE_PCI: + core->dev.parent = &bus->host_pci->dev; + break; + case BCMA_HOSTTYPE_NONE: + case BCMA_HOSTTYPE_SDIO: + break; + } + + err = device_register(&core->dev); + if (err) { + pr_err("Could not register dev for core 0x%03X\n", + core->id.id); + continue; + } + core->dev_registered = true; + dev_id++; + } + + return 0; +} + +static void bcma_unregister_cores(struct bcma_bus *bus) +{ + struct bcma_device *core; + + list_for_each_entry(core, &bus->cores, list) { + if (core->dev_registered) + device_unregister(&core->dev); + } +} + +int bcma_bus_register(struct bcma_bus *bus) +{ + int err; + struct bcma_device *core; + + /* Scan for devices (cores) */ + err = bcma_bus_scan(bus); + if (err) { + pr_err("Failed to scan: %d\n", err); + return -1; + } + + /* Init CC core */ + core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON); + if (core) { + bus->drv_cc.core = core; + bcma_core_chipcommon_init(&bus->drv_cc); + } + + /* Init PCIE core */ + core = bcma_find_core(bus, BCMA_CORE_PCIE); + if (core) { + bus->drv_pci.core = core; + bcma_core_pci_init(&bus->drv_pci); + } + + /* Register found cores */ + bcma_register_cores(bus); + + pr_info("Bus registered\n"); + + return 0; +} +EXPORT_SYMBOL_GPL(bcma_bus_register); + +void bcma_bus_unregister(struct bcma_bus *bus) +{ + bcma_unregister_cores(bus); +} +EXPORT_SYMBOL_GPL(bcma_bus_unregister); + +int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) +{ + drv->drv.name = drv->name; + drv->drv.bus = &bcma_bus_type; + drv->drv.owner = owner; + + return driver_register(&drv->drv); +} +EXPORT_SYMBOL_GPL(__bcma_driver_register); + +void bcma_driver_unregister(struct bcma_driver *drv) +{ + driver_unregister(&drv->drv); +} +EXPORT_SYMBOL_GPL(bcma_driver_unregister); + +static int bcma_bus_match(struct device *dev, struct device_driver *drv) +{ + struct bcma_device *core = container_of(dev, struct bcma_device, dev); + struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv); + const struct bcma_device_id *cid = &core->id; + const struct bcma_device_id *did; + + for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) { + if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) && + (did->id == cid->id || did->id == BCMA_ANY_ID) && + (did->rev == cid->rev || did->rev == BCMA_ANY_REV) && + (did->class == cid->class || did->class == BCMA_ANY_CLASS)) + return 1; + } + return 0; +} + +static int bcma_device_probe(struct device *dev) +{ + struct bcma_device *core = container_of(dev, struct bcma_device, dev); + struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver, + drv); + int err = 0; + + if (adrv->probe) + err = adrv->probe(core); + + return err; +} + +static int bcma_device_remove(struct device *dev) +{ + struct bcma_device *core = container_of(dev, struct bcma_device, dev); + struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver, + drv); + + if (adrv->remove) + adrv->remove(core); + + return 0; +} + +static int __init bcma_modinit(void) +{ + int err; + + err = bus_register(&bcma_bus_type); + if (err) + return err; + +#ifdef CONFIG_BCMA_HOST_PCI + err = bcma_host_pci_init(); + if (err) { + pr_err("PCI host initialization failed\n"); + err = 0; + } +#endif + + return err; +} +fs_initcall(bcma_modinit); + +static void __exit bcma_modexit(void) +{ +#ifdef CONFIG_BCMA_HOST_PCI + bcma_host_pci_exit(); +#endif + bus_unregister(&bcma_bus_type); +} +module_exit(bcma_modexit) diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c new file mode 100644 index 000000000000..40d7dcce8933 --- /dev/null +++ b/drivers/bcma/scan.c @@ -0,0 +1,360 @@ +/* + * Broadcom specific AMBA + * Bus scanning + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "scan.h" +#include "bcma_private.h" + +#include +#include +#include +#include +#include +#include + +struct bcma_device_id_name { + u16 id; + const char *name; +}; +struct bcma_device_id_name bcma_device_names[] = { + { BCMA_CORE_OOB_ROUTER, "OOB Router" }, + { BCMA_CORE_INVALID, "Invalid" }, + { BCMA_CORE_CHIPCOMMON, "ChipCommon" }, + { BCMA_CORE_ILINE20, "ILine 20" }, + { BCMA_CORE_SRAM, "SRAM" }, + { BCMA_CORE_SDRAM, "SDRAM" }, + { BCMA_CORE_PCI, "PCI" }, + { BCMA_CORE_MIPS, "MIPS" }, + { BCMA_CORE_ETHERNET, "Fast Ethernet" }, + { BCMA_CORE_V90, "V90" }, + { BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" }, + { BCMA_CORE_ADSL, "ADSL" }, + { BCMA_CORE_ILINE100, "ILine 100" }, + { BCMA_CORE_IPSEC, "IPSEC" }, + { BCMA_CORE_UTOPIA, "UTOPIA" }, + { BCMA_CORE_PCMCIA, "PCMCIA" }, + { BCMA_CORE_INTERNAL_MEM, "Internal Memory" }, + { BCMA_CORE_MEMC_SDRAM, "MEMC SDRAM" }, + { BCMA_CORE_OFDM, "OFDM" }, + { BCMA_CORE_EXTIF, "EXTIF" }, + { BCMA_CORE_80211, "IEEE 802.11" }, + { BCMA_CORE_PHY_A, "PHY A" }, + { BCMA_CORE_PHY_B, "PHY B" }, + { BCMA_CORE_PHY_G, "PHY G" }, + { BCMA_CORE_MIPS_3302, "MIPS 3302" }, + { BCMA_CORE_USB11_HOST, "USB 1.1 Host" }, + { BCMA_CORE_USB11_DEV, "USB 1.1 Device" }, + { BCMA_CORE_USB20_HOST, "USB 2.0 Host" }, + { BCMA_CORE_USB20_DEV, "USB 2.0 Device" }, + { BCMA_CORE_SDIO_HOST, "SDIO Host" }, + { BCMA_CORE_ROBOSWITCH, "Roboswitch" }, + { BCMA_CORE_PARA_ATA, "PATA" }, + { BCMA_CORE_SATA_XORDMA, "SATA XOR-DMA" }, + { BCMA_CORE_ETHERNET_GBIT, "GBit Ethernet" }, + { BCMA_CORE_PCIE, "PCIe" }, + { BCMA_CORE_PHY_N, "PHY N" }, + { BCMA_CORE_SRAM_CTL, "SRAM Controller" }, + { BCMA_CORE_MINI_MACPHY, "Mini MACPHY" }, + { BCMA_CORE_ARM_1176, "ARM 1176" }, + { BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" }, + { BCMA_CORE_PHY_LP, "PHY LP" }, + { BCMA_CORE_PMU, "PMU" }, + { BCMA_CORE_PHY_SSN, "PHY SSN" }, + { BCMA_CORE_SDIO_DEV, "SDIO Device" }, + { BCMA_CORE_ARM_CM3, "ARM CM3" }, + { BCMA_CORE_PHY_HT, "PHY HT" }, + { BCMA_CORE_MIPS_74K, "MIPS 74K" }, + { BCMA_CORE_MAC_GBIT, "GBit MAC" }, + { BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" }, + { BCMA_CORE_PCIE_RC, "PCIe Root Complex" }, + { BCMA_CORE_OCP_OCP_BRIDGE, "OCP to OCP Bridge" }, + { BCMA_CORE_SHARED_COMMON, "Common Shared" }, + { BCMA_CORE_OCP_AHB_BRIDGE, "OCP to AHB Bridge" }, + { BCMA_CORE_SPI_HOST, "SPI Host" }, + { BCMA_CORE_I2S, "I2S" }, + { BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" }, + { BCMA_CORE_SHIM, "SHIM" }, + { BCMA_CORE_DEFAULT, "Default" }, +}; +const char *bcma_device_name(struct bcma_device_id *id) +{ + int i; + + if (id->manuf == BCMA_MANUF_BCM) { + for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) { + if (bcma_device_names[i].id == id->id) + return bcma_device_names[i].name; + } + } + return "UNKNOWN"; +} + +static u32 bcma_scan_read32(struct bcma_bus *bus, u8 current_coreidx, + u16 offset) +{ + return readl(bus->mmio + offset); +} + +static void bcma_scan_switch_core(struct bcma_bus *bus, u32 addr) +{ + if (bus->hosttype == BCMA_HOSTTYPE_PCI) + pci_write_config_dword(bus->host_pci, BCMA_PCI_BAR0_WIN, + addr); +} + +static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 **eromptr) +{ + u32 ent = readl(*eromptr); + (*eromptr)++; + return ent; +} + +static void bcma_erom_push_ent(u32 **eromptr) +{ + (*eromptr)--; +} + +static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr) +{ + u32 ent = bcma_erom_get_ent(bus, eromptr); + if (!(ent & SCAN_ER_VALID)) + return -ENOENT; + if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_CI) + return -ENOENT; + return ent; +} + +static bool bcma_erom_is_end(struct bcma_bus *bus, u32 **eromptr) +{ + u32 ent = bcma_erom_get_ent(bus, eromptr); + bcma_erom_push_ent(eromptr); + return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID)); +} + +static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr) +{ + u32 ent = bcma_erom_get_ent(bus, eromptr); + bcma_erom_push_ent(eromptr); + return (((ent & SCAN_ER_VALID)) && + ((ent & SCAN_ER_TAGX) == SCAN_ER_TAG_ADDR) && + ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE)); +} + +static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr) +{ + u32 ent; + while (1) { + ent = bcma_erom_get_ent(bus, eromptr); + if ((ent & SCAN_ER_VALID) && + ((ent & SCAN_ER_TAG) == SCAN_ER_TAG_CI)) + break; + if (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID)) + break; + } + bcma_erom_push_ent(eromptr); +} + +static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr) +{ + u32 ent = bcma_erom_get_ent(bus, eromptr); + if (!(ent & SCAN_ER_VALID)) + return -ENOENT; + if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_MP) + return -ENOENT; + return ent; +} + +static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr, + u32 type, u8 port) +{ + u32 addrl, addrh, sizel, sizeh = 0; + u32 size; + + u32 ent = bcma_erom_get_ent(bus, eromptr); + if ((!(ent & SCAN_ER_VALID)) || + ((ent & SCAN_ER_TAGX) != SCAN_ER_TAG_ADDR) || + ((ent & SCAN_ADDR_TYPE) != type) || + (((ent & SCAN_ADDR_PORT) >> SCAN_ADDR_PORT_SHIFT) != port)) { + bcma_erom_push_ent(eromptr); + return -EINVAL; + } + + addrl = ent & SCAN_ADDR_ADDR; + if (ent & SCAN_ADDR_AG32) + addrh = bcma_erom_get_ent(bus, eromptr); + else + addrh = 0; + + if ((ent & SCAN_ADDR_SZ) == SCAN_ADDR_SZ_SZD) { + size = bcma_erom_get_ent(bus, eromptr); + sizel = size & SCAN_SIZE_SZ; + if (size & SCAN_SIZE_SG32) + sizeh = bcma_erom_get_ent(bus, eromptr); + } else + sizel = SCAN_ADDR_SZ_BASE << + ((ent & SCAN_ADDR_SZ) >> SCAN_ADDR_SZ_SHIFT); + + return addrl; +} + +int bcma_bus_scan(struct bcma_bus *bus) +{ + u32 erombase; + u32 __iomem *eromptr, *eromend; + + s32 cia, cib; + u8 ports[2], wrappers[2]; + + s32 tmp; + u8 i, j; + + int err; + + INIT_LIST_HEAD(&bus->cores); + bus->nr_cores = 0; + + bcma_scan_switch_core(bus, BCMA_ADDR_BASE); + + tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); + bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; + bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; + bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; + + erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); + eromptr = bus->mmio; + eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); + + bcma_scan_switch_core(bus, erombase); + + while (eromptr < eromend) { + struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL); + if (!core) + return -ENOMEM; + INIT_LIST_HEAD(&core->list); + core->bus = bus; + + /* get CIs */ + cia = bcma_erom_get_ci(bus, &eromptr); + if (cia < 0) { + bcma_erom_push_ent(&eromptr); + if (bcma_erom_is_end(bus, &eromptr)) + break; + err= -EILSEQ; + goto out; + } + cib = bcma_erom_get_ci(bus, &eromptr); + if (cib < 0) { + err= -EILSEQ; + goto out; + } + + /* parse CIs */ + core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT; + core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT; + core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT; + ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT; + ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT; + wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT; + wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT; + core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT; + + if (((core->id.manuf == BCMA_MANUF_ARM) && + (core->id.id == 0xFFF)) || + (ports[1] == 0)) { + bcma_erom_skip_component(bus, &eromptr); + continue; + } + + /* check if component is a core at all */ + if (wrappers[0] + wrappers[1] == 0) { + /* we could save addrl of the router + if (cid == BCMA_CORE_OOB_ROUTER) + */ + bcma_erom_skip_component(bus, &eromptr); + continue; + } + + if (bcma_erom_is_bridge(bus, &eromptr)) { + bcma_erom_skip_component(bus, &eromptr); + continue; + } + + /* get & parse master ports */ + for (i = 0; i < ports[0]; i++) { + u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr); + if (mst_port_d < 0) { + err= -EILSEQ; + goto out; + } + } + + /* get & parse slave ports */ + for (i = 0; i < ports[1]; i++) { + for (j = 0; ; j++) { + tmp = bcma_erom_get_addr_desc(bus, &eromptr, + SCAN_ADDR_TYPE_SLAVE, i); + if (tmp < 0) { + /* no more entries for port _i_ */ + /* pr_debug("erom: slave port %d " + * "has %d descriptors\n", i, j); */ + break; + } else { + if (i == 0 && j == 0) + core->addr = tmp; + } + } + } + + /* get & parse master wrappers */ + for (i = 0; i < wrappers[0]; i++) { + for (j = 0; ; j++) { + tmp = bcma_erom_get_addr_desc(bus, &eromptr, + SCAN_ADDR_TYPE_MWRAP, i); + if (tmp < 0) { + /* no more entries for port _i_ */ + /* pr_debug("erom: master wrapper %d " + * "has %d descriptors\n", i, j); */ + break; + } else { + if (i == 0 && j == 0) + core->wrap = tmp; + } + } + } + + /* get & parse slave wrappers */ + for (i = 0; i < wrappers[1]; i++) { + u8 hack = (ports[1] == 1) ? 0 : 1; + for (j = 0; ; j++) { + tmp = bcma_erom_get_addr_desc(bus, &eromptr, + SCAN_ADDR_TYPE_SWRAP, i + hack); + if (tmp < 0) { + /* no more entries for port _i_ */ + /* pr_debug("erom: master wrapper %d " + * has %d descriptors\n", i, j); */ + break; + } else { + if (wrappers[0] == 0 && !i && !j) + core->wrap = tmp; + } + } + } + + pr_info("Core %d found: %s " + "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", + bus->nr_cores, bcma_device_name(&core->id), + core->id.manuf, core->id.id, core->id.rev, + core->id.class); + + core->core_index = bus->nr_cores++; + list_add(&core->list, &bus->cores); + continue; +out: + return err; + } + + return 0; +} diff --git a/drivers/bcma/scan.h b/drivers/bcma/scan.h new file mode 100644 index 000000000000..113e6a66884c --- /dev/null +++ b/drivers/bcma/scan.h @@ -0,0 +1,56 @@ +#ifndef BCMA_SCAN_H_ +#define BCMA_SCAN_H_ + +#define BCMA_ADDR_BASE 0x18000000 +#define BCMA_WRAP_BASE 0x18100000 + +#define SCAN_ER_VALID 0x00000001 +#define SCAN_ER_TAGX 0x00000006 /* we have to ignore 0x8 bit when checking tag for SCAN_ER_TAG_ADDR */ +#define SCAN_ER_TAG 0x0000000E +#define SCAN_ER_TAG_CI 0x00000000 +#define SCAN_ER_TAG_MP 0x00000002 +#define SCAN_ER_TAG_ADDR 0x00000004 +#define SCAN_ER_TAG_END 0x0000000E +#define SCAN_ER_BAD 0xFFFFFFFF + +#define SCAN_CIA_CLASS 0x000000F0 +#define SCAN_CIA_CLASS_SHIFT 4 +#define SCAN_CIA_ID 0x000FFF00 +#define SCAN_CIA_ID_SHIFT 8 +#define SCAN_CIA_MANUF 0xFFF00000 +#define SCAN_CIA_MANUF_SHIFT 20 + +#define SCAN_CIB_NMP 0x000001F0 +#define SCAN_CIB_NMP_SHIFT 4 +#define SCAN_CIB_NSP 0x00003E00 +#define SCAN_CIB_NSP_SHIFT 9 +#define SCAN_CIB_NMW 0x0007C000 +#define SCAN_CIB_NMW_SHIFT 14 +#define SCAN_CIB_NSW 0x00F80000 +#define SCAN_CIB_NSW_SHIFT 17 +#define SCAN_CIB_REV 0xFF000000 +#define SCAN_CIB_REV_SHIFT 24 + +#define SCAN_ADDR_AG32 0x00000008 +#define SCAN_ADDR_SZ 0x00000030 +#define SCAN_ADDR_SZ_SHIFT 4 +#define SCAN_ADDR_SZ_4K 0x00000000 +#define SCAN_ADDR_SZ_8K 0x00000010 +#define SCAN_ADDR_SZ_16K 0x00000020 +#define SCAN_ADDR_SZ_SZD 0x00000030 +#define SCAN_ADDR_TYPE 0x000000C0 +#define SCAN_ADDR_TYPE_SLAVE 0x00000000 +#define SCAN_ADDR_TYPE_BRIDGE 0x00000040 +#define SCAN_ADDR_TYPE_SWRAP 0x00000080 +#define SCAN_ADDR_TYPE_MWRAP 0x000000C0 +#define SCAN_ADDR_PORT 0x00000F00 +#define SCAN_ADDR_PORT_SHIFT 8 +#define SCAN_ADDR_ADDR 0xFFFFF000 + +#define SCAN_ADDR_SZ_BASE 0x00001000 /* 4KB */ + +#define SCAN_SIZE_SZ_ALIGN 0x00000FFF +#define SCAN_SIZE_SZ 0xFFFFF000 +#define SCAN_SIZE_SG32 0x00000008 + +#endif /* BCMA_SCAN_H_ */ diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h new file mode 100644 index 000000000000..08763e4e848f --- /dev/null +++ b/include/linux/bcma/bcma.h @@ -0,0 +1,224 @@ +#ifndef LINUX_BCMA_H_ +#define LINUX_BCMA_H_ + +#include +#include + +#include +#include + +#include "bcma_regs.h" + +struct bcma_device; +struct bcma_bus; + +enum bcma_hosttype { + BCMA_HOSTTYPE_NONE, + BCMA_HOSTTYPE_PCI, + BCMA_HOSTTYPE_SDIO, +}; + +struct bcma_chipinfo { + u16 id; + u8 rev; + u8 pkg; +}; + +struct bcma_host_ops { + u8 (*read8)(struct bcma_device *core, u16 offset); + u16 (*read16)(struct bcma_device *core, u16 offset); + u32 (*read32)(struct bcma_device *core, u16 offset); + void (*write8)(struct bcma_device *core, u16 offset, u8 value); + void (*write16)(struct bcma_device *core, u16 offset, u16 value); + void (*write32)(struct bcma_device *core, u16 offset, u32 value); + /* Agent ops */ + u32 (*aread32)(struct bcma_device *core, u16 offset); + void (*awrite32)(struct bcma_device *core, u16 offset, u32 value); +}; + +/* Core manufacturers */ +#define BCMA_MANUF_ARM 0x43B +#define BCMA_MANUF_MIPS 0x4A7 +#define BCMA_MANUF_BCM 0x4BF + +/* Core class values. */ +#define BCMA_CL_SIM 0x0 +#define BCMA_CL_EROM 0x1 +#define BCMA_CL_CORESIGHT 0x9 +#define BCMA_CL_VERIF 0xB +#define BCMA_CL_OPTIMO 0xD +#define BCMA_CL_GEN 0xE +#define BCMA_CL_PRIMECELL 0xF + +/* Core-ID values. */ +#define BCMA_CORE_OOB_ROUTER 0x367 /* Out of band */ +#define BCMA_CORE_INVALID 0x700 +#define BCMA_CORE_CHIPCOMMON 0x800 +#define BCMA_CORE_ILINE20 0x801 +#define BCMA_CORE_SRAM 0x802 +#define BCMA_CORE_SDRAM 0x803 +#define BCMA_CORE_PCI 0x804 +#define BCMA_CORE_MIPS 0x805 +#define BCMA_CORE_ETHERNET 0x806 +#define BCMA_CORE_V90 0x807 +#define BCMA_CORE_USB11_HOSTDEV 0x808 +#define BCMA_CORE_ADSL 0x809 +#define BCMA_CORE_ILINE100 0x80A +#define BCMA_CORE_IPSEC 0x80B +#define BCMA_CORE_UTOPIA 0x80C +#define BCMA_CORE_PCMCIA 0x80D +#define BCMA_CORE_INTERNAL_MEM 0x80E +#define BCMA_CORE_MEMC_SDRAM 0x80F +#define BCMA_CORE_OFDM 0x810 +#define BCMA_CORE_EXTIF 0x811 +#define BCMA_CORE_80211 0x812 +#define BCMA_CORE_PHY_A 0x813 +#define BCMA_CORE_PHY_B 0x814 +#define BCMA_CORE_PHY_G 0x815 +#define BCMA_CORE_MIPS_3302 0x816 +#define BCMA_CORE_USB11_HOST 0x817 +#define BCMA_CORE_USB11_DEV 0x818 +#define BCMA_CORE_USB20_HOST 0x819 +#define BCMA_CORE_USB20_DEV 0x81A +#define BCMA_CORE_SDIO_HOST 0x81B +#define BCMA_CORE_ROBOSWITCH 0x81C +#define BCMA_CORE_PARA_ATA 0x81D +#define BCMA_CORE_SATA_XORDMA 0x81E +#define BCMA_CORE_ETHERNET_GBIT 0x81F +#define BCMA_CORE_PCIE 0x820 +#define BCMA_CORE_PHY_N 0x821 +#define BCMA_CORE_SRAM_CTL 0x822 +#define BCMA_CORE_MINI_MACPHY 0x823 +#define BCMA_CORE_ARM_1176 0x824 +#define BCMA_CORE_ARM_7TDMI 0x825 +#define BCMA_CORE_PHY_LP 0x826 +#define BCMA_CORE_PMU 0x827 +#define BCMA_CORE_PHY_SSN 0x828 +#define BCMA_CORE_SDIO_DEV 0x829 +#define BCMA_CORE_ARM_CM3 0x82A +#define BCMA_CORE_PHY_HT 0x82B +#define BCMA_CORE_MIPS_74K 0x82C +#define BCMA_CORE_MAC_GBIT 0x82D +#define BCMA_CORE_DDR12_MEM_CTL 0x82E +#define BCMA_CORE_PCIE_RC 0x82F /* PCIe Root Complex */ +#define BCMA_CORE_OCP_OCP_BRIDGE 0x830 +#define BCMA_CORE_SHARED_COMMON 0x831 +#define BCMA_CORE_OCP_AHB_BRIDGE 0x832 +#define BCMA_CORE_SPI_HOST 0x833 +#define BCMA_CORE_I2S 0x834 +#define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */ +#define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */ +#define BCMA_CORE_DEFAULT 0xFFF + +#define BCMA_MAX_NR_CORES 16 + +struct bcma_device { + struct bcma_bus *bus; + struct bcma_device_id id; + + struct device dev; + bool dev_registered; + + u8 core_index; + + u32 addr; + u32 wrap; + + void *drvdata; + struct list_head list; +}; + +static inline void *bcma_get_drvdata(struct bcma_device *core) +{ + return core->drvdata; +} +static inline void bcma_set_drvdata(struct bcma_device *core, void *drvdata) +{ + core->drvdata = drvdata; +} + +struct bcma_driver { + const char *name; + const struct bcma_device_id *id_table; + + int (*probe)(struct bcma_device *dev); + void (*remove)(struct bcma_device *dev); + int (*suspend)(struct bcma_device *dev, pm_message_t state); + int (*resume)(struct bcma_device *dev); + void (*shutdown)(struct bcma_device *dev); + + struct device_driver drv; +}; +extern +int __bcma_driver_register(struct bcma_driver *drv, struct module *owner); +static inline int bcma_driver_register(struct bcma_driver *drv) +{ + return __bcma_driver_register(drv, THIS_MODULE); +} +extern void bcma_driver_unregister(struct bcma_driver *drv); + +struct bcma_bus { + /* The MMIO area. */ + void __iomem *mmio; + + const struct bcma_host_ops *ops; + + enum bcma_hosttype hosttype; + union { + /* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */ + struct pci_dev *host_pci; + /* Pointer to the SDIO device (only for BCMA_HOSTTYPE_SDIO) */ + struct sdio_func *host_sdio; + }; + + struct bcma_chipinfo chipinfo; + + struct bcma_device *mapped_core; + struct list_head cores; + u8 nr_cores; + + struct bcma_drv_cc drv_cc; + struct bcma_drv_pci drv_pci; +}; + +extern inline u32 bcma_read8(struct bcma_device *core, u16 offset) +{ + return core->bus->ops->read8(core, offset); +} +extern inline u32 bcma_read16(struct bcma_device *core, u16 offset) +{ + return core->bus->ops->read16(core, offset); +} +extern inline u32 bcma_read32(struct bcma_device *core, u16 offset) +{ + return core->bus->ops->read32(core, offset); +} +extern inline +void bcma_write8(struct bcma_device *core, u16 offset, u32 value) +{ + core->bus->ops->write8(core, offset, value); +} +extern inline +void bcma_write16(struct bcma_device *core, u16 offset, u32 value) +{ + core->bus->ops->write16(core, offset, value); +} +extern inline +void bcma_write32(struct bcma_device *core, u16 offset, u32 value) +{ + core->bus->ops->write32(core, offset, value); +} +extern inline u32 bcma_aread32(struct bcma_device *core, u16 offset) +{ + return core->bus->ops->aread32(core, offset); +} +extern inline +void bcma_awrite32(struct bcma_device *core, u16 offset, u32 value) +{ + core->bus->ops->awrite32(core, offset, value); +} + +extern bool bcma_core_is_enabled(struct bcma_device *core); +extern int bcma_core_enable(struct bcma_device *core, u32 flags); + +#endif /* LINUX_BCMA_H_ */ diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h new file mode 100644 index 000000000000..4f8fd6a4c1e6 --- /dev/null +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -0,0 +1,297 @@ +#ifndef LINUX_BCMA_DRIVER_CC_H_ +#define LINUX_BCMA_DRIVER_CC_H_ + +/** ChipCommon core registers. **/ +#define BCMA_CC_ID 0x0000 +#define BCMA_CC_ID_ID 0x0000FFFF +#define BCMA_CC_ID_ID_SHIFT 0 +#define BCMA_CC_ID_REV 0x000F0000 +#define BCMA_CC_ID_REV_SHIFT 16 +#define BCMA_CC_ID_PKG 0x00F00000 +#define BCMA_CC_ID_PKG_SHIFT 20 +#define BCMA_CC_ID_NRCORES 0x0F000000 +#define BCMA_CC_ID_NRCORES_SHIFT 24 +#define BCMA_CC_ID_TYPE 0xF0000000 +#define BCMA_CC_ID_TYPE_SHIFT 28 +#define BCMA_CC_CAP 0x0004 /* Capabilities */ +#define BCMA_CC_CAP_NRUART 0x00000003 /* # of UARTs */ +#define BCMA_CC_CAP_MIPSEB 0x00000004 /* MIPS in BigEndian Mode */ +#define BCMA_CC_CAP_UARTCLK 0x00000018 /* UART clock select */ +#define BCMA_CC_CAP_UARTCLK_INT 0x00000008 /* UARTs are driven by internal divided clock */ +#define BCMA_CC_CAP_UARTGPIO 0x00000020 /* UARTs on GPIO 15-12 */ +#define BCMA_CC_CAP_EXTBUS 0x000000C0 /* External buses present */ +#define BCMA_CC_CAP_FLASHT 0x00000700 /* Flash Type */ +#define BCMA_CC_FLASHT_NONE 0x00000000 /* No flash */ +#define BCMA_CC_FLASHT_STSER 0x00000100 /* ST serial flash */ +#define BCMA_CC_FLASHT_ATSER 0x00000200 /* Atmel serial flash */ +#define BCMA_CC_FLASHT_PARA 0x00000700 /* Parallel flash */ +#define BCMA_CC_CAP_PLLT 0x00038000 /* PLL Type */ +#define BCMA_PLLTYPE_NONE 0x00000000 +#define BCMA_PLLTYPE_1 0x00010000 /* 48Mhz base, 3 dividers */ +#define BCMA_PLLTYPE_2 0x00020000 /* 48Mhz, 4 dividers */ +#define BCMA_PLLTYPE_3 0x00030000 /* 25Mhz, 2 dividers */ +#define BCMA_PLLTYPE_4 0x00008000 /* 48Mhz, 4 dividers */ +#define BCMA_PLLTYPE_5 0x00018000 /* 25Mhz, 4 dividers */ +#define BCMA_PLLTYPE_6 0x00028000 /* 100/200 or 120/240 only */ +#define BCMA_PLLTYPE_7 0x00038000 /* 25Mhz, 4 dividers */ +#define BCMA_CC_CAP_PCTL 0x00040000 /* Power Control */ +#define BCMA_CC_CAP_OTPS 0x00380000 /* OTP size */ +#define BCMA_CC_CAP_OTPS_SHIFT 19 +#define BCMA_CC_CAP_OTPS_BASE 5 +#define BCMA_CC_CAP_JTAGM 0x00400000 /* JTAG master present */ +#define BCMA_CC_CAP_BROM 0x00800000 /* Internal boot ROM active */ +#define BCMA_CC_CAP_64BIT 0x08000000 /* 64-bit Backplane */ +#define BCMA_CC_CAP_PMU 0x10000000 /* PMU available (rev >= 20) */ +#define BCMA_CC_CAP_ECI 0x20000000 /* ECI available (rev >= 20) */ +#define BCMA_CC_CAP_SPROM 0x40000000 /* SPROM present */ +#define BCMA_CC_CORECTL 0x0008 +#define BCMA_CC_CORECTL_UARTCLK0 0x00000001 /* Drive UART with internal clock */ +#define BCMA_CC_CORECTL_SE 0x00000002 /* sync clk out enable (corerev >= 3) */ +#define BCMA_CC_CORECTL_UARTCLKEN 0x00000008 /* UART clock enable (rev >= 21) */ +#define BCMA_CC_BIST 0x000C +#define BCMA_CC_OTPS 0x0010 /* OTP status */ +#define BCMA_CC_OTPS_PROGFAIL 0x80000000 +#define BCMA_CC_OTPS_PROTECT 0x00000007 +#define BCMA_CC_OTPS_HW_PROTECT 0x00000001 +#define BCMA_CC_OTPS_SW_PROTECT 0x00000002 +#define BCMA_CC_OTPS_CID_PROTECT 0x00000004 +#define BCMA_CC_OTPC 0x0014 /* OTP control */ +#define BCMA_CC_OTPC_RECWAIT 0xFF000000 +#define BCMA_CC_OTPC_PROGWAIT 0x00FFFF00 +#define BCMA_CC_OTPC_PRW_SHIFT 8 +#define BCMA_CC_OTPC_MAXFAIL 0x00000038 +#define BCMA_CC_OTPC_VSEL 0x00000006 +#define BCMA_CC_OTPC_SELVL 0x00000001 +#define BCMA_CC_OTPP 0x0018 /* OTP prog */ +#define BCMA_CC_OTPP_COL 0x000000FF +#define BCMA_CC_OTPP_ROW 0x0000FF00 +#define BCMA_CC_OTPP_ROW_SHIFT 8 +#define BCMA_CC_OTPP_READERR 0x10000000 +#define BCMA_CC_OTPP_VALUE 0x20000000 +#define BCMA_CC_OTPP_READ 0x40000000 +#define BCMA_CC_OTPP_START 0x80000000 +#define BCMA_CC_OTPP_BUSY 0x80000000 +#define BCMA_CC_IRQSTAT 0x0020 +#define BCMA_CC_IRQMASK 0x0024 +#define BCMA_CC_IRQ_GPIO 0x00000001 /* gpio intr */ +#define BCMA_CC_IRQ_EXT 0x00000002 /* ro: ext intr pin (corerev >= 3) */ +#define BCMA_CC_IRQ_WDRESET 0x80000000 /* watchdog reset occurred */ +#define BCMA_CC_CHIPCTL 0x0028 /* Rev >= 11 only */ +#define BCMA_CC_CHIPSTAT 0x002C /* Rev >= 11 only */ +#define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ +#define BCMA_CC_JCMD_START 0x80000000 +#define BCMA_CC_JCMD_BUSY 0x80000000 +#define BCMA_CC_JCMD_PAUSE 0x40000000 +#define BCMA_CC_JCMD0_ACC_MASK 0x0000F000 +#define BCMA_CC_JCMD0_ACC_IRDR 0x00000000 +#define BCMA_CC_JCMD0_ACC_DR 0x00001000 +#define BCMA_CC_JCMD0_ACC_IR 0x00002000 +#define BCMA_CC_JCMD0_ACC_RESET 0x00003000 +#define BCMA_CC_JCMD0_ACC_IRPDR 0x00004000 +#define BCMA_CC_JCMD0_ACC_PDR 0x00005000 +#define BCMA_CC_JCMD0_IRW_MASK 0x00000F00 +#define BCMA_CC_JCMD_ACC_MASK 0x000F0000 /* Changes for corerev 11 */ +#define BCMA_CC_JCMD_ACC_IRDR 0x00000000 +#define BCMA_CC_JCMD_ACC_DR 0x00010000 +#define BCMA_CC_JCMD_ACC_IR 0x00020000 +#define BCMA_CC_JCMD_ACC_RESET 0x00030000 +#define BCMA_CC_JCMD_ACC_IRPDR 0x00040000 +#define BCMA_CC_JCMD_ACC_PDR 0x00050000 +#define BCMA_CC_JCMD_IRW_MASK 0x00001F00 +#define BCMA_CC_JCMD_IRW_SHIFT 8 +#define BCMA_CC_JCMD_DRW_MASK 0x0000003F +#define BCMA_CC_JIR 0x0034 /* Rev >= 10 only */ +#define BCMA_CC_JDR 0x0038 /* Rev >= 10 only */ +#define BCMA_CC_JCTL 0x003C /* Rev >= 10 only */ +#define BCMA_CC_JCTL_FORCE_CLK 4 /* Force clock */ +#define BCMA_CC_JCTL_EXT_EN 2 /* Enable external targets */ +#define BCMA_CC_JCTL_EN 1 /* Enable Jtag master */ +#define BCMA_CC_FLASHCTL 0x0040 +#define BCMA_CC_FLASHCTL_START 0x80000000 +#define BCMA_CC_FLASHCTL_BUSY BCMA_CC_FLASHCTL_START +#define BCMA_CC_FLASHADDR 0x0044 +#define BCMA_CC_FLASHDATA 0x0048 +#define BCMA_CC_BCAST_ADDR 0x0050 +#define BCMA_CC_BCAST_DATA 0x0054 +#define BCMA_CC_GPIOIN 0x0060 +#define BCMA_CC_GPIOOUT 0x0064 +#define BCMA_CC_GPIOOUTEN 0x0068 +#define BCMA_CC_GPIOCTL 0x006C +#define BCMA_CC_GPIOPOL 0x0070 +#define BCMA_CC_GPIOIRQ 0x0074 +#define BCMA_CC_WATCHDOG 0x0080 +#define BCMA_CC_GPIOTIMER 0x0088 /* LED powersave (corerev >= 16) */ +#define BCMA_CC_GPIOTIMER_ONTIME_SHIFT 16 +#define BCMA_CC_GPIOTOUTM 0x008C /* LED powersave (corerev >= 16) */ +#define BCMA_CC_CLOCK_N 0x0090 +#define BCMA_CC_CLOCK_SB 0x0094 +#define BCMA_CC_CLOCK_PCI 0x0098 +#define BCMA_CC_CLOCK_M2 0x009C +#define BCMA_CC_CLOCK_MIPS 0x00A0 +#define BCMA_CC_CLKDIV 0x00A4 /* Rev >= 3 only */ +#define BCMA_CC_CLKDIV_SFLASH 0x0F000000 +#define BCMA_CC_CLKDIV_SFLASH_SHIFT 24 +#define BCMA_CC_CLKDIV_OTP 0x000F0000 +#define BCMA_CC_CLKDIV_OTP_SHIFT 16 +#define BCMA_CC_CLKDIV_JTAG 0x00000F00 +#define BCMA_CC_CLKDIV_JTAG_SHIFT 8 +#define BCMA_CC_CLKDIV_UART 0x000000FF +#define BCMA_CC_CAP_EXT 0x00AC /* Capabilities */ +#define BCMA_CC_PLLONDELAY 0x00B0 /* Rev >= 4 only */ +#define BCMA_CC_FREFSELDELAY 0x00B4 /* Rev >= 4 only */ +#define BCMA_CC_SLOWCLKCTL 0x00B8 /* 6 <= Rev <= 9 only */ +#define BCMA_CC_SLOWCLKCTL_SRC 0x00000007 /* slow clock source mask */ +#define BCMA_CC_SLOWCLKCTL_SRC_LPO 0x00000000 /* source of slow clock is LPO */ +#define BCMA_CC_SLOWCLKCTL_SRC_XTAL 0x00000001 /* source of slow clock is crystal */ +#define BCMA_CC_SLOECLKCTL_SRC_PCI 0x00000002 /* source of slow clock is PCI */ +#define BCMA_CC_SLOWCLKCTL_LPOFREQ 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ +#define BCMA_CC_SLOWCLKCTL_LPOPD 0x00000400 /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */ +#define BCMA_CC_SLOWCLKCTL_FSLOW 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */ +#define BCMA_CC_SLOWCLKCTL_IPLL 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors PLL clock disable requests from core */ +#define BCMA_CC_SLOWCLKCTL_ENXTAL 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't disable crystal when appropriate */ +#define BCMA_CC_SLOWCLKCTL_XTALPU 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */ +#define BCMA_CC_SLOWCLKCTL_CLKDIV 0xFFFF0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */ +#define BCMA_CC_SLOWCLKCTL_CLKDIV_SHIFT 16 +#define BCMA_CC_SYSCLKCTL 0x00C0 /* Rev >= 3 only */ +#define BCMA_CC_SYSCLKCTL_IDLPEN 0x00000001 /* ILPen: Enable Idle Low Power */ +#define BCMA_CC_SYSCLKCTL_ALPEN 0x00000002 /* ALPen: Enable Active Low Power */ +#define BCMA_CC_SYSCLKCTL_PLLEN 0x00000004 /* ForcePLLOn */ +#define BCMA_CC_SYSCLKCTL_FORCEALP 0x00000008 /* Force ALP (or HT if ALPen is not set */ +#define BCMA_CC_SYSCLKCTL_FORCEHT 0x00000010 /* Force HT */ +#define BCMA_CC_SYSCLKCTL_CLKDIV 0xFFFF0000 /* ClkDiv (ILP = 1/(4+divisor)) */ +#define BCMA_CC_SYSCLKCTL_CLKDIV_SHIFT 16 +#define BCMA_CC_CLKSTSTR 0x00C4 /* Rev >= 3 only */ +#define BCMA_CC_EROM 0x00FC +#define BCMA_CC_PCMCIA_CFG 0x0100 +#define BCMA_CC_PCMCIA_MEMWAIT 0x0104 +#define BCMA_CC_PCMCIA_ATTRWAIT 0x0108 +#define BCMA_CC_PCMCIA_IOWAIT 0x010C +#define BCMA_CC_IDE_CFG 0x0110 +#define BCMA_CC_IDE_MEMWAIT 0x0114 +#define BCMA_CC_IDE_ATTRWAIT 0x0118 +#define BCMA_CC_IDE_IOWAIT 0x011C +#define BCMA_CC_PROG_CFG 0x0120 +#define BCMA_CC_PROG_WAITCNT 0x0124 +#define BCMA_CC_FLASH_CFG 0x0128 +#define BCMA_CC_FLASH_WAITCNT 0x012C +#define BCMA_CC_CLKCTLST 0x01E0 /* Clock control and status (rev >= 20) */ +#define BCMA_CC_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */ +#define BCMA_CC_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */ +#define BCMA_CC_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */ +#define BCMA_CC_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */ +#define BCMA_CC_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */ +#define BCMA_CC_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */ +#define BCMA_CC_CLKCTLST_HAVEHT 0x00010000 /* HT available */ +#define BCMA_CC_CLKCTLST_HAVEALP 0x00020000 /* APL available */ +#define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ +#define BCMA_CC_UART0_DATA 0x0300 +#define BCMA_CC_UART0_IMR 0x0304 +#define BCMA_CC_UART0_FCR 0x0308 +#define BCMA_CC_UART0_LCR 0x030C +#define BCMA_CC_UART0_MCR 0x0310 +#define BCMA_CC_UART0_LSR 0x0314 +#define BCMA_CC_UART0_MSR 0x0318 +#define BCMA_CC_UART0_SCRATCH 0x031C +#define BCMA_CC_UART1_DATA 0x0400 +#define BCMA_CC_UART1_IMR 0x0404 +#define BCMA_CC_UART1_FCR 0x0408 +#define BCMA_CC_UART1_LCR 0x040C +#define BCMA_CC_UART1_MCR 0x0410 +#define BCMA_CC_UART1_LSR 0x0414 +#define BCMA_CC_UART1_MSR 0x0418 +#define BCMA_CC_UART1_SCRATCH 0x041C +/* PMU registers (rev >= 20) */ +#define BCMA_CC_PMU_CTL 0x0600 /* PMU control */ +#define BCMA_CC_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */ +#define BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16 +#define BCMA_CC_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */ +#define BCMA_CC_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */ +#define BCMA_CC_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */ +#define BCMA_CC_PMU_CTL_XTALFREQ 0x0000007C /* Crystal freq */ +#define BCMA_CC_PMU_CTL_XTALFREQ_SHIFT 2 +#define BCMA_CC_PMU_CTL_ILPDIVEN 0x00000002 /* ILP div enable */ +#define BCMA_CC_PMU_CTL_LPOSEL 0x00000001 /* LPO sel */ +#define BCMA_CC_PMU_CAP 0x0604 /* PMU capabilities */ +#define BCMA_CC_PMU_CAP_REVISION 0x000000FF /* Revision mask */ +#define BCMA_CC_PMU_STAT 0x0608 /* PMU status */ +#define BCMA_CC_PMU_STAT_INTPEND 0x00000040 /* Interrupt pending */ +#define BCMA_CC_PMU_STAT_SBCLKST 0x00000030 /* Backplane clock status? */ +#define BCMA_CC_PMU_STAT_HAVEALP 0x00000008 /* ALP available */ +#define BCMA_CC_PMU_STAT_HAVEHT 0x00000004 /* HT available */ +#define BCMA_CC_PMU_STAT_RESINIT 0x00000003 /* Res init */ +#define BCMA_CC_PMU_RES_STAT 0x060C /* PMU res status */ +#define BCMA_CC_PMU_RES_PEND 0x0610 /* PMU res pending */ +#define BCMA_CC_PMU_TIMER 0x0614 /* PMU timer */ +#define BCMA_CC_PMU_MINRES_MSK 0x0618 /* PMU min res mask */ +#define BCMA_CC_PMU_MAXRES_MSK 0x061C /* PMU max res mask */ +#define BCMA_CC_PMU_RES_TABSEL 0x0620 /* PMU res table sel */ +#define BCMA_CC_PMU_RES_DEPMSK 0x0624 /* PMU res dep mask */ +#define BCMA_CC_PMU_RES_UPDNTM 0x0628 /* PMU res updown timer */ +#define BCMA_CC_PMU_RES_TIMER 0x062C /* PMU res timer */ +#define BCMA_CC_PMU_CLKSTRETCH 0x0630 /* PMU clockstretch */ +#define BCMA_CC_PMU_WATCHDOG 0x0634 /* PMU watchdog */ +#define BCMA_CC_PMU_RES_REQTS 0x0640 /* PMU res req timer sel */ +#define BCMA_CC_PMU_RES_REQT 0x0644 /* PMU res req timer */ +#define BCMA_CC_PMU_RES_REQM 0x0648 /* PMU res req mask */ +#define BCMA_CC_CHIPCTL_ADDR 0x0650 +#define BCMA_CC_CHIPCTL_DATA 0x0654 +#define BCMA_CC_REGCTL_ADDR 0x0658 +#define BCMA_CC_REGCTL_DATA 0x065C +#define BCMA_CC_PLLCTL_ADDR 0x0660 +#define BCMA_CC_PLLCTL_DATA 0x0664 + +/* Data for the PMU, if available. + * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) + */ +struct bcma_chipcommon_pmu { + u8 rev; /* PMU revision */ + u32 crystalfreq; /* The active crystal frequency (in kHz) */ +}; + +struct bcma_drv_cc { + struct bcma_device *core; + u32 status; + u32 capabilities; + u32 capabilities_ext; + /* Fast Powerup Delay constant */ + u16 fast_pwrup_delay; + struct bcma_chipcommon_pmu pmu; +}; + +/* Register access */ +#define bcma_cc_read32(cc, offset) \ + bcma_read32((cc)->core, offset) +#define bcma_cc_write32(cc, offset, val) \ + bcma_write32((cc)->core, offset, val) + +#define bcma_cc_mask32(cc, offset, mask) \ + bcma_cc_write32(cc, offset, bcma_cc_read32(cc, offset) & (mask)) +#define bcma_cc_set32(cc, offset, set) \ + bcma_cc_write32(cc, offset, bcma_cc_read32(cc, offset) | (set)) +#define bcma_cc_maskset32(cc, offset, mask, set) \ + bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set)) + +extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc); + +extern void bcma_chipco_suspend(struct bcma_drv_cc *cc); +extern void bcma_chipco_resume(struct bcma_drv_cc *cc); + +extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, + u32 ticks); + +void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value); + +u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask); + +/* Chipcommon GPIO pin access. */ +u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask); +u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value); +u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value); +u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value); +u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value); +u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value); + +/* PMU support */ +extern void bcma_pmu_init(struct bcma_drv_cc *cc); + +#endif /* LINUX_BCMA_DRIVER_CC_H_ */ diff --git a/include/linux/bcma/bcma_driver_pci.h b/include/linux/bcma/bcma_driver_pci.h new file mode 100644 index 000000000000..b7e191cf00ec --- /dev/null +++ b/include/linux/bcma/bcma_driver_pci.h @@ -0,0 +1,89 @@ +#ifndef LINUX_BCMA_DRIVER_PCI_H_ +#define LINUX_BCMA_DRIVER_PCI_H_ + +#include + +struct pci_dev; + +/** PCI core registers. **/ +#define BCMA_CORE_PCI_CTL 0x0000 /* PCI Control */ +#define BCMA_CORE_PCI_CTL_RST_OE 0x00000001 /* PCI_RESET Output Enable */ +#define BCMA_CORE_PCI_CTL_RST 0x00000002 /* PCI_RESET driven out to pin */ +#define BCMA_CORE_PCI_CTL_CLK_OE 0x00000004 /* Clock gate Output Enable */ +#define BCMA_CORE_PCI_CTL_CLK 0x00000008 /* Gate for clock driven out to pin */ +#define BCMA_CORE_PCI_ARBCTL 0x0010 /* PCI Arbiter Control */ +#define BCMA_CORE_PCI_ARBCTL_INTERN 0x00000001 /* Use internal arbiter */ +#define BCMA_CORE_PCI_ARBCTL_EXTERN 0x00000002 /* Use external arbiter */ +#define BCMA_CORE_PCI_ARBCTL_PARKID 0x00000006 /* Mask, selects which agent is parked on an idle bus */ +#define BCMA_CORE_PCI_ARBCTL_PARKID_LAST 0x00000000 /* Last requestor */ +#define BCMA_CORE_PCI_ARBCTL_PARKID_4710 0x00000002 /* 4710 */ +#define BCMA_CORE_PCI_ARBCTL_PARKID_EXT0 0x00000004 /* External requestor 0 */ +#define BCMA_CORE_PCI_ARBCTL_PARKID_EXT1 0x00000006 /* External requestor 1 */ +#define BCMA_CORE_PCI_ISTAT 0x0020 /* Interrupt status */ +#define BCMA_CORE_PCI_ISTAT_INTA 0x00000001 /* PCI INTA# */ +#define BCMA_CORE_PCI_ISTAT_INTB 0x00000002 /* PCI INTB# */ +#define BCMA_CORE_PCI_ISTAT_SERR 0x00000004 /* PCI SERR# (write to clear) */ +#define BCMA_CORE_PCI_ISTAT_PERR 0x00000008 /* PCI PERR# (write to clear) */ +#define BCMA_CORE_PCI_ISTAT_PME 0x00000010 /* PCI PME# */ +#define BCMA_CORE_PCI_IMASK 0x0024 /* Interrupt mask */ +#define BCMA_CORE_PCI_IMASK_INTA 0x00000001 /* PCI INTA# */ +#define BCMA_CORE_PCI_IMASK_INTB 0x00000002 /* PCI INTB# */ +#define BCMA_CORE_PCI_IMASK_SERR 0x00000004 /* PCI SERR# */ +#define BCMA_CORE_PCI_IMASK_PERR 0x00000008 /* PCI PERR# */ +#define BCMA_CORE_PCI_IMASK_PME 0x00000010 /* PCI PME# */ +#define BCMA_CORE_PCI_MBOX 0x0028 /* Backplane to PCI Mailbox */ +#define BCMA_CORE_PCI_MBOX_F0_0 0x00000100 /* PCI function 0, INT 0 */ +#define BCMA_CORE_PCI_MBOX_F0_1 0x00000200 /* PCI function 0, INT 1 */ +#define BCMA_CORE_PCI_MBOX_F1_0 0x00000400 /* PCI function 1, INT 0 */ +#define BCMA_CORE_PCI_MBOX_F1_1 0x00000800 /* PCI function 1, INT 1 */ +#define BCMA_CORE_PCI_MBOX_F2_0 0x00001000 /* PCI function 2, INT 0 */ +#define BCMA_CORE_PCI_MBOX_F2_1 0x00002000 /* PCI function 2, INT 1 */ +#define BCMA_CORE_PCI_MBOX_F3_0 0x00004000 /* PCI function 3, INT 0 */ +#define BCMA_CORE_PCI_MBOX_F3_1 0x00008000 /* PCI function 3, INT 1 */ +#define BCMA_CORE_PCI_BCAST_ADDR 0x0050 /* Backplane Broadcast Address */ +#define BCMA_CORE_PCI_BCAST_ADDR_MASK 0x000000FF +#define BCMA_CORE_PCI_BCAST_DATA 0x0054 /* Backplane Broadcast Data */ +#define BCMA_CORE_PCI_GPIO_IN 0x0060 /* rev >= 2 only */ +#define BCMA_CORE_PCI_GPIO_OUT 0x0064 /* rev >= 2 only */ +#define BCMA_CORE_PCI_GPIO_ENABLE 0x0068 /* rev >= 2 only */ +#define BCMA_CORE_PCI_GPIO_CTL 0x006C /* rev >= 2 only */ +#define BCMA_CORE_PCI_SBTOPCI0 0x0100 /* Backplane to PCI translation 0 (sbtopci0) */ +#define BCMA_CORE_PCI_SBTOPCI0_MASK 0xFC000000 +#define BCMA_CORE_PCI_SBTOPCI1 0x0104 /* Backplane to PCI translation 1 (sbtopci1) */ +#define BCMA_CORE_PCI_SBTOPCI1_MASK 0xFC000000 +#define BCMA_CORE_PCI_SBTOPCI2 0x0108 /* Backplane to PCI translation 2 (sbtopci2) */ +#define BCMA_CORE_PCI_SBTOPCI2_MASK 0xC0000000 +#define BCMA_CORE_PCI_PCICFG0 0x0400 /* PCI config space 0 (rev >= 8) */ +#define BCMA_CORE_PCI_PCICFG1 0x0500 /* PCI config space 1 (rev >= 8) */ +#define BCMA_CORE_PCI_PCICFG2 0x0600 /* PCI config space 2 (rev >= 8) */ +#define BCMA_CORE_PCI_PCICFG3 0x0700 /* PCI config space 3 (rev >= 8) */ +#define BCMA_CORE_PCI_SPROM(wordoffset) (0x0800 + ((wordoffset) * 2)) /* SPROM shadow area (72 bytes) */ + +/* SBtoPCIx */ +#define BCMA_CORE_PCI_SBTOPCI_MEM 0x00000000 +#define BCMA_CORE_PCI_SBTOPCI_IO 0x00000001 +#define BCMA_CORE_PCI_SBTOPCI_CFG0 0x00000002 +#define BCMA_CORE_PCI_SBTOPCI_CFG1 0x00000003 +#define BCMA_CORE_PCI_SBTOPCI_PREF 0x00000004 /* Prefetch enable */ +#define BCMA_CORE_PCI_SBTOPCI_BURST 0x00000008 /* Burst enable */ +#define BCMA_CORE_PCI_SBTOPCI_MRM 0x00000020 /* Memory Read Multiple */ +#define BCMA_CORE_PCI_SBTOPCI_RC 0x00000030 /* Read Command mask (rev >= 11) */ +#define BCMA_CORE_PCI_SBTOPCI_RC_READ 0x00000000 /* Memory read */ +#define BCMA_CORE_PCI_SBTOPCI_RC_READL 0x00000010 /* Memory read line */ +#define BCMA_CORE_PCI_SBTOPCI_RC_READM 0x00000020 /* Memory read multiple */ + +/* PCIcore specific boardflags */ +#define BCMA_CORE_PCI_BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ + +struct bcma_drv_pci { + struct bcma_device *core; + u8 setup_done:1; +}; + +/* Register access */ +#define pcicore_read32(pc, offset) bcma_read32((pc)->core, offset) +#define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val) + +extern void bcma_core_pci_init(struct bcma_drv_pci *pc); + +#endif /* LINUX_BCMA_DRIVER_PCI_H_ */ diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h new file mode 100644 index 000000000000..f82d88a960ce --- /dev/null +++ b/include/linux/bcma/bcma_regs.h @@ -0,0 +1,34 @@ +#ifndef LINUX_BCMA_REGS_H_ +#define LINUX_BCMA_REGS_H_ + +/* Agent registers (common for every core) */ +#define BCMA_IOCTL 0x0408 +#define BCMA_IOCTL_CLK 0x0001 +#define BCMA_IOCTL_FGC 0x0002 +#define BCMA_IOCTL_CORE_BITS 0x3FFC +#define BCMA_IOCTL_PME_EN 0x4000 +#define BCMA_IOCTL_BIST_EN 0x8000 +#define BCMA_RESET_CTL 0x0800 +#define BCMA_RESET_CTL_RESET 0x0001 + +/* BCMA PCI config space registers. */ +#define BCMA_PCI_PMCSR 0x44 +#define BCMA_PCI_PE 0x100 +#define BCMA_PCI_BAR0_WIN 0x80 /* Backplane address space 0 */ +#define BCMA_PCI_BAR1_WIN 0x84 /* Backplane address space 1 */ +#define BCMA_PCI_SPROMCTL 0x88 /* SPROM control */ +#define BCMA_PCI_SPROMCTL_WE 0x10 /* SPROM write enable */ +#define BCMA_PCI_BAR1_CONTROL 0x8c /* Address space 1 burst control */ +#define BCMA_PCI_IRQS 0x90 /* PCI interrupts */ +#define BCMA_PCI_IRQMASK 0x94 /* PCI IRQ control and mask (pcirev >= 6 only) */ +#define BCMA_PCI_BACKPLANE_IRQS 0x98 /* Backplane Interrupts */ +#define BCMA_PCI_BAR0_WIN2 0xAC +#define BCMA_PCI_GPIO_IN 0xB0 /* GPIO Input (pcirev >= 3 only) */ +#define BCMA_PCI_GPIO_OUT 0xB4 /* GPIO Output (pcirev >= 3 only) */ +#define BCMA_PCI_GPIO_OUT_ENABLE 0xB8 /* GPIO Output Enable/Disable (pcirev >= 3 only) */ +#define BCMA_PCI_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ +#define BCMA_PCI_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */ +#define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ +#define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ + +#endif /* LINUX_BCMA_REGS_H_ */ diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 48c007dae476..ae28e93fd072 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -382,6 +382,23 @@ struct ssb_device_id { #define SSB_ANY_ID 0xFFFF #define SSB_ANY_REV 0xFF +/* Broadcom's specific AMBA core, see drivers/bcma/ */ +struct bcma_device_id { + __u16 manuf; + __u16 id; + __u8 rev; + __u8 class; +}; +#define BCMA_CORE(_manuf, _id, _rev, _class) \ + { .manuf = _manuf, .id = _id, .rev = _rev, .class = _class, } +#define BCMA_CORETABLE_END \ + { 0, }, + +#define BCMA_ANY_MANUF 0xFFFF +#define BCMA_ANY_ID 0xFFFF +#define BCMA_ANY_REV 0xFF +#define BCMA_ANY_CLASS 0xFF + struct virtio_device_id { __u32 device; __u32 vendor; diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 88f3f07205f8..e26e2fb462d4 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -702,6 +702,24 @@ static int do_ssb_entry(const char *filename, return 1; } +/* Looks like: bcma:mNidNrevNclN. */ +static int do_bcma_entry(const char *filename, + struct bcma_device_id *id, char *alias) +{ + id->manuf = TO_NATIVE(id->manuf); + id->id = TO_NATIVE(id->id); + id->rev = TO_NATIVE(id->rev); + id->class = TO_NATIVE(id->class); + + strcpy(alias, "bcma:"); + ADD(alias, "m", id->manuf != BCMA_ANY_MANUF, id->manuf); + ADD(alias, "id", id->id != BCMA_ANY_ID, id->id); + ADD(alias, "rev", id->rev != BCMA_ANY_REV, id->rev); + ADD(alias, "cl", id->class != BCMA_ANY_CLASS, id->class); + add_wildcard(alias); + return 1; +} + /* Looks like: virtio:dNvN */ static int do_virtio_entry(const char *filename, struct virtio_device_id *id, char *alias) @@ -968,6 +986,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, do_table(symval, sym->st_size, sizeof(struct ssb_device_id), "ssb", do_ssb_entry, mod); + else if (sym_is(symname, "__mod_bcma_device_table")) + do_table(symval, sym->st_size, + sizeof(struct bcma_device_id), "bcma", + do_bcma_entry, mod); else if (sym_is(symname, "__mod_virtio_device_table")) do_table(symval, sym->st_size, sizeof(struct virtio_device_id), "virtio", -- cgit v1.2.3-58-ga151 From 7cc5eb629cefa9a40295ff5ee4b1ec41ad855e8d Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 9 May 2011 19:00:18 -0700 Subject: mwifiex: remove unnecessary struct mwifiex_opt_sleep_confirm_buffer The structure definition is struct mwifiex_opt_sleep_confirm_buffer { u8 hdr[4]; struct mwifiex_opt_sleep_confirm ps_cfm_sleep; } __packed; For sleep_confirm command we already reserve 4 bytes (using skb_reserve()) for an interface header. It will be filled later by interface specific code. We don't need "hdr[4]" element in above structure. So we can use "struct mwifiex_opt_sleep_confirm" directly instead of "struct mwifiex_opt_sleep_confirm_buffer". Signed-off-by: Amitkumar Karwar Signed-off-by: Yogesh Ashok Powar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cmdevt.c | 17 ++++++++--------- drivers/net/wireless/mwifiex/fw.h | 5 ----- drivers/net/wireless/mwifiex/init.c | 26 ++++++++++++-------------- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 1c8b4f7cba47..5c7539932c27 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -223,24 +223,23 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) { int ret; - u16 cmd_len; struct mwifiex_private *priv; - struct mwifiex_opt_sleep_confirm_buffer *sleep_cfm_buf = - (struct mwifiex_opt_sleep_confirm_buffer *) + struct mwifiex_opt_sleep_confirm *sleep_cfm_buf = + (struct mwifiex_opt_sleep_confirm *) adapter->sleep_cfm->data; - cmd_len = sizeof(struct mwifiex_opt_sleep_confirm); priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - sleep_cfm_buf->ps_cfm_sleep.seq_num = + sleep_cfm_buf->seq_num = cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO (adapter->seq_num, priv->bss_num, priv->bss_type))); adapter->seq_num++; + skb_push(adapter->sleep_cfm, INTF_HEADER_LEN); ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, adapter->sleep_cfm->data, - adapter->sleep_cfm->len + - INTF_HEADER_LEN, NULL); + adapter->sleep_cfm->len, NULL); + skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN); if (ret == -1) { dev_err(adapter->dev, "SLEEP_CFM: failed\n"); @@ -249,14 +248,14 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) } if (GET_BSS_ROLE(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY)) == MWIFIEX_BSS_ROLE_STA) { - if (!sleep_cfm_buf->ps_cfm_sleep.resp_ctrl) + if (!sleep_cfm_buf->resp_ctrl) /* Response is not needed for sleep confirm command */ adapter->ps_state = PS_STATE_SLEEP; else adapter->ps_state = PS_STATE_SLEEP_CFM; - if (!sleep_cfm_buf->ps_cfm_sleep.resp_ctrl + if (!sleep_cfm_buf->resp_ctrl && (adapter->is_hs_configured && !adapter->sleep_period.period)) { adapter->pm_wakeup_card_req = true; diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 6d1c4545eda6..c6b26819cd38 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -1198,9 +1198,4 @@ struct mwifiex_opt_sleep_confirm { __le16 action; __le16 resp_ctrl; } __packed; - -struct mwifiex_opt_sleep_confirm_buffer { - u8 hdr[4]; - struct mwifiex_opt_sleep_confirm ps_cfm_sleep; -} __packed; #endif /* !_MWIFIEX_FW_H_ */ diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 6a8fd9989a23..3f1559e61320 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -175,7 +175,7 @@ static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) } adapter->sleep_cfm = - dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm_buffer) + dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm) + INTF_HEADER_LEN); if (!adapter->sleep_cfm) { @@ -197,10 +197,10 @@ static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) */ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) { - struct mwifiex_opt_sleep_confirm_buffer *sleep_cfm_buf = NULL; + struct mwifiex_opt_sleep_confirm *sleep_cfm_buf = NULL; - skb_put(adapter->sleep_cfm, sizeof(sleep_cfm_buf->ps_cfm_sleep)); - sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm_buffer *) + skb_put(adapter->sleep_cfm, sizeof(struct mwifiex_opt_sleep_confirm)); + sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *) (adapter->sleep_cfm->data); adapter->cmd_sent = false; @@ -268,16 +268,14 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) mwifiex_wmm_init(adapter); if (adapter->sleep_cfm) { - memset(&sleep_cfm_buf->ps_cfm_sleep, 0, - adapter->sleep_cfm->len); - sleep_cfm_buf->ps_cfm_sleep.command = - cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); - sleep_cfm_buf->ps_cfm_sleep.size = - cpu_to_le16(adapter->sleep_cfm->len); - sleep_cfm_buf->ps_cfm_sleep.result = 0; - sleep_cfm_buf->ps_cfm_sleep.action = cpu_to_le16(SLEEP_CONFIRM); - sleep_cfm_buf->ps_cfm_sleep.resp_ctrl = - cpu_to_le16(RESP_NEEDED); + memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len); + sleep_cfm_buf->command = + cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); + sleep_cfm_buf->size = + cpu_to_le16(adapter->sleep_cfm->len); + sleep_cfm_buf->result = 0; + sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM); + sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED); } memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params)); memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); -- cgit v1.2.3-58-ga151 From cc4c4353f0ebde05992bf360f16ec92260811393 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Fri, 8 Apr 2011 10:50:52 -0400 Subject: tipc: Update comments in message header include file Removes comments in TIPC's message header include file that are outdated and/or unnecessary. Also introduces short comments (or supplements existing ones) to better describe several set of existing symbolic constants. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/msg.h | 89 +++++++++++++++------------------------------------------- 1 file changed, 23 insertions(+), 66 deletions(-) diff --git a/net/tipc/msg.h b/net/tipc/msg.h index de02339fc175..d098317a513a 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -39,41 +39,24 @@ #include "bearer.h" +/* + * Constants and routines used to read and write TIPC payload message headers + * + * Note: Some items are also used with TIPC internal message headers + */ + #define TIPC_VERSION 2 /* - * TIPC user data message header format, version 2: - * - * - * 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * w0:|vers | user |hdr sz |n|d|s|-| message size | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * w1:|mstyp| error |rer cnt|lsc|opt p| broadcast ack no | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * w2:| link level ack no | broadcast/link level seq no | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * w3:| previous node | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * w4:| originating port | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * w5:| destination port | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * w6:| originating node | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * w7:| destination node | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * w8:| name type / transport sequence number | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * w9:| name instance/multicast lower bound | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * wA:| multicast upper bound | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * / / - * \ options \ - * / / - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * + * Payload message users are defined in TIPC's public API: + * - TIPC_LOW_IMPORTANCE + * - TIPC_MEDIUM_IMPORTANCE + * - TIPC_HIGH_IMPORTANCE + * - TIPC_CRITICAL_IMPORTANCE + */ + +/* + * Payload message types */ #define TIPC_CONN_MSG 0 @@ -81,6 +64,9 @@ #define TIPC_NAMED_MSG 2 #define TIPC_DIRECT_MSG 3 +/* + * Message header sizes + */ #define SHORT_H_SIZE 24 /* Connected, in-cluster messages */ #define DIR_MSG_H_SIZE 32 /* Directly addressed messages */ @@ -473,40 +459,11 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) /* - TIPC internal message header format, version 2 - - 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w0:|vers |msg usr|hdr sz |n|resrv| packet size | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w1:|m typ| sequence gap | broadcast ack no | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w2:| link level ack no/bc_gap_from | seq no / bcast_gap_to | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w3:| previous node | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w4:| next sent broadcast/fragm no | next sent pkt/ fragm msg no | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w5:| session no |rsv=0|r|berid|link prio|netpl|p| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w6:| originating node | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w7:| destination node | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w8:| transport sequence number | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - w9:| msg count / bcast tag | link tolerance | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - \ \ - / User Specific Data / - \ \ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - NB: CONN_MANAGER use data message format. LINK_CONFIG has own format. -*/ + * Constants and routines used to read and write TIPC internal message headers + */ /* - * Internal users + * Internal message users */ #define BCAST_PROTOCOL 5 @@ -520,7 +477,7 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) #define LINK_CONFIG 13 /* - * Connection management protocol messages + * Connection management protocol message types */ #define CONN_PROBE 0 @@ -528,7 +485,7 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) #define CONN_ACK 2 /* - * Name distributor messages + * Name distributor message types */ #define PUBLICATION 0 -- cgit v1.2.3-58-ga151 From 19f53d2cef97506364638c647a3aa11291819896 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Fri, 8 Apr 2011 10:59:04 -0400 Subject: tipc: Eliminate unused routing message definitions Gets rid of unused constants defining the types used in routing messages. These messages no longer exist in TIPC now that multicluster and multizone support has been eliminated. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/msg.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/net/tipc/msg.h b/net/tipc/msg.h index d098317a513a..c5593ac3da94 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -740,15 +740,6 @@ static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n) #define DUPLICATE_MSG 0 #define ORIGINAL_MSG 1 -/* - * Routing table message types - */ -#define EXT_ROUTING_TABLE 0 -#define LOCAL_ROUTING_TABLE 1 /* obsoleted */ -#define SLAVE_ROUTING_TABLE 2 -#define ROUTE_ADDITION 3 -#define ROUTE_REMOVAL 4 - /* * Config protocol message types */ -- cgit v1.2.3-58-ga151 From 92138d1f254d58b818e7c3b91a1967cf57d374b5 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Fri, 8 Apr 2011 11:04:15 -0400 Subject: tipc: Cosmetic consolidation of internal message type definitions Half of the #define entries in msg.h were down at the bottom of the header, instead of up at the top before any of the static inlines etc. Relocate them up to the top, to be consistent with the other normal linux header file layout conventions. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/msg.h | 58 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/net/tipc/msg.h b/net/tipc/msg.h index c5593ac3da94..005b318fd328 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -491,6 +491,35 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) #define PUBLICATION 0 #define WITHDRAWAL 1 +/* + * Segmentation message types + */ + +#define FIRST_FRAGMENT 0 +#define FRAGMENT 1 +#define LAST_FRAGMENT 2 + +/* + * Link management protocol message types + */ + +#define STATE_MSG 0 +#define RESET_MSG 1 +#define ACTIVATE_MSG 2 + +/* + * Changeover tunnel message types + */ +#define DUPLICATE_MSG 0 +#define ORIGINAL_MSG 1 + +/* + * Config protocol message types + */ + +#define DSC_REQ_MSG 0 +#define DSC_RESP_MSG 1 + /* * Word 1 @@ -718,35 +747,6 @@ static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n) msg_set_bits(m, 9, 0, 0xffff, n); } -/* - * Segmentation message types - */ - -#define FIRST_FRAGMENT 0 -#define FRAGMENT 1 -#define LAST_FRAGMENT 2 - -/* - * Link management protocol message types - */ - -#define STATE_MSG 0 -#define RESET_MSG 1 -#define ACTIVATE_MSG 2 - -/* - * Changeover tunnel message types - */ -#define DUPLICATE_MSG 0 -#define ORIGINAL_MSG 1 - -/* - * Config protocol message types - */ - -#define DSC_REQ_MSG 0 -#define DSC_RESP_MSG 1 - u32 tipc_msg_tot_importance(struct tipc_msg *m); void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, u32 destnode); -- cgit v1.2.3-58-ga151 From 7775bcc722ed9993e83401fee9c14008843b83c7 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 12 Apr 2011 14:59:03 -0400 Subject: tipc: Remove code to emulate loss of broadcast messages Eliminates optional code used to test TIPC's ability to recover from lost broadcast messages. This code duplicates functionality already provided by the network stack's QoS option "network emulator". Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/bcast.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 7dc1dc7151ea..08e3216a33d2 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -44,13 +44,6 @@ #define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ -/* - * Loss rate for incoming broadcast frames; used to test retransmission code. - * Set to N to cause every N'th frame to be discarded; 0 => don't discard any. - */ - -#define TIPC_BCAST_LOSS_RATE 0 - /** * struct bcbearer_pair - a pair of bearers used by broadcast link * @primary: pointer to primary bearer @@ -434,9 +427,6 @@ int tipc_bclink_send_msg(struct sk_buff *buf) void tipc_bclink_recv_pkt(struct sk_buff *buf) { -#if (TIPC_BCAST_LOSS_RATE) - static int rx_count; -#endif struct tipc_msg *msg = buf_msg(buf); struct tipc_node *node = tipc_node_find(msg_prevnode(msg)); u32 next_in; @@ -470,14 +460,6 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) return; } -#if (TIPC_BCAST_LOSS_RATE) - if (++rx_count == TIPC_BCAST_LOSS_RATE) { - rx_count = 0; - buf_discard(buf); - return; - } -#endif - tipc_node_lock(node); receive: deferred = node->bclink.deferred_head; -- cgit v1.2.3-58-ga151 From 670c54083aa6e0eeefda1c4b307a91679b577664 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 17 Apr 2011 10:29:16 -0400 Subject: tipc: Don't initialize link selector field in fragmented messages Eliminates code that sets the link selector field in the header of fragmented messages, since this information is never referenced. (The unnecessary initialization was harmless as it was over-written by the fragmented message identifier value before the fragments were transmitted.) Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/link.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index ebf338f7b14e..95249ba6e2d6 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1169,7 +1169,6 @@ again: tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, INT_H_SIZE, msg_destnode(hdr)); - msg_set_link_selector(&fragm_hdr, sender->ref); msg_set_size(&fragm_hdr, max_pkt); msg_set_fragm_no(&fragm_hdr, 1); @@ -2427,7 +2426,6 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, INT_H_SIZE, destaddr); - msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg)); msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++)); msg_set_fragm_no(&fragm_hdr, fragm_no); l_ptr->stats.sent_fragmented++; -- cgit v1.2.3-58-ga151 From e0f085964cac97a3a9e47741365ef6a03e500873 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 17 Apr 2011 11:44:24 -0400 Subject: tipc: Avoid pointless masking of fragmented message identifier Eliminates code that restricts a link's counter of its fragmented messages to a 16-bit value, since the counter value is automatically restricted to this range when it is written into the message header. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/link.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 95249ba6e2d6..ad356df12d1e 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1276,7 +1276,7 @@ reject: /* Append whole chain to send queue: */ buf = buf_chain; - l_ptr->long_msg_seq_no = mod(l_ptr->long_msg_seq_no + 1); + l_ptr->long_msg_seq_no++; if (!l_ptr->next_out) l_ptr->next_out = buf_chain; l_ptr->stats.sent_fragmented++; @@ -2426,7 +2426,7 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, INT_H_SIZE, destaddr); - msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++)); + msg_set_long_msgno(&fragm_hdr, l_ptr->long_msg_seq_no++); msg_set_fragm_no(&fragm_hdr, fragm_no); l_ptr->stats.sent_fragmented++; -- cgit v1.2.3-58-ga151 From 77561557447d3be586e701815e261c93c11ded00 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 17 Apr 2011 13:06:23 -0400 Subject: tipc: Fix issues with fragmentation of an existing message buffer Modifies the routine that fragments an existing message buffer to use similar logic to that used when generating fragments from an iovec. The routine now creates a complete chain of fragments and adds them to the link transmit queue as a unit, so that the link sends all fragments or none; this prevents the incomplete transmission of a fragmented message that might otherwise result because of link congestion or memory exhaustion. This change also ensures that the counter recording the number of fragmented messages sent by the link is now incremented only if the message is actually sent. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/link.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index ad356df12d1e..02b083e5c219 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -2406,6 +2406,8 @@ void tipc_link_recv_bundle(struct sk_buff *buf) */ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) { + struct sk_buff *buf_chain = NULL; + struct sk_buff *buf_chain_tail = (struct sk_buff *)&buf_chain; struct tipc_msg *inmsg = buf_msg(buf); struct tipc_msg fragm_hdr; u32 insize = msg_size(inmsg); @@ -2414,7 +2416,7 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) u32 rest = insize; u32 pack_sz = l_ptr->max_pkt; u32 fragm_sz = pack_sz - INT_H_SIZE; - u32 fragm_no = 1; + u32 fragm_no = 0; u32 destaddr; if (msg_short(inmsg)) @@ -2426,9 +2428,6 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, INT_H_SIZE, destaddr); - msg_set_long_msgno(&fragm_hdr, l_ptr->long_msg_seq_no++); - msg_set_fragm_no(&fragm_hdr, fragm_no); - l_ptr->stats.sent_fragmented++; /* Chop up message: */ @@ -2441,27 +2440,37 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) } fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE); if (fragm == NULL) { - warn("Link unable to fragment message\n"); - dsz = -ENOMEM; - goto exit; + buf_discard(buf); + while (buf_chain) { + buf = buf_chain; + buf_chain = buf_chain->next; + buf_discard(buf); + } + return -ENOMEM; } msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); + fragm_no++; + msg_set_fragm_no(&fragm_hdr, fragm_no); skb_copy_to_linear_data(fragm, &fragm_hdr, INT_H_SIZE); skb_copy_to_linear_data_offset(fragm, INT_H_SIZE, crs, fragm_sz); - /* Send queued messages first, if any: */ + buf_chain_tail->next = fragm; + buf_chain_tail = fragm; - l_ptr->stats.sent_fragments++; - tipc_link_send_buf(l_ptr, fragm); - if (!tipc_link_is_up(l_ptr)) - return dsz; - msg_set_fragm_no(&fragm_hdr, ++fragm_no); rest -= fragm_sz; crs += fragm_sz; msg_set_type(&fragm_hdr, FRAGMENT); } -exit: buf_discard(buf); + + /* Append chain of fragments to send queue & send them */ + + l_ptr->long_msg_seq_no++; + link_add_chain_to_outqueue(l_ptr, buf_chain, l_ptr->long_msg_seq_no); + l_ptr->stats.sent_fragments += fragm_no; + l_ptr->stats.sent_fragmented++; + tipc_link_push_queue(l_ptr); + return dsz; } -- cgit v1.2.3-58-ga151 From 53b94364a7c96d3b2276cb2bbbecfb269bc9f0fc Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 17 Apr 2011 16:02:11 -0400 Subject: tipc: Set name lookup scope field properly in all data messages Ensures that all outgoing data messages have the "name lookup scope" field of their header set correctly; that is, named multicast messages now specify cluster-wide name lookup, while messages not using TIPC naming zero out the lookup field. (Previously, the lookup scope specified for these types of messages was inherited from the last message sent by the sending port.) Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/port.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/tipc/port.c b/net/tipc/port.c index 6ff78f9c7d65..c2229c4b18ef 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -91,6 +91,7 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, hdr = &oport->phdr; msg_set_type(hdr, TIPC_MCAST_MSG); + msg_set_lookup_scope(hdr, TIPC_CLUSTER_SCOPE); msg_set_nametype(hdr, seq->type); msg_set_namelower(hdr, seq->lower); msg_set_nameupper(hdr, seq->upper); @@ -1065,6 +1066,7 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer) msg_set_orignode(msg, tipc_own_addr); msg_set_origport(msg, p_ptr->ref); msg_set_type(msg, TIPC_CONN_MSG); + msg_set_lookup_scope(msg, 0); msg_set_hdr_sz(msg, SHORT_H_SIZE); p_ptr->probing_interval = PROBING_INTERVAL; @@ -1276,6 +1278,7 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest, msg = &p_ptr->phdr; msg_set_type(msg, TIPC_DIRECT_MSG); + msg_set_lookup_scope(msg, 0); msg_set_orignode(msg, tipc_own_addr); msg_set_origport(msg, ref); msg_set_destnode(msg, dest->node); -- cgit v1.2.3-58-ga151 From 7462b9e9f69aa6c5e2fded65d3b03df4ed08ff45 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 18 Apr 2011 10:08:22 -0400 Subject: tipc: Fix problem with bundled multicast message Set the destination node and destination port fields of an outgoing multicast message header to zero; this is necessary to ensure that the receiving node can route the message properly if it was packed into a bundle due to link congestion. (Previously, there was a chance that the receiving node would send the unbundled message to a random node & port, rather than processing the message itself.) Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/port.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/tipc/port.c b/net/tipc/port.c index c2229c4b18ef..ac64037514f3 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -92,6 +92,8 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, hdr = &oport->phdr; msg_set_type(hdr, TIPC_MCAST_MSG); msg_set_lookup_scope(hdr, TIPC_CLUSTER_SCOPE); + msg_set_destport(hdr, 0); + msg_set_destnode(hdr, 0); msg_set_nametype(hdr, seq->type); msg_set_namelower(hdr, seq->lower); msg_set_nameupper(hdr, seq->upper); -- cgit v1.2.3-58-ga151 From 7f47f5c751c93f2ca9e7f0ef6c0915162ac9e076 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 18 Apr 2011 10:14:26 -0400 Subject: tipc: Update destination node field on incoming multicast messages Sets the destination node field of an incoming multicast message to the receiving node's network address before handing off the message to each receiving port. This ensures that, in the event the destination port returns the message to the sender, the sender can identify which node the destination port belonged to. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/port.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/tipc/port.c b/net/tipc/port.c index ac64037514f3..9f2ff12cf436 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -164,6 +164,7 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp) /* Deliver a copy of message to each destination port */ if (dp->count != 0) { + msg_set_destnode(msg, tipc_own_addr); if (dp->count == 1) { msg_set_destport(msg, dp->ports[0]); tipc_port_recv_msg(buf); -- cgit v1.2.3-58-ga151 From bebc55aeffa72d8198e5c54cab9973a30e92f854 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 19 Apr 2011 10:17:58 -0400 Subject: tipc: Fix sk_buff leaks when link congestion is detected Modifies a TIPC send routine that did not discard the outgoing sk_buff if it was not transmitted because of link congestion; this eliminates the potential for buffer leakage in the many callers who did not clean up the unsent buffer. (The two routines that previously did discard the unsent buffer have been updated to eliminate their now-redundant clean up.) Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/bcast.c | 4 +--- net/tipc/link.c | 7 +++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 08e3216a33d2..fa68d1e9ff4b 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -407,9 +407,7 @@ int tipc_bclink_send_msg(struct sk_buff *buf) spin_lock_bh(&bc_lock); res = tipc_link_send_buf(bcl, buf); - if (unlikely(res == -ELINKCONG)) - buf_discard(buf); - else + if (likely(res > 0)) bclink_set_last_sent(); bcl->stats.queue_sz_counts++; diff --git a/net/tipc/link.c b/net/tipc/link.c index 02b083e5c219..2a9f44a203eb 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -864,8 +864,9 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf) if (unlikely(queue_size >= queue_limit)) { if (imp <= TIPC_CRITICAL_IMPORTANCE) { - return link_schedule_port(l_ptr, msg_origport(msg), - size); + link_schedule_port(l_ptr, msg_origport(msg), size); + buf_discard(buf); + return -ELINKCONG; } buf_discard(buf); if (imp > CONN_MANAGER) { @@ -1069,8 +1070,6 @@ again: if (likely(buf)) { res = link_send_buf_fast(l_ptr, buf, &sender->max_pkt); - if (unlikely(res < 0)) - buf_discard(buf); exit: tipc_node_unlock(node); read_unlock_bh(&tipc_net_lock); -- cgit v1.2.3-58-ga151 From 1f3de471adf5c2a584480a6010808d7a17063897 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 19 Apr 2011 13:11:23 -0400 Subject: tipc: make zone/cluster mask constants a define This allows them to be available for easy re-use in other places and avoids trivial mistakes caused by "count the f's and 0's". Signed-off-by: Paul Gortmaker --- net/tipc/addr.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 8971aba99aea..e4f35afe3207 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h @@ -37,14 +37,17 @@ #ifndef _TIPC_ADDR_H #define _TIPC_ADDR_H +#define TIPC_ZONE_MASK 0xff000000u +#define TIPC_CLUSTER_MASK 0xfffff000u + static inline u32 tipc_zone_mask(u32 addr) { - return addr & 0xff000000u; + return addr & TIPC_ZONE_MASK; } static inline u32 tipc_cluster_mask(u32 addr) { - return addr & 0xfffff000u; + return addr & TIPC_CLUSTER_MASK; } static inline int in_own_cluster(u32 addr) -- cgit v1.2.3-58-ga151 From 66e019a6af827a254641e83e96ee36b0f4adc5e3 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Wed, 20 Apr 2011 16:24:07 -0500 Subject: tipc: Strengthen checks for neighboring node discovery Enhances existing checks on the discovery domain associated with a TIPC bearer. A bearer can no longer be configured to accept links from itself only (which would be pointless), or to nodes outside its own cluster (since multi-cluster support has now been removed from TIPC). Also, the neighbor discovery routine now validates link setup requests against the configured discovery domain for the bearer, rather than simply ensuring the requesting node belongs to the node's own cluster. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/bearer.c | 11 +++++++++-- net/tipc/discover.c | 7 +++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 411719feb803..f7c29af4ab81 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -493,8 +493,15 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) warn("Bearer <%s> rejected, illegal name\n", name); return -EINVAL; } - if (!tipc_addr_domain_valid(disc_domain) || - !tipc_in_scope(disc_domain, tipc_own_addr)) { + if (tipc_addr_domain_valid(disc_domain) && + (disc_domain != tipc_own_addr)) { + if (tipc_in_scope(disc_domain, tipc_own_addr)) { + disc_domain = tipc_own_addr & TIPC_CLUSTER_MASK; + res = 0; /* accept any node in own cluster */ + } else if (in_own_cluster(disc_domain)) + res = 0; /* accept specified node in own cluster */ + } + if (res) { warn("Bearer <%s> rejected, illegal discovery domain\n", name); return -EINVAL; } diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 491eff56b9da..d2163bd99e59 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -52,6 +52,7 @@ * struct link_req - information about an ongoing link setup request * @bearer: bearer issuing requests * @dest: destination address for request messages + * @domain: network domain to which links can be established * @buf: request message to be (repeatedly) sent * @timer: timer governing period between requests * @timer_intv: current interval between requests (in ms) @@ -59,6 +60,7 @@ struct link_req { struct tipc_bearer *bearer; struct tipc_media_addr dest; + u32 domain; struct sk_buff *buf; struct timer_list timer; unsigned int timer_intv; @@ -147,7 +149,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) } if (!tipc_in_scope(dest, tipc_own_addr)) return; - if (!in_own_cluster(orig)) + if (!tipc_in_scope(b_ptr->link_req->domain, orig)) return; /* Locate structure corresponding to requesting node */ @@ -287,7 +289,7 @@ static void disc_timeout(struct link_req *req) * tipc_disc_init_link_req - start sending periodic link setup requests * @b_ptr: ptr to bearer issuing requests * @dest: destination address for request messages - * @dest_domain: network domain of node(s) which should respond to message + * @dest_domain: network domain to which links can be established * * Returns pointer to link request structure, or NULL if unable to create. */ @@ -310,6 +312,7 @@ struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr, memcpy(&req->dest, dest, sizeof(*dest)); req->bearer = b_ptr; + req->domain = dest_domain; req->timer_intv = TIPC_LINK_REQ_INIT; k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); k_start_timer(&req->timer, req->timer_intv); -- cgit v1.2.3-58-ga151 From c29c3f70c9eb6f18090da5af9dbe9dcb4adece8c Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 20 Apr 2010 17:58:24 -0400 Subject: tipc: Abort excessive send requests as early as possible Adds checks to TIPC's socket send routines to promptly detect and abort attempts to send more than 66,000 bytes in a single TIPC message or more than 2**31-1 bytes in a single TIPC byte stream request. In addition, this ensures that the number of iovecs in a send request does not exceed the limits of a standard integer variable. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- include/linux/tipc.h | 2 +- net/tipc/socket.c | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/linux/tipc.h b/include/linux/tipc.h index a5b994a204d2..f2d90091cc20 100644 --- a/include/linux/tipc.h +++ b/include/linux/tipc.h @@ -101,7 +101,7 @@ static inline unsigned int tipc_node(__u32 addr) * Limiting values for messages */ -#define TIPC_MAX_USER_MSG_SIZE 66000 +#define TIPC_MAX_USER_MSG_SIZE 66000U /* * Message importance levels diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 29d94d53198d..e1c791798ba1 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -535,6 +535,9 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, if (unlikely((m->msg_namelen < sizeof(*dest)) || (dest->family != AF_TIPC))) return -EINVAL; + if ((total_len > TIPC_MAX_USER_MSG_SIZE) || + (m->msg_iovlen > (unsigned)INT_MAX)) + return -EMSGSIZE; if (iocb) lock_sock(sk); @@ -640,6 +643,10 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, if (unlikely(dest)) return send_msg(iocb, sock, m, total_len); + if ((total_len > TIPC_MAX_USER_MSG_SIZE) || + (m->msg_iovlen > (unsigned)INT_MAX)) + return -EMSGSIZE; + if (iocb) lock_sock(sk); @@ -723,6 +730,12 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, goto exit; } + if ((total_len > (unsigned)INT_MAX) || + (m->msg_iovlen > (unsigned)INT_MAX)) { + res = -EMSGSIZE; + goto exit; + } + /* * Send each iovec entry using one or more messages * -- cgit v1.2.3-58-ga151 From 2689690469c9fd76f9db0afcdf2523f48cce4006 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Thu, 21 Apr 2011 10:42:07 -0500 Subject: tipc: Avoid recomputation of outgoing message length Rework TIPC's message sending routines to take advantage of the total amount of data value passed to it by the kernel socket infrastructure. This change eliminates the need for TIPC to compute the size of outgoing messages itself, as well as the check for an oversize message in tipc_msg_build(). In addition, this change warrants an explanation: - res = send_packet(NULL, sock, &my_msg, 0); + res = send_packet(NULL, sock, &my_msg, bytes_to_send); Previously, the final argument to send_packet() was ignored (since the amount of data being sent was recalculated by a lower-level routine) and we could just pass in a dummy value (0). Now that the recalculation is being eliminated, the argument value being passed to send_packet() is significant and we have to supply the actual amount of data we want to send. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/link.c | 18 +++++++++++------- net/tipc/link.h | 1 + net/tipc/msg.c | 25 +++---------------------- net/tipc/msg.h | 5 ++--- net/tipc/port.c | 49 +++++++++++++++++++++++++++---------------------- net/tipc/port.h | 14 +++++++++----- net/tipc/socket.c | 14 +++++++++----- net/tipc/subscr.c | 4 ++-- 8 files changed, 64 insertions(+), 66 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 2a9f44a203eb..4bab139d5e74 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -92,7 +92,8 @@ static int link_recv_changeover_msg(struct link **l_ptr, struct sk_buff **buf); static void link_set_supervision_props(struct link *l_ptr, u32 tolerance); static int link_send_sections_long(struct tipc_port *sender, struct iovec const *msg_sect, - u32 num_sect, u32 destnode); + u32 num_sect, unsigned int total_len, + u32 destnode); static void link_check_defragm_bufs(struct link *l_ptr); static void link_state_event(struct link *l_ptr, u32 event); static void link_reset_statistics(struct link *l_ptr); @@ -1043,6 +1044,7 @@ int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode) int tipc_link_send_sections_fast(struct tipc_port *sender, struct iovec const *msg_sect, const u32 num_sect, + unsigned int total_len, u32 destaddr) { struct tipc_msg *hdr = &sender->phdr; @@ -1058,8 +1060,8 @@ again: * (Must not hold any locks while building message.) */ - res = tipc_msg_build(hdr, msg_sect, num_sect, sender->max_pkt, - !sender->user_port, &buf); + res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, + sender->max_pkt, !sender->user_port, &buf); read_lock_bh(&tipc_net_lock); node = tipc_node_find(destaddr); @@ -1104,7 +1106,8 @@ exit: goto again; return link_send_sections_long(sender, msg_sect, - num_sect, destaddr); + num_sect, total_len, + destaddr); } tipc_node_unlock(node); } @@ -1116,7 +1119,7 @@ exit: return tipc_reject_msg(buf, TIPC_ERR_NO_NODE); if (res >= 0) return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, - TIPC_ERR_NO_NODE); + total_len, TIPC_ERR_NO_NODE); return res; } @@ -1137,12 +1140,13 @@ exit: static int link_send_sections_long(struct tipc_port *sender, struct iovec const *msg_sect, u32 num_sect, + unsigned int total_len, u32 destaddr) { struct link *l_ptr; struct tipc_node *node; struct tipc_msg *hdr = &sender->phdr; - u32 dsz = msg_data_sz(hdr); + u32 dsz = total_len; u32 max_pkt, fragm_sz, rest; struct tipc_msg fragm_hdr; struct sk_buff *buf, *buf_chain, *prev; @@ -1269,7 +1273,7 @@ reject: buf_discard(buf_chain); } return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, - TIPC_ERR_NO_NODE); + total_len, TIPC_ERR_NO_NODE); } /* Append whole chain to send queue: */ diff --git a/net/tipc/link.h b/net/tipc/link.h index e6a30dbe1aaa..74fbecab1ea0 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -228,6 +228,7 @@ u32 tipc_link_get_max_pkt(u32 dest, u32 selector); int tipc_link_send_sections_fast(struct tipc_port *sender, struct iovec const *msg_sect, const u32 num_sect, + unsigned int total_len, u32 destnode); void tipc_link_recv_bundle(struct sk_buff *buf); int tipc_link_recv_fragment(struct sk_buff **pending, diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 6d92d17e7fb5..03e57bf92c73 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -67,20 +67,6 @@ void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, } } -/** - * tipc_msg_calc_data_size - determine total data size for message - */ - -int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) -{ - int dsz = 0; - int i; - - for (i = 0; i < num_sect; i++) - dsz += msg_sect[i].iov_len; - return dsz; -} - /** * tipc_msg_build - create message using specified header and data * @@ -89,18 +75,13 @@ int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) * Returns message data size or errno */ -int tipc_msg_build(struct tipc_msg *hdr, - struct iovec const *msg_sect, u32 num_sect, +int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, + u32 num_sect, unsigned int total_len, int max_size, int usrmem, struct sk_buff **buf) { int dsz, sz, hsz, pos, res, cnt; - dsz = tipc_msg_calc_data_size(msg_sect, num_sect); - if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) { - *buf = NULL; - return -EINVAL; - } - + dsz = total_len; pos = hsz = msg_hdr_sz(hdr); sz = hsz + dsz; msg_set_size(hdr, sz); diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 005b318fd328..8452454731fa 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -750,9 +750,8 @@ static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n) u32 tipc_msg_tot_importance(struct tipc_msg *m); void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, u32 destnode); -int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect); -int tipc_msg_build(struct tipc_msg *hdr, - struct iovec const *msg_sect, u32 num_sect, +int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, + u32 num_sect, unsigned int total_len, int max_size, int usrmem, struct sk_buff **buf); static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) diff --git a/net/tipc/port.c b/net/tipc/port.c index 9f2ff12cf436..c68dc956a423 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -74,7 +74,8 @@ static u32 port_peerport(struct tipc_port *p_ptr) */ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, - u32 num_sect, struct iovec const *msg_sect) + u32 num_sect, struct iovec const *msg_sect, + unsigned int total_len) { struct tipc_msg *hdr; struct sk_buff *buf; @@ -98,7 +99,7 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, msg_set_namelower(hdr, seq->lower); msg_set_nameupper(hdr, seq->upper); msg_set_hdr_sz(hdr, MCAST_H_SIZE); - res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, + res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, !oport->user_port, &buf); if (unlikely(!buf)) return res; @@ -418,12 +419,12 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, struct iovec const *msg_sect, u32 num_sect, - int err) + unsigned int total_len, int err) { struct sk_buff *buf; int res; - res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, + res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, !p_ptr->user_port, &buf); if (!buf) return res; @@ -1163,12 +1164,13 @@ int tipc_shutdown(u32 ref) */ static int tipc_port_recv_sections(struct tipc_port *sender, unsigned int num_sect, - struct iovec const *msg_sect) + struct iovec const *msg_sect, + unsigned int total_len) { struct sk_buff *buf; int res; - res = tipc_msg_build(&sender->phdr, msg_sect, num_sect, + res = tipc_msg_build(&sender->phdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, !sender->user_port, &buf); if (likely(buf)) tipc_port_recv_msg(buf); @@ -1179,7 +1181,8 @@ static int tipc_port_recv_sections(struct tipc_port *sender, unsigned int num_se * tipc_send - send message sections on connection */ -int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) +int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect, + unsigned int total_len) { struct tipc_port *p_ptr; u32 destnode; @@ -1194,9 +1197,10 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) destnode = port_peernode(p_ptr); if (likely(destnode != tipc_own_addr)) res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, - destnode); + total_len, destnode); else - res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect); + res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect, + total_len); if (likely(res != -ELINKCONG)) { p_ptr->congested = 0; @@ -1207,8 +1211,7 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) } if (port_unreliable(p_ptr)) { p_ptr->congested = 0; - /* Just calculate msg length and return */ - return tipc_msg_calc_data_size(msg_sect, num_sect); + return total_len; } return -ELINKCONG; } @@ -1218,7 +1221,8 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) */ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, - unsigned int num_sect, struct iovec const *msg_sect) + unsigned int num_sect, struct iovec const *msg_sect, + unsigned int total_len) { struct tipc_port *p_ptr; struct tipc_msg *msg; @@ -1245,23 +1249,23 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, if (likely(destport)) { if (likely(destnode == tipc_own_addr)) res = tipc_port_recv_sections(p_ptr, num_sect, - msg_sect); + msg_sect, total_len); else res = tipc_link_send_sections_fast(p_ptr, msg_sect, - num_sect, destnode); + num_sect, total_len, + destnode); if (likely(res != -ELINKCONG)) { if (res > 0) p_ptr->sent++; return res; } if (port_unreliable(p_ptr)) { - /* Just calculate msg length and return */ - return tipc_msg_calc_data_size(msg_sect, num_sect); + return total_len; } return -ELINKCONG; } return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect, - TIPC_ERR_NO_NAME); + total_len, TIPC_ERR_NO_NAME); } /** @@ -1269,7 +1273,8 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, */ int tipc_send2port(u32 ref, struct tipc_portid const *dest, - unsigned int num_sect, struct iovec const *msg_sect) + unsigned int num_sect, struct iovec const *msg_sect, + unsigned int total_len) { struct tipc_port *p_ptr; struct tipc_msg *msg; @@ -1289,18 +1294,18 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest, msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); if (dest->node == tipc_own_addr) - res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect); + res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect, + total_len); else res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, - dest->node); + total_len, dest->node); if (likely(res != -ELINKCONG)) { if (res > 0) p_ptr->sent++; return res; } if (port_unreliable(p_ptr)) { - /* Just calculate msg length and return */ - return tipc_msg_calc_data_size(msg_sect, num_sect); + return total_len; } return -ELINKCONG; } diff --git a/net/tipc/port.h b/net/tipc/port.h index 87b9424ae0ec..b9aa34195aec 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -205,23 +205,27 @@ int tipc_disconnect_port(struct tipc_port *tp_ptr); /* * TIPC messaging routines */ -int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect); +int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect, + unsigned int total_len); int tipc_send2name(u32 portref, struct tipc_name const *name, u32 domain, - unsigned int num_sect, struct iovec const *msg_sect); + unsigned int num_sect, struct iovec const *msg_sect, + unsigned int total_len); int tipc_send2port(u32 portref, struct tipc_portid const *dest, - unsigned int num_sect, struct iovec const *msg_sect); + unsigned int num_sect, struct iovec const *msg_sect, + unsigned int total_len); int tipc_send_buf2port(u32 portref, struct tipc_portid const *dest, struct sk_buff *buf, unsigned int dsz); int tipc_multicast(u32 portref, struct tipc_name_seq const *seq, - unsigned int section_count, struct iovec const *msg); + unsigned int section_count, struct iovec const *msg, + unsigned int total_len); int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, struct iovec const *msg_sect, u32 num_sect, - int err); + unsigned int total_len, int err); struct sk_buff *tipc_port_get_ports(void); void tipc_port_recv_proto_msg(struct sk_buff *buf); void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index e1c791798ba1..338837396642 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -576,12 +576,14 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, &dest->addr.name.name, dest->addr.name.domain, m->msg_iovlen, - m->msg_iov); + m->msg_iov, + total_len); } else if (dest->addrtype == TIPC_ADDR_ID) { res = tipc_send2port(tport->ref, &dest->addr.id, m->msg_iovlen, - m->msg_iov); + m->msg_iov, + total_len); } else if (dest->addrtype == TIPC_ADDR_MCAST) { if (needs_conn) { res = -EOPNOTSUPP; @@ -593,7 +595,8 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, res = tipc_multicast(tport->ref, &dest->addr.nameseq, m->msg_iovlen, - m->msg_iov); + m->msg_iov, + total_len); } if (likely(res != -ELINKCONG)) { if (needs_conn && (res >= 0)) @@ -659,7 +662,8 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, break; } - res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov); + res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov, + total_len); if (likely(res != -ELINKCONG)) break; if (m->msg_flags & MSG_DONTWAIT) { @@ -766,7 +770,7 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, bytes_to_send = curr_left; my_iov.iov_base = curr_start; my_iov.iov_len = bytes_to_send; - res = send_packet(NULL, sock, &my_msg, 0); + res = send_packet(NULL, sock, &my_msg, bytes_to_send); if (res < 0) { if (bytes_sent) res = bytes_sent; diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index aae9eae13404..6cf726863485 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -109,7 +109,7 @@ static void subscr_send_event(struct subscription *sub, sub->evt.found_upper = htohl(found_upper, sub->swap); sub->evt.port.ref = htohl(port_ref, sub->swap); sub->evt.port.node = htohl(node, sub->swap); - tipc_send(sub->server_ref, 1, &msg_sect); + tipc_send(sub->server_ref, 1, &msg_sect, msg_sect.iov_len); } /** @@ -521,7 +521,7 @@ static void subscr_named_msg_event(void *usr_handle, /* Send an ACK- to complete connection handshaking */ - tipc_send(server_port_ref, 0, NULL); + tipc_send(server_port_ref, 0, NULL, 0); /* Handle optional subscription request */ -- cgit v1.2.3-58-ga151 From dc63d91eb1cf74233c68b0058dcd477f5d019d02 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Thu, 21 Apr 2011 11:50:42 -0400 Subject: tipc: Introduce routine to enqueue a chain of messages on link tx queue Create a helper routine to enqueue a chain of sk_buffs to a link's transmit queue. It improves readability and the new function is anticipated to be used more than just once in the future as well. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/link.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 4bab139d5e74..5ed4b4f7452d 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -843,6 +843,25 @@ static void link_add_to_outqueue(struct link *l_ptr, l_ptr->stats.max_queue_sz = l_ptr->out_queue_size; } +static void link_add_chain_to_outqueue(struct link *l_ptr, + struct sk_buff *buf_chain, + u32 long_msgno) +{ + struct sk_buff *buf; + struct tipc_msg *msg; + + if (!l_ptr->next_out) + l_ptr->next_out = buf_chain; + while (buf_chain) { + buf = buf_chain; + buf_chain = buf_chain->next; + + msg = buf_msg(buf); + msg_set_long_msgno(msg, long_msgno); + link_add_to_outqueue(l_ptr, buf, msg); + } +} + /* * tipc_link_send_buf() is the 'full path' for messages, called from * inside TIPC when the 'fast path' in tipc_send_buf @@ -1276,25 +1295,12 @@ reject: total_len, TIPC_ERR_NO_NODE); } - /* Append whole chain to send queue: */ + /* Append chain of fragments to send queue & send them */ - buf = buf_chain; l_ptr->long_msg_seq_no++; - if (!l_ptr->next_out) - l_ptr->next_out = buf_chain; + link_add_chain_to_outqueue(l_ptr, buf_chain, l_ptr->long_msg_seq_no); + l_ptr->stats.sent_fragments += fragm_no; l_ptr->stats.sent_fragmented++; - while (buf) { - struct sk_buff *next = buf->next; - struct tipc_msg *msg = buf_msg(buf); - - l_ptr->stats.sent_fragments++; - msg_set_long_msgno(msg, l_ptr->long_msg_seq_no); - link_add_to_outqueue(l_ptr, buf, msg); - buf = next; - } - - /* Send it, if possible: */ - tipc_link_push_queue(l_ptr); tipc_node_unlock(node); return dsz; -- cgit v1.2.3-58-ga151 From 3a777ff8b14456e15991c9fcc225943453dc3a75 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Thu, 21 Apr 2011 13:58:26 -0500 Subject: tipc: Enhance handling of discovery object creation failures Modifies bearer creation and deletion code to improve handling of scenarios when a neighbor discovery object cannot be created. The creation routine now aborts the creation of a bearer if its discovery object cannot be created, and deletes the newly created bearer, rather than failing quietly and leaving an unusable bearer hanging around. Since the exit via the goto label really isn't a definitive failure in all cases, relabel it appropriately. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/bearer.c | 30 ++++++++++++++++++------------ net/tipc/discover.c | 45 +++++++++++++++++++++------------------------ net/tipc/discover.h | 8 +++----- 3 files changed, 42 insertions(+), 41 deletions(-) diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index f7c29af4ab81..5fcd1c1214fd 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -46,6 +46,8 @@ static u32 media_count; struct tipc_bearer tipc_bearers[MAX_BEARERS]; +static void bearer_disable(struct tipc_bearer *b_ptr); + /** * media_name_valid - validate media name * @@ -518,7 +520,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) if (!m_ptr) { warn("Bearer <%s> rejected, media <%s> not registered\n", name, b_name.media_name); - goto failed; + goto exit; } if (priority == TIPC_MEDIA_LINK_PRI) @@ -534,14 +536,14 @@ restart: } if (!strcmp(name, tipc_bearers[i].name)) { warn("Bearer <%s> rejected, already enabled\n", name); - goto failed; + goto exit; } if ((tipc_bearers[i].priority == priority) && (++with_this_prio > 2)) { if (priority-- == 0) { warn("Bearer <%s> rejected, duplicate priority\n", name); - goto failed; + goto exit; } warn("Bearer <%s> priority adjustment required %u->%u\n", name, priority + 1, priority); @@ -551,7 +553,7 @@ restart: if (bearer_id >= MAX_BEARERS) { warn("Bearer <%s> rejected, bearer limit reached (%u)\n", name, MAX_BEARERS); - goto failed; + goto exit; } b_ptr = &tipc_bearers[bearer_id]; @@ -559,7 +561,7 @@ restart: res = m_ptr->enable_bearer(b_ptr); if (res) { warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res); - goto failed; + goto exit; } b_ptr->identity = bearer_id; @@ -569,14 +571,18 @@ restart: b_ptr->priority = priority; INIT_LIST_HEAD(&b_ptr->cong_links); INIT_LIST_HEAD(&b_ptr->links); - b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr, - disc_domain); spin_lock_init(&b_ptr->lock); - write_unlock_bh(&tipc_net_lock); + + res = tipc_disc_create(b_ptr, &m_ptr->bcast_addr, disc_domain); + if (res) { + bearer_disable(b_ptr); + warn("Bearer <%s> rejected, discovery object creation failed\n", + name); + goto exit; + } info("Enabled bearer <%s>, discovery domain %s, priority %u\n", name, tipc_addr_string_fill(addr_string, disc_domain), priority); - return 0; -failed: +exit: write_unlock_bh(&tipc_net_lock); return res; } @@ -627,14 +633,14 @@ static void bearer_disable(struct tipc_bearer *b_ptr) struct link *temp_l_ptr; info("Disabling bearer <%s>\n", b_ptr->name); - tipc_disc_stop_link_req(b_ptr->link_req); spin_lock_bh(&b_ptr->lock); - b_ptr->link_req = NULL; b_ptr->blocked = 1; b_ptr->media->disable_bearer(b_ptr); list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { tipc_link_delete(l_ptr); } + if (b_ptr->link_req) + tipc_disc_delete(b_ptr->link_req); spin_unlock_bh(&b_ptr->lock); memset(b_ptr, 0, sizeof(struct tipc_bearer)); } diff --git a/net/tipc/discover.c b/net/tipc/discover.c index d2163bd99e59..6acf32a9eef8 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -215,22 +215,6 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) tipc_node_unlock(n_ptr); } -/** - * tipc_disc_stop_link_req - stop sending periodic link setup requests - * @req: ptr to link request structure - */ - -void tipc_disc_stop_link_req(struct link_req *req) -{ - if (!req) - return; - - k_cancel_timer(&req->timer); - k_term_timer(&req->timer); - buf_discard(req->buf); - kfree(req); -} - /** * tipc_disc_update_link_req - update frequency of periodic link setup requests * @req: ptr to link request structure @@ -286,28 +270,27 @@ static void disc_timeout(struct link_req *req) } /** - * tipc_disc_init_link_req - start sending periodic link setup requests + * tipc_disc_create - create object to send periodic link setup requests * @b_ptr: ptr to bearer issuing requests * @dest: destination address for request messages * @dest_domain: network domain to which links can be established * - * Returns pointer to link request structure, or NULL if unable to create. + * Returns 0 if successful, otherwise -errno. */ -struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr, - const struct tipc_media_addr *dest, - u32 dest_domain) +int tipc_disc_create(struct tipc_bearer *b_ptr, + struct tipc_media_addr *dest, u32 dest_domain) { struct link_req *req; req = kmalloc(sizeof(*req), GFP_ATOMIC); if (!req) - return NULL; + return -ENOMEM; req->buf = tipc_disc_init_msg(DSC_REQ_MSG, dest_domain, b_ptr); if (!req->buf) { kfree(req); - return NULL; + return -ENOMSG; } memcpy(&req->dest, dest, sizeof(*dest)); @@ -316,6 +299,20 @@ struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr, req->timer_intv = TIPC_LINK_REQ_INIT; k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); k_start_timer(&req->timer, req->timer_intv); - return req; + b_ptr->link_req = req; + return 0; +} + +/** + * tipc_disc_delete - destroy object sending periodic link setup requests + * @req: ptr to link request structure + */ + +void tipc_disc_delete(struct link_req *req) +{ + k_cancel_timer(&req->timer); + k_term_timer(&req->timer); + buf_discard(req->buf); + kfree(req); } diff --git a/net/tipc/discover.h b/net/tipc/discover.h index e48a167e47b2..d6e44e3dcdbc 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h @@ -39,12 +39,10 @@ struct link_req; -struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr, - const struct tipc_media_addr *dest, - u32 dest_domain); +int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest, + u32 dest_domain); +void tipc_disc_delete(struct link_req *req); void tipc_disc_update_link_req(struct link_req *req); -void tipc_disc_stop_link_req(struct link_req *req); - void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr); #endif -- cgit v1.2.3-58-ga151 From 691a62075922b43b2b03def87ebcfdfbf0cd2ed8 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Thu, 21 Apr 2011 16:28:02 -0500 Subject: tipc: Enhance sending of discovery object link request messages Augments TIPC's discovery object to send its initial neighbor discovery request message as soon as the associated bearer is created, rather than waiting for its first periodic timeout to occur, thereby speeding up the discovery process. Also adds a check to suppress the initial request or subsequent requests if the bearer is blocked at the time the request is scheduled for transmission. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/discover.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 6acf32a9eef8..dba47673124d 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -240,6 +240,17 @@ void tipc_disc_update_link_req(struct link_req *req) } } +/** + * disc_send_msg - send link setup request message + * @req: ptr to link request structure + */ + +static void disc_send_msg(struct link_req *req) +{ + if (!req->bearer->blocked) + tipc_bearer_send(req->bearer, req->buf, &req->dest); +} + /** * disc_timeout - send a periodic link setup request * @req: ptr to link request structure @@ -251,7 +262,7 @@ static void disc_timeout(struct link_req *req) { spin_lock_bh(&req->bearer->lock); - req->bearer->media->send_msg(req->buf, req->bearer, &req->dest); + disc_send_msg(req); if ((req->timer_intv == TIPC_LINK_REQ_SLOW) || (req->timer_intv == TIPC_LINK_REQ_FAST)) { @@ -300,6 +311,7 @@ int tipc_disc_create(struct tipc_bearer *b_ptr, k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); k_start_timer(&req->timer, req->timer_intv); b_ptr->link_req = req; + disc_send_msg(req); return 0; } -- cgit v1.2.3-58-ga151 From 1209966cd5d2ec7f89ad2ed58a6a342aa8ea8712 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Thu, 21 Apr 2011 19:05:25 -0500 Subject: tipc: Add monitoring of number of nodes discovered by bearer Augments TIPC's discovery object to track the number of neighboring nodes having an active link to the associated bearer. This means tipc_disc_update_link_req() becomes either one of: tipc_disc_add_dest() or: tipc_disc_remove_dest() depending on the code flow direction of things. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/bearer.c | 4 ++-- net/tipc/discover.c | 32 +++++++++++++++++++++++++++----- net/tipc/discover.h | 3 ++- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 5fcd1c1214fd..85209eadfae6 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -344,15 +344,15 @@ struct sk_buff *tipc_bearer_get_names(void) void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest) { tipc_nmap_add(&b_ptr->nodes, dest); - tipc_disc_update_link_req(b_ptr->link_req); tipc_bcbearer_sort(); + tipc_disc_add_dest(b_ptr->link_req); } void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest) { tipc_nmap_remove(&b_ptr->nodes, dest); - tipc_disc_update_link_req(b_ptr->link_req); tipc_bcbearer_sort(); + tipc_disc_remove_dest(b_ptr->link_req); } /* diff --git a/net/tipc/discover.c b/net/tipc/discover.c index dba47673124d..3cb232d1f5dc 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -53,6 +53,7 @@ * @bearer: bearer issuing requests * @dest: destination address for request messages * @domain: network domain to which links can be established + * @num_nodes: number of nodes currently discovered (i.e. with an active link) * @buf: request message to be (repeatedly) sent * @timer: timer governing period between requests * @timer_intv: current interval between requests (in ms) @@ -61,6 +62,7 @@ struct link_req { struct tipc_bearer *bearer; struct tipc_media_addr dest; u32 domain; + int num_nodes; struct sk_buff *buf; struct timer_list timer; unsigned int timer_intv; @@ -216,15 +218,12 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) } /** - * tipc_disc_update_link_req - update frequency of periodic link setup requests + * disc_update - update frequency of periodic link setup requests * @req: ptr to link request structure */ -void tipc_disc_update_link_req(struct link_req *req) +static void disc_update(struct link_req *req) { - if (!req) - return; - if (req->timer_intv == TIPC_LINK_REQ_SLOW) { if (!req->bearer->nodes.count) { req->timer_intv = TIPC_LINK_REQ_FAST; @@ -240,6 +239,28 @@ void tipc_disc_update_link_req(struct link_req *req) } } +/** + * tipc_disc_add_dest - increment set of discovered nodes + * @req: ptr to link request structure + */ + +void tipc_disc_add_dest(struct link_req *req) +{ + req->num_nodes++; + disc_update(req); +} + +/** + * tipc_disc_remove_dest - decrement set of discovered nodes + * @req: ptr to link request structure + */ + +void tipc_disc_remove_dest(struct link_req *req) +{ + req->num_nodes--; + disc_update(req); +} + /** * disc_send_msg - send link setup request message * @req: ptr to link request structure @@ -307,6 +328,7 @@ int tipc_disc_create(struct tipc_bearer *b_ptr, memcpy(&req->dest, dest, sizeof(*dest)); req->bearer = b_ptr; req->domain = dest_domain; + req->num_nodes = 0; req->timer_intv = TIPC_LINK_REQ_INIT; k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); k_start_timer(&req->timer, req->timer_intv); diff --git a/net/tipc/discover.h b/net/tipc/discover.h index d6e44e3dcdbc..a3af595b86cb 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h @@ -42,7 +42,8 @@ struct link_req; int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest, u32 dest_domain); void tipc_disc_delete(struct link_req *req); -void tipc_disc_update_link_req(struct link_req *req); +void tipc_disc_add_dest(struct link_req *req); +void tipc_disc_remove_dest(struct link_req *req); void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr); #endif -- cgit v1.2.3-58-ga151 From 972a77fbf1bbea6f54b5986b05041a17b607695b Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Thu, 21 Apr 2011 20:34:03 -0500 Subject: tipc: Revise timings used when sending link request messages Revises the algorithm governing the sending of link request messages to take into account the number of nodes each bearer is currently in contact with, and to ensure more rapid rediscovery of neighboring nodes if a bearer fails and then recovers. The discovery object now sends requests at least once a second if it is not in contact with any other nodes, and at least once a minute if it has at least one neighbor; if contact with the only neighbor is lost, the object immediately reverts to its initial rapid-fire search timing to accelerate the rediscovery process. In addition, the discovery object now stops issuing link request messages if it is in contact with the only neighboring node it is configured to communicate with, since further searching is unnecessary. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/discover.c | 66 +++++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 3cb232d1f5dc..0987933155b9 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -39,13 +39,9 @@ #include "discover.h" #define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */ -#define TIPC_LINK_REQ_FAST 2000 /* normal delay if bearer has no links */ -#define TIPC_LINK_REQ_SLOW 600000 /* normal delay if bearer has links */ - -/* - * TODO: Most of the inter-cluster setup stuff should be - * rewritten, and be made conformant with specification. - */ +#define TIPC_LINK_REQ_FAST 1000 /* max delay if bearer has no links */ +#define TIPC_LINK_REQ_SLOW 60000 /* max delay if bearer has links */ +#define TIPC_LINK_REQ_INACTIVE 0xffffffff /* indicates no timer in use */ /** @@ -220,22 +216,19 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) /** * disc_update - update frequency of periodic link setup requests * @req: ptr to link request structure + * + * Reinitiates discovery process if discovery object has no associated nodes + * and is either not currently searching or is searching at a slow rate */ static void disc_update(struct link_req *req) { - if (req->timer_intv == TIPC_LINK_REQ_SLOW) { - if (!req->bearer->nodes.count) { - req->timer_intv = TIPC_LINK_REQ_FAST; + if (!req->num_nodes) { + if ((req->timer_intv == TIPC_LINK_REQ_INACTIVE) || + (req->timer_intv > TIPC_LINK_REQ_FAST)) { + req->timer_intv = TIPC_LINK_REQ_INIT; k_start_timer(&req->timer, req->timer_intv); } - } else if (req->timer_intv == TIPC_LINK_REQ_FAST) { - if (req->bearer->nodes.count) { - req->timer_intv = TIPC_LINK_REQ_SLOW; - k_start_timer(&req->timer, req->timer_intv); - } - } else { - /* leave timer "as is" if haven't yet reached a "normal" rate */ } } @@ -247,7 +240,6 @@ static void disc_update(struct link_req *req) void tipc_disc_add_dest(struct link_req *req) { req->num_nodes++; - disc_update(req); } /** @@ -281,23 +273,37 @@ static void disc_send_msg(struct link_req *req) static void disc_timeout(struct link_req *req) { + int max_delay; + spin_lock_bh(&req->bearer->lock); - disc_send_msg(req); + /* Stop searching if only desired node has been found */ - if ((req->timer_intv == TIPC_LINK_REQ_SLOW) || - (req->timer_intv == TIPC_LINK_REQ_FAST)) { - /* leave timer interval "as is" if already at a "normal" rate */ - } else { - req->timer_intv *= 2; - if (req->timer_intv > TIPC_LINK_REQ_FAST) - req->timer_intv = TIPC_LINK_REQ_FAST; - if ((req->timer_intv == TIPC_LINK_REQ_FAST) && - (req->bearer->nodes.count)) - req->timer_intv = TIPC_LINK_REQ_SLOW; + if (tipc_node(req->domain) && req->num_nodes) { + req->timer_intv = TIPC_LINK_REQ_INACTIVE; + goto exit; } - k_start_timer(&req->timer, req->timer_intv); + /* + * Send discovery message, then update discovery timer + * + * Keep doubling time between requests until limit is reached; + * hold at fast polling rate if don't have any associated nodes, + * otherwise hold at slow polling rate + */ + + disc_send_msg(req); + + req->timer_intv *= 2; + if (req->num_nodes) + max_delay = TIPC_LINK_REQ_SLOW; + else + max_delay = TIPC_LINK_REQ_FAST; + if (req->timer_intv > max_delay) + req->timer_intv = max_delay; + + k_start_timer(&req->timer, req->timer_intv); +exit: spin_unlock_bh(&req->bearer->lock); } -- cgit v1.2.3-58-ga151 From 0a5ebb8000c5362be368df9d197943deb06b6916 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 9 May 2011 13:22:43 -0700 Subject: ipv4: Pass explicit daddr arg to ip_send_reply(). This eliminates an access to rt->rt_src. Signed-off-by: David S. Miller --- include/net/ip.h | 4 ++-- net/ipv4/ip_output.c | 7 +++---- net/ipv4/tcp_ipv4.c | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index 0b30d3ab4a30..66dd49149208 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -174,8 +174,8 @@ static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg) return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0; } -void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg, - unsigned int len); +void ip_send_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, + struct ip_reply_arg *arg, unsigned int len); struct ipv4_config { int log_martians; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index cd89d22902a9..70778d48aa7b 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1459,20 +1459,19 @@ static int ip_reply_glue_bits(void *dptr, char *to, int offset, * Should run single threaded per socket because it uses the sock * structure to pass arguments. */ -void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg, - unsigned int len) +void ip_send_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, + struct ip_reply_arg *arg, unsigned int len) { struct inet_sock *inet = inet_sk(sk); struct ip_options_data replyopts; struct ipcm_cookie ipc; struct flowi4 fl4; - __be32 daddr; struct rtable *rt = skb_rtable(skb); if (ip_options_echo(&replyopts.opt.opt, skb)) return; - daddr = ipc.addr = rt->rt_src; + ipc.addr = daddr; ipc.opt = NULL; ipc.tx_flags = 0; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 2b655031b392..f67fb34e16e5 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -651,7 +651,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; net = dev_net(skb_dst(skb)->dev); - ip_send_reply(net->ipv4.tcp_sock, skb, + ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr, &arg, arg.iov[0].iov_len); TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); @@ -726,7 +726,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, if (oif) arg.bound_dev_if = oif; - ip_send_reply(net->ipv4.tcp_sock, skb, + ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr, &arg, arg.iov[0].iov_len); TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); -- cgit v1.2.3-58-ga151 From 9f6abb5f175bdb9ecfd390000a631bf0abf2fedb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 9 May 2011 13:28:22 -0700 Subject: ipv4: icmp: Eliminate remaining uses of rt->rt_src On input packets, rt->rt_src always equals ip_hdr(skb)->saddr Anything that mangles or otherwise changes the IP header must relookup the route found at skb_rtable(). Therefore this invariant must always hold true. Signed-off-by: David S. Miller --- net/ipv4/icmp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 853a670f6df6..3314394f0aab 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -345,7 +345,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) icmp_param->data.icmph.checksum = 0; inet->tos = ip_hdr(skb)->tos; - daddr = ipc.addr = rt->rt_src; + daddr = ipc.addr = ip_hdr(skb)->saddr; ipc.opt = NULL; ipc.tx_flags = 0; if (icmp_param->replyopts.opt.opt.optlen) { @@ -930,12 +930,12 @@ static void icmp_address_reply(struct sk_buff *skb) BUG_ON(mp == NULL); for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { if (*mp == ifa->ifa_mask && - inet_ifa_match(rt->rt_src, ifa)) + inet_ifa_match(ip_hdr(skb)->saddr, ifa)) break; } if (!ifa && net_ratelimit()) { printk(KERN_INFO "Wrong address mask %pI4 from %s/%pI4\n", - mp, dev->name, &rt->rt_src); + mp, dev->name, &ip_hdr(skb)->saddr); } } } -- cgit v1.2.3-58-ga151 From 79ab053145ae10edf8f0809d1c788b853c7f6ef1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 9 May 2011 13:31:04 -0700 Subject: ipv4: udp: Eliminate remaining uses of rt->rt_src We already track and pass around the correct flow key, so simply use it in udp_send_skb(). Signed-off-by: David S. Miller --- net/ipv4/udp.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 66341a3c8d36..599374f65c76 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -706,12 +706,11 @@ static void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst) } } -static int udp_send_skb(struct sk_buff *skb, __be32 daddr, __be32 dport) +static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) { struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(sk); struct udphdr *uh; - struct rtable *rt = (struct rtable *)skb_dst(skb); int err = 0; int is_udplite = IS_UDPLITE(sk); int offset = skb_transport_offset(skb); @@ -723,7 +722,7 @@ static int udp_send_skb(struct sk_buff *skb, __be32 daddr, __be32 dport) */ uh = udp_hdr(skb); uh->source = inet->inet_sport; - uh->dest = dport; + uh->dest = fl4->fl4_dport; uh->len = htons(len); uh->check = 0; @@ -737,14 +736,14 @@ static int udp_send_skb(struct sk_buff *skb, __be32 daddr, __be32 dport) } else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ - udp4_hwcsum(skb, rt->rt_src, daddr); + udp4_hwcsum(skb, fl4->saddr, fl4->daddr); goto send; } else csum = udp_csum(skb); /* add protocol-dependent pseudo-header */ - uh->check = csum_tcpudp_magic(rt->rt_src, daddr, len, + uh->check = csum_tcpudp_magic(fl4->saddr, fl4->daddr, len, sk->sk_protocol, csum); if (uh->check == 0) uh->check = CSUM_MANGLED_0; @@ -778,7 +777,7 @@ static int udp_push_pending_frames(struct sock *sk) if (!skb) goto out; - err = udp_send_skb(skb, fl4->daddr, fl4->fl4_dport); + err = udp_send_skb(skb, fl4); out: up->len = 0; @@ -963,7 +962,7 @@ back_from_confirm: msg->msg_flags); err = PTR_ERR(skb); if (skb && !IS_ERR(skb)) - err = udp_send_skb(skb, daddr, dport); + err = udp_send_skb(skb, fl4); goto out; } -- cgit v1.2.3-58-ga151 From 902ebd3e0de618b6d39004edac00b2cc36362065 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 9 May 2011 14:49:13 -0700 Subject: sctp: Remove rt->rt_src usage in sctp_v4_get_saddr() Flow key is available, so fetch it from there. Signed-off-by: David S. Miller --- net/sctp/protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 4f270ac48226..4de77cb80d88 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -566,7 +566,7 @@ static void sctp_v4_get_saddr(struct sctp_sock *sk, if (rt) { saddr->v4.sin_family = AF_INET; - saddr->v4.sin_addr.s_addr = rt->rt_src; + saddr->v4.sin_addr.s_addr = fl->u.ip4.saddr; } } -- cgit v1.2.3-58-ga151 From 5fc3590c81bd233c25fbe127cdcf7a8e26e12378 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 9 May 2011 14:52:02 -0700 Subject: infiniband: Remove rt->rt_src usage in addr4_resolve() Use an explicit flow key and fetch it from there. Signed-off-by: David S. Miller --- drivers/infiniband/core/addr.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 4ffc224faa7f..8e21d457b899 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -185,15 +185,20 @@ static int addr4_resolve(struct sockaddr_in *src_in, __be32 dst_ip = dst_in->sin_addr.s_addr; struct rtable *rt; struct neighbour *neigh; + struct flowi4 fl4; int ret; - rt = ip_route_output(&init_net, dst_ip, src_ip, 0, addr->bound_dev_if); + memset(&fl4, 0, sizeof(fl4)); + fl4.daddr = dst_ip; + fl4.saddr = src_ip; + fl4.flowi4_oif = addr->bound_dev_if; + rt = ip_route_output_key(&init_net, &fl4); if (IS_ERR(rt)) { ret = PTR_ERR(rt); goto out; } src_in->sin_family = AF_INET; - src_in->sin_addr.s_addr = rt->rt_src; + src_in->sin_addr.s_addr = fl4.saddr; if (rt->dst.dev->flags & IFF_LOOPBACK) { ret = rdma_translate_ip((struct sockaddr *) dst_in, addr); -- cgit v1.2.3-58-ga151 From 8f01cb0827c84bd9c4866b849415b3aa6f0428df Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 9 May 2011 15:13:28 -0700 Subject: ipv4: xfrm: Eliminate ->rt_src reference in policy code. Rearrange xfrm4_dst_lookup() so that it works by calling a helper function __xfrm_dst_lookup() that takes an explicit flow key storage area as an argument. Use this new helper in xfrm4_get_saddr() so we can fetch the selected source address from the flow instead of from rt->rt_src Signed-off-by: David S. Miller --- net/ipv4/xfrm4_policy.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 7ff973bd02dd..981e43eaf704 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -18,38 +18,46 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo; -static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, - const xfrm_address_t *saddr, - const xfrm_address_t *daddr) +static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4, + int tos, + const xfrm_address_t *saddr, + const xfrm_address_t *daddr) { - struct flowi4 fl4 = { - .daddr = daddr->a4, - .flowi4_tos = tos, - }; struct rtable *rt; + memset(fl4, 0, sizeof(*fl4)); + fl4->daddr = daddr->a4; + fl4->flowi4_tos = tos; if (saddr) - fl4.saddr = saddr->a4; + fl4->saddr = saddr->a4; - rt = __ip_route_output_key(net, &fl4); + rt = __ip_route_output_key(net, fl4); if (!IS_ERR(rt)) return &rt->dst; return ERR_CAST(rt); } +static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, + const xfrm_address_t *saddr, + const xfrm_address_t *daddr) +{ + struct flowi4 fl4; + + return __xfrm4_dst_lookup(net, &fl4, tos, saddr, daddr); +} + static int xfrm4_get_saddr(struct net *net, xfrm_address_t *saddr, xfrm_address_t *daddr) { struct dst_entry *dst; - struct rtable *rt; + struct flowi4 fl4; - dst = xfrm4_dst_lookup(net, 0, NULL, daddr); + dst = __xfrm4_dst_lookup(net, &fl4, 0, NULL, daddr); if (IS_ERR(dst)) return -EHOSTUNREACH; - rt = (struct rtable *)dst; - saddr->a4 = rt->rt_src; + saddr->a4 = fl4.saddr; dst_release(dst); return 0; } -- cgit v1.2.3-58-ga151 From 1fc19aff84edf97753c58cf4b858c6c4fdb246fa Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 9 May 2011 20:55:03 -0700 Subject: net: fix two lockdep splats Commit e67f88dd12f6 (net: dont hold rtnl mutex during netlink dump callbacks) switched rtnl protection to RCU, but we forgot to adjust two rcu_dereference() lockdep annotations : inet_get_link_af_size() or inet_fill_link_af() might be called with rcu_read_lock or rtnl held, so use rcu_dereference_rtnl() instead of rtnl_dereference() Reported-by: Valdis Kletnieks Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/devinet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index cd9ca0811cfa..0d4a184af16f 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1369,7 +1369,7 @@ errout: static size_t inet_get_link_af_size(const struct net_device *dev) { - struct in_device *in_dev = __in_dev_get_rtnl(dev); + struct in_device *in_dev = rcu_dereference_rtnl(dev->ip_ptr); if (!in_dev) return 0; @@ -1379,7 +1379,7 @@ static size_t inet_get_link_af_size(const struct net_device *dev) static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev) { - struct in_device *in_dev = __in_dev_get_rtnl(dev); + struct in_device *in_dev = rcu_dereference_rtnl(dev->ip_ptr); struct nlattr *nla; int i; -- cgit v1.2.3-58-ga151 From 9fcce61c0eddbe21f42cb47bd5a366a6eb7956ce Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 8 May 2011 20:30:31 +0200 Subject: ssb: update list of devices supporting multiple 80211 cores MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of the BCM43xx chips contain cores that are attached to the SSB, but are inactive as they do not connect to the external environment. These must not be registered. Several of these types are handled in driver ssb; however, the specific case of an inactive 802.11 cores is now treated in b43 and b43legacy. Although the current setup works, this minor change will place all such workarounds in ssb, and simplify the code in drivers b43 and b43legacy. Signed-off-by: Rafał Miłecki Tested-by: Larry Finger Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/ssb/scan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index 7dca719fbcfb..45e5babd3961 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c @@ -258,7 +258,10 @@ static int we_support_multiple_80211_cores(struct ssb_bus *bus) #ifdef CONFIG_SSB_PCIHOST if (bus->bustype == SSB_BUSTYPE_PCI) { if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM && - bus->host_pci->device == 0x4324) + ((bus->host_pci->device == 0x4313) || + (bus->host_pci->device == 0x431A) || + (bus->host_pci->device == 0x4321) || + (bus->host_pci->device == 0x4324))) return 1; } #endif /* CONFIG_SSB_PCIHOST */ -- cgit v1.2.3-58-ga151 From 0e4e06ae5e895864b4a4bca7eec2e3015fddca98 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 2 May 2011 16:49:14 -0700 Subject: libertas: Convert lbs_pr_ to pr_ Use the standard pr_ functions eases grep a bit. Added a few missing terminating newlines to messages. Coalesced long formats. Signed-off-by: Joe Perches Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cfg.c | 15 +++---- drivers/net/wireless/libertas/cmd.c | 36 ++++++++-------- drivers/net/wireless/libertas/cmdresp.c | 29 +++++++------ drivers/net/wireless/libertas/debugfs.c | 6 ++- drivers/net/wireless/libertas/defs.h | 7 ---- drivers/net/wireless/libertas/if_cs.c | 52 ++++++++++++----------- drivers/net/wireless/libertas/if_sdio.c | 38 ++++++++--------- drivers/net/wireless/libertas/if_spi.c | 74 +++++++++++++++------------------ drivers/net/wireless/libertas/if_usb.c | 41 +++++++++--------- drivers/net/wireless/libertas/main.c | 31 +++++++------- drivers/net/wireless/libertas/mesh.c | 8 ++-- drivers/net/wireless/libertas/rx.c | 7 +++- 12 files changed, 173 insertions(+), 171 deletions(-) diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index f582dfd2927f..73c5f54c9b42 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -6,6 +6,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -1322,8 +1324,7 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, sme->ssid, sme->ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (!bss) { - lbs_pr_err("assoc: bss %pM not in scan results\n", - sme->bssid); + pr_err("assoc: bss %pM not in scan results\n", sme->bssid); ret = -ENOENT; goto done; } @@ -1380,8 +1381,8 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, lbs_enable_rsn(priv, sme->crypto.cipher_group != 0); break; default: - lbs_pr_err("unsupported cipher group 0x%x\n", - sme->crypto.cipher_group); + pr_err("unsupported cipher group 0x%x\n", + sme->crypto.cipher_group); ret = -ENOTSUPP; goto done; } @@ -1499,7 +1500,7 @@ static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev, params->key, params->key_len); break; default: - lbs_pr_err("unhandled cipher 0x%x\n", params->cipher); + pr_err("unhandled cipher 0x%x\n", params->cipher); ret = -ENOTSUPP; break; } @@ -2127,13 +2128,13 @@ int lbs_cfg_register(struct lbs_private *priv) ret = wiphy_register(wdev->wiphy); if (ret < 0) - lbs_pr_err("cannot register wiphy device\n"); + pr_err("cannot register wiphy device\n"); priv->wiphy_registered = true; ret = register_netdev(priv->dev); if (ret) - lbs_pr_err("cannot register network device\n"); + pr_err("cannot register network device\n"); INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 6a96fc9c1cea..af8ef90a122a 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -3,6 +3,8 @@ * It prepares command and sends it to firmware when it is ready. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -110,7 +112,7 @@ int lbs_update_hw_spec(struct lbs_private *priv) * CF card firmware 5.0.16p0: cap 0x00000303 * USB dongle firmware 5.110.17p2: cap 0x00000303 */ - lbs_pr_info("%pM, fw %u.%u.%up%u, cap 0x%08x\n", + pr_info("%pM, fw %u.%u.%up%u, cap 0x%08x\n", cmd.permanentaddr, priv->fwrelease >> 24 & 0xff, priv->fwrelease >> 16 & 0xff, @@ -141,7 +143,7 @@ int lbs_update_hw_spec(struct lbs_private *priv) /* if it's unidentified region code, use the default (USA) */ if (i >= MRVDRV_MAX_REGION_CODE) { priv->regioncode = 0x10; - lbs_pr_info("unidentified region code; using the default (USA)\n"); + pr_info("unidentified region code; using the default (USA)\n"); } if (priv->current_addr[0] == 0xff) @@ -211,7 +213,7 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, (uint8_t *)&cmd_config.wol_conf, sizeof(struct wol_config)); } else { - lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret); + pr_info("HOST_SLEEP_CFG failed %d\n", ret); } return ret; @@ -314,7 +316,7 @@ static int lbs_wait_for_ds_awake(struct lbs_private *priv) if (priv->is_deep_sleep) { if (!wait_event_interruptible_timeout(priv->ds_awake_q, !priv->is_deep_sleep, (10 * HZ))) { - lbs_pr_err("ds_awake_q: timer expired\n"); + pr_err("ds_awake_q: timer expired\n"); ret = -1; } } @@ -339,7 +341,7 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) netif_carrier_off(priv->dev); } } else { - lbs_pr_err("deep sleep: already enabled\n"); + pr_err("deep sleep: already enabled\n"); } } else { if (priv->is_deep_sleep) { @@ -349,8 +351,7 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) if (!ret) { ret = lbs_wait_for_ds_awake(priv); if (ret) - lbs_pr_err("deep sleep: wakeup" - "failed\n"); + pr_err("deep sleep: wakeup failed\n"); } } } @@ -384,8 +385,8 @@ int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep) ret = lbs_host_sleep_cfg(priv, priv->wol_criteria, (struct wol_config *)NULL); if (ret) { - lbs_pr_info("Host sleep configuration failed: " - "%d\n", ret); + pr_info("Host sleep configuration failed: %d\n", + ret); return ret; } if (priv->psstate == PS_STATE_FULL_POWER) { @@ -395,19 +396,19 @@ int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep) sizeof(cmd), lbs_ret_host_sleep_activate, 0); if (ret) - lbs_pr_info("HOST_SLEEP_ACTIVATE " - "failed: %d\n", ret); + pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", + ret); } if (!wait_event_interruptible_timeout( priv->host_sleep_q, priv->is_host_sleep_activated, (10 * HZ))) { - lbs_pr_err("host_sleep_q: timer expired\n"); + pr_err("host_sleep_q: timer expired\n"); ret = -1; } } else { - lbs_pr_err("host sleep: already enabled\n"); + pr_err("host sleep: already enabled\n"); } } else { if (priv->is_host_sleep_activated) @@ -1007,7 +1008,7 @@ static void lbs_submit_command(struct lbs_private *priv, ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize); if (ret) { - lbs_pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret); + pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret); /* Let the timer kick in and retry, and potentially reset the whole thing if the condition persists */ timeo = HZ/4; @@ -1276,7 +1277,7 @@ int lbs_execute_next_command(struct lbs_private *priv) spin_lock_irqsave(&priv->driver_lock, flags); if (priv->cur_cmd) { - lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n"); + pr_alert( "EXEC_NEXT_CMD: already processing command!\n"); spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; @@ -1438,7 +1439,7 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep, sizeof(confirm_sleep)); if (ret) { - lbs_pr_alert("confirm_sleep failed\n"); + pr_alert("confirm_sleep failed\n"); goto out; } @@ -1664,8 +1665,7 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command, spin_lock_irqsave(&priv->driver_lock, flags); ret = cmdnode->result; if (ret) - lbs_pr_info("PREP_CMD: command 0x%04x failed: %d\n", - command, ret); + pr_info("PREP_CMD: command 0x%04x failed: %d\n", command, ret); __lbs_cleanup_and_insert_cmd(priv, cmdnode); spin_unlock_irqrestore(&priv->driver_lock, flags); diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 03e528994a9e..45291a4c2a9f 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -2,6 +2,9 @@ * This file contains the handling of command * responses as well as events generated by firmware. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -85,15 +88,17 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len); if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { - lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n", - le16_to_cpu(resp->seqnum), le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum)); + pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n", + le16_to_cpu(resp->seqnum), + le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum)); spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; } if (respcmd != CMD_RET(curcmd) && respcmd != CMD_RET_802_11_ASSOCIATE && curcmd != CMD_802_11_ASSOCIATE) { - lbs_pr_info("Invalid CMD_RESP %x to command %x!\n", respcmd, curcmd); + pr_info("Invalid CMD_RESP %x to command %x!\n", + respcmd, curcmd); spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; @@ -102,8 +107,8 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) if (resp->result == cpu_to_le16(0x0004)) { /* 0x0004 means -EAGAIN. Drop the response, let it time out and be resubmitted */ - lbs_pr_info("Firmware returns DEFER to command %x. Will let it time out...\n", - le16_to_cpu(resp->command)); + pr_info("Firmware returns DEFER to command %x. Will let it time out...\n", + le16_to_cpu(resp->command)); spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; @@ -314,28 +319,28 @@ int lbs_process_event(struct lbs_private *priv, u32 event) lbs_deb_cmd("EVENT: ADHOC beacon lost\n"); break; case MACREG_INT_CODE_RSSI_LOW: - lbs_pr_alert("EVENT: rssi low\n"); + pr_alert("EVENT: rssi low\n"); break; case MACREG_INT_CODE_SNR_LOW: - lbs_pr_alert("EVENT: snr low\n"); + pr_alert("EVENT: snr low\n"); break; case MACREG_INT_CODE_MAX_FAIL: - lbs_pr_alert("EVENT: max fail\n"); + pr_alert("EVENT: max fail\n"); break; case MACREG_INT_CODE_RSSI_HIGH: - lbs_pr_alert("EVENT: rssi high\n"); + pr_alert("EVENT: rssi high\n"); break; case MACREG_INT_CODE_SNR_HIGH: - lbs_pr_alert("EVENT: snr high\n"); + pr_alert("EVENT: snr high\n"); break; case MACREG_INT_CODE_MESH_AUTO_STARTED: /* Ignore spurious autostart events */ - lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n"); + pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n"); break; default: - lbs_pr_alert("EVENT: unknown event id %d\n", event); + pr_alert("EVENT: unknown event id %d\n", event); break; } diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 851fe7bd4ba4..0bd79c5f5b5b 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -1,3 +1,5 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -151,13 +153,13 @@ static ssize_t lbs_host_sleep_write(struct file *file, ret = lbs_set_host_sleep(priv, 0); else if (host_sleep == 1) { if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { - lbs_pr_info("wake parameters not configured"); + pr_info("wake parameters not configured\n"); ret = -EINVAL; goto out_unlock; } ret = lbs_set_host_sleep(priv, 1); } else { - lbs_pr_err("invalid option\n"); + pr_err("invalid option\n"); ret = -EINVAL; } diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 92b5b1f8fd75..ab966f08024a 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -89,13 +89,6 @@ do { if ((lbs_debug & (grp)) == (grp)) \ #define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args) #define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args) -#define lbs_pr_info(format, args...) \ - printk(KERN_INFO DRV_NAME": " format, ## args) -#define lbs_pr_err(format, args...) \ - printk(KERN_ERR DRV_NAME": " format, ## args) -#define lbs_pr_alert(format, args...) \ - printk(KERN_ALERT DRV_NAME": " format, ## args) - #ifdef DEBUG static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len) { diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 4dfd48fe8b6e..f2d10115f5e5 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -21,6 +21,8 @@ */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -362,7 +364,7 @@ static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb) if (status & IF_CS_BIT_COMMAND) break; if (++loops > 100) { - lbs_pr_err("card not ready for commands\n"); + pr_err("card not ready for commands\n"); goto done; } mdelay(1); @@ -432,14 +434,14 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) /* is hardware ready? */ status = if_cs_read16(priv->card, IF_CS_CARD_STATUS); if ((status & IF_CS_BIT_RESP) == 0) { - lbs_pr_err("no cmd response in card\n"); + pr_err("no cmd response in card\n"); *len = 0; goto out; } *len = if_cs_read16(priv->card, IF_CS_RESP_LEN); if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) { - lbs_pr_err("card cmd buffer has invalid # of bytes (%d)\n", *len); + pr_err("card cmd buffer has invalid # of bytes (%d)\n", *len); goto out; } @@ -473,7 +475,7 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) len = if_cs_read16(priv->card, IF_CS_READ_LEN); if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { - lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len); + pr_err("card data buffer has invalid # of bytes (%d)\n", len); priv->dev->stats.rx_dropped++; goto dat_err; } @@ -653,8 +655,8 @@ static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw) ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS, IF_CS_BIT_COMMAND); if (ret < 0) { - lbs_pr_err("can't download helper at 0x%x, ret %d\n", - sent, ret); + pr_err("can't download helper at 0x%x, ret %d\n", + sent, ret); goto done; } @@ -684,7 +686,7 @@ static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw) ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, IF_CS_SQ_HELPER_OK); if (ret < 0) { - lbs_pr_err("helper firmware doesn't answer\n"); + pr_err("helper firmware doesn't answer\n"); goto done; } @@ -692,13 +694,13 @@ static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw) len = if_cs_read16(card, IF_CS_SQ_READ_LOW); if (len & 1) { retry++; - lbs_pr_info("odd, need to retry this firmware block\n"); + pr_info("odd, need to retry this firmware block\n"); } else { retry = 0; } if (retry > 20) { - lbs_pr_err("could not download firmware\n"); + pr_err("could not download firmware\n"); ret = -ENODEV; goto done; } @@ -718,14 +720,14 @@ static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw) ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS, IF_CS_BIT_COMMAND); if (ret < 0) { - lbs_pr_err("can't download firmware at 0x%x\n", sent); + pr_err("can't download firmware at 0x%x\n", sent); goto done; } } ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a); if (ret < 0) - lbs_pr_err("firmware download failed\n"); + pr_err("firmware download failed\n"); done: lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); @@ -759,7 +761,7 @@ static int if_cs_host_to_card(struct lbs_private *priv, ret = if_cs_send_cmd(priv, buf, nb); break; default: - lbs_pr_err("%s: unsupported type %d\n", __func__, type); + pr_err("%s: unsupported type %d\n", __func__, type); } lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); @@ -788,7 +790,7 @@ static int if_cs_ioprobe(struct pcmcia_device *p_dev, void *priv_data) p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; if (p_dev->resource[1]->end) { - lbs_pr_err("wrong CIS (check number of IO windows)\n"); + pr_err("wrong CIS (check number of IO windows)\n"); return -ENODEV; } @@ -809,7 +811,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) card = kzalloc(sizeof(struct if_cs_card), GFP_KERNEL); if (!card) { - lbs_pr_err("error in kzalloc\n"); + pr_err("error in kzalloc\n"); goto out; } card->p_dev = p_dev; @@ -818,7 +820,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) { - lbs_pr_err("error in pcmcia_loop_config\n"); + pr_err("error in pcmcia_loop_config\n"); goto out1; } @@ -834,14 +836,14 @@ static int if_cs_probe(struct pcmcia_device *p_dev) card->iobase = ioport_map(p_dev->resource[0]->start, resource_size(p_dev->resource[0])); if (!card->iobase) { - lbs_pr_err("error in ioport_map\n"); + pr_err("error in ioport_map\n"); ret = -EIO; goto out1; } ret = pcmcia_enable_device(p_dev); if (ret) { - lbs_pr_err("error in pcmcia_enable_device\n"); + pr_err("error in pcmcia_enable_device\n"); goto out2; } @@ -856,8 +858,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev) card->model = get_model(p_dev->manf_id, p_dev->card_id); if (card->model == MODEL_UNKNOWN) { - lbs_pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n", - p_dev->manf_id, p_dev->card_id); + pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n", + p_dev->manf_id, p_dev->card_id); goto out2; } @@ -866,20 +868,20 @@ static int if_cs_probe(struct pcmcia_device *p_dev) if (card->model == MODEL_8305) { card->align_regs = 1; if (prod_id < IF_CS_CF8305_B1_REV) { - lbs_pr_err("8305 rev B0 and older are not supported\n"); + pr_err("8305 rev B0 and older are not supported\n"); ret = -ENODEV; goto out2; } } if ((card->model == MODEL_8381) && prod_id < IF_CS_CF8381_B3_REV) { - lbs_pr_err("8381 rev B2 and older are not supported\n"); + pr_err("8381 rev B2 and older are not supported\n"); ret = -ENODEV; goto out2; } if ((card->model == MODEL_8385) && prod_id < IF_CS_CF8385_B1_REV) { - lbs_pr_err("8385 rev B0 and older are not supported\n"); + pr_err("8385 rev B0 and older are not supported\n"); ret = -ENODEV; goto out2; } @@ -887,7 +889,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model, &fw_table[0], &helper, &mainfw); if (ret) { - lbs_pr_err("failed to find firmware (%d)\n", ret); + pr_err("failed to find firmware (%d)\n", ret); goto out2; } @@ -918,7 +920,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) ret = request_irq(p_dev->irq, if_cs_interrupt, IRQF_SHARED, DRV_NAME, card); if (ret) { - lbs_pr_err("error in request_irq\n"); + pr_err("error in request_irq\n"); goto out3; } @@ -931,7 +933,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) /* And finally bring the card up */ if (lbs_start_card(priv) != 0) { - lbs_pr_err("could not activate card\n"); + pr_err("could not activate card\n"); goto out3; } diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index b4de0ca10feb..ab867795f542 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -26,6 +26,8 @@ * if_sdio_card_to_host() to pad the data. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -409,7 +411,7 @@ static int if_sdio_card_to_host(struct if_sdio_card *card) out: if (ret) - lbs_pr_err("problem fetching packet from firmware\n"); + pr_err("problem fetching packet from firmware\n"); lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); @@ -446,7 +448,7 @@ static void if_sdio_host_to_card_worker(struct work_struct *work) } if (ret) - lbs_pr_err("error %d sending packet to firmware\n", ret); + pr_err("error %d sending packet to firmware\n", ret); sdio_release_host(card->func); @@ -555,7 +557,7 @@ release: out: if (ret) - lbs_pr_err("failed to load helper firmware\n"); + pr_err("failed to load helper firmware\n"); lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); return ret; @@ -669,7 +671,7 @@ release: out: if (ret) - lbs_pr_err("failed to load firmware\n"); + pr_err("failed to load firmware\n"); lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); return ret; @@ -723,7 +725,7 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, card->model, &fw_table[0], &helper, &mainfw); if (ret) { - lbs_pr_err("failed to find firmware (%d)\n", ret); + pr_err("failed to find firmware (%d)\n", ret); goto out; } @@ -849,7 +851,7 @@ static int if_sdio_enter_deep_sleep(struct lbs_private *priv) ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd), lbs_cmd_copyback, (unsigned long) &cmd); if (ret) - lbs_pr_err("DEEP_SLEEP cmd failed\n"); + pr_err("DEEP_SLEEP cmd failed\n"); mdelay(200); return ret; @@ -865,7 +867,7 @@ static int if_sdio_exit_deep_sleep(struct lbs_private *priv) sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret); if (ret) - lbs_pr_err("sdio_writeb failed!\n"); + pr_err("sdio_writeb failed!\n"); sdio_release_host(card->func); lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); @@ -882,7 +884,7 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv) sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret); if (ret) - lbs_pr_err("sdio_writeb failed!\n"); + pr_err("sdio_writeb failed!\n"); sdio_release_host(card->func); lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); @@ -961,7 +963,7 @@ static int if_sdio_probe(struct sdio_func *func, } if (i == func->card->num_info) { - lbs_pr_err("unable to identify card model\n"); + pr_err("unable to identify card model\n"); return -ENODEV; } @@ -995,7 +997,7 @@ static int if_sdio_probe(struct sdio_func *func, break; } if (i == ARRAY_SIZE(fw_table)) { - lbs_pr_err("unknown card model 0x%x\n", card->model); + pr_err("unknown card model 0x%x\n", card->model); ret = -ENODEV; goto free; } @@ -1101,7 +1103,7 @@ static int if_sdio_probe(struct sdio_func *func, lbs_deb_sdio("send function INIT command\n"); if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd), lbs_cmd_copyback, (unsigned long) &cmd)) - lbs_pr_alert("CMD_FUNC_INIT cmd failed\n"); + pr_alert("CMD_FUNC_INIT cmd failed\n"); } ret = lbs_start_card(priv); @@ -1163,7 +1165,7 @@ static void if_sdio_remove(struct sdio_func *func) if (__lbs_cmd(card->priv, CMD_FUNC_SHUTDOWN, &cmd, sizeof(cmd), lbs_cmd_copyback, (unsigned long) &cmd)) - lbs_pr_alert("CMD_FUNC_SHUTDOWN cmd failed\n"); + pr_alert("CMD_FUNC_SHUTDOWN cmd failed\n"); } @@ -1202,21 +1204,19 @@ static int if_sdio_suspend(struct device *dev) mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); - lbs_pr_info("%s: suspend: PM flags = 0x%x\n", - sdio_func_id(func), flags); + pr_info("%s: suspend: PM flags = 0x%x\n", sdio_func_id(func), flags); /* If we aren't being asked to wake on anything, we should bail out * and let the SD stack power down the card. */ if (card->priv->wol_criteria == EHS_REMOVE_WAKEUP) { - lbs_pr_info("Suspend without wake params -- " - "powering down card."); + pr_info("Suspend without wake params -- powering down card\n"); return -ENOSYS; } if (!(flags & MMC_PM_KEEP_POWER)) { - lbs_pr_err("%s: cannot remain alive while host is suspended\n", - sdio_func_id(func)); + pr_err("%s: cannot remain alive while host is suspended\n", + sdio_func_id(func)); return -ENOSYS; } @@ -1237,7 +1237,7 @@ static int if_sdio_resume(struct device *dev) struct if_sdio_card *card = sdio_get_drvdata(func); int ret; - lbs_pr_info("%s: resume: we're back\n", sdio_func_id(func)); + pr_info("%s: resume: we're back\n", sdio_func_id(func)); ret = lbs_resume(card->priv); diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 67de5b3c68b2..4d19b5726c15 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -17,6 +17,8 @@ * (at your option) any later version. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -305,8 +307,7 @@ static int spu_wait_for_u16(struct if_spi_card *card, u16 reg, } udelay(100); if (time_after(jiffies, timeout)) { - lbs_pr_err("%s: timeout with val=%02x, " - "target_mask=%02x, target=%02x\n", + pr_err("%s: timeout with val=%02x, target_mask=%02x, target=%02x\n", __func__, val, target_mask, target); return -ETIMEDOUT; } @@ -405,7 +406,7 @@ static int spu_set_bus_mode(struct if_spi_card *card, u16 mode) if (err) return err; if ((rval & 0xF) != mode) { - lbs_pr_err("Can't read bus mode register.\n"); + pr_err("Can't read bus mode register\n"); return -EIO; } return 0; @@ -534,7 +535,7 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card, out: if (err) - lbs_pr_err("failed to load helper firmware (err=%d)\n", err); + pr_err("failed to load helper firmware (err=%d)\n", err); lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err); return err; } @@ -557,7 +558,7 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, IF_SPI_HIST_CMD_DOWNLOAD_RDY, IF_SPI_HIST_CMD_DOWNLOAD_RDY); if (err) { - lbs_pr_err("timed out waiting for host_int_status\n"); + pr_err("timed out waiting for host_int_status\n"); return err; } @@ -567,9 +568,8 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, return err; if (len > IF_SPI_CMD_BUF_SIZE) { - lbs_pr_err("firmware load device requested a larger " - "tranfer than we are prepared to " - "handle. (len = %d)\n", len); + pr_err("firmware load device requested a larger transfer than we are prepared to handle (len = %d)\n", + len); return -EIO; } if (len & 0x1) { @@ -598,8 +598,8 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card, err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); if (err) { - lbs_pr_err("%s: timed out waiting for initial " - "scratch reg = 0\n", __func__); + pr_err("%s: timed out waiting for initial scratch reg = 0\n", + __func__); goto out; } @@ -617,15 +617,13 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card, * If there are no more bytes left, we would normally * expect to have terminated with len = 0 */ - lbs_pr_err("Firmware load wants more bytes " - "than we have to offer.\n"); + pr_err("Firmware load wants more bytes than we have to offer.\n"); break; } if (crc_err) { /* Previous transfer failed. */ if (++num_crc_errs > MAX_MAIN_FW_LOAD_CRC_ERR) { - lbs_pr_err("Too many CRC errors encountered " - "in firmware load.\n"); + pr_err("Too many CRC errors encountered in firmware load.\n"); err = -EIO; goto out; } @@ -654,21 +652,20 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card, prev_len = len; } if (bytes > prev_len) { - lbs_pr_err("firmware load wants fewer bytes than " - "we have to offer.\n"); + pr_err("firmware load wants fewer bytes than we have to offer\n"); } /* Confirm firmware download */ err = spu_wait_for_u32(card, IF_SPI_SCRATCH_4_REG, SUCCESSFUL_FW_DOWNLOAD_MAGIC); if (err) { - lbs_pr_err("failed to confirm the firmware download\n"); + pr_err("failed to confirm the firmware download\n"); goto out; } out: if (err) - lbs_pr_err("failed to load firmware (err=%d)\n", err); + pr_err("failed to load firmware (err=%d)\n", err); lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err); return err; } @@ -709,14 +706,12 @@ static int if_spi_c2h_cmd(struct if_spi_card *card) if (err) goto out; if (!len) { - lbs_pr_err("%s: error: card has no data for host\n", - __func__); + pr_err("%s: error: card has no data for host\n", __func__); err = -EINVAL; goto out; } else if (len > IF_SPI_CMD_BUF_SIZE) { - lbs_pr_err("%s: error: response packet too large: " - "%d bytes, but maximum is %d\n", - __func__, len, IF_SPI_CMD_BUF_SIZE); + pr_err("%s: error: response packet too large: %d bytes, but maximum is %d\n", + __func__, len, IF_SPI_CMD_BUF_SIZE); err = -EINVAL; goto out; } @@ -737,7 +732,7 @@ static int if_spi_c2h_cmd(struct if_spi_card *card) out: if (err) - lbs_pr_err("%s: err=%d\n", __func__, err); + pr_err("%s: err=%d\n", __func__, err); lbs_deb_leave(LBS_DEB_SPI); return err; } @@ -757,14 +752,12 @@ static int if_spi_c2h_data(struct if_spi_card *card) if (err) goto out; if (!len) { - lbs_pr_err("%s: error: card has no data for host\n", - __func__); + pr_err("%s: error: card has no data for host\n", __func__); err = -EINVAL; goto out; } else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { - lbs_pr_err("%s: error: card has %d bytes of data, but " - "our maximum skb size is %zu\n", - __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); + pr_err("%s: error: card has %d bytes of data, but our maximum skb size is %zu\n", + __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); err = -EINVAL; goto out; } @@ -795,7 +788,7 @@ free_skb: dev_kfree_skb(skb); out: if (err) - lbs_pr_err("%s: err=%d\n", __func__, err); + pr_err("%s: err=%d\n", __func__, err); lbs_deb_leave(LBS_DEB_SPI); return err; } @@ -817,7 +810,7 @@ static void if_spi_h2c(struct if_spi_card *card, port_reg = IF_SPI_CMD_RDWRPORT_REG; break; default: - lbs_pr_err("can't transfer buffer of type %d\n", type); + pr_err("can't transfer buffer of type %d\n", type); err = -EINVAL; goto out; } @@ -831,7 +824,7 @@ out: kfree(packet); if (err) - lbs_pr_err("%s: error %d\n", __func__, err); + pr_err("%s: error %d\n", __func__, err); } /* Inform the host about a card event */ @@ -855,7 +848,7 @@ static void if_spi_e2h(struct if_spi_card *card) lbs_queue_event(priv, cause & 0xff); out: if (err) - lbs_pr_err("%s: error %d\n", __func__, err); + pr_err("%s: error %d\n", __func__, err); } static void if_spi_host_to_card_worker(struct work_struct *work) @@ -877,7 +870,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work) err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG, &hiStatus); if (err) { - lbs_pr_err("I/O error\n"); + pr_err("I/O error\n"); goto err; } @@ -940,7 +933,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work) err: if (err) - lbs_pr_err("%s: got error %d\n", __func__, err); + pr_err("%s: got error %d\n", __func__, err); lbs_deb_leave(LBS_DEB_SPI); } @@ -963,7 +956,7 @@ static int if_spi_host_to_card(struct lbs_private *priv, lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); if (nb == 0) { - lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb); + pr_err("%s: invalid size requested: %d\n", __func__, nb); err = -EINVAL; goto out; } @@ -991,7 +984,7 @@ static int if_spi_host_to_card(struct lbs_private *priv, spin_unlock_irqrestore(&card->buffer_lock, flags); break; default: - lbs_pr_err("can't transfer buffer of type %d", type); + pr_err("can't transfer buffer of type %d\n", type); err = -EINVAL; break; } @@ -1052,8 +1045,7 @@ static int if_spi_init_card(struct if_spi_card *card) break; } if (i == ARRAY_SIZE(fw_table)) { - lbs_pr_err("Unsupported chip_id: 0x%02x\n", - card->card_id); + pr_err("Unsupported chip_id: 0x%02x\n", card->card_id); err = -ENODEV; goto out; } @@ -1062,7 +1054,7 @@ static int if_spi_init_card(struct if_spi_card *card) card->card_id, &fw_table[0], &helper, &mainfw); if (err) { - lbs_pr_err("failed to find firmware (%d)\n", err); + pr_err("failed to find firmware (%d)\n", err); goto out; } @@ -1187,7 +1179,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) err = request_irq(spi->irq, if_spi_host_interrupt, IRQF_TRIGGER_FALLING, "libertas_spi", card); if (err) { - lbs_pr_err("can't get host irq line-- request_irq failed\n"); + pr_err("can't get host irq line-- request_irq failed\n"); goto terminate_workqueue; } diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index e1e2128f4113..b68e162bc323 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -1,6 +1,9 @@ /* * This file contains functions used in USB interface module. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -153,7 +156,7 @@ static void if_usb_write_bulk_callback(struct urb *urb) lbs_host_to_card_done(priv); } else { /* print the failure status number for debug */ - lbs_pr_info("URB in failure status: %d\n", urb->status); + pr_info("URB in failure status: %d\n", urb->status); } } @@ -203,7 +206,7 @@ static void if_usb_setup_firmware(struct lbs_private *priv) wake_method.hdr.size = cpu_to_le16(sizeof(wake_method)); wake_method.action = cpu_to_le16(CMD_ACT_GET); if (lbs_cmd_with_response(priv, CMD_802_11_FW_WAKE_METHOD, &wake_method)) { - lbs_pr_info("Firmware does not seem to support PS mode\n"); + pr_info("Firmware does not seem to support PS mode\n"); priv->fwcapinfo &= ~FW_CAPINFO_PS; } else { if (le16_to_cpu(wake_method.method) == CMD_WAKE_METHOD_COMMAND_INT) { @@ -212,7 +215,7 @@ static void if_usb_setup_firmware(struct lbs_private *priv) /* The versions which boot up this way don't seem to work even if we set it to the command interrupt */ priv->fwcapinfo &= ~FW_CAPINFO_PS; - lbs_pr_info("Firmware doesn't wake via command interrupt; disabling PS mode\n"); + pr_info("Firmware doesn't wake via command interrupt; disabling PS mode\n"); } } } @@ -224,7 +227,7 @@ static void if_usb_fw_timeo(unsigned long priv) if (cardp->fwdnldover) { lbs_deb_usb("Download complete, no event. Assuming success\n"); } else { - lbs_pr_err("Download timed out\n"); + pr_err("Download timed out\n"); cardp->surprise_removed = 1; } wake_up(&cardp->fw_wq); @@ -258,7 +261,7 @@ static int if_usb_probe(struct usb_interface *intf, cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL); if (!cardp) { - lbs_pr_err("Out of memory allocating private data.\n"); + pr_err("Out of memory allocating private data\n"); goto error; } @@ -348,10 +351,10 @@ static int if_usb_probe(struct usb_interface *intf, usb_set_intfdata(intf, cardp); if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_fw)) - lbs_pr_err("cannot register lbs_flash_fw attribute\n"); + pr_err("cannot register lbs_flash_fw attribute\n"); if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2)) - lbs_pr_err("cannot register lbs_flash_boot2 attribute\n"); + pr_err("cannot register lbs_flash_boot2 attribute\n"); /* * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. @@ -536,7 +539,7 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, int ret = -1; if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) { - lbs_pr_err("No free skb\n"); + pr_err("No free skb\n"); goto rx_ret; } @@ -595,7 +598,7 @@ static void if_usb_receive_fwload(struct urb *urb) if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) && tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) { - lbs_pr_info("Firmware ready event received\n"); + pr_info("Firmware ready event received\n"); wake_up(&cardp->fw_wq); } else { lbs_deb_usb("Waiting for confirmation; got %x %x\n", @@ -622,20 +625,20 @@ static void if_usb_receive_fwload(struct urb *urb) bootcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) || bootcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) { if (!cardp->bootcmdresp) - lbs_pr_info("Firmware already seems alive; resetting\n"); + pr_info("Firmware already seems alive; resetting\n"); cardp->bootcmdresp = -1; } else { - lbs_pr_info("boot cmd response wrong magic number (0x%x)\n", + pr_info("boot cmd response wrong magic number (0x%x)\n", le32_to_cpu(bootcmdresp.magic)); } } else if ((bootcmdresp.cmd != BOOT_CMD_FW_BY_USB) && (bootcmdresp.cmd != BOOT_CMD_UPDATE_FW) && (bootcmdresp.cmd != BOOT_CMD_UPDATE_BOOT2)) { - lbs_pr_info("boot cmd response cmd_tag error (%d)\n", - bootcmdresp.cmd); + pr_info("boot cmd response cmd_tag error (%d)\n", + bootcmdresp.cmd); } else if (bootcmdresp.result != BOOT_CMD_RESP_OK) { - lbs_pr_info("boot cmd response result error (%d)\n", - bootcmdresp.result); + pr_info("boot cmd response result error (%d)\n", + bootcmdresp.result); } else { cardp->bootcmdresp = 1; lbs_deb_usbd(&cardp->udev->dev, @@ -901,7 +904,7 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen) } while (!exit); if (ret) - lbs_pr_err("firmware file format check FAIL\n"); + pr_err("firmware file format check FAIL\n"); else lbs_deb_fw("firmware file format check PASS\n"); @@ -998,7 +1001,7 @@ static int __if_usb_prog_firmware(struct if_usb_card *cardp, ret = get_fw(cardp, fwname); if (ret) { - lbs_pr_err("failed to find firmware (%d)\n", ret); + pr_err("failed to find firmware (%d)\n", ret); goto done; } @@ -1073,13 +1076,13 @@ restart: usb_kill_urb(cardp->rx_urb); if (!cardp->fwdnldover) { - lbs_pr_info("failed to load fw, resetting device!\n"); + pr_info("failed to load fw, resetting device!\n"); if (--reset_count >= 0) { if_usb_reset_device(cardp); goto restart; } - lbs_pr_info("FW download failure, time = %d ms\n", i * 100); + pr_info("FW download failure, time = %d ms\n", i * 100); ret = -EIO; goto release_fw; } diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index ae02e6b7bc41..1144afddd5eb 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -4,6 +4,8 @@ * thread etc.. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -442,7 +444,7 @@ static int lbs_thread(void *data) if (priv->cmd_timed_out && priv->cur_cmd) { struct cmd_ctrl_node *cmdnode = priv->cur_cmd; - lbs_pr_info("Timeout submitting command 0x%04x\n", + pr_info("Timeout submitting command 0x%04x\n", le16_to_cpu(cmdnode->cmdbuf->command)); lbs_complete_command(priv, cmdnode, -ETIMEDOUT); if (priv->reset_card) @@ -470,8 +472,7 @@ static int lbs_thread(void *data) * after firmware fixes it */ priv->psstate = PS_STATE_AWAKE; - lbs_pr_alert("ignore PS_SleepConfirm in " - "non-connected state\n"); + pr_alert("ignore PS_SleepConfirm in non-connected state\n"); } } @@ -565,7 +566,7 @@ int lbs_suspend(struct lbs_private *priv) if (priv->is_deep_sleep) { ret = lbs_set_deep_sleep(priv, 0); if (ret) { - lbs_pr_err("deep sleep cancellation failed: %d\n", ret); + pr_err("deep sleep cancellation failed: %d\n", ret); return ret; } priv->deep_sleep_required = 1; @@ -598,7 +599,7 @@ int lbs_resume(struct lbs_private *priv) priv->deep_sleep_required = 0; ret = lbs_set_deep_sleep(priv, 1); if (ret) - lbs_pr_err("deep sleep activation failed: %d\n", ret); + pr_err("deep sleep activation failed: %d\n", ret); } if (priv->setup_fw_on_resume) @@ -626,7 +627,7 @@ static void lbs_cmd_timeout_handler(unsigned long data) if (!priv->cur_cmd) goto out; - lbs_pr_info("command 0x%04x timed out\n", + pr_info("command 0x%04x timed out\n", le16_to_cpu(priv->cur_cmd->cmdbuf->command)); priv->cmd_timed_out = 1; @@ -732,7 +733,7 @@ static int lbs_init_adapter(struct lbs_private *priv) /* Allocate the command buffers */ if (lbs_allocate_cmd_buffer(priv)) { - lbs_pr_err("Out of memory allocating command buffers\n"); + pr_err("Out of memory allocating command buffers\n"); ret = -ENOMEM; goto out; } @@ -742,7 +743,7 @@ static int lbs_init_adapter(struct lbs_private *priv) /* Create the event FIFO */ ret = kfifo_alloc(&priv->event_fifo, sizeof(u32) * 16, GFP_KERNEL); if (ret) { - lbs_pr_err("Out of memory allocating event FIFO buffer\n"); + pr_err("Out of memory allocating event FIFO buffer\n"); goto out; } @@ -793,7 +794,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) /* Allocate an Ethernet device and register it */ wdev = lbs_cfg_alloc(dmdev); if (IS_ERR(wdev)) { - lbs_pr_err("cfg80211 init failed\n"); + pr_err("cfg80211 init failed\n"); goto done; } @@ -802,7 +803,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) priv->wdev = wdev; if (lbs_init_adapter(priv)) { - lbs_pr_err("failed to initialize adapter structure.\n"); + pr_err("failed to initialize adapter structure\n"); goto err_wdev; } @@ -934,7 +935,7 @@ int lbs_start_card(struct lbs_private *priv) goto done; if (lbs_cfg_register(priv)) { - lbs_pr_err("cannot register device\n"); + pr_err("cannot register device\n"); goto done; } @@ -944,7 +945,7 @@ int lbs_start_card(struct lbs_private *priv) lbs_debugfs_init_one(priv, dev); - lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); + pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); ret = 0; @@ -1071,16 +1072,14 @@ int lbs_get_firmware(struct device *dev, const char *user_helper, if (user_helper) { ret = request_firmware(helper, user_helper, dev); if (ret) { - lbs_pr_err("couldn't find helper firmware %s", - user_helper); + pr_err("couldn't find helper firmware %s", user_helper); goto fail; } } if (user_mainfw) { ret = request_firmware(mainfw, user_mainfw, dev); if (ret) { - lbs_pr_err("couldn't find main firmware %s", - user_mainfw); + pr_err("couldn't find main firmware %s", user_mainfw); goto fail; } } diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index a0804d12bf20..054ac07862fd 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c @@ -1,3 +1,5 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -267,7 +269,7 @@ int lbs_init_mesh(struct lbs_private *priv) lbs_add_mesh(priv); if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) - lbs_pr_err("cannot register lbs_mesh attribute\n"); + pr_err("cannot register lbs_mesh attribute\n"); ret = 1; } @@ -395,7 +397,7 @@ int lbs_add_mesh(struct lbs_private *priv) /* Register virtual mesh interface */ ret = register_netdev(mesh_dev); if (ret) { - lbs_pr_err("cannot register mshX virtual interface\n"); + pr_err("cannot register mshX virtual interface\n"); goto err_free; } @@ -973,7 +975,7 @@ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, return ret; if (defs.meshie.val.mesh_id_len > IEEE80211_MAX_SSID_LEN) { - lbs_pr_err("inconsistent mesh ID length"); + pr_err("inconsistent mesh ID length\n"); defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN; } diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index a3f4b55aa41f..24a12daa7c67 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -1,6 +1,9 @@ /* * This file contains the handling of RX in wlan driver. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -191,7 +194,7 @@ static u8 convert_mv_rate_to_radiotap(u8 rate) case 12: /* 54 Mbps */ return 108; } - lbs_pr_alert("Invalid Marvell WLAN rate %i\n", rate); + pr_alert("Invalid Marvell WLAN rate %i\n", rate); return 0; } @@ -248,7 +251,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, /* add space for the new radio header */ if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) && pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) { - lbs_pr_alert("%s: couldn't pskb_expand_head\n", __func__); + pr_alert("%s: couldn't pskb_expand_head\n", __func__); ret = -ENOMEM; kfree_skb(skb); goto done; -- cgit v1.2.3-58-ga151 From f3a57fd148a4afd3c38f558c5b44972cb29ea8ba Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 2 May 2011 16:49:15 -0700 Subject: libertas: Use netdev_ or dev_ where possible Using the more descriptive logging styles gives a bit more information about the device being operated on. Makes the object trivially smaller too. $ size drivers/net/wireless/libertas/built-in.o.* 187730 2973 38488 229191 37f47 drivers/net/wireless/libertas/built-in.o.new 188195 2973 38488 229656 38118 drivers/net/wireless/libertas/built-in.o.old Signed-off-by: Joe Perches Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cfg.c | 9 +++--- drivers/net/wireless/libertas/cmd.c | 42 +++++++++++++----------- drivers/net/wireless/libertas/cmdresp.c | 32 +++++++++--------- drivers/net/wireless/libertas/debugfs.c | 7 ++-- drivers/net/wireless/libertas/if_cs.c | 15 ++++++--- drivers/net/wireless/libertas/if_sdio.c | 19 +++++------ drivers/net/wireless/libertas/if_spi.c | 57 +++++++++++++++++++++------------ drivers/net/wireless/libertas/if_usb.c | 11 ++++--- drivers/net/wireless/libertas/main.c | 25 +++++++++------ drivers/net/wireless/libertas/mesh.c | 4 +-- drivers/net/wireless/libertas/rx.c | 2 +- 11 files changed, 130 insertions(+), 93 deletions(-) diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 73c5f54c9b42..a2e88498c096 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -1324,7 +1324,8 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, sme->ssid, sme->ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (!bss) { - pr_err("assoc: bss %pM not in scan results\n", sme->bssid); + wiphy_err(wiphy, "assoc: bss %pM not in scan results\n", + sme->bssid); ret = -ENOENT; goto done; } @@ -1381,8 +1382,8 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, lbs_enable_rsn(priv, sme->crypto.cipher_group != 0); break; default: - pr_err("unsupported cipher group 0x%x\n", - sme->crypto.cipher_group); + wiphy_err(wiphy, "unsupported cipher group 0x%x\n", + sme->crypto.cipher_group); ret = -ENOTSUPP; goto done; } @@ -1500,7 +1501,7 @@ static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev, params->key, params->key_len); break; default: - pr_err("unhandled cipher 0x%x\n", params->cipher); + wiphy_err(wiphy, "unhandled cipher 0x%x\n", params->cipher); ret = -ENOTSUPP; break; } diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index af8ef90a122a..6d59b4cf8fce 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -3,8 +3,6 @@ * It prepares command and sends it to firmware when it is ready. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -112,7 +110,7 @@ int lbs_update_hw_spec(struct lbs_private *priv) * CF card firmware 5.0.16p0: cap 0x00000303 * USB dongle firmware 5.110.17p2: cap 0x00000303 */ - pr_info("%pM, fw %u.%u.%up%u, cap 0x%08x\n", + netdev_info(priv->dev, "%pM, fw %u.%u.%up%u, cap 0x%08x\n", cmd.permanentaddr, priv->fwrelease >> 24 & 0xff, priv->fwrelease >> 16 & 0xff, @@ -143,7 +141,8 @@ int lbs_update_hw_spec(struct lbs_private *priv) /* if it's unidentified region code, use the default (USA) */ if (i >= MRVDRV_MAX_REGION_CODE) { priv->regioncode = 0x10; - pr_info("unidentified region code; using the default (USA)\n"); + netdev_info(priv->dev, + "unidentified region code; using the default (USA)\n"); } if (priv->current_addr[0] == 0xff) @@ -213,7 +212,7 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, (uint8_t *)&cmd_config.wol_conf, sizeof(struct wol_config)); } else { - pr_info("HOST_SLEEP_CFG failed %d\n", ret); + netdev_info(priv->dev, "HOST_SLEEP_CFG failed %d\n", ret); } return ret; @@ -316,7 +315,7 @@ static int lbs_wait_for_ds_awake(struct lbs_private *priv) if (priv->is_deep_sleep) { if (!wait_event_interruptible_timeout(priv->ds_awake_q, !priv->is_deep_sleep, (10 * HZ))) { - pr_err("ds_awake_q: timer expired\n"); + netdev_err(priv->dev, "ds_awake_q: timer expired\n"); ret = -1; } } @@ -341,7 +340,7 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) netif_carrier_off(priv->dev); } } else { - pr_err("deep sleep: already enabled\n"); + netdev_err(priv->dev, "deep sleep: already enabled\n"); } } else { if (priv->is_deep_sleep) { @@ -351,7 +350,8 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) if (!ret) { ret = lbs_wait_for_ds_awake(priv); if (ret) - pr_err("deep sleep: wakeup failed\n"); + netdev_err(priv->dev, + "deep sleep: wakeup failed\n"); } } } @@ -385,8 +385,9 @@ int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep) ret = lbs_host_sleep_cfg(priv, priv->wol_criteria, (struct wol_config *)NULL); if (ret) { - pr_info("Host sleep configuration failed: %d\n", - ret); + netdev_info(priv->dev, + "Host sleep configuration failed: %d\n", + ret); return ret; } if (priv->psstate == PS_STATE_FULL_POWER) { @@ -396,19 +397,21 @@ int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep) sizeof(cmd), lbs_ret_host_sleep_activate, 0); if (ret) - pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", - ret); + netdev_info(priv->dev, + "HOST_SLEEP_ACTIVATE failed: %d\n", + ret); } if (!wait_event_interruptible_timeout( priv->host_sleep_q, priv->is_host_sleep_activated, (10 * HZ))) { - pr_err("host_sleep_q: timer expired\n"); + netdev_err(priv->dev, + "host_sleep_q: timer expired\n"); ret = -1; } } else { - pr_err("host sleep: already enabled\n"); + netdev_err(priv->dev, "host sleep: already enabled\n"); } } else { if (priv->is_host_sleep_activated) @@ -1008,7 +1011,8 @@ static void lbs_submit_command(struct lbs_private *priv, ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize); if (ret) { - pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret); + netdev_info(priv->dev, "DNLD_CMD: hw_host_to_card failed: %d\n", + ret); /* Let the timer kick in and retry, and potentially reset the whole thing if the condition persists */ timeo = HZ/4; @@ -1277,7 +1281,8 @@ int lbs_execute_next_command(struct lbs_private *priv) spin_lock_irqsave(&priv->driver_lock, flags); if (priv->cur_cmd) { - pr_alert( "EXEC_NEXT_CMD: already processing command!\n"); + netdev_alert(priv->dev, + "EXEC_NEXT_CMD: already processing command!\n"); spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; @@ -1439,7 +1444,7 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep, sizeof(confirm_sleep)); if (ret) { - pr_alert("confirm_sleep failed\n"); + netdev_alert(priv->dev, "confirm_sleep failed\n"); goto out; } @@ -1665,7 +1670,8 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command, spin_lock_irqsave(&priv->driver_lock, flags); ret = cmdnode->result; if (ret) - pr_info("PREP_CMD: command 0x%04x failed: %d\n", command, ret); + netdev_info(priv->dev, "PREP_CMD: command 0x%04x failed: %d\n", + command, ret); __lbs_cleanup_and_insert_cmd(priv, cmdnode); spin_unlock_irqrestore(&priv->driver_lock, flags); diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 45291a4c2a9f..207fc361db84 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -3,8 +3,6 @@ * responses as well as events generated by firmware. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -88,17 +86,18 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len); if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { - pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n", - le16_to_cpu(resp->seqnum), - le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum)); + netdev_info(priv->dev, + "Received CMD_RESP with invalid sequence %d (expected %d)\n", + le16_to_cpu(resp->seqnum), + le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum)); spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; } if (respcmd != CMD_RET(curcmd) && respcmd != CMD_RET_802_11_ASSOCIATE && curcmd != CMD_802_11_ASSOCIATE) { - pr_info("Invalid CMD_RESP %x to command %x!\n", - respcmd, curcmd); + netdev_info(priv->dev, "Invalid CMD_RESP %x to command %x!\n", + respcmd, curcmd); spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; @@ -107,8 +106,9 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) if (resp->result == cpu_to_le16(0x0004)) { /* 0x0004 means -EAGAIN. Drop the response, let it time out and be resubmitted */ - pr_info("Firmware returns DEFER to command %x. Will let it time out...\n", - le16_to_cpu(resp->command)); + netdev_info(priv->dev, + "Firmware returns DEFER to command %x. Will let it time out...\n", + le16_to_cpu(resp->command)); spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; @@ -319,28 +319,28 @@ int lbs_process_event(struct lbs_private *priv, u32 event) lbs_deb_cmd("EVENT: ADHOC beacon lost\n"); break; case MACREG_INT_CODE_RSSI_LOW: - pr_alert("EVENT: rssi low\n"); + netdev_alert(priv->dev, "EVENT: rssi low\n"); break; case MACREG_INT_CODE_SNR_LOW: - pr_alert("EVENT: snr low\n"); + netdev_alert(priv->dev, "EVENT: snr low\n"); break; case MACREG_INT_CODE_MAX_FAIL: - pr_alert("EVENT: max fail\n"); + netdev_alert(priv->dev, "EVENT: max fail\n"); break; case MACREG_INT_CODE_RSSI_HIGH: - pr_alert("EVENT: rssi high\n"); + netdev_alert(priv->dev, "EVENT: rssi high\n"); break; case MACREG_INT_CODE_SNR_HIGH: - pr_alert("EVENT: snr high\n"); + netdev_alert(priv->dev, "EVENT: snr high\n"); break; case MACREG_INT_CODE_MESH_AUTO_STARTED: /* Ignore spurious autostart events */ - pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n"); + netdev_info(priv->dev, "EVENT: MESH_AUTO_STARTED (ignoring)\n"); break; default: - pr_alert("EVENT: unknown event id %d\n", event); + netdev_alert(priv->dev, "EVENT: unknown event id %d\n", event); break; } diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 0bd79c5f5b5b..23250f621761 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -1,5 +1,3 @@ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -153,13 +151,14 @@ static ssize_t lbs_host_sleep_write(struct file *file, ret = lbs_set_host_sleep(priv, 0); else if (host_sleep == 1) { if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { - pr_info("wake parameters not configured\n"); + netdev_info(priv->dev, + "wake parameters not configured\n"); ret = -EINVAL; goto out_unlock; } ret = lbs_set_host_sleep(priv, 1); } else { - pr_err("invalid option\n"); + netdev_err(priv->dev, "invalid option\n"); ret = -EINVAL; } diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index f2d10115f5e5..63ed5798365c 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -364,7 +364,7 @@ static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb) if (status & IF_CS_BIT_COMMAND) break; if (++loops > 100) { - pr_err("card not ready for commands\n"); + netdev_err(priv->dev, "card not ready for commands\n"); goto done; } mdelay(1); @@ -434,14 +434,16 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) /* is hardware ready? */ status = if_cs_read16(priv->card, IF_CS_CARD_STATUS); if ((status & IF_CS_BIT_RESP) == 0) { - pr_err("no cmd response in card\n"); + netdev_err(priv->dev, "no cmd response in card\n"); *len = 0; goto out; } *len = if_cs_read16(priv->card, IF_CS_RESP_LEN); if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) { - pr_err("card cmd buffer has invalid # of bytes (%d)\n", *len); + netdev_err(priv->dev, + "card cmd buffer has invalid # of bytes (%d)\n", + *len); goto out; } @@ -475,7 +477,9 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) len = if_cs_read16(priv->card, IF_CS_READ_LEN); if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { - pr_err("card data buffer has invalid # of bytes (%d)\n", len); + netdev_err(priv->dev, + "card data buffer has invalid # of bytes (%d)\n", + len); priv->dev->stats.rx_dropped++; goto dat_err; } @@ -761,7 +765,8 @@ static int if_cs_host_to_card(struct lbs_private *priv, ret = if_cs_send_cmd(priv, buf, nb); break; default: - pr_err("%s: unsupported type %d\n", __func__, type); + netdev_err(priv->dev, "%s: unsupported type %d\n", + __func__, type); } lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index ab867795f542..a7b5cb0c2753 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -851,7 +851,7 @@ static int if_sdio_enter_deep_sleep(struct lbs_private *priv) ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd), lbs_cmd_copyback, (unsigned long) &cmd); if (ret) - pr_err("DEEP_SLEEP cmd failed\n"); + netdev_err(priv->dev, "DEEP_SLEEP cmd failed\n"); mdelay(200); return ret; @@ -867,7 +867,7 @@ static int if_sdio_exit_deep_sleep(struct lbs_private *priv) sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret); if (ret) - pr_err("sdio_writeb failed!\n"); + netdev_err(priv->dev, "sdio_writeb failed!\n"); sdio_release_host(card->func); lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); @@ -884,7 +884,7 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv) sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret); if (ret) - pr_err("sdio_writeb failed!\n"); + netdev_err(priv->dev, "sdio_writeb failed!\n"); sdio_release_host(card->func); lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); @@ -1103,7 +1103,7 @@ static int if_sdio_probe(struct sdio_func *func, lbs_deb_sdio("send function INIT command\n"); if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd), lbs_cmd_copyback, (unsigned long) &cmd)) - pr_alert("CMD_FUNC_INIT cmd failed\n"); + netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n"); } ret = lbs_start_card(priv); @@ -1204,19 +1204,20 @@ static int if_sdio_suspend(struct device *dev) mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); - pr_info("%s: suspend: PM flags = 0x%x\n", sdio_func_id(func), flags); + dev_info(dev, "%s: suspend: PM flags = 0x%x\n", + sdio_func_id(func), flags); /* If we aren't being asked to wake on anything, we should bail out * and let the SD stack power down the card. */ if (card->priv->wol_criteria == EHS_REMOVE_WAKEUP) { - pr_info("Suspend without wake params -- powering down card\n"); + dev_info(dev, "Suspend without wake params -- powering down card\n"); return -ENOSYS; } if (!(flags & MMC_PM_KEEP_POWER)) { - pr_err("%s: cannot remain alive while host is suspended\n", - sdio_func_id(func)); + dev_err(dev, "%s: cannot remain alive while host is suspended\n", + sdio_func_id(func)); return -ENOSYS; } @@ -1237,7 +1238,7 @@ static int if_sdio_resume(struct device *dev) struct if_sdio_card *card = sdio_get_drvdata(func); int ret; - pr_info("%s: resume: we're back\n", sdio_func_id(func)); + dev_info(dev, "%s: resume: we're back\n", sdio_func_id(func)); ret = lbs_resume(card->priv); diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 4d19b5726c15..463352c890d7 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -585,6 +585,7 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, static int if_spi_prog_main_firmware(struct if_spi_card *card, const struct firmware *firmware) { + struct lbs_private *priv = card->priv; int len, prev_len; int bytes, crc_err = 0, err = 0; const u8 *fw; @@ -598,8 +599,9 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card, err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); if (err) { - pr_err("%s: timed out waiting for initial scratch reg = 0\n", - __func__); + netdev_err(priv->dev, + "%s: timed out waiting for initial scratch reg = 0\n", + __func__); goto out; } @@ -617,7 +619,8 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card, * If there are no more bytes left, we would normally * expect to have terminated with len = 0 */ - pr_err("Firmware load wants more bytes than we have to offer.\n"); + netdev_err(priv->dev, + "Firmware load wants more bytes than we have to offer.\n"); break; } if (crc_err) { @@ -706,12 +709,14 @@ static int if_spi_c2h_cmd(struct if_spi_card *card) if (err) goto out; if (!len) { - pr_err("%s: error: card has no data for host\n", __func__); + netdev_err(priv->dev, "%s: error: card has no data for host\n", + __func__); err = -EINVAL; goto out; } else if (len > IF_SPI_CMD_BUF_SIZE) { - pr_err("%s: error: response packet too large: %d bytes, but maximum is %d\n", - __func__, len, IF_SPI_CMD_BUF_SIZE); + netdev_err(priv->dev, + "%s: error: response packet too large: %d bytes, but maximum is %d\n", + __func__, len, IF_SPI_CMD_BUF_SIZE); err = -EINVAL; goto out; } @@ -732,7 +737,7 @@ static int if_spi_c2h_cmd(struct if_spi_card *card) out: if (err) - pr_err("%s: err=%d\n", __func__, err); + netdev_err(priv->dev, "%s: err=%d\n", __func__, err); lbs_deb_leave(LBS_DEB_SPI); return err; } @@ -740,6 +745,7 @@ out: /* Move data from the card to the host */ static int if_spi_c2h_data(struct if_spi_card *card) { + struct lbs_private *priv = card->priv; struct sk_buff *skb; char *data; u16 len; @@ -752,12 +758,14 @@ static int if_spi_c2h_data(struct if_spi_card *card) if (err) goto out; if (!len) { - pr_err("%s: error: card has no data for host\n", __func__); + netdev_err(priv->dev, "%s: error: card has no data for host\n", + __func__); err = -EINVAL; goto out; } else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { - pr_err("%s: error: card has %d bytes of data, but our maximum skb size is %zu\n", - __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); + netdev_err(priv->dev, + "%s: error: card has %d bytes of data, but our maximum skb size is %zu\n", + __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); err = -EINVAL; goto out; } @@ -788,7 +796,7 @@ free_skb: dev_kfree_skb(skb); out: if (err) - pr_err("%s: err=%d\n", __func__, err); + netdev_err(priv->dev, "%s: err=%d\n", __func__, err); lbs_deb_leave(LBS_DEB_SPI); return err; } @@ -797,6 +805,7 @@ out: static void if_spi_h2c(struct if_spi_card *card, struct if_spi_packet *packet, int type) { + struct lbs_private *priv = card->priv; int err = 0; u16 int_type, port_reg; @@ -810,7 +819,8 @@ static void if_spi_h2c(struct if_spi_card *card, port_reg = IF_SPI_CMD_RDWRPORT_REG; break; default: - pr_err("can't transfer buffer of type %d\n", type); + netdev_err(priv->dev, "can't transfer buffer of type %d\n", + type); err = -EINVAL; goto out; } @@ -824,7 +834,7 @@ out: kfree(packet); if (err) - pr_err("%s: error %d\n", __func__, err); + netdev_err(priv->dev, "%s: error %d\n", __func__, err); } /* Inform the host about a card event */ @@ -848,7 +858,7 @@ static void if_spi_e2h(struct if_spi_card *card) lbs_queue_event(priv, cause & 0xff); out: if (err) - pr_err("%s: error %d\n", __func__, err); + netdev_err(priv->dev, "%s: error %d\n", __func__, err); } static void if_spi_host_to_card_worker(struct work_struct *work) @@ -858,8 +868,10 @@ static void if_spi_host_to_card_worker(struct work_struct *work) u16 hiStatus; unsigned long flags; struct if_spi_packet *packet; + struct lbs_private *priv; card = container_of(work, struct if_spi_card, packet_work); + priv = card->priv; lbs_deb_enter(LBS_DEB_SPI); @@ -870,7 +882,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work) err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG, &hiStatus); if (err) { - pr_err("I/O error\n"); + netdev_err(priv->dev, "I/O error\n"); goto err; } @@ -933,7 +945,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work) err: if (err) - pr_err("%s: got error %d\n", __func__, err); + netdev_err(priv->dev, "%s: got error %d\n", __func__, err); lbs_deb_leave(LBS_DEB_SPI); } @@ -956,7 +968,8 @@ static int if_spi_host_to_card(struct lbs_private *priv, lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); if (nb == 0) { - pr_err("%s: invalid size requested: %d\n", __func__, nb); + netdev_err(priv->dev, "%s: invalid size requested: %d\n", + __func__, nb); err = -EINVAL; goto out; } @@ -984,7 +997,8 @@ static int if_spi_host_to_card(struct lbs_private *priv, spin_unlock_irqrestore(&card->buffer_lock, flags); break; default: - pr_err("can't transfer buffer of type %d\n", type); + netdev_err(priv->dev, "can't transfer buffer of type %d\n", + type); err = -EINVAL; break; } @@ -1017,6 +1031,7 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) static int if_spi_init_card(struct if_spi_card *card) { + struct lbs_private *priv = card->priv; struct spi_device *spi = card->spi; int err, i; u32 scratch; @@ -1045,7 +1060,8 @@ static int if_spi_init_card(struct if_spi_card *card) break; } if (i == ARRAY_SIZE(fw_table)) { - pr_err("Unsupported chip_id: 0x%02x\n", card->card_id); + netdev_err(priv->dev, "Unsupported chip_id: 0x%02x\n", + card->card_id); err = -ENODEV; goto out; } @@ -1054,7 +1070,8 @@ static int if_spi_init_card(struct if_spi_card *card) card->card_id, &fw_table[0], &helper, &mainfw); if (err) { - pr_err("failed to find firmware (%d)\n", err); + netdev_err(priv->dev, "failed to find firmware (%d)\n", + err); goto out; } diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index b68e162bc323..b5acc393a65a 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -206,7 +206,7 @@ static void if_usb_setup_firmware(struct lbs_private *priv) wake_method.hdr.size = cpu_to_le16(sizeof(wake_method)); wake_method.action = cpu_to_le16(CMD_ACT_GET); if (lbs_cmd_with_response(priv, CMD_802_11_FW_WAKE_METHOD, &wake_method)) { - pr_info("Firmware does not seem to support PS mode\n"); + netdev_info(priv->dev, "Firmware does not seem to support PS mode\n"); priv->fwcapinfo &= ~FW_CAPINFO_PS; } else { if (le16_to_cpu(wake_method.method) == CMD_WAKE_METHOD_COMMAND_INT) { @@ -215,7 +215,8 @@ static void if_usb_setup_firmware(struct lbs_private *priv) /* The versions which boot up this way don't seem to work even if we set it to the command interrupt */ priv->fwcapinfo &= ~FW_CAPINFO_PS; - pr_info("Firmware doesn't wake via command interrupt; disabling PS mode\n"); + netdev_info(priv->dev, + "Firmware doesn't wake via command interrupt; disabling PS mode\n"); } } } @@ -351,10 +352,12 @@ static int if_usb_probe(struct usb_interface *intf, usb_set_intfdata(intf, cardp); if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_fw)) - pr_err("cannot register lbs_flash_fw attribute\n"); + netdev_err(priv->dev, + "cannot register lbs_flash_fw attribute\n"); if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2)) - pr_err("cannot register lbs_flash_boot2 attribute\n"); + netdev_err(priv->dev, + "cannot register lbs_flash_boot2 attribute\n"); /* * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 1144afddd5eb..84d05a765b5b 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -444,8 +444,8 @@ static int lbs_thread(void *data) if (priv->cmd_timed_out && priv->cur_cmd) { struct cmd_ctrl_node *cmdnode = priv->cur_cmd; - pr_info("Timeout submitting command 0x%04x\n", - le16_to_cpu(cmdnode->cmdbuf->command)); + netdev_info(dev, "Timeout submitting command 0x%04x\n", + le16_to_cpu(cmdnode->cmdbuf->command)); lbs_complete_command(priv, cmdnode, -ETIMEDOUT); if (priv->reset_card) priv->reset_card(priv); @@ -472,7 +472,8 @@ static int lbs_thread(void *data) * after firmware fixes it */ priv->psstate = PS_STATE_AWAKE; - pr_alert("ignore PS_SleepConfirm in non-connected state\n"); + netdev_alert(dev, + "ignore PS_SleepConfirm in non-connected state\n"); } } @@ -566,7 +567,8 @@ int lbs_suspend(struct lbs_private *priv) if (priv->is_deep_sleep) { ret = lbs_set_deep_sleep(priv, 0); if (ret) { - pr_err("deep sleep cancellation failed: %d\n", ret); + netdev_err(priv->dev, + "deep sleep cancellation failed: %d\n", ret); return ret; } priv->deep_sleep_required = 1; @@ -599,7 +601,8 @@ int lbs_resume(struct lbs_private *priv) priv->deep_sleep_required = 0; ret = lbs_set_deep_sleep(priv, 1); if (ret) - pr_err("deep sleep activation failed: %d\n", ret); + netdev_err(priv->dev, + "deep sleep activation failed: %d\n", ret); } if (priv->setup_fw_on_resume) @@ -627,8 +630,8 @@ static void lbs_cmd_timeout_handler(unsigned long data) if (!priv->cur_cmd) goto out; - pr_info("command 0x%04x timed out\n", - le16_to_cpu(priv->cur_cmd->cmdbuf->command)); + netdev_info(priv->dev, "command 0x%04x timed out\n", + le16_to_cpu(priv->cur_cmd->cmdbuf->command)); priv->cmd_timed_out = 1; wake_up_interruptible(&priv->waitq); @@ -945,7 +948,7 @@ int lbs_start_card(struct lbs_private *priv) lbs_debugfs_init_one(priv, dev); - pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); + netdev_info(dev, "Marvell WLAN 802.11 adapter\n"); ret = 0; @@ -1072,14 +1075,16 @@ int lbs_get_firmware(struct device *dev, const char *user_helper, if (user_helper) { ret = request_firmware(helper, user_helper, dev); if (ret) { - pr_err("couldn't find helper firmware %s", user_helper); + dev_err(dev, "couldn't find helper firmware %s\n", + user_helper); goto fail; } } if (user_mainfw) { ret = request_firmware(mainfw, user_mainfw, dev); if (ret) { - pr_err("couldn't find main firmware %s", user_mainfw); + dev_err(dev, "couldn't find main firmware %s\n", + user_mainfw); goto fail; } } diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 054ac07862fd..24cf06680c6b 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c @@ -269,7 +269,7 @@ int lbs_init_mesh(struct lbs_private *priv) lbs_add_mesh(priv); if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) - pr_err("cannot register lbs_mesh attribute\n"); + netdev_err(dev, "cannot register lbs_mesh attribute\n"); ret = 1; } @@ -975,7 +975,7 @@ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, return ret; if (defs.meshie.val.mesh_id_len > IEEE80211_MAX_SSID_LEN) { - pr_err("inconsistent mesh ID length\n"); + dev_err(dev, "inconsistent mesh ID length\n"); defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN; } diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 24a12daa7c67..fdb0448301a0 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -251,7 +251,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, /* add space for the new radio header */ if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) && pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) { - pr_alert("%s: couldn't pskb_expand_head\n", __func__); + netdev_alert(dev, "%s: couldn't pskb_expand_head\n", __func__); ret = -ENOMEM; kfree_skb(skb); goto done; -- cgit v1.2.3-58-ga151 From 2a7bccccdb9604a717c2128a931f022267d35629 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Mon, 9 May 2011 16:11:16 -0700 Subject: Bluetooth: Device ids for ath3k on Pegatron Lucid tablets New ath3k device IDs used on the Pegatron Lucid (ExoPC and WeTab) units. Signed-off-by: Andy Ross Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/ath3k.c | 1 + drivers/bluetooth/btusb.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 695d4414bd4c..6bacef368fab 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -62,6 +62,7 @@ static struct usb_device_id ath3k_table[] = { /* Atheros AR3011 with sflash firmware*/ { USB_DEVICE(0x0CF3, 0x3002) }, + { USB_DEVICE(0x13d3, 0x3304) }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03F0, 0x311D) }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 762a5109c68a..c2de8951e3fb 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -104,6 +104,7 @@ static struct usb_device_id blacklist_table[] = { /* Atheros 3011 with sflash firmware */ { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, -- cgit v1.2.3-58-ga151 From b3b1b061583ba4909b59a2f736825d86495fe956 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Fri, 6 May 2011 09:42:31 +0200 Subject: Bluetooth: Double check sec req for pre 2.1 device In case of pre v2.1 devices authentication request will return success immediately if the link key already exists without any authentication process. That means, it's not possible to re-authenticate the link if you already have combination key and for instance want to re-authenticate to get the high security (use 16 digit pin). Therefore, it's necessary to check security requirements on auth complete event to prevent not enough secure connection. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/hci_conn.c | 17 +++++++++++++++++ net/bluetooth/rfcomm/core.c | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 14cc3249c1eb..6c994c004d15 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -422,6 +422,7 @@ void hci_conn_check_pending(struct hci_dev *hdev); struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type); int hci_conn_check_link_mode(struct hci_conn *conn); +int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level); int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type); int hci_conn_change_link_key(struct hci_conn *conn); int hci_conn_switch_role(struct hci_conn *conn, __u8 role); diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 7f5ad8a2b22d..3163330cd4f1 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -623,6 +623,23 @@ encrypt: } EXPORT_SYMBOL(hci_conn_security); +/* Check secure link requirement */ +int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level) +{ + BT_DBG("conn %p", conn); + + if (sec_level != BT_SECURITY_HIGH) + return 1; /* Accept if non-secure is required */ + + if (conn->key_type == HCI_LK_AUTH_COMBINATION || + (conn->key_type == HCI_LK_COMBINATION && + conn->pin_length == 16)) + return 1; + + return 0; /* Reject not secure link */ +} +EXPORT_SYMBOL(hci_conn_check_secure); + /* Change link key */ int hci_conn_change_link_key(struct hci_conn *conn) { diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 121a5c13b989..5759bb7054f7 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -2096,7 +2096,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags)) continue; - if (!status) + if (!status && hci_conn_check_secure(conn, d->sec_level)) set_bit(RFCOMM_AUTH_ACCEPT, &d->flags); else set_bit(RFCOMM_AUTH_REJECT, &d->flags); -- cgit v1.2.3-58-ga151 From b130e5cec958bae3867cf6ab09a9b24ba8fada01 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 3 May 2011 16:57:07 -0700 Subject: nl80211: Introduce NL80211_MESH_SETUP_USERSPACE_AMPE Introduce a new configuration option to support AMPE from userspace. Prior to this series we only supported authentication in userspace: an authentication daemon would authenticate peer candidates in userspace and hand them over to the kernel. From that point the mesh stack would take over and establish a peer link (Mesh Peering Management). These patches introduce support for Authenticated Mesh Peering Exchange in userspace. The userspace daemon implements the AMPE protocol and on successfull completion create mesh peers and install encryption keys. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- include/linux/nl80211.h | 10 ++++++++++ include/net/cfg80211.h | 4 +++- net/mac80211/cfg.c | 6 +++++- net/mac80211/ieee80211_i.h | 6 +++++- net/mac80211/mesh.c | 2 +- net/mac80211/mesh_plink.c | 5 +++-- net/wireless/nl80211.c | 4 +++- 7 files changed, 30 insertions(+), 7 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index a75dea9c416e..c53b916036c5 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1769,6 +1769,15 @@ enum nl80211_meshconf_params { * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication * daemon will be authenticating mesh candidates. * + * @NL80211_MESH_SETUP_USERSPACE_AMPE: Enable this option if an authentication + * daemon will be securing peer link frames. AMPE is a secured version of Mesh + * Peering Management (MPM) and is implemented with the assistance of a + * userspace daemon. When this flag is set, the kernel will send peer + * management frames to a userspace daemon that will implement AMPE + * functionality (security capabilities selection, key confirmation, and key + * management). When the flag is unset (default), the kernel can autonomously + * complete (unsecured) mesh peering without the need of a userspace daemon. + * * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use */ @@ -1778,6 +1787,7 @@ enum nl80211_mesh_setup_params { NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC, NL80211_MESH_SETUP_IE, NL80211_MESH_SETUP_USERSPACE_AUTH, + NL80211_MESH_SETUP_USERSPACE_AMPE, /* keep last */ __NL80211_MESH_SETUP_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0920daf36807..10c17d68059f 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -695,7 +695,8 @@ struct mesh_config { * @path_metric: which metric to use * @ie: vendor information elements (optional) * @ie_len: length of vendor information elements - * @is_secure: or not + * @is_authenticated: this mesh requires authentication + * @is_secure: this mesh uses security * * These parameters are fixed when the mesh is created. */ @@ -706,6 +707,7 @@ struct mesh_setup { u8 path_metric; const u8 *ie; u8 ie_len; + bool is_authenticated; bool is_secure; }; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 1ebc13383ae7..18c2555e04e6 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1064,7 +1064,11 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); ifmsh->mesh_pp_id = setup->path_sel_proto; ifmsh->mesh_pm_id = setup->path_metric; - ifmsh->is_secure = setup->is_secure; + ifmsh->security = IEEE80211_MESH_SEC_NONE; + if (setup->is_authenticated) + ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; + if (setup->is_secure) + ifmsh->security |= IEEE80211_MESH_SEC_SECURED; return 0; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e89bc27f8dc3..7f4d0dc1d534 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -490,7 +490,11 @@ struct ieee80211_if_mesh { bool accepting_plinks; const u8 *ie; u8 ie_len; - bool is_secure; + enum { + IEEE80211_MESH_SEC_NONE = 0x0, + IEEE80211_MESH_SEC_AUTHED = 0x1, + IEEE80211_MESH_SEC_SECURED = 0x2, + } security; }; #ifdef CONFIG_MAC80211_MESH diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index c1299e249541..2a59eb345131 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -574,7 +574,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, &elems); /* ignore beacons from secure mesh peers if our security is off */ - if (elems.rsn_len && !sdata->u.mesh.is_secure) + if (elems.rsn_len && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) return; if (elems.ds_params && elems.ds_params_len == 1) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 84e5b056af02..87abf8deb369 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -251,7 +251,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, rcu_read_unlock(); /* Userspace handles peer allocation when security is enabled * */ - if (sdata->u.mesh.is_secure) + if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr, elems->ie_start, elems->total_len, GFP_KERNEL); @@ -460,7 +460,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m mpl_dbg("Mesh plink: missing necessary peer link ie\n"); return; } - if (elems.rsn_len && !sdata->u.mesh.is_secure) { + if (elems.rsn_len && + sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { mpl_dbg("Mesh plink: can't establish link with secure peer\n"); return; } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 0a199a1ca9b6..64efc2d7a7ad 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2871,6 +2871,7 @@ static const struct nla_policy [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, + [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG }, }; static int nl80211_parse_mesh_config(struct genl_info *info, @@ -2980,7 +2981,8 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, setup->ie = nla_data(ieattr); setup->ie_len = nla_len(ieattr); } - setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]); + setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]); + setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]); return 0; } -- cgit v1.2.3-58-ga151 From 0778a6a3e56cabdc322755f97ad23ee67efad0f0 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 3 May 2011 16:57:08 -0700 Subject: mac80211: Let userspace send action frames over mesh interfaces Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/wireless/mlme.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 16881fea4ce6..493b939970cd 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -963,6 +963,16 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, if (memcmp(mgmt->bssid, dev->dev_addr, ETH_ALEN)) err = -EINVAL; break; + case NL80211_IFTYPE_MESH_POINT: + if (memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN)) { + err = -EINVAL; + break; + } + /* + * check for mesh DA must be done by driver as + * cfg80211 doesn't track the stations + */ + break; default: err = -EOPNOTSUPP; break; -- cgit v1.2.3-58-ga151 From d3aaec8ab76c2d604c2ba7332e1338674607597b Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 3 May 2011 16:57:09 -0700 Subject: mac80211: Drop MESH_PLINK category and use new ANA-approved MESH_ACTION Note: This breaks compatibility with previous mesh protocol instances. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 5 ++--- net/mac80211/mesh.c | 2 +- net/mac80211/mesh_plink.c | 2 +- net/mac80211/rx.c | 7 +++++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 79690b710665..ee1c96a866cc 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1261,9 +1261,8 @@ enum ieee80211_category { WLAN_CATEGORY_MULTIHOP_ACTION = 14, WLAN_CATEGORY_SELF_PROTECTED = 15, WLAN_CATEGORY_WMM = 17, - /* TODO: remove MESH_PLINK and MESH_PATH_SEL after */ - /* mesh is updated to current 802.11s draft */ - WLAN_CATEGORY_MESH_PLINK = 30, + /* TODO: remove MESH_PATH_SEL after mesh is updated + * to current 802.11s draft */ WLAN_CATEGORY_MESH_PATH_SEL = 32, WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, WLAN_CATEGORY_VENDOR_SPECIFIC = 127, diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 2a59eb345131..75378e852f00 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -600,7 +600,7 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, struct ieee80211_rx_status *rx_status) { switch (mgmt->u.action.category) { - case WLAN_CATEGORY_MESH_PLINK: + case WLAN_CATEGORY_MESH_ACTION: mesh_rx_plink_frame(sdata, mgmt, len, rx_status); break; case WLAN_CATEGORY_MESH_PATH_SEL: diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 87abf8deb369..0120e9e36286 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -182,7 +182,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, memcpy(mgmt->da, da, ETH_ALEN); memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ - mgmt->u.action.category = WLAN_CATEGORY_MESH_PLINK; + mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; mgmt->u.action.u.plink_action.action_code = action; if (action == PLINK_CLOSE) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 81241e18f3a4..634f3d97a279 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -495,8 +495,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) return RX_DROP_MONITOR; if (ieee80211_is_action(hdr->frame_control)) { + u8 category; mgmt = (struct ieee80211_mgmt *)hdr; - if (mgmt->u.action.category != WLAN_CATEGORY_MESH_PLINK) + category = mgmt->u.action.category; + if (category != WLAN_CATEGORY_MESH_ACTION && + category != WLAN_CATEGORY_SELF_PROTECTED) return RX_DROP_MONITOR; return RX_CONTINUE; } @@ -2205,7 +2208,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) goto handled; } break; - case WLAN_CATEGORY_MESH_PLINK: + case WLAN_CATEGORY_MESH_ACTION: if (!ieee80211_vif_is_mesh(&sdata->vif)) break; goto queue; -- cgit v1.2.3-58-ga151 From 915b5c50f8f45e78ea96d93f1e49edb20c9470bd Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 3 May 2011 16:57:10 -0700 Subject: open80211s: Stop using zero for address 3 in mesh plink mgmt frames Previous versions of 11s draft used the all zeroes address. Current draft uses the same address as address 2. Also, use the ANA-approved action category code for peer establishment frames. Note: This breaks compatibility with previous mesh protocol instances. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/mac80211/mesh_plink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 0120e9e36286..2c37bee3095a 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -43,7 +43,7 @@ #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) enum plink_frame_type { - PLINK_OPEN = 0, + PLINK_OPEN = 1, PLINK_CONFIRM, PLINK_CLOSE }; @@ -181,7 +181,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, IEEE80211_STYPE_ACTION); memcpy(mgmt->da, da, ETH_ALEN); memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); - /* BSSID is left zeroed, wildcard value */ + memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; mgmt->u.action.u.plink_action.action_code = action; -- cgit v1.2.3-58-ga151 From 0a35d36d6f019bde6c98812456798275b02e5aee Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Wed, 4 May 2011 10:24:56 -0700 Subject: cfg80211: Use capability info to detect mesh beacons. Mesh beacons no longer use all-zeroes BSSID. Beacon frames for MBSS, infrastructure BSS, or IBSS are differentiated by the Capability Information field in the Beacon frame. A mesh STA sets the ESS and IBSS subfields to 0 in transmitted Beacon or Probe Response management frames. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 5 +++++ net/wireless/scan.c | 14 +++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index ee1c96a866cc..d527fb7bd67a 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1002,6 +1002,11 @@ struct ieee80211_ht_info { #define WLAN_CAPABILITY_ESS (1<<0) #define WLAN_CAPABILITY_IBSS (1<<1) + +/* A mesh STA sets the ESS and IBSS capability bits to zero */ +#define WLAN_CAPABILITY_IS_MBSS(cap) \ + (!((cap) & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS))) + #define WLAN_CAPABILITY_CF_POLLABLE (1<<2) #define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) #define WLAN_CAPABILITY_PRIVACY (1<<4) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index fbf6f33ae4d0..62e542a2b192 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -210,7 +210,7 @@ static bool is_mesh(struct cfg80211_bss *a, { const u8 *ie; - if (!is_zero_ether_addr(a->bssid)) + if (!WLAN_CAPABILITY_IS_MBSS(a->capability)) return false; ie = cfg80211_find_ie(WLAN_EID_MESH_ID, @@ -248,11 +248,7 @@ static int cmp_bss(struct cfg80211_bss *a, if (a->channel != b->channel) return b->channel->center_freq - a->channel->center_freq; - r = memcmp(a->bssid, b->bssid, ETH_ALEN); - if (r) - return r; - - if (is_zero_ether_addr(a->bssid)) { + if (WLAN_CAPABILITY_IS_MBSS(a->capability | b->capability)) { r = cmp_ies(WLAN_EID_MESH_ID, a->information_elements, a->len_information_elements, @@ -267,6 +263,10 @@ static int cmp_bss(struct cfg80211_bss *a, b->len_information_elements); } + r = memcmp(a->bssid, b->bssid, ETH_ALEN); + if (r) + return r; + return cmp_ies(WLAN_EID_SSID, a->information_elements, a->len_information_elements, @@ -407,7 +407,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, res->ts = jiffies; - if (is_zero_ether_addr(res->pub.bssid)) { + if (WLAN_CAPABILITY_IS_MBSS(res->pub.capability)) { /* must be mesh, verify */ meshid = cfg80211_find_ie(WLAN_EID_MESH_ID, res->pub.information_elements, -- cgit v1.2.3-58-ga151 From 9c3990aaec0ad9f686ef6480f6861f2df89b2a7a Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 3 May 2011 16:57:11 -0700 Subject: nl80211: Let userspace drive the peer link management states. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- include/linux/nl80211.h | 4 ++++ include/net/cfg80211.h | 29 +++++++++++++++++++++++++++++ net/mac80211/cfg.c | 30 +++++++++++++++++++++--------- net/mac80211/sta_info.h | 23 ----------------------- net/wireless/nl80211.c | 6 ++++++ 5 files changed, 60 insertions(+), 32 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index c53b916036c5..de96783954a1 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -913,6 +913,9 @@ enum nl80211_commands { * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver * allows auth frames in a mesh to be passed to userspace for processing via * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. + * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link. Used when + * userspace is driving the peer link management state machine. + * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled. * * @NL80211_ATTR_WOWLAN_SUPPORTED: indicates, as part of the wiphy capabilities, * the supported WoWLAN triggers @@ -1109,6 +1112,7 @@ enum nl80211_attrs { NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, NL80211_ATTR_SUPPORT_MESH_AUTH, + NL80211_ATTR_STA_PLINK_STATE, NL80211_ATTR_WOWLAN_TRIGGERS, NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 10c17d68059f..4b0d035be64f 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -371,6 +371,33 @@ enum plink_actions { PLINK_ACTION_BLOCK, }; +/** + * enum plink_states - state of a mesh peer link finite state machine + * + * @PLINK_LISTEN: initial state, considered the implicit state of non + * existant mesh peer links + * @PLINK_OPN_SNT: mesh plink open frame has been sent to this mesh + * peer @PLINK_OPN_RCVD: mesh plink open frame has been received from + * this mesh peer + * @PLINK_CNF_RCVD: mesh plink confirm frame has been received from + * this mesh peer + * @PLINK_ESTAB: mesh peer link is established + * @PLINK_HOLDING: mesh peer link is being closed or cancelled + * @PLINK_BLOCKED: all frames transmitted from this mesh plink are + * discarded + * @PLINK_INVALID: reserved + */ +enum plink_state { + PLINK_LISTEN, + PLINK_OPN_SNT, + PLINK_OPN_RCVD, + PLINK_CNF_RCVD, + PLINK_ESTAB, + PLINK_HOLDING, + PLINK_BLOCKED, + PLINK_INVALID, +}; + /** * struct station_parameters - station parameters * @@ -387,6 +414,7 @@ enum plink_actions { * @listen_interval: listen interval or -1 for no change * @aid: AID or zero for no change * @plink_action: plink action to take + * @plink_state: set the peer link state for a station * @ht_capa: HT capabilities of station */ struct station_parameters { @@ -397,6 +425,7 @@ struct station_parameters { u16 aid; u8 supported_rates_len; u8 plink_action; + u8 plink_state; struct ieee80211_ht_cap *ht_capa; }; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 18c2555e04e6..51f775772d9e 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -734,15 +734,27 @@ static void sta_apply_parameters(struct ieee80211_local *local, params->ht_capa, &sta->sta.ht_cap); - if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { - switch (params->plink_action) { - case PLINK_ACTION_OPEN: - mesh_plink_open(sta); - break; - case PLINK_ACTION_BLOCK: - mesh_plink_block(sta); - break; - } + if (ieee80211_vif_is_mesh(&sdata->vif)) { + if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) + switch (params->plink_state) { + case PLINK_LISTEN: + case PLINK_ESTAB: + case PLINK_BLOCKED: + sta->plink_state = params->plink_state; + break; + default: + /* nothing */ + break; + } + else + switch (params->plink_action) { + case PLINK_ACTION_OPEN: + mesh_plink_open(sta); + break; + case PLINK_ACTION_BLOCK: + mesh_plink_block(sta); + break; + } } } diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index af1a7f8c8675..f00b4dcb49d7 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -173,29 +173,6 @@ struct sta_ampdu_mlme { }; -/** - * enum plink_state - state of a mesh peer link finite state machine - * - * @PLINK_LISTEN: initial state, considered the implicit state of non existant - * mesh peer links - * @PLINK_OPN_SNT: mesh plink open frame has been sent to this mesh peer - * @PLINK_OPN_RCVD: mesh plink open frame has been received from this mesh peer - * @PLINK_CNF_RCVD: mesh plink confirm frame has been received from this mesh - * peer - * @PLINK_ESTAB: mesh peer link is established - * @PLINK_HOLDING: mesh peer link is being closed or cancelled - * @PLINK_BLOCKED: all frames transmitted from this mesh plink are discarded - */ -enum plink_state { - PLINK_LISTEN, - PLINK_OPN_SNT, - PLINK_OPN_RCVD, - PLINK_CNF_RCVD, - PLINK_ESTAB, - PLINK_HOLDING, - PLINK_BLOCKED -}; - /** * struct sta_info - STA information * diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 64efc2d7a7ad..f698c1d116e4 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -174,6 +174,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED }, + [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 }, }; /* policy for the key attributes */ @@ -2247,6 +2248,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) memset(¶ms, 0, sizeof(params)); params.listen_interval = -1; + params.plink_state = PLINK_INVALID; if (info->attrs[NL80211_ATTR_STA_AID]) return -EINVAL; @@ -2278,6 +2280,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) params.plink_action = nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); + if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) + params.plink_state = + nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); + err = get_vlan(info, rdev, ¶ms.vlan); if (err) goto out; -- cgit v1.2.3-58-ga151 From ff973af74aa6932ca4758266bccec68e8135ddf7 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Tue, 3 May 2011 16:57:12 -0700 Subject: nl80211: allow installing keys for a meshif Signed-off-by: Thomas Pedersen Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 5 ++++- net/wireless/nl80211.c | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 51f775772d9e..c416cce5e1ed 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -136,7 +136,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, mutex_lock(&sdata->local->sta_mtx); if (mac_addr) { - sta = sta_info_get_bss(sdata, mac_addr); + if (ieee80211_vif_is_mesh(&sdata->vif)) + sta = sta_info_get(sdata, mac_addr); + else + sta = sta_info_get_bss(sdata, mac_addr); if (!sta) { ieee80211_key_free(sdata->local, key); err = -ENOENT; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f698c1d116e4..b454f8960a04 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -545,6 +545,7 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_P2P_GO: + case NL80211_IFTYPE_MESH_POINT: break; case NL80211_IFTYPE_ADHOC: if (!wdev->current_bss) -- cgit v1.2.3-58-ga151 From 8429828ec96b66b6861e9fabebec007e9e132370 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Tue, 3 May 2011 16:57:13 -0700 Subject: nl80211: allow setting MFP flag for a meshif Signed-off-by: Thomas Pedersen Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b454f8960a04..fc3c95d92546 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2328,6 +2328,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) err = -EINVAL; if (params.sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | + BIT(NL80211_STA_FLAG_MFP) | BIT(NL80211_STA_FLAG_AUTHORIZED))) err = -EINVAL; break; -- cgit v1.2.3-58-ga151 From 8f9cb77d6d213c153b0571f494df0c24456aaf47 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Tue, 3 May 2011 16:57:14 -0700 Subject: mac80211: Self-protected management frames are not robust They may contain encrypted information elements (as AMPE frames do) but they are not encrypted. Signed-off-by: Thomas Pedersen Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index d527fb7bd67a..b2eee5879883 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1520,6 +1520,7 @@ static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) category = ((u8 *) hdr) + 24; return *category != WLAN_CATEGORY_PUBLIC && *category != WLAN_CATEGORY_HT && + *category != WLAN_CATEGORY_SELF_PROTECTED && *category != WLAN_CATEGORY_VENDOR_SPECIFIC; } -- cgit v1.2.3-58-ga151 From 9ca99eeca0cfe839c481f3350988e9ed94188567 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 3 May 2011 16:57:15 -0700 Subject: mac80211: Check size of a new mesh path table for changes since allocation. Not sure if I'm chasing a ghost here, seems like the mesh_path->size_order needs to be inside an RCU-read section to prevent that value from changing between table allocation and copying. We have observed crashes that might be caused by this. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/mac80211/mesh_pathtbl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 7776ae5a8f15..c1a2bf2aa2de 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -76,7 +76,6 @@ static int mesh_table_grow(struct mesh_table *oldtbl, < oldtbl->mean_chain_len * (oldtbl->hash_mask + 1)) return -EAGAIN; - newtbl->free_node = oldtbl->free_node; newtbl->mean_chain_len = oldtbl->mean_chain_len; newtbl->copy_node = oldtbl->copy_node; @@ -329,7 +328,8 @@ void mesh_mpath_table_grow(void) { struct mesh_table *oldtbl, *newtbl; - newtbl = mesh_table_alloc(mesh_paths->size_order + 1); + rcu_read_lock(); + newtbl = mesh_table_alloc(rcu_dereference(mesh_paths)->size_order + 1); if (!newtbl) return; write_lock(&pathtbl_resize_lock); @@ -339,6 +339,7 @@ void mesh_mpath_table_grow(void) write_unlock(&pathtbl_resize_lock); return; } + rcu_read_unlock(); rcu_assign_pointer(mesh_paths, newtbl); write_unlock(&pathtbl_resize_lock); @@ -350,7 +351,8 @@ void mesh_mpp_table_grow(void) { struct mesh_table *oldtbl, *newtbl; - newtbl = mesh_table_alloc(mpp_paths->size_order + 1); + rcu_read_lock(); + newtbl = mesh_table_alloc(rcu_dereference(mpp_paths)->size_order + 1); if (!newtbl) return; write_lock(&pathtbl_resize_lock); @@ -360,6 +362,7 @@ void mesh_mpp_table_grow(void) write_unlock(&pathtbl_resize_lock); return; } + rcu_read_unlock(); rcu_assign_pointer(mpp_paths, newtbl); write_unlock(&pathtbl_resize_lock); -- cgit v1.2.3-58-ga151 From 9b84b80891e5e25ae21c855bb135b05274125a29 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 3 May 2011 16:57:16 -0700 Subject: mac80211: Fix locking bug on mesh path table access The mesh and mpp path tables are accessed from softirq and workqueue context so non-irq locking cannot be used. Or at least that's what PROVE_RCU seems to tell us here: [ 431.240946] ================================= [ 431.241061] [ INFO: inconsistent lock state ] [ 431.241061] 2.6.39-rc3-wl+ #354 [ 431.241061] --------------------------------- [ 431.241061] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage. [ 431.241061] kworker/u:1/1423 [HC0[0]:SC0[0]:HE1:SE1] takes: [ 431.241061] (&(&newtbl->hashwlock[i])->rlock){+.?...}, at: [] mesh_path_add+0x167/0x257 Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/mac80211/mesh_pathtbl.c | 54 +++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index c1a2bf2aa2de..c7cb3cc083df 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -55,12 +55,12 @@ void mesh_table_free(struct mesh_table *tbl, bool free_leafs) mesh_hash = tbl->hash_buckets; for (i = 0; i <= tbl->hash_mask; i++) { - spin_lock(&tbl->hashwlock[i]); + spin_lock_bh(&tbl->hashwlock[i]); hlist_for_each_safe(p, q, &mesh_hash[i]) { tbl->free_node(p, free_leafs); atomic_dec(&tbl->entries); } - spin_unlock(&tbl->hashwlock[i]); + spin_unlock_bh(&tbl->hashwlock[i]); } __mesh_table_free(tbl); } @@ -274,7 +274,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) if (!new_node) goto err_node_alloc; - read_lock(&pathtbl_resize_lock); + read_lock_bh(&pathtbl_resize_lock); memcpy(new_mpath->dst, dst, ETH_ALEN); new_mpath->sdata = sdata; new_mpath->flags = 0; @@ -289,7 +289,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) hash_idx = mesh_table_hash(dst, sdata, mesh_paths); bucket = &mesh_paths->hash_buckets[hash_idx]; - spin_lock(&mesh_paths->hashwlock[hash_idx]); + spin_lock_bh(&mesh_paths->hashwlock[hash_idx]); err = -EEXIST; hlist_for_each_entry(node, n, bucket, list) { @@ -305,8 +305,8 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) mesh_paths_generation++; - spin_unlock(&mesh_paths->hashwlock[hash_idx]); - read_unlock(&pathtbl_resize_lock); + spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]); + read_unlock_bh(&pathtbl_resize_lock); if (grow) { set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); ieee80211_queue_work(&local->hw, &sdata->work); @@ -314,8 +314,8 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) return 0; err_exists: - spin_unlock(&mesh_paths->hashwlock[hash_idx]); - read_unlock(&pathtbl_resize_lock); + spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]); + read_unlock_bh(&pathtbl_resize_lock); kfree(new_node); err_node_alloc: kfree(new_mpath); @@ -332,16 +332,17 @@ void mesh_mpath_table_grow(void) newtbl = mesh_table_alloc(rcu_dereference(mesh_paths)->size_order + 1); if (!newtbl) return; - write_lock(&pathtbl_resize_lock); + write_lock_bh(&pathtbl_resize_lock); oldtbl = mesh_paths; if (mesh_table_grow(mesh_paths, newtbl) < 0) { + rcu_read_unlock(); __mesh_table_free(newtbl); - write_unlock(&pathtbl_resize_lock); + write_unlock_bh(&pathtbl_resize_lock); return; } rcu_read_unlock(); rcu_assign_pointer(mesh_paths, newtbl); - write_unlock(&pathtbl_resize_lock); + write_unlock_bh(&pathtbl_resize_lock); synchronize_rcu(); mesh_table_free(oldtbl, false); @@ -355,16 +356,17 @@ void mesh_mpp_table_grow(void) newtbl = mesh_table_alloc(rcu_dereference(mpp_paths)->size_order + 1); if (!newtbl) return; - write_lock(&pathtbl_resize_lock); + write_lock_bh(&pathtbl_resize_lock); oldtbl = mpp_paths; if (mesh_table_grow(mpp_paths, newtbl) < 0) { + rcu_read_unlock(); __mesh_table_free(newtbl); - write_unlock(&pathtbl_resize_lock); + write_unlock_bh(&pathtbl_resize_lock); return; } rcu_read_unlock(); rcu_assign_pointer(mpp_paths, newtbl); - write_unlock(&pathtbl_resize_lock); + write_unlock_bh(&pathtbl_resize_lock); synchronize_rcu(); mesh_table_free(oldtbl, false); @@ -398,7 +400,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) if (!new_node) goto err_node_alloc; - read_lock(&pathtbl_resize_lock); + read_lock_bh(&pathtbl_resize_lock); memcpy(new_mpath->dst, dst, ETH_ALEN); memcpy(new_mpath->mpp, mpp, ETH_ALEN); new_mpath->sdata = sdata; @@ -411,7 +413,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) hash_idx = mesh_table_hash(dst, sdata, mpp_paths); bucket = &mpp_paths->hash_buckets[hash_idx]; - spin_lock(&mpp_paths->hashwlock[hash_idx]); + spin_lock_bh(&mpp_paths->hashwlock[hash_idx]); err = -EEXIST; hlist_for_each_entry(node, n, bucket, list) { @@ -425,8 +427,8 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) mpp_paths->mean_chain_len * (mpp_paths->hash_mask + 1)) grow = 1; - spin_unlock(&mpp_paths->hashwlock[hash_idx]); - read_unlock(&pathtbl_resize_lock); + spin_unlock_bh(&mpp_paths->hashwlock[hash_idx]); + read_unlock_bh(&pathtbl_resize_lock); if (grow) { set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags); ieee80211_queue_work(&local->hw, &sdata->work); @@ -434,8 +436,8 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) return 0; err_exists: - spin_unlock(&mpp_paths->hashwlock[hash_idx]); - read_unlock(&pathtbl_resize_lock); + spin_unlock_bh(&mpp_paths->hashwlock[hash_idx]); + read_unlock_bh(&pathtbl_resize_lock); kfree(new_node); err_node_alloc: kfree(new_mpath); @@ -548,11 +550,11 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) int hash_idx; int err = 0; - read_lock(&pathtbl_resize_lock); + read_lock_bh(&pathtbl_resize_lock); hash_idx = mesh_table_hash(addr, sdata, mesh_paths); bucket = &mesh_paths->hash_buckets[hash_idx]; - spin_lock(&mesh_paths->hashwlock[hash_idx]); + spin_lock_bh(&mesh_paths->hashwlock[hash_idx]); hlist_for_each_entry(node, n, bucket, list) { mpath = node->mpath; if (mpath->sdata == sdata && @@ -570,8 +572,8 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) err = -ENXIO; enddel: mesh_paths_generation++; - spin_unlock(&mesh_paths->hashwlock[hash_idx]); - read_unlock(&pathtbl_resize_lock); + spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]); + read_unlock_bh(&pathtbl_resize_lock); return err; } @@ -723,7 +725,7 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) struct hlist_node *p; int i; - read_lock(&pathtbl_resize_lock); + read_lock_bh(&pathtbl_resize_lock); for_each_mesh_entry(mesh_paths, p, node, i) { if (node->mpath->sdata != sdata) continue; @@ -738,7 +740,7 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) } else spin_unlock_bh(&mpath->state_lock); } - read_unlock(&pathtbl_resize_lock); + read_unlock_bh(&pathtbl_resize_lock); } void mesh_pathtbl_unregister(void) -- cgit v1.2.3-58-ga151 From 28104cae63708d1790cd71db8a45af50d5ea5a92 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 3 May 2011 16:57:17 -0700 Subject: mac80211: Move call to mpp_path_lookup inside RCU-read section PROVE_RCU caught that one: [ 431.214070] =================================================== [ 431.215341] [ INFO: suspicious rcu_dereference_check() usage. ] [ 431.215674] --------------------------------------------------- [ 431.216043] net/mac80211/mesh_pathtbl.c:184 invoked rcu_dereference_check() without protection! Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/mac80211/tx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e1a39ed1ef5e..c9f12113ca6a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1751,6 +1751,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, ret = NETDEV_TX_OK; goto fail; } + rcu_read_lock(); if (!is_multicast_ether_addr(skb->data)) mppath = mpp_path_lookup(skb->data, sdata); @@ -1765,13 +1766,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, !(mppath && compare_ether_addr(mppath->mpp, skb->data))) { hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, skb->data, skb->data + ETH_ALEN); + rcu_read_unlock(); meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata, NULL, NULL); } else { int is_mesh_mcast = 1; const u8 *mesh_da; - rcu_read_lock(); if (is_multicast_ether_addr(skb->data)) /* DA TA mSA AE:SA */ mesh_da = skb->data; -- cgit v1.2.3-58-ga151 From 1833d81a1229adeab98f275b47624d66462561e5 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 3 May 2011 16:57:18 -0700 Subject: mac80211: allow setting supported rates on mesh peers This is necessary for userspace managed stations. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index fc3c95d92546..95dd5832e719 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2324,8 +2324,6 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) err = -EINVAL; if (params.listen_interval >= 0) err = -EINVAL; - if (params.supported_rates) - err = -EINVAL; if (params.sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | BIT(NL80211_STA_FLAG_MFP) | -- cgit v1.2.3-58-ga151 From fd5999cf11c8322568034bbf0d5594be94542a57 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 3 May 2011 16:57:19 -0700 Subject: ath9k: fix beaconing for mesh interfaces Mesh beaconing on ath9k was broken by this commit: commit 4801416c76a3a355076d6d371c00270dfe332e1c Author: Ben Greear Date: Sat Jan 15 19:13:48 2011 +0000 This patch assigns the right opmode when the device is used in mesh mode. Reported-by: Fabrice Deyber fabricedeyber@agilemesh.com Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c4d32c54224d..9dd72d8c78ec 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1385,7 +1385,9 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, ath9k_hw_set_tsfadjust(ah, 0); sc->sc_flags &= ~SC_OP_TSF_RESET; - if (iter_data.nwds + iter_data.nmeshes) + if (iter_data.nmeshes) + ah->opmode = NL80211_IFTYPE_MESH_POINT; + else if (iter_data.nwds) ah->opmode = NL80211_IFTYPE_AP; else if (iter_data.nadhocs) ah->opmode = NL80211_IFTYPE_ADHOC; -- cgit v1.2.3-58-ga151 From 9b76b1e4d383868ba9c2a5fa2c2716bbc2384342 Mon Sep 17 00:00:00 2001 From: Fabrice Deyber Date: Fri, 6 May 2011 15:11:51 -0700 Subject: mac80211: Only process mesh PREPs with equal seq number if metric is better. This fixes routing loops in PREP propagation and is in accordance with Draft 11, Section: 11C.9.8.4. Signed-off-by: Fabrice Deyber Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- net/mac80211/mesh_hwmp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index e57f2e728cfe..849fecd0820e 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -391,7 +391,6 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, (mpath->flags & MESH_PATH_SN_VALID)) { if (SN_GT(mpath->sn, orig_sn) || (mpath->sn == orig_sn && - action == MPATH_PREQ && new_metric >= mpath->metric)) { process = false; fresh_info = false; -- cgit v1.2.3-58-ga151 From d381f221199c58d2bf25a7024e786fc58562487c Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Fri, 6 May 2011 15:24:34 -0700 Subject: ath5k: Fix lockup due to un-init spinlock. This was introduced in 2.6.39-rc1 it seems. Signed-off-by: Ben Greear Tested-by: Sedat Dilek Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 7583841fc29a..aaa0cd72b0de 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2394,7 +2394,7 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops) spin_lock_init(&sc->rxbuflock); spin_lock_init(&sc->txbuflock); spin_lock_init(&sc->block); - + spin_lock_init(&sc->irqlock); /* Setup interrupt handler */ ret = request_irq(sc->irq, ath5k_intr, IRQF_SHARED, "ath", sc); -- cgit v1.2.3-58-ga151 From 92ddc111c4bc7216673bce7c49a2d54bedb1593c Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Mon, 9 May 2011 14:40:06 +0300 Subject: mac80211: add a couple of trace event classes to reduce duplicated code The functions drv_add_interface() and drv_remove_interface() print out the same values in the traces. Combine the traces of these two functions into one event class to remove some duplicate code. Also add a new class for functions drv_set_frag_threshold() and drv_set_rts_threshold(). Cc: Johannes Berg Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- net/mac80211/driver-trace.h | 130 ++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 77 deletions(-) diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 11e1ea5111ea..dd9779d41d2b 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -55,6 +55,49 @@ DECLARE_EVENT_CLASS(local_only_evt, TP_printk(LOCAL_PR_FMT, LOCAL_PR_ARG) ); +DECLARE_EVENT_CLASS(local_sdata_addr_evt, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + __array(char, addr, 6) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + memcpy(__entry->addr, sdata->vif.addr, 6); + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT " addr:%pM", + LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr + ) +); + +DECLARE_EVENT_CLASS(local_u32_evt, + TP_PROTO(struct ieee80211_local *local, u32 value), + TP_ARGS(local, value), + + TP_STRUCT__entry( + LOCAL_ENTRY + __field(u32, value) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + __entry->value = value; + ), + + TP_printk( + LOCAL_PR_FMT " value:%d", + LOCAL_PR_ARG, __entry->value + ) +); + DEFINE_EVENT(local_only_evt, drv_return_void, TP_PROTO(struct ieee80211_local *local), TP_ARGS(local) @@ -123,28 +166,10 @@ DEFINE_EVENT(local_only_evt, drv_stop, TP_ARGS(local) ); -TRACE_EVENT(drv_add_interface, +DEFINE_EVENT(local_sdata_addr_evt, drv_add_interface, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata), - - TP_ARGS(local, sdata), - - TP_STRUCT__entry( - LOCAL_ENTRY - VIF_ENTRY - __array(char, addr, 6) - ), - - TP_fast_assign( - LOCAL_ASSIGN; - VIF_ASSIGN; - memcpy(__entry->addr, sdata->vif.addr, 6); - ), - - TP_printk( - LOCAL_PR_FMT VIF_PR_FMT " addr:%pM", - LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr - ) + TP_ARGS(local, sdata) ); TRACE_EVENT(drv_change_interface, @@ -175,27 +200,10 @@ TRACE_EVENT(drv_change_interface, ) ); -TRACE_EVENT(drv_remove_interface, - TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata), - - TP_ARGS(local, sdata), - - TP_STRUCT__entry( - LOCAL_ENTRY - VIF_ENTRY - __array(char, addr, 6) - ), - - TP_fast_assign( - LOCAL_ASSIGN; - VIF_ASSIGN; - memcpy(__entry->addr, sdata->vif.addr, 6); - ), - - TP_printk( - LOCAL_PR_FMT VIF_PR_FMT " addr:%pM", - LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr - ) +DEFINE_EVENT(local_sdata_addr_evt, drv_remove_interface, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata) ); TRACE_EVENT(drv_config, @@ -514,46 +522,14 @@ TRACE_EVENT(drv_get_tkip_seq, ) ); -TRACE_EVENT(drv_set_frag_threshold, +DEFINE_EVENT(local_u32_evt, drv_set_frag_threshold, TP_PROTO(struct ieee80211_local *local, u32 value), - - TP_ARGS(local, value), - - TP_STRUCT__entry( - LOCAL_ENTRY - __field(u32, value) - ), - - TP_fast_assign( - LOCAL_ASSIGN; - __entry->value = value; - ), - - TP_printk( - LOCAL_PR_FMT " value:%d", - LOCAL_PR_ARG, __entry->value - ) + TP_ARGS(local, value) ); -TRACE_EVENT(drv_set_rts_threshold, +DEFINE_EVENT(local_u32_evt, drv_set_rts_threshold, TP_PROTO(struct ieee80211_local *local, u32 value), - - TP_ARGS(local, value), - - TP_STRUCT__entry( - LOCAL_ENTRY - __field(u32, value) - ), - - TP_fast_assign( - LOCAL_ASSIGN; - __entry->value = value; - ), - - TP_printk( - LOCAL_PR_FMT " value:%d", - LOCAL_PR_ARG, __entry->value - ) + TP_ARGS(local, value) ); TRACE_EVENT(drv_set_coverage_class, -- cgit v1.2.3-58-ga151 From a7ffab33203ae0c755b33a80756fe734f732dbb0 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 10 May 2011 15:53:16 +0200 Subject: b43legacy: trivial: use TMSLOW def instead of magic value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index f6d54463b24f..1ab8861dd43a 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2234,7 +2234,7 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev) b43legacy_write32(dev, B43legacy_MMIO_DMA5_IRQ_MASK, 0x0000DC00); value32 = ssb_read32(dev->dev, SSB_TMSLOW); - value32 |= 0x00100000; + value32 |= B43legacy_TMSLOW_MACPHYCLKEN; ssb_write32(dev->dev, SSB_TMSLOW, value32); b43legacy_write16(dev, B43legacy_MMIO_POWERUP_DELAY, -- cgit v1.2.3-58-ga151 From 858a16529cb4c6434d863740283e0dfeb93cd599 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 10 May 2011 16:05:33 +0200 Subject: b43: move MAC PHY clock controling function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is not N-PHY specific function, we partially duplicate code. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 17 +++++++++++++---- drivers/net/wireless/b43/main.h | 1 + drivers/net/wireless/b43/phy_n.c | 13 +------------ 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index f7582c096f8d..1e6a2add2aaf 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2685,6 +2685,17 @@ out: dev->mac_suspended++; } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */ +void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on) +{ + u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW); + if (on) + tmslow |= B43_TMSLOW_MACPHYCLKEN; + else + tmslow &= ~B43_TMSLOW_MACPHYCLKEN; + ssb_write32(dev->dev, SSB_TMSLOW, tmslow); +} + static void b43_adjust_opmode(struct b43_wldev *dev) { struct b43_wl *wl = dev->wl; @@ -2841,7 +2852,7 @@ static int b43_chip_init(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; int err; - u32 value32, macctl; + u32 macctl; u16 value16; /* Initialize the MAC control */ @@ -2919,9 +2930,7 @@ static int b43_chip_init(struct b43_wldev *dev) b43_write32(dev, B43_MMIO_DMA4_IRQ_MASK, 0x0000DC00); b43_write32(dev, B43_MMIO_DMA5_IRQ_MASK, 0x0000DC00); - value32 = ssb_read32(dev->dev, SSB_TMSLOW); - value32 |= 0x00100000; - ssb_write32(dev->dev, SSB_TMSLOW, value32); + b43_mac_phy_clock_set(dev, true); b43_write16(dev, B43_MMIO_POWERUP_DELAY, dev->dev->bus->chipco.fast_pwrup_delay); diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 40db03678d9f..a0d327f13183 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -133,6 +133,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags); void b43_mac_suspend(struct b43_wldev *dev); void b43_mac_enable(struct b43_wldev *dev); +void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on); struct b43_request_fw_context; diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 6755063f955a..b075a3f82a43 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -3540,17 +3540,6 @@ static int b43_nphy_cal_rx_iq(struct b43_wldev *dev, return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug); } -/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */ -static void b43_nphy_mac_phy_clock_set(struct b43_wldev *dev, bool on) -{ - u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW); - if (on) - tmslow |= B43_TMSLOW_MACPHYCLKEN; - else - tmslow &= ~B43_TMSLOW_MACPHYCLKEN; - ssb_write32(dev->dev, SSB_TMSLOW, tmslow); -} - /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) { @@ -3691,7 +3680,7 @@ int b43_phy_initn(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); b43_nphy_bmac_clock_fgc(dev, 0); - b43_nphy_mac_phy_clock_set(dev, true); + b43_mac_phy_clock_set(dev, true); b43_nphy_pa_override(dev, false); b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); -- cgit v1.2.3-58-ga151 From f59a59fea3be78c2bda23cb7f55225b33c502c3c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 10 May 2011 20:52:22 +0200 Subject: ath9k: fix a regression in PS frame filter handling Only leave filtering enabled for AP or VLAN interfaces, clear the destination mask for all other interfaces. Signed-off-by: Felix Fietkau Reported-by: Ben Greear Tested-by: Ben Greear Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 5 +++++ drivers/net/wireless/ath/ath9k/xmit.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 9dd72d8c78ec..33816091b439 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1782,6 +1782,11 @@ static int ath9k_sta_add(struct ieee80211_hw *hw, struct ieee80211_key_conf ps_key = { }; ath_node_attach(sc, sta); + + if (vif->type != NL80211_IFTYPE_AP && + vif->type != NL80211_IFTYPE_AP_VLAN) + return 0; + an->ps_key = ath_key_config(common, vif, sta, &ps_key); return 0; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 947d5b3b6e05..41469d7a2cda 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1845,6 +1845,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_sta *sta = info->control.sta; + struct ieee80211_vif *vif = info->control.vif; struct ath_softc *sc = hw->priv; struct ath_txq *txq = txctl->txq; struct ath_buf *bf; @@ -1882,6 +1883,11 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, memmove(skb->data, skb->data + padsize, padpos); } + if ((vif && vif->type != NL80211_IFTYPE_AP && + vif->type != NL80211_IFTYPE_AP_VLAN) || + !ieee80211_is_data(hdr->frame_control)) + info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; + setup_frame_info(hw, skb, frmlen); /* -- cgit v1.2.3-58-ga151 From 1073e4ee595265086a592a056d903bf4fcc8885a Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 11 May 2011 02:08:09 +0200 Subject: bcma: add missing GPIO defines, use PULL register only when available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar patch was commited to ssb. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/bcma/driver_chipcommon.c | 6 ++++-- include/linux/bcma/bcma_driver_chipcommon.h | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index caf596091d4d..606102256b44 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c @@ -29,8 +29,10 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) if (cc->core->id.rev >= 35) cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT); - bcma_cc_write32(cc, 0x58, 0); - bcma_cc_write32(cc, 0x5C, 0); + if (cc->core->id.rev >= 20) { + bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0); + bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0); + } if (cc->capabilities & BCMA_CC_CAP_PMU) bcma_pmu_init(cc); diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 4f8fd6a4c1e6..083c3b6cd5ce 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -113,6 +113,8 @@ #define BCMA_CC_FLASHDATA 0x0048 #define BCMA_CC_BCAST_ADDR 0x0050 #define BCMA_CC_BCAST_DATA 0x0054 +#define BCMA_CC_GPIOPULLUP 0x0058 /* Rev >= 20 only */ +#define BCMA_CC_GPIOPULLDOWN 0x005C /* Rev >= 20 only */ #define BCMA_CC_GPIOIN 0x0060 #define BCMA_CC_GPIOOUT 0x0064 #define BCMA_CC_GPIOOUTEN 0x0068 @@ -121,6 +123,9 @@ #define BCMA_CC_GPIOIRQ 0x0074 #define BCMA_CC_WATCHDOG 0x0080 #define BCMA_CC_GPIOTIMER 0x0088 /* LED powersave (corerev >= 16) */ +#define BCMA_CC_GPIOTIMER_OFFTIME 0x0000FFFF +#define BCMA_CC_GPIOTIMER_OFFTIME_SHIFT 0 +#define BCMA_CC_GPIOTIMER_ONTIME 0xFFFF0000 #define BCMA_CC_GPIOTIMER_ONTIME_SHIFT 16 #define BCMA_CC_GPIOTOUTM 0x008C /* LED powersave (corerev >= 16) */ #define BCMA_CC_CLOCK_N 0x0090 -- cgit v1.2.3-58-ga151 From 8576f815d5c8beb8b10f96abe31831b90af3d352 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 11 May 2011 02:10:58 +0200 Subject: ssb: move ssb_commit_settings and export it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commiting settings is possible on devices without PCI core (but with CC core). Export it for usage in drivers supporting other cores. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_pcicore.c | 26 -------------------------- drivers/ssb/main.c | 25 +++++++++++++++++++++++++ include/linux/ssb/ssb.h | 1 + 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 8fde1220bc89..82feb348c8bb 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -21,8 +21,6 @@ static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address); static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, u8 address, u16 data); -static void ssb_commit_settings(struct ssb_bus *bus); - static inline u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset) { @@ -659,30 +657,6 @@ static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, pcicore_write32(pc, mdio_control, 0); } -static void ssb_broadcast_value(struct ssb_device *dev, - u32 address, u32 data) -{ - /* This is used for both, PCI and ChipCommon core, so be careful. */ - BUILD_BUG_ON(SSB_PCICORE_BCAST_ADDR != SSB_CHIPCO_BCAST_ADDR); - BUILD_BUG_ON(SSB_PCICORE_BCAST_DATA != SSB_CHIPCO_BCAST_DATA); - - ssb_write32(dev, SSB_PCICORE_BCAST_ADDR, address); - ssb_read32(dev, SSB_PCICORE_BCAST_ADDR); /* flush */ - ssb_write32(dev, SSB_PCICORE_BCAST_DATA, data); - ssb_read32(dev, SSB_PCICORE_BCAST_DATA); /* flush */ -} - -static void ssb_commit_settings(struct ssb_bus *bus) -{ - struct ssb_device *dev; - - dev = bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev; - if (WARN_ON(!dev)) - return; - /* This forces an update of the cached registers. */ - ssb_broadcast_value(dev, 0xFD8, 0); -} - int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, struct ssb_device *dev) { diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index ad3da93a428c..ee2937c41424 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -1329,6 +1329,31 @@ error: } EXPORT_SYMBOL(ssb_bus_powerup); +static void ssb_broadcast_value(struct ssb_device *dev, + u32 address, u32 data) +{ + /* This is used for both, PCI and ChipCommon core, so be careful. */ + BUILD_BUG_ON(SSB_PCICORE_BCAST_ADDR != SSB_CHIPCO_BCAST_ADDR); + BUILD_BUG_ON(SSB_PCICORE_BCAST_DATA != SSB_CHIPCO_BCAST_DATA); + + ssb_write32(dev, SSB_PCICORE_BCAST_ADDR, address); + ssb_read32(dev, SSB_PCICORE_BCAST_ADDR); /* flush */ + ssb_write32(dev, SSB_PCICORE_BCAST_DATA, data); + ssb_read32(dev, SSB_PCICORE_BCAST_DATA); /* flush */ +} + +void ssb_commit_settings(struct ssb_bus *bus) +{ + struct ssb_device *dev; + + dev = bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev; + if (WARN_ON(!dev)) + return; + /* This forces an update of the cached registers. */ + ssb_broadcast_value(dev, 0xFD8, 0); +} +EXPORT_SYMBOL(ssb_commit_settings); + u32 ssb_admatch_base(u32 adm) { u32 base = 0; diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 7e99b348834c..f017b8900f78 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -518,6 +518,7 @@ extern int ssb_bus_may_powerdown(struct ssb_bus *bus); * Otherwise static always-on powercontrol will be used. */ extern int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl); +extern void ssb_commit_settings(struct ssb_bus *bus); /* Various helper functions */ extern u32 ssb_admatch_base(u32 adm); -- cgit v1.2.3-58-ga151 From 0fd82eafe3aa70937905b7e19e256409ae48477e Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 11 May 2011 02:10:59 +0200 Subject: b43: implement timeouts workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documented in: <4DCA7E40.9070709@lwfinger.net> Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 1e6a2add2aaf..a96e05a8ef7e 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4221,7 +4221,18 @@ static void b43_bluetooth_coext_disable(struct b43_wldev *dev) static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev) { - /* TODO: implement 80211 core workaround here */ + struct ssb_bus *bus = dev->dev->bus; + u32 tmp; + + if ((bus->chip_id == 0x4311 && bus->chip_rev == 2) || + (bus->chip_id == 0x4312)) { + tmp = ssb_read32(dev->dev, SSB_IMCFGLO); + tmp &= ~SSB_IMCFGLO_REQTO; + tmp &= ~SSB_IMCFGLO_SERTO; + tmp |= 0x3; + ssb_write32(dev->dev, SSB_IMCFGLO, tmp); + ssb_commit_settings(bus); + } } static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle) -- cgit v1.2.3-58-ga151 From c4859fbcfc12d5cfe8c30a33ad37d192a3093a7b Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Tue, 10 May 2011 20:47:35 -0700 Subject: mwifiex: remove redundant local structures Avoid use of local structure in the function if the structure is already allocated by the caller and the structure pointer is passed. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sta_ioctl.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 75bca56449cb..d05907d05039 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -1250,11 +1250,9 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, int mwifiex_get_signal_info(struct mwifiex_private *priv, struct mwifiex_ds_get_signal *signal) { - struct mwifiex_ds_get_signal info; int status; - memset(&info, 0, sizeof(struct mwifiex_ds_get_signal)); - info.selector = ALL_RSSI_INFO_MASK; + signal->selector = ALL_RSSI_INFO_MASK; /* Signal info can be obtained only if connected */ if (!priv->media_connected) { @@ -1267,13 +1265,10 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv, HostCmd_ACT_GEN_GET, 0, signal); if (!status) { - if (signal) - memcpy(signal, &info, - sizeof(struct mwifiex_ds_get_signal)); - if (info.selector & BCN_RSSI_AVG_MASK) - priv->w_stats.qual.level = info.bcn_rssi_avg; - if (info.selector & BCN_NF_AVG_MASK) - priv->w_stats.qual.noise = info.bcn_nf_avg; + if (signal->selector & BCN_RSSI_AVG_MASK) + priv->w_stats.qual.level = signal->bcn_rssi_avg; + if (signal->selector & BCN_NF_AVG_MASK) + priv->w_stats.qual.noise = signal->bcn_nf_avg; } return status; @@ -1333,19 +1328,14 @@ mwifiex_get_stats_info(struct mwifiex_private *priv, struct mwifiex_ds_get_stats *log) { int ret; - struct mwifiex_ds_get_stats get_log; - memset(&get_log, 0, sizeof(struct mwifiex_ds_get_stats)); ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG, - HostCmd_ACT_GEN_GET, 0, &get_log); + HostCmd_ACT_GEN_GET, 0, log); if (!ret) { - if (log) - memcpy(log, &get_log, sizeof(struct - mwifiex_ds_get_stats)); - priv->w_stats.discard.fragment = get_log.fcs_error; - priv->w_stats.discard.retries = get_log.retry; - priv->w_stats.discard.misc = get_log.ack_failure; + priv->w_stats.discard.fragment = log->fcs_error; + priv->w_stats.discard.retries = log->retry; + priv->w_stats.discard.misc = log->ack_failure; } return ret; -- cgit v1.2.3-58-ga151 From a8c485652ad4217800015aab25f1b70b96adb1a9 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Tue, 10 May 2011 20:47:36 -0700 Subject: mwifiex: cleanup ioctl.h Some structures and macros in ioctl.h are redundant or no longer used. Signed-off-by: Bing Zhao Signed-off-by: Yogesh Ashok Powar Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 9 +--- drivers/net/wireless/mwifiex/fw.h | 16 +------ drivers/net/wireless/mwifiex/ioctl.h | 81 +-------------------------------- 3 files changed, 4 insertions(+), 102 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 19be8870c683..660831ce293c 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -761,7 +761,6 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, struct mwifiex_802_11_ssid *ssid) { - struct mwifiex_scan_resp scan_resp; struct mwifiex_bssdescriptor *scan_table; int i, j; struct ieee80211_channel *chan; @@ -771,10 +770,6 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, int beacon_size; u8 element_id, element_len; - memset(&scan_resp, 0, sizeof(scan_resp)); - scan_resp.scan_table = (u8 *) priv->adapter->scan_table; - scan_resp.num_in_scan_table = priv->adapter->num_in_scan_table; - #define MAX_IE_BUF 2048 ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL); if (!ie_buf) { @@ -783,8 +778,8 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, return -ENOMEM; } - scan_table = (struct mwifiex_bssdescriptor *) scan_resp.scan_table; - for (i = 0; i < scan_resp.num_in_scan_table; i++) { + scan_table = priv->adapter->scan_table; + for (i = 0; i < priv->adapter->num_in_scan_table; i++) { if (ssid) { /* Inform specific BSS only */ if (memcmp(ssid->ssid, scan_table[i].ssid.ssid, diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index c6b26819cd38..afdd145dff0b 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -816,14 +816,7 @@ struct host_cmd_ds_txpwr_cfg { struct mwifiex_scan_cmd_config { /* - * BSS Type to be sent in the firmware command - * - * Field can be used to restrict the types of networks returned in the - * scan. Valid settings are: - * - * - MWIFIEX_SCAN_MODE_BSS (infrastructure) - * - MWIFIEX_SCAN_MODE_IBSS (adhoc) - * - MWIFIEX_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure) + * BSS mode to be sent in the firmware command */ u8 bss_mode; @@ -866,13 +859,6 @@ struct mwifiex_user_scan_cfg { u8 keep_previous_scan; /* * BSS mode to be sent in the firmware command - * - * Field can be used to restrict the types of networks returned in the - * scan. Valid settings are: - * - * - MWIFIEX_SCAN_MODE_BSS (infrastructure) - * - MWIFIEX_SCAN_MODE_IBSS (adhoc) - * - MWIFIEX_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure) */ u8 bss_mode; /* Configure the number of probe requests for active chan scans */ diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 5488e111fd2c..7c1c5ee40eb9 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -22,50 +22,17 @@ #include -enum { - MWIFIEX_SCAN_MODE_UNCHANGED = 0, - MWIFIEX_SCAN_MODE_BSS, - MWIFIEX_SCAN_MODE_IBSS, - MWIFIEX_SCAN_MODE_ANY -}; - enum { MWIFIEX_SCAN_TYPE_UNCHANGED = 0, MWIFIEX_SCAN_TYPE_ACTIVE, MWIFIEX_SCAN_TYPE_PASSIVE }; -struct mwifiex_get_scan_table_fixed { - u8 bssid[ETH_ALEN]; - u8 channel; - u8 rssi; - long long network_tsf; -}; - -struct mwifiex_scan_time_params { - u32 specific_scan_time; - u32 active_scan_time; - u32 passive_scan_time; -}; - struct mwifiex_user_scan { u32 scan_cfg_len; u8 scan_cfg_buf[1]; }; -struct mwifiex_scan_req { - u32 scan_mode; - u32 scan_type; - struct mwifiex_802_11_ssid scan_ssid; - struct mwifiex_scan_time_params scan_time; - struct mwifiex_user_scan user_scan; -}; - -struct mwifiex_scan_resp { - u32 num_in_scan_table; - u8 *scan_table; -}; - #define MWIFIEX_PROMISC_MODE 1 #define MWIFIEX_MULTICAST_MODE 2 #define MWIFIEX_ALL_MULTI_MODE 4 @@ -77,18 +44,11 @@ struct mwifiex_multicast_list { u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; }; -#define MWIFIEX_MAX_CHANNEL_NUM 128 - struct mwifiex_chan_freq { u32 channel; u32 freq; }; -struct mwifiex_chan_list { - u32 num_of_chan; - struct mwifiex_chan_freq cf[MWIFIEX_MAX_CHANNEL_NUM]; -}; - struct mwifiex_ssid_bssid { struct mwifiex_802_11_ssid ssid; u8 bssid[ETH_ALEN]; @@ -136,18 +96,8 @@ struct mwifiex_ds_get_stats { u32 wep_icv_error[4]; }; -#define BCN_RSSI_LAST_MASK 0x00000001 #define BCN_RSSI_AVG_MASK 0x00000002 -#define DATA_RSSI_LAST_MASK 0x00000004 -#define DATA_RSSI_AVG_MASK 0x00000008 -#define BCN_SNR_LAST_MASK 0x00000010 -#define BCN_SNR_AVG_MASK 0x00000020 -#define DATA_SNR_LAST_MASK 0x00000040 -#define DATA_SNR_AVG_MASK 0x00000080 -#define BCN_NF_LAST_MASK 0x00000100 #define BCN_NF_AVG_MASK 0x00000200 -#define DATA_NF_LAST_MASK 0x00000400 -#define DATA_NF_AVG_MASK 0x00000800 #define ALL_RSSI_INFO_MASK 0x00000fff struct mwifiex_ds_get_signal { @@ -174,11 +124,6 @@ struct mwifiex_ds_get_signal { s16 data_nf_avg; }; -struct mwifiex_fw_info { - u32 fw_ver; - u8 mac_addr[ETH_ALEN]; -}; - #define MWIFIEX_MAX_VER_STR_LEN 128 struct mwifiex_ver_ext { @@ -286,11 +231,6 @@ struct mwifiex_rate_cfg { u32 rate; }; -struct mwifiex_data_rate { - u32 tx_data_rate; - u32 rx_data_rate; -}; - struct mwifiex_power_cfg { u32 is_power_auto; u32 power_level; @@ -309,21 +249,14 @@ struct mwifiex_ds_hs_cfg { }; #define DEEP_SLEEP_ON 1 -#define DEEP_SLEEP_OFF 0 - #define DEEP_SLEEP_IDLE_TIME 100 +#define PS_MODE_AUTO 1 struct mwifiex_ds_auto_ds { u16 auto_ds; u16 idle_time; }; -#define PS_MODE_UNCHANGED 0 -#define PS_MODE_AUTO 1 -#define PS_MODE_POLL 2 -#define PS_MODE_NULL 3 - - struct mwifiex_ds_pm_cfg { union { u32 ps_mode; @@ -333,18 +266,6 @@ struct mwifiex_ds_pm_cfg { } param; }; -struct mwifiex_ioctl_wmm_queue_status_ac { - u8 wmm_acm; - u8 flow_required; - u8 flow_created; - u8 disabled; -}; - -struct mwifiex_ds_wmm_queue_status { - struct mwifiex_ioctl_wmm_queue_status_ac - ac_status[IEEE80211_MAX_QUEUES]; -}; - struct mwifiex_ds_11n_tx_cfg { u16 tx_htcap; u16 tx_htinfo; -- cgit v1.2.3-58-ga151 From 6bdbdbf4a151a3a1333818cd17a7d7795e936041 Mon Sep 17 00:00:00 2001 From: Sascha Silbe Date: Wed, 11 May 2011 14:52:34 +0200 Subject: libertas: Add libertas_disablemesh module parameter to disable mesh interface This allows individual users and deployments to disable mesh support at runtime, i.e. without having to build and maintain a custom kernel. Based on a patch by Paul Fox . Signed-off-by: Sascha Silbe Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 84d05a765b5b..8c40949cb076 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -36,6 +36,10 @@ unsigned int lbs_debug; EXPORT_SYMBOL_GPL(lbs_debug); module_param_named(libertas_debug, lbs_debug, int, 0644); +unsigned int lbs_disablemesh; +EXPORT_SYMBOL_GPL(lbs_disablemesh); +module_param_named(libertas_disablemesh, lbs_disablemesh, int, 0644); + /* * This global structure is used to send the confirm_sleep command as @@ -944,7 +948,10 @@ int lbs_start_card(struct lbs_private *priv) lbs_update_channel(priv); - lbs_init_mesh(priv); + if (!lbs_disablemesh) + lbs_init_mesh(priv); + else + pr_info("%s: mesh disabled\n", dev->name); lbs_debugfs_init_one(priv, dev); -- cgit v1.2.3-58-ga151 From 807f8a8c300435d5483e8d78df9dcdbc27333166 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Wed, 11 May 2011 17:09:35 +0300 Subject: cfg80211/nl80211: add support for scheduled scans Implement new functionality for scheduled scan offload. With this feature we can scan automatically at certain intervals. The idea is that the hardware can perform scan automatically and filter on desired results without waking up the host unnecessarily. Add NL80211_CMD_START_SCHED_SCAN and NL80211_CMD_STOP_SCHED_SCAN commands to the nl80211 interface. When results are available they are reported by NL80211_CMD_SCHED_SCAN_RESULTS events. The userspace is informed when the scheduled scan has stopped with a NL80211_CMD_SCHED_SCAN_STOPPED event, which can be triggered either by the driver or by a call to NL80211_CMD_STOP_SCHED_SCAN. Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- include/linux/nl80211.h | 25 +++++ include/net/cfg80211.h | 57 +++++++++++ net/wireless/core.c | 12 ++- net/wireless/core.h | 7 ++ net/wireless/nl80211.c | 250 ++++++++++++++++++++++++++++++++++++++++++++++++ net/wireless/nl80211.h | 4 + net/wireless/scan.c | 70 ++++++++++++++ 7 files changed, 424 insertions(+), 1 deletion(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index de96783954a1..f8b5595ba4af 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -203,6 +203,26 @@ * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, * partial scan results may be available * + * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan. Like with normal + * scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS) are passed, they are used + * in the probe requests. For broadcast, a broadcast SSID must be + * passed (ie. an empty string). If no SSID is passed, no probe + * requests are sent and a passive scan is performed. + * %NL80211_ATTR_SCAN_FREQUENCIES, if passed, define which channels + * should be scanned; if not passed, all channels allowed for the + * current regulatory domain are used. Extra IEs can also be passed + * from the userspace by using the %NL80211_ATTR_IE attribute. + * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan + * @NL80211_CMD_SCHED_SCAN_RESULTS: indicates that there are scheduled scan + * results available. + * @NL80211_CMD_SCHED_SCAN_STOPPED: indicates that the scheduled scan has + * stopped. The driver may issue this event at any time during a + * scheduled scan. One reason for stopping the scan is if the hardware + * does not support starting an association or a normal scan while running + * a scheduled scan. This event is also sent when the + * %NL80211_CMD_STOP_SCHED_SCAN command is received or when the interface + * is brought down while a scheduled scan was running. + * * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation * or noise level * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to @@ -545,6 +565,11 @@ enum nl80211_commands { NL80211_CMD_GET_WOWLAN, NL80211_CMD_SET_WOWLAN, + NL80211_CMD_START_SCHED_SCAN, + NL80211_CMD_STOP_SCHED_SCAN, + NL80211_CMD_SCHED_SCAN_RESULTS, + NL80211_CMD_SCHED_SCAN_STOPPED, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 4b0d035be64f..e214c85b74d2 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -823,6 +823,33 @@ struct cfg80211_scan_request { struct ieee80211_channel *channels[0]; }; +/** + * struct cfg80211_sched_scan_request - scheduled scan request description + * + * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans) + * @n_ssids: number of SSIDs + * @n_channels: total number of channels to scan + * @ie: optional information element(s) to add into Probe Request or %NULL + * @ie_len: length of ie in octets + * @wiphy: the wiphy this was for + * @dev: the interface + * @channels: channels to scan + */ +struct cfg80211_sched_scan_request { + struct cfg80211_ssid *ssids; + int n_ssids; + u32 n_channels; + const u8 *ie; + size_t ie_len; + + /* internal */ + struct wiphy *wiphy; + struct net_device *dev; + + /* keep last */ + struct ieee80211_channel *channels[0]; +}; + /** * enum cfg80211_signal_type - signal type * @@ -1292,6 +1319,10 @@ struct cfg80211_wowlan { * @set_power_mgmt: Configure WLAN power management. A timeout value of -1 * allows the driver to adjust the dynamic ps timeout value. * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold. + * @sched_scan_start: Tell the driver to start a scheduled scan. + * @sched_scan_stop: Tell the driver to stop an ongoing scheduled + * scan. The driver_initiated flag specifies whether the driver + * itself has informed that the scan has stopped. * * @mgmt_frame_register: Notify driver that a management frame type was * registered. Note that this callback may not sleep, and cannot run @@ -1478,6 +1509,12 @@ struct cfg80211_ops { int (*set_ringparam)(struct wiphy *wiphy, u32 tx, u32 rx); void (*get_ringparam)(struct wiphy *wiphy, u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); + + int (*sched_scan_start)(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request *request); + int (*sched_scan_stop)(struct wiphy *wiphy, struct net_device *dev, + bool driver_initiated); }; /* @@ -1522,6 +1559,7 @@ struct cfg80211_ops { * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN. * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing * auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH. + * @WIPHY_FLAG_SCHED_SCAN: The device supports scheduled scans. */ enum wiphy_flags { WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), @@ -1534,6 +1572,7 @@ enum wiphy_flags { WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), WIPHY_FLAG_IBSS_RSN = BIT(8), WIPHY_FLAG_MESH_AUTH = BIT(10), + WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11), }; struct mac_address { @@ -2354,6 +2393,24 @@ int cfg80211_wext_siwpmksa(struct net_device *dev, */ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted); +/** + * cfg80211_sched_scan_results - notify that new scan results are available + * + * @wiphy: the wiphy which got scheduled scan results + */ +void cfg80211_sched_scan_results(struct wiphy *wiphy); + +/** + * cfg80211_sched_scan_stopped - notify that the scheduled scan has stopped + * + * @wiphy: the wiphy on which the scheduled scan stopped + * + * The driver can call this function to inform cfg80211 that the + * scheduled scan had to be stopped, for whatever reason. The driver + * is then called back via the sched_scan_stop operation when done. + */ +void cfg80211_sched_scan_stopped(struct wiphy *wiphy); + /** * cfg80211_inform_bss_frame - inform cfg80211 of a received BSS frame * diff --git a/net/wireless/core.c b/net/wireless/core.c index bea0d80710c8..f924a49b2425 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -370,7 +370,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) spin_lock_init(&rdev->bss_lock); INIT_LIST_HEAD(&rdev->bss_list); INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); - + INIT_WORK(&rdev->sched_scan_results_wk, __cfg80211_sched_scan_results); + INIT_WORK(&rdev->sched_scan_stopped_wk, __cfg80211_sched_scan_stopped); #ifdef CONFIG_CFG80211_WEXT rdev->wiphy.wext = &cfg80211_wext_handler; #endif @@ -672,6 +673,11 @@ static void wdev_cleanup_work(struct work_struct *work) ___cfg80211_scan_done(rdev, true); } + if (WARN_ON(rdev->sched_scan_req && + rdev->sched_scan_req->dev == wdev->netdev)) { + __cfg80211_stop_sched_scan(rdev, false); + } + cfg80211_unlock_rdev(rdev); mutex_lock(&rdev->devlist_mtx); @@ -759,6 +765,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, break; case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_STATION: + cfg80211_lock_rdev(rdev); + __cfg80211_stop_sched_scan(rdev, false); + cfg80211_unlock_rdev(rdev); + wdev_lock(wdev); #ifdef CONFIG_CFG80211_WEXT kfree(wdev->wext.ie); diff --git a/net/wireless/core.h b/net/wireless/core.h index 7a18c10a7fb6..e3f7b1d995cd 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -60,8 +60,11 @@ struct cfg80211_registered_device { struct rb_root bss_tree; u32 bss_generation; struct cfg80211_scan_request *scan_req; /* protected by RTNL */ + struct cfg80211_sched_scan_request *sched_scan_req; unsigned long suspend_at; struct work_struct scan_done_wk; + struct work_struct sched_scan_results_wk; + struct work_struct sched_scan_stopped_wk; #ifdef CONFIG_NL80211_TESTMODE struct genl_info *testmode_info; @@ -411,6 +414,10 @@ void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); void cfg80211_sme_disassoc(struct net_device *dev, int idx); void __cfg80211_scan_done(struct work_struct *wk); void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); +void __cfg80211_sched_scan_results(struct work_struct *wk); +int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, + bool driver_initiated); +void __cfg80211_sched_scan_stopped(struct work_struct *wk); void cfg80211_upload_connect_keys(struct wireless_dev *wdev); int cfg80211_change_iface(struct cfg80211_registered_device *rdev, struct net_device *dev, enum nl80211_iftype ntype, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 95dd5832e719..4fac370284c0 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -761,6 +761,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, } CMD(set_channel, SET_CHANNEL); CMD(set_wds_peer, SET_WDS_PEER); + if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) + CMD(sched_scan_start, START_SCHED_SCAN); #undef CMD @@ -3357,6 +3359,179 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) return err; } +static int nl80211_start_sched_scan(struct sk_buff *skb, + struct genl_info *info) +{ + struct cfg80211_sched_scan_request *request; + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct net_device *dev = info->user_ptr[1]; + struct cfg80211_ssid *ssid; + struct ieee80211_channel *channel; + struct nlattr *attr; + struct wiphy *wiphy; + int err, tmp, n_ssids = 0, n_channels, i; + enum ieee80211_band band; + size_t ie_len; + + if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || + !rdev->ops->sched_scan_start) + return -EOPNOTSUPP; + + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + + if (rdev->sched_scan_req) + return -EINPROGRESS; + + wiphy = &rdev->wiphy; + + if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { + n_channels = validate_scan_freqs( + info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); + if (!n_channels) + return -EINVAL; + } else { + n_channels = 0; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) + if (wiphy->bands[band]) + n_channels += wiphy->bands[band]->n_channels; + } + + if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) + nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], + tmp) + n_ssids++; + + if (n_ssids > wiphy->max_scan_ssids) + return -EINVAL; + + if (info->attrs[NL80211_ATTR_IE]) + ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); + else + ie_len = 0; + + if (ie_len > wiphy->max_scan_ie_len) + return -EINVAL; + + request = kzalloc(sizeof(*request) + + sizeof(*ssid) * n_ssids + + sizeof(channel) * n_channels + + ie_len, GFP_KERNEL); + if (!request) + return -ENOMEM; + + if (n_ssids) + request->ssids = (void *)&request->channels[n_channels]; + request->n_ssids = n_ssids; + if (ie_len) { + if (request->ssids) + request->ie = (void *)(request->ssids + n_ssids); + else + request->ie = (void *)(request->channels + n_channels); + } + + i = 0; + if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { + /* user specified, bail out if channel not found */ + nla_for_each_nested(attr, + info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], + tmp) { + struct ieee80211_channel *chan; + + chan = ieee80211_get_channel(wiphy, nla_get_u32(attr)); + + if (!chan) { + err = -EINVAL; + goto out_free; + } + + /* ignore disabled channels */ + if (chan->flags & IEEE80211_CHAN_DISABLED) + continue; + + request->channels[i] = chan; + i++; + } + } else { + /* all channels */ + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + int j; + if (!wiphy->bands[band]) + continue; + for (j = 0; j < wiphy->bands[band]->n_channels; j++) { + struct ieee80211_channel *chan; + + chan = &wiphy->bands[band]->channels[j]; + + if (chan->flags & IEEE80211_CHAN_DISABLED) + continue; + + request->channels[i] = chan; + i++; + } + } + } + + if (!i) { + err = -EINVAL; + goto out_free; + } + + request->n_channels = i; + + i = 0; + if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { + nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], + tmp) { + if (request->ssids[i].ssid_len > + IEEE80211_MAX_SSID_LEN) { + err = -EINVAL; + goto out_free; + } + memcpy(request->ssids[i].ssid, nla_data(attr), + nla_len(attr)); + request->ssids[i].ssid_len = nla_len(attr); + i++; + } + } + + if (info->attrs[NL80211_ATTR_IE]) { + request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); + memcpy((void *)request->ie, + nla_data(info->attrs[NL80211_ATTR_IE]), + request->ie_len); + } + + request->dev = dev; + request->wiphy = &rdev->wiphy; + + err = rdev->ops->sched_scan_start(&rdev->wiphy, dev, request); + if (!err) { + rdev->sched_scan_req = request; + nl80211_send_sched_scan(rdev, dev, + NL80211_CMD_START_SCHED_SCAN); + goto out; + } + +out_free: + kfree(request); +out: + return err; +} + +static int nl80211_stop_sched_scan(struct sk_buff *skb, + struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + + if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || + !rdev->ops->sched_scan_stop) + return -EOPNOTSUPP; + + return __cfg80211_stop_sched_scan(rdev, false); +} + static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, @@ -5326,6 +5501,22 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .dumpit = nl80211_dump_scan, }, + { + .cmd = NL80211_CMD_START_SCHED_SCAN, + .doit = nl80211_start_sched_scan, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { + .cmd = NL80211_CMD_STOP_SCHED_SCAN, + .doit = nl80211_stop_sched_scan, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, { .cmd = NL80211_CMD_AUTHENTICATE, .doit = nl80211_authenticate, @@ -5652,6 +5843,28 @@ static int nl80211_send_scan_msg(struct sk_buff *msg, return -EMSGSIZE; } +static int +nl80211_send_sched_scan_msg(struct sk_buff *msg, + struct cfg80211_registered_device *rdev, + struct net_device *netdev, + u32 pid, u32 seq, int flags, u32 cmd) +{ + void *hdr; + + hdr = nl80211hdr_put(msg, pid, seq, flags, cmd); + if (!hdr) + return -1; + + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + + return genlmsg_end(msg, hdr); + + nla_put_failure: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, struct net_device *netdev) { @@ -5709,6 +5922,43 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, nl80211_scan_mcgrp.id, GFP_KERNEL); } +void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, + struct net_device *netdev) +{ + struct sk_buff *msg; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return; + + if (nl80211_send_sched_scan_msg(msg, rdev, netdev, 0, 0, 0, + NL80211_CMD_SCHED_SCAN_RESULTS) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, + nl80211_scan_mcgrp.id, GFP_KERNEL); +} + +void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, + struct net_device *netdev, u32 cmd) +{ + struct sk_buff *msg; + + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return; + + if (nl80211_send_sched_scan_msg(msg, rdev, netdev, 0, 0, 0, cmd) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, + nl80211_scan_mcgrp.id, GFP_KERNEL); +} + /* * This can happen on global regulatory changes or device specific settings * based on custom world regulatory domains. diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index f2af6955a665..2f1bfb87a651 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -12,6 +12,10 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, struct net_device *netdev); void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, struct net_device *netdev); +void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, + struct net_device *netdev, u32 cmd); +void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, + struct net_device *netdev); void nl80211_send_reg_change_event(struct regulatory_request *request); void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev, struct net_device *netdev, diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 62e542a2b192..65dfae3b9d41 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -93,6 +93,76 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) } EXPORT_SYMBOL(cfg80211_scan_done); +void __cfg80211_sched_scan_results(struct work_struct *wk) +{ + struct cfg80211_registered_device *rdev; + + rdev = container_of(wk, struct cfg80211_registered_device, + sched_scan_results_wk); + + cfg80211_lock_rdev(rdev); + + /* we don't have sched_scan_req anymore if the scan is stopping */ + if (rdev->sched_scan_req) + nl80211_send_sched_scan_results(rdev, + rdev->sched_scan_req->dev); + + cfg80211_unlock_rdev(rdev); +} + +void cfg80211_sched_scan_results(struct wiphy *wiphy) +{ + /* ignore if we're not scanning */ + if (wiphy_to_dev(wiphy)->sched_scan_req) + queue_work(cfg80211_wq, + &wiphy_to_dev(wiphy)->sched_scan_results_wk); +} +EXPORT_SYMBOL(cfg80211_sched_scan_results); + +void __cfg80211_sched_scan_stopped(struct work_struct *wk) +{ + struct cfg80211_registered_device *rdev; + + rdev = container_of(wk, struct cfg80211_registered_device, + sched_scan_stopped_wk); + + cfg80211_lock_rdev(rdev); + __cfg80211_stop_sched_scan(rdev, true); + cfg80211_unlock_rdev(rdev); +} + +void cfg80211_sched_scan_stopped(struct wiphy *wiphy) +{ + queue_work(cfg80211_wq, &wiphy_to_dev(wiphy)->sched_scan_stopped_wk); +} +EXPORT_SYMBOL(cfg80211_sched_scan_stopped); + +int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, + bool driver_initiated) +{ + int err; + struct net_device *dev; + + ASSERT_RDEV_LOCK(rdev); + + if (!rdev->sched_scan_req) + return 0; + + dev = rdev->sched_scan_req->dev; + + err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev, + driver_initiated); + if (err) + return err; + + nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED); + + kfree(rdev->sched_scan_req); + rdev->sched_scan_req = NULL; + + return err; +} + static void bss_release(struct kref *ref) { struct cfg80211_internal_bss *bss; -- cgit v1.2.3-58-ga151 From 79f460ca49d8d5700756ab7071c951311c7f29cc Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Wed, 11 May 2011 17:09:36 +0300 Subject: mac80211: add support for HW scheduled scan Implement support for HW scheduled scan. The mac80211 code doesn't perform scheduled scans itself, but calls the driver to start and stop scheduled scans. This patch also creates a trace event class to be used by drv_hw_scan and the new drv_sched_scan_start and drv_sched_stop functions, in order to avoid duplicate code. Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- include/net/mac80211.h | 50 +++++++++++++++++++++++ net/mac80211/cfg.c | 27 +++++++++++++ net/mac80211/driver-ops.h | 29 ++++++++++++- net/mac80211/driver-trace.h | 88 +++++++++++++++++++++++++++++++--------- net/mac80211/ieee80211_i.h | 9 +++++ net/mac80211/main.c | 6 ++- net/mac80211/rx.c | 6 ++- net/mac80211/scan.c | 99 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 292 insertions(+), 22 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9e5542794b95..62a1c225b7cb 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -537,6 +537,21 @@ struct ieee80211_tx_info { }; }; +/** + * ieee80211_sched_scan_ies - scheduled scan IEs + * + * This structure is used to pass the appropriate IEs to be used in scheduled + * scans for all bands. It contains both the IEs passed from the userspace + * and the ones generated by mac80211. + * + * @ie: array with the IEs for each supported band + * @len: array with the total length of the IEs for each band + */ +struct ieee80211_sched_scan_ies { + u8 *ie[IEEE80211_NUM_BANDS]; + size_t len[IEEE80211_NUM_BANDS]; +}; + static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb) { return (struct ieee80211_tx_info *)skb->cb; @@ -1693,6 +1708,13 @@ enum ieee80211_ampdu_mlme_action { * any error unless this callback returned a negative error code. * The callback can sleep. * + * @sched_scan_start: Ask the hardware to start scanning repeatedly at + * specific intervals. The driver must call the + * ieee80211_sched_scan_results() function whenever it finds results. + * This process will continue until sched_scan_stop is called. + * + * @sched_scan_stop: Tell the hardware to stop an ongoing scheduled scan. + * * @sw_scan_start: Notifier function that is called just before a software scan * is started. Can be NULL, if the driver doesn't need this notification. * The callback can sleep. @@ -1877,6 +1899,12 @@ struct ieee80211_ops { u32 iv32, u16 *phase1key); int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_scan_request *req); + int (*sched_scan_start)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_sched_scan_request *req, + struct ieee80211_sched_scan_ies *ies); + void (*sched_scan_stop)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); void (*sw_scan_start)(struct ieee80211_hw *hw); void (*sw_scan_complete)(struct ieee80211_hw *hw); int (*get_stats)(struct ieee80211_hw *hw, @@ -2593,6 +2621,28 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw); */ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted); +/** + * ieee80211_sched_scan_results - got results from scheduled scan + * + * When a scheduled scan is running, this function needs to be called by the + * driver whenever there are new scan results available. + * + * @hw: the hardware that is performing scheduled scans + */ +void ieee80211_sched_scan_results(struct ieee80211_hw *hw); + +/** + * ieee80211_sched_scan_stopped - inform that the scheduled scan has stopped + * + * When a scheduled scan is running, this function can be called by + * the driver if it needs to stop the scan to perform another task. + * Usual scenarios are drivers that cannot continue the scheduled scan + * while associating, for instance. + * + * @hw: the hardware that is performing scheduled scans + */ +void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw); + /** * ieee80211_iterate_active_interfaces - iterate active interfaces * diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c416cce5e1ed..a2ff47493e0a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1362,6 +1362,31 @@ static int ieee80211_scan(struct wiphy *wiphy, return ieee80211_request_scan(sdata, req); } +static int +ieee80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request *req) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (!sdata->local->ops->sched_scan_start) + return -EOPNOTSUPP; + + return ieee80211_request_sched_scan_start(sdata, req); +} + +static int +ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev, + bool driver_initiated) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (!sdata->local->ops->sched_scan_stop) + return -EOPNOTSUPP; + + return ieee80211_request_sched_scan_stop(sdata, driver_initiated); +} + static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_auth_request *req) { @@ -2103,6 +2128,8 @@ struct cfg80211_ops mac80211_config_ops = { .suspend = ieee80211_suspend, .resume = ieee80211_resume, .scan = ieee80211_scan, + .sched_scan_start = ieee80211_sched_scan_start, + .sched_scan_stop = ieee80211_sched_scan_stop, .auth = ieee80211_auth, .assoc = ieee80211_assoc, .deauth = ieee80211_deauth, diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index aa16bd8ef789..eebf7a67daf7 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -212,12 +212,39 @@ static inline int drv_hw_scan(struct ieee80211_local *local, might_sleep(); - trace_drv_hw_scan(local, sdata, req); + trace_drv_hw_scan(local, sdata); ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); trace_drv_return_int(local, ret); return ret; } +static inline int +drv_sched_scan_start(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct cfg80211_sched_scan_request *req, + struct ieee80211_sched_scan_ies *ies) +{ + int ret; + + might_sleep(); + + trace_drv_sched_scan_start(local, sdata); + ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, + req, ies); + trace_drv_return_int(local, ret); + return ret; +} + +static inline void drv_sched_scan_stop(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) +{ + might_sleep(); + + trace_drv_sched_scan_stop(local, sdata); + local->ops->sched_scan_stop(&local->hw, &sdata->vif); + trace_drv_return_void(local); +} + static inline void drv_sw_scan_start(struct ieee80211_local *local) { might_sleep(); diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index dd9779d41d2b..ed9edcbd9aa5 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -98,6 +98,27 @@ DECLARE_EVENT_CLASS(local_u32_evt, ) ); +DECLARE_EVENT_CLASS(local_sdata_evt, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT, + LOCAL_PR_ARG, VIF_PR_ARG + ) +); + DEFINE_EVENT(local_only_evt, drv_return_void, TP_PROTO(struct ieee80211_local *local), TP_ARGS(local) @@ -433,27 +454,22 @@ TRACE_EVENT(drv_update_tkip_key, ) ); -TRACE_EVENT(drv_hw_scan, +DEFINE_EVENT(local_sdata_evt, drv_hw_scan, TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - struct cfg80211_scan_request *req), - - TP_ARGS(local, sdata, req), - - TP_STRUCT__entry( - LOCAL_ENTRY - VIF_ENTRY - ), + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata) +); - TP_fast_assign( - LOCAL_ASSIGN; - VIF_ASSIGN; - ), +DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata) +); - TP_printk( - LOCAL_PR_FMT VIF_PR_FMT, - LOCAL_PR_ARG,VIF_PR_ARG - ) +DEFINE_EVENT(local_sdata_evt, drv_sched_scan_stop, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata) ); DEFINE_EVENT(local_only_evt, drv_sw_scan_start, @@ -1180,6 +1196,42 @@ TRACE_EVENT(api_scan_completed, ) ); +TRACE_EVENT(api_sched_scan_results, + TP_PROTO(struct ieee80211_local *local), + + TP_ARGS(local), + + TP_STRUCT__entry( + LOCAL_ENTRY + ), + + TP_fast_assign( + LOCAL_ASSIGN; + ), + + TP_printk( + LOCAL_PR_FMT, LOCAL_PR_ARG + ) +); + +TRACE_EVENT(api_sched_scan_stopped, + TP_PROTO(struct ieee80211_local *local), + + TP_ARGS(local), + + TP_STRUCT__entry( + LOCAL_ENTRY + ), + + TP_fast_assign( + LOCAL_ASSIGN; + ), + + TP_printk( + LOCAL_PR_FMT, LOCAL_PR_ARG + ) +); + TRACE_EVENT(api_sta_block_awake, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sta *sta, bool block), diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 7f4d0dc1d534..6f55a789c099 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -847,6 +847,9 @@ struct ieee80211_local { int scan_channel_idx; int scan_ies_len; + bool sched_scanning; + struct ieee80211_sched_scan_ies sched_scan_ies; + unsigned long leave_oper_channel_time; enum mac80211_scan_state next_scan_state; struct delayed_work scan_work; @@ -1154,6 +1157,12 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_bss *bss); +/* scheduled scan handling */ +int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, + struct cfg80211_sched_scan_request *req); +int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata, + bool driver_initiated); + /* off-channel helpers */ bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, diff --git a/net/mac80211/main.c b/net/mac80211/main.c index ab1f464817af..30e6a682a047 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -358,7 +358,8 @@ static void ieee80211_restart_work(struct work_struct *work) flush_workqueue(local->workqueue); mutex_lock(&local->mtx); - WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), + WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) || + local->sched_scanning, "%s called with hardware scan in progress\n", __func__); mutex_unlock(&local->mtx); @@ -833,6 +834,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (!local->ops->remain_on_channel) local->hw.wiphy->max_remain_on_channel_duration = 5000; + if (local->ops->sched_scan_start) + local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; + result = wiphy_register(local->hw.wiphy); if (result < 0) goto fail_wiphy_register; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 634f3d97a279..1b9413fb3839 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -404,11 +404,13 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); struct sk_buff *skb = rx->skb; - if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN))) + if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN) && + !local->sched_scanning)) return RX_CONTINUE; if (test_bit(SCAN_HW_SCANNING, &local->scanning) || - test_bit(SCAN_SW_SCANNING, &local->scanning)) + test_bit(SCAN_SW_SCANNING, &local->scanning) || + local->sched_scanning) return ieee80211_scan_rx(rx->sdata, skb); /* scanning finished during invoking of handlers */ diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 8acce724f0dc..ea44a8e941ec 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -850,3 +851,101 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) } mutex_unlock(&local->mtx); } + +int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, + struct cfg80211_sched_scan_request *req) +{ + struct ieee80211_local *local = sdata->local; + int ret, i; + + mutex_lock(&sdata->local->mtx); + + if (local->sched_scanning) { + ret = -EBUSY; + goto out; + } + + if (!local->ops->sched_scan_start) { + ret = -ENOTSUPP; + goto out; + } + + for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + local->sched_scan_ies.ie[i] = kzalloc(2 + + IEEE80211_MAX_SSID_LEN + + local->scan_ies_len, + GFP_KERNEL); + if (!local->sched_scan_ies.ie[i]) { + ret = -ENOMEM; + goto out_free; + } + + local->sched_scan_ies.len[i] = + ieee80211_build_preq_ies(local, + local->sched_scan_ies.ie[i], + req->ie, req->ie_len, i, + (u32) -1, 0); + } + + ret = drv_sched_scan_start(local, sdata, req, + &local->sched_scan_ies); + if (ret == 0) { + local->sched_scanning = true; + goto out; + } + +out_free: + while (i > 0) + kfree(local->sched_scan_ies.ie[--i]); +out: + mutex_unlock(&sdata->local->mtx); + return ret; +} + +int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata, + bool driver_initiated) +{ + struct ieee80211_local *local = sdata->local; + int ret = 0, i; + + mutex_lock(&sdata->local->mtx); + + if (!local->ops->sched_scan_stop) { + ret = -ENOTSUPP; + goto out; + } + + if (local->sched_scanning) { + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + kfree(local->sched_scan_ies.ie[i]); + + if (!driver_initiated) + drv_sched_scan_stop(local, sdata); + local->sched_scanning = false; + } + +out: + mutex_unlock(&sdata->local->mtx); + + return ret; +} + +void ieee80211_sched_scan_results(struct ieee80211_hw *hw) +{ + struct ieee80211_local *local = hw_to_local(hw); + + trace_api_sched_scan_results(local); + + cfg80211_sched_scan_results(hw->wiphy); +} +EXPORT_SYMBOL(ieee80211_sched_scan_results); + +void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw) +{ + struct ieee80211_local *local = hw_to_local(hw); + + trace_api_sched_scan_stopped(local); + + cfg80211_sched_scan_stopped(hw->wiphy); +} +EXPORT_SYMBOL(ieee80211_sched_scan_stopped); -- cgit v1.2.3-58-ga151 From bbe6ad6dcb1eb26bd12ec85320f402721c3383ae Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Wed, 11 May 2011 17:09:37 +0300 Subject: cfg80211/nl80211: add interval attribute for scheduled scans Introduce NL80211_ATTR_SCHED_SCAN_INTERVAL as a required attribute for NL80211_CMD_START_SCHED_SCAN. This value informs the driver at which intervals the scheduled scan cycles should be executed. Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- include/linux/nl80211.h | 25 ++++++++++++++++--------- include/net/cfg80211.h | 2 ++ net/wireless/nl80211.c | 10 ++++++++++ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index f8b5595ba4af..281a2bb6a6ec 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -203,15 +203,17 @@ * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, * partial scan results may be available * - * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan. Like with normal - * scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS) are passed, they are used - * in the probe requests. For broadcast, a broadcast SSID must be - * passed (ie. an empty string). If no SSID is passed, no probe - * requests are sent and a passive scan is performed. - * %NL80211_ATTR_SCAN_FREQUENCIES, if passed, define which channels - * should be scanned; if not passed, all channels allowed for the - * current regulatory domain are used. Extra IEs can also be passed - * from the userspace by using the %NL80211_ATTR_IE attribute. + * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan at certain + * intervals, as specified by %NL80211_ATTR_SCHED_SCAN_INTERVAL. + * Like with normal scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS) + * are passed, they are used in the probe requests. For + * broadcast, a broadcast SSID must be passed (ie. an empty + * string). If no SSID is passed, no probe requests are sent and + * a passive scan is performed. %NL80211_ATTR_SCAN_FREQUENCIES, + * if passed, define which channels should be scanned; if not + * passed, all channels allowed for the current regulatory domain + * are used. Extra IEs can also be passed from the userspace by + * using the %NL80211_ATTR_IE attribute. * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan * @NL80211_CMD_SCHED_SCAN_RESULTS: indicates that there are scheduled scan * results available. @@ -948,6 +950,9 @@ enum nl80211_commands { * indicate which WoW triggers should be enabled. This is also * used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN * triggers. + + * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan + * cycles, in msecs. * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -1142,6 +1147,8 @@ enum nl80211_attrs { NL80211_ATTR_WOWLAN_TRIGGERS, NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, + NL80211_ATTR_SCHED_SCAN_INTERVAL, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index e214c85b74d2..1f1e221b6ce3 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -829,6 +829,7 @@ struct cfg80211_scan_request { * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans) * @n_ssids: number of SSIDs * @n_channels: total number of channels to scan + * @interval: interval between each scheduled scan cycle * @ie: optional information element(s) to add into Probe Request or %NULL * @ie_len: length of ie in octets * @wiphy: the wiphy this was for @@ -839,6 +840,7 @@ struct cfg80211_sched_scan_request { struct cfg80211_ssid *ssids; int n_ssids; u32 n_channels; + u32 interval; const u8 *ie; size_t ie_len; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4fac370284c0..b5b050b62f2a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -175,6 +175,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED }, [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 }, + [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, }; /* policy for the key attributes */ @@ -3370,6 +3371,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, struct nlattr *attr; struct wiphy *wiphy; int err, tmp, n_ssids = 0, n_channels, i; + u32 interval; enum ieee80211_band band; size_t ie_len; @@ -3383,6 +3385,13 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, if (rdev->sched_scan_req) return -EINPROGRESS; + if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]) + return -EINVAL; + + interval = nla_get_u32(info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]); + if (interval == 0) + return -EINVAL; + wiphy = &rdev->wiphy; if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { @@ -3505,6 +3514,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, request->dev = dev; request->wiphy = &rdev->wiphy; + request->interval = interval; err = rdev->ops->sched_scan_start(&rdev->wiphy, dev, request); if (!err) { -- cgit v1.2.3-58-ga151 From 83bc71b4102d2a288edaf9ee398b330b88a88086 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 6 May 2011 18:41:43 -0300 Subject: Bluetooth: Add support for sending connection events for LE links We need to be able for receive events notifying that the connection was established, the connection attempt failed or that disconnection happened. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d5aa97ee6ffa..f13ddbf858ba 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1440,7 +1440,7 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff conn->state = BT_CLOSED; - if (conn->type == ACL_LINK) + if (conn->type == ACL_LINK || conn->type == LE_LINK) mgmt_disconnected(hdev->id, &conn->dst); hci_proto_disconn_cfm(conn, ev->reason); @@ -2659,12 +2659,15 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff } if (ev->status) { + mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); hci_proto_connect_cfm(conn, ev->status); conn->state = BT_CLOSED; hci_conn_del(conn); goto unlock; } + mgmt_connected(hdev->id, &ev->bdaddr); + conn->handle = __le16_to_cpu(ev->handle); conn->state = BT_CONNECTED; -- cgit v1.2.3-58-ga151 From 365227e5fdf3d117e096416d9d3cc148959a829e Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 6 May 2011 18:41:44 -0300 Subject: Bluetooth: Add support for disconnecting LE links via mgmt If we can't find a ACL link between the devices, we search the connection list one second time looking for LE links. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo F. Padovan --- net/bluetooth/mgmt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 2481d257ed98..dae382ce7020 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1033,6 +1033,9 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) } conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); + if (!conn) + conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr); + if (!conn) { err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENOTCONN); goto failed; -- cgit v1.2.3-58-ga151 From 009dd872d753f854cf13c8334e0055092f539b38 Mon Sep 17 00:00:00 2001 From: Padmanabh Ratnakar Date: Tue, 10 May 2011 05:12:17 +0000 Subject: be2net: Handle error completion in Lancer In Lancer if a frame is DMAed partially due to lack of RX buffers, an error completion is sent with packet size as zero and num_recvd indicating number of used buffers. These buffers need to be freed and packet dropped. Signed-off-by: Padmanabh Ratnakar Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 3fb4a1f465e1..3202f67d8785 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1757,12 +1757,15 @@ static int be_poll_rx(struct napi_struct *napi, int budget) break; /* Ignore flush completions */ - if (rxcp->num_rcvd) { + if (rxcp->num_rcvd && rxcp->pkt_size) { if (do_gro(rxcp)) be_rx_compl_process_gro(adapter, rxo, rxcp); else be_rx_compl_process(adapter, rxo, rxcp); + } else if (rxcp->pkt_size == 0) { + be_rx_compl_discard(adapter, rxo, rxcp); } + be_rx_stats_update(rxo, rxcp); } -- cgit v1.2.3-58-ga151 From 6bd011d54254d6f2a5314ab0ed38e66772e6b9f7 Mon Sep 17 00:00:00 2001 From: Padmanabh Ratnakar Date: Tue, 10 May 2011 05:12:37 +0000 Subject: be2net: Disable coalesce water mark mode of CQ for Lancer Disable coalesce water mark mode of CQ for Lancer Signed-off-by: Padmanabh Ratnakar Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 5fedc27c8839..391dee211027 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -729,8 +729,6 @@ int be_cmd_cq_create(struct be_adapter *adapter, if (lancer_chip(adapter)) { req->hdr.version = 2; req->page_size = 1; /* 1 for 4K */ - AMAP_SET_BITS(struct amap_cq_context_lancer, coalescwm, ctxt, - coalesce_wm); AMAP_SET_BITS(struct amap_cq_context_lancer, nodelay, ctxt, no_delay); AMAP_SET_BITS(struct amap_cq_context_lancer, count, ctxt, -- cgit v1.2.3-58-ga151 From 18a91e6002207c8212e0960854f88ab924ea22f9 Mon Sep 17 00:00:00 2001 From: Padmanabh Ratnakar Date: Tue, 10 May 2011 05:13:01 +0000 Subject: be2net: In case of UE, do not dump registers for Lancer In case of UE, do not dump registers for Lancer as they are not supported. Signed-off-by: Padmanabh Ratnakar Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 391dee211027..bdd6c5402adf 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -293,7 +293,8 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) if (msecs > 4000) { dev_err(&adapter->pdev->dev, "mbox poll timed out\n"); - be_detect_dump_ue(adapter); + if (!lancer_chip(adapter)) + be_detect_dump_ue(adapter); return -1; } -- cgit v1.2.3-58-ga151 From ecd0bf0f7b280bac3ac7419ed3aac84cd92878e9 Mon Sep 17 00:00:00 2001 From: Padmanabh Ratnakar Date: Tue, 10 May 2011 05:13:26 +0000 Subject: be2net: Use NTWK_RX_FILTER command for promiscous mode Use OPCODE_COMMON_NTWK_RX_FILTER command for promiscous mode as OPCODE_ETH_PROMISCUOUS command is getting deprecated. Signed-off-by: Padmanabh Ratnakar Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 46 ++++++++++++++++++++++++++++++--------------- drivers/net/benet/be_cmds.h | 24 ++++++++++++++--------- drivers/net/benet/be_main.c | 4 ++-- 3 files changed, 48 insertions(+), 26 deletions(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index bdd6c5402adf..0dbb4cbc07b6 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1404,12 +1404,24 @@ err: /* Uses MCC for this command as it may be called in BH context * Uses synchronous mcc */ -int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en) +int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en) { struct be_mcc_wrb *wrb; - struct be_cmd_req_promiscuous_config *req; + struct be_cmd_req_rx_filter *req; + struct be_dma_mem promiscous_cmd; + struct be_sge *sge; int status; + memset(&promiscous_cmd, 0, sizeof(struct be_dma_mem)); + promiscous_cmd.size = sizeof(struct be_cmd_req_rx_filter); + promiscous_cmd.va = pci_alloc_consistent(adapter->pdev, + promiscous_cmd.size, &promiscous_cmd.dma); + if (!promiscous_cmd.va) { + dev_err(&adapter->pdev->dev, + "Memory allocation failure\n"); + return -ENOMEM; + } + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -1417,26 +1429,30 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en) status = -EBUSY; goto err; } - req = embedded_payload(wrb); - be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_ETH_PROMISCUOUS); + req = promiscous_cmd.va; + sge = nonembedded_sgl(wrb); - be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, - OPCODE_ETH_PROMISCUOUS, sizeof(*req)); - - /* In FW versions X.102.149/X.101.487 and later, - * the port setting associated only with the - * issuing pci function will take effect - */ - if (port_num) - req->port1_promiscuous = en; - else - req->port0_promiscuous = en; + be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1, + OPCODE_COMMON_NTWK_RX_FILTER); + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req)); + + req->if_id = cpu_to_le32(adapter->if_handle); + req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); + if (en) + req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); + + sge->pa_hi = cpu_to_le32(upper_32_bits(promiscous_cmd.dma)); + sge->pa_lo = cpu_to_le32(promiscous_cmd.dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(promiscous_cmd.size); status = be_mcc_notify_wait(adapter); err: spin_unlock_bh(&adapter->mcc_lock); + pci_free_consistent(adapter->pdev, promiscous_cmd.size, + promiscous_cmd.va, promiscous_cmd.dma); return status; } diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index af4bbff5feba..78256b65cb03 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -714,13 +714,6 @@ struct be_cmd_req_vlan_config { u16 normal_vlan[64]; } __packed; -struct be_cmd_req_promiscuous_config { - struct be_cmd_req_hdr hdr; - u8 port0_promiscuous; - u8 port1_promiscuous; - u16 rsvd0; -} __packed; - /******************** Multicast MAC Config *******************/ #define BE_MAX_MC 64 /* set mcast promisc if > 64 */ struct macaddr { @@ -741,6 +734,20 @@ hw_stats_from_cmd(struct be_cmd_resp_get_stats *cmd) return &cmd->hw_stats; } + +/******************* RX FILTER ******************************/ +struct be_cmd_req_rx_filter { + struct be_cmd_req_hdr hdr; + u32 global_flags_mask; + u32 global_flags; + u32 if_flags_mask; + u32 if_flags; + u32 if_id; + u32 multicast_num; + struct macaddr mac[BE_MAX_MC]; +}; + + /******************** Link Status Query *******************/ struct be_cmd_req_link_status { struct be_cmd_req_hdr hdr; @@ -1122,8 +1129,7 @@ extern int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd); extern int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, u32 num, bool untagged, bool promiscuous); -extern int be_cmd_promiscuous_config(struct be_adapter *adapter, - u8 port_num, bool en); +extern int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en); extern int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, struct net_device *netdev, struct be_dma_mem *mem); extern int be_cmd_set_flow_control(struct be_adapter *adapter, diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 3202f67d8785..babe53af7e86 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -698,7 +698,7 @@ static void be_set_multicast_list(struct net_device *netdev) struct be_adapter *adapter = netdev_priv(netdev); if (netdev->flags & IFF_PROMISC) { - be_cmd_promiscuous_config(adapter, adapter->port_num, 1); + be_cmd_promiscuous_config(adapter, true); adapter->promiscuous = true; goto done; } @@ -706,7 +706,7 @@ static void be_set_multicast_list(struct net_device *netdev) /* BE was previously in promiscuous mode; disable it */ if (adapter->promiscuous) { adapter->promiscuous = false; - be_cmd_promiscuous_config(adapter, adapter->port_num, 0); + be_cmd_promiscuous_config(adapter, false); } /* Enable multicast promisc if num configured exceeds what we support */ -- cgit v1.2.3-58-ga151 From 4d586b823acc46c55c889ae1798de236c9d403da Mon Sep 17 00:00:00 2001 From: Padmanabh Ratnakar Date: Tue, 10 May 2011 05:13:57 +0000 Subject: be2net: Fix to prevent flooding of TX queue Start/stop TX queue is controlled by TX queue "used" counter. It is incremented while WRBs are posted to TX queue and decremented when TX completions are received. This counter was getting decremented before HW is informed about processing of TX completions. As used counter is decremented, transmit function posts new WRBs and creates completion queue full scenario in HW. Signed-off-by: Padmanabh Ratnakar Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index babe53af7e86..243172bedfa6 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1275,7 +1275,7 @@ static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq) return txcp; } -static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index) +static u16 be_tx_compl_process(struct be_adapter *adapter, u16 last_index) { struct be_queue_info *txq = &adapter->tx_obj.q; struct be_eth_wrb *wrb; @@ -1302,9 +1302,8 @@ static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index) queue_tail_inc(txq); } while (cur_index != last_index); - atomic_sub(num_wrbs, &txq->used); - kfree_skb(sent_skb); + return num_wrbs; } static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj) @@ -1387,7 +1386,7 @@ static void be_tx_compl_clean(struct be_adapter *adapter) struct be_queue_info *tx_cq = &adapter->tx_obj.cq; struct be_queue_info *txq = &adapter->tx_obj.q; struct be_eth_tx_compl *txcp; - u16 end_idx, cmpl = 0, timeo = 0; + u16 end_idx, cmpl = 0, timeo = 0, num_wrbs = 0; struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; struct sk_buff *sent_skb; bool dummy_wrb; @@ -1397,12 +1396,14 @@ static void be_tx_compl_clean(struct be_adapter *adapter) while ((txcp = be_tx_compl_get(tx_cq))) { end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, wrb_index, txcp); - be_tx_compl_process(adapter, end_idx); + num_wrbs += be_tx_compl_process(adapter, end_idx); cmpl++; } if (cmpl) { be_cq_notify(adapter, tx_cq->id, false, cmpl); + atomic_sub(num_wrbs, &txq->used); cmpl = 0; + num_wrbs = 0; } if (atomic_read(&txq->used) == 0 || ++timeo > 200) @@ -1422,7 +1423,8 @@ static void be_tx_compl_clean(struct be_adapter *adapter) index_adv(&end_idx, wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1, txq->len); - be_tx_compl_process(adapter, end_idx); + num_wrbs = be_tx_compl_process(adapter, end_idx); + atomic_sub(num_wrbs, &txq->used); } } @@ -1796,12 +1798,12 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget) struct be_queue_info *tx_cq = &adapter->tx_obj.cq; struct be_eth_tx_compl *txcp; int tx_compl = 0, mcc_compl, status = 0; - u16 end_idx; + u16 end_idx, num_wrbs = 0; while ((txcp = be_tx_compl_get(tx_cq))) { end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, wrb_index, txcp); - be_tx_compl_process(adapter, end_idx); + num_wrbs += be_tx_compl_process(adapter, end_idx); tx_compl++; } @@ -1817,6 +1819,8 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget) if (tx_compl) { be_cq_notify(adapter, adapter->tx_obj.cq.id, true, tx_compl); + atomic_sub(num_wrbs, &txq->used); + /* As Tx wrbs have been freed up, wake up netdev queue if * it was stopped due to lack of tx wrbs. */ -- cgit v1.2.3-58-ga151 From 55183d06cd1bd939ceccdad628b0aae12c86b803 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 11 May 2011 19:26:06 -0300 Subject: Bluetooth: Remove leftover debug messages They were added by me while testing and I forgot to remove. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index d0769a83cb58..a5ab4a29ae31 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -2095,7 +2095,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd u16 dcid = 0, scid = __le16_to_cpu(req->scid); __le16 psm = req->psm; - BT_ERR("psm 0x%2.2x scid 0x%4.4x", psm, scid); + BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); /* Check if we have socket listening on psm */ pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src); @@ -2104,8 +2104,6 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd goto sendresp; } - BT_ERR("%p 0x%2.2x", pchan, pchan->psm); - parent = pchan->sk; bh_lock_sock(parent); -- cgit v1.2.3-58-ga151 From 4daf50f20256e0022c87c1609226e971a70c82fd Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Thu, 12 May 2011 09:32:17 -0400 Subject: mac80211: Fix mesh-related build breakage... MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit net/mac80211/cfg.c: In function ‘sta_apply_parameters’: net/mac80211/cfg.c:746: error: ‘struct sta_info’ has no member named ‘plink_state’ make[1]: *** [net/mac80211/cfg.o] Error 1 make: *** [net/mac80211/mac80211.ko] Error 2 Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a2ff47493e0a..ed3400cd7a5a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -738,6 +738,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, &sta->sta.ht_cap); if (ieee80211_vif_is_mesh(&sdata->vif)) { +#ifdef CONFIG_MAC80211_MESH if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) switch (params->plink_state) { case PLINK_LISTEN: @@ -758,6 +759,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, mesh_plink_block(sta); break; } +#endif } } -- cgit v1.2.3-58-ga151 From 56d1893d94bc06d0b1aa3a53f924ed02f9e207bf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 9 May 2011 18:41:15 +0200 Subject: cfg80211: restrict AP beacon intervals Multiple virtual AP interfaces can currently try to use different beacon intervals, but that just leads to problems since it won't actually be done that way by drivers. Return an error in this case to make sure it won't be done wrong. Also, ignore attempts to change the DTIM period or beacon interval during the lifetime of the BSS. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 4 ++++ net/wireless/core.c | 1 + net/wireless/core.h | 3 +++ net/wireless/nl80211.c | 40 +++++++++++++++++++++++----------------- net/wireless/util.c | 25 +++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 17 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 1f1e221b6ce3..a46adb7a91b7 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1908,6 +1908,8 @@ struct cfg80211_cached_keys; * @mgmt_registrations_lock: lock for the list * @mtx: mutex used to lock data in this struct * @cleanup_work: work struct used for cleanup that can't be done directly + * @beacon_interval: beacon interval used on this device for transmitting + * beacons, 0 when not valid */ struct wireless_dev { struct wiphy *wiphy; @@ -1948,6 +1950,8 @@ struct wireless_dev { bool ps; int ps_timeout; + int beacon_interval; + #ifdef CONFIG_CFG80211_WEXT /* wext data */ struct { diff --git a/net/wireless/core.c b/net/wireless/core.c index f924a49b2425..e2ab65d7c86d 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -787,6 +787,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, default: break; } + wdev->beacon_interval = 0; break; case NETDEV_DOWN: dev_hold(dev); diff --git a/net/wireless/core.h b/net/wireless/core.h index e3f7b1d995cd..fd9135f9b5be 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -433,6 +433,9 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev, u16 cfg80211_calculate_bitrate(struct rate_info *rate); +int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, + u32 beacon_int); + #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS #define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond) #else diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b5b050b62f2a..9ef8e287d61b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1876,8 +1876,9 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) struct beacon_parameters *info); struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; + struct wireless_dev *wdev = dev->ieee80211_ptr; struct beacon_parameters params; - int haveinfo = 0; + int haveinfo = 0, err; if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) return -EINVAL; @@ -1886,6 +1887,8 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) return -EOPNOTSUPP; + memset(¶ms, 0, sizeof(params)); + switch (info->genlhdr->cmd) { case NL80211_CMD_NEW_BEACON: /* these are required for NEW_BEACON */ @@ -1894,6 +1897,15 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) !info->attrs[NL80211_ATTR_BEACON_HEAD]) return -EINVAL; + params.interval = + nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); + params.dtim_period = + nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); + + err = cfg80211_validate_beacon_int(rdev, params.interval); + if (err) + return err; + call = rdev->ops->add_beacon; break; case NL80211_CMD_SET_BEACON: @@ -1907,20 +1919,6 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) if (!call) return -EOPNOTSUPP; - memset(¶ms, 0, sizeof(params)); - - if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) { - params.interval = - nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); - haveinfo = 1; - } - - if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) { - params.dtim_period = - nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); - haveinfo = 1; - } - if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); params.head_len = @@ -1938,13 +1936,18 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) if (!haveinfo) return -EINVAL; - return call(&rdev->wiphy, dev, ¶ms); + err = call(&rdev->wiphy, dev, ¶ms); + if (!err && params.interval) + wdev->beacon_interval = params.interval; + return err; } static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; + struct wireless_dev *wdev = dev->ieee80211_ptr; + int err; if (!rdev->ops->del_beacon) return -EOPNOTSUPP; @@ -1953,7 +1956,10 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) return -EOPNOTSUPP; - return rdev->ops->del_beacon(&rdev->wiphy, dev); + err = rdev->ops->del_beacon(&rdev->wiphy, dev); + if (!err) + wdev->beacon_interval = 0; + return err; } static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { diff --git a/net/wireless/util.c b/net/wireless/util.c index 6a750bc6bcfe..414c9f604df6 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -896,3 +896,28 @@ u16 cfg80211_calculate_bitrate(struct rate_info *rate) /* do NOT round down here */ return (bitrate + 50000) / 100000; } + +int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, + u32 beacon_int) +{ + struct wireless_dev *wdev; + int res = 0; + + if (!beacon_int) + return -EINVAL; + + mutex_lock(&rdev->devlist_mtx); + + list_for_each_entry(wdev, &rdev->netdev_list, list) { + if (!wdev->beacon_interval) + continue; + if (wdev->beacon_interval != beacon_int) { + res = -EINVAL; + break; + } + } + + mutex_unlock(&rdev->devlist_mtx); + + return res; +} -- cgit v1.2.3-58-ga151 From 8fddddff0ad4ccc2787464207eba9ed3063e69cd Mon Sep 17 00:00:00 2001 From: Daniel Halperin Date: Tue, 10 May 2011 19:00:45 -0700 Subject: mac80211: fix contention time computation in minstrel, minstrel_ht When transmitting a frame, the transmitter waits a random number of slots between 0 and cw. Thus, the contention time is (cw / 2) * t_slot which we can represent instead as (cw * t_slot) >> 1. Also fix a few other accounting bugs around contention time, and add comments. Signed-off-by: Daniel Halperin Signed-off-by: John W. Linville --- net/mac80211/rc80211_minstrel.c | 4 ++-- net/mac80211/rc80211_minstrel_ht.c | 27 +++++++++++++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 778c604d7939..8adac67395f7 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -417,8 +417,8 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, tx_time_single = mr->ack_time + mr->perfect_tx_time; /* contention window */ - tx_time_single += t_slot + min(cw, mp->cw_max); - cw = (cw << 1) | 1; + tx_time_single += (t_slot * cw) >> 1; + cw = min((cw << 1) | 1, mp->cw_max); tx_time += tx_time_single; tx_time_cts += tx_time_single + mi->sp_ack_dur; diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index dbdebeda097f..3d09c58938e2 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -464,6 +464,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, const struct mcs_group *group; unsigned int tx_time, tx_time_rtscts, tx_time_data; unsigned int cw = mp->cw_min; + unsigned int ctime = 0; unsigned int t_slot = 9; /* FIXME */ unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len); @@ -480,13 +481,27 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len; - tx_time = 2 * (t_slot + mi->overhead + tx_time_data); - tx_time_rtscts = 2 * (t_slot + mi->overhead_rtscts + tx_time_data); + + /* Contention time for first 2 tries */ + ctime = (t_slot * cw) >> 1; + cw = min((cw << 1) | 1, mp->cw_max); + ctime += (t_slot * cw) >> 1; + cw = min((cw << 1) | 1, mp->cw_max); + + /* Total TX time for data and Contention after first 2 tries */ + tx_time = ctime + 2 * (mi->overhead + tx_time_data); + tx_time_rtscts = ctime + 2 * (mi->overhead_rtscts + tx_time_data); + + /* See how many more tries we can fit inside segment size */ do { - cw = (cw << 1) | 1; - cw = min(cw, mp->cw_max); - tx_time += cw + t_slot + mi->overhead; - tx_time_rtscts += cw + t_slot + mi->overhead_rtscts; + /* Contention time for this try */ + ctime = (t_slot * cw) >> 1; + cw = min((cw << 1) | 1, mp->cw_max); + + /* Total TX time after this try */ + tx_time += ctime + mi->overhead + tx_time_data; + tx_time_rtscts += ctime + mi->overhead_rtscts + tx_time_data; + if (tx_time_rtscts < mp->segment_size) mr->retry_count_rtscts++; } while ((tx_time < mp->segment_size) && -- cgit v1.2.3-58-ga151 From 9ba7f4f5eba5f4b44c7796bbad29f8ec3a7d5864 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 11 May 2011 14:57:26 -0700 Subject: ath9k_hw: fix dual band assumption for XB113 The XB113 cards are single band, 5 GHz-only, but the default settings were configured to assume it was dual band. Users of these cards then would see 2.4 GHz channels but you would never get any scan results from these channels given that the radio is not present. Cc: stable@kernel.org Cc: Fiona Cain Cc: Ray Li Cc: Kathy Giori Cc: Aeolus Yang Cc: Dan Friedman Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 070dc8b882b1..0647cc518d9f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -652,7 +652,7 @@ static const struct ar9300_eeprom ar9300_x113 = { .regDmn = { LE16(0), LE16(0x1f) }, .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ .opCapFlags = { - .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, + .opFlags = AR5416_OPFLAGS_11A, .eepMisc = 0, }, .rfSilent = 0, -- cgit v1.2.3-58-ga151 From f1a9c1e694f84938e6526590d23e88a791a8069f Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 12 May 2011 00:01:47 +0200 Subject: bcma: pci: trivial: correct amount of maximum retries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/bcma/driver_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index b98b8359bef5..e757e4e3c7e2 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c @@ -81,7 +81,7 @@ static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) pcicore_write32(pc, mdio_data, v); /* Wait for the device to complete the transaction */ udelay(10); - for (i = 0; i < 200; i++) { + for (i = 0; i < max_retries; i++) { v = pcicore_read32(pc, mdio_control); if (v & 0x100 /* Trans complete */) { udelay(10); -- cgit v1.2.3-58-ga151 From 406a39ec00992090cda034625e176504eb7a71f9 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 11 May 2011 19:47:11 -0700 Subject: mwifiex: remove mwifiex_recv_complete function The function - increments dropped rx_packet count if status code passed to it is "-1". - frees SKB buffer. But currently the function is being called with "0" status code. This patch replaces above function by dev_kfree_skb_any() call. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cmdevt.c | 6 +++--- drivers/net/wireless/mwifiex/main.h | 4 ---- drivers/net/wireless/mwifiex/util.c | 25 ------------------------- 3 files changed, 3 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 5c7539932c27..cd89fed206ae 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -91,7 +91,7 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, cmd_node->wait_q_enabled = false; if (cmd_node->resp_skb) { - mwifiex_recv_complete(adapter, cmd_node->resp_skb, 0); + dev_kfree_skb_any(cmd_node->resp_skb); cmd_node->resp_skb = NULL; } } @@ -339,7 +339,7 @@ int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter) } if (!cmd_array[i].resp_skb) continue; - mwifiex_recv_complete(adapter, cmd_array[i].resp_skb, 0); + dev_kfree_skb_any(cmd_array[i].resp_skb); } /* Release struct cmd_ctrl_node */ if (adapter->cmd_pool) { @@ -402,7 +402,7 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) adapter->event_cause = 0; adapter->event_skb = NULL; - mwifiex_recv_complete(adapter, skb, 0); + dev_kfree_skb_any(skb); return ret; } diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index b4bb5ec4723e..672701dc2721 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -692,10 +692,6 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter); int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); -int mwifiex_recv_complete(struct mwifiex_adapter *, - struct sk_buff *skb, - int status); - int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb); int mwifiex_process_event(struct mwifiex_adapter *adapter); diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index a8d53aa7e38d..d41291529bc0 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c @@ -176,31 +176,6 @@ int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) return 0; } -/* - * Receive packet completion callback handler. - * - * This function updates the statistics and frees the buffer SKB. - */ -int mwifiex_recv_complete(struct mwifiex_adapter *adapter, - struct sk_buff *skb, int status) -{ - struct mwifiex_private *priv; - struct mwifiex_rxinfo *rx_info; - - if (!skb) - return 0; - - rx_info = MWIFIEX_SKB_RXCB(skb); - priv = mwifiex_bss_index_to_priv(adapter, rx_info->bss_index); - - if (priv && (status == -1)) - priv->stats.rx_dropped++; - - dev_kfree_skb_any(skb); - - return 0; -} - /* * IOCTL completion callback handler. * -- cgit v1.2.3-58-ga151 From be0e6aa5a0c487a2a0880dda8bc70f7f1860fc39 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Thu, 12 May 2011 16:24:28 +0530 Subject: ath9k_hw: Fix STA connection issues with AR9380 (XB113). XB113 (AR9380) 3x3 SB 5G only cards were failing to connect to APs due to incorrect xpabiaslevel configuration. fix it. Cc: stable@kernel.org Cc: Ray Li Cc: Kathy Giori Cc: Aeolus Yang Cc: compat@orbit-lab.org Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 0647cc518d9f..6dfb69ae5b09 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -922,7 +922,7 @@ static const struct ar9300_eeprom ar9300_x113 = { .db_stage2 = {3, 3, 3}, /* 3 chain */ .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ - .xpaBiasLvl = 0, + .xpaBiasLvl = 0xf, .txFrameToDataStart = 0x0e, .txFrameToPaOn = 0x0e, .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ -- cgit v1.2.3-58-ga151 From dea4096bc41a9642039840ced91e585d04883a16 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 May 2011 15:03:32 +0200 Subject: mac80211: remove pointless mesh path timer RCU code The code here to RCU-dereference a pointer that's on the stack is totally pointless, RCU isn't magic (like say Java's weak references are), so the code can't work like whoever wrote it thought it might. Remove it so readers don't get confused. Note that it seems that a bug is there anyway: I don't see any code that cancels the timer when a mesh path struct is destroyed. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mesh_hwmp.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 849fecd0820e..2aec7c4f357b 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -966,20 +966,11 @@ endlookup: void mesh_path_timer(unsigned long data) { - struct ieee80211_sub_if_data *sdata; - struct mesh_path *mpath; - - rcu_read_lock(); - mpath = (struct mesh_path *) data; - mpath = rcu_dereference(mpath); - if (!mpath) - goto endmpathtimer; - sdata = mpath->sdata; + struct mesh_path *mpath = (void *) data; + struct ieee80211_sub_if_data *sdata = mpath->sdata; - if (sdata->local->quiescing) { - rcu_read_unlock(); + if (sdata->local->quiescing) return; - } spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_RESOLVED || @@ -996,8 +987,6 @@ void mesh_path_timer(unsigned long data) } spin_unlock_bh(&mpath->state_lock); -endmpathtimer: - rcu_read_unlock(); } void -- cgit v1.2.3-58-ga151 From 5c0c36412b2dc6b1e243c7e9115306fe286583b7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 May 2011 14:31:49 +0200 Subject: mac80211: make key locking clearer The code in ieee80211_del_key() doesn't acquire the key_mtx properly when it dereferences the keys. It turns out that isn't actually necessary since the key_mtx itself seems to be redundant since all key manipulations are done under the RTNL, but as long as we have the key_mtx we should use it the right way too. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 38 +++++++++++++++----------------------- net/mac80211/key.c | 8 ++++---- net/mac80211/key.h | 1 + 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index ed3400cd7a5a..94690366321c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -160,13 +160,14 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, bool pairwise, const u8 *mac_addr) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; + struct ieee80211_key *key = NULL; int ret; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - mutex_lock(&sdata->local->sta_mtx); + mutex_lock(&local->sta_mtx); + mutex_lock(&local->key_mtx); if (mac_addr) { ret = -ENOENT; @@ -175,33 +176,24 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, if (!sta) goto out_unlock; - if (pairwise) { - if (sta->ptk) { - ieee80211_key_free(sdata->local, sta->ptk); - ret = 0; - } - } else { - if (sta->gtk[key_idx]) { - ieee80211_key_free(sdata->local, - sta->gtk[key_idx]); - ret = 0; - } - } - - goto out_unlock; - } + if (pairwise) + key = sta->ptk; + else + key = sta->gtk[key_idx]; + } else + key = sdata->keys[key_idx]; - if (!sdata->keys[key_idx]) { + if (!key) { ret = -ENOENT; goto out_unlock; } - ieee80211_key_free(sdata->local, sdata->keys[key_idx]); - WARN_ON(sdata->keys[key_idx]); + __ieee80211_key_free(key); ret = 0; out_unlock: - mutex_unlock(&sdata->local->sta_mtx); + mutex_unlock(&local->key_mtx); + mutex_unlock(&local->sta_mtx); return ret; } diff --git a/net/mac80211/key.c b/net/mac80211/key.c index b510721e3b3d..958832dd4f0a 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -471,8 +471,11 @@ int ieee80211_key_link(struct ieee80211_key *key, return ret; } -static void __ieee80211_key_free(struct ieee80211_key *key) +void __ieee80211_key_free(struct ieee80211_key *key) { + if (!key) + return; + /* * Replace key with nothingness if it was ever used. */ @@ -486,9 +489,6 @@ static void __ieee80211_key_free(struct ieee80211_key *key) void ieee80211_key_free(struct ieee80211_local *local, struct ieee80211_key *key) { - if (!key) - return; - mutex_lock(&local->key_mtx); __ieee80211_key_free(key); mutex_unlock(&local->key_mtx); diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 4ddbe27eb570..e5432ef8b203 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -135,6 +135,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, int __must_check ieee80211_key_link(struct ieee80211_key *key, struct ieee80211_sub_if_data *sdata, struct sta_info *sta); +void __ieee80211_key_free(struct ieee80211_key *key); void ieee80211_key_free(struct ieee80211_local *local, struct ieee80211_key *key); void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, -- cgit v1.2.3-58-ga151 From 8cb231530f03961b55aa4e84e6ead5590bcde04d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 May 2011 15:07:15 +0200 Subject: mac80211: fix another key non-race The code here is only not racy because all the places that assign the pointers it uses are holding the sta_mtx as well as the key_mtx and so can't race against this because this code holds the sta_mtx. But that's not intuitive, so fix it to hold the key_mtx. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/sta_info.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f05244dc773e..cba8309e9ace 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -652,10 +652,12 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) if (ret) return ret; + mutex_lock(&local->key_mtx); for (i = 0; i < NUM_DEFAULT_KEYS; i++) - ieee80211_key_free(local, sta->gtk[i]); + __ieee80211_key_free(sta->gtk[i]); if (sta->ptk) - ieee80211_key_free(local, sta->ptk); + __ieee80211_key_free(sta->ptk); + mutex_unlock(&local->key_mtx); sta->dead = true; -- cgit v1.2.3-58-ga151 From a3836e02ba4c50db958d32d710b226f2408623dc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 May 2011 15:11:37 +0200 Subject: mac80211: fix a few RCU issues A few configuration functions correctly do rcu_read_lock() but don't correctly reference some pointers protected by RCU. Fix that. Cc: stable@kernel.org Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 94690366321c..303f33fcb844 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -223,11 +223,11 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, goto out; if (pairwise) - key = sta->ptk; + key = rcu_dereference(sta->ptk); else if (key_idx < NUM_DEFAULT_KEYS) - key = sta->gtk[key_idx]; + key = rcu_dereference(sta->gtk[key_idx]); } else - key = sdata->keys[key_idx]; + key = rcu_dereference(sdata->keys[key_idx]); if (!key) goto out; @@ -952,8 +952,10 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, struct mpath_info *pinfo) { - if (mpath->next_hop) - memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); + struct sta_info *next_hop_sta = rcu_dereference(mpath->next_hop); + + if (next_hop_sta) + memcpy(next_hop, next_hop_sta->sta.addr, ETH_ALEN); else memset(next_hop, 0, ETH_ALEN); -- cgit v1.2.3-58-ga151 From 85a9994a0a6cba1a6cc6af4bd3ebd85f778be0fe Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 12 May 2011 16:28:29 +0300 Subject: cfg80211/mac80211: avoid bounce back mac->cfg->mac on sched_scan_stopped When sched_scan_stopped was called by the driver, mac80211 calls cfg80211, which in turn was calling mac80211 back with a flag "driver_initiated". This flag was used so that mac80211 would do the necessary cleanup but would not call the driver. This was enough to prevent the bounce back between the driver and mac80211, but not between mac80211 and cfg80211. To fix this, we now do the cleanup in mac80211 before calling cfg80211. To help with locking issues, the workqueue was moved from cfg80211 to mac80211. Reported-by: Johannes Berg Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- include/net/cfg80211.h | 3 +-- net/mac80211/cfg.c | 5 ++--- net/mac80211/ieee80211_i.h | 5 +++-- net/mac80211/main.c | 3 +++ net/mac80211/scan.c | 33 +++++++++++++++++++++++++++------ net/wireless/core.c | 1 - net/wireless/core.h | 2 -- net/wireless/scan.c | 21 +++++++-------------- 8 files changed, 43 insertions(+), 30 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a46adb7a91b7..e1f1b41f7b13 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1515,8 +1515,7 @@ struct cfg80211_ops { int (*sched_scan_start)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_sched_scan_request *request); - int (*sched_scan_stop)(struct wiphy *wiphy, struct net_device *dev, - bool driver_initiated); + int (*sched_scan_stop)(struct wiphy *wiphy, struct net_device *dev); }; /* diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 303f33fcb844..2d1c1a5f3c51 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1372,15 +1372,14 @@ ieee80211_sched_scan_start(struct wiphy *wiphy, } static int -ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev, - bool driver_initiated) +ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (!sdata->local->ops->sched_scan_stop) return -EOPNOTSUPP; - return ieee80211_request_sched_scan_stop(sdata, driver_initiated); + return ieee80211_request_sched_scan_stop(sdata); } static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6f55a789c099..82f90ff8bb18 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -849,6 +849,7 @@ struct ieee80211_local { bool sched_scanning; struct ieee80211_sched_scan_ies sched_scan_ies; + struct work_struct sched_scan_stopped_work; unsigned long leave_oper_channel_time; enum mac80211_scan_state next_scan_state; @@ -1160,8 +1161,8 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local, /* scheduled scan handling */ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, struct cfg80211_sched_scan_request *req); -int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata, - bool driver_initiated); +int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); +void ieee80211_sched_scan_stopped_work(struct work_struct *work); /* off-channel helpers */ bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 30e6a682a047..7f89011fa22d 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -652,6 +652,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, setup_timer(&local->dynamic_ps_timer, ieee80211_dynamic_ps_timer, (unsigned long) local); + INIT_WORK(&local->sched_scan_stopped_work, + ieee80211_sched_scan_stopped_work); + sta_info_init(local); for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index ea44a8e941ec..d20046b5d8f4 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -902,8 +902,7 @@ out: return ret; } -int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata, - bool driver_initiated) +int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; int ret = 0, i; @@ -919,11 +918,9 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata, for (i = 0; i < IEEE80211_NUM_BANDS; i++) kfree(local->sched_scan_ies.ie[i]); - if (!driver_initiated) - drv_sched_scan_stop(local, sdata); + drv_sched_scan_stop(local, sdata); local->sched_scanning = false; } - out: mutex_unlock(&sdata->local->mtx); @@ -940,12 +937,36 @@ void ieee80211_sched_scan_results(struct ieee80211_hw *hw) } EXPORT_SYMBOL(ieee80211_sched_scan_results); +void ieee80211_sched_scan_stopped_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, + sched_scan_stopped_work); + int i; + + mutex_lock(&local->mtx); + + if (!local->sched_scanning) { + mutex_unlock(&local->mtx); + return; + } + + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + kfree(local->sched_scan_ies.ie[i]); + + local->sched_scanning = false; + + mutex_unlock(&local->mtx); + + cfg80211_sched_scan_stopped(local->hw.wiphy); +} + void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); trace_api_sched_scan_stopped(local); - cfg80211_sched_scan_stopped(hw->wiphy); + ieee80211_queue_work(&local->hw, &local->sched_scan_stopped_work); } EXPORT_SYMBOL(ieee80211_sched_scan_stopped); diff --git a/net/wireless/core.c b/net/wireless/core.c index e2ab65d7c86d..18b002f16860 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -371,7 +371,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) INIT_LIST_HEAD(&rdev->bss_list); INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); INIT_WORK(&rdev->sched_scan_results_wk, __cfg80211_sched_scan_results); - INIT_WORK(&rdev->sched_scan_stopped_wk, __cfg80211_sched_scan_stopped); #ifdef CONFIG_CFG80211_WEXT rdev->wiphy.wext = &cfg80211_wext_handler; #endif diff --git a/net/wireless/core.h b/net/wireless/core.h index fd9135f9b5be..d4b8f4c0bbbb 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -64,7 +64,6 @@ struct cfg80211_registered_device { unsigned long suspend_at; struct work_struct scan_done_wk; struct work_struct sched_scan_results_wk; - struct work_struct sched_scan_stopped_wk; #ifdef CONFIG_NL80211_TESTMODE struct genl_info *testmode_info; @@ -417,7 +416,6 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); void __cfg80211_sched_scan_results(struct work_struct *wk); int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, bool driver_initiated); -void __cfg80211_sched_scan_stopped(struct work_struct *wk); void cfg80211_upload_connect_keys(struct wireless_dev *wdev); int cfg80211_change_iface(struct cfg80211_registered_device *rdev, struct net_device *dev, enum nl80211_iftype ntype, diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 65dfae3b9d41..73a441d237b5 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -119,22 +119,14 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy) } EXPORT_SYMBOL(cfg80211_sched_scan_results); -void __cfg80211_sched_scan_stopped(struct work_struct *wk) +void cfg80211_sched_scan_stopped(struct wiphy *wiphy) { - struct cfg80211_registered_device *rdev; - - rdev = container_of(wk, struct cfg80211_registered_device, - sched_scan_stopped_wk); + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); cfg80211_lock_rdev(rdev); __cfg80211_stop_sched_scan(rdev, true); cfg80211_unlock_rdev(rdev); } - -void cfg80211_sched_scan_stopped(struct wiphy *wiphy) -{ - queue_work(cfg80211_wq, &wiphy_to_dev(wiphy)->sched_scan_stopped_wk); -} EXPORT_SYMBOL(cfg80211_sched_scan_stopped); int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, @@ -150,10 +142,11 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, dev = rdev->sched_scan_req->dev; - err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev, - driver_initiated); - if (err) - return err; + if (!driver_initiated) { + err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev); + if (err) + return err; + } nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED); -- cgit v1.2.3-58-ga151 From 6b86bd62a505a4a9739474f00f8088395b7a80ba Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 May 2011 13:38:50 +0200 Subject: mac80211: mesh: move some code to make it static There's no need to have table functions in one file and all users in another, move the functions to the right file and make them static. Also move a static variable to the beginning of the file to make it easier to find. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mesh.c | 43 -------------------------------- net/mac80211/mesh.h | 4 --- net/mac80211/mesh_pathtbl.c | 60 +++++++++++++++++++++++++++++++++++++++------ 3 files changed, 53 insertions(+), 54 deletions(-) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 75378e852f00..29e9980c8e60 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -287,49 +287,6 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) } } -u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) -{ - /* Use last four bytes of hw addr and interface index as hash index */ - return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) - & tbl->hash_mask; -} - -struct mesh_table *mesh_table_alloc(int size_order) -{ - int i; - struct mesh_table *newtbl; - - newtbl = kmalloc(sizeof(struct mesh_table), GFP_KERNEL); - if (!newtbl) - return NULL; - - newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) * - (1 << size_order), GFP_KERNEL); - - if (!newtbl->hash_buckets) { - kfree(newtbl); - return NULL; - } - - newtbl->hashwlock = kmalloc(sizeof(spinlock_t) * - (1 << size_order), GFP_KERNEL); - if (!newtbl->hashwlock) { - kfree(newtbl->hash_buckets); - kfree(newtbl); - return NULL; - } - - newtbl->size_order = size_order; - newtbl->hash_mask = (1 << size_order) - 1; - atomic_set(&newtbl->entries, 0); - get_random_bytes(&newtbl->hash_rnd, - sizeof(newtbl->hash_rnd)); - for (i = 0; i <= newtbl->hash_mask; i++) - spin_lock_init(&newtbl->hashwlock[i]); - - return newtbl; -} - static void ieee80211_mesh_path_timer(unsigned long data) { diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 10acf1cc8082..5c0c20389a1a 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -240,12 +240,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, /* Private interfaces */ /* Mesh tables */ -struct mesh_table *mesh_table_alloc(int size_order); -void mesh_table_free(struct mesh_table *tbl, bool free_leafs); void mesh_mpath_table_grow(void); void mesh_mpp_table_grow(void); -u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, - struct mesh_table *tbl); /* Mesh paths */ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, __le16 target_rcode, const u8 *ra, struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index c7cb3cc083df..0aa96cd6bd27 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -40,6 +40,50 @@ static struct mesh_table *mesh_paths; static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ int mesh_paths_generation; + +/* This lock will have the grow table function as writer and add / delete nodes + * as readers. When reading the table (i.e. doing lookups) we are well protected + * by RCU + */ +static DEFINE_RWLOCK(pathtbl_resize_lock); + + +static struct mesh_table *mesh_table_alloc(int size_order) +{ + int i; + struct mesh_table *newtbl; + + newtbl = kmalloc(sizeof(struct mesh_table), GFP_KERNEL); + if (!newtbl) + return NULL; + + newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) * + (1 << size_order), GFP_KERNEL); + + if (!newtbl->hash_buckets) { + kfree(newtbl); + return NULL; + } + + newtbl->hashwlock = kmalloc(sizeof(spinlock_t) * + (1 << size_order), GFP_KERNEL); + if (!newtbl->hashwlock) { + kfree(newtbl->hash_buckets); + kfree(newtbl); + return NULL; + } + + newtbl->size_order = size_order; + newtbl->hash_mask = (1 << size_order) - 1; + atomic_set(&newtbl->entries, 0); + get_random_bytes(&newtbl->hash_rnd, + sizeof(newtbl->hash_rnd)); + for (i = 0; i <= newtbl->hash_mask; i++) + spin_lock_init(&newtbl->hashwlock[i]); + + return newtbl; +} + static void __mesh_table_free(struct mesh_table *tbl) { kfree(tbl->hash_buckets); @@ -47,7 +91,7 @@ static void __mesh_table_free(struct mesh_table *tbl) kfree(tbl); } -void mesh_table_free(struct mesh_table *tbl, bool free_leafs) +static void mesh_table_free(struct mesh_table *tbl, bool free_leafs) { struct hlist_head *mesh_hash; struct hlist_node *p, *q; @@ -66,7 +110,7 @@ void mesh_table_free(struct mesh_table *tbl, bool free_leafs) } static int mesh_table_grow(struct mesh_table *oldtbl, - struct mesh_table *newtbl) + struct mesh_table *newtbl) { struct hlist_head *oldhash; struct hlist_node *p, *q; @@ -97,12 +141,14 @@ errcopy: return -ENOMEM; } +static u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, + struct mesh_table *tbl) +{ + /* Use last four bytes of hw addr and interface index as hash index */ + return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) + & tbl->hash_mask; +} -/* This lock will have the grow table function as writer and add / delete nodes - * as readers. When reading the table (i.e. doing lookups) we are well protected - * by RCU - */ -static DEFINE_RWLOCK(pathtbl_resize_lock); /** * -- cgit v1.2.3-58-ga151 From 889cb360b4f48c1334311093161f06f7b4bd77d2 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 1 May 2011 09:56:45 +0300 Subject: wl12xx: simplify wl1271_ssid_set() Simplify wl1271_ssid_set by re-using cfg80211_find_ie instead of reimplementing it. Additionally, add a length check to prevent a potential buffer overflow. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 6dab6f0c91bc..f82e736ba197 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2376,20 +2376,24 @@ out: static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, int offset) { - u8 *ptr = skb->data + offset; + u8 ssid_len; + const u8 *ptr = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset, + skb->len - offset); - /* find the location of the ssid in the beacon */ - while (ptr < skb->data + skb->len) { - if (ptr[0] == WLAN_EID_SSID) { - wl->ssid_len = ptr[1]; - memcpy(wl->ssid, ptr+2, wl->ssid_len); - return 0; - } - ptr += (ptr[1] + 2); + if (!ptr) { + wl1271_error("No SSID in IEs!"); + return -ENOENT; } - wl1271_error("No SSID in IEs!\n"); - return -ENOENT; + ssid_len = ptr[1]; + if (ssid_len > IEEE80211_MAX_SSID_LEN) { + wl1271_error("SSID is too long!"); + return -EINVAL; + } + + wl->ssid_len = ssid_len; + memcpy(wl->ssid, ptr+2, ssid_len); + return 0; } static int wl1271_bss_erp_info_changed(struct wl1271 *wl, -- cgit v1.2.3-58-ga151 From bc76b94051983b94c8ba04fbfbc59651b9925fa7 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Wed, 11 May 2011 11:14:22 +0300 Subject: wl12xx: Don't filter beacons that include changed HT IEs This patch adds a beacon filter rule to pass up the beacons that contain changed HT information elements. These beacons need to be passed to mac80211 so that it can act on such changes. [Reworded commit log -- Luca.] Signed-off-by: Shahar Levi Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index f82e736ba197..fa6b996d7d4d 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -257,12 +257,16 @@ static struct conf_drv_settings default_conf = { .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, .listen_interval = 1, .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, - .bcn_filt_ie_count = 1, + .bcn_filt_ie_count = 2, .bcn_filt_ie = { [0] = { .ie = WLAN_EID_CHANNEL_SWITCH, .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, - } + }, + [1] = { + .ie = WLAN_EID_HT_INFORMATION, + .rule = CONF_BCN_RULE_PASS_ON_CHANGE, + }, }, .synch_fail_thold = 10, .bss_lose_timeout = 100, -- cgit v1.2.3-58-ga151 From fcd23b6305e98f5ad3ddd7ff3f5081c75fcd4367 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Wed, 11 May 2011 12:12:56 +0300 Subject: wl12xx: add IEEE80211_HW_SPECTRUM_MGMT bit to the hw flags Set the spectrum management bit in the hw flags so that mac80211 will set the WLAN_CAPABILITY_SPECTRUM_MGMT bit in association requests (which in practice means that we support 802.11h spectrum management). [Reworded the commit log -- Luca.] Signed-off-by: Shahar Levi Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index fa6b996d7d4d..acfbbfd3b7dd 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3634,6 +3634,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) IEEE80211_HW_CONNECTION_MONITOR | IEEE80211_HW_SUPPORTS_CQM_RSSI | IEEE80211_HW_REPORTS_TX_ACK_STATUS | + IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_AP_LINK_PS; wl->hw->wiphy->cipher_suites = cipher_suites; -- cgit v1.2.3-58-ga151 From 3a9d60e5bd72f9533b05d39278fec50b181dbdd2 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Tue, 10 May 2011 14:06:31 +0300 Subject: wl12xx: add configuration values for scheduled scan Add the structures and values for driver-configured scheduled scan parameters. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/conf.h | 21 +++++++++++++++++++++ drivers/net/wireless/wl12xx/main.c | 9 +++++++++ 2 files changed, 30 insertions(+) diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 1f947368f9ee..ba558fcc76d0 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -1147,6 +1147,26 @@ struct conf_scan_settings { }; +struct conf_sched_scan_settings { + /* minimum time to wait on the channel for active scans (in TUs) */ + u16 min_dwell_time_active; + + /* maximum time to wait on the channel for active scans (in TUs) */ + u16 max_dwell_time_active; + + /* time to wait on the channel for passive scans (in TUs) */ + u32 dwell_time_passive; + + /* number of probe requests to send on each channel in active scans */ + u8 num_probe_reqs; + + /* RSSI threshold to be used for filtering */ + s8 rssi_threshold; + + /* SNR threshold to be used for filtering */ + s8 snr_threshold; +}; + /* these are number of channels on the band divided by two, rounded up */ #define CONF_TX_PWR_COMPENSATION_LEN_2 7 #define CONF_TX_PWR_COMPENSATION_LEN_5 18 @@ -1234,6 +1254,7 @@ struct conf_drv_settings { struct conf_pm_config_settings pm_config; struct conf_roam_trigger_settings roam_trigger; struct conf_scan_settings scan; + struct conf_sched_scan_settings sched_scan; struct conf_rf_settings rf; struct conf_ht_setting ht; struct conf_memory_settings mem_wl127x; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index acfbbfd3b7dd..88d2e9052a0d 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -306,6 +306,15 @@ static struct conf_drv_settings default_conf = { .max_dwell_time_passive = 100000, .num_probe_reqs = 2, }, + .sched_scan = { + /* sched_scan requires dwell times in TU instead of TU/1000 */ + .min_dwell_time_active = 8, + .max_dwell_time_active = 30, + .dwell_time_passive = 100, + .num_probe_reqs = 2, + .rssi_threshold = -90, + .snr_threshold = 0, + }, .rf = { .tx_per_channel_power_compensation_2 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -- cgit v1.2.3-58-ga151 From 6394c01b61f8ab66a6af1a24ff05f2429130afcd Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Tue, 10 May 2011 14:28:27 +0300 Subject: wl12xx: listen to scheduled scan events Subscribe and listen to PERIODIC_SCAN_REPORT_EVENT_ID and PERIODIC_SCAN_COMPLETE_EVENT_ID in preparation for the scheduled scan implementation. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/boot.c | 4 +++- drivers/net/wireless/wl12xx/event.c | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 2b0cf85788b3..b07f8b7e5f11 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -478,7 +478,9 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) DISCONNECT_EVENT_COMPLETE_ID | RSSI_SNR_TRIGGER_0_EVENT_ID | PSPOLL_DELIVERY_FAILURE_EVENT_ID | - SOFT_GEMINI_SENSE_EVENT_ID; + SOFT_GEMINI_SENSE_EVENT_ID | + PERIODIC_SCAN_REPORT_EVENT_ID | + PERIODIC_SCAN_COMPLETE_EVENT_ID; if (wl->bss_type == BSS_TYPE_AP_BSS) wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index ae69330e807c..dc110e8a618e 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -188,6 +188,16 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) wl1271_scan_stm(wl); } + if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { + wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_REPORT_EVENT " + "(status 0x%0x)", mbox->scheduled_scan_status); + } + + if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID) { + wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT " + "(status 0x%0x)", mbox->scheduled_scan_status); + } + /* disable dynamic PS when requested by the firmware */ if (vector & SOFT_GEMINI_SENSE_EVENT_ID && wl->bss_type == BSS_TYPE_STA_BSS) { -- cgit v1.2.3-58-ga151 From 95feadca6dca909ae0f6e65665b782c7ca9d5122 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Tue, 10 May 2011 14:38:59 +0300 Subject: wl12xx: add scheduled scan structures and commands Add firmware command structures, definitions and code to to configure, start and stop scheduled scans. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/scan.c | 233 +++++++++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/scan.h | 114 ++++++++++++++++++ 2 files changed, 347 insertions(+) diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 5d0544c8f3f5..d78044f00810 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -320,3 +320,236 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, return 0; } + +static int +wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, + struct cfg80211_sched_scan_request *req, + struct conn_scan_ch_params *channels, + u32 band, bool radar, bool passive, + int start) +{ + struct conf_sched_scan_settings *c = &wl->conf.sched_scan; + int i, j; + u32 flags; + + for (i = 0, j = start; + i < req->n_channels && j < MAX_CHANNELS_ALL_BANDS; + i++) { + flags = req->channels[i]->flags; + + if (!(flags & IEEE80211_CHAN_DISABLED) && + ((flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive) && + ((flags & IEEE80211_CHAN_RADAR) == radar) && + (req->channels[i]->band == band)) { + wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", + req->channels[i]->band, + req->channels[i]->center_freq); + wl1271_debug(DEBUG_SCAN, "hw_value %d, flags %X", + req->channels[i]->hw_value, + req->channels[i]->flags); + wl1271_debug(DEBUG_SCAN, "max_power %d", + req->channels[i]->max_power); + + if (flags & IEEE80211_CHAN_PASSIVE_SCAN) { + channels[j].passive_duration = + cpu_to_le16(c->dwell_time_passive); + } else { + channels[j].min_duration = + cpu_to_le16(c->min_dwell_time_active); + channels[j].max_duration = + cpu_to_le16(c->max_dwell_time_active); + } + channels[j].tx_power_att = req->channels[j]->max_power; + channels[j].channel = req->channels[i]->hw_value; + + j++; + } + } + + return j - start; +} + +static int +wl1271_scan_sched_scan_channels(struct wl1271 *wl, + struct cfg80211_sched_scan_request *req, + struct wl1271_cmd_sched_scan_config *cfg) +{ + int idx = 0; + + cfg->passive[0] = + wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, + IEEE80211_BAND_2GHZ, + false, true, idx); + idx += cfg->passive[0]; + + cfg->active[0] = + wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, + IEEE80211_BAND_2GHZ, + false, false, idx); + idx += cfg->active[0]; + + cfg->passive[1] = + wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, + IEEE80211_BAND_5GHZ, + false, true, idx); + idx += cfg->passive[1]; + + cfg->active[1] = + wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, + IEEE80211_BAND_5GHZ, + false, false, 14); + idx += cfg->active[1]; + + cfg->dfs = + wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, + IEEE80211_BAND_5GHZ, + true, false, idx); + idx += cfg->dfs; + + wl1271_debug(DEBUG_SCAN, " 2.4GHz: active %d passive %d", + cfg->active[0], cfg->passive[0]); + wl1271_debug(DEBUG_SCAN, " 5GHz: active %d passive %d", + cfg->active[1], cfg->passive[1]); + + return idx; +} + +int wl1271_scan_sched_scan_config(struct wl1271 *wl, + struct cfg80211_sched_scan_request *req, + struct ieee80211_sched_scan_ies *ies) +{ + struct wl1271_cmd_sched_scan_config *cfg = NULL; + struct conf_sched_scan_settings *c = &wl->conf.sched_scan; + int i, total_channels, ret; + + wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config"); + + cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); + if (!cfg) + return -ENOMEM; + + cfg->rssi_threshold = c->rssi_threshold; + cfg->snr_threshold = c->snr_threshold; + cfg->n_probe_reqs = c->num_probe_reqs; + /* cycles set to 0 it means infinite (until manually stopped) */ + cfg->cycles = 0; + /* report APs when at least 1 is found */ + cfg->report_after = 1; + /* don't stop scanning automatically when something is found */ + cfg->terminate = 0; + cfg->tag = WL1271_SCAN_DEFAULT_TAG; + /* don't filter on BSS type */ + cfg->bss_type = SCAN_BSS_TYPE_ANY; + /* currently NL80211 supports only a single interval */ + for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++) + cfg->intervals[i] = cpu_to_le32(req->interval); + + if (req->ssids[0].ssid_len && req->ssids[0].ssid) { + cfg->filter_type = SCAN_SSID_FILTER_SPECIFIC; + cfg->ssid_len = req->ssids[0].ssid_len; + memcpy(cfg->ssid, req->ssids[0].ssid, + req->ssids[0].ssid_len); + } else { + cfg->filter_type = SCAN_SSID_FILTER_ANY; + cfg->ssid_len = 0; + } + + total_channels = wl1271_scan_sched_scan_channels(wl, req, cfg); + if (total_channels == 0) { + wl1271_error("scan channel list is empty"); + ret = -EINVAL; + goto out; + } + + if (cfg->active[0]) { + ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, + req->ssids[0].ssid_len, + ies->ie[IEEE80211_BAND_2GHZ], + ies->len[IEEE80211_BAND_2GHZ], + IEEE80211_BAND_2GHZ); + if (ret < 0) { + wl1271_error("2.4GHz PROBE request template failed"); + goto out; + } + } + + if (cfg->active[1]) { + ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, + req->ssids[0].ssid_len, + ies->ie[IEEE80211_BAND_5GHZ], + ies->len[IEEE80211_BAND_5GHZ], + IEEE80211_BAND_5GHZ); + if (ret < 0) { + wl1271_error("5GHz PROBE request template failed"); + goto out; + } + } + + wl1271_dump(DEBUG_SCAN, "SCAN_CFG: ", cfg, sizeof(*cfg)); + + ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_CFG, cfg, + sizeof(*cfg), 0); + if (ret < 0) { + wl1271_error("SCAN configuration failed"); + goto out; + } +out: + kfree(cfg); + return ret; +} + +int wl1271_scan_sched_scan_start(struct wl1271 *wl) +{ + struct wl1271_cmd_sched_scan_start *start; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd periodic scan start"); + + start = kzalloc(sizeof(*start), GFP_KERNEL); + if (!start) + return -ENOMEM; + + start->tag = WL1271_SCAN_DEFAULT_TAG; + + ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start, + sizeof(*start), 0); + if (ret < 0) { + wl1271_error("failed to send scan start command"); + goto out_free; + } + +out_free: + kfree(start); + return ret; +} + +void wl1271_scan_sched_scan_results(struct wl1271 *wl) +{ + wl1271_debug(DEBUG_SCAN, "got periodic scan results"); + + ieee80211_sched_scan_results(wl->hw); +} + +void wl1271_scan_sched_scan_stop(struct wl1271 *wl) +{ + struct wl1271_cmd_sched_scan_stop *stop; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd periodic scan stop"); + + /* FIXME: what to do if alloc'ing to stop fails? */ + stop = kzalloc(sizeof(*stop), GFP_KERNEL); + if (!stop) { + wl1271_error("failed to alloc memory to send sched scan stop"); + return; + } + + stop->tag = WL1271_SCAN_DEFAULT_TAG; + + ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, + sizeof(*stop), 0); + if (ret < 0) + wl1271_error("failed to send sched scan stop command"); + + kfree(stop); +} diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h index 421a750add5a..c83319579ca3 100644 --- a/drivers/net/wireless/wl12xx/scan.h +++ b/drivers/net/wireless/wl12xx/scan.h @@ -33,6 +33,12 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl, const u8 *ie, size_t ie_len, u8 band); void wl1271_scan_stm(struct wl1271 *wl); void wl1271_scan_complete_work(struct work_struct *work); +int wl1271_scan_sched_scan_config(struct wl1271 *wl, + struct cfg80211_sched_scan_request *req, + struct ieee80211_sched_scan_ies *ies); +int wl1271_scan_sched_scan_start(struct wl1271 *wl); +void wl1271_scan_sched_scan_stop(struct wl1271 *wl); +void wl1271_scan_sched_scan_results(struct wl1271 *wl); #define WL1271_SCAN_MAX_CHANNELS 24 #define WL1271_SCAN_DEFAULT_TAG 1 @@ -106,4 +112,112 @@ struct wl1271_cmd_trigger_scan_to { __le32 timeout; } __packed; +#define MAX_CHANNELS_ALL_BANDS 41 +#define SCAN_MAX_CYCLE_INTERVALS 16 +#define SCAN_MAX_BANDS 3 + +enum { + SCAN_CHANNEL_TYPE_2GHZ_PASSIVE, + SCAN_CHANNEL_TYPE_2GHZ_ACTIVE, + SCAN_CHANNEL_TYPE_5GHZ_PASSIVE, + SCAN_CHANNEL_TYPE_5GHZ_ACTIVE, + SCAN_CHANNEL_TYPE_5GHZ_DFS, +}; + +enum { + SCAN_SSID_FILTER_ANY = 0, + SCAN_SSID_FILTER_SPECIFIC = 1, + SCAN_SSID_FILTER_LIST = 2, + SCAN_SSID_FILTER_DISABLED = 3 +}; + +enum { + SCAN_BSS_TYPE_INDEPENDENT, + SCAN_BSS_TYPE_INFRASTRUCTURE, + SCAN_BSS_TYPE_ANY, +}; + +struct conn_scan_ch_params { + __le16 min_duration; + __le16 max_duration; + __le16 passive_duration; + + u8 channel; + u8 tx_power_att; + + /* bit 0: DFS channel; bit 1: DFS enabled */ + u8 flags; + + u8 padding[3]; +} __packed; + +struct wl1271_cmd_sched_scan_config { + struct wl1271_cmd_header header; + + __le32 intervals[SCAN_MAX_CYCLE_INTERVALS]; + + s8 rssi_threshold; /* for filtering (in dBm) */ + s8 snr_threshold; /* for filtering (in dB) */ + + u8 cycles; /* maximum number of scan cycles */ + u8 report_after; /* report when this number of results are received */ + u8 terminate; /* stop scanning after reporting */ + + u8 tag; + u8 bss_type; /* for filtering */ + u8 filter_type; + + u8 ssid_len; /* For SCAN_SSID_FILTER_SPECIFIC */ + u8 ssid[IW_ESSID_MAX_SIZE]; + + u8 n_probe_reqs; /* Number of probes requests per channel */ + + u8 passive[SCAN_MAX_BANDS]; + u8 active[SCAN_MAX_BANDS]; + + u8 dfs; + + u8 padding[3]; + + struct conn_scan_ch_params channels[MAX_CHANNELS_ALL_BANDS]; +} __packed; + + +#define SCHED_SCAN_MAX_SSIDS 8 + +enum { + SCAN_SSID_TYPE_PUBLIC = 0, + SCAN_SSID_TYPE_HIDDEN = 1, +}; + +struct wl1271_ssid { + u8 type; + u8 len; + u8 ssid[IW_ESSID_MAX_SIZE]; + /* u8 padding[2]; */ +} __packed; + +struct wl1271_cmd_sched_scan_ssid_list { + struct wl1271_cmd_header header; + + u8 n_ssids; + struct wl1271_ssid ssids[SCHED_SCAN_MAX_SSIDS]; + u8 padding[3]; +} __packed; + +struct wl1271_cmd_sched_scan_start { + struct wl1271_cmd_header header; + + u8 tag; + u8 padding[3]; +} __packed; + +struct wl1271_cmd_sched_scan_stop { + struct wl1271_cmd_header header; + + u8 tag; + u8 padding[3]; +} __packed; + + #endif /* __WL1271_SCAN_H__ */ -- cgit v1.2.3-58-ga151 From 33c2c06cd2d766387cf919d0afd432cc5796c369 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Tue, 10 May 2011 14:46:02 +0300 Subject: wl12xx: implement scheduled scan driver operations and reporting This patch adds the mac80211 operations for scheduled scan and the scheduled scan results reporting. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/event.c | 6 ++++ drivers/net/wireless/wl12xx/main.c | 70 ++++++++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/scan.c | 6 +++- drivers/net/wireless/wl12xx/wl12xx.h | 2 ++ 4 files changed, 83 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index dc110e8a618e..1e4bd6a2c396 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -191,11 +191,17 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_REPORT_EVENT " "(status 0x%0x)", mbox->scheduled_scan_status); + + wl1271_scan_sched_scan_results(wl); } if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT " "(status 0x%0x)", mbox->scheduled_scan_status); + if (wl->sched_scanning) { + wl1271_scan_sched_scan_stop(wl); + ieee80211_sched_scan_stopped(wl->hw); + } } /* disable dynamic PS when requested by the firmware */ diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 88d2e9052a0d..a14a035aa440 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -988,6 +988,11 @@ static void wl1271_recovery_work(struct work_struct *work) /* Prevent spurious TX during FW restart */ ieee80211_stop_queues(wl->hw); + if (wl->sched_scanning) { + ieee80211_sched_scan_stopped(wl->hw); + wl->sched_scanning = false; + } + /* reboot the chipset */ __wl1271_op_remove_interface(wl, false); ieee80211_restart_hw(wl->hw); @@ -1576,6 +1581,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); wl->ap_fw_ps_map = 0; wl->ap_ps_map = 0; + wl->sched_scanning = false; /* * this is performed after the cancel_work calls and the associated @@ -1778,6 +1784,13 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) wl->session_counter++; if (wl->session_counter >= SESSION_COUNTER_MAX) wl->session_counter = 0; + + /* The current firmware only supports sched_scan in idle */ + if (wl->sched_scanning) { + wl1271_scan_sched_scan_stop(wl); + ieee80211_sched_scan_stopped(wl->hw); + } + ret = wl1271_dummy_join(wl); if (ret < 0) goto out; @@ -2330,6 +2343,60 @@ out: return ret; } +static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_sched_scan_request *req, + struct ieee80211_sched_scan_ies *ies) +{ + struct wl1271 *wl = hw->priv; + int ret; + + wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_start"); + + mutex_lock(&wl->mutex); + + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + + ret = wl1271_scan_sched_scan_config(wl, req, ies); + if (ret < 0) + goto out_sleep; + + ret = wl1271_scan_sched_scan_start(wl); + if (ret < 0) + goto out_sleep; + + wl->sched_scanning = true; + +out_sleep: + wl1271_ps_elp_sleep(wl); +out: + mutex_unlock(&wl->mutex); + return ret; +} + +static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct wl1271 *wl = hw->priv; + int ret; + + wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_stop"); + + mutex_lock(&wl->mutex); + + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + + wl1271_scan_sched_scan_stop(wl); + + wl1271_ps_elp_sleep(wl); +out: + mutex_unlock(&wl->mutex); +} + static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) { struct wl1271 *wl = hw->priv; @@ -3445,6 +3512,8 @@ static const struct ieee80211_ops wl1271_ops = { .tx = wl1271_op_tx, .set_key = wl1271_op_set_key, .hw_scan = wl1271_op_hw_scan, + .sched_scan_start = wl1271_op_sched_scan_start, + .sched_scan_stop = wl1271_op_sched_scan_stop, .bss_info_changed = wl1271_op_bss_info_changed, .set_frag_threshold = wl1271_op_set_frag_threshold, .set_rts_threshold = wl1271_op_set_rts_threshold, @@ -3765,6 +3834,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->ap_fw_ps_map = 0; wl->quirks = 0; wl->platform_quirks = 0; + wl->sched_scanning = false; memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); for (i = 0; i < ACX_TX_DESCRIPTORS; i++) diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index d78044f00810..668ff46a6824 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -548,8 +548,12 @@ void wl1271_scan_sched_scan_stop(struct wl1271 *wl) ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, sizeof(*stop), 0); - if (ret < 0) + if (ret < 0) { wl1271_error("failed to send sched scan stop command"); + goto out_free; + } + wl->sched_scanning = false; +out_free: kfree(stop); } diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index b7601438ecac..10f076770fed 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -480,6 +480,8 @@ struct wl1271 { struct wl1271_scan scan; struct delayed_work scan_complete_work; + bool sched_scanning; + /* probe-req template for the current AP */ struct sk_buff *probereq; -- cgit v1.2.3-58-ga151 From d3eff81de6048d8af8f95f52f0f06625980f2efb Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Tue, 10 May 2011 14:47:45 +0300 Subject: wl12xx: export scheduled scan state in debugfs Add the sched_scanning value to the driver_status debugfs entry. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index b2f692babed7..f1f8df9b6cd7 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -377,6 +377,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_HEX(platform_quirks); DRIVER_STATE_PRINT_HEX(chip.id); DRIVER_STATE_PRINT_STR(chip.fw_ver_str); + DRIVER_STATE_PRINT_INT(sched_scanning); #undef DRIVER_STATE_PRINT_INT #undef DRIVER_STATE_PRINT_LONG -- cgit v1.2.3-58-ga151 From 683c002447c12742f5151691083f68524f33b13a Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 12 May 2011 17:07:55 +0300 Subject: wl12xx: prevent sched_scan when not idle or not in station mode The current firmware only supports scheduled scan in station mode and when idle. To prevent the firmware from crashing, return -EOPNOTSUPP when sched_scan start is called in an invalid state. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/scan.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 668ff46a6824..f37e5a391976 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -505,6 +505,12 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl) wl1271_debug(DEBUG_CMD, "cmd periodic scan start"); + if (wl->bss_type != BSS_TYPE_STA_BSS) + return -EOPNOTSUPP; + + if (!test_bit(WL1271_FLAG_IDLE, &wl->flags)) + return -EBUSY; + start = kzalloc(sizeof(*start), GFP_KERNEL); if (!start) return -ENOMEM; -- cgit v1.2.3-58-ga151 From fe44870bcdf614e4abb35657c68081cda35ba741 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 12 May 2011 16:50:41 +0300 Subject: wl12xx: remove unused flag WL1271_FLAG_IDLE_REQUESTED This flag is not used anymore, remove it from the list. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/wl12xx.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 10f076770fed..ab0c2f155b8c 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -351,7 +351,6 @@ enum wl12xx_flags { WL1271_FLAG_PSM_REQUESTED, WL1271_FLAG_IRQ_RUNNING, WL1271_FLAG_IDLE, - WL1271_FLAG_IDLE_REQUESTED, WL1271_FLAG_PSPOLL_FAILURE, WL1271_FLAG_STA_STATE_SENT, WL1271_FLAG_FW_TX_BUSY, -- cgit v1.2.3-58-ga151 From 1769192a3c50778e03352a3d95faec830d47ba55 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 11 May 2011 18:22:36 +0000 Subject: l2tp: fix potential rcu race While trying to remove useless synchronize_rcu() calls, I found l2tp is indeed incorrectly using two of such calls, but also bumps tunnel refcount after list insertion. tunnel refcount must be incremented before being made publically visible by rcu readers. This fix can be applied to 2.6.35+ and might need a backport for older kernels, since things were shuffled in commit fd558d186df2c (l2tp: Split pppol2tp patch into separate l2tp and ppp parts) Signed-off-by: Eric Dumazet CC: Paul E. McKenney CC: James Chapman Reviewed-by: Paul E. McKenney Signed-off-by: David S. Miller --- net/l2tp/l2tp_core.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 9be095e00450..ed8a2335442f 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1435,16 +1435,15 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 /* Add tunnel to our list */ INIT_LIST_HEAD(&tunnel->list); - spin_lock_bh(&pn->l2tp_tunnel_list_lock); - list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); - spin_unlock_bh(&pn->l2tp_tunnel_list_lock); - synchronize_rcu(); atomic_inc(&l2tp_tunnel_count); /* Bump the reference count. The tunnel context is deleted - * only when this drops to zero. + * only when this drops to zero. Must be done before list insertion */ l2tp_tunnel_inc_refcount(tunnel); + spin_lock_bh(&pn->l2tp_tunnel_list_lock); + list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); + spin_unlock_bh(&pn->l2tp_tunnel_list_lock); err = 0; err: @@ -1636,7 +1635,6 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn hlist_add_head_rcu(&session->global_hlist, l2tp_session_id_hash_2(pn, session_id)); spin_unlock_bh(&pn->l2tp_session_hlist_lock); - synchronize_rcu(); } /* Ignore management session in session count value */ -- cgit v1.2.3-58-ga151 From 517aa0bcda9b092a4c3fab7bf93f0cebe372ece0 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 12 May 2011 11:27:20 +0000 Subject: sctp: sctp_sendmsg: Don't initialize default_sinfo This variable only needs initialization when cmsgs.info is NULL. Use memset to ensure padding is also zeroed so kernel doesn't leak any data. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/sctp/socket.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 33d9ee629b4e..d4b8db177e27 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1496,7 +1496,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, struct sctp_chunk *chunk; union sctp_addr to; struct sockaddr *msg_name = NULL; - struct sctp_sndrcvinfo default_sinfo = { 0 }; + struct sctp_sndrcvinfo default_sinfo; struct sctp_sndrcvinfo *sinfo; struct sctp_initmsg *sinit; sctp_assoc_t associd = 0; @@ -1760,6 +1760,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, /* If the user didn't specify SNDRCVINFO, make up one with * some defaults. */ + memset(&default_sinfo, 0, sizeof(default_sinfo)); default_sinfo.sinfo_stream = asoc->default_stream; default_sinfo.sinfo_flags = asoc->default_flags; default_sinfo.sinfo_ppid = asoc->default_ppid; -- cgit v1.2.3-58-ga151 From afd7614c00e364f8f1327e73ad291b02f6d4d1a6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 12 May 2011 09:19:10 +0000 Subject: sctp: sctp_sendmsg: Don't test known non-null sinfo It's already known non-null above. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/sctp/socket.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index d4b8db177e27..6766913a53e6 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1791,12 +1791,10 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, goto out_free; } - if (sinfo) { - /* Check for invalid stream. */ - if (sinfo->sinfo_stream >= asoc->c.sinit_num_ostreams) { - err = -EINVAL; - goto out_free; - } + /* Check for invalid stream. */ + if (sinfo->sinfo_stream >= asoc->c.sinit_num_ostreams) { + err = -EINVAL; + goto out_free; } timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); -- cgit v1.2.3-58-ga151 From e154b639bbe53dc91d1873cd37d162bb2fe87aab Mon Sep 17 00:00:00 2001 From: Shreyas Bhatewara Date: Tue, 10 May 2011 06:13:56 +0000 Subject: vmxnet3: Use single tx queue when CONFIG_PCI_MSI not defined Resending this patch with few changes. Avoid multiple queues when MSI or MSI-X not available Limit number of Tx queues to 1 if MSI/MSI-X support is not configured in the kernel. This will make number of tx and rx queues equal when MSI/X is not configured thus providing better performance. Signed-off-by: Bhavesh Davda Signed-off-by: Shreyas N Bhatewara Signed-off-by: David S. Miller --- drivers/net/vmxnet3/vmxnet3_drv.c | 3 +++ drivers/net/vmxnet3/vmxnet3_int.h | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index c0da23096160..fa6e2ac7475a 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -2884,6 +2884,9 @@ vmxnet3_probe_device(struct pci_dev *pdev, int num_tx_queues; int num_rx_queues; + if (!pci_msi_enabled()) + enable_mq = 0; + #ifdef VMXNET3_RSS if (enable_mq) num_rx_queues = min(VMXNET3_DEVICE_MAX_RX_QUEUES, diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index 8ba7b5f67de2..f50d36fdf405 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -68,10 +68,10 @@ /* * Version numbers */ -#define VMXNET3_DRIVER_VERSION_STRING "1.0.25.0-k" +#define VMXNET3_DRIVER_VERSION_STRING "1.1.9.0-k" /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ -#define VMXNET3_DRIVER_VERSION_NUM 0x01001900 +#define VMXNET3_DRIVER_VERSION_NUM 0x01010900 #if defined(CONFIG_PCI_MSI) /* RSS only makes sense if MSI-X is supported. */ -- cgit v1.2.3-58-ga151 From f607a158004d75c9005423ce1ba70dc6ec3dd9c2 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 12 May 2011 17:46:56 -0400 Subject: garp: remove last synchronize_rcu() call When removing last vlan from a device, garp_uninit_applicant() calls synchronize_rcu() to make sure no user can still manipulate struct garp_applicant before we free it. Use call_rcu() instead, as a step to further net_device dismantle optimizations. Add the temporary garp_cleanup_module() function to make sure no pending call_rcu() are left at module unload time [ this will be removed when kfree_rcu() is available ] Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/garp.h | 1 + net/802/garp.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/net/garp.h b/include/net/garp.h index 8cabbf087169..834d8add9e5f 100644 --- a/include/net/garp.h +++ b/include/net/garp.h @@ -104,6 +104,7 @@ struct garp_applicant { struct sk_buff_head queue; struct sk_buff *pdu; struct rb_root gid; + struct rcu_head rcu; }; struct garp_port { diff --git a/net/802/garp.c b/net/802/garp.c index 5dbe8967bbd5..f8300a8b5fbc 100644 --- a/net/802/garp.c +++ b/net/802/garp.c @@ -603,6 +603,11 @@ err1: } EXPORT_SYMBOL_GPL(garp_init_applicant); +static void garp_app_kfree_rcu(struct rcu_head *head) +{ + kfree(container_of(head, struct garp_applicant, rcu)); +} + void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl) { struct garp_port *port = rtnl_dereference(dev->garp_port); @@ -611,7 +616,6 @@ void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl ASSERT_RTNL(); rcu_assign_pointer(port->applicants[appl->type], NULL); - synchronize_rcu(); /* Delete timer and generate a final TRANSMIT_PDU event to flush out * all pending messages before the applicant is gone. */ @@ -621,7 +625,7 @@ void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl garp_queue_xmit(app); dev_mc_del(dev, appl->proto.group_address); - kfree(app); + call_rcu(&app->rcu, garp_app_kfree_rcu); garp_release_port(dev); } EXPORT_SYMBOL_GPL(garp_uninit_applicant); @@ -639,3 +643,9 @@ void garp_unregister_application(struct garp_application *appl) stp_proto_unregister(&appl->proto); } EXPORT_SYMBOL_GPL(garp_unregister_application); + +static void __exit garp_cleanup_module(void) +{ + rcu_barrier(); /* Wait for completion of call_rcu()'s */ +} +module_exit(garp_cleanup_module); -- cgit v1.2.3-58-ga151 From 864b5418ebc16893cfd27ff3cda254eff0f56d6f Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Thu, 12 May 2011 06:42:04 +0000 Subject: ethtool: bring back missing comma in netdev features strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The issue was introduced in commit eed2a12f1ed9aabf. Signed-off-by: Franco Fichtner Acked-by: Michał Mirosław Acked-by: Ben Hutchings Signed-off-by: David S. Miller --- net/core/ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index b6f405888538..b8c2b10f397a 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -361,7 +361,7 @@ static const char netdev_features_strings[ETHTOOL_DEV_FEATURE_WORDS * 32][ETH_GS /* NETIF_F_NTUPLE */ "rx-ntuple-filter", /* NETIF_F_RXHASH */ "rx-hashing", /* NETIF_F_RXCSUM */ "rx-checksum", - /* NETIF_F_NOCACHE_COPY */ "tx-nocache-copy" + /* NETIF_F_NOCACHE_COPY */ "tx-nocache-copy", /* NETIF_F_LOOPBACK */ "loopback", }; -- cgit v1.2.3-58-ga151 From f0a619ccfb8a2ec8ff083a02299cfd076c362b27 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Fri, 6 May 2011 07:56:29 +0000 Subject: net: Fix vlan_features propagation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix VLAN features propagation for devices which change vlan_features. For this to work, driver needs to make sure netdev_features_changed() gets called after the change (it is e.g. after ndo_set_features()). Side effect is that a user might request features that will never be enabled on a VLAN device. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- net/8021q/vlan_dev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 58f8010e1aef..f247f5bff88d 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -528,7 +528,7 @@ static int vlan_dev_init(struct net_device *dev) (1<<__LINK_STATE_DORMANT))) | (1<<__LINK_STATE_PRESENT); - dev->hw_features = real_dev->vlan_features & NETIF_F_ALL_TX_OFFLOADS; + dev->hw_features = NETIF_F_ALL_TX_OFFLOADS; dev->features |= real_dev->vlan_features | NETIF_F_LLTX; dev->gso_max_size = real_dev->gso_max_size; @@ -587,9 +587,11 @@ static u32 vlan_dev_fix_features(struct net_device *dev, u32 features) { struct net_device *real_dev = vlan_dev_info(dev)->real_dev; - features &= (real_dev->features | NETIF_F_LLTX); + features &= real_dev->features; + features &= real_dev->vlan_features; if (dev_ethtool_get_rx_csum(real_dev)) features |= NETIF_F_RXCSUM; + features |= NETIF_F_LLTX; return features; } -- cgit v1.2.3-58-ga151 From 7f267051bd7a280265b1b5ead58e9c6e4e1ac3a4 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Mon, 9 May 2011 11:53:27 +0000 Subject: net: group FCoE related feature flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Michał Mirosław's patch (http://patchwork.ozlabs.org/patch/94421/) fixes the issue (http://patchwork.ozlabs.org/patch/94188/) about not populating FCoE related flags correctly on vlan devices. However, only NETIF_F_FCOE_CRC is part of the NETIF_F_ALL_TX_OFFLOADS right now, where weed NETIF_F_FCOE_MTU and NETIF_F_FSO as well. Therefore, add NETIF_F_ALL_FCOE to indicate feature flags used by FCoE TX offloads. These include NETIF_F_FCOE_CRC, NETIF_F_FCOE_MTU, and NETIF_F_FSO and add them to be part of NETIF_F_ALL_TX_OFFLOADS. This would eventually make sure all FCoE needed flags are populated properly to vlan devices. Signed-off-by: Yi Zou Signed-off-by: David S. Miller --- include/linux/netdevice.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e7244ed1f9a8..00d650c74800 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1097,10 +1097,14 @@ struct net_device { #define NETIF_F_ALL_TSO (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN) +#define NETIF_F_ALL_FCOE (NETIF_F_FCOE_CRC | NETIF_F_FCOE_MTU | \ + NETIF_F_FSO) + #define NETIF_F_ALL_TX_OFFLOADS (NETIF_F_ALL_CSUM | NETIF_F_SG | \ NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \ NETIF_F_HIGHDMA | \ - NETIF_F_SCTP_CSUM | NETIF_F_FCOE_CRC) + NETIF_F_SCTP_CSUM | \ + NETIF_F_ALL_FCOE) /* * If one device supports one of these features, then enable them -- cgit v1.2.3-58-ga151 From cbfd1526f6076ece92b4e2dcc0a2f1e89041b3bd Mon Sep 17 00:00:00 2001 From: Amit Virdi Date: Thu, 12 May 2011 01:04:40 +0000 Subject: net/irda/ircomm_tty.c: Use flip buffers to deliver data use tty_insert_flip_string and tty_flip_buffer_push to deliver incoming data packets from the IrDA device instead of delivering the packets directly to the line discipline. Following later approach resulted in warning "Sleeping function called from invalid context". Signed-off-by: Amit Virdi Acked-by: Alan Cox Signed-off-by: David S. Miller --- net/irda/ircomm/ircomm_tty.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index a39cca8331df..b3cc8b3989a9 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include /* for MODULE_ALIAS_CHARDEV_MAJOR */ @@ -1132,7 +1133,6 @@ static int ircomm_tty_data_indication(void *instance, void *sap, struct sk_buff *skb) { struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - struct tty_ldisc *ld; IRDA_DEBUG(2, "%s()\n", __func__ ); @@ -1161,15 +1161,11 @@ static int ircomm_tty_data_indication(void *instance, void *sap, } /* - * Just give it over to the line discipline. There is no need to - * involve the flip buffers, since we are not running in an interrupt - * handler + * Use flip buffer functions since the code may be called from interrupt + * context */ - - ld = tty_ldisc_ref(self->tty); - if (ld) - ld->ops->receive_buf(self->tty, skb->data, NULL, skb->len); - tty_ldisc_deref(ld); + tty_insert_flip_string(self->tty, skb->data, skb->len); + tty_flip_buffer_push(self->tty); /* No need to kfree_skb - see ircomm_ttp_data_indication() */ -- cgit v1.2.3-58-ga151 From 06c03c02ea528af0cbce50ce45ddd6a361864550 Mon Sep 17 00:00:00 2001 From: Mahesh Bandewar Date: Sun, 8 May 2011 06:51:48 +0000 Subject: tg3: Allow ethtool to enable/disable loopback. This patch adds tg3_set_features() to handle loopback mode. Currently the capability is added for the devices which support internal MAC loopback mode. So when enabled, it enables internal-MAC loopback. Signed-off-by: Mahesh Bandewar Signed-off-by: David S. Miller --- drivers/net/tg3.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ec1953043102..d5a1f9e3794c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3373,8 +3373,8 @@ relink: tg3_phy_copper_begin(tp); tg3_readphy(tp, MII_BMSR, &bmsr); - if (!tg3_readphy(tp, MII_BMSR, &bmsr) && - (bmsr & BMSR_LSTATUS)) + if ((!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) || + (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK)) current_link_up = 1; } @@ -6309,6 +6309,42 @@ dma_error: return NETDEV_TX_OK; } +static void tg3_set_loopback(struct net_device *dev, u32 features) +{ + struct tg3 *tp = netdev_priv(dev); + + if (features & NETIF_F_LOOPBACK) { + if (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK) + return; + + /* + * Clear MAC_MODE_HALF_DUPLEX or you won't get packets back in + * loopback mode if Half-Duplex mode was negotiated earlier. + */ + tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX; + + /* Enable internal MAC loopback mode */ + tp->mac_mode |= MAC_MODE_PORT_INT_LPBACK; + spin_lock_bh(&tp->lock); + tw32(MAC_MODE, tp->mac_mode); + netif_carrier_on(tp->dev); + spin_unlock_bh(&tp->lock); + netdev_info(dev, "Internal MAC loopback mode enabled.\n"); + } else { + if (!(tp->mac_mode & MAC_MODE_PORT_INT_LPBACK)) + return; + + /* Disable internal MAC loopback mode */ + tp->mac_mode &= ~MAC_MODE_PORT_INT_LPBACK; + spin_lock_bh(&tp->lock); + tw32(MAC_MODE, tp->mac_mode); + /* Force link status check */ + tg3_setup_phy(tp, 1); + spin_unlock_bh(&tp->lock); + netdev_info(dev, "Internal MAC loopback mode disabled.\n"); + } +} + static u32 tg3_fix_features(struct net_device *dev, u32 features) { struct tg3 *tp = netdev_priv(dev); @@ -6319,6 +6355,16 @@ static u32 tg3_fix_features(struct net_device *dev, u32 features) return features; } +static int tg3_set_features(struct net_device *dev, u32 features) +{ + u32 changed = dev->features ^ features; + + if ((changed & NETIF_F_LOOPBACK) && netif_running(dev)) + tg3_set_loopback(dev, features); + + return 0; +} + static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, int new_mtu) { @@ -9485,6 +9531,13 @@ static int tg3_open(struct net_device *dev) netif_tx_start_all_queues(dev); + /* + * Reset loopback feature if it was turned on while the device was down + * make sure that it's installed properly now. + */ + if (dev->features & NETIF_F_LOOPBACK) + tg3_set_loopback(dev, dev->features); + return 0; err_out3: @@ -15033,6 +15086,7 @@ static const struct net_device_ops tg3_netdev_ops = { .ndo_tx_timeout = tg3_tx_timeout, .ndo_change_mtu = tg3_change_mtu, .ndo_fix_features = tg3_fix_features, + .ndo_set_features = tg3_set_features, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = tg3_poll_controller, #endif @@ -15049,6 +15103,7 @@ static const struct net_device_ops tg3_netdev_ops_dma_bug = { .ndo_do_ioctl = tg3_ioctl, .ndo_tx_timeout = tg3_tx_timeout, .ndo_change_mtu = tg3_change_mtu, + .ndo_set_features = tg3_set_features, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = tg3_poll_controller, #endif @@ -15246,6 +15301,16 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, dev->features |= hw_features; dev->vlan_features |= hw_features; + /* + * Add loopback capability only for a subset of devices that support + * MAC-LOOPBACK. Eventually this need to be enhanced to allow INT-PHY + * loopback for the remaining devices. + */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780 && + !tg3_flag(tp, CPMU_PRESENT)) + /* Add the loopback capability */ + dev->hw_features |= NETIF_F_LOOPBACK; + if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 && !tg3_flag(tp, TSO_CAPABLE) && !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) { -- cgit v1.2.3-58-ga151 From e58b34425bfcb08c6bc8c520b82c37ffcec87072 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 12 May 2011 18:22:34 -0400 Subject: ipvs: Use IP_VS_RT_MODE_* instead of magic constants. [ Add some cases I missed, from Julian Anastasov ] Signed-off-by: David S. Miller --- net/netfilter/ipvs/ip_vs_xmit.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 6132b213eddc..5d393c5a802d 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -229,8 +229,6 @@ out_err: /* * Get route to destination or remote server - * rt_mode: flags, &1=Allow local dest, &2=Allow non-local dest, - * &4=Allow redirect from remote daddr to local */ static struct rt6_info * __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest, @@ -274,13 +272,14 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest, } local = __ip_vs_is_local_route6(rt); - if (!((local ? 1 : 2) & rt_mode)) { + if (!((local ? IP_VS_RT_MODE_LOCAL : IP_VS_RT_MODE_NON_LOCAL) & + rt_mode)) { IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI6\n", local ? "local":"non-local", daddr); dst_release(&rt->dst); return NULL; } - if (local && !(rt_mode & 4) && + if (local && !(rt_mode & IP_VS_RT_MODE_RDR) && !((ort = (struct rt6_info *) skb_dst(skb)) && __ip_vs_is_local_route6(ort))) { IP_VS_DBG_RL("Redirect from non-local address %pI6 to local " @@ -440,7 +439,8 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, EnterFunction(10); - if (!(rt = __ip_vs_get_out_rt_v6(skb, NULL, &iph->daddr, NULL, 0, 2))) + if (!(rt = __ip_vs_get_out_rt_v6(skb, NULL, &iph->daddr, NULL, 0, + IP_VS_RT_MODE_NON_LOCAL))) goto tx_error_icmp; /* MTU checking */ @@ -632,7 +632,9 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, } if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, - 0, 1|2|4))) + 0, (IP_VS_RT_MODE_LOCAL | + IP_VS_RT_MODE_NON_LOCAL | + IP_VS_RT_MODE_RDR)))) goto tx_error_icmp; local = __ip_vs_is_local_route6(rt); /* @@ -875,7 +877,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, EnterFunction(10); if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, - &saddr, 1, 1|2))) + &saddr, 1, (IP_VS_RT_MODE_LOCAL | + IP_VS_RT_MODE_NON_LOCAL)))) goto tx_error_icmp; if (__ip_vs_is_local_route6(rt)) { dst_release(&rt->dst); @@ -1050,7 +1053,8 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, EnterFunction(10); if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, - 0, 1|2))) + 0, (IP_VS_RT_MODE_LOCAL | + IP_VS_RT_MODE_NON_LOCAL)))) goto tx_error_icmp; if (__ip_vs_is_local_route6(rt)) { dst_release(&rt->dst); @@ -1254,7 +1258,9 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, */ if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, - 0, 1|2|4))) + 0, (IP_VS_RT_MODE_LOCAL | + IP_VS_RT_MODE_NON_LOCAL | + IP_VS_RT_MODE_RDR)))) goto tx_error_icmp; local = __ip_vs_is_local_route6(rt); -- cgit v1.2.3-58-ga151 From 44e3125ccd521585e73e6dd228b283ab26993c68 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 9 May 2011 14:38:06 -0700 Subject: ipvs: Eliminate rt->rt_dst usage in __ip_vs_get_out_rt(). We can simply track what destination address is used based upon which code block is taken at the top of the function. Signed-off-by: David S. Miller --- net/netfilter/ipvs/ip_vs_xmit.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 5d393c5a802d..3f3e0f4c38a5 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -110,6 +110,7 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, &dest->addr.ip, atomic_read(&rt->dst.__refcnt), rtos); } + daddr = dest->addr.ip; spin_unlock(&dest->dst_lock); } else { rt = ip_route_output(net, daddr, 0, rtos, 0); @@ -125,7 +126,7 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, rt_mode)) { IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI4\n", (rt->rt_flags & RTCF_LOCAL) ? - "local":"non-local", &rt->rt_dst); + "local":"non-local", &daddr); ip_rt_put(rt); return NULL; } @@ -133,14 +134,14 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, !((ort = skb_rtable(skb)) && ort->rt_flags & RTCF_LOCAL)) { IP_VS_DBG_RL("Redirect from non-local address %pI4 to local " "requires NAT method, dest: %pI4\n", - &ip_hdr(skb)->daddr, &rt->rt_dst); + &ip_hdr(skb)->daddr, &daddr); ip_rt_put(rt); return NULL; } if (unlikely(!local && ipv4_is_loopback(ip_hdr(skb)->saddr))) { IP_VS_DBG_RL("Stopping traffic from loopback address %pI4 " "to non-local address, dest: %pI4\n", - &ip_hdr(skb)->saddr, &rt->rt_dst); + &ip_hdr(skb)->saddr, &daddr); ip_rt_put(rt); return NULL; } -- cgit v1.2.3-58-ga151 From c92f5ca2e5120796c56455e0a4b7cc0dfd6ceb49 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Tue, 10 May 2011 12:46:05 +0000 Subject: ipvs: Remove all remaining references to rt->rt_{src,dst} Remove all remaining references to rt->rt_{src,dst} by using dest->dst_saddr to cache saddr (used for TUN mode). For ICMP in FORWARD hook just restrict the rt_mode for NAT to disable LOCALNODE. All other modes do not allow IP_VS_RT_MODE_RDR, so we should be safe with the ICMP forwarding. Using cp->daddr as replacement for rt_dst is safe for all modes except BYPASS, even when cp->dest is NULL because it is cp->daddr that is used to assign cp->dest for sync-ed connections. Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller --- include/net/ip_vs.h | 9 +++--- net/netfilter/ipvs/ip_vs_core.c | 24 ++------------ net/netfilter/ipvs/ip_vs_xmit.c | 72 +++++++++++++++++++++++++++-------------- 3 files changed, 54 insertions(+), 51 deletions(-) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 9d1f510ab6d0..4fff432aeade 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -665,9 +665,7 @@ struct ip_vs_dest { struct dst_entry *dst_cache; /* destination cache entry */ u32 dst_rtos; /* RT_TOS(tos) for dst */ u32 dst_cookie; -#ifdef CONFIG_IP_VS_IPV6 - struct in6_addr dst_saddr; -#endif + union nf_inet_addr dst_saddr; /* for virtual service */ struct ip_vs_service *svc; /* service it belongs to */ @@ -1253,7 +1251,8 @@ extern int ip_vs_tunnel_xmit extern int ip_vs_dr_xmit (struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); extern int ip_vs_icmp_xmit -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, int offset); +(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, + int offset, unsigned int hooknum); extern void ip_vs_dst_reset(struct ip_vs_dest *dest); #ifdef CONFIG_IP_VS_IPV6 @@ -1267,7 +1266,7 @@ extern int ip_vs_dr_xmit_v6 (struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); extern int ip_vs_icmp_xmit_v6 (struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, - int offset); + int offset, unsigned int hooknum); #endif #ifdef CONFIG_SYSCTL diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index a74dae6c5dbc..bfa808f4da13 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1382,15 +1382,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) ip_vs_in_stats(cp, skb); if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) offset += 2 * sizeof(__u16); - verdict = ip_vs_icmp_xmit(skb, cp, pp, offset); - /* LOCALNODE from FORWARD hook is not supported */ - if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD && - skb_rtable(skb)->rt_flags & RTCF_LOCAL) { - IP_VS_DBG(1, "%s(): " - "local delivery to %pI4 but in FORWARD\n", - __func__, &skb_rtable(skb)->rt_dst); - verdict = NF_DROP; - } + verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum); out: __ip_vs_conn_put(cp); @@ -1412,7 +1404,6 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) struct ip_vs_protocol *pp; struct ip_vs_proto_data *pd; unsigned int offset, verdict; - struct rt6_info *rt; *related = 1; @@ -1474,23 +1465,12 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) if (!cp) return NF_ACCEPT; - verdict = NF_DROP; - /* do the statistics and put it back */ ip_vs_in_stats(cp, skb); if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr || IPPROTO_SCTP == cih->nexthdr) offset += 2 * sizeof(__u16); - verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset); - /* LOCALNODE from FORWARD hook is not supported */ - if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD && - (rt = (struct rt6_info *) skb_dst(skb)) && - rt->rt6i_dev && rt->rt6i_dev->flags & IFF_LOOPBACK) { - IP_VS_DBG(1, "%s(): " - "local delivery to %pI6 but in FORWARD\n", - __func__, &rt->rt6i_dst); - verdict = NF_DROP; - } + verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum); __ip_vs_conn_put(cp); diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 3f3e0f4c38a5..ee319a4338b0 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -87,7 +87,7 @@ __ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos) /* Get route to destination or remote server */ static struct rtable * __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, - __be32 daddr, u32 rtos, int rt_mode) + __be32 daddr, u32 rtos, int rt_mode, __be32 *ret_saddr) { struct net *net = dev_net(skb_dst(skb)->dev); struct rtable *rt; /* Route to the other host */ @@ -98,7 +98,12 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, spin_lock(&dest->dst_lock); if (!(rt = (struct rtable *) __ip_vs_dst_check(dest, rtos))) { - rt = ip_route_output(net, dest->addr.ip, 0, rtos, 0); + struct flowi4 fl4; + + memset(&fl4, 0, sizeof(fl4)); + fl4.daddr = dest->addr.ip; + fl4.flowi4_tos = rtos; + rt = ip_route_output_key(net, &fl4); if (IS_ERR(rt)) { spin_unlock(&dest->dst_lock); IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", @@ -106,19 +111,30 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, return NULL; } __ip_vs_dst_set(dest, rtos, dst_clone(&rt->dst), 0); - IP_VS_DBG(10, "new dst %pI4, refcnt=%d, rtos=%X\n", - &dest->addr.ip, + dest->dst_saddr.ip = fl4.saddr; + IP_VS_DBG(10, "new dst %pI4, src %pI4, refcnt=%d, " + "rtos=%X\n", + &dest->addr.ip, &dest->dst_saddr.ip, atomic_read(&rt->dst.__refcnt), rtos); } daddr = dest->addr.ip; + if (ret_saddr) + *ret_saddr = dest->dst_saddr.ip; spin_unlock(&dest->dst_lock); } else { - rt = ip_route_output(net, daddr, 0, rtos, 0); + struct flowi4 fl4; + + memset(&fl4, 0, sizeof(fl4)); + fl4.daddr = daddr; + fl4.flowi4_tos = rtos; + rt = ip_route_output_key(net, &fl4); if (IS_ERR(rt)) { IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", &daddr); return NULL; } + if (ret_saddr) + *ret_saddr = fl4.saddr; } local = rt->rt_flags & RTCF_LOCAL; @@ -249,7 +265,7 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest, u32 cookie; dst = __ip_vs_route_output_v6(net, &dest->addr.in6, - &dest->dst_saddr, + &dest->dst_saddr.in6, do_xfrm); if (!dst) { spin_unlock(&dest->dst_lock); @@ -259,11 +275,11 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest, cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; __ip_vs_dst_set(dest, 0, dst_clone(&rt->dst), cookie); IP_VS_DBG(10, "new dst %pI6, src %pI6, refcnt=%d\n", - &dest->addr.in6, &dest->dst_saddr, + &dest->addr.in6, &dest->dst_saddr.in6, atomic_read(&rt->dst.__refcnt)); } if (ret_saddr) - ipv6_addr_copy(ret_saddr, &dest->dst_saddr); + ipv6_addr_copy(ret_saddr, &dest->dst_saddr.in6); spin_unlock(&dest->dst_lock); } else { dst = __ip_vs_route_output_v6(net, daddr, ret_saddr, do_xfrm); @@ -386,7 +402,7 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, EnterFunction(10); if (!(rt = __ip_vs_get_out_rt(skb, NULL, iph->daddr, RT_TOS(iph->tos), - IP_VS_RT_MODE_NON_LOCAL))) + IP_VS_RT_MODE_NON_LOCAL, NULL))) goto tx_error_icmp; /* MTU checking */ @@ -518,7 +534,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, RT_TOS(iph->tos), IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | - IP_VS_RT_MODE_RDR))) + IP_VS_RT_MODE_RDR, NULL))) goto tx_error_icmp; local = rt->rt_flags & RTCF_LOCAL; /* @@ -540,7 +556,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, #endif /* From world but DNAT to loopback address? */ - if (local && ipv4_is_loopback(rt->rt_dst) && + if (local && ipv4_is_loopback(cp->daddr.ip) && rt_is_input_route(skb_rtable(skb))) { IP_VS_DBG_RL_PKT(1, AF_INET, pp, skb, 0, "ip_vs_nat_xmit(): " "stopping DNAT to loopback address"); @@ -751,6 +767,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp) { struct rtable *rt; /* Route to the other host */ + __be32 saddr; /* Source for tunnel */ struct net_device *tdev; /* Device to other host */ struct iphdr *old_iph = ip_hdr(skb); u8 tos = old_iph->tos; @@ -764,7 +781,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, RT_TOS(tos), IP_VS_RT_MODE_LOCAL | - IP_VS_RT_MODE_NON_LOCAL))) + IP_VS_RT_MODE_NON_LOCAL, + &saddr))) goto tx_error_icmp; if (rt->rt_flags & RTCF_LOCAL) { ip_rt_put(rt); @@ -832,8 +850,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, iph->frag_off = df; iph->protocol = IPPROTO_IPIP; iph->tos = tos; - iph->daddr = rt->rt_dst; - iph->saddr = rt->rt_src; + iph->daddr = cp->daddr.ip; + iph->saddr = saddr; iph->ttl = old_iph->ttl; ip_select_ident(iph, &rt->dst, NULL); @@ -996,7 +1014,7 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, RT_TOS(iph->tos), IP_VS_RT_MODE_LOCAL | - IP_VS_RT_MODE_NON_LOCAL))) + IP_VS_RT_MODE_NON_LOCAL, NULL))) goto tx_error_icmp; if (rt->rt_flags & RTCF_LOCAL) { ip_rt_put(rt); @@ -1114,12 +1132,13 @@ tx_error: */ int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, int offset) + struct ip_vs_protocol *pp, int offset, unsigned int hooknum) { struct rtable *rt; /* Route to the other host */ int mtu; int rc; int local; + int rt_mode; EnterFunction(10); @@ -1140,11 +1159,13 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, * mangle and send the packet here (only for VS/NAT) */ + /* LOCALNODE from FORWARD hook is not supported */ + rt_mode = (hooknum != NF_INET_FORWARD) ? + IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | + IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, RT_TOS(ip_hdr(skb)->tos), - IP_VS_RT_MODE_LOCAL | - IP_VS_RT_MODE_NON_LOCAL | - IP_VS_RT_MODE_RDR))) + rt_mode, NULL))) goto tx_error_icmp; local = rt->rt_flags & RTCF_LOCAL; @@ -1167,7 +1188,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, #endif /* From world but DNAT to loopback address? */ - if (local && ipv4_is_loopback(rt->rt_dst) && + if (local && ipv4_is_loopback(cp->daddr.ip) && rt_is_input_route(skb_rtable(skb))) { IP_VS_DBG(1, "%s(): " "stopping DNAT to loopback %pI4\n", @@ -1232,12 +1253,13 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, #ifdef CONFIG_IP_VS_IPV6 int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, int offset) + struct ip_vs_protocol *pp, int offset, unsigned int hooknum) { struct rt6_info *rt; /* Route to the other host */ int mtu; int rc; int local; + int rt_mode; EnterFunction(10); @@ -1258,10 +1280,12 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, * mangle and send the packet here (only for VS/NAT) */ + /* LOCALNODE from FORWARD hook is not supported */ + rt_mode = (hooknum != NF_INET_FORWARD) ? + IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | + IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, - 0, (IP_VS_RT_MODE_LOCAL | - IP_VS_RT_MODE_NON_LOCAL | - IP_VS_RT_MODE_RDR)))) + 0, rt_mode))) goto tx_error_icmp; local = __ip_vs_is_local_route6(rt); -- cgit v1.2.3-58-ga151 From 6c60408e33aba6d1d7241bc9be3b8d1b39509291 Mon Sep 17 00:00:00 2001 From: Alexey Orishko Date: Fri, 6 May 2011 03:01:30 +0000 Subject: CDC NCM: Add mising short packet in cdc_ncm driver Changes: - while making NTB, driver shall check if device dwNtbOutMaxSize is higher than host value and shall add a short packet if this is the case - previous temporary patch for this issue is replaced by this one Signed-off-by: Alexey Orishko Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ncm.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 1033ef6476a4..4ab557d0287d 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -54,13 +54,13 @@ #include #include -#define DRIVER_VERSION "23-Apr-2011" +#define DRIVER_VERSION "06-May-2011" /* CDC NCM subclass 3.2.1 */ #define USB_CDC_NCM_NDP16_LENGTH_MIN 0x10 /* Maximum NTB length */ -#define CDC_NCM_NTB_MAX_SIZE_TX (16384 + 4) /* bytes, must be short terminated */ +#define CDC_NCM_NTB_MAX_SIZE_TX 16384 /* bytes */ #define CDC_NCM_NTB_MAX_SIZE_RX 16384 /* bytes */ /* Minimum value for MaxDatagramSize, ch. 6.2.9 */ @@ -722,7 +722,7 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb) } else { /* reset variables */ - skb_out = alloc_skb(ctx->tx_max, GFP_ATOMIC); + skb_out = alloc_skb((ctx->tx_max + 1), GFP_ATOMIC); if (skb_out == NULL) { if (skb != NULL) { dev_kfree_skb_any(skb); @@ -861,8 +861,11 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb) /* store last offset */ last_offset = offset; - if ((last_offset < ctx->tx_max) && ((last_offset % - le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0)) { + if (((last_offset < ctx->tx_max) && ((last_offset % + le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0)) || + (((last_offset == ctx->tx_max) && ((ctx->tx_max % + le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0)) && + (ctx->tx_max < le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)))) { /* force short packet */ *(((u8 *)skb_out->data) + last_offset) = 0; last_offset++; -- cgit v1.2.3-58-ga151 From afe12cc86b0ba545a01ad8716539ab07ab6e9e89 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sat, 7 May 2011 03:22:17 +0000 Subject: net: introduce netdev_change_features() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It will be needed by bonding and other drivers changing vlan_features after ndo_init callback. As a bonus, this includes kernel-doc for netdev_update_features(). Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- include/linux/netdevice.h | 1 + net/core/dev.c | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 00d650c74800..1d9696a9ee4d 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2565,6 +2565,7 @@ u32 netdev_increment_features(u32 all, u32 one, u32 mask); u32 netdev_fix_features(struct net_device *dev, u32 features); int __netdev_update_features(struct net_device *dev); void netdev_update_features(struct net_device *dev); +void netdev_change_features(struct net_device *dev); void netif_stacked_transfer_operstate(const struct net_device *rootdev, struct net_device *dev); diff --git a/net/core/dev.c b/net/core/dev.c index 75898a32c038..ea23353e6251 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5289,6 +5289,14 @@ int __netdev_update_features(struct net_device *dev) return 1; } +/** + * netdev_update_features - recalculate device features + * @dev: the device to check + * + * Recalculate dev->features set and send notifications if it + * has changed. Should be called after driver or hardware dependent + * conditions might have changed that influence the features. + */ void netdev_update_features(struct net_device *dev) { if (__netdev_update_features(dev)) @@ -5296,6 +5304,23 @@ void netdev_update_features(struct net_device *dev) } EXPORT_SYMBOL(netdev_update_features); +/** + * netdev_change_features - recalculate device features + * @dev: the device to check + * + * Recalculate dev->features set and send notifications even + * if they have not changed. Should be called instead of + * netdev_update_features() if also dev->vlan_features might + * have changed to allow the changes to be propagated to stacked + * VLAN devices. + */ +void netdev_change_features(struct net_device *dev) +{ + __netdev_update_features(dev); + netdev_features_change(dev); +} +EXPORT_SYMBOL(netdev_change_features); + /** * netif_stacked_transfer_operstate - transfer operstate * @rootdev: the root or lower level device to transfer state from -- cgit v1.2.3-58-ga151 From b2a103e6d0afa432dff66b36473c5a55b6b0376c Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sat, 7 May 2011 03:22:17 +0000 Subject: bonding: convert to ndo_fix_features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should also fix updating of vlan_features and propagating changes to VLAN devices on the bond. Side effect: it allows user to force-disable some offloads on the bond interface. Note: NETIF_F_VLAN_CHALLENGED is managed by bond_fix_features() now. Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 157 +++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 91 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6312db1f7838..088fd845ffdf 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -343,32 +343,6 @@ out: return res; } -/** - * bond_has_challenged_slaves - * @bond: the bond we're working on - * - * Searches the slave list. Returns 1 if a vlan challenged slave - * was found, 0 otherwise. - * - * Assumes bond->lock is held. - */ -static int bond_has_challenged_slaves(struct bonding *bond) -{ - struct slave *slave; - int i; - - bond_for_each_slave(bond, slave, i) { - if (slave->dev->features & NETIF_F_VLAN_CHALLENGED) { - pr_debug("found VLAN challenged slave - %s\n", - slave->dev->name); - return 1; - } - } - - pr_debug("no VLAN challenged slaves found\n"); - return 0; -} - /** * bond_next_vlan - safely skip to the next item in the vlans list. * @bond: the bond we're working on @@ -1406,52 +1380,68 @@ static int bond_sethwaddr(struct net_device *bond_dev, return 0; } -#define BOND_VLAN_FEATURES \ - (NETIF_F_VLAN_CHALLENGED | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX | \ - NETIF_F_HW_VLAN_FILTER) - -/* - * Compute the common dev->feature set available to all slaves. Some - * feature bits are managed elsewhere, so preserve those feature bits - * on the master device. - */ -static int bond_compute_features(struct bonding *bond) +static u32 bond_fix_features(struct net_device *dev, u32 features) { struct slave *slave; - struct net_device *bond_dev = bond->dev; - u32 features = bond_dev->features; - u32 vlan_features = 0; - unsigned short max_hard_header_len = max((u16)ETH_HLEN, - bond_dev->hard_header_len); + struct bonding *bond = netdev_priv(dev); + u32 mask; int i; - features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES); - features |= NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_NOCACHE_COPY; + read_lock(&bond->lock); - if (!bond->first_slave) - goto done; + if (!bond->first_slave) { + /* Disable adding VLANs to empty bond. But why? --mq */ + features |= NETIF_F_VLAN_CHALLENGED; + goto out; + } + mask = features; features &= ~NETIF_F_ONE_FOR_ALL; + features |= NETIF_F_ALL_FOR_ALL; - vlan_features = bond->first_slave->dev->vlan_features; bond_for_each_slave(bond, slave, i) { features = netdev_increment_features(features, slave->dev->features, - NETIF_F_ONE_FOR_ALL); + mask); + } + +out: + read_unlock(&bond->lock); + return features; +} + +#define BOND_VLAN_FEATURES (NETIF_F_ALL_TX_OFFLOADS | \ + NETIF_F_SOFT_FEATURES | \ + NETIF_F_LRO) + +static void bond_compute_features(struct bonding *bond) +{ + struct slave *slave; + struct net_device *bond_dev = bond->dev; + u32 vlan_features = BOND_VLAN_FEATURES; + unsigned short max_hard_header_len = ETH_HLEN; + int i; + + read_lock(&bond->lock); + + if (!bond->first_slave) + goto done; + + bond_for_each_slave(bond, slave, i) { vlan_features = netdev_increment_features(vlan_features, - slave->dev->vlan_features, - NETIF_F_ONE_FOR_ALL); + slave->dev->vlan_features, BOND_VLAN_FEATURES); + if (slave->dev->hard_header_len > max_hard_header_len) max_hard_header_len = slave->dev->hard_header_len; } done: - features |= (bond_dev->features & BOND_VLAN_FEATURES); - bond_dev->features = netdev_fix_features(bond_dev, features); - bond_dev->vlan_features = netdev_fix_features(bond_dev, vlan_features); + bond_dev->vlan_features = vlan_features; bond_dev->hard_header_len = max_hard_header_len; - return 0; + read_unlock(&bond->lock); + + netdev_change_features(bond_dev); } static void bond_setup_by_slave(struct net_device *bond_dev, @@ -1544,7 +1534,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) struct netdev_hw_addr *ha; struct sockaddr addr; int link_reporting; - int old_features = bond_dev->features; int res = 0; if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL && @@ -1577,16 +1566,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) pr_warning("%s: Warning: enslaved VLAN challenged slave %s. Adding VLANs will be blocked as long as %s is part of bond %s\n", bond_dev->name, slave_dev->name, slave_dev->name, bond_dev->name); - bond_dev->features |= NETIF_F_VLAN_CHALLENGED; } } else { pr_debug("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); - if (bond->slave_cnt == 0) { - /* First slave, and it is not VLAN challenged, - * so remove the block of adding VLANs over the bond. - */ - bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED; - } } /* @@ -1775,10 +1757,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) new_slave->delay = 0; new_slave->link_failure_count = 0; - bond_compute_features(bond); - write_unlock_bh(&bond->lock); + bond_compute_features(bond); + read_lock(&bond->lock); new_slave->last_arp_rx = jiffies; @@ -1958,7 +1940,7 @@ err_free: kfree(new_slave); err_undo_flags: - bond_dev->features = old_features; + bond_compute_features(bond); return res; } @@ -1979,6 +1961,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) struct bonding *bond = netdev_priv(bond_dev); struct slave *slave, *oldcurrent; struct sockaddr addr; + u32 old_features = bond_dev->features; /* slave is not a slave or master is not master of this slave */ if (!(slave_dev->flags & IFF_SLAVE) || @@ -2039,8 +2022,6 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) /* release the slave from its bond */ bond_detach_slave(bond, slave); - bond_compute_features(bond); - if (bond->primary_slave == slave) bond->primary_slave = NULL; @@ -2084,24 +2065,23 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) */ memset(bond_dev->dev_addr, 0, bond_dev->addr_len); - if (!bond->vlgrp) { - bond_dev->features |= NETIF_F_VLAN_CHALLENGED; - } else { + if (bond->vlgrp) { pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n", bond_dev->name, bond_dev->name); pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n", bond_dev->name); } - } else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) && - !bond_has_challenged_slaves(bond)) { - pr_info("%s: last VLAN challenged slave %s left bond %s. VLAN blocking is removed\n", - bond_dev->name, slave_dev->name, bond_dev->name); - bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED; } write_unlock_bh(&bond->lock); unblock_netpoll_tx(); + bond_compute_features(bond); + if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) && + (old_features & NETIF_F_VLAN_CHALLENGED)) + pr_info("%s: last VLAN challenged slave %s left bond %s. VLAN blocking is removed\n", + bond_dev->name, slave_dev->name, bond_dev->name); + /* must do this from outside any spinlocks */ bond_destroy_slave_symlinks(bond_dev, slave_dev); @@ -2219,8 +2199,6 @@ static int bond_release_all(struct net_device *bond_dev) bond_alb_deinit_slave(bond, slave); } - bond_compute_features(bond); - bond_destroy_slave_symlinks(bond_dev, slave_dev); bond_del_vlans_from_slave(bond, slave_dev); @@ -2269,9 +2247,7 @@ static int bond_release_all(struct net_device *bond_dev) */ memset(bond_dev->dev_addr, 0, bond_dev->addr_len); - if (!bond->vlgrp) { - bond_dev->features |= NETIF_F_VLAN_CHALLENGED; - } else { + if (bond->vlgrp) { pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n", bond_dev->name, bond_dev->name); pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n", @@ -2282,6 +2258,9 @@ static int bond_release_all(struct net_device *bond_dev) out: write_unlock_bh(&bond->lock); + + bond_compute_features(bond); + return 0; } @@ -4337,11 +4316,6 @@ static void bond_ethtool_get_drvinfo(struct net_device *bond_dev, static const struct ethtool_ops bond_ethtool_ops = { .get_drvinfo = bond_ethtool_get_drvinfo, .get_link = ethtool_op_get_link, - .get_tx_csum = ethtool_op_get_tx_csum, - .get_sg = ethtool_op_get_sg, - .get_tso = ethtool_op_get_tso, - .get_ufo = ethtool_op_get_ufo, - .get_flags = ethtool_op_get_flags, }; static const struct net_device_ops bond_netdev_ops = { @@ -4367,6 +4341,7 @@ static const struct net_device_ops bond_netdev_ops = { #endif .ndo_add_slave = bond_enslave, .ndo_del_slave = bond_release, + .ndo_fix_features = bond_fix_features, }; static void bond_destructor(struct net_device *bond_dev) @@ -4422,14 +4397,14 @@ static void bond_setup(struct net_device *bond_dev) * when there are slaves that are not hw accel * capable */ - bond_dev->features |= (NETIF_F_HW_VLAN_TX | - NETIF_F_HW_VLAN_RX | - NETIF_F_HW_VLAN_FILTER); - /* By default, we enable GRO on bonding devices. - * Actual support requires lowlevel drivers are GRO ready. - */ - bond_dev->features |= NETIF_F_GRO; + bond_dev->hw_features = BOND_VLAN_FEATURES | + NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_RX | + NETIF_F_HW_VLAN_FILTER; + + bond_dev->hw_features &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_NO_CSUM); + bond_dev->features |= bond_dev->hw_features; } static void bond_work_cancel_all(struct bonding *bond) -- cgit v1.2.3-58-ga151 From 10949550bd1e50cc91c0f5085f7080a44b0871fe Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 12 May 2011 19:26:57 -0400 Subject: ipv4: Kill spurious opt->srr check in ip_options_rcv_srr(). All call sites conditionalize the call to ip_options_rcv_srr() with a check of opt->srr, so no need to check it again there. Signed-off-by: David S. Miller --- net/ipv4/ip_options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 01fc40965848..e82c304806bb 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -601,7 +601,7 @@ int ip_options_rcv_srr(struct sk_buff *skb) unsigned long orefdst; int err; - if (!opt->srr || !rt) + if (!rt) return 0; if (skb->pkt_type != PACKET_HOST) -- cgit v1.2.3-58-ga151 From c30883bdff0b3544900a5c4aba18b8985436878f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 12 May 2011 19:30:58 -0400 Subject: ipv4: Simplify iph->daddr overwrite in ip_options_rcv_srr(). We already copy the 4-byte nexthop from the options block into local variable "nexthop" for the route lookup. Re-use that variable instead of memcpy()'ing again when assigning to iph->daddr after the route lookup succeeds. Signed-off-by: David S. Miller --- net/ipv4/ip_options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index e82c304806bb..c5c26192b057 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -635,7 +635,7 @@ int ip_options_rcv_srr(struct sk_buff *skb) if (rt2->rt_type != RTN_LOCAL) break; /* Superfast 8) loopback forward */ - memcpy(&iph->daddr, &optptr[srrptr-1], 4); + iph->daddr = nexthop; opt->is_changed = 1; } if (srrptr <= srrspace) { -- cgit v1.2.3-58-ga151 From def57687e9579b7a797681990dff763c411f5347 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 12 May 2011 19:34:30 -0400 Subject: ipv4: Elide use of rt->rt_dst in ip_forward() No matter what kind of header mangling occurs due to IP options processing, rt->rt_dst will always equal iph->daddr in the packet. So we can safely use iph->daddr instead of rt->rt_dst here. Signed-off-by: David S. Miller --- net/ipv4/ip_forward.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 99461f09320f..fcbc0c8f1261 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -84,7 +84,7 @@ int ip_forward(struct sk_buff *skb) rt = skb_rtable(skb); - if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway) + if (opt->is_strictroute && iph->daddr != rt->rt_gateway) goto sr_failed; if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) && -- cgit v1.2.3-58-ga151 From 72a8f97bf2dfe1b0f02ba8dbaed7d6b76657aae3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 12 May 2011 23:03:46 -0400 Subject: ipv4: Fix 'iph' use before set. I swear none of my compilers warned about this, yet it is so obvious. > net/ipv4/ip_forward.c: In function 'ip_forward': > net/ipv4/ip_forward.c:87: warning: 'iph' may be used uninitialized in this function Reported-by: Stephen Rothwell Signed-off-by: David S. Miller --- net/ipv4/ip_forward.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index fcbc0c8f1261..3b34d1c86270 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -84,7 +84,7 @@ int ip_forward(struct sk_buff *skb) rt = skb_rtable(skb); - if (opt->is_strictroute && iph->daddr != rt->rt_gateway) + if (opt->is_strictroute && ip_hdr(skb)->daddr != rt->rt_gateway) goto sr_failed; if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) && -- cgit v1.2.3-58-ga151 From 2c0f24636c80aa09990c507c0cede39add4b4724 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Fri, 13 May 2011 11:57:08 +0300 Subject: wl12xx_sdio: set interrupt as wake_up interrupt set the sdio interrupt as wake_up interrupt, so we will be able to wake up the suspended system (Wake-On-Wireless) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/sdio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index bcd4ad7ba90d..1298461c45d1 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -267,6 +267,8 @@ static int __devinit wl1271_probe(struct sdio_func *func, goto out_free; } + enable_irq_wake(wl->irq); + disable_irq(wl->irq); ret = wl1271_init_ieee80211(wl); @@ -303,6 +305,7 @@ static void __devexit wl1271_remove(struct sdio_func *func) pm_runtime_get_noresume(&func->dev); wl1271_unregister_hw(wl); + disable_irq_wake(wl->irq); free_irq(wl->irq, wl); wl1271_free_hw(wl); } -- cgit v1.2.3-58-ga151 From 402e48616078c1e56f55a69d314b77f1d750d6ad Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Fri, 13 May 2011 11:57:09 +0300 Subject: wl12xx: declare suspend/resume callbacks (for wowlan) Additionally, add wow_enabled field to wl, to indicate whether wowlan was configured. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 19 +++++++++++++++++++ drivers/net/wireless/wl12xx/wl12xx.h | 6 ++++++ 2 files changed, 25 insertions(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index a14a035aa440..4b421d801873 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1350,6 +1350,23 @@ static struct notifier_block wl1271_dev_notifier = { .notifier_call = wl1271_dev_notify, }; +static int wl1271_op_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wow) +{ + struct wl1271 *wl = hw->priv; + wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); + wl->wow_enabled = !!wow; + return 0; +} + +static int wl1271_op_resume(struct ieee80211_hw *hw) +{ + struct wl1271 *wl = hw->priv; + wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d", + wl->wow_enabled); + return 0; +} + static int wl1271_op_start(struct ieee80211_hw *hw) { wl1271_debug(DEBUG_MAC80211, "mac80211 start"); @@ -3506,6 +3523,8 @@ static const struct ieee80211_ops wl1271_ops = { .stop = wl1271_op_stop, .add_interface = wl1271_op_add_interface, .remove_interface = wl1271_op_remove_interface, + .suspend = wl1271_op_suspend, + .resume = wl1271_op_resume, .config = wl1271_op_config, .prepare_multicast = wl1271_op_prepare_multicast, .configure_filter = wl1271_op_configure_filter, diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index ab0c2f155b8c..9629e90d9b55 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -564,6 +564,12 @@ struct wl1271 { int tcxo_clock; + /* + * wowlan trigger was configured during suspend. + * (currently, only "ANY" trigger is supported) + */ + bool wow_enabled; + /* * AP-mode - links indexed by HLID. The global and broadcast links * are always active. -- cgit v1.2.3-58-ga151 From 039bdb1494d1d514987ce596a4898494021c7af2 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Fri, 13 May 2011 11:57:10 +0300 Subject: wl12xx_sdio: set MMC_PM_KEEP_POWER flag on suspend if a wow trigger was configured, set the MMC_PM_KEEP_POWER flag on suspend, so our power will be kept while the system is suspended. We needed to set this flag on each suspend attempt (when we want to keep power) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/sdio.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 1298461c45d1..5b03fd5ee33f 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -314,7 +314,34 @@ static int wl1271_suspend(struct device *dev) { /* Tell MMC/SDIO core it's OK to power down the card * (if it isn't already), but not to remove it completely */ - return 0; + struct sdio_func *func = dev_to_sdio_func(dev); + struct wl1271 *wl = sdio_get_drvdata(func); + mmc_pm_flag_t sdio_flags; + int ret = 0; + + wl1271_debug(DEBUG_MAC80211, "wl1271 suspend. wow_enabled: %d", + wl->wow_enabled); + + /* check whether sdio should keep power */ + if (wl->wow_enabled) { + sdio_flags = sdio_get_host_pm_caps(func); + + if (!(sdio_flags & MMC_PM_KEEP_POWER)) { + wl1271_error("can't keep power while host " + "is suspended"); + ret = -EINVAL; + goto out; + } + + /* keep power while host suspended */ + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + if (ret) { + wl1271_error("error while trying to keep power"); + goto out; + } + } +out: + return ret; } static int wl1271_resume(struct device *dev) -- cgit v1.2.3-58-ga151 From f44e58681aec420b132a54823d8911293a644d4e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Fri, 13 May 2011 11:57:11 +0300 Subject: wl12xx: prevent scheduling while suspending (WoW enabled) When WoW is enabled, the interface will stay up and the chip will be powered on, so we have to flush/cancel any remaining work, and prevent the irq handler from scheduling a new work until the system is resumed. Add 2 new flags: * WL1271_FLAG_SUSPENDED - the system is (about to be) suspended. * WL1271_FLAG_PENDING_WORK - there is a pending irq work which should be scheduled when the system is being resumed. In order to wake-up the system while getting an irq, we initialize the device as wakeup device, and calling pm_wakeup_event() upon getting the interrupt (while the system is about to be suspended) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 46 ++++++++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/sdio.c | 24 +++++++++++++++++++ drivers/net/wireless/wl12xx/wl12xx.h | 2 ++ 3 files changed, 72 insertions(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 4b421d801873..8f9e6152f3b7 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1356,6 +1356,28 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, struct wl1271 *wl = hw->priv; wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); wl->wow_enabled = !!wow; + if (wl->wow_enabled) { + /* flush any remaining work */ + wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); + flush_delayed_work(&wl->scan_complete_work); + + /* + * disable and re-enable interrupts in order to flush + * the threaded_irq + */ + wl1271_disable_interrupts(wl); + + /* + * set suspended flag to avoid triggering a new threaded_irq + * work. no need for spinlock as interrupts are disabled. + */ + set_bit(WL1271_FLAG_SUSPENDED, &wl->flags); + + wl1271_enable_interrupts(wl); + flush_work(&wl->tx_work); + flush_delayed_work(&wl->pspoll_work); + flush_delayed_work(&wl->elp_work); + } return 0; } @@ -1364,6 +1386,30 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) struct wl1271 *wl = hw->priv; wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d", wl->wow_enabled); + + /* + * re-enable irq_work enqueuing, and call irq_work directly if + * there is a pending work. + */ + if (wl->wow_enabled) { + struct wl1271 *wl = hw->priv; + unsigned long flags; + bool run_irq_work = false; + + spin_lock_irqsave(&wl->wl_lock, flags); + clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags); + if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags)) + run_irq_work = true; + spin_unlock_irqrestore(&wl->wl_lock, flags); + + if (run_irq_work) { + wl1271_debug(DEBUG_MAC80211, + "run postponed irq_work directly"); + wl1271_irq(0, wl); + wl1271_enable_interrupts(wl); + } + } + return 0; } diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 5b03fd5ee33f..41183db34836 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -82,6 +82,16 @@ static irqreturn_t wl1271_hardirq(int irq, void *cookie) complete(wl->elp_compl); wl->elp_compl = NULL; } + + if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) { + /* don't enqueue a work right now. mark it as pending */ + set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags); + wl1271_debug(DEBUG_IRQ, "should not enqueue work"); + disable_irq_nosync(wl->irq); + pm_wakeup_event(wl1271_sdio_wl_to_dev(wl), 0); + spin_unlock_irqrestore(&wl->wl_lock, flags); + return IRQ_HANDLED; + } spin_unlock_irqrestore(&wl->wl_lock, flags); return IRQ_WAKE_THREAD; @@ -268,6 +278,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, } enable_irq_wake(wl->irq); + device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1); disable_irq(wl->irq); @@ -305,6 +316,7 @@ static void __devexit wl1271_remove(struct sdio_func *func) pm_runtime_get_noresume(&func->dev); wl1271_unregister_hw(wl); + device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0); disable_irq_wake(wl->irq); free_irq(wl->irq, wl); wl1271_free_hw(wl); @@ -339,6 +351,9 @@ static int wl1271_suspend(struct device *dev) wl1271_error("error while trying to keep power"); goto out; } + + /* release host */ + sdio_release_host(func); } out: return ret; @@ -346,6 +361,15 @@ out: static int wl1271_resume(struct device *dev) { + struct sdio_func *func = dev_to_sdio_func(dev); + struct wl1271 *wl = sdio_get_drvdata(func); + + wl1271_debug(DEBUG_MAC80211, "wl1271 resume"); + if (wl->wow_enabled) { + /* claim back host */ + sdio_claim_host(func); + } + return 0; } diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 9629e90d9b55..2218b9c63844 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -357,6 +357,8 @@ enum wl12xx_flags { WL1271_FLAG_AP_STARTED, WL1271_FLAG_IF_INITIALIZED, WL1271_FLAG_DUMMY_PACKET_PENDING, + WL1271_FLAG_SUSPENDED, + WL1271_FLAG_PENDING_WORK, }; struct wl1271_link { -- cgit v1.2.3-58-ga151 From f795ea8b2f047409c59e891d6e5e86a925048bf4 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Fri, 13 May 2011 11:57:12 +0300 Subject: wl12xx_sdio: declare support for NL80211_WOW_TRIGGER_ANYTHING trigger Since wowlan requires the ability to stay awake while the host is suspended, declare support for NL80211_WOW_TRIGGER_ANYTHING if the MMC_PM_KEEP_POWER capability is being supported. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/sdio.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 41183db34836..92d29a860fc0 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -231,6 +231,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, const struct wl12xx_platform_data *wlan_data; struct wl1271 *wl; unsigned long irqflags; + mmc_pm_flag_t mmcflags; int ret; /* We are only able to handle the wlan function */ @@ -282,6 +283,13 @@ static int __devinit wl1271_probe(struct sdio_func *func, disable_irq(wl->irq); + /* if sdio can keep power while host is suspended, enable wow */ + mmcflags = sdio_get_host_pm_caps(func); + wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags); + + if (mmcflags & MMC_PM_KEEP_POWER) + hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; + ret = wl1271_init_ieee80211(wl); if (ret) goto out_irq; -- cgit v1.2.3-58-ga151 From 9439064cd9fce8a4db716a748dbf581eb234f9c7 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Fri, 13 May 2011 11:57:13 +0300 Subject: wl12xx: enter/exit psm on wowlan suspend/resume When operating as station, enter psm before suspending the device into wowlan state. Add a new completion event to signal when psm was entered successfully. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/event.c | 7 ++++ drivers/net/wireless/wl12xx/main.c | 81 ++++++++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/ps.h | 2 + drivers/net/wireless/wl12xx/wl12xx.h | 1 + 4 files changed, 91 insertions(+) diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 1e4bd6a2c396..c3c554cd6580 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -135,6 +135,13 @@ static int wl1271_event_ps_report(struct wl1271 *wl, /* enable beacon early termination */ ret = wl1271_acx_bet_enable(wl, true); + if (ret < 0) + break; + + if (wl->ps_compl) { + complete(wl->ps_compl); + wl->ps_compl = NULL; + } break; default: break; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8f9e6152f3b7..610be03a198b 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1350,6 +1350,79 @@ static struct notifier_block wl1271_dev_notifier = { .notifier_call = wl1271_dev_notify, }; +static int wl1271_configure_suspend(struct wl1271 *wl) +{ + int ret; + + if (wl->bss_type != BSS_TYPE_STA_BSS) + return 0; + + mutex_lock(&wl->mutex); + + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out_unlock; + + /* enter psm if needed*/ + if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { + DECLARE_COMPLETION_ONSTACK(compl); + + wl->ps_compl = &compl; + ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, + wl->basic_rate, true); + if (ret < 0) + goto out_sleep; + + /* we must unlock here so we will be able to get events */ + wl1271_ps_elp_sleep(wl); + mutex_unlock(&wl->mutex); + + ret = wait_for_completion_timeout( + &compl, msecs_to_jiffies(WL1271_PS_COMPLETE_TIMEOUT)); + if (ret <= 0) { + wl1271_warning("couldn't enter ps mode!"); + ret = -EBUSY; + goto out; + } + + /* take mutex again, and wakeup */ + mutex_lock(&wl->mutex); + + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out_unlock; + } +out_sleep: + wl1271_ps_elp_sleep(wl); +out_unlock: + mutex_unlock(&wl->mutex); +out: + return ret; + +} + +static void wl1271_configure_resume(struct wl1271 *wl) +{ + int ret; + + if (wl->bss_type != BSS_TYPE_STA_BSS) + return; + + mutex_lock(&wl->mutex); + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + + /* exit psm if it wasn't configured */ + if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) + wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, + wl->basic_rate, true); + + wl1271_ps_elp_sleep(wl); +out: + mutex_unlock(&wl->mutex); +} + static int wl1271_op_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) { @@ -1357,6 +1430,12 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); wl->wow_enabled = !!wow; if (wl->wow_enabled) { + int ret; + ret = wl1271_configure_suspend(wl); + if (ret < 0) { + wl1271_warning("couldn't prepare device to suspend"); + return ret; + } /* flush any remaining work */ wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); flush_delayed_work(&wl->scan_complete_work); @@ -1408,6 +1487,8 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) wl1271_irq(0, wl); wl1271_enable_interrupts(wl); } + + wl1271_configure_resume(wl); } return 0; diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/ps.h index c41bd0a711bc..25eb9bc9b628 100644 --- a/drivers/net/wireless/wl12xx/ps.h +++ b/drivers/net/wireless/wl12xx/ps.h @@ -35,4 +35,6 @@ void wl1271_elp_work(struct work_struct *work); void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues); void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid); +#define WL1271_PS_COMPLETE_TIMEOUT 500 + #endif /* __WL1271_PS_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 2218b9c63844..fbe8f46d1232 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -513,6 +513,7 @@ struct wl1271 { unsigned int rx_filter; struct completion *elp_compl; + struct completion *ps_compl; struct delayed_work elp_work; struct delayed_work pspoll_work; -- cgit v1.2.3-58-ga151 From bdc220da3209d50b8c295490dec94845c88670a2 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 9 May 2011 17:42:46 +0000 Subject: netdevice.h: Align struct net_device members Save a bit of space. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/linux/netdevice.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 1d9696a9ee4d..a134d809125b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1020,9 +1020,6 @@ struct net_device { * part of the usual set specified in Space.c. */ - unsigned char if_port; /* Selectable AUI, TP,..*/ - unsigned char dma; /* DMA channel */ - unsigned long state; struct list_head dev_list; @@ -1146,13 +1143,16 @@ struct net_device { const struct header_ops *header_ops; unsigned int flags; /* interface flags (a la BSD) */ + unsigned int priv_flags; /* Like 'flags' but invisible to userspace. */ unsigned short gflags; - unsigned int priv_flags; /* Like 'flags' but invisible to userspace. */ unsigned short padded; /* How much padding added by alloc_netdev() */ unsigned char operstate; /* RFC2863 operstate */ unsigned char link_mode; /* mapping policy to operstate */ + unsigned char if_port; /* Selectable AUI, TP,..*/ + unsigned char dma; /* DMA channel */ + unsigned int mtu; /* interface MTU value */ unsigned short type; /* interface hardware type */ unsigned short hard_header_len; /* hardware hdr length */ -- cgit v1.2.3-58-ga151 From 29dd54b72ba8c5ad0dd6dd33584449b5953f700b Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Thu, 12 May 2011 12:48:32 +0000 Subject: ethtool: Added support for FW dump Added code to take FW dump via ethtool. Dump level can be controlled via setting the dump flag. A get function is provided to query the current setting of the dump flag. Dump data is obtained from the driver via a separate get function. Changes from v3: Fixed buffer length issue in ethtool_get_dump_data function. Updated kernel doc for ethtool_dump struct and get_dump_flag function. Changes from v2: Provided separate commands for get flag and data. Check for minimum of the two buffer length obtained via ethtool and driver and use that for dump buffer Pass up the driver return error codes up to the caller. Added kernel doc comments. Signed-off-by: Anirban Chakraborty Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- include/linux/ethtool.h | 31 +++++++++++++++++ net/core/ethtool.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index bd0b50b85f06..c6a850ab2ec5 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -601,6 +601,26 @@ struct ethtool_flash { char data[ETHTOOL_FLASH_MAX_FILENAME]; }; +/** + * struct ethtool_dump - used for retrieving, setting device dump + * @cmd: Command number - %ETHTOOL_GET_DUMP_FLAG, %ETHTOOL_GET_DUMP_DATA, or + * %ETHTOOL_SET_DUMP + * @version: FW version of the dump, filled in by driver + * @flag: driver dependent flag for dump setting, filled in by driver during + * get and filled in by ethtool for set operation + * @len: length of dump data, used as the length of the user buffer on entry to + * %ETHTOOL_GET_DUMP_DATA and this is returned as dump length by driver + * for %ETHTOOL_GET_DUMP_FLAG command + * @data: data collected for get dump data operation + */ +struct ethtool_dump { + __u32 cmd; + __u32 version; + __u32 flag; + __u32 len; + __u8 data[0]; +}; + /* for returning and changing feature sets */ /** @@ -853,6 +873,10 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * @get_channels: Get number of channels. * @set_channels: Set number of channels. Returns a negative error code or * zero. + * @get_dump_flag: Get dump flag indicating current dump length, version, + * and flag of the device. + * @get_dump_data: Get dump data. + * @set_dump: Set dump specific flags to the device. * * All operations are optional (i.e. the function pointer may be set * to %NULL) and callers must take this into account. Callers must @@ -927,6 +951,10 @@ struct ethtool_ops { const struct ethtool_rxfh_indir *); void (*get_channels)(struct net_device *, struct ethtool_channels *); int (*set_channels)(struct net_device *, struct ethtool_channels *); + int (*get_dump_flag)(struct net_device *, struct ethtool_dump *); + int (*get_dump_data)(struct net_device *, + struct ethtool_dump *, void *); + int (*set_dump)(struct net_device *, struct ethtool_dump *); }; #endif /* __KERNEL__ */ @@ -998,6 +1026,9 @@ struct ethtool_ops { #define ETHTOOL_SFEATURES 0x0000003b /* Change device offload settings */ #define ETHTOOL_GCHANNELS 0x0000003c /* Get no of channels */ #define ETHTOOL_SCHANNELS 0x0000003d /* Set no of channels */ +#define ETHTOOL_SET_DUMP 0x0000003e /* Set dump settings */ +#define ETHTOOL_GET_DUMP_FLAG 0x0000003f /* Get dump settings */ +#define ETHTOOL_GET_DUMP_DATA 0x00000040 /* Get dump data */ /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET diff --git a/net/core/ethtool.c b/net/core/ethtool.c index b8c2b10f397a..b8c2bcfee6af 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1823,6 +1823,87 @@ static noinline_for_stack int ethtool_flash_device(struct net_device *dev, return dev->ethtool_ops->flash_device(dev, &efl); } +static int ethtool_set_dump(struct net_device *dev, + void __user *useraddr) +{ + struct ethtool_dump dump; + + if (!dev->ethtool_ops->set_dump) + return -EOPNOTSUPP; + + if (copy_from_user(&dump, useraddr, sizeof(dump))) + return -EFAULT; + + return dev->ethtool_ops->set_dump(dev, &dump); +} + +static int ethtool_get_dump_flag(struct net_device *dev, + void __user *useraddr) +{ + int ret; + struct ethtool_dump dump; + const struct ethtool_ops *ops = dev->ethtool_ops; + + if (!dev->ethtool_ops->get_dump_flag) + return -EOPNOTSUPP; + + if (copy_from_user(&dump, useraddr, sizeof(dump))) + return -EFAULT; + + ret = ops->get_dump_flag(dev, &dump); + if (ret) + return ret; + + if (copy_to_user(useraddr, &dump, sizeof(dump))) + return -EFAULT; + return 0; +} + +static int ethtool_get_dump_data(struct net_device *dev, + void __user *useraddr) +{ + int ret; + __u32 len; + struct ethtool_dump dump, tmp; + const struct ethtool_ops *ops = dev->ethtool_ops; + void *data = NULL; + + if (!dev->ethtool_ops->get_dump_data || + !dev->ethtool_ops->get_dump_flag) + return -EOPNOTSUPP; + + if (copy_from_user(&dump, useraddr, sizeof(dump))) + return -EFAULT; + + memset(&tmp, 0, sizeof(tmp)); + tmp.cmd = ETHTOOL_GET_DUMP_FLAG; + ret = ops->get_dump_flag(dev, &tmp); + if (ret) + return ret; + + len = (tmp.len > dump.len) ? dump.len : tmp.len; + if (!len) + return -EFAULT; + + data = vzalloc(tmp.len); + if (!data) + return -ENOMEM; + ret = ops->get_dump_data(dev, &dump, data); + if (ret) + goto out; + + if (copy_to_user(useraddr, &dump, sizeof(dump))) { + ret = -EFAULT; + goto out; + } + useraddr += offsetof(struct ethtool_dump, data); + if (copy_to_user(useraddr, data, len)) + ret = -EFAULT; +out: + vfree(data); + return ret; +} + /* The main entry point in this file. Called from net/core/dev.c */ int dev_ethtool(struct net *net, struct ifreq *ifr) @@ -2039,6 +2120,15 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) case ETHTOOL_SCHANNELS: rc = ethtool_set_channels(dev, useraddr); break; + case ETHTOOL_SET_DUMP: + rc = ethtool_set_dump(dev, useraddr); + break; + case ETHTOOL_GET_DUMP_FLAG: + rc = ethtool_get_dump_flag(dev, useraddr); + break; + case ETHTOOL_GET_DUMP_DATA: + rc = ethtool_get_dump_data(dev, useraddr); + break; default: rc = -EOPNOTSUPP; } -- cgit v1.2.3-58-ga151 From 6ed35eea3b96977d76d61b5862a3209044cb4b1f Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Thu, 12 May 2011 19:32:15 +0000 Subject: be2net: handle signal reception while waiting for POST If waiting on POST returns prematurely (due to a signal), abort polling and return an error. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 0dbb4cbc07b6..d558b9088d7e 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -376,23 +376,25 @@ int be_cmd_POST(struct be_adapter *adapter) { u16 stage; int status, timeout = 0; + struct device *dev = &adapter->pdev->dev; do { status = be_POST_stage_get(adapter, &stage); if (status) { - dev_err(&adapter->pdev->dev, "POST error; stage=0x%x\n", - stage); + dev_err(dev, "POST error; stage=0x%x\n", stage); return -1; } else if (stage != POST_STAGE_ARMFW_RDY) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(2 * HZ); + if (msleep_interruptible(2000)) { + dev_err(dev, "Waiting for POST aborted\n"); + return -EINTR; + } timeout += 2; } else { return 0; } } while (timeout < 40); - dev_err(&adapter->pdev->dev, "POST timeout; stage=0x%x\n", stage); + dev_err(dev, "POST timeout; stage=0x%x\n", stage); return -1; } -- cgit v1.2.3-58-ga151 From 1dbf53a28262aa89ecbe653e8a9127c0baef9bc4 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Thu, 12 May 2011 19:32:16 +0000 Subject: be2net: fix mbox polling for signal reception Sending mbox cmds require multiple steps of writing to the DB register and polling for an ack. Gettting interrupted in the middle by a signal breaks the mbox protocol. Use msleep() to not get interrupted. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index d558b9088d7e..f2c90997fabd 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -298,8 +298,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) return -1; } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(1)); + msleep(1); msecs++; } while (true); -- cgit v1.2.3-58-ga151 From 18f2f616be88736f5daf31d9d40e027abbd607ed Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Thu, 12 May 2011 12:48:33 +0000 Subject: qlcnic: FW dump support Added code to take FW dump. o Driver queries FW at the init time and gets the dump template o It takes FW dump as per the dump template o Level of FW dump (and its size) is configured via dump flag Signed-off-by: Sritej Velaga Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 176 ++++++++++++++- drivers/net/qlcnic/qlcnic_ctx.c | 91 ++++++++ drivers/net/qlcnic/qlcnic_hdr.h | 40 +++- drivers/net/qlcnic/qlcnic_hw.c | 459 +++++++++++++++++++++++++++++++++++++++ drivers/net/qlcnic/qlcnic_init.c | 4 +- drivers/net/qlcnic/qlcnic_main.c | 13 +- 6 files changed, 774 insertions(+), 9 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index f729363b3fc3..689adea62700 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -411,6 +411,29 @@ struct qlcnic_nic_intr_coalesce { u32 timer_out; }; +struct qlcnic_dump_template_hdr { + __le32 type; + __le32 offset; + __le32 size; + __le32 cap_mask; + __le32 num_entries; + __le32 version; + __le32 timestamp; + __le32 checksum; + __le32 drv_cap_mask; + __le32 sys_info[3]; + __le32 saved_state[16]; + __le32 cap_sizes[8]; + __le32 rsvd[0]; +}; + +struct qlcnic_fw_dump { + u8 clr; /* flag to indicate if dump is cleared */ + u32 size; /* total size of the dump */ + void *data; /* dump data area */ + struct qlcnic_dump_template_hdr *tmpl_hdr; +}; + /* * One hardware_context{} per adapter * contains interrupt info as well shared hardware info. @@ -431,6 +454,7 @@ struct qlcnic_hardware_context { u16 board_type; struct qlcnic_nic_intr_coalesce coal; + struct qlcnic_fw_dump fw_dump; }; struct qlcnic_adapter_stats { @@ -574,6 +598,8 @@ struct qlcnic_recv_context { #define QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG 0x00000029 #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a #define QLCNIC_CDRP_CMD_CONFIG_PORT 0x0000002E +#define QLCNIC_CDRP_CMD_TEMP_SIZE 0x0000002f +#define QLCNIC_CDRP_CMD_GET_TEMP_HDR 0x00000030 #define QLCNIC_RCODE_SUCCESS 0 #define QLCNIC_RCODE_NOT_SUPPORTED 9 @@ -1157,6 +1183,152 @@ struct qlcnic_esw_statistics { struct __qlcnic_esw_statistics tx; }; +struct qlcnic_common_entry_hdr { + __le32 type; + __le32 offset; + __le32 cap_size; + u8 mask; + u8 rsvd[2]; + u8 flags; +} __packed; + +struct __crb { + __le32 addr; + u8 stride; + u8 rsvd1[3]; + __le32 data_size; + __le32 no_ops; + __le32 rsvd2[4]; +} __packed; + +struct __ctrl { + __le32 addr; + u8 stride; + u8 index_a; + __le16 timeout; + __le32 data_size; + __le32 no_ops; + u8 opcode; + u8 index_v; + u8 shl_val; + u8 shr_val; + __le32 val1; + __le32 val2; + __le32 val3; +} __packed; + +struct __cache { + __le32 addr; + u8 stride; + u8 rsvd; + __le16 init_tag_val; + __le32 size; + __le32 no_ops; + __le32 ctrl_addr; + __le32 ctrl_val; + __le32 read_addr; + u8 read_addr_stride; + u8 read_addr_num; + u8 rsvd1[2]; +} __packed; + +struct __ocm { + u8 rsvd[8]; + __le32 size; + __le32 no_ops; + u8 rsvd1[8]; + __le32 read_addr; + __le32 read_addr_stride; +} __packed; + +struct __mem { + u8 rsvd[24]; + __le32 addr; + __le32 size; +} __packed; + +struct __mux { + __le32 addr; + u8 rsvd[4]; + __le32 size; + __le32 no_ops; + __le32 val; + __le32 val_stride; + __le32 read_addr; + u8 rsvd2[4]; +} __packed; + +struct __queue { + __le32 sel_addr; + __le16 stride; + u8 rsvd[2]; + __le32 size; + __le32 no_ops; + u8 rsvd2[8]; + __le32 read_addr; + u8 read_addr_stride; + u8 read_addr_cnt; + u8 rsvd3[2]; +} __packed; + +struct qlcnic_dump_entry { + struct qlcnic_common_entry_hdr hdr; + union { + struct __crb crb; + struct __cache cache; + struct __ocm ocm; + struct __mem mem; + struct __mux mux; + struct __queue que; + struct __ctrl ctrl; + } region; +} __packed; + +enum op_codes { + QLCNIC_DUMP_NOP = 0, + QLCNIC_DUMP_READ_CRB = 1, + QLCNIC_DUMP_READ_MUX = 2, + QLCNIC_DUMP_QUEUE = 3, + QLCNIC_DUMP_BRD_CONFIG = 4, + QLCNIC_DUMP_READ_OCM = 6, + QLCNIC_DUMP_PEG_REG = 7, + QLCNIC_DUMP_L1_DTAG = 8, + QLCNIC_DUMP_L1_ITAG = 9, + QLCNIC_DUMP_L1_DATA = 11, + QLCNIC_DUMP_L1_INST = 12, + QLCNIC_DUMP_L2_DTAG = 21, + QLCNIC_DUMP_L2_ITAG = 22, + QLCNIC_DUMP_L2_DATA = 23, + QLCNIC_DUMP_L2_INST = 24, + QLCNIC_DUMP_READ_ROM = 71, + QLCNIC_DUMP_READ_MEM = 72, + QLCNIC_DUMP_READ_CTRL = 98, + QLCNIC_DUMP_TLHDR = 99, + QLCNIC_DUMP_RDEND = 255 +}; + +#define QLCNIC_DUMP_WCRB BIT_0 +#define QLCNIC_DUMP_RWCRB BIT_1 +#define QLCNIC_DUMP_ANDCRB BIT_2 +#define QLCNIC_DUMP_ORCRB BIT_3 +#define QLCNIC_DUMP_POLLCRB BIT_4 +#define QLCNIC_DUMP_RD_SAVE BIT_5 +#define QLCNIC_DUMP_WRT_SAVED BIT_6 +#define QLCNIC_DUMP_MOD_SAVE_ST BIT_7 +#define QLCNIC_DUMP_SKIP BIT_7 + +#define QLCNIC_DUMP_MASK_MIN 3 +#define QLCNIC_DUMP_MASK_DEF 0x0f +#define QLCNIC_DUMP_MASK_MAX 0xff +#define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed + +struct qlcnic_dump_operations { + enum op_codes opcode; + u32 (*handler)(struct qlcnic_adapter *, + struct qlcnic_dump_entry *, u32 *); +}; + +int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter); int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config); u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off); @@ -1203,6 +1375,7 @@ int qlcnic_wol_supported(struct qlcnic_adapter *adapter); int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate); void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter); void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter); +int qlcnic_dump_fw(struct qlcnic_adapter *); /* Functions from qlcnic_init.c */ int qlcnic_load_firmware(struct qlcnic_adapter *adapter); @@ -1213,7 +1386,7 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter); int qlcnic_setup_idc_param(struct qlcnic_adapter *adapter); int qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter); -int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, int addr, int *valp); +int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, u32 addr, u32 *valp); int qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr, u8 *bytes, size_t size); int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter); @@ -1265,6 +1438,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test); netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val); int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data); +void qlcnic_dev_request_reset(struct qlcnic_adapter *); /* Management functions */ int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*); diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c index 3a99886e4736..bab041a5c758 100644 --- a/drivers/net/qlcnic/qlcnic_ctx.c +++ b/drivers/net/qlcnic/qlcnic_ctx.c @@ -64,6 +64,97 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter, return rcode; } +static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u16 temp_size) +{ + uint64_t sum = 0; + int count = temp_size / sizeof(uint32_t); + while (count-- > 0) + sum += *temp_buffer++; + while (sum >> 32) + sum = (sum & 0xFFFFFFFF) + (sum >> 32); + return ~sum; +} + +int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) +{ + int err, i; + u16 temp_size; + void *tmp_addr; + u32 version, csum, *template, *tmp_buf; + struct qlcnic_hardware_context *ahw; + struct qlcnic_dump_template_hdr *tmpl_hdr, *tmp_tmpl; + dma_addr_t tmp_addr_t = 0; + + ahw = adapter->ahw; + err = qlcnic_issue_cmd(adapter, + adapter->ahw->pci_func, + adapter->fw_hal_version, + 0, + 0, + 0, + QLCNIC_CDRP_CMD_TEMP_SIZE); + if (err != QLCNIC_RCODE_SUCCESS) { + err = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); + dev_err(&adapter->pdev->dev, + "Failed to get template size %d\n", err); + err = -EIO; + return err; + } + version = QLCRD32(adapter, QLCNIC_ARG3_CRB_OFFSET); + temp_size = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); + if (!temp_size) + return -EIO; + + tmp_addr = dma_alloc_coherent(&adapter->pdev->dev, temp_size, + &tmp_addr_t, GFP_KERNEL); + if (!tmp_addr) { + dev_err(&adapter->pdev->dev, + "Can't get memory for FW dump template\n"); + return -ENOMEM; + } + err = qlcnic_issue_cmd(adapter, + adapter->ahw->pci_func, + adapter->fw_hal_version, + LSD(tmp_addr_t), + MSD(tmp_addr_t), + temp_size, + QLCNIC_CDRP_CMD_GET_TEMP_HDR); + + if (err != QLCNIC_RCODE_SUCCESS) { + dev_err(&adapter->pdev->dev, + "Failed to get mini dump template header %d\n", err); + err = -EIO; + goto error; + } + tmp_tmpl = (struct qlcnic_dump_template_hdr *) tmp_addr; + csum = qlcnic_temp_checksum((uint32_t *) tmp_addr, temp_size); + if (csum) { + dev_err(&adapter->pdev->dev, + "Template header checksum validation failed\n"); + err = -EIO; + goto error; + } + ahw->fw_dump.tmpl_hdr = vzalloc(temp_size); + if (!ahw->fw_dump.tmpl_hdr) { + err = -EIO; + goto error; + } + tmp_buf = (u32 *) tmp_addr; + template = (u32 *) ahw->fw_dump.tmpl_hdr; + for (i = 0; i < temp_size/sizeof(u32); i++) + *template++ = __le32_to_cpu(*tmp_buf++); + + tmpl_hdr = ahw->fw_dump.tmpl_hdr; + if (tmpl_hdr->cap_mask > QLCNIC_DUMP_MASK_DEF && + tmpl_hdr->cap_mask <= QLCNIC_DUMP_MASK_MAX) + tmpl_hdr->drv_cap_mask = tmpl_hdr->cap_mask; + else + tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF; +error: + dma_free_coherent(&adapter->pdev->dev, temp_size, tmp_addr, tmp_addr_t); + return err; +} + int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu) { diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h index 726ef555b6bc..d14506f764e0 100644 --- a/drivers/net/qlcnic/qlcnic_hdr.h +++ b/drivers/net/qlcnic/qlcnic_hdr.h @@ -492,10 +492,10 @@ enum { #define TEST_AGT_CTRL (0x00) -#define TA_CTL_START 1 -#define TA_CTL_ENABLE 2 -#define TA_CTL_WRITE 4 -#define TA_CTL_BUSY 8 +#define TA_CTL_START BIT_0 +#define TA_CTL_ENABLE BIT_1 +#define TA_CTL_WRITE BIT_2 +#define TA_CTL_BUSY BIT_3 /* * Register offsets for MN @@ -765,6 +765,38 @@ struct qlcnic_legacy_intr_set { #define QLCNIC_MAX_PCI_FUNC 8 #define QLCNIC_MAX_VLAN_FILTERS 64 +/* FW dump defines */ +#define MIU_TEST_CTR 0x41000090 +#define MIU_TEST_ADDR_LO 0x41000094 +#define MIU_TEST_ADDR_HI 0x41000098 +#define FLASH_ROM_WINDOW 0x42110030 +#define FLASH_ROM_DATA 0x42150000 + +static const u32 MIU_TEST_READ_DATA[] = { + 0x410000A8, 0x410000AC, 0x410000B8, 0x410000BC, }; + +#define QLCNIC_FW_DUMP_REG1 0x00130060 +#define QLCNIC_FW_DUMP_REG2 0x001e0000 +#define QLCNIC_FLASH_SEM2_LK 0x0013C010 +#define QLCNIC_FLASH_SEM2_ULK 0x0013C014 +#define QLCNIC_FLASH_LOCK_ID 0x001B2100 + +#define QLCNIC_RD_DUMP_REG(addr, bar0, data) do { \ + writel((addr & 0xFFFF0000), (void *) (bar0 + \ + QLCNIC_FW_DUMP_REG1)); \ + readl((void *) (bar0 + QLCNIC_FW_DUMP_REG1)); \ + *data = readl((void *) (bar0 + QLCNIC_FW_DUMP_REG2 + \ + LSW(addr))); \ +} while (0) + +#define QLCNIC_WR_DUMP_REG(addr, bar0, data) do { \ + writel((addr & 0xFFFF0000), (void *) (bar0 + \ + QLCNIC_FW_DUMP_REG1)); \ + readl((void *) (bar0 + QLCNIC_FW_DUMP_REG1)); \ + writel(data, (void *) (bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr)));\ + readl((void *) (bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr))); \ +} while (0) + /* PCI function operational mode */ enum { QLCNIC_MGMT_FUNC = 0, diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index cbb27f2df008..e9656616f2a2 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -9,6 +9,7 @@ #include #include +#include #define MASK(n) ((1ULL<<(n))-1) #define OCM_WIN_P3P(addr) (addr & 0xffc0000) @@ -1261,3 +1262,461 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) return rv; } + +/* FW dump related functions */ +static u32 +qlcnic_dump_crb(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, + u32 *buffer) +{ + int i; + u32 addr, data; + struct __crb *crb = &entry->region.crb; + void __iomem *base = adapter->ahw->pci_base0; + + addr = crb->addr; + + for (i = 0; i < crb->no_ops; i++) { + QLCNIC_RD_DUMP_REG(addr, base, &data); + *buffer++ = cpu_to_le32(addr); + *buffer++ = cpu_to_le32(data); + addr += crb->stride; + } + return crb->no_ops * 2 * sizeof(u32); +} + +static u32 +qlcnic_dump_ctrl(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, u32 *buffer) +{ + int i, k, timeout = 0; + void __iomem *base = adapter->ahw->pci_base0; + u32 addr, data; + u8 opcode, no_ops; + struct __ctrl *ctr = &entry->region.ctrl; + struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr; + + addr = ctr->addr; + no_ops = ctr->no_ops; + + for (i = 0; i < no_ops; i++) { + k = 0; + opcode = 0; + for (k = 0; k < 8; k++) { + if (!(ctr->opcode & (1 << k))) + continue; + switch (1 << k) { + case QLCNIC_DUMP_WCRB: + QLCNIC_WR_DUMP_REG(addr, base, ctr->val1); + break; + case QLCNIC_DUMP_RWCRB: + QLCNIC_RD_DUMP_REG(addr, base, &data); + QLCNIC_WR_DUMP_REG(addr, base, data); + break; + case QLCNIC_DUMP_ANDCRB: + QLCNIC_RD_DUMP_REG(addr, base, &data); + QLCNIC_WR_DUMP_REG(addr, base, + (data & ctr->val2)); + break; + case QLCNIC_DUMP_ORCRB: + QLCNIC_RD_DUMP_REG(addr, base, &data); + QLCNIC_WR_DUMP_REG(addr, base, + (data | ctr->val3)); + break; + case QLCNIC_DUMP_POLLCRB: + while (timeout <= ctr->timeout) { + QLCNIC_RD_DUMP_REG(addr, base, &data); + if ((data & ctr->val2) == ctr->val1) + break; + msleep(1); + timeout++; + } + if (timeout > ctr->timeout) { + dev_info(&adapter->pdev->dev, + "Timed out, aborting poll CRB\n"); + return -EINVAL; + } + break; + case QLCNIC_DUMP_RD_SAVE: + if (ctr->index_a) + addr = t_hdr->saved_state[ctr->index_a]; + QLCNIC_RD_DUMP_REG(addr, base, &data); + t_hdr->saved_state[ctr->index_v] = data; + break; + case QLCNIC_DUMP_WRT_SAVED: + if (ctr->index_v) + data = t_hdr->saved_state[ctr->index_v]; + else + data = ctr->val1; + if (ctr->index_a) + addr = t_hdr->saved_state[ctr->index_a]; + QLCNIC_WR_DUMP_REG(addr, base, data); + break; + case QLCNIC_DUMP_MOD_SAVE_ST: + data = t_hdr->saved_state[ctr->index_v]; + data <<= ctr->shl_val; + data >>= ctr->shr_val; + if (ctr->val2) + data &= ctr->val2; + data |= ctr->val3; + data += ctr->val1; + t_hdr->saved_state[ctr->index_v] = data; + break; + default: + dev_info(&adapter->pdev->dev, + "Unknown opcode\n"); + break; + } + } + addr += ctr->stride; + } + return 0; +} + +static u32 +qlcnic_dump_mux(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, + u32 *buffer) +{ + int loop; + u32 val, data = 0; + struct __mux *mux = &entry->region.mux; + void __iomem *base = adapter->ahw->pci_base0; + + val = mux->val; + for (loop = 0; loop < mux->no_ops; loop++) { + QLCNIC_WR_DUMP_REG(mux->addr, base, val); + QLCNIC_RD_DUMP_REG(mux->read_addr, base, &data); + *buffer++ = cpu_to_le32(val); + *buffer++ = cpu_to_le32(data); + val += mux->val_stride; + } + return 2 * mux->no_ops * sizeof(u32); +} + +static u32 +qlcnic_dump_que(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, + u32 *buffer) +{ + int i, loop; + u32 cnt, addr, data, que_id = 0; + void __iomem *base = adapter->ahw->pci_base0; + struct __queue *que = &entry->region.que; + + addr = que->read_addr; + cnt = que->read_addr_cnt; + + for (loop = 0; loop < que->no_ops; loop++) { + QLCNIC_WR_DUMP_REG(que->sel_addr, base, que_id); + for (i = 0; i < cnt; i++) { + QLCNIC_RD_DUMP_REG(addr, base, &data); + *buffer++ = cpu_to_le32(data); + addr += que->read_addr_stride; + } + que_id += que->stride; + } + return que->no_ops * cnt * sizeof(u32); +} + +static u32 +qlcnic_dump_ocm(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, + u32 *buffer) +{ + int i; + u32 data; + void __iomem *addr; + struct __ocm *ocm = &entry->region.ocm; + + addr = adapter->ahw->pci_base0 + ocm->read_addr; + for (i = 0; i < ocm->no_ops; i++) { + data = readl(addr); + *buffer++ = cpu_to_le32(data); + addr += ocm->read_addr_stride; + } + return ocm->no_ops * sizeof(u32); +} + +static u32 +qlcnic_read_rom(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, + u32 *buffer) +{ + int i, count = 0; + u32 fl_addr, size, val, lck_val, addr; + struct __mem *rom = &entry->region.mem; + void __iomem *base = adapter->ahw->pci_base0; + + fl_addr = rom->addr; + size = rom->size/4; +lock_try: + lck_val = readl(base + QLCNIC_FLASH_SEM2_LK); + if (!lck_val && count < MAX_CTL_CHECK) { + msleep(10); + count++; + goto lock_try; + } + writel(adapter->ahw->pci_func, (base + QLCNIC_FLASH_LOCK_ID)); + for (i = 0; i < size; i++) { + addr = fl_addr & 0xFFFF0000; + QLCNIC_WR_DUMP_REG(FLASH_ROM_WINDOW, base, addr); + addr = LSW(fl_addr) + FLASH_ROM_DATA; + QLCNIC_RD_DUMP_REG(addr, base, &val); + fl_addr += 4; + *buffer++ = cpu_to_le32(val); + } + readl(base + QLCNIC_FLASH_SEM2_ULK); + return rom->size; +} + +static u32 +qlcnic_dump_l1_cache(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, u32 *buffer) +{ + int i; + u32 cnt, val, data, addr; + void __iomem *base = adapter->ahw->pci_base0; + struct __cache *l1 = &entry->region.cache; + + val = l1->init_tag_val; + + for (i = 0; i < l1->no_ops; i++) { + QLCNIC_WR_DUMP_REG(l1->addr, base, val); + QLCNIC_WR_DUMP_REG(l1->ctrl_addr, base, LSW(l1->ctrl_val)); + addr = l1->read_addr; + cnt = l1->read_addr_num; + while (cnt) { + QLCNIC_RD_DUMP_REG(addr, base, &data); + *buffer++ = cpu_to_le32(data); + addr += l1->read_addr_stride; + cnt--; + } + val += l1->stride; + } + return l1->no_ops * l1->read_addr_num * sizeof(u32); +} + +static u32 +qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, u32 *buffer) +{ + int i; + u32 cnt, val, data, addr; + u8 poll_mask, poll_to, time_out = 0; + void __iomem *base = adapter->ahw->pci_base0; + struct __cache *l2 = &entry->region.cache; + + val = l2->init_tag_val; + poll_mask = LSB(MSW(l2->ctrl_val)); + poll_to = MSB(MSW(l2->ctrl_val)); + + for (i = 0; i < l2->no_ops; i++) { + QLCNIC_WR_DUMP_REG(l2->addr, base, val); + do { + QLCNIC_WR_DUMP_REG(l2->ctrl_addr, base, + LSW(l2->ctrl_val)); + QLCNIC_RD_DUMP_REG(l2->ctrl_addr, base, &data); + if (!(data & poll_mask)) + break; + msleep(1); + time_out++; + } while (time_out <= poll_to); + if (time_out > poll_to) + return -EINVAL; + + addr = l2->read_addr; + cnt = l2->read_addr_num; + while (cnt) { + QLCNIC_RD_DUMP_REG(addr, base, &data); + *buffer++ = cpu_to_le32(data); + addr += l2->read_addr_stride; + cnt--; + } + val += l2->stride; + } + return l2->no_ops * l2->read_addr_num * sizeof(u32); +} + +static u32 +qlcnic_read_memory(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, u32 *buffer) +{ + u32 addr, data, test, ret = 0; + int i, reg_read; + struct __mem *mem = &entry->region.mem; + void __iomem *base = adapter->ahw->pci_base0; + + reg_read = mem->size; + addr = mem->addr; + /* check for data size of multiple of 16 and 16 byte alignment */ + if ((addr & 0xf) || (reg_read%16)) { + dev_info(&adapter->pdev->dev, + "Unaligned memory addr:0x%x size:0x%x\n", + addr, reg_read); + return -EINVAL; + } + + mutex_lock(&adapter->ahw->mem_lock); + + while (reg_read != 0) { + QLCNIC_WR_DUMP_REG(MIU_TEST_ADDR_LO, base, addr); + QLCNIC_WR_DUMP_REG(MIU_TEST_ADDR_HI, base, 0); + QLCNIC_WR_DUMP_REG(MIU_TEST_CTR, base, + TA_CTL_ENABLE | TA_CTL_START); + + for (i = 0; i < MAX_CTL_CHECK; i++) { + QLCNIC_RD_DUMP_REG(MIU_TEST_CTR, base, &test); + if (!(test & TA_CTL_BUSY)) + break; + } + if (i == MAX_CTL_CHECK) { + if (printk_ratelimit()) { + dev_err(&adapter->pdev->dev, + "failed to read through agent\n"); + ret = -EINVAL; + goto out; + } + } + for (i = 0; i < 4; i++) { + QLCNIC_RD_DUMP_REG(MIU_TEST_READ_DATA[i], base, &data); + *buffer++ = cpu_to_le32(data); + } + addr += 16; + reg_read -= 16; + ret += 16; + } +out: + mutex_unlock(&adapter->ahw->mem_lock); + return mem->size; +} + +static u32 +qlcnic_dump_nop(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, u32 *buffer) +{ + entry->hdr.flags |= QLCNIC_DUMP_SKIP; + return 0; +} + +struct qlcnic_dump_operations fw_dump_ops[] = { + { QLCNIC_DUMP_NOP, qlcnic_dump_nop }, + { QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb }, + { QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux }, + { QLCNIC_DUMP_QUEUE, qlcnic_dump_que }, + { QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom }, + { QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm }, + { QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl }, + { QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache }, + { QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache }, + { QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache }, + { QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache }, + { QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache }, + { QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache }, + { QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache }, + { QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache }, + { QLCNIC_DUMP_READ_ROM, qlcnic_read_rom }, + { QLCNIC_DUMP_READ_MEM, qlcnic_read_memory }, + { QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl }, + { QLCNIC_DUMP_TLHDR, qlcnic_dump_nop }, + { QLCNIC_DUMP_RDEND, qlcnic_dump_nop }, +}; + +/* Walk the template and collect dump for each entry in the dump template */ +static int +qlcnic_valid_dump_entry(struct device *dev, struct qlcnic_dump_entry *entry, + u32 size) +{ + int ret = 1; + if (size != entry->hdr.cap_size) { + dev_info(dev, + "Invalidate dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n", + entry->hdr.type, entry->hdr.mask, size, entry->hdr.cap_size); + dev_info(dev, "Aborting further dump capture\n"); + ret = 0; + } + return ret; +} + +int qlcnic_dump_fw(struct qlcnic_adapter *adapter) +{ + u32 *buffer; + char mesg[64]; + char *msg[] = {mesg, NULL}; + int i, k, ops_cnt, ops_index, dump_size = 0; + u32 entry_offset, dump, no_entries, buf_offset = 0; + struct qlcnic_dump_entry *entry; + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr; + + if (fw_dump->clr) { + dev_info(&adapter->pdev->dev, + "Previous dump not cleared, not capturing dump\n"); + return -EIO; + } + /* Calculate the size for dump data area only */ + for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++) + if (i & tmpl_hdr->drv_cap_mask) + dump_size += tmpl_hdr->cap_sizes[k]; + if (!dump_size) + return -EIO; + + fw_dump->data = vzalloc(dump_size); + if (!fw_dump->data) { + dev_info(&adapter->pdev->dev, + "Unable to allocate (%d KB) for fw dump\n", + dump_size/1024); + return -ENOMEM; + } + buffer = fw_dump->data; + fw_dump->size = dump_size; + no_entries = tmpl_hdr->num_entries; + ops_cnt = ARRAY_SIZE(fw_dump_ops); + entry_offset = tmpl_hdr->offset; + tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION; + tmpl_hdr->sys_info[1] = adapter->fw_version; + + for (i = 0; i < no_entries; i++) { + entry = (struct qlcnic_dump_entry *) ((void *) tmpl_hdr + + entry_offset); + if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) { + entry->hdr.flags |= QLCNIC_DUMP_SKIP; + entry_offset += entry->hdr.offset; + continue; + } + /* Find the handler for this entry */ + ops_index = 0; + while (ops_index < ops_cnt) { + if (entry->hdr.type == fw_dump_ops[ops_index].opcode) + break; + ops_index++; + } + if (ops_index == ops_cnt) { + dev_info(&adapter->pdev->dev, + "Invalid entry type %d, exiting dump\n", + entry->hdr.type); + goto error; + } + /* Collect dump for this entry */ + dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer); + if (dump && !qlcnic_valid_dump_entry(&adapter->pdev->dev, entry, + dump)) + entry->hdr.flags |= QLCNIC_DUMP_SKIP; + buf_offset += entry->hdr.cap_size; + entry_offset += entry->hdr.offset; + buffer = fw_dump->data + buf_offset; + } + if (dump_size != buf_offset) { + dev_info(&adapter->pdev->dev, + "Captured(%d) and expected size(%d) do not match\n", + buf_offset, dump_size); + goto error; + } else { + fw_dump->clr = 1; + snprintf(mesg, sizeof(mesg), "FW dump for device: %d\n", + adapter->pdev->devfn); + dev_info(&adapter->pdev->dev, "Dump data, %d bytes captured\n", + fw_dump->size); + /* Send a udev event to notify availability of FW dump */ + kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg); + return 0; + } +error: + vfree(fw_dump->data); + return -EINVAL; +} diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index d0f338b01396..5b8bbcf904d5 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -345,7 +345,7 @@ static int qlcnic_wait_rom_done(struct qlcnic_adapter *adapter) } static int do_rom_fast_read(struct qlcnic_adapter *adapter, - int addr, int *valp) + u32 addr, u32 *valp) { QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ADDRESS, addr); QLCWR32(adapter, QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); @@ -398,7 +398,7 @@ qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr, return ret; } -int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, int addr, int *valp) +int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, u32 addr, u32 *valp) { int ret; diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index d6cc4d479591..3ab7d2c7baf2 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -1343,6 +1343,10 @@ static void qlcnic_free_adapter_resources(struct qlcnic_adapter *adapter) kfree(adapter->recv_ctx); adapter->recv_ctx = NULL; + if (adapter->ahw->fw_dump.tmpl_hdr) { + vfree(adapter->ahw->fw_dump.tmpl_hdr); + adapter->ahw->fw_dump.tmpl_hdr = NULL; + } kfree(adapter->ahw); adapter->ahw = NULL; } @@ -1586,6 +1590,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* This will be reset for mezz cards */ adapter->portnum = adapter->ahw->pci_func; + /* Get FW dump template and store it */ + if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC) + qlcnic_fw_cmd_get_minidump_temp(adapter); + err = qlcnic_get_board_info(adapter); if (err) { dev_err(&pdev->dev, "Error getting board config info.\n"); @@ -2825,6 +2833,8 @@ skip_ack_check: set_bit(__QLCNIC_START_FW, &adapter->state); QLCDB(adapter, DRV, "Restarting fw\n"); qlcnic_idc_debug_info(adapter, 0); + QLCDB(adapter, DRV, "Take FW dump\n"); + qlcnic_dump_fw(adapter); } qlcnic_api_unlock(adapter); @@ -2923,7 +2933,7 @@ qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter) } /*Transit to RESET state from READY state only */ -static void +void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) { u32 state; @@ -3515,7 +3525,6 @@ qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj, return size; } - static struct bin_attribute bin_attr_crb = { .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)}, .size = 0, -- cgit v1.2.3-58-ga151 From b3c687317ff5d65017ee431de9ccf80ec1552e3e Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Thu, 12 May 2011 12:48:34 +0000 Subject: qlcnic: Take FW dump via ethtool Driver checks if the previous dump has been cleared before taking the dump. It doesn't take the dump if it is not cleared. Changes from v2: Added lock to protect dump data structures from being mangled while dumping or setting them via ethtool. Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_ethtool.c | 81 +++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index c541461bc12c..9efc690a289f 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -965,6 +965,84 @@ static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl) adapter->msg_enable = msglvl; } +static int +qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + + dump->len = fw_dump->tmpl_hdr->size + fw_dump->size; + dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; + dump->version = adapter->fw_version; + return 0; +} + +static int +qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, + void *buffer) +{ + int i, copy_sz; + u32 *hdr_ptr, *data; + struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + + if (qlcnic_api_lock(adapter)) + return -EIO; + if (!fw_dump->clr) { + netdev_info(netdev, "Dump not available\n"); + qlcnic_api_unlock(adapter); + return -EINVAL; + } + /* Copy template header first */ + copy_sz = fw_dump->tmpl_hdr->size; + hdr_ptr = (u32 *) fw_dump->tmpl_hdr; + data = (u32 *) buffer; + for (i = 0; i < copy_sz/sizeof(u32); i++) + *data++ = cpu_to_le32(*hdr_ptr++); + + /* Copy captured dump data */ + memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size); + dump->len = copy_sz + fw_dump->size; + dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; + + /* Free dump area once data has been captured */ + vfree(fw_dump->data); + fw_dump->data = NULL; + fw_dump->clr = 0; + qlcnic_api_unlock(adapter); + + return 0; +} + +static int +qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) +{ + int ret = 0; + struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + + if (val->flag == QLCNIC_FORCE_FW_DUMP_KEY) { + netdev_info(netdev, "Forcing a FW dump\n"); + qlcnic_dev_request_reset(adapter); + } else { + if (val->flag > QLCNIC_DUMP_MASK_MAX || + val->flag < QLCNIC_DUMP_MASK_MIN) { + netdev_info(netdev, + "Invalid dump level: 0x%x\n", val->flag); + ret = -EINVAL; + goto out; + } + if (qlcnic_api_lock(adapter)) + return -EIO; + fw_dump->tmpl_hdr->drv_cap_mask = val->flag & 0xff; + qlcnic_api_unlock(adapter); + netdev_info(netdev, "Driver mask changed to: 0x%x\n", + fw_dump->tmpl_hdr->drv_cap_mask); + } +out: + return ret; +} + const struct ethtool_ops qlcnic_ethtool_ops = { .get_settings = qlcnic_get_settings, .set_settings = qlcnic_set_settings, @@ -991,4 +1069,7 @@ const struct ethtool_ops qlcnic_ethtool_ops = { .set_phys_id = qlcnic_set_led, .set_msglevel = qlcnic_set_msglevel, .get_msglevel = qlcnic_get_msglevel, + .get_dump_flag = qlcnic_get_dump_flag, + .get_dump_data = qlcnic_get_dump_data, + .set_dump = qlcnic_set_dump, }; -- cgit v1.2.3-58-ga151 From 32f5469b5ed27b6403a91b6ca9bc64d144ae3a5d Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Thu, 12 May 2011 12:48:35 +0000 Subject: qlcnic: Bumped up version number to 5.0.18 Update driver version number Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 689adea62700..480ef5cb6ef9 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -36,8 +36,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 0 -#define _QLCNIC_LINUX_SUBVERSION 17 -#define QLCNIC_LINUX_VERSIONID "5.0.17" +#define _QLCNIC_LINUX_SUBVERSION 18 +#define QLCNIC_LINUX_VERSIONID "5.0.18" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) -- cgit v1.2.3-58-ga151 From c5e631a8d4e305a68465b7334efe9875be8b7033 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Thu, 12 May 2011 18:45:01 +0000 Subject: qeth: convert to hw_features part 2 Set rx csum default to hw checksumming again. Remove sysfs interface for rx csum (checksumming) and TSO (large_send). With the new hw_features it does not work to keep the old sysfs interface in parallel. Convert options.checksum_type to new hw_features. Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 1 - drivers/s390/net/qeth_core_main.c | 1 - drivers/s390/net/qeth_core_mpc.h | 8 --- drivers/s390/net/qeth_l2_main.c | 5 +- drivers/s390/net/qeth_l3.h | 2 - drivers/s390/net/qeth_l3_main.c | 104 +++++++++++++++++-------------------- drivers/s390/net/qeth_l3_sys.c | 106 -------------------------------------- 7 files changed, 49 insertions(+), 178 deletions(-) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 8d6146a107d9..a2e67558a313 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -639,7 +639,6 @@ struct qeth_card_options { struct qeth_ipa_info adp; /*Adapter parameters*/ struct qeth_routing_info route6; struct qeth_ipa_info ipa6; - enum qeth_checksum_types checksum_type; int broadcast_mode; int macaddr_mode; int fake_broadcast; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 85cc53117ea6..4dffdbe9a674 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1039,7 +1039,6 @@ static void qeth_set_intial_options(struct qeth_card *card) { card->options.route4.type = NO_ROUTER; card->options.route6.type = NO_ROUTER; - card->options.checksum_type = QETH_CHECKSUM_DEFAULT; card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS; card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL; card->options.fake_broadcast = 0; diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 07d588867b57..d8988dca8129 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -80,14 +80,6 @@ enum qeth_tr_broadcast_modes { QETH_TR_BROADCAST_LOCAL = 1, }; -/* these values match CHECKSUM_* in include/linux/skbuff.h */ -enum qeth_checksum_types { - SW_CHECKSUMMING = 0, /* TODO: set to bit flag used in IPA Command */ - HW_CHECKSUMMING = 1, - NO_CHECKSUMMING = 2, -}; -#define QETH_CHECKSUM_DEFAULT SW_CHECKSUMMING - /* * Routing stuff */ diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 6fbaacb21943..8ba4c7e1ee3a 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -420,10 +420,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card, case QETH_HEADER_TYPE_LAYER2: skb->pkt_type = PACKET_HOST; skb->protocol = eth_type_trans(skb, skb->dev); - if (card->options.checksum_type == NO_CHECKSUMMING) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; + skb->ip_summed = CHECKSUM_NONE; if (skb->protocol == htons(ETH_P_802_2)) *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; len = skb->len; diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h index e705b27ec7dc..14a43aeb0c2a 100644 --- a/drivers/s390/net/qeth_l3.h +++ b/drivers/s390/net/qeth_l3.h @@ -62,8 +62,6 @@ void qeth_l3_del_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *); int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *); void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions, const u8 *); -int qeth_l3_set_large_send(struct qeth_card *, enum qeth_large_send_types); -int qeth_l3_set_rx_csum(struct qeth_card *, enum qeth_checksum_types); int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *); #endif /* __QETH_L3_H__ */ diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 1496661507ea..18484b586a3e 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1445,34 +1445,30 @@ static int qeth_l3_send_checksum_command(struct qeth_card *card) return 0; } -int qeth_l3_set_rx_csum(struct qeth_card *card, - enum qeth_checksum_types csum_type) +int qeth_l3_set_rx_csum(struct qeth_card *card, int on) { int rc = 0; - if (card->options.checksum_type == HW_CHECKSUMMING) { - if ((csum_type != HW_CHECKSUMMING) && - (card->state != CARD_STATE_DOWN)) { - rc = qeth_l3_send_simple_setassparms(card, - IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0); + if (on) { + if (card->state != CARD_STATE_DOWN) { + if (!qeth_is_supported(card, + IPA_INBOUND_CHECKSUM)) + return -EPERM; + rc = qeth_l3_send_checksum_command(card); if (rc) return -EIO; } card->dev->features |= NETIF_F_RXCSUM; } else { - if (csum_type == HW_CHECKSUMMING) { - if (card->state != CARD_STATE_DOWN) { - if (!qeth_is_supported(card, - IPA_INBOUND_CHECKSUM)) - return -EPERM; - rc = qeth_l3_send_checksum_command(card); - if (rc) - return -EIO; - } + if (card->state != CARD_STATE_DOWN) { + rc = qeth_l3_send_simple_setassparms(card, + IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0); + if (rc) + return -EIO; } card->dev->features &= ~NETIF_F_RXCSUM; } - card->options.checksum_type = csum_type; + return rc; } @@ -1482,32 +1478,34 @@ static int qeth_l3_start_ipa_checksum(struct qeth_card *card) QETH_CARD_TEXT(card, 3, "strtcsum"); - if (card->options.checksum_type == NO_CHECKSUMMING) { - dev_info(&card->gdev->dev, - "Using no checksumming on %s.\n", - QETH_CARD_IFNAME(card)); - return 0; - } - if (card->options.checksum_type == SW_CHECKSUMMING) { - dev_info(&card->gdev->dev, - "Using SW checksumming on %s.\n", - QETH_CARD_IFNAME(card)); - return 0; - } - if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) { - dev_info(&card->gdev->dev, + if (card->dev->features & NETIF_F_RXCSUM) { + /* hw may have changed during offline or recovery */ + if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) { + dev_info(&card->gdev->dev, "Inbound HW Checksumming not " "supported on %s,\ncontinuing " "using Inbound SW Checksumming\n", QETH_CARD_IFNAME(card)); - card->options.checksum_type = SW_CHECKSUMMING; - return 0; - } - rc = qeth_l3_send_checksum_command(card); - if (!rc) - dev_info(&card->gdev->dev, + goto update_feature; + } + + rc = qeth_l3_send_checksum_command(card); + if (!rc) + dev_info(&card->gdev->dev, "HW Checksumming (inbound) enabled\n"); + else + goto update_feature; + } else + dev_info(&card->gdev->dev, + "Using SW checksumming on %s.\n", + QETH_CARD_IFNAME(card)); + return 0; +update_feature: + rtnl_lock(); + card->dev->features &= ~NETIF_F_RXCSUM; + netdev_update_features(card->dev); + rtnl_unlock(); return rc; } @@ -2037,14 +2035,7 @@ static inline int qeth_l3_rebuild_skb(struct qeth_card *card, is_vlan = 1; } - switch (card->options.checksum_type) { - case SW_CHECKSUMMING: - skb->ip_summed = CHECKSUM_NONE; - break; - case NO_CHECKSUMMING: - skb->ip_summed = CHECKSUM_UNNECESSARY; - break; - case HW_CHECKSUMMING: + if (card->dev->features & NETIF_F_RXCSUM) { if ((hdr->hdr.l3.ext_flags & (QETH_HDR_EXT_CSUM_HDR_REQ | QETH_HDR_EXT_CSUM_TRANSP_REQ)) == @@ -2053,7 +2044,8 @@ static inline int qeth_l3_rebuild_skb(struct qeth_card *card, skb->ip_summed = CHECKSUM_UNNECESSARY; else skb->ip_summed = CHECKSUM_NONE; - } + } else + skb->ip_summed = CHECKSUM_NONE; return is_vlan; } @@ -3235,20 +3227,19 @@ static u32 qeth_l3_fix_features(struct net_device *dev, u32 features) static int qeth_l3_set_features(struct net_device *dev, u32 features) { - enum qeth_checksum_types csum_type; struct qeth_card *card = dev->ml_priv; u32 changed = dev->features ^ features; + int on; if (!(changed & NETIF_F_RXCSUM)) return 0; if (features & NETIF_F_RXCSUM) - csum_type = HW_CHECKSUMMING; + on = 1; else - csum_type = SW_CHECKSUMMING; + on = 0; - dev->features = features ^ NETIF_F_RXCSUM; - return qeth_l3_set_rx_csum(card, csum_type); + return qeth_l3_set_rx_csum(card, on); } static const struct ethtool_ops qeth_l3_ethtool_ops = { @@ -3342,6 +3333,12 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD)) card->dev->dev_id = card->info.unique_id & 0xffff; + if (!card->info.guestlan) { + card->dev->hw_features = NETIF_F_SG | + NETIF_F_RXCSUM | NETIF_F_IP_CSUM | + NETIF_F_TSO; + card->dev->features = NETIF_F_RXCSUM; + } } } else if (card->info.type == QETH_CARD_TYPE_IQD) { card->dev = alloc_netdev(0, "hsi%d", ether_setup); @@ -3357,8 +3354,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) card->dev->watchdog_timeo = QETH_TX_TIMEOUT; card->dev->mtu = card->info.initial_mtu; SET_ETHTOOL_OPS(card->dev, &qeth_l3_ethtool_ops); - card->dev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | - NETIF_F_IP_CSUM | NETIF_F_TSO; card->dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; @@ -3382,9 +3377,6 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev) card->discipline.output_handler = (qdio_handler_t *) qeth_qdio_output_handler; card->discipline.recover = qeth_l3_recover; - if ((card->info.type == QETH_CARD_TYPE_OSD) || - (card->info.type == QETH_CARD_TYPE_OSX)) - card->options.checksum_type = HW_CHECKSUMMING; return 0; } diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index bf9f003e3a97..cd99210296e2 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -15,16 +15,6 @@ #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \ struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store) -static const char *qeth_l3_get_checksum_str(struct qeth_card *card) -{ - if (card->options.checksum_type == SW_CHECKSUMMING) - return "sw"; - else if (card->options.checksum_type == HW_CHECKSUMMING) - return "hw"; - else - return "no"; -} - static ssize_t qeth_l3_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route, char *buf) { @@ -295,51 +285,6 @@ out: static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show, qeth_l3_dev_canonical_macaddr_store); -static ssize_t qeth_l3_dev_checksum_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct qeth_card *card = dev_get_drvdata(dev); - - if (!card) - return -EINVAL; - - return sprintf(buf, "%s checksumming\n", - qeth_l3_get_checksum_str(card)); -} - -static ssize_t qeth_l3_dev_checksum_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct qeth_card *card = dev_get_drvdata(dev); - enum qeth_checksum_types csum_type; - char *tmp; - int rc = 0; - - if (!card) - return -EINVAL; - - mutex_lock(&card->conf_mutex); - tmp = strsep((char **) &buf, "\n"); - if (!strcmp(tmp, "sw_checksumming")) - csum_type = SW_CHECKSUMMING; - else if (!strcmp(tmp, "hw_checksumming")) - csum_type = HW_CHECKSUMMING; - else if (!strcmp(tmp, "no_checksumming")) - csum_type = NO_CHECKSUMMING; - else { - rc = -EINVAL; - goto out; - } - - rc = qeth_l3_set_rx_csum(card, csum_type); -out: - mutex_unlock(&card->conf_mutex); - return rc ? rc : count; -} - -static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show, - qeth_l3_dev_checksum_store); - static ssize_t qeth_l3_dev_sniffer_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -402,64 +347,13 @@ out: static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show, qeth_l3_dev_sniffer_store); -static ssize_t qeth_l3_dev_large_send_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct qeth_card *card = dev_get_drvdata(dev); - - if (!card) - return -EINVAL; - - if (!(card->dev->features & NETIF_F_TSO)) - return sprintf(buf, "%s\n", "no"); - else - return sprintf(buf, "%s\n", "TSO"); -} - -static ssize_t qeth_l3_dev_large_send_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct qeth_card *card; - char *tmp; - int enable; - - if (!card) - return -EINVAL; - tmp = strsep((char **) &buf, "\n"); - if (!strcmp(tmp, "no")) - enable = 0; - else if (!strcmp(tmp, "TSO")) - enable = 1; - else - return -EINVAL; - - rtnl_lock(); - - card = dev_get_drvdata(dev); - - if (enable) - card->dev->wanted_features |= NETIF_F_TSO; - else - card->dev->wanted_features &= ~NETIF_F_TSO; - netdev_update_features(card->dev); - - rtnl_unlock(); - - return count; -} - -static DEVICE_ATTR(large_send, 0644, qeth_l3_dev_large_send_show, - qeth_l3_dev_large_send_store); - static struct attribute *qeth_l3_device_attrs[] = { &dev_attr_route4.attr, &dev_attr_route6.attr, &dev_attr_fake_broadcast.attr, &dev_attr_broadcast_mode.attr, &dev_attr_canonical_macaddr.attr, - &dev_attr_checksumming.attr, &dev_attr_sniffer.attr, - &dev_attr_large_send.attr, NULL, }; -- cgit v1.2.3-58-ga151 From 1da74b1c10062eff5f67accb3bcb27fa329a55d6 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Thu, 12 May 2011 18:45:02 +0000 Subject: qeth: add OSA concurrent hardware trap This patch improves FFDC (first failure data capture) by requesting a hardware trace in case the device driver, the hardware or a user detects an error. Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 18 +++++ drivers/s390/net/qeth_core_main.c | 148 ++++++++++++++++++++++++++++++++++++++ drivers/s390/net/qeth_core_mpc.h | 9 ++- drivers/s390/net/qeth_core_sys.c | 61 ++++++++++++++++ drivers/s390/net/qeth_l2_main.c | 16 +++++ drivers/s390/net/qeth_l3_main.c | 53 +++++--------- 6 files changed, 268 insertions(+), 37 deletions(-) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index a2e67558a313..55c6aa1c9704 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -631,6 +631,8 @@ struct qeth_card_info { __u32 csum_mask; __u32 tx_csum_mask; enum qeth_ipa_promisc_modes promisc_mode; + __u32 diagass_support; + __u32 hwtrap; }; struct qeth_card_options { @@ -752,6 +754,14 @@ struct qeth_card_list_struct { rwlock_t rwlock; }; +struct qeth_trap_id { + __u16 lparnr; + char vmname[8]; + __u8 chpid; + __u8 ssid; + __u16 devno; +} __packed; + /*some helper functions*/ #define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "") @@ -786,6 +796,12 @@ static inline void qeth_put_buffer_pool_entry(struct qeth_card *card, list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list); } +static inline int qeth_is_diagass_supported(struct qeth_card *card, + enum qeth_diags_cmds cmd) +{ + return card->info.diagass_support & (__u32)cmd; +} + extern struct ccwgroup_driver qeth_l2_ccwgroup_driver; extern struct ccwgroup_driver qeth_l3_ccwgroup_driver; const char *qeth_get_cardname_short(struct qeth_card *); @@ -871,6 +887,8 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...); int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); int qeth_set_access_ctrl_online(struct qeth_card *card); int qeth_hdr_chk_and_bounce(struct sk_buff *, int); +int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); +int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot); /* exports for OSN */ int qeth_osn_assist(struct net_device *, void *, int); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 4dffdbe9a674..92e37f728e54 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -24,6 +24,7 @@ #include #include +#include #include "qeth_core.h" @@ -349,6 +350,8 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card, card->info.chpid); netif_carrier_on(card->dev); card->lan_online = 1; + if (card->info.hwtrap) + card->info.hwtrap = 2; qeth_schedule_recovery(card); return NULL; case IPA_CMD_MODCCID: @@ -2573,6 +2576,142 @@ int qeth_query_setadapterparms(struct qeth_card *card) } EXPORT_SYMBOL_GPL(qeth_query_setadapterparms); +static int qeth_query_ipassists_cb(struct qeth_card *card, + struct qeth_reply *reply, unsigned long data) +{ + struct qeth_ipa_cmd *cmd; + + QETH_DBF_TEXT(SETUP, 2, "qipasscb"); + + cmd = (struct qeth_ipa_cmd *) data; + if (cmd->hdr.prot_version == QETH_PROT_IPV4) { + card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; + card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; + } else { + card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; + card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; + } + QETH_DBF_TEXT(SETUP, 2, "suppenbl"); + QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_supported); + QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_enabled); + return 0; +} + +int qeth_query_ipassists(struct qeth_card *card, enum qeth_prot_versions prot) +{ + int rc; + struct qeth_cmd_buffer *iob; + + QETH_DBF_TEXT_(SETUP, 2, "qipassi%i", prot); + iob = qeth_get_ipacmd_buffer(card, IPA_CMD_QIPASSIST, prot); + rc = qeth_send_ipa_cmd(card, iob, qeth_query_ipassists_cb, NULL); + return rc; +} +EXPORT_SYMBOL_GPL(qeth_query_ipassists); + +static int qeth_query_setdiagass_cb(struct qeth_card *card, + struct qeth_reply *reply, unsigned long data) +{ + struct qeth_ipa_cmd *cmd; + __u16 rc; + + cmd = (struct qeth_ipa_cmd *)data; + rc = cmd->hdr.return_code; + if (rc) + QETH_CARD_TEXT_(card, 2, "diagq:%x", rc); + else + card->info.diagass_support = cmd->data.diagass.ext; + return 0; +} + +static int qeth_query_setdiagass(struct qeth_card *card) +{ + struct qeth_cmd_buffer *iob; + struct qeth_ipa_cmd *cmd; + + QETH_DBF_TEXT(SETUP, 2, "qdiagass"); + iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0); + cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); + cmd->data.diagass.subcmd_len = 16; + cmd->data.diagass.subcmd = QETH_DIAGS_CMD_QUERY; + return qeth_send_ipa_cmd(card, iob, qeth_query_setdiagass_cb, NULL); +} + +static void qeth_get_trap_id(struct qeth_card *card, struct qeth_trap_id *tid) +{ + unsigned long info = get_zeroed_page(GFP_KERNEL); + struct sysinfo_2_2_2 *info222 = (struct sysinfo_2_2_2 *)info; + struct sysinfo_3_2_2 *info322 = (struct sysinfo_3_2_2 *)info; + struct ccw_dev_id ccwid; + int level, rc; + + tid->chpid = card->info.chpid; + ccw_device_get_id(CARD_RDEV(card), &ccwid); + tid->ssid = ccwid.ssid; + tid->devno = ccwid.devno; + if (!info) + return; + + rc = stsi(NULL, 0, 0, 0); + if (rc == -ENOSYS) + level = rc; + else + level = (((unsigned int) rc) >> 28); + + if ((level >= 2) && (stsi(info222, 2, 2, 2) != -ENOSYS)) + tid->lparnr = info222->lpar_number; + + if ((level >= 3) && (stsi(info322, 3, 2, 2) != -ENOSYS)) { + EBCASC(info322->vm[0].name, sizeof(info322->vm[0].name)); + memcpy(tid->vmname, info322->vm[0].name, sizeof(tid->vmname)); + } + free_page(info); + return; +} + +static int qeth_hw_trap_cb(struct qeth_card *card, + struct qeth_reply *reply, unsigned long data) +{ + struct qeth_ipa_cmd *cmd; + __u16 rc; + + cmd = (struct qeth_ipa_cmd *)data; + rc = cmd->hdr.return_code; + if (rc) + QETH_CARD_TEXT_(card, 2, "trapc:%x", rc); + return 0; +} + +int qeth_hw_trap(struct qeth_card *card, enum qeth_diags_trap_action action) +{ + struct qeth_cmd_buffer *iob; + struct qeth_ipa_cmd *cmd; + + QETH_DBF_TEXT(SETUP, 2, "diagtrap"); + iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0); + cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); + cmd->data.diagass.subcmd_len = 80; + cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRAP; + cmd->data.diagass.type = 1; + cmd->data.diagass.action = action; + switch (action) { + case QETH_DIAGS_TRAP_ARM: + cmd->data.diagass.options = 0x0003; + cmd->data.diagass.ext = 0x00010000 + + sizeof(struct qeth_trap_id); + qeth_get_trap_id(card, + (struct qeth_trap_id *)cmd->data.diagass.cdata); + break; + case QETH_DIAGS_TRAP_DISARM: + cmd->data.diagass.options = 0x0001; + break; + case QETH_DIAGS_TRAP_CAPTURE: + break; + } + return qeth_send_ipa_cmd(card, iob, qeth_hw_trap_cb, NULL); +} +EXPORT_SYMBOL_GPL(qeth_hw_trap); + int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf, unsigned int qdio_error, const char *dbftext) { @@ -3983,6 +4122,15 @@ retriable: QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); goto out; } + + card->options.ipa4.supported_funcs = 0; + card->options.adp.supported_funcs = 0; + card->info.diagass_support = 0; + qeth_query_ipassists(card, QETH_PROT_IPV4); + if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) + qeth_query_setadapterparms(card); + if (qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST)) + qeth_query_setdiagass(card); return 0; out: dev_warn(&card->gdev->dev, "The qeth device driver failed to recover " diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index d8988dca8129..e5a9d1c03839 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -448,6 +448,12 @@ enum qeth_diags_trace_cmds { QETH_DIAGS_CMD_TRACE_QUERY = 0x0010, }; +enum qeth_diags_trap_action { + QETH_DIAGS_TRAP_ARM = 0x01, + QETH_DIAGS_TRAP_DISARM = 0x02, + QETH_DIAGS_TRAP_CAPTURE = 0x04, +}; + struct qeth_ipacmd_diagass { __u32 host_tod2; __u32:32; @@ -457,7 +463,8 @@ struct qeth_ipacmd_diagass { __u8 type; __u8 action; __u16 options; - __u32:32; + __u32 ext; + __u8 cdata[64]; } __attribute__ ((packed)); /* Header for each IPA command */ diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index b5e967cf7e2d..0a8e86c1b0ea 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -530,6 +530,66 @@ out: static DEVICE_ATTR(isolation, 0644, qeth_dev_isolation_show, qeth_dev_isolation_store); +static ssize_t qeth_hw_trap_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct qeth_card *card = dev_get_drvdata(dev); + + if (!card) + return -EINVAL; + if (card->info.hwtrap) + return snprintf(buf, 5, "arm\n"); + else + return snprintf(buf, 8, "disarm\n"); +} + +static ssize_t qeth_hw_trap_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct qeth_card *card = dev_get_drvdata(dev); + int rc = 0; + char *tmp, *curtoken; + int state = 0; + curtoken = (char *)buf; + + if (!card) + return -EINVAL; + + mutex_lock(&card->conf_mutex); + if (card->state == CARD_STATE_SOFTSETUP || card->state == CARD_STATE_UP) + state = 1; + tmp = strsep(&curtoken, "\n"); + + if (!strcmp(tmp, "arm") && !card->info.hwtrap) { + if (state) { + if (qeth_is_diagass_supported(card, + QETH_DIAGS_CMD_TRAP)) { + rc = qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM); + if (!rc) + card->info.hwtrap = 1; + } else + rc = -EINVAL; + } else + card->info.hwtrap = 1; + } else if (!strcmp(tmp, "disarm") && card->info.hwtrap) { + if (state) { + rc = qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); + if (!rc) + card->info.hwtrap = 0; + } else + card->info.hwtrap = 0; + } else if (!strcmp(tmp, "trap") && state && card->info.hwtrap) + rc = qeth_hw_trap(card, QETH_DIAGS_TRAP_CAPTURE); + else + rc = -EINVAL; + + mutex_unlock(&card->conf_mutex); + return rc ? rc : count; +} + +static DEVICE_ATTR(hw_trap, 0644, qeth_hw_trap_show, + qeth_hw_trap_store); + static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value) { @@ -653,6 +713,7 @@ static struct attribute *qeth_device_attrs[] = { &dev_attr_performance_stats.attr, &dev_attr_layer2.attr, &dev_attr_isolation.attr, + &dev_attr_hw_trap.attr, NULL, }; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 8ba4c7e1ee3a..b70b47fbd6cd 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -876,6 +876,7 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev) INIT_LIST_HEAD(&card->vid_list); INIT_LIST_HEAD(&card->mc_list); card->options.layer2 = 1; + card->info.hwtrap = 0; card->discipline.start_poll = qeth_qdio_start_poll; card->discipline.input_handler = (qdio_handler_t *) qeth_qdio_input_handler; @@ -994,6 +995,13 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) if (card->info.type != QETH_CARD_TYPE_OSN) qeth_l2_send_setmac(card, &card->dev->dev_addr[0]); + if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { + if (card->info.hwtrap && + qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM)) + card->info.hwtrap = 0; + } else + card->info.hwtrap = 0; + card->state = CARD_STATE_HARDSETUP; memset(&card->rx, 0, sizeof(struct qeth_rx)); qeth_print_status_message(card); @@ -1092,6 +1100,10 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, if (card->dev && netif_carrier_ok(card->dev)) netif_carrier_off(card->dev); recover_flag = card->state; + if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { + qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); + card->info.hwtrap = 1; + } qeth_l2_stop_card(card, recovery_mode); rc = ccw_device_set_offline(CARD_DDEV(card)); rc2 = ccw_device_set_offline(CARD_WDEV(card)); @@ -1157,6 +1169,8 @@ static void __exit qeth_l2_exit(void) static void qeth_l2_shutdown(struct ccwgroup_device *gdev) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); + if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap) + qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); qeth_qdio_clear_card(card, 0); qeth_clear_qdio_buffers(card); } @@ -1172,6 +1186,8 @@ static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev) if (gdev->state == CCWGROUP_OFFLINE) return 0; if (card->state == CARD_STATE_UP) { + if (card->info.hwtrap) + qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); __qeth_l2_set_offline(card->gdev, 1); } else __qeth_l2_set_offline(card->gdev, 0); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 18484b586a3e..bbe7e1c058ab 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1277,39 +1277,6 @@ static int qeth_l3_start_ipa_multicast(struct qeth_card *card) return rc; } -static int qeth_l3_query_ipassists_cb(struct qeth_card *card, - struct qeth_reply *reply, unsigned long data) -{ - struct qeth_ipa_cmd *cmd; - - QETH_DBF_TEXT(SETUP, 2, "qipasscb"); - - cmd = (struct qeth_ipa_cmd *) data; - if (cmd->hdr.prot_version == QETH_PROT_IPV4) { - card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; - card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; - } else { - card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; - card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; - } - QETH_DBF_TEXT(SETUP, 2, "suppenbl"); - QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_supported); - QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_enabled); - return 0; -} - -static int qeth_l3_query_ipassists(struct qeth_card *card, - enum qeth_prot_versions prot) -{ - int rc; - struct qeth_cmd_buffer *iob; - - QETH_DBF_TEXT_(SETUP, 2, "qipassi%i", prot); - iob = qeth_get_ipacmd_buffer(card, IPA_CMD_QIPASSIST, prot); - rc = qeth_send_ipa_cmd(card, iob, qeth_l3_query_ipassists_cb, NULL); - return rc; -} - #ifdef CONFIG_QETH_IPV6 static int qeth_l3_softsetup_ipv6(struct qeth_card *card) { @@ -1320,7 +1287,7 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card) if (card->info.type == QETH_CARD_TYPE_IQD) goto out; - rc = qeth_l3_query_ipassists(card, QETH_PROT_IPV6); + rc = qeth_query_ipassists(card, QETH_PROT_IPV6); if (rc) { dev_err(&card->gdev->dev, "Activating IPv6 support for %s failed\n", @@ -3371,6 +3338,7 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev) qeth_l3_create_device_attributes(&gdev->dev); card->options.layer2 = 0; + card->info.hwtrap = 0; card->discipline.start_poll = qeth_qdio_start_poll; card->discipline.input_handler = (qdio_handler_t *) qeth_qdio_input_handler; @@ -3422,13 +3390,18 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) goto out_remove; } - qeth_l3_query_ipassists(card, QETH_PROT_IPV4); - if (!card->dev && qeth_l3_setup_netdev(card)) { rc = -ENODEV; goto out_remove; } + if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { + if (card->info.hwtrap && + qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM)) + card->info.hwtrap = 0; + } else + card->info.hwtrap = 0; + card->state = CARD_STATE_HARDSETUP; memset(&card->rx, 0, sizeof(struct qeth_rx)); qeth_print_status_message(card); @@ -3530,6 +3503,10 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, if (card->dev && netif_carrier_ok(card->dev)) netif_carrier_off(card->dev); recover_flag = card->state; + if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { + qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); + card->info.hwtrap = 1; + } qeth_l3_stop_card(card, recovery_mode); rc = ccw_device_set_offline(CARD_DDEV(card)); rc2 = ccw_device_set_offline(CARD_WDEV(card)); @@ -3585,6 +3562,8 @@ static int qeth_l3_recover(void *ptr) static void qeth_l3_shutdown(struct ccwgroup_device *gdev) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); + if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap) + qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); qeth_qdio_clear_card(card, 0); qeth_clear_qdio_buffers(card); } @@ -3600,6 +3579,8 @@ static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev) if (gdev->state == CCWGROUP_OFFLINE) return 0; if (card->state == CARD_STATE_UP) { + if (card->info.hwtrap) + qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); __qeth_l3_set_offline(card->gdev, 1); } else __qeth_l3_set_offline(card->gdev, 0); -- cgit v1.2.3-58-ga151 From 3e70b3b8141c1a09e3a8809d94a0157756cb8f60 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 12 May 2011 18:45:03 +0000 Subject: qeth: add owner to ccw driver Fill in the owner of qeth's ccw device driver. Signed-off-by: Sebastian Ott Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 92e37f728e54..503678a30981 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -4041,6 +4041,7 @@ MODULE_DEVICE_TABLE(ccw, qeth_ids); static struct ccw_driver qeth_ccw_driver = { .driver = { + .owner = THIS_MODULE, .name = "qeth", }, .ids = qeth_ids, -- cgit v1.2.3-58-ga151 From 38ed18ff5ed170a68f334c2362735c1268cec81b Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 12 May 2011 18:45:04 +0000 Subject: claw: remove unused return code handling Remove unused return code handling. The claw driver is mostly dead, so just make sure it keeps compiling without warnings. Signed-off-by: Heiko Carstens Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/claw.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index da8aa75bb20b..f1fa2483ae6b 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -845,12 +845,10 @@ claw_irq_tasklet ( unsigned long data ) { struct chbk * p_ch; struct net_device *dev; - struct claw_privbk * privptr; p_ch = (struct chbk *) data; dev = (struct net_device *)p_ch->ndev; CLAW_DBF_TEXT(4, trace, "IRQtask"); - privptr = (struct claw_privbk *)dev->ml_priv; unpack_read(dev); clear_bit(CLAW_BH_ACTIVE, (void *)&p_ch->flag_a); CLAW_DBF_TEXT(4, trace, "TskletXt"); @@ -1026,7 +1024,6 @@ claw_write_next ( struct chbk * p_ch ) struct net_device *dev; struct claw_privbk *privptr=NULL; struct sk_buff *pk_skb; - int rc; CLAW_DBF_TEXT(4, trace, "claw_wrt"); if (p_ch->claw_state == CLAW_STOP) @@ -1038,7 +1035,7 @@ claw_write_next ( struct chbk * p_ch ) !skb_queue_empty(&p_ch->collect_queue)) { pk_skb = claw_pack_skb(privptr); while (pk_skb != NULL) { - rc = claw_hw_tx( pk_skb, dev,1); + claw_hw_tx(pk_skb, dev, 1); if (privptr->write_free_count > 0) { pk_skb = claw_pack_skb(privptr); } else @@ -1322,15 +1319,12 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid) unsigned char *pDataAddress; struct endccw *pEnd; struct ccw1 tempCCW; - struct chbk *p_ch; struct claw_env *p_env; - int lock; struct clawph *pk_head; struct chbk *ch; CLAW_DBF_TEXT(4, trace, "hw_tx"); privptr = (struct claw_privbk *)(dev->ml_priv); - p_ch = (struct chbk *)&privptr->channel[WRITE_CHANNEL]; p_env =privptr->p_env; claw_free_wrt_buf(dev); /* Clean up free chain if posible */ /* scan the write queue to free any completed write packets */ @@ -1511,12 +1505,6 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid) } /* endif (p_first_ccw!=NULL) */ dev_kfree_skb_any(skb); - if (linkid==0) { - lock=LOCK_NO; - } - else { - lock=LOCK_YES; - } claw_strt_out_IO(dev ); /* if write free count is zero , set NOBUFFER */ if (privptr->write_free_count==0) { @@ -2821,15 +2809,11 @@ claw_free_wrt_buf( struct net_device *dev ) { struct claw_privbk *privptr = (struct claw_privbk *)dev->ml_priv; - struct ccwbk*p_first_ccw; - struct ccwbk*p_last_ccw; struct ccwbk*p_this_ccw; struct ccwbk*p_next_ccw; CLAW_DBF_TEXT(4, trace, "freewrtb"); /* scan the write queue to free any completed write packets */ - p_first_ccw=NULL; - p_last_ccw=NULL; p_this_ccw=privptr->p_write_active_first; while ( (p_this_ccw!=NULL) && (p_this_ccw->header.flag!=CLAW_PENDING)) { @@ -3072,7 +3056,7 @@ claw_shutdown_device(struct ccwgroup_device *cgdev) { struct claw_privbk *priv; struct net_device *ndev; - int ret; + int ret = 0; CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev)); priv = dev_get_drvdata(&cgdev->dev); @@ -3095,7 +3079,7 @@ claw_shutdown_device(struct ccwgroup_device *cgdev) } ccw_device_set_offline(cgdev->cdev[1]); ccw_device_set_offline(cgdev->cdev[0]); - return 0; + return ret; } static void -- cgit v1.2.3-58-ga151 From 424f73b3ecc41367336ce75cc489c1e373c421fc Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 12 May 2011 18:45:05 +0000 Subject: lcs: get rid of compile warning -Wunused-but-set-variable generates a compile warning for lcs' tasklet function. Invoked functions contain already error handling; thus additional return code checking is not needed here. Signed-off-by: Heiko Carstens Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/lcs.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 49d1cfc3217e..c3b8064a102d 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -1483,7 +1483,6 @@ lcs_tasklet(unsigned long data) struct lcs_channel *channel; struct lcs_buffer *iob; int buf_idx; - int rc; channel = (struct lcs_channel *) data; LCS_DBF_TEXT_(5, trace, "tlet%s", dev_name(&channel->ccwdev->dev)); @@ -1500,14 +1499,11 @@ lcs_tasklet(unsigned long data) channel->buf_idx = buf_idx; if (channel->state == LCS_CH_STATE_STOPPED) - // FIXME: what if rc != 0 ?? - rc = lcs_start_channel(channel); + lcs_start_channel(channel); spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); if (channel->state == LCS_CH_STATE_SUSPENDED && - channel->iob[channel->io_idx].state == LCS_BUF_STATE_READY) { - // FIXME: what if rc != 0 ?? - rc = __lcs_resume_channel(channel); - } + channel->iob[channel->io_idx].state == LCS_BUF_STATE_READY) + __lcs_resume_channel(channel); spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); /* Something happened on the channel. Wake up waiters. */ -- cgit v1.2.3-58-ga151 From ff2aed7da18781bb32ce675e4621475e4baae08f Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Thu, 12 May 2011 18:45:06 +0000 Subject: ctcm: get rid of compile warning -Wunused-but-set-variable generates compile warnings. The affected variables are removed. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/ctcm_main.c | 2 -- drivers/s390/net/ctcm_mpc.c | 13 ++++--------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index c189296763a4..426787efc492 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -672,7 +672,6 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) int ccw_idx; unsigned long hi; unsigned long saveflags = 0; /* avoids compiler warning */ - __u16 block_len; CTCM_PR_DEBUG("Enter %s: %s, cp=%i ch=0x%p id=%s state=%s\n", __func__, dev->name, smp_processor_id(), ch, @@ -719,7 +718,6 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) */ atomic_inc(&skb->users); - block_len = skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH; /* * IDAL support in CTCM is broken, so we have to * care about skb's above 2G ourselves. diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index b64881f33f23..da4c747335e7 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c @@ -653,7 +653,6 @@ static void ctcmpc_send_sweep_resp(struct channel *rch) struct net_device *dev = rch->netdev; struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; - int rc = 0; struct th_sweep *header; struct sk_buff *sweep_skb; struct channel *ch = priv->channel[CTCM_WRITE]; @@ -665,16 +664,14 @@ static void ctcmpc_send_sweep_resp(struct channel *rch) CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, "%s(%s): sweep_skb allocation ERROR\n", CTCM_FUNTAIL, rch->id); - rc = -ENOMEM; - goto done; + goto done; } header = kmalloc(sizeof(struct th_sweep), gfp_type()); if (!header) { dev_kfree_skb_any(sweep_skb); - rc = -ENOMEM; - goto done; + goto done; } header->th.th_seg = 0x00 ; @@ -1370,8 +1367,7 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg) struct net_device *dev = arg; struct ctcm_priv *priv; struct mpc_group *grp; - int rc = 0; - struct channel *wch, *rch; + struct channel *wch; BUG_ON(dev == NULL); CTCM_PR_DEBUG("Enter %s: %s\n", __func__, dev->name); @@ -1396,7 +1392,6 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg) fsm_deltimer(&priv->restart_timer); wch = priv->channel[CTCM_WRITE]; - rch = priv->channel[CTCM_READ]; switch (grp->saved_state) { case MPCG_STATE_RESET: @@ -1435,7 +1430,7 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg) if (grp->send_qllc_disc == 1) { grp->send_qllc_disc = 0; - rc = mpc_send_qllc_discontact(dev); + mpc_send_qllc_discontact(dev); } /* DO NOT issue DEV_EVENT_STOP directly out of this code */ -- cgit v1.2.3-58-ga151 From 5db79c0679e542a156de54e97be8901aeaa7638a Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Thu, 12 May 2011 18:45:07 +0000 Subject: iucv: get rid of compile warning -Wunused-but-set-variable generates a compile warning. The affected variable is removed. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- net/iucv/iucv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 8f156bd86be7..6c1483f90b46 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -828,14 +828,14 @@ EXPORT_SYMBOL(iucv_unregister); static int iucv_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) { - int i, rc; + int i; get_online_cpus(); on_each_cpu(iucv_block_cpu, NULL, 1); preempt_disable(); for (i = 0; i < iucv_max_pathid; i++) { if (iucv_path_table[i]) - rc = iucv_sever_pathid(i, NULL); + iucv_sever_pathid(i, NULL); } preempt_enable(); put_online_cpus(); -- cgit v1.2.3-58-ga151 From 9f6298a6ca38e251aa72a6035a8a36a52cf94536 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Thu, 12 May 2011 18:45:08 +0000 Subject: af_iucv: get rid of compile warning -Wunused-but-set-variable generates compile warnings. The affected variables are removed. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- net/iucv/af_iucv.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 986b2a5e8769..e2013e434d03 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -190,7 +190,6 @@ static int afiucv_pm_freeze(struct device *dev) */ static int afiucv_pm_restore_thaw(struct device *dev) { - struct iucv_sock *iucv; struct sock *sk; struct hlist_node *node; @@ -199,7 +198,6 @@ static int afiucv_pm_restore_thaw(struct device *dev) #endif read_lock(&iucv_sk_list.lock); sk_for_each(sk, node, &iucv_sk_list.head) { - iucv = iucv_sk(sk); switch (sk->sk_state) { case IUCV_CONNECTED: sk->sk_err = EPIPE; @@ -381,7 +379,6 @@ static void iucv_sock_close(struct sock *sk) { unsigned char user_data[16]; struct iucv_sock *iucv = iucv_sk(sk); - int err; unsigned long timeo; iucv_sock_clear_timer(sk); @@ -394,8 +391,6 @@ static void iucv_sock_close(struct sock *sk) case IUCV_CONNECTED: case IUCV_DISCONN: - err = 0; - sk->sk_state = IUCV_CLOSING; sk->sk_state_change(sk); @@ -404,7 +399,7 @@ static void iucv_sock_close(struct sock *sk) timeo = sk->sk_lingertime; else timeo = IUCV_DISCONN_TIMEOUT; - err = iucv_sock_wait(sk, + iucv_sock_wait(sk, iucv_sock_in_state(sk, IUCV_CLOSED, 0), timeo); } @@ -417,7 +412,7 @@ static void iucv_sock_close(struct sock *sk) low_nmcpy(user_data, iucv->src_name); high_nmcpy(user_data, iucv->dst_name); ASCEBC(user_data, sizeof(user_data)); - err = iucv_path_sever(iucv->path, user_data); + iucv_path_sever(iucv->path, user_data); iucv_path_free(iucv->path); iucv->path = NULL; } -- cgit v1.2.3-58-ga151 From f20190302e3e697a166cc28ebef43058749dedda Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Thu, 12 May 2011 18:45:09 +0000 Subject: convert old cpumask API into new one Adapt new API. Signed-off-by: KOSAKI Motohiro Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- net/iucv/iucv.c | 73 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 6c1483f90b46..a15c01524959 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -128,8 +128,8 @@ struct iucv_irq_list { }; static struct iucv_irq_data *iucv_irq_data[NR_CPUS]; -static cpumask_t iucv_buffer_cpumask = CPU_MASK_NONE; -static cpumask_t iucv_irq_cpumask = CPU_MASK_NONE; +static cpumask_t iucv_buffer_cpumask = { CPU_BITS_NONE }; +static cpumask_t iucv_irq_cpumask = { CPU_BITS_NONE }; /* * Queue of interrupt buffers lock for delivery via the tasklet @@ -406,7 +406,7 @@ static void iucv_allow_cpu(void *data) parm->set_mask.ipmask = 0xf8; iucv_call_b2f0(IUCV_SETCONTROLMASK, parm); /* Set indication that iucv interrupts are allowed for this cpu. */ - cpu_set(cpu, iucv_irq_cpumask); + cpumask_set_cpu(cpu, &iucv_irq_cpumask); } /** @@ -426,7 +426,7 @@ static void iucv_block_cpu(void *data) iucv_call_b2f0(IUCV_SETMASK, parm); /* Clear indication that iucv interrupts are allowed for this cpu. */ - cpu_clear(cpu, iucv_irq_cpumask); + cpumask_clear_cpu(cpu, &iucv_irq_cpumask); } /** @@ -451,7 +451,7 @@ static void iucv_block_cpu_almost(void *data) iucv_call_b2f0(IUCV_SETCONTROLMASK, parm); /* Clear indication that iucv interrupts are allowed for this cpu. */ - cpu_clear(cpu, iucv_irq_cpumask); + cpumask_clear_cpu(cpu, &iucv_irq_cpumask); } /** @@ -466,7 +466,7 @@ static void iucv_declare_cpu(void *data) union iucv_param *parm; int rc; - if (cpu_isset(cpu, iucv_buffer_cpumask)) + if (cpumask_test_cpu(cpu, &iucv_buffer_cpumask)) return; /* Declare interrupt buffer. */ @@ -499,9 +499,9 @@ static void iucv_declare_cpu(void *data) } /* Set indication that an iucv buffer exists for this cpu. */ - cpu_set(cpu, iucv_buffer_cpumask); + cpumask_set_cpu(cpu, &iucv_buffer_cpumask); - if (iucv_nonsmp_handler == 0 || cpus_empty(iucv_irq_cpumask)) + if (iucv_nonsmp_handler == 0 || cpumask_empty(&iucv_irq_cpumask)) /* Enable iucv interrupts on this cpu. */ iucv_allow_cpu(NULL); else @@ -520,7 +520,7 @@ static void iucv_retrieve_cpu(void *data) int cpu = smp_processor_id(); union iucv_param *parm; - if (!cpu_isset(cpu, iucv_buffer_cpumask)) + if (!cpumask_test_cpu(cpu, &iucv_buffer_cpumask)) return; /* Block iucv interrupts. */ @@ -531,7 +531,7 @@ static void iucv_retrieve_cpu(void *data) iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm); /* Clear indication that an iucv buffer exists for this cpu. */ - cpu_clear(cpu, iucv_buffer_cpumask); + cpumask_clear_cpu(cpu, &iucv_buffer_cpumask); } /** @@ -546,8 +546,8 @@ static void iucv_setmask_mp(void) get_online_cpus(); for_each_online_cpu(cpu) /* Enable all cpus with a declared buffer. */ - if (cpu_isset(cpu, iucv_buffer_cpumask) && - !cpu_isset(cpu, iucv_irq_cpumask)) + if (cpumask_test_cpu(cpu, &iucv_buffer_cpumask) && + !cpumask_test_cpu(cpu, &iucv_irq_cpumask)) smp_call_function_single(cpu, iucv_allow_cpu, NULL, 1); put_online_cpus(); @@ -564,9 +564,9 @@ static void iucv_setmask_up(void) int cpu; /* Disable all cpu but the first in cpu_irq_cpumask. */ - cpumask = iucv_irq_cpumask; - cpu_clear(first_cpu(iucv_irq_cpumask), cpumask); - for_each_cpu_mask_nr(cpu, cpumask) + cpumask_copy(&cpumask, &iucv_irq_cpumask); + cpumask_clear_cpu(cpumask_first(&iucv_irq_cpumask), &cpumask); + for_each_cpu(cpu, &cpumask) smp_call_function_single(cpu, iucv_block_cpu, NULL, 1); } @@ -593,7 +593,7 @@ static int iucv_enable(void) rc = -EIO; for_each_online_cpu(cpu) smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); - if (cpus_empty(iucv_buffer_cpumask)) + if (cpumask_empty(&iucv_buffer_cpumask)) /* No cpu could declare an iucv buffer. */ goto out; put_online_cpus(); @@ -675,15 +675,16 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self, case CPU_DOWN_PREPARE_FROZEN: if (!iucv_path_table) break; - cpumask = iucv_buffer_cpumask; - cpu_clear(cpu, cpumask); - if (cpus_empty(cpumask)) + cpumask_copy(&cpumask, &iucv_buffer_cpumask); + cpumask_clear_cpu(cpu, &cpumask); + if (cpumask_empty(&cpumask)) /* Can't offline last IUCV enabled cpu. */ return notifier_from_errno(-EINVAL); smp_call_function_single(cpu, iucv_retrieve_cpu, NULL, 1); - if (cpus_empty(iucv_irq_cpumask)) - smp_call_function_single(first_cpu(iucv_buffer_cpumask), - iucv_allow_cpu, NULL, 1); + if (cpumask_empty(&iucv_irq_cpumask)) + smp_call_function_single( + cpumask_first(&iucv_buffer_cpumask), + iucv_allow_cpu, NULL, 1); break; } return NOTIFY_OK; @@ -866,7 +867,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler, int rc; local_bh_disable(); - if (cpus_empty(iucv_buffer_cpumask)) { + if (cpumask_empty(&iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -915,7 +916,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler, spin_lock_bh(&iucv_table_lock); iucv_cleanup_queue(); - if (cpus_empty(iucv_buffer_cpumask)) { + if (cpumask_empty(&iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -975,7 +976,7 @@ int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16]) int rc; local_bh_disable(); - if (cpus_empty(iucv_buffer_cpumask)) { + if (cpumask_empty(&iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1007,7 +1008,7 @@ int iucv_path_resume(struct iucv_path *path, u8 userdata[16]) int rc; local_bh_disable(); - if (cpus_empty(iucv_buffer_cpumask)) { + if (cpumask_empty(&iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1036,7 +1037,7 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16]) int rc; preempt_disable(); - if (cpus_empty(iucv_buffer_cpumask)) { + if (cpumask_empty(&iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1070,7 +1071,7 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg, int rc; local_bh_disable(); - if (cpus_empty(iucv_buffer_cpumask)) { + if (cpumask_empty(&iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1162,7 +1163,7 @@ int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg, if (msg->flags & IUCV_IPRMDATA) return iucv_message_receive_iprmdata(path, msg, flags, buffer, size, residual); - if (cpus_empty(iucv_buffer_cpumask)) { + if (cpumask_empty(&iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1235,7 +1236,7 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg) int rc; local_bh_disable(); - if (cpus_empty(iucv_buffer_cpumask)) { + if (cpumask_empty(&iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1274,7 +1275,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg, int rc; local_bh_disable(); - if (cpus_empty(iucv_buffer_cpumask)) { + if (cpumask_empty(&iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1324,7 +1325,7 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg, union iucv_param *parm; int rc; - if (cpus_empty(iucv_buffer_cpumask)) { + if (cpumask_empty(&iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1411,7 +1412,7 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg, int rc; local_bh_disable(); - if (cpus_empty(iucv_buffer_cpumask)) { + if (cpumask_empty(&iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1888,7 +1889,7 @@ static int iucv_pm_freeze(struct device *dev) printk(KERN_WARNING "iucv_pm_freeze\n"); #endif if (iucv_pm_state != IUCV_PM_FREEZING) { - for_each_cpu_mask_nr(cpu, iucv_irq_cpumask) + for_each_cpu(cpu, &iucv_irq_cpumask) smp_call_function_single(cpu, iucv_block_cpu_almost, NULL, 1); cancel_work_sync(&iucv_work); @@ -1928,7 +1929,7 @@ static int iucv_pm_thaw(struct device *dev) if (rc) goto out; } - if (cpus_empty(iucv_irq_cpumask)) { + if (cpumask_empty(&iucv_irq_cpumask)) { if (iucv_nonsmp_handler) /* enable interrupts on one cpu */ iucv_allow_cpu(NULL); @@ -1961,7 +1962,7 @@ static int iucv_pm_restore(struct device *dev) pr_warning("Suspending Linux did not completely close all IUCV " "connections\n"); iucv_pm_state = IUCV_PM_RESTORING; - if (cpus_empty(iucv_irq_cpumask)) { + if (cpumask_empty(&iucv_irq_cpumask)) { rc = iucv_query_maxconn(); rc = iucv_enable(); if (rc) -- cgit v1.2.3-58-ga151 From 1159024d4c0aafecaa0c6635c55153b4b39cc1c8 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 13 May 2011 09:23:47 -0400 Subject: ssb: fix pcicore build breakage drivers/ssb/main.c:1336: error: 'SSB_PCICORE_BCAST_ADDR' undeclared (first use in this function) drivers/ssb/main.c:1337: error: 'SSB_PCICORE_BCAST_DATA' undeclared (first use in this function) drivers/ssb/main.c:1349: error: 'struct ssb_pcicore' has no member named 'dev' Reported-by: Randy Dunlap Signed-off-by: John W. Linville --- drivers/ssb/main.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index ee2937c41424..f8a13f863217 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -1332,21 +1332,27 @@ EXPORT_SYMBOL(ssb_bus_powerup); static void ssb_broadcast_value(struct ssb_device *dev, u32 address, u32 data) { +#ifdef CONFIG_SSB_DRIVER_PCICORE /* This is used for both, PCI and ChipCommon core, so be careful. */ BUILD_BUG_ON(SSB_PCICORE_BCAST_ADDR != SSB_CHIPCO_BCAST_ADDR); BUILD_BUG_ON(SSB_PCICORE_BCAST_DATA != SSB_CHIPCO_BCAST_DATA); +#endif - ssb_write32(dev, SSB_PCICORE_BCAST_ADDR, address); - ssb_read32(dev, SSB_PCICORE_BCAST_ADDR); /* flush */ - ssb_write32(dev, SSB_PCICORE_BCAST_DATA, data); - ssb_read32(dev, SSB_PCICORE_BCAST_DATA); /* flush */ + ssb_write32(dev, SSB_CHIPCO_BCAST_ADDR, address); + ssb_read32(dev, SSB_CHIPCO_BCAST_ADDR); /* flush */ + ssb_write32(dev, SSB_CHIPCO_BCAST_DATA, data); + ssb_read32(dev, SSB_CHIPCO_BCAST_DATA); /* flush */ } void ssb_commit_settings(struct ssb_bus *bus) { struct ssb_device *dev; +#ifdef CONFIG_SSB_DRIVER_PCICORE dev = bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev; +#else + dev = bus->chipco.dev; +#endif if (WARN_ON(!dev)) return; /* This forces an update of the cached registers. */ -- cgit v1.2.3-58-ga151 From c319b4d76b9e583a5d88d6bf190e079c4e43213d Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 13 May 2011 10:01:00 +0000 Subject: net: ipv4: add IPPROTO_ICMP socket kind This patch adds IPPROTO_ICMP socket kind. It makes it possible to send ICMP_ECHO messages and receive the corresponding ICMP_ECHOREPLY messages without any special privileges. In other words, the patch makes it possible to implement setuid-less and CAP_NET_RAW-less /bin/ping. In order not to increase the kernel's attack surface, the new functionality is disabled by default, but is enabled at bootup by supporting Linux distributions, optionally with restriction to a group or a group range (see below). Similar functionality is implemented in Mac OS X: http://www.manpagez.com/man/4/icmp/ A new ping socket is created with socket(PF_INET, SOCK_DGRAM, PROT_ICMP) Message identifiers (octets 4-5 of ICMP header) are interpreted as local ports. Addresses are stored in struct sockaddr_in. No port numbers are reserved for privileged processes, port 0 is reserved for API ("let the kernel pick a free number"). There is no notion of remote ports, remote port numbers provided by the user (e.g. in connect()) are ignored. Data sent and received include ICMP headers. This is deliberate to: 1) Avoid the need to transport headers values like sequence numbers by other means. 2) Make it easier to port existing programs using raw sockets. ICMP headers given to send() are checked and sanitized. The type must be ICMP_ECHO and the code must be zero (future extensions might relax this, see below). The id is set to the number (local port) of the socket, the checksum is always recomputed. ICMP reply packets received from the network are demultiplexed according to their id's, and are returned by recv() without any modifications. IP header information and ICMP errors of those packets may be obtained via ancillary data (IP_RECVTTL, IP_RETOPTS, and IP_RECVERR). ICMP source quenches and redirects are reported as fake errors via the error queue (IP_RECVERR); the next hop address for redirects is saved to ee_info (in network order). socket(2) is restricted to the group range specified in "/proc/sys/net/ipv4/ping_group_range". It is "1 0" by default, meaning that nobody (not even root) may create ping sockets. Setting it to "100 100" would grant permissions to the single group (to either make /sbin/ping g+s and owned by this group or to grant permissions to the "netadmins" group), "0 4294967295" would enable it for the world, "100 4294967295" would enable it for the users, but not daemons. The existing code might be (in the unlikely case anyone needs it) extended rather easily to handle other similar pairs of ICMP messages (Timestamp/Reply, Information Request/Reply, Address Mask Request/Reply etc.). Userspace ping util & patch for it: http://openwall.info/wiki/people/segoon/ping For Openwall GNU/*/Linux it was the last step on the road to the setuid-less distro. A revision of this patch (for RHEL5/OpenVZ kernels) is in use in Owl-current, such as in the 2011/03/12 LiveCD ISOs: http://mirrors.kernel.org/openwall/Owl/current/iso/ Initially this functionality was written by Pavel Kankovsky for Linux 2.4.32, but unfortunately it was never made public. All ping options (-b, -p, -Q, -R, -s, -t, -T, -M, -I), are tested with the patch. PATCH v3: - switched to flowi4. - minor changes to be consistent with raw sockets code. PATCH v2: - changed ping_debug() to pr_debug(). - removed CONFIG_IP_PING. - removed ping_seq_fops.owner field (unused for procfs). - switched to proc_net_fops_create(). - switched to %pK in seq_printf(). PATCH v1: - fixed checksumming bug. - CAP_NET_RAW may not create icmp sockets anymore. RFC v2: - minor cleanups. - introduced sysctl'able group range to restrict socket(2). Signed-off-by: Vasiliy Kulikov Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 2 + include/net/ping.h | 57 +++ net/ipv4/Makefile | 2 +- net/ipv4/af_inet.c | 22 ++ net/ipv4/icmp.c | 12 +- net/ipv4/ping.c | 937 +++++++++++++++++++++++++++++++++++++++++++++ net/ipv4/sysctl_net_ipv4.c | 80 ++++ 7 files changed, 1110 insertions(+), 2 deletions(-) create mode 100644 include/net/ping.h create mode 100644 net/ipv4/ping.c diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 542195d9469e..d786b4fc02a4 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -54,6 +54,8 @@ struct netns_ipv4 { int sysctl_rt_cache_rebuild_count; int current_rt_cache_rebuild_count; + unsigned int sysctl_ping_group_range[2]; + atomic_t rt_genid; atomic_t dev_addr_genid; diff --git a/include/net/ping.h b/include/net/ping.h new file mode 100644 index 000000000000..23062c369c62 --- /dev/null +++ b/include/net/ping.h @@ -0,0 +1,57 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions for the "ping" module. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _PING_H +#define _PING_H + +#include + +/* PING_HTABLE_SIZE must be power of 2 */ +#define PING_HTABLE_SIZE 64 +#define PING_HTABLE_MASK (PING_HTABLE_SIZE-1) + +#define ping_portaddr_for_each_entry(__sk, node, list) \ + hlist_nulls_for_each_entry(__sk, node, list, sk_nulls_node) + +/* + * gid_t is either uint or ushort. We want to pass it to + * proc_dointvec_minmax(), so it must not be larger than MAX_INT + */ +#define GID_T_MAX (((gid_t)~0U) >> 1) + +struct ping_table { + struct hlist_nulls_head hash[PING_HTABLE_SIZE]; + rwlock_t lock; +}; + +struct ping_iter_state { + struct seq_net_private p; + int bucket; +}; + +extern struct proto ping_prot; + + +extern void ping_rcv(struct sk_buff *); +extern void ping_err(struct sk_buff *, u32 info); + +extern void inet_get_ping_group_range_net(struct net *net, unsigned int *low, unsigned int *high); + +#ifdef CONFIG_PROC_FS +extern int __init ping_proc_init(void); +extern void ping_proc_exit(void); +#endif + +void __init ping_init(void); + + +#endif /* _PING_H */ diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 0dc772d0d125..f2dc69cffb57 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -11,7 +11,7 @@ obj-y := route.o inetpeer.o protocol.o \ datagram.o raw.o udp.o udplite.o \ arp.o icmp.o devinet.o af_inet.o igmp.o \ fib_frontend.o fib_semantics.o fib_trie.o \ - inet_fragment.o + inet_fragment.o ping.o obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o obj-$(CONFIG_PROC_FS) += proc.o diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 851aa056854b..cc1463156cd0 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -105,6 +105,7 @@ #include #include #include +#include #include #include #include @@ -1008,6 +1009,14 @@ static struct inet_protosw inetsw_array[] = .flags = INET_PROTOSW_PERMANENT, }, + { + .type = SOCK_DGRAM, + .protocol = IPPROTO_ICMP, + .prot = &ping_prot, + .ops = &inet_dgram_ops, + .no_check = UDP_CSUM_DEFAULT, + .flags = INET_PROTOSW_REUSE, + }, { .type = SOCK_RAW, @@ -1527,6 +1536,7 @@ static const struct net_protocol udp_protocol = { static const struct net_protocol icmp_protocol = { .handler = icmp_rcv, + .err_handler = ping_err, .no_policy = 1, .netns_ok = 1, }; @@ -1642,6 +1652,10 @@ static int __init inet_init(void) if (rc) goto out_unregister_udp_proto; + rc = proto_register(&ping_prot, 1); + if (rc) + goto out_unregister_raw_proto; + /* * Tell SOCKET that we are alive... */ @@ -1697,6 +1711,8 @@ static int __init inet_init(void) /* Add UDP-Lite (RFC 3828) */ udplite4_register(); + ping_init(); + /* * Set the ICMP layer up */ @@ -1727,6 +1743,8 @@ static int __init inet_init(void) rc = 0; out: return rc; +out_unregister_raw_proto: + proto_unregister(&raw_prot); out_unregister_udp_proto: proto_unregister(&udp_prot); out_unregister_tcp_proto: @@ -1751,11 +1769,15 @@ static int __init ipv4_proc_init(void) goto out_tcp; if (udp4_proc_init()) goto out_udp; + if (ping_proc_init()) + goto out_ping; if (ip_misc_proc_init()) goto out_misc; out: return rc; out_misc: + ping_proc_exit(); +out_ping: udp4_proc_exit(); out_udp: tcp4_proc_exit(); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 3314394f0aab..3f47585aad68 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -83,6 +83,7 @@ #include #include #include +#include #include #include #include @@ -781,6 +782,15 @@ static void icmp_redirect(struct sk_buff *skb) iph->saddr, skb->dev); break; } + + /* Ping wants to see redirects. + * Let's pretend they are errors of sorts... */ + if (iph->protocol == IPPROTO_ICMP && + iph->ihl >= 5 && + pskb_may_pull(skb, (iph->ihl<<2)+8)) { + ping_err(skb, icmp_hdr(skb)->un.gateway); + } + out: return; out_err: @@ -1041,7 +1051,7 @@ error: */ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = { [ICMP_ECHOREPLY] = { - .handler = icmp_discard, + .handler = ping_rcv, }, [1] = { .handler = icmp_discard, diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c new file mode 100644 index 000000000000..a77e2d788dac --- /dev/null +++ b/net/ipv4/ping.c @@ -0,0 +1,937 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * "Ping" sockets + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Based on ipv4/udp.c code. + * + * Authors: Vasiliy Kulikov / Openwall (for Linux 2.6), + * Pavel Kankovsky (for Linux 2.4.32) + * + * Pavel gave all rights to bugs to Vasiliy, + * none of the bugs are Pavel's now. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +struct ping_table ping_table __read_mostly; + +u16 ping_port_rover; + +static inline int ping_hashfn(struct net *net, unsigned num, unsigned mask) +{ + int res = (num + net_hash_mix(net)) & mask; + pr_debug("hash(%d) = %d\n", num, res); + return res; +} + +static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table, + struct net *net, unsigned num) +{ + return &table->hash[ping_hashfn(net, num, PING_HTABLE_MASK)]; +} + +static int ping_v4_get_port(struct sock *sk, unsigned short ident) +{ + struct hlist_nulls_node *node; + struct hlist_nulls_head *hlist; + struct inet_sock *isk, *isk2; + struct sock *sk2 = NULL; + + isk = inet_sk(sk); + write_lock_bh(&ping_table.lock); + if (ident == 0) { + u32 i; + u16 result = ping_port_rover + 1; + + for (i = 0; i < (1L << 16); i++, result++) { + if (!result) + result++; /* avoid zero */ + hlist = ping_hashslot(&ping_table, sock_net(sk), + result); + ping_portaddr_for_each_entry(sk2, node, hlist) { + isk2 = inet_sk(sk2); + + if (isk2->inet_num == result) + goto next_port; + } + + /* found */ + ping_port_rover = ident = result; + break; +next_port: + ; + } + if (i >= (1L << 16)) + goto fail; + } else { + hlist = ping_hashslot(&ping_table, sock_net(sk), ident); + ping_portaddr_for_each_entry(sk2, node, hlist) { + isk2 = inet_sk(sk2); + + if ((isk2->inet_num == ident) && + (sk2 != sk) && + (!sk2->sk_reuse || !sk->sk_reuse)) + goto fail; + } + } + + pr_debug("found port/ident = %d\n", ident); + isk->inet_num = ident; + if (sk_unhashed(sk)) { + pr_debug("was not hashed\n"); + sock_hold(sk); + hlist_nulls_add_head(&sk->sk_nulls_node, hlist); + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); + } + write_unlock_bh(&ping_table.lock); + return 0; + +fail: + write_unlock_bh(&ping_table.lock); + return 1; +} + +static void ping_v4_hash(struct sock *sk) +{ + pr_debug("ping_v4_hash(sk->port=%u)\n", inet_sk(sk)->inet_num); + BUG(); /* "Please do not press this button again." */ +} + +static void ping_v4_unhash(struct sock *sk) +{ + struct inet_sock *isk = inet_sk(sk); + pr_debug("ping_v4_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); + if (sk_hashed(sk)) { + struct hlist_nulls_head *hslot; + + hslot = ping_hashslot(&ping_table, sock_net(sk), isk->inet_num); + write_lock_bh(&ping_table.lock); + hlist_nulls_del(&sk->sk_nulls_node); + sock_put(sk); + isk->inet_num = isk->inet_sport = 0; + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); + write_unlock_bh(&ping_table.lock); + } +} + +struct sock *ping_v4_lookup(struct net *net, u32 saddr, u32 daddr, + u16 ident, int dif) +{ + struct hlist_nulls_head *hslot = ping_hashslot(&ping_table, net, ident); + struct sock *sk = NULL; + struct inet_sock *isk; + struct hlist_nulls_node *hnode; + + pr_debug("try to find: num = %d, daddr = %ld, dif = %d\n", + (int)ident, (unsigned long)daddr, dif); + read_lock_bh(&ping_table.lock); + + ping_portaddr_for_each_entry(sk, hnode, hslot) { + isk = inet_sk(sk); + + pr_debug("found: %p: num = %d, daddr = %ld, dif = %d\n", sk, + (int)isk->inet_num, (unsigned long)isk->inet_rcv_saddr, + sk->sk_bound_dev_if); + + pr_debug("iterate\n"); + if (isk->inet_num != ident) + continue; + if (isk->inet_rcv_saddr && isk->inet_rcv_saddr != daddr) + continue; + if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) + continue; + + sock_hold(sk); + goto exit; + } + + sk = NULL; +exit: + read_unlock_bh(&ping_table.lock); + + return sk; +} + +static int ping_init_sock(struct sock *sk) +{ + struct net *net = sock_net(sk); + gid_t group = current_egid(); + gid_t range[2]; + struct group_info *group_info = get_current_groups(); + int i, j, count = group_info->ngroups; + + inet_get_ping_group_range_net(net, range, range+1); + if (range[0] <= group && group <= range[1]) + return 0; + + for (i = 0; i < group_info->nblocks; i++) { + int cp_count = min_t(int, NGROUPS_PER_BLOCK, count); + + for (j = 0; j < cp_count; j++) { + group = group_info->blocks[i][j]; + if (range[0] <= group && group <= range[1]) + return 0; + } + + count -= cp_count; + } + + return -EACCES; +} + +static void ping_close(struct sock *sk, long timeout) +{ + pr_debug("ping_close(sk=%p,sk->num=%u)\n", + inet_sk(sk), inet_sk(sk)->inet_num); + pr_debug("isk->refcnt = %d\n", sk->sk_refcnt.counter); + + sk_common_release(sk); +} + +/* + * We need our own bind because there are no privileged id's == local ports. + * Moreover, we don't allow binding to multi- and broadcast addresses. + */ + +static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) +{ + struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; + struct inet_sock *isk = inet_sk(sk); + unsigned short snum; + int chk_addr_ret; + int err; + + if (addr_len < sizeof(struct sockaddr_in)) + return -EINVAL; + + pr_debug("ping_v4_bind(sk=%p,sa_addr=%08x,sa_port=%d)\n", + sk, addr->sin_addr.s_addr, ntohs(addr->sin_port)); + + chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); + if (addr->sin_addr.s_addr == INADDR_ANY) + chk_addr_ret = RTN_LOCAL; + + if ((sysctl_ip_nonlocal_bind == 0 && + isk->freebind == 0 && isk->transparent == 0 && + chk_addr_ret != RTN_LOCAL) || + chk_addr_ret == RTN_MULTICAST || + chk_addr_ret == RTN_BROADCAST) + return -EADDRNOTAVAIL; + + lock_sock(sk); + + err = -EINVAL; + if (isk->inet_num != 0) + goto out; + + err = -EADDRINUSE; + isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr; + snum = ntohs(addr->sin_port); + if (ping_v4_get_port(sk, snum) != 0) { + isk->inet_saddr = isk->inet_rcv_saddr = 0; + goto out; + } + + pr_debug("after bind(): num = %d, daddr = %ld, dif = %d\n", + (int)isk->inet_num, + (unsigned long) isk->inet_rcv_saddr, + (int)sk->sk_bound_dev_if); + + err = 0; + if (isk->inet_rcv_saddr) + sk->sk_userlocks |= SOCK_BINDADDR_LOCK; + if (snum) + sk->sk_userlocks |= SOCK_BINDPORT_LOCK; + isk->inet_sport = htons(isk->inet_num); + isk->inet_daddr = 0; + isk->inet_dport = 0; + sk_dst_reset(sk); +out: + release_sock(sk); + pr_debug("ping_v4_bind -> %d\n", err); + return err; +} + +/* + * Is this a supported type of ICMP message? + */ + +static inline int ping_supported(int type, int code) +{ + if (type == ICMP_ECHO && code == 0) + return 1; + return 0; +} + +/* + * This routine is called by the ICMP module when it gets some + * sort of error condition. + */ + +static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); + +void ping_err(struct sk_buff *skb, u32 info) +{ + struct iphdr *iph = (struct iphdr *)skb->data; + struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2)); + struct inet_sock *inet_sock; + int type = icmph->type; + int code = icmph->code; + struct net *net = dev_net(skb->dev); + struct sock *sk; + int harderr; + int err; + + /* We assume the packet has already been checked by icmp_unreach */ + + if (!ping_supported(icmph->type, icmph->code)) + return; + + pr_debug("ping_err(type=%04x,code=%04x,id=%04x,seq=%04x)\n", type, + code, ntohs(icmph->un.echo.id), ntohs(icmph->un.echo.sequence)); + + sk = ping_v4_lookup(net, iph->daddr, iph->saddr, + ntohs(icmph->un.echo.id), skb->dev->ifindex); + if (sk == NULL) { + ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); + pr_debug("no socket, dropping\n"); + return; /* No socket for error */ + } + pr_debug("err on socket %p\n", sk); + + err = 0; + harderr = 0; + inet_sock = inet_sk(sk); + + switch (type) { + default: + case ICMP_TIME_EXCEEDED: + err = EHOSTUNREACH; + break; + case ICMP_SOURCE_QUENCH: + /* This is not a real error but ping wants to see it. + * Report it with some fake errno. */ + err = EREMOTEIO; + break; + case ICMP_PARAMETERPROB: + err = EPROTO; + harderr = 1; + break; + case ICMP_DEST_UNREACH: + if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */ + if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) { + err = EMSGSIZE; + harderr = 1; + break; + } + goto out; + } + err = EHOSTUNREACH; + if (code <= NR_ICMP_UNREACH) { + harderr = icmp_err_convert[code].fatal; + err = icmp_err_convert[code].errno; + } + break; + case ICMP_REDIRECT: + /* See ICMP_SOURCE_QUENCH */ + err = EREMOTEIO; + break; + } + + /* + * RFC1122: OK. Passes ICMP errors back to application, as per + * 4.1.3.3. + */ + if (!inet_sock->recverr) { + if (!harderr || sk->sk_state != TCP_ESTABLISHED) + goto out; + } else { + ip_icmp_error(sk, skb, err, 0 /* no remote port */, + info, (u8 *)icmph); + } + sk->sk_err = err; + sk->sk_error_report(sk); +out: + sock_put(sk); +} + +/* + * Copy and checksum an ICMP Echo packet from user space into a buffer. + */ + +struct pingfakehdr { + struct icmphdr icmph; + struct iovec *iov; + u32 wcheck; +}; + +static int ping_getfrag(void *from, char * to, + int offset, int fraglen, int odd, struct sk_buff *skb) +{ + struct pingfakehdr *pfh = (struct pingfakehdr *)from; + + if (offset == 0) { + if (fraglen < sizeof(struct icmphdr)) + BUG(); + if (csum_partial_copy_fromiovecend(to + sizeof(struct icmphdr), + pfh->iov, 0, fraglen - sizeof(struct icmphdr), + &pfh->wcheck)) + return -EFAULT; + + return 0; + } + if (offset < sizeof(struct icmphdr)) + BUG(); + if (csum_partial_copy_fromiovecend + (to, pfh->iov, offset - sizeof(struct icmphdr), + fraglen, &pfh->wcheck)) + return -EFAULT; + return 0; +} + +static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, struct flowi4 *fl4) +{ + struct sk_buff *skb = skb_peek(&sk->sk_write_queue); + + pfh->wcheck = csum_partial((char *)&pfh->icmph, + sizeof(struct icmphdr), pfh->wcheck); + pfh->icmph.checksum = csum_fold(pfh->wcheck); + memcpy(icmp_hdr(skb), &pfh->icmph, sizeof(struct icmphdr)); + skb->ip_summed = CHECKSUM_NONE; + return ip_push_pending_frames(sk, fl4); +} + +int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len) +{ + struct net *net = sock_net(sk); + struct flowi4 fl4; + struct inet_sock *inet = inet_sk(sk); + struct ipcm_cookie ipc; + struct icmphdr user_icmph; + struct pingfakehdr pfh; + struct rtable *rt = NULL; + struct ip_options_data opt_copy; + int free = 0; + u32 saddr, daddr, faddr; + u8 tos; + int err; + + pr_debug("ping_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); + + + if (len > 0xFFFF) + return -EMSGSIZE; + + /* + * Check the flags. + */ + + /* Mirror BSD error message compatibility */ + if (msg->msg_flags & MSG_OOB) + return -EOPNOTSUPP; + + /* + * Fetch the ICMP header provided by the userland. + * iovec is modified! + */ + + if (memcpy_fromiovec((u8 *)&user_icmph, msg->msg_iov, + sizeof(struct icmphdr))) + return -EFAULT; + if (!ping_supported(user_icmph.type, user_icmph.code)) + return -EINVAL; + + /* + * Get and verify the address. + */ + + if (msg->msg_name) { + struct sockaddr_in *usin = (struct sockaddr_in *)msg->msg_name; + if (msg->msg_namelen < sizeof(*usin)) + return -EINVAL; + if (usin->sin_family != AF_INET) + return -EINVAL; + daddr = usin->sin_addr.s_addr; + /* no remote port */ + } else { + if (sk->sk_state != TCP_ESTABLISHED) + return -EDESTADDRREQ; + daddr = inet->inet_daddr; + /* no remote port */ + } + + ipc.addr = inet->inet_saddr; + ipc.opt = NULL; + ipc.oif = sk->sk_bound_dev_if; + ipc.tx_flags = 0; + err = sock_tx_timestamp(sk, &ipc.tx_flags); + if (err) + return err; + + if (msg->msg_controllen) { + err = ip_cmsg_send(sock_net(sk), msg, &ipc); + if (err) + return err; + if (ipc.opt) + free = 1; + } + if (!ipc.opt) { + struct ip_options_rcu *inet_opt; + + rcu_read_lock(); + inet_opt = rcu_dereference(inet->inet_opt); + if (inet_opt) { + memcpy(&opt_copy, inet_opt, + sizeof(*inet_opt) + inet_opt->opt.optlen); + ipc.opt = &opt_copy.opt; + } + rcu_read_unlock(); + } + + saddr = ipc.addr; + ipc.addr = faddr = daddr; + + if (ipc.opt && ipc.opt->opt.srr) { + if (!daddr) + return -EINVAL; + faddr = ipc.opt->opt.faddr; + } + tos = RT_TOS(inet->tos); + if (sock_flag(sk, SOCK_LOCALROUTE) || + (msg->msg_flags & MSG_DONTROUTE) || + (ipc.opt && ipc.opt->opt.is_strictroute)) { + tos |= RTO_ONLINK; + } + + if (ipv4_is_multicast(daddr)) { + if (!ipc.oif) + ipc.oif = inet->mc_index; + if (!saddr) + saddr = inet->mc_addr; + } + + flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, + RT_SCOPE_UNIVERSE, sk->sk_protocol, + inet_sk_flowi_flags(sk), faddr, saddr, 0, 0); + + security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); + rt = ip_route_output_flow(net, &fl4, sk); + if (IS_ERR(rt)) { + err = PTR_ERR(rt); + rt = NULL; + if (err == -ENETUNREACH) + IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); + goto out; + } + + err = -EACCES; + if ((rt->rt_flags & RTCF_BROADCAST) && + !sock_flag(sk, SOCK_BROADCAST)) + goto out; + + if (msg->msg_flags & MSG_CONFIRM) + goto do_confirm; +back_from_confirm: + + if (!ipc.addr) + ipc.addr = fl4.daddr; + + lock_sock(sk); + + pfh.icmph.type = user_icmph.type; /* already checked */ + pfh.icmph.code = user_icmph.code; /* ditto */ + pfh.icmph.checksum = 0; + pfh.icmph.un.echo.id = inet->inet_sport; + pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence; + pfh.iov = msg->msg_iov; + pfh.wcheck = 0; + + err = ip_append_data(sk, &fl4, ping_getfrag, &pfh, len, + 0, &ipc, &rt, msg->msg_flags); + if (err) + ip_flush_pending_frames(sk); + else + err = ping_push_pending_frames(sk, &pfh, &fl4); + release_sock(sk); + +out: + ip_rt_put(rt); + if (free) + kfree(ipc.opt); + if (!err) { + icmp_out_count(sock_net(sk), user_icmph.type); + return len; + } + return err; + +do_confirm: + dst_confirm(&rt->dst); + if (!(msg->msg_flags & MSG_PROBE) || len) + goto back_from_confirm; + err = 0; + goto out; +} + +/* + * IOCTL requests applicable to the UDP^H^H^HICMP protocol + */ + +int ping_ioctl(struct sock *sk, int cmd, unsigned long arg) +{ + pr_debug("ping_ioctl(sk=%p,sk->num=%u,cmd=%d,arg=%lu)\n", + inet_sk(sk), inet_sk(sk)->inet_num, cmd, arg); + switch (cmd) { + case SIOCOUTQ: + case SIOCINQ: + return udp_ioctl(sk, cmd, arg); + default: + return -ENOIOCTLCMD; + } +} + +int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int noblock, int flags, int *addr_len) +{ + struct inet_sock *isk = inet_sk(sk); + struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; + struct sk_buff *skb; + int copied, err; + + pr_debug("ping_recvmsg(sk=%p,sk->num=%u)\n", isk, isk->inet_num); + + if (flags & MSG_OOB) + goto out; + + if (addr_len) + *addr_len = sizeof(*sin); + + if (flags & MSG_ERRQUEUE) + return ip_recv_error(sk, msg, len); + + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) + goto out; + + copied = skb->len; + if (copied > len) { + msg->msg_flags |= MSG_TRUNC; + copied = len; + } + + /* Don't bother checking the checksum */ + err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + if (err) + goto done; + + sock_recv_timestamp(msg, sk, skb); + + /* Copy the address. */ + if (sin) { + sin->sin_family = AF_INET; + sin->sin_port = 0 /* skb->h.uh->source */; + sin->sin_addr.s_addr = ip_hdr(skb)->saddr; + memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + } + if (isk->cmsg_flags) + ip_cmsg_recv(msg, skb); + err = copied; + +done: + skb_free_datagram(sk, skb); +out: + pr_debug("ping_recvmsg -> %d\n", err); + return err; +} + +static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) +{ + pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n", + inet_sk(sk), inet_sk(sk)->inet_num, skb); + if (sock_queue_rcv_skb(sk, skb) < 0) { + ICMP_INC_STATS_BH(sock_net(sk), ICMP_MIB_INERRORS); + kfree_skb(skb); + pr_debug("ping_queue_rcv_skb -> failed\n"); + return -1; + } + return 0; +} + + +/* + * All we need to do is get the socket. + */ + +void ping_rcv(struct sk_buff *skb) +{ + struct sock *sk; + struct net *net = dev_net(skb->dev); + struct iphdr *iph = ip_hdr(skb); + struct icmphdr *icmph = icmp_hdr(skb); + u32 saddr = iph->saddr; + u32 daddr = iph->daddr; + + /* We assume the packet has already been checked by icmp_rcv */ + + pr_debug("ping_rcv(skb=%p,id=%04x,seq=%04x)\n", + skb, ntohs(icmph->un.echo.id), ntohs(icmph->un.echo.sequence)); + + /* Push ICMP header back */ + skb_push(skb, skb->data - (u8 *)icmph); + + sk = ping_v4_lookup(net, saddr, daddr, ntohs(icmph->un.echo.id), + skb->dev->ifindex); + if (sk != NULL) { + pr_debug("rcv on socket %p\n", sk); + ping_queue_rcv_skb(sk, skb_get(skb)); + sock_put(sk); + return; + } + pr_debug("no socket, dropping\n"); + + /* We're called from icmp_rcv(). kfree_skb() is done there. */ +} + +struct proto ping_prot = { + .name = "PING", + .owner = THIS_MODULE, + .init = ping_init_sock, + .close = ping_close, + .connect = ip4_datagram_connect, + .disconnect = udp_disconnect, + .ioctl = ping_ioctl, + .setsockopt = ip_setsockopt, + .getsockopt = ip_getsockopt, + .sendmsg = ping_sendmsg, + .recvmsg = ping_recvmsg, + .bind = ping_bind, + .backlog_rcv = ping_queue_rcv_skb, + .hash = ping_v4_hash, + .unhash = ping_v4_unhash, + .get_port = ping_v4_get_port, + .obj_size = sizeof(struct inet_sock), +}; +EXPORT_SYMBOL(ping_prot); + +#ifdef CONFIG_PROC_FS + +static struct sock *ping_get_first(struct seq_file *seq, int start) +{ + struct sock *sk; + struct ping_iter_state *state = seq->private; + struct net *net = seq_file_net(seq); + + for (state->bucket = start; state->bucket < PING_HTABLE_SIZE; + ++state->bucket) { + struct hlist_nulls_node *node; + struct hlist_nulls_head *hslot = &ping_table.hash[state->bucket]; + + if (hlist_nulls_empty(hslot)) + continue; + + sk_nulls_for_each(sk, node, hslot) { + if (net_eq(sock_net(sk), net)) + goto found; + } + } + sk = NULL; +found: + return sk; +} + +static struct sock *ping_get_next(struct seq_file *seq, struct sock *sk) +{ + struct ping_iter_state *state = seq->private; + struct net *net = seq_file_net(seq); + + do { + sk = sk_nulls_next(sk); + } while (sk && (!net_eq(sock_net(sk), net))); + + if (!sk) + return ping_get_first(seq, state->bucket + 1); + return sk; +} + +static struct sock *ping_get_idx(struct seq_file *seq, loff_t pos) +{ + struct sock *sk = ping_get_first(seq, 0); + + if (sk) + while (pos && (sk = ping_get_next(seq, sk)) != NULL) + --pos; + return pos ? NULL : sk; +} + +static void *ping_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct ping_iter_state *state = seq->private; + state->bucket = 0; + + read_lock_bh(&ping_table.lock); + + return *pos ? ping_get_idx(seq, *pos-1) : SEQ_START_TOKEN; +} + +static void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct sock *sk; + + if (v == SEQ_START_TOKEN) + sk = ping_get_idx(seq, 0); + else + sk = ping_get_next(seq, v); + + ++*pos; + return sk; +} + +static void ping_seq_stop(struct seq_file *seq, void *v) +{ + read_unlock_bh(&ping_table.lock); +} + +static void ping_format_sock(struct sock *sp, struct seq_file *f, + int bucket, int *len) +{ + struct inet_sock *inet = inet_sk(sp); + __be32 dest = inet->inet_daddr; + __be32 src = inet->inet_rcv_saddr; + __u16 destp = ntohs(inet->inet_dport); + __u16 srcp = ntohs(inet->inet_sport); + + seq_printf(f, "%5d: %08X:%04X %08X:%04X" + " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d%n", + bucket, src, srcp, dest, destp, sp->sk_state, + sk_wmem_alloc_get(sp), + sk_rmem_alloc_get(sp), + 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), + atomic_read(&sp->sk_refcnt), sp, + atomic_read(&sp->sk_drops), len); +} + +static int ping_seq_show(struct seq_file *seq, void *v) +{ + if (v == SEQ_START_TOKEN) + seq_printf(seq, "%-127s\n", + " sl local_address rem_address st tx_queue " + "rx_queue tr tm->when retrnsmt uid timeout " + "inode ref pointer drops"); + else { + struct ping_iter_state *state = seq->private; + int len; + + ping_format_sock(v, seq, state->bucket, &len); + seq_printf(seq, "%*s\n", 127 - len, ""); + } + return 0; +} + +static const struct seq_operations ping_seq_ops = { + .show = ping_seq_show, + .start = ping_seq_start, + .next = ping_seq_next, + .stop = ping_seq_stop, +}; + +static int ping_seq_open(struct inode *inode, struct file *file) +{ + return seq_open_net(inode, file, &ping_seq_ops, + sizeof(struct ping_iter_state)); +} + +static const struct file_operations ping_seq_fops = { + .open = ping_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_net, +}; + +static int ping_proc_register(struct net *net) +{ + struct proc_dir_entry *p; + int rc = 0; + + p = proc_net_fops_create(net, "icmp", S_IRUGO, &ping_seq_fops); + if (!p) + rc = -ENOMEM; + return rc; +} + +static void ping_proc_unregister(struct net *net) +{ + proc_net_remove(net, "icmp"); +} + + +static int __net_init ping_proc_init_net(struct net *net) +{ + return ping_proc_register(net); +} + +static void __net_exit ping_proc_exit_net(struct net *net) +{ + ping_proc_unregister(net); +} + +static struct pernet_operations ping_net_ops = { + .init = ping_proc_init_net, + .exit = ping_proc_exit_net, +}; + +int __init ping_proc_init(void) +{ + return register_pernet_subsys(&ping_net_ops); +} + +void ping_proc_exit(void) +{ + unregister_pernet_subsys(&ping_net_ops); +} + +#endif + +void __init ping_init(void) +{ + int i; + + for (i = 0; i < PING_HTABLE_SIZE; i++) + INIT_HLIST_NULLS_HEAD(&ping_table.hash[i], i); + rwlock_init(&ping_table.lock); +} diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 321e6e84dbcc..28e8273bbef8 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include static int zero; static int tcp_retr1_max = 255; @@ -30,6 +32,8 @@ static int tcp_adv_win_scale_min = -31; static int tcp_adv_win_scale_max = 31; static int ip_ttl_min = 1; static int ip_ttl_max = 255; +static int ip_ping_group_range_min[] = { 0, 0 }; +static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX }; /* Update system visible IP port range */ static void set_local_port_range(int range[2]) @@ -68,6 +72,65 @@ static int ipv4_local_port_range(ctl_table *table, int write, return ret; } + +void inet_get_ping_group_range_net(struct net *net, gid_t *low, gid_t *high) +{ + gid_t *data = net->ipv4.sysctl_ping_group_range; + unsigned seq; + do { + seq = read_seqbegin(&sysctl_local_ports.lock); + + *low = data[0]; + *high = data[1]; + } while (read_seqretry(&sysctl_local_ports.lock, seq)); +} + +void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, gid_t *high) +{ + gid_t *data = table->data; + unsigned seq; + do { + seq = read_seqbegin(&sysctl_local_ports.lock); + + *low = data[0]; + *high = data[1]; + } while (read_seqretry(&sysctl_local_ports.lock, seq)); +} + +/* Update system visible IP port range */ +static void set_ping_group_range(struct ctl_table *table, int range[2]) +{ + gid_t *data = table->data; + write_seqlock(&sysctl_local_ports.lock); + data[0] = range[0]; + data[1] = range[1]; + write_sequnlock(&sysctl_local_ports.lock); +} + +/* Validate changes from /proc interface. */ +static int ipv4_ping_group_range(ctl_table *table, int write, + void __user *buffer, + size_t *lenp, loff_t *ppos) +{ + int ret; + gid_t range[2]; + ctl_table tmp = { + .data = &range, + .maxlen = sizeof(range), + .mode = table->mode, + .extra1 = &ip_ping_group_range_min, + .extra2 = &ip_ping_group_range_max, + }; + + inet_get_ping_group_range_table(table, range, range + 1); + ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); + + if (write && ret == 0) + set_ping_group_range(table, range); + + return ret; +} + static int proc_tcp_congestion_control(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -677,6 +740,13 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "ping_group_range", + .data = &init_net.ipv4.sysctl_ping_group_range, + .maxlen = sizeof(init_net.ipv4.sysctl_ping_group_range), + .mode = 0644, + .proc_handler = ipv4_ping_group_range, + }, { } }; @@ -711,8 +781,18 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) &net->ipv4.sysctl_icmp_ratemask; table[6].data = &net->ipv4.sysctl_rt_cache_rebuild_count; + table[7].data = + &net->ipv4.sysctl_ping_group_range; + } + /* + * Sane defaults - nobody may create ping sockets. + * Boot scripts should set this to distro-specific group. + */ + net->ipv4.sysctl_ping_group_range[0] = 1; + net->ipv4.sysctl_ping_group_range[1] = 0; + net->ipv4.sysctl_rt_cache_rebuild_count = 4; net->ipv4.ipv4_hdr = register_net_sysctl_table(net, -- cgit v1.2.3-58-ga151 From 5310cbce900094dce5df4a671b411e15319a75d4 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 13 May 2011 04:15:39 +0000 Subject: drivers/isdn/hisax: Drop unused list The file st5481_init.c locally defines and initializes the adapter_list variable, but does not use it for anything. Removing the list makes it possible to remove the list field from the st5481_adapter data structure. In the function probe_st5481, it also makes it possible to free the locally allocated adapter value on an error exit. Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/isdn/hisax/st5481.h | 1 - drivers/isdn/hisax/st5481_init.c | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h index 64f78a8c28c5..b9054cb7a0da 100644 --- a/drivers/isdn/hisax/st5481.h +++ b/drivers/isdn/hisax/st5481.h @@ -377,7 +377,6 @@ struct st5481_bcs { }; struct st5481_adapter { - struct list_head list; int number_of_leds; struct usb_device *usb_dev; struct hisax_d_if hisax_d_if; diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c index 13751237bfcd..9f7fd18ff773 100644 --- a/drivers/isdn/hisax/st5481_init.c +++ b/drivers/isdn/hisax/st5481_init.c @@ -46,8 +46,6 @@ module_param(debug, int, 0); #endif int st5481_debug; -static LIST_HEAD(adapter_list); - /* ====================================================================== * registration/deregistration with the USB layer */ @@ -86,7 +84,6 @@ static int probe_st5481(struct usb_interface *intf, adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i]; adapter->bcs[i].b_if.ifc.l2l1 = st5481_b_l2l1; } - list_add(&adapter->list, &adapter_list); retval = st5481_setup_usb(adapter); if (retval < 0) @@ -125,6 +122,7 @@ static int probe_st5481(struct usb_interface *intf, err_usb: st5481_release_usb(adapter); err: + kfree(adapter); return -EIO; } @@ -142,8 +140,6 @@ static void disconnect_st5481(struct usb_interface *intf) if (!adapter) return; - list_del(&adapter->list); - st5481_stop(adapter); st5481_release_b(&adapter->bcs[1]); st5481_release_b(&adapter->bcs[0]); -- cgit v1.2.3-58-ga151 From 1334cb60826377de8f75adb9902c25302222f4fe Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Thu, 12 May 2011 20:28:04 +0000 Subject: stmmac: don't go through ethtool to start auto-negotiation The driver used to call phy's ethtool configuration routine to start auto-negotiation. This change has it call directly phy's routine to start auto-negotiation. The initial version was hiding phy_start_aneg() return value, this patch returns it (<0 upon error). Tested: module compiles, tested on STM HDK7108 STB. Signed-off-by: David Decotigny Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/stmmac_ethtool.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c index 6f5aaeb986ff..9c05cf07a432 100644 --- a/drivers/net/stmmac/stmmac_ethtool.c +++ b/drivers/net/stmmac/stmmac_ethtool.c @@ -236,17 +236,8 @@ stmmac_set_pauseparam(struct net_device *netdev, priv->flow_ctrl = new_pause; if (phy->autoneg) { - if (netif_running(netdev)) { - struct ethtool_cmd cmd = { .cmd = ETHTOOL_SSET }; - /* auto-negotiation automatically restarted */ - cmd.supported = phy->supported; - cmd.advertising = phy->advertising; - cmd.autoneg = phy->autoneg; - ethtool_cmd_speed_set(&cmd, phy->speed); - cmd.duplex = phy->duplex; - cmd.phy_address = phy->addr; - ret = phy_ethtool_sset(phy, &cmd); - } + if (netif_running(netdev)) + ret = phy_start_aneg(phy); } else priv->hw->mac->flow_ctrl(priv->ioaddr, phy->duplex, priv->flow_ctrl, priv->pause); -- cgit v1.2.3-58-ga151 From 64c7f304b81a9a92dc7046c97a10427a5997dc07 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Thu, 12 May 2011 20:28:05 +0000 Subject: stmmac: fix autoneg in set_pauseparam This patch fixes a bug in the set_pauseparam function that didn't well manage the ANE field and returned broken values when use ethtool -A|-a. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/stmmac_ethtool.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c index 9c05cf07a432..ae5213a8c4cd 100644 --- a/drivers/net/stmmac/stmmac_ethtool.c +++ b/drivers/net/stmmac/stmmac_ethtool.c @@ -234,6 +234,7 @@ stmmac_set_pauseparam(struct net_device *netdev, new_pause |= FLOW_TX; priv->flow_ctrl = new_pause; + phy->autoneg = pause->autoneg; if (phy->autoneg) { if (netif_running(netdev)) -- cgit v1.2.3-58-ga151 From 0696c3a8acd3b7c3186dd231d65d97e05a75189f Mon Sep 17 00:00:00 2001 From: "Peter Pan(潘卫平)" Date: Thu, 12 May 2011 15:46:56 +0000 Subject: net:set valid name before calling ndo_init() In commit 1c5cae815d19 (net: call dev_alloc_name from register_netdevice), a bug of bonding was involved, see example 1 and 2. In register_netdevice(), the name of net_device is not valid until dev_get_valid_name() is called. But dev->netdev_ops->ndo_init(that is bond_init) is called before dev_get_valid_name(), and it uses the invalid name of net_device. I think register_netdevice() should make sure that the name of net_device is valid before calling ndo_init(). example 1: modprobe bonding ls /proc/net/bonding/bond%d ps -eLf root 3398 2 3398 0 1 21:34 ? 00:00:00 [bond%d] example 2: modprobe bonding max_bonds=3 [ 170.100292] bonding: Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011) [ 170.101090] bonding: Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details. [ 170.102469] ------------[ cut here ]------------ [ 170.103150] WARNING: at /home/pwp/net-next-2.6/fs/proc/generic.c:586 proc_register+0x126/0x157() [ 170.104075] Hardware name: VirtualBox [ 170.105065] proc_dir_entry 'bonding/bond%d' already registered [ 170.105613] Modules linked in: bonding(+) sunrpc ipv6 uinput microcode ppdev parport_pc parport joydev e1000 pcspkr i2c_piix4 i2c_core [last unloaded: bonding] [ 170.108397] Pid: 3457, comm: modprobe Not tainted 2.6.39-rc2+ #14 [ 170.108935] Call Trace: [ 170.109382] [] warn_slowpath_common+0x6a/0x7f [ 170.109911] [] ? proc_register+0x126/0x157 [ 170.110329] [] warn_slowpath_fmt+0x2b/0x2f [ 170.110846] [] proc_register+0x126/0x157 [ 170.111870] [] proc_create_data+0x82/0x98 [ 170.112335] [] bond_create_proc_entry+0x3f/0x73 [bonding] [ 170.112905] [] bond_init+0x77/0xa5 [bonding] [ 170.113319] [] register_netdevice+0x8c/0x1d3 [ 170.113848] [] bond_create+0x6c/0x90 [bonding] [ 170.114322] [] bonding_init+0x763/0x7b1 [bonding] [ 170.114879] [] do_one_initcall+0x76/0x122 [ 170.115317] [] ? 0xf94f3fff [ 170.115799] [] sys_init_module+0x1286/0x140d [ 170.116879] [] sysenter_do_call+0x12/0x28 [ 170.117404] ---[ end trace 64e4fac3ae5fff1a ]--- [ 170.117924] bond%d: Warning: failed to register to debugfs [ 170.128728] ------------[ cut here ]------------ [ 170.129360] WARNING: at /home/pwp/net-next-2.6/fs/proc/generic.c:586 proc_register+0x126/0x157() [ 170.130323] Hardware name: VirtualBox [ 170.130797] proc_dir_entry 'bonding/bond%d' already registered [ 170.131315] Modules linked in: bonding(+) sunrpc ipv6 uinput microcode ppdev parport_pc parport joydev e1000 pcspkr i2c_piix4 i2c_core [last unloaded: bonding] [ 170.133731] Pid: 3457, comm: modprobe Tainted: G W 2.6.39-rc2+ #14 [ 170.134308] Call Trace: [ 170.134743] [] warn_slowpath_common+0x6a/0x7f [ 170.135305] [] ? proc_register+0x126/0x157 [ 170.135820] [] warn_slowpath_fmt+0x2b/0x2f [ 170.137168] [] proc_register+0x126/0x157 [ 170.137700] [] proc_create_data+0x82/0x98 [ 170.138174] [] bond_create_proc_entry+0x3f/0x73 [bonding] [ 170.138745] [] bond_init+0x77/0xa5 [bonding] [ 170.139278] [] register_netdevice+0x8c/0x1d3 [ 170.139828] [] bond_create+0x6c/0x90 [bonding] [ 170.140361] [] bonding_init+0x763/0x7b1 [bonding] [ 170.140927] [] do_one_initcall+0x76/0x122 [ 170.141494] [] ? 0xf94f3fff [ 170.141975] [] sys_init_module+0x1286/0x140d [ 170.142463] [] sysenter_do_call+0x12/0x28 [ 170.142974] ---[ end trace 64e4fac3ae5fff1b ]--- [ 170.144949] bond%d: Warning: failed to register to debugfs Signed-off-by: Weiping Pan Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- net/core/dev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index ea23353e6251..3ed09f8ecbf8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5437,6 +5437,10 @@ int register_netdevice(struct net_device *dev) dev->iflink = -1; + ret = dev_get_valid_name(dev, dev->name); + if (ret < 0) + goto out; + /* Init, if this function is available */ if (dev->netdev_ops->ndo_init) { ret = dev->netdev_ops->ndo_init(dev); @@ -5447,10 +5451,6 @@ int register_netdevice(struct net_device *dev) } } - ret = dev_get_valid_name(dev, dev->name); - if (ret < 0) - goto err_uninit; - dev->ifindex = dev_new_index(net); if (dev->iflink == -1) dev->iflink = dev->ifindex; -- cgit v1.2.3-58-ga151 From 48e20467227fe540e6bbf3d98df98c2c0fca10f3 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 13 May 2011 16:50:49 -0400 Subject: olympic: convert to seq_file ->read_proc interface is going away, switch to seq_file. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/net/tokenring/olympic.c | 57 ++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index 2684003b8ab6..e3855aeb13d4 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -86,6 +86,7 @@ #include #include #include +#include #include #include #include @@ -193,7 +194,7 @@ static void olympic_arb_cmd(struct net_device *dev); static int olympic_change_mtu(struct net_device *dev, int mtu); static void olympic_srb_bh(struct net_device *dev) ; static void olympic_asb_bh(struct net_device *dev) ; -static int olympic_proc_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data) ; +static const struct file_operations olympic_proc_ops; static const struct net_device_ops olympic_netdev_ops = { .ndo_open = olympic_open, @@ -272,7 +273,7 @@ static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device char proc_name[20] ; strcpy(proc_name,"olympic_") ; strcat(proc_name,dev->name) ; - create_proc_read_entry(proc_name,0,init_net.proc_net,olympic_proc_info,(void *)dev) ; + proc_create_data(proc_name, 0, init_net.proc_net, &olympic_proc_ops, dev); printk("Olympic: Network Monitor information: /proc/%s\n",proc_name); } return 0 ; @@ -1615,29 +1616,25 @@ static int olympic_change_mtu(struct net_device *dev, int mtu) return 0 ; } -static int olympic_proc_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data) +static int olympic_proc_show(struct seq_file *m, void *v) { - struct net_device *dev = (struct net_device *)data ; + struct net_device *dev = m->private; struct olympic_private *olympic_priv=netdev_priv(dev); u8 __iomem *oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; u8 __iomem *opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; - int size = 0 ; - int len=0; - off_t begin=0; - off_t pos=0; u8 addr[6]; u8 addr2[6]; int i; - size = sprintf(buffer, + seq_printf(m, "IBM Pit/Pit-Phy/Olympic Chipset Token Ring Adapter %s\n",dev->name); - size += sprintf(buffer+size, "\n%6s: Adapter Address : Node Address : Functional Addr\n", + seq_printf(m, "\n%6s: Adapter Address : Node Address : Functional Addr\n", dev->name); for (i = 0 ; i < 6 ; i++) addr[i] = readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr) + i); - size += sprintf(buffer+size, "%6s: %pM : %pM : %02x:%02x:%02x:%02x\n", + seq_printf(m, "%6s: %pM : %pM : %02x:%02x:%02x:%02x\n", dev->name, dev->dev_addr, addr, readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)), @@ -1645,9 +1642,9 @@ static int olympic_proc_info(char *buffer, char **start, off_t offset, int lengt readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+2), readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+3)); - size += sprintf(buffer+size, "\n%6s: Token Ring Parameters Table:\n", dev->name); + seq_printf(m, "\n%6s: Token Ring Parameters Table:\n", dev->name); - size += sprintf(buffer+size, "%6s: Physical Addr : Up Node Address : Poll Address : AccPri : Auth Src : Att Code :\n", + seq_printf(m, "%6s: Physical Addr : Up Node Address : Poll Address : AccPri : Auth Src : Att Code :\n", dev->name) ; for (i = 0 ; i < 6 ; i++) @@ -1655,7 +1652,7 @@ static int olympic_proc_info(char *buffer, char **start, off_t offset, int lengt for (i = 0 ; i < 6 ; i++) addr2[i] = readb(opt+offsetof(struct olympic_parameters_table, poll_addr) + i); - size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x : %pM : %pM : %04x : %04x : %04x :\n", + seq_printf(m, "%6s: %02x:%02x:%02x:%02x : %pM : %pM : %04x : %04x : %04x :\n", dev->name, readb(opt+offsetof(struct olympic_parameters_table, phys_addr)), readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+1), @@ -1666,12 +1663,12 @@ static int olympic_proc_info(char *buffer, char **start, off_t offset, int lengt swab16(readw(opt+offsetof(struct olympic_parameters_table, auth_source_class))), swab16(readw(opt+offsetof(struct olympic_parameters_table, att_code)))); - size += sprintf(buffer+size, "%6s: Source Address : Bcn T : Maj. V : Lan St : Lcl Rg : Mon Err : Frame Correl : \n", + seq_printf(m, "%6s: Source Address : Bcn T : Maj. V : Lan St : Lcl Rg : Mon Err : Frame Correl : \n", dev->name) ; for (i = 0 ; i < 6 ; i++) addr[i] = readb(opt+offsetof(struct olympic_parameters_table, source_addr) + i); - size += sprintf(buffer+size, "%6s: %pM : %04x : %04x : %04x : %04x : %04x : %04x : \n", + seq_printf(m, "%6s: %pM : %04x : %04x : %04x : %04x : %04x : %04x : \n", dev->name, addr, swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_type))), swab16(readw(opt+offsetof(struct olympic_parameters_table, major_vector))), @@ -1680,12 +1677,12 @@ static int olympic_proc_info(char *buffer, char **start, off_t offset, int lengt swab16(readw(opt+offsetof(struct olympic_parameters_table, mon_error))), swab16(readw(opt+offsetof(struct olympic_parameters_table, frame_correl)))); - size += sprintf(buffer+size, "%6s: Beacon Details : Tx : Rx : NAUN Node Address : NAUN Node Phys : \n", + seq_printf(m, "%6s: Beacon Details : Tx : Rx : NAUN Node Address : NAUN Node Phys : \n", dev->name) ; for (i = 0 ; i < 6 ; i++) addr[i] = readb(opt+offsetof(struct olympic_parameters_table, beacon_naun) + i); - size += sprintf(buffer+size, "%6s: : %02x : %02x : %pM : %02x:%02x:%02x:%02x : \n", + seq_printf(m, "%6s: : %02x : %02x : %pM : %02x:%02x:%02x:%02x : \n", dev->name, swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_transmit))), swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_receive))), @@ -1695,19 +1692,21 @@ static int olympic_proc_info(char *buffer, char **start, off_t offset, int lengt readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+2), readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+3)); - len=size; - pos=begin+size; - if (poslength) - len=length; /* Ending slop */ - return len; + return 0; } +static int olympic_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, olympic_proc_show, PDE(inode)->data); +} + +static const struct file_operations olympic_proc_ops = { + .open = olympic_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static void __devexit olympic_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev) ; -- cgit v1.2.3-58-ga151 From 0374d9ceb02eb12fcd65be9dd5df9c911ef93424 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 13 May 2011 17:15:50 -0400 Subject: ipv4: Kill spurious write to iph->daddr in ip_forward_options(). This code block executes when opt->srr_is_hit is set. It will be set only by ip_options_rcv_srr(). ip_options_rcv_srr() walks until it hits a matching nexthop in the SRR option addresses, and when it matches one 1) looks up the route for that nexthop and 2) on route lookup success it writes that nexthop value into iph->daddr. ip_forward_options() runs later, and again walks the SRR option addresses looking for the option matching the destination of the route stored in skb_rtable(). This route will be the same exact one looked up for the nexthop by ip_options_rcv_srr(). Therefore "rt->rt_dst == iph->daddr" must be true. All it really needs to do is record the route's source address in the matching SRR option adddress. It need not write iph->daddr again, since that has already been done by ip_options_rcv_srr() as detailed above. Signed-off-by: David S. Miller --- net/ipv4/ip_options.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index c5c26192b057..c6474cd1cbfa 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -573,7 +573,6 @@ void ip_forward_options(struct sk_buff *skb) if (srrptr + 3 <= srrspace) { opt->is_changed = 1; ip_rt_get_source(&optptr[srrptr-1], rt); - ip_hdr(skb)->daddr = rt->rt_dst; optptr[2] = srrptr+4; } else if (net_ratelimit()) printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n"); -- cgit v1.2.3-58-ga151 From 22f728f8f311659b068e73ed92833c205651a47f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 13 May 2011 17:21:27 -0400 Subject: ipv4: Always call ip_options_build() after rest of IP header is filled in. This will allow ip_options_build() to reliably look at the values of iph->{daddr,saddr} Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 70778d48aa7b..98af3697c718 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1327,10 +1327,6 @@ struct sk_buff *__ip_make_skb(struct sock *sk, iph = (struct iphdr *)skb->data; iph->version = 4; iph->ihl = 5; - if (opt) { - iph->ihl += opt->optlen>>2; - ip_options_build(skb, opt, cork->addr, rt, 0); - } iph->tos = inet->tos; iph->frag_off = df; ip_select_ident(iph, &rt->dst, sk); @@ -1339,6 +1335,11 @@ struct sk_buff *__ip_make_skb(struct sock *sk, iph->saddr = fl4->saddr; iph->daddr = fl4->daddr; + if (opt) { + iph->ihl += opt->optlen>>2; + ip_options_build(skb, opt, cork->addr, rt, 0); + } + skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; /* -- cgit v1.2.3-58-ga151 From 8e36360ae876995e92d3a7538dda70548e64e685 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 13 May 2011 17:29:41 -0400 Subject: ipv4: Remove route key identity dependencies in ip_rt_get_source(). Pass in the sk_buff so that we can fetch the necessary keys from the packet header when working with input routes. Signed-off-by: David S. Miller --- include/net/route.h | 2 +- net/ipv4/ip_options.c | 12 ++++++------ net/ipv4/route.c | 24 ++++++++++++++---------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index 9f8070b251fb..ba0e0840370c 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -189,7 +189,7 @@ extern unsigned inet_addr_type(struct net *net, __be32 addr); extern unsigned inet_dev_addr_type(struct net *net, const struct net_device *dev, __be32 addr); extern void ip_rt_multicast_event(struct in_device *); extern int ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg); -extern void ip_rt_get_source(u8 *src, struct rtable *rt); +extern void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt); extern int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb); struct in_ifaddr; diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index c6474cd1cbfa..89268baabc87 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -37,7 +37,7 @@ */ void ip_options_build(struct sk_buff *skb, struct ip_options *opt, - __be32 daddr, struct rtable *rt, int is_frag) + __be32 daddr, struct rtable *rt, int is_frag) { unsigned char *iph = skb_network_header(skb); @@ -50,9 +50,9 @@ void ip_options_build(struct sk_buff *skb, struct ip_options *opt, if (!is_frag) { if (opt->rr_needaddr) - ip_rt_get_source(iph+opt->rr+iph[opt->rr+2]-5, rt); + ip_rt_get_source(iph+opt->rr+iph[opt->rr+2]-5, skb, rt); if (opt->ts_needaddr) - ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, rt); + ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, skb, rt); if (opt->ts_needtime) { struct timespec tv; __be32 midtime; @@ -553,7 +553,7 @@ void ip_forward_options(struct sk_buff *skb) if (opt->rr_needaddr) { optptr = (unsigned char *)raw + opt->rr; - ip_rt_get_source(&optptr[optptr[2]-5], rt); + ip_rt_get_source(&optptr[optptr[2]-5], skb, rt); opt->is_changed = 1; } if (opt->srr_is_hit) { @@ -572,13 +572,13 @@ void ip_forward_options(struct sk_buff *skb) } if (srrptr + 3 <= srrspace) { opt->is_changed = 1; - ip_rt_get_source(&optptr[srrptr-1], rt); + ip_rt_get_source(&optptr[srrptr-1], skb, rt); optptr[2] = srrptr+4; } else if (net_ratelimit()) printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n"); if (opt->ts_needaddr) { optptr = raw + opt->ts; - ip_rt_get_source(&optptr[optptr[2]-9], rt); + ip_rt_get_source(&optptr[optptr[2]-9], skb, rt); opt->is_changed = 1; } } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 6a83840b16af..ad141d894e4e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1699,22 +1699,26 @@ static int ip_rt_bug(struct sk_buff *skb) in IP options! */ -void ip_rt_get_source(u8 *addr, struct rtable *rt) +void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt) { __be32 src; - struct fib_result res; if (rt_is_output_route(rt)) src = rt->rt_src; else { - struct flowi4 fl4 = { - .daddr = rt->rt_key_dst, - .saddr = rt->rt_key_src, - .flowi4_tos = rt->rt_key_tos, - .flowi4_oif = rt->rt_oif, - .flowi4_iif = rt->rt_iif, - .flowi4_mark = rt->rt_mark, - }; + struct fib_result res; + struct flowi4 fl4; + struct iphdr *iph; + + iph = ip_hdr(skb); + + memset(&fl4, 0, sizeof(fl4)); + fl4.daddr = iph->daddr; + fl4.saddr = iph->saddr; + fl4.flowi4_tos = iph->tos; + fl4.flowi4_oif = rt->dst.dev->ifindex; + fl4.flowi4_iif = skb->dev->ifindex; + fl4.flowi4_mark = skb->mark; rcu_read_lock(); if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res) == 0) -- cgit v1.2.3-58-ga151 From 7be799a70ba3dd90a59e8d2c72bbe06020005b3f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 13 May 2011 17:31:02 -0400 Subject: ipv4: Remove rt->rt_dst reference from ip_forward_options(). At this point iph->daddr equals what rt->rt_dst would hold. Signed-off-by: David S. Miller --- net/ipv4/ip_options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 89268baabc87..c3118e1cd3bb 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -567,7 +567,7 @@ void ip_forward_options(struct sk_buff *skb) ) { if (srrptr + 3 > srrspace) break; - if (memcmp(&rt->rt_dst, &optptr[srrptr-1], 4) == 0) + if (memcmp(&ip_hdr(skb)->daddr, &optptr[srrptr-1], 4) == 0) break; } if (srrptr + 3 <= srrspace) { -- cgit v1.2.3-58-ga151 From 47a8467cc0907e2fd3e6f4d02465dfb64494133e Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 14 May 2011 02:35:25 +0100 Subject: sfc: Fix return value from efx_ethtool_set_rx_ntuple() ethtool_ops::set_rx_ntuple is supposed to return 0 on success, but it currently returns the filter ID when it inserts or modifies a filter. Signed-off-by: Ben Hutchings --- drivers/net/sfc/ethtool.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 8c5e0052c44a..348437a8117e 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -955,8 +955,9 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev, if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_CLEAR) return efx_filter_remove_filter(efx, &filter); - else - return efx_filter_insert_filter(efx, &filter, true); + + rc = efx_filter_insert_filter(efx, &filter, true); + return rc < 0 ? rc : 0; } static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev, -- cgit v1.2.3-58-ga151 From 6d5808d4ae1b0851c3b732d9ec2860d5f7804294 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Wed, 11 May 2011 20:59:06 +0200 Subject: batman-adv: Add missing hardif_free_ref in forw_packet_free add_bcast_packet_to_list increases the refcount for if_incoming but the reference count is never decreased. The reference count must be increased for all kinds of forwarded packets which have the primary interface stored and forw_packet_free must decrease them. Also purge_outstanding_packets has to invoke forw_packet_free when a work item was really cancelled. This regression was introduced in 32ae9b221e788413ce68feaae2ca39e406211a0a. Reported-by: Antonio Quartulli Signed-off-by: Sven Eckelmann --- net/batman-adv/aggregation.c | 14 +++++++++++--- net/batman-adv/send.c | 17 +++++++++++++++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c index 9b9459024479..a8c32030527c 100644 --- a/net/batman-adv/aggregation.c +++ b/net/batman-adv/aggregation.c @@ -23,6 +23,7 @@ #include "aggregation.h" #include "send.h" #include "routing.h" +#include "hard-interface.h" /* calculate the size of the tt information for a given packet */ static int tt_len(struct batman_packet *batman_packet) @@ -105,12 +106,15 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, struct forw_packet *forw_packet_aggr; unsigned char *skb_buff; + if (!atomic_inc_not_zero(&if_incoming->refcount)) + return; + /* own packet should always be scheduled */ if (!own_packet) { if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) { bat_dbg(DBG_BATMAN, bat_priv, "batman packet queue full\n"); - return; + goto out; } } @@ -118,7 +122,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, if (!forw_packet_aggr) { if (!own_packet) atomic_inc(&bat_priv->batman_queue_left); - return; + goto out; } if ((atomic_read(&bat_priv->aggregated_ogms)) && @@ -133,7 +137,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, if (!own_packet) atomic_inc(&bat_priv->batman_queue_left); kfree(forw_packet_aggr); - return; + goto out; } skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr)); @@ -164,6 +168,10 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, queue_delayed_work(bat_event_workqueue, &forw_packet_aggr->delayed_work, send_time - jiffies); + + return; +out: + hardif_free_ref(if_incoming); } /* aggregate a new packet into the existing aggregation */ diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index f30d0c69ccbb..76daa46efe19 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -377,6 +377,8 @@ static void forw_packet_free(struct forw_packet *forw_packet) { if (forw_packet->skb) kfree_skb(forw_packet->skb); + if (forw_packet->if_incoming) + hardif_free_ref(forw_packet->if_incoming); kfree(forw_packet); } @@ -539,6 +541,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, { struct forw_packet *forw_packet; struct hlist_node *tmp_node, *safe_tmp_node; + bool pending; if (hard_iface) bat_dbg(DBG_BATMAN, bat_priv, @@ -567,8 +570,13 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, * send_outstanding_bcast_packet() will lock the list to * delete the item from the list */ - cancel_delayed_work_sync(&forw_packet->delayed_work); + pending = cancel_delayed_work_sync(&forw_packet->delayed_work); spin_lock_bh(&bat_priv->forw_bcast_list_lock); + + if (pending) { + hlist_del(&forw_packet->list); + forw_packet_free(forw_packet); + } } spin_unlock_bh(&bat_priv->forw_bcast_list_lock); @@ -591,8 +599,13 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, * send_outstanding_bat_packet() will lock the list to * delete the item from the list */ - cancel_delayed_work_sync(&forw_packet->delayed_work); + pending = cancel_delayed_work_sync(&forw_packet->delayed_work); spin_lock_bh(&bat_priv->forw_bat_list_lock); + + if (pending) { + hlist_del(&forw_packet->list); + forw_packet_free(forw_packet); + } } spin_unlock_bh(&bat_priv->forw_bat_list_lock); } -- cgit v1.2.3-58-ga151 From ca06c6eb9a31ae782e74596231fb23df4fc5e46d Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Sat, 14 May 2011 20:01:22 +0200 Subject: batman-adv: reset broadcast flood protection on error The broadcast flood protection should be reset to its original value if the primary interface could not be retrieved. Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/send.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 76daa46efe19..33779278f1b2 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -421,7 +421,7 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) primary_if = primary_if_get_selected(bat_priv); if (!primary_if) - goto out; + goto out_and_inc; forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); -- cgit v1.2.3-58-ga151 From d64a6f4dca0b45495dd5be8116b618d9cc004eea Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 13 May 2011 07:19:58 +0000 Subject: e1000e: minor comment cleanups Signed-off-by: Bruce Allan Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/e1000e/lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index 6432ddab40ce..dd8ab05b5590 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -144,7 +144,7 @@ void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) * @hw: pointer to the HW structure * @rar_count: receive address registers * - * Setups the receive address registers by setting the base receive address + * Setup the receive address registers by setting the base receive address * register to the devices MAC address and clearing all the other receive * address registers to 0. **/ @@ -1181,7 +1181,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) * of pause frames. In this case, we had to advertise * FULL flow control because we could not advertise Rx * ONLY. Hence, we must now check to see if we need to - * turn OFF the TRANSMISSION of PAUSE frames. + * turn OFF the TRANSMISSION of PAUSE frames. */ if (hw->fc.requested_mode == e1000_fc_full) { hw->fc.current_mode = e1000_fc_full; -- cgit v1.2.3-58-ga151 From 46ec20ff7d6f9f011e06d58e4e87153ed8c893ed Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Fri, 13 May 2011 01:33:42 +0000 Subject: ixgbevf: Add macvlan support in the set rx mode op Implement setup of unicast address list in the VF driver's set_rx_mode netdev op. Unicast addresses are sent to the PF via a mailbox message and the PF will check if it has room in the RAR table and if so set the filter for the VF. Signed-off-by: Greg Rose Tested-by: Sibai Li Signed-off-by: Jeff Kirsher --- drivers/net/ixgbevf/ixgbevf_main.c | 30 ++++++++++++++++++++++++++++++ drivers/net/ixgbevf/mbx.h | 1 + drivers/net/ixgbevf/vf.c | 34 ++++++++++++++++++++++++++++++++++ drivers/net/ixgbevf/vf.h | 1 + 4 files changed, 66 insertions(+) diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index 05fa7c85deed..d7ab202fb95c 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -1460,6 +1460,34 @@ static void ixgbevf_restore_vlan(struct ixgbevf_adapter *adapter) } } +static int ixgbevf_write_uc_addr_list(struct net_device *netdev) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + int count = 0; + + if ((netdev_uc_count(netdev)) > 10) { + printk(KERN_ERR "Too many unicast filters - No Space\n"); + return -ENOSPC; + } + + if (!netdev_uc_empty(netdev)) { + struct netdev_hw_addr *ha; + netdev_for_each_uc_addr(ha, netdev) { + hw->mac.ops.set_uc_addr(hw, ++count, ha->addr); + udelay(200); + } + } else { + /* + * If the list is empty then send message to PF driver to + * clear all macvlans on this VF. + */ + hw->mac.ops.set_uc_addr(hw, 0, NULL); + } + + return count; +} + /** * ixgbevf_set_rx_mode - Multicast set * @netdev: network interface device structure @@ -1476,6 +1504,8 @@ static void ixgbevf_set_rx_mode(struct net_device *netdev) /* reprogram multicast list */ if (hw->mac.ops.update_mc_addr_list) hw->mac.ops.update_mc_addr_list(hw, netdev); + + ixgbevf_write_uc_addr_list(netdev); } static void ixgbevf_napi_enable_all(struct ixgbevf_adapter *adapter) diff --git a/drivers/net/ixgbevf/mbx.h b/drivers/net/ixgbevf/mbx.h index b2b5bf5daa3d..ea393eb03f3a 100644 --- a/drivers/net/ixgbevf/mbx.h +++ b/drivers/net/ixgbevf/mbx.h @@ -81,6 +81,7 @@ #define IXGBE_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */ #define IXGBE_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */ #define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */ +#define IXGBE_VF_SET_MACVLAN 0x06 /* VF requests PF for unicast filter */ /* length of permanent address message returned from PF */ #define IXGBE_VF_PERMADDR_MSG_LEN 4 diff --git a/drivers/net/ixgbevf/vf.c b/drivers/net/ixgbevf/vf.c index eecd3bf6833f..aa3682e8c473 100644 --- a/drivers/net/ixgbevf/vf.c +++ b/drivers/net/ixgbevf/vf.c @@ -216,6 +216,39 @@ static s32 ixgbevf_get_mac_addr_vf(struct ixgbe_hw *hw, u8 *mac_addr) return 0; } +static s32 ixgbevf_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index, u8 *addr) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + u32 msgbuf[3]; + u8 *msg_addr = (u8 *)(&msgbuf[1]); + s32 ret_val; + + memset(msgbuf, 0, sizeof(msgbuf)); + /* + * If index is one then this is the start of a new list and needs + * indication to the PF so it can do it's own list management. + * If it is zero then that tells the PF to just clear all of + * this VF's macvlans and there is no new list. + */ + msgbuf[0] |= index << IXGBE_VT_MSGINFO_SHIFT; + msgbuf[0] |= IXGBE_VF_SET_MACVLAN; + if (addr) + memcpy(msg_addr, addr, 6); + ret_val = mbx->ops.write_posted(hw, msgbuf, 3); + + if (!ret_val) + ret_val = mbx->ops.read_posted(hw, msgbuf, 3); + + msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS; + + if (!ret_val) + if (msgbuf[0] == + (IXGBE_VF_SET_MACVLAN | IXGBE_VT_MSGTYPE_NACK)) + ret_val = -ENOMEM; + + return ret_val; +} + /** * ixgbevf_set_rar_vf - set device MAC address * @hw: pointer to hardware structure @@ -378,6 +411,7 @@ static struct ixgbe_mac_operations ixgbevf_mac_ops = { .check_link = ixgbevf_check_mac_link_vf, .set_rar = ixgbevf_set_rar_vf, .update_mc_addr_list = ixgbevf_update_mc_addr_list_vf, + .set_uc_addr = ixgbevf_set_uc_addr_vf, .set_vfta = ixgbevf_set_vfta_vf, }; diff --git a/drivers/net/ixgbevf/vf.h b/drivers/net/ixgbevf/vf.h index 23eb114c149f..10306b492ee6 100644 --- a/drivers/net/ixgbevf/vf.h +++ b/drivers/net/ixgbevf/vf.h @@ -62,6 +62,7 @@ struct ixgbe_mac_operations { /* RAR, Multicast, VLAN */ s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32); + s32 (*set_uc_addr)(struct ixgbe_hw *, u32, u8 *); s32 (*init_rx_addrs)(struct ixgbe_hw *); s32 (*update_mc_addr_list)(struct ixgbe_hw *, struct net_device *); s32 (*enable_mc)(struct ixgbe_hw *); -- cgit v1.2.3-58-ga151 From a1cbb15c13971bd5d41626e9e5ced9f9de132c47 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Fri, 13 May 2011 01:33:48 +0000 Subject: ixgbe: Add macvlan support for VF Add infrastructure in the PF driver to support macvlan in the VF driver. Signed-off-by: Greg Rose Tested-by: Sibai Li Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe.h | 13 ++++++ drivers/net/ixgbe/ixgbe_main.c | 28 +++++++++++- drivers/net/ixgbe/ixgbe_mbx.h | 1 + drivers/net/ixgbe/ixgbe_sriov.c | 96 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 134 insertions(+), 4 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 37ff531d59c0..91c15403c6bb 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -106,6 +106,7 @@ #define IXGBE_MAX_VF_FUNCTIONS 64 #define IXGBE_MAX_VFTA_ENTRIES 128 #define MAX_EMULATION_MAC_ADDRS 16 +#define IXGBE_MAX_PF_MACVLANS 15 #define VMDQ_P(p) ((p) + adapter->num_vfs) struct vf_data_storage { @@ -121,6 +122,15 @@ struct vf_data_storage { u16 tx_rate; }; +struct vf_macvlans { + struct list_head l; + int vf; + int rar_entry; + bool free; + bool is_macvlan; + u8 vf_macvlan[ETH_ALEN]; +}; + /* wrapper around a pointer to a socket buffer, * so a DMA handle can be stored along with the buffer */ struct ixgbe_tx_buffer { @@ -471,6 +481,9 @@ struct ixgbe_adapter { unsigned int num_vfs; struct vf_data_storage *vfinfo; int vf_rate_link_speed; + struct vf_macvlans vf_mvs; + struct vf_macvlans *mv_list; + bool antispoofing_enabled; }; enum ixbge_state_t { diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index a3e384bc50fe..f8196e0d2745 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3188,7 +3188,9 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter) /* enable Tx loopback for VF/PF communication */ IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); /* Enable MAC Anti-Spoofing */ - hw->mac.ops.set_mac_anti_spoofing(hw, (adapter->num_vfs != 0), + hw->mac.ops.set_mac_anti_spoofing(hw, + (adapter->antispoofing_enabled = + (adapter->num_vfs != 0)), adapter->num_vfs); } @@ -3497,7 +3499,7 @@ static int ixgbe_write_uc_addr_list(struct net_device *netdev) struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; unsigned int vfn = adapter->num_vfs; - unsigned int rar_entries = hw->mac.num_rar_entries - (vfn + 1); + unsigned int rar_entries = IXGBE_MAX_PF_MACVLANS; int count = 0; /* return ENOMEM indicating insufficient memory for addresses */ @@ -7107,6 +7109,8 @@ static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter, #ifdef CONFIG_PCI_IOV struct ixgbe_hw *hw = &adapter->hw; int err; + int num_vf_macvlans, i; + struct vf_macvlans *mv_list; if (hw->mac.type == ixgbe_mac_82598EB || !max_vfs) return; @@ -7123,6 +7127,26 @@ static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter, e_err(probe, "Failed to enable PCI sriov: %d\n", err); goto err_novfs; } + + num_vf_macvlans = hw->mac.num_rar_entries - + (IXGBE_MAX_PF_MACVLANS + 1 + adapter->num_vfs); + + adapter->mv_list = mv_list = kcalloc(num_vf_macvlans, + sizeof(struct vf_macvlans), + GFP_KERNEL); + if (mv_list) { + /* Initialize list of VF macvlans */ + INIT_LIST_HEAD(&adapter->vf_mvs.l); + for (i = 0; i < num_vf_macvlans; i++) { + mv_list->vf = -1; + mv_list->free = true; + mv_list->rar_entry = hw->mac.num_rar_entries - + (i + adapter->num_vfs + 1); + list_add(&mv_list->l, &adapter->vf_mvs.l); + mv_list++; + } + } + /* If call to enable VFs succeeded then allocate memory * for per VF control structures. */ diff --git a/drivers/net/ixgbe/ixgbe_mbx.h b/drivers/net/ixgbe/ixgbe_mbx.h index f53dc5bb28b7..b239bdac38da 100644 --- a/drivers/net/ixgbe/ixgbe_mbx.h +++ b/drivers/net/ixgbe/ixgbe_mbx.h @@ -67,6 +67,7 @@ #define IXGBE_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */ #define IXGBE_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */ #define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */ +#define IXGBE_VF_SET_MACVLAN 0x06 /* VF requests PF for unicast filter */ /* length of permanent address message returned from PF */ #define IXGBE_VF_PERMADDR_MSG_LEN 4 diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c index 47650278d414..9f972460e780 100644 --- a/drivers/net/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ixgbe/ixgbe_sriov.c @@ -82,6 +82,21 @@ static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, return 0; } +static void ixgbe_restore_vf_macvlans(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + struct list_head *pos; + struct vf_macvlans *entry; + + list_for_each(pos, &adapter->vf_mvs.l) { + entry = list_entry(pos, struct vf_macvlans, l); + if (entry->free == false) + hw->mac.ops.set_rar(hw, entry->rar_entry, + entry->vf_macvlan, + entry->vf, IXGBE_RAH_AV); + } +} + void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; @@ -102,6 +117,9 @@ void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); } } + + /* Restore any VF macvlans */ + ixgbe_restore_vf_macvlans(adapter); } static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, @@ -200,6 +218,61 @@ static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, return 0; } +static int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter, + int vf, int index, unsigned char *mac_addr) +{ + struct ixgbe_hw *hw = &adapter->hw; + struct list_head *pos; + struct vf_macvlans *entry; + + if (index <= 1) { + list_for_each(pos, &adapter->vf_mvs.l) { + entry = list_entry(pos, struct vf_macvlans, l); + if (entry->vf == vf) { + entry->vf = -1; + entry->free = true; + entry->is_macvlan = false; + hw->mac.ops.clear_rar(hw, entry->rar_entry); + } + } + } + + /* + * If index was zero then we were asked to clear the uc list + * for the VF. We're done. + */ + if (!index) + return 0; + + entry = NULL; + + list_for_each(pos, &adapter->vf_mvs.l) { + entry = list_entry(pos, struct vf_macvlans, l); + if (entry->free) + break; + } + + /* + * If we traversed the entire list and didn't find a free entry + * then we're out of space on the RAR table. Also entry may + * be NULL because the original memory allocation for the list + * failed, which is not fatal but does mean we can't support + * VF requests for MACVLAN because we couldn't allocate + * memory for the list management required. + */ + if (!entry || !entry->free) + return -ENOSPC; + + entry->free = false; + entry->is_macvlan = true; + entry->vf = vf; + memcpy(entry->vf_macvlan, mac_addr, ETH_ALEN); + + hw->mac.ops.set_rar(hw, entry->rar_entry, mac_addr, vf, IXGBE_RAH_AV); + + return 0; +} + int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) { unsigned char vf_mac_addr[6]; @@ -256,7 +329,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) s32 retval; int entries; u16 *hash_list; - int add, vid; + int add, vid, index; u8 *new_mac; retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf); @@ -345,6 +418,24 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) retval = ixgbe_set_vf_vlan(adapter, add, vid, vf); } break; + case IXGBE_VF_SET_MACVLAN: + index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> + IXGBE_VT_MSGINFO_SHIFT; + /* + * If the VF is allowed to set MAC filters then turn off + * anti-spoofing to avoid false positives. An index + * greater than 0 will indicate the VF is setting a + * macvlan MAC filter. + */ + if (index > 0 && adapter->antispoofing_enabled) { + hw->mac.ops.set_mac_anti_spoofing(hw, false, + adapter->num_vfs); + hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf); + adapter->antispoofing_enabled = false; + } + retval = ixgbe_set_vf_macvlan(adapter, vf, index, + (unsigned char *)(&msgbuf[1])); + break; default: e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]); retval = IXGBE_ERR_MBX; @@ -452,7 +543,8 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) goto out; ixgbe_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf); ixgbe_set_vmolr(hw, vf, false); - hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); + if (adapter->antispoofing_enabled) + hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); adapter->vfinfo[vf].pf_vlan = vlan; adapter->vfinfo[vf].pf_qos = qos; dev_info(&adapter->pdev->dev, -- cgit v1.2.3-58-ga151 From 51275d37a85bc82bda7e5b179ee520e85e66e782 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Fri, 8 Apr 2011 01:23:59 +0000 Subject: ixgbe: force unlock on timeout The semaphore can be in locked state upon driver load, particularly on 82598 if a machine is rebooted due to panic and the semaphore was acquired just prior to the panic. This patch unlocks the semaphore if it times out. Signed-off-by: Emil Tantilov Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_common.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index c4730cd39b22..b894b42a741c 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -1189,6 +1189,28 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) udelay(50); } + if (i == timeout) { + hw_dbg(hw, "Driver can't access the Eeprom - SMBI Semaphore " + "not granted.\n"); + /* + * this release is particularly important because our attempts + * above to get the semaphore may have succeeded, and if there + * was a timeout, we should unconditionally clear the semaphore + * bits to free the driver to make progress + */ + ixgbe_release_eeprom_semaphore(hw); + + udelay(50); + /* + * one last try + * If the SMBI bit is 0 when we read it, then the bit will be + * set and we have the semaphore + */ + swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); + if (!(swsm & IXGBE_SWSM_SMBI)) + status = 0; + } + /* Now get the semaphore between SW/FW through the SWESMBI bit */ if (status == 0) { for (i = 0; i < timeout; i++) { -- cgit v1.2.3-58-ga151 From e606bfe74de63d6c3778c145ee0673d96ab257c9 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 22 Apr 2011 04:07:43 +0000 Subject: ixgbe: move flags and state into the same cacheline This change moves flags and state into the same cacheline. The reason for this change is because both are frequently read around the same time and infrequently written. By combining them into the same cacheline this should help to reduce memory utilization. Signed-off-by: Alexander Duyck Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe.h | 88 ++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 91c15403c6bb..ec948ffec553 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -341,10 +341,48 @@ struct ixgbe_q_vector { /* board specific private data structure */ struct ixgbe_adapter { - struct timer_list watchdog_timer; + unsigned long state; + + /* Some features need tri-state capability, + * thus the additional *_CAPABLE flags. + */ + u32 flags; +#define IXGBE_FLAG_RX_CSUM_ENABLED (u32)(1) +#define IXGBE_FLAG_MSI_CAPABLE (u32)(1 << 1) +#define IXGBE_FLAG_MSI_ENABLED (u32)(1 << 2) +#define IXGBE_FLAG_MSIX_CAPABLE (u32)(1 << 3) +#define IXGBE_FLAG_MSIX_ENABLED (u32)(1 << 4) +#define IXGBE_FLAG_RX_1BUF_CAPABLE (u32)(1 << 6) +#define IXGBE_FLAG_RX_PS_CAPABLE (u32)(1 << 7) +#define IXGBE_FLAG_RX_PS_ENABLED (u32)(1 << 8) +#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 9) +#define IXGBE_FLAG_DCA_ENABLED (u32)(1 << 10) +#define IXGBE_FLAG_DCA_CAPABLE (u32)(1 << 11) +#define IXGBE_FLAG_IMIR_ENABLED (u32)(1 << 12) +#define IXGBE_FLAG_MQ_CAPABLE (u32)(1 << 13) +#define IXGBE_FLAG_DCB_ENABLED (u32)(1 << 14) +#define IXGBE_FLAG_RSS_ENABLED (u32)(1 << 16) +#define IXGBE_FLAG_RSS_CAPABLE (u32)(1 << 17) +#define IXGBE_FLAG_VMDQ_CAPABLE (u32)(1 << 18) +#define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 19) +#define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 20) +#define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22) +#define IXGBE_FLAG_IN_SFP_LINK_TASK (u32)(1 << 23) +#define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 24) +#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 25) +#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 26) +#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 27) +#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 28) +#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 29) +#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 30) + + u32 flags2; +#define IXGBE_FLAG2_RSC_CAPABLE (u32)(1) +#define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1) +#define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 2) + unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; u16 bd_number; - struct work_struct reset_task; struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; /* DCB parameters */ @@ -387,43 +425,6 @@ struct ixgbe_adapter { u32 alloc_rx_page_failed; u32 alloc_rx_buff_failed; - /* Some features need tri-state capability, - * thus the additional *_CAPABLE flags. - */ - u32 flags; -#define IXGBE_FLAG_RX_CSUM_ENABLED (u32)(1) -#define IXGBE_FLAG_MSI_CAPABLE (u32)(1 << 1) -#define IXGBE_FLAG_MSI_ENABLED (u32)(1 << 2) -#define IXGBE_FLAG_MSIX_CAPABLE (u32)(1 << 3) -#define IXGBE_FLAG_MSIX_ENABLED (u32)(1 << 4) -#define IXGBE_FLAG_RX_1BUF_CAPABLE (u32)(1 << 6) -#define IXGBE_FLAG_RX_PS_CAPABLE (u32)(1 << 7) -#define IXGBE_FLAG_RX_PS_ENABLED (u32)(1 << 8) -#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 9) -#define IXGBE_FLAG_DCA_ENABLED (u32)(1 << 10) -#define IXGBE_FLAG_DCA_CAPABLE (u32)(1 << 11) -#define IXGBE_FLAG_IMIR_ENABLED (u32)(1 << 12) -#define IXGBE_FLAG_MQ_CAPABLE (u32)(1 << 13) -#define IXGBE_FLAG_DCB_ENABLED (u32)(1 << 14) -#define IXGBE_FLAG_RSS_ENABLED (u32)(1 << 16) -#define IXGBE_FLAG_RSS_CAPABLE (u32)(1 << 17) -#define IXGBE_FLAG_VMDQ_CAPABLE (u32)(1 << 18) -#define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 19) -#define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 20) -#define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22) -#define IXGBE_FLAG_IN_SFP_LINK_TASK (u32)(1 << 23) -#define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 24) -#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 25) -#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 26) -#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 27) -#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 28) -#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 29) -#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 30) - - u32 flags2; -#define IXGBE_FLAG2_RSC_CAPABLE (u32)(1) -#define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1) -#define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 2) /* default to trying for four seconds */ #define IXGBE_TRY_LINK_TIMEOUT (4 * HZ) @@ -444,7 +445,6 @@ struct ixgbe_adapter { u32 rx_eitr_param; u32 tx_eitr_param; - unsigned long state; u64 tx_busy; unsigned int tx_ring_count; unsigned int rx_ring_count; @@ -453,15 +453,18 @@ struct ixgbe_adapter { bool link_up; unsigned long link_check_timeout; + struct work_struct reset_task; struct work_struct watchdog_task; struct work_struct sfp_task; - struct timer_list sfp_timer; struct work_struct multispeed_fiber_task; struct work_struct sfp_config_module_task; + struct work_struct fdir_reinit_task; + struct work_struct check_overtemp_task; + struct timer_list watchdog_timer; + struct timer_list sfp_timer; u32 fdir_pballoc; u32 atr_sample_rate; spinlock_t fdir_perfect_lock; - struct work_struct fdir_reinit_task; #ifdef IXGBE_FCOE struct ixgbe_fcoe fcoe; #endif /* IXGBE_FCOE */ @@ -472,7 +475,6 @@ struct ixgbe_adapter { int node; u32 led_reg; - struct work_struct check_overtemp_task; u32 interrupt_event; char lsc_int_name[IFNAMSIZ + 9]; -- cgit v1.2.3-58-ga151 From 7086400d87a06588c13270949db9134afc9553ba Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 27 Apr 2011 09:13:56 +0000 Subject: ixgbe: Combine SFP and multi-speed fiber task into single service task This change is meant to address several race conditions with multi-speed fiber SFP+ modules in 82599 adapters. Specifically issues have been seen in which both the SFP configuration and the multi-speed fiber configuration are running simultaneously which will result in the device getting into an erroneous link down state. Signed-off-by: Alexander Duyck Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe.h | 26 +-- drivers/net/ixgbe/ixgbe_main.c | 388 +++++++++++++++++++++-------------------- 2 files changed, 213 insertions(+), 201 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index ec948ffec553..cbb04ba58289 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -367,19 +367,20 @@ struct ixgbe_adapter { #define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 19) #define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 20) #define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22) -#define IXGBE_FLAG_IN_SFP_LINK_TASK (u32)(1 << 23) -#define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 24) -#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 25) -#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 26) -#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 27) -#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 28) -#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 29) -#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 30) +#define IXGBE_FLAG_NEED_LINK_CONFIG (u32)(1 << 23) +#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 24) +#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 25) +#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 26) +#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 27) +#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 28) +#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 29) u32 flags2; #define IXGBE_FLAG2_RSC_CAPABLE (u32)(1) #define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1) #define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 2) +#define IXGBE_FLAG2_SEARCH_FOR_SFP (u32)(1 << 4) +#define IXGBE_FLAG2_SFP_NEEDS_RESET (u32)(1 << 5) unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; u16 bd_number; @@ -455,13 +456,11 @@ struct ixgbe_adapter { struct work_struct reset_task; struct work_struct watchdog_task; - struct work_struct sfp_task; - struct work_struct multispeed_fiber_task; - struct work_struct sfp_config_module_task; struct work_struct fdir_reinit_task; struct work_struct check_overtemp_task; + struct work_struct service_task; struct timer_list watchdog_timer; - struct timer_list sfp_timer; + struct timer_list service_timer; u32 fdir_pballoc; u32 atr_sample_rate; spinlock_t fdir_perfect_lock; @@ -492,7 +491,8 @@ enum ixbge_state_t { __IXGBE_TESTING, __IXGBE_RESETTING, __IXGBE_DOWN, - __IXGBE_SFP_MODULE_NOT_FOUND + __IXGBE_SERVICE_SCHED, + __IXGBE_IN_SFP_INIT, }; struct ixgbe_rsc_cb { diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index f8196e0d2745..a5d4226eee0c 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -191,6 +191,22 @@ static inline void ixgbe_disable_sriov(struct ixgbe_adapter *adapter) adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED; } +static void ixgbe_service_event_schedule(struct ixgbe_adapter *adapter) +{ + if (!test_bit(__IXGBE_DOWN, &adapter->state) && + !test_and_set_bit(__IXGBE_SERVICE_SCHED, &adapter->state)) + schedule_work(&adapter->service_task); +} + +static void ixgbe_service_event_complete(struct ixgbe_adapter *adapter) +{ + BUG_ON(!test_bit(__IXGBE_SERVICE_SCHED, &adapter->state)); + + /* flush memory to make sure state is correct before next watchog */ + smp_mb__before_clear_bit(); + clear_bit(__IXGBE_SERVICE_SCHED, &adapter->state); +} + struct ixgbe_reg_info { u32 ofs; char *name; @@ -1858,15 +1874,19 @@ static void ixgbe_check_sfp_event(struct ixgbe_adapter *adapter, u32 eicr) if (eicr & IXGBE_EICR_GPI_SDP2) { /* Clear the interrupt */ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2); - if (!test_bit(__IXGBE_DOWN, &adapter->state)) - schedule_work(&adapter->sfp_config_module_task); + if (!test_bit(__IXGBE_DOWN, &adapter->state)) { + adapter->flags2 |= IXGBE_FLAG2_SFP_NEEDS_RESET; + ixgbe_service_event_schedule(adapter); + } } if (eicr & IXGBE_EICR_GPI_SDP1) { /* Clear the interrupt */ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1); - if (!test_bit(__IXGBE_DOWN, &adapter->state)) - schedule_work(&adapter->multispeed_fiber_task); + if (!test_bit(__IXGBE_DOWN, &adapter->state)) { + adapter->flags |= IXGBE_FLAG_NEED_LINK_CONFIG; + ixgbe_service_event_schedule(adapter); + } } } @@ -1937,8 +1957,10 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) ixgbe_check_fan_failure(adapter, eicr); + /* re-enable the original interrupt state, no lsc, no queues */ if (!test_bit(__IXGBE_DOWN, &adapter->state)) - IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); + IXGBE_WRITE_REG(hw, IXGBE_EIMS, eicr & + ~(IXGBE_EIMS_LSC | IXGBE_EIMS_RTX_QUEUE)); return IRQ_HANDLED; } @@ -3772,31 +3794,16 @@ static inline bool ixgbe_is_sfp(struct ixgbe_hw *hw) **/ static void ixgbe_sfp_link_config(struct ixgbe_adapter *adapter) { - struct ixgbe_hw *hw = &adapter->hw; + /* + * We are assuming the worst case scenerio here, and that + * is that an SFP was inserted/removed after the reset + * but before SFP detection was enabled. As such the best + * solution is to just start searching as soon as we start + */ + if (adapter->hw.mac.type == ixgbe_mac_82598EB) + adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP; - if (hw->phy.multispeed_fiber) { - /* - * In multispeed fiber setups, the device may not have - * had a physical connection when the driver loaded. - * If that's the case, the initial link configuration - * couldn't get the MAC into 10G or 1G mode, so we'll - * never have a link status change interrupt fire. - * We need to try and force an autonegotiation - * session, then bring up link. - */ - if (hw->mac.ops.setup_sfp) - hw->mac.ops.setup_sfp(hw); - if (!(adapter->flags & IXGBE_FLAG_IN_SFP_LINK_TASK)) - schedule_work(&adapter->multispeed_fiber_task); - } else { - /* - * Direct Attach Cu and non-multispeed fiber modules - * still need to be configured properly prior to - * attempting link. - */ - if (!(adapter->flags & IXGBE_FLAG_IN_SFP_MOD_TASK)) - schedule_work(&adapter->sfp_config_module_task); - } + adapter->flags2 |= IXGBE_FLAG2_SFP_NEEDS_RESET; } /** @@ -3926,17 +3933,6 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) e_crit(drv, "Fan has stopped, replace the adapter\n"); } - /* - * For hot-pluggable SFP+ devices, a new SFP+ module may have - * arrived before interrupts were enabled but after probe. Such - * devices wouldn't have their type identified yet. We need to - * kick off the SFP+ module setup first, then try to bring up link. - * If we're not hot-pluggable SFP+, we just need to configure link - * and bring it up. - */ - if (hw->phy.type == ixgbe_phy_none) - schedule_work(&adapter->sfp_config_module_task); - /* enable transmits */ netif_tx_start_all_queues(adapter->netdev); @@ -3945,6 +3941,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; adapter->link_check_timeout = jiffies; mod_timer(&adapter->watchdog_timer, jiffies); + mod_timer(&adapter->service_timer, jiffies); /* Set PF Reset Done bit so PF/VF Mail Ops can work */ ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); @@ -3957,6 +3954,9 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) void ixgbe_reinit_locked(struct ixgbe_adapter *adapter) { WARN_ON(in_interrupt()); + /* put off any impending NetWatchDogTimeout */ + adapter->netdev->trans_start = jiffies; + while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) usleep_range(1000, 2000); ixgbe_down(adapter); @@ -3985,10 +3985,20 @@ void ixgbe_reset(struct ixgbe_adapter *adapter) struct ixgbe_hw *hw = &adapter->hw; int err; + /* lock SFP init bit to prevent race conditions with the watchdog */ + while (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state)) + usleep_range(1000, 2000); + + /* clear all SFP and link config related flags while holding SFP_INIT */ + adapter->flags2 &= ~(IXGBE_FLAG2_SEARCH_FOR_SFP | + IXGBE_FLAG2_SFP_NEEDS_RESET); + adapter->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG; + err = hw->mac.ops.init_hw(hw); switch (err) { case 0: case IXGBE_ERR_SFP_NOT_PRESENT: + case IXGBE_ERR_SFP_NOT_SUPPORTED: break; case IXGBE_ERR_MASTER_REQUESTS_PENDING: e_dev_err("master disable timed out\n"); @@ -4006,6 +4016,8 @@ void ixgbe_reset(struct ixgbe_adapter *adapter) e_dev_err("Hardware Error: %d\n", err); } + clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state); + /* reprogram the RAR[0] in case user changed it. */ hw->mac.ops.set_rar(hw, 0, hw->mac.addr, adapter->num_vfs, IXGBE_RAH_AV); @@ -4167,11 +4179,9 @@ void ixgbe_down(struct ixgbe_adapter *adapter) netif_tx_stop_all_queues(netdev); - clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state); - del_timer_sync(&adapter->sfp_timer); del_timer_sync(&adapter->watchdog_timer); cancel_work_sync(&adapter->watchdog_task); - + /* call carrier off first to avoid false dev_watchdog timeouts */ netif_carrier_off(netdev); netif_tx_disable(netdev); @@ -4179,6 +4189,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter) ixgbe_napi_disable_all(adapter); + adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE; + + del_timer_sync(&adapter->service_timer); + /* Cleanup the affinity_hint CPU mask memory and callback */ for (i = 0; i < num_q_vectors; i++) { struct ixgbe_q_vector *q_vector = adapter->q_vector[i]; @@ -5147,57 +5161,6 @@ void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter) ixgbe_reset_interrupt_capability(adapter); } -/** - * ixgbe_sfp_timer - worker thread to find a missing module - * @data: pointer to our adapter struct - **/ -static void ixgbe_sfp_timer(unsigned long data) -{ - struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data; - - /* - * Do the sfp_timer outside of interrupt context due to the - * delays that sfp+ detection requires - */ - schedule_work(&adapter->sfp_task); -} - -/** - * ixgbe_sfp_task - worker thread to find a missing module - * @work: pointer to work_struct containing our data - **/ -static void ixgbe_sfp_task(struct work_struct *work) -{ - struct ixgbe_adapter *adapter = container_of(work, - struct ixgbe_adapter, - sfp_task); - struct ixgbe_hw *hw = &adapter->hw; - - if ((hw->phy.type == ixgbe_phy_nl) && - (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) { - s32 ret = hw->phy.ops.identify_sfp(hw); - if (ret == IXGBE_ERR_SFP_NOT_PRESENT) - goto reschedule; - ret = hw->phy.ops.reset(hw); - if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { - e_dev_err("failed to initialize because an unsupported " - "SFP+ module type was detected.\n"); - e_dev_err("Reload the driver after installing a " - "supported module.\n"); - unregister_netdev(adapter->netdev); - } else { - e_info(probe, "detected SFP+: %d\n", hw->phy.sfp_type); - } - /* don't need this routine any more */ - clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state); - } - return; -reschedule: - if (test_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state)) - mod_timer(&adapter->sfp_timer, - round_jiffies(jiffies + (2 * HZ))); -} - /** * ixgbe_sw_init - Initialize general software structures (struct ixgbe_adapter) * @adapter: board private structure to initialize @@ -6041,65 +6004,6 @@ watchdog_short_circuit: schedule_work(&adapter->watchdog_task); } -/** - * ixgbe_multispeed_fiber_task - worker thread to configure multispeed fiber - * @work: pointer to work_struct containing our data - **/ -static void ixgbe_multispeed_fiber_task(struct work_struct *work) -{ - struct ixgbe_adapter *adapter = container_of(work, - struct ixgbe_adapter, - multispeed_fiber_task); - struct ixgbe_hw *hw = &adapter->hw; - u32 autoneg; - bool negotiation; - - adapter->flags |= IXGBE_FLAG_IN_SFP_LINK_TASK; - autoneg = hw->phy.autoneg_advertised; - if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) - hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiation); - hw->mac.autotry_restart = false; - if (hw->mac.ops.setup_link) - hw->mac.ops.setup_link(hw, autoneg, negotiation, true); - adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; - adapter->flags &= ~IXGBE_FLAG_IN_SFP_LINK_TASK; -} - -/** - * ixgbe_sfp_config_module_task - worker thread to configure a new SFP+ module - * @work: pointer to work_struct containing our data - **/ -static void ixgbe_sfp_config_module_task(struct work_struct *work) -{ - struct ixgbe_adapter *adapter = container_of(work, - struct ixgbe_adapter, - sfp_config_module_task); - struct ixgbe_hw *hw = &adapter->hw; - u32 err; - - adapter->flags |= IXGBE_FLAG_IN_SFP_MOD_TASK; - - /* Time for electrical oscillations to settle down */ - msleep(100); - err = hw->phy.ops.identify_sfp(hw); - - if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { - e_dev_err("failed to initialize because an unsupported SFP+ " - "module type was detected.\n"); - e_dev_err("Reload the driver after installing a supported " - "module.\n"); - unregister_netdev(adapter->netdev); - return; - } - if (hw->mac.ops.setup_sfp) - hw->mac.ops.setup_sfp(hw); - - if (!(adapter->flags & IXGBE_FLAG_IN_SFP_LINK_TASK)) - /* This will also work for DA Twinax connections */ - schedule_work(&adapter->multispeed_fiber_task); - adapter->flags &= ~IXGBE_FLAG_IN_SFP_MOD_TASK; -} - /** * ixgbe_fdir_reinit_task - worker thread to reinit FDIR filter table * @work: pointer to work_struct containing our data @@ -6273,6 +6177,141 @@ static void ixgbe_watchdog_task(struct work_struct *work) mutex_unlock(&ixgbe_watchdog_lock); } +/** + * ixgbe_sfp_detection_subtask - poll for SFP+ cable + * @adapter - the ixgbe adapter structure + **/ +static void ixgbe_sfp_detection_subtask(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + s32 err; + + /* not searching for SFP so there is nothing to do here */ + if (!(adapter->flags2 & IXGBE_FLAG2_SEARCH_FOR_SFP) && + !(adapter->flags2 & IXGBE_FLAG2_SFP_NEEDS_RESET)) + return; + + /* someone else is in init, wait until next service event */ + if (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state)) + return; + + err = hw->phy.ops.identify_sfp(hw); + if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) + goto sfp_out; + + if (err == IXGBE_ERR_SFP_NOT_PRESENT) { + /* If no cable is present, then we need to reset + * the next time we find a good cable. */ + adapter->flags2 |= IXGBE_FLAG2_SFP_NEEDS_RESET; + } + + /* exit on error */ + if (err) + goto sfp_out; + + /* exit if reset not needed */ + if (!(adapter->flags2 & IXGBE_FLAG2_SFP_NEEDS_RESET)) + goto sfp_out; + + adapter->flags2 &= ~IXGBE_FLAG2_SFP_NEEDS_RESET; + + /* + * A module may be identified correctly, but the EEPROM may not have + * support for that module. setup_sfp() will fail in that case, so + * we should not allow that module to load. + */ + if (hw->mac.type == ixgbe_mac_82598EB) + err = hw->phy.ops.reset(hw); + else + err = hw->mac.ops.setup_sfp(hw); + + if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) + goto sfp_out; + + adapter->flags |= IXGBE_FLAG_NEED_LINK_CONFIG; + e_info(probe, "detected SFP+: %d\n", hw->phy.sfp_type); + +sfp_out: + clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state); + + if ((err == IXGBE_ERR_SFP_NOT_SUPPORTED) && + (adapter->netdev->reg_state == NETREG_REGISTERED)) { + e_dev_err("failed to initialize because an unsupported " + "SFP+ module type was detected.\n"); + e_dev_err("Reload the driver after installing a " + "supported module.\n"); + unregister_netdev(adapter->netdev); + } +} + +/** + * ixgbe_sfp_link_config_subtask - set up link SFP after module install + * @adapter - the ixgbe adapter structure + **/ +static void ixgbe_sfp_link_config_subtask(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 autoneg; + bool negotiation; + + if (!(adapter->flags & IXGBE_FLAG_NEED_LINK_CONFIG)) + return; + + /* someone else is in init, wait until next service event */ + if (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state)) + return; + + adapter->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG; + + autoneg = hw->phy.autoneg_advertised; + if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) + hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiation); + hw->mac.autotry_restart = false; + if (hw->mac.ops.setup_link) + hw->mac.ops.setup_link(hw, autoneg, negotiation, true); + + adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; + adapter->link_check_timeout = jiffies; + clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state); +} + +/** + * ixgbe_service_timer - Timer Call-back + * @data: pointer to adapter cast into an unsigned long + **/ +static void ixgbe_service_timer(unsigned long data) +{ + struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data; + unsigned long next_event_offset; + + /* poll faster when waiting for link */ + if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE) + next_event_offset = HZ / 10; + else + next_event_offset = HZ * 2; + + /* Reset the timer */ + mod_timer(&adapter->service_timer, next_event_offset + jiffies); + + ixgbe_service_event_schedule(adapter); +} + +/** + * ixgbe_service_task - manages and runs subtasks + * @work: pointer to work_struct containing our data + **/ +static void ixgbe_service_task(struct work_struct *work) +{ + struct ixgbe_adapter *adapter = container_of(work, + struct ixgbe_adapter, + service_task); + + ixgbe_sfp_detection_subtask(adapter); + ixgbe_sfp_link_config_subtask(adapter); + + ixgbe_service_event_complete(adapter); +} + static int ixgbe_tso(struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring, struct sk_buff *skb, u32 tx_flags, u8 *hdr_len, __be16 protocol) @@ -7317,22 +7356,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, hw->phy.mdio.mdio_read = ixgbe_mdio_read; hw->phy.mdio.mdio_write = ixgbe_mdio_write; - /* set up this timer and work struct before calling get_invariants - * which might start the timer - */ - init_timer(&adapter->sfp_timer); - adapter->sfp_timer.function = ixgbe_sfp_timer; - adapter->sfp_timer.data = (unsigned long) adapter; - - INIT_WORK(&adapter->sfp_task, ixgbe_sfp_task); - - /* multispeed fiber has its own tasklet, called from GPI SDP1 context */ - INIT_WORK(&adapter->multispeed_fiber_task, ixgbe_multispeed_fiber_task); - - /* a new SFP+ module arrival, called from GPI SDP2 context */ - INIT_WORK(&adapter->sfp_config_module_task, - ixgbe_sfp_config_module_task); - ii->get_invariants(hw); /* setup the private structure */ @@ -7366,17 +7389,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, hw->phy.reset_if_overtemp = false; if (err == IXGBE_ERR_SFP_NOT_PRESENT && hw->mac.type == ixgbe_mac_82598EB) { - /* - * Start a kernel thread to watch for a module to arrive. - * Only do this for 82598, since 82599 will generate - * interrupts on module arrival. - */ - set_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state); - mod_timer(&adapter->sfp_timer, - round_jiffies(jiffies + (2 * HZ))); err = 0; } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { - e_dev_err("failed to initialize because an unsupported SFP+ " + e_dev_err("failed to load because an unsupported SFP+ " "module type was detected.\n"); e_dev_err("Reload the driver after installing a supported " "module.\n"); @@ -7468,6 +7483,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, (hw->mac.type == ixgbe_mac_82599EB)))) hw->mac.ops.disable_tx_laser(hw); + setup_timer(&adapter->service_timer, &ixgbe_service_timer, + (unsigned long) adapter); init_timer(&adapter->watchdog_timer); adapter->watchdog_timer.function = ixgbe_watchdog; adapter->watchdog_timer.data = (unsigned long)adapter; @@ -7475,6 +7492,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, INIT_WORK(&adapter->reset_task, ixgbe_reset_task); INIT_WORK(&adapter->watchdog_task, ixgbe_watchdog_task); + INIT_WORK(&adapter->service_task, ixgbe_service_task); + clear_bit(__IXGBE_SERVICE_SCHED, &adapter->state); + err = ixgbe_init_interrupt_scheme(adapter); if (err) goto err_sw_init; @@ -7593,11 +7613,7 @@ err_sw_init: err_eeprom: if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) ixgbe_disable_sriov(adapter); - clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state); - del_timer_sync(&adapter->sfp_timer); - cancel_work_sync(&adapter->sfp_task); - cancel_work_sync(&adapter->multispeed_fiber_task); - cancel_work_sync(&adapter->sfp_config_module_task); + adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP; iounmap(hw->hw_addr); err_ioremap: free_netdev(netdev); @@ -7625,19 +7641,15 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) struct net_device *netdev = adapter->netdev; set_bit(__IXGBE_DOWN, &adapter->state); + cancel_work_sync(&adapter->service_task); /* * The timers may be rescheduled, so explicitly disable them * from being rescheduled. */ - clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state); del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->sfp_timer); cancel_work_sync(&adapter->watchdog_task); - cancel_work_sync(&adapter->sfp_task); - cancel_work_sync(&adapter->multispeed_fiber_task); - cancel_work_sync(&adapter->sfp_config_module_task); if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE || adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) cancel_work_sync(&adapter->fdir_reinit_task); -- cgit v1.2.3-58-ga151 From 93c52dd0033be3cb91376916b8461fcb94ef0c22 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 22 Apr 2011 04:07:54 +0000 Subject: ixgbe: Merge watchdog functionality into service task This patch is meant to merge the functionality of the ixgbe watchdog task into the service task. By doing this all link state functionality will be controlled by a single task. As a result the reliability of the interface will be improved as the likelihood of any race conditions is further reduced. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe.h | 2 - drivers/net/ixgbe/ixgbe_main.c | 364 ++++++++++++++++++++++------------------- 2 files changed, 200 insertions(+), 166 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index cbb04ba58289..193c6c4243cb 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -455,11 +455,9 @@ struct ixgbe_adapter { unsigned long link_check_timeout; struct work_struct reset_task; - struct work_struct watchdog_task; struct work_struct fdir_reinit_task; struct work_struct check_overtemp_task; struct work_struct service_task; - struct timer_list watchdog_timer; struct timer_list service_timer; u32 fdir_pballoc; u32 atr_sample_rate; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index a5d4226eee0c..d1e52b5cebfa 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1900,7 +1900,7 @@ static void ixgbe_check_lsc(struct ixgbe_adapter *adapter) if (!test_bit(__IXGBE_DOWN, &adapter->state)) { IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); IXGBE_WRITE_FLUSH(hw); - schedule_work(&adapter->watchdog_task); + ixgbe_service_event_schedule(adapter); } } @@ -3940,7 +3940,6 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) * link up interrupt but shouldn't be a problem */ adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; adapter->link_check_timeout = jiffies; - mod_timer(&adapter->watchdog_timer, jiffies); mod_timer(&adapter->service_timer, jiffies); /* Set PF Reset Done bit so PF/VF Mail Ops can work */ @@ -4179,8 +4178,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter) netif_tx_stop_all_queues(netdev); - del_timer_sync(&adapter->watchdog_timer); - cancel_work_sync(&adapter->watchdog_task); /* call carrier off first to avoid false dev_watchdog timeouts */ netif_carrier_off(netdev); netif_tx_disable(netdev); @@ -5957,23 +5954,54 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) } /** - * ixgbe_watchdog - Timer Call-back - * @data: pointer to adapter cast into an unsigned long + * ixgbe_fdir_reinit_task - worker thread to reinit FDIR filter table + * @work: pointer to work_struct containing our data **/ -static void ixgbe_watchdog(unsigned long data) +static void ixgbe_fdir_reinit_task(struct work_struct *work) +{ + struct ixgbe_adapter *adapter = container_of(work, + struct ixgbe_adapter, + fdir_reinit_task); + struct ixgbe_hw *hw = &adapter->hw; + int i; + + if (ixgbe_reinit_fdir_tables_82599(hw) == 0) { + for (i = 0; i < adapter->num_tx_queues; i++) + set_bit(__IXGBE_TX_FDIR_INIT_DONE, + &(adapter->tx_ring[i]->state)); + } else { + e_err(probe, "failed to finish FDIR re-initialization, " + "ignored adding FDIR ATR filters\n"); + } + /* Done FDIR Re-initialization, enable transmits */ + netif_tx_start_all_queues(adapter->netdev); +} + +/** + * ixgbe_check_hang_subtask - check for hung queues and dropped interrupts + * @adapter - pointer to the device adapter structure + * + * This function serves two purposes. First it strobes the interrupt lines + * in order to make certain interrupts are occuring. Secondly it sets the + * bits needed to check for TX hangs. As a result we should immediately + * determine if a hang has occured. + */ +static void ixgbe_check_hang_subtask(struct ixgbe_adapter *adapter) { - struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data; struct ixgbe_hw *hw = &adapter->hw; u64 eics = 0; int i; - /* - * Do the watchdog outside of interrupt context due to the lovely - * delays that some of the newer hardware requires - */ + /* If we're down or resetting, just bail */ + if (test_bit(__IXGBE_DOWN, &adapter->state) || + test_bit(__IXGBE_RESETTING, &adapter->state)) + return; - if (test_bit(__IXGBE_DOWN, &adapter->state)) - goto watchdog_short_circuit; + /* Force detection of hung controller */ + if (netif_carrier_ok(adapter->netdev)) { + for (i = 0; i < adapter->num_tx_queues; i++) + set_check_for_tx_hang(adapter->tx_ring[i]); + } if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) { /* @@ -5983,179 +6011,157 @@ static void ixgbe_watchdog(unsigned long data) */ IXGBE_WRITE_REG(hw, IXGBE_EICS, (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER)); - goto watchdog_reschedule; - } - - /* get one bit for every active tx/rx interrupt vector */ - for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) { - struct ixgbe_q_vector *qv = adapter->q_vector[i]; - if (qv->rxr_count || qv->txr_count) - eics |= ((u64)1 << i); + } else { + /* get one bit for every active tx/rx interrupt vector */ + for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) { + struct ixgbe_q_vector *qv = adapter->q_vector[i]; + if (qv->rxr_count || qv->txr_count) + eics |= ((u64)1 << i); + } } - /* Cause software interrupt to ensure rx rings are cleaned */ + /* Cause software interrupt to ensure rings are cleaned */ ixgbe_irq_rearm_queues(adapter, eics); -watchdog_reschedule: - /* Reset the timer */ - mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ)); - -watchdog_short_circuit: - schedule_work(&adapter->watchdog_task); } /** - * ixgbe_fdir_reinit_task - worker thread to reinit FDIR filter table - * @work: pointer to work_struct containing our data + * ixgbe_watchdog_update_link - update the link status + * @adapter - pointer to the device adapter structure + * @link_speed - pointer to a u32 to store the link_speed **/ -static void ixgbe_fdir_reinit_task(struct work_struct *work) +static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter) { - struct ixgbe_adapter *adapter = container_of(work, - struct ixgbe_adapter, - fdir_reinit_task); struct ixgbe_hw *hw = &adapter->hw; + u32 link_speed = adapter->link_speed; + bool link_up = adapter->link_up; int i; - if (ixgbe_reinit_fdir_tables_82599(hw) == 0) { - for (i = 0; i < adapter->num_tx_queues; i++) - set_bit(__IXGBE_TX_FDIR_INIT_DONE, - &(adapter->tx_ring[i]->state)); + if (!(adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE)) + return; + + if (hw->mac.ops.check_link) { + hw->mac.ops.check_link(hw, &link_speed, &link_up, false); } else { - e_err(probe, "failed to finish FDIR re-initialization, " - "ignored adding FDIR ATR filters\n"); + /* always assume link is up, if no check link function */ + link_speed = IXGBE_LINK_SPEED_10GB_FULL; + link_up = true; } - /* Done FDIR Re-initialization, enable transmits */ - netif_tx_start_all_queues(adapter->netdev); + if (link_up) { + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + for (i = 0; i < MAX_TRAFFIC_CLASS; i++) + hw->mac.ops.fc_enable(hw, i); + } else { + hw->mac.ops.fc_enable(hw, 0); + } + } + + if (link_up || + time_after(jiffies, (adapter->link_check_timeout + + IXGBE_TRY_LINK_TIMEOUT))) { + adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE; + IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC); + IXGBE_WRITE_FLUSH(hw); + } + + adapter->link_up = link_up; + adapter->link_speed = link_speed; } -static void ixgbe_spoof_check(struct ixgbe_adapter *adapter) +/** + * ixgbe_watchdog_link_is_up - update netif_carrier status and + * print link up message + * @adapter - pointer to the device adapter structure + **/ +static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) { - u32 ssvpc; + struct net_device *netdev = adapter->netdev; + struct ixgbe_hw *hw = &adapter->hw; + u32 link_speed = adapter->link_speed; + bool flow_rx, flow_tx; - /* Do not perform spoof check for 82598 */ - if (adapter->hw.mac.type == ixgbe_mac_82598EB) + /* only continue if link was previously down */ + if (netif_carrier_ok(netdev)) return; - ssvpc = IXGBE_READ_REG(&adapter->hw, IXGBE_SSVPC); + adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP; - /* - * ssvpc register is cleared on read, if zero then no - * spoofed packets in the last interval. - */ - if (!ssvpc) - return; + switch (hw->mac.type) { + case ixgbe_mac_82598EB: { + u32 frctl = IXGBE_READ_REG(hw, IXGBE_FCTRL); + u32 rmcs = IXGBE_READ_REG(hw, IXGBE_RMCS); + flow_rx = !!(frctl & IXGBE_FCTRL_RFCE); + flow_tx = !!(rmcs & IXGBE_RMCS_TFCE_802_3X); + } + break; + case ixgbe_mac_X540: + case ixgbe_mac_82599EB: { + u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN); + u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG); + flow_rx = !!(mflcn & IXGBE_MFLCN_RFCE); + flow_tx = !!(fccfg & IXGBE_FCCFG_TFCE_802_3X); + } + break; + default: + flow_tx = false; + flow_rx = false; + break; + } + e_info(drv, "NIC Link is Up %s, Flow Control: %s\n", + (link_speed == IXGBE_LINK_SPEED_10GB_FULL ? + "10 Gbps" : + (link_speed == IXGBE_LINK_SPEED_1GB_FULL ? + "1 Gbps" : + (link_speed == IXGBE_LINK_SPEED_100_FULL ? + "100 Mbps" : + "unknown speed"))), + ((flow_rx && flow_tx) ? "RX/TX" : + (flow_rx ? "RX" : + (flow_tx ? "TX" : "None")))); - e_warn(drv, "%d Spoofed packets detected\n", ssvpc); + netif_carrier_on(netdev); +#ifdef HAVE_IPLINK_VF_CONFIG + ixgbe_check_vf_rate_limit(adapter); +#endif /* HAVE_IPLINK_VF_CONFIG */ } -static DEFINE_MUTEX(ixgbe_watchdog_lock); - /** - * ixgbe_watchdog_task - worker thread to bring link up - * @work: pointer to work_struct containing our data + * ixgbe_watchdog_link_is_down - update netif_carrier status and + * print link down message + * @adapter - pointer to the adapter structure **/ -static void ixgbe_watchdog_task(struct work_struct *work) +static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter* adapter) { - struct ixgbe_adapter *adapter = container_of(work, - struct ixgbe_adapter, - watchdog_task); struct net_device *netdev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; - u32 link_speed; - bool link_up; - int i; - struct ixgbe_ring *tx_ring; - int some_tx_pending = 0; - - mutex_lock(&ixgbe_watchdog_lock); - link_up = adapter->link_up; - link_speed = adapter->link_speed; + adapter->link_up = false; + adapter->link_speed = 0; - if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE) { - hw->mac.ops.check_link(hw, &link_speed, &link_up, false); - if (link_up) { -#ifdef CONFIG_DCB - if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - for (i = 0; i < MAX_TRAFFIC_CLASS; i++) - hw->mac.ops.fc_enable(hw, i); - } else { - hw->mac.ops.fc_enable(hw, 0); - } -#else - hw->mac.ops.fc_enable(hw, 0); -#endif - } + /* only continue if link was up previously */ + if (!netif_carrier_ok(netdev)) + return; - if (link_up || - time_after(jiffies, (adapter->link_check_timeout + - IXGBE_TRY_LINK_TIMEOUT))) { - adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE; - IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC); - } - adapter->link_up = link_up; - adapter->link_speed = link_speed; - } + /* poll for SFP+ cable when link is down */ + if (ixgbe_is_sfp(hw) && hw->mac.type == ixgbe_mac_82598EB) + adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP; - if (link_up) { - if (!netif_carrier_ok(netdev)) { - bool flow_rx, flow_tx; - - switch (hw->mac.type) { - case ixgbe_mac_82598EB: { - u32 frctl = IXGBE_READ_REG(hw, IXGBE_FCTRL); - u32 rmcs = IXGBE_READ_REG(hw, IXGBE_RMCS); - flow_rx = !!(frctl & IXGBE_FCTRL_RFCE); - flow_tx = !!(rmcs & IXGBE_RMCS_TFCE_802_3X); - } - break; - case ixgbe_mac_82599EB: - case ixgbe_mac_X540: { - u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN); - u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG); - flow_rx = !!(mflcn & IXGBE_MFLCN_RFCE); - flow_tx = !!(fccfg & IXGBE_FCCFG_TFCE_802_3X); - } - break; - default: - flow_tx = false; - flow_rx = false; - break; - } + e_info(drv, "NIC Link is Down\n"); + netif_carrier_off(netdev); +} - e_info(drv, "NIC Link is Up %s, Flow Control: %s\n", - (link_speed == IXGBE_LINK_SPEED_10GB_FULL ? - "10 Gbps" : - (link_speed == IXGBE_LINK_SPEED_1GB_FULL ? - "1 Gbps" : - (link_speed == IXGBE_LINK_SPEED_100_FULL ? - "100 Mbps" : - "unknown speed"))), - ((flow_rx && flow_tx) ? "RX/TX" : - (flow_rx ? "RX" : - (flow_tx ? "TX" : "None")))); - - netif_carrier_on(netdev); - ixgbe_check_vf_rate_limit(adapter); - } else { - /* Force detection of hung controller */ - for (i = 0; i < adapter->num_tx_queues; i++) { - tx_ring = adapter->tx_ring[i]; - set_check_for_tx_hang(tx_ring); - } - } - } else { - adapter->link_up = false; - adapter->link_speed = 0; - if (netif_carrier_ok(netdev)) { - e_info(drv, "NIC Link is Down\n"); - netif_carrier_off(netdev); - } - } +/** + * ixgbe_watchdog_flush_tx - flush queues on link down + * @adapter - pointer to the device adapter structure + **/ +static void ixgbe_watchdog_flush_tx(struct ixgbe_adapter *adapter) +{ + int i; + int some_tx_pending = 0; - if (!netif_carrier_ok(netdev)) { + if (!netif_carrier_ok(adapter->netdev)) { for (i = 0; i < adapter->num_tx_queues; i++) { - tx_ring = adapter->tx_ring[i]; + struct ixgbe_ring *tx_ring = adapter->tx_ring[i]; if (tx_ring->next_to_use != tx_ring->next_to_clean) { some_tx_pending = 1; break; @@ -6168,13 +6174,52 @@ static void ixgbe_watchdog_task(struct work_struct *work) * to get done, so reset controller to flush Tx. * (Do the reset outside of interrupt context). */ - schedule_work(&adapter->reset_task); + schedule_work(&adapter->reset_task); } } +} + +static void ixgbe_spoof_check(struct ixgbe_adapter *adapter) +{ + u32 ssvpc; + + /* Do not perform spoof check for 82598 */ + if (adapter->hw.mac.type == ixgbe_mac_82598EB) + return; + + ssvpc = IXGBE_READ_REG(&adapter->hw, IXGBE_SSVPC); + + /* + * ssvpc register is cleared on read, if zero then no + * spoofed packets in the last interval. + */ + if (!ssvpc) + return; + + e_warn(drv, "%d Spoofed packets detected\n", ssvpc); +} + +/** + * ixgbe_watchdog_subtask - check and bring link up + * @adapter - pointer to the device adapter structure + **/ +static void ixgbe_watchdog_subtask(struct ixgbe_adapter *adapter) +{ + /* if interface is down do nothing */ + if (test_bit(__IXGBE_DOWN, &adapter->state)) + return; + + ixgbe_watchdog_update_link(adapter); + + if (adapter->link_up) + ixgbe_watchdog_link_is_up(adapter); + else + ixgbe_watchdog_link_is_down(adapter); ixgbe_spoof_check(adapter); ixgbe_update_stats(adapter); - mutex_unlock(&ixgbe_watchdog_lock); + + ixgbe_watchdog_flush_tx(adapter); } /** @@ -6308,6 +6353,8 @@ static void ixgbe_service_task(struct work_struct *work) ixgbe_sfp_detection_subtask(adapter); ixgbe_sfp_link_config_subtask(adapter); + ixgbe_watchdog_subtask(adapter); + ixgbe_check_hang_subtask(adapter); ixgbe_service_event_complete(adapter); } @@ -7485,12 +7532,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, setup_timer(&adapter->service_timer, &ixgbe_service_timer, (unsigned long) adapter); - init_timer(&adapter->watchdog_timer); - adapter->watchdog_timer.function = ixgbe_watchdog; - adapter->watchdog_timer.data = (unsigned long)adapter; INIT_WORK(&adapter->reset_task, ixgbe_reset_task); - INIT_WORK(&adapter->watchdog_task, ixgbe_watchdog_task); INIT_WORK(&adapter->service_task, ixgbe_service_task); clear_bit(__IXGBE_SERVICE_SCHED, &adapter->state); @@ -7643,13 +7686,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) set_bit(__IXGBE_DOWN, &adapter->state); cancel_work_sync(&adapter->service_task); - /* - * The timers may be rescheduled, so explicitly disable them - * from being rescheduled. - */ - del_timer_sync(&adapter->watchdog_timer); - - cancel_work_sync(&adapter->watchdog_task); if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE || adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) cancel_work_sync(&adapter->fdir_reinit_task); -- cgit v1.2.3-58-ga151 From c83c6cbdbff360e5323748720dfb2b000c0ae491 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 27 Apr 2011 09:21:16 +0000 Subject: ixgbe: merge reset task into service task This change is meant to further help to reduce possible configuration collisions between the various tasklets. This change combines the device reset with the service task. As a result it is now not possible to be updating the link on the device while also resetting the part. Signed-off-by: Alexander Duyck Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe.h | 2 +- drivers/net/ixgbe/ixgbe_main.c | 60 ++++++++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 193c6c4243cb..760b850e8292 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -381,6 +381,7 @@ struct ixgbe_adapter { #define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 2) #define IXGBE_FLAG2_SEARCH_FOR_SFP (u32)(1 << 4) #define IXGBE_FLAG2_SFP_NEEDS_RESET (u32)(1 << 5) +#define IXGBE_FLAG2_RESET_REQUESTED (u32)(1 << 6) unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; u16 bd_number; @@ -454,7 +455,6 @@ struct ixgbe_adapter { bool link_up; unsigned long link_check_timeout; - struct work_struct reset_task; struct work_struct fdir_reinit_task; struct work_struct check_overtemp_task; struct work_struct service_task; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index d1e52b5cebfa..dbb20e57f660 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -833,7 +833,19 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_ring *tx_ring) #define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \ MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */ -static void ixgbe_tx_timeout(struct net_device *netdev); +/** + * ixgbe_tx_timeout_reset - initiate reset due to Tx timeout + * @adapter: driver private struct + **/ +static void ixgbe_tx_timeout_reset(struct ixgbe_adapter *adapter) +{ + + /* Do the reset outside of interrupt context */ + if (!test_bit(__IXGBE_DOWN, &adapter->state)) { + adapter->flags2 |= IXGBE_FLAG2_RESET_REQUESTED; + ixgbe_service_event_schedule(adapter); + } +} /** * ixgbe_clean_tx_irq - Reclaim resources after transmit completes @@ -915,7 +927,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, adapter->tx_timeout_count + 1, tx_ring->queue_index); /* schedule immediate reset if we believe we hung */ - ixgbe_tx_timeout(adapter->netdev); + ixgbe_tx_timeout_reset(adapter); /* the adapter is about to reset, no point in enabling stuff */ return true; @@ -4186,6 +4198,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) ixgbe_napi_disable_all(adapter); + adapter->flags2 &= ~IXGBE_FLAG2_RESET_REQUESTED; adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE; del_timer_sync(&adapter->service_timer); @@ -4288,25 +4301,8 @@ static void ixgbe_tx_timeout(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - adapter->tx_timeout_count++; - /* Do the reset outside of interrupt context */ - schedule_work(&adapter->reset_task); -} - -static void ixgbe_reset_task(struct work_struct *work) -{ - struct ixgbe_adapter *adapter; - adapter = container_of(work, struct ixgbe_adapter, reset_task); - - /* If we're already down or resetting, just bail */ - if (test_bit(__IXGBE_DOWN, &adapter->state) || - test_bit(__IXGBE_RESETTING, &adapter->state)) - return; - - ixgbe_dump(adapter); - netdev_err(adapter->netdev, "Reset adapter\n"); - ixgbe_reinit_locked(adapter); + ixgbe_tx_timeout_reset(adapter); } /** @@ -6174,7 +6170,7 @@ static void ixgbe_watchdog_flush_tx(struct ixgbe_adapter *adapter) * to get done, so reset controller to flush Tx. * (Do the reset outside of interrupt context). */ - schedule_work(&adapter->reset_task); + adapter->flags2 |= IXGBE_FLAG2_RESET_REQUESTED; } } } @@ -6341,6 +6337,25 @@ static void ixgbe_service_timer(unsigned long data) ixgbe_service_event_schedule(adapter); } +static void ixgbe_reset_subtask(struct ixgbe_adapter *adapter) +{ + if (!(adapter->flags2 & IXGBE_FLAG2_RESET_REQUESTED)) + return; + + adapter->flags2 &= ~IXGBE_FLAG2_RESET_REQUESTED; + + /* If we're already down or resetting, just bail */ + if (test_bit(__IXGBE_DOWN, &adapter->state) || + test_bit(__IXGBE_RESETTING, &adapter->state)) + return; + + ixgbe_dump(adapter); + netdev_err(adapter->netdev, "Reset adapter\n"); + adapter->tx_timeout_count++; + + ixgbe_reinit_locked(adapter); +} + /** * ixgbe_service_task - manages and runs subtasks * @work: pointer to work_struct containing our data @@ -6351,6 +6366,7 @@ static void ixgbe_service_task(struct work_struct *work) struct ixgbe_adapter, service_task); + ixgbe_reset_subtask(adapter); ixgbe_sfp_detection_subtask(adapter); ixgbe_sfp_link_config_subtask(adapter); ixgbe_watchdog_subtask(adapter); @@ -7533,8 +7549,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, setup_timer(&adapter->service_timer, &ixgbe_service_timer, (unsigned long) adapter); - INIT_WORK(&adapter->reset_task, ixgbe_reset_task); - INIT_WORK(&adapter->service_task, ixgbe_service_task); clear_bit(__IXGBE_SERVICE_SCHED, &adapter->state); -- cgit v1.2.3-58-ga151 From d034acf1851c15c3da56d31e7eb4151e40ed0119 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 27 Apr 2011 09:25:34 +0000 Subject: ixgbe: Merge ATR reinit into the service task This change merges the ATR table reinitialization into the service task. This is yet another opportunity to avoid any race conditions as we don't want to be attempting to reinitialize the table during a possible reset. In addition this change adds a counter for table reinitialization so that it can be tracked as part of the regular statistics. Signed-off-by: Alexander Duyck Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe.h | 3 +- drivers/net/ixgbe/ixgbe_ethtool.c | 1 + drivers/net/ixgbe/ixgbe_main.c | 65 ++++++++++++++++++++------------------- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 760b850e8292..a180cde6008a 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -382,6 +382,7 @@ struct ixgbe_adapter { #define IXGBE_FLAG2_SEARCH_FOR_SFP (u32)(1 << 4) #define IXGBE_FLAG2_SFP_NEEDS_RESET (u32)(1 << 5) #define IXGBE_FLAG2_RESET_REQUESTED (u32)(1 << 6) +#define IXGBE_FLAG2_FDIR_REQUIRES_REINIT (u32)(1 << 7) unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; u16 bd_number; @@ -455,12 +456,12 @@ struct ixgbe_adapter { bool link_up; unsigned long link_check_timeout; - struct work_struct fdir_reinit_task; struct work_struct check_overtemp_task; struct work_struct service_task; struct timer_list service_timer; u32 fdir_pballoc; u32 atr_sample_rate; + unsigned long fdir_overflow; /* number of times ATR was backed off */ spinlock_t fdir_perfect_lock; #ifdef IXGBE_FCOE struct ixgbe_fcoe fcoe; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 1fdd075afe79..cb1555bc8548 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -84,6 +84,7 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = { {"hw_rsc_flushed", IXGBE_STAT(rsc_total_flush)}, {"fdir_match", IXGBE_STAT(stats.fdirmatch)}, {"fdir_miss", IXGBE_STAT(stats.fdirmiss)}, + {"fdir_overflow", IXGBE_STAT(fdir_overflow)}, {"rx_fifo_errors", IXGBE_NETDEV_STAT(rx_fifo_errors)}, {"rx_missed_errors", IXGBE_NETDEV_STAT(rx_missed_errors)}, {"tx_aborted_errors", IXGBE_NETDEV_STAT(tx_aborted_errors)}, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index dbb20e57f660..7edd3603344a 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1950,16 +1950,20 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) case ixgbe_mac_X540: /* Handle Flow Director Full threshold interrupt */ if (eicr & IXGBE_EICR_FLOW_DIR) { + int reinit_count = 0; int i; - IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_FLOW_DIR); - /* Disable transmits before FDIR Re-initialization */ - netif_tx_stop_all_queues(netdev); for (i = 0; i < adapter->num_tx_queues; i++) { - struct ixgbe_ring *tx_ring = - adapter->tx_ring[i]; + struct ixgbe_ring *ring = adapter->tx_ring[i]; if (test_and_clear_bit(__IXGBE_TX_FDIR_INIT_DONE, - &tx_ring->state)) - schedule_work(&adapter->fdir_reinit_task); + &ring->state)) + reinit_count++; + } + if (reinit_count) { + /* no more flow director interrupts until after init */ + IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR); + eicr &= ~IXGBE_EICR_FLOW_DIR; + adapter->flags2 |= IXGBE_FLAG2_FDIR_REQUIRES_REINIT; + ixgbe_service_event_schedule(adapter); } } break; @@ -4198,7 +4202,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter) ixgbe_napi_disable_all(adapter); - adapter->flags2 &= ~IXGBE_FLAG2_RESET_REQUESTED; + adapter->flags2 &= ~(IXGBE_FLAG2_FDIR_REQUIRES_REINIT | + IXGBE_FLAG2_RESET_REQUESTED); adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE; del_timer_sync(&adapter->service_timer); @@ -4212,13 +4217,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter) free_cpumask_var(q_vector->affinity_mask); } - if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE || - adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) - cancel_work_sync(&adapter->fdir_reinit_task); - - if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) - cancel_work_sync(&adapter->check_overtemp_task); - /* disable transmits in the hardware now that interrupts are off */ for (i = 0; i < adapter->num_tx_queues; i++) { u8 reg_idx = adapter->tx_ring[i]->reg_idx; @@ -5950,27 +5948,39 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) } /** - * ixgbe_fdir_reinit_task - worker thread to reinit FDIR filter table - * @work: pointer to work_struct containing our data + * ixgbe_fdir_reinit_subtask - worker thread to reinit FDIR filter table + * @adapter - pointer to the device adapter structure **/ -static void ixgbe_fdir_reinit_task(struct work_struct *work) +static void ixgbe_fdir_reinit_subtask(struct ixgbe_adapter *adapter) { - struct ixgbe_adapter *adapter = container_of(work, - struct ixgbe_adapter, - fdir_reinit_task); struct ixgbe_hw *hw = &adapter->hw; int i; + if (!(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT)) + return; + + adapter->flags2 &= ~IXGBE_FLAG2_FDIR_REQUIRES_REINIT; + + /* if interface is down do nothing */ + if (test_bit(__IXGBE_DOWN, &adapter->state)) + return; + + /* do nothing if we are not using signature filters */ + if (!(adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)) + return; + + adapter->fdir_overflow++; + if (ixgbe_reinit_fdir_tables_82599(hw) == 0) { for (i = 0; i < adapter->num_tx_queues; i++) set_bit(__IXGBE_TX_FDIR_INIT_DONE, &(adapter->tx_ring[i]->state)); + /* re-enable flow director interrupts */ + IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR); } else { e_err(probe, "failed to finish FDIR re-initialization, " "ignored adding FDIR ATR filters\n"); } - /* Done FDIR Re-initialization, enable transmits */ - netif_tx_start_all_queues(adapter->netdev); } /** @@ -6370,6 +6380,7 @@ static void ixgbe_service_task(struct work_struct *work) ixgbe_sfp_detection_subtask(adapter); ixgbe_sfp_link_config_subtask(adapter); ixgbe_watchdog_subtask(adapter); + ixgbe_fdir_reinit_subtask(adapter); ixgbe_check_hang_subtask(adapter); ixgbe_service_event_complete(adapter); @@ -7637,10 +7648,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, /* carrier off reporting is important to ethtool even BEFORE open */ netif_carrier_off(netdev); - if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE || - adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) - INIT_WORK(&adapter->fdir_reinit_task, ixgbe_fdir_reinit_task); - if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) INIT_WORK(&adapter->check_overtemp_task, ixgbe_check_overtemp_task); @@ -7700,12 +7707,8 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) set_bit(__IXGBE_DOWN, &adapter->state); cancel_work_sync(&adapter->service_task); - if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE || - adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) - cancel_work_sync(&adapter->fdir_reinit_task); if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) cancel_work_sync(&adapter->check_overtemp_task); - #ifdef CONFIG_IXGBE_DCA if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED; -- cgit v1.2.3-58-ga151 From f0f9778d043481f3cded693849e3b88b01fbc69b Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 22 Apr 2011 04:08:09 +0000 Subject: ixgbe: Merge over-temp task into service task This change merges the over-temp task into the service task. As a result all tasklets are finally combined into once single tasklet for easier management. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe.h | 2 +- drivers/net/ixgbe/ixgbe_main.c | 87 +++++++++++++++++++++++++----------------- 2 files changed, 53 insertions(+), 36 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index a180cde6008a..e467b20ed1f0 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -379,6 +379,7 @@ struct ixgbe_adapter { #define IXGBE_FLAG2_RSC_CAPABLE (u32)(1) #define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1) #define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 2) +#define IXGBE_FLAG2_TEMP_SENSOR_EVENT (u32)(1 << 3) #define IXGBE_FLAG2_SEARCH_FOR_SFP (u32)(1 << 4) #define IXGBE_FLAG2_SFP_NEEDS_RESET (u32)(1 << 5) #define IXGBE_FLAG2_RESET_REQUESTED (u32)(1 << 6) @@ -456,7 +457,6 @@ struct ixgbe_adapter { bool link_up; unsigned long link_check_timeout; - struct work_struct check_overtemp_task; struct work_struct service_task; struct timer_list service_timer; u32 fdir_pballoc; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 7edd3603344a..dad56e15d4f9 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1825,35 +1825,51 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) } /** - * ixgbe_check_overtemp_task - worker thread to check over tempurature - * @work: pointer to work_struct containing our data + * ixgbe_check_overtemp_subtask - check for over tempurature + * @adapter: pointer to adapter **/ -static void ixgbe_check_overtemp_task(struct work_struct *work) +static void ixgbe_check_overtemp_subtask(struct ixgbe_adapter *adapter) { - struct ixgbe_adapter *adapter = container_of(work, - struct ixgbe_adapter, - check_overtemp_task); struct ixgbe_hw *hw = &adapter->hw; u32 eicr = adapter->interrupt_event; - if (!(adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)) + if (test_bit(__IXGBE_DOWN, &adapter->state)) return; + if (!(adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) && + !(adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_EVENT)) + return; + + adapter->flags2 &= ~IXGBE_FLAG2_TEMP_SENSOR_EVENT; + switch (hw->device_id) { - case IXGBE_DEV_ID_82599_T3_LOM: { - u32 autoneg; - bool link_up = false; + case IXGBE_DEV_ID_82599_T3_LOM: + /* + * Since the warning interrupt is for both ports + * we don't have to check if: + * - This interrupt wasn't for our port. + * - We may have missed the interrupt so always have to + * check if we got a LSC + */ + if (!(eicr & IXGBE_EICR_GPI_SDP0) && + !(eicr & IXGBE_EICR_LSC)) + return; + + if (!(eicr & IXGBE_EICR_LSC) && hw->mac.ops.check_link) { + u32 autoneg; + bool link_up = false; - if (hw->mac.ops.check_link) hw->mac.ops.check_link(hw, &autoneg, &link_up, false); - if (((eicr & IXGBE_EICR_GPI_SDP0) && (!link_up)) || - (eicr & IXGBE_EICR_LSC)) - /* Check if this is due to overtemp */ - if (hw->phy.ops.check_overtemp(hw) == IXGBE_ERR_OVERTEMP) - break; - return; - } + if (link_up) + return; + } + + /* Check if this is not due to overtemp */ + if (hw->phy.ops.check_overtemp(hw) != IXGBE_ERR_OVERTEMP) + return; + + break; default: if (!(eicr & IXGBE_EICR_GPI_SDP0)) return; @@ -1863,8 +1879,8 @@ static void ixgbe_check_overtemp_task(struct work_struct *work) "Network adapter has been stopped because it has over heated. " "Restart the computer. If the problem persists, " "power off the system and replace the adapter\n"); - /* write to clear the interrupt */ - IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0); + + adapter->interrupt_event = 0; } static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr) @@ -1940,13 +1956,6 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) switch (hw->mac.type) { case ixgbe_mac_82599EB: - ixgbe_check_sfp_event(adapter, eicr); - if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) && - ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) { - adapter->interrupt_event = eicr; - schedule_work(&adapter->check_overtemp_task); - } - /* now fallthrough to handle Flow Director */ case ixgbe_mac_X540: /* Handle Flow Director Full threshold interrupt */ if (eicr & IXGBE_EICR_FLOW_DIR) { @@ -1966,6 +1975,15 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) ixgbe_service_event_schedule(adapter); } } + ixgbe_check_sfp_event(adapter, eicr); + if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) && + ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) { + if (!test_bit(__IXGBE_DOWN, &adapter->state)) { + adapter->interrupt_event = eicr; + adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_EVENT; + ixgbe_service_event_schedule(adapter); + } + } break; default: break; @@ -2561,8 +2579,11 @@ static irqreturn_t ixgbe_intr(int irq, void *data) ixgbe_check_sfp_event(adapter, eicr); if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) && ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) { - adapter->interrupt_event = eicr; - schedule_work(&adapter->check_overtemp_task); + if (!test_bit(__IXGBE_DOWN, &adapter->state)) { + adapter->interrupt_event = eicr; + adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_EVENT; + ixgbe_service_event_schedule(adapter); + } } break; default: @@ -5974,7 +5995,7 @@ static void ixgbe_fdir_reinit_subtask(struct ixgbe_adapter *adapter) if (ixgbe_reinit_fdir_tables_82599(hw) == 0) { for (i = 0; i < adapter->num_tx_queues; i++) set_bit(__IXGBE_TX_FDIR_INIT_DONE, - &(adapter->tx_ring[i]->state)); + &(adapter->tx_ring[i]->state)); /* re-enable flow director interrupts */ IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR); } else { @@ -6379,6 +6400,7 @@ static void ixgbe_service_task(struct work_struct *work) ixgbe_reset_subtask(adapter); ixgbe_sfp_detection_subtask(adapter); ixgbe_sfp_link_config_subtask(adapter); + ixgbe_check_overtemp_subtask(adapter); ixgbe_watchdog_subtask(adapter); ixgbe_fdir_reinit_subtask(adapter); ixgbe_check_hang_subtask(adapter); @@ -7648,9 +7670,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, /* carrier off reporting is important to ethtool even BEFORE open */ netif_carrier_off(netdev); - if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) - INIT_WORK(&adapter->check_overtemp_task, - ixgbe_check_overtemp_task); #ifdef CONFIG_IXGBE_DCA if (dca_add_requester(&pdev->dev) == 0) { adapter->flags |= IXGBE_FLAG_DCA_ENABLED; @@ -7707,8 +7726,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) set_bit(__IXGBE_DOWN, &adapter->state); cancel_work_sync(&adapter->service_task); - if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) - cancel_work_sync(&adapter->check_overtemp_task); #ifdef CONFIG_IXGBE_DCA if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED; -- cgit v1.2.3-58-ga151 From 34cecbbfad5a01050604d5b12fd7d7fb02597dbe Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 22 Apr 2011 04:08:14 +0000 Subject: ixgbe: cleanup some minor issues in ixgbe_down() This patch cleans up two minor issues in ixgbe_down. Specifically it addresses the fact that the VFs should not be pinged until after interrupts are disabled otherwise they might still get a response. It also drops the use of the txdctl temporary variable since the only bit we should be writing to the TXDCTL registers during a shutdown is the flush bit. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_main.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index dad56e15d4f9..4be2af22d69b 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4182,26 +4182,12 @@ void ixgbe_down(struct ixgbe_adapter *adapter) struct net_device *netdev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; u32 rxctrl; - u32 txdctl; int i; int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; /* signal that we are down to the interrupt handler */ set_bit(__IXGBE_DOWN, &adapter->state); - /* disable receive for all VFs and wait one second */ - if (adapter->num_vfs) { - /* ping all the active vfs to let them know we are going down */ - ixgbe_ping_all_vfs(adapter); - - /* Disable all VFTE/VFRE TX/RX */ - ixgbe_disable_tx_rx(adapter); - - /* Mark all the VFs as inactive */ - for (i = 0 ; i < adapter->num_vfs; i++) - adapter->vfinfo[i].clear_to_send = 0; - } - /* disable receives */ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN); @@ -4229,6 +4215,19 @@ void ixgbe_down(struct ixgbe_adapter *adapter) del_timer_sync(&adapter->service_timer); + /* disable receive for all VFs and wait one second */ + if (adapter->num_vfs) { + /* ping all the active vfs to let them know we are going down */ + ixgbe_ping_all_vfs(adapter); + + /* Disable all VFTE/VFRE TX/RX */ + ixgbe_disable_tx_rx(adapter); + + /* Mark all the VFs as inactive */ + for (i = 0 ; i < adapter->num_vfs; i++) + adapter->vfinfo[i].clear_to_send = 0; + } + /* Cleanup the affinity_hint CPU mask memory and callback */ for (i = 0; i < num_q_vectors; i++) { struct ixgbe_q_vector *q_vector = adapter->q_vector[i]; @@ -4241,11 +4240,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter) /* disable transmits in the hardware now that interrupts are off */ for (i = 0; i < adapter->num_tx_queues; i++) { u8 reg_idx = adapter->tx_ring[i]->reg_idx; - txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx)); - IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), - (txdctl & ~IXGBE_TXDCTL_ENABLE)); + IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH); } - /* Disable the Tx DMA engine on 82599 */ + + /* Disable the Tx DMA engine on 82599 and X540 */ switch (hw->mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: -- cgit v1.2.3-58-ga151 From c050999e2c00b189a21df3ee9ad8d27c85ce9c34 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Sat, 7 May 2011 06:49:18 +0000 Subject: ixgbe: fix sparse warning error: bad constant expression Signed-off-by: Emil Tantilov Tested-by: Evan Swanson Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_sriov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c index 9f972460e780..ac99b0458fe2 100644 --- a/drivers/net/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ixgbe/ixgbe_sriov.c @@ -324,7 +324,7 @@ static inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf) static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) { u32 mbx_size = IXGBE_VFMAILBOX_SIZE; - u32 msgbuf[mbx_size]; + u32 msgbuf[IXGBE_VFMAILBOX_SIZE]; struct ixgbe_hw *hw = &adapter->hw; s32 retval; int entries; -- cgit v1.2.3-58-ga151 From 4f6290cf610a7a48b39603ff7822746463453e01 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Sat, 14 May 2011 06:36:35 +0000 Subject: ixgbe: Add support for new 82599 adapter This patch adds support for a new adapter in the 82599 family. Included in that support is a new media_type ixgbe_media_type_fiber_lco. Signed-of-by: Don Skidmore Signed-off-by: Jeff Kirsher --- drivers/net/ixgbe/ixgbe_82599.c | 3 +++ drivers/net/ixgbe/ixgbe_main.c | 2 ++ drivers/net/ixgbe/ixgbe_type.h | 2 ++ 3 files changed, 7 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index dba5ca6e35c4..8ee661245af3 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -368,6 +368,9 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82599_T3_LOM: media_type = ixgbe_media_type_copper; break; + case IXGBE_DEV_ID_82599_LS: + media_type = ixgbe_media_type_fiber_lco; + break; default: media_type = ixgbe_media_type_unknown; break; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 4be2af22d69b..2dce3d038188 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -126,6 +126,8 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = { board_X540 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF2), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS), + board_82599 }, /* required last entry */ {0, } diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 70e6870be01f..fa43f2507f43 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -62,6 +62,7 @@ #define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC #define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8 #define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ 0x000C +#define IXGBE_DEV_ID_82599_LS 0x154F #define IXGBE_DEV_ID_X540T 0x1528 /* General Registers */ @@ -2395,6 +2396,7 @@ enum ixgbe_sfp_type { enum ixgbe_media_type { ixgbe_media_type_unknown = 0, ixgbe_media_type_fiber, + ixgbe_media_type_fiber_lco, ixgbe_media_type_copper, ixgbe_media_type_backplane, ixgbe_media_type_cx4, -- cgit v1.2.3-58-ga151 From 1b1cb1f78a5e9d54c13e176020c3e8ded5d081ce Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 13 May 2011 22:59:19 +0000 Subject: net: ping: small changes ping_table is not __read_mostly, since it contains one rwlock, and is static to ping.c ping_port_rover & ping_v4_lookup are static Signed-off-by: Eric Dumazet Acked-by: Vasiliy Kulikov Signed-off-by: David S. Miller --- net/ipv4/ping.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index a77e2d788dac..7041d09ae5d5 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -49,9 +49,9 @@ #include -struct ping_table ping_table __read_mostly; +static struct ping_table ping_table; -u16 ping_port_rover; +static u16 ping_port_rover; static inline int ping_hashfn(struct net *net, unsigned num, unsigned mask) { @@ -150,8 +150,8 @@ static void ping_v4_unhash(struct sock *sk) } } -struct sock *ping_v4_lookup(struct net *net, u32 saddr, u32 daddr, - u16 ident, int dif) +static struct sock *ping_v4_lookup(struct net *net, u32 saddr, u32 daddr, + u16 ident, int dif) { struct hlist_nulls_head *hslot = ping_hashslot(&ping_table, net, ident); struct sock *sk = NULL; -- cgit v1.2.3-58-ga151 From 0b1e9738deb30f4c35c0add43a52dcd0608b227e Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Fri, 13 May 2011 02:43:59 +0000 Subject: caif: Use rcu_read_lock in CAIF mux layer. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace spin_lock with rcu_read_lock when accessing lists to layers and cache. While packets are in flight rcu_read_lock should not be held, instead ref-counters are used in combination with RCU. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- include/net/caif/cffrml.h | 2 + net/caif/cffrml.c | 8 ++++ net/caif/cfmuxl.c | 119 +++++++++++++++++++++++++++++----------------- 3 files changed, 85 insertions(+), 44 deletions(-) diff --git a/include/net/caif/cffrml.h b/include/net/caif/cffrml.h index 3f14d2e1ce61..4f126d777212 100644 --- a/include/net/caif/cffrml.h +++ b/include/net/caif/cffrml.h @@ -12,5 +12,7 @@ struct cffrml; struct cflayer *cffrml_create(u16 phyid, bool DoFCS); void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up); void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn); +void cffrml_put(struct cflayer *layr); +void cffrml_hold(struct cflayer *layr); #endif /* CFFRML_H_ */ diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c index 2423fed8e26c..f4b88924f83a 100644 --- a/net/caif/cffrml.c +++ b/net/caif/cffrml.c @@ -145,3 +145,11 @@ static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, if (layr->up->ctrlcmd) layr->up->ctrlcmd(layr->up, ctrl, layr->id); } + +void cffrml_put(struct cflayer *layr) +{ +} + +void cffrml_hold(struct cflayer *layr) +{ +} diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c index fc2497468571..2a56df7e0a4b 100644 --- a/net/caif/cfmuxl.c +++ b/net/caif/cfmuxl.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -64,31 +65,31 @@ struct cflayer *cfmuxl_create(void) int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid) { struct cfmuxl *muxl = container_obj(layr); - spin_lock(&muxl->receive_lock); - cfsrvl_get(up); - list_add(&up->node, &muxl->srvl_list); - spin_unlock(&muxl->receive_lock); + + spin_lock_bh(&muxl->receive_lock); + list_add_rcu(&up->node, &muxl->srvl_list); + spin_unlock_bh(&muxl->receive_lock); return 0; } int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *dn, u8 phyid) { struct cfmuxl *muxl = (struct cfmuxl *) layr; - spin_lock(&muxl->transmit_lock); - list_add(&dn->node, &muxl->frml_list); - spin_unlock(&muxl->transmit_lock); + + spin_lock_bh(&muxl->transmit_lock); + list_add_rcu(&dn->node, &muxl->frml_list); + spin_unlock_bh(&muxl->transmit_lock); return 0; } static struct cflayer *get_from_id(struct list_head *list, u16 id) { - struct list_head *node; - struct cflayer *layer; - list_for_each(node, list) { - layer = list_entry(node, struct cflayer, node); - if (layer->id == id) - return layer; + struct cflayer *lyr; + list_for_each_entry_rcu(lyr, list, node) { + if (lyr->id == id) + return lyr; } + return NULL; } @@ -96,41 +97,45 @@ struct cflayer *cfmuxl_remove_dnlayer(struct cflayer *layr, u8 phyid) { struct cfmuxl *muxl = container_obj(layr); struct cflayer *dn; - spin_lock(&muxl->transmit_lock); - memset(muxl->dn_cache, 0, sizeof(muxl->dn_cache)); + int idx = phyid % DN_CACHE_SIZE; + + spin_lock_bh(&muxl->transmit_lock); + rcu_assign_pointer(muxl->dn_cache[idx], NULL); dn = get_from_id(&muxl->frml_list, phyid); - if (dn == NULL) { - spin_unlock(&muxl->transmit_lock); - return NULL; - } - list_del(&dn->node); + if (dn == NULL) + goto out; + + list_del_rcu(&dn->node); caif_assert(dn != NULL); - spin_unlock(&muxl->transmit_lock); +out: + spin_unlock_bh(&muxl->transmit_lock); return dn; } -/* Invariant: lock is taken */ static struct cflayer *get_up(struct cfmuxl *muxl, u16 id) { struct cflayer *up; int idx = id % UP_CACHE_SIZE; - up = muxl->up_cache[idx]; + up = rcu_dereference(muxl->up_cache[idx]); if (up == NULL || up->id != id) { + spin_lock_bh(&muxl->receive_lock); up = get_from_id(&muxl->srvl_list, id); - muxl->up_cache[idx] = up; + rcu_assign_pointer(muxl->up_cache[idx], up); + spin_unlock_bh(&muxl->receive_lock); } return up; } -/* Invariant: lock is taken */ static struct cflayer *get_dn(struct cfmuxl *muxl, struct dev_info *dev_info) { struct cflayer *dn; int idx = dev_info->id % DN_CACHE_SIZE; - dn = muxl->dn_cache[idx]; + dn = rcu_dereference(muxl->dn_cache[idx]); if (dn == NULL || dn->id != dev_info->id) { + spin_lock_bh(&muxl->transmit_lock); dn = get_from_id(&muxl->frml_list, dev_info->id); - muxl->dn_cache[idx] = dn; + rcu_assign_pointer(muxl->dn_cache[idx], dn); + spin_unlock_bh(&muxl->transmit_lock); } return dn; } @@ -139,15 +144,17 @@ struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 id) { struct cflayer *up; struct cfmuxl *muxl = container_obj(layr); - spin_lock(&muxl->receive_lock); - up = get_up(muxl, id); + int idx = id % UP_CACHE_SIZE; + + spin_lock_bh(&muxl->receive_lock); + up = get_from_id(&muxl->srvl_list, id); if (up == NULL) goto out; - memset(muxl->up_cache, 0, sizeof(muxl->up_cache)); - list_del(&up->node); - cfsrvl_put(up); + + rcu_assign_pointer(muxl->up_cache[idx], NULL); + list_del_rcu(&up->node); out: - spin_unlock(&muxl->receive_lock); + spin_unlock_bh(&muxl->receive_lock); return up; } @@ -162,22 +169,28 @@ static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt) cfpkt_destroy(pkt); return -EPROTO; } - - spin_lock(&muxl->receive_lock); + rcu_read_lock(); up = get_up(muxl, id); - spin_unlock(&muxl->receive_lock); + if (up == NULL) { - pr_info("Received data on unknown link ID = %d (0x%x) up == NULL", - id, id); + pr_debug("Received data on unknown link ID = %d (0x%x)" + " up == NULL", id, id); cfpkt_destroy(pkt); /* * Don't return ERROR, since modem misbehaves and sends out * flow on before linksetup response. */ + + rcu_read_unlock(); return /* CFGLU_EPROT; */ 0; } + + /* We can't hold rcu_lock during receive, so take a ref count instead */ cfsrvl_get(up); + rcu_read_unlock(); + ret = up->receive(up, pkt); + cfsrvl_put(up); return ret; } @@ -185,31 +198,49 @@ static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt) static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt) { struct cfmuxl *muxl = container_obj(layr); + int err; u8 linkid; struct cflayer *dn; struct caif_payload_info *info = cfpkt_info(pkt); BUG_ON(!info); + + rcu_read_lock(); + dn = get_dn(muxl, info->dev_info); if (dn == NULL) { - pr_warn("Send data on unknown phy ID = %d (0x%x)\n", + pr_debug("Send data on unknown phy ID = %d (0x%x)\n", info->dev_info->id, info->dev_info->id); + rcu_read_unlock(); + cfpkt_destroy(pkt); return -ENOTCONN; } + info->hdr_len += 1; linkid = info->channel_id; cfpkt_add_head(pkt, &linkid, 1); - return dn->transmit(dn, pkt); + + /* We can't hold rcu_lock during receive, so take a ref count instead */ + cffrml_hold(dn); + + rcu_read_unlock(); + + err = dn->transmit(dn, pkt); + + cffrml_put(dn); + return err; } static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, int phyid) { struct cfmuxl *muxl = container_obj(layr); - struct list_head *node, *next; struct cflayer *layer; - list_for_each_safe(node, next, &muxl->srvl_list) { - layer = list_entry(node, struct cflayer, node); - if (cfsrvl_phyid_match(layer, phyid)) + + rcu_read_lock(); + list_for_each_entry_rcu(layer, &muxl->srvl_list, node) { + if (cfsrvl_phyid_match(layer, phyid) && layer->ctrlcmd) + /* NOTE: ctrlcmd is not allowed to block */ layer->ctrlcmd(layer, ctrl, phyid); } + rcu_read_unlock(); } -- cgit v1.2.3-58-ga151 From bd30ce4bc0b7dc859c1d1cba7ad87e08642418b0 Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Fri, 13 May 2011 02:44:00 +0000 Subject: caif: Use RCU instead of spin-lock in caif_dev.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RCU read_lock and refcount is used to protect in-flight packets. Use RCU and counters to manage freeing lower part of the CAIF stack if CAIF-link layer is removed. Old solution based on delaying removal of device is removed. When CAIF link layer goes down the use of CAIF link layer is disabled (by calling caif_set_phy_state()), but removal and freeing of the lower part of the CAIF stack is done when Link layer is unregistered. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- include/net/caif/cfcnfg.h | 10 ++ net/caif/caif_dev.c | 277 ++++++++++++++++++++++++++-------------------- 2 files changed, 169 insertions(+), 118 deletions(-) diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h index f33d36341132..e0a1eb5d7eaf 100644 --- a/include/net/caif/cfcnfg.h +++ b/include/net/caif/cfcnfg.h @@ -145,4 +145,14 @@ struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, * @ifi: ifindex obtained from socket.c bindtodevice. */ int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi); + +/** + * cfcnfg_set_phy_state() - Set the state of the physical interface device. + * @cnfg: Configuration object + * @phy_layer: Physical Layer representation + * @up: State of device + */ +int cfcnfg_set_phy_state(struct cfcnfg *cnfg, struct cflayer *phy_layer, + bool up); + #endif /* CFCNFG_H_ */ diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index 75e00d59eb49..6d1d86be187b 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -12,14 +12,11 @@ #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ #include -#include #include #include #include #include -#include -#include -#include +#include #include #include #include @@ -30,23 +27,19 @@ #include MODULE_LICENSE("GPL"); -#define TIMEOUT (HZ*5) /* Used for local tracking of the CAIF net devices */ struct caif_device_entry { struct cflayer layer; struct list_head list; - atomic_t in_use; - atomic_t state; - u16 phyid; struct net_device *netdev; - wait_queue_head_t event; + int __percpu *pcpu_refcnt; }; struct caif_device_entry_list { struct list_head list; /* Protects simulanous deletes in list */ - spinlock_t lock; + struct mutex lock; }; struct caif_net { @@ -65,19 +58,39 @@ static struct caif_device_entry_list *caif_device_list(struct net *net) return &caifn->caifdevs; } +static void caifd_put(struct caif_device_entry *e) +{ + irqsafe_cpu_dec(*e->pcpu_refcnt); +} + +static void caifd_hold(struct caif_device_entry *e) +{ + irqsafe_cpu_inc(*e->pcpu_refcnt); +} + +static int caifd_refcnt_read(struct caif_device_entry *e) +{ + int i, refcnt = 0; + for_each_possible_cpu(i) + refcnt += *per_cpu_ptr(e->pcpu_refcnt, i); + return refcnt; +} + /* Allocate new CAIF device. */ static struct caif_device_entry *caif_device_alloc(struct net_device *dev) { struct caif_device_entry_list *caifdevs; struct caif_device_entry *caifd; + caifdevs = caif_device_list(dev_net(dev)); BUG_ON(!caifdevs); + caifd = kzalloc(sizeof(*caifd), GFP_ATOMIC); if (!caifd) return NULL; + caifd->pcpu_refcnt = alloc_percpu(int); caifd->netdev = dev; - list_add(&caifd->list, &caifdevs->list); - init_waitqueue_head(&caifd->event); + dev_hold(dev); return caifd; } @@ -87,35 +100,13 @@ static struct caif_device_entry *caif_get(struct net_device *dev) caif_device_list(dev_net(dev)); struct caif_device_entry *caifd; BUG_ON(!caifdevs); - list_for_each_entry(caifd, &caifdevs->list, list) { + list_for_each_entry_rcu(caifd, &caifdevs->list, list) { if (caifd->netdev == dev) return caifd; } return NULL; } -static void caif_device_destroy(struct net_device *dev) -{ - struct caif_device_entry_list *caifdevs = - caif_device_list(dev_net(dev)); - struct caif_device_entry *caifd; - ASSERT_RTNL(); - if (dev->type != ARPHRD_CAIF) - return; - - spin_lock_bh(&caifdevs->lock); - caifd = caif_get(dev); - if (caifd == NULL) { - spin_unlock_bh(&caifdevs->lock); - return; - } - - list_del(&caifd->list); - spin_unlock_bh(&caifdevs->lock); - - kfree(caifd); -} - static int transmit(struct cflayer *layer, struct cfpkt *pkt) { struct caif_device_entry *caifd = @@ -130,23 +121,8 @@ static int transmit(struct cflayer *layer, struct cfpkt *pkt) return 0; } -static int modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) -{ - struct caif_device_entry *caifd; - caifd = container_of(layr, struct caif_device_entry, layer); - if (ctrl == _CAIF_MODEMCMD_PHYIF_USEFULL) { - atomic_set(&caifd->in_use, 1); - wake_up_interruptible(&caifd->event); - - } else if (ctrl == _CAIF_MODEMCMD_PHYIF_USELESS) { - atomic_set(&caifd->in_use, 0); - wake_up_interruptible(&caifd->event); - } - return 0; -} - /* - * Stuff received packets to associated sockets. + * Stuff received packets into the CAIF stack. * On error, returns non-zero and releases the skb. */ static int receive(struct sk_buff *skb, struct net_device *dev, @@ -154,14 +130,27 @@ static int receive(struct sk_buff *skb, struct net_device *dev, { struct cfpkt *pkt; struct caif_device_entry *caifd; + pkt = cfpkt_fromnative(CAIF_DIR_IN, skb); + + rcu_read_lock(); caifd = caif_get(dev); - if (!caifd || !caifd->layer.up || !caifd->layer.up->receive) - return NET_RX_DROP; - if (caifd->layer.up->receive(caifd->layer.up, pkt)) + if (!caifd || !caifd->layer.up || !caifd->layer.up->receive || + !netif_oper_up(caifd->netdev)) { + rcu_read_unlock(); + kfree_skb(skb); return NET_RX_DROP; + } + + /* Hold reference to netdevice while using CAIF stack */ + caifd_hold(caifd); + rcu_read_unlock(); + caifd->layer.up->receive(caifd->layer.up, pkt); + + /* Release reference to stack upwards */ + caifd_put(caifd); return 0; } @@ -172,15 +161,25 @@ static struct packet_type caif_packet_type __read_mostly = { static void dev_flowctrl(struct net_device *dev, int on) { - struct caif_device_entry *caifd = caif_get(dev); - if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) + struct caif_device_entry *caifd; + + rcu_read_lock(); + + caifd = caif_get(dev); + if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) { + rcu_read_unlock(); return; + } + + caifd_hold(caifd); + rcu_read_unlock(); caifd->layer.up->ctrlcmd(caifd->layer.up, on ? _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND : _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND, caifd->layer.id); + caifd_put(caifd); } /* notify Caif of device events */ @@ -192,34 +191,22 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, struct caif_dev_common *caifdev; enum cfcnfg_phy_preference pref; enum cfcnfg_phy_type phy_type; + struct caif_device_entry_list *caifdevs = + caif_device_list(dev_net(dev)); if (dev->type != ARPHRD_CAIF) return 0; switch (what) { case NETDEV_REGISTER: - netdev_info(dev, "register\n"); caifd = caif_device_alloc(dev); - if (caifd == NULL) - break; + if (!caifd) + return 0; + caifdev = netdev_priv(dev); caifdev->flowctrl = dev_flowctrl; - atomic_set(&caifd->state, what); - break; - case NETDEV_UP: - netdev_info(dev, "up\n"); - caifd = caif_get(dev); - if (caifd == NULL) - break; - caifdev = netdev_priv(dev); - if (atomic_read(&caifd->state) == NETDEV_UP) { - netdev_info(dev, "already up\n"); - break; - } - atomic_set(&caifd->state, what); caifd->layer.transmit = transmit; - caifd->layer.modemcmd = modemcmd; if (caifdev->use_frag) phy_type = CFPHYTYPE_FRAG; @@ -237,62 +224,95 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, pref = CFPHYPREF_HIGH_BW; break; } - dev_hold(dev); + strncpy(caifd->layer.name, dev->name, + sizeof(caifd->layer.name) - 1); + caifd->layer.name[sizeof(caifd->layer.name) - 1] = 0; + + mutex_lock(&caifdevs->lock); + list_add_rcu(&caifd->list, &caifdevs->list); + cfcnfg_add_phy_layer(cfg, phy_type, dev, &caifd->layer, - &caifd->phyid, + 0, pref, caifdev->use_fcs, caifdev->use_stx); - strncpy(caifd->layer.name, dev->name, - sizeof(caifd->layer.name) - 1); - caifd->layer.name[sizeof(caifd->layer.name) - 1] = 0; + mutex_unlock(&caifdevs->lock); break; - case NETDEV_GOING_DOWN: + case NETDEV_UP: + rcu_read_lock(); + caifd = caif_get(dev); - if (caifd == NULL) + if (caifd == NULL) { + rcu_read_unlock(); break; - netdev_info(dev, "going down\n"); + } - if (atomic_read(&caifd->state) == NETDEV_GOING_DOWN || - atomic_read(&caifd->state) == NETDEV_DOWN) - break; + cfcnfg_set_phy_state(cfg, &caifd->layer, true); + rcu_read_unlock(); - atomic_set(&caifd->state, what); - if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) - return -EINVAL; - caifd->layer.up->ctrlcmd(caifd->layer.up, - _CAIF_CTRLCMD_PHYIF_DOWN_IND, - caifd->layer.id); - might_sleep(); - wait_event_interruptible_timeout(caifd->event, - atomic_read(&caifd->in_use) == 0, - TIMEOUT); break; case NETDEV_DOWN: + rcu_read_lock(); + caifd = caif_get(dev); - if (caifd == NULL) - break; - netdev_info(dev, "down\n"); - if (atomic_read(&caifd->in_use)) - netdev_warn(dev, - "Unregistering an active CAIF device\n"); - cfcnfg_del_phy_layer(cfg, &caifd->layer); - dev_put(dev); - atomic_set(&caifd->state, what); + if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) { + rcu_read_unlock(); + return -EINVAL; + } + + cfcnfg_set_phy_state(cfg, &caifd->layer, false); + caifd_hold(caifd); + rcu_read_unlock(); + + caifd->layer.up->ctrlcmd(caifd->layer.up, + _CAIF_CTRLCMD_PHYIF_DOWN_IND, + caifd->layer.id); + caifd_put(caifd); break; case NETDEV_UNREGISTER: + mutex_lock(&caifdevs->lock); + caifd = caif_get(dev); - if (caifd == NULL) + if (caifd == NULL) { + mutex_unlock(&caifdevs->lock); break; - netdev_info(dev, "unregister\n"); - atomic_set(&caifd->state, what); - caif_device_destroy(dev); + } + list_del_rcu(&caifd->list); + + /* + * NETDEV_UNREGISTER is called repeatedly until all reference + * counts for the net-device are released. If references to + * caifd is taken, simply ignore NETDEV_UNREGISTER and wait for + * the next call to NETDEV_UNREGISTER. + * + * If any packets are in flight down the CAIF Stack, + * cfcnfg_del_phy_layer will return nonzero. + * If no packets are in flight, the CAIF Stack associated + * with the net-device un-registering is freed. + */ + + if (caifd_refcnt_read(caifd) != 0 || + cfcnfg_del_phy_layer(cfg, &caifd->layer) != 0) { + + pr_info("Wait for device inuse\n"); + /* Enrole device if CAIF Stack is still in use */ + list_add_rcu(&caifd->list, &caifdevs->list); + mutex_unlock(&caifdevs->lock); + break; + } + + synchronize_rcu(); + dev_put(caifd->netdev); + free_percpu(caifd->pcpu_refcnt); + kfree(caifd); + + mutex_unlock(&caifdevs->lock); break; } return 0; @@ -304,8 +324,8 @@ static struct notifier_block caif_device_notifier = { }; int caif_connect_client(struct caif_connect_request *conn_req, - struct cflayer *client_layer, int *ifindex, - int *headroom, int *tailroom) + struct cflayer *client_layer, int *ifindex, + int *headroom, int *tailroom) { struct cfctrl_link_param param; int ret; @@ -315,8 +335,8 @@ int caif_connect_client(struct caif_connect_request *conn_req, return ret; /* Hook up the adaptation layer. */ return cfcnfg_add_adaptation_layer(cfg, ¶m, - client_layer, ifindex, - headroom, tailroom); + client_layer, ifindex, + headroom, tailroom); } EXPORT_SYMBOL(caif_connect_client); @@ -331,20 +351,40 @@ static int caif_init_net(struct net *net) { struct caif_net *caifn = net_generic(net, caif_net_id); INIT_LIST_HEAD(&caifn->caifdevs.list); - spin_lock_init(&caifn->caifdevs.lock); + mutex_init(&caifn->caifdevs.lock); return 0; } static void caif_exit_net(struct net *net) { - struct net_device *dev; + struct caif_device_entry *caifd, *tmp; + struct caif_device_entry_list *caifdevs = + caif_device_list(net); + rtnl_lock(); - for_each_netdev(net, dev) { - if (dev->type != ARPHRD_CAIF) - continue; - dev_close(dev); - caif_device_destroy(dev); + mutex_lock(&caifdevs->lock); + + list_for_each_entry_safe(caifd, tmp, &caifdevs->list, list) { + int i = 0; + list_del_rcu(&caifd->list); + cfcnfg_set_phy_state(cfg, &caifd->layer, false); + + while (i < 10 && + (caifd_refcnt_read(caifd) != 0 || + cfcnfg_del_phy_layer(cfg, &caifd->layer) != 0)) { + + pr_info("Wait for device inuse\n"); + msleep(250); + i++; + } + synchronize_rcu(); + dev_put(caifd->netdev); + free_percpu(caifd->pcpu_refcnt); + kfree(caifd); } + + + mutex_unlock(&caifdevs->lock); rtnl_unlock(); } @@ -359,6 +399,7 @@ static struct pernet_operations caif_net_ops = { static int __init caif_device_init(void) { int result; + cfg = cfcnfg_create(); if (!cfg) { pr_warn("can't create cfcnfg\n"); -- cgit v1.2.3-58-ga151 From f36214408470ecf6a052e76b72d05b2328b60fcf Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Fri, 13 May 2011 02:44:01 +0000 Subject: caif: Use RCU and lists in cfcnfg.c for managing caif link layers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RCU lists are used for handling the link layers instead of array. When generating CAIF phy-id, ifindex is used as base. Legal range is 1-6. Introduced set_phy_state() for managing CAIF Link layer state. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- net/caif/cfcnfg.c | 373 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 213 insertions(+), 160 deletions(-) diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index 25c0b198e285..7892cc084e27 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -18,11 +19,7 @@ #include #include #include - -#include -#include - -#define MAX_PHY_LAYERS 7 +#include #define container_obj(layr) container_of(layr, struct cfcnfg, layer) @@ -30,6 +27,9 @@ * to manage physical interfaces */ struct cfcnfg_phyinfo { + struct list_head node; + bool up; + /* Pointer to the layer below the MUX (framing layer) */ struct cflayer *frm_layer; /* Pointer to the lowest actual physical layer */ @@ -39,9 +39,6 @@ struct cfcnfg_phyinfo { /* Preference of the physical in interface */ enum cfcnfg_phy_preference pref; - /* Reference count, number of channels using the device */ - int phy_ref_count; - /* Information about the physical device */ struct dev_info dev_info; @@ -59,8 +56,8 @@ struct cfcnfg { struct cflayer layer; struct cflayer *ctrl; struct cflayer *mux; - u8 last_phyid; - struct cfcnfg_phyinfo phy_layers[MAX_PHY_LAYERS]; + struct list_head phys; + struct mutex lock; }; static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, @@ -76,6 +73,9 @@ struct cfcnfg *cfcnfg_create(void) { struct cfcnfg *this; struct cfctrl_rsp *resp; + + might_sleep(); + /* Initiate this layer */ this = kzalloc(sizeof(struct cfcnfg), GFP_ATOMIC); if (!this) { @@ -99,15 +99,19 @@ struct cfcnfg *cfcnfg_create(void) resp->radioset_rsp = cfctrl_resp_func; resp->linksetup_rsp = cfcnfg_linkup_rsp; resp->reject_rsp = cfcnfg_reject_rsp; - - this->last_phyid = 1; + INIT_LIST_HEAD(&this->phys); cfmuxl_set_uplayer(this->mux, this->ctrl, 0); layer_set_dn(this->ctrl, this->mux); layer_set_up(this->ctrl, this); + mutex_init(&this->lock); + return this; out_of_mem: pr_warn("Out of memory\n"); + + synchronize_rcu(); + kfree(this->mux); kfree(this->ctrl); kfree(this); @@ -117,7 +121,10 @@ EXPORT_SYMBOL(cfcnfg_create); void cfcnfg_remove(struct cfcnfg *cfg) { + might_sleep(); if (cfg) { + synchronize_rcu(); + kfree(cfg->mux); kfree(cfg->ctrl); kfree(cfg); @@ -128,6 +135,17 @@ static void cfctrl_resp_func(void) { } +static struct cfcnfg_phyinfo *cfcnfg_get_phyinfo_rcu(struct cfcnfg *cnfg, + u8 phyid) +{ + struct cfcnfg_phyinfo *phy; + + list_for_each_entry_rcu(phy, &cnfg->phys, node) + if (phy->id == phyid) + return phy; + return NULL; +} + static void cfctrl_enum_resp(void) { } @@ -135,106 +153,65 @@ static void cfctrl_enum_resp(void) struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, enum cfcnfg_phy_preference phy_pref) { - u16 i; - /* Try to match with specified preference */ - for (i = 1; i < MAX_PHY_LAYERS; i++) { - if (cnfg->phy_layers[i].id == i && - cnfg->phy_layers[i].pref == phy_pref && - cnfg->phy_layers[i].frm_layer != NULL) { - caif_assert(cnfg->phy_layers != NULL); - caif_assert(cnfg->phy_layers[i].id == i); - return &cnfg->phy_layers[i].dev_info; - } - } - /* Otherwise just return something */ - for (i = 1; i < MAX_PHY_LAYERS; i++) { - if (cnfg->phy_layers[i].id == i) { - caif_assert(cnfg->phy_layers != NULL); - caif_assert(cnfg->phy_layers[i].id == i); - return &cnfg->phy_layers[i].dev_info; - } + struct cfcnfg_phyinfo *phy; + + list_for_each_entry_rcu(phy, &cnfg->phys, node) { + if (phy->up && phy->pref == phy_pref && + phy->frm_layer != NULL) + + return &phy->dev_info; } - return NULL; -} + /* Otherwise just return something */ + list_for_each_entry_rcu(phy, &cnfg->phys, node) + if (phy->up) + return &phy->dev_info; -static struct cfcnfg_phyinfo *cfcnfg_get_phyinfo(struct cfcnfg *cnfg, - u8 phyid) -{ - int i; - /* Try to match with specified preference */ - for (i = 0; i < MAX_PHY_LAYERS; i++) - if (cnfg->phy_layers[i].frm_layer != NULL && - cnfg->phy_layers[i].id == phyid) - return &cnfg->phy_layers[i]; return NULL; } - int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) { - int i; - for (i = 0; i < MAX_PHY_LAYERS; i++) - if (cnfg->phy_layers[i].frm_layer != NULL && - cnfg->phy_layers[i].ifindex == ifi) - return i; + struct cfcnfg_phyinfo *phy; + + list_for_each_entry_rcu(phy, &cnfg->phys, node) + if (phy->ifindex == ifi && phy->up) + return phy->id; return -ENODEV; } -int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer) +int cfcnfg_disconn_adapt_layer(struct cfcnfg *cfg, struct cflayer *adap_layer) { u8 channel_id = 0; int ret = 0; struct cflayer *servl = NULL; - struct cfcnfg_phyinfo *phyinfo = NULL; - u8 phyid = 0; caif_assert(adap_layer != NULL); + channel_id = adap_layer->id; if (adap_layer->dn == NULL || channel_id == 0) { pr_err("adap_layer->dn == NULL or adap_layer->id is 0\n"); ret = -ENOTCONN; goto end; } - servl = cfmuxl_remove_uplayer(cnfg->mux, channel_id); + + servl = cfmuxl_remove_uplayer(cfg->mux, channel_id); if (servl == NULL) { - pr_err("PROTOCOL ERROR - Error removing service_layer Channel_Id(%d)", - channel_id); + pr_err("PROTOCOL ERROR - " + "Error removing service_layer Channel_Id(%d)", + channel_id); ret = -EINVAL; goto end; } - layer_set_up(servl, NULL); - ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer); - if (ret) - goto end; - caif_assert(channel_id == servl->id); - if (adap_layer->dn != NULL) { - phyid = cfsrvl_getphyid(adap_layer->dn); - - phyinfo = cfcnfg_get_phyinfo(cnfg, phyid); - if (phyinfo == NULL) { - pr_warn("No interface to send disconnect to\n"); - ret = -ENODEV; - goto end; - } - if (phyinfo->id != phyid || - phyinfo->phy_layer->id != phyid || - phyinfo->frm_layer->id != phyid) { - pr_err("Inconsistency in phy registration\n"); - ret = -EINVAL; - goto end; - } - } - if (phyinfo != NULL && --phyinfo->phy_ref_count == 0 && - phyinfo->phy_layer != NULL && - phyinfo->phy_layer->modemcmd != NULL) { - phyinfo->phy_layer->modemcmd(phyinfo->phy_layer, - _CAIF_MODEMCMD_PHYIF_USELESS); - } + + ret = cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer); + end: - cfsrvl_put(servl); - cfctrl_cancel_req(cnfg->ctrl, adap_layer); + cfctrl_cancel_req(cfg->ctrl, adap_layer); + + /* Do RCU sync before initiating cleanup */ + synchronize_rcu(); if (adap_layer->ctrlcmd != NULL) adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0); return ret; @@ -269,39 +246,56 @@ int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, int *proto_tail) { struct cflayer *frml; + struct cfcnfg_phyinfo *phy; + int err; + + rcu_read_lock(); + phy = cfcnfg_get_phyinfo_rcu(cnfg, param->phyid); + if (!phy) { + err = -ENODEV; + goto unlock; + } + err = -EINVAL; + if (adap_layer == NULL) { pr_err("adap_layer is zero\n"); - return -EINVAL; + goto unlock; } if (adap_layer->receive == NULL) { pr_err("adap_layer->receive is NULL\n"); - return -EINVAL; + goto unlock; } if (adap_layer->ctrlcmd == NULL) { pr_err("adap_layer->ctrlcmd == NULL\n"); - return -EINVAL; + goto unlock; } - frml = cnfg->phy_layers[param->phyid].frm_layer; + + err = -ENODEV; + frml = phy->frm_layer; if (frml == NULL) { pr_err("Specified PHY type does not exist!\n"); - return -ENODEV; + goto unlock; } - caif_assert(param->phyid == cnfg->phy_layers[param->phyid].id); - caif_assert(cnfg->phy_layers[param->phyid].frm_layer->id == + caif_assert(param->phyid == phy->id); + caif_assert(phy->frm_layer->id == param->phyid); - caif_assert(cnfg->phy_layers[param->phyid].phy_layer->id == + caif_assert(phy->phy_layer->id == param->phyid); - *ifindex = cnfg->phy_layers[param->phyid].ifindex; + *ifindex = phy->ifindex; + *proto_tail = 2; *proto_head = - protohead[param->linktype]+ - (cnfg->phy_layers[param->phyid].use_stx ? 1 : 0); + protohead[param->linktype] + (phy->use_stx ? 1 : 0); - *proto_tail = 2; + rcu_read_unlock(); /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ cfctrl_enum_req(cnfg->ctrl, param->phyid); return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer); + +unlock: + rcu_read_unlock(); + return err; } EXPORT_SYMBOL(cfcnfg_add_adaptation_layer); @@ -315,32 +309,37 @@ static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, - u8 phyid, struct cflayer *adapt_layer) + u8 phyid, struct cflayer *adapt_layer) { struct cfcnfg *cnfg = container_obj(layer); struct cflayer *servicel = NULL; struct cfcnfg_phyinfo *phyinfo; struct net_device *netdev; + rcu_read_lock(); + if (adapt_layer == NULL) { - pr_debug("link setup response but no client exist, send linkdown back\n"); + pr_debug("link setup response but no client exist," + "send linkdown back\n"); cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL); - return; + goto unlock; } caif_assert(cnfg != NULL); caif_assert(phyid != 0); - phyinfo = &cnfg->phy_layers[phyid]; + + phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid); + if (phyinfo == NULL) { + pr_err("ERROR: Link Layer Device dissapeared" + "while connecting\n"); + goto unlock; + } + + caif_assert(phyinfo != NULL); caif_assert(phyinfo->id == phyid); caif_assert(phyinfo->phy_layer != NULL); caif_assert(phyinfo->phy_layer->id == phyid); - phyinfo->phy_ref_count++; - if (phyinfo->phy_ref_count == 1 && - phyinfo->phy_layer->modemcmd != NULL) { - phyinfo->phy_layer->modemcmd(phyinfo->phy_layer, - _CAIF_MODEMCMD_PHYIF_USEFULL); - } adapt_layer->id = channel_id; switch (serv) { @@ -348,7 +347,8 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, servicel = cfvei_create(channel_id, &phyinfo->dev_info); break; case CFCTRL_SRV_DATAGRAM: - servicel = cfdgml_create(channel_id, &phyinfo->dev_info); + servicel = cfdgml_create(channel_id, + &phyinfo->dev_info); break; case CFCTRL_SRV_RFM: netdev = phyinfo->dev_info.dev; @@ -365,94 +365,93 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, servicel = cfdbgl_create(channel_id, &phyinfo->dev_info); break; default: - pr_err("Protocol error. Link setup response - unknown channel type\n"); - return; + pr_err("Protocol error. Link setup response " + "- unknown channel type\n"); + goto unlock; } if (!servicel) { pr_warn("Out of memory\n"); - return; + goto unlock; } layer_set_dn(servicel, cnfg->mux); cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id); layer_set_up(servicel, adapt_layer); layer_set_dn(adapt_layer, servicel); - cfsrvl_get(servicel); + + rcu_read_unlock(); + servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0); + return; +unlock: + rcu_read_unlock(); } void cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, struct net_device *dev, struct cflayer *phy_layer, - u16 *phyid, enum cfcnfg_phy_preference pref, + u16 *phy_id, enum cfcnfg_phy_preference pref, bool fcs, bool stx) { struct cflayer *frml; struct cflayer *phy_driver = NULL; + struct cfcnfg_phyinfo *phyinfo; int i; + u8 phyid; + mutex_lock(&cnfg->lock); - if (cnfg->phy_layers[cnfg->last_phyid].frm_layer == NULL) { - *phyid = cnfg->last_phyid; - - /* range: * 1..(MAX_PHY_LAYERS-1) */ - cnfg->last_phyid = - (cnfg->last_phyid % (MAX_PHY_LAYERS - 1)) + 1; - } else { - *phyid = 0; - for (i = 1; i < MAX_PHY_LAYERS; i++) { - if (cnfg->phy_layers[i].frm_layer == NULL) { - *phyid = i; - break; - } - } - } - if (*phyid == 0) { - pr_err("No Available PHY ID\n"); - return; + /* CAIF protocol allow maximum 6 link-layers */ + for (i = 0; i < 7; i++) { + phyid = (dev->ifindex + i) & 0x7; + if (phyid == 0) + continue; + if (cfcnfg_get_phyinfo_rcu(cnfg, phyid) == NULL) + goto got_phyid; } + pr_warn("Too many CAIF Link Layers (max 6)\n"); + goto out; + +got_phyid: + phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC); switch (phy_type) { case CFPHYTYPE_FRAG: phy_driver = - cfserl_create(CFPHYTYPE_FRAG, *phyid, stx); + cfserl_create(CFPHYTYPE_FRAG, phyid, stx); if (!phy_driver) { pr_warn("Out of memory\n"); - return; + goto out; } - break; case CFPHYTYPE_CAIF: phy_driver = NULL; break; default: - pr_err("%d\n", phy_type); - return; - break; + goto out; } - - phy_layer->id = *phyid; - cnfg->phy_layers[*phyid].pref = pref; - cnfg->phy_layers[*phyid].id = *phyid; - cnfg->phy_layers[*phyid].dev_info.id = *phyid; - cnfg->phy_layers[*phyid].dev_info.dev = dev; - cnfg->phy_layers[*phyid].phy_layer = phy_layer; - cnfg->phy_layers[*phyid].phy_ref_count = 0; - cnfg->phy_layers[*phyid].ifindex = dev->ifindex; - cnfg->phy_layers[*phyid].use_stx = stx; - cnfg->phy_layers[*phyid].use_fcs = fcs; + phy_layer->id = phyid; + phyinfo->pref = pref; + phyinfo->id = phyid; + phyinfo->dev_info.id = phyid; + phyinfo->dev_info.dev = dev; + phyinfo->phy_layer = phy_layer; + phyinfo->ifindex = dev->ifindex; + phyinfo->use_stx = stx; + phyinfo->use_fcs = fcs; phy_layer->type = phy_type; - frml = cffrml_create(*phyid, fcs); + frml = cffrml_create(phyid, fcs); + if (!frml) { pr_warn("Out of memory\n"); - return; + kfree(phyinfo); + goto out; } - cnfg->phy_layers[*phyid].frm_layer = frml; - cfmuxl_set_dnlayer(cnfg->mux, frml, *phyid); + phyinfo->frm_layer = frml; layer_set_up(frml, cnfg->mux); if (phy_driver != NULL) { - phy_driver->id = *phyid; + phy_driver->id = phyid; layer_set_dn(frml, phy_driver); layer_set_up(phy_driver, frml); layer_set_dn(phy_driver, phy_layer); @@ -461,33 +460,87 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, layer_set_dn(frml, phy_layer); layer_set_up(phy_layer, frml); } + + list_add_rcu(&phyinfo->node, &cnfg->phys); +out: + mutex_unlock(&cnfg->lock); } EXPORT_SYMBOL(cfcnfg_add_phy_layer); +int cfcnfg_set_phy_state(struct cfcnfg *cnfg, struct cflayer *phy_layer, + bool up) +{ + struct cfcnfg_phyinfo *phyinfo; + + rcu_read_lock(); + phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phy_layer->id); + if (phyinfo == NULL) { + rcu_read_unlock(); + return -ENODEV; + } + + if (phyinfo->up == up) { + rcu_read_unlock(); + return 0; + } + phyinfo->up = up; + + if (up) { + cffrml_hold(phyinfo->frm_layer); + cfmuxl_set_dnlayer(cnfg->mux, phyinfo->frm_layer, + phy_layer->id); + } else { + cfmuxl_remove_dnlayer(cnfg->mux, phy_layer->id); + cffrml_put(phyinfo->frm_layer); + } + + rcu_read_unlock(); + return 0; +} +EXPORT_SYMBOL(cfcnfg_set_phy_state); + int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) { struct cflayer *frml, *frml_dn; u16 phyid; + struct cfcnfg_phyinfo *phyinfo; + + might_sleep(); + + mutex_lock(&cnfg->lock); + phyid = phy_layer->id; - caif_assert(phyid == cnfg->phy_layers[phyid].id); - caif_assert(phy_layer == cnfg->phy_layers[phyid].phy_layer); + phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid); + + if (phyinfo == NULL) + return 0; + caif_assert(phyid == phyinfo->id); + caif_assert(phy_layer == phyinfo->phy_layer); caif_assert(phy_layer->id == phyid); - caif_assert(cnfg->phy_layers[phyid].frm_layer->id == phyid); + caif_assert(phyinfo->frm_layer->id == phyid); + + list_del_rcu(&phyinfo->node); + synchronize_rcu(); - memset(&cnfg->phy_layers[phy_layer->id], 0, - sizeof(struct cfcnfg_phyinfo)); - frml = cfmuxl_remove_dnlayer(cnfg->mux, phy_layer->id); + frml = phyinfo->frm_layer; frml_dn = frml->dn; cffrml_set_uplayer(frml, NULL); cffrml_set_dnlayer(frml, NULL); - kfree(frml); - if (phy_layer != frml_dn) { layer_set_up(frml_dn, NULL); layer_set_dn(frml_dn, NULL); - kfree(frml_dn); } layer_set_up(phy_layer, NULL); + + + + if (phyinfo->phy_layer != frml_dn) + kfree(frml_dn); + + kfree(frml); + kfree(phyinfo); + mutex_unlock(&cnfg->lock); + return 0; } EXPORT_SYMBOL(cfcnfg_del_phy_layer); -- cgit v1.2.3-58-ga151 From cb3cb423a0f3c627639535e5d87977ae662d779f Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Fri, 13 May 2011 02:44:02 +0000 Subject: caif: Add ref-count to framing layer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce Per-cpu reference for lower part of CAIF Stack. Before freeing payload is disabled, synchronize_rcu() is called, and then ref-count verified to be zero. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- include/net/caif/cffrml.h | 5 ++++- net/caif/cfcnfg.c | 9 ++++++++- net/caif/cffrml.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/include/net/caif/cffrml.h b/include/net/caif/cffrml.h index 4f126d777212..afac1a48cce7 100644 --- a/include/net/caif/cffrml.h +++ b/include/net/caif/cffrml.h @@ -7,12 +7,15 @@ #ifndef CFFRML_H_ #define CFFRML_H_ #include +#include struct cffrml; -struct cflayer *cffrml_create(u16 phyid, bool DoFCS); +struct cflayer *cffrml_create(u16 phyid, bool use_fcs); +void cffrml_free(struct cflayer *layr); void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up); void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn); void cffrml_put(struct cflayer *layr); void cffrml_hold(struct cflayer *layr); +int cffrml_refcnt_read(struct cflayer *layr); #endif /* CFFRML_H_ */ diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index 7892cc084e27..3f4f31fca2c1 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c @@ -519,6 +519,13 @@ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) caif_assert(phy_layer->id == phyid); caif_assert(phyinfo->frm_layer->id == phyid); + /* Fail if reference count is not zero */ + if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) { + pr_info("Wait for device inuse\n"); + mutex_unlock(&cnfg->lock); + return -EAGAIN; + } + list_del_rcu(&phyinfo->node); synchronize_rcu(); @@ -537,7 +544,7 @@ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) if (phyinfo->phy_layer != frml_dn) kfree(frml_dn); - kfree(frml); + cffrml_free(frml); kfree(phyinfo); mutex_unlock(&cnfg->lock); diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c index f4b88924f83a..4f4f756c49ac 100644 --- a/net/caif/cffrml.c +++ b/net/caif/cffrml.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ struct cffrml { struct cflayer layer; bool dofcs; /* !< FCS active */ + int __percpu *pcpu_refcnt; }; static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt); @@ -31,12 +33,19 @@ static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, static u32 cffrml_rcv_error; static u32 cffrml_rcv_checsum_error; struct cflayer *cffrml_create(u16 phyid, bool use_fcs) + { struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC); if (!this) { pr_warn("Out of memory\n"); return NULL; } + this->pcpu_refcnt = alloc_percpu(int); + if (this->pcpu_refcnt == NULL) { + kfree(this); + return NULL; + } + caif_assert(offsetof(struct cffrml, layer) == 0); memset(this, 0, sizeof(struct cflayer)); @@ -49,6 +58,13 @@ struct cflayer *cffrml_create(u16 phyid, bool use_fcs) return (struct cflayer *) this; } +void cffrml_free(struct cflayer *layer) +{ + struct cffrml *this = container_obj(layer); + free_percpu(this->pcpu_refcnt); + kfree(layer); +} + void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up) { this->up = up; @@ -148,8 +164,23 @@ static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, void cffrml_put(struct cflayer *layr) { + struct cffrml *this = container_obj(layr); + if (layr != NULL && this->pcpu_refcnt != NULL) + irqsafe_cpu_dec(*this->pcpu_refcnt); } void cffrml_hold(struct cflayer *layr) { + struct cffrml *this = container_obj(layr); + if (layr != NULL && this->pcpu_refcnt != NULL) + irqsafe_cpu_inc(*this->pcpu_refcnt); +} + +int cffrml_refcnt_read(struct cflayer *layr) +{ + int i, refcnt = 0; + struct cffrml *this = container_obj(layr); + for_each_possible_cpu(i) + refcnt += *per_cpu_ptr(this->pcpu_refcnt, i); + return refcnt; } -- cgit v1.2.3-58-ga151 From 43e3692101086add8719c3b8b50b05c9ac5b14e1 Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Fri, 13 May 2011 02:44:03 +0000 Subject: caif: Move refcount from service layer to sock and dev. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of having reference counts in caif service layers, we hook into existing refcount handling in socket layer and netdevice. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- include/net/caif/cfsrvl.h | 29 ++++++++++++++++------------- net/caif/cfrfml.c | 4 ++-- net/caif/cfsrvl.c | 35 +++++++++++++++++++++++++++++------ 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/include/net/caif/cfsrvl.h b/include/net/caif/cfsrvl.h index 6c8279c1ae9a..0f5905241843 100644 --- a/include/net/caif/cfsrvl.h +++ b/include/net/caif/cfsrvl.h @@ -10,6 +10,7 @@ #include #include #include +#include struct cfsrvl { struct cflayer layer; @@ -17,9 +18,11 @@ struct cfsrvl { bool phy_flow_on; bool modem_flow_on; bool supports_flowctrl; - void (*release)(struct kref *); + void (*release)(struct cflayer *layer); struct dev_info dev_info; - struct kref ref; + void (*hold)(struct cflayer *lyr); + void (*put)(struct cflayer *lyr); + struct rcu_head rcu; }; struct cflayer *cfvei_create(u8 linkid, struct dev_info *dev_info); @@ -29,6 +32,10 @@ struct cflayer *cfvidl_create(u8 linkid, struct dev_info *dev_info); struct cflayer *cfrfml_create(u8 linkid, struct dev_info *dev_info, int mtu_size); struct cflayer *cfdbgl_create(u8 linkid, struct dev_info *dev_info); + +void cfsrvl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, + int phyid); + bool cfsrvl_phyid_match(struct cflayer *layer, int phyid); void cfsrvl_init(struct cfsrvl *service, @@ -40,23 +47,19 @@ u8 cfsrvl_getphyid(struct cflayer *layer); static inline void cfsrvl_get(struct cflayer *layr) { - struct cfsrvl *s; - if (layr == NULL) + struct cfsrvl *s = container_of(layr, struct cfsrvl, layer); + if (layr == NULL || layr->up == NULL || s->hold == NULL) return; - s = container_of(layr, struct cfsrvl, layer); - kref_get(&s->ref); + + s->hold(layr->up); } static inline void cfsrvl_put(struct cflayer *layr) { - struct cfsrvl *s; - if (layr == NULL) + struct cfsrvl *s = container_of(layr, struct cfsrvl, layer); + if (layr == NULL || layr->up == NULL || s->hold == NULL) return; - s = container_of(layr, struct cfsrvl, layer); - WARN_ON(!s->release); - if (s->release) - kref_put(&s->ref, s->release); + s->put(layr->up); } - #endif /* CFSRVL_H_ */ diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c index e2fb5fa75795..0deabb440051 100644 --- a/net/caif/cfrfml.c +++ b/net/caif/cfrfml.c @@ -31,9 +31,9 @@ struct cfrfml { spinlock_t sync; }; -static void cfrfml_release(struct kref *kref) +static void cfrfml_release(struct cflayer *layer) { - struct cfsrvl *srvl = container_of(kref, struct cfsrvl, ref); + struct cfsrvl *srvl = container_of(layer, struct cfsrvl, layer); struct cfrfml *rfml = container_obj(&srvl->layer); if (rfml->incomplete_frm) diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index 24ba392f203b..535a1e72b366 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -27,8 +28,8 @@ static void cfservl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, { struct cfsrvl *service = container_obj(layr); - caif_assert(layr->up != NULL); - caif_assert(layr->up->ctrlcmd != NULL); + if (layr->up == NULL || layr->up->ctrlcmd == NULL) + return; switch (ctrl) { case CAIF_CTRLCMD_INIT_RSP: @@ -151,9 +152,9 @@ static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) return -EINVAL; } -static void cfsrvl_release(struct kref *kref) +static void cfsrvl_release(struct cflayer *layer) { - struct cfsrvl *service = container_of(kref, struct cfsrvl, ref); + struct cfsrvl *service = container_of(layer, struct cfsrvl, layer); kfree(service); } @@ -173,10 +174,8 @@ void cfsrvl_init(struct cfsrvl *service, service->dev_info = *dev_info; service->supports_flowctrl = supports_flowctrl; service->release = cfsrvl_release; - kref_init(&service->ref); } - bool cfsrvl_ready(struct cfsrvl *service, int *err) { if (service->open && service->modem_flow_on && service->phy_flow_on) @@ -189,6 +188,7 @@ bool cfsrvl_ready(struct cfsrvl *service, int *err) *err = -EAGAIN; return false; } + u8 cfsrvl_getphyid(struct cflayer *layer) { struct cfsrvl *servl = container_obj(layer); @@ -200,3 +200,26 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid) struct cfsrvl *servl = container_obj(layer); return servl->dev_info.id == phyid; } + +void caif_free_client(struct cflayer *adap_layer) +{ + struct cfsrvl *servl; + if (adap_layer == NULL || adap_layer->dn == NULL) + return; + servl = container_obj(adap_layer->dn); + servl->release(&servl->layer); +} +EXPORT_SYMBOL(caif_free_client); + +void caif_client_register_refcnt(struct cflayer *adapt_layer, + void (*hold)(struct cflayer *lyr), + void (*put)(struct cflayer *lyr)) +{ + struct cfsrvl *service; + service = container_of(adapt_layer->dn, struct cfsrvl, layer); + + WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL); + service->hold = hold; + service->put = put; +} +EXPORT_SYMBOL(caif_client_register_refcnt); -- cgit v1.2.3-58-ga151 From b3ccfbe4098a5542177d0f34e8979f32e7d606e1 Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Fri, 13 May 2011 02:44:04 +0000 Subject: caif: Protected in-flight packets using dev or sock refcont. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CAIF Socket Layer and ip-interface registers reference counters in CAIF service layer. The functions sock_hold, sock_put and dev_hold, dev_put are used by CAIF Stack to protect from freeing memory while packets are in-flight. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- include/net/caif/caif_dev.h | 29 +++++++++++++++++++++++++++++ net/caif/caif_socket.c | 19 +++++++++++++++++-- net/caif/chnl_net.c | 28 ++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h index 7e3f7a6d2ba3..6638435525fc 100644 --- a/include/net/caif/caif_dev.h +++ b/include/net/caif/caif_dev.h @@ -73,6 +73,23 @@ int caif_connect_client(struct caif_connect_request *conn_req, */ int caif_disconnect_client(struct cflayer *client_layer); +/** + * caif_client_register_refcnt - register ref-count functions provided by client. + * + * @adapt_layer: Client layer using CAIF Stack. + * @hold: Function provided by client layer increasing ref-count + * @put: Function provided by client layer decreasing ref-count + * + * Client of the CAIF Stack must register functions for reference counting. + * These functions are called by the CAIF Stack for every upstream packet, + * and must therefore be implemented efficiently. + * + * Client should call caif_free_client when reference count degrease to zero. + */ + +void caif_client_register_refcnt(struct cflayer *adapt_layer, + void (*hold)(struct cflayer *lyr), + void (*put)(struct cflayer *lyr)); /** * caif_connect_req_to_link_param - Translate configuration parameters * from socket format to internal format. @@ -83,8 +100,20 @@ int caif_disconnect_client(struct cflayer *client_layer); * setting up channels. * */ + int caif_connect_req_to_link_param(struct cfcnfg *cnfg, struct caif_connect_request *con_req, struct cfctrl_link_param *setup_param); +/** + * caif_free_client - Free memory used to manage the client in the CAIF Stack. + * + * @client_layer: Client layer to be removed. + * + * This function must be called from client layer in order to free memory. + * Caller must guarantee that no packets are in flight upstream when calling + * this function. + */ +void caif_free_client(struct cflayer *adap_layer); + #endif /* CAIF_DEV_H_ */ diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 20212424e2e8..01f612df7df1 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -209,6 +209,18 @@ static int caif_sktrecv_cb(struct cflayer *layr, struct cfpkt *pkt) return 0; } +static void cfsk_hold(struct cflayer *layr) +{ + struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); + sock_hold(&cf_sk->sk); +} + +static void cfsk_put(struct cflayer *layr) +{ + struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); + sock_put(&cf_sk->sk); +} + /* Packet Control Callback function called from CAIF */ static void caif_ctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, @@ -232,6 +244,8 @@ static void caif_ctrl_cb(struct cflayer *layr, case CAIF_CTRLCMD_INIT_RSP: /* We're now connected */ + caif_client_register_refcnt(&cf_sk->layer, + cfsk_hold, cfsk_put); dbfs_atomic_inc(&cnt.num_connect_resp); cf_sk->sk.sk_state = CAIF_CONNECTED; set_tx_flow_on(cf_sk); @@ -242,7 +256,6 @@ static void caif_ctrl_cb(struct cflayer *layr, /* We're now disconnected */ cf_sk->sk.sk_state = CAIF_DISCONNECTED; cf_sk->sk.sk_state_change(&cf_sk->sk); - cfcnfg_release_adap_layer(&cf_sk->layer); break; case CAIF_CTRLCMD_INIT_FAIL_RSP: @@ -837,8 +850,10 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, dbfs_atomic_inc(&cnt.num_connect_req); cf_sk->layer.receive = caif_sktrecv_cb; + err = caif_connect_client(&cf_sk->conn_req, &cf_sk->layer, &ifindex, &headroom, &tailroom); + if (err < 0) { cf_sk->sk.sk_socket->state = SS_UNCONNECTED; cf_sk->sk.sk_state = CAIF_DISCONNECTED; @@ -940,7 +955,6 @@ static int caif_release(struct socket *sock) wake_up_interruptible_poll(sk_sleep(sk), POLLERR|POLLHUP); sock_orphan(sk); - cf_sk->layer.dn = NULL; sk_stream_kill_queues(&cf_sk->sk); release_sock(sk); sock_put(sk); @@ -1036,6 +1050,7 @@ static void caif_sock_destructor(struct sock *sk) } sk_stream_kill_queues(&cf_sk->sk); dbfs_atomic_dec(&cnt.caif_nr_socks); + caif_free_client(&cf_sk->layer); } static int caif_create(struct net *net, struct socket *sock, int protocol, diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 6008d6dc18a0..9ef8f1660ee1 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -153,6 +153,18 @@ static void close_work(struct work_struct *work) } static DECLARE_WORK(close_worker, close_work); +static void chnl_hold(struct cflayer *lyr) +{ + struct chnl_net *priv = container_of(lyr, struct chnl_net, chnl); + dev_hold(priv->netdev); +} + +static void chnl_put(struct cflayer *lyr) +{ + struct chnl_net *priv = container_of(lyr, struct chnl_net, chnl); + dev_put(priv->netdev); +} + static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, int phyid) { @@ -190,6 +202,7 @@ static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, netif_wake_queue(priv->netdev); break; case CAIF_CTRLCMD_INIT_RSP: + caif_client_register_refcnt(&priv->chnl, chnl_hold, chnl_put); priv->state = CAIF_CONNECTED; priv->flowenabled = true; netif_wake_queue(priv->netdev); @@ -373,11 +386,18 @@ static const struct net_device_ops netdev_ops = { .ndo_start_xmit = chnl_net_start_xmit, }; +static void chnl_net_destructor(struct net_device *dev) +{ + struct chnl_net *priv = netdev_priv(dev); + caif_free_client(&priv->chnl); + free_netdev(dev); +} + static void ipcaif_net_setup(struct net_device *dev) { struct chnl_net *priv; dev->netdev_ops = &netdev_ops; - dev->destructor = free_netdev; + dev->destructor = chnl_net_destructor; dev->flags |= IFF_NOARP; dev->flags |= IFF_POINTOPOINT; dev->mtu = GPRS_PDP_MTU; @@ -391,7 +411,7 @@ static void ipcaif_net_setup(struct net_device *dev) priv->conn_req.link_selector = CAIF_LINK_HIGH_BANDW; priv->conn_req.priority = CAIF_PRIO_LOW; /* Insert illegal value */ - priv->conn_req.sockaddr.u.dgm.connection_id = -1; + priv->conn_req.sockaddr.u.dgm.connection_id = 0; priv->flowenabled = false; init_waitqueue_head(&priv->netmgmt_wq); @@ -453,6 +473,10 @@ static int ipcaif_newlink(struct net *src_net, struct net_device *dev, pr_warn("device rtml registration failed\n"); else list_add(&caifdev->list_field, &chnl_net_list); + + /* Take ifindex as connection-id if null */ + if (caifdev->conn_req.sockaddr.u.dgm.connection_id == 0) + caifdev->conn_req.sockaddr.u.dgm.connection_id = dev->ifindex; return ret; } -- cgit v1.2.3-58-ga151 From bee925db9a77a5736596dcf6f91d0879f5ee915b Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Fri, 13 May 2011 02:44:05 +0000 Subject: caif: prepare support for namespaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use struct net to reference CAIF configuration object instead of static variables. Refactor functions caif_connect_client, caif_disconnect_client and squach files cfcnfg.c and caif_config_utils. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- include/net/caif/caif_dev.h | 24 ++------ include/net/caif/cfcnfg.h | 71 +++------------------ net/caif/Makefile | 2 +- net/caif/caif_config_util.c | 99 ------------------------------ net/caif/caif_dev.c | 77 +++++++++++------------ net/caif/caif_socket.c | 6 +- net/caif/cfcnfg.c | 146 +++++++++++++++++++++++++++++++++++--------- net/caif/chnl_net.c | 12 ++-- 8 files changed, 176 insertions(+), 261 deletions(-) delete mode 100644 net/caif/caif_config_util.c diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h index 6638435525fc..c011281d92c0 100644 --- a/include/net/caif/caif_dev.h +++ b/include/net/caif/caif_dev.h @@ -11,6 +11,7 @@ #include #include #include +#include /** * struct caif_param - CAIF parameters. @@ -62,16 +63,18 @@ struct caif_connect_request { * E.g. CAIF Socket will call this function for each socket it connects * and have one client_layer instance for each socket. */ -int caif_connect_client(struct caif_connect_request *conn_req, +int caif_connect_client(struct net *net, + struct caif_connect_request *conn_req, struct cflayer *client_layer, int *ifindex, int *headroom, int *tailroom); /** * caif_disconnect_client - Disconnects a client from the CAIF stack. * - * @client_layer: Client layer to be removed. + * @client_layer: Client layer to be disconnected. */ -int caif_disconnect_client(struct cflayer *client_layer); +int caif_disconnect_client(struct net *net, struct cflayer *client_layer); + /** * caif_client_register_refcnt - register ref-count functions provided by client. @@ -90,21 +93,6 @@ int caif_disconnect_client(struct cflayer *client_layer); void caif_client_register_refcnt(struct cflayer *adapt_layer, void (*hold)(struct cflayer *lyr), void (*put)(struct cflayer *lyr)); -/** - * caif_connect_req_to_link_param - Translate configuration parameters - * from socket format to internal format. - * @cnfg: Pointer to configuration handler - * @con_req: Configuration parameters supplied in function - * caif_connect_client - * @channel_setup_param: Parameters supplied to the CAIF Core stack for - * setting up channels. - * - */ - -int caif_connect_req_to_link_param(struct cfcnfg *cnfg, - struct caif_connect_request *con_req, - struct cfctrl_link_param *setup_param); - /** * caif_free_client - Free memory used to manage the client in the CAIF Stack. * diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h index e0a1eb5d7eaf..3e93a4a4b677 100644 --- a/include/net/caif/cfcnfg.h +++ b/include/net/caif/cfcnfg.h @@ -45,6 +45,12 @@ enum cfcnfg_phy_preference { CFPHYPREF_LOOP }; +/** + * cfcnfg_create() - Get the CAIF configuration object given network. + * @net: Network for the CAIF configuration object. + */ +struct cfcnfg *get_cfcnfg(struct net *net); + /** * cfcnfg_create() - Create the CAIF configuration object. */ @@ -65,17 +71,15 @@ void cfcnfg_remove(struct cfcnfg *cfg); * @dev: Pointer to link layer device * @phy_layer: Specify the physical layer. The transmit function * MUST be set in the structure. - * @phyid: The assigned physical ID for this layer, used in - * cfcnfg_add_adapt_layer to specify PHY for the link. * @pref: The phy (link layer) preference. * @fcs: Specify if checksum is used in CAIF Framing Layer. - * @stx: Specify if Start Of Frame extension is used. + * @stx: Specify if Start Of Frame eXtention is used. */ void cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, struct net_device *dev, struct cflayer *phy_layer, - u16 *phyid, enum cfcnfg_phy_preference pref, + enum cfcnfg_phy_preference pref, bool fcs, bool stx); /** @@ -87,65 +91,6 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, */ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer); -/** - * cfcnfg_disconn_adapt_layer - Disconnects an adaptation layer. - * - * @cnfg: Pointer to a CAIF configuration object, created by - * cfcnfg_create(). - * @adap_layer: Adaptation layer to be removed. - */ -int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, - struct cflayer *adap_layer); - -/** - * cfcnfg_release_adap_layer - Used by client to release the adaptation layer. - * - * @adap_layer: Adaptation layer. - */ -void cfcnfg_release_adap_layer(struct cflayer *adap_layer); - -/** - * cfcnfg_add_adaptation_layer - Add an adaptation layer to the CAIF stack. - * - * The adaptation Layer is where the interface to application or higher-level - * driver functionality is implemented. - * - * @cnfg: Pointer to a CAIF configuration object, created by - * cfcnfg_create(). - * @param: Link setup parameters. - * @adap_layer: Specify the adaptation layer; the receive and - * flow-control functions MUST be set in the structure. - * @ifindex: Link layer interface index used for this connection. - * @proto_head: Protocol head-space needed by CAIF protocol, - * excluding link layer. - * @proto_tail: Protocol tail-space needed by CAIF protocol, - * excluding link layer. - */ -int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, - struct cfctrl_link_param *param, - struct cflayer *adap_layer, - int *ifindex, - int *proto_head, - int *proto_tail); - -/** - * cfcnfg_get_phyid() - Get physical ID, given type. - * Returns one of the physical interfaces matching the given type. - * Zero if no match is found. - * @cnfg: Configuration object - * @phy_pref: Caif Link Layer preference - */ -struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, - enum cfcnfg_phy_preference phy_pref); - -/** - * cfcnfg_get_id_from_ifi() - Get the Physical Identifier of ifindex, - * it matches caif physical id with the kernel interface id. - * @cnfg: Configuration object - * @ifi: ifindex obtained from socket.c bindtodevice. - */ -int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi); - /** * cfcnfg_set_phy_state() - Set the state of the physical interface device. * @cnfg: Configuration object diff --git a/net/caif/Makefile b/net/caif/Makefile index 9d38e406e4a4..ebcd4e7e6f47 100644 --- a/net/caif/Makefile +++ b/net/caif/Makefile @@ -5,7 +5,7 @@ caif-y := caif_dev.o \ cffrml.o cfveil.o cfdbgl.o\ cfserl.o cfdgml.o \ cfrfml.o cfvidl.o cfutill.o \ - cfsrvl.o cfpkt_skbuff.o caif_config_util.o + cfsrvl.o cfpkt_skbuff.o obj-$(CONFIG_CAIF) += caif.o obj-$(CONFIG_CAIF_NETDEV) += chnl_net.o diff --git a/net/caif/caif_config_util.c b/net/caif/caif_config_util.c deleted file mode 100644 index 9b63e4e3910e..000000000000 --- a/net/caif/caif_config_util.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) ST-Ericsson AB 2010 - * Author: Sjur Brendeland sjur.brandeland@stericsson.com - * License terms: GNU General Public License (GPL) version 2 - */ - -#include -#include -#include -#include -#include - -int caif_connect_req_to_link_param(struct cfcnfg *cnfg, - struct caif_connect_request *s, - struct cfctrl_link_param *l) -{ - struct dev_info *dev_info; - enum cfcnfg_phy_preference pref; - int res; - - memset(l, 0, sizeof(*l)); - /* In caif protocol low value is high priority */ - l->priority = CAIF_PRIO_MAX - s->priority + 1; - - if (s->ifindex != 0){ - res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex); - if (res < 0) - return res; - l->phyid = res; - } - else { - switch (s->link_selector) { - case CAIF_LINK_HIGH_BANDW: - pref = CFPHYPREF_HIGH_BW; - break; - case CAIF_LINK_LOW_LATENCY: - pref = CFPHYPREF_LOW_LAT; - break; - default: - return -EINVAL; - } - dev_info = cfcnfg_get_phyid(cnfg, pref); - if (dev_info == NULL) - return -ENODEV; - l->phyid = dev_info->id; - } - switch (s->protocol) { - case CAIFPROTO_AT: - l->linktype = CFCTRL_SRV_VEI; - if (s->sockaddr.u.at.type == CAIF_ATTYPE_PLAIN) - l->chtype = 0x02; - else - l->chtype = s->sockaddr.u.at.type; - l->endpoint = 0x00; - break; - case CAIFPROTO_DATAGRAM: - l->linktype = CFCTRL_SRV_DATAGRAM; - l->chtype = 0x00; - l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; - break; - case CAIFPROTO_DATAGRAM_LOOP: - l->linktype = CFCTRL_SRV_DATAGRAM; - l->chtype = 0x03; - l->endpoint = 0x00; - l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; - break; - case CAIFPROTO_RFM: - l->linktype = CFCTRL_SRV_RFM; - l->u.datagram.connid = s->sockaddr.u.rfm.connection_id; - strncpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume, - sizeof(l->u.rfm.volume)-1); - l->u.rfm.volume[sizeof(l->u.rfm.volume)-1] = 0; - break; - case CAIFPROTO_UTIL: - l->linktype = CFCTRL_SRV_UTIL; - l->endpoint = 0x00; - l->chtype = 0x00; - strncpy(l->u.utility.name, s->sockaddr.u.util.service, - sizeof(l->u.utility.name)-1); - l->u.utility.name[sizeof(l->u.utility.name)-1] = 0; - caif_assert(sizeof(l->u.utility.name) > 10); - l->u.utility.paramlen = s->param.size; - if (l->u.utility.paramlen > sizeof(l->u.utility.params)) - l->u.utility.paramlen = sizeof(l->u.utility.params); - - memcpy(l->u.utility.params, s->param.data, - l->u.utility.paramlen); - - break; - case CAIFPROTO_DEBUG: - l->linktype = CFCTRL_SRV_DBG; - l->endpoint = s->sockaddr.u.dbg.service; - l->chtype = s->sockaddr.u.dbg.type; - break; - default: - return -EINVAL; - } - return 0; -} diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index 6d1d86be187b..0e651cf577cf 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -43,11 +42,21 @@ struct caif_device_entry_list { }; struct caif_net { + struct cfcnfg *cfg; struct caif_device_entry_list caifdevs; }; static int caif_net_id; -static struct cfcnfg *cfg; + +struct cfcnfg *get_cfcnfg(struct net *net) +{ + struct caif_net *caifn; + BUG_ON(!net); + caifn = net_generic(net, caif_net_id); + BUG_ON(!caifn); + return caifn->cfg; +} +EXPORT_SYMBOL(get_cfcnfg); static struct caif_device_entry_list *caif_device_list(struct net *net) { @@ -191,12 +200,17 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, struct caif_dev_common *caifdev; enum cfcnfg_phy_preference pref; enum cfcnfg_phy_type phy_type; + struct cfcnfg *cfg; struct caif_device_entry_list *caifdevs = caif_device_list(dev_net(dev)); if (dev->type != ARPHRD_CAIF) return 0; + cfg = get_cfcnfg(dev_net(dev)); + if (cfg == NULL) + return 0; + switch (what) { case NETDEV_REGISTER: caifd = caif_device_alloc(dev); @@ -235,7 +249,6 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, phy_type, dev, &caifd->layer, - 0, pref, caifdev->use_fcs, caifdev->use_stx); @@ -323,35 +336,20 @@ static struct notifier_block caif_device_notifier = { .priority = 0, }; -int caif_connect_client(struct caif_connect_request *conn_req, - struct cflayer *client_layer, int *ifindex, - int *headroom, int *tailroom) -{ - struct cfctrl_link_param param; - int ret; - - ret = caif_connect_req_to_link_param(cfg, conn_req, ¶m); - if (ret) - return ret; - /* Hook up the adaptation layer. */ - return cfcnfg_add_adaptation_layer(cfg, ¶m, - client_layer, ifindex, - headroom, tailroom); -} -EXPORT_SYMBOL(caif_connect_client); - -int caif_disconnect_client(struct cflayer *adap_layer) -{ - return cfcnfg_disconn_adapt_layer(cfg, adap_layer); -} -EXPORT_SYMBOL(caif_disconnect_client); - /* Per-namespace Caif devices handling */ static int caif_init_net(struct net *net) { struct caif_net *caifn = net_generic(net, caif_net_id); + BUG_ON(!caifn); INIT_LIST_HEAD(&caifn->caifdevs.list); mutex_init(&caifn->caifdevs.lock); + + caifn->cfg = cfcnfg_create(); + if (!caifn->cfg) { + pr_warn("can't create cfcnfg\n"); + return -ENOMEM; + } + return 0; } @@ -360,10 +358,17 @@ static void caif_exit_net(struct net *net) struct caif_device_entry *caifd, *tmp; struct caif_device_entry_list *caifdevs = caif_device_list(net); + struct cfcnfg *cfg; rtnl_lock(); mutex_lock(&caifdevs->lock); + cfg = get_cfcnfg(net); + if (cfg == NULL) { + mutex_unlock(&caifdevs->lock); + return; + } + list_for_each_entry_safe(caifd, tmp, &caifdevs->list, list) { int i = 0; list_del_rcu(&caifd->list); @@ -382,7 +387,7 @@ static void caif_exit_net(struct net *net) free_percpu(caifd->pcpu_refcnt); kfree(caifd); } - + cfcnfg_remove(cfg); mutex_unlock(&caifdevs->lock); rtnl_unlock(); @@ -400,32 +405,22 @@ static int __init caif_device_init(void) { int result; - cfg = cfcnfg_create(); - if (!cfg) { - pr_warn("can't create cfcnfg\n"); - goto err_cfcnfg_create_failed; - } result = register_pernet_device(&caif_net_ops); - if (result) { - kfree(cfg); - cfg = NULL; + if (result) return result; - } - dev_add_pack(&caif_packet_type); + register_netdevice_notifier(&caif_device_notifier); + dev_add_pack(&caif_packet_type); return result; -err_cfcnfg_create_failed: - return -ENODEV; } static void __exit caif_device_exit(void) { - dev_remove_pack(&caif_packet_type); unregister_pernet_device(&caif_net_ops); unregister_netdevice_notifier(&caif_device_notifier); - cfcnfg_remove(cfg); + dev_remove_pack(&caif_packet_type); } module_init(caif_device_init); diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 01f612df7df1..653db759eb7e 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -810,7 +810,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, sk->sk_state == CAIF_DISCONNECTED); if (sk->sk_shutdown & SHUTDOWN_MASK) { /* Allow re-connect after SHUTDOWN_IND */ - caif_disconnect_client(&cf_sk->layer); + caif_disconnect_client(sock_net(sk), &cf_sk->layer); break; } /* No reconnect on a seqpacket socket */ @@ -851,7 +851,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, dbfs_atomic_inc(&cnt.num_connect_req); cf_sk->layer.receive = caif_sktrecv_cb; - err = caif_connect_client(&cf_sk->conn_req, + err = caif_connect_client(sock_net(sk), &cf_sk->conn_req, &cf_sk->layer, &ifindex, &headroom, &tailroom); if (err < 0) { @@ -949,7 +949,7 @@ static int caif_release(struct socket *sock) if (cf_sk->sk.sk_socket->state == SS_CONNECTED || cf_sk->sk.sk_socket->state == SS_CONNECTING) - res = caif_disconnect_client(&cf_sk->layer); + res = caif_disconnect_client(sock_net(sk), &cf_sk->layer); cf_sk->sk.sk_socket->state = SS_DISCONNECTING; wake_up_interruptible_poll(sk_sleep(sk), POLLERR|POLLHUP); diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index 3f4f31fca2c1..e857d8995ca3 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c @@ -150,7 +150,7 @@ static void cfctrl_enum_resp(void) { } -struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, +static struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, enum cfcnfg_phy_preference phy_pref) { /* Try to match with specified preference */ @@ -171,7 +171,7 @@ struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, return NULL; } -int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) +static int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) { struct cfcnfg_phyinfo *phy; @@ -181,11 +181,12 @@ int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) return -ENODEV; } -int cfcnfg_disconn_adapt_layer(struct cfcnfg *cfg, struct cflayer *adap_layer) +int caif_disconnect_client(struct net *net, struct cflayer *adap_layer) { u8 channel_id = 0; int ret = 0; struct cflayer *servl = NULL; + struct cfcnfg *cfg = get_cfcnfg(net); caif_assert(adap_layer != NULL); @@ -217,14 +218,7 @@ end: return ret; } -EXPORT_SYMBOL(cfcnfg_disconn_adapt_layer); - -void cfcnfg_release_adap_layer(struct cflayer *adap_layer) -{ - if (adap_layer->dn) - cfsrvl_put(adap_layer->dn); -} -EXPORT_SYMBOL(cfcnfg_release_adap_layer); +EXPORT_SYMBOL(caif_disconnect_client); static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id) { @@ -238,19 +232,109 @@ static const int protohead[CFCTRL_SRV_MASK] = { [CFCTRL_SRV_DBG] = 3, }; -int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, - struct cfctrl_link_param *param, - struct cflayer *adap_layer, - int *ifindex, + +static int caif_connect_req_to_link_param(struct cfcnfg *cnfg, + struct caif_connect_request *s, + struct cfctrl_link_param *l) +{ + struct dev_info *dev_info; + enum cfcnfg_phy_preference pref; + int res; + + memset(l, 0, sizeof(*l)); + /* In caif protocol low value is high priority */ + l->priority = CAIF_PRIO_MAX - s->priority + 1; + + if (s->ifindex != 0) { + res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex); + if (res < 0) + return res; + l->phyid = res; + } else { + switch (s->link_selector) { + case CAIF_LINK_HIGH_BANDW: + pref = CFPHYPREF_HIGH_BW; + break; + case CAIF_LINK_LOW_LATENCY: + pref = CFPHYPREF_LOW_LAT; + break; + default: + return -EINVAL; + } + dev_info = cfcnfg_get_phyid(cnfg, pref); + if (dev_info == NULL) + return -ENODEV; + l->phyid = dev_info->id; + } + switch (s->protocol) { + case CAIFPROTO_AT: + l->linktype = CFCTRL_SRV_VEI; + l->endpoint = (s->sockaddr.u.at.type >> 2) & 0x3; + l->chtype = s->sockaddr.u.at.type & 0x3; + break; + case CAIFPROTO_DATAGRAM: + l->linktype = CFCTRL_SRV_DATAGRAM; + l->chtype = 0x00; + l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; + break; + case CAIFPROTO_DATAGRAM_LOOP: + l->linktype = CFCTRL_SRV_DATAGRAM; + l->chtype = 0x03; + l->endpoint = 0x00; + l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; + break; + case CAIFPROTO_RFM: + l->linktype = CFCTRL_SRV_RFM; + l->u.datagram.connid = s->sockaddr.u.rfm.connection_id; + strncpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume, + sizeof(l->u.rfm.volume)-1); + l->u.rfm.volume[sizeof(l->u.rfm.volume)-1] = 0; + break; + case CAIFPROTO_UTIL: + l->linktype = CFCTRL_SRV_UTIL; + l->endpoint = 0x00; + l->chtype = 0x00; + strncpy(l->u.utility.name, s->sockaddr.u.util.service, + sizeof(l->u.utility.name)-1); + l->u.utility.name[sizeof(l->u.utility.name)-1] = 0; + caif_assert(sizeof(l->u.utility.name) > 10); + l->u.utility.paramlen = s->param.size; + if (l->u.utility.paramlen > sizeof(l->u.utility.params)) + l->u.utility.paramlen = sizeof(l->u.utility.params); + + memcpy(l->u.utility.params, s->param.data, + l->u.utility.paramlen); + + break; + case CAIFPROTO_DEBUG: + l->linktype = CFCTRL_SRV_DBG; + l->endpoint = s->sockaddr.u.dbg.service; + l->chtype = s->sockaddr.u.dbg.type; + break; + default: + return -EINVAL; + } + return 0; +} + +int caif_connect_client(struct net *net, struct caif_connect_request *conn_req, + struct cflayer *adap_layer, int *ifindex, int *proto_head, int *proto_tail) { struct cflayer *frml; struct cfcnfg_phyinfo *phy; int err; + struct cfctrl_link_param param; + struct cfcnfg *cfg = get_cfcnfg(net); + caif_assert(cfg != NULL); rcu_read_lock(); - phy = cfcnfg_get_phyinfo_rcu(cnfg, param->phyid); + err = caif_connect_req_to_link_param(cfg, conn_req, ¶m); + if (err) + goto unlock; + + phy = cfcnfg_get_phyinfo_rcu(cfg, param.phyid); if (!phy) { err = -ENODEV; goto unlock; @@ -276,28 +360,29 @@ int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, pr_err("Specified PHY type does not exist!\n"); goto unlock; } - caif_assert(param->phyid == phy->id); + caif_assert(param.phyid == phy->id); caif_assert(phy->frm_layer->id == - param->phyid); + param.phyid); caif_assert(phy->phy_layer->id == - param->phyid); + param.phyid); *ifindex = phy->ifindex; *proto_tail = 2; *proto_head = - protohead[param->linktype] + (phy->use_stx ? 1 : 0); + + protohead[param.linktype] + (phy->use_stx ? 1 : 0); rcu_read_unlock(); /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ - cfctrl_enum_req(cnfg->ctrl, param->phyid); - return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer); + cfctrl_enum_req(cfg->ctrl, param.phyid); + return cfctrl_linkup_request(cfg->ctrl, ¶m, adap_layer); unlock: rcu_read_unlock(); return err; } -EXPORT_SYMBOL(cfcnfg_add_adaptation_layer); +EXPORT_SYMBOL(caif_connect_client); static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, struct cflayer *adapt_layer) @@ -389,7 +474,7 @@ unlock: void cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, struct net_device *dev, struct cflayer *phy_layer, - u16 *phy_id, enum cfcnfg_phy_preference pref, + enum cfcnfg_phy_preference pref, bool fcs, bool stx) { struct cflayer *frml; @@ -512,23 +597,26 @@ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) phyid = phy_layer->id; phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid); - if (phyinfo == NULL) + if (phyinfo == NULL) { + mutex_unlock(&cnfg->lock); return 0; + } caif_assert(phyid == phyinfo->id); caif_assert(phy_layer == phyinfo->phy_layer); caif_assert(phy_layer->id == phyid); caif_assert(phyinfo->frm_layer->id == phyid); + list_del_rcu(&phyinfo->node); + synchronize_rcu(); + /* Fail if reference count is not zero */ if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) { pr_info("Wait for device inuse\n"); + list_add_rcu(&phyinfo->node, &cnfg->phys); mutex_unlock(&cnfg->lock); return -EAGAIN; } - list_del_rcu(&phyinfo->node); - synchronize_rcu(); - frml = phyinfo->frm_layer; frml_dn = frml->dn; cffrml_set_uplayer(frml, NULL); @@ -539,8 +627,6 @@ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) } layer_set_up(phy_layer, NULL); - - if (phyinfo->phy_layer != frml_dn) kfree(frml_dn); diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 9ef8f1660ee1..1a3398a89aee 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -270,8 +269,9 @@ static int chnl_net_open(struct net_device *dev) if (priv->state != CAIF_CONNECTING) { priv->state = CAIF_CONNECTING; - result = caif_connect_client(&priv->conn_req, &priv->chnl, - &llifindex, &headroom, &tailroom); + result = caif_connect_client(dev_net(dev), &priv->conn_req, + &priv->chnl, &llifindex, + &headroom, &tailroom); if (result != 0) { pr_debug("err: " "Unable to register and open device," @@ -327,7 +327,7 @@ static int chnl_net_open(struct net_device *dev) if (result == 0) { pr_debug("connect timeout\n"); - caif_disconnect_client(&priv->chnl); + caif_disconnect_client(dev_net(dev), &priv->chnl); priv->state = CAIF_DISCONNECTED; pr_debug("state disconnected\n"); result = -ETIMEDOUT; @@ -343,7 +343,7 @@ static int chnl_net_open(struct net_device *dev) return 0; error: - caif_disconnect_client(&priv->chnl); + caif_disconnect_client(dev_net(dev), &priv->chnl); priv->state = CAIF_DISCONNECTED; pr_debug("state disconnected\n"); return result; @@ -357,7 +357,7 @@ static int chnl_net_stop(struct net_device *dev) ASSERT_RTNL(); priv = netdev_priv(dev); priv->state = CAIF_DISCONNECTED; - caif_disconnect_client(&priv->chnl); + caif_disconnect_client(dev_net(dev), &priv->chnl); return 0; } -- cgit v1.2.3-58-ga151 From c85c2951d4da1236e32f1858db418221e624aba5 Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Fri, 13 May 2011 02:44:06 +0000 Subject: caif: Handle dev_queue_xmit errors. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do proper handling of dev_queue_xmit errors in order to avoid double free of skb and leaks in error conditions. In cfctrl pending requests are removed when CAIF Link layer goes down. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- include/net/caif/cfctrl.h | 3 +- net/caif/caif_dev.c | 7 ++- net/caif/caif_socket.c | 8 +-- net/caif/cfcnfg.c | 2 +- net/caif/cfctrl.c | 121 ++++++++++++++++++++++++++++++++-------------- net/caif/cffrml.c | 17 ++++++- net/caif/cfveil.c | 8 ++- 7 files changed, 119 insertions(+), 47 deletions(-) diff --git a/include/net/caif/cfctrl.h b/include/net/caif/cfctrl.h index d84416fa175a..9e5425b4a1d7 100644 --- a/include/net/caif/cfctrl.h +++ b/include/net/caif/cfctrl.h @@ -124,6 +124,7 @@ int cfctrl_linkdown_req(struct cflayer *cfctrl, u8 linkid, struct cflayer *cfctrl_create(void); struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer); -void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer); +int cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer); +void cfctrl_remove(struct cflayer *layr); #endif /* CFCTRL_H_ */ diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index 0e651cf577cf..366ca0fb7a29 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -118,6 +118,7 @@ static struct caif_device_entry *caif_get(struct net_device *dev) static int transmit(struct cflayer *layer, struct cfpkt *pkt) { + int err; struct caif_device_entry *caifd = container_of(layer, struct caif_device_entry, layer); struct sk_buff *skb; @@ -125,9 +126,11 @@ static int transmit(struct cflayer *layer, struct cfpkt *pkt) skb = cfpkt_tonative(pkt); skb->dev = caifd->netdev; - dev_queue_xmit(skb); + err = dev_queue_xmit(skb); + if (err > 0) + err = -EIO; - return 0; + return err; } /* diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 653db759eb7e..7baae11a6126 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -604,7 +604,9 @@ static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock, goto err; ret = transmit_skb(skb, cf_sk, noblock, timeo); if (ret < 0) - goto err; + /* skb is already freed */ + return ret; + return len; err: kfree_skb(skb); @@ -933,9 +935,9 @@ static int caif_release(struct socket *sock) * caif_queue_rcv_skb checks SOCK_DEAD holding the queue lock, * this ensures no packets when sock is dead. */ - spin_lock(&sk->sk_receive_queue.lock); + spin_lock_bh(&sk->sk_receive_queue.lock); sock_set_flag(sk, SOCK_DEAD); - spin_unlock(&sk->sk_receive_queue.lock); + spin_unlock_bh(&sk->sk_receive_queue.lock); sock->sk = NULL; dbfs_atomic_inc(&cnt.num_disconnect); diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index e857d8995ca3..423009918f79 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c @@ -126,7 +126,7 @@ void cfcnfg_remove(struct cfcnfg *cfg) synchronize_rcu(); kfree(cfg->mux); - kfree(cfg->ctrl); + cfctrl_remove(cfg->ctrl); kfree(cfg); } } diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c index 397a2c099e2c..0c00a6015dda 100644 --- a/net/caif/cfctrl.c +++ b/net/caif/cfctrl.c @@ -17,7 +17,6 @@ #define UTILITY_NAME_LENGTH 16 #define CFPKT_CTRL_PKT_LEN 20 - #ifdef CAIF_NO_LOOP static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt){ @@ -51,13 +50,29 @@ struct cflayer *cfctrl_create(void) this->serv.layer.receive = cfctrl_recv; sprintf(this->serv.layer.name, "ctrl"); this->serv.layer.ctrlcmd = cfctrl_ctrlcmd; +#ifndef CAIF_NO_LOOP spin_lock_init(&this->loop_linkid_lock); + this->loop_linkid = 1; +#endif spin_lock_init(&this->info_list_lock); INIT_LIST_HEAD(&this->list); - this->loop_linkid = 1; return &this->serv.layer; } +void cfctrl_remove(struct cflayer *layer) +{ + struct cfctrl_request_info *p, *tmp; + struct cfctrl *ctrl = container_obj(layer); + + spin_lock_bh(&ctrl->info_list_lock); + list_for_each_entry_safe(p, tmp, &ctrl->list, list) { + list_del(&p->list); + kfree(p); + } + spin_unlock_bh(&ctrl->info_list_lock); + kfree(layer); +} + static bool param_eq(const struct cfctrl_link_param *p1, const struct cfctrl_link_param *p2) { @@ -116,11 +131,11 @@ static bool cfctrl_req_eq(const struct cfctrl_request_info *r1, static void cfctrl_insert_req(struct cfctrl *ctrl, struct cfctrl_request_info *req) { - spin_lock(&ctrl->info_list_lock); + spin_lock_bh(&ctrl->info_list_lock); atomic_inc(&ctrl->req_seq_no); req->sequence_no = atomic_read(&ctrl->req_seq_no); list_add_tail(&req->list, &ctrl->list); - spin_unlock(&ctrl->info_list_lock); + spin_unlock_bh(&ctrl->info_list_lock); } /* Compare and remove request */ @@ -129,7 +144,6 @@ static struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, { struct cfctrl_request_info *p, *tmp, *first; - spin_lock(&ctrl->info_list_lock); first = list_first_entry(&ctrl->list, struct cfctrl_request_info, list); list_for_each_entry_safe(p, tmp, &ctrl->list, list) { @@ -145,7 +159,6 @@ static struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, } p = NULL; out: - spin_unlock(&ctrl->info_list_lock); return p; } @@ -179,10 +192,6 @@ void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid) cfpkt_addbdy(pkt, physlinkid); ret = cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); - if (ret < 0) { - pr_err("Could not transmit enum message\n"); - cfpkt_destroy(pkt); - } } int cfctrl_linkup_request(struct cflayer *layer, @@ -196,14 +205,23 @@ int cfctrl_linkup_request(struct cflayer *layer, struct cfctrl_request_info *req; int ret; char utility_name[16]; - struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); + struct cfpkt *pkt; + + if (cfctrl_cancel_req(layer, user_layer) > 0) { + /* Slight Paranoia, check if already connecting */ + pr_err("Duplicate connect request for same client\n"); + WARN_ON(1); + return -EALREADY; + } + + pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); if (!pkt) { pr_warn("Out of memory\n"); return -ENOMEM; } cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP); - cfpkt_addbdy(pkt, (param->chtype << 4) + param->linktype); - cfpkt_addbdy(pkt, (param->priority << 3) + param->phyid); + cfpkt_addbdy(pkt, (param->chtype << 4) | param->linktype); + cfpkt_addbdy(pkt, (param->priority << 3) | param->phyid); cfpkt_addbdy(pkt, param->endpoint & 0x03); switch (param->linktype) { @@ -266,9 +284,13 @@ int cfctrl_linkup_request(struct cflayer *layer, ret = cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); if (ret < 0) { - pr_err("Could not transmit linksetup request\n"); - cfpkt_destroy(pkt); - return -ENODEV; + int count; + + count = cfctrl_cancel_req(&cfctrl->serv.layer, + user_layer); + if (count != 1) + pr_err("Could not remove request (%d)", count); + return -ENODEV; } return 0; } @@ -288,28 +310,29 @@ int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, init_info(cfpkt_info(pkt), cfctrl); ret = cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); - if (ret < 0) { - pr_err("Could not transmit link-down request\n"); - cfpkt_destroy(pkt); - } +#ifndef CAIF_NO_LOOP + cfctrl->loop_linkused[channelid] = 0; +#endif return ret; } -void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer) +int cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer) { struct cfctrl_request_info *p, *tmp; struct cfctrl *ctrl = container_obj(layr); - spin_lock(&ctrl->info_list_lock); + int found = 0; + spin_lock_bh(&ctrl->info_list_lock); list_for_each_entry_safe(p, tmp, &ctrl->list, list) { if (p->client_layer == adap_layer) { - pr_debug("cancel req :%d\n", p->sequence_no); list_del(&p->list); kfree(p); + found++; } } - spin_unlock(&ctrl->info_list_lock); + spin_unlock_bh(&ctrl->info_list_lock); + return found; } static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) @@ -461,6 +484,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) rsp.cmd = cmd; rsp.param = linkparam; + spin_lock_bh(&cfctrl->info_list_lock); req = cfctrl_remove_req(cfctrl, &rsp); if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) || @@ -480,6 +504,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) if (req != NULL) kfree(req); + + spin_unlock_bh(&cfctrl->info_list_lock); } break; case CFCTRL_CMD_LINK_DESTROY: @@ -523,12 +549,29 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, switch (ctrl) { case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: case CAIF_CTRLCMD_FLOW_OFF_IND: - spin_lock(&this->info_list_lock); + spin_lock_bh(&this->info_list_lock); if (!list_empty(&this->list)) { pr_debug("Received flow off in control layer\n"); } - spin_unlock(&this->info_list_lock); + spin_unlock_bh(&this->info_list_lock); break; + case _CAIF_CTRLCMD_PHYIF_DOWN_IND: { + struct cfctrl_request_info *p, *tmp; + + /* Find all connect request and report failure */ + spin_lock_bh(&this->info_list_lock); + list_for_each_entry_safe(p, tmp, &this->list, list) { + if (p->param.phyid == phyid) { + list_del(&p->list); + p->client_layer->ctrlcmd(p->client_layer, + CAIF_CTRLCMD_INIT_FAIL_RSP, + phyid); + kfree(p); + } + } + spin_unlock_bh(&this->info_list_lock); + break; + } default: break; } @@ -538,27 +581,33 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt) { static int last_linkid; + static int dec; u8 linkid, linktype, tmp; switch (cmd) { case CFCTRL_CMD_LINK_SETUP: - spin_lock(&ctrl->loop_linkid_lock); - for (linkid = last_linkid + 1; linkid < 255; linkid++) - if (!ctrl->loop_linkused[linkid]) - goto found; + spin_lock_bh(&ctrl->loop_linkid_lock); + if (!dec) { + for (linkid = last_linkid + 1; linkid < 255; linkid++) + if (!ctrl->loop_linkused[linkid]) + goto found; + } + dec = 1; for (linkid = last_linkid - 1; linkid > 0; linkid--) if (!ctrl->loop_linkused[linkid]) goto found; - spin_unlock(&ctrl->loop_linkid_lock); - pr_err("Out of link-ids\n"); - return -EINVAL; + spin_unlock_bh(&ctrl->loop_linkid_lock); + found: + if (linkid < 10) + dec = 0; + if (!ctrl->loop_linkused[linkid]) ctrl->loop_linkused[linkid] = 1; last_linkid = linkid; cfpkt_add_trail(pkt, &linkid, 1); - spin_unlock(&ctrl->loop_linkid_lock); + spin_unlock_bh(&ctrl->loop_linkid_lock); cfpkt_peek_head(pkt, &linktype, 1); if (linktype == CFCTRL_SRV_UTIL) { tmp = 0x01; @@ -568,10 +617,10 @@ found: break; case CFCTRL_CMD_LINK_DESTROY: - spin_lock(&ctrl->loop_linkid_lock); + spin_lock_bh(&ctrl->loop_linkid_lock); cfpkt_peek_head(pkt, &linkid, 1); ctrl->loop_linkused[linkid] = 0; - spin_unlock(&ctrl->loop_linkid_lock); + spin_unlock_bh(&ctrl->loop_linkid_lock); break; default: break; diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c index 4f4f756c49ac..04204b202718 100644 --- a/net/caif/cffrml.c +++ b/net/caif/cffrml.c @@ -33,7 +33,6 @@ static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, static u32 cffrml_rcv_error; static u32 cffrml_rcv_checsum_error; struct cflayer *cffrml_create(u16 phyid, bool use_fcs) - { struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC); if (!this) { @@ -128,6 +127,13 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt) cfpkt_destroy(pkt); return -EPROTO; } + + if (layr->up == NULL) { + pr_err("Layr up is missing!\n"); + cfpkt_destroy(pkt); + return -EINVAL; + } + return layr->up->receive(layr->up, pkt); } @@ -150,15 +156,22 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt) cfpkt_info(pkt)->hdr_len += 2; if (cfpkt_erroneous(pkt)) { pr_err("Packet is erroneous!\n"); + cfpkt_destroy(pkt); return -EPROTO; } + + if (layr->dn == NULL) { + cfpkt_destroy(pkt); + return -ENODEV; + + } return layr->dn->transmit(layr->dn, pkt); } static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, int phyid) { - if (layr->up->ctrlcmd) + if (layr->up && layr->up->ctrlcmd) layr->up->ctrlcmd(layr->up, ctrl, layr->id); } diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c index 1a588cd818ea..3ec83fbc2887 100644 --- a/net/caif/cfveil.c +++ b/net/caif/cfveil.c @@ -82,13 +82,14 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt) int ret; struct cfsrvl *service = container_obj(layr); if (!cfsrvl_ready(service, &ret)) - return ret; + goto err; caif_assert(layr->dn != NULL); caif_assert(layr->dn->transmit != NULL); if (cfpkt_add_head(pkt, &tmp, 1) < 0) { pr_err("Packet is erroneous!\n"); - return -EPROTO; + ret = -EPROTO; + goto err; } /* Add info-> for MUX-layer to route the packet out. */ @@ -97,4 +98,7 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt) info->hdr_len = 1; info->dev_info = &service->dev_info; return layr->dn->transmit(layr->dn, pkt); +err: + cfpkt_destroy(pkt); + return ret; } -- cgit v1.2.3-58-ga151 From 33b2f5598b4ee68021364a7b795c09ad66bc0aa8 Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Fri, 13 May 2011 02:44:07 +0000 Subject: caif: Bugfix debugfs directory name must be unique. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Race condition caused debugfs_create_dir() to fail due to duplicate name. Use atomic counter to create unique directory name. net_ratelimit() is introduced to limit debug printouts. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- net/caif/caif_socket.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 7baae11a6126..5cf9c73a4078 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -48,6 +48,7 @@ static struct dentry *debugfsdir; #ifdef CONFIG_DEBUG_FS struct debug_fs_counter { atomic_t caif_nr_socks; + atomic_t caif_sock_create; atomic_t num_connect_req; atomic_t num_connect_resp; atomic_t num_connect_fail_resp; @@ -59,11 +60,11 @@ struct debug_fs_counter { atomic_t num_rx_flow_on; }; static struct debug_fs_counter cnt; -#define dbfs_atomic_inc(v) atomic_inc(v) -#define dbfs_atomic_dec(v) atomic_dec(v) +#define dbfs_atomic_inc(v) atomic_inc_return(v) +#define dbfs_atomic_dec(v) atomic_dec_return(v) #else -#define dbfs_atomic_inc(v) -#define dbfs_atomic_dec(v) +#define dbfs_atomic_inc(v) 0 +#define dbfs_atomic_dec(v) 0 #endif struct caifsock { @@ -155,9 +156,10 @@ static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= (unsigned)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { - pr_debug("sending flow OFF (queue len = %d %d)\n", - atomic_read(&cf_sk->sk.sk_rmem_alloc), - sk_rcvbuf_lowwater(cf_sk)); + if (net_ratelimit()) + pr_debug("sending flow OFF (queue len = %d %d)\n", + atomic_read(&cf_sk->sk.sk_rmem_alloc), + sk_rcvbuf_lowwater(cf_sk)); set_rx_flow_off(cf_sk); dbfs_atomic_inc(&cnt.num_rx_flow_off); caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ); @@ -168,7 +170,8 @@ static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) return err; if (!sk_rmem_schedule(sk, skb->truesize) && rx_flow_is_on(cf_sk)) { set_rx_flow_off(cf_sk); - pr_debug("sending flow OFF due to rmem_schedule\n"); + if (net_ratelimit()) + pr_debug("sending flow OFF due to rmem_schedule\n"); dbfs_atomic_inc(&cnt.num_rx_flow_off); caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ); } @@ -838,7 +841,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, sock->state = SS_CONNECTING; sk->sk_state = CAIF_CONNECTING; - /* Check priority value coming from socket */ + /* Check priority value comming from socket */ /* if priority value is out of range it will be ajusted */ if (cf_sk->sk.sk_priority > CAIF_PRIO_MAX) cf_sk->conn_req.priority = CAIF_PRIO_MAX; @@ -942,6 +945,7 @@ static int caif_release(struct socket *sock) dbfs_atomic_inc(&cnt.num_disconnect); + WARN_ON(IS_ERR(cf_sk->debugfs_socket_dir)); if (cf_sk->debugfs_socket_dir != NULL) debugfs_remove_recursive(cf_sk->debugfs_socket_dir); @@ -1047,7 +1051,7 @@ static void caif_sock_destructor(struct sock *sk) caif_assert(sk_unhashed(sk)); caif_assert(!sk->sk_socket); if (!sock_flag(sk, SOCK_DEAD)) { - pr_info("Attempt to release alive CAIF socket: %p\n", sk); + pr_debug("Attempt to release alive CAIF socket: %p\n", sk); return; } sk_stream_kill_queues(&cf_sk->sk); @@ -1058,6 +1062,7 @@ static void caif_sock_destructor(struct sock *sk) static int caif_create(struct net *net, struct socket *sock, int protocol, int kern) { + int num; struct sock *sk = NULL; struct caifsock *cf_sk = NULL; static struct proto prot = {.name = "PF_CAIF", @@ -1120,14 +1125,16 @@ static int caif_create(struct net *net, struct socket *sock, int protocol, cf_sk->conn_req.protocol = protocol; /* Increase the number of sockets created. */ dbfs_atomic_inc(&cnt.caif_nr_socks); + num = dbfs_atomic_inc(&cnt.caif_sock_create); #ifdef CONFIG_DEBUG_FS if (!IS_ERR(debugfsdir)) { + /* Fill in some information concerning the misc socket. */ - snprintf(cf_sk->name, sizeof(cf_sk->name), "cfsk%d", - atomic_read(&cnt.caif_nr_socks)); + snprintf(cf_sk->name, sizeof(cf_sk->name), "cfsk%d", num); cf_sk->debugfs_socket_dir = debugfs_create_dir(cf_sk->name, debugfsdir); + debugfs_create_u32("sk_state", S_IRUSR | S_IWUSR, cf_sk->debugfs_socket_dir, (u32 *) &cf_sk->sk.sk_state); @@ -1171,6 +1178,9 @@ static int __init caif_sktinit_module(void) debugfs_create_u32("num_sockets", S_IRUSR | S_IWUSR, debugfsdir, (u32 *) &cnt.caif_nr_socks); + debugfs_create_u32("num_create", S_IRUSR | S_IWUSR, + debugfsdir, + (u32 *) &cnt.caif_sock_create); debugfs_create_u32("num_connect_req", S_IRUSR | S_IWUSR, debugfsdir, (u32 *) &cnt.num_connect_req); -- cgit v1.2.3-58-ga151 From 3f874adc4ae80828b79e8aac6891c108c1f6be6d Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Fri, 13 May 2011 02:44:08 +0000 Subject: caif: remove unesesarry exports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- include/net/caif/cfpkt.h | 1 - net/caif/caif_socket.c | 4 ++-- net/caif/cfcnfg.c | 1 - net/caif/cfpkt_skbuff.c | 27 ++++++++------------------- net/caif/chnl_net.c | 5 +++-- 5 files changed, 13 insertions(+), 25 deletions(-) diff --git a/include/net/caif/cfpkt.h b/include/net/caif/cfpkt.h index 8b550f8950d7..6bd200a4754a 100644 --- a/include/net/caif/cfpkt.h +++ b/include/net/caif/cfpkt.h @@ -195,5 +195,4 @@ void *cfpkt_tonative(struct cfpkt *pkt); * @return Packet information */ struct caif_payload_info *cfpkt_info(struct cfpkt *pkt); -/*! @} */ #endif /* CFPKT_H_ */ diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 5cf9c73a4078..b840395ced1d 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -205,7 +205,7 @@ static int caif_sktrecv_cb(struct cflayer *layr, struct cfpkt *pkt) skb = cfpkt_tonative(pkt); if (unlikely(cf_sk->sk.sk_state != CAIF_CONNECTED)) { - cfpkt_destroy(pkt); + kfree_skb(skb); return 0; } caif_queue_rcv_skb(&cf_sk->sk, skb); @@ -537,7 +537,7 @@ static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk, struct cfpkt *pkt; pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb); - memset(cfpkt_info(pkt), 0, sizeof(struct caif_payload_info)); + memset(skb->cb, 0, sizeof(struct caif_payload_info)); if (cf_sk->layer.dn == NULL) return -EINVAL; diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index 423009918f79..351c2ca7e7b9 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c @@ -117,7 +117,6 @@ out_of_mem: kfree(this); return NULL; } -EXPORT_SYMBOL(cfcnfg_create); void cfcnfg_remove(struct cfcnfg *cfg) { diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c index 20c6cb3522e0..75d4bfae1a78 100644 --- a/net/caif/cfpkt_skbuff.c +++ b/net/caif/cfpkt_skbuff.c @@ -97,21 +97,20 @@ inline struct cfpkt *cfpkt_create(u16 len) { return cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); } -EXPORT_SYMBOL(cfpkt_create); void cfpkt_destroy(struct cfpkt *pkt) { struct sk_buff *skb = pkt_to_skb(pkt); kfree_skb(skb); } -EXPORT_SYMBOL(cfpkt_destroy); + inline bool cfpkt_more(struct cfpkt *pkt) { struct sk_buff *skb = pkt_to_skb(pkt); return skb->len > 0; } -EXPORT_SYMBOL(cfpkt_more); + int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len) { @@ -123,7 +122,6 @@ int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len) return !cfpkt_extr_head(pkt, data, len) && !cfpkt_add_head(pkt, data, len); } -EXPORT_SYMBOL(cfpkt_peek_head); int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len) { @@ -148,7 +146,6 @@ int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len) memcpy(data, from, len); return 0; } -EXPORT_SYMBOL(cfpkt_extr_head); int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len) { @@ -171,13 +168,13 @@ int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len) memcpy(data, from, len); return 0; } -EXPORT_SYMBOL(cfpkt_extr_trail); + int cfpkt_pad_trail(struct cfpkt *pkt, u16 len) { return cfpkt_add_body(pkt, NULL, len); } -EXPORT_SYMBOL(cfpkt_pad_trail); + int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len) { @@ -226,13 +223,11 @@ int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len) memcpy(to, data, len); return 0; } -EXPORT_SYMBOL(cfpkt_add_body); inline int cfpkt_addbdy(struct cfpkt *pkt, u8 data) { return cfpkt_add_body(pkt, &data, 1); } -EXPORT_SYMBOL(cfpkt_addbdy); int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) { @@ -259,20 +254,20 @@ int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) memcpy(to, data, len); return 0; } -EXPORT_SYMBOL(cfpkt_add_head); + inline int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len) { return cfpkt_add_body(pkt, data, len); } -EXPORT_SYMBOL(cfpkt_add_trail); + inline u16 cfpkt_getlen(struct cfpkt *pkt) { struct sk_buff *skb = pkt_to_skb(pkt); return skb->len; } -EXPORT_SYMBOL(cfpkt_getlen); + inline u16 cfpkt_iterate(struct cfpkt *pkt, u16 (*iter_func)(u16, void *, u16), @@ -290,7 +285,7 @@ inline u16 cfpkt_iterate(struct cfpkt *pkt, } return iter_func(data, pkt->skb.data, cfpkt_getlen(pkt)); } -EXPORT_SYMBOL(cfpkt_iterate); + int cfpkt_setlen(struct cfpkt *pkt, u16 len) { @@ -315,7 +310,6 @@ int cfpkt_setlen(struct cfpkt *pkt, u16 len) return cfpkt_getlen(pkt); } -EXPORT_SYMBOL(cfpkt_setlen); struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, struct cfpkt *addpkt, @@ -357,7 +351,6 @@ struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, dst->len += addlen; return skb_to_pkt(dst); } -EXPORT_SYMBOL(cfpkt_append); struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) { @@ -395,17 +388,13 @@ struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) skb2->len += len2nd; return skb_to_pkt(skb2); } -EXPORT_SYMBOL(cfpkt_split); bool cfpkt_erroneous(struct cfpkt *pkt) { return cfpkt_priv(pkt)->erronous; } -EXPORT_SYMBOL(cfpkt_erroneous); - struct caif_payload_info *cfpkt_info(struct cfpkt *pkt) { return (struct caif_payload_info *)&pkt_to_skb(pkt)->cb; } -EXPORT_SYMBOL(cfpkt_info); diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 1a3398a89aee..649ebacaf6bc 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -83,10 +83,11 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt) if (!priv) return -EINVAL; + skb = (struct sk_buff *) cfpkt_tonative(pkt); + /* Get length of CAIF packet. */ - pktlen = cfpkt_getlen(pkt); + pktlen = skb->len; - skb = (struct sk_buff *) cfpkt_tonative(pkt); /* Pass some minimum information and * send the packet to the net stack. */ -- cgit v1.2.3-58-ga151 From 534ea99b063de7c30262a8e22f0ab44dd7d11a71 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Fri, 13 May 2011 21:08:47 +0000 Subject: net: drivers: kill two unused macro definitions Signed-off-by: Shan Wei Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bonding.h | 10 ---------- drivers/net/veth.c | 1 - 2 files changed, 11 deletions(-) diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index d08362e1a0dd..ea1d005be92d 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -38,16 +38,6 @@ netif_running(dev) && \ netif_carrier_ok(dev)) -/* - * Checks whether bond is ready for transmit. - * - * Caller must hold bond->lock - */ -#define BOND_IS_OK(bond) \ - (((bond)->dev->flags & IFF_UP) && \ - netif_running((bond)->dev) && \ - ((bond)->slave_cnt > 0)) - /* * Checks whether slave is ready for transmit. */ diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 3b0151a2a31b..8461576fa015 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -22,7 +22,6 @@ #define MIN_MTU 68 /* Min L3 MTU */ #define MAX_MTU 65535 /* Max L3 MTU (arbitrary) */ -#define MTU_PAD (ETH_HLEN + 4) /* Max difference between L2 and L3 size MTU */ struct veth_net_stats { unsigned long rx_packets; -- cgit v1.2.3-58-ga151 From 274ea0e2a4cdf18110e5931b8ecbfef6353e5293 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 16 May 2011 14:42:26 +0200 Subject: netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages Verify that the message length of a single SIP message, which is calculated based on the Content-Length field contained in the SIP message, does not exceed the packet boundaries. Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_sip.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index bcf47eb518ef..1f81abde131f 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -1461,6 +1461,8 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, end += strlen("\r\n\r\n") + clen; msglen = origlen = end - dptr; + if (msglen > datalen) + return NF_DROP; ret = process_sip_msg(skb, ct, dataoff, &dptr, &msglen); if (ret != NF_ACCEPT) -- cgit v1.2.3-58-ga151 From e6e4d9ed11fb1fab8b3256a3dc14d71b5e984ac4 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 16 May 2011 14:45:39 +0200 Subject: netfilter: nf_ct_sip: fix SDP parsing in TCP SIP messages for some Cisco phones Some Cisco phones do not place the Content-Length field at the end of the SIP message. This is valid, due to a misunderstanding of the specification the parser expects the SDP body to start directly after the Content-Length field. Fix the parser to scan for \r\n\r\n to locate the beginning of the SDP body. Reported-by: Teresa Kang Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_sip.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 1f81abde131f..c05c0dc33499 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -1419,6 +1419,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, const char *dptr, *end; s16 diff, tdiff = 0; int ret = NF_ACCEPT; + bool term; typeof(nf_nat_sip_seq_adjust_hook) nf_nat_sip_seq_adjust; if (ctinfo != IP_CT_ESTABLISHED && @@ -1453,10 +1454,15 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, if (dptr + matchoff == end) break; - if (end + strlen("\r\n\r\n") > dptr + datalen) - break; - if (end[0] != '\r' || end[1] != '\n' || - end[2] != '\r' || end[3] != '\n') + term = false; + for (; end + strlen("\r\n\r\n") <= dptr + datalen; end++) { + if (end[0] == '\r' && end[1] == '\n' && + end[2] == '\r' && end[3] == '\n') { + term = true; + break; + } + } + if (!term) break; end += strlen("\r\n\r\n") + clen; -- cgit v1.2.3-58-ga151 From 1a8218e96271790a07dd7065a2ef173e0f67e328 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 15 May 2011 21:26:31 +0000 Subject: net: ping: dont call udp_ioctl() udp_ioctl() really handles UDP and UDPLite protocols. 1) It can increment UDP_MIB_INERRORS in case first_packet_length() finds a frame with bad checksum. 2) It has a dependency on sizeof(struct udphdr), not applicable to ICMP/PING If ping sockets need to handle SIOCINQ/SIOCOUTQ ioctl, this should be done differently. Signed-off-by: Eric Dumazet CC: Vasiliy Kulikov Acked-by: Vasiliy Kulikov Signed-off-by: David S. Miller --- net/ipv4/ping.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 7041d09ae5d5..41836ab6c200 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -609,23 +608,6 @@ do_confirm: goto out; } -/* - * IOCTL requests applicable to the UDP^H^H^HICMP protocol - */ - -int ping_ioctl(struct sock *sk, int cmd, unsigned long arg) -{ - pr_debug("ping_ioctl(sk=%p,sk->num=%u,cmd=%d,arg=%lu)\n", - inet_sk(sk), inet_sk(sk)->inet_num, cmd, arg); - switch (cmd) { - case SIOCOUTQ: - case SIOCINQ: - return udp_ioctl(sk, cmd, arg); - default: - return -ENOIOCTLCMD; - } -} - int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len, int noblock, int flags, int *addr_len) { @@ -735,7 +717,6 @@ struct proto ping_prot = { .close = ping_close, .connect = ip4_datagram_connect, .disconnect = udp_disconnect, - .ioctl = ping_ioctl, .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, .sendmsg = ping_sendmsg, -- cgit v1.2.3-58-ga151 From 602a5322a7a1b6b005cb50d423939bb7a8782838 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 16 May 2011 17:32:39 +0100 Subject: sfc: Fix TX queue numbering when separate_tx_channels=1 This option appears to have been broken by commit 8313aca38b3937947fffebca6e34bac8e24300c8 ('sfc: Allocate each channel separately, along with its RX and TX queues'). Signed-off-by: Ben Hutchings --- drivers/net/sfc/efx.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 38a55e9e89e4..796c47e03f65 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1319,8 +1319,20 @@ static void efx_remove_interrupts(struct efx_nic *efx) static void efx_set_channels(struct efx_nic *efx) { + struct efx_channel *channel; + struct efx_tx_queue *tx_queue; + efx->tx_channel_offset = separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0; + + /* We need to adjust the TX queue numbers if we have separate + * RX-only and TX-only channels. + */ + efx_for_each_channel(channel, efx) { + efx_for_each_channel_tx_queue(tx_queue, channel) + tx_queue->queue -= (efx->tx_channel_offset * + EFX_TXQ_TYPES); + } } static int efx_probe_nic(struct efx_nic *efx) -- cgit v1.2.3-58-ga151 From c5be24ff62d238a3fdd5d15461b420cd72e78a14 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 13 May 2011 18:01:21 -0400 Subject: ipv4: Trivial rt->rt_src conversions in net/ipv4/route.c At these points we have a fully filled in value via the IP header the form of ip_hdr(skb)->saddr Signed-off-by: David S. Miller --- net/ipv4/route.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index ad141d894e4e..cb93c32027d7 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1435,7 +1435,7 @@ void ip_rt_send_redirect(struct sk_buff *skb) peer->rate_tokens == ip_rt_redirect_number && net_ratelimit()) printk(KERN_WARNING "host %pI4/if%d ignores redirects for %pI4 to %pI4.\n", - &rt->rt_src, rt->rt_iif, + &ip_hdr(skb)->saddr, rt->rt_iif, &rt->rt_dst, &rt->rt_gateway); #endif } @@ -1704,7 +1704,7 @@ void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt) __be32 src; if (rt_is_output_route(rt)) - src = rt->rt_src; + src = ip_hdr(skb)->saddr; else { struct fib_result res; struct flowi4 fl4; -- cgit v1.2.3-58-ga151 From 538dd2e3976a7c572ee927d6bbebe01bf4d6f128 Mon Sep 17 00:00:00 2001 From: Mahesh Bandewar Date: Fri, 13 May 2011 15:08:49 +0000 Subject: bnx2x: Allow ethtool to enable/disable loopback. This patch updates the bnx2x_set_features() to handle loopback mode. When enabled; it sets internal-MAC loopback. Signed-off-by: Mahesh Bandewar Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_cmn.c | 16 ++++++++++++++++ drivers/net/bnx2x/bnx2x_main.c | 3 +++ 2 files changed, 19 insertions(+) diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 6ee6601b5176..ca2bbc0e5d48 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -2840,15 +2840,31 @@ int bnx2x_set_features(struct net_device *dev, u32 features) { struct bnx2x *bp = netdev_priv(dev); u32 flags = bp->flags; + bool bnx2x_reload = false; if (features & NETIF_F_LRO) flags |= TPA_ENABLE_FLAG; else flags &= ~TPA_ENABLE_FLAG; + if (features & NETIF_F_LOOPBACK) { + if (bp->link_params.loopback_mode != LOOPBACK_BMAC) { + bp->link_params.loopback_mode = LOOPBACK_BMAC; + bnx2x_reload = true; + } + } else { + if (bp->link_params.loopback_mode != LOOPBACK_NONE) { + bp->link_params.loopback_mode = LOOPBACK_NONE; + bnx2x_reload = true; + } + } + if (flags ^ bp->flags) { bp->flags = flags; + bnx2x_reload = true; + } + if (bnx2x_reload) { if (bp->recovery_state == BNX2X_RECOVERY_DONE) return bnx2x_reload_if_running(dev); /* else: bnx2x_nic_load() will be called at end of recovery */ diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 2762edf956e9..f45c0caf3240 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -9273,6 +9273,9 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, if (bp->flags & USING_DAC_FLAG) dev->features |= NETIF_F_HIGHDMA; + /* Add Loopback capability to the device */ + dev->hw_features |= NETIF_F_LOOPBACK; + #ifdef BCM_DCBNL dev->dcbnl_ops = &bnx2x_dcbnl_ops; #endif -- cgit v1.2.3-58-ga151 From 8220ba3e2e671492b777159d8dac721f95f4a0ec Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 12 May 2011 16:50:04 -0700 Subject: iwlegacy: Silence DEBUG_STRICT_USER_COPY_CHECKS=y warning Enabling DEBUG_STRICT_USER_COPY_CHECKS causes the following warning: In file included from arch/x86/include/asm/uaccess.h:573, from include/net/checksum.h:25, from include/linux/skbuff.h:28, from drivers/net/wireless/iwlegacy/iwl-4965-rs.c:28: In function 'copy_from_user', inlined from 'iwl4965_rs_sta_dbgfs_scale_table_write' at drivers/net/wireless/iwlegacy/iwl-4965-rs.c:2616: arch/x86/include/asm/uaccess_64.h:65: warning: call to 'copy_from_user_overflow' declared with attribute warning: copy_from_user() buffer size is not provably correct presumably due to buf_size being signed causing GCC to fail to see that buf_size can't become negative. Cc: Johannes Berg Signed-off-by: Stephen Boyd Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-4965-rs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c index 89509392ef5d..24d149909ba3 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c @@ -2604,7 +2604,7 @@ static ssize_t iwl4965_rs_sta_dbgfs_scale_table_write(struct file *file, struct iwl_lq_sta *lq_sta = file->private_data; struct iwl_priv *priv; char buf[64]; - int buf_size; + size_t buf_size; u32 parsed_rate; struct iwl_station_priv *sta_priv = container_of(lq_sta, struct iwl_station_priv, lq_sta); -- cgit v1.2.3-58-ga151 From 805d7d23ef9806e47b550ad80270c4cea4ffc984 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 12 May 2011 16:50:05 -0700 Subject: iwlwifi: Silence DEBUG_STRICT_USER_COPY_CHECKS=y warning Enabling DEBUG_STRICT_USER_COPY_CHECKS causes the following warning: In file included from arch/x86/include/asm/uaccess.h:573, from include/net/checksum.h:25, from include/linux/skbuff.h:28, from drivers/net/wireless/iwlwifi/iwl-agn-rs.c:28: In function 'copy_from_user', inlined from 'rs_sta_dbgfs_scale_table_write' at drivers/net/wireless/iwlwifi/iwl-agn-rs.c:3099: arch/x86/include/asm/uaccess_64.h:65: warning: call to 'copy_from_user_overflow' declared with attribute warning: copy_from_user() buffer size is not provably correct presumably due to buf_size being signed causing GCC to fail to see that buf_size can't become negative. Signed-off-by: Stephen Boyd Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index dbe6295bbf23..91f26556ac23 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -3086,7 +3086,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, struct iwl_lq_sta *lq_sta = file->private_data; struct iwl_priv *priv; char buf[64]; - int buf_size; + size_t buf_size; u32 parsed_rate; struct iwl_station_priv *sta_priv = container_of(lq_sta, struct iwl_station_priv, lq_sta); -- cgit v1.2.3-58-ga151 From 7527a782e187d1214a5b3dc2897ce441033bb4ef Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 13 May 2011 10:58:57 +0200 Subject: cfg80211: advertise possible interface combinations Add the ability to advertise interface combinations in nl80211. This allows the driver to indicate what the combinations are that it supports. "Combinations" of just a single interface are implicit, as previously. Note that cfg80211 will enforce that the restrictions are met, but not for all drivers yet (once all drivers are updated, we can remove the flag and enforce for all). When no combinations are actually supported, an empty list will be exported so that userspace can know if the kernel exported this info or not (although it isn't clear to me what tools using the info should do if the kernel didn't export it). Since some interface types are purely virtual/software and don't fit the restrictions, those are exposed in a new list of pure SW types, not subject to restrictions. This mainly exists to handle AP-VLAN and monitor interfaces in mac80211. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 122 +++++++++++++++++++++++++++++++++++++++++++++++- include/net/cfg80211.h | 88 ++++++++++++++++++++++++++++++++++ net/mac80211/main.c | 16 +++++-- net/wireless/core.c | 69 +++++++++++++++++++++++++++ net/wireless/core.h | 11 +++++ net/wireless/nl80211.c | 105 +++++++++++++++++++++++++++++++++++------ net/wireless/util.c | 80 +++++++++++++++++++++++++++++++ 7 files changed, 472 insertions(+), 19 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 281a2bb6a6ec..0ea497cb607c 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -76,6 +76,39 @@ * below. */ +/** + * DOC: Virtual interface / concurrency capabilities + * + * Some devices are able to operate with virtual MACs, they can have + * more than one virtual interface. The capability handling for this + * is a bit complex though, as there may be a number of restrictions + * on the types of concurrency that are supported. + * + * To start with, each device supports the interface types listed in + * the %NL80211_ATTR_SUPPORTED_IFTYPES attribute, but by listing the + * types there no concurrency is implied. + * + * Once concurrency is desired, more attributes must be observed: + * To start with, since some interface types are purely managed in + * software, like the AP-VLAN type in mac80211 for example, there's + * an additional list of these, they can be added at any time and + * are only restricted by some semantic restrictions (e.g. AP-VLAN + * cannot be added without a corresponding AP interface). This list + * is exported in the %NL80211_ATTR_SOFTWARE_IFTYPES attribute. + * + * Further, the list of supported combinations is exported. This is + * in the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute. Basically, + * it exports a list of "groups", and at any point in time the + * interfaces that are currently active must fall into any one of + * the advertised groups. Within each group, there are restrictions + * on the number of interfaces of different types that are supported + * and also the number of different channels, along with potentially + * some other restrictions. See &enum nl80211_if_combination_attrs. + * + * All together, these attributes define the concurrency of virtual + * interfaces that a given device supports. + */ + /** * enum nl80211_commands - supported nl80211 commands * @@ -954,6 +987,14 @@ enum nl80211_commands { * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan * cycles, in msecs. * + * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported + * interface combinations. In each nested item, it contains attributes + * defined in &enum nl80211_if_combination_attrs. + * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like + * %NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that + * are managed in software: interfaces of these types aren't subject to + * any restrictions in their number or combinations. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1149,6 +1190,9 @@ enum nl80211_attrs { NL80211_ATTR_SCHED_SCAN_INTERVAL, + NL80211_ATTR_INTERFACE_COMBINATIONS, + NL80211_ATTR_SOFTWARE_IFTYPES, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1201,7 +1245,9 @@ enum nl80211_attrs { * @NL80211_IFTYPE_ADHOC: independent BSS member * @NL80211_IFTYPE_STATION: managed BSS member * @NL80211_IFTYPE_AP: access point - * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points + * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points; VLAN interfaces + * are a bit special in that they must always be tied to a pre-existing + * AP type interface. * @NL80211_IFTYPE_WDS: wireless distribution interface * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames * @NL80211_IFTYPE_MESH_POINT: mesh point @@ -2206,4 +2252,78 @@ enum nl80211_wowlan_triggers { MAX_NL80211_WOWLAN_TRIG = NUM_NL80211_WOWLAN_TRIG - 1 }; +/** + * enum nl80211_iface_limit_attrs - limit attributes + * @NL80211_IFACE_LIMIT_UNSPEC: (reserved) + * @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that + * can be chosen from this set of interface types (u32) + * @NL80211_IFACE_LIMIT_TYPES: nested attribute containing a + * flag attribute for each interface type in this set + * @NUM_NL80211_IFACE_LIMIT: number of attributes + * @MAX_NL80211_IFACE_LIMIT: highest attribute number + */ +enum nl80211_iface_limit_attrs { + NL80211_IFACE_LIMIT_UNSPEC, + NL80211_IFACE_LIMIT_MAX, + NL80211_IFACE_LIMIT_TYPES, + + /* keep last */ + NUM_NL80211_IFACE_LIMIT, + MAX_NL80211_IFACE_LIMIT = NUM_NL80211_IFACE_LIMIT - 1 +}; + +/** + * enum nl80211_if_combination_attrs -- interface combination attributes + * + * @NL80211_IFACE_COMB_UNSPEC: (reserved) + * @NL80211_IFACE_COMB_LIMITS: Nested attributes containing the limits + * for given interface types, see &enum nl80211_iface_limit_attrs. + * @NL80211_IFACE_COMB_MAXNUM: u32 attribute giving the total number of + * interfaces that can be created in this group. This number doesn't + * apply to interfaces purely managed in software, which are listed + * in a separate attribute %NL80211_ATTR_INTERFACES_SOFTWARE. + * @NL80211_IFACE_COMB_STA_AP_BI_MATCH: flag attribute specifying that + * beacon intervals within this group must be all the same even for + * infrastructure and AP/GO combinations, i.e. the GO(s) must adopt + * the infrastructure network's beacon interval. + * @NL80211_IFACE_COMB_NUM_CHANNELS: u32 attribute specifying how many + * different channels may be used within this group. + * @NUM_NL80211_IFACE_COMB: number of attributes + * @MAX_NL80211_IFACE_COMB: highest attribute number + * + * Examples: + * limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2 + * => allows an AP and a STA that must match BIs + * + * numbers = [ #{AP, P2P-GO} <= 8 ], channels = 1, max = 8 + * => allows 8 of AP/GO + * + * numbers = [ #{STA} <= 2 ], channels = 2, max = 2 + * => allows two STAs on different channels + * + * numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4 + * => allows a STA plus three P2P interfaces + * + * The list of these four possiblities could completely be contained + * within the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute to indicate + * that any of these groups must match. + * + * "Combinations" of just a single interface will not be listed here, + * a single interface of any valid interface type is assumed to always + * be possible by itself. This means that implicitly, for each valid + * interface type, the following group always exists: + * numbers = [ #{} <= 1 ], channels = 1, max = 1 + */ +enum nl80211_if_combination_attrs { + NL80211_IFACE_COMB_UNSPEC, + NL80211_IFACE_COMB_LIMITS, + NL80211_IFACE_COMB_MAXNUM, + NL80211_IFACE_COMB_STA_AP_BI_MATCH, + NL80211_IFACE_COMB_NUM_CHANNELS, + + /* keep last */ + NUM_NL80211_IFACE_COMB, + MAX_NL80211_IFACE_COMB = NUM_NL80211_IFACE_COMB - 1 +}; + #endif /* __LINUX_NL80211_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index e1f1b41f7b13..04afcfb9eaf4 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1547,6 +1547,10 @@ struct cfg80211_ops { * hints read the documenation for regulatory_hint_found_beacon() * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this * wiphy at all + * @WIPHY_FLAG_ENFORCE_COMBINATIONS: Set this flag to enforce interface + * combinations for this device. This flag is used for backward + * compatibility only until all drivers advertise combinations and + * they will always be enforced. * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled * by default -- this flag will be set depending on the kernel's default * on wiphy_new(), but can be changed by the driver if it has a good @@ -1574,6 +1578,81 @@ enum wiphy_flags { WIPHY_FLAG_IBSS_RSN = BIT(8), WIPHY_FLAG_MESH_AUTH = BIT(10), WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11), + WIPHY_FLAG_ENFORCE_COMBINATIONS = BIT(12), +}; + +/** + * struct ieee80211_iface_limit - limit on certain interface types + * @max: maximum number of interfaces of these types + * @types: interface types (bits) + */ +struct ieee80211_iface_limit { + u16 max; + u16 types; +}; + +/** + * struct ieee80211_iface_combination - possible interface combination + * @limits: limits for the given interface types + * @n_limits: number of limitations + * @num_different_channels: can use up to this many different channels + * @max_interfaces: maximum number of interfaces in total allowed in this + * group + * @beacon_int_infra_match: In this combination, the beacon intervals + * between infrastructure and AP types must match. This is required + * only in special cases. + * + * These examples can be expressed as follows: + * + * Allow #STA <= 1, #AP <= 1, matching BI, channels = 1, 2 total: + * + * struct ieee80211_iface_limit limits1[] = { + * { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), }, + * { .max = 1, .types = BIT(NL80211_IFTYPE_AP}, }, + * }; + * struct ieee80211_iface_combination combination1 = { + * .limits = limits1, + * .n_limits = ARRAY_SIZE(limits1), + * .max_interfaces = 2, + * .beacon_int_infra_match = true, + * }; + * + * + * Allow #{AP, P2P-GO} <= 8, channels = 1, 8 total: + * + * struct ieee80211_iface_limit limits2[] = { + * { .max = 8, .types = BIT(NL80211_IFTYPE_AP) | + * BIT(NL80211_IFTYPE_P2P_GO), }, + * }; + * struct ieee80211_iface_combination combination2 = { + * .limits = limits2, + * .n_limits = ARRAY_SIZE(limits2), + * .max_interfaces = 8, + * .num_different_channels = 1, + * }; + * + * + * Allow #STA <= 1, #{P2P-client,P2P-GO} <= 3 on two channels, 4 total. + * This allows for an infrastructure connection and three P2P connections. + * + * struct ieee80211_iface_limit limits3[] = { + * { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), }, + * { .max = 3, .types = BIT(NL80211_IFTYPE_P2P_GO) | + * BIT(NL80211_IFTYPE_P2P_CLIENT), }, + * }; + * struct ieee80211_iface_combination combination3 = { + * .limits = limits3, + * .n_limits = ARRAY_SIZE(limits3), + * .max_interfaces = 4, + * .num_different_channels = 2, + * }; + */ +struct ieee80211_iface_combination { + const struct ieee80211_iface_limit *limits; + u32 num_different_channels; + u16 max_interfaces; + u8 n_limits; + bool beacon_int_infra_match; }; struct mac_address { @@ -1653,6 +1732,11 @@ struct wiphy_wowlan_support { * @priv: driver private data (sized according to wiphy_new() parameter) * @interface_modes: bitmask of interfaces types valid for this wiphy, * must be set by driver + * @iface_combinations: Valid interface combinations array, should not + * list single interface types. + * @n_iface_combinations: number of entries in @iface_combinations array. + * @software_iftypes: bitmask of software interface types, these are not + * subject to any restrictions since they are purely managed in SW. * @flags: wiphy flags, see &enum wiphy_flags * @bss_priv_size: each BSS struct has private data allocated with it, * this variable determines its size @@ -1697,6 +1781,10 @@ struct wiphy { const struct ieee80211_txrx_stypes *mgmt_stypes; + const struct ieee80211_iface_combination *iface_combinations; + int n_iface_combinations; + u16 software_iftypes; + u16 n_addresses; /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 7f89011fa22d..79a2281678bf 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -685,7 +685,7 @@ EXPORT_SYMBOL(ieee80211_alloc_hw); int ieee80211_register_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); - int result; + int result, i; enum ieee80211_band band; int channels, max_bitrates; bool supp_ht; @@ -743,11 +743,19 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) return -ENOMEM; /* if low-level driver supports AP, we also support VLAN */ - if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) - local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); + if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); + hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN); + } /* mac80211 always supports monitor */ - local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); + hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); + + /* mac80211 doesn't support more than 1 channel */ + for (i = 0; i < hw->wiphy->n_iface_combinations; i++) + if (hw->wiphy->iface_combinations[i].num_different_channels > 1) + return -EINVAL; #ifndef CONFIG_MAC80211_MESH /* mesh depends on Kconfig, but drivers should set it if they want */ diff --git a/net/wireless/core.c b/net/wireless/core.c index 18b002f16860..c22ef3492ee6 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -416,6 +416,67 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) } EXPORT_SYMBOL(wiphy_new); +static int wiphy_verify_combinations(struct wiphy *wiphy) +{ + const struct ieee80211_iface_combination *c; + int i, j; + + /* If we have combinations enforce them */ + if (wiphy->n_iface_combinations) + wiphy->flags |= WIPHY_FLAG_ENFORCE_COMBINATIONS; + + for (i = 0; i < wiphy->n_iface_combinations; i++) { + u32 cnt = 0; + u16 all_iftypes = 0; + + c = &wiphy->iface_combinations[i]; + + /* Combinations with just one interface aren't real */ + if (WARN_ON(c->max_interfaces < 2)) + return -EINVAL; + + /* Need at least one channel */ + if (WARN_ON(!c->num_different_channels)) + return -EINVAL; + + if (WARN_ON(!c->n_limits)) + return -EINVAL; + + for (j = 0; j < c->n_limits; j++) { + u16 types = c->limits[j].types; + + /* + * interface types shouldn't overlap, this is + * used in cfg80211_can_change_interface() + */ + if (WARN_ON(types & all_iftypes)) + return -EINVAL; + all_iftypes |= types; + + if (WARN_ON(!c->limits[j].max)) + return -EINVAL; + + /* Shouldn't list software iftypes in combinations! */ + if (WARN_ON(wiphy->software_iftypes & types)) + return -EINVAL; + + cnt += c->limits[j].max; + /* + * Don't advertise an unsupported type + * in a combination. + */ + if (WARN_ON((wiphy->interface_modes & types) != types)) + return -EINVAL; + } + + /* You can't even choose that many! */ + if (WARN_ON(cnt < c->max_interfaces)) + return -EINVAL; + } + + return 0; +} + int wiphy_register(struct wiphy *wiphy) { struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); @@ -444,6 +505,10 @@ int wiphy_register(struct wiphy *wiphy) if (WARN_ON(ifmodes != wiphy->interface_modes)) wiphy->interface_modes = ifmodes; + res = wiphy_verify_combinations(wiphy); + if (res) + return res; + /* sanity check supported bands/channels */ for (band = 0; band < IEEE80211_NUM_BANDS; band++) { sband = wiphy->bands[band]; @@ -698,6 +763,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, struct net_device *dev = ndev; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev; + int ret; if (!wdev) return NOTIFY_DONE; @@ -893,6 +959,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, return notifier_from_errno(-EOPNOTSUPP); if (rfkill_blocked(rdev->rfkill)) return notifier_from_errno(-ERFKILL); + ret = cfg80211_can_add_interface(rdev, wdev->iftype); + if (ret) + return notifier_from_errno(ret); break; } diff --git a/net/wireless/core.h b/net/wireless/core.h index d4b8f4c0bbbb..bf0fb40e3c8b 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -422,6 +422,17 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, u32 *flags, struct vif_params *params); void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); +int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, + enum nl80211_iftype iftype); + +static inline int +cfg80211_can_add_interface(struct cfg80211_registered_device *rdev, + enum nl80211_iftype iftype) +{ + return cfg80211_can_change_interface(rdev, NULL, iftype); +} + struct ieee80211_channel * rdev_freq_to_chan(struct cfg80211_registered_device *rdev, int freq, enum nl80211_channel_type channel_type); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 9ef8e287d61b..beac296b1fde 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -564,6 +564,88 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) return 0; } +static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes) +{ + struct nlattr *nl_modes = nla_nest_start(msg, attr); + int i; + + if (!nl_modes) + goto nla_put_failure; + + i = 0; + while (ifmodes) { + if (ifmodes & 1) + NLA_PUT_FLAG(msg, i); + ifmodes >>= 1; + i++; + } + + nla_nest_end(msg, nl_modes); + return 0; + +nla_put_failure: + return -ENOBUFS; +} + +static int nl80211_put_iface_combinations(struct wiphy *wiphy, + struct sk_buff *msg) +{ + struct nlattr *nl_combis; + int i, j; + + nl_combis = nla_nest_start(msg, + NL80211_ATTR_INTERFACE_COMBINATIONS); + if (!nl_combis) + goto nla_put_failure; + + for (i = 0; i < wiphy->n_iface_combinations; i++) { + const struct ieee80211_iface_combination *c; + struct nlattr *nl_combi, *nl_limits; + + c = &wiphy->iface_combinations[i]; + + nl_combi = nla_nest_start(msg, i + 1); + if (!nl_combi) + goto nla_put_failure; + + nl_limits = nla_nest_start(msg, NL80211_IFACE_COMB_LIMITS); + if (!nl_limits) + goto nla_put_failure; + + for (j = 0; j < c->n_limits; j++) { + struct nlattr *nl_limit; + + nl_limit = nla_nest_start(msg, j + 1); + if (!nl_limit) + goto nla_put_failure; + NLA_PUT_U32(msg, NL80211_IFACE_LIMIT_MAX, + c->limits[j].max); + if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES, + c->limits[j].types)) + goto nla_put_failure; + nla_nest_end(msg, nl_limit); + } + + nla_nest_end(msg, nl_limits); + + if (c->beacon_int_infra_match) + NLA_PUT_FLAG(msg, + NL80211_IFACE_COMB_STA_AP_BI_MATCH); + NLA_PUT_U32(msg, NL80211_IFACE_COMB_NUM_CHANNELS, + c->num_different_channels); + NLA_PUT_U32(msg, NL80211_IFACE_COMB_MAXNUM, + c->max_interfaces); + + nla_nest_end(msg, nl_combi); + } + + nla_nest_end(msg, nl_combis); + + return 0; +nla_put_failure: + return -ENOBUFS; +} + static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, struct cfg80211_registered_device *dev) { @@ -571,13 +653,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, struct nlattr *nl_bands, *nl_band; struct nlattr *nl_freqs, *nl_freq; struct nlattr *nl_rates, *nl_rate; - struct nlattr *nl_modes; struct nlattr *nl_cmds; enum ieee80211_band band; struct ieee80211_channel *chan; struct ieee80211_rate *rate; int i; - u16 ifmodes = dev->wiphy.interface_modes; const struct ieee80211_txrx_stypes *mgmt_stypes = dev->wiphy.mgmt_stypes; @@ -637,20 +717,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, } } - nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); - if (!nl_modes) + if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, + dev->wiphy.interface_modes)) goto nla_put_failure; - i = 0; - while (ifmodes) { - if (ifmodes & 1) - NLA_PUT_FLAG(msg, i); - ifmodes >>= 1; - i++; - } - - nla_nest_end(msg, nl_modes); - nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); if (!nl_bands) goto nla_put_failure; @@ -865,6 +935,13 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, nla_nest_end(msg, nl_wowlan); } + if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, + dev->wiphy.software_iftypes)) + goto nla_put_failure; + + if (nl80211_put_iface_combinations(&dev->wiphy, msg)) + goto nla_put_failure; + return genlmsg_end(msg, hdr); nla_put_failure: diff --git a/net/wireless/util.c b/net/wireless/util.c index 414c9f604df6..95e4e254da0a 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -803,6 +803,11 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, return -EBUSY; if (ntype != otype) { + err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, + ntype); + if (err) + return err; + dev->ieee80211_ptr->use_4addr = false; dev->ieee80211_ptr->mesh_id_up_len = 0; @@ -921,3 +926,78 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, return res; } + +int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, + enum nl80211_iftype iftype) +{ + struct wireless_dev *wdev_iter; + int num[NUM_NL80211_IFTYPES]; + int total = 1; + int i, j; + + ASSERT_RTNL(); + + /* Always allow software iftypes */ + if (rdev->wiphy.software_iftypes & BIT(iftype)) + return 0; + + /* + * Drivers will gradually all set this flag, until all + * have it we only enforce for those that set it. + */ + if (!(rdev->wiphy.flags & WIPHY_FLAG_ENFORCE_COMBINATIONS)) + return 0; + + memset(num, 0, sizeof(num)); + + num[iftype] = 1; + + mutex_lock(&rdev->devlist_mtx); + list_for_each_entry(wdev_iter, &rdev->netdev_list, list) { + if (wdev_iter == wdev) + continue; + if (!netif_running(wdev_iter->netdev)) + continue; + + if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype)) + continue; + + num[wdev_iter->iftype]++; + total++; + } + mutex_unlock(&rdev->devlist_mtx); + + for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { + const struct ieee80211_iface_combination *c; + struct ieee80211_iface_limit *limits; + + c = &rdev->wiphy.iface_combinations[i]; + + limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits, + GFP_KERNEL); + if (!limits) + return -ENOMEM; + if (total > c->max_interfaces) + goto cont; + + for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { + if (rdev->wiphy.software_iftypes & BIT(iftype)) + continue; + for (j = 0; j < c->n_limits; j++) { + if (!(limits[j].types & iftype)) + continue; + if (limits[j].max < num[iftype]) + goto cont; + limits[j].max -= num[iftype]; + } + } + /* yay, it fits */ + kfree(limits); + return 0; + cont: + kfree(limits); + } + + return -EBUSY; +} -- cgit v1.2.3-58-ga151 From ec034b208dc8aa5dc73ec46c3f27e34c5efbf113 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 13 May 2011 13:35:40 +0200 Subject: mac80211: fix TX a-MPDU locking During my quest to make mac80211 not have any RCU warnings from sparse, I came across the a-MPDU code again and it wasn't quite clear why it isn't racy. So instead of assigning the tid_tx array with just the spinlock held in ieee80211_start_tx_ba_session use a separate temporary array protected only by the spinlock and protect all assignments to the "live" array by both the spinlock and the mutex so that other code is easily verified to be correct. Due to pointer assignment atomicity I don't think this is a real issue, but I'm not sure, especially on Alpha the current code might be problematic. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-tx.c | 23 +++++++++++++++++------ net/mac80211/ht.c | 27 +++++++++++++++++++++------ net/mac80211/sta_info.h | 4 ++++ 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 63d852cb4ca2..f614ee602089 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -136,6 +136,14 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 ieee80211_tx_skb(sdata, skb); } +void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, + struct tid_ampdu_tx *tid_tx) +{ + lockdep_assert_held(&sta->ampdu_mlme.mtx); + lockdep_assert_held(&sta->lock); + rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx); +} + static void kfree_tid_tx(struct rcu_head *rcu_head) { struct tid_ampdu_tx *tid_tx = @@ -161,7 +169,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { /* not even started yet! */ - rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); + ieee80211_assign_tid_tx(sta, tid, NULL); spin_unlock_bh(&sta->lock); call_rcu(&tid_tx->rcu_head, kfree_tid_tx); return 0; @@ -318,7 +326,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) " tid %d\n", tid); #endif spin_lock_bh(&sta->lock); - rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); + ieee80211_assign_tid_tx(sta, tid, NULL); spin_unlock_bh(&sta->lock); ieee80211_wake_queue_agg(local, tid); @@ -398,7 +406,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, tid_tx = sta->ampdu_mlme.tid_tx[tid]; /* check if the TID is not in aggregation flow already */ - if (tid_tx) { + if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "BA request denied - session is not " "idle on tid %u\n", tid); @@ -433,8 +441,11 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, sta->ampdu_mlme.dialog_token_allocator++; tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator; - /* finally, assign it to the array */ - rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx); + /* + * Finally, assign it to the start array; the work item will + * collect it and move it to the normal array. + */ + sta->ampdu_mlme.tid_start_tx[tid] = tid_tx; ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); @@ -697,7 +708,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) ieee80211_agg_splice_packets(local, tid_tx, tid); /* future packets must not find the tid_tx struct any more */ - rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); + ieee80211_assign_tid_tx(sta, tid, NULL); ieee80211_agg_splice_finish(local, tid); diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index b9e4b9bd2179..9f5842a43111 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -140,14 +140,29 @@ void ieee80211_ba_session_work(struct work_struct *work) sta, tid, WLAN_BACK_RECIPIENT, WLAN_REASON_QSTA_TIMEOUT, true); - tid_tx = sta->ampdu_mlme.tid_tx[tid]; - if (!tid_tx) - continue; + tid_tx = sta->ampdu_mlme.tid_start_tx[tid]; + if (tid_tx) { + /* + * Assign it over to the normal tid_tx array + * where it "goes live". + */ + spin_lock_bh(&sta->lock); + + sta->ampdu_mlme.tid_start_tx[tid] = NULL; + /* could there be a race? */ + if (sta->ampdu_mlme.tid_tx[tid]) + kfree(tid_tx); + else + ieee80211_assign_tid_tx(sta, tid, tid_tx); + spin_unlock_bh(&sta->lock); - if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) ieee80211_tx_ba_session_handle_start(sta, tid); - else if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, - &tid_tx->state)) + continue; + } + + tid_tx = sta->ampdu_mlme.tid_tx[tid]; + if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP, + &tid_tx->state)) ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, true); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index f00b4dcb49d7..55c51855ceb7 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -152,6 +152,7 @@ struct tid_ampdu_rx { * * @tid_rx: aggregation info for Rx per TID -- RCU protected * @tid_tx: aggregation info for Tx per TID + * @tid_start_tx: sessions where start was requested * @addba_req_num: number of times addBA request has been sent. * @dialog_token_allocator: dialog token enumerator for each new session; * @work: work struct for starting/stopping aggregation @@ -168,6 +169,7 @@ struct sta_ampdu_mlme { /* tx */ struct work_struct work; struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; + struct tid_ampdu_tx *tid_start_tx[STA_TID_NUM]; u8 addba_req_num[STA_TID_NUM]; u8 dialog_token_allocator; }; @@ -398,6 +400,8 @@ static inline u32 get_sta_flags(struct sta_info *sta) return ret; } +void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, + struct tid_ampdu_tx *tid_tx); #define STA_HASH_SIZE 256 -- cgit v1.2.3-58-ga151 From 40b275b69ee660274b77fb612b0db31fd282fc3f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 13 May 2011 14:15:49 +0200 Subject: mac80211: sparse RCU annotations This adds sparse RCU annotations to most of mac80211, only the mesh code remains to be done. Due the the previous patches, the annotations are pretty simple. The only thing that this actually changes is removing the RCU usage of key->sta in debugfs since this pointer isn't actually an RCU-managed pointer (it only has a single assignment done before the key even goes live). As that is otherwise harmless, I decided to make it part of this patch. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-rx.c | 3 ++- net/mac80211/agg-tx.c | 36 +++++++++++++++++++++--------------- net/mac80211/cfg.c | 17 +++++++---------- net/mac80211/debugfs_key.c | 21 +++++++++------------ net/mac80211/ht.c | 2 +- net/mac80211/ibss.c | 11 ++++++++--- net/mac80211/ieee80211_i.h | 16 +++++++++------- net/mac80211/iface.c | 3 ++- net/mac80211/key.c | 22 ++++++++++++++-------- net/mac80211/key.h | 3 +++ net/mac80211/main.c | 2 ++ net/mac80211/mesh.h | 2 +- net/mac80211/mesh_hwmp.c | 20 +++++++++++++++++--- net/mac80211/sta_info.c | 15 +++++++++------ net/mac80211/sta_info.h | 17 ++++++++++++----- net/mac80211/tx.c | 2 +- 16 files changed, 118 insertions(+), 74 deletions(-) diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 0c9d0c07eae6..9c0d76cdca92 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -63,7 +63,8 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, lockdep_assert_held(&sta->ampdu_mlme.mtx); - tid_rx = sta->ampdu_mlme.tid_rx[tid]; + tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid], + lockdep_is_held(&sta->ampdu_mlme.mtx)); if (!tid_rx) return; diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index f614ee602089..cd5125f77cc5 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -157,16 +157,19 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, bool tx) { struct ieee80211_local *local = sta->local; - struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; + struct tid_ampdu_tx *tid_tx; int ret; lockdep_assert_held(&sta->ampdu_mlme.mtx); - if (!tid_tx) - return -ENOENT; - spin_lock_bh(&sta->lock); + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); + if (!tid_tx) { + spin_unlock_bh(&sta->lock); + return -ENOENT; + } + if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { /* not even started yet! */ ieee80211_assign_tid_tx(sta, tid, NULL); @@ -291,13 +294,13 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) { - struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; + struct tid_ampdu_tx *tid_tx; struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; u16 start_seq_num; int ret; - lockdep_assert_held(&sta->ampdu_mlme.mtx); + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); /* * While we're asking the driver about the aggregation, @@ -404,7 +407,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, goto err_unlock_sta; } - tid_tx = sta->ampdu_mlme.tid_tx[tid]; + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); /* check if the TID is not in aggregation flow already */ if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { #ifdef CONFIG_MAC80211_HT_DEBUG @@ -491,16 +494,19 @@ ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) static void ieee80211_agg_tx_operational(struct ieee80211_local *local, struct sta_info *sta, u16 tid) { + struct tid_ampdu_tx *tid_tx; + lockdep_assert_held(&sta->ampdu_mlme.mtx); + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); + #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); #endif drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_TX_OPERATIONAL, - &sta->sta, tid, NULL, - sta->ampdu_mlme.tid_tx[tid]->buf_size); + &sta->sta, tid, NULL, tid_tx->buf_size); /* * synchronize with TX path, while splicing the TX path @@ -508,13 +514,13 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, */ spin_lock_bh(&sta->lock); - ieee80211_agg_splice_packets(local, sta->ampdu_mlme.tid_tx[tid], tid); + ieee80211_agg_splice_packets(local, tid_tx, tid); /* * Now mark as operational. This will be visible * in the TX path, and lets it go lock-free in * the common case. */ - set_bit(HT_AGG_STATE_OPERATIONAL, &sta->ampdu_mlme.tid_tx[tid]->state); + set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); ieee80211_agg_splice_finish(local, tid); spin_unlock_bh(&sta->lock); @@ -548,7 +554,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) } mutex_lock(&sta->ampdu_mlme.mtx); - tid_tx = sta->ampdu_mlme.tid_tx[tid]; + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); if (WARN_ON(!tid_tx)) { #ifdef CONFIG_MAC80211_HT_DEBUG @@ -626,7 +632,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) return -EINVAL; spin_lock_bh(&sta->lock); - tid_tx = sta->ampdu_mlme.tid_tx[tid]; + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); if (!tid_tx) { ret = -ENOENT; @@ -682,7 +688,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) mutex_lock(&sta->ampdu_mlme.mtx); spin_lock_bh(&sta->lock); - tid_tx = sta->ampdu_mlme.tid_tx[tid]; + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { #ifdef CONFIG_MAC80211_HT_DEBUG @@ -763,7 +769,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, mutex_lock(&sta->ampdu_mlme.mtx); - tid_tx = sta->ampdu_mlme.tid_tx[tid]; + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); if (!tid_tx) goto out; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 2d1c1a5f3c51..6ecd5862735d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -177,11 +177,11 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, goto out_unlock; if (pairwise) - key = sta->ptk; + key = key_mtx_dereference(local, sta->ptk); else - key = sta->gtk[key_idx]; + key = key_mtx_dereference(local, sta->gtk[key_idx]); } else - key = sdata->keys[key_idx]; + key = key_mtx_dereference(local, sdata->keys[key_idx]); if (!key) { ret = -ENOENT; @@ -463,7 +463,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, int size; int err = -EINVAL; - old = sdata->u.ap.beacon; + old = rtnl_dereference(sdata->u.ap.beacon); /* head must not be zero-length */ if (params->head && !params->head_len) @@ -558,8 +558,7 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - old = sdata->u.ap.beacon; - + old = rtnl_dereference(sdata->u.ap.beacon); if (old) return -EALREADY; @@ -574,8 +573,7 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - old = sdata->u.ap.beacon; - + old = rtnl_dereference(sdata->u.ap.beacon); if (!old) return -ENOENT; @@ -589,8 +587,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) sdata = IEEE80211_DEV_TO_SUB_IF(dev); - old = sdata->u.ap.beacon; - + old = rtnl_dereference(sdata->u.ap.beacon); if (!old) return -ENOENT; diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index f7ef3477c24a..33c58b85c911 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -241,16 +241,12 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) if (!key->debugfs.dir) return; - rcu_read_lock(); - sta = rcu_dereference(key->sta); - if (sta) + sta = key->sta; + if (sta) { sprintf(buf, "../../stations/%pM", sta->sta.addr); - rcu_read_unlock(); - - /* using sta as a boolean is fine outside RCU lock */ - if (sta) key->debugfs.stalink = debugfs_create_symlink("station", key->debugfs.dir, buf); + } DEBUGFS_ADD(keylen); DEBUGFS_ADD(flags); @@ -286,7 +282,8 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) lockdep_assert_held(&sdata->local->key_mtx); if (sdata->default_unicast_key) { - key = sdata->default_unicast_key; + key = key_mtx_dereference(sdata->local, + sdata->default_unicast_key); sprintf(buf, "../keys/%d", key->debugfs.cnt); sdata->debugfs.default_unicast_key = debugfs_create_symlink("default_unicast_key", @@ -297,7 +294,8 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) } if (sdata->default_multicast_key) { - key = sdata->default_multicast_key; + key = key_mtx_dereference(sdata->local, + sdata->default_multicast_key); sprintf(buf, "../keys/%d", key->debugfs.cnt); sdata->debugfs.default_multicast_key = debugfs_create_symlink("default_multicast_key", @@ -316,9 +314,8 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) if (!sdata->debugfs.dir) return; - /* this is running under the key lock */ - - key = sdata->default_mgmt_key; + key = key_mtx_dereference(sdata->local, + sdata->default_mgmt_key); if (key) { sprintf(buf, "../keys/%d", key->debugfs.cnt); sdata->debugfs.default_mgmt_key = diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 9f5842a43111..591add22bcc0 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -160,7 +160,7 @@ void ieee80211_ba_session_work(struct work_struct *work) continue; } - tid_tx = sta->ampdu_mlme.tid_tx[tid]; + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state)) ___ieee80211_stop_tx_ba_session(sta, tid, diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index b81860c94698..421eaa6b0c2b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -662,12 +662,16 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, int tx_last_beacon, len = req->len; struct sk_buff *skb; struct ieee80211_mgmt *resp; + struct sk_buff *presp; u8 *pos, *end; lockdep_assert_held(&ifibss->mtx); + presp = rcu_dereference_protected(ifibss->presp, + lockdep_is_held(&ifibss->mtx)); + if (ifibss->state != IEEE80211_IBSS_MLME_JOINED || - len < 24 + 2 || !ifibss->presp) + len < 24 + 2 || !presp) return; tx_last_beacon = drv_tx_last_beacon(local); @@ -705,7 +709,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, } /* Reply with ProbeResp */ - skb = skb_copy(ifibss->presp, GFP_KERNEL); + skb = skb_copy(presp, GFP_KERNEL); if (!skb) return; @@ -985,7 +989,8 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) /* remove beacon */ kfree(sdata->u.ibss.ie); - skb = sdata->u.ibss.presp; + skb = rcu_dereference_protected(sdata->u.ibss.presp, + lockdep_is_held(&sdata->u.ibss.mtx)); rcu_assign_pointer(sdata->u.ibss.presp, NULL); sdata->vif.bss_conf.ibss_joined = false; ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 82f90ff8bb18..ed755889645d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -214,7 +214,7 @@ struct beacon_data { }; struct ieee80211_if_ap { - struct beacon_data *beacon; + struct beacon_data __rcu *beacon; struct list_head vlans; @@ -237,7 +237,7 @@ struct ieee80211_if_vlan { struct list_head list; /* used for all tx if the VLAN is configured to 4-addr mode */ - struct sta_info *sta; + struct sta_info __rcu *sta; }; struct mesh_stats { @@ -442,7 +442,8 @@ struct ieee80211_if_ibss { unsigned long ibss_join_req; /* probe response/beacon for IBSS */ - struct sk_buff *presp, *skb; + struct sk_buff __rcu *presp; + struct sk_buff *skb; enum { IEEE80211_IBSS_MLME_SEARCH, @@ -567,9 +568,10 @@ struct ieee80211_sub_if_data { struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; unsigned int fragment_next; - struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; - struct ieee80211_key *default_unicast_key, *default_multicast_key; - struct ieee80211_key *default_mgmt_key; + struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; + struct ieee80211_key __rcu *default_unicast_key; + struct ieee80211_key __rcu *default_multicast_key; + struct ieee80211_key __rcu *default_mgmt_key; u16 sequence_number; __be16 control_port_protocol; @@ -805,7 +807,7 @@ struct ieee80211_local { spinlock_t sta_lock; unsigned long num_sta; struct list_head sta_list, sta_pending_list; - struct sta_info *sta_hash[STA_HASH_SIZE]; + struct sta_info __rcu *sta_hash[STA_HASH_SIZE]; struct timer_list sta_cleanup; struct work_struct sta_finish_work; int sta_generation; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 4054399be907..0d00ac93d958 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -449,7 +449,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, /* APs need special treatment */ if (sdata->vif.type == NL80211_IFTYPE_AP) { struct ieee80211_sub_if_data *vlan, *tmpsdata; - struct beacon_data *old_beacon = sdata->u.ap.beacon; + struct beacon_data *old_beacon = + rtnl_dereference(sdata->u.ap.beacon); /* sdata_running will return false, so this will disable */ ieee80211_bss_info_change_notify(sdata, diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 958832dd4f0a..31afd712930d 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -195,7 +195,7 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, assert_key_lock(sdata->local); if (idx >= 0 && idx < NUM_DEFAULT_KEYS) - key = sdata->keys[idx]; + key = key_mtx_dereference(sdata->local, sdata->keys[idx]); if (uni) rcu_assign_pointer(sdata->default_unicast_key, key); @@ -222,7 +222,7 @@ __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx) if (idx >= NUM_DEFAULT_KEYS && idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) - key = sdata->keys[idx]; + key = key_mtx_dereference(sdata->local, sdata->keys[idx]); rcu_assign_pointer(sdata->default_mgmt_key, key); @@ -266,9 +266,15 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, else idx = new->conf.keyidx; - defunikey = old && sdata->default_unicast_key == old; - defmultikey = old && sdata->default_multicast_key == old; - defmgmtkey = old && sdata->default_mgmt_key == old; + defunikey = old && + old == key_mtx_dereference(sdata->local, + sdata->default_unicast_key); + defmultikey = old && + old == key_mtx_dereference(sdata->local, + sdata->default_multicast_key); + defmgmtkey = old && + old == key_mtx_dereference(sdata->local, + sdata->default_mgmt_key); if (defunikey && !new) __ieee80211_set_default_key(sdata, -1, true, false); @@ -451,11 +457,11 @@ int ieee80211_key_link(struct ieee80211_key *key, mutex_lock(&sdata->local->key_mtx); if (sta && pairwise) - old_key = sta->ptk; + old_key = key_mtx_dereference(sdata->local, sta->ptk); else if (sta) - old_key = sta->gtk[idx]; + old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]); else - old_key = sdata->keys[idx]; + old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]); __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); __ieee80211_key_destroy(old_key); diff --git a/net/mac80211/key.h b/net/mac80211/key.h index e5432ef8b203..d801d5351336 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -146,4 +146,7 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); +#define key_mtx_dereference(local, ref) \ + rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx))) + #endif /* IEEE80211_KEY_H */ diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 79a2281678bf..0d7b08db8e56 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -871,8 +871,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) * and we need some headroom for passing the frame to monitor * interfaces, but never both at the same time. */ +#ifndef __CHECKER__ BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM != sizeof(struct ieee80211_tx_status_rtap_hdr)); +#endif local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, sizeof(struct ieee80211_tx_status_rtap_hdr)); diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 5c0c20389a1a..e7c5fddb4804 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -92,7 +92,7 @@ struct mesh_path { u8 dst[ETH_ALEN]; u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ struct ieee80211_sub_if_data *sdata; - struct sta_info *next_hop; + struct sta_info __rcu *next_hop; struct timer_list timer; struct sk_buff_head frame_queue; struct rcu_head rcu; diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 2aec7c4f357b..2b18053070c1 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -560,6 +560,14 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, } +static inline struct sta_info * +next_hop_deref_protected(struct mesh_path *mpath) +{ + return rcu_dereference_protected(mpath->next_hop, + lockdep_is_held(&mpath->state_lock)); +} + + static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *prep_elem, u32 metric) @@ -599,7 +607,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, spin_unlock_bh(&mpath->state_lock); goto fail; } - memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); + memcpy(next_hop, next_hop_deref_protected(mpath)->sta.addr, ETH_ALEN); spin_unlock_bh(&mpath->state_lock); --ttl; flags = PREP_IE_FLAGS(prep_elem); @@ -651,7 +659,8 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, if (mpath) { spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_ACTIVE && - memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 && + memcmp(ta, next_hop_deref_protected(mpath)->sta.addr, + ETH_ALEN) == 0 && (!(mpath->flags & MESH_PATH_SN_VALID) || SN_GT(target_sn, mpath->sn))) { mpath->flags &= ~MESH_PATH_ACTIVE; @@ -913,6 +922,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, { struct sk_buff *skb_to_free = NULL; struct mesh_path *mpath; + struct sta_info *next_hop; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; u8 *target_addr = hdr->addr3; int err = 0; @@ -940,7 +950,11 @@ int mesh_nexthop_lookup(struct sk_buff *skb, mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); } - memcpy(hdr->addr1, mpath->next_hop->sta.addr, ETH_ALEN); + next_hop = rcu_dereference(mpath->next_hop); + if (next_hop) + memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); + else + err = -ENOENT; } else { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (!(mpath->flags & MESH_PATH_RESOLVING)) { diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index cba8309e9ace..82ab6b4643fc 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -67,7 +67,8 @@ static int sta_info_hash_del(struct ieee80211_local *local, { struct sta_info *s; - s = local->sta_hash[STA_HASH(sta->sta.addr)]; + s = rcu_dereference_protected(local->sta_hash[STA_HASH(sta->sta.addr)], + lockdep_is_held(&local->sta_lock)); if (!s) return -ENOENT; if (s == sta) { @@ -76,9 +77,11 @@ static int sta_info_hash_del(struct ieee80211_local *local, return 0; } - while (s->hnext && s->hnext != sta) - s = s->hnext; - if (s->hnext) { + while (rcu_access_pointer(s->hnext) && + rcu_access_pointer(s->hnext) != sta) + s = rcu_dereference_protected(s->hnext, + lockdep_is_held(&local->sta_lock)); + if (rcu_access_pointer(s->hnext)) { rcu_assign_pointer(s->hnext, sta->hnext); return 0; } @@ -654,9 +657,9 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) mutex_lock(&local->key_mtx); for (i = 0; i < NUM_DEFAULT_KEYS; i++) - __ieee80211_key_free(sta->gtk[i]); + __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i])); if (sta->ptk) - __ieee80211_key_free(sta->ptk); + __ieee80211_key_free(key_mtx_dereference(local, sta->ptk)); mutex_unlock(&local->key_mtx); sta->dead = true; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 55c51855ceb7..d6b566076f05 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -164,11 +164,11 @@ struct tid_ampdu_rx { struct sta_ampdu_mlme { struct mutex mtx; /* rx */ - struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; + struct tid_ampdu_rx __rcu *tid_rx[STA_TID_NUM]; unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)]; /* tx */ struct work_struct work; - struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; + struct tid_ampdu_tx __rcu *tid_tx[STA_TID_NUM]; struct tid_ampdu_tx *tid_start_tx[STA_TID_NUM]; u8 addba_req_num[STA_TID_NUM]; u8 dialog_token_allocator; @@ -243,11 +243,11 @@ struct sta_ampdu_mlme { struct sta_info { /* General information, mostly static */ struct list_head list; - struct sta_info *hnext; + struct sta_info __rcu *hnext; struct ieee80211_local *local; struct ieee80211_sub_if_data *sdata; - struct ieee80211_key *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; - struct ieee80211_key *ptk; + struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; + struct ieee80211_key __rcu *ptk; struct rate_control_ref *rate_ctrl; void *rate_ctrl_priv; spinlock_t lock; @@ -403,6 +403,13 @@ static inline u32 get_sta_flags(struct sta_info *sta) void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, struct tid_ampdu_tx *tid_tx); +static inline struct tid_ampdu_tx * +rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid) +{ + return rcu_dereference_protected(sta->ampdu_mlme.tid_tx[tid], + lockdep_is_held(&sta->lock) || + lockdep_is_held(&sta->ampdu_mlme.mtx)); +} #define STA_HASH_SIZE 256 #define STA_HASH(sta) (sta[5]) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c9f12113ca6a..6eeaaa2bbafe 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1147,7 +1147,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, * packet pass through because splicing the frames * back is already done. */ - tid_tx = tx->sta->ampdu_mlme.tid_tx[tid]; + tid_tx = rcu_dereference_protected_tid_tx(tx->sta, tid); if (!tid_tx) { /* do nothing, let packet pass through */ -- cgit v1.2.3-58-ga151 From bd2281b85d929af0bd192f05135f70dd05f4fd85 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 13 May 2011 15:52:10 +0200 Subject: net/rfkill/core.c: Avoid leaving freed data in a list The list_for_each_entry loop can fail, in which case the list element is not removed from the list rfkill_fds. Since this list is not accessed by the loop, the addition of &data->list into the list is just moved after the loop. The sematic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression E,E1,E2; identifier l; @@ *list_add(&E->l,E1); ... when != E1 when != list_del(&E->l) when != list_del_init(&E->l) when != E = E2 *kfree(E);// Signed-off-by: Julia Lawall Signed-off-by: John W. Linville --- net/rfkill/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 0198191b756d..be90640a2774 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -1024,7 +1024,6 @@ static int rfkill_fop_open(struct inode *inode, struct file *file) * start getting events from elsewhere but hold mtx to get * startup events added first */ - list_add(&data->list, &rfkill_fds); list_for_each_entry(rfkill, &rfkill_list, node) { ev = kzalloc(sizeof(*ev), GFP_KERNEL); @@ -1033,6 +1032,7 @@ static int rfkill_fop_open(struct inode *inode, struct file *file) rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD); list_add_tail(&ev->list, &data->events); } + list_add(&data->list, &rfkill_fds); mutex_unlock(&data->mtx); mutex_unlock(&rfkill_global_mutex); -- cgit v1.2.3-58-ga151 From 69de3721750ea4fae504be9e67f140cafe1c7a89 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 13 May 2011 20:29:04 +0530 Subject: ath9k_hw: make antenna diversity modules chip specific this is necessary to support Antenna diversity and combining in new chip sets such as AR9485, previously Antenna diversity support is available only in AR9285 Cc: Gabriel Tseng Cc: Senthilkumar Balasubramanian Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_phy.c | 42 +++++++++++++++-------------- drivers/net/wireless/ath/ath9k/hw-ops.h | 12 +++++++++ drivers/net/wireless/ath/ath9k/hw.h | 9 ++++--- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 7d68d61e406b..b4a0c1d3b115 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -517,23 +517,7 @@ static void ar9002_hw_set_nf_limits(struct ath_hw *ah) } } -void ar9002_hw_attach_phy_ops(struct ath_hw *ah) -{ - struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); - - priv_ops->set_rf_regs = NULL; - priv_ops->rf_alloc_ext_banks = NULL; - priv_ops->rf_free_ext_banks = NULL; - priv_ops->rf_set_freq = ar9002_hw_set_channel; - priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate; - priv_ops->olc_init = ar9002_olc_init; - priv_ops->compute_pll_control = ar9002_hw_compute_pll_control; - priv_ops->do_getnf = ar9002_hw_do_getnf; - - ar9002_hw_set_nf_limits(ah); -} - -void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, +static void ar9002_hw_antdiv_comb_conf_get(struct ath_hw *ah, struct ath_hw_antcomb_conf *antconf) { u32 regval; @@ -546,9 +530,8 @@ void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >> AR_PHY_9285_FAST_DIV_BIAS_S; } -EXPORT_SYMBOL(ath9k_hw_antdiv_comb_conf_get); -void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, +static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah, struct ath_hw_antcomb_conf *antconf) { u32 regval; @@ -566,4 +549,23 @@ void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval); } -EXPORT_SYMBOL(ath9k_hw_antdiv_comb_conf_set); + +void ar9002_hw_attach_phy_ops(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + struct ath_hw_ops *ops = ath9k_hw_ops(ah); + + priv_ops->set_rf_regs = NULL; + priv_ops->rf_alloc_ext_banks = NULL; + priv_ops->rf_free_ext_banks = NULL; + priv_ops->rf_set_freq = ar9002_hw_set_channel; + priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate; + priv_ops->olc_init = ar9002_olc_init; + priv_ops->compute_pll_control = ar9002_hw_compute_pll_control; + priv_ops->do_getnf = ar9002_hw_do_getnf; + + ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get; + ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set; + + ar9002_hw_set_nf_limits(ah); +} diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 99f8334d1dfe..8b8f0445aef8 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -121,6 +121,18 @@ static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val); } +static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, + struct ath_hw_antcomb_conf *antconf) +{ + ath9k_hw_ops(ah)->antdiv_comb_conf_get(ah, antconf); +} + +static inline void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, + struct ath_hw_antcomb_conf *antconf) +{ + ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf); +} + /* Private hardware call ops */ /* PHY ops */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b2248bba25a2..67cca10bf4c9 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -629,6 +629,11 @@ struct ath_hw_ops { void (*set11n_aggr_last)(struct ath_hw *ah, void *ds); void (*clr11n_aggr)(struct ath_hw *ah, void *ds); void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val); + void (*antdiv_comb_conf_get)(struct ath_hw *ah, + struct ath_hw_antcomb_conf *antconf); + void (*antdiv_comb_conf_set)(struct ath_hw *ah, + struct ath_hw_antcomb_conf *antconf); + }; struct ath_nf_limits { @@ -904,10 +909,6 @@ void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); u32 ath9k_hw_getdefantenna(struct ath_hw *ah); void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); -void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, - struct ath_hw_antcomb_conf *antconf); -void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, - struct ath_hw_antcomb_conf *antconf); /* General Operation */ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); -- cgit v1.2.3-58-ga151 From 21d2c63a2866a47030803de3db9b4e8759806095 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 13 May 2011 20:29:31 +0530 Subject: ath9k_hw: enable Antenna diversity for AR9485 read antenna diversity and combining information from the EEPROM. Enable antenna diversity/combining feature only when both LNA diversity and fast diversity are supported Cc: Gabriel Tseng Cc: Senthilkumar Balasubramanian Tested-by: Mohammed Shafi Shajakhan Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 58f3d4210338..b75b5dca4e29 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2022,6 +2022,22 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) } + if (AR_SREV_9485(ah)) { + ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); + /* + * enable the diversity-combining algorithm only when + * both enable_lna_div and enable_fast_div are set + * Table for Diversity + * ant_div_alt_lnaconf bit 0-1 + * ant_div_main_lnaconf bit 2-3 + * ant_div_alt_gaintb bit 4 + * ant_div_main_gaintb bit 5 + * enable_ant_div_lnadiv bit 6 + * enable_ant_fast_div bit 7 + */ + if ((ant_div_ctl1 >> 0x6) == 0x3) + pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; + } if (AR_SREV_9485_10(ah)) { pCap->pcie_lcr_extsync_en = true; -- cgit v1.2.3-58-ga151 From c6ba9feb4fa33f31f26ac1a2b0a337d79426b822 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 13 May 2011 20:29:53 +0530 Subject: ath9k_hw: define registers/macros to support Antenna diversity define few registers and macros to configure/enable Antenna diversity parameters in AR9485 Cc: Gabriel Tseng Cc: Senthilkumar Balasubramanian Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.h | 22 ++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/hw.h | 3 +++ 2 files changed, 25 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 2a0d5cbb7e76..c7505b48e5c0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -261,12 +261,34 @@ #define AR_PHY_EXT_CCA0 (AR_AGC_BASE + 0x20) #define AR_PHY_RESTART (AR_AGC_BASE + 0x24) +/* + * Antenna Diversity settings + */ #define AR_PHY_MC_GAIN_CTRL (AR_AGC_BASE + 0x28) #define AR_ANT_DIV_CTRL_ALL 0x7e000000 #define AR_ANT_DIV_CTRL_ALL_S 25 #define AR_ANT_DIV_ENABLE 0x1000000 #define AR_ANT_DIV_ENABLE_S 24 + +#define AR_PHY_9485_ANT_FAST_DIV_BIAS 0x00007e00 +#define AR_PHY_9485_ANT_FAST_DIV_BIAS_S 9 +#define AR_PHY_9485_ANT_DIV_LNADIV 0x01000000 +#define AR_PHY_9485_ANT_DIV_LNADIV_S 24 +#define AR_PHY_9485_ANT_DIV_ALT_LNACONF 0x06000000 +#define AR_PHY_9485_ANT_DIV_ALT_LNACONF_S 25 +#define AR_PHY_9485_ANT_DIV_MAIN_LNACONF 0x18000000 +#define AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S 27 +#define AR_PHY_9485_ANT_DIV_ALT_GAINTB 0x20000000 +#define AR_PHY_9485_ANT_DIV_ALT_GAINTB_S 29 +#define AR_PHY_9485_ANT_DIV_MAIN_GAINTB 0x40000000 +#define AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S 30 + +#define AR_PHY_9485_ANT_DIV_LNA1_MINUS_LNA2 0x0 +#define AR_PHY_9485_ANT_DIV_LNA2 0x1 +#define AR_PHY_9485_ANT_DIV_LNA1 0x2 +#define AR_PHY_9485_ANT_DIV_LNA1_PLUS_LNA2 0x3 + #define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c) #define AR_PHY_EXT_CHN_WIN (AR_AGC_BASE + 0x30) #define AR_PHY_20_40_DET_THR (AR_AGC_BASE + 0x34) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 67cca10bf4c9..80f512d1f975 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -479,6 +479,9 @@ struct ath_hw_antcomb_conf { u8 main_lna_conf; u8 alt_lna_conf; u8 fast_div_bias; + u8 main_gaintb; + u8 alt_gaintb; + int lna1_lna2_delta; }; /** -- cgit v1.2.3-58-ga151 From 842ca780af06d166c87725b68f4fe359c3da7bc0 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 13 May 2011 20:30:27 +0530 Subject: ath9k_hw: config diversity based on eeprom contents * enable LNA-diversity, fast-diversity for AR9485 based on the value read from EEPROM content * if antenna diversity/combining is supported, set LNA1 for the main antenna and LNA2 for the alternate antenna based on the new diversity algorithm Cc: Gabriel Tseng Cc: Senthilkumar Balasubramanian Cc: Luis Rodriguez Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 50 ++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 6dfb69ae5b09..c7ad0562596a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3498,6 +3498,8 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) { int chain; + u32 regval; + u32 ant_div_ctl1; static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { AR_PHY_SWITCH_CHAIN_0, AR_PHY_SWITCH_CHAIN_1, @@ -3523,13 +3525,49 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) if (AR_SREV_9485(ah)) { value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1); - REG_RMW_FIELD(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_CTRL_ALL, - value); - REG_RMW_FIELD(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE, - value >> 6); - REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE, - value >> 7); + /* + * main_lnaconf, alt_lnaconf, main_tb, alt_tb + * are the fields present + */ + regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); + regval &= (~AR_ANT_DIV_CTRL_ALL); + regval |= (value & 0x3f) << AR_ANT_DIV_CTRL_ALL_S; + /* enable_lnadiv */ + regval &= (~AR_PHY_9485_ANT_DIV_LNADIV); + regval |= ((value >> 6) & 0x1) << + AR_PHY_9485_ANT_DIV_LNADIV_S; + REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); + + /*enable fast_div */ + regval = REG_READ(ah, AR_PHY_CCK_DETECT); + regval &= (~AR_FAST_DIV_ENABLE); + regval |= ((value >> 7) & 0x1) << + AR_FAST_DIV_ENABLE_S; + REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); + ant_div_ctl1 = + ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); + /* check whether antenna diversity is enabled */ + if ((ant_div_ctl1 >> 0x6) == 0x3) { + regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); + /* + * clear bits 25-30 main_lnaconf, alt_lnaconf, + * main_tb, alt_tb + */ + regval &= (~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF | + AR_PHY_9485_ANT_DIV_ALT_LNACONF | + AR_PHY_9485_ANT_DIV_ALT_GAINTB | + AR_PHY_9485_ANT_DIV_MAIN_GAINTB)); + /* by default use LNA1 for the main antenna */ + regval |= (AR_PHY_9485_ANT_DIV_LNA1 << + AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S); + regval |= (AR_PHY_9485_ANT_DIV_LNA2 << + AR_PHY_9485_ANT_DIV_ALT_LNACONF_S); + REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); + } + + } + } static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) -- cgit v1.2.3-58-ga151 From 6bcbc062c23ac769cb775f3d2cf209db9d1a96fe Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 13 May 2011 20:30:41 +0530 Subject: ath9k_hw: define modules to get/set Antenna diversity paramaters these are the two important modules that will be called by the antenna diversity algorithm module in the rx. this will continuosly configure the hardware based on the current diversity status obtained from the algorithm Cc: Gabriel Tseng Cc: Senthilkumar Balasubramanian Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 44 +++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index c83be2dd5718..d2a5d2737cd3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1184,9 +1184,50 @@ static void ar9003_hw_set_radar_conf(struct ath_hw *ah) conf->radar_inband = 8; } +static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah, + struct ath_hw_antcomb_conf *antconf) +{ + u32 regval; + + regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); + antconf->main_lna_conf = (regval & AR_PHY_9485_ANT_DIV_MAIN_LNACONF) >> + AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S; + antconf->alt_lna_conf = (regval & AR_PHY_9485_ANT_DIV_ALT_LNACONF) >> + AR_PHY_9485_ANT_DIV_ALT_LNACONF_S; + antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >> + AR_PHY_9485_ANT_FAST_DIV_BIAS_S; +} + +static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah, + struct ath_hw_antcomb_conf *antconf) +{ + u32 regval; + + regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); + regval &= ~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF | + AR_PHY_9485_ANT_DIV_ALT_LNACONF | + AR_PHY_9485_ANT_FAST_DIV_BIAS | + AR_PHY_9485_ANT_DIV_MAIN_GAINTB | + AR_PHY_9485_ANT_DIV_ALT_GAINTB); + regval |= ((antconf->main_lna_conf << + AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S) + & AR_PHY_9485_ANT_DIV_MAIN_LNACONF); + regval |= ((antconf->alt_lna_conf << AR_PHY_9485_ANT_DIV_ALT_LNACONF_S) + & AR_PHY_9485_ANT_DIV_ALT_LNACONF); + regval |= ((antconf->fast_div_bias << AR_PHY_9485_ANT_FAST_DIV_BIAS_S) + & AR_PHY_9485_ANT_FAST_DIV_BIAS); + regval |= ((antconf->main_gaintb << AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S) + & AR_PHY_9485_ANT_DIV_MAIN_GAINTB); + regval |= ((antconf->alt_gaintb << AR_PHY_9485_ANT_DIV_ALT_GAINTB_S) + & AR_PHY_9485_ANT_DIV_ALT_GAINTB); + + REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); +} + void ar9003_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + struct ath_hw_ops *ops = ath9k_hw_ops(ah); static const u32 ar9300_cca_regs[6] = { AR_PHY_CCA_0, AR_PHY_CCA_1, @@ -1213,6 +1254,9 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; priv_ops->set_radar_params = ar9003_hw_set_radar_params; + ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; + ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; + ar9003_hw_set_nf_limits(ah); ar9003_hw_set_radar_conf(ah); memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs)); -- cgit v1.2.3-58-ga151 From 8afbcc8bfb549a522298fa4a31ee5155c2b5f7a0 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 13 May 2011 20:30:56 +0530 Subject: ath9k_hw: define antenna diversity group AR9285 belongs to diversity group 0 and AR9485 belongs to diversity group 2. Based on the diversity group we configure certain antenna diversity paramaters such as lna1_lna2_delta and fast diversity bias values. For AR9485 we have some gain table parameter which selects the gain table 0/1 for main and alternate antenna Cc: Gabriel Tseng Cc: Senthilkumar Balasubramanian Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_phy.c | 2 ++ drivers/net/wireless/ath/ath9k/ar9003_phy.c | 2 ++ drivers/net/wireless/ath/ath9k/ath9k.h | 1 - drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/recv.c | 2 +- 5 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index b4a0c1d3b115..a57e963cf0dc 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -529,6 +529,8 @@ static void ar9002_hw_antdiv_comb_conf_get(struct ath_hw *ah, AR_PHY_9285_ANT_DIV_ALT_LNACONF_S; antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >> AR_PHY_9285_FAST_DIV_BIAS_S; + antconf->lna1_lna2_delta = -3; + antconf->div_group = 0; } static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index d2a5d2737cd3..25f3c2fdf2bc 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1196,6 +1196,8 @@ static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah, AR_PHY_9485_ANT_DIV_ALT_LNACONF_S; antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >> AR_PHY_9485_ANT_FAST_DIV_BIAS_S; + antconf->lna1_lna2_delta = -9; + antconf->div_group = 2; } static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index f2f672bc5966..03b37d7be1c3 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -483,7 +483,6 @@ static inline void ath_deinit_leds(struct ath_softc *sc) #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30 #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20 -#define ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA -3 #define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1 #define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4 #define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2 diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 80f512d1f975..7af2773d2bfc 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -482,6 +482,7 @@ struct ath_hw_antcomb_conf { u8 main_gaintb; u8 alt_gaintb; int lna1_lna2_delta; + u8 div_group; }; /** diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 9fcd1e4f4504..85e05329a607 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1442,7 +1442,7 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) } if ((alt_rssi_avg < (main_rssi_avg + - ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA))) + div_ant_conf.lna1_lna2_delta))) goto div_comb_done; } -- cgit v1.2.3-58-ga151 From b85c5734f00886ee0f33ef4d0038ed9a278eefce Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 13 May 2011 20:31:09 +0530 Subject: ath9k: Implement an API to swap main/ALT LNA's for the diversity group 2(AR9485) we swap the LNA's of main/ALT antenna based on alternate antenna's rssi average in comparision with main antenna's rssi, while for AR9285(antenna diversity group 0)we still follow the older method of looking at the packet count in alternate antenna Cc: Gabriel Tseng Cc: Senthilkumar Balasubramanian Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 85e05329a607..47e0fc1aaba3 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -28,6 +28,33 @@ static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); } +static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio, + int curr_main_set, int curr_alt_set, + int alt_rssi_avg, int main_rssi_avg) +{ + bool result = false; + switch (div_group) { + case 0: + if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) + result = true; + break; + case 1: + if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) && + (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) && + (alt_rssi_avg >= (main_rssi_avg - 5))) || + ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) && + (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) && + (alt_rssi_avg >= (main_rssi_avg - 2)))) && + (alt_rssi_avg >= 4)) + result = true; + else + result = false; + break; + } + + return result; +} + static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) { return sc->ps_enabled && @@ -1413,7 +1440,9 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) } if (!antcomb->scan) { - if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { + if (ath_ant_div_comb_alt_check(div_ant_conf.div_group, + alt_ratio, curr_main_set, curr_alt_set, + alt_rssi_avg, main_rssi_avg)) { if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { /* Switch main and alt LNA */ div_ant_conf.main_lna_conf = -- cgit v1.2.3-58-ga151 From 3e9a212a9e21266115bad2982016950fb2bf29c2 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 13 May 2011 20:31:23 +0530 Subject: ath9k: configure fast_div_bias based on diversity group configure fast diversity bias based on the antenna diversity group and based on main/alt LNA configurations. also configure main antenna and alternate antenna to gain-table 0 for diversity group 2(AR9485) Cc: Gabriel Tseng Cc: Senthilkumar Balasubramanian Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 174 +++++++++++++++++++++++++--------- 1 file changed, 131 insertions(+), 43 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 47e0fc1aaba3..2fecfcb78106 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1317,49 +1317,138 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, } } -static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf) +static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, + struct ath_ant_comb *antcomb, int alt_ratio) { - /* Adjust the fast_div_bias based on main and alt lna conf */ - switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) { - case (0x01): /* A-B LNA2 */ - ant_conf->fast_div_bias = 0x3b; - break; - case (0x02): /* A-B LNA1 */ - ant_conf->fast_div_bias = 0x3d; - break; - case (0x03): /* A-B A+B */ - ant_conf->fast_div_bias = 0x1; - break; - case (0x10): /* LNA2 A-B */ - ant_conf->fast_div_bias = 0x7; - break; - case (0x12): /* LNA2 LNA1 */ - ant_conf->fast_div_bias = 0x2; - break; - case (0x13): /* LNA2 A+B */ - ant_conf->fast_div_bias = 0x7; - break; - case (0x20): /* LNA1 A-B */ - ant_conf->fast_div_bias = 0x6; - break; - case (0x21): /* LNA1 LNA2 */ - ant_conf->fast_div_bias = 0x0; - break; - case (0x23): /* LNA1 A+B */ - ant_conf->fast_div_bias = 0x6; - break; - case (0x30): /* A+B A-B */ - ant_conf->fast_div_bias = 0x1; - break; - case (0x31): /* A+B LNA2 */ - ant_conf->fast_div_bias = 0x3b; - break; - case (0x32): /* A+B LNA1 */ - ant_conf->fast_div_bias = 0x3d; - break; - default: - break; + if (ant_conf->div_group == 0) { + /* Adjust the fast_div_bias based on main and alt lna conf */ + switch ((ant_conf->main_lna_conf << 4) | + ant_conf->alt_lna_conf) { + case (0x01): /* A-B LNA2 */ + ant_conf->fast_div_bias = 0x3b; + break; + case (0x02): /* A-B LNA1 */ + ant_conf->fast_div_bias = 0x3d; + break; + case (0x03): /* A-B A+B */ + ant_conf->fast_div_bias = 0x1; + break; + case (0x10): /* LNA2 A-B */ + ant_conf->fast_div_bias = 0x7; + break; + case (0x12): /* LNA2 LNA1 */ + ant_conf->fast_div_bias = 0x2; + break; + case (0x13): /* LNA2 A+B */ + ant_conf->fast_div_bias = 0x7; + break; + case (0x20): /* LNA1 A-B */ + ant_conf->fast_div_bias = 0x6; + break; + case (0x21): /* LNA1 LNA2 */ + ant_conf->fast_div_bias = 0x0; + break; + case (0x23): /* LNA1 A+B */ + ant_conf->fast_div_bias = 0x6; + break; + case (0x30): /* A+B A-B */ + ant_conf->fast_div_bias = 0x1; + break; + case (0x31): /* A+B LNA2 */ + ant_conf->fast_div_bias = 0x3b; + break; + case (0x32): /* A+B LNA1 */ + ant_conf->fast_div_bias = 0x3d; + break; + default: + break; + } + } else if (ant_conf->div_group == 2) { + /* Adjust the fast_div_bias based on main and alt_lna_conf */ + switch ((ant_conf->main_lna_conf << 4) | + ant_conf->alt_lna_conf) { + case (0x01): /* A-B LNA2 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case (0x02): /* A-B LNA1 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case (0x03): /* A-B A+B */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case (0x10): /* LNA2 A-B */ + if (!(antcomb->scan) && + (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) + ant_conf->fast_div_bias = 0x1; + else + ant_conf->fast_div_bias = 0x2; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case (0x12): /* LNA2 LNA1 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case (0x13): /* LNA2 A+B */ + if (!(antcomb->scan) && + (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) + ant_conf->fast_div_bias = 0x1; + else + ant_conf->fast_div_bias = 0x2; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case (0x20): /* LNA1 A-B */ + if (!(antcomb->scan) && + (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) + ant_conf->fast_div_bias = 0x1; + else + ant_conf->fast_div_bias = 0x2; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case (0x21): /* LNA1 LNA2 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case (0x23): /* LNA1 A+B */ + if (!(antcomb->scan) && + (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) + ant_conf->fast_div_bias = 0x1; + else + ant_conf->fast_div_bias = 0x2; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case (0x30): /* A+B A-B */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case (0x31): /* A+B LNA2 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case (0x32): /* A+B LNA1 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + default: + break; + } + } + } /* Antenna diversity and combining */ @@ -1585,8 +1674,7 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) antcomb->quick_scan_cnt++; div_comb_done: - ath_ant_div_conf_fast_divbias(&div_ant_conf); - + ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio); ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); antcomb->scan_start_time = jiffies; -- cgit v1.2.3-58-ga151 From 21e8ee6d207f6d384689571101436eb9070c22ca Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 13 May 2011 20:31:40 +0530 Subject: ath9k: make sure main_rssi is positive some times the rssi control descriptor for the main antenna may be negative like that of alternate antenna, hence before incrementing packet counts/rssi of main/alternate antenna make sure both main_rssi and alt_rssi are positive only. this avoids wrong selection of antenna due to diversity Cc: Gabriel Tseng Cc: Senthilkumar Balasubramanian Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 2fecfcb78106..4f52e0429f99 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1468,8 +1468,8 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & ATH_ANT_RX_MASK; - /* Record packet only when alt_rssi is positive */ - if (alt_rssi > 0) { + /* Record packet only when both main_rssi and alt_rssi is positive */ + if (main_rssi > 0 && alt_rssi > 0) { antcomb->total_pkt_count++; antcomb->main_total_rssi += main_rssi; antcomb->alt_total_rssi += alt_rssi; -- cgit v1.2.3-58-ga151 From 108697c44b8e50bea3505c6bf9667da4627cb2d5 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 13 May 2011 20:59:42 +0530 Subject: ath9k: make npending frames check as bool we are not doing anything by tracking the number of pending frames. bail out when we first find a pending frame in any one of the 10 queues. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 33816091b439..45303bdbc465 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2276,7 +2276,7 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) timeout = 1; for (j = 0; j < timeout; j++) { - int npend = 0; + bool npend = false; if (j) usleep_range(1000, 2000); @@ -2285,7 +2285,10 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) if (!ATH_TXQ_SETUP(sc, i)) continue; - npend += ath9k_has_pending_frames(sc, &sc->tx.txq[i]); + npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); + + if (npend) + break; } if (!npend) -- cgit v1.2.3-58-ga151 From 57cf8043a64b56a10b9f194572548a3dfb62e596 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Fri, 13 May 2011 10:45:43 -0700 Subject: nl80211: Move peer link state definition to nl80211 These definitions need to be exposed now that we can set the peer link states via NL80211_ATTR_STA_PLINK_STATE. They were already being (opaquely) reported by NL80211_STA_INFO_PLINK_STATE. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- include/linux/nl80211.h | 41 +++++++++++++++++++++++++-- include/net/cfg80211.h | 27 ------------------ net/mac80211/cfg.c | 6 ++-- net/mac80211/mesh_plink.c | 72 +++++++++++++++++++++++------------------------ net/mac80211/rx.c | 2 +- net/mac80211/sta_info.c | 2 +- net/mac80211/sta_info.h | 6 ++-- net/wireless/nl80211.c | 2 +- 8 files changed, 83 insertions(+), 75 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 0ea497cb607c..fc3a94821b1e 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -973,9 +973,10 @@ enum nl80211_commands { * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver * allows auth frames in a mesh to be passed to userspace for processing via * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. - * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link. Used when - * userspace is driving the peer link management state machine. - * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled. + * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as + * defined in &enum nl80211_plink_state. Used when userspace is + * driving the peer link management state machine. + * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled. * * @NL80211_ATTR_WOWLAN_SUPPORTED: indicates, as part of the wiphy capabilities, * the supported WoWLAN triggers @@ -1396,6 +1397,7 @@ enum nl80211_sta_bss_param { * @NL80211_STA_INFO_LLID: the station's mesh LLID * @NL80211_STA_INFO_PLID: the station's mesh PLID * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station + * (see %enum nl80211_plink_state) * @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested * attribute, like NL80211_STA_INFO_TX_BITRATE. * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute @@ -2326,4 +2328,37 @@ enum nl80211_if_combination_attrs { MAX_NL80211_IFACE_COMB = NUM_NL80211_IFACE_COMB - 1 }; + +/** + * enum nl80211_plink_state - state of a mesh peer link finite state machine + * + * @NL80211_PLINK_LISTEN: initial state, considered the implicit + * state of non existant mesh peer links + * @NL80211_PLINK_OPN_SNT: mesh plink open frame has been sent to + * this mesh peer + * @NL80211_PLINK_OPN_RCVD: mesh plink open frame has been received + * from this mesh peer + * @NL80211_PLINK_CNF_RCVD: mesh plink confirm frame has been + * received from this mesh peer + * @NL80211_PLINK_ESTAB: mesh peer link is established + * @NL80211_PLINK_HOLDING: mesh peer link is being closed or cancelled + * @NL80211_PLINK_BLOCKED: all frames transmitted from this mesh + * plink are discarded + * @NUM_NL80211_PLINK_STATES: number of peer link states + * @MAX_NL80211_PLINK_STATES: highest numerical value of plink states + */ +enum nl80211_plink_state { + NL80211_PLINK_LISTEN, + NL80211_PLINK_OPN_SNT, + NL80211_PLINK_OPN_RCVD, + NL80211_PLINK_CNF_RCVD, + NL80211_PLINK_ESTAB, + NL80211_PLINK_HOLDING, + NL80211_PLINK_BLOCKED, + + /* keep last */ + NUM_NL80211_PLINK_STATES, + MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1 +}; + #endif /* __LINUX_NL80211_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 04afcfb9eaf4..0a2d795d35de 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -371,33 +371,6 @@ enum plink_actions { PLINK_ACTION_BLOCK, }; -/** - * enum plink_states - state of a mesh peer link finite state machine - * - * @PLINK_LISTEN: initial state, considered the implicit state of non - * existant mesh peer links - * @PLINK_OPN_SNT: mesh plink open frame has been sent to this mesh - * peer @PLINK_OPN_RCVD: mesh plink open frame has been received from - * this mesh peer - * @PLINK_CNF_RCVD: mesh plink confirm frame has been received from - * this mesh peer - * @PLINK_ESTAB: mesh peer link is established - * @PLINK_HOLDING: mesh peer link is being closed or cancelled - * @PLINK_BLOCKED: all frames transmitted from this mesh plink are - * discarded - * @PLINK_INVALID: reserved - */ -enum plink_state { - PLINK_LISTEN, - PLINK_OPN_SNT, - PLINK_OPN_RCVD, - PLINK_CNF_RCVD, - PLINK_ESTAB, - PLINK_HOLDING, - PLINK_BLOCKED, - PLINK_INVALID, -}; - /** * struct station_parameters - station parameters * diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6ecd5862735d..be70c70d3f5b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -730,9 +730,9 @@ static void sta_apply_parameters(struct ieee80211_local *local, #ifdef CONFIG_MAC80211_MESH if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) switch (params->plink_state) { - case PLINK_LISTEN: - case PLINK_ESTAB: - case PLINK_BLOCKED: + case NL80211_PLINK_LISTEN: + case NL80211_PLINK_ESTAB: + case NL80211_PLINK_BLOCKED: sta->plink_state = params->plink_state; break; default: diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 2c37bee3095a..f4adc0917888 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -83,7 +83,7 @@ void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) */ static inline void mesh_plink_fsm_restart(struct sta_info *sta) { - sta->plink_state = PLINK_LISTEN; + sta->plink_state = NL80211_PLINK_LISTEN; sta->llid = sta->plid = sta->reason = 0; sta->plink_retries = 0; } @@ -126,11 +126,11 @@ static bool __mesh_plink_deactivate(struct sta_info *sta) struct ieee80211_sub_if_data *sdata = sta->sdata; bool deactivated = false; - if (sta->plink_state == PLINK_ESTAB) { + if (sta->plink_state == NL80211_PLINK_ESTAB) { mesh_plink_dec_estab_count(sdata); deactivated = true; } - sta->plink_state = PLINK_BLOCKED; + sta->plink_state = NL80211_PLINK_BLOCKED; mesh_path_flush_by_nexthop(sta); return deactivated; @@ -268,7 +268,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, sta->last_rx = jiffies; sta->sta.supp_rates[local->hw.conf.channel->band] = rates; if (mesh_peer_accepts_plinks(elems) && - sta->plink_state == PLINK_LISTEN && + sta->plink_state == NL80211_PLINK_LISTEN && sdata->u.mesh.accepting_plinks && sdata->u.mesh.mshcfg.auto_open_plinks) mesh_plink_open(sta); @@ -308,8 +308,8 @@ static void mesh_plink_timer(unsigned long data) sdata = sta->sdata; switch (sta->plink_state) { - case PLINK_OPN_RCVD: - case PLINK_OPN_SNT: + case NL80211_PLINK_OPN_RCVD: + case NL80211_PLINK_OPN_SNT: /* retry timer */ if (sta->plink_retries < dot11MeshMaxRetries(sdata)) { u32 rand; @@ -328,17 +328,17 @@ static void mesh_plink_timer(unsigned long data) } reason = cpu_to_le16(MESH_MAX_RETRIES); /* fall through on else */ - case PLINK_CNF_RCVD: + case NL80211_PLINK_CNF_RCVD: /* confirm timer */ if (!reason) reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); - sta->plink_state = PLINK_HOLDING; + sta->plink_state = NL80211_PLINK_HOLDING; mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, reason); break; - case PLINK_HOLDING: + case NL80211_PLINK_HOLDING: /* holding timer */ del_timer(&sta->plink_timer); mesh_plink_fsm_restart(sta); @@ -386,11 +386,11 @@ int mesh_plink_open(struct sta_info *sta) spin_lock_bh(&sta->lock); get_random_bytes(&llid, 2); sta->llid = llid; - if (sta->plink_state != PLINK_LISTEN) { + if (sta->plink_state != NL80211_PLINK_LISTEN) { spin_unlock_bh(&sta->lock); return -EBUSY; } - sta->plink_state = PLINK_OPN_SNT; + sta->plink_state = NL80211_PLINK_OPN_SNT; mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); spin_unlock_bh(&sta->lock); mpl_dbg("Mesh plink: starting establishment with %pM\n", @@ -407,7 +407,7 @@ void mesh_plink_block(struct sta_info *sta) spin_lock_bh(&sta->lock); deactivated = __mesh_plink_deactivate(sta); - sta->plink_state = PLINK_BLOCKED; + sta->plink_state = NL80211_PLINK_BLOCKED; spin_unlock_bh(&sta->lock); if (deactivated) @@ -430,13 +430,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m __le16 plid, llid, reason; #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG static const char *mplstates[] = { - [PLINK_LISTEN] = "LISTEN", - [PLINK_OPN_SNT] = "OPN-SNT", - [PLINK_OPN_RCVD] = "OPN-RCVD", - [PLINK_CNF_RCVD] = "CNF_RCVD", - [PLINK_ESTAB] = "ESTAB", - [PLINK_HOLDING] = "HOLDING", - [PLINK_BLOCKED] = "BLOCKED" + [NL80211_PLINK_LISTEN] = "LISTEN", + [NL80211_PLINK_OPN_SNT] = "OPN-SNT", + [NL80211_PLINK_OPN_RCVD] = "OPN-RCVD", + [NL80211_PLINK_CNF_RCVD] = "CNF_RCVD", + [NL80211_PLINK_ESTAB] = "ESTAB", + [NL80211_PLINK_HOLDING] = "HOLDING", + [NL80211_PLINK_BLOCKED] = "BLOCKED" }; #endif @@ -502,7 +502,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m return; } - if (sta && sta->plink_state == PLINK_BLOCKED) { + if (sta && sta->plink_state == NL80211_PLINK_BLOCKED) { rcu_read_unlock(); return; } @@ -572,7 +572,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m event = CNF_ACPT; break; case PLINK_CLOSE: - if (sta->plink_state == PLINK_ESTAB) + if (sta->plink_state == NL80211_PLINK_ESTAB) /* Do not check for llid or plid. This does not * follow the standard but since multiple plinks * per sta are not supported, it is necessary in @@ -607,14 +607,14 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m reason = 0; switch (sta->plink_state) { /* spin_unlock as soon as state is updated at each case */ - case PLINK_LISTEN: + case NL80211_PLINK_LISTEN: switch (event) { case CLS_ACPT: mesh_plink_fsm_restart(sta); spin_unlock_bh(&sta->lock); break; case OPN_ACPT: - sta->plink_state = PLINK_OPN_RCVD; + sta->plink_state = NL80211_PLINK_OPN_RCVD; sta->plid = plid; get_random_bytes(&llid, 2); sta->llid = llid; @@ -631,7 +631,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m } break; - case PLINK_OPN_SNT: + case NL80211_PLINK_OPN_SNT: switch (event) { case OPN_RJCT: case CNF_RJCT: @@ -640,7 +640,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m if (!reason) reason = cpu_to_le16(MESH_CLOSE_RCVD); sta->reason = reason; - sta->plink_state = PLINK_HOLDING; + sta->plink_state = NL80211_PLINK_HOLDING; if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata))) sta->ignore_plink_timer = true; @@ -652,7 +652,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m break; case OPN_ACPT: /* retry timer is left untouched */ - sta->plink_state = PLINK_OPN_RCVD; + sta->plink_state = NL80211_PLINK_OPN_RCVD; sta->plid = plid; llid = sta->llid; spin_unlock_bh(&sta->lock); @@ -660,7 +660,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m plid, 0); break; case CNF_ACPT: - sta->plink_state = PLINK_CNF_RCVD; + sta->plink_state = NL80211_PLINK_CNF_RCVD; if (!mod_plink_timer(sta, dot11MeshConfirmTimeout(sdata))) sta->ignore_plink_timer = true; @@ -673,7 +673,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m } break; - case PLINK_OPN_RCVD: + case NL80211_PLINK_OPN_RCVD: switch (event) { case OPN_RJCT: case CNF_RJCT: @@ -682,7 +682,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m if (!reason) reason = cpu_to_le16(MESH_CLOSE_RCVD); sta->reason = reason; - sta->plink_state = PLINK_HOLDING; + sta->plink_state = NL80211_PLINK_HOLDING; if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata))) sta->ignore_plink_timer = true; @@ -700,7 +700,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m break; case CNF_ACPT: del_timer(&sta->plink_timer); - sta->plink_state = PLINK_ESTAB; + sta->plink_state = NL80211_PLINK_ESTAB; spin_unlock_bh(&sta->lock); mesh_plink_inc_estab_count(sdata); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); @@ -713,7 +713,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m } break; - case PLINK_CNF_RCVD: + case NL80211_PLINK_CNF_RCVD: switch (event) { case OPN_RJCT: case CNF_RJCT: @@ -722,7 +722,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m if (!reason) reason = cpu_to_le16(MESH_CLOSE_RCVD); sta->reason = reason; - sta->plink_state = PLINK_HOLDING; + sta->plink_state = NL80211_PLINK_HOLDING; if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata))) sta->ignore_plink_timer = true; @@ -734,7 +734,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m break; case OPN_ACPT: del_timer(&sta->plink_timer); - sta->plink_state = PLINK_ESTAB; + sta->plink_state = NL80211_PLINK_ESTAB; spin_unlock_bh(&sta->lock); mesh_plink_inc_estab_count(sdata); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); @@ -749,13 +749,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m } break; - case PLINK_ESTAB: + case NL80211_PLINK_ESTAB: switch (event) { case CLS_ACPT: reason = cpu_to_le16(MESH_CLOSE_RCVD); sta->reason = reason; deactivated = __mesh_plink_deactivate(sta); - sta->plink_state = PLINK_HOLDING; + sta->plink_state = NL80211_PLINK_HOLDING; llid = sta->llid; mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); @@ -775,7 +775,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m break; } break; - case PLINK_HOLDING: + case NL80211_PLINK_HOLDING: switch (event) { case CLS_ACPT: if (del_timer(&sta->plink_timer)) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 1b9413fb3839..3a9515cb7ce1 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -490,7 +490,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) * establisment frame, beacon or probe, drop the frame. */ - if (!rx->sta || sta_plink_state(rx->sta) != PLINK_ESTAB) { + if (!rx->sta || sta_plink_state(rx->sta) != NL80211_PLINK_ESTAB) { struct ieee80211_mgmt *mgmt; if (!ieee80211_is_mgmt(hdr->frame_control)) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 82ab6b4643fc..4a15f9603562 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -277,7 +277,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ #ifdef CONFIG_MAC80211_MESH - sta->plink_state = PLINK_LISTEN; + sta->plink_state = NL80211_PLINK_LISTEN; init_timer(&sta->plink_timer); #endif diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index d6b566076f05..c6ae8718bd57 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -318,7 +318,7 @@ struct sta_info { u8 plink_retries; bool ignore_plink_timer; bool plink_timer_was_running; - enum plink_state plink_state; + enum nl80211_plink_state plink_state; u32 plink_timeout; struct timer_list plink_timer; #endif @@ -336,12 +336,12 @@ struct sta_info { struct ieee80211_sta sta; }; -static inline enum plink_state sta_plink_state(struct sta_info *sta) +static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta) { #ifdef CONFIG_MAC80211_MESH return sta->plink_state; #endif - return PLINK_LISTEN; + return NL80211_PLINK_LISTEN; } static inline void set_sta_flags(struct sta_info *sta, const u32 flags) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index beac296b1fde..2222ce08ee91 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2335,7 +2335,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) memset(¶ms, 0, sizeof(params)); params.listen_interval = -1; - params.plink_state = PLINK_INVALID; + params.plink_state = -1; if (info->attrs[NL80211_ATTR_STA_AID]) return -EINVAL; -- cgit v1.2.3-58-ga151 From 8b3becadc82de3b87a5c196239db3fef6caa9c82 Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Fri, 13 May 2011 11:22:31 -0700 Subject: cfg80211: make stripping of 802.11 header optional from AMSDU Currently the devices that have already stripped IEEE 802.11 header from the AMSDU SKB can not use ieee80211_amsdu_to_8023s routine. This patch enhances ieee80211_amsdu_to_8023s() API by changing mandatory removing of IEEE 802.11 header from AMSDU to optional. Signed-off-by: Yogesh Ashok Powar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 3 ++- include/net/cfg80211.h | 4 +++- net/mac80211/rx.c | 2 +- net/wireless/util.c | 21 +++++++++++++-------- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 9a57cf6a488f..5665a1a9b99e 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -1576,7 +1576,8 @@ static void iwm_rx_process_amsdu(struct iwm_priv *iwm, struct sk_buff *skb) IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len); __skb_queue_head_init(&list); - ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0); + ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0, + true); while ((frame = __skb_dequeue(&list))) { ndev->stats.rx_packets++; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0a2d795d35de..bfd6557946be 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2237,10 +2237,12 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, * @addr: The device MAC address. * @iftype: The device interface type. * @extra_headroom: The hardware extra headroom for SKBs in the @list. + * @has_80211_header: Set it true if SKB is with IEEE 802.11 header. */ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, const u8 *addr, enum nl80211_iftype iftype, - const unsigned int extra_headroom); + const unsigned int extra_headroom, + bool has_80211_header); /** * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3a9515cb7ce1..78c72a41d864 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1783,7 +1783,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, rx->sdata->vif.type, - rx->local->hw.extra_tx_headroom); + rx->local->hw.extra_tx_headroom, true); while (!skb_queue_empty(&frame_list)) { rx->skb = __skb_dequeue(&frame_list); diff --git a/net/wireless/util.c b/net/wireless/util.c index 95e4e254da0a..f0536d44d43c 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -544,7 +544,8 @@ EXPORT_SYMBOL(ieee80211_data_from_8023); void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, const u8 *addr, enum nl80211_iftype iftype, - const unsigned int extra_headroom) + const unsigned int extra_headroom, + bool has_80211_header) { struct sk_buff *frame = NULL; u16 ethertype; @@ -553,14 +554,18 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, int remaining, err; u8 dst[ETH_ALEN], src[ETH_ALEN]; - err = ieee80211_data_to_8023(skb, addr, iftype); - if (err) - goto out; + if (has_80211_header) { + err = ieee80211_data_to_8023(skb, addr, iftype); + if (err) + goto out; - /* skip the wrapping header */ - eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr)); - if (!eth) - goto out; + /* skip the wrapping header */ + eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr)); + if (!eth) + goto out; + } else { + eth = (struct ethhdr *) skb->data; + } while (skb != frame) { u8 padding; -- cgit v1.2.3-58-ga151 From 3b8ab88acaceb505aa06ef3bbf3a73b92470ae78 Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Fri, 13 May 2011 11:22:32 -0700 Subject: mwifiex: use ieee80211_amsdu_to_8023s routine mwifiex was using its own implementation of converting 802.11n AMSDU to 802.3s. This patch removes mwifiex specific implementation and uses existing ieee80211_amsdu_to_8023s routine. Signed-off-by: Yogesh Ashok Powar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n_aggr.c | 125 -------------------------------- drivers/net/wireless/mwifiex/sta_rx.c | 22 +++++- 2 files changed, 20 insertions(+), 127 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 2b2cca5e6d0f..d3d5e0853c45 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -135,131 +135,6 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, } } -/* - * Counts the number of subframes in an aggregate packet. - * - * This function parses an aggregate packet buffer, looking for - * subframes and counting the number of such subframe found. The - * function automatically skips the DA/SA fields at the beginning - * of each subframe and padding at the end. - */ -static int -mwifiex_11n_get_num_aggr_pkts(u8 *data, int total_pkt_len) -{ - int pkt_count = 0, pkt_len, pad; - - while (total_pkt_len > 0) { - /* Length will be in network format, change it to host */ - pkt_len = ntohs((*(__be16 *)(data + 2 * ETH_ALEN))); - pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ? - (4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0; - data += pkt_len + pad + sizeof(struct ethhdr); - total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr); - ++pkt_count; - } - - return pkt_count; -} - -/* - * De-aggregate received packets. - * - * This function parses the received aggregate buffer, extracts each subframe, - * strips off the SNAP header from them and sends the data portion for further - * processing. - * - * Each subframe body is copied onto a separate buffer, which are freed by - * upper layer after processing. The function also performs sanity tests on - * the received buffer. - */ -int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - u16 pkt_len; - int total_pkt_len; - u8 *data; - int pad; - struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); - struct rxpd *local_rx_pd = (struct rxpd *) skb->data; - struct sk_buff *skb_daggr; - struct mwifiex_rxinfo *rx_info_daggr; - int ret = -1; - struct rx_packet_hdr *rx_pkt_hdr; - struct mwifiex_adapter *adapter = priv->adapter; - u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; - - data = (u8 *) (local_rx_pd + local_rx_pd->rx_pkt_offset); - total_pkt_len = local_rx_pd->rx_pkt_length; - - /* Sanity test */ - if (total_pkt_len > MWIFIEX_RX_DATA_BUF_SIZE) { - dev_err(adapter->dev, "total pkt len greater than buffer" - " size %d\n", total_pkt_len); - return -1; - } - - rx_info->use_count = mwifiex_11n_get_num_aggr_pkts(data, total_pkt_len); - - while (total_pkt_len > 0) { - rx_pkt_hdr = (struct rx_packet_hdr *) data; - /* Length will be in network format, change it to host */ - pkt_len = ntohs((*(__be16 *) (data + 2 * ETH_ALEN))); - if (pkt_len > total_pkt_len) { - dev_err(adapter->dev, "pkt_len %d > total_pkt_len %d\n", - total_pkt_len, pkt_len); - break; - } - - pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ? - (4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0; - - total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr); - - if (memcmp(&rx_pkt_hdr->rfc1042_hdr, - rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) { - memmove(data + LLC_SNAP_LEN, data, 2 * ETH_ALEN); - data += LLC_SNAP_LEN; - pkt_len += sizeof(struct ethhdr) - LLC_SNAP_LEN; - } else { - *(u16 *) (data + 2 * ETH_ALEN) = (u16) 0; - pkt_len += sizeof(struct ethhdr); - } - - skb_daggr = dev_alloc_skb(pkt_len); - if (!skb_daggr) { - dev_err(adapter->dev, "%s: failed to alloc skb_daggr\n", - __func__); - return -1; - } - rx_info_daggr = MWIFIEX_SKB_RXCB(skb_daggr); - - rx_info_daggr->bss_index = rx_info->bss_index; - skb_daggr->tstamp = skb->tstamp; - rx_info_daggr->parent = skb; - skb_daggr->priority = skb->priority; - skb_put(skb_daggr, pkt_len); - memcpy(skb_daggr->data, data, pkt_len); - - ret = mwifiex_recv_packet(adapter, skb_daggr); - - switch (ret) { - case -EINPROGRESS: - break; - case -1: - dev_err(adapter->dev, "deaggr: host_to_card failed\n"); - case 0: - mwifiex_recv_packet_complete(adapter, skb_daggr, ret); - break; - default: - break; - } - - data += pkt_len + pad; - } - - return ret; -} - /* * Create aggregated packet. * diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index e047f0d8a983..1fdddece7479 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c @@ -141,10 +141,28 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, dev_kfree_skb_any(skb); return ret; } + if (local_rx_pd->rx_pkt_type == PKT_TYPE_AMSDU) { - mwifiex_11n_deaggregate_pkt(priv, skb); - return ret; + struct sk_buff_head list; + struct sk_buff *rx_skb; + + __skb_queue_head_init(&list); + + skb_pull(skb, local_rx_pd->rx_pkt_offset); + skb_trim(skb, local_rx_pd->rx_pkt_length); + + ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, + priv->wdev->iftype, 0, false); + + while (!skb_queue_empty(&list)) { + rx_skb = __skb_dequeue(&list); + ret = mwifiex_recv_packet(adapter, rx_skb); + if (ret == -1) + dev_err(adapter->dev, "Rx of A-MSDU failed"); + } + return 0; } + /* * If the packet is not an unicast packet then send the packet * directly to os. Don't pass thru rx reordering -- cgit v1.2.3-58-ga151 From 89a88ab84b946a90839fb66ca3583a2504c11292 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Mon, 16 May 2011 07:36:18 +0000 Subject: be2net: Support for version 1 of stats for BE3 Added support to get version 1 of the stats for BE3. Use old stats command for BE2. Signed-off-by: Ajit Khaparde Signed-off-by: Selvin Xavier Signed-off-by: Padmanabh Ratnakar Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 38 +++++++++ drivers/net/benet/be_cmds.c | 32 ++++++-- drivers/net/benet/be_cmds.h | 181 ++++++++++++++++++++++++++++++++++------ drivers/net/benet/be_ethtool.c | 108 ++++++++++-------------- drivers/net/benet/be_main.c | 182 ++++++++++++++++++++++++++++++++++------- 5 files changed, 413 insertions(+), 128 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 41bbc32123f8..0da0384efee7 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -244,6 +244,43 @@ struct be_rx_obj { struct be_drv_stats { u8 be_on_die_temperature; + u32 be_tx_events; + u32 eth_red_drops; + u32 rx_drops_no_pbuf; + u32 rx_drops_no_txpb; + u32 rx_drops_no_erx_descr; + u32 rx_drops_no_tpre_descr; + u32 rx_drops_too_many_frags; + u32 rx_drops_invalid_ring; + u32 forwarded_packets; + u32 rx_drops_mtu; + u32 rx_crc_errors; + u32 rx_alignment_symbol_errors; + u32 rx_pause_frames; + u32 rx_priority_pause_frames; + u32 rx_control_frames; + u32 rx_in_range_errors; + u32 rx_out_range_errors; + u32 rx_frame_too_long; + u32 rx_address_match_errors; + u32 rx_dropped_too_small; + u32 rx_dropped_too_short; + u32 rx_dropped_header_too_small; + u32 rx_dropped_tcp_length; + u32 rx_dropped_runt; + u32 rx_ip_checksum_errs; + u32 rx_tcp_checksum_errs; + u32 rx_udp_checksum_errs; + u32 rx_switched_unicast_packets; + u32 rx_switched_multicast_packets; + u32 rx_switched_broadcast_packets; + u32 tx_pauseframes; + u32 tx_priority_pauseframes; + u32 tx_controlframes; + u32 rxpp_fifo_overflow_drop; + u32 rx_input_fifo_overflow_drop; + u32 pmem_fifo_overflow_drop; + u32 jabber_events; }; struct be_vf_cfg { @@ -483,5 +520,6 @@ extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped); extern void be_link_status_update(struct be_adapter *adapter, bool link_up); extern void netdev_stats_update(struct be_adapter *adapter); +extern void be_parse_stats(struct be_adapter *adapter); extern int be_load_fw(struct be_adapter *adapter, u8 *func); #endif /* BE_H */ diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index f2c90997fabd..08e09388789a 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -80,10 +80,20 @@ static int be_mcc_compl_process(struct be_adapter *adapter, if (compl_status == MCC_STATUS_SUCCESS) { if ((compl->tag0 == OPCODE_ETH_GET_STATISTICS) && (compl->tag1 == CMD_SUBSYSTEM_ETH)) { - struct be_cmd_resp_get_stats *resp = - adapter->stats_cmd.va; - be_dws_le_to_cpu(&resp->hw_stats, - sizeof(resp->hw_stats)); + if (adapter->generation == BE_GEN3) { + struct be_cmd_resp_get_stats_v1 *resp = + adapter->stats_cmd.va; + + be_dws_le_to_cpu(&resp->hw_stats, + sizeof(resp->hw_stats)); + } else { + struct be_cmd_resp_get_stats_v0 *resp = + adapter->stats_cmd.va; + + be_dws_le_to_cpu(&resp->hw_stats, + sizeof(resp->hw_stats)); + } + be_parse_stats(adapter); netdev_stats_update(adapter); adapter->stats_cmd_sent = false; } @@ -1075,7 +1085,7 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id, u32 domain) int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) { struct be_mcc_wrb *wrb; - struct be_cmd_req_get_stats *req; + struct be_cmd_req_hdr *hdr; struct be_sge *sge; int status = 0; @@ -1089,14 +1099,18 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) status = -EBUSY; goto err; } - req = nonemb_cmd->va; + hdr = nonemb_cmd->va; sge = nonembedded_sgl(wrb); - be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1, + be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1, OPCODE_ETH_GET_STATISTICS); - be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, - OPCODE_ETH_GET_STATISTICS, sizeof(*req)); + be_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH, + OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size); + + if (adapter->generation == BE_GEN3) + hdr->version = 1; + wrb->tag1 = CMD_SUBSYSTEM_ETH; sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 78256b65cb03..bcf816d76521 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -568,7 +568,7 @@ struct be_cmd_req_if_destroy { }; /*************** HW Stats Get **********************************/ -struct be_port_rxf_stats { +struct be_port_rxf_stats_v0 { u32 rx_bytes_lsd; /* dword 0*/ u32 rx_bytes_msd; /* dword 1*/ u32 rx_total_frames; /* dword 2*/ @@ -637,8 +637,8 @@ struct be_port_rxf_stats { u32 rx_input_fifo_overflow; /* dword 65*/ }; -struct be_rxf_stats { - struct be_port_rxf_stats port[2]; +struct be_rxf_stats_v0 { + struct be_port_rxf_stats_v0 port[2]; u32 rx_drops_no_pbuf; /* dword 132*/ u32 rx_drops_no_txpb; /* dword 133*/ u32 rx_drops_no_erx_descr; /* dword 134*/ @@ -661,34 +661,31 @@ struct be_rxf_stats { u32 rsvd1[6]; }; -struct be_erx_stats { +struct be_erx_stats_v0 { u32 rx_drops_no_fragments[44]; /* dwordS 0 to 43*/ - u32 debug_wdma_sent_hold; /* dword 44*/ - u32 debug_wdma_pbfree_sent_hold; /* dword 45*/ - u32 debug_wdma_zerobyte_pbfree_sent_hold; /* dword 46*/ - u32 debug_pmem_pbuf_dealloc; /* dword 47*/ + u32 rsvd[4]; }; struct be_pmem_stats { u32 eth_red_drops; - u32 rsvd[4]; + u32 rsvd[5]; }; -struct be_hw_stats { - struct be_rxf_stats rxf; +struct be_hw_stats_v0 { + struct be_rxf_stats_v0 rxf; u32 rsvd[48]; - struct be_erx_stats erx; + struct be_erx_stats_v0 erx; struct be_pmem_stats pmem; }; -struct be_cmd_req_get_stats { +struct be_cmd_req_get_stats_v0 { struct be_cmd_req_hdr hdr; - u8 rsvd[sizeof(struct be_hw_stats)]; + u8 rsvd[sizeof(struct be_hw_stats_v0)]; }; -struct be_cmd_resp_get_stats { +struct be_cmd_resp_get_stats_v0 { struct be_cmd_resp_hdr hdr; - struct be_hw_stats hw_stats; + struct be_hw_stats_v0 hw_stats; }; struct be_cmd_req_get_cntl_addnl_attribs { @@ -728,13 +725,6 @@ struct be_cmd_req_mcast_mac_config { struct macaddr mac[BE_MAX_MC]; } __packed; -static inline struct be_hw_stats * -hw_stats_from_cmd(struct be_cmd_resp_get_stats *cmd) -{ - return &cmd->hw_stats; -} - - /******************* RX FILTER ******************************/ struct be_cmd_req_rx_filter { struct be_cmd_req_hdr hdr; @@ -1087,6 +1077,151 @@ struct be_cmd_resp_set_func_cap { u8 rsvd[212]; }; +/*************** HW Stats Get v1 **********************************/ +#define BE_TXP_SW_SZ 48 +struct be_port_rxf_stats_v1 { + u32 rsvd0[12]; + u32 rx_crc_errors; + u32 rx_alignment_symbol_errors; + u32 rx_pause_frames; + u32 rx_priority_pause_frames; + u32 rx_control_frames; + u32 rx_in_range_errors; + u32 rx_out_range_errors; + u32 rx_frame_too_long; + u32 rx_address_match_errors; + u32 rx_dropped_too_small; + u32 rx_dropped_too_short; + u32 rx_dropped_header_too_small; + u32 rx_dropped_tcp_length; + u32 rx_dropped_runt; + u32 rsvd1[10]; + u32 rx_ip_checksum_errs; + u32 rx_tcp_checksum_errs; + u32 rx_udp_checksum_errs; + u32 rsvd2[7]; + u32 rx_switched_unicast_packets; + u32 rx_switched_multicast_packets; + u32 rx_switched_broadcast_packets; + u32 rsvd3[3]; + u32 tx_pauseframes; + u32 tx_priority_pauseframes; + u32 tx_controlframes; + u32 rsvd4[10]; + u32 rxpp_fifo_overflow_drop; + u32 rx_input_fifo_overflow_drop; + u32 pmem_fifo_overflow_drop; + u32 jabber_events; + u32 rsvd5[3]; +}; + + +struct be_rxf_stats_v1 { + struct be_port_rxf_stats_v1 port[4]; + u32 rsvd0[2]; + u32 rx_drops_no_pbuf; + u32 rx_drops_no_txpb; + u32 rx_drops_no_erx_descr; + u32 rx_drops_no_tpre_descr; + u32 rsvd1[6]; + u32 rx_drops_too_many_frags; + u32 rx_drops_invalid_ring; + u32 forwarded_packets; + u32 rx_drops_mtu; + u32 rsvd2[14]; +}; + +struct be_erx_stats_v1 { + u32 rx_drops_no_fragments[68]; /* dwordS 0 to 67*/ + u32 rsvd[4]; +}; + +struct be_hw_stats_v1 { + struct be_rxf_stats_v1 rxf; + u32 rsvd0[BE_TXP_SW_SZ]; + struct be_erx_stats_v1 erx; + struct be_pmem_stats pmem; + u32 rsvd1[3]; +}; + +struct be_cmd_req_get_stats_v1 { + struct be_cmd_req_hdr hdr; + u8 rsvd[sizeof(struct be_hw_stats_v1)]; +}; + +struct be_cmd_resp_get_stats_v1 { + struct be_cmd_resp_hdr hdr; + struct be_hw_stats_v1 hw_stats; +}; + +static inline void * +hw_stats_from_cmd(struct be_adapter *adapter) +{ + if (adapter->generation == BE_GEN3) { + struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va; + + return &cmd->hw_stats; + } else { + struct be_cmd_resp_get_stats_v0 *cmd = adapter->stats_cmd.va; + + return &cmd->hw_stats; + } +} + +static inline void *be_port_rxf_stats_from_cmd(struct be_adapter *adapter) +{ + if (adapter->generation == BE_GEN3) { + struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter); + struct be_rxf_stats_v1 *rxf_stats = &hw_stats->rxf; + + return &rxf_stats->port[adapter->port_num]; + } else { + struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter); + struct be_rxf_stats_v0 *rxf_stats = &hw_stats->rxf; + + return &rxf_stats->port[adapter->port_num]; + } +} + +static inline void *be_rxf_stats_from_cmd(struct be_adapter *adapter) +{ + if (adapter->generation == BE_GEN3) { + struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter); + + return &hw_stats->rxf; + } else { + struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter); + + return &hw_stats->rxf; + } +} + +static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter) +{ + if (adapter->generation == BE_GEN3) { + struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter); + + return &hw_stats->erx; + } else { + struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter); + + return &hw_stats->erx; + } +} + +static inline void *be_pmem_stats_from_cmd(struct be_adapter *adapter) +{ + if (adapter->generation == BE_GEN3) { + struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter); + + return &hw_stats->pmem; + } else { + struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter); + + return &hw_stats->pmem; + } +} + extern int be_pci_fnum_get(struct be_adapter *adapter); extern int be_cmd_POST(struct be_adapter *adapter); extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 8e770e8275df..facfe3ca5c40 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -26,8 +26,8 @@ struct be_ethtool_stat { int offset; }; -enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT, - PMEMSTAT, DRVSTAT}; +enum {NETSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT, + DRVSTAT}; #define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \ offsetof(_struct, field) #define NETSTAT_INFO(field) #field, NETSTAT,\ @@ -37,15 +37,8 @@ enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT, FIELDINFO(struct be_tx_stats, field) #define DRVSTAT_RX_INFO(field) #field, DRVSTAT_RX,\ FIELDINFO(struct be_rx_stats, field) -#define MISCSTAT_INFO(field) #field, MISCSTAT,\ - FIELDINFO(struct be_rxf_stats, field) -#define PORTSTAT_INFO(field) #field, PORTSTAT,\ - FIELDINFO(struct be_port_rxf_stats, \ - field) -#define ERXSTAT_INFO(field) #field, ERXSTAT,\ - FIELDINFO(struct be_erx_stats, field) -#define PMEMSTAT_INFO(field) #field, PMEMSTAT,\ - FIELDINFO(struct be_pmem_stats, field) +#define ERXSTAT_INFO(field) #field, ERXSTAT,\ + FIELDINFO(struct be_erx_stats_v1, field) #define DRVSTAT_INFO(field) #field, DRVSTAT,\ FIELDINFO(struct be_drv_stats, \ field) @@ -65,50 +58,41 @@ static const struct be_ethtool_stat et_stats[] = { {DRVSTAT_TX_INFO(be_tx_stops)}, {DRVSTAT_TX_INFO(be_tx_events)}, {DRVSTAT_TX_INFO(be_tx_compl)}, - {PORTSTAT_INFO(rx_unicast_frames)}, - {PORTSTAT_INFO(rx_multicast_frames)}, - {PORTSTAT_INFO(rx_broadcast_frames)}, - {PORTSTAT_INFO(rx_crc_errors)}, - {PORTSTAT_INFO(rx_alignment_symbol_errors)}, - {PORTSTAT_INFO(rx_pause_frames)}, - {PORTSTAT_INFO(rx_control_frames)}, - {PORTSTAT_INFO(rx_in_range_errors)}, - {PORTSTAT_INFO(rx_out_range_errors)}, - {PORTSTAT_INFO(rx_frame_too_long)}, - {PORTSTAT_INFO(rx_address_match_errors)}, - {PORTSTAT_INFO(rx_vlan_mismatch)}, - {PORTSTAT_INFO(rx_dropped_too_small)}, - {PORTSTAT_INFO(rx_dropped_too_short)}, - {PORTSTAT_INFO(rx_dropped_header_too_small)}, - {PORTSTAT_INFO(rx_dropped_tcp_length)}, - {PORTSTAT_INFO(rx_dropped_runt)}, - {PORTSTAT_INFO(rx_fifo_overflow)}, - {PORTSTAT_INFO(rx_input_fifo_overflow)}, - {PORTSTAT_INFO(rx_ip_checksum_errs)}, - {PORTSTAT_INFO(rx_tcp_checksum_errs)}, - {PORTSTAT_INFO(rx_udp_checksum_errs)}, - {PORTSTAT_INFO(rx_non_rss_packets)}, - {PORTSTAT_INFO(rx_ipv4_packets)}, - {PORTSTAT_INFO(rx_ipv6_packets)}, - {PORTSTAT_INFO(rx_switched_unicast_packets)}, - {PORTSTAT_INFO(rx_switched_multicast_packets)}, - {PORTSTAT_INFO(rx_switched_broadcast_packets)}, - {PORTSTAT_INFO(tx_unicastframes)}, - {PORTSTAT_INFO(tx_multicastframes)}, - {PORTSTAT_INFO(tx_broadcastframes)}, - {PORTSTAT_INFO(tx_pauseframes)}, - {PORTSTAT_INFO(tx_controlframes)}, - {MISCSTAT_INFO(rx_drops_no_pbuf)}, - {MISCSTAT_INFO(rx_drops_no_txpb)}, - {MISCSTAT_INFO(rx_drops_no_erx_descr)}, - {MISCSTAT_INFO(rx_drops_no_tpre_descr)}, - {MISCSTAT_INFO(rx_drops_too_many_frags)}, - {MISCSTAT_INFO(rx_drops_invalid_ring)}, - {MISCSTAT_INFO(forwarded_packets)}, - {MISCSTAT_INFO(rx_drops_mtu)}, - {MISCSTAT_INFO(port0_jabber_events)}, - {MISCSTAT_INFO(port1_jabber_events)}, - {PMEMSTAT_INFO(eth_red_drops)}, + {DRVSTAT_INFO(rx_crc_errors)}, + {DRVSTAT_INFO(rx_alignment_symbol_errors)}, + {DRVSTAT_INFO(rx_pause_frames)}, + {DRVSTAT_INFO(rx_control_frames)}, + {DRVSTAT_INFO(rx_in_range_errors)}, + {DRVSTAT_INFO(rx_out_range_errors)}, + {DRVSTAT_INFO(rx_frame_too_long)}, + {DRVSTAT_INFO(rx_address_match_errors)}, + {DRVSTAT_INFO(rx_dropped_too_small)}, + {DRVSTAT_INFO(rx_dropped_too_short)}, + {DRVSTAT_INFO(rx_dropped_header_too_small)}, + {DRVSTAT_INFO(rx_dropped_tcp_length)}, + {DRVSTAT_INFO(rx_dropped_runt)}, + {DRVSTAT_INFO(rxpp_fifo_overflow_drop)}, + {DRVSTAT_INFO(rx_input_fifo_overflow_drop)}, + {DRVSTAT_INFO(rx_ip_checksum_errs)}, + {DRVSTAT_INFO(rx_tcp_checksum_errs)}, + {DRVSTAT_INFO(rx_udp_checksum_errs)}, + {DRVSTAT_INFO(rx_switched_unicast_packets)}, + {DRVSTAT_INFO(rx_switched_multicast_packets)}, + {DRVSTAT_INFO(rx_switched_broadcast_packets)}, + {DRVSTAT_INFO(tx_pauseframes)}, + {DRVSTAT_INFO(tx_controlframes)}, + {DRVSTAT_INFO(rx_priority_pause_frames)}, + {DRVSTAT_INFO(pmem_fifo_overflow_drop)}, + {DRVSTAT_INFO(jabber_events)}, + {DRVSTAT_INFO(rx_drops_no_pbuf)}, + {DRVSTAT_INFO(rx_drops_no_txpb)}, + {DRVSTAT_INFO(rx_drops_no_erx_descr)}, + {DRVSTAT_INFO(rx_drops_no_tpre_descr)}, + {DRVSTAT_INFO(rx_drops_too_many_frags)}, + {DRVSTAT_INFO(rx_drops_invalid_ring)}, + {DRVSTAT_INFO(forwarded_packets)}, + {DRVSTAT_INFO(rx_drops_mtu)}, + {DRVSTAT_INFO(eth_red_drops)}, {DRVSTAT_INFO(be_on_die_temperature)} }; #define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats) @@ -268,8 +252,6 @@ be_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, uint64_t *data) { struct be_adapter *adapter = netdev_priv(netdev); - struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats_cmd.va); - struct be_erx_stats *erx_stats = &hw_stats->erx; struct be_rx_obj *rxo; void *p = NULL; int i, j; @@ -282,15 +264,6 @@ be_get_ethtool_stats(struct net_device *netdev, case DRVSTAT_TX: p = &adapter->tx_stats; break; - case PORTSTAT: - p = &hw_stats->rxf.port[adapter->port_num]; - break; - case MISCSTAT: - p = &hw_stats->rxf; - break; - case PMEMSTAT: - p = &hw_stats->pmem; - break; case DRVSTAT: p = &adapter->drv_stats; break; @@ -308,7 +281,8 @@ be_get_ethtool_stats(struct net_device *netdev, p = (u8 *)&rxo->stats + et_rx_stats[i].offset; break; case ERXSTAT: - p = (u32 *)erx_stats + rxo->q.id; + p = (u32 *)be_erx_stats_from_cmd(adapter) + + rxo->q.id; break; } data[ETHTOOL_STATS_NUM + j * ETHTOOL_RXSTATS_NUM + i] = diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 243172bedfa6..cff2cca3087d 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -245,14 +245,126 @@ netdev_addr: return status; } +static void populate_be2_stats(struct be_adapter *adapter) +{ + + struct be_drv_stats *drvs = &adapter->drv_stats; + struct be_pmem_stats *pmem_sts = be_pmem_stats_from_cmd(adapter); + struct be_port_rxf_stats_v0 *port_stats = + be_port_rxf_stats_from_cmd(adapter); + struct be_rxf_stats_v0 *rxf_stats = + be_rxf_stats_from_cmd(adapter); + + drvs->rx_pause_frames = port_stats->rx_pause_frames; + drvs->rx_crc_errors = port_stats->rx_crc_errors; + drvs->rx_control_frames = port_stats->rx_control_frames; + drvs->rx_in_range_errors = port_stats->rx_in_range_errors; + drvs->rx_frame_too_long = port_stats->rx_frame_too_long; + drvs->rx_dropped_runt = port_stats->rx_dropped_runt; + drvs->rx_ip_checksum_errs = port_stats->rx_ip_checksum_errs; + drvs->rx_tcp_checksum_errs = port_stats->rx_tcp_checksum_errs; + drvs->rx_udp_checksum_errs = port_stats->rx_udp_checksum_errs; + drvs->rxpp_fifo_overflow_drop = port_stats->rx_fifo_overflow; + drvs->rx_dropped_tcp_length = port_stats->rx_dropped_tcp_length; + drvs->rx_dropped_too_small = port_stats->rx_dropped_too_small; + drvs->rx_dropped_too_short = port_stats->rx_dropped_too_short; + drvs->rx_out_range_errors = port_stats->rx_out_range_errors; + drvs->rx_input_fifo_overflow_drop = + port_stats->rx_input_fifo_overflow; + drvs->rx_dropped_header_too_small = + port_stats->rx_dropped_header_too_small; + drvs->rx_address_match_errors = + port_stats->rx_address_match_errors; + drvs->rx_alignment_symbol_errors = + port_stats->rx_alignment_symbol_errors; + + drvs->tx_pauseframes = port_stats->tx_pauseframes; + drvs->tx_controlframes = port_stats->tx_controlframes; + + if (adapter->port_num) + drvs->jabber_events = + rxf_stats->port1_jabber_events; + else + drvs->jabber_events = + rxf_stats->port0_jabber_events; + drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf; + drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb; + drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr; + drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring; + drvs->forwarded_packets = rxf_stats->forwarded_packets; + drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu; + drvs->rx_drops_no_tpre_descr = + rxf_stats->rx_drops_no_tpre_descr; + drvs->rx_drops_too_many_frags = + rxf_stats->rx_drops_too_many_frags; + adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops; +} + +static void populate_be3_stats(struct be_adapter *adapter) +{ + struct be_drv_stats *drvs = &adapter->drv_stats; + struct be_pmem_stats *pmem_sts = be_pmem_stats_from_cmd(adapter); + + struct be_rxf_stats_v1 *rxf_stats = + be_rxf_stats_from_cmd(adapter); + struct be_port_rxf_stats_v1 *port_stats = + be_port_rxf_stats_from_cmd(adapter); + + drvs->rx_priority_pause_frames = 0; + drvs->pmem_fifo_overflow_drop = 0; + drvs->rx_pause_frames = port_stats->rx_pause_frames; + drvs->rx_crc_errors = port_stats->rx_crc_errors; + drvs->rx_control_frames = port_stats->rx_control_frames; + drvs->rx_in_range_errors = port_stats->rx_in_range_errors; + drvs->rx_frame_too_long = port_stats->rx_frame_too_long; + drvs->rx_dropped_runt = port_stats->rx_dropped_runt; + drvs->rx_ip_checksum_errs = port_stats->rx_ip_checksum_errs; + drvs->rx_tcp_checksum_errs = port_stats->rx_tcp_checksum_errs; + drvs->rx_udp_checksum_errs = port_stats->rx_udp_checksum_errs; + drvs->rx_dropped_tcp_length = port_stats->rx_dropped_tcp_length; + drvs->rx_dropped_too_small = port_stats->rx_dropped_too_small; + drvs->rx_dropped_too_short = port_stats->rx_dropped_too_short; + drvs->rx_out_range_errors = port_stats->rx_out_range_errors; + drvs->rx_dropped_header_too_small = + port_stats->rx_dropped_header_too_small; + drvs->rx_input_fifo_overflow_drop = + port_stats->rx_input_fifo_overflow_drop; + drvs->rx_address_match_errors = + port_stats->rx_address_match_errors; + drvs->rx_alignment_symbol_errors = + port_stats->rx_alignment_symbol_errors; + drvs->rxpp_fifo_overflow_drop = + port_stats->rxpp_fifo_overflow_drop; + drvs->tx_pauseframes = port_stats->tx_pauseframes; + drvs->tx_controlframes = port_stats->tx_controlframes; + drvs->jabber_events = port_stats->jabber_events; + drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf; + drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb; + drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr; + drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring; + drvs->forwarded_packets = rxf_stats->forwarded_packets; + drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu; + drvs->rx_drops_no_tpre_descr = + rxf_stats->rx_drops_no_tpre_descr; + drvs->rx_drops_too_many_frags = + rxf_stats->rx_drops_too_many_frags; + adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops; +} + + + +void be_parse_stats(struct be_adapter *adapter) +{ + if (adapter->generation == BE_GEN3) + populate_be3_stats(adapter); + else + populate_be2_stats(adapter); +} + void netdev_stats_update(struct be_adapter *adapter) { - struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats_cmd.va); - struct be_rxf_stats *rxf_stats = &hw_stats->rxf; - struct be_port_rxf_stats *port_stats = - &rxf_stats->port[adapter->port_num]; + struct be_drv_stats *drvs = &adapter->drv_stats; struct net_device_stats *dev_stats = &adapter->netdev->stats; - struct be_erx_stats *erx_stats = &hw_stats->erx; struct be_rx_obj *rxo; int i; @@ -262,43 +374,52 @@ void netdev_stats_update(struct be_adapter *adapter) dev_stats->rx_bytes += rx_stats(rxo)->rx_bytes; dev_stats->multicast += rx_stats(rxo)->rx_mcast_pkts; /* no space in linux buffers: best possible approximation */ - dev_stats->rx_dropped += - erx_stats->rx_drops_no_fragments[rxo->q.id]; + if (adapter->generation == BE_GEN3) { + struct be_erx_stats_v1 *erx_stats = + be_erx_stats_from_cmd(adapter); + dev_stats->rx_dropped += + erx_stats->rx_drops_no_fragments[rxo->q.id]; + } else { + struct be_erx_stats_v0 *erx_stats = + be_erx_stats_from_cmd(adapter); + dev_stats->rx_dropped += + erx_stats->rx_drops_no_fragments[rxo->q.id]; + } } dev_stats->tx_packets = tx_stats(adapter)->be_tx_pkts; dev_stats->tx_bytes = tx_stats(adapter)->be_tx_bytes; /* bad pkts received */ - dev_stats->rx_errors = port_stats->rx_crc_errors + - port_stats->rx_alignment_symbol_errors + - port_stats->rx_in_range_errors + - port_stats->rx_out_range_errors + - port_stats->rx_frame_too_long + - port_stats->rx_dropped_too_small + - port_stats->rx_dropped_too_short + - port_stats->rx_dropped_header_too_small + - port_stats->rx_dropped_tcp_length + - port_stats->rx_dropped_runt + - port_stats->rx_tcp_checksum_errs + - port_stats->rx_ip_checksum_errs + - port_stats->rx_udp_checksum_errs; + dev_stats->rx_errors = drvs->rx_crc_errors + + drvs->rx_alignment_symbol_errors + + drvs->rx_in_range_errors + + drvs->rx_out_range_errors + + drvs->rx_frame_too_long + + drvs->rx_dropped_too_small + + drvs->rx_dropped_too_short + + drvs->rx_dropped_header_too_small + + drvs->rx_dropped_tcp_length + + drvs->rx_dropped_runt + + drvs->rx_tcp_checksum_errs + + drvs->rx_ip_checksum_errs + + drvs->rx_udp_checksum_errs; /* detailed rx errors */ - dev_stats->rx_length_errors = port_stats->rx_in_range_errors + - port_stats->rx_out_range_errors + - port_stats->rx_frame_too_long; + dev_stats->rx_length_errors = drvs->rx_in_range_errors + + drvs->rx_out_range_errors + + drvs->rx_frame_too_long; - dev_stats->rx_crc_errors = port_stats->rx_crc_errors; + dev_stats->rx_crc_errors = drvs->rx_crc_errors; /* frame alignment errors */ - dev_stats->rx_frame_errors = port_stats->rx_alignment_symbol_errors; + dev_stats->rx_frame_errors = drvs->rx_alignment_symbol_errors; /* receiver fifo overrun */ /* drops_no_pbuf is no per i/f, it's per BE card */ - dev_stats->rx_fifo_errors = port_stats->rx_fifo_overflow + - port_stats->rx_input_fifo_overflow + - rxf_stats->rx_drops_no_pbuf; + dev_stats->rx_fifo_errors = drvs->rxpp_fifo_overflow_drop + + drvs->rx_input_fifo_overflow_drop + + drvs->rx_drops_no_pbuf; } void be_link_status_update(struct be_adapter *adapter, bool link_up) @@ -2823,7 +2944,10 @@ static int be_stats_init(struct be_adapter *adapter) { struct be_dma_mem *cmd = &adapter->stats_cmd; - cmd->size = sizeof(struct be_cmd_req_get_stats); + if (adapter->generation == BE_GEN2) + cmd->size = sizeof(struct be_cmd_req_get_stats_v0); + else + cmd->size = sizeof(struct be_cmd_req_get_stats_v1); cmd->va = dma_alloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma, GFP_KERNEL); if (cmd->va == NULL) -- cgit v1.2.3-58-ga151 From 005d569600b404cae0b356e3c4085290ecc17775 Mon Sep 17 00:00:00 2001 From: Selvin Xavier Date: Mon, 16 May 2011 07:36:35 +0000 Subject: be2net: Stats for Lancer Added Lancer stats implementation. Signed-off-by: Selvin Xavier Signed-off-by: Padmanabh Ratnakar Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 74 ++++++++--------- drivers/net/benet/be_cmds.c | 55 ++++++++++++- drivers/net/benet/be_cmds.h | 197 ++++++++++++++++++++++++++++++++++++++++++++ drivers/net/benet/be_main.c | 91 +++++++++++++++++--- 4 files changed, 367 insertions(+), 50 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 0da0384efee7..0b73dcf26924 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -244,43 +244,43 @@ struct be_rx_obj { struct be_drv_stats { u8 be_on_die_temperature; - u32 be_tx_events; - u32 eth_red_drops; - u32 rx_drops_no_pbuf; - u32 rx_drops_no_txpb; - u32 rx_drops_no_erx_descr; - u32 rx_drops_no_tpre_descr; - u32 rx_drops_too_many_frags; - u32 rx_drops_invalid_ring; - u32 forwarded_packets; - u32 rx_drops_mtu; - u32 rx_crc_errors; - u32 rx_alignment_symbol_errors; - u32 rx_pause_frames; - u32 rx_priority_pause_frames; - u32 rx_control_frames; - u32 rx_in_range_errors; - u32 rx_out_range_errors; - u32 rx_frame_too_long; - u32 rx_address_match_errors; - u32 rx_dropped_too_small; - u32 rx_dropped_too_short; - u32 rx_dropped_header_too_small; - u32 rx_dropped_tcp_length; - u32 rx_dropped_runt; - u32 rx_ip_checksum_errs; - u32 rx_tcp_checksum_errs; - u32 rx_udp_checksum_errs; - u32 rx_switched_unicast_packets; - u32 rx_switched_multicast_packets; - u32 rx_switched_broadcast_packets; - u32 tx_pauseframes; - u32 tx_priority_pauseframes; - u32 tx_controlframes; - u32 rxpp_fifo_overflow_drop; - u32 rx_input_fifo_overflow_drop; - u32 pmem_fifo_overflow_drop; - u32 jabber_events; + u64 be_tx_events; + u64 eth_red_drops; + u64 rx_drops_no_pbuf; + u64 rx_drops_no_txpb; + u64 rx_drops_no_erx_descr; + u64 rx_drops_no_tpre_descr; + u64 rx_drops_too_many_frags; + u64 rx_drops_invalid_ring; + u64 forwarded_packets; + u64 rx_drops_mtu; + u64 rx_crc_errors; + u64 rx_alignment_symbol_errors; + u64 rx_pause_frames; + u64 rx_priority_pause_frames; + u64 rx_control_frames; + u64 rx_in_range_errors; + u64 rx_out_range_errors; + u64 rx_frame_too_long; + u64 rx_address_match_errors; + u64 rx_dropped_too_small; + u64 rx_dropped_too_short; + u64 rx_dropped_header_too_small; + u64 rx_dropped_tcp_length; + u64 rx_dropped_runt; + u64 rx_ip_checksum_errs; + u64 rx_tcp_checksum_errs; + u64 rx_udp_checksum_errs; + u64 rx_switched_unicast_packets; + u64 rx_switched_multicast_packets; + u64 rx_switched_broadcast_packets; + u64 tx_pauseframes; + u64 tx_priority_pauseframes; + u64 tx_controlframes; + u64 rxpp_fifo_overflow_drop; + u64 rx_input_fifo_overflow_drop; + u64 pmem_fifo_overflow_drop; + u64 jabber_events; }; struct be_vf_cfg { diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 08e09388789a..aaef0c731b9a 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -78,14 +78,22 @@ static int be_mcc_compl_process(struct be_adapter *adapter, } if (compl_status == MCC_STATUS_SUCCESS) { - if ((compl->tag0 == OPCODE_ETH_GET_STATISTICS) && + if (((compl->tag0 == OPCODE_ETH_GET_STATISTICS) || + (compl->tag0 == OPCODE_ETH_GET_PPORT_STATS)) && (compl->tag1 == CMD_SUBSYSTEM_ETH)) { if (adapter->generation == BE_GEN3) { - struct be_cmd_resp_get_stats_v1 *resp = + if (lancer_chip(adapter)) { + struct lancer_cmd_resp_pport_stats + *resp = adapter->stats_cmd.va; + be_dws_le_to_cpu(&resp->pport_stats, + sizeof(resp->pport_stats)); + } else { + struct be_cmd_resp_get_stats_v1 *resp = adapter->stats_cmd.va; be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats)); + } } else { struct be_cmd_resp_get_stats_v0 *resp = adapter->stats_cmd.va; @@ -1124,6 +1132,49 @@ err: return status; } +/* Lancer Stats */ +int lancer_cmd_get_pport_stats(struct be_adapter *adapter, + struct be_dma_mem *nonemb_cmd) +{ + + struct be_mcc_wrb *wrb; + struct lancer_cmd_req_pport_stats *req; + struct be_sge *sge; + int status = 0; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + req = nonemb_cmd->va; + sge = nonembedded_sgl(wrb); + + be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1, + OPCODE_ETH_GET_PPORT_STATS); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, + OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size); + + + req->cmd_params.params.pport_num = cpu_to_le16(adapter->port_num); + req->cmd_params.params.reset_stats = 0; + + wrb->tag1 = CMD_SUBSYSTEM_ETH; + sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); + sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(nonemb_cmd->size); + + be_mcc_notify(adapter); + adapter->stats_cmd_sent = true; + +err: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} + /* Uses synchronous mcc */ int be_cmd_link_status_query(struct be_adapter *adapter, bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom) diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index bcf816d76521..9cff226c94f1 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -203,6 +203,7 @@ struct be_mcc_mailbox { #define OPCODE_ETH_TX_DESTROY 9 #define OPCODE_ETH_RX_DESTROY 10 #define OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG 12 +#define OPCODE_ETH_GET_PPORT_STATS 18 #define OPCODE_LOWLEVEL_HOST_DDR_DMA 17 #define OPCODE_LOWLEVEL_LOOPBACK_TEST 18 @@ -688,6 +689,200 @@ struct be_cmd_resp_get_stats_v0 { struct be_hw_stats_v0 hw_stats; }; +#define make_64bit_val(hi_32, lo_32) (((u64)hi_32<<32) | lo_32) +struct lancer_cmd_pport_stats { + u32 tx_packets_lo; + u32 tx_packets_hi; + u32 tx_unicast_packets_lo; + u32 tx_unicast_packets_hi; + u32 tx_multicast_packets_lo; + u32 tx_multicast_packets_hi; + u32 tx_broadcast_packets_lo; + u32 tx_broadcast_packets_hi; + u32 tx_bytes_lo; + u32 tx_bytes_hi; + u32 tx_unicast_bytes_lo; + u32 tx_unicast_bytes_hi; + u32 tx_multicast_bytes_lo; + u32 tx_multicast_bytes_hi; + u32 tx_broadcast_bytes_lo; + u32 tx_broadcast_bytes_hi; + u32 tx_discards_lo; + u32 tx_discards_hi; + u32 tx_errors_lo; + u32 tx_errors_hi; + u32 tx_pause_frames_lo; + u32 tx_pause_frames_hi; + u32 tx_pause_on_frames_lo; + u32 tx_pause_on_frames_hi; + u32 tx_pause_off_frames_lo; + u32 tx_pause_off_frames_hi; + u32 tx_internal_mac_errors_lo; + u32 tx_internal_mac_errors_hi; + u32 tx_control_frames_lo; + u32 tx_control_frames_hi; + u32 tx_packets_64_bytes_lo; + u32 tx_packets_64_bytes_hi; + u32 tx_packets_65_to_127_bytes_lo; + u32 tx_packets_65_to_127_bytes_hi; + u32 tx_packets_128_to_255_bytes_lo; + u32 tx_packets_128_to_255_bytes_hi; + u32 tx_packets_256_to_511_bytes_lo; + u32 tx_packets_256_to_511_bytes_hi; + u32 tx_packets_512_to_1023_bytes_lo; + u32 tx_packets_512_to_1023_bytes_hi; + u32 tx_packets_1024_to_1518_bytes_lo; + u32 tx_packets_1024_to_1518_bytes_hi; + u32 tx_packets_1519_to_2047_bytes_lo; + u32 tx_packets_1519_to_2047_bytes_hi; + u32 tx_packets_2048_to_4095_bytes_lo; + u32 tx_packets_2048_to_4095_bytes_hi; + u32 tx_packets_4096_to_8191_bytes_lo; + u32 tx_packets_4096_to_8191_bytes_hi; + u32 tx_packets_8192_to_9216_bytes_lo; + u32 tx_packets_8192_to_9216_bytes_hi; + u32 tx_lso_packets_lo; + u32 tx_lso_packets_hi; + u32 rx_packets_lo; + u32 rx_packets_hi; + u32 rx_unicast_packets_lo; + u32 rx_unicast_packets_hi; + u32 rx_multicast_packets_lo; + u32 rx_multicast_packets_hi; + u32 rx_broadcast_packets_lo; + u32 rx_broadcast_packets_hi; + u32 rx_bytes_lo; + u32 rx_bytes_hi; + u32 rx_unicast_bytes_lo; + u32 rx_unicast_bytes_hi; + u32 rx_multicast_bytes_lo; + u32 rx_multicast_bytes_hi; + u32 rx_broadcast_bytes_lo; + u32 rx_broadcast_bytes_hi; + u32 rx_unknown_protos; + u32 rsvd_69; /* Word 69 is reserved */ + u32 rx_discards_lo; + u32 rx_discards_hi; + u32 rx_errors_lo; + u32 rx_errors_hi; + u32 rx_crc_errors_lo; + u32 rx_crc_errors_hi; + u32 rx_alignment_errors_lo; + u32 rx_alignment_errors_hi; + u32 rx_symbol_errors_lo; + u32 rx_symbol_errors_hi; + u32 rx_pause_frames_lo; + u32 rx_pause_frames_hi; + u32 rx_pause_on_frames_lo; + u32 rx_pause_on_frames_hi; + u32 rx_pause_off_frames_lo; + u32 rx_pause_off_frames_hi; + u32 rx_frames_too_long_lo; + u32 rx_frames_too_long_hi; + u32 rx_internal_mac_errors_lo; + u32 rx_internal_mac_errors_hi; + u32 rx_undersize_packets; + u32 rx_oversize_packets; + u32 rx_fragment_packets; + u32 rx_jabbers; + u32 rx_control_frames_lo; + u32 rx_control_frames_hi; + u32 rx_control_frames_unknown_opcode_lo; + u32 rx_control_frames_unknown_opcode_hi; + u32 rx_in_range_errors; + u32 rx_out_of_range_errors; + u32 rx_address_match_errors; + u32 rx_vlan_mismatch_errors; + u32 rx_dropped_too_small; + u32 rx_dropped_too_short; + u32 rx_dropped_header_too_small; + u32 rx_dropped_invalid_tcp_length; + u32 rx_dropped_runt; + u32 rx_ip_checksum_errors; + u32 rx_tcp_checksum_errors; + u32 rx_udp_checksum_errors; + u32 rx_non_rss_packets; + u32 rsvd_111; + u32 rx_ipv4_packets_lo; + u32 rx_ipv4_packets_hi; + u32 rx_ipv6_packets_lo; + u32 rx_ipv6_packets_hi; + u32 rx_ipv4_bytes_lo; + u32 rx_ipv4_bytes_hi; + u32 rx_ipv6_bytes_lo; + u32 rx_ipv6_bytes_hi; + u32 rx_nic_packets_lo; + u32 rx_nic_packets_hi; + u32 rx_tcp_packets_lo; + u32 rx_tcp_packets_hi; + u32 rx_iscsi_packets_lo; + u32 rx_iscsi_packets_hi; + u32 rx_management_packets_lo; + u32 rx_management_packets_hi; + u32 rx_switched_unicast_packets_lo; + u32 rx_switched_unicast_packets_hi; + u32 rx_switched_multicast_packets_lo; + u32 rx_switched_multicast_packets_hi; + u32 rx_switched_broadcast_packets_lo; + u32 rx_switched_broadcast_packets_hi; + u32 num_forwards_lo; + u32 num_forwards_hi; + u32 rx_fifo_overflow; + u32 rx_input_fifo_overflow; + u32 rx_drops_too_many_frags_lo; + u32 rx_drops_too_many_frags_hi; + u32 rx_drops_invalid_queue; + u32 rsvd_141; + u32 rx_drops_mtu_lo; + u32 rx_drops_mtu_hi; + u32 rx_packets_64_bytes_lo; + u32 rx_packets_64_bytes_hi; + u32 rx_packets_65_to_127_bytes_lo; + u32 rx_packets_65_to_127_bytes_hi; + u32 rx_packets_128_to_255_bytes_lo; + u32 rx_packets_128_to_255_bytes_hi; + u32 rx_packets_256_to_511_bytes_lo; + u32 rx_packets_256_to_511_bytes_hi; + u32 rx_packets_512_to_1023_bytes_lo; + u32 rx_packets_512_to_1023_bytes_hi; + u32 rx_packets_1024_to_1518_bytes_lo; + u32 rx_packets_1024_to_1518_bytes_hi; + u32 rx_packets_1519_to_2047_bytes_lo; + u32 rx_packets_1519_to_2047_bytes_hi; + u32 rx_packets_2048_to_4095_bytes_lo; + u32 rx_packets_2048_to_4095_bytes_hi; + u32 rx_packets_4096_to_8191_bytes_lo; + u32 rx_packets_4096_to_8191_bytes_hi; + u32 rx_packets_8192_to_9216_bytes_lo; + u32 rx_packets_8192_to_9216_bytes_hi; +}; + +struct pport_stats_params { + u16 pport_num; + u8 rsvd; + u8 reset_stats; +}; + +struct lancer_cmd_req_pport_stats { + struct be_cmd_req_hdr hdr; + union { + struct pport_stats_params params; + u8 rsvd[sizeof(struct lancer_cmd_pport_stats)]; + } cmd_params; +}; + +struct lancer_cmd_resp_pport_stats { + struct be_cmd_resp_hdr hdr; + struct lancer_cmd_pport_stats pport_stats; +}; + +static inline struct lancer_cmd_pport_stats* + pport_stats_from_cmd(struct be_adapter *adapter) +{ + struct lancer_cmd_resp_pport_stats *cmd = adapter->stats_cmd.va; + return &cmd->pport_stats; +} + struct be_cmd_req_get_cntl_addnl_attribs { struct be_cmd_req_hdr hdr; u8 rsvd[8]; @@ -1258,6 +1453,8 @@ extern int be_cmd_link_status_query(struct be_adapter *adapter, extern int be_cmd_reset(struct be_adapter *adapter); extern int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd); +extern int lancer_cmd_get_pport_stats(struct be_adapter *adapter, + struct be_dma_mem *nonemb_cmd); extern int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver); extern int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd); diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index cff2cca3087d..93be84ce9bad 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -351,14 +351,73 @@ static void populate_be3_stats(struct be_adapter *adapter) adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops; } +static void populate_lancer_stats(struct be_adapter *adapter) +{ + struct be_drv_stats *drvs = &adapter->drv_stats; + struct lancer_cmd_pport_stats *pport_stats = pport_stats_from_cmd + (adapter); + drvs->rx_priority_pause_frames = 0; + drvs->pmem_fifo_overflow_drop = 0; + drvs->rx_pause_frames = + make_64bit_val(pport_stats->rx_pause_frames_lo, + pport_stats->rx_pause_frames_hi); + drvs->rx_crc_errors = make_64bit_val(pport_stats->rx_crc_errors_hi, + pport_stats->rx_crc_errors_lo); + drvs->rx_control_frames = + make_64bit_val(pport_stats->rx_control_frames_hi, + pport_stats->rx_control_frames_lo); + drvs->rx_in_range_errors = pport_stats->rx_in_range_errors; + drvs->rx_frame_too_long = + make_64bit_val(pport_stats->rx_internal_mac_errors_hi, + pport_stats->rx_frames_too_long_lo); + drvs->rx_dropped_runt = pport_stats->rx_dropped_runt; + drvs->rx_ip_checksum_errs = pport_stats->rx_ip_checksum_errors; + drvs->rx_tcp_checksum_errs = pport_stats->rx_tcp_checksum_errors; + drvs->rx_udp_checksum_errs = pport_stats->rx_udp_checksum_errors; + drvs->rx_dropped_tcp_length = + pport_stats->rx_dropped_invalid_tcp_length; + drvs->rx_dropped_too_small = pport_stats->rx_dropped_too_small; + drvs->rx_dropped_too_short = pport_stats->rx_dropped_too_short; + drvs->rx_out_range_errors = pport_stats->rx_out_of_range_errors; + drvs->rx_dropped_header_too_small = + pport_stats->rx_dropped_header_too_small; + drvs->rx_input_fifo_overflow_drop = pport_stats->rx_fifo_overflow; + drvs->rx_address_match_errors = pport_stats->rx_address_match_errors; + drvs->rx_alignment_symbol_errors = + make_64bit_val(pport_stats->rx_symbol_errors_hi, + pport_stats->rx_symbol_errors_lo); + drvs->rxpp_fifo_overflow_drop = pport_stats->rx_fifo_overflow; + drvs->tx_pauseframes = make_64bit_val(pport_stats->tx_pause_frames_hi, + pport_stats->tx_pause_frames_lo); + drvs->tx_controlframes = + make_64bit_val(pport_stats->tx_control_frames_hi, + pport_stats->tx_control_frames_lo); + drvs->jabber_events = pport_stats->rx_jabbers; + drvs->rx_drops_no_pbuf = 0; + drvs->rx_drops_no_txpb = 0; + drvs->rx_drops_no_erx_descr = 0; + drvs->rx_drops_invalid_ring = pport_stats->rx_drops_invalid_queue; + drvs->forwarded_packets = make_64bit_val(pport_stats->num_forwards_hi, + pport_stats->num_forwards_lo); + drvs->rx_drops_mtu = make_64bit_val(pport_stats->rx_drops_mtu_hi, + pport_stats->rx_drops_mtu_lo); + drvs->rx_drops_no_tpre_descr = 0; + drvs->rx_drops_too_many_frags = + make_64bit_val(pport_stats->rx_drops_too_many_frags_hi, + pport_stats->rx_drops_too_many_frags_lo); +} void be_parse_stats(struct be_adapter *adapter) { - if (adapter->generation == BE_GEN3) - populate_be3_stats(adapter); - else + if (adapter->generation == BE_GEN3) { + if (lancer_chip(adapter)) + populate_lancer_stats(adapter); + else + populate_be3_stats(adapter); + } else { populate_be2_stats(adapter); + } } void netdev_stats_update(struct be_adapter *adapter) @@ -375,10 +434,12 @@ void netdev_stats_update(struct be_adapter *adapter) dev_stats->multicast += rx_stats(rxo)->rx_mcast_pkts; /* no space in linux buffers: best possible approximation */ if (adapter->generation == BE_GEN3) { - struct be_erx_stats_v1 *erx_stats = + if (!(lancer_chip(adapter))) { + struct be_erx_stats_v1 *erx_stats = be_erx_stats_from_cmd(adapter); - dev_stats->rx_dropped += + dev_stats->rx_dropped += erx_stats->rx_drops_no_fragments[rxo->q.id]; + } } else { struct be_erx_stats_v0 *erx_stats = be_erx_stats_from_cmd(adapter); @@ -2022,9 +2083,13 @@ static void be_worker(struct work_struct *work) goto reschedule; } - if (!adapter->stats_cmd_sent) - be_cmd_get_stats(adapter, &adapter->stats_cmd); - + if (!adapter->stats_cmd_sent) { + if (lancer_chip(adapter)) + lancer_cmd_get_pport_stats(adapter, + &adapter->stats_cmd); + else + be_cmd_get_stats(adapter, &adapter->stats_cmd); + } be_tx_rate_update(adapter); for_all_rx_queues(adapter, rxo, i) { @@ -2944,10 +3009,14 @@ static int be_stats_init(struct be_adapter *adapter) { struct be_dma_mem *cmd = &adapter->stats_cmd; - if (adapter->generation == BE_GEN2) + if (adapter->generation == BE_GEN2) { cmd->size = sizeof(struct be_cmd_req_get_stats_v0); - else - cmd->size = sizeof(struct be_cmd_req_get_stats_v1); + } else { + if (lancer_chip(adapter)) + cmd->size = sizeof(struct lancer_cmd_req_pport_stats); + else + cmd->size = sizeof(struct be_cmd_req_get_stats_v1); + } cmd->va = dma_alloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma, GFP_KERNEL); if (cmd->va == NULL) -- cgit v1.2.3-58-ga151 From 485bf569ba798b4702bc2efbfd3a355fe2c8db04 Mon Sep 17 00:00:00 2001 From: Shripad Nunjundarao Date: Mon, 16 May 2011 07:36:59 +0000 Subject: be2net: FW download for Lancer Added implementation of FW download feature for Lancer. Signed-off-by: Shripad Nunjundarao Signed-off-by: Sevin Xavier Signed-off-by: Padmanabh Ratnakar Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 78 ++++++++++++++++++++++++++- drivers/net/benet/be_cmds.h | 36 +++++++++++++ drivers/net/benet/be_main.c | 129 +++++++++++++++++++++++++++++++++++++------- 3 files changed, 223 insertions(+), 20 deletions(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index aaef0c731b9a..2463b1c97922 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -71,7 +71,8 @@ static int be_mcc_compl_process(struct be_adapter *adapter, compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & CQE_STATUS_COMPL_MASK; - if ((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) && + if (((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) || + (compl->tag0 == OPCODE_COMMON_WRITE_OBJECT)) && (compl->tag1 == CMD_SUBSYSTEM_COMMON)) { adapter->flash_status = compl_status; complete(&adapter->flash_compl); @@ -1801,6 +1802,81 @@ err: return status; } +int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, + u32 data_size, u32 data_offset, const char *obj_name, + u32 *data_written, u8 *addn_status) +{ + struct be_mcc_wrb *wrb; + struct lancer_cmd_req_write_object *req; + struct lancer_cmd_resp_write_object *resp; + void *ctxt = NULL; + int status; + + spin_lock_bh(&adapter->mcc_lock); + adapter->flash_status = 0; + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err_unlock; + } + + req = embedded_payload(wrb); + + be_wrb_hdr_prepare(wrb, sizeof(struct lancer_cmd_req_write_object), + true, 1, OPCODE_COMMON_WRITE_OBJECT); + wrb->tag1 = CMD_SUBSYSTEM_COMMON; + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_WRITE_OBJECT, + sizeof(struct lancer_cmd_req_write_object)); + + ctxt = &req->context; + AMAP_SET_BITS(struct amap_lancer_write_obj_context, + write_length, ctxt, data_size); + + if (data_size == 0) + AMAP_SET_BITS(struct amap_lancer_write_obj_context, + eof, ctxt, 1); + else + AMAP_SET_BITS(struct amap_lancer_write_obj_context, + eof, ctxt, 0); + + be_dws_cpu_to_le(ctxt, sizeof(req->context)); + req->write_offset = cpu_to_le32(data_offset); + strcpy(req->object_name, obj_name); + req->descriptor_count = cpu_to_le32(1); + req->buf_len = cpu_to_le32(data_size); + req->addr_low = cpu_to_le32((cmd->dma + + sizeof(struct lancer_cmd_req_write_object)) + & 0xFFFFFFFF); + req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma + + sizeof(struct lancer_cmd_req_write_object))); + + be_mcc_notify(adapter); + spin_unlock_bh(&adapter->mcc_lock); + + if (!wait_for_completion_timeout(&adapter->flash_compl, + msecs_to_jiffies(12000))) + status = -1; + else + status = adapter->flash_status; + + resp = embedded_payload(wrb); + if (!status) { + *data_written = le32_to_cpu(resp->actual_write_len); + } else { + *addn_status = resp->additional_status; + status = resp->status; + } + + return status; + +err_unlock: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} + int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, u32 flash_type, u32 flash_opcode, u32 buf_size) { diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 9cff226c94f1..8148cc66cbe9 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -193,6 +193,7 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_GET_PHY_DETAILS 102 #define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103 #define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121 +#define OPCODE_COMMON_WRITE_OBJECT 172 #define OPCODE_ETH_RSS_CONFIG 1 #define OPCODE_ETH_ACPI_CONFIG 2 @@ -1131,6 +1132,36 @@ struct be_cmd_write_flashrom { struct flashrom_params params; }; +/**************** Lancer Firmware Flash ************/ +struct amap_lancer_write_obj_context { + u8 write_length[24]; + u8 reserved1[7]; + u8 eof; +} __packed; + +struct lancer_cmd_req_write_object { + struct be_cmd_req_hdr hdr; + u8 context[sizeof(struct amap_lancer_write_obj_context) / 8]; + u32 write_offset; + u8 object_name[104]; + u32 descriptor_count; + u32 buf_len; + u32 addr_low; + u32 addr_high; +}; + +struct lancer_cmd_resp_write_object { + u8 opcode; + u8 subsystem; + u8 rsvd1[2]; + u8 status; + u8 additional_status; + u8 rsvd2[2]; + u32 resp_len; + u32 actual_resp_len; + u32 actual_write_len; +}; + /************************ WOL *******************************/ struct be_cmd_req_acpi_wol_magic_config{ struct be_cmd_req_hdr hdr; @@ -1481,6 +1512,11 @@ extern int be_cmd_get_beacon_state(struct be_adapter *adapter, extern int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, u32 flash_oper, u32 flash_opcode, u32 buf_size); +extern int lancer_cmd_write_object(struct be_adapter *adapter, + struct be_dma_mem *cmd, + u32 data_size, u32 data_offset, + const char *obj_name, + u32 *data_written, u8 *addn_status); int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, int offset); extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 93be84ce9bad..7322a511e936 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2712,7 +2712,6 @@ static int be_flash_data(struct be_adapter *adapter, "cmd to write to flash rom failed.\n"); return -1; } - yield(); } } return 0; @@ -2730,32 +2729,98 @@ static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr) return 0; } -int be_load_fw(struct be_adapter *adapter, u8 *func) +static int lancer_fw_download(struct be_adapter *adapter, + const struct firmware *fw) { - char fw_file[ETHTOOL_FLASH_MAX_FILENAME]; - const struct firmware *fw; - struct flash_file_hdr_g2 *fhdr; - struct flash_file_hdr_g3 *fhdr3; - struct image_hdr *img_hdr_ptr = NULL; +#define LANCER_FW_DOWNLOAD_CHUNK (32 * 1024) +#define LANCER_FW_DOWNLOAD_LOCATION "/prg" struct be_dma_mem flash_cmd; - int status, i = 0, num_imgs = 0; - const u8 *p; + struct lancer_cmd_req_write_object *req; + const u8 *data_ptr = NULL; + u8 *dest_image_ptr = NULL; + size_t image_size = 0; + u32 chunk_size = 0; + u32 data_written = 0; + u32 offset = 0; + int status = 0; + u8 add_status = 0; - if (!netif_running(adapter->netdev)) { + if (!IS_ALIGNED(fw->size, sizeof(u32))) { dev_err(&adapter->pdev->dev, - "Firmware load not allowed (interface is down)\n"); - return -EPERM; + "FW Image not properly aligned. " + "Length must be 4 byte aligned.\n"); + status = -EINVAL; + goto lancer_fw_exit; } - strcpy(fw_file, func); + flash_cmd.size = sizeof(struct lancer_cmd_req_write_object) + + LANCER_FW_DOWNLOAD_CHUNK; + flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size, + &flash_cmd.dma, GFP_KERNEL); + if (!flash_cmd.va) { + status = -ENOMEM; + dev_err(&adapter->pdev->dev, + "Memory allocation failure while flashing\n"); + goto lancer_fw_exit; + } - status = request_firmware(&fw, fw_file, &adapter->pdev->dev); - if (status) - goto fw_exit; + req = flash_cmd.va; + dest_image_ptr = flash_cmd.va + + sizeof(struct lancer_cmd_req_write_object); + image_size = fw->size; + data_ptr = fw->data; + + while (image_size) { + chunk_size = min_t(u32, image_size, LANCER_FW_DOWNLOAD_CHUNK); + + /* Copy the image chunk content. */ + memcpy(dest_image_ptr, data_ptr, chunk_size); + + status = lancer_cmd_write_object(adapter, &flash_cmd, + chunk_size, offset, LANCER_FW_DOWNLOAD_LOCATION, + &data_written, &add_status); + + if (status) + break; + + offset += data_written; + data_ptr += data_written; + image_size -= data_written; + } + + if (!status) { + /* Commit the FW written */ + status = lancer_cmd_write_object(adapter, &flash_cmd, + 0, offset, LANCER_FW_DOWNLOAD_LOCATION, + &data_written, &add_status); + } + + dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va, + flash_cmd.dma); + if (status) { + dev_err(&adapter->pdev->dev, + "Firmware load error. " + "Status code: 0x%x Additional Status: 0x%x\n", + status, add_status); + goto lancer_fw_exit; + } + + dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n"); +lancer_fw_exit: + return status; +} + +static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) +{ + struct flash_file_hdr_g2 *fhdr; + struct flash_file_hdr_g3 *fhdr3; + struct image_hdr *img_hdr_ptr = NULL; + struct be_dma_mem flash_cmd; + const u8 *p; + int status = 0, i = 0, num_imgs = 0; p = fw->data; fhdr = (struct flash_file_hdr_g2 *) p; - dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file); flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size, @@ -2764,7 +2829,7 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) status = -ENOMEM; dev_err(&adapter->pdev->dev, "Memory allocation failure while flashing\n"); - goto fw_exit; + goto be_fw_exit; } if ((adapter->generation == BE_GEN3) && @@ -2792,11 +2857,37 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) flash_cmd.dma); if (status) { dev_err(&adapter->pdev->dev, "Firmware load error\n"); - goto fw_exit; + goto be_fw_exit; } dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n"); +be_fw_exit: + return status; +} + +int be_load_fw(struct be_adapter *adapter, u8 *fw_file) +{ + const struct firmware *fw; + int status; + + if (!netif_running(adapter->netdev)) { + dev_err(&adapter->pdev->dev, + "Firmware load not allowed (interface is down)\n"); + return -1; + } + + status = request_firmware(&fw, fw_file, &adapter->pdev->dev); + if (status) + goto fw_exit; + + dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file); + + if (lancer_chip(adapter)) + status = lancer_fw_download(adapter, fw); + else + status = be_fw_download(adapter, fw); + fw_exit: release_firmware(fw); return status; -- cgit v1.2.3-58-ga151 From 5173cc057787560c127c6e9737f308c833dc4ff3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 16 May 2011 08:37:37 +0000 Subject: ipv4: more compliant RFC 3168 support Commit 6623e3b24a5e (ipv4: IP defragmentation must be ECN aware) was an attempt to not lose "Congestion Experienced" (CE) indications when performing datagram defragmentation. Stefanos Harhalakis raised the point that RFC 3168 requirements were not completely met by this commit. In particular, we MUST detect invalid combinations and eventually drop illegal frames. Reported-by: Stefanos Harhalakis Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/ip_fragment.c | 60 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index b1d282f11be7..9e1458d3e465 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -77,22 +77,42 @@ struct ipq { struct inet_peer *peer; }; -#define IPFRAG_ECN_CLEAR 0x01 /* one frag had INET_ECN_NOT_ECT */ -#define IPFRAG_ECN_SET_CE 0x04 /* one frag had INET_ECN_CE */ +/* RFC 3168 support : + * We want to check ECN values of all fragments, do detect invalid combinations. + * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value. + */ +enum { + IPFRAG_ECN_NOT_ECT = 0x01, /* one frag had ECN_NOT_ECT */ + IPFRAG_ECN_ECT_1 = 0x02, /* one frag had ECN_ECT_1 */ + IPFRAG_ECN_ECT_0 = 0x04, /* one frag had ECN_ECT_0 */ + IPFRAG_ECN_CE = 0x08, /* one frag had ECN_CE */ +}; static inline u8 ip4_frag_ecn(u8 tos) { - tos = (tos & INET_ECN_MASK) + 1; - /* - * After the last operation we have (in binary): - * INET_ECN_NOT_ECT => 001 - * INET_ECN_ECT_1 => 010 - * INET_ECN_ECT_0 => 011 - * INET_ECN_CE => 100 - */ - return (tos & 2) ? 0 : tos; + return 1 << (tos & INET_ECN_MASK); } +/* Given the OR values of all fragments, apply RFC 3168 5.3 requirements + * Value : 0xff if frame should be dropped. + * 0 or INET_ECN_CE value, to be ORed in to final iph->tos field + */ +static const u8 ip4_frag_ecn_table[16] = { + /* at least one fragment had CE, and others ECT_0 or ECT_1 */ + [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0] = INET_ECN_CE, + [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1] = INET_ECN_CE, + [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = INET_ECN_CE, + + /* invalid combinations : drop frame */ + [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE] = 0xff, + [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0] = 0xff, + [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_1] = 0xff, + [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff, + [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0] = 0xff, + [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1] = 0xff, + [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff, +}; + static struct inet_frags ip4_frags; int ip_frag_nqueues(struct net *net) @@ -524,9 +544,15 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, int len; int ihlen; int err; + u8 ecn; ipq_kill(qp); + ecn = ip4_frag_ecn_table[qp->ecn]; + if (unlikely(ecn == 0xff)) { + err = -EINVAL; + goto out_fail; + } /* Make the one we just received the head. */ if (prev) { head = prev->next; @@ -605,17 +631,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, iph = ip_hdr(head); iph->frag_off = 0; iph->tot_len = htons(len); - /* RFC3168 5.3 Fragmentation support - * If one fragment had INET_ECN_NOT_ECT, - * reassembled frame also has INET_ECN_NOT_ECT - * Elif one fragment had INET_ECN_CE - * reassembled frame also has INET_ECN_CE - */ - if (qp->ecn & IPFRAG_ECN_CLEAR) - iph->tos &= ~INET_ECN_MASK; - else if (qp->ecn & IPFRAG_ECN_SET_CE) - iph->tos |= INET_ECN_CE; - + iph->tos |= ecn; IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS); qp->q.fragments = NULL; qp->q.fragments_tail = NULL; -- cgit v1.2.3-58-ga151 From 2142c131a3e290ae350f8a0b0d354c0585a96df1 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Mon, 16 May 2011 11:53:49 -0700 Subject: net: convert to new cpumask API We plan to remove cpu_xx() old api later. Thus this patch convert it. This patch has no functional change. Signed-off-by: KOSAKI Motohiro Signed-off-by: David S. Miller --- net/core/net-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 381813eae46c..1b122177c8fa 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -964,7 +964,7 @@ static ssize_t store_xps_map(struct netdev_queue *queue, } else pos = map_len = alloc_len = 0; - need_set = cpu_isset(cpu, *mask) && cpu_online(cpu); + need_set = cpumask_test_cpu(cpu, mask) && cpu_online(cpu); #ifdef CONFIG_NUMA if (need_set) { if (numa_node == -2) -- cgit v1.2.3-58-ga151 From e4abce8538496ba90cb89909894ea42e00f96a7d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 16 May 2011 18:51:24 +0100 Subject: sfc: Use netif_device_{detach,attach}() around reset and self-test We need to keep the TX queues stopped throughout a reset, without triggering the TX watchdog and regardless of the link state. The proper way to do this is to use netif_device_{detach,attach}() just as we do around suspend/resume, rather than the current bodge of faking link-down. Since we also need to do this during an offline self-test and we perform a reset during that, add these function calls outside of efx_reset_down() and efx_reset_up(). Signed-off-by: Ben Hutchings --- drivers/net/sfc/efx.c | 9 +++------ drivers/net/sfc/net_driver.h | 4 +--- drivers/net/sfc/selftest.c | 11 +++++------ drivers/net/sfc/tx.c | 9 +++++---- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 796c47e03f65..05502b359b9e 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -798,11 +798,6 @@ void efx_link_status_changed(struct efx_nic *efx) if (!netif_running(efx->net_dev)) return; - if (efx->port_inhibited) { - netif_carrier_off(efx->net_dev); - return; - } - if (link_state->up != netif_carrier_ok(efx->net_dev)) { efx->n_link_state_changes++; @@ -1450,7 +1445,7 @@ static void efx_start_all(struct efx_nic *efx) * restart the transmit interface early so the watchdog timer stops */ efx_start_port(efx); - if (efx_dev_registered(efx) && !efx->port_inhibited) + if (efx_dev_registered(efx) && netif_device_present(efx->net_dev)) netif_tx_wake_all_queues(efx->net_dev); efx_for_each_channel(channel, efx) @@ -2114,6 +2109,7 @@ int efx_reset(struct efx_nic *efx, enum reset_type method) netif_info(efx, drv, efx->net_dev, "resetting (%s)\n", RESET_TYPE(method)); + netif_device_detach(efx->net_dev); efx_reset_down(efx, method); rc = efx->type->reset(efx, method); @@ -2147,6 +2143,7 @@ out: efx->state = STATE_DISABLED; } else { netif_dbg(efx, drv, efx->net_dev, "reset complete\n"); + netif_device_attach(efx->net_dev); } return rc; } diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 5718260298c4..ce9697bac1b9 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -670,13 +670,12 @@ struct efx_filter_state; * @mtd_list: List of MTDs attached to the NIC * @nic_data: Hardware dependent state * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode, - * @port_inhibited, efx_monitor() and efx_reconfigure_port() + * efx_monitor() and efx_reconfigure_port() * @port_enabled: Port enabled indicator. * Serialises efx_stop_all(), efx_start_all(), efx_monitor() and * efx_mac_work() with kernel interfaces. Safe to read under any * one of the rtnl_lock, mac_lock, or netif_tx_lock, but all three must * be held to modify it. - * @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock * @port_initialized: Port initialized? * @net_dev: Operating system network device. Consider holding the rtnl lock * @stats_buffer: DMA buffer for statistics @@ -764,7 +763,6 @@ struct efx_nic { struct mutex mac_lock; struct work_struct mac_work; bool port_enabled; - bool port_inhibited; bool port_initialized; struct net_device *net_dev; diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index 50ad3bcaf68a..822f6c2a6a7c 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c @@ -695,12 +695,12 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, /* Offline (i.e. disruptive) testing * This checks MAC and PHY loopback on the specified port. */ - /* force the carrier state off so the kernel doesn't transmit during - * the loopback test, and the watchdog timeout doesn't fire. Also put - * falcon into loopback for the register test. + /* Detach the device so the kernel doesn't transmit during the + * loopback test and the watchdog timeout doesn't fire. */ + netif_device_detach(efx->net_dev); + mutex_lock(&efx->mac_lock); - efx->port_inhibited = true; if (efx->loopback_modes) { /* We need the 312 clock from the PHY to test the XMAC * registers, so move into XGMII loopback if available */ @@ -750,12 +750,11 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, /* restore the PHY to the previous state */ mutex_lock(&efx->mac_lock); efx->phy_mode = phy_mode; - efx->port_inhibited = false; efx->loopback_mode = loopback_mode; __efx_reconfigure_port(efx); mutex_unlock(&efx->mac_lock); - netif_tx_wake_all_queues(efx->net_dev); + netif_device_attach(efx->net_dev); return rc_test; } diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c index d2c85dfdf3bf..84eb99e0f8d2 100644 --- a/drivers/net/sfc/tx.c +++ b/drivers/net/sfc/tx.c @@ -205,7 +205,9 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb) goto unwind; } smp_mb(); - netif_tx_start_queue(tx_queue->core_txq); + if (likely(!efx->loopback_selftest)) + netif_tx_start_queue( + tx_queue->core_txq); } insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask; @@ -338,8 +340,7 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb, struct efx_tx_queue *tx_queue; unsigned index, type; - if (unlikely(efx->port_inhibited)) - return NETDEV_TX_BUSY; + EFX_WARN_ON_PARANOID(!netif_device_present(net_dev)); index = skb_get_queue_mapping(skb); type = skb->ip_summed == CHECKSUM_PARTIAL ? EFX_TXQ_TYPE_OFFLOAD : 0; @@ -436,7 +437,7 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index) smp_mb(); if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) && likely(efx->port_enabled) && - likely(!efx->port_inhibited)) { + likely(netif_device_present(efx->net_dev))) { fill_level = tx_queue->insert_count - tx_queue->read_count; if (fill_level < EFX_TXQ_THRESHOLD(efx)) { EFX_BUG_ON_PARANOID(!efx_dev_registered(efx)); -- cgit v1.2.3-58-ga151 From 6dcae1eaee2b437536b2fe928a609f9589691ebf Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 16 May 2011 23:09:26 -0400 Subject: bluetooth: Fix warnings in l2cap_core.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit net/bluetooth/l2cap_core.c: In function ‘l2cap_recv_frame’: net/bluetooth/l2cap_core.c:3758:15: warning: ‘sk’ may be used uninitialized in this function net/bluetooth/l2cap_core.c:3758:15: note: ‘sk’ was declared here net/bluetooth/l2cap_core.c:3791:15: warning: ‘sk’ may be used uninitialized in this function net/bluetooth/l2cap_core.c:3791:15: note: ‘sk’ was declared here Signed-off-by: David S. Miller --- net/bluetooth/l2cap_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 4f3bc741183c..a86f9ba4f05c 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -3755,7 +3755,7 @@ done: static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) { - struct sock *sk; + struct sock *sk = NULL; struct l2cap_chan *chan; chan = l2cap_global_chan_by_psm(0, psm, conn->src); @@ -3788,7 +3788,7 @@ done: static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb) { - struct sock *sk; + struct sock *sk = NULL; struct l2cap_chan *chan; chan = l2cap_global_chan_by_scid(0, cid, conn->src); -- cgit v1.2.3-58-ga151 From 372b2312010bece1e36f577d6c99a6193ec54cbd Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 17 May 2011 13:56:59 -0400 Subject: net: use hlist_del_rcu() in dev_change_name() Using plain hlist_del() in dev_change_name() is wrong since a concurrent reader can crash trying to dereference LIST_POISON1. Bug introduced in commit 72c9528bab94 (net: Introduce dev_get_by_name_rcu()) Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index b624fe4d9bd7..30a4078b3fa2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1007,7 +1007,7 @@ rollback: } write_lock_bh(&dev_base_lock); - hlist_del(&dev->name_hlist); + hlist_del_rcu(&dev->name_hlist); write_unlock_bh(&dev_base_lock); synchronize_rcu(); -- cgit v1.2.3-58-ga151 From f56e03e8dc149bf0ac2888d6843584f48c8700fc Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Tue, 17 May 2011 00:16:56 +0000 Subject: net: ping: fix build failure If CONFIG_PROC_SYSCTL=n the building process fails: ping.c:(.text+0x52af3): undefined reference to `inet_get_ping_group_range_net' Moved inet_get_ping_group_range_net() to ping.c. Reported-by: Randy Dunlap Signed-off-by: Vasiliy Kulikov Acked-by: Eric Dumazet Acked-by: Randy Dunlap Signed-off-by: David S. Miller --- include/net/ping.h | 2 -- net/ipv4/ping.c | 13 +++++++++++++ net/ipv4/sysctl_net_ipv4.c | 12 ------------ 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/net/ping.h b/include/net/ping.h index 23062c369c62..682b5ae9af51 100644 --- a/include/net/ping.h +++ b/include/net/ping.h @@ -44,8 +44,6 @@ extern struct proto ping_prot; extern void ping_rcv(struct sk_buff *); extern void ping_err(struct sk_buff *, u32 info); -extern void inet_get_ping_group_range_net(struct net *net, unsigned int *low, unsigned int *high); - #ifdef CONFIG_PROC_FS extern int __init ping_proc_init(void); extern void ping_proc_exit(void); diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 41836ab6c200..6a21da906532 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -187,6 +187,19 @@ exit: return sk; } +static void inet_get_ping_group_range_net(struct net *net, gid_t *low, gid_t *high) +{ + gid_t *data = net->ipv4.sysctl_ping_group_range; + unsigned seq; + do { + seq = read_seqbegin(&sysctl_local_ports.lock); + + *low = data[0]; + *high = data[1]; + } while (read_seqretry(&sysctl_local_ports.lock, seq)); +} + + static int ping_init_sock(struct sock *sk) { struct net *net = sock_net(sk); diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 28e8273bbef8..57d0752e239a 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -73,18 +73,6 @@ static int ipv4_local_port_range(ctl_table *table, int write, } -void inet_get_ping_group_range_net(struct net *net, gid_t *low, gid_t *high) -{ - gid_t *data = net->ipv4.sysctl_ping_group_range; - unsigned seq; - do { - seq = read_seqbegin(&sysctl_local_ports.lock); - - *low = data[0]; - *high = data[1]; - } while (read_seqretry(&sysctl_local_ports.lock, seq)); -} - void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, gid_t *high) { gid_t *data = table->data; -- cgit v1.2.3-58-ga151 From 11e73de7ccc1c9c61c65f914a214cb6467966a51 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 16 May 2011 23:59:48 +0000 Subject: xen: netback: use __CONST_RING_SIZE not __RING_SIZE The later causes warnings with gcc 4.5+. __CONST_RING_SIZE was introduced in 667c78afaec0 to fix this but as netback wasn't upstream at the time it did not benefit, hence: CC drivers/net/xen-netback/netback.o drivers/net/xen-netback/netback.c:110:37: warning: variably modified 'grant_copy_op' at file scope [enabled by default] drivers/net/xen-netback/netback.c:111:30: warning: variably modified 'meta' at file scope [enabled by default] drivers/net/xen-netback/netback.c: In function 'xen_netbk_rx_action': drivers/net/xen-netback/netback.c:584:6: warning: variable 'irq' set but not used [-Wunused-but-set-variable] Thanks to Witold Baryluk for pointing this out. Signed-off-by: Ian Campbell Cc: Witold Baryluk Signed-off-by: David S. Miller --- drivers/net/xen-netback/common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 8753e6ddff8f..161f207786a4 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -106,8 +106,8 @@ struct xenvif { wait_queue_head_t waiting_to_free; }; -#define XEN_NETIF_TX_RING_SIZE __RING_SIZE((struct xen_netif_tx_sring *)0, PAGE_SIZE) -#define XEN_NETIF_RX_RING_SIZE __RING_SIZE((struct xen_netif_rx_sring *)0, PAGE_SIZE) +#define XEN_NETIF_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE) +#define XEN_NETIF_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE) struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, -- cgit v1.2.3-58-ga151 From b9eb8b8752804cecbacdb4d24b52e823cf07f107 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 17 May 2011 15:38:57 -0400 Subject: net: recvmmsg: Strip MSG_WAITFORONE when calling recvmsg recvmmsg fails on a raw socket with EINVAL. The reason for this is packet_recvmsg checks the incoming flags: err = -EINVAL; if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT|MSG_ERRQUEUE)) goto out; This patch strips out MSG_WAITFORONE when calling recvmmsg which fixes the issue. Signed-off-by: Anton Blanchard Cc: stable@kernel.org [2.6.34+] Signed-off-by: David S. Miller --- net/socket.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/socket.c b/net/socket.c index 310d16b1b3c9..65b2310a2cb2 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2122,14 +2122,16 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, */ if (MSG_CMSG_COMPAT & flags) { err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry, - &msg_sys, flags, datagrams); + &msg_sys, flags & ~MSG_WAITFORONE, + datagrams); if (err < 0) break; err = __put_user(err, &compat_entry->msg_len); ++compat_entry; } else { err = __sys_recvmsg(sock, (struct msghdr __user *)entry, - &msg_sys, flags, datagrams); + &msg_sys, flags & ~MSG_WAITFORONE, + datagrams); if (err < 0) break; err = put_user(err, &entry->msg_len); -- cgit v1.2.3-58-ga151 From 604ae14ffb6d75d6eef4757859226b758d6bf9e3 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 16 May 2011 10:37:39 +0000 Subject: net: Change netdev_fix_features messages loglevel Cool, how about we make 'Features changed' debug as well? This way userspace can't fill up the log just by tweaking tun features with an ioctl. Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 30a4078b3fa2..acd742379344 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5258,7 +5258,7 @@ void netdev_update_features(struct net_device *dev) if (dev->features == features) return; - netdev_info(dev, "Features changed: 0x%08x -> 0x%08x\n", + netdev_dbg(dev, "Features changed: 0x%08x -> 0x%08x\n", dev->features, features); if (dev->netdev_ops->ndo_set_features) -- cgit v1.2.3-58-ga151 From 7cc31a9ae1477abc79d5992b3afe889f25c50c99 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 17 May 2011 16:50:02 -0400 Subject: net: ethtool: fix IPV6 checksum feature name string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- net/core/ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 74ead9eca126..f33752533119 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -330,7 +330,7 @@ static const char netdev_features_strings[ETHTOOL_DEV_FEATURE_WORDS * 32][ETH_GS /* NETIF_F_IP_CSUM */ "tx-checksum-ipv4", /* NETIF_F_NO_CSUM */ "tx-checksum-unneeded", /* NETIF_F_HW_CSUM */ "tx-checksum-ip-generic", - /* NETIF_F_IPV6_CSUM */ "tx_checksum-ipv6", + /* NETIF_F_IPV6_CSUM */ "tx-checksum-ipv6", /* NETIF_F_HIGHDMA */ "highdma", /* NETIF_F_FRAGLIST */ "tx-scatter-gather-fraglist", /* NETIF_F_HW_VLAN_TX */ "tx-vlan-hw-insert", -- cgit v1.2.3-58-ga151 From 1d1652cbdb9885e4d73972263e4cdbe1b0beebfe Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 17 May 2011 17:28:02 -0400 Subject: ipv4: Don't use enums as bitmasks in ip_fragment.c Noticed by Joe Perches. Signed-off-by: David S. Miller --- net/ipv4/ip_fragment.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 9e1458d3e465..0ad6035f6366 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -81,12 +81,10 @@ struct ipq { * We want to check ECN values of all fragments, do detect invalid combinations. * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value. */ -enum { - IPFRAG_ECN_NOT_ECT = 0x01, /* one frag had ECN_NOT_ECT */ - IPFRAG_ECN_ECT_1 = 0x02, /* one frag had ECN_ECT_1 */ - IPFRAG_ECN_ECT_0 = 0x04, /* one frag had ECN_ECT_0 */ - IPFRAG_ECN_CE = 0x08, /* one frag had ECN_CE */ -}; +#define IPFRAG_ECN_NOT_ECT 0x01 /* one frag had ECN_NOT_ECT */ +#define IPFRAG_ECN_ECT_1 0x02 /* one frag had ECN_ECT_1 */ +#define IPFRAG_ECN_ECT_0 0x04 /* one frag had ECN_ECT_0 */ +#define IPFRAG_ECN_CE 0x08 /* one frag had ECN_CE */ static inline u8 ip4_frag_ecn(u8 tos) { -- cgit v1.2.3-58-ga151 From b56269468483a0255a27126ebc2ae7e321638d7b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 17 May 2011 17:53:22 -0400 Subject: sfc: Don't use enums as a bitmask. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes: drivers/net/sfc/mcdi_mac.c: In function ‘efx_mcdi_set_mac’: drivers/net/sfc/mcdi_mac.c:36:2: warning: case value ‘3’ not in enumerated type ‘enum efx_fc_type’ Signed-off-by: David S. Miller --- drivers/net/sfc/efx.c | 2 +- drivers/net/sfc/efx.h | 2 +- drivers/net/sfc/ethtool.c | 2 +- drivers/net/sfc/mdio_10g.c | 2 +- drivers/net/sfc/mdio_10g.h | 2 +- drivers/net/sfc/net_driver.h | 12 +++++------- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 05502b359b9e..c914729f9554 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -833,7 +833,7 @@ void efx_link_set_advertising(struct efx_nic *efx, u32 advertising) } } -void efx_link_set_wanted_fc(struct efx_nic *efx, enum efx_fc_type wanted_fc) +void efx_link_set_wanted_fc(struct efx_nic *efx, u8 wanted_fc) { efx->wanted_fc = wanted_fc; if (efx->link_advertising) { diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h index 3d83a1f74fef..b0d1209ea18d 100644 --- a/drivers/net/sfc/efx.h +++ b/drivers/net/sfc/efx.h @@ -142,6 +142,6 @@ static inline void efx_schedule_channel(struct efx_channel *channel) extern void efx_link_status_changed(struct efx_nic *efx); extern void efx_link_set_advertising(struct efx_nic *efx, u32); -extern void efx_link_set_wanted_fc(struct efx_nic *efx, enum efx_fc_type); +extern void efx_link_set_wanted_fc(struct efx_nic *efx, u8); #endif /* EFX_EFX_H */ diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 348437a8117e..d229027dc363 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -698,7 +698,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, struct ethtool_pauseparam *pause) { struct efx_nic *efx = netdev_priv(net_dev); - enum efx_fc_type wanted_fc, old_fc; + u8 wanted_fc, old_fc; u32 old_adv; bool reset; int rc = 0; diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index 71159145b4bf..7ab385c8136d 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c @@ -284,7 +284,7 @@ void efx_mdio_an_reconfigure(struct efx_nic *efx) efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); } -enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx) +u8 efx_mdio_get_pause(struct efx_nic *efx) { BUILD_BUG_ON(EFX_FC_AUTO & (EFX_FC_RX | EFX_FC_TX)); diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h index df0703940c83..a97dbbd2de99 100644 --- a/drivers/net/sfc/mdio_10g.h +++ b/drivers/net/sfc/mdio_10g.h @@ -92,7 +92,7 @@ extern void efx_mdio_an_reconfigure(struct efx_nic *efx); /* Get pause parameters from AN if available (otherwise return * requested pause parameters) */ -enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx); +u8 efx_mdio_get_pause(struct efx_nic *efx); /* Wait for specified MMDs to exit reset within a timeout */ extern int efx_mdio_wait_reset_mmds(struct efx_nic *efx, diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index ce9697bac1b9..e8d5f03a89fe 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -449,11 +449,9 @@ enum nic_state { struct efx_nic; /* Pseudo bit-mask flow control field */ -enum efx_fc_type { - EFX_FC_RX = FLOW_CTRL_RX, - EFX_FC_TX = FLOW_CTRL_TX, - EFX_FC_AUTO = 4, -}; +#define EFX_FC_RX FLOW_CTRL_RX +#define EFX_FC_TX FLOW_CTRL_TX +#define EFX_FC_AUTO 4 /** * struct efx_link_state - Current state of the link @@ -465,7 +463,7 @@ enum efx_fc_type { struct efx_link_state { bool up; bool fd; - enum efx_fc_type fc; + u8 fc; unsigned int speed; }; @@ -784,7 +782,7 @@ struct efx_nic { bool promiscuous; union efx_multicast_hash multicast_hash; - enum efx_fc_type wanted_fc; + u8 wanted_fc; atomic_t rx_reset; enum efx_loopback_mode loopback_mode; -- cgit v1.2.3-58-ga151 From abb57ea48fd9431fa320a5c55f73e6b5a44c2efb Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 18 May 2011 02:21:31 -0400 Subject: net: add skb_dst_force() in sock_queue_err_skb() Commit 7fee226ad239 (add a noref bit on skb dst) forgot to use skb_dst_force() on packets queued in sk_error_queue This triggers following warning, for applications using IP_CMSG_PKTINFO receiving one error status ------------[ cut here ]------------ WARNING: at include/linux/skbuff.h:457 ip_cmsg_recv_pktinfo+0xa6/0xb0() Hardware name: 2669UYD Modules linked in: isofs vboxnetadp vboxnetflt nfsd ebtable_nat ebtables lib80211_crypt_ccmp uinput xcbc hdaps tp_smapi thinkpad_ec radeonfb fb_ddc radeon ttm drm_kms_helper drm ipw2200 intel_agp intel_gtt libipw i2c_algo_bit i2c_i801 agpgart rng_core cfbfillrect cfbcopyarea cfbimgblt video raid10 raid1 raid0 linear md_mod vboxdrv Pid: 4697, comm: miredo Not tainted 2.6.39-rc6-00569-g5895198-dirty #22 Call Trace: [] ? printk+0x1d/0x1f [] warn_slowpath_common+0x72/0xa0 [] ? ip_cmsg_recv_pktinfo+0xa6/0xb0 [] ? ip_cmsg_recv_pktinfo+0xa6/0xb0 [] warn_slowpath_null+0x20/0x30 [] ip_cmsg_recv_pktinfo+0xa6/0xb0 [] ip_cmsg_recv+0x127/0x260 [] ? skb_dequeue+0x4d/0x70 [] ? skb_copy_datagram_iovec+0x53/0x300 [] ? sub_preempt_count+0x24/0x50 [] ip_recv_error+0x23d/0x270 [] udp_recvmsg+0x264/0x2b0 [] inet_recvmsg+0xd9/0x130 [] sock_recvmsg+0xf2/0x120 [] ? might_fault+0x4b/0xa0 [] ? verify_iovec+0x4c/0xc0 [] ? sock_recvmsg_nosec+0x100/0x100 [] __sys_recvmsg+0x114/0x1e0 [] ? __lock_acquire+0x365/0x780 [] ? fget_light+0xa6/0x3e0 [] ? fget_light+0xbf/0x3e0 [] ? fget_light+0x2e/0x3e0 [] sys_recvmsg+0x39/0x60 Close bug https://bugzilla.kernel.org/show_bug.cgi?id=34622 Reported-by: Witold Baryluk Signed-off-by: Eric Dumazet CC: Stephen Hemminger Signed-off-by: David S. Miller --- net/core/skbuff.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 7ebeed0a877c..3e934fe96f29 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2993,6 +2993,9 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) skb->destructor = sock_rmem_free; atomic_add(skb->truesize, &sk->sk_rmem_alloc); + /* before exiting rcu section, make sure dst is refcounted */ + skb_dst_force(skb); + skb_queue_tail(&sk->sk_error_queue, skb); if (!sock_flag(sk, SOCK_DEAD)) sk->sk_data_ready(sk, skb->len); -- cgit v1.2.3-58-ga151 From f634a4e7074f66ac3dfaf2cc6786e0ec3080a2d1 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Wed, 18 May 2011 16:51:26 -0400 Subject: wl12xx: fix compilation error when CONFIG_PM is not set There was a compilation error when PM is not enabled: CC [M] drivers/net/wireless/wl12xx/main.o drivers/net/wireless/wl12xx/main.c:3653: error: unknown field 'suspend' specified in initializer drivers/net/wireless/wl12xx/main.c:3653: warning: initialization from incompatible pointer type drivers/net/wireless/wl12xx/main.c:3654: error: unknown field 'resume' specified in initializer drivers/net/wireless/wl12xx/main.c:3654: warning: initialization from incompatible pointer type Fix this by adding #ifdef's in the appropriate places. Cc: Eliad Peller Signed-off-by: Luciano Coelho Signed-off-by: David S. Miller --- drivers/net/wireless/wl12xx/main.c | 4 ++++ drivers/net/wireless/wl12xx/sdio.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 610be03a198b..bc00e52f6445 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1350,6 +1350,7 @@ static struct notifier_block wl1271_dev_notifier = { .notifier_call = wl1271_dev_notify, }; +#ifdef CONFIG_PM static int wl1271_configure_suspend(struct wl1271 *wl) { int ret; @@ -1493,6 +1494,7 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) return 0; } +#endif static int wl1271_op_start(struct ieee80211_hw *hw) { @@ -3650,8 +3652,10 @@ static const struct ieee80211_ops wl1271_ops = { .stop = wl1271_op_stop, .add_interface = wl1271_op_add_interface, .remove_interface = wl1271_op_remove_interface, +#ifdef CONFIG_PM .suspend = wl1271_op_suspend, .resume = wl1271_op_resume, +#endif .config = wl1271_op_config, .prepare_multicast = wl1271_op_prepare_multicast, .configure_filter = wl1271_op_configure_filter, diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 92d29a860fc0..536e5065454b 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -330,6 +330,7 @@ static void __devexit wl1271_remove(struct sdio_func *func) wl1271_free_hw(wl); } +#ifdef CONFIG_PM static int wl1271_suspend(struct device *dev) { /* Tell MMC/SDIO core it's OK to power down the card @@ -385,15 +386,18 @@ static const struct dev_pm_ops wl1271_sdio_pm_ops = { .suspend = wl1271_suspend, .resume = wl1271_resume, }; +#endif static struct sdio_driver wl1271_sdio_driver = { .name = "wl1271_sdio", .id_table = wl1271_devices, .probe = wl1271_probe, .remove = __devexit_p(wl1271_remove), +#ifdef CONFIG_PM .drv = { .pm = &wl1271_sdio_pm_ops, }, +#endif }; static int __init wl1271_init(void) -- cgit v1.2.3-58-ga151 From 60a34277d5da958e7f39a942e0ed1016a904f6c6 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Wed, 18 May 2011 03:28:35 +0000 Subject: qeth: use ndo_set_features callback for initial setup and recovery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch uses the ndo_set_features callback during normal device startup or recovery to turn on hardware RX checksum. Patch was done with much help from Michal Miroslaw, thx!!! Signed-off-by: Frank Blaschka Reviewed-by: Michał Mirosław Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l3_main.c | 77 +++++++++++++---------------------------- 1 file changed, 25 insertions(+), 52 deletions(-) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index bbe7e1c058ab..fd69da3fa6b4 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1417,63 +1417,33 @@ int qeth_l3_set_rx_csum(struct qeth_card *card, int on) int rc = 0; if (on) { - if (card->state != CARD_STATE_DOWN) { - if (!qeth_is_supported(card, - IPA_INBOUND_CHECKSUM)) - return -EPERM; - rc = qeth_l3_send_checksum_command(card); - if (rc) - return -EIO; - } - card->dev->features |= NETIF_F_RXCSUM; + rc = qeth_l3_send_checksum_command(card); + if (rc) + return -EIO; + dev_info(&card->gdev->dev, + "HW Checksumming (inbound) enabled\n"); } else { - if (card->state != CARD_STATE_DOWN) { - rc = qeth_l3_send_simple_setassparms(card, - IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0); - if (rc) - return -EIO; - } - card->dev->features &= ~NETIF_F_RXCSUM; + rc = qeth_l3_send_simple_setassparms(card, + IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0); + if (rc) + return -EIO; } - return rc; + return 0; } static int qeth_l3_start_ipa_checksum(struct qeth_card *card) { - int rc = 0; - QETH_CARD_TEXT(card, 3, "strtcsum"); if (card->dev->features & NETIF_F_RXCSUM) { - /* hw may have changed during offline or recovery */ - if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) { - dev_info(&card->gdev->dev, - "Inbound HW Checksumming not " - "supported on %s,\ncontinuing " - "using Inbound SW Checksumming\n", - QETH_CARD_IFNAME(card)); - goto update_feature; - } - - rc = qeth_l3_send_checksum_command(card); - if (!rc) - dev_info(&card->gdev->dev, - "HW Checksumming (inbound) enabled\n"); - else - goto update_feature; - } else - dev_info(&card->gdev->dev, - "Using SW checksumming on %s.\n", - QETH_CARD_IFNAME(card)); + rtnl_lock(); + /* force set_features call */ + card->dev->features &= ~NETIF_F_RXCSUM; + netdev_update_features(card->dev); + rtnl_unlock(); + } return 0; - -update_feature: - rtnl_lock(); - card->dev->features &= ~NETIF_F_RXCSUM; - netdev_update_features(card->dev); - rtnl_unlock(); - return rc; } static int qeth_l3_start_ipa_tx_checksum(struct qeth_card *card) @@ -3196,17 +3166,20 @@ static int qeth_l3_set_features(struct net_device *dev, u32 features) { struct qeth_card *card = dev->ml_priv; u32 changed = dev->features ^ features; - int on; + int err; if (!(changed & NETIF_F_RXCSUM)) return 0; - if (features & NETIF_F_RXCSUM) - on = 1; - else - on = 0; + if (card->state == CARD_STATE_DOWN || + card->state == CARD_STATE_RECOVER) + return 0; + + err = qeth_l3_set_rx_csum(card, features & NETIF_F_RXCSUM); + if (err) + dev->features = features ^ NETIF_F_RXCSUM; - return qeth_l3_set_rx_csum(card, on); + return err; } static const struct ethtool_ops qeth_l3_ethtool_ops = { -- cgit v1.2.3-58-ga151 From 0be6bc62cdd5e1bed75b2122ba7d26fc245b534b Mon Sep 17 00:00:00 2001 From: Shmulik Ravid Date: Wed, 18 May 2011 02:55:31 +0000 Subject: bnx2x: add support for retrieving dcb peer configuration This patch adds support to the bnx2x for retrieving dcb peer (remote) configuration from the embedded DCBX stack. Signed-off-by: Shmulik Ravid Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x.h | 4 ++ drivers/net/bnx2x/bnx2x_dcb.c | 152 +++++++++++++++++++++++++++++++++++------- 2 files changed, 131 insertions(+), 25 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 16a76f074df5..668a578c49e9 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -1242,6 +1242,10 @@ struct bnx2x { /* DCBX Negotiation results */ struct dcbx_features dcbx_local_feat; u32 dcbx_error; +#ifdef BCM_DCBNL + struct dcbx_features dcbx_remote_feat; + u32 dcbx_remote_flags; +#endif u32 pending_max; }; diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c index 0f8309233ff2..410a49e571ac 100644 --- a/drivers/net/bnx2x/bnx2x_dcb.c +++ b/drivers/net/bnx2x/bnx2x_dcb.c @@ -485,6 +485,36 @@ static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp) } } +#ifdef BCM_DCBNL +static int bnx2x_dcbx_read_shmem_remote_mib(struct bnx2x *bp) +{ + struct lldp_remote_mib remote_mib = {0}; + u32 dcbx_remote_mib_offset = SHMEM2_RD(bp, dcbx_remote_mib_offset); + int rc; + + DP(NETIF_MSG_LINK, "dcbx_remote_mib_offset 0x%x\n", + dcbx_remote_mib_offset); + + if (SHMEM_DCBX_REMOTE_MIB_NONE == dcbx_remote_mib_offset) { + BNX2X_ERR("FW doesn't support dcbx_remote_mib_offset\n"); + return -EINVAL; + } + + rc = bnx2x_dcbx_read_mib(bp, (u32 *)&remote_mib, dcbx_remote_mib_offset, + DCBX_READ_REMOTE_MIB); + + if (rc) { + BNX2X_ERR("Faild to read remote mib from FW\n"); + return rc; + } + + /* save features and flags */ + bp->dcbx_remote_feat = remote_mib.features; + bp->dcbx_remote_flags = remote_mib.flags; + return 0; +} +#endif + static int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x *bp) { struct lldp_local_mib local_mib = {0}; @@ -601,6 +631,10 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state) * negotiation results */ bnx2x_dcbnl_update_applist(bp, true); + + /* Read rmeote mib if dcbx is in the FW */ + if (bnx2x_dcbx_read_shmem_remote_mib(bp)) + return; #endif /* Read neg results if dcbx is in the FW */ if (bnx2x_dcbx_read_shmem_neg_results(bp)) @@ -2031,7 +2065,6 @@ static u8 bnx2x_dcbnl_set_dcbx(struct net_device *netdev, u8 state) return 0; } - static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid, u8 *flags) { @@ -2111,31 +2144,100 @@ static u8 bnx2x_dcbnl_set_featcfg(struct net_device *netdev, int featid, return rval; } +static int bnx2x_peer_appinfo(struct net_device *netdev, + struct dcb_peer_app_info *info, u16* app_count) +{ + int i; + struct bnx2x *bp = netdev_priv(netdev); + + DP(NETIF_MSG_LINK, "APP-INFO\n"); + + info->willing = (bp->dcbx_remote_flags & DCBX_APP_REM_WILLING) ?: 0; + info->error = (bp->dcbx_remote_flags & DCBX_APP_RX_ERROR) ?: 0; + *app_count = 0; + + for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++) + if (bp->dcbx_remote_feat.app.app_pri_tbl[i].appBitfield & + DCBX_APP_ENTRY_VALID) + (*app_count)++; + return 0; +} + +static int bnx2x_peer_apptable(struct net_device *netdev, + struct dcb_app *table) +{ + int i, j; + struct bnx2x *bp = netdev_priv(netdev); + + DP(NETIF_MSG_LINK, "APP-TABLE\n"); + + for (i = 0, j = 0; i < DCBX_MAX_APP_PROTOCOL; i++) { + struct dcbx_app_priority_entry *ent = + &bp->dcbx_remote_feat.app.app_pri_tbl[i]; + + if (ent->appBitfield & DCBX_APP_ENTRY_VALID) { + table[j].selector = bnx2x_dcbx_dcbnl_app_idtype(ent); + table[j].priority = bnx2x_dcbx_dcbnl_app_up(ent); + table[j++].protocol = ent->app_id; + } + } + return 0; +} + +static int bnx2x_cee_peer_getpg(struct net_device *netdev, struct cee_pg *pg) +{ + int i; + struct bnx2x *bp = netdev_priv(netdev); + + pg->willing = (bp->dcbx_remote_flags & DCBX_ETS_REM_WILLING) ?: 0; + + for (i = 0; i < CEE_DCBX_MAX_PGS; i++) { + pg->pg_bw[i] = + DCBX_PG_BW_GET(bp->dcbx_remote_feat.ets.pg_bw_tbl, i); + pg->prio_pg[i] = + DCBX_PRI_PG_GET(bp->dcbx_remote_feat.ets.pri_pg_tbl, i); + } + return 0; +} + +static int bnx2x_cee_peer_getpfc(struct net_device *netdev, + struct cee_pfc *pfc) +{ + struct bnx2x *bp = netdev_priv(netdev); + pfc->tcs_supported = bp->dcbx_remote_feat.pfc.pfc_caps; + pfc->pfc_en = bp->dcbx_remote_feat.pfc.pri_en_bitmap; + return 0; +} + const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops = { - .getstate = bnx2x_dcbnl_get_state, - .setstate = bnx2x_dcbnl_set_state, - .getpermhwaddr = bnx2x_dcbnl_get_perm_hw_addr, - .setpgtccfgtx = bnx2x_dcbnl_set_pg_tccfg_tx, - .setpgbwgcfgtx = bnx2x_dcbnl_set_pg_bwgcfg_tx, - .setpgtccfgrx = bnx2x_dcbnl_set_pg_tccfg_rx, - .setpgbwgcfgrx = bnx2x_dcbnl_set_pg_bwgcfg_rx, - .getpgtccfgtx = bnx2x_dcbnl_get_pg_tccfg_tx, - .getpgbwgcfgtx = bnx2x_dcbnl_get_pg_bwgcfg_tx, - .getpgtccfgrx = bnx2x_dcbnl_get_pg_tccfg_rx, - .getpgbwgcfgrx = bnx2x_dcbnl_get_pg_bwgcfg_rx, - .setpfccfg = bnx2x_dcbnl_set_pfc_cfg, - .getpfccfg = bnx2x_dcbnl_get_pfc_cfg, - .setall = bnx2x_dcbnl_set_all, - .getcap = bnx2x_dcbnl_get_cap, - .getnumtcs = bnx2x_dcbnl_get_numtcs, - .setnumtcs = bnx2x_dcbnl_set_numtcs, - .getpfcstate = bnx2x_dcbnl_get_pfc_state, - .setpfcstate = bnx2x_dcbnl_set_pfc_state, - .setapp = bnx2x_dcbnl_set_app_up, - .getdcbx = bnx2x_dcbnl_get_dcbx, - .setdcbx = bnx2x_dcbnl_set_dcbx, - .getfeatcfg = bnx2x_dcbnl_get_featcfg, - .setfeatcfg = bnx2x_dcbnl_set_featcfg, + .getstate = bnx2x_dcbnl_get_state, + .setstate = bnx2x_dcbnl_set_state, + .getpermhwaddr = bnx2x_dcbnl_get_perm_hw_addr, + .setpgtccfgtx = bnx2x_dcbnl_set_pg_tccfg_tx, + .setpgbwgcfgtx = bnx2x_dcbnl_set_pg_bwgcfg_tx, + .setpgtccfgrx = bnx2x_dcbnl_set_pg_tccfg_rx, + .setpgbwgcfgrx = bnx2x_dcbnl_set_pg_bwgcfg_rx, + .getpgtccfgtx = bnx2x_dcbnl_get_pg_tccfg_tx, + .getpgbwgcfgtx = bnx2x_dcbnl_get_pg_bwgcfg_tx, + .getpgtccfgrx = bnx2x_dcbnl_get_pg_tccfg_rx, + .getpgbwgcfgrx = bnx2x_dcbnl_get_pg_bwgcfg_rx, + .setpfccfg = bnx2x_dcbnl_set_pfc_cfg, + .getpfccfg = bnx2x_dcbnl_get_pfc_cfg, + .setall = bnx2x_dcbnl_set_all, + .getcap = bnx2x_dcbnl_get_cap, + .getnumtcs = bnx2x_dcbnl_get_numtcs, + .setnumtcs = bnx2x_dcbnl_set_numtcs, + .getpfcstate = bnx2x_dcbnl_get_pfc_state, + .setpfcstate = bnx2x_dcbnl_set_pfc_state, + .setapp = bnx2x_dcbnl_set_app_up, + .getdcbx = bnx2x_dcbnl_get_dcbx, + .setdcbx = bnx2x_dcbnl_set_dcbx, + .getfeatcfg = bnx2x_dcbnl_get_featcfg, + .setfeatcfg = bnx2x_dcbnl_set_featcfg, + .peer_getappinfo = bnx2x_peer_appinfo, + .peer_getapptable = bnx2x_peer_apptable, + .cee_peer_getpg = bnx2x_cee_peer_getpg, + .cee_peer_getpfc = bnx2x_cee_peer_getpfc, }; #endif /* BCM_DCBNL */ -- cgit v1.2.3-58-ga151 From 12f4d0a8770ab26639091d0b2509b19681daad69 Mon Sep 17 00:00:00 2001 From: Mammatha Edhala Date: Wed, 18 May 2011 03:26:22 +0000 Subject: be2net: Enable SR-IOV for Lancer Enable SR-IOV for Lancer Signed-off-by: Mammatha Edhala Signed-off-by: Padmanabh Ratnakar Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 5 ++++- drivers/net/benet/be_main.c | 17 +++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 0b73dcf26924..a7db870d1641 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -49,6 +49,7 @@ #define OC_DEVICE_ID1 0x700 /* Device Id for BE2 cards */ #define OC_DEVICE_ID2 0x710 /* Device Id for BE3 cards */ #define OC_DEVICE_ID3 0xe220 /* Device id for Lancer cards */ +#define OC_DEVICE_ID4 0xe228 /* Device id for VF in Lancer */ static inline char *nic_name(struct pci_dev *pdev) { @@ -58,6 +59,7 @@ static inline char *nic_name(struct pci_dev *pdev) case OC_DEVICE_ID2: return OC_NAME_BE; case OC_DEVICE_ID3: + case OC_DEVICE_ID4: return OC_NAME_LANCER; case BE_DEVICE_ID2: return BE3_NAME; @@ -383,7 +385,8 @@ struct be_adapter { #define BE_GEN2 2 #define BE_GEN3 3 -#define lancer_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID3) +#define lancer_chip(adapter) ((adapter->pdev->device == OC_DEVICE_ID3) || \ + (adapter->pdev->device == OC_DEVICE_ID4)) extern const struct ethtool_ops be_ethtool_ops; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 7322a511e936..ce6edac007a7 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -42,6 +42,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)}, + { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID4)}, { 0 } }; MODULE_DEVICE_TABLE(pci, be_dev_ids); @@ -3161,7 +3162,8 @@ static int be_get_config(struct be_adapter *adapter) memset(mac, 0, ETH_ALEN); - if (be_physfn(adapter)) { + /* A default permanent address is given to each VF for Lancer*/ + if (be_physfn(adapter) || lancer_chip(adapter)) { status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK, true /*permanent */, 0); @@ -3203,6 +3205,7 @@ static int be_dev_family_check(struct be_adapter *adapter) adapter->generation = BE_GEN3; break; case OC_DEVICE_ID3: + case OC_DEVICE_ID4: pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf); if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> SLI_INTF_IF_TYPE_SHIFT; @@ -3212,10 +3215,6 @@ static int be_dev_family_check(struct be_adapter *adapter) dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n"); return -EINVAL; } - if (num_vfs > 0) { - dev_err(&pdev->dev, "VFs not supported\n"); - return -EINVAL; - } adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >> SLI_INTF_FAMILY_SHIFT); adapter->generation = BE_GEN3; @@ -3381,9 +3380,11 @@ static int __devinit be_probe(struct pci_dev *pdev, bool link_up; u16 vf, lnk_speed; - status = be_vf_eth_addr_config(adapter); - if (status) - goto unreg_netdev; + if (!lancer_chip(adapter)) { + status = be_vf_eth_addr_config(adapter); + if (status) + goto unreg_netdev; + } for (vf = 0; vf < num_vfs; vf++) { status = be_cmd_link_status_query(adapter, &link_up, -- cgit v1.2.3-58-ga151 From 6882f933ccee5c3a86443ffc7621ce888b93ab6b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 May 2011 18:23:21 -0400 Subject: ipv4: Kill RT_CACHE_DEBUG It's way past it's usefulness. And this gets rid of a bunch of stray ->rt_{dst,src} references. Even the comment documenting the macro was inaccurate (stated default was 1 when it's 0). If reintroduced, it should be done properly, with dynamic debug facilities. Signed-off-by: David S. Miller --- include/net/dst.h | 7 ------- net/core/dst.c | 22 ---------------------- net/ipv4/route.c | 22 ---------------------- 3 files changed, 51 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index 2588a9a88cc6..07a0402c52e6 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -16,13 +16,6 @@ #include #include -/* - * 0 - no debugging messages - * 1 - rare events and bugs (default) - * 2 - trace mode. - */ -#define RT_CACHE_DEBUG 0 - #define DST_GC_MIN (HZ/10) #define DST_GC_INC (HZ/2) #define DST_GC_MAX (120*HZ) diff --git a/net/core/dst.c b/net/core/dst.c index 30f009327b62..da47a299618a 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -33,9 +33,6 @@ * 3) This list is guarded by a mutex, * so that the gc_task and dst_dev_event() can be synchronized. */ -#if RT_CACHE_DEBUG >= 2 -static atomic_t dst_total = ATOMIC_INIT(0); -#endif /* * We want to keep lock & list close together @@ -69,10 +66,6 @@ static void dst_gc_task(struct work_struct *work) unsigned long expires = ~0L; struct dst_entry *dst, *next, head; struct dst_entry *last = &head; -#if RT_CACHE_DEBUG >= 2 - ktime_t time_start = ktime_get(); - struct timespec elapsed; -#endif mutex_lock(&dst_gc_mutex); next = dst_busy_list; @@ -146,15 +139,6 @@ loop: spin_unlock_bh(&dst_garbage.lock); mutex_unlock(&dst_gc_mutex); -#if RT_CACHE_DEBUG >= 2 - elapsed = ktime_to_timespec(ktime_sub(ktime_get(), time_start)); - printk(KERN_DEBUG "dst_total: %d delayed: %d work_perf: %d" - " expires: %lu elapsed: %lu us\n", - atomic_read(&dst_total), delayed, work_performed, - expires, - elapsed.tv_sec * USEC_PER_SEC + - elapsed.tv_nsec / NSEC_PER_USEC); -#endif } int dst_discard(struct sk_buff *skb) @@ -205,9 +189,6 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev, dst->lastuse = jiffies; dst->flags = flags; dst->next = NULL; -#if RT_CACHE_DEBUG >= 2 - atomic_inc(&dst_total); -#endif dst_entries_add(ops, 1); return dst; } @@ -267,9 +248,6 @@ again: dst->ops->destroy(dst); if (dst->dev) dev_put(dst->dev); -#if RT_CACHE_DEBUG >= 2 - atomic_dec(&dst_total); -#endif kmem_cache_free(dst->ops->kmem_cachep, dst); dst = child; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index cb93c32027d7..9c5ad86bc783 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -968,10 +968,6 @@ static int rt_garbage_collect(struct dst_ops *ops) break; expire >>= 1; -#if RT_CACHE_DEBUG >= 2 - printk(KERN_DEBUG "expire>> %u %d %d %d\n", expire, - dst_entries_get_fast(&ipv4_dst_ops), goal, i); -#endif if (dst_entries_get_fast(&ipv4_dst_ops) < ip_rt_max_size) goto out; @@ -992,10 +988,6 @@ work_done: dst_entries_get_fast(&ipv4_dst_ops) < ipv4_dst_ops.gc_thresh || dst_entries_get_slow(&ipv4_dst_ops) < ipv4_dst_ops.gc_thresh) expire = ip_rt_gc_timeout; -#if RT_CACHE_DEBUG >= 2 - printk(KERN_DEBUG "expire++ %u %d %d %d\n", expire, - dst_entries_get_fast(&ipv4_dst_ops), goal, rover); -#endif out: return 0; } @@ -1179,16 +1171,6 @@ restart: rt->dst.rt_next = rt_hash_table[hash].chain; -#if RT_CACHE_DEBUG >= 2 - if (rt->dst.rt_next) { - struct rtable *trt; - printk(KERN_DEBUG "rt_cache @%02x: %pI4", - hash, &rt->rt_dst); - for (trt = rt->dst.rt_next; trt; trt = trt->dst.rt_next) - printk(" . %pI4", &trt->rt_dst); - printk("\n"); - } -#endif /* * Since lookup is lockfree, we must make sure * previous writes to rt are committed to memory @@ -1347,10 +1329,6 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) unsigned hash = rt_hash(rt->rt_key_dst, rt->rt_key_src, rt->rt_oif, rt_genid(dev_net(dst->dev))); -#if RT_CACHE_DEBUG >= 1 - printk(KERN_DEBUG "ipv4_negative_advice: redirect to %pI4/%02x dropped\n", - &rt->rt_dst, rt->rt_key_tos); -#endif rt_del(hash, rt); ret = NULL; } else if (rt->peer && -- cgit v1.2.3-58-ga151 From 6bd023f3dddfc7c5f660089598c10e1f4167083b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 May 2011 18:32:03 -0400 Subject: ipv4: Make caller provide flowi4 key to inet_csk_route_req(). This way the caller can get at the fully resolved fl4->{daddr,saddr} etc. Signed-off-by: David S. Miller --- include/net/inet_connection_sock.h | 1 + net/dccp/ipv4.c | 3 ++- net/ipv4/inet_connection_sock.c | 10 +++++----- net/ipv4/tcp_ipv4.c | 6 ++++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 96546cae1cba..e6db62e756dc 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -249,6 +249,7 @@ extern int inet_csk_bind_conflict(const struct sock *sk, extern int inet_csk_get_port(struct sock *sk, unsigned short snum); extern struct dst_entry* inet_csk_route_req(struct sock *sk, + struct flowi4 *fl4, const struct request_sock *req); extern struct dst_entry* inet_csk_route_child_sock(struct sock *sk, struct sock *newsk, diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 46b15e9e9b57..8c36adfd1919 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -497,8 +497,9 @@ static int dccp_v4_send_response(struct sock *sk, struct request_sock *req, int err = -1; struct sk_buff *skb; struct dst_entry *dst; + struct flowi4 fl4; - dst = inet_csk_route_req(sk, req); + dst = inet_csk_route_req(sk, &fl4, req); if (dst == NULL) goto out; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 3a2ba5632dff..61fac4cabc78 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -350,24 +350,24 @@ void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long len) EXPORT_SYMBOL(inet_csk_reset_keepalive_timer); struct dst_entry *inet_csk_route_req(struct sock *sk, + struct flowi4 *fl4, const struct request_sock *req) { struct rtable *rt; const struct inet_request_sock *ireq = inet_rsk(req); struct ip_options_rcu *opt = inet_rsk(req)->opt; struct net *net = sock_net(sk); - struct flowi4 fl4; - flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark, + flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, sk->sk_protocol, inet_sk_flowi_flags(sk), (opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr, ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport); - security_req_classify_flow(req, flowi4_to_flowi(&fl4)); - rt = ip_route_output_flow(net, &fl4, sk); + security_req_classify_flow(req, flowi4_to_flowi(fl4)); + rt = ip_route_output_flow(net, fl4, sk); if (IS_ERR(rt)) goto no_route; - if (opt && opt->opt.is_strictroute && fl4.daddr != rt->rt_gateway) + if (opt && opt->opt.is_strictroute && fl4->daddr != rt->rt_gateway) goto route_err; return &rt->dst; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index f67fb34e16e5..7e0bc604ebd2 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -769,11 +769,12 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, struct request_values *rvp) { const struct inet_request_sock *ireq = inet_rsk(req); + struct flowi4 fl4; int err = -1; struct sk_buff * skb; /* First, grab a route. */ - if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL) + if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL) return -1; skb = tcp_make_synack(sk, dst, req, rvp); @@ -1338,6 +1339,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) req->cookie_ts = tmp_opt.tstamp_ok; } else if (!isn) { struct inet_peer *peer = NULL; + struct flowi4 fl4; /* VJ's idea. We save last timestamp seen * from the destination in peer table, when entering @@ -1350,7 +1352,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) */ if (tmp_opt.saw_tstamp && tcp_death_row.sysctl_tw_recycle && - (dst = inet_csk_route_req(sk, req)) != NULL && + (dst = inet_csk_route_req(sk, &fl4, req)) != NULL && (peer = rt_get_peer((struct rtable *)dst)) != NULL && peer->daddr.addr.a4 == saddr) { inet_peer_refcheck(peer); -- cgit v1.2.3-58-ga151 From ed2361e66eec60645f8e4715fe39a42235ef43ae Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 May 2011 18:38:54 -0400 Subject: ipv4: Pass explicit destination address to rt_get_peer(). This will next trickle down to rt_bind_peer(). Signed-off-by: David S. Miller --- include/net/route.h | 2 +- net/ipv4/tcp_ipv4.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index ba0e0840370c..600d0f2ef8d6 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -292,7 +292,7 @@ static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable extern void rt_bind_peer(struct rtable *rt, int create); -static inline struct inet_peer *rt_get_peer(struct rtable *rt) +static inline struct inet_peer *rt_get_peer(struct rtable *rt, __be32 daddr) { if (rt->peer) return rt->peer; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 7e0bc604ebd2..1d290acdcb27 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -206,7 +206,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (tcp_death_row.sysctl_tw_recycle && !tp->rx_opt.ts_recent_stamp && fl4->daddr == daddr) { - struct inet_peer *peer = rt_get_peer(rt); + struct inet_peer *peer = rt_get_peer(rt, fl4->daddr); /* * VJ's idea. We save last timestamp seen from * the destination in peer table, when entering state @@ -1353,8 +1353,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) if (tmp_opt.saw_tstamp && tcp_death_row.sysctl_tw_recycle && (dst = inet_csk_route_req(sk, &fl4, req)) != NULL && - (peer = rt_get_peer((struct rtable *)dst)) != NULL && - peer->daddr.addr.a4 == saddr) { + fl4.daddr == saddr && + (peer = rt_get_peer((struct rtable *)dst, fl4.daddr)) != NULL) { inet_peer_refcheck(peer); if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL && (s32)(peer->tcp_ts - req->ts_recent) > -- cgit v1.2.3-58-ga151 From a48eff128865aa20520fa6e0e0c5fbd2ac50d712 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 May 2011 18:42:43 -0400 Subject: ipv4: Pass explicit destination address to rt_bind_peer(). Signed-off-by: David S. Miller --- include/net/route.h | 4 ++-- net/ipv4/icmp.c | 8 ++++---- net/ipv4/route.c | 16 ++++++++-------- net/ipv4/tcp_ipv4.c | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index 600d0f2ef8d6..db7b3432f07c 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -290,14 +290,14 @@ static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable return rt; } -extern void rt_bind_peer(struct rtable *rt, int create); +extern void rt_bind_peer(struct rtable *rt, __be32 daddr, int create); static inline struct inet_peer *rt_get_peer(struct rtable *rt, __be32 daddr) { if (rt->peer) return rt->peer; - rt_bind_peer(rt, 0); + rt_bind_peer(rt, daddr, 0); return rt->peer; } diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 3f47585aad68..5395e45dcce6 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -234,7 +234,7 @@ static inline void icmp_xmit_unlock(struct sock *sk) */ static inline bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt, - int type, int code) + struct flowi4 *fl4, int type, int code) { struct dst_entry *dst = &rt->dst; bool rc = true; @@ -253,7 +253,7 @@ static inline bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt, /* Limit if icmp type is enabled in ratemask. */ if ((1 << type) & net->ipv4.sysctl_icmp_ratemask) { if (!rt->peer) - rt_bind_peer(rt, 1); + rt_bind_peer(rt, fl4->daddr, 1); rc = inet_peer_xrlim_allow(rt->peer, net->ipv4.sysctl_icmp_ratelimit); } @@ -363,7 +363,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) rt = ip_route_output_key(net, &fl4); if (IS_ERR(rt)) goto out_unlock; - if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type, + if (icmpv4_xrlim_allow(net, rt, &fl4, icmp_param->data.icmph.type, icmp_param->data.icmph.code)) icmp_push_reply(icmp_param, &fl4, &ipc, &rt); ip_rt_put(rt); @@ -603,7 +603,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) if (IS_ERR(rt)) goto out_unlock; - if (!icmpv4_xrlim_allow(net, rt, type, code)) + if (!icmpv4_xrlim_allow(net, rt, &fl4, type, code)) goto ende; /* RFC says return as much as we can without exceeding 576 bytes. */ diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 9c5ad86bc783..b24d58e6bbcd 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -156,7 +156,7 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old) u32 *p = NULL; if (!rt->peer) - rt_bind_peer(rt, 1); + rt_bind_peer(rt, rt->rt_dst, 1); peer = rt->peer; if (peer) { @@ -1193,11 +1193,11 @@ static u32 rt_peer_genid(void) return atomic_read(&__rt_peer_genid); } -void rt_bind_peer(struct rtable *rt, int create) +void rt_bind_peer(struct rtable *rt, __be32 daddr, int create) { struct inet_peer *peer; - peer = inet_getpeer_v4(rt->rt_dst, create); + peer = inet_getpeer_v4(daddr, create); if (peer && cmpxchg(&rt->peer, NULL, peer) != NULL) inet_putpeer(peer); @@ -1231,7 +1231,7 @@ void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more) if (rt) { if (rt->peer == NULL) - rt_bind_peer(rt, 1); + rt_bind_peer(rt, rt->rt_dst, 1); /* If peer is attached to destination, it is never detached, so that we need not to grab a lock to dereference it. @@ -1377,7 +1377,7 @@ void ip_rt_send_redirect(struct sk_buff *skb) rcu_read_unlock(); if (!rt->peer) - rt_bind_peer(rt, 1); + rt_bind_peer(rt, rt->rt_dst, 1); peer = rt->peer; if (!peer) { icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway); @@ -1445,7 +1445,7 @@ static int ip_error(struct sk_buff *skb) } if (!rt->peer) - rt_bind_peer(rt, 1); + rt_bind_peer(rt, rt->rt_dst, 1); peer = rt->peer; send = true; @@ -1552,7 +1552,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) dst_confirm(dst); if (!rt->peer) - rt_bind_peer(rt, 1); + rt_bind_peer(rt, rt->rt_dst, 1); peer = rt->peer; if (peer) { if (mtu < ip_rt_min_pmtu) @@ -1609,7 +1609,7 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) struct inet_peer *peer; if (!rt->peer) - rt_bind_peer(rt, 0); + rt_bind_peer(rt, rt->rt_dst, 0); peer = rt->peer; if (peer && peer->pmtu_expires) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1d290acdcb27..3c8d9b6f1ea4 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1781,7 +1781,7 @@ struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it) *release_it = true; } else { if (!rt->peer) - rt_bind_peer(rt, 1); + rt_bind_peer(rt, inet->inet_daddr, 1); peer = rt->peer; *release_it = false; } -- cgit v1.2.3-58-ga151 From bb0cd2fb539c4e454ed32e32194acc03b75753f3 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Wed, 18 May 2011 21:16:00 +0000 Subject: net: ping: make local functions static As these functions are only used in this file. Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- net/ipv4/ping.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 6a21da906532..5f9e2d1ea4df 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -449,8 +449,8 @@ static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, st return ip_push_pending_frames(sk, fl4); } -int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len) +static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len) { struct net *net = sock_net(sk); struct flowi4 fl4; @@ -621,8 +621,8 @@ do_confirm: goto out; } -int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len, int noblock, int flags, int *addr_len) +static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int noblock, int flags, int *addr_len) { struct inet_sock *isk = inet_sk(sk); struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; -- cgit v1.2.3-58-ga151 From 75e308c894c4a5e47c005b8e821ae5f539ad2ef3 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Wed, 18 May 2011 21:16:01 +0000 Subject: net: ping: fix the coding style The characters in a line should be no more than 80. Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- net/ipv4/ping.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 5f9e2d1ea4df..1f3bb11490c9 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -187,7 +187,8 @@ exit: return sk; } -static void inet_get_ping_group_range_net(struct net *net, gid_t *low, gid_t *high) +static void inet_get_ping_group_range_net(struct net *net, gid_t *low, + gid_t *high) { gid_t *data = net->ipv4.sysctl_ping_group_range; unsigned seq; @@ -437,7 +438,8 @@ static int ping_getfrag(void *from, char * to, return 0; } -static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, struct flowi4 *fl4) +static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, + struct flowi4 *fl4) { struct sk_buff *skb = skb_peek(&sk->sk_write_queue); @@ -754,7 +756,9 @@ static struct sock *ping_get_first(struct seq_file *seq, int start) for (state->bucket = start; state->bucket < PING_HTABLE_SIZE; ++state->bucket) { struct hlist_nulls_node *node; - struct hlist_nulls_head *hslot = &ping_table.hash[state->bucket]; + struct hlist_nulls_head *hslot; + + hslot = &ping_table.hash[state->bucket]; if (hlist_nulls_empty(hslot)) continue; -- cgit v1.2.3-58-ga151 From be281e554e2a4cf2478df7a8b8926c89454bccfa Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 19 May 2011 01:14:23 +0000 Subject: ipv6: reduce per device ICMP mib sizes ipv6 has per device ICMP SNMP counters, taking too much space because they use percpu storage. needed size per device is : (512+4)*sizeof(long)*number_of_possible_cpus*2 On a 32bit kernel, 16 possible cpus, this wastes more than 64kbytes of memory per ipv6 enabled network device, taken in vmalloc pool. Since ICMP messages are rare, just use shared counters (atomic_long_t) Per network space ICMP counters are still using percpu memory, we might also convert them to shared counters in a future patch. Signed-off-by: Eric Dumazet CC: Denys Fedoryshchenko Signed-off-by: David S. Miller --- include/net/if_inet6.h | 4 ++-- include/net/ipv6.h | 19 ++++++++++++++----- include/net/snmp.h | 14 ++++++++++++++ net/ipv6/addrconf.c | 24 ++++++++++++------------ net/ipv6/proc.c | 40 ++++++++++++++++++++++++++-------------- 5 files changed, 68 insertions(+), 33 deletions(-) diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index 0c603fe65377..11cf373970a9 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -154,8 +154,8 @@ struct ifacaddr6 { struct ipv6_devstat { struct proc_dir_entry *proc_dir_entry; DEFINE_SNMP_STAT(struct ipstats_mib, ipv6); - DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6); - DEFINE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg); + DEFINE_SNMP_STAT_ATOMIC(struct icmpv6_mib_device, icmpv6dev); + DEFINE_SNMP_STAT_ATOMIC(struct icmpv6msg_mib_device, icmpv6msgdev); }; struct inet6_dev { diff --git a/include/net/ipv6.h b/include/net/ipv6.h index e1c60b43e73b..c033ed00df7d 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -123,6 +123,15 @@ extern struct ctl_path net_ipv6_ctl_path[]; SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\ }) +/* per device counters are atomic_long_t */ +#define _DEVINCATOMIC(net, statname, modifier, idev, field) \ +({ \ + struct inet6_dev *_idev = (idev); \ + if (likely(_idev != NULL)) \ + SNMP_INC_STATS_ATOMIC_LONG((_idev)->stats.statname##dev, (field)); \ + SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\ +}) + #define _DEVADD(net, statname, modifier, idev, field, val) \ ({ \ struct inet6_dev *_idev = (idev); \ @@ -154,16 +163,16 @@ extern struct ctl_path net_ipv6_ctl_path[]; #define IP6_UPD_PO_STATS_BH(net, idev,field,val) \ _DEVUPD(net, ipv6, 64_BH, idev, field, val) #define ICMP6_INC_STATS(net, idev, field) \ - _DEVINC(net, icmpv6, , idev, field) + _DEVINCATOMIC(net, icmpv6, , idev, field) #define ICMP6_INC_STATS_BH(net, idev, field) \ - _DEVINC(net, icmpv6, _BH, idev, field) + _DEVINCATOMIC(net, icmpv6, _BH, idev, field) #define ICMP6MSGOUT_INC_STATS(net, idev, field) \ - _DEVINC(net, icmpv6msg, , idev, field +256) + _DEVINCATOMIC(net, icmpv6msg, , idev, field +256) #define ICMP6MSGOUT_INC_STATS_BH(net, idev, field) \ - _DEVINC(net, icmpv6msg, _BH, idev, field +256) + _DEVINCATOMIC(net, icmpv6msg, _BH, idev, field +256) #define ICMP6MSGIN_INC_STATS_BH(net, idev, field) \ - _DEVINC(net, icmpv6msg, _BH, idev, field) + _DEVINCATOMIC(net, icmpv6msg, _BH, idev, field) struct ip6_ra_chain { struct ip6_ra_chain *next; diff --git a/include/net/snmp.h b/include/net/snmp.h index 27461d6dd46f..479083a78b0c 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -72,14 +72,24 @@ struct icmpmsg_mib { /* ICMP6 (IPv6-ICMP) */ #define ICMP6_MIB_MAX __ICMP6_MIB_MAX +/* per network ns counters */ struct icmpv6_mib { unsigned long mibs[ICMP6_MIB_MAX]; }; +/* per device counters, (shared on all cpus) */ +struct icmpv6_mib_device { + atomic_long_t mibs[ICMP6_MIB_MAX]; +}; #define ICMP6MSG_MIB_MAX __ICMP6MSG_MIB_MAX +/* per network ns counters */ struct icmpv6msg_mib { unsigned long mibs[ICMP6MSG_MIB_MAX]; }; +/* per device counters, (shared on all cpus) */ +struct icmpv6msg_mib_device { + atomic_long_t mibs[ICMP6MSG_MIB_MAX]; +}; /* TCP */ @@ -114,6 +124,8 @@ struct linux_xfrm_mib { */ #define DEFINE_SNMP_STAT(type, name) \ __typeof__(type) __percpu *name[2] +#define DEFINE_SNMP_STAT_ATOMIC(type, name) \ + __typeof__(type) *name #define DECLARE_SNMP_STAT(type, name) \ extern __typeof__(type) __percpu *name[2] @@ -124,6 +136,8 @@ struct linux_xfrm_mib { __this_cpu_inc(mib[0]->mibs[field]) #define SNMP_INC_STATS_USER(mib, field) \ this_cpu_inc(mib[1]->mibs[field]) +#define SNMP_INC_STATS_ATOMIC_LONG(mib, field) \ + atomic_long_inc(&mib->mibs[field]) #define SNMP_INC_STATS(mib, field) \ this_cpu_inc(mib[!in_softirq()]->mibs[field]) #define SNMP_DEC_STATS(mib, field) \ diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f2f9b2e3cfe9..3cfbbf3387a0 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -289,19 +289,19 @@ static int snmp6_alloc_dev(struct inet6_dev *idev) sizeof(struct ipstats_mib), __alignof__(struct ipstats_mib)) < 0) goto err_ip; - if (snmp_mib_init((void __percpu **)idev->stats.icmpv6, - sizeof(struct icmpv6_mib), - __alignof__(struct icmpv6_mib)) < 0) + idev->stats.icmpv6dev = kzalloc(sizeof(struct icmpv6_mib_device), + GFP_KERNEL); + if (!idev->stats.icmpv6dev) goto err_icmp; - if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg, - sizeof(struct icmpv6msg_mib), - __alignof__(struct icmpv6msg_mib)) < 0) + idev->stats.icmpv6msgdev = kzalloc(sizeof(struct icmpv6msg_mib_device), + GFP_KERNEL); + if (!idev->stats.icmpv6msgdev) goto err_icmpmsg; return 0; err_icmpmsg: - snmp_mib_free((void __percpu **)idev->stats.icmpv6); + kfree(idev->stats.icmpv6dev); err_icmp: snmp_mib_free((void __percpu **)idev->stats.ipv6); err_ip: @@ -310,8 +310,8 @@ err_ip: static void snmp6_free_dev(struct inet6_dev *idev) { - snmp_mib_free((void __percpu **)idev->stats.icmpv6msg); - snmp_mib_free((void __percpu **)idev->stats.icmpv6); + kfree(idev->stats.icmpv6msgdev); + kfree(idev->stats.icmpv6dev); snmp_mib_free((void __percpu **)idev->stats.ipv6); } @@ -3838,7 +3838,7 @@ static inline size_t inet6_if_nlmsg_size(void) + nla_total_size(inet6_ifla6_size()); /* IFLA_PROTINFO */ } -static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, +static inline void __snmp6_fill_statsdev(u64 *stats, atomic_long_t *mib, int items, int bytes) { int i; @@ -3848,7 +3848,7 @@ static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, /* Use put_unaligned() because stats may not be aligned for u64. */ put_unaligned(items, &stats[0]); for (i = 1; i < items; i++) - put_unaligned(snmp_fold_field(mib, i), &stats[i]); + put_unaligned(atomic_long_read(&mib[i]), &stats[i]); memset(&stats[items], 0, pad); } @@ -3877,7 +3877,7 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, IPSTATS_MIB_MAX, bytes, offsetof(struct ipstats_mib, syncp)); break; case IFLA_INET6_ICMP6STATS: - __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); + __snmp6_fill_statsdev(stats, idev->stats.icmpv6dev->mibs, ICMP6_MIB_MAX, bytes); break; } } diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 24b3558b8e67..18ff5df7ec02 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -141,7 +141,11 @@ static const struct snmp_mib snmp6_udplite6_list[] = { SNMP_MIB_SENTINEL }; -static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void __percpu **mib) +/* can be called either with percpu mib (pcpumib != NULL), + * or shared one (smib != NULL) + */ +static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void __percpu **pcpumib, + atomic_long_t *smib) { char name[32]; int i; @@ -158,14 +162,14 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void __percpu **mib) snprintf(name, sizeof(name), "Icmp6%s%s", i & 0x100 ? "Out" : "In", p); seq_printf(seq, "%-32s\t%lu\n", name, - snmp_fold_field(mib, i)); + pcpumib ? snmp_fold_field(pcpumib, i) : atomic_long_read(smib + i)); } /* print by number (nonzero only) - ICMPMsgStat format */ for (i = 0; i < ICMP6MSG_MIB_MAX; i++) { unsigned long val; - val = snmp_fold_field(mib, i); + val = pcpumib ? snmp_fold_field(pcpumib, i) : atomic_long_read(smib + i); if (!val) continue; snprintf(name, sizeof(name), "Icmp6%sType%u", @@ -174,14 +178,22 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void __percpu **mib) } } -static void snmp6_seq_show_item(struct seq_file *seq, void __percpu **mib, +/* can be called either with percpu mib (pcpumib != NULL), + * or shared one (smib != NULL) + */ +static void snmp6_seq_show_item(struct seq_file *seq, void __percpu **pcpumib, + atomic_long_t *smib, const struct snmp_mib *itemlist) { int i; + unsigned long val; - for (i = 0; itemlist[i].name; i++) - seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name, - snmp_fold_field(mib, itemlist[i].entry)); + for (i = 0; itemlist[i].name; i++) { + val = pcpumib ? + snmp_fold_field(pcpumib, itemlist[i].entry) : + atomic_long_read(smib + itemlist[i].entry); + seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name, val); + } } static void snmp6_seq_show_item64(struct seq_file *seq, void __percpu **mib, @@ -201,13 +213,13 @@ static int snmp6_seq_show(struct seq_file *seq, void *v) snmp6_seq_show_item64(seq, (void __percpu **)net->mib.ipv6_statistics, snmp6_ipstats_list, offsetof(struct ipstats_mib, syncp)); snmp6_seq_show_item(seq, (void __percpu **)net->mib.icmpv6_statistics, - snmp6_icmp6_list); + NULL, snmp6_icmp6_list); snmp6_seq_show_icmpv6msg(seq, - (void __percpu **)net->mib.icmpv6msg_statistics); + (void __percpu **)net->mib.icmpv6msg_statistics, NULL); snmp6_seq_show_item(seq, (void __percpu **)net->mib.udp_stats_in6, - snmp6_udp6_list); + NULL, snmp6_udp6_list); snmp6_seq_show_item(seq, (void __percpu **)net->mib.udplite_stats_in6, - snmp6_udplite6_list); + NULL, snmp6_udplite6_list); return 0; } @@ -229,11 +241,11 @@ static int snmp6_dev_seq_show(struct seq_file *seq, void *v) struct inet6_dev *idev = (struct inet6_dev *)seq->private; seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); - snmp6_seq_show_item(seq, (void __percpu **)idev->stats.ipv6, + snmp6_seq_show_item(seq, (void __percpu **)idev->stats.ipv6, NULL, snmp6_ipstats_list); - snmp6_seq_show_item(seq, (void __percpu **)idev->stats.icmpv6, + snmp6_seq_show_item(seq, NULL, idev->stats.icmpv6dev->mibs, snmp6_icmp6_list); - snmp6_seq_show_icmpv6msg(seq, (void __percpu **)idev->stats.icmpv6msg); + snmp6_seq_show_icmpv6msg(seq, NULL, idev->stats.icmpv6msgdev->mibs); return 0; } -- cgit v1.2.3-58-ga151 From c182f90bc1f22ce5039b8722e45621d5f96862c2 Mon Sep 17 00:00:00 2001 From: Jacek Luczak Date: Thu, 19 May 2011 09:55:13 +0000 Subject: SCTP: fix race between sctp_bind_addr_free() and sctp_bind_addr_conflict() During the sctp_close() call, we do not use rcu primitives to destroy the address list attached to the endpoint. At the same time, we do the removal of addresses from this list before attempting to remove the socket from the port hash As a result, it is possible for another process to find the socket in the port hash that is in the process of being closed. It then proceeds to traverse the address list to find the conflict, only to have that address list suddenly disappear without rcu() critical section. Fix issue by closing address list removal inside RCU critical section. Race can result in a kernel crash with general protection fault or kernel NULL pointer dereference: kernel: general protection fault: 0000 [#1] SMP kernel: RIP: 0010:[] [] sctp_bind_addr_conflict+0x64/0x82 [sctp] kernel: Call Trace: kernel: [] ? sctp_get_port_local+0x17b/0x2a3 [sctp] kernel: [] ? sctp_bind_addr_match+0x33/0x68 [sctp] kernel: [] ? sctp_do_bind+0xd3/0x141 [sctp] kernel: [] ? sctp_bindx_add+0x4d/0x8e [sctp] kernel: [] ? sctp_setsockopt_bindx+0x112/0x4a4 [sctp] kernel: [] ? generic_file_aio_write+0x7f/0x9b kernel: [] ? sctp_setsockopt+0x14f/0xfee [sctp] kernel: [] ? do_sync_write+0xab/0xeb kernel: [] ? fsnotify+0x239/0x282 kernel: [] ? alloc_file+0x18/0xb1 kernel: [] ? compat_sys_setsockopt+0x1a5/0x1d9 kernel: [] ? compat_sys_socketcall+0x143/0x1a4 kernel: [] ? sysenter_dispatch+0x7/0x32 Signed-off-by: Jacek Luczak Acked-by: Vlad Yasevich CC: Eric Dumazet Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- net/sctp/bind_addr.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index faf71d179e46..6150ac5cf5dd 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -140,14 +140,12 @@ void sctp_bind_addr_init(struct sctp_bind_addr *bp, __u16 port) /* Dispose of the address list. */ static void sctp_bind_addr_clean(struct sctp_bind_addr *bp) { - struct sctp_sockaddr_entry *addr; - struct list_head *pos, *temp; + struct sctp_sockaddr_entry *addr, *temp; /* Empty the bind address list. */ - list_for_each_safe(pos, temp, &bp->address_list) { - addr = list_entry(pos, struct sctp_sockaddr_entry, list); - list_del(pos); - kfree(addr); + list_for_each_entry_safe(addr, temp, &bp->address_list, list) { + list_del_rcu(&addr->list); + call_rcu(&addr->rcu, sctp_local_addr_free); SCTP_DBG_OBJCNT_DEC(addr); } } -- cgit v1.2.3-58-ga151 From 3fb72f1e6e6165c5f495e8dc11c5bbd14c73385c Mon Sep 17 00:00:00 2001 From: Micha Nelissen Date: Thu, 19 May 2011 10:14:06 +0000 Subject: ipconfig wait for carrier v3 -> v4: fix return boolean false instead of 0 for ic_is_init_dev Currently the ip auto configuration has a hardcoded delay of 1 second. When (ethernet) link takes longer to come up (e.g. more than 3 seconds), nfs root may not be found. Remove the hardcoded delay, and wait for carrier on at least one network device. Signed-off-by: Micha Nelissen Cc: David Miller Signed-off-by: David S. Miller --- net/ipv4/ipconfig.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index cbff2ecccf3d..ab7e5542c1cf 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -87,8 +87,8 @@ #endif /* Define the friendly delay before and after opening net devices */ -#define CONF_PRE_OPEN 500 /* Before opening: 1/2 second */ -#define CONF_POST_OPEN 1 /* After opening: 1 second */ +#define CONF_POST_OPEN 10 /* After opening: 10 msecs */ +#define CONF_CARRIER_TIMEOUT 120000 /* Wait for carrier timeout */ /* Define the timeout for waiting for a DHCP/BOOTP/RARP reply */ #define CONF_OPEN_RETRIES 2 /* (Re)open devices twice */ @@ -188,14 +188,14 @@ struct ic_device { static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */ static struct net_device *ic_dev __initdata = NULL; /* Selected device */ -static bool __init ic_device_match(struct net_device *dev) +static bool __init ic_is_init_dev(struct net_device *dev) { - if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) : + if (dev->flags & IFF_LOOPBACK) + return false; + return user_dev_name[0] ? !strcmp(dev->name, user_dev_name) : (!(dev->flags & IFF_LOOPBACK) && (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) && - strncmp(dev->name, "dummy", 5))) - return true; - return false; + strncmp(dev->name, "dummy", 5)); } static int __init ic_open_devs(void) @@ -203,6 +203,7 @@ static int __init ic_open_devs(void) struct ic_device *d, **last; struct net_device *dev; unsigned short oflags; + unsigned long start; last = &ic_first_dev; rtnl_lock(); @@ -216,9 +217,7 @@ static int __init ic_open_devs(void) } for_each_netdev(&init_net, dev) { - if (dev->flags & IFF_LOOPBACK) - continue; - if (ic_device_match(dev)) { + if (ic_is_init_dev(dev)) { int able = 0; if (dev->mtu >= 364) able |= IC_BOOTP; @@ -252,6 +251,17 @@ static int __init ic_open_devs(void) dev->name, able, d->xid)); } } + + /* wait for a carrier on at least one device */ + start = jiffies; + while (jiffies - start < msecs_to_jiffies(CONF_CARRIER_TIMEOUT)) { + for_each_netdev(&init_net, dev) + if (ic_is_init_dev(dev) && netif_carrier_ok(dev)) + goto have_carrier; + + msleep(1); + } +have_carrier: rtnl_unlock(); *last = NULL; @@ -1324,14 +1334,13 @@ static int __init wait_for_devices(void) { int i; - msleep(CONF_PRE_OPEN); for (i = 0; i < DEVICE_WAIT_MAX; i++) { struct net_device *dev; int found = 0; rtnl_lock(); for_each_netdev(&init_net, dev) { - if (ic_device_match(dev)) { + if (ic_is_init_dev(dev)) { found = 1; break; } @@ -1378,7 +1387,7 @@ static int __init ip_auto_config(void) return err; /* Give drivers a chance to settle */ - ssleep(CONF_POST_OPEN); + msleep(CONF_POST_OPEN); /* * If the config information is insufficient (e.g., our IP address or -- cgit v1.2.3-58-ga151 From 99517e3d7930f8cc064f7e9443b1b441e00e83d7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 17:38:57 -0400 Subject: 9p: Kill set but not used variable 'ret' in parse_opts() Signed-off-by: David S. Miller --- net/9p/trans_fd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index aa5672b15eae..4a9084395d35 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -716,7 +716,6 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) substring_t args[MAX_OPT_ARGS]; int option; char *options, *tmp_options; - int ret; opts->port = P9_PORT; opts->rfd = ~0; @@ -744,7 +743,6 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) if (r < 0) { P9_DPRINTK(P9_DEBUG_ERROR, "integer field, but no integer?\n"); - ret = r; continue; } } -- cgit v1.2.3-58-ga151 From 5b5ed8afe48ca6916daabf9822e7a19fc19fdab4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 17:45:29 -0400 Subject: 9p: Kill unused variable 'ret' in trans_rdma.c:parse_opts() Probably just cut and pasted from the other parse_opts() implementations in the 9p sources. Signed-off-by: David S. Miller --- net/9p/trans_rdma.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 150e0c4bbf40..844a7a5607e3 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -167,7 +167,6 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts) substring_t args[MAX_OPT_ARGS]; int option; char *options, *tmp_options; - int ret; opts->port = P9_PORT; opts->sq_depth = P9_RDMA_SQ_DEPTH; @@ -195,7 +194,6 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts) if (r < 0) { P9_DPRINTK(P9_DEBUG_ERROR, "integer field, but no integer?\n"); - ret = r; continue; } switch (token) { -- cgit v1.2.3-58-ga151 From 2ffcc981d823a0518c627ca22d51ef72d0b7ca9a Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 12:12:44 +0000 Subject: tg3: Set tx bug flags for more devices It has been recently discovered that all tg3 devices have a 4Gb boundary DMA problem, and that all 5755 and newer devices can't handle fragments less than or equal to 8 bytes in size. This patch adjusts the flags and removes tg3_start_xmit(). tg3_start_xmit_dma_bug() has been renamed to tg3_start_xmit(). Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 262 +++++++----------------------------------------------- 1 file changed, 33 insertions(+), 229 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index d5a1f9e3794c..4c441682a291 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -5735,7 +5735,28 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping, #endif } -static void tg3_set_txd(struct tg3_napi *, int, dma_addr_t, int, u32, u32); +static void tg3_set_txd(struct tg3_napi *tnapi, int entry, + dma_addr_t mapping, int len, u32 flags, + u32 mss_and_is_end) +{ + struct tg3_tx_buffer_desc *txd = &tnapi->tx_ring[entry]; + int is_end = (mss_and_is_end & 0x1); + u32 mss = (mss_and_is_end >> 1); + u32 vlan_tag = 0; + + if (is_end) + flags |= TXD_FLAG_END; + if (flags & TXD_FLAG_VLAN) { + vlan_tag = flags >> 16; + flags &= 0xffff; + } + vlan_tag |= (mss << TXD_MSS_SHIFT); + + txd->addr_hi = ((u64) mapping >> 32); + txd->addr_lo = ((u64) mapping & 0xffffffff); + txd->len_flags = (len << TXD_LEN_SHIFT) | flags; + txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; +} /* Workaround 4GB and 40-bit hardware DMA bugs. */ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, @@ -5818,202 +5839,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, return ret; } -static void tg3_set_txd(struct tg3_napi *tnapi, int entry, - dma_addr_t mapping, int len, u32 flags, - u32 mss_and_is_end) -{ - struct tg3_tx_buffer_desc *txd = &tnapi->tx_ring[entry]; - int is_end = (mss_and_is_end & 0x1); - u32 mss = (mss_and_is_end >> 1); - u32 vlan_tag = 0; - - if (is_end) - flags |= TXD_FLAG_END; - if (flags & TXD_FLAG_VLAN) { - vlan_tag = flags >> 16; - flags &= 0xffff; - } - vlan_tag |= (mss << TXD_MSS_SHIFT); - - txd->addr_hi = ((u64) mapping >> 32); - txd->addr_lo = ((u64) mapping & 0xffffffff); - txd->len_flags = (len << TXD_LEN_SHIFT) | flags; - txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; -} - -/* hard_start_xmit for devices that don't have any bugs and - * support TG3_FLAG_HW_TSO_2 and TG3_FLAG_HW_TSO_3 only. - */ -static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct tg3 *tp = netdev_priv(dev); - u32 len, entry, base_flags, mss; - dma_addr_t mapping; - struct tg3_napi *tnapi; - struct netdev_queue *txq; - unsigned int i, last; - - txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); - tnapi = &tp->napi[skb_get_queue_mapping(skb)]; - if (tg3_flag(tp, ENABLE_TSS)) - tnapi++; - - /* We are running in BH disabled context with netif_tx_lock - * and TX reclaim runs via tp->napi.poll inside of a software - * interrupt. Furthermore, IRQ processing runs lockless so we have - * no IRQ context deadlocks to worry about either. Rejoice! - */ - if (unlikely(tg3_tx_avail(tnapi) <= (skb_shinfo(skb)->nr_frags + 1))) { - if (!netif_tx_queue_stopped(txq)) { - netif_tx_stop_queue(txq); - - /* This is a hard error, log it. */ - netdev_err(dev, - "BUG! Tx Ring full when queue awake!\n"); - } - return NETDEV_TX_BUSY; - } - - entry = tnapi->tx_prod; - base_flags = 0; - mss = skb_shinfo(skb)->gso_size; - if (mss) { - int tcp_opt_len, ip_tcp_len; - u32 hdrlen; - - if (skb_header_cloned(skb) && - pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { - dev_kfree_skb(skb); - goto out_unlock; - } - - if (skb_is_gso_v6(skb)) { - hdrlen = skb_headlen(skb) - ETH_HLEN; - } else { - struct iphdr *iph = ip_hdr(skb); - - tcp_opt_len = tcp_optlen(skb); - ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr); - - iph->check = 0; - iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); - hdrlen = ip_tcp_len + tcp_opt_len; - } - - if (tg3_flag(tp, HW_TSO_3)) { - mss |= (hdrlen & 0xc) << 12; - if (hdrlen & 0x10) - base_flags |= 0x00000010; - base_flags |= (hdrlen & 0x3e0) << 5; - } else - mss |= hdrlen << 9; - - base_flags |= (TXD_FLAG_CPU_PRE_DMA | - TXD_FLAG_CPU_POST_DMA); - - tcp_hdr(skb)->check = 0; - - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - base_flags |= TXD_FLAG_TCPUDP_CSUM; - } - - if (vlan_tx_tag_present(skb)) - base_flags |= (TXD_FLAG_VLAN | - (vlan_tx_tag_get(skb) << 16)); - - len = skb_headlen(skb); - - /* Queue skb data, a.k.a. the main skb fragment. */ - mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(tp->pdev, mapping)) { - dev_kfree_skb(skb); - goto out_unlock; - } - - tnapi->tx_buffers[entry].skb = skb; - dma_unmap_addr_set(&tnapi->tx_buffers[entry], mapping, mapping); - - if (tg3_flag(tp, USE_JUMBO_BDFLAG) && - !mss && skb->len > VLAN_ETH_FRAME_LEN) - base_flags |= TXD_FLAG_JMB_PKT; - - tg3_set_txd(tnapi, entry, mapping, len, base_flags, - (skb_shinfo(skb)->nr_frags == 0) | (mss << 1)); - - entry = NEXT_TX(entry); - - /* Now loop through additional data fragments, and queue them. */ - if (skb_shinfo(skb)->nr_frags > 0) { - last = skb_shinfo(skb)->nr_frags - 1; - for (i = 0; i <= last; i++) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - len = frag->size; - mapping = pci_map_page(tp->pdev, - frag->page, - frag->page_offset, - len, PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(tp->pdev, mapping)) - goto dma_error; - - tnapi->tx_buffers[entry].skb = NULL; - dma_unmap_addr_set(&tnapi->tx_buffers[entry], mapping, - mapping); - - tg3_set_txd(tnapi, entry, mapping, len, - base_flags, (i == last) | (mss << 1)); - - entry = NEXT_TX(entry); - } - } - - /* Packets are ready, update Tx producer idx local and on card. */ - tw32_tx_mbox(tnapi->prodmbox, entry); - - tnapi->tx_prod = entry; - if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) { - netif_tx_stop_queue(txq); - - /* netif_tx_stop_queue() must be done before checking - * checking tx index in tg3_tx_avail() below, because in - * tg3_tx(), we update tx index before checking for - * netif_tx_queue_stopped(). - */ - smp_mb(); - if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)) - netif_tx_wake_queue(txq); - } - -out_unlock: - mmiowb(); - - return NETDEV_TX_OK; - -dma_error: - last = i; - entry = tnapi->tx_prod; - tnapi->tx_buffers[entry].skb = NULL; - pci_unmap_single(tp->pdev, - dma_unmap_addr(&tnapi->tx_buffers[entry], mapping), - skb_headlen(skb), - PCI_DMA_TODEVICE); - for (i = 0; i <= last; i++) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - entry = NEXT_TX(entry); - - pci_unmap_page(tp->pdev, - dma_unmap_addr(&tnapi->tx_buffers[entry], - mapping), - frag->size, PCI_DMA_TODEVICE); - } - - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - -static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *, - struct net_device *); +static netdev_tx_t tg3_start_xmit(struct sk_buff *, struct net_device *); /* Use GSO to workaround a rare TSO bug that may be triggered when the * TSO header is greater than 80 bytes. @@ -6047,7 +5873,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) nskb = segs; segs = segs->next; nskb->next = NULL; - tg3_start_xmit_dma_bug(nskb, tp->dev); + tg3_start_xmit(nskb, tp->dev); } while (segs); tg3_tso_bug_end: @@ -6059,8 +5885,7 @@ tg3_tso_bug_end: /* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and * support TG3_FLAG_HW_TSO_1 or firmware TSO only. */ -static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, - struct net_device *dev) +static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); u32 len, entry, base_flags, mss; @@ -13857,14 +13682,15 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + /* All chips can get confused if TX buffers + * straddle the 4GB address boundary. + */ + tg3_flag_set(tp, 4G_DMA_BNDRY_BUG); + + if (tg3_flag(tp, 5755_PLUS)) tg3_flag_set(tp, SHORT_DMA_BUG); - else if (!tg3_flag(tp, 5755_PLUS)) { - tg3_flag_set(tp, 4G_DMA_BNDRY_BUG); + else tg3_flag_set(tp, 40BIT_DMA_LIMIT_BUG); - } if (tg3_flag(tp, 5717_PLUS)) tg3_flag_set(tp, LRG_PROD_RING_CAP); @@ -15092,23 +14918,6 @@ static const struct net_device_ops tg3_netdev_ops = { #endif }; -static const struct net_device_ops tg3_netdev_ops_dma_bug = { - .ndo_open = tg3_open, - .ndo_stop = tg3_close, - .ndo_start_xmit = tg3_start_xmit_dma_bug, - .ndo_get_stats64 = tg3_get_stats64, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = tg3_set_rx_mode, - .ndo_set_mac_address = tg3_set_mac_addr, - .ndo_do_ioctl = tg3_ioctl, - .ndo_tx_timeout = tg3_tx_timeout, - .ndo_change_mtu = tg3_change_mtu, - .ndo_set_features = tg3_set_features, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = tg3_poll_controller, -#endif -}; - static int __devinit tg3_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -15205,6 +15014,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, dev->ethtool_ops = &tg3_ethtool_ops; dev->watchdog_timeo = TG3_TX_TIMEOUT; + dev->netdev_ops = &tg3_netdev_ops; dev->irq = pdev->irq; err = tg3_get_invariants(tp); @@ -15214,12 +15024,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_iounmap; } - if (tg3_flag(tp, 5755_PLUS) && !tg3_flag(tp, 5717_PLUS)) - dev->netdev_ops = &tg3_netdev_ops; - else - dev->netdev_ops = &tg3_netdev_ops_dma_bug; - - /* The EPB bridge inside 5714, 5715, and 5780 and any * device behind the EPB cannot support DMA addresses > 40-bit. * On 64-bit systems with IOMMU, use 40-bit dma_mask. -- cgit v1.2.3-58-ga151 From 432aa7ed75b3adaef6040d2cbe745fdd1c899415 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 12:12:45 +0000 Subject: tg3: Cleanup transmit error path This patch consolidates the skb cleanup code into a function named tg3_skb_error_unmap(). The modification addresses a long-standing bug where pci_unmap_single() was incorrectly being called instead of pci_unmap_page() in tigon3_dma_hwbug_workaround(). Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 98 +++++++++++++++++++++---------------------------------- 1 file changed, 38 insertions(+), 60 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 4c441682a291..b2b1ba168c88 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -5758,16 +5758,39 @@ static void tg3_set_txd(struct tg3_napi *tnapi, int entry, txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; } +static void tg3_skb_error_unmap(struct tg3_napi *tnapi, + struct sk_buff *skb, int last) +{ + int i; + u32 entry = tnapi->tx_prod; + struct ring_info *txb = &tnapi->tx_buffers[entry]; + + pci_unmap_single(tnapi->tp->pdev, + dma_unmap_addr(txb, mapping), + skb_headlen(skb), + PCI_DMA_TODEVICE); + for (i = 0; i <= last; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + entry = NEXT_TX(entry); + txb = &tnapi->tx_buffers[entry]; + + pci_unmap_page(tnapi->tp->pdev, + dma_unmap_addr(txb, mapping), + frag->size, PCI_DMA_TODEVICE); + } +} + /* Workaround 4GB and 40-bit hardware DMA bugs. */ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, - struct sk_buff *skb, u32 last_plus_one, - u32 *start, u32 base_flags, u32 mss) + struct sk_buff *skb, + u32 base_flags, u32 mss) { struct tg3 *tp = tnapi->tp; struct sk_buff *new_skb; dma_addr_t new_addr = 0; - u32 entry = *start; - int i, ret = 0; + u32 entry = tnapi->tx_prod; + int ret = 0; if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) new_skb = skb_copy(skb, GFP_ATOMIC); @@ -5783,14 +5806,12 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, ret = -1; } else { /* New SKB is guaranteed to be linear. */ - entry = *start; new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len, PCI_DMA_TODEVICE); /* Make sure the mapping succeeded */ if (pci_dma_mapping_error(tp->pdev, new_addr)) { ret = -1; dev_kfree_skb(new_skb); - new_skb = NULL; /* Make sure new skb does not cross any 4G boundaries. * Drop the packet if it does. @@ -5801,39 +5822,16 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, PCI_DMA_TODEVICE); ret = -1; dev_kfree_skb(new_skb); - new_skb = NULL; } else { + tnapi->tx_buffers[entry].skb = new_skb; + dma_unmap_addr_set(&tnapi->tx_buffers[entry], + mapping, new_addr); + tg3_set_txd(tnapi, entry, new_addr, new_skb->len, base_flags, 1 | (mss << 1)); - *start = NEXT_TX(entry); } } - /* Now clean up the sw ring entries. */ - i = 0; - while (entry != last_plus_one) { - int len; - - if (i == 0) - len = skb_headlen(skb); - else - len = skb_shinfo(skb)->frags[i-1].size; - - pci_unmap_single(tp->pdev, - dma_unmap_addr(&tnapi->tx_buffers[entry], - mapping), - len, PCI_DMA_TODEVICE); - if (i == 0) { - tnapi->tx_buffers[entry].skb = new_skb; - dma_unmap_addr_set(&tnapi->tx_buffers[entry], mapping, - new_addr); - } else { - tnapi->tx_buffers[entry].skb = NULL; - } - entry = NEXT_TX(entry); - i++; - } - dev_kfree_skb(skb); return ret; @@ -5889,11 +5887,11 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); u32 len, entry, base_flags, mss; - int would_hit_hwbug; + int i = -1, would_hit_hwbug; dma_addr_t mapping; struct tg3_napi *tnapi; struct netdev_queue *txq; - unsigned int i, last; + unsigned int last; txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); tnapi = &tp->napi[skb_get_queue_mapping(skb)]; @@ -6074,20 +6072,15 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) } if (would_hit_hwbug) { - u32 last_plus_one = entry; - u32 start; - - start = entry - 1 - skb_shinfo(skb)->nr_frags; - start &= (TG3_TX_RING_SIZE - 1); + tg3_skb_error_unmap(tnapi, skb, i); /* If the workaround fails due to memory/mapping * failure, silently drop this packet. */ - if (tigon3_dma_hwbug_workaround(tnapi, skb, last_plus_one, - &start, base_flags, mss)) + if (tigon3_dma_hwbug_workaround(tnapi, skb, base_flags, mss)) goto out_unlock; - entry = start; + entry = NEXT_TX(tnapi->tx_prod); } /* Packets are ready, update Tx producer idx local and on card. */ @@ -6113,24 +6106,9 @@ out_unlock: return NETDEV_TX_OK; dma_error: - last = i; - entry = tnapi->tx_prod; - tnapi->tx_buffers[entry].skb = NULL; - pci_unmap_single(tp->pdev, - dma_unmap_addr(&tnapi->tx_buffers[entry], mapping), - skb_headlen(skb), - PCI_DMA_TODEVICE); - for (i = 0; i <= last; i++) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - entry = NEXT_TX(entry); - - pci_unmap_page(tp->pdev, - dma_unmap_addr(&tnapi->tx_buffers[entry], - mapping), - frag->size, PCI_DMA_TODEVICE); - } - + tg3_skb_error_unmap(tnapi, skb, i); dev_kfree_skb(skb); + tnapi->tx_buffers[tnapi->tx_prod].skb = NULL; return NETDEV_TX_OK; } -- cgit v1.2.3-58-ga151 From 1ff30a59f6d0c754e99442501a5145bdbbcfa6ea Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 12:12:46 +0000 Subject: tg3: Fix 57765 B0 data corruption The PCIe max FTS limit is too aggressive on these chips. This patch loosens the limit a little to eliminate data corruption issues. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 16 ++++++++++++++++ drivers/net/tg3.h | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b2b1ba168c88..09f2c11db247 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7990,6 +7990,22 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(GRC_MODE, grc_mode); } + if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_57765_AX) { + u32 grc_mode = tr32(GRC_MODE); + + /* Access the lower 1K of DL PCIE block registers. */ + val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK; + tw32(GRC_MODE, val | GRC_MODE_PCIE_DL_SEL); + + val = tr32(TG3_PCIE_TLDLPL_PORT + + TG3_PCIE_DL_LO_FTSMAX); + val &= ~TG3_PCIE_DL_LO_FTSMAX_MSK; + tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_DL_LO_FTSMAX, + val | TG3_PCIE_DL_LO_FTSMAX_VAL); + + tw32(GRC_MODE, grc_mode); + } + val = tr32(TG3_CPMU_LSPD_10MB_CLK); val &= ~CPMU_LSPD_10MB_MACCLK_MASK; val |= CPMU_LSPD_10MB_MACCLK_6_25; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index ce010cd33895..330959b9cfbc 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -180,6 +180,7 @@ #define CHIPREV_5750_BX 0x41 #define CHIPREV_5784_AX 0x57840 #define CHIPREV_5761_AX 0x57610 +#define CHIPREV_57765_AX 0x577650 #define GET_METAL_REV(CHIP_REV_ID) ((CHIP_REV_ID) & 0xff) #define METAL_REV_A0 0x00 #define METAL_REV_A1 0x01 @@ -1951,6 +1952,9 @@ /* Alternate PCIE definitions */ #define TG3_PCIE_TLDLPL_PORT 0x00007c00 +#define TG3_PCIE_DL_LO_FTSMAX 0x0000000c +#define TG3_PCIE_DL_LO_FTSMAX_MSK 0x000000ff +#define TG3_PCIE_DL_LO_FTSMAX_VAL 0x0000002c #define TG3_PCIE_PL_LO_PHYCTL1 0x00000004 #define TG3_PCIE_PL_LO_PHYCTL1_L1PLLPD_EN 0x00001000 #define TG3_PCIE_PL_LO_PHYCTL5 0x00000014 -- cgit v1.2.3-58-ga151 From 108a6c1655f184c9abb7b5917838a8fb204361f5 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 12:12:47 +0000 Subject: tg3: Fix IPv6 TCP problems for 5719 Commit 4d163b75e979833979cc401ae433cb1d7743d57e, entitled "tg3: Fix 5719 A0 tx completion bug" turned off TSO to fix a hardware bug. In doing so, it accidentally turned off all IPv6 TCP checksum offloading too. This patch fixes the problem by reenabling the hardware bit that control both features. The TSO capability is still not exposed to the kernel. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 09f2c11db247..6c53e2c4aa7c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8303,7 +8303,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tg3_flag(tp, HW_TSO_3)) rdmac_mode |= RDMAC_MODE_IPV4_LSO_EN; - if (tg3_flag(tp, HW_TSO_3) || + if (tg3_flag(tp, 57765_PLUS) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) rdmac_mode |= RDMAC_MODE_IPV6_LSO_EN; -- cgit v1.2.3-58-ga151 From b0c5943f1ca4df6c1c451ef6be5287a161d29a9d Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 12:12:48 +0000 Subject: tg3: Fix EEE interoperability workaround Commit 21a00ab270f95d32e502d92f166dd75c518d3c5f, entitled "tg3: Fix EEE interoperability issue", added an EEE interoperability fix. We found that the fix doesn't work if applied too early though. This patch delays the fix until right before allowing LPI assertion. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 41 +++++++++++++++++++++-------------------- drivers/net/tg3.h | 2 +- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 6c53e2c4aa7c..695dab274d1e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1822,22 +1822,9 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) tg3_phy_cl45_read(tp, MDIO_MMD_AN, TG3_CL45_D7_EEERES_STAT, &val); - switch (val) { - case TG3_CL45_D7_EEERES_STAT_LP_1000T: - switch (GET_ASIC_REV(tp->pci_chip_rev_id)) { - case ASIC_REV_5717: - case ASIC_REV_5719: - case ASIC_REV_57765: - if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { - tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, - 0x0000); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); - } - } - /* Fallthrough */ - case TG3_CL45_D7_EEERES_STAT_LP_100TX: + if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T || + val == TG3_CL45_D7_EEERES_STAT_LP_100TX) tp->setlpicnt = 2; - } } if (!tp->setlpicnt) { @@ -1846,6 +1833,23 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) } } +static void tg3_phy_eee_enable(struct tg3 *tp) +{ + u32 val; + + if (tp->link_config.active_speed == SPEED_1000 && + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) && + !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0003); + TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + } + + val = tr32(TG3_CPMU_EEE_MODE); + tw32(TG3_CPMU_EEE_MODE, val | TG3_CPMU_EEEMD_LPI_ENABLE); +} + static int tg3_wait_macro_done(struct tg3 *tp) { int limit = 100; @@ -8844,11 +8848,8 @@ static void tg3_timer(unsigned long __opaque) if (tg3_flag(tp, 5705_PLUS)) tg3_periodic_fetch_stats(tp); - if (tp->setlpicnt && !--tp->setlpicnt) { - u32 val = tr32(TG3_CPMU_EEE_MODE); - tw32(TG3_CPMU_EEE_MODE, - val | TG3_CPMU_EEEMD_LPI_ENABLE); - } + if (tp->setlpicnt && !--tp->setlpicnt) + tg3_phy_eee_enable(tp); if (tg3_flag(tp, USE_LINKCHG_REG)) { u32 mac_stat; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 330959b9cfbc..83f45bf0a08e 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2186,7 +2186,7 @@ #define MII_TG3_DSP_TAP26_OPCSINPT 0x0004 #define MII_TG3_DSP_AADJ1CH0 0x001f #define MII_TG3_DSP_CH34TP2 0x4022 -#define MII_TG3_DSP_CH34TP2_HIBW01 0x0010 +#define MII_TG3_DSP_CH34TP2_HIBW01 0x017b #define MII_TG3_DSP_AADJ1CH3 0x601f #define MII_TG3_DSP_AADJ1CH3_ADCCKADJ 0x0002 #define MII_TG3_DSP_EXP1_INT_STAT 0x0f01 -- cgit v1.2.3-58-ga151 From 42b64a450b81ec9e8cdd5b3fb13613ab9bb25048 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 12:12:49 +0000 Subject: tg3: Consolidate autoneg advertisement setup code Autonegotiation setup has gotten a little more complicated since the tg3 driver was created. This patch consolidates autoneg setup into one routine and modifies the call sites accordingly. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 217 +++++++++++++++++++++++++----------------------------- 1 file changed, 99 insertions(+), 118 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 695dab274d1e..7675231d9a9d 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -2929,102 +2929,54 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 } } -static void tg3_phy_copper_begin(struct tg3 *tp) +static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) { - u32 new_adv; - int i; - - if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { - /* Entering low power mode. Disable gigabit and - * 100baseT advertisements. - */ - tg3_writephy(tp, MII_TG3_CTRL, 0); + int err = 0; + u32 val, new_adv; - new_adv = (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); - if (tg3_flag(tp, WOL_SPEED_100MB)) - new_adv |= (ADVERTISE_100HALF | ADVERTISE_100FULL); + new_adv = ADVERTISE_CSMA; + if (advertise & ADVERTISED_10baseT_Half) + new_adv |= ADVERTISE_10HALF; + if (advertise & ADVERTISED_10baseT_Full) + new_adv |= ADVERTISE_10FULL; + if (advertise & ADVERTISED_100baseT_Half) + new_adv |= ADVERTISE_100HALF; + if (advertise & ADVERTISED_100baseT_Full) + new_adv |= ADVERTISE_100FULL; - tg3_writephy(tp, MII_ADVERTISE, new_adv); - } else if (tp->link_config.speed == SPEED_INVALID) { - if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) - tp->link_config.advertising &= - ~(ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full); + new_adv |= tg3_advert_flowctrl_1000T(flowctrl); - new_adv = ADVERTISE_CSMA; - if (tp->link_config.advertising & ADVERTISED_10baseT_Half) - new_adv |= ADVERTISE_10HALF; - if (tp->link_config.advertising & ADVERTISED_10baseT_Full) - new_adv |= ADVERTISE_10FULL; - if (tp->link_config.advertising & ADVERTISED_100baseT_Half) - new_adv |= ADVERTISE_100HALF; - if (tp->link_config.advertising & ADVERTISED_100baseT_Full) - new_adv |= ADVERTISE_100FULL; - - new_adv |= tg3_advert_flowctrl_1000T(tp->link_config.flowctrl); - - tg3_writephy(tp, MII_ADVERTISE, new_adv); - - if (tp->link_config.advertising & - (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) { - new_adv = 0; - if (tp->link_config.advertising & ADVERTISED_1000baseT_Half) - new_adv |= MII_TG3_CTRL_ADV_1000_HALF; - if (tp->link_config.advertising & ADVERTISED_1000baseT_Full) - new_adv |= MII_TG3_CTRL_ADV_1000_FULL; - if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY) && - (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)) - new_adv |= (MII_TG3_CTRL_AS_MASTER | - MII_TG3_CTRL_ENABLE_AS_MASTER); - tg3_writephy(tp, MII_TG3_CTRL, new_adv); - } else { - tg3_writephy(tp, MII_TG3_CTRL, 0); - } - } else { - new_adv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl); - new_adv |= ADVERTISE_CSMA; + err = tg3_writephy(tp, MII_ADVERTISE, new_adv); + if (err) + goto done; - /* Asking for a specific link mode. */ - if (tp->link_config.speed == SPEED_1000) { - tg3_writephy(tp, MII_ADVERTISE, new_adv); + if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) + goto done; - if (tp->link_config.duplex == DUPLEX_FULL) - new_adv = MII_TG3_CTRL_ADV_1000_FULL; - else - new_adv = MII_TG3_CTRL_ADV_1000_HALF; - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) - new_adv |= (MII_TG3_CTRL_AS_MASTER | - MII_TG3_CTRL_ENABLE_AS_MASTER); - } else { - if (tp->link_config.speed == SPEED_100) { - if (tp->link_config.duplex == DUPLEX_FULL) - new_adv |= ADVERTISE_100FULL; - else - new_adv |= ADVERTISE_100HALF; - } else { - if (tp->link_config.duplex == DUPLEX_FULL) - new_adv |= ADVERTISE_10FULL; - else - new_adv |= ADVERTISE_10HALF; - } - tg3_writephy(tp, MII_ADVERTISE, new_adv); + new_adv = 0; + if (advertise & ADVERTISED_1000baseT_Half) + new_adv |= MII_TG3_CTRL_ADV_1000_HALF; + if (advertise & ADVERTISED_1000baseT_Full) + new_adv |= MII_TG3_CTRL_ADV_1000_FULL; - new_adv = 0; - } + if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) + new_adv |= (MII_TG3_CTRL_AS_MASTER | + MII_TG3_CTRL_ENABLE_AS_MASTER); - tg3_writephy(tp, MII_TG3_CTRL, new_adv); - } + err = tg3_writephy(tp, MII_TG3_CTRL, new_adv); + if (err) + goto done; - if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) { - u32 val; + if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) + goto done; - tw32(TG3_CPMU_EEE_MODE, - tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); + tw32(TG3_CPMU_EEE_MODE, + tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); - TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + if (!err) { + u32 err2; switch (GET_ASIC_REV(tp->pci_chip_rev_id)) { case ASIC_REV_5717: @@ -3041,19 +2993,66 @@ static void tg3_phy_copper_begin(struct tg3 *tp) } val = 0; - if (tp->link_config.autoneg == AUTONEG_ENABLE) { - /* Advertise 100-BaseTX EEE ability */ - if (tp->link_config.advertising & - ADVERTISED_100baseT_Full) - val |= MDIO_AN_EEE_ADV_100TX; - /* Advertise 1000-BaseT EEE ability */ - if (tp->link_config.advertising & - ADVERTISED_1000baseT_Full) - val |= MDIO_AN_EEE_ADV_1000T; + /* Advertise 100-BaseTX EEE ability */ + if (advertise & ADVERTISED_100baseT_Full) + val |= MDIO_AN_EEE_ADV_100TX; + /* Advertise 1000-BaseT EEE ability */ + if (advertise & ADVERTISED_1000baseT_Full) + val |= MDIO_AN_EEE_ADV_1000T; + err = tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val); + + err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + if (!err) + err = err2; + } + +done: + return err; +} + +static void tg3_phy_copper_begin(struct tg3 *tp) +{ + u32 new_adv; + int i; + + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { + new_adv = ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full; + if (tg3_flag(tp, WOL_SPEED_100MB)) + new_adv |= ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full; + + tg3_phy_autoneg_cfg(tp, new_adv, + FLOW_CTRL_TX | FLOW_CTRL_RX); + } else if (tp->link_config.speed == SPEED_INVALID) { + if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) + tp->link_config.advertising &= + ~(ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full); + + tg3_phy_autoneg_cfg(tp, tp->link_config.advertising, + tp->link_config.flowctrl); + } else { + /* Asking for a specific link mode. */ + if (tp->link_config.speed == SPEED_1000) { + if (tp->link_config.duplex == DUPLEX_FULL) + new_adv = ADVERTISED_1000baseT_Full; + else + new_adv = ADVERTISED_1000baseT_Half; + } else if (tp->link_config.speed == SPEED_100) { + if (tp->link_config.duplex == DUPLEX_FULL) + new_adv = ADVERTISED_100baseT_Full; + else + new_adv = ADVERTISED_100baseT_Half; + } else { + if (tp->link_config.duplex == DUPLEX_FULL) + new_adv = ADVERTISED_10baseT_Full; + else + new_adv = ADVERTISED_10baseT_Half; } - tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_autoneg_cfg(tp, new_adv, + tp->link_config.flowctrl); } if (tp->link_config.autoneg == AUTONEG_DISABLE && @@ -12953,7 +12952,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && !tg3_flag(tp, ENABLE_APE) && !tg3_flag(tp, ENABLE_ASF)) { - u32 bmsr, adv_reg, tg3_ctrl, mask; + u32 bmsr, mask; tg3_readphy(tp, MII_BMSR, &bmsr); if (!tg3_readphy(tp, MII_BMSR, &bmsr) && @@ -12964,36 +12963,18 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) if (err) return err; - adv_reg = (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL | - ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); - tg3_ctrl = 0; - if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) { - tg3_ctrl = (MII_TG3_CTRL_ADV_1000_HALF | - MII_TG3_CTRL_ADV_1000_FULL); - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) - tg3_ctrl |= (MII_TG3_CTRL_AS_MASTER | - MII_TG3_CTRL_ENABLE_AS_MASTER); - } + tg3_phy_set_wirespeed(tp); mask = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full); if (!tg3_copper_is_advertising_all(tp, mask)) { - tg3_writephy(tp, MII_ADVERTISE, adv_reg); - - if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) - tg3_writephy(tp, MII_TG3_CTRL, tg3_ctrl); + tg3_phy_autoneg_cfg(tp, tp->link_config.advertising, + tp->link_config.flowctrl); tg3_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); } - tg3_phy_set_wirespeed(tp); - - tg3_writephy(tp, MII_ADVERTISE, adv_reg); - if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) - tg3_writephy(tp, MII_TG3_CTRL, tg3_ctrl); } skip_phy_reset: -- cgit v1.2.3-58-ga151 From 54e0a67f446fae290f99781691eba46c5cda66e7 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 12:12:50 +0000 Subject: tg3: Fix TSO loopback test Commit bb158d696489244f79fd4c3abd47968a06b48c79, entitled "tg3: Add TSO loopback test", mistakenly inverted the checksum field test from the receive BD. This patch corrects the problem. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7675231d9a9d..d05c6a06da44 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -11195,7 +11195,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) } } else if ((desc->type_flags & RXD_FLAG_TCPUDP_CSUM) && (desc->ip_tcp_csum & RXD_TCPCSUM_MASK) - >> RXD_TCPCSUM_SHIFT == 0xffff) { + >> RXD_TCPCSUM_SHIFT != 0xffff) { goto out; } -- cgit v1.2.3-58-ga151 From 4452d0999906e3e26b718566362e943fcaa3d694 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 12:12:51 +0000 Subject: tg3: Fix stats for 5704 and later devices Commit 4d95847381228639844c7197deb8b2211274ef22, entitled "tg3: Workaround rx_discards stat bug" modified the hardware statistics data structure. The modification shifted the statistics so that the labels no longer corresponded to the counter values. This patch fixes the problem by utilizing reserved space for the new counters. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 7 +++++-- drivers/net/tg3.h | 10 ++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index d05c6a06da44..574fe9785f3c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -364,7 +364,6 @@ static const struct { { "dma_write_prioq_full" }, { "rxbds_empty" }, { "rx_discards" }, - { "mbuf_lwm_thresh_hit" }, { "rx_errors" }, { "rx_threshold_hit" }, @@ -376,7 +375,9 @@ static const struct { { "ring_status_update" }, { "nic_irqs" }, { "nic_avoided_irqs" }, - { "nic_tx_threshold_hit" } + { "nic_tx_threshold_hit" }, + + { "mbuf_lwm_thresh_hit" }, }; #define TG3_NUM_STATS ARRAY_SIZE(ethtool_stats_keys) @@ -9546,6 +9547,8 @@ static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp) ESTAT_ADD(nic_avoided_irqs); ESTAT_ADD(nic_tx_threshold_hit); + ESTAT_ADD(mbuf_lwm_thresh_hit); + return estats; } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 83f45bf0a08e..5b3d2f34da7a 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2620,7 +2620,6 @@ struct tg3_hw_stats { tg3_stat64_t dma_write_prioq_full; tg3_stat64_t rxbds_empty; tg3_stat64_t rx_discards; - tg3_stat64_t mbuf_lwm_thresh_hit; tg3_stat64_t rx_errors; tg3_stat64_t rx_threshold_hit; @@ -2639,7 +2638,12 @@ struct tg3_hw_stats { tg3_stat64_t nic_avoided_irqs; tg3_stat64_t nic_tx_threshold_hit; - u8 __reserved4[0xb00-0x9c0]; + /* NOT a part of the hardware statistics block format. + * These stats are here as storage for tg3_periodic_fetch_stats(). + */ + tg3_stat64_t mbuf_lwm_thresh_hit; + + u8 __reserved4[0xb00-0x9c8]; }; /* 'mapping' is superfluous as the chip does not write into @@ -2771,6 +2775,8 @@ struct tg3_ethtool_stats { u64 nic_irqs; u64 nic_avoided_irqs; u64 nic_tx_threshold_hit; + + u64 mbuf_lwm_thresh_hit; }; struct tg3_rx_prodring_set { -- cgit v1.2.3-58-ga151 From dabc5c670d3f86d15ee4f42ab38ec5bd2682487d Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 12:12:52 +0000 Subject: tg3: Move TSO_CAPABLE assignment This patch moves the code that asserts the TSO_CAPABLE flag closer to where the TSO capabilities flags are set. There isn't a good enough reason for the code to be separated. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 574fe9785f3c..09fe06784432 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -13639,6 +13639,21 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->fw_needed = FIRMWARE_TG3TSO; } + /* Selectively allow TSO based on operating conditions */ + if ((tg3_flag(tp, HW_TSO_1) || + tg3_flag(tp, HW_TSO_2) || + tg3_flag(tp, HW_TSO_3)) || + (tp->fw_needed && !tg3_flag(tp, ENABLE_ASF))) + tg3_flag_set(tp, TSO_CAPABLE); + else { + tg3_flag_clear(tp, TSO_CAPABLE); + tg3_flag_clear(tp, TSO_BUG); + tp->fw_needed = NULL; + } + + if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) + tp->fw_needed = FIRMWARE_TG3; + tp->irq_max = 1; if (tg3_flag(tp, 5750_PLUS)) { @@ -13705,6 +13720,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tg3_flag_clear(tp, HW_TSO_2); + tg3_flag_clear(tp, TSO_CAPABLE); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || tp->pci_chip_rev_id == CHIPREV_ID_57780_A0 || @@ -15044,21 +15060,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_bufmgr_config(tp); - /* Selectively allow TSO based on operating conditions */ - if ((tg3_flag(tp, HW_TSO_1) || - tg3_flag(tp, HW_TSO_2) || - tg3_flag(tp, HW_TSO_3)) || - (tp->fw_needed && !tg3_flag(tp, ENABLE_ASF))) - tg3_flag_set(tp, TSO_CAPABLE); - else { - tg3_flag_clear(tp, TSO_CAPABLE); - tg3_flag_clear(tp, TSO_BUG); - tp->fw_needed = NULL; - } - - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) - tp->fw_needed = FIRMWARE_TG3; - /* TSO is on by default on chips that support hardware TSO. * Firmware TSO on older chips gives lower performance, so it * is off by default, but can be enabled using ethtool. -- cgit v1.2.3-58-ga151 From 0da0606f493c5cdab74bdcc96b12f4305ad94085 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 12:12:53 +0000 Subject: tg3: Consolidate all netdev feature assignments This patch consolidates all the netdev feature bit assignments to one location. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 51 ++++++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 09fe06784432..5bf2ce125421 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -13602,19 +13602,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tg3_flag(tp, 5750_PLUS)) tg3_flag_set(tp, 5705_PLUS); - /* 5700 B0 chips do not support checksumming correctly due - * to hardware bugs. - */ - if (tp->pci_chip_rev_id != CHIPREV_ID_5700_B0) { - u32 features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM; - - if (tg3_flag(tp, 5755_PLUS)) - features |= NETIF_F_IPV6_CSUM; - tp->dev->features |= features; - tp->dev->hw_features |= features; - tp->dev->vlan_features |= features; - } - /* Determine TSO capabilities */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) ; /* Do nothing. HW bug. */ @@ -14922,7 +14909,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, u32 sndmbx, rcvmbx, intmbx; char str[40]; u64 dma_mask, persist_dma_mask; - u32 hw_features = 0; + u32 features = 0; printk_once(KERN_INFO "%s\n", version); @@ -14958,8 +14945,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, SET_NETDEV_DEV(dev, &pdev->dev); - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - tp = netdev_priv(dev); tp->pdev = pdev; tp->dev = dev; @@ -15039,7 +15024,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, if (dma_mask > DMA_BIT_MASK(32)) { err = pci_set_dma_mask(pdev, dma_mask); if (!err) { - dev->features |= NETIF_F_HIGHDMA; + features |= NETIF_F_HIGHDMA; err = pci_set_consistent_dma_mask(pdev, persist_dma_mask); if (err < 0) { @@ -15060,6 +15045,18 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_bufmgr_config(tp); + features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + + /* 5700 B0 chips do not support checksumming correctly due + * to hardware bugs. + */ + if (tp->pci_chip_rev_id != CHIPREV_ID_5700_B0) { + features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM; + + if (tg3_flag(tp, 5755_PLUS)) + features |= NETIF_F_IPV6_CSUM; + } + /* TSO is on by default on chips that support hardware TSO. * Firmware TSO on older chips gives lower performance, so it * is off by default, but can be enabled using ethtool. @@ -15067,24 +15064,20 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, if ((tg3_flag(tp, HW_TSO_1) || tg3_flag(tp, HW_TSO_2) || tg3_flag(tp, HW_TSO_3)) && - (dev->features & NETIF_F_IP_CSUM)) - hw_features |= NETIF_F_TSO; + (features & NETIF_F_IP_CSUM)) + features |= NETIF_F_TSO; if (tg3_flag(tp, HW_TSO_2) || tg3_flag(tp, HW_TSO_3)) { - if (dev->features & NETIF_F_IPV6_CSUM) - hw_features |= NETIF_F_TSO6; + if (features & NETIF_F_IPV6_CSUM) + features |= NETIF_F_TSO6; if (tg3_flag(tp, HW_TSO_3) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) - hw_features |= NETIF_F_TSO_ECN; + features |= NETIF_F_TSO_ECN; } - dev->hw_features |= hw_features; - dev->features |= hw_features; - dev->vlan_features |= hw_features; - /* * Add loopback capability only for a subset of devices that support * MAC-LOOPBACK. Eventually this need to be enhanced to allow INT-PHY @@ -15093,7 +15086,11 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780 && !tg3_flag(tp, CPMU_PRESENT)) /* Add the loopback capability */ - dev->hw_features |= NETIF_F_LOOPBACK; + features |= NETIF_F_LOOPBACK; + + dev->features |= features; + dev->hw_features |= features; + dev->vlan_features |= features; if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 && !tg3_flag(tp, TSO_CAPABLE) && -- cgit v1.2.3-58-ga151 From 6ff6f81dd4ec08945e10147dbfe611569ef4cc09 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 12:12:54 +0000 Subject: tg3: Remove excessive parenthesis This patch removes some excessive parenthesizing. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 5bf2ce125421..eb8dc7b1a28a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -553,7 +553,7 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) { unsigned long flags; - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) && + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 && (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) return; @@ -578,7 +578,7 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) { unsigned long flags; - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) && + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 && (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) { *val = 0; return; @@ -2806,7 +2806,7 @@ static int tg3_power_down_prepare(struct tg3 *tp) CLOCK_CTRL_PWRDOWN_PLL133, 40); } else if (tg3_flag(tp, 5780_CLASS) || tg3_flag(tp, CPMU_PRESENT) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)) { + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { /* do nothing */ } else if (!(tg3_flag(tp, 5750_PLUS) && tg3_flag(tp, ENABLE_ASF))) { u32 newbits1, newbits2; @@ -8646,7 +8646,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) } if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) && - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) { + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { u32 tmp; tmp = tr32(SERDES_RX_CTRL); @@ -11636,7 +11636,7 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp) tw32(NVRAM_CFG1, nvcfg1); } - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) || + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || tg3_flag(tp, 5780_CLASS)) { switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) { case FLASH_VENDOR_ATMEL_FLASH_BUFFERED: @@ -12640,9 +12640,9 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tg3_read_mem(tp, NIC_SRAM_DATA_VER, &ver); ver >>= NIC_SRAM_DATA_VER_SHIFT; - if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) && - (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) && - (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5703) && + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5703 && (ver > 0) && (ver < 0x100)) tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &cfg2); @@ -13498,7 +13498,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } } - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { static struct tg3_dev_id { u32 vendor; u32 device; @@ -13598,7 +13598,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tg3_flag(tp, 5780_CLASS)) tg3_flag_set(tp, 5750_PLUS); - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) || + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || tg3_flag(tp, 5750_PLUS)) tg3_flag_set(tp, 5705_PLUS); @@ -13627,9 +13627,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } /* Selectively allow TSO based on operating conditions */ - if ((tg3_flag(tp, HW_TSO_1) || - tg3_flag(tp, HW_TSO_2) || - tg3_flag(tp, HW_TSO_3)) || + if (tg3_flag(tp, HW_TSO_1) || + tg3_flag(tp, HW_TSO_2) || + tg3_flag(tp, HW_TSO_3) || (tp->fw_needed && !tg3_flag(tp, ENABLE_ASF))) tg3_flag_set(tp, TSO_CAPABLE); else { @@ -13891,7 +13891,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * It is also used as eeprom write protect on LOMs. */ tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM; - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) || + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || tg3_flag(tp, EEPROM_WRITE_PROT)) tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1); @@ -13943,8 +13943,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->phy_flags |= TG3_PHYFLG_IS_FET; /* A few boards don't want Ethernet@WireSpeed phy feature */ - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) || - ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) && + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) && (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)) || (tp->phy_flags & TG3_PHYFLG_IS_FET) || @@ -14064,7 +14064,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tg3_flag_set(tp, IS_5788); if (!tg3_flag(tp, IS_5788) && - (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)) + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) tg3_flag_set(tp, TAGGED_STATUS); if (tg3_flag(tp, TAGGED_STATUS)) { tp->coalesce_mode |= (HOSTCC_MODE_CLRTICK_RXBD | @@ -14215,7 +14215,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) #endif mac_offset = 0x7c; - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || tg3_flag(tp, 5780_CLASS)) { if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID) mac_offset = 0xcc; -- cgit v1.2.3-58-ga151 From 310050fad8962a2ebc70011353a549614e118152 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 12:12:55 +0000 Subject: tg3: Apply rx_discards fix to 5719/5720 Commit 4d95847381228639844c7197deb8b2211274ef22, entitled "tg3: Workaround rx_discards stat bug", was intended to be applied to the 5717, 5718, 5719_A0, and 5720 A0 chip revisions. The implementation missed the latter two when applying the fix in a critical area. This patch fixes the problem. Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index eb8dc7b1a28a..8311f8e98bb3 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8797,7 +8797,9 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp) TG3_STAT_ADD32(&sp->rx_undersize_packets, MAC_RX_STATS_UNDERSIZE); TG3_STAT_ADD32(&sp->rxbds_empty, RCVLPC_NO_RCV_BD_CNT); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && + tp->pci_chip_rev_id != CHIPREV_ID_5719_A0 && + tp->pci_chip_rev_id != CHIPREV_ID_5720_A0) { TG3_STAT_ADD32(&sp->rx_discards, RCVLPC_IN_DISCARDS_CNT); } else { u32 val = tr32(HOSTCC_FLOW_ATTN); -- cgit v1.2.3-58-ga151 From 43a5f002afc6f24891e57d31275f34e19a1a07d0 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 12:12:56 +0000 Subject: tg3: Update version to 3.119 This patch updates the tg3 version to 3.119. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 8311f8e98bb3..012ce70aeaf5 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -88,10 +88,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 -#define TG3_MIN_NUM 118 +#define TG3_MIN_NUM 119 #define DRV_MODULE_VERSION \ __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM) -#define DRV_MODULE_RELDATE "April 22, 2011" +#define DRV_MODULE_RELDATE "May 18, 2011" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.3-58-ga151 From 8fb53b959bd9e503b646a3d68c7b1759667b6a19 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 18:20:29 -0400 Subject: isdn: capi: Use pr_debug() instead of ifdefs. I was investigating some warnings that spew because of the _DEBUG_FOO ifdef'ery in here. Instead of adding more ifdefs to fix that warning, let's use pr_debug() and get rid of these CPP checks altogether. Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 115 +++++++++++++---------------------------------- 1 file changed, 32 insertions(+), 83 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index bea100983336..e44933d58790 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -42,9 +42,6 @@ MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); -#undef _DEBUG_TTYFUNCS /* call to tty_driver */ -#undef _DEBUG_DATAFLOW /* data flow */ - /* -------- driver information -------------------------------------- */ static DEFINE_MUTEX(capi_mutex); @@ -418,9 +415,7 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) tty = tty_port_tty_get(&mp->port); if (!tty) { -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi: currently no receiver\n"); -#endif + pr_debug("capi: currently no receiver\n"); return -1; } @@ -433,23 +428,17 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) } if (ld->ops->receive_buf == NULL) { -#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) - printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n"); -#endif + pr_debug("capi: ldisc has no receive_buf function\n"); /* fatal error, do not requeue */ goto free_skb; } if (mp->ttyinstop) { -#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) - printk(KERN_DEBUG "capi: recv tty throttled\n"); -#endif + pr_debug("capi: recv tty throttled\n"); goto deref_ldisc; } if (tty->receive_room < datalen) { -#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) - printk(KERN_DEBUG "capi: no room in tty\n"); -#endif + pr_debug("capi: no room in tty\n"); goto deref_ldisc; } @@ -465,10 +454,8 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) if (errcode == CAPI_NOERROR) { skb_pull(skb, CAPIMSG_LEN(skb->data)); -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", - datahandle, skb->len); -#endif + pr_debug("capi: DATA_B3_RESP %u len=%d => ldisc\n", + datahandle, skb->len); ld->ops->receive_buf(tty, skb->data, NULL, skb->len); } else { printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", @@ -515,9 +502,7 @@ static void handle_minor_send(struct capiminor *mp) return; if (mp->ttyoutstop) { -#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) - printk(KERN_DEBUG "capi: send: tty stopped\n"); -#endif + pr_debug("capi: send: tty stopped\n"); tty_kref_put(tty); return; } @@ -559,10 +544,8 @@ static void handle_minor_send(struct capiminor *mp) } errcode = capi20_put_message(mp->ap, skb); if (errcode == CAPI_NOERROR) { -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n", - datahandle, len); -#endif + pr_debug("capi: DATA_B3_REQ %u len=%u\n", + datahandle, len); continue; } capiminor_del_ack(mp, datahandle); @@ -636,10 +619,8 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) } if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2); -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n", - datahandle, skb->len-CAPIMSG_LEN(skb->data)); -#endif + pr_debug("capi_signal: DATA_B3_IND %u len=%d\n", + datahandle, skb->len-CAPIMSG_LEN(skb->data)); skb_queue_tail(&mp->inqueue, skb); handle_minor_recv(mp); @@ -647,11 +628,9 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) } else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) { datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4); -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi_signal: DATA_B3_CONF %u 0x%x\n", - datahandle, - CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2)); -#endif + pr_debug("capi_signal: DATA_B3_CONF %u 0x%x\n", + datahandle, + CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2)); kfree_skb(skb); capiminor_del_ack(mp, datahandle); tty = tty_port_tty_get(&mp->port); @@ -1081,9 +1060,7 @@ static int capinc_tty_write(struct tty_struct *tty, struct capiminor *mp = tty->driver_data; struct sk_buff *skb; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count); -#endif + pr_debug("capinc_tty_write(count=%d)\n", count); spin_lock_bh(&mp->outlock); skb = mp->outskb; @@ -1119,9 +1096,7 @@ static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) struct sk_buff *skb; int ret = 1; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_put_char(%u)\n", ch); -#endif + pr_debug("capinc_put_char(%u)\n", ch); spin_lock_bh(&mp->outlock); skb = mp->outskb; @@ -1160,9 +1135,7 @@ static void capinc_tty_flush_chars(struct tty_struct *tty) struct capiminor *mp = tty->driver_data; struct sk_buff *skb; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_flush_chars\n"); -#endif + pr_debug("capinc_tty_flush_chars\n"); spin_lock_bh(&mp->outlock); skb = mp->outskb; @@ -1186,9 +1159,7 @@ static int capinc_tty_write_room(struct tty_struct *tty) room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue); room *= CAPI_MAX_BLKSIZE; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write_room = %d\n", room); -#endif + pr_debug("capinc_tty_write_room = %d\n", room); return room; } @@ -1196,12 +1167,10 @@ static int capinc_tty_chars_in_buffer(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n", - mp->outbytes, mp->nack, - skb_queue_len(&mp->outqueue), - skb_queue_len(&mp->inqueue)); -#endif + pr_debug("capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n", + mp->outbytes, mp->nack, + skb_queue_len(&mp->outqueue), + skb_queue_len(&mp->inqueue)); return mp->outbytes; } @@ -1213,17 +1182,13 @@ static int capinc_tty_ioctl(struct tty_struct *tty, static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_set_termios\n"); -#endif + pr_debug("capinc_tty_set_termios\n"); } static void capinc_tty_throttle(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_throttle\n"); -#endif + pr_debug("capinc_tty_throttle\n"); mp->ttyinstop = 1; } @@ -1231,9 +1196,7 @@ static void capinc_tty_unthrottle(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_unthrottle\n"); -#endif + pr_debug("capinc_tty_unthrottle\n"); mp->ttyinstop = 0; handle_minor_recv(mp); } @@ -1242,9 +1205,7 @@ static void capinc_tty_stop(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_stop\n"); -#endif + pr_debug("capinc_tty_stop\n"); mp->ttyoutstop = 1; } @@ -1252,9 +1213,7 @@ static void capinc_tty_start(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_start\n"); -#endif + pr_debug("capinc_tty_start\n"); mp->ttyoutstop = 0; handle_minor_send(mp); } @@ -1263,39 +1222,29 @@ static void capinc_tty_hangup(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_hangup\n"); -#endif + pr_debug("capinc_tty_hangup\n"); tty_port_hangup(&mp->port); } static int capinc_tty_break_ctl(struct tty_struct *tty, int state) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state); -#endif + pr_debug("capinc_tty_break_ctl(%d)\n", state); return 0; } static void capinc_tty_flush_buffer(struct tty_struct *tty) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_flush_buffer\n"); -#endif + pr_debug("capinc_tty_flush_buffer\n"); } static void capinc_tty_set_ldisc(struct tty_struct *tty) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_set_ldisc\n"); -#endif + pr_debug("capinc_tty_set_ldisc\n"); } static void capinc_tty_send_xchar(struct tty_struct *tty, char ch) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_send_xchar(%d)\n", ch); -#endif + pr_debug("capinc_tty_send_xchar(%d)\n", ch); } static const struct tty_operations capinc_ops = { -- cgit v1.2.3-58-ga151 From f06cd54f555a4ceca4de39160c68c7e3da657e89 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 18:32:55 -0400 Subject: pkt_sched: Kill set but unused variable 'protocol' in tc_classify() I checked the history and this has been like this since the beginning of time. Signed-off-by: David S. Miller --- net/sched/sch_api.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 7490f3f2db8b..6b8627661c98 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1673,10 +1673,8 @@ int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, { int err = 0; #ifdef CONFIG_NET_CLS_ACT - __be16 protocol; struct tcf_proto *otp = tp; reclassify: - protocol = skb->protocol; #endif err = tc_classify_compat(skb, tp, res); -- cgit v1.2.3-58-ga151 From 504f284a713c46c6ecf975fbd20af00f4e205f5b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 18:34:37 -0400 Subject: rxrpc: Kill set but unused variable 'sp' in rxrpc_rotate_tx_window() Signed-off-by: David S. Miller --- net/rxrpc/ar-ack.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c index b6ffe4e1b84a..f99cfce7ca97 100644 --- a/net/rxrpc/ar-ack.c +++ b/net/rxrpc/ar-ack.c @@ -375,7 +375,6 @@ protocol_error: */ static void rxrpc_rotate_tx_window(struct rxrpc_call *call, u32 hard) { - struct rxrpc_skb_priv *sp; unsigned long _skb; int tail = call->acks_tail, old_tail; int win = CIRC_CNT(call->acks_head, tail, call->acks_winsz); @@ -387,7 +386,6 @@ static void rxrpc_rotate_tx_window(struct rxrpc_call *call, u32 hard) while (call->acks_hard < hard) { smp_read_barrier_depends(); _skb = call->acks_window[tail] & ~1; - sp = rxrpc_skb((struct sk_buff *) _skb); rxrpc_free_skb((struct sk_buff *) _skb); old_tail = tail; tail = (tail + 1) & (call->acks_winsz - 1); -- cgit v1.2.3-58-ga151 From 9e5e10a22507b8d372bcf0e88875d4a3f6ede297 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 18:35:58 -0400 Subject: rxrpc: Kill set but unused variable 'sp' in rxrpc_process_connection() Signed-off-by: David S. Miller --- net/rxrpc/ar-connevent.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/rxrpc/ar-connevent.c b/net/rxrpc/ar-connevent.c index 0505cdc4d6d4..e7ed43a54c41 100644 --- a/net/rxrpc/ar-connevent.c +++ b/net/rxrpc/ar-connevent.c @@ -259,7 +259,6 @@ void rxrpc_process_connection(struct work_struct *work) { struct rxrpc_connection *conn = container_of(work, struct rxrpc_connection, processor); - struct rxrpc_skb_priv *sp; struct sk_buff *skb; u32 abort_code = RX_PROTOCOL_ERROR; int ret; @@ -276,8 +275,6 @@ void rxrpc_process_connection(struct work_struct *work) /* go through the conn-level event packets, releasing the ref on this * connection that each one has when we've finished with it */ while ((skb = skb_dequeue(&conn->rx_queue))) { - sp = rxrpc_skb(skb); - ret = rxrpc_process_event(conn, skb, &abort_code); switch (ret) { case -EPROTO: -- cgit v1.2.3-58-ga151 From c9d10c497c3728a5c798c11486dccdc01b2092a8 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 18:37:11 -0400 Subject: rxrpc: Kill set but unused variable 'local' in rxrpc_UDP_error_handler() Signed-off-by: David S. Miller --- net/rxrpc/ar-error.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/net/rxrpc/ar-error.c b/net/rxrpc/ar-error.c index d4d1ae26d293..5d6b572a6704 100644 --- a/net/rxrpc/ar-error.c +++ b/net/rxrpc/ar-error.c @@ -139,7 +139,7 @@ void rxrpc_UDP_error_handler(struct work_struct *work) struct rxrpc_transport *trans = container_of(work, struct rxrpc_transport, error_handler); struct sk_buff *skb; - int local, err; + int err; _enter(""); @@ -157,7 +157,6 @@ void rxrpc_UDP_error_handler(struct work_struct *work) switch (ee->ee_origin) { case SO_EE_ORIGIN_ICMP: - local = 0; switch (ee->ee_type) { case ICMP_DEST_UNREACH: switch (ee->ee_code) { @@ -207,7 +206,6 @@ void rxrpc_UDP_error_handler(struct work_struct *work) case SO_EE_ORIGIN_LOCAL: _proto("Rx Received local error { error=%d }", ee->ee_errno); - local = 1; break; case SO_EE_ORIGIN_NONE: @@ -215,7 +213,6 @@ void rxrpc_UDP_error_handler(struct work_struct *work) default: _proto("Rx Received error report { orig=%u }", ee->ee_origin); - local = 0; break; } -- cgit v1.2.3-58-ga151 From 2a64255019e13dd975f1487cec32b873bcb76da6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 18:41:03 -0400 Subject: rxrpc: Fix set but unused variable 'usage' in rxrpc_get_peer(). I backed off from trying to just eliminate this variable, since transforming atomic_inc_return() into atomic_inc() takes away the memory barriers. Signed-off-by: David S. Miller --- net/rxrpc/ar-peer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/rxrpc/ar-peer.c b/net/rxrpc/ar-peer.c index b6ff06351d67..2754f098d436 100644 --- a/net/rxrpc/ar-peer.c +++ b/net/rxrpc/ar-peer.c @@ -157,6 +157,7 @@ struct rxrpc_peer *rxrpc_get_peer(struct sockaddr_rxrpc *srx, gfp_t gfp) /* we can now add the new candidate to the list */ peer = candidate; candidate = NULL; + usage = atomic_read(&peer->usage); list_add_tail(&peer->link, &rxrpc_peers); write_unlock_bh(&rxrpc_peer_lock); @@ -171,7 +172,7 @@ success: &peer->srx.transport.sin.sin_addr, ntohs(peer->srx.transport.sin.sin_port)); - _leave(" = %p {u=%d}", peer, atomic_read(&peer->usage)); + _leave(" = %p {u=%d}", peer, usage); return peer; /* we found the peer in the list immediately */ -- cgit v1.2.3-58-ga151 From d187c1aab8d30771bb781c745b150f6159467d6f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 18:44:41 -0400 Subject: atl1c: atl1c_resume() is only used when CONFIG_PM_SLEEP is defined. Signed-off-by: David S. Miller --- drivers/net/atl1c/atl1c_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 48868de386a0..1269ba5d6e56 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -2537,6 +2537,7 @@ static int atl1c_suspend(struct device *dev) return 0; } +#ifdef CONFIG_PM_SLEEP static int atl1c_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); @@ -2563,6 +2564,7 @@ static int atl1c_resume(struct device *dev) return 0; } +#endif static void atl1c_shutdown(struct pci_dev *pdev) { -- cgit v1.2.3-58-ga151 From fa7479cf48103ee9261398034528495966bd7d2d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 18:46:41 -0400 Subject: irda: Kill set but unused vars 'saddr' and 'daddr' in irlan_provider_connect_indication() Signed-off-by: David S. Miller --- net/irda/irlan/irlan_provider.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c index 5cf5e6c872bb..b8af74ab8b68 100644 --- a/net/irda/irlan/irlan_provider.c +++ b/net/irda/irlan/irlan_provider.c @@ -128,7 +128,6 @@ static void irlan_provider_connect_indication(void *instance, void *sap, { struct irlan_cb *self; struct tsap_cb *tsap; - __u32 saddr, daddr; IRDA_DEBUG(0, "%s()\n", __func__ ); @@ -141,8 +140,6 @@ static void irlan_provider_connect_indication(void *instance, void *sap, IRDA_ASSERT(tsap == self->provider.tsap_ctrl,return;); IRDA_ASSERT(self->provider.state == IRLAN_IDLE, return;); - daddr = irttp_get_daddr(tsap); - saddr = irttp_get_saddr(tsap); self->provider.max_sdu_size = max_sdu_size; self->provider.max_header_size = max_header_size; -- cgit v1.2.3-58-ga151 From 63722966d703aeb8071d52172de87e377006cd28 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 18:49:54 -0400 Subject: be2net: Kill set but unused variable 'req' in lancer_fw_download() Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index ce6edac007a7..4b5e0ed49ed8 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2736,7 +2736,6 @@ static int lancer_fw_download(struct be_adapter *adapter, #define LANCER_FW_DOWNLOAD_CHUNK (32 * 1024) #define LANCER_FW_DOWNLOAD_LOCATION "/prg" struct be_dma_mem flash_cmd; - struct lancer_cmd_req_write_object *req; const u8 *data_ptr = NULL; u8 *dest_image_ptr = NULL; size_t image_size = 0; @@ -2765,7 +2764,6 @@ static int lancer_fw_download(struct be_adapter *adapter, goto lancer_fw_exit; } - req = flash_cmd.va; dest_image_ptr = flash_cmd.va + sizeof(struct lancer_cmd_req_write_object); image_size = fw->size; -- cgit v1.2.3-58-ga151 From ed84cadb21e15a3e59a2154158c58579774f0851 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 18:51:50 -0400 Subject: rxrpc: Fix set but unused variable 'usage' in rxrpc_get_transport() This is identical to the case I fixed in rxrpc_get_peer() Signed-off-by: David S. Miller --- net/rxrpc/ar-transport.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/rxrpc/ar-transport.c b/net/rxrpc/ar-transport.c index 5e0226fe587e..92df566930b9 100644 --- a/net/rxrpc/ar-transport.c +++ b/net/rxrpc/ar-transport.c @@ -111,6 +111,7 @@ struct rxrpc_transport *rxrpc_get_transport(struct rxrpc_local *local, /* we can now add the new candidate to the list */ trans = candidate; candidate = NULL; + usage = atomic_read(&trans->usage); rxrpc_get_local(trans->local); atomic_inc(&trans->peer->usage); @@ -125,7 +126,7 @@ success: trans->local->debug_id, trans->peer->debug_id); - _leave(" = %p {u=%d}", trans, atomic_read(&trans->usage)); + _leave(" = %p {u=%d}", trans, usage); return trans; /* we found the transport in the list immediately */ -- cgit v1.2.3-58-ga151 From bfad6ef6d29e776472b3ead1f5bc920c5410ed2c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 18:52:59 -0400 Subject: irda: Kill set but unused variable 'clen' in ircomm_connect_indication() Signed-off-by: David S. Miller --- net/irda/ircomm/ircomm_core.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c index e97082017f4f..52079f19bbbe 100644 --- a/net/irda/ircomm/ircomm_core.c +++ b/net/irda/ircomm/ircomm_core.c @@ -244,14 +244,8 @@ EXPORT_SYMBOL(ircomm_connect_request); void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb, struct ircomm_info *info) { - int clen = 0; - IRDA_DEBUG(2, "%s()\n", __func__ ); - /* Check if the packet contains data on the control channel */ - if (skb->len > 0) - clen = skb->data[0]; - /* * If there are any data hiding in the control channel, we must * deliver it first. The side effect is that the control channel -- cgit v1.2.3-58-ga151 From ad6376434c945495ea8c4082ad8a392cc58c3406 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 18:53:58 -0400 Subject: irda: Kill set but unused variable 'bytes' in irlan_check_command_param() Signed-off-by: David S. Miller --- net/irda/irlan/irlan_filter.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/irda/irlan/irlan_filter.c b/net/irda/irlan/irlan_filter.c index 9ff7823abec7..7977be7caf0f 100644 --- a/net/irda/irlan/irlan_filter.c +++ b/net/irda/irlan/irlan_filter.c @@ -143,12 +143,8 @@ void irlan_filter_request(struct irlan_cb *self, struct sk_buff *skb) */ void irlan_check_command_param(struct irlan_cb *self, char *param, char *value) { - __u8 *bytes; - IRDA_DEBUG(4, "%s()\n", __func__ ); - bytes = value; - IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); -- cgit v1.2.3-58-ga151 From 8ce6eb1a4a4bc46820f23e927377d386d3ec5404 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2011 18:58:39 -0400 Subject: irda: Fix error propagation in ircomm_lmp_connect_response() The variable 'ret' is set but unused, and this pointed out that errors from irlmp_connect_response() are not propagated to the caller. Note that this is currently academic since irlmp_connect_response() always returns 0. :-) Signed-off-by: David S. Miller --- net/irda/ircomm/ircomm_lmp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/net/irda/ircomm/ircomm_lmp.c b/net/irda/ircomm/ircomm_lmp.c index 08fb54dc8c41..3b8095c771d4 100644 --- a/net/irda/ircomm/ircomm_lmp.c +++ b/net/irda/ircomm/ircomm_lmp.c @@ -75,7 +75,6 @@ static int ircomm_lmp_connect_response(struct ircomm_cb *self, struct sk_buff *userdata) { struct sk_buff *tx_skb; - int ret; IRDA_DEBUG(0, "%s()\n", __func__ ); @@ -100,9 +99,7 @@ static int ircomm_lmp_connect_response(struct ircomm_cb *self, tx_skb = userdata; } - ret = irlmp_connect_response(self->lsap, tx_skb); - - return 0; + return irlmp_connect_response(self->lsap, tx_skb); } static int ircomm_lmp_disconnect_request(struct ircomm_cb *self, -- cgit v1.2.3-58-ga151 From 034cfe48d0efc248ba4b725e3a94b95e76fbc5d3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 19 May 2011 19:23:28 -0400 Subject: networking: NET_CLS_ROUTE4 depends on INET IP_ROUTE_CLASSID depends on INET and NET_CLS_ROUTE4 selects IP_ROUTE_CLASSID, but when INET is not enabled, this kconfig warning is produced, so fix it by making NET_CLS_ROUTE4 depend on INET. warning: (NET_CLS_ROUTE4) selects IP_ROUTE_CLASSID which has unmet direct dependencies (NET && INET) Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller --- net/sched/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sched/Kconfig b/net/sched/Kconfig index aeaa2110b699..2590e91b3289 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -288,6 +288,7 @@ config NET_CLS_TCINDEX config NET_CLS_ROUTE4 tristate "Routing decision (ROUTE)" + depends on INET select IP_ROUTE_CLASSID select NET_CLS ---help--- -- cgit v1.2.3-58-ga151 From 449f4544267e73d5db372971da63634707c32299 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 19 May 2011 12:24:16 +0000 Subject: macvlan: remove one synchronize_rcu() call When one macvlan device is dismantled, we can avoid one synchronize_rcu() call done after deletion from hash list, since caller will perform a synchronize_net() call after its ndo_stop() call. Add a new netdev->dismantle field to signal this dismantle intent. Reduces RTNL hold time. Signed-off-by: Eric Dumazet CC: Patrick McHardy CC: Ben Greear Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 9 +++++---- include/linux/netdevice.h | 4 +++- net/core/dev.c | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index d7c0bc62da7f..07bcb8084d78 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -70,16 +70,17 @@ static void macvlan_hash_add(struct macvlan_dev *vlan) hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[addr[5]]); } -static void macvlan_hash_del(struct macvlan_dev *vlan) +static void macvlan_hash_del(struct macvlan_dev *vlan, bool sync) { hlist_del_rcu(&vlan->hlist); - synchronize_rcu(); + if (sync) + synchronize_rcu(); } static void macvlan_hash_change_addr(struct macvlan_dev *vlan, const unsigned char *addr) { - macvlan_hash_del(vlan); + macvlan_hash_del(vlan, true); /* Now that we are unhashed it is safe to change the device * address without confusing packet delivery. */ @@ -345,7 +346,7 @@ static int macvlan_stop(struct net_device *dev) dev_uc_del(lowerdev, dev->dev_addr); hash_del: - macvlan_hash_del(vlan); + macvlan_hash_del(vlan, !dev->dismantle); return 0; } diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a134d809125b..ca333e79e10f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1293,7 +1293,9 @@ struct net_device { NETREG_UNREGISTERED, /* completed unregister todo */ NETREG_RELEASED, /* called free_netdev */ NETREG_DUMMY, /* dummy device for NAPI poll */ - } reg_state:16; + } reg_state:8; + + bool dismantle; /* device is going do be freed */ enum { RTNL_LINK_INITIALIZED, diff --git a/net/core/dev.c b/net/core/dev.c index 155de2094e71..d94537914a71 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5126,7 +5126,7 @@ static void rollback_registered_many(struct list_head *head) list_del(&dev->unreg_list); continue; } - + dev->dismantle = true; BUG_ON(dev->reg_state != NETREG_REGISTERED); } -- cgit v1.2.3-58-ga151 From d542fe27c86ecf932f40c898881208ccdaef9dc5 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 16:02:43 +0000 Subject: tg3: Fix NETIF_F_LOOPBACK error Mahesh Bandewar noticed that the features cleanup in commit 0da0606f493c5cdab74bdcc96b12f4305ad94085, entitled "tg3: Consolidate all netdev feature assignments", mistakenly sets NETIF_F_LOOPBACK by default. This patch corrects the error. Signed-off-by: Matt Carlson Signed-off-by: Mahesh Bandewar Signed-off-by: David S. Miller --- drivers/net/tg3.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 012ce70aeaf5..284e99853ed3 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -15080,6 +15080,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, features |= NETIF_F_TSO_ECN; } + dev->features |= features; + dev->vlan_features |= features; + /* * Add loopback capability only for a subset of devices that support * MAC-LOOPBACK. Eventually this need to be enhanced to allow INT-PHY @@ -15090,9 +15093,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, /* Add the loopback capability */ features |= NETIF_F_LOOPBACK; - dev->features |= features; dev->hw_features |= features; - dev->vlan_features |= features; if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 && !tg3_flag(tp, TSO_CAPABLE) && -- cgit v1.2.3-58-ga151 From 7196cd6c3d4863000ef88b09f34d6dd75610ec3e Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 19 May 2011 16:02:44 +0000 Subject: tg3: Add braces around 5906 workaround. Commit dabc5c670d3f86d15ee4f42ab38ec5bd2682487d, entitled "tg3: Move TSO_CAPABLE assignment", moved some TSO flagging code around. In the process it failed to add braces around an exceptional 5906 condition. This patch fixes the problem. Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 284e99853ed3..db19332a7d87 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -13707,9 +13707,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pcie_cap + PCI_EXP_LNKCTL, &lnkctl); if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == + ASIC_REV_5906) { tg3_flag_clear(tp, HW_TSO_2); tg3_flag_clear(tp, TSO_CAPABLE); + } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || tp->pci_chip_rev_id == CHIPREV_ID_57780_A0 || -- cgit v1.2.3-58-ga151 From d93515611bbc70c2fe4db232e5feb448ed8e4cc9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 20 May 2011 14:59:23 -0400 Subject: macvlan: fix panic if lowerdev in a bond commit a35e2c1b6d905 (macvlan: use rx_handler_data pointer to store macvlan_port pointer V2) added a bug in macvlan_port_create() Steps to reproduce the bug: # ifenslave bond0 eth0 eth1 # ip link add link eth0 up name eth0#1 type macvlan ->error EBUSY # ip link add link eth0 up name eth0#1 type macvlan ->panic Fix: Dont set IFF_MACVLAN_PORT in error case. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 07bcb8084d78..bbcf80afaf16 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -585,8 +585,8 @@ static int macvlan_port_create(struct net_device *dev) err = netdev_rx_handler_register(dev, macvlan_handle_frame, port); if (err) kfree(port); - - dev->priv_flags |= IFF_MACVLAN_PORT; + else + dev->priv_flags |= IFF_MACVLAN_PORT; return err; } -- cgit v1.2.3-58-ga151